diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..89822e64b --- /dev/null +++ b/.gitignore @@ -0,0 +1,107 @@ +# +# cache files +# +*~ +*.swp +*.gc?? + +# +# gnu global files +# +GPATH +GRTAGS +GSYMS +GTAGS +ID +cscope.in.out +cscope.out +cscope.po.out +tags +.prjBuild.sh +.prjDebug.sh +prjBuild.sh +prjDebug.sh +debug.gdb + +# +# GNU Autotools +# +aclocal.m4 +autom4te.cache +config.h +config.h.in +config.h-new +config.log +config.status +config.guess +config.sub +config.rpath +configure +libtool +stamp-h +stamp-h.in +stamp-h1 +ltmain.sh +missing +mkinstalldirs +compile +install-sh +depcomp +autoregen.sh +ABOUT-NLS +/INSTALL +_stdint.h +.dirstamp +/m4 +.deps +.libs +*.lo +*.la +*.o +Makefile.in +Makefile +/m4 +tmp-orc.c +*orc.h + +# +# VS +# +Build +*.user +*.suo +*.ipch +*.sdf +*.opensdf +*.DS_Store + +/test-driver +*.log +*.trs + +/subprojects + +# +# Building cache +# +/build +/mpp/version.h + +# +# Debian +# +/obj-arm-linux-gnueabihf/ +/obj-aarch64-linux-gnu/ + +# +# VSCode +# +.vscode/ +.code-workspace + +# +# Clangd +# +.clangd +.clang-format +compile_commands.json diff --git a/Android.bp b/Android.bp new file mode 100644 index 000000000..f13e8dce4 --- /dev/null +++ b/Android.bp @@ -0,0 +1,330 @@ +cc_defaults { + name: "mpp_defaults", + + cflags: [ + "-DENABLE_FASTPLAY_ONCE", + "-DHAVE_AV1D", + "-DHAVE_AVS2D", + "-DHAVE_AVSD", + "-DHAVE_H263D", + "-DHAVE_H264D", + "-DHAVE_H264E", + "-DHAVE_H265D", + "-DHAVE_H265E", + "-DHAVE_JPEGD", + "-DHAVE_JPEGE", + "-DHAVE_MPEG2D", + "-DHAVE_MPEG4D", + "-DHAVE_VP8D", + "-DHAVE_VP8E", + "-DHAVE_VP9D", + "-DHAVE_VPROC", + "-Wno-implicit-fallthrough", + "-Wno-pointer-arith", + "-Wno-typedef-redefinition", + "-Wno-unused-variable", + "-Wno-unused-parameter", + "-Wno-unused-function", + "-Wno-unused-label", + "-Wno-address-of-packed-member", + "-Wno-sometimes-uninitialized", + "-Wno-missing-field-initializers", + ], + + local_include_dirs: [ + "mpp/base/inc", + "mpp/common", + "mpp/codec/inc", + "mpp/codec/dec/common", + "mpp/codec/enc/h264", + "mpp/codec/enc/h265", + "mpp/vproc/inc", + "mpp/hal/inc", + "mpp/hal/common", + "mpp/hal/common/av1", + "mpp/hal/common/h265", + "mpp/hal/common/h264", + "mpp/hal/common/jpeg", + "mpp/hal/rkenc/common", + "mpp/hal/rkenc/h265e", + "mpp/hal/rkenc/h264e", + "mpp/hal/rkenc/jpege", + "mpp/hal/rkdec/inc", + "mpp/hal/rkdec/av1d", + "mpp/hal/vpu/common", + "mpp/hal/vpu/jpege", + "mpp/hal/vpu/av1d", + "mpp/hal/vpu/h264e", + "mpp/inc", + "osal", + "osal/inc", + "osal/allocator", + "osal/driver/inc", + "kmpp/inc", + "kmpp/base/inc", + "inc", + "utils", + ], + + generated_headers: ["mpp_version_header"], +} + +filegroup { + name: "mpp_base_srcs", + srcs: [ + "mpp/base/*.c", + ], +} + +filegroup { + name: "mpp_codec_srcs", + srcs: [ + "mpp/codec/*.c", + "mpp/codec/dec/**/*.c", + "mpp/codec/enc/**/*.c", + "mpp/codec/rc/*.c", + ], +} + +filegroup { + name: "mpp_hal_srcs", + srcs: [ + "mpp/hal/*.c", + "mpp/hal/common/**/*.c", + "mpp/hal/vpu/**/*.c", + "mpp/hal/rkdec/**/*.c", + "mpp/hal/rkenc/common/*.c", + "mpp/hal/rkenc/h264e/hal_h264e_vepu541.c", + "mpp/hal/rkenc/h264e/hal_h264e_vepu580.c", + "mpp/hal/rkenc/h264e/hal_h264e_vepu540c.c", + "mpp/hal/rkenc/h264e/hal_h264e_vepu510.c", + "mpp/hal/rkenc/h264e/hal_h264e_vepu511.c", + "mpp/hal/rkenc/h265e/hal_h265e_vepu541.c", + "mpp/hal/rkenc/h265e/hal_h265e_vepu580.c", + "mpp/hal/rkenc/h265e/hal_h265e_vepu540c.c", + "mpp/hal/rkenc/h265e/hal_h265e_vepu510.c", + "mpp/hal/rkenc/h265e/hal_h265e_vepu511.c", + "mpp/hal/rkenc/jpege/hal_jpege_vepu540c.c", + "mpp/hal/rkenc/jpege/hal_jpege_vepu511.c", + "mpp/hal/rkenc/jpege/hal_jpege_vpu720.c", + "mpp/hal/dummy/*.c", + ], +} + +filegroup { + name: "mpp_vproc_srcs", + srcs: [ + "mpp/vproc/*.c", + "mpp/vproc/iep/*.c", + "mpp/vproc/iep2/*.c", + "mpp/vproc/rga/*.c", + "mpp/vproc/vdpp/*.c", + ], +} + +filegroup { + name: "mpp_kmpp_srcs", + srcs: [ + "kmpp/base/*.c", + "kmpp/*.c" + ], +} + +filegroup { + name: "mpp_osal_srcs", + srcs: [ + "osal/*.c", + "osal/allocator/*.c", + "osal/android/*.c", + "osal/driver/*.c", + ], +} + +genrule { + name: "mpp_version_header", + srcs: ["build/cmake/version.in"], + out: ["version.h"], + cmd: "VERSION_INFO=`cd hardware/rockchip/libmpp; git log -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s\"`;" + + "HISTORY_0=`cd hardware/rockchip/libmpp; git log HEAD~0 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_1=`cd hardware/rockchip/libmpp; git log HEAD~1 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_2=`cd hardware/rockchip/libmpp; git log HEAD~2 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_3=`cd hardware/rockchip/libmpp; git log HEAD~3 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_4=`cd hardware/rockchip/libmpp; git log HEAD~4 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_5=`cd hardware/rockchip/libmpp; git log HEAD~5 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_6=`cd hardware/rockchip/libmpp; git log HEAD~6 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_7=`cd hardware/rockchip/libmpp; git log HEAD~7 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_8=`cd hardware/rockchip/libmpp; git log HEAD~8 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "HISTORY_9=`cd hardware/rockchip/libmpp; git log HEAD~9 -1 --oneline --date=short --pretty=format:\"%h author: %<|(30)%an %cd %s %d\"`;" + + "sed -e \"s|@VERSION_INFO@|\\\"$$VERSION_INFO\\\"|g\" " + + " -e \"s|@VERSION_CNT@|10|g\" " + + " -e \"s|@VERSION_HISTORY_0@|\\\"$$HISTORY_0\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_1@|\\\"$$HISTORY_1\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_2@|\\\"$$HISTORY_2\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_3@|\\\"$$HISTORY_3\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_4@|\\\"$$HISTORY_4\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_5@|\\\"$$HISTORY_5\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_6@|\\\"$$HISTORY_6\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_7@|\\\"$$HISTORY_7\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_8@|\\\"$$HISTORY_8\\\"|g\" " + + " -e \"s|@VERSION_HISTORY_9@|\\\"$$HISTORY_9\\\"|g\" " + + " $(in)>$(out)", +} + +cc_library_static { + name: "libmpputils-static", + srcs: [ + "utils/*.c", + ], + export_include_dirs: [ + "utils", + ], + defaults: [ + "mpp_defaults", + ], +} + +cc_library_headers { + name: "libmpp_headers", + export_include_dirs: [ + "inc", + "osal/inc", + ], + vendor_available: true, +} + +cc_library { + name: "libmpp", + srcs: [ + "mpp/*.c", + ":mpp_base_srcs", + ":mpp_codec_srcs", + ":mpp_vproc_srcs", + ":mpp_kmpp_srcs", + ":mpp_hal_srcs", + ":mpp_osal_srcs", + ], + + export_include_dirs: [ + "inc", + "osal/inc", + ], + + shared_libs: [ + "liblog", + ], + + defaults: [ + "mpp_defaults", + ], + + vendor_available: true, +} + +cc_library { + name: "libvpu", + srcs: [ + "mpp/legacy/vpu.c", + "mpp/legacy/vpu_api.cpp", + "mpp/legacy/vpu_api_legacy.cpp", + "mpp/legacy/vpu_api_mlvec.cpp", + "mpp/legacy/vpu_mem_legacy.c", + "mpp/legacy/rk_list.cpp", + "mpp/mpp_info.c", + ], + + export_include_dirs: [ + "inc" + ], + + shared_libs: [ + "libmpp", + ], + + defaults: [ + "mpp_defaults", + ], + + vendor_available: true, +} + +cc_test { + name: "mpp_info_test", + srcs: ["test/mpp_info_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_dec_test", + srcs: ["test/mpi_dec_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_dec_mt_test", + srcs: ["test/mpi_dec_mt_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_dec_nt_test", + srcs: ["test/mpi_dec_nt_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_enc_test", + srcs: ["test/mpi_enc_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_enc_mt_test", + srcs: ["test/mpi_enc_mt_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_rc2_test", + srcs: ["test/mpi_rc2_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_dec_multi_test", + srcs: ["test/mpi_dec_multi_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +/* +cc_test { + name: "mpi_dec_slt_test", + srcs: ["test/mpi_dec_slt_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} + +cc_test { + name: "mpi_enc_slt_test", + srcs: ["test/mpi_enc_slt_test.c"], + shared_libs: ["libmpp"], + static_libs: ["libmpputils-static"], + defaults: ["mpp_defaults"], +} +*/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..6309ef827 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,761 @@ +## 1.0.11 (2025-09-10) +### Feature +- [mpp_trie]: Add info name max length record +- [mpp_enc_cfg]: Separate init function +- [mpp]: Add jpeg roi function for RV1126B +- [kmpp]: Add jpeg roi function for kmpp +- [kmpp]: Set chan_fd to init cfg +- [kmpp]: Replace frame_infos with kmpp_frame +- [kmpp_frame]: Add self_meta in kmpp_frame +- [kmpp_buffer]: Add ioctl to inc ref and flush +- [mpp_meta]: Add more frame buffer key to meta +- [base]: Add toml function +- [base]: Use enc cfg obj +- [smart_v3]: Add new frame qp interface +- [kmpp]: Add KmppMeta module +- [kmpp]: Add KmppBuffer module +- [kmpp_obj]: Add priv prop support for objdef + +### Fix +- [h265e]: Remove unused buffer +- [mpp]: Add null check for sync pkt buffer +- [mpp_meta]: Add user data deep copy support +- [mpp_meta]: Add KEY_NPU_UOBJ_FLAG and KEY_NPU_SOBJ_FLAG +- [kmpp_obj]: Fix obj ioctl typo +- [mpp_trie]: Fix get err node issue +- [vdpp] Fix building tests against musl libc +- [script]: Prepend bash with /usr/bin/env +- [kmpp_buffer]: Close fd when deinit +- [mpp_thread]: Fix thread name is not set +- Rename FFmpeg to FF for sdk release request +- [kmpp_obj]: Fix kmpp obj get by sptr +- [h265d]: Ensure the DTS is transmitted to the frame +- [kmpp_obj]: Rename kmpp_obj_impl_put func +- [kmpp_obj]: Fix kmpp frm/pkt self meta erro +- [h264e_api_v2]: Fix bit_real calc in skip mode +- [h264d]: Fix fast play mode not working in shell environment. +- [kmpp_frame]: Remove unnecessary logs +- [enc_test]: Set input block mode in init kcfg +- [hal_h265e]: Fix nal type in tsvc mode +- [h265d]: Fix log issue +- [vepu511]: Add tune stat update +- [kmpp_obj]: Update tbl after objdef registration +- [mpp_cfg_io]: Add more mpp_cfg_io function +- [kmpp_obj]: Fix grp_cfg and buf_cfg leak in kmpp_obj_test +- [vproc]: Fix unit tests cannot be disabled + +### Docs +- Update 1.0.11 CHANGELOG.md + +### Refactor +- [sys_cfg]: Refactor C++ sys_cfg to C +- [test]: Refactor C++ test file to C +- [osal]: Refactor C++ osal file to C +- [rc]: Refactor C++ rc/rc_base to C +- [enc]: Use KmppShmPtr to represent osd buffer +- [kmpp]: Fix kmpp obj compilation warning +- [rc_api]: Refactor C++ rc_api to C + +### Test +- [mpi_enc_test]: Add jpeg roi test + +### Chore +- [dec_test]: Remove unused code +- [mpp_singleton]: Update name print +- [hal]: Organize the relevant processes for vepu fmt +- Rename Dolby for sdk release requirement +- [kmpp_meta]: Disable failure log +- [mpp_enc_cfg]: Add base:smart_en option +- [kmpp_obj]: Add is_kobj query function +- [rc_smt]: Adjust code style for rc_smt + +## 1.0.10 (2025-06-23) +### Feature +- [mpp_log]: Add long log (llog) function +- [mpp_buffer]: Add mpp_buffer discard function +- [build]: add Android.bp support +- [kmpp_packet]: Add kmpp_packet interface +- [mpp_log]: Add external callback support +- [kmpp_obj]: Refactor kmpp_obj helper +- [kmpp_obj]: Add more kmpp_obj property +- [kmpp_obj]: Add object update function +- [kmpp_obj]: Add userspace objdef functions +- [osal]: Add mpp_singleton module +- [mpp_cfg_io]: Add mpp cfg io module +- [kmpp]: Add kmpp_frame_test + +### Fix +- [h265d]: Fix yuv400 decode error +- [h265d]: Fix GDR stream decoding +- [kmpp_obj]: Undef KMPP_OBJ_SGLN_ID macro +- [osal]: Fix timeout expire too soon issue +- [cmake]: Fix static build issue +- [vp8e]: Remove unused vp8e_rc file +- [h265d_rkv]: Fix dec err after cut streams +- [mpp_singleton]: fix init order issue +- [mpp_dec]: Fix compile warning +- [h265d_parser]: Fix slice header parse +- [mpp_sys_cfg]: afbc calc support yuv444sp_10bit +- [kmpp_obj]: Update helper macro +- [h263d]: Fix missing initializer for field problem +- [enc_utils]: Remove duplicate option +- [kmpp_obj]: Remove extra print in helper +- [avsd_plus]: Fix page fault when filtering field data +- [h265d_vdpu384a]: Fix CABAC error detection issue. +- [mpp_sys_cfg]: Fix stride issue on resolution change +- [vepu_540c]: Reduce print hw_status when irq ret +- [mpp_sys_cfg]: Fix ver_stride calc issue +- [sys_cfg]: Fix ver stride calculation issue. +- [vepu541]: Add warning for unsupport nv21/nv42 +- [avs2d]: fix vertical stride config +- Revert "fix[mpp_enc_impl]: fix rc cfg for jpeg enc" +- [h265d_ps]: Suppress YUV444 unsupported warning logs +- [mpp_cfg]: Fix function define on C++ field +- [h264e_dpb]: fix walk_len when refs_dryrun +- [av1d_vdpu383]: fix segid page fault issue +- [allocator]: Fix misc buffer group flag issue +- [h265d_parser]: fix startcode finder for 00 00 00 xx case +- [kmpp]: Fix eos frame with NULL buffer issue +- [utils]: Remove duplicate assignments +- [mpi_enc_test]: Sync mdc config of RV1126B +- [sys_cfg]: Avoid frequent environment variable access. +- [mpp_enc]: Add avc rc parameter set +- [h265d_vdpu383]: Fix CABAC error detection issue. +- [mpi]: Fix typo +- [h264_vdpu384a]: Fix error proc issue +- [h265e]: Correct tile syntax elements at PPS +- [mpp]: Add atf set, atf value 0~3 +- [mpp_enc_cfg]: Add lambda_idx_i and lambda_idx_p +- [mpp_enc]: Add encoder speed mode setup +- [test]: Add qbias_arr and aq_rnge_arr init +- [packet]: fix packet partition and eoi logic +- [mpp]: add qpmap_en and enc_spd +- [cmake]: Fix double object include issue +- [sys_cfg]: Align to CTU64 to avoid info change. +- [mpp]: Fix compile warning with ipc sdk toolchain + +### Docs +- Update 1.0.10 CHANGELOG.md + +### Refactor +- [base]: Refactor C++ mpp_enc_cfg to C +- [base]: Refactor C++ mpp_meta to C +- [base]: Refactor C++ mpp_packet to C +- [base]: Refactor C++ mpp_frame to C +- [base]: Refactor C++ mpp_buffer to C +- [mpp_mem_pool]: Add exit leak pool print +- [osal]: Refactor C++ mpp_server to C +- [osal]: Refactor more module from C++ to C +- [mpp_trace]: Refactor C++ mpp_trace to C +- [mpp_runtime]: Refactor C++ mpp_runtime to C +- [mpp_soc]: Refactor C++ mpp_soc to C +- [mpp_platform]: Refactor C++ mpp_platform to C +- [mem_pool]: Refactor C++ mem_pool to C +- [mpp_mem]: Refactor C++ mpp_mem to C +- [kmpp]: Replace venc_packet with KmppPacket +- [osal/linux/os_log]: Use C constructor. +- [base]: Remove MppDecCfgImpl +- [base]: Refactor mpp_trie from C++ to C +- [mpp_cfg_io]: Change cfg to trie interface + +### Test +- [osal]: Add libc and OS compatibility checking +- [resolution]: Add resolution test tool + +### Chore +- [kmpp]: Modify kmpp_objs init / deinit order +- [kmpp_obj]: Add from objs device macro +- [kmpp_obj]: Add more obj function +- [kmpp_obj]: Update flag calculation macro +- [utils]: Add fbc frame data dump +- A fix for company release requirement +- [kmpp]: Remove get packet failed log + +## 1.0.9 (2025-04-03) +### Feature +- [kmpp_frame]: Add KmppFrame module +- [vepu_511]: Add rv1126b 265e/264e/jpge support +- [mpp_meta]: Add osd_data3 fmt for 1103b/1126b +- [kmpp_obj]: Sync to new KmppEntry share object +- [err_proc]: Add a new command: DIS_ERR_CLR_MARK +- [mpi_enc_test]: Support enc for kmpp flow +- [kmpp_obj]: Add more kmpp_obj functions +- [vdpu384a]: Support RV1126B new features +- [mpp_soc]: Support rv1126b soc +- [kmpp_obj]: Sync to new kmpp_meta +- [kmpp_obj]: Sync to loctbl without flag_type +- [mpp_buf_slot]: buf_slot add coded width alignment config +- [h265d]: Add vdpu383 hevc yuv444_10bit support +- [vproc]: Add more log for debugging +- [mpp]: Support kmpp access +- [kmpp]: Add kmpp module +- [rk_mpi_cmd]: Merge cmds from mpp_interface +- [build]: Add --toolchain to config toolchain for linux +- [mpp_meta]: Use trie to index the meta key +- [mpp_packet]: Add realease callback info +- [kmpp_obj]: Update to new objdef query mode +- [mpp_trie]: Allow empty name trie for import +- [enc]: Support setting temporal_id +- [mpp_enc_cfg]: Merge enc cfgs from mpp_interface +- [mpp_sys_cfg_st]: Provide packaging for use on products +- [mpp_sys_cfg]: Add raster/tile/fbc buffer alignment +- [mpp_sys_cfg]: Support sys_cfg buffer alignment +- [kmpp_obj]: Add kmpp_obj_get_hnd func +- [mpp_venc_kcfg]: Add mpp_venc_kcfg module + +### Fix +- [sys_cfg]: Add debug info +- [sys_cfg]: fix fbc ver stride calc issue +- [sys_cfg]: Fix external configuration stride issue +- [sys_cfg]: Support alignment for mpeg2/mpeg4/h263/vp8. +- [sys_cfg]: AVC is aligned to ctu to avoid info change +- [sys_cfg]: Fix RK3399 hor/ver stride calculation issue. +- [sys_cfg]: Fix HAL layer buffer alignment issue +- [h264d]: Recovery only takes effect when no IDR frames present +- [hal_jpege_api]: Fix jpege api path judgment +- [vdpp]: Fix vdpp blk_size calculation. +- [mpp_venc_kcfg]: Revert to mpp interface +- [cmake]: Fix kmpp_base symbol missing +- [av1_syntax]: Fix array out-of-bounds issue. +- [build]: fix build failure with CMake 4.0 +- [vepu_511]: Speed grade configuration of 0.67 +- [mpp_frame]: Add rk_fbc fmt for 1126b +- [jpegd_rkv]: New JPEG IP supports tile 4x4 output by default. +- [jpeg_rkv]: New JPEG IP defaults to no RGB support. +- [hal_rcb]: Fix rcb buf size calc issue +- [kmpp_obj]: Fix rockit compile error +- [avsd]: Skip redundant zeros between fields inside one picture +- [av1]: parameter is 16 bits +- [base]: Fix strncpy compile warning +- [hal_h265e_vepu580]: Fix overflow status check +- [kmpp]: Fix channel dup issue +- [os_log]: Modify default log option for linux +- [kmpp_obj]: Fix warning on arm32 +- [kmpp]: Set KEY_OUTPUT_INTRA meta to packet +- [sys_cfg]: Align rk3399 h_stride to an odd multiple of 265. +- [mpp_sys]: Fix old IP vertical alignment to 16 issue +- [kmpp_obj]: Disable /dev/kmpp_objs not found log +- [mpp_soc]: Fix cap_fbc for rv1126b +- [sys_cfg]: Optimize comparison information printing. +- [sys_cfg]: Print comparison information only once. +- [mpp_meta]: Fix compile error +- [vepu510]: Mark frame first part when split slice out +- [hdr_meta]: Fix hdr format for av1 +- [mpp_sys_cfg]: Fix align pixel stride on rk3576 +- [vproc]: fix height out of boundary problem +- [mpp_sys_cfg]: Fix abnormal stride calculation. +- [h264d]: disable ref erorr when decode recovery frame period +- [jpege_vpu720]: Correct encoded size config +- [buf_slot]: Correct coding mistakes. +- [build]: Avoid exporting toolchain to system PATH +- [mpp_enc]: Fix some exceptions when force pskip +- [kmpp]: Fill pts/dts/flag to MppPacket +- [vproc]: fix frame output disorder problem +- [vproc]: Fix field disordered problem +- [mpp_enc_cfg]: Remove a redundant atr_str +- []: Fix abnormal FBC info issue in Info Change +- [h264d]: Fix segment fault problem +- [vproc]: Fix error info missed problem +- [vproc]: Fix output blank buffer problem +- [fbc]: Fix RK3588 av1 FBC usage issue +- [sys_cfg/buf_slot]: support yuv422sp 10bit +- [mpp_enc_cfg]: Add sao_bit_ratio from mpp_interface +- [buf_slot]: Correct coding mistakes. +- [mpp_venc_kcfg]: Get objdef at runtime +- [jpegd]: Avoid buffer overrun +- [sys_cfg/buf_slot]: fix fbc yuv444sp buf calculation issue +- [kmpp_obj]: Add extern C + +### Docs +- Update 1.0.9 CHANGELOG.md + +### Refactor +- [kmpp]: Move kmpp to seperate directory +- [mpp_trie]: Replace root import +- [mpp_enc_cfg]: Adjust cu_qp_delta_depth + +### Chore +- [mpp_buf_slot]: Modify sys_cfg mismatch print + +## 1.0.8 (2024-12-30) +### Feature +- [enc]: Add switch for disable IDR encoding when FPS changed. +- [test]: Add PSNR info for video encoder +- [mpp_buf_slots]: Add coding attribute to buf slots +- [mpp_sys_cfg]: Add mpp_sys_cfg function +- [dec_nt_test]: Support jpeg decoding on decode +- [mpp_dec]: Add jpeg put/get decode support +- [mpp_obj]: Add mpp_obj for kernel object +- [mpp_trie]: Add functions for import / export +- [rk_type.h]: Add kernel driver compat define +- [mpp_dec]: add control for select codec device +- [mpp_dec]: support hdr10plus dynamic metadata parse +- [hal_avsd]: enable hw dec timeout +- [vpu_api]: Support configuration to disable decoding errors +- [enc]: Support use frame meta to cfg pskip +- [vepu510]: Add scaling list regs setup + +### Fix +- [enc]: Fix CPB size not enough problem +- [m4v_parser]: Fix split_parse setting failure issue +- [mpp_trie]: Remove a redundant variables from log +- [mpp_enc]: Set frm type in pkt meta +- [mpp_sys_cfg]: Fix compile warning +- [rc_smt]: Fix the variable overflow issue +- [h264e_sps]: fix constraint_set3_flag flag issue +- [vpu_legacy]: Fix vpu fbc configuration issue +- [mpp_buffer]: Fix buffer put log +- [mpp_mem_pool]: Record pool buffer allocator caller +- [mpp]: Fix input_task_count for async enc +- [av1d]: Fix uninitialized fbc_hdr_stride issue +- [cfg]: fix cfg test segment fault problem +- [drm]: Call drop master by default +- [vepu580]: fix is_yuv/is_fbc typo +- [misc]: Fix compile on 32bit platform +- [jpegd]: replace packet size with stream length +- [av1_vdpu383]: Fix the CDF issue between GOPs +- [mpp_enc_impl]: fix rc cfg for jpeg enc +- [av1_vdpu383]: fix cdf usage issue +- [hal_h265d]: Avoid reg offset duplicate setting issue +- [vepu580]: fix incorrect color range problem +- [buf_slots]: Fix the issue of fmt conv during info change +- [h264d]: force reset matrix coefficients when parse unknown value +- [h264d]: Parse hdr parameters on enable_hdr_meta enabled +- [h264d_parser]: Fix pps parsing issue +- [hal_vdpu383]: fix fbc hor_stride mismatch issue +- [hal_vepu580]: re-get roi buf when resolution switch +- [hal_vepu541]: re-get roi buf when resolution switch +- [iep2]: Remove unnessary log on init failed +- [h264_dpb]: Add env variables to force fast play mode +- [h265e_slice]: fix compilation warning +- [hal_avs2d_vdpu383]: handle scene reference frame +- [debain]: fix typo in compat version +- [debian]: Update debian control +- [debain]: Update debian/control +- [debain]: Update compat to 10 +- [h264e_pps]: add pic_scaling_matrix_present check +- [h2645d_sei]: fix read byte overflow error +- [m2vd]: Fix refer frame error on beginning +- [vdpu383]: fix err detection mask issue +- [test]: Fix AQ table error +- [vepu580]: Add md info internal buffer +- [vepu580]: Add ATF weight adjust switch for H.265 +- [tune]: Replace qpmap_en with deblur_en +- [vepu580]: Adjust frame-level QP for VI frame +- [hal_jpegd]: fix huffman table selection +- [h265]: fix pskip when enable tile mode +- [smt_rc]: Fix first frame QP error +- [h264d]: fix no output for mvc stream +- [vepu580]: Fix motion level assignment error +- [avsd]: Fix attach dev error issue +- [h265d]: Fix conformance window offsets for chroma formats +- [test]: Fix mdinfo size according to soc type +- [h265d_vdpu383]: fix dec err when ps_update_flag=0 +- [vepu510]: Sync code from enc_tune branch +- [mpp_cfg]: Fix compile warning +- [h265d]: fix output err causeby refs cleard +- [h264d]: remove error check for B frame has only one ref +- [test]: Fix test demo stuck issue + +### Docs +- Update 1.0.8 CHANGELOG.md +- update doc for fast play + +### Refactor +- [hal]: Update the reg offset setting method. +- [mpi]: Add ops name when assign for reading friendly +- [av1d_vdpu383]: Regs definition sync with other protocols. +- [vproc]: Refactor iep2 progress +- [h265]: unify calculation tile width + +### Chore +- [hal_jpegd]: Remove reset / flush functions +- [test]: Use put/get in mpi_dec_test for jpeg +- [MppPacket]: Add caller log on check failure + +## 1.0.7 (2024-09-04) +### Feature +- [rc_smt]: Add rc container for smart mode +- [vepu580]: Optimization to improve VMAF +- [vepu580]: Optimize hal processing for smart encoding +- [vepu580]: Add qpmap and rc container interface +- [vepu510]: Add anti-smear regs setup for H.264 +- [vepu510]: Add H.264 tuning setup +- [vepu510]: Sync code from enc_tune branch +- [vepu510]: Sync code from enc_tune branch +- [vepu510]: Sync code from enc_tune branch +- [mpp_trie]: Add trie context filling feature +- [mpp_trie]: Add trie tag and shrink feature +- [h264d]: support hdr meta parse +- [h265e]: Support force mark & use ltr +- [vpu_api]: support yuv444sp decode ouput pixel format + +### Fix +- [h265d]: fix infochange loss when two sps continuous +- [hal_h264e]: Fix CAVLC encode smartP stream err +- [mpi_enc_test]: Remove redundant code about smart encoding +- [h264e_sps]: fix the default value of max mv length +- [enc_roi]: Fix cu_map init in vepu_54x_roi +- [hal_vp9]: Optimize prob memory usage +- [hal_h265d]: Allow reference missing for GDR +- [osal]: Fix mpp_mem single instance issue +- [hal_vp9d_com]: Fixed memory leak issue +- [hal_h265d]: Avoid risk of segment fault +- [hal_h265d]: fix error slot index marking +- [h265d]: Adjust condition of scan type judgement +- [mpp_hdr]: Fix buffer overflow issue +- [mpp_buffer]: Synchronous log addition point +- [hal_vepu]: fix split regs assignment +- [vepu580]: poll max set to 1 on split out lowdelay mode +- [mpp_common]: fix compile err on F_DUPFD_CLOEXEC not defined +- [h265d]: return error on sps/pps read failure +- [build]: The first toolchains is selected by default +- [265e]:Fix the st refernce frame err in tsvc +- [av1d]: when MetaData found then it is new frame +- [m2vd]: Fix seq_head check error +- [h265e_vepu510]: Fix a memory leak +- [h265d]: auto output frame in dpb when ready +- [m2vd]: Remove ref frame when info changed +- [mpp_meta]: Missing data in the instance +- [mpp_bitread]: Fix negative shift error +- [osal]: fix 128 odd plus 64 bytes alignment +- [h265d_parser]: Fix fmt configuration issue +- [hal_av1d_vdpu383]: modify av1 segid wr/rd base config +- [h265d_parser]: Fix fmt configuration issue +- [hal_av1d_vdpu383]: add segid reg base config + +### Docs +- Update 1.0.7 CHANGELOG.md +- [readme]: Add more repo info + +### Refactor +- [mpp_cfg]: Refactor MppTrie and string cfg + +### Chore +- [mpp_mem]: Add mpp_realloc_size +- [mpp_cfg]: Remove some unused code +- fix compile warning + +## 1.0.6 (2024-06-12) +### Feature +- [vdpu383]: refine rcb info setup +- [enc_265]: Support get Largest Code Unit size +- [mpp_dec_cfg]: Add disable dpb check config +- [vdpu383]: support 8K downscale mode + +### Fix +- [drm]: Fix permission check issue on GKI kernel +- [hal_h265e]: Amend 510 tid and sync cache +- [hal_h265e]: Fix nalu type avoid stream warning +- [h265e]: Fix vps/sps max temparal layers val +- [hal_jpeg_vdpu1]: fix dec failed on RK3036 problem +- [osal]: rv1109/rv1126 vcodec_type mismatch problem +- [h264e_vepu2]: Adjust inter favor table +- [h264d]: fix drop packets after reset when err stream +- [h265d]: Allow filtering of consecutive start code +- [hal_h264d_vdpu383]: fix spspps update issue +- [mpp]: fix mpp frame leak when async enc +- [enc]: Add use_lt_idx to output packet meta +- [hal_h265e]: fix sse_sum get err +- [mpp_enc_async]: fix mpp packet leak when thread quit +- [enc_roi]: Support ROI cfg under CQP mode +- [hal]: Fix the lib interdependence issue +- [vepu_510]: fix same log type when enc feedback +- [mpp_buffer]: fix dec/inc ref_count in multi threads +- [mpp_enc_async]: fix debreath not work on async flow +- [base]: fix AV1 and AVS2 string info missing problem +- [mpp]: Add encoder input/output pts log +- [hal_vepu580/510]: fix split out err when pass1 frame +- [hal]: Fix target link issue +- [hal_enc]: Fix lib dependency issue +- [hal_h265d_vdpu383]: fix ref_err mark for special poc +- [rc2_test]: fix pkt buffer overflow error +- [enc_utils]: Support read odd resolution image +- [allocator]: fix on invalid DMA heap allocator +- [hal_h265e_vepu580]: fix reg config err for 2pass +- [jpegd_vdpu]: Adjust file dump path +- [mpp_common]: fix 128 odd plus 64 alignment +- [cmake]: fix static build +- [vdpu383]: Update vdpu383 error detection + +### Docs +- Update 1.0.6 CHANGELOG.md + +### Refactor +- [hal_jpegd]: init devices at hal_jpegd_api +- [dec]: get deocder capability via common routine +- [hal_av1d]: Migrate av1d from vpu to rkdec + +### Chore +- [h265d]: Reduce malloc/free frequency of vps +- [mpp_service]: fix typo err +- [hal_h265d]: use INT_MAX for poc distance initiation +- [cmake]: remove duplicate code + +## 1.0.5 (2024-04-19) +### Feature +- [vdpu383]: align hor stride to 128 odds + 64 byte +- [vdpu383]: support 2x2 scale down +- [mpp_buffer]: Add MppBuffer attach/detach func +- [mpp_dev]: Add fd attach/detach operation +- [vdpp]: Add libvdpp for hwpq +- [vdpp]: Add capacity check function +- [cmake]: Add building static library +- [vdpp_test]: Add vdpp slt testcase +- [av1d]: Add tile4x4 frame format support +- [mpp_enc_cfg]: Add H.265 tier config +- [jpeg]: Add VPU720 JPEG support +- [enc]: Add config entry for output chroma format +- [vdpu383]: Add vdpu383 av1 module +- [vdpu383]: Add vdpu383 vp9 module +- [vdpu383]: Add vdpu383 avs2 module +- [vdpu383]: Add vdpu383 H.264 module +- [vdpu383]: Add vdpu383 H.265 module +- [vdpu383]: Add vdpu383 common module +- [vdpp]: Add vdpp2 for rk3576 +- [vdpp]: Add vdpp module and vdpp_test +- [vepu_510]: Add vepu510 h265e support +- [vepu_510]: Add vepu510 h264e support +- [mpp_frame]: Add tile format flag +- [vepu_510] add vepu 510 common for H264 & h265 +- [mpp_soc]: support rk3576 soc + +### Fix +- [avs2d_vdpu383]: Optimise dec result +- [vdpu383]: Fix compiler warning +- [vdpp]: Fix dmsr reg size imcompat error +- [vdpu383]: hor stride alignment fix for vdpu383 +- [h265d_ref]: fix set fbc output fmt not effect issue +- [vdpu383]: Fix memory out of bounds issue +- [h264d_vdpu383]: Fix global parameter config issue +- [avs2_parse]: add colorspace config to mpp_frame +- [hal_h264e]:fix crash after init vepu buffer failure +- [vpu_api]: Fix frame format and eos cfg +- [av1d_vdpu383]: fix fbc hor_stride error +- [av1d_parser]: fix fmt error for 10bit HDR source +- [avs2d]: fix stuck when seq_end shows at pkt tail +- [av1d_vdpu]: Fix forced 8bit output failure issue +- [enc_async]: Invalidate cache for output buffer +- [hal_av1d_vdpu383]: memleak for cdf_bufs +- [av1d_vdpu383]: fix rcb buffer size +- [vp9d_vdpu383]: Fix segid config issue +- [vepu510]: Add split low delay output mode support +- [avs2d_vdpu383]: Fix declaring shadow local variables issue +- [av1]: Fix global config issue +- [hal_av1d]: Delte cdf unused value +- [av1]: Fix av1 display abnormality issue +- [avs2d]: Remove a unnecessary log +- [vepu510]: Adjust regs assignment +- [hal_jpegd]: Add stream buffer flush +- [265e_api]: Support cons_intra_pred_flag cfg +- [mpp_enc]: Add device attach/detach on enc flow +- [mpp_dec]: Add device attach/detach on dec flow +- [vdpp]: Add error detection +- [hal_265e_510]: modify srgn_max & rime_lvl val +- [vdpu383]: spspps data not need copy all range ppsid +- [vpu_api_legacy]: fix frame CodingType err +- [av1]: Fix 10bit source display issue +- [mpp_enc]: Expand the hdr_buf size +- [av1]: Fix delta_q value read issue +- [vdpu383]: Enable error detection +- [ext_dma]: fix mmap permission error +- [jpege_vpu720]: sync cache before return task +- [mpp_buffer]: fix buffer type assigning +- [vepu510]: Configure reg of Subjective param +- [vepu510]: Checkout and optimize 510 reg.h +- [mpp_dec]: Optimize HDR meta process +- [av1d]: Fix scanlist calc issue +- [h265e]: fix the profile tier cfg +- [av1d]: Fix av1d ref stride error +- [hal_h265e_vepu510]: Add cudecis reg cfg +- [av1d]: Only rk3588 support 10bit translate to 8bit +- [vp9d]: Fix vp9 hor stride issue +- [rc]: Add i quality delta cfg on fixqp mode +- [hal_h265d]: Fix filter col rcb buffer size calc +- [av1d]: Fix compiler warning +- [h264d]: Fix error mvc stream crash issue +- [hal_h264e]: Fix qp err when fixqp mode +- [h264d]: Fix H.264 error chroma_format_idc +- [vdpu383]: Fix av1 rkfbc output error +- [av1d]: Fix compatibility issues +- [hal_h264d_vdpu383]: Reduce mpp_put_bits calls +- Fix clerical error +- [avs2d]: Fix get ref_frm slot idx error +- [vdpu383]: Fix av1 global params bit pos issue +- [vdpp]: fix sharp config error +- [hal_av1d]: fix av1 dec err for rk3588 +- [vdpu383]: Fix av1 global params issue +- [vepu510]: Fix camera record stuck issue +- [utils]: fix read and write some YUV format +- [mpp_bitput]: fix put bits overflow +- [mpp_service]: fix rcb info env config +- [vepu510]: Fix compile warning +- [hal_vp9d]: fix colmv size calculator err +- [avsd]: Fix the ref_frm slot idx erro in fast mode. + +### Docs +- Update 1.0.5 CHANGELOG.md +- [mpp_frame]: Add MppFrameFormat description + +### Refactor +- [hal_av2sd]: refactor hal_api assign flow +- [hal_h264d]: refactor hal_api assign flow +- Using soc_type for compare instead of soc_name + +### Chore +- [hal_h264e]: clean some unused code + +## 1.0.4 (2024-02-07) +### Feature +- [vpu_api_legacy]: Support RGB24 setup +- [avsd]: keep codec type if not avs+ +- [mpi_enc_test]: add YUV400 fmt support +- [mpp_enc]: Add YUV400 support for vepu580/540 + +### Fix +- [h265e]: fix hw stream size check error +- [hal_vdpu]: unify colmv buffer size calculation +- [vproc]: Fix deadlock in vproc thread +- [h265e]: disable tmvp by default +- [h265e]: Amend temporal_id to stream +- [mpp_dump]: add YUV420SP_10BIT format dump +- [hal_h265d]: Fix register length for rk3328/rk3328H +- [hal_avsd]: Fix crash on no buffer decoded +- [mpp_enc]: allow vp8 to cfg force idr frame +- [m2vd]: fix unindentical of input and output pts list +- [h265e_vepu580]: fix SIGSEGV when reencoding +- [mpp_dmabuf]: fix align cache line size calculate err +- [h265e_vepu580]: flush cache for the first tile +- [dmabuf]: Disable dmabuf partial sync function +- [iep_test]: use internal buffer group +- [common]: Add mpp_dup function +- [h265e]: Adapter RK3528 when encoding P frame skip +- [h265e]: fix missing end_of_slice_segment_flag problem +- [hal_av1d_vdpu]: change rkv_hor_align to 16 align +- [av1d_parser]: set color info per frame +- [jpegd]: add sof marker check when parser done + +### Docs +- Update 1.0.4 CHANGELOG.md + +### Chore +- [script]: add rebuild and clean for build +- [mpp_enc_roi_utils]: change file format dos to unix + +## 1.0.3 (2023-12-08) +### Feature +- [dec_test]: Add buffer mode option +- [mpp_dmabuf]: Add dmabuf sync operation +- [jpege]: Allow rk3588 jpege 4 tasks async +- [rc_v2]: Support flex fps rate control + +### Fix +- [av1d_api]: fix loss last frame when empty eos +- [h265e_dpb]: do not check frm status when pass1 +- [hal_bufs]: clear buffer when hal_bufs get failed +- [dma-buf]: Add dma-buf.h for old ndk compiling +- [enc]: Fix sw enc path segment_info issue +- [cmake]: Remove HAVE_DRM option +- [m2vd]: update frame period on frame rate code change +- [test]: Fix mpi_enc_mt_test error +- [dma_heap]: add dma heap uncached node checking +- [mpp_mem]: Fix MEM_ALIGNED macro error +- [mpeg4_api]: fix drop frame when two stream switch +- [script]: fix shift clear input parameter error +- [hal_h265e_vepu541]: fix roi buffer variables incorrect use + +### Docs +- Update 1.0.3 CHANGELOG.md + +### Refactor +- [allocator]: Refactor allocator flow + +### Chore +- [vp8d]: optimize vp8d debug +- [mpp_enc]: Encoder changes to cacheable buffer +- [mpp_dec]: Decoder changes to cacheable buffer +- [mpp_dmabuf]: Add dmabuf ioctl unit test + +## 1.0.2 (2023-11-01) +### Feature +- [mpp_lock]: Add spinlock timing statistic +- [mpp_thread]: Add simple thread +- add more enc info to meta + +### Fix +- [vepu540c]: fix h265 config +- [h264d]: Optimize sps check error +- [utils]: adjust format range constraint +- [h264d]: fix mpp split eos process err +- [h264d]: add errinfo for 4:4:4 lossless mode +- [h264d]: fix eos not updated err +- [camera_source]: Fix memory double-free issue +- [mpp_dec]:fix mpp_destroy crash +- [mpp_enc]: Fix async multi-thread case error +- [jpeg_dec]: Add parse & gen_reg err check for jpeg dec +- [h265e_vepu580]: fix tile mode cfg +- [vp9d]: Fix AFBC to non-FBC mode switch issue +- [h264e_dpb]: fix modification_of_pic_nums_idc error issue +- [allocator]: dma_heap allocator has the highest priority +- [camera_source]: enumerate device and format +- [utils]: fix hor_stride 24 aligned error + +### Docs +- Update 1.0.2 CHANGELOG.md +- Add mpp developer guide markdown + +### Chore +- [scipt]: Update changelog.sh + +## 1.0.1 (2023-09-28) +### Feature +- [venc]: Modify fqp init value to invalid. +- [vepu580]: Add frm min/max qp and scene_mode cmd param +- [venc]: Add qbias for rkvenc encoder +- Support fbc mode change on info change stage +- [hal_vepu5xx]: Expand color transform for 540c +- Add rk3528a support + +### Fix +- [mpp_enc_impl]: fix some error values without return an error +- [av1d_cbs]: fix read 32bit data err +- [Venc]: Fix jpeg and vpx fqp param error. +- [h265e_vepu580]: dual cores concurrency problem +- [hal_h264e_vepu]: terminate task if not support +- [vdpu_34x]: disable cabac err check for rk3588 +- [enc]: fix duplicate idr frame +- [h264e_amend]: fix slice read overread issue +- [hal_jpegd]: add pp feature check +- [enc]: fix duplicate sps/pps information +- [h264e_slice]: fix pic_order_cnt_lsb wrap issue +- [hal_h264e_vepu540c]: fix reg configuration +- [hal_h264e_vepu540c]: Amend slice header +- [h264d]: fix crash on check reflist +- [hal_vp9d]: not support fast mode for rk3588 +- [h264d]: fix frame output order when dpb full +- [mpp_frame]: setup color default UNSPECIFIED instead 0 +- [hal_h264d]: adjust position of env_get +- [h264e_slice]: fix pic_order_cnt_lsb wrap issue +- [hal_avs2d]: fix some issue +- fix redundant prefix NALU amended problem +- [hal_jpegd]: fix rgb out_fmt mismatch error +- [utils]: fix convert format error +- [h265e]: check input profile_idc +- [hal_h264e_vepu580]: fix SEGV on GDR setting +- [h264d]: fix TSVC decode assert error. +- [hal_vepu580]: fix comiple issue +- [h264d]: fix MVC DPB allocation +- [h264d]: fix SEI packet parsing +- [hal_vp8e]: fix entropy init +- [mpp_soc]: fix rk356x vepu2 capability + +### Docs +- Add 1.0.1 CHANGELOG.md +- update readme.txt + +### Refactor +- move same tables to common module + +## 1.0.0 (2023-07-26) +### Docs +- Add 1.0.0 CHANGELOG.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 41146658b..3295e1ef2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,368 +1,384 @@ -# ---------------------------------------------------------------------------- -# Root CMake file for Rockchip Media Process Platform (MPP) -# -# - 10:34 2015/7/27: Initial version -# -# ---------------------------------------------------------------------------- - -# vim: syntax=cmake -if(NOT CMAKE_BUILD_TYPE) - # default to Release build for GCC builds - set(CMAKE_BUILD_TYPE Debug CACHE STRING - "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." - FORCE) -endif() -message(STATUS "cmake version ${CMAKE_VERSION}") -if(NOT CMAKE_VERSION VERSION_LESS "2.8.12.20131121") - cmake_policy(SET CMP0025 OLD) # report Apple's Clang as just Clang - cmake_policy(SET CMP0042 OLD) # do not require MACOSX_RPATH -endif() - -# Search packages for host system instead of packages for target system -# in case of cross compilation these macro should be defined by toolchain file -if(NOT COMMAND find_host_package) - macro(find_host_package) - find_package(${ARGN}) - endmacro() -endif() -if(NOT COMMAND find_host_program) - macro(find_host_program) - find_program(${ARGN}) - endmacro() -endif() - - -project (rk_mpp) - -cmake_minimum_required (VERSION 2.8.8) # OBJECT libraries require 2.8.8 -include(CheckIncludeFiles) -include(CheckFunctionExists) -include(CheckSymbolExists) -include(CheckCXXCompilerFlag) - -# ---------------------------------------------------------------------------- -# set property to classify library kinds -# ---------------------------------------------------------------------------- -set_property(GLOBAL PROPERTY USE_FOLDERS ON) -set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") -# ---------------------------------------------------------------------------- -# enable test in this project -# ---------------------------------------------------------------------------- -enable_testing() - -# ---------------------------------------------------------------------------- -# add debug define in project -# ---------------------------------------------------------------------------- -if(NOT $(CMAKE_BUILD_TYPE) MATCHES "Release") - option(RK_DEBUG "Enable run-time debug mode(debugging)" ON) - if(RK_DEBUG) - add_definitions(-DRK_DEBUG) - message(STATUS "rk_mpp debug mode is enabled") - endif() -endif() - -# ---------------------------------------------------------------------------- -# System architecture detection -# ---------------------------------------------------------------------------- -string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSPROC) -set(X86_ALIASES x86 i386 i686 x86_64 amd64) -list(FIND X86_ALIASES "${SYSPROC}" X86MATCH) -if("${SYSPROC}" STREQUAL "" OR X86MATCH GREATER "-1") - message(STATUS "Detected x86 system processor") - set(X86 true) - add_definitions(-DARCH_X86=1) - if("${CMAKE_SIZEOF_VOID_P}" MATCHES 8) - set(X64 true) - add_definitions(-DARCH_X64=1) - message(STATUS "Define X86_64 to 1") - endif() -elseif(${SYSPROC} STREQUAL "armv6l") - message(STATUS "Detected ARMv6 system processor") - set(ARM true) - set(ARMEABI_V6 true) - add_definitions(-DARCH_ARM=1 -DDHAVE_ARMV6=1) -elseif(${SYSPROC} STREQUAL "armv7-a") - message(STATUS "Detected ARMv7 system processor") - set(ARM true) - set(ARMEABI_V7A true) - add_definitions(-DARCH_ARM=1 -DDHAVE_ARMV7=1) -else() - message(STATUS "CMAKE_SYSTEM_PROCESSOR value `${CMAKE_SYSTEM_PROCESSOR}` is unknown") - message(STATUS "Please add this value near ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}") -endif() - -if(UNIX) - SET(PLATFORM_LIBS pthread) - if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - SET(PLATFORM_LIBS ${PLATFORM_LIBS} rt) - endif() -endif(UNIX) - -# ---------------------------------------------------------------------------- -# Compiler detection -# ---------------------------------------------------------------------------- -if(CMAKE_GENERATOR STREQUAL "Xcode") - set(XCODE true) -endif() - -if (APPLE) - add_definitions(-DMACOS) -endif() - -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(CLANG true) -endif() -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") - set(INTEL_CXX true) -endif() -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(GCC true) -endif() - -if(INTEL_CXX AND WIN32) - # treat icl roughly like MSVC - set(MSVC true) -endif() -if(MSVC) - option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF) - if (STATIC_LINK_CRT) - set(CompilerFlags CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_RELEASE) - foreach(CompilerFlag ${CompilerFlags}) - string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") - endforeach() - endif (STATIC_LINK_CRT) - add_definitions(/W3) # Full warnings - add_definitions(/Ob2) # always inline - add_definitions(/MP) # multithreaded build - # disable Microsofts suggestions for proprietary secure APIs - add_definitions(/D_CRT_SECURE_NO_WARNINGS) -endif(MSVC) - -if(INTEL_CXX AND UNIX) - # treat icpc roughly like gcc - set(GCC true) - add_definitions(-Wall -Wextra -Wshadow) -elseif(CLANG) - # treat clang roughly like gcc - set(GCC true) - add_definitions(-Wall -Wextra -Wshadow -ffast-math) -elseif(CMAKE_COMPILER_IS_GNUCXX) - add_definitions(-Wall -Wextra -Wshadow -ffast-math) - check_cxx_compiler_flag(-Wno-narrowing GCC_HAS_NO_NARROWING) - check_cxx_compiler_flag(-mstackrealign GCC_HAS_STACK_REALIGN) - if (GCC_HAS_STACK_REALIGN) - add_definitions(-mstackrealign) - endif() - execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) -endif() - -if(GCC) - if(X64 AND NOT WIN32) - add_definitions(-fPIC) - endif(X64 AND NOT WIN32) - if(X86 AND NOT X64) - add_definitions(-march=i686) - endif() - if(ARM) - if(ARMEABI_V6) - add_definitions(-march=armv6 -mfloat-abi=hard -mfpu=vfp) - elseif(ARMEABI_V7A) - add_definitions(-march=armv7-a -mfloat-abi=softfp -mfpu=neon) - endif() - endif() -endif(GCC) - -# ---------------------------------------------------------------------------- -# Create svn version information -# ---------------------------------------------------------------------------- -set(HAVE_SVN 0) -if(EXISTS "${PROJECT_SOURCE_DIR}/.svn/") - find_host_package(Subversion) - if(Subversion_FOUND) - set(HAVE_SVN true) - else() - if(WIN32) - # The official subversion client is not available, so fall back to - # tortoise if it is installed. - find_program(TORTOISE_WCREV_EXECUTABLE - NAMES SubWCRev.exe - PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\TortoiseSVN;Directory]/bin" - ) - - if (NOT TORTOISE_WCREV_EXECUTABLE) - message(STATUS "TortoiseSVN was not found.") - else(NOT TORTOISE_WCREV_EXECUTABLE) - message(STATUS "TortoiseSVN was Found.") - set(HAVE_SVN true) - - macro(Subversion_WC_INFO dir prefix) - # the subversion commands should be executed with the C locale, otherwise - # the message (which are parsed) may be translated, Alex - set(_Subversion_SAVED_LC_ALL "$ENV{LC_ALL}") - set(ENV{LC_ALL} C) - - execute_process(COMMAND ${TORTOISE_WCREV_EXECUTABLE} ${dir} - OUTPUT_VARIABLE ${prefix}_WC_INFO - ERROR_VARIABLE Subversion_svn_info_error - RESULT_VARIABLE Subversion_svn_info_result - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_STRIP_TRAILING_WHITESPACE) - - if(NOT ${Subversion_svn_info_result} EQUAL 0) - message(SEND_ERROR "Command \"${TORTOISE_WCREV_EXECUTABLE} ${dir}\" failed with output:\n${Subversion_svn_info_error}") - else() - string(REGEX REPLACE "^(.*\n)?Last committed at revision ([0-9]*)\n.*" - "\\2" ${prefix}_WC_REVISION "${${prefix}_WC_INFO}") - endif() - set(Project_WC_LAST_CHANGED_AUTHOR "unknown") - set(Project_WC_LAST_CHANGED_DATE "unknown") - - # restore the previous LC_ALL - set(ENV{LC_ALL} ${_Subversion_SAVED_LC_ALL}) - endmacro() - endif (NOT TORTOISE_WCREV_EXECUTABLE) - endif(WIN32) - endif(Subversion_FOUND) - -endif(EXISTS "${PROJECT_SOURCE_DIR}/.svn/") - -if(${HAVE_SVN}) - Subversion_WC_INFO(${PROJECT_SOURCE_DIR} Project) - - message(STATUS "Current svn revision is ${Project_WC_REVISION}") - set(VERSION_REVISION ${Project_WC_REVISION}) - set(VERSION_LAST_AUTHOR ${Project_WC_LAST_CHANGED_AUTHOR}) - set(VERSION_LAST_DATA ${Project_WC_LAST_CHANGED_DATE}) -else() - set(VERSION_REVISION -1) -endif() - -configure_file( - "${PROJECT_SOURCE_DIR}/build/cmake/svn_info.in" - "${PROJECT_SOURCE_DIR}/mpp/svn_info.h" -) - - -# ---------------------------------------------------------------------------- -# Build options -# ---------------------------------------------------------------------------- -set(CMAKE_INSTALL_PREFIX "") -set(LIB_INSTALL_DIR "${CMAKE_SOURCE_DIR}/out/lib" CACHE STRING "Install location of libraries") -set(BIN_INSTALL_DIR "${CMAKE_SOURCE_DIR}/out/bin" CACHE STRING "Install location of executables") -set(TEST_INSTALL_DIR "${CMAKE_BINARY_DIR}/test" CACHE STRING "Install location of unit test") - - -# ---------------------------------------------------------------------------- -# Set Warning as Error -# ---------------------------------------------------------------------------- -option(WARNINGS_AS_ERRORS "Stop compiles on first warning" OFF) -if(WARNINGS_AS_ERRORS) - if(GCC) - add_definitions(-Werror) - elseif(MSVC) - add_definitions(/WX) - endif() -endif(WARNINGS_AS_ERRORS) - -# ---------------------------------------------------------------------------- -# Visual leak detector -# ---------------------------------------------------------------------------- -if (WIN32) - find_host_package(VLD QUIET) - if(VLD_FOUND) - add_definitions(-DHAVE_VLD) - include_directories(${VLD_INCLUDE_DIRS}) - set(PLATFORM_LIBS ${PLATFORM_LIBS} ${VLD_LIBRARIES}) - link_directories(${VLD_LIBRARY_DIRS}) - endif() - option(WINXP_SUPPORT "Make binaries compatible with Windows XP" OFF) - if(WINXP_SUPPORT) - # force use of workarounds for CONDITION_VARIABLE and atomic - # intrinsics introduced after XP - add_definitions(-D_WIN32_WINNT=_WIN32_WINNT_WINXP) - endif() -endif() - -# ---------------------------------------------------------------------------- -# look for stdint.h -# ---------------------------------------------------------------------------- -if(MSVC) - check_include_files(stdint.h HAVE_STDINT_H) - if(NOT HAVE_STDINT_H) - include_directories(osal/window) - endif(NOT HAVE_STDINT_H) -endif(MSVC) - -# ---------------------------------------------------------------------------- -# On window import win32 pthread library -# ---------------------------------------------------------------------------- -if(MSVC) - set(WIN32_PTHREAD_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/osal/window/pthread/inc") - include_directories(${WIN32_PTHREAD_INCLUDE_DIRS}) - add_library(pthread SHARED IMPORTED) - message(STATUS "platform X86 ${X86} X64 ${X64}") - set(WIN32_PTHREAD_LIB_DIRS "${CMAKE_SOURCE_DIR}/osal/window/pthread/lib") - set(WIN32_PTHREAD_DLL_DIRS "${CMAKE_SOURCE_DIR}/osal/window/pthread/dll") - if(X64) - set(WIN32_ARCH "x64") - else() - set(WIN32_ARCH "x86") - endif() - include_directories("${WIN32_PTHREAD_LIB_DIRS}/${WIN32_ARCH}") - include_directories("${WIN32_PTHREAD_DLL_DIRS}/${WIN32_ARCH}") - set_target_properties(pthread PROPERTIES - IMPORTED_LOCATION - "${WIN32_PTHREAD_LIB_DIRS}/${WIN32_ARCH}/pthreadVC2.dll") - set_target_properties(pthread PROPERTIES - IMPORTED_IMPLIB - "${WIN32_PTHREAD_LIB_DIRS}/${WIN32_ARCH}/pthreadVC2.lib") -endif() - -# ---------------------------------------------------------------------------- -# Share library option -# ---------------------------------------------------------------------------- -option(ENABLE_STATIC "Build shared library" ON) -option(ENABLE_SHARED "Build shared library" OFF) - -# ---------------------------------------------------------------------------- -# scan all LOG_TAG for log information and generate module header file -# ---------------------------------------------------------------------------- -set( module_list "" ) -file ( GLOB_RECURSE ALL_SRC . *.c;*.cpp ) -foreach( files ${ALL_SRC} ) - file( STRINGS ${files} module_tag_line REGEX "MODULE_TAG( )+\".+\"" ) - if(module_tag_line) - string( REGEX REPLACE "^(.)* MODULE_TAG( )+\"(.*)\"" \\3 module_tag ${module_tag_line} ) - list( APPEND module_list ${module_tag} ) - endif() -endforeach() -list( SORT module_list ) -list( LENGTH module_list module_size ) -#message(STATUS "module_list: ${module_list}") -#message(STATUS "module_size: ${module_size}") - -# ---------------------------------------------------------------------------- -# Start module definition -# ---------------------------------------------------------------------------- -# project overall include file -include_directories(inc) - -# ---------------------------------------------------------------------------- -# osal library -# ---------------------------------------------------------------------------- -# Operation System Abstract Layer (OSAL) include -include_directories(osal/inc) -# OSAL is needed on all platform, do not need option -add_subdirectory(osal) - -# ---------------------------------------------------------------------------- -# Media Process Platform library -# ---------------------------------------------------------------------------- -# Media Process Platform include -include_directories(mpp/inc) -add_subdirectory(mpp) - -# ---------------------------------------------------------------------------- -# test / demo -# ---------------------------------------------------------------------------- -add_subdirectory(test) +# ---------------------------------------------------------------------------- +# Root CMake file for Rockchip Media Process Platform (MPP) +# +# - 10:34 2015/7/27: Initial version +# +# ---------------------------------------------------------------------------- + +# vim: syntax=cmake +set(CMAKE_POLICY_VERSION_MINIMUM 3.5) +if(NOT CMAKE_BUILD_TYPE) + # default to Release build for GCC builds + set(CMAKE_BUILD_TYPE Debug CACHE STRING + "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." + FORCE) +endif() +message(STATUS "cmake version ${CMAKE_VERSION}") + +# Search packages for host system instead of packages for target system +# in case of cross compilation these macro should be defined by toolchain file +if(NOT COMMAND find_host_package) + macro(find_host_package) + find_package(${ARGN}) + endmacro() +endif() +if(NOT COMMAND find_host_program) + macro(find_host_program) + find_program(${ARGN}) + endmacro() +endif() + +if(POLICY CMP0009) + cmake_policy(SET CMP0009 NEW) +endif() + +cmake_minimum_required(VERSION 3.5) +project (rk_mpp) + +include(CheckIncludeFiles) +include(CheckFunctionExists) +include(CheckSymbolExists) +include(CheckCXXCompilerFlag) +include(${PROJECT_SOURCE_DIR}/build/cmake/merge_objects.cmake) + +# setup output library name +# Linux default name - rockchip_mpp and rockchip_vpu +# Android default name - mpp and vpu +# For historical reason libraries on Android is named as mpp and vpu. But for +# better naming rule on Linux it should add vendor prefix. +# So we use this ugly method to avoid massive maintain issue. +if (NOT MPP_PROJECT_NAME) + set(MPP_PROJECT_NAME rockchip_mpp) +endif() +set(MPP_STATIC ${MPP_PROJECT_NAME}_static) +set(MPP_SHARED ${MPP_PROJECT_NAME}) + +if (NOT VPU_PROJECT_NAME) + set(VPU_PROJECT_NAME rockchip_vpu) +endif() +set(VPU_STATIC ${VPU_PROJECT_NAME}_static) +set(VPU_SHARED ${VPU_PROJECT_NAME}) + +# ---------------------------------------------------------------------------- +# set property to classify library kinds +# ---------------------------------------------------------------------------- +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") +# ---------------------------------------------------------------------------- +# enable test in this project +# ---------------------------------------------------------------------------- +option(BUILD_TEST "enable test binary building)" ON) +# ---------------------------------------------------------------------------- +# export json compile commands +# ---------------------------------------------------------------------------- +set(CMAKE_EXPORT_COMPILE_COMMANDS true) + +# ---------------------------------------------------------------------------- +# System architecture detection +# ---------------------------------------------------------------------------- +string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSPROC) +set(X86_ALIASES x86 i386 i686 x86_64 amd64) +list(FIND X86_ALIASES "${SYSPROC}" X86MATCH) +if("${CMAKE_C_COMPILER}" MATCHES "-buildroot-[^/]+$") + message(STATUS "Detected Buildroot toolchain") + # Use buildroot toolchain's default architecture settings +elseif("${SYSPROC}" STREQUAL "" OR X86MATCH GREATER "-1") + message(STATUS "Detected x86 system processor") + set(X86 true) + add_definitions(-DARCH_X86=1) + if("${CMAKE_SIZEOF_VOID_P}" MATCHES 8) + set(X64 true) + add_definitions(-DARCH_X64=1) + message(STATUS "Define X86_64 to 1") + endif() +elseif(${SYSPROC} STREQUAL "armv6l") + message(STATUS "Detected ARMv6 system processor") + set(ARM true) + set(ARMEABI_V6 true) +elseif(${SYSPROC} STREQUAL "armv7-a") + message(STATUS "Detected ARMv7 system processor") + set(ARM true) + set(ARMEABI_V7A true) +elseif(${SYSPROC} STREQUAL "armv7-a_hardfp" OR ${SYSPROC} STREQUAL "armv7l") + message(STATUS "Detected ARMv7 system processor") + set(ARM true) + set(ARMEABI_V7A_HARDFP true) +elseif(${SYSPROC} STREQUAL "aarch64" OR ${SYSPROC} STREQUAL "armv8-a") + message(STATUS "Detected ARMv8 system processor") + set(ARM true) + set(ARMEABI_V8 true) +else() + message(STATUS "CMAKE_SYSTEM_PROCESSOR value `${CMAKE_SYSTEM_PROCESSOR}` is unknown") + message(STATUS "Please add this value near ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}") +endif() + +# ---------------------------------------------------------------------------- +# Compiler detection +# ---------------------------------------------------------------------------- +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(CLANG true) +endif() +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(GCC true) +endif() + +if(${CMAKE_BUILD_TYPE} MATCHES "Release") + # remove -g option for high version ndk + string(REGEX REPLACE "-g[^ ]*" "" TMP "${CMAKE_C_FLAGS}") + string(REGEX REPLACE "[ ]+" " " CMAKE_C_FLAGS "${TMP}") + string(REGEX REPLACE "-g[^ ]*" "" TMP "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "[ ]+" " " CMAKE_CXX_FLAGS "${TMP}") + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -DNDEBUG") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG") +else() + add_definitions(-g) +endif() + +if(GCC) + if(ARM) + if(ARMEABI_V6) + add_definitions(-march=armv6 -mfloat-abi=hard -mfpu=vfp) + elseif(ARMEABI_V7A) + add_definitions(-march=armv7-a -mfloat-abi=softfp -mfpu=neon) + elseif(ARMEABI_V7A_HARDFP) + add_definitions(-march=armv7-a -mfloat-abi=hard -mfpu=neon) + elseif(ARMEABI_V8) + add_definitions(-march=armv8-a) + endif() + else() + if(X86 AND NOT X64) + add_definitions(-march=i686) + endif() + endif() + + # disable multichar warning + add_definitions(-Wno-multichar) + # add PIC flag + add_definitions(-fPIC) + # disable exception for C++ + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti") + # save intermediate files + # add_definitions(-save-temps) + + # check library mvec + find_library(LMVEC_LIB mvec) + if(LMVEC_LIB) + set(LIBM mvec m) + set(MPP_PKGCONFIG_DEPENDENT_LIBS "-lmvec -lm") + else() + set(LIBM m) + set(MPP_PKGCONFIG_DEPENDENT_LIBS "-lm") + add_definitions(-fno-builtin-pow) + endif() + + option(ASAN_CHECK "enable Address Sanitizer (Asan)" OFF) + if(ASAN_CHECK) + add_definitions(-fsanitize=address -static-libasan -g) + set(ASAN_LIB libasan.a dl rt m) + set(ASAN_BIN dl rt m) + endif(ASAN_CHECK) +endif(GCC) + +if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + add_compile_options( + "$<$:-Wall;-Wextra;-Wuninitialized;-Wmissing-field-initializers>" + ) +endif() + +# for libary linking +set(BEGIN_WHOLE_ARCHIVE -Wl,--whole-archive) +set(END_WHOLE_ARCHIVE -Wl,--no-whole-archive) + +# ---------------------------------------------------------------------------- +# Create git version information +# ---------------------------------------------------------------------------- +set(VERSION_CNT 0) +set(VERSION_MAX_CNT 9) +set(VERSION_INFO "\"unknown mpp version for missing VCS info\"") +foreach (CNT RANGE ${VERSION_MAX_CNT}) + set(VERSION_HISTORY_${CNT} "NULL") +endforeach(CNT) + +if(EXISTS "${PROJECT_SOURCE_DIR}/.git") + find_host_package(Git) + if(GIT_FOUND) + # get current version info + set(GIT_LOG_FORMAT "%h author: %<|(30)%an %cd %s") + + execute_process(COMMAND ${GIT_EXECUTABLE} log -1 --oneline --date=short --pretty=format:${GIT_LOG_FORMAT} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE EXEC_OUT + ERROR_VARIABLE EXEC_ERROR + RESULT_VARIABLE EXEC_RET + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + + if (NOT EXEC_RET) + set(VERSION_INFO ${EXEC_OUT}) + message(STATUS "current version:") + message(STATUS "${VERSION_INFO}") + string(REPLACE "\"" "\\\"" VERSION_INFO ${VERSION_INFO}) + set(VERSION_INFO "\"${VERSION_INFO}\"") + else() + message(STATUS "git ret ${EXEC_RET}") + message(STATUS "${EXEC_ERROR}") + endif() + + set(GIT_LOG_FORMAT "%h author: %<|(30)%an %cd %s %d") + + # get history version information + # setup logs + message(STATUS "git version history:") + foreach (CNT RANGE ${VERSION_MAX_CNT}) + execute_process(COMMAND ${GIT_EXECUTABLE} log HEAD~${CNT} -1 --oneline --date=short --pretty=format:${GIT_LOG_FORMAT} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE EXEC_OUT + ERROR_VARIABLE EXEC_ERROR + RESULT_VARIABLE EXEC_RET + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + + if (NOT EXEC_RET) + set(VERSION_LOG ${EXEC_OUT}) + string(REPLACE "\"" "\\\"" VERSION_LOG ${VERSION_LOG}) + message(STATUS ${VERSION_LOG}) + set(VERSION_HISTORY_${CNT} "\"${VERSION_LOG}\"") + math(EXPR VERSION_CNT "${VERSION_CNT}+1") + endif() + endforeach(CNT) + message(STATUS "total ${VERSION_CNT} git version recorded") + endif() + + # add git hooks + if (EXISTS "${PROJECT_SOURCE_DIR}/tools/hooks/") + set(GIT_HOOK_SRC "${PROJECT_SOURCE_DIR}/tools/hooks/") + if(EXISTS "${PROJECT_SOURCE_DIR}/.git/hooks") + set(GIT_HOOK_DST "${PROJECT_SOURCE_DIR}/.git/hooks/") + file(COPY ${GIT_HOOK_SRC} DESTINATION ${GIT_HOOK_DST}) + message(STATUS "Install git hooks done") + endif(EXISTS "${PROJECT_SOURCE_DIR}/.git/hooks") + endif(EXISTS "${PROJECT_SOURCE_DIR}/tools/hooks/") +endif(EXISTS "${PROJECT_SOURCE_DIR}/.git") + +configure_file( + "${PROJECT_SOURCE_DIR}/build/cmake/version.in" + "${PROJECT_SOURCE_DIR}/mpp/version.h" +) + +# ---------------------------------------------------------------------------- +# Build options +# ---------------------------------------------------------------------------- +find_package(PkgConfig) +include(GNUInstallDirs) +pkg_search_module(PTHREAD pthread) + +find_package(Threads) + +# ---------------------------------------------------------------------------- +# Set Warning as Error +# ---------------------------------------------------------------------------- +option(WARNINGS_AS_ERRORS "Stop compiles on first warning" OFF) +if(WARNINGS_AS_ERRORS) + if(GCC) + add_definitions(-Werror) + elseif(MSVC) + add_definitions(/WX) + endif() +endif(WARNINGS_AS_ERRORS) + +# ---------------------------------------------------------------------------- +# look for stdint.h +# ---------------------------------------------------------------------------- +if(MSVC) + check_include_files(stdint.h HAVE_STDINT_H) + if(NOT HAVE_STDINT_H) + include_directories(osal/windows) + endif(NOT HAVE_STDINT_H) +endif(MSVC) + +# ---------------------------------------------------------------------------- +# Share library option +# ---------------------------------------------------------------------------- +option(BUILD_SHARED_LIBS "Build shared library" ON) + +# ---------------------------------------------------------------------------- +# scan all LOG_TAG for log information and generate module header file +# ---------------------------------------------------------------------------- +set( module_list "" ) + +file ( GLOB_RECURSE ALL_SRC . *.c;*.cpp ) +foreach( files ${ALL_SRC} ) + file( STRINGS ${files} module_tag_line REGEX "MODULE_TAG( )+\".+\"" ) + if(module_tag_line) + string( REGEX REPLACE "^(.)* MODULE_TAG( )+\"(.*)\"" \\3 module_tag ${module_tag_line} ) + list( APPEND module_list ${module_tag} ) + endif() +endforeach() +list( SORT module_list ) +list( LENGTH module_list module_size ) +#message(STATUS "module_list: ${module_list}") +#message(STATUS "module_size: ${module_size}") + +# ---------------------------------------------------------------------------- +# Start module definition +# ---------------------------------------------------------------------------- +# project overall include file +include_directories(inc) +# small utile functions for test case +include_directories(utils) + +# ---------------------------------------------------------------------------- +# osal library +# ---------------------------------------------------------------------------- +# Operation System Abstract Layer (OSAL) include +include_directories(osal/inc) +# OSAL is needed on all platform, do not need option +add_subdirectory(osal) + +# Media Process Platform include +include_directories(mpp/inc) +include_directories(mpp/base/inc) +# Kernel Media Process Platform include +include_directories(kmpp/inc) +include_directories(kmpp/base/inc) + +# ---------------------------------------------------------------------------- +# utils for test case +# ---------------------------------------------------------------------------- +add_subdirectory(utils) + +# ---------------------------------------------------------------------------- +# Kernel Media Process Platform library +# ---------------------------------------------------------------------------- +add_subdirectory(kmpp) + +# ---------------------------------------------------------------------------- +# Media Process Platform library +# ---------------------------------------------------------------------------- +add_subdirectory(mpp) + +# ---------------------------------------------------------------------------- +# test / demo +# ---------------------------------------------------------------------------- +add_subdirectory(test) + +# ---------------------------------------------------------------------------- +# install headers +# ---------------------------------------------------------------------------- +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/inc/ + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rockchip" + FILES_MATCHING PATTERN "*.h" + ) + +# ---------------------------------------------------------------------------- +# pkgconfig +# ---------------------------------------------------------------------------- +CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/rockchip_mpp.pc.cmake" + "${CMAKE_BINARY_DIR}/rockchip_mpp.pc" @ONLY) +CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/rockchip_vpu.pc.cmake" + "${CMAKE_BINARY_DIR}/rockchip_vpu.pc" @ONLY) +install(FILES "${CMAKE_BINARY_DIR}/rockchip_mpp.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") +install(FILES "${CMAKE_BINARY_DIR}/rockchip_vpu.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") diff --git a/LICENSES/Apache-2.0 b/LICENSES/Apache-2.0 new file mode 100644 index 000000000..7cd903f57 --- /dev/null +++ b/LICENSES/Apache-2.0 @@ -0,0 +1,183 @@ +Valid-License-Identifier: Apache-2.0 +SPDX-URL: https://spdx.org/licenses/Apache-2.0.html +Usage-Guide: + To use the Apache License version 2.0 put the following SPDX tag/value + pair into a comment according to the placement guidelines in the + licensing rules documentation: + SPDX-License-Identifier: Apache-2.0 +License-Text: + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control with +that entity. For the purposes of this definition, "control" means (i) the +power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty +percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled +object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the +Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, as +a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or +merely link (or bind by name) to the interfaces of, the Work and Derivative +Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the +purposes of this definition, "submitted" means any form of electronic, +verbal, or written communication sent to the Licensor or its +representatives, including but not limited to communication on electronic +mailing lists, source code control systems, and issue tracking systems that +are managed by, or on behalf of, the Licensor for the purpose of discussing +and improving the Work, but excluding communication that is conspicuously +marked or otherwise designated in writing by the copyright owner as "Not a +Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on +behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly + perform, sublicense, and distribute the Work and such Derivative Works + in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as stated in + this section) patent license to make, have made, use, offer to sell, + sell, import, and otherwise transfer the Work, where such license + applies only to those patent claims licensable by such Contributor that + are necessarily infringed by their Contribution(s) alone or by + combination of their Contribution(s) with the Work to which such + Contribution(s) was submitted. If You institute patent litigation + against any entity (including a cross-claim or counterclaim in a + lawsuit) alleging that the Work or a Contribution incorporated within + the Work constitutes direct or contributory patent infringement, then + any patent licenses granted to You under this License for that Work + shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or + Derivative Works thereof in any medium, with or without modifications, + and in Source or Object form, provided that You meet the following + conditions: + + a. You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + b. You must cause any modified files to carry prominent notices stating + that You changed the files; and + + c. You must retain, in the Source form of any Derivative Works that You + distribute, all copyright, patent, trademark, and attribution notices + from the Source form of the Work, excluding those notices that do not + pertain to any part of the Derivative Works; and + + d. If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained within + such NOTICE file, excluding those notices that do not pertain to any + part of the Derivative Works, in at least one of the following + places: within a NOTICE text file distributed as part of the + Derivative Works; within the Source form or documentation, if + provided along with the Derivative Works; or, within a display + generated by the Derivative Works, if and wherever such third-party + notices normally appear. The contents of the NOTICE file are for + informational purposes only and do not modify the License. You may + add Your own attribution notices within Derivative Works that You + distribute, alongside or as an addendum to the NOTICE text from the + Work, provided that such additional attribution notices cannot be + construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated + in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to + the Licensor shall be under the terms and conditions of this License, + without any additional terms or conditions. Notwithstanding the above, + nothing herein shall supersede or modify the terms of any separate + license agreement you may have executed with Licensor regarding such + Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to + in writing, Licensor provides the Work (and each Contributor provides + its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY KIND, either express or implied, including, without limitation, + any warranties or conditions of TITLE, NON-INFRINGEMENT, + MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely + responsible for determining the appropriateness of using or + redistributing the Work and assume any risks associated with Your + exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether + in tort (including negligence), contract, or otherwise, unless required + by applicable law (such as deliberate and grossly negligent acts) or + agreed to in writing, shall any Contributor be liable to You for + damages, including any direct, indirect, special, incidental, or + consequential damages of any character arising as a result of this + License or out of the use or inability to use the Work (including but + not limited to damages for loss of goodwill, work stoppage, computer + failure or malfunction, or any and all other commercial damages or + losses), even if such Contributor has been advised of the possibility of + such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the + Work or Derivative Works thereof, You may choose to offer, and charge a + fee for, acceptance of support, warranty, indemnity, or other liability + obligations and/or rights consistent with this License. However, in + accepting such obligations, You may act only on Your own behalf and on + Your sole responsibility, not on behalf of any other Contributor, and + only if You agree to indemnify, defend, and hold each Contributor + harmless for any liability incurred by, or claims asserted against, such + Contributor by reason of your accepting any such warranty or additional + liability. + +END OF TERMS AND CONDITIONS diff --git a/LICENSES/MIT b/LICENSES/MIT new file mode 100644 index 000000000..f33a68ceb --- /dev/null +++ b/LICENSES/MIT @@ -0,0 +1,30 @@ +Valid-License-Identifier: MIT +SPDX-URL: https://spdx.org/licenses/MIT.html +Usage-Guide: + To use the MIT License put the following SPDX tag/value pair into a + comment according to the placement guidelines in the licensing rules + documentation: + SPDX-License-Identifier: MIT +License-Text: + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..3a623596d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,77 @@ +# Security Policy + +## Supported Versions + +The following versions of MPP are currently supported with security updates: + +| Version | Supported | +| :--------------------------- | :----------------------------- | +| develop branch (latest) | ✅ Fully supported | +| release branch (latest) | ✅ Fully supported | +| Older release branches | ⚠️ Critical security fixes only | +| Archived versions (< 1.0) | ❌ No longer supported | + +## Reporting a Vulnerability + +**Please do not** report security vulnerabilities through public GitHub issues, as this could expose the vulnerability to malicious actors. + +If you discover a security vulnerability in MPP, please report it privately using the following methods: + +### Reporting Channels + +1. **Primary Contact** (Recommended) + - Email the maintainer at: **herman.chen@rock-chips.com** + - Subject format: `[SECURITY] MPP vulnerability report - [brief description]` + +2. **Alternative Channel** + - If you cannot reach the primary maintainer, please email: rockchip-opensource@rock-chips.com + - Or submit a private ticket via [Rockchip Redmine](http://redmine.rockchip.com.cn) + +### Report Content + +Please include the following information to help us quickly locate and fix the issue: + +- **Vulnerability Description**: Type of vulnerability (e.g., buffer overflow, use-after-free, integer overflow) and scope of impact +- **Affected Versions**: Specific MPP version or Git commit hash +- **Affected Components**: Specific modules (e.g., codec/parser/HAL/OSAL/allocator, etc.) +- **Environment Details**: + - Rockchip SoC model (e.g., RK3588, RK3568, etc.) + - Operating system (Linux/Android version) + - Kernel version +- **Reproduction Steps**: Detailed steps to reproduce or PoC (Proof of Concept) code +- **Suggested Fix** (optional): If you have a proposed fix, please include it + +## Response Process + +Upon receiving a security report, the maintenance team will follow this process: + +| Timeframe | Action | +| :------------------ | :----------------------------------------------------------- | +| Within 48 hours | Acknowledge receipt and begin initial assessment | +| Within 7 days | Complete vulnerability verification and severity assessment, provide feedback | +| Within 30 days | Release security patch (critical vulnerabilities may be faster) | +| After patch release | Public disclosure of vulnerability details (coordinated disclosure) | + +## Disclosure Policy + +- **Coordinated Disclosure**: We follow coordinated disclosure principles. After the vulnerability is fixed, details will typically be publicly disclosed within 90 days, or adjusted according to the reporter's preferences +- **Acknowledgment**: Once the vulnerability is confirmed and fixed, we will credit the reporter in the release notes (unless you wish to remain anonymous) +- **CVE**: If a CVE identifier is needed, please let us know in advance and we will assist with the application + +## Security Best Practices + +When using MPP, the following security measures are recommended: + +1. **Input Validation**: Ensure media streams passed to MPP come from trusted sources, or perform strict validation before decoding +2. **Memory Limits**: Use `mpp_buffer_group_limit_config` to limit memory usage and prevent resource exhaustion attacks +3. **Sandboxing**: Run MPP-related processes in a privilege-restricted environment +4. **Timely Updates**: Keep MPP updated to the latest version to receive the latest security fixes +5. **Kernel Security**: Ensure the underlying kernel drivers (vcodec_service/v4l2) are updated to the latest version + +## Known Security Issues + +View [GitHub Security Advisories](https://github.com/HermanChen/mpp/security/advisories) for publicly disclosed security announcements. + +--- + +Thank you for contributing to MPP security! diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 000000000..93dee0077 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,2 @@ +!*.bash +!*.sh diff --git a/build/android/aarch64/make-Android.bash b/build/android/aarch64/make-Android.bash new file mode 100755 index 000000000..eb2bf0b26 --- /dev/null +++ b/build/android/aarch64/make-Android.bash @@ -0,0 +1,66 @@ +#!/bin/bash + +BUILD_TYPE="Release" +ANDROID_ABI="arm64-v8a" +ANDROID_STL="system" + +#Specify Android NDK path if needed +#ANDROID_NDK= + +#Specify cmake if needed +#CMAKE_PROGRAM= + +for ARG in "$@"; do + if [[ "$ARG" == "-c" ]]; then + clear + fi +done + +MPP_PWD=`pwd` + +source ../env_setup.sh + +${CMAKE_PROGRAM} -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ + -DCMAKE_MAKE_PROGRAM=${MAKE_PROGRAM} \ + -DANDROID_FORCE_ARM_BUILD=ON \ + -DANDROID_NDK=${ANDROID_NDK} \ + -DANDROID_SYSROOT=${PLATFORM} \ + -DANDROID_ABI=${ANDROID_ABI} \ + -DANDROID_TOOLCHAIN_NAME=${TOOLCHAIN_NAME} \ + -DANDROID_NATIVE_API_LEVEL=${NATIVE_API_LEVEL} \ + -DANDROID_STL=${ANDROID_STL} \ + -DMPP_PROJECT_NAME=mpp \ + -DVPU_PROJECT_NAME=vpu \ + -DHAVE_DRM=ON \ + ../../../ + +if [ "${CMAKE_PARALLEL_ENABLE}" = "0" ]; then + ${CMAKE_PROGRAM} --build . +else + ${CMAKE_PROGRAM} --build . -j +fi + +# ---------------------------------------------------------------------------- +# usefull cmake debug flag +# ---------------------------------------------------------------------------- + #-DMPP_NAME="rockchip_mpp" \ + #-DVPU_NAME="rockchip_vpu" \ + #-DHAVE_DRM \ + #-DCMAKE_BUILD_TYPE=Debug \ + #-DCMAKE_VERBOSE_MAKEFILE=true \ + #--trace \ + #--debug-output \ + +#cmake --build . --clean-first -- V=1 + +# ---------------------------------------------------------------------------- +# test script +# ---------------------------------------------------------------------------- +#adb push osal/test/rk_log_test /system/bin/ +#adb push osal/test/rk_thread_test /system/bin/ +#adb shell sync +#adb shell logcat -c +#adb shell rk_log_test +#adb shell rk_thread_test +#adb logcat -d|tail -30 diff --git a/build/android/aarch64/make-Android.bat b/build/android/aarch64/make-Android.bat new file mode 100644 index 000000000..3337b35e3 --- /dev/null +++ b/build/android/aarch64/make-Android.bat @@ -0,0 +1,102 @@ +@echo off +REM Windows build script for MPP Android ARM64 (arm64-v8a) + +setlocal + +set BUILD_TYPE=Release +set ANDROID_ABI=arm64-v8a +set ANDROID_STL=system + +REM Parse command line arguments by position +:parse_loop +if "%~1"=="--ndk" ( + set ANDROID_NDK=%~2 + shift + shift + goto parse_loop +) +if "%~1"=="--cmake" ( + set CMAKE_PROGRAM=%~2 + shift + shift + goto parse_loop +) +if "%~1"=="--debug" ( + set BUILD_TYPE=Debug + shift + goto parse_loop +) +if "%~1"=="-c" ( + cls + shift + goto parse_loop +) +if "%~1"=="--rebuild" ( + shift + goto parse_loop +) +if not "%~1"=="" ( + shift + goto parse_loop +) + +echo Configuration: +echo ANDROID_NDK=%ANDROID_NDK% +echo CMAKE_PROGRAM=%CMAKE_PROGRAM% +echo BUILD_TYPE=%BUILD_TYPE% +echo. + +REM Get current directory +set MPP_PWD=%cd% + +REM Call environment setup +call ..\env_setup.bat +if %errorlevel% neq 0 ( + echo [ERROR] Environment setup failed! + exit /b 1 +) + +REM Run CMake configuration +echo. +echo ======================================== +echo Running CMake configuration... +echo ======================================== +echo Build Type: %BUILD_TYPE% +echo Android ABI: %ANDROID_ABI% +echo Toolchain File: %TOOLCHAIN_FILE% +echo. + +echo Executing CMake command: +echo "%CMAKE_PROGRAM%" -G Ninja -DCMAKE_TOOLCHAIN_FILE="%TOOLCHAIN_FILE%" -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DANDROID_FORCE_ARM_BUILD=ON -DANDROID_NDK=%ANDROID_NDK% -DANDROID_ABI=%ANDROID_ABI% -DANDROID_NATIVE_API_LEVEL=%NATIVE_API_LEVEL% -DANDROID_STL=%ANDROID_STL% -DMPP_PROJECT_NAME=mpp -DVPU_PROJECT_NAME=vpu -DHAVE_DRM=ON ..\..\.. +echo. + +"%CMAKE_PROGRAM%" -G Ninja -DCMAKE_TOOLCHAIN_FILE="%TOOLCHAIN_FILE%" -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DANDROID_FORCE_ARM_BUILD=ON -DANDROID_NDK=%ANDROID_NDK% -DANDROID_ABI=%ANDROID_ABI% -DANDROID_NATIVE_API_LEVEL=%NATIVE_API_LEVEL% -DANDROID_STL=%ANDROID_STL% -DMPP_PROJECT_NAME=mpp -DVPU_PROJECT_NAME=vpu -DHAVE_DRM=ON ..\..\.. + +if %errorlevel% neq 0 ( + echo [ERROR] CMake configuration failed! + exit /b 1 +) + +REM Run build +echo. +echo ======================================== +echo Building MPP... +echo ======================================== + +if "%CMAKE_PARALLEL_ENABLE%"=="0" ( + "%CMAKE_PROGRAM%" --build . +) else ( + "%CMAKE_PROGRAM%" --build . -j +) + +if %errorlevel% neq 0 ( + echo [ERROR] Build failed! + exit /b 1 +) + +echo. +echo ======================================== +echo Build completed successfully! +echo ======================================== + +endlocal diff --git a/build/android/android.toolchain.cmake b/build/android/android.toolchain.cmake index 06004c207..e4da1b301 100644 --- a/build/android/android.toolchain.cmake +++ b/build/android/android.toolchain.cmake @@ -186,6 +186,9 @@ cmake_minimum_required( VERSION 2.6.3 ) +set(MPP_PROJECT_NAME mpp) +set(VPU_PROJECT_NAME vpu) + if( DEFINED CMAKE_CROSSCOMPILING ) # subsequent toolchain loading is not really needed return() @@ -1124,8 +1127,8 @@ if( APPLE ) endif() # Force set compilers because standard identification works badly for us -include( CMakeForceCompiler ) -CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +#include( CMakeForceCompiler ) +#CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) if( ANDROID_COMPILER_IS_CLANG ) set( CMAKE_C_COMPILER_ID Clang ) endif() @@ -1137,7 +1140,7 @@ else() endif() set( CMAKE_C_HAS_ISYSROOT 1 ) set( CMAKE_C_COMPILER_ABI ELF ) -CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +#CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) if( ANDROID_COMPILER_IS_CLANG ) set( CMAKE_CXX_COMPILER_ID Clang) endif() @@ -1260,6 +1263,9 @@ elseif( ARMEABI ) set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) endif() +# setup default C link flag +set( CMAKE_C_LINK_EXECUTABLE " -o " ) + if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) @@ -1299,7 +1305,6 @@ if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) endif() endif() -# ---------------------------------------------------------------------------- # add crt object to executable link list for Android SDK build # ---------------------------------------------------------------------------- set( ANDROID_CRT_BEGIN "${ANDROID_SYSROOT}/usr/lib/crtbegin_dynamic.o") @@ -1307,10 +1312,11 @@ set( ANDROID_CRT_END "${ANDROID_SYSROOT}/usr/lib/crtend_android.o") set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} ${ANDROID_CRT_BEGIN} ${ANDROID_CRT_END}" ) set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_CRT_BEGIN} ${ANDROID_CRT_END}" ) +# ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- # add libgcc.a to executable link list # ---------------------------------------------------------------------------- -set( ANDROID_LIB_GCC "${ANDROID_TOOLCHAIN_ROOT}/lib/gcc/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${ANDROID_COMPILER_VERSION}/${CMAKE_SYSTEM_PROCESSOR}/libgcc.a") +set( ANDROID_LIB_GCC "${ANDROID_TOOLCHAIN_ROOT}/lib/gcc/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${ANDROID_COMPILER_VERSION}/libgcc.a") set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} ${ANDROID_LIB_GCC}" ) set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIB_GCC}" ) @@ -1337,7 +1343,7 @@ set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) # linker flags -set( ANDROID_LINKER_FLAGS "" ) +set( ANDROID_LINKER_FLAGS "-Wl,--allow-multiple-definition" ) if( ARMEABI_V7A ) # this is *required* to use the following linker flags that routes around @@ -1394,7 +1400,11 @@ endif() # ---------------------------------------------------------------------------- # add linker definition for Android SDK build # ---------------------------------------------------------------------------- +if( X86_64 OR MIPS64 OR ARM64_V8A ) +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-dynamic-linker,/system/bin/linker64 " ) +else() set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-dynamic-linker,/system/bin/linker " ) +endif() if( ANDROID_COMPILER_IS_CLANG ) set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" ) @@ -1406,7 +1416,7 @@ endif() # ---------------------------------------------------------------------------- # add nostdlib for Android SDK build # ---------------------------------------------------------------------------- -set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -nostdlib" ) +set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostdlib -ldl -lc" ) # cache flags set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) diff --git a/build/android/arm/make-Android.bash b/build/android/arm/make-Android.bash new file mode 100755 index 000000000..343ad06c4 --- /dev/null +++ b/build/android/arm/make-Android.bash @@ -0,0 +1,65 @@ +#!/bin/bash + +BUILD_TYPE="Release" +ANDROID_ABI="armeabi-v7a with NEON" + +#Specify Android NDK path if needed +#ANDROID_NDK= + +#Specify cmake if needed +#CMAKE_PROGRAM= + +for ARG in "$@"; do + if [[ "$ARG" == "-c" ]]; then + clear + fi +done + +MPP_PWD=`pwd` + +source ../env_setup.sh + +${CMAKE_PROGRAM} -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ + -DCMAKE_MAKE_PROGRAM=${MAKE_PROGRAM} \ + -DANDROID_FORCE_ARM_BUILD=ON \ + -DANDROID_NDK=${ANDROID_NDK} \ + -DANDROID_SYSROOT=${PLATFORM} \ + -DANDROID_ABI=${ANDROID_ABI} \ + -DANDROID_TOOLCHAIN_NAME=${TOOLCHAIN_NAME} \ + -DANDROID_NATIVE_API_LEVEL=${NATIVE_API_LEVEL} \ + -DANDROID_STL=${ANDROID_STL} \ + -DMPP_PROJECT_NAME=mpp \ + -DVPU_PROJECT_NAME=vpu \ + -DHAVE_DRM=ON \ + ../../../ + +if [ "${CMAKE_PARALLEL_ENABLE}" = "0" ]; then + ${CMAKE_PROGRAM} --build . +else + ${CMAKE_PROGRAM} --build . -j +fi + +# ---------------------------------------------------------------------------- +# usefull cmake debug flag +# ---------------------------------------------------------------------------- + #-DMPP_NAME="rockchip_mpp" \ + #-DVPU_NAME="rockchip_vpu" \ + #-DHAVE_DRM \ + #-DCMAKE_BUILD_TYPE=Debug \ + #-DCMAKE_VERBOSE_MAKEFILE=true \ + #--trace \ + #--debug-output \ + +#cmake --build . --clean-first -- V=1 + +# ---------------------------------------------------------------------------- +# test script +# ---------------------------------------------------------------------------- +#adb push osal/test/rk_log_test /system/bin/ +#adb push osal/test/rk_thread_test /system/bin/ +#adb shell sync +#adb shell logcat -c +#adb shell rk_log_test +#adb shell rk_thread_test +#adb logcat -d|tail -30 diff --git a/build/android/arm/make-Android.bat b/build/android/arm/make-Android.bat new file mode 100644 index 000000000..a1495b756 --- /dev/null +++ b/build/android/arm/make-Android.bat @@ -0,0 +1,96 @@ +@echo off +REM Windows build script for MPP Android ARMv7 (armeabi-v7a with NEON) + +setlocal + +set BUILD_TYPE=Release +set ANDROID_ABI=armeabi-v7a with NEON + +REM Parse command line arguments by position +:parse_loop +if "%~1"=="--ndk" ( + set ANDROID_NDK=%~2 + shift + shift + goto parse_loop +) +if "%~1"=="--cmake" ( + set CMAKE_PROGRAM=%~2 + shift + shift + goto parse_loop +) +if "%~1"=="--debug" ( + set BUILD_TYPE=Debug + shift + goto parse_loop +) +if "%~1"=="-c" ( + cls + shift + goto parse_loop +) +if "%~1"=="--rebuild" ( + shift + goto parse_loop +) +if not "%~1"=="" ( + shift + goto parse_loop +) + +echo Configuration: +echo ANDROID_NDK=%ANDROID_NDK% +echo CMAKE_PROGRAM=%CMAKE_PROGRAM% +echo BUILD_TYPE=%BUILD_TYPE% +echo. + +REM Get current directory +set MPP_PWD=%cd% + +REM Call environment setup +call ..\env_setup.bat +if %errorlevel% neq 0 ( + echo [ERROR] Environment setup failed! + exit /b 1 +) + +REM Run CMake configuration +echo. +echo ======================================== +echo Running CMake configuration... +echo ======================================== +echo Build Type: %BUILD_TYPE% +echo Android ABI: %ANDROID_ABI% +echo. + +"%CMAKE_PROGRAM%" -G Ninja -DCMAKE_TOOLCHAIN_FILE="%TOOLCHAIN_FILE%" -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DANDROID_FORCE_ARM_BUILD=ON -DANDROID_NDK=%ANDROID_NDK% -DANDROID_ABI=%ANDROID_ABI% -DANDROID_NATIVE_API_LEVEL=%NATIVE_API_LEVEL% -DANDROID_STL=%ANDROID_STL% -DMPP_PROJECT_NAME=mpp -DVPU_PROJECT_NAME=vpu -DHAVE_DRM=ON ..\..\.. + +if %errorlevel% neq 0 ( + echo [ERROR] CMake configuration failed! + exit /b 1 +) + +REM Run build +echo. +echo ======================================== +echo Building MPP... +echo ======================================== + +if "%CMAKE_PARALLEL_ENABLE%"=="0" ( + "%CMAKE_PROGRAM%" --build . +) else ( + "%CMAKE_PROGRAM%" --build . -j +) + +if %errorlevel% neq 0 ( + echo [ERROR] Build failed! + exit /b 1 +) + +echo. +echo ======================================== +echo Build completed successfully! +echo ======================================== + +endlocal diff --git a/build/android/env_setup.bat b/build/android/env_setup.bat new file mode 100644 index 000000000..e8449b395 --- /dev/null +++ b/build/android/env_setup.bat @@ -0,0 +1,214 @@ +@echo off +REM Windows environment setup for Android MPP build +REM This script reads configuration from environment variables + +setlocal enabledelayedexpansion + +echo ======================================== +echo Environment Setup Script +echo ======================================== + +REM Default build type +if not defined BUILD_TYPE set BUILD_TYPE=Release + +REM Detect cmake +echo Checking cmake... +if not defined CMAKE_PROGRAM ( + where cmake >nul 2>&1 + if %errorlevel% equ 0 ( + set CMAKE_PROGRAM=cmake + echo Found cmake in PATH + ) else ( + REM Search in Android SDK cmake directory + echo Searching cmake in Android SDK... + + REM Extract SDK root from ANDROID_NDK if possible + set SDK_ROOT= + if defined ANDROID_NDK ( + for %%A in ("%ANDROID_NDK%") do set SDK_ROOT=%%~dpA + if "!SDK_ROOT:~-1!"=="\" set SDK_ROOT=!SDK_ROOT:~0,-1! + + echo SDK root candidate: !SDK_ROOT! + ) + + REM Look for cmake in SDK + set CMAKE_PROGRAM= + if defined SDK_ROOT ( + if exist "!SDK_ROOT!\cmake" ( + for /d %%D in ("!SDK_ROOT!\cmake\*") do ( + if not defined CMAKE_PROGRAM ( + if exist "%%D\bin\cmake.exe" ( + set CMAKE_PROGRAM=%%D\bin\cmake.exe + echo Found cmake at !CMAKE_PROGRAM! + ) + ) + ) + ) + ) + + REM Common cmake paths in Android SDK + if not defined CMAKE_PROGRAM ( + for %%P in (D:\android-sdk-windows\cmake C:\android-sdk\cmake %LOCALAPPDATA%\Android\Sdk\cmake) do ( + if not defined CMAKE_PROGRAM ( + if exist "%%P" ( + for /d %%D in ("%%P\*") do ( + if not defined CMAKE_PROGRAM ( + if exist "%%D\bin\cmake.exe" ( + set CMAKE_PROGRAM=%%D\bin\cmake.exe + echo Found cmake at !CMAKE_PROGRAM! + ) + ) + ) + ) + ) + ) + ) + + if not defined CMAKE_PROGRAM ( + echo [ERROR] cmake not found in PATH or Android SDK! + echo Please set CMAKE_PROGRAM environment variable, e.g.: + echo set CMAKE_PROGRAM=D:\android-sdk-windows\cmake\3.22.1\bin\cmake.exe + echo Or add cmake to PATH + echo Or install cmake from: https://cmake.org/download/ + exit /b 1 + ) + ) +) + +REM Verify cmake exists +echo Verifying cmake at: %CMAKE_PROGRAM% +if not exist "%CMAKE_PROGRAM%" ( + echo [ERROR] cmake not found at %CMAKE_PROGRAM% + exit /b 1 +) + +echo Getting cmake version... +set CMAKE_VERSION= +"%CMAKE_PROGRAM%" --version > "%TEMP%\cmake_version.tmp" 2>&1 +for /f "tokens=3" %%i in ('type "%TEMP%\cmake_version.tmp" ^| findstr /i "version"') do set CMAKE_VERSION=%%i +del "%TEMP%\cmake_version.tmp" >nul 2>&1 + +if not defined CMAKE_VERSION ( + echo [ERROR] Failed to get cmake version from %CMAKE_PROGRAM% + exit /b 1 +) + +echo Found cmake version: %CMAKE_VERSION% + +REM Parse cmake version +for /f "tokens=1,2 delims=." %%a in ("%CMAKE_VERSION%") do ( + set CMAKE_MAJOR_VERSION=%%a + set CMAKE_MINOR_VERSION=%%b +) + +echo CMake major version: %CMAKE_MAJOR_VERSION%, minor version: %CMAKE_MINOR_VERSION% + +set CMAKE_PARALLEL_ENABLE=0 +if defined CMAKE_MAJOR_VERSION ( + if %CMAKE_MAJOR_VERSION% geq 3 ( + if defined CMAKE_MINOR_VERSION ( + if %CMAKE_MINOR_VERSION% geq 12 ( + set CMAKE_PARALLEL_ENABLE=1 + echo use cmake parallel build. + ) + ) + ) +) + +REM Detect NDK path +echo Checking NDK... +if not defined ANDROID_NDK ( + echo [ERROR] ANDROID_NDK environment variable not set! + echo Please set ANDROID_NDK environment variable, e.g.: + echo set ANDROID_NDK=D:\android-sdk-windows\ndk\26.3.11579264 + exit /b 1 +) + +REM Remove quotes from ANDROID_NDK if present +set ANDROID_NDK=!ANDROID_NDK:"=! + +if not exist "%ANDROID_NDK%" ( + echo [ERROR] Specified NDK path does not exist: %ANDROID_NDK% + exit /b 1 +) + +echo Using NDK: %ANDROID_NDK% + +REM Detect NDK version +echo Detecting NDK version... +set NDK_VERSION=0 +set SOURCE_PROPS=%ANDROID_NDK%\source.properties +if exist "%SOURCE_PROPS%" ( + echo Found source.properties + REM NDK version is greater than 10 + REM Format: Pkg.Revision = 26.3.11579264 + for /f "tokens=1,2,3" %%a in ('type "%SOURCE_PROPS%" 2^>nul ^| findstr /C:"Pkg.Revision"') do ( + set NDK_VERSION_RAW=%%c + ) + if defined NDK_VERSION_RAW ( + for /f "tokens=1 delims=." %%a in ("%NDK_VERSION_RAW%") do set NDK_VERSION=%%a + echo Detected NDK version: %NDK_VERSION% + ) +) else if exist "%ANDROID_NDK%\RELEASE.TXT" ( + echo Found RELEASE.TXT + REM NDK version is less than 11 + for /f "tokens=1" %%a in ('type "%ANDROID_NDK%\RELEASE.TXT" 2^>nul ^| findstr /R "^r[0-9]"') do set NDK_LINE=%%a + set NDK_VERSION=%NDK_LINE:~1% + set NDK_VERSION=%NDK_VERSION:a=% + set NDK_VERSION=%NDK_VERSION:b=% + set NDK_VERSION=%NDK_VERSION:c=% + set NDK_VERSION=%NDK_VERSION:d=% + set NDK_VERSION=%NDK_VERSION:e=% + set NDK_VERSION=%NDK_VERSION:f=% +) + +REM Check if NDK_VERSION is a valid number +if "%NDK_VERSION%"=="0" ( + set NDK_VERSION=26 + echo [WARNING] Could not detect NDK version, assuming 26+ +) + +echo NDK version: %NDK_VERSION% + +REM Configure NDK settings based on version +if %NDK_VERSION% geq 16 ( + set TOOLCHAIN_FILE=%ANDROID_NDK%\build\cmake\android.toolchain.cmake + set NATIVE_API_LEVEL=android-27 + set ANDROID_STL=c++_static + set TOOLCHAIN_NAME= + set PLATFORM= +) else if %NDK_VERSION% gtr 12 ( + set TOOLCHAIN_FILE=%ANDROID_NDK%\build\cmake\android.toolchain.cmake + set NATIVE_API_LEVEL=android-21 + set ANDROID_STL=system + set TOOLCHAIN_NAME= + set PLATFORM= +) else ( + set TOOLCHAIN_FILE=..\..\android.toolchain.cmake + set NATIVE_API_LEVEL=android-21 + set ANDROID_STL=system +) + +echo Configuration: +echo NDK path: %ANDROID_NDK% +echo Toolchain file: %TOOLCHAIN_FILE% +echo API level: %NATIVE_API_LEVEL% +echo STL: %ANDROID_STL% +echo. + +endlocal & ( + set ANDROID_NDK=%ANDROID_NDK% + set TOOLCHAIN_FILE=%TOOLCHAIN_FILE% + set TOOLCHAIN_NAME=%TOOLCHAIN_NAME% + set PLATFORM=%PLATFORM% + set NATIVE_API_LEVEL=%NATIVE_API_LEVEL% + set ANDROID_STL=%ANDROID_STL% + set CMAKE_PROGRAM=%CMAKE_PROGRAM% + set BUILD_TYPE=%BUILD_TYPE% + set CMAKE_PARALLEL_ENABLE=%CMAKE_PARALLEL_ENABLE% +) + +echo Environment setup completed successfully! +echo. + +exit /b 0 diff --git a/build/android/env_setup.sh b/build/android/env_setup.sh new file mode 100755 index 000000000..0028c79b0 --- /dev/null +++ b/build/android/env_setup.sh @@ -0,0 +1,274 @@ +#!/bin/bash + +# Run this from within a bash shell +MAKE_PROGRAM=`which make` + +# delete list +FILES_TO_DELETE=( + "CMakeCache.txt" + "Makefile" + "cmake_install.cmake" + "compile_commands.json" + "rockchip_mpp.pc" + "rockchip_vpu.pc" +) + +DIRS_TO_DELETE=( + "CMakeFiles" + "mpp" + "osal" + "test" + "utils" +) + +################################################# +# Arguments +################################################# +while [ $# -gt 0 ]; do + case $1 in + --help | -h) + echo "Execute make-Android.sh in *arm/* or *aarch64/* with some args." + echo " use --ndk to set ANDROID_NDK" + echo " use --cmake to specify which cmake to use" + echo " use --debug to enable debug build" + echo " use --rebuild to rebuild after clean" + echo " use --clean to clean all build file" + exit 1 + ;; + --debug) + BUILD_TYPE="Debug" + ;; + -B) + if [ -f "CMakeCache.txt" ]; then + rm CMakeCache.txt + fi + ;; + --ndk) + ANDROID_NDK=$2 + shift + ;; + --cmake) + CMAKE_PROGRAM=$2 + shift + ;; + --rebuild) + ${MAKE_PROGRAM} clean + if [ -f "CMakeCache.txt" ]; then + rm CMakeCache.txt + fi + shift + ;; + --clean) + for FILE_TO_DELETE in "${FILES_TO_DELETE[@]}"; do + if [ -f ${FILE_TO_DELETE} ]; then + rm ${FILE_TO_DELETE} + fi + done + for DIR_TO_DELETE in "${DIRS_TO_DELETE[@]}"; do + if [ -d ${DIR_TO_DELETE} ]; then + rm -rf ${DIR_TO_DELETE} + fi + done + exit 1 + ;; + esac + shift +done + +CMAKE_PARALLEL_ENABLE=0 + +################################################# +# Detect cmake version +################################################# +if [ -z $CMAKE_PROGRAM ]; then + CMAKE_PROGRAM=`which cmake` +fi + +CMAKE_VERSION=$(${CMAKE_PROGRAM} --version | grep "version" | cut -d " " -f 3) +CMAKE_MAJOR_VERSION=`echo ${CMAKE_VERSION} | cut -d "." -f 1` +CMAKE_MINOR_VERSION=`echo ${CMAKE_VERSION} | cut -d "." -f 2` + +if [ -z ${CMAKE_VERSION} ]; then + echo -e "\e[1;31m cmake in ${CMAKE_PROGRAM} is invalid, please check!\e[0m" + exit 1 +else + echo "Found cmake in ${CMAKE_PROGRAM}, version: ${CMAKE_VERSION}" +fi + +if [ ${CMAKE_MAJOR_VERSION} -ge 3 ] && [ ${CMAKE_MINOR_VERSION} -ge 12 ]; then + CMAKE_PARALLEL_ENABLE=1 + echo "use cmake parallel build." +fi + +################################################# +# Detect ndk path and version +################################################# + +NDK_SEARCH_PATH=( + /home/pub/ndk/ + ~/work/android/ndk/ +) + +FOUND_NDK=0 + +if [ -z "$ANDROID_NDK" ]; then + # try find ndk path in CMakeCache.txt + if [ -f "CMakeCache.txt" ]; then + ANDROID_NDK=`grep ANDROID_NDK\: CMakeCache.txt | awk -F '=' '{ print $2 }'` + + if [ -d "${ANDROID_NDK}" ]; then + echo "use android ndk from CMakeCache.txt : ${ANDROID_NDK}" + FOUND_NDK=1 + fi + fi +else + FOUND_NDK=1 +fi + +################################################# +# search possible path to get ndk with higher version +################################################# +NDK_OPTION="" +NDK_COUNT=0 + +if [ "${FOUND_NDK}" = "0" ]; then + echo "trying to find android ndk in the following paths:" + for NDK_BASE in ${NDK_SEARCH_PATH[@]}; + do + echo "${NDK_BASE}" + done + + echo "find valid android ndk:" + + for NDK_BASE in ${NDK_SEARCH_PATH[@]}; + do + if [ -d ${NDK_BASE} ]; then + NDKS=`ls -r -d ${NDK_BASE}android-ndk-r*/` + + for NDK_PATH in ${NDKS[@]}; + do + if [ -d ${NDK_PATH} ]; then + NDK_COUNT=$[${NDK_COUNT}+1] + NDK_OPT="${NDK_COUNT} - ${NDK_PATH}" + + echo ${NDK_OPT} + + NDK_OPTION+="${NDK_PATH} " + fi + done + fi + done +fi + +case ${NDK_COUNT} in + 0) + ;; + 1) + ANDROID_NDK=${NDK_PATH[0]} + FOUND_NDK=1 + + echo "use ndk: ${ANDROID_NDK}" + ;; + *) + read -p "select [1-${NDK_COUNT}] ndk used for compiling, def[1]: " -ra NDK_INTPUT + NDK_INTPUT=${NDK_INTPUT:-1} + + NDK_INDEX=0 + + for NDK_PATH in ${NDK_OPTION[@]}; + do + NDK_INDEX=$[${NDK_INDEX}+1] + + if [ "${NDK_INDEX}" == "${NDK_INTPUT}" ]; then + echo "${NDK_INTPUT} - ${NDK_PATH} selected as ANDROID_NDK" + ANDROID_NDK=${NDK_PATH} + FOUND_NDK=1 + break + fi + done + + if [ $FOUND_NDK -eq 0 ]; then + echo "invalid input option ${NDK_INTPUT}" + fi +esac + +if [ $FOUND_NDK -eq 0 ]; then + echo "can not found any valid android ndk" + exit 1 +fi + +################################################# +# try to detect NDK version +# for ndk > 10, ndk version is presented at $ANDROID_NDK/source.properties +# for ndk <=10, ndk version is presented at $ANDROID_NDK/RELEASE.TXT +# parameter: ndk path +# return: ndk version, 0 if not found +################################################# +detect_ndk_version() +{ + RET=0 + + if [ -f "$1/source.properties" ]; then + # NDK version is greater than 10 + RET=$(grep -o '^Pkg.Revision.*[0-9]*.*' $ANDROID_NDK/source.properties |cut -d " " -f 3 | cut -d "." -f 1) + elif [ -f "$1/RELEASE.TXT" ]; then + # NDK version is less than 11 + RET=$(grep -o '^r[0-9]*.*' $ANDROID_NDK/RELEASE.TXT | cut -d " " -f 1 | cut -b2- | sed 's/[a-z]//g') + else + # A correct NDK directory must be pointed + RET=0 + fi + + echo $RET +} + +NDK_VERSION=$(detect_ndk_version ${ANDROID_NDK}) + +echo "NDK: ${ANDROID_NDK} version: ${NDK_VERSION}" + +if [ $NDK_VERSION -eq 0 ]; then + echo "NDK version isn't detected, please check $ANDROID_NDK" + FOUND_NDK=0 +else + FOUND_NDK=1 + + if [ $NDK_VERSION -ge 16 ]; then + TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake + NATIVE_API_LEVEL="android-27" + elif [ $NDK_VERSION -gt 12 ]; then + TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake + NATIVE_API_LEVEL="android-21" + elif [ $NDK_VERSION -le 12 ]; then + TOOLCHAIN_FILE=../android.toolchain.cmake + NATIVE_API_LEVEL="android-21" + fi + + if [ $NDK_VERSION -lt 18 ]; then + ################################################# + # Set platform tools + ################################################# + if [ "${ANDROID_ABI}" = "armeabi-v7a" ] || [ "${ANDROID_ABI}" = "armeabi-v7a with NEON" ]; then + TOOLCHAIN_NAME="arm-linux-androideabi-4.9" + PLATFORM=$ANDROID_NDK/platforms/${NATIVE_API_LEVEL}/arch-arm + elif [ "${ANDROID_ABI}" = "arm64-v8a" ]; then + TOOLCHAIN_NAME="aarch64-linux-android-4.9" + PLATFORM=$ANDROID_NDK/platforms/${NATIVE_API_LEVEL}/arch-arm64 + fi + ANDROID_STL="system" + else + # From NDK 18, GCC is deprecated + TOOLCHAIN_NAME="" + PLATFORM="" + ANDROID_STL="c++_static" + fi +fi + +if [ "${FOUND_NDK}" = "0" ]; then + echo -e "\e[1;31m No ndk path found. You should add your ndk path\e[0m" + exit 1 +else + echo "ndk path: $ANDROID_NDK" + echo "toolchain file: $TOOLCHAIN_FILE" + echo "toolchain name: $TOOLCHAIN_NAME" + echo "api level: $NATIVE_API_LEVEL" +fi diff --git a/build/android/ndk_links.md b/build/android/ndk_links.md index 6d93d61d2..c9ebfd58e 100644 --- a/build/android/ndk_links.md +++ b/build/android/ndk_links.md @@ -1,199 +1,197 @@ +============== r25c ============== -============== r1 ============== (dead links) +* ndk_r25c -* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip -* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip -* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip +https://dl.google.com/android/repository/android-ndk-r25c-windows.zip +https://dl.google.com/android/repository/android-ndk-r25c-darwin.dmg +https://dl.google.com/android/repository/android-ndk-r25c-linux.zip -============== r2 ============== +============== r24 ============== -* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip -* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip -* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip +* ndk_r24 -============== r3 ============== +https://dl.google.com/android/repository/android-ndk-r24-darwin.dmg +https://dl.google.com/android/repository/android-ndk-r24-linux.zip +https://dl.google.com/android/repository/android-ndk-r24-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip +============== r23c ============== -============== r4 ============== +* ndk_r23c -* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip +https://dl.google.com/android/repository/android-ndk-r23c-windows.zip +https://dl.google.com/android/repository/android-ndk-r23c-darwin.dmg +https://dl.google.com/android/repository/android-ndk-r23c-linux.zip -============== r4b ============== +============== r22b ============== -* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip +* ndk_r22b -============== r5 ============== +https://dl.google.com/android/repository/android-ndk-r22-darwin-x86_64.dmg +https://dl.google.com/android/repository/android-ndk-r22b-darwin-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r22b-linux-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r22b-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2 +============== r21e ============== -============== r5b ============== +* ndk_r21e -* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2 +https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r21-darwin-x86_64.dmg +https://dl.google.com/android/repository/android-ndk-r21e-darwin-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r21e-windows-x86_64.zip -============== r5c ============== +============== r20b ============== -* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2 +* ndk_r20b -============== r6 ============== +https://dl.google.com/android/repository/android-ndk-r20b-windows-x86.zip +https://dl.google.com/android/repository/android-ndk-r20b-windows-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r20b-darwin-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 +============== r19c ============== -============== r6b ============== +* ndk_r19c -* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2 +https://dl.google.com/android/repository/android-ndk-r19c-windows-x86.zip +https://dl.google.com/android/repository/android-ndk-r19c-windows-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r19c-darwin-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r19c-linux-x86_64.zip -============== r7 ============== +============== r18b ============== -* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2 +* ndk_r18b -============== r7b ============== +https://dl.google.com/android/repository/android-ndk-r18b-windows-x86.zip +https://dl.google.com/android/repository/android-ndk-r18b-windows-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r18b-darwin-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r18b-linux-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2 +============== r17c ============== -============== r7c ============== +* ndk_r17c -* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2 +https://dl.google.com/android/repository/android-ndk-r17c-windows-x86.zip +https://dl.google.com/android/repository/android-ndk-r17c-windows-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r17c-darwin-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip -============== r8 ============== +============== r16b ============== -* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2 +* ndk_r16b -============== r8b ============== +https://dl.google.com/android/repository/android-ndk-r16b-windows-x86.zip +https://dl.google.com/android/repository/android-ndk-r16b-windows-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r16b-darwin-x86_64.zip +https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2 +============== r15c ============== -============== r8c ============== +* ndk_r15c (July 2017) -* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2 +* https://dl.google.com/android/repository/android-ndk-r15c-windows-x86.zip +* https://dl.google.com/android/repository/android-ndk-r15c-windows-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r15c-darwin-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip -============== r8d ============== +============== r15b ============== -* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip -* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2 +* ndk_r15b (June 2017) -============== r8e ============== +* https://dl.google.com/android/repository/android-ndk-r15c-windows-x86.zip +* https://dl.google.com/android/repository/android-ndk-r15c-windows-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r15c-darwin-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2 +============== r14b ============== -============== r9 ============== +* ndk_r14b (Dec 2016) -* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip -* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip -* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2 +* https://dl.google.com/android/repository/android-ndk-r14b-windows-x86.zip +* https://dl.google.com/android/repository/android-ndk-r14b-windows-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r14b-darwin-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip -============== r9b ============== +============== r13b ============== -* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip -* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip -* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2 +* ndk_r13b (Oct 2016) -============== r9c ============== +* https://dl.google.com/android/repository/android-ndk-r13b-windows-x86.zip +* https://dl.google.com/android/repository/android-ndk-r13b-windows-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r13b-darwin-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r13b-linux-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip +============== r13 ============== -============== r9d ============== +* ndk_r13 (Sept 2016) -* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip +* https://dl.google.com/android/repository/android-ndk-r13-windows-x86.zip +* https://dl.google.com/android/repository/android-ndk-r13-windows-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r13-darwin-x86_64.zip +* https://dl.google.com/android/repository/android-ndk-r13-linux-x86_64.zip -============== r10 ============== +============== r12 ============== -* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip +* ndk_r12 (June 2016) -============== r10b ============== +* http://dl.google.com/android/repository/android-ndk-r12b-windows-x86.zip +* http://dl.google.com/android/repository/android-ndk-r12b-windows-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r12b-darwin-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r12b-linux-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip -* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip -* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2 -* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip +============== r11c ============== + +* ndk_r11c (March 2016) + +* http://dl.google.com/android/repository/android-ndk-r11c-windows-x86.zip +* http://dl.google.com/android/repository/android-ndk-r11c-windows-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r11c-darwin-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r11c-linux-x86_64.zip + +============== r11b ============== + +* ndk_r11b (March 2016) + +* http://dl.google.com/android/repository/android-ndk-r11b-windows-x86.zip +* http://dl.google.com/android/repository/android-ndk-r11b-windows-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r11b-darwin-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r11b-linux-x86_64.zip + +============== r11 ============== + +* ndk_r11 (March 2016) + +* http://dl.google.com/android/repository/android-ndk-r11-windows-x86.zip +* http://dl.google.com/android/repository/android-ndk-r11-windows-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r11-darwin-x86_64.zip +* http://dl.google.com/android/repository/android-ndk-r11-linux-x86_64.zip + +============== r10e ============== + +* ndk_r10e(Jan 2015) + +* http://dl.google.com/android/ndk/android-ndk-r10e-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10e-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10e-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10e-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin + +============== r10d ============== + +* ndk_r10d(December 2014) + +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin ============== r10c ============== +* ndk_r10c(October2014) + * http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe * http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe * http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin @@ -201,11 +199,205 @@ * http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin * http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin -============== r10d ============== +============== r10b ============== + +* ndk_r10b(September2014) + +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2 + +============== r10 ============== + +* ndk_r10(July2014) + +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2 + +============== r9d ============== + +* ndk_r9d(March2014) + +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2 + +============== r9c ============== + +* ndk_r9c(December2013) + +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2 + +============== r9b ============== + +* ndk_r9b(October 2013) + +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2 + +============== r9 ============== + +* ndk_r9(July 2013) + +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 + +============== r8e ============== + +* ndk_r8e(March 2013) + +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2 + +Note : + +NDKr8e is the first NDK with 32bit and 64bit releases. The prior ones were +all32bit and didn't have any suffix, so r8b would be: + +============== r8d ============== + +* ndk_r8d(December 2012) + +* https://dl.google.com/android/ndk/android-ndk-r8d-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2 + +============== r8c ============== + +* ndk_r8C(November 2012) + +* https://dl.google.com/android/ndk/android-ndk-r8C-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8C-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8C-linux-x86.tar.bz2 + +============== r8b ============== + +* ndk_r8b(July 2012) + +* https://dl.google.com/android/ndk/android-ndk-r8b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2 + +============== r8 ============== + +* ndk_r8(May 2012) + +* https://dl.google.com/android/ndk/android-ndk-r8-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2 + +============== r7c ============== + +* ndk_r7c(April 2012) + +* https://dl.google.com/android/ndk/android-ndk-r7c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2 + +============== r7b ============== + +* ndk_r7b(February 2012) + +* https://dl.google.com/android/ndk/android-ndk-r7b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2 + +============== r7 ============== + +* ndk_r7(November 2011) + +* https://dl.google.com/android/ndk/android-ndk-r7-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2 + +============== r6b ============== + +* ndk_r6b(August 2011) + +* https://dl.google.com/android/ndk/android-ndk-r6b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2 + +============== r6 ============== + +* ndk_r6(July 2011) + +* https://dl.google.com/android/ndk/android-ndk-r6-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 + +============== r5c ============== + +* ndk_r5c(June 2011) + +* https://dl.google.com/android/ndk/android-ndk-r5c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2 + +============== r5b ============== + +* ndk_r5b(January 2011) + +* https://dl.google.com/android/ndk/android-ndk-r5b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2 + +============== r5 ============== + +* ndk_r5(December 2010) + +* https://dl.google.com/android/ndk/android-ndk-r5-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2 + +============== r4b ============== + +* ndk_r4b(June 2010) + +* https://dl.google.com/android/ndk/android-ndk-r4b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip + +============== r4 ============== + +* ndk_r4(may 2010) + +* https://dl.google.com/android/ndk/android-ndk-r4-windows.zip +* 32-bit : http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip + +============== r3 ============== + +* ndk_r3(March 2010) + +* https://dl.google.com/android/ndk/android-ndk-r3-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip -* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe -* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe -* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin -* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin -* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin -* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin diff --git a/build/android/update.bat b/build/android/update.bat new file mode 100644 index 000000000..9cbc99540 --- /dev/null +++ b/build/android/update.bat @@ -0,0 +1,59 @@ +@echo off +REM Windows script to push compiled MPP files to Android device + +set BASE_PATH=/vendor +REM Other options: +REM set BASE_PATH=/system +REM set BASE_PATH=/oem/usr + +set BIN_PATH=%BASE_PATH%/bin/ +set LIB_PATH=%BASE_PATH%/lib/ + +echo. +echo ======================================== +echo Pushing MPP files to Android device... +echo ======================================== +echo. + +REM Check if adb is available +where adb >nul 2>&1 +if %errorlevel% neq 0 ( + echo [ERROR] adb not found in PATH! + echo Please install Android SDK Platform-tools. + exit /b 1 +) + +REM Restart adbd with root permissions +echo Getting root permissions... +adb root +adb remount + +REM Function to push file if exists +:push_file +if exist "%~1" ( + echo Pushing %~1 to %~2 + adb push "%~1" %~2 +) else ( + echo [WARNING] File not found: %~1 + exit /b 0 +) + +REM Push library files +echo. +echo Pushing libraries... +call :push_file ".\mpp\libmpp.so" %LIB_PATH% +call :push_file ".\mpp\legacy\libvpu.so" %LIB_PATH% + +REM Push test executables +echo. +echo Pushing test executables... +call :push_file ".\test\mpi_dec_test" %BIN_PATH% +call :push_file ".\test\mpi_enc_test" %BIN_PATH% +call :push_file ".\test\vpu_api_test" %BIN_PATH% +call :push_file ".\test\mpp_info_test" %BIN_PATH% + +echo. +echo ======================================== +echo Push completed! +echo ======================================== +echo. diff --git a/build/android/update.sh b/build/android/update.sh new file mode 100644 index 000000000..7cb1b2006 --- /dev/null +++ b/build/android/update.sh @@ -0,0 +1,23 @@ +#!/bin/bash +adb root +adb remount + +#BASE_PATH=/system +BASE_PATH=/vendor +#BASE_PATH=/oem/usr + +BIN_PATH=${BASE_PATH}/bin/ +LIB_PATH=${BASE_PATH}/lib/ + +push_file() { + if [ -f $1 ]; then + adb push $1 $2 + fi +} + +push_file ./mpp/libmpp.so ${LIB_PATH} +push_file ./mpp/legacy/libvpu.so ${LIB_PATH} +push_file ./test/mpi_dec_test ${BIN_PATH} +push_file ./test/mpi_enc_test ${BIN_PATH} +push_file ./test/vpu_api_test ${BIN_PATH} +push_file ./test/mpp_info_test ${BIN_PATH} diff --git a/build/android/make-Android.bash b/build/android/x86/make-Android.bash similarity index 65% rename from build/android/make-Android.bash rename to build/android/x86/make-Android.bash index b9a2c5cbe..79ca63cfc 100755 --- a/build/android/make-Android.bash +++ b/build/android/x86/make-Android.bash @@ -1,16 +1,25 @@ #!/bin/bash # Run this from within a bash shell -ANDROID_NDK=~/work/android/ndk/android-ndk-r10d/ -PLATFORM=$ANDROID_NDK/platforms/android-17/arch-arm - -cmake -DCMAKE_TOOLCHAIN_FILE=./android.toolchain.cmake \ +HOST_IP=`hostname --all-ip-addresses` +if [ ${HOST_IP} == "10.10.10.65" ] || [ ${HOST_IP} == "10.10.10.67" ]; then + ANDROID_NDK=/home/pub/ndk/android-ndk-r10d/ +else + ANDROID_NDK=~/work/android/ndk/android-ndk-r10d/ +fi + +PLATFORM=$ANDROID_NDK/platforms/android-21/arch-x86 + +cmake -DCMAKE_TOOLCHAIN_FILE=../android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DANDROID_FORCE_ARM_BUILD=ON \ -DANDROID_NDK=${ANDROID_NDK} \ -DANDROID_SYSROOT=${PLATFORM} \ - -DANDROID_ABI="armeabi-v7a with NEON" \ - -DANDROID_TOOLCHAIN_NAME="arm-linux-androideabi-4.8" \ + -DANDROID_ABI="x86" \ + -DANDROID_TOOLCHAIN_NAME="x86-4.8" \ -DANDROID_NATIVE_API_LEVEL=android-21 \ -DANDROID_STL=system \ - ../../ + -DRKPLATFORM=ON \ + ../../../ # ---------------------------------------------------------------------------- # usefull cmake debug flag @@ -35,6 +44,3 @@ cmake --build . #adb logcat -d|tail -30 - - - diff --git a/build/cmake/merge_objects.cmake b/build/cmake/merge_objects.cmake new file mode 100644 index 000000000..28f165e51 --- /dev/null +++ b/build/cmake/merge_objects.cmake @@ -0,0 +1,56 @@ +# merge_objects.cmake +# Usage: +# merge_objects( [ ...]) +# Merge multiple OBJECT libraries → single large .o → immediately wrap into new OBJECT library (IMPORTED) +function(merge_objects out_obj) + # 1. Sanity-check: make sure the caller actually gave us a non-empty output name + if(out_obj STREQUAL "") + return() + endif() + + # 2. Collect all $ and validate + set(obj_inputs) + set(deps) + foreach(lib IN LISTS ARGN) + # Skip if target doesn't exist + if(NOT TARGET "${lib}") + message("merge_objects: '${lib}' is not a target") + continue() + endif() + + get_target_property(_type "${lib}" TYPE) + if(NOT _type STREQUAL "OBJECT_LIBRARY") + message(FATAL_ERROR "merge_objects: '${lib}' is not an OBJECT library") + endif() + list(APPEND obj_inputs "$") + list(APPEND deps "${lib}") + endforeach() + + # If no valid targets to merge, skip merge + if(NOT obj_inputs) + message(STATUS "merge_objects: no valid targets to merge for '${out_obj}', skipping") + return() + endif() + + set(merged_o "${CMAKE_CURRENT_BINARY_DIR}/${out_obj}.o") + set(rsp_file "${CMAKE_CURRENT_BINARY_DIR}/${out_obj}.rsp") + + # 3. Generate response file (one .o per line) + file(GENERATE OUTPUT "${rsp_file}" CONTENT "$") + + # 4. Merge command + add_custom_target( + ${out_obj}_t + COMMAND ${CMAKE_LINKER} -r -o "${merged_o}" "@${rsp_file}" + DEPENDS ${deps} "${rsp_file}" + BYPRODUCTS "${merged_o}" + COMMENT "Merging OBJECT libs into ${out_obj}.o" + ) + + # 5. Immediately wrap into **IMPORTED OBJECT library** + add_library("${out_obj}" OBJECT IMPORTED) + set_target_properties("${out_obj}" PROPERTIES + IMPORTED_OBJECTS "${merged_o}") + # Dependency chain: users must wait for large .o generation when linking + add_dependencies("${out_obj}" ${out_obj}_t) +endfunction() \ No newline at end of file diff --git a/build/cmake/svn_info.in b/build/cmake/svn_info.in deleted file mode 100644 index 1d3137e3f..000000000 --- a/build/cmake/svn_info.in +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VERSION_H__ -#define __VERSION_H__ - -#define SVN_VERSION "@VERSION_REVISION@" -#define SVN_AUTHOR "@VERSION_LAST_AUTHOR@" -#define SVN_DATE "@VERSION_LAST_DATA@" -#define SVN_ONE_LINE "r@VERSION_REVISION@ author: @VERSION_LAST_AUTHOR@ date: @VERSION_LAST_DATA@" - -#endif /*__VERSION_H__*/ - diff --git a/build/cmake/version.in b/build/cmake/version.in new file mode 100644 index 000000000..d534c50ba --- /dev/null +++ b/build/cmake/version.in @@ -0,0 +1,33 @@ +/* + * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VERSION_H +#define VERSION_H + +#define MPP_VERSION @VERSION_INFO@ +#define MPP_VER_HIST_CNT @VERSION_CNT@ +#define MPP_VER_HIST_0 @VERSION_HISTORY_0@ +#define MPP_VER_HIST_1 @VERSION_HISTORY_1@ +#define MPP_VER_HIST_2 @VERSION_HISTORY_2@ +#define MPP_VER_HIST_3 @VERSION_HISTORY_3@ +#define MPP_VER_HIST_4 @VERSION_HISTORY_4@ +#define MPP_VER_HIST_5 @VERSION_HISTORY_5@ +#define MPP_VER_HIST_6 @VERSION_HISTORY_6@ +#define MPP_VER_HIST_7 @VERSION_HISTORY_7@ +#define MPP_VER_HIST_8 @VERSION_HISTORY_8@ +#define MPP_VER_HIST_9 @VERSION_HISTORY_9@ + +#endif /*__VERSION_H__*/ diff --git a/build/linux/aarch64/arm.linux.cross.cmake b/build/linux/aarch64/arm.linux.cross.cmake new file mode 100644 index 000000000..1d512ecf7 --- /dev/null +++ b/build/linux/aarch64/arm.linux.cross.cmake @@ -0,0 +1,8 @@ +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_C_COMPILER "${TOOLCHAIN}gcc") +SET(CMAKE_CXX_COMPILER "${TOOLCHAIN}g++") +SET(CMAKE_SYSTEM_PROCESSOR "armv8-a") + +add_definitions(-fPIC) +add_definitions(-DARMLINUX) +add_definitions(-Dlinux) diff --git a/build/linux/aarch64/make-Makefiles.bash b/build/linux/aarch64/make-Makefiles.bash new file mode 100755 index 000000000..38a564767 --- /dev/null +++ b/build/linux/aarch64/make-Makefiles.bash @@ -0,0 +1,45 @@ +#!/bin/bash +# Run this from within a bash shell + +set +e + +MPP_PWD=`pwd` +MPP_TOP=${MPP_PWD}/../../.. +DEFAULT_TOOLCHAIN=aarch64-linux-gnu- + +# toolchain detection +check_cmd(){ + "$@" >> /dev/null 2>&1 +} +check_gcc(){ + check_cmd ${TOOLCHAIN}gcc -v +} + +source ../opt_proc.sh + +if [ -z "${TOOLCHAIN}" ]; then + echo "Using system ${DEFAULT_TOOLCHAIN} as toolchain." + TOOLCHAIN=$DEFAULT_TOOLCHAIN +fi + +check_gcc + +if [ $? -eq 127 ];then + echo -e "\e[31m${TOOLCHAIN}gcc is not found!\e[0m" + echo -e "Please specify valid toolchain path and it's prefix to variable 'TOOLCHAIN' with argument --toolchain." + echo -e "For example:\n \t./make-Makefiles.bin --toolchain /path-to-toolchain/arm-linux-gnueabi-" + exit 1 +fi + +# generate Makefile +cmake -DCMAKE_BUILD_TYPE=Release \ + -DTOOLCHAIN=${TOOLCHAIN} \ + -DCMAKE_TOOLCHAIN_FILE=./arm.linux.cross.cmake \ + -G "Unix Makefiles" \ + ${MPP_TOP} + +if [ "${CMAKE_PARALLEL_ENABLE}" = "0" ]; then + cmake --build . +else + cmake --build . -j +fi diff --git a/build/linux/arm/arm.linux.cross.cmake b/build/linux/arm/arm.linux.cross.cmake new file mode 100644 index 000000000..bfa79c51e --- /dev/null +++ b/build/linux/arm/arm.linux.cross.cmake @@ -0,0 +1,9 @@ +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_C_COMPILER "${TOOLCHAIN}gcc") +SET(CMAKE_CXX_COMPILER "${TOOLCHAIN}g++") +SET(CMAKE_SYSTEM_PROCESSOR "armv7-a") +#SET(CMAKE_SYSTEM_PROCESSOR "armv7-a_hardfp") + +add_definitions(-fPIC) +add_definitions(-DARMLINUX) +add_definitions(-Dlinux) diff --git a/build/linux/arm/make-Makefiles.bash b/build/linux/arm/make-Makefiles.bash new file mode 100755 index 000000000..916eaaf1e --- /dev/null +++ b/build/linux/arm/make-Makefiles.bash @@ -0,0 +1,46 @@ +#!/bin/bash +# Run this from within a bash shell + +set +e + +MPP_PWD=`pwd` +MPP_TOP=${MPP_PWD}/../../.. +DEFAULT_TOOLCHAIN=arm-linux-gnueabi- + +# toolchain detection +check_cmd(){ + "$@" >> /dev/null 2>&1 +} +check_gcc(){ + check_cmd ${TOOLCHAIN}gcc -v +} + +source ../opt_proc.sh + +if [ -z "${TOOLCHAIN}" ]; then + echo "Using system ${DEFAULT_TOOLCHAIN} as toolchain." + TOOLCHAIN=$DEFAULT_TOOLCHAIN +fi + +check_gcc + +if [ $? -eq 127 ];then + echo -e "\e[31m${TOOLCHAIN}gcc is not found!\e[0m" + echo -e "Please specify valid toolchain path and it's prefix to variable 'TOOLCHAIN' with argument --toolchain." + echo -e "For example:\n \t./make-Makefiles.bin --toolchain /path-to-toolchain/arm-linux-gnueabi-" + exit 1 +fi + +# generate Makefile +cmake -DCMAKE_BUILD_TYPE=Release \ + -DTOOLCHAIN=${TOOLCHAIN} \ + -DCMAKE_TOOLCHAIN_FILE=./arm.linux.cross.cmake \ + -DHAVE_DRM=ON \ + -G "Unix Makefiles" \ + ${MPP_TOP} + +if [ "${CMAKE_PARALLEL_ENABLE}" = "0" ]; then + cmake --build . +else + cmake --build . -j +fi diff --git a/build/linux/make-Makefiles.bash b/build/linux/make-Makefiles.bash deleted file mode 100755 index c0f8c3ad5..000000000 --- a/build/linux/make-Makefiles.bash +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# Run this from within a bash shell -cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=debug ../../ && ccmake ../../ - diff --git a/build/linux/opt_proc.sh b/build/linux/opt_proc.sh new file mode 100755 index 000000000..4e22bf353 --- /dev/null +++ b/build/linux/opt_proc.sh @@ -0,0 +1,58 @@ +# Run this from within a bash shell +MAKE_PROGRAM=`which make` + +# delete list +FILES_TO_DELETE=( + "CMakeCache.txt" + "Makefile" + "cmake_install.cmake" + "compile_commands.json" + "rockchip_mpp.pc" + "rockchip_vpu.pc" +) + +DIRS_TO_DELETE=( + "CMakeFiles" + "mpp" + "osal" + "test" + "utils" +) + +while [ $# -gt 0 ]; do + case $1 in + --help | -h) + echo "Execute make-Makefiles.sh in *arm/* or *aarch64/* with some args." + echo " use --toolchain to set toolchain e.g. --toolchain path/aarch64-none-linux-gnu-" + echo " use --rebuild to rebuild after clean" + echo " use --clean to clean all build file" + exit 1 + ;; + --toolchain) + TOOLCHAIN=$2 + echo "toolchain: ${TOOLCHAIN}" + shift + ;; + --rebuild) + ${MAKE_PROGRAM} clean + if [ -f "CMakeCache.txt" ]; then + rm CMakeCache.txt + fi + shift + ;; + --clean) + for FILE_TO_DELETE in "${FILES_TO_DELETE[@]}"; do + if [ -f ${FILE_TO_DELETE} ]; then + rm ${FILE_TO_DELETE} + fi + done + for DIR_TO_DELETE in "${DIRS_TO_DELETE[@]}"; do + if [ -d ${DIR_TO_DELETE} ]; then + rm -rf ${DIR_TO_DELETE} + fi + done + exit 1 + ;; + esac + shift +done \ No newline at end of file diff --git a/build/linux/x86/sofia-3gr/make-Makefiles.bash b/build/linux/x86/sofia-3gr/make-Makefiles.bash new file mode 100755 index 000000000..8a8f5e3f8 --- /dev/null +++ b/build/linux/x86/sofia-3gr/make-Makefiles.bash @@ -0,0 +1,6 @@ +#!/bin/bash +# Run this from within a bash shell +cmake -G "Unix Makefiles" \ + -DCMAKE_TOOLCHAIN_FILE=./sofia-3gr.linux.cross.cmake \ + -DRKPLATFORM=ON \ + ../../../../ && ccmake ../../../../ diff --git a/build/linux/x86/sofia-3gr/sofia-3gr.linux.cross.cmake b/build/linux/x86/sofia-3gr/sofia-3gr.linux.cross.cmake new file mode 100644 index 000000000..497c7fb76 --- /dev/null +++ b/build/linux/x86/sofia-3gr/sofia-3gr.linux.cross.cmake @@ -0,0 +1,6 @@ +cmake_minimum_required( VERSION 2.6.3 ) + +SET(CMAKE_SYSTEM_NAME Linux) +add_definitions(-fPIC) +add_definitions(-DSOFIA_3GR_LINUX) +include_directories(osal) diff --git a/build/linux/x86_64/make-Makefiles.bash b/build/linux/x86_64/make-Makefiles.bash new file mode 100755 index 000000000..99741be53 --- /dev/null +++ b/build/linux/x86_64/make-Makefiles.bash @@ -0,0 +1,12 @@ +#!/bin/bash +# Run this from within a bash shell +# x86_64 is for simulation do not enable RK platform + +set +e + +cmake -G "Unix Makefiles" \ + -DCMAKE_BUILD_TYPE=debug \ + -DRKPLATFORM=OFF \ + ../../../ + +cmake --build . -j diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 000000000..4e592a415 --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1,14 @@ +/.debhelper/ +/debhelper-build-stamp +/files +/librockchip-mpp-dev.substvars +/librockchip-mpp-dev/ +/librockchip-mpp-static.substvars +/librockchip-mpp-static/ +/librockchip-mpp1.substvars +/librockchip-mpp1/ +/rockchip-mpp-demos.substvars +/rockchip-mpp-demos/ +/librockchip-vpu0.substvars +/librockchip-vpu0/ +/tmp/ diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 000000000..87253393b --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,6 @@ +mpp for Debian +-------------- + + + + -- Randy Li Wed, 03 Aug 2016 08:14:14 +0000 diff --git a/debian/README.source b/debian/README.source new file mode 100644 index 000000000..836400248 --- /dev/null +++ b/debian/README.source @@ -0,0 +1,10 @@ +mpp for Debian +-------------- + + + + + + -- Randy Li Wed, 03 Aug 2016 08:14:14 +0000 + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..d38c2b3fa --- /dev/null +++ b/debian/changelog @@ -0,0 +1,256 @@ +mpp (1.5.0-1) stable; urgency=critical + + * [mpp_enc_impl]: Cleanup hal_task on empty eos task + ... + + -- Caesar Wang Thu, 20 May 2021 09:40:00 +0800 + +mpp (1.4.0-1) stable; urgency=critical + + [ Herman Chen ] + * [vp8d]: Remove unused table + + [ timkingh.huang ] + * [h264e]: add SSE parameter check + + [ Herman Chen ] + * [h264e]: Add qp min/max limit by bps max/min + + [ timkingh.huang ] + * [h264e]: limit bit rate on movement scene + + [ leo.ding ] + * [h264e]: fix bug: vepu1 h264 encode + * [h264d]: fix bug: when judge whether is end of frame + + [ Herman Chen ] + * [rc]: Add bps information print + * [test]: Fix rc2 test rc_mode error + + [ leo.ding ] + * [h264e]: fix bug: vepu h264 encode rate control + + [ Herman Chen ] + * [osal]: Change mpp time print to us + * [h264e_rkv]: Fix error qp prev update + + [ leo.ding ] + * [jpege]: add vepu1 jpeg encode support + * [osal]: linux: add -ldl -lct to link relative library + + [ Herman Chen ] + * [oasl]: Add lock timing test + * [base]: Add mpp/base/test for task en/dequeue demo + + [ Randy Li ] + * [jpege]: fix some compiler warnings + * [jpegd]: fix the compiler warnings and hide some symbols + * [osal]: fixup for a compiler warning + * [allocator]: force using drm allocator in Linux platform + * [vpu]: use the platform function to open device node + * [vp8d]: fix the vdpu2 decoding error + + [ leo.ding ] + * [hal_vp9d]: change stride align to 256 odds + + [ Randy Li ] + * [m2vd]: a various of fixup + + [ Herman Chen ] + * [h264e]: Fix QP stuck error + + [ timkingh.huang ] + * [h264e]: record rate control parameter + * [h264e]: tidy code + + [ leo.ding ] + * [h264e]: fix bps check failed when mpi setup to fix_qp mode + + [ Randy Li ] + * [jpege]: fixup mpp device + * Revert "[osal]: linux: add -ldl -lct to link relative library" + + [ leo.ding ] + * [h265d]: fix bug: when has no short_rps, it should be has no rps + + [ Randy Li ] + * [mpp_dec]: remove obsoleted code and format comments + * [mpp]: fixup for the deadlock in decoding + + [ ayaka ] + * [test]: add timeout poll type sample code + + [ leo.ding ] + * [h265d]: fix bug: malloc buffer matching + + [ timkingh.huang ] + * [h264e]: fix rate-control bug + * [h264e]: allocate buffers before encoding + + [ sliver.chen ] + * [h264]: fix xrgb encode bug + + [ sayon.chen ] + * [h265d]: hiding the vps_id information + + [ Randy Li ] + * [h264d]: add supporting for the interlace mode + + [ leo.ding ] + * [mpg4d]: update spit mode in prepare + + [ ZhouJing ] + * [m4vd]: add m4v decoder support for vdpu1 + + [ Randy Li ] + * [mpg4d]: fixup the compiler warnings + * .gitignore: ignore those debian generated files + + [ timkingh.huang ] + * [h264e]: fix rate control bug + + [ Randy Li ] + * [h264d]: move some variables to its scope + * [h264d]: handle svc_extension correctly + + [ leo.ding ] + * [vpu_api_legacy]: disprese MPP_DEC_SET_FRAME_INFO function to each codec. + + [ Randy Li ] + * [mpp]: wake up the parser thread in the correct place + + [ sliver.chen ] + * [test]: add README.md for mpi unit test + * [test]: modify to avoid encode dead loop + + [ leo.ding ] + * [avsd]: fix bugs: when video is field + * [mpp_buf_slot]: fix bug: should return the info_set frame back + * [avsd]: add dpb error marking + + [ Randy Li ] + * [osal]: fixup for build in linux + * [mpp]: move header files into header directory + + [ timkingh.huang ] + * [h264e]: add command of MPP_ENC_SET_QP_RANGE + * [h264e]: Clear OSD data when zero region number + + [ sliver.chen ] + * [m2vd]: add m2vd parser mode + + [ leo.ding ] + * [mpg4d]: fix hiding bugs when split mode + + [ Herman Chen ] + * [base]: Remove misc buffer group creation + * [base]: Disable default print on exit + + [ leo.ding ] + * [vpu_api]: add vpuCodecContext parameters + + [ Randy Li ] + * [mpp_frame]: add complex formats and more comments + + [ leo.ding ] + * [vp9d]: fix error: opening device should close, when deinit + + [ Randy Li ] + * h264e: add supporting for more input pixel format + * [drm]: fix a various of bugs in drm allocator + * [drm]: use mmap() in native way for GNU Linux target + + [ timkingh.huang ] + * [jpegd]: just scan parts of markers for rv1108 + + [ sliver.chen ] + * [h264e]: fix h264 xrgb encode bug + + [ Herman Chen ] + * [ioctl]: Add compatible patch for different kernel + + [ sayon.chen ] + * [rkvenc] modfiy ratecontrol to be more smooth + + [ Randy Li ] + * [ion]: file descriptor for the external buffer + + [ Herman Chen ] + * [hal_vp9d]: Fix buffer alignment conflict + + [ sliver.chen ] + * [test]: add err info check when decode + * [osal]: force mpp use drm buffer when HAVE_DRM are defined. + + [ timkingh.huang ] + * [h264e]: rate control for all intra stream + + [ Randy Li ] + * [osal]: add queue data type + * [mpp]: use the blokcing queue on the input + * [mpp_list]: release the blocked thread at reset + + [ leo.ding ] + * [hal_h264d]: add command for switch hard_mode + + [ Randy Li ] + * [mpp]: silent lots of message + * [mpp_buf_slot]: return an error code when stride is invalid + * [jpegd]: stop the future work when the parser is error + * [osal]: add rk3036 platform + * [mpp]: rename and update build rules + * [legacy]: rename mpp legacy library + * [pkgconfig]: offer a sample for pkgconfig + * [build]: a simple build rules + + -- Randy Li Tue, 21 Nov 2017 07:35:23 +0000 + +mpp (1.3.1-1) testing; urgency=medium + + * [allocator]: force using drm allocator in Linux platform + * [mpp_buffer]: access the index field of buffer info + * [mpi]: decode_put_packet() would return the internal error + * [meta]: use fourcc format to store the meta data for those enum types + * [drm]: use mmap64() in native way for GNU Linux target + * [mpp/hal/vp8d]: rename and add device type info + * [mpp/hal/vp8d]: add support for VDPU1 + * [mpp_frame]: export more functions to MppFrame fields + * [h264d]: make H.264 common data and functions together + * [h264d]: move the register table into the other file + * [test]: fix the align problem in decode_advanced() + * [jpegd] rename to its device type + * [jpegd]: isolate the common functions + * [jpegd]: add support for VDPU1 + + -- Randy Li Thu, 09 Mar 2017 09:52:21 +0000 + +mpp (1.3.0-1) testing; urgency=medium + + * [mpp]: a fixup for wrong place scope symbols + * .gitignore: the intial version of gitignore + * build: support cross build in debian + * mpp: add pkgconfig file + * debian: support install for multiarch + * debian: add debian build rules + * utils: move the header files to common include directories + * osal: match system implementation with pre-defined marco + * osal: rename the directory of windows implementation + * osal: build: update the build system + * osal: build: use system default thread library + * osal: build: test: do not install unit test + * mpp: move header files into header directory + * mpp: test: build: rename the mpp library name in unit test + * mpp: legacy: rename mpp legacy library as rockchip_vpu + * mpp: build: update build rules + * build: a simple build rules + * mpp: install mpp library to target + * build: install development files + * build: add pkgconfig support + + -- Randy Li Wed, 08 Feb 2017 08:37:49 +0000 + +mpp (73f2ee87a7f836daa6d09b3f65e5abd8e1380318-1) unstable; urgency=low + + * The origin version from algorithmn group + + -- Randy Li Sun, 05 Feb 2017 03:14:14 +0000 diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000..f599e28b8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..08771ae0c --- /dev/null +++ b/debian/control @@ -0,0 +1,30 @@ +Source: mpp +Priority: optional +Maintainer: Randy Li +Build-Depends: debhelper (>= 10), cmake, dh-exec +Standards-Version: 3.9.5 +Section: libs +Homepage: http://www.rock-chips.com +#Vcs-Git: git://anonscm.debian.org/collab-maint/mpp.git +#Vcs-Browser: http://anonscm.debian.org/?p=collab-maint/mpp.git;a=summary + +Package: librockchip-mpp-dev +Section: libdevel +Architecture: any +Depends: librockchip-mpp1 (= ${binary:Version}), ${misc:Depends} +Description: Media Process Platform + +Package: librockchip-mpp1 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Media Process Platform + +Package: librockchip-vpu0 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Media Process Platform + +Package: rockchip-mpp-demos +Architecture: any +Depends: librockchip-mpp1 (= ${binary:Version}), librockchip-vpu0 (= ${binary:Version}), ${misc:Depends} +Description: Media Process Platform Demos diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..3c881caa5 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,18 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Media Process Platform (MPP) module +Source: https://github.com/rockchip-linux/mpp + +Files: * +Copyright: 2015 Herman Chen +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/debian/docs b/debian/docs new file mode 100644 index 000000000..f3d4ef20e --- /dev/null +++ b/debian/docs @@ -0,0 +1,2 @@ +readme.txt +readme.txt diff --git a/debian/librockchip-mpp-dev.install b/debian/librockchip-mpp-dev.install new file mode 100755 index 000000000..02845c22d --- /dev/null +++ b/debian/librockchip-mpp-dev.install @@ -0,0 +1,3 @@ +#! /usr/bin/dh-exec +usr/include/* +usr/lib/${DEB_HOST_MULTIARCH}/pkgconfig/* diff --git a/debian/librockchip-mpp1.install b/debian/librockchip-mpp1.install new file mode 100755 index 000000000..230c5a457 --- /dev/null +++ b/debian/librockchip-mpp1.install @@ -0,0 +1,3 @@ +#! /usr/bin/dh-exec +usr/lib/${DEB_HOST_MULTIARCH}/librockchip_mpp.so +usr/lib/${DEB_HOST_MULTIARCH}/librockchip_mpp.so.* diff --git a/debian/librockchip-vpu0.install b/debian/librockchip-vpu0.install new file mode 100755 index 000000000..0ae62799a --- /dev/null +++ b/debian/librockchip-vpu0.install @@ -0,0 +1,3 @@ +#! /usr/bin/dh-exec +usr/lib/${DEB_HOST_MULTIARCH}/librockchip_vpu.so +usr/lib/${DEB_HOST_MULTIARCH}/librockchip_vpu.so.* diff --git a/debian/rockchip-mpp-demos.install b/debian/rockchip-mpp-demos.install new file mode 100644 index 000000000..4b6438ad3 --- /dev/null +++ b/debian/rockchip-mpp-demos.install @@ -0,0 +1,2 @@ +#! /usr/bin/dh-exec +usr/bin/* diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..1086f035a --- /dev/null +++ b/debian/rules @@ -0,0 +1,32 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#DH_VERBOSE = 1 + +# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/* +DPKG_EXPORT_BUILDFLAGS = 1 +include /usr/share/dpkg/default.mk + +# see FEATURE AREAS in dpkg-buildflags(1) +#export DEB_BUILD_MAINT_OPTIONS = hardening=+all + +# see ENVIRONMENT in dpkg-buildflags(1) +# package maintainers to append CFLAGS +#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic +# package maintainers to append LDFLAGS +#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed + +ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) +export CMAKE_TOOLCHAIN_FILE=/etc/dpkg-cross/cmake/CMakeCross.txt +endif + +# main packaging script based on dh7 syntax +%: + dh $@ --parallel --buildsystem=cmake + +# debmake generated override targets +# This is example for Cmake (See http://bugs.debian.org/641051 ) +override_dh_auto_configure: + dh_auto_configure -- \ + -DCMAKE_BUILD_TYPE=Release \ + -DARM_MIX_32_64=ON diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/doc/Rockchip_Developer_Guide_MPP_CN.md b/doc/Rockchip_Developer_Guide_MPP_CN.md new file mode 100644 index 000000000..59ca45c58 --- /dev/null +++ b/doc/Rockchip_Developer_Guide_MPP_CN.md @@ -0,0 +1,1132 @@ +# MPP 开发参考 + +| Project: | MPP | +| --------- | ---------- | +| Version: | 0.7 | +| Author: | 陈恒明 | +| Date: | 10/17/2023 | + +| Revision | Date | Description | Author | +| -------- | ---------- | ------------------------------------------------------- | ----------------------- | +| 0.1 | 04/18/2018 | 初始版本 | 陈恒明 | +| 0.2 | 05/07/2018 | 增加解码器control命令说明,编码器部分说明和demo部分说明 | 陈恒明 | +| 0.3 | 05/22/2018 | 修正一些笔误和说明错误,重新编排页码 | 陈恒明 谢雄斌(精英智通) | +| 0.4 | 11/28/2018 | 更新编码器输入图像的内存排布说明。 修正编码器流程图笔误 | 陈恒明 研果(科通) | +| 0.5 | 06/08/2020 | 更新编码器新配置接口 不再支持RK3188 | 陈恒明 | +| 0.6 | 08/31/2022 | 更新MPP demo说明 更新编码器控制接口说明 | 陈恒明 阮学满 | +| 0.7 | 10/17/2023 | 添加markdown文档 |阮学满 林言东| +| | | | | +| | | | | + +# 第一章 MPP 介绍 + +## 1.1 概述 + +瑞芯微提供的媒体处理软件平台(Media Process Platform,简称MPP)是适用于瑞芯微芯片系列的通用媒体处理软件平台。该平台对应用软件屏蔽了芯片相关的复杂底层处理,其目的是为了屏蔽不同芯片的差异,为使用者提供统一的视频媒体处理接口(Media Process Interface,缩写MPI)。MPP提供的功能包括: + +- 视频解码 + - H.265 / H.264 / H.263 / VP9 / VP8 / MPEG-4 / MPEG-2 / MPEG-1 / VC1 / MJPEG / AV1 +- 视频编码 + - H.265 / H.264 / VP8 / MJPEG +- 视频处理 + - 视频拷贝,缩放,色彩空间转换,场视频解交织(Deinterlace) + +本文档描述了MPP框架以及组成模块,以及供用户使用的MPI接口。本文档适合于上层应用开发人员以及技术支持人员阅读。 + +## 1.2 系统架构 + +MPP平台在系统架构的层次图如下图: + +![](media/Figure01_MPP_system_framework.png) +
图表 1 MPP系统框架
+ +- 硬件层Hardware + +硬件层是瑞芯微系列芯片平台的视频编解码硬件加速模块,包括vdpu、vepu、rkvdec和rkvenc等不同类型、不同功能的硬件加速器。 + +- 内核驱动层Kernel driver + +Linux内核的编码器硬件设备驱动,以及相关的mmu,内存,时钟,电源管理模块等。支持的平台版本主要是Linux kernel 3.10、4.4、4.19、5.10和6.1。MPP库对于内核驱动有依赖。 + +- MPP层 + +用户态的MPP层屏蔽了不同操作系统和不同芯片平台的差异,为上层使用者提供统一的MPI接口。 + +MPP层包括MPI模块、OSAL模块、HAL模块以及视频编解码器(Video Decoder / Video Encoder)和视频处理功能模块(Video Process)。 + +- 操作系统层 + +MPP用户态的运行平台,如Android以及Debian等Linux发行版 + +- 应用层 + +MPP层通过MPI对接各种中间件软件,如OpenMax和gstreamer,或者直接对接客户的上层应用。 + +## 1.3 平台支持 + +### 1.3.1 软件平台支持 + +MPP支持在各种版本的Android平台和纯Linux平台上运行。 + +支持瑞芯微Linux内核3.10、4.4、4.19和5.10版本,需要有vcodec_service设备驱动支持以及相应的DTS配置支持。 + +### 1.3.2 硬件平台支持 + +支持瑞芯微主流的各种系列芯片平台: + +RK3288系列,RK3368系列,RK3399系列,RK3588系列 + +RK30xx系列,RK312x系列芯片,RK322x系列芯片,RK332x系列 + +RV1109 / RV1126系列(注:RV1107/RV1108会逐步退出支持) + +## 1.4 功能支持 + +MPP支持的编解码功能随运行的芯片平台规格不同区别很大,请查询对应芯片的《Multimedia Benchmark》。 + +## 1.5 注意事项 + +如果想快速了解MPP的使用和demo,请直接转至——第四章 MPP demo说明。 + +如果想快速编译和使用MPP代码,请直接转至——第五章 MPP库编译与使用。 + +如果想了解MPP设计细节与设计思路,请参考MPP代码根目录的readme.txt,doc目录下的txt文档以及头文件的注释说明。 + +# 第二章 接口设计说明 + +本章节描述了用户在使用MPP过程中会直接接触到的数据结构,以及这些数据结构的使用说明。 + +由于视频编解码与视频处理过程需要处理大量的数据交互,包括码流数据、图像数据以及内存数据,同时还要处理与上层应用以及内核驱动的交叉关系,所以MPP设计了MPI接口,用于与上层交互。 + +本章节说明了MPI接口使用的数据结构,以及设计思路。 + +## 2.1 接口结构概述 + +下图为MPI接口使用的主要数据结构: + +![](media/Figure02_Data_structure_used_in_MPI_interface.png) +
图表 2 MPI接口使用的数据结构
+ +MppMem为C库malloc内存的封装。 + +MppBuffer为硬件用的dmabuf内存的封装。 + +MppPacket为一维缓存封装,可以从MppMem和MppBuffer生成,主要用于表示码流数据。 + +MppFrame为二维帧数据封装,可以从MppMem和MppBuffer生成,主要用于表示图像数据。 + +使用MppPacket和MppFrame就可以简单有效的完成一般的视频编解码工作。 + +以视频解码为例,码流输入端把地址和大小赋值给MppPacket,通过put_packet接口输入,在输出端通过get_frame接口得到输入图像MppFrame,即可完成最简单的视频解码过程。 + +![](media/Figure03_Use_simple_interface_to_realize_video_decoding.png) +
图表 3 使用简单接口实现视频解码
+ +MppMeta和MppTask为输入输出用任务的高级组合接口,可以支持指定输入输出方式等复杂使用方式,支持异步数据流处理。 + +**注意**:以上这些接口数据结构都是使用void\*句柄来引用使用,其目的是为了方便扩展和前向兼容。 + +本段落中的提到的成员都是通过形如mpp_xxx_set/get_xxx的接口来访问。 + +## 2.2 内存封装MppBuffer + +MppBuffer主要用于描述供硬件使用的内存块(即缓存),提供了内存块的分配、释放和加减引用等功能,目前支持的分配器有:ion、drm和dma_heap。MppBuffer几个重要的参数成员如下: + +| 成员名称 | 成员类型 | 描述说明 | +|----------|----------|----------------------------------| +| ptr | void \* | 表示内存块的起始虚拟地址。 | +| size | size_t | 表示内存块的大小。 | +| fd | int | 表示内存块的用户态空间文件句柄。 | + +在解码过程中,解码图像的缓存通常需要在固定的缓存池里进行轮转,为了实现这一点,MPP在MppBuffer基础之上又定义了MppBufferGroup。MppBuffer的使用方式有两种:常规使用方式和外部导入方式,由于二者的内存分配方式不同,也称为internal模式和external模式。 + +在MppBuffer常规使用方式下,MppBufferGroup由MPP内部生成和维护。通过mpp_buffer_get和mpp_buffer_put对内存块进行申请和释放,如下图所示: + +![](media/Figure04_Normal_usage_of_MppBuffer.png) +
图表 4 MppBuffer的常规使用方式
+ +其流程伪代码如下图: + +![](media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage.png) + +这种方式可以实现解码器在解码过程中**零拷贝输出**(解码器的输出帧与解码器内部使用的参考帧用是同一帧),但不容易实现**零拷贝显示**(解码器的输出帧不一定在显示端可以直接显示),同时要求用户知道需要给解码器开多大的空间进行解码。 + +另一种使用方式是把MppBufferGroup完全做为一个缓存的管理器,用于管理外部导入的缓存。其使用方式如下图: + +![](media/Figure05_Usage_of_MppBuffer_External_Import.png) +
图表 5 MppBuffer外部导入使用方式
+ +其流程伪代码如下图: + +![](media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage.png) + +这种方式可以使得解码器使用外部的缓存,可以对接OpenMax/gstreamer这样的中间件,也方便对接用户己有的上层代码,便于实现零拷贝显示。 + +## 2.3 码流封装MppPacket + +MppPacket主要用于描述一维码流的相关信息,特别是有效数据的位置与长度。MppPacket几个重要的参数成员如下: + +| 成员名称 | 成员类型 | 描述说明 | +|----------|----------|----------------------------------------------------------------------------------------------------| +| data | void \* | 表示缓存空间的起始地址。 | +| size | size_t | 表示缓存空间的大小。 | +| pos | void \* | 表示缓存空间内有效数据的起始地址。 | +| length | size_t | 表示缓存空间内有效数据的长度。如果在decode_put_packet调用之后length变为0,说明此包码流己消耗完成。 | + +其关系如下图所示: + +![](media/Figure06_Important_parameter_description_of_MppPacket.png) + +
图表 6 MppPacket重要参数说明
+ +MppPacket的其他配置参数成员如下: + +| 成员名称 | 成员类型 | 描述说明 | +| -------- | --------- | ------------------------------------------------------------ | +| pts | RK_U64 | 表示显示时间戳(Present Time Stamp)。 | +| dts | RK_U64 | 表示解码时间戳(Decoding Time Stamp)。 | +| eos | RK_U32 | 表示码流结束标志(End Of Stream)。 | +| buffer | MppBuffer | 表示MppPacket对应的MppBuffer。 | +| flag | RK_U32 | 表示MPP内部使用的标志位,包含如下标志:
\#define MPP_PACKET_FLAG_EOS (0x00000001)
\#define MPP_PACKET_FLAG_EXTRA_DATA (0x00000002)
\#define MPP_PACKET_FLAG_INTERNAL (0x00000004)
\#define MPP_PACKET_FLAG_INTRA (0x00000008) | + +MppPacket做为描述一维内存的结构体,在使用时需要使用malloc出来的内存或者使用MppBuffer的内存进行初始化。在释放MppPacket时有几种情况: + +如果是外部malloc地址配置到MppPacket,不会做free释放处理,如下示例; + +![](media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket.png) + +如果是拷贝产生的MppPacket,会做free释放内存,如下示例; + +![](media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init.png) + +如果是MppBuffer产生的MppPacket,会在生成时对MppBuffer加引用,在释放时对MppPacket减引用。 + +![](media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer.png) + +## 2.4 图像封装MppFrame + +MppFrame主要用于定义二维图像缓存的相关信息,有效数据的位置与长度。MppFrame几个重要的参数成员如下: + +| 成员名称 | 成员类型 | 描述说明 | +|------------|----------|------------------------------------------------| +| width | RK_U32 | 表示水平方向像素数,单位为像素个数。 | +| height | RK_U32 | 表示垂直方向像素数,单位为像素个数。 | +| hor_stride | RK_U32 | 表示垂直方向相邻两行之间的距离,单位为byte数。 | +| ver_stride | RK_U32 | 表示图像分量之间的以行数间隔数,单位为1。 | + +![](media/Figure07_Important_parameter_description_of_MppFrame.png) +
图表 7 MppFrame重要参数说明
+ +MppFrame的其他配置参数成员如下: + +| 成员名称 | 成员类型 | 描述说明 | +|-------------|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| mode | RK_U32 | 表示图像数据帧场属性: ![](media/Rockchip_Developer_Guide_MPP/MPP_image_data_frame_field_properties.png) | +| pts | RK_U64 | 表示图像的显示时间戳(Present Time Stamp)。 | +| dts | RK_U64 | 表示图像的解码时间戳(Decoding Time Stamp)。 | +| eos | RK_U32 | 表示图像的结束标志(End Of Stream)。 | +| errinfo | RK_U32 | 表示图像的错误标志,是否图像内有解码错误。 | +| discard | RK_U32 | 表示图像的丢弃标志,如果图像解码时的参考关系不满足要求,则这帧图像会被标记为需要丢弃,不被显示。 | +| buf_size | size_t | 表示图像需要分配的缓存大小,与图像的格式相关,也与解码数据的格式相关。 | +| info_change | RK_U32 | 如果为真,表示当前MppFrame是一个用于标记码流信息变化的描述结构,说明了新的宽高,stride,以及图像格式。 可能的info_change原因有: 图像序列宽高变化。 图像序列格式变化,如8bit变为10bit。 一旦info_change产生,需要重新分析解码器使用的内存池。 | +| fmt | MppFrameFormat | 表示图像色彩空间格式以及内存排布方式: ![](media/Rockchip_Developer_Guide_MPP/MPP_image_colorspace_format_and_memory_arrangement.png) | +| color_range | MppFrameColorRange | 表示图像数据彩色空间范围: YUV full range:0 \~ 255(8bit) YUV limit range:16 \~ 235(8bit) ![](media/Rockchip_Developer_Guide_MPP/MPP_color_space_range.png) | +| buffer | MppBuffer | 表示MppFrame对应的MppBuffer。 | + +对于解码器来说,MppFrame是其输出的信息结构体,码流解码后的信息(包括像素数据与pts,错误信息等相关信息)都需要带在MppFrame结构体给调用者。MppFrame中的pts/dts,以及eos标志,就是继承自对应的输入MppPacket。 + +同时,一旦发现码流分辨率改变,MppFrame中的info_change标志就会对应置位,向用户通知发生了info_change事件,需要用户进行缓存池修改处理。 + +## 2.5 高级任务封装MppTask + +当MppPacket与MppFrame组成的接口无法满足需求时,需要使用MppTask做为一个数据容器,来满足复杂的输入输出需求。MppTask需要与poll/dequeuer/enqueue接口来配合使用,对比put_packet/get_frame等简单流程接口,MppTask的使用流程复杂,效率低,是为了满足复杂需求的代价。 + +![](media/Figure08_Use_MppTask_for_input_and_output.png) +
图表 8 使用MppTask来进行输入输出
+ +MppTask是一个通过关键字key值(MppMetaKey)来进行扩展的结构,可以通过扩展支持的数据类型来支持复杂的高级需求。可以使用通过mpp_task_meta_set/get_xxx系列接口来对MppTask里的不同关键字数据进行访问。 + +![](media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask.png) +
图表 9 MppTask支持的数据类型与关键字类型
+ +在实际使用中,需要从MPP的输入端口通过dequeue接口获取MppTask,把需要处理的数据通过mpp_task_meta_set_xxx系列接口配置到MppTask里,之后enqueue输出到MPP实例进行处理。MPP的输出端口流程类似,需要把mpp_task_meta_set_xxx系列接口换成mpp_task_meta_get_xxx系列接口来从MppTask里获取数据。 + +目前实用的编码器接口,以及MJPEG解码接口有使用MppTask进行实现。 + +## 2.6 实例上下文封装MppCtx + +MppCtx是提供给用户使用的MPP实例上下文句柄,用于指代解码器或编码器实例。 + +用户可以通过mpp_create接口获取MppCtx实例以及MppApi结构体,再通过mpp_init来初始化MppCtx的编解码类型与格式,之后通过decode_xxx/encode_xxx以及poll/dequeuer/enqueue接口来进行访问,使用结束时通过mpp_destroy接口进行销毁。 + +![](media/Figure10_MppCtx_usage_process.png) +
图表 10 MppCtx使用过程
+ +## 2.7 API封装MppApi(MPI) + +MppApi结构体封装了MPP的对外API接口,用户通过使用MppApi结构中提供的函数指针实现视频编解码功能,其结构如下: + +| 成员名称 | 成员类型 | 描述 | +| ----------------- | -------- | ------------------------------------------------------------ | +| size | RK_U32 | MppApi结构体大小。 | +| version | RK_U32 | MppApi结构体版本。 | +| decode | 函数指针 | MPP_RET (\*decode)(MppCtx ctx, MppPacket packet, MppFrame \*frame)
视频解码接口,同时进行输入与输出,单独使用。
ctx :MPP实例上下文。
packet :输入码流。
frame :输出图像。
返回值 :0为正常,非零为错误码。 | +| decode_put_packet | 函数指针 | MPP_RET (\*decode_put_packet)(MppCtx ctx, MppPacket packet)
视频解码输入接口,与decode_get_frame配合使用。
ctx :MPP实例上下文。
packet :输入码流。
返回值 :0为正常,表示码流己被MPP处理;非零为出现错误,码流未被处理,需要把码流重新输入。 | +| decode_get_frame | 函数指针 | MPP_RET (\*decode_get_frame)(MppCtx ctx, MppFrame \*frame)
视频解码输出接口,与decode_put_packet配合使用。
ctx :MPP实例上下文。
frame :输出图像。
返回值 :0为正常,表示获取输出过程正常,需要判断是否有得到有值的frame指针;非零为出现错误。 | +| encode | 函数指针 | MPP_RET (\*encode)(MppCtx ctx, MppFrame frame, MppPacket \*packet)
视频编码接口,同时进行输入与输出,单独使用。
ctx :MPP实例上下文。
frame :输入图像。
packet :输出码流。
返回值 :0为正常,非零为错误码。 | +| encode_put_frame | 函数指针 | MPP_RET (\*encode_put_frame)(MppCtx ctx, MppFrame frame)
视频编码输入接口,与encode_get_packet配合使用。
ctx :MPP实例上下文。
frame :输入图像。
返回值 :0为正常,非零为错误码。 | +| encode_get_packet | 函数指针 | MPP_RET (\*encode_get_packet)(MppCtx ctx, MppPacket \*packet)
视频编码输出接口,与encode_put_frame配合使用。
ctx :MPP实例上下文。
packet :输出码流。
返回值 :0为正常,非零为错误码。 | +| poll | 函数指针 | MPP_RET (\*poll)(MppCtx ctx, MppPortType type, MppPollType timeout)
端口查询接口,用于查询端口是否有数据可供dequeue。
ctx :MPP实例上下文。
type :端口类型,分为输入端口与输出端口。
timeout :查询超时参数,-1为阻塞查询,0为非阻塞查询,正值为超时毫秒数。
返回值 :0为正常,有数据可取出,非零为错误码。 | +| dequeue | 函数指针 | MPP_RET (\*dequeue)(MppCtx ctx, MppPortType type, MppTask \*task)
端口出队列接口,用于从端口中取出MppTask结构。
ctx :MPP实例上下文。
type :端口类型,分为输入端口与输出端口。
task :MppTask。
返回值 :0为正常,有数据可取出,非零为错误码。 | +| enqueue | 函数指针 | MPP_RET (\*enqueue)(MppCtx ctx, MppPortType type, MppTask task)
端口入队列接口,用于往端口送入MppTask结构。
ctx :MPP实例上下文。
type :端口类型,分为输入端口与输出端口。
task :MppTask。
返回值 :0为正常,有数据可取出,非零为错误码。 | +| reset | 函数指针 | MPP_RET (\*reset)(MppCtx ctx)
复位接口,用于对MppCtx的内部状态进行复位,回到可用的初始化状态。需要注意的是,reset接口是阻塞的同步接口。
ctx :MPP实例上下文。
返回值 :0为正常,有数据可取出,非零为错误码。 | +| control | 函数指针 | MPP_RET (\*control)(MppCtx ctx, MpiCmd cmd, MppParam param)
控制接口,用于向MPP实例进行额外控制操作的接口。
ctx :MPP实例上下文。
cmd :Mpi命令类型,表示控制命令的不同类型的。
param :Mpi命令参数,表示控制控制命令的附加参数。
返回值 :0为正常,有数据可取出,非零为错误码。 | + +# 第三章 MPI接口使用说明 + +本章节描述了用户使用MPI接口的具体过程,以及过程是的一些注意事项。 + +MPI(Media Process Interface)是MPP提供给用户的接口,用于提供硬件编解码功能,以及一些必要的相关功能。MPI是通过C结构里的函数指针方式提供给用户,用户可以通过MPP上下文结构MppCtx与MPI接口结构MppApi组合使用来实现解码器与编码器的功能。 + +![](media/Figure11_MPI_interface_range.png) +
图表 11 MPI接口范围
+ +如上图所示,mpp_create,mpp_init,mpp_destroy是操作MppCtx接口的过程,其中mpp_create接口也获取到了MPI接口结构体MppApi,真正的编码与解码过程是通过调用MppApi结构体里内的函数指针来实现,也就是上图中红框内的部分。红框内的函数调用分为编解码流程接口put/get_packet/frame和相关的control和reset接口。下文先描述编解码器接口,再对编解码器工作中的一些要点进行说明。 + +## 3.1 解码器数据流接口 + +解码器接口为用户提供了输入码流,输出图像的功能,接口函数为MppApi结构体里的decode_put_packet函数,decode_get_frame函数和decode函数。这组函数提供了最简洁的解码功能支持。 + +### 3.1.1 decode_put_packet + +| 接口定义 | MPP_RET decode_put_packet(MppCtx ctx, MppPacket packet) | +|----------|---------------------------------------------------------| +| 输入参数 | ctx :MPP解码器实例 packet :待输入的码流数据 | +| 返回参数 | 运行错误码 | +| 功能 | 输入packet码流包数据给ctx指定的MPP解码器实例 | + +#### 输入码流的形式 + +MPP的输入都是没有封装信息的裸码流,裸码流输入有两种形式: + +1. 外部分帧 + +一种是外部已经按帧分段的数据,即每一包输入给decode_put_packet函数的MppPacket数据都已经包含完整的一帧,不多也不少。在这种情况下,MPP可以直接按包处理码流,是MPP的默认运行情况。 + +2. 内部分帧 + +另一种是按长度读取的数据,这样的数据无法判断一包MppPacket数据是否是完整的一帧,需要MPP内部进行分帧处理。MPP也可以支持这种形式的输入,但需要在mpp_init之前,通过control接口的MPP_DEC_SET_PARSER_SPLIT_MODE命令,MPP内的need_split标志打开。 + +![](media/Rockchip_Developer_Guide_MPP/MPP_Split_mode_config.png) + +这样,调用decode_put_packet输入的MppPacket就会被MPP重新分帧,进入到情况一的处理。 + +如果这两种情况出现了混用,会出现码流解码出错的问题。 + +分帧方式处理效率高,但需要输入码流之前先进行解析与分帧; + +不分帧方式使用简单,但效率会受影响。 + +在mpi_dec_test的测试用例中,使用的是方式内部分帧的方式。在瑞芯微的Android SDK中,使用的是外部分帧的方式。用户可以根据自己的应用场景和平台条件进行选择。 + +#### 输入码流的消耗 + +输入MppPacket的有效数据长度为length,在送入decode_put_packet之后,如果输入码流被成功地消耗,函数返回值为零(MPP_OK),同时MppPacket的length被清为0。如果输入码流还没有被处理,会返回非零错误码,MppPacket的length保持不变。 + +#### 函数的工作模式 + +decode_put_packet函数的功能是输入待解码码流给MPP实例,但在一些情况下,MPP实例无法接收更多的数据,这时,工作于非阻塞模式的decode_put_packet会报出错误信息并直接返回。用户得到decode_put_packet返回的错误码之后,需要进行一定时间的等待,再重新送入码流数据,避免额外的频繁cpu开销。 + +#### 最大缓冲数据包数量 + +MPP实例默认可以接收4个输入码流包在处理队列中,如果码流送得太快,就会报出错误码要求用户等待后再送。 + +### 3.1.2 decode_get_frame + +| 接口定义 | MPP_RET decode_get_frame(MppCtx ctx, MppFrame \*frame) | +|----------|------------------------------------------------------------| +| 输入参数 | ctx :MPP解码器实例。 frame :用于获取MppFrame实例的指针。 | +| 返回参数 | 运行错误码 | +| 功能 | 从ctx指定的MPP解码器实例里获取完成解码的frame描述信息。 | + +MPP解码输出的图像是通过MppFrame结构来描述的,同时MppFrame结构也是MPP实例输出信息的管道,图像的错误信息,以及变宽高信息(info change)也是带在MppFrame结构进行输出的。 + +- 输出图像的错误信息 + +图像的错误信息为errinfo,表示图像内容是否有错误,errinfo不为零则表示码流解码时发生了错误,图像内容是有问题的,可以做丢弃处理。 + +- 解码器图像空间需求的确认 + +解码器在解码时,需要为输出图像获取保存像素数据的内存空间,用户需要给解码器提供足够大小,这个空间大小的需求,会在MPP解码器内部根据不同的芯片平台以及不同的视频格式需求进行计算,计算后的内存空间需求会通过MppFrame的成员变量buf_size提供给用户。用户需要按buf_size的大小进行内存分配,即可满足解码器的要求。 + +- 输出图像的变宽高信息(Info change) + +当码流的宽高,格式,像素位深等信息发生变化时,需要反馈给用户,用户需要更新解码器使用的内存池,把新的内存更新给解码器。这里涉及到解码内存分配与使用模式,会在3.3.2 图像内存分配以及交互模式进行说明。 + +### 3.1.3 decode + +decode函数是decode_put_packet与decode_get_frame数据的结合,为用户提供了两个函数的复合调用。其内部逻辑为: + +1. 获取输出图像; +2. 如果输出图像获取成功即返回; +3. 判断码流己送入成功则返回; +4. 送入输入码流; +5. 标记码流送入是否成功并循环第一步; + +在用户看来,decode函数首先是获取解码图像,有解码图像优先返回解码图像,没有可输出的解码图像的情况下送入码流,最后再尝试一次获取解码图像并退出。 + +## 3.2 解码器控制接口 + +### 3.2.1 control + +在定义于rk_mpi_cmd.h文件的MpiCmd枚举类型定义了control接口命令字,其中与解码器和解码过程相关的命令如下: + +![](media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type.png) + +从MPP_DEC_CMD_BASE到MPP_DEC_CMD_END之间的命令为解码器的control接口命令,分别介绍这些命令的功能如下: + +- MPP_DEC_SET_FRAME_INFO + +命令参数为MppFrame,用于配置解码器的默认宽高信息,返回的MppFrame结构会从解码器中带出需要分配的图像缓存大小。命令调用时机一般在mpp_init之后,mpi-\>decode_put_packet之前。 + +- MPP_DEC_SET_EXT_BUF_GROUP + +命令参数为MppBufferGroup,用于把解码器图像解码所需的MppBufferGroup配置给解码器。命令调用时机视图像内存分配模式有不同。 + +- MPP_DEC_SET_INFO_CHANGE_READY + +无命令参数,用于标记解码器使用的MppBufferGroup已经完成Info Change操作的reset处理,可以继续解码。命令调用时机视图像内存分配模式有不同。 + +- MPP_DEC_SET_PRESENT_TIME_ORDER + +命令参数为RK_U32\*,用于处理异常的码流时间戳。 + +- MPP_DEC_SET_PARSER_SPLIT_MODE + +命令参数为RK_U32\*,用于使能MPP内的协议解析器使用内部分帧处理,默认为码流按帧输入,不开启。命令调用时机是在- MPP_init之前。 + +- MPP_DEC_SET_PARSER_FAST_MODE + +命令参数为RK_U32\*,用于使能MPP内的快速帧解析,提升解码的软硬件并行度,但副作用是会对错误码流的标志有影响,默认关闭。命令调用时机是在- MPP_init之前。 + +- MPP_DEC_GET_STREAM_COUT + +命令参数为RK_U32\*,用于外部应用获取还未处理的码流包数量,历史遗留接口。 + +- MPP_DEC_GET_VPUMEM_USED_COUT + +命令参数为RK_U32\*,用于外部应用获取MPP使用的MppBuffer数量,历史遗留接口。 + +- MPP_DEC_SET_VC1_EXTRA_DATA + +暂未实现,历史遗留接口。 + +- MPP_DEC_SET_OUTPUT_FORMAT + +命令参数为MppFrameFormat,用于外部应用配置JPEG解码器的输出格式,默认不使用。 + +- MPP_DEC_SET_DISABLE_ERROR + +命令参数为RK_U32\*,用于关闭MPP解码器的错误处理。一旦使能,MPP解码会无视码流的错误情况,输出全部的可解码图像,同时不对输出的MppFrame结构里的errinfo进行标记。命令调用时机在decode_put_packet之前。 + +- MPP_DEC_SET_IMMEDIATE_OUT + +命令参数为RK_U32\*,用于使能H.264解码器的立即输出模式。一旦使能,H.264解码器会忽略丢帧导致的帧序不连续情况,立即输出解码的图像。命令调用时机在decode_put_packet之前。 + +- MPP_DEC_SET_ENABLE_FAST_PLAY + +命令参数为FastPlayMode\*,用于使能H.264解码器的快速起播,不必等到dpb full之后出帧。如果当前帧在I帧之后解码,但在I帧之前显示,可能会出现丢帧的情况。命令调用时机在decode_put_packet之前。 + +### 3.2.2 reset + +reset接口用于把解码器恢复为正常初始化后的状态。 + +当用户发送最后一包MppPacket码流,并置上EOS标记送入解码器,解码器在处理完这最后一包数据之后会进入EOS的状态,不再接收和处理码流,需要reset之后再才能再继续接收新的码流。 + +## 3.3 解码器使用要点 + +解码器在使用过程中,需要注意的一些重要事项: + +### 3.3.1 解码器单/多线程使用方式 + +MPP解码器的MPI接口是线程安全的,可以在多线环境下使用。单线程工作模式如mpi_dec_test的demo所示,多线程工作模式如mpi_dec_mt_test的demo所示。 + +![](media/Figure12_Decoder_single_thread_usage.png) + +![](media/Figure12_Decoder_multi_thread_usage.png) + +
图表 12 解码器单线程与多线程使用方式
+ +### 3.3.2 图像内存分配以及交互模式 + +解码器在解码图像时,需要获取内存空间以写入数据,在解码完成之后,这块内存空间需要交给用户使用,在用户使用完成之后要释放给解码器,在关闭解码器时要释放全部内存空间。在这种工作方式下,解码器与用户之间才可以形成零拷贝的数据交互。MPP解码器支持三种内存分配以及与用户交互图像数据的模式: + +#### 模式一:纯内部分配模式 + +图像内存直接从MPP解码器内部分配,内存由解码器直接分配,用户得到解码器输出图像,在使用完成之后直接释放。 + +![](media/Figure13_Schematic_diagram_of_pure_internal_allocation_mode.png) +
图表 13 解码器图像内存纯内部分配模式示意图
+ +在这种方式下,用户不需要调用解码器control接口的MPP_DEC_SET_EXT_BUF_GROUP命令,只需要在解码器上报info change时直接调用control接口的MPP_DEC_SET_INFO_CHANGE_READY命令即可。解码器会自动在内部进行内存分配,用户需要把获取到的每帧数据直接释放。 + +![](media/Figure14_Code_flow_of_decoder_image_memory_pure_internal_allocation_mode.png) +
图表 14 解码器图像内存纯内部分配模式代码流程
+ +**优点:** + +过程简单,可以快速完成一个可用的demo,评估解码器的性能。 + +**缺点:** + +1. 内存都是从解码器内部分配的,如果内存在解码器被销毁时还没有被释放,有可能出现内存泄漏或崩溃问题。 +2. 无法控制解码器的内存使用量。解码器可以不受限制地使用内存,如果码流输入的速度很快,用户又没有及时释放内存,解码器会很快消耗掉全部的可用内存。 +3. 实现零拷贝的显示比较困难,因为内存是从解码器内部分配的,不一定和用户的显示系统兼容。 + +#### 模式二:半内部分配模式 + +这种模式是mpi_dec_test demo使用的默认模式。用户需要根据get_frame返回的MppFrame的buf_size来创建MppBufferGroup,并通过control接口的MPP_DEC_SET_EXT_BUF_GROUP配置给解码器。用户可以通过mpp_buffer_group_limit_config接口来限制解码器的内存使用量。 + +![](media/Figure15_Semi-internal_allocation_mode_decoder_work_flow.png) +
图表 15 解码器图像内存半内部分配模式代码流程
+ +**优点:** + +过程简单,易上手,可以一定程度限制内存的使用。 + +**缺点:** + +1. 内存空间的限制并不准确,内存的使用量不是100%固定的,会有波动。 +2. 同样难于实现零拷贝的显示。 + +#### 模式三:纯外部分配模式 + +这种模式通过创建空的external模式的MppBufferGroup,从用户那里导入外部分配器分析的内存块文件句柄(一般是dmabuf/ion/drm)。在Android平台上,Mediaserver通过gralloc从SurfaceFlinger获取显示用内存,把gralloc得到的文件句柄提交(commit)到MppBufferGroup里,再把MppBufferGroup通过control接口MPP_DEC_SET_EXT_BUF_GROUP命令配置给解码器,然后MPP解码器将循环使用gralloc得到的内存空间。 + +![](media/Figure16_Schematic_diagram_of_pure_external_allocation_mode.png) +
图表 16 解码器图像内存纯外部分配模式示意图
+ +![](media/Figure17_Pure_external_allocation_mode_decoder_work_flow.png) +
图表 17 解码器图像内存纯外部分配模式代码流程
+ +**优点:** + +直接使用外部显示用的内存,容易实现零拷贝。 + +**缺点:** + +1. 理解与使用较困难。 +2. 需要修改用户程序,一些用户程序的调用方式限制了纯外部分配方式的使用。 + +**纯外部分配模式使用时的注意事项:** + +1. 如果图像内存分配是在解码器创建之前,需要有额外的方式来得到图像内存的大小。 + +一般的YUV420图像内存空间计算方法: + +图像像素数据:hor_stride \* ver_stride \* 3 / 2 +额外附加信息:hor_stride \* ver_stride / 2 + +2. 内存块数需要考虑解码和显示的需求,如果内存块数分配得太少,可能会卡住解码器。 + +H.264/H.265这类参考帧较多的协议需要20+内存块能保证一定能解码。其它协议需要10+内存块能保证一定能解码。 + +3. 如果在码流解码过程中发生了info change,需要把已有的MppBufferGroup进行reset,再commit进新的图像缓存,同时外部的显示也需要相应调整。 + + +## 3.4 编码器数据流接口 + +编码器接口为用户提供了输入图像,输出码流的功能,接口函数为MppApi结构体里的encode_put_frame函数, encode_get_packet函数和encode函数。这组函数提供了简洁的编码功能支持。 + +### 3.4.1 encode_put_frame + +| 接口定义 | MPP_RET encode_put_frame(MppCtx ctx, MppFrame frame) | +|----------|------------------------------------------------------| +| 输入参数 | ctx :MPP解码器实例 frame :待输入的图像数据 | +| 返回参数 | 运行错误码 | +| 功能 | 输入frame图像数据给ctx指定的MPP编码器实例 | + +#### 函数的工作模式 + +由于编码器的输入图像一般都比较大,如果进行拷贝,效率会大幅度下降,所以编码器的输入函数需要等待编码器硬件完成对输入图像内存的使用,才能把输入函数返回,把使用后的图像归还给调用者。基于以上的考虑,encode_put_frame是阻塞式函数,会把调用者阻塞住,直到输入图像使用完成,会一定程度上导致软硬件运行无法并行,效率下降。 + +#### 拷贝与零拷贝输入 + +编码器的输入不支持CPU分配的空间,如果需要支持编码CPU分配的地址,需要分配MppBuffer并把数据拷贝进去,这样做会很大程度影响效率。编码器更喜欢dmabuf/ion/drm内存形式的输入,这样可以实现零拷贝的编码,额外的系统开销最小。 + +### 3.4.2 encode_get_packet + +| 接口定义 | MPP_RET encode_get_packet(MppCtx ctx, MppPacket \*packet) | +|----------|------------------------------------------------------------| +| 输入参数 | ctx :MPP解码器实例 packet :用于获取MppPacket实例的指针。 | +| 返回参数 | 运行错误码 | +| 功能 | 从ctx指定的MPP编码器实例里获取完成编码的packet描述信息。 | + +#### 取头信息与图像数据 + +以H.264编码器为例,编码器的输出数据分为头信息(sps/pps)和图像数据(I/P slice)两部分,头信息需要通过control接口的MPP_ENC_GET_EXTRA_INFO命令获取,图像数据则是通过encode_get_packet接口来获取。获取的时机是在control接口的SET_RC_CFG/SET_PREP_CFG/SET_CODEC_CFG参数配置命令完成之后。在参数配置命令调用时,编码器会进行各个参数的更新,在更新全部完成之后,调用MPP_ENC_GET_EXTRA_INFO获取到的头信息才是最新的。 + +#### H.264编码器输出码流的格式 + +目前硬件固定输出带00 00 00 01起始码的码流,所以encode_get_packet函数获取到码流都是带有00 00 00 01起始码。如果需要去掉起始码,可以从起始码之后的地址进行拷贝。 + +#### 码流数据的零拷贝 + +由于使用encode_put_frame和encode_get_packet接口时没有提供配置输出缓存的方法,所以使用encode_get_packet时一定会进行一次拷贝。一般来说,编码器的输出码流相对于输入图像不算大,数据拷贝可以接受。如果需要使用零拷贝的接口,需要使用enqueue/dequeue接口以及MppTask结构。 + +### 3.4.3 encode + +暂未实现 + +## 3.5 编码器控制接口 + +编码器与解码器不同,需要用户进行一定的参数配置。编码器需要用户通过control接口配置编码器信息之后才可以进行编码工作。 + +### 3.5.1 control与MppEncCfg + +MPP推荐使用封装后的MppEncCfg结构通过control接口的MPP_ENC_SET_CFG/MPP_ENC_GET_CFG命令来进行编码器信息配置。 + +由于编码器可配置的选项与参数繁多,使用固定结构体容易出现接口结构体频繁变化,导致接口二进制兼容性无法得到保证,版本管理复杂,极大增加维护量。 + +为了缓解这个问题MppEncCfg使用(void \*)作为类型,使用<字符串-值>进行key map式的配置,函数接口分为s32/u32/s64/u64/ptr,对应的接口函数分为set与get两组,如下: + +```c +配置编码器信息: +MPP_RET mpp_enc_cfg_set_s32(MppEncCfg cfg, const char *name, RK_S32 val); +MPP_RET mpp_enc_cfg_set_u32(MppEncCfg cfg, const char *name, RK_U32 val); +MPP_RET mpp_enc_cfg_set_s64(MppEncCfg cfg, const char *name, RK_S64 val); +MPP_RET mpp_enc_cfg_set_u64(MppEncCfg cfg, const char *name, RK_U64 val); +MPP_RET mpp_enc_cfg_set_ptr(MppEncCfg cfg, const char *name, void *val); +MPP_RET mpp_enc_cfg_set_st(MppEncCfg cfg, const char *name, void *val); +获取编码器信息: +MPP_RET mpp_enc_cfg_get_s32(MppEncCfg cfg, const char *name, RK_S32 *val); +MPP_RET mpp_enc_cfg_get_u32(MppEncCfg cfg, const char *name, RK_U32 *val); +MPP_RET mpp_enc_cfg_get_s64(MppEncCfg cfg, const char *name, RK_S64 *val); +MPP_RET mpp_enc_cfg_get_u64(MppEncCfg cfg, const char *name, RK_U64 *val); +MPP_RET mpp_enc_cfg_get_ptr(MppEncCfg cfg, const char *name, void **val); +MPP_RET mpp_enc_cfg_get_st(MppEncCfg cfg, const char *name, void *val); +``` + + +字符串一般用\[类型:参数\]的方式进行定义,可支持的字符串与参数类型如下: + +| 参数字串 | 接口 | 实际类型 | 描述说明 | +| ----------------------- | ---- | ----------------------------------- | ------------------------------------------------------------ | +| base:low_delay | S32 | RK_S32 | 表示低延时输出模式。 0 – 表示关闭;1 – 表示开启。 | +| rc:mode | S32 | MppEncRcMode | 表示码率控制模式,目前支持CBR、VBR和AVBR三种: CBR为Constant Bit Rate,固定码率模式。 在固定码率模式下,目标码率起决定性作用。 VBR为Variable Bit Rate,可变码率模式。 在可变码率模式下,最大最小码率起决定性作用。 AVBR为Adaptive Variable Bit Rate,自适应码率模式。 在自适应码率模式下,静止场景中最小码率起决定性作用,运动场景中最大码率起决定性作用。最终平均码率将接近目标码率。 FIX_QP为固定QP模式,用于调试和性能评估。 ![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcMode.png) | +| rc:bps_target | S32 | RK_S32 | 表示CBR模式下的目标码率。 | +| rc:bps_max | S32 | RK_S32 | 表示VBR/AVBR模式下的最高码率。 | +| rc:bps_min | S32 | RK_S32 | 表示VBR/AVBR模式下的最低码率。 | +| rc:fps_in_flex | S32 | RK_S32 | 表示输入帧率是否可变的标志位,默认为0。 为0表示输入帧率固定,帧率计算方式为: fps_in_num / fps_in_denom,可以表示分数帧率。 为1表示输入帧率可变。可变帧率的情况下,帧率不固定,对应的码率计算与分配的规则变为按实际时间进行计算。 | +| rc:fps_in_num | S32 | RK_S32 | 表示输入帧率分数值的分子部分,默认值为30。 | +| rc:fps_in_denom | S32 | RK_S32 | 表示输入帧率分数值的分母部分,默认值为1。 | +| rc:fps_out_flex | S32 | RK_S32 | 表示输出帧率是否可变的标志位,默认为0。 为0表示输出帧率固定,帧率计算方式为: fps_out_num / fps_out_denom,可以表示分数帧率。 为1表示输出帧率可变。可变帧率的情况下,帧率不固定,对应的码流输出时间按实际时间进行计算。 | +| rc:fps_out_num | S32 | RK_S32 | 表示输出帧率分数值的分子部分,默认值为30。 | +| rc:fps_out_denom | S32 | RK_S32 | 表示输出帧率分数值的分母部分,默认值为1。 | +| rc:gop | S32 | RK_S32 | 表示Group Of Picture,即两个I帧之间的间隔,含义如下: 0 – 表示只有一个I帧,其他帧均为P帧。 1 – 表示全为I帧。 2 – 表示序列为I P I P I P… 3 – 表示序列为I P P I P P I P P… 一般情况下,gop应配置为输出帧率的整数倍,默认值为两倍输出帧率。 | +| rc:max_reenc_times | U32 | RK_U32 | 表示一帧图像最大重编码次数,默认值为1。在低延时输出模式下,max_reenc_times只能配置为0。 | +| rc:priority | U32 | MppEncRcPriority | 表示超大帧重编优先级。 0 – 表示目标码率优先。 1 – 表示超大帧阈值优先。 此优先级只在超大帧重编时有效。 ![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcPriority.png) | +| rc:drop_mode | U32 | MppEncRcDropFrmMode | 表示丢帧模式。 0 – 表示丢帧模式未使能。 1 – 表示正常丢帧模式。当瞬时码率超过丢帧阈值时,正常丢帧。 2 – 表示pskip构造模式。当瞬时码率超过丢帧阈值时,编码pskip帧替代当前帧。 ![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcDropFrmMode.png) | +| rc:drop_thd | U32 | RK_U32 | 表示丢帧阈值控制变量,默认值为20。丢帧阈值计算公式为: bps_max \* (1 + drop_thd / 100)。 | +| rc:drop_gap | U32 | RK_U32 | 表示最大允许连续丢帧数。当输出码流的poc_type为2时,drop_gap只能配置为1。 | +| rc:max_i_prop | S32 | RK_S32 | 表示最大 IP 比例,用于钳位IP比例的范围,默认值为30。当max_i_proportion被调整较小时,会导致I帧模糊,P 帧清晰。 | +| rc:min_i_prop | S32 | RK_S32 | 表示最小 IP 比例,用于钳位IP比例的范围,默认值为10。当min_i_proportion被调整较大时,会导致I帧清晰,P 帧模糊。 | +| rc:init_ip_ratio | S32 | RK_S32 | 表示初始IP比例,默认值为160。IP比例表示I帧和P帧的bits数的比例,有效范围为\[160, 640\]。 | +| rc:super_mode | U32 | MppEncRcSuperFrameMode | 表示超大帧处理模式。 0 – 表示无特殊策略。 1 – 表示丢弃超大帧。 2 – 表示重编超大帧。
![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcSuperFrameMode.png) | +| rc:super_i_thd | U32 | RK_U32 | 表示超大I帧阈值。 | +| rc:super_p_thd | U32 | RK_U32 | 表示超大P帧阈值。 | +| rc:debreath_en | U32 | RK_U32 | 表示去除呼吸效应使能标志。 0 – 表示关闭;1 – 表示开启。 | +| rc:debreath_strength | U32 | RK_U32 | 表示去除呼吸效应强度调节参数,有效范围为\[0, 35\]。值越大,呼吸效应改善会越弱;值越小,呼吸效应改善越明显。 | +| rc:qp_init | S32 | RK_S32 | 表示初始QP值。 | +| rc:qp_min | S32 | RK_S32 | 表示P、B帧的最小QP值。 | +| rc:qp_max | S32 | RK_S32 | 表示P、B帧的最大QP值。 | +| rc:qp_min_i | S32 | RK_S32 | 表示I帧的最小QP值。 | +| rc:qp_max_i | S32 | RK_S32 | 表示I帧的最大QP值。 | +| rc:qp_step | S32 | RK_S32 | 表示相临两帧之间的帧级QP变化幅度。目前仅配备于RV1109/RV1126系统芯片,默认值为4。 | +| rc:qp_ip | S32 | RK_S32 | 表示I帧和P帧的QP差值,有效范围为\[0, 8\]。 | +| rc:qp_vi | S32 | RK_S32 | 表示虚拟I帧和P帧的QP差值,有效范围为\[0, 6\]。 | +| rc:hier_qp_en | S32 | RK_S32 | 表示QP分层使能标识。 0 – 表示关闭;1 – 表示开启。 | +| rc:hier_qp_delta | St | RK_S32 \* | 表示各层帧相对于第0层P帧的QP差值,层数为4,用数组存储。 | +| rc:hier_frame_num | St | RK_S32 \* | 表示各层帧数,层数为4,用数组存储。 | +| rc:stats_time | S32 | RK_S32 | 表示瞬时码率统计时间,单位为秒,有效范围为\[1, 60\]。默认值为3。 | +| prep:width | S32 | RK_S32 | 表示图像水平方向像素数,单位为像素个数。 | +| prep:height | S32 | RK_S32 | 表示图像垂直方向像素数,单位为像素个数。 | +| prep:format | S32 | MppFrameFormat | 表示图像色彩空间格式以及内存排布方式。 ![](media/Rockchip_Developer_Guide_MPP/MPP_MppFrameFormat.png) | +| prep:hor_stride | S32 | RK_S32 | 表示图像垂直方向相邻两行之间的距离,单位为byte数。 | +| prep:ver_stride | S32 | RK_S32 | 表示图像分量之间的以行数间隔数,单位为1。 | +| prep:colorspace | S32 | MppFrameColorSpace | 表示VUI信息中色域空间类型,用于colour_primaries和transfer_characteristics的备注。 | +| prep:colorprim | S32 | MppFrameColorPrimaries | 表示VUI信息中colour_primaries参数,具体含义请参考H.264/H.265协议。 | +| prep:colortrc | S32 | MppFrameColorTransferCharacteristic | 表示VUI信息中transfer_characteristics参数,具体含义请参考H.264/H.265协议。 | +| prep:colorrange | S32 | MppFrameColorRange | 表示YUV转RGB的色彩范围。 0 – 表示未指定,由MPP配置。 1 – 表示码流格式为MPEG,限制色彩范围。 2 – 表示码流格式为JPEG,不限制色彩范围。 ![](media/Rockchip_Developer_Guide_MPP/MPP_MppFrameColorRange.png) | +| prep:range | S32 | MppFrameColorRange | 同prep:colorrange,用于前向兼容MPP版本。 | +| prep:rotation | S32 | MppEncRotationCfg | 表示图像旋转属性,默认值为0。除了RK3588芯片,其他芯片均不支持FBC数据结构的旋转操作。 0 – 表示图像不旋转。 1 – 表示图像逆时针旋转90度。 2 – 表示图像逆时针旋转180度。 3 – 表示图像逆时针旋转270度。 | +| prep:mirroring | S32 | RK_S32 | 表示图像镜像属性,默认值为0。除了RK3588芯片,其他芯片均不支持FBC数据结构的镜像操作。 0 – 表示图像不做镜像。 1 – 表示图像做水平镜像。 2 – 表示图像做垂直镜像。 | +| codec:type | S32 | MppCodingType | 表示MppEncCodecCfg对应的协议类型,需要与MppCtx初始化函数mpp_init的参数一致。 ![](media/Rockchip_Developer_Guide_MPP/MPP_MppCodingType.png) | +| h264:stream_type | S32 | RK_S32 | 表示H.264码流格式类型。 0 – 表示Annex-B格式,即用00 00 00 01的起始码对齐、分割码流数据。 1 – 表示AVCC格式,仅支持extradata中码流的解析。 目前MPP内部固定为带00 00 00 01起始码的格式。 | +| h264:profile | S32 | RK_S32 | 表示SPS中的profile_idc参数。 ![](media/Rockchip_Developer_Guide_MPP/MPP_H264Profile.png) | +| h264:level | S32 | RK_S32 | 表示SPS中的level_idc参数,其中10表示level 1.0: 10/11/12/13 – qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps 20/21/22 – cif@30fps / half-D1@25fps / D1@12.5fps 30/31/32 – D1@25fps / 720p@30fps / 720p@60fps 40/41/42 – 1080p@30fps / 1080p@30fps / 1080p@60fps 50/51/52 – 4K@30fps / 4K@30fps / 4K@60fps 一般配置为level 4.1即可满足要求。 | +| h264:poc_type | U32 | RK_U32 | 表示SPS中的pic_order_cnt_type参数。 | +| h264:log2_max_poc_lsb | U32 | RK_U32 | 表示SPS中的log2_max_pic_order_cnt_lsb_minus4参数,只在pic_order_cnt_type为0时使用。 | +| h264:log2_max_frm_num | U32 | RK_U32 | 表示SPS中的log2_max_frame_num_minus4参数。 | +| h264:gaps_not_allowed | U32 | RK_U32 | 表示SPS中的gaps_in_frame_num_value_allowed_flag参数的非。 | +| h264:cabac_en | S32 | RK_S32 | 表示编码器使用的熵编码格式。 0 – 表示CAVLC,自适应变长编码。 1 – 表示CABAC,自适应算术编码。 | +| h264:cabac_idc | S32 | RK_S32 | 表示H.264协议中的cabac_init_idc参数,只在cabac_en为1时使用,有效范围为\[0, 2\]。 | +| h264:trans8x8 | S32 | RK_S32 | 表示H.264协议中transform_8x8_mode_flag参数,即8x8变换的使能标志。 0 – 表示关闭,在Baseline/Main profile时固定关闭。 1 – 表示开启,在High profile时可选开启。 | +| h264:const_intra | S32 | RK_S32 | 表示H.264协议中constrained_intra_pred_flag参数,即 constrained_intra_pred_mode模式使能标志。 0 – 表示关闭;1 – 表示开启。 | +| h264:scaling_list | S32 | RK_S32 | 表示H.264协议中scaling_list_matrix模式。 0 – 表示flat matrix;1 – 表示默认matrix。 | +| h264:cb_qp_offset | S32 | RK_S32 | 表示H.264协议中chroma_qp_index_offset参数,即应添加到QPY和QSY的偏移量,用于寻址Cb色度分量的QPC表,有效范围为\[-12, 12\]。 | +| h264:cr_qp_offset | S32 | RK_S32 | 表示H.264协议中second_chroma_qp_index_offset参数,即应添加到QPY和QSY的偏移量,用于寻址Cr色度分量的QPC表,有效范围为\[-12, 12\]。 | +| h264:dblk_disable | S32 | RK_S32 | 表示H.264协议中deblocking_filter_control_present_flag参数,即deblock禁用标志,有效范围为\[0, 2\]。
0 – deblocking开启。
1 – deblocking关闭。
2 – 在slice边界关闭deblocking。 | +| h264:dblk_alpha | S32 | RK_S32 | 表示H.264协议中slice_alpha_c0_offset_div2参数,有效范围为\[-6, 6\]。 | +| h264:dblk_beta | S32 | RK_S32 | 表示H.264协议中slice_beta_offset_div2参数,有效范围为\[-6, 6\]。 | +| h264:qp_init | S32 | RK_S32 | 表示初始QP值,同rc:qp_init,用于前向兼容MPP版本。 | +| h264:qp_max | S32 | RK_S32 | 表示P、B帧的最大QP值,同rc:qp_max,用于前向兼容MPP版本。 | +| h264:qp_min | S32 | RK_S32 | 表示P、B帧的最小QP值,同rc:qp_min,用于前向兼容MPP版本。 | +| h264:qp_max_i | S32 | RK_S32 | 表示I帧的最大QP值,同rc:qp_max_i,用于前向兼容MPP版本。 | +| h264:qp_min_i | S32 | RK_S32 | 表示I帧的最小QP值,同rc:qp_min_i,用于前向兼容MPP版本。 | +| h264:qp_step | S32 | RK_S32 | 表示相临两帧之间的帧级QP变化幅度,同rc:qp_step,用于前向兼容MPP版本。 | +| h264:qp_delta_ip | S32 | RK_S32 | 表示I帧和P帧的QP差值,同rc:qp_ip,用于前向兼容MPP版本。 | +| h264:max_tid | S32 | RK_S32 | 表示最大时序层ID。 | +| h264:max_ltr | S32 | RK_S32 | 表示最大长期参考帧数。 | +| h264:prefix_mode | S32 | RK_S32 | 表示添加prefix nal的使能标志。 0 – 表示关闭。 1 – 表示开启,在SEI信息和硬件编码的码流数据之间添加prefix nal。 | +| h264:base_layer_pid | S32 | RK_S32 | 表示基准层优先级ID。 | +| h264:constraint_set | U32 | RK_U32 | 表示SPS中的constraint_set0_flag至constraint_set5_flag参数。 | +| h265:profile | S32 | RK_S32 | 表示VPS中的profile_idc参数。目前MPP内部固定为1,Main profile。 | +| h265:level | S32 | RK_S32 | 表示VPS中的level_idc参数。 | +| h265:scaling_list | S32 | RK_S32 | 表示H.265协议中scaling_list_matrix模式。 0 – 表示flat matrix,1 – 表示默认matrix。 | +| h265:cb_qp_offset | S32 | RK_S32 | 表示H.265协议中chroma_qp_index_offset参数,即应添加到QPY和QSY的偏移量,用于寻址Cb色度分量的QPC表,有效范围为\[-12, 12\]。 | +| h265:cr_qp_offset | S32 | RK_S32 | 表示H.265协议中second_chroma_qp_index_offset参数,即应添加到QPY和QSY的偏移量,用于寻址Cr色度分量的QPC表,有效范围为\[-12, 12\]。 | +| h265:dblk_disable | S32 | RK_S32 | 表示H.265协议中deblocking_filter_control_present_flag参数,即deblock禁用标志,有效范围为\[0, 2\]。
0 – deblocking开启。
1 – deblocking关闭。
2 – 在slice边界关闭deblocking。 | +| h265:dblk_alpha | S32 | RK_S32 | 表示H.265协议中slice_alpha_c0_offset_div2参数,有效范围为\[-6, 6\]。 | +| h265:dblk_beta | S32 | RK_S32 | 表示H.265协议中slice_beta_offset_div2参数,有效范围为\[-6, 6\]。 | +| h265:qp_init | S32 | RK_S32 | 表示初始QP值,同rc:qp_init,用于前向兼容MPP版本。 | +| h265:qp_max | S32 | RK_S32 | 表示P、B帧的最大QP值,同rc:qp_max,用于前向兼容MPP版本。 | +| h265:qp_min | S32 | RK_S32 | 表示P、B帧的最小QP值,同rc:qp_min,用于前向兼容MPP版本。 | +| h265:qp_max_i | S32 | RK_S32 | 表示I帧的最大QP值,同rc:qp_max_i,用于前向兼容MPP版本。 | +| h265:qp_min_i | S32 | RK_S32 | 表示I帧的最小QP值,同rc:qp_min_i,用于前向兼容MPP版本。 | +| h265:qp_step | S32 | RK_S32 | 表示相临两帧之间的帧级QP变化幅度,同rc:qp_step,用于前向兼容MPP版本。 | +| h265:qp_delta_ip | S32 | RK_S32 | 表示I帧和P帧的QP差值,同rc:qp_ip,用于前向兼容MPP版本。 | +| h265:sao_luma_disable | S32 | RK_S32 | 表示H.265协议中slice_sao_luma_flag参数的非,即当前slice亮度分量的采样点自适应偏移的禁用标志。
0 – 亮度分量的SAO开启。
1 – 亮度分量的SAO关闭。 | +| h265:sao_chroma_disable | S32 | RK_S32 | 表示H.265协议中slice_sao_chroma_flag参数的非,即当前slice色度分量的采样点自适应偏移的禁用标志。
0 – 色度分量的SAO开启。
1 – 色度分量的SAO关闭。 | +| vp8:qp_init | S32 | RK_S32 | 表示初始QP值,同rc:qp_init,用于前向兼容MPP版本。 | +| vp8:qp_max | S32 | RK_S32 | 表示P、B帧的最大QP值,同rc:qp_max,用于前向兼容MPP版本。 | +| vp8:qp_min | S32 | RK_S32 | 表示P、B帧的最小QP值,同rc:qp_min,用于前向兼容MPP版本。 | +| vp8:qp_max_i | S32 | RK_S32 | 表示I帧的最大QP值,同rc:qp_max_i,用于前向兼容MPP版本。 | +| vp8:qp_min_i | S32 | RK_S32 | 表示I帧的最小QP值,同rc:qp_min_i,用于前向兼容MPP版本。 | +| vp8:qp_step | S32 | RK_S32 | 表示相临两帧之间的帧级QP变化幅度,同rc:qp_step,用于前向兼容MPP版本。 | +| vp8:qp_delta_ip | S32 | RK_S32 | 表示I帧和P帧的QP差值,同rc:qp_ip,用于前向兼容MPP版本。 | +| vp8:disable_ivf | S32 | RK_S32 | 表示ivf封装的禁用标志,禁用后硬件编码的码流数据不封装成ivf格式。
0 – 表示开启;
1 – 表示关闭。 | +| jpeg:quant | S32 | RK_S32 | 表示JPEG编码器使用的量化参数等级,编码器一共内置了11级量化系数表格,从0到10,图像质量从差到好。 | +| jpeg:qtable_y | Ptr | RK_U8 \* | 表示样本亮度分量量化表,大小为64,用数组存储。 | +| jpeg:qtable_u | Ptr | RK_U8 \* | 表示样本色度分量u量化表,大小为64,用数组存储。 | +| jpeg:qtable_v | Ptr | RK_U8 \* | 表示样本色度分量v量化表,大小为64,用数组存储。 | +| jpeg:q_factor | S32 | RK_S32 | 表示量化表因子,有效范围为\[1, 99\]。qfactor 越大,量化表中的量化系数越小,得到的图像质量更好,但编码压缩率更低。同理,qfactor 越小,量化表中的量化系数越大,编码压缩率更高,但得到的图像质量更差。默认值为80。 | +| jpeg:qf_max | S32 | RK_S32 | 表示量化表因子最大值,默认值为99。 | +| jpeg:qf_min | S32 | RK_S32 | 表示量化表因子最小值,默认值为1。 | +| split:mode | U32 | MppEncSplitMode | 表示H.264/H.265协议的slice切分模式 ![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncSplitMode.png)
0– 不切分。
1– BY_BYTE 切分 slice 根据 slice 大小。
2– BY_CTU 切分 slice 根据宏块或 CTU 个数。 | +| split:arg | U32 | RK_U32 | Slice切分参数: 在BY_BYTE模式下,参数表示每个slice的最大大小。 在BY_CTU模式下,参数表示每个slice包含的宏块或CTU个数。 | + +其他的字符串与参数会进行后续扩展。 + +### 3.5.2 control其他命令 + +在定义于rk_mpi_cmd.h文件的MpiCmd枚举类型定义了control接口命令字,其中与编码器和编码过程相关的命令如下: + +![](media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type_related_to_MPP.png) + +从MPP_ENC_CMD_BASE到MPP_ENC_CMD_END之间的命令为编码器的control接口命令,其中配置命令的MPP_ENC_SET/GET\_ CFG已经做为基本的配置命令在3.5.1进行了介绍。剩下的命令在下面进行简要的介绍,其中的命令与编码器硬件相关,只有部分硬件支持。 + +目前MPP支持的编码器硬件分为vepu系列和rkvenc系列,vepu系列支持H.264编码,vp8编码和jpeg编码,配备于绝大多数RK芯片中。rkvenc系列只支持H.264编码,目前只配备于RV1109/RV1126系统芯片,其支持的编码功能相对于vepu系统会更多更强。 + +部分CMD命令简要说明: + +- ~~MPP_ENC_SET_PREP_CFG/ MPP_ENC_GET_PREP_CFG~~ + +- ~~MPP_ENC_SET_RC_CFG/ MPP_ENC_GET_RC_CFG~~ + +- ~~MPP_ENC_SET_CODEC_CFG/ MPP_ENC_GET_CODEC_CFG~~ + +废弃命令,为了前向兼容保留,不要使用 + +- MPP_ENC_SET_IDR_FRAME + +无命令参数,用于向编码器请求I帖,编码器收到请求之后,会将待编码的下一帧编码为IDR帧。 + +全部硬件都支持。 + +- ~~MPP_ENC_SET_OSD_LEGACY_0~~ + +- ~~MPP_ENC_SET_OSD_LEGACY_1~~ + +- ~~MPP_ENC_SET_OSD_LEGACY_2~~ + +废弃命令,前向兼容用保留,不要使用 + +- MPP_ENC_GET_HDR_SYNC/ ~~MPP_ENC_GET_EXTRA_INFO~~ + +用于单独获取码流头数据的命令,其中MPP_ENC_GET_EXTRA_INFO为旧命令,不推荐使用。 + +MPP_ENC_GET_HDR_SYNC输入参数为MppPacket,需要外部用户分配好空间并封装为MppPacket再control到编码器,control接口调用返回时就完成了数据拷贝,线程安全。调用时机在编码器基本配置完成之后。需要用户手动释放之前分配的MppPacket。 + +MPP_ENC_GET_EXTRA_INFO输入参数为MppPacket\*,会获取编码器的内部MppPacket来进行访问。调用时机在编码器基本配置完成之后。需要注意的是,这里得到的MppPacket是MPP的内部空间,不需要用户释放。 + +由于在多线程情况下,MPP_ENC_GET_EXTRA_INFO命令获取的MppPacket有可能在读取时被其他control修改,所以这个命令并不是线程安全的,仅做为旧vpu_api的兼容用,不要再使用。 + +- ~~MPP_ENC_SET_SEI_CFG/MPP_ENC_GET_SEI_DATA~~ + +废弃命令,前向兼容用保留,不要使用 + +- ~~MPP_ENC_PRE_ALLOC_BUFF/ MPP_ENC_SET_QP_RANGE/ MPP_ENC_SET_ROI_CFG/ MPP_ENC_SET_CTU_QP~~ + +废弃命令,前向兼容用保留,不要使用 + +- MPP_ENC_GET_RC_API_ALL + +获取MPP目前支持的码率控制策略API信息的接口,输入 RcApiQueryAll\*指针,在返回时填充好结构体内容 + +- MPP_ENC_GET_RC_API_BY_TYPE + +获取指定MppCodingType类型的所有码率控制策略API信息,输入RcApiQueryType\*指针并指定MppCodingType,在返回时会填充好结构体内容。 + +- MPP_ENC_SET_RC_API_CFG + +注册外部码率控制策略API,输入RcImplApi\*指针,该结构中的函数指针定义了码率控制策略插件的行为,注册之后的码率控制策略才可以被查询和激活使用。 + +- MPP_ENC_GET_RC_API_CURRENT + +返回当前使用的码率控制策略API信息,输入RcApiBrief\*指针,在返回时会填充好结构体内容。 + +- MPP_ENC_SET_RC_API_CURRENT + +激活指定名字的码率控制策略API,输入RcApiBrief\*指针,编码器会搜索到RcApiBrief中指定字符串名字的码率控制策略API并激活为当前码率控制策略。 + +- MPP_ENC_SET_HEADER_MODE/MPP_ENC_GET_HEADER_MODE + +配置和获取H.264/H.265编码器的SEI调试信息输出方式,调试用开关,以后会被环境变量取代,不要使用。 + +- MPP_ENC_SET_SPLIT/MPP_ENC_GET_SPLIT + +配置和获取H.264/H265编码器的slice切分配置信息,己被MppEncCfg中的split:mode和split:arg取代,不要使用 + +- MPP_ENC_SET_REF_CFG + +配置编码器高级参考帧模式,默认不需要配置,在需要配置长期参考帧,短期参考帧参考关系模式时使用,用于配置特殊的参考关系模式。高级接口,文档待完善。 + +- MPP_ENC_SET_OSD_PLT_CFG + +用于配置rkvenc系列硬件的OSD调色板,命令参数为MppEncOSDPlt。一般只在编码开始时配置一次,全编码过程使用统一的调色板。仅RV1109/RV1126系列支持。 + +- MPP_ENC_GET_OSD_PLT_CFG + +用于获取rkvenc系列硬件的OSD调色板,命令参数为MppEncOSDPlt\*。一般不使用 + +- MPP_ENC_SET_OSD_DATA_CFG + +用于配置rkvenc系列硬件的OSD数据,命令参数为MppEncOSDData。需要每帧进行配置,每编码一帧之后需要重新配置。本命令被MppFrame带的MppMeta中的KEY_OSD_DATA进行替代,不再使用。 + +## 3.6 编码器使用要点 + +### 3.6.1 输入图像的宽高与stride + +编码器的输入图像宽高配置需要与图像数据在内存中的排布一致。以1920x1080大小的YUV420图像编码为例,参考`图表 7 `MppFrame重要参数说明的内容,假设有两种情况如下: + +![](media/Figure18_Encoder_input_frame_memory_arrangement_1.png) + +![](media/Figure18_Encoder_input_frame_memory_arrangement_2.png) +
图表 18 编码器输入帧内存排布
+ +上图图情况:亮度分量的宽度为1920,高度为1080,亮度数据与色度数据不直接相接,中间有8行的空行。 + +这种情况下,水平stride为1920,垂直stride为1088,应用需要以1920\*1088\*3/2的大小分配空间并写入数据,使用宽1920,高1080,水平stride 1920,垂直stride 1088的配置即可以正常进行编码。 + +下图情况:亮度分量的宽度为1920,高度为1080,亮度数据与色度数据直接相接,中间没有空行。 + +这种情况下,水平stride为1920,垂直stride为1080,但由于编码器对数据的访问是16对齐的,在读取亮度下边缘数据时会读取到色度部分,读取色度下边缘数据时会读取到色度数据之外的部分,需要用户开出额外的空间,这里的空间为1920\*1080\*3/2+1920\*4的填充,才能保证编码器不出现访问未分配空间的情况。 + +### 3.6.2 编码器控制信息输入方式以及扩展 + +编码器控制信息的输入方式分为两种: + +一种是全局性控制信息,如码率配置,宽高配置等,作用于整个编码器和编码过程;另一种是临时性控制信息,如每帧的OSD配置信息,用户数据信息等,只作用于单帧编码过程。 + +第一类控制信息主要通过control接口来进行配置,第二类控制信息主要是通过MppFrame所带的MppMeta接口来进行配置。 + +今后对控制信息的扩展也会遵循这两种规则来进行扩展。 + +### 3.6.3 编码器输入输出流程 + +目前编码器默认输入接口仅支持阻塞式调用,输出接口支持非阻塞式和阻塞式调用,默认为非阻塞式调用,有可能出现获取数据失败的情况,需要在使用中注意。 + +### 3.6.4 插件式自定义码率控制策略机制 + +MPP支持用户自己定义码率控制策略,码率控制策略接口RcImplApi定义了几个编码处理流程上的钩子函数,用于在指定环节插入用户自定义的处理方法。具体使用方法可以参考默认的H.264/H.265码控策略实现(default_h264e/default_h265e结构)。 + +码控插件机制在MPP中有预留,接口与流程都不算稳定,可以预见将来还会有不少调整,只建议有能力阅读理解代码,以及持续维护更新的用户使用这个机制,一般用户不建议使用。 + +# 第四章 MPP demo说明 + +MPP的demo程序变化比较快,以下说明仅供参考,具体情况以实际运行结果为准。Demo的运行环境均以Android 32bit平台为准。 + +## 4.1 解码器demo + +解码器demo为mpi_dec_test系列程序,包括使用decode_put_packet和decode_get_frame接口的单线程mpi_dec_test、多线程的mpi_dec_mt_test以及多实例的mpi_dec_multi_test。 + +以Android平台上的mpi_dec_test为例进行使用说明。直接运行测试用例mpi_dec_test,可以在日志中打印帮助文档,如下图所示: + +![](media/Rockchip_Developer_Guide_MPP/MPP_print_decode_help.png) + +帮助文档可以分为两部分:一是mpi_dec_test的命令参数说明;二是码流文件的协议类型说明。 + +命令参数的描述说明如下: + +| 命令参数 | 描述说明 | +|----------|-------------------------------------------------| +| -i | 输入的码流文件。 | +| -o | 输出的图像文件。 | +| -w | 图像宽度,单位为像素。 | +| -h | 图像高度,单位为像素。 | +| -t | 码流文件的协议类型。 | +| -f | 图像色彩空间格式以及内存排布方式,默认为NV12。 | +| -n | 最大解码帧数。测试时若码流较长,可仅输出前n帧。 | +| -s | MPP实例数,默认为1。 | +| -v | 日志选项:q为静默标志;f为fps显示标志。 | +| -slt | 输出帧对应的校验文件。 | +| -help | 打开帮助文档。 | + +mpi_dec_test的命令参数中,输入文件(i)和码流类型(t)为强制要求配置的参数,其他参数如输出文件(o)、图像宽度(w)、图像高度(h)和解码帧数(n)等为可选参数,可以根据不同的测试需求进行配置。 + +mpi_dec_test的命令参数中,输出帧对应的校验文件(slt)将输出帧数据转换为对应的循环冗余校验码(具体逻辑见utils/utils.c)。校验文件的大小往往只有几kB,在芯片的slt测试中,将输出帧文件的对比转换成校验文件的对比,可以显著缩短测试周期。 + +MPP库支持的输入文件的编码格式(t)为MPEG2/4、H.263/4/5、VP8/9和JPEG等,id后的数字为不同编码格式对应的参数值。参数值来源于OMX的定义,值得注意的是,HEVC和AVS格式的参数值与其他格式的有显著区别。 + +以目录/data/下的ocrean.h264解码30帧为例,对demo和输出进行说明。运行的命令为: + +```bash + mpi_dec_test -t 7 -i /data/ocrean.h264 -n 30 +``` + +其中,-t 7表示输入码流文件的协议类型是H.264,-i表示输入文件,-n 30表示解码30帧。测试用例正常运行结果如下: + +![](media/Rockchip_Developer_Guide_MPP/MPP_decode_log.png) + +其中,打印的信息里包含了部分命令参数和部分解码日志。 + +MPP库的版本信息: + +``` +I mpp_info: mpp version: 6cc173d1 author: Ding Wei 2022-08-29 [hal_avsd]: Fix crash on avsd ref err path +``` + +`I mpi_dec_test: 0xeebc01c0 decode_get_frame get info changed found` + +为mpi_dec_test本身的打印,表示发现解码器上报了info change事件。 + +`I mpi_dec_test: 0xeebc01c0 decoder require buffer w:h [1920:1080] stride [1920:1088] buf_size 4177920` + +为mpi_dec_test本身的打印,表示解码器请求的图像内存情况。 + +`I mpi_dec_test: 0xf1c40730 decode get frame 0` + +为mpi_dec_test本身的打印,表示解码器在正常解码和输出图像。 + +`I mpi_dec_test: decode 10 frames time 263ms delay 69ms fps 113.99` + +为mpi_dec_test本身的打印,表示解码器解码30帧所用的时间为263ms,解码第一包数据的延迟时间为69ms,帧率为113.99。 + +`I mpi_dec_test: test success max memory 19.92 MB` + +为mpi_dec_test本身的打印,表示解码器完成了解码30帧的功能,最大的内存开销为19.92 MB。 + +解码器的demo具体代码参见test/mpi_dec_test.c。 + +## 4.2 编码器demo + +编码器demo为mpi_enc_test系列程序,包括单线程的mpi_enc_test及多实例的mpi_enc_multi_test。 + +以下以Android平台上的mpi_enc_test为例进行使用说明。直接运行测试用例mpi_enc_test,可以在日志中打印帮助文档,如下图所示: + +![](media/Rockchip_Developer_Guide_MPP/MPP_print_encode_help.png) + +帮助文档可以分为三部分:一是mpi_enc_test的命令参数说明;二是码流文件的协议类型说明;三是图像色彩空间格式以及内存排布方式说明。 + +命令参数的描述说明如下: + +| 命令参数 | 描述说明 | +|------------------------------|-------------------------------------------------------------------------------------------------| +| -i | 输入的图像文件。 | +| -o | 输出的码流文件。 | +| -w | 图像宽度,单位为像素。 | +| -h | 图像高度,单位为像素。 | +| -hstride | 垂直方向相邻两行之间的距离,单位为byte。 | +| -vstride | 图像分量之间的以行数间隔数,单位为1。 | +| -f | 图像色彩空间格式以及内存排布方式,默认为NV12。 | +| -t | 码流文件的协议类型。 | +| -tsrc | 源码流格式,仅在测试整体编解码性能时使用。 | +| -n | 最大解码帧数。测试时若码流较长,可仅输出前n帧。 | +| -g | gop参考模式,对应不同的TSVC码流。 | +| -rc | 码率控制模式。0:VBR; 1:CBR; 2:FIXQP; 3:AVBR。 | +| -bps | 码率约束参数。命令格式:bps_target:bps_min:bps_max。 | +| -fps | 输入/输出帧率控制,默认为30。该命令参数仅说明输入帧率和输出帧率之间的比例关系,与实际帧率无关。 | +| -qc | 质量控制。 | +| -s | MPP实例数,默认为1。 | +| -v | 日志选项:q为静默标志;f为fps显示标志。 | +| -ini | 额外的编码配置文件ini(暂未生效)。 | +| -slt | 输出码流对应的校验文件。 | + +mpi_enc_test的命令参数中,图像宽度(w)、图像高度(h)和码流类型(t)为强制要求配置的参数,其他参数如输入文件(i)、输出文件(o)、编码帧数(n)和色彩空间格式及内存排布方式(f)等为可选参数。如果没有指定输入文件,mpi_enc_test会生成默认的彩条图像进行编码。 + +mpi_enc_test的命令参数提供了多样化的码率控制方案,用户可以通过码率控制模式(rc)和码率约束参数(bps)对输出码流的码率进行控制。码率控制模式(rc)分为可变码率模式(VBR)、固定码率模式(CBR)、qp修正的码率模式(FIXQP)和自适应码率模式(AVBR),默认模式为VBR;码率约束参数(bps)则是为MPP内部配置码率边界提供参考。 + +mpi_enc_test的命令参数中,输入/输出帧率控制(fps)的格式为: + +```bash +-fps fps_in_num:fps_in_den:fps_in_flex/fps_out_num:fps_out_den:fps_out_flex +``` + +其中,in/out分别表示输入/输出;num表示分子;den表示分母;flex为0表示帧率固定,为1表示帧率可变。输入和输出默认的num和den分别为30和1,即默认的输入/输出帧率为30。该命令参数仅说明输入帧率和输出帧率之间的比例关系,与实际帧率无关。 + +mpi_enc_test的命令参数中,质量控制(qc)仅在输出码流格式为H.264、H.265、VP8和JPEG时生效,命令格式为: + +```bash +-qc qp_init/min/max/min_i/max_i +``` + +其中,qp表示质量参数;init表示初值;min表示最小值;max表示最大值;后缀i表示I帧最值,未标注则表示B、P帧最值。 + +mpi_enc_test的命令参数中,日志选项(v)为q时,MPP日常日志关闭;日志选项(v)为f时,每秒会打印一次平均帧率和当前帧率。 + +图像的色彩空间格式分为YUV和RGB两类。MPP支持多种内存排布方式(f),id后的数字为不同内存排布方式对应的参数值,值得注意的是,YUV和RGB格式的参数值有显著区别。 + +以目录/data/下的ocrean.yuv编码30帧为例,对demo和输出进行说明。运行的命令为: + +```bash +mpi_enc_test -w 1920 -h 1080 -t 7 -i /data/ocrean.yuv -o /data/out.h264 -n 30 +``` + +测试用例正常运行结果如下: + +![](media/Rockchip_Developer_Guide_MPP/MPP_encode_log.png) + +在解码器demo中已经介绍的日志略。 + +`I mpp_enc : MPP_ENC_SET_RC_CFG bps 7776000 [486000 : 8262000] fps [30:30] gop 60` + +默认的编码器的码率控制参数,目标码率为7.8Mbps,码率参考下界为0.5Mbps,码率参考上界为8.3Mbps;默认的输入和输出帧率为30;默认gop数为60。 + +`I mpi_enc_test: chn 0 encoded frame 0 size 218616 qp 11` + +为mpi_enc_test本身的打印,表示编码器在正常编码,输出单帧码流大小为0.2M,质量参数为11。 + +`I mpi_enc_test: chn 0 encode 30 frames time 628 ms delay 4 ms fps 47.72 bps 10265048` + +为mpi_enc_test本身的打印,表示编码器编码30帧所用的时间为628 ms,编码第一帧数据的延迟时间为4ms,帧率为47.72,码率为10.2Mbps。 + +`I mpi_enc_test: mpi_enc_test average frame rate 47.72` + +为mpi_enc_test本身的打印,表示编码器编码平均帧率为47.72。 + +编码器的控制参数还可以通过环境变量配置。在android环境下,环境变量配置命令为: + +```bash +setprop <控制参数> value +``` + +在linux环境下,环境变量配置命令为: + +```bash +export <控制参数>=value +``` + +相应的描述说明如下: + +| 控制参数 | 类型 | 描述说明 | +|------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| constraint_set | RK_U32 | 仅对H.264格式的码流生效,对应语法中的constraint_set0_flag至constraint_set5_flag。其中,强制标志force_flag和强制约束参数constraint_force存储格式为:\| 00 \| force_flag \| 00 \| constraint_force \|。 只有低6位生效,对应constraint_set5_flag至constraint_set0_flag,当force_flag为1时,对应的constraint_set将被配置入编码器。 | +| split_mode | RK_U32 | 编码器分片模式。0:不分片; 1:按字节分片; 2:按CTU分片。 | +| split_arg | RK_U32 | 分片大小参数,编码器分片模式开启后生效。按字节分片时,该参数为各片字节上限;按CTU分片时,该参数为各片CTU数上限。 | +| split_out | RK_U32 | 分片输出模式,编码器分片模式开启后生效。1:低延时输出模式; 2:段信息输出模式。低延时输出模式下,编码器输出包内每个片的延时较低;段信息输出模式下,编码器会为每个片封装段信息。 | +| sei_mode | RK_U32 | SEI写入模式。0:不写入SEI; 1:序列写入模式; 2:帧写入模式。序列写入模式下,每个gop只有一个SEI;帧写入模式下,若SEI信息发生改变,则还会在每帧数据前添加SEI。 | +| gop_mode | RK_U32 | gop参考模式。若环境变量gop_mode未配置,则按命令参数配置;否则,按环境变量配置。 | +| osd_enable | RK_U32 | 使能OSD调色板。 | +| osd_mode | RK_U32 | OSD调色板模式,使能OSD调色板后生效。0:默认配置; 1:用户定义配置。 | +| roi_enable | RK_U32 | 使能ROI测试,并根据平台配置默认的roi_type。 | +| roi_type | RK_U32 | 强制配置roi_type。 | +| user_data_enable | RK_U32 | 使能用户数据。 | + +编码器的demo具体代码参见test/mpi_enc_test.c。 + +## 4.3 实用工具 + +MPP提供了一些单元测试用的工具程序,这种程序可以对软硬件平台以及MPP库本身进行测试 + +- mpp_info_test + +用于读取和打印MPP库的版本信息,在反馈问题时,可以把打印出来信息附上。 + +- mpp_buffer_test + +用于测试内核的内存分配器是否正常。 + +- mpp_mem_test + +用于测试C库的内存分配器是否正常。 + +- mpp_runtime_test + +用于测试一些软硬件运行时环境是否正常。 + +- mpp_platform_test + +用于读取和测试芯片平台信息是否正常。 + +# 第五章 MPP库编译与使用 + +## 5.1 下载源代码 + +MPP源代码发布官方地址: + +发布分支为release分支,开发分支为develop分支,默认为开发分支。 + +下载命令:git clone https://github.com/rockchip-linux/mpp.git + +## 5.2 编译 + +MPP源代码编译脚本为cmake,需要依赖2.8.12以上的版本,建议使用3.x版。cmake-3.28版本验证通过。使用高版本的cmake工具可能会产生较多的warning。 + +### 5.2.1 Android平台交叉编译 + +编译Android库需要使用ndk环境,默认脚本使用android-ndk-r16b进行编译。android-ndk-r16b和android-ndk-r25c均验证通过,前者适用于android 14之前的sdk,后者适用于android 14及其之后的sdk。 + +以r16b ndk为例进行说明: + +r16b ndk的下载路径可以在源代码目录下的build/android/ndk_links.md文件里查找。 + +把下载好的ndk解压到/home/pub/ndk/android-ndk-r16b,或者手动修改build/android/目录下env_setup.sh脚本的ANDROID_NDK变量路径。 + +进入build/android/arm/目录,运行make-Android.bash脚本生成编译用Makefile,运行make –j16进行编译。 + +### 5.2.2 Unix/Linux平台编译 + +先配置build/linux/arm/目录下arm.linux.cross.cmake文件里的工具链,再运行make-Makefiles.bash脚本通过cmake生成Makefile,最后运行make –j16进行编译。 + +MPP也支持直接在开发板运行的Debian上编译。 + +# 第六章 常见问题FAQ + +Q:aarch64编译出错,报错为undefined reference to \`__system_property_get'。 + +A:这是google 64bit ndk的问题,其libc.so中缺少一些符号定义,问题情况参见: + + + +解决方法:MPP中已经把对应的libc.so放到build/android/aarch64/fix/目录下,把库拷贝到path_to_ndk/platforms/android-21/arch-arm64/usr/lib/路径下,重新编译即正常。 + +Q:运行时会打印如下这样的内核log,是不是有问题? + +vpu_service_ioctl:1844: error: unknow vpu service ioctl cmd 40086c01 + +A:没有问题,mpp对内核驱动有一些依赖,内核驱动有不同版本的接口,mpp会进行多次尝试。如果遇到尝试失败会进行另外一种接口的尝试。这个打印是尝试失败时打印出来的,只会打印一次,可以忽略这个打印。 + +Q:MPP运行异常如何分析? + +A:首先先分析错误日志,如果出现打开内核设备失败的log,需要先分析内核平台的视频编解码器硬件设备配置文件是否有使能,然后提交问题到redmine上,分析运行环境问题之后,再来分析MPP运行的内部问题。 diff --git a/doc/Rockchip_Developer_Guide_MPP_EN.md b/doc/Rockchip_Developer_Guide_MPP_EN.md new file mode 100644 index 000000000..e52b3b4a2 --- /dev/null +++ b/doc/Rockchip_Developer_Guide_MPP_EN.md @@ -0,0 +1,1080 @@ +# MPP Development Reference + +| Project: | MPP | +| --------- | ----------- | +| Version: | 0.7 | +| Author: | Herman Chen | +| Date: | 10/17/2023 | + +| **Revision** | **Date** | **Description** | **Author** | +| ------------ | ---------- | ------------------------------------------------------------ | --------------------------------------- | +| 0.1 | 04/18/2018 | Initial version | Herman Chen | +| 0.2 | 05/07/2018 | Add decoder control command description, encoder part description and demo part description | Herman Chen | +| 0.3 | 05/22/2018 | Fix some clerical errors and explanation errors, rearrange page numbers | Herman Chen
Xiongbin Xie(精英智通) | +| | 07/08/2019 | Translation | Lily Chen | +| 0.4 | 11/28/2018 | 1、Updated the memory layout instructions of the encoder input image.
2、Correct the encoder flowchart error | Herman Chen
Vyagoo | +| 0.5 | 06/08/2020 | Update encoder new configuration interface, no longer supports RK3188 | Herman Chen | +| 0.6 | 06/11/2020 | Translation | Lily Chen | +| 0.7 | 10/17/2023 | add markdown document | Xueman Ruan
Yandong Lin | +| | | | | +| | | | | + + +# 1.1 Overview + +Media Process Platform (MPP) provided by Rockchip is a general media processing software platform for Rockchip chip series. For applications the MPP platform shields the complex lower-level processing related to chips. Its purpose is to shield the differences between different chips and provide a unified media process interface (MPI) to users. The functions provided by MPP include: + +- video decoding + - H.265 / H.264 / H.263 / AV1 / VP9 / VP8 / AVS2 / AVS / AVS+ / MPEG-4 / MPEG-2 / MPEG-1 / VC1 / MJPEG +- video encoding + - H.265 / H.264 / VP8 / MJPEG +- video processing + - Video copy, zoom, color space conversion, Field video de-interleaving (Deinterlace) + + This document describes the MPP framework and its components, as well as the MPI interface for users. This document is intended for upper-level application developers and technical support staff. + +# 1.2 System framework + +The hierarchical diagram of MPP platform in system architecture is shown below: + +![](media/Figure01_MPP_system_framework.png) +
Figure 1 MPP system framework
+ +- Hardware layer + + Hardware layer is the hardware accelerator module of video encoding and decoding based on Rockchip platform, including vdpu, vepu, rkvdec, rkvenc and other different type hardware accelerators with different functions. + +- Kernel driver layer + +Linux kernel codec hardware driver contains device driver and related MMU, memory, clock, power management module. The supported platforms are mainly Linux kernel version 3.10, 4.4, 4.19, 5.10 and 6.1. MPP libraries depend on kernel drivers. + +- MPP layer + +Userspace MPP layer shields the differences between different operating systems and different chip platforms, and provides a unified MPI interface for upper users. MPP layer includes MPI module, OSAL module, HAL module, Video Decoder / Video Encoder and Video Processing module. + +- Operating system layer + + MPP userspace operating platforms, Linux distributions such as Android and Debian + +- Application layer + +MPP layer can adapt to various middleware by MPI, such as OpenMax and gstreamer, or directly be called by the upper application of customers. + +# 1.3 Supported platform + +## 1.3.1 Software platform + +MPP supports running on different versions of Android platforms and pure Linux platforms. + +It supports Rockchip 3.10, 4.4, 4.19 and 5.10 Linux kernels with vcodec_service device driver and corresponding DTS configuration as requirement. + +## 1.3.2 Hardware platform + +Support different series of Rockchip mainstream chip platforms: + +RK3288 series,RK3368 series,RK3399 series,RK3588 series + +RK30xx series,RK312x series,RK322x series ,RK332x series + +RV1109 / RV1126 series(Note: RV1107/RV1108 will gradually not support anymore) + +# 1.4 Supported function + +There are a lot of great differences when MPP encoding and decoding function is running on the different chip platforms. Please refer to the Multimedia Benchmark of the corresponding chip. + +# 1.5 Attentions + +If you want to quickly understand MPP usage and demo please go to Chapter 4 MPP demo instruction. + +If you want to compile and use MPP code quickly, please go to Chapter 5 compilation and use MPP library For detail MPP design and design principle, please refer to readme.txt in the MPP code root directory, txt documents in doc directory and annotations of header files. + +# Chapter 2 Interface design instruction + +This chapter describes the data structure that directly exposed to users in the process of using MPP and the usage instruction of the data structures. + +Because video encoding, decoding and video processing process need to deal with a large number of data interaction, including bitstream data, image data and memory data and also deal with the cross-relationship between upper application and kernel driver MPP designed MPI interface for interaction with the upper layer. This chapter explains the data structure used in MPI interface and design principle. + +## 2.1 Interface structure overview + +The following figure shows the main data structures used by the MPI interface: + +![](media/Figure02_Data_structure_used_in_MPI_interface.png) +
Figure 2 Data structure used in MPI interface
+ +MppMem is the encapsulation of malloc memory in library C. + +MppBuffer is the encapsulation of dmabuf memory for hardware. + +MppPacket is a one-dimensional buffer encapsulation, which can be generated from MppMem and MapBuffer. It is mainly used to represent bitstream data. + +MppFrame is a two-dimensional frame data encapsulation, which can be generated from MppMem and MapBuffer. It is mainly used to represent image data. + +Using MppPacket and MapFrame the general video encoding and decoding can be accomplished simply and effectively. + +Taking video decoding for example, bitstream at input side assigns the address and size to MppPacket. Input through the put_packet interface, and then get the input image MppFrame through the get_frame interface at the output side. It completes the simplest video decoding process. + +![](media/Figure03_Use_simple_interface_to_realize_video_decoding_EN.png) +
Figure 3 Use simple interface to realize video decoding
+ +MppMeta and MPTask are advanced combination interfaces for input and output tasks which can support complex usage modes such as specified input and output modes. It is occasionally used. + +Note: The above interface data structures are all referenced using void\*handle in order to facilitate extension and forward compatibility. The members mentioned in this paragraph are accessed through interfaces such as mpp_xxx_set/get_xxx. + +## 2.2 Memory structure(MppBuffer) + +MppBuffer is mainly used to describe memory blocks for hardware. It provides functions such as memory block allocate and release, reference counter increase and decrease. So far ion/drm allocators are supported. Several important parameters are listed as follows: + +| Parameter name | Parameter type | Description | +|----------------|----------------|----------------------------------------------------| +| ptr | void \* | Represents virtual address of memory block. | +| size | size_t | Represents size of memory block. | +| fd | int | Represents userspace file handler of memory block. | + +In decoding process the decoded picture buffer usually needs to be recycled in a fixed buffer pool. To achieve this behavior MPP defines MppBufferGroup based on MppBuffer. There are two ways to use them as follows: + +![](media/Figure04_Normal_usage_of_MppBuffer_EN.png) +
Figure 4 Normal usage of MppBuffer
+ +The procedure pseudo code is shown as follows: + +![](media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage_EN.png) + +This method can implement decoder zero-copy output in decoding process (the output frame of decoder is the same as the reference frame used in decoder). But it is not easy to implement zero-copy display (the output frame of decoder may not be displayed directly on the display side). At the same time users are required to know the memory space requirement of the decoder. + +Another way to use MppBufferGroup is to use it as a buffer manager only to manage external imported buffers. Its usage is shown as follows: + +![](media/Figure05_Usage_of_MppBuffer_External_Import_EN.png) +
Figure 5 Usage of MppBuffer External Import
+ +The procedure pseudo code is shown as follows: + +![](media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage_EN.png) + +This procedure can enable decoder to use external buffer, adapt to middleware such as OpenMax / gstreamer, easy to adapt to user upper application. It’s also easy to implement zero-copy display. + +## 2.3 Bitstream structure(MppPacket) + +MppPacket is mainly used to describe the related information of one-dimensional bitstream data, especially the location and length of valid data. Several important parameters of MppPacket are listed below: + +| Parameter name | Parameter type | Description | +|----------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| data | void \* | Represents start address of the buffer space. | +| size | size_t | Represents size of the buffer space. | +| pos | void \* | Represents start address of valid data in the buffer space. | +| length | size_t | Represents length of valid data in the buffer space. If the length changes to 0 after the decode_put_packet call the packet stream is consumed. | + +Their relationship is shown below: + +![](media/Figure06_Important_parameter_description_of_MppPacket_EN.png) +
Figure 6 Important parameter description of MppPacket
+ +The other configuration parameters of MppPacket are listed as follows: + +| Parameter name | Parameter type | Description | +|----------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| pts | RK_U64 | Represents display time stamp(Present Time Stamp) | +| dts | RK_U64 | Represents decoding time stamp(Decoding Time Stamp) | +| eos | RK_U32 | Represents end of stream flag(End Of Stream) | +| buffer | MppBuffer | Represents MppBuffer associated with MppPacket | +| flag | RK_U32 | Represents the flag bits used within MPP, including the following flag:
\#define MPP_PACKET_FLAG_EOS (0x00000001)
\#define MPP_PACKET_FLAG_EXTRA_DATA (0x00000002)
\#define MPP_PACKET_FLAG_INTERNAL (0x00000004)
\#define MPP_PACKET_FLAG_INTRA (0x00000008) | + +MppPacket, as a structure describing one-dimensional memory, needs to be initialized using allocated memory or MppBuffer memory. There are several situations when releasing MppPacket: + +If the external malloc address is configured to MppPacket,the memory will not be released. As shown in the following example. + +![](media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket_EN.png) + +If the MppPacket is generated by copy_init, the memory allocated during the copying process will be released after the copy is completed. As shown in the following example. + +![](media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init_EN.png) + +If MppPacket is generated from MppBuffer, MppBuffer is referenced at the time of MppPacket creation and dereferenced at the time of MppPacket releasing. + +![](media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer_EN.png) + +## 2.4 Image structure(MppFrame) + +MppFrame is mainly used to define the related information of two-dimensional image buffer, the location and length of valid data. Several important parameters of the MppFrame are listed below: + +| Parameter name | Parameter type | Description | +|----------------|----------------|---------------------------------------------------------------------------------------------| +| width | RK_U32 | Represents the number of pixels in horizontal direction, in units of pixels. | +| height | RK_U32 | Represents the number of pixels in vertical direction, in units of pixels. | +| hor_stride | RK_U32 | Represents the distance between two adjacent rows in vertical direction, in units of bytes. | +| ver_stride | RK_U32 | Represents the number of row spacing between image components, in units of 1. | + +![](media/Figure07_Important_parameter_description_of_MppFrame_EN.png) +
Figure 7 Important parameter description of MppFrame
+ +The other configuration parameters of MppFrame are listed below: + +| Parameter name | Parameter type | Description | +|----------------|----------------|-----------------------------------------------| +| mode | RK_U32 | Represents image data frame field properties:
![](media/Rockchip_Developer_Guide_MPP/MPP_image_data_frame_field_properties.png) | +| pts | RK_U64 | Represents display time stamp of image(Present Time Stamp) | +| dts | RK_U64 | Represents Image decoding time stamp(Decoding Time Stamp) | +| eos | RK_U32 | Represents the end stream flag of image(End Of Stream) | +| errinfo | RK_U32 | Represents the image error flag, whether there is decoding error in the image. | +| discard | RK_U32 | Represents the discarding mark of the image. If the reference relation of image decoding does not satisfy the requirement the frame image will be marked as needing to be discarded and not to be displayed. | +| buf_size | size_t | Represents the size of the buffer that the image needs to allocate, which is related to the format of the image and the format of the decoded data. | +| info_change | RK_U32 | If true it represents that the current MppFrame is a descriptive structure for marking changes in bitstream information, indicating changes on width, height, stride or the image format.
Possible reasons for info_change are:
1. Change of image sequence width and height.
2. Image sequence format changes, for example 8 bit to 10 bit.
Once info_change is generated the memory pool used by the decoder needs to be reallocated. | +| fmt | MppFrameFormat | Represents image color space format and memory arrangement: ![](media/Rockchip_Developer_Guide_MPP/MPP_image_colorspace_format_and_memory_arrangement.png) | +| color_range | MppFrameColorRange | Represents the color space range of image data:
YUV full range:0 \~ 255(8bit)
YUV limit range:16 ~ 235(8bit )
![](media/Rockchip_Developer_Guide_MPP/MPP_color_space_range.png) | +| buffer | MppBuffer | Represents the MppBuffer corresponding to the MppFrame. | + +For the decoder the MppFrame is its output information structure. The decoded information (including pixel data, pts, error information and other related information) of the bitstream needs to be brought to the caller within MppFrame structure. The PTS / DTS and EOS flags in the MppFrame are inherited from the corresponding input MppPacket. + +Meanwhile once the resolution of input stream is changed the info_change flag in MppFrame will be set and info_change event will be notified to user who is required to modify the buffer pool. + +## 2.5 Advanced task structure (MppTask) + +When the interface between MppPacket and MppFrame cannot fulfill user’s requirements it is necessary to use MppTask as a data container to fulfill more complex input and output requirements. MppTask needs to be used in conjunction with poll/dequeuer/enqueue interface. Compared with simple process interfaces such as put_packet/get_frame, MppTask has complex process and low efficiency which is the cost of fulfilling complex requirements. + +![](media/Figure08_Use_MppTask_for_input_and_output_EN.png) +
Figure 8 Use MppTask for input and output
+ +MppTask is a structure which can be extended by keyword value (MppMetaKey) and support complex high-level requirements by extending the supported data types. Different keyword data in MppTask can be accessed using mpp_task_meta_set/get_xxx series interface. + +![](media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask_EN.png) +
Figure 9 Data Types and Keyword Types Supported by MppTask
+ +In practical usage we need to get MppTask from the input port of MPP by dequeue interface. Configure data to MppTask through mpp_task_meta_set_xxx series interface, and then enqueue to MPP instance for processing. The output port workflow of MPP is similar. But need to replace the serial interfaces of mpp_task_meta_set_xxx with the serial interfaces of mpp_task_meta_get_xxx to obtain data from MppTask. + +At present the practical encoder interface and MJPEG decoding interface are implemented with MppTask. + +## 2.6 Instance context structure(MppCtx) + +MppCtx is the MPP instance context handle provided to user as decoder or encoder. Users can create MppCtx instance and MppApi structure by mpp_create function, initialize type of encoding or decoding and format by mpp_init function, and then access context by decode_xxx/encode_xx or poll/dequeuer/enqueue function. Finally destroy it by mpp_destroy function at the end of use. + +![](media/Figure10_MppCtx_usage_process.png) +
Figure 10 MppCtx usage process
+ +## 2.7 API structure MppApi(MPI) + +The MppApi structure encapsulates the API of MPP. User implements the video codec function by using the function pointer provided in the MppApi structure. The structure is shown below: + +| Parameter name | Parameter type | Description | +|--------------------|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| size | RK_U32 | MppApi structure size | +| version | RK_U32 | MppApi structure version | +| decode | Function pointer | MPP_RET (\*decode)(MppCtx ctx, MppPacket packet, MppFrame \*frame)
Video decoding interface, input and output at the same time, used alone.
ctx :MPP instance context.
packet :Input bitstream
frame :output image return value :0 is normal and non-zero is error code. | +| decode_put_packet | Function pointer | MPP_RET (\*decode_put_packet)(MppCtx ctx, MppPacket packet)
Video decoding input interface, used in conjunction with decode_get_frame.
ctx :MPP instance context.
packet :Input bitstream
return value :0 is normal, indicating that the stream has been processed by MPP; non-zero is an error, and the stream has not been processed, so the stream needs to be resented. | +| decode_get_frame | Function pointer | MPP_RET (\*decode_get_frame)(MppCtx ctx, MppFrame \*frame)
Video decoding output interface, used in conjunction with decode_put_packet.
ctx :MPP instance context.
frame :output image
return value :0 is normal, indicating that the acquisition of output process is normal, we need to determine whether there is a value of the frame pointer; non-zero is error code. | +| encode | Function pointer | MPP_RET (\*encode)(MppCtx ctx, MppFrame frame, MppPacket \*packet)
Video encoding interface, input and output at the same time, used separately.
ctx :MPP instance context.
frame :input image
packet :output bitstream
return value:0 is normal, non-zero is error code. | +| encode_put_frame | Function pointer | MPP_RET (\*encode_put_frame)(MppCtx ctx, MppFrame frame)
Video encoding input interface, used in conjunction with encode_get_packet.
ctx :MPP instance context.
frame :input image
return value :0 is normal and non-zero is error code. | +| encode_get_packet | Function pointer | MPP_RET (\*encode_get_packet)(MppCtx ctx, MppPacket \*packet) Video encoding output interface, used in conjunction with encode_put_frame.
ctx :MPP instance context.
packet :output bitstream
return value :0 is normal, non-zero is error code.| +| poll | Function pointer | MPP_RET (\*poll)(MppCtx ctx, MppPortType type, MppPollType timeout) Port query interface, used to query whether the port has data available for dequeue.
ctx :MPP instance context.
type :Port types are divided into input port and output port.
timeout :Query timeout parameter, -1 is blocking query, 0 is non-blocking query, and positive value is milliseconds of timeout.
return value :0 is normal, data can be retrieved, non-zero is error code. | +| dequeue | Function pointer | MPP_RET (\*dequeue)(MppCtx ctx, MppPortType type, MppTask \*task) The port dequeue interface is used to dequeue the MppTask structure from the port.
ctx :MPP instance context.
type :Port types are divided into input port and output port.
task :MppTask
return value :0 is normal, non-zero is error code. | +| enqueue | Function pointer | MPP_RET (\*enqueue)( MppCtx ctx, MppPortType type, MppTask task) The port enqueue interface is used to feed the port into the MppTask structure.
ctx :MPP instance context.
type :Port types are divided into input port and output port.
task :MppTask
return value:0 is normal, non-zero is error code. | +| reset | Function pointer | MPP_RET (\*reset)(MppCtx ctx) The reset interface is used to reset the internal state of MppCtx and set to available initialized state.
NOTE: the reset interface is a blocked synchronous interface.
ctx :MPP instance context.
return value :0 is normal, non-zero is error code. | +| control | Function pointer | MPP_RET (\*control)(MppCtx ctx, MpiCmd cmd, MppParam param) Control interface, an interface for additional control operations to MPP instances.
ctx :MPP instance context.
cmd :Mpi command id, representing different types of control commands.
param :The Mpi command parameter represents the additional parameter of the control command.
return value :0 is normal, non-zero is error code. | + +# Chapter 3 MPI interface instructions + +This chapter describes the specific process for user to use MPI interface and some considerations on use. MPI (Media Process Interface) is the interface provided by MPP for user. It provides hardware encoding and decoding functions, as well as some necessary related functions. MPI is provided to users through function pointer in C structure. Users can use MPP context structure MppCtx and MPI interface structure MppApi to implement decoder and encoder function. + +![](media/Figure11_MPI_interface_range.png) +
Figure 11 MPI interface range range
+ +As shown in the figure above mpp_create, mpp_init and mpp_destroy are the interfaces of operating MppCtx. The mpp_create interface also obtains the MPI interface structure MppApi. The real encoding and decoding process is achieved by calling the function pointer in the MppApi structure, that is, the part in the red box in the figure above. Function calls in red boxes are divided into codec process interface put/get_packet/frame and related control and reset interfaces. The description of the codec interface is shown below, and then some key points in the work of the codec are explained. + +# 3.1 Decoder data flow interface + +The decoder interface provides the user with the function of input stream and output image. The interface functions are decode_put_packet function, decode_get_frame function and decode function in MppApi structure. This set of functions provides the simplest decoding support. + +## 3.1.1 decode_put_packet + +| Interface definition | MPP_RET decode_put_packet(MppCtx ctx, MppPacket packet) | +|----------------------|-----------------------------------------------------------------| +| Input parameter | ctx :MPP Decoder instance packet :Bit stream data to be input | +| Return parameter | Runtime error code | +| Function | Input stream data **packet** to MPP decoder instance **ctx**. | + +##### The Form of Input Bit Stream: whole-frame and broken-frame + +The input of MPP is raw stream without encapsulated information. There are two forms of raw stream input: + +1. Whole frame data: + The input data has been segmented by frame, that is, each packet of MppPacket data input to decode_put_packet function already contains one and only one complete frame. In this case, MPP can directly process the stream by package, which is the default operation of MPP. + +2. Broken frame data: + The input data is segmented by length, and then it cannot judge whether a package of MppPacket data is only one complete frame or not. MPP needs frame segmenting operation internally. MPP can also support this broken frame data. But it needs to set the need_split flag through the MPP_DEC_SET_PARSER_SPLIT_MODE command of the control interface before mpp_init. + +![](media/Rockchip_Developer_Guide_MPP/MPP_Split_mode_config.png) + +In this way the MppPacket with broken frame data that input by decode_put_packet will be segmented frame by frame inside MPP and processed in the same way of whole frame data. + +If these two situations are mixed up there will be some bitstream decoding error generated. + +Whole frame data process is more efficient, but it needs to be parsed and frame segmented before input. Broken frame data process is simple to use, but its efficiency will be affected. + +In the mpi_dec_test test case the default mode is broken frame mode. In Rockchip Android SDK the whole frame mode is used. Users can choose according to their application scenarios and platform conditions. + +##### **Consumption of input bit stream** + +The valid data length of input MppPacket is “length”. After input decode_put_packet, if the input stream is consumed successfully, the function return value is zero (MPP_OK), and the length of MppPacket is cleared to zero. If the input stream has not been processed a non-zero error code is returned, and the length of MppPacket remains unchanged. + +##### **Working mode of function call** + +The decode_put_packet function is to input the raw bitstream to MPP instance, but in some cases the MPP instance cannot receive more data. At this time decode_put_packet works in non-blocking mode and it will return error code directly. User gets the returned error codes and waits for a certain time, and then resends the stream data to avoid extra overhead. + +##### **The number of maximum buffered packets** + +By default the MPP instance can receive four input stream packets in the processing queue. If input stream is sent too fast an error code will be reported and user will be required to wait a moment and resent the stream.. + +## 3.1.2 decode_get_frame + +| Interface definition | MPP_RET decode_get_frame(MppCtx ctx, MppFrame \*frame) | +|----------------------|----------------------------------------------------------------------------| +| Input parameter | ctx :MPP Decoder instance
frame :A pointer to obtain MppFrame instances. | +| Return parameter | Runtime error code | +| function | Get **frame** description information of decoded frame from MPP decoder instance **ctx**. | + +The image decoded by MPP is described by the structure of MppFrame. Also the structure of MppFrame is the channel for MPP decoder instance to output information. The error information of image and the info change are also output with MppFrame structure. + +##### **Error information of output image** + +The error information of the image is errinfo, which indicates whether there is an error in the process of decoding this image. If errInfo is not zero it means that an error occurred on decoding the corresponding bitstream. The image contains error can be discarded. + +##### **Space requirement on decoding image** + +When decoding image the decoder needs to obtain memory for the pixel data of output image. User is required to provide buffer with proper size to decoder. The space size requirement will be calculated in MPP decoder according to different chip platform and different video format. The calculated memory space requirement will be provided to user through the member variable buf_size of MppFrame. Users need to allocate memory according to the buf_size value to meet the requirement of decoder. + +##### **Change of output image information (Info change)** + +When the information such as the width, height, format, and pixel bit depth of the bitstream is changed decoder will report to user. User is required to update the memory pool used by decoder by update new memory buffer to the decoder. This involves decoding memory allocation and usage procedure, which are described in 3..2 Image Memory Allocation and Interactive Mode. + +## 3.1.3 decode + +The decode function is a combination of decode_put_packet and decode_get_frame data, providing user with a composite call of two functions. Its internal logic is: + +1. Try to acquire an output image; +2. If the output image is successfully acquired, function will return; +3. If the bitstream has been successfully sent, function will return; +4. Send the input bitstream; +5. Check the bitstream is sent successfully or not and loops back to step 1; + +In user view, the decode function firstly try to acquire a decoded image. If the decoded image is obtained, the decoded image is preferentially returned to the caller. If there is no decoded image can be output the bitstream is sent, and then try again to get the decoded image and exit. + +# 3.2 Decoder control interface + +## 3.2.1 control + +The MpiCmd enumeration type defined in rk_mpi_cmd.h defines the control interface command word. The decoder and decoding process commands are shown as follows: + +![](media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type.png) + +**MPP_DEC_SET_FRAME_INFO** + +The command parameter is MppFrame, which is used to configure the default width and height information of the decoder. The returned MppFrame structure will bring out the image buffer size to be allocated from the decoder. This command is called usually right after mpp_init and before decode_put_packet. + +**MPP_DEC_SET_EXT_BUF_GROUP** + +The command parameter is MppBufferGroup, which is used to configure the MppBufferGroup as buffer pool to decoder. This command is called at different position depending on image memory allocation mode. + +**MPP_DEC_SET_INFO_CHANGE_READY** + +There is no command parameter for this command. It is used to mark decoder’s MppBufferGroup has completed the reset processing of the Info change operation, and decoder can continue decoding. This command is called at different position depending on image memory allocation mode. + +**MPP_DEC_SET_PRESENT_TIME_ORDER** + +The command parameter is RK_U32*, which is used to process special bitstream timestamp case. + +**MPP_DEC_SET_PARSER_SPLIT_MODE** + +The command parameter is RK_U32*, which is used to enable the protocol parser in the MPP to process internal frame segmentation. The default bitstream input mode is whole frame mode and assume the input is frame segmented. This command is called before mpp_init. + +**MPP_DEC_SET_PARSER_FAST_MODE** + +The command parameter is RK_U32*, which is used to enable fast frame parsing in MPP and improve the parallelism of decoder hardware and software. However, the side-effect is some influence on error stream flag so it is disabled by default. This command is called before mpp_init. + +**MPP_DEC_GET_STREAM_COUT** + +The command parameter is RK_U32*. It is called by external applications to obtain the number of bitstream packets that have not been processed. It is a historical legacy interface. + +**MPP_DEC_GET_VPUMEM_USED_COUT** + +The command parameter is RK_U32*. It is called by external applications to obtain the number of MppBuffer used by MPP. It is a historical legacy interface. + +**~~MPP_DEC_SET_VC1_EXTRA_DATA~~** + +Not yet implemented. It is a historical legacy interface. + +**MPP_DEC_SET_OUTPUT_FORMAT** + +The command parameter is MppFrameFormat. It is called by external applications to configure the output image format of the JPEG decoder. It is not used by default. + +**MPP_DEC_SET_DISABLE_ERROR** + +The command parameter is RK_U32*. It is used to disable error handling of the MPP decoder. Once enabled, MPP decoding ignores the error flag of the stream, outputs all decodable images, and does not mark any errinfo in the output MppFrame structure. This command is called before decode_put_packet. + +**MPP_DEC_SET_IMMEDIATE_OUT** + +The command parameter is RK_U32*. It is used to enable the immediate output mode of H.264 decoder. Once enabled the H.264 decoder ignores the frame sequence discontinuity caused by frame dropping or picture order count, just outputs the current decoded image immediately. This command is called before decode_put_packet. + +- MPP_DEC_SET_ENABLE_FAST_PLAY + +The command parameter is FastPlayMode\*. It is used to enable the fast play of H.264, without waiting for dpb full to output the frame. If the current frame is decoded after the I frame but displayed before the I frame, frame loss may occur. The command is called before decode_put_packet. + +## 3.2.2 reset + +The reset interface is used to restore the decoder to the state after normal initialization. + +When the user sends the last packet of MppPacket code stream, and puts the EOS mark into the decoder, the decoder will enter the EOS state after processing the last packet of data, and will no longer receive and process the code stream. Only after resetting can it continue to receive the new code stream. + +# 3.3 Key points on decoder usage + +In the process of using decoder some important notices need to be paid attention to: + +## 3.3.1 Decoder single/multithread usage + +The MPI interface of MPP decoder is thread-safe and can be used in multi-thread environment. The single-thread mode is shown in mpi_dec_test demo, and the multi-threaded mode is shown in mpi_dec_mt_test demo. + +![](media/Figure12_Decoder_single_thread_usage_EN.png) + +![](media/Figure12_Decoder_multi_thread_usage_EN.png) + +
Figure 12 Decoder single/multithread usage
+ +## 3.3.2 Image memory allocation and user interaction mode + +When decoder decodes image it needs to obtain memory space to write pixel data. When decoding is completed, the memory space needs to be handed over to user, and released back to decoder after user completes his usage. And all the Memory space will be released when the decoder is closed. In this procedure mode zero-copy interaction can be achieved between the decoder and the user. The MPP decoder supports three memory allocation and user interaction mode: + +##### **Mode 1: Pure internal allocation mode** + +The image memory is allocated from the MPP decoder directly. The user obtains the decoder output image and releases it directly after use. + +![](media/Figure13_Schematic_diagram_of_pure_internal_allocation_mode.png) +
Figure 13 Schematic diagram of pure internal allocation mode
+ +In this way the user does not need to call the MPP_DEC_SET_EXT_BUF_GROUP command of the decoder control interface, and only needs to directly call the MPP_DEC_SET_INFO_CHANGE_READY command of + +the control interface when the decoder reports the info change. The decoder will automatically allocate memory internally and the user needs to release the acquired data of each frame direct I. + +![](media/Figure14_Code_flow_of_decoder_image_memory_pure_internal_allocation_mode.png) +
Figure 14 Code flow of decoder image memory pure internal allocation mode
+ +Advantage: + +Procedure is simple. A demo can be setup quickly to evaluate the decoder performance. Disadvantage: + +1. Memory is allocated internally from the decoder. If the memory has not been released when the decoder is destroyed, there may be a memory leak or crash. +2. Unable to control the memory usage of the decoder. The decoder can use the memory without restrictions. If the bitstream is input quickly and the user does not release the decoded image memory in time, the decoder will quickly consume all available memory. +3. To achieve zero-copy display is difficult, because the memory is allocated from the inner decoder, and the user's display system may be not compatible. + +##### **Mode 2:Semi-internal allocation mode** + +This mode is the default mode used by the mpi_dec_test demo. The user needs to create an MppBufferGroup according to the buf_size of the MppFrame returned by the get_frame, and configure it to the decoder through the MPP_DEC_SET_EXT_BUF_GROUP of the control interface. Users can limit the memory usage of the decoder through the mpp_buffer_group_limit_config interface. + +![](media/Figure15_Semi-internal_allocation_mode_decoder_work_flow.png) + +
Figure 15 Semi-internal allocation mode decoder work flow
+ + + +Advantage: + +Procedure is simple, approachable, can do some limitation on the memory usage. Disadvantage: + +1. The limitation of memory space is not accurate. The usage of memory is not fixed at 100% and will fluctuate. +2. It is also difficult to achieve zero copy display + +##### **Mode 3:Pure external allocation mode** + +In this mode decoder imports the memory file handle of the external allocator (usually dmabuf/ion/drm) from the user by creating an empty external mode MppBufferGroup. On the Android platform, Mediaserver obtains the display memory from SurfaceFlinger through gralloc, commits the file handle obtained by gralloc to MppBufferGroup, configures MppBufferGroup to the decoder through the control interface MPP_DEC_SET_EXT_BUF_GROUP command, and then the MPP decoder will recycle the memory space obtained by gralloc + +![](media/Figure16_Schematic_diagram_of_pure_external_allocation_mode.png) +
Figure 16 Schematic diagram of pure external allocation mode
+ +![](media/Figure17_Pure_external_allocation_mode_decoder_work_flow.png) +
Figure 17 Pure external allocation mode decoder work flow
+ +Advantage: + +It is easy to achieve zero copy by directly using the memory from external display. Disadvantage: + +1. It is difficult to understand and use. +2. The user program needs to be modified. Some user program work flow restricts the pure external allocation mode usage. + +**Note on use of pure external distribution mode:** + +1. If the image memory pool is created before the decoder is created there should be an extra way to get the size of the image memory. + + General YUV420 image memory space calculation method: Image pixel datahor_stride \* ver_stride \* 3 / 2 Additional information: hor_stride \* ver_stride / 2 + +2. The number of memory blocks needs to consider the requirements of both decoding and display. If the number of memory blocks is enough the decoder may get stuck. + + H.264/H.265 protocols with more reference frames require 20+ memory blocks to guarantee decoding. Other protocols require 10+ memory blocks to ensure decoding. + +3. If an info change occurs during the bitstream decoding process, the existing MppBufferGroup needs to be reset. New image memory buffer should be committed, and the external display needs to be adjusted accordingly. + +# 3.4 Encoder data flow interface + +The encoder interface provides the user with the image input function and bitstream output functions . The interface function is the encode_put_frame function, the encode_get_packet function and the encode function in the MppApi structure. This set of functions provides simple coding support, while the control interface provides the ability to configure the encoder. + +## 3.4.1 encode_put_frame + +| Interface definition | MPP_RET encode_put_frame(MppCtx ctx, MppFrame frame) | +|----------------------|----------------------------------------------------------------------| +| Input parameter | ctx :MPP decoder instance
frame :Image data to be input | +| Return parameter | Running error code | +| Function | Input frame image data to the MPP encoder instance specified by ctx. | + +#### **Function working mode** + +Since the input image of the encoder is very large in normal case, if the image copy is performed, the efficiency will be greatly reduced. Therefore, the input function of the encoder needs to wait for the encoder hardware to complete the use of the input image memory then the input function can return. The used image is returned to the caller. Based on the above considerations the encode_put_frame is a blocking function that blocks the call until the input image usage is finished. To a certain extent, the software and hardware operations cannot be paralleled and the efficiency is reduced. + +#### **Copy and zero copy input** + +The input of the encoder does not support the space allocated by the CPU. If you need to support the address allocated by the CPU, you need to allocate MppBuffer and copy the data into it. This will greatly affect the efficiency. The encoder prefers input memory to be in form of dmabuf/ion/drm, which enables zero-copy encoding with minimal overhead. + +## 3.4.2 encode_get_packet + +| Interface definition | MPP_RET encode_get_packet(MppCtx ctx, MppPacket \*packet) | +|----------------------|--------------------------------------------------------------------------------------------------------------------------| +| Input parameter | ctx :MPP decoder instance
packet :A pointer to get an instance of MppPacket. | +| Return parameter | Runtime error mode | +| Function | The packet description information of the completed encoding is obtained from the MPP encoder instance specified by ctx. | + +##### **Header information and image data** + +Taking the H.264 encoder as an example, the output data of the encoder is divided into two parts: header information bitstream (sps/pps) and image data bitstream (I/P slice). The header information needs to be obtained by the MPP_ENC_GET_EXTRA_INFO command of the control interface, and the image data is obtained through the encode_get_packet interface. The timing of the header information acquisition is after the SET_RC_CFG/SET_PREP_CFG/SET_CODEC_CFG parameter configuration command of the control interface is completed. When the parameter configuration command is called, the encoder will update each parameter. After the update is completed, the latest header information can be obtained by calling MPP_ENC_GET_EXTRA_INFO + +##### **H.264 encoder output stream format** + +At present, the hardware fixed output stream with the start code of 00 00 00 01, so the encode_get_packet function gets the code stream with the start code of 00 00 00 01. If you need to remove the start code, you can copy it start with the address after the start code. + +##### **Zero copy of code stream data** + +Since there is no way to configure the output buffer when using the encode_put_frame and encode_get_packet interfaces, a copy will be made when using encode_get_packet. In general the output stream of the encoder is not large comparing to the input image, and the copy of the bitstream data is acceptable. If you need to use a zero-copy interface, you need to use the enqueue/dequeue interface and the MppTask structure. + +## 3.4.3 encode + +##### **Not yet implemented** + +# 3.5 Encoder control interface + +Encoders and decoders are different and require users to configure certain parameters. The encoder requires the user to configure the encoder configuration information through the control interface before encoding. + +## 3.5.1 Control and MppEncCfg + +MPP recommends using the encapsulated MppEncCfg structure to configure encoder information through the MPP_ENC_SET_CFG/MPP_ENC_GET_CFG command of the control interface. + +Due to the configurable options and parameters of the encoder, the use of fixed structures is prone to frequent changes in the interface structure, resulting in the inability to ensure binary compatibility of the interface, complicated version management, and greatly increased maintenance. + +To alleviate this problem, MppEncCfg uses (void \*) as the type, and uses \ for key map configuration. The function interface is divided into s32/u32/s64/u64/ptr/st, and the corresponding interface functions are divided into set and get two groups, as follows: + +```c +MPP_RET mpp_enc_cfg_set_s32(MppEncCfg cfg, const char *name, RK_S32 val); +MPP_RET mpp_enc_cfg_set_u32(MppEncCfg cfg, const char *name, RK_U32 val); +MPP_RET mpp_enc_cfg_set_s64(MppEncCfg cfg, const char *name, RK_S64 val); +MPP_RET mpp_enc_cfg_set_u64(MppEncCfg cfg, const char *name, RK_U64 val); +MPP_RET mpp_enc_cfg_set_ptr(MppEncCfg cfg, const char *name, void *val); +MPP_RET mpp_enc_cfg_set_st(MppEncCfg cfg, const char *name, void *val); + +MPP_RET mpp_enc_cfg_get_s32(MppEncCfg cfg, const char *name, RK_S32 *val); +MPP_RET mpp_enc_cfg_get_u32(MppEncCfg cfg, const char *name, RK_U32 *val); +MPP_RET mpp_enc_cfg_get_s64(MppEncCfg cfg, const char *name, RK_S64 *val); +MPP_RET mpp_enc_cfg_get_u64(MppEncCfg cfg, const char *name, RK_U64 *val); +MPP_RET mpp_enc_cfg_get_ptr(MppEncCfg cfg, const char *name, void **val); +MPP_RET mpp_enc_cfg_get_st(MppEncCfg cfg, const char *name, void *val); +``` + +The character string is generally defined by \[type:parameter\]. The supported character strings and parameter types are as follows: + +|Parameter string |Interface |Actual type |Description | +|---|---|---|---| +|rc:mode|S32|MppEncRcMode|Indicates the bit rate control mode, currently supports CBR and VBR:
CBR is Constant Bit Rate,fixed bit rate mode。In fixed bit rate mode, the target bit rate plays a decisive role.
VBR is Variable Bit Rate, variable bit rate mode.In variable bit rate mode, the maximum and minimum bit rates play a decisive role.
FIX_QP is a fixed QP mode, used for debugging and performance evaluation.
![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcMode.png)| +|rc:bps_target|S32|RK_S32|Indicates the target code rate in CBR mode.| +|rc:bps_max|S32|RK_S32|Indicates the highest bit rate in VBR mode.| +|rc:bps_min|S32|RK_S32|Indicates the lowest bit rate in VBR mode.| +|rc:fps_in_flex|S32|RK_S32|Flag bit indicating whether the input frame rate is variable. The default is 0.
0 means that the input frame rate is fixed, and the frame rate calculation method is fps_in_num/fps_in_denom, which can indicate the fractional frame rate.
1 means that the input frame rate is variable. In the case of a variable frame rate, the frame rate is not fixed, and the corresponding code rate calculation and allocation rules become calculated according to actual time.| +|rc:fps_in_flex|S32|RK_S32|Flag bit indicating whether the input frame rate is variable. The default is 0.
0 means that the input frame rate is fixed, and the frame rate calculation method is fps_in_num/fps_in_denom, which can indicate the fractional frame rate.
1 means that the input frame rate is variable. In the case of a variable frame rate, the frame rate is not fixed, and the corresponding code rate calculation and allocation rules become calculated according to actual time.| +|rc:fps_in_num|S32|RK_S32|Indicates the numerator part of the input frame rate score value, for example, 0 means the default 30fps.| +|rc:fps_in_denom|S32|RK_S32|Indicates the denominator part of the input frame rate fraction value. If 0 is 1| +|rc:fps_out_flex|S32|RK_S32|Flag indicating whether the output frame rate is variable. The default is 0.
0 means that the output frame rate is fixed, and the frame rate calculation method is fps_out_num/fps_out_denom, which can indicate the fractional frame rate.
1 means that the output frame rate is variable. In the case of variable frame rate, the frame rate is not fixed, and the corresponding code stream output time is calculated according to the actual time.| +|rc:fps_out_num|S32|RK_S32|Indicates the numerator part of the output frame rate score, such as 0 means the default 30fps.| +|rc:fps_out_denom|S32|RK_S32|Indicates the denominator part of the output frame rate score value. If 0 is 1| +|rc:gop||RK_S32|Indicates Group Of Picture, that is, the interval between two I frames, the meaning is as follows.
0-indicates that there is only one I frame, other frames are P frames
1-means all I frames
2-means the sequence is I P I P I P...
3-means the sequence is I P P I P P I P P...
In general, gop is selected as an integer multiple of the input frame rate.| +|rc:max_reenc_times|U32|RK_U32|The maximum recoding times of a frame of image.| +|prep:width|S32|RK_S32|Indicates the number of pixels in the horizontal direction of the input image, in units of pixels.| +|prep:height|S32|RK_S32|Indicates the number of pixels in the vertical direction of the input image, in units of pixels.| +|prep:hor_stride|S32|RK_S32|Indicates the distance between two adjacent lines in the vertical direction of the input image, in bytes.| +|prep:ver_stride|S32|RK_S32|Indicates the number of lines between input image components, and the unit is 1.| +|prep:format|S32|MppFrameFormat|Represents the input image color space format and memory layout.
![](media/Rockchip_Developer_Guide_MPP/MPP_MppFrameFormat.png)| +|prep:color|S32|MppFrameColorSpace|Represents the color space range of input image data.| +|prep:range|S32|MppFrameColorRange|Indicates whether the input image is full range or limit range
![](media/Rockchip_Developer_Guide_MPP/MPP_MppFrameColorRange.png)| +|prep:rotation|S32|MppEncRotationCfg|Represents the input image rotation attribute, the default is 0, no rotation.
![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncRotationCfg.png)| +|prep:mirroring|S32|RK_S32|Indicates the mirroring attribute of the input image, the default is no mirroring . 
![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncMirrorCfg.png)| +|codec:type|S32|MppCodingType|Indicates the protocol type corresponding to MppEncCodecCfg, which needs to be consistent with the parameters of the MppCtx initialization function mpp_init.
![](media/Rockchip_Developer_Guide_MPP/MPP_MppCodingType.png)| +|h264:stream_type|S32|RK_S32|Indicates the type of input H.264 stream format, and the default is 0.
0-indicates Annex B format, that is, the start code of 00 00 00 01 is added.
1-indicates a format without a start code.
At present, the internal fixed format is Annex B format| +|h264:profile|S32|RK_S32|The profile_idc parameter in SPS:
66-indicates Baseline profile.
77-indicates Main profile.
100-indicates High profile.
![](media/Rockchip_Developer_Guide_MPP/MPP_H264Profile.png)| +|h264:level|S32|RK_S32|Indicates  the level_idc parameter in SPS, where 10 represents level 1.0:10/11/12/13 – qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
20/21/22 – cif@30fps / half-D1@25fps / D1@12.5fps
30/31/32 – D1@25fps / 720p@30fps / 720p@60fps
40/41/42 – 1080p@30fps / 1080p@30fps / 1080p@60fps
50/51/52 – 4K@30fps / 4K@30fps / 4K@60fps
The general configuration is level 4.1 to meet the requirements.| +|h264:cabac_en|S32|RK_S32|Represents the entropy encoding format used by the encoder:
0 – CAVLC,Adaptive variable length coding.
1 – CABAC, Adaptive arithmetic coding.| +|h264:cabac_idc|S32|RK_S32|The cabac_init_idc in the protocol syntax is valid when cabac_en is 1, and the valid value is 0~2.| +|h264:trans8x8|S32|RK_S32|Indicates the 8x8 conversion enable flag in the protocol syntax.| +|h264:const_intra|S32|RK_S32|0-to close, fixed close in Baseline/Main profile.| +|h264:scaling_list|S32|RK_S32|1-to enable, selectable to enable in High profile.| +|h264:cb_qp_offset|S32|RK_S32|It indicates the constrained_intra_pred_mode mode enable flag in the protocol syntax.| +|h264:cr_qp_offset|S32|RK_S32|0-is off, 1-is on.| +|h264:dblk_disable|S32|RK_S32|Represents the scaling_list_matrix mode in the protocol syntax| +|h264:dblk_alpha|S32|RK_S32|0-flat matrix, 1-default matrix.| +|h264:dblk_beta|S32|RK_S32|Indicates the deblock_offset_beta value in the protocol syntax.| +|h264:qp_init|S32|RK_S32|The valid range is [-6, 6].| +|h264:qp_max|S32|RK_S32|Indicates the initial QP value. Do not configure it under normal circumstances.| +|h264:qp_min|S32|RK_S32|Indicates the maximum QP value, do not configure it under normal circumstances.| +|h264:qp_max_i|S32|RK_S32|Indicates the minimum QP value, do not configure it under normal circumstances.| +|h264:qp_min_i|S32|RK_S32|Indicates the maximum I frame QP value. Do not configure it under normal circumstances.| +|h264:qp_step|S32|RK_S32|Indicates the minimum I frame QP value. Do not configure it under normal circumstances.| +|h265:profile|S32|RK_S32|Indicates the frame-level QP change amplitude between two adjacent frames.| +|h265:level|S32|RK_S32|The profile_idc parameter in the VPS:| +|h265:scaling_list|S32|RK_S32|Fixed at 1, Main profile| +|h265:cb_qp_offset|S32|RK_S32|Represents the level_idc parameter in VPS| +|h265:cr_qp_offset|S32|RK_S32|Represents the scaling_list_matrix mode in the protocol syntax| +|h265:dblk_disable|S32|RK_S32|0-flat matrix, 1-default matrix.| +|h265:dblk_alpha|S32|RK_S32|Indicates the chroma_cb_qp_offset value in the protocol syntax.| +|h265:dblk_beta|S32|RK_S32|The valid range is [-12, 12].| +|h265:qp_init|S32|RK_S32|Indicates the chroma_cr_qp_offset value in the protocol syntax.| +|h265:qp_max|S32|RK_S32|The valid range is [-12, 12].| +|h265:qp_min|S32|RK_S32|Indicates the deblock_disable flag in the protocol syntax, and the valid range is [0, 2].| +|h265:qp_max_i|S32|RK_S32|0 – deblocking is enabled.| +|h265:qp_min_i|S32|RK_S32|Indicates the minimum I frame QP value. Do not configure it under normal circumstances.| +|h265:qp_step|S32|RK_S32|Indicates the frame-level QP change amplitude between two adjacent frames.| +|h265:qp_delta_ip|S32|RK_S32|Indicates the QP difference between the I frame and the previous P frame.| +|jpeg: quant|S32|RK_S32|Indicates the quantization parameter level used by the JPEG encoder. The encoder has a total of 11 levels of quantization coefficient tables, from 0 to 10, and the image quality is from poor to good.| +|split:mode|U32|MppEncSplitMode|Represents the slice split mode of H.264/H.265 protocol
![](media/Rockchip_Developer_Guide_MPP/MPP_MppEncSplitMode.png)
0–  no split.
1– BY_BYTE divides the slice according to the slice size.
2– BY_CTU divides the slice according to the number of macroblocks or CTUs.| +|split:arg|U32|RK_U32|Slice cutting parameters:
In BY_BYTE mode, the parameter indicates the maximum size of each slice.
In BY_CTU mode, the parameter indicates the number of macroblocks or CTUs contained in each slice.| + +Other strings and parameters will be expanded later. + +## 3.5.2 Control other commands + +The MpiCmd enumeration type defined in the rk_mpi_cmd.h file defines the control interface command word, where the commands related to the encoder and encoding process are as follows: + +![](media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type_related_to_MPP.png) + +The commands from MPP_ENC_CMD_BASE to MPP_ENC_CMD_END are the control interface commands of the encoder. Among them, the MPP_ENC_SET/GET_CFG configuration command has been introduced as the basic configuration command in 3.5.1. The rest of the commands are briefly described below, where the commands are related to the encoder hardware and only some hardware support. + +At present, the encoder hardware supported by MPP is divided into vepu series and rkvenc series. The vepu series supports H.264 encoding, vp8 encoding and jpeg encoding, and is equipped in most RK chips. The rkvenc series only supports H.264 encoding, and is currently only available on the RV1109/RV1126 SoC, which supports more encoding functions than the vepu series. + +Brief description of some CMD commands: + +**~~MPP_ENC_SET_PREP_CFG/ MPP_ENC_GET_PREP_CFG~~** +**~~MPP_ENC_SET_RC_CFG/ MPP_ENC_GET_RC_CFG~~** +**~~MPP_ENC_SET_CODEC_CFG/ MPP_ENC_GET_CODEC_CFG~~** + +Deprecated commands, reserved for forward compatibility, do not use. + +**MPP_ENC_SET_IDR_FRAME** + +There is no command parameter. It is used to request IDR frame to the encoder. After the encoder receives the request, it encodes the next frame to be an IDR frame. All hardware supports. + + +**~~MPP_ENC_SET_OSD_LEGACY_0~~** +**~~MPP_ENC_SET_OSD_LEGACY_1~~** +**~~MPP_ENC_SET_OSD_LEGACY_2~~** + +Deprecated commands, reserved for forward compatibility, do not use. + +**MPP_ENC_GET_HDR_SYNC**/ ~~MPP_ENC_GET_EXTRA_INFO~~ + +The command used to obtain the stream header data separately. MPP_ENC_GET_EXTRA_INFO is an old command and is not recommended. + +The input parameter of MPP_ENC_GET_HDR_SYNC is MppPacket, which requires external users to allocate space and encapsulate it as MppPacket and then control to the encoder. When the control interface returns, the data copy is completed and the thread is safe. The calling timing is after the basic configuration of the encoder is completed. The user needs to manually release the previously allocated The input parameter of MppPacket.MPP_ENC_GET_EXTRA_INFO is MppPacket*, and the internal MppPacket of the encoder will be obtained for access. The calling timing is after the basic configuration of the encoder is completed. It should be noted that the MppPacket obtained here is the internal space of the MPP and does not need to be released by the user. + +In the case of multi-threading, the MppPacket obtained by the MPP_ENC_GET_EXTRA_INFO command may be modified by other controls during reading, so this command is not thread-safe and is only used for compatibility with the old vpu_api. Do not use it again. + + +**~~MPP_ENC_SET_SEI_CFG/MPP_ENC_GET_SEI_DATA~~** + +Deprecated commands, reserved for forward compatibility, do not use. + + +**~~MPP_ENC_PRE_ALLOC_BUFF/MPP_ENC_SET_QP_RANGE/MPP_ENC_SET_ROI_CFG/ MPP_ENC_SET_CTU_QP~~** + +Deprecated commands, reserved for forward compatibility, do not use. + + +**MPP_ENC_GET_RC_API_ALL** + +Get the API information of the rate control strategy currently supported by MPP, enter the RcApiQueryAll* pointer, and fill in the structure content when returning. + + +**MPP_ENC_GET_RC_API_BY_TYPE** + +Obtain the API information of all the rate control strategies of the specified MppCodingType type, enter the RcApiQueryType* pointer and specify MppCodingType, and the structure content will be filled in when returned. + + +**MPP_ENC_SET_RC_API_CFG** + +Register the external rate control strategy API, and enter the RcImplApi* pointer. The function pointer in this structure defines the behavior of the rate control strategy plug-in. The rate control strategy after registration can be queried and activated. + + +**MPP_ENC_GET_RC_API_CURRENT** + +Return the API information of the currently used rate control strategy, enter the RcApiBrief* pointer, and the content of the structure will be filled in when returning. + + +**MPP_ENC_SET_RC_API_CURRENT** + +Activate the rate control strategy API of the specified name, enter the RcApiBrief* pointer, the encoder will search the rate control strategy API of the specified string name in RcApiBrief and activate it as the current rate control strategy. + + +**~~MPP_ENC_SET_HEADER_MODE/MPP_ENC_GET_HEADER_MODE~~** + +Configure and obtain the SEI debugging information output method of the H.264/H.265 encoder. The debugging switch will be replaced by environment variables in the future. Do not use + + +**~~MPP_ENC_SET_SPLIT/ MPP_ENC_GET_SPLIT~~** + +Configure and obtain slice split configuration information of H.264/H265 encoder, which has been replaced by split:mode and split:arg in MppEncCfg, do not use + + +**MPP_ENC_SET_REF_CFG** + +Configure the advanced reference frame mode of the encoder. By default, no configuration is required. It is used when the long-term reference frame and short-term reference frame reference relationship modes need to be configured. It is used to configure a special reference relationship mode. It is advanced interface to be more documented. + + +**MPP_ENC_SET_OSD_PLT_CFG** + +The command parameter is MppEncOSDPlt, which is used to configure the OSD palette of the rkvenc series hardware. Used to configure the OSD palette of rkvenc series hardware, the command parameter is MppEncOSDPlt.It is usually configured only once at the beginning of the encoding, and the full encoding process uses a uniform palette. Only the RV1109/RV1126 series supports. + + +**MPP_ENC_GET_OSD_PLT_CFG** + +Used to obtain the OSD palette of rkvenc series hardware, the command parameter is MppEncOSDPlt*. Generally not used + + +**~~MPP_ENC_SET_OSD_DATA_CFG~~** + +The command parameter is MppEncOSDData, which is used to configure the OSD data of the rkvenc series hardware.Used to configure OSD data of rkvenc series hardware, the command parameter is MppEncOSDData.It needs to be configured every frame, and needs to be reconfigured after each frame is encoded.This command is replaced by KEY_OSD_DATA in MppMeta with MppFrame and is no longer used. + +# **3.6** **Key** points **on** **encoder** **usage** + +## **3.6.1** **Width** and height of input image and stride + +The width and height configuration of the input image of the encoder needs to be consistent with the arrangement of the image data in the memory. Taking the 1920x1080 size YUV420 image coding as an example, referring to the description of the important parameters of Figure 7 MppFrame, it is assumed that there are two cases as follows: + +![](media/Figure18_Encoder_input_frame_memory_arrangement_1_EN.png) + +![](media/Figure18_Encoder_input_frame_memory_arrangement_2_EN.png) + +
Figure 18 Encoder input frame memory arrangement
+ +Left case: the width of the luminance component is 1920, the height is 1080, the luminance data and the chrominance data are not directly connected, there are 8 blank lines in the middle. + +In this case, the horizontal stride is 1920 and the vertical stride is 1088. The application needs to allocate space and write data in the size of 1920\*1088\*3\/2. Use the configuration of width 1920, height 1080, horizontal stride 1920, and vertical stride 1088. That is, the encoding can be performed normally. + +Right case: The width of the luminance component is 1920 and the height is 1080. The luminance data and the chrominance data are directly connected, and there is no blank line in the middle. + +In this case, the horizontal stride is 1920 and the vertical stride is 1080, but because the encoder accesses the data to 16 alignment, the chroma part will be read when reading the lower edge data of the brightness, and the lower edge of the chroma will be read. The data will be read out of the chroma data, and the user needs to provide extra space. The space here is 1920\*1080\*3\/2+1920\*4 padding to ensure that the encoder does not access unallocated space. + +## 3.6.2 Encoder control information input method and expansion + +There are two ways to input encoder control information: + +One is global control information, such as code rate configuration, width and height configuration, etc., which affects the entire encoder and encoding process; the other is temporary control information, such as OSD configuration information per frame, user data information, etc., only Acts on the single frame encoding process. + +The first type of control information is mainly configured through the control interface, and the second type of control information is mainly configured through the MppMeta interface carried by the MppFrame. + +Future expansion of control information will follow these two rules. + +## 3.6.3 Encoder input and output process + +At present, the encoder's default input interface only supports blocking calls, and the output interface supports non-blocking and blocking calls. The default is non-blocking calls. There may be a failure to obtain data. You need to pay attention to it in use. + +## 3.6.4 Plug-in custom rate control strategy mechanism + +MPP supports users to define their own rate control strategy. The rate control strategy interface RcImplApi defines several hook functions on the encoding processing flow, which are used to insert user-defined processing methods in designated links. For specific usage, please refer to the default H.264/H.265 code control strategy implementation (default_h264e/default_h265e structure). + +The code control plug-in mechanism is reserved in the MPP, and the interface and process are not stable. It is foreseeable that there will be many adjustments in the future. It is only recommended to users who have the ability to read and understand the code and continue to maintain and update this mechanism. The general users do not Recommended for use. + +# Chapter 4 MPP demo description + +The demo program of MPP changes quickly. The following descriptions are for reference only. The actual operation results shall subject to practice. The operating environment of Demo is based on the Android 32bit platform. + +# 4.1 Decoder demo + +The decoder demo is the mpi_dec_test series programs including the single-threaded mpi_dec_test using the decode_put_packet and decode_get_frame interfaces, the multi-threaded mpi_dec_mt_test, and the multi-instance mpi_dec_multi_test. + +The following is an example of using mpi_dec_test on the Android platform as an example. First run mpi_dec_test directly, help document can be printed in the log, as shown below: + +![](media/Rockchip_Developer_Guide_MPP/MPP_print_decode_help.png) + +The help document can be divided into two parts: command parameter descriptions of mpi_dec_test and the description of supported coding type of the input bitstream file. + +The command parameter descriptions as follows. + +| command parameter | descriptions | +| ----------------- | ------------------------------------------------------------ | +| -i | input bitstream file | +| -o | output decoded frame file | +| -w | width of input bitstream, in pixels | +| -h | height of input bitstream, in pixels | +| -t | input bitstream coding type | +| -f | output frame format type, NV12 by default | +| -n | max output frame number. If input bitstream is too long, only the first n frames can be decoded. | +| -s | number of instances, 1 by default | +| -v | trace option: q - quiet; f - show fps | +| -slt | slt verify data file corresponding to output decoded frame | +| -help | show help | + +In the command parameters of mpi_dec_test, input file (i), coding type (t) is mandatory parameter. Other parameters such as output file (o), image width (w) image height (h), decoded frame number (n), etc. are optional parameters with less effect. + +In the command parameter of mpi_dec_test, slt verify data file converts the output frame data into the corresponding cyclic redundancy check code (see utils/utils.c). The size of the slt file is often only a few kB. In the slt test of the chip, the comparison of the output frame file is converted to the comparison of the slt file, which can significantly shorten the test cycle. + +The following print shows the encoding format supported by the MPP library. It supports MPEG2/4, H.263/4/5, and VP8/9 decoding. The number after the id is the parameter value after the -t item corresponding to the format. The parameter values are derived from the definition of OMX. The format parameter values of HEVC and AVS are quite different from other format parameter values, so you need to pay attention. + +Take 30 frames of ocrean.h264 under /data/ as an example to introduce the demo and output. The command is: + +```bash +mpi_dec_test -t 7 -i /data/ocrean.h264 -n 30 +``` + +where -t 7 indicates H.264 code stream, -i indicates input file, and -n 30 indicates decoding 30 frames. If everything is normal, the following result will be obtained: + +![](media/Rockchip_Developer_Guide_MPP/MPP_decode_log.png) + +The printed information contains the version information of the MPP library: + +``` +I mpp_info: mpp version: 6cc173d1 author: Ding Wei 2022-08-29 [hal_avsd]: Fix crash on avsd ref err path +``` + +``` +I mpi_dec_test: 0xeebc01c0 decode_get_frame get info changed found +``` + +The mpi_dec_test printing indicates that the MPP decoder has reported an info change event. + + ``` + I mpi_dec_test: 0xeebc01c0 decoder require buffer w:h [1920:1080] stride [1920:1088] buf_size 4177920 + ``` + +The mpi_dec_test printing indicates that the image memory condition requested by the MPP decoder. + + ``` + I mpi_dec_test: 0xf1c40730 decode get frame 0 + ``` + +The mpi_dec_test printing indicates that the decoder is decoding and outputting images normally. + +``` +I mpi_dec_test: decode 30 frames time 263ms delay 69ms fps 113.99 +``` + +The mpi_dec_test printing indicates that the decoder uses 263ms to decode 30 frames, first frame delays 69ms, fps is 113.99. + +``` +I mpi_dec_test: test success max memory 19.92 MB +``` + +The mpi_dec_test printing indicates that max memory of decoding is 19.92 MB. + +See the test/mpi_dec_test.c for detailed decoder demo source code. + +# 4.2 Encoder demo + +The encoder demo is the mpi_enc_test series programs, including single-threaded mpi_enc_test and multi-instance mpi_enc_multi_test. + +Take mpi_enc_test on the Android platform as an example. First run mpi_enc_test directly, output is shown below: + +![](media/Rockchip_Developer_Guide_MPP/MPP_print_encode_help.png) + +The help document can be divided into three parts: + +(1) mpi_enc_test command parameter descriptions; + +(2) the coding type description of the output encoded bitstream file; + +(3) the format description of the input picture. + +The command parameter descriptions as follows. + +| command parameter | descriptions | +| ----------------- | ------------------------------------------------------------ | +| -i | input frame file | +| -o | output encoded bitstream | +| -w | width of input bitstream, in pixels | +| -h | height of input bitstream, in pixels | +| -hstride | the horizontal stride of input picture, in byte | +| -vstride | the vertical stride of input picture, in 1 | +| -f | the format of input picture, NV12 by default | +| -t | output stream coding type | +| -tsrc | input file source coding type, only used in the codec performance test(see mpi_rc2_test.c) | +| -n | max encoding frame number. If input bitstream is too long, only the first n frames can be decoded. | +| -g | gop reference mode | +| -rc | set rc_mode, 0:vbr 1:cbr 2:fixqp 3:avbr | +| -bps | set bit rate | +| -fps | set input and output frame rate, 30 by default. This command parameter only describes the proportional relationship between the input frame rate and the output frame rate, which is to related to the real frame rate. | +| -qc | set quality control | +| -s | number of instances, 1 by default | +| -v | trace option: q - quiet; f - show fps | +| -ini | encoder extra ini config file(not yet in effect) | +| -slt | slt verify data file corresponding to output encoded bitstream | + +mpi_enc_test command parameters, image width (w), image height (h), and coding type (t) are mandatory configuration parameters, while other parameters such as input file (i), output file (o), encoding frame number (n), and the format of input picture(f) are optional parameters. If no input file is specified, mpi_enc_test will generate a default color bar image for encoding. + +mpi_enc_test command parameters provide diversified bit rate control schemes, allowing users to control the bit rate of the output stream through bit rate control mode and bit rate constraint parameter. The bit rate control mode is divided into variable bit rate mode (VBR), fixed bit rate mode (CBR), QP-adjusted bit rate mode (FIXQP), and adaptive bit rate mode (AVBR), with the default mode being VBR; the bit rate constraint parameter provides reference for configuring bit rate boundaries within MPP. + +The format for input/output frame rate control (fps) in mpi_enc_test command parameters is: + + ``` + -fps fps_in_num:fps_in_den:fps_in_flex/fps_out_num:fps_out_den:fps_out_flex + ``` + +where in/out represents input/output, num represents the numerator, den represents the denominator, and flex being 0 indicates fixed frame rate and 1 indicates variable frame rate. The default num and den for input and output are 30 and 1, respectively, indicating a default input/output frame rate of 30. This command parameter only indicates the proportional relationship between input frame rate and output frame rate, and is independent of the actual frame rate. + +In mpi_enc_test command parameters, quality control only takes effect when the output stream format is H.264, H.265, VP8, or JPEG. The command format is: + + ``` + -qc qp_init/min/max/min_i/max_i + ``` + +where qp represents quality parameters, init represents the initial value, min represents the minimum value, max represents the maximum value; the suffix i indicates the maximum value of I frames if unspecified, representing B and P frames. + +In mpi_enc_test command parameters, if the logging option (v) is set to q, MPP daily logging will be disabled; if set to f, the average frame rate and current frame rate will be printed once every second. + +Image color space formats are divided into YUV and RGB. MPP supports multiple formats (f), with different parameter values corresponding to different layouts; it is worth noting that there are significant differences between YUV and RGB format parameter values. + +Taking encoding of ocrean.yuv under the directory /data with 30 frames as an example, the corresponding demo and output are described. The running command is: + + ```bash + mpi_enc_test -w 1920 -h 1080 -t 7 -i /data/ocrean.yuv -o /data/out.h264 -n 30 + ``` + +If everything is normal, the following result will be obtained: + +![](media/Rockchip_Developer_Guide_MPP/MPP_encode_log.png) + +Log introduction related to the decoder demo have been omitted. + + ``` + I mpp_enc: MPP_ENC_SET_RC_CFG bps 7776000 [486000:8262000] fps [30:30] gop 60 + ``` + +Default bitrate control parameters for the encoder, with a target bitrate of 7.8 Mbps, a lower reference bitrate of 0.5 Mbps, and an upper reference bitrate of 8.3 Mbps. The default input and output frame rate is 30, and the default GOP size is 60. + + ``` + I mpi_enc_test: chn 0 encoded frame 0 size 218616 qp 11 + ``` + +The mpi_enc_test printing indicates that the encoder is encoding normally. The size of the output single-frame bitstream is 0.2 M, and the quality parameter is 11. + + ``` + I mpi_enc_test: chn 0 encode 30 frames time 628 ms delay 4 ms fps 47.72 bps 10265048 + ``` + +The mpi_enc_test printing indicates that the encoder encoded 30 frames within 628 ms, with a delay of 4 ms for the first frame. The frame rate is 47.72 fps, and the bitrate is 10.2 Mbps. + +``` +I mpi_enc_test: mpi_enc_test average frame rate 47.72 +``` + +The mpi_enc_test printing indicates that the average frame rate of the encoder is 47.72 fps. + +The encoder's control parameters can also be configured through environment variables. In the Android environment, the command for configuring environment variables is: + +```bash +setprop value +``` + +In the Linux environment, the command for configuring environment variables is: + +```bash +export =value +``` + +The corresponding descriptions are as follows: + +| Control Parameter | Type | Description | +| ----------------- | ------ | ------------------------------------------------------------ | +| constraint_set | RK_U32 | Only effective for H.264 bitstream, corresponding to the constraint_set0_flag to constraint_set5_flag in the syntax. The forced flag force_flag and forced constraint parameter constraint_force are stored in the format: \| 00 \| force_flag \| 00 \| constraint_force \| Only the lower 6 bits are valid, corresponding to constraint_set5_flag to constraint_set0_flag. When force_flag is 1, the corresponding constraint_set is configured to the encoder. | +| split_mode | RK_U32 | Encoder split mode. 0: No split. 1: divides the slice according to the slice size. 2: divides the slice according to the number of macroblocks or CTUs. | +| split_arg | RK_U32 | split_arg takes effect only when encoder split_mode is enabled. When by byte, this parameter is the byte limit for each slice; when by CTU, this parameter is the CTU limit for each slice. | +| split_out | RK_U32 | Split output mode, effective only when encoder splitting mode is enabled. 1: Low delay output mode; 2:Segment information output mode. Under low delay output mode, the encoder outputs each slice with low delay; under segment information output mode, the encoder encapsulates segment information for each slice. | +| sei_mode | RK_U32 | SEI write mode. 0: No SEI write; 1: Sequence write mode; 2: Frame write mode. Under sequence write mode, there is only one SEI for each GOP; under frame write mode, SEI will also be added before each frame if SEI information changes. | +| gop_mode | RK_U32 | gop reference mode. If the environment variable gop_mode is not configured, it will be configured according to the command parameter; otherwise, it will be configured according to the environment variable. | +| osd_enable | RK_U32 | Enable OSD palette. | +| osd_mode | RK_U32 | OSD palette mode, effective only after enabling OSD palette. 0: Default configuration; 1: User-defined configuration. | +| roi_enable | RK_U32 | Enable ROI testing and use the platform's default roi_type configuration. | +| roi_type | RK_U32 | Forced configuration of roi_type. | +| user_data_enable | RK_U32 | Enable user data. | + +The specific code of the encoder demo can be found in test/mpi_enc_test.c, but the current encoder demo uses the enqueue/dequeue interface mode, which will be modified later. + +# 4.3 Utilities + +MPP provides some tool programs for unit testing, which can test the hardware and software platform and the MPP library itself. + +**mpp_info_test** + +Used to read and print the version information of the MPP library. When feeding back the problem, you can attach the printed information. + + **mpp_buffer_test** + +Used to test whether kernel memory allocator is normal or not. + + **mpp_mem_test** + +Used to test whether memory allocator of the C library is normal or not. + + **mpp_runtime_test** + +Used to test whether some hardware and software running environment is normal. + + **mpp_platform_test** + +Used to read and test whether the chip platform information is normal. + +# Chapter 5 MPP library compiling and use + +# 5.1 Download source code + +The MPP source code is released at the official address: https://github.com/rockchip-linux/mpp + +The release branch is the release branch, the development branch is the develop branch, and the default is the development branch. + +The command of download: git clone [https://github.com/rockchip-linux/mpp.git](https://github.com/rockchip-linux/mpp.git) + +# 5.2 Compiling + +The MPP source code compilation script is cmake. It depends on the version above 2.8.12. It is recommended to use the 3.x version. cmake-3.28 version verification passed. Using the high version of the cmake tool may generate more warnings. + +## 5.2.1 Android platform cross-compiling + +Compiling the Android library requires the ndk environment, and the default script is compiled using android-ndk-r16b. Both android-ndk-r16b and android-ndk-r25c are verified. The former applies to sdks below android 14, and the latter applies to sdks above android 14. + +Take the r16b ndk for example: + +The download path for r16b ndk can be found in the build/android/ndk_links.md file in the source directory. + +Unzip the downloaded ndk to /home/pub/ndk/android-ndk-r16b, or manually modify the ANDROID_NDK variable path of the env_setup.sh script in the build/android/ directory. + +Go to the build/android/arm/ directory, run the make-Android.bash script to generate the Makefile for compilation, and run make –j16 to compile. + +## 5.2.2 Unix/Linux platform compiling + +First configure the toolchain in the arm.linux.cross.cmake file in the build/linux/arm/ directory, then run the make-Makefiles.bash script to generate the Makefile via cmake, and finally run make –j16 to compile. + +MPP also supports compiling directly on Debian running on the development board. + +# Chapter 6 Frequently Asked Questions + +Q: Aarch64 compile error, the error is undefined reference to \`system_property_get\`. + +A: This is a problem with google 64bit ndk. Some symbol definitions are missing from libc.so. For the problem, see: + +[http://stackoverflow.com/questions/28413530/api-to-get-android-system-properties-is-removed-in-arm6](http://stackoverflow.com/questions/28413530/api-to-get-android-system-properties-is-removed-in-arm64-platforms) [4-platforms](http://stackoverflow.com/questions/28413530/api-to-get-android-system-properties-is-removed-in-arm64-platforms) + +Solution: MPP has put the corresponding libc.so into the build/android/aarch64/fix/ directory, copy the library to the path_to_ndk/platforms/android-21/arch-arm64/usr/lib/ path. You just need recompiling. + +Q: When running, the following kernel log will be printed, is there a problem?? + +vpu_service_ioctl:1844: error: unknow vpu service ioctl cmd 40086c01 + +A: No problem, mpp has some dependencies on the kernel driver, the kernel driver has different versions of the interface, mpp will make multiple attempts. If it fails, it will try another interface. This print is printed when the attempt fails and will only be printed once. This print can be ignored. + +Q: How to analyze the problem of abnormal MPP operation? + +A: First analyze the error log. If there is a log that fails to open the kernel device, you need to analyze whether the hardware device configuration file of the video codec of the kernel platform is available, and then submit the problem to redmine. After analyzing the operating environment problem, analyze the MPP operation Internal issue. diff --git a/doc/design/1.mpp_design.txt b/doc/design/1.mpp_design.txt new file mode 100644 index 000000000..da4b14845 --- /dev/null +++ b/doc/design/1.mpp_design.txt @@ -0,0 +1,112 @@ +MPP (Media Process Platform) design (2016.10.12) +================================================================================ + +The mpp is a middleware library for Rockchip SoC's cross platform media process. +The main purpose of mpp is to provide very high performance, high flexibility +and expansibility on multimedia (mainly video and image) process. + +The design target of mpp is to connect different Rockchip hardware kernel driver +and different userspace application. + +Rockchip has two sets of hardware kernel driver. + +The first one is vcodec_service/vpu_service/mpp_service which is a high +performance stateless frame base hardware kernel driver. This driver supports +all available codecs that hardware can provide. This driver is used on Android/ +Linux. + +The second one is v4l2 driver which is developed for ChromeOS. It currently +supports H.264/H.265/vp8/vp9. This driver is used on ChomeOS/Linux. + +Mpp plans to support serval userspace applications including OpenMax, +gstreamer, libva. + + +Feature explaination +================================================================================ + +1. Cross Platform +The target OS platform including Android, Linux, ChromeOS and windows. Mpp uses +cmake to compile on different platform. + +2. High Performance +Mpp supports sync / async interface to reduce the time blocked in interface. And +mpp internally make hardware and software run parallelly. When hardware is +running sofware will prepare next hardware task at the same time. + +3. High Flexibility +mpi (Media Process Interface) is easy to extend by different control function. +The input/output element packet/frame/buffer is easy to extend different +components. + + +System Diagram +================================================================================ + + +---------------------------------------+ + | | + | OpenMax / gstreamer / libva | + | | + +---------------------------------------+ + + +-------------------- MPP ----------------------+ + | | + | +-------------------------+ +--------+ | + | | | | | | + | | MPI / MPP | | | | + | | buffer queue manage | | | | + | | | | | | + | +-------------------------+ | | | + | | | | + | +-------------------------+ | | | + | | | | | | + | | codec | | OSAL | | + | | decoder / encoder | | | | + | | | | | | + | +-------------------------+ | | | + | | | | + | +-----------+ +-----------+ | | | + | | | | | | | | + | | parser | | HAL | | | | + | | control | | reg_gen | | | | + | | | | | | | | + | +-----------+ +-----------+ +--------| | + | | + +-------------------- MPP ----------------------+ + + +---------------------------------------+ + | | + | kernel | + | RK vcodec_service / v4l2 | + | | + +---------------------------------------+ + +Mpp is composed of four main sub-modules: + +OSAL (Operation System Abstraction Layer) +This module shutters the differences between different operation systems and +provide basic components including memory, time, thread, log and hardware memory +allocator. + +MPI (Media Process Interface) / MPP +This module is on charge of interaction with external user. Mpi layer has two +ways for user. The simple way - User can use put/get packet/frame function set. +The advanced way - User has to config MppTask and use dequeue/enqueue function +set to communicate with mpp. MppTask can carry different meta data and complete +complex work. + +Codec (encoder / decoder) +This module implements the high efficiency internal work flow. The codec module +provides a general call flow for different video format. Software process will +be separated from hardware specified process. The software will communicate with +hardware with a common task interface which combines the buffer information and +codec specified infomation. + +Parser/Controller and hal (Hardware Abstraction Layer) +This layer provides the implement function call of different video format and +different hardware. For decoder parser provide the video stream parse function +and output format related syntax structure to hal. The hal will translate the +syntax structure to register set on different hardware. Current hal supports +vcodec_service kernel driver and plan to support v4l2 driver later. + + diff --git a/doc/design/2.kernel_driver.txt b/doc/design/2.kernel_driver.txt new file mode 100644 index 000000000..a627a0976 --- /dev/null +++ b/doc/design/2.kernel_driver.txt @@ -0,0 +1,70 @@ +Hardware kernel driver design (2016.10.17) +================================================================================ + +Rockchip has two sets of hardware kernel driver. + +The first one is vcodec_service/vpu_service/mpp_service which is a high +performance stateless frame base hardware kernel driver. This driver supports +all available codecs that hardware can provide. This driver is used on Android/ +Linux. + +Here is the vcodec_service kernel driver framework diagram. + + +-------------+ +-------------+ +-------------+ + | client A | | client B | | client C | + +-------------+ +-------------+ +-------------+ + +userspace ++------------------------------------------------------------------------------+ + kernel + + +-------------+ +-------------+ +-------------+ + | session A | | session B | | session C | + +-------------+ +-------------+ +-------------+ + | | | | | | + waiting done waiting done waiting done + | | | | | | ++---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +| task3 | | task0 | | task1 | | task0 | | task0 | ++---+---+ +-------+ +-------+ +-------+ +---+---+ + | | ++---+---+ +---+---+ +| task2 | | task1 | ++-------+ +-------+ + +-----------+ + | service | + +---------+-----------+---------+ + | | | + waiting running done + | | | + +-----+-----+ +-----+-----+ +-----+-----+ + | task A2 | | task A1 | | task C0 | + +-----+-----+ +-----------+ +-----+-----+ + | | + +-----+-----+ +-----+-----+ + | task B1 | | task C1 | + +-----+-----+ +-----+-----+ + | | + +-----+-----+ +-----+-----+ + | task A3 | | task A0 | + +-----------+ +-----+-----+ + | + +-----+-----+ + | task B0 | + +-----------+ + +The principle of this design is to separate user task handling and hardware +resource management and minimize the kernel serial process time between two +hardware process operation. + +The driver uses session as communication channel. Each userspace client (client) +will have a kernel session. Client will commit tasks to session. Then hardware +is managed by service (vpu_service/vcodec_service). Service will provide the +ability to process tasks in sessions. + +When client commits a task to kernel the task will be set to waiting status and +link to both session waiting list and service waiting list. Then service will +get task from waiting list to running list and run. When hardware finishs a task +the task will be moved to done list and put to both service done list and +session done list. Finally client will get the finished task from session. + diff --git a/doc/design/3.mpp_buffer.txt b/doc/design/3.mpp_buffer.txt new file mode 100644 index 000000000..5daec4f5f --- /dev/null +++ b/doc/design/3.mpp_buffer.txt @@ -0,0 +1,57 @@ +Mpp buffer design (2016.10.12) +================================================================================ + +Mpp buffer is the warpper of the buffer used by hardware. Hardware usually can +not use the buffer malloc by cpu. Then we design MppBuffer for different memory +allocator on different platform. Currently it is designed for ion buffer on +Android and drm buffer on Linux. Later may support vb2_buffer in v4l2 devices. + +In order to manage buffer usage in different user mpp buffer module introduces +MppBufferGroup as bufffer manager. All MppBuffer will connect to its manager. +MppBufferGroup provides allocator service and buffer reuse ability. + +Different MppBufferGroup has different allocator. And besides normal malloc/free +function the allocator can also accept buffer from external file descriptor. + +MppBufferGroup has two lists, unused buffer list and used buffer list. When +buffer is free buffer will not be released immediately. Buffer will be moved to +unused list for later reuse. There is a good reason for doing so. When video +resolution comes to 4K the buffer size will be above 12M. It will take a long +time to allocate buffer and generate map table for it. So reusing the buffer +will save the allocate/free time. + +Here is the diagram of Mpp buffer status transaction. + + +----------+ +---------+ + | create | | commit | + +-----+----+ +----+----+ + | | + | | + | +----v----+ + +----------+ unused <-----------+ + | +---------+ | + | | | | + | | | | + +-----v----+ | | +-----+----+ + | malloc | | | | free | + +----------+ | | +----------+ + | inc_ref | +---------+ | dec_ref | + +-----+----+ +-----^----+ + | | + | | + | +---------+ | + +----------> used +-----------+ + +---------+ + | | + | | + | | + | | + | | + +----^----+ + | + | + +----+----+ + | import | + +---------+ + + diff --git a/doc/design/4.mpp_task.txt b/doc/design/4.mpp_task.txt new file mode 100644 index 000000000..dbc1bfc5d --- /dev/null +++ b/doc/design/4.mpp_task.txt @@ -0,0 +1,117 @@ +MPP task design (2017.4.7) +================================================================================ + +Mpp task is the contain component for transaction with external user in advanced +mode. The target of advanced mode is to provide flexible, multiple input/output +content for extension. + +Mpp task has mpp_meta as the rich content carrier. Mpp meta uses KEY and value +pair for extension. One task can carries multiple data into or out of mpp. +The typical case is encoder with OSD and motion detection. One task may contain +OSD buffer, motion detection buffer, frame buffer and stream buffer as input and +output stream buffer and motion detection buffer with data. And this case can +also be used on decoder if decoder wants to output some side information. + + +Mpp task transaction +================================================================================ + +1. Mpp task queue +Mpp task queue is the manager of tasks. Due to user may incorrectly use the task +we choose the design that hold all task inside mpp. Task queue will create and +release task. But task queue will not interact with user directly. We use port +and task status to control the transaction. + +2. Mpp port +Mpp port is the transaction interface of task queue. External user and internal +worker thread will use mpp_port_poll / mpp_port_dequeue / mpp_port_enqueue +interface to poll / dequeue / enqueue the task task queue. Mpp advanced mode is +using port to connect external user, interface storage and internal process +thread. Each task queue has two port: input port and output port. And from a +global view the task will always flow from input port to output port. + +3. Mpp task status +There are four status for one task. Mpp use list_head to represent the status. + +INPUT_PORT : Initial status for input port user to dequeue. Or when output port + successfully enqueue a task then the task is on this status. + +INPUT_HOLD : When input port user successfully dequeue a task then the task is + on this status. + +OUTPUT_PORT: When input port user successfully enqueue a task then the task is + on OUTPUT_PORT status. And this task is ready for dequeue from + output port. + +OUTPUT_HOLD: When output port user successfully dequeue a task then the task is + on this status. + +4. Mpp task / port transaction +There are three transaction functions on a port: poll / dequeue / enqueue. +When port user call the transaction function task will be transfer from one +status to next status. The status transform flow is unidirectional from input +port to output port. + +The overall relationship graph of task / port / status is shown below. + + 1. task queue + +------------------------------+ + | | + +----+----+ +--------------+ +----+----+ + | 4 | | 3 | | 2.1 | + +--------+ dequeue <--+ status <--+ enqueue <---------+ + | | | | INPUT_PORT | | | | + | +---------+ | | +---------+ | + +------v-----+ | | +--------------+ | | +------+------+ + | 3 | | 2 | | 2 | | 3 | + | status | | input | | output | | status | + | INPUT_HOLD | | port | | port | | OUTPUT_HOLD | + | | | | | | | | + +------+-----+ | | +--------------+ | | +------^------+ + | +---------+ | 3 | +---------+ | + | | 4 | | status | | 2.1 | | + +--------> enqueue +--> INPUT_PORT +--> dequeue +---------+ + | | | | | | + +----+----+ +--------------+ -----+----+ + | | + +------------------------------+ + + +Mpp task transaction of a complete work flow +================================================================================ + +On advanced mode mpp uses two task queue: input task queue and output task +queue. +Input task queue connects input side external user to internal worker thread. +Output task queue connects internal worker thread to output side external user. +Then there will be three threads to parallelize internal process and external +transation. This will maximize mpp efficiency. + +The work flow is demonstrated as below graph. + + +-------------------+ +-------------------+ + | input side user | | output side user | + +----^---------+----+ +----^---------+----+ + | | | | + +----+----+----v----+ +----+----+----v----+ + | dequeue | enqueue | | dequeue | enqueue | + +----^----+----+----+ +----^----+----+----+ + | | | | + +----+---------+----+ MPP +----+---------v----+ + +---+ input port +-----------+ output port +---+ + | +-------------------+ +-------------------+ | + | | input task queue | | output task queue | | + | +-------------------+ +-------------------+ | + | | output port | | input port | | + | +----+---------^----+ +----+---------^----+ | + | | | | | | + | +----v----+----+----+ +----v----+----+----+ | + | | dequeue | enqueue | | dequeue | enqueue | | + | +----+----+----^----+ +----+----+----^----+ | + | | | | | | + | +----v---------+---------------------v---------+----+ | + | | internal work thread | | + | +---------------------------------------------------+ | + | | + +-----------------------------------------------------------+ + diff --git a/doc/media/Figure01_MPP_system_framework.png b/doc/media/Figure01_MPP_system_framework.png new file mode 100644 index 000000000..a486fc5a5 Binary files /dev/null and b/doc/media/Figure01_MPP_system_framework.png differ diff --git a/doc/media/Figure02_Data_structure_used_in_MPI_interface.png b/doc/media/Figure02_Data_structure_used_in_MPI_interface.png new file mode 100644 index 000000000..45b8eaa51 Binary files /dev/null and b/doc/media/Figure02_Data_structure_used_in_MPI_interface.png differ diff --git a/doc/media/Figure03_Use_simple_interface_to_realize_video_decoding.png b/doc/media/Figure03_Use_simple_interface_to_realize_video_decoding.png new file mode 100644 index 000000000..9bc4e8c83 Binary files /dev/null and b/doc/media/Figure03_Use_simple_interface_to_realize_video_decoding.png differ diff --git a/doc/media/Figure03_Use_simple_interface_to_realize_video_decoding_EN.png b/doc/media/Figure03_Use_simple_interface_to_realize_video_decoding_EN.png new file mode 100644 index 000000000..7550577c8 Binary files /dev/null and b/doc/media/Figure03_Use_simple_interface_to_realize_video_decoding_EN.png differ diff --git a/doc/media/Figure04_Normal_usage_of_MppBuffer.png b/doc/media/Figure04_Normal_usage_of_MppBuffer.png new file mode 100644 index 000000000..f5c8b33d0 Binary files /dev/null and b/doc/media/Figure04_Normal_usage_of_MppBuffer.png differ diff --git a/doc/media/Figure04_Normal_usage_of_MppBuffer_EN.png b/doc/media/Figure04_Normal_usage_of_MppBuffer_EN.png new file mode 100644 index 000000000..7a915fbc5 Binary files /dev/null and b/doc/media/Figure04_Normal_usage_of_MppBuffer_EN.png differ diff --git a/doc/media/Figure05_Usage_of_MppBuffer_External_Import.png b/doc/media/Figure05_Usage_of_MppBuffer_External_Import.png new file mode 100644 index 000000000..8a582ecfb Binary files /dev/null and b/doc/media/Figure05_Usage_of_MppBuffer_External_Import.png differ diff --git a/doc/media/Figure05_Usage_of_MppBuffer_External_Import_EN.png b/doc/media/Figure05_Usage_of_MppBuffer_External_Import_EN.png new file mode 100644 index 000000000..0a5305e3f Binary files /dev/null and b/doc/media/Figure05_Usage_of_MppBuffer_External_Import_EN.png differ diff --git a/doc/media/Figure06_Important_parameter_description_of_MppPacket.png b/doc/media/Figure06_Important_parameter_description_of_MppPacket.png new file mode 100644 index 000000000..f02ee40c9 Binary files /dev/null and b/doc/media/Figure06_Important_parameter_description_of_MppPacket.png differ diff --git a/doc/media/Figure06_Important_parameter_description_of_MppPacket_EN.png b/doc/media/Figure06_Important_parameter_description_of_MppPacket_EN.png new file mode 100644 index 000000000..688f54653 Binary files /dev/null and b/doc/media/Figure06_Important_parameter_description_of_MppPacket_EN.png differ diff --git a/doc/media/Figure07_Important_parameter_description_of_MppFrame.png b/doc/media/Figure07_Important_parameter_description_of_MppFrame.png new file mode 100644 index 000000000..3a945da54 Binary files /dev/null and b/doc/media/Figure07_Important_parameter_description_of_MppFrame.png differ diff --git a/doc/media/Figure07_Important_parameter_description_of_MppFrame_EN.png b/doc/media/Figure07_Important_parameter_description_of_MppFrame_EN.png new file mode 100644 index 000000000..e8969ef9a Binary files /dev/null and b/doc/media/Figure07_Important_parameter_description_of_MppFrame_EN.png differ diff --git a/doc/media/Figure08_Use_MppTask_for_input_and_output.png b/doc/media/Figure08_Use_MppTask_for_input_and_output.png new file mode 100644 index 000000000..6cf50ea97 Binary files /dev/null and b/doc/media/Figure08_Use_MppTask_for_input_and_output.png differ diff --git a/doc/media/Figure08_Use_MppTask_for_input_and_output_EN.png b/doc/media/Figure08_Use_MppTask_for_input_and_output_EN.png new file mode 100644 index 000000000..06f382671 Binary files /dev/null and b/doc/media/Figure08_Use_MppTask_for_input_and_output_EN.png differ diff --git a/doc/media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask.png b/doc/media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask.png new file mode 100644 index 000000000..2df56e88e Binary files /dev/null and b/doc/media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask.png differ diff --git a/doc/media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask_EN.png b/doc/media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask_EN.png new file mode 100644 index 000000000..d1cb6c241 Binary files /dev/null and b/doc/media/Figure09_Data_Types_and_Keyword_Types_Supported_by_MppTask_EN.png differ diff --git a/doc/media/Figure10_MppCtx_usage_process.png b/doc/media/Figure10_MppCtx_usage_process.png new file mode 100644 index 000000000..b5df8ae75 Binary files /dev/null and b/doc/media/Figure10_MppCtx_usage_process.png differ diff --git a/doc/media/Figure11_MPI_interface_range.png b/doc/media/Figure11_MPI_interface_range.png new file mode 100644 index 000000000..d7d9696ef Binary files /dev/null and b/doc/media/Figure11_MPI_interface_range.png differ diff --git a/doc/media/Figure12_Decoder_multi_thread_usage.png b/doc/media/Figure12_Decoder_multi_thread_usage.png new file mode 100644 index 000000000..7fe1c26d1 Binary files /dev/null and b/doc/media/Figure12_Decoder_multi_thread_usage.png differ diff --git a/doc/media/Figure12_Decoder_multi_thread_usage_EN.png b/doc/media/Figure12_Decoder_multi_thread_usage_EN.png new file mode 100644 index 000000000..e93108116 Binary files /dev/null and b/doc/media/Figure12_Decoder_multi_thread_usage_EN.png differ diff --git a/doc/media/Figure12_Decoder_single_thread_usage.png b/doc/media/Figure12_Decoder_single_thread_usage.png new file mode 100644 index 000000000..43f08207e Binary files /dev/null and b/doc/media/Figure12_Decoder_single_thread_usage.png differ diff --git a/doc/media/Figure12_Decoder_single_thread_usage_EN.png b/doc/media/Figure12_Decoder_single_thread_usage_EN.png new file mode 100644 index 000000000..6f758f287 Binary files /dev/null and b/doc/media/Figure12_Decoder_single_thread_usage_EN.png differ diff --git a/doc/media/Figure13_Schematic_diagram_of_pure_internal_allocation_mode.png b/doc/media/Figure13_Schematic_diagram_of_pure_internal_allocation_mode.png new file mode 100644 index 000000000..04f914c0d Binary files /dev/null and b/doc/media/Figure13_Schematic_diagram_of_pure_internal_allocation_mode.png differ diff --git a/doc/media/Figure14_Code_flow_of_decoder_image_memory_pure_internal_allocation_mode.png b/doc/media/Figure14_Code_flow_of_decoder_image_memory_pure_internal_allocation_mode.png new file mode 100644 index 000000000..6e459031c Binary files /dev/null and b/doc/media/Figure14_Code_flow_of_decoder_image_memory_pure_internal_allocation_mode.png differ diff --git a/doc/media/Figure15_Semi-internal_allocation_mode_decoder_work_flow.png b/doc/media/Figure15_Semi-internal_allocation_mode_decoder_work_flow.png new file mode 100644 index 000000000..4b687fd1e Binary files /dev/null and b/doc/media/Figure15_Semi-internal_allocation_mode_decoder_work_flow.png differ diff --git a/doc/media/Figure16_Schematic_diagram_of_pure_external_allocation_mode.png b/doc/media/Figure16_Schematic_diagram_of_pure_external_allocation_mode.png new file mode 100644 index 000000000..e46261ce8 Binary files /dev/null and b/doc/media/Figure16_Schematic_diagram_of_pure_external_allocation_mode.png differ diff --git a/doc/media/Figure17_Pure_external_allocation_mode_decoder_work_flow.png b/doc/media/Figure17_Pure_external_allocation_mode_decoder_work_flow.png new file mode 100644 index 000000000..0aa33019a Binary files /dev/null and b/doc/media/Figure17_Pure_external_allocation_mode_decoder_work_flow.png differ diff --git a/doc/media/Figure18_Encoder_input_frame_memory_arrangement_1.png b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_1.png new file mode 100644 index 000000000..73bbae4b4 Binary files /dev/null and b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_1.png differ diff --git a/doc/media/Figure18_Encoder_input_frame_memory_arrangement_1_EN.png b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_1_EN.png new file mode 100644 index 000000000..d80df22da Binary files /dev/null and b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_1_EN.png differ diff --git a/doc/media/Figure18_Encoder_input_frame_memory_arrangement_2.png b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_2.png new file mode 100644 index 000000000..8bab7e2a6 Binary files /dev/null and b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_2.png differ diff --git a/doc/media/Figure18_Encoder_input_frame_memory_arrangement_2_EN.png b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_2_EN.png new file mode 100644 index 000000000..e2d88a649 Binary files /dev/null and b/doc/media/Figure18_Encoder_input_frame_memory_arrangement_2_EN.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_H264Profile.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_H264Profile.png new file mode 100644 index 000000000..287bf4562 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_H264Profile.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type.png new file mode 100644 index 000000000..a13613f55 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type_related_to_MPP.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type_related_to_MPP.png new file mode 100644 index 000000000..1a72084cb Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MpiCmd_enumeration_type_related_to_MPP.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppCodingType.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppCodingType.png new file mode 100644 index 000000000..328d59588 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppCodingType.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncMirrorCfg.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncMirrorCfg.png new file mode 100644 index 000000000..649606a7b Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncMirrorCfg.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcDropFrmMode.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcDropFrmMode.png new file mode 100644 index 000000000..e7a059e31 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcDropFrmMode.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcMode.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcMode.png new file mode 100644 index 000000000..e31b19efd Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcMode.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcPriority.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcPriority.png new file mode 100644 index 000000000..9ebca5ca6 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcPriority.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcSuperFrameMode.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcSuperFrameMode.png new file mode 100644 index 000000000..31e1808a8 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRcSuperFrameMode.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRotationCfg.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRotationCfg.png new file mode 100644 index 000000000..29df9ef9b Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncRotationCfg.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncSplitMode.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncSplitMode.png new file mode 100644 index 000000000..2e8c095b2 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppEncSplitMode.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppFrameColorRange.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppFrameColorRange.png new file mode 100644 index 000000000..466d01e80 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppFrameColorRange.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppFrameFormat.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppFrameFormat.png new file mode 100644 index 000000000..87475ac3e Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppFrameFormat.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init.png new file mode 100644 index 000000000..e34aa61ad Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init_EN.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init_EN.png new file mode 100644 index 000000000..8ed3a99bc Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_by_copy_init_EN.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer.png new file mode 100644 index 000000000..c64ca91e8 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer_EN.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer_EN.png new file mode 100644 index 000000000..c25a12e0a Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_MppPacket_is_generated_from_MppBuffer_EN.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_Split_mode_config.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_Split_mode_config.png new file mode 100644 index 000000000..06f149a51 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_Split_mode_config.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_color_space_range.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_color_space_range.png new file mode 100644 index 000000000..1754b7bfb Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_color_space_range.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_decode_log.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_decode_log.png new file mode 100644 index 000000000..bce110af3 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_decode_log.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_encode_log.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_encode_log.png new file mode 100644 index 000000000..7afb58276 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_encode_log.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket.png new file mode 100644 index 000000000..7e896b0df Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket_EN.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket_EN.png new file mode 100644 index 000000000..c12966961 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_external_malloc_address_is_configured_to_MppPacket_EN.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_image_colorspace_format_and_memory_arrangement.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_image_colorspace_format_and_memory_arrangement.png new file mode 100644 index 000000000..ac9df3e60 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_image_colorspace_format_and_memory_arrangement.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_image_data_frame_field_properties.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_image_data_frame_field_properties.png new file mode 100644 index 000000000..f7a20c0f7 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_image_data_frame_field_properties.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_print_decode_help.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_print_decode_help.png new file mode 100644 index 000000000..6f4dfd39a Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_print_decode_help.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_print_encode_help.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_print_encode_help.png new file mode 100644 index 000000000..0811285d3 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_print_encode_help.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage.png new file mode 100644 index 000000000..5a2337449 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage_EN.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage_EN.png new file mode 100644 index 000000000..deab6cc68 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_external_import_usage_EN.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage.png new file mode 100644 index 000000000..74f851bb9 Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage.png differ diff --git a/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage_EN.png b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage_EN.png new file mode 100644 index 000000000..7dc26e0dc Binary files /dev/null and b/doc/media/Rockchip_Developer_Guide_MPP/MPP_procedure_pseudo_code_of_normal_usage_EN.png differ diff --git a/doc/readme.txt b/doc/readme.txt new file mode 100644 index 000000000..6aae849dc --- /dev/null +++ b/doc/readme.txt @@ -0,0 +1,12 @@ +Media Process Platform document directory description + +Mpp document is separated into two parts: + +1. Mpp user guide and user manual for library user +This part contains information about how to use mpp and external study resource +besides source code. + +2. Mpp design document for developer +This part contains information about design principle, module design and other +information which will benefit developer further understand. + diff --git a/inc/mpp_bit.h b/inc/mpp_bit.h new file mode 100644 index 000000000..eac7725b2 --- /dev/null +++ b/inc/mpp_bit.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_BIT_H +#define MPP_BIT_H + +#define MPP_BIT(n) (1UL << (n)) +#define MPP_BIT64(n) (1ULL << (n)) + +#define MPP_FLAG_1OR(a) ((RK_U32)(a)) +#define MPP_FLAG_2OR(a, b) ((RK_U32)(a) | (RK_U32)(b)) +#define MPP_FLAG_3OR(a, b, c) ((RK_U32)(a) | (RK_U32)(b) | (RK_U32)(c)) +#define MPP_FLAG_4OR(a, b, c, d) ((RK_U32)(a) | (RK_U32)(b) | (RK_U32)(c) | (RK_U32)(d)) +#define MPP_FLAG_5OR(a, b, c, d, e) ((RK_U32)(a) | (RK_U32)(b) | (RK_U32)(c) | (RK_U32)(d) | (RK_U32)(e)) +#define MPP_FLAG_6OR(a, b, c, d, e, f) ((RK_U32)(a) | (RK_U32)(b) | (RK_U32)(c) | (RK_U32)(d) | (RK_U32)(e) | (RK_U32)(f)) + +#define MPP_FLAG_OR_HELPER(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#define MPP_FLAG_OR(...) MPP_FLAG_OR_HELPER(__VA_ARGS__, MPP_FLAG_6OR, MPP_FLAG_5OR, MPP_FLAG_4OR, MPP_FLAG_3OR, MPP_FLAG_2OR, MPP_FLAG_1OR)(__VA_ARGS__) + +#define MPP_BIT32_1OR(a) (MPP_BIT(a)) +#define MPP_BIT32_2OR(a, b) (MPP_BIT(a) | MPP_BIT(b)) +#define MPP_BIT32_3OR(a, b, c) (MPP_BIT(a) | MPP_BIT(b) | MPP_BIT(c)) +#define MPP_BIT32_4OR(a, b, c, d) (MPP_BIT(a) | MPP_BIT(b) | MPP_BIT(c) | MPP_BIT(d)) +#define MPP_BIT32_5OR(a, b, c, d, e) (MPP_BIT(a) | MPP_BIT(b) | MPP_BIT(c) | MPP_BIT(d) | MPP_BIT(e)) +#define MPP_BIT32_6OR(a, b, c, d, e, f) (MPP_BIT(a) | MPP_BIT(b) | MPP_BIT(c) | MPP_BIT(d) | MPP_BIT(e) | MPP_BIT(f)) + +#define MPP_BIT32_OR_HELPER(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#define MPP_BIT32_OR(...) MPP_BIT32_OR_HELPER(__VA_ARGS__, MPP_BIT32_6OR, MPP_BIT32_5OR, MPP_BIT32_4OR, MPP_BIT32_3OR, MPP_BIT32_2OR, MPP_BIT32_1OR)(__VA_ARGS__) + +#define MPP_BIT64_1OR(a) (MPP_BIT64(a)) +#define MPP_BIT64_2OR(a, b) (MPP_BIT64(a) | MPP_BIT64(b)) +#define MPP_BIT64_3OR(a, b, c) (MPP_BIT64(a) | MPP_BIT64(b) | MPP_BIT64(c)) +#define MPP_BIT64_4OR(a, b, c, d) (MPP_BIT64(a) | MPP_BIT64(b) | MPP_BIT64(c) | MPP_BIT64(d)) +#define MPP_BIT64_5OR(a, b, c, d, e) (MPP_BIT64(a) | MPP_BIT64(b) | MPP_BIT64(c) | MPP_BIT64(d) | MPP_BIT64(e)) +#define MPP_BIT64_6OR(a, b, c, d, e, f) (MPP_BIT64(a) | MPP_BIT64(b) | MPP_BIT64(c) | MPP_BIT64(d) | MPP_BIT64(e) | MPP_BIT64(f)) + +#define MPP_BIT64_OR_HELPER(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#define MPP_BIT64_OR(...) MPP_BIT64_OR_HELPER(__VA_ARGS__, MPP_BIT64_6OR, MPP_BIT64_5OR, MPP_BIT64_4OR, MPP_BIT64_3OR, MPP_BIT64_2OR, MPP_BIT64_1OR)(__VA_ARGS__) + +#define MPP_SET_BIT(bits, n) ((bits) |= MPP_BIT(n)) +#define MPP_CLR_BIT(bits, n) ((bits) &= ~MPP_BIT(n)) +#define MPP_GET_BIT(bits, n) (((bits) >> (n)) & 1U) +#define MPP_MOD_BIT(bits, n, v) ((v) ? MPP_SET_BIT(bits, n) : MPP_CLR_BIT(bits, n)) + +#define MPP_SET_BIT64(bits, n) ((bits) |= MPP_BIT64(n)) +#define MPP_CLR_BIT64(bits, n) ((bits) &= ~MPP_BIT64(n)) +#define MPP_GET_BIT64(bits, n) (((bits) >> (n)) & 1ULL) +#define MPP_MOD_BIT64(bits, n, v) ((v) ? MPP_SET_BIT64(bits, n) : MPP_CLR_BIT64(bits, n)) + +#endif /* MPP_BIT_H */ diff --git a/inc/mpp_buffer.h b/inc/mpp_buffer.h index 53912c145..51144b722 100644 --- a/inc/mpp_buffer.h +++ b/inc/mpp_buffer.h @@ -1,221 +1,354 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_BUFFER_H__ -#define __MPP_BUFFER_H__ - -#include "rk_type.h" -#include "mpp_err.h" - -/* - * because buffer usage maybe unknown when decoder is not started - * buffer group may need to set a default group size limit - */ -#define SZ_1K (1024) -#define SZ_2K (SZ_1K*2) -#define SZ_4K (SZ_1K*4) -#define SZ_8K (SZ_1K*8) -#define SZ_16K (SZ_1K*16) -#define SZ_32K (SZ_1K*32) -#define SZ_64K (SZ_1K*64) -#define SZ_128K (SZ_1K*128) -#define SZ_256K (SZ_1K*256) -#define SZ_512K (SZ_1K*512) -#define SZ_1M (SZ_1K*SZ_1K) -#define SZ_2M (SZ_1M*2) -#define SZ_4M (SZ_1M*4) -#define SZ_8M (SZ_1M*8) -#define SZ_16M (SZ_1M*16) -#define SZ_32M (SZ_1M*32) -#define SZ_64M (SZ_1M*64) -#define SZ_80M (SZ_1M*80) -#define SZ_128M (SZ_1M*128) - -/* - * MppBuffer module has several functions: - * - * 1. buffer get / put / reference management / external commit / get info. - * this part is the basic user interface for MppBuffer. - * - * function: - * - * mpp_buffer_get - * mpp_buffer_put - * mpp_buffer_inc_ref - * mpp_buffer_commit - * mpp_buffer_info_get - * - * 2. user buffer working flow control abstraction. - * buffer should attach to certain group, and buffer mode control the buffer usage flow. - * this part is also a part of user interface. - * - * function: - * - * mpp_buffer_group_get - * mpp_buffer_group_normal_get - * mpp_buffer_group_limit_get - * mpp_buffer_group_put - * mpp_buffer_group_limit_config - * - * 3. buffer allocator management - * this part is for allocator on different os, it does not have user interface - * it will support normal buffer, Android ion buffer, Linux v4l2 vb2 buffer - * user can only use MppBufferType to choose. - * - */ -typedef void* MppBuffer; -typedef void* MppBufferGroup; - -/* - * mpp buffer group support two work flow mode: - * - * normal flow: all buffer are generated by MPP - * under this mode, buffer pool is maintained internally - * - * typical call flow: - * - * mpp_buffer_group_get() return A - * mpp_buffer_get(A) return a ref +1 -> used - * mpp_buffer_inc_ref(a) ref +1 - * mpp_buffer_put(a) ref -1 - * mpp_buffer_put(a) ref -1 -> unused - * mpp_buffer_group_put(A) - * - * commit flow: all buffer are commited out of MPP - * under this mode, buffers is commit by external api. - * normally MPP only use it but not generate it. - * - * typical call flow: - * - * ==== external allocator ==== - * mpp_buffer_group_get() return A - * mpp_buffer_commit(A, x) - * mpp_buffer_commit(A, y) - * - * ======= internal user ====== - * mpp_buffer_get(A) return a - * mpp_buffer_get(A) return b - * mpp_buffer_put(a) - * mpp_buffer_put(b) - * - * ==== external allocator ==== - * mpp_buffer_group_put(A) - * - * NOTE: commit interface required group handle to record group information - */ - -/* - * mpp buffer group has two buffer limit mode: normal and limit - * - * normal mode: allows any buffer size and always general new buffer is no unused buffer - * is available. - * This mode normally use with normal flow and is used for table / stream buffer - * - * limit mode : restrict the buffer's size and count in the buffer group. if try to calloc - * buffer with different size or extra count it will fail. - * This mode normally use with commit flow and is used for frame buffer - */ - -/* - * NOTE: normal mode is recommanded to work with normal flow, working with limit mode is not. - * limit mode is recommanded to work with commit flow, working with normal mode is not. - */ -typedef enum { - MPP_BUFFER_MODE_NORMAL, - MPP_BUFFER_MODE_LIMIT, - MPP_BUFFER_MODE_BUTT, -} MppBufferMode; - -/* - * mpp buffer has two types: - * - * normal : normal malloc buffer for unit test or hardware simulation - * ion : use ion device under Android/Linux, MppBuffer will encapsulte ion file handle - */ -typedef enum { - MPP_BUFFER_TYPE_NORMAL, - MPP_BUFFER_TYPE_ION, - MPP_BUFFER_TYPE_V4L2, - MPP_BUFFER_TYPE_BUTT, -} MppBufferType; - -/* - * MppBufferInfo variable's meaning is different in different MppBufferType - * - * MPP_BUFFER_TYPE_NORMAL - * - * ptr - virtual address of normal malloced buffer - * fd - unused and set to -1 - * - * MPP_BUFFER_TYPE_ION - * - * ptr - virtual address of ion buffer in user space - * hnd - ion handle in user space - * fd - ion buffer file handle for map / unmap - * - * MPP_BUFFER_TYPE_V4L2 - * - * TODO: to be implemented. - */ -typedef struct MppBufferInfo_t { - MppBufferType type; - size_t size; - void *ptr; - void *hnd; - int fd; - void *extension; -} MppBufferInfo; - -#define BUFFER_GROUP_SIZE_DEFAULT (SZ_1M*80) - -#define mpp_buffer_get(...) \ - mpp_buffer_get_with_tag(MODULE_TAG, ## __VA_ARGS__) - -#define mpp_buffer_group_normal_get(...) \ - mpp_buffer_group_get(MODULE_TAG, MPP_BUFFER_MODE_NORMAL, ## __VA_ARGS__) - -#define mpp_buffer_group_limited_get(...) \ - mpp_buffer_group_get(MODULE_TAG, MPP_BUFFER_MODE_LIMIT, ## __VA_ARGS__) - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * MppBuffer interface - * these interface will change value of group and buffer so before calling functions - * parameter need to be checked. - */ -MPP_RET mpp_buffer_commit(MppBufferGroup group, MppBufferInfo *info); -MPP_RET mpp_buffer_get_with_tag(const char *tag, MppBufferGroup group, MppBuffer *buffer, size_t size); -MPP_RET mpp_buffer_put(MppBuffer buffer); -MPP_RET mpp_buffer_inc_ref(MppBuffer buffer); - -MPP_RET mpp_buffer_info_get(MppBuffer buffer, MppBufferInfo *info); -MPP_RET mpp_buffer_read(MppBuffer buffer, size_t offset, void *data, size_t size); -MPP_RET mpp_buffer_write(MppBuffer buffer, size_t offset, void *data, size_t size); -void *mpp_buffer_get_ptr(MppBuffer buffer); -int mpp_buffer_get_fd(MppBuffer buffer); - -MPP_RET mpp_buffer_group_get(const char *tag, MppBufferMode mode, MppBufferGroup *group, MppBufferType type); -MPP_RET mpp_buffer_group_put(MppBufferGroup group); -MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_BUFFER_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_BUFFER_H +#define MPP_BUFFER_H + +#include "rk_type.h" +#include "mpp_err.h" + +/* + * MppBuffer module has several functions: + * + * 1. buffer get / put / reference management / external commit / get info. + * this part is the basic user interface for MppBuffer. + * + * function: + * + * mpp_buffer_get + * mpp_buffer_put + * mpp_buffer_inc_ref + * mpp_buffer_commit + * mpp_buffer_info_get + * + * 2. user buffer working flow control abstraction. + * buffer should attach to certain group, and buffer mode control the buffer usage flow. + * this part is also a part of user interface. + * + * function: + * + * mpp_buffer_group_get + * mpp_buffer_group_normal_get + * mpp_buffer_group_limit_get + * mpp_buffer_group_put + * mpp_buffer_group_limit_config + * + * 3. buffer allocator management + * this part is for allocator on different os, it does not have user interface + * it will support normal buffer, Android ion buffer, Linux v4l2 vb2 buffer + * user can only use MppBufferType to choose. + * + */ + +/* + * mpp buffer group support two work flow mode: + * + * normal flow: all buffer are generated by MPP + * under this mode, buffer pool is maintained internally + * + * typical call flow: + * + * mpp_buffer_group_get() return A + * mpp_buffer_get(A) return a ref +1 -> used + * mpp_buffer_inc_ref(a) ref +1 + * mpp_buffer_put(a) ref -1 + * mpp_buffer_put(a) ref -1 -> unused + * mpp_buffer_group_put(A) + * + * commit flow: all buffer are commited out of MPP + * under this mode, buffers is commit by external api. + * normally MPP only use it but not generate it. + * + * typical call flow: + * + * ==== external allocator ==== + * mpp_buffer_group_get() return A + * mpp_buffer_commit(A, x) + * mpp_buffer_commit(A, y) + * + * ======= internal user ====== + * mpp_buffer_get(A) return a + * mpp_buffer_get(A) return b + * mpp_buffer_put(a) + * mpp_buffer_put(b) + * + * ==== external allocator ==== + * mpp_buffer_group_put(A) + * + * NOTE: commit interface required group handle to record group information + */ + +/* + * mpp buffer group has two buffer limit mode: normal and limit + * + * normal mode: allows any buffer size and always general new buffer is no unused buffer + * is available. + * This mode normally use with normal flow and is used for table / stream buffer + * + * limit mode : restrict the buffer's size and count in the buffer group. if try to calloc + * buffer with different size or extra count it will fail. + * This mode normally use with commit flow and is used for frame buffer + */ + +/* + * NOTE: normal mode is recommanded to work with normal flow, working with limit mode is not. + * limit mode is recommanded to work with commit flow, working with normal mode is not. + */ +typedef enum { + MPP_BUFFER_INTERNAL, + MPP_BUFFER_EXTERNAL, + MPP_BUFFER_MODE_BUTT, +} MppBufferMode; + +/* + * the mpp buffer has serval types: + * + * normal : normal malloc buffer for unit test or hardware simulation + * ion : use ion device under Android/Linux, MppBuffer will encapsulte ion file handle + * ext_dma : the DMABUF(DMA buffers) come from the application + * drm : use the drm device interface for memory management + * + * MPP default allocator select priority for kernel above 5.10: + * MPP_BUFFER_TYPE_DMA_HEAP > MPP_BUFFER_TYPE_DRM > MPP_BUFFER_TYPE_ION + * MPP_BUFFER_TYPE_EXT_DMA is only used for general external dma_buf fd import. + */ +typedef enum { + MPP_BUFFER_TYPE_NORMAL, + MPP_BUFFER_TYPE_ION, + MPP_BUFFER_TYPE_EXT_DMA, + MPP_BUFFER_TYPE_DRM, + MPP_BUFFER_TYPE_DMA_HEAP, + MPP_BUFFER_TYPE_BUTT, +} MppBufferType; + +#define MPP_BUFFER_TYPE_MASK 0x0000FFFF + +/* + * MPP_BUFFER_FLAGS cooperate with MppBufferType + * 16 high bits of MppBufferType are used in flags + * + * eg: + * DMA_HEAP CMA buffer : MPP_BUFFER_TYPE_DMA_HEAP | MPP_BUFFER_FLAGS_CONTIG + * = 0x00010004 + * DRM SECURE buffer : MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_SECURE + * = 0x00080003 + * + * The dma buffer source can also be set by format: flags | type. + * dma buffer source flags: + * MPP_BUFFER_FLAGS_CONTIG means cma + * MPP_BUFFER_FLAGS_CACHABLE means cachable + * MPP_BUFFER_FLAGS_DMA32 means dma32 + * + * flags originate from drm_rockchip_gem_mem_type + */ +#define MPP_BUFFER_FLAGS_MASK 0x003f0000 //ROCKCHIP_BO_MASK << 16 +#define MPP_BUFFER_FLAGS_CONTIG 0x00010000 //ROCKCHIP_BO_CONTIG << 16 +#define MPP_BUFFER_FLAGS_CACHABLE 0x00020000 //ROCKCHIP_BO_CACHABLE << 16 +#define MPP_BUFFER_FLAGS_WC 0x00040000 //ROCKCHIP_BO_WC << 16 +#define MPP_BUFFER_FLAGS_SECURE 0x00080000 //ROCKCHIP_BO_SECURE << 16 +#define MPP_BUFFER_FLAGS_ALLOC_KMAP 0x00100000 //ROCKCHIP_BO_ALLOC_KMAP << 16 +#define MPP_BUFFER_FLAGS_DMA32 0x00200000 //ROCKCHIP_BO_DMA32 << 16 + +/* + * MppBufferInfo variable's meaning is different in different MppBufferType + * + * Common + * index - the buffer index used to track buffer in buffer pool + * size - the buffer size + * + * MPP_BUFFER_TYPE_NORMAL + * + * ptr - virtual address of normal malloced buffer + * fd - unused and set to -1, the allocator would return its + * internal buffer counter number + * + * MPP_BUFFER_TYPE_ION + * + * ptr - virtual address of ion buffer in user space + * hnd - ion handle in user space + * fd - ion buffer file handle for map / unmap + * + */ +typedef struct MppBufferInfo_t { + MppBufferType type; + size_t size; + void *ptr; + void *hnd; + int fd; + int index; +} MppBufferInfo; + +#define BUFFER_GROUP_SIZE_DEFAULT (SZ_1M*80) + +/* + * mpp_buffer_import_with_tag(MppBufferGroup group, MppBufferInfo *info, MppBuffer *buffer) + * + * 1. group - specified the MppBuffer to be attached to. + * group can be NULL then this buffer will attached to default legecy group + * Default to NULL on mpp_buffer_import case + * + * 2. info - input information for the output MppBuffer + * info can NOT be NULL. It must contain at least one of ptr/fd. + * + * 3. buffer - generated MppBuffer from MppBufferInfo. + * buffer can be NULL then the buffer is commit to group with unused status. + * Otherwise generated buffer will be directly got and ref_count increased. + * Default to NULL on mpp_buffer_commit case + * + * mpp_buffer_commit usage: + * + * Add a external buffer info to group. This buffer will be on unused status. + * Typical usage is on Android. MediaPlayer gralloc Graphic buffer then commit these buffer + * to decoder's buffer group. Then decoder will recycle these buffer and return buffer reference + * to MediaPlayer for display. + * + * mpp_buffer_import usage: + * + * Transfer a external buffer info to MppBuffer but it is not expected to attached to certain + * buffer group. So the group is set to NULL. Then this buffer can be used for MppFrame/MppPacket. + * Typical usage is for image processing. Image processing normally will be a oneshot operation + * It does not need complicated group management. But in other hand mpp still need to know the + * imported buffer is leak or not and trace its usage inside mpp process. So we attach this kind + * of buffer to default misc buffer group for management. + */ +#define mpp_buffer_commit(group, info) \ + mpp_buffer_import_with_tag(group, info, NULL, MODULE_TAG, __FUNCTION__) + +#define mpp_buffer_import(buffer, info) \ + mpp_buffer_import_with_tag(NULL, info, buffer, MODULE_TAG, __FUNCTION__) + +#define mpp_buffer_get(group, buffer, size) \ + mpp_buffer_get_with_tag(group, buffer, size, MODULE_TAG, __FUNCTION__) + +#define mpp_buffer_put(buffer) \ + mpp_buffer_put_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_inc_ref(buffer) \ + mpp_buffer_inc_ref_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_info_get(buffer, info) \ + mpp_buffer_info_get_with_caller(buffer, info, __FUNCTION__) + +#define mpp_buffer_read(buffer, offset, data, size) \ + mpp_buffer_read_with_caller(buffer, offset, data, size, __FUNCTION__) + +#define mpp_buffer_write(buffer, offset, data, size) \ + mpp_buffer_write_with_caller(buffer, offset, data, size, __FUNCTION__) + +#define mpp_buffer_get_ptr(buffer) \ + mpp_buffer_get_ptr_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_get_fd(buffer) \ + mpp_buffer_get_fd_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_get_size(buffer) \ + mpp_buffer_get_size_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_get_index(buffer) \ + mpp_buffer_get_index_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_set_index(buffer, index) \ + mpp_buffer_set_index_with_caller(buffer, index, __FUNCTION__) + +#define mpp_buffer_get_offset(buffer) \ + mpp_buffer_get_offset_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_set_offset(buffer, offset) \ + mpp_buffer_set_offset_with_caller(buffer, offset, __FUNCTION__) + +#define mpp_buffer_set_discard(buffer) \ + mpp_buffer_discard_with_caller(buffer, __FUNCTION__) + +#define mpp_buffer_sync_begin(buffer) \ + mpp_buffer_sync_begin_f(buffer, 0, __FUNCTION__) +#define mpp_buffer_sync_end(buffer) \ + mpp_buffer_sync_end_f(buffer, 0, __FUNCTION__) +#define mpp_buffer_sync_partial_begin(buffer, offset, length) \ + mpp_buffer_sync_partial_begin_f(buffer, 0, offset, length, __FUNCTION__) +#define mpp_buffer_sync_partial_end(buffer, offset, length) \ + mpp_buffer_sync_partial_end_f(buffer, 0, offset, length, __FUNCTION__) + +#define mpp_buffer_sync_ro_begin(buffer) \ + mpp_buffer_sync_begin_f(buffer, 1, __FUNCTION__) +#define mpp_buffer_sync_ro_end(buffer) \ + mpp_buffer_sync_end_f(buffer, 1, __FUNCTION__) +#define mpp_buffer_sync_ro_partial_begin(buffer, offset, length) \ + mpp_buffer_sync_partial_begin_f(buffer, 1, offset, length, __FUNCTION__) +#define mpp_buffer_sync_ro_partial_end(buffer, offset, length) \ + mpp_buffer_sync_partial_end_f(buffer, 1, offset, length, __FUNCTION__) + +#define mpp_buffer_group_get_internal(group, type, ...) \ + mpp_buffer_group_get(group, (MppBufferType)(type), MPP_BUFFER_INTERNAL, MODULE_TAG, __FUNCTION__) + +#define mpp_buffer_group_get_external(group, type, ...) \ + mpp_buffer_group_get(group, (MppBufferType)(type), MPP_BUFFER_EXTERNAL, MODULE_TAG, __FUNCTION__) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MppBuffer interface + * these interface will change value of group and buffer so before calling functions + * parameter need to be checked. + * + * IMPORTANT: + * mpp_buffer_import_with_tag - compounded interface for commit and import + * + */ +MPP_RET mpp_buffer_import_with_tag(MppBufferGroup group, MppBufferInfo *info, MppBuffer *buffer, + const char *tag, const char *caller); +MPP_RET mpp_buffer_get_with_tag(MppBufferGroup group, MppBuffer *buffer, size_t size, + const char *tag, const char *caller); +MPP_RET mpp_buffer_put_with_caller(MppBuffer buffer, const char *caller); +MPP_RET mpp_buffer_inc_ref_with_caller(MppBuffer buffer, const char *caller); +MPP_RET mpp_buffer_discard_with_caller(MppBuffer buffer, const char *caller); + +MPP_RET mpp_buffer_info_get_with_caller(MppBuffer buffer, MppBufferInfo *info, const char *caller); +MPP_RET mpp_buffer_read_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller); +MPP_RET mpp_buffer_write_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller); +void *mpp_buffer_get_ptr_with_caller(MppBuffer buffer, const char *caller); +int mpp_buffer_get_fd_with_caller(MppBuffer buffer, const char *caller); +size_t mpp_buffer_get_size_with_caller(MppBuffer buffer, const char *caller); +int mpp_buffer_get_index_with_caller(MppBuffer buffer, const char *caller); +MPP_RET mpp_buffer_set_index_with_caller(MppBuffer buffer, int index, const char *caller); +size_t mpp_buffer_get_offset_with_caller(MppBuffer buffer, const char *caller); +MPP_RET mpp_buffer_set_offset_with_caller(MppBuffer buffer, size_t offset, const char *caller); + +/** + * @brief MppBuffer cache operation function + * @param buffer The MppBuffer to run the cache operation + * @param ro for readonly option + * @param offset partial sync data start offset + * @param length partial sync data length + */ +MPP_RET mpp_buffer_sync_begin_f(MppBuffer buffer, RK_S32 ro, const char* caller); +MPP_RET mpp_buffer_sync_end_f(MppBuffer buffer, RK_S32 ro, const char* caller); +MPP_RET mpp_buffer_sync_partial_begin_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller); +MPP_RET mpp_buffer_sync_partial_end_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller); + +MPP_RET mpp_buffer_group_get(MppBufferGroup *group, MppBufferType type, MppBufferMode mode, + const char *tag, const char *caller); +MPP_RET mpp_buffer_group_put(MppBufferGroup group); +MPP_RET mpp_buffer_group_clear(MppBufferGroup group); +RK_S32 mpp_buffer_group_unused(MppBufferGroup group); +size_t mpp_buffer_group_usage(MppBufferGroup group); +MppBufferMode mpp_buffer_group_mode(MppBufferGroup group); +MppBufferType mpp_buffer_group_type(MppBufferGroup group); + +/* + * size : 0 - no limit, other - max buffer size + * count : 0 - no limit, other - max buffer count + */ +MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count); + +RK_U32 mpp_buffer_total_now(void); +RK_U32 mpp_buffer_total_max(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_BUFFER_H */ diff --git a/inc/mpp_compat.h b/inc/mpp_compat.h new file mode 100644 index 000000000..561d184d4 --- /dev/null +++ b/inc/mpp_compat.h @@ -0,0 +1,62 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_COMPAT_H +#define MPP_COMPAT_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef enum MppCompatId_e { + MPP_COMPAT_INC_FBC_BUF_SIZE, + MPP_COMPAT_ENC_ASYNC_INPUT, + MPP_COMPAT_DEC_FBC_HDR_256_ODD, + MPP_COMPAT_BUTT, +} MppCompatId; + +typedef enum MppCompatType_e { + MPP_COMPAT_BOOL, + MPP_COMPAT_S32, + MPP_COMPAT_TYPE_BUTT, +} MppCompatType; + +typedef struct MppCompat_t MppCompat; + +/* external user can only update value_ext to notify mpp to change its behavior */ +struct MppCompat_t { + const MppCompatId feature_id; + const MppCompatType feature_type; + const RK_S32 value_mpp; + RK_S32 value_usr; + const char *name; + MppCompat * const next; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +MppCompat *mpp_compat_query(void); +MppCompat *mpp_compat_query_by_id(MppCompatId id); +MPP_RET mpp_compat_update(MppCompat *compat, RK_S32 value); + +void mpp_compat_show(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_COMPAT_H */ diff --git a/inc/mpp_err.h b/inc/mpp_err.h index 58156b170..596b1577a 100644 --- a/inc/mpp_err.h +++ b/inc/mpp_err.h @@ -1,46 +1,43 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_ERR_H__ -#define __MPP_ERR_H__ - -#define RK_OK 0 -#define RK_SUCCESS 0 - -typedef enum { - MPP_SUCCESS = RK_SUCCESS, - MPP_OK = RK_OK, - - MPP_NOK = -1, - MPP_ERR_UNKNOW = -2, - MPP_ERR_NULL_PTR = -3, - MPP_ERR_MALLOC = -4, - MPP_ERR_OPEN_FILE = -5, - MPP_ERR_VALUE = -6, - MPP_ERR_READ_BIT = -7, - - MPP_ERR_BASE = -1000, - - MPP_ERR_LIST_STREAM = MPP_ERR_BASE - 1, - MPP_ERR_INIT = MPP_ERR_BASE - 2, - MPP_ERR_VPU_CODEC_INIT = MPP_ERR_BASE - 3, - MPP_ERR_STREAM = MPP_ERR_BASE - 4, - MPP_ERR_FATAL_THREAD = MPP_ERR_BASE - 5, - MPP_EOS_STREAM_REACHED = MPP_ERR_BASE - 11, - -} MPP_RET; - -#endif /*__MPP_ERR_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_ERR_H +#define MPP_ERR_H + +#define RK_OK 0 +#define RK_SUCCESS 0 + +typedef enum { + MPP_SUCCESS = RK_SUCCESS, + MPP_OK = RK_OK, + + MPP_NOK = -1, + MPP_ERR_UNKNOW = -2, + MPP_ERR_NULL_PTR = -3, + MPP_ERR_MALLOC = -4, + MPP_ERR_OPEN_FILE = -5, + MPP_ERR_VALUE = -6, + MPP_ERR_READ_BIT = -7, + MPP_ERR_TIMEOUT = -8, + MPP_ERR_PERM = -9, + + MPP_ERR_BASE = -1000, + + /* The error in stream processing */ + MPP_ERR_LIST_STREAM = MPP_ERR_BASE - 1, + MPP_ERR_INIT = MPP_ERR_BASE - 2, + MPP_ERR_VPU_CODEC_INIT = MPP_ERR_BASE - 3, + MPP_ERR_STREAM = MPP_ERR_BASE - 4, + MPP_ERR_FATAL_THREAD = MPP_ERR_BASE - 5, + MPP_ERR_NOMEM = MPP_ERR_BASE - 6, + MPP_ERR_PROTOL = MPP_ERR_BASE - 7, + MPP_FAIL_SPLIT_FRAME = MPP_ERR_BASE - 8, + MPP_ERR_VPUHW = MPP_ERR_BASE - 9, + MPP_EOS_STREAM_REACHED = MPP_ERR_BASE - 11, + MPP_ERR_BUFFER_FULL = MPP_ERR_BASE - 12, + MPP_ERR_DISPLAY_FULL = MPP_ERR_BASE - 13, +} MPP_RET; + +#endif /* MPP_ERR_H */ diff --git a/inc/mpp_frame.h b/inc/mpp_frame.h index 2acda257d..5e175ec95 100644 --- a/inc/mpp_frame.h +++ b/inc/mpp_frame.h @@ -1,189 +1,480 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_FRAME_H__ -#define __MPP_FRAME_H__ - -#include "mpp_buffer.h" - -typedef void* MppFrame; - -/* - * bit definition for mode flag in MppFrame - */ -#define MPP_FRAME_FLAG_FRAME (0x00000000) -#define MPP_FRAME_FLAG_TOP_FIELD (0x00000001) -#define MPP_FRAME_FLAG_BOT_FIELD (0x00000002) -#define MPP_FRAME_FLAG_PAIRED_FIELD (MPP_FRAME_FLAG_TOP_FIELD|MPP_FRAME_FLAG_BOT_FIELD) -#define MPP_FRAME_FLAG_DEINTERLACED (0x00000004) -#define MPP_FRAME_FLAG_TOP_FIRST (0x00000008) -// for multiview stream -#define MPP_FRAME_FLAG_VIEW_ID_MASK (0x000000f0) - - -/* - * MPEG vs JPEG YUV range. - */ -typedef enum { - MPP_FRAME_RANGE_UNSPECIFIED = 0, - MPP_FRAME_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges - MPP_FRAME_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges - MPP_FRAME_RANGE_NB, ///< Not part of ABI -} MppFrameColorRange; - -/* - * Chromaticity coordinates of the source primaries. - */ -typedef enum { - MPP_FRAME_PRI_RESERVED0 = 0, - MPP_FRAME_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B - MPP_FRAME_PRI_UNSPECIFIED = 2, - MPP_FRAME_PRI_RESERVED = 3, - MPP_FRAME_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) - - MPP_FRAME_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM - MPP_FRAME_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC - MPP_FRAME_PRI_SMPTE240M = 7, ///< functionally identical to above - MPP_FRAME_PRI_FILM = 8, ///< colour filters using Illuminant C - MPP_FRAME_PRI_BT2020 = 9, ///< ITU-R BT2020 - MPP_FRAME_PRI_NB, ///< Not part of ABI -} MppFrameColorPrimaries; - -/* - * Color Transfer Characteristic. - */ -typedef enum { - MPP_FRAME_TRC_RESERVED0 = 0, - MPP_FRAME_TRC_BT709 = 1, ///< also ITU-R BT1361 - MPP_FRAME_TRC_UNSPECIFIED = 2, - MPP_FRAME_TRC_RESERVED = 3, - MPP_FRAME_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM - MPP_FRAME_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG - MPP_FRAME_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC - MPP_FRAME_TRC_SMPTE240M = 7, - MPP_FRAME_TRC_LINEAR = 8, ///< "Linear transfer characteristics" - MPP_FRAME_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" - MPP_FRAME_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" - MPP_FRAME_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 - MPP_FRAME_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut - MPP_FRAME_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) - MPP_FRAME_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10 bit system - MPP_FRAME_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12 bit system - MPP_FRAME_TRC_NB, ///< Not part of ABI -} MppFrameColorTransferCharacteristic; - -/* - * YUV colorspace type. - */ -typedef enum { - MPP_FRAME_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) - MPP_FRAME_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B - MPP_FRAME_SPC_UNSPECIFIED = 2, - MPP_FRAME_SPC_RESERVED = 3, - MPP_FRAME_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) - MPP_FRAME_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 - MPP_FRAME_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above - MPP_FRAME_SPC_SMPTE240M = 7, - MPP_FRAME_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 - MPP_FRAME_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system - MPP_FRAME_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system - MPP_FRAME_SPC_NB, ///< Not part of ABI -} MppFrameColorSpace; - -/* - * Location of chroma samples. - * - * Illustration showing the location of the first (top left) chroma sample of the - * image, the left shows only luma, the right - * shows the location of the chroma sample, the 2 could be imagined to overlay - * each other but are drawn separately due to limitations of ASCII - * - * 1st 2nd 1st 2nd horizontal luma sample positions - * v v v v - * ______ ______ - *1st luma line > |X X ... |3 4 X ... X are luma samples, - * | |1 2 1-6 are possible chroma positions - *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position - */ -typedef enum { - MPP_CHROMA_LOC_UNSPECIFIED = 0, - MPP_CHROMA_LOC_LEFT = 1, ///< mpeg2/4 4:2:0, h264 default for 4:2:0 - MPP_CHROMA_LOC_CENTER = 2, ///< mpeg1 4:2:0, jpeg 4:2:0, h263 4:2:0 - MPP_CHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 - MPP_CHROMA_LOC_TOP = 4, - MPP_CHROMA_LOC_BOTTOMLEFT = 5, - MPP_CHROMA_LOC_BOTTOM = 6, - MPP_CHROMA_LOC_NB, ///< Not part of ABI -} MppFrameChromaLocation; - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * MppFrame interface - */ -MPP_RET mpp_frame_init(MppFrame *frame); -MPP_RET mpp_frame_deinit(MppFrame *frame); -MppFrame mpp_frame_get_next(MppFrame frame); - -/* - * normal parameter - */ -RK_U32 mpp_frame_get_width(const MppFrame frame); -void mpp_frame_set_width(MppFrame frame, RK_U32 width); -RK_U32 mpp_frame_get_height(const MppFrame frame); -void mpp_frame_set_height(MppFrame frame, RK_U32 height); -RK_U32 mpp_frame_get_hor_stride(const MppFrame frame); -void mpp_frame_set_hor_stride(MppFrame frame, RK_U32 hor_stride); -RK_U32 mpp_frame_get_ver_stride(const MppFrame frame); -void mpp_frame_set_ver_stride(MppFrame frame, RK_U32 ver_stride); -RK_U32 mpp_frame_get_mode(const MppFrame frame); -void mpp_frame_set_mode(MppFrame frame, RK_U32 mode); -RK_S64 mpp_frame_get_pts(const MppFrame frame); -void mpp_frame_set_pts(MppFrame frame, RK_S64 pts); -RK_S64 mpp_frame_get_dts(const MppFrame frame); -void mpp_frame_set_dts(MppFrame frame, RK_S64 dts); - -/* - * buffer parameter - */ -MppBuffer mpp_frame_get_buffer(const MppFrame frame); -void mpp_frame_set_buffer(MppFrame frame, MppBuffer buffer); - -/* - * color related parameter - */ -MppFrameColorRange mpp_frame_get_color_range(const MppFrame frame); -void mpp_frame_set_color_range(MppFrame frame, MppFrameColorRange color_range); -MppFrameColorPrimaries mpp_frame_get_color_primaries(const MppFrame frame); -void mpp_frame_set_color_primaries(MppFrame frame, MppFrameColorPrimaries color_primaries); -MppFrameColorTransferCharacteristic mpp_frame_get_color_trc(const MppFrame frame); -void mpp_frame_set_color_trc(MppFrame frame, MppFrameColorTransferCharacteristic color_trc); -MppFrameColorSpace mpp_frame_get_colorspace(const MppFrame frame); -void mpp_frame_set_colorspace(MppFrame frame, MppFrameColorSpace colorspace); -MppFrameChromaLocation mpp_frame_get_chroma_location(const MppFrame frame); -void mpp_frame_set_chroma_location(MppFrame frame, MppFrameChromaLocation chroma_location); - -/* - * HDR parameter - */ - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_FRAME_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_FRAME_H +#define MPP_FRAME_H + +#include "mpp_buffer.h" +#include "mpp_meta.h" + +/* + * bit definition for mode flag in MppFrame + */ +/* progressive frame */ +#define MPP_FRAME_FLAG_FRAME (0x00000000) +/* top field only */ +#define MPP_FRAME_FLAG_TOP_FIELD (0x00000001) +/* bottom field only */ +#define MPP_FRAME_FLAG_BOT_FIELD (0x00000002) +/* paired field */ +#define MPP_FRAME_FLAG_PAIRED_FIELD (MPP_FRAME_FLAG_TOP_FIELD|MPP_FRAME_FLAG_BOT_FIELD) +/* paired field with field order of top first */ +#define MPP_FRAME_FLAG_TOP_FIRST (0x00000004) +/* paired field with field order of bottom first */ +#define MPP_FRAME_FLAG_BOT_FIRST (0x00000008) +/* paired field with unknown field order (MBAFF) */ +#define MPP_FRAME_FLAG_DEINTERLACED (MPP_FRAME_FLAG_TOP_FIRST|MPP_FRAME_FLAG_BOT_FIRST) +#define MPP_FRAME_FLAG_FIELD_ORDER_MASK (0x0000000C) +// for multiview stream +#define MPP_FRAME_FLAG_VIEW_ID_MASK (0x000000f0) + +#define MPP_FRAME_FLAG_IEP_DEI_MASK (0x00000f00) +#define MPP_FRAME_FLAG_IEP_DEI_I2O1 (0x00000100) +#define MPP_FRAME_FLAG_IEP_DEI_I4O2 (0x00000200) +#define MPP_FRAME_FLAG_IEP_DEI_I4O1 (0x00000300) + +/* + * MPEG vs JPEG YUV range. + */ +typedef enum { + MPP_FRAME_RANGE_UNSPECIFIED = 0, + MPP_FRAME_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges + MPP_FRAME_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges + MPP_FRAME_RANGE_NB, ///< Not part of ABI +} MppFrameColorRange; + +typedef enum { + MPP_FRAME_CHROMA_DOWN_SAMPLE_MODE_NONE, + MPP_FRAME_CHORMA_DOWN_SAMPLE_MODE_AVERAGE, + MPP_FRAME_CHORMA_DOWN_SAMPLE_MODE_DISCARD, +} MppFrameChromaDownSampleMode; + +typedef enum { + MPP_FRAME_VIDEO_FMT_COMPONEMT = 0, + MPP_FRAME_VIDEO_FMT_PAL = 1, + MPP_FRAME_VIDEO_FMT_NTSC = 2, + MPP_FRAME_VIDEO_FMT_SECAM = 3, + MPP_FRAME_VIDEO_FMT_MAC = 4, + MPP_FRAME_VIDEO_FMT_UNSPECIFIED = 5, + MPP_FRAME_VIDEO_FMT_RESERVED0 = 6, + MPP_FRAME_VIDEO_FMT_RESERVED1 = 7, +} MppFrameVideoFormat; + +/* + * Chromaticity coordinates of the source primaries. + */ +typedef enum { + MPP_FRAME_PRI_RESERVED0 = 0, + MPP_FRAME_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + MPP_FRAME_PRI_UNSPECIFIED = 2, + MPP_FRAME_PRI_RESERVED = 3, + MPP_FRAME_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + MPP_FRAME_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + MPP_FRAME_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC/SMPTE ST 170 (2004) + MPP_FRAME_PRI_SMPTE240M = 7, ///< functionally identical to above/SMPTE ST 240 + MPP_FRAME_PRI_FILM = 8, ///< colour filters using Illuminant C + MPP_FRAME_PRI_BT2020 = 9, ///< ITU-R BT2020 / ITU-R BT.2100-2 + MPP_FRAME_PRI_SMPTEST428_1 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + MPP_FRAME_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 + MPP_FRAME_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + MPP_FRAME_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphors + MPP_FRAME_PRI_NB, ///< Not part of ABI +} MppFrameColorPrimaries; + +/* + * Color Transfer Characteristic. + */ +typedef enum { + MPP_FRAME_TRC_RESERVED0 = 0, + MPP_FRAME_TRC_BT709 = 1, ///< also ITU-R BT1361 + MPP_FRAME_TRC_UNSPECIFIED = 2, + MPP_FRAME_TRC_RESERVED = 3, + MPP_FRAME_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + MPP_FRAME_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + MPP_FRAME_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + MPP_FRAME_TRC_SMPTE240M = 7, + MPP_FRAME_TRC_LINEAR = 8, ///< "Linear transfer characteristics" + MPP_FRAME_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)" + MPP_FRAME_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + MPP_FRAME_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4 + MPP_FRAME_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut + MPP_FRAME_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) + MPP_FRAME_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10 bit system + MPP_FRAME_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12 bit system + MPP_FRAME_TRC_SMPTEST2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + MPP_FRAME_TRC_SMPTEST428_1 = 17, ///< SMPTE ST 428-1 + MPP_FRAME_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" + MPP_FRAME_TRC_NB, ///< Not part of ABI +} MppFrameColorTransferCharacteristic; + +/* + * YUV colorspace type. + */ +typedef enum { + MPP_FRAME_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) + MPP_FRAME_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + MPP_FRAME_SPC_UNSPECIFIED = 2, + MPP_FRAME_SPC_RESERVED = 3, + MPP_FRAME_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + MPP_FRAME_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + MPP_FRAME_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + MPP_FRAME_SPC_SMPTE240M = 7, + MPP_FRAME_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + MPP_FRAME_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system + MPP_FRAME_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system + MPP_FRAME_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'x + MPP_FRAME_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system + MPP_FRAME_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system + MPP_FRAME_SPC_ICTCP = 14, ///< ITU-R BT.2100-0, ICtCp + MPP_FRAME_SPC_NB, ///< Not part of ABI +} MppFrameColorSpace; + +/* + * Location of chroma samples. + * + * Illustration showing the location of the first (top left) chroma sample of the + * image, the left shows only luma, the right + * shows the location of the chroma sample, the 2 could be imagined to overlay + * each other but are drawn separately due to limitations of ASCII + * + * 1st 2nd 1st 2nd horizontal luma sample positions + * v v v v + * ______ ______ + *1st luma line > |X X ... |3 4 X ... X are luma samples, + * | |1 2 1-6 are possible chroma positions + *2nd luma line > |X X ... |5 6 X ... 0 is undefined/unknown position + */ +typedef enum { + MPP_CHROMA_LOC_UNSPECIFIED = 0, + MPP_CHROMA_LOC_LEFT = 1, ///< mpeg2/4 4:2:0, h264 default for 4:2:0 + MPP_CHROMA_LOC_CENTER = 2, ///< mpeg1 4:2:0, jpeg 4:2:0, h263 4:2:0 + MPP_CHROMA_LOC_TOPLEFT = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2 + MPP_CHROMA_LOC_TOP = 4, + MPP_CHROMA_LOC_BOTTOMLEFT = 5, + MPP_CHROMA_LOC_BOTTOM = 6, + MPP_CHROMA_LOC_NB, ///< Not part of ABI +} MppFrameChromaLocation; + +typedef enum { + MPP_CHROMA_UNSPECIFIED, + MPP_CHROMA_400, + MPP_CHROMA_410, + MPP_CHROMA_411, + MPP_CHROMA_420, + MPP_CHROMA_422, + MPP_CHROMA_440, + MPP_CHROMA_444, +} MppFrameChromaFormat; + +/* + * MppFrameFormat bit flag: + * + * +-----------------------------------------------+ + * | 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 | + * +-----------------------------------------------+ + * bit 0 ~ 15: YUV / RGB format value + * bit 16 ~ 19: YUV / RGB flag 0 - YUV; 1 - RGB; + * bit 20 ~ 23: Frame Buffer Compression (FBC) flag, 0 - No FBC; 1 - FBCv1; 2 - FBCv2; + * bit 24 : Big / little end flag, 0 - big end; 1 - little end; + * bit 25 : Tile format flag, 0 - No tile; 1 - tile format; + * bit 26 ~ 27: High Dynamic Range (HDR) flag, 0 - Standard Dynamic Range (SDR); 1 - HDR; + * + * NOTE: FBC format and tile format can not exist at the same time. + */ + +#define MPP_FRAME_FMT_MASK (0x000fffff) +#define MPP_FRAME_FMT_PROP_MASK (0x0ff00000) + +#define MPP_FRAME_FMT_COLOR_MASK (0x000f0000) +#define MPP_FRAME_FMT_YUV (0x00000000) +#define MPP_FRAME_FMT_RGB (0x00010000) + +#define MPP_FRAME_FBC_MASK (0x00f00000) +#define MPP_FRAME_FBC_NONE (0x00000000) + +#define MPP_FRAME_HDR_MASK (0x0c000000) +#define MPP_FRAME_HDR_NONE (0x00000000) +#define MPP_FRAME_HDR (0x04000000) + +#define MPP_FRAME_TILE_FLAG (0x02000000) + +/* + * AFBC_V1 is for ISP output. + * It has default payload offset to be calculated * from width and height: + * Payload offset = MPP_ALIGN(MPP_ALIGN(width, 16) * MPP_ALIGN(height, 16) / 16, SZ_4K) + */ +#define MPP_FRAME_FBC_AFBC_V1 (0x00100000) +/* + * AFBC_V2 is for video decoder output. + * It stores payload offset in first 32-bit in header address + * Payload offset is always set to zero. + */ +#define MPP_FRAME_FBC_AFBC_V2 (0x00200000) + +/* +* RKFBC is for video decoder output and video encoder Input. +* It has default header stride to be calculated * from width and height: +* Header stride = MPP_ALIGN(width, 64) / 64 * 16 +* Payload offset is always set to zero. +*/ +#define MPP_FRAME_FBC_RKFBC (0x00400000) + +#define MPP_FRAME_FMT_LE_MASK (0x01000000) + +#define MPP_FRAME_FMT_IS_YUV(fmt) (((fmt & MPP_FRAME_FMT_COLOR_MASK) == MPP_FRAME_FMT_YUV) && \ + ((fmt & MPP_FRAME_FMT_MASK) < MPP_FMT_YUV_BUTT)) +#define MPP_FRAME_FMT_IS_YUV_10BIT(fmt) ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP_10BIT || \ + (fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV422SP_10BIT || \ + (fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP_10BIT) +#define MPP_FRAME_FMT_IS_RGB(fmt) (((fmt & MPP_FRAME_FMT_COLOR_MASK) == MPP_FRAME_FMT_RGB) && \ + ((fmt & MPP_FRAME_FMT_MASK) < MPP_FMT_RGB_BUTT)) + +/* + * For MPP_FRAME_FBC_AFBC_V1 the 16byte aligned stride is used. + */ +#define MPP_FRAME_FMT_IS_FBC(fmt) (fmt & MPP_FRAME_FBC_MASK) +#define MPP_FRAME_FMT_IS_AFBC(fmt) (fmt & (MPP_FRAME_FBC_AFBC_V1 | MPP_FRAME_FBC_AFBC_V2)) +#define MPP_FRAME_FMT_IS_RKFBC(fmt) (fmt & MPP_FRAME_FBC_RKFBC) + +#define MPP_FRAME_FMT_IS_HDR(fmt) (fmt & MPP_FRAME_HDR_MASK) + +#define MPP_FRAME_FMT_IS_LE(fmt) ((fmt & MPP_FRAME_FMT_LE_MASK) == MPP_FRAME_FMT_LE_MASK) +#define MPP_FRAME_FMT_IS_BE(fmt) ((fmt & MPP_FRAME_FMT_LE_MASK) == 0) + +#define MPP_FRAME_FMT_IS_TILE(fmt) (fmt & MPP_FRAME_TILE_FLAG) + +/* mpp color format index definition */ +typedef enum { + MPP_FMT_YUV420SP = (MPP_FRAME_FMT_YUV + 0), /* YYYY... UV... (NV12) */ + /* + * A rockchip specific pixel format, without gap between pixel against + * the P010_10LE/P010_10BE + */ + MPP_FMT_YUV420SP_10BIT = (MPP_FRAME_FMT_YUV + 1), + MPP_FMT_YUV422SP = (MPP_FRAME_FMT_YUV + 2), /* YYYY... UVUV... (NV16) */ + MPP_FMT_YUV422SP_10BIT = (MPP_FRAME_FMT_YUV + 3), ///< Not part of ABI + MPP_FMT_YUV420P = (MPP_FRAME_FMT_YUV + 4), /* YYYY... U...V... (I420) */ + MPP_FMT_YUV420SP_VU = (MPP_FRAME_FMT_YUV + 5), /* YYYY... VUVUVU... (NV21) */ + MPP_FMT_YUV422P = (MPP_FRAME_FMT_YUV + 6), /* YYYY... UU...VV...(422P) */ + MPP_FMT_YUV422SP_VU = (MPP_FRAME_FMT_YUV + 7), /* YYYY... VUVUVU... (NV61) */ + MPP_FMT_YUV422_YUYV = (MPP_FRAME_FMT_YUV + 8), /* YUYVYUYV... (YUY2) */ + MPP_FMT_YUV422_YVYU = (MPP_FRAME_FMT_YUV + 9), /* YVYUYVYU... (YVY2) */ + MPP_FMT_YUV422_UYVY = (MPP_FRAME_FMT_YUV + 10), /* UYVYUYVY... (UYVY) */ + MPP_FMT_YUV422_VYUY = (MPP_FRAME_FMT_YUV + 11), /* VYUYVYUY... (VYUY) */ + MPP_FMT_YUV400 = (MPP_FRAME_FMT_YUV + 12), /* YYYY... */ + MPP_FMT_YUV440SP = (MPP_FRAME_FMT_YUV + 13), /* YYYY... UVUV... */ + MPP_FMT_YUV411SP = (MPP_FRAME_FMT_YUV + 14), /* YYYY... UV... */ + MPP_FMT_YUV444SP = (MPP_FRAME_FMT_YUV + 15), /* YYYY... UVUVUVUV... */ + MPP_FMT_YUV444P = (MPP_FRAME_FMT_YUV + 16), /* YYYY... UUUU... VVVV... */ + MPP_FMT_YUV444SP_10BIT = (MPP_FRAME_FMT_YUV + 17), + MPP_FMT_AYUV2BPP = (MPP_FRAME_FMT_YUV + 18), /* YYYY... UVUVUVUV... */ + MPP_FMT_AYUV1BPP = (MPP_FRAME_FMT_YUV + 19), + MPP_FMT_YUV_BUTT, + + MPP_FMT_RGB565 = (MPP_FRAME_FMT_RGB + 0), /* 16-bit RGB */ + MPP_FMT_BGR565 = (MPP_FRAME_FMT_RGB + 1), /* 16-bit RGB */ + MPP_FMT_RGB555 = (MPP_FRAME_FMT_RGB + 2), /* 15-bit RGB */ + MPP_FMT_BGR555 = (MPP_FRAME_FMT_RGB + 3), /* 15-bit RGB */ + MPP_FMT_RGB444 = (MPP_FRAME_FMT_RGB + 4), /* 12-bit RGB */ + MPP_FMT_BGR444 = (MPP_FRAME_FMT_RGB + 5), /* 12-bit RGB */ + MPP_FMT_RGB888 = (MPP_FRAME_FMT_RGB + 6), /* 24-bit RGB */ + MPP_FMT_BGR888 = (MPP_FRAME_FMT_RGB + 7), /* 24-bit RGB */ + MPP_FMT_RGB101010 = (MPP_FRAME_FMT_RGB + 8), /* 30-bit RGB */ + MPP_FMT_BGR101010 = (MPP_FRAME_FMT_RGB + 9), /* 30-bit RGB */ + MPP_FMT_ARGB8888 = (MPP_FRAME_FMT_RGB + 10), /* 32-bit RGB */ + MPP_FMT_ABGR8888 = (MPP_FRAME_FMT_RGB + 11), /* 32-bit RGB */ + MPP_FMT_BGRA8888 = (MPP_FRAME_FMT_RGB + 12), /* 32-bit RGB */ + MPP_FMT_RGBA8888 = (MPP_FRAME_FMT_RGB + 13), /* 32-bit RGB */ + MPP_FMT_ARGB4444 = (MPP_FRAME_FMT_RGB + 14), /* 16-bit RGB */ + MPP_FMT_ARGB1555 = (MPP_FRAME_FMT_RGB + 15), /* 2-bit RGB */ + MPP_FMT_RGB_BUTT, + + MPP_FMT_BUTT, +} MppFrameFormat; + +/** + * Rational number (pair of numerator and denominator). + */ +typedef struct MppFrameRational { + RK_S32 num; ///< Numerator + RK_S32 den; ///< Denominator +} MppFrameRational; + +typedef struct MppFrameMasteringDisplayMetadata { + RK_U16 display_primaries[3][2]; + RK_U16 white_point[2]; + RK_U32 max_luminance; + RK_U32 min_luminance; +} MppFrameMasteringDisplayMetadata; + +typedef struct MppFrameContentLightMetadata { + RK_U16 MaxCLL; + RK_U16 MaxFALL; +} MppFrameContentLightMetadata; + +typedef struct MppFrameHdrDynamicMeta { + RK_U32 hdr_fmt; + RK_U32 size; + RK_U8 data[0]; +} MppFrameHdrDynamicMeta; + +typedef enum MppFrameError { + /* General error not specified */ + MPP_FRAME_ERR_UNKNOW = 0x0001, + + /* Critical error for decoder not support error */ + MPP_FRAME_ERR_UNSUPPORT = 0x0002, + + /* + * Fatal error for decoder can not parse a valid frame for hardware. + * the pixel data is all invalid. + */ + MPP_FRAME_ERR_DEC_INVALID = 0x0010, + + /* + * Normal error for decoder found hardware error on decoding. + */ + MPP_FRAME_ERR_DEC_HW_ERR = 0x0100, + + /* + * Normal error for decoder found missing reference frame on decoding. + */ + MPP_FRAME_ERR_DEC_MISS_REF = 0x0200, +} MppFrameError; + +typedef enum { + MPP_FRAME_THUMBNAIL_NONE, + MPP_FRAME_THUMBNAIL_MIXED, + MPP_FRAME_THUMBNAIL_ONLY, +} MppFrameThumbnailMode; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MppFrame interface + */ +MPP_RET mpp_frame_init(MppFrame *frame); +MPP_RET mpp_frame_deinit(MppFrame *frame); + +/* + * normal parameter + * + * offset_x + * <--------> + * + * <---------------+ hor_stride +---------------> + * + * +------------------------------------------------------+ ^ ^ + * | | | | + * | | | | offset_y + * | | | | + * | +--------------------------------+ ^ | | v + * | | | | | | + * | | | + | + + * | | | | + * | | valid data area | height | ver_stride + * | | | | + * | | | + | + + * | | | | | | + * | +--------------------------------+ v | | + * | | | + * | <----------+ width +---------> | | + * | | | + * +------------------------------------------------------+ v + * + */ +RK_U32 mpp_frame_get_width(const MppFrame frame); +void mpp_frame_set_width(MppFrame frame, RK_U32 width); +RK_U32 mpp_frame_get_height(const MppFrame frame); +void mpp_frame_set_height(MppFrame frame, RK_U32 height); +RK_U32 mpp_frame_get_hor_stride(const MppFrame frame); +void mpp_frame_set_hor_stride(MppFrame frame, RK_U32 hor_stride); +RK_U32 mpp_frame_get_ver_stride(const MppFrame frame); +void mpp_frame_set_ver_stride(MppFrame frame, RK_U32 ver_stride); +void mpp_frame_set_hor_stride_pixel(MppFrame frame, RK_U32 hor_stride_pixel); +RK_U32 mpp_frame_get_hor_stride_pixel(const MppFrame frame); +void mpp_frame_set_fbc_hdr_stride(MppFrame frame, RK_U32 fbc_hdr_stride); +RK_U32 mpp_frame_get_fbc_hdr_stride(const MppFrame frame); + +RK_U32 mpp_frame_get_offset_x(const MppFrame frame); +void mpp_frame_set_offset_x(MppFrame frame, RK_U32 offset_x); +RK_U32 mpp_frame_get_offset_y(const MppFrame frame); +void mpp_frame_set_offset_y(MppFrame frame, RK_U32 offset_y); +RK_U32 mpp_frame_get_mode(const MppFrame frame); +void mpp_frame_set_mode(MppFrame frame, RK_U32 mode); +RK_U32 mpp_frame_get_discard(const MppFrame frame); +void mpp_frame_set_discard(MppFrame frame, RK_U32 discard); +RK_U32 mpp_frame_get_viewid(const MppFrame frame); +void mpp_frame_set_viewid(MppFrame frame, RK_U32 viewid); +RK_U32 mpp_frame_get_poc(const MppFrame frame); +void mpp_frame_set_poc(MppFrame frame, RK_U32 poc); +RK_S64 mpp_frame_get_pts(const MppFrame frame); +void mpp_frame_set_pts(MppFrame frame, RK_S64 pts); +RK_S64 mpp_frame_get_dts(const MppFrame frame); +void mpp_frame_set_dts(MppFrame frame, RK_S64 dts); +RK_U32 mpp_frame_get_errinfo(const MppFrame frame); +void mpp_frame_set_errinfo(MppFrame frame, RK_U32 errinfo); +size_t mpp_frame_get_buf_size(const MppFrame frame); +void mpp_frame_set_buf_size(MppFrame frame, size_t buf_size); +void mpp_frame_set_thumbnail_en(MppFrame frame, RK_U32 thumbnail_en); +RK_U32 mpp_frame_get_thumbnail_en(const MppFrame frame); + +/* + * flow control parmeter + */ +RK_U32 mpp_frame_get_eos(const MppFrame frame); +void mpp_frame_set_eos(MppFrame frame, RK_U32 eos); +RK_U32 mpp_frame_get_info_change(const MppFrame frame); +void mpp_frame_set_info_change(MppFrame frame, RK_U32 info_change); + +/* + * buffer parameter + */ +MppBuffer mpp_frame_get_buffer(const MppFrame frame); +void mpp_frame_set_buffer(MppFrame frame, MppBuffer buffer); + +/* + * meta data parameter + */ +RK_S32 mpp_frame_has_meta(const MppFrame frame); +MppMeta mpp_frame_get_meta(const MppFrame frame); +void mpp_frame_set_meta(MppFrame frame, MppMeta meta); + +/* + * color related parameter + */ +MppFrameColorRange mpp_frame_get_color_range(const MppFrame frame); +void mpp_frame_set_color_range(MppFrame frame, MppFrameColorRange color_range); +MppFrameColorPrimaries mpp_frame_get_color_primaries(const MppFrame frame); +void mpp_frame_set_color_primaries(MppFrame frame, MppFrameColorPrimaries color_primaries); +MppFrameColorTransferCharacteristic mpp_frame_get_color_trc(const MppFrame frame); +void mpp_frame_set_color_trc(MppFrame frame, MppFrameColorTransferCharacteristic color_trc); +MppFrameColorSpace mpp_frame_get_colorspace(const MppFrame frame); +void mpp_frame_set_colorspace(MppFrame frame, MppFrameColorSpace colorspace); +MppFrameChromaLocation mpp_frame_get_chroma_location(const MppFrame frame); +void mpp_frame_set_chroma_location(MppFrame frame, MppFrameChromaLocation chroma_location); +MppFrameFormat mpp_frame_get_fmt(MppFrame frame); +void mpp_frame_set_fmt(MppFrame frame, MppFrameFormat fmt); +MppFrameRational mpp_frame_get_sar(const MppFrame frame); +void mpp_frame_set_sar(MppFrame frame, MppFrameRational sar); +MppFrameMasteringDisplayMetadata mpp_frame_get_mastering_display(const MppFrame frame); +void mpp_frame_set_mastering_display(MppFrame frame, MppFrameMasteringDisplayMetadata mastering_display); +MppFrameContentLightMetadata mpp_frame_get_content_light(const MppFrame frame); +void mpp_frame_set_content_light(MppFrame frame, MppFrameContentLightMetadata content_light); +MppFrameHdrDynamicMeta* mpp_frame_get_hdr_dynamic_meta(const MppFrame frame); +void mpp_frame_set_hdr_dynamic_meta(MppFrame frame, MppFrameHdrDynamicMeta *vivi_data); + +/* + * HDR parameter + */ + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_FRAME_H */ diff --git a/inc/mpp_log.h b/inc/mpp_log.h new file mode 100644 index 000000000..7c57cb7ad --- /dev/null +++ b/inc/mpp_log.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_LOG_H +#define MPP_LOG_H + +#include + +#include "rk_type.h" +#include "mpp_log_def.h" + +/* + * _c function will add condition check + * _f function will add function name to the log + * _cf function will add both function name and condition check + */ + +/* + * mpp runtime log system usage: + * mpp_logf is for fatal logging. For use when aborting + * mpp_loge is for error logging. For use with unrecoverable failures. + * mpp_logw is for warning logging. For use with recoverable failures. + * mpp_logi is for informational logging. + * mpp_logd is for debug logging. + * mpp_logv is for verbose logging + */ + +#define mpp_logf(fmt, ...) _mpp_log_l(MPP_LOG_FATAL, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_loge(fmt, ...) _mpp_log_l(MPP_LOG_ERROR, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_logw(fmt, ...) _mpp_log_l(MPP_LOG_WARN, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_logi(fmt, ...) _mpp_log_l(MPP_LOG_INFO, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_logd(fmt, ...) _mpp_log_l(MPP_LOG_DEBUG, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_logv(fmt, ...) _mpp_log_l(MPP_LOG_VERBOSE, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) + +#define mpp_logf_f(fmt, ...) _mpp_log_l(MPP_LOG_FATAL, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_loge_f(fmt, ...) _mpp_log_l(MPP_LOG_ERROR, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_logw_f(fmt, ...) _mpp_log_l(MPP_LOG_WARN, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_logi_f(fmt, ...) _mpp_log_l(MPP_LOG_INFO, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_logd_f(fmt, ...) _mpp_log_l(MPP_LOG_DEBUG, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_logv_f(fmt, ...) _mpp_log_l(MPP_LOG_VERBOSE, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) + +#define mpp_logf_c(cond, fmt, ...) do { if (cond) mpp_logf(fmt, ## __VA_ARGS__); } while (0) +#define mpp_loge_c(cond, fmt, ...) do { if (cond) mpp_loge(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logw_c(cond, fmt, ...) do { if (cond) mpp_logw(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logi_c(cond, fmt, ...) do { if (cond) mpp_logi(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logd_c(cond, fmt, ...) do { if (cond) mpp_logd(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logv_c(cond, fmt, ...) do { if (cond) mpp_logv(fmt, ## __VA_ARGS__); } while (0) + +#define mpp_logf_cf(cond, fmt, ...) do { if (cond) mpp_logf_f(fmt, ## __VA_ARGS__); } while (0) +#define mpp_loge_cf(cond, fmt, ...) do { if (cond) mpp_loge_f(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logw_cf(cond, fmt, ...) do { if (cond) mpp_logw_f(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logi_cf(cond, fmt, ...) do { if (cond) mpp_logi_f(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logd_cf(cond, fmt, ...) do { if (cond) mpp_logd_f(fmt, ## __VA_ARGS__); } while (0) +#define mpp_logv_cf(cond, fmt, ...) do { if (cond) mpp_logv_f(fmt, ## __VA_ARGS__); } while (0) + +/* + * mpp runtime log system usage: + * mpp_err is for error status message, it will print for sure. + * mpp_log is for important message like open/close/reset/flush, it will print too. + */ + +#define mpp_log(fmt, ...) mpp_logi(fmt, ## __VA_ARGS__) +#define mpp_err(fmt, ...) mpp_loge(fmt, ## __VA_ARGS__) + +#define mpp_log_f(fmt, ...) mpp_logi_f(fmt, ## __VA_ARGS__) +#define mpp_err_f(fmt, ...) mpp_loge_f(fmt, ## __VA_ARGS__) + +#define mpp_log_c(cond, fmt, ...) do { if (cond) mpp_log(fmt, ## __VA_ARGS__); } while (0) +#define mpp_log_cf(cond, fmt, ...) do { if (cond) mpp_log_f(fmt, ## __VA_ARGS__); } while (0) + +#ifdef __cplusplus +extern "C" { +#endif + +void _mpp_log_l(int level, const char *tag, const char *fmt, const char *func, ...); + +void mpp_set_log_level(int level); +int mpp_get_log_level(void); + +typedef void (*MppLogCb)(void *ctx, int level, const char *tag, const char *fmt, const char *func, va_list args); +int mpp_set_log_callback(void *ctx, MppLogCb cb); + +/* deprecated function */ +void _mpp_log(const char *tag, const char *fmt, const char *func, ...); +void _mpp_err(const char *tag, const char *fmt, const char *func, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_LOG_H */ diff --git a/inc/mpp_log_def.h b/inc/mpp_log_def.h new file mode 100644 index 000000000..49e0fe236 --- /dev/null +++ b/inc/mpp_log_def.h @@ -0,0 +1,37 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_LOG_DEF_H +#define MPP_LOG_DEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MPP_LOG_UNKNOWN 0 /* internal use only */ +#define MPP_LOG_FATAL 1 /* fatal error on aborting */ +#define MPP_LOG_ERROR 2 /* error log on unrecoverable failures */ +#define MPP_LOG_WARN 3 /* warning log on recoverable failures */ +#define MPP_LOG_INFO 4 /* Informational log */ +#define MPP_LOG_DEBUG 5 /* Debug log */ +#define MPP_LOG_VERBOSE 6 /* Verbose log */ +#define MPP_LOG_SILENT 7 /* internal use only */ + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_LOG_DEF_H */ diff --git a/inc/mpp_meta.h b/inc/mpp_meta.h new file mode 100644 index 000000000..598fd4ab1 --- /dev/null +++ b/inc/mpp_meta.h @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_META_H +#define MPP_META_H + +#include +#include "rk_type.h" + +#define FOURCC_META(a, b, c, d) ((RK_U32)(a) << 24 | \ + ((RK_U32)(b) << 16) | \ + ((RK_U32)(c) << 8) | \ + ((RK_U32)(d) << 0)) + +/* + * Mpp Metadata definition + * + * Metadata is for information transmision in mpp. + * Mpp task will contain two meta data: + * + * 1. Data flow metadata + * This metadata contains information of input / output data flow. For example + * A. decoder input side task the input packet must be defined and output frame + * may not be defined. Then decoder will try malloc or use committed buffer to + * complete decoding. + * B. decoder output side task + * + * + * 2. Flow control metadata + * + */ +typedef enum MppMetaKey_e { + /* data flow key */ + KEY_INPUT_FRAME = FOURCC_META('i', 'f', 'r', 'm'), + KEY_INPUT_PACKET = FOURCC_META('i', 'p', 'k', 't'), + KEY_OUTPUT_FRAME = FOURCC_META('o', 'f', 'r', 'm'), + KEY_OUTPUT_PACKET = FOURCC_META('o', 'p', 'k', 't'), + /* output motion information for motion detection */ + KEY_MOTION_INFO = FOURCC_META('m', 'v', 'i', 'f'), + KEY_HDR_INFO = FOURCC_META('h', 'd', 'r', ' '), + KEY_HDR_META_OFFSET = FOURCC_META('h', 'd', 'r', 'o'), + KEY_HDR_META_SIZE = FOURCC_META('h', 'd', 'r', 'l'), + + /* flow control key */ + KEY_INPUT_BLOCK = FOURCC_META('i', 'b', 'l', 'k'), + KEY_OUTPUT_BLOCK = FOURCC_META('o', 'b', 'l', 'k'), + KEY_INPUT_IDR_REQ = FOURCC_META('i', 'i', 'd', 'r'), /* input idr frame request flag */ + KEY_OUTPUT_INTRA = FOURCC_META('o', 'i', 'd', 'r'), /* output intra frame indicator */ + + /* mpp_frame / mpp_packet meta data info key */ + KEY_TEMPORAL_ID = FOURCC_META('t', 'l', 'i', 'd'), + KEY_LONG_REF_IDX = FOURCC_META('l', 't', 'i', 'd'), + KEY_ENC_AVERAGE_QP = FOURCC_META('a', 'v', 'g', 'q'), + KEY_ENC_START_QP = FOURCC_META('s', 't', 'r', 'q'), + KEY_ENC_BPS_RT = FOURCC_META('r', 't', 'b', 'r'), /* realtime bps */ + KEY_ROI_DATA = FOURCC_META('r', 'o', 'i', ' '), + KEY_JPEG_ROI_DATA = FOURCC_META('j', 'r', 'o', 'i'), + KEY_OSD_DATA = FOURCC_META('o', 's', 'd', ' '), + KEY_OSD_DATA2 = FOURCC_META('o', 's', 'd', '2'), + KEY_OSD_DATA3 = FOURCC_META('o', 's', 'd', '3'), + KEY_USER_DATA = FOURCC_META('u', 's', 'r', 'd'), + KEY_USER_DATAS = FOURCC_META('u', 'r', 'd', 's'), + + /* num of inter different size predicted block */ + KEY_LVL64_INTER_NUM = FOURCC_META('l', '6', '4', 'p'), + KEY_LVL32_INTER_NUM = FOURCC_META('l', '3', '2', 'p'), + KEY_LVL16_INTER_NUM = FOURCC_META('l', '1', '6', 'p'), + KEY_LVL8_INTER_NUM = FOURCC_META('l', '8', 'p', ' '), + /* num of intra different size predicted block */ + KEY_LVL32_INTRA_NUM = FOURCC_META('l', '3', '2', 'i'), + KEY_LVL16_INTRA_NUM = FOURCC_META('l', '1', '6', 'i'), + KEY_LVL8_INTRA_NUM = FOURCC_META('l', '8', 'i', ' '), + KEY_LVL4_INTRA_NUM = FOURCC_META('l', '4', 'i', ' '), + /* output P skip frame indicator */ + KEY_OUTPUT_PSKIP = FOURCC_META('o', 'p', 's', 'p'), + /* + * Input P-skip frame request + * KEY_INPUT_PSKIP: The skip frame will be referenced in the next frame. + * KEY_INPUT_PSKIP_NON_REF: The skip frame will not be referenced as a frame. + */ + KEY_INPUT_PSKIP = FOURCC_META('i', 'p', 's', 'p'), + KEY_INPUT_PSKIP_NON_REF = FOURCC_META('i', 'p', 'n', 'r'), + KEY_ENC_SSE = FOURCC_META('e', 's', 's', 'e'), + + /* + * For vepu580 roi buffer config mode + * The encoder roi structure is so complex that we should provide a buffer + * tunnel for externl user to config encoder hardware by direct sending + * roi data buffer. + * This way can reduce the config parsing and roi buffer data generating + * overhead in mpp. + */ + KEY_ROI_DATA2 = FOURCC_META('r', 'o', 'i', '2'), + + /* + * qpmap for rv1109/1126 encoder qpmap config + * Input data is a MppBuffer which contains an array of 16bit Vepu541RoiCfg. + * And each 16bit represents a 16x16 block qp info. + * + * H.264 - 16x16 block qp is arranged in raster order: + * each value is a 16bit data + * 00 01 02 03 04 05 06 07 -> 00 01 02 03 04 05 06 07 + * 10 11 12 13 14 15 16 17 10 11 12 13 14 15 16 17 + * 20 21 22 23 24 25 26 27 20 21 22 23 24 25 26 27 + * 30 31 32 33 34 35 36 37 30 31 32 33 34 35 36 37 + * + * H.265 - 16x16 block qp is reorder to 64x64/32x32 ctu order then 64x64 / 32x32 ctu raster order + * 64x64 ctu + * 00 01 02 03 04 05 06 07 -> 00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33 04 05 06 07 14 15 16 17 24 25 26 27 34 35 36 37 + * 10 11 12 13 14 15 16 17 + * 20 21 22 23 24 25 26 27 + * 30 31 32 33 34 35 36 37 + * 32x32 ctu + * 00 01 02 03 04 05 06 07 -> 00 01 10 11 02 03 12 13 04 05 14 15 06 07 16 17 + * 10 11 12 13 14 15 16 17 20 21 30 31 22 23 32 33 24 25 34 35 26 27 36 37 + * 20 21 22 23 24 25 26 27 + * 30 31 32 33 34 35 36 37 + */ + KEY_QPMAP0 = FOURCC_META('e', 'q', 'm', '0'), + + /* + * shared memory buffer for object dectection flag from NPU, for rv1126b + * Picture width is aligned to 16, each 16x16 block is 8bit data. + * H.264: 16x16 block is arranged in raster order. + * H.265: 16x16 block is reordered to ctu order then ctu raster order + */ + KEY_NPU_SOBJ_FLAG = FOURCC_META('n', 'p', 'u', 's'), + /* userspace object dectection flag from NPU, for rk3588 and rk3576 */ + KEY_NPU_UOBJ_FLAG = FOURCC_META('n', 'p', 'u', 'u'), + + /* + * smart v4 encoder input key + */ + KEY_BUFFER_UPSCALE = FOURCC_META('u', 'b', 'u', 'f'), + KEY_BUFFER_DOWNSCALE = FOURCC_META('d', 'b', 'u', 'f'), + + /* frame long-term reference frame operation */ + KEY_ENC_MARK_LTR = FOURCC_META('m', 'l', 't', 'r'), + KEY_ENC_USE_LTR = FOURCC_META('u', 'l', 't', 'r'), + + /* MLVEC specified encoder feature */ + KEY_ENC_FRAME_QP = FOURCC_META('f', 'r', 'm', 'q'), + KEY_ENC_BASE_LAYER_PID = FOURCC_META('b', 'p', 'i', 'd'), + + /* Thumbnail info for decoder output frame */ + KEY_DEC_TBN_EN = FOURCC_META('t', 'b', 'e', 'n'), + KEY_DEC_TBN_Y_OFFSET = FOURCC_META('t', 'b', 'y', 'o'), + KEY_DEC_TBN_UV_OFFSET = FOURCC_META('t', 'b', 'c', 'o'), + + /* combo frame */ + KEY_COMBO_FRAME = FOURCC_META('c', 'f', 'r', 'm'), + KEY_CHANNEL_ID = FOURCC_META('c', 'h', 'a', 'n'), + + /* Preprocess (pp) operation metat data */ + /* Motion Detection output buffer */ + KEY_PP_MD_BUF = FOURCC_META('m', 'd', 'b', 'f'), + /* Occlusion Detection output buffer */ + KEY_PP_OD_BUF = FOURCC_META('o', 'd', 'b', 'f'), + /* pp output data */ + KEY_PP_OUT = FOURCC_META('o', 'p', 'p', ' '), +} MppMetaKey; + +#define mpp_meta_get(meta) mpp_meta_get_with_tag(meta, MODULE_TAG, __FUNCTION__) + +#include "mpp_frame.h" +#include "mpp_packet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_meta_get_with_tag(MppMeta *meta, const char *tag, const char *caller); +MPP_RET mpp_meta_put(MppMeta meta); +RK_S32 mpp_meta_size(MppMeta meta); +MppMeta mpp_meta_dup(MppMeta meta); + +MPP_RET mpp_meta_set_s32(MppMeta meta, MppMetaKey key, RK_S32 val); +MPP_RET mpp_meta_set_s64(MppMeta meta, MppMetaKey key, RK_S64 val); +MPP_RET mpp_meta_set_ptr(MppMeta meta, MppMetaKey key, void *val); +MPP_RET mpp_meta_get_s32(MppMeta meta, MppMetaKey key, RK_S32 *val); +MPP_RET mpp_meta_get_s64(MppMeta meta, MppMetaKey key, RK_S64 *val); +MPP_RET mpp_meta_get_ptr(MppMeta meta, MppMetaKey key, void **val); + +MPP_RET mpp_meta_set_frame (MppMeta meta, MppMetaKey key, MppFrame frame); +MPP_RET mpp_meta_set_packet(MppMeta meta, MppMetaKey key, MppPacket packet); +MPP_RET mpp_meta_set_buffer(MppMeta meta, MppMetaKey key, MppBuffer buffer); +MPP_RET mpp_meta_get_frame (MppMeta meta, MppMetaKey key, MppFrame *frame); +MPP_RET mpp_meta_get_packet(MppMeta meta, MppMetaKey key, MppPacket *packet); +MPP_RET mpp_meta_get_buffer(MppMeta meta, MppMetaKey key, MppBuffer *buffer); + +MPP_RET mpp_meta_get_s32_d(MppMeta meta, MppMetaKey key, RK_S32 *val, RK_S32 def); +MPP_RET mpp_meta_get_s64_d(MppMeta meta, MppMetaKey key, RK_S64 *val, RK_S64 def); +MPP_RET mpp_meta_get_ptr_d(MppMeta meta, MppMetaKey key, void **val, void *def); +MPP_RET mpp_meta_get_frame_d(MppMeta meta, MppMetaKey key, MppFrame *frame, MppFrame def); +MPP_RET mpp_meta_get_packet_d(MppMeta meta, MppMetaKey key, MppPacket *packet, MppPacket def); +MPP_RET mpp_meta_get_buffer_d(MppMeta meta, MppMetaKey key, MppBuffer *buffer, MppBuffer def); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_META_H */ diff --git a/inc/mpp_packet.h b/inc/mpp_packet.h index 5feda7671..dd3f16389 100644 --- a/inc/mpp_packet.h +++ b/inc/mpp_packet.h @@ -1,79 +1,106 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_PACKET_H__ -#define __MPP_PACKET_H__ - -#include "rk_type.h" -#include "mpp_err.h" - -typedef void* MppPacket; - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * MppPacket interface - * - * mpp_packet_init = mpp_packet_new + mpp_packet_set_data + mpp_packet_set_size - */ -MPP_RET mpp_packet_new(MppPacket *packet); -MPP_RET mpp_packet_init(MppPacket *packet, void *data, size_t size); -MPP_RET mpp_packet_copy(MppPacket *packet, const MppPacket src); -MPP_RET mpp_packet_deinit(MppPacket *packet); - -/* - * data : ( R/W ) start address of the whole packet memory - * size : ( R/W ) total size of the whole packet memory - * pos : ( R/W ) current access position of the whole packet memory, used for buffer read/write - * length : ( R ) the rest length from current position to end of buffer, read only - */ -void mpp_packet_set_data(MppPacket packet, void *data); -void mpp_packet_set_size(MppPacket packet, size_t size); -void mpp_packet_set_pos(MppPacket packet, void *pos); - -void* mpp_packet_get_data(const MppPacket packet); -void* mpp_packet_get_pos(const MppPacket packet); -size_t mpp_packet_get_size(const MppPacket packet); -size_t mpp_packet_get_length(const MppPacket packet); - - -void mpp_packet_set_pts(MppPacket packet, RK_S64 pts); -RK_S64 mpp_packet_get_pts(const MppPacket packet); -void mpp_packet_set_dts(MppPacket packet, RK_S64 dts); -RK_S64 mpp_packet_get_dts(const MppPacket packet); - -void mpp_packet_set_flag(MppPacket packet, RK_U32 flag); -RK_U32 mpp_packet_get_flag(const MppPacket packet); - - -MPP_RET mpp_packet_set_eos(MppPacket packet); -RK_U32 mpp_packet_get_eos(MppPacket packet); -MPP_RET mpp_packet_set_extra_data(MppPacket packet); - -/* - * data access interface - */ -MPP_RET mpp_packet_read(MppPacket packet, size_t offset, void *data, size_t size); -MPP_RET mpp_packet_write(MppPacket packet, size_t offset, void *data, size_t size); - - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_PACKET_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_PACKET_H +#define MPP_PACKET_H + +#include "mpp_meta.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MppPacket interface + * + * mpp_packet_init = mpp_packet_new + mpp_packet_set_data + mpp_packet_set_size + * mpp_packet_copy_init = mpp_packet_init + memcpy + */ +MPP_RET mpp_packet_new(MppPacket *packet); +MPP_RET mpp_packet_init(MppPacket *packet, void *data, size_t size); +MPP_RET mpp_packet_init_with_buffer(MppPacket *packet, MppBuffer buffer); +MPP_RET mpp_packet_copy_init(MppPacket *packet, const MppPacket src); +MPP_RET mpp_packet_deinit(MppPacket *packet); + +/* + * data : ( R/W ) start address of the whole packet memory + * size : ( R/W ) total size of the whole packet memory + * pos : ( R/W ) current access position of the whole packet memory, used for buffer read/write + * length : ( R/W ) the rest length from current position to end of buffer + * NOTE: normally length is updated only by set_pos, + * so set length must be used carefully for special usage + */ +void mpp_packet_set_data(MppPacket packet, void *data); +void mpp_packet_set_size(MppPacket packet, size_t size); +void mpp_packet_set_pos(MppPacket packet, void *pos); +void mpp_packet_set_length(MppPacket packet, size_t size); + +void* mpp_packet_get_data(const MppPacket packet); +void* mpp_packet_get_pos(const MppPacket packet); +size_t mpp_packet_get_size(const MppPacket packet); +size_t mpp_packet_get_length(const MppPacket packet); + + +void mpp_packet_set_pts(MppPacket packet, RK_S64 pts); +RK_S64 mpp_packet_get_pts(const MppPacket packet); +void mpp_packet_set_dts(MppPacket packet, RK_S64 dts); +RK_S64 mpp_packet_get_dts(const MppPacket packet); + +void mpp_packet_set_flag(MppPacket packet, RK_U32 flag); +RK_U32 mpp_packet_get_flag(const MppPacket packet); + +MPP_RET mpp_packet_set_eos(MppPacket packet); +MPP_RET mpp_packet_clr_eos(MppPacket packet); +RK_U32 mpp_packet_get_eos(MppPacket packet); +MPP_RET mpp_packet_set_extra_data(MppPacket packet); + +void mpp_packet_set_buffer(MppPacket packet, MppBuffer buffer); +MppBuffer mpp_packet_get_buffer(const MppPacket packet); + +/* + * data access interface + */ +MPP_RET mpp_packet_read(MppPacket packet, size_t offset, void *data, size_t size); +MPP_RET mpp_packet_write(MppPacket packet, size_t offset, void *data, size_t size); + +/* + * meta data access interface + */ +RK_S32 mpp_packet_has_meta(const MppPacket packet); +MppMeta mpp_packet_get_meta(const MppPacket packet); + +/* + * multi packet sequence interface for slice/split encoding/decoding + * partition - the packet is a part of a while image + * soi - Start Of Image + * eoi - End Of Image + */ +RK_U32 mpp_packet_is_partition(const MppPacket packet); +RK_U32 mpp_packet_is_soi(const MppPacket packet); +RK_U32 mpp_packet_is_eoi(const MppPacket packet); + +/* + * packet segement pack info for + * segment number - number of segment + * segment info - base address of segment info + */ +typedef struct MppPktSeg_t MppPktSeg; + +struct MppPktSeg_t { + RK_S32 index; + RK_S32 type; + RK_U32 offset; + RK_U32 len; + const MppPktSeg *next; +}; + +RK_U32 mpp_packet_get_segment_nb(const MppPacket packet); +const MppPktSeg *mpp_packet_get_segment_info(const MppPacket packet); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_PACKET_H */ diff --git a/inc/mpp_rc_api.h b/inc/mpp_rc_api.h new file mode 100644 index 000000000..e5dd3abe5 --- /dev/null +++ b/inc/mpp_rc_api.h @@ -0,0 +1,255 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_RC_API_H +#define MPP_RC_API_H + +#include "mpp_err.h" +#include "rk_venc_rc.h" +#include "mpp_rc_defs.h" + +/* + * Mpp rate control has three parts: + * + * 1. MPI user config module + * MppEncRcCfg structure is provided to user for overall rate control config + * Mpp will receive MppEncRcCfg from user, check parameter and set it to + * encoder. + * + * 2. Encoder rate control module + * Encoder will implement the rate control strategy required by users + * including CBR, VBR, AVBR and so on. + * This module only implement the target bit calculation behavior and + * quality restriction. And the quality level will be controlled by hal. + * + * 3. Hal rate control module + * Hal will implement the rate control on hardware. Hal will calculate the + * QP parameter for hardware according to the frame level target bit + * specified by the encoder. And the report the real bitrate and quality to + * encoder. + * + * The header defines the communication interfaces and structures used between + * MPI, encoder and hal. + */ + +typedef enum RcMode_e { + RC_VBR, + RC_CBR, + RC_FIXQP, + RC_AVBR, + RC_SMT, + RC_CVBR, + RC_QVBR, + RC_SE, // super encode mode + RC_MODE_BUTT, +} RcMode; + +typedef enum GopMode_e { + NORMAL_P, + SMART_P, +} GopMode; + +/* + * frame rate parameters have great effect on rate control + * + * fps_in_flex + * 0 - fix input frame rate + * 1 - variable input frame rate + * + * fps_in_num + * input frame rate numerator, if 0 then default 30 + * + * fps_in_denom + * input frame rate denominator, if 0 then default 1 + * + * fps_out_flex + * 0 - fix output frame rate + * 1 - variable output frame rate + * + * fps_out_num + * output frame rate numerator, if 0 then default 30 + * + * fps_out_denom + * output frame rate denominator, if 0 then default 1 + */ +typedef struct RcFpsCfg_t { + RK_S32 fps_in_flex; + RK_S32 fps_in_num; + RK_S32 fps_in_denom; + RK_S32 fps_out_flex; + RK_S32 fps_out_num; + RK_S32 fps_out_denom; +} RcFpsCfg; + +typedef struct RcSuperframeCfg_t { + MppEncRcSuperFrameMode super_mode; + RK_U32 super_i_thd; + RK_U32 super_p_thd; + MppEncRcPriority rc_priority; +} RcSuperframeCfg; + +typedef struct RcDebreathCfg_t { + RK_U32 enable; + RK_U32 strength; +} RcDebreathCfg; + +typedef struct RcHierQPCfg_t { + RK_S32 hier_qp_en; + RK_S32 hier_qp_delta[4]; + RK_S32 hier_frame_num[4]; +} RcHierQPCfg; + +/* + * Control parameter from external config + * + * It will be updated on rc/prep/gopref config changed. + */ +typedef struct RcCfg_s { + /* encode image size */ + RK_S32 width; + RK_S32 height; + + /* Use rc_mode to find different api */ + RcMode mode; + + RcFpsCfg fps; + + GopMode gop_mode; + /* I frame gop len */ + RK_S32 igop; + /* visual gop len */ + RK_S32 vgop; + + /* bitrate parameter */ + RK_S32 bps_min; + RK_S32 bps_target; + RK_S32 bps_max; + RK_S32 stats_time; + + /* max I frame bit ratio to P frame bit */ + RK_S32 max_i_bit_prop; + RK_S32 min_i_bit_prop; + RK_S32 init_ip_ratio; + /* layer bitrate proportion */ + RK_S32 layer_bit_prop[4]; + + /* quality parameter */ + RK_S32 init_quality; + RK_S32 max_quality; + RK_S32 min_quality; + RK_S32 max_i_quality; + RK_S32 min_i_quality; + RK_S32 i_quality_delta; + RK_S32 vi_quality_delta; + RK_S32 fqp_min_i; + RK_S32 fqp_min_p; + RK_S32 fqp_max_i; + RK_S32 fqp_max_p; + /* layer quality proportion */ + RK_S32 layer_quality_delta[4]; + + /* reencode parameter */ + RK_S32 max_reencode_times; + + /* still / motion desision parameter */ + RK_S32 min_still_prop; + RK_S32 max_still_quality; + + /* + * vbr parameter + * + * vbr_hi_prop - high proportion bitrate for reduce quality + * vbr_lo_prop - low proportion bitrate for increase quality + */ + RK_S32 vbr_hi_prop; + RK_S32 vbr_lo_prop; + + MppEncRcDropFrmMode drop_mode; + RK_U32 drop_thd; + RK_U32 drop_gap; + + RcSuperframeCfg super_cfg; + RcDebreathCfg debreath_cfg; + RcHierQPCfg hier_qp_cfg; + RK_U32 refresh_len; + RK_S32 scene_mode; + RK_U32 fps_chg_prop; + + RK_S32 rc_container; +} RcCfg; + +/* + * Different rate control strategy will be implemented by different API config + */ +typedef struct RcImplApi_t { + char *name; + MppCodingType type; + RK_U32 ctx_size; + + MPP_RET (*init)(void *ctx, RcCfg *cfg); + MPP_RET (*deinit)(void *ctx); + + MPP_RET (*check_drop)(void *ctx, EncRcTask *task); + MPP_RET (*check_reenc)(void *ctx, EncRcTask *task); + + /* + * frm_start - frame level rate control frm_start. + * The EncRcTaskInfo will be output to hal for hardware to implement. + * frm_end - frame level rate control frm_end. + * The EncRcTaskInfo is returned for real quality and bitrate. + */ + MPP_RET (*frm_start)(void *ctx, EncRcTask *task); + MPP_RET (*frm_end)(void *ctx, EncRcTask *task); + + /* + * hal_start - hardware level rate control start. + * The EncRcTaskInfo will be output to hal for hardware to implement. + * hal_end - hardware level rate control end. + * The EncRcTaskInfo is returned for real quality and bitrate. + */ + MPP_RET (*hal_start)(void *ctx, EncRcTask *task); + MPP_RET (*hal_end)(void *ctx, EncRcTask *task); +} RcImplApi; + +/* + * structures for RC API register and query + */ +typedef struct RcApiBrief_t { + const char *name; + MppCodingType type; +} RcApiBrief; + +typedef struct RcApiQueryAll_t { + /* input param for query */ + RcApiBrief *brief; + RK_S32 max_count; + + /* output query count */ + RK_S32 count; +} RcApiQueryAll; + +typedef struct RcApiQueryType_t { + /* input param for query */ + RcApiBrief *brief; + RK_S32 max_count; + MppCodingType type; + + /* output query count */ + RK_S32 count; +} RcApiQueryType; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET rc_api_add(const RcImplApi *api); +MPP_RET rc_brief_get_all(RcApiQueryAll *query); +MPP_RET rc_brief_get_by_type(RcApiQueryType *query); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_RC_API_H */ diff --git a/inc/mpp_rc_defs.h b/inc/mpp_rc_defs.h new file mode 100644 index 000000000..16c09d026 --- /dev/null +++ b/inc/mpp_rc_defs.h @@ -0,0 +1,235 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_RC_DEFS_H +#define MPP_RC_DEFS_H + +#include "rk_venc_ref.h" + +#define MAX_CPB_REFS (8) + +typedef enum EncFrmType_e { + INTER_P_FRAME = 0, + INTER_B_FRAME = 1, + INTRA_FRAME = 2, + INTER_VI_FRAME = 3, + INTRA_RFH_FRAME = 4, +} EncFrmType; + +/* + * EncFrmStatus controls record the encoding frame status and also control + * work flow of encoder. It is the communicat channel between encoder implement + * module, rate control module and hardware module. + * + * bit 0 ~ 31 frame status + * 0 ~ 15 current frame status + * 16 ~ 31 reference frame status + * bit 32 ~ 63 encoding flow control + */ +typedef union EncFrmStatus_u { + struct { + /* + * bit 0 ~ 31 frame status + */ + /* status flag */ + RK_U32 valid : 1; + /* + * 0 - write the reconstructed frame pixel to memory + * 1 - do not write the reconstructed frame pixel to memory + */ + RK_U32 non_recn : 1; + + /* + * 0 - normal frame and normal dpb management + * 1 - save recon frame as first pass extra frame. Used in two pass mode + */ + RK_U32 save_pass1 : 1; + + /* + * 0 - use normal input source frame as input + * 1 - use the previously stored first pass recon frame as input frame + */ + RK_U32 use_pass1 : 1; + + /* reference status flag */ + /* + * 0 - inter frame + * 1 - intra frame + */ + RK_U32 is_intra : 1; + + /* + * Valid when is_intra is true + * 0 - normal intra frame + * 1 - IDR frame + */ + RK_U32 is_idr : 1; + + /* + * 0 - mark as reference frame + * 1 - mark as non-refernce frame + */ + RK_U32 is_non_ref : 1; + + /* + * Valid when is_non_ref is false + * 0 - mark as short-term reference frame + * 1 - mark as long-term refernce frame + */ + RK_U32 is_lt_ref : 1; + + /* bit 8 - 15 */ + RK_U32 lt_idx : 4; + RK_U32 temporal_id : 4; + + /* distance between current frame and reference frame */ + MppEncRefMode ref_mode : 6; + RK_S32 ref_arg : 8; + RK_S32 ref_dist : 2; + + /* + * bit 32 ~ 63 encoder flow control flags + */ + /* + * 0 - normal frame encoding + * 1 - current frame will be dropped + */ + RK_U32 drop : 1; + + /* + * 0 - rate control module does not change frame type parameter + * 1 - rate control module changes frame type parameter reencode is needed + * to reprocess the dpb process. Also this means dpb module will follow + * the frame status parameter provided by rate control module. + */ + RK_U32 re_dpb_proc : 1; + + /* + * 0 - current frame encoding is in normal flow + * 1 - current frame encoding is in reencode flow + */ + RK_U32 reencode : 1; + + /* + * When true current frame size is super large then the frame should be reencoded. + */ + RK_U32 super_frame : 1; + + /* + * When true currnet frame is force to encoded as software skip frame + */ + RK_U32 force_pskip : 1; + RK_U32 force_pskip_is_ref : 1; + + /* + * Current frame is intra refresh frame + */ + RK_U32 is_i_refresh : 1; + /* + * Current frame needs add recovery point prefix + */ + RK_U32 is_i_recovery : 1; + + /* reencode times */ + RK_U32 reencode_times : 8; + + /* sequential index for each frame */ + RK_U32 seq_idx : 16; + }; + RK_U64 val; +} EncFrmStatus; + +typedef struct EncCpbStatus_t { + RK_S32 seq_idx; + + EncFrmStatus curr; + EncFrmStatus refr; + + /* initial cpb status for current frame encoding */ + EncFrmStatus init[MAX_CPB_REFS]; + /* final cpb status after current frame encoding */ + EncFrmStatus final[MAX_CPB_REFS]; +} EncCpbStatus; + +#define ENC_RC_FORCE_QP (0x00000001) + +typedef struct EncRcForceCfg_t { + RK_U32 force_flag; + RK_S32 force_qp; + RK_U32 reserve[6]; +} EncRcForceCfg; + +/* + * communication channel between rc / hal / hardware + * + * rc -> hal bit_target / bit_max / bit_min + * hal -> hw quality_target / quality_max / quality_min + * hw -> rc / hal bit_real / quality_real / madi / madp + */ +typedef struct EncRcCommonInfo_t { + EncFrmType frame_type; + + /* rc to hal */ + RK_S32 bit_target; + RK_S32 bit_target_fix; + RK_S32 bit_max; + RK_S32 bit_min; + + RK_S32 quality_target; + RK_S32 quality_max; + RK_S32 quality_min; + + /* rc from hardware */ + RK_S32 bit_real; + RK_S32 quality_real; + RK_S32 madi; + RK_S32 madp; + /* average of down scaled pixels of luma */ + RK_U32 dsp_y_avg; + + RK_U32 iblk4_prop; // scale 256 + + RK_S64 sse; + RK_U32 lvl64_inter_num; + RK_U32 lvl32_inter_num; + RK_U32 lvl16_inter_num; + RK_U32 lvl8_inter_num; + RK_U32 lvl32_intra_num; + RK_U32 lvl16_intra_num; + RK_U32 lvl8_intra_num; + RK_U32 lvl4_intra_num; + + RK_U32 motion_level; + RK_U32 complex_level; + RK_S32 complex_scene; + RK_S32 scene_mode; + RK_S32 last_scene_mode; + + /* rc stats info: real time bits */ + RK_S32 rt_bits; + + RK_S32 reserve[4]; +} EncRcTaskInfo; + +typedef struct EncRcTask_s { + EncCpbStatus cpb; + EncFrmStatus frm; + EncRcTaskInfo info; + EncRcForceCfg force; + MppFrame frame; +} EncRcTask; + +#endif /* MPP_RC_DEFS_H */ diff --git a/inc/mpp_sys_cfg.h b/inc/mpp_sys_cfg.h new file mode 100644 index 000000000..1adc73d38 --- /dev/null +++ b/inc/mpp_sys_cfg.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SYS_CFG_H +#define MPP_SYS_CFG_H + +#include "mpp_bit.h" +#include "mpp_list.h" +#include "mpp_frame.h" + +typedef enum MppSysDecBufCkhCfgChange_e { + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_ENABLE = MPP_BIT(0), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_TYPE = MPP_BIT(1), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_FMT_CODEC = MPP_BIT(2), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_FMT_FBC = MPP_BIT(3), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_FMT_HDR = MPP_BIT(4), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_WIDTH = MPP_BIT(5), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_HEIGHT = MPP_BIT(6), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_CROP_TOP = MPP_BIT(7), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_CROP_BOTTOM = MPP_BIT(8), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_CROP_LEFT = MPP_BIT(9), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_CROP_RIGHT = MPP_BIT(10), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_FLAG_METADATA = MPP_BIT(11), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_FLAG_THUMBNAIL = MPP_BIT(12), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_H_STRIDE_BYTE = MPP_BIT(13), + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_V_STRIDE = MPP_BIT(14), + + MPP_SYS_DEC_BUF_CHK_CFG_CHANGE_ALL = (0xFFFFFFFFU), +} MppSysDecBufCkhChange; + +typedef struct MppSysBaseCfg_t { + RK_U64 change; + + RK_U32 enable; + + /* input args start */ + MppCodingType type; + MppFrameFormat fmt_codec; + RK_U32 fmt_fbc; + RK_U32 fmt_hdr; + + /* video codec width and height */ + RK_U32 width; + RK_U32 height; + + /* display crop info */ + RK_U32 crop_top; + RK_U32 crop_bottom; + RK_U32 crop_left; + RK_U32 crop_right; + + /* bit mask for metadata and thumbnail config */ + RK_U32 has_metadata; + RK_U32 has_thumbnail; + + /* extra protocol config */ + /* H.265 ctu size, VP9/Av1 super block size */ + RK_U32 unit_size; + + /* output args start */ + /* system support capability */ + RK_U32 cap_fbc; + RK_U32 cap_tile; + + /* 2 horizontal stride for 2 planes like Y/UV */ + RK_U32 h_stride_by_pixel; + RK_U32 h_stride_by_byte; + RK_U32 v_stride; + RK_U32 buf_total_size; + + /* fbc display offset config for some fbc version */ + RK_U32 offset_y; + RK_U32 size_total; + RK_U32 size_fbc_hdr; + RK_U32 size_fbc_bdy; + + /* extra buffer size */ + RK_U32 size_metadata; + RK_U32 size_thumbnail; +} MppSysDecBufChkCfg; + +typedef struct MppSysCfgSet_t { + RK_U32 change; + MppSysDecBufChkCfg dec_buf_chk; +} MppSysCfgSet; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_sys_dec_buf_chk_proc(MppSysDecBufChkCfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SYS_CFG_H */ diff --git a/inc/mpp_sys_cfg_st.h b/inc/mpp_sys_cfg_st.h new file mode 100644 index 000000000..b7452e7dd --- /dev/null +++ b/inc/mpp_sys_cfg_st.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SYS_CFG_ST_H +#define MPP_SYS_CFG_ST_H + +#include "rk_type.h" +#include "mpp_err.h" + +#include "mpp_frame.h" + +typedef struct MppSysCfgStHStrd_t { + /* input args start */ + MppCodingType type; + RK_U32 fmt_fbc; + RK_U32 width; + RK_U32 h_stride_by_byte; + + /* output args start */ + RK_U32 h_stride_by_pixel; +} MppSysCfgStHStrd; + +typedef struct MppSysCfgStHByteStrd_t { + /* input args start */ + MppCodingType type; + MppFrameFormat fmt_codec; + RK_U32 fmt_fbc; + RK_U32 width; + + /* in/output args start */ + RK_U32 h_stride_by_byte; +} MppSysCfgStHByteStrd; + +typedef struct MppSysCfgStVStrd_t { + /* input args start */ + MppCodingType type; + RK_U32 fmt_fbc; + RK_U32 height; + + /* in/output args start */ + RK_U32 v_stride; +} MppSysCfgStVStrd; + +typedef struct MppSysCfgStSize_t { + /* input args start */ + MppCodingType type; + MppFrameFormat fmt_codec; + RK_U32 fmt_fbc; + RK_U32 width; + RK_U32 height; + + /* in/output args start */ + RK_U32 h_stride_by_byte; + RK_U32 v_stride; + + /* output args start */ + RK_U32 h_stride_by_pixel; + RK_U32 size_total; + RK_U32 size_fbc_hdr; + RK_U32 size_fbc_bdy; +} MppSysCfgStSize; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_sys_cfg_st_get_h_stride(MppSysCfgStHStrd *h_stride_cfg); +MPP_RET mpp_sys_cfg_st_get_byte_stride(MppSysCfgStHByteStrd *byte_stride_cfg); +MPP_RET mpp_sys_cfg_st_get_v_stride(MppSysCfgStVStrd *v_stride_cfg); +MPP_RET mpp_sys_cfg_st_get_size(MppSysCfgStSize *size_cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SYS_CFGI_H */ diff --git a/inc/mpp_task.h b/inc/mpp_task.h new file mode 100644 index 000000000..ade5f04ad --- /dev/null +++ b/inc/mpp_task.h @@ -0,0 +1,237 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_TASK_H +#define MPP_TASK_H + +#include "mpp_meta.h" + +/* + * Advanced task flow + * Advanced task flow introduces three concepts: port, task and item + * + * Port is from OpenMAX + * Port has two type: input port and output port which are all for data transaction. + * Port work like a queue. task will be dequeue from or enqueue to one port. + * On input side user will dequeue task from input port, setup task and enqueue task + * back to input port. + * On output side user will dequeue task from output port, get the information from + * and then enqueue task back to output port. + * + * Task indicates one transaction on the port. + * Task has two working mode: async mode and sync mode + * If mpp is work in sync mode on task enqueue function return the task has been done + * If mpp is work in async mode on task enqueue function return the task is just put + * on the task queue for process. + * Task can carry different items. Task just like a container of items + * + * Item indicates MppPacket or MppFrame which is contained in one task + */ + +/* + * One mpp task queue has two ports: input and output + * + * The whole picture is: + * Top layer mpp has two ports: mpp_input_port and mpp_output_port + * But internally these two ports belongs to two task queue. + * The mpp_input_port is the mpp_input_task_queue's input port. + * The mpp_output_port is the mpp_output_task_queue's output port. + * + * Each port uses its task queue to communication + */ +typedef enum { + MPP_PORT_INPUT, + MPP_PORT_OUTPUT, + MPP_PORT_BUTT, +} MppPortType; + +/* + * Advance task work flow mode: + ****************************************************************************** + * 1. async mode (default_val) + * + * mpp_init(type, coding, MPP_WORK_ASYNC) + * + * input thread + * a - poll(input) + * b - dequeue(input, *task) + * c - task_set_item(packet/frame) + * d - enqueue(input, task) -- when enqueue return the task is not done yet + * + * output thread + * a - poll(output) + * b - dequeue(output, *task) + * c - task_get_item(frame/packet) + * d - enqueue(output, task) + ****************************************************************************** + * 2. sync mode + * + * mpp_init(type, coding, MPP_WORK_SYNC) + * + * a - poll(input) + * b - dequeue(input, *task) + * c - task_set_item(packet/frame) + * d - enqueue(task) -- when enqueue return the task is finished + ****************************************************************************** + */ +typedef enum { + MPP_TASK_ASYNC, + MPP_TASK_SYNC, + MPP_TASK_WORK_MODE_BUTT, +} MppTaskWorkMode; + +/* + * Mpp port poll type + * + * MPP_POLL_BLOCK - for block poll + * MPP_POLL_NON_BLOCK - for non-block poll + * small than MPP_POLL_MAX - for poll with timeout in ms + * small than MPP_POLL_BUTT or larger than MPP_POLL_MAX is invalid value + */ +typedef enum { + MPP_POLL_BUTT = -2, + MPP_POLL_BLOCK = -1, + MPP_POLL_NON_BLOCK = 0, + MPP_POLL_MAX = 8000, +} MppPollType; + +/* + * Mpp timeout define + * MPP_TIMEOUT_BLOCK - for block poll + * MPP_TIMEOUT_NON_BLOCK - for non-block poll + * small than MPP_TIMEOUT_MAX - for poll with timeout in ms + * small than MPP_TIMEOUT_BUTT or larger than MPP_TIMEOUT_MAX is invalid value + */ +#define MPP_TIMEOUT_BUTT (-2L) +#define MPP_TIMEOUT_BLOCK (-1L) +#define MPP_TIMEOUT_NON_BLOCK (0L) +#define MPP_TIMEOUT_MAX (8000L) + +/* + * MppTask is descriptor of a task which send to mpp for process + * mpp can support different type of work mode, for example: + * + * decoder: + * + * 1. typical decoder mode: + * input - MppPacket (normal cpu buffer, need cpu copy) + * output - MppFrame (ion/drm buffer in external/internal mode) + * 2. secure decoder mode: + * input - MppPacket (externel ion/drm buffer, cpu can not access) + * output - MppFrame (ion/drm buffer in external/internal mode, cpu can not access) + * + * interface usage: + * + * typical flow + * input side: + * task_dequeue(ctx, PORT_INPUT, &task); + * task_put_item(task, MODE_INPUT, packet) + * task_enqueue(ctx, PORT_INPUT, task); + * output side: + * task_dequeue(ctx, PORT_OUTPUT, &task); + * task_get_item(task, MODE_OUTPUT, &frame) + * task_enqueue(ctx, PORT_OUTPUT, task); + * + * secure flow + * input side: + * task_dequeue(ctx, PORT_INPUT, &task); + * task_put_item(task, MODE_INPUT, packet) + * task_put_item(task, MODE_OUTPUT, frame) -- buffer will be specified here + * task_enqueue(ctx, PORT_INPUT, task); + * output side: + * task_dequeue(ctx, PORT_OUTPUT, &task); + * task_get_item(task, MODE_OUTPUT, &frame) + * task_enqueue(ctx, PORT_OUTPUT, task); + * + * encoder: + * + * 1. typical encoder mode: + * input - MppFrame (ion/drm buffer in external mode) + * output - MppPacket (normal cpu buffer, need cpu copy) + * 2. user input encoder mode: + * input - MppFrame (normal cpu buffer, need to build hardware table for this buffer) + * output - MppPacket (normal cpu buffer, need cpu copy) + * 3. secure encoder mode: + * input - MppFrame (ion/drm buffer in external mode, cpu can not access) + * output - MppPacket (externel ion/drm buffer, cpu can not access) + * + * typical / user input flow + * input side: + * task_dequeue(ctx, PORT_INPUT, &task); + * task_put_item(task, MODE_INPUT, frame) + * task_enqueue(ctx, PORT_INPUT, task); + * output side: + * task_dequeue(ctx, PORT_OUTPUT, &task); + * task_get_item(task, MODE_OUTPUT, &packet) + * task_enqueue(ctx, PORT_OUTPUT, task); + * + * secure flow + * input side: + * task_dequeue(ctx, PORT_INPUT, &task); + * task_put_item(task, MODE_OUTPUT, packet) -- buffer will be specified here + * task_put_item(task, MODE_INPUT, frame) + * task_enqueue(ctx, PORT_INPUT, task); + * output side: + * task_dequeue(ctx, PORT_OUTPUT, &task); + * task_get_item(task, MODE_OUTPUT, &packet) + * task_get_item(task, MODE_OUTPUT, &frame) + * task_enqueue(ctx, PORT_OUTPUT, task); + * + * NOTE: this flow can specify the output frame. User will setup both intput frame and output packet + * buffer at the input side. Then at output side when user gets a finished task user can get the output + * packet and corresponding released input frame. + * + * image processing + * + * 1. typical image process mode: + * input - MppFrame (ion/drm buffer in external mode) + * output - MppFrame (ion/drm buffer in external mode) + * + * typical / user input flow + * input side: + * task_dequeue(ctx, PORT_INPUT, &task); + * task_put_item(task, MODE_INPUT, frame) + * task_enqueue(ctx, PORT_INPUT, task); + * output side: + * task_dequeue(ctx, PORT_OUTPUT, &task); + * task_get_item(task, MODE_OUTPUT, &frame) + * task_enqueue(ctx, PORT_OUTPUT, task); + */ +/* NOTE: use index rather then handle to descripbe task */ + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_task_meta_set_s32(MppTask task, MppMetaKey key, RK_S32 val); +MPP_RET mpp_task_meta_set_s64(MppTask task, MppMetaKey key, RK_S64 val); +MPP_RET mpp_task_meta_set_ptr(MppTask task, MppMetaKey key, void *val); +MPP_RET mpp_task_meta_set_frame (MppTask task, MppMetaKey key, MppFrame frame); +MPP_RET mpp_task_meta_set_packet(MppTask task, MppMetaKey key, MppPacket packet); +MPP_RET mpp_task_meta_set_buffer(MppTask task, MppMetaKey key, MppBuffer buffer); + +MPP_RET mpp_task_meta_get_s32(MppTask task, MppMetaKey key, RK_S32 *val, RK_S32 default_val); +MPP_RET mpp_task_meta_get_s64(MppTask task, MppMetaKey key, RK_S64 *val, RK_S64 default_val); +MPP_RET mpp_task_meta_get_ptr(MppTask task, MppMetaKey key, void **val, void *default_val); +MPP_RET mpp_task_meta_get_frame (MppTask task, MppMetaKey key, MppFrame *frame); +MPP_RET mpp_task_meta_get_packet(MppTask task, MppMetaKey key, MppPacket *packet); +MPP_RET mpp_task_meta_get_buffer(MppTask task, MppMetaKey key, MppBuffer *buffer); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_QUEUE_H */ diff --git a/inc/rk_hdr_meta_com.h b/inc/rk_hdr_meta_com.h new file mode 100644 index 000000000..3f899bc1b --- /dev/null +++ b/inc/rk_hdr_meta_com.h @@ -0,0 +1,126 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RK_HDR_META_COM_H +#define RK_HDR_META_COM_H + +#include "rk_type.h" + +typedef enum HdrCodecType_e { + HDR_CODEC_UNSPECIFIED = -1, + HDR_AVS2 = 0, + HDR_HEVC = 1, + HDR_H264 = 2, + HDR_AV1 = 3, +} HdrCodecType; + +typedef enum HdrFormat_e { + HDR_NONE = 0, + HDR10 = 1, + HLG = 2, +// RESERVED3 = 3, //reserved for more future static hdr format +// RESERVED4 = 4, //reserved for more future static hdr format + HDRVIVID = 5, +// RESERVED6 = 6, //reserved for hdr vivid +// RESERVED7 = 7, //reserved for hdr vivid + HDR10PLUS = 8, +// RESERVED9 = 9, //reserved for hdr10+ +// RESERVED10 = 10,//reserved for hdr10+ + DLBY = 11, +// RESERVED12 = 12, //reserved for other dynamic hdr format +// RESERVED13 = 13, //reserved for other dynamic hdr format + HDR_FORMAT_MAX, +} HdrFormat; + +typedef enum HdrPayloadFormat_e { + STATIC = 0, + DYNAMIC = 1, + HDR_PAYLOAD_FORMAT_MAX, +} HdrPayloadFormat; + +typedef struct HdrStaticMeta_t { + RK_U32 color_space; + RK_U32 color_primaries; + RK_U32 color_trc; + RK_U32 red_x; + RK_U32 red_y; + RK_U32 green_x; + RK_U32 green_y; + RK_U32 blue_x; + RK_U32 blue_y; + RK_U32 white_point_x; + RK_U32 white_point_y; + RK_U32 min_luminance; + RK_U32 max_luminance; + RK_U32 max_cll; + RK_U32 max_fall; + RK_U32 reserved[4]; +} HdrStaticMeta; + +/* + * HDR metadata format from codec + * + * +----------+ + * | header1 | + * +----------+ + * | | + * | payload | + * | | + * +----------+ + * | header2 | + * +----------+ + * | | + * | payload | + * | | + * +----------+ + * | header3 | + * +----------+ + * | | + * | payload | + * | | + * +----------+ + */ +typedef struct RkMetaHdrHeader_t { + /* For transmission */ + RK_U16 magic; /* magic word for checking overwrite error */ + RK_U16 size; /* total header+payload length including header */ + RK_U16 message_total; /* total message count in current transmission */ + RK_U16 message_index; /* current message index in the transmission */ + + /* For payload identification */ + RK_U16 version; /* payload structure version */ + RK_U16 hdr_format; /* HDR protocol: HDR10, HLG, Dlby, HDRVivid ... */ + RK_U16 hdr_payload_type; /* HDR data type: static data, dynamic data ... */ + RK_U16 video_format; /* video format: H.264, H.265, AVS2 ... */ + + /* For extenstion usage */ + RK_U32 reserve[4]; + + /* payload data aligned to 32bits */ + RK_U32 payload[0]; +} RkMetaHdrHeader; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void fill_hdr_meta_to_frame(MppFrame frame, MppCodingType in_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/rk_mpi.h b/inc/rk_mpi.h index 682be05b6..f84e8cc53 100644 --- a/inc/rk_mpi.h +++ b/inc/rk_mpi.h @@ -1,177 +1,274 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __RK_MPI_H__ -#define __RK_MPI_H__ - -#include "mpp_packet.h" -#include "mpp_frame.h" - -typedef enum { - MPP_CTX_DEC, - MPP_CTX_ENC, - MPP_CTX_BUTT, -} MppCtxType; - -/** - * Enumeration used to define the possible video compression codings. - * NOTE: This essentially refers to file extensions. If the coding is - * being used to specify the ENCODE type, then additional work - * must be done to configure the exact flavor of the compression - * to be used. For decode cases where the user application can - * not differentiate between MPEG-4 and H.264 bit streams, it is - * up to the codec to handle this. - */ -//sync with the omx_video.h -typedef enum { - MPP_VIDEO_CodingUnused, /**< Value when coding is N/A */ - MPP_VIDEO_CodingAutoDetect, /**< Autodetection of coding type */ - MPP_VIDEO_CodingMPEG2, /**< AKA: H.262 */ - MPP_VIDEO_CodingH263, /**< H.263 */ - MPP_VIDEO_CodingMPEG4, /**< MPEG-4 */ - MPP_VIDEO_CodingWMV, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ - MPP_VIDEO_CodingRV, /**< all versions of Real Video */ - MPP_VIDEO_CodingAVC, /**< H.264/AVC */ - MPP_VIDEO_CodingMJPEG, /**< Motion JPEG */ - MPP_VIDEO_CodingVP8, /**< VP8 */ - MPP_VIDEO_CodingVP9, /**< VP9 */ - MPP_VIDEO_CodingVC1 = 0x01000000, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ - MPP_VIDEO_CodingFLV1, /**< Sorenson H.263 */ - MPP_VIDEO_CodingDIVX3, /**< DIVX3 */ - MPP_VIDEO_CodingVP6, - MPP_VIDEO_CodingHEVC, /**< H.265/HEVC */ - MPP_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ - MPP_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ - MPP_VIDEO_CodingMax = 0x7FFFFFFF -} MppCodingType; - - -typedef enum { - MPP_CMD_BASE = 0, - MPP_ENABLE_DEINTERLACE, - - MPP_HAL_CMD_BASE = 0x10000, - - MPP_OSAL_CMD_BASE = 0x20000, - MPP_OSAL_SET_VPUMEM_CONTEXT, - - MPP_CODEC_CMD_BASE = 0x30000, - MPP_CODEC_INFO_CHANGE, - MPP_CODEC_SET_DEFAULT_WIDTH_HEIGH, - - MPP_DEC_CMD_BASE = 0x40000, - MPP_DEC_USE_PRESENT_TIME_ORDER, - MPP_DEC_SET_VC1_EXTRA_DATA, - MPP_DEC_SET_VP6_ID, - - MPP_ENC_CMD_BASE = 0x50000, - MPP_ENC_SETCFG, - MPP_ENC_GETCFG, - MPP_ENC_SETFORMAT, - MPP_ENC_SETIDRFRAME, -} MpiCmd; - - -typedef void* MppCtx; -typedef void* MppParam; - -/* - * in decoder mode application need to specify the coding type first - * send a stream header to mpi ctx using parameter data / size - * and decoder will try to decode the - */ -typedef struct MppEncConfig_t { - /* - * input source data format - */ - RK_S32 width; - RK_S32 height; - RK_S32 format; - - /* - * rate control parameter - * - * rc_mode - rate control mode - * 0 - fix qp mode - * 1 - constant bit rate mode (CBR) - * 2 - variable bit rate mode (VBR) - * bps - target bit rate, unit: bit per second - * fps_in - input frame rate, unit: frame per second - * fps_out - output frame rate, unit: frame per second - * qp - constant qp for fix qp mode - * initial qp for CBR / VBR - * gop - gap between Intra frame - * 0 for only 1 I frame the rest are all P frames - * 1 for all I frame - * 2 for I P I P I P - * 3 for I P P I P P - * etc... - */ - RK_S32 rc_mode; - RK_S32 bps; - RK_S32 fps_in; - RK_S32 fps_out; - RK_S32 qp; - RK_S32 gop; - - /* - * stream feature parameter - */ - RK_S32 profile; - RK_S32 level; - RK_S32 cabac_en; - RK_S32 trans8x8_en; -} MppEncConfig; - -typedef struct MppApi_t { - RK_U32 size; - RK_U32 version; - - MPP_RET (*config)(MppCtx ctx, MppEncConfig cfg); - - // sync interface - MPP_RET (*decode)(MppCtx ctx, MppPacket packet, MppFrame *frame); - MPP_RET (*encode)(MppCtx ctx, MppFrame frame, MppPacket *packet); - - // async interface - MPP_RET (*decode_put_packet)(MppCtx ctx, MppPacket packet); - MPP_RET (*decode_get_frame)(MppCtx ctx, MppFrame *frame); - - MPP_RET (*encode_put_frame)(MppCtx ctx, MppFrame frame); - MPP_RET (*encode_get_packet)(MppCtx ctx, MppPacket *packet); - - MPP_RET (*flush)(MppCtx ctx); - MPP_RET (*control)(MppCtx ctx, MpiCmd cmd, MppParam param); - - RK_U32 reserv[16]; -} MppApi; - - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * mpp interface - */ -MPP_RET mpp_init(MppCtx *ctx, MppApi **mpi, MppCtxType type, MppCodingType coding); -MPP_RET mpp_deinit(MppCtx ctx); - -#ifdef __cplusplus -} -#endif - -#endif /*__RK_MPI_H__*/ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RK_MPI_H +#define RK_MPI_H + +/** + * @addtogroup rk_mpi + * @brief Rockchip Media Process Interface + * @details Media Process Platform(MPP) provides application programming + * interface for the application layer, by which applications can + * call hardware encode and decode. Current MPP fully supports + * chipset RK3288/RK3228/RK3229/RK3399/RK3328/RV1108. Old chipset + * like RK29xx/RK30xx/RK31XX/RK3368 is partly supported due to lack + * of some hardware register generation module. + */ + +#include "rk_mpi_cmd.h" +#include "mpp_task.h" + +/** + * @ingroup rk_mpi + * @brief MPP main work function set + * @details all api function are seperated into two sets: data io api set + * and control api set + * + * (1). the data api set is for data input/output flow including: + * + * (1.1) simple data api set: + * + * decode : both send video stream packet to decoder and get video frame from + * decoder at the same time. + * + * encode : both send video frame to encoder and get encoded video stream from + * encoder at the same time. + * + * decode_put_packet: send video stream packet to decoder only, async interface + * + * decode_get_frame : get video frame from decoder only, async interface + * + * encode_put_frame : send video frame to encoder only, async interface + * + * encode_get_packet: get encoded video packet from encoder only, async interface + * + * (1.2) advanced task api set: + * + * poll : poll port for dequeue + * + * dequeue : pop a task from mpp task queue + * + * enqueue : push a task to mpp task queue + * + * (2). the control api set is for mpp context control including: + * + * control : similiar to ioctl in kernel driver, setup or get mpp internal parameter + * + * reset : clear all data in mpp context, discard all packet and frame, + * reset all components to initialized status + */ +typedef struct MppApi_t { + /** + * @brief size of struct MppApi + */ + RK_U32 size; + /** + * @brief mpp api version, generated by Git + */ + RK_U32 version; + + // simple data flow interface + /** + * @brief both send video stream packet to decoder and get video frame from + * decoder at the same time + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] packet The input video stream, its usage can refer mpp_packet.h. + * @param[out] frame The output picture, its usage can refer mpp_frame.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*decode)(MppCtx ctx, MppPacket packet, MppFrame *frame); + /** + * @brief send video stream packet to decoder only, async interface + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] packet The input video stream, its usage can refer mpp_packet.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*decode_put_packet)(MppCtx ctx, MppPacket packet); + /** + * @brief get video frame from decoder only, async interface + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[out] frame The output picture, its usage can refer mpp_frame.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*decode_get_frame)(MppCtx ctx, MppFrame *frame); + /** + * @brief both send video frame to encoder and get encoded video stream from + * encoder at the same time + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] frame The input video data, its usage can refer mpp_frame.h. + * @param[out] packet The output compressed data, its usage can refer mpp_packet.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*encode)(MppCtx ctx, MppFrame frame, MppPacket *packet); + /** + * @brief send video frame to encoder only, async interface + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] frame The input video data, its usage can refer mpp_frame.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*encode_put_frame)(MppCtx ctx, MppFrame frame); + /** + * @brief get encoded video packet from encoder only, async interface + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[out] packet The output compressed data, its usage can refer mpp_packet.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*encode_get_packet)(MppCtx ctx, MppPacket *packet); + + /** + * @brief ISP interface, will be supported in the future. + */ + MPP_RET (*isp)(MppCtx ctx, MppFrame dst, MppFrame src); + /** + * @brief ISP interface, will be supported in the future. + */ + MPP_RET (*isp_put_frame)(MppCtx ctx, MppFrame frame); + /** + * @brief ISP interface, will be supported in the future. + */ + MPP_RET (*isp_get_frame)(MppCtx ctx, MppFrame *frame); + + // advance data flow interface + /** + * @brief poll port for dequeue + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] type input port or output port which are both for data transaction + * @param[in] timeout mpp poll type, its usage can refer mpp_task.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*poll)(MppCtx ctx, MppPortType type, MppPollType timeout); + /** + * @brief dequeue MppTask, pop a task from mpp task queue + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] type input port or output port which are both for data transaction + * @param[out] task MppTask popped from mpp task queue, its usage can refer mpp_task.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*dequeue)(MppCtx ctx, MppPortType type, MppTask *task); + /** + * @brief enqueue MppTask, push a task to mpp task queue + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] type input port or output port which are both for data transaction + * @param[in] task MppTask which is sent to mpp for process, its usage can refer mpp_task.h. + * @return 0 and positive for success, negative for failure. The return + * value is an error code. For details, please refer mpp_err.h. + */ + MPP_RET (*enqueue)(MppCtx ctx, MppPortType type, MppTask task); + + // control interface + /** + * @brief discard all packet and frame, reset all component, + * for both decoder and encoder + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @return 0 for success, others for failure. The return value is an + * error code. For details, please refer mpp_err.h. + */ + MPP_RET (*reset)(MppCtx ctx); + /** + * @brief control function for mpp property setting + * @param[in] ctx The context of mpp, created by mpp_create() and initiated + * by mpp_init(). + * @param[in] cmd The mpi command, its definition can refer rk_mpi_cmd.h. + * @param[in,out] param The mpi command parameter + * @return 0 for success, others for failure. The return value is an + * error code. For details, please refer mpp_err.h. + */ + MPP_RET (*control)(MppCtx ctx, MpiCmd cmd, MppParam param); + + /** + * @brief The reserved segment, may be used in the future + */ + RK_U32 reserv[16]; +} MppApi; + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @ingroup rk_mpi + * @brief Create empty context structure and mpi function pointers. + * Use functions in MppApi to access mpp services. + * @param[in,out] ctx pointer of the mpp context, refer to MpiImpl_t. + * @param[in,out] mpi pointer of mpi function, refer to MppApi. + * @return 0 for success, others for failure. The return value is an + * error code. For details, please refer mpp_err.h. + * @note This interface creates base flow context, all function calls + * are based on it. + */ +MPP_RET mpp_create(MppCtx *ctx, MppApi **mpi); +/** + * @ingroup rk_mpi + * @brief Call after mpp_create to setup mpp type and video format. + * This function will call internal context init function. + * @param[in] ctx The context of mpp, created by mpp_create(). + * @param[in] type specify decoder or encoder, refer to MppCtxType. + * @param[in] coding specify video compression coding, refer to MppCodingType. + * @return 0 for success, others for failure. The return value is an + * error code. For details, please refer mpp_err.h. + */ +MPP_RET mpp_init(MppCtx ctx, MppCtxType type, MppCodingType coding); +/** + * @ingroup rk_mpi + * @brief Destroy mpp context and free both context and mpi structure, + * it matches with mpp_init(). + * @param[in] ctx The context of mpp, created by mpp_create(). + * @return 0 for success, others for failure. The return value is an + * error code. For details, please refer mpp_err.h. + */ +MPP_RET mpp_destroy(MppCtx ctx); +/** + * @ingroup rk_mpi + * @brief judge given format is supported or not by MPP. + * @param[in] type specify decoder or encoder, refer to MppCtxType. + * @param[in] coding specify video compression coding, refer to MppCodingType. + * @return 0 for support, -1 for unsupported. + */ +MPP_RET mpp_check_support_format(MppCtxType type, MppCodingType coding); +/** + * @ingroup rk_mpi + * @brief List all formats supported by MPP + * @param NULL no need to input parameter + * @return No return value. This function just prints format information supported + * by MPP on standard output. + */ +void mpp_show_support_format(void); +void mpp_show_color_format(void); + +#ifdef __cplusplus +} +#endif + +#endif /* RK_MPI_H */ diff --git a/inc/rk_mpi_cmd.h b/inc/rk_mpi_cmd.h new file mode 100644 index 000000000..55861c0ef --- /dev/null +++ b/inc/rk_mpi_cmd.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_MPI_CMD_H +#define RK_MPI_CMD_H + +#include "rk_type.h" +#include "mpp_bit.h" + +/* + * Command id bit usage is defined as follows: + * bit 20 - 23 - module id + * bit 16 - 19 - contex id + * bit 0 - 15 - command id + */ +#define CMD_MODULE_ID_MASK (0x00F00000) +#define CMD_MODULE_OSAL (0x00100000) +#define CMD_MODULE_MPP (0x00200000) +#define CMD_MODULE_CODEC (0x00300000) +#define CMD_MODULE_HAL (0x00400000) + +#define CMD_CTX_ID_MASK (0x000F0000) +#define CMD_CTX_ID_DEC (0x00010000) +#define CMD_CTX_ID_ENC (0x00020000) +#define CMD_CTX_ID_ISP (0x00030000) + +/* separate encoder / decoder control command to different segment */ +#define CMD_CFG_ID_MASK (0x0000FF00) + +/* mpp status control command */ +#define CMD_STATE_OPS (0x00000100) + +/* decoder control command */ +#define CMD_DEC_CFG_ALL (0x00000000) +#define CMD_DEC_QUERY (0x00000100) +#define CMD_DEC_CFG (0x00000200) + +/* encoder control command */ +#define CMD_ENC_CFG_ALL (0x00000000) +#define CMD_ENC_QUERY (0x00000100) +#define CMD_ENC_CFG_RC_API (0x00000200) + +#define CMD_ENC_CFG_MISC (0x00008000) +#define CMD_ENC_CFG_SPLIT (0x00008100) +#define CMD_ENC_CFG_REF (0x00008200) +#define CMD_ENC_CFG_ROI (0x00008300) +#define CMD_ENC_CFG_OSD (0x00008400) +#define CMD_ENC_CFG_USERDATA (0x00008500) + +typedef enum { + MPP_OSAL_CMD_BASE = CMD_MODULE_OSAL, + MPP_OSAL_CMD_END, + + MPP_CMD_BASE = CMD_MODULE_MPP, + MPP_ENABLE_DEINTERLACE, + MPP_SET_INPUT_BLOCK, /* deprecated */ + MPP_SET_INTPUT_BLOCK_TIMEOUT, /* deprecated */ + MPP_SET_OUTPUT_BLOCK, /* deprecated */ + MPP_SET_OUTPUT_BLOCK_TIMEOUT, /* deprecated */ + /* + * timeout setup, refer to MPP_TIMEOUT_XXX + * zero - non block + * negative - block with no timeout + * positive - timeout in milisecond + */ + MPP_SET_INPUT_TIMEOUT, /* parameter type RK_S64 */ + MPP_SET_OUTPUT_TIMEOUT, /* parameter type RK_S64 */ + MPP_SET_DISABLE_THREAD, /* MPP no thread mode and use external thread to decode */ + MPP_SET_SELECT_TIMEOUT, /* kmpp path select operation timeout */ + MPP_SET_VENC_INIT_KCFG, /* kmpp path venc init cfg set */ + + MPP_STATE_CMD_BASE = MPP_FLAG_OR(CMD_MODULE_MPP, CMD_STATE_OPS), + MPP_START, + MPP_STOP, + MPP_PAUSE, + MPP_RESUME, + + MPP_CMD_END, + + MPP_CODEC_CMD_BASE = CMD_MODULE_CODEC, + MPP_CODEC_GET_FRAME_INFO, + MPP_CODEC_CMD_END, + + MPP_DEC_CMD_BASE = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_DEC), + MPP_DEC_SET_FRAME_INFO, /* vpu api legacy control for buffer slot dimension init */ + MPP_DEC_SET_EXT_BUF_GROUP, /* IMPORTANT: set external buffer group to mpp decoder */ + MPP_DEC_SET_INFO_CHANGE_READY, + MPP_DEC_SET_PRESENT_TIME_ORDER, /* use input time order for output */ + MPP_DEC_SET_PARSER_SPLIT_MODE, /* Need to setup before init */ + MPP_DEC_SET_PARSER_FAST_MODE, /* Need to setup before init */ + MPP_DEC_GET_STREAM_COUNT, + MPP_DEC_GET_VPUMEM_USED_COUNT, + MPP_DEC_SET_VC1_EXTRA_DATA, + MPP_DEC_SET_OUTPUT_FORMAT, + MPP_DEC_SET_DISABLE_ERROR, /* When set it will disable sw/hw error (H.264 / H.265) */ + MPP_DEC_SET_IMMEDIATE_OUT, + MPP_DEC_SET_ENABLE_DEINTERLACE, /* MPP enable deinterlace by default. Vpuapi can disable it */ + MPP_DEC_SET_ENABLE_FAST_PLAY, /* enable idr output immediately */ + MPP_DEC_SET_DISABLE_THREAD, /* MPP no thread mode and use external thread to decode */ + MPP_DEC_SET_MAX_USE_BUFFER_SIZE, + MPP_DEC_SET_ENABLE_MVC, /* enable MVC decoding*/ + MPP_DEC_GET_THUMBNAIL_FRAME_INFO, /* update thumbnail frame info to user, for MPP_FRAME_THUMBNAIL_ONLY mode */ + MPP_DEC_SET_DISABLE_DPB_CHECK, /* disable dpb discontinuous check */ + MPP_DEC_SET_CODEC_MODE, /* select codec mode */ + MPP_DEC_SET_DIS_ERR_CLR_MARK, + + MPP_DEC_CMD_QUERY = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_DEC, CMD_DEC_QUERY), + /* query decoder runtime information for decode stage */ + MPP_DEC_QUERY, /* set and get MppDecQueryCfg structure */ + + CMD_DEC_CMD_CFG = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_DEC, CMD_DEC_CFG), + MPP_DEC_SET_CFG, /* set MppDecCfg structure */ + MPP_DEC_GET_CFG, /* get MppDecCfg structure */ + + MPP_DEC_CMD_END, + + MPP_ENC_CMD_BASE = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC), + /* basic encoder setup control */ + MPP_ENC_SET_CFG, /* set MppEncCfg structure */ + MPP_ENC_GET_CFG, /* get MppEncCfg structure */ + MPP_ENC_SET_PREP_CFG, /* deprecated set MppEncPrepCfg structure, use MPP_ENC_SET_CFG instead */ + MPP_ENC_GET_PREP_CFG, /* deprecated get MppEncPrepCfg structure, use MPP_ENC_GET_CFG instead */ + MPP_ENC_SET_RC_CFG, /* deprecated set MppEncRcCfg structure, use MPP_ENC_SET_CFG instead */ + MPP_ENC_GET_RC_CFG, /* deprecated get MppEncRcCfg structure, use MPP_ENC_GET_CFG instead */ + MPP_ENC_SET_CODEC_CFG, /* deprecated set MppEncCodecCfg structure, use MPP_ENC_SET_CFG instead */ + MPP_ENC_GET_CODEC_CFG, /* deprecated get MppEncCodecCfg structure, use MPP_ENC_GET_CFG instead */ + /* runtime encoder setup control */ + MPP_ENC_SET_IDR_FRAME, /* next frame will be encoded as intra frame */ + MPP_ENC_SET_OSD_LEGACY_0, /* deprecated */ + MPP_ENC_SET_OSD_LEGACY_1, /* deprecated */ + MPP_ENC_SET_OSD_LEGACY_2, /* deprecated */ + MPP_ENC_GET_HDR_SYNC, /* get vps / sps / pps which has better sync behavior parameter is MppPacket */ + MPP_ENC_GET_EXTRA_INFO, /* deprecated */ + MPP_ENC_SET_SEI_CFG, /* SEI: Supplement Enhancemant Information, parameter is MppSeiMode */ + MPP_ENC_GET_SEI_DATA, /* SEI: Supplement Enhancemant Information, parameter is MppPacket */ + MPP_ENC_PRE_ALLOC_BUFF, /* deprecated */ + MPP_ENC_SET_QP_RANGE, /* used for adjusting qp range, the parameter can be 1 or 2 */ + MPP_ENC_SET_ROI_CFG, /* set MppEncROICfg structure */ + MPP_ENC_SET_CTU_QP, /* for H265 Encoder,set CTU's size and QP */ + MPP_ENC_GET_ROI_CFG, /* get MppEncROICfg structure */ + MPP_ENC_SET_JPEG_ROI_CFG, /* set MppJpegROICfg structure */ + MPP_ENC_GET_JPEG_ROI_CFG, /* get MppJpegROICfg structure */ + + MPP_ENC_CMD_QUERY = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC, CMD_ENC_QUERY), + /* query encoder runtime information for encode stage */ + MPP_ENC_QUERY, /* set and get MppEncQueryCfg structure */ + + /* User define rate control stategy API control */ + MPP_ENC_CFG_RC_API = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC, CMD_ENC_CFG_RC_API), + /* + * Get RcApiQueryAll structure + * Get all available rate control stategy string and count + */ + MPP_ENC_GET_RC_API_ALL = MPP_ENC_CFG_RC_API + 1, + /* + * Get RcApiQueryType structure + * Get available rate control stategy string with certain type + */ + MPP_ENC_GET_RC_API_BY_TYPE = MPP_ENC_CFG_RC_API + 2, + /* + * Set RcImplApi structure + * Add new or update rate control stategy function pointers + */ + MPP_ENC_SET_RC_API_CFG = MPP_ENC_CFG_RC_API + 3, + /* + * Get RcApiBrief structure + * Get current used rate control stategy brief information (type and name) + */ + MPP_ENC_GET_RC_API_CURRENT = MPP_ENC_CFG_RC_API + 4, + /* + * Set RcApiBrief structure + * Set current used rate control stategy brief information (type and name) + */ + MPP_ENC_SET_RC_API_CURRENT = MPP_ENC_CFG_RC_API + 5, + + MPP_ENC_CFG_MISC = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC, CMD_ENC_CFG_MISC), + MPP_ENC_SET_HEADER_MODE, /* set MppEncHeaderMode */ + MPP_ENC_GET_HEADER_MODE, /* get MppEncHeaderMode */ + + MPP_ENC_CFG_SPLIT = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC, CMD_ENC_CFG_SPLIT), + MPP_ENC_SET_SPLIT, /* set MppEncSliceSplit structure */ + MPP_ENC_GET_SPLIT, /* get MppEncSliceSplit structure */ + + MPP_ENC_CFG_REF = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC, CMD_ENC_CFG_REF), + MPP_ENC_SET_REF_CFG, /* set MppEncRefCfg structure */ + MPP_ENC_GET_REF_CFG, + + MPP_ENC_CFG_OSD = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC, CMD_ENC_CFG_OSD), + MPP_ENC_SET_OSD_PLT_CFG, /* set OSD palette, parameter should be pointer to MppEncOSDPltCfg */ + MPP_ENC_GET_OSD_PLT_CFG, /* get OSD palette, parameter should be pointer to MppEncOSDPltCfg */ + MPP_ENC_SET_OSD_DATA_CFG, /* set OSD data with at most 8 regions, parameter should be pointer to MppEncOSDData */ + + MPP_ENC_CFG_USERDATA = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ENC, CMD_ENC_CFG_USERDATA), + MPP_ENC_SET_USERDATA, + MPP_ENC_GET_USERDATA, + MPP_ENC_CMD_END, + + MPP_ISP_CMD_BASE = MPP_FLAG_OR(CMD_MODULE_CODEC, CMD_CTX_ID_ISP), + MPP_ISP_CMD_END, + + MPP_HAL_CMD_BASE = CMD_MODULE_HAL, + MPP_HAL_CMD_END, + + MPI_CMD_BUTT, +} MpiCmd; + +#include "rk_vdec_cmd.h" +#include "rk_vdec_cfg.h" +#include "rk_venc_cmd.h" +#include "rk_venc_cfg.h" +#include "rk_venc_ref.h" + +#endif /* RK_MPI_CMD_H */ diff --git a/inc/rk_mpp_cfg.h b/inc/rk_mpp_cfg.h new file mode 100644 index 000000000..2a94dd5c6 --- /dev/null +++ b/inc/rk_mpp_cfg.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_MPP_CFG_H +#define RK_MPP_CFG_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef enum MppCfgStrFmt_e { + MPP_CFG_STR_FMT_LOG, + MPP_CFG_STR_FMT_JSON, + MPP_CFG_STR_FMT_TOML, + MPP_CFG_STR_FMT_BUTT, +} MppCfgStrFmt; + +typedef void* MppSysCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_sys_cfg_get(MppSysCfg *cfg); +MPP_RET mpp_sys_cfg_put(MppSysCfg cfg); +MPP_RET mpp_sys_cfg_ioctl(MppSysCfg cfg); + +MPP_RET mpp_sys_cfg_set_s32(MppSysCfg cfg, const char *name, RK_S32 val); +MPP_RET mpp_sys_cfg_set_u32(MppSysCfg cfg, const char *name, RK_U32 val); +MPP_RET mpp_sys_cfg_set_s64(MppSysCfg cfg, const char *name, RK_S64 val); +MPP_RET mpp_sys_cfg_set_u64(MppSysCfg cfg, const char *name, RK_U64 val); +MPP_RET mpp_sys_cfg_set_ptr(MppSysCfg cfg, const char *name, void *val); + +MPP_RET mpp_sys_cfg_get_s32(MppSysCfg cfg, const char *name, RK_S32 *val); +MPP_RET mpp_sys_cfg_get_u32(MppSysCfg cfg, const char *name, RK_U32 *val); +MPP_RET mpp_sys_cfg_get_s64(MppSysCfg cfg, const char *name, RK_S64 *val); +MPP_RET mpp_sys_cfg_get_u64(MppSysCfg cfg, const char *name, RK_U64 *val); +MPP_RET mpp_sys_cfg_get_ptr(MppSysCfg cfg, const char *name, void **val); + +void mpp_sys_cfg_show(void); + +#ifdef __cplusplus +} +#endif + +#endif /* RK_MPP_CFG_H */ diff --git a/inc/rk_type.h b/inc/rk_type.h index 4b736c54b..45e7a1bc3 100644 --- a/inc/rk_type.h +++ b/inc/rk_type.h @@ -1,60 +1,204 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * File : rk_type.h - * Description : type definition - * Author : Jian Huan - * Date : 2010-11-23 21:48:40 - */ - -#ifndef __RK_TYPE_H__ -#define __RK_TYPE_H__ - -#include - -#if defined(_WIN32) && !defined(__MINGW32CE__) - -typedef unsigned char RK_U8; -typedef unsigned short RK_U16; -typedef unsigned int RK_U32; -typedef unsigned __int64 RK_U64; - -typedef signed char RK_S8; -typedef signed short RK_S16; -typedef signed int RK_S32; -typedef signed __int64 RK_S64; - -#else - -typedef unsigned char RK_U8; -typedef unsigned short RK_U16; -typedef unsigned int RK_U32; -typedef unsigned long long int RK_U64; - - -typedef signed char RK_S8; -typedef signed short RK_S16; -typedef signed int RK_S32; -typedef signed long long int RK_S64; - -#endif - -#ifndef MODULE_TAG -#define MODULE_TAG NULL -#endif - -#endif /*__RK_TYPE_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_TYPE_H +#define RK_TYPE_H + +#include + +typedef unsigned char RK_U8; +typedef unsigned short RK_U16; +typedef unsigned int RK_U32; +typedef unsigned long RK_ULONG; +typedef RK_ULONG RK_UL; +typedef unsigned long long int RK_U64; + +typedef signed char RK_S8; +typedef signed short RK_S16; +typedef signed int RK_S32; +typedef signed long RK_LONG; +typedef RK_LONG RK_SL; +typedef signed long long int RK_S64; + +typedef float RK_FLOAT; +typedef double RK_DOUBLE; + +typedef unsigned long RK_SIZE_T; +typedef unsigned int RK_HANDLE; + +typedef unsigned char rk_u8; +typedef unsigned short rk_u16; +typedef unsigned int rk_u32; +typedef unsigned long rk_ulong; +typedef rk_ulong rk_ul; +typedef unsigned long long int rk_u64; + +typedef signed char rk_s8; +typedef signed short rk_s16; +typedef signed int rk_s32; +typedef signed long rk_long; +typedef rk_long rk_sl; +typedef signed long long int rk_s64; + +typedef float rk_float; +typedef double rk_double; + +typedef unsigned long rk_size_t; +typedef unsigned int rk_handle; + +typedef enum { + RK_FALSE = 0, + RK_TRUE = 1, +} RK_BOOL; + +typedef enum { + rk_false = 0, + rk_true = 1, +} rk_bool; + +#ifndef NULL +#define NULL 0L +#endif + +#define RK_RET RK_S32 +#define RK_NULL 0L +#define RK_OK 0 +#define RK_NOK (-1) +#define RK_SUCCESS 0 +#define RK_FAILURE (-1) + +#define RK_VOID void +#define RK_UNUSED(x) ((void)((x))) + +#define rk_ret rk_s32 +#define rk_null 0L +#define rk_ok 0 +#define rk_nok (-1) +#define rk_success 0 +#define rk_failure (-1) + +#define rk_void void +#define rk_unused(x) ((void)((x))) + +#ifndef MODULE_TAG +#define MODULE_TAG NULL +#endif + +/** + * @ingroup rk_mpi + * @brief The type of mpp context + * @details This type is used when calling mpp_init(), which including decoder, + * encoder and Image Signal Process(ISP). So far decoder and encoder + * are supported perfectly, and ISP will be supported in the future. + */ +typedef enum { + MPP_CTX_DEC, /**< decoder */ + MPP_CTX_ENC, /**< encoder */ + MPP_CTX_ISP, /**< isp */ + MPP_CTX_BUTT, /**< undefined */ +} MppCtxType; + +/** + * @ingroup rk_mpi + * @brief Enumeration used to define the possible video compression codings. + * sync with the omx_video.h + * + * @note This essentially refers to file extensions. If the coding is + * being used to specify the ENCODE type, then additional work + * must be done to configure the exact flavor of the compression + * to be used. For decode cases where the user application can + * not differentiate between MPEG-4 and H.264 bit streams, it is + * up to the codec to handle this. + */ +typedef enum { + MPP_VIDEO_CodingUnused, /**< Value when coding is N/A */ + MPP_VIDEO_CodingAutoDetect, /**< Autodetection of coding type */ + MPP_VIDEO_CodingMPEG2, /**< AKA: H.262 */ + MPP_VIDEO_CodingH263, /**< H.263 */ + MPP_VIDEO_CodingMPEG4, /**< MPEG-4 */ + MPP_VIDEO_CodingWMV, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ + MPP_VIDEO_CodingRV, /**< all versions of Real Video */ + MPP_VIDEO_CodingAVC, /**< H.264/AVC */ + MPP_VIDEO_CodingMJPEG, /**< Motion JPEG */ + MPP_VIDEO_CodingVP8, /**< VP8 */ + MPP_VIDEO_CodingVP9, /**< VP9 */ + MPP_VIDEO_CodingVC1 = 0x01000000, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ + MPP_VIDEO_CodingFLV1, /**< Sorenson H.263 */ + MPP_VIDEO_CodingDIVX3, /**< DIVX3 */ + MPP_VIDEO_CodingVP6, + MPP_VIDEO_CodingHEVC, /**< H.265/HEVC */ + MPP_VIDEO_CodingAVSPLUS, /**< AVS+ */ + MPP_VIDEO_CodingAVS, /**< AVS profile=0x20 */ + MPP_VIDEO_CodingAVS2, /**< AVS2 */ + MPP_VIDEO_CodingAV1, /**< av1 */ + MPP_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + MPP_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + MPP_VIDEO_CodingMax = 0x7FFFFFFF +} MppCodingType; + +/* + * All external interface object list here. + * The interface object is defined as void * for expandability + * The cross include between these objects will introduce extra + * compiling difficulty. So we move them together in this header. + * + * Object interface header list: + * + * MppCtx - rk_mpi.h + * MppParam - rk_mpi.h + * + * MppFrame - mpp_frame.h + * MppPacket - mpp_packet.h + * + * MppBuffer - mpp_buffer.h + * MppBufferGroup - mpp_buffer.h + * + * MppTask - mpp_task.h + * MppMeta - mpp_meta.h + */ + +typedef void* MppCtx; +typedef void* MppParam; + +typedef void* MppFrame; +typedef void* MppPacket; + +typedef void* MppBuffer; +typedef void* MppBufferGroup; + +typedef void* MppTask; +typedef void* MppMeta; + +/* KmppObjDef - mpp object name size and access table trie definition */ +typedef void* KmppObjDef; +/* KmppObj - mpp object for string name access and function access */ +typedef void* KmppObj; +/* KmppShm - mpp share memory for kernel / userspace transaction */ +typedef void* KmppShm; + +/* kmpp transaction object */ +typedef void* KmppMeta; +typedef void* KmppFrame; +typedef void* KmppPacket; + +typedef void* KmppBuffer; +typedef void* KmppBufGrp; + +/* MUST be the same to the KmppObjShm in rk-mpp-kobj.h */ +typedef struct KmppShmPtr_t { + /* uaddr - the userspace base address for userspace access */ + union { + rk_u64 uaddr; + void *uptr; + }; + /* kaddr - the kernel base address for kernel access */ + union { + rk_u64 kaddr; + void *kptr; + }; + /* DO NOT access reserved data only used by kernel */ +} KmppShmPtr; + +#endif /* RK_TYPE_H */ diff --git a/inc/rk_vdec_cfg.h b/inc/rk_vdec_cfg.h new file mode 100644 index 000000000..69fd57c94 --- /dev/null +++ b/inc/rk_vdec_cfg.h @@ -0,0 +1,50 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RK_VDEC_CFG_H +#define RK_VDEC_CFG_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef void* MppDecCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_dec_cfg_init(MppDecCfg *cfg); +MPP_RET mpp_dec_cfg_deinit(MppDecCfg cfg); + +MPP_RET mpp_dec_cfg_set_s32(MppDecCfg cfg, const char *name, RK_S32 val); +MPP_RET mpp_dec_cfg_set_u32(MppDecCfg cfg, const char *name, RK_U32 val); +MPP_RET mpp_dec_cfg_set_s64(MppDecCfg cfg, const char *name, RK_S64 val); +MPP_RET mpp_dec_cfg_set_u64(MppDecCfg cfg, const char *name, RK_U64 val); +MPP_RET mpp_dec_cfg_set_ptr(MppDecCfg cfg, const char *name, void *val); + +MPP_RET mpp_dec_cfg_get_s32(MppDecCfg cfg, const char *name, RK_S32 *val); +MPP_RET mpp_dec_cfg_get_u32(MppDecCfg cfg, const char *name, RK_U32 *val); +MPP_RET mpp_dec_cfg_get_s64(MppDecCfg cfg, const char *name, RK_S64 *val); +MPP_RET mpp_dec_cfg_get_u64(MppDecCfg cfg, const char *name, RK_U64 *val); +MPP_RET mpp_dec_cfg_get_ptr(MppDecCfg cfg, const char *name, void **val); + +void mpp_dec_cfg_show(void); + +#ifdef __cplusplus +} +#endif + +#endif /* RK_VDEC_CFG_H */ diff --git a/inc/rk_vdec_cmd.h b/inc/rk_vdec_cmd.h new file mode 100644 index 000000000..fc333d5c4 --- /dev/null +++ b/inc/rk_vdec_cmd.h @@ -0,0 +1,69 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RK_VDEC_CMD_H +#define RK_VDEC_CMD_H + +#include "rk_type.h" +#include "mpp_err.h" + +/* + * decoder query interface is only for debug usage + */ +#define MPP_DEC_QUERY_STATUS (0x00000001) +#define MPP_DEC_QUERY_WAIT (0x00000002) +#define MPP_DEC_QUERY_FPS (0x00000004) +#define MPP_DEC_QUERY_BPS (0x00000008) +#define MPP_DEC_QUERY_DEC_IN_PKT (0x00000010) +#define MPP_DEC_QUERY_DEC_WORK (0x00000020) +#define MPP_DEC_QUERY_DEC_OUT_FRM (0x00000040) + +#define MPP_DEC_QUERY_ALL (MPP_DEC_QUERY_STATUS | \ + MPP_DEC_QUERY_WAIT | \ + MPP_DEC_QUERY_FPS | \ + MPP_DEC_QUERY_BPS | \ + MPP_DEC_QUERY_DEC_IN_PKT | \ + MPP_DEC_QUERY_DEC_WORK | \ + MPP_DEC_QUERY_DEC_OUT_FRM) + +typedef struct MppDecQueryCfg_t { + /* + * 32 bit query flag for query data check + * Each bit represent a query data switch. + * bit 0 - for querying decoder runtime status + * bit 1 - for querying decoder runtime waiting status + * bit 2 - for querying decoder realtime decode fps + * bit 3 - for querying decoder realtime input bps + * bit 4 - for querying decoder input packet count + * bit 5 - for querying decoder start hardware times + * bit 6 - for querying decoder output frame count + */ + RK_U32 query_flag; + + /* 64 bit query data output */ + RK_U32 rt_status; + RK_U32 rt_wait; + RK_U32 rt_fps; + RK_U32 rt_bps; + RK_U32 dec_in_pkt_cnt; + RK_U32 dec_hw_run_cnt; + RK_U32 dec_out_frm_cnt; +} MppDecQueryCfg; + +typedef void* MppExtCbCtx; +typedef MPP_RET (*MppExtCbFunc)(MppExtCbCtx cb_ctx, MppCtx mpp, RK_S32 cmd, void *arg); + +#endif /* RK_VDEC_CMD_H */ diff --git a/inc/rk_vdec_kcfg.h b/inc/rk_vdec_kcfg.h new file mode 100644 index 000000000..d3b7a3f67 --- /dev/null +++ b/inc/rk_vdec_kcfg.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_VDEC_KCFG_H +#define RK_VDEC_KCFG_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef void* MppVdecKcfg; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MPP_VDEC_KCFG_TYPE_INIT, + MPP_VDEC_KCFG_TYPE_DEINIT, + MPP_VDEC_KCFG_TYPE_RESET, + MPP_VDEC_KCFG_TYPE_START, + MPP_VDEC_KCFG_TYPE_STOP, + MPP_VDEC_KCFG_TYPE_BUTT, +} MppVdecKcfgType; + +MPP_RET mpp_vdec_kcfg_init(MppVdecKcfg *cfg, MppVdecKcfgType type); +MPP_RET mpp_vdec_kcfg_init_by_name(MppVdecKcfg *cfg, const char *name); +MPP_RET mpp_vdec_kcfg_deinit(MppVdecKcfg cfg); + +MPP_RET mpp_vdec_kcfg_set_s32(MppVdecKcfg cfg, const char *name, RK_S32 val); +MPP_RET mpp_vdec_kcfg_set_u32(MppVdecKcfg cfg, const char *name, RK_U32 val); +MPP_RET mpp_vdec_kcfg_set_s64(MppVdecKcfg cfg, const char *name, RK_S64 val); +MPP_RET mpp_vdec_kcfg_set_u64(MppVdecKcfg cfg, const char *name, RK_U64 val); +MPP_RET mpp_vdec_kcfg_set_ptr(MppVdecKcfg cfg, const char *name, void *val); +MPP_RET mpp_vdec_kcfg_set_st(MppVdecKcfg cfg, const char *name, void *val); + +MPP_RET mpp_vdec_kcfg_get_s32(MppVdecKcfg cfg, const char *name, RK_S32 *val); +MPP_RET mpp_vdec_kcfg_get_u32(MppVdecKcfg cfg, const char *name, RK_U32 *val); +MPP_RET mpp_vdec_kcfg_get_s64(MppVdecKcfg cfg, const char *name, RK_S64 *val); +MPP_RET mpp_vdec_kcfg_get_u64(MppVdecKcfg cfg, const char *name, RK_U64 *val); +MPP_RET mpp_vdec_kcfg_get_ptr(MppVdecKcfg cfg, const char *name, void **val); +MPP_RET mpp_vdec_kcfg_get_st(MppVdecKcfg cfg, const char *name, void *val); + +void mpp_vdec_kcfg_show(MppVdecKcfg cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* RK_VDEC_KCFG_H */ diff --git a/inc/rk_venc_cfg.h b/inc/rk_venc_cfg.h new file mode 100644 index 000000000..f1fce4855 --- /dev/null +++ b/inc/rk_venc_cfg.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_VENC_CFG_H +#define RK_VENC_CFG_H + +#include "rk_mpp_cfg.h" + +typedef void* MppEncCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +/* userspace encoder config init */ +MPP_RET mpp_enc_cfg_init(MppEncCfg *cfg); +/* kernel encoder config init */ +MPP_RET mpp_enc_cfg_init_k(MppEncCfg *cfg); +/* common config deinit */ +MPP_RET mpp_enc_cfg_deinit(MppEncCfg cfg); + +MPP_RET mpp_enc_cfg_set_s8(MppEncCfg cfg, const char *name, RK_S8 val); +MPP_RET mpp_enc_cfg_set_u8(MppEncCfg cfg, const char *name, RK_U8 val); +MPP_RET mpp_enc_cfg_set_s16(MppEncCfg cfg, const char *name, RK_S16 val); +MPP_RET mpp_enc_cfg_set_u16(MppEncCfg cfg, const char *name, RK_U16 val); +MPP_RET mpp_enc_cfg_set_s32(MppEncCfg cfg, const char *name, RK_S32 val); +MPP_RET mpp_enc_cfg_set_u32(MppEncCfg cfg, const char *name, RK_U32 val); +MPP_RET mpp_enc_cfg_set_s64(MppEncCfg cfg, const char *name, RK_S64 val); +MPP_RET mpp_enc_cfg_set_u64(MppEncCfg cfg, const char *name, RK_U64 val); +MPP_RET mpp_enc_cfg_set_ptr(MppEncCfg cfg, const char *name, void *val); +MPP_RET mpp_enc_cfg_set_st(MppEncCfg cfg, const char *name, void *val); + +MPP_RET mpp_enc_cfg_get_s8(MppEncCfg cfg, const char *name, RK_S8 *val); +MPP_RET mpp_enc_cfg_get_u8(MppEncCfg cfg, const char *name, RK_U8 *val); +MPP_RET mpp_enc_cfg_get_s16(MppEncCfg cfg, const char *name, RK_S16 *val); +MPP_RET mpp_enc_cfg_get_u16(MppEncCfg cfg, const char *name, RK_U16 *val); +MPP_RET mpp_enc_cfg_get_s32(MppEncCfg cfg, const char *name, RK_S32 *val); +MPP_RET mpp_enc_cfg_get_u32(MppEncCfg cfg, const char *name, RK_U32 *val); +MPP_RET mpp_enc_cfg_get_s64(MppEncCfg cfg, const char *name, RK_S64 *val); +MPP_RET mpp_enc_cfg_get_u64(MppEncCfg cfg, const char *name, RK_U64 *val); +MPP_RET mpp_enc_cfg_get_ptr(MppEncCfg cfg, const char *name, void **val); +MPP_RET mpp_enc_cfg_get_st(MppEncCfg cfg, const char *name, void *val); + +void mpp_enc_cfg_show(void); +MPP_RET mpp_enc_cfg_extract(MppEncCfg cfg, MppCfgStrFmt fmt, char **buf); +MPP_RET mpp_enc_cfg_apply(MppEncCfg cfg, MppCfgStrFmt fmt, char *buf); + +#ifdef __cplusplus +} +#endif + +#endif /* RK_VENC_CFG_H */ diff --git a/inc/rk_venc_cmd.h b/inc/rk_venc_cmd.h new file mode 100644 index 000000000..e50cec30c --- /dev/null +++ b/inc/rk_venc_cmd.h @@ -0,0 +1,1310 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_VENC_CMD_H +#define RK_VENC_CMD_H + +#include "mpp_bit.h" +#include "mpp_frame.h" +#include "rk_venc_rc.h" + +/* + * Configure of encoder is very complicated. So we divide configures into + * four parts: + * + * 1. Rate control parameter + * This is quality and bitrate request from user. + * + * 2. Data source MppFrame parameter + * This is data source buffer information. + * Now it is PreP config + * PreP : Encoder Preprocess configuration + * + * 3. Video codec infomation + * This is user custormized stream information. + * including: + * H.264 / H.265 / vp8 / mjpeg + * + * 4. Misc parameter + * including: + * Split : Slice split configuration + * GopRef: Reference gop configuration + * ROI : Region Of Interest + * OSD : On Screen Display + * MD : Motion Detection + * + * The module transcation flow is as follows: + * + * + + + * User | Mpi/Mpp | EncImpl + * | | Hal + * | | + * +----------+ | +---------+ | +-----------+ + * | | | | +-----RcCfg-----> | + * | RcCfg +---------> | | | EncImpl | + * | | | | | +-Frame-----> | + * +----------+ | | | | | +--+-----^--+ + * | | | | | | | + * | | | | | | | + * +----------+ | | | | | syntax | + * | | | | | | | | | + * | MppFrame +---------> MppEnc +---+ | | result + * | | | | | | | | | + * +----------+ | | | | | | | + * | | | | | +--v-----+--+ + * | | | +-Frame-----> | + * +----------+ | | | | | | + * | | | | +---CodecCfg----> Hal | + * | CodecCfg +---------> | | | | + * | | | | <-----Extra-----> | + * +----------+ | +---------+ | +-----------+ + * | | + * | | + * + + + * + * The function call flow is shown below: + * + * mpi mpp_enc controller hal + * + + + + + * | | | | + * | | | | + * +----------init------------> | | + * | | | | + * | | | | + * | PrepCfg | | | + * +---------control----------> PrepCfg | | + * | +-----control-----> | + * | | | PrepCfg | + * | +--------------------------control--------> + * | | | allocate + * | | | buffer + * | | | | + * | RcCfg | | | + * +---------control----------> RcCfg | | + * | +-----control-----> | + * | | rc_init | + * | | | | + * | | | | + * | CodecCfg | | | + * +---------control----------> | CodecCfg | + * | +--------------------------control--------> + * | | | generate + * | | | sps/pps + * | | | Get extra info | + * | +--------------------------control--------> + * | Get extra info | | | + * +---------control----------> | | + * | | | | + * | | | | + * | ROICfg | | | + * +---------control----------> | ROICfg | + * | +--------------------------control--------> + * | | | | + * | OSDCfg | | | + * +---------control----------> | OSDCfg | + * | +--------------------------control--------> + * | | | | + * | MDCfg | | | + * +---------control----------> | MDCfg | + * | +--------------------------control--------> + * | | | | + * | Set extra info | | | + * +---------control----------> | Set extra info | + * | +--------------------------control--------> + * | | | | + * | task | | | + * +----------encode----------> task | | + * | +-----encode------> | + * | | encode | + * | | | syntax | + * | +--------------------------gen_reg--------> + * | | | | + * | | | | + * | +---------------------------start---------> + * | | | | + * | | | | + * | +---------------------------wait----------> + * | | | | + * | | callback | | + * | +-----------------> | + * +--OSD-MD--encode----------> | | + * | . | | | + * | . | | | + * | . | | | + * +--OSD-MD--encode----------> | | + * | | | | + * +----------deinit----------> | | + * + + + + + */ + +/* + * encoder query interface is only for debug usage + */ +#define MPP_ENC_QUERY_STATUS (0x00000001) +#define MPP_ENC_QUERY_WAIT (0x00000002) +#define MPP_ENC_QUERY_FPS (0x00000004) +#define MPP_ENC_QUERY_BPS (0x00000008) +#define MPP_ENC_QUERY_ENC_IN_FRM (0x00000010) +#define MPP_ENC_QUERY_ENC_WORK (0x00000020) +#define MPP_ENC_QUERY_ENC_OUT_PKT (0x00000040) + +#define MPP_ENC_QUERY_ALL (MPP_ENC_QUERY_STATUS | \ + MPP_ENC_QUERY_WAIT | \ + MPP_ENC_QUERY_FPS | \ + MPP_ENC_QUERY_BPS | \ + MPP_ENC_QUERY_ENC_IN_FRM | \ + MPP_ENC_QUERY_ENC_WORK | \ + MPP_ENC_QUERY_ENC_OUT_PKT) + +typedef struct MppEncQueryCfg_t { + /* + * 32 bit query flag for query data check + * Each bit represent a query data switch. + * bit 0 - for querying encoder runtime status + * bit 1 - for querying encoder runtime waiting status + * bit 2 - for querying encoder realtime encode fps + * bit 3 - for querying encoder realtime output bps + * bit 4 - for querying encoder input frame count + * bit 5 - for querying encoder start hardware times + * bit 6 - for querying encoder output packet count + */ + RK_U32 query_flag; + + /* 64 bit query data output */ + RK_U32 rt_status; + RK_U32 rt_wait; + RK_U32 rt_fps; + RK_U32 rt_bps; + RK_U32 enc_in_frm_cnt; + RK_U32 enc_hw_run_cnt; + RK_U32 enc_out_pkt_cnt; +} MppEncQueryCfg; + +/* + * base working mode parameter + */ +typedef struct MppEncBaseCfg_t { + MppCodingType coding; + RK_S32 low_delay; + RK_S32 smart_en; + RK_S32 smt1_en; + RK_S32 smt3_en; +} MppEncBaseCfg; + +/* + * Rate control parameter + */ +typedef enum MppEncRcQuality_e { + MPP_ENC_RC_QUALITY_WORST, + MPP_ENC_RC_QUALITY_WORSE, + MPP_ENC_RC_QUALITY_MEDIUM, + MPP_ENC_RC_QUALITY_BETTER, + MPP_ENC_RC_QUALITY_BEST, + MPP_ENC_RC_QUALITY_CQP, + MPP_ENC_RC_QUALITY_AQ_ONLY, + MPP_ENC_RC_QUALITY_BUTT +} MppEncRcQuality; + +typedef struct MppEncRcCfg_t { + /* + * rc_mode - rate control mode + * + * mpp provide two rate control mode: + * + * Constant Bit Rate (CBR) mode + * - paramter 'bps*' define target bps + * - paramter quality and qp will not take effect + * + * Variable Bit Rate (VBR) mode + * - paramter 'quality' define 5 quality levels + * - paramter 'bps*' is used as reference but not strict condition + * - special Constant QP (CQP) mode is under VBR mode + * CQP mode will work with qp in CodecCfg. But only use for test + * + * default: CBR + */ + MppEncRcMode rc_mode; + + /* + * quality - quality parameter, only takes effect in VBR mode + * + * Mpp does not give the direct parameter in different protocol. + * + * Mpp provide total 5 quality level: + * Worst - worse - Medium - better - best + * + * extra CQP level means special constant-qp (CQP) mode + * + * default value: Medium + */ + MppEncRcQuality quality; + + /* + * bit rate parameters + * mpp gives three bit rate control parameter for control + * bps_target - target bit rate, unit: bit per second + * bps_max - maximun bit rate, unit: bit per second + * bps_min - minimun bit rate, unit: bit per second + * if user need constant bit rate set parameters to the similar value + * if user need variable bit rate set parameters as they need + */ + RK_S32 bps_target; + RK_S32 bps_max; + RK_S32 bps_min; + + /* + * frame rate parameters have great effect on rate control + * + * fps_in_flex + * 0 - fix input frame rate + * 1 - variable input frame rate + * + * fps_in_num + * input frame rate numerator, if 0 then default 30 + * + * fps_in_denom + * input frame rate denominator, if 0 then default 1 + * + * fps_out_flex + * 0 - fix output frame rate + * 1 - variable output frame rate + * + * fps_out_num + * output frame rate numerator, if 0 then default 30 + * + * fps_out_denom + * output frame rate denominator, if 0 then default 1 + */ + RK_S32 fps_in_flex; + RK_S32 fps_in_num; + RK_S32 fps_in_denom; + RK_S32 fps_out_flex; + RK_S32 fps_out_num; + RK_S32 fps_out_denom; + /* + * Whether to encoder IDR when fps_out is changed. + * 0 -- default value, SPS, PPS headers and IDR will be added. + * 1 -- only SPS, PPS headers is added. + */ + RK_S32 fps_chg_no_idr; + + /* + * gop - group of picture, gap between Intra frame + * 0 for only 1 I frame the rest are all P frames + * 1 for all I frame + * 2 for I P I P I P + * 3 for I P P I P P + * etc... + */ + RK_S32 gop; + /* internal gop mode: 0 - normal P; 1 - smart P */ + RK_S32 gop_mode; + void *ref_cfg; + + /* + * skip_cnt - max continuous frame skip count + * 0 - frame skip is not allow + */ + RK_S32 skip_cnt; + + /* + * max_reenc_times - max reencode time for one frame + * 0 - reencode is not allowed + * 1~3 max reencode time is limited to 3 + */ + RK_U32 max_reenc_times; + + /* + * stats_time - the time of bitrate statistics + */ + RK_S32 stats_time; + + /* + * drop frame parameters + * used on bitrate is far over the max bitrate + * + * drop_mode + * + * MPP_ENC_RC_DROP_FRM_DISABLED + * - do not drop frame when bitrate overflow. + * MPP_ENC_RC_DROP_FRM_NORMAL + * - do not encode the dropped frame when bitrate overflow. + * MPP_ENC_RC_DROP_FRM_PSKIP + * - encode a all skip frame when bitrate overflow. + * + * drop_threshold + * + * The percentage threshold over max_bitrate for trigger frame drop. + * + * drop_gap + * The max continuous frame drop number + */ + MppEncRcDropFrmMode drop_mode; + RK_U32 drop_threshold; + RK_U32 drop_gap; + + MppEncRcSuperFrameMode super_mode; + RK_U32 super_i_thd; + RK_U32 super_p_thd; + + MppEncRcPriority rc_priority; + + RK_U32 debreath_en; + RK_U32 debre_strength; + RK_S32 max_i_prop; + RK_S32 min_i_prop; + RK_S32 init_ip_ratio; + + /* general qp control */ + RK_S32 qp_init; + RK_S32 qp_max; + RK_S32 qp_max_i; + RK_S32 qp_min; + RK_S32 qp_min_i; + RK_S32 qp_max_step; /* delta qp between each two P frame */ + RK_S32 qp_delta_ip; /* delta qp between I and P */ + RK_S32 qp_delta_vi; /* delta qp between vi and P */ + RK_S32 fqp_min_i; + RK_S32 fqp_min_p; + RK_S32 fqp_max_i; + RK_S32 fqp_max_p; + RK_S32 mt_st_swth_frm_qp; + + RK_S32 hier_qp_en; + RK_S32 hier_qp_delta[4]; + RK_S32 hier_frame_num[4]; + + RK_U32 refresh_en; + MppEncRcRefreshMode refresh_mode; + RK_U32 refresh_num; + RK_S32 refresh_length; + RK_S32 inst_br_lvl; +} MppEncRcCfg; + +/* + * Hardware related rate control config + * + * This config will open some detail feature to external user to control + * hardware behavior directly. + */ +typedef struct MppEncHwCfg_t { + /* vepu541/vepu540 */ + RK_S32 qp_delta_row; /* delta qp between two row in P frame */ + RK_S32 qp_delta_row_i; /* delta qp between two row in I frame */ + RK_S32 qbias_i; + RK_S32 qbias_p; + RK_S32 qbias_en; + RK_S32 flt_str_i; + RK_S32 flt_str_p; + RK_U32 aq_thrd_i[16]; + RK_U32 aq_thrd_p[16]; + RK_S32 aq_step_i[16]; + RK_S32 aq_step_p[16]; + + /* vepu1/2 */ + RK_S32 mb_rc_disable; + + /* vepu580 */ + RK_S32 extra_buf; + + /* + * block mode decision bias config + * 0 - intra32x32 + * 1 - intra16x16 + * 2 - intra8x8 + * 3 - intra4x4 + * 4 - inter64x64 + * 5 - inter32x32 + * 6 - inter16x16 + * 7 - inter8x8 + * value range 0 ~ 15, default : 8 + * If the value is smaller then encoder will be more likely to encode corresponding block mode. + */ + RK_S32 mode_bias[8]; + + /* + * skip mode bias config + * skip_bias_en - enable flag for skip bias config + * skip_sad - sad threshold for skip / non-skip + * skip_bias - tendency for skip, value range 0 ~ 15, default : 8 + * If the value is smaller then encoder will be more likely to encode skip block. + */ + RK_S32 skip_bias_en; + RK_S32 skip_sad; + RK_S32 skip_bias; + + /* vepu500 + * 0-2: I frame thd; 3-6: I frame bias + * 7-9: P frame thd; 10-13: I block bias of P frame + * 14-17: P block bias of P frame + */ + RK_S32 qbias_arr[18]; + /* vepu500 + * 0: aq16_range; 1: aq32_range; 2: aq8_range + * 3: aq16_diff0; 4: aq16_diff1 + * 0 ~ 4 for I frame, 5 ~ 9 for P frame + */ + RK_S32 aq_rnge_arr[10]; +} MppEncHwCfg; + +/* + * Mpp preprocess parameter + */ +/* + * Preprocess sharpen parameter + * + * 5x5 sharpen core + * + * enable_y - enable luma sharpen + * enable_uv - enable chroma sharpen + */ +typedef struct { + RK_U32 enable_y; + RK_U32 enable_uv; + RK_S32 coef[5]; + RK_S32 div; + RK_S32 threshold; +} MppEncPrepSharpenCfg; + +/* + * input frame rotation parameter + * 0 - disable rotation + * 1 - 90 degree + * 2 - 180 degree + * 3 - 270 degree + */ +typedef enum MppEncRotationCfg_e { + MPP_ENC_ROT_0, + MPP_ENC_ROT_90, + MPP_ENC_ROT_180, + MPP_ENC_ROT_270, + MPP_ENC_ROT_BUTT +} MppEncRotationCfg; + +typedef struct MppEncPrepCfg_t { + /* + * Mpp encoder input data dimension config + * + * width / height / hor_stride / ver_stride / format + * These information will be used for buffer allocation and rc config init + * The output format is always YUV420. So if input is RGB then color + * conversion will be done internally + */ + /* width / height set - user set value */ + RK_S32 width_set; + RK_S32 height_set; + /* width / height - final value in bitstream */ + RK_S32 width; + RK_S32 height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_S32 max_width; + RK_S32 max_height; + + /* resolution change flag */ + RK_S32 change_res; + + /* + * Mpp encoder input/output color config + */ + MppFrameFormat format; + MppFrameColorSpace color; + MppFrameColorPrimaries colorprim; + MppFrameColorTransferCharacteristic colortrc; + MppFrameColorRange range; + MppFrameChromaFormat format_out; + MppFrameChromaDownSampleMode chroma_ds_mode; + MppFrameColorRange range_out; + RK_S32 fix_chroma_en; + RK_S32 fix_chroma_u; + RK_S32 fix_chroma_v; + + /* suffix ext means the user set config externally */ + MppEncRotationCfg rotation; + MppEncRotationCfg rotation_ext; + + /* + * input frame mirroring parameter + * 0 - disable mirroring + * 1 - horizontal mirroring + */ + RK_S32 mirroring; + RK_S32 mirroring_ext; + + /* + * input frame flip parameter + * 0 - disable flip + * 1 - flip, vertical mirror transformation + */ + RK_S32 flip; + + /* + * TODO: + */ + RK_S32 denoise; + + MppEncPrepSharpenCfg sharpen; +} MppEncPrepCfg; + +/* + * Mpp Motion Detection parameter + * + * Mpp can output Motion Detection infomation for each frame. + * If user euqueue a encode task with KEY_MOTION_INFO by following function + * then encoder will output Motion Detection information to the buffer. + * + * mpp_task_meta_set_buffer(task, KEY_MOTION_INFO, buffer); + * + * Motion Detection information will be organized in this way: + * 1. Each 16x16 block will have a 32 bit block information which contains + * 15 bit SAD(Sum of Abstract Difference value + * 9 bit signed horizontal motion vector + * 8 bit signed vertical motion vector + * 2. The sequence of MD information in the buffer is corresponding to the + * block position in the frame, left-to right, top-to-bottom. + * 3. If the width of the frame is not a multiple of 256 pixels (16 macro + * blocks), DMA would extend the frame to a multiple of 256 pixels and + * the extended blocks' MD information are 32'h0000_0000. + * 4. Buffer must be ion buffer and 1024 byte aligned. + */ +typedef struct MppEncMDBlkInfo_t { + RK_U32 sad : 15; /* bit 0~14 - SAD */ + RK_S32 mvx : 9; /* bit 15~23 - signed horizontal mv */ + RK_S32 mvy : 8; /* bit 24~31 - signed vertical mv */ +} MppEncMDBlkInfo; + +typedef enum MppEncHeaderMode_e { + /* default mode: attach vps/sps/pps only on first frame */ + MPP_ENC_HEADER_MODE_DEFAULT, + /* IDR mode: attach vps/sps/pps on each IDR frame */ + MPP_ENC_HEADER_MODE_EACH_IDR, + MPP_ENC_HEADER_MODE_BUTT, +} MppEncHeaderMode; + +typedef enum MppEncSeiMode_e { + MPP_ENC_SEI_MODE_DISABLE, /* default mode, SEI writing is disabled */ + MPP_ENC_SEI_MODE_ONE_SEQ, /* one sequence has only one SEI */ + MPP_ENC_SEI_MODE_ONE_FRAME /* one frame may have one SEI, if SEI info has changed */ +} MppEncSeiMode; + +/* + * Mpp codec parameter + * parameter is defined from here + */ +typedef struct MppEncVuiCfg_t { + RK_U32 change; + RK_S32 vui_en; + RK_S32 vui_aspect_ratio; + RK_S32 vui_sar_size; + RK_S32 full_range; + RK_S32 time_scale; +} MppEncVuiCfg; + +/* + * H.264 configurable parameter + */ +/* default H.264 hardware config */ +typedef struct MppEncH264HwCfg_t { + /* + * VEPU 1/2 : 2 + * others : 0 + */ + RK_U32 hw_poc_type; + /* + * VEPU 1/2 : fixed to 12 + * others : changeable, default 12 + */ + RK_U32 hw_log2_max_frame_num_minus4; + /* default 0, only RKVENC2 support split out */ + RK_U32 hw_split_out; +} MppEncH264HwCfg; + +typedef struct MppEncH264Cfg_t { + /* + * H.264 stream format + * 0 - H.264 Annex B: NAL unit starts with '00 00 00 01' + * 1 - Plain NAL units without startcode + */ + RK_S32 stream_type; + + /* + * H.264 codec syntax config + * + * do NOT setup the three option below unless you are familiar with encoder detail + * poc_type - picture order count type 0 ~ 2 + * log2_max_poc_lsb - used in sps with poc_type 0, + * log2_max_frame_num - used in sps + */ + RK_U32 poc_type; + RK_U32 log2_max_poc_lsb; + RK_U32 log2_max_frame_num; /* actually log2_max_frame_num_minus4 */ + RK_U32 gaps_not_allowed; + + MppEncH264HwCfg hw_cfg; + + /* + * H.264 profile_idc parameter + * 66 - Baseline profile + * 77 - Main profile + * 100 - High profile + */ + RK_S32 profile; + + /* + * H.264 level_idc parameter + * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps + * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps + * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps + * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps + * 50 / 51 / 52 - 4K@30fps + */ + RK_S32 level; + + /* + * H.264 entropy coding method + * 0 - CAVLC + * 1 - CABAC + * When CABAC is select cabac_init_idc can be range 0~2 + */ + RK_S32 entropy_coding_mode; + RK_S32 entropy_coding_mode_ex; + RK_S32 cabac_init_idc; + RK_S32 cabac_init_idc_ex; + + /* + * 8x8 intra prediction and 8x8 transform enable flag + * This flag can only be enable under High profile + * 0 : disable (BP/MP) + * 1 : enable (HP) + */ + RK_S32 transform8x8_mode; + RK_S32 transform8x8_mode_ex; + + /* + * 0 : disable + * 1 : enable + */ + RK_S32 constrained_intra_pred_mode; + + /* + * 0 : flat scaling list + * 1 : default scaling list for all cases + * 2 : customized scaling list (not supported) + */ + RK_S32 scaling_list_mode; + + /* + * chroma qp offset (-12 - 12) + */ + RK_S32 chroma_cb_qp_offset; + RK_S32 chroma_cr_qp_offset; + + /* + * H.264 deblock filter mode flag + * 0 : enable + * 1 : disable + * 2 : disable deblocking filter at slice boundaries + * + * deblock filter offset alpha (-6 - 6) + * deblock filter offset beta (-6 - 6) + */ + RK_S32 deblock_disable; + RK_S32 deblock_offset_alpha; + RK_S32 deblock_offset_beta; + + /* + * H.264 long term reference picture enable flag + * 0 - disable + * 1 - enable + */ + RK_S32 use_longterm; + + /* + * quality config + * qp_max - 8 ~ 51 + * qp_max_i - 10 ~ 40 + * qp_min - 8 ~ 48 + * qp_min_i - 10 ~ 40 + * qp_max_step - max delta qp step between two frames + */ + RK_S32 qp_init; + RK_S16 qp_max; + RK_S16 qp_max_i; + RK_S16 qp_min; + RK_S16 qp_min_i; + RK_S16 qp_max_step; + RK_S16 qp_delta_ip; + + /* + * intra fresh config + * + * intra_refresh_mode + * 0 - no intra refresh + * 1 - intra refresh by MB row + * 2 - intra refresh by MB column + * 3 - intra refresh by MB gap + * + * intra_refresh_arg + * mode 0 - no effect + * mode 1 - refresh MB row number + * mode 2 - refresh MB colmn number + * mode 3 - refresh MB gap count + */ + RK_S32 intra_refresh_mode; + RK_S32 intra_refresh_arg; + + /* extra mode config */ + RK_S32 max_ltr_frames; + RK_S32 max_tid; + RK_S32 prefix_mode; + RK_S32 base_layer_pid; + /* + * Mpp encoder constraint_set parameter + * Mpp encoder constraint_set controls constraint_setx_flag in AVC. + * Mpp encoder constraint_set uses type RK_U32 to store force_flag and constraint_force as followed. + * | 00 | force_flag | 00 | constraint_force | + * As for force_flag and constraint_force, only low 6 bits are valid, + * corresponding to constraint_setx_flag from 5 to 0. + * If force_flag bit is enabled, constraint_setx_flag will be set correspondingly. + * Otherwise, constraint_setx_flag will use default value. + */ + RK_U32 constraint_set; + + /* extra info */ + MppEncVuiCfg vui; +} MppEncH264Cfg; + +#define H265E_MAX_ROI_NUMBER 64 + +typedef struct H265eRect_t { + RK_S32 left; + RK_S32 right; + RK_S32 top; + RK_S32 bottom; +} H265eRect; + +typedef struct H265eRoi_Region_t { + RK_U8 level; + H265eRect rect; +} H265eRoiRegion; + +typedef struct H265eCtuQp_t { + /* the qp value using in ctu region */ + RK_U32 qp; + + /* + * define the ctu region + * method = H265E_METHOD_CUT_SIZE, the value of rect is in ctu size + * method = H264E_METHOD_COORDINATE,the value of rect is in coordinates + */ + H265eRect rect; +} H265eCtu; + +/* + * define the method when set CTU/ROI parameters + * this value is using by method in H265eCtuRegion or H265eRoi struct + */ +typedef enum { + H265E_METHOD_CTU_SIZE, + H264E_METHOD_COORDINATE, +} H265eCtuMethod; + +/* + * H.265 configurable parameter + */ +typedef struct MppEncH265SliceCfg_t { + /* default value: 0, means no slice split*/ + RK_U32 split_enable; + + /* 0: by bits number; 1: by lcu line number*/ + RK_U32 split_mode; + + /* + * when splitmode is 0, this value presents bits number, + * when splitmode is 1, this value presents lcu line number + */ + RK_U32 slice_size; + RK_U32 slice_out; +} MppEncH265SliceCfg; + +typedef struct MppEncH265CuCfg_t { + RK_U32 cu32x32_en; /*default: 1 */ + RK_U32 cu16x16_en; /*default: 1 */ + RK_U32 cu8x8_en; /*default: 1 */ + RK_U32 cu4x4_en; /*default: 1 */ + + // intra pred + RK_U32 constrained_intra_pred_flag; /*default: 0 */ + RK_U32 strong_intra_smoothing_enabled_flag; /*INTRA_SMOOTH*/ + RK_U32 pcm_enabled_flag; /*default: 0, enable ipcm*/ + RK_U32 pcm_loop_filter_disabled_flag; +} MppEncH265CuCfg; + +typedef struct MppEncH265DblkCfg_t { + RK_U32 slice_deblocking_filter_disabled_flag; /* default value: 0. {0,1} */ + RK_S32 slice_beta_offset_div2; /* default value: 0. [-6,+6] */ + RK_S32 slice_tc_offset_div2; /* default value: 0. [-6,+6] */ +} MppEncH265DblkCfg_t; + +typedef struct MppEncH265SaoCfg_t { + RK_U32 slice_sao_luma_disable; + RK_U32 slice_sao_chroma_disable; + RK_U32 sao_bit_ratio; +} MppEncH265SaoCfg; + +typedef struct MppEncH265TransCfg_t { + RK_U32 transquant_bypass_enabled_flag; + RK_U32 transform_skip_enabled_flag; + RK_U32 scaling_list_mode; /* default: 0 */ + RK_S32 cb_qp_offset; + RK_S32 cr_qp_offset; + RK_S32 diff_cu_qp_delta_depth; +} MppEncH265TransCfg; + +typedef struct MppEncH265MergeCfg_t { + RK_U32 max_mrg_cnd; + RK_U32 merge_up_flag; + RK_U32 merge_left_flag; +} MppEncH265MergesCfg; + +typedef struct MppEncH265EntropyCfg_t { + RK_U32 cabac_init_flag; /* default: 0 */ +} MppEncH265EntropyCfg; + +typedef struct MppEncH265Cfg_t { + /* H.265 codec syntax config */ + RK_S32 profile; + RK_S32 level; + RK_S32 tier; + + /* constraint intra prediction flag */ + RK_S32 const_intra_pred; + RK_S32 ctu_size; + RK_S32 max_cu_size; + RK_S32 tmvp_enable; + RK_S32 amp_enable; + RK_S32 wpp_enable; + RK_S32 merge_range; + RK_S32 sao_enable; + RK_U32 num_ref; + + /* quality config */ + RK_S32 intra_qp; + RK_U8 qpmax_map[8]; + RK_U8 qpmin_map[8]; + RK_S32 qpmap_mode; + + /* extra mode config */ + RK_S32 max_ltr_frames; + RK_S32 max_tid; + RK_S32 base_layer_pid; + + MppEncH265CuCfg cu_cfg; + MppEncH265SliceCfg slice_cfg; + MppEncH265EntropyCfg entropy_cfg; + MppEncH265TransCfg trans_cfg; + MppEncH265SaoCfg sao_cfg; + MppEncH265DblkCfg_t dblk_cfg; + MppEncH265MergesCfg merge_cfg; + RK_S32 auto_tile; + RK_U32 lpf_acs_sli_en; + RK_U32 lpf_acs_tile_disable; + + /* extra info */ + MppEncVuiCfg vui; +} MppEncH265Cfg; + +/* + * motion jpeg configurable parameter + */ +typedef enum MppEncJpegQpMode_e { + JPEG_QP_NA = 0, + JPEG_QUANT = 1, + JPEG_QFACTOR = 2, + JPEG_QTABLE = 3, +} MppEncJpegQpMode; + +typedef struct MppEncJpegCfg_t { + RK_S32 q_mode; + RK_S32 update; + + RK_S32 quant; + RK_S32 quant_ext; + /* + * quality factor config + * + * q_factor - 1 ~ 99 + * qf_max - 1 ~ 99 + * qf_min - 1 ~ 99 + * qtable_y: qtable for luma + * qtable_u: qtable for chroma + * qtable_v: default equal qtable_u + */ + RK_S32 q_factor; + RK_S32 q_factor_ext; + RK_S32 qf_max; + RK_S32 qf_max_ext; + RK_S32 qf_min; + RK_S32 qf_min_ext; + /* + * qtable_y: qtable for luma + * qtable_u: qtable for chroma u + * qtable_v: qtable for chroma v + * for most case u and v use the same table + */ + RK_U8 qtable_y[64]; + RK_U8 qtable_u[64]; + RK_U8 qtable_v[64]; +} MppEncJpegCfg; + +/* + * vp8 configurable parameter + */ +typedef struct MppEncVp8Cfg_t { + RK_S32 quant; + RK_S32 disable_ivf; +} MppEncVp8Cfg; + +typedef enum MppEncSliceSplit_e { + /* change on quant parameter */ + MPP_ENC_SPLIT_CFG_CHANGE_MODE = MPP_BIT(0), + MPP_ENC_SPLIT_CFG_CHANGE_ARG = MPP_BIT(1), + MPP_ENC_SPLIT_CFG_CHANGE_OUTPUT = MPP_BIT(2), + MPP_ENC_SPLIT_CFG_CHANGE_ALL = (0xFFFFFFFFU), +} MppEncSliceSplitChange; + +typedef enum MppEncSplitMode_e { + MPP_ENC_SPLIT_NONE, + MPP_ENC_SPLIT_BY_BYTE, + MPP_ENC_SPLIT_BY_CTU, + MPP_ENC_SPLIT_MODE_BUTT, +} MppEncSplitMode; + +typedef enum MppEncSplitOutMode_e { + MPP_ENC_SPLIT_OUT_LOWDELAY = MPP_BIT(0), + MPP_ENC_SPLIT_OUT_SEGMENT = MPP_BIT(1), +} MppEncSplitOutMode; + +typedef struct MppEncSliceSplit_t { + RK_U32 change; + /* + * slice split mode + * + * MPP_ENC_SPLIT_NONE - No slice is split + * MPP_ENC_SPLIT_BY_BYTE - Slice is split by byte number + * MPP_ENC_SPLIT_BY_CTU - Slice is split by macroblock / ctu number + */ + RK_U32 split_mode; + + /* + * slice split size parameter + * + * When split by byte number this value is the max byte number for each + * slice. + * When split by macroblock / ctu number this value is the MB/CTU number + * for each slice. + */ + RK_U32 split_arg; + + /* + * slice split output mode + * + * MPP_ENC_SPLIT_OUT_LOWDELAY + * - When enabled encoder will lowdelay output each slice in a single packet + * MPP_ENC_SPLIT_OUT_SEGMENT + * - When enabled encoder will packet with segment info for each slice + */ + RK_U32 split_out; +} MppEncSliceSplit; + +/** + * @brief Mpp ROI parameter + * Region configure define a rectangle as ROI + * @note x, y, w, h are calculated in pixels, which had better be 16-pixel aligned. + * These parameters MUST retain in memory when encoder is running. + * Both absolute qp and relative qp are supported in vepu541. + * Only absolute qp is supported in rv1108 + */ +typedef struct MppEncROIRegion_t { + RK_U16 x; /**< horizontal position of top left corner */ + RK_U16 y; /**< vertical position of top left corner */ + RK_U16 w; /**< width of ROI rectangle */ + RK_U16 h; /**< height of ROI rectangle */ + RK_U16 intra; /**< flag of forced intra macroblock */ + RK_S16 quality; /**< absolute / relative qp of macroblock */ + RK_U16 qp_area_idx; /**< qp min max area select*/ + RK_U8 area_map_en; /**< enable area map */ + RK_U8 abs_qp_en; /**< absolute qp enable flag*/ +} MppEncROIRegion; + +/** + * @brief MPP encoder's ROI configuration + */ +typedef struct MppEncROICfg_t { + RK_U32 number; /**< ROI rectangle number */ + MppEncROIRegion *regions; /**< ROI parameters */ +} MppEncROICfg; + +typedef struct MppEncROICfg0_t { + RK_U32 change; /**< change flag */ + RK_U32 number; /**< ROI rectangle number */ + MppEncROIRegion regions[8]; /**< ROI parameters */ +} MppEncROICfgLegacy; + +/** + * @brief Mpp ROI parameter for vepu54x / vepu58x + * @note These encoders have more complex roi configure structure. + * User need to generate roi structure data for different soc. + * And send buffers to encoder through metadata. + */ +typedef struct MppEncROICfg2_t { + MppBuffer base_cfg_buf; + MppBuffer qp_cfg_buf; + MppBuffer amv_cfg_buf; + MppBuffer mv_cfg_buf; + + RK_U32 roi_qp_en : 1; + RK_U32 roi_amv_en : 1; + RK_U32 roi_mv_en : 1; + RK_U32 reserve_bits : 29; + RK_U32 reserve[3]; +} MppEncROICfg2; + +typedef struct MppJpegROIRegion_t { + RK_U16 x; /* horizontal position of top left corner */ + RK_U16 y; /* vertical position of top left corner */ + RK_U16 w; /* width of ROI rectangle */ + RK_U16 h; /* height of ROI rectangle */ + RK_U8 level; /* the strength of erasing residuals for roi */ + RK_U8 roi_en; /* enable roi */ +} MppJpegROIRegion; + +typedef struct MppJpegROICfg_t { + RK_U32 change; + RK_U16 non_roi_level; /* the strength of erasing residuals for non-roi */ + RK_U16 non_roi_en; /* enable non-roi */ + MppJpegROIRegion regions[16]; +} MppJpegROICfg; + +/* + * Mpp OSD parameter + * + * Mpp OSD support total 8 regions + * Mpp OSD support 256-color palette two mode palette: + * 1. Configurable OSD palette + * When palette is set. + * 2. fixed OSD palette + * When palette is NULL. + * + * if MppEncOSDPlt.buf != NULL , palette includes maximun 256 levels, + * every level composed of 32 bits defined below: + * Y : 8 bits + * U : 8 bits + * V : 8 bits + * alpha : 8 bits + */ +#define MPP_ENC_OSD_PLT_WHITE ((255<<24)|(128<<16)|(128<<8)|235) +#define MPP_ENC_OSD_PLT_YELLOW ((255<<24)|(146<<16)|( 16<<8)|210) +#define MPP_ENC_OSD_PLT_CYAN ((255<<24)|( 16<<16)|(166<<8)|170) +#define MPP_ENC_OSD_PLT_GREEN ((255<<24)|( 34<<16)|( 54<<8)|145) +#define MPP_ENC_OSD_PLT_TRANS (( 0<<24)|(222<<16)|(202<<8)|106) +#define MPP_ENC_OSD_PLT_RED ((255<<24)|(240<<16)|( 90<<8)| 81) +#define MPP_ENC_OSD_PLT_BLUE ((255<<24)|(110<<16)|(240<<8)| 41) +#define MPP_ENC_OSD_PLT_BLACK ((255<<24)|(128<<16)|(128<<8)| 16) + +typedef enum MppEncOSDPltType_e { + MPP_ENC_OSD_PLT_TYPE_DEFAULT, + MPP_ENC_OSD_PLT_TYPE_USERDEF, + MPP_ENC_OSD_PLT_TYPE_BUTT, +} MppEncOSDPltType; + +/* OSD palette value define */ +typedef union MppEncOSDPltVal_u { + struct { + RK_U32 v : 8; + RK_U32 u : 8; + RK_U32 y : 8; + RK_U32 alpha : 8; + }; + RK_U32 val; +} MppEncOSDPltVal; + +typedef struct MppEncOSDPlt_t { + MppEncOSDPltVal data[256]; +} MppEncOSDPlt; + +typedef enum MppEncOSDPltCfgChange_e { + MPP_ENC_OSD_PLT_CFG_CHANGE_MODE = MPP_BIT(0), /* change osd plt type */ + MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL = MPP_BIT(1), /* change osd plt table value */ + MPP_ENC_OSD_PLT_CFG_CHANGE_ALL = (0xFFFFFFFFU), +} MppEncOSDPltCfgChange; + +typedef struct MppEncOSDPltCfg_t { + RK_U32 change; + MppEncOSDPltType type; + MppEncOSDPlt *plt; +} MppEncOSDPltCfg; + +/* position info is unit in 16 pixels(one MB), and + * x-directon range in pixels = (rd_pos_x - lt_pos_x + 1) * 16; + * y-directon range in pixels = (rd_pos_y - lt_pos_y + 1) * 16; + */ +typedef struct MppEncOSDRegion_t { + RK_U32 enable; + RK_U32 inverse; + RK_U32 start_mb_x; + RK_U32 start_mb_y; + RK_U32 num_mb_x; + RK_U32 num_mb_y; + RK_U32 buf_offset; +} MppEncOSDRegion; + +/* if num_region > 0 && region==NULL + * use old osd data + */ +typedef struct MppEncOSDData_t { + MppBuffer buf; + RK_U32 num_region; + MppEncOSDRegion region[8]; +} MppEncOSDData; + +typedef struct MppEncOSDRegion2_t { + RK_U32 enable; + RK_U32 inverse; + RK_U32 start_mb_x; + RK_U32 start_mb_y; + RK_U32 num_mb_x; + RK_U32 num_mb_y; + RK_U32 buf_offset; + MppBuffer buf; +} MppEncOSDRegion2; + +typedef struct MppEncOSDData2_t { + RK_U32 num_region; + MppEncOSDRegion2 region[8]; +} MppEncOSDData2; + +/* kmpp osd configure */ +typedef struct EncOSDInvCfg_t { + RK_U32 yg_inv_en; + RK_U32 uvrb_inv_en; + RK_U32 alpha_inv_en; + RK_U32 inv_sel; + RK_U32 uv_sw_inv_en; + RK_U32 inv_size; + RK_U32 inv_stride; + KmppShmPtr inv_buf; +} EncOSDInvCfg; + +typedef struct EncOSDAlphaCfg_t { + RK_U32 alpha_swap; + RK_U32 bg_alpha; + RK_U32 fg_alpha; + RK_U32 fg_alpha_sel; +} EncOSDAlphaCfg; + +typedef struct EncOSDQpCfg_t { + RK_U32 qp_adj_en; + RK_U32 qp_adj_sel; + RK_S32 qp; + RK_U32 qp_max; + RK_U32 qp_min; + RK_U32 qp_prj; +} EncOSDQpCfg; + +typedef struct MppEncOSDRegion3_t { + RK_U32 enable; + RK_U32 range_trns_en; + RK_U32 range_trns_sel; + RK_U32 fmt; + RK_U32 rbuv_swap; + RK_U32 lt_x; + RK_U32 lt_y; + RK_U32 rb_x; + RK_U32 rb_y; + RK_U32 stride; + RK_U32 ch_ds_mode; + RK_U32 osd_endn; + EncOSDInvCfg inv_cfg; + EncOSDAlphaCfg alpha_cfg; + EncOSDQpCfg qp_cfg; + KmppShmPtr osd_buf; + RK_U8 lut[8]; //vuy vuy alpha +} MppEncOSDRegion3; + +typedef struct MppEncOSDData3_t { + RK_U32 change; + RK_U32 num_region; + MppEncOSDRegion3 region[8]; +} MppEncOSDData3; +/* kmpp osd configure end */ + +typedef struct MppEncUserData_t { + RK_U32 len; + void *pdata; +} MppEncUserData; + +typedef struct MppEncUserDataFull_t { + RK_U32 len; + RK_U8 *uuid; + void *pdata; +} MppEncUserDataFull; + +typedef struct MppEncUserDataSet_t { + RK_U32 count; + MppEncUserDataFull *datas; +} MppEncUserDataSet; + +typedef enum MppEncSceneMode_e { + MPP_ENC_SCENE_MODE_DEFAULT, + MPP_ENC_SCENE_MODE_IPC, + MPP_ENC_SCENE_MODE_IPC_PTZ, + MPP_ENC_SCENE_MODE_BUTT, +} MppEncSceneMode; + +typedef struct MppEncFineTuneCfg_t { + MppEncSceneMode scene_mode; + MppEncSeMode se_mode; + RK_S32 deblur_en; /* qpmap_en */ + RK_S32 deblur_str; /* deblur strength */ + RK_S32 anti_flicker_str; + RK_S32 lambda_idx_i; + RK_S32 lambda_idx_p; + RK_S32 atr_str_i; /* line_en */ + RK_S32 atr_str_p; /* line_en */ + RK_S32 atl_str; /* anti_stripe */ + RK_S32 sao_str_i; /* anti blur */ + RK_S32 sao_str_p; /* anti blur */ + RK_S32 rc_container; + RK_S32 vmaf_opt; + + RK_S32 motion_static_switch_enable; + RK_S32 atf_str; + /* vepu500 only */ + RK_S32 lgt_chg_lvl; /* light change level, [0, 3] */ + RK_S32 static_frm_num; /* static frame number, [0, 7] */ + RK_S32 madp16_th; /* madp threshold for static block detection, [0, 63] */ + RK_S32 skip16_wgt; /* weight for skip16, 0 or [3, 8] */ + RK_S32 skip32_wgt; /* weight for skip32, 0 or [3, 8] */ + RK_S32 qpmap_en; + RK_S32 speed; /* encoder speed [0..3], 0:normal; 1:fast; 2:faster; 3:fastest */ + + /* smart v3 only */ + RK_S32 bg_delta_qp_i; /* background delta qp for i frame */ + RK_S32 bg_delta_qp_p; /* background delta qp for p frame */ + RK_S32 fg_delta_qp_i; /* foreground delta qp for i frame */ + RK_S32 fg_delta_qp_p; /* foreground delta qp for p frame */ + RK_S32 bmap_qpmin_i; /* min qp for i frame in bmap */ + RK_S32 bmap_qpmin_p; /* min qp for p frame in bmap */ + RK_S32 bmap_qpmax_i; /* max qp for i frame in bmap */ + RK_S32 bmap_qpmax_p; /* max qp for p frame in bmap */ + RK_S32 min_bg_fqp; /* min frame qp for background region */ + RK_S32 max_bg_fqp; /* max frame qp for background region */ + RK_S32 min_fg_fqp; /* min frame qp for foreground region */ + RK_S32 max_fg_fqp; /* max frame qp for foreground region */ + RK_S32 fg_area; /* foreground area, [-1, 100] */ +} MppEncFineTuneCfg; + +#endif /* RK_VENC_CMD_H */ diff --git a/inc/rk_venc_kcfg.h b/inc/rk_venc_kcfg.h new file mode 100644 index 000000000..b13bf57fb --- /dev/null +++ b/inc/rk_venc_kcfg.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef RK_VENC_KCFG_H +#define RK_VENC_KCFG_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef void* MppVencKcfg; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MPP_VENC_KCFG_TYPE_INIT, + MPP_VENC_KCFG_TYPE_DEINIT, + MPP_VENC_KCFG_TYPE_RESET, + MPP_VENC_KCFG_TYPE_START, + MPP_VENC_KCFG_TYPE_STOP, + MPP_VENC_KCFG_TYPE_ST_CFG, + MPP_VENC_KCFG_TYPE_BUTT, +} MppVencKcfgType; + +MPP_RET mpp_venc_kcfg_init(MppVencKcfg *cfg, MppVencKcfgType type); +MPP_RET mpp_venc_kcfg_init_by_name(MppVencKcfg *cfg, const char *name); +MPP_RET mpp_venc_kcfg_deinit(MppVencKcfg cfg); + +MPP_RET mpp_venc_kcfg_set_s8(MppVencKcfg cfg, const char *name, RK_S8 val); +MPP_RET mpp_venc_kcfg_set_u8(MppVencKcfg cfg, const char *name, RK_U8 val); +MPP_RET mpp_venc_kcfg_set_s16(MppVencKcfg cfg, const char *name, RK_S16 val); +MPP_RET mpp_venc_kcfg_set_u16(MppVencKcfg cfg, const char *name, RK_U16 val); +MPP_RET mpp_venc_kcfg_set_s32(MppVencKcfg cfg, const char *name, RK_S32 val); +MPP_RET mpp_venc_kcfg_set_u32(MppVencKcfg cfg, const char *name, RK_U32 val); +MPP_RET mpp_venc_kcfg_set_s64(MppVencKcfg cfg, const char *name, RK_S64 val); +MPP_RET mpp_venc_kcfg_set_u64(MppVencKcfg cfg, const char *name, RK_U64 val); +MPP_RET mpp_venc_kcfg_set_ptr(MppVencKcfg cfg, const char *name, void *val); +MPP_RET mpp_venc_kcfg_set_st(MppVencKcfg cfg, const char *name, void *val); + +MPP_RET mpp_venc_kcfg_get_s8(MppVencKcfg cfg, const char *name, RK_S8 *val); +MPP_RET mpp_venc_kcfg_get_u8(MppVencKcfg cfg, const char *name, RK_U8 *val); +MPP_RET mpp_venc_kcfg_get_s16(MppVencKcfg cfg, const char *name, RK_S16 *val); +MPP_RET mpp_venc_kcfg_get_u16(MppVencKcfg cfg, const char *name, RK_U16 *val); +MPP_RET mpp_venc_kcfg_get_s32(MppVencKcfg cfg, const char *name, RK_S32 *val); +MPP_RET mpp_venc_kcfg_get_u32(MppVencKcfg cfg, const char *name, RK_U32 *val); +MPP_RET mpp_venc_kcfg_get_s64(MppVencKcfg cfg, const char *name, RK_S64 *val); +MPP_RET mpp_venc_kcfg_get_u64(MppVencKcfg cfg, const char *name, RK_U64 *val); +MPP_RET mpp_venc_kcfg_get_ptr(MppVencKcfg cfg, const char *name, void **val); +MPP_RET mpp_venc_kcfg_get_st(MppVencKcfg cfg, const char *name, void *val); + +void mpp_venc_kcfg_show(MppVencKcfg cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* RK_VENC_KCFG_H */ diff --git a/inc/rk_venc_rc.h b/inc/rk_venc_rc.h new file mode 100644 index 000000000..c884bcb29 --- /dev/null +++ b/inc/rk_venc_rc.h @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RK_VENC_RC_H +#define RK_VENC_RC_H + +#include "rk_type.h" + +#define MPP_ENC_MIN_BPS (SZ_1K) +#define MPP_ENC_MAX_BPS (SZ_1M * 200) + +/* Rate control parameter */ +typedef enum MppEncRcMode_e { + MPP_ENC_RC_MODE_VBR, + MPP_ENC_RC_MODE_CBR, + MPP_ENC_RC_MODE_FIXQP, + MPP_ENC_RC_MODE_AVBR, + MPP_ENC_RC_MODE_SMTRC, + MPP_ENC_RC_MODE_SE, + MPP_ENC_RC_MODE_BUTT +} MppEncRcMode; + +typedef enum MppEncSeMode_e { + MPP_ENC_SE_DISABLE = 0, // disable super encoder + MPP_ENC_SE_MODE_BAL, // balance mode + MPP_ENC_SE_MODE_QF, // quality first mode + MPP_ENC_SE_MODE_BF, // bitrate first mode + MPP_ENC_SE_MODE_EXTERNAL, // external se mode + MPP_ENC_SE_MODE_BUTT +} MppEncSeMode; + +typedef enum MppEncRcPriority_e { + MPP_ENC_RC_BY_BITRATE_FIRST, + MPP_ENC_RC_BY_FRM_SIZE_FIRST, + MPP_ENC_RC_PRIORITY_BUTT +} MppEncRcPriority; + +typedef enum MppEncRcDropFrmMode_e { + MPP_ENC_RC_DROP_FRM_DISABLED, + MPP_ENC_RC_DROP_FRM_NORMAL, + MPP_ENC_RC_DROP_FRM_PSKIP, + MPP_ENC_RC_DROP_FRM_BUTT +} MppEncRcDropFrmMode; + +typedef enum MppEncRcSuperFrameMode_t { + MPP_ENC_RC_SUPER_FRM_NONE, + MPP_ENC_RC_SUPER_FRM_DROP, + MPP_ENC_RC_SUPER_FRM_REENC, + MPP_ENC_RC_SUPER_FRM_BUTT +} MppEncRcSuperFrameMode; + +typedef enum MppEncRcGopMode_e { + MPP_ENC_RC_NORMAL_P, + MPP_ENC_RC_SMART_P, + MPP_ENC_RC_GOP_MODE_BUTT, +} MppEncRcGopMode; + +typedef enum MppEncRcIntraRefreshMode_e { + MPP_ENC_RC_INTRA_REFRESH_ROW = 0, + MPP_ENC_RC_INTRA_REFRESH_COL, + MPP_ENC_RC_INTRA_REFRESH_BUTT +} MppEncRcRefreshMode; + +#endif /* RK_VENC_RC_H */ diff --git a/inc/rk_venc_ref.h b/inc/rk_venc_ref.h new file mode 100644 index 000000000..04edc6a69 --- /dev/null +++ b/inc/rk_venc_ref.h @@ -0,0 +1,265 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RK_VENC_REF_H +#define RK_VENC_REF_H + +#include "rk_type.h" +#include "mpp_err.h" + +/* + * MPP reference management system follows the model of H.264/H.265 reference + * frame mangement. + * + * The reference frame is defined into two type: long-term reference frame and + * short-refernce frame (lt_ref and st_ref). + * + * The lt_ref can be only indexed by long-term reference frame index (lt_idx). + * The st_ref can be indexed by its temporal id (tid) and previous count. + * + * MppEncRefMode defined the way for user to reference the required frame. + * + * Normal reference mode without argument + * REF_TO_PREV_REF_FRM - refer to previous reference frame in encode order (No matter Lt or St) + * REF_TO_PREV_ST_REF - refer to previous short-term reference frame + * REF_TO_PREV_LT_REF - refer to previous long-term reference frame + * REF_TO_PREV_INTRA - refer to previous Intra / IDR frame + * REF_TO_ST_REF_SETUP - refer to refernce frame defined in StRefSetup + * + * Normal reference mode with argument + * REF_TO_TEMPORAL_LAYER - refer to previous reference frame with temporal id argument + * REF_TO_LT_REF_IDX - refer to long-term reference frame with lt_ref_idx argument + * REF_TO_ST_PREV_N_REF - refer to short-term reference frame with diff frame_num argument + * + * Long-term reference only mode + * REF_TO_ST_REF_SETUP - use corresponding mode of original short-term reference frame + * + * Short-term reference only mode + * REF_TO_LT_REF_SETUP - indicate that this frame will be overwrited by long-term config + * + * By combining frames with these modes user can define many kinds of reference hierarchy + * structure. But normally user should use simplified preset hierarchy pattern. + * + * The rules for virtual cpb management is similiar to H.264/H.265 + * 1. When one frame is marked as long-term reference frame it will be kept in cpb until + * it is replaced by other frame with the same lt_idx or IDR frame. + * 2. When one frame is marked as short-term reference frame it will be inert into cpb when + * there is enough storage space. When the number of total sum of long-term and short-term + * reference frame excess the cpb size limit the oldest short-term frame will be removed. + * This is call sliding window in H.264. + */ + +/* max 4 temporal layer */ +#define MPP_ENC_MAX_TEMPORAL_LAYER_NUM 4 +/* max 4 long-term reference frame */ +#define MPP_ENC_MAX_LT_REF_NUM 16 + +/* + * Group Of Picture (GOP) config is separated into three parts: + * + * 1. Intra / IDR frame config + * igop - the interval of two intra / IDR frames + * + * 2. Long-term reference config (MppEncRefLtFrmCfg) + * + * Setup long-term reference index max lt_idx, loop interval and reference + * mode for auto long-term reference frame generation. The encoder will + * mark frame to be long-term reference frame with given interval. + * + * 2.1 lt_idx + * The long-term reference frame index is unique identifier for a long-term + * reference frame. + * The max long-term reference frame index should NOT larger than + * max_num_ref_frames in sps. + * + * 2.2 lt_gap + * When lt_gap is zero the long-term reference frame generation is disabled. + * When lt_gap is non-zero (usually 2~3 second interval) then the long-term + * reference frame will be generated for error recovery or smart hierarchy. + * + * 2.2 lt_delay + * The lt_delay is the delay time for generation of long-term reference frame. + * The start point of lt_delay is the IDR/intra frame genertaed by igop. + * + * 2.4 ref_mode: Long-term refernce frame reference mode + * NOTE: temporal id of longterm reference frame is always zero. + * + * Examples: + * Sequence has only one lt_ref 0 and setup one long-term reference frame + * every 300 frame. + * { + * .lt_idx = 0, + * .lt_gap = 300, + * .lt_delay = 0, + * } + * result: + * frame 0 ...... 299 300 301 ...... 599 600 601 + * lt_idx 0 xxxxxx x 0 x xxxxxx x 0 x + * + * Sequence has lt_ref from 0 to 2 and setup a long-term reference frame + * every 100 frame. + * { + * .lt_idx = 0, + * .lt_gap = 300, + * .lt_delay = 0, + * } + * { + * .lt_idx = 1, + * .lt_gap = 300, + * .lt_delay = 100, + * } + * { + * .lt_idx = 2, + * .lt_gap = 300, + * .lt_delay = 200, + * } + * result: + * frame 0 ... 99 100 101 ... 199 200 201 ... 299 300 301 + * lt_idx 0 xxx x 1 x xxx x 2 x xxx x 0 x + * + * 3. Short-term reference config (MppEncStRefSetup) + * + * 3.1 is_non_ref + * The is_non_ref indicated the current frame is reference frame or not. + * + * 3.2 temporal_id + * The temporal id of the current frame configure. + * + * 3.3 ref_mode: short-term refernce frame reference mode + * + * 3.4 repeat + * The repeat time of the short-term reference frame configure. + * The overall frame count with the same config is repeat + 1. + * + * Examples: + * + */ + +#define REF_MODE_MODE_MASK (0x1F) +#define REF_MODE_ARG_MASK (0xFFFF0000) + +typedef enum MppEncRefMode_e { + /* max 32 mode in 32-bit */ + /* for default ref global config */ + REF_TO_PREV_REF_FRM, + REF_TO_PREV_ST_REF, + REF_TO_PREV_LT_REF, + REF_TO_PREV_INTRA, + + /* for global config with args */ + REF_MODE_GLOBAL_WITH_ARG = 0x4, + /* with ref arg as temporal layer id */ + REF_TO_TEMPORAL_LAYER = REF_MODE_GLOBAL_WITH_ARG, + /* with ref arg as long-term reference picture index */ + REF_TO_LT_REF_IDX, + /* with ref arg as short-term reference picture difference frame_num */ + REF_TO_ST_PREV_N_REF, + REF_MODE_GLOBAL_BUTT, + + /* for lt-ref */ + REF_MODE_LT = 0x18, + REF_TO_ST_REF_SETUP, + REF_MODE_LT_BUTT, + + /* for st-ref */ + REF_MODE_ST = 0x1C, + REF_TO_LT_REF_SETUP, + REF_MODE_ST_BUTT, +} MppEncRefMode; + +typedef struct MppEncRefLtFrmCfg_t { + RK_S32 lt_idx; /* lt_idx of the reference frame */ + RK_S32 temporal_id; /* temporal_id of the reference frame */ + MppEncRefMode ref_mode; + RK_S32 ref_arg; + RK_S32 lt_gap; /* gap between two lt-ref with same lt_idx */ + RK_S32 lt_delay; /* delay offset to igop start frame */ +} MppEncRefLtFrmCfg; + +typedef struct MppEncRefStFrmCfg_t { + RK_S32 is_non_ref; + RK_S32 temporal_id; + MppEncRefMode ref_mode; + RK_S32 ref_arg; + RK_S32 repeat; /* repeat times */ +} MppEncRefStFrmCfg; + +typedef struct MppEncRefPreset_t { + /* input parameter for query */ + const char *name; + RK_S32 max_lt_cnt; + RK_S32 max_st_cnt; + MppEncRefLtFrmCfg *lt_cfg; + MppEncRefStFrmCfg *st_cfg; + + /* output parameter */ + RK_S32 lt_cnt; + RK_S32 st_cnt; +} MppEncRefPreset; + +typedef void* MppEncRefCfg; + +/* for kmpp enc ref cfg */ +typedef enum MppEncRefCfgMode_e { + REF_IPPP, + REF_TSVC1, + REF_TSVC2, + REF_TSVC3, + REF_VI, + REF_HIR_SKIP, + REF_BUTT, +} MppEncRefCfgMode; + +typedef struct MppEncRefParam_t { + MppEncRefCfgMode cfg_mode; + + RK_S32 gop_len; + /*used for smartp ref*/ + RK_S32 vi_len; + + /*used for skip reg*/ + RK_U32 base_N; + RK_U32 enh_M; + RK_U32 pre_en; +} MppEncRefParam; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_enc_ref_cfg_init(MppEncRefCfg *ref); +MPP_RET mpp_enc_ref_cfg_deinit(MppEncRefCfg *ref); + +MPP_RET mpp_enc_ref_cfg_reset(MppEncRefCfg ref); +MPP_RET mpp_enc_ref_cfg_set_cfg_cnt(MppEncRefCfg ref, RK_S32 lt_cnt, RK_S32 st_cnt); +MPP_RET mpp_enc_ref_cfg_add_lt_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefLtFrmCfg *frm); +MPP_RET mpp_enc_ref_cfg_add_st_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefStFrmCfg *frm); +MPP_RET mpp_enc_ref_cfg_check(MppEncRefCfg ref); + +/* + * A new reference configure will restart a new gop and clear cpb by default. + * The keep cpb function will let encoder keeps the current cpb status and do NOT + * reset all the reference frame in cpb. + */ +MPP_RET mpp_enc_ref_cfg_set_keep_cpb(MppEncRefCfg ref, RK_S32 keep); +MPP_RET mpp_enc_ref_cfg_get_preset(MppEncRefPreset *preset); +MPP_RET mpp_enc_ref_cfg_show(MppEncRefCfg ref); + +#ifdef __cplusplus +} +#endif + +#endif /* RK_VENC_REF_H */ diff --git a/inc/vpu.h b/inc/vpu.h index ead20e916..6815e8e93 100644 --- a/inc/vpu.h +++ b/inc/vpu.h @@ -1,126 +1,123 @@ -/* - * - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VPU_H__ -#define __VPU_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "rk_type.h" - -#define VPU_SUCCESS (0) -#define VPU_FAILURE (-1) - -#define VPU_HW_WAIT_OK VPU_SUCCESS -#define VPU_HW_WAIT_ERROR VPU_FAILURE -#define VPU_HW_WAIT_TIMEOUT 1 - -// vpu decoder 60 registers, size 240B -#define VPU_REG_NUM_DEC (60) -// vpu post processor 41 registers, size 164B -#define VPU_REG_NUM_PP (41) -// vpu decoder + post processor 101 registers, size 404B -#define VPU_REG_NUM_DEC_PP (VPU_REG_NUM_DEC+VPU_REG_NUM_PP) -// vpu encoder 96 registers, size 384B -#define VPU_REG_NUM_ENC (96) - -typedef enum { - - VPU_ENC = 0x0, - VPU_DEC = 0x1, - VPU_PP = 0x2, - VPU_DEC_PP = 0x3, - VPU_DEC_HEVC = 0x4, - VPU_TYPE_BUTT , - -} VPU_CLIENT_TYPE; - -/* Hardware decoder configuration description */ - -typedef struct VPUHwDecConfig { - RK_U32 maxDecPicWidth; /* Maximum video decoding width supported */ - RK_U32 maxPpOutPicWidth; /* Maximum output width of Post-Processor */ - RK_U32 h264Support; /* HW supports h.264 */ - RK_U32 jpegSupport; /* HW supports JPEG */ - RK_U32 mpeg4Support; /* HW supports MPEG-4 */ - RK_U32 customMpeg4Support; /* HW supports custom MPEG-4 features */ - RK_U32 vc1Support; /* HW supports VC-1 Simple */ - RK_U32 mpeg2Support; /* HW supports MPEG-2 */ - RK_U32 ppSupport; /* HW supports post-processor */ - RK_U32 ppConfig; /* HW post-processor functions bitmask */ - RK_U32 sorensonSparkSupport; /* HW supports Sorenson Spark */ - RK_U32 refBufSupport; /* HW supports reference picture buffering */ - RK_U32 vp6Support; /* HW supports VP6 */ - RK_U32 vp7Support; /* HW supports VP7 */ - RK_U32 vp8Support; /* HW supports VP8 */ - RK_U32 avsSupport; /* HW supports AVS */ - RK_U32 jpegESupport; /* HW supports JPEG extensions */ - RK_U32 rvSupport; /* HW supports REAL */ - RK_U32 mvcSupport; /* HW supports H264 MVC extension */ -} VPUHwDecConfig_t; - -/* Hardware encoder configuration description */ - -typedef struct VPUHwEndConfig { - RK_U32 maxEncodedWidth; /* Maximum supported width for video encoding (not JPEG) */ - RK_U32 h264Enabled; /* HW supports H.264 */ - RK_U32 jpegEnabled; /* HW supports JPEG */ - RK_U32 mpeg4Enabled; /* HW supports MPEG-4 */ - RK_U32 vsEnabled; /* HW supports video stabilization */ - RK_U32 rgbEnabled; /* HW supports RGB input */ - RK_U32 reg_size; /* HW bus type in use */ - RK_U32 reserv[2]; -} VPUHwEncConfig_t; - -typedef enum { - - // common command - VPU_CMD_REGISTER , - VPU_CMD_REGISTER_ACK_OK , - VPU_CMD_REGISTER_ACK_FAIL , - VPU_CMD_UNREGISTER , - - VPU_SEND_CONFIG , - VPU_SEND_CONFIG_ACK_OK , - VPU_SEND_CONFIG_ACK_FAIL , - - VPU_GET_HW_INFO , - VPU_GET_HW_INFO_ACK_OK , - VPU_GET_HW_INFO_ACK_FAIL , - - VPU_CMD_BUTT , -} VPU_CMD_TYPE; - -int VPUClientInit(VPU_CLIENT_TYPE type); -RK_S32 VPUClientRelease(int socket); -RK_S32 VPUClientSendReg(int socket, RK_U32 *regs, RK_U32 nregs); -RK_S32 VPUClientWaitResult(int socket, RK_U32 *regs, RK_U32 nregs, VPU_CMD_TYPE *cmd, RK_S32 *len); -RK_S32 VPUClientGetHwCfg(int socket, RK_U32 *cfg, RK_U32 cfg_size); -RK_S32 VPUClientGetIOMMUStatus(); -RK_U32 VPUCheckSupportWidth(); - -#ifdef __cplusplus -} - -#endif - -#endif /* __VPU_H__ */ - - +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VPU_H +#define VPU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "rk_type.h" + +#define VPU_SUCCESS (0) +#define VPU_FAILURE (-1) + +#define VPU_HW_WAIT_OK VPU_SUCCESS +#define VPU_HW_WAIT_ERROR VPU_FAILURE +#define VPU_HW_WAIT_TIMEOUT 1 + +// vpu decoder 60 registers, size 240B +#define VPU_REG_NUM_DEC (60) +// vpu post processor 41 registers, size 164B +#define VPU_REG_NUM_PP (41) +// vpu decoder + post processor 101 registers, size 404B +#define VPU_REG_NUM_DEC_PP (VPU_REG_NUM_DEC+VPU_REG_NUM_PP) +// vpu encoder 96 registers, size 384B +#define VPU_REG_NUM_ENC (96) + +typedef enum { + VPU_ENC = 0x0, + VPU_DEC = 0x1, + VPU_PP = 0x2, + VPU_DEC_PP = 0x3, + VPU_DEC_HEVC = 0x4, + VPU_DEC_RKV = 0x5, + VPU_ENC_RKV = 0x6, + VPU_DEC_AVSPLUS = 0x7, + VPU_ENC_VEPU22 = 0x8, + VPU_TYPE_BUTT , +} VPU_CLIENT_TYPE; + +/* Hardware decoder configuration description */ + +typedef struct VPUHwDecConfig { + RK_U32 maxDecPicWidth; /* Maximum video decoding width supported */ + RK_U32 maxPpOutPicWidth; /* Maximum output width of Post-Processor */ + RK_U32 h264Support; /* HW supports h.264 */ + RK_U32 jpegSupport; /* HW supports JPEG */ + RK_U32 mpeg4Support; /* HW supports MPEG-4 */ + RK_U32 customMpeg4Support; /* HW supports custom MPEG-4 features */ + RK_U32 vc1Support; /* HW supports VC-1 Simple */ + RK_U32 mpeg2Support; /* HW supports MPEG-2 */ + RK_U32 ppSupport; /* HW supports post-processor */ + RK_U32 ppConfig; /* HW post-processor functions bitmask */ + RK_U32 sorensonSparkSupport; /* HW supports Sorenson Spark */ + RK_U32 refBufSupport; /* HW supports reference picture buffering */ + RK_U32 vp6Support; /* HW supports VP6 */ + RK_U32 vp7Support; /* HW supports VP7 */ + RK_U32 vp8Support; /* HW supports VP8 */ + RK_U32 avsSupport; /* HW supports AVS */ + RK_U32 jpegESupport; /* HW supports JPEG extensions */ + RK_U32 rvSupport; /* HW supports REAL */ + RK_U32 mvcSupport; /* HW supports H264 MVC extension */ +} VPUHwDecConfig_t; + +/* Hardware encoder configuration description */ + +typedef struct VPUHwEndConfig { + RK_U32 maxEncodedWidth; /* Maximum supported width for video encoding (not JPEG) */ + RK_U32 h264Enabled; /* HW supports H.264 */ + RK_U32 jpegEnabled; /* HW supports JPEG */ + RK_U32 mpeg4Enabled; /* HW supports MPEG-4 */ + RK_U32 vsEnabled; /* HW supports video stabilization */ + RK_U32 rgbEnabled; /* HW supports RGB input */ + RK_U32 reg_size; /* HW bus type in use */ + RK_U32 reserv[2]; +} VPUHwEncConfig_t; + +typedef enum { + // common command + VPU_CMD_REGISTER , + VPU_CMD_REGISTER_ACK_OK , + VPU_CMD_REGISTER_ACK_FAIL , + VPU_CMD_UNREGISTER , + + VPU_SEND_CONFIG , + VPU_SEND_CONFIG_ACK_OK , + VPU_SEND_CONFIG_ACK_FAIL , + + VPU_GET_HW_INFO , + VPU_GET_HW_INFO_ACK_OK , + VPU_GET_HW_INFO_ACK_FAIL , + + VPU_CMD_BUTT , +} VPU_CMD_TYPE; + +int VPUClientInit(VPU_CLIENT_TYPE type); +RK_S32 VPUClientRelease(int socket); +RK_S32 VPUClientSendReg(int socket, RK_U32 *regs, RK_U32 nregs); +RK_S32 VPUClientSendReg2(RK_S32 socket, RK_S32 offset, RK_S32 size, void *param); +RK_S32 VPUClientWaitResult(int socket, RK_U32 *regs, RK_U32 nregs, VPU_CMD_TYPE *cmd, RK_S32 *len); +RK_S32 VPUClientGetHwCfg(int socket, RK_U32 *cfg, RK_U32 cfg_size); +RK_S32 VPUClientGetIOMMUStatus(void); +RK_U32 VPUCheckSupportWidth(void); + +#ifdef __cplusplus +} +#endif + +#endif /* VPU_H */ diff --git a/inc/vpu_api.h b/inc/vpu_api.h index fa0d46696..13b92ba62 100644 --- a/inc/vpu_api.h +++ b/inc/vpu_api.h @@ -1,357 +1,520 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VPU_API_LEGACY_H__ -#define __VPU_API_LEGACY_H__ - -#include "rk_type.h" -#include "mpp_err.h" - -#define VPU_API_NOPTS_VALUE (0x8000000000000000LL) - -/* - * bit definition of ColorType in structure VPU_FRAME - */ -#define VPU_OUTPUT_FORMAT_TYPE_MASK (0x0000ffff) -#define VPU_OUTPUT_FORMAT_ARGB8888 (0x00000000) -#define VPU_OUTPUT_FORMAT_ABGR8888 (0x00000001) -#define VPU_OUTPUT_FORMAT_RGB888 (0x00000002) -#define VPU_OUTPUT_FORMAT_RGB565 (0x00000003) -#define VPU_OUTPUT_FORMAT_RGB555 (0x00000004) -#define VPU_OUTPUT_FORMAT_YUV420_SEMIPLANAR (0x00000005) -#define VPU_OUTPUT_FORMAT_YUV420_PLANAR (0x00000006) -#define VPU_OUTPUT_FORMAT_YUV422 (0x00000007) -#define VPU_OUTPUT_FORMAT_YUV444 (0x00000008) -#define VPU_OUTPUT_FORMAT_YCH420 (0x00000009) -#define VPU_OUTPUT_FORMAT_BIT_MASK (0x000f0000) -#define VPU_OUTPUT_FORMAT_BIT_8 (0x00000000) -#define VPU_OUTPUT_FORMAT_BIT_10 (0x00010000) -#define VPU_OUTPUT_FORMAT_BIT_12 (0x00020000) -#define VPU_OUTPUT_FORMAT_BIT_14 (0x00030000) -#define VPU_OUTPUT_FORMAT_BIT_16 (0x00040000) - - -typedef enum VPU_API_CMD { - VPU_API_ENC_SETCFG, - VPU_API_ENC_GETCFG, - VPU_API_ENC_SETFORMAT, - VPU_API_ENC_SETIDRFRAME, - VPU_API_ENABLE_DEINTERLACE, - VPU_API_SET_VPUMEM_CONTEXT, - VPU_API_USE_PRESENT_TIME_ORDER, - VPU_API_SET_DEFAULT_WIDTH_HEIGH, - VPU_API_SET_INFO_CHANGE, -} VPU_API_CMD; - -typedef struct { - RK_U32 TimeLow; - RK_U32 TimeHigh; -} TIME_STAMP; - -typedef struct VPUMem { - RK_U32 phy_addr; - RK_U32 *vir_addr; - RK_U32 size; - RK_U32 *offset; -} VPUMemLinear_t; - -typedef struct tVPU_FRAME { - RK_U32 FrameBusAddr[2]; // 0: Y address; 1: UV address; - RK_U32 FrameWidth; // buffer horizontal stride - RK_U32 FrameHeight; // buffer vertical stride - RK_U32 OutputWidth; // deprecated - RK_U32 OutputHeight; // deprecated - RK_U32 DisplayWidth; // valid width for display - RK_U32 DisplayHeight; // valid height for display - RK_U32 CodingType; - RK_U32 FrameType; // frame; top_field_first; bot_field_first - RK_U32 ColorType; - RK_U32 DecodeFrmNum; - TIME_STAMP ShowTime; - RK_U32 ErrorInfo; // error information - RK_U32 employ_cnt; - VPUMemLinear_t vpumem; - struct tVPU_FRAME *next_frame; - RK_U32 Res[4]; -} VPU_FRAME; - -typedef struct VideoPacket { - RK_S64 pts; /* with unit of us*/ - RK_S64 dts; /* with unit of us*/ - RK_U8 *data; - RK_S32 size; - RK_U32 capability; - RK_U32 nFlags; -} VideoPacket_t; - -typedef struct DecoderOut { - RK_U8 *data; - RK_U32 size; - RK_S64 timeUs; - RK_S32 nFlags; -} DecoderOut_t; - -typedef struct ParserOut { - RK_U8 *data; - RK_U32 size; - RK_S64 timeUs; - RK_U32 nFlags; - RK_U32 width; - RK_U32 height; -} ParserOut_t; - -typedef struct EncInputStream { - RK_U8 *buf; - RK_S32 size; - RK_U32 bufPhyAddr; - RK_S64 timeUs; - RK_U32 nFlags; -} EncInputStream_t; - -typedef struct EncoderOut { - RK_U8 *data; - RK_S32 size; - RK_S64 timeUs; - RK_S32 keyFrame; - -} EncoderOut_t; - -typedef enum { - VPU_H264ENC_YUV420_PLANAR = 0, /* YYYY... UUUU... VVVV */ - VPU_H264ENC_YUV420_SEMIPLANAR = 1, /* YYYY... UVUVUV... */ - VPU_H264ENC_YUV422_INTERLEAVED_YUYV = 2, /* YUYVYUYV... */ - VPU_H264ENC_YUV422_INTERLEAVED_UYVY = 3, /* UYVYUYVY... */ - VPU_H264ENC_RGB565 = 4, /* 16-bit RGB */ - VPU_H264ENC_BGR565 = 5, /* 16-bit RGB */ - VPU_H264ENC_RGB555 = 6, /* 15-bit RGB */ - VPU_H264ENC_BGR555 = 7, /* 15-bit RGB */ - VPU_H264ENC_RGB444 = 8, /* 12-bit RGB */ - VPU_H264ENC_BGR444 = 9, /* 12-bit RGB */ - VPU_H264ENC_RGB888 = 10, /* 24-bit RGB */ - VPU_H264ENC_BGR888 = 11, /* 24-bit RGB */ - VPU_H264ENC_RGB101010 = 12, /* 30-bit RGB */ - VPU_H264ENC_BGR101010 = 13 /* 30-bit RGB */ -} H264EncPictureType; - -/* - * Enumeration used to define the possible video compression codings. - * NOTE: This essentially refers to file extensions. If the coding is - * being used to specify the ENCODE type, then additional work - * must be done to configure the exact flavor of the compression - * to be used. For decode cases where the user application can - * not differentiate between MPEG-4 and H.264 bit streams, it is - * up to the codec to handle this. - */ -//sync with the omx_video.h -typedef enum OMX_RK_VIDEO_CODINGTYPE { - OMX_RK_VIDEO_CodingUnused, /**< Value when coding is N/A */ - OMX_RK_VIDEO_CodingAutoDetect, /**< Autodetection of coding type */ - OMX_RK_VIDEO_CodingMPEG2, /**< AKA: H.262 */ - OMX_RK_VIDEO_CodingH263, /**< H.263 */ - OMX_RK_VIDEO_CodingMPEG4, /**< MPEG-4 */ - OMX_RK_VIDEO_CodingWMV, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ - OMX_RK_VIDEO_CodingRV, /**< all versions of Real Video */ - OMX_RK_VIDEO_CodingAVC, /**< H.264/AVC */ - OMX_RK_VIDEO_CodingMJPEG, /**< Motion JPEG */ - OMX_RK_VIDEO_CodingVP8, /**< VP8 */ - OMX_RK_VIDEO_CodingVP9, /**< VP9 */ - OMX_RK_VIDEO_CodingVC1 = 0x01000000, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ - OMX_RK_VIDEO_CodingFLV1, /**< Sorenson H.263 */ - OMX_RK_VIDEO_CodingDIVX3, /**< DIVX3 */ - OMX_RK_VIDEO_CodingVP6, - OMX_RK_VIDEO_CodingHEVC, /**< H.265/HEVC */ - OMX_RK_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ - OMX_RK_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ - OMX_RK_VIDEO_CodingMax = 0x7FFFFFFF -} OMX_RK_VIDEO_CODINGTYPE; - -typedef enum CODEC_TYPE { - CODEC_NONE, - CODEC_DECODER, - CODEC_ENCODER, - CODEC_BUTT, -} CODEC_TYPE; - -typedef enum VPU_API_ERR { - VPU_API_OK = 0, - VPU_API_ERR_UNKNOW = -1, - VPU_API_ERR_BASE = -1000, - VPU_API_ERR_LIST_STREAM = VPU_API_ERR_BASE - 1, - VPU_API_ERR_INIT = VPU_API_ERR_BASE - 2, - VPU_API_ERR_VPU_CODEC_INIT = VPU_API_ERR_BASE - 3, - VPU_API_ERR_STREAM = VPU_API_ERR_BASE - 4, - VPU_API_ERR_FATAL_THREAD = VPU_API_ERR_BASE - 5, - VPU_API_EOS_STREAM_REACHED = VPU_API_ERR_BASE - 11, - - VPU_API_ERR_BUTT, -} VPU_API_ERR; - -typedef struct EncParameter { - RK_S32 width; - RK_S32 height; - RK_S32 rc_mode; - RK_S32 bitRate; - RK_S32 framerate; - RK_S32 qp; - RK_S32 enableCabac; - RK_S32 cabacInitIdc; - RK_S32 format; - RK_S32 intraPicRate; - RK_S32 framerateout; - RK_S32 profileIdc; - RK_S32 levelIdc; - RK_S32 reserved[3]; -} EncParameter_t; - - -typedef struct EXtraCfg { - RK_S32 vc1extra_size; - RK_S32 vp6codeid; - RK_S32 tsformat; - RK_U32 reserved[20]; -} EXtraCfg_t; -/** - * @addtogroup rk_vpu_codec - * @{ - */ -typedef struct VpuCodecContext { - void* vpuApiObj; - - CODEC_TYPE codecType; - OMX_RK_VIDEO_CODINGTYPE videoCoding; - - RK_U32 width; - RK_U32 height; - RK_U8 *extradata; - RK_S32 extradata_size; - - RK_U8 enableparsing; - - - - RK_S32 no_thread; - EXtraCfg_t extra_cfg; - - void* private_data; - - /* - ** 1: error state(not working) 0: working - */ - RK_S32 decoder_err; - - - /** - * Allocate and initialize an VpuCodecContext. - * - * @param ctx The context of vpu api, allocated in this function. - * @param extraData The extra data of codec, some codecs need / can - * use extradata like Huffman tables, also live VC1 codec can - * use extradata to initialize itself. - * @param extra_size The size of extra data. - * - * @return 0 for init success, others for failure. - * note: check whether ctx has been allocated success after you do init. - */ - RK_S32 (*init)(struct VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size); - - /** - * @return 0 for decode success, others for failure. - */ - RK_S32 (*decode)(struct VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut); - - /** - * @return 0 for encode success, others for failure. - */ - RK_S32 (*encode)(struct VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut); - - /** - * flush codec while do fast forward playing. - * - * @return 0 for flush success, others for failure. - */ - RK_S32 (*flush)(struct VpuCodecContext *ctx); - RK_S32 (*control)(struct VpuCodecContext *ctx, VPU_API_CMD cmdType, void* param); - /** - *seperate the decode function to two function - * - */ - RK_S32 (*decode_sendstream)(struct VpuCodecContext *ctx, VideoPacket_t *pkt); - RK_S32 (*decode_getframe)(struct VpuCodecContext *ctx, DecoderOut_t *aDecOut); - - RK_S32 (*encoder_sendframe)(struct VpuCodecContext *ctx, EncInputStream_t *aEncInStrm); - RK_S32 (*encoder_getstream)(struct VpuCodecContext *ctx, EncoderOut_t *aEncOut); -} VpuCodecContext_t; - -/* allocated vpu codec context */ -#ifdef __cplusplus -extern "C" -{ -#endif - -RK_S32 vpu_open_context(struct VpuCodecContext **ctx); -RK_S32 vpu_close_context(struct VpuCodecContext **ctx); - -#ifdef __cplusplus -} -#endif - -/* - * vpu_mem api - */ - -typedef struct vpu_display_mem_pool vpu_display_mem_pool; - -struct vpu_display_mem_pool { - int (*commit_hdl)(vpu_display_mem_pool *p, int hdl, int size); - void* (*get_free)(vpu_display_mem_pool *p); - int (*inc_used)(vpu_display_mem_pool *p, int hdl); - int (*put_used)(vpu_display_mem_pool *p, int hdl); - int (*reset)(vpu_display_mem_pool *p); - int (*get_unused_num)(vpu_display_mem_pool *p); - int buff_size; - float version; - int res[18]; -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* - * vpu memory handle interface - */ -RK_S32 VPUMallocLinear(VPUMemLinear_t *p, RK_U32 size); -RK_S32 VPUFreeLinear(VPUMemLinear_t *p); -RK_S32 VPUMemDuplicate(VPUMemLinear_t *dst, VPUMemLinear_t *src); -RK_S32 VPUMemLink(VPUMemLinear_t *p); -RK_S32 VPUMemFlush(VPUMemLinear_t *p); -RK_S32 VPUMemClean(VPUMemLinear_t *p); -RK_S32 VPUMemInvalidate(VPUMemLinear_t *p); - -/* - * vpu memory allocator and manager interface - */ -vpu_display_mem_pool* open_vpu_memory_pool(); -void close_vpu_memory_pool(vpu_display_mem_pool *p); -int create_vpu_memory_pool_allocator(vpu_display_mem_pool **ipool, int num, int size); -void release_vpu_memory_pool_allocator(vpu_display_mem_pool *ipool); - -#ifdef __cplusplus -} -#endif - -#endif /*__VPU_API_LEGACY_H__*/ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VPU_API_H +#define VPU_API_H + +#include "rk_type.h" +#include "mpp_err.h" + +/** + * @brief rockchip media process interface + */ + +#define VPU_API_NOPTS_VALUE (0x8000000000000000LL) + +/* + * bit definition of ColorType in structure VPU_FRAME + */ +#define VPU_OUTPUT_FORMAT_TYPE_MASK (0x0000ffff) +#define VPU_OUTPUT_FORMAT_ARGB8888 (0x00000000) +#define VPU_OUTPUT_FORMAT_ABGR8888 (0x00000001) +#define VPU_OUTPUT_FORMAT_RGB888 (0x00000002) +#define VPU_OUTPUT_FORMAT_RGB565 (0x00000003) +#define VPU_OUTPUT_FORMAT_RGB555 (0x00000004) +#define VPU_OUTPUT_FORMAT_YUV420_SEMIPLANAR (0x00000005) +#define VPU_OUTPUT_FORMAT_YUV420_PLANAR (0x00000006) +#define VPU_OUTPUT_FORMAT_YUV422 (0x00000007) +#define VPU_OUTPUT_FORMAT_YUV444 (0x00000008) +#define VPU_OUTPUT_FORMAT_YCH420 (0x00000009) +#define VPU_OUTPUT_FORMAT_BIT_MASK (0x000f0000) +#define VPU_OUTPUT_FORMAT_BIT_8 (0x00000000) +#define VPU_OUTPUT_FORMAT_BIT_10 (0x00010000) +#define VPU_OUTPUT_FORMAT_BIT_12 (0x00020000) +#define VPU_OUTPUT_FORMAT_BIT_14 (0x00030000) +#define VPU_OUTPUT_FORMAT_BIT_16 (0x00040000) +#define VPU_OUTPUT_FORMAT_FBC_MASK (0x00f00000) +#define VPU_OUTPUT_FORMAT_FBC_AFBC_V1 (0x00100000) +#define VPU_OUTPUT_FORMAT_FBC_AFBC_V2 (0x00200000) +#define VPU_OUTPUT_FORMAT_DYNCRANGE_MASK (0x0f000000) +#define VPU_OUTPUT_FORMAT_DYNCRANGE_SDR (0x00000000) +#define VPU_OUTPUT_FORMAT_DYNCRANGE_HDR10 (0x01000000) +#define VPU_OUTPUT_FORMAT_DYNCRANGE_HDR_HLG (0x02000000) +#define VPU_OUTPUT_FORMAT_DYNCRANGE_HDR_DLBY (0x03000000) + +/** + * @brief input picture type + */ +typedef enum { + ENC_INPUT_YUV420_PLANAR = 0, /**< YYYY... UUUU... VVVV */ + ENC_INPUT_YUV420_SEMIPLANAR = 1, /**< YYYY... UVUVUV... */ + ENC_INPUT_YUV422_INTERLEAVED_YUYV = 2, /**< YUYVYUYV... */ + ENC_INPUT_YUV422_INTERLEAVED_UYVY = 3, /**< UYVYUYVY... */ + ENC_INPUT_RGB565 = 4, /**< 16-bit RGB */ + ENC_INPUT_BGR565 = 5, /**< 16-bit RGB */ + ENC_INPUT_RGB555 = 6, /**< 15-bit RGB */ + ENC_INPUT_BGR555 = 7, /**< 15-bit RGB */ + ENC_INPUT_RGB444 = 8, /**< 12-bit RGB */ + ENC_INPUT_BGR444 = 9, /**< 12-bit RGB */ + ENC_INPUT_RGB888 = 10, /**< 24-bit RGB */ + ENC_INPUT_BGR888 = 11, /**< 24-bit RGB */ + ENC_INPUT_RGB101010 = 12, /**< 30-bit RGB */ + ENC_INPUT_BGR101010 = 13, /**< 30-bit RGB */ + ENC_INPUT_YUV420_SEMIPLANAR_VU = 0X100 /**< YYYY... VUVUVUVU... */ +} EncInputPictureType; + +typedef enum VPU_API_CMD { + VPU_API_ENC_SETCFG, + VPU_API_ENC_GETCFG, + VPU_API_ENC_SETFORMAT, + VPU_API_ENC_SETIDRFRAME, + + VPU_API_ENABLE_DEINTERLACE, + VPU_API_SET_VPUMEM_CONTEXT, + VPU_API_USE_PRESENT_TIME_ORDER, + VPU_API_SET_DEFAULT_WIDTH_HEIGH, + VPU_API_SET_INFO_CHANGE, + VPU_API_USE_FAST_MODE, + VPU_API_DEC_GET_STREAM_COUNT, + VPU_API_GET_VPUMEM_USED_COUNT, + VPU_API_GET_FRAME_INFO, + VPU_API_SET_OUTPUT_BLOCK, + VPU_API_GET_EOS_STATUS, + VPU_API_SET_OUTPUT_MODE, + VPU_API_SET_FRAME_INFO, + + /* get sps/pps header */ + VPU_API_GET_EXTRA_INFO = 0x200, + + VPU_API_SET_IMMEDIATE_OUT = 0x1000, + VPU_API_SET_PARSER_SPLIT_MODE, /* NOTE: should control before init */ + VPU_API_DEC_OUT_FRM_STRUCT_TYPE, + VPU_API_DEC_EN_THUMBNAIL, + VPU_API_DEC_EN_HDR_META, + VPU_API_DEC_EN_MVC, + VPU_API_DEC_EN_FBC_HDR_256_ODD, + VPU_API_SET_INPUT_BLOCK, + VPU_API_SET_DISABLE_ERROR, + VPU_API_SET_DIS_ERR_CLR_MARK, + + /* set pkt/frm ready callback */ + VPU_API_SET_PKT_RDY_CB = 0x1100, + VPU_API_SET_FRM_RDY_CB, + + VPU_API_ENC_VEPU22_START = 0x2000, + VPU_API_ENC_SET_VEPU22_CFG, + VPU_API_ENC_GET_VEPU22_CFG, + VPU_API_ENC_SET_VEPU22_CTU_QP, + VPU_API_ENC_SET_VEPU22_ROI, + + VPU_API_ENC_MPP = 0x3000, + VPU_API_ENC_MPP_SETCFG, + VPU_API_ENC_MPP_GETCFG, + + /* mlvec dynamic configure */ + VPU_API_ENC_MLVEC_CFG = 0x4000, + VPU_API_ENC_SET_MAX_TID, + VPU_API_ENC_SET_MARK_LTR, + VPU_API_ENC_SET_USE_LTR, + VPU_API_ENC_SET_FRAME_QP, + VPU_API_ENC_SET_BASE_LAYER_PID, +} VPU_API_CMD; + +typedef struct { + RK_U32 TimeLow; + RK_U32 TimeHigh; +} TIME_STAMP; + +typedef struct { + RK_U32 CodecType; + RK_U32 ImgWidth; + RK_U32 ImgHeight; + RK_U32 ImgHorStride; + RK_U32 ImgVerStride; + RK_U32 BufSize; +} VPU_GENERIC; + +typedef struct VPUMem { + RK_U32 phy_addr; + RK_U32 *vir_addr; + RK_U32 size; + RK_U32 *offset; +} VPUMemLinear_t; + +typedef struct tVPU_FRAME { + RK_U32 FrameBusAddr[2]; // 0: Y address; 1: UV address; + RK_U32 FrameWidth; // buffer horizontal stride + RK_U32 FrameHeight; // buffer vertical stride + RK_U32 OutputWidth; // deprecated + RK_U32 OutputHeight; // deprecated + RK_U32 DisplayWidth; // valid width for display + RK_U32 DisplayHeight; // valid height for display + RK_U32 CodingType; + RK_U32 FrameType; // frame; top_field_first; bot_field_first + RK_U32 ColorType; + RK_U32 DecodeFrmNum; + TIME_STAMP ShowTime; + RK_U32 ErrorInfo; // error information + RK_U32 employ_cnt; + VPUMemLinear_t vpumem; + struct tVPU_FRAME *next_frame; + union { + struct { + RK_U32 Res0[2]; + struct { + RK_U32 ColorPrimaries : 8; + RK_U32 ColorTransfer : 8; + RK_U32 ColorCoeffs : 8; + RK_U32 ColorRange : 1; + RK_U32 Res1 : 7; + }; + + RK_U32 Res2; + }; + + RK_U32 Res[4]; + }; +} VPU_FRAME; + +typedef struct FrameThumbInfo { + RK_U32 enable; + RK_U32 yOffset; + RK_U32 uvOffset; +} FrameThumbInfo_t; + +typedef struct FrameHdrInfo { + RK_U32 isHdr; + RK_U32 offset; + RK_U32 size; +} FrameHdrInfo_t; + +typedef struct VideoFrame { + VPU_FRAME vpuFrame; + FrameThumbInfo_t thumbInfo; + FrameHdrInfo_t hdrInfo; + RK_U32 viewId; + RK_U32 reserved[16]; +} VideoFrame_t; + +typedef struct VideoPacket { + RK_S64 pts; /* with unit of us*/ + RK_S64 dts; /* with unit of us*/ + RK_U8 *data; + RK_S32 size; + RK_U32 capability; + RK_U32 nFlags; +} VideoPacket_t; + +typedef struct DecoderOut { + RK_U8 *data; + RK_U32 size; + RK_S64 timeUs; + RK_S32 nFlags; +} DecoderOut_t; + +typedef struct ParserOut { + RK_U8 *data; + RK_U32 size; + RK_S64 timeUs; + RK_U32 nFlags; + RK_U32 width; + RK_U32 height; +} ParserOut_t; + +typedef struct EncInputStream { + RK_U8 *buf; + RK_S32 size; + RK_U32 bufPhyAddr; + RK_S64 timeUs; + RK_U32 nFlags; +} EncInputStream_t; + +typedef struct EncoderOut { + RK_U8 *data; + RK_S32 size; + RK_S64 timeUs; + RK_S32 keyFrame; + +} EncoderOut_t; + +typedef RK_S32 (*VpuFrmRdyCbFunc)(void *cb_ctx); + +typedef struct { + VpuFrmRdyCbFunc cb; + void *cbCtx; +} FrameRdyCB; + +/* + * @brief Enumeration used to define the possible video compression codings. + * @note This essentially refers to file extensions. If the coding is + * being used to specify the ENCODE type, then additional work + * must be done to configure the exact flavor of the compression + * to be used. For decode cases where the user application can + * not differentiate between MPEG-4 and H.264 bit streams, it is + * up to the codec to handle this. + * + * sync with the omx_video.h + */ +typedef enum OMX_RK_VIDEO_CODINGTYPE { + OMX_RK_VIDEO_CodingUnused, /**< Value when coding is N/A */ + OMX_RK_VIDEO_CodingAutoDetect, /**< Autodetection of coding type */ + OMX_RK_VIDEO_CodingMPEG2, /**< AKA: H.262 */ + OMX_RK_VIDEO_CodingH263, /**< H.263 */ + OMX_RK_VIDEO_CodingMPEG4, /**< MPEG-4 */ + OMX_RK_VIDEO_CodingWMV, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ + OMX_RK_VIDEO_CodingRV, /**< all versions of Real Video */ + OMX_RK_VIDEO_CodingAVC, /**< H.264/AVC */ + OMX_RK_VIDEO_CodingMJPEG, /**< Motion JPEG */ + OMX_RK_VIDEO_CodingVP8, /**< VP8 */ + OMX_RK_VIDEO_CodingVP9, /**< VP9 */ + OMX_RK_VIDEO_CodingVC1 = 0x01000000, /**< Windows Media Video (WMV1,WMV2,WMV3)*/ + OMX_RK_VIDEO_CodingFLV1, /**< Sorenson H.263 */ + OMX_RK_VIDEO_CodingDIVX3, /**< DIVX3 */ + OMX_RK_VIDEO_CodingVP6, + OMX_RK_VIDEO_CodingHEVC, /**< H.265/HEVC */ + OMX_RK_VIDEO_CodingAVSPLUS, /**< AVS+ profile 0x48 */ + OMX_RK_VIDEO_CodingAVS, /**< AVS profile 0x20 */ + OMX_RK_VIDEO_CodingAVS2, /**< AVS2 */ + OMX_RK_VIDEO_CodingAV1, /**< av1 */ + OMX_RK_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_RK_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_RK_VIDEO_CodingMax = 0x7FFFFFFF +} OMX_RK_VIDEO_CODINGTYPE; + +typedef enum CODEC_TYPE { + CODEC_NONE, + CODEC_DECODER, + CODEC_ENCODER, + CODEC_BUTT, +} CODEC_TYPE; + +typedef enum VPU_API_ERR { + VPU_API_OK = 0, + VPU_API_ERR_UNKNOW = -1, + VPU_API_ERR_BASE = -1000, + VPU_API_ERR_LIST_STREAM = VPU_API_ERR_BASE - 1, + VPU_API_ERR_INIT = VPU_API_ERR_BASE - 2, + VPU_API_ERR_VPU_CODEC_INIT = VPU_API_ERR_BASE - 3, + VPU_API_ERR_STREAM = VPU_API_ERR_BASE - 4, + VPU_API_ERR_FATAL_THREAD = VPU_API_ERR_BASE - 5, + VPU_API_EOS_STREAM_REACHED = VPU_API_ERR_BASE - 11, + + VPU_API_ERR_BUTT, +} VPU_API_ERR; + +typedef enum VPU_FRAME_ERR { + VPU_FRAME_ERR_UNKNOW = 0x0001, + VPU_FRAME_ERR_UNSUPPORT = 0x0002, + +} VPU_FRAME_ERR; + +typedef struct EncParameter { + RK_S32 width; + RK_S32 height; + RK_S32 rc_mode; /* 0 - CQP mode; 1 - CBR mode; 2 - FIXQP mode*/ + RK_S32 bitRate; /* target bitrate */ + RK_S32 framerate; + RK_S32 qp; + RK_S32 enableCabac; + RK_S32 cabacInitIdc; + RK_S32 format; + RK_S32 intraPicRate; + RK_S32 framerateout; + RK_S32 profileIdc; + RK_S32 levelIdc; + RK_S32 reserved[3]; +} EncParameter_t; + +typedef struct EXtraCfg { + RK_S32 vc1extra_size; + RK_S32 vp6codeid; + RK_S32 tsformat; + RK_U32 ori_vpu; /* use origin vpu framework */ + /* below used in decode */ + RK_U32 mpp_mode; /* use mpp framework */ + RK_U32 bit_depth; /* 8 or 10 bit */ + RK_U32 yuv_format; /* 0:420 1:422 2:444 */ + RK_U32 reserved[16]; +} EXtraCfg_t; + +/** + * @brief vpu function interface + */ +typedef struct VpuCodecContext { + void* vpuApiObj; + + CODEC_TYPE codecType; + OMX_RK_VIDEO_CODINGTYPE videoCoding; + + RK_U32 width; + RK_U32 height; + void *extradata; + RK_S32 extradata_size; + + RK_U8 enableparsing; + + RK_S32 no_thread; + EXtraCfg_t extra_cfg; + + void* private_data; + + /* + ** 1: error state(not working) 0: working + */ + RK_S32 decoder_err; + + + /** + * Allocate and initialize an VpuCodecContext. + * + * @param ctx The context of vpu api, allocated in this function. + * @param extraData The extra data of codec, some codecs need / can + * use extradata like Huffman tables, also live VC1 codec can + * use extradata to initialize itself. + * @param extra_size The size of extra data. + * + * @return 0 for init success, others for failure. + * @note check whether ctx has been allocated success after you do init. + */ + RK_S32 (*init)(struct VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size); + /** + * @brief both send video stream packet to decoder and get video frame from + * decoder at the same time + * @param ctx The context of vpu codec + * @param pkt[in] Stream to be decoded + * @param aDecOut[out] Decoding frame + * @return 0 for decode success, others for failure. + */ + RK_S32 (*decode)(struct VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut); + /** + * @brief both send video frame to encoder and get encoded video stream from + * encoder at the same time. + * @param ctx The context of vpu codec + * @param aEncInStrm[in] Frame to be encoded + * @param aEncOut[out] Encoding stream + * @return 0 for encode success, others for failure. + */ + RK_S32 (*encode)(struct VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut); + /** + * @brief flush codec while do fast forward playing. + * @param ctx The context of vpu codec + * @return 0 for flush success, others for failure. + */ + RK_S32 (*flush)(struct VpuCodecContext *ctx); + RK_S32 (*control)(struct VpuCodecContext *ctx, VPU_API_CMD cmdType, void* param); + /** + * @brief send video stream packet to decoder only, async interface + * @param ctx The context of vpu codec + * @param pkt Stream to be decoded + * @return 0 for success, others for failure. + */ + RK_S32 (*decode_sendstream)(struct VpuCodecContext *ctx, VideoPacket_t *pkt); + /** + * @brief get video frame from decoder only, async interface + * @param ctx The context of vpu codec + * @param aDecOut Decoding frame + * @return 0 for success, others for failure. + */ + RK_S32 (*decode_getframe)(struct VpuCodecContext *ctx, DecoderOut_t *aDecOut); + /** + * @brief send video frame to encoder only, async interface + * @param ctx The context of vpu codec + * @param aEncInStrm Frame to be encoded + * @return 0 for success, others for failure. + */ + RK_S32 (*encoder_sendframe)(struct VpuCodecContext *ctx, EncInputStream_t *aEncInStrm); + /** + * @brief get encoded video packet from encoder only, async interface + * @param ctx The context of vpu codec + * @param aEncOut Encoding stream + * @return 0 for success, others for failure. + */ + RK_S32 (*encoder_getstream)(struct VpuCodecContext *ctx, EncoderOut_t *aEncOut); +} VpuCodecContext_t; + +/* allocated vpu codec context */ +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief open context of vpu + * @param ctx pointer of vpu codec context + */ +RK_S32 vpu_open_context(struct VpuCodecContext **ctx); +/** + * @brief close context of vpu + * @param ctx pointer of vpu codec context + */ +RK_S32 vpu_close_context(struct VpuCodecContext **ctx); + +#ifdef __cplusplus +} +#endif + +/* + * vpu_mem api + */ +#define vpu_display_mem_pool_FIELDS \ + RK_S32 (*commit_hdl)(vpu_display_mem_pool *p, RK_S32 hdl, RK_S32 size); \ + void* (*get_free)(vpu_display_mem_pool *p); \ + RK_S32 (*inc_used)(vpu_display_mem_pool *p, void *hdl); \ + RK_S32 (*put_used)(vpu_display_mem_pool *p, void *hdl); \ + RK_S32 (*reset)(vpu_display_mem_pool *p); \ + RK_S32 (*get_unused_num)(vpu_display_mem_pool *p); \ + RK_S32 buff_size;\ + float version; \ + RK_S32 res[18]; + +typedef struct vpu_display_mem_pool vpu_display_mem_pool; + +struct vpu_display_mem_pool { + vpu_display_mem_pool_FIELDS +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * vpu memory handle interface + */ +RK_S32 VPUMemJudgeIommu(void); +RK_S32 VPUMallocLinear(VPUMemLinear_t *p, RK_U32 size); +RK_S32 VPUFreeLinear(VPUMemLinear_t *p); +RK_S32 VPUMemDuplicate(VPUMemLinear_t *dst, VPUMemLinear_t *src); +RK_S32 VPUMemLink(VPUMemLinear_t *p); +RK_S32 VPUMemFlush(VPUMemLinear_t *p); +RK_S32 VPUMemClean(VPUMemLinear_t *p); +RK_S32 VPUMemInvalidate(VPUMemLinear_t *p); +RK_S32 VPUMemGetFD(VPUMemLinear_t *p); +RK_S32 VPUMallocLinearFromRender(VPUMemLinear_t *p, RK_U32 size, void *ctx); + +/* + * vpu memory allocator and manager interface + */ +vpu_display_mem_pool* open_vpu_memory_pool(void); +void close_vpu_memory_pool(vpu_display_mem_pool *p); +int create_vpu_memory_pool_allocator(vpu_display_mem_pool **ipool, int num, int size); +void release_vpu_memory_pool_allocator(vpu_display_mem_pool *ipool); + +#ifdef __cplusplus +} +#endif + +#endif /* VPU_API_H */ diff --git a/kmpp/CMakeLists.txt b/kmpp/CMakeLists.txt new file mode 100644 index 000000000..dfeb4bfe3 --- /dev/null +++ b/kmpp/CMakeLists.txt @@ -0,0 +1,30 @@ +# vim: syntax=cmake + +# ---------------------------------------------------------------------------- +# add include directory +# ---------------------------------------------------------------------------- +include_directories(${PROJECT_SOURCE_DIR}/mpp/codec/inc) +include_directories(${PROJECT_SOURCE_DIR}/osal/driver/inc) + +# ---------------------------------------------------------------------------- +# add kmpp base component +# ---------------------------------------------------------------------------- +add_subdirectory(base) + +# ---------------------------------------------------------------------------- +# add kmpp implement +# ---------------------------------------------------------------------------- +set (KMPP_SRC + kmpp.c + kmpp_venc.c + kmpp_vdec.c + ) + +add_library(kmpp OBJECT ${KMPP_SRC}) +set_target_properties(kmpp PROPERTIES FOLDER "kmpp") + +# ---------------------------------------------------------------------------- +# add kmpp test case +# ---------------------------------------------------------------------------- +add_subdirectory(test) + diff --git a/kmpp/base/CMakeLists.txt b/kmpp/base/CMakeLists.txt new file mode 100644 index 000000000..9d2c1299d --- /dev/null +++ b/kmpp/base/CMakeLists.txt @@ -0,0 +1,20 @@ +# vim: syntax=cmake + +# ---------------------------------------------------------------------------- +# add kmpp basic components +# ---------------------------------------------------------------------------- +add_library(kmpp_base OBJECT + kmpp_ioc.c + kmpp_obj.c + kmpp_meta.c + kmpp_frame.c + kmpp_buffer.c + kmpp_venc_cfg.c + kmpp_vdec_cfg.c + kmpp_packet.c + ) + +set_target_properties(kmpp_base PROPERTIES FOLDER "kmpp/base") + +# unit test +add_subdirectory(test) diff --git a/kmpp/base/inc/kmpp_buffer.h b/kmpp/base/inc/kmpp_buffer.h new file mode 100644 index 000000000..2a1deae00 --- /dev/null +++ b/kmpp/base/inc/kmpp_buffer.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_BUFFER_H +#define KMPP_BUFFER_H + +#include "mpp_buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* KmppBufGrpCfg; +typedef void* KmppBufCfg; +typedef void* KmppDmaBuf; + +typedef enum { + KMPP_BUFFER_INTERNAL, + KMPP_BUFFER_EXTERNAL, + KMPP_BUFFER_MODE_BUTT, +} KmppBufferMode; + +/* + * KmppBufGrp is the ioctl entry for KmppBufGrpCfg + * KmppBufGrpCfg is the buffer group config data entry + * Usage: + * 1. kmpp_buf_grp_get() to get a buffer group + * 2. kmpp_buf_grp_to_cfg() to get the buffer group config data entry + * 3. kmpp_buf_grp_cfg_set_xxx to write buffer group config + * 4. kmpp_buf_grp_setup() to activate buffer group config + * 5. kmpp_buf_grp_put() to release buffer group with group config + */ +#define KMPP_BUF_GRP_IOCTL_TABLE(prefix, IOC_CTX, IOC_IN_, IOC_OUT, IOC_IO_) \ + IOC_CTX(prefix, setup, 0) + +#define KMPP_OBJ_NAME kmpp_buf_grp +#define KMPP_OBJ_INTF_TYPE KmppBufGrp +#define KMPP_OBJ_FUNC_IOCTL KMPP_BUF_GRP_IOCTL_TABLE +#include "kmpp_obj_func.h" + +KmppBufGrpCfg kmpp_buf_grp_to_cfg(KmppBufGrp grp); + +#define KMPP_BUF_GRP_CFG_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + ENTRY(prefix, u32, rk_u32, flag, FLAG_NONE, flag) \ + ENTRY(prefix, u32, rk_u32, count, FLAG_NONE, count) \ + ENTRY(prefix, u32, rk_u32, size, FLAG_NONE, size) \ + ENTRY(prefix, u32, KmppBufferMode, mode, FLAG_NONE, mode) \ + ENTRY(prefix, s32, rk_s32, fd, FLAG_NONE, fd) \ + ENTRY(prefix, s32, rk_s32, grp_id, FLAG_NONE, grp_id) \ + ENTRY(prefix, s32, rk_s32, used, FLAG_NONE, used) \ + ENTRY(prefix, s32, rk_s32, unused, FLAG_NONE, unused) \ + STRCT(prefix, shm, KmppShmPtr, name, FLAG_NONE, name) \ + STRCT(prefix, shm, KmppShmPtr, allocator, FLAG_NONE, allocator) + +#define KMPP_OBJ_NAME kmpp_buf_grp_cfg +#define KMPP_OBJ_INTF_TYPE KmppBufGrpCfg +#define KMPP_OBJ_ENTRY_TABLE KMPP_BUF_GRP_CFG_ENTRY_TABLE +#include "kmpp_obj_func.h" + +/* + * KmppBuffer is the ioctl entry for KmppBufCfg + * KmppBufCfg is the buffer config data entry + * Usage: + * 1. kmpp_buffer_get() to get a buffer + * 2. kmpp_buffer_to_cfg() to get the buffer config data entry + * 3. kmpp_buffer_cfg_set_xxx to write buffer config + * 4. kmpp_buffer_setup() to activate buffer config + * 5. kmpp_buffer_put() to release buffer with config + */ +#define KMPP_BUFFER_IOCTL_TABLE(prefix, IOC_CTX, IOC_IN_, IOC_OUT, IOC_IO_) \ + IOC_CTX(prefix, setup, 0) \ + IOC_CTX(prefix, inc_ref, 1) \ + IOC_CTX(prefix, flush, 2) + +#define KMPP_OBJ_NAME kmpp_buffer +#define KMPP_OBJ_INTF_TYPE KmppBuffer +#define KMPP_OBJ_FUNC_IOCTL KMPP_BUFFER_IOCTL_TABLE +#include "kmpp_obj_func.h" + +KmppBufCfg kmpp_buffer_to_cfg(KmppBuffer buf); + +#define KMPP_BUF_CFG_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + ENTRY(prefix, u32, rk_u32, size, FLAG_NONE, size) \ + ENTRY(prefix, u32, rk_u32, offset, FLAG_NONE, offset) \ + ENTRY(prefix, u32, rk_u32, flag, FLAG_NONE, flag) \ + ENTRY(prefix, s32, rk_s32, fd, FLAG_NONE, fd) \ + ENTRY(prefix, s32, rk_s32, index, FLAG_NONE, index) \ + ENTRY(prefix, s32, rk_s32, grp_id, FLAG_NONE, grp_id) \ + ENTRY(prefix, s32, rk_s32, buf_gid, FLAG_NONE, buf_gid) \ + ENTRY(prefix, s32, rk_s32, buf_uid, FLAG_NONE, buf_uid) \ + STRCT(prefix, shm, KmppShmPtr, sptr, FLAG_NONE, sptr) \ + STRCT(prefix, shm, KmppShmPtr, group, FLAG_NONE, group) \ + ALIAS(prefix, uptr, rk_u64, uptr, FLAG_NONE, uptr) \ + ALIAS(prefix, uptr, rk_u64, upriv, FLAG_NONE, upriv) \ + ALIAS(prefix, ufp, rk_u64, ufp, FLAG_NONE, ufp) + +#define KMPP_OBJ_NAME kmpp_buf_cfg +#define KMPP_OBJ_INTF_TYPE KmppBufCfg +#define KMPP_OBJ_ENTRY_TABLE KMPP_BUF_CFG_ENTRY_TABLE +#include "kmpp_obj_func.h" + +#ifdef __cplusplus +} +#endif + +#endif /* KMPP_BUFFER_H */ diff --git a/kmpp/base/inc/kmpp_buffer_impl.h b/kmpp/base/inc/kmpp_buffer_impl.h new file mode 100644 index 000000000..731e701ec --- /dev/null +++ b/kmpp/base/inc/kmpp_buffer_impl.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_BUFFER_IMPL_H +#define KMPP_BUFFER_IMPL_H + +#include "mpp_list.h" +#include "kmpp_obj.h" +#include "kmpp_buffer.h" + +#define BUF_ST_NONE (0) +#define BUF_ST_INIT (1) +#define BUF_ST_INIT_TO_USED (2) +#define BUF_ST_USED (3) +#define BUF_ST_UNUSED (4) +#define BUF_ST_USED_TO_DEINIT (5) +#define BUF_ST_DEINIT_AT_GRP (6) +#define BUF_ST_DEINIT_AT_SRV (7) + +/* buffer group share name storage for both name and allocator */ +#define BUF_GRP_STR_BUF_SIZE (64) + +typedef struct KmppBufGrpCfgImpl_t { + rk_u32 flag; + rk_u32 count; + rk_u32 size; + KmppBufferMode mode; + rk_s32 fd; + rk_s32 grp_id; + rk_s32 used; + rk_s32 unused; + void *device; + KmppShmPtr allocator; + KmppShmPtr name; + void *grp_impl; +} KmppBufGrpCfgImpl; + +typedef struct KmppBufGrpPriv_t { + KmppObj obj; + KmppBufGrpCfgImpl *impl; +} KmppBufGrpPriv; + +typedef struct KmppBufGrpImpl_t { + /* group share config pointer */ + KmppShmPtr cfg; + KmppBufGrpCfg cfg_ext; + KmppBufGrpCfgImpl *cfg_usr; + KmppObj obj; + + /* internal parameter set on used */ + rk_u32 flag; + rk_u32 count; + rk_u32 size; + KmppBufferMode mode; + + pthread_mutex_t lock; + struct list_head list_srv; + struct list_head list_used; + struct list_head list_unused; + rk_s32 count_used; + rk_s32 count_unused; + + /* allocator */ + void* heap; + rk_s32 heap_fd; + rk_s32 grp_id; + rk_s32 buf_id; + rk_s32 buf_cnt; + rk_s32 buffer_count; + + /* status status */ + rk_s32 log_runtime_en; + rk_s32 log_history_en; + rk_s32 clear_on_exit; + rk_s32 dump_on_exit; + rk_s32 is_orphan; + rk_s32 is_finalizing; + rk_s32 is_default; + + /* string storage */ + rk_s32 name_offset; + rk_u8 str_buf[BUF_GRP_STR_BUF_SIZE]; + + /* buffer group config for internal usage */ + KmppBufGrpCfgImpl cfg_int; +} KmppBufGrpImpl; + +typedef struct KmppBufCfgImpl_t { + rk_u32 size; + rk_u32 offset; + rk_u32 flag; + rk_s32 fd; + rk_s32 index; /* index for external user buffer match */ + rk_s32 grp_id; + rk_s32 buf_gid; + rk_s32 buf_uid; + + void *hnd; + void *dmabuf; + void *kdev; + void *dev; + rk_u64 iova; + void *kptr; + void *kpriv; + void *kfp; + rk_u64 uptr; + rk_u64 upriv; + rk_u64 ufp; + KmppShmPtr sptr; + KmppShmPtr group; + void *buf_impl; +} KmppBufCfgImpl; + +typedef struct KmppBufPriv_t { + KmppObj obj; + KmppBufCfgImpl *impl; +} KmppBufPriv; + +typedef struct KmppBufferImpl_t { + KmppShmPtr cfg; + KmppBufCfg cfg_ext; + KmppBufCfgImpl *cfg_usr; + + KmppBufGrpImpl *grp; + /* when grp is valid used grp lock else use srv lock */ + pthread_mutex_t lock; + struct list_head list_status; + KmppObj obj; + + KmppDmaBuf buf; + void *kptr; + rk_u64 uaddr; + rk_u32 size; + + rk_s32 grp_id; + rk_s32 buf_gid; + rk_s32 buf_uid; + rk_s32 ref_cnt; + + rk_u32 status; + rk_u32 discard; + + /* mutex for list_maps */ + void *mutex_maps; + /* list for list in KmppBufIovaMap */ + struct list_head list_maps; + + KmppBufCfgImpl cfg_int; +} KmppBufferImpl; + +#endif /* KMPP_BUF_GRP_IMPL_H */ diff --git a/kmpp/base/inc/kmpp_frame.h b/kmpp/base/inc/kmpp_frame.h new file mode 100644 index 000000000..7af1fa635 --- /dev/null +++ b/kmpp/base/inc/kmpp_frame.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_FRAME_H +#define KMPP_FRAME_H + +#include "mpp_frame.h" + +#define KMPP_FRAME_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + ENTRY(prefix, u32, rk_u32, width, FLAG_NONE, width) \ + ENTRY(prefix, u32, rk_u32, height, FLAG_NONE, height) \ + ENTRY(prefix, u32, rk_u32, hor_stride, FLAG_NONE, hor_stride) \ + ENTRY(prefix, u32, rk_u32, ver_stride, FLAG_NONE, ver_stride) \ + ENTRY(prefix, u32, rk_u32, hor_stride_pixel, FLAG_NONE, hor_stride_pixel) \ + ENTRY(prefix, u32, rk_u32, offset_x, FLAG_NONE, offset_x) \ + ENTRY(prefix, u32, rk_u32, offset_y, FLAG_NONE, offset_y) \ + ENTRY(prefix, u32, rk_u32, poc, FLAG_NONE, poc) \ + ENTRY(prefix, s64, rk_s64, pts, FLAG_NONE, pts) \ + ENTRY(prefix, s64, rk_s64, dts, FLAG_NONE, dts) \ + ENTRY(prefix, u32, rk_u32, eos, FLAG_NONE, eos) \ + ENTRY(prefix, u32, rk_u32, color_range, FLAG_NONE, color_range) \ + ENTRY(prefix, u32, rk_u32, color_primaries, FLAG_NONE, color_primaries) \ + ENTRY(prefix, u32, rk_u32, color_trc, FLAG_NONE, color_trc) \ + ENTRY(prefix, u32, rk_u32, colorspace, FLAG_NONE, colorspace) \ + ENTRY(prefix, u32, rk_u32, chroma_location, FLAG_NONE, chroma_location) \ + ENTRY(prefix, u32, rk_u32, fmt, FLAG_NONE, fmt) \ + ENTRY(prefix, u32, rk_u32, buf_size, FLAG_NONE, buf_size) \ + ENTRY(prefix, u32, rk_u32, buf_fd, FLAG_NONE, buf_fd) \ + ENTRY(prefix, u32, rk_u32, is_gray, FLAG_NONE, is_gray) \ + STRCT(prefix, shm, KmppShmPtr, buffer, FLAG_NONE, buffer) \ + STRCT(prefix, st, MppFrameRational, sar, FLAG_NONE, sar) + +#ifdef __cplusplus +extern "C" { +#endif + +#define KMPP_OBJ_NAME kmpp_frame +#define KMPP_OBJ_INTF_TYPE KmppFrame +#define KMPP_OBJ_ENTRY_TABLE KMPP_FRAME_ENTRY_TABLE +#include "kmpp_obj_func.h" + +rk_s32 kmpp_frame_get_meta(KmppFrame frame, KmppMeta *meta); + +#ifdef __cplusplus +} +#endif + +#endif /* KMPP_FRAME_H */ diff --git a/kmpp/base/inc/kmpp_frame_impl.h b/kmpp/base/inc/kmpp_frame_impl.h new file mode 100644 index 000000000..cea4c6f2c --- /dev/null +++ b/kmpp/base/inc/kmpp_frame_impl.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_FRAME_IMPL_H +#define KMPP_FRAME_IMPL_H + +#include "kmpp_frame.h" + +typedef struct KmppFrameImpl_t { + const char *name; + KmppObj obj; + + /* + * dimension parameter for display + */ + rk_u32 width; + rk_u32 height; + rk_u32 hor_stride; + rk_u32 ver_stride; + rk_u32 hor_stride_pixel; + rk_u32 offset_x; + rk_u32 offset_y; + + /* + * poc - picture order count + */ + rk_u32 poc; + /* + * pts - display time stamp + * dts - decode time stamp + */ + rk_s64 pts; + rk_s64 dts; + + /* + * eos - end of stream + * info_change - set when buffer resized or frame infomation changed + */ + rk_u32 eos; + MppFrameColorRange color_range; + MppFrameColorPrimaries color_primaries; + MppFrameColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * It must be accessed using av_frame_get_colorspace() and + * av_frame_set_colorspace(). + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + MppFrameColorSpace colorspace; + MppFrameChromaLocation chroma_location; + + MppFrameFormat fmt; + + MppFrameRational sar; + + /* + * buffer information + * NOTE: buf_size only access internally + */ + KmppShmPtr buffer; + size_t buf_size; + RK_U32 buf_fd; + /* + * frame buffer compression (FBC) information + * + * NOTE: some constraint on fbc data + * 1. FBC config need two addresses but only one buffer. + * The second address should be represented by base + offset form. + * 2. FBC has header address and payload address + * Both addresses should be 4K aligned. + * 3. The header section size is default defined by: + * header size = aligned(aligned(width, 16) * aligned(height, 16) / 16, 4096) + * 4. The stride in header section is defined by: + * stride = aligned(width, 16) + */ + rk_u32 fbc_offset; + rk_u32 is_gray; + + KmppShmPtr meta; + KmppMeta self_meta; +} KmppFrameImpl; + +typedef struct KmppFramePriv_t { + KmppMeta meta; +} KmppFramePriv; + +#endif /* KMPP_FRAME_IMPL_H */ diff --git a/kmpp/base/inc/kmpp_ioc.h b/kmpp/base/inc/kmpp_ioc.h new file mode 100644 index 000000000..cca34fdaf --- /dev/null +++ b/kmpp/base/inc/kmpp_ioc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_IOC_H +#define KMPP_IOC_H + +#include "rk_type.h" + +typedef void* KmppIoc; + +#define KMPP_IOC_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + ENTRY(prefix, u32, rk_u32, def, FLAG_NONE, def) \ + ENTRY(prefix, u32, rk_u32, cmd, FLAG_NONE, cmd) \ + ENTRY(prefix, u32, rk_u32, flags, FLAG_NONE, flags) \ + ENTRY(prefix, u32, rk_u32, id, FLAG_NONE, id) \ + ENTRY(prefix, s32, rk_s32, ret, FLAG_NONE, ret) \ + STRCT(prefix, shm, KmppShmPtr, ctx, FLAG_NONE, ctx) \ + STRCT(prefix, shm, KmppShmPtr, in, FLAG_NONE, in) \ + STRCT(prefix, shm, KmppShmPtr, out, FLAG_NONE, out) + +#define KMPP_OBJ_NAME kmpp_ioc +#define KMPP_OBJ_INTF_TYPE KmppIoc +#define KMPP_OBJ_ENTRY_TABLE KMPP_IOC_ENTRY_TABLE +#include "kmpp_obj_func.h" + +#endif /* KMPP_IOC_H */ diff --git a/kmpp/base/inc/kmpp_meta.h b/kmpp/base/inc/kmpp_meta.h new file mode 100644 index 000000000..37bc4ec4c --- /dev/null +++ b/kmpp/base/inc/kmpp_meta.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_META_H +#define KMPP_META_H + +#include "mpp_meta.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define KmppMetaKey MppMetaKey + +#define kmpp_meta_get_f(meta) kmpp_meta_get(meta, __FUNCTION__) +#define kmpp_meta_put_f(meta) kmpp_meta_put(meta, __FUNCTION__) +#define kmpp_meta_size_f(meta) kmpp_meta_size(meta, __FUNCTION__) +#define kmpp_meta_dump_f(meta) kmpp_meta_dump(meta, __FUNCTION__) + +rk_s32 kmpp_meta_get(KmppMeta *meta, const char *caller); +rk_s32 kmpp_meta_put(KmppMeta meta, const char *caller); +rk_s32 kmpp_meta_size(KmppMeta meta, const char *caller); +rk_s32 kmpp_meta_dump(KmppMeta meta, const char *caller); +rk_s32 kmpp_meta_dump_all(const char *caller); + +rk_s32 kmpp_meta_set_s32(KmppMeta meta, KmppMetaKey key, rk_s32 val); +rk_s32 kmpp_meta_set_s64(KmppMeta meta, KmppMetaKey key, rk_s64 val); +rk_s32 kmpp_meta_set_ptr(KmppMeta meta, KmppMetaKey key, void *val); +rk_s32 kmpp_meta_get_s32(KmppMeta meta, KmppMetaKey key, rk_s32 *val); +rk_s32 kmpp_meta_get_s64(KmppMeta meta, KmppMetaKey key, rk_s64 *val); +rk_s32 kmpp_meta_get_ptr(KmppMeta meta, KmppMetaKey key, void **val); +rk_s32 kmpp_meta_get_s32_d(KmppMeta meta, KmppMetaKey key, rk_s32 *val, rk_s32 def); +rk_s32 kmpp_meta_get_s64_d(KmppMeta meta, KmppMetaKey key, rk_s64 *val, rk_s64 def); +rk_s32 kmpp_meta_get_ptr_d(KmppMeta meta, KmppMetaKey key, void **val, void *def); + +rk_s32 kmpp_meta_set_obj(KmppMeta meta, KmppMetaKey key, KmppObj obj); +rk_s32 kmpp_meta_get_obj(KmppMeta meta, KmppMetaKey key, KmppObj *obj); +rk_s32 kmpp_meta_get_obj_d(KmppMeta meta, KmppMetaKey key, KmppObj *obj, KmppObj def); +rk_s32 kmpp_meta_set_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr); +rk_s32 kmpp_meta_get_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr); +rk_s32 kmpp_meta_get_shm_d(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr, KmppShmPtr *def); + +#ifdef __cplusplus +} +#endif + +#endif /* KMPP_META_H */ diff --git a/kmpp/base/inc/kmpp_meta_impl.h b/kmpp/base/inc/kmpp_meta_impl.h new file mode 100644 index 000000000..95e985d6a --- /dev/null +++ b/kmpp/base/inc/kmpp_meta_impl.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_META_IMPL_H +#define KMPP_META_IMPL_H + +#include "mpp_list.h" +#include "kmpp_meta.h" + +#define MPP_TAG_SIZE 32 + +typedef struct __attribute__((packed, aligned(4))) KmppMetaVal_t { + rk_u32 state; + union { + rk_s32 val_s32; + rk_s64 val_s64; + void *val_ptr; + }; +} KmppMetaVal; + +typedef struct __attribute__((packed, aligned(4))) KmppMetaShmVal_t { + rk_u32 state; + KmppShmPtr val_shm; +} KmppMetaObj; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* KMPP_META_IMPL_H */ diff --git a/kmpp/base/inc/kmpp_obj.h b/kmpp/base/inc/kmpp_obj.h new file mode 100644 index 000000000..a87dbadb4 --- /dev/null +++ b/kmpp/base/inc/kmpp_obj.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_OBJ_H +#define KMPP_OBJ_H + +#include "mpp_internal.h" + +typedef rk_s32 (*KmppObjInit)(void *entry, KmppObj obj, const char *caller); +typedef rk_s32 (*KmppObjDeinit)(void *entry, KmppObj obj, const char *caller); +typedef rk_s32 (*KmppObjPreset)(void *entry, KmppObj obj, const char *val, const char *caller); +typedef rk_s32 (*KmppObjDump)(void *entry); + +#ifdef __cplusplus +extern "C" { +#endif + +/* userspace objdef register */ +rk_s32 kmpp_objdef_register(KmppObjDef *def, rk_s32 priv_size, rk_s32 size, const char *name); +/* kernel objdef query from /dev/kmpp_objs */ +rk_s32 kmpp_objdef_get(KmppObjDef *def, rk_s32 priv_size, const char *name); +/* find kernel objdef by name */ +rk_s32 kmpp_objdef_find(KmppObjDef *def, const char *name); +/* kernel objdef from /dev/kmpp_objs reduce refcnt */ +rk_s32 kmpp_objdef_put(KmppObjDef def); + +/* userspace objdef add MppCfgObj root */ +rk_s32 kmpp_objdef_add_cfg_root(KmppObjDef def, MppCfgObj root); +/* userspace objdef get MppCfgObj root */ +MppCfgObj kmpp_objdef_get_cfg_root(KmppObjDef def); +/* userspace objdef add KmppEntry table */ +rk_s32 kmpp_objdef_add_entry(KmppObjDef def, const char *name, KmppEntry *tbl); +/* userspace object init function register default object is all zero */ +rk_s32 kmpp_objdef_add_init(KmppObjDef def, KmppObjInit init); +/* userspace object deinit function register */ +rk_s32 kmpp_objdef_add_deinit(KmppObjDef def, KmppObjDeinit deinit); +/* userspace object preset function register */ +rk_s32 kmpp_objdef_add_preset(KmppObjDef def, KmppObjPreset preset); +/* userspace object dump function register */ +rk_s32 kmpp_objdef_add_dump(KmppObjDef def, KmppObjDump dump); + +rk_s32 kmpp_objdef_set_prop(KmppObjDef def, const char *op, rk_s32 value); + +rk_s32 kmpp_objdef_get_entry(KmppObjDef def, const char *name, KmppEntry **tbl); +rk_s32 kmpp_objdef_get_offset(KmppObjDef def, const char *name); +rk_s32 kmpp_objdef_get_cmd(KmppObjDef def, const char *name); +rk_s32 kmpp_objdef_dump(KmppObjDef def); + +/* mpp objcet internal element set / get function */ +const char *kmpp_objdef_get_name(KmppObjDef def); +rk_s32 kmpp_objdef_get_entry_size(KmppObjDef def); +MppTrie kmpp_objdef_get_trie(KmppObjDef def); + +/* import kernel object ref */ +rk_s32 kmpp_obj_get(KmppObj *obj, KmppObjDef def, const char *caller); +rk_s32 kmpp_obj_get_by_name(KmppObj *obj, const char *name, const char *caller); +rk_s32 kmpp_obj_get_by_sptr(KmppObj *obj, KmppShmPtr *sptr, const char *caller); +/* release object and impl head */ +rk_s32 kmpp_obj_put(KmppObj obj, const char *caller); +/* release impl head only */ +rk_s32 kmpp_obj_impl_put(KmppObj obj, const char *caller); +/* setup object to a preset value by string args input */ +rk_s32 kmpp_obj_preset(KmppObj obj, const char *arg, const char *caller); +/* check object is valid or not */ +rk_s32 kmpp_obj_check(KmppObj obj, const char *caller); +/* run object's ioctl to kernel with input and output object */ +rk_s32 kmpp_obj_ioctl(KmppObj ctx, rk_s32 cmd, KmppObj in, KmppObj *out, const char *caller); + +#define kmpp_obj_get_f(obj, def) kmpp_obj_get(obj, def, __FUNCTION__) +#define kmpp_obj_get_by_name_f(obj, name) kmpp_obj_get_by_name(obj, name, __FUNCTION__) +#define kmpp_obj_get_by_sptr_f(obj, sptr) kmpp_obj_get_by_sptr(obj, sptr, __FUNCTION__) +#define kmpp_obj_put_f(obj) kmpp_obj_put(obj, __FUNCTION__) +#define kmpp_obj_impl_put_f(obj) kmpp_obj_impl_put(obj, __FUNCTION__) +#define kmpp_obj_preset_f(obj, arg) kmpp_obj_preset(obj, arg, __FUNCTION__) +#define kmpp_obj_check_f(obj) kmpp_obj_check(obj, __FUNCTION__) +#define kmpp_obj_ioctl_f(ctx, cmd, in, out) kmpp_obj_ioctl(ctx, cmd, in, out, __FUNCTION__) + +/* check a object is kobject or not */ +rk_s32 kmpp_obj_is_kobj(KmppObj obj); +/* object to its objdef */ +KmppObjDef kmpp_obj_to_objdef(KmppObj obj); +/* object implement element update flags access */ +void *kmpp_obj_to_flags(KmppObj obj); +rk_s32 kmpp_obj_to_flags_size(KmppObj obj); +/* KmppShmPtr is the kernel share object userspace base address for kernel ioctl */ +KmppShmPtr *kmpp_obj_to_shm(KmppObj obj); +/* KmppShmPtr size defined the copy size for kernel ioctl */ +rk_s32 kmpp_obj_to_shm_size(KmppObj obj); +const char *kmpp_obj_get_name(KmppObj obj); +/* + * priv is the private data in userspace KmppObjImpl struct for kobject transaction + * priv = KmppObjImpl->priv + */ +void *kmpp_obj_to_priv(KmppObj obj); +/* + * entry is the userspace address for kernel share object body + * entry = KmppShmPtr->uaddr + entry_offset + */ +void *kmpp_obj_to_entry(KmppObj obj); +/* offset is the entry offset from kernel share object body */ +rk_s32 kmpp_obj_to_offset(KmppObj obj, const char *name); + +/* value access function */ +rk_s32 kmpp_obj_set_s8(KmppObj obj, const char *name, rk_s8 val); +rk_s32 kmpp_obj_get_s8(KmppObj obj, const char *name, rk_s8 *val); +rk_s32 kmpp_obj_set_u8(KmppObj obj, const char *name, rk_u8 val); +rk_s32 kmpp_obj_get_u8(KmppObj obj, const char *name, rk_u8 *val); +rk_s32 kmpp_obj_set_s16(KmppObj obj, const char *name, rk_s16 val); +rk_s32 kmpp_obj_get_s16(KmppObj obj, const char *name, rk_s16 *val); +rk_s32 kmpp_obj_set_u16(KmppObj obj, const char *name, rk_u16 val); +rk_s32 kmpp_obj_get_u16(KmppObj obj, const char *name, rk_u16 *val); +rk_s32 kmpp_obj_set_s32(KmppObj obj, const char *name, rk_s32 val); +rk_s32 kmpp_obj_get_s32(KmppObj obj, const char *name, rk_s32 *val); +rk_s32 kmpp_obj_set_u32(KmppObj obj, const char *name, rk_u32 val); +rk_s32 kmpp_obj_get_u32(KmppObj obj, const char *name, rk_u32 *val); +rk_s32 kmpp_obj_set_s64(KmppObj obj, const char *name, rk_s64 val); +rk_s32 kmpp_obj_get_s64(KmppObj obj, const char *name, rk_s64 *val); +rk_s32 kmpp_obj_set_u64(KmppObj obj, const char *name, rk_u64 val); +rk_s32 kmpp_obj_get_u64(KmppObj obj, const char *name, rk_u64 *val); +rk_s32 kmpp_obj_set_st(KmppObj obj, const char *name, void *val); +rk_s32 kmpp_obj_get_st(KmppObj obj, const char *name, void *val); +rk_s32 kmpp_obj_tbl_set_s8(KmppObj obj, KmppEntry *tbl, rk_s8 val); +rk_s32 kmpp_obj_tbl_get_s8(KmppObj obj, KmppEntry *tbl, rk_s8 *val); +rk_s32 kmpp_obj_tbl_set_u8(KmppObj obj, KmppEntry *tbl, rk_u8 val); +rk_s32 kmpp_obj_tbl_get_u8(KmppObj obj, KmppEntry *tbl, rk_u8 *val); +rk_s32 kmpp_obj_tbl_set_s16(KmppObj obj, KmppEntry *tbl, rk_s16 val); +rk_s32 kmpp_obj_tbl_get_s16(KmppObj obj, KmppEntry *tbl, rk_s16 *val); +rk_s32 kmpp_obj_tbl_set_u16(KmppObj obj, KmppEntry *tbl, rk_u16 val); +rk_s32 kmpp_obj_tbl_get_u16(KmppObj obj, KmppEntry *tbl, rk_u16 *val); +rk_s32 kmpp_obj_tbl_set_s32(KmppObj obj, KmppEntry *tbl, rk_s32 val); +rk_s32 kmpp_obj_tbl_get_s32(KmppObj obj, KmppEntry *tbl, rk_s32 *val); +rk_s32 kmpp_obj_tbl_set_u32(KmppObj obj, KmppEntry *tbl, rk_u32 val); +rk_s32 kmpp_obj_tbl_get_u32(KmppObj obj, KmppEntry *tbl, rk_u32 *val); +rk_s32 kmpp_obj_tbl_set_s64(KmppObj obj, KmppEntry *tbl, rk_s64 val); +rk_s32 kmpp_obj_tbl_get_s64(KmppObj obj, KmppEntry *tbl, rk_s64 *val); +rk_s32 kmpp_obj_tbl_set_u64(KmppObj obj, KmppEntry *tbl, rk_u64 val); +rk_s32 kmpp_obj_tbl_get_u64(KmppObj obj, KmppEntry *tbl, rk_u64 *val); +rk_s32 kmpp_obj_tbl_set_st(KmppObj obj, KmppEntry *tbl, void *val); +rk_s32 kmpp_obj_tbl_get_st(KmppObj obj, KmppEntry *tbl, void *val); + +/* userspace access only function */ +rk_s32 kmpp_obj_set_obj(KmppObj obj, const char *name, KmppObj val); +rk_s32 kmpp_obj_get_obj(KmppObj obj, const char *name, KmppObj *val); +rk_s32 kmpp_obj_set_ptr(KmppObj obj, const char *name, void *val); +rk_s32 kmpp_obj_get_ptr(KmppObj obj, const char *name, void **val); +rk_s32 kmpp_obj_set_fp(KmppObj obj, const char *name, void *val); +rk_s32 kmpp_obj_get_fp(KmppObj obj, const char *name, void **val); +rk_s32 kmpp_obj_tbl_set_obj(KmppObj obj, KmppEntry *tbl, KmppObj val); +rk_s32 kmpp_obj_tbl_get_obj(KmppObj obj, KmppEntry *tbl, KmppObj *val); +rk_s32 kmpp_obj_tbl_set_ptr(KmppObj obj, KmppEntry *tbl, void *val); +rk_s32 kmpp_obj_tbl_get_ptr(KmppObj obj, KmppEntry *tbl, void **val); +rk_s32 kmpp_obj_tbl_set_fp(KmppObj obj, KmppEntry *tbl, void *val); +rk_s32 kmpp_obj_tbl_get_fp(KmppObj obj, KmppEntry *tbl, void **val); + +/* share access function */ +rk_s32 kmpp_obj_set_shm(KmppObj obj, const char *name, KmppShmPtr *val); +rk_s32 kmpp_obj_get_shm(KmppObj obj, const char *name, KmppShmPtr *val); +rk_s32 kmpp_obj_tbl_set_shm(KmppObj obj, KmppEntry *tbl, KmppShmPtr *val); +rk_s32 kmpp_obj_tbl_get_shm(KmppObj obj, KmppEntry *tbl, KmppShmPtr *val); + +/* helper for get share object from a share memory element */ +rk_s32 kmpp_obj_set_shm_obj(KmppObj obj, const char *name, KmppObj val); +rk_s32 kmpp_obj_get_shm_obj(KmppObj obj, const char *name, KmppObj *val); + +/* update flag check function */ +rk_s32 kmpp_obj_test(KmppObj obj, const char *name); +rk_s32 kmpp_obj_tbl_test(KmppObj obj, KmppEntry *tbl); + +/* update entry value marked by update flag from src to dst (clear src flag) */ +rk_s32 kmpp_obj_update(KmppObj dst, KmppObj src); +/* update entry value marked by update flag from src to dst (keep src flag) */ +rk_s32 kmpp_obj_update_entry(void *entry, KmppObj src); + +/* copy entry value and update flag from src to dst (keep src flag) */ +rk_s32 kmpp_obj_copy(KmppObj dst, KmppObj src); +/* copy entry value from src to dst only (keep src flag) */ +rk_s32 kmpp_obj_copy_entry(KmppObj dst, KmppObj src); + +/* run a callback function */ +rk_s32 kmpp_obj_run(KmppObj obj, const char *name); +/* dump by userspace */ +rk_s32 kmpp_obj_udump_f(KmppObj obj, const char *caller); +/* dump by kernel */ +rk_s32 kmpp_obj_kdump_f(KmppObj obj, const char *caller); + +#define kmpp_obj_udump(obj) kmpp_obj_udump_f(obj, __FUNCTION__) +#define kmpp_obj_kdump(obj) kmpp_obj_kdump_f(obj, __FUNCTION__) + +rk_s32 kmpp_shm_get(KmppShm *shm, rk_s32 size, const char *caller); +rk_s32 kmpp_shm_put(KmppShm shm, const char *caller); + +void *kmpp_shm_to_entry(KmppShm shm, const char *caller); + +#define kmpp_shm_get_f(shm, size) kmpp_shm_get(shm, size, __FUNCTION__) +#define kmpp_shm_put_f(shm) kmpp_shm_put(shm, __FUNCTION__) +#define kmpp_shm_to_entry_f(shm) kmpp_shm_to_entry(shm, __FUNCTION__) + +const char *strof_elem_type(ElemType type); + +#ifdef __cplusplus +} +#endif + +#endif /* KMPP_OBJ_H */ diff --git a/kmpp/base/inc/kmpp_obj_func.h b/kmpp/base/inc/kmpp_obj_func.h new file mode 100644 index 000000000..4af0a92c2 --- /dev/null +++ b/kmpp/base/inc/kmpp_obj_func.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#include "kmpp_obj_macro.h" + +#ifndef KMPP_OBJ_NAME +#error "KMPP_OBJ_NAME must be defined on using kmpp_obj_func.h" +#endif + +#ifndef KMPP_OBJ_INTF_TYPE +#error "KMPP_OBJ_INTF_TYPE must be defined on using kmpp_obj_func.h" +#endif + +#include "rk_type.h" + +/* always define object common function */ +#define KMPP_OBJ_FUNC_DEFINE(prefix) \ + rk_s32 CONCAT_US(prefix, size)(void); \ + rk_s32 CONCAT_US(prefix, get)(KMPP_OBJ_INTF_TYPE *p); \ + rk_s32 CONCAT_US(prefix, assign)(KMPP_OBJ_INTF_TYPE *p, void *buf, rk_s32 size); \ + rk_s32 CONCAT_US(prefix, put)(KMPP_OBJ_INTF_TYPE p); \ + rk_s32 CONCAT_US(prefix, dump)(KMPP_OBJ_INTF_TYPE p, const char *caller); \ + KmppObjDef CONCAT_US(prefix, objdef)(void); + +#ifdef __cplusplus +extern "C" { +#endif + +KMPP_OBJ_FUNC_DEFINE(KMPP_OBJ_NAME) + +#ifdef __cplusplus +} +#endif + +#undef KMPP_OBJ_FUNC_DEFINE + +/* entry and hook access functions */ +#ifdef KMPP_OBJ_ENTRY_TABLE +/* disable all hierarchy macro in header */ +#define CFG_DEF_START(...) +#define CFG_DEF_END(...) +#define STRUCT_START(...) +#define STRUCT_END(...) + +#define ENTRY_DECLARE(prefix, ftype, type, name, flag, ...) \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE p, type val); \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE p, type* val); \ + rk_s32 CONCAT_US(prefix, test, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE p); + +#define STRCT_DECLARE(prefix, ftype, type, name, flag, ...) \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE p, type* val); \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE p, type* val); \ + rk_s32 CONCAT_US(prefix, test, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE p); + +#define ALIAS_DECLARE(prefix, ftype, type, name, flag, ...) + +#ifdef __cplusplus +extern "C" { +#endif + +KMPP_OBJ_ENTRY_TABLE(KMPP_OBJ_NAME, ENTRY_DECLARE, STRCT_DECLARE, + ENTRY_DECLARE, STRCT_DECLARE, ALIAS_DECLARE) + +#ifdef __cplusplus +} +#endif + +#undef ENTRY_DECLARE +#undef ENTRY_TO_ALIAS +#undef STRCT_DECLARE + +#undef CFG_DEF_START +#undef CFG_DEF_END +#undef STRUCT_START +#undef STRUCT_END + +#endif /* KMPP_OBJ_ENTRY_TABLE */ + +#ifdef KMPP_OBJ_FUNC_IOCTL + +#define IOCTL_CTX(prefix, func, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx); + +#define IOCTL_IN_(prefix, func, in_type, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx, in_type in); + +#define IOCTL_OUT(prefix, func, out_type, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx, out_type *out); + +#define IOCTL_IO_(prefix, func, in_type, out_type, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx, in_type in, out_type *out); + +#ifdef __cplusplus +extern "C" { +#endif + +KMPP_OBJ_FUNC_IOCTL(KMPP_OBJ_NAME, IOCTL_CTX, IOCTL_IN_, IOCTL_OUT, IOCTL_IO_) + +#ifdef __cplusplus +} +#endif + +#undef IOCTL_CTX +#undef IOCTL_IN_ +#undef IOCTL_OUT +#undef IOCTL_IO_ + +#endif /* KMPP_OBJ_FUNC_IOCTL */ + +#undef KMPP_OBJ_NAME +#undef KMPP_OBJ_INTF_TYPE +#undef KMPP_OBJ_ENTRY_TABLE +#undef KMPP_OBJ_FUNC_IOCTL diff --git a/kmpp/base/inc/kmpp_obj_helper.h b/kmpp/base/inc/kmpp_obj_helper.h new file mode 100644 index 000000000..c2cae333c --- /dev/null +++ b/kmpp/base/inc/kmpp_obj_helper.h @@ -0,0 +1,684 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#include "kmpp_obj_macro.h" + +#ifdef OBJECT_HERLPER_H +#error “MUST NOT include obj_helper.h within obj_helper.h“ +#endif + +/* define object helper for loop include detection */ +#define OBJECT_HERLPER_H + +#if !defined(KMPP_OBJ_NAME) || \ + !defined(KMPP_OBJ_INTF_TYPE) + +#warning "When using kmpp_obj_helper.h The following macro must be defined:" +#warning "KMPP_OBJ_NAME - object name" +#warning "KMPP_OBJ_INTF_TYPE - object interface type" +#warning "option macro:" +#warning "KMPP_OBJ_IMPL_TYPE - object implement type" +#warning "KMPP_OBJ_EXTRA_SIZE - object extra size in bytes" +#warning "KMPP_OBJ_ENTRY_TABLE - object element value / pointer entry table" +#warning "KMPP_OBJ_FUNC_IOCTL - object element ioctl cmd and function table" +#warning "KMPP_OBJ_FUNC_INIT - add object init function" +#warning "KMPP_OBJ_FUNC_DEINIT - add object deinit function" +#warning "KMPP_OBJ_FUNC_DUMP - add object dump function" +#warning "KMPP_OBJ_SGLN - singleton macro (default MPP_SINGLETON)" +#warning "KMPP_OBJ_SGLN_ID - add object singleton id for singleton macro" +#warning "KMPP_OBJ_FUNC_EXPORT_DISABLE - disable function exprot by EXPORT_SYMBOL" +#warning "KMPP_OBJ_ACCESS_DISABLE - disable access function creation" +#warning "KMPP_OBJ_SHARE_DISABLE - disable object sharing by /dev/kmpp_objs to userspace" +#warning "KMPP_OBJ_HIERARCHY_ENABLE - enable hierarchy name creation" +#warning "KMPP_OBJ_MISMATCH_LOG_DISABLE - disable entry query mismatch log" + +#ifndef KMPP_OBJ_NAME +#error "KMPP_OBJ_NAME not defined" +#endif +#ifndef KMPP_OBJ_INTF_TYPE +#error "KMPP_OBJ_INTF_TYPE not defined" +#endif + +#else /* all input macro defined */ + +#include + +#ifndef KMPP_OBJ_PRIV_SIZE +#define KMPP_OBJ_PRIV_SIZE 0 +#endif + +#ifndef KMPP_OBJ_EXTRA_SIZE +#define KMPP_OBJ_EXTRA_SIZE 0 +#endif + +#ifndef KMPP_OBJ_ENTRY_TABLE +#define KMPP_OBJ_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) +#endif + +#ifndef KMPP_OBJ_SGLN +#define KMPP_OBJ_SGLN MPP_SINGLETON +#endif + +#ifdef KMPP_OBJ_IMPL_TYPE +#ifdef KMPP_OBJ_HIERARCHY_ENABLE + +#define MPP_CFG_TYPE_ptr MPP_CFG_TYPE_OBJECT +#define MPP_CFG_TYPE_st MPP_CFG_TYPE_OBJECT +#define MPP_CFG_TYPE_starr MPP_CFG_TYPE_ARRAY +#define ELEM_TYPE_starr ELEM_TYPE_arr + +#define KMPP_TYPE_TO_ELEM_TYPE(type) ({ \ + ElemType _ret = ELEM_TYPE_BUTT; \ + if (__builtin_types_compatible_p(type, rk_s8)) \ + _ret = ELEM_TYPE_s8; \ + else if (__builtin_types_compatible_p(type, rk_u8)) \ + _ret = ELEM_TYPE_u8; \ + else if (__builtin_types_compatible_p(type, rk_s16)) \ + _ret = ELEM_TYPE_s16; \ + else if (__builtin_types_compatible_p(type, rk_u16)) \ + _ret = ELEM_TYPE_u16; \ + else if (__builtin_types_compatible_p(type, rk_s32)) \ + _ret = ELEM_TYPE_s32; \ + else if (__builtin_types_compatible_p(type, rk_u32)) \ + _ret = ELEM_TYPE_u32; \ + else if (__builtin_types_compatible_p(type, rk_s64)) \ + _ret = ELEM_TYPE_s64; \ + else if (__builtin_types_compatible_p(type, rk_u64)) \ + _ret = ELEM_TYPE_u64; \ + _ret; \ +}) + +#define ENTRY_TO_TRIE(prefix, ftype, type, name, flag, ...) \ + do { \ + KmppEntry tbl = { \ + .tbl.elem_offset = ((size_t)&(((KMPP_OBJ_IMPL_TYPE *)0)->CONCAT_DOT(__VA_ARGS__))), \ + .tbl.elem_size = sizeof(((KMPP_OBJ_IMPL_TYPE *)0)->CONCAT_DOT(__VA_ARGS__)), \ + .tbl.elem_type = ELEM_TYPE_##ftype, \ + .tbl.flag_offset = FLAG_TYPE_TO_OFFSET(name, flag, #flag), \ + }; \ + MppCfgObj CONCAT_US(obj, name) = NULL; \ + kmpp_objdef_add_entry(KMPP_OBJ_DEF(prefix), ENTRY_TO_NAME_START(name), &tbl); \ + if (tbl.tbl.elem_type == ELEM_TYPE_starr) { \ + rk_s32 elem_size = sizeof(type); \ + rk_s32 elem_cnt = (rk_s32)(tbl.tbl.elem_size / elem_size); \ + rk_s32 i; \ + char array_name[64]; \ + mpp_cfg_get_array(&CONCAT_US(obj, name), TO_STR(name), 0); \ + for (i = 0; i < elem_cnt; i++) { \ + KmppEntry tmp_tbl = { .val = 0 }; \ + MppCfgObj tmp_obj = NULL; \ + tmp_tbl.tbl.elem_offset = tbl.tbl.elem_offset + i * elem_size; \ + tmp_tbl.tbl.elem_size = elem_size; \ + tmp_tbl.tbl.elem_type = KMPP_TYPE_TO_ELEM_TYPE(type); \ + snprintf(array_name, sizeof(array_name), "array_%d", i); \ + mpp_cfg_get_object(&tmp_obj, array_name, mpp_cfg_type_from_elem_type(tmp_tbl.tbl.elem_type), NULL); \ + mpp_cfg_set_entry(tmp_obj, &tmp_tbl); \ + mpp_cfg_add(CONCAT_US(obj, name), tmp_obj); \ + } \ + } else \ + mpp_cfg_get_object(&CONCAT_US(obj, name), TO_STR(name), MPP_CFG_TYPE_##ftype, NULL); \ + mpp_cfg_set_entry(CONCAT_US(obj, name), &tbl); \ + mpp_cfg_add(__parent, CONCAT_US(obj, name)); \ + ENTRY_TO_NAME_END(name); \ + } while (0); +#else +#define ENTRY_TO_TRIE(prefix, ftype, type, name, flag, ...) \ + do { \ + KmppEntry tbl = { \ + .tbl.elem_offset = ((size_t)&(((KMPP_OBJ_IMPL_TYPE *)0)->CONCAT_DOT(__VA_ARGS__))), \ + .tbl.elem_size = sizeof(((KMPP_OBJ_IMPL_TYPE *)0)->CONCAT_DOT(__VA_ARGS__)), \ + .tbl.elem_type = ELEM_TYPE_##ftype, \ + .tbl.flag_offset = FLAG_TYPE_TO_OFFSET(name, flag, #flag), \ + }; \ + kmpp_objdef_add_entry(KMPP_OBJ_DEF(prefix), ENTRY_TO_NAME_START(name), &tbl); \ + ENTRY_TO_NAME_END(name); \ + } while (0); +#endif /* KMPP_OBJ_HIERARCHY_ENABLE */ +#else +#define ENTRY_TO_TRIE(prefix, ftype, type, name, flag, ...) +#endif /* KMPP_OBJ_IMPL_TYPE */ + +#if !defined(KMPP_OBJ_ACCESS_DISABLE) +#define VAL_ENTRY_TBL(prefix, ftype, type, name, flag, ...) \ + static KmppEntry *CONCAT_US(tbl, prefix, __VA_ARGS__) = NULL; + +#define VAL_HOOK_IDX(prefix, ftype, type, name, flag, ...) \ + static rk_s32 CONCAT_US(hook, prefix, get, __VA_ARGS__) = -1; \ + static rk_s32 CONCAT_US(hook, prefix, set, __VA_ARGS__) = -1; + +#define ENTRY_QUERY(prefix, ftype, type, name, flag, ...) \ + do { \ + kmpp_objdef_get_entry(KMPP_OBJ_DEF(prefix), ENTRY_TO_NAME_START(name), &CONCAT_US(tbl, prefix, __VA_ARGS__)); \ + } while (0); + +#define HOOK_QUERY(prefix, ftype, type, name, flag, ...) \ + do { \ + CONCAT_US(hook, prefix, set, __VA_ARGS__) = \ + kmpp_objdef_get_hook(KMPP_OBJ_DEF(prefix), CONCAT_STR(set, __VA_ARGS__)); \ + CONCAT_US(hook, prefix, get, __VA_ARGS__) = \ + kmpp_objdef_get_hook(KMPP_OBJ_DEF(prefix), CONCAT_STR(get, __VA_ARGS__)); \ + } while (0); + +#ifdef KMPP_OBJ_IMPL_TYPE +#define ENTRY_TO_FUNC(prefix, ftype, type, name, flag, ...) \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_get_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + else \ + *v = ((KMPP_OBJ_IMPL_TYPE*)kmpp_obj_to_entry(s))->CONCAT_DOT(__VA_ARGS__); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_set_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + else \ + ((KMPP_OBJ_IMPL_TYPE*)kmpp_obj_to_entry(s))->CONCAT_DOT(__VA_ARGS__) = v; \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, test, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s) \ + { \ + if (kmpp_obj_check(s, __FUNCTION__)) return 0; \ + return kmpp_obj_tbl_test(s, CONCAT_US(tbl, prefix, __VA_ARGS__)); \ + } + +#define STRUCT_TO_FUNC(prefix, ftype, type, name, flag, ...) \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_get_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + else \ + memcpy(v, &((KMPP_OBJ_IMPL_TYPE*)kmpp_obj_to_entry(s))->CONCAT_DOT(__VA_ARGS__), \ + sizeof(((KMPP_OBJ_IMPL_TYPE*)0)->CONCAT_DOT(__VA_ARGS__))); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_set_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + else \ + memcpy(&((KMPP_OBJ_IMPL_TYPE*)kmpp_obj_to_entry(s))->CONCAT_DOT(__VA_ARGS__), v, \ + sizeof(((KMPP_OBJ_IMPL_TYPE*)0)->CONCAT_DOT(__VA_ARGS__))); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, test, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s) \ + { \ + if (kmpp_obj_check(s, __FUNCTION__)) return 0; \ + return kmpp_obj_tbl_test(s, CONCAT_US(tbl, prefix, __VA_ARGS__)); \ + } +#else +#define ENTRY_TO_FUNC(prefix, ftype, type, name, flag, ...) \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_get_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_set_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, test, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s) \ + { \ + if (kmpp_obj_check(s, __FUNCTION__)) return 0; \ + return kmpp_obj_tbl_test(s, CONCAT_US(tbl, prefix, __VA_ARGS__)); \ + } + +#define STRUCT_TO_FUNC(prefix, ftype, type, name, flag, ...) \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_get_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(tbl, prefix, __VA_ARGS__)) \ + ret = kmpp_obj_tbl_set_##ftype(s, CONCAT_US(tbl, prefix, __VA_ARGS__), v); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, test, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s) \ + { \ + if (kmpp_obj_check(s, __FUNCTION__)) return 0; \ + return kmpp_obj_tbl_test(s, CONCAT_US(tbl, prefix, __VA_ARGS__)); \ + } +#endif + +#define EHOOK_TO_FUNC(prefix, ftype, type, name, flag, ...) \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(hook, prefix, get, __VA_ARGS__) >= 0) \ + ret = kmpp_obj_idx_run(s, CONCAT_US(hook, prefix, get, __VA_ARGS__), (void *)v, __FUNCTION__); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(hook, prefix, set, __VA_ARGS__) >= 0) \ + ret = kmpp_obj_idx_run(s, CONCAT_US(hook, prefix, set, __VA_ARGS__), (void *)&v, __FUNCTION__); \ + return ret; \ + } + +#define SHOOK_TO_FUNC(prefix, ftype, type, name, flag, ...) \ \ + rk_s32 CONCAT_US(prefix, get, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(hook, prefix, get, __VA_ARGS__) >= 0) \ + ret = kmpp_obj_idx_run(s, CONCAT_US(hook, prefix, get, __VA_ARGS__), (void *)v, __FUNCTION__); \ + return ret; \ + } \ + rk_s32 CONCAT_US(prefix, set, __VA_ARGS__)(KMPP_OBJ_INTF_TYPE s, type *v) \ + { \ + rk_s32 ret = kmpp_obj_check(s, __FUNCTION__); \ + if (ret) return ret; \ + if (CONCAT_US(hook, prefix, set, __VA_ARGS__) >= 0) \ + ret = kmpp_obj_idx_run(s, CONCAT_US(prefix, set, __VA_ARGS__), (void *)v, __FUNCTION__); \ + return ret; \ + } + +#else +#define VAL_ENTRY_TBL ENTRY_NOTHING +#define VAL_HOOK_IDX ENTRY_NOTHING +#define ENTRY_QUERY ENTRY_NOTHING +#define HOOK_QUERY ENTRY_NOTHING +#define ENTRY_TO_FUNC ENTRY_NOTHING +#define STRUCT_TO_FUNC ENTRY_NOTHING +#define EHOOK_TO_FUNC ENTRY_NOTHING +#define SHOOK_TO_FUNC ENTRY_NOTHING +#endif + +/* disable structure layout macro for global variable definition */ +#undef CFG_DEF_START +#undef CFG_DEF_END +#undef STRUCT_START +#undef STRUCT_END +#undef ENTRY_TO_NAME_START +#undef ENTRY_TO_NAME_END + +#define CFG_DEF_START(...) +#define CFG_DEF_END(...) +#define STRUCT_START(...) +#define STRUCT_END(...) +#define ENTRY_TO_NAME_START(name, ...) TO_STR(name) +#define ENTRY_TO_NAME_END(...) + +/* object definition common functions */ +static KmppObjDef KMPP_OBJ_DEF(KMPP_OBJ_NAME) = NULL; +static rk_u32 KMPP_OBJ_DEF_DEUBG(KMPP_OBJ_NAME) = 0; + +/* globla variable definitions */ +KMPP_OBJ_ENTRY_TABLE(KMPP_OBJ_NAME, VAL_ENTRY_TBL, VAL_ENTRY_TBL, + VAL_HOOK_IDX, VAL_HOOK_IDX, ENTRY_NOTHING) + +/* enable structure layout macro for objdef registration */ +#ifdef KMPP_OBJ_HIERARCHY_ENABLE +#undef CFG_DEF_START +#undef CFG_DEF_END +#undef STRUCT_START +#undef STRUCT_END +#undef ENTRY_TO_NAME_START +#undef ENTRY_TO_NAME_END + +#define CFG_DEF_START(...) \ + { \ + char str_buf[256] = {0}; \ + rk_s32 str_pos __maybe_unused = 0; \ + rk_s32 str_size __maybe_unused = sizeof(str_buf) - 1; \ + MppCfgObj __parent __maybe_unused = NULL; \ + MppCfgObj root = NULL; \ + if (once) { \ + mpp_cfg_get_object(&root, NULL, MPP_CFG_TYPE_OBJECT, NULL); \ + __parent = root; \ + } + +#define CFG_DEF_END(...) \ + { \ + if (once) { \ + kmpp_objdef_add_cfg_root(KMPP_OBJ_DEF(KMPP_OBJ_NAME), root); \ + } \ + } \ + } + +#define STRUCT_START(...) \ + { \ + rk_s32 CONCAT_US(pos, __VA_ARGS__, root) = str_pos; \ + MppCfgObj CONCAT_US(obj, __VA_ARGS__) = NULL; \ + MppCfgObj CONCAT_US(__parent, __VA_ARGS__) = __parent; \ + if (once) { \ + str_pos += snprintf(str_buf + str_pos, str_size - str_pos, \ + str_pos ? ":%s" : "%s", CONCAT_STR(__VA_ARGS__)); \ + mpp_cfg_get_object(&CONCAT_US(obj, __VA_ARGS__), CONCAT_STR(__VA_ARGS__), MPP_CFG_TYPE_OBJECT, NULL); \ + mpp_cfg_add(CONCAT_US(__parent, __VA_ARGS__), CONCAT_US(obj, __VA_ARGS__)); \ + __parent = CONCAT_US(obj, __VA_ARGS__); \ + } + +#define STRUCT_END(...) \ + str_pos = CONCAT_US(pos, __VA_ARGS__, root); \ + str_buf[str_pos] = '\0'; \ + if (__parent) \ + __parent = CONCAT_US(__parent, __VA_ARGS__); \ + } + +#define ENTRY_TO_NAME_START(name, ...) \ + ({ \ + snprintf(str_buf + str_pos, str_size - str_pos, str_pos ? ":%s" : "%s", TO_STR(name)); \ + str_buf; \ + }) + +#define ENTRY_TO_NAME_END(...) \ + str_buf[str_pos] = '\0'; + +#endif + +static void CONCAT_US(KMPP_OBJ_NAME, register)(void) +{ + rk_u32 once __maybe_unused = 1; + + mpp_env_get_u32(TO_STR(CONCAT_US(KMPP_OBJ_NAME, debug)), &KMPP_OBJ_DEF_DEUBG(KMPP_OBJ_NAME), 0); + + KMPP_OBJ_DBG_LOG("register enter\n"); + + kmpp_objdef_get(&KMPP_OBJ_DEF(KMPP_OBJ_NAME), KMPP_OBJ_PRIV_SIZE, TO_STR(KMPP_OBJ_INTF_TYPE)); + if (KMPP_OBJ_DEF(KMPP_OBJ_NAME)) { + KMPP_OBJ_DBG_LOG(TO_STR(KMPP_OBJ_NAME) " found at kernel\n"); + } else { +#ifdef KMPP_OBJ_IMPL_TYPE + rk_s32 impl_size = (sizeof(KMPP_OBJ_IMPL_TYPE) + KMPP_OBJ_EXTRA_SIZE + 3) & ~3; + rk_s32 __flag_base __maybe_unused = impl_size << 3; + rk_s32 __flag_step __maybe_unused = 0; + rk_s32 __flag_prev __maybe_unused = 0; + rk_s32 __flag_record[ELEM_FLAG_RECORD_MAX] __maybe_unused; + + kmpp_objdef_register(&KMPP_OBJ_DEF(KMPP_OBJ_NAME), KMPP_OBJ_PRIV_SIZE, + impl_size, TO_STR(KMPP_OBJ_INTF_TYPE)); + + if (!KMPP_OBJ_DEF(KMPP_OBJ_NAME)) { + mpp_loge_f(TO_STR(KMPP_OBJ_NAME) " init failed\n"); + return; + } + + KMPP_OBJ_DBG_LOG(TO_STR(KMPP_OBJ_NAME) " registered at userspace\n"); + + KMPP_OBJ_ENTRY_TABLE(KMPP_OBJ_NAME, ENTRY_TO_TRIE, ENTRY_TO_TRIE, + ENTRY_TO_TRIE, ENTRY_TO_TRIE, ENTRY_TO_TRIE) + kmpp_objdef_add_entry(KMPP_OBJ_DEF(KMPP_OBJ_NAME), NULL, NULL); + once = 0; +#else + KMPP_OBJ_DBG_LOG(TO_STR(KMPP_OBJ_NAME) " has no implementation\n"); + return; +#endif + } + +#if defined(KMPP_OBJ_MISMATCH_LOG_DISABLE) + kmpp_objdef_set_prop(KMPP_OBJ_DEF(KMPP_OBJ_NAME), "disable_mismatch_log", 1); +#endif + + KMPP_OBJ_ENTRY_TABLE(KMPP_OBJ_NAME, ENTRY_QUERY, ENTRY_QUERY, + HOOK_QUERY, HOOK_QUERY, ENTRY_NOTHING); + +#if defined(KMPP_OBJ_FUNC_INIT) + kmpp_objdef_add_init(KMPP_OBJ_DEF(KMPP_OBJ_NAME), KMPP_OBJ_FUNC_INIT); +#endif +#if defined(KMPP_OBJ_FUNC_DEINIT) + kmpp_objdef_add_deinit(KMPP_OBJ_DEF(KMPP_OBJ_NAME), KMPP_OBJ_FUNC_DEINIT); +#endif +#if defined(KMPP_OBJ_FUNC_DUMP) + kmpp_objdef_add_dump(KMPP_OBJ_DEF(KMPP_OBJ_NAME), KMPP_OBJ_FUNC_DUMP); +#endif +#if !defined(KMPP_OBJ_SHARE_DISABLE) && defined(__KERNEL__) + kmpp_objdef_share(KMPP_OBJ_DEF(KMPP_OBJ_NAME)); +#endif + KMPP_OBJ_DBG_LOG("register leave\n"); +} + +static void CONCAT_US(KMPP_OBJ_NAME, unregister)(void) +{ + KmppObjDef def = __sync_fetch_and_and(&KMPP_OBJ_DEF(KMPP_OBJ_NAME), NULL); + + KMPP_OBJ_DBG_LOG("unregister enter\n"); + kmpp_objdef_put(def); + KMPP_OBJ_DBG_LOG("unregister leave\n"); +} + +KMPP_OBJ_SGLN(KMPP_OBJ_SGLN_ID, KMPP_OBJ_NAME, CONCAT_US(KMPP_OBJ_NAME, register), CONCAT_US(KMPP_OBJ_NAME, unregister)) + +rk_s32 CONCAT_US(KMPP_OBJ_NAME, size)(void) +{ + return kmpp_objdef_get_entry_size(KMPP_OBJ_DEF(KMPP_OBJ_NAME)); +} + +rk_s32 CONCAT_US(KMPP_OBJ_NAME, get)(KMPP_OBJ_INTF_TYPE *obj) +{ + return kmpp_obj_get_f((KmppObj *)obj, KMPP_OBJ_DEF(KMPP_OBJ_NAME)); +} + +rk_s32 CONCAT_US(KMPP_OBJ_NAME, put)(KMPP_OBJ_INTF_TYPE obj) +{ + return kmpp_obj_put_f(obj); +} + +rk_s32 CONCAT_US(KMPP_OBJ_NAME, dump)(KMPP_OBJ_INTF_TYPE obj, const char *caller) +{ + if (!obj) + return rk_nok; + + return kmpp_obj_is_kobj(obj) ? kmpp_obj_kdump_f(obj, caller) : kmpp_obj_udump_f(obj, caller); +} + +KmppObjDef CONCAT_US(KMPP_OBJ_NAME, objdef)(void) +{ + return KMPP_OBJ_DEF(KMPP_OBJ_NAME); +} + +#if !defined(KMPP_OBJ_FUNC_EXPORT_DISABLE) && defined(__KERNEL__) +#include + +EXPORT_SYMBOL(CONCAT_US(KMPP_OBJ_NAME, size)); +EXPORT_SYMBOL(CONCAT_US(KMPP_OBJ_NAME, get)); +EXPORT_SYMBOL(CONCAT_US(KMPP_OBJ_NAME, put)); +EXPORT_SYMBOL(CONCAT_US(KMPP_OBJ_NAME, dump)); +#endif + +/* disable structure layout macro for access function definition */ +#undef CFG_DEF_START +#undef CFG_DEF_END +#undef STRUCT_START +#undef STRUCT_END +#undef ENTRY_TO_NAME_START +#undef ENTRY_TO_NAME_END + +#define CFG_DEF_START(...) +#define CFG_DEF_END(...) +#define STRUCT_START(...) +#define STRUCT_END(...) + +#if !defined(KMPP_OBJ_ACCESS_DISABLE) +/* object element access functions */ +KMPP_OBJ_ENTRY_TABLE(KMPP_OBJ_NAME, ENTRY_TO_FUNC, STRUCT_TO_FUNC, + EHOOK_TO_FUNC, SHOOK_TO_FUNC, ENTRY_NOTHING) + +#if !defined(KMPP_OBJ_FUNC_EXPORT_DISABLE) && defined(__KERNEL__) +#define KMPP_OBJ_EXPORT(prefix, ftype, type, name, flag, ...) \ + EXPORT_SYMBOL(CONCAT_US(prefix, get, __VA_ARGS__)); \ + EXPORT_SYMBOL(CONCAT_US(prefix, set, __VA_ARGS__)); + +#define KMPP_OBJ_EXPORT_NONE(prefix, ftype, type, name, flag, ...) + +KMPP_OBJ_ENTRY_TABLE(KMPP_OBJ_NAME, KMPP_OBJ_EXPORT, KMPP_OBJ_EXPORT, + KMPP_OBJ_EXPORT, KMPP_OBJ_EXPORT, KMPP_OBJ_EXPORT_NONE) +#undef KMPP_OBJ_EXPORT +#endif +#endif + +/* restore layout definition */ +#undef CFG_DEF_START +#undef CFG_DEF_END +#undef STRUCT_START +#undef STRUCT_END + +/* kmpp_obj ioctl function */ +#ifdef KMPP_OBJ_FUNC_IOCTL + +#define IOCTL_CTX(prefix, func, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx) \ + { \ + static rk_s32 old_cmd = GET_ARG0(-1, __VA_ARGS__); \ + static rk_s32 cmd = -1; \ + static rk_s32 once = 1; \ + KmppObjDef def = KMPP_OBJ_DEF(KMPP_OBJ_NAME); \ + if (!def) { \ + mpp_loge_f(TO_STR(KMPP_OBJ_NAME) " can not be found for ioctl\n"); \ + return rk_nok; \ + } \ + /* legacy compatible */ \ + if (old_cmd >= 0) \ + return kmpp_obj_ioctl(ctx, old_cmd, ctx, NULL, __FUNCTION__); \ + if (cmd < 0) { \ + cmd = kmpp_objdef_get_cmd(def, TO_STR(func)); \ + if (cmd < 0) { \ + mpp_loge_cf(once, TO_STR(KMPP_OBJ_NAME) " ioctl cmd %s not supported\n", TO_STR(func)); \ + once = 0; \ + return rk_nok; \ + } \ + } \ + return kmpp_obj_ioctl(ctx, cmd, NULL, NULL, __FUNCTION__); \ + } + +#define IOCTL_IN_(prefix, func, in_type, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx, in_type in) \ + { \ + KmppObjDef def = KMPP_OBJ_DEF(KMPP_OBJ_NAME); \ + static rk_s32 cmd = -1; \ + static rk_s32 once = 1; \ + if (!def) { \ + mpp_loge_f(TO_STR(KMPP_OBJ_NAME) " can not be found for ioctl\n"); \ + return rk_nok; \ + } \ + if (cmd < 0) { \ + cmd = kmpp_objdef_get_cmd(def, TO_STR(func)); \ + if (cmd < 0) { \ + mpp_loge_cf(once, TO_STR(KMPP_OBJ_NAME) " ioctl cmd %s not supported\n", TO_STR(func)); \ + once = 0; \ + return rk_nok; \ + } \ + } \ + return kmpp_obj_ioctl(ctx, cmd, in, NULL, __FUNCTION__); \ + } + +#define IOCTL_OUT(prefix, func, out_type, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx, out_type *out) \ + { \ + KmppObjDef def = KMPP_OBJ_DEF(KMPP_OBJ_NAME); \ + static rk_s32 cmd = -1; \ + static rk_s32 once = 1; \ + if (!def) { \ + mpp_loge_f(TO_STR(KMPP_OBJ_NAME) " can not be found for ioctl\n"); \ + return rk_nok; \ + } \ + if (cmd < 0) { \ + cmd = kmpp_objdef_get_cmd(def, TO_STR(func)); \ + if (cmd < 0) { \ + mpp_loge_cf(once, TO_STR(KMPP_OBJ_NAME) " ioctl cmd %s not supported\n", TO_STR(func)); \ + once = 0; \ + return rk_nok; \ + } \ + } \ + return kmpp_obj_ioctl(ctx, cmd, NULL, out, __FUNCTION__); \ + } + +#define IOCTL_IO_(prefix, func, in_type, out_type, ...) \ + rk_s32 CONCAT_US(prefix, func)(KMPP_OBJ_INTF_TYPE ctx, in_type in, out_type *out) \ + { \ + KmppObjDef def = KMPP_OBJ_DEF(KMPP_OBJ_NAME); \ + static rk_s32 cmd = -1; \ + static rk_s32 once = 1; \ + if (!def) { \ + mpp_loge_f(TO_STR(KMPP_OBJ_NAME) " can not be found for ioctl\n"); \ + return rk_nok; \ + } \ + if (cmd < 0) { \ + cmd = kmpp_objdef_get_cmd(def, TO_STR(func)); \ + if (cmd < 0) { \ + mpp_loge_cf(once, TO_STR(KMPP_OBJ_NAME) " ioctl cmd %s not supported\n", TO_STR(func)); \ + once = 0; \ + return rk_nok; \ + } \ + } \ + return kmpp_obj_ioctl(ctx, cmd, in, out, __FUNCTION__); \ + } + +#ifdef __cplusplus +extern "C" { +#endif + + KMPP_OBJ_FUNC_IOCTL(KMPP_OBJ_NAME, IOCTL_CTX, IOCTL_IN_, IOCTL_OUT, IOCTL_IO_) + +#ifdef __cplusplus +} +#endif + +#undef IOCTL_CTX +#undef IOCTL_IN_ +#undef IOCTL_OUT +#undef IOCTL_IO_ + +#endif /* KMPP_OBJ_FUNC_IOCTL */ + +#undef KMPP_OBJ_NAME +#undef KMPP_OBJ_INTF_TYPE +#undef KMPP_OBJ_IMPL_TYPE +#undef KMPP_OBJ_EXTRA_SIZE +#undef KMPP_OBJ_ENTRY_TABLE +#undef KMPP_OBJ_PRIV_SIZE +#undef KMPP_OBJ_FUNC_INIT +#undef KMPP_OBJ_FUNC_DEINIT +#undef KMPP_OBJ_FUNC_IOCTL +#undef KMPP_OBJ_FUNC_DUMP +#undef KMPP_OBJ_SGLN_ID +#undef KMPP_OBJ_FUNC_EXPORT_DISABLE +#undef KMPP_OBJ_ACCESS_DISABLE +#undef KMPP_OBJ_SHARE_DISABLE +#undef KMPP_OBJ_HIERARCHY_ENABLE +#undef KMPP_OBJ_MISMATCH_LOG_DISABLE + +/* undef tmp macro */ +#undef ENTRY_TO_TRIE +#undef ENTRY_TO_FUNC +#undef STRUCT_TO_FUNC +#undef EHOOK_TO_FUNC +#undef SHOOK_TO_FUNC +#undef VAL_ENTRY_TBL +#undef VAL_HOOK_IDX +#undef ENTRY_QUERY +#undef HOOK_QUERY +#undef MPP_CFG_TYPE_ptr +#undef MPP_CFG_TYPE_st + +#undef OBJECT_HERLPER_H + +#endif diff --git a/kmpp/base/inc/kmpp_obj_impl.h b/kmpp/base/inc/kmpp_obj_impl.h new file mode 100644 index 000000000..cbf3f559c --- /dev/null +++ b/kmpp/base/inc/kmpp_obj_impl.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_OBJ_IMPL_H +#define KMPP_OBJ_IMPL_H + +#include "kmpp_obj.h" + +rk_s32 kmpp_obj_impl_set_s8(KmppEntry *tbl, void *entry, rk_s8 val); +rk_s32 kmpp_obj_impl_get_s8(KmppEntry *tbl, void *entry, rk_s8 *val); +rk_s32 kmpp_obj_impl_set_u8(KmppEntry *tbl, void *entry, rk_u8 val); +rk_s32 kmpp_obj_impl_get_u8(KmppEntry *tbl, void *entry, rk_u8 *val); +rk_s32 kmpp_obj_impl_set_s16(KmppEntry *tbl, void *entry, rk_s16 val); +rk_s32 kmpp_obj_impl_get_s16(KmppEntry *tbl, void *entry, rk_s16 *val); +rk_s32 kmpp_obj_impl_set_u16(KmppEntry *tbl, void *entry, rk_u16 val); +rk_s32 kmpp_obj_impl_get_u16(KmppEntry *tbl, void *entry, rk_u16 *val); +rk_s32 kmpp_obj_impl_set_s32(KmppEntry *tbl, void *entry, rk_s32 val); +rk_s32 kmpp_obj_impl_get_s32(KmppEntry *tbl, void *entry, rk_s32 *val); +rk_s32 kmpp_obj_impl_set_u32(KmppEntry *tbl, void *entry, rk_u32 val); +rk_s32 kmpp_obj_impl_get_u32(KmppEntry *tbl, void *entry, rk_u32 *val); +rk_s32 kmpp_obj_impl_set_s64(KmppEntry *tbl, void *entry, rk_s64 val); +rk_s32 kmpp_obj_impl_get_s64(KmppEntry *tbl, void *entry, rk_s64 *val); +rk_s32 kmpp_obj_impl_set_u64(KmppEntry *tbl, void *entry, rk_u64 val); +rk_s32 kmpp_obj_impl_get_u64(KmppEntry *tbl, void *entry, rk_u64 *val); +rk_s32 kmpp_obj_impl_set_st(KmppEntry *tbl, void *entry, void *val); +rk_s32 kmpp_obj_impl_get_st(KmppEntry *tbl, void *entry, void *val); +rk_s32 kmpp_obj_impl_set_arr(KmppEntry *tbl, void *entry, void *val); +rk_s32 kmpp_obj_impl_get_arr(KmppEntry *tbl, void *entry, void *val); + +rk_s32 kmpp_obj_impl_set_shm(KmppEntry *tbl, void *entry, KmppShmPtr *val); +rk_s32 kmpp_obj_impl_get_shm(KmppEntry *tbl, void *entry, KmppShmPtr *val); + +rk_s32 kmpp_obj_impl_set_obj(KmppEntry *tbl, void *entry, void *val); +rk_s32 kmpp_obj_impl_get_obj(KmppEntry *tbl, void *entry, void **val); +rk_s32 kmpp_obj_impl_set_ptr(KmppEntry *tbl, void *entry, void *val); +rk_s32 kmpp_obj_impl_get_ptr(KmppEntry *tbl, void *entry, void **val); +rk_s32 kmpp_obj_impl_set_fp(KmppEntry *tbl, void *entry, void *val); +rk_s32 kmpp_obj_impl_get_fp(KmppEntry *tbl, void *entry, void **val); + +#endif /* KMPP_OBJ_IMPL_H */ \ No newline at end of file diff --git a/kmpp/base/inc/kmpp_obj_macro.h b/kmpp/base/inc/kmpp_obj_macro.h new file mode 100644 index 000000000..b74a71823 --- /dev/null +++ b/kmpp/base/inc/kmpp_obj_macro.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_OBJ_MACRO_H +#define KMPP_OBJ_MACRO_H + +#include + +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_singleton.h" + +#include "kmpp_obj.h" + +/* Compiler attributes for unused variables */ +#ifndef __maybe_unused +#define __maybe_unused __attribute__((__unused__)) +#endif + +#define TO_STR_(x) #x +#define TO_STR(x) TO_STR_(x) + +/* concat two args */ +#define CONCAT_1(a) a +#define CONCAT_2(a,b) a##b +#define CONCAT_3(a,b,c) a##b##c +#define CONCAT_4(a,b,c,d) a##b##c##d +#define CONCAT_5(a,b,c,d,e) a##b##c##d##e +#define CONCAT_6(a,b,c,d,e,f) a##b##c##d##e##f + +#define CONCAT_HELPER(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#define CONCAT(...) CONCAT_HELPER(__VA_ARGS__, CONCAT_6, CONCAT_5, CONCAT_4, CONCAT_3, CONCAT_2, CONCAT_1)(__VA_ARGS__) + +/* concat by underscore */ +#define CONCAT_US1(a) a +#define CONCAT_US2(a,b) a##_##b +#define CONCAT_US3(a,b,c) a##_##b##_##c +#define CONCAT_US4(a,b,c,d) a##_##b##_##c##_##d +#define CONCAT_US5(a,b,c,d,e) a##_##b##_##c##_##d##_##e +#define CONCAT_US6(a,b,c,d,e,f) a##_##b##_##c##_##d##_##e##_##f + +#define CONCAT_US_HELPER(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#define CONCAT_US(...) CONCAT_US_HELPER(__VA_ARGS__, CONCAT_US6, CONCAT_US5, CONCAT_US4, CONCAT_US3, CONCAT_US2, CONCAT_US1)(__VA_ARGS__) + +/* concat by dot */ +#define CONCAT_DOT1(a) a +#define CONCAT_DOT2(a,b) a.b +#define CONCAT_DOT3(a,b,c) a.b.c +#define CONCAT_DOT4(a,b,c,d) a.b.c.d +#define CONCAT_DOT5(a,b,c,d,e) a.b.c.d.e +#define CONCAT_DOT6(a,b,c,d,e,f) a.b.c.d.e.f + +#define CONCAT_DOT_HELPER(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#define CONCAT_DOT(...) CONCAT_DOT_HELPER(__VA_ARGS__, CONCAT_DOT6, CONCAT_DOT5, CONCAT_DOT4, CONCAT_DOT3, CONCAT_DOT2, CONCAT_DOT1)(__VA_ARGS__) + +/* concat to string connect with colon */ +#define CONCAT_STR1(a) TO_STR(a) +#define CONCAT_STR2(a,b) TO_STR(a:b) +#define CONCAT_STR3(a,b,c) TO_STR(a:b:c) +#define CONCAT_STR4(a,b,c,d) TO_STR(a:b:c:d) +#define CONCAT_STR5(a,b,c,d,e) TO_STR(a:b:c:d:e) +#define CONCAT_STR6(a,b,c,d,e,f) TO_STR(a:b:c:d:e:f) + +#define CONCAT_STR_HELPER(_1, _2, _3, _4, _5, _6, NAME, ...) NAME +#define CONCAT_STR(...) CONCAT_STR_HELPER(__VA_ARGS__, CONCAT_STR6, CONCAT_STR5, CONCAT_STR4, CONCAT_STR3, CONCAT_STR2, CONCAT_STR1)(__VA_ARGS__) + +/* objdef struct name */ +#define KMPP_OBJ_DEF(x) CONCAT_US(x, def) +#define KMPP_OBJ_DEF_DEUBG(x) CONCAT_US(x, debug) +#define KMPP_OBJ_DBG_LOG(...) mpp_logi_c(KMPP_OBJ_DEF_DEUBG(KMPP_OBJ_NAME), __VA_ARGS__) + +/* + * element update flag bits usage: + * bit 0 - 7 record / replay operation index bit + * bit 8 - 9 record / replay operation bit + * bit 10 - 11 update flag update operation invalid / start / update / hold + */ +typedef union ElemFlagDef_u { + rk_u32 val; + struct { + rk_u32 idx : 8; + rk_u32 slot : 4; + rk_u32 op : 4; + rk_u32 record : 1; + rk_u32 replay : 1; + rk_u32 reserved : 10; + }; +} ElemFlagDef; + +#define ELEM_FLAG_OP_SHIFT 8 +#define ELEM_FLAG_IDX_MASK ((1 << ELEM_FLAG_OP_SHIFT) - 1) + +typedef enum ElemFlagType_e { + /* element without update flag (not available) */ + ELEM_FLAG_NONE, + /* element update flag will align to new 32bit */ + ELEM_FLAG_START, + /* element flag align up to 64bit */ + ELEM_FLAG_START64, + /* element flag increase by one */ + ELEM_FLAG_OFFSET, + /* element flag increase by one */ + ELEM_FLAG_INCR, + /* element flag equal to previous one */ + ELEM_FLAG_PREV, + + ELEM_FLAG_RECORD_MAX = 16, +} ElemFlagType; + +#define FLAG_NONE ((0 & 0xff) | ((0 & 0xf) << 8) | (ELEM_FLAG_NONE << 12) | (0 << 16) | (0 << 17)) +#define FLAG_BASE(x) ((0 & 0xff) | ((0 & 0xf) << 8) | (ELEM_FLAG_START << 12) | (0 << 16) | (0 << 17)) +#define FLAG_AT(x) ((x & 0xff) | ((0 & 0xf) << 8) | (ELEM_FLAG_OFFSET << 12) | (0 << 16) | (0 << 17)) +#define FLAG_INCR ((0 & 0xff) | ((0 & 0xf) << 8) | (ELEM_FLAG_INCR << 12) | (0 << 16) | (0 << 17)) +#define FLAG_PREV ((0 & 0xff) | ((0 & 0xf) << 8) | (ELEM_FLAG_PREV << 12) | (0 << 16) | (0 << 17)) +#define FLAG_REC(s, x) ((x & 0xff) | ((s & 0xf) << 8) | (ELEM_FLAG_OFFSET << 12) | (1 << 16) | (0 << 17)) +#define FLAG_REC_INC(s) ((0 & 0xff) | ((s & 0xf) << 8) | (ELEM_FLAG_INCR << 12) | (1 << 16) | (0 << 17)) +#define FLAG_REPLAY(s) ((0 & 0xff) | ((s & 0xf) << 8) | (ELEM_FLAG_OFFSET << 12) | (0 << 16) | (1 << 17)) + +/* macro for register structure update flag type to offset */ +#define FLAG_TYPE_TO_OFFSET(name, flag, flag_str) \ + ({ \ + ElemFlagDef __flag = { .val = flag, }; \ + rk_u16 __offset; \ + switch (__flag.op) { \ + case ELEM_FLAG_START : { \ + /* NOTE: increase to next 32bit */ \ + if (__flag_prev > __flag_base) \ + __flag_base = (__flag_prev + 31) & (~31); \ + else if (__flag_prev == __flag_base) \ + __flag_base = ((__flag_base + 32) & (~31)); \ + __flag_step = 0; \ + __offset = __flag_prev = __flag_base; \ + } break; \ + case ELEM_FLAG_START64 : { \ + /* NOTE: increase to next 64bit */ \ + if (__flag_prev > __flag_base) \ + __flag_base = (__flag_prev + 63) & (~63); \ + else if (__flag_prev == __flag_base) \ + __flag_base = ((__flag_base + 64) & (~63)); \ + __flag_step = 0; \ + __offset = __flag_prev = __flag_base; \ + } break; \ + case ELEM_FLAG_OFFSET : { \ + /* define offset to the base */ \ + __offset = __flag_prev = __flag_base + __flag.idx; \ + if (__flag.idx > __flag_step) \ + __flag_step = __flag.idx; \ + } break; \ + case ELEM_FLAG_INCR : { \ + /* increase from the max step */ \ + __flag_step++; \ + __offset = __flag_prev = __flag_base + __flag_step; \ + } break; \ + case ELEM_FLAG_PREV : { \ + __offset = __flag_prev; \ + } break; \ + default : { \ + __offset = 0; \ + } break; \ + }; \ + if (__flag.record) { \ + __flag_record[__flag.slot] = __offset; \ + } \ + if (__flag.replay) { \ + __offset = __flag_record[__flag.slot]; \ + } \ + KMPP_OBJ_DBG_LOG("%-20s - (%x:%x:%02x) -> %#4x (%2d) - %s\n", \ + TO_STR(name), __flag_base, __flag_prev, __flag_step, \ + __offset, __offset ? __offset - __flag_base : 0, flag_str); \ + __offset; \ + }) + +#define ENTRY_NOTHING(prefix, ftype, type, name, flag, ...) + +#define GET_ARG0(val, ...) GET_ARG0_CHOOSER(dummy, ##__VA_ARGS__)(__VA_ARGS__) +#define GET_ARG0_1(_1) (-1) +#define GET_ARG0_2(_1, _2, ...) _1 +#define GET_ARG0_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, N, ...) GET_ARG0_##N +#define GET_ARG0_CHOOSER(...) GET_ARG0_N(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +#endif /* KMPP_OBJ_MACRO_H */ diff --git a/kmpp/base/inc/kmpp_packet.h b/kmpp/base/inc/kmpp_packet.h new file mode 100644 index 000000000..0e25b9ff4 --- /dev/null +++ b/kmpp/base/inc/kmpp_packet.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_PACKET_H +#define KMPP_PACKET_H + +#include "rk_type.h" + +#define KMPP_PACKET_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + ENTRY(prefix, s32, rk_s32, size, FLAG_NONE, size) \ + ENTRY(prefix, s32, rk_s32, length, FLAG_NONE, length) \ + ENTRY(prefix, s64, rk_s64, pts, FLAG_NONE, pts) \ + ENTRY(prefix, s64, rk_s64, dts, FLAG_NONE, dts) \ + ENTRY(prefix, u32, rk_u32, status, FLAG_NONE, status) \ + ENTRY(prefix, u32, rk_u32, temporal_id, FLAG_NONE, temporal_id) \ + STRCT(prefix, shm, KmppShmPtr, data, FLAG_NONE, data) \ + STRCT(prefix, shm, KmppShmPtr, buffer, FLAG_NONE, buffer) \ + STRCT(prefix, shm, KmppShmPtr, pos, FLAG_NONE, pos) \ + ENTRY(prefix, u32, rk_u32, flag, FLAG_NONE, flag) + +#ifdef __cplusplus +extern "C" { +#endif + +#define KMPP_OBJ_NAME kmpp_packet +#define KMPP_OBJ_INTF_TYPE KmppPacket +#define KMPP_OBJ_ENTRY_TABLE KMPP_PACKET_ENTRY_TABLE +#include "kmpp_obj_func.h" + +rk_s32 kmpp_packet_get_meta(KmppPacket packet, KmppMeta *meta); + +#ifdef __cplusplus +} +#endif + +#endif /* KMPP_PACKET_H */ \ No newline at end of file diff --git a/kmpp/base/inc/kmpp_packet_impl.h b/kmpp/base/inc/kmpp_packet_impl.h new file mode 100644 index 000000000..36e8c0db6 --- /dev/null +++ b/kmpp/base/inc/kmpp_packet_impl.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_PACKET_IMPL_H +#define KMPP_PACKET_IMPL_H + +#include "kmpp_packet.h" + +#define KMPP_PACKET_FLAG_EOS (0x00000001) +#define KMPP_PACKET_FLAG_EXTRA_DATA (0x00000002) +#define KMPP_PACKET_FLAG_INTERNAL (0x00000004) +#define KMPP_PACKET_FLAG_EXTERNAL (0x00000008) +#define KMPP_PACKET_FLAG_INTRA (0x00000010) +#define KMPP_PACKET_FLAG_PARTITION (0x00000020) +#define KMPP_PACKET_FLAG_EOI (0x00000040) + +typedef struct RingBufPool_t { + rk_u32 r_pos; + rk_u32 w_pos; + rk_u32 len; + rk_u32 use_len; + void *buf_base; + MppBuffer buf; + rk_u32 init_done; + rk_u32 min_buf_size; + rk_u32 l_r_pos; + rk_u32 l_w_pos; + rk_u32 max_use_len; +} RingBufPool; + +typedef struct RingBuf_t { + MppBuffer buf; + void *buf_start; + RingBufPool *ring_pool; + rk_u32 start_offset; + rk_u32 r_pos; + rk_u32 use_len; + rk_u32 size; + rk_u32 cir_flag; +} RingBuf; + +typedef struct KmppPacketImpl_t { + const char *name; + rk_s32 size; + rk_s32 length; + rk_s64 pts; + rk_s64 dts; + rk_u32 status; + rk_u32 flag; + rk_u32 temporal_id; + KmppShmPtr data; + KmppShmPtr pos; + KmppShmPtr buffer; + RingBuf buf; +} KmppPacketImpl; + +typedef struct KmppPacketPriv_t { + KmppMeta meta; +} KmppPacketPriv; + +#endif /* KMPP_PACKET_IMPL_H */ \ No newline at end of file diff --git a/kmpp/base/kmpp_buffer.c b/kmpp/base/kmpp_buffer.c new file mode 100644 index 000000000..a2beb2b7c --- /dev/null +++ b/kmpp/base/kmpp_buffer.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_buffer" + +#include +#include "mpp_mem.h" + +#include "mpp_list.h" +#include "mpp_log.h" +#include "mpp_lock.h" +#include "mpp_thread.h" +#include "kmpp_obj.h" +#include "kmpp_buffer_impl.h" + +#define KMPP_OBJ_NAME kmpp_buf_grp_cfg +#define KMPP_OBJ_INTF_TYPE KmppBufGrpCfg +#define KMPP_OBJ_IMPL_TYPE KmppBufGrpCfgImpl +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_BUF_GRP_CFG +#define KMPP_OBJ_ENTRY_TABLE KMPP_BUF_GRP_CFG_ENTRY_TABLE +#include "kmpp_obj_helper.h" + +KmppBufGrpCfg kmpp_buf_grp_to_cfg(KmppBufGrp grp) +{ + if (grp) { + KmppBufGrpPriv *priv = (KmppBufGrpPriv *)kmpp_obj_to_priv((KmppObj)grp); + + if (priv) + return (KmppBufGrpCfg)(priv->obj); + } + + return NULL; +} + +rk_s32 kmpp_buf_grp_impl_init(void *entry, KmppObj obj, const char *caller) +{ + KmppBufGrpPriv *priv = (KmppBufGrpPriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid grp %p without priv at %s\n", obj, caller); + return rk_nok; + } + + { + KmppBufGrpCfg cfg; + KmppShmPtr sptr; + + kmpp_obj_get_shm(obj, "cfg", &sptr); + kmpp_obj_get_by_sptr_f(&cfg, &sptr); + + mpp_assert(cfg); + + priv->obj = cfg; + priv->impl = kmpp_obj_to_entry(cfg); + } + + return rk_ok; +} + +rk_s32 kmpp_buf_grp_impl_deinit(void *entry, KmppObj obj, const char *caller) +{ + KmppBufGrpPriv *priv = (KmppBufGrpPriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid grp %p without priv at %s\n", obj, caller); + return rk_nok; + } + + if (priv->obj) { + kmpp_obj_impl_put(priv->obj, caller); + priv->obj = NULL; + } + + priv->impl = NULL; + + return rk_ok; +} + +#define KMPP_OBJ_NAME kmpp_buf_grp +#define KMPP_OBJ_INTF_TYPE KmppBufGrp +#define KMPP_OBJ_IMPL_TYPE KmppBufGrpImpl +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_BUF_GRP +#define KMPP_OBJ_FUNC_INIT kmpp_buf_grp_impl_init +#define KMPP_OBJ_FUNC_DEINIT kmpp_buf_grp_impl_deinit +#define KMPP_OBJ_FUNC_IOCTL KMPP_BUF_GRP_IOCTL_TABLE +#define KMPP_OBJ_PRIV_SIZE sizeof(KmppBufGrpPriv) +#include "kmpp_obj_helper.h" + +#define KMPP_OBJ_NAME kmpp_buf_cfg +#define KMPP_OBJ_INTF_TYPE KmppBufCfg +#define KMPP_OBJ_IMPL_TYPE KmppBufCfgImpl +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_BUF_CFG +#define KMPP_OBJ_ENTRY_TABLE KMPP_BUF_CFG_ENTRY_TABLE +#include "kmpp_obj_helper.h" + +KmppBufCfg kmpp_buffer_to_cfg(KmppBuffer buf) +{ + if (buf) { + KmppBufPriv *priv = (KmppBufPriv *)kmpp_obj_to_priv((KmppObj)buf); + + if (priv) + return (KmppBufCfg)(priv->obj); + } + + return NULL; +} + +rk_s32 kmpp_buffer_impl_init(void *entry, KmppObj obj, const char *caller) +{ + KmppBufPriv *priv = (KmppBufPriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid buf %p without priv at %s\n", obj, caller); + return rk_nok; + } + + { + KmppBufCfg cfg; + KmppShmPtr sptr; + + kmpp_obj_get_shm(obj, "cfg", &sptr); + kmpp_obj_get_by_sptr_f(&cfg, &sptr); + + mpp_assert(cfg); + + priv->obj = cfg; + priv->impl = kmpp_obj_to_entry(cfg); + } + + return rk_ok; +} + +rk_s32 kmpp_buffer_impl_deinit(void *entry, KmppObj obj, const char *caller) +{ + KmppBufPriv *priv = (KmppBufPriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid buf %p without priv at %s\n", obj, caller); + return rk_nok; + } + + if (priv->impl->fd > 0) { + close(priv->impl->fd); + priv->impl->fd = -1; + } + + if (priv->obj) { + kmpp_obj_impl_put(priv->obj, caller); + priv->obj = NULL; + } + + priv->impl = NULL; + + return rk_ok; +} + +#define KMPP_OBJ_NAME kmpp_buffer +#define KMPP_OBJ_INTF_TYPE KmppBuffer +#define KMPP_OBJ_IMPL_TYPE KmppBufferImpl +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_BUFFER +#define KMPP_OBJ_FUNC_INIT kmpp_buffer_impl_init +#define KMPP_OBJ_FUNC_DEINIT kmpp_buffer_impl_deinit +#define KMPP_OBJ_FUNC_IOCTL KMPP_BUFFER_IOCTL_TABLE +#define KMPP_OBJ_PRIV_SIZE sizeof(KmppBufPriv) +#include "kmpp_obj_helper.h" diff --git a/kmpp/base/kmpp_frame.c b/kmpp/base/kmpp_frame.c new file mode 100644 index 000000000..cf48b393f --- /dev/null +++ b/kmpp/base/kmpp_frame.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_frame" + +#include "kmpp_frame_impl.h" + +rk_s32 kmpp_frame_get_meta(KmppFrame frame, KmppMeta *meta) +{ + KmppFramePriv *priv = NULL; + KmppShmPtr sptr; + rk_s32 ret; + + if (!frame || !meta) { + mpp_loge_f("invalid frame %p meta %p\n", frame, meta); + return rk_nok; + } + + priv = (KmppFramePriv *)kmpp_obj_to_priv(frame); + if (priv->meta) { + *meta = priv->meta; + return rk_ok; + } + + kmpp_obj_get_shm(frame, "meta", &sptr); + ret = kmpp_obj_get_by_sptr_f(&priv->meta, &sptr); + if (ret) { + *meta = NULL; + mpp_loge_f("self_meta get obj by sptr failed, ret %d\n", ret); + return ret; + } + + *meta = priv->meta; + + return rk_ok; +} + +static rk_s32 kmpp_frame_impl_init(void *entry, KmppObj obj, const char *caller) +{ + KmppFramePriv *priv = (KmppFramePriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid %p without priv at %s\n", obj, caller); + return rk_nok; + } + + priv->meta = NULL; + + return rk_ok; +} + +static rk_s32 kmpp_frame_impl_deinit(void *entry, KmppObj obj, const char *caller) +{ + KmppFramePriv *priv = (KmppFramePriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid %p without priv at %s\n", obj, caller); + return rk_nok; + } + + if (priv->meta) { + kmpp_obj_impl_put(priv->meta, caller); + priv->meta = NULL; + } + + return rk_ok; +} + +#define KMPP_OBJ_NAME kmpp_frame +#define KMPP_OBJ_INTF_TYPE KmppFrame +#define KMPP_OBJ_IMPL_TYPE KmppFrameImpl +#define KMPP_OBJ_FUNC_INIT kmpp_frame_impl_init +#define KMPP_OBJ_FUNC_DEINIT kmpp_frame_impl_deinit +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_FRAME +#define KMPP_OBJ_ENTRY_TABLE KMPP_FRAME_ENTRY_TABLE +#define KMPP_OBJ_PRIV_SIZE sizeof(KmppFramePriv) +#include "kmpp_obj_helper.h" diff --git a/kmpp/base/kmpp_ioc.c b/kmpp/base/kmpp_ioc.c new file mode 100644 index 000000000..dedce54db --- /dev/null +++ b/kmpp/base/kmpp_ioc.c @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "kmpp_ioc.h" + +#define KMPP_OBJ_NAME kmpp_ioc +#define KMPP_OBJ_INTF_TYPE KmppIoc +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_IOC +#define KMPP_OBJ_ENTRY_TABLE KMPP_IOC_ENTRY_TABLE +#define KMPP_OBJ_MISMATCH_LOG_DISABLE +#include "kmpp_obj_helper.h" diff --git a/kmpp/base/kmpp_meta.c b/kmpp/base/kmpp_meta.c new file mode 100644 index 000000000..2ccf83507 --- /dev/null +++ b/kmpp/base/kmpp_meta.c @@ -0,0 +1,473 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_meta" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_lock.h" +#include "mpp_debug.h" +#include "mpp_thread.h" +#include "mpp_singleton.h" + +#include "kmpp_obj.h" +#include "kmpp_meta_impl.h" + +#define KMETA_DBG_FUNC (0x00000001) +#define KMETA_DBG_SIZE (0x00000002) +#define KMETA_DBG_SET (0x00000004) +#define KMETA_DBG_GET (0x00000008) + +#define kmeta_dbg(flag, fmt, ...) mpp_dbg_f(kmpp_meta_debug, flag, fmt, ## __VA_ARGS__) + +#define kmeta_dbg_func(fmt, ...) kmeta_dbg(KMETA_DBG_FUNC, fmt, ## __VA_ARGS__) +#define kmeta_dbg_size(fmt, ...) kmeta_dbg(KMETA_DBG_SIZE, fmt, ## __VA_ARGS__) +#define kmeta_dbg_set(fmt, ...) kmeta_dbg(KMETA_DBG_SET, fmt, ## __VA_ARGS__) +#define kmeta_dbg_get(fmt, ...) kmeta_dbg(KMETA_DBG_GET, fmt, ## __VA_ARGS__) + +#define META_ON_OPS (0x00010000) +#define META_VAL_INVALID (0x00000000) +#define META_VAL_VALID (0x00000001) +#define META_VAL_READY (0x00000002) +#define META_READY_MASK (META_VAL_VALID | META_VAL_READY) +/* property mask */ +#define META_VAL_IS_OBJ (0x00000010) +#define META_VAL_IS_SHM (0x00000020) +#define META_PROP_MASK (META_VAL_IS_OBJ | META_VAL_IS_SHM) +#define META_UNMASK_PROP(x) MPP_FETCH_AND(x, (~META_PROP_MASK)) + +#define META_KEY_TO_U64(key, type) ((rk_u64)((rk_u32)htobe32(key)) | ((rk_u64)type << 32)) + +typedef enum KmppMetaDataType_e { + /* kmpp meta data of normal data type */ + TYPE_VAL_32 = '3', + TYPE_VAL_64 = '6', + TYPE_KPTR = 'k', /* kernel pointer */ + TYPE_UPTR = 'u', /* userspace pointer */ + TYPE_SPTR = 's', /* share memory pointer */ +} KmppMetaType; + +typedef struct KmppMetaSrv_s { + pthread_mutex_t lock; + struct list_head list; + KmppObjDef def; + + rk_s32 offset_size; + rk_u32 meta_id; + rk_s32 meta_count; +} KmppMetaSrv; + +typedef struct KmppMetaPriv_s { + struct list_head list; + + KmppObj meta; + rk_u32 meta_id; +} KmppMetaPriv; + +static KmppMetaSrv *srv_meta = NULL; +static rk_u32 kmpp_meta_debug = 0; + +#define get_meta_srv(caller) \ + ({ \ + KmppMetaSrv *__tmp; \ + if (srv_meta) { \ + __tmp = srv_meta; \ + } else { \ + mpp_loge_f("kmpp meta srv not init at %s : %s\n", __FUNCTION__, caller); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +static rk_s32 kmpp_meta_impl_init(void *entry, KmppObj obj, const char *caller) +{ + KmppMetaPriv *priv = (KmppMetaPriv *)kmpp_obj_to_priv(obj); + KmppMetaSrv *srv = get_meta_srv(caller); + (void)entry; + + if (srv) { + priv->meta = obj; + INIT_LIST_HEAD(&priv->list); + + pthread_mutex_lock(&srv->lock); + list_add_tail(&priv->list, &srv->list); + priv->meta_id = srv->meta_id++; + srv->meta_count++; + pthread_mutex_unlock(&srv->lock); + } + + return rk_ok; +} + +static rk_s32 kmpp_meta_impl_deinit(void *entry, KmppObj obj, const char *caller) +{ + KmppMetaPriv *priv = (KmppMetaPriv *)kmpp_obj_to_priv(obj); + KmppMetaSrv *srv = get_meta_srv(caller); + (void)entry; + + if (srv) { + pthread_mutex_lock(&srv->lock); + list_del_init(&priv->list); + srv->meta_count--; + pthread_mutex_unlock(&srv->lock); + } + + return rk_ok; +} + +static void kmpp_meta_deinit(void) +{ + KmppMetaSrv *srv = srv_meta; + + if (!srv) { + kmeta_dbg_func("kmpp meta already deinit\n"); + return; + } + + if (srv->def) { + kmpp_objdef_put(srv->def); + srv->def = NULL; + } + + pthread_mutex_destroy(&srv->lock); + + MPP_FREE(srv); + srv_meta = NULL; +} + +static void kmpp_meta_init(void) +{ + KmppMetaSrv *srv = srv_meta; + pthread_mutexattr_t attr; + + if (srv) { + kmeta_dbg_func("kmpp meta %p already init\n", srv); + kmpp_meta_deinit(); + } + + srv = mpp_calloc(KmppMetaSrv, 1); + if (!srv) { + mpp_loge_f("kmpp meta malloc failed\n"); + return; + } + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&srv->lock, &attr); + pthread_mutexattr_destroy(&attr); + + INIT_LIST_HEAD(&srv->list); + kmpp_objdef_get(&srv->def, sizeof(KmppMetaPriv), "KmppMeta"); + if (!srv->def) { + kmeta_dbg_func("kmpp meta get objdef failed\n"); + MPP_FREE(srv); + return; + } + + kmpp_objdef_add_init(srv->def, kmpp_meta_impl_init); + kmpp_objdef_add_deinit(srv->def, kmpp_meta_impl_deinit); + + { + KmppEntry *tbl = NULL; + + kmpp_objdef_get_entry(srv->def, "size", &tbl); + srv->offset_size = tbl ? tbl->tbl.elem_offset : 0; + } + + srv_meta = srv; +} + +MPP_SINGLETON(MPP_SGLN_KMPP_META, kmpp_meta, kmpp_meta_init, kmpp_meta_deinit) + +static void *meta_key_to_addr(KmppObj meta, KmppMetaKey key, KmppMetaType type) +{ + if (meta) { + KmppMetaSrv *srv = srv_meta; + rk_u64 val = META_KEY_TO_U64(key, type); + KmppEntry *tbl = NULL; + + kmpp_objdef_get_entry(srv->def, (const char *)&val, &tbl); + if (tbl) + return ((rk_u8 *)kmpp_obj_to_entry(meta)) + tbl->tbl.elem_offset; + } + + return NULL; +} + +static rk_s32 meta_inc_size(KmppObj meta, rk_s32 val, const char *caller) +{ + rk_s32 ret = 0; + + if (meta && srv_meta) { + void *entry = kmpp_obj_to_entry(meta); + rk_s32 offset = srv_meta->offset_size; + + if (entry && offset) { + rk_s32 *p = (rk_s32 *)((rk_u8 *)entry + offset); + + ret = MPP_FETCH_ADD(p, val); + kmeta_dbg_size("meta %p size %d -> %d at %s\n", + meta, p[0], ret, caller); + } + } + + return ret; +} + +static rk_s32 meta_dec_size(KmppObj meta, rk_s32 val, const char *caller) +{ + rk_s32 ret = 0; + + if (meta && srv_meta) { + void *entry = kmpp_obj_to_entry(meta); + rk_s32 offset = srv_meta->offset_size; + + if (entry && offset) { + rk_s32 *p = (rk_s32 *)((rk_u8 *)entry + offset); + + ret = MPP_FETCH_SUB(p, val); + kmeta_dbg_size("meta %p size %d -> %d at %s\n", + meta, p[0], ret, caller); + } + } + + return ret; +} + +rk_s32 kmpp_meta_get(KmppMeta *meta, const char *caller) +{ + KmppMetaSrv *srv = get_meta_srv(caller); + + if (!srv) + return rk_nok; + + return kmpp_obj_get(meta, srv->def, caller); +} + +rk_s32 kmpp_meta_put(KmppMeta meta, const char *caller) +{ + KmppMetaSrv *srv = get_meta_srv(caller); + + if (!srv) + return rk_nok; + + return kmpp_obj_put(meta, caller); +} + +rk_s32 kmpp_meta_size(KmppMeta meta, const char *caller) +{ + return meta_inc_size(meta, 0, caller); +} + +rk_s32 kmpp_meta_dump(KmppMeta meta, const char *caller) +{ + return kmpp_obj_udump_f(meta, caller); +} + +rk_s32 kmpp_meta_dump_all(const char *caller) +{ + KmppMetaSrv *srv = get_meta_srv(caller); + + if (srv) { + KmppMeta meta = NULL; + KmppMetaPriv *pos, *n; + + pthread_mutex_lock(&srv->lock); + list_for_each_entry_safe(pos, n, &srv->list, KmppMetaPriv, list) { + meta = pos->meta; + mpp_logi("meta %p:%d size %d\n", meta, pos->meta_id, + kmpp_meta_size(meta, caller)); + kmpp_meta_dump(meta, caller); + } + } + + return rk_ok; +} + +#define KMPP_META_ACCESSOR(func_type, arg_type, key_type, key_field) \ + rk_s32 kmpp_meta_set_##func_type(KmppMeta meta, KmppMetaKey key, arg_type val) \ + { \ + KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \ + if (!meta_val) \ + return rk_nok; \ + if (MPP_BOOL_CAS(&meta_val->state, META_VAL_INVALID, META_VAL_VALID)) \ + meta_inc_size(meta, 1, __FUNCTION__); \ + meta_val->key_field = val; \ + MPP_FETCH_OR(&meta_val->state, META_VAL_READY); \ + return rk_ok; \ + } \ + rk_s32 kmpp_meta_get_##func_type(KmppMeta meta, KmppMetaKey key, arg_type *val) \ + { \ + KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \ + if (!meta_val) \ + return rk_nok; \ + if (MPP_BOOL_CAS(&meta_val->state, META_READY_MASK, META_VAL_INVALID)) { \ + if (val) *val = meta_val->key_field; \ + meta_dec_size(meta, 1, __FUNCTION__); \ + return rk_ok; \ + } \ + return rk_nok; \ + } \ + rk_s32 kmpp_meta_get_##func_type##_d(KmppMeta meta, KmppMetaKey key, arg_type *val, arg_type def) \ + { \ + KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \ + if (!meta_val) \ + return rk_nok; \ + if (MPP_BOOL_CAS(&meta_val->state, META_READY_MASK, META_VAL_INVALID)) { \ + if (val) *val = meta_val->key_field; \ + meta_dec_size(meta, 1, __FUNCTION__); \ + } else { \ + if (val) *val = def; \ + } \ + return rk_ok; \ + } + +KMPP_META_ACCESSOR(s32, rk_s32, TYPE_VAL_32, val_s32) +KMPP_META_ACCESSOR(s64, rk_s64, TYPE_VAL_64, val_s64) +KMPP_META_ACCESSOR(ptr, void *, TYPE_UPTR, val_ptr) + +rk_s32 kmpp_meta_set_obj(KmppMeta meta, KmppMetaKey key, KmppObj val) +{ + KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR); + + if (!meta_obj) + return rk_nok; + + if (MPP_BOOL_CAS(&meta_obj->state, META_VAL_INVALID, META_VAL_VALID)) + meta_inc_size(meta, 1, __FUNCTION__); + + { + KmppShmPtr *ptr = kmpp_obj_to_shm(val); + + if (ptr) { + meta_obj->val_shm.uaddr = ptr->uaddr; + meta_obj->val_shm.kaddr = ptr->kaddr;; + MPP_FETCH_OR(&meta_obj->state, META_VAL_IS_SHM); + } else { + meta_obj->val_shm.uaddr = 0; + meta_obj->val_shm.kptr = val; + MPP_FETCH_AND(&meta_obj->state, ~META_VAL_IS_SHM); + } + } + MPP_FETCH_OR(&meta_obj->state, META_VAL_READY); + return rk_ok; +} + +rk_s32 kmpp_meta_get_obj(KmppMeta meta, KmppMetaKey key, KmppObj *val) +{ + KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR); + + if (!meta_obj) + return rk_nok; + + META_UNMASK_PROP(&meta_obj->state); + if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) { + if (val) + *val = meta_obj->val_shm.kptr; + meta_dec_size(meta, 1, __FUNCTION__); + return rk_ok; + } + + return rk_nok; +} + +rk_s32 kmpp_meta_get_obj_d(KmppMeta meta, KmppMetaKey key, KmppObj *val, KmppObj def) +{ + KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR); + + if (!meta_obj) + return rk_nok; + + META_UNMASK_PROP(&meta_obj->state); + if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) { + if (val) + *val = meta_obj->val_shm.kptr; + meta_dec_size(meta, 1, __FUNCTION__); + } else { + if (val) + *val = def ? def : NULL; + } + + return rk_ok; +} + +rk_s32 kmpp_meta_set_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr) +{ + KmppMetaObj *meta_obj = (KmppMetaObj *)meta_key_to_addr(meta, key, TYPE_SPTR); + + if (!meta_obj) + return rk_nok; + + if (MPP_BOOL_CAS(&meta_obj->state, META_VAL_INVALID, META_VAL_VALID)) + meta_inc_size(meta, 1, __FUNCTION__); + + if (sptr) { + meta_obj->val_shm.uaddr = sptr->uaddr; + meta_obj->val_shm.kaddr = sptr->kaddr; + } else { + meta_obj->val_shm.uaddr = 0; + meta_obj->val_shm.kptr = 0; + } + + if (sptr && sptr->uaddr) + MPP_FETCH_OR(&meta_obj->state, META_VAL_IS_SHM); + else + MPP_FETCH_AND(&meta_obj->state, ~META_VAL_IS_SHM); + + MPP_FETCH_OR(&meta_obj->state, META_VAL_READY); + + return rk_ok; +} + +rk_s32 kmpp_meta_get_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr) +{ + KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR); + + if (!meta_obj) + return rk_nok; + + META_UNMASK_PROP(&meta_obj->state); + if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) { + if (sptr) { + sptr->uaddr = meta_obj->val_shm.uaddr; + sptr->kaddr = meta_obj->val_shm.kaddr; + } + meta_dec_size(meta, 1, __FUNCTION__); + return rk_ok; + } + return rk_nok; +} + +rk_s32 kmpp_meta_get_shm_d(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr, KmppShmPtr *def) +{ + KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR); + + if (!meta_obj) + return rk_nok; + + META_UNMASK_PROP(&meta_obj->state); + if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) { + if (sptr) { + sptr->uaddr = meta_obj->val_shm.uaddr; + sptr->kaddr = meta_obj->val_shm.kaddr; + } + meta_dec_size(meta, 1, __FUNCTION__); + } else { + if (sptr) { + if (def) { + sptr->uaddr = def->uaddr; + sptr->kaddr = def->kaddr; + } else { + sptr->uaddr = 0; + sptr->kaddr = 0; + } + } + } + + return rk_ok; +} diff --git a/kmpp/base/kmpp_obj.c b/kmpp/base/kmpp_obj.c new file mode 100644 index 000000000..1b6874189 --- /dev/null +++ b/kmpp/base/kmpp_obj.c @@ -0,0 +1,2297 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_obj" + +#include + +#include +#include + +#include "mpp_env.h" +#include "mpp_list.h" +#include "mpp_lock.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_mem_pool.h" +#include "mpp_singleton.h" + +#include "mpp_trie.h" +#include "mpp_cfg_io.h" +#include "kmpp_ioc.h" +#include "kmpp_obj_impl.h" + +#define KMPP_SHM_IOC_MAGIC 'm' +#define KMPP_SHM_IOC_QUERY_INFO _IOW(KMPP_SHM_IOC_MAGIC, 1, unsigned int) +#define KMPP_SHM_IOC_RELEASE_INFO _IOW(KMPP_SHM_IOC_MAGIC, 2, unsigned int) +#define KMPP_SHM_IOC_GET_SHM _IOW(KMPP_SHM_IOC_MAGIC, 3, unsigned int) +#define KMPP_SHM_IOC_PUT_SHM _IOW(KMPP_SHM_IOC_MAGIC, 4, unsigned int) +#define KMPP_SHM_IOC_DUMP _IOW(KMPP_SHM_IOC_MAGIC, 5, unsigned int) + +#define KMPP_IOCTL_IOC_MAGIC 'i' +#define KMPP_IOCTL_IOC_QUERY_INFO _IOW(KMPP_IOCTL_IOC_MAGIC, 1, unsigned int) +#define KMPP_IOCTL_IOC_PROC _IOW(KMPP_IOCTL_IOC_MAGIC, 2, unsigned int) + +#define OBJ_DBG_FLOW (0x00000001) +#define OBJ_DBG_SHARE (0x00000002) +#define OBJ_DBG_ENTRY (0x00000004) +#define OBJ_DBG_POOL (0x00000008) +#define OBJ_DBG_IOCTL (0x00000010) +#define OBJ_DBG_UPDATE (0x00000020) +#define OBJ_DBG_SET (0x00000040) +#define OBJ_DBG_GET (0x00000080) + +#define obj_dbg(flag, fmt, ...) mpp_dbg(kmpp_obj_debug, flag, fmt, ## __VA_ARGS__) + +#define obj_dbg_flow(fmt, ...) obj_dbg(OBJ_DBG_FLOW, fmt, ## __VA_ARGS__) +#define obj_dbg_share(fmt, ...) obj_dbg(OBJ_DBG_SHARE, fmt, ## __VA_ARGS__) +#define obj_dbg_entry(fmt, ...) obj_dbg(OBJ_DBG_ENTRY, fmt, ## __VA_ARGS__) +#define obj_dbg_pool(fmt, ...) obj_dbg(OBJ_DBG_POOL, fmt, ## __VA_ARGS__) +#define obj_dbg_ioctl(fmt, ...) obj_dbg(OBJ_DBG_IOCTL, fmt, ## __VA_ARGS__) +#define obj_dbg_update(fmt, ...) obj_dbg(OBJ_DBG_UPDATE, fmt, ## __VA_ARGS__) +#define obj_dbg_set(fmt, ...) obj_dbg(OBJ_DBG_SET, fmt, ## __VA_ARGS__) +#define obj_dbg_get(fmt, ...) obj_dbg(OBJ_DBG_GET, fmt, ## __VA_ARGS__) + +#define U64_TO_PTR(ptr) ((void *)(intptr_t)(ptr)) + +#define ENTRY_TO_PTR(tbl, entry) (((char *)entry) + tbl->tbl.elem_offset) +#define ENTRY_TO_s8_PTR(tbl, entry) ((rk_s8 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_u8_PTR(tbl, entry) ((rk_u8 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_s16_PTR(tbl, entry) ((rk_s16 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_u16_PTR(tbl, entry) ((rk_u16 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_s32_PTR(tbl, entry) ((rk_s32 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_u32_PTR(tbl, entry) ((rk_u32 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_s64_PTR(tbl, entry) ((rk_s64 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_u64_PTR(tbl, entry) ((rk_u64 *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_obj_PTR(tbl, entry) ((KmppObj *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_ptr_PTR(tbl, entry) ((void **)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_fp_PTR(tbl, entry) ((void **)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_st_PTR(tbl, entry) ((void *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_shm_PTR(tbl, entry) ((void *)ENTRY_TO_PTR(tbl, entry)) +#define ENTRY_TO_arr_PTR(tbl, entry) ((void *)ENTRY_TO_PTR(tbl, entry)) + +/* 32bit unsigned long pointer */ +#define ELEM_FLAG_U32_POS(offset) (((offset) & (~31)) / 8) +#define ELEM_FLAG_BIT_POS(offset) ((offset) & 31) +#define ENTRY_TO_FLAG_PTR(e, entry) ((rk_ul *)((rk_u8 *)entry + ELEM_FLAG_U32_POS(e->tbl.flag_offset))) + +#define ENTRY_SET_FLAG(e, entry) \ + *ENTRY_TO_FLAG_PTR(e, entry) |= 1ul << (ELEM_FLAG_BIT_POS(e->tbl.flag_offset)) + +#define ENTRY_CLR_FLAG(e, entry) \ + *ENTRY_TO_FLAG_PTR(e, entry) &= ~(1ul << (ELEM_FLAG_BIT_POS(e->tbl.flag_offset))) + +#define ENTRY_TEST_FLAG(e, entry) \ + ((*ENTRY_TO_FLAG_PTR(e, entry) & 1ul << (ELEM_FLAG_BIT_POS(e->tbl.flag_offset))) != 0) ? 1 : 0 + +typedef struct KmppShmReq_t { + /* shm_name - NULL name addresss for shm direct allocation */ + __u64 shm_name; + /* shm_size - share memory size for shm direct allocation */ + __u32 shm_size; + /* shm_flag - share memory allocation flags */ + __u32 shm_flag; +} KmppShmReq; + +/* kernel object share memory get / put ioctl data */ +typedef struct KmppObjIocArg_t { + /* address array element count */ + __u32 count; + + /* flag for batch operation */ + __u32 flag; + + /* + * at KMPP_SHM_IOC_GET_SHM + * name_uaddr - kernel object name in userspace address + * obj_sptr - kernel object userspace / kernel address of KmppShmPtr + * + * at KMPP_SHM_IOC_PUT_SHM + * obj_sptr - kernel object userspace / kernel address of KmppShmPtr + */ + union { + __u64 name_uaddr[0]; + /* ioctl object userspace / kernel address */ + KmppShmPtr obj_sptr[0]; + KmppShmReq shm_req[0]; + }; +} KmppObjIocArg; + +typedef struct KmppObjDefImpl_t { + /* userspace objdef */ + MppCfgObj cfg; + MppMemPool pool; + /* object define from kernel or userspace */ + rk_s32 is_kobj; + KmppObjInit init; + KmppObjDeinit deinit; + KmppObjPreset preset; + KmppObjDump dump; + + /* comment data of userspace / kernel objdef */ + MppTrie trie; + MppTrie ioctl; + /* objdef index in kernel (/dev/kmpp_objs) */ + rk_s32 index; + /* objdef set index in objdefset for ioctl */ + rk_s32 defs_idx; + rk_s32 ref_cnt; + /* private data size for priv in KmppObjImpl */ + rk_s32 priv_size; + /* entry size for entry in KmppObjImpl */ + rk_s32 entry_size; + rk_s32 flag_max_pos; + rk_s32 flag_offset; + /* entry size + flag size for entry in KmppObjImpl */ + rk_s32 buf_size; + /* all size for sizeof(KmppObjImpl) + priv_size + entry_size + flag_size */ + rk_s32 all_size; + + /* properties */ + rk_s32 disable_mismatch_log; + + const char *name; +} KmppObjDefImpl; + +typedef struct KmppObjImpl_t { + const char *name; + /* class infomation link */ + KmppObjDefImpl *def; + /* trie for fast access */ + MppTrie trie; + void *priv; + KmppShmPtr *shm; + void *entry; +} KmppObjImpl; + +typedef struct KmppKtrieInfo_t { + rk_s32 fd; + MppTrie trie; + void *root; +} KmppKtrieInfo; + +typedef struct KmppObjs_t { + KmppKtrieInfo obj; + KmppKtrieInfo ioc; + rk_s32 count; + rk_s32 entry_offset; + rk_s32 priv_offset; + rk_s32 name_offset; + KmppObjDefImpl defs[0]; +} KmppObjs; + +static rk_u32 kmpp_obj_debug = 0; +static KmppObjs *objs = NULL; + +#define get_objs(caller) \ +({ \ + KmppObjs *__tmp; \ + if (objs) { \ + __tmp = objs; \ + } else { \ + obj_dbg_flow("kmpp objs srv not init at %s\n", caller); \ + __tmp = NULL; \ + } \ + __tmp; \ +}) + +#define get_objs_f() get_objs(__FUNCTION__) + +const char *strof_elem_type(ElemType type) +{ + static const char *ELEM_TYPE_names[] = { + [ELEM_TYPE_s8] = "s8", + [ELEM_TYPE_u8] = "u8", + [ELEM_TYPE_s16] = "s16", + [ELEM_TYPE_u16] = "u16", + [ELEM_TYPE_s32] = "s32", + [ELEM_TYPE_u32] = "u32", + [ELEM_TYPE_s64] = "s64", + [ELEM_TYPE_u64] = "u64", + [ELEM_TYPE_ptr] = "ptr", + [ELEM_TYPE_st] = "struct", + [ELEM_TYPE_arr] = "array", + [ELEM_TYPE_shm] = "shm_ptr", + [ELEM_TYPE_kobj] = "kobj", + [ELEM_TYPE_kptr] = "kptr", + [ELEM_TYPE_kfp] = "kfunc_ptr", + [ELEM_TYPE_uobj] = "uobj", + [ELEM_TYPE_uptr] = "uptr", + [ELEM_TYPE_ufp] = "ufunc_ptr", + }; + static const char *invalid_type_str = "invalid"; + + if (type >= ELEM_TYPE_BUTT) + return invalid_type_str; + + return ELEM_TYPE_names[type] ? ELEM_TYPE_names[type] : invalid_type_str; +} + +#define MPP_OBJ_ACCESS_IMPL(type, base_type, log_str) \ + rk_s32 kmpp_obj_impl_set_##type(KmppEntry *tbl, void *entry, base_type val) \ + { \ + base_type *dst = ENTRY_TO_##type##_PTR(tbl, entry); \ + base_type old = dst[0]; \ + dst[0] = val; \ + if (!tbl->tbl.flag_offset) { \ + obj_dbg_set("%p + %x set " #type " change " #log_str " -> " #log_str "\n", entry, tbl->tbl.elem_offset, old, val); \ + } else { \ + if (old != val) { \ + obj_dbg_set("%p + %x set " #type " update " #log_str " -> " #log_str " flag %d\n", \ + entry, tbl->tbl.elem_offset, old, val, tbl->tbl.flag_offset); \ + ENTRY_SET_FLAG(tbl, entry); \ + } else { \ + obj_dbg_set("%p + %x set " #type " keep " #log_str "\n", entry, tbl->tbl.elem_offset, old); \ + } \ + } \ + return rk_ok; \ + } \ + rk_s32 kmpp_obj_impl_get_##type(KmppEntry *tbl, void *entry, base_type *val) \ + { \ + if (tbl && tbl->tbl.elem_size) { \ + base_type *src = ENTRY_TO_##type##_PTR(tbl, entry); \ + obj_dbg_get("%p + %x get " #type " value " #log_str "\n", entry, tbl->tbl.elem_offset, src[0]); \ + val[0] = src[0]; \ + return rk_ok; \ + } \ + return rk_nok; \ + } +MPP_OBJ_ACCESS_IMPL(s8, rk_s8, % d) +MPP_OBJ_ACCESS_IMPL(u8, rk_u8, % u) +MPP_OBJ_ACCESS_IMPL(s16, rk_s16, % d) +MPP_OBJ_ACCESS_IMPL(u16, rk_u16, % u) +MPP_OBJ_ACCESS_IMPL(s32, rk_s32, % d) +MPP_OBJ_ACCESS_IMPL(u32, rk_u32, % u) +MPP_OBJ_ACCESS_IMPL(s64, rk_s64, % #llx) +MPP_OBJ_ACCESS_IMPL(u64, rk_u64, % #llx) +MPP_OBJ_ACCESS_IMPL(obj, KmppObj, % p) +MPP_OBJ_ACCESS_IMPL(ptr, void *, % p) +MPP_OBJ_ACCESS_IMPL(fp, void *, % p) + +#define MPP_OBJ_STRUCT_ACCESS_IMPL(type, base_type, log_str) \ + rk_s32 kmpp_obj_impl_set_##type(KmppEntry *tbl, void *entry, base_type *val) \ + { \ + void *dst = ENTRY_TO_##type##_PTR(tbl, entry); \ + if (!tbl->tbl.flag_offset) { \ + /* simple copy */ \ + obj_dbg_set("%p + %x set " #type " size %d change %p -> %p\n", entry, tbl->tbl.elem_offset, tbl->tbl.elem_size, dst, val); \ + memcpy(dst, val, tbl->tbl.elem_size); \ + return rk_ok; \ + } \ + /* copy with flag check and updata */ \ + if (memcmp(dst, val, tbl->tbl.elem_size)) { \ + obj_dbg_set("%p + %x set " #type " size %d update %p -> %p flag %d\n", \ + entry, tbl->tbl.elem_offset, tbl->tbl.elem_size, dst, val, tbl->tbl.flag_offset); \ + memcpy(dst, val, tbl->tbl.elem_size); \ + ENTRY_SET_FLAG(tbl, entry); \ + } else { \ + obj_dbg_set("%p + %x set " #type " size %d keep %p\n", entry, tbl->tbl.elem_offset, tbl->tbl.elem_size, dst); \ + } \ + return rk_ok; \ + } \ + rk_s32 kmpp_obj_impl_get_##type(KmppEntry *tbl, void *entry, base_type *val) \ + { \ + if (tbl && tbl->tbl.elem_size) { \ + void *src = ENTRY_TO_##type##_PTR(tbl, entry); \ + obj_dbg_get("%p + %x get " #type " size %d value " #log_str "\n", entry, tbl->tbl.elem_offset, tbl->tbl.elem_size, src); \ + memcpy(val, src, tbl->tbl.elem_size); \ + return rk_ok; \ + } \ + return rk_nok; \ + } + +MPP_OBJ_STRUCT_ACCESS_IMPL(st, void, % p) +MPP_OBJ_STRUCT_ACCESS_IMPL(shm, KmppShmPtr, % p) +MPP_OBJ_STRUCT_ACCESS_IMPL(arr, void, % p) + +static rk_s32 kmpp_ktrie_get(KmppKtrieInfo *info, const char *path, rk_ul cmd) +{ + rk_s32 fd = open(path, O_RDWR); + MppTrie trie = NULL; + rk_u64 uaddr = 0; + void *root; + rk_s32 ret; + + info->fd = fd; + info->trie = NULL; + info->root = NULL; + + if (fd < 0) { + obj_dbg_flow("%s open failed ret fd %d\n", path, fd); + return rk_nok; + } + + ret = ioctl(fd, cmd, &uaddr); + if (ret < 0) { + obj_dbg_flow("%s ioctl failed ret %d\n", path, ret); + goto __ret; + } + + root = (void *)(intptr_t)uaddr; + obj_dbg_share("query fd %d root %p from kernel\n", fd, root); + + ret = mpp_trie_init_by_root(&trie, root); + if (ret || !trie) { + mpp_loge_f("init trie by root failed ret %d\n", ret); + goto __ret; + } + + if (kmpp_obj_debug & OBJ_DBG_SHARE) + mpp_trie_dump_f(trie); + + info->trie = trie; + info->root = root; + +__ret: + return rk_ok; +} + +rk_s32 kmpp_ktrie_put(KmppKtrieInfo *info) +{ + if (info->fd >= 0) { + close(info->fd); + info->fd = -1; + } + + if (info->trie) { + mpp_trie_deinit(info->trie); + info->trie = NULL; + } + + info->root = NULL; + + return rk_ok; +} + +static void kmpp_objs_deinit(void) +{ + KmppObjs *p = MPP_FETCH_AND(&objs, NULL); + + obj_dbg_flow("kmpp_objs_deinit objs %p\n", p); + + if (p) { + rk_s32 i; + + for (i = 0; i < p->count; i++) { + KmppObjDefImpl *impl = &p->defs[i]; + + if (impl->pool) { + mpp_mem_pool_deinit_f(impl->pool); + impl->pool = NULL; + } + + if (impl->trie) { + mpp_trie_deinit(impl->trie); + impl->trie = NULL; + } + + if (impl->ioctl) { + mpp_trie_deinit(impl->ioctl); + impl->ioctl = NULL; + } + } + + kmpp_ktrie_put(&p->obj); + kmpp_ktrie_put(&p->ioc); + + mpp_free(p); + } +} + +static void kmpp_objs_init(void) +{ + static const char *dev_obj = "/dev/kmpp_objs"; + static const char *dev_ioc = "/dev/kmpp_ioctl"; + KmppObjs *p = objs; + KmppKtrieInfo obj; + KmppKtrieInfo ioc; + void *root = NULL; + MppTrie trie = NULL; + MppTrieInfo *info; + rk_s32 offset; + rk_s32 count; + rk_s32 ret; + rk_s32 i; + + if (p) { + obj_dbg_flow("objs already inited %p\n", p); + kmpp_objs_deinit(); + p = NULL; + } + + mpp_env_get_u32("kmpp_obj_debug", &kmpp_obj_debug, 0); + + /* skip kmpp_ioctls failure and call ioc init first to avoid deinit crash */ + kmpp_ktrie_get(&ioc, dev_ioc, KMPP_IOCTL_IOC_QUERY_INFO); + + ret = kmpp_ktrie_get(&obj, dev_obj, KMPP_SHM_IOC_QUERY_INFO); + if (ret < 0) + goto __failed; + + trie = obj.trie; + root = obj.root; + info = mpp_trie_get_info(trie, "__count"); + count = info ? *(rk_s32 *)mpp_trie_info_ctx(info) : 0; + + p = mpp_calloc_size(KmppObjs, sizeof(KmppObjs) + sizeof(KmppObjDefImpl) * count); + if (!p) { + mpp_loge_f("alloc objs failed\n"); + goto __failed; + } + + p->obj = obj; + p->ioc = ioc; + p->count = count; + + info = mpp_trie_get_info(trie, "__offset"); + offset = info ? *(rk_s32 *)mpp_trie_info_ctx(info) : 0; + p->entry_offset = offset; + info = mpp_trie_get_info(trie, "__priv"); + offset = info ? *(rk_s32 *)mpp_trie_info_ctx(info) : 0; + p->priv_offset = offset; + info = mpp_trie_get_info(trie, "__name_offset"); + offset = info ? *(rk_s32 *)mpp_trie_info_ctx(info) : 0; + p->name_offset = offset; + + obj_dbg_share("count %d object offsets - priv %d name %d entry %d\n", count, + p->priv_offset, p->name_offset, p->entry_offset); + + info = mpp_trie_get_info_first(trie); + + for (i = 0; i < count && info; i++) { + KmppObjDefImpl *impl = &p->defs[i]; + const char *name = mpp_trie_info_name(info); + MppTrie trie_objdef = NULL; + MppTrieInfo *info_objdef; + + offset = *(rk_s32 *)mpp_trie_info_ctx(info); + ret = mpp_trie_init_by_root(&trie_objdef, root + offset); + if (!trie_objdef) { + mpp_loge_f("init %d:%d obj trie failed\n", count, i); + break; + } + + impl->trie = trie_objdef; + + info_objdef = mpp_trie_get_info(trie_objdef, "__index"); + impl->index = info_objdef ? *(rk_s32 *)mpp_trie_info_ctx(info_objdef) : -1; + impl->defs_idx = info->index; + info_objdef = mpp_trie_get_info(trie_objdef, "__size"); + impl->entry_size = info_objdef ? *(rk_s32 *)mpp_trie_info_ctx(info_objdef) : 0; + impl->name = name; + impl->is_kobj = 1; + + info = mpp_trie_get_info_next(trie, info); + obj_dbg_share("%2d:%2d - %s offset %d entry_size %d\n", + count, i, name, offset, impl->entry_size); + + obj_dbg_flow("objdef %-16s in kernel size %4d\n", + name, impl->entry_size); + + /* check ioctl functions */ + if (ioc.root) { + MppTrieInfo *ioc_info = mpp_trie_get_info(ioc.trie, name); + + if (ioc_info) { + rk_s32 ioc_offset = *(rk_s32 *)mpp_trie_info_ctx(ioc_info); + + mpp_trie_init_by_root(&impl->ioctl, ioc.root + ioc_offset); + if (impl->ioctl) + obj_dbg_flow("objdef %-16s in kernel support ioctl %d\n", + name, mpp_trie_get_info_count(impl->ioctl)); + } + } + } + + objs = p; + + return; + +__failed: + kmpp_ktrie_put(&obj); + kmpp_ktrie_put(&ioc); +} + +MPP_SINGLETON(MPP_SGLN_KOBJ, kmpp_obj, kmpp_objs_init, kmpp_objs_deinit) + +rk_s32 kmpp_objdef_put(KmppObjDef def) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + rk_s32 ret = rk_nok; + + if (impl) { + rk_s32 release = 0; + + if (impl->is_kobj) { + impl->ref_cnt--; + if (!impl->ref_cnt) + release = 1; + else + mpp_loge_f("objdef %-16s non-zero ref_cnt %d\n", + impl->name, impl->ref_cnt); + } else { + if (impl->cfg) { + mpp_cfg_put_all(impl->cfg); + impl->cfg = NULL; + } + release = 1; + } + + if (release) { + if (impl->pool) { + mpp_mem_pool_deinit_f(impl->pool); + impl->pool = NULL; + } + + if (impl->trie) { + mpp_trie_deinit(impl->trie); + impl->trie = NULL; + } + } + + if (!impl->is_kobj) + mpp_free(impl); + + ret = rk_ok; + } + + return ret; +} + +rk_s32 kmpp_objdef_register(KmppObjDef *def, rk_s32 priv_size, rk_s32 size, const char *name) +{ + KmppObjDefImpl *impl = NULL; + rk_s32 name_len; + rk_s32 name_buf_size; + char *buf; + + if (!def || !name || size <= 0) { + mpp_loge_f("invalid param def %p size %d name %p\n", def, size, name); + return rk_nok; + } + + *def = NULL; + name_len = strlen(name); + name_buf_size = MPP_ALIGN(name_len + 1, sizeof(rk_s32)); + impl = mpp_calloc_size(KmppObjDefImpl, sizeof(KmppObjDefImpl) + name_buf_size); + if (!impl) { + mpp_loge_f("alloc objdef size %d failed\n", sizeof(KmppObjDefImpl) + name_buf_size); + return rk_nok; + } + + buf = (char *)(impl + 1); + memcpy(buf, name, name_len); + buf[name_len] = '\0'; + impl->name = buf; + impl->priv_size = MPP_ALIGN(priv_size, sizeof(void *)); + impl->entry_size = size; + impl->buf_size = size + sizeof(KmppObjImpl); + impl->ref_cnt = 1; + + obj_dbg_flow("objdef %-16s registered size %4d\n", name, size, impl); + + *def = impl; + + return rk_ok; +} + +rk_s32 kmpp_objdef_find(KmppObjDef *def, const char *name) +{ + KmppObjs *p = get_objs_f(); + MppTrieInfo *info = NULL; + + if (!def || !name) { + mpp_loge_f("invalid param def %p name %p objs %p\n", def, name, p); + return rk_nok; + } + + *def = NULL; + + if (!p) + return rk_nok; + + info = mpp_trie_get_info(p->obj.trie, name); + if (!info) { + obj_dbg_flow("objdef %-16s can not be found in kernel\n", name); + return rk_nok; + } + + if (p->count > 0 && info->index < (RK_U32)p->count) { + *def = &p->defs[info->index]; + return rk_ok; + } + + mpp_loge_f("objdef %-16s is found but with invalid index %d max %d\n", + name, info->index, p->count); + + return rk_nok; +} + +static rk_s32 create_objdef_mem_pool(KmppObjDefImpl *impl) +{ + rk_s32 old_size = impl->all_size; + + /* When last entry finish update and create memory pool */ + if (impl->flag_max_pos) { + rk_s32 flag_max_pos = MPP_ALIGN(impl->flag_max_pos, 8); + rk_s32 flag_size = flag_max_pos / 8; + + impl->flag_offset = impl->entry_size; + impl->flag_max_pos = flag_max_pos; + + flag_size -= impl->entry_size; + flag_size = MPP_ALIGN(flag_size, 4); + + impl->buf_size = impl->entry_size + flag_size; + } + + impl->all_size = sizeof(KmppObjImpl) + impl->priv_size + impl->buf_size; + + obj_dbg_pool("objdef %-16s entry size %4d buf size %4d -> %4d\n", impl->name, + impl->entry_size, old_size, impl->all_size); + + impl->pool = mpp_mem_pool_init_f(impl->name, impl->all_size); + if (!impl->pool) + mpp_loge_f("get mem pool size %d failed\n", impl->all_size); + + return impl->pool ? rk_ok : rk_nok; +} + +rk_s32 kmpp_objdef_get(KmppObjDef *def, rk_s32 priv_size, const char *name) +{ + KmppObjDefImpl *impl = NULL; + + if (!def || !name) { + mpp_loge_f("invalid param def %p name %p\n", def, name); + return rk_nok; + } + + if (kmpp_objdef_find((KmppObjDef *)&impl, name)) { + *def = NULL; + return rk_nok; + } + + mpp_assert(impl); + impl->priv_size = priv_size; + create_objdef_mem_pool(impl); + if (impl->ref_cnt) + mpp_logw_f("objdef %-16s already get ref %d\n", name, impl->ref_cnt); + else + impl->ref_cnt++; + + *def = impl; + + return rk_ok; +} + +rk_s32 kmpp_objdef_add_cfg_root(KmppObjDef def, MppCfgObj root) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + rk_s32 ret = rk_nok; + + if (impl) { + impl->cfg = root; + ret = rk_ok; + } + + return ret; +} + +MppCfgObj kmpp_objdef_get_cfg_root(KmppObjDef def) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + return impl ? impl->cfg : NULL; +} + +rk_s32 kmpp_objdef_add_entry(KmppObjDef def, const char *name, KmppEntry *tbl) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + rk_s32 ret = rk_nok; + + if (!impl->trie) { + if (!name) { + /* NOTE: no entry objdef still need to create mempool */ + return create_objdef_mem_pool(impl); + } + + mpp_trie_init(&impl->trie, impl->name); + } + + if (impl->trie) { + MppTrie trie = impl->trie; + + if (name) { + ret = mpp_trie_add_info(trie, name, tbl, tbl ? sizeof(*tbl) : 0); + + if (tbl->tbl.flag_offset > impl->flag_max_pos) + impl->flag_max_pos = tbl->tbl.flag_offset; + + obj_dbg_entry("objdef %-16s add entry %-16s flag offset %4d\n", + impl->name, name, tbl->tbl.flag_offset); + } else { + /* record object impl size */ + ret = mpp_trie_add_info(trie, "__index", &impl->index, sizeof(rk_s32)); + ret = mpp_trie_add_info(trie, "__size", &impl->entry_size, sizeof(rk_s32)); + ret |= mpp_trie_add_info(trie, NULL, NULL, 0); + ret |= create_objdef_mem_pool(impl); + } + } + + if (ret) + mpp_loge("objdef %s add entry %s failed ret %d\n", impl ? impl->name : NULL, name, ret); + + return ret; +} + +rk_s32 kmpp_objdef_add_init(KmppObjDef def, KmppObjInit init) +{ + if (def) { + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + impl->init = init; + return rk_ok; + } + + return rk_nok; +} + +rk_s32 kmpp_objdef_add_deinit(KmppObjDef def, KmppObjDeinit deinit) +{ + if (def) { + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + impl->deinit = deinit; + return rk_ok; + } + + return rk_nok; +} + +rk_s32 kmpp_objdef_add_preset(KmppObjDef def, KmppObjPreset preset) +{ + if (def) { + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + impl->preset = preset; + return rk_ok; + } + + return rk_nok; +} + +rk_s32 kmpp_objdef_add_dump(KmppObjDef def, KmppObjDump dump) +{ + if (def) { + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + impl->dump = dump; + return rk_ok; + } + + return rk_nok; +} + +rk_s32 kmpp_objdef_set_prop(KmppObjDef def, const char *op, rk_s32 value) +{ + if (def && op) { + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + if (!strcmp(op, "disable_mismatch_log")) { + impl->disable_mismatch_log = (value != 0) ? 1 : 0; + } else { + mpp_loge_f("unknown property %s value %d\n", op, value); + return rk_nok; + } + + return rk_ok; + } + + return rk_nok; +} + +rk_s32 kmpp_objdef_get_entry(KmppObjDef def, const char *name, KmppEntry **tbl) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + rk_s32 ret = rk_nok; + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + ret = rk_ok; + } + } + + if (ret && !impl->disable_mismatch_log) + mpp_loge("objdef %s get entry %s failed ret %d\n", + impl ? impl->name : NULL, name, ret); + + return ret; +} + +rk_s32 kmpp_objdef_get_offset(KmppObjDef def, const char *name) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + rk_s32 offset = -1; + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + if (tbl) + offset = tbl->tbl.elem_offset; + } + } + + return offset; +} + +rk_s32 kmpp_objdef_get_cmd(KmppObjDef def, const char *name) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + if (impl->ioctl) { + MppTrieInfo *info = mpp_trie_get_info(impl->ioctl, name); + + if (info) + return info->index; + } + + return -1; +} + +rk_s32 kmpp_objdef_dump(KmppObjDef def) +{ + if (def) { + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + MppTrie trie = impl->trie; + MppTrieInfo *info = NULL; + const char *name = impl->name; + RK_S32 i = 0; + + mpp_logi("dump objdef %-16s entry_size %d element count %d\n", + name, impl->entry_size, mpp_trie_get_info_count(trie)); + + info = mpp_trie_get_info_first(trie); + while (info) { + name = mpp_trie_info_name(info); + if (!strstr(name, "__")) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + rk_s32 idx = i++; + + mpp_logi("%-2d - %-16s offset %4d size %d\n", idx, + name, tbl->tbl.elem_offset, tbl->tbl.elem_size); + } + info = mpp_trie_get_info_next(trie, info); + } + + info = mpp_trie_get_info_first(trie); + while (info) { + name = mpp_trie_info_name(info); + if (strstr(name, "__")) { + void *p = mpp_trie_info_ctx(info); + rk_s32 idx = i++; + + if (info->ctx_len == sizeof(RK_U32)) { + + mpp_logi("%-2d - %-16s val %d\n", idx, name, *(RK_U32 *)p); + } else { + mpp_logi("%-2d - %-16s str %s\n", idx, name, p); + } + } + info = mpp_trie_get_info_next(trie, info); + } + + return rk_ok; + } + + return rk_nok; +} + +const char *kmpp_objdef_get_name(KmppObjDef def) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + return impl ? impl->name : NULL; +} + +rk_s32 kmpp_objdef_get_entry_size(KmppObjDef def) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + return impl ? impl->entry_size : 0; +} + +MppTrie kmpp_objdef_get_trie(KmppObjDef def) +{ + KmppObjDefImpl *impl = (KmppObjDefImpl *)def; + + return impl ? impl->trie : NULL; +} + +#define get_obj_from_def(p, def, shm, caller) \ + _get_obj_from_def(p, def, shm, caller, __FUNCTION__) + +static KmppObjImpl *_get_obj_from_def(KmppObjs *p, KmppObjDefImpl *def, KmppShmPtr *shm, + const char *caller, const char *func) +{ + KmppObjImpl *impl = mpp_mem_pool_get(def->pool, caller); + rk_u8 *base; + + if (!impl) { + mpp_loge("%s get obj %s impl %d failed at %s\n", + func, def->name, def->all_size, caller); + return NULL; + } + + base = (rk_u8 *)(impl + 1); + impl->name = def->name; + impl->def = def; + impl->trie = def->trie; + + if (def->priv_size) { + impl->priv = base; + base += def->priv_size; + } else { + impl->priv = NULL; + } + + if (shm && p) { + impl->shm = shm; + impl->entry = (void *)(shm->uptr + p->entry_offset); + + /* write userspace object address to share memory userspace private value */ + *(RK_U64 *)(shm->uptr + p->priv_offset) = (RK_U64)(intptr_t)impl; + + obj_dbg_flow("%s get kobj %-16s - %p entry [u:k] %llx:%llx at %s\n", func, + def->name, impl, shm->uaddr, shm->kaddr, caller); + } else { + impl->shm = NULL; + impl->entry = base; + + obj_dbg_flow("%s get uobj %-16s - %p entry %p at %s\n", func, + def->name, impl, base, caller); + } + + if (def->init) + def->init(impl->entry, impl, caller); + + return impl; +} + +rk_s32 kmpp_obj_get(KmppObj *obj, KmppObjDef def, const char *caller) +{ + KmppObjs *p; + KmppObjDefImpl *def_impl; + KmppObjIocArg *ioc; + rk_u64 uaddr; + rk_s32 ret = rk_nok; + + if (!obj || !def) { + mpp_loge_f("invalid param obj %p def %p at %s\n", obj, def, caller); + return ret; + } + + *obj = NULL; + + def_impl = (KmppObjDefImpl *)def; + + /* use buf_size to check userspace objdef or kernel objdef */ + if (!def_impl->pool) { + mpp_loge_f("invalid objdef %s without pool at %s\n", def_impl->name, caller); + return ret; + } + + /* userspace objdef path */ + if (!def_impl->is_kobj) { + *obj = get_obj_from_def(NULL, def_impl, NULL, caller); + + return *obj ? rk_ok : rk_nok; + } + + /* kernel objdef path */ + p = get_objs(caller); + if (!p) + return ret; + + ioc = alloca(sizeof(KmppObjIocArg) + sizeof(KmppShmPtr)); + + ioc->count = 1; + ioc->flag = 0; + ioc->name_uaddr[0] = (__u64)(intptr_t)def_impl->name; + + ret = ioctl(p->obj.fd, KMPP_SHM_IOC_GET_SHM, ioc); + if (ret) { + mpp_err("%s fd %d ioctl KMPP_SHM_IOC_GET_SHM failed at %s\n", + def_impl->name, p->obj.fd, caller); + return ret; + } + + uaddr = ioc->obj_sptr[0].uaddr; + + *obj = get_obj_from_def(p, def_impl, (KmppShmPtr *)U64_TO_PTR(uaddr), caller); + + return *obj ? rk_ok : rk_nok; +} + +rk_s32 kmpp_obj_get_by_name(KmppObj *obj, const char *name, const char *caller) +{ + KmppObjDefImpl *def; + + if (!obj || !name) { + mpp_loge_f("invalid param obj %p name %p at %s\n", + obj, name, caller); + return rk_nok; + } + + if (kmpp_objdef_find((KmppObjDef *)&def, name)) { + *obj = NULL; + return rk_nok; + } + + mpp_assert(def); + if (def->is_kobj && !def->pool) + create_objdef_mem_pool(def); + + return kmpp_obj_get(obj, def, caller); +} + +rk_s32 kmpp_obj_get_by_sptr(KmppObj *obj, KmppShmPtr *sptr, const char *caller) +{ + KmppObjs *p = get_objs(caller); + KmppObjImpl *impl; + KmppObjDefImpl *def; + rk_u8 *uptr = sptr ? sptr->uptr : NULL; + + if (!obj) { + mpp_loge_f("invalid param obj %p sptr %p uptr %p at %s\n", + obj, sptr, uptr, caller); + return rk_nok; + } + + *obj = NULL; + + /* allow NULL sptr and NULL uptr return NULL object value without error */ + if (!sptr || !uptr) + return rk_ok; + + if (!p) + return rk_nok; + + impl = (KmppObjImpl *)(intptr_t) * (rk_u64 *)(uptr + p->priv_offset); + if (impl) { + if (!kmpp_obj_check_f((KmppObj)impl)) + goto done; + } + + { + rk_u32 val = *((rk_u32 *)(uptr + p->name_offset)); + char *str; + + if (!val) { + mpp_loge_f("invalid obj name offset %d at %s\n", val, caller); + return rk_nok; + } + + str = (char *)p->obj.root + val; + if (kmpp_objdef_find((KmppObjDef *)&def, str)) { + mpp_loge_f("failed to get objdef %p - %s at %s\n", str, str, caller); + return rk_nok; + } + } + + mpp_assert(def && def->pool); + impl = get_obj_from_def(p, def, (KmppShmPtr *)uptr, caller); + +done: + *obj = impl; + + return impl ? rk_ok : rk_nok; +} + +rk_s32 kmpp_obj_put(KmppObj obj, const char *caller) +{ + if (obj) { + KmppObjImpl *impl = (KmppObjImpl *)obj; + KmppObjDefImpl *def = impl->def; + KmppObjs *p; + + mpp_assert(def && def->pool); + + if (def && def->deinit) + def->deinit(impl->entry, impl, caller); + + /* use shm to check userspace objdef or kernel objdef */ + /* userspace objdef path */ + if (impl->shm) { + p = get_objs(caller); + if (p && p->obj.fd >= 0) { + KmppObjIocArg *ioc = alloca(sizeof(KmppObjIocArg) + sizeof(KmppShmPtr)); + rk_s32 ret; + + ioc->count = 1; + ioc->flag = 0; + ioc->obj_sptr[0].uaddr = impl->shm->uaddr; + ioc->obj_sptr[0].kaddr = impl->shm->kaddr; + + obj_dbg_flow("put obj %-16s - %p entry [u:k] %llx:%llx at %s\n", def ? def->name : NULL, + impl, impl->shm->uaddr, impl->shm->kaddr, caller); + + ret = ioctl(p->obj.fd, KMPP_SHM_IOC_PUT_SHM, ioc); + if (ret) + mpp_err("ioctl KMPP_SHM_IOC_PUT_SHM failed ret %d at %s\n", ret, caller); + } + impl->shm = NULL; + } + + mpp_mem_pool_put(def->pool, impl, caller); + + return rk_ok; + } + + return rk_nok; +} + +rk_s32 kmpp_obj_impl_put(KmppObj obj, const char *caller) +{ + if (obj) { + KmppObjImpl *impl = (KmppObjImpl *)obj; + KmppObjDefImpl *def = impl->def; + + mpp_assert(def); + + if (def) { + if (def->deinit) + def->deinit(impl->entry, impl, caller); + + mpp_assert(def->pool); + mpp_mem_pool_put(def->pool, impl, caller); + + return rk_ok; + } + } + + return rk_nok; +} + +rk_s32 kmpp_obj_preset(KmppObj obj, const char *arg, const char *caller) +{ + if (obj) { + KmppObjImpl *impl = (KmppObjImpl *)obj; + KmppObjDefImpl *def = impl->def; + + mpp_assert(def); + + if (def && def->preset) + return def->preset(impl->entry, impl, arg, caller); + } + + return rk_ok; +} + +rk_s32 kmpp_obj_check(KmppObj obj, const char *caller) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + if (!impl) { + mpp_loge_f("from %s failed for NULL arg\n", caller); + return rk_nok; + } + + if (!impl->name || !impl->def || impl->name != impl->def->name) { + mpp_loge_f("from %s failed for name check %s but %s\n", caller, + impl->def ? impl->def->name : NULL, impl->name); + return rk_nok; + } + + if (!impl->entry || !impl->def->trie) { + mpp_loge_f("from %s failed for entry %p and def trie %p\n", caller, + impl->entry, impl->def->trie); + return rk_nok; + } + + return rk_ok; +} + +rk_s32 kmpp_obj_ioctl(KmppObj ctx, rk_s32 cmd, KmppObj in, KmppObj *out, const char *caller) +{ + KmppObjs *p = get_objs_f(); + KmppObjDef def_ioc = kmpp_ioc_objdef(); + KmppObjImpl *impl = (KmppObjImpl *)ctx; + KmppObjImpl *ioc = NULL; + KmppObjIocArg *ioc_arg; + KmppObjDefImpl *def; + rk_s32 ret; + + if (!p) + return rk_nok; + + if (!def_ioc) { + static rk_s32 once = 1; + + if (once) { + mpp_loge("KmppIoc is not defined\n"); + once = 0; + } + + return rk_nok; + } + + if (!impl || !impl->def) { + mpp_err("invalid ioctl ctx %p def %p failed at %s\n", + impl, impl ? impl->def : NULL, caller); + return rk_nok; + } + + def = impl->def; + + obj_dbg_ioctl("ioctl def %s:%d cmd %d ctx %p in %p out %p at %s\n", + def->name, def->defs_idx, cmd, ctx, in, out, caller); + + ret = kmpp_obj_get((KmppObj *)&ioc, def_ioc, caller); + if (ret) { + mpp_loge("failed to get KmppIoc ret %d\n", ret); + return rk_nok; + } + + ioc_arg = alloca(sizeof(KmppObjIocArg) + sizeof(KmppShmPtr)); + ioc_arg->count = 1; + ioc_arg->flag = 0; + ioc_arg->obj_sptr[0].uaddr = ioc->shm->uaddr; + ioc_arg->obj_sptr[0].kaddr = ioc->shm->kaddr; + + obj_dbg_ioctl("ioctl arg %p obj_sptr [u:k] %llx : %llx\n", ioc_arg, + ioc_arg->obj_sptr[0].uaddr, ioc_arg->obj_sptr[0].kaddr); + + kmpp_ioc_set_def(ioc, def->defs_idx); + kmpp_ioc_set_cmd(ioc, cmd); + kmpp_ioc_set_flags(ioc, 0); + kmpp_ioc_set_id(ioc, 0); + + { + static rk_s32 has_ctx = -1; + + if (has_ctx < 0) + has_ctx = kmpp_objdef_get_offset(def_ioc, "ctx") >= 0; + + if (has_ctx) { + KmppShmPtr *sptr = kmpp_obj_to_shm(ctx); + + kmpp_ioc_set_ctx(ioc, sptr); + obj_dbg_ioctl("ioctl [u:k] ctx %#llx : %#llx\n", sptr->uaddr, sptr->kaddr); + } + } + + if (in) { + KmppShmPtr *sptr = kmpp_obj_to_shm(in); + + kmpp_ioc_set_in(ioc, sptr); + obj_dbg_ioctl("ioctl [u:k] in %#llx : %#llx\n", sptr->uaddr, sptr->kaddr); + } + + ret = ioctl(p->ioc.fd, 0, ioc_arg); + + /* if defined ret in ioc object use ret in ioc object */ + kmpp_ioc_get_ret(ioc, &ret); + + if (out) { + *out = NULL; + + if (!ret) { + KmppShmPtr sptr = { 0 }; + + kmpp_ioc_get_out(ioc, &sptr); + kmpp_obj_get_by_sptr(out, &sptr, caller); + + obj_dbg_ioctl("ioctl [u:k] out %#llx : %#llx obj %p\n", + sptr.uaddr, sptr.kaddr, *out); + } + } + + kmpp_obj_put(ioc, caller); + + return ret; +} + +rk_s32 kmpp_obj_is_kobj(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + return (impl && impl->def) ? impl->def->is_kobj : 0; +} + +KmppObjDef kmpp_obj_to_objdef(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + return impl ? impl->def : NULL; +} + +void *kmpp_obj_to_flags(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + if (impl && impl->def && impl->def->flag_offset) + return impl->entry + impl->def->flag_offset; + + return NULL; +} + +rk_s32 kmpp_obj_to_flags_size(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + if (impl && impl->def && impl->def->flag_max_pos) { + KmppObjDefImpl *def = impl->def; + rk_s32 max_pos = MPP_ALIGN(def->flag_max_pos, 8) / 8; + + return MPP_ALIGN(max_pos - def->flag_offset, 4); + } + + return 0; +} + +KmppShmPtr *kmpp_obj_to_shm(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + if (!impl) { + mpp_loge("invalid obj %p\n", obj); + return NULL; + } + + return impl->shm; +} + +rk_s32 kmpp_obj_to_shm_size(KmppObj obj) +{ + (void)obj; + return sizeof(KmppShmPtr); +} + +const char *kmpp_obj_get_name(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + if (impl && impl->def && impl->def->name) + return impl->def->name; + + return NULL; +} + +void *kmpp_obj_to_priv(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + return impl ? impl->priv : NULL; +} + +void *kmpp_obj_to_entry(KmppObj obj) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + return impl ? impl->entry : NULL; +} + +rk_s32 kmpp_obj_to_offset(KmppObj obj, const char *name) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + if (!impl || !name) { + mpp_loge("invalid obj %p name %s\n", obj, name); + return -1; + } + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + if (tbl) + return tbl->tbl.elem_offset; + } + } + + mpp_loge("invalid offset for name %s\n", name); + + return -1; +} + +#define MPP_OBJ_ACCESS(type, base_type) \ + rk_s32 kmpp_obj_set_##type(KmppObj obj, const char *name, base_type val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl->trie) { \ + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); \ + if (info) { \ + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); \ + ret = kmpp_obj_impl_set_##type(tbl, impl->entry, val); \ + } \ + } \ + if (ret) \ + mpp_loge("obj %s set %s " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, name, ret); \ + return ret; \ + } \ + rk_s32 kmpp_obj_get_##type(KmppObj obj, const char *name, base_type *val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl->trie) { \ + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); \ + if (info) { \ + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); \ + ret = kmpp_obj_impl_get_##type(tbl, impl->entry, val); \ + } \ + } \ + if (ret) \ + mpp_loge("obj %s get %s " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, name, ret); \ + return ret; \ + } + +MPP_OBJ_ACCESS(s8, rk_s8) +MPP_OBJ_ACCESS(u8, rk_u8) +MPP_OBJ_ACCESS(s16, rk_s16) +MPP_OBJ_ACCESS(u16, rk_u16) +MPP_OBJ_ACCESS(s32, rk_s32) +MPP_OBJ_ACCESS(u32, rk_u32) +MPP_OBJ_ACCESS(s64, rk_s64) +MPP_OBJ_ACCESS(u64, rk_u64) +MPP_OBJ_ACCESS(obj, KmppObj) +MPP_OBJ_ACCESS(fp, void *) + +/* compatible for pointer and structure setup */ +rk_s32 kmpp_obj_set_ptr(KmppObj obj, const char *name, void* val) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + rk_s32 ret = rk_nok; + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + if (tbl->tbl.elem_type == ELEM_TYPE_st) + ret = kmpp_obj_impl_set_st(tbl, impl->entry, val); + else if (tbl->tbl.elem_type == ELEM_TYPE_arr) + ret = kmpp_obj_impl_set_arr(tbl, impl->entry, val); + else + ret = kmpp_obj_impl_set_ptr(tbl, impl->entry, val); + } + } + + if (ret) + mpp_loge("obj %s set %s ptr failed ret %d\n", + (impl && impl->def && impl->def->name) ? impl->def->name : NULL, name, ret); + + return ret; +} + +rk_s32 kmpp_obj_get_ptr(KmppObj obj, const char *name, void **val) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + rk_s32 ret = rk_nok; + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + if (tbl->tbl.elem_type == ELEM_TYPE_st) + ret = kmpp_obj_impl_get_st(tbl, impl->entry, val); + else if (tbl->tbl.elem_type == ELEM_TYPE_arr) + ret = kmpp_obj_impl_get_arr(tbl, impl->entry, val); + else + ret = kmpp_obj_impl_get_ptr(tbl, impl->entry, val); + } + } + + if (ret) + mpp_loge("obj %s get %s ptr failed ret %d\n", + (impl && impl->def && impl->def->name) ? impl->def->name : NULL, name, ret); + + return ret; +} + +#define MPP_OBJ_STRUCT_ACCESS(type, base_type) \ + rk_s32 kmpp_obj_set_##type(KmppObj obj, const char *name, base_type *val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl->trie) { \ + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); \ + if (info) { \ + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); \ + ret = kmpp_obj_impl_set_##type(tbl, impl->entry, val); \ + } \ + } \ + if (ret) \ + mpp_loge("obj %s set %s " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, name, ret); \ + return ret; \ + } \ + rk_s32 kmpp_obj_get_##type(KmppObj obj, const char *name, base_type *val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl->trie) { \ + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); \ + if (info) { \ + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); \ + ret = kmpp_obj_impl_get_##type(tbl, impl->entry, val); \ + } \ + } \ + if (ret) \ + mpp_loge("obj %s get %s " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, name, ret); \ + return ret; \ + } + +MPP_OBJ_STRUCT_ACCESS(shm, KmppShmPtr) + +/* st access also handles arr for backward compatibility */ +rk_s32 kmpp_obj_set_st(KmppObj obj, const char *name, void *val) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + rk_s32 ret = rk_nok; + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + if (tbl->tbl.elem_type == ELEM_TYPE_arr) + ret = kmpp_obj_impl_set_arr(tbl, impl->entry, val); + else + ret = kmpp_obj_impl_set_st(tbl, impl->entry, val); + } + } + + if (ret) + mpp_loge("obj %s set %s st failed ret %d\n", + impl ? impl->def ? impl->def->name : NULL : NULL, name, ret); + + return ret; +} + +rk_s32 kmpp_obj_get_st(KmppObj obj, const char *name, void *val) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + rk_s32 ret = rk_nok; + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + if (tbl->tbl.elem_type == ELEM_TYPE_arr) + ret = kmpp_obj_impl_get_arr(tbl, impl->entry, val); + else + ret = kmpp_obj_impl_get_st(tbl, impl->entry, val); + } + } + + if (ret) + mpp_loge("obj %s get %s st failed ret %d\n", + impl ? impl->def ? impl->def->name : NULL : NULL, name, ret); + + return ret; +} + +#define MPP_OBJ_TBL_ACCESS(type, base_type) \ + rk_s32 kmpp_obj_tbl_set_##type(KmppObj obj, KmppEntry *tbl, base_type val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl) \ + ret = kmpp_obj_impl_set_##type(tbl, impl->entry, val); \ + if (ret) \ + mpp_loge("obj %s tbl %08x set " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, tbl ? tbl->val : 0, ret); \ + return ret; \ + } \ + rk_s32 kmpp_obj_tbl_get_##type(KmppObj obj, KmppEntry *tbl, base_type *val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl) \ + ret = kmpp_obj_impl_get_##type(tbl, impl->entry, val); \ + if (ret) \ + mpp_loge("obj %s tbl %08x get " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, tbl ? tbl->val : 0, ret); \ + return ret; \ + } +MPP_OBJ_TBL_ACCESS(s8, rk_s8) +MPP_OBJ_TBL_ACCESS(u8, rk_u8) +MPP_OBJ_TBL_ACCESS(s16, rk_s16) +MPP_OBJ_TBL_ACCESS(u16, rk_u16) +MPP_OBJ_TBL_ACCESS(s32, rk_s32) +MPP_OBJ_TBL_ACCESS(u32, rk_u32) +MPP_OBJ_TBL_ACCESS(s64, rk_s64) +MPP_OBJ_TBL_ACCESS(u64, rk_u64) +MPP_OBJ_TBL_ACCESS(obj, KmppObj) +MPP_OBJ_TBL_ACCESS(ptr, void *) +MPP_OBJ_TBL_ACCESS(fp, void *) + +#define MPP_OBJ_STRUCT_TBL_ACCESS(type, base_type) \ + rk_s32 kmpp_obj_tbl_set_##type(KmppObj obj, KmppEntry *tbl, base_type *val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl) \ + ret = kmpp_obj_impl_set_##type(tbl, impl->entry, val); \ + if (ret) \ + mpp_loge("obj %s tbl %08x set " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, tbl ? tbl->val : 0, ret); \ + return ret; \ + } \ + rk_s32 kmpp_obj_tbl_get_##type(KmppObj obj, KmppEntry *tbl, base_type *val) \ + { \ + KmppObjImpl *impl = (KmppObjImpl *)obj; \ + rk_s32 ret = rk_nok; \ + if (impl) \ + ret = kmpp_obj_impl_get_##type(tbl, impl->entry, val); \ + if (ret) \ + mpp_loge("obj %s tbl %08x get " #type " failed ret %d\n", \ + impl ? impl->def ? impl->def->name : NULL : NULL, tbl ? tbl->val : 0, ret); \ + return ret; \ + } + +MPP_OBJ_STRUCT_TBL_ACCESS(shm, KmppShmPtr) + +/* st tbl access also handles arr for backward compatibility */ +rk_s32 kmpp_obj_tbl_set_st(KmppObj obj, KmppEntry *tbl, void *val) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + rk_s32 ret = rk_nok; + + if (impl) { + if (tbl->tbl.elem_type == ELEM_TYPE_arr) + ret = kmpp_obj_impl_set_arr(tbl, impl->entry, val); + else + ret = kmpp_obj_impl_set_st(tbl, impl->entry, val); + } + if (ret) + mpp_loge("obj %s tbl %08x set st failed ret %d\n", + impl ? impl->def ? impl->def->name : NULL : NULL, tbl ? tbl->val : 0, ret); + + return ret; +} + +rk_s32 kmpp_obj_tbl_get_st(KmppObj obj, KmppEntry *tbl, void *val) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + rk_s32 ret = rk_nok; + + if (impl) { + if (tbl->tbl.elem_type == ELEM_TYPE_arr) + ret = kmpp_obj_impl_get_arr(tbl, impl->entry, val); + else + ret = kmpp_obj_impl_get_st(tbl, impl->entry, val); + } + if (ret) + mpp_loge("obj %s tbl %08x get st failed ret %d\n", + impl ? impl->def ? impl->def->name : NULL : NULL, tbl ? tbl->val : 0, ret); + + return ret; +} + +rk_s32 kmpp_obj_set_shm_obj(KmppObj obj, const char *name, KmppObj val) +{ + rk_s32 ret = rk_nok; + + if (!obj || !name || !val) { + mpp_loge_f("obj %p set shm obj %s to %p failed invalid param\n", + obj, name, val); + } else { + KmppShmPtr *sptr = kmpp_obj_to_shm(val); + + if (!sptr) { + mpp_loge_f("obj %p found invalid shm ptr\n", val); + } else { + ret = kmpp_obj_set_shm(obj, name, sptr); + } + } + + return ret; +} + +rk_s32 kmpp_obj_get_shm_obj(KmppObj obj, const char *name, KmppObj *val) +{ + rk_s32 ret = rk_nok; + + if (!obj || !name || !val) { + mpp_loge_f("obj %p get shm obj %s to %p failed invalid param\n", + obj, name, val); + } else { + KmppObjImpl *impl = (KmppObjImpl *)obj; + KmppShmPtr sptr = {0}; + + *val = NULL; + + ret = kmpp_obj_get_shm(obj, name, &sptr); + if (ret || !sptr.uptr) { + mpp_loge_f("obj %p get shm %s failed ret %d\n", impl, name, ret); + } else { + ret = kmpp_obj_get_by_sptr(val, &sptr, __FUNCTION__); + } + } + + return ret; +} + +rk_s32 kmpp_obj_test(KmppObj obj, const char *name) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + if (impl && impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + return ENTRY_TEST_FLAG(tbl, impl->entry);; + } + } + + return 0; +} + +rk_s32 kmpp_obj_tbl_test(KmppObj obj, KmppEntry *tbl) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + + return (impl && tbl) ? ENTRY_TEST_FLAG(tbl, impl->entry) : 0; +} + +rk_s32 kmpp_obj_update(KmppObj dst, KmppObj src) +{ + KmppObjImpl *dst_impl = (KmppObjImpl *)dst; + KmppObjImpl *src_impl = (KmppObjImpl *)src; + MppTrie trie = NULL; + MppTrieInfo *info = NULL; + + if (kmpp_obj_check_f(src) || kmpp_obj_check_f(dst) || src_impl->def != dst_impl->def) { + mpp_loge_f("obj %p update to %p failed invalid param\n", src, dst); + return rk_nok; + } + + trie = src_impl->def->trie; + + info = mpp_trie_get_info_first(trie); + do { + KmppEntry *e; + + if (mpp_trie_info_is_self(info)) + continue; + + e = (KmppEntry *)mpp_trie_info_ctx(info); + if (e->tbl.flag_offset && ENTRY_TEST_FLAG(e, src_impl->entry)) { + rk_s32 offset = e->tbl.elem_offset; + rk_s32 size = e->tbl.elem_size; + + obj_dbg_update("obj %s %p update %s\n", src_impl->name, + dst, mpp_trie_info_name(info)); + memcpy(dst_impl->entry + offset, src_impl->entry + offset, size); + } + } while ((info = mpp_trie_get_info_next(trie, info))); + + if (src_impl->def) { + KmppObjDefImpl *def = src_impl->def; + rk_s32 flag_offset = def->flag_offset; + rk_s32 flag_size = kmpp_obj_to_flags_size(src); + + if (flag_offset && flag_size) { + rk_s32 i; + + for (i = flag_offset; i < flag_offset + flag_size; i += 4) + obj_dbg_update("obj %s %p update flag at %#06x - %08x\n", src_impl->def->name, + dst, i, *((rk_u32 *)((rk_u8 *)src_impl->entry + i))); + + memcpy(dst_impl->entry + flag_offset, + src_impl->entry + flag_offset, flag_size); + memset(src_impl->entry + flag_offset, 0, flag_size); + } + } + + return rk_ok; +} + +rk_s32 kmpp_obj_update_entry(void *entry, KmppObj src) +{ + KmppObjImpl *src_impl = (KmppObjImpl *)src; + MppTrie trie = NULL; + MppTrieInfo *info = NULL; + + if (kmpp_obj_check_f(src) || !entry) { + mpp_loge_f("obj %p update to entry %p failed invalid param\n", src, entry); + return rk_nok; + } + + trie = src_impl->def->trie; + + info = mpp_trie_get_info_first(trie); + do { + KmppEntry *e; + + if (mpp_trie_info_is_self(info)) + continue; + + e = (KmppEntry *)mpp_trie_info_ctx(info); + if (e->tbl.flag_offset && ENTRY_TEST_FLAG(e, src_impl->entry)) { + rk_s32 offset = e->tbl.elem_offset; + rk_s32 size = e->tbl.elem_size; + + obj_dbg_update("obj %s %p -> %p update %s\n", src_impl->name, + src_impl, entry, mpp_trie_info_name(info)); + memcpy(entry + offset, src_impl->entry + offset, size); + } + } while ((info = mpp_trie_get_info_next(trie, info))); + + return rk_ok; +} + +rk_s32 kmpp_obj_copy(KmppObj dst, KmppObj src) +{ + KmppObjImpl *dst_impl = (KmppObjImpl *)dst; + KmppObjImpl *src_impl = (KmppObjImpl *)src; + + if (kmpp_obj_check_f(src) || kmpp_obj_check_f(dst) || src_impl->def != dst_impl->def) { + mpp_loge_f("obj %p copy to %p failed invalid param\n", src, dst); + return rk_nok; + } + + memcpy(dst_impl->entry, src_impl->entry, src_impl->def->entry_size); + { + rk_s32 offset = src_impl->def->flag_offset; + rk_s32 size = kmpp_obj_to_flags_size(src); + + memcpy(dst_impl->entry + offset, src_impl->entry + offset, size); + } + + return rk_ok; +} + +rk_s32 kmpp_obj_copy_entry(KmppObj dst, KmppObj src) +{ + KmppObjImpl *dst_impl = (KmppObjImpl *)dst; + KmppObjImpl *src_impl = (KmppObjImpl *)src; + + if (kmpp_obj_check_f(src) || kmpp_obj_check_f(dst) || src_impl->def != dst_impl->def) { + mpp_loge_f("obj %p copy entry to %p failed invalid param\n", src, dst); + return rk_nok; + } + + memcpy(dst_impl->entry, src_impl->entry, src_impl->def->entry_size); + { /* NOTE: clear dst update flags */ + rk_s32 offset = src_impl->def->flag_offset; + rk_s32 size = kmpp_obj_to_flags_size(src); + + memset(dst_impl->entry + offset, 0, size); + } + + return rk_ok; +} + +static rk_s32 kmpp_obj_impl_run(rk_s32 (*run)(void *ctx), void *ctx) +{ + return run(ctx); +} + +rk_s32 kmpp_obj_run(KmppObj obj, const char *name) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + rk_s32 ret = rk_nok; + + if (impl->trie) { + MppTrieInfo *info = mpp_trie_get_info(impl->trie, name); + void *val = NULL; + + if (info) { + KmppEntry *tbl = (KmppEntry *)mpp_trie_info_ctx(info); + + ret = kmpp_obj_impl_get_fp(tbl, impl->entry, &val); + } + + if (val) + ret = kmpp_obj_impl_run(val, impl->entry); + } + + return ret; +} + +rk_s32 kmpp_obj_udump_f(KmppObj obj, const char *caller) +{ + KmppObjImpl *impl = (KmppObjImpl *)obj; + KmppObjDefImpl *def = impl ? impl->def : NULL; + MppTrie trie = NULL; + MppTrieInfo *info = NULL; + MppTrieInfo *next = NULL; + const char *name = NULL; + rk_s32 ret = rk_nok; + RK_S32 i = 0; + + if (!impl || !def) { + mpp_loge_f("invalid obj %p def %p\n", impl, def); + return rk_nok; + } + + trie = impl->trie; + name = def->name; + + mpp_logi("dump obj %-12s - %p at %s:\n", name, impl, caller); + + if (def->dump) + return def->dump(impl->entry); + + next = mpp_trie_get_info_first(trie); + while (next) { + KmppEntry *e; + rk_s32 idx; + + info = next; + next = mpp_trie_get_info_next(trie, info); + + e = (KmppEntry *)mpp_trie_info_ctx(info); + name = mpp_trie_info_name(info); + + if (mpp_trie_info_is_self(info)) + continue; + + idx = i++; + + switch (e->tbl.elem_type) { + case ELEM_TYPE_s8 : { + rk_s8 val; + rk_s8 val_chk; + + ret = kmpp_obj_tbl_get_s8(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s s8 %#x:%d\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s s8 get failed\n", idx, name); + + kmpp_obj_get_s8(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s s8 check failed\n", idx, name); + } break; + case ELEM_TYPE_u8 : { + rk_u8 val; + rk_u8 val_chk; + + ret = kmpp_obj_tbl_get_u8(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s u8 %#x:%u\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s u8 get failed\n", idx, name); + + kmpp_obj_get_u8(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s u8 check failed\n", idx, name); + } break; + case ELEM_TYPE_s16 : { + rk_s16 val; + rk_s16 val_chk; + + ret = kmpp_obj_tbl_get_s16(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s s16 %#x:%d\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s s16 get failed\n", idx, name); + + kmpp_obj_get_s16(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s s16 check failed\n", idx, name); + } break; + case ELEM_TYPE_u16 : { + rk_u16 val; + rk_u16 val_chk; + + ret = kmpp_obj_tbl_get_u16(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s u16 %#x:%u\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s u16 get failed\n", idx, name); + + kmpp_obj_get_u16(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s u16 check failed\n", idx, name); + } break; + case ELEM_TYPE_s32 : { + rk_s32 val; + rk_s32 val_chk; + + ret = kmpp_obj_tbl_get_s32(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s s32 %#x:%d\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s s32 get failed\n", idx, name); + + kmpp_obj_get_s32(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s s32 check failed\n", idx, name); + } break; + case ELEM_TYPE_u32 : { + rk_u32 val; + rk_u32 val_chk; + + ret = kmpp_obj_tbl_get_u32(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s u32 %#x:%u\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s u32 get failed\n", idx, name); + + kmpp_obj_get_u32(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s u32 check failed\n", idx, name); + } break; + case ELEM_TYPE_s64 : { + rk_s64 val; + rk_s64 val_chk; + + ret = kmpp_obj_tbl_get_s64(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s s64 %#llx:%lld\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s s64 get failed\n", idx, name); + + kmpp_obj_get_s64(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s s64 check failed\n", idx, name); + } break; + case ELEM_TYPE_u64 : { + rk_u64 val; + rk_u64 val_chk; + + ret = kmpp_obj_tbl_get_u64(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s u64 %#llx:%llu\n", idx, name, val, val); + else + mpp_loge("%-2d - %-16s u64 get failed\n", idx, name); + + kmpp_obj_get_u64(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s u64 check failed\n", idx, name); + } break; + case ELEM_TYPE_st : + case ELEM_TYPE_arr : { + void *val_chk = mpp_malloc_size(void, e->tbl.elem_size); + void *val = mpp_malloc_size(void, e->tbl.elem_size); + rk_s32 data_size = e->tbl.elem_size; + char logs[128]; + + ret = kmpp_obj_tbl_get_st(obj, e, val); + if (!ret) { + rk_s32 pos; + rk_s32 j; + + mpp_logi("%-2d - %-16s st/arr %d:%d\n", idx, name, e->tbl.elem_offset, data_size); + + j = 0; + for (; j < data_size / 4 - 8; j += 8) { + snprintf(logs, sizeof(logs) - 1, " - %02x : %#08x %#08x %#08x %#08x %#08x %#08x %#08x %#08x", j, + ((RK_U32 *)val)[j + 0], ((RK_U32 *)val)[j + 1], + ((RK_U32 *)val)[j + 2], ((RK_U32 *)val)[j + 3], + ((RK_U32 *)val)[j + 4], ((RK_U32 *)val)[j + 5], + ((RK_U32 *)val)[j + 6], ((RK_U32 *)val)[j + 7]); + + mpp_logi("%s\n", logs); + } + + pos = snprintf(logs, sizeof(logs) - 1, " - %02x :", j); + for (; j < data_size / 4; j++) + pos += snprintf(logs + pos, sizeof(logs) - 1 - pos, " %#08x", ((RK_U32 *)val)[j]); + + mpp_logi("%s\n", logs); + } else + mpp_loge("%-2d - %-16s st get failed\n", idx, name); + + kmpp_obj_get_st(obj, name, val_chk); + if (memcmp(val, val_chk, e->tbl.elem_size)) { + mpp_loge("%-2d - %-16s st/arr check failed\n", idx, name); + mpp_loge("val %p\n", val); + mpp_loge("val_chk %p\n", val_chk); + } + + MPP_FREE(val); + MPP_FREE(val_chk); + } break; + case ELEM_TYPE_shm : { + KmppShmPtr *val_chk = mpp_malloc_size(void, e->tbl.elem_size); + KmppShmPtr *val = mpp_malloc_size(void, e->tbl.elem_size); + + ret = kmpp_obj_tbl_get_st(obj, e, val); + if (!ret) + mpp_logi("%-2d - %-16s shm u%#llx:k%#llx\n", + idx, name, val->uaddr, val->kaddr); + else + mpp_loge("%-2d - %-16s shm get failed\n", idx, name); + + kmpp_obj_get_st(obj, name, val_chk); + if (memcmp(val, val_chk, e->tbl.elem_size)) { + mpp_loge("%-2d - %-16s shm check failed\n", idx, name); + mpp_loge("val %p - %#llx:%#llx\n", val, val->uaddr, val->kaddr); + mpp_loge("val_chk %p - %#llx:%#llx\n", val_chk, val_chk->uaddr, val_chk->kaddr); + } + + MPP_FREE(val); + MPP_FREE(val_chk); + } break; + case ELEM_TYPE_uptr : { + void *val; + void *val_chk; + + ret = kmpp_obj_tbl_get_ptr(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s ptr %p\n", idx, name, val); + else + mpp_loge("%-2d - %-16s ptr get failed\n", idx, name); + + kmpp_obj_get_ptr(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s ptr check failed\n", idx, name); + } break; + case ELEM_TYPE_ufp : { + void *val; + void *val_chk; + + ret = kmpp_obj_tbl_get_fp(obj, e, &val); + if (!ret) + mpp_logi("%-2d - %-16s fp %p\n", idx, name, val); + else + mpp_loge("%-2d - %-16s fp get failed\n", idx, name); + + kmpp_obj_get_fp(obj, name, &val_chk); + if (val != val_chk) + mpp_loge("%-2d - %-16s fp check failed\n", idx, name); + } break; + default : { + mpp_loge("%-2d - %-16s found invalid type %d\n", idx, name, e->tbl.elem_type); + ret = rk_nok; + } break; + } + } + + return (ret != rk_ok) ? rk_nok : rk_ok; +} + +rk_s32 kmpp_obj_kdump_f(KmppObj obj, const char *caller) +{ + KmppObjs *p = get_objs(caller); + KmppObjImpl *impl = (KmppObjImpl *)obj; + KmppObjDefImpl *def = impl ? impl->def : NULL; + rk_s32 ret = rk_nok; + + if (!impl || !def || !p) { + mpp_loge_f("invalid obj %p def %p objs %p\n", impl, def, p); + return rk_nok; + } + + mpp_logi("dump obj %-12s - %p at %s by kernel\n", def->name, impl, caller); + + ret = ioctl(p->obj.fd, KMPP_SHM_IOC_DUMP, impl->shm); + if (ret) + mpp_err("ioctl KMPP_SHM_IOC_DUMP failed ret %d\n", ret); + + return (ret != rk_ok) ? rk_nok : rk_ok; +} + +rk_s32 kmpp_shm_get(KmppShm *shm, rk_s32 size, const char *caller) +{ + KmppObjs *p; + KmppObjIocArg *ioc; + rk_s32 ret = rk_nok; + + if (!shm || !size) { + mpp_loge_f("invalid param shm %p size %d at %s\n", shm, size, caller); + return ret; + } + + *shm = NULL; + + /* kernel objdef path */ + p = get_objs(caller); + if (!p) + return ret; + + ioc = alloca(sizeof(KmppObjIocArg) + sizeof(KmppShmPtr)); + + ioc->count = 1; + ioc->flag = 0; + ioc->shm_req->shm_name = 0; + ioc->shm_req->shm_size = size; + ioc->shm_req->shm_flag = 0; + + ret = ioctl(p->obj.fd, KMPP_SHM_IOC_GET_SHM, ioc); + if (ret) { + mpp_err("shm fd %d ioctl KMPP_SHM_IOC_GET_SHM failed at %s\n", + p->obj.fd, caller); + return ret; + } + + *shm = U64_TO_PTR(ioc->obj_sptr[0].uaddr); + + return *shm ? rk_ok : rk_nok; +} + +rk_s32 kmpp_shm_put(KmppShm shm, const char *caller) +{ + KmppObjs *p = get_objs(caller); + rk_s32 ret = rk_nok; + + if (!shm) { + mpp_loge_f("invalid param shm %p at %s\n", shm, caller); + return ret; + } + + if (!p) + return ret; + + if (p && p->obj.fd >= 0) { + KmppShmPtr *sptr = (KmppShmPtr *)shm; + KmppObjIocArg *ioc = alloca(sizeof(KmppObjIocArg) + sizeof(KmppShmPtr)); + + ioc->count = 1; + ioc->flag = 0; + + ioc->count = 1; + ioc->flag = 0; + ioc->obj_sptr[0].uaddr = sptr->uaddr; + ioc->obj_sptr[0].kaddr = sptr->kaddr; + + obj_dbg_flow("put shm %p entry [u:k] %llx:%llx at %s\n", + sptr, sptr->uaddr, sptr->kaddr, caller); + + ret = ioctl(p->obj.fd, KMPP_SHM_IOC_PUT_SHM, ioc); + if (ret) + mpp_err("ioctl KMPP_SHM_IOC_PUT_SHM failed ret %d at %s\n", ret, caller); + } + + return ret; +} + +void *kmpp_shm_to_entry(KmppShm shm, const char *caller) +{ + KmppObjs *p = get_objs(caller); + KmppShmPtr *sptr = (KmppShmPtr *)shm; + + if (!shm) { + mpp_loge_f("invalid param shm %p at %s\n", shm, caller); + return NULL; + } + + return sptr->uptr + p->entry_offset; +} diff --git a/kmpp/base/kmpp_packet.c b/kmpp/base/kmpp_packet.c new file mode 100644 index 000000000..28773b1c3 --- /dev/null +++ b/kmpp/base/kmpp_packet.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "kmpp_packet_impl.h" + +rk_s32 kmpp_packet_get_meta(KmppPacket packet, KmppMeta *meta) +{ + KmppPacketPriv *priv = NULL; + KmppShmPtr sptr; + rk_s32 ret; + + if (!packet || !meta) { + mpp_loge_f("invalid packet %p meta %p\n", packet, meta); + return rk_nok; + } + + priv = (KmppPacketPriv *)kmpp_obj_to_priv(packet); + if (priv->meta) { + *meta = priv->meta; + return rk_ok; + } + + kmpp_obj_get_shm(packet, "meta", &sptr); + ret = kmpp_obj_get_by_sptr_f(priv->meta, &sptr); + if (ret) { + *meta = NULL; + mpp_loge_f("self_meta get obj by sptr failed, ret %d\n", ret); + return ret; + } + + *meta = priv->meta; + + return rk_ok; +} + +static rk_s32 kmpp_packet_impl_init(void *entry, KmppObj obj, const char *caller) +{ + KmppPacketPriv *priv = (KmppPacketPriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid %p without priv at %s\n", obj, caller); + return rk_nok; + } + + priv->meta = NULL; + + return rk_ok; +} + +static rk_s32 kmpp_packet_impl_deinit(void *entry, KmppObj obj, const char *caller) +{ + KmppPacketPriv *priv = (KmppPacketPriv *)kmpp_obj_to_priv(obj); + (void)entry; + + if (!priv) { + mpp_loge_f("invalid %p without priv at %s\n", obj, caller); + return rk_nok; + } + + if (priv->meta) { + kmpp_obj_impl_put(priv->meta, caller); + priv->meta = NULL; + } + + return rk_ok; +} + +#define KMPP_OBJ_NAME kmpp_packet +#define KMPP_OBJ_INTF_TYPE KmppPacket +#define KMPP_OBJ_IMPL_TYPE KmppPacketImpl +#define KMPP_OBJ_FUNC_INIT kmpp_packet_impl_init +#define KMPP_OBJ_FUNC_DEINIT kmpp_packet_impl_deinit +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_PACKET +#define KMPP_OBJ_ENTRY_TABLE KMPP_PACKET_ENTRY_TABLE +#define KMPP_OBJ_PRIV_SIZE sizeof(KmppPacketPriv) +#include "kmpp_obj_helper.h" \ No newline at end of file diff --git a/kmpp/base/kmpp_vdec_cfg.c b/kmpp/base/kmpp_vdec_cfg.c new file mode 100644 index 000000000..669131ce6 --- /dev/null +++ b/kmpp/base/kmpp_vdec_cfg.c @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_vdec_cfg" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "kmpp_obj.h" +#include "rk_vdec_kcfg.h" + +#define VDEC_KCFG_DBG_FUNC (0x00000001) +#define VDEC_KCFG_DBG_INFO (0x00000002) +#define VDEC_KCFG_DBG_SET (0x00000004) +#define VDEC_KCFG_DBG_GET (0x00000008) + +#define vdec_kcfg_dbg(flag, fmt, ...) mpp_dbg_f(vdec_kcfg_debug, flag, fmt, ## __VA_ARGS__) + +#define vdec_kcfg_dbg_func(fmt, ...) vdec_kcfg_dbg(VDEC_KCFG_DBG_FUNC, fmt, ## __VA_ARGS__) +#define vdec_kcfg_dbg_info(fmt, ...) vdec_kcfg_dbg(VDEC_KCFG_DBG_INFO, fmt, ## __VA_ARGS__) +#define vdec_kcfg_dbg_set(fmt, ...) vdec_kcfg_dbg(VDEC_KCFG_DBG_SET, fmt, ## __VA_ARGS__) +#define vdec_kcfg_dbg_get(fmt, ...) vdec_kcfg_dbg(VDEC_KCFG_DBG_GET, fmt, ## __VA_ARGS__) + +static RK_U32 vdec_kcfg_debug = 0; + +static char *kcfg_names[] = { + [MPP_VDEC_KCFG_TYPE_INIT] = "KmppVdecInitCfg", + [MPP_VDEC_KCFG_TYPE_DEINIT] = "KmppVdecDeinitCfg", + [MPP_VDEC_KCFG_TYPE_RESET] = "KmppVdecResetCfg", + [MPP_VDEC_KCFG_TYPE_START] = "KmppVdecStartCfg", + [MPP_VDEC_KCFG_TYPE_STOP] = "KmppVdecStopCfg", +}; +static KmppObjDef kcfg_defs[MPP_VDEC_KCFG_TYPE_BUTT] = {NULL}; + +static void mpp_vdec_kcfg_def_init(void) +{ + RK_U32 i; + + for (i = 0; i < MPP_VDEC_KCFG_TYPE_BUTT; i++) { + kmpp_objdef_get(&kcfg_defs[i], 0, kcfg_names[i]); + } +} + +static void mpp_vdec_kcfg_def_deinit(void) +{ + RK_U32 i; + + for (i = 0; i < MPP_VDEC_KCFG_TYPE_BUTT; i++) { + if (kcfg_defs[i]) { + kmpp_objdef_put(kcfg_defs[i]); + kcfg_defs[i] = NULL; + } + } +} + +MPP_SINGLETON(MPP_SGLN_KMPP_VDEC_CFG, kmpp_vdec_cfg, mpp_vdec_kcfg_def_init, mpp_vdec_kcfg_def_deinit) + +MPP_RET mpp_vdec_kcfg_init(MppVdecKcfg *cfg, MppVdecKcfgType type) +{ + KmppObj obj = NULL; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return MPP_ERR_NULL_PTR; + } + + if (type >= MPP_VDEC_KCFG_TYPE_BUTT) { + mpp_err_f("invalid config type %d\n", type); + return MPP_ERR_VALUE; + } + + mpp_env_get_u32("vdec_kcfg_debug", &vdec_kcfg_debug, 0); + + if (kcfg_defs[type]) + kmpp_obj_get_f(&obj, kcfg_defs[type]); + + *cfg = obj; + + return obj ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_vdec_kcfg_init_by_name(MppVdecKcfg *cfg, const char *name) +{ + KmppObj obj = NULL; + MppVdecKcfgType type = MPP_VDEC_KCFG_TYPE_BUTT; + RK_U32 i; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return MPP_ERR_NULL_PTR; + } + + for (i = 0; i < MPP_VDEC_KCFG_TYPE_BUTT; i++) { + if (!strncmp(name, kcfg_names[i], strlen(kcfg_names[i]))) { + type = i; + break; + } + } + + if (type >= MPP_VDEC_KCFG_TYPE_BUTT) { + mpp_err_f("invalid config name %s\n", name); + return MPP_ERR_VALUE; + } + + mpp_env_get_u32("vdec_kcfg_debug", &vdec_kcfg_debug, 0); + + kmpp_obj_get_f(&obj, kcfg_defs[type]); + + *cfg = obj; + + return obj ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_vdec_kcfg_deinit(MppVdecKcfg cfg) +{ + KmppObj obj = cfg; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return MPP_ERR_NULL_PTR; + } + + return kmpp_obj_put_f(obj); +} + +#define MPP_VDEC_KCFG_ACCESS(set_type, get_type, cfg_type) \ + MPP_RET mpp_vdec_kcfg_set_##cfg_type(MppVdecKcfg cfg, const char *name, set_type val) \ + { \ + if (!cfg || !name) { \ + mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \ + return MPP_ERR_NULL_PTR; \ + } \ + KmppObj obj = (KmppObj)cfg; \ + MPP_RET ret = (MPP_RET)kmpp_obj_set_##cfg_type(obj, name, val); \ + return ret; \ + } \ + MPP_RET mpp_vdec_kcfg_get_##cfg_type(MppVdecKcfg cfg, const char *name, get_type val) \ + { \ + if (!cfg || !name) { \ + mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \ + return MPP_ERR_NULL_PTR; \ + } \ + KmppObj obj = (KmppObj)cfg; \ + MPP_RET ret = (MPP_RET)kmpp_obj_get_##cfg_type(obj, name, val); \ + return ret; \ + } + +MPP_VDEC_KCFG_ACCESS(RK_S32, RK_S32*, s32); +MPP_VDEC_KCFG_ACCESS(RK_U32, RK_U32*, u32); +MPP_VDEC_KCFG_ACCESS(RK_S64, RK_S64*, s64); +MPP_VDEC_KCFG_ACCESS(RK_U64, RK_U64*, u64); +MPP_VDEC_KCFG_ACCESS(void *, void **, ptr); +MPP_VDEC_KCFG_ACCESS(void *, void *, st); + +void mpp_vdec_kcfg_show(MppVdecKcfg cfg) +{ + KmppObj obj = cfg; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return; + } + + kmpp_obj_udump(obj); +} diff --git a/kmpp/base/kmpp_venc_cfg.c b/kmpp/base/kmpp_venc_cfg.c new file mode 100644 index 000000000..2a8b8469d --- /dev/null +++ b/kmpp/base/kmpp_venc_cfg.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_venc_cfg" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "kmpp_obj.h" +#include "rk_venc_kcfg.h" + +#define VENC_KCFG_DBG_FUNC (0x00000001) +#define VENC_KCFG_DBG_INFO (0x00000002) +#define VENC_KCFG_DBG_SET (0x00000004) +#define VENC_KCFG_DBG_GET (0x00000008) + +#define venc_kcfg_dbg(flag, fmt, ...) mpp_dbg_f(venc_kcfg_debug, flag, fmt, ## __VA_ARGS__) + +#define venc_kcfg_dbg_func(fmt, ...) venc_kcfg_dbg(VENC_KCFG_DBG_FUNC, fmt, ## __VA_ARGS__) +#define venc_kcfg_dbg_info(fmt, ...) venc_kcfg_dbg(VENC_KCFG_DBG_INFO, fmt, ## __VA_ARGS__) +#define venc_kcfg_dbg_set(fmt, ...) venc_kcfg_dbg(VENC_KCFG_DBG_SET, fmt, ## __VA_ARGS__) +#define venc_kcfg_dbg_get(fmt, ...) venc_kcfg_dbg(VENC_KCFG_DBG_GET, fmt, ## __VA_ARGS__) + +static RK_U32 venc_kcfg_debug = 0; + +static char *kcfg_names[] = { + [MPP_VENC_KCFG_TYPE_INIT] = "KmppVencInitCfg", + [MPP_VENC_KCFG_TYPE_DEINIT] = "KmppVencDeinitCfg", + [MPP_VENC_KCFG_TYPE_RESET] = "KmppVencResetCfg", + [MPP_VENC_KCFG_TYPE_START] = "KmppVencStartCfg", + [MPP_VENC_KCFG_TYPE_STOP] = "KmppVencStopCfg", + [MPP_VENC_KCFG_TYPE_ST_CFG] = "KmppVencStCfg", +}; +static KmppObjDef kcfg_defs[MPP_VENC_KCFG_TYPE_BUTT] = {NULL}; + +static void mpp_venc_kcfg_def_init(void) +{ + RK_U32 i; + + for (i = 0; i < MPP_VENC_KCFG_TYPE_BUTT; i++) { + kmpp_objdef_get(&kcfg_defs[i], 0, kcfg_names[i]); + } +} + +static void mpp_venc_kcfg_def_deinit(void) +{ + RK_U32 i; + + for (i = 0; i < MPP_VENC_KCFG_TYPE_BUTT; i++) { + if (kcfg_defs[i]) { + kmpp_objdef_put(kcfg_defs[i]); + kcfg_defs[i] = NULL; + } + } +} + +MPP_SINGLETON(MPP_SGLN_KMPP_VENC_CFG, kmpp_venc_cfg, mpp_venc_kcfg_def_init, mpp_venc_kcfg_def_deinit) + +MPP_RET mpp_venc_kcfg_init(MppVencKcfg *cfg, MppVencKcfgType type) +{ + KmppObj obj = NULL; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return MPP_ERR_NULL_PTR; + } + + if (type >= MPP_VENC_KCFG_TYPE_BUTT) { + mpp_err_f("invalid config type %d\n", type); + return MPP_ERR_VALUE; + } + + mpp_env_get_u32("venc_kcfg_debug", &venc_kcfg_debug, 0); + + if (kcfg_defs[type]) + kmpp_obj_get_f(&obj, kcfg_defs[type]); + + *cfg = obj; + + return obj ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_venc_kcfg_init_by_name(MppVencKcfg *cfg, const char *name) +{ + KmppObj obj = NULL; + MppVencKcfgType type = MPP_VENC_KCFG_TYPE_BUTT; + RK_U32 i; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return MPP_ERR_NULL_PTR; + } + + for (i = 0; i < MPP_VENC_KCFG_TYPE_BUTT; i++) { + if (!strncmp(name, kcfg_names[i], strlen(kcfg_names[i]))) { + type = i; + break; + } + } + + if (type >= MPP_VENC_KCFG_TYPE_BUTT) { + mpp_err_f("invalid config name %s\n", name); + return MPP_ERR_VALUE; + } + + mpp_env_get_u32("venc_kcfg_debug", &venc_kcfg_debug, 0); + + kmpp_obj_get_f(&obj, kcfg_defs[type]); + + *cfg = obj; + + return obj ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_venc_kcfg_deinit(MppVencKcfg cfg) +{ + KmppObj obj = cfg; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return MPP_ERR_NULL_PTR; + } + + return kmpp_obj_put_f(obj); +} + +#define MPP_VENC_KCFG_ACCESS(set_type, get_type, cfg_type) \ + MPP_RET mpp_venc_kcfg_set_##cfg_type(MppVencKcfg cfg, const char *name, set_type val) \ + { \ + if (!cfg || !name) { \ + mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \ + return MPP_ERR_NULL_PTR; \ + } \ + KmppObj obj = (KmppObj)cfg; \ + MPP_RET ret = (MPP_RET)kmpp_obj_set_##cfg_type(obj, name, val); \ + return ret; \ + } \ + MPP_RET mpp_venc_kcfg_get_##cfg_type(MppVencKcfg cfg, const char *name, get_type val) \ + { \ + if (!cfg || !name) { \ + mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \ + return MPP_ERR_NULL_PTR; \ + } \ + KmppObj obj = (KmppObj)cfg; \ + MPP_RET ret = (MPP_RET)kmpp_obj_get_##cfg_type(obj, name, val); \ + return ret; \ + } + +MPP_VENC_KCFG_ACCESS(RK_S8, RK_S8*, s8); +MPP_VENC_KCFG_ACCESS(RK_U8, RK_U8*, u8); +MPP_VENC_KCFG_ACCESS(RK_S16, RK_S16*, s16); +MPP_VENC_KCFG_ACCESS(RK_U16, RK_U16*, u16); +MPP_VENC_KCFG_ACCESS(RK_S32, RK_S32*, s32); +MPP_VENC_KCFG_ACCESS(RK_U32, RK_U32*, u32); +MPP_VENC_KCFG_ACCESS(RK_S64, RK_S64*, s64); +MPP_VENC_KCFG_ACCESS(RK_U64, RK_U64*, u64); +MPP_VENC_KCFG_ACCESS(void *, void **, ptr); +MPP_VENC_KCFG_ACCESS(void *, void *, st); + +void mpp_venc_kcfg_show(MppVencKcfg cfg) +{ + KmppObj obj = cfg; + + if (!cfg) { + mpp_err_f("invalid NULL input config\n"); + return; + } + + kmpp_obj_udump(obj); +} diff --git a/kmpp/base/test/CMakeLists.txt b/kmpp/base/test/CMakeLists.txt new file mode 100644 index 000000000..beb45ffb2 --- /dev/null +++ b/kmpp/base/test/CMakeLists.txt @@ -0,0 +1,32 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# kmpp/base built-in unit test case +# ---------------------------------------------------------------------------- +# macro for adding osal sub-module unit test +macro(add_kmpp_base_test module) + set(test_name ${module}_test) + string(TOUPPER ${test_name} test_tag) + #message(STATUS "moduule : ${module}") + #message(STATUS "test_name : ${test_name}") + #message(STATUS "test_tag : ${test_tag}") + + option(${test_tag} "Build base ${module} unit test" ${BUILD_TEST}) + if(${test_tag}) + add_executable(${test_name} ${test_name}.c) + target_link_libraries(${test_name} ${MPP_SHARED}) + set_target_properties(${test_name} PROPERTIES FOLDER "kmpp/test") + add_test(NAME ${test_name} COMMAND ${test_name}) + endif() +endmacro() + +# kmpp object unit test +add_kmpp_base_test(kmpp_obj) + +# kmpp frame unit test +add_kmpp_base_test(kmpp_frame) + +# kmpp buffer unit test +add_kmpp_base_test(kmpp_buffer) + +# kmpp meta unit test +add_kmpp_base_test(kmpp_meta) diff --git a/kmpp/base/test/kmpp_buffer_test.c b/kmpp/base/test/kmpp_buffer_test.c new file mode 100644 index 000000000..60bf42834 --- /dev/null +++ b/kmpp/base/test/kmpp_buffer_test.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_buffer_test" + +#include "mpp_debug.h" + +#include "kmpp_obj.h" +#include "kmpp_buffer.h" + +int main(void) +{ + KmppShmPtr sptr; + KmppBufGrp grp = NULL; + KmppBufGrpCfg grp_cfg = NULL; + KmppBuffer buf = NULL; + KmppBufCfg buf_cfg = NULL; + rk_s32 used = 0; + rk_s32 unused = 0; + rk_u32 size = 1920 * 1080 * 3 / 2; + rk_s32 ret = rk_ok; + + mpp_logi(MODULE_TAG " start\n"); + + /* KmppBufGrp object ready */ + ret = kmpp_buf_grp_get(&grp); + mpp_logi("object %s ready\n", kmpp_obj_get_name(grp)); + + /* get KmppBufGrpCfg from KmppBufGrp to config */ + grp_cfg = kmpp_buf_grp_to_cfg(grp); + mpp_logi("object %s ready\n", kmpp_obj_get_name(grp_cfg)); + + /* write parameters to KmppBufGrpCfg */ + ret |= kmpp_buf_grp_cfg_set_flag(grp_cfg, 0); + ret |= kmpp_buf_grp_cfg_set_count(grp_cfg, 10); + ret |= kmpp_buf_grp_cfg_set_size(grp_cfg, size); + ret |= kmpp_buf_grp_cfg_set_fd(grp_cfg, -1); + + sptr.uptr = "rk dma heap"; + sptr.kaddr = 0; + ret |= kmpp_buf_grp_cfg_set_allocator(grp_cfg, &sptr); + + sptr.uptr = "test"; + sptr.kaddr = 0; + ret |= kmpp_buf_grp_cfg_set_name(grp_cfg, &sptr); + if (ret) + mpp_loge("set buf grp cfg failed\n"); + + /* enable KmppBufGrpCfg by ioctl */ + ret = kmpp_buf_grp_setup(grp); + if (ret) + mpp_loge("setup buf grp cfg failed\n"); + + /* get KmppBuffer for buffer allocation */ + ret = kmpp_buffer_get(&buf); + mpp_logi("object %s ready\n", kmpp_obj_get_name(buf)); + + /* get KmppBufCfg to setup */ + buf_cfg = kmpp_buffer_to_cfg(buf); + mpp_logi("object %s ready\n", kmpp_obj_get_name(buf_cfg)); + + /* setup buffer config parameters */ + ret = kmpp_buf_cfg_set_group(buf_cfg, kmpp_obj_to_shm(grp)); + if (ret) + mpp_loge("set kmpp_buf_cfg_set_group failed\n"); + + /* set buffer size */ + kmpp_buf_cfg_set_size(buf_cfg, size); + + /* enable KmppBufCfg by ioctl */ + kmpp_buffer_setup(buf); + if (ret) + mpp_loge("setup buf grp cfg failed\n"); + + /* get buffer group from buf_cfg */ + ret = kmpp_buf_cfg_get_group(buf_cfg, &sptr); + if (ret) + mpp_loge("get buf cfg grp failed"); + + /* get buffer share pointer and access */ + ret = kmpp_buf_cfg_get_sptr(buf_cfg, &sptr); + if (ret || !sptr.uptr) + mpp_loge("get buf cfg sptr failed"); + + ret = kmpp_buf_grp_cfg_get_used(grp_cfg, &used); + ret |= kmpp_buf_grp_cfg_get_unused(grp_cfg, &unused); + if (ret) + mpp_loge("get buf grp cfg used failed"); + + mpp_logi("buf grp cfg used %d unused %d after buffer_setup\n", used, unused); + + mpp_assert(used == 1); + + if (sptr.uptr) { + rk_u32 *val = sptr.uptr; + + memset(sptr.uptr, 0xff, size); + + *val = 0x12345678; + if (*val != 0x12345678) + mpp_loge("buf cfg sptr access failed"); + else + mpp_logi("buf sptr [u:k] %p:%llx access success", sptr.uptr, sptr.kaddr); + } + + if (buf) { + kmpp_buffer_put(buf); + buf = NULL; + } + + ret = kmpp_buf_grp_cfg_get_used(grp_cfg, &used); + ret |= kmpp_buf_grp_cfg_get_unused(grp_cfg, &unused); + if (ret) + mpp_loge("get buf grp cfg used failed"); + + mpp_logi("buf grp cfg used %d unused %d after buffer_put\n", used, unused); + + if (grp) { + kmpp_buf_grp_put(grp); + grp = NULL; + } + + mpp_logi(MODULE_TAG " %s\n", ret ? "failed" : "success"); + + return ret; +} diff --git a/kmpp/base/test/kmpp_frame_test.c b/kmpp/base/test/kmpp_frame_test.c new file mode 100644 index 000000000..1e847ce0f --- /dev/null +++ b/kmpp/base/test/kmpp_frame_test.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_frame_test" + +#include "mpp_debug.h" +#include "kmpp_frame.h" + +#define KMPP_FRAME_TEST_SIZE 1024 + +#define TEST_CHECK(ret, func, ...) \ + do { \ + ret = func(__VA_ARGS__); \ + if (ret) { \ + mpp_err(MODULE_TAG " %s failed ret %d\n", #func, ret); \ + goto failed; \ + } \ + } while (0) + +int main(void) +{ + KmppFrame frame = NULL; + rk_u32 width = 1920; + rk_u32 height = 1080; + rk_u32 val = 0; + rk_s32 ret = rk_ok; + + mpp_log(MODULE_TAG " start\n"); + + TEST_CHECK(ret, kmpp_frame_get, &frame); + TEST_CHECK(ret, kmpp_frame_set_width, frame, width); + TEST_CHECK(ret, kmpp_frame_set_height, frame, height); + + kmpp_frame_dump(frame, "test"); + + TEST_CHECK(ret, kmpp_frame_get_width, frame, &val); + mpp_assert(val == width); + TEST_CHECK(ret, kmpp_frame_get_height, frame, &val); + mpp_assert(val == height); + +failed: + kmpp_frame_put(frame); + + mpp_log(MODULE_TAG " %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/kmpp/base/test/kmpp_meta_test.c b/kmpp/base/test/kmpp_meta_test.c new file mode 100644 index 000000000..b3d3740bb --- /dev/null +++ b/kmpp/base/test/kmpp_meta_test.c @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_meta_test" + +#include + +#include "mpp_time.h" +#include "mpp_debug.h" +#include "kmpp_meta_impl.h" + +#define TEST_MAX 1 +#define LOOP_MAX 10 + +void *meta_test(void *param) +{ + RK_S32 loop_max = LOOP_MAX; + RK_S64 time_start; + RK_S64 time_end; + MppMeta meta[LOOP_MAX]; + MPP_RET ret = MPP_OK; + KmppShmPtr frame; + KmppShmPtr packet; + KmppShmPtr buffer; + KmppShmPtr sptr; + void *ptr; + RK_S32 val; + RK_S32 i; + + time_start = mpp_time(); + + frame.uaddr = 0; + frame.kaddr = 0; + packet.uaddr = 0; + packet.kaddr = 0; + buffer.uaddr = 0; + buffer.kaddr = 0; + sptr.uaddr = 0; + sptr.kaddr = 0; + + for (i = 0; i < loop_max; i++) { + ret |= kmpp_meta_get_f(&meta[i]); + mpp_assert(meta[i]); + } + + for (i = 0; i < loop_max; i++) { + /* set */ + ret |= kmpp_meta_set_shm(meta[i], KEY_INPUT_FRAME, &frame); + ret |= kmpp_meta_set_shm(meta[i], KEY_INPUT_PACKET, &packet); + ret |= kmpp_meta_set_shm(meta[i], KEY_OUTPUT_FRAME, &frame); + ret |= kmpp_meta_set_shm(meta[i], KEY_OUTPUT_PACKET, &packet); + + ret |= kmpp_meta_set_shm(meta[i], KEY_MOTION_INFO, &sptr); + ret |= kmpp_meta_set_shm(meta[i], KEY_HDR_INFO, &sptr); + + ret |= kmpp_meta_set_s32(meta[i], KEY_INPUT_BLOCK, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_OUTPUT_BLOCK, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_INPUT_IDR_REQ, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_OUTPUT_INTRA, 0); + + ret |= kmpp_meta_set_s32(meta[i], KEY_TEMPORAL_ID, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_LONG_REF_IDX, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_ENC_AVERAGE_QP, 0); + + //ret |= kmpp_meta_set_shm(meta[i], KEY_ROI_DATA, NULL); + ret |= kmpp_meta_set_shm(meta[i], KEY_OSD_DATA, NULL); + ret |= kmpp_meta_set_shm(meta[i], KEY_OSD_DATA2, NULL); + ret |= kmpp_meta_set_shm(meta[i], KEY_USER_DATA, NULL); + ret |= kmpp_meta_set_shm(meta[i], KEY_USER_DATAS, NULL); + + ret |= kmpp_meta_set_shm(meta[i], KEY_QPMAP0, NULL); + ret |= kmpp_meta_set_shm(meta[i], KEY_NPU_SOBJ_FLAG, NULL); + ret |= kmpp_meta_set_ptr(meta[i], KEY_NPU_UOBJ_FLAG, NULL); + + ret |= kmpp_meta_set_s32(meta[i], KEY_ENC_MARK_LTR, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_ENC_USE_LTR, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_ENC_FRAME_QP, 0); + ret |= kmpp_meta_set_s32(meta[i], KEY_ENC_BASE_LAYER_PID, 0); + + /* get */ + ret |= kmpp_meta_get_shm(meta[i], KEY_INPUT_FRAME, &frame); + ret |= kmpp_meta_get_shm(meta[i], KEY_INPUT_PACKET, &packet); + ret |= kmpp_meta_get_shm(meta[i], KEY_OUTPUT_FRAME, &frame); + ret |= kmpp_meta_get_shm(meta[i], KEY_OUTPUT_PACKET, &packet); + + ret |= kmpp_meta_get_shm(meta[i], KEY_MOTION_INFO, &buffer); + ret |= kmpp_meta_get_shm(meta[i], KEY_HDR_INFO, &buffer); + + ret |= kmpp_meta_get_s32(meta[i], KEY_INPUT_BLOCK, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_OUTPUT_BLOCK, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_INPUT_IDR_REQ, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_OUTPUT_INTRA, &val); + + ret |= kmpp_meta_get_s32(meta[i], KEY_TEMPORAL_ID, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_LONG_REF_IDX, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_ENC_AVERAGE_QP, &val); + + //ret |= kmpp_meta_get_shm(meta[i], KEY_ROI_DATA, &sptr); + ret |= kmpp_meta_get_shm(meta[i], KEY_OSD_DATA, &sptr); + ret |= kmpp_meta_get_shm(meta[i], KEY_OSD_DATA2, &sptr); + ret |= kmpp_meta_get_shm(meta[i], KEY_USER_DATA, &sptr); + ret |= kmpp_meta_get_shm(meta[i], KEY_USER_DATAS, &sptr); + + ret |= kmpp_meta_get_shm(meta[i], KEY_QPMAP0, &buffer); + ret |= kmpp_meta_get_shm(meta[i], KEY_NPU_SOBJ_FLAG, &sptr); + ret |= kmpp_meta_get_ptr(meta[i], KEY_NPU_UOBJ_FLAG, &ptr); + + ret |= kmpp_meta_get_s32(meta[i], KEY_ENC_MARK_LTR, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_ENC_USE_LTR, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_ENC_FRAME_QP, &val); + ret |= kmpp_meta_get_s32(meta[i], KEY_ENC_BASE_LAYER_PID, &val); + } + + for (i = 0; i < loop_max; i++) { + ret |= kmpp_meta_put_f(meta[i]); + } + + time_end = mpp_time(); + + if (ret) + mpp_log("meta setting and getting, ret %d\n", ret); + + *((RK_S64 *)param) = (time_end - time_start) / loop_max; + + return NULL; +} + +int main(void) +{ + pthread_t thds[TEST_MAX]; + RK_S64 times[TEST_MAX]; + RK_S32 thd_cnt = TEST_MAX; + RK_S64 avg_time = 0; + pthread_attr_t attr; + RK_S32 i; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + mpp_log(MODULE_TAG " start\n"); + + for (i = 0; i < thd_cnt; i++) + pthread_create(&thds[i], &attr, meta_test, ×[i]); + + for (i = 0; i < thd_cnt; i++) + pthread_join(thds[i], NULL); + + for (i = 0; i < thd_cnt; i++) + avg_time += times[i]; + + mpp_log(MODULE_TAG " %d threads %d loop config avg %lld us", + thd_cnt, LOOP_MAX, avg_time / thd_cnt); + + mpp_log(MODULE_TAG " done\n"); + + return 0; +} diff --git a/kmpp/base/test/kmpp_obj_test.c b/kmpp/base/test/kmpp_obj_test.c new file mode 100644 index 000000000..bd5887ed6 --- /dev/null +++ b/kmpp/base/test/kmpp_obj_test.c @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_obj_test" + +#include "mpp_log.h" +#include "mpp_common.h" + +#include "kmpp_obj.h" +#include "kmpp_buffer.h" + +#define TEST_DETAIL 1 +#define TEST_DEF_DUMP 2 +#define TEST_OBJ_UDUMP 4 +#define TEST_OBJ_KDUMP 8 + +#define test_detail(fmt, ...) \ + do { \ + if (flag & TEST_DETAIL) \ + mpp_log(fmt, ##__VA_ARGS__); \ + } while (0) + +typedef struct KmppObjTest_t { + const char *name; + rk_u32 flag; + rk_s32 (*func)(const char *name, rk_u32 flag); +} KmppObjTest; + +static rk_s32 kmpp_obj_std_test(const char *name, rk_u32 flag) +{ + KmppObjDef def = NULL; + KmppObj obj = NULL; + MPP_RET ret = MPP_NOK; + + ret = kmpp_objdef_find(&def, name); + if (ret) { + mpp_log("kmpp_objdef_find %s failed\n", name); + goto done; + } + + if (flag & TEST_DEF_DUMP) + kmpp_objdef_dump(def); + + ret = kmpp_obj_get_f(&obj, def); + if (ret) { + mpp_log("kmpp_obj_get %s failed ret %d\n", name, ret); + goto done; + } + + if (flag & TEST_OBJ_UDUMP) + kmpp_obj_udump(obj); + if (flag & TEST_OBJ_KDUMP) + kmpp_obj_kdump(obj); + + ret = kmpp_obj_put_f(obj); + if (ret) { + mpp_log("kmpp_obj_put %s failed\n", name); + } + obj = NULL; + def = NULL; + +done: + if (obj) + kmpp_obj_put_f(obj); + + return ret; +} + +static rk_s32 kmpp_obj_by_name_test(const char *name, rk_u32 flag) +{ + KmppObj obj = NULL; + MPP_RET ret = MPP_NOK; + + ret = kmpp_obj_get_by_name_f(&obj, name); + if (ret) { + mpp_log("kmpp_obj_get_by_name %s failed ret %d\n", name, ret); + goto done; + } + + if (flag & TEST_OBJ_UDUMP) + kmpp_obj_udump(obj); + if (flag & TEST_OBJ_KDUMP) + kmpp_obj_kdump(obj); + + ret = kmpp_obj_put_f(obj); + if (ret) { + mpp_log("kmpp_obj_put %s failed\n", name); + goto done; + } + obj = NULL; + +done: + if (obj) + kmpp_obj_put_f(obj); + + return ret; +} + +static rk_s32 kmpp_buffer_test(const char *name, rk_u32 flag) +{ + KmppShmPtr sptr; + KmppObj grp = NULL; + KmppObj grp_cfg = NULL; + KmppObj buf = NULL; + KmppObj buf_cfg = NULL; + MPP_RET ret = MPP_NOK; + rk_u32 val = 0; + + ret = kmpp_obj_get_by_name_f(&grp, "KmppBufGrp"); + if (ret) { + mpp_log("buf grp get obj failed ret %d\n", ret); + goto done; + } + + /* KmppBufGrp object ready */ + test_detail("object %s ready\n", kmpp_obj_get_name(grp)); + + /* get KmppBufGrpCfg from KmppBufGrp to config */ + grp_cfg = kmpp_buf_grp_to_cfg(grp); + if (!grp_cfg) { + mpp_log("buf grp to cfg failed ret %d\n", ret); + ret = MPP_NOK; + goto done; + } + + /* KmppBufGrpCfg object ready */ + test_detail("object %s ready\n", kmpp_obj_get_name(grp_cfg)); + + if (flag & TEST_OBJ_UDUMP) + kmpp_obj_udump(buf_cfg); + + /* write parameters to KmppBufGrpCfg */ + ret = kmpp_obj_set_u32(grp_cfg, "flag", 0); + if (ret) { + mpp_log("grp cfg set flag failed ret %d\n", ret); + goto done; + } + + ret = kmpp_obj_set_u32(grp_cfg, "count", 10); + if (ret) { + mpp_log("grp cfg set count failed ret %d\n", ret); + goto done; + } + + ret = kmpp_obj_set_u32(grp_cfg, "size", 4096); + if (ret) { + mpp_log("grp cfg set size failed ret %d\n", ret); + goto done; + } + + ret = kmpp_obj_set_s32(grp_cfg, "fd", -1); + if (ret) { + mpp_log("grp cfg set fd failed ret %d\n", ret); + goto done; + } + + /* set buffer group name to test */ + name = "allocator"; + sptr.kaddr = 0; + sptr.uptr = "rk dma heap"; + + ret = kmpp_obj_set_shm(grp_cfg, name, &sptr); + if (ret) { + mpp_log("grp cfg set %s failed ret %d\n", name, ret); + goto done; + } + + /* set buffer group name to test */ + name = "name"; + sptr.kaddr = 0; + sptr.uptr = "test"; + + ret = kmpp_obj_set_shm(grp_cfg, name, &sptr); + if (ret) { + mpp_log("grp cfg set %s failed ret %d\n", name, ret); + goto done; + } + + test_detail("object %s write parameters ready\n", kmpp_obj_get_name(grp_cfg)); + + /* enable KmppBufGrpCfg by ioctl */ + ret = kmpp_buf_grp_setup(grp); + + test_detail("object %s ioctl ret %d\n", kmpp_obj_get_name(grp), ret); + + /* get KmppBuffer for buffer allocation */ + ret = kmpp_obj_get_by_name_f(&buf, "KmppBuffer"); + if (ret) { + mpp_log("kmpp_obj_get_by_name failed ret %d\n", ret); + goto done; + } + + test_detail("object %s ready\n", kmpp_obj_get_name(buf)); + + /* get KmppBufGrpCfg to setup */ + buf_cfg = kmpp_buffer_to_cfg(buf); + if (!buf_cfg) { + mpp_log("buf to cfg failed ret %d\n", ret); + ret = MPP_NOK; + goto done; + } + + if (flag & TEST_OBJ_UDUMP) + kmpp_obj_udump(buf_cfg); + + test_detail("object %s ready\n", kmpp_obj_get_name(buf_cfg)); + + /* setup buffer config parameters */ + /* set buffer group */ + ret = kmpp_obj_set_shm_obj(buf_cfg, "group", grp); + if (ret) { + mpp_log("buf cfg set group failed ret %d\n", ret); + goto done; + } + + /* enable KmppBufferCfg by ioctl */ + ret = kmpp_buffer_setup(buf); + + test_detail("object %s ioctl ret %d\n", kmpp_obj_get_name(buf), ret); + + kmpp_obj_get_u32(buf_cfg, "size", &val); + + test_detail("object %s size %d\n", kmpp_obj_get_name(buf_cfg), val); + +done: + if (grp) + kmpp_obj_put_f(grp); + + if (buf) + kmpp_obj_put_f(buf); + + return ret; +} + +static rk_s32 kmpp_shm_test(const char *name, rk_u32 flag) +{ + rk_u32 sizes[] = {512, SZ_4K, SZ_16K, SZ_128K, SZ_256K, SZ_1M, SZ_4M, SZ_16M}; + rk_u32 count = sizeof(sizes) / sizeof(sizes[0]); + KmppShm shm[count]; + void *ptr; + rk_s32 ret = rk_ok; + rk_s32 i; + (void)name; + (void)flag; + + memset(shm, 0, sizeof(shm)); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sizes); i++) { + kmpp_shm_get_f(&shm[i], sizes[i]); + if (!shm[i]) { + mpp_log_f("shm get size %d failed\n", sizes[i]); + ret = rk_nok; + break; + } + + test_detail("shm get size %d addr %p\n", sizes[i], kmpp_shm_to_entry_f(shm[i])); + } + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(sizes); i++) { + if (!shm[i]) + continue; + + if (kmpp_shm_put_f(shm[i])) { + mpp_log_f("shm put size %d failed\n", sizes[i]); + ret = rk_nok; + break; + } + shm[i] = NULL; + } + + if (ret) + return ret; + + for (i = (RK_S32)MPP_ARRAY_ELEMS(sizes) - 1; i >= 0; i--) { + kmpp_shm_get_f(&shm[i], sizes[i]); + if (!shm[i]) { + mpp_log_f("shm get size %d failed\n", sizes[i]); + ret = rk_nok; + } + + if (ret) + break; + + ptr = kmpp_shm_to_entry_f(shm[i]); + + test_detail("shm get size %d addr %p\n", sizes[i], ptr); + + if (ptr) + memset(ptr, 0, sizes[i]); + + if (kmpp_shm_put_f(shm[i])) { + mpp_log_f("shm put size %d failed\n", sizes[i]); + ret = rk_nok; + } + } + + return ret; +} + +static KmppObjTest obj_tests[] = { + { + "KmppFrame", + 0, + kmpp_obj_std_test, + }, + { + "KmppVencInitCfg", + 0, + kmpp_obj_by_name_test, + }, + { + "KmppBuffer", + 0, + kmpp_buffer_test, + }, + { + "kmpp_shm_test", + 0, + kmpp_shm_test, + }, +}; + +int main(void) +{ + MPP_RET ret = MPP_NOK; + rk_u32 i; + + mpp_log("start\n"); + + for (i = 0; i < MPP_ARRAY_ELEMS(obj_tests); i++) { + const char *name = obj_tests[i].name; + rk_u32 flag = obj_tests[i].flag; + + ret = obj_tests[i].func(name, flag); + if (ret) { + mpp_log("test %-16s failed ret %d\n", name, ret); + goto done; + } + mpp_log("test %-16s success\n", name); + } + +done: + mpp_log("done %s \n", ret ? "failed" : "success"); + + return ret; +} diff --git a/kmpp/inc/kmpp.h b/kmpp/inc/kmpp.h new file mode 100644 index 000000000..01c44a1f9 --- /dev/null +++ b/kmpp/inc/kmpp.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_H +#define KMPP_H + +#include + +#include "mpp_impl.h" +#include "mpp_dec_cfg.h" +#include "mpp_enc_cfg.h" +#include "mpp_mem_pool.h" +#include "kmpp_obj.h" + +typedef struct Kmpp_t Kmpp; +typedef struct KmppOps_t { + MPP_RET (*open_client)(Kmpp *ctx); + MPP_RET (*init)(Kmpp *ctx, MppCtxType type, MppCodingType coding); + + MPP_RET (*start)(Kmpp *ctx); + MPP_RET (*stop)(Kmpp *ctx); + + MPP_RET (*pause)(Kmpp *ctx); + MPP_RET (*resume)(Kmpp *ctx); + + MPP_RET (*put_packet)(Kmpp *ctx, MppPacket packet); + MPP_RET (*get_frame)(Kmpp *ctx, MppFrame *frame); + + MPP_RET (*put_frame)(Kmpp *ctx, MppFrame frame); + MPP_RET (*get_packet)(Kmpp *ctx, MppPacket *packet); + MPP_RET (*release_packet)(Kmpp *ctx, MppPacket *packet); + + MPP_RET (*poll)(Kmpp *ctx, MppPortType type, MppPollType timeout); + MPP_RET (*dequeue)(Kmpp *ctx, MppPortType type, MppTask *task); + MPP_RET (*enqueue)(Kmpp *ctx, MppPortType type, MppTask task); + + MPP_RET (*reset)(Kmpp *ctx); + MPP_RET (*control)(Kmpp *ctx, MpiCmd cmd, MppParam param); + + MPP_RET (*notify_flag)(Kmpp *ctx, RK_U32 flag); + MPP_RET (*notify)(Kmpp *ctx, MppBufferGroup group); + + MPP_RET (*get_fd)(Kmpp *ctx, RK_S32 *fd); + MPP_RET (*close_fd)(Kmpp *ctx, RK_S32 fd); + void (*clear)(Kmpp *ctx); +} KmppOps; + +struct Kmpp_t { + MppPollType mInputTimeout; + MppPollType mOutputTimeout; + + MppCtx mCtx; + RK_S32 mChanId; + RK_U32 mEncVersion; + + MppCtxType mType; + MppCodingType mCoding; + RK_U32 mChanDup; + + RK_U32 mInitDone; + + RK_S32 mClientFd; + struct timeval mTimeout; + + MppBufferGroup mPacketGroup; + MppPacket mPacket; + KmppFrame mKframe; + + KmppOps *mApi; + KmppObj mVencInitKcfg; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void mpp_get_api(Kmpp *ctx); + +#ifdef __cplusplus +} +#endif +#endif /* MPP_H */ diff --git a/kmpp/inc/kmpp_vdec.h b/kmpp/inc/kmpp_vdec.h new file mode 100644 index 000000000..92a3f6008 --- /dev/null +++ b/kmpp/inc/kmpp_vdec.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_VDEC_H +#define KMPP_VDEC_H + +#include "rk_vdec_kcfg.h" + +typedef void* KmppVdec; + +#define KMPP_VDEC_IOCTL_TABLE(prefix, IOC_CTX, IOC_IN_, IOC_OUT, IOC_IO_) \ + IOC_IN_(prefix, init, MppVdecKcfg) \ + IOC_CTX(prefix, deinit) \ + IOC_CTX(prefix, reset) \ + IOC_CTX(prefix, start) \ + IOC_CTX(prefix, stop) \ + IOC_IN_(prefix, get_cfg, MppVdecKcfg) \ + IOC_IN_(prefix, set_cfg, MppVdecKcfg) \ + IOC_IN_(prefix, get_rt_cfg, MppVdecKcfg) \ + IOC_IN_(prefix, set_rt_cfg, MppVdecKcfg) \ + IOC_IO_(prefix, decode, KmppPacket, KmppFrame) \ + IOC_IN_(prefix, put_pkt, KmppPacket) \ + IOC_OUT(prefix, get_frm, KmppFrame) \ + IOC_IN_(prefix, put_frm, KmppFrame) + +#define KMPP_OBJ_NAME kmpp_vdec +#define KMPP_OBJ_INTF_TYPE KmppVdec +#define KMPP_OBJ_FUNC_IOCTL KMPP_VDEC_IOCTL_TABLE +#include "kmpp_obj_func.h" + +#endif /* KMPP_VDEC_H */ diff --git a/kmpp/inc/kmpp_venc.h b/kmpp/inc/kmpp_venc.h new file mode 100644 index 000000000..447705c85 --- /dev/null +++ b/kmpp/inc/kmpp_venc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef KMPP_VENC_H__ +#define KMPP_VENC_H__ + +#include "rk_venc_kcfg.h" + +typedef void* KmppVenc; + +#define KMPP_VENC_IOCTL_TABLE(prefix, IOC_CTX, IOC_IN_, IOC_OUT, IOC_IO_) \ + IOC_IN_(prefix, init, MppVencKcfg) \ + IOC_CTX(prefix, deinit) \ + IOC_CTX(prefix, reset) \ + IOC_CTX(prefix, start) \ + IOC_CTX(prefix, stop) \ + IOC_CTX(prefix, suspend) \ + IOC_CTX(prefix, resume) \ + IOC_IN_(prefix, get_cfg, MppVencKcfg) \ + IOC_IN_(prefix, set_cfg, MppVencKcfg) \ + IOC_IO_(prefix, encode, KmppFrame, KmppPacket) \ + IOC_IN_(prefix, put_frm, KmppFrame) \ + IOC_OUT(prefix, get_pkt, KmppPacket) \ + IOC_IN_(prefix, put_pkt, KmppPacket) + +#define KMPP_OBJ_NAME kmpp_venc +#define KMPP_OBJ_INTF_TYPE KmppVenc +#define KMPP_OBJ_FUNC_IOCTL KMPP_VENC_IOCTL_TABLE +#include "kmpp_obj_func.h" + +#endif /* KMPP_VENC_H__*/ diff --git a/kmpp/kmpp.c b/kmpp/kmpp.c new file mode 100644 index 000000000..be227e211 --- /dev/null +++ b/kmpp/kmpp.c @@ -0,0 +1,651 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp" + +#include +#include +#include +#include +#include +#include + +#include "rk_mpi.h" + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_impl.h" +#include "mpp_2str.h" +#include "mpp_debug.h" + +#include "kmpp.h" +#include "kmpp_obj.h" +#include "mpp_soc.h" +#include "kmpp_frame.h" +#include "mpp_buffer_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" +#include "kmpp_packet.h" +#include "mpp_vcodec_client.h" +#include "mpp_enc_cfg.h" + +typedef struct KmppFrameInfos_t { + RK_U32 width; + RK_U32 height; + RK_U32 hor_stride; + RK_U32 ver_stride; + RK_U32 hor_stride_pixel; + RK_U32 offset_x; + RK_U32 offset_y; + RK_U32 fmt; + RK_U32 fd; + RK_U64 pts; + RK_S32 jpeg_chan_id; + void *osd_buf; + RK_S32 mpi_buf_id; + void *jpg_combo_osd_buf; + RK_U32 is_gray; + RK_U32 is_full; + RK_U32 phy_addr; + RK_U64 dts; + void *pp_info; + RK_U32 pskip_num; + union { + RK_U32 val; + struct { + RK_U32 eos : 1; + RK_U32 pskip : 1; + RK_U32 isr_request : 1; + }; + }; +} KmppFrameInfos; + +static void kmpp_release_venc_packet(void *ctx, void *arg) +{ + KmppPacket pkt = (KmppPacket)arg; + + if (!ctx || !pkt) { + mpp_err_f("invalid input ctx %p pkt %p\n", ctx, pkt); + return; + } + + kmpp_packet_put(pkt); +} + +static MPP_RET init(Kmpp *ctx, MppCtxType type, MppCodingType coding) +{ + MPP_RET ret = MPP_NOK; + RK_U32 chan_id; + void *hnd; + RK_U32 size; + + if (!ctx) + return MPP_ERR_VALUE; + + if (mpp_check_support_format(type, coding)) { + mpp_err("unable to create %s %s for mpp unsupported\n", + strof_ctx_type(type), strof_coding_type(coding)); + return MPP_NOK; + } + + if (ctx->mClientFd < 0) { + ctx->mClientFd = mpp_vcodec_open(); + if (ctx->mClientFd < 0) { + mpp_err("mpp_vcodec dev open failed\n"); + return MPP_NOK; + } + } + + hnd = kmpp_obj_to_shm(ctx->mVencInitKcfg); + size = kmpp_obj_to_shm_size(ctx->mVencInitKcfg); + kmpp_obj_get_u32(ctx->mVencInitKcfg, "chan_dup", &ctx->mChanDup); + kmpp_obj_set_s32(ctx->mVencInitKcfg, "chan_fd", ctx->mClientFd); + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_CREATE, 0, size, hnd); + if (ret) { + mpp_err("chan %d VCODEC_CHAN_CREATE failed\n", ctx->mChanId); + return ret; + } + + if (!ctx->mChanDup) { + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0); + if (ret) { + mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId); + return ret; + } + } + + if (ctx->mPacketGroup == NULL) + mpp_buffer_group_get_internal(&ctx->mPacketGroup, MPP_BUFFER_TYPE_ION); + + kmpp_obj_get_u32(ctx->mVencInitKcfg, "chan_id", &chan_id); + mpp_log("client %d open chan_id %d ok", ctx->mClientFd, chan_id); + ctx->mInitDone = 1; + ctx->mChanId = chan_id; + ctx->mType = type; + ctx->mOutputTimeout = MPP_POLL_BLOCK; + ctx->mTimeout.tv_sec = 2; + ctx->mTimeout.tv_usec = 100000; + + return ret; +} + +static MPP_RET open_client(Kmpp *ctx) +{ + if (!ctx) + return MPP_ERR_VALUE; + + ctx->mClientFd = mpp_vcodec_open(); + if (ctx->mClientFd < 0) { + mpp_err("mpp_vcodec dev open failed\n"); + return MPP_NOK; + } + return MPP_OK; +} + +static void clear(Kmpp *ctx) +{ + if (!ctx) + return; + + if (!ctx->mChanDup) { + MPP_RET ret; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_DESTROY, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_DESTROY failed\n", ctx->mChanId); + } + + if (ctx->mClientFd >= 0) + mpp_vcodec_close(ctx->mClientFd); + ctx->mClientFd = -1; + + if (ctx->mPacketGroup) { + mpp_buffer_group_put(ctx->mPacketGroup); + ctx->mPacketGroup = NULL; + } + + if (ctx->mKframe) { + kmpp_frame_put(ctx->mKframe); + ctx->mKframe = NULL; + } +} + +static MPP_RET start(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET stop(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_START, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_START failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET mpp_pause(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_PAUSE, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_PAUSE failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET resume(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mChanDup) + return MPP_OK; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_RESUME, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_RESUME failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET put_packet(Kmpp *ctx, MppPacket packet) +{ + (void) packet; + MPP_RET ret = MPP_OK; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET get_frame(Kmpp *ctx, MppFrame *frame) +{ + (void)frame; + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return MPP_OK; +} + +static MPP_RET put_frame(Kmpp *ctx, MppFrame frame) +{ + MPP_RET ret = MPP_OK; + KmppShmPtr *ptr = NULL; + rk_s32 size; + + if (!ctx) + return MPP_ERR_VALUE; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + if (!__check_is_mpp_frame(frame)) { + MppFrameImpl *impl = (MppFrameImpl *)frame; + + if (ctx->mKframe == NULL) + kmpp_frame_get(&ctx->mKframe); + + kmpp_frame_set_width(ctx->mKframe, impl->width); + kmpp_frame_set_height(ctx->mKframe, impl->height); + kmpp_frame_set_hor_stride(ctx->mKframe, impl->hor_stride); + kmpp_frame_set_ver_stride(ctx->mKframe, impl->ver_stride); + kmpp_frame_set_fmt(ctx->mKframe, impl->fmt); + kmpp_frame_set_eos(ctx->mKframe, impl->eos); + kmpp_frame_set_pts(ctx->mKframe, impl->pts); + kmpp_frame_set_dts(ctx->mKframe, impl->dts); + kmpp_frame_set_offset_x(ctx->mKframe, impl->offset_x); + kmpp_frame_set_offset_y(ctx->mKframe, impl->offset_y); + kmpp_frame_set_hor_stride_pixel(ctx->mKframe, impl->hor_stride_pixel); + + if (impl->buffer) { + kmpp_frame_set_buf_fd(ctx->mKframe, mpp_buffer_get_fd(impl->buffer)); + } else { + mpp_loge_f("kmpp put_frame buf is NULL\n"); + return MPP_NOK; + } + + if (mpp_frame_has_meta(frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + MppPacket packet = NULL; + + mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet); + ctx->mPacket = packet; + + /* set roi */ + { + MppEncROICfg *roi_data = NULL; + MppEncROICfgLegacy roi_data0; + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void**)&roi_data); + if (roi_data) { + roi_data0.change = 1; + roi_data0.number = roi_data->number; + memcpy(roi_data0.regions, roi_data->regions, roi_data->number * sizeof(MppEncROIRegion)); + ctx->mApi->control(ctx, MPP_ENC_SET_ROI_CFG, &roi_data0); + } + } + + /* set osd */ + { + MppEncOSDData3 *osd_data3 = NULL; + + mpp_meta_get_ptr(meta, KEY_OSD_DATA3, (void**)&osd_data3); + if (osd_data3) { + osd_data3->change = 1; + ctx->mApi->control(ctx, MPP_ENC_SET_OSD_DATA_CFG, osd_data3); + } + } + } + + ptr = kmpp_obj_to_shm(ctx->mKframe); + size = kmpp_obj_to_shm_size(ctx->mKframe); + } else { + ptr = kmpp_obj_to_shm(frame); + size = kmpp_obj_to_shm_size(frame); + } + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_IN_FRM_RDY, 0, size, ptr); + if (ret) + mpp_err("chan %d VCODEC_CHAN_IN_FRM_RDY failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET get_packet(Kmpp *ctx, MppPacket *packet) +{ + RK_S32 ret; + + if (!ctx) + return MPP_ERR_VALUE; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + struct timeval timeout; + fd_set read_fds; + + FD_ZERO(&read_fds); + FD_SET(ctx->mClientFd, &read_fds); + + memcpy(&timeout, &ctx->mTimeout, sizeof(timeout)); + ret = select(ctx->mClientFd + 1, &read_fds, NULL, NULL, &timeout); + if (ret <= 0) + return MPP_NOK; + + if (FD_ISSET(ctx->mClientFd, &read_fds)) { + KmppShmPtr sptr; + MppPacket pkt = NULL; + KmppPacket kmpp_pkt = NULL; + RK_S32 len; + RK_U32 flag; + KmppShmPtr pos; + RK_S64 dts; + RK_S64 pts; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_OUT_PKT_RDY, + 0, sizeof(KmppShmPtr), &sptr); + if (ret) { + mpp_err("chan %d VCODEC_CHAN_OUT_PKT_RDY failed\n", ctx->mChanId); + return MPP_NOK; + } + + kmpp_obj_get_by_sptr_f(&kmpp_pkt, &sptr); + kmpp_packet_get_flag(kmpp_pkt, &flag); + kmpp_packet_get_length(kmpp_pkt, &len); + kmpp_packet_get_pos(kmpp_pkt, &pos); + kmpp_packet_get_dts(kmpp_pkt, &dts); + kmpp_packet_get_pts(kmpp_pkt, &pts); + + if (ctx->mPacket) { + void *dst; + + pkt = ctx->mPacket; + ctx->mPacket = NULL; + if (pos.uptr) { + dst = mpp_packet_get_pos(pkt); + memcpy(dst, pos.uptr, len); + } + + kmpp_packet_put(kmpp_pkt); + mpp_packet_set_length(pkt, len); + } else { + mpp_packet_init(&pkt, pos.uptr, len); + mpp_packet_set_release(pkt, kmpp_release_venc_packet, ctx, kmpp_pkt); + } + + mpp_packet_set_dts(pkt, dts); + mpp_packet_set_pts(pkt, pts); + mpp_packet_set_flag(pkt, flag); + if (flag & MPP_PACKET_FLAG_INTRA) { + MppMeta meta = mpp_packet_get_meta(pkt); + + mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, 1); + } + *packet = pkt; + } + + return MPP_OK; +} + +static MPP_RET release_packet(Kmpp *ctx, MppPacket *packet) +{ + KmppPacket pkt = (KmppPacket) * packet; + + if (!ctx) + return MPP_ERR_VALUE; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + if (*packet == NULL) + return MPP_NOK; + + if (ctx->mClientFd < 0) + return MPP_NOK; + + kmpp_packet_put(pkt); + + return MPP_OK; +} + +static MPP_RET poll(Kmpp *ctx, MppPortType type, MppPollType timeout) +{ + MPP_RET ret = MPP_NOK; + (void)type; + (void)timeout; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET dequeue(Kmpp *ctx, MppPortType type, MppTask *task) +{ + MPP_RET ret = MPP_NOK; + (void)type; + (void)task; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET enqueue(Kmpp *ctx, MppPortType type, MppTask task) +{ + MPP_RET ret = MPP_NOK; + (void)type; + (void)task; + + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + return ret; +} + +static MPP_RET control(Kmpp *ctx, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + RK_U32 size = 0; + void *arg = param; + + if (!ctx) + return MPP_ERR_VALUE; + + switch (cmd) { + case MPP_ENC_SET_CFG : + case MPP_ENC_GET_CFG : { + KmppObj obj = (KmppObj)param; + + if (kmpp_obj_is_kobj(obj)) { + arg = kmpp_obj_to_shm(obj); + size = kmpp_obj_to_shm_size(obj); + } else { + mpp_loge("can not set non-kobj %p to kmpp\n", obj); + return MPP_NOK; + } + } break; + case MPP_ENC_SET_HEADER_MODE : + case MPP_ENC_SET_SEI_CFG : { + size = sizeof(RK_U32); + } break; + case MPP_ENC_GET_REF_CFG : + case MPP_ENC_SET_REF_CFG : { + size = sizeof(MppEncRefParam); + } break; + case MPP_ENC_GET_ROI_CFG: + case MPP_ENC_SET_ROI_CFG: { + size = sizeof(MppEncROICfgLegacy); + } break; + case MPP_ENC_SET_JPEG_ROI_CFG : + case MPP_ENC_GET_JPEG_ROI_CFG : { + size = sizeof(MppJpegROICfg); + } break; + case MPP_ENC_SET_OSD_DATA_CFG: { + size = sizeof(MppEncOSDData3); + } break; + case MPP_ENC_SET_USERDATA: { + size = sizeof(MppEncUserData); + } break; + case MPP_SET_VENC_INIT_KCFG: { + KmppObj obj = param; + + arg = kmpp_obj_to_shm(obj); + size = kmpp_obj_to_shm_size(obj); + } break; + case MPP_SET_SELECT_TIMEOUT: { + struct timeval *p = (struct timeval *)param; + ctx->mTimeout.tv_sec = p->tv_sec; + ctx->mTimeout.tv_usec = p->tv_usec; + return MPP_OK; + } break; + case MPP_ENC_SET_IDR_FRAME: { + size = 0; + } break; + default : { + size = 0; + return MPP_OK; + } break; + } + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_CONTROL, cmd, size, arg); + if (ret) + mpp_err("chan %d VCODEC_CHAN_CONTROL failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET reset(Kmpp *ctx) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + if (ctx->mChanDup) + return MPP_OK; + if (!ctx->mInitDone) + return MPP_ERR_INIT; + + ret = mpp_vcodec_ioctl(ctx->mClientFd, VCODEC_CHAN_RESET, 0, 0, 0); + if (ret) + mpp_err("chan %d VCODEC_CHAN_RESET failed\n", ctx->mChanId); + + return ret; +} + +static MPP_RET notify_flag(Kmpp *ctx, RK_U32 flag) +{ + (void)flag; + (void)ctx; + + return MPP_NOK; +} + +static MPP_RET notify(Kmpp *ctx, MppBufferGroup group) +{ + MPP_RET ret = MPP_OK; + (void)group; + + switch (ctx->mType) { + case MPP_CTX_DEC : { + } break; + default : { + } break; + } + + return ret; +} + +static MPP_RET get_fd(Kmpp *ctx, RK_S32 *fd) +{ + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + if (ctx->mClientFd >= 0) + *fd = fcntl(ctx->mClientFd, F_DUPFD_CLOEXEC, 3); + else + *fd = -1; + + if (*fd < 0) + ret = MPP_NOK; + + return ret; +} + +static MPP_RET close_fd(Kmpp *ctx, RK_S32 fd) +{ + if (fd >= 0) + close(fd); + (void)ctx; + return MPP_OK; +} + +static KmppOps ops = { + .open_client = open_client, + .init = init, + .start = start, + .stop = stop, + .pause = mpp_pause, + .resume = resume, + .put_packet = put_packet, + .get_frame = get_frame, + .put_frame = put_frame, + .get_packet = get_packet, + .release_packet = release_packet, + .poll = poll, + .dequeue = dequeue, + .enqueue = enqueue, + .reset = reset, + .control = control, + .notify_flag = notify_flag, + .notify = notify, + .get_fd = get_fd, + .close_fd = close_fd, + .clear = clear, +}; + +void mpp_get_api(Kmpp *ctx) +{ + if (!ctx) + return; + + ctx->mApi = &ops; +} diff --git a/kmpp/kmpp_vdec.c b/kmpp/kmpp_vdec.c new file mode 100644 index 000000000..7eae13eca --- /dev/null +++ b/kmpp/kmpp_vdec.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_vdec" + +#include "kmpp_obj.h" +#include "kmpp_vdec.h" + +#define KMPP_OBJ_NAME kmpp_vdec +#define KMPP_OBJ_INTF_TYPE KmppVdec +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_VDEC +#define KMPP_OBJ_FUNC_IOCTL KMPP_VDEC_IOCTL_TABLE +#include "kmpp_obj_helper.h" diff --git a/kmpp/kmpp_venc.c b/kmpp/kmpp_venc.c new file mode 100644 index 000000000..65563b833 --- /dev/null +++ b/kmpp/kmpp_venc.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_venc" + +#include "kmpp_obj.h" +#include "kmpp_venc.h" + +#define KMPP_OBJ_NAME kmpp_venc +#define KMPP_OBJ_INTF_TYPE KmppVenc +#define KMPP_OBJ_SGLN_ID MPP_SGLN_KMPP_VENC +#define KMPP_OBJ_FUNC_IOCTL KMPP_VENC_IOCTL_TABLE +#include "kmpp_obj_helper.h" diff --git a/kmpp/test/CMakeLists.txt b/kmpp/test/CMakeLists.txt new file mode 100644 index 000000000..f1144e653 --- /dev/null +++ b/kmpp/test/CMakeLists.txt @@ -0,0 +1,27 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# kmpp/base built-in unit test case +# ---------------------------------------------------------------------------- +# macro for adding osal sub-module unit test +macro(add_kmpp_test module) + set(test_name ${module}_test) + string(TOUPPER ${test_name} test_tag) + #message(STATUS "moduule : ${module}") + #message(STATUS "test_name : ${test_name}") + #message(STATUS "test_tag : ${test_tag}") + + option(${test_tag} "Build base ${module} unit test" ${BUILD_TEST}) + if(${test_tag}) + add_executable(${test_name} ${test_name}.c) + target_link_libraries(${test_name} ${MPP_SHARED}) + set_target_properties(${test_name} PROPERTIES FOLDER "kmpp/test") + add_test(NAME ${test_name} COMMAND ${test_name}) + endif() +endmacro() + +# kmpp venc unit test +add_kmpp_test(kmpp_venc) + +# kmpp vdec unit test +add_kmpp_test(kmpp_vdec) + diff --git a/kmpp/test/kmpp_vdec_test.c b/kmpp/test/kmpp_vdec_test.c new file mode 100644 index 000000000..a408d7907 --- /dev/null +++ b/kmpp/test/kmpp_vdec_test.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_vdec_test" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "kmpp_frame.h" +#include "kmpp_packet.h" +#include "kmpp_vdec.h" +#include "rk_vdec_kcfg.h" + +int main(int argc, char **argv) +{ + KmppVdec vdec = NULL; + char *path = argv[1]; + MppVdecKcfg cfg; + rk_s32 ret = rk_ok; + (void)argc; + + mpp_log(MODULE_TAG " start path %s\n", path); + + ret = kmpp_vdec_get(&vdec); + if (ret) { + mpp_err(MODULE_TAG " get vdec failed\n"); + return ret; + } + + mpp_vdec_kcfg_init(&cfg, MPP_VDEC_KCFG_TYPE_INIT); + mpp_vdec_kcfg_set_u32(cfg, "type", MPP_CTX_ENC); + mpp_vdec_kcfg_set_u32(cfg, "coding", MPP_VIDEO_CodingAVC); + + ret = kmpp_vdec_init(vdec, cfg); + if (ret) { + mpp_err(MODULE_TAG " init vdec failed\n"); + return ret; + } + mpp_vdec_kcfg_deinit(cfg); + cfg = NULL; + + ret = kmpp_vdec_start(vdec); + if (ret) { + mpp_err(MODULE_TAG " start vdec failed\n"); + return ret; + } + + if (path) { + FILE *fp = fopen(path, "rb"); + char *buf = NULL; + rk_s32 size = 0; + + if (fp) { + fseek(fp, 0L, SEEK_END); + size = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + buf = mpp_calloc(char, size); + + if (buf) { + KmppPacket packet = NULL; + KmppFrame frame = NULL; + KmppShmPtr sptr; + rk_s32 rd; + + rd = fread(buf, 1, size, fp); + if (rd != size) { + mpp_err(MODULE_TAG " read file failed: size %d, rd %d\n", size, rd); + return ret; + } + + kmpp_packet_get(&packet); + + sptr.uptr = buf; + sptr.kaddr = 0; + kmpp_packet_set_data(packet, &sptr); + kmpp_packet_set_size(packet, size); + kmpp_packet_set_pos(packet, &sptr); + kmpp_packet_set_length(packet, size); + + kmpp_vdec_put_pkt(vdec, packet); + + kmpp_vdec_get_frm(vdec, &frame); + + kmpp_packet_put(packet); + kmpp_frame_put(frame); + } + + MPP_FREE(buf); + fclose(fp); + } + } + + ret = kmpp_vdec_stop(vdec); + if (ret) { + mpp_err(MODULE_TAG " stop vdec failed\n"); + return ret; + } + + ret = kmpp_vdec_deinit(vdec); + if (ret) { + mpp_err(MODULE_TAG " deinit vdec failed\n"); + return ret; + } + + ret = kmpp_vdec_put(vdec); + + mpp_log(MODULE_TAG " %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/kmpp/test/kmpp_venc_test.c b/kmpp/test/kmpp_venc_test.c new file mode 100644 index 000000000..1b6a98ee6 --- /dev/null +++ b/kmpp/test/kmpp_venc_test.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "kmpp_venc_test" + +#include "mpp_debug.h" +#include "kmpp_frame.h" +#include "kmpp_packet.h" +#include "kmpp_venc.h" +#include "rk_venc_kcfg.h" + +int main() +{ + KmppVenc venc = NULL; + MppVencKcfg cfg = NULL; + KmppFrame frm = NULL; + KmppPacket pkt = NULL; + rk_s32 ret = rk_ok; + + mpp_log(MODULE_TAG " start\n"); + + ret = kmpp_venc_get(&venc); + if (ret) { + mpp_err(MODULE_TAG " get venc failed\n"); + return ret; + } + + mpp_venc_kcfg_init(&cfg, MPP_VENC_KCFG_TYPE_INIT); + mpp_venc_kcfg_set_u32(cfg, "type", MPP_CTX_ENC); + mpp_venc_kcfg_set_u32(cfg, "coding", MPP_VIDEO_CodingAVC); + mpp_venc_kcfg_set_s32(cfg, "chan_id", 0); + mpp_venc_kcfg_set_u32(cfg, "buf_size", 4096); + mpp_venc_kcfg_set_u32(cfg, "max_width", 1920); + mpp_venc_kcfg_set_u32(cfg, "max_height", 1080); + mpp_venc_kcfg_set_u32(cfg, "max_lt_cnt", 0); + mpp_venc_kcfg_set_s32(cfg, "input_timeout", -1); + + ret = kmpp_venc_init(venc, cfg); + if (ret) { + mpp_err(MODULE_TAG " init venc failed\n"); + return ret; + } + + mpp_venc_kcfg_deinit(cfg); + cfg = NULL; + + mpp_venc_kcfg_init(&cfg, MPP_VENC_KCFG_TYPE_ST_CFG); + + ret = kmpp_venc_get_cfg(venc, cfg); + if (ret) { + mpp_err(MODULE_TAG " get venc cfg failed\n"); + return ret; + } + + ret = kmpp_venc_set_cfg(venc, cfg); + if (ret) { + mpp_err(MODULE_TAG " set venc cfg failed\n"); + return ret; + } + + mpp_venc_kcfg_deinit(cfg); + cfg = NULL; + + ret = kmpp_venc_start(venc); + if (ret) { + mpp_err(MODULE_TAG " start venc failed\n"); + return ret; + } + + kmpp_frame_get(&frm); + + ret = kmpp_venc_put_frm(venc, frm); + if (ret) { + mpp_err(MODULE_TAG " put frm failed\n"); + return ret; + } + + kmpp_frame_put(frm); + frm = NULL; + + ret = kmpp_venc_get_pkt(venc, &pkt); + if (ret) { + mpp_err(MODULE_TAG " get pkt failed\n"); + return ret; + } + + if (pkt) { + ret = kmpp_venc_put_pkt(venc, pkt); + if (ret) { + mpp_err(MODULE_TAG " put pkt failed\n"); + return ret; + } + } + + ret = kmpp_venc_stop(venc); + if (ret) { + mpp_err(MODULE_TAG " stop venc failed\n"); + return ret; + } + + ret = kmpp_venc_deinit(venc); + if (ret) { + mpp_err(MODULE_TAG " deinit venc failed\n"); + return ret; + } + + ret = kmpp_venc_put(venc); + + mpp_log(MODULE_TAG " %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/merge_static_lib.bat b/merge_static_lib.bat new file mode 100644 index 000000000..acd855ddb --- /dev/null +++ b/merge_static_lib.bat @@ -0,0 +1,99 @@ +@echo off +REM Windows version of merge_static_lib.sh +REM Merges multiple static library files into one +REM Usage: merge_static_lib.bat + +setlocal enabledelayedexpansion + +set BUILD_DIR=%~1 +set LIB_NAME=%~2 + +echo merge_static_lib.bat: BUILD_DIR=%BUILD_DIR% LIB_NAME=%LIB_NAME% + +cd /d "%BUILD_DIR%" +if errorlevel 1 exit /b 1 + +REM Remove old merged library +if exist "mpp\lib%LIB_NAME%.a" ( + echo Removing old library: mpp\lib%LIB_NAME%.a + del /F /Q "mpp\lib%LIB_NAME%.a" +) + +REM Find ar.exe in Android NDK +set AR_CMD= + +REM Check environment variable first +if defined ANDROID_NDK ( + set "TEST_PATH=%ANDROID_NDK%\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-ar.exe" + if exist "!TEST_PATH!" ( + set "AR_CMD=!TEST_PATH!" + echo Found ar via ANDROID_NDK + ) +) + +REM If not found, try common paths +if "%AR_CMD%"=="" ( + echo Searching for ar.exe in D:\android-sdk-windows\ndk\... + for /d %%d in (D:\android-sdk-windows\ndk\*) do ( + set "TEST_PATH=%%d\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-ar.exe" + if exist "!TEST_PATH!" ( + set "AR_CMD=!TEST_PATH!" + echo Found ar: !AR_CMD! + ) + ) +) + +REM Fallback to ar in PATH +if "%AR_CMD%"=="" ( + set AR_CMD=ar + echo Using ar from PATH +) + +echo Using ar: %AR_CMD% + +REM Create MRI script for ar command +set MRI_SCRIPT=%TEMP%\merge_lib_%RANDOM%.mri + +echo CREATE mpp\lib%LIB_NAME%.a > "%MRI_SCRIPT%" + +REM Find all .a files and add them to the script +REM Skip files in mpp subdirectory +for /r %%f in (*.a) do ( + set "filepath=%%f" + set "skip=0" + + REM Check if file is in mpp directory + echo !filepath! | findstr /C:"\mpp\\" >nul + if not errorlevel 1 ( + set "skip=1" + ) + + if "!skip!"=="0" ( + echo ADDLIB %%f >> "%MRI_SCRIPT%" + ) +) + +echo SAVE >> "%MRI_SCRIPT%" +echo END >> "%MRI_SCRIPT%" + +REM Display script for debugging +echo MRI Script contents: +type "%MRI_SCRIPT%" +echo. + +REM Execute ar with the MRI script +type "%MRI_SCRIPT%" | "%AR_CMD%" -M + +if errorlevel 1 ( + echo [ERROR] ar command failed! + del /F /Q "%MRI_SCRIPT%" 2>nul + exit /b 1 +) + +REM Clean up +del /F /Q "%MRI_SCRIPT%" 2>nul + +echo Successfully merged libraries into mpp\lib%LIB_NAME%.a + +endlocal +exit /b 0 diff --git a/merge_static_lib.sh b/merge_static_lib.sh new file mode 100755 index 000000000..d3658c292 --- /dev/null +++ b/merge_static_lib.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +cd $1 +rm -rf mpp/lib'$2$'.a + +SCRIPT=$'CREATE mpp/lib'$2$'.a\n' +SCRIPT=$SCRIPT$(find . -name '*.a' -exec echo 'ADDLIB {}' \;) +SCRIPT=$SCRIPT$'\nSAVE\nEND\n' + +ar -M <<< $SCRIPT diff --git a/mpp/CMakeLists.txt b/mpp/CMakeLists.txt index ee3a583a7..b29dd43a9 100644 --- a/mpp/CMakeLists.txt +++ b/mpp/CMakeLists.txt @@ -1,40 +1,115 @@ # vim: syntax=cmake -include_directories(.) +# ---------------------------------------------------------------------------- +# setup mpp codec config first +# ---------------------------------------------------------------------------- +include(soc.cmake) +include(codecs.cmake) +include(vproc.cmake) + +# ---------------------------------------------------------------------------- +# add include directory +# ---------------------------------------------------------------------------- +include_directories(inc) include_directories(common) +include_directories(base/inc) include_directories(codec/inc) include_directories(hal/inc) +include_directories(hal/common) +include_directories(vproc/inc) + +# ---------------------------------------------------------------------------- +# Set script suffix based on host OS +# ---------------------------------------------------------------------------- +if(CMAKE_HOST_WIN32) + set(SCRIPT_SUFFIX ".bat") + set(CLEAN_OBJ_FILES cmd /c "if exist *.o del /F /Q *.o") + set(PRINT_CURRENT_DIR cmd /c cd) +else() + set(SCRIPT_SUFFIX ".sh") + set(CLEAN_OBJ_FILES rm *.o || true) + set(PRINT_CURRENT_DIR pwd) +endif() + +# ---------------------------------------------------------------------------- +# add mpp base component +# ---------------------------------------------------------------------------- +add_subdirectory(base) # ---------------------------------------------------------------------------- # add codec parsers # ---------------------------------------------------------------------------- add_subdirectory(codec) +# ---------------------------------------------------------------------------- +# add video processor +# ---------------------------------------------------------------------------- +add_subdirectory(vproc) # ---------------------------------------------------------------------------- # add register generation hal # ---------------------------------------------------------------------------- add_subdirectory(hal) - # ---------------------------------------------------------------------------- # add mpp implement # ---------------------------------------------------------------------------- -add_library(mpp STATIC - mpp_info.cpp - mpp_buffer_impl.cpp - mpp_buffer.cpp - mpp_packet.cpp - mpp_frame.cpp - mpp.cpp - mpi_impl.cpp - mpi.cpp +set (MPP_SRC + mpp_info.c + mpp_sys.c + mpp.c + mpp_impl.c + mpi.c ) -set_target_properties(mpp PROPERTIES FOLDER "mpp") +set(MPP_VERSION "0") +set(MPP_ABI_VERSION "1") -add_subdirectory(legacy) +add_library(${MPP_SHARED} SHARED ${MPP_SRC}) +target_link_libraries(${MPP_SHARED} ${ASAN_LIB}) +set_target_properties(${MPP_SHARED} PROPERTIES C_VISIBILITY_PRESET default) +set_target_properties(${MPP_SHARED} PROPERTIES CXX_VISIBILITY_PRESET default) + +# NOTE: due to legacy libray naming issue we can not support version on Android +if (NOT ANDROID) +set_target_properties(${MPP_SHARED} PROPERTIES VERSION ${MPP_VERSION}) +set_target_properties(${MPP_SHARED} PROPERTIES SOVERSION ${MPP_ABI_VERSION}) +endif() -target_link_libraries(mpp mpp_codec mpp_hal mpp_legacy osal) +set_target_properties(${MPP_SHARED} PROPERTIES FOLDER "mpp") +set_target_properties(${MPP_SHARED} PROPERTIES CLEAN_DIRECT_OUTPUT 1) +target_link_libraries(${MPP_SHARED} PRIVATE kmpp + ${BEGIN_WHOLE_ARCHIVE} mpp_vproc mpp_codec mpp_hal mpp_base kmpp_base osal ${END_WHOLE_ARCHIVE}) +target_link_libraries(${MPP_SHARED} PUBLIC ${LIBM} ${CMAKE_THREAD_LIBS_INIT}) -add_subdirectory(test) +# those special platform here +if(ANDROID) + add_definitions(-static) + # in Android pthread is in libc, also need liblog + # Android 14 requires libc++ not libstdc++ + if("${ANDROID_STL}" STREQUAL "c++_static") + target_link_libraries(${MPP_SHARED} PUBLIC log) + else() + target_link_libraries(${MPP_SHARED} PUBLIC log stdc++) + endif() +endif(ANDROID) + +# build static library +add_library(${MPP_STATIC} STATIC ${MPP_SRC}) +set_target_properties(${MPP_STATIC} PROPERTIES FOLDER "mpp" OUTPUT_NAME "${MPP_SHARED}") +set_target_properties(${MPP_STATIC} PROPERTIES CLEAN_DIRECT_OUTPUT 1) +target_link_libraries(${MPP_STATIC} PRIVATE kmpp + ${BEGIN_WHOLE_ARCHIVE} mpp_vproc mpp_codec mpp_hal mpp_base kmpp_base osal ${END_WHOLE_ARCHIVE}) + +add_custom_command(TARGET ${MPP_STATIC} POST_BUILD + COMMAND ${CMAKE_AR} x $ + COMMAND ${CMAKE_AR} rcs lib${MPP_SHARED}.a *.o + COMMAND ${CMAKE_COMMAND} -E env ANDROID_NDK=${ANDROID_NDK} ${CMAKE_SOURCE_DIR}/merge_static_lib${SCRIPT_SUFFIX} ${CMAKE_BINARY_DIR} ${MPP_SHARED} + COMMAND ${CMAKE_STRIP} --strip-debug lib${MPP_SHARED}.a + COMMAND ${PRINT_CURRENT_DIR} + COMMAND ${CLEAN_OBJ_FILES} + ) + +add_subdirectory(legacy) +install(TARGETS ${MPP_SHARED} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") +install(TARGETS ${MPP_STATIC} ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/mpp/base/CMakeLists.txt b/mpp/base/CMakeLists.txt new file mode 100644 index 000000000..20b66755e --- /dev/null +++ b/mpp/base/CMakeLists.txt @@ -0,0 +1,38 @@ +# vim: syntax=cmake + +# ---------------------------------------------------------------------------- +# add mpp basic components +# ---------------------------------------------------------------------------- +add_library(mpp_base OBJECT + mpp_enc_refs.c + mpp_enc_ref.c + mpp_enc_cfg.c + mpp_dec_cfg.c + mpp_sys_cfg.c + mpp_sys_cfg_st.c + mpp_cluster.c + mpp_buf_slot.c + mpp_buffer_impl.c + mpp_buffer.c + mpp_packet.c + mpp_frame.c + mpp_task_impl.c + mpp_task.c + mpp_meta.c + mpp_trie.c + mpp_bitwrite.c + mpp_bitread.c + mpp_bitput.c + mpp_cfg_io.c + mpp_cfg.c + mpp_2str.c + mpp_dec_hdr_meta.c + mpp_ref_pool.c + ) + +set_target_properties(mpp_base PROPERTIES FOLDER "mpp/base") + +#target_link_libraries(mpp_base osal) + +# unit test +add_subdirectory(test) diff --git a/osal/mpp_time.cpp b/mpp/base/inc/mpp_2str.h similarity index 54% rename from osal/mpp_time.cpp rename to mpp/base/inc/mpp_2str.h index 422d9d5c9..830dd4859 100644 --- a/osal/mpp_time.cpp +++ b/mpp/base/inc/mpp_2str.h @@ -1,40 +1,38 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mpp_time.h" - -#if _WIN32 -#include -#include - -RK_S64 mpp_time() -{ - struct timeb tb; - ftime(&tb); - return ((RK_S64)tb.time * 1000 + (RK_S64)tb.millitm) * 1000; -} - -#else -#include - -RK_S64 mpp_time() -{ - struct timeval tv_date; - gettimeofday(&tv_date, NULL); - return (RK_S64)tv_date.tv_sec * 1000000 + (RK_S64)tv_date.tv_usec; -} - -#endif +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_2STR_H +#define MPP_2STR_H + +#include "rk_type.h" +#include "rk_venc_rc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +const char *strof_ctx_type(MppCtxType type); +const char *strof_coding_type(MppCodingType coding); +const char *strof_rc_mode(MppEncRcMode rc_mode); +const char *strof_profle(MppCodingType coding, RK_U32 profile); +const char *strof_gop_mode(MppEncRcGopMode gop_mode); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/base/inc/mpp_bitput.h b/mpp/base/inc/mpp_bitput.h new file mode 100644 index 000000000..45e34c17c --- /dev/null +++ b/mpp/base/inc/mpp_bitput.h @@ -0,0 +1,46 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_BITPUT_H +#define MPP_BITPUT_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_common.h" + +typedef struct bitput_ctx_t { + RK_U32 buflen; //!< max buf length, 64bit uint + RK_U32 index; //!< current uint position + RK_U64 *pbuf; //!< outpacket data + RK_U64 bvalue; //!< buffer value, 64 bit + RK_U8 bitpos; //!< bit pos in 64bit + RK_U32 size; //!< data size,except header +} BitputCtx_t; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_set_bitput_ctx(BitputCtx_t *bp, RK_U64 *data, RK_U32 len); +void mpp_put_bits(BitputCtx_t *bp, RK_U64 invalue, RK_S32 lbits); +void mpp_put_align(BitputCtx_t *bp, RK_S32 align_bits, int flag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/base/inc/mpp_bitread.h b/mpp/base/inc/mpp_bitread.h new file mode 100644 index 000000000..e285a134b --- /dev/null +++ b/mpp/base/inc/mpp_bitread.h @@ -0,0 +1,189 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef MPP_BITREAD_H +#define MPP_BITREAD_H + +#include +#include + +#include "mpp_err.h" +#include "mpp_common.h" + +#define __BITREAD_ERR __bitread_error + +#define READ_ONEBIT(bitctx, out)\ + do {\ + RK_S32 _out; \ + bitctx->ret = mpp_read_bits(bitctx, 1, &_out); \ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +#define READ_BITS(bitctx, num_bits, out)\ + do {\ + RK_S32 _out; \ + bitctx->ret = mpp_read_bits(bitctx, num_bits, &_out); \ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +#define READ_BITS_LONG(bitctx, num_bits, out)\ + do {\ + RK_U32 _out; \ + bitctx->ret = mpp_read_longbits(bitctx, num_bits, &_out); \ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +#define SHOW_BITS(bitctx, num_bits, out)\ + do {\ + RK_S32 _out; \ + bitctx->ret = mpp_show_bits(bitctx, num_bits, &_out); \ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +#define SHOW_BITS_LONG(bitctx, num_bits, out)\ + do {\ + RK_U32 _out; \ + bitctx->ret = mpp_show_longbits(bitctx, num_bits, &_out); \ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +#define SKIP_BITS(bitctx, num_bits)\ + do {\ + bitctx->ret = mpp_skip_longbits(bitctx, num_bits); \ + if (bitctx->ret) { goto __BITREAD_ERR; }\ + } while (0) + +#define SKIP_BITS_LONG(bitctx, num_bits)\ + do {\ + bitctx->ret = mpp_skip_longbits(bitctx, num_bits); \ + if (bitctx->ret) { goto __BITREAD_ERR; }\ + } while (0) + +#define READ_UE(bitctx, out)\ + do {\ + RK_U32 _out; \ + bitctx->ret = mpp_read_ue(bitctx, &_out); \ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +#define READ_SE(bitctx, out)\ + do {\ + RK_S32 _out; \ + bitctx->ret = mpp_read_se(bitctx, &_out); \ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +#define READ_SIGNBITS(bitctx, num_bits, out)\ + do {\ + RK_S32 _out;\ + bitctx->ret = mpp_read_signbits(bitctx, num_bits, &_out);\ + if (!bitctx->ret) { *out = _out; }\ + else { goto __BITREAD_ERR; }\ + } while (0) + +typedef enum PseudoCodeType_e { + PSEUDO_CODE_NONE = 0, + PSEUDO_CODE_H264_H265, + PSEUDO_CODE_H264_H265_SEI, + PSEUDO_CODE_AVS2, + PSEUDO_CODE_BUT +} PseudoCodeType; + +typedef struct bitread_ctx_t { + // Pointer to the next unread (not in curr_byte_) byte in the stream. + RK_U8 *data_; + // Bytes left in the stream (without the curr_byte_). + RK_U32 bytes_left_; + // Contents of the current byte; first unread bit starting at position + // 8 - num_remaining_bits_in_curr_byte_ from MSB. + RK_S64 curr_byte_; + // Number of bits remaining in curr_byte_ + RK_S32 num_remaining_bits_in_curr_byte_; + // Used in emulation prevention three byte detection (see spec). + // Initially set to 0xffff to accept all initial two-byte sequences. + RK_S64 prev_two_bytes_; + // Number of emulation presentation bytes (0x000003) we met. + RK_S64 emulation_prevention_bytes_; + // count PPS SPS SEI read bits + RK_S32 used_bits; + RK_U8 *buf; + RK_S32 buf_len; + // ctx + MPP_RET ret; + PseudoCodeType prevention_type; + MPP_RET (*update_curbyte)(struct bitread_ctx_t *bitctx); +} BitReadCtx_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +//!< set bit read context +void mpp_set_bitread_ctx(BitReadCtx_t *bitctx, RK_U8 *data, RK_S32 size); + +//!< Read bits (1-31) +MPP_RET mpp_read_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out); + +//!< Read bits (1-32) +MPP_RET mpp_read_longbits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_U32 *out); + +//!< Show bits (1-31) +MPP_RET mpp_show_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out); + +//!< Show bits (1-32) +MPP_RET mpp_show_longbits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_U32 *out); + +//!< skip bits(1-31) +MPP_RET mpp_skip_bits(BitReadCtx_t *bitctx, RK_S32 num_bits); + +//!< skip bits(1-32) +MPP_RET mpp_skip_longbits(BitReadCtx_t *bitctx, RK_S32 num_bits); + +//!< read ue(1-32) +MPP_RET mpp_read_ue(BitReadCtx_t *bitctx, RK_U32* val); + +//!< read se(1-31) +MPP_RET mpp_read_se(BitReadCtx_t *bitctx, RK_S32* val); + +void mpp_set_bitread_pseudo_code_type(BitReadCtx_t *bitctx, PseudoCodeType type); + +//!< check whether has more rbsp data(used in h264) +RK_U32 mpp_has_more_rbsp_data(BitReadCtx_t * bitctx); + +//!< align bits and get current pointer +RK_U8 *mpp_align_get_bits(BitReadCtx_t *bitctx); + +RK_S32 mpp_get_bits_left(BitReadCtx_t *bitctx); + +RK_S32 mpp_get_bits_count(BitReadCtx_t *bitctx); + +//!< Read sign bits (1-31) +MPP_RET mpp_read_signbits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out); + +#ifdef __cplusplus +} +#endif + + +#endif /* MPP_BITREAD_H */ diff --git a/mpp/base/inc/mpp_bitwrite.h b/mpp/base/inc/mpp_bitwrite.h new file mode 100644 index 000000000..3a188650d --- /dev/null +++ b/mpp/base/inc/mpp_bitwrite.h @@ -0,0 +1,69 @@ +/* + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_BITWRITER_H +#define MPP_BITWRITER_H + +#include "rk_type.h" +#include "mpp_err.h" + +/* + * Mpp bitstream writer for H.264/H.265 + */ +typedef struct MppWriteCtx_t { + RK_U8 *buffer; /* point to first byte of stream */ + RK_U8 *stream; /* Pointer to next byte of stream */ + RK_U32 size; /* Byte size of stream buffer */ + RK_U32 byte_cnt; /* Byte counter */ + RK_U32 byte_buffer; /* Byte buffer */ + RK_U32 buffered_bits; /* Amount of bits in byte buffer, [0-7] */ + RK_U32 zero_bytes; /* Amount of consecutive zero bytes */ + RK_S32 overflow; /* This will signal a buffer overflow */ + RK_U32 emul_cnt; /* Counter for emulation_3_byte, needed in SEI */ +} MppWriteCtx; + +MPP_RET mpp_writer_init(MppWriteCtx *ctx, void *p, RK_S32 size); +MPP_RET mpp_writer_reset(MppWriteCtx *ctx); + +/* check overflow status */ +MPP_RET mpp_writer_status(MppWriteCtx *ctx); +/* write bit in last byte to memory */ +void mpp_writer_flush(MppWriteCtx *ctx); + +/* write raw bit without emulation prevention 0x03 byte */ +void mpp_writer_put_raw_bits(MppWriteCtx *ctx, RK_S32 val, RK_S32 len); + +/* write bit with emulation prevention 0x03 byte */ +void mpp_writer_put_bits(MppWriteCtx *ctx, RK_S32 val, RK_S32 len); + +/* insert zero bits until byte-aligned */ +void mpp_writer_align_zero(MppWriteCtx *ctx); + +/* insert one bits until byte-aligned */ +void mpp_writer_align_one(MppWriteCtx *ctx); + +/* insert one bit then pad to byte-align with zero */ +void mpp_writer_trailing(MppWriteCtx * ctx); + +void mpp_writer_put_ue(MppWriteCtx *ctx, RK_U32 val); +void mpp_writer_put_se(MppWriteCtx *ctx, RK_S32 val); + +RK_S32 mpp_writer_bytes(MppWriteCtx *ctx); +RK_S32 mpp_writer_bits(MppWriteCtx *ctx); + +RK_S32 mpp_exp_golomb_signed(RK_S32 val); + +#endif /* MPP_BITWRITER_H */ diff --git a/mpp/codec/inc/mpp_buf_slot.h b/mpp/base/inc/mpp_buf_slot.h similarity index 65% rename from mpp/codec/inc/mpp_buf_slot.h rename to mpp/base/inc/mpp_buf_slot.h index 3328b11a9..d5847cabb 100644 --- a/mpp/codec/inc/mpp_buf_slot.h +++ b/mpp/base/inc/mpp_buf_slot.h @@ -1,203 +1,275 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_BUF_SLOT_H__ -#define __MPP_BUF_SLOT_H__ - -#include "rk_type.h" -#include "mpp_frame.h" - -/* - * mpp_dec will alloc 18 decoded picture buffer slot - * buffer slot is for transferring information between parser / mpp/ hal - * it represent the dpb routine in logical - * - * basic working flow: - * - * buf_slot parser hal - * - * + + + - * | | | - * | +--------+--------+ | - * | | | | - * | | do parsing here | | - * | | | | - * | +--------+--------+ | - * | | | - * | get_slot | | - * | <--------------------------+ | - * | get unused dpb slot for | | - * | current decoder output | | - * | | | - * | update dpb refer status | | - * | <--------------------------+ | - * | parser will send marking | | - * | operation to dpb slot | | - * | including: | | - * | ref/unref/output/display | | - * | | | - * | | | - * | | set buffer status to hal | - * +-------------------------------------------------------> | - * | | | - * | | +--------+--------+ - * | | | | - * | | | reg generation | - * | | | | - * | | +--------+--------+ - * | | | - * | | get buffer address info | - * | <-------------------------------------------------------+ - * | | used buffer index to get | - * | | physical address or iommu | - * | | address for hardware | - * | | | - * | | +--------+--------+ - * | | | | - * | | | set/wait hw | - * | | | | - * | | +--------+--------+ - * | | | - * | | update the output status | - * | <-------------------------------------------------------+ - * | | mark picture is available | - * | | for output and generate | - * | | output frame information | - * + + + - * - * typical buffer status transfer - * - * -> unused initial - * -> set_hw_dst by parser - * -> set_buffer by mpp - do alloc buffer here / info change here - * -> clr_hw_dst by hal() - * - * next four step can be different order - * -> set_dpb_ref by parser - * -> set_display by parser - slot ready to display, can be output - * -> clr_display by mpp - output buffer struct - * -> clr_dpb_ref by parser - * - * -> set_unused automatic clear and dec buffer ref - * - */ - -typedef void* MppBufSlots; - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * called by mpp context - * - * init / deinit - normal initialize and de-initialize function - * setup - called by parser when slot information changed - * is_changed - called by mpp to detect whether info change flow is needed - * ready - called by mpp when info changed is done - * - * typical info change flow: - * - * mpp_buf_slot_setup called in parser with changed equal to 1 - * mpp_buf_slot_is_changed called in mpp and found info change - * - * do info change outside - * - * mpp_buf_slot_ready called in mpp when info change is done - * - */ -MPP_RET mpp_buf_slot_init(MppBufSlots *slots); -MPP_RET mpp_buf_slot_deinit(MppBufSlots slots); -MPP_RET mpp_buf_slot_setup(MppBufSlots slots, RK_U32 count, RK_U32 size, RK_U32 changed); -RK_U32 mpp_buf_slot_is_changed(MppBufSlots slots); -MPP_RET mpp_buf_slot_ready(MppBufSlots slots); -RK_U32 mpp_buf_slot_get_size(MppBufSlots slots); - -/* - * called by parser - * - * mpp_buf_slot_get_unused - * - parser need a new slot ffor output, on field mode alloc one buffer for two field - * - * mpp_buf_slot_set_dpb_ref - * - mark a slot to be used as reference frame in dpb - * - * mpp_buf_slot_clr_dpb_ref - * - mark a slot to be unused as reference frame and remove from dpb - * - * mpp_buf_slot_set_hw_dst - * - mark a slot to be output destination buffer - * - NOTE: the frame information MUST be set here - * - * mpp_buf_slot_set_display - * - mark a slot to be can be display - * - NOTE: set display will generate a MppFrame for buffer slot internal usage - * for example store pts / buffer address, etc. - * - * mpp_buf_slot_inc_hw_ref - * - MUST be called once when one slot is used in hardware decoding as reference frame - * - * called by mpp - * - * mpp_buf_slot_get_hw_dst - * - mpp_dec need to get the output slot index to check buffer status - * - * mpp_buf_slot_clr_display - * - mark a slot has been send out to display - * - NOTE: will be called inside mpp_buf_slot_get_display - * - * called by hal - * - * mpp_buf_slot_clr_hw_dst - * - mark a slot's buffer is already decoded by hardware - * - NOTE: this call will clear used as output flag - * - * mpp_buf_slot_dec_hw_ref - * - when hal finished on hardware decoding it MUST be called once for each used slot - */ -MPP_RET mpp_buf_slot_get_unused(MppBufSlots slots, RK_U32 *index); -MPP_RET mpp_buf_slot_set_dpb_ref(MppBufSlots slots, RK_U32 index); -MPP_RET mpp_buf_slot_clr_dpb_ref(MppBufSlots slots, RK_U32 index); -MPP_RET mpp_buf_slot_set_display(MppBufSlots slots, RK_U32 index); - -MPP_RET mpp_buf_slot_set_hw_dst(MppBufSlots slots, RK_U32 index, MppFrame frame); -MPP_RET mpp_buf_slot_clr_hw_dst(MppBufSlots slots, RK_U32 index); -MPP_RET mpp_buf_slot_get_hw_dst(MppBufSlots slots, RK_U32 *index); - -MPP_RET mpp_buf_slot_inc_hw_ref(MppBufSlots slots, RK_U32 index); -MPP_RET mpp_buf_slot_dec_hw_ref(MppBufSlots slots, RK_U32 index); - -/* - * mpp_buf_slot_set_buffer - * - called by dec thread when find a output index has not buffer - * - * mpp_buf_slot_get_buffer - * - called by hal module on register generation - * - * mpp_buf_slot_get_display - * - called by hal thread to output a display slot's frame info - * NOTE: get display will generate a new MppFrame for external mpp_frame_deinit call - * So that external mpp_frame_deinit will not release the MppFrame used in buf_slot - */ -MPP_RET mpp_buf_slot_set_buffer(MppBufSlots slots, RK_U32 index, MppBuffer buffer); -MppBuffer mpp_buf_slot_get_buffer(MppBufSlots slots, RK_U32 index); -MPP_RET mpp_buf_slot_get_display(MppBufSlots slots, MppFrame *frame); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_BUF_SLOT_H__*/ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_BUF_SLOT_H +#define MPP_BUF_SLOT_H + +#include "rk_vdec_cfg.h" + +#include "mpp_frame.h" +#include "mpp_callback.h" + +/* + * mpp_dec will alloc 18 decoded picture buffer slot + * buffer slot is for transferring information between parser / mpp/ hal + * it represent the dpb routine in logical + * + * basic working flow: + * + * buf_slot parser hal + * + * + + + + * | | | + * | +--------+--------+ | + * | | | | + * | | do parsing here | | + * | | | | + * | +--------+--------+ | + * | | | + * | get_slot | | + * | <--------------------------+ | + * | get unused dpb slot for | | + * | current decoder output | | + * | | | + * | update dpb refer status | | + * | <--------------------------+ | + * | parser will send marking | | + * | operation to dpb slot | | + * | including: | | + * | ref/unref/output/display | | + * | | | + * | | | + * | | set buffer status to hal | + * +-------------------------------------------------------> | + * | | | + * | | +--------+--------+ + * | | | | + * | | | reg generation | + * | | | | + * | | +--------+--------+ + * | | | + * | | get buffer address info | + * | <-------------------------------------------------------+ + * | | used buffer index to get | + * | | physical address or iommu | + * | | address for hardware | + * | | | + * | | +--------+--------+ + * | | | | + * | | | set/wait hw | + * | | | | + * | | +--------+--------+ + * | | | + * | | update the output status | + * | <-------------------------------------------------------+ + * | | mark picture is available | + * | | for output and generate | + * | | output frame information | + * + + + + * + * typical buffer status transfer + * + * -> unused initial + * -> set_hw_dst by parser + * -> set_buffer by mpp - do alloc buffer here / info change here + * -> clr_hw_dst by hal() + * + * next four step can be different order + * -> set_dpb_ref by parser + * -> set_display by parser - slot ready to display, can be output + * -> clr_display by mpp - output buffer struct + * -> clr_dpb_ref by parser + * + * -> set_unused automatic clear and dec buffer ref + * + */ + +typedef void* MppBufSlots; + +/* + * buffer slot index range is 0~254, 0xff (255) will indicated the invalid index + */ +#define SLOT_IDX_BUTT (0xff) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * called by mpp context + * + * init / deinit - normal initialize and de-initialize function + * setup - called by parser when slot information changed + * is_changed - called by mpp to detect whether info change flow is needed + * ready - called by mpp when info changed is done + * + * typical info change flow: + * + * mpp_buf_slot_setup called in parser with changed equal to 1 + * mpp_buf_slot_is_changed called in mpp and found info change + * + * do info change outside + * + * mpp_buf_slot_ready called in mpp when info change is done + * + */ +MPP_RET mpp_buf_slot_init(MppBufSlots *slots); +MPP_RET mpp_buf_slot_deinit(MppBufSlots slots); +MPP_RET mpp_buf_slot_setup(MppBufSlots slots, RK_S32 count); +RK_U32 mpp_buf_slot_is_changed(MppBufSlots slots); +MPP_RET mpp_buf_slot_ready(MppBufSlots slots); +size_t mpp_buf_slot_get_size(MppBufSlots slots); +RK_S32 mpp_buf_slot_get_count(MppBufSlots slots); +MPP_RET mpp_buf_slot_set_callback(MppBufSlots slots, MppCbCtx *cb_ctx); +MPP_RET mpp_buf_slot_set_dec_cfg(MppBufSlots slots, MppDecCfg cfg); + +/* + * called by parser + * + * mpp_buf_slot_get_unused + * - parser need a new slot for output, on field mode alloc one buffer for two field + * + * mpp_buf_slot_set_dpb_ref + * - mark a slot to be used as reference frame in dpb + * + * mpp_buf_slot_clr_dpb_ref + * - mark a slot to be unused as reference frame and remove from dpb + * + * mpp_buf_slot_set_hw_dst + * - mark a slot to be output destination buffer + * - NOTE: the frame information MUST be set here + * + * mpp_buf_slot_set_display + * - mark a slot to be can be display + * - NOTE: set display will generate a MppFrame for buffer slot internal usage + * for example store pts / buffer address, etc. + * + * mpp_buf_slot_inc_hw_ref + * - MUST be called once when one slot is used in hardware decoding as reference frame + * + * called by mpp + * + * mpp_buf_slot_get_hw_dst + * - mpp_dec need to get the output slot index to check buffer status + * + * mpp_buf_slot_clr_display + * - mark a slot has been send out to display + * - NOTE: will be called inside mpp_buf_slot_get_display + * + * called by hal + * + * mpp_buf_slot_clr_hw_dst + * - mark a slot's buffer is already decoded by hardware + * - NOTE: this call will clear used as output flag + * + * mpp_buf_slot_dec_hw_ref + * - when hal finished on hardware decoding it MUST be called once for each used slot + */ +MPP_RET mpp_buf_slot_get_unused(MppBufSlots slots, RK_S32 *index); + +/* + * mpp_buf_slot_set_buffer + * - called by dec thread when find a output index has not buffer + * + * mpp_buf_slot_get_buffer + * - called by hal module on register generation + * + * mpp_buf_slot_get_display + * - called by hal thread to output a display slot's frame info + * NOTE: get display will generate a new MppFrame for external mpp_frame_deinit call + * So that external mpp_frame_deinit will not release the MppFrame used in buf_slot + */ + +/* + * NOTE: + * buffer slot will be used both for frame and packet + * when buffer slot is used for packet management only inc_hw_ref and dec_hw_ref is used + */ + +typedef enum SlotUsageType_e { + SLOT_CODEC_READY, // bit flag for buffer is prepared by codec + SLOT_CODEC_USE, // bit flag for buffer is used as reference by codec + SLOT_HAL_INPUT, // counter for buffer is used as hardware input + SLOT_HAL_OUTPUT, // counter + bit flag for buffer is used as hardware output + SLOT_QUEUE_USE, // bit flag for buffer is hold in different queues + SLOT_USAGE_BUTT, +} SlotUsageType; + +MPP_RET mpp_buf_slot_set_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type); +MPP_RET mpp_buf_slot_clr_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type); + +// TODO: can be extended here +typedef enum SlotQueueType_e { + QUEUE_OUTPUT, // queue for mpp output to user + QUEUE_DISPLAY, // queue for decoder output display + QUEUE_DEINTERLACE, // queue for deinterlace process + QUEUE_COLOR_CONVERT, // queue for color convertion process + QUEUE_BUTT, +} SlotQueueType; + +MPP_RET mpp_buf_slot_enqueue(MppBufSlots slots, RK_S32 index, SlotQueueType type); +MPP_RET mpp_buf_slot_dequeue(MppBufSlots slots, RK_S32 *index, SlotQueueType type); + +typedef enum SlotPropType_e { + SLOT_EOS, + SLOT_FRAME, + SLOT_BUFFER, + SLOT_FRAME_PTR, + SLOT_PROP_BUTT, +} SlotPropType; + +MPP_RET mpp_buf_slot_set_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val); +MPP_RET mpp_buf_slot_get_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val); + +typedef enum SlotsPropType_e { + SLOTS_EOS, + SLOTS_NUMERATOR, // numerator of buffer size scale ratio + SLOTS_DENOMINATOR, // denominator of buffer size scale ratio + SLOTS_HOR_ALIGN, // input must be buf_align function pointer + SLOTS_VER_ALIGN, // input must be buf_align function pointer + SLOTS_LEN_ALIGN, + SLOTS_COUNT, + SLOTS_SIZE, + SLOTS_FRAME_INFO, + SLOTS_HAL_FBC_ADJ, + SLOTS_CODING_TYPE, + SLOTS_WIDTH_ALIGN, + SLOTS_PROP_BUTT, +} SlotsPropType; + +typedef RK_U32 (*AlignFunc)(RK_U32 val); +/* for fbc mode change on info change and external user set frame info */ +typedef void (*HalFbcAdjFunc)(MppBufSlots slots, MppFrame frame, RK_U32 expand); +typedef struct SlotHalFbcAdjCfg_t { + HalFbcAdjFunc func; + RK_U32 expand; +} SlotHalFbcAdjCfg; + +RK_U32 mpp_slots_is_empty(MppBufSlots slots, SlotQueueType type); +RK_S32 mpp_slots_get_used_count(MppBufSlots slots); +RK_S32 mpp_slots_get_unused_count(MppBufSlots slots); +MPP_RET mpp_slots_set_prop(MppBufSlots slots, SlotsPropType type, void *val); +MPP_RET mpp_slots_get_prop(MppBufSlots slots, SlotsPropType type, void *val); +MPP_RET mpp_buf_slot_reset(MppBufSlots slots, RK_S32 index); //rest slot status when info_change no ok + +// special one for generate default frame to slot at index and return pointer +MPP_RET mpp_buf_slot_default_info(MppBufSlots slots, RK_S32 index, void *val); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_BUF_SLOT_H */ diff --git a/mpp/base/inc/mpp_buffer_impl.h b/mpp/base/inc/mpp_buffer_impl.h new file mode 100644 index 000000000..651142066 --- /dev/null +++ b/mpp/base/inc/mpp_buffer_impl.h @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_BUFFER_IMPL_H +#define MPP_BUFFER_IMPL_H + +#include "mpp_list.h" +#include "mpp_hash.h" +#include "mpp_common.h" +#include "mpp_allocator.h" +#include "mpp_device.h" + +#define MPP_BUF_DBG_FUNCTION (0x00000001) +#define MPP_BUF_DBG_OPS_RUNTIME (0x00000002) +#define MPP_BUF_DBG_OPS_HISTORY (0x00000004) +#define MPP_BUF_DBG_CLR_ON_EXIT (0x00000010) +#define MPP_BUF_DBG_DUMP_ON_EXIT (0x00000020) +#define MPP_BUF_DBG_CHECK_SIZE (0x00000100) + +#define mpp_buf_dbg(flag, fmt, ...) mpp_dbg(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_buf_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__) + +#define MPP_BUF_FUNCTION_ENTER() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "enter\n") +#define MPP_BUF_FUNCTION_LEAVE() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "leave\n") +#define MPP_BUF_FUNCTION_LEAVE_OK() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "success\n") +#define MPP_BUF_FUNCTION_LEAVE_FAIL() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "failed\n") + +typedef enum MppBufOps_e { + GRP_CREATE, + GRP_RELEASE, + GRP_RESET, + GRP_ORPHAN, + GRP_DESTROY, + BUF_COMMIT, + BUF_CREATE, + BUF_MMAP, + BUF_REF_INC, + BUF_REF_DEC, + BUF_DISCARD, + BUF_DESTROY, + BUF_OPS_BUTT, +} MppBufOps; + +typedef struct MppBufLog_t { + RK_U32 group_id; + RK_S32 buffer_id; + MppBufOps ops; + RK_S32 ref_count; + const char *caller; +} MppBufLog; + +typedef struct MppBufLogs_t { + pthread_mutex_t lock; + RK_U16 max_count; + RK_U16 log_count; + RK_U16 log_write; + RK_U16 log_read; + MppBufLog *logs; +} MppBufLogs; + +typedef struct MppBufferImpl_t MppBufferImpl; +typedef struct MppBufferGroupImpl_t MppBufferGroupImpl; +typedef void (*MppBufCallback)(void *arg1, void *arg2); + +// use index instead of pointer to avoid invalid pointer +struct MppBufferImpl_t { + char tag[MPP_TAG_SIZE]; + const char *caller; + pthread_mutex_t lock; + /* parameter store from MppBufferGroup */ + MppAllocator allocator; + MppAllocatorApi *alloc_api; + RK_U32 log_runtime_en; + RK_U32 log_history_en; + RK_U32 group_id; + RK_S32 buffer_id; + MppBufferMode mode; + MppBufferType type; + MppBufLogs *logs; + + MppBufferInfo info; + size_t offset; + size_t length; + + /* cacheable flag */ + RK_U32 uncached; + + /* + * discard: + * used for buf on group reset mode + * set disard value to 1 when frame refcount no zero , + * we will delay relesase buffer after refcount to zero, + * not put this buf to unused list + */ + RK_S32 discard; + // used flag is for used/unused list detection + RK_U32 used; + RK_S32 ref_count; + struct list_head list_status; + + /* + * mpp_device map for attach / detach operation + */ + struct list_head list_maps; +}; + +struct MppBufferGroupImpl_t { + char tag[MPP_TAG_SIZE]; + const char *caller; + /* parameter store for MppBuffer */ + MppAllocator allocator; + MppAllocatorApi *alloc_api; + MppAllocFlagType flags; + RK_U32 log_runtime_en; + RK_U32 log_history_en; + RK_U32 group_id; + MppBufferMode mode; + MppBufferType type; + + /* group status flag */ + // buffer force clear mode flag + RK_U32 clear_on_exit; + RK_U32 dump_on_exit; + // is_misc: 0 - normal group 1 - misc group + RK_U32 is_misc; + // is_orphan: 0 - normal group 1 - orphan group + RK_U32 is_orphan; + RK_U32 is_finalizing; + // used in limit mode only + size_t limit_size; + RK_S32 limit_count; + // status record + size_t limit; + size_t usage; + RK_S32 buffer_id; + RK_S32 buffer_count; + + // thread that will be signal on buffer return + MppBufCallback callback; + void *arg; + + // link to list_status in MppBufferImpl + pthread_mutex_t buf_lock; + struct hlist_node hlist; + struct list_head list_used; + struct list_head list_unused; + RK_S32 count_used; + RK_S32 count_unused; + + // buffer log function + MppBufLogs *logs; + + // link to the other MppBufferGroupImpl + struct list_head list_group; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +extern RK_U32 mpp_buffer_debug; + +/* + * mpp_buffer_create : create a unused buffer with parameter tag/size/data + * if input buffer is NULL then buffer will be register to unused list + * otherwise the buffer will be register to used list and set to paramter buffer + * + * mpp_buffer_mmap : The created mpp_buffer can not be accessed directly. + * It required map to access. This is an optimization + * for reducing virtual memory usage. + * + * mpp_buffer_get_unused : get unused buffer with size. it will first search + * the unused list. if failed it will create on from + * group allocator. + * + * mpp_buffer_ref_inc : increase buffer's reference counter. if it is unused + * then it will be moved to used list. + * + * mpp_buffer_ref_dec : decrease buffer's reference counter. if the reference + * reduce to zero buffer will be moved to unused list. + * + * normal call flow will be like this: + * + * mpp_buffer_create - create a unused buffer + * mpp_buffer_get_unused - get the unused buffer + * mpp_buffer_ref_inc/dec - use the buffer + * mpp_buffer_destory - destroy the buffer + */ +MPP_RET mpp_buffer_create(const char *tag, const char *caller, MppBufferGroupImpl *group, MppBufferInfo *info, MppBufferImpl **buffer); +MPP_RET mpp_buffer_mmap(MppBufferImpl *buffer, const char* caller); +MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer, const char* caller); +MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer, const char* caller); +MPP_RET mpp_buffer_discard(MppBufferImpl *buffer, const char* caller); +MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size, const char* caller); +RK_U32 mpp_buffer_to_addr(MppBuffer buffer, size_t offset); +MPP_RET mpp_buffer_attach_dev_f(const char *caller, MppBuffer buffer, MppDev dev); +MPP_RET mpp_buffer_detach_dev_f(const char *caller, MppBuffer buffer, MppDev dev); +RK_U32 mpp_buffer_get_iova_f(const char *caller, MppBuffer buffer, MppDev dev); + +#define mpp_buffer_attach_dev(buf, dev) mpp_buffer_attach_dev_f(__FUNCTION__, buf, dev) +#define mpp_buffer_detach_dev(buf, dev) mpp_buffer_detach_dev_f(__FUNCTION__, buf, dev) +#define mpp_buffer_get_iova(buf, dev) mpp_buffer_get_iova_f(__FUNCTION__, buf, dev) + +MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, const char *caller, MppBufferMode mode, MppBufferType type); +MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p); +MPP_RET mpp_buffer_group_reset(MppBufferGroupImpl *p); +MPP_RET mpp_buffer_group_set_callback(MppBufferGroupImpl *p, + MppBufCallback callback, void *arg); +// mpp_buffer_group helper function +void mpp_buffer_group_dump(MppBufferGroupImpl *p, const char *caller); +MppBufferGroupImpl *mpp_buffer_get_misc_group(MppBufferMode mode, MppBufferType type); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_BUFFER_IMPL_H */ diff --git a/mpp/base/inc/mpp_cfg_io.h b/mpp/base/inc/mpp_cfg_io.h new file mode 100644 index 000000000..32672d99d --- /dev/null +++ b/mpp/base/inc/mpp_cfg_io.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_CFG_IO_H +#define MPP_CFG_IO_H + +#include "rk_mpp_cfg.h" + +#include "mpp_internal.h" + +typedef enum MppCfgType_e { + MPP_CFG_TYPE_INVALID = 0, + + /* invalid or empty value type */ + MPP_CFG_TYPE_NULL, + + /* leaf type must with name */ + MPP_CFG_TYPE_BOOL, + MPP_CFG_TYPE_s8, + MPP_CFG_TYPE_u8, + MPP_CFG_TYPE_s16, + MPP_CFG_TYPE_u16, + MPP_CFG_TYPE_s32, + MPP_CFG_TYPE_u32, + MPP_CFG_TYPE_s64, + MPP_CFG_TYPE_u64, + MPP_CFG_TYPE_f32, + MPP_CFG_TYPE_f64, + MPP_CFG_TYPE_STRING, + MPP_CFG_TYPE_RAW, + + /* branch type */ + MPP_CFG_TYPE_OBJECT, + MPP_CFG_TYPE_ARRAY, + + MPP_CFG_TYPE_BUTT, +} MppCfgType; + +typedef union MppCfgVal_u { + rk_bool b1; + rk_s8 s8; + rk_u8 u8; + rk_s16 s16; + rk_u16 u16; + rk_s32 s32; + rk_u32 u32; + rk_s64 s64; + rk_u64 u64; + rk_float f32; + rk_double f64; + void *str; + void *ptr; +} MppCfgVal; + +typedef void* MppCfgObj; +typedef rk_s32 (*MppCfgObjCond)(MppCfgObj obj); + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_cfg_get_object(MppCfgObj *obj, const char *name, MppCfgType type, MppCfgVal *val); +rk_s32 mpp_cfg_get_array(MppCfgObj *obj, const char *name, rk_s32 count); +rk_s32 mpp_cfg_put(MppCfgObj obj); +rk_s32 mpp_cfg_put_all(MppCfgObj obj); + +/* object tree build */ +rk_s32 mpp_cfg_add(MppCfgObj root, MppCfgObj leaf); +/* object tree release */ +rk_s32 mpp_cfg_del(MppCfgObj obj); +/* find by name string */ +rk_s32 mpp_cfg_find(MppCfgObj *obj, MppCfgObj root, char *name, rk_s32 type); + +/* attach KmppEntry for access location */ +rk_s32 mpp_cfg_set_entry(MppCfgObj obj, KmppEntry *entry); +/* add cfg obj condition for input / output option */ +rk_s32 mpp_cfg_set_cond(MppCfgObj obj, MppCfgObjCond cond); + +void mpp_cfg_dump(MppCfgObj obj, const char *func); +#define mpp_cfg_dump_f(obj) mpp_cfg_dump(obj, __FUNCTION__) + +/* mark all MppCfgObject ready and build trie for string access */ +MppTrie mpp_cfg_to_trie(MppCfgObj obj); + +/* mpp_cfg output to string and input from string */ +rk_s32 mpp_cfg_to_string(MppCfgObj obj, MppCfgStrFmt fmt, char **buf); +rk_s32 mpp_cfg_from_string(MppCfgObj *obj, MppCfgStrFmt fmt, const char *buf); + +/* + * obj - read from file or string and get an object as source + * type - struct type object root for location table indexing and access + * st - struct body to write obj values to + */ +rk_s32 mpp_cfg_to_struct(MppCfgObj obj, MppCfgObj type, void *st); +/* + * obj - output object root for the struct values + * type - struct type object root for location table access + * st - struct body to write obj values + */ +rk_s32 mpp_cfg_from_struct(MppCfgObj *obj, MppCfgObj type, void *st); + +rk_s32 mpp_cfg_print_string(char *buf); + +/* convert element type to config type */ +MppCfgType mpp_cfg_type_from_elem_type(ElemType type); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_CFG_IO_H */ diff --git a/mpp/base/inc/mpp_cluster.h b/mpp/base/inc/mpp_cluster.h new file mode 100644 index 000000000..8522c5936 --- /dev/null +++ b/mpp/base/inc/mpp_cluster.h @@ -0,0 +1,51 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_CLUSTER_H +#define MPP_CLUSTER_H + +#include "mpp_err.h" +#include "mpp_list.h" +#include "mpp_thread.h" +#include "mpp_dev_defs.h" + +#define MAX_PRIORITY 1 + +typedef void* MppNode; + +typedef MPP_RET (*TaskProc)(void *param); + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_node_init(MppNode *node); +MPP_RET mpp_node_deinit(MppNode node); + +MPP_RET mpp_node_set_func(MppNode node, TaskProc proc, void *param); + +MPP_RET mpp_node_attach(MppNode node, MppClientType type); +MPP_RET mpp_node_detach(MppNode node); + +#define mpp_node_trigger(node, trigger) mpp_node_trigger_f(__FUNCTION__, node, trigger) + +MPP_RET mpp_node_trigger_f(const char *caller, MppNode node, RK_S32 trigger); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_CLUSTER_H */ diff --git a/mpp/base/inc/mpp_dec_cb_param.h b/mpp/base/inc/mpp_dec_cb_param.h new file mode 100644 index 000000000..97f723b39 --- /dev/null +++ b/mpp/base/inc/mpp_dec_cb_param.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_DEC_CB_PARAM_H +#define MPP_DEC_CB_PARAM_H + +#include "rk_type.h" + +typedef enum MppDecCbCmd_e { + DEC_CALLBACK_NONE = 0, + + DEC_CALLBACK_BASE = 0x100, + DEC_PARSER_CALLBACK = (DEC_CALLBACK_BASE + 1), + DEC_CALLBACK_CMD_BUTT, +} MppDecCbCmd; + +/* DEC_PARSER_CALLBACK */ +typedef struct DecCallBackParam_t { + void *task; + RK_U32 *regs; + RK_U32 hard_err; +} DecCbHalDone; + +#endif /* MPP_DEC_CB_PARAM_H */ diff --git a/mpp/base/inc/mpp_enc_cb_param.h b/mpp/base/inc/mpp_enc_cb_param.h new file mode 100644 index 000000000..b84951f4b --- /dev/null +++ b/mpp/base/inc/mpp_enc_cb_param.h @@ -0,0 +1,39 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_ENC_CB_PARAM_H +#define MPP_ENC_CB_PARAM_H + +#include "rk_type.h" + +typedef enum MppEncCbCmd_e { + ENC_CALLBACK_NONE = 0, + + ENC_CALLBACK_BASE = 0x200, + ENC_OUTPUT_FINISH = (ENC_CALLBACK_BASE + 1), + ENC_OUTPUT_SLICE = (ENC_CALLBACK_BASE + 2), + ENC_CALLBACK_CMD_BUTT, +} MppEncCbCmd; + +/* DEC_PARSER_CALLBACK */ +typedef struct EncOutParam_t { + void *task; + void *base; + RK_S32 start; + RK_S32 length; +} EncOutParam; + +#endif /* MPP_ENC_CB_PARAM_H */ diff --git a/mpp/base/inc/mpp_enc_ref.h b/mpp/base/inc/mpp_enc_ref.h new file mode 100644 index 000000000..6fa47a29f --- /dev/null +++ b/mpp/base/inc/mpp_enc_ref.h @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_ENC_REF_H +#define MPP_ENC_REF_H + +#include "rk_venc_ref.h" + +#define REF_MODE_IS_GLOBAL(mode) ((mode >= REF_TO_PREV_REF_FRM) && (mode < REF_MODE_GLOBAL_BUTT)) +#define REF_MODE_IS_LT_MODE(mode) ((mode > REF_MODE_LT) && (mode < REF_MODE_LT_BUTT)) +#define REF_MODE_IS_ST_MODE(mode) ((mode > REF_MODE_ST) && (mode < REF_MODE_ST_BUTT)) + +typedef struct MppEncCpbInfo_t { + RK_S32 dpb_size; + RK_S32 max_lt_cnt; + RK_S32 max_st_cnt; + RK_S32 max_lt_idx; + RK_S32 max_st_tid; + /* loop length of st/lt config */ + RK_S32 lt_gop; + RK_S32 st_gop; +} MppEncCpbInfo; + +typedef struct MppEncRefCfgImpl_t { + const char *name; + RK_S32 ready; + RK_U32 debug; + + /* config from user */ + RK_S32 keep_cpb; + RK_S32 max_lt_cfg; + RK_S32 max_st_cfg; + RK_S32 lt_cfg_cnt; + RK_S32 st_cfg_cnt; + RK_S32 max_tlayers; + MppEncRefLtFrmCfg *lt_cfg; + MppEncRefStFrmCfg *st_cfg; + + /* generated parameter for MppEncRefs */ + MppEncCpbInfo cpb_info; +} MppEncRefCfgImpl; + +#ifdef __cplusplus +extern "C" { +#endif + +MppEncRefCfg mpp_enc_ref_default(void); +MPP_RET mpp_enc_ref_cfg_copy(MppEncRefCfg dst, MppEncRefCfg src); +MppEncCpbInfo *mpp_enc_ref_cfg_get_cpb_info(MppEncRefCfg ref); + +#define check_is_mpp_enc_ref_cfg(ref) _check_is_mpp_enc_ref_cfg(__FUNCTION__, ref) +MPP_RET _check_is_mpp_enc_ref_cfg(const char *func, void *ref); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENC_REF_H */ diff --git a/mpp/base/inc/mpp_enc_refs.h b/mpp/base/inc/mpp_enc_refs.h new file mode 100644 index 000000000..34a69c6b7 --- /dev/null +++ b/mpp/base/inc/mpp_enc_refs.h @@ -0,0 +1,94 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_ENC_REFS_H +#define MPP_ENC_REFS_H + +#include "mpp_enc_cfg.h" +#include "mpp_enc_ref.h" + +/* + * MppEncRefs has two runtime mode: + * + * 1. dryrun mode + * This mode is for estimating the dpb size and configure check. + * + * 2. runtime mode + * Thie mode is for real dpb loop in real encoder workflow. + * + * When encoder is running user can change the frame property by MppEncRefFrmUsrCfg. + */ +#define ENC_FORCE_IDR (0x00000001) +#define ENC_FORCE_NONREF (0x00000002) +#define ENC_FORCE_LT_REF_IDX (0x00000004) +#define ENC_FORCE_TEMPORAL_ID (0x00000008) +#define ENC_FORCE_REF_MODE (0x00000010) +#define ENC_FORCE_PSKIP_IS_REF (0x00000020) +#define ENC_FORCE_PSKIP_NON_REF (0x00000040) + +typedef struct MppEncRefFrmForceCfg_t { + RK_U32 force_flag; + RK_S32 force_idr; + RK_S32 force_pskip; + RK_S32 force_nonref; + RK_S32 force_lt_idx; + RK_S32 force_temporal_id; + MppEncRefMode force_ref_mode; + RK_S32 force_ref_arg; +} MppEncRefFrmUsrCfg; + +typedef void* MppEncRefs; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_enc_refs_init(MppEncRefs *refs); +MPP_RET mpp_enc_refs_deinit(MppEncRefs *refs); + +MPP_RET mpp_enc_refs_set_cfg(MppEncRefs refs, MppEncRefCfg ref_cfg); +MPP_RET mpp_enc_refs_set_usr_cfg(MppEncRefs refs, MppEncRefFrmUsrCfg *force); +MPP_RET mpp_enc_refs_set_rc_igop(MppEncRefs refs, RK_S32 igop); +MPP_RET mpp_enc_refs_set_refresh_length(MppEncRefs refs, RK_S32 len); + +/* return hdr need update or not */ +RK_S32 mpp_enc_refs_update_hdr(MppEncRefs refs); + +/* get dpb size */ +MPP_RET mpp_enc_refs_get_cpb_info(MppEncRefs refs, MppEncCpbInfo *info); +/* get status for next frame */ +MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status); +/* dryrun and check all configure */ +MPP_RET mpp_enc_refs_dryrun(MppEncRefs refs); + +MPP_RET mpp_enc_refs_stash(MppEncRefs refs); +MPP_RET mpp_enc_refs_rollback(MppEncRefs refs); + +/* two-pass encoding functions */ +/* check next frame is intra or not */ +RK_S32 mpp_enc_refs_next_frm_is_intra(MppEncRefs refs); +MPP_RET mpp_enc_refs_get_cpb_pass1(MppEncRefs refs, EncCpbStatus *status); +MPP_RET mpp_enc_refs_force_recon(MppEncRefs refs, RK_S32 force_recon); + +#define dump_frm(frm) _dump_frm(frm, __FUNCTION__, __LINE__) + +void _dump_frm(EncFrmStatus *frm, const char *func, RK_S32 line); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENC_REFS_H */ diff --git a/mpp/base/inc/mpp_frame_impl.h b/mpp/base/inc/mpp_frame_impl.h new file mode 100644 index 000000000..98a747984 --- /dev/null +++ b/mpp/base/inc/mpp_frame_impl.h @@ -0,0 +1,224 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_FRAME_IMPL_H +#define MPP_FRAME_IMPL_H + +#include "mpp_time.h" +#include "mpp_frame.h" + +typedef struct MppFrameImpl_t MppFrameImpl; + +typedef union MppFrameStatus_u { + /* total 64 bit frame status for internal flow */ + RK_U64 val; + + struct { + /* bit 0 ~ 7 common frame status flag for both encoder and decoder */ + + /* + * data status flag + * 0 - pixel data is invalid + * 1 - pixel data is valid + */ + RK_U32 valid : 1; + + /* reference status flag */ + /* + * 0 - inter frame + * 1 - intra frame + */ + RK_U32 is_intra : 1; + + /* + * Valid when is_intra is true + * 0 - normal intra frame + * 1 - IDR frame + */ + RK_U32 is_idr : 1; + + /* + * 0 - mark as reference frame + * 1 - mark as non-refernce frame + */ + RK_U32 is_non_ref : 1; + + /* + * Valid when is_non_ref is false + * 0 - mark as short-term reference frame + * 1 - mark as long-term refernce frame + */ + RK_U32 is_lt_ref : 1; + RK_U32 is_b_frame : 1; + + /* + * frame usage flag for decoder / encoder flow + * 0 - mark as general frame + * 1 - mark as used by decoder + * 2 - mark as used by encoder + * 4 - mark as used by vproc + */ + RK_U32 usage : 3; + }; +} MppFrameStatus; + +struct MppFrameImpl_t { + const char *name; + + /* + * dimension parameter for display + */ + RK_U32 width; + RK_U32 height; + RK_U32 hor_stride; + RK_U32 ver_stride; + RK_U32 hor_stride_pixel; + RK_U32 fbc_hdr_stride; + RK_U32 offset_x; + RK_U32 offset_y; + + /* + * interlaced related mode status + * + * 0 - frame + * 1 - top field + * 2 - bottom field + * 3 - paired top and bottom field + * 4 - deinterlaced flag + * 7 - deinterlaced paired field + */ + RK_U32 mode; + /* + * current decoded frame whether to display + * + * 0 - reserve + * 1 - discard + */ + RK_U32 discard; + /* + * send decoded frame belong which view + */ + RK_U32 viewid; + /* + * poc - picture order count + */ + RK_U32 poc; + /* + * pts - display time stamp + * dts - decode time stamp + */ + RK_S64 pts; + RK_S64 dts; + + /* + * eos - end of stream + * info_change - set when buffer resized or frame infomation changed + */ + RK_U32 eos; + RK_U32 info_change; + RK_U32 errinfo; + MppFrameColorRange color_range; + MppFrameColorPrimaries color_primaries; + MppFrameColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * It must be accessed using av_frame_get_colorspace() and + * av_frame_set_colorspace(). + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + MppFrameColorSpace colorspace; + MppFrameChromaLocation chroma_location; + + MppFrameFormat fmt; + + MppFrameRational sar; + MppFrameMasteringDisplayMetadata mastering_display; + MppFrameContentLightMetadata content_light; + MppFrameHdrDynamicMeta *hdr_dynamic_meta; + + /* + * buffer information + * NOTE: buf_size only access internally + */ + MppBuffer buffer; + size_t buf_size; + + /* + * meta data information + */ + MppTask task; + MppMeta meta; + MppStopwatch stopwatch; + + /* + * frame buffer compression (FBC) information + * + * NOTE: some constraint on fbc data + * 1. FBC config need two addresses but only one buffer. + * The second address should be represented by base + offset form. + * 2. FBC has header address and payload address + * Both addresses should be 4K aligned. + * 3. The header section size is default defined by: + * header size = aligned(aligned(width, 16) * aligned(height, 16) / 16, 4096) + * 4. The stride in header section is defined by: + * stride = aligned(width, 16) + */ + RK_U32 fbc_offset; + size_t fbc_size; + + /* + * frame buffer contain downsacle pic + * + * downscale pic is no fbc fmt the downscale pic size + * w/2 x h / 2 + */ + RK_U32 thumbnail_en; + + /* + * frame status info for internal flow + */ + MppFrameStatus status; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +MppFrame mpp_frame_dup(MppFrame src); +MPP_RET mpp_frame_copy(MppFrame dst, MppFrame src); +MPP_RET mpp_frame_info_cmp(MppFrame frame0, MppFrame frame1); +RK_U32 mpp_frame_get_fbc_offset(MppFrame frame); +RK_U32 mpp_frame_get_fbc_stride(MppFrame frame); +size_t mpp_frame_get_fbc_size(MppFrame frame); +void mpp_frame_set_fbc_size(MppFrame frame, size_t size); + +MppFrameStatus *mpp_frame_get_status(MppFrame frame); + +/* + * Debug for frame process timing + */ +void mpp_frame_set_stopwatch_enable(MppFrame frame, RK_S32 enable); +MppStopwatch mpp_frame_get_stopwatch(const MppFrame frame); + +MPP_RET __check_is_mpp_frame(void *frame); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_FRAME_IMPL_H */ diff --git a/mpp/base/inc/mpp_meta_impl.h b/mpp/base/inc/mpp_meta_impl.h new file mode 100644 index 000000000..57e349ff1 --- /dev/null +++ b/mpp/base/inc/mpp_meta_impl.h @@ -0,0 +1,69 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_META_IMPL_H +#define MPP_META_IMPL_H + +#include "mpp_common.h" + +#include "mpp_list.h" +#include "mpp_meta.h" +#include "rk_venc_cmd.h" + +typedef struct MppMetaVal_t { + RK_U32 state; + union { + RK_S32 val_s32; + RK_S64 val_s64; + void *val_ptr; + MppFrame frame; + MppPacket packet; + MppBuffer buffer; + RK_U64 val_kptr; /* kernel object userspace address */ + }; +} MppMetaVal; + +typedef struct MppMetaImpl_t { + char tag[MPP_TAG_SIZE]; + const char *caller; + RK_S32 meta_id; + RK_S32 ref_count; + + struct list_head list_meta; + RK_S32 node_count; + MppEncUserData user_data; + MppEncUserDataSet user_data_set; + RK_U32 datas_buf_size; + MppMetaVal vals[0]; +} MppMetaImpl; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_meta_dump(MppMeta meta); +MPP_RET mpp_meta_inc_ref(MppMeta meta); + +RK_S32 mpp_meta_s32_read(MppMeta meta, RK_S32 index, RK_S32 *val); + +extern RK_S32 meta_hdr_offset_index; +extern RK_S32 meta_hdr_size_index; + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_META_IMPL_H */ diff --git a/mpp/base/inc/mpp_packet_impl.h b/mpp/base/inc/mpp_packet_impl.h new file mode 100644 index 000000000..984add9fc --- /dev/null +++ b/mpp/base/inc/mpp_packet_impl.h @@ -0,0 +1,118 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_PACKET_IMPL_H +#define MPP_PACKET_IMPL_H + +#include "mpp_packet.h" + +#define MPP_PACKET_FLAG_EOS (0x00000001) +#define MPP_PACKET_FLAG_EXTRA_DATA (0x00000002) +#define MPP_PACKET_FLAG_INTERNAL (0x00000004) +#define MPP_PACKET_FLAG_INTRA (0x00000010) +#define MPP_PACKET_FLAG_PARTITION (0x00000020) +#define MPP_PACKET_FLAG_EOI (0x00000040) + +#define MPP_PKT_SEG_CNT_DEFAULT 8 + +typedef void (*ReleaseCb)(void *ctx, void *arg); + +typedef union MppPacketStatus_t { + RK_U32 val; + struct { + RK_U32 eos : 1; + RK_U32 extra_data : 1; + RK_U32 internal : 1; + /* packet is inputed on reset mark as discard */ + RK_U32 discard : 1; + + /* for slice input output */ + RK_U32 partition : 1; + RK_U32 soi : 1; + RK_U32 eoi : 1; + }; +} MppPacketStatus; + +/* + * mpp_packet_imp structure + * + * data : pointer + * size : total buffer size + * offset : valid data start offset + * length : valid data length + * pts : packet pts + * dts : packet dts + */ +typedef struct MppPacketImpl_t { + const char *name; + + void *data; + void *pos; + size_t size; + size_t length; + + RK_S64 pts; + RK_S64 dts; + + MppPacketStatus status; + RK_U32 flag; + + MppBuffer buffer; + MppMeta meta; + MppTask task; + + RK_U32 segment_nb; + RK_U32 segment_buf_cnt; + MppPktSeg segments_def[MPP_PKT_SEG_CNT_DEFAULT]; + MppPktSeg *segments_ext; + MppPktSeg *segments; + + /* release callback info */ + ReleaseCb release; + void *release_ctx; + void *release_arg; +} MppPacketImpl; + +#ifdef __cplusplus +extern "C" { +#endif +/* + * mpp_packet_reset is only used internelly and should NOT be used outside + */ +MPP_RET mpp_packet_reset(MppPacketImpl *packet); +MPP_RET mpp_packet_copy(MppPacket dst, MppPacket src); +MPP_RET mpp_packet_append(MppPacket dst, MppPacket src); + +MPP_RET mpp_packet_set_status(MppPacket packet, MppPacketStatus status); +MPP_RET mpp_packet_get_status(MppPacket packet, MppPacketStatus *status); +void mpp_packet_set_task(MppPacket packet, MppTask task); +MppTask mpp_packet_get_task(MppPacket packet); + +void mpp_packet_reset_segment(MppPacket packet); +void mpp_packet_set_segment_nb(MppPacket packet, RK_U32 segment_nb); +MPP_RET mpp_packet_add_segment_info(MppPacket packet, RK_S32 type, RK_S32 offset, RK_S32 len); +void mpp_packet_copy_segment_info(MppPacket dst, MppPacket src); +void mpp_packet_set_release(MppPacket packet, ReleaseCb release, void *ctx, void *arg); + +/* pointer check function */ +MPP_RET check_is_mpp_packet_f(void *ptr, const char *caller); +#define check_is_mpp_packet(ptr) check_is_mpp_packet_f(ptr, __FUNCTION__) + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_PACKET_IMPL_H */ diff --git a/mpp/base/inc/mpp_ref_pool.h b/mpp/base/inc/mpp_ref_pool.h new file mode 100644 index 000000000..caa63bd48 --- /dev/null +++ b/mpp/base/inc/mpp_ref_pool.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_REF_POOL_H +#define MPP_REF_POOL_H + +#include "rk_type.h" + +/* header of reference pool */ +typedef struct MppRefPool_t { + RK_S32 capacity; + RK_S32 count; + void *slots; +} MppRefPool; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_ref_pool_init(MppRefPool *pool, RK_U32 capacity); +void mpp_ref_pool_deinit(MppRefPool *pool); +void mpp_ref_pool_cleanup(MppRefPool *pool); + +RK_S32 mpp_ref_pool_get(MppRefPool *pool, RK_U32 size); +void mpp_ref_pool_ref(MppRefPool *pool, RK_S32 idx); +void mpp_ref_pool_put(MppRefPool *pool, RK_S32 idx); + +void *mpp_ref_pool_ptr(MppRefPool *pool, RK_S32 idx); +RK_U32 mpp_ref_pool_size(MppRefPool *pool, RK_S32 idx); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_REF_POOL_H */ diff --git a/mpp/base/inc/mpp_task_impl.h b/mpp/base/inc/mpp_task_impl.h new file mode 100644 index 000000000..3333fcb34 --- /dev/null +++ b/mpp/base/inc/mpp_task_impl.h @@ -0,0 +1,129 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_TASK_IMPL_H +#define MPP_TASK_IMPL_H + +#include "mpp_list.h" +#include "mpp_task.h" + +typedef void* MppPort; +typedef void* MppTaskQueue; + +/* + * mpp task status transaction + * + * mpp task is generated from mpp port. When create a mpp port the corresponding task + * will be created, too. Then external user will dequeue task from port and enqueue to + * mpp port for process. + * + * input port task work flow: + * + * description | call | status transaction + * 1. input port init | enqueue(external) | -> external_queue + * 2. input port user dequeue | dequeue(external) | external_queue -> external_hold + * 3. user setup task for processing| | + * 4. input port user enqueue | enqueue(external) | external_hold -> internal_queue + * 5. input port mpp start process | dequeue(internal) | internal_queue -> internal_hold + * 6. mpp process task | | + * 7. input port mpp task finish | enqueue(internal) | internal_hold -> external_queue + * loop to 2 + * + * output port task work flow: + * description | call | status transaction + * 1. output port init | enqueue(internal) | -> internal_queue + * 2. output port mpp task dequeue | dequeue(internal) | internal_queue -> internal_hold + * 3. mpp setup task by processed frame/packet | + * 4. output port mpp task enqueue | enqueue(internal) | internal_hold -> external_queue + * 5. output port user task dequeue | dequeue(external) | external_queue -> external_hold + * 6. user get task as output | | + * 7. output port user release task | enqueue(external) | external_hold -> external_queue + * loop to 2 + * + */ +typedef enum MppTaskStatus_e { + MPP_INPUT_PORT, /* in external queue and ready for external dequeue */ + MPP_INPUT_HOLD, /* dequeued and hold by external user, user will config */ + MPP_OUTPUT_PORT, /* in mpp internal work queue and ready for mpp dequeue */ + MPP_OUTPUT_HOLD, /* dequeued and hold by mpp internal worker, mpp is processing */ + MPP_TASK_STATUS_BUTT, +} MppTaskStatus; + +typedef struct MppTaskImpl_t { + const char *name; + struct list_head list; + MppTaskQueue queue; + RK_S32 index; + MppTaskStatus status; + + MppMeta meta; +} MppTaskImpl; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET check_mpp_task_name(MppTask task); + +/* + * Mpp task queue function: + * + * mpp_task_queue_init - create task queue structure + * mpp_task_queue_deinit - destory task queue structure + * mpp_task_queue_get_port - return input or output port of task queue + * + * Typical work flow, task mpp_dec for example: + * + * 1. Mpp layer creates one task queue in order to connect mpp input and mpp_dec input. + * 2. Mpp layer setups the task count in task queue input port. + * 3. Get input port from the task queue and assign to mpp input as mpp_input_port. + * 4. Get output port from the task queue and assign to mpp_dec input as dec_input_port. + * 5. Let the loop start. + * a. mpi user will dequeue task from mpp_input_port. + * b. mpi user will setup task. + * c. mpi user will enqueue task back to mpp_input_port. + * d. task will automatically transfer to dec_input_port. + * e. mpp_dec will dequeue task from dec_input_port. + * f. mpp_dec will process task. + * g. mpp_dec will enqueue task back to dec_input_port. + * h. task will automatically transfer to mpp_input_port. + * 6. Stop the loop. All tasks must be return to input port with idle status. + * 6. Mpp layer destory the task queue. + */ +MPP_RET mpp_task_queue_init(MppTaskQueue *queue, void *mpp, const char *name); +MPP_RET mpp_task_queue_setup(MppTaskQueue queue, RK_S32 task_count); +MPP_RET mpp_task_queue_deinit(MppTaskQueue queue); +MppPort mpp_task_queue_get_port(MppTaskQueue queue, MppPortType type); + +#define mpp_port_poll(port, timeout) _mpp_port_poll(__FUNCTION__, port, timeout) +#define mpp_port_dequeue(port, task) _mpp_port_dequeue(__FUNCTION__, port, task) +#define mpp_port_enqueue(port, task) _mpp_port_enqueue(__FUNCTION__, port, task) +#define mpp_port_awake(port) _mpp_port_awake(__FUNCTION__, port) +#define mpp_port_move(port, task, status) _mpp_port_move(__FUNCTION__, port, task, status) + +MPP_RET _mpp_port_poll(const char *caller, MppPort port, MppPollType timeout); +MPP_RET _mpp_port_dequeue(const char *caller, MppPort port, MppTask *task); +MPP_RET _mpp_port_enqueue(const char *caller, MppPort port, MppTask task); +MPP_RET _mpp_port_awake(const char *caller, MppPort port); +MPP_RET _mpp_port_move(const char *caller, MppPort port, MppTask task, MppTaskStatus status); + +MppMeta mpp_task_get_meta(MppTask task); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_TASK_IMPL_H */ diff --git a/mpp/base/inc/mpp_trie.h b/mpp/base/inc/mpp_trie.h new file mode 100644 index 000000000..9e6bd62db --- /dev/null +++ b/mpp/base/inc/mpp_trie.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_TRIE_H +#define MPP_TRIE_H + +#include + +#include "mpp_internal.h" + +#define MPP_TRIE_KEY_LEN (4) +#define MPP_TRIE_KEY_MAX (1 << (MPP_TRIE_KEY_LEN)) + +/* + * MppTrie node buffer layout + * +---------------+ + * | MppTrieImpl | + * +---------------+ + * | MppTrieNodes | + * +---------------+ + * | MppTrieInfos | + * +---------------+ + * + * MppTrieInfo element layout + * +---------------+ + * | MppTrieInfo | + * +---------------+ + * | name string | + * +---------------+ + * | User context | + * +---------------+ + */ +typedef struct MppTrieInfo_t { + rk_u32 index : 12; + rk_u32 ctx_len : 12; + rk_u32 str_len : 8; +} MppTrieInfo; + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_trie_init(MppTrie *trie, const char *name); +rk_s32 mpp_trie_init_by_root(MppTrie *trie, void *root); +rk_s32 mpp_trie_deinit(MppTrie trie); + +/* Add NULL info to mark the last trie entry */ +rk_s32 mpp_trie_add_info(MppTrie trie, const char *name, void *ctx, rk_u32 ctx_len); + +rk_s32 mpp_trie_get_node_count(MppTrie trie); +rk_s32 mpp_trie_get_info_count(MppTrie trie); +rk_s32 mpp_trie_get_buf_size(MppTrie trie); +rk_s32 mpp_trie_get_name_max(MppTrie trie); +void *mpp_trie_get_node_root(MppTrie trie); + +static inline const char *mpp_trie_info_name(MppTrieInfo *info) +{ + return (info) ? (const char *)(info + 1) : NULL; +} + +static inline void *mpp_trie_info_ctx(MppTrieInfo *info) +{ + return (info) ? (void *)((char *)(info + 1) + info->str_len) : NULL; +} + +static inline rk_s32 mpp_trie_info_is_self(MppTrieInfo *info) +{ + return (info) ? (strstr((const char *)(info + 1), "__") != NULL ? 1 : 0) : 0; +} + +static inline rk_s32 mpp_trie_info_name_is_self(const char *name) +{ + return (name) ? (strstr(name, "__") != NULL ? 1 : 0) : 0; +} + +/* trie lookup function */ +MppTrieInfo *mpp_trie_get_info(MppTrie trie, const char *name); +MppTrieInfo *mpp_trie_get_info_first(MppTrie trie); +MppTrieInfo *mpp_trie_get_info_next(MppTrie trie, MppTrieInfo *info); +/* root base lookup function */ +MppTrieInfo *mpp_trie_get_info_from_root(void *root, const char *name); + +void mpp_trie_dump(MppTrie trie, const char *func); +#define mpp_trie_dump_f(trie) mpp_trie_dump(trie, __FUNCTION__) + +void mpp_trie_timing_test(MppTrie trie); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_TRIE_H */ diff --git a/mpp/base/mpp_2str.c b/mpp/base/mpp_2str.c new file mode 100644 index 000000000..08df849c6 --- /dev/null +++ b/mpp/base/mpp_2str.c @@ -0,0 +1,148 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mpp_2str.h" +#include "h264_syntax.h" +#include "h265_syntax.h" + +const char *strof_ctx_type(MppCtxType type) +{ + static const char *ctx_type_str[MPP_CTX_BUTT] = { + "dec", + "enc", + "isp", + }; + + return ctx_type_str[type]; +} + +const char *strof_coding_type(MppCodingType coding) +{ + static const char *coding_type_str0[] = { + "unused", + "autodetect", + "mpeg2", + "h263", + "mpeg4", + "wmv", + "rv", + "h264", + "mjpeg", + "vp8", + "vp9", + }; + static const char *coding_type_str1[] = { + "vc1", + "flv1", + "divx3", + "vp6", + "h265", + "avs+", + "avs", + "avs2", + "av1", + }; + + if (coding >= MPP_VIDEO_CodingUnused && coding <= MPP_VIDEO_CodingVP9) + return coding_type_str0[coding]; + else if (coding >= MPP_VIDEO_CodingVC1 && coding <= MPP_VIDEO_CodingAV1) + return coding_type_str1[coding - MPP_VIDEO_CodingVC1]; + + return NULL; +} + +const char *strof_rc_mode(MppEncRcMode rc_mode) +{ + static const char *rc_mode_str[] = { + "vbr", + "cbr", + "fixqp", + "avbr", + "smtrc" + }; + + if (rc_mode >= MPP_ENC_RC_MODE_VBR && rc_mode < MPP_ENC_RC_MODE_BUTT) + return rc_mode_str[rc_mode]; + + return NULL; +} +const char *strof_gop_mode(MppEncRcGopMode gop_mode) +{ + static const char *gop_mode_str[] = { + "normalp", + "smartp", + }; + + if (gop_mode >= MPP_ENC_RC_NORMAL_P && gop_mode < MPP_ENC_RC_GOP_MODE_BUTT) + return gop_mode_str[gop_mode]; + + return NULL; +} + +const char *strof_profle(MppCodingType coding, RK_U32 profile) +{ + static const char *h264_profile_str[] = { + "baseline", + "main", + "high", + "high10", + }; + static const char *h265_profile_str[] = { + "main", + "main10", + }; + static const char *jpeg_profile_str[] = { + "base", + }; + static const char *vp8_profile_str[] = { + "base", + }; + static const char *unknown_str[] = { + "unknown", + }; + + switch (coding) { + case MPP_VIDEO_CodingAVC : { + if (profile == H264_PROFILE_BASELINE) + return h264_profile_str[0]; + else if (profile == H264_PROFILE_MAIN) + return h264_profile_str[1]; + else if (profile == H264_PROFILE_HIGH) + return h264_profile_str[2]; + else if (profile == H264_PROFILE_HIGH10) + return h264_profile_str[3]; + else + return unknown_str[0]; + } break; + case MPP_VIDEO_CodingHEVC : { + if (profile < 2) + return h265_profile_str[0]; + else + return unknown_str[0]; + } break; + case MPP_VIDEO_CodingMJPEG : { + return jpeg_profile_str[0]; + } break; + case MPP_VIDEO_CodingVP8 : { + return vp8_profile_str[0]; + } break; + default : { + } break; + } + + return NULL; +} diff --git a/mpp/base/mpp_bitput.c b/mpp/base/mpp_bitput.c new file mode 100644 index 000000000..33a9539cb --- /dev/null +++ b/mpp/base/mpp_bitput.c @@ -0,0 +1,80 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "mpp_bitput.h" + +RK_S32 mpp_set_bitput_ctx(BitputCtx_t *bp, RK_U64 *data, RK_U32 len) +{ + memset(bp, 0, sizeof(BitputCtx_t)); + bp->index = 0; + bp->bitpos = 0; + bp->bvalue = 0; + bp->size = len; + bp->buflen = len; // align 64bit + bp->pbuf = data; + return 0; +} + +void mpp_put_bits(BitputCtx_t *bp, RK_U64 invalue, RK_S32 lbits) +{ + RK_U8 hbits = 0; + + if (!lbits) return; + + if (bp->index >= bp->buflen) return; + + hbits = 64 - lbits; + invalue = (invalue << hbits) >> hbits; + bp->bvalue |= invalue << bp->bitpos; // high bits value + if ((bp->bitpos + lbits) >= 64) { + bp->pbuf[bp->index] = bp->bvalue; + bp->bvalue = invalue >> (64 - bp->bitpos); // low bits value + bp->index++; + } + + if (bp->index >= bp->buflen) + return; + + bp->pbuf[bp->index] = bp->bvalue; + bp->bitpos = (bp->bitpos + lbits) & 63; + // mpp_log("bp->index = %d bp->bitpos = %d lbits = %d invalue 0x%x bp->hvalue 0x%x bp->lvalue 0x%x",bp->index,bp->bitpos,lbits, (RK_U32)invalue,(RK_U32)(bp->bvalue >> 32),(RK_U32)bp->bvalue); +} + +void mpp_put_align(BitputCtx_t *bp, RK_S32 align_bits, int flag) +{ + RK_U32 word_offset = 0, len = 0; + + word_offset = (align_bits >= 64) ? ((bp->index & (((align_bits & 0xfe0) >> 6) - 1)) << 6) : 0; + len = (align_bits - (word_offset + (bp->bitpos % align_bits))) % align_bits; + while (len > 0) { + if (len >= 8) { + if (flag == 0) + mpp_put_bits(bp, ((RK_U64)0 << (64 - 8)) >> (64 - 8), 8); + else + mpp_put_bits(bp, (0xffffffffffffffff << (64 - 8)) >> (64 - 8), 8); + len -= 8; + } else { + if (flag == 0) + mpp_put_bits(bp, ((RK_U64)0 << (64 - len)) >> (64 - len), len); + else + mpp_put_bits(bp, (0xffffffffffffffff << (64 - len)) >> (64 - len), len); + len -= len; + } + } +} + diff --git a/mpp/base/mpp_bitread.c b/mpp/base/mpp_bitread.c new file mode 100644 index 000000000..87e5ddb12 --- /dev/null +++ b/mpp/base/mpp_bitread.c @@ -0,0 +1,398 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include "rk_type.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" + +static MPP_RET update_curbyte_default(BitReadCtx_t *bitctx) +{ + if (bitctx->bytes_left_ < 1) + return MPP_ERR_READ_BIT; + + // Load a new byte and advance pointers. + bitctx->curr_byte_ = *bitctx->data_++ & 0xff; + --bitctx->bytes_left_; + bitctx->num_remaining_bits_in_curr_byte_ = 8; + bitctx->prev_two_bytes_ = (bitctx->prev_two_bytes_ << 8) | bitctx->curr_byte_; + + return MPP_OK; +} + +static MPP_RET update_curbyte_h264(BitReadCtx_t *bitctx) +{ + if (bitctx->bytes_left_ < 1) + return MPP_ERR_READ_BIT; + + // Emulation prevention three-byte detection. + // If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03). + if ((*bitctx->data_ == 0x03) + && ((bitctx->prev_two_bytes_ & 0xffff) == 0)) { + // Detected 0x000003, skip last byte. + ++bitctx->data_; + --bitctx->bytes_left_; + ++bitctx->emulation_prevention_bytes_; + bitctx->used_bits += 8; + // Need another full three bytes before we can detect the sequence again. + bitctx->prev_two_bytes_ = 0xffff; + if (bitctx->bytes_left_ < 1) + return MPP_ERR_READ_BIT; + } + // Load a new byte and advance pointers. + bitctx->curr_byte_ = *bitctx->data_++ & 0xff; + --bitctx->bytes_left_; + bitctx->num_remaining_bits_in_curr_byte_ = 8; + bitctx->prev_two_bytes_ = (bitctx->prev_two_bytes_ << 8) | bitctx->curr_byte_; + + return MPP_OK; +} + +static MPP_RET update_curbyte_h2645_sei(BitReadCtx_t *bitctx) +{ + if (bitctx->bytes_left_ < 1) + return MPP_ERR_READ_BIT; + + // Emulation prevention three-byte detection. + // If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03). + if ((*bitctx->data_ == 0x03) + && ((bitctx->prev_two_bytes_ & 0xffff) == 0)) { + // Detected 0x000003, skip last byte. + ++bitctx->data_; + // Need another full three bytes before we can detect the sequence again. + bitctx->prev_two_bytes_ = 0xffff; + } + // Load a new byte and advance pointers. + bitctx->curr_byte_ = *bitctx->data_++ & 0xff; + --bitctx->bytes_left_; + bitctx->num_remaining_bits_in_curr_byte_ = 8; + bitctx->prev_two_bytes_ = (bitctx->prev_two_bytes_ << 8) | bitctx->curr_byte_; + + return MPP_OK; +} + +static MPP_RET update_curbyte_avs2(BitReadCtx_t *bitctx) +{ + if (bitctx->bytes_left_ < 1) + return MPP_ERR_READ_BIT; + + if (*bitctx->data_ == 0x02 && ((bitctx->prev_two_bytes_ & 0xffff) == 0)) { + // Detected 0x000002, get 2 bits from next byte + bitctx->curr_byte_ = 0; + bitctx->num_remaining_bits_in_curr_byte_ = 6; + ++bitctx->data_; + } else { + bitctx->curr_byte_ = *bitctx->data_++ & 0xff; + bitctx->num_remaining_bits_in_curr_byte_ = 8; + } + // Load a new byte and advance pointers. + bitctx->prev_two_bytes_ = (bitctx->prev_two_bytes_ << 8) | bitctx->curr_byte_; + --bitctx->bytes_left_; + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* Read |num_bits| (1 to 31 inclusive) from the stream and return them +* in |out|, with first bit in the stream as MSB in |out| at position +* (|num_bits| - 1) +*********************************************************************** +*/ +MPP_RET mpp_read_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out) +{ + RK_S32 bits_left = num_bits; + *out = 0; + if (num_bits > 31) { + return MPP_ERR_READ_BIT; + } + while (bitctx->num_remaining_bits_in_curr_byte_ < bits_left) { + // Take all that's left in current byte, shift to make space for the rest. + *out |= (bitctx->curr_byte_ << (bits_left - bitctx->num_remaining_bits_in_curr_byte_)); + bits_left -= bitctx->num_remaining_bits_in_curr_byte_; + if (bitctx->update_curbyte(bitctx)) { + return MPP_ERR_READ_BIT; + } + } + *out |= (bitctx->curr_byte_ >> (bitctx->num_remaining_bits_in_curr_byte_ - bits_left)); + *out &= ((1 << num_bits) - 1); + bitctx->num_remaining_bits_in_curr_byte_ -= bits_left; + bitctx->used_bits += num_bits; + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* read more than 32 bits data +*********************************************************************** +*/ +MPP_RET mpp_read_longbits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_U32 *out) +{ + RK_S32 val = 0, val1 = 0; + + if (num_bits < 32) + return mpp_read_bits(bitctx, num_bits, (RK_S32 *)out); + + if (mpp_read_bits(bitctx, 16, &val)) { + return MPP_ERR_READ_BIT; + } + if (mpp_read_bits(bitctx, (num_bits - 16), &val1)) { + return MPP_ERR_READ_BIT; + } + + *out = (RK_U32)((val << 16) | val1); + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* skip bits (0 - 31) +*********************************************************************** +*/ +MPP_RET mpp_skip_bits(BitReadCtx_t *bitctx, RK_S32 num_bits) +{ + RK_S32 bits_left = num_bits; + + while (bitctx->num_remaining_bits_in_curr_byte_ < bits_left) { + // Take all that's left in current byte, shift to make space for the rest. + bits_left -= bitctx->num_remaining_bits_in_curr_byte_; + if (bitctx->update_curbyte(bitctx)) { + return MPP_ERR_READ_BIT; + } + } + bitctx->num_remaining_bits_in_curr_byte_ -= bits_left; + bitctx->used_bits += num_bits; + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* skip bits long (0 - 32) +*********************************************************************** +*/ +MPP_RET mpp_skip_longbits(BitReadCtx_t *bitctx, RK_S32 num_bits) +{ + if (num_bits < 32) + return mpp_skip_bits(bitctx, num_bits); + + if (mpp_skip_bits(bitctx, 16)) { + return MPP_ERR_READ_BIT; + } + if (mpp_skip_bits(bitctx, (num_bits - 16))) { + return MPP_ERR_READ_BIT; + } + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* show bits (0 - 31) +*********************************************************************** +*/ +MPP_RET mpp_show_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + BitReadCtx_t tmp_ctx = *bitctx; + + if (num_bits < 32) + ret = mpp_read_bits(&tmp_ctx, num_bits, out); + else + ret = mpp_read_longbits(&tmp_ctx, num_bits, (RK_U32 *)out); + + return ret; +} +/*! +*********************************************************************** +* \brief +* show long bits (0 - 32) +*********************************************************************** +*/ +MPP_RET mpp_show_longbits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_U32 *out) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + BitReadCtx_t tmp_ctx = *bitctx; + + ret = mpp_read_longbits(&tmp_ctx, num_bits, out); + + return ret; +} +/*! +*********************************************************************** +* \brief +* read unsigned data +*********************************************************************** +*/ +MPP_RET mpp_read_ue(BitReadCtx_t *bitctx, RK_U32 *val) +{ + RK_S32 num_bits = -1; + RK_S32 bit; + RK_S32 rest; + // Count the number of contiguous zero bits. + do { + if (mpp_read_bits(bitctx, 1, &bit)) { + return MPP_ERR_READ_BIT; + } + num_bits++; + } while (bit == 0); + if (num_bits > 31) { + return MPP_ERR_READ_BIT; + } + // Calculate exp-Golomb code value of size num_bits. + *val = (1 << num_bits) - 1; + if (num_bits > 0) { + if (mpp_read_bits(bitctx, num_bits, &rest)) { + return MPP_ERR_READ_BIT; + } + *val += rest; + } + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* read signed data +*********************************************************************** +*/ +MPP_RET mpp_read_se(BitReadCtx_t *bitctx, RK_S32 *val) +{ + RK_U32 ue; + + if (mpp_read_ue(bitctx, &ue)) { + return MPP_ERR_READ_BIT; + } + if (ue % 2 == 0) { // odd + *val = -(RK_S32)(ue >> 1); + } else { + *val = (RK_S32)((ue >> 1) + 1); + } + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* check whether has more rbsp data +*********************************************************************** +*/ +RK_U32 mpp_has_more_rbsp_data(BitReadCtx_t *bitctx) +{ + // remove tail byte which equal zero + while (bitctx->bytes_left_ && + bitctx->data_[bitctx->bytes_left_ - 1] == 0) + bitctx->bytes_left_--; + + // Make sure we have more bits, if we are at 0 bits in current byte + // and updating current byte fails, we don't have more data anyway. + if (bitctx->num_remaining_bits_in_curr_byte_ == 0 && bitctx->update_curbyte(bitctx)) + return 0; + // On last byte? + if (bitctx->bytes_left_) + return 1; + // Last byte, look for stop bit; + // We have more RBSP data if the last non-zero bit we find is not the + // first available bit. + if (bitctx->num_remaining_bits_in_curr_byte_) + return (bitctx->curr_byte_ & + ((1 << (bitctx->num_remaining_bits_in_curr_byte_ - 1)) - 1)) != 0; + else + return 0; +} +/*! +*********************************************************************** +* \brief +* initialize bit read context +*********************************************************************** +*/ +void mpp_set_bitread_ctx(BitReadCtx_t *bitctx, RK_U8 *data, RK_S32 size) +{ + memset(bitctx, 0, sizeof(BitReadCtx_t)); + bitctx->data_ = data; + bitctx->bytes_left_ = size; + bitctx->num_remaining_bits_in_curr_byte_ = 0; + // Initially set to 0xffff to accept all initial two-byte sequences. + bitctx->prev_two_bytes_ = 0xffff; + bitctx->emulation_prevention_bytes_ = 0; + // add + bitctx->buf = data; + bitctx->buf_len = size; + bitctx->used_bits = 0; + mpp_set_bitread_pseudo_code_type(bitctx, PSEUDO_CODE_NONE); +} + +void mpp_set_bitread_pseudo_code_type(BitReadCtx_t *bitctx, PseudoCodeType type) +{ + bitctx->prevention_type = type; + switch (type) { + case PSEUDO_CODE_H264_H265: + bitctx->update_curbyte = update_curbyte_h264; + break; + case PSEUDO_CODE_H264_H265_SEI: + bitctx->update_curbyte = update_curbyte_h2645_sei; + break; + case PSEUDO_CODE_AVS2: + bitctx->update_curbyte = update_curbyte_avs2; + break; + default: + bitctx->update_curbyte = update_curbyte_default; + break; + } +} + +/*! +*********************************************************************** +* \brief +* align data and get current point +*********************************************************************** +*/ +RK_U8 *mpp_align_get_bits(BitReadCtx_t *bitctx) +{ + int n = bitctx->num_remaining_bits_in_curr_byte_; + if (n) + mpp_skip_bits(bitctx, n); + return bitctx->data_; +} + +RK_S32 mpp_get_bits_left(BitReadCtx_t *bitctx) +{ + return bitctx->bytes_left_ * 8 + bitctx->num_remaining_bits_in_curr_byte_; +} + +RK_S32 mpp_get_bits_count(BitReadCtx_t *bitctx) +{ + return bitctx->used_bits; +} + +MPP_RET mpp_read_signbits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out) +{ + RK_S32 sign; + RK_S32 _out; + MPP_RET ret; + + ret = mpp_read_bits(bitctx, num_bits, &_out); + ret |= mpp_read_bits(bitctx, 1, &sign); + + if (!ret) + *out = (sign != 0) ? (-_out) : _out; + + return ret; +} diff --git a/mpp/base/mpp_bitwrite.c b/mpp/base/mpp_bitwrite.c new file mode 100644 index 000000000..2cbee89fb --- /dev/null +++ b/mpp/base/mpp_bitwrite.c @@ -0,0 +1,249 @@ +/* + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "mpp_bitwrite.h" + +MPP_RET mpp_writer_status(MppWriteCtx *ctx) +{ + if (ctx->byte_cnt > ctx->size) { + ctx->overflow = 1; + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_writer_reset(MppWriteCtx *ctx) +{ + ctx->stream = ctx->buffer; + ctx->byte_cnt = 0; + ctx->byte_buffer = 0; + ctx->buffered_bits = 0; + ctx->zero_bytes = 0; + ctx->overflow = 0; + ctx->emul_cnt = 0; + + return MPP_OK; +} + +MPP_RET mpp_writer_init(MppWriteCtx *ctx, void *p, RK_S32 size) +{ + MPP_RET ret; + + ctx->buffer = p; + ctx->stream = p; + ctx->size = size; + ctx->byte_cnt = 0; + ctx->overflow = 0; + ctx->byte_buffer = 0; + ctx->buffered_bits = 0; + ctx->zero_bytes = 0; + ctx->emul_cnt = 0; + + ret = mpp_writer_status(ctx); + if (ret) + mpp_err_f("failed to init with overflow config\n"); + + return ret; +} + +void mpp_writer_put_raw_bits(MppWriteCtx *ctx, RK_S32 val, RK_S32 len) +{ + RK_S32 bits; + RK_U32 byte_buffer = ctx->byte_buffer; + RK_U8*stream = ctx->stream; + + if (mpp_writer_status(ctx)) + return; + + mpp_assert(val < (1 << len)); + mpp_assert(len < 25); + + bits = len + ctx->buffered_bits; + val <<= (32 - bits); + byte_buffer = byte_buffer | val; + + while (bits > 7) { + *stream = (RK_U8)(byte_buffer >> 24); + + bits -= 8; + byte_buffer <<= 8; + stream++; + ctx->byte_cnt++; + } + + ctx->byte_buffer = byte_buffer; + ctx->buffered_bits = (RK_U8)bits; + ctx->stream = stream; + + return; +} + +void mpp_writer_flush(MppWriteCtx *ctx) +{ + RK_U32 byte_buffer = ctx->byte_buffer; + RK_U8*stream = ctx->stream; + + if (mpp_writer_status(ctx)) + return; + + if (ctx->buffered_bits) + *stream = (RK_U8)(byte_buffer >> 24); + + return; +} + +void mpp_writer_put_bits(MppWriteCtx * ctx, RK_S32 val, RK_S32 len) +{ + RK_S32 bits; + RK_U8 *stream = ctx->stream; + RK_U32 byte_buffer = ctx->byte_buffer; + + if (val) { + mpp_assert(val < (1 << len)); + mpp_assert(len < 25); + } + bits = len + ctx->buffered_bits; + + byte_buffer = byte_buffer | ((RK_U32) val << (32 - bits)); + + while (bits > 7) { + RK_S32 zeroBytes = ctx->zero_bytes; + RK_S32 byteCnt = ctx->byte_cnt; + + if (mpp_writer_status(ctx)) + return; + + *stream = (RK_U8) (byte_buffer >> 24); + + byteCnt++; + if ((zeroBytes == 2) && (*stream < 4)) { + *stream++ = 3; + *stream = (RK_U8) (byte_buffer >> 24); + byteCnt++; + zeroBytes = 0; + ctx->emul_cnt++; + } + + if (*stream == 0) + zeroBytes++; + else + zeroBytes = 0; + + bits -= 8; + byte_buffer <<= 8; + stream++; + ctx->zero_bytes = zeroBytes; + ctx->byte_cnt = byteCnt; + ctx->stream = stream; + } + + ctx->buffered_bits = (RK_U8) bits; + ctx->byte_buffer = byte_buffer; +} + +void mpp_writer_align_zero(MppWriteCtx *ctx) +{ + if (ctx->buffered_bits) + mpp_writer_put_raw_bits(ctx, 0, 8 - ctx->buffered_bits); +} + +void mpp_writer_align_one(MppWriteCtx *ctx) +{ + if (ctx->buffered_bits) { + RK_S32 len = 8 - ctx->buffered_bits; + + mpp_writer_put_raw_bits(ctx, (1 << len) - 1, len); + } +} + +void mpp_writer_trailing(MppWriteCtx *ctx) +{ + mpp_writer_put_bits(ctx, 1, 1); + if (ctx->buffered_bits) + mpp_writer_put_bits(ctx, 0, 8 - ctx->buffered_bits); +} + +void mpp_writer_put_ue(MppWriteCtx *ctx, RK_U32 val) +{ + RK_U32 num_bits = 0; + + val++; + while (val >> ++num_bits); + + if (num_bits > 12) { + RK_U32 tmp; + + tmp = num_bits - 1; + + if (tmp > 24) { + tmp -= 24; + mpp_writer_put_bits(ctx, 0, 24); + } + + mpp_writer_put_bits(ctx, 0, tmp); + + if (num_bits > 24) { + num_bits -= 24; + mpp_writer_put_bits(ctx, val >> num_bits, 24); + val = val >> num_bits; + } + + mpp_writer_put_bits(ctx, val, num_bits); + } else { + mpp_writer_put_bits(ctx, val, 2 * num_bits - 1); + } +} + +void mpp_writer_put_se(MppWriteCtx *ctx, RK_S32 val) +{ + RK_U32 tmp; + + if (val > 0) + tmp = (RK_U32)(2 * val - 1); + else + tmp = (RK_U32)(-2 * val); + + mpp_writer_put_ue(ctx, tmp); +} + +RK_S32 mpp_writer_bytes(MppWriteCtx *ctx) +{ + return ctx->byte_cnt + (ctx->buffered_bits > 0); +} + +RK_S32 mpp_writer_bits(MppWriteCtx *ctx) +{ + return ctx->byte_cnt * 8 + ctx->buffered_bits; +} + +RK_S32 mpp_exp_golomb_signed(RK_S32 val) +{ + RK_S32 tmp = 0; + + if (val > 0) + val = 2 * val; + else + val = -2 * val + 1; + + while (val >> ++tmp) + ; + + return tmp * 2 - 1; +} diff --git a/mpp/base/mpp_buf_slot.c b/mpp/base/mpp_buf_slot.c new file mode 100644 index 000000000..9453d69c1 --- /dev/null +++ b/mpp/base/mpp_buf_slot.c @@ -0,0 +1,1578 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_buf_slot" + +#include + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_list.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_frame_impl.h" +#include "mpp_buf_slot.h" +#include "mpp_compat_impl.h" +#include "rk_mpp_cfg.h" + +#define BUF_SLOT_DBG_FUNCTION (0x00000001) +#define BUF_SLOT_DBG_SETUP (0x00000002) +#define BUF_SLOT_DBG_INFO_CHANGE (0x00000004) +#define BUF_SLOT_DBG_OPS_RUNTIME (0x00000010) +#define BUF_SLOT_DBG_BUFFER (0x00000100) +#define BUF_SLOT_DBG_FRAME (0x00000200) +#define BUF_SLOT_DBG_BUF_UESD (0x00000400) +#define BUF_SLOT_DBG_INFO_SET (0x00000800) +#define BUF_SLOT_DBG_OPS_HISTORY (0x10000000) +#define BUF_SLOT_DBG_ALL (0x10000011) + +#define buf_slot_dbg(flag, fmt, ...) mpp_dbg(buf_slot_debug, flag, fmt, ## __VA_ARGS__) + +static RK_U32 buf_slot_debug = 0; +static RK_U32 buf_slot_idx = 0; +static RK_U32 use_legacy_align = 0; + +#define slot_assert(impl, cond) do { \ + if (!(cond)) { \ + dump_slots(impl); \ + mpp_err("Assertion %s failed at %s:%d\n", \ + MPP_STRINGS(cond), __FUNCTION__, __LINE__); \ + abort(); \ + } \ +} while (0) + +typedef struct MppBufSlotEntry_t MppBufSlotEntry; +typedef struct MppBufSlotsImpl_t MppBufSlotsImpl; + +#define SLOT_OPS_MAX_COUNT 1024 + +typedef enum MppBufSlotOps_e { + // status opertaion + SLOT_INIT, + SLOT_SET_ON_USE, + SLOT_CLR_ON_USE, + SLOT_SET_NOT_READY, + SLOT_CLR_NOT_READY, + SLOT_SET_CODEC_READY, + SLOT_CLR_CODEC_READY, + SLOT_SET_CODEC_USE, + SLOT_CLR_CODEC_USE, + SLOT_SET_HAL_INPUT, + SLOT_CLR_HAL_INPUT, + SLOT_SET_HAL_OUTPUT, + SLOT_CLR_HAL_OUTPUT, + SLOT_SET_QUEUE_USE, + SLOT_CLR_QUEUE_USE, + + // queue operation + SLOT_ENQUEUE, + SLOT_ENQUEUE_OUTPUT = SLOT_ENQUEUE, + SLOT_ENQUEUE_DISPLAY, + SLOT_ENQUEUE_DEINTER, + SLOT_ENQUEUE_CONVERT, + SLOT_DEQUEUE, + SLOT_DEQUEUE_OUTPUT = SLOT_DEQUEUE, + SLOT_DEQUEUE_DISPLAY, + SLOT_DEQUEUE_DEINTER, + SLOT_DEQUEUE_CONVERT, + + // value operation + SLOT_SET_EOS, + SLOT_CLR_EOS, + SLOT_SET_FRAME, + SLOT_CLR_FRAME, + SLOT_SET_BUFFER, + SLOT_CLR_BUFFER, +} MppBufSlotOps; + +static const char op_string[][16] = { + "init ", + "set on use ", + "clr on use ", + "set not ready ", + "set ready ", + "set codec ready", + "clr codec ready", + "set codec use ", + "clr codec use ", + "set hal input ", + "clr hal input ", + "set hal output ", + "clr hal output ", + "set queue use ", + "clr queue use ", + + "enqueue output ", + "enqueue display", + "enqueue deint ", + "enqueue convert", + "dequeue output ", + "dequeue display", + "dequeue deint ", + "dequeue convert", + + "set eos ", + "clr eos ", + "set frame ", + "clr frame ", + "set buffer ", + "clr buffer ", +}; + +static const MppBufSlotOps set_flag_op[SLOT_USAGE_BUTT] = { + SLOT_SET_CODEC_READY, + SLOT_SET_CODEC_USE, + SLOT_SET_HAL_INPUT, + SLOT_SET_HAL_OUTPUT, + SLOT_SET_QUEUE_USE, +}; + +static const MppBufSlotOps clr_flag_op[SLOT_USAGE_BUTT] = { + SLOT_CLR_CODEC_READY, + SLOT_CLR_CODEC_USE, + SLOT_CLR_HAL_INPUT, + SLOT_CLR_HAL_OUTPUT, + SLOT_CLR_QUEUE_USE, +}; + +static const MppBufSlotOps set_val_op[SLOT_PROP_BUTT] = { + SLOT_SET_EOS, + SLOT_SET_FRAME, + SLOT_SET_BUFFER, +}; + +typedef union SlotStatus_u { + RK_U32 val; + struct { + // status flags + RK_U32 on_used : 1; + RK_U32 not_ready : 1; // buffer slot is filled or not + RK_U32 codec_use : 1; // buffer slot is used by codec ( dpb reference ) + RK_U32 hal_output : 2; // buffer slot is set to hw output will ready when hw done + RK_U32 hal_use : 8; // buffer slot is used by hardware + RK_U32 queue_use : 5; // buffer slot is used in different queue + + // value flags + RK_U32 eos : 1; // buffer slot is last buffer slot from codec + RK_U32 has_buffer : 1; + RK_U32 has_frame : 1; + }; +} SlotStatus; + +typedef struct MppBufSlotLog_t { + RK_S32 index; + MppBufSlotOps ops; + SlotStatus status_in; + SlotStatus status_out; +} MppBufSlotLog; + +typedef struct MppBufSlotLogs_t { + pthread_mutex_t lock; + RK_U16 max_count; + RK_U16 log_count; + RK_U16 log_write; + RK_U16 log_read; + MppBufSlotLog *logs; +} MppBufSlotLogs; + +struct MppBufSlotEntry_t { + MppBufSlotsImpl *slots; + struct list_head list; + SlotStatus status; + RK_S32 index; + + RK_U32 eos; + MppFrame frame; + MppBuffer buffer; +}; + +struct MppBufSlotsImpl_t { + MppMutex lock; + RK_U32 slots_idx; + + // status tracing + RK_U32 decode_count; + RK_U32 display_count; + + MppCodingType coding_type; + + // if slot changed, all will be hold until all slot is unused + RK_U32 info_changed; + RK_S32 info_change_slot_idx; + RK_S32 new_count; + + // slot infomation for info change and eos + RK_U32 eos; + + // buffer parameter, default alignement is 16 + MppDecCfg dec_cfg; + MppSysCfg sys_cfg; + AlignFunc hal_hor_align; // default NULL + AlignFunc hal_ver_align; // default NULL + AlignFunc hal_len_align; // default NULL + AlignFunc hal_width_align; // default NULL + SlotHalFbcAdjCfg hal_fbc_adj_cfg; // hal fbc frame adjust config + size_t buf_size; + RK_S32 buf_count; + RK_S32 used_count; + RK_U32 align_chk_log_env; + RK_U32 align_chk_log_en; + // buffer size equal to (h_stride * v_stride) * numerator / denominator + // internal parameter + RK_U32 numerator; + RK_U32 denominator; + + // callback for free slot notify + MppCbCtx callback; + + // NOTE: use MppFrame to store the buffer/display infomation + // any buffer related infomation change comparing to previous frame will + // trigger a buffer info changed requirement + // any display related infomation change comparing to pevious frame will + // trigger a display info changed requirement + MppFrame info; + MppFrame info_set; + + // list for display + struct list_head queue[QUEUE_BUTT]; + + // list for log + MppBufSlotLogs *logs; + + MppBufSlotEntry *slots; +}; + +typedef struct MppBufSlotInfoSet_t { + RK_U32 h_stride_by_pixel; + RK_U32 h_stride_by_byte; + RK_U32 v_stride; + RK_U32 size_total; +} MppBufSlotInfoSet; + +static RK_U32 default_align_16(RK_U32 val) +{ + return MPP_ALIGN(val, 16); +} + +/* Based on drm_gem_framebuffer_helper.c drm_gem_afbc_min_size() */ +static RK_S32 get_afbc_min_size(RK_S32 width, RK_S32 height, RK_S32 bpp) +{ +#define AFBC_HEADER_SIZE 16 +#define AFBC_HDR_ALIGN 64 +#define AFBC_SUPERBLOCK_PIXELS 256 +#define AFBC_SUPERBLOCK_ALIGNMENT 128 + + RK_S32 n_blocks, hdr_alignment, size; + + /* AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 and !AFBC_FORMAT_MOD_TILED */ + width = MPP_ALIGN(width, 16); + height = MPP_ALIGN(height, 16); + hdr_alignment = AFBC_HDR_ALIGN; + + n_blocks = (width * height) / AFBC_SUPERBLOCK_PIXELS; + + size = MPP_ALIGN(n_blocks * AFBC_HEADER_SIZE, hdr_alignment); + size += n_blocks * MPP_ALIGN(bpp * AFBC_SUPERBLOCK_PIXELS / 8, + AFBC_SUPERBLOCK_ALIGNMENT); + return size; +} + +static void prepare_info_set_legacy(MppBufSlotsImpl *impl, MppFrame frame, + MppBufSlotInfoSet *info_set, + RK_U32 force_def_align) +{ + const RK_U32 width = mpp_frame_get_width(frame); + const RK_U32 height = mpp_frame_get_height(frame); + const MppFrameFormat fmt = mpp_frame_get_fmt(frame); + RK_U32 depth = ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP_10BIT || + (fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV422SP_10BIT || + (fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP_10BIT) ? 10 : 8; + RK_U32 codec_hor_stride = mpp_frame_get_hor_stride(frame); + RK_U32 codec_ver_stride = mpp_frame_get_ver_stride(frame); + RK_U32 coded_width = (impl->hal_width_align) ? + (impl->hal_width_align(width)) : width; + + RK_U32 hal_hor_stride = (codec_hor_stride != 0) ? + (impl->hal_hor_align(codec_hor_stride)) : + (impl->hal_hor_align(coded_width * depth >> 3)); + RK_U32 hal_ver_stride = (codec_ver_stride != 0) ? + (impl->hal_ver_align(codec_ver_stride)) : + (impl->hal_ver_align(height)); + RK_U32 hor_stride_pixel; + RK_S32 size; + + hal_hor_stride = (force_def_align && codec_hor_stride) ? codec_hor_stride : hal_hor_stride; + hal_ver_stride = (force_def_align && codec_ver_stride) ? codec_ver_stride : hal_ver_stride; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + /*fbc stride default 64 align*/ + if (*compat_ext_fbc_hdr_256_odd) + hal_hor_stride = (MPP_ALIGN(width, 256) | 256) * depth >> 3; + else + hal_hor_stride = MPP_ALIGN(width, 64) * depth >> 3; + } + + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP_10BIT: + case MPP_FMT_YUV422SP_10BIT: + case MPP_FMT_YUV444SP_10BIT: { + hor_stride_pixel = hal_hor_stride * 8 / 10; + } break; + case MPP_FMT_YUV422_YVYU: + case MPP_FMT_YUV422_YUYV: + case MPP_FMT_RGB565: + case MPP_FMT_BGR565: { + hor_stride_pixel = hal_hor_stride / 2; + } break; + case MPP_FMT_RGB888: + case MPP_FMT_BGR888: { + hor_stride_pixel = hal_hor_stride / 3; + } break; + default : { + hor_stride_pixel = hal_hor_stride; + } break; + } + + size = hal_hor_stride * hal_ver_stride; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + hor_stride_pixel = MPP_ALIGN(hor_stride_pixel, 64); + switch ((fmt & MPP_FRAME_FMT_MASK)) { + case MPP_FMT_YUV420SP_10BIT : { + size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 15); + } break; + case MPP_FMT_YUV422SP_10BIT : { + size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 20); + } break; + case MPP_FMT_YUV420SP : { + size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 12); + } break; + case MPP_FMT_YUV422SP : { + size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 16); + } break; + case MPP_FMT_YUV444SP : { + size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 24); + } break; + case MPP_FMT_YUV444SP_10BIT : { + size = get_afbc_min_size(hor_stride_pixel, hal_ver_stride, 30); + } break; + default : { + size = hal_hor_stride * hal_ver_stride * 3 / 2; + mpp_err("dec out fmt is no support"); + } break; + } + mpp_frame_set_fbc_size(frame, size); + } else { + size *= impl->numerator; + size /= impl->denominator; + size = impl->hal_len_align ? (RK_S32)impl->hal_len_align(hal_hor_stride * hal_ver_stride) : size; + } + + info_set->h_stride_by_byte = hal_hor_stride; + info_set->v_stride = hal_ver_stride; + info_set->h_stride_by_pixel = hor_stride_pixel; + info_set->size_total = size; +} + +static void prepare_info_set_by_sys_cfg(MppBufSlotsImpl *impl, MppFrame frame, + MppBufSlotInfoSet *info_set) +{ + const RK_U32 width = mpp_frame_get_width(frame); + const RK_U32 height = mpp_frame_get_height(frame); + const RK_U32 codec_hor_stride = mpp_frame_get_hor_stride(frame); + const RK_U32 codec_ver_stride = mpp_frame_get_ver_stride(frame); + const MppFrameFormat fmt = mpp_frame_get_fmt(frame); + + /* set correct parameter */ + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:enable", 1); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:type", impl->coding_type); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_codec", fmt & MPP_FRAME_FMT_MASK); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_fbc", fmt & MPP_FRAME_FBC_MASK); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:fmt_hdr", fmt & MPP_FRAME_HDR_MASK); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:width", width); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:height", height); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_byte", codec_hor_stride); + mpp_sys_cfg_set_u32(impl->sys_cfg, "dec_buf_chk:v_stride", codec_ver_stride); + + /* get result */ + mpp_sys_cfg_ioctl(impl->sys_cfg); + + mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_byte", &info_set->h_stride_by_byte); + mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:h_stride_by_pixel", &info_set->h_stride_by_pixel); + mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:v_stride", &info_set->v_stride); + mpp_sys_cfg_get_u32(impl->sys_cfg, "dec_buf_chk:size_total", &info_set->size_total); + + return; +} + +static void generate_info_set(MppBufSlotsImpl *impl, MppFrame frame, RK_U32 force_def_align) +{ + const RK_U32 width = mpp_frame_get_width(frame); + const RK_U32 height = mpp_frame_get_height(frame); + const MppFrameFormat fmt = mpp_frame_get_fmt(frame); + MppBufSlotInfoSet legacy_info_set; + MppBufSlotInfoSet sys_cfg_info_set; + MppBufSlotInfoSet *info_set_ptr = NULL; + MppFrameImpl *info_set_impl = NULL; + MppFrameImpl *frame_impl = NULL; + + prepare_info_set_legacy(impl, frame, &legacy_info_set, force_def_align); + prepare_info_set_by_sys_cfg(impl, frame, &sys_cfg_info_set); + + mpp_frame_set_width(impl->info_set, width); + mpp_frame_set_height(impl->info_set, height); + mpp_frame_set_fmt(impl->info_set, fmt); + info_set_ptr = (use_legacy_align != 0) ? &legacy_info_set : &sys_cfg_info_set; + mpp_frame_set_hor_stride(impl->info_set, info_set_ptr->h_stride_by_byte); + mpp_frame_set_ver_stride(impl->info_set, info_set_ptr->v_stride); + mpp_frame_set_hor_stride_pixel(impl->info_set, info_set_ptr->h_stride_by_pixel); + mpp_frame_set_buf_size(impl->info_set, info_set_ptr->size_total); + mpp_frame_set_buf_size(frame, info_set_ptr->size_total); + mpp_frame_set_hor_stride(frame, info_set_ptr->h_stride_by_byte); + mpp_frame_set_ver_stride(frame, info_set_ptr->v_stride); + mpp_frame_set_hor_stride_pixel(frame, info_set_ptr->h_stride_by_pixel); + impl->buf_size = info_set_ptr->size_total; + + if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_MIXED) { + /* + * The decode hw only support 1/2 scaling in width and height, + * downscale output image only support raster mode with 8bit depth. + */ + RK_U32 down_scale_ver = MPP_ALIGN(mpp_frame_get_height(frame) >> 1, 16); + RK_U32 down_scale_hor = MPP_ALIGN(mpp_frame_get_width(frame) >> 1, 16); + RK_U32 downscale_buf_size; + RK_U32 down_scale_y_virstride = down_scale_ver * down_scale_hor; + + switch ((fmt & MPP_FRAME_FMT_MASK)) { + case MPP_FMT_YUV400 : { + downscale_buf_size = down_scale_y_virstride; + } break; + case MPP_FMT_YUV420SP_10BIT : + case MPP_FMT_YUV420SP : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + case MPP_FMT_YUV422SP_10BIT : + case MPP_FMT_YUV422SP : { + downscale_buf_size = down_scale_y_virstride * 2; + } break; + case MPP_FMT_YUV444SP_10BIT : + case MPP_FMT_YUV444SP : { + downscale_buf_size = down_scale_y_virstride * 3; + } break; + default : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + } + downscale_buf_size = MPP_ALIGN(downscale_buf_size, 16); + impl->buf_size += downscale_buf_size; + mpp_frame_set_buf_size(impl->info_set, impl->buf_size); + mpp_frame_set_buf_size(frame, impl->buf_size); + } + info_set_impl = (MppFrameImpl *)impl->info_set; + frame_impl = (MppFrameImpl *)frame; + info_set_impl->color_range = frame_impl->color_range; + info_set_impl->color_primaries = frame_impl->color_primaries; + info_set_impl->color_trc = frame_impl->color_trc; + info_set_impl->colorspace = frame_impl->colorspace; + info_set_impl->chroma_location = frame_impl->chroma_location; + + if (impl->align_chk_log_en) { + impl->align_chk_log_en = 0; + if (legacy_info_set.h_stride_by_pixel != sys_cfg_info_set.h_stride_by_pixel) + mpp_logi("mismatch h_stride_by_pixel %d - %d\n", + legacy_info_set.h_stride_by_pixel, + sys_cfg_info_set.h_stride_by_pixel); + if (legacy_info_set.h_stride_by_byte != sys_cfg_info_set.h_stride_by_byte) + mpp_logi("mismatch h_stride_by_byte %d - %d\n", + legacy_info_set.h_stride_by_byte, + sys_cfg_info_set.h_stride_by_byte); + if (legacy_info_set.v_stride != sys_cfg_info_set.v_stride) + mpp_logi("mismatch v_stride %d - %d\n", + legacy_info_set.v_stride, + sys_cfg_info_set.v_stride); + if (legacy_info_set.size_total != sys_cfg_info_set.size_total) + mpp_logi("mismatch size_total %d - %d\n", + legacy_info_set.size_total, + sys_cfg_info_set.size_total); + } +} + +#define dump_slots(...) _dump_slots(__FUNCTION__, ## __VA_ARGS__) + +static void buf_slot_logs_reset(MppBufSlotLogs *logs) +{ + logs->log_count = 0; + logs->log_write = 0; + logs->log_read = 0; +} + +static MppBufSlotLogs *buf_slot_logs_init(RK_U32 max_count) +{ + MppBufSlotLogs *logs = NULL; + + if (!max_count) + return NULL; + + logs = mpp_malloc_size(MppBufSlotLogs, sizeof(MppBufSlotLogs) + + max_count * sizeof(MppBufSlotLog)); + if (!logs) { + mpp_err_f("failed to create %d buf slot logs\n", max_count); + return NULL; + } + + logs->max_count = max_count; + logs->logs = (MppBufSlotLog *)(logs + 1); + buf_slot_logs_reset(logs); + + return logs; +} + +static void buf_slot_logs_deinit(MppBufSlotLogs *logs) +{ + MPP_FREE(logs); +} + +static void buf_slot_logs_write(MppBufSlotLogs *logs, RK_S32 index, MppBufSlotOps op, + SlotStatus before, SlotStatus after) +{ + MppBufSlotLog *log = NULL; + + log = &logs->logs[logs->log_write]; + log->index = index; + log->ops = op; + log->status_in = before; + log->status_out = after; + + logs->log_write++; + if (logs->log_write >= logs->max_count) + logs->log_write = 0; + + if (logs->log_count < logs->max_count) + logs->log_count++; + else { + logs->log_read++; + if (logs->log_read >= logs->max_count) + logs->log_read = 0; + } +} + +static void buf_slot_logs_dump(MppBufSlotLogs *logs) +{ + while (logs->log_count) { + MppBufSlotLog *log = &logs->logs[logs->log_read]; + + mpp_log("index %2d op: %s status in %08x out %08x", + log->index, op_string[log->ops], log->status_in.val, log->status_out.val); + + logs->log_read++; + if (logs->log_read >= logs->max_count) + logs->log_read = 0; + logs->log_count--; + } + mpp_assert(logs->log_read == logs->log_write); +} + +static void _dump_slots(const char *caller, MppBufSlotsImpl *impl) +{ + MppBufSlotEntry *slot = impl->slots; + RK_S32 i; + + mpp_log("\ncaller %s is dumping slots\n", caller, impl->slots_idx); + mpp_log("slots %d %p buffer count %d buffer size %d\n", impl->slots_idx, + impl, impl->buf_count, impl->buf_size); + mpp_log("decode count %d\n", impl->decode_count); + mpp_log("display count %d\n", impl->display_count); + + for (i = 0; i < impl->buf_count; i++, slot++) { + SlotStatus status = slot->status; + mpp_log("slot %2d used %d refer %d decoding %d display %d status %08x\n", + i, status.on_used, status.codec_use, status.hal_use, status.queue_use, status.val); + } + + mpp_log("\nslot operation history:\n\n"); + + if (impl->logs) + buf_slot_logs_dump(impl->logs); + + mpp_assert(0); + + return; +} + +static void slot_ops_with_log(MppBufSlotsImpl *impl, MppBufSlotEntry *slot, MppBufSlotOps op, void *arg) +{ + RK_U32 error = 0; + RK_S32 index = slot->index; + SlotStatus status = slot->status; + SlotStatus before = status; + switch (op) { + case SLOT_INIT : { + status.val = 0; + } break; + case SLOT_SET_ON_USE : { + status.on_used = 1; + } break; + case SLOT_CLR_ON_USE : { + status.on_used = 0; + } break; + case SLOT_SET_NOT_READY : { + status.not_ready = 1; + } break; + case SLOT_CLR_NOT_READY : { + status.not_ready = 0; + } break; + case SLOT_SET_CODEC_READY : { + status.not_ready = 0; + } break; + case SLOT_CLR_CODEC_READY : { + status.not_ready = 1; + } break; + case SLOT_SET_CODEC_USE : { + status.codec_use = 1; + } break; + case SLOT_CLR_CODEC_USE : { + status.codec_use = 0; + } break; + case SLOT_SET_HAL_INPUT : { + status.hal_use++; + } break; + case SLOT_CLR_HAL_INPUT : { + if (status.hal_use) + status.hal_use--; + else { + mpp_err("can not clr hal_input on slot %d\n", slot->index); + error = 1; + } + } break; + case SLOT_SET_HAL_OUTPUT : { + status.hal_output++; + status.not_ready = 1; + } break; + case SLOT_CLR_HAL_OUTPUT : { + if (status.hal_output) + status.hal_output--; + else + mpp_err("can not clr hal_output on slot %d\n", slot->index); + + // NOTE: set output index ready here + if (!status.hal_output) + status.not_ready = 0; + } break; + case SLOT_SET_QUEUE_USE : + case SLOT_ENQUEUE_OUTPUT : + case SLOT_ENQUEUE_DISPLAY : + case SLOT_ENQUEUE_DEINTER : + case SLOT_ENQUEUE_CONVERT : { + status.queue_use++; + } break; + case SLOT_CLR_QUEUE_USE : + case SLOT_DEQUEUE_OUTPUT : + case SLOT_DEQUEUE_DISPLAY : + case SLOT_DEQUEUE_DEINTER : + case SLOT_DEQUEUE_CONVERT : { + if (status.queue_use) + status.queue_use--; + else { + mpp_err("can not clr queue_use on slot %d\n", slot->index); + error = 1; + } + } break; + case SLOT_SET_EOS : { + status.eos = 1; + } break; + case SLOT_CLR_EOS : { + status.eos = 0; + slot->eos = 0; + } break; + case SLOT_SET_FRAME : { + status.has_frame = (arg) ? (1) : (0); + } break; + case SLOT_CLR_FRAME : { + status.has_frame = 0; + } break; + case SLOT_SET_BUFFER : { + status.has_buffer = (arg) ? (1) : (0); + } break; + case SLOT_CLR_BUFFER : { + status.has_buffer = 0; + } break; + default : { + mpp_err("found invalid operation code %d\n", op); + error = 1; + } break; + } + slot->status = status; + buf_slot_dbg(BUF_SLOT_DBG_OPS_RUNTIME, "slot %3d index %2d op: %s arg %010p status in %08x out %08x", + impl->slots_idx, index, op_string[op], arg, before.val, status.val); + if (impl->logs) + buf_slot_logs_write(impl->logs, index, op, before, status); + if (error) + dump_slots(impl); +} + +static void init_slot_entry(MppBufSlotsImpl *impl, RK_S32 pos, RK_S32 count) +{ + MppBufSlotEntry *slot = impl->slots; + RK_S32 i; + + for (i = 0; i < count; i++, slot++) { + slot->slots = impl; + INIT_LIST_HEAD(&slot->list); + slot->index = pos + i; + slot->frame = NULL; + slot_ops_with_log(impl, slot, SLOT_INIT, NULL); + } +} + +/* + * only called on unref / displayed / decoded + * + * NOTE: MppFrame will be destroyed outside mpp + * but MppBuffer must dec_ref here + */ +static RK_S32 check_entry_unused(MppBufSlotsImpl *impl, MppBufSlotEntry *entry) +{ + SlotStatus status = entry->status; + + if (status.on_used && + !status.not_ready && + !status.codec_use && + !status.hal_output && + !status.hal_use && + !status.queue_use) { + if (entry->frame) { + slot_ops_with_log(impl, entry, SLOT_CLR_FRAME, entry->frame); + mpp_frame_deinit(&entry->frame); + } + if (entry->buffer) { + mpp_buffer_put(entry->buffer); + slot_ops_with_log(impl, entry, SLOT_CLR_BUFFER, entry->buffer); + entry->buffer = NULL; + } + + slot_ops_with_log(impl, entry, SLOT_CLR_ON_USE, NULL); + impl->used_count--; + return 1; + } + + return 0; +} + +static void clear_slots_impl(MppBufSlotsImpl *impl) +{ + MppBufSlotEntry *slot = (MppBufSlotEntry *)impl->slots; + RK_S32 i; + + if (impl->sys_cfg) + mpp_sys_cfg_put(impl->sys_cfg); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(impl->queue); i++) { + if (!list_empty(&impl->queue[i])) + dump_slots(impl); + + mpp_assert(list_empty(&impl->queue[i])); + } + + for (i = 0; i < impl->buf_count; i++, slot++) { + mpp_assert(!slot->status.on_used); + if (slot->status.on_used) { + dump_slots(impl); + mpp_buf_slot_reset(impl, i); + } + } + + impl->used_count = 0; + + if (impl->info) + mpp_frame_deinit(&impl->info); + + if (impl->info_set) + mpp_frame_deinit(&impl->info_set); + + if (impl->logs) { + buf_slot_logs_deinit(impl->logs); + impl->logs = NULL; + } + + mpp_mutex_destroy(&impl->lock); + + mpp_free(impl->slots); + mpp_free(impl); +} + +MPP_RET mpp_buf_slot_init(MppBufSlots *slots) +{ + MppBufSlotsImpl *impl; + RK_U32 i; + + if (!slots) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + impl = mpp_calloc(MppBufSlotsImpl, 1); + if (!impl) { + *slots = NULL; + return MPP_NOK; + } + + mpp_env_get_u32("buf_slot_debug", &buf_slot_debug, + BUF_SLOT_DBG_OPS_HISTORY | BUF_SLOT_DBG_INFO_SET); + mpp_env_get_u32("use_legacy_align", &use_legacy_align, 0); + + do { + if (mpp_sys_cfg_get(&impl->sys_cfg)) { + mpp_err_f("mpp_sys_cfg_get failed\n"); + break; + } + + mpp_mutex_init(&impl->lock); + + for (i = 0; i < MPP_ARRAY_ELEMS(impl->queue); i++) { + INIT_LIST_HEAD(&impl->queue[i]); + } + + if (buf_slot_debug & BUF_SLOT_DBG_OPS_HISTORY) { + impl->logs = buf_slot_logs_init(SLOT_OPS_MAX_COUNT); + if (!impl->logs) + break; + } + + if (mpp_frame_init(&impl->info)) + break; + + if (mpp_frame_init(&impl->info_set)) + break; + + // slots information default setup + impl->hal_hor_align = default_align_16; + impl->hal_ver_align = default_align_16; + impl->hal_len_align = NULL; + impl->numerator = 9; + impl->denominator = 5; + impl->slots_idx = buf_slot_idx++; + impl->info_change_slot_idx = -1; + impl->align_chk_log_env = ((buf_slot_debug & BUF_SLOT_DBG_INFO_SET) != 0) ? 1 : 0; + impl->align_chk_log_en = impl->align_chk_log_env; + + *slots = impl; + return MPP_OK; + } while (0); + + clear_slots_impl(impl); + + *slots = NULL; + return MPP_NOK; +} + +MPP_RET mpp_buf_slot_deinit(MppBufSlots slots) +{ + if (!slots) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + clear_slots_impl((MppBufSlotsImpl *)slots); + return MPP_OK; +} + +MPP_RET mpp_buf_slot_setup(MppBufSlots slots, RK_S32 count) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p setup: count %d\n", impl, count); + + mpp_mutex_lock(&impl->lock); + + if (!impl->slots) { + // first slot setup + impl->buf_count = impl->new_count = count; + impl->slots = mpp_calloc(MppBufSlotEntry, count); + init_slot_entry(impl, 0, count); + impl->used_count = 0; + } else { + // record the slot count for info changed ready config + if (count > impl->buf_count) { + impl->slots = mpp_realloc(impl->slots, MppBufSlotEntry, count); + mpp_assert(impl->slots); + init_slot_entry(impl, impl->buf_count, (count - impl->buf_count)); + } + impl->new_count = count; + } + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +RK_U32 mpp_buf_slot_is_changed(MppBufSlots slots) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + RK_U32 info_changed = 0; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return 0; + } + + mpp_mutex_lock(&impl->lock); + info_changed = impl->info_changed; + mpp_mutex_unlock(&impl->lock); + + return info_changed; +} + +MPP_RET mpp_buf_slot_ready(MppBufSlots slots) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p is ready now\n", impl); + + mpp_mutex_lock(&impl->lock); + + slot_assert(impl, impl->slots); + if (!impl->info_changed) + mpp_log("found info change ready set without internal info change\n"); + + // ready mean the info_set will be copy to info as the new configuration + if (impl->buf_count != impl->new_count) { + impl->slots = mpp_realloc(impl->slots, MppBufSlotEntry, impl->new_count); + mpp_assert(impl->slots); + init_slot_entry(impl, 0, impl->new_count); + } + impl->buf_count = impl->new_count; + + mpp_frame_copy(impl->info, impl->info_set); + + if (impl->logs) + buf_slot_logs_reset(impl->logs); + + impl->info_changed = 0; + impl->info_change_slot_idx = -1; + + if (impl->dec_cfg) { + MppDecCfg cfg = impl->dec_cfg; + MppFrameImpl *frm = (MppFrameImpl *)impl->info; + + mpp_dec_cfg_set_s32(cfg, "status:width", frm->width); + mpp_dec_cfg_set_s32(cfg, "status:height", frm->height); + mpp_dec_cfg_set_s32(cfg, "status:hor_stride", frm->hor_stride); + mpp_dec_cfg_set_s32(cfg, "status:ver_stride", frm->ver_stride); + mpp_dec_cfg_set_s32(cfg, "status:buf_size", frm->buf_size); + } + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +size_t mpp_buf_slot_get_size(MppBufSlots slots) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + size_t size = 0; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return 0; + } + + mpp_mutex_lock(&impl->lock); + size = impl->buf_size; + mpp_mutex_unlock(&impl->lock); + + return size; +} + +RK_S32 mpp_buf_slot_get_count(MppBufSlots slots) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + size_t count = 0; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return -1; + } + + mpp_mutex_lock(&impl->lock); + count = impl->buf_count; + mpp_mutex_unlock(&impl->lock); + + return count; +} + +MPP_RET mpp_buf_slot_set_callback(MppBufSlots slots, MppCbCtx *cb_ctx) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_NOK; + } + + mpp_mutex_lock(&impl->lock); + impl->callback = *cb_ctx; + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_set_dec_cfg(MppBufSlots slots, MppDecCfg cfg) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_NOK; + } + + mpp_mutex_lock(&impl->lock); + impl->dec_cfg = cfg; + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_get_unused(MppBufSlots slots, RK_S32 *index) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + MppBufSlotEntry *slot; + RK_S32 i; + + if (!impl || !index) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + slot = impl->slots; + + mpp_mutex_lock(&impl->lock); + + for (i = 0; i < impl->buf_count; i++, slot++) { + if (!slot->status.on_used) { + *index = i; + slot_ops_with_log(impl, slot, SLOT_SET_ON_USE, NULL); + slot_ops_with_log(impl, slot, SLOT_SET_NOT_READY, NULL); + impl->used_count++; + mpp_mutex_unlock(&impl->lock); + return MPP_OK; + } + } + + *index = -1; + mpp_err_f("failed to get a unused slot\n"); + dump_slots(impl); + slot_assert(impl, 0); + + mpp_mutex_unlock(&impl->lock); + + return MPP_NOK; +} + +MPP_RET mpp_buf_slot_set_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_lock(&impl->lock); + + slot_assert(impl, (index >= 0) && (index < impl->buf_count)); + slot_ops_with_log(impl, &impl->slots[index], set_flag_op[type], NULL); + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_clr_flag(MppBufSlots slots, RK_S32 index, SlotUsageType type) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + MppBufSlotEntry *slot; + RK_S32 unused = 0; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_lock(&impl->lock); + + slot_assert(impl, (index >= 0) && (index < impl->buf_count)); + slot = &impl->slots[index]; + slot_ops_with_log(impl, slot, clr_flag_op[type], NULL); + + if (type == SLOT_HAL_OUTPUT) + impl->decode_count++; + + unused = check_entry_unused(impl, slot); + + mpp_mutex_unlock(&impl->lock); + + if (unused) + mpp_callback(&impl->callback, impl); + return MPP_OK; +} + +MPP_RET mpp_buf_slot_enqueue(MppBufSlots slots, RK_S32 index, SlotQueueType type) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + MppBufSlotEntry *slot; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_lock(&impl->lock); + + slot_assert(impl, (index >= 0) && (index < impl->buf_count)); + slot = &impl->slots[index]; + slot_ops_with_log(impl, slot, (MppBufSlotOps)(SLOT_ENQUEUE + type), NULL); + + // add slot to display list + list_del_init(&slot->list); + list_add_tail(&slot->list, &impl->queue[type]); + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_dequeue(MppBufSlots slots, RK_S32 *index, SlotQueueType type) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + MppBufSlotEntry *slot; + + if (!impl || !index) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_lock(&impl->lock); + + if (list_empty(&impl->queue[type])) { + mpp_mutex_unlock(&impl->lock); + return MPP_NOK; + } + + slot = list_entry(impl->queue[type].next, MppBufSlotEntry, list); + if (slot->status.not_ready) { + mpp_mutex_unlock(&impl->lock); + return MPP_NOK; + } + + // make sure that this slot is just the next display slot + list_del_init(&slot->list); + slot_assert(impl, slot->index < impl->buf_count); + slot_ops_with_log(impl, slot, (MppBufSlotOps)(SLOT_DEQUEUE + type), NULL); + impl->display_count++; + *index = slot->index; + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_set_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + MppBufSlotEntry *slot; + + if (!impl || !val || type >= SLOT_PROP_BUTT) { + mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val); + return MPP_ERR_UNKNOW; + } + + mpp_mutex_lock(&impl->lock); + + slot_assert(impl, (index >= 0) && (index < impl->buf_count)); + slot = &impl->slots[index]; + slot_ops_with_log(impl, slot, set_val_op[type], val); + + switch (type) { + case SLOT_EOS: { + RK_U32 eos = *(RK_U32*)val; + + slot->eos = eos; + if (slot->frame) + mpp_frame_set_eos(slot->frame, eos); + } break; + case SLOT_FRAME: { + MppFrame frame = val; + MppFrameImpl *src; + MppFrameImpl *dst; + + slot_assert(impl, slot->status.not_ready); + /* + * we need to detect infomation change here + * there are two types of info change: + * 1. buffer size change + * this case need to reset buffer group and commit buffer with new size + * 2. display info change + * if only width/height/fmt is change and buffer do not need to be reset + * only display info change is need + */ + generate_info_set(impl, frame, 0); + + if (!slot->frame) + mpp_frame_init(&slot->frame); + + src = (MppFrameImpl *)frame; + dst = (MppFrameImpl *)slot->frame; + mpp_frame_copy(dst, src); + // NOTE: stride from codec need to be change to hal stride + // hor_stride and ver_stride can not be zero + // they are the stride required by codec + // then hal will modify it according to hardware requirement + mpp_assert(src->hor_stride); + mpp_assert(src->ver_stride); + dst->hor_stride = src->hor_stride; + dst->ver_stride = src->ver_stride; + dst->eos = slot->eos; + + if (mpp_frame_info_cmp(impl->info, impl->info_set)) { + MppFrameImpl *old = (MppFrameImpl *)impl->info; + + impl->info_changed = 1; + impl->info_change_slot_idx = index; + + if (impl->coding_type != MPP_VIDEO_CodingMJPEG) + impl->align_chk_log_en = impl->align_chk_log_env; + + if (old->width || old->height) { + sys_dbg_info("info change found\n"); + sys_dbg_info("old width %4d height %4d stride hor %4d ver %4d fmt %4d\n", + old->width, old->height, old->hor_stride, + old->ver_stride, old->fmt); + } + sys_dbg_info("new width %4d height %4d stride hor %4d ver %4d fmt %4d\n", + dst->width, dst->height, dst->hor_stride, dst->ver_stride, + dst->fmt); + // info change found here + } + } break; + case SLOT_BUFFER: { + MppBuffer buffer = val; + + if (slot->buffer) { + // NOTE: reset buffer only on stream buffer slot + slot_assert(impl, !slot->frame); + mpp_buffer_put(slot->buffer); + } + mpp_buffer_inc_ref(buffer); + slot->buffer = buffer; + + if (slot->frame) + mpp_frame_set_buffer(slot->frame, buffer); + } break; + default : { + } break; + } + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_get_prop(MppBufSlots slots, RK_S32 index, SlotPropType type, void *val) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + MppBufSlotEntry *slot; + + if (!impl || !val || type >= SLOT_PROP_BUTT) { + mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val); + return MPP_ERR_UNKNOW; + } + + mpp_mutex_lock(&impl->lock); + + slot_assert(impl, (index >= 0) && (index < impl->buf_count)); + slot = &impl->slots[index]; + + switch (type) { + case SLOT_EOS: { + *(RK_U32*)val = slot->eos; + } break; + case SLOT_FRAME: { + MppFrame *frame = (MppFrame *)val; + //*frame = (slot->status.has_frame) ? (slot->frame) : (NULL); + + mpp_assert(slot->status.has_frame); + if (slot->status.has_frame) { + if (!*frame ) + mpp_frame_init(frame); + if (*frame) + mpp_frame_copy(*frame, slot->frame); + } else + *frame = NULL; + } break; + case SLOT_FRAME_PTR: { + MppFrame *frame = (MppFrame *)val; + + mpp_assert(slot->status.has_frame); + *frame = (slot->status.has_frame != 0) ? (slot->frame) : (NULL); + } break; + case SLOT_BUFFER: { + MppBuffer *buffer = (MppBuffer *)val; + + *buffer = (slot->status.has_buffer != 0) ? (slot->buffer) : (NULL); + } break; + default : { + } break; + } + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_reset(MppBufSlots slots, RK_S32 index) +{ + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + MppBufSlotEntry *slot; + + if (!impl || index < 0) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p reset index %d\n", slots, index); + + mpp_mutex_lock(&impl->lock); + + slot_assert(impl, (index >= 0) && (index < impl->buf_count)); + slot = &impl->slots[index]; + + // make sure that this slot is just the next display slot + list_del_init(&slot->list); + slot_ops_with_log(impl, slot, SLOT_CLR_QUEUE_USE, NULL); + slot_ops_with_log(impl, slot, SLOT_DEQUEUE, NULL); + slot_ops_with_log(impl, slot, SLOT_CLR_ON_USE, NULL); + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_buf_slot_default_info(MppBufSlots slots, RK_S32 index, void *val) +{ + if (!slots || index < 0) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + mpp_mutex_lock(&impl->lock); + slot_assert(impl, (index >= 0) && (index < impl->buf_count)); + MppBufSlotEntry *slot = &impl->slots[index]; + + slot_assert(impl, slot->status.not_ready); + slot_assert(impl, !slot->frame); + slot_assert(impl, impl->info_set); + + if (!slot->frame) { + mpp_frame_init(&slot->frame); + mpp_frame_copy(slot->frame, impl->info_set); + } + + MppFrame *frame = (MppFrame *)val; + *frame = slot->frame; + + slot_ops_with_log(impl, slot, SLOT_CLR_NOT_READY, NULL); + slot_ops_with_log(impl, slot, SLOT_SET_FRAME, slot->frame); + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +RK_U32 mpp_slots_is_empty(MppBufSlots slots, SlotQueueType type) +{ + RK_U32 is_empty = 0; + if (!slots) { + mpp_err_f("found NULL input\n"); + return 0; + } + + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + mpp_mutex_lock(&impl->lock); + is_empty = (list_empty(&impl->queue[type]) != 0) ? 1 : 0; + mpp_mutex_unlock(&impl->lock); + + return is_empty; +} + +RK_S32 mpp_slots_get_used_count(MppBufSlots slots) +{ + RK_S32 used_count = 0; + if (!slots) { + mpp_err_f("found NULL input\n"); + return 0; + } + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + mpp_mutex_lock(&impl->lock); + used_count = impl->used_count; + mpp_mutex_unlock(&impl->lock); + + return used_count; +} + +RK_S32 mpp_slots_get_unused_count(MppBufSlots slots) +{ + RK_S32 unused_count = 0; + if (!slots) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + mpp_mutex_lock(&impl->lock); + slot_assert(impl, (impl->used_count >= 0) && (impl->used_count <= impl->buf_count)); + unused_count = impl->buf_count - impl->used_count; + mpp_mutex_unlock(&impl->lock); + + return unused_count; +} + +MPP_RET mpp_slots_set_prop(MppBufSlots slots, SlotsPropType type, void *val) +{ + if (!slots || !val || type >= SLOTS_PROP_BUTT) { + mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val); + return MPP_ERR_UNKNOW; + } + + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + mpp_mutex_lock(&impl->lock); + RK_U32 value = *((RK_U32*)val); + switch (type) { + case SLOTS_EOS: { + impl->eos = value; + } break; + case SLOTS_NUMERATOR : { + impl->numerator = value; + } break; + case SLOTS_DENOMINATOR : { + impl->denominator = value; + } break; + case SLOTS_HOR_ALIGN: { + impl->hal_hor_align = (AlignFunc)val; + } break; + case SLOTS_VER_ALIGN: { + impl->hal_ver_align = (AlignFunc)val; + } break; + case SLOTS_LEN_ALIGN: { + impl->hal_len_align = (AlignFunc)val; + } break; + case SLOTS_COUNT: { + impl->buf_count = value; + } break; + case SLOTS_SIZE: { + impl->buf_size = value; + } break; + case SLOTS_FRAME_INFO: { + // do info change detection here + generate_info_set(impl, (MppFrame)val, 1); + mpp_frame_copy(impl->info, impl->info_set); + { + MppFrameImpl *p = (MppFrameImpl *)impl->info; + mpp_log("set frame info: w %4d h %4d hor %4d ver %4d\n", p->width, p->height, p->hor_stride, p->ver_stride); + } + mpp_frame_copy((MppFrame)val, impl->info_set); + if (impl->info_change_slot_idx >= 0) { + MppBufSlotEntry *slot = &impl->slots[impl->info_change_slot_idx]; + + if (slot->frame) { + MppFrameImpl *dst = (MppFrameImpl *)slot->frame; + MppFrameImpl *src = (MppFrameImpl *)val; + + dst->fmt = src->fmt; + dst->hor_stride = src->hor_stride; + dst->hor_stride_pixel = src->hor_stride_pixel; + dst->ver_stride = src->ver_stride; + dst->buf_size = src->buf_size; + + if (MPP_FRAME_FMT_IS_FBC(dst->fmt) && impl->hal_fbc_adj_cfg.func) + impl->hal_fbc_adj_cfg.func(impl, dst, impl->hal_fbc_adj_cfg.expand); + } + + impl->info_change_slot_idx = -1; + } + + if (impl->dec_cfg) { + MppDecCfg cfg = impl->dec_cfg; + MppFrameImpl *frm = (MppFrameImpl *)val; + + mpp_dec_cfg_set_s32(cfg, "status:width", frm->width); + mpp_dec_cfg_set_s32(cfg, "status:height", frm->height); + mpp_dec_cfg_set_s32(cfg, "status:hor_stride", frm->hor_stride); + mpp_dec_cfg_set_s32(cfg, "status:ver_stride", frm->ver_stride); + mpp_dec_cfg_set_s32(cfg, "status:buf_size", frm->buf_size); + } + } break; + case SLOTS_HAL_FBC_ADJ : { + impl->hal_fbc_adj_cfg = *((SlotHalFbcAdjCfg *)val); + } break; + case SLOTS_CODING_TYPE : { + impl->coding_type = *((MppCodingType *)val); + } break; + case SLOTS_WIDTH_ALIGN: { + impl->hal_width_align = (AlignFunc)val; + } break; + default : { + } break; + } + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_slots_get_prop(MppBufSlots slots, SlotsPropType type, void *val) +{ + if (!slots || !val || type >= SLOTS_PROP_BUTT) { + mpp_err_f("found invalid input slots %p type %d val %p\n", slots, type, val); + return MPP_NOK; + } + + MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; + mpp_mutex_lock(&impl->lock); + MPP_RET ret = MPP_OK; + + switch (type) { + case SLOTS_EOS: { + *((RK_U32 *)val) = impl->eos; + } break; + case SLOTS_COUNT: { + *((RK_U32 *)val) = impl->buf_count; + } break; + case SLOTS_SIZE: { + *((RK_U32 *)val) = (RK_U32)impl->buf_size; + } break; + case SLOTS_FRAME_INFO: { + MppFrame frame = (MppFrame)val; + MppFrame info = impl->info; + mpp_frame_copy(frame, info); + } break; + default : { + mpp_err("can not get slots prop type %d\n", type); + ret = MPP_NOK; + } break; + } + mpp_mutex_unlock(&impl->lock); + + return ret; +} diff --git a/mpp/base/mpp_buffer.c b/mpp/base/mpp_buffer.c new file mode 100644 index 000000000..f00496008 --- /dev/null +++ b/mpp/base/mpp_buffer.c @@ -0,0 +1,449 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_buffer" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_dmabuf.h" +#include "mpp_buffer_impl.h" + +MPP_RET mpp_buffer_import_with_tag(MppBufferGroup group, MppBufferInfo *info, MppBuffer *buffer, + const char *tag, const char *caller) +{ + if (NULL == info) { + mpp_err("mpp_buffer_commit invalid input: info NULL from %s\n", caller); + return MPP_ERR_NULL_PTR; + } + + MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; + + if (p) { + // if group is specified we need to check the parameter + if ((p->type & MPP_BUFFER_TYPE_MASK) != info->type || + (p->type & MPP_BUFFER_TYPE_MASK) >= MPP_BUFFER_TYPE_BUTT || + p->mode != MPP_BUFFER_EXTERNAL) { + mpp_err("mpp_buffer_commit invalid type found group %d info %d group mode %d from %s\n", + p->type, info->type, p->mode, caller); + return MPP_ERR_UNKNOW; + } + } else { + // otherwise use default external group to manage them + p = mpp_buffer_get_misc_group(MPP_BUFFER_EXTERNAL, info->type); + } + + mpp_assert(p); + + MPP_RET ret = MPP_OK; + if (buffer) { + MppBufferImpl *buf = NULL; + ret = mpp_buffer_create(tag, caller, p, info, &buf); + *buffer = buf; + } else { + ret = mpp_buffer_create(tag, caller, p, info, NULL); + } + return ret; +} + +MPP_RET mpp_buffer_get_with_tag(MppBufferGroup group, MppBuffer *buffer, size_t size, + const char *tag, const char *caller) +{ + if (NULL == buffer || 0 == size) { + mpp_err("mpp_buffer_get invalid input: group %p buffer %p size %u from %s\n", + group, buffer, size, caller); + return MPP_ERR_UNKNOW; + } + + if (NULL == group) { + // deprecated, only for libvpu support + group = mpp_buffer_get_misc_group(MPP_BUFFER_INTERNAL, MPP_BUFFER_TYPE_ION); + } + + mpp_assert(group); + + MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; + // try unused buffer first + MppBufferImpl *buf = mpp_buffer_get_unused(p, size, caller); + if (NULL == buf && MPP_BUFFER_INTERNAL == p->mode) { + MppBufferInfo info = { + p->type, + size, + NULL, + NULL, + -1, + -1, + }; + // if failed try init a new buffer + mpp_buffer_create(tag, caller, p, &info, &buf); + } + *buffer = buf; + return (buf) ? (MPP_OK) : (MPP_NOK); +} + + +MPP_RET mpp_buffer_put_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_put invalid input: buffer NULL from %s\n", caller); + return MPP_ERR_UNKNOW; + } + + return mpp_buffer_ref_dec((MppBufferImpl*)buffer, caller); +} + +MPP_RET mpp_buffer_inc_ref_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_inc_ref invalid input: buffer NULL from %s\n", caller); + return MPP_ERR_UNKNOW; + } + + return mpp_buffer_ref_inc((MppBufferImpl*)buffer, caller); +} + +MPP_RET mpp_buffer_discard_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_discard invalid input: buffer NULL from %s\n", caller); + return MPP_ERR_UNKNOW; + } + + return mpp_buffer_discard((MppBufferImpl*)buffer, caller); +} + +MPP_RET mpp_buffer_read_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller) +{ + if (NULL == buffer || NULL == data) { + mpp_err("mpp_buffer_read invalid input: buffer %p data %p from %s\n", + buffer, data, caller); + return MPP_ERR_UNKNOW; + } + + if (0 == size) + return MPP_OK; + + MppBufferImpl *p = (MppBufferImpl*)buffer; + if (NULL == p->info.ptr) + mpp_buffer_mmap(p, caller); + + void *src = p->info.ptr; + mpp_assert(src != NULL); + if (src) + memcpy(data, (char*)src + offset, size); + + return MPP_OK; +} + +MPP_RET mpp_buffer_write_with_caller(MppBuffer buffer, size_t offset, void *data, size_t size, const char *caller) +{ + if (NULL == buffer || NULL == data) { + mpp_err("mpp_buffer_write invalid input: buffer %p data %p from %s\n", + buffer, data, caller); + return MPP_ERR_UNKNOW; + } + + if (0 == size) + return MPP_OK; + + MppBufferImpl *p = (MppBufferImpl*)buffer; + if (offset + size > p->info.size) + return MPP_ERR_VALUE; + if (NULL == p->info.ptr) + mpp_buffer_mmap(p, caller); + + void *dst = p->info.ptr; + mpp_assert(dst != NULL); + if (dst) + memcpy((char*)dst + offset, data, size); + + return MPP_OK; +} + +void *mpp_buffer_get_ptr_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_get_ptr invalid NULL input from %s\n", caller); + return NULL; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + if (NULL == p->info.ptr) + mpp_buffer_mmap(p, caller); + + mpp_assert(p->info.ptr != NULL); + if (NULL == p->info.ptr) + mpp_err("mpp_buffer_get_ptr buffer %p ret NULL from %s\n", buffer, caller); + + return p->info.ptr; +} + +int mpp_buffer_get_fd_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_get_fd invalid NULL input from %s\n", caller); + return -1; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + int fd = p->info.fd; + mpp_assert(fd >= 0); + if (fd < 0) + mpp_err("mpp_buffer_get_fd buffer %p fd %d from %s\n", buffer, fd, caller); + + return fd; +} + +size_t mpp_buffer_get_size_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_get_size invalid NULL input from %s\n", caller); + return 0; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + if (p->info.size == 0) + mpp_err("mpp_buffer_get_size buffer %p ret zero size from %s\n", buffer, caller); + + return p->info.size; +} + +int mpp_buffer_get_index_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_get_index invalid NULL input from %s\n", caller); + return -1; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + return p->info.index; +} + +MPP_RET mpp_buffer_set_index_with_caller(MppBuffer buffer, int index, + const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_set_index invalid NULL input from %s\n", caller); + return MPP_ERR_UNKNOW; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + p->info.index = index; + return MPP_OK; +} + +size_t mpp_buffer_get_offset_with_caller(MppBuffer buffer, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_get_offset invalid NULL input from %s\n", caller); + return -1; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + return p->offset; +} + +MPP_RET mpp_buffer_set_offset_with_caller(MppBuffer buffer, size_t offset, const char *caller) +{ + if (NULL == buffer) { + mpp_err("mpp_buffer_set_offset invalid NULL input from %s\n", caller); + return MPP_ERR_UNKNOW; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + p->offset = offset; + return MPP_OK; +} + +MPP_RET mpp_buffer_info_get_with_caller(MppBuffer buffer, MppBufferInfo *info, const char *caller) +{ + if (NULL == buffer || NULL == info) { + mpp_err("mpp_buffer_info_get invalid input buffer %p info %p from %s\n", + buffer, info, caller); + return MPP_ERR_UNKNOW; + } + + MppBufferImpl *p = (MppBufferImpl*)buffer; + if (NULL == p->info.ptr) + mpp_buffer_mmap(p, caller); + + *info = p->info; + (void)caller; + return MPP_OK; +} + +static MPP_RET check_buf_need_sync(MppBuffer buffer, MPP_RET *ret, const char *caller) +{ + if (NULL == buffer) { + mpp_err("check buffer found NULL pointer from %s\n", caller); + return MPP_NOK; + } + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + if (impl->info.fd <= 0) { + mpp_err("check fd found invalid fd %d from %s\n", impl->info.fd, caller); + return MPP_NOK; + } + + /* uncached buffer do not need to sync */ + if (impl->uncached) { + *ret = MPP_OK; + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_buffer_sync_begin_f(MppBuffer buffer, RK_S32 ro, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_begin(impl->info.fd, ro, caller); +} + +MPP_RET mpp_buffer_sync_end_f(MppBuffer buffer, RK_S32 ro, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_end(impl->info.fd, ro, caller); +} + +MPP_RET mpp_buffer_sync_partial_begin_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_partial_begin(impl->info.fd, ro, impl->offset + offset, length, caller); +} + +MPP_RET mpp_buffer_sync_partial_end_f(MppBuffer buffer, RK_S32 ro, RK_U32 offset, RK_U32 length, const char* caller) +{ + MPP_RET ret = MPP_NOK; + + if (check_buf_need_sync(buffer, &ret, caller)) + return ret; + + MppBufferImpl *impl = (MppBufferImpl *)buffer; + + return mpp_dmabuf_sync_partial_end(impl->info.fd, ro, impl->offset + offset, length, caller); +} + +MPP_RET mpp_buffer_group_get(MppBufferGroup *group, MppBufferType type, MppBufferMode mode, + const char *tag, const char *caller) +{ + if (NULL == group || + mode >= MPP_BUFFER_MODE_BUTT || + (type & MPP_BUFFER_TYPE_MASK) >= MPP_BUFFER_TYPE_BUTT) { + mpp_err_f("input invalid group %p mode %d type %d from %s\n", + group, mode, type, caller); + return MPP_ERR_UNKNOW; + } + + return mpp_buffer_group_init((MppBufferGroupImpl**)group, tag, caller, mode, type); +} + +MPP_RET mpp_buffer_group_put(MppBufferGroup group) +{ + if (NULL == group) { + mpp_err_f("input invalid group %p\n", group); + return MPP_NOK; + } + + return mpp_buffer_group_deinit((MppBufferGroupImpl *)group); +} + +MPP_RET mpp_buffer_group_clear(MppBufferGroup group) +{ + if (NULL == group) { + mpp_err_f("input invalid group %p\n", group); + return MPP_NOK; + } + + return mpp_buffer_group_reset((MppBufferGroupImpl *)group); +} + +RK_S32 mpp_buffer_group_unused(MppBufferGroup group) +{ + if (NULL == group) { + mpp_err_f("input invalid group %p\n", group); + return MPP_NOK; + } + + MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; + RK_S32 unused = 0; + + if (p->mode == MPP_BUFFER_INTERNAL) { + if (p->limit_count) + unused = p->limit_count - p->count_used; + else + unused = 3; /* NOTE: 3 for 1 decoding 2 deinterlace buffer */ + } else + unused = p->count_unused; + + return unused; +} + +size_t mpp_buffer_group_usage(MppBufferGroup group) +{ + if (NULL == group) { + mpp_err_f("input invalid group %p\n", group); + return MPP_BUFFER_MODE_BUTT; + } + + MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; + return p->usage; +} + +MppBufferMode mpp_buffer_group_mode(MppBufferGroup group) +{ + if (NULL == group) { + mpp_err_f("input invalid group %p\n", group); + return MPP_BUFFER_MODE_BUTT; + } + + MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; + return p->mode; +} + +MppBufferType mpp_buffer_group_type(MppBufferGroup group) +{ + if (NULL == group) { + mpp_err_f("input invalid group %p\n", group); + return MPP_BUFFER_TYPE_BUTT; + } + + MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; + return p->type; +} + +MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count) +{ + if (NULL == group) { + mpp_err_f("input invalid group %p\n", group); + return MPP_NOK; + } + + MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; + mpp_assert(p->mode == MPP_BUFFER_INTERNAL); + p->limit_size = size; + p->limit_count = count; + return MPP_OK; +} \ No newline at end of file diff --git a/mpp/base/mpp_buffer_impl.c b/mpp/base/mpp_buffer_impl.c new file mode 100644 index 000000000..9c9d1470a --- /dev/null +++ b/mpp/base/mpp_buffer_impl.c @@ -0,0 +1,1348 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_buffer" + +#include + +#include "mpp_env.h" +#include "mpp_hash.h" +#include "mpp_lock.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_thread.h" +#include "mpp_mem_pool.h" +#include "mpp_singleton.h" + +#include "mpp_buffer_impl.h" + +#define MAX_GROUP_BIT 8 +#define MAX_MISC_GROUP_BIT 3 +#define BUFFER_OPS_MAX_COUNT 1024 +#define MPP_ALLOCATOR_WITH_FLAG_NUM 8 + +/* NOTE: user may call buffer / buf_grp deinit after buffer service deinited */ +typedef enum MppBufSrvStatus_e { + MPP_BUF_SRV_UNINITED = -1, + MPP_BUF_SRV_NORMAL = 0, + MPP_BUF_SRV_FINALIZED = 1, + MPP_BUF_SRV_BUTT, +} MppBufSrvStatus; + +#define SEARCH_GROUP_BY_ID(srv, id) (get_group_by_id(srv, id)) + +#define get_srv_buffer(void) \ + ({ \ + MppBufferService *__tmp; \ + if (srv_buffer) \ + __tmp = srv_buffer; \ + else { \ + switch (srv_status) { \ + case MPP_BUF_SRV_UNINITED : { \ + mpp_buffer_service_init(); \ + __tmp = srv_buffer; \ + } break; \ + case MPP_BUF_SRV_FINALIZED : { \ + /* if called after buf srv deinited return NULL without error log */ \ + __tmp = NULL; \ + } break; \ + default : { \ + mpp_err("mpp buffer srv not init status %d at %s\n", __FUNCTION__); \ + __tmp = NULL; \ + } break; \ + } \ + } \ + __tmp; \ + }) + +static void mpp_buffer_service_init(void); + +typedef MPP_RET (*BufferOp)(MppAllocator allocator, MppBufferInfo *data); + +typedef struct MppBufferService_t { + rk_u32 group_id; + rk_u32 group_count; + rk_u32 finalizing; + + rk_u32 total_size; + rk_u32 total_max; + + MppMutex lock; + // misc group for internal / externl buffer with different type + rk_u32 misc[MPP_BUFFER_MODE_BUTT][MPP_BUFFER_TYPE_BUTT][MPP_ALLOCATOR_WITH_FLAG_NUM]; + rk_u32 misc_count; + /* preset allocator apis */ + MppAllocator allocator[MPP_BUFFER_TYPE_BUTT][MPP_ALLOCATOR_WITH_FLAG_NUM]; + MppAllocatorApi *allocator_api[MPP_BUFFER_TYPE_BUTT]; + + struct list_head list_group; + DECLARE_HASHTABLE(hash_group, MAX_GROUP_BIT); + + // list for used buffer which do not have group + struct list_head list_orphan; +} MppBufferService; + +static const char *mode2str[MPP_BUFFER_MODE_BUTT] = { + "internal", + "external", +}; + +static const char *type2str[MPP_BUFFER_TYPE_BUTT] = { + "normal", + "ion", + "dma-buf", + "drm", +}; +static const char *ops2str[BUF_OPS_BUTT] = { + "grp create ", + "grp release", + "grp reset", + "grp orphan", + "grp destroy", + + "buf commit ", + "buf create ", + "buf mmap ", + "buf ref inc", + "buf ref dec", + "buf discard", + "buf destroy", +}; + +static MppMemPool pool_buf = NULL; +static MppMemPool pool_buf_grp = NULL; +static MppMemPool pool_buf_map_node = NULL; +static MppBufferService *srv_buffer = NULL; +static MppBufSrvStatus srv_status = MPP_BUF_SRV_UNINITED; +rk_u32 mpp_buffer_debug = 0; + +static MppBufferGroupImpl *service_get_group(const char *tag, const char *caller, + MppBufferMode mode, MppBufferType type, + rk_u32 is_misc); + +static void service_put_group(MppBufferService *srv, MppBufferGroupImpl *p, const char *caller); +static void service_dump(MppBufferService *srv, const char *info); + +static MppBufferGroupImpl *get_group_by_id(MppBufferService *srv, rk_u32 id) +{ + MppBufferGroupImpl *impl = NULL; + + hash_for_each_possible(srv->hash_group, impl, hlist, id) { + if (impl->group_id == id) + break; + } + + return impl; +} + +static MppBufLogs *buf_logs_init(rk_u32 max_count) +{ + MppBufLogs *logs = NULL; + + if (!max_count) + return NULL; + + logs = mpp_malloc_size(MppBufLogs, sizeof(MppBufLogs) + max_count * sizeof(MppBufLog)); + if (!logs) { + mpp_err_f("failed to create %d buf logs\n", max_count); + return NULL; + } + + { + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&logs->lock, &attr); + pthread_mutexattr_destroy(&attr); + } + + logs->max_count = max_count; + logs->log_count = 0; + logs->log_write = 0; + logs->log_read = 0; + logs->logs = (MppBufLog *)(logs + 1); + + return logs; +} + +static void buf_logs_deinit(MppBufLogs *logs) +{ + pthread_mutex_destroy(&logs->lock); + MPP_FREE(logs); +} + +static void buf_logs_write(MppBufLogs *logs, rk_u32 group_id, rk_s32 buffer_id, + MppBufOps ops, rk_s32 ref_count, const char *caller) +{ + MppBufLog *log = NULL; + + pthread_mutex_lock(&logs->lock); + + log = &logs->logs[logs->log_write]; + log->group_id = group_id; + log->buffer_id = buffer_id; + log->ops = ops; + log->ref_count = ref_count; + log->caller = caller; + + logs->log_write++; + if (logs->log_write >= logs->max_count) + logs->log_write = 0; + + if (logs->log_count < logs->max_count) + logs->log_count++; + else { + logs->log_read++; + if (logs->log_read >= logs->max_count) + logs->log_read = 0; + } + + pthread_mutex_unlock(&logs->lock); +} + +static void buf_logs_dump(MppBufLogs *logs) +{ + while (logs->log_count) { + MppBufLog *log = &logs->logs[logs->log_read]; + + if (log->buffer_id >= 0) + mpp_log("group %3d buffer %4d ops %s ref_count %d caller %s\n", + log->group_id, log->buffer_id, + ops2str[log->ops], log->ref_count, log->caller); + else + mpp_log("group %3d ops %s\n", log->group_id, ops2str[log->ops]); + + logs->log_read++; + if (logs->log_read >= logs->max_count) + logs->log_read = 0; + logs->log_count--; + } + mpp_assert(logs->log_read == logs->log_write); +} + +static void buf_add_log(MppBufferImpl *buffer, MppBufOps ops, const char* caller) +{ + if (buffer->log_runtime_en) { + mpp_log("group %3d buffer %4d fd %3d ops %s ref_count %d caller %s\n", + buffer->group_id, buffer->buffer_id, buffer->info.fd, + ops2str[ops], buffer->ref_count, caller); + } + if (buffer->logs) + buf_logs_write(buffer->logs, buffer->group_id, buffer->buffer_id, + ops, buffer->ref_count, caller); +} + +static void buf_grp_add_log(MppBufferGroupImpl *group, MppBufOps ops, const char* caller) +{ + if (group->log_runtime_en) { + mpp_log("group %3d mode %d type %d ops %s\n", group->group_id, + group->mode, group->type, ops2str[ops]); + } + if (group->logs) + buf_logs_write(group->logs, group->group_id, -1, ops, 0, caller); +} + +static void dump_buffer_info(MppBufferImpl *buffer) +{ + mpp_log("buffer %p fd %4d size %10d ref_count %3d discard %d caller %s\n", + buffer, buffer->info.fd, buffer->info.size, + buffer->ref_count, buffer->discard, buffer->caller); +} + +void mpp_buffer_group_dump(MppBufferGroupImpl *group, const char *caller) +{ + MppBufferImpl *pos, *n; + + mpp_log("\ndumping buffer group %p id %d from %s\n", group, + group->group_id, caller); + mpp_log("mode %s\n", mode2str[group->mode]); + mpp_log("type %s\n", type2str[group->type]); + mpp_log("limit size %d count %d\n", group->limit_size, group->limit_count); + + mpp_log("used buffer count %d\n", group->count_used); + + list_for_each_entry_safe(pos, n, &group->list_used, MppBufferImpl, list_status) { + dump_buffer_info(pos); + } + + mpp_log("unused buffer count %d\n", group->count_unused); + list_for_each_entry_safe(pos, n, &group->list_unused, MppBufferImpl, list_status) { + dump_buffer_info(pos); + } + + if (group->logs) + buf_logs_dump(group->logs); +} + +static void clear_buffer_info(MppBufferInfo *info) +{ + info->fd = -1; + info->ptr = NULL; + info->hnd = NULL; + info->size = 0; + info->index = -1; + info->type = MPP_BUFFER_TYPE_BUTT; +} + +static void service_put_buffer(MppBufferService *srv, MppBufferGroupImpl *group, + MppBufferImpl *buffer, rk_u32 reuse, const char *caller) +{ + struct list_head list_maps; + MppDevBufMapNode *pos, *n; + MppBufferInfo info; + + mpp_assert(group); + + pthread_mutex_lock(&buffer->lock); + + if (!srv && !srv->finalizing) { + mpp_assert(buffer->ref_count == 0); + if (buffer->ref_count > 0) { + pthread_mutex_unlock(&buffer->lock); + return; + } + } + + list_del_init(&buffer->list_status); + + if (reuse) { + if (buffer->used && group) { + group->count_used--; + list_add_tail(&buffer->list_status, &group->list_unused); + group->count_unused++; + } else { + mpp_err_f("can not reuse unused buffer %d at group %p:%d\n", + buffer->buffer_id, group, buffer->group_id); + } + buffer->used = 0; + + pthread_mutex_unlock(&buffer->lock); + return; + } + + /* remove all map from buffer */ + INIT_LIST_HEAD(&list_maps); + list_for_each_entry_safe(pos, n, &buffer->list_maps, MppDevBufMapNode, list_buf) { + list_move_tail(&pos->list_buf, &list_maps); + pos->iova = (rk_u32)(-1); + } + mpp_assert(list_empty(&buffer->list_maps)); + info = buffer->info; + if (group) { + rk_u32 destroy = 0; + rk_u32 size = buffer->info.size; + + if (buffer->used) + group->count_used--; + else + group->count_unused--; + + group->usage -= size; + group->buffer_count--; + + /* reduce total buffer size record */ + if (group->mode == MPP_BUFFER_INTERNAL && srv) + MPP_FETCH_SUB(&srv->total_size, size); + + buf_add_log(buffer, BUF_DESTROY, caller); + + if (group->is_orphan && !group->usage && !group->is_finalizing) + destroy = 1; + + if (destroy) + service_put_group(srv, group, caller); + } else { + mpp_assert(srv_status); + } + clear_buffer_info(&buffer->info); + + pthread_mutex_unlock(&buffer->lock); + + list_for_each_entry_safe(pos, n, &list_maps, MppDevBufMapNode, list_buf) { + MppDev dev = pos->dev; + + mpp_assert(dev); + mpp_dev_ioctl(dev, MPP_DEV_LOCK_MAP, NULL); + /* remove buffer from group */ + mpp_dev_ioctl(dev, MPP_DEV_DETACH_FD, pos); + mpp_dev_ioctl(dev, MPP_DEV_UNLOCK_MAP, NULL); + mpp_mem_pool_put(pool_buf_map_node, pos, caller); + } + + /* release buffer here */ + { + BufferOp func = (buffer->mode == MPP_BUFFER_INTERNAL) ? + (buffer->alloc_api->free) : + (buffer->alloc_api->release); + + func(buffer->allocator, &info); + } + + mpp_mem_pool_put(pool_buf, buffer, caller); +} + +static MPP_RET inc_buffer_ref(MppBufferImpl *buffer, const char *caller) +{ + MPP_RET ret = MPP_OK; + + pthread_mutex_lock(&buffer->lock); + buffer->ref_count++; + buf_add_log(buffer, BUF_REF_INC, caller); + if (!buffer->used) { + MppBufferGroupImpl *group = NULL; + MppBufferService *srv = get_srv_buffer(); + + if (srv) { + mpp_mutex_lock(&srv->lock); + group = SEARCH_GROUP_BY_ID(srv, buffer->group_id); + mpp_mutex_unlock(&srv->lock); + } + // NOTE: when increasing ref_count the unused buffer must be under certain group + mpp_assert(group); + buffer->used = 1; + if (group) { + pthread_mutex_lock(&group->buf_lock); + list_del_init(&buffer->list_status); + list_add_tail(&buffer->list_status, &group->list_used); + group->count_used++; + group->count_unused--; + pthread_mutex_unlock(&group->buf_lock); + } else { + mpp_err_f("unused buffer without group\n"); + ret = MPP_NOK; + } + } + pthread_mutex_unlock(&buffer->lock); + return ret; +} + +MPP_RET mpp_buffer_create(const char *tag, const char *caller, + MppBufferGroupImpl *group, MppBufferInfo *info, + MppBufferImpl **buffer) +{ + MPP_BUF_FUNCTION_ENTER(); + + MPP_RET ret = MPP_OK; + BufferOp func = NULL; + MppBufferImpl *p = NULL; + + if (!group) { + mpp_err_f("can not create buffer without group\n"); + ret = MPP_NOK; + goto RET; + } + + if (group->limit_count && group->buffer_count >= group->limit_count) { + if (group->log_runtime_en) + mpp_log_f("group %d reach count limit %d\n", group->group_id, group->limit_count); + ret = MPP_NOK; + goto RET; + } + + if (group->limit_size && info->size > group->limit_size) { + mpp_err_f("required size %d reach group size limit %d\n", info->size, group->limit_size); + ret = MPP_NOK; + goto RET; + } + + p = (MppBufferImpl *)mpp_mem_pool_get(pool_buf, caller); + if (!p) { + mpp_err_f("failed to allocate context\n"); + ret = MPP_ERR_MALLOC; + goto RET; + } + + func = (group->mode == MPP_BUFFER_INTERNAL) ? + (group->alloc_api->alloc) : (group->alloc_api->import); + ret = func(group->allocator, info); + if (ret) { + mpp_err_f("failed to create buffer with size %d\n", info->size); + mpp_mem_pool_put(pool_buf, p, caller); + ret = MPP_ERR_MALLOC; + goto RET; + } + + if (!tag) + tag = group->tag; + + snprintf(p->tag, sizeof(p->tag), "%s", tag); + p->caller = caller; + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p->lock, &attr); + pthread_mutexattr_destroy(&attr); + p->allocator = group->allocator; + p->alloc_api = group->alloc_api; + p->log_runtime_en = group->log_runtime_en; + p->log_history_en = group->log_history_en; + p->group_id = group->group_id; + p->mode = group->mode; + p->type = group->type; + p->uncached = ((group->flags & MPP_ALLOC_FLAG_CACHABLE) != 0) ? 0 : 1; + p->logs = group->logs; + p->info = *info; + + pthread_mutex_lock(&group->buf_lock); + p->buffer_id = group->buffer_id++; + INIT_LIST_HEAD(&p->list_status); + INIT_LIST_HEAD(&p->list_maps); + + if (buffer) { + p->ref_count++; + p->used = 1; + list_add_tail(&p->list_status, &group->list_used); + group->count_used++; + *buffer = p; + } else { + list_add_tail(&p->list_status, &group->list_unused); + group->count_unused++; + } + + group->usage += info->size; + group->buffer_count++; + pthread_mutex_unlock(&group->buf_lock); + + buf_add_log(p, (group->mode == MPP_BUFFER_INTERNAL) ? (BUF_CREATE) : (BUF_COMMIT), caller); + + if (group->mode == MPP_BUFFER_INTERNAL) { + MppBufferService *srv = get_srv_buffer(); + + if (srv) { + rk_u32 total = MPP_ADD_FETCH(&srv->total_size, info->size); + bool cas_ret; + + do { + rk_u32 old_max = srv->total_max; + rk_u32 new_max = MPP_MAX(total, old_max); + + cas_ret = MPP_BOOL_CAS(&srv->total_max, old_max, new_max); + } while (!cas_ret); + } + } + + if (group->callback) + group->callback(group->arg, group); +RET: + MPP_BUF_FUNCTION_LEAVE(); + return ret; +} + +MPP_RET mpp_buffer_mmap(MppBufferImpl *buffer, const char* caller) +{ + MPP_BUF_FUNCTION_ENTER(); + + MPP_RET ret = buffer->alloc_api->mmap(buffer->allocator, &buffer->info); + if (ret) + mpp_err_f("buffer %d group %d fd %d map failed caller %s\n", + buffer->buffer_id, buffer->group_id, buffer->info.fd, caller); + + buf_add_log(buffer, BUF_MMAP, caller); + + MPP_BUF_FUNCTION_LEAVE(); + return ret; +} + +MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer, const char* caller) +{ + MPP_BUF_FUNCTION_ENTER(); + + MPP_RET ret = inc_buffer_ref(buffer, caller); + + MPP_BUF_FUNCTION_LEAVE(); + return ret; +} + + +MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer, const char* caller) +{ + MPP_RET ret = MPP_OK; + rk_u32 release = 0; + + MPP_BUF_FUNCTION_ENTER(); + + pthread_mutex_lock(&buffer->lock); + + if (buffer->ref_count <= 0) { + buf_add_log(buffer, BUF_REF_DEC, caller); + mpp_err_f("buffer from %s found non-positive ref_count %d caller %s\n", + buffer->caller, buffer->ref_count, caller); + mpp_abort(); + ret = MPP_NOK; + pthread_mutex_unlock(&buffer->lock); + goto done; + } + + buffer->ref_count--; + if (buffer->ref_count == 0) + release = 1; + buf_add_log(buffer, BUF_REF_DEC, caller); + + pthread_mutex_unlock(&buffer->lock); + + if (release) { + MppBufferGroupImpl *group = NULL; + MppBufferService *srv = get_srv_buffer(); + + if (srv) { + mpp_mutex_lock(&srv->lock); + group = SEARCH_GROUP_BY_ID(srv, buffer->group_id); + mpp_mutex_unlock(&srv->lock); + } + + mpp_assert(group); + if (group) { + rk_u32 reuse = 0; + + pthread_mutex_lock(&group->buf_lock); + + reuse = (!group->is_misc && !buffer->discard); + service_put_buffer(srv, group, buffer, reuse, caller); + + if (group->callback) + group->callback(group->arg, group); + + pthread_mutex_unlock(&group->buf_lock); + } + } + +done: + MPP_BUF_FUNCTION_LEAVE(); + return ret; +} + +MPP_RET mpp_buffer_discard(MppBufferImpl *buffer, const char* caller) +{ + MppBufferService *srv = get_srv_buffer(); + MppBufferGroupImpl *group = NULL; + + MPP_BUF_FUNCTION_ENTER(); + + if (srv) { + mpp_mutex_lock(&srv->lock); + group = SEARCH_GROUP_BY_ID(srv, buffer->group_id); + mpp_mutex_unlock(&srv->lock); + } + + mpp_assert(group); + if (group) { + pthread_mutex_lock(&group->buf_lock); + buffer->discard = 1; + buf_add_log(buffer, BUF_DISCARD, caller); + pthread_mutex_unlock(&group->buf_lock); + } + + MPP_BUF_FUNCTION_LEAVE(); + + return MPP_OK; +} + +MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size, const char* caller) +{ + MppBufferImpl *buffer = NULL; + + MPP_BUF_FUNCTION_ENTER(); + + pthread_mutex_lock(&p->buf_lock); + + if (!list_empty(&p->list_unused)) { + MppBufferImpl *pos, *n; + rk_s32 found = 0; + rk_s32 search_count = 0; + + list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) { + mpp_buf_dbg(MPP_BUF_DBG_CHECK_SIZE, "request size %d on buf idx %d size %d\n", + size, pos->buffer_id, pos->info.size); + if (pos->info.size >= size) { + buffer = pos; + pthread_mutex_lock(&buffer->lock); + buffer->ref_count++; + buffer->used = 1; + buf_add_log(buffer, BUF_REF_INC, caller); + list_del_init(&buffer->list_status); + list_add_tail(&buffer->list_status, &p->list_used); + p->count_used++; + p->count_unused--; + pthread_mutex_unlock(&buffer->lock); + found = 1; + break; + } else { + if (MPP_BUFFER_INTERNAL == p->mode) { + service_put_buffer(get_srv_buffer(), p, pos, 0, caller); + } else + search_count++; + } + } + + if (!found && search_count) { + mpp_err_f("can not found match buffer with size larger than %d\n", size); + mpp_buffer_group_dump(p, caller); + } + } + + pthread_mutex_unlock(&p->buf_lock); + + MPP_BUF_FUNCTION_LEAVE(); + return buffer; +} + +rk_u32 mpp_buffer_to_addr(MppBuffer buffer, size_t offset) +{ + MppBufferImpl *impl = (MppBufferImpl *)buffer; + rk_u32 addr = 0; + + if (!impl) { + mpp_err_f("NULL buffer convert to zero address\n"); + return 0; + } + + if (impl->info.fd >= (1 << 10)) { + mpp_err_f("buffer fd %d is too large\n"); + return 0; + } + + if (impl->offset + offset >= SZ_4M) { + mpp_err_f("offset %d + %d is larger than 4M use extra info to send offset\n"); + return 0; + } + + addr = impl->info.fd + ((impl->offset + offset) << 10); + + return addr; +} + +static MppDevBufMapNode *mpp_buffer_attach_dev_lock(const char *caller, MppBuffer buffer, MppDev dev) +{ + MppBufferImpl *impl = (MppBufferImpl *)buffer; + MppDevBufMapNode *pos, *n; + MppDevBufMapNode *node = NULL; + MPP_RET ret = MPP_OK; + + mpp_dev_ioctl(dev, MPP_DEV_LOCK_MAP, NULL); + + pthread_mutex_lock(&impl->lock); + + list_for_each_entry_safe(pos, n, &impl->list_maps, MppDevBufMapNode, list_buf) { + if (pos->dev == dev) { + node = pos; + goto DONE; + } + } + + node = (MppDevBufMapNode *)mpp_mem_pool_get(pool_buf_map_node, caller); + if (!node) { + mpp_err("mpp_buffer_attach_dev failed to allocate map node\n"); + ret = MPP_NOK; + goto DONE; + } + + INIT_LIST_HEAD(&node->list_buf); + INIT_LIST_HEAD(&node->list_dev); + node->lock_buf = &impl->lock; + node->buffer = impl; + node->dev = dev; + node->pool = pool_buf_map_node; + node->buf_fd = impl->info.fd; + + ret = mpp_dev_ioctl(dev, MPP_DEV_ATTACH_FD, node); + if (ret) { + mpp_mem_pool_put(pool_buf_map_node, node, caller); + node = NULL; + goto DONE; + } + list_add_tail(&node->list_buf, &impl->list_maps); + +DONE: + pthread_mutex_unlock(&impl->lock); + mpp_dev_ioctl(dev, MPP_DEV_UNLOCK_MAP, NULL); + + return node; +} + +MPP_RET mpp_buffer_attach_dev_f(const char *caller, MppBuffer buffer, MppDev dev) +{ + MppDevBufMapNode *node; + + node = mpp_buffer_attach_dev_lock(caller, buffer, dev); + + return node ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_buffer_detach_dev_f(const char *caller, MppBuffer buffer, MppDev dev) +{ + MppBufferImpl *impl = (MppBufferImpl *)buffer; + MppDevBufMapNode *pos, *n; + MPP_RET ret = MPP_OK; + + mpp_dev_ioctl(dev, MPP_DEV_LOCK_MAP, NULL); + pthread_mutex_lock(&impl->lock); + list_for_each_entry_safe(pos, n, &impl->list_maps, MppDevBufMapNode, list_buf) { + if (pos->dev == dev) { + list_del_init(&pos->list_buf); + ret = mpp_dev_ioctl(dev, MPP_DEV_DETACH_FD, pos); + mpp_mem_pool_put(pool_buf_map_node, pos, caller); + break; + } + } + pthread_mutex_unlock(&impl->lock); + mpp_dev_ioctl(dev, MPP_DEV_UNLOCK_MAP, NULL); + + return ret; +} + +rk_u32 mpp_buffer_get_iova_f(const char *caller, MppBuffer buffer, MppDev dev) +{ + MppDevBufMapNode *node; + + node = mpp_buffer_attach_dev_lock(caller, buffer, dev); + + return node ? node->iova : (rk_u32)(-1); +} + +MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, const char *caller, + MppBufferMode mode, MppBufferType type) +{ + MPP_BUF_FUNCTION_ENTER(); + mpp_assert(caller); + + *group = service_get_group(tag, caller, mode, type, 0); + + MPP_BUF_FUNCTION_LEAVE(); + return ((*group) ? (MPP_OK) : (MPP_NOK)); +} + +MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p) +{ + if (!p) { + mpp_err_f("found NULL pointer\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_BUF_FUNCTION_ENTER(); + + service_put_group(get_srv_buffer(), p, __FUNCTION__); + + MPP_BUF_FUNCTION_LEAVE(); + return MPP_OK; +} + +MPP_RET mpp_buffer_group_reset(MppBufferGroupImpl *p) +{ + if (!p) { + mpp_err_f("found NULL pointer\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_BUF_FUNCTION_ENTER(); + + pthread_mutex_lock(&p->buf_lock); + + buf_grp_add_log(p, GRP_RESET, NULL); + + if (!list_empty(&p->list_used)) { + MppBufferImpl *pos, *n; + + list_for_each_entry_safe(pos, n, &p->list_used, MppBufferImpl, list_status) { + buf_add_log(pos, BUF_DISCARD, NULL); + pos->discard = 1; + } + } + + // remove unused list + if (!list_empty(&p->list_unused)) { + MppBufferService *srv = get_srv_buffer(); + MppBufferImpl *pos, *n; + + list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) { + service_put_buffer(srv, p, pos, 0, __FUNCTION__); + } + } + + pthread_mutex_unlock(&p->buf_lock); + + MPP_BUF_FUNCTION_LEAVE(); + return MPP_OK; +} + +MPP_RET mpp_buffer_group_set_callback(MppBufferGroupImpl *p, + MppBufCallback callback, void *arg) +{ + if (!p) + return MPP_OK; + + MPP_BUF_FUNCTION_ENTER(); + + p->arg = arg; + p->callback = callback; + + MPP_BUF_FUNCTION_LEAVE(); + return MPP_OK; +} + +rk_u32 mpp_buffer_total_now(void) +{ + MppBufferService *srv = get_srv_buffer(); + rk_u32 size = 0; + + if (srv) + size = srv->total_size; + + return size; +} + +rk_u32 mpp_buffer_total_max(void) +{ + MppBufferService *srv = get_srv_buffer(); + rk_u32 size = 0; + + if (srv) + size = srv->total_max; + + return size; +} + +static rk_u32 type_to_flag(MppBufferType type) +{ + rk_u32 flag = MPP_ALLOC_FLAG_NONE; + + if (type & MPP_BUFFER_FLAGS_DMA32) + flag += MPP_ALLOC_FLAG_DMA32; + + if (type & MPP_BUFFER_FLAGS_CACHABLE) + flag += MPP_ALLOC_FLAG_CACHABLE; + + if (type & MPP_BUFFER_FLAGS_CONTIG) + flag += MPP_ALLOC_FLAG_CMA; + + return flag; +} + +static rk_u32 service_get_misc(MppBufferService *srv, MppBufferMode mode, MppBufferType type) +{ + rk_u32 flag = type_to_flag(type); + + type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK); + if (type == MPP_BUFFER_TYPE_NORMAL) + return 0; + + mpp_assert(mode < MPP_BUFFER_MODE_BUTT); + mpp_assert(type < MPP_BUFFER_TYPE_BUTT); + mpp_assert(flag < MPP_ALLOC_FLAG_TYPE_NB); + + return srv->misc[mode][type][flag]; +} + +MppBufferGroupImpl *mpp_buffer_get_misc_group(MppBufferMode mode, MppBufferType type) +{ + MppBufferService *srv = get_srv_buffer(); + MppBufferGroupImpl *misc; + MppBufferType buf_type; + MppMutex *lock = &srv->lock; + rk_u32 id; + + buf_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK); + if (buf_type == MPP_BUFFER_TYPE_NORMAL) + return NULL; + + mpp_assert(mode < MPP_BUFFER_MODE_BUTT); + mpp_assert(buf_type < MPP_BUFFER_TYPE_BUTT); + + mpp_mutex_lock(lock); + + id = service_get_misc(srv, mode, type); + if (!id) { + char tag[32]; + rk_s32 offset = 0; + + offset += snprintf(tag + offset, sizeof(tag) - offset, "misc"); + offset += snprintf(tag + offset, sizeof(tag) - offset, "_%s", + buf_type == MPP_BUFFER_TYPE_ION ? "ion" : + buf_type == MPP_BUFFER_TYPE_DRM ? "drm" : "na"); + offset += snprintf(tag + offset, sizeof(tag) - offset, "_%s", + mode == MPP_BUFFER_INTERNAL ? "int" : "ext"); + + misc = service_get_group(tag, __FUNCTION__, mode, type, 1); + } else + misc = get_group_by_id(srv, id); + mpp_mutex_unlock(lock); + + return misc; +} + +static void mpp_buffer_service_init(void) +{ + MppBufferService *srv = srv_buffer; + rk_s32 i, j, k; + + if (srv) + return; + + mpp_env_get_u32("mpp_buffer_debug", &mpp_buffer_debug, 0); + + srv = mpp_calloc(MppBufferService, 1); + if (!srv) { + mpp_err_f("alloc buffer service failed\n"); + return; + } + + srv_buffer = srv; + + srv_status = MPP_BUF_SRV_NORMAL; + pool_buf = mpp_mem_pool_init_f(MODULE_TAG, sizeof(MppBufferImpl)); + pool_buf_grp = mpp_mem_pool_init_f("mpp_buf_grp", sizeof(MppBufferGroupImpl)); + pool_buf_map_node = mpp_mem_pool_init_f("mpp_buf_map_node", sizeof(MppDevBufMapNode)); + + srv->group_id = 1; + + INIT_LIST_HEAD(&srv->list_group); + INIT_LIST_HEAD(&srv->list_orphan); + + // NOTE: Do not create misc group at beginning. Only create on when needed. + for (i = 0; i < MPP_BUFFER_MODE_BUTT; i++) + for (j = 0; j < MPP_BUFFER_TYPE_BUTT; j++) + for (k = 0; k < MPP_ALLOCATOR_WITH_FLAG_NUM; k++) + srv->misc[i][j][k] = 0; + + for (i = 0; i < (rk_s32)HASH_SIZE(srv->hash_group); i++) + INIT_HLIST_HEAD(&srv->hash_group[i]); + + mpp_mutex_init(&srv->lock); +} + +static void mpp_buffer_service_deinit() +{ + MppBufferService *srv = srv_buffer; + rk_s32 i, j, k; + + if (!srv) + return; + + srv->finalizing = 1; + + // first remove legacy group which is the normal case + if (srv->misc_count) { + mpp_log_f("cleaning misc group\n"); + for (i = 0; i < MPP_BUFFER_MODE_BUTT; i++) + for (j = 0; j < MPP_BUFFER_TYPE_BUTT; j++) + for (k = 0; k < MPP_ALLOCATOR_WITH_FLAG_NUM; k++) { + rk_u32 id = srv->misc[i][j][k]; + + if (id) { + service_put_group(srv, get_group_by_id(srv, id), __FUNCTION__); + srv->misc[i][j][k] = 0; + } + } + } + + // then remove the remaining group which is the leak one + if (!list_empty(&srv->list_group)) { + MppBufferGroupImpl *pos, *n; + + if (mpp_buffer_debug & MPP_BUF_DBG_DUMP_ON_EXIT) + service_dump(srv, "leaked group found"); + + mpp_log_f("cleaning leaked group\n"); + list_for_each_entry_safe(pos, n, &srv->list_group, MppBufferGroupImpl, list_group) { + service_put_group(srv, pos, __FUNCTION__); + } + } + + // remove all orphan buffer group + if (!list_empty(&srv->list_orphan)) { + MppBufferGroupImpl *pos, *n; + + mpp_log_f("cleaning leaked buffer\n"); + + list_for_each_entry_safe(pos, n, &srv->list_orphan, MppBufferGroupImpl, list_group) { + pos->clear_on_exit = 1; + pos->is_finalizing = 1; + service_put_group(srv, pos, __FUNCTION__); + } + } + + for (i = 0; i < MPP_BUFFER_TYPE_BUTT; i++) { + for (j = 0; j < MPP_ALLOCATOR_WITH_FLAG_NUM; j++) { + if (srv->allocator[i][j]) + mpp_allocator_put(&(srv->allocator[i][j])); + } + } + mpp_mutex_destroy(&srv->lock); + + MPP_FREE(srv_buffer); + srv_status = MPP_BUF_SRV_FINALIZED; +} + +rk_u32 service_get_group_id(MppBufferService *srv) +{ + static rk_u32 overflowed = 0; + rk_u32 id = 0; + + if (!overflowed) { + /* avoid 0 group id */ + if (srv->group_id) + id = srv->group_id++; + else { + overflowed = 1; + srv->group_id = 1; + } + } + + if (overflowed) { + id = srv->group_id++; + + /* when it is overflow avoid the used id */ + while (get_group_by_id(srv, id)) + id = srv->group_id++; + } + + srv->group_count++; + + return id; +} + +static MppBufferGroupImpl *service_get_group(const char *tag, const char *caller, + MppBufferMode mode, MppBufferType type, + rk_u32 is_misc) +{ + MppBufferType buffer_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK); + MppBufferGroupImpl *p = NULL; + MppBufferService *srv = get_srv_buffer(); + MppMutex *lock; + rk_u32 flag; + rk_u32 id; + + /* env update */ + mpp_env_get_u32("mpp_buffer_debug", &mpp_buffer_debug, mpp_buffer_debug); + + if (mode >= MPP_BUFFER_MODE_BUTT || buffer_type >= MPP_BUFFER_TYPE_BUTT) { + mpp_err("MppBufferService get_group found invalid mode %d type %x\n", mode, type); + return NULL; + } + + if (!srv) { + mpp_err("MppBufferService get_group failed to get service\n"); + return NULL; + } + + lock = &srv->lock; + p = (MppBufferGroupImpl *)mpp_mem_pool_get(pool_buf_grp, caller); + if (!p) { + mpp_err("MppBufferService failed to allocate group context\n"); + return NULL; + } + + flag = type_to_flag(type); + + p->flags = (MppAllocFlagType)flag; + + { + MppAllocator allocator = NULL; + MppAllocatorApi *alloc_api = NULL; + + mpp_mutex_lock(lock); + + allocator = srv->allocator[buffer_type][flag]; + alloc_api = srv->allocator_api[buffer_type]; + + // allocate general buffer first + if (!allocator) { + mpp_allocator_get(&allocator, &alloc_api, type, p->flags); + srv->allocator[buffer_type][flag] = allocator; + srv->allocator_api[buffer_type] = alloc_api; + } + + p->allocator = allocator; + p->alloc_api = alloc_api; + p->flags = mpp_allocator_get_flags(allocator); + + mpp_mutex_unlock(lock); + } + + if (!p->allocator || !p->alloc_api) { + mpp_mem_pool_put(pool_buf_grp, p, caller); + mpp_err("MppBufferService get_group failed to get allocater with mode %d type %x\n", mode, type); + return NULL; + } + + INIT_LIST_HEAD(&p->list_group); + INIT_LIST_HEAD(&p->list_used); + INIT_LIST_HEAD(&p->list_unused); + INIT_HLIST_NODE(&p->hlist); + + p->log_runtime_en = ((mpp_buffer_debug & MPP_BUF_DBG_OPS_RUNTIME) != 0) ? (1) : (0); + p->log_history_en = ((mpp_buffer_debug & MPP_BUF_DBG_OPS_HISTORY) != 0) ? (1) : (0); + + p->caller = caller; + p->mode = mode; + p->type = buffer_type; + p->limit = BUFFER_GROUP_SIZE_DEFAULT; + p->clear_on_exit = ((mpp_buffer_debug & MPP_BUF_DBG_CLR_ON_EXIT) != 0) ? (1) : (0); + p->dump_on_exit = ((mpp_buffer_debug & MPP_BUF_DBG_DUMP_ON_EXIT) != 0) ? (1) : (0); + + { + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p->buf_lock, &attr); + pthread_mutexattr_destroy(&attr); + } + + if (p->log_history_en) + p->logs = buf_logs_init(BUFFER_OPS_MAX_COUNT); + + mpp_mutex_lock(lock); + + id = service_get_group_id(srv); + if (tag) { + snprintf(p->tag, sizeof(p->tag) - 1, "%s_%d", tag, id); + } else { + snprintf(p->tag, sizeof(p->tag) - 1, "unknown"); + } + p->group_id = id; + + list_add_tail(&p->list_group, &srv->list_group); + hash_add(srv->hash_group, &p->hlist, id); + + buf_grp_add_log(p, GRP_CREATE, caller); + + if (is_misc) { + srv->misc[mode][buffer_type][flag] = id; + p->is_misc = 1; + srv->misc_count++; + } + + mpp_mutex_unlock(lock); + + return p; +} + +static void destroy_group(MppBufferService *srv, MppBufferGroupImpl *group) +{ + mpp_assert(group->count_used == 0); + mpp_assert(group->count_unused == 0); + + if (group->count_unused || group->count_used) { + mpp_err("mpp_buffer_group %s deinit mismatch counter used %4d unused %4d found\n", + group->caller, group->count_used, group->count_unused); + group->count_unused = 0; + group->count_used = 0; + } + + buf_grp_add_log(group, GRP_DESTROY, __FUNCTION__); + + list_del_init(&group->list_group); + hash_del(&group->hlist); + pthread_mutex_destroy(&group->buf_lock); + + if (group->logs) { + buf_logs_deinit(group->logs); + group->logs = NULL; + } + + if (srv) { + MppBufferMode mode = group->mode; + MppBufferType type = group->type; + rk_u32 flag = type_to_flag(type); + rk_u32 id = group->group_id; + + srv->group_count--; + + if (id == srv->misc[mode][type][flag]) { + srv->misc[mode][type][flag] = 0; + srv->misc_count--; + } + } + + if (pool_buf_grp) + mpp_mem_pool_put_f(pool_buf_grp, group); +} + +static void service_put_group(MppBufferService *srv, MppBufferGroupImpl *p, const char *caller) +{ + MppMutex *lock; + + if (!srv) + return; + + lock = &srv->lock; + + if (!srv->finalizing) + mpp_mutex_lock(lock); + + buf_grp_add_log(p, GRP_RELEASE, caller); + + // remove unused list + if (!list_empty(&p->list_unused)) { + MppBufferImpl *pos, *n; + + list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) { + service_put_buffer(srv, p, pos, 0, caller); + } + } + + if (list_empty(&p->list_used)) { + destroy_group(srv, p); + } else { + if (!srv->finalizing || (srv->finalizing && p->dump_on_exit)) { + mpp_err("mpp_group %p tag %s caller %s mode %s type %s deinit with %d bytes not released\n", + p, p->tag, p->caller, mode2str[p->mode], type2str[p->type], p->usage); + + mpp_buffer_group_dump(p, caller); + } + + /* if clear on exit we need to release remaining buffer */ + if (p->clear_on_exit) { + MppBufferImpl *pos, *n; + + if (p->dump_on_exit) + mpp_err("force release all remaining buffer\n"); + + list_for_each_entry_safe(pos, n, &p->list_used, MppBufferImpl, list_status) { + if (p->dump_on_exit) + mpp_err("clearing buffer %p\n", pos); + pos->ref_count = 0; + pos->discard = 1; + service_put_buffer(srv, p, pos, 0, caller); + } + + destroy_group(srv, p); + } else { + // otherwise move the group to list_orphan and wait for buffer release + buf_grp_add_log(p, GRP_ORPHAN, caller); + list_del_init(&p->list_group); + list_add_tail(&p->list_group, &srv->list_orphan); + p->is_orphan = 1; + } + } + + if (!srv->finalizing) + mpp_mutex_unlock(lock); +} + + +static void service_dump(MppBufferService *srv, const char *info) +{ + MppBufferGroupImpl *group; + struct hlist_node *n; + rk_u32 key; + + mpp_mutex_lock(&srv->lock); + + mpp_log("dumping all buffer groups for %s\n", info); + + if (hash_empty(srv->hash_group)) { + mpp_log("no buffer group can be dumped\n"); + } else { + hash_for_each_safe(srv->hash_group, key, n, group, hlist) { + mpp_buffer_group_dump(group, __FUNCTION__); + } + } + + mpp_mutex_unlock(&srv->lock); +} + +MPP_SINGLETON(MPP_SGLN_BUFFER, mpp_buffer, mpp_buffer_service_init, mpp_buffer_service_deinit) diff --git a/mpp/base/mpp_cfg.c b/mpp/base/mpp_cfg.c new file mode 100644 index 000000000..9b3f60396 --- /dev/null +++ b/mpp/base/mpp_cfg.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_cfg" + +#include + +#include "mpp_env.h" +#include "mpp_cfg.h" +#include "mpp_debug.h" + +static void show_cfg_entry_err(KmppEntry *node, ElemType type, const char *func, const char *name) +{ + mpp_err("%s cfg %s expect %s input NOT %s\n", func, name, + strof_elem_type(node->tbl.elem_type), strof_elem_type(type)); +} + +MPP_RET check_cfg_entry(KmppEntry *node, const char *name, ElemType type, + const char *func) +{ + if (NULL == node) { + mpp_err("%s: cfg %s is invalid\n", func, name); + return MPP_NOK; + } + + ElemType cfg_type = (ElemType)node->tbl.elem_type; + RK_S32 cfg_size = node->tbl.elem_size; + MPP_RET ret = MPP_OK; + + switch (type) { + case ELEM_TYPE_st : + case ELEM_TYPE_arr : { + if (cfg_type != type) { + show_cfg_entry_err(node, type, func, name); + ret = MPP_NOK; + } + if (cfg_size <= 0) { + mpp_err("%s: cfg %s found invalid size %d\n", func, name, cfg_size); + ret = MPP_NOK; + } + } break; + case ELEM_TYPE_ptr : { + if (cfg_type != type) { + show_cfg_entry_err(node, type, func, name); + ret = MPP_NOK; + } + } break; + case ELEM_TYPE_s8 : + case ELEM_TYPE_u8 : { + if (cfg_size != sizeof(RK_S8)) { + show_cfg_entry_err(node, type, func, name); + ret = MPP_NOK; + } + } break; + case ELEM_TYPE_s16 : + case ELEM_TYPE_u16 : { + if (cfg_size != sizeof(RK_S16)) { + show_cfg_entry_err(node, type, func, name); + ret = MPP_NOK; + } + } break; + case ELEM_TYPE_s32 : + case ELEM_TYPE_u32 : { + if (cfg_size != sizeof(RK_S32)) { + show_cfg_entry_err(node, type, func, name); + ret = MPP_NOK; + } + } break; + case ELEM_TYPE_s64 : + case ELEM_TYPE_u64 : { + if (cfg_size != sizeof(RK_S64)) { + show_cfg_entry_err(node, type, func, name); + ret = MPP_NOK; + } + } break; + default : { + mpp_err("%s: cfg %s found invalid cfg type %d\n", func, name, type); + ret = MPP_NOK; + } break; + } + + return ret; +} diff --git a/mpp/base/mpp_cfg_io.c b/mpp/base/mpp_cfg_io.c new file mode 100644 index 000000000..efb9713f9 --- /dev/null +++ b/mpp/base/mpp_cfg_io.c @@ -0,0 +1,3411 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_cfg_io" + +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_trie.h" +#include "mpp_cfg.h" +#include "mpp_cfg_io.h" +#include "rk_venc_cfg.h" +#include "kmpp_obj.h" + +#define MAX_CFG_DEPTH (64) +#define CFG_IO_ARRAY_ELEM_COUNT (8) + +#define CFG_IO_DBG_FLOW (0x00000001) +#define CFG_IO_DBG_BYTE (0x00000002) +#define CFG_IO_DBG_TO (0x00000004) +#define CFG_IO_DBG_FROM (0x00000008) +#define CFG_IO_DBG_FREE (0x00000010) +#define CFG_IO_DBG_NAME (0x00000020) +#define CFG_IO_DBG_SHOW (0x00000040) +#define CFG_IO_DBG_INFO (0x00000080) + +#define cfg_io_dbg(flag, fmt, ...) mpp_dbg(mpp_cfg_io_debug, flag, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_cfg_io_debug, flag, fmt, ## __VA_ARGS__) + +#define cfg_io_dbg_flow(fmt, ...) cfg_io_dbg(CFG_IO_DBG_FLOW, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_byte(fmt, ...) cfg_io_dbg(CFG_IO_DBG_BYTE, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_to(fmt, ...) cfg_io_dbg(CFG_IO_DBG_TO, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_from(fmt, ...) cfg_io_dbg(CFG_IO_DBG_FROM, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_free(fmt, ...) cfg_io_dbg(CFG_IO_DBG_FREE, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_name(fmt, ...) cfg_io_dbg(CFG_IO_DBG_NAME, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_show(fmt, ...) cfg_io_dbg_f(CFG_IO_DBG_SHOW, fmt, ## __VA_ARGS__) +#define cfg_io_dbg_info(fmt, ...) cfg_io_dbg(CFG_IO_DBG_INFO, fmt, ## __VA_ARGS__) + +typedef enum MppCfgParserType_e { + MPP_CFG_PARSER_TYPE_KEY = 0, + MPP_CFG_PARSER_TYPE_VALUE, + MPP_CFG_PARSER_TYPE_TABLE, + MPP_CFG_PARSER_TYPE_ARRAY_TABLE, + MPP_CFG_PARSER_TYPE_BUTT, +} MppCfgParserType; + +typedef struct MppCfgIoImpl_t MppCfgIoImpl; +typedef void (*MppCfgIoFunc)(MppCfgIoImpl *obj, void *data); + +struct MppCfgIoImpl_t { + /* list for bothers */ + struct list_head list; + /* list for children */ + struct list_head child; + /* parent of current object */ + MppCfgIoImpl *parent; + /* valid condition callback for the current object */ + MppCfgObjCond cond; + + MppCfgType type; + MppCfgVal val; + + rk_s32 buf_size; + /* depth in tree */ + rk_s32 depth; + + /* internal name storage */ + char *name; + rk_s32 name_len; + rk_s32 name_buf_len; + + rk_s32 array_count; + + /* location entry for structure access */ + MppTrie trie; + KmppEntry entry; + + union { + /* MPP_CFG_TYPE_STRING */ + struct { + char *string; + rk_s32 str_len; + }; + /* MPP_CFG_TYPE_ARRAY */ + struct { + MppCfgIoImpl **elems; + rk_s32 array_size; + }; + }; +}; + +typedef struct MppCfgStrBuf_t { + char *buf; + rk_s32 buf_size; + rk_s32 offset; + rk_s32 depth; + MppCfgStrFmt type; +} MppCfgStrBuf; + +static rk_u32 mpp_cfg_io_debug = 0; + +static const char *strof_type(MppCfgType type) +{ + static const char *str[MPP_CFG_TYPE_BUTT + 1] = { + [MPP_CFG_TYPE_INVALID] = "invalid", + [MPP_CFG_TYPE_NULL] = "null", + [MPP_CFG_TYPE_BOOL] = "bool", + [MPP_CFG_TYPE_s8] = "s8", + [MPP_CFG_TYPE_u8] = "u8", + [MPP_CFG_TYPE_s16] = "s16", + [MPP_CFG_TYPE_u16] = "u16", + [MPP_CFG_TYPE_s32] = "s32", + [MPP_CFG_TYPE_u32] = "u32", + [MPP_CFG_TYPE_s64] = "s64", + [MPP_CFG_TYPE_u64] = "u64", + [MPP_CFG_TYPE_f32] = "f32", + [MPP_CFG_TYPE_f64] = "f64", + [MPP_CFG_TYPE_STRING] = "string", + [MPP_CFG_TYPE_RAW] = "raw", + [MPP_CFG_TYPE_OBJECT] = "object", + [MPP_CFG_TYPE_ARRAY] = "array", + [MPP_CFG_TYPE_BUTT] = "unknown", + }; + + if (type < 0 || type > MPP_CFG_TYPE_BUTT) + type = MPP_CFG_TYPE_BUTT; + + return str[type]; +} + +static char *dup_str(const char *str, rk_s32 len) +{ + char *ret = NULL; + + if (str && len > 0) { + ret = mpp_calloc_size(char, len + 1); + if (ret) { + memcpy(ret, str, len); + ret[len] = '\0'; + } + } + + return ret; +} + +static rk_s32 get_full_name(MppCfgIoImpl *obj, char *buf, rk_s32 buf_size) +{ + MppCfgIoImpl *curr = obj; + char *name[MAX_CFG_DEPTH]; + char *delmiter = ":"; + rk_s32 depth = 0; + rk_s32 len = 0; + rk_s32 i = 0; + + while (curr && curr->parent) { + /* skip the root */ + if (curr->name) { + /* Add delimiter on object */ + if (curr->type >= MPP_CFG_TYPE_OBJECT) + name[i++] = delmiter; + + name[i++] = curr->name; + } + + curr = curr->parent; + depth++; + + if (i >= MAX_CFG_DEPTH) { + mpp_loge_f("too deep depth %d\n", depth); + return 0; + } + } + + if (!i) { + buf[0] = '\0'; + return 0; + } + + depth = i; + for (i = depth - 1; i >= 0; i--) { + len += snprintf(buf + len, buf_size - len, "%s", name[i]); + + if (len >= buf_size) { + mpp_loge_f("buffer overflow len %d buf_size %d\n", len, buf_size); + break; + } + } + + cfg_io_dbg_name("depth %d obj %-16s -> %s\n", obj->depth, obj->name, buf); + + return len; +} + +void loop_all_children(MppCfgIoImpl *impl, MppCfgIoFunc func, void *data) +{ + MppCfgIoImpl *pos, *n; + + func(impl, data); + + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + loop_all_children(pos, func, data); + } +} + +rk_s32 mpp_cfg_get_object(MppCfgObj *obj, const char *name, MppCfgType type, MppCfgVal *val) +{ + MppCfgIoImpl *impl = NULL; + rk_s32 name_buf_len = 0; + rk_s32 name_len = 0; + rk_s32 buf_size = 0; + rk_s32 str_len = 0; + + if (!obj || type <= MPP_CFG_TYPE_INVALID || type >= MPP_CFG_TYPE_BUTT) { + mpp_loge_f("invalid param obj %p name %s type %d val %p\n", obj, name, type, val); + return rk_nok; + } + + mpp_env_get_u32("mpp_cfg_io_debug", &mpp_cfg_io_debug, mpp_cfg_io_debug); + + if (*obj) + mpp_logw_f("obj %p overwrite\n", *obj); + + *obj = NULL; + + if (name) { + name_len = strlen(name); + name_buf_len = MPP_ALIGN(name_len + 1, 4); + } + + if (type == MPP_CFG_TYPE_STRING && val && val->str) + str_len = MPP_ALIGN(strlen(val->str) + 1, 4); + + buf_size = sizeof(MppCfgIoImpl) + name_buf_len + str_len; + impl = mpp_calloc_size(MppCfgIoImpl, buf_size); + + if (!impl) { + mpp_loge_f("failed to alloc impl size %d\n", buf_size); + return rk_nok; + } + + INIT_LIST_HEAD(&impl->list); + INIT_LIST_HEAD(&impl->child); + + if (name_buf_len) { + impl->name = (char *)(impl + 1); + memcpy(impl->name, name, name_len); + impl->name[name_len] = '\0'; + impl->name_len = name_len; + impl->name_buf_len = name_buf_len; + } + + if (str_len) { + impl->string = (char *)(impl + 1) + name_buf_len; + strncpy(impl->string, val->str, str_len); + impl->str_len = str_len; + } + + impl->type = type; + if (val) + impl->val = *val; + impl->buf_size = buf_size; + /* set invalid data type by default */ + impl->entry.tbl.elem_type = ELEM_TYPE_BUTT; + + if (type == MPP_CFG_TYPE_STRING) + impl->val.str = impl->string; + + *obj = impl; + + return rk_ok; +} + +rk_s32 mpp_cfg_get_array(MppCfgObj *obj, const char *name, rk_s32 count) +{ + MppCfgIoImpl *impl = NULL; + rk_s32 name_buf_len = 0; + rk_s32 name_len = 0; + rk_s32 buf_size = 0; + + if (!obj) { + mpp_loge_f("invalid param obj %p name %s count %d\n", obj, name, count); + return rk_nok; + } + + if (*obj) + mpp_logw_f("obj %p overwrite\n", *obj); + + *obj = NULL; + + if (name) { + name_len = strlen(name); + name_buf_len = MPP_ALIGN(name_len + 1, 4); + } + + buf_size = sizeof(MppCfgIoImpl) + name_buf_len + count * sizeof(MppCfgObj); + impl = mpp_calloc_size(MppCfgIoImpl, buf_size); + + if (!impl) { + mpp_loge_f("failed to alloc impl size %d\n", buf_size); + return rk_nok; + } + + INIT_LIST_HEAD(&impl->list); + INIT_LIST_HEAD(&impl->child); + + if (name_len) { + impl->name = (char *)(impl + 1); + memcpy(impl->name, name, name_len); + impl->name[name_len] = '\0'; + impl->name_len = name_len; + impl->name_buf_len = name_buf_len; + } + + impl->type = MPP_CFG_TYPE_ARRAY; + impl->buf_size = buf_size; + impl->array_count = 0; + /* set invalid data type by default */ + impl->entry.tbl.elem_type = ELEM_TYPE_BUTT; + + if (count) { + impl->elems = (MppCfgIoImpl **)((char *)(impl + 1) + name_buf_len); + impl->array_size = count; + } + + *obj = impl; + + return rk_ok; +} + +rk_s32 mpp_cfg_put(MppCfgObj obj) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + + if (!obj) { + mpp_loge_f("invalid param obj %p\n", obj); + return rk_nok; + } + + list_del_init(&impl->list); + + { + MppCfgIoImpl *pos, *n; + + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + list_del_init(&pos->list); + } + } + + impl->parent = NULL; + + mpp_free(impl); + + return rk_ok; +} + +static void mpp_cfg_put_all_child(MppCfgIoImpl *impl) +{ + MppCfgIoImpl *pos, *n; + + cfg_io_dbg_free("depth %d - %p free start type %d name %s\n", + impl->depth, impl, impl->type, impl->name); + + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + list_del_init(&pos->list); + + cfg_io_dbg_free("depth %d - %p free child %p type %d name %s\n", + impl->depth, impl, pos, pos->type, pos->name); + + mpp_cfg_put_all_child(pos); + } + + cfg_io_dbg_free("depth %d - %p free done type %d name %s\n", + impl->depth, impl, impl->type, impl->name); + + mpp_free(impl); +} + +rk_s32 mpp_cfg_put_all(MppCfgObj obj) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + MppCfgIoImpl *root; + + if (!obj) { + mpp_loge_f("invalid param obj %p\n", obj); + return rk_nok; + } + + if (impl->trie) { + mpp_trie_deinit(impl->trie); + impl->trie = NULL; + } + + root = impl->parent; + do { + mpp_cfg_put_all_child(impl); + + if (!root) + break; + + impl = root; + root = impl->parent; + } while (impl); + + return rk_ok; +} + +static void update_depth(MppCfgIoImpl *impl, void *data) +{ + (void)data; + + if (impl->parent) + impl->depth = impl->parent->depth + 1; +} + +rk_s32 mpp_cfg_add(MppCfgObj root, MppCfgObj leaf) +{ + MppCfgIoImpl *root_impl = (MppCfgIoImpl *)root; + MppCfgIoImpl *leaf_impl = (MppCfgIoImpl *)leaf; + + if (!root || !leaf) { + mpp_loge_f("invalid param root %p leaf %p\n", root, leaf); + return rk_nok; + } + + if (root_impl->type <= MPP_CFG_TYPE_INVALID || root_impl->type >= MPP_CFG_TYPE_BUTT) { + mpp_loge_f("invalid root type %d\n", root_impl->type); + return rk_nok; + } + + list_add_tail(&leaf_impl->list, &root_impl->child); + leaf_impl->parent = root_impl; + + loop_all_children(root, update_depth, NULL); + + if (root_impl->type == MPP_CFG_TYPE_ARRAY && root_impl->elems) { + rk_s32 i; + + for (i = 0; i < root_impl->array_size; i++) { + if (!root_impl->elems[i]) { + root_impl->elems[i] = leaf_impl; + break; + } + } + } + + return rk_ok; +} + +rk_s32 mpp_cfg_del(MppCfgObj obj) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + MppCfgIoImpl *parent; + + if (!obj) { + mpp_loge_f("invalid param obj %p\n", obj); + return rk_nok; + } + + parent = impl->parent; + if (parent) { + list_del_init(&impl->list); + + if (parent->type == MPP_CFG_TYPE_ARRAY && parent->elems) { + rk_s32 i; + + for (i = 0; i < parent->array_size; i++) { + if (parent->elems[i] == impl) { + parent->elems[i] = NULL; + break; + } + } + } + + impl->parent = NULL; + impl->depth = 0; + loop_all_children(impl, update_depth, NULL); + } + + return rk_ok; +} + +rk_s32 mpp_cfg_find(MppCfgObj *obj, MppCfgObj root, char *name, rk_s32 type) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)root; + rk_s32 str_start = 0; + rk_s32 str_len = 0; + rk_s32 i; + char delimiter; + + if (!obj || !root || !name) { + mpp_loge_f("invalid param obj %p root %p name %s\n", obj, root, name); + return rk_nok; + } + + delimiter = (type == MPP_CFG_STR_FMT_TOML) ? '.' : ':'; + str_len = strlen(name); + + for (i = 0; i <= str_len; i++) { + if (name[i] == delimiter || name[i] == '\0') { + MppCfgIoImpl *pos, *n; + MppCfgIoImpl *last_array = NULL; + char bak = name[i]; + rk_s32 found = 0; + + name[i] = '\0'; + mpp_logi("try match %s\n", name + str_start); + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + if (pos->name && !strcmp(pos->name, name + str_start)) { + impl = pos; + found = 1; + break; + } + + /* if impl is array, find impl->chil is object and has no name, to match its child */ + if (impl->type == MPP_CFG_TYPE_ARRAY && pos->type == MPP_CFG_TYPE_OBJECT && !pos->name) + last_array = pos; + } + + if (last_array) { + MppCfgIoImpl *array_pos, *array_n; + + list_for_each_entry_safe(array_pos, array_n, &last_array->child, MppCfgIoImpl, list) { + if (array_pos->name && !strcmp(array_pos->name, name + str_start)) { + impl = array_pos; + found = 1; + break; + } + } + } + + name[i] = bak; + + if (!found) { + *obj = NULL; + return rk_nok; + } + + str_start = i + 1; + } + } + + *obj = impl; + return rk_ok; +} + +MppCfgType mpp_cfg_type_from_elem_type(ElemType type) +{ + switch (type) { + case ELEM_TYPE_s8 : { + return MPP_CFG_TYPE_s8; + } break; + case ELEM_TYPE_u8 : { + return MPP_CFG_TYPE_u8; + } break; + case ELEM_TYPE_s16 : { + return MPP_CFG_TYPE_s16; + } break; + case ELEM_TYPE_u16 : { + return MPP_CFG_TYPE_u16; + } break; + case ELEM_TYPE_s32 : { + return MPP_CFG_TYPE_s32; + } break; + case ELEM_TYPE_u32 : { + return MPP_CFG_TYPE_u32; + } break; + case ELEM_TYPE_s64 : { + return MPP_CFG_TYPE_s64; + } break; + case ELEM_TYPE_u64 : { + return MPP_CFG_TYPE_u64; + } break; + case ELEM_TYPE_arr : { + return MPP_CFG_TYPE_ARRAY; + } break; + default : { + return MPP_CFG_TYPE_BUTT; + } break; + } +} + +rk_s32 mpp_cfg_set_entry(MppCfgObj obj, KmppEntry *entry) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + + if (impl && entry) { + cfg_io_dbg_info("obj %-16s set entry type %s offset %d size %d\n", + impl->name, strof_elem_type(entry->tbl.elem_type), + entry->tbl.elem_offset, entry->tbl.elem_size); + + if (entry->tbl.elem_type < ELEM_TYPE_BUTT) { + memcpy(&impl->entry, entry, sizeof(impl->entry)); + impl->type = mpp_cfg_type_from_elem_type(entry->tbl.elem_type); + } else { + impl->entry.tbl.elem_type = ELEM_TYPE_BUTT; + } + + return rk_ok; + } + + return rk_nok; +} + +rk_s32 mpp_cfg_set_cond(MppCfgObj obj, MppCfgObjCond cond) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + + if (impl) + impl->cond = cond; + + return rk_ok; +} +typedef struct MppCfgFullNameCtx_t { + MppTrie trie; + char *buf; + rk_s32 buf_size; +} MppCfgFullNameCtx; + +static void add_obj_info(MppCfgIoImpl *impl, void *data) +{ + /* NOTE: skip the root object and the invalid object */ + if (impl->entry.tbl.elem_type < ELEM_TYPE_BUTT && impl->parent) { + MppCfgFullNameCtx *ctx = (MppCfgFullNameCtx *)data; + + get_full_name(impl, ctx->buf, ctx->buf_size); + mpp_trie_add_info(ctx->trie, ctx->buf, &impl->entry, sizeof(impl->entry)); + } +} + +MppTrie mpp_cfg_to_trie(MppCfgObj obj) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + MppTrie p = NULL; + + do { + MppCfgFullNameCtx ctx; + rk_s32 ret = rk_nok; + char name[256]; + + if (!impl) { + mpp_loge_f("invalid param obj\n", impl); + break; + } + + if (impl->parent) { + mpp_loge_f("invalid param obj %p not root\n", impl); + break; + } + + if (impl->trie) { + p = impl->trie; + break; + } + + ret = mpp_trie_init(&p, impl->name ? impl->name : "cfg_io"); + if (ret || !p) { + mpp_loge_f("failed to init obj %s trie\n", impl->name ? impl->name : "cfg_io"); + break; + } + + ctx.trie = p; + ctx.buf = name; + ctx.buf_size = sizeof(name) - 1; + + loop_all_children(impl, add_obj_info, &ctx); + mpp_trie_add_info(p, NULL, NULL, 0); + impl->trie = p; + } while (0); + + return p; +} + +/* read byte functions */ +/* check valid len, get offset position */ +#define test_byte_f(str, len) test_byte(str, len, __FUNCTION__) +/* check valid pos, get offset + pos position */ +#define show_byte_f(str, pos) show_byte(str, pos, __FUNCTION__) +/* check valid len, get offset + len position and increase offset by len */ +#define skip_byte_f(str, len) skip_byte(str, len, __FUNCTION__) +#define skip_ws_f(str) skip_ws(str, __FUNCTION__) + +/* write byte functions */ +#define write_byte_f(str, buf, size) write_byte(str, (void *)buf, size, __FUNCTION__) +#define write_indent_f(str) write_indent(str, __FUNCTION__) +/* revert comma for json */ +#define revert_comma_f(str) revert_comma(str, __FUNCTION__) + +static char *test_byte(MppCfgStrBuf *str, rk_s32 len, const char *caller) +{ + char *ret = NULL; + + if (str->offset + len >= str->buf_size) { + cfg_io_dbg_byte("str %p-[%p:%d] offset %d test %d get the end at %s\n", + str, str->buf, str->buf_size, str->offset, len, caller); + return ret; + } + + ret = str->buf + str->offset; + + cfg_io_dbg_byte("str %p-[%p:%d] offset %d test %d ret %p at %s\n", + str, str->buf, str->buf_size, str->offset, len, ret, caller); + + return ret; +} + +static char *show_byte(MppCfgStrBuf *str, rk_s32 pos, const char *caller) +{ + char *ret = NULL; + + if (str->offset + pos >= str->buf_size) { + cfg_io_dbg_byte("str %p-[%p:%d] offset %d show pos %d get the end at %s\n", + str, str->buf, str->buf_size, str->offset, pos, caller); + return ret; + } + + ret = str->buf + str->offset + pos; + + cfg_io_dbg_byte("str %p-[%p:%d] offset %d show %d ret %p at %s\n", + str, str->buf, str->buf_size, str->offset, pos, ret, caller); + + return ret; +} + +static char *skip_byte(MppCfgStrBuf *str, rk_s32 len, const char *caller) +{ + char *ret = NULL; + + if (str->offset + len >= str->buf_size) { + cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip %d get the end at %s\n", + str, str->buf, str->buf_size, str->offset, len, caller); + return NULL; + } + + ret = str->buf + str->offset + len; + + cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip %d ret %p at %s\n", + str, str->buf, str->buf_size, str->offset, len, ret, caller); + + str->offset += len; + return ret; +} + +static char *skip_ws(MppCfgStrBuf *str, const char *caller) +{ + rk_s32 old = str->offset; + char *p; + + cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip ws start at %s\n", + str, str->buf, str->buf_size, old, caller); + + while ((p = show_byte(str, 0, caller)) && p[0] <= 32) + str->offset++; + + if (str->offset >= str->buf_size) { + cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip ws to the end at %s\n", + str, str->buf, str->buf_size, str->offset, caller); + str->offset--; + return NULL; + } + + cfg_io_dbg_byte("str %p-[%p:%d] offset %d skip ws to %d at %s\n", + str, str->buf, str->buf_size, old, str->offset, caller); + + return str->buf + str->offset; +} + +static rk_s32 write_byte(MppCfgStrBuf *str, void *buf, rk_s32 *size, const char *caller) +{ + rk_s32 len = size[0]; + + if (!len) + return rk_ok; + + if (str->offset + len >= str->buf_size) { + void *ptr = mpp_realloc_size(str->buf, void, str->buf_size * 2); + + if (!ptr) { + mpp_loge("failed to realloc buf size %d -> %d at %s\n", + str->buf_size, str->buf_size * 2, caller); + return rk_nok; + } + + cfg_io_dbg_byte("str %p-[%p:%d] enlarger buffer to [%p:%d] at %s\n", + str, str->buf, str->buf_size, ptr, str->buf_size * 2, caller); + + str->buf = ptr; + str->buf_size *= 2; + } + + cfg_io_dbg_byte("str %p-[%p:%d] write offset %d from [%p:%d] at %s\n", + str, str->buf, str->buf_size, str->offset, buf, len, caller); + + memcpy(str->buf + str->offset, buf, len); + str->offset += len; + str->buf[str->offset] = '\0'; + size[0] = 0; + + return rk_ok; +} + +static rk_s32 write_indent(MppCfgStrBuf *str, const char *caller) +{ + rk_s32 depth; + + cfg_io_dbg_byte("str %p-[%p:%d] write indent %d at %s\n", + str, str->buf, str->buf_size, str->depth, caller); + + depth = str->depth; + if (str->type == MPP_CFG_STR_FMT_TOML) { + depth = depth - 1; + depth = depth >= 0 ? depth : 0; + } + + if (depth) { + char space[17] = " "; + rk_s32 i; + + for (i = 0; i < depth; i++) { + rk_s32 indent_width = 4; + + if (write_byte_f(str, space, &indent_width)) + return rk_nok; + } + } + + return rk_ok; +} + +static rk_s32 revert_comma(MppCfgStrBuf *str, const char *caller) +{ + cfg_io_dbg_byte("str %p-[%p:%d] revert_comma %d at %s\n", + str, str->buf, str->buf_size, str->depth, caller); + + if (str->offset <= 1) { + cfg_io_dbg_byte("str %p offset %d skip revert_comma at %s\n", + str, str->offset, caller); + return rk_ok; + } + + if (str->buf[str->offset - 2] == ',') { + str->buf[str->offset - 2] = str->buf[str->offset - 1]; + str->buf[str->offset - 1] = str->buf[str->offset]; + str->offset--; + } + + return rk_ok; +} + +static rk_s32 mpp_cfg_format_leaf_value(MppCfgIoImpl *impl, char *buf, rk_s32 total) +{ + rk_s32 len = 0; + + switch (impl->type) { + case MPP_CFG_TYPE_NULL : { + len += snprintf(buf + len, total - len, "null"); + } break; + case MPP_CFG_TYPE_BOOL : { + len += snprintf(buf + len, total - len, "%s", impl->val.b1 ? "true" : "false"); + } break; + case MPP_CFG_TYPE_s8 : { + len += snprintf(buf + len, total - len, "%d", impl->val.s8); + } break; + case MPP_CFG_TYPE_u8 : { + len += snprintf(buf + len, total - len, "%u", impl->val.u8); + } break; + case MPP_CFG_TYPE_s16 : { + len += snprintf(buf + len, total - len, "%d", impl->val.s16); + } break; + case MPP_CFG_TYPE_u16 : { + len += snprintf(buf + len, total - len, "%u", impl->val.u16); + } break; + case MPP_CFG_TYPE_s32 : { + len += snprintf(buf + len, total - len, "%d", impl->val.s32); + } break; + case MPP_CFG_TYPE_u32 : { + len += snprintf(buf + len, total - len, "%u", impl->val.u32); + } break; + case MPP_CFG_TYPE_s64 : { + len += snprintf(buf + len, total - len, "%lld", impl->val.s64); + } break; + case MPP_CFG_TYPE_u64 : { + len += snprintf(buf + len, total - len, "%llu", impl->val.u64); + } break; + case MPP_CFG_TYPE_f32 : { + len += snprintf(buf + len, total - len, "%f", impl->val.f32); + } break; + case MPP_CFG_TYPE_f64 : { + len += snprintf(buf + len, total - len, "%lf", impl->val.f64); + } break; + case MPP_CFG_TYPE_STRING : + case MPP_CFG_TYPE_RAW : { + len += snprintf(buf + len, total - len, "\"%s\"", (char *)impl->val.str); + } break; + default : { + mpp_loge("invalid type %d\n", impl->type); + } break; + } + + return len; +} + +static rk_s32 mpp_cfg_to_log(MppCfgIoImpl *impl, MppCfgStrBuf *str) +{ + MppCfgIoImpl *pos, *n; + char buf[256]; + rk_s32 len = 0; + rk_s32 total = sizeof(buf) - 1; + rk_s32 ret = rk_ok; + rk_s32 is_array_elem = impl->parent && impl->parent->type == MPP_CFG_TYPE_ARRAY; + rk_s32 is_array = impl->type == MPP_CFG_TYPE_ARRAY; + rk_s32 skip_indent = 0; /* Flag to skip indent for array elements */ + + /* For simple array elements, skip indent - parent will handle it */ + if (is_array_elem && impl->type < MPP_CFG_TYPE_OBJECT) + skip_indent = 1; + + if (!skip_indent) + write_indent_f(str); + + /* leaf node write once and finish */ + if (impl->type < MPP_CFG_TYPE_OBJECT) { + cfg_io_dbg_to("depth %d leaf write name %s type %d\n", str->depth, impl->name, impl->type); + + if (impl->name && !strstr(impl->name, "array_")) + len += snprintf(buf + len, total - len, "%s : ", impl->name); + + len += mpp_cfg_format_leaf_value(impl, buf + len, total - len); + + /* Add separator: " " for array elements, "\n" for others */ + if (is_array_elem) + len += snprintf(buf + len, total - len, " "); + else + len += snprintf(buf + len, total - len, "\n"); + + return write_byte_f(str, buf, &len); + } + + cfg_io_dbg_to("depth %d branch write name %s type %d\n", str->depth, impl->name, impl->type); + + if (impl->name && !strstr(impl->name, "array_")) + len += snprintf(buf + len, total - len, "%s : ", impl->name); + + if (list_empty(&impl->child)) { + len += snprintf(buf + len, total - len, "%s", + impl->type == MPP_CFG_TYPE_OBJECT ? "{}" : "[]"); + + if (is_array_elem) + len += snprintf(buf + len, total - len, " "); + else + len += snprintf(buf + len, total - len, "\n"); + + return write_byte_f(str, buf, &len); + } + + len += snprintf(buf + len, total - len, "%c\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '{' : '['); + + ret = write_byte_f(str, buf, &len); + if (ret) + return ret; + + str->depth++; + + /* For arrays, track element count to implement line break */ + if (is_array) { + rk_s32 elem_count = 0; + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type); + + /* Add indent for first element, newline + indent every define elements */ + if (pos->type < MPP_CFG_TYPE_OBJECT) { + if (elem_count == 0) { + write_indent_f(str); + } else if (elem_count % CFG_IO_ARRAY_ELEM_COUNT == 0) { + write_byte_f(str, "\n", &(rk_s32) {1}); + write_indent_f(str); + } + } + + ret = mpp_cfg_to_log(pos, str); + if (ret) + break; + elem_count++; + } + } else { + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type); + ret = mpp_cfg_to_log(pos, str); + if (ret) + break; + } + } + + str->depth--; + + /* Add newline before closing bracket for semi-compact format */ + if (str->offset == 0 || str->buf[str->offset - 1] != '\n') + write_byte_f(str, "\n", &(rk_s32) {1}); + write_indent_f(str); + + len += snprintf(buf + len, total - len, "%c\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']'); + + return write_byte_f(str, buf, &len); +} + +static rk_s32 mpp_cfg_to_json(MppCfgIoImpl *impl, MppCfgStrBuf *str) +{ + MppCfgIoImpl *pos, *n; + char buf[256]; + rk_s32 len = 0; + rk_s32 total = sizeof(buf) - 1; + rk_s32 ret = rk_ok; + rk_s32 is_array_elem = impl->parent && impl->parent->type == MPP_CFG_TYPE_ARRAY; + rk_s32 is_array = impl->type == MPP_CFG_TYPE_ARRAY; + rk_s32 skip_indent = 0; /* Flag to skip indent for array elements */ + + /* For simple array elements, skip indent - parent will handle it */ + if (is_array_elem && impl->type < MPP_CFG_TYPE_OBJECT) + skip_indent = 1; + + if (!skip_indent) + write_indent_f(str); + + /* leaf node write once and finish */ + if (impl->type < MPP_CFG_TYPE_OBJECT) { + cfg_io_dbg_to("depth %d leaf write name %s type %d\n", str->depth, impl->name, impl->type); + + if (impl->name && !strstr(impl->name, "array_")) + len += snprintf(buf + len, total - len, "\"%s\" : ", impl->name); + + len += mpp_cfg_format_leaf_value(impl, buf + len, total - len); + + /* Add separator: ",\n" for non-array elements, ", " for array elements */ + if (is_array_elem) + len += snprintf(buf + len, total - len, ", "); + else + len += snprintf(buf + len, total - len, ",\n"); + + return write_byte_f(str, buf, &len); + } + + cfg_io_dbg_to("depth %d branch write name %s type %d\n", str->depth, impl->name, impl->type); + + if (impl->name && !strstr(impl->name, "array_")) + len += snprintf(buf + len, total - len, "\"%s\" : ", impl->name); + + if (list_empty(&impl->child)) { + len += snprintf(buf + len, total - len, "%s", + impl->type == MPP_CFG_TYPE_OBJECT ? "{}" : "[]"); + + if (is_array_elem) + len += snprintf(buf + len, total - len, ", "); + else + len += snprintf(buf + len, total - len, ",\n"); + + return write_byte_f(str, buf, &len); + } + + len += snprintf(buf + len, total - len, "%c\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '{' : '['); + + ret = write_byte_f(str, buf, &len); + if (ret) + return ret; + + str->depth++; + + /* For arrays, track element count to implement line break */ + if (is_array) { + rk_s32 elem_count = 0; + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type); + + /* Add indent for first element, newline + indent every define elements */ + if (pos->type < MPP_CFG_TYPE_OBJECT) { + if (elem_count == 0) { + write_indent_f(str); + } else if (elem_count % CFG_IO_ARRAY_ELEM_COUNT == 0) { + write_byte_f(str, "\n", &(rk_s32) {1}); + write_indent_f(str); + } + } + + ret = mpp_cfg_to_json(pos, str); + if (ret) + break; + elem_count++; + } + } else { + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type); + ret = mpp_cfg_to_json(pos, str); + if (ret) + break; + } + } + + revert_comma_f(str); + + str->depth--; + + /* Add newline before closing bracket for semi-compact format */ + if (str->offset == 0 || str->buf[str->offset - 1] != '\n') + write_byte_f(str, "\n", &(rk_s32) {1}); + write_indent_f(str); + + if (str->depth) + len += snprintf(buf + len, total - len, "%c,\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']'); + else + len += snprintf(buf + len, total - len, "%c\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']'); + + return write_byte_f(str, buf, &len); +} + +static rk_s32 mpp_toml_parent_is_array_table(MppCfgIoImpl *impl, MppCfgStrBuf *str) +{ + return str->depth == 1 && impl->type == MPP_CFG_TYPE_OBJECT && + !impl->name && impl->parent->type == MPP_CFG_TYPE_ARRAY; +} + +static rk_s32 mpp_toml_top(MppCfgIoImpl *impl, MppCfgStrBuf *str) +{ + char buf[256]; + rk_s32 len = 0; + rk_s32 total = sizeof(buf) - 1; + + if (impl->name && !strstr(impl->name, "array_") && impl->type == MPP_CFG_TYPE_OBJECT) + len += snprintf(buf + len, total - len, "\n[%s]\n", impl->name); + + return write_byte_f(str, buf, &len); +} + +static rk_s32 mpp_toml_non_top(MppCfgIoImpl *impl, MppCfgStrBuf *str) +{ + char buf[256]; + rk_s32 len = 0; + rk_s32 total = sizeof(buf) - 1; + + if (impl->name && !strstr(impl->name, "array_")) + len += snprintf(buf + len, total - len, "%s = ", impl->name); + + if (list_empty(&impl->child)) { + len += snprintf(buf + len, total - len, "%s\n", + impl->type == MPP_CFG_TYPE_OBJECT ? "{}" : "[]"); + return write_byte_f(str, buf, &len); + } + + if (mpp_toml_parent_is_array_table(impl, str)) + len += snprintf(buf + len, total - len, "\n[[%s]]\n", impl->parent->name); + else + len += snprintf(buf + len, total - len, "%c\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '{' : '['); + + return write_byte_f(str, buf, &len); +} + +static rk_s32 mpp_cfg_to_toml(MppCfgIoImpl *impl, MppCfgStrBuf *str, rk_s32 first_time) +{ + MppCfgIoImpl *pos, *n; + char buf[256]; + rk_s32 len = 0; + rk_s32 total = sizeof(buf) - 1; + rk_s32 ret = rk_ok; + + write_indent_f(str); + + /* leaf node write once and finish */ + if (impl->type < MPP_CFG_TYPE_OBJECT) { + cfg_io_dbg_to("depth %d leaf write name %s type %d\n", str->depth, impl->name, impl->type); + + if (impl->name && !strstr(impl->name, "array_")) + len += snprintf(buf + len, total - len, "%s = ", impl->name); + + switch (impl->type) { + case MPP_CFG_TYPE_NULL : { + len += snprintf(buf + len, total - len, "null"); + } break; + case MPP_CFG_TYPE_BOOL : { + len += snprintf(buf + len, total - len, "%s", impl->val.b1 ? "true" : "false"); + } break; + case MPP_CFG_TYPE_s8 : { + len += snprintf(buf + len, total - len, "%d", impl->val.s8); + } break; + case MPP_CFG_TYPE_u8 : { + len += snprintf(buf + len, total - len, "%u", impl->val.u8); + } break; + case MPP_CFG_TYPE_s16 : { + len += snprintf(buf + len, total - len, "%d", impl->val.s16); + } break; + case MPP_CFG_TYPE_u16 : { + len += snprintf(buf + len, total - len, "%u", impl->val.u16); + } break; + case MPP_CFG_TYPE_s32 : { + len += snprintf(buf + len, total - len, "%d", impl->val.s32); + } break; + case MPP_CFG_TYPE_u32 : { + len += snprintf(buf + len, total - len, "%u", impl->val.u32); + } break; + case MPP_CFG_TYPE_s64 : { + len += snprintf(buf + len, total - len, "%lld", impl->val.s64); + } break; + case MPP_CFG_TYPE_u64 : { + len += snprintf(buf + len, total - len, "%llu", impl->val.u64); + } break; + case MPP_CFG_TYPE_f32 : { + len += snprintf(buf + len, total - len, "%f", impl->val.f32); + } break; + case MPP_CFG_TYPE_f64 : { + len += snprintf(buf + len, total - len, "%lf", impl->val.f64); + } break; + case MPP_CFG_TYPE_STRING : + case MPP_CFG_TYPE_RAW : { + len += snprintf(buf + len, total - len, "\"%s\"", (char *)impl->val.str); + } break; + default : { + mpp_loge("invalid type %d\n", impl->type); + } break; + } + + if (str->depth > 1) + len += snprintf(buf + len, total - len, ",\n"); + else + len += snprintf(buf + len, total - len, "\n"); + + return write_byte_f(str, buf, &len); + } + + cfg_io_dbg_to("depth %d branch write name %s type %d\n", str->depth, impl->name, impl->type); + + if (str->depth == 0) { + ret = mpp_toml_top(impl, str); + } else { + ret = mpp_toml_non_top(impl, str); + } + if (ret) + return ret; + + if (list_empty(&impl->child)) + return rk_ok; + + if (!mpp_toml_parent_is_array_table(impl, str) && !first_time) + str->depth++; + + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + cfg_io_dbg_to("depth %d child write name %s type %d\n", str->depth, pos->name, pos->type); + ret = mpp_cfg_to_toml(pos, str, 0); + if (ret) + break; + } + + if (str->depth > 1) + revert_comma_f(str); + + if (!mpp_toml_parent_is_array_table(impl, str) && !first_time) + str->depth--; + + write_indent_f(str); + + if (str->depth > 0 && !mpp_toml_parent_is_array_table(impl, str)) { + if (str->depth == 1) + len += snprintf(buf + len, total - len, "%c\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']'); + else + len += snprintf(buf + len, total - len, "%c,\n", + impl->type == MPP_CFG_TYPE_OBJECT ? '}' : ']'); + } + + return write_byte_f(str, buf, &len); +} + +static rk_s32 parse_number(MppCfgStrBuf *str, MppCfgType *type, MppCfgVal *val) +{ + char *buf = NULL; + char tmp[64]; + long double value; + rk_u32 i; + + for (i = 0; i < sizeof(tmp) - 1; i++) { + buf = show_byte_f(str, 0); + if (!buf) + break; + + switch (buf[0]) { + case '0' ... '9' : + case '.' : + case 'e' : + case 'E' : + case '+' : + case '-' : { + tmp[i] = buf[0]; + } break; + default : { + tmp[i] = '\0'; + goto done; + } break; + } + skip_byte_f(str, 1); + } + +done: + if (!i) + return rk_nok; + + errno = 0; + value = strtold(tmp, NULL); + if (errno) { + mpp_loge_f("failed to parse number %s errno %s\n", tmp, strerror(errno)); + return rk_nok; + } + + if (strstr(tmp, ".")) { + if (value >= FLT_MIN && value <= FLT_MAX) { + *type = MPP_CFG_TYPE_f32; + val->f32 = (float)value; + } else { + *type = MPP_CFG_TYPE_f64; + val->f64 = (double)value; + } + } else { + if (value >= INT_MIN && value <= INT_MAX) { + *type = MPP_CFG_TYPE_s32; + val->s32 = (int)value; + } else if (value >= 0 && value <= UINT_MAX) { + *type = MPP_CFG_TYPE_u32; + val->u32 = (unsigned int)value; + } else if (value >= (long double)LLONG_MIN && value <= (long double)LLONG_MAX) { + *type = MPP_CFG_TYPE_u64; + val->u64 = (unsigned long long)value; + } else if (value >= 0 && value <= (long double)ULLONG_MAX) { + *type = MPP_CFG_TYPE_s64; + val->s64 = (long long)value; + } else { + mpp_loge_f("invalid number %s\n", tmp); + return rk_nok; + } + } + + return rk_ok; +} + +static rk_s32 parse_log_string(MppCfgStrBuf *str, char **name, rk_s32 *len, rk_u32 type) +{ + char *buf = NULL; + char *start = NULL; + rk_s32 name_len = 0; + char terminator = (type != 0) ? '\"' : ' '; + + *name = NULL; + *len = 0; + + /* skip whitespace and find first double quotes */ + buf = skip_ws_f(str); + if (!buf) + return -101; + + if (type) { + if (buf[0] != '\"') + return -101; + + buf = skip_byte_f(str, 1); + if (!buf) + return -102; + } + + start = buf; + + /* find the terminator */ + while ((buf = show_byte_f(str, name_len)) && buf[0] != terminator) { + name_len++; + } + + if (!buf || buf[0] != terminator) + return -103; + + /* find complete string skip the string and terminator */ + buf = skip_byte_f(str, name_len + 1); + if (!buf) + return -104; + + *name = start; + *len = name_len; + + return rk_ok; +} + +static rk_s32 parse_log_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str); + +static rk_s32 parse_log_array(MppCfgIoImpl *obj, MppCfgStrBuf *str) +{ + MppCfgIoImpl *parent = obj; + char *buf = NULL; + rk_s32 old = str->offset; + rk_s32 ret = rk_nok; + char arr_name[64] = {0}; + + if (str->depth >= MAX_CFG_DEPTH) { + mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH); + return rk_nok; + } + + parent->array_count = 0; + str->depth++; + + cfg_io_dbg_from("depth %d offset %d array parse start\n", str->depth, str->offset); + + buf = test_byte_f(str, 0); + if (!buf || buf[0] != '[') { + ret = -2; + goto failed; + } + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -3; + goto failed; + } + + /* skip whitespace and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) { + ret = -4; + goto failed; + } + + /* check empty object */ + if (buf[0] == ']') { + skip_byte_f(str, 1); + cfg_io_dbg_from("depth %d found empty array\n", str->depth); + str->depth--; + return rk_ok; + } + + do { + /* find colon for separater */ + buf = skip_ws_f(str); + if (!buf) { + ret = -5; + goto failed; + } + + snprintf(arr_name, sizeof(arr_name), "array_%d", parent->array_count); + /* parse value */ + ret = parse_log_value(parent, arr_name, str); + if (ret) { + ret = -6; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) { + ret = -7; + goto failed; + } + parent->array_count++; + + if (buf[0] == ']') + break; + } while (1); + + if (!buf || buf[0] != ']') { + ret = -9; + goto failed; + } + + skip_byte_f(str, 1); + + cfg_io_dbg_from("depth %d offset %d -> %d array parse success\n", + str->depth, old, str->offset); + + str->depth--; + ret = rk_ok; + +failed: + if (ret) + cfg_io_dbg_from("depth %d offset %d -> %d array parse failed ret %d\n", + str->depth, old, str->offset, ret); + + return ret; +} + +static rk_s32 parse_log_object(MppCfgIoImpl *obj, MppCfgStrBuf *str); + +static rk_s32 parse_log_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str) +{ + MppCfgObj obj = NULL; + char *buf = NULL; + + cfg_io_dbg_from("depth %d offset %d: parse value\n", str->depth, str->offset); + + buf = test_byte_f(str, 4); + if (buf && !strncmp(buf, "null", 4)) { + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_NULL, NULL); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value null\n", str->depth, str->offset); + skip_byte_f(str, 4); + return rk_ok; + } + + if (buf && !strncmp(buf, "true", 4)) { + MppCfgVal val; + + val.b1 = 1; + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value true\n", str->depth, str->offset); + skip_byte_f(str, 4); + return rk_ok; + } + + buf = test_byte_f(str, 5); + if (buf && !strncmp(buf, "false", 5)) { + MppCfgVal val; + + val.b1 = 0; + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value false\n", str->depth, str->offset); + skip_byte_f(str, 5); + return rk_ok; + } + + buf = test_byte_f(str, 0); + if (buf && buf[0] == '\"') { + MppCfgVal val; + char *string = NULL; + rk_s32 len = 0; + + cfg_io_dbg_from("depth %d offset %d: get value string start\n", str->depth, str->offset); + + parse_log_string(str, &string, &len, MPP_CFG_PARSER_TYPE_VALUE); + if (!string) + return rk_nok; + + val.str = dup_str(string, len); + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val); + mpp_cfg_add(parent, obj); + MPP_FREE(val.str); + + cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset); + return rk_ok; + } + + if (buf && (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9'))) { + MppCfgType type; + MppCfgVal val; + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value number start\n", + str->depth, str->offset); + + ret = parse_number(str, &type, &val); + if (ret) + return ret; + + mpp_cfg_get_object(&obj, name, type, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value number success\n", + str->depth, str->offset); + return ret; + } + + if (buf && buf[0] == '{') { + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value object start\n", + str->depth, str->offset); + + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_OBJECT, NULL); + mpp_cfg_add(parent, obj); + + ret = parse_log_object(obj, str); + + cfg_io_dbg_from("depth %d offset %d: get value object ret %d\n", + str->depth, str->offset, ret); + return ret; + } + + if (buf && buf[0] == '[') { + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value array start\n", + str->depth, str->offset); + + mpp_cfg_get_array(&obj, name, 0); + mpp_cfg_add(parent, obj); + + ret = parse_log_array(obj, str); + + cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n", + str->depth, str->offset, ret); + return ret; + } + + return rk_nok; +} + +static rk_s32 parse_log_object(MppCfgIoImpl *obj, MppCfgStrBuf *str) +{ + MppCfgIoImpl *parent = obj; + char *buf = NULL; + rk_s32 old = str->offset; + rk_s32 ret = rk_nok; + + if (str->depth >= MAX_CFG_DEPTH) { + mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH); + return rk_nok; + } + + str->depth++; + + cfg_io_dbg_from("depth %d offset %d object parse start\n", str->depth, str->offset); + + buf = test_byte_f(str, 0); + if (!buf || buf[0] != '{') { + ret = -2; + goto failed; + } + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -3; + goto failed; + } + + /* skip whitespace and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) { + ret = -4; + goto failed; + } + + /* check empty object */ + if (buf[0] == '}') { + skip_byte_f(str, 1); + cfg_io_dbg_from("depth %d found empty object\n", str->depth); + str->depth--; + return rk_ok; + } + + do { + rk_s32 name_len = 0; + char *name = NULL; + char *tmp = NULL; + + /* support array without name */ + if (buf[0] == '[') { + MppCfgObj object = NULL; + + cfg_io_dbg_from("depth %d offset %d: get value array start\n", + str->depth, str->offset); + + mpp_cfg_get_array(&object, NULL, 0); + mpp_cfg_add(parent, object); + + ret = parse_log_array(object, str); + + cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n", + str->depth, str->offset, ret); + + if (ret) { + mpp_cfg_put_all_child(object); + goto failed; + } + + goto __next; + } + + ret = parse_log_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_KEY); + if (ret) { + goto failed; + } + + tmp = dup_str(name, name_len); + cfg_io_dbg_from("depth %d offset %d found object key %s len %d\n", + str->depth, str->offset, tmp, name_len); + MPP_FREE(tmp); + + /* find colon for separater */ + buf = skip_ws_f(str); + if (!buf || buf[0] != ':') { + ret = -5; + goto failed; + } + + /* skip colon */ + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -6; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) { + ret = -7; + goto failed; + } + + tmp = dup_str(name, name_len); + if (!tmp) { + mpp_loge_f("failed to dup name\n"); + ret = -8; + goto failed; + } + + /* parse value */ + ret = parse_log_value(parent, tmp, str); + MPP_FREE(tmp); + if (ret) { + ret = -9; + goto failed; + } + __next: + buf = skip_ws_f(str); + if (!buf) { + ret = -10; + goto failed; + } + + if (buf[0] == '}') + break; + + cfg_io_dbg_from("depth %d offset %d: get next object\n", str->depth, str->offset); + } while (1); + + skip_byte_f(str, 1); + + cfg_io_dbg_from("depth %d offset %d -> %d object parse success\n", + str->depth, old, str->offset); + + str->depth--; + ret = rk_ok; + +failed: + if (ret) + cfg_io_dbg_from("depth %d offset %d -> %d object parse failed ret %d\n", + str->depth, old, str->offset, ret); + + return ret; +} + +static rk_s32 mpp_cfg_from_log(MppCfgObj *obj, MppCfgStrBuf *str) +{ + MppCfgObj object = NULL; + char *buf = NULL; + rk_s32 ret = rk_ok; + + /* skip white space and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) + return rk_nok; + + if (buf[0] == '{') { + ret = mpp_cfg_get_object(&object, NULL, MPP_CFG_TYPE_OBJECT, NULL); + if (ret || !object) { + mpp_loge_f("failed to create top object\n"); + return rk_nok; + } + + ret = parse_log_object(object, str); + } else if (buf[0] == '[') { + ret = mpp_cfg_get_array(&object, NULL, 0); + if (ret || !object) { + mpp_loge_f("failed to create top object\n"); + return rk_nok; + } + + ret = parse_log_array(object, str); + } else { + mpp_loge_f("invalid top element '%c' on offset %d\n", buf[0], str->offset); + } + + *obj = object; + + return ret; +} + +static rk_s32 parse_json_string(MppCfgStrBuf *str, char **name, rk_s32 *len) +{ + char *buf = NULL; + char *start = NULL; + rk_s32 name_len = 0; + + *name = NULL; + *len = 0; + + /* skip whitespace and find first double quotes */ + buf = skip_ws_f(str); + if (!buf || buf[0] != '\"') + return -101; + + buf = skip_byte_f(str, 1); + if (!buf) + return -102; + + start = buf; + + /* find the last double quotes */ + while ((buf = show_byte_f(str, name_len)) && buf[0] != '\"') { + name_len++; + } + + if (!buf || buf[0] != '\"') + return -103; + + /* find complete string skip the string and double quotes */ + buf = skip_byte_f(str, name_len + 1); + if (!buf) + return -104; + + *name = start; + *len = name_len; + + return rk_ok; +} + +static rk_s32 parse_json_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str); +static rk_s32 parse_json_array(MppCfgIoImpl *obj, MppCfgStrBuf *str); + +static rk_s32 parse_json_object(MppCfgIoImpl *obj, MppCfgStrBuf *str) +{ + MppCfgIoImpl *parent = obj; + char *buf = NULL; + rk_s32 old = str->offset; + rk_s32 ret = rk_nok; + + if (str->depth >= MAX_CFG_DEPTH) { + mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH); + return rk_nok; + } + + str->depth++; + + cfg_io_dbg_from("depth %d offset %d object parse start\n", str->depth, str->offset); + + buf = test_byte_f(str, 0); + if (!buf || buf[0] != '{') { + ret = -2; + goto failed; + } + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -3; + goto failed; + } + + /* skip whitespace and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) { + ret = -4; + goto failed; + } + + /* check empty object */ + if (buf[0] == '}') { + skip_byte_f(str, 1); + cfg_io_dbg_from("depth %d found empty object\n", str->depth); + str->depth--; + return rk_ok; + } + + do { + rk_s32 name_len = 0; + char *name = NULL; + char *tmp = NULL; + + if (buf[0] == '[') { + MppCfgObj object = NULL; + + cfg_io_dbg_from("depth %d offset %d: get value array start\n", + str->depth, str->offset); + + mpp_cfg_get_array(&object, NULL, 0); + mpp_cfg_add(parent, object); + + ret = parse_json_array(object, str); + + cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n", + str->depth, str->offset, ret); + + if (ret) { + mpp_cfg_put_all_child(object); + goto failed; + } + + goto __next; + } + + ret = parse_json_string(str, &name, &name_len); + if (ret) { + goto failed; + } + + /* find colon for separater */ + buf = skip_ws_f(str); + if (!buf || buf[0] != ':') { + ret = -5; + goto failed; + } + + /* skip colon */ + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -6; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) { + ret = -7; + goto failed; + } + + tmp = dup_str(name, name_len); + if (!tmp) { + mpp_loge_f("failed to dup name\n"); + ret = -8; + goto failed; + } + + /* parse value */ + ret = parse_json_value(parent, tmp, str); + MPP_FREE(tmp); + if (ret) { + ret = -9; + goto failed; + } + __next: + buf = skip_ws_f(str); + if (!buf) { + ret = -10; + goto failed; + } + + if (buf[0] == ',') { + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -11; + goto failed; + } + + buf = skip_ws_f(str); + if (buf[0] == '}') + break; + + cfg_io_dbg_from("depth %d offset %d: get next object\n", str->depth, str->offset); + continue; + } + + break; + } while (1); + + buf = skip_ws_f(str); + if (!buf || buf[0] != '}') { + ret = -12; + goto failed; + } + + skip_byte_f(str, 1); + + cfg_io_dbg_from("depth %d offset %d -> %d object parse success\n", + str->depth, old, str->offset); + + str->depth--; + ret = rk_ok; + +failed: + if (ret) + cfg_io_dbg_from("depth %d offset %d -> %d object parse failed ret %d\n", + str->depth, old, str->offset, ret); + + return ret; +} + +static rk_s32 parse_json_array(MppCfgIoImpl *obj, MppCfgStrBuf *str) +{ + MppCfgIoImpl *parent = obj; + char *buf = NULL; + rk_s32 old = str->offset; + rk_s32 ret = rk_nok; + char arr_name[64] = {0}; + + if (str->depth >= MAX_CFG_DEPTH) { + mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH); + return rk_nok; + } + + parent->array_count = 0; + str->depth++; + + cfg_io_dbg_from("depth %d offset %d array parse start\n", str->depth, str->offset); + + buf = test_byte_f(str, 0); + if (!buf || buf[0] != '[') { + ret = -2; + goto failed; + } + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -3; + goto failed; + } + + /* skip whitespace and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) { + ret = -4; + goto failed; + } + + /* check empty object */ + if (buf[0] == ']') { + skip_byte_f(str, 1); + cfg_io_dbg_from("depth %d found empty array\n", str->depth); + str->depth--; + return rk_ok; + } + + do { + /* find colon for separater */ + buf = skip_ws_f(str); + if (!buf) { + ret = -5; + goto failed; + } + + snprintf(arr_name, sizeof(arr_name), "array_%d", parent->array_count); + + /* parse value */ + ret = parse_json_value(parent, arr_name, str); + if (ret) { + ret = -6; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) { + ret = -7; + goto failed; + } + + if (buf[0] == ',') { + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -8; + goto failed; + } + + buf = skip_ws_f(str); + if (buf[0] == '}') + break; + + cfg_io_dbg_from("depth %d offset %d: get next array\n", str->depth, str->offset); + parent->array_count++; + continue; + } + break; + } while (1); + + buf = skip_ws_f(str); + if (!buf || buf[0] != ']') { + ret = -9; + goto failed; + } + + skip_byte_f(str, 1); + + cfg_io_dbg_from("depth %d offset %d -> %d array parse success\n", + str->depth, old, str->offset); + + str->depth--; + ret = rk_ok; + +failed: + if (ret) + cfg_io_dbg_from("depth %d offset %d -> %d array parse failed ret %d\n", + str->depth, old, str->offset, ret); + + return ret; +} + +static rk_s32 parse_json_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str) +{ + MppCfgObj obj = NULL; + char *buf = NULL; + + cfg_io_dbg_from("depth %d offset %d: parse value\n", str->depth, str->offset); + + buf = test_byte_f(str, 4); + if (buf && !strncmp(buf, "null", 4)) { + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_NULL, NULL); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value null\n", str->depth, str->offset); + skip_byte_f(str, 4); + return rk_ok; + } + + if (buf && !strncmp(buf, "true", 4)) { + MppCfgVal val; + + val.b1 = 1; + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value true\n", str->depth, str->offset); + skip_byte_f(str, 4); + return rk_ok; + } + + buf = test_byte_f(str, 5); + if (buf && !strncmp(buf, "false", 5)) { + MppCfgVal val; + + val.b1 = 0; + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value false\n", str->depth, str->offset); + skip_byte_f(str, 5); + return rk_ok; + } + + buf = test_byte_f(str, 0); + if (buf && buf[0] == '\"') { + MppCfgVal val; + char *string = NULL; + rk_s32 len = 0; + + cfg_io_dbg_from("depth %d offset %d: get value string start\n", str->depth, str->offset); + + parse_json_string(str, &string, &len); + if (!string) + return rk_nok; + + val.str = dup_str(string, len); + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val); + mpp_cfg_add(parent, obj); + MPP_FREE(val.str); + + cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset); + return rk_ok; + } + + if (buf && (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9'))) { + MppCfgType type; + MppCfgVal val; + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value number start\n", + str->depth, str->offset); + + ret = parse_number(str, &type, &val); + if (ret) + return ret; + + mpp_cfg_get_object(&obj, name, type, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value number success\n", + str->depth, str->offset); + return ret; + } + + if (buf && buf[0] == '{') { + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value object start\n", + str->depth, str->offset); + + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_OBJECT, NULL); + mpp_cfg_add(parent, obj); + + ret = parse_json_object(obj, str); + + cfg_io_dbg_from("depth %d offset %d: get value object ret %d\n", + str->depth, str->offset, ret); + return ret; + } + + if (buf && buf[0] == '[') { + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value array start\n", + str->depth, str->offset); + + mpp_cfg_get_array(&obj, name, 0); + mpp_cfg_add(parent, obj); + + ret = parse_json_array(obj, str); + + cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n", + str->depth, str->offset, ret); + return ret; + } + + return rk_nok; +} + +static rk_s32 mpp_cfg_from_json(MppCfgObj *obj, MppCfgStrBuf *str) +{ + MppCfgObj object = NULL; + char *buf = NULL; + rk_s32 ret = rk_ok; + + /* skip UTF-8 */ + buf = test_byte_f(str, 4); + if (buf && !strncmp(buf, "\xEF\xBB\xBF", 3)) + skip_byte_f(str, 3); + + /* skip white space and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) + return rk_nok; + + if (buf[0] == '{') { + ret = mpp_cfg_get_object(&object, NULL, MPP_CFG_TYPE_OBJECT, NULL); + if (ret || !object) { + mpp_loge_f("failed to create top object\n"); + return rk_nok; + } + + ret = parse_json_object(object, str); + } else if (buf[0] == '[') { + ret = mpp_cfg_get_array(&object, NULL, 0); + if (ret || !object) { + mpp_loge_f("failed to create top object\n"); + return rk_nok; + } + + ret = parse_json_array(object, str); + } else { + mpp_loge_f("invalid top element '%c' on offset %d\n", buf[0], str->offset); + } + + *obj = object; + + return ret; +} + +static rk_s32 parse_toml_nested_table(MppCfgIoImpl *root, MppCfgObj *object, char *name, + rk_s32 name_len) +{ + MppCfgObj obj = NULL; + MppCfgIoImpl *parent = root; + rk_s32 i = 0; + char sub_name_offset = 0; + char sub_name_len = 0; + char sub_name[256] = {0}; + rk_s32 ret = rk_ok; + + for (i = 0; i <= name_len; i++) { + if (name[i] == '.' || name[i] == '\0') { + sub_name_len = i; + memcpy(sub_name, name, sub_name_len); + sub_name[i] = '\0'; + obj = NULL; + mpp_cfg_find(&obj, root, sub_name, MPP_CFG_STR_FMT_TOML); + if (!obj) { + memcpy(sub_name, name + sub_name_offset, sub_name_len - sub_name_offset); + sub_name[sub_name_len - sub_name_offset] = '\0'; + ret = mpp_cfg_get_object(&obj, sub_name, MPP_CFG_TYPE_OBJECT, NULL); + if (ret || !obj) { + mpp_loge_f("failed to create object %s\n", name); + ret = -101; + return ret; + } + mpp_cfg_add(parent, obj); + } + + parent = obj; + sub_name_offset = i + 1; + } + } + + *object = obj; + + return ret; +} + +static rk_s32 parse_toml_nested_array_table(MppCfgIoImpl *root, MppCfgObj *object, char *name, + rk_s32 name_len) +{ + MppCfgObj obj = NULL; + MppCfgIoImpl *parent = root; + rk_s32 i = 0; + char sub_name_offset = 0; + char sub_name_len = 0; + char sub_name[256] = {0}; + rk_s32 ret = rk_ok; + + for (i = 0; i <= name_len; i++) { + if (name[i] == '.' || name[i] == '\0') { + sub_name_len = i; + memcpy(sub_name, name, sub_name_len); + sub_name[i] = '\0'; + obj = NULL; + mpp_cfg_find(&obj, root, sub_name, MPP_CFG_STR_FMT_TOML); + if (!obj) { + memcpy(sub_name, name + sub_name_offset, sub_name_len - sub_name_offset); + sub_name[sub_name_len - sub_name_offset] = '\0'; + + /* if parent type is array, need get its last child as new parent */ + if (parent->type == MPP_CFG_TYPE_ARRAY) { + MppCfgIoImpl *child_pos, *child_n; + MppCfgIoImpl *last_child = NULL; + list_for_each_entry_safe(child_pos, child_n, &parent->child, MppCfgIoImpl, list) { + if (!child_pos->name && child_pos->type == MPP_CFG_TYPE_OBJECT) { + last_child = child_pos; + } + } + if (!last_child) { + mpp_loge_f("failed to find last child\n"); + ret = -111; + return ret; + } + parent = last_child; + } + if (name[i] == '\0') { + ret = mpp_cfg_get_array(&obj, sub_name, 0); + if (ret || !obj) { + mpp_loge_f("failed to create object %s\n", name); + ret = -112; + return ret; + } + mpp_cfg_add(parent, obj); + } else { + ret = mpp_cfg_get_object(&obj, sub_name, MPP_CFG_TYPE_OBJECT, NULL); + if (ret || !obj) { + mpp_loge_f("failed to create nested object %s\n", name); + ret = -113; + return ret; + } + mpp_cfg_add(parent, obj); + } + } + + parent = obj; + sub_name_offset = i + 1; + } + } + + *object = obj; + + return ret; +} + +static rk_s32 parse_toml_string(MppCfgStrBuf *str, char **name, rk_s32 *len, rk_u32 type) +{ + char *buf = NULL; + char *start = NULL; + rk_s32 name_len = 0; + char terminator; + + *name = NULL; + *len = 0; + + /* skip whitespace and find first double quotes */ + buf = skip_ws_f(str); + if (!buf) + return -201; + + if (type == MPP_CFG_PARSER_TYPE_VALUE) { + terminator = '\"'; + if (buf[0] != '\"') + return -202; + + buf = skip_byte_f(str, 1); + if (!buf) + return -203; + } else if (type == MPP_CFG_PARSER_TYPE_KEY) { + terminator = ' '; + } else if (type == MPP_CFG_PARSER_TYPE_TABLE || type == MPP_CFG_PARSER_TYPE_ARRAY_TABLE) { + terminator = ']'; + } else { + return -204; + } + + start = buf; + + /* find the terminator */ + while ((buf = show_byte_f(str, name_len)) && buf[0] != terminator) { + name_len++; + } + + if (!buf || buf[0] != terminator) + return -205; + + /* find complete string skip the string */ + if (type == MPP_CFG_PARSER_TYPE_VALUE) + buf = skip_byte_f(str, name_len + 1); + else + buf = skip_byte_f(str, name_len); + if (!buf) + return -206; + + *name = start; + *len = name_len; + + return rk_ok; +} + +static rk_s32 parse_toml_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str); +static rk_s32 parse_toml_object(MppCfgIoImpl *parent, MppCfgStrBuf *str, rk_s32 is_brace); + +static rk_s32 parse_toml_array(MppCfgIoImpl *obj, MppCfgStrBuf *str) +{ + MppCfgIoImpl *parent = obj; + char *buf = NULL; + rk_s32 old = str->offset; + rk_s32 ret = rk_nok; + char arr_name[64] = {0}; + + if (str->depth >= MAX_CFG_DEPTH) { + mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH); + return rk_nok; + } + + parent->array_count = 0; + str->depth++; + + cfg_io_dbg_from("depth %d offset %d array parse start\n", str->depth, str->offset); + + buf = test_byte_f(str, 0); + if (!buf || buf[0] != '[') { + ret = -61; + goto failed; + } + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -62; + goto failed; + } + + /* skip whitespace and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) { + ret = -63; + goto failed; + } + + /* check empty object */ + if (buf[0] == ']') { + skip_byte_f(str, 1); + cfg_io_dbg_from("depth %d found empty array\n", str->depth); + str->depth--; + return rk_ok; + } + + do { + buf = skip_ws_f(str); + if (!buf) { + ret = -64; + goto failed; + } + + snprintf(arr_name, sizeof(arr_name), "array_%d", parent->array_count); + /* parse value */ + ret = parse_toml_value(parent, arr_name, str); + if (ret) { + ret = -65; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) { + ret = -66; + goto failed; + } + + if (buf[0] == ',') { + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -67; + goto failed; + } + + buf = skip_ws_f(str); + if (buf[0] == '}') + break; + + cfg_io_dbg_from("depth %d offset %d: get next array\n", str->depth, str->offset); + parent->array_count++; + continue; + } + break; + } while (1); + + if (!buf || buf[0] != ']') { + ret = -68; + goto failed; + } + + skip_byte_f(str, 1); + + cfg_io_dbg_from("depth %d offset %d -> %d array parse success\n", + str->depth, old, str->offset); + + str->depth--; + ret = rk_ok; + +failed: + if (ret) + cfg_io_dbg_from("depth %d offset %d -> %d array parse failed ret %d\n", + str->depth, old, str->offset, ret); + + return ret; +} + +static rk_s32 parse_toml_value(MppCfgIoImpl *parent, const char *name, MppCfgStrBuf *str) +{ + MppCfgObj obj = NULL; + char *buf = NULL; + + cfg_io_dbg_from("depth %d offset %d: parse value\n", str->depth, str->offset); + + buf = test_byte_f(str, 4); + if (buf && !strncmp(buf, "null", 4)) { + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_NULL, NULL); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value null\n", str->depth, str->offset); + skip_byte_f(str, 4); + return rk_ok; + } + + if (buf && !strncmp(buf, "true", 4)) { + MppCfgVal val; + + val.b1 = 1; + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value true\n", str->depth, str->offset); + skip_byte_f(str, 4); + return rk_ok; + } + + buf = test_byte_f(str, 5); + if (buf && !strncmp(buf, "false", 5)) { + MppCfgVal val; + + val.b1 = 0; + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_BOOL, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value false\n", str->depth, str->offset); + skip_byte_f(str, 5); + return rk_ok; + } + + buf = test_byte_f(str, 3); + if (buf && !strncmp(buf, "\"\"\"", 3)) { + MppCfgVal val; + char *string = NULL; + rk_s32 len = 0; + + skip_byte_f(str, 2); + cfg_io_dbg_from("depth %d offset %d: get value multi line string start\n", str->depth, str->offset); + + parse_toml_string(str, &string, &len, MPP_CFG_PARSER_TYPE_VALUE); + if (!string) + return rk_nok; + buf = test_byte_f(str, 1); + if (!buf || strncmp(buf, "\"\"", 2)) { + return rk_nok; + } + skip_byte_f(str, 2); + + val.str = dup_str(string, len); + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val); + mpp_cfg_add(parent, obj); + MPP_FREE(val.str); + + cfg_io_dbg_from("depth %d offset %d: get value multi line string success\n", str->depth, str->offset); + return rk_ok; + } + + buf = test_byte_f(str, 0); + if (buf && buf[0] == '\"') { + MppCfgVal val; + char *string = NULL; + rk_s32 len = 0; + + cfg_io_dbg_from("depth %d offset %d: get value string start\n", str->depth, str->offset); + + parse_toml_string(str, &string, &len, MPP_CFG_PARSER_TYPE_VALUE); + if (!string) + return rk_nok; + + val.str = dup_str(string, len); + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_STRING, &val); + mpp_cfg_add(parent, obj); + MPP_FREE(val.str); + + cfg_io_dbg_from("depth %d offset %d: get value string success\n", str->depth, str->offset); + return rk_ok; + } + + if (buf && (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9'))) { + MppCfgType type; + MppCfgVal val; + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value number start\n", + str->depth, str->offset); + + ret = parse_number(str, &type, &val); + if (ret) + return ret; + + mpp_cfg_get_object(&obj, name, type, &val); + mpp_cfg_add(parent, obj); + + cfg_io_dbg_from("depth %d offset %d: get value number success\n", + str->depth, str->offset); + return ret; + } + + if (buf && buf[0] == '{') { + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value object start\n", + str->depth, str->offset); + + mpp_cfg_get_object(&obj, name, MPP_CFG_TYPE_OBJECT, NULL); + mpp_cfg_add(parent, obj); + + ret = parse_toml_object(obj, str, 1); + + cfg_io_dbg_from("depth %d offset %d: get value object ret %d\n", + str->depth, str->offset, ret); + return ret; + } + + if (buf && buf[0] == '[') { + rk_s32 ret; + + cfg_io_dbg_from("depth %d offset %d: get value array start\n", + str->depth, str->offset); + + mpp_cfg_get_array(&obj, name, 0); + mpp_cfg_add(parent, obj); + + ret = parse_toml_array(obj, str); + + cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n", + str->depth, str->offset, ret); + return ret; + } + + return rk_nok; +} + +static rk_s32 parse_toml_object(MppCfgIoImpl *parent, MppCfgStrBuf *str, rk_s32 is_brace) +{ + char *buf = NULL; + rk_s32 ret = rk_nok; + rk_s32 old = str->offset; + + if (str->depth >= MAX_CFG_DEPTH) { + mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH); + return rk_nok; + } + + str->depth++; + /* skip whitespace and check the end of buffer */ + if (is_brace) { + buf = test_byte_f(str, 0); + if (!buf || buf[0] != '{') { + ret = -31; + goto failed; + } + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -32; + goto failed; + } + + /* skip whitespace and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) { + ret = -33; + goto failed; + } + + /* check empty object */ + if (buf[0] == '}') { + skip_byte_f(str, 1); + cfg_io_dbg_from("depth %d found empty object\n", str->depth); + str->depth--; + return rk_ok; + } + } else { + buf = skip_ws_f(str); + if (!buf) { + ret = -34; + goto failed; + } + } + + do { + rk_s32 name_len = 0; + char *name = NULL; + char *tmp = NULL; + + if (buf[0] == '[') { + MppCfgObj object = NULL; + + cfg_io_dbg_from("depth %d offset %d: get value array start\n", + str->depth, str->offset); + + mpp_cfg_get_array(&object, NULL, 0); + mpp_cfg_add(parent, object); + + ret = parse_toml_array(object, str); + + cfg_io_dbg_from("depth %d offset %d: get value array ret %d\n", + str->depth, str->offset, ret); + + if (ret) { + mpp_cfg_put_all_child(object); + goto failed; + } + + goto __next; + } + + ret = parse_toml_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_KEY); + if (ret) { + ret = -35; + goto failed; + } + + /* find equal for separater */ + buf = skip_ws_f(str); + if (!buf || buf[0] != '=') { + ret = -36; + goto failed; + } + + /* skip equal */ + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -37; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) { + ret = -38; + goto failed; + } + + tmp = dup_str(name, name_len); + if (!tmp) { + mpp_loge_f("failed to dup name\n"); + ret = -39; + goto failed; + } + + /* parse value */ + ret = parse_toml_value(parent, tmp, str); + MPP_FREE(tmp); + if (ret) { + ret = -40; + goto failed; + } + __next: + buf = skip_ws_f(str); + if (!buf || buf[0] == '[' || buf[0] == '}') + break; + + if (buf[0] == ',') { + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -41; + goto failed; + } + + buf = skip_ws_f(str); + if (buf[0] == '[' || buf[0] == '}') + break; + + cfg_io_dbg_from("depth %d offset %d: get next object\n", str->depth, str->offset); + } + } while (1); + + if (is_brace) { + if (buf && buf[0] == '}') + skip_byte_f(str, 1); + else { + ret = -42; + goto failed; + } + } + + cfg_io_dbg_from("depth %d offset %d -> %d object parse success\n", + str->depth, old, str->offset); + + str->depth--; + ret = rk_ok; + +failed: + if (ret) + cfg_io_dbg_from("depth %d offset %d -> %d object parse failed ret %d\n", + str->depth, old, str->offset, ret); + + return ret; +} + +static rk_s32 parse_toml_table(MppCfgIoImpl *parent, MppCfgStrBuf *str) +{ + MppCfgObj obj = NULL; + char *buf = NULL; + rk_s32 ret = rk_nok; + rk_s32 name_len = 0; + char *name = NULL; + char *tmp = NULL; + + ret = parse_toml_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_TABLE); + if (ret) { + ret = -11; + goto failed; + } + + tmp = dup_str(name, name_len); + if (!tmp) { + mpp_loge_f("failed to dup tmp\n"); + ret = -12; + goto failed; + } + + if (strchr(tmp, '.')) { + ret = parse_toml_nested_table(parent, &obj, tmp, name_len); + MPP_FREE(tmp); + if (ret || !obj) { + return ret; + } + } else { + ret = mpp_cfg_get_object(&obj, tmp, MPP_CFG_TYPE_OBJECT, NULL); + MPP_FREE(tmp); + if (ret || !obj) { + mpp_loge_f("failed to create object %s\n", tmp); + ret = -13; + goto failed; + } + mpp_cfg_add(parent, obj); + } + + buf = test_byte_f(str, 0); + if (!buf || buf[0] != ']') { + ret = -14; + goto failed; + } + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -15; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) + return rk_nok; + + if (buf[0] == '[') + ret = rk_ok; + else + ret = parse_toml_object(obj, str, 0); + +failed: + if (ret) + cfg_io_dbg_from("table parse failed ret %d\n", ret); + + return ret; +} + +static rk_s32 parse_toml_array_table(MppCfgIoImpl *parent, MppCfgStrBuf *str) +{ + MppCfgObj obj = NULL; + char *buf = NULL; + rk_s32 ret = rk_nok; + rk_s32 name_len = 0; + char *name = NULL; + char *tmp = NULL; + + ret = parse_toml_string(str, &name, &name_len, MPP_CFG_PARSER_TYPE_ARRAY_TABLE); + if (ret) { + ret = -22; + goto failed; + } + + tmp = dup_str(name, name_len); + if (!tmp) { + mpp_loge_f("failed to dup tmp\n"); + ret = -23; + goto failed; + } + + if (strchr(tmp, '.')) { + ret = parse_toml_nested_array_table(parent, &obj, tmp, name_len); + MPP_FREE(tmp); + if (ret || !obj) { + return ret; + } + } else { + mpp_cfg_find(&obj, parent, tmp, MPP_CFG_STR_FMT_TOML); + if (!obj) { + ret = mpp_cfg_get_array(&obj, tmp, 0); + MPP_FREE(tmp); + if (ret || !obj) { + mpp_loge_f("failed to create object %s\n", tmp); + ret = -24; + goto failed; + } + mpp_cfg_add(parent, obj); + } else { + MPP_FREE(tmp); + } + } + + /* array object need create object as child */ + parent = obj; + obj = NULL; + mpp_cfg_get_object(&obj, NULL, MPP_CFG_TYPE_OBJECT, NULL); + mpp_cfg_add(parent, obj); + + buf = test_byte_f(str, 1); + if (!buf || strncmp(buf, "]]", 2)) { + ret = -25; + goto failed; + } + + buf = skip_byte_f(str, 2); + if (!buf) { + ret = -26; + goto failed; + } + + buf = skip_ws_f(str); + if (!buf) + return rk_nok; + + if (buf[0] == '[') + ret = rk_ok; + else + ret = parse_toml_object(obj, str, 0); + +failed: + if (ret) + cfg_io_dbg_from("array table parse failed ret %d\n", ret); + return ret; +} + +static rk_s32 parse_toml_section(MppCfgIoImpl *parent, MppCfgStrBuf *str) +{ + char *buf = NULL; + rk_s32 ret = rk_nok; + rk_s32 old = str->offset; + + if (str->depth >= MAX_CFG_DEPTH) { + mpp_loge_f("depth %d reached max\n", MAX_CFG_DEPTH); + return rk_nok; + } + + buf = test_byte_f(str, 0); + if (!buf) { + ret = -2; + goto failed; + } + + if (buf[0] == '[') { + str->depth++; + + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -3; + goto failed; + } + if (buf[0] != '[') { + ret = parse_toml_table(parent, str); + if (ret) + goto failed; + } else { + buf = skip_byte_f(str, 1); + if (!buf) { + ret = -4; + goto failed; + } + + ret = parse_toml_array_table(parent, str); + if (ret) + goto failed; + } + str->depth--; + } else { + ret = parse_toml_object(parent, str, 0); + if (ret) + goto failed; + } + cfg_io_dbg_from("depth %d offset %d -> %d section parse success\n", + str->depth, old, str->offset); + + ret = rk_ok; + +failed: + if (ret) + cfg_io_dbg_from("depth %d offset %d -> %d section parse failed ret %d\n", + str->depth, old, str->offset, ret); + + return ret; +} + +static rk_s32 mpp_cfg_from_toml(MppCfgObj *obj, MppCfgStrBuf *str) +{ + MppCfgObj object = NULL; + char *buf = NULL; + rk_s32 ret = rk_ok; + + /* skip white space and check the end of buffer */ + buf = skip_ws_f(str); + if (!buf) + return rk_nok; + + ret = mpp_cfg_get_object(&object, NULL, MPP_CFG_TYPE_OBJECT, NULL); + if (ret || !object) { + mpp_loge_f("failed to create top object\n"); + return rk_nok; + } + + do { + /* parse section */ + ret = parse_toml_section(object, str); + if (ret) { + mpp_loge_f("failed to parse section, ret : %d.\n", ret); + return rk_nok; + } + + buf = skip_ws_f(str); + if (!buf) + break; + } while (1); + + *obj = object; + + return ret; +} + +void mpp_cfg_dump(MppCfgObj obj, const char *func) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + MppCfgStrBuf str; + rk_s32 ret; + + if (!obj) { + mpp_loge_f("invalid param obj %p at %s\n", obj, func); + return; + } + + mpp_logi_f("obj %s - %p at %s\n", impl->name ? impl->name : "n/a", impl, func); + + str.buf_size = 4096; + str.buf = mpp_malloc_size(void, str.buf_size); + str.offset = 0; + str.depth = 0; + str.type = MPP_CFG_STR_FMT_LOG; + + ret = mpp_cfg_to_log(impl, &str); + if (ret) + mpp_loge_f("failed to get log buffer\n"); + else + mpp_cfg_print_string(str.buf); + + MPP_FREE(str.buf); +} + +rk_s32 mpp_cfg_to_string(MppCfgObj obj, MppCfgStrFmt fmt, char **buf) +{ + MppCfgIoImpl *impl = (MppCfgIoImpl *)obj; + MppCfgStrBuf str; + rk_s32 ret = rk_nok; + + if (!obj || !buf || fmt >= MPP_CFG_STR_FMT_BUTT) { + mpp_loge_f("invalid param obj %p fmt %d buf %p\n", obj, fmt, buf); + return ret; + } + + mpp_env_get_u32("mpp_cfg_io_debug", &mpp_cfg_io_debug, mpp_cfg_io_debug); + + str.buf_size = 4096; + str.buf = mpp_malloc_size(void, str.buf_size); + str.offset = 0; + str.depth = 0; + str.type = fmt; + + switch (fmt) { + case MPP_CFG_STR_FMT_LOG : { + ret = mpp_cfg_to_log(impl, &str); + } break; + case MPP_CFG_STR_FMT_JSON : { + ret = mpp_cfg_to_json(impl, &str); + } break; + case MPP_CFG_STR_FMT_TOML : { + ret = mpp_cfg_to_toml(impl, &str, 1); + } break; + default : { + mpp_loge_f("invalid formoffset %d\n", fmt); + } break; + } + + if (ret) { + mpp_loge_f("%p %s failed to get string buffer\n", impl, impl->name); + MPP_FREE(str.buf); + } + + *buf = str.buf; + return ret; +} + +rk_s32 mpp_cfg_from_string(MppCfgObj *obj, MppCfgStrFmt fmt, const char *buf) +{ + MppCfgObj object = NULL; + rk_s32 size; + rk_s32 ret = rk_nok; + + if (!obj || fmt >= MPP_CFG_STR_FMT_BUTT || !buf) { + mpp_loge_f("invalid param obj %p fmt %d buf %p\n", obj, fmt, buf); + return ret; + } + + mpp_env_get_u32("mpp_cfg_io_debug", &mpp_cfg_io_debug, mpp_cfg_io_debug); + + size = strlen(buf); + if (size) { + MppCfgStrBuf str; + + size++; + + str.buf = (char *)buf; + str.buf_size = size; + str.offset = 0; + str.depth = 0; + str.type = fmt; + + cfg_io_dbg_from("buf %p size %d\n", buf, size); + cfg_io_dbg_from("%s", buf); + + switch (fmt) { + case MPP_CFG_STR_FMT_LOG : { + ret = mpp_cfg_from_log(&object, &str); + } break; + case MPP_CFG_STR_FMT_JSON : { + ret = mpp_cfg_from_json(&object, &str); + } break; + case MPP_CFG_STR_FMT_TOML : { + ret = mpp_cfg_from_toml(&object, &str); + } break; + default : { + mpp_loge_f("invalid formoffset %d\n", fmt); + } break; + } + } + + if (ret) + mpp_loge_f("buf %p size %d failed to get object\n", buf, size); + + *obj = object; + return ret; +} + +static void write_struct(MppCfgIoImpl *obj, MppTrie trie, MppCfgStrBuf *str, void *st) +{ + KmppEntry *tbl = NULL; + + if (obj->name) { + MppTrieInfo *info = NULL; + + /* use string to index the location table */ + get_full_name(obj, str->buf, str->buf_size); + + info = mpp_trie_get_info(trie, str->buf); + if (info) + tbl = mpp_trie_info_ctx(info); + } + + if (!tbl) + tbl = &obj->entry; + + cfg_io_dbg_show("depth %d obj type %s name %s -> info %s offset %d size %d\n", + obj->depth, strof_type(obj->type), obj->name ? str->buf : "null", + strof_elem_type(tbl->tbl.elem_type), tbl->tbl.elem_offset, tbl->tbl.elem_size); + + if (tbl->tbl.elem_type < ELEM_TYPE_BUTT) { + switch (tbl->tbl.elem_type) { + case ELEM_TYPE_s8 : { + kmpp_obj_impl_set_s8(tbl, st, obj->val.s8); + } break; + case ELEM_TYPE_u8 : { + kmpp_obj_impl_set_u8(tbl, st, obj->val.u8); + } break; + case ELEM_TYPE_s16 : { + kmpp_obj_impl_set_s16(tbl, st, obj->val.s16); + } break; + case ELEM_TYPE_u16 : { + kmpp_obj_impl_set_u16(tbl, st, obj->val.u16); + } break; + case ELEM_TYPE_s32 : { + kmpp_obj_impl_set_s32(tbl, st, obj->val.s32); + } break; + case ELEM_TYPE_u32 : { + kmpp_obj_impl_set_u32(tbl, st, obj->val.u32); + } break; + case ELEM_TYPE_s64 : { + kmpp_obj_impl_set_s64(tbl, st, obj->val.s64); + } break; + case ELEM_TYPE_u64 : { + kmpp_obj_impl_set_u64(tbl, st, obj->val.u64); + } break; + default : { + } break; + } + } + + { + MppCfgIoImpl *pos, *n; + + list_for_each_entry_safe(pos, n, &obj->child, MppCfgIoImpl, list) { + write_struct(pos, trie, str, st); + } + } +} + +rk_s32 mpp_cfg_to_struct(MppCfgObj obj, MppCfgObj type, void *st) +{ + MppCfgIoImpl *orig; + MppCfgIoImpl *impl; + MppTrie trie; + MppCfgStrBuf str; + char name[256] = { 0 }; + + if (!obj || !st) { + mpp_loge_f("invalid param obj %p st %p\n", obj, st); + return rk_nok; + } + + impl = (MppCfgIoImpl *)obj; + orig = (MppCfgIoImpl *)type; + trie = mpp_cfg_to_trie(orig); + + str.buf = name; + str.buf_size = sizeof(name) - 1; + str.offset = 0; + str.depth = 0; + + write_struct(impl, trie, &str, st + orig->entry.tbl.elem_offset); + + return rk_ok; +} + +static MppCfgObj read_struct(MppCfgIoImpl *impl, MppCfgObj parent, void *st) +{ + KmppEntry *entry = &impl->entry; + MppCfgIoImpl *ret = NULL; + + /* dup node first */ + ret = mpp_calloc_size(MppCfgIoImpl, impl->buf_size); + if (!ret) { + mpp_loge_f("failed to alloc impl size %d\n", impl->buf_size); + return NULL; + } + + INIT_LIST_HEAD(&ret->list); + INIT_LIST_HEAD(&ret->child); + + ret->type = impl->type; + ret->buf_size = impl->buf_size; + + if (impl->name_buf_len) { + ret->name = (char *)(ret + 1); + memcpy(ret->name, impl->name, impl->name_buf_len); + ret->name_len = impl->name_len; + ret->name_buf_len = impl->name_buf_len; + } + + /* assign value by different type */ + switch (entry->tbl.elem_type) { + case ELEM_TYPE_s8 : + case ELEM_TYPE_u8 : + case ELEM_TYPE_s16 : + case ELEM_TYPE_u16 : + case ELEM_TYPE_s32 : + case ELEM_TYPE_u32 : + case ELEM_TYPE_s64 : + case ELEM_TYPE_u64 : { + switch (entry->tbl.elem_type) { + case ELEM_TYPE_s8 : { + mpp_assert(impl->type == MPP_CFG_TYPE_s8); + kmpp_obj_impl_get_s8(entry, st, &ret->val.s8); + } break; + case ELEM_TYPE_u8 : { + mpp_assert(impl->type == MPP_CFG_TYPE_u8); + kmpp_obj_impl_get_u8(entry, st, &ret->val.u8); + } break; + case ELEM_TYPE_s16 : { + mpp_assert(impl->type == MPP_CFG_TYPE_s16); + kmpp_obj_impl_get_s16(entry, st, &ret->val.s16); + } break; + case ELEM_TYPE_u16 : { + mpp_assert(impl->type == MPP_CFG_TYPE_u16); + kmpp_obj_impl_get_u16(entry, st, &ret->val.u16); + } break; + case ELEM_TYPE_s32 : { + mpp_assert(impl->type == MPP_CFG_TYPE_s32); + kmpp_obj_impl_get_s32(entry, st, &ret->val.s32); + } break; + case ELEM_TYPE_u32 : { + mpp_assert(impl->type == MPP_CFG_TYPE_u32); + kmpp_obj_impl_get_u32(entry, st, &ret->val.u32); + } break; + case ELEM_TYPE_s64 : { + mpp_assert(impl->type == MPP_CFG_TYPE_s64); + kmpp_obj_impl_get_s64(entry, st, &ret->val.s64); + } break; + case ELEM_TYPE_u64 : { + mpp_assert(impl->type == MPP_CFG_TYPE_u64); + kmpp_obj_impl_get_u64(entry, st, &ret->val.u64); + } break; + default : { + } break; + } + } break; + case ELEM_TYPE_st : + case ELEM_TYPE_arr : + case ELEM_TYPE_ptr : { + ret->val = impl->val; + } break; + default : { + } break; + } + + cfg_io_dbg_show("depth %d obj type %s name %s\n", ret->depth, + strof_type(ret->type), ret->name); + + if (parent) + mpp_cfg_add(parent, ret); + + { + MppCfgIoImpl *pos, *n; + + list_for_each_entry_safe(pos, n, &impl->child, MppCfgIoImpl, list) { + read_struct(pos, ret, st); + } + } + + return ret; +} + +rk_s32 mpp_cfg_from_struct(MppCfgObj *obj, MppCfgObj type, void *st) +{ + MppCfgIoImpl *orig = (MppCfgIoImpl *)type; + + if (!obj || !type || !st) { + mpp_loge_f("invalid param obj %p type %p st %p\n", obj, type, st); + return rk_nok; + } + + /* NOTE: update structure pointer by data_offset */ + *obj = read_struct(orig, NULL, st + orig->entry.tbl.elem_offset); + + return *obj ? rk_ok : rk_nok; +} + +rk_s32 mpp_cfg_print_string(char *buf) +{ + rk_s32 start = 0; + rk_s32 pos = 0; + rk_s32 len = strlen(buf); + + /* it may be a very long string, split by \n to different line and print */ + for (pos = 0; pos < len; pos++) { + if (buf[pos] == '\n') { + buf[pos] = '\0'; + mpp_logi("%s\n", &buf[start]); + buf[pos] = '\n'; + start = pos + 1; + } + } + + return rk_ok; +} diff --git a/mpp/base/mpp_cluster.c b/mpp/base/mpp_cluster.c new file mode 100644 index 000000000..995048d70 --- /dev/null +++ b/mpp/base/mpp_cluster.c @@ -0,0 +1,782 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_cluster" + +#include + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_lock.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "mpp_cluster.h" +#include "mpp_dev_defs.h" + +#define MPP_CLUSTER_DBG_FLOW (0x00000001) +#define MPP_CLUSTER_DBG_LOCK (0x00000002) + +#define cluster_dbg(flag, fmt, ...) mpp_dbg(mpp_cluster_debug, flag, fmt, ## __VA_ARGS__) +#define cluster_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_cluster_debug, flag, fmt, ## __VA_ARGS__) + +#define cluster_dbg_flow(fmt, ...) cluster_dbg(MPP_CLUSTER_DBG_FLOW, fmt, ## __VA_ARGS__) +#define cluster_dbg_lock(fmt, ...) cluster_dbg(MPP_CLUSTER_DBG_LOCK, fmt, ## __VA_ARGS__) + +RK_U32 mpp_cluster_debug = 0; +RK_U32 mpp_cluster_thd_cnt = 1; + +typedef struct MppNodeProc_s MppNodeProc; +typedef struct MppNodeTask_s MppNodeTask; +typedef struct MppNodeImpl_s MppNodeImpl; + +typedef struct ClusterQueue_s ClusterQueue; +typedef struct ClusterWorker_s ClusterWorker; +typedef struct MppCluster_s MppCluster; + +#define NODE_VALID (0x00000001) +#define NODE_IDLE (0x00000002) +#define NODE_SIGNAL (0x00000004) +#define NODE_WAIT (0x00000008) +#define NODE_RUN (0x00000010) + +#define NODE_ACT_NONE (0x00000000) +#define NODE_ACT_IDLE_TO_WAIT (0x00000001) +#define NODE_ACT_RUN_TO_SIGNAL (0x00000002) + +typedef enum MppWorkerState_e { + WORKER_IDLE, + WORKER_RUNNING, + + WORKER_STATE_BUTT, +} MppWorkerState; + +struct MppNodeProc_s { + TaskProc proc; + void *param; + + /* timing statistic */ + RK_U32 run_count; + RK_S64 run_time; +}; + +struct MppNodeTask_s { + struct list_head list_sched; + MppNodeImpl *node; + const char *node_name; + + /* lock ptr to cluster queue lock */ + ClusterQueue *queue; + + MppNodeProc *proc; +}; + +/* MppNode will be embeded in MppCtx */ +struct MppNodeImpl_s { + char name[32]; + /* list linked to scheduler */ + RK_S32 node_id; + RK_U32 state; + + MppNodeProc work; + + RK_U32 priority; + RK_S32 attached; + sem_t sem_detach; + + /* for cluster schedule */ + MppNodeTask task; +}; + +struct ClusterQueue_s { + MppCluster *cluster; + + pthread_mutex_t lock; + struct list_head list; + RK_S32 count; +}; + +struct ClusterWorker_s { + char name[32]; + MppCluster *cluster; + RK_S32 worker_id; + + MppThread *thd; + MppWorkerState state; + + RK_S32 batch_count; + RK_S32 work_count; + struct list_head list_task; +}; + +struct MppCluster_s { + char name[16]; + pid_t pid; + RK_S32 client_type; + RK_S32 node_id; + RK_S32 worker_id; + + ClusterQueue queue[MAX_PRIORITY]; + RK_S32 node_count; + + /* multi-worker info */ + RK_S32 worker_count; + ClusterWorker *worker; + MppThreadFunc worker_func; +}; + +typedef struct MppClusterServer_s { + MppMutex mutex; + MppCluster *clusters[VPU_CLIENT_BUTT]; +} MppClusterServer; + +static MppClusterServer *srv_cluster = NULL; + +static MppCluster *cluster_server_get(MppClientType client_type); +static MPP_RET cluster_server_put(MppClientType client_type); + +#define mpp_node_task_schedule(task) \ + mpp_node_task_schedule_f(__FUNCTION__, task) + +#define mpp_node_task_schedule_from(caller, task) \ + mpp_node_task_schedule_f(caller, task) + +#define cluster_queue_lock(queue) cluster_queue_lock_f(__FUNCTION__, queue) +#define cluster_queue_unlock(queue) cluster_queue_unlock_f(__FUNCTION__, queue) + +#define get_srv_cluster_f() \ + ({ \ + MppClusterServer *__tmp; \ + if (srv_cluster) { \ + __tmp = srv_cluster; \ + } else { \ + mpp_cluster_srv_init(); \ + __tmp = srv_cluster; \ + if (!__tmp) \ + mpp_err("mpp cluster srv not init at %s\n", __FUNCTION__); \ + } \ + __tmp; \ + }) + +static MPP_RET cluster_queue_lock_f(const char *caller, ClusterQueue *queue) +{ + MppCluster *cluster = queue->cluster; + RK_S32 ret; + + cluster_dbg_lock("%s lock queue at %s start\n", cluster->name, caller); + + ret = pthread_mutex_lock(&queue->lock); + + cluster_dbg_lock("%s lock queue at %s ret %d \n", cluster->name, caller, ret); + + return (ret) ? MPP_NOK : MPP_OK; +} + +static MPP_RET cluster_queue_unlock_f(const char *caller, ClusterQueue *queue) +{ + MppCluster *cluster = queue->cluster; + RK_S32 ret; + + cluster_dbg_lock("%s unlock queue at %s start\n", cluster->name, caller); + + ret = pthread_mutex_unlock(&queue->lock); + + cluster_dbg_lock("%s unlock queue at %s ret %d \n", cluster->name, caller, ret); + + return (ret) ? MPP_NOK : MPP_OK; +} + +void cluster_signal_f(const char *caller, MppCluster *p); + +MPP_RET mpp_cluster_queue_init(ClusterQueue *queue, MppCluster *cluster) +{ + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&queue->lock, &attr); + pthread_mutexattr_destroy(&attr); + + queue->cluster = cluster; + INIT_LIST_HEAD(&queue->list); + queue->count = 0; + + return MPP_OK; +} + +MPP_RET mpp_cluster_queue_deinit(ClusterQueue *queue) +{ + mpp_assert(!queue->count); + mpp_assert(list_empty(&queue->list)); + + pthread_mutex_destroy(&queue->lock); + + return MPP_OK; +} + +MPP_RET mpp_node_task_attach(MppNodeTask *task, MppNodeImpl *node, + ClusterQueue *queue, MppNodeProc *proc) +{ + INIT_LIST_HEAD(&task->list_sched); + + task->node = node; + task->node_name = node->name; + + task->queue = queue; + task->proc = proc; + + node->state = NODE_VALID | NODE_IDLE; + node->attached = 1; + + return MPP_OK; +} + +MPP_RET mpp_node_task_schedule_f(const char *caller, MppNodeTask *task) +{ + ClusterQueue *queue = task->queue; + MppCluster *cluster = queue->cluster; + MppNodeImpl *node = task->node; + MppNodeProc *proc = task->proc; + const char *node_name = task->node_name; + RK_U32 new_st; + RK_U32 action = NODE_ACT_NONE; + bool ret = false; + + cluster_dbg_flow("%s sched from %s before [%d:%d] queue %d\n", + node_name, caller, node->state, proc->run_count, queue->count); + + do { + RK_U32 old_st = node->state; + + action = NODE_ACT_NONE; + new_st = 0; + + if (old_st & NODE_WAIT) { + cluster_dbg_flow("%s sched task %x stay wait\n", node_name, old_st); + break; + } + + if (old_st & NODE_IDLE) { + new_st = old_st ^ (NODE_IDLE | NODE_WAIT); + cluster_dbg_flow("%s sched task %x -> %x wait\n", node_name, old_st, new_st); + action = NODE_ACT_IDLE_TO_WAIT; + } else if (old_st & NODE_RUN) { + new_st = old_st | NODE_SIGNAL; + action = NODE_ACT_RUN_TO_SIGNAL; + cluster_dbg_flow("%s sched task %x -> %x signal\n", node_name, old_st, new_st); + } else { + cluster_dbg_flow("%s sched task %x unknow state %x\n", node_name, old_st); + } + + ret = MPP_BOOL_CAS(&node->state, old_st, new_st); + cluster_dbg_flow("%s sched task %x -> %x cas ret %d act %d\n", + node_name, old_st, new_st, ret, action); + } while (!ret); + + switch (action) { + case NODE_ACT_IDLE_TO_WAIT : { + cluster_queue_lock(queue); + mpp_assert(list_empty(&task->list_sched)); + list_add_tail(&task->list_sched, &queue->list); + queue->count++; + cluster_dbg_flow("%s sched task -> wq %s:%d\n", node_name, cluster->name, queue->count); + cluster_queue_unlock(queue); + + cluster_dbg_flow("%s sched signal from %s\n", node_name, caller); + cluster_signal_f(caller, cluster); + } break; + case NODE_ACT_RUN_TO_SIGNAL : { + cluster_dbg_flow("%s sched signal from %s\n", node_name, caller); + cluster_signal_f(caller, cluster); + } break; + } + + cluster_dbg_flow("%s sched from %s after [%d:%d] queue %d\n", + node_name, caller, node->state, proc->run_count, queue->count); + + return MPP_OK; +} + +MPP_RET mpp_node_task_detach(MppNodeTask *task) +{ + MppNodeImpl *node = task->node; + MPP_RET ret = MPP_OK; + + if (node->attached) { + const char *node_name = task->node_name; + MppNodeProc *proc = task->proc; + + MPP_FETCH_AND(&node->state, ~NODE_VALID); + + mpp_node_task_schedule(task); + + cluster_dbg_flow("%s state %x:%d wait detach start\n", + node_name, node->state, proc->run_count); + + sem_wait(&node->sem_detach); + mpp_assert(node->attached == 0); + + cluster_dbg_flow("%s state %x:%d wait detach done\n", + node_name, node->state, proc->run_count); + } + + return ret; +} + +MPP_RET mpp_node_init(MppNode *node) +{ + MppNodeImpl *p = mpp_calloc(MppNodeImpl, 1); + if (p) + sem_init(&p->sem_detach, 0, 0); + + *node = p; + + return p ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_node_deinit(MppNode node) +{ + MppNodeImpl *p = (MppNodeImpl *)node; + + if (p) { + if (p->attached) + mpp_node_task_detach(&p->task); + + mpp_assert(p->attached == 0); + + sem_destroy(&p->sem_detach); + + mpp_free(p); + } + + return MPP_OK; +} + +MPP_RET mpp_node_set_func(MppNode node, TaskProc proc, void *param) +{ + MppNodeImpl *p = (MppNodeImpl *)node; + if (!p) + return MPP_NOK; + + p->work.proc = proc; + p->work.param = param; + + return MPP_OK; +} + +MPP_RET cluster_worker_init(ClusterWorker *p, MppCluster *cluster) +{ + MppThread *thd = NULL; + MPP_RET ret = MPP_NOK; + + INIT_LIST_HEAD(&p->list_task); + p->worker_id = cluster->worker_id++; + + p->batch_count = 1; + p->work_count = 0; + p->cluster = cluster; + p->state = WORKER_IDLE; + snprintf(p->name, sizeof(p->name) - 1, "%d:W%d", cluster->pid, p->worker_id); + thd = mpp_thread_create(cluster->worker_func, p, p->name); + if (thd) { + p->thd = thd; + mpp_thread_start(thd); + ret = MPP_OK; + } + + return ret; +} + +MPP_RET cluster_worker_deinit(ClusterWorker *p) +{ + if (p->thd) { + mpp_thread_stop(p->thd); + mpp_thread_destroy(p->thd); + p->thd = NULL; + } + + mpp_assert(list_empty(&p->list_task)); + mpp_assert(p->work_count == 0); + + p->batch_count = 0; + p->cluster = NULL; + + return MPP_OK; +} + +RK_S32 cluster_worker_get_task(ClusterWorker *p) +{ + MppCluster *cluster = p->cluster; + RK_S32 batch_count = p->batch_count; + RK_S32 count = 0; + RK_U32 new_st; + RK_U32 old_st; + bool ret; + RK_S32 i; + + cluster_dbg_flow("%s get %d task start\n", p->name, batch_count); + + for (i = 0; i < MAX_PRIORITY; i++) { + ClusterQueue *queue = &cluster->queue[i]; + MppNodeTask *task = NULL; + MppNodeImpl *node = NULL; + + do { + cluster_queue_lock(queue); + + if (list_empty(&queue->list)) { + mpp_assert(queue->count == 0); + cluster_dbg_flow("%s get P%d task ret no task\n", p->name, i); + cluster_queue_unlock(queue); + break; + } + + mpp_assert(queue->count); + task = list_first_entry(&queue->list, MppNodeTask, list_sched); + list_del_init(&task->list_sched); + node = task->node; + + queue->count--; + + do { + old_st = node->state; + new_st = old_st ^ (NODE_WAIT | NODE_RUN); + + mpp_assert(old_st & NODE_WAIT); + ret = MPP_BOOL_CAS(&node->state, old_st, new_st); + } while (!ret); + + list_add_tail(&task->list_sched, &p->list_task); + p->work_count++; + count++; + + cluster_dbg_flow("%s get P%d %s -> rq %d\n", p->name, i, node->name, p->work_count); + + cluster_queue_unlock(queue); + + if (count >= batch_count) + break; + } while (1); + + if (count >= batch_count) + break; + } + + cluster_dbg_flow("%s get %d task ret %d\n", p->name, batch_count, count); + + return count; +} + +static void cluster_worker_run_task(ClusterWorker *p) +{ + RK_U32 new_st; + RK_U32 old_st; + bool cas_ret; + + cluster_dbg_flow("%s run %d work start\n", p->name, p->work_count); + + while (!list_empty(&p->list_task)) { + MppNodeTask *task = list_first_entry(&p->list_task, MppNodeTask, list_sched); + MppNodeProc *proc = task->proc; + MppNodeImpl *node = task->node; + RK_S64 time_start; + RK_S64 time_end; + RK_U32 state; + MPP_RET proc_ret; + + /* check trigger for re-add task */ + cluster_dbg_flow("%s run %s start atate %d\n", p->name, task->node_name, node->state); + mpp_assert(node->state & NODE_RUN); + if (!(node->state & NODE_RUN)) + mpp_err_f("%s run state check %x is invalid on run", p->name, node->state); + + time_start = mpp_time(); + proc_ret = proc->proc(proc->param); + time_end = mpp_time(); + + cluster_dbg_flow("%s run %s ret %d\n", p->name, task->node_name, proc_ret); + proc->run_time += time_end - time_start; + proc->run_count++; + + state = node->state; + if (!(state & NODE_VALID)) { + cluster_dbg_flow("%s run found destroy\n", p->name); + list_del_init(&task->list_sched); + node->attached = 0; + + sem_post(&node->sem_detach); + cluster_dbg_flow("%s run sem post done\n", p->name); + } else if (state & NODE_SIGNAL) { + ClusterQueue *queue = task->queue; + + list_del_init(&task->list_sched); + + do { + old_st = state; + // NOTE: clear NODE_RUN and NODE_SIGNAL, set NODE_WAIT + new_st = old_st ^ (NODE_SIGNAL | NODE_WAIT | NODE_RUN); + cas_ret = MPP_BOOL_CAS(&node->state, old_st, new_st); + } while (!cas_ret); + + cluster_dbg_flow("%s run state %x -> %x signal -> wait\n", p->name, old_st, new_st); + + cluster_queue_lock(queue); + list_add_tail(&task->list_sched, &queue->list); + queue->count++; + cluster_queue_unlock(queue); + } else { + list_del_init(&task->list_sched); + do { + old_st = node->state; + new_st = old_st ^ (NODE_IDLE | NODE_RUN); + + cas_ret = MPP_BOOL_CAS(&node->state, old_st, new_st); + } while (!cas_ret); + mpp_assert(node->state & NODE_IDLE); + mpp_assert(!(node->state & NODE_RUN)); + + cluster_dbg_flow("%s run state %x -> %x run -> idle\n", p->name, old_st, new_st); + } + + p->work_count--; + } + + mpp_assert(p->work_count == 0); + + cluster_dbg_flow("%s run all done\n", p->name); +} + +static void *cluster_worker(void *data) +{ + ClusterWorker *p = (ClusterWorker *)data; + MppThread *thd = p->thd; + + while (1) { + { + RK_S32 task_count = 0; + + cluster_dbg_lock("%s lock start\n", p->name); + mpp_thread_lock(thd, THREAD_WORK); + cluster_dbg_lock("%s lock done\n", p->name); + + if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd, THREAD_WORK)) { + mpp_thread_unlock(thd, THREAD_WORK); + break; + } + + task_count = cluster_worker_get_task(p); + if (!task_count) { + p->state = WORKER_IDLE; + mpp_thread_wait(thd, THREAD_WORK); + p->state = WORKER_RUNNING; + } + mpp_thread_unlock(thd, THREAD_WORK); + } + + cluster_worker_run_task(p); + } + + return NULL; +} + +void cluster_signal_f(const char *caller, MppCluster *p) +{ + RK_S32 i; + + cluster_dbg_flow("%s signal from %s\n", p->name, caller); + + for (i = 0; i < p->worker_count; i++) { + ClusterWorker *worker = &p->worker[i]; + MppThread *thd = worker->thd; + + mpp_thread_lock(thd, THREAD_WORK); + + if (worker->state == WORKER_IDLE) { + mpp_thread_signal(thd, THREAD_WORK); + cluster_dbg_flow("%s signal\n", p->name); + mpp_thread_unlock(thd, THREAD_WORK); + break; + } + + mpp_thread_unlock(thd, THREAD_WORK); + } +} + +static void mpp_cluster_srv_init(void) +{ + MppClusterServer *srv = srv_cluster; + + mpp_env_get_u32("mpp_cluster_debug", &mpp_cluster_debug, 0); + mpp_env_get_u32("mpp_cluster_thd_cnt", &mpp_cluster_thd_cnt, 1); + + if (srv) + return; + + srv = mpp_calloc(MppClusterServer, 1); + if (!srv) { + mpp_err_f("failed to allocate cluster server\n"); + return; + } + + memset(srv->clusters, 0, sizeof(srv->clusters)); + mpp_mutex_init(&srv->mutex); + + srv_cluster = srv; +} + +static void mpp_cluster_srv_deinit(void) +{ + MppClusterServer *srv = srv_cluster; + RK_S32 i; + + if (!srv) + return; + + for (i = 0; i < VPU_CLIENT_BUTT; i++) + cluster_server_put((MppClientType)i); + + mpp_mutex_destroy(&srv->mutex); + MPP_FREE(srv_cluster); +} + +MPP_SINGLETON(MPP_SGLN_CLUSTER, mpp_cluster, mpp_cluster_srv_init, mpp_cluster_srv_deinit) + +static MppCluster *cluster_server_get(MppClientType client_type) +{ + MppClusterServer *srv = get_srv_cluster_f(); + RK_S32 i; + MppCluster *p = NULL; + + if (!srv || client_type >= VPU_CLIENT_BUTT) + goto done; + + { + mpp_mutex_lock(&srv->mutex); + + p = srv->clusters[client_type]; + if (p) { + mpp_mutex_unlock(&srv->mutex); + goto done; + } + + p = mpp_malloc(MppCluster, 1); + if (p) { + for (i = 0; i < MAX_PRIORITY; i++) + mpp_cluster_queue_init(&p->queue[i], p); + + p->pid = getpid(); + p->client_type = client_type; + snprintf(p->name, sizeof(p->name) - 1, "%d:%d", p->pid, client_type); + p->node_id = 0; + p->worker_id = 0; + p->worker_func = cluster_worker; + p->worker_count = mpp_cluster_thd_cnt; + + mpp_assert(p->worker_count > 0); + + p->worker = mpp_malloc(ClusterWorker, p->worker_count); + + for (i = 0; i < p->worker_count; i++) + cluster_worker_init(&p->worker[i], p); + + srv->clusters[client_type] = p; + cluster_dbg_flow("%s created\n", p->name); + } + + mpp_mutex_unlock(&srv->mutex); + } + +done: + if (p) + cluster_dbg_flow("%s get\n", p->name); + else + cluster_dbg_flow("%d get cluster %d failed\n", getpid(), client_type); + + return p; +} + +static MPP_RET cluster_server_put(MppClientType client_type) +{ + MppClusterServer *srv = get_srv_cluster_f(); + MppCluster *p; + RK_S32 i; + + if (!srv || client_type >= VPU_CLIENT_BUTT) + return MPP_NOK; + + mpp_mutex_lock(&srv->mutex); + + p = srv->clusters[client_type]; + if (!p) { + mpp_mutex_unlock(&srv->mutex); + return MPP_NOK; + } + + for (i = 0; i < p->worker_count; i++) + cluster_worker_deinit(&p->worker[i]); + + for (i = 0; i < MAX_PRIORITY; i++) + mpp_cluster_queue_deinit(&p->queue[i]); + + cluster_dbg_flow("put %s\n", p->name); + + MPP_FREE(p->worker); + mpp_free(p); + srv->clusters[client_type] = NULL; + + mpp_mutex_unlock(&srv->mutex); + + return MPP_OK; +} + +MPP_RET mpp_node_attach(MppNode node, MppClientType type) +{ + MppNodeImpl *impl = (MppNodeImpl *)node; + MppCluster *p = cluster_server_get(type); + RK_U32 priority = impl->priority; + ClusterQueue *queue = &p->queue[priority]; + + mpp_assert(priority < MAX_PRIORITY); + mpp_assert(p); + + impl->node_id = MPP_FETCH_ADD(&p->node_id, 1); + + snprintf(impl->name, sizeof(impl->name) - 1, "%s:%d", p->name, impl->node_id); + + mpp_node_task_attach(&impl->task, impl, queue, &impl->work); + + MPP_FETCH_ADD(&p->node_count, 1); + + cluster_dbg_flow("%s:%d attached %d\n", p->name, impl->node_id, p->node_count); + + /* attach and run once first */ + mpp_node_task_schedule(&impl->task); + cluster_dbg_flow("%s trigger signal from %s\n", impl->name, __FUNCTION__); + + return MPP_OK; +} + +MPP_RET mpp_node_detach(MppNode node) +{ + MppNodeImpl *impl = (MppNodeImpl *)node; + + mpp_node_task_detach(&impl->task); + cluster_dbg_flow("%s detached\n", impl->name); + + return MPP_OK; +} + +MPP_RET mpp_node_trigger_f(const char *caller, MppNode node, RK_S32 trigger) +{ + if (trigger) { + MppNodeImpl *impl = (MppNodeImpl *)node; + + mpp_node_task_schedule_from(caller, &impl->task); + } + + return MPP_OK; +} diff --git a/mpp/base/mpp_dec_cfg.c b/mpp/base/mpp_dec_cfg.c new file mode 100644 index 000000000..dad6781f5 --- /dev/null +++ b/mpp/base/mpp_dec_cfg.c @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dec_cfg" + +#include "rk_vdec_cfg.h" +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_lock.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" +#include "mpp_internal.h" + +#include "mpp_trie.h" +#include "mpp_cfg.h" +#include "mpp_cfg_io.h" +#include "mpp_dec_cfg.h" + +#define MPP_DEC_CFG_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + CFG_DEF_START() \ + STRUCT_START(base) \ + ENTRY(prefix, u32, rk_u32, type, FLAG_BASE(0), base, type) \ + ENTRY(prefix, u32, rk_u32, coding, FLAG_INCR, base, coding) \ + ENTRY(prefix, u32, rk_u32, hw_type, FLAG_INCR, base, hw_type) \ + ENTRY(prefix, u32, rk_u32, batch_mode, FLAG_INCR, base, batch_mode) \ + ENTRY(prefix, u32, rk_u32, out_fmt, FLAG_INCR, base, out_fmt) \ + ENTRY(prefix, u32, rk_u32, fast_out, FLAG_INCR, base, fast_out) \ + ENTRY(prefix, u32, rk_u32, fast_parse, FLAG_INCR, base, fast_parse) \ + ENTRY(prefix, u32, rk_u32, split_parse, FLAG_INCR, base, split_parse) \ + ENTRY(prefix, u32, rk_u32, internal_pts, FLAG_INCR, base, internal_pts) \ + ENTRY(prefix, u32, rk_u32, sort_pts, FLAG_INCR, base, sort_pts) \ + ENTRY(prefix, u32, rk_u32, disable_error, FLAG_INCR, base, disable_error) \ + ENTRY(prefix, u32, rk_u32, enable_vproc, FLAG_INCR, base, enable_vproc) \ + ENTRY(prefix, u32, rk_u32, enable_fast_play, FLAG_INCR, base, enable_fast_play) \ + ENTRY(prefix, u32, rk_u32, enable_hdr_meta, FLAG_INCR, base, enable_hdr_meta) \ + ENTRY(prefix, u32, rk_u32, enable_thumbnail, FLAG_INCR, base, enable_thumbnail) \ + ENTRY(prefix, u32, rk_u32, enable_mvc, FLAG_INCR, base, enable_mvc) \ + ENTRY(prefix, u32, rk_u32, disable_dpb_chk, FLAG_INCR, base, disable_dpb_chk) \ + ENTRY(prefix, u32, rk_u32, disable_thread, FLAG_INCR, base, disable_thread) \ + ENTRY(prefix, u32, rk_u32, codec_mode, FLAG_INCR, base, codec_mode) \ + ENTRY(prefix, u32, rk_u32, dis_err_clr_mark, FLAG_INCR, base, dis_err_clr_mark) \ + STRUCT_END(base) \ + STRUCT_START(status) \ + ENTRY(prefix, s32, rk_s32, width, FLAG_NONE, status, width) \ + ENTRY(prefix, s32, rk_s32, height, FLAG_NONE, status, height) \ + ENTRY(prefix, s32, rk_s32, hor_stride, FLAG_NONE, status, hor_stride) \ + ENTRY(prefix, s32, rk_s32, ver_stride, FLAG_NONE, status, ver_stride) \ + ENTRY(prefix, s32, rk_s32, buf_size, FLAG_NONE, status, buf_size) \ + STRUCT_END(status) \ + STRUCT_START(cb) \ + ENTRY(prefix, ptr, void *, pkt_rdy_cb, FLAG_BASE(0), cb, pkt_rdy_cb) \ + ENTRY(prefix, ptr, void *, pkt_rdy_ctx, FLAG_PREV, cb, pkt_rdy_ctx) \ + ENTRY(prefix, s32, rk_s32, pkt_rdy_cmd, FLAG_PREV, cb, pkt_rdy_cmd) \ + ENTRY(prefix, ptr, void *, frm_rdy_cb, FLAG_INCR, cb, frm_rdy_cb) \ + ENTRY(prefix, ptr, void *, frm_rdy_ctx, FLAG_PREV, cb, frm_rdy_ctx) \ + ENTRY(prefix, s32, rk_s32, frm_rdy_cmd, FLAG_PREV, cb, frm_rdy_cmd) \ + STRUCT_END(cb) \ + CFG_DEF_END() + +rk_s32 mpp_dec_cfg_set_default(void *entry, KmppObj obj, const char *caller) +{ + MppDecCfgSet *cfg = (MppDecCfgSet *)entry; + + cfg->base.type = MPP_CTX_BUTT; + cfg->base.coding = MPP_VIDEO_CodingUnused; + cfg->base.hw_type = -1; + cfg->base.fast_parse = 1; +#ifdef ENABLE_FASTPLAY_ONCE + cfg->base.enable_fast_play = MPP_ENABLE_FAST_PLAY_ONCE; +#else + cfg->base.enable_fast_play = MPP_ENABLE_FAST_PLAY; +#endif + (void) obj; + (void) caller; + + return rk_ok; +} + +#define KMPP_OBJ_NAME mpp_dec_cfg +#define KMPP_OBJ_INTF_TYPE MppDecCfg +#define KMPP_OBJ_IMPL_TYPE MppDecCfgSet +#define KMPP_OBJ_SGLN_ID MPP_SGLN_DEC_CFG +#define KMPP_OBJ_FUNC_INIT mpp_dec_cfg_set_default +#define KMPP_OBJ_ENTRY_TABLE MPP_DEC_CFG_ENTRY_TABLE +#define KMPP_OBJ_ACCESS_DISABLE +#define KMPP_OBJ_HIERARCHY_ENABLE +#include "kmpp_obj_helper.h" + +/* wrapper for old interface */ +MPP_RET mpp_dec_cfg_init(MppDecCfg *cfg) +{ + return mpp_dec_cfg_get(cfg); +} + +MPP_RET mpp_dec_cfg_deinit(MppDecCfg cfg) +{ + return mpp_dec_cfg_put(cfg); +} + +#define DEC_CFG_SET_ACCESS(func_name, in_type, cfg_type) \ + MPP_RET func_name(MppDecCfg cfg, const char *name, in_type val) \ + { \ + if (NULL == cfg || NULL == name) { \ + mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \ + return rk_nok; \ + } \ + return kmpp_obj_set_##cfg_type(cfg, name, val); \ + } + +DEC_CFG_SET_ACCESS(mpp_dec_cfg_set_s32, RK_S32, s32) +DEC_CFG_SET_ACCESS(mpp_dec_cfg_set_u32, RK_U32, u32) +DEC_CFG_SET_ACCESS(mpp_dec_cfg_set_s64, RK_S64, s64) +DEC_CFG_SET_ACCESS(mpp_dec_cfg_set_u64, RK_U64, u64) +DEC_CFG_SET_ACCESS(mpp_dec_cfg_set_ptr, void *, ptr) +DEC_CFG_SET_ACCESS(mpp_dec_cfg_set_st, void *, st) + +#define DEC_CFG_GET_ACCESS(func_name, in_type, cfg_type) \ + MPP_RET func_name(MppDecCfg cfg, const char *name, in_type *val) \ + { \ + if (NULL == cfg || NULL == name) { \ + mpp_err_f("invalid input cfg %p name %p\n", cfg, name); \ + return rk_nok; \ + } \ + return kmpp_obj_get_##cfg_type(cfg, name, val); \ + } + +DEC_CFG_GET_ACCESS(mpp_dec_cfg_get_s32, RK_S32, s32) +DEC_CFG_GET_ACCESS(mpp_dec_cfg_get_u32, RK_U32, u32) +DEC_CFG_GET_ACCESS(mpp_dec_cfg_get_s64, RK_S64, s64) +DEC_CFG_GET_ACCESS(mpp_dec_cfg_get_u64, RK_U64, u64) +DEC_CFG_GET_ACCESS(mpp_dec_cfg_get_ptr, void *, ptr) +DEC_CFG_GET_ACCESS(mpp_dec_cfg_get_st, void , st) + +void mpp_dec_cfg_show(void) +{ + MppTrie trie = kmpp_objdef_get_trie(mpp_dec_cfg_def); + MppTrieInfo *root; + + if (!trie) + return; + + root = mpp_trie_get_info_first(trie); + + mpp_log("dumping valid configure string start\n"); + + if (root) { + MppTrieInfo *node = root; + rk_s32 len = mpp_trie_get_name_max(trie); + + mpp_log("%-*s %-6s | %6s | %4s | %4s\n", len, "name", "type", "offset", "size", "flag (hex)"); + + do { + if (mpp_trie_info_is_self(node)) + continue; + + if (node->ctx_len == sizeof(KmppEntry)) { + KmppEntry *entry = (KmppEntry *)mpp_trie_info_ctx(node); + + mpp_log("%-*s %-6s | %-6d | %-4d | %-4x\n", len, mpp_trie_info_name(node), + strof_elem_type(entry->tbl.elem_type), entry->tbl.elem_offset, + entry->tbl.elem_size, entry->tbl.flag_offset); + } else { + mpp_log("%-*s size - %d\n", len, mpp_trie_info_name(node), node->ctx_len); + } + } while ((node = mpp_trie_get_info_next(trie, node))); + } + + mpp_log("dumping valid configure string done\n"); + + mpp_log("dec cfg size %d count %d with trie node %d size %d\n", + sizeof(MppDecCfgSet), mpp_trie_get_info_count(trie), + mpp_trie_get_node_count(trie), mpp_trie_get_buf_size(trie)); +} diff --git a/mpp/base/mpp_dec_hdr_meta.c b/mpp/base/mpp_dec_hdr_meta.c new file mode 100644 index 000000000..7d62a6087 --- /dev/null +++ b/mpp/base/mpp_dec_hdr_meta.c @@ -0,0 +1,170 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "rk_hdr_meta_com.h" +#include "mpp_common.h" +#include "mpp_log.h" +#include "mpp_frame.h" + +/* h(104) + d(100) + r(114) */ +#define HDR_META_MAGIC 318 + +static RK_U32 hdr_get_offset_from_frame(MppFrame frame) +{ + return mpp_frame_get_buf_size(frame); +} + +void fill_hdr_meta_to_frame(MppFrame frame, MppCodingType in_type) +{ + RK_U32 off = hdr_get_offset_from_frame(frame); + MppBuffer buf = mpp_frame_get_buffer(frame); + void *ptr = mpp_buffer_get_ptr(buf); + MppFrameHdrDynamicMeta *dynamic_meta = mpp_frame_get_hdr_dynamic_meta(frame); + MppFrameMasteringDisplayMetadata mastering_display = mpp_frame_get_mastering_display(frame); + MppFrameContentLightMetadata content_light = mpp_frame_get_content_light(frame); + RkMetaHdrHeader *hdr_static_meta_header; + RkMetaHdrHeader *hdr_dynamic_meta_header; + RK_U32 msg_idx = 0; + RK_U16 hdr_format = HDR_NONE; + MppMeta meta = NULL; + RK_U32 max_size = mpp_buffer_get_size(buf); + RK_U32 static_size, dynamic_size = 0, total_size = 0; + HdrCodecType codec_type = HDR_CODEC_UNSPECIFIED; + + if (!ptr || !buf) { + mpp_err_f("buf is null!\n"); + return; + } + + if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_ONLY) { + // only for 8K thumbnail downscale to 4K 8bit mode + RK_U32 downscale_width = mpp_frame_get_width(frame) / 2; + RK_U32 downscale_height = mpp_frame_get_height(frame) / 2; + + off = downscale_width * downscale_height * 3 / 2; + } + off = MPP_ALIGN(off, SZ_4K); + + static_size = sizeof(RkMetaHdrHeader) + sizeof(HdrStaticMeta); + if (dynamic_meta && dynamic_meta->size) + dynamic_size = sizeof(RkMetaHdrHeader) + dynamic_meta->size; + + total_size = static_size + dynamic_size; + + if ((off + total_size) > max_size) { + mpp_err_f("fill hdr meta overflow off %d size %d max %d\n", + off, total_size, max_size); + return; + } + meta = mpp_frame_get_meta(frame); + mpp_meta_set_s32(meta, KEY_HDR_META_OFFSET, off); + /* 1. fill hdr static meta date */ + hdr_static_meta_header = (RkMetaHdrHeader*)(ptr + off); + /* For transmission */ + hdr_static_meta_header->magic = HDR_META_MAGIC; + hdr_static_meta_header->size = static_size; + hdr_static_meta_header->message_index = msg_idx++; + + switch (in_type) { + case MPP_VIDEO_CodingAVS2 : { + codec_type = HDR_AVS2; + } break; + case MPP_VIDEO_CodingHEVC : { + codec_type = HDR_HEVC; + } break; + case MPP_VIDEO_CodingAVC : { + codec_type = HDR_H264; + } break; + case MPP_VIDEO_CodingAV1 : { + codec_type = HDR_AV1; + } break; + default : break; + } + + /* For payload identification */ + hdr_static_meta_header->hdr_payload_type = STATIC; + hdr_static_meta_header->video_format = codec_type; + { + HdrStaticMeta *static_meta = (HdrStaticMeta*)hdr_static_meta_header->payload; + + static_meta->min_luminance = mastering_display.min_luminance; + static_meta->max_luminance = mastering_display.max_luminance; + static_meta->green_x = mastering_display.display_primaries[0][0]; + static_meta->green_y = mastering_display.display_primaries[0][1]; + static_meta->blue_x = mastering_display.display_primaries[1][0]; + static_meta->blue_y = mastering_display.display_primaries[1][1]; + static_meta->red_x = mastering_display.display_primaries[2][0]; + static_meta->red_y = mastering_display.display_primaries[2][1]; + static_meta->white_point_x = mastering_display.white_point[0]; + static_meta->white_point_y = mastering_display.white_point[1]; + static_meta->color_trc = mpp_frame_get_color_trc(frame); + static_meta->color_space = mpp_frame_get_colorspace(frame); + static_meta->color_primaries = mpp_frame_get_color_primaries(frame); + static_meta->max_cll = content_light.MaxCLL; + static_meta->max_fall = content_light.MaxFALL; + /* + * hlg: + * hevc trc = 18 + * avs trc = 14 + * hdr10: + * hevc/h264 trc = 16 + * avs trc = 12 + */ + switch (codec_type) { + case HDR_AV1 : + case HDR_HEVC : + case HDR_H264 : { + if (static_meta->color_trc == MPP_FRAME_TRC_ARIB_STD_B67) + hdr_format = HLG; + else if (static_meta->color_trc == MPP_FRAME_TRC_SMPTEST2084) + hdr_format = HDR10; + } break; + case HDR_AVS2 : { + if (static_meta->color_trc == MPP_FRAME_TRC_BT2020_10) + hdr_format = HLG; + else if (static_meta->color_trc == MPP_FRAME_TRC_BT1361_ECG) + hdr_format = HDR10; + } break; + default : { + } break; + } + } + off += hdr_static_meta_header->size; + + /* 2. fill hdr dynamic meta date */ + if (dynamic_meta && dynamic_meta->size) { + hdr_dynamic_meta_header = (RkMetaHdrHeader*)(ptr + off); + + /* For transmission */ + hdr_dynamic_meta_header->magic = HDR_META_MAGIC; + hdr_dynamic_meta_header->size = dynamic_size; + hdr_dynamic_meta_header->message_index = msg_idx++; + + /* For payload identification */ + hdr_dynamic_meta_header->hdr_payload_type = DYNAMIC; + hdr_dynamic_meta_header->video_format = codec_type; + hdr_format = dynamic_meta->hdr_fmt; + + memcpy(hdr_dynamic_meta_header->payload, dynamic_meta->data, dynamic_meta->size); + hdr_dynamic_meta_header->message_total = msg_idx; + hdr_dynamic_meta_header->hdr_format = hdr_format; + } + + mpp_meta_set_s32(meta, KEY_HDR_META_SIZE, total_size); + hdr_static_meta_header->message_total = msg_idx; + hdr_static_meta_header->hdr_format = hdr_format; +} \ No newline at end of file diff --git a/mpp/base/mpp_enc_cfg.c b/mpp/base/mpp_enc_cfg.c new file mode 100644 index 000000000..73a3f5d33 --- /dev/null +++ b/mpp/base/mpp_enc_cfg.c @@ -0,0 +1,544 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_enc_cfg" + +#include + +#include "rk_venc_cfg.h" +#include "rk_venc_kcfg.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" +#include "mpp_internal.h" + +#include "mpp_cfg.h" +#include "mpp_trie.h" +#include "mpp_cfg_io.h" +#include "mpp_enc_cfg.h" + +#define ENC_CFG_DBG_FUNC (0x00000001) +#define ENC_CFG_DBG_INFO (0x00000002) +#define ENC_CFG_DBG_SET (0x00000004) +#define ENC_CFG_DBG_GET (0x00000008) + +#define enc_cfg_dbg(flag, fmt, ...) mpp_dbg_f(mpp_enc_cfg_debug, flag, fmt, ## __VA_ARGS__) + +#define enc_cfg_dbg_func(fmt, ...) enc_cfg_dbg(ENC_CFG_DBG_FUNC, fmt, ## __VA_ARGS__) +#define enc_cfg_dbg_info(fmt, ...) enc_cfg_dbg(ENC_CFG_DBG_INFO, fmt, ## __VA_ARGS__) +#define enc_cfg_dbg_set(fmt, ...) enc_cfg_dbg(ENC_CFG_DBG_SET, fmt, ## __VA_ARGS__) +#define enc_cfg_dbg_get(fmt, ...) enc_cfg_dbg(ENC_CFG_DBG_GET, fmt, ## __VA_ARGS__) + +#define MPP_ENC_CFG_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + CFG_DEF_START() \ + /* prefix ElemType base type trie name update flag type element address */ \ + STRUCT_START(codec); \ + ENTRY(prefix, s32, rk_s32, type, FLAG_BASE(0), base, coding); \ + STRUCT_END(codec); \ + STRUCT_START(base) \ + ENTRY(prefix, s32, rk_s32, low_delay, FLAG_INCR, base, low_delay) \ + ENTRY(prefix, s32, rk_s32, smt1_en, FLAG_INCR, base, smt1_en) \ + ENTRY(prefix, s32, rk_s32, smt3_en, FLAG_INCR, base, smt3_en) \ + STRUCT_END(base) \ + STRUCT_START(rc) \ + ENTRY(prefix, s32, rk_s32, mode, FLAG_BASE(0), rc, rc_mode) \ + ENTRY(prefix, s32, rk_s32, quality, FLAG_INCR, rc, quality); \ + ENTRY(prefix, s32, rk_s32, bps_target, FLAG_INCR, rc, bps_target) \ + ENTRY(prefix, s32, rk_s32, bps_max, FLAG_PREV, rc, bps_max) \ + ENTRY(prefix, s32, rk_s32, bps_min, FLAG_PREV, rc, bps_min) \ + ENTRY(prefix, s32, rk_s32, fps_in_flex, FLAG_INCR, rc, fps_in_flex) \ + ENTRY(prefix, s32, rk_s32, fps_in_num, FLAG_PREV, rc, fps_in_num) \ + ENTRY(prefix, s32, rk_s32, fps_in_denorm, FLAG_PREV, rc, fps_in_denom) \ + ALIAS(prefix, s32, rk_s32, fps_in_denom, FLAG_PREV, rc, fps_in_denom) \ + ENTRY(prefix, s32, rk_s32, fps_out_flex, FLAG_INCR, rc, fps_out_flex) \ + ENTRY(prefix, s32, rk_s32, fps_out_num, FLAG_PREV, rc, fps_out_num) \ + ENTRY(prefix, s32, rk_s32, fps_out_denorm, FLAG_PREV, rc, fps_out_denom) \ + ALIAS(prefix, s32, rk_s32, fps_out_denom, FLAG_PREV, rc, fps_out_denom) \ + ENTRY(prefix, s32, rk_s32, fps_chg_no_idr, FLAG_PREV, rc, fps_chg_no_idr) \ + ENTRY(prefix, s32, rk_s32, gop, FLAG_INCR, rc, gop) \ + ENTRY(prefix, ptr, void *, ref_cfg, FLAG_INCR, rc, ref_cfg) \ + ENTRY(prefix, u32, rk_u32, max_reenc_times, FLAG_INCR, rc, max_reenc_times) \ + ENTRY(prefix, u32, rk_u32, priority, FLAG_INCR, rc, rc_priority) \ + ENTRY(prefix, u32, rk_u32, drop_mode, FLAG_INCR, rc, drop_mode) \ + ENTRY(prefix, u32, rk_u32, drop_thd, FLAG_PREV, rc, drop_threshold) \ + ENTRY(prefix, u32, rk_u32, drop_gap, FLAG_PREV, rc, drop_gap) \ + ENTRY(prefix, s32, rk_s32, max_i_prop, FLAG_INCR, rc, max_i_prop) \ + ENTRY(prefix, s32, rk_s32, min_i_prop, FLAG_INCR, rc, min_i_prop) \ + ENTRY(prefix, s32, rk_s32, init_ip_ratio, FLAG_INCR, rc, init_ip_ratio) \ + ENTRY(prefix, u32, rk_u32, super_mode, FLAG_INCR, rc, super_mode) \ + ENTRY(prefix, u32, rk_u32, super_i_thd, FLAG_PREV, rc, super_i_thd) \ + ENTRY(prefix, u32, rk_u32, super_p_thd, FLAG_PREV, rc, super_p_thd) \ + ENTRY(prefix, u32, rk_u32, debreath_en, FLAG_INCR, rc, debreath_en) \ + ENTRY(prefix, u32, rk_u32, debreath_strength, FLAG_PREV, rc, debre_strength) \ + ENTRY(prefix, s32, rk_s32, qp_init, FLAG_REC_INC(0), rc, qp_init) \ + ENTRY(prefix, s32, rk_s32, qp_min, FLAG_REC_INC(1), rc, qp_min) \ + ENTRY(prefix, s32, rk_s32, qp_max, FLAG_REPLAY(1), rc, qp_max) \ + ENTRY(prefix, s32, rk_s32, qp_min_i, FLAG_REC_INC(2), rc, qp_min_i) \ + ENTRY(prefix, s32, rk_s32, qp_max_i, FLAG_REPLAY(2), rc, qp_max_i) \ + ENTRY(prefix, s32, rk_s32, qp_step, FLAG_REC_INC(3), rc, qp_max_step) \ + ENTRY(prefix, s32, rk_s32, qp_ip, FLAG_REC_INC(4), rc, qp_delta_ip) \ + ENTRY(prefix, s32, rk_s32, qp_vi, FLAG_INCR, rc, qp_delta_vi) \ + ENTRY(prefix, s32, rk_s32, hier_qp_en, FLAG_INCR, rc, hier_qp_en) \ + STRCT(prefix, starr, rk_s32, hier_qp_delta, FLAG_PREV, rc, hier_qp_delta); \ + STRCT(prefix, starr, rk_s32, hier_frame_num, FLAG_PREV, rc, hier_frame_num); \ + ENTRY(prefix, s32, rk_s32, stats_time, FLAG_INCR, rc, stats_time) \ + ENTRY(prefix, u32, rk_u32, refresh_en, FLAG_INCR, rc, refresh_en) \ + ENTRY(prefix, u32, rk_u32, refresh_mode, FLAG_PREV, rc, refresh_mode) \ + ENTRY(prefix, u32, rk_u32, refresh_num, FLAG_PREV, rc, refresh_num) \ + ENTRY(prefix, s32, rk_s32, fqp_min_i, FLAG_INCR, rc, fqp_min_i) \ + ENTRY(prefix, s32, rk_s32, fqp_min_p, FLAG_PREV, rc, fqp_min_p) \ + ENTRY(prefix, s32, rk_s32, fqp_max_i, FLAG_PREV, rc, fqp_max_i) \ + ENTRY(prefix, s32, rk_s32, fqp_max_p, FLAG_PREV, rc, fqp_max_p) \ + ENTRY(prefix, s32, rk_s32, mt_st_swth_frm_qp, FLAG_PREV, rc, mt_st_swth_frm_qp) \ + ENTRY(prefix, s32, rk_s32, inst_br_lvl, FLAG_INCR, rc, inst_br_lvl) \ + STRUCT_END(rc) \ + STRUCT_START(prep); \ + ENTRY(prefix, s32, rk_s32, width, FLAG_BASE(0), prep, width_set); \ + ENTRY(prefix, s32, rk_s32, height, FLAG_PREV, prep, height_set); \ + ENTRY(prefix, s32, rk_s32, max_width, FLAG_PREV, prep, max_width); \ + ENTRY(prefix, s32, rk_s32, max_height, FLAG_PREV, prep, max_height); \ + ENTRY(prefix, s32, rk_s32, hor_stride, FLAG_PREV, prep, hor_stride); \ + ENTRY(prefix, s32, rk_s32, ver_stride, FLAG_PREV, prep, ver_stride); \ + ENTRY(prefix, s32, rk_s32, format, FLAG_INCR, prep, format); \ + ENTRY(prefix, s32, rk_s32, format_out, FLAG_PREV, prep, format_out); \ + ENTRY(prefix, s32, rk_s32, chroma_ds_mode, FLAG_PREV, prep, chroma_ds_mode); \ + ENTRY(prefix, s32, rk_s32, fix_chroma_en, FLAG_PREV, prep, fix_chroma_en); \ + ENTRY(prefix, s32, rk_s32, fix_chroma_u, FLAG_PREV, prep, fix_chroma_u); \ + ENTRY(prefix, s32, rk_s32, fix_chroma_v, FLAG_PREV, prep, fix_chroma_v); \ + ENTRY(prefix, s32, rk_s32, colorspace, FLAG_INCR, prep, color); \ + ENTRY(prefix, s32, rk_s32, colorprim, FLAG_INCR, prep, colorprim); \ + ENTRY(prefix, s32, rk_s32, colortrc, FLAG_INCR, prep, colortrc); \ + ENTRY(prefix, s32, rk_s32, colorrange, FLAG_INCR, prep, range); \ + ALIAS(prefix, s32, rk_s32, range, FLAG_PREV, prep, range); \ + ENTRY(prefix, s32, rk_s32, range_out, FLAG_PREV, prep, range_out); \ + ENTRY(prefix, s32, rk_s32, rotation, FLAG_INCR, prep, rotation_ext); \ + ENTRY(prefix, s32, rk_s32, mirroring, FLAG_INCR, prep, mirroring_ext); \ + ENTRY(prefix, s32, rk_s32, flip, FLAG_INCR, prep, flip); \ + STRUCT_END(prep); \ + STRUCT_START(h264); \ + /* h264 config */ \ + ENTRY(prefix, s32, rk_s32, stream_type, FLAG_BASE(0), h264, stream_type); \ + ENTRY(prefix, s32, rk_s32, profile, FLAG_INCR, h264, profile); \ + ENTRY(prefix, s32, rk_s32, level, FLAG_PREV, h264, level); \ + ENTRY(prefix, u32, rk_u32, poc_type, FLAG_INCR, h264, poc_type); \ + ENTRY(prefix, u32, rk_u32, log2_max_poc_lsb, FLAG_INCR, h264, log2_max_poc_lsb); \ + ENTRY(prefix, u32, rk_u32, log2_max_frm_num, FLAG_INCR, h264, log2_max_frame_num); \ + ENTRY(prefix, u32, rk_u32, gaps_not_allowed, FLAG_INCR, h264, gaps_not_allowed); \ + ENTRY(prefix, s32, rk_s32, cabac_en, FLAG_INCR, h264, entropy_coding_mode_ex); \ + ENTRY(prefix, s32, rk_s32, cabac_idc, FLAG_PREV, h264, cabac_init_idc_ex); \ + ENTRY(prefix, s32, rk_s32, trans8x8, FLAG_INCR, h264, transform8x8_mode_ex); \ + ENTRY(prefix, s32, rk_s32, const_intra, FLAG_INCR, h264, constrained_intra_pred_mode); \ + ENTRY(prefix, s32, rk_s32, scaling_list, FLAG_INCR, h264, scaling_list_mode); \ + ENTRY(prefix, s32, rk_s32, cb_qp_offset, FLAG_INCR, h264, chroma_cb_qp_offset); \ + ENTRY(prefix, s32, rk_s32, cr_qp_offset, FLAG_PREV, h264, chroma_cr_qp_offset); \ + ENTRY(prefix, s32, rk_s32, dblk_disable, FLAG_INCR, h264, deblock_disable); \ + ENTRY(prefix, s32, rk_s32, dblk_alpha, FLAG_PREV, h264, deblock_offset_alpha); \ + ENTRY(prefix, s32, rk_s32, dblk_beta, FLAG_PREV, h264, deblock_offset_beta); \ + ALIAS(prefix, s32, rk_s32, qp_init, FLAG_REPLAY(0), rc, qp_init); \ + ALIAS(prefix, s32, rk_s32, qp_min, FLAG_REPLAY(1), rc, qp_min); \ + ALIAS(prefix, s32, rk_s32, qp_max, FLAG_REPLAY(1), rc, qp_max); \ + ALIAS(prefix, s32, rk_s32, qp_min_i, FLAG_REPLAY(2), rc, qp_min_i); \ + ALIAS(prefix, s32, rk_s32, qp_max_i, FLAG_REPLAY(2), rc, qp_max_i); \ + ALIAS(prefix, s32, rk_s32, qp_step, FLAG_REPLAY(3), rc, qp_max_step); \ + ALIAS(prefix, s32, rk_s32, qp_delta_ip, FLAG_REPLAY(4), rc, qp_delta_ip); \ + ENTRY(prefix, s32, rk_s32, max_tid, FLAG_INCR, h264, max_tid); \ + ENTRY(prefix, s32, rk_s32, max_ltr, FLAG_INCR, h264, max_ltr_frames); \ + ENTRY(prefix, s32, rk_s32, prefix_mode, FLAG_INCR, h264, prefix_mode); \ + ENTRY(prefix, s32, rk_s32, base_layer_pid, FLAG_INCR, h264, base_layer_pid); \ + ENTRY(prefix, u32, rk_u32, constraint_set, FLAG_INCR, h264, constraint_set); \ + ENTRY(prefix, u32, rk_u32, vui_en, FLAG_INCR, h264, vui, vui_en); \ + STRUCT_END(h264); \ + /* h265 config*/ \ + STRUCT_START(h265); \ + ENTRY(prefix, s32, rk_s32, profile, FLAG_BASE(0), h265, profile); \ + ENTRY(prefix, s32, rk_s32, tier, FLAG_PREV, h265, tier); \ + ENTRY(prefix, s32, rk_s32, level, FLAG_PREV, h265, level); \ + ENTRY(prefix, u32, rk_u32, scaling_list, FLAG_INCR, h265, trans_cfg, scaling_list_mode); \ + ENTRY(prefix, s32, rk_s32, cb_qp_offset, FLAG_PREV, h265, trans_cfg, cb_qp_offset); \ + ENTRY(prefix, s32, rk_s32, cr_qp_offset, FLAG_PREV, h265, trans_cfg, cr_qp_offset); \ + ENTRY(prefix, s32, rk_s32, diff_cu_qp_delta_depth, FLAG_PREV, h265, trans_cfg, diff_cu_qp_delta_depth); \ + ENTRY(prefix, u32, rk_u32, dblk_disable, FLAG_INCR, h265, dblk_cfg, slice_deblocking_filter_disabled_flag); \ + ENTRY(prefix, s32, rk_s32, dblk_alpha, FLAG_PREV, h265, dblk_cfg, slice_beta_offset_div2); \ + ENTRY(prefix, s32, rk_s32, dblk_beta, FLAG_PREV, h265, dblk_cfg, slice_tc_offset_div2); \ + ALIAS(prefix, s32, rk_s32, qp_init, FLAG_REPLAY(0), rc, qp_init); \ + ALIAS(prefix, s32, rk_s32, qp_min, FLAG_REPLAY(1), rc, qp_min); \ + ALIAS(prefix, s32, rk_s32, qp_max, FLAG_REPLAY(1), rc, qp_max); \ + ALIAS(prefix, s32, rk_s32, qp_min_i, FLAG_REPLAY(2), rc, qp_min_i); \ + ALIAS(prefix, s32, rk_s32, qp_max_i, FLAG_REPLAY(2), rc, qp_max_i); \ + ALIAS(prefix, s32, rk_s32, qp_step, FLAG_REPLAY(3), rc, qp_max_step); \ + ALIAS(prefix, s32, rk_s32, qp_delta_ip, FLAG_REPLAY(4), rc, qp_delta_ip); \ + ENTRY(prefix, s32, rk_s32, sao_luma_disable, FLAG_INCR, h265, sao_cfg, slice_sao_luma_disable); \ + ENTRY(prefix, s32, rk_s32, sao_chroma_disable, FLAG_PREV, h265, sao_cfg, slice_sao_chroma_disable); \ + ENTRY(prefix, s32, rk_s32, sao_bit_ratio, FLAG_PREV, h265, sao_cfg, sao_bit_ratio); \ + ENTRY(prefix, u32, rk_u32, lpf_acs_sli_en, FLAG_INCR, h265, lpf_acs_sli_en); \ + ENTRY(prefix, u32, rk_u32, lpf_acs_tile_disable, FLAG_INCR, h265, lpf_acs_tile_disable); \ + ENTRY(prefix, s32, rk_s32, auto_tile, FLAG_INCR, h265, auto_tile); \ + ENTRY(prefix, s32, rk_s32, max_tid, FLAG_INCR, h265, max_tid); \ + ENTRY(prefix, s32, rk_s32, max_ltr, FLAG_INCR, h265, max_ltr_frames); \ + ENTRY(prefix, s32, rk_s32, base_layer_pid, FLAG_INCR, h265, base_layer_pid); \ + ENTRY(prefix, s32, rk_s32, const_intra, FLAG_INCR, h265, const_intra_pred); \ + ENTRY(prefix, s32, rk_s32, lcu_size, FLAG_INCR, h265, max_cu_size); \ + ENTRY(prefix, s32, rk_s32, vui_en, FLAG_INCR, h265, vui, vui_en); \ + STRUCT_END(h265); \ + /* vp8 config */ \ + STRUCT_START(vp8); \ + ENTRY(prefix, s32, rk_s32, disable_ivf, FLAG_BASE(0), vp8, disable_ivf); \ + ALIAS(prefix, s32, rk_s32, qp_init, FLAG_REPLAY(0), rc, qp_init); \ + ALIAS(prefix, s32, rk_s32, qp_min, FLAG_REPLAY(1), rc, qp_min); \ + ALIAS(prefix, s32, rk_s32, qp_max, FLAG_REPLAY(1), rc, qp_max); \ + ALIAS(prefix, s32, rk_s32, qp_min_i, FLAG_REPLAY(2), rc, qp_min_i); \ + ALIAS(prefix, s32, rk_s32, qp_max_i, FLAG_REPLAY(2), rc, qp_max_i); \ + ALIAS(prefix, s32, rk_s32, qp_step, FLAG_REPLAY(3), rc, qp_max_step); \ + ALIAS(prefix, s32, rk_s32, qp_delta_ip, FLAG_REPLAY(4), rc, qp_delta_ip); \ + STRUCT_END(vp8); \ + /* jpeg config */ \ + STRUCT_START(jpeg); \ + ENTRY(prefix, s32, rk_s32, q_mode, FLAG_BASE(0), jpeg, q_mode); \ + ENTRY(prefix, s32, rk_s32, quant, FLAG_INCR, jpeg, quant_ext); \ + ENTRY(prefix, s32, rk_s32, q_factor, FLAG_INCR, jpeg, q_factor_ext); \ + ENTRY(prefix, s32, rk_s32, qf_max, FLAG_PREV, jpeg, qf_max_ext); \ + ENTRY(prefix, s32, rk_s32, qf_min, FLAG_PREV, jpeg, qf_min_ext); \ + ENTRY(prefix, starr, rk_u8, qtable_y, FLAG_INCR, jpeg, qtable_y); \ + ENTRY(prefix, starr, rk_u8, qtable_u, FLAG_PREV, jpeg, qtable_u); \ + ENTRY(prefix, starr, rk_u8, qtable_v, FLAG_PREV, jpeg, qtable_v); \ + STRUCT_END(jpeg); \ + /* split config */ \ + STRUCT_START(split); \ + ENTRY(prefix, u32, rk_u32, mode, FLAG_BASE(0), split, split_mode) \ + ENTRY(prefix, u32, rk_u32, arg, FLAG_INCR, split, split_arg) \ + ENTRY(prefix, u32, rk_u32, out, FLAG_INCR, split, split_out) \ + STRUCT_END(split); \ + /* hardware detail config */ \ + STRUCT_START(hw); \ + ENTRY(prefix, s32, rk_s32, qp_row, FLAG_BASE(0), hw, qp_delta_row) \ + ENTRY(prefix, s32, rk_s32, qp_row_i, FLAG_INCR, hw, qp_delta_row_i) \ + STRCT(prefix, starr, rk_u32, aq_thrd_i, FLAG_INCR, hw, aq_thrd_i) \ + STRCT(prefix, starr, rk_u32, aq_thrd_p, FLAG_INCR, hw, aq_thrd_p) \ + STRCT(prefix, starr, rk_s32, aq_step_i, FLAG_INCR, hw, aq_step_i) \ + STRCT(prefix, starr, rk_s32, aq_step_p, FLAG_INCR, hw, aq_step_p) \ + ENTRY(prefix, s32, rk_s32, mb_rc_disable, FLAG_INCR, hw, mb_rc_disable) \ + STRCT(prefix, starr, rk_s32, aq_rnge_arr, FLAG_INCR, hw, aq_rnge_arr) \ + STRCT(prefix, starr, rk_s32, mode_bias, FLAG_INCR, hw, mode_bias) \ + ENTRY(prefix, s32, rk_s32, skip_bias_en, FLAG_INCR, hw, skip_bias_en) \ + ENTRY(prefix, s32, rk_s32, skip_sad, FLAG_PREV, hw, skip_sad) \ + ENTRY(prefix, s32, rk_s32, skip_bias, FLAG_PREV, hw, skip_bias) \ + ENTRY(prefix, s32, rk_s32, qbias_i, FLAG_INCR, hw, qbias_i) \ + ENTRY(prefix, s32, rk_s32, qbias_p, FLAG_INCR, hw, qbias_p) \ + ENTRY(prefix, s32, rk_s32, qbias_en, FLAG_INCR, hw, qbias_en) \ + STRCT(prefix, st, rk_s32, qbias_arr, FLAG_INCR, hw, qbias_arr) \ + ENTRY(prefix, s32, rk_s32, flt_str_i, FLAG_INCR, hw, flt_str_i) \ + ENTRY(prefix, s32, rk_s32, flt_str_p, FLAG_INCR, hw, flt_str_p) \ + STRUCT_END(hw); \ + /* quality fine tuning config */ \ + STRUCT_START(tune); \ + ENTRY(prefix, s32, rk_s32, scene_mode, FLAG_BASE(0), tune, scene_mode); \ + ENTRY(prefix, s32, rk_s32, se_mode, FLAG_INCR, tune, se_mode); \ + ENTRY(prefix, s32, rk_s32, deblur_en, FLAG_INCR, tune, deblur_en); \ + ENTRY(prefix, s32, rk_s32, deblur_str, FLAG_INCR, tune, deblur_str); \ + ENTRY(prefix, s32, rk_s32, anti_flicker_str, FLAG_INCR, tune, anti_flicker_str); \ + ENTRY(prefix, s32, rk_s32, lambda_idx_i, FLAG_INCR, tune, lambda_idx_i); \ + ENTRY(prefix, s32, rk_s32, lambda_idx_p, FLAG_INCR, tune, lambda_idx_p); \ + ENTRY(prefix, s32, rk_s32, atr_str_i, FLAG_INCR, tune, atr_str_i); \ + ENTRY(prefix, s32, rk_s32, atr_str_p, FLAG_INCR, tune, atr_str_p); \ + ENTRY(prefix, s32, rk_s32, atl_str, FLAG_INCR, tune, atl_str); \ + ENTRY(prefix, s32, rk_s32, sao_str_i, FLAG_INCR, tune, sao_str_i); \ + ENTRY(prefix, s32, rk_s32, sao_str_p, FLAG_INCR, tune, sao_str_p); \ + ENTRY(prefix, s32, rk_s32, rc_container, FLAG_INCR, tune, rc_container); \ + ENTRY(prefix, s32, rk_s32, vmaf_opt, FLAG_INCR, tune, vmaf_opt); \ + ENTRY(prefix, s32, rk_s32, motion_static_switch_enable, FLAG_INCR, tune, motion_static_switch_enable); \ + ENTRY(prefix, s32, rk_s32, atf_str, FLAG_INCR, tune, atf_str); \ + ENTRY(prefix, s32, rk_s32, lgt_chg_lvl, FLAG_INCR, tune, lgt_chg_lvl); \ + ENTRY(prefix, s32, rk_s32, static_frm_num, FLAG_INCR, tune, static_frm_num); \ + ENTRY(prefix, s32, rk_s32, madp16_th, FLAG_INCR, tune, madp16_th); \ + ENTRY(prefix, s32, rk_s32, skip16_wgt, FLAG_INCR, tune, skip16_wgt); \ + ENTRY(prefix, s32, rk_s32, skip32_wgt, FLAG_INCR, tune, skip32_wgt); \ + ENTRY(prefix, s32, rk_s32, speed, FLAG_INCR, tune, speed); \ + ENTRY(prefix, s32, rk_s32, bg_delta_qp_i, FLAG_INCR, tune, bg_delta_qp_i); \ + ENTRY(prefix, s32, rk_s32, bg_delta_qp_p, FLAG_PREV, tune, bg_delta_qp_p); \ + ENTRY(prefix, s32, rk_s32, fg_delta_qp_i, FLAG_PREV, tune, fg_delta_qp_i); \ + ENTRY(prefix, s32, rk_s32, fg_delta_qp_p, FLAG_PREV, tune, fg_delta_qp_p); \ + ENTRY(prefix, s32, rk_s32, bmap_qpmin_i, FLAG_PREV, tune, bmap_qpmin_i); \ + ENTRY(prefix, s32, rk_s32, bmap_qpmin_p, FLAG_PREV, tune, bmap_qpmin_p); \ + ENTRY(prefix, s32, rk_s32, bmap_qpmax_i, FLAG_PREV, tune, bmap_qpmax_i); \ + ENTRY(prefix, s32, rk_s32, bmap_qpmax_p, FLAG_PREV, tune, bmap_qpmax_p); \ + ENTRY(prefix, s32, rk_s32, min_bg_fqp, FLAG_PREV, tune, min_bg_fqp); \ + ENTRY(prefix, s32, rk_s32, max_bg_fqp, FLAG_PREV, tune, max_bg_fqp); \ + ENTRY(prefix, s32, rk_s32, min_fg_fqp, FLAG_PREV, tune, min_fg_fqp); \ + ENTRY(prefix, s32, rk_s32, max_fg_fqp, FLAG_PREV, tune, max_fg_fqp); \ + ENTRY(prefix, s32, rk_s32, fg_area, FLAG_PREV, tune, fg_area); \ + ENTRY(prefix, s32, rk_s32, qpmap_en, FLAG_INCR, tune, qpmap_en); \ + STRUCT_END(tune); \ + CFG_DEF_END() + +static rk_s32 mpp_enc_cfg_impl_init(void *entry, KmppObj obj, const char *caller) +{ + MppEncCfgSet *cfg = (MppEncCfgSet *)entry; + rk_u32 i; + + cfg->rc.max_reenc_times = 1; + + cfg->prep.color = MPP_FRAME_SPC_UNSPECIFIED; + cfg->prep.colorprim = MPP_FRAME_PRI_UNSPECIFIED; + cfg->prep.colortrc = MPP_FRAME_TRC_UNSPECIFIED; + cfg->prep.format_out = MPP_CHROMA_UNSPECIFIED; + cfg->prep.chroma_ds_mode = MPP_FRAME_CHROMA_DOWN_SAMPLE_MODE_NONE; + cfg->prep.fix_chroma_en = 0; + cfg->prep.range_out = MPP_FRAME_RANGE_UNSPECIFIED; + + for (i = 0; i < MPP_ARRAY_ELEMS(cfg->hw.mode_bias); i++) + cfg->hw.mode_bias[i] = 8; + + cfg->hw.skip_sad = 8; + cfg->hw.skip_bias = 8; + + (void) obj; + (void) caller; + + return rk_ok; +} + +static rk_s32 mpp_enc_cfg_impl_dump(void *entry) +{ + MppEncCfgSet *cfg = (MppEncCfgSet *)entry; + rk_u32 *flag; + + if (!cfg) + return rk_nok; + + flag = mpp_enc_cfg_prep_change(cfg); + + mpp_logi("cfg %p prep flag %p\n", cfg, flag); + mpp_logi("prep change %x\n", *flag); + mpp_logi("width %4d -> %4d\n", cfg->prep.width, cfg->prep.width_set); + mpp_logi("height %4d -> %4d\n", cfg->prep.height, cfg->prep.height_set); + mpp_logi("hor_stride %d\n", cfg->prep.hor_stride); + mpp_logi("ver_stride %d\n", cfg->prep.ver_stride); + mpp_logi("format_in %d\n", cfg->prep.format); + mpp_logi("format_out %d\n", cfg->prep.format_out); + mpp_logi("rotation %d -> %d\n", cfg->prep.rotation, cfg->prep.rotation_ext); + mpp_logi("mirroring %d -> %d\n", cfg->prep.mirroring, cfg->prep.mirroring_ext); + + return rk_ok; +} + +#define KMPP_OBJ_NAME mpp_enc_cfg +#define KMPP_OBJ_INTF_TYPE MppEncCfg +#define KMPP_OBJ_IMPL_TYPE MppEncCfgSet +#define KMPP_OBJ_SGLN_ID MPP_SGLN_ENC_CFG +#define KMPP_OBJ_FUNC_INIT mpp_enc_cfg_impl_init +#define KMPP_OBJ_FUNC_DUMP mpp_enc_cfg_impl_dump +#define KMPP_OBJ_ENTRY_TABLE MPP_ENC_CFG_ENTRY_TABLE +#define KMPP_OBJ_ACCESS_DISABLE +#define KMPP_OBJ_HIERARCHY_ENABLE +#include "kmpp_obj_helper.h" + +#define TO_CHANGE_POS(name, ...) \ + static rk_s32 to_change_pos_##name(void) \ + { \ + static rk_s32 CONCAT_US(name, flag, pos) = -1; \ + if (CONCAT_US(name, flag, pos) < 0) { \ + KmppEntry *tbl = NULL; \ + kmpp_objdef_get_entry(mpp_enc_cfg_def, CONCAT_STR(name, __VA_ARGS__), &tbl); \ + CONCAT_US(name, flag, pos) = tbl ? (tbl->tbl.flag_offset / 8) : 0; \ + } \ + return CONCAT_US(name, flag, pos); \ + } + +/* vcodec type -> base.change */ +TO_CHANGE_POS(rc, mode) +TO_CHANGE_POS(prep, width) +TO_CHANGE_POS(h264, stream_type) +TO_CHANGE_POS(h265, profile) +TO_CHANGE_POS(vp8, disable_ivf) +TO_CHANGE_POS(jpeg, q_mode) +TO_CHANGE_POS(hw, qp_row) +TO_CHANGE_POS(tune, scene_mode) + +MPP_RET mpp_enc_cfg_init(MppEncCfg *cfg) +{ + mpp_env_get_u32("mpp_enc_cfg_debug", &mpp_enc_cfg_debug, 0); + + return mpp_enc_cfg_get(cfg); +} + +RK_S32 mpp_enc_cfg_init_k(MppEncCfg *cfg) +{ + mpp_env_get_u32("mpp_enc_cfg_debug", &mpp_enc_cfg_debug, 0); + + return mpp_venc_kcfg_init(cfg, MPP_VENC_KCFG_TYPE_ST_CFG); +} + +RK_S32 mpp_enc_cfg_deinit(MppEncCfg cfg) +{ + return kmpp_obj_put_f(cfg); +} + +#define kmpp_obj_set_S8(obj, name, val) \ + kmpp_obj_set_s8(obj, name, val) +#define kmpp_obj_set_U8(obj, name, val) \ + kmpp_obj_set_u8(obj, name, val) +#define kmpp_obj_set_S16(obj, name, val) \ + kmpp_obj_set_s16(obj, name, val) +#define kmpp_obj_set_U16(obj, name, val) \ + kmpp_obj_set_u16(obj, name, val) +#define kmpp_obj_set_S32(obj, name, val) \ + kmpp_obj_set_s32(obj, name, val) +#define kmpp_obj_set_U32(obj, name, val) \ + kmpp_obj_set_u32(obj, name, val) +#define kmpp_obj_set_S64(obj, name, val) \ + kmpp_obj_set_s64(obj, name, val) +#define kmpp_obj_set_U64(obj, name, val) \ + kmpp_obj_set_u64(obj, name, val) +#define kmpp_obj_set_Ptr(obj, name, val) \ + kmpp_obj_set_ptr(obj, name, val) +#define kmpp_obj_set_St(obj, name, val) \ + kmpp_obj_set_st(obj, name, val) + +#define ENC_CFG_SET_ACCESS(func_name, in_type, cfg_type) \ + MPP_RET func_name(MppEncCfg cfg, const char *name, in_type val) \ + { \ + return kmpp_obj_set_##cfg_type((KmppObj)cfg, name, val); \ + } + +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_s8, RK_S8, S8) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_u8, RK_U8, U8) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_s16, RK_S16, S16) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_u16, RK_U16, U16) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_s32, RK_S32, S32) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_u32, RK_U32, U32) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_s64, RK_S64, S64) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_u64, RK_U64, U64) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_ptr, void *, Ptr) +ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_st, void *, St) + +#define kmpp_obj_get_S8(obj, name, val) \ + kmpp_obj_get_s8(obj, name, val) +#define kmpp_obj_get_U8(obj, name, val) \ + kmpp_obj_get_u8(obj, name, val) +#define kmpp_obj_get_S16(obj, name, val) \ + kmpp_obj_get_s16(obj, name, val) +#define kmpp_obj_get_U16(obj, name, val) \ + kmpp_obj_get_u16(obj, name, val) +#define kmpp_obj_get_S32(obj, name, val) \ + kmpp_obj_get_s32(obj, name, val) +#define kmpp_obj_get_U32(obj, name, val) \ + kmpp_obj_get_u32(obj, name, val) +#define kmpp_obj_get_S64(obj, name, val) \ + kmpp_obj_get_s64(obj, name, val) +#define kmpp_obj_get_U64(obj, name, val) \ + kmpp_obj_get_u64(obj, name, val) +#define kmpp_obj_get_Ptr(obj, name, val) \ + kmpp_obj_get_ptr(obj, name, val) +#define kmpp_obj_get_St(obj, name, val) \ + kmpp_obj_get_st(obj, name, val) + +#define ENC_CFG_GET_ACCESS(func_name, in_type, cfg_type) \ + MPP_RET func_name(MppEncCfg cfg, const char *name, in_type *val) \ + { \ + return kmpp_obj_get_##cfg_type((KmppObj)cfg, name, val); \ + } + +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_s8, RK_S8, S8) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_u8, RK_U8, U8) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_s16, RK_S16, S16) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_u16, RK_U16, U16) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_s32, RK_S32, S32) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_u32, RK_U32, U32) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_s64, RK_S64, S64) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_u64, RK_U64, U64) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_ptr, void *, Ptr) +ENC_CFG_GET_ACCESS(mpp_enc_cfg_get_st, void , St) + +void mpp_enc_cfg_show(void) +{ + MppTrie trie = kmpp_objdef_get_trie(mpp_enc_cfg_def); + MppTrieInfo *root; + + if (!trie) + return; + + mpp_log("dumping valid configure string start\n"); + + root = mpp_trie_get_info_first(trie); + if (root) { + MppTrieInfo *node = root; + rk_s32 len = mpp_trie_get_name_max(trie); + + do { + if (mpp_trie_info_is_self(node)) + continue; + + if (node->ctx_len == sizeof(KmppEntry)) { + KmppEntry *entry = (KmppEntry *)mpp_trie_info_ctx(node); + + mpp_log("%-*s %-6s | %-6d | %-4d | %-4x\n", len, mpp_trie_info_name(node), + strof_elem_type(entry->tbl.elem_type), entry->tbl.elem_offset, + entry->tbl.elem_size, entry->tbl.flag_offset); + } else { + mpp_log("%-*s size - %d\n", len, mpp_trie_info_name(node), node->ctx_len); + } + } while ((node = mpp_trie_get_info_next(trie, node))); + } + mpp_log("dumping valid configure string done\n"); + + mpp_log("enc cfg size %d count %d with trie node %d size %d\n", + sizeof(MppEncCfgSet), mpp_trie_get_info_count(trie), + mpp_trie_get_node_count(trie), mpp_trie_get_buf_size(trie)); +} + +#define GET_ENC_CFG_CHANGE(name) \ + rk_u32 *mpp_enc_cfg_##name##_change(MppEncCfgSet *cfg) \ + { \ + if (cfg) \ + return (rk_u32 *)(POS_TO_FLAG(cfg, to_change_pos_##name())); \ + return NULL; \ + } + +GET_ENC_CFG_CHANGE(prep) +GET_ENC_CFG_CHANGE(rc) +GET_ENC_CFG_CHANGE(hw) +GET_ENC_CFG_CHANGE(tune) +GET_ENC_CFG_CHANGE(h264) +GET_ENC_CFG_CHANGE(h265) +GET_ENC_CFG_CHANGE(jpeg) +GET_ENC_CFG_CHANGE(vp8) + +MPP_RET mpp_enc_cfg_extract(MppEncCfg cfg, MppCfgStrFmt fmt, char **buf) +{ + MppEncCfgSet *cfg_impl = kmpp_obj_to_entry(cfg); + MppCfgObj obj = NULL; + MppCfgObj root = NULL; + + root = kmpp_objdef_get_cfg_root(mpp_enc_cfg_def); + + mpp_cfg_from_struct(&obj, root, cfg_impl); + if (obj) { + mpp_cfg_to_string(obj, fmt, buf); + mpp_cfg_put_all(obj); + } + + return MPP_OK; +} + +MPP_RET mpp_enc_cfg_apply(MppEncCfg cfg, MppCfgStrFmt fmt, char *buf) +{ + MppEncCfgSet *cfg_impl = kmpp_obj_to_entry(cfg); + MppCfgObj obj = NULL; + MppCfgObj root = NULL; + + root = kmpp_objdef_get_cfg_root(mpp_enc_cfg_def); + + mpp_cfg_from_string(&obj, fmt, buf); + if (obj) { + mpp_cfg_to_struct(obj, root, cfg_impl); + mpp_cfg_put_all(obj); + } + + return MPP_OK; +} diff --git a/mpp/base/mpp_enc_ref.c b/mpp/base/mpp_enc_ref.c new file mode 100644 index 000000000..95fce5154 --- /dev/null +++ b/mpp/base/mpp_enc_ref.c @@ -0,0 +1,433 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_enc_ref" + +#include + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_time.h" + +#include "mpp_rc_defs.h" +#include "mpp_enc_ref.h" +#include "mpp_enc_refs.h" + +#define setup_mpp_enc_ref_cfg(ref) \ + ((MppEncRefCfgImpl*)ref)->name = MODULE_TAG; + +MPP_RET _check_is_mpp_enc_ref_cfg(const char *func, void *ref) +{ + if (NULL == ref) { + mpp_err("%s input ref check NULL failed\n", func); + return MPP_NOK; + } + + if (strcmp(((MppEncRefCfgImpl*)(ref))->name, MODULE_TAG) != 0) { + mpp_err("%s input ref check %p %p failed\n", func, ((MppEncRefCfgImpl*)(ref))->name); + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_init(MppEncRefCfg *ref) +{ + if (NULL == ref) { + mpp_err_f("invalid NULL input ref_cfg\n"); + return MPP_ERR_NULL_PTR; + } + + MppEncRefCfgImpl *p = mpp_calloc(MppEncRefCfgImpl, 1); + *ref = p; + if (NULL == p) { + mpp_err_f("malloc failed\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_env_get_u32("enc_ref_cfg_debug", &p->debug, 0); + + setup_mpp_enc_ref_cfg(p); + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_deinit(MppEncRefCfg *ref) +{ + if (!ref || check_is_mpp_enc_ref_cfg(*ref)) { + mpp_err_f("input %p check failed\n", ref); + return MPP_ERR_VALUE; + } + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)(*ref); + MPP_FREE(p->lt_cfg); + MPP_FREE(p->st_cfg); + MPP_FREE(p); + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_reset(MppEncRefCfg ref) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return MPP_ERR_VALUE; + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + MPP_FREE(p->lt_cfg); + MPP_FREE(p->st_cfg); + memset(p, 0, sizeof(*p)); + setup_mpp_enc_ref_cfg(p); + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_set_cfg_cnt(MppEncRefCfg ref, RK_S32 lt_cnt, RK_S32 st_cnt) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return MPP_ERR_NULL_PTR; + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + MppEncRefLtFrmCfg *lt_cfg = p->lt_cfg; + MppEncRefStFrmCfg *st_cfg = p->st_cfg;; + + if (lt_cfg || st_cfg) { + mpp_err_f("do call reset before setup new cnout\n"); + MPP_FREE(lt_cfg); + MPP_FREE(st_cfg); + } + + if (lt_cnt) { + lt_cfg = mpp_calloc(MppEncRefLtFrmCfg, lt_cnt); + if (NULL == lt_cfg) + mpp_log_f("failed to create %d lt ref cfg\n", lt_cnt); + } + + if (st_cnt) { + st_cfg = mpp_calloc(MppEncRefStFrmCfg, st_cnt); + if (NULL == st_cfg) + mpp_log_f("failed to create %d st ref cfg\n", lt_cnt); + } + + p->max_lt_cfg = lt_cnt; + p->max_st_cfg = st_cnt; + p->lt_cfg_cnt = 0; + p->st_cfg_cnt = 0; + p->lt_cfg = lt_cfg; + p->st_cfg = st_cfg; + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_add_lt_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefLtFrmCfg *frm) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return MPP_ERR_VALUE; + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + + if (p->debug) + mpp_log("ref %p add lt %d cfg idx %d tid %d gap %d delay %d ref mode %x\n", + ref, p->lt_cfg_cnt, frm->lt_idx, frm->temporal_id, + frm->lt_gap, frm->lt_delay, frm->ref_mode); + + memcpy(&p->lt_cfg[p->lt_cfg_cnt], frm, sizeof(*frm) * cnt); + p->lt_cfg_cnt += cnt; + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_add_st_cfg(MppEncRefCfg ref, RK_S32 cnt, MppEncRefStFrmCfg *frm) +{ + if (check_is_mpp_enc_ref_cfg(ref)) { + mpp_err_f("input %p check failed\n", ref); + return MPP_ERR_VALUE; + } + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + + if (p->debug) + mpp_log("ref %p add lt %d cfg non %d tid %d gap repeat %d ref mode %x arg %d\n", + ref, p->st_cfg_cnt, frm->is_non_ref, frm->temporal_id, + frm->repeat, frm->ref_mode, frm->ref_arg); + + memcpy(&p->st_cfg[p->st_cfg_cnt], frm, sizeof(*frm) * cnt); + p->st_cfg_cnt += cnt; + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_check(MppEncRefCfg ref) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return MPP_ERR_VALUE; + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + RK_S32 lt_cfg_cnt = p->lt_cfg_cnt; + RK_S32 st_cfg_cnt = p->st_cfg_cnt; + RK_S32 max_lt_ref_cnt = 0; + RK_S32 max_lt_ref_idx = 0; + RK_S32 lt_idx_used_mask = 0; + RK_S32 lt_dryrun_length = 0; + RK_S32 max_st_ref_cnt = 0; + RK_S32 max_st_tid = 0; + RK_S32 st_tid_used_mask = 0; + RK_S32 st_dryrun_length = 0; + RK_S32 ready = 1; + + /* parse and check gop config for encoder */ + if (lt_cfg_cnt) { + RK_S32 pos = 0; + MppEncRefLtFrmCfg *cfg = p->lt_cfg; + + for (pos = 0; pos < lt_cfg_cnt; pos++, cfg++) { + MppEncRefMode ref_mode = cfg->ref_mode; + RK_S32 temporal_id = cfg->temporal_id; + RK_S32 lt_idx = cfg->lt_idx; + RK_U32 lt_idx_mask = 1 << lt_idx; + + /* check lt idx */ + if (lt_idx >= MPP_ENC_MAX_LT_REF_NUM) { + mpp_err_f("ref cfg %p lt cfg %d with invalid lt_idx %d larger than MPP_ENC_MAX_LT_REF_NUM\n", + ref, pos, lt_idx); + ready = 0; + } + + if (lt_idx_used_mask & lt_idx_mask) { + mpp_err_f("ref cfg %p lt cfg %d with redefined lt_idx %d config\n", + ref, pos, lt_idx); + ready = 0; + } + + if (!(lt_idx_used_mask & lt_idx_mask)) { + lt_idx_used_mask |= lt_idx_mask; + max_lt_ref_cnt++; + } + + if (lt_idx > max_lt_ref_idx) + max_lt_ref_idx = lt_idx; + + /* check temporal id */ + if (temporal_id != 0) { + mpp_err_f("ref cfg %p lt cfg %d with invalid temporal_id %d is non-zero\n", + ref, pos, temporal_id); + ready = 0; + } + + /* check gop mode */ + if (!REF_MODE_IS_GLOBAL(ref_mode) && !REF_MODE_IS_LT_MODE(ref_mode)) { + mpp_err_f("ref cfg %p lt cfg %d with invalid ref mode %x\n", + ref, pos, ref_mode); + ready = 0; + } + + /* if check failed just quit */ + if (!ready) + break; + + if (cfg->lt_gap && (cfg->lt_gap + cfg->lt_delay > lt_dryrun_length)) + lt_dryrun_length = cfg->lt_gap + cfg->lt_delay; + } + } + + /* check st-ref config */ + if (ready && st_cfg_cnt) { + RK_S32 pos = 0; + MppEncRefStFrmCfg *cfg = p->st_cfg; + + for (pos = 0; pos < st_cfg_cnt; pos++, cfg++) { + MppEncRefMode ref_mode = cfg->ref_mode; + RK_S32 temporal_id = cfg->temporal_id; + RK_U32 tid_mask = 1 << temporal_id; + + /* check temporal_id */ + if (temporal_id > MPP_ENC_MAX_TEMPORAL_LAYER_NUM - 1) { + mpp_err_f("ref cfg %p st cfg %d with invalid temporal_id %d larger than MPP_ENC_MAX_TEMPORAL_LAYER_NUM\n", + ref, pos, temporal_id); + ready = 0; + } + + /* check gop mode */ + if (!REF_MODE_IS_GLOBAL(ref_mode) && !REF_MODE_IS_ST_MODE(ref_mode)) { + mpp_err_f("ref cfg %p st cfg %d with invalid ref mode %x\n", + ref, pos, ref_mode); + ready = 0; + } + + if (cfg->repeat < 0) { + mpp_err_f("ref cfg %p st cfg %d with negative repeat %d set to zero\n", + ref, pos, cfg->repeat); + cfg->repeat = 0; + } + + /* constrain on head and tail frame */ + if (pos == 0 || (pos == st_cfg_cnt - 1)) { + if (cfg->is_non_ref) { + mpp_err_f("ref cfg %p st cfg %d with invalid non-ref frame on head/tail frame\n", + ref, pos); + ready = 0; + } + + if (temporal_id > 0) { + mpp_err_f("ref cfg %p st cfg %d with invalid non-zero temporal id %d on head/tail frame\n", + ref, pos, temporal_id); + ready = 0; + } + } + + if (!ready) + break; + + if (!cfg->is_non_ref && !(st_tid_used_mask & tid_mask)) { + max_st_ref_cnt++; + st_tid_used_mask |= tid_mask; + } + + if (temporal_id > max_st_tid) + max_st_tid = temporal_id; + + st_dryrun_length++; + st_dryrun_length += cfg->repeat; + } + } + + if (ready) { + MppEncCpbInfo *cpb_info = &p->cpb_info; + MppEncRefs refs = NULL; + MPP_RET ret = MPP_OK; + + cpb_info->dpb_size = 0; + cpb_info->max_lt_cnt = max_lt_ref_cnt; + cpb_info->max_st_cnt = max_st_ref_cnt; + cpb_info->max_lt_idx = max_lt_ref_idx; + cpb_info->max_st_tid = max_st_tid; + cpb_info->lt_gop = lt_dryrun_length; + cpb_info->st_gop = st_dryrun_length - 1; + + ret = mpp_enc_refs_init(&refs); + ready = (ret) ? 0 : (ready); + ret = mpp_enc_refs_set_cfg(refs, ref); + ready = (ret) ? 0 : (ready); + ret = mpp_enc_refs_dryrun(refs); + ready = (ret) ? 0 : (ready); + + /* update dpb size */ + ret = mpp_enc_refs_get_cpb_info(refs, cpb_info); + ready = (ret) ? 0 : (ready); + + ret = mpp_enc_refs_deinit(&refs); + ready = (ret) ? 0 : (ready); + } else { + mpp_err_f("check ref cfg %p failed\n", ref); + } + p->ready = ready; + + return ready ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_enc_ref_cfg_set_keep_cpb(MppEncRefCfg ref, RK_S32 keep) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return MPP_ERR_VALUE; + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + p->keep_cpb = keep; + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_show(MppEncRefCfg ref) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return MPP_ERR_VALUE; + + return MPP_OK; +} + +MPP_RET mpp_enc_ref_cfg_copy(MppEncRefCfg dst, MppEncRefCfg src) +{ + if (check_is_mpp_enc_ref_cfg(dst) || check_is_mpp_enc_ref_cfg(src)) + return MPP_ERR_VALUE; + + MPP_RET ret = MPP_OK; + MppEncRefCfgImpl *d = (MppEncRefCfgImpl *)dst; + MppEncRefCfgImpl *s = (MppEncRefCfgImpl *)src; + RK_S32 max_lt_cfg = s->max_lt_cfg; + RK_S32 max_st_cfg = s->max_st_cfg; + + /* step 1 - free cfg in dst */ + MPP_FREE(d->lt_cfg); + MPP_FREE(d->st_cfg); + + /* step 2 - copy contex from src */ + memcpy(d, s, sizeof(*d)); + + /* step 3 - create new storage and copy lt/st cfg */ + if (max_lt_cfg) { + MppEncRefLtFrmCfg *lt_cfg = mpp_calloc(MppEncRefLtFrmCfg, max_lt_cfg); + + if (NULL == lt_cfg) { + mpp_log_f("failed to create %d lt ref cfg\n", max_lt_cfg); + ret = MPP_NOK; + } else + memcpy(lt_cfg, s->lt_cfg, sizeof(lt_cfg[0]) * s->max_lt_cfg); + + d->lt_cfg = lt_cfg; + } + + if (max_st_cfg) { + MppEncRefStFrmCfg *st_cfg = mpp_calloc(MppEncRefStFrmCfg, max_st_cfg); + + if (NULL == st_cfg) { + mpp_log_f("failed to create %d st ref cfg\n", max_st_cfg); + ret = MPP_NOK; + } else + memcpy(st_cfg, s->st_cfg, sizeof(st_cfg[0]) * s->max_st_cfg); + + d->st_cfg = st_cfg; + } + + if (ret) + mpp_enc_ref_cfg_reset(dst); + + return ret; +} + +MppEncCpbInfo *mpp_enc_ref_cfg_get_cpb_info(MppEncRefCfg ref) +{ + if (check_is_mpp_enc_ref_cfg(ref)) + return NULL; + + MppEncRefCfgImpl *p = (MppEncRefCfgImpl *)ref; + return &p->cpb_info; +} + +static MppEncRefStFrmCfg default_st_ref_cfg = { + .is_non_ref = 0, + .temporal_id = 0, + .ref_mode = REF_TO_PREV_REF_FRM, + .ref_arg = 0, + .repeat = 0, +}; + +static const MppEncRefCfgImpl default_ref_cfg = { + .name = MODULE_TAG, + .ready = 1, + .debug = 0, + .keep_cpb = 0, + .max_lt_cfg = 0, + .max_st_cfg = 1, + .lt_cfg_cnt = 0, + .st_cfg_cnt = 1, + .max_tlayers = 1, + .lt_cfg = NULL, + .st_cfg = &default_st_ref_cfg, + .cpb_info = { 1, 0, 1, 0, 0, 0, 0 }, +}; + +MppEncRefCfg mpp_enc_ref_default(void) +{ + return (MppEncRefCfg)&default_ref_cfg; +} diff --git a/mpp/base/mpp_enc_refs.c b/mpp/base/mpp_enc_refs.c new file mode 100644 index 000000000..e9cd8255e --- /dev/null +++ b/mpp/base/mpp_enc_refs.c @@ -0,0 +1,1095 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_enc_refs" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_enc_ref.h" +#include "mpp_enc_refs.h" + +#define MAX_CPB_ST_FRM 16 +#define MAX_CPB_LT_FRM 16 +#define MAX_CPB_TID_FRM 16 +#define MAX_CPB_LT_IDX 16 +#define MAX_CPB_FRM ((MAX_CPB_ST_FRM) + (MAX_CPB_LT_FRM)) + +#define MPP_ENC_REFS_DBG_FUNC (0x00000001) +#define MPP_ENC_REFS_DBG_FLOW (0x00000002) +#define MPP_ENC_REFS_DBG_FRM (0x00000004) +#define MPP_ENC_REFS_DBG_SIZE (0x00000008) + +#define enc_refs_dbg_func(fmt, ...) mpp_dbg_f(enc_refs_debug, MPP_ENC_REFS_DBG_FUNC, fmt, ## __VA_ARGS__) +#define enc_refs_dbg_flow(fmt, ...) mpp_dbg_f(enc_refs_debug, MPP_ENC_REFS_DBG_FLOW, fmt, ## __VA_ARGS__) +#define enc_refs_dbg_frm(fmt, ...) mpp_dbg(enc_refs_debug, MPP_ENC_REFS_DBG_FRM, fmt, ## __VA_ARGS__) +#define enc_refs_dbg_size(fmt, ...) mpp_dbg(enc_refs_debug, MPP_ENC_REFS_DBG_SIZE, fmt, ## __VA_ARGS__) + +#define ENC_REFS_REF_CFG_CHANGED (0x00000001) +#define ENC_REFS_USR_CFG_CHANGED (0x00000002) +#define ENC_REFS_IGOP_CHANGED (0x00000004) + +typedef struct RefsCnt_t { + RK_S32 delay; + RK_S32 delay_cnt; + RK_S32 len; + RK_S32 cnt; + RK_S32 idx; + + RK_S32 lt_idx; + RK_S32 tid; + MppEncRefMode ref_mode; + RK_S32 ref_arg; +} RefsCnt; + +typedef struct EncVirtualCpb_t { + MppEncCpbInfo info; + + /* + * max 32 reference slot for frame searching + * (max 16 lt + max 16 st) + * st_slot 0 ~ 15 + * lt_slot 16 ~ 31 + */ + EncFrmStatus cpb_refs[MAX_CPB_FRM]; + + /* max 32 reference mode */ + EncFrmStatus mode_refs[MAX_CPB_FRM]; + + /* + * reference mode storage with args + * st + tid - max 16 + * lt + idx - max 16 + */ + EncFrmStatus st_tid_refs[MAX_CPB_TID_FRM]; + EncFrmStatus lt_idx_refs[MAX_CPB_LT_IDX]; + + /* long-term counter */ + /* lt ref will have multiple counters */ + RefsCnt lt_cnter[MAX_CPB_LT_IDX]; + + /* max two list and each list as two frames */ + EncFrmStatus list0[2]; + EncFrmStatus list1[2]; + /* frame kept in cpb */ + EncFrmStatus cpb_st[2]; + + /* runtime record */ + RK_S32 frm_idx; /* overall frame index */ + RK_S32 seq_idx; /* sequence index in one gop */ + RK_S32 seq_cnt; + RK_S32 st_cfg_pos; + RK_S32 st_cfg_repeat_pos; +} EncVirtualCpb; + +typedef struct MppEncRefsImpl_t { + RK_U32 changed; + MppEncRefCfgImpl *ref_cfg; + MppEncRefFrmUsrCfg usr_cfg; + RK_S32 igop; + RK_S32 force_recon; + RK_U32 refresh_length; + + RK_S32 hdr_need_update; + + EncVirtualCpb cpb; + EncVirtualCpb cpb_stash; +} MppEncRefsImpl; + +RK_U32 enc_refs_debug = 0; + +void _dump_frm(EncFrmStatus *frm, const char *func, RK_S32 line) +{ + if (!frm->valid) + return ; + + if (frm->is_non_ref) { + mpp_log("%s:%d valid %d frm %d %s tid %d non-ref -> [%x:%d]\n", + func, line, frm->valid, frm->seq_idx, + (frm->is_intra != 0) ? "intra" : "inter", + frm->temporal_id, frm->ref_mode, frm->ref_arg); + } else if (frm->is_lt_ref) { + mpp_log("%s:%d valid %d frm %d %s tid %d lt-ref -> [%x:%d] lt_idx %d\n", + func, line, frm->valid, frm->seq_idx, + (frm->is_intra != 0) ? "intra" : "inter", + frm->temporal_id, frm->ref_mode, frm->ref_arg, + frm->lt_idx); + } else { + mpp_log("%s:%d valid %d frm %d %s tid %d st-ref -> [%x:%d]\n", + func, line, frm->valid, frm->seq_idx, + (frm->is_intra != 0) ? "intra" : "inter", + frm->temporal_id, frm->ref_mode, frm->ref_arg); + } +} + +#define dump_cpb(cpb) _dump_cpb(cpb, __FUNCTION__, __LINE__) + +void _dump_cpb(EncVirtualCpb *cpb, const char *func, RK_S32 line) +{ + MppEncCpbInfo *info = &cpb->info; + RK_S32 i; + + mpp_log("%s:%d cpb %p status:\n", func, line, cpb); + mpp_log("cpb info: dpb_size %d max_lt/st cnt [%d:%d] \n", + info->dpb_size, info->max_lt_cnt, info->max_st_cnt); + mpp_log("cpb info: max_lt_idx %d max_st_tid %d\n", + info->max_lt_idx, info->max_st_tid); + mpp_log("cpb info: lt_gop %d st_gop %d\n", + info->lt_gop, info->st_gop); + + mpp_log("cpb cpb_refs:\n"); + for (i = 0; i < MAX_CPB_FRM; i++) + dump_frm(&cpb->cpb_refs[i]); + + mpp_log("cpb mode_refs:\n"); + for (i = 0; i < MAX_CPB_FRM; i++) + dump_frm(&cpb->mode_refs[i]); + + mpp_log("cpb st_tid_refs:\n"); + for (i = 0; i < MAX_CPB_TID_FRM; i++) + dump_frm(&cpb->st_tid_refs[i]); + + mpp_log("cpb lt_idx_refs:\n"); + for (i = 0; i < MAX_CPB_LT_IDX; i++) + dump_frm(&cpb->lt_idx_refs[i]); + + mpp_log("cpb runtime: frm_idx %d seq_idx %d seq_cnt %d st_cfg [%d:%d]\n", + cpb->frm_idx, cpb->seq_idx, cpb->seq_cnt, + cpb->st_cfg_pos, cpb->st_cfg_repeat_pos); +} + +MPP_RET mpp_enc_refs_init(MppEncRefs *refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_NULL_PTR; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = mpp_calloc(MppEncRefsImpl, 1); + *refs = p; + if (NULL == p) { + mpp_err_f("create refs_impl failed\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_env_get_u32("enc_refs_debug", &enc_refs_debug, 0); + + enc_refs_dbg_func("leave %p\n", p); + return MPP_OK; +} + +MPP_RET mpp_enc_refs_deinit(MppEncRefs *refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)(*refs); + MPP_FREE(p); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +MPP_RET mpp_enc_refs_set_cfg(MppEncRefs refs, MppEncRefCfg ref_cfg) +{ + if (NULL == refs || (ref_cfg && check_is_mpp_enc_ref_cfg(ref_cfg))) { + mpp_err_f("invalid input refs %p ref_cfg %p\n", refs, ref_cfg); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p cfg %p\n", refs, ref_cfg); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + EncVirtualCpb *cpb = &p->cpb; + MppEncRefCfgImpl *cfg = NULL; + + if (NULL == ref_cfg) + ref_cfg = mpp_enc_ref_default(); + + cfg = (MppEncRefCfgImpl *)ref_cfg; + + p->ref_cfg = cfg; + p->changed |= ENC_REFS_REF_CFG_CHANGED; + p->hdr_need_update = 0; + + /* clear cpb on setup new cfg */ + if (!cfg->keep_cpb) { + memset(cpb, 0, sizeof(*cpb)); + p->hdr_need_update = 1; + } + + if (cfg->lt_cfg_cnt) { + RK_S32 i; + + mpp_assert(cfg->lt_cfg_cnt < MAX_CPB_LT_FRM); + + for (i = 0; i < cfg->lt_cfg_cnt; i++) { + RefsCnt *lt_cnt = &cpb->lt_cnter[i]; + MppEncRefLtFrmCfg *lt_cfg = &cfg->lt_cfg[i]; + + lt_cnt->delay = lt_cfg->lt_delay; + lt_cnt->delay_cnt = lt_cfg->lt_delay; + lt_cnt->len = lt_cfg->lt_gap; + lt_cnt->lt_idx = lt_cfg->lt_idx; + lt_cnt->tid = lt_cfg->temporal_id; + lt_cnt->ref_mode = lt_cfg->ref_mode; + lt_cnt->ref_arg = lt_cfg->ref_arg; + } + } + + MppEncCpbInfo *info = &cpb->info; + + if (info->dpb_size && info->dpb_size < cfg->cpb_info.dpb_size) + p->hdr_need_update = 1; + + memcpy(info, &cfg->cpb_info, sizeof(cfg->cpb_info)); + + enc_refs_dbg_flow("ref_cfg cpb size: lt %d st %d max lt_idx %d tid %d\n", + info->max_lt_cnt, info->max_st_cnt, + info->max_lt_idx, info->max_st_tid); + + enc_refs_dbg_func("leave %p cfg %p\n", refs, ref_cfg); + return MPP_OK; +} + +static void cleanup_cpb_refs(EncVirtualCpb *cpb) +{ + RK_U32 i; + + memset(cpb->cpb_refs, 0, sizeof(cpb->cpb_refs)); + memset(cpb->mode_refs, 0, sizeof(cpb->mode_refs)); + memset(cpb->st_tid_refs, 0, sizeof(cpb->st_tid_refs)); + memset(cpb->lt_idx_refs, 0, sizeof(cpb->lt_idx_refs)); + memset(cpb->list0, 0, sizeof(cpb->list0)); + memset(cpb->list1, 0, sizeof(cpb->list1)); + memset(cpb->cpb_st, 0, sizeof(cpb->cpb_st)); + + cpb->seq_idx = 0; + cpb->seq_cnt++; + cpb->st_cfg_pos = 0; + cpb->st_cfg_repeat_pos = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(cpb->lt_cnter); i++) { + RefsCnt *lt_cnt = &cpb->lt_cnter[i]; + + lt_cnt->delay_cnt = lt_cnt->delay; + lt_cnt->cnt = 0; + lt_cnt->idx = 0; + } +} + +static void set_st_cfg_to_frm(EncFrmStatus *frm, RK_S32 seq_idx, + MppEncRefStFrmCfg *st_cfg) +{ + memset(frm, 0, sizeof(*frm)); + + frm->seq_idx = seq_idx; + frm->valid = 1; + frm->is_idr = (seq_idx == 0); + frm->is_intra = frm->is_idr; + frm->is_non_ref = st_cfg->is_non_ref; + frm->is_lt_ref = 0; + frm->temporal_id = st_cfg->temporal_id; + frm->ref_mode = st_cfg->ref_mode; + frm->ref_arg = st_cfg->ref_arg; + + if (enc_refs_debug & MPP_ENC_REFS_DBG_FRM) + dump_frm(frm); +} + +static MPP_RET set_frm_refresh_flag(EncFrmStatus *frm, MppEncRefsImpl *p) +{ + MPP_RET ret = MPP_OK; + + if (!frm || !p) + return ret = MPP_ERR_NULL_PTR; + + if (p->refresh_length) { + frm->is_i_refresh = ((frm->seq_idx % p->igop) < p->refresh_length) && p->cpb.seq_cnt > 1; + frm->is_i_recovery = !(frm->seq_idx % p->igop) && p->cpb.seq_cnt > 1; + } else + frm->is_i_refresh = 0; + + return ret; +} + +static void set_lt_cfg_to_frm(EncFrmStatus *frm, RefsCnt *lt_cfg) +{ + frm->is_non_ref = 0; + frm->is_lt_ref = 1; + frm->temporal_id = lt_cfg->tid; + frm->lt_idx = lt_cfg->lt_idx; + + if (lt_cfg->ref_mode != REF_TO_ST_REF_SETUP) { + frm->ref_mode = lt_cfg->ref_mode; + frm->ref_arg = lt_cfg->ref_arg; + } + + if (enc_refs_debug & MPP_ENC_REFS_DBG_FRM) + dump_frm(frm); +} + +static EncFrmStatus *get_ref_from_cpb(EncVirtualCpb *cpb, EncFrmStatus *frm) +{ + MppEncRefMode ref_mode = frm->ref_mode; + RK_S32 ref_arg = frm->ref_arg; + + if (frm->is_idr) + return NULL; + + EncFrmStatus *ref = NULL; + + /* step 3.1 find seq_idx by mode and arg */ + switch (ref_mode) { + case REF_TO_PREV_REF_FRM : + case REF_TO_PREV_ST_REF : + case REF_TO_PREV_LT_REF : + case REF_TO_PREV_INTRA : { + ref = &cpb->mode_refs[ref_mode]; + } break; + case REF_TO_TEMPORAL_LAYER : { + ref = &cpb->st_tid_refs[ref_arg]; + } break; + case REF_TO_LT_REF_IDX : { + ref = &cpb->lt_idx_refs[ref_arg]; + } break; + case REF_TO_ST_PREV_N_REF : { + ref = &cpb->cpb_refs[ref_arg]; + } break; + case REF_TO_ST_REF_SETUP : + default : { + mpp_err_f("frm %d not supported ref mode 0x%x\n", frm->seq_idx, ref_mode); + } break; + } + + if (ref) { + if (ref->valid) + enc_refs_dbg_flow("frm %d ref mode %d arg %d -> seq %d %s idx %d\n", + frm->seq_idx, ref_mode, ref_arg, ref->seq_idx, + (ref->is_lt_ref != 0) ? "lt" : "st", + (ref->is_lt_ref != 0) ? ref->lt_idx : 0); + else + mpp_err_f("frm %d found mode %d arg %d -> ref %d but it is invalid\n", + frm->seq_idx, ref_mode, ref_arg, ref->seq_idx); + } else { + ref = NULL; + } + + return ref; +} + +static RK_S32 check_ref_cpb_pos(EncVirtualCpb *cpb, EncFrmStatus *frm) +{ + RK_S32 seq_idx = frm->seq_idx; + RK_S32 found = 0; + RK_S32 pos = -1; + + if (!frm->valid || frm->is_non_ref) { + enc_refs_dbg_flow("frm %d is not valid ref frm\n", seq_idx); + return pos; + } + + if (frm->is_lt_ref) { + /* find same lt_idx */ + for (pos = 0; pos < MAX_CPB_LT_FRM; pos++) { + RK_S32 cpb_idx = pos + MAX_CPB_ST_FRM; + EncFrmStatus *cpb_ref = &cpb->cpb_refs[cpb_idx]; + + if (cpb_ref->valid && cpb_ref->lt_idx == frm->lt_idx) { + pos = cpb_idx; + enc_refs_dbg_flow("found ltr ref %d at pos %d\n", seq_idx, pos); + found = 1; + break; + } + } + } else { + /* search seq_idx in cpb to check the st cpb size */ + for (pos = 0; pos < MAX_CPB_ST_FRM; pos++) { + EncFrmStatus *cpb_ref = &cpb->cpb_refs[pos]; + + enc_refs_dbg_flow("matching ref %d at pos %d %d\n", + seq_idx, pos, cpb_ref->seq_idx); + + if (cpb_ref->valid && cpb_ref->seq_idx == seq_idx) { + enc_refs_dbg_flow("found ref %d at pos %d\n", seq_idx, pos); + found = 1; + break; + } + } + } + + if (!found) { + mpp_err_f("frm %d can NOT be found in st refs!!\n", seq_idx); + pos = -1; + dump_cpb(cpb); + } + + return pos; +} + +static void save_cpb_status(EncVirtualCpb *cpb, EncFrmStatus *refs) +{ + EncFrmStatus *ref = &cpb->cpb_refs[MAX_CPB_ST_FRM]; + MppEncCpbInfo *info = &cpb->info; + RK_S32 dpb_size = info->dpb_size; + RK_S32 lt_ref_cnt = 0; + RK_S32 st_ref_cnt = 0; + RK_S32 ref_cnt = 0; + RK_S32 i; + + /* save lt ref */ + for (i = 0; i < info->max_lt_cnt; i++, ref++) { + if (!ref->valid || ref->is_non_ref || !ref->is_lt_ref) + continue; + + mpp_assert(!ref->is_non_ref); + mpp_assert(ref->is_lt_ref); + mpp_assert(ref->lt_idx >= 0); + + enc_refs_dbg_flow("save lt ref %d to slot %d\n", ref->seq_idx, ref_cnt); + refs[ref_cnt++].val = ref->val; + lt_ref_cnt++; + } + + ref = &cpb->cpb_refs[0]; + /* save st ref */ + if (ref_cnt < dpb_size) { + RK_S32 max_st_cnt = info->max_st_cnt; + + if (max_st_cnt < dpb_size - ref_cnt) + max_st_cnt = dpb_size - ref_cnt; + + for (i = 0; i < max_st_cnt; i++, ref++) { + if (!ref->valid || ref->is_non_ref || ref->is_lt_ref) + continue; + + mpp_assert(!ref->is_non_ref); + mpp_assert(!ref->is_lt_ref); + mpp_assert(ref->temporal_id >= 0); + + enc_refs_dbg_flow("save st ref %d to slot %d\n", ref->seq_idx, ref_cnt); + refs[ref_cnt++].val = ref->val; + st_ref_cnt++; + } + } + + enc_refs_dbg_flow("save ref total %d lt %d st %d\n", ref_cnt, lt_ref_cnt, st_ref_cnt); + if (enc_refs_debug & MPP_ENC_REFS_DBG_FLOW) + for (i = 0; i < ref_cnt; i++) + dump_frm(&refs[i]); +} + +static void store_ref_to_cpb(EncVirtualCpb *cpb, EncFrmStatus *frm) +{ + RK_S32 seq_idx = frm->seq_idx; + RK_S32 lt_idx = frm->lt_idx; + RK_S32 tid = frm->temporal_id; + RK_S32 i; + + mpp_assert(frm->valid); + mpp_assert(lt_idx < MAX_CPB_LT_IDX); + mpp_assert(tid < MAX_CPB_LT_FRM); + + /* non-ref do not save to cpb */ + if (frm->is_non_ref) + return ; + + if (frm->is_intra) + cpb->mode_refs[REF_TO_PREV_INTRA].val = frm->val; + + if (frm->is_lt_ref) { + cpb->lt_idx_refs[lt_idx].val = frm->val; + cpb->st_tid_refs[tid].val = frm->val; + cpb->mode_refs[REF_TO_PREV_REF_FRM].val = frm->val; + cpb->mode_refs[REF_TO_PREV_LT_REF].val = frm->val; + + RK_S32 found = 0; + EncFrmStatus *cpb_ref = NULL; + + /* find same lt_idx and replace */ + for (i = 0; i < MAX_CPB_LT_FRM; i++) { + RK_S32 cpb_idx = i + MAX_CPB_ST_FRM; + cpb_ref = &cpb->cpb_refs[cpb_idx]; + + if (!cpb_ref->valid) { + found = 1; + break; + } else { + if (cpb_ref->lt_idx == lt_idx) { + found = 2; + break; + } + } + } + + if (found) { + cpb_ref->val = frm->val; + enc_refs_dbg_flow("frm %d with lt idx %d %s to pos %d\n", + seq_idx, lt_idx, (found == 1) ? "add" : "replace", i); + } else { + mpp_err_f("frm %d with lt idx %d found no place to add or relace\n", + seq_idx, lt_idx); + } + } else { + /* do normal st sliding window */ + cpb->st_tid_refs[tid].val = frm->val; + cpb->mode_refs[REF_TO_PREV_REF_FRM].val = frm->val; + cpb->mode_refs[REF_TO_PREV_ST_REF].val = frm->val; + + for (i = MAX_CPB_ST_FRM - 1; i > 0; i--) + cpb->cpb_refs[i].val = cpb->cpb_refs[i - 1].val; + + cpb->cpb_refs[0].val = frm->val; + + // TODO: Add prev intra valid check? + } + + enc_refs_dbg_flow("dumping cpb refs status start\n"); + if (enc_refs_debug & MPP_ENC_REFS_DBG_FLOW) + for (i = 0; i < MAX_CPB_FRM; i++) + if (cpb->cpb_refs[i].valid) + dump_frm(&cpb->cpb_refs[i]); + + enc_refs_dbg_flow("dumping cpb refs status done\n"); +} + +MPP_RET mpp_enc_refs_dryrun(MppEncRefs refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + MppEncRefCfgImpl *cfg = p->ref_cfg; + MppEncRefStFrmCfg *st_cfg = cfg->st_cfg; + EncVirtualCpb *cpb = &p->cpb; + MppEncCpbInfo *info = &cpb->info; + RK_S32 lt_cfg_cnt = cfg->lt_cfg_cnt; + RK_S32 st_cfg_cnt = cfg->st_cfg_cnt; + RK_S32 cpb_st_used_size = 0; + RK_S32 seq_idx = 0; + RK_S32 st_idx; + RK_S32 walk_len = MPP_MAX(lt_cfg_cnt, st_cfg_cnt); + + if (cfg->ready) + goto DONE; + + cleanup_cpb_refs(cpb); + + cfg->max_tlayers = cpb->info.max_st_tid + 1; + enc_refs_dbg_flow("dryrun start: lt_cfg %d st_cfg %d\n", + lt_cfg_cnt, st_cfg_cnt); + + for (st_idx = 0; st_idx < walk_len; st_idx++) { + st_cfg = &cfg->st_cfg[st_idx % st_cfg_cnt]; + EncFrmStatus frm; + RK_S32 repeat = (st_cfg->repeat != 0) ? st_cfg->repeat : 1; + + while (repeat-- > 0) { + /* step 1. updated by st_cfg */ + set_st_cfg_to_frm(&frm, seq_idx++, st_cfg); + set_frm_refresh_flag(&frm, p); + + /* step 2. updated by lt_cfg */ + RefsCnt *lt_cfg = &cpb->lt_cnter[0]; + RK_S32 set_to_lt = 0; + RK_S32 i; + + for (i = 0; i < lt_cfg_cnt; i++, lt_cfg++) { + if (lt_cfg->delay_cnt) { + lt_cfg->delay_cnt--; + continue; + } + + if (!set_to_lt) { + if (!lt_cfg->cnt) { + set_lt_cfg_to_frm(&frm, lt_cfg); + set_to_lt = 1; + } + } + + lt_cfg->cnt++; + if (lt_cfg->cnt >= lt_cfg->len) { + if (lt_cfg->len) { + /* when there is loop len loop lt_cfg */ + lt_cfg->cnt = 0; + lt_cfg->idx++; + } else { + /* else just set lt_cfg once */ + lt_cfg->cnt = 1; + lt_cfg->idx = 1; + } + } + } + + /* step 3. try find ref by the ref_mode and update used cpb size */ + EncFrmStatus *ref = get_ref_from_cpb(cpb, &frm); + + if (ref) { + RK_S32 cpb_pos = check_ref_cpb_pos(cpb, ref); + + if (cpb_pos < MAX_CPB_ST_FRM) { + if (cpb_st_used_size < cpb_pos + 1) { + cpb_st_used_size = cpb_pos + 1; + enc_refs_dbg_flow("cpb_st_used_size update to %d\n", cpb_st_used_size); + } + } + } + + /* step 4. store frame according to status */ + store_ref_to_cpb(cpb, &frm); + } + } + + cleanup_cpb_refs(cpb); + info->max_st_cnt = (cpb_st_used_size != 0) ? cpb_st_used_size : 1; + +DONE: + info->dpb_size = info->max_lt_cnt + info->max_st_cnt; + + enc_refs_dbg_size("dryrun success: cpb size %d\n", info->dpb_size); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +MPP_RET mpp_enc_refs_set_usr_cfg(MppEncRefs refs, MppEncRefFrmUsrCfg *cfg) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + memcpy(&p->usr_cfg, cfg, sizeof(p->usr_cfg)); + if (cfg->force_flag) + p->changed |= ENC_REFS_USR_CFG_CHANGED; + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +MPP_RET mpp_enc_refs_set_rc_igop(MppEncRefs refs, RK_S32 igop) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + + if (p->igop != igop) { + p->igop = igop; + p->changed |= ENC_REFS_IGOP_CHANGED; + } + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +MPP_RET mpp_enc_refs_set_refresh_length(MppEncRefs refs, RK_S32 len) +{ + MPP_RET ret = MPP_OK; + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + + if (len < p->igop) { + p->refresh_length = len; + } else { + p->refresh_length = p->igop; + ret = MPP_ERR_VALUE; + goto RET; + } + enc_refs_dbg_func("leave %p\n", refs); +RET: + return ret; +} + +RK_S32 mpp_enc_refs_update_hdr(MppEncRefs refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return 0; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + RK_S32 hdr_need_update = p->hdr_need_update; + + enc_refs_dbg_func("leave %p\n", refs); + return hdr_need_update; +} + +MPP_RET mpp_enc_refs_get_cpb_info(MppEncRefs refs, MppEncCpbInfo *info) +{ + if (NULL == refs || NULL == info) { + mpp_err_f("invalid input refs %p info %p\n", refs, info); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + memcpy(info, &p->cpb.info, sizeof(*info)); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +static RK_S32 get_cpb_st_cfg_pos(EncVirtualCpb *cpb, MppEncRefCfgImpl *cfg) +{ + RK_S32 st_cfg_pos = cpb->st_cfg_pos; + RK_S32 st_cfg_cnt = cfg->st_cfg_cnt; + + /* NOTE: second loop will start from 1 */ + if (st_cfg_pos >= st_cfg_cnt) + st_cfg_pos = (st_cfg_cnt > 1) ? (1) : (0); + + return st_cfg_pos; +} + +MPP_RET mpp_enc_refs_get_cpb(MppEncRefs refs, EncCpbStatus *status) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + MppEncRefCfgImpl *cfg = p->ref_cfg; + EncVirtualCpb *cpb = &p->cpb; + MppEncRefStFrmCfg *st_cfg = NULL; + MppEncRefFrmUsrCfg *usr_cfg = &p->usr_cfg; + EncFrmStatus *frm = &status->curr; + EncFrmStatus *ref = &status->refr; + RefsCnt *lt_cfg = cpb->lt_cnter; + RK_S32 set_to_lt = 0; + RK_S32 cleanup_cpb = 0; + RK_S32 prev_frm_is_pass1 = frm->save_pass1; + RK_S32 i; + + /* step 1. check igop from cfg_set and force idr for usr_cfg */ + if (p->changed & ENC_REFS_IGOP_CHANGED) + cleanup_cpb = 1; + + if (p->igop && (cpb->seq_idx >= p->igop)) { + if (p->refresh_length) { + p->cpb.seq_cnt = cpb->seq_idx / p->igop + 1; + } else + cleanup_cpb = 1; + } + + if (usr_cfg->force_flag & ENC_FORCE_IDR) { + usr_cfg->force_flag &= (~ENC_FORCE_IDR); + cleanup_cpb = 1; + p->cpb.seq_cnt = 0; + } + + if (cleanup_cpb) { + /* update seq_idx for igop loop and force idr */ + cleanup_cpb_refs(cpb); + } else if (p->changed & ENC_REFS_REF_CFG_CHANGED) { + cpb->st_cfg_pos = 0; + cpb->st_cfg_repeat_pos = 0; + } + + p->changed = 0; + + cpb->frm_idx++; + cpb->st_cfg_pos = get_cpb_st_cfg_pos(cpb, cfg); + st_cfg = &cfg->st_cfg[cpb->st_cfg_pos]; + /* step 2. updated by st_cfg */ + set_st_cfg_to_frm(frm, cpb->seq_idx++, st_cfg); + set_frm_refresh_flag(frm, p); + + lt_cfg = p->cpb.lt_cnter; + + /* step 3. updated by lt_cfg */ + for (i = 0; i < cfg->lt_cfg_cnt; i++, lt_cfg++) { + if (lt_cfg->delay_cnt) { + lt_cfg->delay_cnt--; + continue; + } + + if (!set_to_lt) { + if (!lt_cfg->cnt) { + set_lt_cfg_to_frm(frm, lt_cfg); + set_to_lt = 1; + } + } + + lt_cfg->cnt++; + if (lt_cfg->cnt >= lt_cfg->len) { + if (lt_cfg->len) { + /* when there is loop len loop lt_cfg */ + lt_cfg->cnt = 0; + lt_cfg->idx++; + } else { + /* else just set lt_cfg once */ + lt_cfg->cnt = 1; + lt_cfg->idx = 1; + } + } + } + + /* step 4. process force flags and force ref_mode */ + if (usr_cfg->force_flag & ENC_FORCE_LT_REF_IDX) { + frm->is_non_ref = 0; + frm->is_lt_ref = 1; + frm->lt_idx = usr_cfg->force_lt_idx; + if (frm->is_idr && frm->lt_idx) { + frm->lt_idx = 0; + mpp_err_f("can not set IDR to ltr with non-zero index\n"); + } + /* lt_ref will be forced to tid 0 */ + frm->temporal_id = 0; + + /* reset st_cfg to next loop */ + cpb->st_cfg_repeat_pos = 0; + cpb->st_cfg_pos = 0; + usr_cfg->force_flag &= ~ENC_FORCE_LT_REF_IDX; + } + + if (usr_cfg->force_flag & ENC_FORCE_TEMPORAL_ID) { + if (usr_cfg->force_temporal_id >= cfg->max_tlayers || + frm->is_idr || frm->is_lt_ref) + mpp_err_f("Invalid temporal_id %d, frm is %s\n", usr_cfg->force_temporal_id, + (frm->is_idr != 0) ? "IDR" : ((frm->is_lt_ref != 0) ? "LTR" : "st")); + else + frm->temporal_id = usr_cfg->force_temporal_id; + + usr_cfg->force_flag &= ~ENC_FORCE_TEMPORAL_ID; + } + + if (usr_cfg->force_flag & ENC_FORCE_REF_MODE) { + frm->ref_mode = usr_cfg->force_ref_mode; + frm->ref_arg = usr_cfg->force_ref_arg; + + usr_cfg->force_flag &= ~ENC_FORCE_REF_MODE; + } + + if (usr_cfg->force_flag & ENC_FORCE_PSKIP_NON_REF) { + frm->is_non_ref = 1; + + usr_cfg->force_flag &= ~ENC_FORCE_PSKIP_NON_REF; + } + + if (usr_cfg->force_flag & ENC_FORCE_PSKIP_IS_REF) { + frm->force_pskip_is_ref = 1; + + usr_cfg->force_flag &= ~ENC_FORCE_PSKIP_IS_REF; + } + + frm->non_recn = (frm->is_non_ref || (p->igop == 1)) && !p->force_recon; + + /* update st_cfg for st_cfg loop */ + cpb->st_cfg_repeat_pos++; + if (cpb->st_cfg_repeat_pos > st_cfg->repeat) { + cpb->st_cfg_repeat_pos = 0; + cpb->st_cfg_pos++; + } + + /* step 4. try find ref by the ref_mode */ + EncFrmStatus *ref_found = get_ref_from_cpb(&p->cpb, frm); + if (ref_found) { + RK_S32 cpb_idx = check_ref_cpb_pos(&p->cpb, ref_found); + + mpp_assert(cpb_idx >= 0); + cpb->list0[0].val = ref->val; + ref->val = ref_found->val; + } else + ref->val = 0; + + /* step 5. check use previous pass one frame as input */ + if (prev_frm_is_pass1) + frm->use_pass1 = 1; + + if (enc_refs_debug & MPP_ENC_REFS_DBG_FRM) { + mpp_log_f("frm status:\n"); + dump_frm(frm); + mpp_log_f("ref status:\n"); + dump_frm(ref); + } + + /* step 5. generate cpb init */ + memset(status->init, 0, sizeof(status->init)); + save_cpb_status(&p->cpb, status->init); + // TODO: cpb_init must be the same to cpb_final + + /* step 6. store frame according to status */ + store_ref_to_cpb(&p->cpb, frm); + + /* step 7. generate cpb final */ + memset(status->final, 0, sizeof(status->final)); + save_cpb_status(&p->cpb, status->final); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +RK_S32 mpp_enc_refs_next_frm_is_intra(MppEncRefs refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + EncVirtualCpb *cpb = &p->cpb; + MppEncRefFrmUsrCfg *usr_cfg = &p->usr_cfg; + RK_S32 is_intra = 0; + + if (p->changed & ENC_REFS_IGOP_CHANGED) + is_intra = 1; + + if (p->igop && cpb->seq_idx >= p->igop) + is_intra = 1; + + if (usr_cfg->force_flag & ENC_FORCE_IDR) + is_intra = 1; + + if (!cpb->frm_idx) + is_intra = 0; + + enc_refs_dbg_func("leave %p\n", refs); + + return is_intra; +} + +MPP_RET mpp_enc_refs_get_cpb_pass1(MppEncRefs refs, EncCpbStatus *status) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + EncVirtualCpb *cpb = &p->cpb; + EncFrmStatus *frm = &status->curr; + EncFrmStatus *ref = &status->refr; + + frm->valid = 1; + frm->save_pass1 = 1; + frm->is_non_ref = 1; + frm->is_lt_ref = 0; + frm->temporal_id = 0; + frm->ref_mode = REF_TO_PREV_REF_FRM; + frm->ref_arg = 0; + frm->non_recn = 0; + frm->seq_idx = cpb->seq_idx; + + /* step 4. try find ref by the ref_mode */ + EncFrmStatus *ref_found = get_ref_from_cpb(cpb, frm); + if (ref_found) { + RK_S32 cpb_idx = check_ref_cpb_pos(cpb, ref_found); + + mpp_assert(cpb_idx >= 0); + cpb->list0[0].val = ref->val; + ref->val = ref_found->val; + } else + ref->val = 0; + + if (enc_refs_debug & MPP_ENC_REFS_DBG_FRM) { + mpp_log_f("frm status:\n"); + dump_frm(frm); + mpp_log_f("ref status:\n"); + dump_frm(ref); + } + + /* step 5. generate cpb init */ + memset(status->init, 0, sizeof(status->init)); + save_cpb_status(cpb, status->init); + // TODO: cpb_init must be the same to cpb_final + + /* step 6. store frame according to status */ + store_ref_to_cpb(cpb, frm); + + /* step 7. generate cpb final */ + memset(status->final, 0, sizeof(status->final)); + save_cpb_status(cpb, status->final); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} +MPP_RET mpp_enc_refs_stash(MppEncRefs refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + memcpy(&p->cpb_stash, &p->cpb, sizeof(p->cpb_stash)); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +MPP_RET mpp_enc_refs_rollback(MppEncRefs refs) +{ + if (NULL == refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + MppEncRefsImpl *p = (MppEncRefsImpl *)refs; + memcpy(&p->cpb, &p->cpb_stash, sizeof(p->cpb)); + + enc_refs_dbg_func("leave %p\n", refs); + return MPP_OK; +} + +MPP_RET mpp_enc_refs_force_recon(MppEncRefs refs, RK_S32 force_recon) +{ + MppEncRefsImpl *p = NULL; + + if (!refs) { + mpp_err_f("invalid NULL input refs\n"); + return MPP_ERR_VALUE; + } + + enc_refs_dbg_func("enter %p\n", refs); + + p = (MppEncRefsImpl *)refs; + p->force_recon = force_recon; + + enc_refs_dbg_func("leave %p\n", refs); + + return MPP_OK; +} diff --git a/mpp/base/mpp_frame.c b/mpp/base/mpp_frame.c new file mode 100644 index 000000000..ecd73a3c3 --- /dev/null +++ b/mpp/base/mpp_frame.c @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_frame" + +#include + +#include "mpp_debug.h" +#include "mpp_mem_pool.h" +#include "mpp_singleton.h" + +#include "mpp_meta_impl.h" +#include "mpp_frame_impl.h" + +static const char *module_name = MODULE_TAG; +static MppMemPool pool_frame = NULL; + +static void setup_mpp_frame_name(MppFrameImpl *frame) +{ + frame->name = module_name; +} + +static void setup_mpp_frame_defaults(MppFrameImpl *frame) +{ + frame->color_range = MPP_FRAME_RANGE_UNSPECIFIED; + frame->color_primaries = MPP_FRAME_PRI_UNSPECIFIED; + frame->color_trc = MPP_FRAME_TRC_UNSPECIFIED; + frame->colorspace = MPP_FRAME_SPC_UNSPECIFIED; +} + +#define check_is_mpp_frame(frame) _check_is_mpp_frame(__FUNCTION__, frame) + +static void mpp_frame_srv_init() +{ + if (pool_frame) + return; + + pool_frame = mpp_mem_pool_init_f("MppFrame", sizeof(MppFrameImpl)); +} + +static void mpp_frame_srv_deinit() +{ + if (pool_frame) { + mpp_mem_pool_deinit_f(pool_frame); + pool_frame = NULL; + } +} + +MPP_SINGLETON(MPP_SGLN_FRAME, mpp_frame, mpp_frame_srv_init, mpp_frame_srv_deinit) + +MPP_RET _check_is_mpp_frame(const char *func, void *frame) +{ + if (!__check_is_mpp_frame(frame)) + return MPP_OK; + + mpp_err("pointer %p failed on %s check mpp_frame\n", frame, func); + mpp_abort(); + return MPP_NOK; +} + +MPP_RET __check_is_mpp_frame(void *frame) +{ + if (frame && ((MppFrameImpl*)frame)->name == module_name) + return MPP_OK; + + return MPP_NOK; +} + +MPP_RET mpp_frame_init(MppFrame *frame) +{ + MppFrameImpl *p; + + if (!frame) { + mpp_err_f("invalid NULL pointer input\n"); + return MPP_ERR_NULL_PTR; + } + + if (!pool_frame) + mpp_frame_srv_init(); + + p = (MppFrameImpl*)mpp_mem_pool_get_f(pool_frame); + if (!p) { + mpp_err_f("malloc failed\n"); + return MPP_ERR_NULL_PTR; + } + + setup_mpp_frame_name(p); + setup_mpp_frame_defaults(p); + *frame = p; + + return MPP_OK; +} + +MPP_RET mpp_frame_deinit(MppFrame *frame) +{ + MppFrameImpl *p; + + if (!frame || check_is_mpp_frame(*frame)) { + mpp_err_f("invalid NULL pointer input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (MppFrameImpl *)*frame; + if (p->buffer) + mpp_buffer_put(p->buffer); + + if (p->meta) + mpp_meta_put(p->meta); + + if (p->stopwatch) + mpp_stopwatch_put(p->stopwatch); + + mpp_mem_pool_put_f(pool_frame, *frame); + *frame = NULL; + return MPP_OK; +} + +MppBuffer mpp_frame_get_buffer(MppFrame frame) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return NULL; + + return (MppFrame)p->buffer; +} + +void mpp_frame_set_buffer(MppFrame frame, MppBuffer buffer) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return; + + if (p->buffer != buffer) { + if (buffer) + mpp_buffer_inc_ref(buffer); + + if (p->buffer) + mpp_buffer_put(p->buffer); + + p->buffer = buffer; + } +} + +RK_S32 mpp_frame_has_meta(const MppFrame frame) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return 0; + + return (NULL != p->meta); +} + +MppMeta mpp_frame_get_meta(MppFrame frame) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return NULL; + + if (!p->meta) + mpp_meta_get(&p->meta); + + return p->meta; +} + +void mpp_frame_set_meta(MppFrame frame, MppMeta meta) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return; + + if (p->meta) { + mpp_meta_put(p->meta); + p->meta = NULL; + } + + p->meta = meta; +} + +MppFrameStatus *mpp_frame_get_status(MppFrame frame) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + return &p->status; +} + +void mpp_frame_set_stopwatch_enable(MppFrame frame, RK_S32 enable) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return; + + if (enable && !p->stopwatch) { + char name[32]; + + snprintf(name, sizeof(name) - 1, "frm %8llx", p->pts); + p->stopwatch = mpp_stopwatch_get(name); + if (p->stopwatch) + mpp_stopwatch_set_show_on_exit(p->stopwatch, 1); + } else if (!enable && p->stopwatch) { + mpp_stopwatch_put(p->stopwatch); + p->stopwatch = NULL; + } +} + +MppStopwatch mpp_frame_get_stopwatch(const MppFrame frame) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return NULL; + + return p->stopwatch; +} + +MppFrame mpp_frame_dup(MppFrame src) +{ + MppFrameImpl *p = (MppFrameImpl *)src; + MppFrameImpl *ret; + MppFrame frame = NULL; + + if (check_is_mpp_frame(src)) { + mpp_err_f("invalid input src %p\n", src); + return NULL; + } + + mpp_frame_init(&frame); + if (!frame) + return NULL; + + ret = (MppFrameImpl *)frame; + memcpy(ret, p, sizeof(MppFrameImpl)); + + if (p->meta) + ret->meta = mpp_meta_dup(p->meta); + + return frame; +} + +MPP_RET mpp_frame_copy(MppFrame dst, MppFrame src) +{ + MppFrameImpl *p = (MppFrameImpl *)dst; + + if (!dst || check_is_mpp_frame(src)) { + mpp_err_f("invalid input dst %p src %p\n", dst, src); + return MPP_ERR_UNKNOW; + } + + if (p->meta) + mpp_meta_put(p->meta); + + memcpy(dst, src, sizeof(MppFrameImpl)); + p = (MppFrameImpl *)src; + if (p->meta) + mpp_meta_inc_ref(p->meta); + + return MPP_OK; +} + +MPP_RET mpp_frame_info_cmp(MppFrame frame0, MppFrame frame1) +{ + MppFrameImpl *f0 = (MppFrameImpl *)frame0; + MppFrameImpl *f1 = (MppFrameImpl *)frame1; + + if (check_is_mpp_frame(f0) || check_is_mpp_frame(f1)) { + mpp_err_f("invalid NULL pointer input\n"); + return MPP_ERR_NULL_PTR; + } + + if ((f0->width == f1->width) && + (f0->height == f1->height) && + (f0->hor_stride == f1->hor_stride) && + (f0->ver_stride == f1->ver_stride) && + ((f0->fmt & ~MPP_FRAME_HDR_MASK) == (f1->fmt & ~MPP_FRAME_HDR_MASK)) && + (f0->buf_size == f1->buf_size)) { + return MPP_OK; + } + return MPP_NOK; +} + +RK_U32 mpp_frame_get_fbc_offset(MppFrame frame) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return 0; + + if (MPP_FRAME_FMT_IS_FBC(p->fmt)) { + RK_U32 fbc_version = p->fmt & MPP_FRAME_FBC_MASK; + RK_U32 fbc_offset = 0; + + if (fbc_version == MPP_FRAME_FBC_AFBC_V1) { + fbc_offset = MPP_ALIGN(MPP_ALIGN(p->width, 16) * + MPP_ALIGN(p->height, 16) / 16, SZ_4K); + } else if (fbc_version == MPP_FRAME_FBC_AFBC_V2 || + fbc_version == MPP_FRAME_FBC_RKFBC) { + fbc_offset = 0; + } + p->fbc_offset = fbc_offset; + } + + return p->fbc_offset; +} + +RK_U32 mpp_frame_get_fbc_stride(MppFrame frame) +{ + MppFrameImpl *p = (MppFrameImpl *)frame; + + if (check_is_mpp_frame(p)) + return 0; + + return MPP_ALIGN(p->width, 16); +} + +/* + * object access function macro + */ +#define MPP_FRAME_ACCESSORS(type, field) \ + type mpp_frame_get_##field(const MppFrame s) \ + { \ + check_is_mpp_frame((MppFrameImpl*)s); \ + return ((MppFrameImpl*)s)->field; \ + } \ + void mpp_frame_set_##field(MppFrame s, type v) \ + { \ + check_is_mpp_frame((MppFrameImpl*)s); \ + ((MppFrameImpl*)s)->field = v; \ + } + +MPP_FRAME_ACCESSORS(RK_U32, width) +MPP_FRAME_ACCESSORS(RK_U32, height) +MPP_FRAME_ACCESSORS(RK_U32, hor_stride_pixel) +MPP_FRAME_ACCESSORS(RK_U32, hor_stride) +MPP_FRAME_ACCESSORS(RK_U32, ver_stride) +MPP_FRAME_ACCESSORS(RK_U32, fbc_hdr_stride) +MPP_FRAME_ACCESSORS(RK_U32, offset_x) +MPP_FRAME_ACCESSORS(RK_U32, offset_y) +MPP_FRAME_ACCESSORS(RK_U32, mode) +MPP_FRAME_ACCESSORS(RK_U32, discard) +MPP_FRAME_ACCESSORS(RK_U32, viewid) +MPP_FRAME_ACCESSORS(RK_U32, poc) +MPP_FRAME_ACCESSORS(RK_S64, pts) +MPP_FRAME_ACCESSORS(RK_S64, dts) +MPP_FRAME_ACCESSORS(RK_U32, eos) +MPP_FRAME_ACCESSORS(RK_U32, info_change) +MPP_FRAME_ACCESSORS(MppFrameColorRange, color_range) +MPP_FRAME_ACCESSORS(MppFrameColorPrimaries, color_primaries) +MPP_FRAME_ACCESSORS(MppFrameColorTransferCharacteristic, color_trc) +MPP_FRAME_ACCESSORS(MppFrameColorSpace, colorspace) +MPP_FRAME_ACCESSORS(MppFrameChromaLocation, chroma_location) +MPP_FRAME_ACCESSORS(MppFrameFormat, fmt) +MPP_FRAME_ACCESSORS(MppFrameRational, sar) +MPP_FRAME_ACCESSORS(MppFrameMasteringDisplayMetadata, mastering_display) +MPP_FRAME_ACCESSORS(MppFrameContentLightMetadata, content_light) +MPP_FRAME_ACCESSORS(MppFrameHdrDynamicMeta*, hdr_dynamic_meta) +MPP_FRAME_ACCESSORS(size_t, buf_size) +MPP_FRAME_ACCESSORS(RK_U32, errinfo) +MPP_FRAME_ACCESSORS(MppTask, task) +MPP_FRAME_ACCESSORS(RK_U32, thumbnail_en) +MPP_FRAME_ACCESSORS(size_t, fbc_size) diff --git a/mpp/base/mpp_meta.c b/mpp/base/mpp_meta.c new file mode 100644 index 000000000..7cfd5e616 --- /dev/null +++ b/mpp/base/mpp_meta.c @@ -0,0 +1,716 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_meta" + +#include +#include + +#include "mpp_env.h" +#include "mpp_lock.h" +#include "mpp_debug.h" +#include "mpp_mem_pool.h" +#include "mpp_singleton.h" + +#include "mpp_trie.h" +#include "mpp_meta_impl.h" + +#define META_DBG_FLOW (0x00000001) +#define META_DBG_KEYS (0x00000002) + +#define meta_dbg(flag, fmt, ...) mpp_dbg(mpp_meta_debug, flag, fmt, ## __VA_ARGS__) +#define meta_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_meta_debug, flag, fmt, ## __VA_ARGS__) + +#define meta_dbg_flow(fmt, ...) meta_dbg(META_DBG_FLOW, fmt, ## __VA_ARGS__) + +#define META_VAL_INVALID (0x00000000) +#define META_VAL_VALID (0x00000001) +#define META_VAL_READY (0x00000002) + +#define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val)) +#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) + +#define get_srv_meta(caller) \ + ({ \ + MppMetaSrv *__tmp; \ + if (srv_meta || srv_finalized) { \ + __tmp = srv_meta; \ + } else { \ + mpp_meta_srv_init(); \ + __tmp = srv_meta; \ + if (!__tmp) { \ + mpp_err("mpp meta srv not init at %s : %s\n", __FUNCTION__, caller); \ + } \ + } \ + __tmp; \ + }) + +#define get_srv_meta_f() \ + ({ \ + MppMetaSrv *__tmp; \ + if (srv_meta || srv_finalized) { \ + __tmp = srv_meta; \ + } else { \ + mpp_meta_srv_init(); \ + __tmp = srv_meta; \ + if (!__tmp) { \ + mpp_err("mpp meta srv not init at %s\n", __FUNCTION__); \ + } \ + } \ + __tmp; \ + }) + +typedef enum MppMetaDataType_e { + /* mpp meta data of normal data type */ + TYPE_VAL_32 = '3', + TYPE_VAL_64 = '6', + TYPE_KPTR = 'k', + TYPE_UPTR = 'u', + TYPE_SPTR = 's', +} MppMetaType; + +static inline RK_U64 META_KEY_TO_U64(RK_U32 key, RK_U32 type) +{ + return (RK_U64)((RK_U32)htobe32(key)) | ((RK_U64)type << 32); +} + +#define EXPAND_AS_TRIE(key, type) \ + do { \ + RK_U64 val = META_KEY_TO_U64(key, type); \ + mpp_trie_add_info(srv->trie, (const char *)&val, NULL, 0); \ + meta_key_count++; \ + } while (0); + +#define EXPAND_AS_LOG(key, type) \ + do { \ + RK_U32 key_val = htobe32(key); \ + char *str = (char *)&key_val; \ + mpp_logi("%2d - %-24s (%c%c%c%c) : %-12s\n", \ + i++, #key, str[0], str[1], str[2], str[3], #type); \ + } while (0); + +#define META_ENTRY_TABLE(ENTRY) \ + /* categorized by type */ \ + /* data flow type */ \ + ENTRY(KEY_INPUT_FRAME, TYPE_SPTR) \ + ENTRY(KEY_OUTPUT_FRAME, TYPE_SPTR) \ + ENTRY(KEY_INPUT_PACKET, TYPE_SPTR) \ + ENTRY(KEY_OUTPUT_PACKET, TYPE_SPTR) \ + /* buffer for motion detection */ \ + ENTRY(KEY_MOTION_INFO, TYPE_SPTR) \ + /* buffer storing the HDR information for current frame*/ \ + ENTRY(KEY_HDR_INFO, TYPE_SPTR) \ + /* the offset of HDR meta data in frame buffer */ \ + ENTRY(KEY_HDR_META_OFFSET, TYPE_VAL_32) \ + ENTRY(KEY_HDR_META_SIZE, TYPE_VAL_32) \ + \ + ENTRY(KEY_OUTPUT_INTRA, TYPE_VAL_32) \ + ENTRY(KEY_INPUT_BLOCK, TYPE_VAL_32) \ + ENTRY(KEY_OUTPUT_BLOCK, TYPE_VAL_32) \ + ENTRY(KEY_INPUT_IDR_REQ, TYPE_VAL_32) \ + \ + /* extra information for tsvc */ \ + ENTRY(KEY_TEMPORAL_ID, TYPE_VAL_32) \ + ENTRY(KEY_LONG_REF_IDX, TYPE_VAL_32) \ + ENTRY(KEY_ENC_AVERAGE_QP, TYPE_VAL_32) \ + ENTRY(KEY_ENC_START_QP, TYPE_VAL_32) \ + ENTRY(KEY_ENC_BPS_RT, TYPE_VAL_32) \ + \ + ENTRY(KEY_ROI_DATA, TYPE_UPTR) \ + ENTRY(KEY_ROI_DATA2, TYPE_UPTR) \ + ENTRY(KEY_JPEG_ROI_DATA, TYPE_UPTR) \ + ENTRY(KEY_OSD_DATA, TYPE_UPTR) \ + ENTRY(KEY_OSD_DATA2, TYPE_UPTR) \ + ENTRY(KEY_OSD_DATA3, TYPE_UPTR) \ + ENTRY(KEY_USER_DATA, TYPE_UPTR) \ + ENTRY(KEY_USER_DATAS, TYPE_UPTR) \ + ENTRY(KEY_QPMAP0, TYPE_SPTR) \ + /* buffer for super encode v3 */ \ + ENTRY(KEY_NPU_SOBJ_FLAG, TYPE_SPTR) \ + ENTRY(KEY_NPU_UOBJ_FLAG, TYPE_UPTR) \ + ENTRY(KEY_BUFFER_UPSCALE, TYPE_SPTR) \ + ENTRY(KEY_BUFFER_DOWNSCALE, TYPE_SPTR) \ + \ + ENTRY(KEY_LVL64_INTER_NUM, TYPE_VAL_32) \ + ENTRY(KEY_LVL32_INTER_NUM, TYPE_VAL_32) \ + ENTRY(KEY_LVL16_INTER_NUM, TYPE_VAL_32) \ + ENTRY(KEY_LVL8_INTER_NUM, TYPE_VAL_32) \ + ENTRY(KEY_LVL32_INTRA_NUM, TYPE_VAL_32) \ + ENTRY(KEY_LVL16_INTRA_NUM, TYPE_VAL_32) \ + ENTRY(KEY_LVL8_INTRA_NUM, TYPE_VAL_32) \ + ENTRY(KEY_LVL4_INTRA_NUM, TYPE_VAL_32) \ + ENTRY(KEY_INPUT_PSKIP, TYPE_VAL_32) \ + ENTRY(KEY_OUTPUT_PSKIP, TYPE_VAL_32) \ + ENTRY(KEY_INPUT_PSKIP_NON_REF, TYPE_VAL_32) \ + ENTRY(KEY_ENC_SSE, TYPE_VAL_64) \ + \ + ENTRY(KEY_ENC_MARK_LTR, TYPE_VAL_32) \ + ENTRY(KEY_ENC_USE_LTR, TYPE_VAL_32) \ + ENTRY(KEY_ENC_FRAME_QP, TYPE_VAL_32) \ + ENTRY(KEY_ENC_BASE_LAYER_PID, TYPE_VAL_32) \ + \ + ENTRY(KEY_DEC_TBN_EN, TYPE_VAL_32) \ + ENTRY(KEY_DEC_TBN_Y_OFFSET, TYPE_VAL_32) \ + ENTRY(KEY_DEC_TBN_UV_OFFSET, TYPE_VAL_32) + +typedef struct MppMetaSrv_t { + spinlock_t lock; + struct list_head list_meta; + MppTrie trie; + + RK_U32 meta_id; + RK_S32 meta_count; +} MppMetaSrv; + +static MppMetaSrv *srv_meta = NULL; +static MppMemPool pool_meta = NULL; +static RK_U32 srv_finalized = 0; +static RK_U32 meta_key_count = 0; +static RK_U32 mpp_meta_debug = 0; +static RK_S32 user_data_index = -1; +static RK_S32 user_datas_index = -1; + +RK_S32 meta_hdr_offset_index = -1; +RK_S32 meta_hdr_size_index = -1; + +static void put_meta(MppMetaSrv *srv, MppMetaImpl *meta); +static inline RK_S32 get_index_of_key(MppMetaKey key, MppMetaType type, const char *caller); +#define get_index_of_key_f(key, type) get_index_of_key(key, type, __FUNCTION__); + +static void mpp_meta_srv_init() +{ + MppMetaSrv *srv = srv_meta; + + mpp_env_get_u32("mpp_meta_debug", &mpp_meta_debug, 0); + + if (srv) + return; + + srv = mpp_calloc(MppMetaSrv, 1); + if (!srv) { + mpp_err_f("failed to malloc meta service\n"); + return; + } + + srv_meta = srv; + + mpp_spinlock_init(&srv->lock); + INIT_LIST_HEAD(&srv->list_meta); + + mpp_trie_init(&srv->trie, "MppMetaDef"); + if (srv->trie) { + meta_key_count = 0; + META_ENTRY_TABLE(EXPAND_AS_TRIE) + mpp_trie_add_info(srv->trie, NULL, NULL, 0); + user_data_index = get_index_of_key_f(KEY_USER_DATA, TYPE_UPTR); + user_datas_index = get_index_of_key_f(KEY_USER_DATAS, TYPE_UPTR); + meta_hdr_offset_index = get_index_of_key_f(KEY_HDR_META_OFFSET, TYPE_VAL_32); + meta_hdr_size_index = get_index_of_key_f(KEY_HDR_META_SIZE, TYPE_VAL_32); + } + + pool_meta = mpp_mem_pool_init_f("MppMeta", sizeof(MppMetaImpl) + + sizeof(MppMetaVal) * meta_key_count); + + meta_dbg_flow("meta key count %d\n", meta_key_count); + if (mpp_meta_debug & META_DBG_KEYS) { + RK_S32 i = 0; + + META_ENTRY_TABLE(EXPAND_AS_LOG) + } +} + +static void mpp_meta_srv_deinit() +{ + MppMetaSrv *srv = srv_meta; + + if (!srv) + return; + + if (!list_empty(&srv->list_meta)) { + MppMetaImpl *pos, *n; + + mpp_log_f("cleaning leaked metadata\n"); + + list_for_each_entry_safe(pos, n, &srv->list_meta, MppMetaImpl, list_meta) { + put_meta(srv, pos); + } + } + + mpp_assert(srv->meta_count == 0); + + if (srv->trie) { + mpp_trie_deinit(srv->trie); + srv->trie = NULL; + } + + MPP_FREE(srv_meta); + + if (pool_meta) { + mpp_mem_pool_deinit_f(pool_meta); + pool_meta = NULL; + } + + srv_finalized = 1; + + meta_dbg_flow("meta srv deinited\n"); +} + +MPP_SINGLETON(MPP_SGLN_META, mpp_meta, mpp_meta_srv_init, mpp_meta_srv_deinit) + +static inline RK_S32 get_index_of_key(MppMetaKey key, MppMetaType type, const char *caller) +{ + MppMetaSrv *srv = get_srv_meta(caller); + MppTrieInfo *info = NULL; + + if (srv) { + RK_U64 val = META_KEY_TO_U64(key, type); + + info = mpp_trie_get_info(srv->trie, (const char *)&val); + } + + return info ? info->index : -1; +} + +static MppMetaImpl *get_meta(MppMetaSrv *srv, const char *tag, const char *caller) +{ + MppMetaImpl *impl = (MppMetaImpl *)mpp_mem_pool_get(pool_meta, caller); + + if (impl) { + const char *tag_src = (tag) ? (tag) : (MODULE_TAG); + RK_U32 i; + + strncpy(impl->tag, tag_src, sizeof(impl->tag) - 1); + impl->caller = caller; + impl->meta_id = MPP_FETCH_ADD(&srv->meta_id, 1); + INIT_LIST_HEAD(&impl->list_meta); + impl->ref_count = 1; + impl->node_count = 0; + + for (i = 0; i < meta_key_count; i++) + impl->vals[i].state = 0; + + mpp_spinlock_lock(&srv->lock); + list_add_tail(&impl->list_meta, &srv->list_meta); + mpp_spinlock_unlock(&srv->lock); + MPP_FETCH_ADD(&srv->meta_count, 1); + } else { + mpp_err_f("failed to malloc meta data\n"); + } + + return impl; +} + +static void clean_user_data(MppMetaImpl *impl) +{ + MPP_FREE(impl->user_data.pdata); + impl->user_data.len = 0; +} + +static void clean_user_datas(MppMetaImpl *impl) +{ + MPP_FREE(impl->user_data_set.datas); + impl->user_data_set.count = 0; + impl->datas_buf_size = 0; +} + +static void put_meta(MppMetaSrv *srv, MppMetaImpl *meta) +{ + RK_S32 ref_count; + + if (!srv) + return; + + ref_count = MPP_SUB_FETCH(&meta->ref_count, 1); + if (ref_count > 0) + return; + + if (ref_count < 0) { + mpp_err_f("invalid negative ref_count %d\n", ref_count); + return; + } + + mpp_spinlock_lock(&srv->lock); + clean_user_data(meta); + clean_user_datas(meta); + list_del_init(&meta->list_meta); + mpp_spinlock_unlock(&srv->lock); + MPP_FETCH_SUB(&srv->meta_count, 1); + + if (pool_meta) + mpp_mem_pool_put_f(pool_meta, meta); +} + +MPP_RET mpp_meta_get_with_tag(MppMeta *meta, const char *tag, const char *caller) +{ + MppMetaSrv *srv = get_srv_meta(caller); + MppMetaImpl *impl; + + if (!srv) + return MPP_NOK; + + if (!meta) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + impl = get_meta(srv, tag, caller); + *meta = (MppMeta) impl; + return (impl) ? (MPP_OK) : (MPP_NOK); +} + +MPP_RET mpp_meta_put(MppMeta meta) +{ + MppMetaImpl *impl = (MppMetaImpl *)meta; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + put_meta(get_srv_meta_f(), impl); + return MPP_OK; +} + +MPP_RET mpp_meta_inc_ref(MppMeta meta) +{ + MppMetaImpl *impl = (MppMetaImpl *)meta; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_FETCH_ADD(&impl->ref_count, 1); + return MPP_OK; +} + +RK_S32 mpp_meta_size(MppMeta meta) +{ + MppMetaImpl *impl = (MppMetaImpl *)meta; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return -1; + } + + return MPP_FETCH_ADD(&impl->node_count, 0); +} + +static MPP_RET set_user_data(MppMetaImpl *impl, void *user_data) +{ + MppEncUserData *src = (MppEncUserData *)user_data; + + if (!src) { + clean_user_data(impl); + return MPP_OK; + } + + if (!src->pdata || !src->len) { + mpp_err_f("invalid user data %p pdata %p len %d\n", user_data, src->pdata, src->len); + return MPP_ERR_NULL_PTR; + } + + if (impl->user_data.len < src->len) { + void *buf_ptr = mpp_realloc(impl->user_data.pdata, RK_U8, src->len); + + if (!buf_ptr) { + mpp_err_f("failed to realloc user data buf size %d\n", src->len); + impl->user_data.len = 0; + return MPP_ERR_MALLOC; + } + impl->user_data.pdata = buf_ptr; + } + + memcpy(impl->user_data.pdata, src->pdata, src->len); + impl->user_data.len = src->len; + + return MPP_OK; +} + +static MPP_RET set_user_datas(MppMetaImpl *impl, void *user_data) +{ + MppEncUserDataSet *src_set = (MppEncUserDataSet *)user_data; + MppEncUserDataFull *dst_set = NULL; + void *buf_ptr = NULL; + RK_U32 data_size = 0; + RK_U32 struct_size = 0; + RK_U32 buf_size = 0; + RK_U32 i = 0; + + if (!src_set) { + clean_user_datas(impl); + return MPP_OK; + } + + if (!src_set->datas || !src_set->count) { + mpp_err_f("invalid user data %p datas %p count %d\n", src_set, src_set->datas, src_set->count); + return MPP_ERR_NULL_PTR; + } + + struct_size = sizeof(MppEncUserDataFull) * src_set->count; + for (i = 0; i < src_set->count; i++) { + MppEncUserDataFull *src = &src_set->datas[i]; + + if (src->uuid) + data_size += strlen((const char *)src->uuid) + 1; + data_size += src->len; + } + buf_size = struct_size + data_size; + + if (impl->datas_buf_size < buf_size) { + buf_ptr = mpp_realloc(impl->user_data_set.datas, RK_U8, buf_size); + if (!buf_ptr) { + mpp_err_f("failed to realloc user data buf size %d\n", buf_size); + impl->user_data_set.count = 0; + impl->datas_buf_size = 0; + return MPP_ERR_MALLOC; + } + impl->user_data_set.datas = (MppEncUserDataFull *)buf_ptr; + } + + impl->datas_buf_size = buf_size; + dst_set = impl->user_data_set.datas; + buf_ptr = (void *)dst_set + struct_size; + + for (i = 0; i < src_set->count; i++) { + MppEncUserDataFull *src = &src_set->datas[i]; + MppEncUserDataFull *dst = &dst_set[i]; + + dst->len = src->len; + if (src->uuid) { + size_t uuid_len = strlen((const char *)src->uuid) + 1; + + dst->uuid = (RK_U8 *)buf_ptr; + memcpy(buf_ptr, src->uuid, uuid_len); + buf_ptr += uuid_len; + } else { + dst->uuid = NULL; + } + if (src->pdata) { + dst->pdata = buf_ptr; + memcpy(buf_ptr, src->pdata, src->len); + buf_ptr += src->len; + } else { + dst->pdata = NULL; + } + } + impl->user_data_set.count = src_set->count; + + return MPP_OK; +} + +static MPP_RET get_user_data(MppMetaImpl *impl, void **val) +{ + if (impl->user_data.pdata) { + *val = &impl->user_data; + return MPP_OK; + } + + *val = NULL; + return MPP_NOK; +} + +static MPP_RET get_user_datas(MppMetaImpl *impl, void **val) +{ + if (impl->user_data_set.datas) { + *val = &impl->user_data_set; + return MPP_OK; + } + + *val = NULL; + return MPP_NOK; +} + +MppMeta mpp_meta_dup(MppMeta meta) +{ + MppMetaSrv *srv = get_srv_meta_f(); + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaImpl *ret; + + if (!srv || !meta) + return NULL; + + ret = get_meta(srv, impl->tag, __FUNCTION__); + if (ret) { + memcpy(ret->vals, impl->vals, meta_key_count * sizeof(MppMetaVal)); + if (ret->user_data.len) { + memset(&ret->user_data, 0, sizeof(ret->user_data)); + set_user_data(ret, (void *)(intptr_t)&impl->user_data); + } + if (ret->user_data_set.count) { + memset(&ret->user_data, 0, sizeof(ret->user_data)); + set_user_datas(impl, (void *)(intptr_t)&impl->user_data_set); + } + ret->node_count = impl->node_count; + } + + return ret; +} + +MPP_RET mpp_meta_dump(MppMeta meta) +{ + MppMetaSrv *srv = get_srv_meta_f(); + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppTrieInfo *root; + + if (!impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_logi("dumping meta %d node count %d\n", impl->meta_id, impl->node_count); + + if (!srv || !srv->trie) + return MPP_NOK; + + root = mpp_trie_get_info_first(srv->trie); + if (root) { + MppTrieInfo *node = root; + const char *key = NULL; + char log_str[256]; + RK_S32 pos; + + do { + if (mpp_trie_info_is_self(node)) + continue; + + key = mpp_trie_info_name(node); + + pos = snprintf(log_str, sizeof(log_str) - 1, "key %c%c%c%c - ", + key[0], key[1], key[2], key[3]); + + switch (key[4]) { + case '3' : { + snprintf(log_str + pos, sizeof(log_str) - pos - 1, "s32 - %d", + impl->vals[node->index].val_s32); + } break; + case '6' : { + snprintf(log_str + pos, sizeof(log_str) - pos - 1, "s64 - %lld", + impl->vals[node->index].val_s64); + } break; + case 'k' : + case 'u' : + case 's' : { + snprintf(log_str + pos, sizeof(log_str) - pos - 1, "ptr - %p", + impl->vals[node->index].val_ptr); + } break; + default : { + } break; + } + + mpp_logi("%s\n", log_str); + } while ((node = mpp_trie_get_info_next(srv->trie, node))); + } + + return MPP_OK; +} + +#define MPP_META_ACCESSOR(func_type, arg_type, key_type, key_field) \ + MPP_RET mpp_meta_set_##func_type(MppMeta meta, MppMetaKey key, arg_type val) \ + { \ + MppMetaImpl *impl = (MppMetaImpl *)meta; \ + MppMetaVal *meta_val; \ + RK_S32 index; \ + if (!impl) { \ + mpp_err_f("found NULL input\n"); \ + return MPP_ERR_NULL_PTR; \ + } \ + index = get_index_of_key_f(key, key_type); \ + if (index < 0) \ + return MPP_NOK; \ + meta_val = &impl->vals[index]; \ + if (MPP_BOOL_CAS(&meta_val->state, META_VAL_INVALID, META_VAL_VALID)) \ + MPP_FETCH_ADD(&impl->node_count, 1); \ + if (index == user_data_index) { \ + set_user_data(impl, (void *)(intptr_t)val); \ + } else if (index == user_datas_index) { \ + set_user_datas(impl, (void *)(intptr_t)val); \ + } else { \ + meta_val->key_field = val; \ + } \ + MPP_FETCH_OR(&meta_val->state, META_VAL_READY); \ + return MPP_OK; \ + } \ + MPP_RET mpp_meta_get_##func_type(MppMeta meta, MppMetaKey key, arg_type *val) \ + { \ + MppMetaImpl *impl = (MppMetaImpl *)meta; \ + MppMetaVal *meta_val; \ + RK_S32 index; \ + MPP_RET ret = MPP_NOK; \ + if (!impl) { \ + mpp_err_f("found NULL input\n"); \ + return MPP_ERR_NULL_PTR; \ + } \ + index = get_index_of_key_f(key, key_type); \ + if (index < 0) \ + return MPP_NOK; \ + meta_val = &impl->vals[index]; \ + if (MPP_BOOL_CAS(&meta_val->state, META_VAL_VALID | META_VAL_READY, META_VAL_INVALID)) { \ + if (index == user_data_index) \ + get_user_data(impl, (void**)val); \ + else if (index == user_datas_index) \ + get_user_datas(impl, (void**)val); \ + else \ + *val = meta_val->key_field; \ + MPP_FETCH_SUB(&impl->node_count, 1); \ + ret = MPP_OK; \ + } \ + return ret; \ + } \ + MPP_RET mpp_meta_get_##func_type##_d(MppMeta meta, MppMetaKey key, arg_type *val, arg_type def) \ + { \ + MppMetaImpl *impl = (MppMetaImpl *)meta; \ + MppMetaVal *meta_val; \ + RK_S32 index; \ + MPP_RET ret = MPP_NOK; \ + if (!impl) { \ + mpp_err_f("found NULL input\n"); \ + return MPP_ERR_NULL_PTR; \ + } \ + index = get_index_of_key_f(key, key_type); \ + if (index < 0) \ + return MPP_NOK; \ + meta_val = &impl->vals[index]; \ + if (MPP_BOOL_CAS(&meta_val->state, META_VAL_VALID | META_VAL_READY, META_VAL_INVALID)) { \ + if (index == user_data_index) \ + get_user_data(impl, (void**)val); \ + else if (index == user_datas_index) \ + get_user_datas(impl, (void**)val); \ + else \ + *val = meta_val->key_field; \ + MPP_FETCH_SUB(&impl->node_count, 1); \ + ret = MPP_OK; \ + } else { \ + *val = def; \ + } \ + return ret; \ + } + +MPP_META_ACCESSOR(s32, RK_S32, TYPE_VAL_32, val_s32) +MPP_META_ACCESSOR(s64, RK_S64, TYPE_VAL_64, val_s64) +MPP_META_ACCESSOR(ptr, void *, TYPE_UPTR, val_ptr) +MPP_META_ACCESSOR(frame, MppFrame, TYPE_SPTR, frame) +MPP_META_ACCESSOR(packet, MppPacket, TYPE_SPTR, packet) +MPP_META_ACCESSOR(buffer, MppBuffer, TYPE_SPTR, buffer) + +RK_S32 mpp_meta_s32_read(MppMeta meta, RK_S32 index, RK_S32 *val) +{ + MppMetaImpl *impl = (MppMetaImpl *)meta; + MppMetaVal *meta_val; + MPP_RET ret = MPP_NOK; + + if (!impl || index < 0 || (RK_U32)index >= meta_key_count) { + mpp_err_f("found NULL input meta %p index %d\n", meta, index); + return MPP_ERR_NULL_PTR; + } + + meta_val = &impl->vals[index]; + if (meta_val->state == (META_VAL_VALID | META_VAL_READY)) { + *val = meta_val->val_s32; + ret = MPP_OK; + } + + return ret; +} diff --git a/mpp/base/mpp_packet.c b/mpp/base/mpp_packet.c new file mode 100644 index 000000000..19e26dc18 --- /dev/null +++ b/mpp/base/mpp_packet.c @@ -0,0 +1,695 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_packet" + +#include + +#include "mpp_debug.h" +#include "mpp_mem_pool.h" +#include "mpp_singleton.h" + +#include "mpp_meta_impl.h" +#include "mpp_packet_impl.h" + +static const char *module_name = MODULE_TAG; +static MppMemPool pool_packet = NULL; + +#define setup_mpp_packet_name(packet) ((MppPacketImpl*)packet)->name = module_name; + +static void mpp_packet_srv_init() +{ + if (pool_packet) + return; + + pool_packet = mpp_mem_pool_init_f(module_name, sizeof(MppPacketImpl)); +} + +static void mpp_packet_srv_deinit() +{ + if (pool_packet) { + mpp_mem_pool_deinit_f(pool_packet); + pool_packet = NULL; + } +} + +MPP_SINGLETON(MPP_SGLN_PACKET, mpp_packet, mpp_packet_srv_init, mpp_packet_srv_deinit) + +MPP_RET check_is_mpp_packet_f(void *packet, const char *caller) +{ + if (packet && ((MppPacketImpl*)packet)->name == module_name) + return MPP_OK; + + mpp_err("MppPacket %p failed on check from %s\n", packet, caller); + mpp_abort(); + return MPP_NOK; +} + +MPP_RET mpp_packet_new(MppPacket *packet) +{ + MppPacketImpl *p; + + if (!packet) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + if (!pool_packet) + mpp_packet_srv_init(); + + p = (MppPacketImpl*)mpp_mem_pool_get_f(pool_packet); + *packet = p; + if (!p) { + mpp_err_f("malloc failed\n"); + return MPP_ERR_NULL_PTR; + } + setup_mpp_packet_name(p); + p->segment_buf_cnt = MPP_PKT_SEG_CNT_DEFAULT; + + return MPP_OK; +} + +MPP_RET mpp_packet_init(MppPacket *packet, void *data, size_t size) +{ + MppPacketImpl *p; + MPP_RET ret; + + if (!packet) { + mpp_err_f("invalid NULL input packet\n"); + return MPP_ERR_NULL_PTR; + } + + ret = mpp_packet_new(packet); + if (ret) { + mpp_err_f("new packet failed\n"); + return ret; + } + + p = (MppPacketImpl *)*packet; + p->data = p->pos = data; + p->size = p->length = size; + + return MPP_OK; +} + +MPP_RET mpp_packet_init_with_buffer(MppPacket *packet, MppBuffer buffer) +{ + MppPacketImpl *p; + MPP_RET ret; + + if (!packet || !buffer) { + mpp_err_f("invalid input packet %p buffer %p\n", packet, buffer); + return MPP_ERR_NULL_PTR; + } + + ret = mpp_packet_new(packet); + if (ret) { + mpp_err_f("new packet failed\n"); + return ret; + } + + p = (MppPacketImpl *)*packet; + p->data = p->pos = mpp_buffer_get_ptr(buffer); + p->size = p->length = mpp_buffer_get_size(buffer); + p->buffer = buffer; + mpp_buffer_inc_ref(buffer); + + return MPP_OK; +} + +MPP_RET mpp_packet_copy_init(MppPacket *packet, const MppPacket src) +{ + MppPacketImpl *src_impl; + MppPacket pkt; + MPP_RET ret; + + if (!packet || check_is_mpp_packet(src)) { + mpp_err_f("found invalid input %p %p\n", packet, src); + return MPP_ERR_UNKNOW; + } + + *packet = NULL; + + src_impl = (MppPacketImpl *)src; + ret = mpp_packet_new(&pkt); + if (ret) + return ret; + + /* copy the source data */ + memcpy(pkt, src_impl, sizeof(*src_impl)); + + /* increase reference of meta data */ + if (src_impl->meta) + mpp_meta_inc_ref(src_impl->meta); + + if (src_impl->buffer) { + /* if source packet has buffer just create a new reference to buffer */ + mpp_buffer_inc_ref(src_impl->buffer); + } else { + MppPacketImpl *p; + /* + * NOTE: only copy valid data + */ + size_t length = mpp_packet_get_length(src); + /* + * due to parser may be read 32 bit interface so we must alloc more size + * then real size to avoid read carsh + */ + void *pos = mpp_malloc_size(void, length + 256); + + if (!pos) { + mpp_err_f("malloc failed, size %d\n", length); + mpp_packet_deinit(&pkt); + return MPP_ERR_MALLOC; + } + + p = (MppPacketImpl *)pkt; + p->data = p->pos = pos; + p->size = p->length = length; + p->flag |= MPP_PACKET_FLAG_INTERNAL; + + if (length) { + memcpy(pos, src_impl->pos, length); + /* + * clean more alloc byte to zero + */ + memset((RK_U8*)pos + length, 0, 256); + } + } + + *packet = pkt; + return MPP_OK; +} + +MPP_RET mpp_packet_deinit(MppPacket *packet) +{ + MppPacketImpl *p; + + if (!packet || check_is_mpp_packet(*packet)) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (MppPacketImpl *)(*packet); + + /* release buffer reference */ + if (p->buffer) + mpp_buffer_put(p->buffer); + + if (p->flag & MPP_PACKET_FLAG_INTERNAL) + mpp_free(p->data); + + if (p->meta) + mpp_meta_put(p->meta); + + MPP_FREE(p->segments_ext); + + if (p->release) + p->release(p->release_ctx, p->release_arg); + + mpp_mem_pool_put_f(pool_packet, *packet); + *packet = NULL; + return MPP_OK; +} + +void mpp_packet_set_pos(MppPacket packet, void *pos) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + size_t offset; + size_t diff; + + if (check_is_mpp_packet(p)) + return; + + offset = (RK_U8 *)pos - (RK_U8 *)p->data; + diff = (RK_U8 *)pos - (RK_U8 *)p->pos; + + /* + * If set pos is a simple update on original buffer update the length + * If set pos setup a new buffer reset length to size - offset + * This will avoid assert on change "data" in mpp_packet + */ + if (diff <= p->length) + p->length -= diff; + else + p->length = p->size - offset; + + p->pos = pos; + mpp_assert(p->data <= p->pos); + mpp_assert(p->size >= p->length); +} + +void *mpp_packet_get_pos(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return NULL; + + return p->pos; +} + +MPP_RET mpp_packet_set_eos(MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return MPP_ERR_UNKNOW; + + p->flag |= MPP_PACKET_FLAG_EOS; + return MPP_OK; +} + +MPP_RET mpp_packet_clr_eos(MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return MPP_ERR_UNKNOW; + + p->flag &= ~MPP_PACKET_FLAG_EOS; + return MPP_OK; +} + +RK_U32 mpp_packet_get_eos(MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return 0; + + return ((p->flag & MPP_PACKET_FLAG_EOS) != 0) ? (1) : (0); +} + +MPP_RET mpp_packet_set_extra_data(MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return MPP_ERR_UNKNOW; + + p->flag |= MPP_PACKET_FLAG_EXTRA_DATA; + return MPP_OK; +} + +MPP_RET mpp_packet_reset(MppPacketImpl *packet) +{ + void *data; + size_t size; + + if (check_is_mpp_packet(packet)) + return MPP_ERR_UNKNOW; + + data = packet->data; + size = packet->size; + + memset(packet, 0, sizeof(*packet)); + + packet->data = data; + packet->pos = data; + packet->size = size; + setup_mpp_packet_name(packet); + mpp_packet_reset_segment(packet); + return MPP_OK; +} + +void mpp_packet_set_buffer(MppPacket packet, MppBuffer buffer) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return; + + if (p->buffer != buffer) { + if (buffer) + mpp_buffer_inc_ref(buffer); + + if (p->buffer) + mpp_buffer_put(p->buffer); + + p->buffer = buffer; + } +} + +MppBuffer mpp_packet_get_buffer(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return NULL; + + return p->buffer; +} + +RK_S32 mpp_packet_has_meta(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return 0; + + return (NULL != p->meta); +} + +MppMeta mpp_packet_get_meta(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return NULL; + + if (!p->meta) + mpp_meta_get(&p->meta); + + return p->meta; +} + +MPP_RET mpp_packet_set_status(MppPacket packet, MppPacketStatus status) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return MPP_ERR_UNKNOW; + + p->status.val = status.val; + return MPP_OK; +} + +MPP_RET mpp_packet_get_status(MppPacket packet, MppPacketStatus *status) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) { + status->val = 0; + return MPP_ERR_UNKNOW; + } + + status->val = p->status.val; + return MPP_OK; +} + +RK_U32 mpp_packet_is_partition(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return 0; + + return (p->status.partition) || (p->flag & MPP_PACKET_FLAG_PARTITION); +} + +RK_U32 mpp_packet_is_soi(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return 0; + + return p->status.soi; +} + +RK_U32 mpp_packet_is_eoi(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return 0; + + return (p->status.eoi) || (p->flag & MPP_PACKET_FLAG_EOI); +} + +MPP_RET mpp_packet_read(MppPacket packet, size_t offset, void *data, size_t size) +{ + void *src; + + if (check_is_mpp_packet(packet) || !data) { + mpp_err_f("invalid input: packet %p data %p\n", packet, data); + return MPP_ERR_UNKNOW; + } + + if (0 == size) + return MPP_OK; + + src = mpp_packet_get_data(packet); + mpp_assert(src != NULL); + memcpy(data, (char*)src + offset, size); + return MPP_OK; +} + +MPP_RET mpp_packet_write(MppPacket packet, size_t offset, void *data, size_t size) +{ + void *dst; + + if (check_is_mpp_packet(packet) || !data) { + mpp_err_f("invalid input: packet %p data %p\n", packet, data); + return MPP_ERR_UNKNOW; + } + + if (0 == size) + return MPP_OK; + + dst = mpp_packet_get_data(packet); + mpp_assert(dst != NULL); + memcpy((char*)dst + offset, data, size); + return MPP_OK; +} + +MPP_RET mpp_packet_copy(MppPacket dst, MppPacket src) +{ + MppPacketImpl *dst_impl = (MppPacketImpl *)dst; + MppPacketImpl *src_impl = (MppPacketImpl *)src; + + if (check_is_mpp_packet(dst) || check_is_mpp_packet(src)) { + mpp_err_f("invalid input: dst %p src %p\n", dst, src); + return MPP_ERR_UNKNOW; + } + + memcpy(dst_impl->pos, src_impl->pos, src_impl->length); + dst_impl->length = src_impl->length; + + if (src_impl->segment_nb) + mpp_packet_copy_segment_info(dst, src); + + return MPP_OK; +} + +MPP_RET mpp_packet_append(MppPacket dst, MppPacket src) +{ + MppPacketImpl *dst_impl = (MppPacketImpl *)dst; + MppPacketImpl *src_impl = (MppPacketImpl *)src; + + if (check_is_mpp_packet(dst) || check_is_mpp_packet(src)) { + mpp_err_f("invalid input: dst %p src %p\n", dst, src); + return MPP_ERR_UNKNOW; + } + + memcpy((RK_U8 *)dst_impl->pos + dst_impl->length, src_impl->pos, + src_impl->length); + + if (src_impl->segment_nb) { + MppPktSeg *segs = src_impl->segments; + RK_U32 offset = dst_impl->length; + RK_U32 i; + + for (i = 0; i < src_impl->segment_nb; i++, segs++) { + mpp_packet_add_segment_info(dst, segs->type, offset, segs->len); + offset += segs->len; + } + } + + dst_impl->length += src_impl->length; + return MPP_OK; +} + +void mpp_packet_reset_segment(MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + p->segment_nb = 0; + p->segment_buf_cnt = MPP_PKT_SEG_CNT_DEFAULT; + memset(p->segments_def, 0, sizeof(p->segments_def)); + p->segments = NULL; + MPP_FREE(p->segments_ext); +} + +void mpp_packet_set_segment_nb(MppPacket packet, RK_U32 segment_nb) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + MppPktSeg *segs = p->segments; + RK_S32 i; + + if (segment_nb >= p->segment_nb || !segs) + return; + + if (!segment_nb) { + mpp_packet_reset_segment(packet); + return; + } + + /* truncate segment member and drop later segment info */ + if (segment_nb <= MPP_PKT_SEG_CNT_DEFAULT) { + if (p->segments_ext) { + memcpy(p->segments_def, segs, sizeof(*segs) * segment_nb); + segs = p->segments_def; + p->segments = segs; + MPP_FREE(p->segments_ext); + } + + p->segment_buf_cnt = MPP_PKT_SEG_CNT_DEFAULT; + } + + /* relink segment info */ + for (i = 0; i < (RK_S32)segment_nb - 1; i++) + segs[i].next = &segs[i + 1]; + + segs[segment_nb - 1].next = NULL; + + p->segment_nb = segment_nb; +} + +MPP_RET mpp_packet_add_segment_info(MppPacket packet, RK_S32 type, RK_S32 offset, RK_S32 len) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + RK_U32 old_buf_cnt = p->segment_buf_cnt; + RK_U32 segment_nb = p->segment_nb; + MppPktSeg *seg_buf = p->segments; + + if (segment_nb >= old_buf_cnt) { + RK_U32 i; + + /* realloc segment info buffer. default 8 segments */ + old_buf_cnt *= 2; + + if (!p->segments_ext) { + seg_buf = mpp_calloc(MppPktSeg, old_buf_cnt); + if (seg_buf) + memcpy(seg_buf, p->segments_def, sizeof(p->segments_def)); + } else { + seg_buf = mpp_realloc(p->segments_ext, MppPktSeg, old_buf_cnt); + } + + if (!seg_buf) + return MPP_NOK; + + for (i = 0; i < segment_nb - 1; i++) + seg_buf[i].next = &seg_buf[i + 1]; + + p->segments_ext = seg_buf; + p->segments = seg_buf; + p->segment_buf_cnt = old_buf_cnt; + } else { + if (!seg_buf) { + seg_buf = p->segments_def; + p->segments = seg_buf; + } + } + + mpp_assert(seg_buf); + seg_buf += segment_nb; + seg_buf->index = segment_nb; + seg_buf->type = type; + seg_buf->offset = offset; + seg_buf->len = len; + seg_buf->next = NULL; + + if (segment_nb) + seg_buf[-1].next = seg_buf; + + p->segment_nb++; + mpp_assert(p->segment_nb <= p->segment_buf_cnt); + + return MPP_OK; +} + +void mpp_packet_copy_segment_info(MppPacket dst, MppPacket src) +{ + MppPacketImpl *dst_impl = (MppPacketImpl *)dst; + MppPacketImpl *src_impl = (MppPacketImpl *)src; + + mpp_packet_reset_segment(dst); + + if (src_impl->segment_nb) { + MppPktSeg *src_segs = src_impl->segments; + MppPktSeg *dst_segs = NULL; + RK_U32 segment_nb = src_impl->segment_nb; + RK_U32 i; + + dst_impl->segment_nb = segment_nb; + dst_impl->segment_buf_cnt = src_impl->segment_buf_cnt; + + if (segment_nb <= MPP_PKT_SEG_CNT_DEFAULT) { + dst_segs = dst_impl->segments_def; + + memcpy(dst_segs, src_segs, sizeof(*dst_segs) * segment_nb); + } else { + dst_segs = mpp_calloc(MppPktSeg, dst_impl->segment_buf_cnt); + + mpp_assert(dst_segs); + dst_impl->segments_ext = dst_segs; + memcpy(dst_segs, src_segs, sizeof(*dst_segs) * segment_nb); + } + + for (i = 0; i < segment_nb - 1; i++) + dst_segs[i].next = &dst_segs[i + 1]; + + dst_impl->segments = dst_segs; + } +} + +const MppPktSeg *mpp_packet_get_segment_info(const MppPacket packet) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return NULL; + + if (!p->segment_nb) + return NULL; + + return (const MppPktSeg *)p->segments; +} + +void mpp_packet_set_release(MppPacket packet, ReleaseCb release, void *ctx, void *arg) +{ + MppPacketImpl *p = (MppPacketImpl *)packet; + + if (check_is_mpp_packet(p)) + return; + + p->release = release; + p->release_ctx = ctx; + p->release_arg = arg; +} + +/* + * object access function macro + */ +#define MPP_PACKET_ACCESSORS(type, field) \ + type mpp_packet_get_##field(const MppPacket s) \ + { \ + check_is_mpp_packet(s); \ + return ((MppPacketImpl*)s)->field; \ + } \ + void mpp_packet_set_##field(MppPacket s, type v) \ + { \ + check_is_mpp_packet(s); \ + ((MppPacketImpl*)s)->field = v; \ + } + +#define MPP_PACKET_ACCESSOR_GET(type, field) \ + type mpp_packet_get_##field(const MppPacket s) \ + { \ + check_is_mpp_packet(s); \ + return ((MppPacketImpl*)s)->field; \ + } + +MPP_PACKET_ACCESSORS(void *, data) +MPP_PACKET_ACCESSORS(size_t, size) +MPP_PACKET_ACCESSORS(size_t, length) +MPP_PACKET_ACCESSORS(RK_S64, pts) +MPP_PACKET_ACCESSORS(RK_S64, dts) +MPP_PACKET_ACCESSORS(RK_U32, flag) +MPP_PACKET_ACCESSORS(MppTask, task) +MPP_PACKET_ACCESSOR_GET(RK_U32, segment_nb) diff --git a/mpp/base/mpp_ref_pool.c b/mpp/base/mpp_ref_pool.c new file mode 100644 index 000000000..591c4eac8 --- /dev/null +++ b/mpp/base/mpp_ref_pool.c @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_ref_pool" + +#include + +#include "mpp_log.h" +#include "mpp_mem.h" + +#include "mpp_ref_pool.h" + +typedef struct MppRefSlot_t { + void *ptr; + RK_U32 size; + RK_U32 ref_count; +} MppRefSlot; + +RK_S32 mpp_ref_pool_init(MppRefPool *pool, RK_U32 capacity) +{ + if (!pool || !capacity) + return MPP_NOK; + + pool->slots = mpp_calloc(MppRefSlot, capacity); + if (!pool->slots) { + mpp_loge_f("failed to alloc pool slots for %u\n", capacity); + return MPP_NOK; + } + + pool->count = 0; + pool->capacity = capacity; + + return MPP_OK; +} + +void mpp_ref_pool_deinit(MppRefPool *pool) +{ + MppRefSlot *slots; + RK_S32 i; + + if (!pool) + return; + + slots = (MppRefSlot *)pool->slots; + if (slots) { + for (i = 0; i < pool->count; i++) + MPP_FREE(slots[i].ptr); + + MPP_FREE(pool->slots); + } +} + +void mpp_ref_pool_cleanup(MppRefPool *pool) +{ + MppRefSlot *slots; + RK_S32 i; + + if (!pool || !pool->slots) + return; + + slots = (MppRefSlot *)pool->slots; + for (i = 0; i < pool->count; i++) { + MppRefSlot *slot = &slots[i]; + + if (slot->ref_count == 0) { + MPP_FREE(slot->ptr); + slot->size = 0; + } + } +} + +RK_S32 mpp_ref_pool_get(MppRefPool *pool, RK_U32 size) +{ + MppRefSlot *slots; + RK_S32 i; + + if (!pool) + return -1; + + slots = (MppRefSlot *)pool->slots; + for (i = 0; i < pool->count; i++) { + MppRefSlot *slot = &slots[i]; + + if (slot->ref_count == 0) { + if (slot->ptr && slot->size >= size) { + slot->ref_count = 1; + return i; + } + if (slot->ptr) { + MPP_FREE(slot->ptr); + slot->ptr = NULL; + slot->size = 0; + } + break; + } + } + + if (i >= pool->count) { + if (pool->count >= pool->capacity) { + RK_U32 new_capacity = pool->capacity * 2; + MppRefSlot *new_slots; + + new_slots = mpp_realloc(slots, MppRefSlot, new_capacity); + if (!new_slots) { + mpp_loge_f("failed to expand pool from %u to %u\n", + pool->capacity, new_capacity); + return -1; + } + + pool->slots = new_slots; + slots = new_slots; + pool->capacity = new_capacity; + } + pool->count++; + i = pool->count - 1; + } + + slots[i].ptr = mpp_malloc_size(void, size); + if (!slots[i].ptr) { + mpp_loge_f("failed to allocate buffer size %u\n", size); + return -1; + } + + slots[i].ref_count = 1; + slots[i].size = size; + + return (RK_S32)i; +} + +void mpp_ref_pool_ref(MppRefPool *pool, RK_S32 idx) +{ + MppRefSlot *slots; + + if (!pool || idx < 0 || idx >= pool->count) + return; + + slots = (MppRefSlot *)pool->slots; + slots[idx].ref_count++; +} + +void mpp_ref_pool_put(MppRefPool *pool, RK_S32 idx) +{ + MppRefSlot *slots; + + if (!pool || idx < 0 || idx >= pool->count) + return; + + slots = (MppRefSlot *)pool->slots; + if (slots[idx].ref_count > 0) { + slots[idx].ref_count--; + + if (slots[idx].ref_count == 0 && pool->count >= pool->capacity) { + MPP_FREE(slots[idx].ptr); + slots[idx].size = 0; + } + } +} + +void *mpp_ref_pool_ptr(MppRefPool *pool, RK_S32 idx) +{ + MppRefSlot *slots; + + if (!pool || idx < 0 || idx >= pool->count) + return NULL; + + slots = (MppRefSlot *)pool->slots; + return slots[idx].ptr; +} + +RK_U32 mpp_ref_pool_size(MppRefPool *pool, RK_S32 idx) +{ + MppRefSlot *slots; + + if (!pool || idx < 0 || idx >= pool->count) + return 0; + + slots = (MppRefSlot *)pool->slots; + return slots[idx].size; +} diff --git a/mpp/base/mpp_sys_cfg.c b/mpp/base/mpp_sys_cfg.c new file mode 100644 index 000000000..a901ae2d4 --- /dev/null +++ b/mpp/base/mpp_sys_cfg.c @@ -0,0 +1,621 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_sys_cfg" + +#include + +#include "rk_mpp_cfg.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" +#include "mpp_singleton.h" + +#include "mpp_cfg.h" +#include "mpp_soc.h" +#include "mpp_trie.h" +#include "mpp_sys_cfg.h" +#include "mpp_mem_pool.h" +#include "mpp_compat_impl.h" + +#include "mpp_cfg.h" +#include "mpp_cfg_io.h" +#include "kmpp_obj.h" + +#define SYS_CFG_DBG_FUNC (0x00000001) +#define SYS_CFG_DBG_INFO (0x00000002) +#define SYS_CFG_DBG_SET (0x00000004) +#define SYS_CFG_DBG_GET (0x00000008) +#define SYS_CFG_DBG_DEC_BUF (0x00000010) + +#define sys_cfg_dbg(flag, fmt, ...) mpp_dbg_f(mpp_sys_cfg_debug, flag, fmt, ## __VA_ARGS__) + +#define sys_cfg_dbg_func(fmt, ...) sys_cfg_dbg(SYS_CFG_DBG_FUNC, fmt, ## __VA_ARGS__) +#define sys_cfg_dbg_info(fmt, ...) sys_cfg_dbg(SYS_CFG_DBG_INFO, fmt, ## __VA_ARGS__) +#define sys_cfg_dbg_set(fmt, ...) sys_cfg_dbg(SYS_CFG_DBG_SET, fmt, ## __VA_ARGS__) +#define sys_cfg_dbg_get(fmt, ...) sys_cfg_dbg(SYS_CFG_DBG_GET, fmt, ## __VA_ARGS__) +#define sys_cfg_dbg_dec_buf(fmt, ...) sys_cfg_dbg(SYS_CFG_DBG_DEC_BUF, fmt, ## __VA_ARGS__) + +#define MPP_SYS_CFG_ENTRY_TABLE(prefix, ENTRY, STRCT, EHOOK, SHOOK, ALIAS) \ + CFG_DEF_START() \ + STRUCT_START(dec_buf_chk) \ + ENTRY(prefix, u32, RK_U32, enable, FLAG_BASE(0), dec_buf_chk, enable) \ + ENTRY(prefix, u32, MppCodingType, type, FLAG_INCR, dec_buf_chk, type) \ + ENTRY(prefix, u32, MppFrameFormat, fmt_codec, FLAG_INCR, dec_buf_chk, fmt_codec) \ + ENTRY(prefix, u32, RK_U32, fmt_fbc, FLAG_INCR, dec_buf_chk, fmt_fbc) \ + ENTRY(prefix, u32, RK_U32, fmt_hdr, FLAG_INCR, dec_buf_chk, fmt_hdr) \ + ENTRY(prefix, u32, RK_U32, width, FLAG_INCR, dec_buf_chk, width) \ + ENTRY(prefix, u32, RK_U32, height, FLAG_INCR, dec_buf_chk, height) \ + ENTRY(prefix, u32, RK_U32, crop_top, FLAG_INCR, dec_buf_chk, crop_top) \ + ENTRY(prefix, u32, RK_U32, crop_bottom, FLAG_INCR, dec_buf_chk, crop_bottom) \ + ENTRY(prefix, u32, RK_U32, crop_left, FLAG_INCR, dec_buf_chk, crop_left) \ + ENTRY(prefix, u32, RK_U32, crop_right, FLAG_INCR, dec_buf_chk, crop_right) \ + ENTRY(prefix, u32, RK_U32, unit_size, FLAG_INCR, dec_buf_chk, unit_size) \ + ENTRY(prefix, u32, RK_U32, has_metadata, FLAG_INCR, dec_buf_chk, has_metadata) \ + ENTRY(prefix, u32, RK_U32, has_thumbnail, FLAG_INCR, dec_buf_chk, has_thumbnail) \ + ENTRY(prefix, u32, RK_U32, h_stride_by_byte, FLAG_INCR, dec_buf_chk, h_stride_by_byte) \ + ENTRY(prefix, u32, RK_U32, v_stride, FLAG_INCR, dec_buf_chk, v_stride) \ + /* read-only config */ \ + ENTRY(prefix, u32, RK_U32, cap_fbc, FLAG_NONE, dec_buf_chk, cap_fbc) \ + ENTRY(prefix, u32, RK_U32, cap_tile, FLAG_NONE, dec_buf_chk, cap_tile) \ + ENTRY(prefix, u32, RK_U32, h_stride_by_pixel, FLAG_NONE, dec_buf_chk, h_stride_by_pixel) \ + ENTRY(prefix, u32, RK_U32, offset_y, FLAG_NONE, dec_buf_chk, offset_y) \ + ENTRY(prefix, u32, RK_U32, size_total, FLAG_NONE, dec_buf_chk, size_total) \ + ENTRY(prefix, u32, RK_U32, size_fbc_hdr, FLAG_NONE, dec_buf_chk, size_fbc_hdr) \ + ENTRY(prefix, u32, RK_U32, size_fbc_bdy, FLAG_NONE, dec_buf_chk, size_fbc_bdy) \ + ENTRY(prefix, u32, RK_U32, size_metadata, FLAG_NONE, dec_buf_chk, size_metadata) \ + ENTRY(prefix, u32, RK_U32, size_thumbnail, FLAG_NONE, dec_buf_chk, size_thumbnail) \ + STRUCT_END(dec_buf_chk) \ + CFG_DEF_END() + +#define KMPP_OBJ_NAME mpp_sys_cfg +#define KMPP_OBJ_INTF_TYPE MppSysCfg +#define KMPP_OBJ_IMPL_TYPE MppSysCfgSet +#define KMPP_OBJ_SGLN_ID MPP_SGLN_SYS_CFG +#define KMPP_OBJ_ENTRY_TABLE MPP_SYS_CFG_ENTRY_TABLE +#define KMPP_OBJ_ACCESS_DISABLE +#define KMPP_OBJ_HIERARCHY_ENABLE +#include "kmpp_obj_helper.h" + +typedef enum SysCfgAlignType_e { + SYS_CFG_ALIGN_8, + SYS_CFG_ALIGN_16, + SYS_CFG_ALIGN_32, + SYS_CFG_ALIGN_64, + SYS_CFG_ALIGN_128, + SYS_CFG_ALIGN_256, + SYS_CFG_ALIGN_256_ODD, + SYS_CFG_ALIGN_128_ODD_PLUS_64, + SYS_CFG_ALIGN_LEN_DEFAULT, + SYS_CFG_ALIGN_LEN_420, + SYS_CFG_ALIGN_LEN_422, + SYS_CFG_ALIGN_LEN_444, + SYS_CFG_ALIGN_LEN_422_AVC, + SYS_CFG_ALIGN_LEN_420_AV1, + SYS_CFG_ALIGN_LEN_422_AV1, + SYS_CFG_ALIGN_BUTT, +} SysCfgAlignType; + +static RK_U32 mpp_sys_cfg_align(SysCfgAlignType type, RK_U32 val) +{ + switch (type) { + case SYS_CFG_ALIGN_8: { return MPP_ALIGN(val, 8);}; + case SYS_CFG_ALIGN_16: { return MPP_ALIGN(val, 16);}; + case SYS_CFG_ALIGN_32: { return MPP_ALIGN(val, 32);}; + case SYS_CFG_ALIGN_64: { return MPP_ALIGN(val, 64);}; + case SYS_CFG_ALIGN_128: { return MPP_ALIGN(val, 128);}; + case SYS_CFG_ALIGN_256: { return MPP_ALIGN(val, 256);}; + case SYS_CFG_ALIGN_256_ODD: {return MPP_ALIGN(val, 256) | 256;}; + case SYS_CFG_ALIGN_128_ODD_PLUS_64: { + val = MPP_ALIGN(val, 64); + if (((val - 64) % 256 == 128)) + return val; + else + return ((MPP_ALIGN(val, 128) | 128) + 64); + }; + case SYS_CFG_ALIGN_LEN_DEFAULT: { return (9 * MPP_ALIGN(val, 16) / 5);}; + case SYS_CFG_ALIGN_LEN_420: + case SYS_CFG_ALIGN_LEN_422: { return (2 * MPP_ALIGN(val, 16));}; + case SYS_CFG_ALIGN_LEN_444: { return (3 * MPP_ALIGN(val, 16));}; + case SYS_CFG_ALIGN_LEN_422_AVC: { return ((5 * MPP_ALIGN(val, 16)) / 2);}; + case SYS_CFG_ALIGN_LEN_420_AV1: { return (2 * MPP_ALIGN(val, 128));}; + case SYS_CFG_ALIGN_LEN_422_AV1: { return ((5 * MPP_ALIGN(val, 64)) / 2);}; + default: { + mpp_err("Specifying the align type is necessary"); + return MPP_NOK; + }; + } +} + +/* Based on drm_gem_framebuffer_helper.c drm_gem_afbc_min_size() */ +static RK_S32 get_afbc_min_size(RK_S32 width, RK_S32 height, RK_S32 bpp) +{ +#define AFBC_HEADER_SIZE 16 +#define AFBC_HDR_ALIGN 64 +#define AFBC_SUPERBLOCK_PIXELS 256 +#define AFBC_SUPERBLOCK_ALIGNMENT 128 + + RK_S32 n_blocks, hdr_alignment, size; + + /* AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 and !AFBC_FORMAT_MOD_TILED */ + width = MPP_ALIGN(width, 16); + height = MPP_ALIGN(height, 16); + hdr_alignment = AFBC_HDR_ALIGN; + + n_blocks = (width * height) / AFBC_SUPERBLOCK_PIXELS; + + size = MPP_ALIGN(n_blocks * AFBC_HEADER_SIZE, hdr_alignment); + size += n_blocks * MPP_ALIGN(bpp * AFBC_SUPERBLOCK_PIXELS / 8, + AFBC_SUPERBLOCK_ALIGNMENT); + return size; +} + +/* + * in: fmt_fbc,type,width,h_stride + * out: stride_w + * + * in: fmt_fbc,type,height,v_stride + * out: stride_h + * + * in: fmt_fbc,type,fmt_codec,width,h_stride + * out: h_stride_by_byte + * + * in: fmt_fbc,type,fmt_codec,width,height,h_stride,v_stride + * out: buffer_size + */ +MPP_RET mpp_sys_dec_buf_chk_proc(MppSysDecBufChkCfg *cfg) +{ + MppCodingType type = cfg->type; + MppFrameFormat fmt = (MppFrameFormat)(((RK_U32)cfg->fmt_codec & MPP_FRAME_FMT_MASK) | + (cfg->fmt_fbc & MPP_FRAME_FBC_MASK) | + (cfg->fmt_hdr & MPP_FRAME_HDR_MASK)); + MppFrameFormat fmt_raw = cfg->fmt_codec; + + RK_U32 aligned_pixel = 0; + RK_U32 aligned_pixel_byte = 0; + RK_U32 aligned_byte = 0; + RK_U32 aligned_height = 0; + RK_U32 size_total = 0; + RK_U32 size_total_old = 0; + RK_U32 depth = MPP_FRAME_FMT_IS_YUV_10BIT(fmt) ? 10 : 8; + RockchipSocType soc_type = mpp_get_soc_type(); + + if (type == MPP_VIDEO_CodingUnused) { + mpp_err("The coding type is invalid"); + return MPP_NOK; + } + + /* use codec stride */ + if (cfg->h_stride_by_byte) + aligned_pixel = cfg->h_stride_by_byte * 8 / depth; + if (cfg->v_stride) + aligned_height = cfg->v_stride; + + sys_cfg_dbg_dec_buf("org pixel wxh: [%d %d]\n", cfg->width, cfg->height); + sys_cfg_dbg_dec_buf("outside stride wxh: [%d %d]\n", + cfg->h_stride_by_byte, cfg->v_stride); + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + RK_U32 ext_pix = 0; + /* fbc case */ + switch (type) { + case MPP_VIDEO_CodingHEVC : { + if (((soc_type == ROCKCHIP_SOC_RK3538) || + (soc_type == ROCKCHIP_SOC_RK3572)) && + MPP_FRAME_FMT_IS_AFBC(fmt)) { + ext_pix = ((aligned_height == cfg->height) || + (aligned_height - cfg->height < 8)) ? + 8 : 0; + } + sys_cfg_dbg_dec_buf("height padding: %d\n", ext_pix); + aligned_pixel = MPP_ALIGN(cfg->width, 64); + aligned_height = ((aligned_height != 0) ? aligned_height : + cfg->height) + ext_pix; + aligned_height = MPP_ALIGN(aligned_height, 16); + } break; + case MPP_VIDEO_CodingAV1 : { + aligned_pixel = MPP_ALIGN(cfg->width, 64); + aligned_height = MPP_ALIGN((aligned_height != 0) ? aligned_height : + cfg->height, 16); + } break; + /* + * avc aligned to ctu + * p_Vid->width = p_Vid->PicWidthInMbs * 16 + * p_Vid->height = p_Vid->FrameHeightInMbs * 16 + */ + case MPP_VIDEO_CodingAVC : { + if (((soc_type == ROCKCHIP_SOC_RK3538) || + (soc_type == ROCKCHIP_SOC_RK3572)) && + MPP_FRAME_FMT_IS_AFBC(fmt)) { + ext_pix = ((aligned_height == cfg->height) || + (aligned_height - cfg->height < 16)) ? + 8 : 0; + } + sys_cfg_dbg_dec_buf("height padding: %d\n", ext_pix); + aligned_pixel = MPP_ALIGN(cfg->width, 64); + aligned_height = ((aligned_height != 0) ? aligned_height : + cfg->height) + ext_pix; + aligned_height = MPP_ALIGN(aligned_height, 16); + } break; + case MPP_VIDEO_CodingAVSPLUS : + case MPP_VIDEO_CodingAVS : + case MPP_VIDEO_CodingAVS2 : { + aligned_pixel = MPP_ALIGN(cfg->width, 64); + aligned_height = MPP_ALIGN((aligned_height != 0) ? aligned_height : + cfg->height, 16); + } break; + case MPP_VIDEO_CodingVP9 : { + aligned_pixel = MPP_ALIGN(cfg->width, 64); + aligned_height = MPP_ALIGN((aligned_height != 0) ? aligned_height : + cfg->height, 64); + } break; + default : { + aligned_pixel = MPP_ALIGN(cfg->width, 16); + aligned_height = MPP_ALIGN((aligned_height != 0) ? aligned_height : + cfg->height, 16); + } break; + } + sys_cfg_dbg_dec_buf("spec aligned pixel wxh: [%d %d]\n", aligned_pixel, aligned_height); + + /*fbc stride default 64 align*/ + if (*compat_ext_fbc_hdr_256_odd) + aligned_pixel_byte = (MPP_ALIGN(aligned_pixel, 256) | 256) * depth >> 3; + else + aligned_pixel_byte = MPP_ALIGN(aligned_pixel, 64) * depth >> 3; + sys_cfg_dbg_dec_buf("need 256 odd align: %d\n", *compat_ext_fbc_hdr_256_odd); + + switch (type) { + case MPP_VIDEO_CodingAVC : + case MPP_VIDEO_CodingAVSPLUS : + case MPP_VIDEO_CodingAVS : + case MPP_VIDEO_CodingAVS2 : { + aligned_byte = MPP_ALIGN(aligned_pixel_byte, 64); + } break; + case MPP_VIDEO_CodingHEVC : { + aligned_byte = MPP_ALIGN(aligned_pixel_byte, 64); + } break; + case MPP_VIDEO_CodingVP9 : { + aligned_byte = MPP_ALIGN(aligned_pixel_byte, 64); + } break; + case MPP_VIDEO_CodingAV1 : { + aligned_byte = MPP_ALIGN(aligned_pixel_byte, 16); + } break; + default : { + aligned_byte = MPP_ALIGN(aligned_pixel_byte, 16); + } break; + } + sys_cfg_dbg_dec_buf("dec hw aligned hor_byte: [%d]\n", aligned_byte); + + cfg->h_stride_by_byte = aligned_byte; + cfg->h_stride_by_pixel = aligned_pixel; + cfg->v_stride = aligned_height; + + switch ((fmt_raw & MPP_FRAME_FMT_MASK)) { + case MPP_FMT_YUV420SP_10BIT : { + size_total = get_afbc_min_size(aligned_pixel, aligned_height, 15); + } break; + case MPP_FMT_YUV422SP_10BIT : { + size_total = get_afbc_min_size(aligned_pixel, aligned_height, 20); + } break; + case MPP_FMT_YUV420SP : { + size_total = get_afbc_min_size(aligned_pixel, aligned_height, 12); + } break; + case MPP_FMT_YUV422SP : { + size_total = get_afbc_min_size(aligned_pixel, aligned_height, 16); + } break; + case MPP_FMT_YUV444SP : { + size_total = get_afbc_min_size(aligned_pixel, aligned_height, 24); + } break; + case MPP_FMT_YUV444SP_10BIT : { + size_total = get_afbc_min_size(aligned_pixel, aligned_height, 30); + } break; + default : { + size_total = aligned_byte * aligned_height * 3 / 2; + mpp_err("dec out fmt 0x%x is no support", fmt_raw & MPP_FRAME_FMT_MASK); + } break; + } + sys_cfg_dbg_dec_buf("res aligned_pixel %d\n", aligned_pixel); + sys_cfg_dbg_dec_buf("res aligned_byte %d\n", aligned_byte); + sys_cfg_dbg_dec_buf("res aligned_height %d\n", aligned_height); + sys_cfg_dbg_dec_buf("res GPU aligned size_total: [%d]\n", size_total); + + cfg->size_total = size_total; + } else { + /* tile case */ + /* raster case */ + aligned_pixel = cfg->width; + switch (type) { + case MPP_VIDEO_CodingHEVC : { + aligned_pixel = MPP_ALIGN(cfg->width, 64); + aligned_height = MPP_ALIGN(cfg->height, 8); + } break; + /* + * avc aligned to ctu + * p_Vid->width = p_Vid->PicWidthInMbs * 16 + * p_Vid->height = p_Vid->FrameHeightInMbs * 16 + */ + case MPP_VIDEO_CodingAVC : { + aligned_pixel = MPP_ALIGN(cfg->width, 16); + aligned_height = MPP_ALIGN(cfg->height, 16); + } break; + case MPP_VIDEO_CodingVP9 : { + if (soc_type == ROCKCHIP_SOC_RK3399) + aligned_height = MPP_ALIGN(cfg->height, 64); + else if (soc_type == ROCKCHIP_SOC_RK3588) + aligned_height = MPP_ALIGN(cfg->height, 16); + else + aligned_height = MPP_ALIGN(cfg->height, 8); + } break; + case MPP_VIDEO_CodingAV1 : { + aligned_height = MPP_ALIGN(cfg->height, 8); + } break; + case MPP_VIDEO_CodingVP8 : + case MPP_VIDEO_CodingH263 : + case MPP_VIDEO_CodingMPEG2 : + case MPP_VIDEO_CodingMPEG4 : { + aligned_height = MPP_ALIGN(cfg->height, 16); + } break; + case MPP_VIDEO_CodingAVS2 : { + aligned_pixel = MPP_ALIGN(cfg->width, 64); + aligned_height = MPP_ALIGN(cfg->height, 8); + } break; + default : { + aligned_height = MPP_ALIGN(cfg->height, 8); + } break; + } + sys_cfg_dbg_dec_buf("spec aligned pixel wxh: [%d %d]\n", aligned_pixel, aligned_height); + + aligned_pixel_byte = (cfg->h_stride_by_byte != 0) ? cfg->h_stride_by_byte : + aligned_pixel * depth / 8; + aligned_height = (cfg->v_stride != 0) ? cfg->v_stride : aligned_height; + + switch (type) { + case MPP_VIDEO_CodingHEVC : { + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_64, aligned_pixel_byte); + } break; + case MPP_VIDEO_CodingVP9 : { + if (soc_type == ROCKCHIP_SOC_RK3576) + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_128_ODD_PLUS_64, + aligned_pixel_byte); + else + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_256_ODD, aligned_pixel_byte); + } break; + case MPP_VIDEO_CodingAV1 : { + if (soc_type == ROCKCHIP_SOC_RK3588) + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_16, aligned_pixel_byte); + else + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_128, aligned_pixel_byte); + } break; + default : { + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_16, aligned_pixel_byte); + } break; + } + sys_cfg_dbg_dec_buf("dec hw aligned hor_byte: [%d %d]\n", aligned_byte); + + /* + * NOTE: rk3576 use 128 odd plus 64 for all non jpeg format + * all the other socs use 256 odd on larger than 1080p + */ + if ((aligned_byte > 1920 || soc_type == ROCKCHIP_SOC_RK3576) + && type != MPP_VIDEO_CodingMJPEG) { + rk_s32 update = 0; + + switch (soc_type) { + case ROCKCHIP_SOC_RK3399 : + case ROCKCHIP_SOC_RK3568 : + case ROCKCHIP_SOC_RK3562 : + case ROCKCHIP_SOC_RK3528 : + case ROCKCHIP_SOC_RK3588 : { + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_256_ODD, aligned_byte); + update = 1; + } break; + case ROCKCHIP_SOC_RK3576 : { + aligned_byte = mpp_sys_cfg_align(SYS_CFG_ALIGN_128_ODD_PLUS_64, aligned_byte); + update = 1; + } break; + default : { + } break; + } + + /* + * recalc aligned_pixel here + * NOTE: no RGB format here in fact + */ + if (update) { + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP_10BIT: + case MPP_FMT_YUV422SP_10BIT: + case MPP_FMT_YUV444SP_10BIT: { + aligned_pixel = aligned_byte * 8 / 10; + } break; + case MPP_FMT_YUV422_YVYU: + case MPP_FMT_YUV422_YUYV: + case MPP_FMT_RGB565: + case MPP_FMT_BGR565: { + aligned_pixel = aligned_byte / 2; + } break; + case MPP_FMT_RGB888: + case MPP_FMT_BGR888: { + aligned_pixel = aligned_byte / 3; + } break; + default : { + aligned_pixel = aligned_byte; + } break; + } + } + } + sys_cfg_dbg_dec_buf("dec hw performance aligned hor_byte: [%d]\n", aligned_pixel); + + cfg->h_stride_by_byte = aligned_byte; + cfg->h_stride_by_pixel = aligned_pixel; + cfg->v_stride = aligned_height; + + size_total = aligned_byte * aligned_height; + size_total_old = size_total; + sys_cfg_dbg_dec_buf("fmt_raw %x\n", fmt_raw); + sys_cfg_dbg_dec_buf("res aligned_pixel %d\n", aligned_pixel); + sys_cfg_dbg_dec_buf("res aligned_byte %d\n", aligned_byte); + sys_cfg_dbg_dec_buf("res aligned_height %d\n", aligned_height); + + switch (fmt_raw) { + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_10BIT : + case MPP_FMT_YUV420P : + case MPP_FMT_YUV420SP_VU : { + SysCfgAlignType align_type = SYS_CFG_ALIGN_LEN_DEFAULT; + + /* hevc and vp9 - SYS_CFG_ALIGN_LEN_DEFAULT */ + if (type == MPP_VIDEO_CodingAV1) + align_type = SYS_CFG_ALIGN_LEN_420_AV1; + else if (type == MPP_VIDEO_CodingAVC) + align_type = SYS_CFG_ALIGN_LEN_420; + + size_total = mpp_sys_cfg_align(align_type, size_total); + } break; + case MPP_FMT_YUV422SP : + case MPP_FMT_YUV422SP_10BIT : + case MPP_FMT_YUV422P : + case MPP_FMT_YUV422SP_VU : + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_YVYU : + case MPP_FMT_YUV422_UYVY : + case MPP_FMT_YUV422_VYUY : + case MPP_FMT_YUV440SP : + case MPP_FMT_YUV411SP : { + SysCfgAlignType align_type; + + if (type == MPP_VIDEO_CodingAVC) + align_type = SYS_CFG_ALIGN_LEN_422_AVC; + else if (type == MPP_VIDEO_CodingAV1) + align_type = SYS_CFG_ALIGN_LEN_422_AV1; + else + align_type = SYS_CFG_ALIGN_LEN_422; + + size_total = mpp_sys_cfg_align(align_type, size_total); + } break; + case MPP_FMT_YUV400 : { + /* do nothing */ + } break; + case MPP_FMT_YUV444SP : + case MPP_FMT_YUV444P : + case MPP_FMT_YUV444SP_10BIT : { + size_total = mpp_sys_cfg_align(SYS_CFG_ALIGN_LEN_444, size_total); + } break; + default : { + size_total = size_total * 3 / 2; + } + } + sys_cfg_dbg_dec_buf("res size total %d -> %d\n", size_total_old, size_total); + + cfg->size_total = size_total; + } + + return MPP_OK; +} + +MPP_RET mpp_sys_cfg_ioctl(MppSysCfg cfg) +{ + MppSysCfgSet *p = (MppSysCfgSet *)kmpp_obj_to_entry(cfg); + + if (!p) { + mpp_loge_f("invalid NULL input config\n"); + return MPP_ERR_NULL_PTR; + } + + if (p->dec_buf_chk.enable) { + mpp_sys_dec_buf_chk_proc(&p->dec_buf_chk); + p->dec_buf_chk.enable = 0; + } + + return MPP_OK; +} + +#define MPP_CFG_SET_ACCESS(func_name, in_type, cfg_type) \ + MPP_RET func_name(MppSysCfg cfg, const char *name, in_type val) \ + { \ + KmppEntry *entry = NULL; \ + if (NULL == cfg || NULL == name) { \ + mpp_loge_f("invalid input cfg %p name %p\n", cfg, name); \ + return rk_nok; \ + } \ + kmpp_objdef_get_entry(mpp_sys_cfg_def, name, &entry); \ + if (!entry) \ + return rk_nok; \ + if (!entry->tbl.flag_offset) { \ + mpp_loge_f("can not set readonly cfg %s\n", name); \ + return rk_nok; \ + } \ + return kmpp_obj_tbl_set_##cfg_type(cfg, entry, val); \ + } + +MPP_CFG_SET_ACCESS(mpp_sys_cfg_set_s32, RK_S32, s32); +MPP_CFG_SET_ACCESS(mpp_sys_cfg_set_u32, RK_U32, u32); +MPP_CFG_SET_ACCESS(mpp_sys_cfg_set_s64, RK_S64, s64); +MPP_CFG_SET_ACCESS(mpp_sys_cfg_set_u64, RK_U64, u64); +MPP_CFG_SET_ACCESS(mpp_sys_cfg_set_ptr, void *, ptr); +MPP_CFG_SET_ACCESS(mpp_sys_cfg_set_st, void *, st); + +#define MPP_CFG_GET_ACCESS(func_name, in_type, cfg_type) \ + MPP_RET func_name(MppSysCfg cfg, const char *name, in_type *val) \ + { \ + if (NULL == cfg || NULL == name) { \ + mpp_loge_f("invalid input cfg %p name %p\n", cfg, name); \ + return rk_nok; \ + } \ + return kmpp_obj_get_##cfg_type(cfg, name, val); \ + } + +MPP_CFG_GET_ACCESS(mpp_sys_cfg_get_s32, RK_S32, s32); +MPP_CFG_GET_ACCESS(mpp_sys_cfg_get_u32, RK_U32, u32); +MPP_CFG_GET_ACCESS(mpp_sys_cfg_get_s64, RK_S64, s64); +MPP_CFG_GET_ACCESS(mpp_sys_cfg_get_u64, RK_U64, u64); +MPP_CFG_GET_ACCESS(mpp_sys_cfg_get_ptr, void *, ptr); +MPP_CFG_GET_ACCESS(mpp_sys_cfg_get_st, void , st); + +void mpp_sys_cfg_show(void) +{ + MppTrie *trie = kmpp_objdef_get_trie(mpp_sys_cfg_def); + MppTrieInfo *root; + + if (!trie) + return ; + + root = mpp_trie_get_info_first(trie); + + mpp_logi("dumping valid configure string start\n"); + + if (root) { + MppTrieInfo *node = root; + rk_s32 len = mpp_trie_get_name_max(trie); + + mpp_logi("%-*s %-6s | %6s | %4s | %4s\n", len, "name", "type", "offset", "size", "flag (hex)"); + + do { + if (mpp_trie_info_is_self(node)) + continue; + + if (node->ctx_len == sizeof(KmppEntry)) { + KmppEntry *entry = (KmppEntry *)mpp_trie_info_ctx(node); + + mpp_logi("%-*s %-6s | %-6d | %-4d | %-4x %s\n", len, mpp_trie_info_name(node), + strof_elem_type(entry->tbl.elem_type), entry->tbl.elem_offset, + entry->tbl.elem_size, entry->tbl.flag_offset, + entry->tbl.flag_offset ? "wr" : "ro"); + } else { + mpp_logi("%-*s size - %d\n", len, mpp_trie_info_name(node), node->ctx_len); + } + } while ((node = mpp_trie_get_info_next(trie, node))); + } + + mpp_logi("dumping valid configure string done\n"); + + mpp_logi("sys cfg size %d count %d with trie node %d size %d\n", + sizeof(MppSysCfgSet), mpp_trie_get_info_count(trie), + mpp_trie_get_node_count(trie), mpp_trie_get_buf_size(trie)); +} diff --git a/mpp/base/mpp_sys_cfg_st.c b/mpp/base/mpp_sys_cfg_st.c new file mode 100644 index 000000000..1a73818f4 --- /dev/null +++ b/mpp/base/mpp_sys_cfg_st.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_sys_cfg_st" + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "rk_mpp_cfg.h" +#include "mpp_sys_cfg.h" +#include "mpp_sys_cfg_st.h" + +MPP_RET mpp_sys_cfg_st_get_h_stride(MppSysCfgStHStrd *h_stride_cfg) +{ + MPP_RET ret = MPP_OK; + MppSysCfg cfg; + + ret = mpp_sys_cfg_get(&cfg); + if (ret) { + mpp_err("mpp_sys_cfg_get failed\n"); + goto DONE; + } + + /* set correct parameter */ + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:enable", 1); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:type", h_stride_cfg->type); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_fbc", h_stride_cfg->fmt_fbc); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:width", h_stride_cfg->width); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:h_stride_by_byte", h_stride_cfg->h_stride_by_byte); + + /* get result */ + mpp_sys_cfg_ioctl(cfg); + + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:h_stride_by_pixel", + &h_stride_cfg->h_stride_by_pixel); + + ret = mpp_sys_cfg_put(cfg); + if (ret) { + mpp_err("mpp_sys_cfg_put failed\n"); + goto DONE; + } + +DONE: + mpp_err_f("sys cfg get paras %s\n", ret ? "failed" : "success"); + return ret; +} + +MPP_RET mpp_sys_cfg_st_get_byte_stride(MppSysCfgStHByteStrd *byte_stride_cfg) +{ + MPP_RET ret = MPP_OK; + MppSysCfg cfg; + + ret = mpp_sys_cfg_get(&cfg); + if (ret) { + mpp_err("mpp_sys_cfg_get failed\n"); + goto DONE; + } + + /* set correct parameter */ + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:enable", 1); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:type", byte_stride_cfg->type); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_codec", byte_stride_cfg->fmt_codec); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_fbc", byte_stride_cfg->fmt_fbc); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:width", byte_stride_cfg->width); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:h_stride_by_byte", byte_stride_cfg->h_stride_by_byte); + + /* get result */ + mpp_sys_cfg_ioctl(cfg); + + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:h_stride_by_byte", + &byte_stride_cfg->h_stride_by_byte); + + ret = mpp_sys_cfg_put(cfg); + if (ret) { + mpp_err("mpp_sys_cfg_put failed\n"); + goto DONE; + } + +DONE: + mpp_err_f("sys cfg get paras %s\n", ret ? "failed" : "success"); + return ret; +} + +MPP_RET mpp_sys_cfg_st_get_v_stride(MppSysCfgStVStrd *v_stride_cfg) +{ + MPP_RET ret = MPP_OK; + MppSysCfg cfg; + + ret = mpp_sys_cfg_get(&cfg); + if (ret) { + mpp_err("mpp_sys_cfg_get failed\n"); + goto DONE; + } + + /* set correct parameter */ + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:enable", 1); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:type", v_stride_cfg->type); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_fbc", v_stride_cfg->fmt_fbc); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:height", v_stride_cfg->height); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:v_stride", v_stride_cfg->v_stride); + + /* get result */ + mpp_sys_cfg_ioctl(cfg); + + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:v_stride", &v_stride_cfg->v_stride); + + ret = mpp_sys_cfg_put(cfg); + if (ret) { + mpp_err("mpp_sys_cfg_put failed\n"); + goto DONE; + } + +DONE: + mpp_err_f("sys cfg get paras %s\n", ret ? "failed" : "success"); + return ret; +} + +MPP_RET mpp_sys_cfg_st_get_size(MppSysCfgStSize *size_cfg) +{ + MPP_RET ret = MPP_OK; + MppSysCfg cfg; + + ret = mpp_sys_cfg_get(&cfg); + if (ret) { + mpp_err("mpp_sys_cfg_get failed\n"); + goto DONE; + } + + /* set correct parameter */ + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:enable", 1); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:type", size_cfg->type); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_codec", size_cfg->fmt_codec); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_fbc", size_cfg->fmt_fbc); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:width", size_cfg->width); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:height", size_cfg->height); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:h_stride_by_byte", size_cfg->h_stride_by_byte); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:v_stride", size_cfg->v_stride); + + /* get result */ + mpp_sys_cfg_ioctl(cfg); + + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:h_stride_by_byte", &size_cfg->h_stride_by_byte); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:h_stride_by_pixel", &size_cfg->h_stride_by_pixel); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:v_stride", &size_cfg->v_stride); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:size_total", &size_cfg->size_total); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:size_fbc_hdr", &size_cfg->size_fbc_hdr); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:size_fbc_bdy", &size_cfg->size_fbc_bdy); + + ret = mpp_sys_cfg_put(cfg); + if (ret) { + mpp_err("mpp_sys_cfg_put failed\n"); + goto DONE; + } + +DONE: + mpp_err_f("sys cfg get paras %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/mpp/base/mpp_task.c b/mpp/base/mpp_task.c new file mode 100644 index 000000000..0db474475 --- /dev/null +++ b/mpp/base/mpp_task.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_task" + +#include + +#include "mpp_task.h" +#include "mpp_task_impl.h" + +MPP_RET mpp_task_meta_set_s32(MppTask task, MppMetaKey key, RK_S32 val) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + return mpp_meta_set_s32(impl->meta, key, val); +} + +MPP_RET mpp_task_meta_set_s64(MppTask task, MppMetaKey key, RK_S64 val) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + return mpp_meta_set_s64(impl->meta, key, val); +} + +MPP_RET mpp_task_meta_set_ptr(MppTask task, MppMetaKey key, void *val) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + return mpp_meta_set_ptr(impl->meta, key, val); +} + +MPP_RET mpp_task_meta_set_frame(MppTask task, MppMetaKey key, MppFrame frame) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + return mpp_meta_set_frame(impl->meta, key, frame); +} + +MPP_RET mpp_task_meta_set_packet(MppTask task, MppMetaKey key, MppPacket packet) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + return mpp_meta_set_packet(impl->meta, key, packet); +} + +MPP_RET mpp_task_meta_set_buffer(MppTask task, MppMetaKey key, MppBuffer buffer) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + return mpp_meta_set_buffer(impl->meta, key, buffer); +} + +MPP_RET mpp_task_meta_get_s32(MppTask task, MppMetaKey key, RK_S32 *val, RK_S32 default_val) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + MPP_RET ret = mpp_meta_get_s32(impl->meta, key, val); + if (ret) + *val = default_val; + return ret; +} + +MPP_RET mpp_task_meta_get_s64(MppTask task, MppMetaKey key, RK_S64 *val, RK_S64 default_val) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + MPP_RET ret = mpp_meta_get_s64(impl->meta, key, val); + if (ret) + *val = default_val; + return ret; +} + +MPP_RET mpp_task_meta_get_ptr(MppTask task, MppMetaKey key, void **val, void *default_val) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + MPP_RET ret = mpp_meta_get_ptr(impl->meta, key, val); + if (ret) + *val = default_val; + return ret; +} + +MPP_RET mpp_task_meta_get_frame(MppTask task, MppMetaKey key, MppFrame *frame) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + MPP_RET ret = mpp_meta_get_frame(impl->meta, key, frame); + if (ret) + *frame = NULL; + return ret; +} + +MPP_RET mpp_task_meta_get_packet(MppTask task, MppMetaKey key, MppPacket *packet) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + MPP_RET ret = mpp_meta_get_packet(impl->meta, key, packet); + if (ret) + *packet = NULL; + return ret; +} + +MPP_RET mpp_task_meta_get_buffer(MppTask task, MppMetaKey key, MppBuffer *buffer) +{ + if (check_mpp_task_name(task)) + return MPP_NOK; + + MppTaskImpl *impl = (MppTaskImpl *)task; + MPP_RET ret = mpp_meta_get_buffer(impl->meta, key, buffer); + if (ret) + *buffer = NULL; + return ret; +} + diff --git a/mpp/base/mpp_task_impl.c b/mpp/base/mpp_task_impl.c new file mode 100644 index 000000000..92c10223e --- /dev/null +++ b/mpp/base/mpp_task_impl.c @@ -0,0 +1,549 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_task_impl" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "mpp_task_impl.h" +#include "mpp_meta_impl.h" + +#define MAX_TASK_COUNT 8 + +#define MPP_TASK_DBG_FUNCTION (0x00000001) +#define MPP_TASK_DBG_FLOW (0x00000002) + +#define mpp_task_dbg(flag, fmt, ...) mpp_dbg(mpp_task_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_task_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_task_debug, flag, fmt, ## __VA_ARGS__) + +#define mpp_task_dbg_func(fmt, ...) mpp_task_dbg_f(MPP_TASK_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define mpp_task_dbg_flow(fmt, ...) mpp_task_dbg(MPP_TASK_DBG_FLOW, fmt, ## __VA_ARGS__) + +typedef struct MppTaskStatusInfo_t { + struct list_head list; + RK_S32 count; + MppTaskStatus status; + MppCond cond; +} MppTaskStatusInfo; + +typedef struct MppTaskQueueImpl_t { + char name[32]; + void *mpp; + MppMutex lock; + RK_S32 task_count; + RK_S32 ready; // flag for deinit + + // two ports inside of task queue + MppPort input; + MppPort output; + + MppTaskImpl *tasks; + + MppTaskStatusInfo info[MPP_TASK_STATUS_BUTT]; +} MppTaskQueueImpl; + +typedef struct MppPortImpl_t { + MppPortType type; + MppTaskQueueImpl *queue; + + MppTaskStatus status_curr; + MppTaskStatus next_on_dequeue; + MppTaskStatus next_on_enqueue; +} MppPortImpl; + +static const char *module_name = MODULE_TAG; +static const char *port_type_str[] = { + "input", + "output", + "NULL", +}; + +static const char *task_status_str[] = { + "input_port", + "input_hold", + "output_port", + "output_hold", + "NULL", +}; + +RK_U32 mpp_task_debug = 0; + +static inline void setup_mpp_task_name(MppTaskImpl *task) +{ + task->name = module_name; +} + +MPP_RET check_mpp_task_name(MppTask task) +{ + if (task && ((MppTaskImpl *)task)->name == module_name) + return MPP_OK; + + mpp_err_f("pointer %p failed on check\n", task); + mpp_abort(); + return MPP_NOK; +} + +static MPP_RET mpp_port_init(MppTaskQueueImpl *queue, MppPortType type, MppPort *port) +{ + MppPortImpl *impl = mpp_malloc(MppPortImpl, 1); + if (!impl) { + mpp_err_f("failed to malloc MppPort type %d\n", type); + return MPP_ERR_MALLOC; + } + + mpp_task_dbg_func("enter queue %p type %d\n", queue, type); + + impl->type = type; + impl->queue = queue; + + if (MPP_PORT_INPUT == type) { + impl->status_curr = MPP_INPUT_PORT; + impl->next_on_dequeue = MPP_INPUT_HOLD; + impl->next_on_enqueue = MPP_OUTPUT_PORT; + } else { + impl->status_curr = MPP_OUTPUT_PORT; + impl->next_on_dequeue = MPP_OUTPUT_HOLD; + impl->next_on_enqueue = MPP_INPUT_PORT; + } + + *port = (MppPort *)impl; + + mpp_task_dbg_func("leave queue %p port %p\n", queue, impl); + + return MPP_OK; +} + +static MPP_RET mpp_port_deinit(MppPort port) +{ + mpp_task_dbg_func("enter port %p\n", port); + mpp_free(port); + mpp_task_dbg_func("leave\n"); + return MPP_OK; +} + +MPP_RET _mpp_port_poll(const char *caller, MppPort port, MppPollType timeout) +{ + MppPortImpl *port_impl = (MppPortImpl *)port; + MppTaskQueueImpl *queue = port_impl->queue; + MppTaskStatusInfo *curr = NULL; + MPP_RET ret = MPP_NOK; + + mpp_mutex_lock(&queue->lock); + + mpp_task_dbg_func("enter port %p\n", port); + if (!queue->ready) { + mpp_err("try to query when %s queue is not ready\n", + port_type_str[port_impl->type]); + goto RET; + } + + curr = &queue->info[port_impl->status_curr]; + if (curr->count) { + mpp_assert(!list_empty(&curr->list)); + ret = (MPP_RET)curr->count; + mpp_task_dbg_flow("mpp %p %s from %s poll %s port timeout %d count %d\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type], + timeout, curr->count); + } else { + mpp_assert(list_empty(&curr->list)); + + /* timeout + * zero - non-block + * negtive - block + * positive - timeout value + */ + if (timeout) { + MppCond *cond = &curr->cond; + + if (timeout < 0) { + mpp_task_dbg_flow("mpp %p %s from %s poll %s port block wait start\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type]); + + ret = (MPP_RET)mpp_cond_wait(cond, &queue->lock); + } else { + mpp_task_dbg_flow("mpp %p %s from %s poll %s port %d timeout wait start\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type], timeout); + ret = (MPP_RET)mpp_cond_timedwait(cond, &queue->lock, timeout); + } + + if (curr->count) { + mpp_assert(!list_empty(&curr->list)); + ret = (MPP_RET)curr->count; + } else if (ret > 0) + ret = MPP_NOK; + } + + mpp_task_dbg_flow("mpp %p %s from %s poll %s port timeout %d ret %d\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type], timeout, ret); + } +RET: + mpp_mutex_unlock(&queue->lock); + mpp_task_dbg_func("leave\n"); + return ret; +} + +MPP_RET _mpp_port_move(const char *caller, MppPort port, MppTask task, + MppTaskStatus status) +{ + MppTaskImpl *task_impl = (MppTaskImpl *)task; + MppPortImpl *port_impl = (MppPortImpl *)port; + MppTaskQueueImpl *queue = port_impl->queue; + MppTaskStatusInfo *curr = NULL; + MppTaskStatusInfo *next = NULL; + MPP_RET ret = MPP_NOK; + + mpp_mutex_lock(&queue->lock); + + mpp_task_dbg_func("caller %s enter port %p task %p\n", caller, port, task); + + if (!queue->ready) { + mpp_err("try to move task when %s queue is not ready\n", + port_type_str[port_impl->type]); + goto RET; + } + + check_mpp_task_name(task); + + mpp_assert(task_impl->queue == (MppTaskQueue)queue); + + curr = &queue->info[task_impl->status]; + next = &queue->info[status]; + + list_del_init(&task_impl->list); + curr->count--; + list_add_tail(&task_impl->list, &next->list); + next->count++; + + mpp_task_dbg_flow("mpp %p %s from %s move %s port task %p %s -> %s done\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type], task_impl, + task_status_str[task_impl->status], + task_status_str[status]); + task_impl->status = status; + + mpp_cond_signal(&next->cond); + mpp_task_dbg_func("signal port %p\n", next); + ret = MPP_OK; +RET: + mpp_task_dbg_func("caller %s leave port %p task %p ret %d\n", caller, port, task, ret); + mpp_mutex_unlock(&queue->lock); + + return ret; +} + +MPP_RET _mpp_port_dequeue(const char *caller, MppPort port, MppTask *task) +{ + MppPortImpl *port_impl = (MppPortImpl *)port; + MppTaskQueueImpl *queue = port_impl->queue; + MppTaskStatusInfo *curr = NULL; + MppTaskStatusInfo *next = NULL; + MppTaskImpl *task_impl = NULL; + MppTask p = NULL; + MPP_RET ret = MPP_NOK; + + mpp_mutex_lock(&queue->lock); + + mpp_task_dbg_func("caller %s enter port %p\n", caller, port); + + if (!queue->ready) { + mpp_err("try to dequeue when %s queue is not ready\n", + port_type_str[port_impl->type]); + goto RET; + } + + curr = &queue->info[port_impl->status_curr]; + next = &queue->info[port_impl->next_on_dequeue]; + + *task = NULL; + if (curr->count == 0) { + mpp_assert(list_empty(&curr->list)); + mpp_task_dbg_flow("mpp %p %s from %s dequeue %s port task %s -> %s failed\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type], + task_status_str[port_impl->status_curr], + task_status_str[port_impl->next_on_dequeue]); + goto RET; + } + + mpp_assert(!list_empty(&curr->list)); + task_impl = list_entry(curr->list.next, MppTaskImpl, list); + p = (MppTask)task_impl; + check_mpp_task_name(p); + list_del_init(&task_impl->list); + curr->count--; + mpp_assert(curr->count >= 0); + + list_add_tail(&task_impl->list, &next->list); + next->count++; + task_impl->status = next->status; + + mpp_task_dbg_flow("mpp %p %s from %s dequeue %s port task %p %s -> %s done\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type], task_impl, + task_status_str[port_impl->status_curr], + task_status_str[port_impl->next_on_dequeue]); + + *task = p; + ret = MPP_OK; +RET: + mpp_task_dbg_func("caller %s leave port %p task %p ret %d\n", caller, port, *task, ret); + mpp_mutex_unlock(&queue->lock); + + return ret; +} + +MPP_RET _mpp_port_enqueue(const char *caller, MppPort port, MppTask task) +{ + MppTaskImpl *task_impl = (MppTaskImpl *)task; + MppPortImpl *port_impl = (MppPortImpl *)port; + MppTaskQueueImpl *queue = port_impl->queue; + MppTaskStatusInfo *curr = NULL; + MppTaskStatusInfo *next = NULL; + MPP_RET ret = MPP_NOK; + + mpp_mutex_lock(&queue->lock); + + mpp_task_dbg_func("caller %s enter port %p task %p\n", caller, port, task); + + if (!queue->ready) { + mpp_err("try to enqueue when %s queue is not ready\n", + port_type_str[port_impl->type]); + mpp_mutex_unlock(&queue->lock); + goto RET; + } + + check_mpp_task_name(task); + + mpp_assert(task_impl->queue == (MppTaskQueue)queue); + mpp_assert(task_impl->status == port_impl->next_on_dequeue); + + curr = &queue->info[task_impl->status]; + next = &queue->info[port_impl->next_on_enqueue]; + + list_del_init(&task_impl->list); + curr->count--; + list_add_tail(&task_impl->list, &next->list); + next->count++; + task_impl->status = next->status; + + mpp_task_dbg_flow("mpp %p %s from %s enqueue %s port task %p %s -> %s done\n", + queue->mpp, queue->name, caller, + port_type_str[port_impl->type], task_impl, + task_status_str[port_impl->next_on_dequeue], + task_status_str[port_impl->next_on_enqueue]); + + mpp_cond_signal(&next->cond); + mpp_task_dbg_func("signal port %p\n", next); + ret = MPP_OK; +RET: + mpp_task_dbg_func("caller %s leave port %p task %p ret %d\n", caller, port, task, ret); + mpp_mutex_unlock(&queue->lock); + + return ret; +} + +MPP_RET _mpp_port_awake(const char *caller, MppPort port) +{ + if (port == NULL) + return MPP_NOK; + + mpp_task_dbg_func("caller %s enter port %p\n", caller, port); + MppPortImpl *port_impl = (MppPortImpl *)port; + MppTaskQueueImpl *queue = port_impl->queue; + MppTaskStatusInfo *curr = NULL; + if (queue) { + mpp_mutex_lock(&queue->lock); + curr = &queue->info[port_impl->status_curr]; + if (curr) { + mpp_cond_signal(&curr->cond); + } + mpp_mutex_unlock(&queue->lock); + } + + mpp_task_dbg_func("caller %s leave port %p\n", caller, port); + return MPP_OK; +} + +MPP_RET mpp_task_queue_init(MppTaskQueue *queue, void *mpp, const char *name) +{ + if (!queue) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_NOK; + MppTaskQueueImpl *p = NULL; + RK_S32 i; + + mpp_env_get_u32("mpp_task_debug", &mpp_task_debug, 0); + mpp_task_dbg_func("enter\n"); + + *queue = NULL; + + p = mpp_calloc(MppTaskQueueImpl, 1); + if (!p) { + mpp_err_f("malloc queue failed\n"); + goto RET; + } + + for (i = 0; i < MPP_TASK_STATUS_BUTT; i++) { + INIT_LIST_HEAD(&p->info[i].list); + p->info[i].count = 0; + p->info[i].status = (MppTaskStatus)i; + if (i == MPP_INPUT_PORT || i == MPP_OUTPUT_PORT) + mpp_cond_init(&p->info[i].cond); + } + + mpp_mutex_init(&p->lock); + + if (mpp_port_init(p, MPP_PORT_INPUT, &p->input)) + goto RET; + + if (mpp_port_init(p, MPP_PORT_OUTPUT, &p->output)) { + mpp_port_deinit(p->input); + goto RET; + } + + p->mpp = mpp; + if (name) + strncpy(p->name, name, sizeof(p->name) - 1); + else + strncpy(p->name, "none", sizeof(p->name) - 1); + + ret = MPP_OK; +RET: + if (ret) { + mpp_mutex_destroy(&p->lock); + mpp_cond_destroy(&p->info[MPP_INPUT_PORT].cond); + mpp_cond_destroy(&p->info[MPP_OUTPUT_PORT].cond); + MPP_FREE(p); + } + + *queue = p; + + mpp_task_dbg_func("leave ret %d queue %p\n", ret, p); + return ret; +} + +MPP_RET mpp_task_queue_setup(MppTaskQueue queue, RK_S32 task_count) +{ + MppTaskQueueImpl *impl = (MppTaskQueueImpl *)queue; + MppTaskStatusInfo *info; + MppTaskImpl *tasks; + RK_S32 i; + + mpp_mutex_lock(&impl->lock); + + // NOTE: queue can only be setup once + mpp_assert(impl->tasks == NULL); + mpp_assert(impl->task_count == 0); + tasks = mpp_calloc(MppTaskImpl, task_count); + if (!tasks) { + mpp_err_f("malloc tasks list failed\n"); + mpp_mutex_unlock(&impl->lock); + return MPP_ERR_MALLOC; + } + + impl->tasks = tasks; + impl->task_count = task_count; + + info = &impl->info[MPP_INPUT_PORT]; + + for (i = 0; i < task_count; i++) { + setup_mpp_task_name(&tasks[i]); + INIT_LIST_HEAD(&tasks[i].list); + tasks[i].index = i; + tasks[i].queue = queue; + tasks[i].status = MPP_INPUT_PORT; + mpp_meta_get(&tasks[i].meta); + + list_add_tail(&tasks[i].list, &info->list); + info->count++; + } + impl->ready = 1; + + mpp_mutex_unlock(&impl->lock); + + return MPP_OK; +} + +MPP_RET mpp_task_queue_deinit(MppTaskQueue queue) +{ + MppTaskQueueImpl *p = (MppTaskQueueImpl *)queue; + RK_S32 i; + + if (!p) { + mpp_err_f("found NULL input queue\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_lock(&p->lock); + + p->ready = 0; + mpp_cond_signal(&p->info[MPP_INPUT_PORT].cond); + mpp_cond_signal(&p->info[MPP_OUTPUT_PORT].cond); + + if (p->tasks) { + for (i = 0; i < p->task_count; i++) { + MppMeta meta = p->tasks[i].meta; + + /* we must ensure that all task return to init status */ + if (mpp_meta_size(meta)) { + mpp_err_f("%s queue idx %d task %p status %d meta size %d\n", + p->name, i, &p->tasks[i], p->tasks[i].status, + mpp_meta_size(meta)); + mpp_meta_dump(meta); + } + mpp_meta_put(p->tasks[i].meta); + } + mpp_free(p->tasks); + } + + if (p->input) { + mpp_port_deinit(p->input); + p->input = NULL; + } + if (p->output) { + mpp_port_deinit(p->output); + p->output = NULL; + } + mpp_mutex_unlock(&p->lock); + mpp_mutex_destroy(&p->lock); + + mpp_cond_destroy(&p->info[MPP_INPUT_PORT].cond); + mpp_cond_destroy(&p->info[MPP_OUTPUT_PORT].cond); + + mpp_free(p); + return MPP_OK; +} + +MppPort mpp_task_queue_get_port(MppTaskQueue queue, MppPortType type) +{ + if (!queue || type >= MPP_PORT_BUTT) { + mpp_err_f("invalid input queue %p type %d\n", queue, type); + return NULL; + } + + MppTaskQueueImpl *impl = (MppTaskQueueImpl *)queue; + return (type == MPP_PORT_INPUT) ? (impl->input) : (impl->output); +} + +MppMeta mpp_task_get_meta(MppTask task) +{ + MppMeta meta = NULL; + + if (task) + meta = ((MppTaskImpl *)task)->meta; + + return meta; +} diff --git a/mpp/base/mpp_trie.c b/mpp/base/mpp_trie.c new file mode 100644 index 000000000..9435bcf8a --- /dev/null +++ b/mpp/base/mpp_trie.c @@ -0,0 +1,939 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_trie" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_trie.h" + +#define MPP_TRIE_DBG_PAVE (0x00000001) +#define MPP_TRIE_DBG_SET (0x00000002) +#define MPP_TRIE_DBG_GET (0x00000004) +#define MPP_TRIE_DBG_CNT (0x00000008) +#define MPP_TRIE_DBG_WALK (0x00000010) +#define MPP_TRIE_DBG_LAST (0x00000020) +#define MPP_TRIE_DBG_LAST_STEP (0x00000040) +#define MPP_TRIE_DBG_LAST_CHECK (0x00000080) +#define MPP_TRIE_DBG_IMPORT (0x00000100) + +#define trie_dbg(flag, fmt, ...) mpp_dbg_f(mpp_trie_debug, flag, fmt, ## __VA_ARGS__) +#define trie_dbg_pave(fmt, ...) trie_dbg(MPP_TRIE_DBG_PAVE, fmt, ## __VA_ARGS__) +#define trie_dbg_set(fmt, ...) trie_dbg(MPP_TRIE_DBG_SET, fmt, ## __VA_ARGS__) +#define trie_dbg_get(fmt, ...) trie_dbg(MPP_TRIE_DBG_GET, fmt, ## __VA_ARGS__) +#define trie_dbg_cnt(fmt, ...) trie_dbg(MPP_TRIE_DBG_CNT, fmt, ## __VA_ARGS__) +#define trie_dbg_walk(fmt, ...) trie_dbg(MPP_TRIE_DBG_WALK, fmt, ## __VA_ARGS__) +#define trie_dbg_last(fmt, ...) trie_dbg(MPP_TRIE_DBG_LAST, fmt, ## __VA_ARGS__) + +#define MPP_TRIE_KEY_LEN (4) +#define MPP_TRIE_KEY_MAX (1 << (MPP_TRIE_KEY_LEN)) +#define MPP_TRIE_INFO_MAX (1 << 12) +#define MPP_TRIE_NAME_MAX (1 << 12) + +#define DEFAULT_NODE_COUNT 900 +#define DEFAULT_INFO_COUNT 80 +#define INVALID_NODE_ID (-1) +#define MPP_TRIE_TAG_LEN_MAX ((sizeof(rk_u64) * 8) / MPP_TRIE_KEY_LEN) + +/* spatial optimized trie tree */ +typedef struct MppTrieNode_t { + /* next - next trie node index */ + rk_s16 next[MPP_TRIE_KEY_MAX]; + /* id - payload data offset of current trie node */ + rk_s32 id; + /* idx - trie node index in ascending order */ + rk_s16 idx; + /* prev - previous trie node index */ + rk_s16 prev; + + /* tag_val - prefix tag */ + rk_u64 tag_val; + /* key - current key value in previous node as next */ + rk_u16 key; + /* + * tag len - prefix tag length + * zero - normal node with 16 next node + * positive - tag node with 64bit prefix tag + */ + rk_s16 tag_len; + + /* next_cnt - valid next node count */ + rk_u16 next_cnt; +} MppTrieNode; + +typedef struct MppTrieImpl_t { + char *name; + rk_s32 name_len; + rk_s32 buf_size; + + rk_s32 node_count; + rk_s32 node_used; + MppTrieNode *nodes; + + /* info and name record buffer */ + void *info_buf; + rk_s32 info_count; + rk_s32 info_buf_size; + rk_s32 info_buf_pos; + rk_s32 info_name_max; +} MppTrieImpl; + +/* work structure for trie traversal */ +typedef struct MppTrieWalk_t { + MppTrieNode *root; + rk_u64 tag; + rk_u32 len; + rk_s32 match; +} MppTrieWalk; + +rk_u32 mpp_trie_debug = 0; + +static rk_s32 trie_get_node(MppTrieImpl *trie, rk_s32 prev, rk_u64 key) +{ + MppTrieNode *node; + rk_s32 idx; + + if (trie->node_used >= trie->node_count) { + rk_s32 old_count = trie->node_count; + rk_s32 new_count = old_count * 2; + MppTrieNode *new_nodes = mpp_realloc(trie->nodes, MppTrieNode, new_count); + + if (!new_nodes) { + mpp_err_f("failed to realloc new nodes %d\n", new_count); + return -1; + } + + /* NOTE: new memory should be memset to zero */ + memset(new_nodes + old_count, 0, sizeof(*new_nodes) * old_count); + + trie_dbg_cnt("trie %p enlarge node %p:%d -> %p:%d\n", + trie, trie->nodes, trie->node_count, new_nodes, new_count); + + trie->nodes = new_nodes; + trie->node_count = new_count; + } + + idx = trie->node_used++; + node = &trie->nodes[idx]; + node->idx = idx; + node->prev = (prev > 0) ? prev : 0; + node->key = key; + node->id = INVALID_NODE_ID; + + if (prev >= 0) + trie->nodes[prev].next_cnt++; + + trie_dbg_cnt("get node %d\n", idx); + + return idx; +} + +static rk_s32 trie_prepare_buf(MppTrieImpl *p, rk_s32 info_size) +{ + if (p->info_count >= MPP_TRIE_INFO_MAX) { + mpp_loge_f("invalid trie info count %d larger than max %d\n", + p->info_count, MPP_TRIE_INFO_MAX); + return rk_nok; + } + + /* check and enlarge info buffer */ + if (p->info_buf_pos + info_size > p->info_buf_size) { + rk_s32 old_size = p->info_buf_size; + rk_s32 new_size = old_size * 2; + void *ptr = mpp_realloc(p->info_buf, void, new_size); + + if (!ptr) { + mpp_loge_f("failed to realloc new info buffer %d\n", new_size); + return rk_nok; + } + + trie_dbg_cnt("trie %p enlarge info_buf %p:%d -> %p:%d\n", + p, p->info_buf, old_size, ptr, new_size); + + p->info_buf = ptr; + p->info_buf_size = new_size; + } + + return rk_ok; +} + +static rk_s32 trie_pave_node(MppTrieImpl *p, const char *name, rk_s32 str_len) +{ + MppTrieNode *node = NULL; + const char *s = name; + rk_s32 next = 0; + rk_s32 idx = 0; + rk_s32 i; + + trie_dbg_pave("trie %p add info %s len %d\n", p, s, str_len); + + for (i = 0; i < str_len && s[i]; i++) { + rk_u32 key = s[i]; + rk_s32 key0 = (key >> 4) & 0xf; + rk_s32 key1 = (key >> 0) & 0xf; + + node = p->nodes + idx; + next = node->next[key0]; + + trie_dbg_pave("trie %p add %s at %2d char %c:%3d:%x:%x node %d -> %d\n", + p, name, i, key, key, key0, key1, idx, next); + + if (!next) { + next = trie_get_node(p, idx, key0); + if (next < 0) + return next; + + /* realloc may cause memory address change */ + node = p->nodes + idx; + node->next[key0] = next; + + trie_dbg_pave("trie %p add %s at %2d char %c:%3d node %d -> %d as new key0\n", + p, name, i, key, key, node->idx, next); + } + + idx = next; + node = p->nodes + idx; + next = node->next[key1]; + + trie_dbg_pave("trie %p add %s at %2d char %c:%3d:%x:%x node %d -> %d as key0\n", + p, s, i, key, key, key0, key1, idx, next); + + if (!next) { + next = trie_get_node(p, idx, key1); + if (next < 0) + return next; + + /* realloc may cause memory address change */ + node = p->nodes + idx; + node->next[key1] = next; + + trie_dbg_pave("trie %p add %s at %2d char %c:%3d node %d -> %d as new child\n", + p, name, i, key, key, node->idx, next); + } + + idx = next; + + trie_dbg_pave("trie %p add %s at %2d char %c:%3d:%x:%x node %d -> %d as key1\n", + p, name, i, key, key, key0, key1, idx, next); + } + + return idx; +} + +rk_s32 mpp_trie_init(MppTrie *trie, const char *name) +{ + MppTrieImpl *p; + rk_s32 name_len; + rk_s32 ret = rk_nok; + + if (!trie || !name) { + mpp_loge_f("invalid trie %p name %p\n", trie, name); + return ret; + } + + mpp_env_get_u32("mpp_trie_debug", &mpp_trie_debug, 0); + + name_len = strnlen(name, MPP_TRIE_NAME_MAX) + 1; + p = mpp_calloc_size(MppTrieImpl, sizeof(*p) + name_len); + if (!p) { + mpp_loge_f("create trie impl %s failed\n", name); + goto done; + } + + p->name = (char *)(p + 1); + p->name_len = name_len; + strncpy(p->name, name, name_len); + + p->node_count = DEFAULT_NODE_COUNT; + p->nodes = mpp_calloc(MppTrieNode, p->node_count); + if (!p->nodes) { + mpp_loge_f("create %d nodes failed\n", p->node_count); + goto done; + } + + p->info_buf_size = 4096; + p->info_buf = mpp_calloc(void, p->info_buf_size); + if (!p->info_buf) { + mpp_loge_f("failed to alloc %d info buffer\n", p->info_buf_size); + goto done; + } + + /* get node 0 as root node*/ + trie_get_node(p, -1, 0); + + ret = rk_ok; + +done: + if (ret && p) { + MPP_FREE(p->info_buf); + MPP_FREE(p->nodes); + MPP_FREE(p); + } + + *trie = p; + return ret; +} + +rk_s32 mpp_trie_init_by_root(MppTrie *trie, void *root) +{ + MppTrieImpl *p; + MppTrieInfo *info; + rk_s32 i; + + if (!trie || !root) { + mpp_loge_f("invalid trie %p root %p\n", trie, root); + return rk_nok; + } + + *trie = NULL; + p = mpp_calloc(MppTrieImpl, 1); + if (!p) { + mpp_loge_f("create trie impl failed\n"); + return rk_nok; + } + + info = mpp_trie_get_info_from_root(root, "__name__"); + if (info) + p->name = mpp_trie_info_ctx(info); + + info = mpp_trie_get_info_from_root(root, "__node__"); + if (info) + p->node_used = *(rk_u32 *)mpp_trie_info_ctx(info); + + info = mpp_trie_get_info_from_root(root, "__info__"); + if (info) + p->info_count = *(rk_u32 *)mpp_trie_info_ctx(info); + + /* import and update new buffer */ + p->nodes = (MppTrieNode *)root; + + if (mpp_trie_debug & MPP_TRIE_DBG_IMPORT) + mpp_trie_dump(p, "root import"); + + info = mpp_trie_get_info_first(p); + + for (i = 0; i < p->info_count; i++) { + const char *name = mpp_trie_info_name(info); + MppTrieInfo *info_set = info; + MppTrieInfo *info_ret = mpp_trie_get_info(p, name); + + info = mpp_trie_get_info_next(p, info); + + if (info_ret && info_set == info_ret && info_ret->index == i) + continue; + + mpp_loge_f("trie check on import found mismatch info %s [%d:%p] - [%d:%p]\n", + name, i, info_set, info_ret ? info_ret->index : -1, info_ret); + return rk_nok; + } + + *trie = p; + + return rk_ok; +} + +rk_s32 mpp_trie_deinit(MppTrie trie) +{ + if (trie) { + MppTrieImpl *p = (MppTrieImpl *)trie; + + /* NOTE: do not remvoe imported root */ + if (p->node_count) + mpp_free(p->nodes); + else + p->nodes = NULL; + + MPP_FREE(p->info_buf); + MPP_FREE(p); + return rk_ok; + } + + return rk_nok; +} + +static rk_s32 mpp_trie_walk(MppTrieWalk *p, rk_s32 idx, rk_u32 key, rk_u32 keyx, rk_u32 end) +{ + MppTrieNode *node = &p->root[idx]; + char log_buf[128]; + rk_u32 log_size = sizeof(log_buf) - 1; + rk_u32 log_len = 0; + rk_u32 log_en = ((mpp_trie_debug & MPP_TRIE_DBG_WALK) != 0) ? 1 : 0; + rk_s32 next = -1; + + if (log_en) + log_len += snprintf(log_buf + log_len, log_size - log_len, + "node %d:%d key %02x:%x -> ", + node->idx, node->id, key, keyx); + + /* check high 4 bits */ + if (!node->tag_len || p->match == node->idx) { + /* not tag or tag has be matched -> normal next switch node */ + next = node->next[keyx]; + if (log_en) + log_len += snprintf(log_buf + log_len, log_size - log_len, + "tag %s -> ", + (node->tag_len == 0) ? "n/a" : "match"); + p->tag = 0; + p->len = 0; + p->match = -1; + } else { + /* with tag check len to fill or to stop */ + rk_u64 val_new = (p->tag << 4) | keyx; + rk_s32 len_new = p->len + 1; + + if (log_en) + log_len += snprintf(log_buf + log_len, log_size - log_len, + "tag %0*llx:%d - st %0*llx:%d -> ", + node->tag_len, node->tag_val, node->tag_len, + node->tag_len, val_new, len_new); + + /* clear old matched node */ + p->match = -1; + if (node->tag_len > len_new && !end) { + /* more tag to fill keep current node */ + p->tag = val_new; + p->len = len_new; + next = node->idx; + if (log_en) + log_len += snprintf(log_buf + log_len, log_size - log_len, + "fill -> "); + } else { + /* check tag match with new value */ + p->tag = 0; + p->len = 0; + + if (node->tag_val != val_new) { + if (log_en) + log_len += snprintf(log_buf + log_len, log_size - log_len, + "mismatch -> "); + next = INVALID_NODE_ID; + } else { + if (log_en) + log_len += snprintf(log_buf + log_len, log_size - log_len, + "match -> "); + next = node->idx; + p->match = node->idx; + } + } + } + + if (log_en) { + snprintf(log_buf + log_len, log_size - log_len, "%d", next); + mpp_logi_f("%s\n", log_buf); + } + + return next; +} + +static MppTrieNode *mpp_trie_get_node(MppTrieNode *root, const char *name) +{ + MppTrieNode *ret = NULL; + const char *s = name; + MppTrieWalk walk; + rk_s32 idx = 0; + + if (!root || !name) { + mpp_err_f("invalid root %p name %p\n", root, name); + return NULL; + } + + trie_dbg_get("root %p search %s start\n", root, name); + + walk.root = root; + walk.tag = 0; + walk.len = 0; + walk.match = 0; + + do { + char key = *s++; + rk_u32 key0 = (key >> 4) & 0xf; + rk_u32 key1 = key & 0xf; + rk_u32 end = s[0] == '\0'; + + idx = mpp_trie_walk(&walk, idx, key, key0, 0); + if (idx < 0) + break; + + idx = mpp_trie_walk(&walk, idx, key, key1, end); + if (idx < 0 || end) + break; + } while (1); + + ret = (idx >= 0) ? &root[idx] : NULL; + + trie_dbg_get("get %s ret node %d:%d\n", name, idx, ret ? ret->id : INVALID_NODE_ID); + + return ret; +} + +static rk_s32 mpp_trie_check(MppTrie trie, const char *log) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + char *base = p->info_buf; + rk_s32 info_size = 0; + rk_s32 pos = 0; + rk_s32 i; + + for (i = 0; i < p->info_count; i++, pos += info_size) { + MppTrieInfo *info = (MppTrieInfo *)(base + pos); + const char *name = (const char *)(info + 1); + MppTrieNode *node = mpp_trie_get_node(p->nodes, name); + + info_size = sizeof(*info) + info->str_len + info->ctx_len; + + if (node && node->id >= 0 && node->id == pos) + continue; + + mpp_loge("trie check on %s found mismatch info %s %d - %d\n", + log, name, i, node ? node->id : -1); + return rk_nok; + } + + return rk_ok; +} + +rk_s32 mpp_trie_last_info(MppTrie trie) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + MppTrieNode *root; + MppTrieNode *node; + char *buf; + rk_s32 node_count; + rk_s32 node_valid; + rk_s32 nodes_size; + rk_s32 len = 0; + rk_s32 pos = 0; + rk_s32 i; + rk_s32 j; + + if (!trie) { + mpp_loge_f("invalid NULL trie\n"); + return rk_nok; + } + + /* write trie self entry info */ + pos = p->info_count + 3; + mpp_trie_add_info(trie, "__name__", p->name, p->name_len); + mpp_trie_add_info(trie, "__info__", &pos, sizeof(pos)); + /* NOTE: node count need to be update after shrinking */ + mpp_trie_add_info(trie, "__node__", &p->node_used, sizeof(p->node_used)); + + root = p->nodes; + node_count = p->node_used; + node_valid = node_count; + + trie_dbg_last("shrink trie node start node %d info %d\n", node_count, p->info_count); + + if (mpp_trie_debug & MPP_TRIE_DBG_LAST_STEP) + mpp_trie_dump_f(trie); + + for (i = node_count - 1; i > 0; i--) { + MppTrieNode *prev; + rk_s32 prev_idx; + + node = &root[i]; + prev_idx = node->prev; + prev = &root[prev_idx]; + + if (prev->next_cnt > 1) { + trie_dbg_last("node %d:%d prev %d next count %d stop shrinking for multi next\n", + i, node->id, prev_idx, prev->next_cnt); + continue; + } + + if (node->tag_len >= (rk_s16)MPP_TRIE_TAG_LEN_MAX) { + trie_dbg_last("node %d:%d tag %d - %016llx stop shrinking for max tag len\n", + i, node->id, node->tag_len, node->tag_val); + continue; + } + + if (prev->id >= 0) { + trie_dbg_last("node %d:%d tag %d - %016llx stop shrinking for valid info node\n", + i, node->id, node->tag_len, node->tag_val); + continue; + } + + prev->id = node->id; + /* NOTE: do NOT increase tag length on root node */ + prev->tag_len = node->tag_len + 1; + prev->tag_val = ((rk_u64)node->key << (node->tag_len * 4)) | node->tag_val; + prev->next_cnt = node->next_cnt; + memcpy(prev->next, node->next, sizeof(node->next)); + + trie_dbg_last("node %d:%d shrink prev %d key %x tag %016llx -> %016llx\n", + i, node->id, prev->idx, prev->key, node->tag_val, prev->tag_val); + + for (j = 0; j < MPP_TRIE_KEY_MAX; j++) { + if (!prev->next[j]) + continue; + + root[prev->next[j]].prev = prev_idx; + } + + memset(node, 0, sizeof(*node)); + node->id = INVALID_NODE_ID; + node_valid--; + } + + trie_dbg_last("shrink trie node finish count %d -> %d\n", node_count, node_valid); + + if (mpp_trie_debug & MPP_TRIE_DBG_LAST_STEP) + mpp_trie_dump_f(trie); + + if (mpp_trie_debug & MPP_TRIE_DBG_LAST_CHECK) + mpp_trie_check(trie, "shrink merge tag stage"); + + trie_dbg_last("move trie node start to reduce memory %d -> %d\n", node_count, node_valid); + + for (i = 1; i < node_valid; i++) { + node = &root[i]; + + /* skip valid node */ + if (node->idx) + continue; + + for (j = i; j < node_count; j++) { + MppTrieNode *tmp = &root[j]; + MppTrieNode *prev; + rk_s32 k; + + /* skip empty node */ + if (!tmp->idx) + continue; + + trie_dbg_last("move node %d to %d prev %d\n", j, i, tmp->prev); + + prev = &root[tmp->prev]; + + /* relink previous node */ + for (k = 0; k < MPP_TRIE_KEY_MAX; k++) { + if (prev->next[k] != tmp->idx) + continue; + + prev->next[k] = i; + break; + } + + memcpy(node, tmp, sizeof(*node)); + node->idx = i; + memset(tmp, 0, sizeof(*tmp)); + + /* relink next node */ + for (k = 0; k < MPP_TRIE_KEY_MAX; k++) { + if (!node->next[k]) + continue; + + root[node->next[k]].prev = i; + } + + break; + } + } + + p->node_used = node_valid; + + trie_dbg_last("move trie node finish used %d\n", p->node_used); + + if (mpp_trie_debug & MPP_TRIE_DBG_LAST_STEP) + mpp_trie_dump_f(trie); + + if (mpp_trie_debug & MPP_TRIE_DBG_LAST_CHECK) + mpp_trie_check(trie, "shrink move node stage"); + + trie_dbg_last("create user buffer start\n"); + + nodes_size = sizeof(MppTrieNode) * p->node_used; + p->buf_size = nodes_size + p->info_buf_pos; + p->buf_size = MPP_ALIGN(p->buf_size, sizeof(void *)); + + buf = mpp_calloc(char, p->buf_size); + if (!buf) { + mpp_loge("failed to alloc trie buffer size %d\n", p->buf_size); + return rk_nok; + } + + p->nodes = (MppTrieNode *)buf; + memcpy(p->nodes, root, nodes_size); + pos = nodes_size; + len = 0; + + for (i = 0; i < p->info_count; i++) { + MppTrieInfo *src = (MppTrieInfo *)(p->info_buf + len); + MppTrieInfo *dst = (MppTrieInfo *)(buf + pos); + rk_s32 info_size = sizeof(MppTrieInfo) + src->str_len + src->ctx_len; + const char *name = (char *)(src + 1); + + node = mpp_trie_get_node(p->nodes, name); + node->id = pos; + + memcpy(dst, src, info_size); + pos += info_size; + len += info_size; + } + + MPP_FREE(root); + MPP_FREE(p->info_buf); + + /* NOTE: udpate final shrinked node count */ + { + MppTrieInfo *info = mpp_trie_get_info_from_root(p->nodes, "__node__"); + + if (info) + *(rk_u32 *)mpp_trie_info_ctx(info) = p->node_used; + } + + return rk_ok; +} + +rk_s32 mpp_trie_add_info(MppTrie trie, const char *name, void *ctx, rk_u32 ctx_len) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + rk_s32 info_size; + rk_u32 ctx_real; + rk_s32 str_real; + rk_s32 str_len; + rk_s32 idx; + + if (!p) { + mpp_loge_f("invalid trie %p name %s ctx %p\n", p, name, ctx); + return rk_nok; + } + + if (!name) + return mpp_trie_last_info(p); + + str_real = strnlen(name, MPP_TRIE_NAME_MAX) + 1; + str_len = MPP_ALIGN(str_real, 4); + /* NOTE: align all ctx_len to four bytes */ + ctx_real = ctx_len; + ctx_len = MPP_ALIGN(ctx_real, 4); + info_size = sizeof(MppTrieInfo) + str_len + ctx_len; + + if (str_len >= MPP_TRIE_NAME_MAX) { + mpp_loge_f("invalid trie name %s len %d larger than max %d\n", + name, str_len, MPP_TRIE_NAME_MAX); + return rk_nok; + } + + if (trie_prepare_buf(p, info_size)) + return rk_nok; + + idx = trie_pave_node(p, name, str_real); + if (idx < 0) { + mpp_loge_f("trie %p pave node %s failed\n", p, name); + return rk_nok; + } + if (p->nodes[idx].id != -1) { + mpp_loge_f("trie %p add info %s already exist\n", p, name); + return rk_nok; + } + + p->nodes[idx].id = p->info_buf_pos; + if (p->info_name_max < str_real - 1) + p->info_name_max = str_real - 1; + + { + MppTrieInfo *info = (MppTrieInfo *)(p->info_buf + p->info_buf_pos); + char *buf = (char *)(info + 1); + + info->index = p->info_count; + info->ctx_len = ctx_len; + info->str_len = str_len; + + memcpy(buf, name, str_real); + while (str_real < str_len) + buf[str_real++] = 0; + + buf += str_len; + + memcpy(buf, ctx, ctx_real); + while (ctx_real < ctx_len) + buf[ctx_real++] = 0; + } + + trie_dbg_set("trie %p add info %d - %s at node %d pos %d ctx %p size %d\n", + p, p->info_count, name, idx, p->info_buf_pos, ctx, ctx_len); + + p->info_buf_pos += info_size; + p->info_count++; + + return rk_ok; +} + +rk_s32 mpp_trie_get_node_count(MppTrie trie) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + + return (p) ? p->node_used : 0; +} + +rk_s32 mpp_trie_get_info_count(MppTrie trie) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + + return (p) ? p->info_count : 0; +} + +rk_s32 mpp_trie_get_buf_size(MppTrie trie) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + + return (p) ? p->buf_size : 0; +} + +rk_s32 mpp_trie_get_name_max(MppTrie trie) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + + return (p) ? p->info_name_max : 0; +} + +void *mpp_trie_get_node_root(MppTrie trie) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + + return (p) ? p->nodes : NULL; +} + +MppTrieInfo *mpp_trie_get_info(MppTrie trie, const char *name) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + MppTrieNode *node; + + if (!trie || !name) { + mpp_err_f("invalid trie %p name %p\n", trie, name); + return NULL; + } + + node = mpp_trie_get_node(p->nodes, name); + if (!node || node->id < 0) + return NULL; + + return (MppTrieInfo *)(((char *)p->nodes) + node->id); +} + +MppTrieInfo *mpp_trie_get_info_first(MppTrie trie) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + + return (p) ? (MppTrieInfo *)(((char *)p->nodes) + p->node_used * sizeof(MppTrieNode)) : NULL; +} + +MppTrieInfo *mpp_trie_get_info_next(MppTrie trie, MppTrieInfo *info) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + + if (!p || !info || info->index >= p->info_count - 1) + return NULL; + + return (MppTrieInfo *)((char *)(info + 1) + info->str_len + info->ctx_len); +} + +MppTrieInfo *mpp_trie_get_info_from_root(void *root, const char *name) +{ + MppTrieNode *node; + + if (!root || !name) { + mpp_loge_f("invalid root %p name %p\n", root, name); + return NULL; + } + + mpp_env_get_u32("mpp_trie_debug", &mpp_trie_debug, 0); + + node = mpp_trie_get_node((MppTrieNode *)root, name); + if (!node || node->id < 0) + return NULL; + + return (MppTrieInfo *)(((char *)root) + node->id); +} + +void mpp_trie_dump(MppTrie trie, const char *func) +{ + MppTrieImpl *p = (MppTrieImpl *)trie; + char *base = p->info_buf ? (char *)p->info_buf : (char *)p->nodes; + rk_s32 i; + rk_s32 next_cnt[17]; + rk_s32 tag_len[17]; + + memset(next_cnt, 0, sizeof(next_cnt)); + memset(tag_len, 0, sizeof(tag_len)); + + mpp_logi("%s dumping trie %p\n", func, trie); + mpp_logi("name %s size %d node %d info %d\n", + p->name, p->buf_size, p->node_used, p->info_count); + + for (i = 0; i < p->node_used; i++) { + MppTrieNode *node = &p->nodes[i]; + rk_s32 valid_count = 0; + rk_s32 j; + + if (i && !node->idx) + continue; + + if (node->id >= 0) { + MppTrieInfo *info = (MppTrieInfo *)((char *)base + node->id); + + /* check before and after last info */ + if (node->id < (rk_s32)(p->node_used * sizeof(MppTrieNode))) + mpp_logi("node %d key %x info %d - %s\n", node->idx, node->key, node->id, + mpp_trie_info_name(info)); + else + mpp_logi("node %d key %x info %d - %s\n", node->idx, node->key, node->id, + mpp_trie_info_name(info)); + } else + mpp_logi("node %d key %x\n", node->idx, node->key); + + if (node->tag_len) + mpp_logi(" prev %d count %d tag %d - %llx\n", node->prev, node->next_cnt, node->tag_len, node->tag_val); + else + mpp_logi(" prev %d count %d\n", node->prev, node->next_cnt); + + for (j = 0; j < MPP_TRIE_KEY_MAX; j++) { + if (node->next[j] > 0) { + mpp_logi(" next %d:%d -> %d\n", valid_count, j, node->next[j]); + valid_count++; + } + } + + next_cnt[valid_count]++; + tag_len[node->tag_len]++; + } + + mpp_logi("node | next | tag | used %d\n", p->node_used); + + for (i = 0; i < 17; i++) { + if (next_cnt[i] || tag_len[i]) + mpp_logi("%2d | %4d | %4d |\n", i, next_cnt[i], tag_len[i]); + } + + mpp_logi("%s dumping node end\n", func, p->node_used); +} + +void mpp_trie_timing_test(MppTrie trie) +{ + MppTrieInfo *root = mpp_trie_get_info_first(trie); + MppTrieInfo *info = root; + rk_s64 sum = 0; + rk_s32 loop = 0; + + do { + rk_s64 start, end; + + start = mpp_time(); + mpp_trie_get_info(trie, mpp_trie_info_name(info)); + end = mpp_time(); + + info = mpp_trie_get_info_next(trie, info); + sum += end - start; + loop++; + } while (info); + + mpp_logi("trie access %d info %lld us averga %lld us\n", + loop, sum, sum / loop); +} diff --git a/mpp/base/test/CMakeLists.txt b/mpp/base/test/CMakeLists.txt new file mode 100644 index 000000000..6ca6965de --- /dev/null +++ b/mpp/base/test/CMakeLists.txt @@ -0,0 +1,62 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# mpp/base built-in unit test case +# ---------------------------------------------------------------------------- +# macro for adding osal sub-module unit test +macro(add_mpp_base_test module) + set(test_name ${module}_test) + string(TOUPPER ${test_name} test_tag) + #message(STATUS "moduule : ${module}") + #message(STATUS "test_name : ${test_name}") + #message(STATUS "test_tag : ${test_tag}") + + option(${test_tag} "Build base ${module} unit test" ${BUILD_TEST}) + if(${test_tag}) + add_executable(${test_name} ${test_name}.c) + target_link_libraries(${test_name} ${MPP_SHARED}) + set_target_properties(${test_name} PROPERTIES FOLDER "osal/test") + add_test(NAME ${test_name} COMMAND ${test_name}) + endif() +endmacro() + +# task system unit test +add_mpp_base_test(mpp_task) + +# mpp_buffer unit test +add_mpp_base_test(mpp_buffer) + +# mpp_packet unit test +add_mpp_base_test(mpp_packet) + +# mpp_meta unit test +add_mpp_base_test(mpp_meta) + +# mpp_bitwriter unit test +add_mpp_base_test(mpp_bit) + +# mpp_bitread unit test +add_mpp_base_test(mpp_bit_read) + +# mpp_trie unit test +add_mpp_base_test(mpp_trie) + +# mpp_cluster unit test +add_mpp_base_test(mpp_cluster) + +# mpp_enc_cfg unit test +add_mpp_base_test(mpp_enc_cfg) + +# mpp_enc_ref unit test +add_mpp_base_test(mpp_enc_ref) + +# mpp_dec_cfg unit test +add_mpp_base_test(mpp_dec_cfg) + +# mpp_sys_cfg unit test +add_mpp_base_test(mpp_sys_cfg) + +# mpp_sys_cfgi unit test +add_mpp_base_test(mpp_sys_cfg_st) + +# mpp_cfg_io unit test +add_mpp_base_test(mpp_cfg) diff --git a/mpp/base/test/mpp_bit_read_test.c b/mpp/base/test/mpp_bit_read_test.c new file mode 100644 index 000000000..ca4a4fb8d --- /dev/null +++ b/mpp/base/test/mpp_bit_read_test.c @@ -0,0 +1,388 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_bit_read_test" + +#include +#include + +#include "mpp_log.h" +#include "mpp_common.h" +#include "mpp_bitread.h" + +#define BIT_READ_BUFFER_SIZE (1024) + +typedef enum BitReadOpsType_e { + BIT_GET, + BIT_GET_UE, + BIT_GET_SE, + BIT_SKIP, +} BitOpsType; + +static RK_U8 bitOpsStr[][10] = { + "read_bit", + "read_ue", + "read_se", + "skip_bit" +}; + +typedef struct BitOps_t { + BitOpsType type; + RK_S32 len; + RK_S32 val; + char syntax[50]; +} BitOps; + +// AVS2 I-frame data containing "00 00 02" +static RK_U8 test_data_1[] = { + 0x00, 0x00, 0x01, 0xB3, 0x00, 0x00, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0x02, 0x04, 0x40, 0xCA, 0xB3, + 0xD2, 0x2B, 0x33, 0x4C, 0x91, 0x88, 0xAC, 0xCD, + 0x14, 0xD8, 0xA1, 0x86, 0x14, 0x30, 0x8A, 0x58, + 0xE1, 0x46, 0x8C, 0x1D, 0x80, 0x00, 0x00, 0x01 +}; + +static BitOps bit_ops_1 [] = { + {BIT_SKIP, 32, 0, "Skip start code of I Pic"}, + {BIT_GET, 32, 65535, "bbv_delay"}, + {BIT_GET, 1, 1, "time_code_flag"}, + {BIT_GET, 24, 0, "time_code"}, + {BIT_GET, 8, 0, "coding_order"}, + {BIT_GET_UE, 0, 3, "picture_output_delay"}, + {BIT_GET, 1, 0, "use RCS in SPS"}, + {BIT_GET, 1, 1, "refered by others"}, + {BIT_GET, 3, 0, "number of reference picture"}, + {BIT_GET, 3, 0, "number of removed picture"}, + {BIT_GET, 1, 1, "marker bit"}, + {BIT_GET, 1, 1, "progressive_frame"}, + {BIT_GET, 1, 0, "top_field_first"}, + {BIT_GET, 1, 0, "repeat_first_field"}, + {BIT_GET, 1, 1, "fixed_picture_qp"}, + {BIT_GET, 7, 43, "picture_qp"}, + {BIT_GET, 1, 0, "loop_filter_disable"}, + {BIT_GET, 1, 0, "loop_filter_parameter_flag"}, + {BIT_GET, 1, 1, "chroma_quant_param_disable"} +}; + +// AVS2 Sequence header data without "00 00 02" +static RK_U8 test_data_2[] = { + 0x00, 0x00, 0x01, 0xB0, 0x20, 0x42, 0x81, 0xA0, + 0x03, 0xC1, 0x23, 0x0F, 0x42, 0x44, 0x00, 0x10, + 0x00, 0x01, 0x9F, 0xFE, 0x46, 0x10, 0x18, 0xE8, + 0x0D, 0x02, 0x4B, 0x10, 0xA4, 0x74, 0x09, 0x44, + 0x99, 0x02, 0x58, 0x90, 0x61, 0x0D, 0x0A, 0x20, + 0x90, 0x22, 0x91, 0x24, 0x38, 0x42, 0x39, 0x00, + 0x00, 0x01, 0xB5, 0x23, 0x0F, 0x01, 0x14, 0x99 +}; + +static BitOps bit_ops_2 [] = { + {BIT_SKIP, 32, 0, "Skip start code of Seq header"}, + {BIT_GET, 8, 32, "profile_id"}, + {BIT_GET, 8, 66, "level_id"}, + {BIT_GET, 1, 1, "progressive_sequence"}, + {BIT_GET, 1, 0, "field_coded_sequence"}, + {BIT_GET, 14, 416, "horizontal_size"}, + {BIT_GET, 14, 240, "vertical_size"}, + {BIT_GET, 2, 1, "chroma_format"}, + {BIT_GET, 3, 1, "sample_precision"}, + {BIT_GET, 4, 1, "aspect_ratio"}, + {BIT_GET, 4, 8, "frame_rate_code"}, + {BIT_GET, 18, 125000, "bit_rate_lower_18"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 12, 0, "bit_rate_upper_12"}, + {BIT_GET, 1, 0, "low_delay"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 0, "enable_temporal_id"}, + {BIT_GET, 18, 0, "bbv_uffer_size"}, + {BIT_GET, 3, 6, "lcu_size"}, + {BIT_GET, 1, 0, "enable_weighted_quant"}, + // weighted quant matrix + {BIT_GET, 1, 1, "disable_background_picture"}, + {BIT_GET, 1, 1, "enable_mhp_skip"}, + {BIT_GET, 1, 1, "enable_dhp"}, + {BIT_GET, 1, 1, "enable_wsm"}, + {BIT_GET, 1, 1, "enable_amp"}, + {BIT_GET, 1, 1, "enable_nsqt"}, + {BIT_GET, 1, 1, "enable_nsip"}, + {BIT_GET, 1, 1, "enable_2nd_transform"}, + {BIT_GET, 1, 1, "enable_sao"}, + {BIT_GET, 1, 1, "enable_alf"}, + {BIT_GET, 1, 1, "enable_pmvr"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 6, 8, "num_of_rps"}, + {BIT_GET, 1, 1, "refered_by_others[0]"}, + {BIT_GET, 3, 4, "num_of_ref[0]"}, + {BIT_GET, 6, 8, "ref_pic[0][0]"}, + {BIT_GET, 6, 3, "ref_pic[0][1]"}, + {BIT_GET, 6, 7, "ref_pic[0][2]"}, + {BIT_GET, 6, 16, "ref_pic[0][3]"}, + {BIT_GET, 3, 0, "num_to_remove[0]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 1, "refered_by_others[1]"}, + {BIT_GET, 3, 2, "num_of_ref[1]"}, + {BIT_GET, 6, 1, "ref_pic[1][0]"}, + {BIT_GET, 6, 9, "ref_pic[1][1]"}, + {BIT_GET, 3, 3, "num_to_remove[1]"}, + {BIT_GET, 6, 4, "remove_pic[1][0]"}, + {BIT_GET, 6, 10, "remove_pic[1][0]"}, + {BIT_GET, 6, 17, "remove_pic[1][0]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 1, "refered_by_others[2]"}, + {BIT_GET, 3, 2, "num_of_ref[2]"}, + {BIT_GET, 6, 1, "ref_pic[2][0]"}, + {BIT_GET, 6, 10, "ref_pic[2][1]"}, + {BIT_GET, 3, 1, "num_to_remove[2]"}, + {BIT_GET, 6, 9, "remove_pic[2][0]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 0, "refered_by_others[3]"}, + {BIT_GET, 3, 2, "num_of_ref[3]"}, + {BIT_GET, 6, 1, "ref_pic[3][0]"}, + {BIT_GET, 6, 11, "ref_pic[3][1]"}, + {BIT_GET, 3, 0, "num_to_remove[3]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 0, "refered_by_others[4]"}, + {BIT_GET, 3, 2, "num_of_ref[4]"}, + {BIT_GET, 6, 3, "ref_pic[4][0]"}, + {BIT_GET, 6, 2, "ref_pic[4][1]"}, + {BIT_GET, 3, 0, "num_to_remove[4]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 1, "refered_by_others[5]"}, + {BIT_GET, 3, 2, "num_of_ref[5]"}, + {BIT_GET, 6, 5, "ref_pic[5][0]"}, + {BIT_GET, 6, 4, "ref_pic[5][1]"}, + {BIT_GET, 3, 0, "num_to_remove[5]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 0, "refered_by_6thers[6]"}, + {BIT_GET, 3, 2, "num_of_ref[6]"}, + {BIT_GET, 6, 1, "ref_pic[6][0]"}, + {BIT_GET, 6, 5, "ref_pic[6][1]"}, + {BIT_GET, 3, 1, "num_to_remove[6]"}, + {BIT_GET, 6, 4, "remove_pic[6][0]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 1, 0, "refered_by_others[7]"}, + {BIT_GET, 3, 2, "num_of_ref[7]"}, + {BIT_GET, 6, 7, "ref_pic[7][0]"}, + {BIT_GET, 6, 2, "ref_pic[7][1]"}, + {BIT_GET, 3, 0, "num_to_remove[7]"}, + {BIT_GET, 1, 1, "marker_bit"}, + {BIT_GET, 5, 3, "picture_reorder_delay"}, + {BIT_GET, 1, 1, "enable_clf"}, + {BIT_GET, 2, 0, "reserved 2bits 00"} +}; + +// H264 SPS data with "00 00 03 00" +static RK_U8 test_data_3[] = {0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x28, 0xAD, 0x00, + 0x2C, 0xA4, 0x01, 0xE0, 0x11, 0x1F, 0x78, 0x0B, 0x50, 0x10, + 0x10, 0x14, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, + 0x00, 0xCB, 0x9B, 0x80, 0x03, 0xD0, 0x90, 0x03, 0xA9, 0xEF, + 0x7B, 0xE0, 0xA0 + }; + +// H264 PPS and SEI data without "00 00 03 00" +static RK_U8 test_data_4[] = {0x00, 0x00, 0x00, 0x01, 0x68, 0xFE, 0x3C, 0xB0}; + +static BitOps bit_ops_3[] = { + {BIT_SKIP, 40, 0, "start code of SPS"}, + {BIT_GET, 8, 100, "profile_idc"}, + {BIT_GET, 1, 0, "constraint_set0_flag"}, + {BIT_GET, 1, 0, "constraint_set1_flag"}, + {BIT_GET, 1, 0, "constraint_set2_flag"}, + {BIT_GET, 1, 0, "constraint_set3_flag"}, + {BIT_GET, 1, 0, "constraint_set4_flag"}, + {BIT_GET, 1, 0, "constraint_set5_flag"}, + {BIT_GET, 2, 0, "reserved_zero_2bits"}, + {BIT_GET, 8, 40, "level_idc"}, + {BIT_GET_UE, 0, 0, "seq_parameter_set_id"}, + {BIT_GET_UE, 0, 1, "chroma_format_idc"}, + {BIT_GET_UE, 0, 0, "bit_depth_luma_minus8"}, + {BIT_GET_UE, 0, 0, "bit_depth_chroma_minus8"}, + {BIT_GET, 1, 0, "qp_prime_y_zero_transform_bypass"}, + {BIT_GET, 1, 1, "seq_scaling_matrix_present_flag"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[0]"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[1]"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[2]"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[3]"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[4]"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[5]"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[6]"}, + {BIT_GET, 1, 0, "seq_sacling_list_present_flag[7]"}, + {BIT_GET_UE, 0, 4, "log2_max_frame_num_minus4"}, + {BIT_GET_UE, 0, 0, "pic_order_cnt_type"}, + {BIT_GET_UE, 0, 4, "log2_max_pic_order_cnt_lsb_minus"}, + {BIT_GET_UE, 0, 3, "max_num_ref_frames"}, + {BIT_GET, 1, 0, "gaps_in_frame_num_value_allowed_flag"}, + {BIT_GET_UE, 0, 119, "pic_width_in_mbs_minus1"}, + {BIT_GET_UE, 0, 33, "pic_height_in_map_units_minus1"}, + {BIT_GET, 1, 0, "frame_mbs_only_flag"}, + {BIT_GET, 1, 0, "mb_adaptive_frame_field_flag"}, + {BIT_GET, 1, 1, "direct_8x8_inference_flag"}, + {BIT_GET, 1, 1, "frame_cropping_flag"}, + {BIT_GET_UE, 0, 0, "frame_crop_left_offset"}, + {BIT_GET_UE, 0, 0, "frame_crop_right_offset"}, + {BIT_GET_UE, 0, 0, "frame_crop_top_offset"}, + {BIT_GET_UE, 0, 2, "frame_crop_bottom_offset"}, + {BIT_GET, 1, 1, "vui_parameters_present_flag"}, + {BIT_GET, 1, 1, "aspect_ratio_info_present_flag"}, + {BIT_GET, 8, 1, "aspect_ratio_idc"}, + {BIT_GET, 1, 0, "overscan_info_ipresent_flag"}, + {BIT_GET, 1, 1, "video_signal_type_present_flag"}, + {BIT_GET, 3, 5, "video_format"}, + {BIT_GET, 1, 0, "video_full_range_flag"}, + {BIT_GET, 1, 1, "colour_description_present_flag"}, + {BIT_GET, 8, 1, "colour_primaries"}, + {BIT_GET, 8, 1, "transfer_characteristics"}, + {BIT_GET, 8, 1, "matrix_coefficient"}, + {BIT_GET, 1, 0, "chroma_loc_info_present_flag"}, + {BIT_GET, 1, 1, "timing_info_presetn_flag"}, + {BIT_GET, 32, 1, "num_units_in_tick"}, + {BIT_GET, 32, 50, "time_scale"}, + {BIT_GET, 1, 1, "fixed_frame_rate_flag"}, + {BIT_GET, 1, 1, "nal_hrd_parameters_present_flag"}, + {BIT_GET_UE, 0, 0, "cpb_cnt_minus1"}, + {BIT_GET, 4, 3, "bit_rate_scale"}, + {BIT_GET, 4, 7, "cpb_size_scale"}, + {BIT_GET_UE, 0, 15624, "bit_rate_value_minus1[0]"}, + {BIT_GET_UE, 0, 1874, "cpb_size_value_minus1[0]"}, + {BIT_GET, 1, 1, "cbr_flag[0]"}, + {BIT_GET, 5, 23, "initial_cpb_removal_delay_length_minus1"}, + {BIT_GET, 5, 23, "cpb_removal_delay_length_minus1"}, + {BIT_GET, 5, 23, "dpb_output_delay_length_minus1"}, + {BIT_GET, 5, 24, "time_offset_length"}, + {BIT_GET, 1, 0, "vcl_hrd_parameters_present_flag"}, + {BIT_GET, 1, 0, "low_delay_hrd_flag"}, + {BIT_GET, 1, 1, "picture_sturct_present_flag"}, + {BIT_GET, 1, 0, "bitstream_restriction_flag"}, +}; + +static BitOps bit_ops_4[] = { + {BIT_SKIP, 40, 0, "Skip start code of PPS"}, + {BIT_GET_UE, 0, 0, "pic_parameter_set_id"}, + {BIT_GET_UE, 0, 0, "seq_parameter_set_id"}, + {BIT_GET, 1, 1, "entropy_coding_mode_flag"}, + {BIT_GET, 1, 1, "bottom_field_pic_order_in_frame_present_flag"}, + {BIT_GET_UE, 0, 0, "num_slice_groups_minus1"}, + {BIT_GET_UE, 0, 0, "num_ref_idx_l0_default_active_minus1"}, + {BIT_GET_UE, 0, 0, "num_ref_idx_l1_default_active_minus1"}, + {BIT_GET, 1, 0, "weighted_pred_flag"}, + {BIT_GET, 2, 0, "weighted_bipred_idc"}, + {BIT_GET_SE, 0, 0, "pic_init_qp_minus26"}, + {BIT_GET_SE, 0, 0, "pic_init_qs_minus26"}, + {BIT_GET_SE, 0, 0, "chroma_qp_index_offset"}, + {BIT_GET, 1, 1, "debloking_filter_control_present_flag"}, + {BIT_GET, 1, 0, "constrained_intra_pred_flag"}, + {BIT_GET, 1, 0, "redundant_pic_cnt_present_flag"}, + {BIT_GET, 1, 1, "transform_8x8_mode_flag"}, + {BIT_GET, 1, 0, "pic_scaling_matrix_present_flag"}, + {BIT_GET_SE, 0, 0, "second_chroma_qp_index_offset"} +}; + +MPP_RET proc_bit_ops(BitReadCtx_t *ctx, BitOps *ops, RK_S32 *ret_val) +{ + MPP_RET ret = MPP_OK; + switch (ops->type) { + case BIT_GET : + if (ops->len >= 32) { + READ_BITS_LONG(ctx, ops->len, ret_val); + } else { + READ_BITS(ctx, ops->len, ret_val); + } + break; + case BIT_GET_UE: + READ_UE(ctx, ret_val); + break; + case BIT_GET_SE: + READ_SE(ctx, ret_val); + break; + case BIT_SKIP: + if (ops->len >= 32) { + SKIP_BITS_LONG(ctx, ops->len); + } else { + SKIP_BITS(ctx, ops->len); + } + break; + } + goto __NORMAL; +__BITREAD_ERR: + mpp_err("Read failed: syntax %s, %s, %d bits\n", ops->syntax, bitOpsStr[ops->type], ops->len); + return ret = MPP_ERR_VALUE; +__NORMAL: + if (ops->val != *ret_val) { + mpp_err("Read error: syntax %s, expect %d but %d\n", ops->syntax, ops->val, *ret_val); + ret = MPP_ERR_VALUE; + } else { + mpp_log("Read OK, syntax %s, %d\n", ops->syntax, *ret_val); + } + return ret; +} + +int main(void) +{ + BitReadCtx_t reader; + RK_U32 i; + RK_S32 tmp = 0; + + mpp_log("mpp bit read test start\n"); + mpp_log("Reading H264 data with 00 00 03 00..."); + memset(&reader, 0, sizeof(BitReadCtx_t)); + mpp_set_bitread_ctx(&reader, test_data_3, sizeof(test_data_3)); + // mpp_set_pre_detection(&reader); + mpp_set_bitread_pseudo_code_type(&reader, PSEUDO_CODE_H264_H265); + for (i = 0; i < MPP_ARRAY_ELEMS(bit_ops_3); i++) { + + if (proc_bit_ops(&reader, &bit_ops_3[i], &tmp)) + goto __READ_FAILED; + + tmp = 0; + } + + mpp_log("Reading H264 data without 00 00 03 00..."); + memset(&reader, 0, sizeof(BitReadCtx_t)); + mpp_set_bitread_ctx(&reader, test_data_4, sizeof(test_data_4)); + + for (i = 0; i < MPP_ARRAY_ELEMS(bit_ops_4); i++) { + if (proc_bit_ops(&reader, &bit_ops_4[i], &tmp)) + goto __READ_FAILED; + + tmp = 0; + } + + mpp_log("Reading AVS2 data without 00 00 02..."); + memset(&reader, 0, sizeof(BitReadCtx_t)); + mpp_set_bitread_ctx(&reader, test_data_2, sizeof(test_data_2)); + + for (i = 0; i < MPP_ARRAY_ELEMS(bit_ops_2); i++) { + if (proc_bit_ops(&reader, &bit_ops_2[i], &tmp)) + goto __READ_FAILED; + + tmp = 0; + } + + mpp_log("Reading AVS2 data with 00 00 02..."); + memset(&reader, 0, sizeof(BitReadCtx_t)); + mpp_set_bitread_ctx(&reader, test_data_1, sizeof(test_data_1)); + mpp_set_bitread_pseudo_code_type(&reader, PSEUDO_CODE_AVS2); + + for (i = 0; i < MPP_ARRAY_ELEMS(bit_ops_1); i++) { + if (proc_bit_ops(&reader, &bit_ops_1[i], &tmp)) + goto __READ_FAILED; + + tmp = 0; + } + mpp_log("mpp bit read test end\n"); + return 0; +__READ_FAILED: + return -1; +} \ No newline at end of file diff --git a/mpp/base/test/mpp_bit_test.c b/mpp/base/test/mpp_bit_test.c new file mode 100644 index 000000000..c3d161752 --- /dev/null +++ b/mpp/base/test/mpp_bit_test.c @@ -0,0 +1,128 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_bit_test" + +#include + +#include "mpp_log.h" +#include "mpp_common.h" +#include "mpp_bitwrite.h" + +#define BIT_WRITER_BUFFER_SIZE 1024 + +/* + * type is for operation type + * 0 - plain bit put + * 1 - bit put with detection + * 2 - write ue + * 3 - write se + * 4 - align byte + */ +typedef enum BitOpsType_e { + BIT_PUT_NO03, + BIT_PUT, + BIT_PUT_UE, + BIT_PUT_SE, + BIT_ALIGN_BYTE, +} BitOpsType; + +typedef struct BitOps_t { + BitOpsType type; + RK_S32 val; + RK_S32 len; +} BitOps; + +static BitOps bit_ops[] = { + { BIT_PUT_NO03, 0, 8, }, + { BIT_PUT, 0, 3, }, + { BIT_PUT, 0, 15, }, + { BIT_PUT, 0, 23, }, + { BIT_PUT_UE, 17, 0, }, + { BIT_PUT_SE, 9, 0, }, + { BIT_ALIGN_BYTE, 0, 0, }, +}; + +void proc_bit_ops(MppWriteCtx *writer, BitOps *ops) +{ + switch (ops->type) { + case BIT_PUT_NO03 : { + mpp_writer_put_raw_bits(writer, ops->val, ops->len); + } break; + case BIT_PUT : { + mpp_writer_put_bits(writer, ops->val, ops->len); + } break; + case BIT_PUT_UE : { + mpp_writer_put_ue(writer, ops->val); + } break; + case BIT_PUT_SE : { + mpp_writer_put_ue(writer, ops->val); + } break; + case BIT_ALIGN_BYTE : { + mpp_writer_trailing(writer); + } break; + default : { + mpp_err("invalid ops type %d\n", ops->type); + } break; + } +} + +int main(void) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + void *data = NULL; + size_t size = BIT_WRITER_BUFFER_SIZE; + MppWriteCtx writer; + RK_U32 len_byte; + RK_U32 i; + RK_U32 buf_len = 0; + char buf[BIT_WRITER_BUFFER_SIZE]; + + mpp_log("mpp_bit_test start\n"); + + data = malloc(size); + if (NULL == data) { + mpp_err("mpp_bit_test malloc failed\n"); + goto TEST_FAILED; + } + + mpp_writer_init(&writer, data, size); + + for (i = 0; i < MPP_ARRAY_ELEMS(bit_ops); i++) + proc_bit_ops(&writer, &bit_ops[i]); + + len_byte = writer.byte_cnt; + + for (i = 0; i < len_byte; i++) { + buf_len += snprintf(buf + buf_len, sizeof(buf) - buf_len, + "%02x ", writer.buffer[i]); + } + + mpp_log("stream %s\n", buf); + + ret = MPP_OK; +TEST_FAILED: + if (data) + free(data); + + if (ret) + mpp_log("mpp_bit_test failed\n"); + else + mpp_log("mpp_bit_test success\n"); + + return ret; +} + diff --git a/mpp/base/test/mpp_buffer_test.c b/mpp/base/test/mpp_buffer_test.c new file mode 100644 index 000000000..0bb20f20b --- /dev/null +++ b/mpp/base/test/mpp_buffer_test.c @@ -0,0 +1,298 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_buffer_test" + +#include + +#if defined(_WIN32) +#include "vld.h" +#endif +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_buffer.h" +#include "mpp_allocator.h" + +#define MPP_BUFFER_TEST_DEBUG_FLAG (0xf) +#define MPP_BUFFER_TEST_SIZE (SZ_1K*4) +#define MPP_BUFFER_TEST_COMMIT_COUNT 10 +#define MPP_BUFFER_TEST_NORMAL_COUNT 10 + +int main(void) +{ + MPP_RET ret = MPP_OK; + MppAllocator allocator = NULL; + MppAllocatorApi *api = NULL; + MppBufferInfo commit; + MppBufferGroup group = NULL; + MppBuffer commit_buffer[MPP_BUFFER_TEST_COMMIT_COUNT]; + void *commit_ptr[MPP_BUFFER_TEST_COMMIT_COUNT]; + MppBuffer normal_buffer[MPP_BUFFER_TEST_NORMAL_COUNT]; + MppBuffer legacy_buffer = NULL; + size_t size = MPP_BUFFER_TEST_SIZE; + RK_S32 count = MPP_BUFFER_TEST_COMMIT_COUNT; + RK_S32 i; + RK_U32 debug = 0; + + mpp_env_set_u32("mpp_buffer_debug", MPP_BUFFER_TEST_DEBUG_FLAG); + mpp_env_get_u32("mpp_buffer_debug", &debug, 0); + + mpp_log("mpp_buffer_test start with debug 0x%x\n", debug); + + memset(commit_ptr, 0, sizeof(commit_ptr)); + memset(commit_buffer, 0, sizeof(commit_buffer)); + memset(normal_buffer, 0, sizeof(normal_buffer)); + + // create group with external type + ret = mpp_buffer_group_get_external(&group, MPP_BUFFER_TYPE_ION); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_group_get failed\n"); + goto MPP_BUFFER_failed; + } + + mpp_log("mpp_buffer_test commit mode with unused status start\n"); + + commit.type = MPP_BUFFER_TYPE_ION; + commit.size = size; + + // create misc ion buffer and commit to external group + for (i = 0; i < count; i++) { + // can be change to different buffer allocator here + ret = mpp_buffer_get(NULL, &normal_buffer[i], size); + if (ret || NULL == normal_buffer[i]) { + mpp_err("mpp_buffer_test get misc buffer failed ret %d\n", ret); + goto MPP_BUFFER_failed; + } + + // NOTE: setup fd / index in necessary + commit.ptr = mpp_buffer_get_ptr(normal_buffer[i]); + commit.fd = mpp_buffer_get_fd(normal_buffer[i]); + commit.index = i; + + ret = mpp_buffer_commit(group, &commit); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_commit failed\n"); + goto MPP_BUFFER_failed; + } + } + + for (i = 0; i < count; i++) { + ret = mpp_buffer_get(group, &commit_buffer[i], size); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_get commit mode failed\n"); + goto MPP_BUFFER_failed; + } + } + + for (i = 0; i < count; i++) { + if (commit_buffer[i]) { + ret = mpp_buffer_put(commit_buffer[i]); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_put commit mode failed\n"); + goto MPP_BUFFER_failed; + } + commit_buffer[i] = NULL; + } + } + + for (i = 0; i < count; i++) { + if (normal_buffer[i]) { + mpp_buffer_put(normal_buffer[i]); + normal_buffer[i] = NULL; + } + } + + mpp_buffer_group_put(group); + + mpp_log("mpp_buffer_test commit mode with unused status success\n"); + + + mpp_log("mpp_buffer_test commit mode with used status start\n"); + + ret = mpp_allocator_get(&allocator, &api, MPP_BUFFER_TYPE_ION, 0); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_allocator_get ion failed\n"); + goto MPP_BUFFER_failed; + } + + commit.type = MPP_BUFFER_TYPE_ION; + commit.size = size; + + for (i = 0; i < count; i++) { + ret = api->alloc(allocator, &commit); + if (ret) { + mpp_err("mpp_buffer_test mpp_allocator_alloc failed\n"); + goto MPP_BUFFER_failed; + } + + mpp_log("allocator get ptr %p with fd %d\n", commit.ptr, commit.fd); + + /* + * NOTE: commit buffer info will be directly return within new MppBuffer + * This mode allow input group is NULL + */ + ret = mpp_buffer_import(&commit_buffer[i], &commit); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_commit failed\n"); + goto MPP_BUFFER_failed; + } + + /* + * test imported buffer + */ + { + void *ptr = mpp_buffer_get_ptr(commit_buffer[i]); + if (NULL == ptr) { + mpp_err("mpp_buffer_test mpp_buffer_get_ptr failed\n"); + goto MPP_BUFFER_failed; + } + + mpp_log("get ptr %p from fd %d\n", ptr, mpp_buffer_get_fd(commit_buffer[i])); + + memset(ptr, 0, mpp_buffer_get_size(commit_buffer[i])); + } + } + + for (i = 0; i < count; i++) { + if (commit_buffer[i]) { + ret = mpp_buffer_info_get(commit_buffer[i], &commit); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_info_get failed\n"); + goto MPP_BUFFER_failed; + } + + ret = mpp_buffer_put(commit_buffer[i]); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_put commit mode failed\n"); + goto MPP_BUFFER_failed; + } + + commit_buffer[i] = NULL; + + /* NOTE: buffer info from allocator need to be free directly */ + ret = api->free(allocator, &commit); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test api->free failed\n"); + goto MPP_BUFFER_failed; + } + } + } + + ret = mpp_allocator_put(&allocator); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_allocator_put failed\n"); + goto MPP_BUFFER_failed; + } + + mpp_log("mpp_buffer_test commit mode with used status success\n"); + + + mpp_log("mpp_buffer_test normal mode start\n"); + + ret = mpp_buffer_group_get_internal(&group, MPP_BUFFER_TYPE_ION); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_group_get failed\n"); + goto MPP_BUFFER_failed; + } + + count = MPP_BUFFER_TEST_NORMAL_COUNT; + + mpp_buffer_group_limit_config(group, 0, count); + + for (i = 0; i < count; i++) { + ret = mpp_buffer_get(group, &normal_buffer[i], (i + 1) * SZ_1K); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_get mode normal failed\n"); + goto MPP_BUFFER_failed; + } + } + + for (i = 0; i < count; i++) { + if (normal_buffer[i]) { + ret = mpp_buffer_put(normal_buffer[i]); + if (MPP_OK != ret) { + mpp_err("mpp_buffer_test mpp_buffer_get mode normal failed\n"); + goto MPP_BUFFER_failed; + } + normal_buffer[i] = NULL; + } + } + + mpp_log("mpp_buffer_test normal mode success\n"); + + if (group) { + mpp_buffer_group_put(group); + group = NULL; + } + + mpp_log("mpp_buffer_test success\n"); + + ret = mpp_buffer_get(NULL, &legacy_buffer, MPP_BUFFER_TEST_SIZE); + if (MPP_OK != ret) { + mpp_log("mpp_buffer_test mpp_buffer_get legacy buffer failed\n"); + goto MPP_BUFFER_failed; + } + + ret = mpp_buffer_put(legacy_buffer); + if (MPP_OK != ret) { + mpp_log("mpp_buffer_test mpp_buffer_put legacy buffer failed\n"); + goto MPP_BUFFER_failed; + } + + mpp_env_set_u32("mpp_buffer_debug", 0); + + return ret; + +MPP_BUFFER_failed: + for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { + if (commit_buffer[i]) + mpp_buffer_put(commit_buffer[i]); + } + + for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { + if (commit_ptr[i]) { + free(commit_ptr[i]); + commit_ptr[i] = NULL; + } + } + for (i = 0; i < MPP_BUFFER_TEST_NORMAL_COUNT; i++) { + if (normal_buffer[i]) + mpp_buffer_put(normal_buffer[i]); + } + + if (group) { + mpp_buffer_group_put(group); + group = NULL; + } + + if (legacy_buffer) { + mpp_buffer_put(legacy_buffer); + legacy_buffer = NULL; + } + + if (allocator) { + mpp_allocator_put(&allocator); + } + mpp_assert(NULL == allocator); + + mpp_log("mpp_buffer_test failed\n"); + + mpp_env_set_u32("mpp_buffer_debug", 0); + + return ret; +} + diff --git a/mpp/base/test/mpp_cfg_test.c b/mpp/base/test/mpp_cfg_test.c new file mode 100644 index 000000000..a0b0802d8 --- /dev/null +++ b/mpp/base/test/mpp_cfg_test.c @@ -0,0 +1,635 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_cfg_test" + +#include +#include +#include +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "mpp_cfg_io.h" + +static const char *str_fmt[] = { + "log", + "json", + "toml", + "invalid" +}; + +static rk_s32 add_array_element(MppCfgObj array, MppCfgType type, MppCfgVal *val) +{ + MppCfgObj obj = NULL; + rk_s32 ret; + + ret = mpp_cfg_get_object(&obj, NULL, type, val); + if (ret) { + mpp_loge("mpp_cfg_get_object array element type %d failed\n", type); + return ret; + } + + ret = mpp_cfg_add(array, obj); + if (ret) { + mpp_loge("mpp_cfg_add array element failed\n"); + mpp_cfg_put_all(obj); + return ret; + } + + return rk_ok; +} + +static rk_s32 test_typed_arrays(MppCfgObj root) +{ + MppCfgObj array = NULL; + MppCfgVal val; + rk_s32 ret = rk_nok; + rk_s32 i; + + mpp_logi("test typed arrays\n"); + + ret = mpp_cfg_get_array(&array, "s8_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array s8 failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.s8 = (rk_s8)(-128 + i * 10); + ret = add_array_element(array, MPP_CFG_TYPE_s8, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add s8_array failed\n"); + goto DONE; + } + array = NULL; + + ret = mpp_cfg_get_array(&array, "u8_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array u8 failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.u8 = (rk_u8)(i * 50); + ret = add_array_element(array, MPP_CFG_TYPE_u8, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add u8_array failed\n"); + goto DONE; + } + array = NULL; + + ret = mpp_cfg_get_array(&array, "s16_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array s16 failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.s16 = (rk_s16)(-1000 + i * 100); + ret = add_array_element(array, MPP_CFG_TYPE_s16, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add s16_array failed\n"); + goto DONE; + } + array = NULL; + + ret = mpp_cfg_get_array(&array, "u16_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array u16 failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.u16 = (rk_u16)(i * 1000); + ret = add_array_element(array, MPP_CFG_TYPE_u16, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add u16_array failed\n"); + goto DONE; + } + array = NULL; + + ret = mpp_cfg_get_array(&array, "s64_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array s64 failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.s64 = (rk_s64)(-1000000LL + i * 100000LL); + ret = add_array_element(array, MPP_CFG_TYPE_s64, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add s64_array failed\n"); + goto DONE; + } + array = NULL; + + ret = mpp_cfg_get_array(&array, "u64_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array u64 failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.u64 = (rk_u64)(i * 1000000ULL); + ret = add_array_element(array, MPP_CFG_TYPE_u64, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add u64_array failed\n"); + goto DONE; + } + array = NULL; + + ret = mpp_cfg_get_array(&array, "bool_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array bool failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.b1 = (i % 2 == 0) ? (rk_bool)RK_TRUE : (rk_bool)RK_FALSE; + ret = add_array_element(array, MPP_CFG_TYPE_BOOL, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add bool_array failed\n"); + goto DONE; + } + array = NULL; + + { + const char *str_values[] = {"str0", "str1", "str2", "str3"}; + ret = mpp_cfg_get_array(&array, "string_array", 4); + if (ret) { + mpp_loge("mpp_cfg_get_array string failed\n"); + goto DONE; + } + for (i = 0; i < 4; i++) { + val.str = (char *)str_values[i]; + ret = add_array_element(array, MPP_CFG_TYPE_STRING, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add string_array failed\n"); + goto DONE; + } + array = NULL; + } + + ret = rk_ok; +DONE: + return ret; +} + +static rk_s32 test_object_array(MppCfgObj root) +{ + MppCfgObj array = NULL; + MppCfgObj obj = NULL; + MppCfgObj inner_obj = NULL; + MppCfgVal val; + rk_s32 ret = rk_nok; + rk_s32 i; + const char *obj_names[] = {"obj_a", "obj_b", "obj_c"}; + + mpp_logi("test object array\n"); + + ret = mpp_cfg_get_array(&array, "object_array", 3); + if (ret) { + mpp_loge("mpp_cfg_get_array object failed\n"); + goto DONE; + } + + for (i = 0; i < 3; i++) { + ret = mpp_cfg_get_object(&obj, NULL, MPP_CFG_TYPE_OBJECT, NULL); + if (ret) { + mpp_loge("mpp_cfg_get_object for inner object failed\n"); + goto DONE; + } + + val.s32 = i + 100; + ret = mpp_cfg_get_object(&inner_obj, "id", MPP_CFG_TYPE_s32, &val); + if (ret) { + mpp_loge("mpp_cfg_get_object id failed\n"); + goto DONE; + } + ret = mpp_cfg_add(obj, inner_obj); + if (ret) { + mpp_loge("mpp_cfg_add id failed\n"); + goto DONE; + } + inner_obj = NULL; + + val.str = (char *)obj_names[i]; + ret = mpp_cfg_get_object(&inner_obj, "name", MPP_CFG_TYPE_STRING, &val); + if (ret) { + mpp_loge("mpp_cfg_get_object name failed\n"); + goto DONE; + } + ret = mpp_cfg_add(obj, inner_obj); + if (ret) { + mpp_loge("mpp_cfg_add name failed\n"); + goto DONE; + } + inner_obj = NULL; + + val.b1 = (i == 0) ? (rk_bool)RK_TRUE : (rk_bool)RK_FALSE; + ret = mpp_cfg_get_object(&inner_obj, "active", MPP_CFG_TYPE_BOOL, &val); + if (ret) { + mpp_loge("mpp_cfg_get_object active failed\n"); + goto DONE; + } + ret = mpp_cfg_add(obj, inner_obj); + if (ret) { + mpp_loge("mpp_cfg_add active failed\n"); + goto DONE; + } + inner_obj = NULL; + + ret = mpp_cfg_add(array, obj); + if (ret) { + mpp_loge("mpp_cfg_add object to array failed\n"); + goto DONE; + } + obj = NULL; + } + + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add object_array failed\n"); + goto DONE; + } + + ret = rk_ok; +DONE: + if (inner_obj) + mpp_cfg_put_all(inner_obj); + if (obj) + mpp_cfg_put_all(obj); + return ret; +} + +static rk_s32 test_nested_array(MppCfgObj root) +{ + MppCfgObj outer_array = NULL; + MppCfgObj inner_array = NULL; + MppCfgVal val; + rk_s32 ret = rk_nok; + rk_s32 i, j; + + mpp_logi("test nested array\n"); + + ret = mpp_cfg_get_array(&outer_array, "nested_array", 3); + if (ret) { + mpp_loge("mpp_cfg_get_array outer failed\n"); + goto DONE; + } + + for (i = 0; i < 3; i++) { + ret = mpp_cfg_get_array(&inner_array, NULL, 3); + if (ret) { + mpp_loge("mpp_cfg_get_array inner failed\n"); + goto DONE; + } + + for (j = 0; j < 3; j++) { + val.s32 = i * 10 + j; + ret = add_array_element(inner_array, MPP_CFG_TYPE_s32, &val); + if (ret) + goto DONE; + } + + ret = mpp_cfg_add(outer_array, inner_array); + if (ret) { + mpp_loge("mpp_cfg_add inner array failed\n"); + goto DONE; + } + inner_array = NULL; + } + + ret = mpp_cfg_add(root, outer_array); + if (ret) { + mpp_loge("mpp_cfg_add nested_array failed\n"); + goto DONE; + } + + ret = rk_ok; +DONE: + if (inner_array) + mpp_cfg_put_all(inner_array); + return ret; +} + +static rk_s32 test_to_from(MppCfgObj obj, MppCfgStrFmt fmt) +{ + MppCfgObj out = NULL; + char *std = NULL; + char *str = NULL; + rk_s32 ret = rk_nok; + + ret = mpp_cfg_to_string(obj, fmt, &std); + if (ret) { + mpp_loge("mpp_cfg obj to %s string failed\n", str_fmt[fmt]); + goto DONE; + } + if (!std || !std[0]) { + mpp_loge("mpp_cfg obj to %s string returned empty\n", str_fmt[fmt]); + ret = rk_nok; + goto DONE; + } + + ret = mpp_cfg_from_string(&out, fmt, std); + if (ret) { + mpp_loge("mpp_cfg out from %s string failed ret %d\n", str_fmt[fmt], ret); + goto DONE; + } + if (!out) { + mpp_loge("mpp_cfg out from %s string returned NULL object\n", str_fmt[fmt]); + ret = rk_nok; + goto DONE; + } + + ret = mpp_cfg_to_string(out, fmt, &str); + if (ret) { + mpp_loge("mpp_cfg out to %s string failed ret %d\n", str_fmt[fmt], ret); + goto DONE; + } + if (!str || !str[0]) { + mpp_loge("mpp_cfg out to %s string returned empty\n", str_fmt[fmt]); + ret = rk_nok; + goto DONE; + } + + if (strcmp(std, str)) { + mpp_loge("mpp_cfg mismatch on from / to %s string\n", str_fmt[fmt]); + mpp_logi("string std:\n"); + mpp_cfg_print_string(std); + mpp_logi("string out:\n"); + mpp_cfg_print_string(str); + ret = rk_nok; + } else { + ret = rk_ok; + } + +DONE: + MPP_FREE(std); + MPP_FREE(str); + mpp_cfg_put_all(out); + + return ret; +} + +int main(int argc, char *argv[]) +{ + MppCfgObj root = NULL; + MppCfgObj array = NULL; + MppCfgObj obj = NULL; + MppCfgVal val; + rk_s32 array_size = 4; + rk_s32 ret = rk_nok; + rk_s32 i; + + mpp_logi("start\n"); + + if (argc > 1) { + char *path = argv[1]; + void *buf = NULL; + rk_s32 fd = -1; + rk_s32 size = 0; + MppCfgStrFmt file_fmt = MPP_CFG_STR_FMT_JSON; + char *ext = strrchr(path, '.'); + + if (ext) { + if (!strcmp(ext, ".toml")) + file_fmt = MPP_CFG_STR_FMT_TOML; + else if (!strcmp(ext, ".json")) + file_fmt = MPP_CFG_STR_FMT_JSON; + } + mpp_logi("file %s format %s\n", path, str_fmt[file_fmt]); + + fd = open(path, O_RDWR); + if (fd < 0) { + mpp_loge("open %s failed\n", path); + goto FILE_DONE; + } + + size = lseek(fd, 0, SEEK_END); + if (size < 0) { + mpp_loge("lseek failed\n"); + goto FILE_DONE; + } + lseek(fd, 0, SEEK_SET); + + buf = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (!buf) { + mpp_loge("mmap fd %d size %d failed\n", fd, size); + goto FILE_DONE; + } + + ret = mpp_cfg_from_string(&root, file_fmt, buf); + if (ret) { + mpp_loge("mpp_cfg_from_string failed\n"); + goto FILE_DONE; + } + + mpp_logi("cfg object %p from file\n", root); + mpp_cfg_dump_f(root); + + ret = test_to_from(root, file_fmt); + mpp_logi("test to / from %s string %s\n", str_fmt[file_fmt], ret ? "failed" : "success"); + + FILE_DONE: + if (buf) { + munmap(buf, size); + buf = NULL; + } + if (fd >= 0) { + close(fd); + fd = -1; + } + + mpp_cfg_put_all(root); + root = NULL; + + if (ret) + return ret; + } + + ret = mpp_cfg_get_object(&root, NULL, MPP_CFG_TYPE_OBJECT, NULL); + if (ret) { + mpp_loge("mpp_cfg_get_object failed\n"); + goto DONE; + } + + mpp_logi("test basic s32 array\n"); + ret = mpp_cfg_get_array(&array, NULL, array_size); + if (ret) { + mpp_loge("mpp_cfg_get_array failed\n"); + goto DONE; + } + + for (i = 0; i < array_size; i++) { + obj = NULL; + val.s32 = i; + ret = mpp_cfg_get_object(&obj, NULL, MPP_CFG_TYPE_s32, &val); + if (ret) { + mpp_loge("mpp_cfg_get_object array element failed\n"); + goto DONE; + } + + ret = mpp_cfg_add(array, obj); + if (ret) { + mpp_loge("mpp_cfg_add array element failed\n"); + goto DONE; + } + } + + ret = mpp_cfg_add(root, array); + if (ret) { + mpp_loge("mpp_cfg_add failed\n"); + goto DONE; + } + + obj = NULL; + val.s32 = 1920; + ret = mpp_cfg_get_object(&obj, "width", MPP_CFG_TYPE_s32, &val); + if (ret) { + mpp_loge("mpp_cfg_get s32 failed\n"); + goto DONE; + } + ret = mpp_cfg_add(root, obj); + if (ret) { + mpp_loge("mpp_cfg_add s32 failed\n"); + goto DONE; + } + + obj = NULL; + val.u32 = 1080; + ret = mpp_cfg_get_object(&obj, "height", MPP_CFG_TYPE_u32, &val); + if (ret) { + mpp_loge("mpp_cfg_get u32 failed\n"); + goto DONE; + } + ret = mpp_cfg_add(root, obj); + if (ret) { + mpp_loge("mpp_cfg_add u32 failed\n"); + goto DONE; + } + + obj = NULL; + val.str = "hello world"; + ret = mpp_cfg_get_object(&obj, "test", MPP_CFG_TYPE_STRING, &val); + if (ret) { + mpp_loge("mpp_cfg_get string failed\n"); + goto DONE; + } + ret = mpp_cfg_add(root, obj); + if (ret) { + mpp_loge("mpp_cfg_add string failed\n"); + goto DONE; + } + + ret = test_typed_arrays(root); + if (ret) { + mpp_loge("test_typed_arrays failed\n"); + goto DONE; + } + array = NULL; + + ret = test_object_array(root); + if (ret) { + mpp_loge("test_object_array failed\n"); + goto DONE; + } + + ret = test_nested_array(root); + if (ret) { + mpp_loge("test_nested_array failed\n"); + goto DONE; + } + + mpp_cfg_dump_f(root); + + { + MppCfgObj simple_root = NULL; + MppCfgObj simple_array = NULL; + rk_s32 ser_ret; + + mpp_logi("test serialization\n"); + + ret = mpp_cfg_get_object(&simple_root, NULL, MPP_CFG_TYPE_OBJECT, NULL); + if (ret) + goto DONE; + + val.s32 = 1920; + ret = mpp_cfg_get_object(&obj, "width", MPP_CFG_TYPE_s32, &val); + if (ret) + goto DONE; + ret = mpp_cfg_add(simple_root, obj); + if (ret) + goto DONE; + obj = NULL; + + ret = mpp_cfg_get_array(&simple_array, "values", 4); + if (ret) + goto DONE; + for (i = 0; i < 4; i++) { + val.s32 = i * 10; + ret = add_array_element(simple_array, MPP_CFG_TYPE_s32, &val); + if (ret) + goto DONE; + } + ret = mpp_cfg_add(simple_root, simple_array); + if (ret) + goto DONE; + simple_array = NULL; + + ser_ret = test_to_from(simple_root, MPP_CFG_STR_FMT_LOG); + mpp_logi("to/from log %s\n", ser_ret ? "failed" : "success"); + + ser_ret = test_to_from(simple_root, MPP_CFG_STR_FMT_JSON); + mpp_logi("to/from json %s\n", ser_ret ? "failed" : "success"); + + mpp_cfg_put_all(simple_root); + } + + ret = rk_ok; + +DONE: + if (root) { + mpp_cfg_put_all(root); + root = NULL; + } + if (array) { + mpp_cfg_put_all(array); + array = NULL; + } + + mpp_logi("done %s\n", ret ? "failed" : "success"); + + return ret; +} diff --git a/mpp/base/test/mpp_cluster_test.c b/mpp/base/test/mpp_cluster_test.c new file mode 100644 index 000000000..c8a34b294 --- /dev/null +++ b/mpp/base/test/mpp_cluster_test.c @@ -0,0 +1,103 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_cluster_test" + +#include "mpp_log.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "mpp_cluster.h" + +typedef struct MppTestNode_t { + MppNode node; +} MppTestNode; + +MppTestNode test_node; + +static RK_S32 mpp_cluster_test_worker(void *param) +{ + RK_S32 ret = MPP_NOK; + (void) param; + + mpp_log_f("worker run start\n"); + mpp_log_f("worker run ret %d\n", ret); + + return ret; +} + +int main(void) +{ + MPP_RET ret = MPP_OK; + MppNode node = test_node.node; + RK_U32 total_run = 2; + + mpp_log("mpp_cluster_test start\n"); + + ret = mpp_node_init(&node); + if (ret) { + mpp_err("mpp_node_init failed ret %d\n", ret); + goto DONE; + } + + mpp_log("mpp_cluster_test init node done\n"); + + /* setup node info */ + mpp_node_set_func(node, mpp_cluster_test_worker, &test_node); + + mpp_log("mpp_cluster_test attach node start\n"); + ret = mpp_node_attach(node, VPU_CLIENT_RKVDEC); + if (ret) { + mpp_err("mpp_node_attach failed ret %d\n", ret); + goto DONE; + } + + mpp_log("mpp_cluster_test trigger start\n"); + + do { + ret = mpp_node_trigger(node, 1); + if (ret) { + mpp_err("mpp_node_trigger failed ret %d\n", ret); + goto DONE; + } + + mpp_log("mpp_cluster_test trigger %d left\n", total_run); + + msleep(5); + } while (--total_run); + + mpp_log("mpp_cluster_test detach start\n"); + + ret = mpp_node_detach(node); + if (ret) { + mpp_err("mpp_node_detach failed ret %d\n", ret); + goto DONE; + } + + mpp_log("mpp_cluster_test deinit start\n"); + + ret = mpp_node_deinit(node); + if (ret) { + mpp_err("mpp_node_deinit failed ret %d\n", ret); + goto DONE; + } + + mpp_log("mpp_cluster_test deinit done\n"); + +DONE: + mpp_log("mpp_cluster_test done %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/mpp/base/test/mpp_dec_cfg_test.c b/mpp/base/test/mpp_dec_cfg_test.c new file mode 100644 index 000000000..e010e6f0e --- /dev/null +++ b/mpp/base/test/mpp_dec_cfg_test.c @@ -0,0 +1,66 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_dec_cfg_test" + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "rk_vdec_cfg.h" +#include "mpp_dec_cfg.h" + +int main(void) +{ + MPP_RET ret = MPP_OK; + MppDecCfg cfg; + RK_S64 end = 0; + RK_S64 start = 0; + + mpp_dec_cfg_show(); + + mpp_log("mpp_dec_cfg_test start\n"); + + ret = mpp_dec_cfg_init(&cfg); + if (ret) { + mpp_err("mpp_dec_cfg_init failed\n"); + goto DONE; + } + + RK_S32 fast_out = 1; + + MppDecCfgSet *impl = (MppDecCfgSet *)cfg; + + mpp_log("before set: fast_out %d\n", impl->base.fast_out); + + start = mpp_time(); + ret = mpp_dec_cfg_set_u32(cfg, "base:fast_out", fast_out); + end = mpp_time(); + mpp_log("set u32 time %lld us\n", end - start); + + mpp_log("after get: fast_out %d\n", fast_out); + + ret = mpp_dec_cfg_deinit(cfg); + if (ret) { + mpp_err("mpp_dec_cfg_deinit failed\n"); + goto DONE; + } + +DONE: + mpp_log("mpp_dec_cfg_test done %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/mpp/base/test/mpp_enc_cfg_test.c b/mpp/base/test/mpp_enc_cfg_test.c new file mode 100644 index 000000000..0eee52ad9 --- /dev/null +++ b/mpp/base/test/mpp_enc_cfg_test.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_enc_cfg_test" + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "rk_venc_cfg.h" +#include "mpp_enc_cfg.h" + +int main(void) +{ + MPP_RET ret = MPP_OK; + MppEncCfg cfg; + RK_S64 end = 0; + RK_S64 start = 0; + + mpp_enc_cfg_show(); + + mpp_log("mpp_enc_cfg_test start\n"); + + ret = mpp_enc_cfg_init(&cfg); + if (ret) { + mpp_err("mpp_enc_cfg_init failed\n"); + goto DONE; + } + + RK_S32 rc_mode = 1; + RK_S32 bps_target = 400000; + RK_S32 aq_thrd_i[16] = { + 0, 0, 0, 0, + 3, 3, 5, 5, + 8, 8, 8, 15, + 15, 20, 25, 35 + }; + + RK_S32 aq_thrd_i_ret[16] = { + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + }; + + MppEncCfgSet *impl = (MppEncCfgSet *)kmpp_obj_to_entry(cfg); + + mpp_log("before set: rc mode %d bps_target %d\n", + impl->rc.rc_mode, impl->rc.bps_target); + + start = mpp_time(); + ret = mpp_enc_cfg_set_u32(cfg, "rc:mode", rc_mode); + ret = mpp_enc_cfg_set_s32(cfg, "rc:mode", rc_mode); + ret = mpp_enc_cfg_set_s32(cfg, "rc:bps", 400000); + ret = mpp_enc_cfg_set_s32(cfg, "rc:bps_target", bps_target); + end = mpp_time(); + mpp_log("set s32 time %lld us\n", end - start); + + mpp_log("after set: rc mode %d bps_target %d\n", + impl->rc.rc_mode, impl->rc.bps_target); + + rc_mode = 0; + bps_target = 0; + + mpp_log("before get: rc mode %d bps_target %d\n", rc_mode, bps_target); + + ret = mpp_enc_cfg_get_s32(cfg, "rc:mode", &rc_mode); + ret = mpp_enc_cfg_get_s32(cfg, "rc:bps_target", &bps_target); + mpp_log("after get: rc mode %d bps_target %d\n", rc_mode, bps_target); + + mpp_log("before set: rc aq_thrd_i: %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d\n", + aq_thrd_i_ret[0], aq_thrd_i_ret[1], aq_thrd_i_ret[2], aq_thrd_i_ret[3], + aq_thrd_i_ret[4], aq_thrd_i_ret[5], aq_thrd_i_ret[6], aq_thrd_i_ret[7], + aq_thrd_i_ret[8], aq_thrd_i_ret[9], aq_thrd_i_ret[10], aq_thrd_i_ret[11], + aq_thrd_i_ret[12], aq_thrd_i_ret[13], aq_thrd_i_ret[14], aq_thrd_i_ret[15]); + + ret = mpp_enc_cfg_set_st(cfg, "hw:aq_step_i", aq_thrd_i); + ret = mpp_enc_cfg_get_st(cfg, "hw:aq_step_i", aq_thrd_i_ret); + + mpp_log("after get: rc aq_thrd_i: %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d\n", + aq_thrd_i_ret[0], aq_thrd_i_ret[1], aq_thrd_i_ret[2], aq_thrd_i_ret[3], + aq_thrd_i_ret[4], aq_thrd_i_ret[5], aq_thrd_i_ret[6], aq_thrd_i_ret[7], + aq_thrd_i_ret[8], aq_thrd_i_ret[9], aq_thrd_i_ret[10], aq_thrd_i_ret[11], + aq_thrd_i_ret[12], aq_thrd_i_ret[13], aq_thrd_i_ret[14], aq_thrd_i_ret[15]); + + ret = mpp_enc_cfg_deinit(cfg); + if (ret) { + mpp_err("mpp_enc_cfg_deinit failed\n"); + goto DONE; + } + +DONE: + mpp_log("mpp_enc_cfg_test done %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/mpp/base/test/mpp_enc_ref_test.c b/mpp/base/test/mpp_enc_ref_test.c new file mode 100644 index 000000000..5ddf5d38a --- /dev/null +++ b/mpp/base/test/mpp_enc_ref_test.c @@ -0,0 +1,176 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_enc_ref_test" + +#include + +#include "mpp_log.h" + +#include "rk_venc_ref.h" + +int main(void) +{ + MPP_RET ret = MPP_OK; + RK_S32 lt_cnt = 0; + RK_S32 st_cnt = 0; + MppEncRefCfg ref = NULL; + MppEncRefLtFrmCfg lt_ref[4]; + MppEncRefStFrmCfg st_ref[16]; + + memset(<_ref, 0, sizeof(lt_ref)); + memset(&st_ref, 0, sizeof(st_ref)); + + mpp_log("mpp_enc_ref_test start\n"); + + ret = mpp_enc_ref_cfg_init(&ref); + + mpp_log("mpp_enc_ref_test tsvc4 ref info generation start\n"); + + lt_cnt = 1; + st_cnt = 9; + + ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt); + + /* set 8 frame lt-ref gap */ + lt_ref[0].lt_idx = 0; + lt_ref[0].temporal_id = 0; + lt_ref[0].ref_mode = REF_TO_PREV_LT_REF; + lt_ref[0].lt_gap = 8; + lt_ref[0].lt_delay = 0; + + ret = mpp_enc_ref_cfg_add_lt_cfg(ref, 1, lt_ref); + + /* set tsvc4 st-ref struct */ + /* st 0 layer 0 - ref */ + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + /* st 1 layer 3 - non-ref */ + st_ref[1].is_non_ref = 1; + st_ref[1].temporal_id = 3; + st_ref[1].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 0; + /* st 2 layer 2 - ref */ + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 2; + st_ref[2].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + /* st 3 layer 3 - non-ref */ + st_ref[3].is_non_ref = 1; + st_ref[3].temporal_id = 3; + st_ref[3].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[3].ref_arg = 0; + st_ref[3].repeat = 0; + /* st 4 layer 1 - ref */ + st_ref[4].is_non_ref = 0; + st_ref[4].temporal_id = 1; + st_ref[4].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[4].ref_arg = 0; + st_ref[4].repeat = 0; + /* st 5 layer 3 - non-ref */ + st_ref[5].is_non_ref = 1; + st_ref[5].temporal_id = 3; + st_ref[5].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[5].ref_arg = 0; + st_ref[5].repeat = 0; + /* st 6 layer 2 - ref */ + st_ref[6].is_non_ref = 0; + st_ref[6].temporal_id = 2; + st_ref[6].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[6].ref_arg = 0; + st_ref[6].repeat = 0; + /* st 7 layer 3 - non-ref */ + st_ref[7].is_non_ref = 1; + st_ref[7].temporal_id = 3; + st_ref[7].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[7].ref_arg = 0; + st_ref[7].repeat = 0; + /* st 8 layer 0 - ref */ + st_ref[8].is_non_ref = 0; + st_ref[8].temporal_id = 0; + st_ref[8].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[8].ref_arg = 0; + st_ref[8].repeat = 0; + + ret = mpp_enc_ref_cfg_add_st_cfg(ref, 9, st_ref); + + /* check and get dpb size */ + mpp_log("mpp_enc_ref_test tsvc4 ref info verification start\n"); + ret = mpp_enc_ref_cfg_check(ref); + mpp_log("mpp_enc_ref_test tsvc4 ref info verification ret %d\n", ret); + + ret = mpp_enc_ref_cfg_show(ref); + + /* reset for next config */ + ret = mpp_enc_ref_cfg_reset(ref); + +#if 0 + mpp_log("mpp_enc_ref_test smartp ref info generation start\n"); + + /* typical smartp config */ + lt_cnt = 1; + st_cnt = 3; + + ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt); + + memset(<_ref, 0, sizeof(lt_ref)); + memset(&st_ref, 0, sizeof(st_ref)); + + /* set 300 frame lt-ref gap */ + lt_ref[0].lt_idx = 0; + lt_ref[0].temporal_id = 0; + lt_ref[0].ref_mode = REF_TO_PREV_INTRA; + lt_ref[0].lt_gap = 300; + lt_ref[0].lt_delay = 0; + + ret = mpp_enc_ref_cfg_add_lt_cfg(ref, 1, lt_ref); + + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_PREV_LT_REF; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + + st_ref[1].is_non_ref = 0; + st_ref[1].temporal_id = 0; + st_ref[1].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 299; + + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 0; + st_ref[2].ref_mode = REF_TO_PREV_LT_REF; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + + ret = mpp_enc_ref_cfg_add_st_cfg(ref, 3, st_ref); + + mpp_log("mpp_enc_ref_test smartp ref info verification start\n"); + ret = mpp_enc_ref_cfg_check(ref); + mpp_log("mpp_enc_ref_test smartp ref info verification ret %d\n", ret); + + ret = mpp_enc_ref_cfg_deinit(&ref); +#endif + + mpp_log("mpp_enc_ref_test %s\n", ret ? "failed" : "success"); + + return ret; +} diff --git a/mpp/base/test/mpp_meta_test.c b/mpp/base/test/mpp_meta_test.c new file mode 100644 index 000000000..424edd392 --- /dev/null +++ b/mpp/base/test/mpp_meta_test.c @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_meta_test" + +#include + +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_meta_impl.h" + +#define TEST_MAX 200 +#define LOOP_MAX 100000 + +static MPP_RET meta_set(MppMeta meta) +{ + MPP_RET ret = MPP_OK; + + ret |= mpp_meta_set_frame(meta, KEY_INPUT_FRAME, NULL); + ret |= mpp_meta_set_packet(meta, KEY_INPUT_PACKET, NULL); + ret |= mpp_meta_set_frame(meta, KEY_OUTPUT_FRAME, NULL); + ret |= mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, NULL); + + ret |= mpp_meta_set_buffer(meta, KEY_MOTION_INFO, NULL); + ret |= mpp_meta_set_buffer(meta, KEY_HDR_INFO, NULL); + + ret |= mpp_meta_set_s32(meta, KEY_INPUT_BLOCK, 0); + ret |= mpp_meta_set_s32(meta, KEY_OUTPUT_BLOCK, 0); + ret |= mpp_meta_set_s32(meta, KEY_INPUT_IDR_REQ, 0); + ret |= mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, 0); + + ret |= mpp_meta_set_s32(meta, KEY_TEMPORAL_ID, 0); + ret |= mpp_meta_set_s32(meta, KEY_LONG_REF_IDX, 0); + ret |= mpp_meta_set_s32(meta, KEY_ENC_AVERAGE_QP, 0); + + ret |= mpp_meta_set_ptr(meta, KEY_ROI_DATA, NULL); + ret |= mpp_meta_set_ptr(meta, KEY_OSD_DATA, NULL); + ret |= mpp_meta_set_ptr(meta, KEY_OSD_DATA2, NULL); + ret |= mpp_meta_set_ptr(meta, KEY_USER_DATA, NULL); + ret |= mpp_meta_set_ptr(meta, KEY_USER_DATAS, NULL); + + ret |= mpp_meta_set_buffer(meta, KEY_QPMAP0, NULL); + ret |= mpp_meta_set_ptr(meta, KEY_NPU_UOBJ_FLAG, NULL); + + ret |= mpp_meta_set_s32(meta, KEY_ENC_MARK_LTR, 0); + ret |= mpp_meta_set_s32(meta, KEY_ENC_USE_LTR, 0); + ret |= mpp_meta_set_s32(meta, KEY_ENC_FRAME_QP, 0); + ret |= mpp_meta_set_s32(meta, KEY_ENC_BASE_LAYER_PID, 0); + + return ret; +} + +static MPP_RET meta_get(MppMeta meta) +{ + MppFrame frame; + MppPacket packet; + MppBuffer buffer; + void *ptr; + RK_S32 val; + MPP_RET ret = MPP_OK; + + ret |= mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frame); + ret |= mpp_meta_get_packet(meta, KEY_INPUT_PACKET, &packet); + ret |= mpp_meta_get_frame(meta, KEY_OUTPUT_FRAME, &frame); + ret |= mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet); + + ret |= mpp_meta_get_buffer(meta, KEY_MOTION_INFO, &buffer); + ret |= mpp_meta_get_buffer(meta, KEY_HDR_INFO, &buffer); + + ret |= mpp_meta_get_s32(meta, KEY_INPUT_BLOCK, &val); + ret |= mpp_meta_get_s32(meta, KEY_OUTPUT_BLOCK, &val); + ret |= mpp_meta_get_s32(meta, KEY_INPUT_IDR_REQ, &val); + ret |= mpp_meta_get_s32(meta, KEY_OUTPUT_INTRA, &val); + + ret |= mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &val); + ret |= mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, &val); + ret |= mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &val); + + ret |= mpp_meta_get_ptr(meta, KEY_ROI_DATA, &ptr); + ret |= mpp_meta_get_ptr(meta, KEY_OSD_DATA, &ptr); + ret |= mpp_meta_get_ptr(meta, KEY_OSD_DATA2, &ptr); + ret |= mpp_meta_get_ptr(meta, KEY_USER_DATA, &ptr); + ret |= mpp_meta_get_ptr(meta, KEY_USER_DATAS, &ptr); + + ret |= mpp_meta_get_buffer(meta, KEY_QPMAP0, &buffer); + ret |= mpp_meta_get_ptr(meta, KEY_NPU_UOBJ_FLAG, &ptr); + + ret |= mpp_meta_get_s32(meta, KEY_ENC_MARK_LTR, &val); + ret |= mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &val); + ret |= mpp_meta_get_s32(meta, KEY_ENC_FRAME_QP, &val); + ret |= mpp_meta_get_s32(meta, KEY_ENC_BASE_LAYER_PID, &val); + + return ret; +} + +void *meta_test(void *param) +{ + RK_S32 loop_max = LOOP_MAX; + RK_S64 time_start; + RK_S64 time_end; + MPP_RET ret = MPP_OK; + RK_S32 i; + + time_start = mpp_time(); + + for (i = 0; i < loop_max; i++) { + MppMeta meta = NULL; + + ret |= mpp_meta_get(&meta); + mpp_assert(meta); + + /* set */ + ret |= meta_set(meta); + /* get */ + ret |= meta_get(meta); + + ret |= mpp_meta_put(meta); + } + + time_end = mpp_time(); + + if (ret) + mpp_log("meta setting and getting, ret %d\n", ret); + + *((RK_S64 *)param) = (time_end - time_start) / loop_max; + + return NULL; +} + +int main(void) +{ + pthread_t thds[TEST_MAX]; + RK_S64 times[TEST_MAX]; + RK_S32 thd_cnt = TEST_MAX; + RK_S64 avg_time = 0; + pthread_attr_t attr; + MppMeta meta = NULL; + RK_S32 i; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + mpp_log("mpp_meta_test start\n"); + + mpp_meta_get(&meta); + if (meta) { + meta_set(meta); + mpp_meta_dump(meta); + mpp_meta_put(meta); + } + + for (i = 0; i < thd_cnt; i++) + pthread_create(&thds[i], &attr, meta_test, ×[i]); + + for (i = 0; i < thd_cnt; i++) + pthread_join(thds[i], NULL); + + for (i = 0; i < thd_cnt; i++) + avg_time += times[i]; + + mpp_log("mpp_meta_test %d threads %d loop config avg %lld us", + thd_cnt, LOOP_MAX, avg_time / thd_cnt); + + mpp_log("mpp_meta_test done\n"); + + return 0; +} diff --git a/test/mpp_packet_test.c b/mpp/base/test/mpp_packet_test.c similarity index 91% rename from test/mpp_packet_test.c rename to mpp/base/test/mpp_packet_test.c index 0ac6002be..8259ddf28 100644 --- a/test/mpp_packet_test.c +++ b/mpp/base/test/mpp_packet_test.c @@ -1,67 +1,67 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_packet_test" - -#include - -#include "mpp_log.h" -#include "mpp_packet.h" - -#define MPP_PACKET_TEST_SIZE 1024 - -int main() -{ - MPP_RET ret; - MppPacket packet = NULL; - void *data = NULL; - size_t size = MPP_PACKET_TEST_SIZE; - - mpp_log("mpp_packet_test start\n"); - - data = malloc(size); - if (NULL == data) { - mpp_err("mpp_packet_test malloc failed\n"); - goto MPP_PACKET_failed; - } - - ret = mpp_packet_init(&packet, data, size); - if (MPP_OK != ret) { - mpp_err("mpp_packet_test mpp_packet_init failed\n"); - goto MPP_PACKET_failed; - } - mpp_packet_set_eos(packet); - if (MPP_OK != ret) { - mpp_err("mpp_packet_test mpp_packet_set_eos failed\n"); - goto MPP_PACKET_failed; - } - mpp_packet_deinit(&packet); - - free(data); - mpp_log("mpp_packet_test success\n"); - return ret; - -MPP_PACKET_failed: - if (packet) - mpp_packet_deinit(&packet); - - if (data) - free(data); - - mpp_log("mpp_packet_test failed\n"); - return ret; -} - +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_packet_test" + +#include + +#include "mpp_log.h" +#include "mpp_packet.h" + +#define MPP_PACKET_TEST_SIZE 1024 + +int main(void) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + MppPacket packet = NULL; + void *data = NULL; + size_t size = MPP_PACKET_TEST_SIZE; + + mpp_log("mpp_packet_test start\n"); + + data = malloc(size); + if (NULL == data) { + mpp_err("mpp_packet_test malloc failed\n"); + goto MPP_PACKET_failed; + } + + ret = mpp_packet_init(&packet, data, size); + if (MPP_OK != ret) { + mpp_err("mpp_packet_test mpp_packet_init failed\n"); + goto MPP_PACKET_failed; + } + mpp_packet_set_eos(packet); + if (MPP_OK != ret) { + mpp_err("mpp_packet_test mpp_packet_set_eos failed\n"); + goto MPP_PACKET_failed; + } + mpp_packet_deinit(&packet); + + free(data); + mpp_log("mpp_packet_test success\n"); + return ret; + +MPP_PACKET_failed: + if (packet) + mpp_packet_deinit(&packet); + + if (data) + free(data); + + mpp_log("mpp_packet_test failed\n"); + return ret; +} + diff --git a/mpp/base/test/mpp_sys_cfg_st_test.c b/mpp/base/test/mpp_sys_cfg_st_test.c new file mode 100644 index 000000000..cb9cd809c --- /dev/null +++ b/mpp/base/test/mpp_sys_cfg_st_test.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "rk_mpp_cfg.h" +#include "mpp_sys_cfg_st.h" + +int main(void) +{ + MPP_RET ret = MPP_OK; + MppCodingType type = MPP_VIDEO_CodingHEVC; + RK_U32 width = 4096; + RK_U32 height = 2304; + + MppSysCfgStHStrd h_stride_cfg; + MppSysCfgStHByteStrd byte_stride_cfg; + MppSysCfgStVStrd v_stride_cfg; + MppSysCfgStSize size_cfg; + + + mpp_log("mpp_sys_cfg_st_test h_stride start\n"); + h_stride_cfg.type = type; + h_stride_cfg.fmt_fbc = MPP_FRAME_FBC_AFBC_V1; + h_stride_cfg.width = width; + ret = mpp_sys_cfg_st_get_h_stride(&h_stride_cfg); + mpp_log("mpp_sys_cfg_st_test result: h_stride_by_pixel(%d)", + h_stride_cfg.h_stride_by_pixel); + mpp_log("mpp_sys_cfg_st_test h_stride done %s\n", ret ? "failed" : "success"); + + + mpp_log("mpp_sys_cfg_st_test byte_stride start\n"); + byte_stride_cfg.type = type; + byte_stride_cfg.fmt_codec = MPP_FMT_YUV420SP; + byte_stride_cfg.fmt_fbc = MPP_FRAME_FBC_AFBC_V1; + byte_stride_cfg.width = width; + ret = mpp_sys_cfg_st_get_byte_stride(&byte_stride_cfg); + mpp_log("mpp_sys_cfg_st_test result: h_stride_by_byte(%d)", + byte_stride_cfg.h_stride_by_byte); + mpp_log("mpp_sys_cfg_st_test byte_stride done %s\n", ret ? "failed" : "success"); + + + mpp_log("mpp_sys_cfg_st_test v_stride_cfg start\n"); + v_stride_cfg.type = type; + v_stride_cfg.fmt_fbc = MPP_FRAME_FBC_AFBC_V1; + v_stride_cfg.height = height; + ret = mpp_sys_cfg_st_get_v_stride(&v_stride_cfg); + mpp_log("mpp_sys_cfg_st_test result: v_stride(%d)", + v_stride_cfg.v_stride); + mpp_log("mpp_sys_cfg_st_test v_stride_cfg done %s\n", ret ? "failed" : "success"); + + + mpp_log("mpp_sys_cfg_st_test size_cfg start\n"); + size_cfg.type = type; + size_cfg.fmt_codec = MPP_FMT_YUV420SP; + size_cfg.fmt_fbc = MPP_FRAME_FBC_AFBC_V1; + size_cfg.width = width; + size_cfg.height = height; + ret = mpp_sys_cfg_st_get_size(&size_cfg); + mpp_log("mpp_sys_cfg_st_test result: h_stride_by_pixel(%d)", + size_cfg.h_stride_by_pixel); + mpp_log("mpp_sys_cfg_st_test result: h_stride_by_byte(%d)", + size_cfg.h_stride_by_byte); + mpp_log("mpp_sys_cfg_st_test result: v_stride(%d)", + size_cfg.v_stride); + mpp_log("mpp_sys_cfg_st_test result: size_total(%d)", + size_cfg.size_total); + mpp_log("mpp_sys_cfg_st_test result: size_fbc_hdr(%d)", + size_cfg.size_fbc_hdr); + mpp_log("mpp_sys_cfg_st_test result: size_fbc_bdy(%d)", + size_cfg.size_fbc_bdy); + mpp_log("mpp_sys_cfg_st_test size_cfg done %s\n", ret ? "failed" : "success"); + + + return ret; +} diff --git a/mpp/base/test/mpp_sys_cfg_test.c b/mpp/base/test/mpp_sys_cfg_test.c new file mode 100644 index 000000000..5c6fb42a2 --- /dev/null +++ b/mpp/base/test/mpp_sys_cfg_test.c @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_sys_cfg_test" + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "rk_mpp_cfg.h" +#include "mpp_sys_cfg.h" + +int main(void) +{ + MPP_RET ret = MPP_OK; + MppSysCfg cfg; + RK_S64 end = 0; + RK_S64 start = 0; + MppCodingType type = MPP_VIDEO_CodingHEVC; + RK_U32 width = 4096; + RK_U32 height = 2304; + RK_U32 h_stride_by_byte; + RK_U32 h_stride_by_pixel; + RK_U32 v_stride; + RK_U32 size_total; + RK_U32 size_fbc_hdr; + RK_U32 size_fbc_bdy; + + mpp_sys_cfg_show(); + + mpp_log("mpp_sys_cfg_test start\n"); + + start = mpp_time(); + + ret = mpp_sys_cfg_get(&cfg); + if (ret) { + mpp_err("mpp_sys_cfg_get failed\n"); + goto DONE; + } + + /* set correct parameter */ + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:type", 1); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:enable", 1); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:type", type); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_codec", MPP_FMT_YUV420SP); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:fmt_fbc", MPP_FRAME_FBC_AFBC_V1); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:width", width); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:height", height); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:h_stride_by_byte", 0); + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:h_stride_by_pixel", 0); + + /* try get readonly parameter */ + ret = mpp_sys_cfg_set_u32(cfg, "dec_buf_chk:cap_fbc", 1); + if (!ret) { + mpp_log("set readonly success, should be a failure\n"); + goto DONE; + } + + /* get result */ + mpp_sys_cfg_ioctl(cfg); + + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:h_stride_by_byte", &h_stride_by_byte); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:h_stride_by_pixel", &h_stride_by_pixel); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:v_stride", &v_stride); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:size_total", &size_total); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:size_fbc_hdr", &size_fbc_hdr); + ret = mpp_sys_cfg_get_u32(cfg, "dec_buf_chk:size_fbc_bdy", &size_fbc_bdy); + + ret = mpp_sys_cfg_put(cfg); + if (ret) { + mpp_err("mpp_sys_cfg_put failed\n"); + goto DONE; + } + + end = mpp_time(); + mpp_log("set u32 time %lld us\n", end - start); + +DONE: + mpp_log("mpp_sys_cfg_test done %s\n", ret ? "failed" : "success"); + return ret; +} diff --git a/mpp/base/test/mpp_task_test.c b/mpp/base/test/mpp_task_test.c new file mode 100644 index 000000000..45d82f853 --- /dev/null +++ b/mpp/base/test/mpp_task_test.c @@ -0,0 +1,252 @@ +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_thread.h" + +#include "mpp_task.h" +#include "mpp_task_impl.h" + +#define MAX_TASK_LOOP 10000 + +static MppTaskQueue input = NULL; +static MppTaskQueue output = NULL; + +void *task_input(void *arg) +{ + RK_S32 i; + MppTask task = NULL; + MPP_RET ret = MPP_OK; + MppPort port = mpp_task_queue_get_port(input, MPP_PORT_INPUT); + MppFrame frm; + + mpp_frame_init(&frm); + + for (i = 0; i < MAX_TASK_LOOP; i++) { + ret = mpp_port_poll(port, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port, task); + mpp_assert(!ret); + } + + mpp_frame_deinit(&frm); + + (void)arg; + return NULL; +} + +void *task_output(void *arg) +{ + RK_S32 i; + MppTask task = NULL; + MPP_RET ret = MPP_OK; + MppPort port = mpp_task_queue_get_port(output, MPP_PORT_OUTPUT); + MppPacket pkt; + + mpp_packet_init(&pkt, NULL, 0); + + for (i = 0; i < MAX_TASK_LOOP; i++) { + ret = mpp_port_poll(port, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port, task); + mpp_assert(!ret); + } + + mpp_packet_deinit(&pkt); + + (void)arg; + return NULL; +} + +void *task_in_and_out(void *arg) +{ + RK_S32 i; + MppTask task = NULL; + MPP_RET ret = MPP_OK; + MppPort port_input = mpp_task_queue_get_port(input, MPP_PORT_INPUT); + MppPort port_output = mpp_task_queue_get_port(output, MPP_PORT_OUTPUT); + + for (i = 0; i < MAX_TASK_LOOP; i++) { + ret = mpp_port_poll(port_input, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_input, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_input, task); + mpp_assert(!ret); + + + ret = mpp_port_poll(port_output, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_output, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_output, task); + mpp_assert(!ret); + } + + (void)arg; + return NULL; +} + +void *task_worker(void *arg) +{ + RK_S32 i; + MppTask task = NULL; + MPP_RET ret = MPP_OK; + MppPort port_src = mpp_task_queue_get_port(input, MPP_PORT_OUTPUT); + MppPort port_dst = mpp_task_queue_get_port(output, MPP_PORT_INPUT); + + for (i = 0; i < MAX_TASK_LOOP; i++) { + ret = mpp_port_poll(port_src, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_src, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_src, task); + mpp_assert(!ret); + + ret = mpp_port_poll(port_dst, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_dst, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_dst, task); + mpp_assert(!ret); + } + + (void)arg; + return NULL; +} + +void serial_task(void) +{ + RK_S32 i; + MppTask task = NULL; + MPP_RET ret = MPP_OK; + MppPort port_ii = mpp_task_queue_get_port(input, MPP_PORT_INPUT); + MppPort port_io = mpp_task_queue_get_port(input, MPP_PORT_OUTPUT); + MppPort port_oi = mpp_task_queue_get_port(output, MPP_PORT_INPUT); + MppPort port_oo = mpp_task_queue_get_port(output, MPP_PORT_OUTPUT); + + for (i = 0; i < MAX_TASK_LOOP; i++) { + ret = mpp_port_poll(port_ii, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_ii, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_ii, task); + mpp_assert(!ret); + + + ret = mpp_port_poll(port_io, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_io, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_io, task); + mpp_assert(!ret); + + + ret = mpp_port_poll(port_oi, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_oi, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_oi, task); + mpp_assert(!ret); + + + ret = mpp_port_poll(port_oo, MPP_POLL_BLOCK); + mpp_assert(ret >= 0); + + ret = mpp_port_dequeue(port_oo, &task); + mpp_assert(!ret); + mpp_assert(task); + + ret = mpp_port_enqueue(port_oo, task); + mpp_assert(!ret); + } +} + +int main(void) +{ + RK_S64 time_start, time_end; + + pthread_t thread_input; + pthread_t thread_output; + pthread_t thread_in_and_out; + pthread_t thread_worker; + pthread_attr_t attr; + void *dummy; + + mpp_log("mpp task test start\n"); + + mpp_task_queue_init(&input, NULL, "test_input"); + mpp_task_queue_init(&output, NULL, "test_output"); + mpp_task_queue_setup(input, 4); + mpp_task_queue_setup(output, 4); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + mpp_debug = MPP_DBG_TIMING; + + time_start = mpp_time(); + pthread_create(&thread_input, &attr, task_input, NULL); + pthread_create(&thread_output, &attr, task_output, NULL); + pthread_create(&thread_worker, &attr, task_worker, NULL); + + pthread_join(thread_input, &dummy); + pthread_join(thread_worker, &dummy); + pthread_join(thread_output, &dummy); + time_end = mpp_time(); + mpp_time_diff(time_start, time_end, 0, "3 thread test"); + + time_start = mpp_time(); + pthread_create(&thread_in_and_out, &attr, task_in_and_out, NULL); + pthread_create(&thread_worker, &attr, task_worker, NULL); + + pthread_join(thread_in_and_out, &dummy); + pthread_join(thread_worker, &dummy); + time_end = mpp_time(); + mpp_time_diff(time_start, time_end, 0, "2 thread test"); + pthread_attr_destroy(&attr); + + time_start = mpp_time(); + serial_task(); + time_end = mpp_time(); + mpp_time_diff(time_start, time_end, 0, "1 thread test"); + + mpp_debug = 0; + + mpp_task_queue_deinit(input); + mpp_task_queue_deinit(output); + + mpp_log("mpp task test done\n"); + + return 0; +} + diff --git a/mpp/base/test/mpp_trie_test.c b/mpp/base/test/mpp_trie_test.c new file mode 100644 index 000000000..176db4e05 --- /dev/null +++ b/mpp/base/test/mpp_trie_test.c @@ -0,0 +1,121 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_trie_test" + +#include + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "mpp_trie.h" + +typedef void *(*TestProc)(void *, RK_S64 time); + +typedef struct TestAction_t { + const char *name; + void *ctx; + TestProc proc; +} TestAction; + +typedef struct TestCase_t { + const char *name; + MPP_RET ret; +} TestCase; + +void *print_opt(void *ctx, RK_S64 time) +{ + RK_U8 **str = (RK_U8 **)ctx; + + if (str && *str) + mpp_log("get option %-16s time %lld us\n", *str, time); + + return NULL; +} + +TestAction test_info[] = { + { "rc:mode", &test_info[0], print_opt}, + { "rc:bps_target", &test_info[1], print_opt}, + { "rc:bps_max", &test_info[2], print_opt}, + { "rc:bps_min", &test_info[3], print_opt}, + /* test valid info end in the middle */ + { "rc:bps", &test_info[4], print_opt}, +}; + +TestCase test_case[] = { + { "rc:mode", MPP_OK, }, + { "rc:bps_target", MPP_OK, }, + { "rc:bps_max", MPP_OK, }, + { "rc:bps", MPP_OK, }, + { "this is an error string", MPP_NOK, }, + { "", MPP_NOK, }, +}; + +int main(void) +{ + MppTrie trie = NULL; + RK_S32 i; + RK_S64 end = 0; + RK_S64 start = 0; + RK_S32 info_cnt = MPP_ARRAY_ELEMS(test_info); + RK_S32 ret = MPP_OK; + + mpp_log("mpp_trie_test start\n"); + + mpp_trie_init(&trie, "test_trie"); + + start = mpp_time(); + for (i = 0; i < info_cnt; i++) + mpp_trie_add_info(trie, test_info[i].name, &test_info[i], sizeof(test_info[i])); + end = mpp_time(); + mpp_log("add act time %lld us\n", end - start); + + ret = mpp_trie_add_info(trie, NULL, NULL, 0); + if (ret) { + mpp_loge("mpp_trie_add_info last failed\n"); + goto DONE; + } + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(test_case); i++) { + MppTrieInfo *info = NULL; + TestAction *act = NULL; + const char *name = test_case[i].name; + + start = mpp_time(); + info = mpp_trie_get_info(trie, name); + end = mpp_time(); + + if (info) + act = (TestAction *)mpp_trie_info_ctx(info); + + if (act && act->proc) + act->proc(act->ctx, end - start); + else + mpp_loge("search %s failed time %lld us\n", name, end - start); + + ret |= ((info && !test_case[i].ret) || + (!info && test_case[i].ret)) ? MPP_OK : MPP_NOK; + } + + mpp_trie_deinit(trie); + +DONE: + mpp_log("mpp_trie_test ret %s\n", ret ? "failed" : "success"); + + return ret; +} diff --git a/mpp/codec/CMakeLists.txt b/mpp/codec/CMakeLists.txt index e48a40395..2f98ecfec 100644 --- a/mpp/codec/CMakeLists.txt +++ b/mpp/codec/CMakeLists.txt @@ -4,20 +4,57 @@ # add mpp_dec implement # ---------------------------------------------------------------------------- add_library(mpp_codec STATIC - mpp_buf_slot.cpp - mpp_enc.cpp - mpp_dec.cpp - mpp_parser.cpp + mpp_enc_impl.c + mpp_enc_v2.c + enc_impl.c + mpp_dec_no_thread.c + mpp_dec_normal.c + mpp_dec.c + mpp_parser.c ) -set_target_properties(mpp_codec PROPERTIES FOLDER "mpp/codec") + +add_library(mpp_rc OBJECT mpp_rc.c) add_subdirectory(dec) add_subdirectory(enc) -target_link_libraries(mpp_codec - codec_h264d - codec_dummy_enc - codec_dummy_dec - mpp) +add_subdirectory(rc) + +merge_objects("${CODEC_MPEG2D}" mpeg2d_api) +merge_objects("${CODEC_MPEG4D}" mpeg4d_api) +merge_objects("${CODEC_H263D}" h263d_api) +merge_objects("${CODEC_H264D}" h264d_api) +merge_objects("${CODEC_H265D}" h265d_api) +merge_objects("${CODEC_VP8D}" vp8d_api) +merge_objects("${CODEC_VP9D}" vp9d_api) +merge_objects("${CODEC_AV1D}" av1d_api) +merge_objects("${CODEC_AVSD}" avsd_api) +merge_objects("${CODEC_AVS2D}" avs2d_api) +merge_objects("${CODEC_JPEGD}" jpegd_api) +merge_objects("${CODEC_H264E}" h264e_api) +merge_objects("${CODEC_H265E}" h265e_api) +merge_objects("${CODEC_JPEGE}" jpege_api) +merge_objects("${CODEC_VP8E}" vp8e_api) + +target_link_libraries(mpp_codec + mpp_rc + enc_rc + ${CODEC_AVSD} + ${CODEC_AVS2D} + ${CODEC_H263D} + ${CODEC_H264D} + ${CODEC_H265D} + ${CODEC_MPEG2D} + ${CODEC_MPEG4D} + ${CODEC_VP8D} + ${CODEC_VP9D} + ${CODEC_JPEGD} + ${CODEC_AV1D} + ${CODEC_H264E} + ${CODEC_H265E} + ${CODEC_JPEGE} + ${CODEC_VP8E} + dec_common + ) diff --git a/mpp/codec/dec/CMakeLists.txt b/mpp/codec/dec/CMakeLists.txt index fbee3459d..250b72b61 100644 --- a/mpp/codec/dec/CMakeLists.txt +++ b/mpp/codec/dec/CMakeLists.txt @@ -1,9 +1,47 @@ # vim: syntax=cmake -add_subdirectory(dummy) +add_subdirectory(common) -add_subdirectory(h264) +if( HAVE_AVSD ) + add_subdirectory(avs) +endif() -add_subdirectory(h265) +if( HAVE_AVS2D ) + add_subdirectory(avs2) +endif() -add_subdirectory(vp9) +if( HAVE_H263D ) + add_subdirectory(h263) +endif() + +if( HAVE_H264D ) + add_subdirectory(h264) +endif() + +if( HAVE_H265D ) + add_subdirectory(h265) +endif() + +if( HAVE_MPEG2D ) + add_subdirectory(m2v) +endif() + +if( HAVE_MPEG4D ) + add_subdirectory(mpg4) +endif() + +if( HAVE_VP8D ) + add_subdirectory(vp8) +endif() + +if( HAVE_VP9D ) + add_subdirectory(vp9) +endif() + +if( HAVE_JPEGD ) + add_subdirectory(jpeg) +endif() + +if( HAVE_AV1D ) + add_subdirectory(av1) +endif() diff --git a/mpp/codec/dec/av1/CMakeLists.txt b/mpp/codec/dec/av1/CMakeLists.txt new file mode 100644 index 000000000..b8d53fd56 --- /dev/null +++ b/mpp/codec/dec/av1/CMakeLists.txt @@ -0,0 +1,10 @@ +# vim: syntax=cmake +include_directories(.) + +# av1 decoder sourse +add_library(av1d_api OBJECT + av1d_api.c + av1d_parser.c + av1d_codec.c + av1d_entropy.c + ) diff --git a/mpp/codec/dec/av1/av1d_api.c b/mpp/codec/dec/av1/av1d_api.c new file mode 100644 index 000000000..fd9e08695 --- /dev/null +++ b/mpp/codec/dec/av1/av1d_api.c @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "av1d_api" + +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_packet_impl.h" + +#include "mpp_parser.h" +#include "av1d_ctx.h" +#include "av1d_parser.h" + +/*! + *********************************************************************** + * \brief + * free all buffer + *********************************************************************** + */ +MPP_RET av1d_deinit(void *ctx) +{ + Av1DecCtx *av1_ctx = (Av1DecCtx *)ctx; + + if (av1_ctx) { + av1d_parser_deinit(av1_ctx); + if (av1_ctx->pkt) { + RK_U8 *buf; + + buf = mpp_packet_get_data(av1_ctx->pkt); + MPP_FREE(buf); + mpp_packet_deinit(&av1_ctx->pkt); + } + } + + return MPP_OK; +} + +/*! + *********************************************************************** + * \brief + * alloc all buffer + *********************************************************************** + */ +MPP_RET av1d_init(void *ctx, ParserCfg *init) +{ + Av1DecCtx *av1_ctx = (Av1DecCtx *)ctx; + RK_U8 *buf = NULL; + RK_S32 size = SZ_512K; + MPP_RET ret = MPP_OK; + + if (!av1_ctx || !init) { + mpp_err("av1d init fail"); + return MPP_ERR_NULL_PTR; + } + + av1_ctx->pix_fmt = MPP_FMT_BUTT; + av1_ctx->usr_set_fmt = MPP_FMT_BUTT; + + if ((ret = av1d_parser_init(av1_ctx, init)) != MPP_OK) + goto _err_exit; + + buf = mpp_malloc(RK_U8, size); + if (!buf) { + mpp_err("av1d init malloc stream buffer fail"); + ret = MPP_ERR_NOMEM; + goto _err_exit; + } + + if ((ret = mpp_packet_init(&av1_ctx->pkt, (void *)buf, size)) != MPP_OK) + goto _err_exit; + + av1_ctx->stream_data = buf; + av1_ctx->stream_size = size; + mpp_packet_set_size(av1_ctx->pkt, size); + mpp_packet_set_length(av1_ctx->pkt, 0); + + return ret; + +_err_exit: + av1d_deinit(av1_ctx); + return ret; +} + +/*! + *********************************************************************** + * \brief + * reset + *********************************************************************** + */ +MPP_RET av1d_reset(void *ctx) +{ + Av1DecCtx *av1_ctx = (Av1DecCtx *)ctx; + + return av1d_paser_reset(av1_ctx); +} + +/*! + *********************************************************************** + * \brief + * flush + *********************************************************************** + */ +MPP_RET av1d_flush(void *ctx) +{ + (void)ctx; + + return MPP_OK; +} + +/*! + *********************************************************************** + * \brief + * prepare + *********************************************************************** + */ +MPP_RET av1d_prepare(void *ctx, MppPacket pkt, HalDecTask *task) +{ + Av1DecCtx *av1_ctx = (Av1DecCtx *)ctx; + Av1Codec *s = (Av1Codec *)av1_ctx->priv_data; + RK_S64 pts = mpp_packet_get_pts(pkt); + RK_S64 dts = mpp_packet_get_dts(pkt); + RK_U8 *buf = NULL; + RK_S32 length = (RK_S32)mpp_packet_get_length(pkt); + RK_U8 *out_data = NULL; + RK_S32 out_size = -1; + RK_S32 consumed = 0; + RK_U8 *pos = NULL; + RK_U32 need_split = av1_ctx->cfg->base.split_parse; + MPP_RET ret = MPP_OK; + + need_split = 1; + task->valid = 0; + av1_ctx->is_new_frame = 0; + + buf = pos = mpp_packet_get_pos(pkt); + if (mpp_packet_get_flag(pkt)& MPP_PACKET_FLAG_EXTRA_DATA) { + s->extra_has_frame = 0; + task = NULL; + s->current_obu.data = buf; + s->current_obu.data_size = length; + ret = av1d_parser_fragment_header(&s->current_obu); + if (ret < 0) { + return ret; + } + ret = av1d_get_fragment_units(&s->current_obu); + if (ret < 0) { + return ret; + } + ret = av1d_read_fragment_uints(s, &s->current_obu); + if (ret < 0) { + return ret; + } + if (!s->seq_header) { + goto end; + } + ret = av1d_set_context_with_seq(av1_ctx, s->seq_header); + end: + pos = buf + length; + mpp_packet_set_pos(pkt, pos); + av1d_fragment_reset(&s->current_obu); + return ret; + } + + if (need_split) { + consumed = av1d_split_frame(av1_ctx, &out_data, &out_size, buf, length); + } else { + out_size = consumed = length; + av1_ctx->is_new_frame = 1; + } + + pos += (consumed >= 0) ? consumed : length; + + mpp_packet_set_pos(pkt, pos); + mpp_packet_set_length(pkt, length - consumed); + if (!mpp_packet_get_length(pkt)) + av1_ctx->eos = mpp_packet_get_eos(pkt); + av1d_dbg(AV1D_DBG_STRMIN, "pkt_len=%d, pts=%lld , out_size %d consumed %d new frame %d eos %d\n", + length, pts, out_size, consumed, av1_ctx->is_new_frame, av1_ctx->eos); + if (out_size > 0) { + av1d_get_frame_stream(av1_ctx, buf, consumed); + task->input_packet = av1_ctx->pkt; + mpp_packet_set_pts(av1_ctx->pkt, pts); + mpp_packet_set_dts(av1_ctx->pkt, dts); + } else { + task->valid = 0; + if (av1_ctx->eos) + task->input_packet = av1_ctx->pkt; + } + if (av1_ctx->eos && !mpp_packet_get_length(pkt)) + task->flags.eos = av1_ctx->eos; + + if (av1_ctx->is_new_frame || (task->flags.eos)) { + if (av1_ctx->stream_offset > 0) + task->valid = 1; + av1_ctx->stream_offset = 0; + } + + return ret = MPP_OK; +} + +/*! + *********************************************************************** + * \brief + * parser + *********************************************************************** + */ +MPP_RET av1d_parser(void *ctx, HalDecTask *in_task) +{ + Av1DecCtx *av1_ctx = (Av1DecCtx *)ctx; + + av1d_parser_frame(av1_ctx, in_task); + return MPP_OK; +} + +/*! + *********************************************************************** + * \brief + * control + *********************************************************************** + */ +MPP_RET av1d_control(void *ctx, MpiCmd cmd, void *param) +{ + Av1DecCtx *av1_ctx = (Av1DecCtx *)ctx; + MPP_RET ret = MPP_OK; + + if (!ctx) + return MPP_ERR_VALUE; + + switch (cmd) { + case MPP_DEC_SET_OUTPUT_FORMAT : { + av1_ctx->usr_set_fmt = param ? *((MppFrameFormat *)param) : MPP_FMT_YUV420SP; + } break; + default : { + } break; + } + + return ret; +} + +/*! + *********************************************************************** + * \brief + * callback + *********************************************************************** + */ +MPP_RET av1d_callback(void *decoder, void *info) +{ + Av1DecCtx *av1_ctx = (Av1DecCtx *)decoder; + + av1d_parser_update(av1_ctx, info); + + return MPP_OK; +} + +/*! + *********************************************************************** + * \brief + * api struct interface + *********************************************************************** + */ +static const ParserApi mpp_av1d = { + .name = "av1d_parse", + .coding = MPP_VIDEO_CodingAV1, + .ctx_size = sizeof(Av1DecCtx), + .flag = 0, + .init = av1d_init, + .deinit = av1d_deinit, + .prepare = av1d_prepare, + .parse = av1d_parser, + .reset = av1d_reset, + .flush = av1d_flush, + .control = av1d_control, + .callback = av1d_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_av1d); diff --git a/mpp/codec/dec/av1/av1d_codec.c b/mpp/codec/dec/av1/av1d_codec.c new file mode 100644 index 000000000..1bc223a84 --- /dev/null +++ b/mpp/codec/dec/av1/av1d_codec.c @@ -0,0 +1,2663 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "av1d_codec" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_bitread.h" +#include "mpp_bitwrite.h" +#include "rk_hdr_meta_com.h" + +#include "av1d_parser.h" + +#ifndef UINT32_MAX +#define UINT32_MAX 0xFFFFFFFF +#endif + +#ifndef INT_MAX +#define INT_MAX 2147483647 /* maximum (signed) RK_S32 value */ +#endif + +#define BUFFER_PADDING_SIZE 64 + +static MPP_RET read_ns(BitReadCtx_t *gb, RK_U32 n, RK_U32 *out_val) +{ + RK_U32 w = mpp_log2(n) + 1; + RK_S32 m = (1 << w) - n; + RK_S32 value = 0; + RK_S32 v; + + if (w - 1 > 0) + READ_BITS(gb, w - 1, &v); + else + v = 0; + + if (v < m) { + value = v; + } else { + RK_S32 extra_bit; + READ_ONEBIT(gb, &extra_bit); + value = (v << 1) - m + extra_bit; + } + + *out_val = value; + return MPP_OK; + +__BITREAD_ERR: + return MPP_NOK; + +} + +/* + * Reads an incrementally encoded value from the bitstream using a unary coding variant. + * The function reads consecutive 1 bits from the bitstream, incrementing a value starting + * from range_min, until a 0 bit is encountered or the value reaches range_max. + */ +static MPP_RET read_increment(BitReadCtx_t *gb, RK_U32 range_min, + RK_U32 range_max, RK_U32 *out_val) +{ + RK_U32 value = range_min; + RK_S32 tmp; + + while (value < range_max) { + mpp_read_bits(gb, 1, &tmp); + if (!tmp) break; + value++; + } + + *out_val = value; + return MPP_OK; +} + +static MPP_RET read_signed_subexp(BitReadCtx_t *gb, RK_U32 range_max, RK_U32 *out_val) +{ + RK_U32 max_len = mpp_log2(range_max - 1) - 3; + RK_U32 value = 0; + RK_U32 len, range_offset, range_bits; + + read_increment(gb, 0, max_len, &len); + if (len) { + range_bits = 2 + len; + range_offset = 1 << range_bits; + } else { + range_bits = 3; + range_offset = 0; + } + + if (len < max_len) { + READ_BITS_LONG(gb, range_bits, &value); + } else { + MPP_RET ret = read_ns(gb, range_max - range_offset, &value); + + if (ret < 0) + return ret; + } + value += range_offset; + + *out_val = value; + return MPP_OK; +__BITREAD_ERR: + return MPP_NOK; +} + +RK_S32 av1d_get_relative_dist(const AV1SeqHeader *seq, RK_U32 a, RK_U32 b) +{ + RK_U32 diff = 0; + + if (seq->enable_order_hint) { + RK_U32 m = 1 << seq->order_hint_bits_minus_1; + + diff = a - b; + diff = (diff & (m - 1)) - (diff & m); + } + return diff; +} + +static MPP_RET read_leb128(BitReadCtx_t *gb, RK_U64 *out_value) +{ + RK_U64 value = 0; + RK_S32 byte = 0; + RK_S32 i; + + for (i = 0; i < 8; i++) { // kMaximumLeb128Size = 8 + READ_BITS(gb, 8, &byte); + value |= (RK_U64)(byte & 0x7f) << (i * 7); + if (!(byte & 0x80)) + break; + } + // Fail on values larger than 32-bits to ensure consistent behavior on + // 32 and 64 bit targets: value is typically used to determine buffer + // allocation size. + if (value > UINT32_MAX) + return MPP_NOK; + + *out_value = value; + return MPP_OK; + +__BITREAD_ERR: + return MPP_NOK; +} + +MPP_RET av1d_read_obu_header(BitReadCtx_t *gb, AV1OBUHeader *hdr) +{ + READ_ONEBIT(gb, &hdr->obu_forbidden_bit); + READ_BITS(gb, 4, &hdr->obu_type); + READ_ONEBIT(gb, &hdr->obu_extension_flag); + READ_ONEBIT(gb, &hdr->obu_has_size_field); + READ_ONEBIT(gb, &hdr->obu_reserved_1bit); + + if (hdr->obu_extension_flag) { + READ_BITS(gb, 3, &hdr->temporal_id); + READ_BITS(gb, 2, &hdr->spatial_id); + READ_BITS(gb, 3, &hdr->extension_header_reserved_3bits); + } else { + hdr->temporal_id = 0; + hdr->spatial_id = 0; + } + + if (hdr->obu_has_size_field) + read_leb128(gb, &hdr->obu_filed_size); + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_color_config(Av1Codec *ctx, BitReadCtx_t *gb, + AV1ColorConfig *cfg, RK_S32 seq_profile) +{ + READ_ONEBIT(gb, &cfg->high_bitdepth); + + if (seq_profile == AV1_PROFILE_PROFESSIONAL && + cfg->high_bitdepth) { + READ_ONEBIT(gb, &cfg->twelve_bit); + ctx->bit_depth = cfg->twelve_bit ? 12 : 10; + } else { + ctx->bit_depth = cfg->high_bitdepth ? 10 : 8; + } + + if (seq_profile == AV1_PROFILE_HIGH) + cfg->mono_chrome = 0; + else + READ_ONEBIT(gb, &cfg->mono_chrome); + ctx->num_planes = cfg->mono_chrome ? 1 : 3; + + READ_ONEBIT(gb, &cfg->color_description_present_flag); + if (cfg->color_description_present_flag) { + READ_BITS(gb, 8, &cfg->color_primaries); + READ_BITS(gb, 8, &cfg->transfer_characteristics); + READ_BITS(gb, 8, &cfg->matrix_coefficients); + if (cfg->transfer_characteristics == MPP_FRAME_TRC_BT2020_10 || + cfg->transfer_characteristics == MPP_FRAME_TRC_SMPTEST2084) + ctx->is_hdr = 1; + } else { + cfg->color_primaries = MPP_FRAME_PRI_UNSPECIFIED; + cfg->transfer_characteristics = MPP_FRAME_TRC_UNSPECIFIED; + cfg->matrix_coefficients = MPP_FRAME_SPC_UNSPECIFIED; + } + + if (cfg->mono_chrome) { + READ_ONEBIT(gb, &cfg->color_range); + + cfg->subsampling_x = 1; + cfg->subsampling_y = 1; + cfg->chroma_sample_position = AV1_CSP_UNKNOWN; + cfg->separate_uv_delta_q = 0; + + } else if (cfg->color_primaries == MPP_FRAME_PRI_BT709 && + cfg->transfer_characteristics == MPP_FRAME_TRC_IEC61966_2_1 && + cfg->matrix_coefficients == MPP_FRAME_SPC_RGB) { + cfg->color_range = 1; + cfg->subsampling_x = 0; + cfg->subsampling_y = 0; + READ_ONEBIT(gb, &cfg->separate_uv_delta_q); + + } else { + READ_ONEBIT(gb, &cfg->color_range); + + if (seq_profile == AV1_PROFILE_MAIN) { + cfg->subsampling_x = 1; + cfg->subsampling_y = 1; + } else if (seq_profile == AV1_PROFILE_HIGH) { + cfg->subsampling_x = 0; + cfg->subsampling_y = 0; + } else { + if (ctx->bit_depth == 12) { + READ_ONEBIT(gb, &cfg->subsampling_x); + if (cfg->subsampling_x) + READ_ONEBIT(gb, &cfg->subsampling_y); + else + cfg->subsampling_y = 0; + } else { + cfg->subsampling_x = 1; + cfg->subsampling_y = 0; + } + } + if (cfg->subsampling_x && cfg->subsampling_y) { + READ_BITS(gb, 2, &cfg->chroma_sample_position); + } + + READ_ONEBIT(gb, &cfg->separate_uv_delta_q); + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_timing_info(Av1Codec *ctx, BitReadCtx_t *gb, + AV1TimingInfo *info) +{ + READ_BITS_LONG(gb, 32, &info->num_units_in_display_tick); + READ_BITS_LONG(gb, 32, &info->time_scale); + + READ_ONEBIT(gb, &info->equal_picture_interval); + if (info->equal_picture_interval) + READ_UE(gb, &info->num_ticks_per_picture_minus_1); + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_model_info(Av1Codec *ctx, BitReadCtx_t *gb, + AV1DecoderModelInfo *info) +{ + READ_BITS(gb, 5, &info->buffer_delay_length_minus_1); + READ_BITS_LONG(gb, 32, &info->num_units_in_decoding_tick); + READ_BITS(gb, 5, &info->buffer_removal_time_length_minus_1); + READ_BITS(gb, 5, &info->frame_presentation_time_length_minus_1); + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_sequence_header_obu(Av1Codec *ctx, BitReadCtx_t *gb, + AV1SeqHeader *seq) +{ + RK_S32 i; + + READ_BITS(gb, 3, &seq->seq_profile); + READ_ONEBIT(gb, &seq->still_picture); + READ_ONEBIT(gb, &seq->reduced_still_picture_header); + + if (seq->reduced_still_picture_header) { + seq->timing_info_present_flag = 0; + seq->decoder_model_info_present_flag = 0; + seq->initial_display_delay_present_flag = 0; + seq->operating_points_cnt_minus_1 = 0; + seq->operating_point_idc[0] = 0; + + READ_BITS(gb, 5, &seq->seq_level_idx[0]); + + seq->seq_tier[0] = 0; + seq->decoder_model_present_for_this_op[0] = 0; + seq->initial_display_delay_present_for_this_op[0] = 0; + + } else { + READ_ONEBIT(gb, &seq->timing_info_present_flag); + if (seq->timing_info_present_flag) { + FUN_CHECK(read_timing_info(ctx, gb, &seq->timing_info)); + + READ_ONEBIT(gb, &seq->decoder_model_info_present_flag); + if (seq->decoder_model_info_present_flag) { + FUN_CHECK(read_model_info(ctx, gb, &seq->decoder_model_info)); + } + } else { + seq->decoder_model_info_present_flag = 0; + } + + READ_ONEBIT(gb, &seq->initial_display_delay_present_flag); + + READ_BITS(gb, 5, &seq->operating_points_cnt_minus_1); + for (i = 0; i <= seq->operating_points_cnt_minus_1; i++) { + READ_BITS(gb, 12, &seq->operating_point_idc[i]); + READ_BITS(gb, 5, &seq->seq_level_idx[i]); + + if (seq->seq_level_idx[i] > 7) + READ_ONEBIT(gb, &seq->seq_tier[i]); + else + seq->seq_tier[i] = 0; + + if (seq->decoder_model_info_present_flag) { + READ_ONEBIT(gb, &seq->decoder_model_present_for_this_op[i]); + if (seq->decoder_model_present_for_this_op[i]) { + RK_S32 n = seq->decoder_model_info.buffer_delay_length_minus_1 + 1; + READ_BITS_LONG(gb, n, &seq->decoder_buffer_delay[i]); + READ_BITS_LONG(gb, n, &seq->encoder_buffer_delay[i]); + READ_ONEBIT(gb, &seq->low_delay_mode_flag[i]); + } + } else { + seq->decoder_model_present_for_this_op[i] = 0; + } + + if (seq->initial_display_delay_present_flag) { + READ_ONEBIT(gb, &seq->initial_display_delay_present_for_this_op[i]); + if (seq->initial_display_delay_present_for_this_op[i]) + READ_BITS(gb, 4, &seq->initial_display_delay_minus_1[i]); + } + } + } + + READ_BITS(gb, 4, &seq->frame_width_bits_minus_1); + READ_BITS(gb, 4, &seq->frame_height_bits_minus_1); + + READ_BITS_LONG(gb, seq->frame_width_bits_minus_1 + 1, &seq->max_frame_width_minus_1); + READ_BITS_LONG(gb, seq->frame_height_bits_minus_1 + 1, &seq->max_frame_height_minus_1); + + if (seq->reduced_still_picture_header) + seq->frame_id_numbers_present_flag = 0; + else + READ_ONEBIT(gb, &seq->frame_id_numbers_present_flag); + if (seq->frame_id_numbers_present_flag) { + READ_BITS(gb, 4, &seq->delta_frame_id_length_minus_2); + READ_BITS(gb, 3, &seq->additional_frame_id_length_minus_1); + } + + READ_ONEBIT(gb, &seq->use_128x128_superblock); + READ_ONEBIT(gb, &seq->enable_filter_intra); + READ_ONEBIT(gb, &seq->enable_intra_edge_filter); + + if (seq->reduced_still_picture_header) { + seq->enable_interintra_compound = 0; + seq->enable_masked_compound = 0; + seq->enable_warped_motion = 0; + seq->enable_dual_filter = 0; + seq->enable_order_hint = 0; + seq->enable_jnt_comp = 0; + seq->enable_ref_frame_mvs = 0; + seq->seq_force_screen_content_tools = AV1_SELECT_SCREEN_CONTENT_TOOLS; + seq->seq_force_integer_mv = AV1_SELECT_INTEGER_MV; + } else { + READ_ONEBIT(gb, &seq->enable_interintra_compound); + READ_ONEBIT(gb, &seq->enable_masked_compound); + READ_ONEBIT(gb, &seq->enable_warped_motion); + READ_ONEBIT(gb, &seq->enable_dual_filter); + + READ_ONEBIT(gb, &seq->enable_order_hint); + if (seq->enable_order_hint) { + READ_ONEBIT(gb, &seq->enable_jnt_comp); + READ_ONEBIT(gb, &seq->enable_ref_frame_mvs); + } else { + seq->enable_jnt_comp = 0; + seq->enable_ref_frame_mvs = 0; + } + + READ_ONEBIT(gb, &seq->seq_choose_screen_content_tools); + if (seq->seq_choose_screen_content_tools) + seq->seq_force_screen_content_tools = AV1_SELECT_SCREEN_CONTENT_TOOLS; + else + READ_ONEBIT(gb, &seq->seq_force_screen_content_tools); + if (seq->seq_force_screen_content_tools > 0) { + READ_ONEBIT(gb, &seq->seq_choose_integer_mv); + if (seq->seq_choose_integer_mv) + seq->seq_force_integer_mv = AV1_SELECT_INTEGER_MV; + else + READ_ONEBIT(gb, &seq->seq_force_integer_mv); + } else { + seq->seq_force_integer_mv = AV1_SELECT_INTEGER_MV; + } + + if (seq->enable_order_hint) + READ_BITS(gb, 3, &seq->order_hint_bits_minus_1); + } + + READ_ONEBIT(gb, &seq->enable_superres); + READ_ONEBIT(gb, &seq->enable_cdef); + READ_ONEBIT(gb, &seq->enable_restoration); + + FUN_CHECK(read_color_config(ctx, gb, &seq->color_config, seq->seq_profile)); + + READ_ONEBIT(gb, &seq->film_grain_params_present); + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_temporal_delimiter_obu(Av1Codec *ctx, BitReadCtx_t *gb) +{ + ctx->seen_frame_header = 0; + // TODO + + (void)gb; + return MPP_OK; +} + +static const RK_U8 av1_ref_frame_list[AV1_NUM_REF_FRAMES - 2] = { + AV1_REF_FRAME_LAST2, AV1_REF_FRAME_LAST3, AV1_REF_FRAME_BWDREF, + AV1_REF_FRAME_ALTREF2, AV1_REF_FRAME_ALTREF +}; +static MPP_RET set_frame_refs(Av1Codec *ctx, AV1FrameHeader *f) +{ + RK_S32 i, j; + RK_S8 ref_frame_idx[AV1_REFS_PER_FRAME]; + RK_S8 used_frame[AV1_NUM_REF_FRAMES]; + RK_S8 shifted_order_hints[AV1_NUM_REF_FRAMES]; + RK_S32 cur_frame_hint, latest_order_hint, earliest_order_hint, ref; + const AV1SeqHeader *seq = ctx->seq_header; + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) + ref_frame_idx[i] = -1; + ref_frame_idx[AV1_REF_FRAME_LAST - AV1_REF_FRAME_LAST] = f->last_frame_idx; + ref_frame_idx[AV1_REF_FRAME_GOLDEN - AV1_REF_FRAME_LAST] = f->golden_frame_idx; + + /* + * An array usedFrame marking which reference frames + * have been used is prepared as follows: + */ + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + used_frame[i] = 0; + used_frame[f->last_frame_idx] = 1; + used_frame[f->golden_frame_idx] = 1; + + /* + * An array shiftedOrderHints (containing the expected output order shifted + * such that the current frame has hint equal to curFrameHint) is prepared as follows: + */ + cur_frame_hint = 1 << (seq->order_hint_bits_minus_1); + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + shifted_order_hints[i] = cur_frame_hint + + av1d_get_relative_dist(seq, ctx->ref_s[i].order_hint, ctx->order_hint); + + latest_order_hint = shifted_order_hints[f->last_frame_idx]; + earliest_order_hint = shifted_order_hints[f->golden_frame_idx]; + + /* find_latest_backward */ + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + RK_S32 hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint >= latest_order_hint)) { + ref = i; + latest_order_hint = hint; + } + } + /* + * The ALTREF_FRAME reference is set to be a backward reference to the frame + * with highest output order as follows: + */ + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_ALTREF - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + /* find_earliest_backward */ + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + RK_S32 hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint < earliest_order_hint)) { + ref = i; + earliest_order_hint = hint; + } + } + /* + * The BWDREF_FRAME reference is set to be a backward reference to + * the closest frame as follows: + */ + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_BWDREF - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + RK_S32 hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint < earliest_order_hint)) { + ref = i; + earliest_order_hint = hint; + } + } + + /* + * The ALTREF2_FRAME reference is set to the next closest + * backward reference as follows: + */ + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_ALTREF2 - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + /* + * The remaining references are set to be forward references + * in anti-chronological order as follows: + */ + for (i = 0; i < AV1_REFS_PER_FRAME - 2; i++) { + RK_S32 ref_frame = av1_ref_frame_list[i]; + if (ref_frame_idx[ref_frame - AV1_REF_FRAME_LAST] < 0 ) { + /* find_latest_forward */ + ref = -1; + for (j = 0; j < AV1_NUM_REF_FRAMES; j++) { + RK_S32 hint = shifted_order_hints[j]; + if (!used_frame[j] && hint < cur_frame_hint && + (ref < 0 || hint >= latest_order_hint)) { + ref = j; + latest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[ref_frame - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + } + } + + /* + * Finally, any remaining references are set to the reference + * frame with smallest output order as follows: + */ + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + RK_S32 hint = shifted_order_hints[i]; + if (ref < 0 || hint < earliest_order_hint) { + ref = i; + earliest_order_hint = hint; + } + } + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + if (ref_frame_idx[i] < 0) + ref_frame_idx[i] = ref; + f->ref_frame_idx[i] = ref_frame_idx[i]; + } + + return MPP_OK; +} + +static MPP_RET read_superres_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_S32 denom; + + if (seq->enable_superres) + READ_ONEBIT(gb, &f->use_superres); + else + f->use_superres = 0; + + if (f->use_superres) { + READ_BITS(gb, 3, &f->coded_denom); + denom = f->coded_denom + AV1_SUPERRES_DENOM_MIN; + } else { + denom = AV1_SUPERRES_NUM; + } + + ctx->upscaled_width = ctx->frame_width; + ctx->frame_width = (ctx->upscaled_width * AV1_SUPERRES_NUM + denom / 2) / denom; + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_frame_size(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + + if (f->frame_size_override_flag) { + READ_BITS_LONG(gb, seq->frame_width_bits_minus_1 + 1, &f->frame_width_minus_1); + READ_BITS_LONG(gb, seq->frame_height_bits_minus_1 + 1, &f->frame_height_minus_1); + } else { + f->frame_width_minus_1 = seq->max_frame_width_minus_1; + f->frame_height_minus_1 = seq->max_frame_height_minus_1; + } + + ctx->frame_width = f->frame_width_minus_1 + 1; + ctx->frame_height = f->frame_height_minus_1 + 1; + + FUN_CHECK(read_superres_params(ctx, gb, f)); + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_render_size(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + READ_ONEBIT(gb, &f->render_and_frame_size_different); + if (f->render_and_frame_size_different) { + READ_BITS(gb, 16, &f->render_width_minus_1); + READ_BITS(gb, 16, &f->render_height_minus_1); + } else { + f->render_width_minus_1 = f->frame_width_minus_1; + f->render_height_minus_1 = f->frame_height_minus_1; + } + + ctx->render_width = f->render_width_minus_1 + 1; + ctx->render_height = f->render_height_minus_1 + 1; + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_frame_size_with_refs(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + RK_S32 i; + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + READ_ONEBIT(gb, &f->found_ref[i]); + if (f->found_ref[i]) { + AV1RefFrameState *ref = &ctx->ref_s[f->ref_frame_idx[i]]; + + if (!ref->valid) { + mpp_err_f("Missing reference frame, ref = %d, ref_frame_idx = %d.\n", + i, f->ref_frame_idx[i]); + return MPP_ERR_PROTOL; + } + + f->frame_width_minus_1 = ref->upscaled_width - 1; + f->frame_height_minus_1 = ref->frame_height - 1; + f->render_width_minus_1 = ref->render_width - 1; + f->render_height_minus_1 = ref->render_height - 1; + + ctx->upscaled_width = ref->upscaled_width; + ctx->frame_width = ctx->upscaled_width; + ctx->frame_height = ref->frame_height; + ctx->render_width = ref->render_width; + ctx->render_height = ref->render_height; + break; + } + } + + if (i >= AV1_REFS_PER_FRAME) { + FUN_CHECK(read_frame_size(ctx, gb, f)); + FUN_CHECK(read_render_size(ctx, gb, f)); + } else { + FUN_CHECK(read_superres_params(ctx, gb, f)); + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_interpolation_filter(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + READ_ONEBIT(gb, &f->is_filter_switchable); + if (f->is_filter_switchable) + f->interpolation_filter = AV1_INTERP_SWITCHABLE; + else + READ_BITS(gb, 2, &f->interpolation_filter); + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static RK_S32 tile_log2(RK_S32 blksize, RK_S32 target) +{ + RK_S32 k; + + for (k = 0; (blksize << k) < target; k++); + return k; +} + +static MPP_RET read_tile_info_max_tile(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_S32 max_tile_width_sb, max_tile_height_sb, max_tile_area_sb; + RK_S32 min_log2_tile_cols, max_log2_tile_cols, max_log2_tile_rows; + RK_S32 min_log2_tiles, min_log2_tile_rows; + RK_S32 sb_rows, sb_cols; + RK_S32 i; + + // get tile limits + { + RK_S32 mi_cols = 2 * ((ctx->frame_width + 7) >> 3); + RK_S32 mi_rows = 2 * ((ctx->frame_height + 7) >> 3); + RK_S32 sb_size = seq->use_128x128_superblock ? 7 : 6; + + sb_cols = seq->use_128x128_superblock ? ((mi_cols + 31) >> 5) : ((mi_cols + 15) >> 4); + sb_rows = seq->use_128x128_superblock ? ((mi_rows + 31) >> 5) : ((mi_rows + 15) >> 4); + max_tile_width_sb = AV1_MAX_TILE_WIDTH >> sb_size; + max_tile_area_sb = AV1_MAX_TILE_AREA >> (2 * sb_size); + + min_log2_tile_cols = tile_log2(max_tile_width_sb, sb_cols); + max_log2_tile_cols = tile_log2(1, MPP_MIN(sb_cols, AV1_MAX_TILE_COLS)); + max_log2_tile_rows = tile_log2(1, MPP_MIN(sb_rows, AV1_MAX_TILE_ROWS)); + min_log2_tiles = MPP_MAX(min_log2_tile_cols, tile_log2(max_tile_area_sb, sb_rows * sb_cols)); + } + + READ_ONEBIT(gb, &f->uniform_tile_spacing_flag); + av1d_dbg(AV1D_DBG_HEADER, "uniform_tile_spacing_flag=%d\n", f->uniform_tile_spacing_flag); + if (f->uniform_tile_spacing_flag) { + RK_S32 tile_width_sb, tile_height_sb; + RK_U32 val; + + read_increment(gb, min_log2_tile_cols, max_log2_tile_cols, &val); + f->tile_cols_log2 = (RK_U8)val; + + tile_width_sb = (sb_cols + (1 << f->tile_cols_log2) - 1) >> f->tile_cols_log2; + f->tile_cols = (sb_cols + tile_width_sb - 1) / tile_width_sb; + + min_log2_tile_rows = MPP_MAX(min_log2_tiles - f->tile_cols_log2, 0); + read_increment(gb, min_log2_tile_rows, max_log2_tile_rows, &val); + f->tile_rows_log2 = (RK_U8)val; + + tile_height_sb = (sb_rows + (1 << f->tile_rows_log2) - 1) >> + f->tile_rows_log2; + f->tile_rows = (sb_rows + tile_height_sb - 1) / tile_height_sb; + + for (i = 0; i < f->tile_cols - 1; i++) + f->width_in_sbs_minus_1[i] = tile_width_sb - 1; + f->width_in_sbs_minus_1[i] = sb_cols - (f->tile_cols - 1) * tile_width_sb - 1; + for (i = 0; i < f->tile_rows - 1; i++) + f->height_in_sbs_minus_1[i] = tile_height_sb - 1; + f->height_in_sbs_minus_1[i] = sb_rows - (f->tile_rows - 1) * tile_height_sb - 1; + } else { + RK_S32 widest_tile_sb = 0; + RK_S32 start_sb = 0; + RK_S32 size_sb; + + for (i = 0; start_sb < sb_cols && i < AV1_MAX_TILE_COLS; i++) { + RK_S32 max_width = MPP_MIN(sb_cols - start_sb, max_tile_width_sb); + RK_U32 val = 0; + + read_ns(gb, max_width, &val); + f->width_in_sbs_minus_1[i] = (RK_U8)val; + size_sb = f->width_in_sbs_minus_1[i] + 1; + widest_tile_sb = MPP_MAX(size_sb, widest_tile_sb); + start_sb += size_sb; + } + f->tile_cols_log2 = tile_log2(1, i); + f->tile_cols = i; + + if (min_log2_tiles > 0) + max_tile_area_sb = (sb_rows * sb_cols) >> (min_log2_tiles + 1); + else + max_tile_area_sb = sb_rows * sb_cols; + max_tile_height_sb = MPP_MAX(max_tile_area_sb / widest_tile_sb, 1); + + start_sb = 0; + for (i = 0; start_sb < sb_rows && i < AV1_MAX_TILE_ROWS; i++) { + RK_S32 max_height = MPP_MIN(sb_rows - start_sb, max_tile_height_sb); + RK_U32 val = 0; + + read_ns(gb, max_height, &val); + f->height_in_sbs_minus_1[i] = (RK_U8)val; + size_sb = f->height_in_sbs_minus_1[i] + 1; + start_sb += size_sb; + } + f->tile_rows_log2 = tile_log2(1, i); + f->tile_rows = i; + } + + if (f->tile_cols_log2 > 0 || f->tile_rows_log2 > 0) { + READ_BITS(gb, f->tile_cols_log2 + f->tile_rows_log2, + &f->context_update_tile_id); + READ_BITS(gb, 2, &f->tile_size_bytes_minus1); + } else { + f->context_update_tile_id = 0; + f->tile_size_bytes_minus1 = 3; + } + + ctx->tile_cols = f->tile_cols; + ctx->tile_rows = f->tile_rows; + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static const RK_U32 bitmask_table[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, + 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, + 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, +}; + +#define READ_DELTA_Q(gb, bits, val) do { \ + RK_U32 delta_flag = 0; \ + RK_S32 delta_q_val = 0; \ + READ_ONEBIT(gb, &delta_flag);\ + if (delta_flag) {\ + READ_BITS(gb, bits, &delta_q_val);\ + delta_q_val &= bitmask_table[bits];\ + }\ + *(val) = delta_q_val; \ + } while (0) + +static MPP_RET read_quantization_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + + READ_BITS(gb, 8, &f->base_q_idx); + READ_DELTA_Q(gb, 7, &f->delta_q_y_dc); + if (ctx->num_planes > 1) { + f->diff_uv_delta = 0; + if (seq->color_config.separate_uv_delta_q) + READ_ONEBIT(gb, &f->diff_uv_delta); + + READ_DELTA_Q(gb, 7, &f->delta_q_u_dc); + READ_DELTA_Q(gb, 7, &f->delta_q_u_ac); + if (f->diff_uv_delta) { + READ_DELTA_Q(gb, 7, &f->delta_q_v_dc); + READ_DELTA_Q(gb, 7, &f->delta_q_v_ac); + } else { + f->delta_q_v_dc = f->delta_q_u_dc; + f->delta_q_v_ac = f->delta_q_u_ac; + } + } else { + f->delta_q_u_dc = 0; + f->delta_q_u_ac = 0; + f->delta_q_v_dc = 0; + f->delta_q_v_ac = 0; + } + + READ_ONEBIT(gb, &f->using_qmatrix); + if (f->using_qmatrix) { + READ_BITS(gb, 4, &f->qm_y); + READ_BITS(gb, 4, &f->qm_u); + if (seq->color_config.separate_uv_delta_q) + READ_BITS(gb, 4, &f->qm_v); + else + f->qm_v = f->qm_u; + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_segmentation_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + static const RK_U8 segment_bits[AV1_SEG_LVL_MAX] = { 8, 6, 6, 6, 6, 3, 0, 0 }; + static const RK_U8 segment_sign[AV1_SEG_LVL_MAX] = { 1, 1, 1, 1, 1, 0, 0, 0 }; + static const RK_U8 default_feature_enabled[AV1_SEG_LVL_MAX] = { 0 }; + static const RK_S16 default_feature_value[AV1_SEG_LVL_MAX] = { 0 }; + RK_S32 i, j; + + READ_ONEBIT(gb, &f->segmentation_enabled); + + if (f->segmentation_enabled) { + if (f->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + f->segmentation_update_map = 1; + f->segmentation_temporal_update = 0; + f->segmentation_update_data = 1; + } else { + READ_ONEBIT(gb, &f->segmentation_update_map); + if (f->segmentation_update_map) + READ_ONEBIT(gb, &f->segmentation_temporal_update); + else + f->segmentation_temporal_update = 0; + READ_ONEBIT(gb, &f->segmentation_update_data); + } + + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + const RK_U8 *ref_feature_enabled; + const RK_S16 *ref_feature_value; + + if (f->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + ref_feature_enabled = default_feature_enabled; + ref_feature_value = default_feature_value; + } else { + ref_feature_enabled = + ctx->ref_s[f->ref_frame_idx[f->primary_ref_frame]].feature_enabled[i]; + ref_feature_value = + ctx->ref_s[f->ref_frame_idx[f->primary_ref_frame]].feature_value[i]; + } + + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + if (f->segmentation_update_data) { + READ_ONEBIT(gb, &f->feature_enabled[i][j]); + if (f->feature_enabled[i][j] && segment_bits[j] > 0) { + if (segment_sign[j]) { + RK_S32 sign_, data; + + READ_ONEBIT(gb, &sign_); + READ_BITS(gb, segment_bits[j], &data); + if (sign_) data -= (1 << segment_bits[j]); + f->feature_value[i][j] = data; + } else + READ_BITS(gb, segment_bits[j], &f->feature_value[i][j]); + } else { + f->feature_value[i][j] = 0; + } + } else { + f->feature_enabled[i][j] = ref_feature_enabled[j]; + f->feature_value[i][j] = ref_feature_value[j]; + } + } + } + } else { + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + f->feature_enabled[i][j] = 0; + f->feature_value[i][j] = 0; + } + } + } + + f->segmentation_id_last_active = 0; + f->segmentation_id_preskip = 0; + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + if (f->feature_enabled[i][j]) { + f->segmentation_id_last_active = i; + if ( j > AV1_SEG_LVL_REF_FRAME) + f->segmentation_id_preskip = 1; + } + } + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET read_delta_q_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + if (f->base_q_idx > 0) + READ_ONEBIT(gb, &f->delta_q_present); + else + f->delta_q_present = 0; + + if (f->delta_q_present) + READ_BITS(gb, 2, &f->delta_q_res); + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_delta_lf_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + if (f->delta_q_present) { + if (!f->allow_intrabc) + READ_ONEBIT(gb, &f->delta_lf_present); + else + f->delta_lf_present = 0; + if (f->delta_lf_present) { + READ_BITS(gb, 2, &f->delta_lf_res); + READ_ONEBIT(gb, &f->delta_lf_multi); + } else { + f->delta_lf_res = 0; + f->delta_lf_multi = 0; + } + } else { + f->delta_lf_present = 0; + f->delta_lf_res = 0; + f->delta_lf_multi = 0; + } + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static const RK_S8 default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] = +{ 1, 0, 0, 0, -1, 0, -1, -1 }; +static const RK_S8 default_loop_filter_mode_deltas[2] = { 0, 0 }; + +static MPP_RET read_loop_filter_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + RK_S32 i; + + if (ctx->coded_lossless || f->allow_intrabc) { + f->loop_filter_level[0] = 0; + f->loop_filter_level[1] = 0; + f->loop_filter_ref_deltas[AV1_REF_FRAME_INTRA] = 1; + f->loop_filter_ref_deltas[AV1_REF_FRAME_LAST] = 0; + f->loop_filter_ref_deltas[AV1_REF_FRAME_LAST2] = 0; + f->loop_filter_ref_deltas[AV1_REF_FRAME_LAST3] = 0; + f->loop_filter_ref_deltas[AV1_REF_FRAME_BWDREF] = 0; + f->loop_filter_ref_deltas[AV1_REF_FRAME_GOLDEN] = -1; + f->loop_filter_ref_deltas[AV1_REF_FRAME_ALTREF] = -1; + f->loop_filter_ref_deltas[AV1_REF_FRAME_ALTREF2] = -1; + for (i = 0; i < 2; i++) + f->loop_filter_mode_deltas[i] = 0; + return MPP_OK; + } + + READ_BITS(gb, 6, &f->loop_filter_level[0]); + READ_BITS(gb, 6, &f->loop_filter_level[1]); + + if (ctx->num_planes > 1) { + if (f->loop_filter_level[0] || + f->loop_filter_level[1]) { + READ_BITS(gb, 6, &f->loop_filter_level[2]); + READ_BITS(gb, 6, &f->loop_filter_level[3]); + } + } + + av1d_dbg(AV1D_DBG_HEADER, "orderhint %d loop_filter_level %d %d %d %d\n", + f->order_hint, + f->loop_filter_level[0], f->loop_filter_level[1], + f->loop_filter_level[2], f->loop_filter_level[3]); + READ_BITS(gb, 3, &f->loop_filter_sharpness); + + READ_ONEBIT(gb, &f->loop_filter_delta_enabled); + if (f->loop_filter_delta_enabled) { + const RK_S8 *ref_loop_filter_ref_deltas, *ref_loop_filter_mode_deltas; + + if (f->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + ref_loop_filter_ref_deltas = default_loop_filter_ref_deltas; + ref_loop_filter_mode_deltas = default_loop_filter_mode_deltas; + } else { + ref_loop_filter_ref_deltas = + ctx->ref_s[f->ref_frame_idx[f->primary_ref_frame]].loop_filter_ref_deltas; + ref_loop_filter_mode_deltas = + ctx->ref_s[f->ref_frame_idx[f->primary_ref_frame]].loop_filter_mode_deltas; + } + + READ_ONEBIT(gb, &f->loop_filter_delta_update); + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + if (f->loop_filter_delta_update) + READ_ONEBIT(gb, &f->update_ref_delta[i]); + else + f->update_ref_delta[i] = 0; + if (f->update_ref_delta[i]) + READ_SIGNBITS(gb, 7, &f->loop_filter_ref_deltas[i]); + else + f->loop_filter_ref_deltas[i] = ref_loop_filter_ref_deltas[i]; + } + for (i = 0; i < 2; i++) { + if (f->loop_filter_delta_update) + READ_ONEBIT(gb, &f->update_mode_delta[i]); + else + f->update_mode_delta[i] = 0; + if (f->update_mode_delta[i]) + READ_SIGNBITS(gb, 7, &f->loop_filter_mode_deltas[i]); + else + f->loop_filter_mode_deltas[i] = ref_loop_filter_mode_deltas[i]; + } + } else { + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) + f->loop_filter_ref_deltas[i] = default_loop_filter_ref_deltas[i]; + for (i = 0; i < 2; i++) + f->loop_filter_mode_deltas[i] = default_loop_filter_mode_deltas[i]; + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_cdef_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_S32 i; + + if (ctx->coded_lossless || f->allow_intrabc || + !seq->enable_cdef) { + f->cdef_damping_minus_3 = 0; + f->cdef_bits = 0; + f->cdef_y_pri_strength[0] = 0; + f->cdef_y_sec_strength[0] = 0; + f->cdef_uv_pri_strength[0] = 0; + f->cdef_uv_sec_strength[0] = 0; + + return MPP_OK; + } + + READ_BITS(gb, 2, &f->cdef_damping_minus_3); + READ_BITS(gb, 2, &f->cdef_bits); + + for (i = 0; i < (1 << f->cdef_bits); i++) { + READ_BITS(gb, 4, &f->cdef_y_pri_strength[i]); + READ_BITS(gb, 2, &f->cdef_y_sec_strength[i]); + + if (ctx->num_planes > 1) { + READ_BITS(gb, 4, &f->cdef_uv_pri_strength[i]); + READ_BITS(gb, 2, &f->cdef_uv_sec_strength[i]); + } + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_lr_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_S32 uses_lr, uses_chroma_lr; + RK_S32 i; + + if (ctx->all_lossless || f->allow_intrabc || + !seq->enable_restoration) { + return MPP_OK; + } + + uses_lr = uses_chroma_lr = 0; + for (i = 0; i < ctx->num_planes; i++) { + READ_BITS(gb, 2, &f->lr_type[i]); + + if (f->lr_type[i] != AV1_RESTORE_NONE) { + uses_lr = 1; + if (i > 0) + uses_chroma_lr = 1; + } + } + + if (uses_lr) { + RK_U32 val = 0; + + if (seq->use_128x128_superblock) + read_increment(gb, 1, 2, &val); + else + read_increment(gb, 0, 2, &val); + f->lr_unit_shift = (RK_U8)val; + + if (seq->color_config.subsampling_x && + seq->color_config.subsampling_y && uses_chroma_lr) { + READ_ONEBIT(gb, &f->lr_uv_shift); + } else { + f->lr_uv_shift = 0; + } + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_tx_mode(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + if (ctx->coded_lossless) + f->tx_mode = 0; + else { + READ_ONEBIT(gb, &f->tx_mode); + f->tx_mode = f->tx_mode ? AV1_TX_MODE_SELECT : AV1_TX_MODE_LARGEST; + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_frame_reference_mode(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + if (f->frame_type == AV1_FRAME_INTRA_ONLY || + f->frame_type == AV1_FRAME_KEY) + f->reference_select = 0; + else + READ_ONEBIT(gb, &f->reference_select); + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_skip_mode_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_U8 skip_mode_allowed = 0; + + ctx->skip_ref0 = 0; + ctx->skip_ref1 = 0; + + if (f->frame_type == AV1_FRAME_KEY || + f->frame_type == AV1_FRAME_INTRA_ONLY || + !f->reference_select || !seq->enable_order_hint) { + f->skip_mode_present = 0; + + return MPP_OK; + } + + /* + * Determine whether skip mode is allowed. + * If allowed, set skip_ref0 and skip_ref1. + * skip_ref0 and skip_ref1 are the indices (plus 1) of the two + * reference frames used in skip mode. + */ + { + RK_S32 forward_idx = -1; + RK_S32 backward_idx = -1; + RK_S32 forward_hint = -1; + RK_S32 backward_hint = -1; + RK_S32 ref_hint, dist, i; + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = ctx->ref_s[f->ref_frame_idx[i]].order_hint; + dist = av1d_get_relative_dist(seq, ref_hint, ctx->order_hint); + if (dist < 0) { + if (forward_idx < 0 || + av1d_get_relative_dist(seq, ref_hint, forward_hint) > 0) { + forward_idx = i; + forward_hint = ref_hint; + } + } else if (dist > 0) { + if (backward_idx < 0 || + av1d_get_relative_dist(seq, ref_hint, backward_hint) < 0) { + backward_idx = i; + backward_hint = ref_hint; + } + } + } + + skip_mode_allowed = 0; + if (forward_idx < 0) { + skip_mode_allowed = 0; + } else if (backward_idx >= 0) { + skip_mode_allowed = 1; + ctx->skip_ref0 = MPP_MIN(forward_idx, backward_idx) + 1; + ctx->skip_ref1 = MPP_MAX(forward_idx, backward_idx) + 1; + } else { + RK_S32 second_forward_hint; + RK_S32 second_forward_idx = -1; + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = ctx->ref_s[f->ref_frame_idx[i]].order_hint; + if (av1d_get_relative_dist(seq, ref_hint, forward_hint) < 0) { + if (second_forward_idx < 0 || + av1d_get_relative_dist(seq, ref_hint, second_forward_hint) > 0) { + second_forward_idx = i; + second_forward_hint = ref_hint; + } + } + } + + if (second_forward_idx < 0) { + skip_mode_allowed = 0; + } else { + ctx->skip_ref0 = MPP_MIN(forward_idx, second_forward_idx) + 1; + ctx->skip_ref1 = MPP_MAX(forward_idx, second_forward_idx) + 1; + skip_mode_allowed = 1; + } + } + } + + if (skip_mode_allowed) + READ_ONEBIT(gb, &f->skip_mode_present); + else + f->skip_mode_present = 0; + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_gm_param(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f, RK_S32 type, RK_S32 ref, RK_S32 idx) +{ + RK_U32 abs_bits, prec_bits, num_syms; + + if (idx < 2) { + if (type == AV1_WARP_MODEL_TRANSLATION) { + abs_bits = AV1_GM_ABS_TRANS_ONLY_BITS - !f->allow_high_precision_mv; + prec_bits = AV1_GM_TRANS_ONLY_PREC_BITS - !f->allow_high_precision_mv; + } else { + abs_bits = AV1_GM_ABS_TRANS_BITS; + prec_bits = AV1_GM_TRANS_PREC_BITS; + } + } else { + abs_bits = AV1_GM_ABS_ALPHA_BITS; + prec_bits = AV1_GM_ALPHA_PREC_BITS; + } + + num_syms = 2 * (1 << abs_bits) + 1; + read_signed_subexp(gb, num_syms, &f->gm_params[ref][idx]); + + (void)prec_bits; + (void)ctx; + return MPP_OK; +} + +static MPP_RET read_global_motion_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + RK_S32 ref, type; + + if (f->frame_type == AV1_FRAME_KEY || + f->frame_type == AV1_FRAME_INTRA_ONLY) + return MPP_OK; + + for (ref = AV1_REF_FRAME_LAST; ref <= AV1_REF_FRAME_ALTREF; ref++) { + READ_ONEBIT(gb, &f->is_global[ref]); + if (f->is_global[ref]) { + READ_ONEBIT(gb, &f->is_rot_zoom[ref]); + if (f->is_rot_zoom[ref]) { + type = AV1_WARP_MODEL_ROTZOOM; + } else { + READ_ONEBIT(gb, &f->is_translation[ref]); + type = f->is_translation[ref] ? AV1_WARP_MODEL_TRANSLATION + : AV1_WARP_MODEL_AFFINE; + } + } else { + type = AV1_WARP_MODEL_IDENTITY; + } + + if (type >= AV1_WARP_MODEL_ROTZOOM) { + FUN_CHECK(read_gm_param(ctx, gb, f, type, ref, 2)); + FUN_CHECK(read_gm_param(ctx, gb, f, type, ref, 3)); + if (type == AV1_WARP_MODEL_AFFINE) { + FUN_CHECK(read_gm_param(ctx, gb, f, type, ref, 4)); + FUN_CHECK(read_gm_param(ctx, gb, f, type, ref, 5)); + } else { + f->gm_params[ref][4] = -f->gm_params[ref][3]; + f->gm_params[ref][5] = f->gm_params[ref][2]; + } + } + if (type >= AV1_WARP_MODEL_TRANSLATION) { + FUN_CHECK(read_gm_param(ctx, gb, f, type, ref, 0)); + FUN_CHECK(read_gm_param(ctx, gb, f, type, ref, 1)); + } + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_film_grain_params(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FilmGrainParams *gm, AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_S32 num_pos_luma, num_pos_chroma; + RK_S32 i; + + if (!seq->film_grain_params_present || + (!f->show_frame && !f->showable_frame)) + return MPP_OK; + + READ_ONEBIT(gb, &gm->apply_grain); + + if (!gm->apply_grain) + return MPP_OK; + + READ_BITS(gb, 16, &gm->grain_seed); + + if (f->frame_type == AV1_FRAME_INTER) + READ_ONEBIT(gb, &gm->update_grain); + else + gm->update_grain = 1; + + if (!gm->update_grain) { + READ_BITS(gb, 3, &gm->film_grain_params_ref_idx); + return MPP_OK; + } + + READ_BITS(gb, 4, &gm->num_y_points); + for (i = 0; i < gm->num_y_points; i++) { + READ_BITS(gb, 8, &gm->point_y_value[i]); + READ_BITS(gb, 8, &gm->point_y_scaling[i]); + } + + if (seq->color_config.mono_chrome) + gm->chroma_scaling_from_luma = 0; + else + READ_ONEBIT(gb, &gm->chroma_scaling_from_luma); + + if (seq->color_config.mono_chrome || + gm->chroma_scaling_from_luma || + (seq->color_config.subsampling_x == 1 && + seq->color_config.subsampling_y == 1 && + gm->num_y_points == 0)) { + gm->num_cb_points = 0; + gm->num_cr_points = 0; + } else { + READ_BITS(gb, 4, &gm->num_cb_points); + for (i = 0; i < gm->num_cb_points; i++) { + READ_BITS(gb, 8, &gm->point_cb_value[i]); + READ_BITS(gb, 8, &gm->point_cb_scaling[i]); + } + READ_BITS(gb, 4, &gm->num_cr_points); + for (i = 0; i < gm->num_cr_points; i++) { + READ_BITS(gb, 8, &gm->point_cr_value[i]); + READ_BITS(gb, 8, &gm->point_cr_scaling[i]); + } + } + + READ_BITS(gb, 2, &gm->grain_scaling_minus_8); + READ_BITS(gb, 2, &gm->ar_coeff_lag); + num_pos_luma = 2 * gm->ar_coeff_lag * (gm->ar_coeff_lag + 1); + if (gm->num_y_points) { + num_pos_chroma = num_pos_luma + 1; + for (i = 0; i < num_pos_luma; i++) + READ_BITS(gb, 8, &gm->ar_coeffs_y_plus_128[i]); + } else { + num_pos_chroma = num_pos_luma; + } + if (gm->chroma_scaling_from_luma || gm->num_cb_points) { + for (i = 0; i < num_pos_chroma; i++) + READ_BITS(gb, 8, &gm->ar_coeffs_cb_plus_128[i]); + } + if (gm->chroma_scaling_from_luma || gm->num_cr_points) { + for (i = 0; i < num_pos_chroma; i++) + READ_BITS(gb, 8, &gm->ar_coeffs_cr_plus_128[i]); + } + READ_BITS(gb, 2, &gm->ar_coeff_shift_minus_6); + READ_BITS(gb, 2, &gm->grain_scale_shift); + if (gm->num_cb_points) { + READ_BITS(gb, 8, &gm->cb_mult); + READ_BITS(gb, 8, &gm->cb_luma_mult); + READ_BITS(gb, 9, &gm->cb_offset); + } + if (gm->num_cr_points) { + READ_BITS(gb, 8, &gm->cr_mult); + READ_BITS(gb, 8, &gm->cr_luma_mult); + READ_BITS(gb, 9, &gm->cr_offset); + } + + READ_ONEBIT(gb, &gm->overlap_flag); + READ_ONEBIT(gb, &gm->clip_to_restricted_range); + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_uncompressed_header(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_S32 id_len, diff_len, all_frames, frame_is_intra, order_hint_bits; + RK_S32 i; + + if (!seq) { + mpp_err_f("No sequence header available.\n"); + return MPP_ERR_UNKNOW; + } + + id_len = seq->additional_frame_id_length_minus_1 + + seq->delta_frame_id_length_minus_2 + 3; + all_frames = (1 << AV1_NUM_REF_FRAMES) - 1; + + if (seq->reduced_still_picture_header) { + f->show_existing_frame = 0; + f->frame_type = AV1_FRAME_KEY; + f->show_frame = 1; + f->showable_frame = 0; + frame_is_intra = 1; + } else { + READ_ONEBIT(gb, &f->show_existing_frame); + + if (f->show_existing_frame) { + AV1RefFrameState *ref; + + READ_BITS(gb, 3, &f->frame_to_show_map_idx); + ref = &ctx->ref_s[f->frame_to_show_map_idx]; + + if (!ref->valid) { + mpp_err_f("Missing reference frame needed for " + "show_existing_frame (frame_to_show_map_idx = %d).\n", + f->frame_to_show_map_idx); + return MPP_ERR_UNKNOW; + } + + if (seq->decoder_model_info_present_flag && + !seq->timing_info.equal_picture_interval) { + READ_BITS_LONG(gb, seq->decoder_model_info.frame_presentation_time_length_minus_1 + 1, + &f->frame_presentation_time); + } + + if (seq->frame_id_numbers_present_flag) + READ_BITS_LONG(gb, id_len, &f->display_frame_id); + + f->frame_type = ref->frame_type; + if (f->frame_type == AV1_FRAME_KEY) { + f->refresh_frame_flags = all_frames; + + // Section 7.21 + f->current_frame_id = ref->frame_id; + ctx->upscaled_width = ref->upscaled_width; + ctx->frame_width = ref->frame_width; + ctx->frame_height = ref->frame_height; + ctx->render_width = ref->render_width; + ctx->render_height = ref->render_height; + ctx->bit_depth = ref->bit_depth; + ctx->order_hint = ref->order_hint; + } else + f->refresh_frame_flags = 0; + + f->frame_width_minus_1 = ref->upscaled_width - 1; + f->frame_height_minus_1 = ref->frame_height - 1; + f->render_width_minus_1 = ref->render_width - 1; + f->render_height_minus_1 = ref->render_height - 1; + + return MPP_OK; + } + + READ_BITS(gb, 2, &f->frame_type); + frame_is_intra = (f->frame_type == AV1_FRAME_INTRA_ONLY || + f->frame_type == AV1_FRAME_KEY); + + ctx->frame_is_intra = frame_is_intra; + if (f->frame_type == AV1_FRAME_KEY) { + RK_U32 refresh_frame_flags = (1 << AV1_NUM_REF_FRAMES) - 1; + + av1d_get_cdfs(ctx, f->frame_to_show_map_idx); + av1d_store_cdfs(ctx, refresh_frame_flags); + } + + READ_ONEBIT(gb, &f->show_frame); + if (f->show_frame && + seq->decoder_model_info_present_flag && + !seq->timing_info.equal_picture_interval) { + READ_BITS_LONG(gb, seq->decoder_model_info.frame_presentation_time_length_minus_1 + 1, + &f->frame_presentation_time); + } + if (f->show_frame) + f->showable_frame = (f->frame_type != AV1_FRAME_KEY) ? 1 : 0; + else + READ_ONEBIT(gb, &f->showable_frame); + + if (f->frame_type == AV1_FRAME_SWITCH || + (f->frame_type == AV1_FRAME_KEY && f->show_frame)) + f->error_resilient_mode = 1; + else + READ_ONEBIT(gb, &f->error_resilient_mode); + } + + if (f->frame_type == AV1_FRAME_KEY && f->show_frame) { + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + ctx->ref_s[i].valid = 0; + ctx->ref_s[i].order_hint = 0; + } + } + + READ_ONEBIT(gb, &f->disable_cdf_update); + + if (seq->seq_force_screen_content_tools == AV1_SELECT_SCREEN_CONTENT_TOOLS) { + READ_ONEBIT(gb, &f->allow_screen_content_tools); + } else { + f->allow_screen_content_tools = seq->seq_force_screen_content_tools; + } + if (f->allow_screen_content_tools) { + if (seq->seq_force_integer_mv == AV1_SELECT_INTEGER_MV) + READ_ONEBIT(gb, &f->force_integer_mv); + else + f->force_integer_mv = seq->seq_force_integer_mv; + } else { + f->force_integer_mv = 0; + } + + if (seq->frame_id_numbers_present_flag) { + READ_BITS_LONG(gb, id_len, &f->current_frame_id); + + diff_len = seq->delta_frame_id_length_minus_2 + 2; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (f->current_frame_id > (RK_S32)(1 << diff_len)) { + if (ctx->ref_s[i].frame_id > f->current_frame_id || + ctx->ref_s[i].frame_id < (f->current_frame_id - (RK_S32)(1 << diff_len))) + ctx->ref_s[i].valid = 0; + } else { + if (ctx->ref_s[i].frame_id > f->current_frame_id && + ctx->ref_s[i].frame_id < (RK_S32)((1 << id_len) + f->current_frame_id - (1 << diff_len))) + ctx->ref_s[i].valid = 0; + } + } + } else { + f->current_frame_id = 0; + } + + if (f->frame_type == AV1_FRAME_SWITCH) + f->frame_size_override_flag = 1; + else if (seq->reduced_still_picture_header) + f->frame_size_override_flag = 0; + else + READ_ONEBIT(gb, &f->frame_size_override_flag); + + order_hint_bits = seq->enable_order_hint ? seq->order_hint_bits_minus_1 + 1 : 0; + if (order_hint_bits > 0) + READ_BITS_LONG(gb, order_hint_bits, &f->order_hint); + else + f->order_hint = 0; + ctx->order_hint = f->order_hint; + + if (frame_is_intra || f->error_resilient_mode) + f->primary_ref_frame = AV1_PRIMARY_REF_NONE; + else + READ_BITS(gb, 3, &f->primary_ref_frame); + + if (seq->decoder_model_info_present_flag) { + READ_ONEBIT(gb, &f->buffer_removal_time_present_flag); + if (f->buffer_removal_time_present_flag) { + for (i = 0; i <= seq->operating_points_cnt_minus_1; i++) { + if (seq->decoder_model_present_for_this_op[i]) { + RK_S32 op_pt_idc = seq->operating_point_idc[i]; + RK_S32 in_temporal_layer = (op_pt_idc >> ctx->temporal_id ) & 1; + RK_S32 in_spatial_layer = (op_pt_idc >> (ctx->spatial_id + 8)) & 1; + + if (seq->operating_point_idc[i] == 0 || + (in_temporal_layer && in_spatial_layer)) { + READ_BITS_LONG(gb, seq->decoder_model_info.buffer_removal_time_length_minus_1 + 1, + &f->buffer_removal_time[i]); + } + } + } + } + } + + if (f->frame_type == AV1_FRAME_SWITCH || + (f->frame_type == AV1_FRAME_KEY && f->show_frame)) + f->refresh_frame_flags = all_frames; + else + READ_BITS(gb, 8, &f->refresh_frame_flags); + + ctx->refresh_frame_flags = f->refresh_frame_flags; + if (!frame_is_intra || f->refresh_frame_flags != all_frames) { + if (seq->enable_order_hint) { + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (f->error_resilient_mode) + READ_BITS(gb, order_hint_bits, &f->ref_order_hint[i]); + else + f->ref_order_hint[i] = ctx->ref_s[i].order_hint; + if (f->ref_order_hint[i] != ctx->ref_s[i].order_hint) + ctx->ref_s[i].valid = 0; + } + } + } + + f->ref_frame_valued = 1; + if (f->frame_type == AV1_FRAME_KEY || + f->frame_type == AV1_FRAME_INTRA_ONLY) { + FUN_CHECK(read_frame_size(ctx, gb, f)); + FUN_CHECK(read_render_size(ctx, gb, f)); + + if (f->allow_screen_content_tools && + ctx->upscaled_width == ctx->frame_width) + READ_ONEBIT(gb, &f->allow_intrabc); + else + f->allow_intrabc = 0; + + f->ref_frame_valued = 0; + } else { + if (!seq->enable_order_hint) { + f->frame_refs_short_signaling = 0; + } else { + READ_ONEBIT(gb, &f->frame_refs_short_signaling); + if (f->frame_refs_short_signaling) { + READ_BITS(gb, 3, &f->last_frame_idx); + READ_BITS(gb, 3, &f->golden_frame_idx); + FUN_CHECK(set_frame_refs(ctx, f)); + } + } + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + if (!f->frame_refs_short_signaling) + READ_BITS(gb, 3, &f->ref_frame_idx[i]); + if (seq->frame_id_numbers_present_flag) { + READ_BITS_LONG(gb, seq->delta_frame_id_length_minus_2 + 2, + &f->delta_frame_id_minus1[i]); + } + } + + if (f->frame_size_override_flag && + !f->error_resilient_mode) { + FUN_CHECK(read_frame_size_with_refs(ctx, gb, f)); + } else { + FUN_CHECK(read_frame_size(ctx, gb, f)); + FUN_CHECK(read_render_size(ctx, gb, f)); + } + + if (f->force_integer_mv) + f->allow_high_precision_mv = 0; + else + READ_ONEBIT(gb, &f->allow_high_precision_mv); + + FUN_CHECK(read_interpolation_filter(ctx, gb, f)); + + READ_ONEBIT(gb, &f->is_motion_mode_switchable); + + if (f->error_resilient_mode || + !seq->enable_ref_frame_mvs) + f->use_ref_frame_mvs = 0; + else + READ_ONEBIT(gb, &f->use_ref_frame_mvs); + + f->allow_intrabc = 0; + } + + if (seq->reduced_still_picture_header || f->disable_cdf_update) + f->disable_frame_end_update_cdf = 1; + else + READ_ONEBIT(gb, &f->disable_frame_end_update_cdf); + + ctx->disable_frame_end_update_cdf = f->disable_frame_end_update_cdf; + + av1d_dbg(AV1D_DBG_HEADER, "ptile_info in %d", mpp_get_bits_count(gb)); + FUN_CHECK(read_tile_info_max_tile(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "ptile_info out %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_quantization_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "quantization out %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_segmentation_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "segmentation out %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_delta_q_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "delta_q out %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_delta_lf_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "lf out %d", mpp_get_bits_count(gb)); + + // Load CDF tables for non-coeffs. + if (f->error_resilient_mode || frame_is_intra || + f->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + // Init non-coeff CDFs. + // Setup past independence. + ctx->cdfs = &ctx->default_cdfs; + ctx->cdfs_ndvc = &ctx->default_cdfs_ndvc; + av1d_set_default_coeff_probs(f->base_q_idx, ctx->cdfs); + } else { + // Load CDF tables from previous frame. + // Load params from previous frame. + RK_U32 idx = f->ref_frame_idx[f->primary_ref_frame]; + + av1d_get_cdfs(ctx, idx); + } + av1d_dbg(AV1D_DBG_HEADER, + "show_existing_frame_index %d primary_ref_frame %d %d (%d) " + "refresh_frame_flags %d base_q_idx %d\n", + f->frame_to_show_map_idx, + f->ref_frame_idx[f->primary_ref_frame], + ctx->ref[f->ref_frame_idx[f->primary_ref_frame]].slot_index, + f->primary_ref_frame, + f->refresh_frame_flags, + f->base_q_idx); + av1d_store_cdfs(ctx, f->refresh_frame_flags); + + ctx->coded_lossless = 1; + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + RK_S32 qindex; + + if (f->feature_enabled[i][AV1_SEG_LVL_ALT_Q]) { + qindex = (f->base_q_idx + f->feature_value[i][AV1_SEG_LVL_ALT_Q]); + } else { + qindex = f->base_q_idx; + } + qindex = mpp_clip_uint_pow2(qindex, 8); + + if (qindex || f->delta_q_y_dc || + f->delta_q_u_ac || f->delta_q_u_dc || + f->delta_q_v_ac || f->delta_q_v_dc) { + ctx->coded_lossless = 0; + } + } + ctx->all_lossless = ctx->coded_lossless && ctx->frame_width == ctx->upscaled_width; + av1d_dbg(AV1D_DBG_HEADER, "filter in %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_loop_filter_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "cdef in %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_cdef_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "lr in %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_lr_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "read_tx in %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_tx_mode(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "reference in%d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_frame_reference_mode(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "kip_mode in %d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_skip_mode_params(ctx, gb, f)); + + if (frame_is_intra || f->error_resilient_mode || + !seq->enable_warped_motion) + f->allow_warped_motion = 0; + else + READ_ONEBIT(gb, &f->allow_warped_motion); + + READ_ONEBIT(gb, &f->reduced_tx_set); + av1d_dbg(AV1D_DBG_HEADER, "motion in%d", mpp_get_bits_count(gb)); + + FUN_CHECK(read_global_motion_params(ctx, gb, f)); + av1d_dbg(AV1D_DBG_HEADER, "grain in %d", mpp_get_bits_count(gb)); + FUN_CHECK(read_film_grain_params(ctx, gb, &f->film_grain, f)); + av1d_dbg(AV1D_DBG_HEADER, "film_grain out %d", mpp_get_bits_count(gb)); + + av1d_dbg(AV1D_DBG_REF, "Frame %d: size %dx%d upscaled %d render %dx%d subsample %dx%d " + "bitdepth %d tiles %dx%d.\n", ctx->order_hint, + ctx->frame_width, ctx->frame_height, ctx->upscaled_width, + ctx->render_width, ctx->render_height, + seq->color_config.subsampling_x + 1, + seq->color_config.subsampling_y + 1, ctx->bit_depth, + ctx->tile_rows, ctx->tile_cols); + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_frame_header_obu(Av1Codec *ctx, BitReadCtx_t *gb, + AV1FrameHeader *f, RK_S32 redundant, + void *rw_buffer_ref) +{ + if (ctx->seen_frame_header) { + if (!redundant) { + mpp_err_f("Invalid repeated frame header OBU.\n"); + return MPP_ERR_UNKNOW; + } else { + BitReadCtx_t fh; + + mpp_set_bitread_ctx(&fh, ctx->frame_header_data, ctx->frame_header_size); + for (size_t i = 0; i < ctx->frame_header_size; i += 8) { + RK_S32 val; + RK_S32 b = MPP_MIN(ctx->frame_header_size - i, 8); + mpp_assert(b < 32); + mpp_read_bits(&fh, b, &val); + READ_BITS_LONG(gb, b, &val); + } + } + } else { + RK_S32 start_pos = mpp_get_bits_count(gb); + + FUN_CHECK(read_uncompressed_header(ctx, gb, f)); + + ctx->tile_num = 0; + ctx->seen_frame_header = f->show_existing_frame ? 0 : 1; + if (!f->show_existing_frame) { + RK_S32 fh_bits = mpp_get_bits_count(gb) - start_pos; + RK_U8 *fh_start = (RK_U8*)gb->buf + start_pos / 8; + RK_S32 fh_bytes = (fh_bits + 7) / 8; + + ctx->frame_header_size = fh_bits; + + // Store frame header for possible future use. + MPP_FREE(ctx->frame_header_data); + ctx->frame_header_data = mpp_malloc(RK_U8, fh_bytes + BUFFER_PADDING_SIZE); + if (!ctx->frame_header_data) { + mpp_err_f("frame header data malloc failed\n"); + return MPP_ERR_NOMEM; + } + memcpy(ctx->frame_header_data, fh_start, fh_bytes); + } + } + (void)rw_buffer_ref; + return MPP_OK; +__BITREAD_ERR: + return MPP_NOK; +} + +static MPP_RET read_tile_group_obu(Av1Codec *ctx, BitReadCtx_t *gb, + AV1TileGroup *tile) +{ + RK_S32 num_tiles = ctx->tile_cols * ctx->tile_rows; + + if (num_tiles > 1) + READ_ONEBIT(gb, &tile->tile_start_and_end_present_flag); + else + tile->tile_start_and_end_present_flag = 0; + + if (num_tiles == 1 || !tile->tile_start_and_end_present_flag) { + tile->tg_start = 0; + tile->tg_end = num_tiles - 1; + } else { + RK_S32 tile_bits = tile_log2(1, ctx->tile_cols) + tile_log2(1, ctx->tile_rows); + + READ_BITS_LONG(gb, tile_bits, &tile->tg_start); + READ_BITS_LONG(gb, tile_bits, &tile->tg_end); + } + + ctx->tile_num = tile->tg_end + 1; + + mpp_align_get_bits(gb); + + // reset for next frame + if (tile->tg_end == num_tiles - 1) + ctx->seen_frame_header = 0; + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_frame_obu(Av1Codec *ctx, BitReadCtx_t *gb, + AV1Frame *f, void *rw_buffer_ref) +{ + RK_U32 start_pos = mpp_get_bits_count(gb); + + FUN_CHECK(read_frame_header_obu(ctx, gb, &f->header, 0, rw_buffer_ref)); + + mpp_align_get_bits(gb); + + FUN_CHECK(read_tile_group_obu(ctx, gb, &f->tile_group)); + ctx->frame_tag_size += (mpp_get_bits_count(gb) - start_pos + 7) >> 3; + + return MPP_OK; +} + +static MPP_RET read_tile_list_obu(Av1Codec *ctx, BitReadCtx_t *gb, + AV1TileList *list) +{ + READ_BITS(gb, 8, &list->output_frame_width_in_tiles_minus_1); + READ_BITS(gb, 8, &list->output_frame_height_in_tiles_minus_1); + READ_BITS(gb, 16, &list->tile_count_minus_1); + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_metadata_hdr_cll(Av1Codec *ctx, BitReadCtx_t *gb, + AV1MetadataHDRCLL *cll) +{ + READ_BITS(gb, 16, &cll->max_cll); + READ_BITS(gb, 16, &cll->max_fall); + + ctx->content_light.MaxCLL = cll->max_cll; + ctx->content_light.MaxFALL = cll->max_fall; + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static RK_S32 read_metadata_hdr_mdcv(Av1Codec *ctx, BitReadCtx_t *gb, + AV1MetadataHDRMDCV *mdcv) +{ + RK_S32 i; + + for (i = 0; i < 3; i++) { + READ_BITS(gb, 16, &mdcv->primary_chromaticity_x[i]); + READ_BITS(gb, 16, &mdcv->primary_chromaticity_y[i]); + } + + READ_BITS(gb, 16, &mdcv->white_point_chromaticity_x); + READ_BITS(gb, 16, &mdcv->white_point_chromaticity_y); + + READ_BITS_LONG(gb, 32, &mdcv->luminance_max); + READ_BITS_LONG(gb, 32, &mdcv->luminance_min); + + for (i = 0; i < 3; i++) { + ctx->mastering_display.display_primaries[i][0] = mdcv->primary_chromaticity_x[i]; + ctx->mastering_display.display_primaries[i][1] = mdcv->primary_chromaticity_y[i]; + } + ctx->mastering_display.white_point[0] = mdcv->white_point_chromaticity_x; + ctx->mastering_display.white_point[1] = mdcv->white_point_chromaticity_y; + ctx->mastering_display.max_luminance = mdcv->luminance_max; + ctx->mastering_display.min_luminance = mdcv->luminance_min; + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_scalability_structure(Av1Codec *ctx, BitReadCtx_t *gb, + AV1MetadataScalability *scale) +{ + const AV1SeqHeader *seq = ctx->seq_header; + RK_S32 i, j; + + if (!seq) { + mpp_err_f("No sequence header available.\n"); + return MPP_ERR_UNKNOW; + } + + READ_BITS(gb, 2, &scale->spatial_layers_cnt_minus_1); + READ_ONEBIT(gb, &scale->spatial_layer_dimensions_present_flag); + READ_ONEBIT(gb, &scale->spatial_layer_description_present_flag); + READ_ONEBIT(gb, &scale->temporal_group_description_present_flag); + READ_BITS(gb, 3, &scale->scalability_structure_reserved_3bits); + if (scale->spatial_layer_dimensions_present_flag) { + for (i = 0; i <= scale->spatial_layers_cnt_minus_1; i++) { + READ_BITS(gb, 16, &scale->spatial_layer_max_width[i]); + READ_BITS(gb, 16, &scale->spatial_layer_max_height[i]); + } + } + if (scale->spatial_layer_description_present_flag) { + for (i = 0; i <= scale->spatial_layers_cnt_minus_1; i++) + READ_BITS(gb, 8, &scale->spatial_layer_ref_id[i]); + } + if (scale->temporal_group_description_present_flag) { + READ_BITS(gb, 8, &scale->temporal_group_size); + for (i = 0; i < scale->temporal_group_size; i++) { + READ_BITS(gb, 3, &scale->temporal_group_temporal_id[i]); + READ_ONEBIT(gb, &scale->temporal_group_temporal_switching_up_point_flag[i]); + READ_ONEBIT(gb, &scale->temporal_group_spatial_switching_up_point_flag[i]); + READ_BITS(gb, 3, &scale->temporal_group_ref_cnt[i]); + for (j = 0; j < scale->temporal_group_ref_cnt[i]; j++) { + READ_BITS(gb, 8, &scale->temporal_group_ref_pic_diff[i][j]); + } + } + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_metadata_scalability(Av1Codec *ctx, BitReadCtx_t *gb, + AV1MetadataScalability *scale) +{ + READ_BITS(gb, 8, &scale->scalability_mode_idc); + + if (scale->scalability_mode_idc == AV1_SCALABILITY_SS) + FUN_CHECK(read_scalability_structure(ctx, gb, scale)); + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET get_dlby_rpu(Av1Codec *ctx, BitReadCtx_t *gb) +{ + MppFrameHdrDynamicMeta *dynamic = ctx->hdr_dynamic_meta; + MppWriteCtx m_bc, *bc = &m_bc; + RK_U32 emdf_payload_size = 0; + RK_S32 flag = 0; + RK_U32 i; + + // skip emdf_container + SKIP_BITS(gb, 3); + SKIP_BITS(gb, 2); + SKIP_BITS(gb, 5); + SKIP_BITS(gb, 5); + SKIP_BITS(gb, 1); + SKIP_BITS(gb, 5); + SKIP_BITS(gb, 1); + // skip emdf_payload_config + SKIP_BITS(gb, 5); + + // get payload size + do { + RK_U32 tmp; + + READ_BITS(gb, 8, &tmp); + emdf_payload_size += tmp; + READ_ONEBIT(gb, &flag); + if (!flag) break; + emdf_payload_size <<= 8; + emdf_payload_size += (1 << 8); + } while (flag); + + if (!dynamic) { + dynamic = mpp_calloc_size(MppFrameHdrDynamicMeta, sizeof(*dynamic) + SZ_1K); + if (!dynamic) { + mpp_err_f("malloc hdr dynamic data failed!\n"); + return MPP_ERR_NOMEM; + } + } + + mpp_writer_init(bc, dynamic->data, SZ_1K); + + mpp_writer_put_raw_bits(bc, 0, 24); + mpp_writer_put_raw_bits(bc, 1, 8); + mpp_writer_put_raw_bits(bc, 0x19, 8); + for (i = 0; i < emdf_payload_size; i++) { + RK_U8 data; + + READ_BITS(gb, 8, &data); + mpp_writer_put_bits(bc, data, 8); + } + + dynamic->size = mpp_writer_bytes(bc); + dynamic->hdr_fmt = DLBY; + av1d_dbg(AV1D_DBG_STRMIN, "dlby rpu size %d -> %d\n", + emdf_payload_size, dynamic->size); + + ctx->hdr_dynamic_meta = dynamic; + ctx->hdr_dynamic = 1; + ctx->is_hdr = 1; + + if (av1d_debug & AV1D_DBG_DUMP_RPU) { + RK_U8 *p = dynamic->data; + char fname[128]; + FILE *fp_in = NULL; + static RK_U32 g_frame_no = 0; + + sprintf(fname, "/data/video/meta_%d.txt", g_frame_no++); + fp_in = fopen(fname, "wb"); + mpp_err("open %s %p\n", fname, fp_in); + if (fp_in) + fwrite(p, 1, dynamic->size, fp_in); + fflush(fp_in); + fclose(fp_in); + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET fill_dynamic_meta(Av1Codec *ctx, const RK_U8 *data, RK_U32 size, RK_U32 hdr_fmt) +{ + MppFrameHdrDynamicMeta *dynamic = ctx->hdr_dynamic_meta; + + if (dynamic && (dynamic->size < size)) { + mpp_free(dynamic); + dynamic = NULL; + } + + if (!dynamic) { + dynamic = mpp_calloc_size(MppFrameHdrDynamicMeta, sizeof(*dynamic) + size); + if (!dynamic) { + mpp_err_f("malloc hdr dynamic data failed!\n"); + return MPP_ERR_NOMEM; + } + } + if (size && data) { + switch (hdr_fmt) { + case HDR10PLUS: { + memcpy((RK_U8*)dynamic->data, (RK_U8*)data, size); + } break; + default: break; + } + dynamic->size = size; + dynamic->hdr_fmt = hdr_fmt; + + ctx->hdr_dynamic_meta = dynamic; + ctx->hdr_dynamic = 1; + ctx->is_hdr = 1; + } + return MPP_OK; +} + +static MPP_RET read_metadata_itut_t35(Av1Codec *ctx, BitReadCtx_t *gb, + AV1MetadataITUTT35 *t35) +{ + READ_BITS(gb, 8, &t35->itu_t_t35_country_code); + if (t35->itu_t_t35_country_code == 0xff) + READ_BITS(gb, 8, &t35->itu_t_t35_country_code_extension_byte); + + t35->payload_size = mpp_get_bits_left(gb) / 8 - 1; + + av1d_dbg(AV1D_DBG_STRMIN, "%s itu_t_t35_country_code %d payload_size %d\n", + __func__, t35->itu_t_t35_country_code, t35->payload_size); + + READ_BITS(gb, 16, &t35->itu_t_t35_terminal_provider_code); + + av1d_dbg(AV1D_DBG_STRMIN, "itu_t_t35_country_code 0x%x\n", + t35->itu_t_t35_country_code); + av1d_dbg(AV1D_DBG_STRMIN, "itu_t_t35_terminal_provider_code 0x%x\n", + t35->itu_t_t35_terminal_provider_code); + + switch (t35->itu_t_t35_terminal_provider_code) { + case 0x3B: {/* dlby provider_code is 0x3b*/ + READ_BITS_LONG(gb, 32, &t35->itu_t_t35_terminal_provider_oriented_code); + av1d_dbg(AV1D_DBG_STRMIN, "itu_t_t35_terminal_provider_oriented_code 0x%x\n", + t35->itu_t_t35_terminal_provider_oriented_code); + if (t35->itu_t_t35_terminal_provider_oriented_code == 0x800) + get_dlby_rpu(ctx, gb); + } break; + case 0x3C: {/* smpte2094_40 provider_code is 0x3c*/ + const RK_U16 smpte2094_40_provider_oriented_code = 0x0001; + const RK_U8 smpte2094_40_application_identifier = 0x04; + RK_U8 application_identifier; + + READ_BITS(gb, 16, &t35->itu_t_t35_terminal_provider_oriented_code); + av1d_dbg(AV1D_DBG_STRMIN, "itu_t_t35_terminal_provider_oriented_code 0x%x\n", + t35->itu_t_t35_terminal_provider_oriented_code); + READ_BITS(gb, 8, &application_identifier); + /* hdr10plus priverder_oriented_code is 0x0001, application_identifier is 0x04 */ + if (t35->itu_t_t35_terminal_provider_oriented_code == smpte2094_40_provider_oriented_code && + application_identifier == smpte2094_40_application_identifier) + fill_dynamic_meta(ctx, gb->data_, mpp_get_bits_left(gb) >> 3, HDR10PLUS); + } break; + default: + break; + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_metadata_timecode(Av1Codec *ctx, BitReadCtx_t *gb, + AV1MetadataTimecode *timecode) +{ + READ_BITS(gb, 5, &timecode->counting_type); + READ_ONEBIT(gb, &timecode->full_timestamp_flag); + READ_ONEBIT(gb, &timecode->discontinuity_flag); + READ_ONEBIT(gb, &timecode->cnt_dropped_flag); + READ_BITS(gb, 9, &timecode->n_frames); + + if (timecode->full_timestamp_flag) { + READ_BITS(gb, 6, &timecode->seconds_value); + READ_BITS(gb, 6, &timecode->minutes_value); + READ_BITS(gb, 5, &timecode->hours_value); + } else { + READ_ONEBIT(gb, &timecode->seconds_flag); + if (timecode->seconds_flag) { + READ_BITS(gb, 6, &timecode->seconds_value); + READ_ONEBIT(gb, &timecode->minutes_flag); + if (timecode->minutes_flag) { + READ_BITS(gb, 6, &timecode->minutes_value); + READ_ONEBIT(gb, &timecode->hours_flag); + if (timecode->hours_flag) + READ_BITS(gb, 5, &timecode->hours_value); + } + } + } + + READ_BITS(gb, 5, &timecode->time_offset_length); + if (timecode->time_offset_length > 0) + READ_BITS_LONG(gb, timecode->time_offset_length, &timecode->time_offset_value); + else + timecode->time_offset_length = 0; + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET read_metadata_obu(Av1Codec *ctx, BitReadCtx_t *gb, + AV1Metadata *meta) +{ + FUN_CHECK(read_leb128(gb, &meta->metadata_type)); + + av1d_dbg(AV1D_DBG_STRMIN, "%s meta type %lld\n", __func__, meta->metadata_type); + switch (meta->metadata_type) { + case AV1_METADATA_TYPE_HDR_CLL: + FUN_CHECK(read_metadata_hdr_cll(ctx, gb, &meta->metadata.hdr_cll)); + break; + case AV1_METADATA_TYPE_HDR_MDCV: + FUN_CHECK(read_metadata_hdr_mdcv(ctx, gb, &meta->metadata.hdr_mdcv)); + break; + case AV1_METADATA_TYPE_SCALABILITY: + FUN_CHECK(read_metadata_scalability(ctx, gb, &meta->metadata.scalability)); + break; + case AV1_METADATA_TYPE_ITUT_T35: + FUN_CHECK(read_metadata_itut_t35(ctx, gb, &meta->metadata.itut_t35)); + break; + case AV1_METADATA_TYPE_TIMECODE: + FUN_CHECK(read_metadata_timecode(ctx, gb, &meta->metadata.timecode)); + break; + default: + mpp_err_f("unknown metadata type %lld\n", meta->metadata_type); + break; + } + + return MPP_OK; +} + +static MPP_RET read_padding_obu(Av1Codec *ctx, BitReadCtx_t *gb, AV1Padding *pad) +{ + BitReadCtx_t tmp_gb; + RK_S32 flag, last_nonzero_byte = 0; + RK_U32 i; + + // make a copy of gb for read twice + memcpy(&tmp_gb, gb, sizeof(*gb)); + + // read first, find last non-zero byte + for (i = 0; mpp_get_bits_left(gb) >= 8; i++) { + READ_BITS(gb, 8, &flag); + if (flag) + last_nonzero_byte = i; + } + pad->payload_size = last_nonzero_byte; + pad->payload = mpp_malloc(RK_U8, pad->payload_size); + if (!pad->payload ) + return MPP_ERR_NOMEM; + + // read twice for padding payload + memcpy(gb, &tmp_gb, sizeof(*gb)); + for (i = 0; i < pad->payload_size; i++) + READ_BITS(gb, 8, &pad->payload[i]); + + (void)ctx; + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_READ_BIT; +} + +static MPP_RET insert_unit_data(Av1UnitFragment *frag, RK_S32 position, + RK_U32 type, RK_U8 *data, size_t data_size) +{ + Av1ObuUnit *units; + + if (position == -1) + position = frag->nb_units; + mpp_assert(position >= 0 && position <= frag->nb_units); + + // Make space for new unit. + if (frag->nb_units < frag->nb_units_allocated) { + units = frag->units; + + if (position < frag->nb_units) + memmove(units + position + 1, units + position, + (frag->nb_units - position) * sizeof(*units)); + } else { + units = mpp_malloc(Av1ObuUnit, frag->nb_units * 2 + 1); + if (!units) + return MPP_ERR_NOMEM; + + frag->nb_units_allocated = 2 * frag->nb_units_allocated + 1; + + if (position > 0) + memcpy(units, frag->units, position * sizeof(*units)); + + if (position < frag->nb_units) + memcpy(units + position + 1, frag->units + position, + (frag->nb_units - position) * sizeof(*units)); + } + + memset(units + position, 0, sizeof(*units)); + + // Update fragment unit list. + if (units != frag->units) { + mpp_free(frag->units); + frag->units = units; + } + ++frag->nb_units; + + // Fill in unit data. + frag->units[position].type = type; + frag->units[position].data = data; + frag->units[position].data_size = data_size; + + return MPP_OK; +} + +static MPP_RET read_ref_tile_data(Av1ObuUnit *unit, BitReadCtx_t *gb, AV1TileData *td) +{ + RK_S32 pos = mpp_get_bits_count(gb); + + if (pos >= (RK_S32)(8 * unit->data_size)) { + mpp_err( "Bitstream ended before %d bits read.\n", pos); + return MPP_ERR_STREAM; + } + // Must be byte-aligned at this point. + mpp_assert(pos % 8 == 0); + + td->offset = pos / 8; + td->data = unit->data + pos / 8; + td->data_size = unit->data_size - pos / 8; + + return MPP_OK; +} + +static MPP_RET read_one_obu_unit(Av1Codec *ctx, Av1ObuUnit *unit) +{ + AV1OBU *obu = &unit->obu; + AV1OBUHeader *h = &obu->header; + BitReadCtx_t m_gb, *gb = &m_gb; + RK_S32 start_pos, end_pos, hdr_start_pos; + MPP_RET ret = MPP_OK; + + memset(obu, 0, sizeof(*obu)); + mpp_set_bitread_ctx(gb, unit->data, unit->data_size); + hdr_start_pos = mpp_get_bits_count(gb); + + ret = av1d_read_obu_header(gb, h); + if (ret < 0) + return ret; + mpp_assert(h->obu_type == unit->type); + ctx->temporal_id = h->temporal_id; + ctx->spatial_id = h->spatial_id; + + if (h->obu_has_size_field) { + obu->obu_size = h->obu_filed_size; + } else { + if (unit->data_size < (RK_U32)(1 + h->obu_extension_flag)) { + mpp_err( "Invalid OBU length %d, too short.\n", unit->data_size); + return MPP_NOK; + } + obu->obu_size = unit->data_size - 1 - h->obu_extension_flag; + } + + start_pos = mpp_get_bits_count(gb); + if (!ctx->fist_tile_group) + ctx->frame_tag_size += ((start_pos - hdr_start_pos + 7) >> 3); + if (h->obu_extension_flag) { + if (h->obu_type != AV1_OBU_SEQUENCE_HEADER && + h->obu_type != AV1_OBU_TEMPORAL_DELIMITER && + ctx->operating_point_idc) { + RK_S32 in_temporal_layer = (ctx->operating_point_idc >> ctx->temporal_id) & 1; + RK_S32 in_spatial_layer = (ctx->operating_point_idc >> (ctx->spatial_id + 8)) & 1; + if (!in_temporal_layer || !in_spatial_layer) { + return MPP_ERR_PROTOL; // drop_obu() + } + } + } + av1d_dbg(AV1D_DBG_HEADER, "obu type %d size %d\n", h->obu_type, obu->obu_size); + switch (h->obu_type) { + case AV1_OBU_SEQUENCE_HEADER: { + ret = read_sequence_header_obu(ctx, gb, &obu->payload.seq_header); + if (ret < 0) + return ret; + ctx->frame_tag_size += obu->obu_size; + if (ctx->operating_point >= 0) { + AV1SeqHeader *seq = &obu->payload.seq_header; + + if (ctx->operating_point > seq->operating_points_cnt_minus_1) { + mpp_err("Invalid Operating Point %d requested, Must not be higher than %u.\n", + ctx->operating_point, seq->operating_points_cnt_minus_1); + return MPP_ERR_PROTOL; + } + ctx->operating_point_idc = seq->operating_point_idc[ctx->operating_point]; + } + + ctx->seq_header = NULL; + ctx->seq_header = &obu->payload.seq_header; + } break; + case AV1_OBU_TEMPORAL_DELIMITER: { + ret = read_temporal_delimiter_obu(ctx, gb); + if (ret < 0) + return ret; + } break; + case AV1_OBU_FRAME_HEADER: + case AV1_OBU_REDUNDANT_FRAME_HEADER: { + ret = read_frame_header_obu(ctx, gb, &obu->payload.frame_header, + h->obu_type == AV1_OBU_REDUNDANT_FRAME_HEADER, + NULL); + if (ret < 0) + return ret; + ctx->frame_tag_size += obu->obu_size; + } break; + case AV1_OBU_TILE_GROUP: { + RK_U32 cur_pos = mpp_get_bits_count(gb); + + ret = read_tile_group_obu(ctx, gb, &obu->payload.tile_group); + if (ret < 0) + return ret; + if (!ctx->fist_tile_group) + ctx->frame_tag_size += MPP_ALIGN(mpp_get_bits_count(gb) - cur_pos, 8) / 8; + ctx->fist_tile_group = 1; + ret = read_ref_tile_data(unit, gb, &obu->payload.tile_group.tile_data); + if (ret < 0) + return ret; + } break; + case AV1_OBU_FRAME: { + ret = read_frame_obu(ctx, gb, &obu->payload.frame, NULL); + if (ret < 0) + return ret; + + ret = read_ref_tile_data(unit, gb, &obu->payload.frame.tile_group.tile_data); + if (ret < 0) + return ret; + } break; + case AV1_OBU_TILE_LIST: { + ret = read_tile_list_obu(ctx, gb, &obu->payload.tile_list); + if (ret < 0) + return ret; + + ret = read_ref_tile_data(unit, gb, &obu->payload.tile_list.tile_data); + if (ret < 0) + return ret; + } break; + case AV1_OBU_METADATA: { + ctx->frame_tag_size += obu->obu_size; + ret = read_metadata_obu(ctx, gb, &obu->payload.metadata); + if (ret < 0) + return ret; + } break; + case AV1_OBU_PADDING: { + ret = read_padding_obu(ctx, gb, &obu->payload.padding); + if (ret < 0) + return ret; + } break; + default: + return MPP_ERR_VALUE; + } + + end_pos = mpp_get_bits_count(gb); + mpp_assert(end_pos <= (RK_S32)(unit->data_size * 8)); + + if (obu->obu_size > 0 && + h->obu_type != AV1_OBU_TILE_GROUP && + h->obu_type != AV1_OBU_TILE_LIST && + h->obu_type != AV1_OBU_FRAME) { + RK_S32 nb_bits = obu->obu_size * 8 + start_pos - end_pos; + + if (nb_bits <= 0) + return MPP_NOK; + // skip the remaining bits in the OBU + while (nb_bits >= 32) { + SKIP_BITS(gb, 16); + nb_bits -= 16; + } + SKIP_BITS(gb, nb_bits); + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +MPP_RET av1d_parser_fragment_header(Av1UnitFragment *frag) +{ + RK_U8 *data = frag->data; + size_t size = frag->data_size; + + if (size && data[0] & 0x80) { + RK_S32 version = data[0] & 0x7f; + + if (version != 1) { + mpp_err( "Unknown version %d!\n", version); + goto fail; + } + if (size < 4) { + mpp_err("Size %d invalid\n", size); + goto fail; + } + frag->data += 4; + frag->data_size -= 4; + } + + return MPP_OK; + +fail: + frag->data_size = 0; + return MPP_NOK; +} + +MPP_RET av1d_get_fragment_units(Av1UnitFragment *frag) +{ + RK_U8 *data = frag->data; + size_t size = frag->data_size; + MPP_RET ret = MPP_NOK; + + if (INT_MAX / 8 < size) { + mpp_err( "Invalid size (%d bytes).\n", size); + ret = MPP_NOK; + goto fail; + } + + while (size > 0) { + AV1OBUHeader m_hdr; + BitReadCtx_t m_gb, *gb = &m_gb; + RK_S32 pos = 0; + RK_U64 obu_size = 0; + RK_U64 obu_length = 0; + + memset(&m_hdr, 0, sizeof(m_hdr)); + mpp_set_bitread_ctx(gb, data, size); + ret = av1d_read_obu_header(gb, &m_hdr); + if (ret < 0) + goto fail; + + if (m_hdr.obu_has_size_field) + obu_size = m_hdr.obu_filed_size; + else + obu_size = size - 1 - m_hdr.obu_extension_flag; + + pos = mpp_get_bits_count(gb); + mpp_assert(pos % 8 == 0); + mpp_assert(pos / 8 <= (RK_S32)size); + obu_length = pos / 8 + obu_size; + + if (size < obu_length) { + mpp_err( "Invalid OBU length: %lld > %d remaining bytes.\n", + obu_length, size); + ret = MPP_NOK; + goto fail; + } + ret = insert_unit_data(frag, -1, m_hdr.obu_type, data, obu_length); + if (ret < 0) + goto fail; + + data += obu_length; + size -= obu_length; + } + + ret = MPP_OK; +fail: + return ret; +} + +MPP_RET av1d_read_fragment_uints(Av1Codec *ctx, Av1UnitFragment *frag) +{ + MPP_RET ret = MPP_NOK; + RK_S32 i, j; + + ctx->frame_tag_size = 0; + ctx->fist_tile_group = 0; + for (i = 0; i < frag->nb_units; i++) { + Av1ObuUnit *unit = &frag->units[i]; + + if (ctx->unit_types) { + for (j = 0; j < ctx->nb_unit_types; j++) { + if (ctx->unit_types[j] == unit->type) + break; + } + if (j >= ctx->nb_unit_types) + continue; + } + mpp_assert(unit->data); + ret = read_one_obu_unit(ctx, unit); + + if (ret < 0) { + mpp_err_f("Failed to read unit %d (type %d).\n", i, unit->type); + return ret; + } + av1d_dbg(AV1D_DBG_HEADER, "obu_type %d, obu_size %d, frame_tag_size %d", + unit->obu.header.obu_type, unit->obu.obu_size, ctx->frame_tag_size); + } + return MPP_OK; +} + +MPP_RET av1d_fragment_reset(Av1UnitFragment *frag) +{ + RK_S32 i; + + for (i = 0; i < frag->nb_units; i++) { + Av1ObuUnit *unit = &frag->units[i]; + + memset(&unit->obu, 0, sizeof(unit->obu)); + unit->data = NULL; + unit->data_size = 0; + } + frag->nb_units = 0; + frag->data = NULL; + frag->data_size = 0; + + return MPP_OK; +} diff --git a/mpp/codec/dec/av1/av1d_ctx.h b/mpp/codec/dec/av1/av1d_ctx.h new file mode 100644 index 000000000..1473b9b8b --- /dev/null +++ b/mpp/codec/dec/av1/av1d_ctx.h @@ -0,0 +1,657 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef AV1D_CODEC_H +#define AV1D_CODEC_H + +#include "mpp_frame.h" + +#include "mpp_bitread.h" +#include "av1d_syntax.h" + +// Profiles +#define AV1_PROFILE_MAIN 0 +#define AV1_PROFILE_HIGH 1 +#define AV1_PROFILE_PROFESSIONAL 2 + +// Constants +#define AV1_MAX_OPERATING_POINTS 32 +#define AV1_SELECT_SCREEN_CONTENT_TOOLS 2 +#define AV1_SELECT_INTEGER_MV 2 +#define AV1_SUPERRES_NUM 8 +#define AV1_SUPERRES_DENOM_MIN 9 + +// Divisor lookup table +#define AV1_DIV_LUT_BITS 8 +#define AV1_DIV_LUT_PREC_BITS 14 +#define AV1_DIV_LUT_NUM 257 + +// global motion params bits +#define AV1_GM_ABS_ALPHA_BITS 12 +#define AV1_GM_ALPHA_PREC_BITS 15 +#define AV1_GM_ABS_TRANS_ONLY_BITS 9 +#define AV1_GM_TRANS_ONLY_PREC_BITS 3 +#define AV1_GM_ABS_TRANS_BITS 12 +#define AV1_GM_TRANS_PREC_BITS 6 + +// Bits of precision used for the model +#define AV1_WARPEDMODEL_PREC_BITS 16 + +// OBU types +enum { + // 0 reserved. + AV1_OBU_SEQUENCE_HEADER = 1, + AV1_OBU_TEMPORAL_DELIMITER = 2, + AV1_OBU_FRAME_HEADER = 3, + AV1_OBU_TILE_GROUP = 4, + AV1_OBU_METADATA = 5, + AV1_OBU_FRAME = 6, + AV1_OBU_REDUNDANT_FRAME_HEADER = 7, + AV1_OBU_TILE_LIST = 8, + // 9-14 reserved. + AV1_OBU_PADDING = 15, +} ; + +// Metadata types +enum { + AV1_METADATA_TYPE_HDR_CLL = 1, + AV1_METADATA_TYPE_HDR_MDCV = 2, + AV1_METADATA_TYPE_SCALABILITY = 3, + AV1_METADATA_TYPE_ITUT_T35 = 4, + AV1_METADATA_TYPE_TIMECODE = 5, +}; + +// Warp models +enum { + AV1_WARP_MODEL_IDENTITY = 0, // identity transformation, 0-parameter + AV1_WARP_MODEL_TRANSLATION = 1, // translational motion 2-parameter + AV1_WARP_MODEL_ROTZOOM = 2, // simplified affine with rotation + zoom only, 4-parameter + AV1_WARP_MODEL_AFFINE = 3, // affine, 6-parameter + AV1_WARP_PARAM_REDUCE_BITS = 6, +}; + +// Chroma sample position +enum { + AV1_CSP_UNKNOWN = 0, + AV1_CSP_VERTICAL = 1, + AV1_CSP_COLOCATED = 2, +}; + +// Scalability modes +enum { + AV1_SCALABILITY_L1T2 = 0, + AV1_SCALABILITY_L1T3 = 1, + AV1_SCALABILITY_L2T1 = 2, + AV1_SCALABILITY_L2T2 = 3, + AV1_SCALABILITY_L2T3 = 4, + AV1_SCALABILITY_S2T1 = 5, + AV1_SCALABILITY_S2T2 = 6, + AV1_SCALABILITY_S2T3 = 7, + AV1_SCALABILITY_L2T1h = 8, + AV1_SCALABILITY_L2T2h = 9, + AV1_SCALABILITY_L2T3h = 10, + AV1_SCALABILITY_S2T1h = 11, + AV1_SCALABILITY_S2T2h = 12, + AV1_SCALABILITY_S2T3h = 13, + AV1_SCALABILITY_SS = 14, + AV1_SCALABILITY_L3T1 = 15, + AV1_SCALABILITY_L3T2 = 16, + AV1_SCALABILITY_L3T3 = 17, + AV1_SCALABILITY_S3T1 = 18, + AV1_SCALABILITY_S3T2 = 19, + AV1_SCALABILITY_S3T3 = 20, + AV1_SCALABILITY_L3T2_KEY = 21, + AV1_SCALABILITY_L3T3_KEY = 22, + AV1_SCALABILITY_L4T5_KEY = 23, + AV1_SCALABILITY_L4T7_KEY = 24, + AV1_SCALABILITY_L3T2_KEY_SHIFT = 25, + AV1_SCALABILITY_L3T3_KEY_SHIFT = 26, + AV1_SCALABILITY_L4T5_KEY_SHIFT = 27, + AV1_SCALABILITY_L4T7_KEY_SHIFT = 28, +}; + +typedef struct AV1ColorConfig_t { + RK_U8 high_bitdepth; + RK_U8 twelve_bit; + RK_U8 mono_chrome; + + RK_U8 color_description_present_flag; + RK_U8 color_primaries; + RK_U8 transfer_characteristics; + RK_U8 matrix_coefficients; + + RK_U8 color_range; + RK_U8 subsampling_x; + RK_U8 subsampling_y; + RK_U8 chroma_sample_position; + RK_U8 separate_uv_delta_q; +} AV1ColorConfig; + +typedef struct AV1TimingInfo_t { + RK_U32 num_units_in_display_tick; + RK_U32 time_scale; + + RK_U8 equal_picture_interval; + RK_U32 num_ticks_per_picture_minus_1; +} AV1TimingInfo; + +typedef struct AV1DecoderModelInfo_t { + RK_U8 buffer_delay_length_minus_1; + RK_U32 num_units_in_decoding_tick; + RK_U8 buffer_removal_time_length_minus_1; + RK_U8 frame_presentation_time_length_minus_1; +} AV1DecoderModelInfo; + +typedef struct AV1SequenceHeader_t { + RK_U8 seq_profile; + RK_U8 still_picture; + RK_U8 reduced_still_picture_header; + + RK_U8 timing_info_present_flag; + RK_U8 decoder_model_info_present_flag; + RK_U8 initial_display_delay_present_flag; + RK_U8 operating_points_cnt_minus_1; + + AV1TimingInfo timing_info; + AV1DecoderModelInfo decoder_model_info; + + RK_U16 operating_point_idc[AV1_MAX_OPERATING_POINTS]; + RK_U8 seq_level_idx[AV1_MAX_OPERATING_POINTS]; + RK_U8 seq_tier[AV1_MAX_OPERATING_POINTS]; + RK_U8 decoder_model_present_for_this_op[AV1_MAX_OPERATING_POINTS]; + RK_U32 decoder_buffer_delay[AV1_MAX_OPERATING_POINTS]; + RK_U32 encoder_buffer_delay[AV1_MAX_OPERATING_POINTS]; + RK_U8 low_delay_mode_flag[AV1_MAX_OPERATING_POINTS]; + RK_U8 initial_display_delay_present_for_this_op[AV1_MAX_OPERATING_POINTS]; + RK_U8 initial_display_delay_minus_1[AV1_MAX_OPERATING_POINTS]; + + RK_U8 frame_width_bits_minus_1; + RK_U8 frame_height_bits_minus_1; + RK_U16 max_frame_width_minus_1; + RK_U16 max_frame_height_minus_1; + + RK_U8 frame_id_numbers_present_flag; + RK_U8 delta_frame_id_length_minus_2; + RK_U8 additional_frame_id_length_minus_1; + + RK_U8 use_128x128_superblock; + RK_U8 enable_filter_intra; + RK_U8 enable_intra_edge_filter; + RK_U8 enable_interintra_compound; + RK_U8 enable_masked_compound; + RK_U8 enable_warped_motion; + RK_U8 enable_dual_filter; + + RK_U8 enable_order_hint; + RK_U8 enable_jnt_comp; + RK_U8 enable_ref_frame_mvs; + + RK_U8 seq_choose_screen_content_tools; + RK_U8 seq_force_screen_content_tools; + RK_U8 seq_choose_integer_mv; + RK_U8 seq_force_integer_mv; + + RK_U8 order_hint_bits_minus_1; + + RK_U8 enable_superres; + RK_U8 enable_cdef; + RK_U8 enable_restoration; + + AV1ColorConfig color_config; + + RK_U8 film_grain_params_present; +} AV1SeqHeader; + +typedef struct AV1FilmGrainParams_t { + RK_U8 apply_grain; + RK_U16 grain_seed; + RK_U8 update_grain; + RK_U8 film_grain_params_ref_idx; + RK_U8 num_y_points; + RK_U8 point_y_value[14]; + RK_U8 point_y_scaling[14]; + RK_U8 chroma_scaling_from_luma; + RK_U8 num_cb_points; + RK_U8 point_cb_value[10]; + RK_U8 point_cb_scaling[10]; + RK_U8 num_cr_points; + RK_U8 point_cr_value[10]; + RK_U8 point_cr_scaling[10]; + RK_U8 grain_scaling_minus_8; + RK_U8 ar_coeff_lag; + RK_U8 ar_coeffs_y_plus_128[24]; + RK_U8 ar_coeffs_cb_plus_128[25]; + RK_U8 ar_coeffs_cr_plus_128[25]; + RK_U8 ar_coeff_shift_minus_6; + RK_U8 grain_scale_shift; + RK_U8 cb_mult; + RK_U8 cb_luma_mult; + RK_U16 cb_offset; + RK_U8 cr_mult; + RK_U8 cr_luma_mult; + RK_U16 cr_offset; + RK_U8 overlap_flag; + RK_U8 clip_to_restricted_range; +} AV1FilmGrainParams; + +typedef struct AV1FrameHeader_t { + RK_U8 show_existing_frame; + RK_U8 frame_to_show_map_idx; + RK_U32 frame_presentation_time; + RK_U32 display_frame_id; + + RK_U8 frame_type; + RK_U8 show_frame; + RK_U8 showable_frame; + + RK_U8 error_resilient_mode; + RK_U8 disable_cdf_update; + RK_U8 allow_screen_content_tools; + RK_U8 force_integer_mv; + + RK_S32 current_frame_id; + RK_U8 frame_size_override_flag; + RK_U8 order_hint; + + RK_U8 buffer_removal_time_present_flag; + RK_U32 buffer_removal_time[AV1_MAX_OPERATING_POINTS]; + + RK_U8 primary_ref_frame; + RK_U16 frame_width_minus_1; + RK_U16 frame_height_minus_1; + RK_U8 use_superres; + RK_U8 coded_denom; + RK_U8 render_and_frame_size_different; + RK_U16 render_width_minus_1; + RK_U16 render_height_minus_1; + + RK_U8 found_ref[AV1_REFS_PER_FRAME]; + + RK_U8 refresh_frame_flags; + RK_U8 allow_intrabc; + RK_U8 ref_order_hint[AV1_NUM_REF_FRAMES]; + RK_U8 frame_refs_short_signaling; + RK_U8 last_frame_idx; + RK_U8 golden_frame_idx; + RK_U8 ref_frame_valued; + RK_S8 ref_frame_idx[AV1_REFS_PER_FRAME]; + RK_U32 delta_frame_id_minus1[AV1_REFS_PER_FRAME]; + + RK_U8 allow_high_precision_mv; + RK_U8 is_filter_switchable; + RK_U8 interpolation_filter; + RK_U8 is_motion_mode_switchable; + RK_U8 use_ref_frame_mvs; + + RK_U8 disable_frame_end_update_cdf; + + RK_U8 uniform_tile_spacing_flag; + RK_U8 tile_cols_log2; + RK_U8 tile_rows_log2; + RK_U8 width_in_sbs_minus_1[AV1_MAX_TILE_COLS]; + RK_U8 height_in_sbs_minus_1[AV1_MAX_TILE_ROWS]; + RK_U16 context_update_tile_id; + RK_U8 tile_size_bytes_minus1; + + RK_U16 tile_cols; + RK_U16 tile_rows; + + RK_U8 base_q_idx; + RK_S8 delta_q_y_dc; + RK_U8 diff_uv_delta; + RK_S8 delta_q_u_dc; + RK_S8 delta_q_u_ac; + RK_S8 delta_q_v_dc; + RK_S8 delta_q_v_ac; + RK_U8 using_qmatrix; + RK_U8 qm_y; + RK_U8 qm_u; + RK_U8 qm_v; + + RK_U8 segmentation_enabled; + RK_U8 segmentation_update_map; + RK_U8 segmentation_temporal_update; + RK_U8 segmentation_update_data; + RK_U8 feature_enabled[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; + RK_S16 feature_value[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; + RK_U8 segmentation_id_last_active; + RK_U8 segmentation_id_preskip; + + RK_U8 delta_q_present; + RK_U8 delta_q_res; + RK_U8 delta_lf_present; + RK_U8 delta_lf_res; + RK_U8 delta_lf_multi; + + RK_U8 loop_filter_level[4]; + RK_U8 loop_filter_sharpness; + RK_U8 loop_filter_delta_enabled; + RK_U8 loop_filter_delta_update; + RK_U8 update_ref_delta[AV1_TOTAL_REFS_PER_FRAME]; + RK_S8 loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME]; + RK_U8 update_mode_delta[2]; + RK_S8 loop_filter_mode_deltas[2]; + + RK_U8 cdef_damping_minus_3; + RK_U8 cdef_bits; + RK_U8 cdef_y_pri_strength[8]; + RK_U8 cdef_y_sec_strength[8]; + RK_U8 cdef_uv_pri_strength[8]; + RK_U8 cdef_uv_sec_strength[8]; + + RK_U8 lr_type[3]; + RK_U8 lr_unit_shift; + RK_U8 lr_uv_shift; + + RK_U8 tx_mode; + RK_U8 reference_select; + RK_U8 skip_mode_present; + + RK_U8 allow_warped_motion; + RK_U8 reduced_tx_set; + + RK_U8 is_global[AV1_TOTAL_REFS_PER_FRAME]; + RK_U8 is_rot_zoom[AV1_TOTAL_REFS_PER_FRAME]; + RK_U8 is_translation[AV1_TOTAL_REFS_PER_FRAME]; + + RK_U32 gm_params[AV1_TOTAL_REFS_PER_FRAME][6]; + + AV1FilmGrainParams film_grain; +} AV1FrameHeader; + +typedef struct AV1TileData_t { + RK_U8 *data; + size_t offset; + size_t data_size; +} AV1TileData; + +typedef struct AV1TileGroup_t { + RK_U8 tile_start_and_end_present_flag; + RK_U8 tg_start; + RK_U8 tg_end; + + AV1TileData tile_data; +} AV1TileGroup; + +typedef struct AV1Frame_t { + AV1FrameHeader header; + AV1TileGroup tile_group; +} AV1Frame; + +typedef struct AV1TileList_t { + RK_U8 output_frame_width_in_tiles_minus_1; + RK_U8 output_frame_height_in_tiles_minus_1; + RK_U8 tile_count_minus_1; + + AV1TileData tile_data; +} AV1TileList; + +typedef struct AV1MetadataHDRCLL_t { + RK_U16 max_cll; + RK_U16 max_fall; +} AV1MetadataHDRCLL; + +typedef struct AV1MetadataHDRMDCV_t { + RK_U16 primary_chromaticity_x[3]; + RK_U16 primary_chromaticity_y[3]; + RK_U16 white_point_chromaticity_x; + RK_U16 white_point_chromaticity_y; + RK_U32 luminance_max; + RK_U32 luminance_min; +} AV1MetadataHDRMDCV; + +typedef struct AV1MetadataScalability_t { + RK_U8 scalability_mode_idc; + RK_U8 spatial_layers_cnt_minus_1; + RK_U8 spatial_layer_dimensions_present_flag; + RK_U8 spatial_layer_description_present_flag; + RK_U8 temporal_group_description_present_flag; + RK_U8 scalability_structure_reserved_3bits; + RK_U8 spatial_layer_max_width[4]; + RK_U8 spatial_layer_max_height[4]; + RK_U8 spatial_layer_ref_id[4]; + RK_U8 temporal_group_size; + RK_U8 temporal_group_temporal_id[255]; + RK_U8 temporal_group_temporal_switching_up_point_flag[255]; + RK_U8 temporal_group_spatial_switching_up_point_flag[255]; + RK_U8 temporal_group_ref_cnt[255]; + RK_U8 temporal_group_ref_pic_diff[255][7]; +} AV1MetadataScalability; + +typedef struct AV1MetadataITUTT35_t { + RK_U8 itu_t_t35_country_code; + RK_U8 itu_t_t35_country_code_extension_byte; + RK_U32 itu_t_t35_terminal_provider_code; + RK_U32 itu_t_t35_terminal_provider_oriented_code; + + RK_U8 *payload; + size_t payload_size; +} AV1MetadataITUTT35; + +typedef struct AV1MetadataTimecode_t { + RK_U8 counting_type; + RK_U8 full_timestamp_flag; + RK_U8 discontinuity_flag; + RK_U8 cnt_dropped_flag; + RK_U8 n_frames; + RK_U8 seconds_value; + RK_U8 minutes_value; + RK_U8 hours_value; + RK_U8 seconds_flag; + RK_U8 minutes_flag; + RK_U8 hours_flag; + RK_U8 time_offset_length; + RK_U32 time_offset_value; +} AV1MetadataTimecode; + +typedef struct AV1Metadata_t { + RK_U64 metadata_type; + union { + AV1MetadataHDRCLL hdr_cll; + AV1MetadataHDRMDCV hdr_mdcv; + AV1MetadataScalability scalability; + AV1MetadataITUTT35 itut_t35; + AV1MetadataTimecode timecode; + } metadata; +} AV1Metadata; + +typedef struct AV1Padding_t { + RK_U8 *payload; + size_t payload_size; +} AV1Padding; + + +typedef struct AV1OBUHeader_t { + RK_U8 obu_forbidden_bit; + RK_U8 obu_type; + RK_U8 obu_extension_flag; + RK_U8 obu_has_size_field; + RK_U8 obu_reserved_1bit; + + RK_U8 temporal_id; + RK_U8 spatial_id; + RK_U8 extension_header_reserved_3bits; + + RK_U64 obu_filed_size; // when obu_has_size_field=1 +} AV1OBUHeader; + +typedef struct AV1OBU_t { + AV1OBUHeader header; + + size_t obu_size; + union { + AV1SeqHeader seq_header; + AV1FrameHeader frame_header; + AV1Frame frame; + AV1TileGroup tile_group; + AV1TileList tile_list; + AV1Metadata metadata; + AV1Padding padding; + } payload; +} AV1OBU; + +typedef struct AV1RefFrameState_t { + RK_S32 valid; // RefValid + RK_S32 frame_id; // RefFrameId + RK_S32 upscaled_width; // RefUpscaledWidth + RK_S32 frame_width; // RefFrameWidth + RK_S32 frame_height; // RefFrameHeight + RK_S32 render_width; // RefRenderWidth + RK_S32 render_height; // RefRenderHeight + RK_S32 frame_type; // RefFrameType + RK_S32 subsampling_x; // RefSubsamplingX + RK_S32 subsampling_y; // RefSubsamplingY + RK_S32 bit_depth; // RefBitDepth + RK_S32 order_hint; // RefOrderHint + + RK_S8 loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME]; + RK_S8 loop_filter_mode_deltas[2]; + RK_U8 feature_enabled[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; + RK_S16 feature_value[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; +} AV1RefFrameState; + +typedef struct Av1ObuUnit_t { + RK_U32 type; + RK_U8 *data; + size_t data_size; + AV1OBU obu; +} Av1ObuUnit; + +typedef struct Av1UnitFragment_t { + RK_U8 *data; + size_t data_size; + RK_S32 nb_units; + RK_S32 nb_units_allocated; + Av1ObuUnit *units; +} Av1UnitFragment; + +typedef struct AV1DRefInfo_t { + RK_S32 ref_count; + RK_U32 invisible; + RK_U32 is_output; + RK_U32 lst_frame_offset; + RK_U32 lst2_frame_offset; + RK_U32 lst3_frame_offset; + RK_U32 gld_frame_offset; + RK_U32 bwd_frame_offset; + RK_U32 alt2_frame_offset; + RK_U32 alt_frame_offset; + RK_U32 is_intra_frame; + RK_U32 intra_only; +} Av1RefInfo; + +typedef struct AV1WarpedMotion_t { + RK_U32 wmtype; + RK_S32 wmmat[6]; + RK_S32 wmmat_val[6]; + RK_S32 alpha, beta, gamma, delta; +} AV1WarpedMotion; + +typedef struct AV1FrameInfo_t { + MppFrame f; + RK_S32 slot_index; + RK_S32 temporal_id; + RK_S32 spatial_id; + RK_U8 order_hint; + AV1WarpedMotion gm_params[AV1_NUM_REF_FRAMES]; + + RK_U8 skip_mode_frame_idx[2]; + AV1FilmGrainParams film_grain; + RK_U8 coded_lossless; + Av1RefInfo *ref; +} AV1FrameIInfo; + +typedef struct Av1Codec_t { + BitReadCtx_t gb; + + AV1SeqHeader *seq_header; + AV1SeqHeader *seq_ref; + AV1FrameHeader *frame_header; + Av1UnitFragment current_obu; + + RK_S32 seen_frame_header; + RK_U8 *frame_header_data; + size_t frame_header_size; + + AV1FrameIInfo ref[AV1_NUM_REF_FRAMES]; + AV1FrameIInfo cur_frame; + + MppFrameMasteringDisplayMetadata mastering_display; + MppFrameContentLightMetadata content_light; + MppFrameHdrDynamicMeta *hdr_dynamic_meta; + RK_U32 hdr_dynamic; + RK_U32 is_hdr; + + RK_S32 temporal_id; + RK_S32 spatial_id; + RK_S32 operating_point_idc; + + RK_S32 bit_depth; + RK_S32 order_hint; + RK_S32 frame_width; + RK_S32 frame_height; + RK_S32 upscaled_width; + RK_S32 render_width; + RK_S32 render_height; + + RK_S32 num_planes; + RK_S32 coded_lossless; + RK_S32 all_lossless; + RK_S32 tile_cols; + RK_S32 tile_rows; + RK_S32 tile_num; + RK_S32 operating_point; + RK_S32 extra_has_frame; + RK_U32 frame_tag_size; + RK_U32 fist_tile_group; + RK_U32 tile_offset; + + AV1CDFs *cdfs; + Av1MvCDFs *cdfs_ndvc; + AV1CDFs default_cdfs; + Av1MvCDFs default_cdfs_ndvc; + AV1CDFs cdfs_last[AV1_NUM_REF_FRAMES]; + Av1MvCDFs cdfs_last_ndvc[AV1_NUM_REF_FRAMES]; + RK_U8 disable_frame_end_update_cdf; + RK_U8 frame_is_intra; + RK_U8 refresh_frame_flags; + + const RK_U32 *unit_types; + RK_S32 nb_unit_types; + + RK_U32 tile_offset_start[AV1_MAX_TILES]; + RK_U32 tile_offset_end[AV1_MAX_TILES]; + + AV1RefFrameState ref_s[AV1_NUM_REF_FRAMES]; + + RK_U8 skip_ref0; + RK_U8 skip_ref1; + + RK_S32 eos; + RK_S64 pts; + RK_S64 dts; +} Av1Codec; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 av1d_get_relative_dist(const AV1SeqHeader *seq, RK_U32 a, RK_U32 b); +MPP_RET av1d_read_obu_header(BitReadCtx_t *gb, AV1OBUHeader *hdr); +MPP_RET av1d_parser_fragment_header(Av1UnitFragment *frag); +MPP_RET av1d_get_fragment_units(Av1UnitFragment *frag); +MPP_RET av1d_read_fragment_uints(Av1Codec *ctx, Av1UnitFragment *frag); +MPP_RET av1d_fragment_reset(Av1UnitFragment *frag); + +MPP_RET av1d_get_cdfs(Av1Codec *ctx, RK_U32 ref_idx); +MPP_RET av1d_store_cdfs(Av1Codec *ctx, RK_U32 refresh_frame_flags); +MPP_RET av1d_set_default_cdfs(AV1CDFs *cdfs, Av1MvCDFs *cdfs_ndvc); +MPP_RET av1d_set_default_coeff_probs(RK_U32 base_qindex, AV1CDFs *cdfs); + +#ifdef __cplusplus +} +#endif + +#endif // AV1D_CODEC_H diff --git a/mpp/codec/dec/av1/av1d_entropy.c b/mpp/codec/dec/av1/av1d_entropy.c new file mode 100644 index 000000000..52156de7f --- /dev/null +++ b/mpp/codec/dec/av1/av1d_entropy.c @@ -0,0 +1,4387 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include + +#include "av1d_parser.h" + +#define ICDF(x) (32768U - (x)) + +#define CDF2(a0) ICDF(a0) +#define CDF3(a0, a1) ICDF(a0), ICDF(a1) +#define CDF4(a0, a1, a2) ICDF(a0), ICDF(a1), ICDF(a2) +#define CDF5(a0, a1, a2, a3) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3) +#define CDF6(a0, a1, a2, a3, a4) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), ICDF(a4) + +#define CDF7(a0, a1, a2, a3, a4, a5) \ + ICDF(a0), ICDF(a1), ICDF(a2), \ + ICDF(a3), ICDF(a4), ICDF(a5) + +#define CDF8(a0, a1, a2, a3, a4, a5, a6) \ + ICDF(a0), ICDF(a1), ICDF(a2), \ + ICDF(a3), ICDF(a4), ICDF(a5), ICDF(a6) + +#define CDF9(a0, a1, a2, a3, a4, a5, a6, a7) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), \ + ICDF(a4), ICDF(a5), ICDF(a6), ICDF(a7) + +#define CDF10(a0, a1, a2, a3, a4, a5, a6, a7, a8) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3),\ + ICDF(a4), ICDF(a5), ICDF(a6), ICDF(a7), ICDF(a8) + +#define CDF11(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), ICDF(a4), \ + ICDF(a5), ICDF(a6), ICDF(a7), ICDF(a8), ICDF(a9) + +#define CDF12(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), ICDF(a4), ICDF(a5), \ + ICDF(a6), ICDF(a7), ICDF(a8), ICDF(a9), ICDF(a10) + +#define CDF13(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), ICDF(a4), ICDF(a5), \ + ICDF(a6), ICDF(a7), ICDF(a8), ICDF(a9), ICDF(a10), ICDF(a11) + +#define CDF14(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), ICDF(a4), \ + ICDF(a5), ICDF(a6), ICDF(a7), ICDF(a8), ICDF(a9), \ + ICDF(a10), ICDF(a11), ICDF(a12) + +#define CDF15(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), ICDF(a4), \ + ICDF(a5),ICDF(a6), ICDF(a7), ICDF(a8), ICDF(a9), \ + ICDF(a10), ICDF(a11), ICDF(a12), ICDF(a13) + +#define CDF16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \ + ICDF(a0), ICDF(a1), ICDF(a2), ICDF(a3), ICDF(a4), \ + ICDF(a5), ICDF(a6), ICDF(a7), ICDF(a8), ICDF(a9), \ + ICDF(a10), ICDF(a11), ICDF(a12), ICDF(a13), ICDF(a14) + + +static const RK_U16 +default_kf_y_mode_cdf[AV1_KF_MODE_CONTEXTS][AV1_KF_MODE_CONTEXTS][AV1_CDF_SIZE(AV1_INTRA_MODES)] = { + { + { + CDF13(15588, 17027, 19338, 20218, 20682, 21110, 21825, 23244, + 24189, 28165, 29093, 30466) + }, + { + CDF13(12016, 18066, 19516, 20303, 20719, 21444, 21888, 23032, + 24434, 28658, 30172, 31409) + }, + { + CDF13(10052, 10771, 22296, 22788, 23055, 23239, 24133, 25620, + 26160, 29336, 29929, 31567) + }, + { + CDF13(14091, 15406, 16442, 18808, 19136, 19546, 19998, 22096, + 24746, 29585, 30958, 32462) + }, + { + CDF13(12122, 13265, 15603, 16501, 18609, 20033, 22391, 25583, + 26437, 30261, 31073, 32475) + } + }, + { + { + CDF13(10023, 19585, 20848, 21440, 21832, 22760, 23089, 24023, + 25381, 29014, 30482, 31436) + }, + { + CDF13(5983, 24099, 24560, 24886, 25066, 25795, 25913, 26423, + 27610, 29905, 31276, 31794) + }, + { + CDF13(7444, 12781, 20177, 20728, 21077, 21607, 22170, 23405, + 24469, 27915, 29090, 30492) + }, + { + CDF13(8537, 14689, 15432, 17087, 17408, 18172, 18408, 19825, + 24649, 29153, 31096, 32210) + }, + { + CDF13(7543, 14231, 15496, 16195, 17905, 20717, 21984, 24516, + 26001, 29675, 30981, 31994) + } + }, + { + { + CDF13(12613, 13591, 21383, 22004, 22312, 22577, 23401, 25055, + 25729, 29538, 30305, 32077) + }, + { + CDF13(9687, 13470, 18506, 19230, 19604, 20147, 20695, 22062, + 23219, 27743, 29211, 30907) + }, + { + CDF13(6183, 6505, 26024, 26252, 26366, 26434, 27082, 28354, 28555, + 30467, 30794, 32086) + }, + { + CDF13(10718, 11734, 14954, 17224, 17565, 17924, 18561, 21523, + 23878, 28975, 30287, 32252) + }, + { + CDF13(9194, 9858, 16501, 17263, 18424, 19171, 21563, 25961, 26561, + 30072, 30737, 32463) + } + }, + { + { + CDF13(12602, 14399, 15488, 18381, 18778, 19315, 19724, 21419, + 25060, 29696, 30917, 32409) + }, + { + CDF13(8203, 13821, 14524, 17105, 17439, 18131, 18404, 19468, + 25225, 29485, 31158, 32342) + }, + { + CDF13(8451, 9731, 15004, 17643, 18012, 18425, 19070, 21538, 24605, + 29118, 30078, 32018) + }, + { + CDF13(7714, 9048, 9516, 16667, 16817, 16994, 17153, 18767, 26743, + 30389, 31536, 32528) + }, + { + CDF13(8843, 10280, 11496, 15317, 16652, 17943, 19108, 22718, + 25769, 29953, 30983, 32485) + } + }, + { + { + CDF13(12578, 13671, 15979, 16834, 19075, 20913, 22989, 25449, + 26219, 30214, 31150, 32477) + }, + { + CDF13(9563, 13626, 15080, 15892, 17756, 20863, 22207, 24236, + 25380, 29653, 31143, 32277) + }, + { + CDF13(8356, 8901, 17616, 18256, 19350, 20106, 22598, 25947, 26466, + 29900, 30523, 32261) + }, + { + CDF13(10835, 11815, 13124, 16042, 17018, 18039, 18947, 22753, + 24615, 29489, 30883, 32482) + }, + { + CDF13(7618, 8288, 9859, 10509, 15386, 18657, 22903, 28776, 29180, + 31355, 31802, 32593) + } + } +}; + +static const RK_U16 +default_angle_delta_cdf[AV1_DIRECTIONAL_MODES][AV1_CDF_SIZE(2 * AV1_MAX_ANGLE_DELTA + 1)] = { + {CDF7(2180, 5032, 7567, 22776, 26989, 30217)}, + {CDF7(2301, 5608, 8801, 23487, 26974, 30330)}, + {CDF7(3780, 11018, 13699, 19354, 23083, 31286)}, + {CDF7(4581, 11226, 15147, 17138, 21834, 28397)}, + {CDF7(1737, 10927, 14509, 19588, 22745, 28823)}, + {CDF7(2664, 10176, 12485, 17650, 21600, 30495)}, + {CDF7(2240, 11096, 15453, 20341, 22561, 28917)}, + {CDF7(3605, 10428, 12459, 17676, 21244, 30655)} +}; + +static const RK_U16 +default_if_y_mode_cdf[AV1_BLOCK_SIZE_GROUPS][AV1_CDF_SIZE(AV1_INTRA_MODES)] = { + { + CDF13(22801, 23489, 24293, 24756, 25601, 26123, + 26606, 27418, 27945, 29228, 29685, 30349) + }, + { + CDF13(18673, 19845, 22631, 23318, 23950, 24649, + 25527, 27364, 28152, 29701, 29984, 30852) + }, + { + CDF13(19770, 20979, 23396, 23939, 24241, 24654, + 25136, 27073, 27830, 29360, 29730, 30659) + }, + { + CDF13(20155, 21301, 22838, 23178, 23261, 23533, + 23703, 24804, 25352, 26575, 27016, 28049) + } +}; + +static const RK_U16 +default_uv_mode_cdf[AV1_CFL_ALLOWED_TYPES][AV1_INTRA_MODES][AV1_CDF_SIZE(AV1_UV_INTRA_MODES)] = { + { + { + CDF13(22631, 24152, 25378, 25661, 25986, 26520, 27055, 27923, + 28244, 30059, 30941, 31961) + }, + { + CDF13(9513, 26881, 26973, 27046, 27118, 27664, 27739, 27824, + 28359, 29505, 29800, 31796) + }, + { + CDF13(9845, 9915, 28663, 28704, 28757, 28780, 29198, 29822, 29854, + 30764, 31777, 32029) + }, + { + CDF13(13639, 13897, 14171, 25331, 25606, 25727, 25953, 27148, + 28577, 30612, 31355, 32493) + }, + { + CDF13(9764, 9835, 9930, 9954, 25386, 27053, 27958, 28148, 28243, + 31101, 31744, 32363) + }, + { + CDF13(11825, 13589, 13677, 13720, 15048, 29213, 29301, 29458, + 29711, 31161, 31441, 32550) + }, + { + CDF13(14175, 14399, 16608, 16821, 17718, 17775, 28551, 30200, + 30245, 31837, 32342, 32667) + }, + { + CDF13(12885, 13038, 14978, 15590, 15673, 15748, 16176, 29128, + 29267, 30643, 31961, 32461) + }, + { + CDF13(12026, 13661, 13874, 15305, 15490, 15726, 15995, 16273, + 28443, 30388, 30767, 32416) + }, + { + CDF13(19052, 19840, 20579, 20916, 21150, 21467, 21885, 22719, + 23174, 28861, 30379, 32175) + }, + { + CDF13(18627, 19649, 20974, 21219, 21492, 21816, 22199, 23119, + 23527, 27053, 31397, 32148) + }, + { + CDF13(17026, 19004, 19997, 20339, 20586, 21103, 21349, 21907, + 22482, 25896, 26541, 31819) + }, + { + CDF13(12124, 13759, 14959, 14992, 15007, 15051, 15078, 15166, + 15255, 15753, 16039, 16606) + } + }, + { + { + CDF14(10407, 11208, 12900, 13181, 13823, 14175, 14899, 15656, + 15986, 20086, 20995, 22455, 24212) + }, + { + CDF14(4532, 19780, 20057, 20215, 20428, 21071, 21199, 21451, + 22099, 24228, 24693, 27032, 29472) + }, + { + CDF14(5273, 5379, 20177, 20270, 20385, 20439, 20949, 21695, 21774, + 23138, 24256, 24703, 26679) + }, + { + CDF14(6740, 7167, 7662, 14152, 14536, 14785, 15034, 16741, 18371, + 21520, 22206, 23389, 24182) + }, + { + CDF14(4987, 5368, 5928, 6068, 19114, 20315, 21857, 22253, 22411, + 24911, 25380, 26027, 26376) + }, + { + CDF14(5370, 6889, 7247, 7393, 9498, 21114, 21402, 21753, 21981, + 24780, 25386, 26517, 27176) + }, + { + CDF14(4816, 4961, 7204, 7326, 8765, 8930, 20169, 20682, 20803, + 23188, 23763, 24455, 24940) + }, + { + CDF14(6608, 6740, 8529, 9049, 9257, 9356, 9735, 18827, 19059, + 22336, 23204, 23964, 24793) + }, + { + CDF14(5998, 7419, 7781, 8933, 9255, 9549, 9753, 10417, 18898, + 22494, 23139, 24764, 25989) + }, + { + CDF14(10660, 11298, 12550, 12957, 13322, 13624, 14040, 15004, + 15534, 20714, 21789, 23443, 24861) + }, + { + CDF14(10522, 11530, 12552, 12963, 13378, 13779, 14245, 15235, + 15902, 20102, 22696, 23774, 25838) + }, + { + CDF14(10099, 10691, 12639, 13049, 13386, 13665, 14125, 15163, + 15636, 19676, 20474, 23519, 25208) + }, + { + CDF14(3144, 5087, 7382, 7504, 7593, 7690, 7801, 8064, 8232, 9248, + 9875, 10521, 29048) + } + } +}; + +static const RK_U16 +default_partition_cdf[13][16] = { + { + CDF4(19132, 25510, 30392), CDF4(13928, 19855, 28540), + CDF4(12522, 23679, 28629), CDF4(9896, 18783, 25853), + CDF2(11570), CDF2(16855), CDF3(9413, 22581) + }, + {CDF10(15597, 20929, 24571, 26706, 27664, 28821, 29601, 30571, 31902)}, + {CDF10(7925, 11043, 16785, 22470, 23971, 25043, 26651, 28701, 29834)}, + {CDF10(5414, 13269, 15111, 20488, 22360, 24500, 25537, 26336, 32117)}, + {CDF10(2662, 6362, 8614, 20860, 23053, 24778, 26436, 27829, 31171)}, + {CDF10(18462, 20920, 23124, 27647, 28227, 29049, 29519, 30178, 31544)}, + {CDF10(7689, 9060, 12056, 24992, 25660, 26182, 26951, 28041, 29052)}, + {CDF10(6015, 9009, 10062, 24544, 25409, 26545, 27071, 27526, 32047)}, + {CDF10(1394, 2208, 2796, 28614, 29061, 29466, 29840, 30185, 31899)}, + { + CDF10(20137, 21547, 23078, 29566, 29837, 30261, 30524, 30892, 31724), + CDF8(27899, 28219, 28529, 32484, 32539, 32619, 32639) + }, + { + CDF10(6732, 7490, 9497, 27944, 28250, 28515, 28969, 29630, 30104), + CDF8(6607, 6990, 8268, 32060, 32219, 32338, 32371) + }, + { + CDF10(5945, 7663, 8348, 28683, 29117, 29749, 30064, 30298, 32238), + CDF8(5429, 6676, 7122, 32027, 32227, 32531, 32582) + }, + { + CDF10(870, 1212, 1487, 31198, 31394, 31574, 31743, 31881, 32332), + CDF8(711, 966, 1172, 32448, 32538, 32617, 32664) + }, +}; + +static const RK_U16 +default_intra_ext_tx0_cdf[AV1_EXTTX_SIZES][AV1_INTRA_MODES][8] = { + { + {CDF7(1535, 8035, 9461, 12751, 23467, 27825)}, + {CDF7(564, 3335, 9709, 10870, 18143, 28094)}, + {CDF7(672, 3247, 3676, 11982, 19415, 23127)}, + {CDF7(5279, 13885, 15487, 18044, 23527, 30252)}, + {CDF7(4423, 6074, 7985, 10416, 25693, 29298)}, + {CDF7(1486, 4241, 9460, 10662, 16456, 27694)}, + {CDF7(439, 2838, 3522, 6737, 18058, 23754)}, + {CDF7(1190, 4233, 4855, 11670, 20281, 24377)}, + {CDF7(1045, 4312, 8647, 10159, 18644, 29335)}, + {CDF7(202, 3734, 4747, 7298, 17127, 24016)}, + {CDF7(447, 4312, 6819, 8884, 16010, 23858)}, + {CDF7(277, 4369, 5255, 8905, 16465, 22271)}, + {CDF7(3409, 5436, 10599, 15599, 19687, 24040)}, + }, + { + {CDF7(1870, 13742, 14530, 16498, 23770, 27698)}, + {CDF7(326, 8796, 14632, 15079, 19272, 27486)}, + {CDF7(484, 7576, 7712, 14443, 19159, 22591)}, + {CDF7(1126, 15340, 15895, 17023, 20896, 30279)}, + {CDF7(655, 4854, 5249, 5913, 22099, 27138)}, + {CDF7(1299, 6458, 8885, 9290, 14851, 25497)}, + {CDF7(311, 5295, 5552, 6885, 16107, 22672)}, + {CDF7(883, 8059, 8270, 11258, 17289, 21549)}, + {CDF7(741, 7580, 9318, 10345, 16688, 29046)}, + {CDF7(110, 7406, 7915, 9195, 16041, 23329)}, + {CDF7(363, 7974, 9357, 10673, 15629, 24474)}, + {CDF7(153, 7647, 8112, 9936, 15307, 19996)}, + {CDF7(3511, 6332, 11165, 15335, 19323, 23594)}, + }, + { + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + }, + { + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + {CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + }, +}; + +static const RK_U16 +default_intra_ext_tx1_cdf[AV1_EXTTX_SIZES][AV1_INTRA_MODES][4] = { + { + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + }, + { + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + }, + { + {CDF5(1127, 12814, 22772, 27483)}, + {CDF5(145, 6761, 11980, 26667)}, + {CDF5(362, 5887, 11678, 16725)}, + {CDF5(385, 15213, 18587, 30693)}, + {CDF5(25, 2914, 23134, 27903)}, + {CDF5(60, 4470, 11749, 23991)}, + {CDF5(37, 3332, 14511, 21448)}, + {CDF5(157, 6320, 13036, 17439)}, + {CDF5(119, 6719, 12906, 29396)}, + {CDF5(47, 5537, 12576, 21499)}, + {CDF5(269, 6076, 11258, 23115)}, + {CDF5(83, 5615, 12001, 17228)}, + {CDF5(1968, 5556, 12023, 18547)}, + }, + { + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + {CDF5(6554, 13107, 19661, 26214)}, + }, +}; + +static const RK_U16 +default_inter_ext_tx_cdf[2][AV1_EXTTX_SIZES][AV1_EXT_TX_TYPES] = { + { + { + CDF16(4458, 5560, 7695, 9709, 13330, 14789, 17537, 20266, + 21504, 22848, 23934, 25474, 27727, 28915, 30631) + }, + { + CDF16(1645, 2573, 4778, 5711, 7807, 8622, 10522, 15357, 17674, + 20408, 22517, 25010, 27116, 28856, 30749) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + }, + { + { + CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + CDF2(16384) + }, + { + CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + CDF2(4167) + }, + { + CDF12(770, 2421, 5225, 12907, 15819, 18927, 21561, 24089, + 26595, 28526, 30529), + CDF2(1998) + }, + { + CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + CDF2(748) + }, + } +}; + +static const RK_U16 +default_cfl_sign_cdf[AV1_CDF_SIZE(AV1_CFL_JOINT_SIGNS)] = { + CDF8(1418, 2123, 13340, 18405, 26972, 28343, 32294) +}; + +static const RK_U16 +default_cfl_alpha_cdf[AV1_CFL_ALPHA_CONTEXTS][AV1_CDF_SIZE(AV1_CFL_ALPHABET_SIZE)] = { + { + CDF16(7637, 20719, 31401, 32481, 32657, 32688, 32692, 32696, 32700, + 32704, 32708, 32712, 32716, 32720, 32724) + }, + { + CDF16(14365, 23603, 28135, 31168, 32167, 32395, 32487, 32573, + 32620, 32647, 32668, 32672, 32676, 32680, 32684) + }, + { + CDF16(11532, 22380, 28445, 31360, 32349, 32523, 32584, 32649, + 32673, 32677, 32681, 32685, 32689, 32693, 32697) + }, + { + CDF16(26990, 31402, 32282, 32571, 32692, 32696, 32700, 32704, + 32708, 32712, 32716, 32720, 32724, 32728, 32732) + }, + { + CDF16(17248, 26058, 28904, 30608, 31305, 31877, 32126, 32321, + 32394, 32464, 32516, 32560, 32576, 32593, 32622) + }, + { + CDF16(14738, 21678, 25779, 27901, 29024, 30302, 30980, 31843, + 32144, 32413, 32520, 32594, 32622, 32656, 32660) + } +}; + +static const RK_U16 +default_switchable_interp_cdf[AV1_SWITCHABLE_FILTER_CONTEXTS][AV1_CDF_SIZE(AV1_SWITCHABLE_FILTERS)] = { + {CDF3(31935, 32720)}, {CDF3(5568, 32719)}, + {CDF3(422, 2938)}, {CDF3(28244, 32608)}, + {CDF3(31206, 31953)}, {CDF3(4862, 32121)}, + {CDF3(770, 1152)}, {CDF3(20889, 25637)}, + {CDF3(31910, 32724)}, {CDF3(4120, 32712)}, + {CDF3(305, 2247)}, {CDF3(27403, 32636)}, + {CDF3(31022, 32009)}, {CDF3(2963, 32093)}, + {CDF3(601, 943)}, {CDF3(14969, 21398)} +}; + +static const RK_U16 +default_newmv_cdf[AV1_NEWMV_MODE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(24035)}, {CDF2(16630)}, {CDF2(15339)}, + {CDF2(8386)}, {CDF2(12222)}, {CDF2(4676)} +}; + +static const RK_U16 +default_zeromv_cdf[AV1_GLOBALMV_MODE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(2175)}, {CDF2(1054)} +}; + +static const RK_U16 +default_refmv_cdf[AV1_REFMV_MODE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(23974)}, {CDF2(24188)}, {CDF2(17848)}, + {CDF2(28622)}, {CDF2(24312)}, {CDF2(19923)} +}; + +static const RK_U16 +default_drl_cdf[AV1_DRL_MODE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(13104)}, {CDF2(24560)}, {CDF2(18945)} +}; + +static const RK_U16 +default_inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS][AV1_CDF_SIZE(INTER_COMPOUND_MODES)] = { + {CDF8(7760, 13823, 15808, 17641, 19156, 20666, 26891)}, + {CDF8(10730, 19452, 21145, 22749, 24039, 25131, 28724)}, + {CDF8(10664, 20221, 21588, 22906, 24295, 25387, 28436)}, + {CDF8(13298, 16984, 20471, 24182, 25067, 25736, 26422)}, + {CDF8(18904, 23325, 25242, 27432, 27898, 28258, 30758)}, + {CDF8(10725, 17454, 20124, 22820, 24195, 25168, 26046)}, + {CDF8(17125, 24273, 25814, 27492, 28214, 28704, 30592)}, + {CDF8(13046, 23214, 24505, 25942, 27435, 28442, 29330)} +}; + +static const RK_U16 +default_interintra_cdf[AV1_BLOCK_SIZE_GROUPS][AV1_CDF_SIZE(2)] = { + {CDF2(16384)}, {CDF2(26887)}, {CDF2(27597)}, {CDF2(30237)} +}; + +static const RK_U16 +default_interintra_mode_cdf[AV1_BLOCK_SIZE_GROUPS][AV1_CDF_SIZE(AV1_INTERINTRA_MODES)] = { + {CDF4(8192, 16384, 24576)}, + {CDF4(1875, 11082, 27332)}, + {CDF4(2473, 9996, 26388)}, + {CDF4(4238, 11537, 25926)} +}; + +static const RK_U16 +default_wedge_interintra_cdf[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(2)] = { + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(20036)}, {CDF2(24957)}, {CDF2(26704)}, + {CDF2(27530)}, {CDF2(29564)}, {CDF2(29444)}, + {CDF2(26872)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(16384)} +}; + +static const RK_U16 +default_compound_type_cdf[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(AV1_COMPOUND_TYPES - 1)] = { + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, {CDF2(23431)}, + {CDF2(13171)}, {CDF2(11470)}, {CDF2(9770)}, {CDF2(9100)}, + {CDF2(8233)}, {CDF2(6172)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(16384)}, {CDF2(16384)}, {CDF2(11820)}, {CDF2(7701)}, + {CDF2(16384)}, {CDF2(16384)} +}; + +static const RK_U16 +default_wedge_idx_cdf[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(16)] = { + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094, 20359, + 22362, 24127, 25702, 27752, 29450, 31171) + }, + { + CDF16(806, 3266, 6005, 6738, 7218, 7367, 7771, 14588, 16323, 17367, + 18452, 19422, 22839, 26127, 29629) + }, + { + CDF16(2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357, 17939, 21332, + 24520, 27470, 29456, 30529, 31656) + }, + { + CDF16(1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144, 19163, 20961, + 22884, 24471, 26719, 28714, 30877) + }, + { + CDF16(1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624, 15369, 16730, + 18114, 19313, 22521, 26012, 29550) + }, + { + CDF16(2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124, 17270, 20533, + 23434, 25972, 27944, 29570, 31416) + }, + { + CDF16(1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944, 20638, 22038, + 23963, 25311, 26988, 28766, 31012) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(154, 987, 1925, 2051, 2088, 2111, 2151, 23033, 23703, 24284, + 24985, 25684, 27259, 28883, 30911) + }, + { + CDF16(1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016, 22935, 25057, + 27251, 29173, 30089, 30960, 31933) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + } +}; + +static const RK_U16 +default_motion_mode_cdf[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(AV1_MOTION_MODES)] = { + {CDF3(10923, 21845)}, {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, {CDF3(7651, 24760)}, + {CDF3(4738, 24765)}, {CDF3(5391, 25528)}, + {CDF3(19419, 26810)}, {CDF3(5123, 23606)}, + {CDF3(11606, 24308)}, {CDF3(26260, 29116)}, + {CDF3(20360, 28062)}, {CDF3(21679, 26830)}, + {CDF3(29516, 30701)}, {CDF3(28898, 30397)}, + {CDF3(30878, 31335)}, {CDF3(32507, 32558)}, + {CDF3(10923, 21845)}, {CDF3(10923, 21845)}, + {CDF3(28799, 31390)}, {CDF3(26431, 30774)}, + {CDF3(28973, 31594)}, {CDF3(29742, 31203)} +}; + +static const RK_U16 +default_obmc_cdf[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(2)] = { + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, {CDF2(10437)}, + {CDF2(9371)}, {CDF2(9301)}, {CDF2(17432)}, {CDF2(14423)}, + {CDF2(15142)}, {CDF2(25817)}, {CDF2(22823)}, {CDF2(22083)}, + {CDF2(30128)}, {CDF2(31014)}, {CDF2(31560)}, {CDF2(32638)}, + {CDF2(16384)}, {CDF2(16384)}, {CDF2(23664)}, {CDF2(20901)}, + {CDF2(24008)}, {CDF2(26879)} +}; + +static const RK_U16 +default_intra_inter_cdf[AV1_INTRA_INTER_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(806)}, + {CDF2(16662)}, + {CDF2(20186)}, + {CDF2(26538)} +}; + +static const RK_U16 +default_comp_inter_cdf[AV1_COMP_INTER_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(26828)}, + {CDF2(24035)}, + {CDF2(12031)}, + {CDF2(10640)}, + {CDF2(2901)} +}; + +static const RK_U16 +default_comp_ref_type_cdf[AV1_COMP_REF_TYPE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(1198)}, + {CDF2(2070)}, + {CDF2(9166)}, + {CDF2(7499)}, + {CDF2(22475)} +}; + +static const RK_U16 +default_uni_comp_ref_cdf[AV1_UNI_COMP_REF_CONTEXTS][AV1_UNIDIR_COMP_REFS - 1][AV1_CDF_SIZE(2)] = { + {{CDF2(5284)}, {CDF2(3865)}, {CDF2(3128)}}, + {{CDF2(23152)}, {CDF2(14173)}, {CDF2(15270)}}, + {{CDF2(31774)}, {CDF2(25120)}, {CDF2(26710)}} +}; + +static const RK_U16 +default_single_ref_cdf[AV1_REF_CONTEXTS][AV1_SINGLE_REFS - 1][AV1_CDF_SIZE(2)] = { + { + {CDF2(4897)}, + {CDF2(1555)}, + {CDF2(4236)}, + {CDF2(8650)}, + {CDF2(904)}, + {CDF2(1444)} + }, + { + {CDF2(16973)}, + {CDF2(16751)}, + {CDF2(19647)}, + {CDF2(24773)}, + {CDF2(11014)}, + {CDF2(15087)} + }, + { + {CDF2(29744)}, + {CDF2(30279)}, + {CDF2(31194)}, + {CDF2(31895)}, + {CDF2(26875)}, + {CDF2(30304)} + } +}; + +static const RK_U16 +default_comp_ref_cdf[AV1_REF_CONTEXTS][AV1_FWD_REFS - 1][AV1_CDF_SIZE(2)] = { + {{CDF2(4946)}, {CDF2(9468)}, {CDF2(1503)}}, + {{CDF2(19891)}, {CDF2(22441)}, {CDF2(15160)}}, + {{CDF2(30731)}, {CDF2(31059)}, {CDF2(27544)}} +}; + +static const RK_U16 +default_comp_bwdref_cdf[AV1_REF_CONTEXTS][AV1_BWD_REFS - 1][AV1_CDF_SIZE(2)] = { + {{CDF2(2235)}, {CDF2(1423)}}, + {{CDF2(17182)}, {CDF2(15175)}}, + {{CDF2(30606)}, {CDF2(30489)}} +}; + +static const RK_U16 +default_palette_y_size_cdf[AV1_PALETTE_BLOCK_SIZES][AV1_CDF_SIZE(AV1_PALETTE_SIZES)] = { + {CDF7(7952, 13000, 18149, 21478, 25527, 29241)}, + {CDF7(7139, 11421, 16195, 19544, 23666, 28073)}, + {CDF7(7788, 12741, 17325, 20500, 24315, 28530)}, + {CDF7(8271, 14064, 18246, 21564, 25071, 28533)}, + {CDF7(12725, 19180, 21863, 24839, 27535, 30120)}, + {CDF7(9711, 14888, 16923, 21052, 25661, 27875)}, + {CDF7(14940, 20797, 21678, 24186, 27033, 28999)} +}; + +static const RK_U16 +default_palette_uv_size_cdf[AV1_PALETTE_BLOCK_SIZES][AV1_CDF_SIZE(AV1_PALETTE_SIZES)] = { + {CDF7(8713, 19979, 27128, 29609, 31331, 32272)}, + {CDF7(5839, 15573, 23581, 26947, 29848, 31700)}, + {CDF7(4426, 11260, 17999, 21483, 25863, 29430)}, + {CDF7(3228, 9464, 14993, 18089, 22523, 27420)}, + {CDF7(3768, 8886, 13091, 17852, 22495, 27207)}, + {CDF7(2464, 8451, 12861, 21632, 25525, 28555)}, + {CDF7(1269, 5435, 10433, 18963, 21700, 25865)} +}; + +static const RK_U16 +default_palette_y_mode_cdf[AV1_PALETTE_BLOCK_SIZES][AV1_PALETTE_Y_MODE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {{CDF2(31676)}, {CDF2(3419)}, {CDF2(1261)}}, + {{CDF2(31912)}, {CDF2(2859)}, {CDF2(980)}}, + {{CDF2(31823)}, {CDF2(3400)}, {CDF2(781)}}, + {{CDF2(32030)}, {CDF2(3561)}, {CDF2(904)}}, + {{CDF2(32309)}, {CDF2(7337)}, {CDF2(1462)}}, + {{CDF2(32265)}, {CDF2(4015)}, {CDF2(1521)}}, + {{CDF2(32450)}, {CDF2(7946)}, {CDF2(129)}} +}; + +static const RK_U16 +default_palette_uv_mode_cdf[AV1_PALETTE_UV_MODE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(32461)}, {CDF2(21488)} +}; + +static const RK_U16 +default_palette_y_color_index_cdf[AV1_PALETTE_IDX_CONTEXTS][8] = { + // Palette sizes 2 & 8 + { + CDF2(28710), + CDF8(21689, 23883, 25163, 26352, 27506, 28827, 30195) + }, + { + CDF2(16384), + CDF8(6892, 15385, 17840, 21606, 24287, 26753, 29204) + }, + { + CDF2(10553), + CDF8(5651, 23182, 25042, 26518, 27982, 29392, 30900) + }, + { + CDF2(27036), + CDF8(19349, 22578, 24418, 25994, 27524, 29031, 30448) + }, + { + CDF2(31603), + CDF8(31028, 31270, 31504, 31705, 31927, 32153, 32392) + }, + // Palette sizes 3 & 7 + { + CDF3(27877, 30490), + CDF7(23105, 25199, 26464, 27684, 28931, 30318) + }, + { + CDF3(11532, 25697), + CDF7(6950, 15447, 18952, 22681, 25567, 28563) + }, + { + CDF3(6544, 30234), + CDF7(7560, 23474, 25490, 27203, 28921, 30708) + }, + { + CDF3(23018, 28072), + CDF7(18544, 22373, 24457, 26195, 28119, 30045) + }, + { + CDF3(31915, 32385), + CDF7(31198, 31451, 31670, 31882, 32123, 32391) + }, + // Palette sizes 4 & 6 + { + CDF4(25572, 28046, 30045), + CDF6(23132, 25407, 26970, 28435, 30073) + }, + { + CDF4(9478, 21590, 27256), + CDF6(7443, 17242, 20717, 24762, 27982) + }, + { + CDF4(7248, 26837, 29824), + CDF6(6300, 24862, 26944, 28784, 30671) + }, + { + CDF4(19167, 24486, 28349), + CDF6(18916, 22895, 25267, 27435, 29652) + }, + { + CDF4(31400, 31825, 32250), + CDF6(31270, 31550, 31808, 32059, 32353) + }, + // Palette size 5 + { + CDF5(24779, 26955, 28576, 30282), + CDF5(8669, 20364, 24073, 28093) + }, + { + CDF5(4255, 27565, 29377, 31067), + CDF5(19864, 23674, 26716, 29530) + }, + { + CDF5(31646, 31893, 32147, 32426), 0, 0, 0, 0 + } +}; + +static const RK_U16 +default_palette_uv_color_index_cdf[AV1_PALETTE_IDX_CONTEXTS][8] = { + // Palette sizes 2 & 8 + { + CDF2(29089), + CDF8(21442, 23288, 24758, 26246, 27649, 28980, 30563) + }, + { + CDF2(16384), + CDF8(5863, 14933, 17552, 20668, 23683, 26411, 29273) + }, + { + CDF2(8713), + CDF8(3415, 25810, 26877, 27990, 29223, 30394, 31618) + }, + { + CDF2(29257), + CDF8(17965, 20084, 22232, 23974, 26274, 28402, 30390) + }, + { + CDF2(31610), + CDF8(31190, 31329, 31516, 31679, 31825, 32026, 32322) + }, + // Palette sizes 3 & 7 + { + CDF3(25257, 29145), + CDF7(21239, 23168, 25044, 26962, 28705, 30506) + }, + { + CDF3(12287, 27293), + CDF7(6545, 15012, 18004, 21817, 25503, 28701) + }, + { + CDF3(7033, 27960), + CDF7(3448, 26295, 27437, 28704, 30126, 31442) + }, + { + CDF3(20145, 25405), + CDF7(15889, 18323, 21704, 24698, 26976, 29690) + }, + { + CDF3(30608, 31639), + CDF7(30988, 31204, 31479, 31734, 31983, 32325) + }, + // Palette sizes 4 & 6 + { + CDF4(24210, 27175, 29903), + CDF6(22217, 24567, 26637, 28683, 30548) + }, + { + CDF4(9888, 22386, 27214), + CDF6(7307, 16406, 19636, 24632, 28424) + }, + { + CDF4(5901, 26053, 29293), + CDF6(4441, 25064, 26879, 28942, 30919) + }, + { + CDF4(18318, 22152, 28333), + CDF6(17210, 20528, 23319, 26750, 29582) + }, + { + CDF4(30459, 31136, 31926), + CDF6(30674, 30953, 31396, 31735, 32207) + }, + // Palette size 5 + { + CDF5(22980, 25479, 27781, 29986), + CDF5(8413, 21408, 24859, 28874) + }, + { + CDF5(2257, 29449, 30594, 31598), + CDF5(19189, 21202, 25915, 28620) + }, + { + CDF5(31844, 32044, 32281, 32518), 0, 0, 0, 0 + } +}; + +static const RK_U16 +default_txfm_partition_cdf[AV1_TXFM_PARTITION_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(28581)}, {CDF2(23846)}, {CDF2(20847)}, + {CDF2(24315)}, {CDF2(18196)}, {CDF2(12133)}, + {CDF2(18791)}, {CDF2(10887)}, {CDF2(11005)}, + {CDF2(27179)}, {CDF2(20004)}, {CDF2(11281)}, + {CDF2(26549)}, {CDF2(19308)}, {CDF2(14224)}, + {CDF2(28015)}, {CDF2(21546)}, {CDF2(14400)}, + {CDF2(28165)}, {CDF2(22401)}, {CDF2(16088)} +}; + +static const RK_U16 +default_skip_cdfs[AV1_SKIP_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(31671)}, {CDF2(16515)}, {CDF2(4576)} +}; + +static const RK_U16 +default_skip_mode_cdfs[AV1_SKIP_MODE_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(32621)}, {CDF2(20708)}, {CDF2(8127)} +}; + +static const RK_U16 +default_compound_idx_cdfs[AV1_COMP_INDEX_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(18244)}, {CDF2(12865)}, {CDF2(7053)}, + {CDF2(13259)}, {CDF2(9334)}, {CDF2(4644)} +}; + +static const RK_U16 +default_comp_group_idx_cdfs[AV1_COMP_GROUP_IDX_CONTEXTS][AV1_CDF_SIZE(2)] = { + {CDF2(26607)}, {CDF2(22891)}, {CDF2(18840)}, + {CDF2(24594)}, {CDF2(19934)}, {CDF2(22674)} +}; + +static const RK_U16 +default_intrabc_cdf[AV1_CDF_SIZE(2)] = {CDF2(30531)}; + +static const RK_U16 +default_filter_intra_mode_cdf[AV1_CDF_SIZE(AV1_FILTER_INTRA_MODES)] = { + CDF5(8949, 12776, 17211, 29558) +}; + +static const RK_U16 +default_filter_intra_cdfs[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(2)] = { + {CDF2(4621)}, {CDF2(6743)}, {CDF2(5893)}, {CDF2(7866)}, + {CDF2(12551)}, {CDF2(9394)}, {CDF2(12408)}, {CDF2(14301)}, + {CDF2(12756)}, {CDF2(22343)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, {CDF2(16384)}, + {CDF2(12770)}, {CDF2(10368)}, {CDF2(20229)}, {CDF2(18101)}, + {CDF2(16384)}, {CDF2(16384)} +}; + +static const RK_U16 +default_delta_q_cdf[AV1_CDF_SIZE(AV1_DELTA_Q_PROBS + 1)] = { + CDF4(28160, 32120, 32677) +}; + +static const RK_U16 +default_delta_lf_multi_cdf[AV1_FRAME_LF_COUNT][AV1_CDF_SIZE(AV1_DELTA_LF_PROBS + 1)] = { + {CDF4(28160, 32120, 32677)}, + {CDF4(28160, 32120, 32677)}, + {CDF4(28160, 32120, 32677)}, + {CDF4(28160, 32120, 32677)} +}; + +static const RK_U16 +default_delta_lf_cdf[AV1_CDF_SIZE(AV1_DELTA_LF_PROBS + 1)] = { + CDF4(28160, 32120, 32677) +}; + +static const RK_U16 +default_segment_pred_cdf[AV1_SEG_TEMPORAL_PRED_CTXS][AV1_CDF_SIZE(2)] = { + {CDF2(128 * 128)}, {CDF2(128 * 128)}, {CDF2(128 * 128)} +}; + +static const RK_U16 +default_spatial_pred_seg_tree_cdf[AV1_SPATIAL_PREDICTION_PROBS][AV1_CDF_SIZE(AV1_MAX_SEGMENTS)] = { + { + CDF8(5622, 7893, 16093, 18233, 27809, 28373, 32533), + }, + { + CDF8(14274, 18230, 22557, 24935, 29980, 30851, 32344), + }, + { + CDF8(27527, 28487, 28723, 28890, 32397, 32647, 32679), + }, +}; + +static const RK_U16 +default_tx_size_cdf[AV1_MAX_TX_CATS][AV1_TX_SIZE_CONTEXTS][AV1_CDF_SIZE(AV1_MAX_TX_DEPTH + 1)] = { + { + {CDF2(19968)}, + {CDF2(19968)}, + {CDF2(24320)} + }, + { + {CDF3(12272, 30172)}, + {CDF3(12272, 30172)}, + {CDF3(18677, 30848)} + }, + { + {CDF3(12986, 15180)}, + {CDF3(12986, 15180)}, + {CDF3(24302, 25602)} + }, + { + {CDF3(5782, 11475)}, + {CDF3(5782, 11475)}, + {CDF3(16803, 22759)} + }, +}; + +static const RK_U16 +av1_default_dc_sign_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][AV1_DC_SIGN_CONTEXTS][AV1_CDF_SIZE(2)] = { + { + { + {CDF2(128 * 125)}, + {CDF2(128 * 102)}, + {CDF2(128 * 147)}, + }, + { + {CDF2(128 * 119)}, + {CDF2(128 * 101)}, + {CDF2(128 * 135)}, + } + }, + { + { + {CDF2(128 * 125)}, + {CDF2(128 * 102)}, + {CDF2(128 * 147)}, + }, + { + {CDF2(128 * 119)}, + {CDF2(128 * 101)}, + {CDF2(128 * 135)}, + } + }, + { + { + {CDF2(128 * 125)}, + {CDF2(128 * 102)}, + {CDF2(128 * 147)}, + }, + { + {CDF2(128 * 119)}, + {CDF2(128 * 101)}, + {CDF2(128 * 135)}, + } + }, + { + { + {CDF2(128 * 125)}, + {CDF2(128 * 102)}, + {CDF2(128 * 147)}, + }, + { + {CDF2(128 * 119)}, + {CDF2(128 * 101)}, + {CDF2(128 * 135)}, + } + }, +}; + +static const RK_U16 +av1_default_txb_skip_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_TX_SIZES][AV1_TXB_SKIP_CONTEXTS] [AV1_CDF_SIZE(2)] = { + { + { + {CDF2(31849)}, + {CDF2(5892)}, + {CDF2(12112)}, + {CDF2(21935)}, + {CDF2(20289)}, + {CDF2(27473)}, + {CDF2(32487)}, + {CDF2(7654)}, + {CDF2(19473)}, + {CDF2(29984)}, + {CDF2(9961)}, + {CDF2(30242)}, + {CDF2(32117)} + }, + { + {CDF2(31548)}, + {CDF2(1549)}, + {CDF2(10130)}, + {CDF2(16656)}, + {CDF2(18591)}, + {CDF2(26308)}, + {CDF2(32537)}, + {CDF2(5403)}, + {CDF2(18096)}, + {CDF2(30003)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(29957)}, + {CDF2(5391)}, + {CDF2(18039)}, + {CDF2(23566)}, + {CDF2(22431)}, + {CDF2(25822)}, + {CDF2(32197)}, + {CDF2(3778)}, + {CDF2(15336)}, + {CDF2(28981)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(17920)}, + {CDF2(1818)}, + {CDF2(7282)}, + {CDF2(25273)}, + {CDF2(10923)}, + {CDF2(31554)}, + {CDF2(32624)}, + {CDF2(1366)}, + {CDF2(15628)}, + {CDF2(30462)}, + {CDF2(146)}, + {CDF2(5132)}, + {CDF2(31657)} + }, + { + {CDF2(6308)}, + {CDF2(117)}, + {CDF2(1638)}, + {CDF2(2161)}, + {CDF2(16384)}, + {CDF2(10923)}, + {CDF2(30247)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + } + }, + { + { + {CDF2(30371)}, + {CDF2(7570)}, + {CDF2(13155)}, + {CDF2(20751)}, + {CDF2(20969)}, + {CDF2(27067)}, + {CDF2(32013)}, + {CDF2(5495)}, + {CDF2(17942)}, + {CDF2(28280)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(31782)}, + {CDF2(1836)}, + {CDF2(10689)}, + {CDF2(17604)}, + {CDF2(21622)}, + {CDF2(27518)}, + {CDF2(32399)}, + {CDF2(4419)}, + {CDF2(16294)}, + {CDF2(28345)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(31901)}, + {CDF2(10311)}, + {CDF2(18047)}, + {CDF2(24806)}, + {CDF2(23288)}, + {CDF2(27914)}, + {CDF2(32296)}, + {CDF2(4215)}, + {CDF2(15756)}, + {CDF2(28341)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(26726)}, + {CDF2(1045)}, + {CDF2(11703)}, + {CDF2(20590)}, + {CDF2(18554)}, + {CDF2(25970)}, + {CDF2(31938)}, + {CDF2(5583)}, + {CDF2(21313)}, + {CDF2(29390)}, + {CDF2(641)}, + {CDF2(22265)}, + {CDF2(31452)} + }, + { + {CDF2(26584)}, + {CDF2(188)}, + {CDF2(8847)}, + {CDF2(24519)}, + {CDF2(22938)}, + {CDF2(30583)}, + {CDF2(32608)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + } + }, + { + { + {CDF2(29614)}, + {CDF2(9068)}, + {CDF2(12924)}, + {CDF2(19538)}, + {CDF2(17737)}, + {CDF2(24619)}, + {CDF2(30642)}, + {CDF2(4119)}, + {CDF2(16026)}, + {CDF2(25657)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(31957)}, + {CDF2(3230)}, + {CDF2(11153)}, + {CDF2(18123)}, + {CDF2(20143)}, + {CDF2(26536)}, + {CDF2(31986)}, + {CDF2(3050)}, + {CDF2(14603)}, + {CDF2(25155)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(32363)}, + {CDF2(10692)}, + {CDF2(19090)}, + {CDF2(24357)}, + {CDF2(24442)}, + {CDF2(28312)}, + {CDF2(32169)}, + {CDF2(3648)}, + {CDF2(15690)}, + {CDF2(26815)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(30669)}, + {CDF2(3832)}, + {CDF2(11663)}, + {CDF2(18889)}, + {CDF2(19782)}, + {CDF2(23313)}, + {CDF2(31330)}, + {CDF2(5124)}, + {CDF2(18719)}, + {CDF2(28468)}, + {CDF2(3082)}, + {CDF2(20982)}, + {CDF2(29443)} + }, + { + {CDF2(28573)}, + {CDF2(3183)}, + {CDF2(17802)}, + {CDF2(25977)}, + {CDF2(26677)}, + {CDF2(27832)}, + {CDF2(32387)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + } + }, + { + { + {CDF2(26887)}, + {CDF2(6729)}, + {CDF2(10361)}, + {CDF2(17442)}, + {CDF2(15045)}, + {CDF2(22478)}, + {CDF2(29072)}, + {CDF2(2713)}, + {CDF2(11861)}, + {CDF2(20773)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(31903)}, + {CDF2(2044)}, + {CDF2(7528)}, + {CDF2(14618)}, + {CDF2(16182)}, + {CDF2(24168)}, + {CDF2(31037)}, + {CDF2(2786)}, + {CDF2(11194)}, + {CDF2(20155)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(32510)}, + {CDF2(8430)}, + {CDF2(17318)}, + {CDF2(24154)}, + {CDF2(23674)}, + {CDF2(28789)}, + {CDF2(32139)}, + {CDF2(3440)}, + {CDF2(13117)}, + {CDF2(22702)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + }, + { + {CDF2(31671)}, + {CDF2(2056)}, + {CDF2(11746)}, + {CDF2(16852)}, + {CDF2(18635)}, + {CDF2(24715)}, + {CDF2(31484)}, + {CDF2(4656)}, + {CDF2(16074)}, + {CDF2(24704)}, + {CDF2(1806)}, + {CDF2(14645)}, + {CDF2(25336)} + }, + { + {CDF2(31539)}, + {CDF2(8433)}, + {CDF2(20576)}, + {CDF2(27904)}, + {CDF2(27852)}, + {CDF2(30026)}, + {CDF2(32441)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)} + } + } +}; + +static const RK_U16 +av1_default_eob_extra_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_EOB_COEF_CONTEXTS][AV1_CDF_SIZE(2)] = { + { + { + { + {CDF2(16961)}, + {CDF2(17223)}, + {CDF2(7621)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(19069)}, + {CDF2(22525)}, + {CDF2(13377)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(20401)}, + {CDF2(17025)}, + {CDF2(12845)}, + {CDF2(12873)}, + {CDF2(14094)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(20681)}, + {CDF2(20701)}, + {CDF2(15250)}, + {CDF2(15017)}, + {CDF2(14928)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(23905)}, + {CDF2(17194)}, + {CDF2(16170)}, + {CDF2(17695)}, + {CDF2(13826)}, + {CDF2(15810)}, + {CDF2(12036)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(23959)}, + {CDF2(20799)}, + {CDF2(19021)}, + {CDF2(16203)}, + {CDF2(17886)}, + {CDF2(14144)}, + {CDF2(12010)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(27399)}, + {CDF2(16327)}, + {CDF2(18071)}, + {CDF2(19584)}, + {CDF2(20721)}, + {CDF2(18432)}, + {CDF2(19560)}, + {CDF2(10150)}, + {CDF2(8805)}, + }, + { + {CDF2(24932)}, + {CDF2(20833)}, + {CDF2(12027)}, + {CDF2(16670)}, + {CDF2(19914)}, + {CDF2(15106)}, + {CDF2(17662)}, + {CDF2(13783)}, + {CDF2(28756)}, + } + }, + { + { + {CDF2(23406)}, + {CDF2(21845)}, + {CDF2(18432)}, + {CDF2(16384)}, + {CDF2(17096)}, + {CDF2(12561)}, + {CDF2(17320)}, + {CDF2(22395)}, + {CDF2(21370)}, + }, + { + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + } + }, + { + { + { + {CDF2(17471)}, + {CDF2(20223)}, + {CDF2(11357)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(20335)}, + {CDF2(21667)}, + {CDF2(14818)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(20430)}, + {CDF2(20662)}, + {CDF2(15367)}, + {CDF2(16970)}, + {CDF2(14657)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(22117)}, + {CDF2(22028)}, + {CDF2(18650)}, + {CDF2(16042)}, + {CDF2(15885)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(22409)}, + {CDF2(21012)}, + {CDF2(15650)}, + {CDF2(17395)}, + {CDF2(15469)}, + {CDF2(20205)}, + {CDF2(19511)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(24220)}, + {CDF2(22480)}, + {CDF2(17737)}, + {CDF2(18916)}, + {CDF2(19268)}, + {CDF2(18412)}, + {CDF2(18844)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(25991)}, + {CDF2(20314)}, + {CDF2(17731)}, + {CDF2(19678)}, + {CDF2(18649)}, + {CDF2(17307)}, + {CDF2(21798)}, + {CDF2(17549)}, + {CDF2(15630)}, + }, + { + {CDF2(26585)}, + {CDF2(21469)}, + {CDF2(20432)}, + {CDF2(17735)}, + {CDF2(19280)}, + {CDF2(15235)}, + {CDF2(20297)}, + {CDF2(22471)}, + {CDF2(28997)}, + } + }, + { + { + {CDF2(26605)}, + {CDF2(11304)}, + {CDF2(16726)}, + {CDF2(16560)}, + {CDF2(20866)}, + {CDF2(23524)}, + {CDF2(19878)}, + {CDF2(13469)}, + {CDF2(23084)}, + }, + { + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + } + }, + { + { + { + {CDF2(18983)}, + {CDF2(20512)}, + {CDF2(14885)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(20090)}, + {CDF2(19444)}, + {CDF2(17286)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(19139)}, + {CDF2(21487)}, + {CDF2(18959)}, + {CDF2(20910)}, + {CDF2(19089)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(20536)}, + {CDF2(20664)}, + {CDF2(20625)}, + {CDF2(19123)}, + {CDF2(14862)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(19833)}, + {CDF2(21502)}, + {CDF2(17485)}, + {CDF2(20267)}, + {CDF2(18353)}, + {CDF2(23329)}, + {CDF2(21478)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(22041)}, + {CDF2(23434)}, + {CDF2(20001)}, + {CDF2(20554)}, + {CDF2(20951)}, + {CDF2(20145)}, + {CDF2(15562)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(23312)}, + {CDF2(21607)}, + {CDF2(16526)}, + {CDF2(18957)}, + {CDF2(18034)}, + {CDF2(18934)}, + {CDF2(24247)}, + {CDF2(16921)}, + {CDF2(17080)}, + }, + { + {CDF2(26579)}, + {CDF2(24910)}, + {CDF2(18637)}, + {CDF2(19800)}, + {CDF2(20388)}, + {CDF2(9887)}, + {CDF2(15642)}, + {CDF2(30198)}, + {CDF2(24721)}, + } + }, + { + { + {CDF2(26998)}, + {CDF2(16737)}, + {CDF2(17838)}, + {CDF2(18922)}, + {CDF2(19515)}, + {CDF2(18636)}, + {CDF2(17333)}, + {CDF2(15776)}, + {CDF2(22658)}, + }, + { + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + } + }, + { + { + { + {CDF2(20177)}, + {CDF2(20789)}, + {CDF2(20262)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(21416)}, + {CDF2(20855)}, + {CDF2(23410)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(20238)}, + {CDF2(21057)}, + {CDF2(19159)}, + {CDF2(22337)}, + {CDF2(20159)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(20125)}, + {CDF2(20559)}, + {CDF2(21707)}, + {CDF2(22296)}, + {CDF2(17333)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(19941)}, + {CDF2(20527)}, + {CDF2(21470)}, + {CDF2(22487)}, + {CDF2(19558)}, + {CDF2(22354)}, + {CDF2(20331)}, + {CDF2(16384)}, + {CDF2(16384)}, + }, + { + {CDF2(22752)}, + {CDF2(25006)}, + {CDF2(22075)}, + {CDF2(21576)}, + {CDF2(17740)}, + {CDF2(21690)}, + {CDF2(19211)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + }, + { + { + {CDF2(21442)}, + {CDF2(22358)}, + {CDF2(18503)}, + {CDF2(20291)}, + {CDF2(19945)}, + {CDF2(21294)}, + {CDF2(21178)}, + {CDF2(19400)}, + {CDF2(10556)}, + }, + { + {CDF2(24648)}, + {CDF2(24949)}, + {CDF2(20708)}, + {CDF2(23905)}, + {CDF2(20501)}, + {CDF2(9558)}, + {CDF2(9423)}, + {CDF2(30365)}, + {CDF2(19253)}, + } + }, + { + { + {CDF2(26064)}, + {CDF2(22098)}, + {CDF2(19613)}, + {CDF2(20525)}, + {CDF2(17595)}, + {CDF2(16618)}, + {CDF2(20497)}, + {CDF2(18989)}, + {CDF2(15513)}, + }, + { + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + {CDF2(16384)}, + } + } + } +}; + +static const RK_U16 +av1_default_eob_multi16_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][2][4] = { + { + { + {CDF5(840, 1039, 1980, 4895)}, + {CDF5(370, 671, 1883, 4471)} + }, + { + {CDF5(3247, 4950, 9688, 14563)}, + {CDF5(1904, 3354, 7763, 14647)} + } + }, + { + { + {CDF5(2125, 2551, 5165, 8946)}, + {CDF5(513, 765, 1859, 6339)} + }, + { + {CDF5(7637, 9498, 14259, 19108)}, + {CDF5(2497, 4096, 8866, 16993)} + } + }, + { + { + {CDF5(4016, 4897, 8881, 14968)}, + {CDF5(716, 1105, 2646, 10056)} + }, + { + {CDF5(11139, 13270, 18241, 23566)}, + {CDF5(3192, 5032, 10297, 19755)} + } + }, + { + { + {CDF5(6708, 8958, 14746, 22133)}, + {CDF5(1222, 2074, 4783, 15410)} + }, + { + {CDF5(19575, 21766, 26044, 29709)}, + {CDF5(7297, 10767, 19273, 28194)} + } + } +}; + +static const RK_U16 +av1_default_eob_multi32_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][2][8] = { + { + { + {CDF6(400, 520, 977, 2102, 6542)}, + {CDF6(210, 405, 1315, 3326, 7537)} + }, + { + {CDF6(2636, 4273, 7588, 11794, 20401)}, + {CDF6(1786, 3179, 6902, 11357, 19054)} + } + }, + { + { + {CDF6(989, 1249, 2019, 4151, 10785)}, + {CDF6(313, 441, 1099, 2917, 8562)} + }, + { + {CDF6(8394, 10352, 13932, 18855, 26014)}, + {CDF6(2578, 4124, 8181, 13670, 24234)} + } + }, + { + { + {CDF6(2515, 3003, 4452, 8162, 16041)}, + {CDF6(574, 821, 1836, 5089, 13128)} + }, + { + {CDF6(13468, 16303, 20361, 25105, 29281)}, + {CDF6(3542, 5502, 10415, 16760, 25644)} + } + }, + { + { + {CDF6(4617, 5709, 8446, 13584, 23135)}, + {CDF6(1156, 1702, 3675, 9274, 20539)} + }, + { + {CDF6(22086, 24282, 27010, 29770, 31743)}, + {CDF6(7699, 10897, 20891, 26926, 31628)} + } + } +}; + +static const RK_U16 +av1_default_eob_multi64_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][2][8] = { + { + { + {CDF7(329, 498, 1101, 1784, 3265, 7758)}, + {CDF7(335, 730, 1459, 5494, 8755, 12997)} + }, + { + {CDF7(3505, 5304, 10086, 13814, 17684, 23370)}, + {CDF7(1563, 2700, 4876, 10911, 14706, 22480)} + } + }, + { + { + {CDF7(1260, 1446, 2253, 3712, 6652, 13369)}, + {CDF7(401, 605, 1029, 2563, 5845, 12626)} + }, + { + {CDF7(8609, 10612, 14624, 18714, 22614, 29024)}, + {CDF7(1923, 3127, 5867, 9703, 14277, 27100)} + } + }, + { + { + {CDF7(2374, 2772, 4583, 7276, 12288, 19706)}, + {CDF7(497, 810, 1315, 3000, 7004, 15641)} + }, + { + {CDF7(15050, 17126, 21410, 24886, 28156, 30726)}, + {CDF7(4034, 6290, 10235, 14982, 21214, 28491)} + } + }, + { + { + {CDF7(6307, 7541, 12060, 16358, 22553, 27865)}, + {CDF7(1289, 2320, 3971, 7926, 14153, 24291)} + }, + { + {CDF7(24212, 25708, 28268, 30035, 31307, 32049)}, + {CDF7(8726, 12378, 19409, 26450, 30038, 32462)} + } + } +}; + +static const RK_U16 +av1_default_eob_multi128_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][2][8] = { + { + { + {CDF8(219, 482, 1140, 2091, 3680, 6028, 12586)}, + {CDF8(371, 699, 1254, 4830, 9479, 12562, 17497)} + }, + { + {CDF8(5245, 7456, 12880, 15852, 20033, 23932, 27608)}, + {CDF8(2054, 3472, 5869, 14232, 18242, 20590, 26752)} + } + }, + { + { + {CDF8(685, 933, 1488, 2714, 4766, 8562, 19254)}, + {CDF8(217, 352, 618, 2303, 5261, 9969, 17472)} + }, + { + {CDF8(8045, 11200, 15497, 19595, 23948, 27408, 30938)}, + {CDF8(2310, 4160, 7471, 14997, 17931, 20768, 30240)} + } + }, + { + { + {CDF8(1366, 1738, 2527, 5016, 9355, 15797, 24643)}, + {CDF8(354, 558, 944, 2760, 7287, 14037, 21779)} + }, + { + {CDF8(13627, 16246, 20173, 24429, 27948, 30415, 31863)}, + {CDF8(6275, 9889, 14769, 23164, 27988, 30493, 32272)} + } + }, + { + { + {CDF8(3472, 4885, 7489, 12481, 18517, 24536, 29635)}, + {CDF8(886, 1731, 3271, 8469, 15569, 22126, 28383)} + }, + { + {CDF8(24313, 26062, 28385, 30107, 31217, 31898, 32345)}, + {CDF8(9165, 13282, 21150, 30286, 31894, 32571, 32712)} + } + } +}; + +static const RK_U16 +av1_default_eob_multi256_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][2][8] = { + { + { + {CDF9(310, 584, 1887, 3589, 6168, 8611, 11352, 15652)}, + {CDF9(998, 1850, 2998, 5604, 17341, 19888, 22899, 25583)} + }, + { + {CDF9(2520, 3240, 5952, 8870, 12577, 17558, 19954, 24168)}, + {CDF9(2203, 4130, 7435, 10739, 20652, 23681, 25609, 27261)} + } + }, + { + { + {CDF9(1448, 2109, 4151, 6263, 9329, 13260, 17944, 23300)}, + {CDF9(399, 1019, 1749, 3038, 10444, 15546, 22739, 27294)} + }, + { + {CDF9(6402, 8148, 12623, 15072, 18728, 22847, 26447, 29377)}, + {CDF9(1674, 3252, 5734, 10159, 22397, 23802, 24821, 30940)} + } + }, + { + { + {CDF9(3089, 3920, 6038, 9460, 14266, 19881, 25766, 29176)}, + {CDF9(1084, 2358, 3488, 5122, 11483, 18103, 26023, 29799)} + }, + { + {CDF9(11514, 13794, 17480, 20754, 24361, 27378, 29492, 31277)}, + {CDF9(6571, 9610, 15516, 21826, 29092, 30829, 31842, 32708)} + } + }, + { + { + {CDF9(5348, 7113, 11820, 15924, 22106, 26777, 30334, 31757)}, + {CDF9(2453, 4474, 6307, 8777, 16474, 22975, 29000, 31547)} + }, + { + {CDF9(23110, 24597, 27140, 28894, 30167, 30927, 31392, 32094)}, + {CDF9(9998, 17661, 25178, 28097, 31308, 32038, 32403, 32695)} + } + } +}; + +static const RK_U16 +av1_default_eob_multi512_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][2][16] = { + { + { + {CDF10(641, 983, 3707, 5430, 10234, 14958, 18788, 23412, 26061)}, + {CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + {CDF10(5095, 6446, 9996, 13354, 16017, 17986, 20919, 26129, 29140)}, + { + CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, + 29491) + } + } + }, + { + { + {CDF10(1230, 2278, 5035, 7776, 11871, 15346, 19590, 24584, 28749)}, + {CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + {CDF10(7265, 9979, 15819, 19250, 21780, 23846, 26478, 28396, 31811)}, + {CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + {CDF10(2624, 3936, 6480, 9686, 13979, 17726, 23267, 28410, 31078)}, + {CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + {CDF10(12015, 14769, 19588, 22052, 24222, 25812, 27300, 29219, 32114)}, + {CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + {CDF10(5927, 7809, 10923, 14597, 19439, 24135, 28456, 31142, 32060)}, + {CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + {CDF10(21093, 23043, 25742, 27658, 29097, 29716, 30073, 30820, 31956)}, + {CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + } +}; + +static const RK_U16 +av1_default_eob_multi1024_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_PLANE_TYPES][2][16] = { + { + { + {CDF11(393, 421, 751, 1623, 3160, 6352, 13345, 18047, 22571, 25830)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + }, + { + {CDF11(1865, 1988, 2930, 4242, 10533, 16538, 21354, 27255, 28546, 31784)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + {CDF11(696, 948, 3145, 5702, 9706, 13217, 17851, 21856, 25692, 28034)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + }, + { + {CDF11(2672, 3591, 9330, 17084, 22725, 24284, 26527, 28027, 28377, 30876)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + {CDF11(2784, 3831, 7041, 10521, 14847, 18844, 23155, 26682, 29229, 31045)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + }, + { + {CDF11(9577, 12466, 17739, 20750, 22061, 23215, 24601, 25483, 25843, 32056)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + {CDF11(6698, 8334, 11961, 15762, 20186, 23862, 27434, 29326, 31082, 32050)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + }, + { + {CDF11(20569, 22426, 25569, 26859, 28053, 28913, 29486, 29724, 29807, 32570)}, + {CDF11(2979, 5958, 8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789)} + } + } +}; + +static const RK_U16 +av1_default_coeff_lps_multi_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_LEVEL_CONTEXTS][AV1_CDF_SIZE(AV1_BR_CDF_SIZE) + 1] = { + { + { + { + {CDF4(14298, 20718, 24174)}, {CDF4(12536, 19601, 23789)}, + {CDF4(8712, 15051, 19503)}, {CDF4(6170, 11327, 15434)}, + {CDF4(4742, 8926, 12538)}, {CDF4(3803, 7317, 10546)}, + {CDF4(1696, 3317, 4871)}, {CDF4(14392, 19951, 22756)}, + {CDF4(15978, 23218, 26818)}, {CDF4(12187, 19474, 23889)}, + {CDF4(9176, 15640, 20259)}, {CDF4(7068, 12655, 17028)}, + {CDF4(5656, 10442, 14472)}, {CDF4(2580, 4992, 7244)}, + {CDF4(12136, 18049, 21426)}, {CDF4(13784, 20721, 24481)}, + {CDF4(10836, 17621, 21900)}, {CDF4(8372, 14444, 18847)}, + {CDF4(6523, 11779, 16000)}, {CDF4(5337, 9898, 13760)}, + {CDF4(3034, 5860, 8462)} + }, + { + {CDF4(15967, 22905, 26286)}, {CDF4(13534, 20654, 24579)}, + {CDF4(9504, 16092, 20535)}, {CDF4(6975, 12568, 16903)}, + {CDF4(5364, 10091, 14020)}, {CDF4(4357, 8370, 11857)}, + {CDF4(2506, 4934, 7218)}, {CDF4(23032, 28815, 30936)}, + {CDF4(19540, 26704, 29719)}, {CDF4(15158, 22969, 27097)}, + {CDF4(11408, 18865, 23650)}, {CDF4(8885, 15448, 20250)}, + {CDF4(7108, 12853, 17416)}, {CDF4(4231, 8041, 11480)}, + {CDF4(19823, 26490, 29156)}, {CDF4(18890, 25929, 28932)}, + {CDF4(15660, 23491, 27433)}, {CDF4(12147, 19776, 24488)}, + {CDF4(9728, 16774, 21649)}, {CDF4(7919, 14277, 19066)}, + {CDF4(5440, 10170, 14185)} + } + }, + { + { + {CDF4(14406, 20862, 24414)}, {CDF4(11824, 18907, 23109)}, + {CDF4(8257, 14393, 18803)}, {CDF4(5860, 10747, 14778)}, + {CDF4(4475, 8486, 11984)}, {CDF4(3606, 6954, 10043)}, + {CDF4(1736, 3410, 5048)}, {CDF4(14430, 20046, 22882)}, + {CDF4(15593, 22899, 26709)}, {CDF4(12102, 19368, 23811)}, + {CDF4(9059, 15584, 20262)}, {CDF4(6999, 12603, 17048)}, + {CDF4(5684, 10497, 14553)}, {CDF4(2822, 5438, 7862)}, + {CDF4(15785, 21585, 24359)}, {CDF4(18347, 25229, 28266)}, + {CDF4(14974, 22487, 26389)}, {CDF4(11423, 18681, 23271)}, + {CDF4(8863, 15350, 20008)}, {CDF4(7153, 12852, 17278)}, + {CDF4(3707, 7036, 9982)} + }, + { + {CDF4(15460, 21696, 25469)}, {CDF4(12170, 19249, 23191)}, + {CDF4(8723, 15027, 19332)}, {CDF4(6428, 11704, 15874)}, + {CDF4(4922, 9292, 13052)}, {CDF4(4139, 7695, 11010)}, + {CDF4(2291, 4508, 6598)}, {CDF4(19856, 26920, 29828)}, + {CDF4(17923, 25289, 28792)}, {CDF4(14278, 21968, 26297)}, + {CDF4(10910, 18136, 22950)}, {CDF4(8423, 14815, 19627)}, + {CDF4(6771, 12283, 16774)}, {CDF4(4074, 7750, 11081)}, + {CDF4(19852, 26074, 28672)}, {CDF4(19371, 26110, 28989)}, + {CDF4(16265, 23873, 27663)}, {CDF4(12758, 20378, 24952)}, + {CDF4(10095, 17098, 21961)}, {CDF4(8250, 14628, 19451)}, + {CDF4(5205, 9745, 13622)} + } + }, + { + { + {CDF4(10563, 16233, 19763)}, {CDF4(9794, 16022, 19804)}, + {CDF4(6750, 11945, 15759)}, {CDF4(4963, 9186, 12752)}, + {CDF4(3845, 7435, 10627)}, {CDF4(3051, 6085, 8834)}, + {CDF4(1311, 2596, 3830)}, {CDF4(11246, 16404, 19689)}, + {CDF4(12315, 18911, 22731)}, {CDF4(10557, 17095, 21289)}, + {CDF4(8136, 14006, 18249)}, {CDF4(6348, 11474, 15565)}, + {CDF4(5196, 9655, 13400)}, {CDF4(2349, 4526, 6587)}, + {CDF4(13337, 18730, 21569)}, {CDF4(19306, 26071, 28882)}, + {CDF4(15952, 23540, 27254)}, {CDF4(12409, 19934, 24430)}, + {CDF4(9760, 16706, 21389)}, {CDF4(8004, 14220, 18818)}, + {CDF4(4138, 7794, 10961)} + }, + { + {CDF4(10870, 16684, 20949)}, {CDF4(9664, 15230, 18680)}, + {CDF4(6886, 12109, 15408)}, {CDF4(4825, 8900, 12305)}, + {CDF4(3630, 7162, 10314)}, {CDF4(3036, 6429, 9387)}, + {CDF4(1671, 3296, 4940)}, {CDF4(13819, 19159, 23026)}, + {CDF4(11984, 19108, 23120)}, {CDF4(10690, 17210, 21663)}, + {CDF4(7984, 14154, 18333)}, {CDF4(6868, 12294, 16124)}, + {CDF4(5274, 8994, 12868)}, {CDF4(2988, 5771, 8424)}, + {CDF4(19736, 26647, 29141)}, {CDF4(18933, 26070, 28984)}, + {CDF4(15779, 23048, 27200)}, {CDF4(12638, 20061, 24532)}, + {CDF4(10692, 17545, 22220)}, {CDF4(9217, 15251, 20054)}, + {CDF4(5078, 9284, 12594)} + } + }, + { + { + {CDF4(2331, 3662, 5244)}, {CDF4(2891, 4771, 6145)}, + {CDF4(4598, 7623, 9729)}, {CDF4(3520, 6845, 9199)}, + {CDF4(3417, 6119, 9324)}, {CDF4(2601, 5412, 7385)}, + {CDF4(600, 1173, 1744)}, {CDF4(7672, 13286, 17469)}, + {CDF4(4232, 7792, 10793)}, {CDF4(2915, 5317, 7397)}, + {CDF4(2318, 4356, 6152)}, {CDF4(2127, 4000, 5554)}, + {CDF4(1850, 3478, 5275)}, {CDF4(977, 1933, 2843)}, + {CDF4(18280, 24387, 27989)}, {CDF4(15852, 22671, 26185)}, + {CDF4(13845, 20951, 24789)}, {CDF4(11055, 17966, 22129)}, + {CDF4(9138, 15422, 19801)}, {CDF4(7454, 13145, 17456)}, + {CDF4(3370, 6393, 9013)} + }, + { + {CDF4(5842, 9229, 10838)}, {CDF4(2313, 3491, 4276)}, + {CDF4(2998, 6104, 7496)}, {CDF4(2420, 7447, 9868)}, + {CDF4(3034, 8495, 10923)}, {CDF4(4076, 8937, 10975)}, + {CDF4(1086, 2370, 3299)}, {CDF4(9714, 17254, 20444)}, + {CDF4(8543, 13698, 17123)}, {CDF4(4918, 9007, 11910)}, + {CDF4(4129, 7532, 10553)}, {CDF4(2364, 5533, 8058)}, + {CDF4(1834, 3546, 5563)}, {CDF4(1473, 2908, 4133)}, + {CDF4(15405, 21193, 25619)}, {CDF4(15691, 21952, 26561)}, + {CDF4(12962, 19194, 24165)}, {CDF4(10272, 17855, 22129)}, + {CDF4(8588, 15270, 20718)}, {CDF4(8682, 14669, 19500)}, + {CDF4(4870, 9636, 13205)} + } + }, + { + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + {CDF4(14995, 21341, 24749)}, {CDF4(13158, 20289, 24601)}, + {CDF4(8941, 15326, 19876)}, {CDF4(6297, 11541, 15807)}, + {CDF4(4817, 9029, 12776)}, {CDF4(3731, 7273, 10627)}, + {CDF4(1847, 3617, 5354)}, {CDF4(14472, 19659, 22343)}, + {CDF4(16806, 24162, 27533)}, {CDF4(12900, 20404, 24713)}, + {CDF4(9411, 16112, 20797)}, {CDF4(7056, 12697, 17148)}, + {CDF4(5544, 10339, 14460)}, {CDF4(2954, 5704, 8319)}, + {CDF4(12464, 18071, 21354)}, {CDF4(15482, 22528, 26034)}, + {CDF4(12070, 19269, 23624)}, {CDF4(8953, 15406, 20106)}, + {CDF4(7027, 12730, 17220)}, {CDF4(5887, 10913, 15140)}, + {CDF4(3793, 7278, 10447)} + }, + { + {CDF4(15571, 22232, 25749)}, {CDF4(14506, 21575, 25374)}, + {CDF4(10189, 17089, 21569)}, {CDF4(7316, 13301, 17915)}, + {CDF4(5783, 10912, 15190)}, {CDF4(4760, 9155, 13088)}, + {CDF4(2993, 5966, 8774)}, {CDF4(23424, 28903, 30778)}, + {CDF4(20775, 27666, 30290)}, {CDF4(16474, 24410, 28299)}, + {CDF4(12471, 20180, 24987)}, {CDF4(9410, 16487, 21439)}, + {CDF4(7536, 13614, 18529)}, {CDF4(5048, 9586, 13549)}, + {CDF4(21090, 27290, 29756)}, {CDF4(20796, 27402, 30026)}, + {CDF4(17819, 25485, 28969)}, {CDF4(13860, 21909, 26462)}, + {CDF4(11002, 18494, 23529)}, {CDF4(8953, 15929, 20897)}, + {CDF4(6448, 11918, 16454)} + } + }, + { + { + {CDF4(15999, 22208, 25449)}, {CDF4(13050, 19988, 24122)}, + {CDF4(8594, 14864, 19378)}, {CDF4(6033, 11079, 15238)}, + {CDF4(4554, 8683, 12347)}, {CDF4(3672, 7139, 10337)}, + {CDF4(1900, 3771, 5576)}, {CDF4(15788, 21340, 23949)}, + {CDF4(16825, 24235, 27758)}, {CDF4(12873, 20402, 24810)}, + {CDF4(9590, 16363, 21094)}, {CDF4(7352, 13209, 17733)}, + {CDF4(5960, 10989, 15184)}, {CDF4(3232, 6234, 9007)}, + {CDF4(15761, 20716, 23224)}, {CDF4(19318, 25989, 28759)}, + {CDF4(15529, 23094, 26929)}, {CDF4(11662, 18989, 23641)}, + {CDF4(8955, 15568, 20366)}, {CDF4(7281, 13106, 17708)}, + {CDF4(4248, 8059, 11440)} + }, + { + {CDF4(14899, 21217, 24503)}, {CDF4(13519, 20283, 24047)}, + {CDF4(9429, 15966, 20365)}, {CDF4(6700, 12355, 16652)}, + {CDF4(5088, 9704, 13716)}, {CDF4(4243, 8154, 11731)}, + {CDF4(2702, 5364, 7861)}, {CDF4(22745, 28388, 30454)}, + {CDF4(20235, 27146, 29922)}, {CDF4(15896, 23715, 27637)}, + {CDF4(11840, 19350, 24131)}, {CDF4(9122, 15932, 20880)}, + {CDF4(7488, 13581, 18362)}, {CDF4(5114, 9568, 13370)}, + {CDF4(20845, 26553, 28932)}, {CDF4(20981, 27372, 29884)}, + {CDF4(17781, 25335, 28785)}, {CDF4(13760, 21708, 26297)}, + {CDF4(10975, 18415, 23365)}, {CDF4(9045, 15789, 20686)}, + {CDF4(6130, 11199, 15423)} + } + }, + { + { + {CDF4(13549, 19724, 23158)}, {CDF4(11844, 18382, 22246)}, + {CDF4(7919, 13619, 17773)}, {CDF4(5486, 10143, 13946)}, + {CDF4(4166, 7983, 11324)}, {CDF4(3364, 6506, 9427)}, + {CDF4(1598, 3160, 4674)}, {CDF4(15281, 20979, 23781)}, + {CDF4(14939, 22119, 25952)}, {CDF4(11363, 18407, 22812)}, + {CDF4(8609, 14857, 19370)}, {CDF4(6737, 12184, 16480)}, + {CDF4(5506, 10263, 14262)}, {CDF4(2990, 5786, 8380)}, + {CDF4(20249, 25253, 27417)}, {CDF4(21070, 27518, 30001)}, + {CDF4(16854, 24469, 28074)}, {CDF4(12864, 20486, 25000)}, + {CDF4(9962, 16978, 21778)}, {CDF4(8074, 14338, 19048)}, + {CDF4(4494, 8479, 11906)} + }, + { + {CDF4(13960, 19617, 22829)}, {CDF4(11150, 17341, 21228)}, + {CDF4(7150, 12964, 17190)}, {CDF4(5331, 10002, 13867)}, + {CDF4(4167, 7744, 11057)}, {CDF4(3480, 6629, 9646)}, + {CDF4(1883, 3784, 5686)}, {CDF4(18752, 25660, 28912)}, + {CDF4(16968, 24586, 28030)}, {CDF4(13520, 21055, 25313)}, + {CDF4(10453, 17626, 22280)}, {CDF4(8386, 14505, 19116)}, + {CDF4(6742, 12595, 17008)}, {CDF4(4273, 8140, 11499)}, + {CDF4(22120, 27827, 30233)}, {CDF4(20563, 27358, 29895)}, + {CDF4(17076, 24644, 28153)}, {CDF4(13362, 20942, 25309)}, + {CDF4(10794, 17965, 22695)}, {CDF4(9014, 15652, 20319)}, + {CDF4(5708, 10512, 14497)} + } + }, + { + { + {CDF4(5705, 10930, 15725)}, {CDF4(7946, 12765, 16115)}, + {CDF4(6801, 12123, 16226)}, {CDF4(5462, 10135, 14200)}, + {CDF4(4189, 8011, 11507)}, {CDF4(3191, 6229, 9408)}, + {CDF4(1057, 2137, 3212)}, {CDF4(10018, 17067, 21491)}, + {CDF4(7380, 12582, 16453)}, {CDF4(6068, 10845, 14339)}, + {CDF4(5098, 9198, 12555)}, {CDF4(4312, 8010, 11119)}, + {CDF4(3700, 6966, 9781)}, {CDF4(1693, 3326, 4887)}, + {CDF4(18757, 24930, 27774)}, {CDF4(17648, 24596, 27817)}, + {CDF4(14707, 22052, 26026)}, {CDF4(11720, 18852, 23292)}, + {CDF4(9357, 15952, 20525)}, {CDF4(7810, 13753, 18210)}, + {CDF4(3879, 7333, 10328)} + }, + { + {CDF4(8278, 13242, 15922)}, {CDF4(10547, 15867, 18919)}, + {CDF4(9106, 15842, 20609)}, {CDF4(6833, 13007, 17218)}, + {CDF4(4811, 9712, 13923)}, {CDF4(3985, 7352, 11128)}, + {CDF4(1688, 3458, 5262)}, {CDF4(12951, 21861, 26510)}, + {CDF4(9788, 16044, 20276)}, {CDF4(6309, 11244, 14870)}, + {CDF4(5183, 9349, 12566)}, {CDF4(4389, 8229, 11492)}, + {CDF4(3633, 6945, 10620)}, {CDF4(3600, 6847, 9907)}, + {CDF4(21748, 28137, 30255)}, {CDF4(19436, 26581, 29560)}, + {CDF4(16359, 24201, 27953)}, {CDF4(13961, 21693, 25871)}, + {CDF4(11544, 18686, 23322)}, {CDF4(9372, 16462, 20952)}, + {CDF4(6138, 11210, 15390)} + } + }, + { + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + {CDF4(16138, 22223, 25509)}, {CDF4(15347, 22430, 26332)}, + {CDF4(9614, 16736, 21332)}, {CDF4(6600, 12275, 16907)}, + {CDF4(4811, 9424, 13547)}, {CDF4(3748, 7809, 11420)}, + {CDF4(2254, 4587, 6890)}, {CDF4(15196, 20284, 23177)}, + {CDF4(18317, 25469, 28451)}, {CDF4(13918, 21651, 25842)}, + {CDF4(10052, 17150, 21995)}, {CDF4(7499, 13630, 18587)}, + {CDF4(6158, 11417, 16003)}, {CDF4(4014, 7785, 11252)}, + {CDF4(15048, 21067, 24384)}, {CDF4(18202, 25346, 28553)}, + {CDF4(14302, 22019, 26356)}, {CDF4(10839, 18139, 23166)}, + {CDF4(8715, 15744, 20806)}, {CDF4(7536, 13576, 18544)}, + {CDF4(5413, 10335, 14498)} + }, + { + {CDF4(17394, 24501, 27895)}, {CDF4(15889, 23420, 27185)}, + {CDF4(11561, 19133, 23870)}, {CDF4(8285, 14812, 19844)}, + {CDF4(6496, 12043, 16550)}, {CDF4(4771, 9574, 13677)}, + {CDF4(3603, 6830, 10144)}, {CDF4(21656, 27704, 30200)}, + {CDF4(21324, 27915, 30511)}, {CDF4(17327, 25336, 28997)}, + {CDF4(13417, 21381, 26033)}, {CDF4(10132, 17425, 22338)}, + {CDF4(8580, 15016, 19633)}, {CDF4(5694, 11477, 16411)}, + {CDF4(24116, 29780, 31450)}, {CDF4(23853, 29695, 31591)}, + {CDF4(20085, 27614, 30428)}, {CDF4(15326, 24335, 28575)}, + {CDF4(11814, 19472, 24810)}, {CDF4(10221, 18611, 24767)}, + {CDF4(7689, 14558, 20321)} + } + }, + { + { + {CDF4(16214, 22380, 25770)}, {CDF4(14213, 21304, 25295)}, + {CDF4(9213, 15823, 20455)}, {CDF4(6395, 11758, 16139)}, + {CDF4(4779, 9187, 13066)}, {CDF4(3821, 7501, 10953)}, + {CDF4(2293, 4567, 6795)}, {CDF4(15859, 21283, 23820)}, + {CDF4(18404, 25602, 28726)}, {CDF4(14325, 21980, 26206)}, + {CDF4(10669, 17937, 22720)}, {CDF4(8297, 14642, 19447)}, + {CDF4(6746, 12389, 16893)}, {CDF4(4324, 8251, 11770)}, + {CDF4(16532, 21631, 24475)}, {CDF4(20667, 27150, 29668)}, + {CDF4(16728, 24510, 28175)}, {CDF4(12861, 20645, 25332)}, + {CDF4(10076, 17361, 22417)}, {CDF4(8395, 14940, 19963)}, + {CDF4(5731, 10683, 14912)} + }, + { + {CDF4(14433, 21155, 24938)}, {CDF4(14658, 21716, 25545)}, + {CDF4(9923, 16824, 21557)}, {CDF4(6982, 13052, 17721)}, + {CDF4(5419, 10503, 15050)}, {CDF4(4852, 9162, 13014)}, + {CDF4(3271, 6395, 9630)}, {CDF4(22210, 27833, 30109)}, + {CDF4(20750, 27368, 29821)}, {CDF4(16894, 24828, 28573)}, + {CDF4(13247, 21276, 25757)}, {CDF4(10038, 17265, 22563)}, + {CDF4(8587, 14947, 20327)}, {CDF4(5645, 11371, 15252)}, + {CDF4(22027, 27526, 29714)}, {CDF4(23098, 29146, 31221)}, + {CDF4(19886, 27341, 30272)}, {CDF4(15609, 23747, 28046)}, + {CDF4(11993, 20065, 24939)}, {CDF4(9637, 18267, 23671)}, + {CDF4(7625, 13801, 19144)} + } + }, + { + { + {CDF4(14438, 20798, 24089)}, {CDF4(12621, 19203, 23097)}, + {CDF4(8177, 14125, 18402)}, {CDF4(5674, 10501, 14456)}, + {CDF4(4236, 8239, 11733)}, {CDF4(3447, 6750, 9806)}, + {CDF4(1986, 3950, 5864)}, {CDF4(16208, 22099, 24930)}, + {CDF4(16537, 24025, 27585)}, {CDF4(12780, 20381, 24867)}, + {CDF4(9767, 16612, 21416)}, {CDF4(7686, 13738, 18398)}, + {CDF4(6333, 11614, 15964)}, {CDF4(3941, 7571, 10836)}, + {CDF4(22819, 27422, 29202)}, {CDF4(22224, 28514, 30721)}, + {CDF4(17660, 25433, 28913)}, {CDF4(13574, 21482, 26002)}, + {CDF4(10629, 17977, 22938)}, {CDF4(8612, 15298, 20265)}, + {CDF4(5607, 10491, 14596)} + }, + { + {CDF4(13569, 19800, 23206)}, {CDF4(13128, 19924, 23869)}, + {CDF4(8329, 14841, 19403)}, {CDF4(6130, 10976, 15057)}, + {CDF4(4682, 8839, 12518)}, {CDF4(3656, 7409, 10588)}, + {CDF4(2577, 5099, 7412)}, {CDF4(22427, 28684, 30585)}, + {CDF4(20913, 27750, 30139)}, {CDF4(15840, 24109, 27834)}, + {CDF4(12308, 20029, 24569)}, {CDF4(10216, 16785, 21458)}, + {CDF4(8309, 14203, 19113)}, {CDF4(6043, 11168, 15307)}, + {CDF4(23166, 28901, 30998)}, {CDF4(21899, 28405, 30751)}, + {CDF4(18413, 26091, 29443)}, {CDF4(15233, 23114, 27352)}, + {CDF4(12683, 20472, 25288)}, {CDF4(10702, 18259, 23409)}, + {CDF4(8125, 14464, 19226)} + } + }, + { + { + {CDF4(9040, 14786, 18360)}, {CDF4(9979, 15718, 19415)}, + {CDF4(7913, 13918, 18311)}, {CDF4(5859, 10889, 15184)}, + {CDF4(4593, 8677, 12510)}, {CDF4(3820, 7396, 10791)}, + {CDF4(1730, 3471, 5192)}, {CDF4(11803, 18365, 22709)}, + {CDF4(11419, 18058, 22225)}, {CDF4(9418, 15774, 20243)}, + {CDF4(7539, 13325, 17657)}, {CDF4(6233, 11317, 15384)}, + {CDF4(5137, 9656, 13545)}, {CDF4(2977, 5774, 8349)}, + {CDF4(21207, 27246, 29640)}, {CDF4(19547, 26578, 29497)}, + {CDF4(16169, 23871, 27690)}, {CDF4(12820, 20458, 25018)}, + {CDF4(10224, 17332, 22214)}, {CDF4(8526, 15048, 19884)}, + {CDF4(5037, 9410, 13118)} + }, + { + {CDF4(12339, 17329, 20140)}, {CDF4(13505, 19895, 23225)}, + {CDF4(9847, 16944, 21564)}, {CDF4(7280, 13256, 18348)}, + {CDF4(4712, 10009, 14454)}, {CDF4(4361, 7914, 12477)}, + {CDF4(2870, 5628, 7995)}, {CDF4(20061, 25504, 28526)}, + {CDF4(15235, 22878, 26145)}, {CDF4(12985, 19958, 24155)}, + {CDF4(9782, 16641, 21403)}, {CDF4(9456, 16360, 20760)}, + {CDF4(6855, 12940, 18557)}, {CDF4(5661, 10564, 15002)}, + {CDF4(25656, 30602, 31894)}, {CDF4(22570, 29107, 31092)}, + {CDF4(18917, 26423, 29541)}, {CDF4(15940, 23649, 27754)}, + {CDF4(12803, 20581, 25219)}, {CDF4(11082, 18695, 23376)}, + {CDF4(7939, 14373, 19005)} + } + }, + { + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + {CDF4(18315, 24289, 27551)}, {CDF4(16854, 24068, 27835)}, + {CDF4(10140, 17927, 23173)}, {CDF4(6722, 12982, 18267)}, + {CDF4(4661, 9826, 14706)}, {CDF4(3832, 8165, 12294)}, + {CDF4(2795, 6098, 9245)}, {CDF4(17145, 23326, 26672)}, + {CDF4(20733, 27680, 30308)}, {CDF4(16032, 24461, 28546)}, + {CDF4(11653, 20093, 25081)}, {CDF4(9290, 16429, 22086)}, + {CDF4(7796, 14598, 19982)}, {CDF4(6502, 12378, 17441)}, + {CDF4(21681, 27732, 30320)}, {CDF4(22389, 29044, 31261)}, + {CDF4(19027, 26731, 30087)}, {CDF4(14739, 23755, 28624)}, + {CDF4(11358, 20778, 25511)}, {CDF4(10995, 18073, 24190)}, + {CDF4(9162, 14990, 20617)} + }, + { + {CDF4(21425, 27952, 30388)}, {CDF4(18062, 25838, 29034)}, + {CDF4(11956, 19881, 24808)}, {CDF4(7718, 15000, 20980)}, + {CDF4(5702, 11254, 16143)}, {CDF4(4898, 9088, 16864)}, + {CDF4(3679, 6776, 11907)}, {CDF4(23294, 30160, 31663)}, + {CDF4(24397, 29896, 31836)}, {CDF4(19245, 27128, 30593)}, + {CDF4(13202, 19825, 26404)}, {CDF4(11578, 19297, 23957)}, + {CDF4(8073, 13297, 21370)}, {CDF4(5461, 10923, 19745)}, + {CDF4(27367, 30521, 31934)}, {CDF4(24904, 30671, 31940)}, + {CDF4(23075, 28460, 31299)}, {CDF4(14400, 23658, 30417)}, + {CDF4(13885, 23882, 28325)}, {CDF4(14746, 22938, 27853)}, + {CDF4(5461, 16384, 27307)} + } + }, + { + { + {CDF4(18274, 24813, 27890)}, {CDF4(15537, 23149, 27003)}, + {CDF4(9449, 16740, 21827)}, {CDF4(6700, 12498, 17261)}, + {CDF4(4988, 9866, 14198)}, {CDF4(4236, 8147, 11902)}, + {CDF4(2867, 5860, 8654)}, {CDF4(17124, 23171, 26101)}, + {CDF4(20396, 27477, 30148)}, {CDF4(16573, 24629, 28492)}, + {CDF4(12749, 20846, 25674)}, {CDF4(10233, 17878, 22818)}, + {CDF4(8525, 15332, 20363)}, {CDF4(6283, 11632, 16255)}, + {CDF4(20466, 26511, 29286)}, {CDF4(23059, 29174, 31191)}, + {CDF4(19481, 27263, 30241)}, {CDF4(15458, 23631, 28137)}, + {CDF4(12416, 20608, 25693)}, {CDF4(10261, 18011, 23261)}, + {CDF4(8016, 14655, 19666)} + }, + { + {CDF4(17616, 24586, 28112)}, {CDF4(15809, 23299, 27155)}, + {CDF4(10767, 18890, 23793)}, {CDF4(7727, 14255, 18865)}, + {CDF4(6129, 11926, 16882)}, {CDF4(4482, 9704, 14861)}, + {CDF4(3277, 7452, 11522)}, {CDF4(22956, 28551, 30730)}, + {CDF4(22724, 28937, 30961)}, {CDF4(18467, 26324, 29580)}, + {CDF4(13234, 20713, 25649)}, {CDF4(11181, 17592, 22481)}, + {CDF4(8291, 18358, 24576)}, {CDF4(7568, 11881, 14984)}, + {CDF4(24948, 29001, 31147)}, {CDF4(25674, 30619, 32151)}, + {CDF4(20841, 26793, 29603)}, {CDF4(14669, 24356, 28666)}, + {CDF4(11334, 23593, 28219)}, {CDF4(8922, 14762, 22873)}, + {CDF4(8301, 13544, 20535)} + } + }, + { + { + {CDF4(17113, 23733, 27081)}, {CDF4(14139, 21406, 25452)}, + {CDF4(8552, 15002, 19776)}, {CDF4(5871, 11120, 15378)}, + {CDF4(4455, 8616, 12253)}, {CDF4(3469, 6910, 10386)}, + {CDF4(2255, 4553, 6782)}, {CDF4(18224, 24376, 27053)}, + {CDF4(19290, 26710, 29614)}, {CDF4(14936, 22991, 27184)}, + {CDF4(11238, 18951, 23762)}, {CDF4(8786, 15617, 20588)}, + {CDF4(7317, 13228, 18003)}, {CDF4(5101, 9512, 13493)}, + {CDF4(22639, 28222, 30210)}, {CDF4(23216, 29331, 31307)}, + {CDF4(19075, 26762, 29895)}, {CDF4(15014, 23113, 27457)}, + {CDF4(11938, 19857, 24752)}, {CDF4(9942, 17280, 22282)}, + {CDF4(7167, 13144, 17752)} + }, + { + {CDF4(15820, 22738, 26488)}, {CDF4(13530, 20885, 25216)}, + {CDF4(8395, 15530, 20452)}, {CDF4(6574, 12321, 16380)}, + {CDF4(5353, 10419, 14568)}, {CDF4(4613, 8446, 12381)}, + {CDF4(3440, 7158, 9903)}, {CDF4(24247, 29051, 31224)}, + {CDF4(22118, 28058, 30369)}, {CDF4(16498, 24768, 28389)}, + {CDF4(12920, 21175, 26137)}, {CDF4(10730, 18619, 25352)}, + {CDF4(10187, 16279, 22791)}, {CDF4(9310, 14631, 22127)}, + {CDF4(24970, 30558, 32057)}, {CDF4(24801, 29942, 31698)}, + {CDF4(22432, 28453, 30855)}, {CDF4(19054, 25680, 29580)}, + {CDF4(14392, 23036, 28109)}, {CDF4(12495, 20947, 26650)}, + {CDF4(12442, 20326, 26214)} + } + }, + { + { + {CDF4(12162, 18785, 22648)}, {CDF4(12749, 19697, 23806)}, + {CDF4(8580, 15297, 20346)}, {CDF4(6169, 11749, 16543)}, + {CDF4(4836, 9391, 13448)}, {CDF4(3821, 7711, 11613)}, + {CDF4(2228, 4601, 7070)}, {CDF4(16319, 24725, 28280)}, + {CDF4(15698, 23277, 27168)}, {CDF4(12726, 20368, 25047)}, + {CDF4(9912, 17015, 21976)}, {CDF4(7888, 14220, 19179)}, + {CDF4(6777, 12284, 17018)}, {CDF4(4492, 8590, 12252)}, + {CDF4(23249, 28904, 30947)}, {CDF4(21050, 27908, 30512)}, + {CDF4(17440, 25340, 28949)}, {CDF4(14059, 22018, 26541)}, + {CDF4(11288, 18903, 23898)}, {CDF4(9411, 16342, 21428)}, + {CDF4(6278, 11588, 15944)} + }, + { + {CDF4(13981, 20067, 23226)}, {CDF4(16922, 23580, 26783)}, + {CDF4(11005, 19039, 24487)}, {CDF4(7389, 14218, 19798)}, + {CDF4(5598, 11505, 17206)}, {CDF4(6090, 11213, 15659)}, + {CDF4(3820, 7371, 10119)}, {CDF4(21082, 26925, 29675)}, + {CDF4(21262, 28627, 31128)}, {CDF4(18392, 26454, 30437)}, + {CDF4(14870, 22910, 27096)}, {CDF4(12620, 19484, 24908)}, + {CDF4(9290, 16553, 22802)}, {CDF4(6668, 14288, 20004)}, + {CDF4(27704, 31055, 31949)}, {CDF4(24709, 29978, 31788)}, + {CDF4(21668, 29264, 31657)}, {CDF4(18295, 26968, 30074)}, + {CDF4(16399, 24422, 29313)}, {CDF4(14347, 23026, 28104)}, + {CDF4(12370, 19806, 24477)} + } + }, + { + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)} + } + } + } +}; + +static const RK_U16 +av1_default_coeff_base_multi_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_SIG_COEF_CONTEXTS] [AV1_CDF_SIZE(AV1_NUM_BASE_LEVELS + 2) + 1] = { + { + { + { + {CDF4(4034, 8930, 12727)}, {CDF4(18082, 29741, 31877)}, + {CDF4(12596, 26124, 30493)}, {CDF4(9446, 21118, 27005)}, + {CDF4(6308, 15141, 21279)}, {CDF4(2463, 6357, 9783)}, + {CDF4(20667, 30546, 31929)}, {CDF4(13043, 26123, 30134)}, + {CDF4(8151, 18757, 24778)}, {CDF4(5255, 12839, 18632)}, + {CDF4(2820, 7206, 11161)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(15736, 27553, 30604)}, + {CDF4(11210, 23794, 28787)}, {CDF4(5947, 13874, 19701)}, + {CDF4(4215, 9323, 13891)}, {CDF4(2833, 6462, 10059)}, + {CDF4(19605, 30393, 31582)}, {CDF4(13523, 26252, 30248)}, + {CDF4(8446, 18622, 24512)}, {CDF4(3818, 10343, 15974)}, + {CDF4(1481, 4117, 6796)}, {CDF4(22649, 31302, 32190)}, + {CDF4(14829, 27127, 30449)}, {CDF4(8313, 17702, 23304)}, + {CDF4(3022, 8301, 12786)}, {CDF4(1536, 4412, 7184)}, + {CDF4(22354, 29774, 31372)}, {CDF4(14723, 25472, 29214)}, + {CDF4(6673, 13745, 18662)}, {CDF4(2068, 5766, 9322)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(6302, 16444, 21761)}, {CDF4(23040, 31538, 32475)}, + {CDF4(15196, 28452, 31496)}, {CDF4(10020, 22946, 28514)}, + {CDF4(6533, 16862, 23501)}, {CDF4(3538, 9816, 15076)}, + {CDF4(24444, 31875, 32525)}, {CDF4(15881, 28924, 31635)}, + {CDF4(9922, 22873, 28466)}, {CDF4(6527, 16966, 23691)}, + {CDF4(4114, 11303, 17220)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(20201, 30770, 32209)}, + {CDF4(14754, 28071, 31258)}, {CDF4(8378, 20186, 26517)}, + {CDF4(5916, 15299, 21978)}, {CDF4(4268, 11583, 17901)}, + {CDF4(24361, 32025, 32581)}, {CDF4(18673, 30105, 31943)}, + {CDF4(10196, 22244, 27576)}, {CDF4(5495, 14349, 20417)}, + {CDF4(2676, 7415, 11498)}, {CDF4(24678, 31958, 32585)}, + {CDF4(18629, 29906, 31831)}, {CDF4(9364, 20724, 26315)}, + {CDF4(4641, 12318, 18094)}, {CDF4(2758, 7387, 11579)}, + {CDF4(25433, 31842, 32469)}, {CDF4(18795, 29289, 31411)}, + {CDF4(7644, 17584, 23592)}, {CDF4(3408, 9014, 15047)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(4536, 10072, 14001)}, {CDF4(25459, 31416, 32206)}, + {CDF4(16605, 28048, 30818)}, {CDF4(11008, 22857, 27719)}, + {CDF4(6915, 16268, 22315)}, {CDF4(2625, 6812, 10537)}, + {CDF4(24257, 31788, 32499)}, {CDF4(16880, 29454, 31879)}, + {CDF4(11958, 25054, 29778)}, {CDF4(7916, 18718, 25084)}, + {CDF4(3383, 8777, 13446)}, {CDF4(22720, 31603, 32393)}, + {CDF4(14960, 28125, 31335)}, {CDF4(9731, 22210, 27928)}, + {CDF4(6304, 15832, 22277)}, {CDF4(2910, 7818, 12166)}, + {CDF4(20375, 30627, 32131)}, {CDF4(13904, 27284, 30887)}, + {CDF4(9368, 21558, 27144)}, {CDF4(5937, 14966, 21119)}, + {CDF4(2667, 7225, 11319)}, {CDF4(23970, 31470, 32378)}, + {CDF4(17173, 29734, 32018)}, {CDF4(12795, 25441, 29965)}, + {CDF4(8981, 19680, 25893)}, {CDF4(4728, 11372, 16902)}, + {CDF4(24287, 31797, 32439)}, {CDF4(16703, 29145, 31696)}, + {CDF4(10833, 23554, 28725)}, {CDF4(6468, 16566, 23057)}, + {CDF4(2415, 6562, 10278)}, {CDF4(26610, 32395, 32659)}, + {CDF4(18590, 30498, 32117)}, {CDF4(12420, 25756, 29950)}, + {CDF4(7639, 18746, 24710)}, {CDF4(3001, 8086, 12347)}, + {CDF4(25076, 32064, 32580)}, {CDF4(17946, 30128, 32028)}, + {CDF4(12024, 24985, 29378)}, {CDF4(7517, 18390, 24304)}, + {CDF4(3243, 8781, 13331)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(6037, 16771, 21957)}, {CDF4(24774, 31704, 32426)}, + {CDF4(16830, 28589, 31056)}, {CDF4(10602, 22828, 27760)}, + {CDF4(6733, 16829, 23071)}, {CDF4(3250, 8914, 13556)}, + {CDF4(25582, 32220, 32668)}, {CDF4(18659, 30342, 32223)}, + {CDF4(12546, 26149, 30515)}, {CDF4(8420, 20451, 26801)}, + {CDF4(4636, 12420, 18344)}, {CDF4(27581, 32362, 32639)}, + {CDF4(18987, 30083, 31978)}, {CDF4(11327, 24248, 29084)}, + {CDF4(7264, 17719, 24120)}, {CDF4(3995, 10768, 16169)}, + {CDF4(25893, 31831, 32487)}, {CDF4(16577, 28587, 31379)}, + {CDF4(10189, 22748, 28182)}, {CDF4(6832, 17094, 23556)}, + {CDF4(3708, 10110, 15334)}, {CDF4(25904, 32282, 32656)}, + {CDF4(19721, 30792, 32276)}, {CDF4(12819, 26243, 30411)}, + {CDF4(8572, 20614, 26891)}, {CDF4(5364, 14059, 20467)}, + {CDF4(26580, 32438, 32677)}, {CDF4(20852, 31225, 32340)}, + {CDF4(12435, 25700, 29967)}, {CDF4(8691, 20825, 26976)}, + {CDF4(4446, 12209, 17269)}, {CDF4(27350, 32429, 32696)}, + {CDF4(21372, 30977, 32272)}, {CDF4(12673, 25270, 29853)}, + {CDF4(9208, 20925, 26640)}, {CDF4(5018, 13351, 18732)}, + {CDF4(27351, 32479, 32713)}, {CDF4(21398, 31209, 32387)}, + {CDF4(12162, 25047, 29842)}, {CDF4(7896, 18691, 25319)}, + {CDF4(4670, 12882, 18881)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(5487, 10460, 13708)}, {CDF4(21597, 28303, 30674)}, + {CDF4(11037, 21953, 26476)}, {CDF4(8147, 17962, 22952)}, + {CDF4(5242, 13061, 18532)}, {CDF4(1889, 5208, 8182)}, + {CDF4(26774, 32133, 32590)}, {CDF4(17844, 29564, 31767)}, + {CDF4(11690, 24438, 29171)}, {CDF4(7542, 18215, 24459)}, + {CDF4(2993, 8050, 12319)}, {CDF4(28023, 32328, 32591)}, + {CDF4(18651, 30126, 31954)}, {CDF4(12164, 25146, 29589)}, + {CDF4(7762, 18530, 24771)}, {CDF4(3492, 9183, 13920)}, + {CDF4(27591, 32008, 32491)}, {CDF4(17149, 28853, 31510)}, + {CDF4(11485, 24003, 28860)}, {CDF4(7697, 18086, 24210)}, + {CDF4(3075, 7999, 12218)}, {CDF4(28268, 32482, 32654)}, + {CDF4(19631, 31051, 32404)}, {CDF4(13860, 27260, 31020)}, + {CDF4(9605, 21613, 27594)}, {CDF4(4876, 12162, 17908)}, + {CDF4(27248, 32316, 32576)}, {CDF4(18955, 30457, 32075)}, + {CDF4(11824, 23997, 28795)}, {CDF4(7346, 18196, 24647)}, + {CDF4(3403, 9247, 14111)}, {CDF4(29711, 32655, 32735)}, + {CDF4(21169, 31394, 32417)}, {CDF4(13487, 27198, 30957)}, + {CDF4(8828, 21683, 27614)}, {CDF4(4270, 11451, 17038)}, + {CDF4(28708, 32578, 32731)}, {CDF4(20120, 31241, 32482)}, + {CDF4(13692, 27550, 31321)}, {CDF4(9418, 22514, 28439)}, + {CDF4(4999, 13283, 19462)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(5673, 14302, 19711)}, {CDF4(26251, 30701, 31834)}, + {CDF4(12782, 23783, 27803)}, {CDF4(9127, 20657, 25808)}, + {CDF4(6368, 16208, 21462)}, {CDF4(2465, 7177, 10822)}, + {CDF4(29961, 32563, 32719)}, {CDF4(18318, 29891, 31949)}, + {CDF4(11361, 24514, 29357)}, {CDF4(7900, 19603, 25607)}, + {CDF4(4002, 10590, 15546)}, {CDF4(29637, 32310, 32595)}, + {CDF4(18296, 29913, 31809)}, {CDF4(10144, 21515, 26871)}, + {CDF4(5358, 14322, 20394)}, {CDF4(3067, 8362, 13346)}, + {CDF4(28652, 32470, 32676)}, {CDF4(17538, 30771, 32209)}, + {CDF4(13924, 26882, 30494)}, {CDF4(10496, 22837, 27869)}, + {CDF4(7236, 16396, 21621)}, {CDF4(30743, 32687, 32746)}, + {CDF4(23006, 31676, 32489)}, {CDF4(14494, 27828, 31120)}, + {CDF4(10174, 22801, 28352)}, {CDF4(6242, 15281, 21043)}, + {CDF4(25817, 32243, 32720)}, {CDF4(18618, 31367, 32325)}, + {CDF4(13997, 28318, 31878)}, {CDF4(12255, 26534, 31383)}, + {CDF4(9561, 21588, 28450)}, {CDF4(28188, 32635, 32724)}, + {CDF4(22060, 32365, 32728)}, {CDF4(18102, 30690, 32528)}, + {CDF4(14196, 28864, 31999)}, {CDF4(12262, 25792, 30865)}, + {CDF4(24176, 32109, 32628)}, {CDF4(18280, 29681, 31963)}, + {CDF4(10205, 23703, 29664)}, {CDF4(7889, 20025, 27676)}, + {CDF4(6060, 16743, 23970)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(5141, 7096, 8260)}, {CDF4(27186, 29022, 29789)}, + {CDF4(6668, 12568, 15682)}, {CDF4(2172, 6181, 8638)}, + {CDF4(1126, 3379, 4531)}, {CDF4(443, 1361, 2254)}, + {CDF4(26083, 31153, 32436)}, {CDF4(13486, 24603, 28483)}, + {CDF4(6508, 14840, 19910)}, {CDF4(3386, 8800, 13286)}, + {CDF4(1530, 4322, 7054)}, {CDF4(29639, 32080, 32548)}, + {CDF4(15897, 27552, 30290)}, {CDF4(8588, 20047, 25383)}, + {CDF4(4889, 13339, 19269)}, {CDF4(2240, 6871, 10498)}, + {CDF4(28165, 32197, 32517)}, {CDF4(20735, 30427, 31568)}, + {CDF4(14325, 24671, 27692)}, {CDF4(5119, 12554, 17805)}, + {CDF4(1810, 5441, 8261)}, {CDF4(31212, 32724, 32748)}, + {CDF4(23352, 31766, 32545)}, {CDF4(14669, 27570, 31059)}, + {CDF4(8492, 20894, 27272)}, {CDF4(3644, 10194, 15204)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(2461, 7013, 9371)}, {CDF4(24749, 29600, 30986)}, + {CDF4(9466, 19037, 22417)}, {CDF4(3584, 9280, 14400)}, + {CDF4(1505, 3929, 5433)}, {CDF4(677, 1500, 2736)}, + {CDF4(23987, 30702, 32117)}, {CDF4(13554, 24571, 29263)}, + {CDF4(6211, 14556, 21155)}, {CDF4(3135, 10972, 15625)}, + {CDF4(2435, 7127, 11427)}, {CDF4(31300, 32532, 32550)}, + {CDF4(14757, 30365, 31954)}, {CDF4(4405, 11612, 18553)}, + {CDF4(580, 4132, 7322)}, {CDF4(1695, 10169, 14124)}, + {CDF4(30008, 32282, 32591)}, {CDF4(19244, 30108, 31748)}, + {CDF4(11180, 24158, 29555)}, {CDF4(5650, 14972, 19209)}, + {CDF4(2114, 5109, 8456)}, {CDF4(31856, 32716, 32748)}, + {CDF4(23012, 31664, 32572)}, {CDF4(13694, 26656, 30636)}, + {CDF4(8142, 19508, 26093)}, {CDF4(4253, 10955, 16724)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(601, 983, 1311)}, {CDF4(18725, 23406, 28087)}, + {CDF4(5461, 8192, 10923)}, {CDF4(3781, 15124, 21425)}, + {CDF4(2587, 7761, 12072)}, {CDF4(106, 458, 810)}, + {CDF4(22282, 29710, 31894)}, {CDF4(8508, 20926, 25984)}, + {CDF4(3726, 12713, 18083)}, {CDF4(1620, 7112, 10893)}, + {CDF4(729, 2236, 3495)}, {CDF4(30163, 32474, 32684)}, + {CDF4(18304, 30464, 32000)}, {CDF4(11443, 26526, 29647)}, + {CDF4(6007, 15292, 21299)}, {CDF4(2234, 6703, 8937)}, + {CDF4(30954, 32177, 32571)}, {CDF4(17363, 29562, 31076)}, + {CDF4(9686, 22464, 27410)}, {CDF4(8192, 16384, 21390)}, + {CDF4(1755, 8046, 11264)}, {CDF4(31168, 32734, 32748)}, + {CDF4(22486, 31441, 32471)}, {CDF4(12833, 25627, 29738)}, + {CDF4(6980, 17379, 23122)}, {CDF4(3111, 8887, 13479)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + {CDF4(6041, 11854, 15927)}, {CDF4(20326, 30905, 32251)}, + {CDF4(14164, 26831, 30725)}, {CDF4(9760, 20647, 26585)}, + {CDF4(6416, 14953, 21219)}, {CDF4(2966, 7151, 10891)}, + {CDF4(23567, 31374, 32254)}, {CDF4(14978, 27416, 30946)}, + {CDF4(9434, 20225, 26254)}, {CDF4(6658, 14558, 20535)}, + {CDF4(3916, 8677, 12989)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(18088, 29545, 31587)}, + {CDF4(13062, 25843, 30073)}, {CDF4(8940, 16827, 22251)}, + {CDF4(7654, 13220, 17973)}, {CDF4(5733, 10316, 14456)}, + {CDF4(22879, 31388, 32114)}, {CDF4(15215, 27993, 30955)}, + {CDF4(9397, 19445, 24978)}, {CDF4(3442, 9813, 15344)}, + {CDF4(1368, 3936, 6532)}, {CDF4(25494, 32033, 32406)}, + {CDF4(16772, 27963, 30718)}, {CDF4(9419, 18165, 23260)}, + {CDF4(2677, 7501, 11797)}, {CDF4(1516, 4344, 7170)}, + {CDF4(26556, 31454, 32101)}, {CDF4(17128, 27035, 30108)}, + {CDF4(8324, 15344, 20249)}, {CDF4(1903, 5696, 9469)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8455, 19003, 24368)}, {CDF4(23563, 32021, 32604)}, + {CDF4(16237, 29446, 31935)}, {CDF4(10724, 23999, 29358)}, + {CDF4(6725, 17528, 24416)}, {CDF4(3927, 10927, 16825)}, + {CDF4(26313, 32288, 32634)}, {CDF4(17430, 30095, 32095)}, + {CDF4(11116, 24606, 29679)}, {CDF4(7195, 18384, 25269)}, + {CDF4(4726, 12852, 19315)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(22822, 31648, 32483)}, + {CDF4(16724, 29633, 31929)}, {CDF4(10261, 23033, 28725)}, + {CDF4(7029, 17840, 24528)}, {CDF4(4867, 13886, 21502)}, + {CDF4(25298, 31892, 32491)}, {CDF4(17809, 29330, 31512)}, + {CDF4(9668, 21329, 26579)}, {CDF4(4774, 12956, 18976)}, + {CDF4(2322, 7030, 11540)}, {CDF4(25472, 31920, 32543)}, + {CDF4(17957, 29387, 31632)}, {CDF4(9196, 20593, 26400)}, + {CDF4(4680, 12705, 19202)}, {CDF4(2917, 8456, 13436)}, + {CDF4(26471, 32059, 32574)}, {CDF4(18458, 29783, 31909)}, + {CDF4(8400, 19464, 25956)}, {CDF4(3812, 10973, 17206)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(6779, 13743, 17678)}, {CDF4(24806, 31797, 32457)}, + {CDF4(17616, 29047, 31372)}, {CDF4(11063, 23175, 28003)}, + {CDF4(6521, 16110, 22324)}, {CDF4(2764, 7504, 11654)}, + {CDF4(25266, 32367, 32637)}, {CDF4(19054, 30553, 32175)}, + {CDF4(12139, 25212, 29807)}, {CDF4(7311, 18162, 24704)}, + {CDF4(3397, 9164, 14074)}, {CDF4(25988, 32208, 32522)}, + {CDF4(16253, 28912, 31526)}, {CDF4(9151, 21387, 27372)}, + {CDF4(5688, 14915, 21496)}, {CDF4(2717, 7627, 12004)}, + {CDF4(23144, 31855, 32443)}, {CDF4(16070, 28491, 31325)}, + {CDF4(8702, 20467, 26517)}, {CDF4(5243, 13956, 20367)}, + {CDF4(2621, 7335, 11567)}, {CDF4(26636, 32340, 32630)}, + {CDF4(19990, 31050, 32341)}, {CDF4(13243, 26105, 30315)}, + {CDF4(8588, 19521, 25918)}, {CDF4(4717, 11585, 17304)}, + {CDF4(25844, 32292, 32582)}, {CDF4(19090, 30635, 32097)}, + {CDF4(11963, 24546, 28939)}, {CDF4(6218, 16087, 22354)}, + {CDF4(2340, 6608, 10426)}, {CDF4(28046, 32576, 32694)}, + {CDF4(21178, 31313, 32296)}, {CDF4(13486, 26184, 29870)}, + {CDF4(7149, 17871, 23723)}, {CDF4(2833, 7958, 12259)}, + {CDF4(27710, 32528, 32686)}, {CDF4(20674, 31076, 32268)}, + {CDF4(12413, 24955, 29243)}, {CDF4(6676, 16927, 23097)}, + {CDF4(2966, 8333, 12919)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8639, 19339, 24429)}, {CDF4(24404, 31837, 32525)}, + {CDF4(16997, 29425, 31784)}, {CDF4(11253, 24234, 29149)}, + {CDF4(6751, 17394, 24028)}, {CDF4(3490, 9830, 15191)}, + {CDF4(26283, 32471, 32714)}, {CDF4(19599, 31168, 32442)}, + {CDF4(13146, 26954, 30893)}, {CDF4(8214, 20588, 26890)}, + {CDF4(4699, 13081, 19300)}, {CDF4(28212, 32458, 32669)}, + {CDF4(18594, 30316, 32100)}, {CDF4(11219, 24408, 29234)}, + {CDF4(6865, 17656, 24149)}, {CDF4(3678, 10362, 16006)}, + {CDF4(25825, 32136, 32616)}, {CDF4(17313, 29853, 32021)}, + {CDF4(11197, 24471, 29472)}, {CDF4(6947, 17781, 24405)}, + {CDF4(3768, 10660, 16261)}, {CDF4(27352, 32500, 32706)}, + {CDF4(20850, 31468, 32469)}, {CDF4(14021, 27707, 31133)}, + {CDF4(8964, 21748, 27838)}, {CDF4(5437, 14665, 21187)}, + {CDF4(26304, 32492, 32698)}, {CDF4(20409, 31380, 32385)}, + {CDF4(13682, 27222, 30632)}, {CDF4(8974, 21236, 26685)}, + {CDF4(4234, 11665, 16934)}, {CDF4(26273, 32357, 32711)}, + {CDF4(20672, 31242, 32441)}, {CDF4(14172, 27254, 30902)}, + {CDF4(9870, 21898, 27275)}, {CDF4(5164, 13506, 19270)}, + {CDF4(26725, 32459, 32728)}, {CDF4(20991, 31442, 32527)}, + {CDF4(13071, 26434, 30811)}, {CDF4(8184, 20090, 26742)}, + {CDF4(4803, 13255, 19895)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(7555, 14942, 18501)}, {CDF4(24410, 31178, 32287)}, + {CDF4(14394, 26738, 30253)}, {CDF4(8413, 19554, 25195)}, + {CDF4(4766, 12924, 18785)}, {CDF4(2029, 5806, 9207)}, + {CDF4(26776, 32364, 32663)}, {CDF4(18732, 29967, 31931)}, + {CDF4(11005, 23786, 28852)}, {CDF4(6466, 16909, 23510)}, + {CDF4(3044, 8638, 13419)}, {CDF4(29208, 32582, 32704)}, + {CDF4(20068, 30857, 32208)}, {CDF4(12003, 25085, 29595)}, + {CDF4(6947, 17750, 24189)}, {CDF4(3245, 9103, 14007)}, + {CDF4(27359, 32465, 32669)}, {CDF4(19421, 30614, 32174)}, + {CDF4(11915, 25010, 29579)}, {CDF4(6950, 17676, 24074)}, + {CDF4(3007, 8473, 13096)}, {CDF4(29002, 32676, 32735)}, + {CDF4(22102, 31849, 32576)}, {CDF4(14408, 28009, 31405)}, + {CDF4(9027, 21679, 27931)}, {CDF4(4694, 12678, 18748)}, + {CDF4(28216, 32528, 32682)}, {CDF4(20849, 31264, 32318)}, + {CDF4(12756, 25815, 29751)}, {CDF4(7565, 18801, 24923)}, + {CDF4(3509, 9533, 14477)}, {CDF4(30133, 32687, 32739)}, + {CDF4(23063, 31910, 32515)}, {CDF4(14588, 28051, 31132)}, + {CDF4(9085, 21649, 27457)}, {CDF4(4261, 11654, 17264)}, + {CDF4(29518, 32691, 32748)}, {CDF4(22451, 31959, 32613)}, + {CDF4(14864, 28722, 31700)}, {CDF4(9695, 22964, 28716)}, + {CDF4(4932, 13358, 19502)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(6465, 16958, 21688)}, {CDF4(25199, 31514, 32360)}, + {CDF4(14774, 27149, 30607)}, {CDF4(9257, 21438, 26972)}, + {CDF4(5723, 15183, 21882)}, {CDF4(3150, 8879, 13731)}, + {CDF4(26989, 32262, 32682)}, {CDF4(17396, 29937, 32085)}, + {CDF4(11387, 24901, 29784)}, {CDF4(7289, 18821, 25548)}, + {CDF4(3734, 10577, 16086)}, {CDF4(29728, 32501, 32695)}, + {CDF4(17431, 29701, 31903)}, {CDF4(9921, 22826, 28300)}, + {CDF4(5896, 15434, 22068)}, {CDF4(3430, 9646, 14757)}, + {CDF4(28614, 32511, 32705)}, {CDF4(19364, 30638, 32263)}, + {CDF4(13129, 26254, 30402)}, {CDF4(8754, 20484, 26440)}, + {CDF4(4378, 11607, 17110)}, {CDF4(30292, 32671, 32744)}, + {CDF4(21780, 31603, 32501)}, {CDF4(14314, 27829, 31291)}, + {CDF4(9611, 22327, 28263)}, {CDF4(4890, 13087, 19065)}, + {CDF4(25862, 32567, 32733)}, {CDF4(20794, 32050, 32567)}, + {CDF4(17243, 30625, 32254)}, {CDF4(13283, 27628, 31474)}, + {CDF4(9669, 22532, 28918)}, {CDF4(27435, 32697, 32748)}, + {CDF4(24922, 32390, 32714)}, {CDF4(21449, 31504, 32536)}, + {CDF4(16392, 29729, 31832)}, {CDF4(11692, 24884, 29076)}, + {CDF4(24193, 32290, 32735)}, {CDF4(18909, 31104, 32563)}, + {CDF4(12236, 26841, 31403)}, {CDF4(8171, 21840, 29082)}, + {CDF4(7224, 17280, 25275)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(3078, 6839, 9890)}, {CDF4(13837, 20450, 24479)}, + {CDF4(5914, 14222, 19328)}, {CDF4(3866, 10267, 14762)}, + {CDF4(2612, 7208, 11042)}, {CDF4(1067, 2991, 4776)}, + {CDF4(25817, 31646, 32529)}, {CDF4(13708, 26338, 30385)}, + {CDF4(7328, 18585, 24870)}, {CDF4(4691, 13080, 19276)}, + {CDF4(1825, 5253, 8352)}, {CDF4(29386, 32315, 32624)}, + {CDF4(17160, 29001, 31360)}, {CDF4(9602, 21862, 27396)}, + {CDF4(5915, 15772, 22148)}, {CDF4(2786, 7779, 12047)}, + {CDF4(29246, 32450, 32663)}, {CDF4(18696, 29929, 31818)}, + {CDF4(10510, 23369, 28560)}, {CDF4(6229, 16499, 23125)}, + {CDF4(2608, 7448, 11705)}, {CDF4(30753, 32710, 32748)}, + {CDF4(21638, 31487, 32503)}, {CDF4(12937, 26854, 30870)}, + {CDF4(8182, 20596, 26970)}, {CDF4(3637, 10269, 15497)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(5244, 12150, 16906)}, {CDF4(20486, 26858, 29701)}, + {CDF4(7756, 18317, 23735)}, {CDF4(3452, 9256, 13146)}, + {CDF4(2020, 5206, 8229)}, {CDF4(1801, 4993, 7903)}, + {CDF4(27051, 31858, 32531)}, {CDF4(15988, 27531, 30619)}, + {CDF4(9188, 21484, 26719)}, {CDF4(6273, 17186, 23800)}, + {CDF4(3108, 9355, 14764)}, {CDF4(31076, 32520, 32680)}, + {CDF4(18119, 30037, 31850)}, {CDF4(10244, 22969, 27472)}, + {CDF4(4692, 14077, 19273)}, {CDF4(3694, 11677, 17556)}, + {CDF4(30060, 32581, 32720)}, {CDF4(21011, 30775, 32120)}, + {CDF4(11931, 24820, 29289)}, {CDF4(7119, 17662, 24356)}, + {CDF4(3833, 10706, 16304)}, {CDF4(31954, 32731, 32748)}, + {CDF4(23913, 31724, 32489)}, {CDF4(15520, 28060, 31286)}, + {CDF4(11517, 23008, 28571)}, {CDF4(6193, 14508, 20629)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(1035, 2807, 4156)}, {CDF4(13162, 18138, 20939)}, + {CDF4(2696, 6633, 8755)}, {CDF4(1373, 4161, 6853)}, + {CDF4(1099, 2746, 4716)}, {CDF4(340, 1021, 1599)}, + {CDF4(22826, 30419, 32135)}, {CDF4(10395, 21762, 26942)}, + {CDF4(4726, 12407, 17361)}, {CDF4(2447, 7080, 10593)}, + {CDF4(1227, 3717, 6011)}, {CDF4(28156, 31424, 31934)}, + {CDF4(16915, 27754, 30373)}, {CDF4(9148, 20990, 26431)}, + {CDF4(5950, 15515, 21148)}, {CDF4(2492, 7327, 11526)}, + {CDF4(30602, 32477, 32670)}, {CDF4(20026, 29955, 31568)}, + {CDF4(11220, 23628, 28105)}, {CDF4(6652, 17019, 22973)}, + {CDF4(3064, 8536, 13043)}, {CDF4(31769, 32724, 32748)}, + {CDF4(22230, 30887, 32373)}, {CDF4(12234, 25079, 29731)}, + {CDF4(7326, 18816, 25353)}, {CDF4(3933, 10907, 16616)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + {CDF4(8896, 16227, 20630)}, {CDF4(23629, 31782, 32527)}, + {CDF4(15173, 27755, 31321)}, {CDF4(10158, 21233, 27382)}, + {CDF4(6420, 14857, 21558)}, {CDF4(3269, 8155, 12646)}, + {CDF4(24835, 32009, 32496)}, {CDF4(16509, 28421, 31579)}, + {CDF4(10957, 21514, 27418)}, {CDF4(7881, 15930, 22096)}, + {CDF4(5388, 10960, 15918)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(20745, 30773, 32093)}, + {CDF4(15200, 27221, 30861)}, {CDF4(13032, 20873, 25667)}, + {CDF4(12285, 18663, 23494)}, {CDF4(11563, 17481, 21489)}, + {CDF4(26260, 31982, 32320)}, {CDF4(15397, 28083, 31100)}, + {CDF4(9742, 19217, 24824)}, {CDF4(3261, 9629, 15362)}, + {CDF4(1480, 4322, 7499)}, {CDF4(27599, 32256, 32460)}, + {CDF4(16857, 27659, 30774)}, {CDF4(9551, 18290, 23748)}, + {CDF4(3052, 8933, 14103)}, {CDF4(2021, 5910, 9787)}, + {CDF4(29005, 32015, 32392)}, {CDF4(17677, 27694, 30863)}, + {CDF4(9204, 17356, 23219)}, {CDF4(2403, 7516, 12814)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(10808, 22056, 26896)}, {CDF4(25739, 32313, 32676)}, + {CDF4(17288, 30203, 32221)}, {CDF4(11359, 24878, 29896)}, + {CDF4(6949, 17767, 24893)}, {CDF4(4287, 11796, 18071)}, + {CDF4(27880, 32521, 32705)}, {CDF4(19038, 31004, 32414)}, + {CDF4(12564, 26345, 30768)}, {CDF4(8269, 19947, 26779)}, + {CDF4(5674, 14657, 21674)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(25742, 32319, 32671)}, + {CDF4(19557, 31164, 32454)}, {CDF4(13381, 26381, 30755)}, + {CDF4(10101, 21466, 26722)}, {CDF4(9209, 19650, 26825)}, + {CDF4(27107, 31917, 32432)}, {CDF4(18056, 28893, 31203)}, + {CDF4(10200, 21434, 26764)}, {CDF4(4660, 12913, 19502)}, + {CDF4(2368, 6930, 12504)}, {CDF4(26960, 32158, 32613)}, + {CDF4(18628, 30005, 32031)}, {CDF4(10233, 22442, 28232)}, + {CDF4(5471, 14630, 21516)}, {CDF4(3235, 10767, 17109)}, + {CDF4(27696, 32440, 32692)}, {CDF4(20032, 31167, 32438)}, + {CDF4(8700, 21341, 28442)}, {CDF4(5662, 14831, 21795)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(9704, 17294, 21132)}, {CDF4(26762, 32278, 32633)}, + {CDF4(18382, 29620, 31819)}, {CDF4(10891, 23475, 28723)}, + {CDF4(6358, 16583, 23309)}, {CDF4(3248, 9118, 14141)}, + {CDF4(27204, 32573, 32699)}, {CDF4(19818, 30824, 32329)}, + {CDF4(11772, 25120, 30041)}, {CDF4(6995, 18033, 25039)}, + {CDF4(3752, 10442, 16098)}, {CDF4(27222, 32256, 32559)}, + {CDF4(15356, 28399, 31475)}, {CDF4(8821, 20635, 27057)}, + {CDF4(5511, 14404, 21239)}, {CDF4(2935, 8222, 13051)}, + {CDF4(24875, 32120, 32529)}, {CDF4(15233, 28265, 31445)}, + {CDF4(8605, 20570, 26932)}, {CDF4(5431, 14413, 21196)}, + {CDF4(2994, 8341, 13223)}, {CDF4(28201, 32604, 32700)}, + {CDF4(21041, 31446, 32456)}, {CDF4(13221, 26213, 30475)}, + {CDF4(8255, 19385, 26037)}, {CDF4(4930, 12585, 18830)}, + {CDF4(28768, 32448, 32627)}, {CDF4(19705, 30561, 32021)}, + {CDF4(11572, 23589, 28220)}, {CDF4(5532, 15034, 21446)}, + {CDF4(2460, 7150, 11456)}, {CDF4(29874, 32619, 32699)}, + {CDF4(21621, 31071, 32201)}, {CDF4(12511, 24747, 28992)}, + {CDF4(6281, 16395, 22748)}, {CDF4(3246, 9278, 14497)}, + {CDF4(29715, 32625, 32712)}, {CDF4(20958, 31011, 32283)}, + {CDF4(11233, 23671, 28806)}, {CDF4(6012, 16128, 22868)}, + {CDF4(3427, 9851, 15414)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(11016, 22111, 26794)}, {CDF4(25946, 32357, 32677)}, + {CDF4(17890, 30452, 32252)}, {CDF4(11678, 25142, 29816)}, + {CDF4(6720, 17534, 24584)}, {CDF4(4230, 11665, 17820)}, + {CDF4(28400, 32623, 32747)}, {CDF4(21164, 31668, 32575)}, + {CDF4(13572, 27388, 31182)}, {CDF4(8234, 20750, 27358)}, + {CDF4(5065, 14055, 20897)}, {CDF4(28981, 32547, 32705)}, + {CDF4(18681, 30543, 32239)}, {CDF4(10919, 24075, 29286)}, + {CDF4(6431, 17199, 24077)}, {CDF4(3819, 10464, 16618)}, + {CDF4(26870, 32467, 32693)}, {CDF4(19041, 30831, 32347)}, + {CDF4(11794, 25211, 30016)}, {CDF4(6888, 18019, 24970)}, + {CDF4(4370, 12363, 18992)}, {CDF4(29578, 32670, 32744)}, + {CDF4(23159, 32007, 32613)}, {CDF4(15315, 28669, 31676)}, + {CDF4(9298, 22607, 28782)}, {CDF4(6144, 15913, 22968)}, + {CDF4(28110, 32499, 32669)}, {CDF4(21574, 30937, 32015)}, + {CDF4(12759, 24818, 28727)}, {CDF4(6545, 16761, 23042)}, + {CDF4(3649, 10597, 16833)}, {CDF4(28163, 32552, 32728)}, + {CDF4(22101, 31469, 32464)}, {CDF4(13160, 25472, 30143)}, + {CDF4(7303, 18684, 25468)}, {CDF4(5241, 13975, 20955)}, + {CDF4(28400, 32631, 32744)}, {CDF4(22104, 31793, 32603)}, + {CDF4(13557, 26571, 30846)}, {CDF4(7749, 19861, 26675)}, + {CDF4(4873, 14030, 21234)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(9800, 17635, 21073)}, {CDF4(26153, 31885, 32527)}, + {CDF4(15038, 27852, 31006)}, {CDF4(8718, 20564, 26486)}, + {CDF4(5128, 14076, 20514)}, {CDF4(2636, 7566, 11925)}, + {CDF4(27551, 32504, 32701)}, {CDF4(18310, 30054, 32100)}, + {CDF4(10211, 23420, 29082)}, {CDF4(6222, 16876, 23916)}, + {CDF4(3462, 9954, 15498)}, {CDF4(29991, 32633, 32721)}, + {CDF4(19883, 30751, 32201)}, {CDF4(11141, 24184, 29285)}, + {CDF4(6420, 16940, 23774)}, {CDF4(3392, 9753, 15118)}, + {CDF4(28465, 32616, 32712)}, {CDF4(19850, 30702, 32244)}, + {CDF4(10983, 24024, 29223)}, {CDF4(6294, 16770, 23582)}, + {CDF4(3244, 9283, 14509)}, {CDF4(30023, 32717, 32748)}, + {CDF4(22940, 32032, 32626)}, {CDF4(14282, 27928, 31473)}, + {CDF4(8562, 21327, 27914)}, {CDF4(4846, 13393, 19919)}, + {CDF4(29981, 32590, 32695)}, {CDF4(20465, 30963, 32166)}, + {CDF4(11479, 23579, 28195)}, {CDF4(5916, 15648, 22073)}, + {CDF4(3031, 8605, 13398)}, {CDF4(31146, 32691, 32739)}, + {CDF4(23106, 31724, 32444)}, {CDF4(13783, 26738, 30439)}, + {CDF4(7852, 19468, 25807)}, {CDF4(3860, 11124, 16853)}, + {CDF4(31014, 32724, 32748)}, {CDF4(23629, 32109, 32628)}, + {CDF4(14747, 28115, 31403)}, {CDF4(8545, 21242, 27478)}, + {CDF4(4574, 12781, 19067)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(9185, 19694, 24688)}, {CDF4(26081, 31985, 32621)}, + {CDF4(16015, 29000, 31787)}, {CDF4(10542, 23690, 29206)}, + {CDF4(6732, 17945, 24677)}, {CDF4(3916, 11039, 16722)}, + {CDF4(28224, 32566, 32744)}, {CDF4(19100, 31138, 32485)}, + {CDF4(12528, 26620, 30879)}, {CDF4(7741, 20277, 26885)}, + {CDF4(4566, 12845, 18990)}, {CDF4(29933, 32593, 32718)}, + {CDF4(17670, 30333, 32155)}, {CDF4(10385, 23600, 28909)}, + {CDF4(6243, 16236, 22407)}, {CDF4(3976, 10389, 16017)}, + {CDF4(28377, 32561, 32738)}, {CDF4(19366, 31175, 32482)}, + {CDF4(13327, 27175, 31094)}, {CDF4(8258, 20769, 27143)}, + {CDF4(4703, 13198, 19527)}, {CDF4(31086, 32706, 32748)}, + {CDF4(22853, 31902, 32583)}, {CDF4(14759, 28186, 31419)}, + {CDF4(9284, 22382, 28348)}, {CDF4(5585, 15192, 21868)}, + {CDF4(28291, 32652, 32746)}, {CDF4(19849, 32107, 32571)}, + {CDF4(14834, 26818, 29214)}, {CDF4(10306, 22594, 28672)}, + {CDF4(6615, 17384, 23384)}, {CDF4(28947, 32604, 32745)}, + {CDF4(25625, 32289, 32646)}, {CDF4(18758, 28672, 31403)}, + {CDF4(10017, 23430, 28523)}, {CDF4(6862, 15269, 22131)}, + {CDF4(23933, 32509, 32739)}, {CDF4(19927, 31495, 32631)}, + {CDF4(11903, 26023, 30621)}, {CDF4(7026, 20094, 27252)}, + {CDF4(5998, 18106, 24437)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(4456, 11274, 15533)}, {CDF4(21219, 29079, 31616)}, + {CDF4(11173, 23774, 28567)}, {CDF4(7282, 18293, 24263)}, + {CDF4(4890, 13286, 19115)}, {CDF4(1890, 5508, 8659)}, + {CDF4(26651, 32136, 32647)}, {CDF4(14630, 28254, 31455)}, + {CDF4(8716, 21287, 27395)}, {CDF4(5615, 15331, 22008)}, + {CDF4(2675, 7700, 12150)}, {CDF4(29954, 32526, 32690)}, + {CDF4(16126, 28982, 31633)}, {CDF4(9030, 21361, 27352)}, + {CDF4(5411, 14793, 21271)}, {CDF4(2943, 8422, 13163)}, + {CDF4(29539, 32601, 32730)}, {CDF4(18125, 30385, 32201)}, + {CDF4(10422, 24090, 29468)}, {CDF4(6468, 17487, 24438)}, + {CDF4(2970, 8653, 13531)}, {CDF4(30912, 32715, 32748)}, + {CDF4(20666, 31373, 32497)}, {CDF4(12509, 26640, 30917)}, + {CDF4(8058, 20629, 27290)}, {CDF4(4231, 12006, 18052)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(10202, 20633, 25484)}, {CDF4(27336, 31445, 32352)}, + {CDF4(12420, 24384, 28552)}, {CDF4(7648, 18115, 23856)}, + {CDF4(5662, 14341, 19902)}, {CDF4(3611, 10328, 15390)}, + {CDF4(30945, 32616, 32736)}, {CDF4(18682, 30505, 32253)}, + {CDF4(11513, 25336, 30203)}, {CDF4(7449, 19452, 26148)}, + {CDF4(4482, 13051, 18886)}, {CDF4(32022, 32690, 32747)}, + {CDF4(18578, 30501, 32146)}, {CDF4(11249, 23368, 28631)}, + {CDF4(5645, 16958, 22158)}, {CDF4(5009, 11444, 16637)}, + {CDF4(31357, 32710, 32748)}, {CDF4(21552, 31494, 32504)}, + {CDF4(13891, 27677, 31340)}, {CDF4(9051, 22098, 28172)}, + {CDF4(5190, 13377, 19486)}, {CDF4(32364, 32740, 32748)}, + {CDF4(24839, 31907, 32551)}, {CDF4(17160, 28779, 31696)}, + {CDF4(12452, 24137, 29602)}, {CDF4(6165, 15389, 22477)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(2575, 7281, 11077)}, {CDF4(14002, 20866, 25402)}, + {CDF4(6343, 15056, 19658)}, {CDF4(4474, 11858, 17041)}, + {CDF4(2865, 8299, 12534)}, {CDF4(1344, 3949, 6391)}, + {CDF4(24720, 31239, 32459)}, {CDF4(12585, 25356, 29968)}, + {CDF4(7181, 18246, 24444)}, {CDF4(5025, 13667, 19885)}, + {CDF4(2521, 7304, 11605)}, {CDF4(29908, 32252, 32584)}, + {CDF4(17421, 29156, 31575)}, {CDF4(9889, 22188, 27782)}, + {CDF4(5878, 15647, 22123)}, {CDF4(2814, 8665, 13323)}, + {CDF4(30183, 32568, 32713)}, {CDF4(18528, 30195, 32049)}, + {CDF4(10982, 24606, 29657)}, {CDF4(6957, 18165, 25231)}, + {CDF4(3508, 10118, 15468)}, {CDF4(31761, 32736, 32748)}, + {CDF4(21041, 31328, 32546)}, {CDF4(12568, 26732, 31166)}, + {CDF4(8052, 20720, 27733)}, {CDF4(4336, 12192, 18396)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + {CDF4(7062, 16472, 22319)}, {CDF4(24538, 32261, 32674)}, + {CDF4(13675, 28041, 31779)}, {CDF4(8590, 20674, 27631)}, + {CDF4(5685, 14675, 22013)}, {CDF4(3655, 9898, 15731)}, + {CDF4(26493, 32418, 32658)}, {CDF4(16376, 29342, 32090)}, + {CDF4(10594, 22649, 28970)}, {CDF4(8176, 17170, 24303)}, + {CDF4(5605, 12694, 19139)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(23888, 31902, 32542)}, + {CDF4(18612, 29687, 31987)}, {CDF4(16245, 24852, 29249)}, + {CDF4(15765, 22608, 27559)}, {CDF4(19895, 24699, 27510)}, + {CDF4(28401, 32212, 32457)}, {CDF4(15274, 27825, 30980)}, + {CDF4(9364, 18128, 24332)}, {CDF4(2283, 8193, 15082)}, + {CDF4(1228, 3972, 7881)}, {CDF4(29455, 32469, 32620)}, + {CDF4(17981, 28245, 31388)}, {CDF4(10921, 20098, 26240)}, + {CDF4(3743, 11829, 18657)}, {CDF4(2374, 9593, 15715)}, + {CDF4(31068, 32466, 32635)}, {CDF4(20321, 29572, 31971)}, + {CDF4(10771, 20255, 27119)}, {CDF4(2795, 10410, 17361)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(9320, 22102, 27840)}, {CDF4(27057, 32464, 32724)}, + {CDF4(16331, 30268, 32309)}, {CDF4(10319, 23935, 29720)}, + {CDF4(6189, 16448, 24106)}, {CDF4(3589, 10884, 18808)}, + {CDF4(29026, 32624, 32748)}, {CDF4(19226, 31507, 32587)}, + {CDF4(12692, 26921, 31203)}, {CDF4(7049, 19532, 27635)}, + {CDF4(7727, 15669, 23252)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(28056, 32625, 32748)}, + {CDF4(22383, 32075, 32669)}, {CDF4(15417, 27098, 31749)}, + {CDF4(18127, 26493, 27190)}, {CDF4(5461, 16384, 21845)}, + {CDF4(27982, 32091, 32584)}, {CDF4(19045, 29868, 31972)}, + {CDF4(10397, 22266, 27932)}, {CDF4(5990, 13697, 21500)}, + {CDF4(1792, 6912, 15104)}, {CDF4(28198, 32501, 32718)}, + {CDF4(21534, 31521, 32569)}, {CDF4(11109, 25217, 30017)}, + {CDF4(5671, 15124, 26151)}, {CDF4(4681, 14043, 18725)}, + {CDF4(28688, 32580, 32741)}, {CDF4(22576, 32079, 32661)}, + {CDF4(10627, 22141, 28340)}, {CDF4(9362, 14043, 28087)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(7754, 16948, 22142)}, {CDF4(25670, 32330, 32691)}, + {CDF4(15663, 29225, 31994)}, {CDF4(9878, 23288, 29158)}, + {CDF4(6419, 17088, 24336)}, {CDF4(3859, 11003, 17039)}, + {CDF4(27562, 32595, 32725)}, {CDF4(17575, 30588, 32399)}, + {CDF4(10819, 24838, 30309)}, {CDF4(7124, 18686, 25916)}, + {CDF4(4479, 12688, 19340)}, {CDF4(28385, 32476, 32673)}, + {CDF4(15306, 29005, 31938)}, {CDF4(8937, 21615, 28322)}, + {CDF4(5982, 15603, 22786)}, {CDF4(3620, 10267, 16136)}, + {CDF4(27280, 32464, 32667)}, {CDF4(15607, 29160, 32004)}, + {CDF4(9091, 22135, 28740)}, {CDF4(6232, 16632, 24020)}, + {CDF4(4047, 11377, 17672)}, {CDF4(29220, 32630, 32718)}, + {CDF4(19650, 31220, 32462)}, {CDF4(13050, 26312, 30827)}, + {CDF4(9228, 20870, 27468)}, {CDF4(6146, 15149, 21971)}, + {CDF4(30169, 32481, 32623)}, {CDF4(17212, 29311, 31554)}, + {CDF4(9911, 21311, 26882)}, {CDF4(4487, 13314, 20372)}, + {CDF4(2570, 7772, 12889)}, {CDF4(30924, 32613, 32708)}, + {CDF4(19490, 30206, 32107)}, {CDF4(11232, 23998, 29276)}, + {CDF4(6769, 17955, 25035)}, {CDF4(4398, 12623, 19214)}, + {CDF4(30609, 32627, 32722)}, {CDF4(19370, 30582, 32287)}, + {CDF4(10457, 23619, 29409)}, {CDF4(6443, 17637, 24834)}, + {CDF4(4645, 13236, 20106)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8626, 20271, 26216)}, {CDF4(26707, 32406, 32711)}, + {CDF4(16999, 30329, 32286)}, {CDF4(11445, 25123, 30286)}, + {CDF4(6411, 18828, 25601)}, {CDF4(6801, 12458, 20248)}, + {CDF4(29918, 32682, 32748)}, {CDF4(20649, 31739, 32618)}, + {CDF4(12879, 27773, 31581)}, {CDF4(7896, 21751, 28244)}, + {CDF4(5260, 14870, 23698)}, {CDF4(29252, 32593, 32731)}, + {CDF4(17072, 30460, 32294)}, {CDF4(10653, 24143, 29365)}, + {CDF4(6536, 17490, 23983)}, {CDF4(4929, 13170, 20085)}, + {CDF4(28137, 32518, 32715)}, {CDF4(18171, 30784, 32407)}, + {CDF4(11437, 25436, 30459)}, {CDF4(7252, 18534, 26176)}, + {CDF4(4126, 13353, 20978)}, {CDF4(31162, 32726, 32748)}, + {CDF4(23017, 32222, 32701)}, {CDF4(15629, 29233, 32046)}, + {CDF4(9387, 22621, 29480)}, {CDF4(6922, 17616, 25010)}, + {CDF4(28838, 32265, 32614)}, {CDF4(19701, 30206, 31920)}, + {CDF4(11214, 22410, 27933)}, {CDF4(5320, 14177, 23034)}, + {CDF4(5049, 12881, 17827)}, {CDF4(27484, 32471, 32734)}, + {CDF4(21076, 31526, 32561)}, {CDF4(12707, 26303, 31211)}, + {CDF4(8169, 21722, 28219)}, {CDF4(6045, 19406, 27042)}, + {CDF4(27753, 32572, 32745)}, {CDF4(20832, 31878, 32653)}, + {CDF4(13250, 27356, 31674)}, {CDF4(7718, 21508, 29858)}, + {CDF4(7209, 18350, 25559)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(7876, 16901, 21741)}, {CDF4(24001, 31898, 32625)}, + {CDF4(14529, 27959, 31451)}, {CDF4(8273, 20818, 27258)}, + {CDF4(5278, 14673, 21510)}, {CDF4(2983, 8843, 14039)}, + {CDF4(28016, 32574, 32732)}, {CDF4(17471, 30306, 32301)}, + {CDF4(10224, 24063, 29728)}, {CDF4(6602, 17954, 25052)}, + {CDF4(4002, 11585, 17759)}, {CDF4(30190, 32634, 32739)}, + {CDF4(17497, 30282, 32270)}, {CDF4(10229, 23729, 29538)}, + {CDF4(6344, 17211, 24440)}, {CDF4(3849, 11189, 17108)}, + {CDF4(28570, 32583, 32726)}, {CDF4(17521, 30161, 32238)}, + {CDF4(10153, 23565, 29378)}, {CDF4(6455, 17341, 24443)}, + {CDF4(3907, 11042, 17024)}, {CDF4(30689, 32715, 32748)}, + {CDF4(21546, 31840, 32610)}, {CDF4(13547, 27581, 31459)}, + {CDF4(8912, 21757, 28309)}, {CDF4(5548, 15080, 22046)}, + {CDF4(30783, 32540, 32685)}, {CDF4(17540, 29528, 31668)}, + {CDF4(10160, 21468, 26783)}, {CDF4(4724, 13393, 20054)}, + {CDF4(2702, 8174, 13102)}, {CDF4(31648, 32686, 32742)}, + {CDF4(20954, 31094, 32337)}, {CDF4(12420, 25698, 30179)}, + {CDF4(7304, 19320, 26248)}, {CDF4(4366, 12261, 18864)}, + {CDF4(31581, 32723, 32748)}, {CDF4(21373, 31586, 32525)}, + {CDF4(12744, 26625, 30885)}, {CDF4(7431, 20322, 26950)}, + {CDF4(4692, 13323, 20111)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(7833, 18369, 24095)}, {CDF4(26650, 32273, 32702)}, + {CDF4(16371, 29961, 32191)}, {CDF4(11055, 24082, 29629)}, + {CDF4(6892, 18644, 25400)}, {CDF4(5006, 13057, 19240)}, + {CDF4(29834, 32666, 32748)}, {CDF4(19577, 31335, 32570)}, + {CDF4(12253, 26509, 31122)}, {CDF4(7991, 20772, 27711)}, + {CDF4(5677, 15910, 23059)}, {CDF4(30109, 32532, 32720)}, + {CDF4(16747, 30166, 32252)}, {CDF4(10134, 23542, 29184)}, + {CDF4(5791, 16176, 23556)}, {CDF4(4362, 10414, 17284)}, + {CDF4(29492, 32626, 32748)}, {CDF4(19894, 31402, 32525)}, + {CDF4(12942, 27071, 30869)}, {CDF4(8346, 21216, 27405)}, + {CDF4(6572, 17087, 23859)}, {CDF4(32035, 32735, 32748)}, + {CDF4(22957, 31838, 32618)}, {CDF4(14724, 28572, 31772)}, + {CDF4(10364, 23999, 29553)}, {CDF4(7004, 18433, 25655)}, + {CDF4(27528, 32277, 32681)}, {CDF4(16959, 31171, 32096)}, + {CDF4(10486, 23593, 27962)}, {CDF4(8192, 16384, 23211)}, + {CDF4(8937, 17873, 20852)}, {CDF4(27715, 32002, 32615)}, + {CDF4(15073, 29491, 31676)}, {CDF4(11264, 24576, 28672)}, + {CDF4(2341, 18725, 23406)}, {CDF4(7282, 18204, 25486)}, + {CDF4(28547, 32213, 32657)}, {CDF4(20788, 29773, 32239)}, + {CDF4(6780, 21469, 30508)}, {CDF4(5958, 14895, 23831)}, + {CDF4(16384, 21845, 27307)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(5992, 14304, 19765)}, {CDF4(22612, 31238, 32456)}, + {CDF4(13456, 27162, 31087)}, {CDF4(8001, 20062, 26504)}, + {CDF4(5168, 14105, 20764)}, {CDF4(2632, 7771, 12385)}, + {CDF4(27034, 32344, 32709)}, {CDF4(15850, 29415, 31997)}, + {CDF4(9494, 22776, 28841)}, {CDF4(6151, 16830, 23969)}, + {CDF4(3461, 10039, 15722)}, {CDF4(30134, 32569, 32731)}, + {CDF4(15638, 29422, 31945)}, {CDF4(9150, 21865, 28218)}, + {CDF4(5647, 15719, 22676)}, {CDF4(3402, 9772, 15477)}, + {CDF4(28530, 32586, 32735)}, {CDF4(17139, 30298, 32292)}, + {CDF4(10200, 24039, 29685)}, {CDF4(6419, 17674, 24786)}, + {CDF4(3544, 10225, 15824)}, {CDF4(31333, 32726, 32748)}, + {CDF4(20618, 31487, 32544)}, {CDF4(12901, 27217, 31232)}, + {CDF4(8624, 21734, 28171)}, {CDF4(5104, 14191, 20748)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(11206, 21090, 26561)}, {CDF4(28759, 32279, 32671)}, + {CDF4(14171, 27952, 31569)}, {CDF4(9743, 22907, 29141)}, + {CDF4(6871, 17886, 24868)}, {CDF4(4960, 13152, 19315)}, + {CDF4(31077, 32661, 32748)}, {CDF4(19400, 31195, 32515)}, + {CDF4(12752, 26858, 31040)}, {CDF4(8370, 22098, 28591)}, + {CDF4(5457, 15373, 22298)}, {CDF4(31697, 32706, 32748)}, + {CDF4(17860, 30657, 32333)}, {CDF4(12510, 24812, 29261)}, + {CDF4(6180, 19124, 24722)}, {CDF4(5041, 13548, 17959)}, + {CDF4(31552, 32716, 32748)}, {CDF4(21908, 31769, 32623)}, + {CDF4(14470, 28201, 31565)}, {CDF4(9493, 22982, 28608)}, + {CDF4(6858, 17240, 24137)}, {CDF4(32543, 32752, 32756)}, + {CDF4(24286, 32097, 32666)}, {CDF4(15958, 29217, 32024)}, + {CDF4(10207, 24234, 29958)}, {CDF4(6929, 18305, 25652)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + }, + { + { + {CDF4(4137, 10847, 15682)}, {CDF4(17824, 27001, 30058)}, + {CDF4(10204, 22796, 28291)}, {CDF4(6076, 15935, 22125)}, + {CDF4(3852, 10937, 16816)}, {CDF4(2252, 6324, 10131)}, + {CDF4(25840, 32016, 32662)}, {CDF4(15109, 28268, 31531)}, + {CDF4(9385, 22231, 28340)}, {CDF4(6082, 16672, 23479)}, + {CDF4(3318, 9427, 14681)}, {CDF4(30594, 32574, 32718)}, + {CDF4(16836, 29552, 31859)}, {CDF4(9556, 22542, 28356)}, + {CDF4(6305, 16725, 23540)}, {CDF4(3376, 9895, 15184)}, + {CDF4(29383, 32617, 32745)}, {CDF4(18891, 30809, 32401)}, + {CDF4(11688, 25942, 30687)}, {CDF4(7468, 19469, 26651)}, + {CDF4(3909, 11358, 17012)}, {CDF4(31564, 32736, 32748)}, + {CDF4(20906, 31611, 32600)}, {CDF4(13191, 27621, 31537)}, + {CDF4(8768, 22029, 28676)}, {CDF4(5079, 14109, 20906)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + }, + { + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)}, + {CDF4(8192, 16384, 24576)}, {CDF4(8192, 16384, 24576)} + } + } + } +}; + +static const RK_U16 +av1_default_coeff_base_eob_multi_cdfs[AV1_TOKEN_CDF_Q_CTXS][AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_SIG_COEF_CONTEXTS_EOB][AV1_CDF_SIZE(AV1_NUM_BASE_LEVELS + 1)] = { + { + { + { + {CDF3(17837, 29055)}, + {CDF3(29600, 31446)}, + {CDF3(30844, 31878)}, + {CDF3(24926, 28948)} + }, + { + {CDF3(21365, 30026)}, + {CDF3(30512, 32423)}, + {CDF3(31658, 32621)}, + {CDF3(29630, 31881)} + } + }, + { + { + {CDF3(5717, 26477)}, + {CDF3(30491, 31703)}, + {CDF3(31550, 32158)}, + {CDF3(29648, 31491)} + }, + { + {CDF3(12608, 27820)}, + {CDF3(30680, 32225)}, + {CDF3(30809, 32335)}, + {CDF3(31299, 32423)} + } + }, + { + { + {CDF3(1786, 12612)}, + {CDF3(30663, 31625)}, + {CDF3(32339, 32468)}, + {CDF3(31148, 31833)} + }, + { + {CDF3(18857, 23865)}, + {CDF3(31428, 32428)}, + {CDF3(31744, 32373)}, + {CDF3(31775, 32526)} + } + }, + { + { + {CDF3(1787, 2532)}, + {CDF3(30832, 31662)}, + {CDF3(31824, 32682)}, + {CDF3(32133, 32569)} + }, + { + {CDF3(13751, 22235)}, + {CDF3(32089, 32409)}, + {CDF3(27084, 27920)}, + {CDF3(29291, 32594)} + } + }, + { + { + {CDF3(1725, 3449)}, + {CDF3(31102, 31935)}, + {CDF3(32457, 32613)}, + {CDF3(32412, 32649)} + }, + { + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)} + } + } + }, + { + { + { + {CDF3(17560, 29888)}, + {CDF3(29671, 31549)}, + {CDF3(31007, 32056)}, + {CDF3(27286, 30006)} + }, + { + {CDF3(26594, 31212)}, + {CDF3(31208, 32582)}, + {CDF3(31835, 32637)}, + {CDF3(30595, 32206)} + } + }, + { + { + {CDF3(15239, 29932)}, + {CDF3(31315, 32095)}, + {CDF3(32130, 32434)}, + {CDF3(30864, 31996)} + }, + { + {CDF3(26279, 30968)}, + {CDF3(31142, 32495)}, + {CDF3(31713, 32540)}, + {CDF3(31929, 32594)} + } + }, + { + { + {CDF3(2644, 25198)}, + {CDF3(32038, 32451)}, + {CDF3(32639, 32695)}, + {CDF3(32166, 32518)} + }, + { + {CDF3(17187, 27668)}, + {CDF3(31714, 32550)}, + {CDF3(32283, 32678)}, + {CDF3(31930, 32563)} + } + }, + { + { + {CDF3(1044, 2257)}, + {CDF3(30755, 31923)}, + {CDF3(32208, 32693)}, + {CDF3(32244, 32615)} + }, + { + {CDF3(21317, 26207)}, + {CDF3(29133, 30868)}, + {CDF3(29311, 31231)}, + {CDF3(29657, 31087)} + } + }, + { + { + {CDF3(478, 1834)}, + {CDF3(31005, 31987)}, + {CDF3(32317, 32724)}, + {CDF3(30865, 32648)} + }, + { + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)} + } + } + }, + { + { + { + {CDF3(20092, 30774)}, + {CDF3(30695, 32020)}, + {CDF3(31131, 32103)}, + {CDF3(28666, 30870)} + }, + { + {CDF3(27258, 31095)}, + {CDF3(31804, 32623)}, + {CDF3(31763, 32528)}, + {CDF3(31438, 32506)} + } + }, + { + { + {CDF3(18049, 30489)}, + {CDF3(31706, 32286)}, + {CDF3(32163, 32473)}, + {CDF3(31550, 32184)} + }, + { + {CDF3(27116, 30842)}, + {CDF3(31971, 32598)}, + {CDF3(32088, 32576)}, + {CDF3(32067, 32664)} + } + }, + { + { + {CDF3(12854, 29093)}, + {CDF3(32272, 32558)}, + {CDF3(32667, 32729)}, + {CDF3(32306, 32585)} + }, + { + {CDF3(25476, 30366)}, + {CDF3(32169, 32687)}, + {CDF3(32479, 32689)}, + {CDF3(31673, 32634)} + } + }, + { + { + {CDF3(2809, 19301)}, + {CDF3(32205, 32622)}, + {CDF3(32338, 32730)}, + {CDF3(31786, 32616)} + }, + { + {CDF3(22737, 29105)}, + {CDF3(30810, 32362)}, + {CDF3(30014, 32627)}, + {CDF3(30528, 32574)} + } + }, + { + { + {CDF3(935, 3382)}, + {CDF3(30789, 31909)}, + {CDF3(32466, 32756)}, + {CDF3(30860, 32513)} + }, + { + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)} + } + } + }, + { + { + { + {CDF3(22497, 31198)}, + {CDF3(31715, 32495)}, + {CDF3(31606, 32337)}, + {CDF3(30388, 31990)} + }, + { + {CDF3(27877, 31584)}, + {CDF3(32170, 32728)}, + {CDF3(32155, 32688)}, + {CDF3(32219, 32702)} + } + }, + { + { + {CDF3(21457, 31043)}, + {CDF3(31951, 32483)}, + {CDF3(32153, 32562)}, + {CDF3(31473, 32215)} + }, + { + {CDF3(27558, 31151)}, + {CDF3(32020, 32640)}, + {CDF3(32097, 32575)}, + {CDF3(32242, 32719)} + } + }, + { + { + {CDF3(19980, 30591)}, + {CDF3(32219, 32597)}, + {CDF3(32581, 32706)}, + {CDF3(31803, 32287)} + }, + { + {CDF3(26473, 30507)}, + {CDF3(32431, 32723)}, + {CDF3(32196, 32611)}, + {CDF3(31588, 32528)} + } + }, + { + { + {CDF3(24647, 30463)}, + {CDF3(32412, 32695)}, + {CDF3(32468, 32720)}, + {CDF3(31269, 32523)} + }, + { + {CDF3(28482, 31505)}, + {CDF3(32152, 32701)}, + {CDF3(31732, 32598)}, + {CDF3(31767, 32712)} + } + }, + { + { + {CDF3(12358, 24977)}, + {CDF3(31331, 32385)}, + {CDF3(32634, 32756)}, + {CDF3(30411, 32548)} + }, + { + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)}, + {CDF3(10923, 21845)} + } + } + } +}; + +static const RK_U16 default_joint_cdf[] = {ICDF(4096), ICDF(11264), ICDF(19328)}; + +static const RK_U16 default_clsss_cdf[][10] = { + // Vertical component + { + ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551), + ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767) + }, + // Horizontal component + { + ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551), + ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767) + } +}; + +static const RK_U16 default_clsss0_fp_cdf[][2][3] = { + // Vertical component + { + {ICDF(16384), ICDF(24576), ICDF(26624)}, + {ICDF(12288), ICDF(21248), ICDF(24128)} + }, + // Horizontal component + { + {ICDF(16384), ICDF(24576), ICDF(26624)}, + {ICDF(12288), ICDF(21248), ICDF(24128)} + } +}; + +static const RK_U16 default_fp_cdf[][3] = { + // Vertical component + {ICDF(8192), ICDF(17408), ICDF(21248)}, + // Horizontal component + {ICDF(8192), ICDF(17408), ICDF(21248)} +}; + +static const RK_U16 default_sign_cdf[] = {ICDF(128 * 128), ICDF(128 * 128)}; +static const RK_U16 default_class0_hp_cdf[] = {ICDF(160 * 128), ICDF(160 * 128)}; +static const RK_U16 default_hp_cdf[] = {ICDF(128 * 128), ICDF(128 * 128)}; +static const RK_U16 default_class0_cdf[] = {ICDF(216 * 128), ICDF(216 * 128)}; +static const RK_U16 default_bits_cdf[][10] = { + { + ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160), + ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234), + ICDF(128 * 234), ICDF(128 * 240) + }, + { + ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160), + ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234), + ICDF(128 * 234), ICDF(128 * 240) + } +}; + +MPP_RET av1d_set_default_coeff_probs(RK_U32 base_qindex, AV1CDFs *cdfs) +{ + RK_S32 index = (base_qindex <= 20) ? 0 : + (base_qindex <= 60) ? 1 : + (base_qindex <= 120) ? 2 : 3; + + memcpy(cdfs->txb_skip_cdf, av1_default_txb_skip_cdfs[index], + sizeof(av1_default_txb_skip_cdfs[0])); + memcpy(cdfs->eob_extra_cdf, av1_default_eob_extra_cdfs[index], + sizeof(av1_default_eob_extra_cdfs[0])); + memcpy(cdfs->dc_sign_cdf, av1_default_dc_sign_cdfs[index], + sizeof(av1_default_dc_sign_cdfs[0])); + memcpy(cdfs->coeff_br_cdf, av1_default_coeff_lps_multi_cdfs[index], + sizeof(av1_default_coeff_lps_multi_cdfs[0])); + memcpy(cdfs->coeff_base_cdf, av1_default_coeff_base_multi_cdfs[index], + sizeof(av1_default_coeff_base_multi_cdfs[0])); + memcpy(cdfs->coeff_base_eob_cdf, + av1_default_coeff_base_eob_multi_cdfs[index], + sizeof(av1_default_coeff_base_eob_multi_cdfs[0])); + memcpy(cdfs->eob_flag_cdf16, av1_default_eob_multi16_cdfs[index], + sizeof(av1_default_eob_multi16_cdfs[0])); + memcpy(cdfs->eob_flag_cdf32, av1_default_eob_multi32_cdfs[index], + sizeof(av1_default_eob_multi32_cdfs[0])); + memcpy(cdfs->eob_flag_cdf64, av1_default_eob_multi64_cdfs[index], + sizeof(av1_default_eob_multi64_cdfs[0])); + memcpy(cdfs->eob_flag_cdf128, av1_default_eob_multi128_cdfs[index], + sizeof(av1_default_eob_multi128_cdfs[0])); + memcpy(cdfs->eob_flag_cdf256, av1_default_eob_multi256_cdfs[index], + sizeof(av1_default_eob_multi256_cdfs[0])); + memcpy(cdfs->eob_flag_cdf512, av1_default_eob_multi512_cdfs[index], + sizeof(av1_default_eob_multi512_cdfs[0])); + memcpy(cdfs->eob_flag_cdf1024, av1_default_eob_multi1024_cdfs[index], + sizeof(av1_default_eob_multi1024_cdfs[0])); + + return MPP_OK; +} + +MPP_RET av1d_set_default_cdfs(AV1CDFs *cdfs, Av1MvCDFs *cdfs_ndvc) +{ + memcpy(cdfs->partition_cdf, default_partition_cdf, + sizeof(cdfs->partition_cdf)); + + memcpy(cdfs->tx_type_intra0_cdf, default_intra_ext_tx0_cdf, + sizeof(cdfs->tx_type_intra0_cdf)); + memcpy(cdfs->tx_type_intra1_cdf, default_intra_ext_tx1_cdf, + sizeof(cdfs->tx_type_intra1_cdf)); + memcpy(cdfs->tx_type_inter_cdf, default_inter_ext_tx_cdf, + sizeof(cdfs->tx_type_inter_cdf)); + + memcpy(cdfs->vartx_part_cdf, default_txfm_partition_cdf, + sizeof(cdfs->vartx_part_cdf)); + memcpy(cdfs->mbskip_cdf, default_skip_cdfs, sizeof(cdfs->mbskip_cdf)); + memcpy(cdfs->delta_q_cdf, default_delta_q_cdf, + sizeof(cdfs->delta_q_cdf)); + memcpy(cdfs->delta_lf_multi_cdf, default_delta_lf_multi_cdf, + sizeof(cdfs->delta_lf_multi_cdf)); + memcpy(cdfs->delta_lf_cdf, default_delta_lf_cdf, + sizeof(cdfs->delta_lf_cdf)); + + memcpy(cdfs->segment_pred_cdf, default_segment_pred_cdf, + sizeof(cdfs->segment_pred_cdf)); + + memcpy(cdfs->spatial_pred_seg_tree_cdf, default_spatial_pred_seg_tree_cdf, + sizeof(cdfs->spatial_pred_seg_tree_cdf)); + + memcpy(cdfs->skip_mode_cdf, default_skip_mode_cdfs, + sizeof(cdfs->skip_mode_cdf)); + + memcpy(cdfs->tx_size_cdf, default_tx_size_cdf, + sizeof(cdfs->tx_size_cdf)); + + memcpy(cdfs->kf_ymode_cdf, default_kf_y_mode_cdf, + sizeof(cdfs->kf_ymode_cdf)); + memcpy(cdfs->uv_mode_cdf, default_uv_mode_cdf, + sizeof(cdfs->uv_mode_cdf)); + memcpy(cdfs->if_ymode_cdf, default_if_y_mode_cdf, + sizeof(cdfs->if_ymode_cdf)); + + memcpy(cdfs->intra_inter_cdf, default_intra_inter_cdf, + sizeof(cdfs->intra_inter_cdf)); + + memcpy(cdfs->comp_ref_cdf, default_comp_ref_cdf, + sizeof(cdfs->comp_ref_cdf)); + memcpy(cdfs->comp_bwdref_cdf, default_comp_bwdref_cdf, + sizeof(cdfs->comp_bwdref_cdf)); + + memcpy(cdfs->comp_inter_cdf, default_comp_inter_cdf, + sizeof(cdfs->comp_inter_cdf)); + + memcpy(cdfs->single_ref_cdf, default_single_ref_cdf, + sizeof(cdfs->single_ref_cdf)); + memcpy(cdfs->comp_ref_type_cdf, default_comp_ref_type_cdf, + sizeof(cdfs->comp_ref_type_cdf)); + memcpy(cdfs->uni_comp_ref_cdf, default_uni_comp_ref_cdf, + sizeof(cdfs->uni_comp_ref_cdf)); + + memcpy(cdfs->newmv_cdf, default_newmv_cdf, sizeof(cdfs->newmv_cdf)); + memcpy(cdfs->zeromv_cdf, default_zeromv_cdf, sizeof(cdfs->zeromv_cdf)); + memcpy(cdfs->refmv_cdf, default_refmv_cdf, sizeof(cdfs->refmv_cdf)); + memcpy(cdfs->drl_cdf, default_drl_cdf, sizeof(cdfs->drl_cdf)); + + memcpy(cdfs->interp_filter_cdf, default_switchable_interp_cdf, + sizeof(cdfs->interp_filter_cdf)); + + // Regular MV cdfs + memcpy(cdfs->mv_cdf.joint_cdf, default_joint_cdf, + sizeof(cdfs->mv_cdf.joint_cdf)); + memcpy(cdfs->mv_cdf.sign_cdf, default_sign_cdf, + sizeof(cdfs->mv_cdf.sign_cdf)); + memcpy(cdfs->mv_cdf.clsss_cdf, default_clsss_cdf, + sizeof(cdfs->mv_cdf.clsss_cdf)); + memcpy(cdfs->mv_cdf.clsss0_fp_cdf, default_clsss0_fp_cdf, + sizeof(cdfs->mv_cdf.clsss0_fp_cdf)); + memcpy(cdfs->mv_cdf.fp_cdf, default_fp_cdf, + sizeof(cdfs->mv_cdf.fp_cdf)); + memcpy(cdfs->mv_cdf.class0_hp_cdf, default_class0_hp_cdf, + sizeof(cdfs->mv_cdf.class0_hp_cdf)); + memcpy(cdfs->mv_cdf.hp_cdf, default_hp_cdf, + sizeof(cdfs->mv_cdf.hp_cdf)); + memcpy(cdfs->mv_cdf.class0_cdf, default_class0_cdf, + sizeof(cdfs->mv_cdf.class0_cdf)); + memcpy(cdfs->mv_cdf.bits_cdf, default_bits_cdf, + sizeof(cdfs->mv_cdf.bits_cdf)); + + // Intrabc cdfs + memcpy(cdfs_ndvc->joint_cdf, default_joint_cdf, + sizeof(cdfs_ndvc->joint_cdf)); + memcpy(cdfs_ndvc->sign_cdf, default_sign_cdf, + sizeof(cdfs_ndvc->sign_cdf)); + memcpy(cdfs_ndvc->clsss_cdf, default_clsss_cdf, + sizeof(cdfs_ndvc->clsss_cdf)); + memcpy(cdfs_ndvc->clsss0_fp_cdf, default_clsss0_fp_cdf, + sizeof(cdfs_ndvc->clsss0_fp_cdf)); + memcpy(cdfs_ndvc->fp_cdf, default_fp_cdf, sizeof(cdfs_ndvc->fp_cdf)); + memcpy(cdfs_ndvc->class0_hp_cdf, default_class0_hp_cdf, + sizeof(cdfs_ndvc->class0_hp_cdf)); + memcpy(cdfs_ndvc->hp_cdf, default_hp_cdf, sizeof(cdfs_ndvc->hp_cdf)); + memcpy(cdfs_ndvc->class0_cdf, default_class0_cdf, + sizeof(cdfs_ndvc->class0_cdf)); + memcpy(cdfs_ndvc->bits_cdf, default_bits_cdf, + sizeof(cdfs_ndvc->bits_cdf)); + + memcpy(cdfs->obmc_cdf, default_obmc_cdf, sizeof(cdfs->obmc_cdf)); + memcpy(cdfs->motion_mode_cdf, default_motion_mode_cdf, + sizeof(cdfs->motion_mode_cdf)); + + memcpy(cdfs->inter_compound_mode_cdf, default_inter_compound_mode_cdf, + sizeof(cdfs->inter_compound_mode_cdf)); + memcpy(cdfs->compound_type_cdf, default_compound_type_cdf, + sizeof(cdfs->compound_type_cdf)); + memcpy(cdfs->interintra_cdf, default_interintra_cdf, + sizeof(cdfs->interintra_cdf)); + memcpy(cdfs->interintra_mode_cdf, default_interintra_mode_cdf, + sizeof(cdfs->interintra_mode_cdf)); + memcpy(cdfs->wedge_interintra_cdf, default_wedge_interintra_cdf, + sizeof(cdfs->wedge_interintra_cdf)); + memcpy(cdfs->wedge_idx_cdf, default_wedge_idx_cdf, + sizeof(cdfs->wedge_idx_cdf)); + + memcpy(cdfs->palette_y_mode_cdf, default_palette_y_mode_cdf, + sizeof(cdfs->palette_y_mode_cdf)); + memcpy(cdfs->palette_uv_mode_cdf, default_palette_uv_mode_cdf, + sizeof(cdfs->palette_uv_mode_cdf)); + memcpy(cdfs->palette_y_size_cdf, default_palette_y_size_cdf, + sizeof(cdfs->palette_y_size_cdf)); + memcpy(cdfs->palette_uv_size_cdf, default_palette_uv_size_cdf, + sizeof(cdfs->palette_uv_size_cdf)); + memcpy(cdfs->palette_y_color_index_cdf, default_palette_y_color_index_cdf, + sizeof(cdfs->palette_y_color_index_cdf)); + memcpy(cdfs->palette_uv_color_index_cdf, + default_palette_uv_color_index_cdf, + sizeof(cdfs->palette_uv_color_index_cdf)); + + memcpy(cdfs->cfl_sign_cdf, default_cfl_sign_cdf, + sizeof(cdfs->cfl_sign_cdf)); + memcpy(cdfs->cfl_alpha_cdf, default_cfl_alpha_cdf, + sizeof(cdfs->cfl_alpha_cdf)); + + memcpy(cdfs->intrabc_cdf, default_intrabc_cdf, + sizeof(cdfs->intrabc_cdf)); + memcpy(cdfs->angle_delta_cdf, default_angle_delta_cdf, + sizeof(cdfs->angle_delta_cdf)); + memcpy(cdfs->filter_intra_mode_cdf, default_filter_intra_mode_cdf, + sizeof(cdfs->filter_intra_mode_cdf)); + memcpy(cdfs->filter_intra_cdf, default_filter_intra_cdfs, + sizeof(cdfs->filter_intra_cdf)); + memcpy(cdfs->comp_group_idx_cdf, default_comp_group_idx_cdfs, + sizeof(cdfs->comp_group_idx_cdf)); + memcpy(cdfs->compound_idx_cdf, default_compound_idx_cdfs, + sizeof(cdfs->compound_idx_cdf)); + + return MPP_OK; +} diff --git a/mpp/codec/dec/av1/av1d_parser.c b/mpp/codec/dec/av1/av1d_parser.c new file mode 100644 index 000000000..0d9a933b9 --- /dev/null +++ b/mpp/codec/dec/av1/av1d_parser.c @@ -0,0 +1,1550 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "av1d_parser" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_compat_impl.h" +#include "rk_hdr_meta_com.h" + +#include "mpp_bitread.h" +#include "mpp_packet_impl.h" + +#include "av1d_parser.h" +#include "mpp_dec_cb_param.h" +#include "mpp_frame_impl.h" + +static const RK_S16 div_lut[AV1_DIV_LUT_NUM] = { + 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768, + 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142, + 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564, + 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028, + 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530, + 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066, + 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633, + 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228, + 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848, + 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491, + 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155, + 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838, + 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538, + 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255, + 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986, + 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732, + 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489, + 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259, + 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039, + 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830, + 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630, + 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439, + 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257, + 8240, 8224, 8208, 8192 +}; + +static MPP_RET get_pixel_format(Av1DecCtx *ctx) +{ + Av1Codec *s = ctx->priv_data; + const AV1SeqHeader *seq = s->seq_header; + uint8_t bit_depth = 8; + MppFrameFormat pix_fmt = MPP_FMT_BUTT; + + if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) + bit_depth = (seq->color_config.twelve_bit != 0) ? 12 : 10; + else if (seq->seq_profile <= 2) + bit_depth = (seq->color_config.high_bitdepth != 0) ? 10 : 8; + else { + mpp_err_f("Unknown AV1 profile %d.\n", seq->seq_profile); + return MPP_ERR_VALUE; + } + + if (!seq->color_config.mono_chrome) { + // 4:4:4 x:0 y:0, 4:2:2 x:1 y:0, 4:2:0 x:1 y:1 + if (seq->color_config.subsampling_x == 0 && + seq->color_config.subsampling_y == 0) { + mpp_err_f("no support yuv444 AV1 pixel format.\n"); + return MPP_ERR_UNKNOW; + } else if (seq->color_config.subsampling_x == 1 && + seq->color_config.subsampling_y == 0) { + if (bit_depth == 8) + pix_fmt = MPP_FMT_YUV422P; + else { + mpp_err_f("no support yuv422 bit depth > 8\n"); + return MPP_ERR_UNKNOW; + } + } else if (seq->color_config.subsampling_x == 1 && + seq->color_config.subsampling_y == 1) { + if (bit_depth == 8) + pix_fmt = MPP_FMT_YUV420SP; + else if (bit_depth == 10) { + pix_fmt = MPP_FMT_YUV420SP_10BIT; + /* rk3588, allow user config 8bit for 10bit source. */ + if ((mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) && + (ctx->usr_set_fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP && + (ctx->cfg->base.out_fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP) + pix_fmt = MPP_FMT_YUV420SP; + } else { + mpp_err_f("no support MPP_FMT_YUV420SP bit depth > 8\n"); + return MPP_ERR_UNKNOW; + } + } + } else { + mpp_err_f("no supprot PIX_FMT_GRAY pixel format.\n"); + return MPP_ERR_UNKNOW; + } + + + if (pix_fmt == MPP_FMT_BUTT) + return MPP_ERR_UNKNOW; + ctx->pix_fmt = pix_fmt; + s->bit_depth = bit_depth; + return MPP_OK; +} + +// Inverse recenters a non-negative literal v around a reference r +static RK_U32 inv_recenter_nonneg(RK_S32 r, RK_U32 v) +{ + if (v > (RK_U32)(r << 1)) + return v; + else if (v & 1) // v is odd + return r - ((v + 1) >> 1); + else // v is even + return r + (v >> 1); +} + +static RK_S32 decode_signed_subexp(RK_U32 sub_exp, RK_S32 low, RK_S32 high, RK_S32 r) +{ + RK_S32 x = 0; + + // Map to unsigned interval [0, high - low) + high -= low; + r -= low; + // Inverse recenters a non-negative literal v in [0, n-1] around a + // reference r also in [0, n-1] + if (high < (r << 1)) { + x = high - 1 - inv_recenter_nonneg(high - 1 - r, sub_exp); + } else { + x = inv_recenter_nonneg(r, sub_exp); + } + // Map back to signed interval [low, high) + x += low; + return x; +} + +static MPP_RET set_current_global_param(Av1Codec *s, RK_S32 type, RK_S32 ref, RK_S32 idx) +{ + uint8_t primary_frame, prev_frame; + RK_U32 abs_bits, prec_bits, round, prec_diff, sub, mx; + RK_S32 r, prev_gm_param; + const AV1FrameHeader *f = s->frame_header; + + primary_frame = f->primary_ref_frame; + prev_frame = f->ref_frame_idx[primary_frame]; + abs_bits = AV1_GM_ABS_ALPHA_BITS; + prec_bits = AV1_GM_ALPHA_PREC_BITS; + + /* setup_past_independence() sets PrevGmParams to default values. We can + * simply point to the current's frame gm_params as they will be initialized + * with defaults at this point. + */ + if (primary_frame == AV1_PRIMARY_REF_NONE) + prev_gm_param = s->cur_frame.gm_params[ref].wmmat[idx]; + else + prev_gm_param = s->ref[prev_frame].gm_params[ref].wmmat[idx]; + + if (idx < 2) { + if (type == AV1_WARP_MODEL_TRANSLATION) { + abs_bits = AV1_GM_ABS_TRANS_ONLY_BITS - !f->allow_high_precision_mv; + prec_bits = AV1_GM_TRANS_ONLY_PREC_BITS - !f->allow_high_precision_mv; + } else { + abs_bits = AV1_GM_ABS_TRANS_BITS; + prec_bits = AV1_GM_TRANS_PREC_BITS; + } + } + round = (idx % 3) == 2 ? (1 << AV1_WARPEDMODEL_PREC_BITS) : 0; + prec_diff = AV1_WARPEDMODEL_PREC_BITS - prec_bits; + sub = (idx % 3) == 2 ? (1 << prec_bits) : 0; + mx = 1 << abs_bits; + r = (prev_gm_param >> prec_diff) - sub; + + s->cur_frame.gm_params[ref].wmmat_val[idx] = + decode_signed_subexp(f->gm_params[ref][idx], -mx, mx + 1, r); + s->cur_frame.gm_params[ref].wmmat[idx] = + (s->cur_frame.gm_params[ref].wmmat_val[idx] << prec_diff) + round; + + return MPP_OK; +} + +/* + * Decomposes a divisor D such that 1/D = y/2^shift, where y is returned + * at precision of DIV_LUT_PREC_BITS along with the shift. +*/ +static RK_S16 resolve_divisor(RK_U32 d, RK_S16 *shift) +{ + RK_S32 e, f; + + *shift = mpp_log2(d); + // e is obtained from D after resetting the most significant 1 bit. + e = d - (1 << (*shift)); + // Get the most significant DIV_LUT_BITS (8) bits of e into f + if (*shift > AV1_DIV_LUT_BITS) + f = mpp_round_pow2(e, *shift - AV1_DIV_LUT_BITS); + else + f = e << (AV1_DIV_LUT_BITS - (*shift)); + + *shift += AV1_DIV_LUT_PREC_BITS; + // Use f as lookup into the precomputed table of multipliers + return div_lut[f]; +} + +// Returns 1 on success or 0 on an invalid affine set +static RK_U8 is_shear_params_valid(Av1Codec *s, RK_S32 idx) +{ + RK_S16 alpha, beta, gamma, delta, divf, divs; + RK_S64 v, w; + RK_S32 *mat = &s->cur_frame.gm_params[idx].wmmat[0]; + + // check affine shear params validity + if (mat[2] < 0) + return 0; + + alpha = MPP_CLIP3(INT16_MIN, INT16_MAX, mat[2] - (1 << AV1_WARPEDMODEL_PREC_BITS)); + beta = MPP_CLIP3(INT16_MIN, INT16_MAX, mat[3]); + divf = resolve_divisor(MPP_ABS(mat[2]), &divs) * (mat[2] < 0 ? -1 : 1); + v = (RK_S64)mat[4] * (1 << AV1_WARPEDMODEL_PREC_BITS); + w = (RK_S64)mat[3] * mat[4]; + gamma = MPP_CLIP3(INT16_MIN, INT16_MAX, (RK_S32)mpp_round_pow2_signed((v * divf), divs)); + delta = MPP_CLIP3(INT16_MIN, INT16_MAX, + mat[5] - (RK_S32)mpp_round_pow2_signed((w * divf), + divs) - (1 << AV1_WARPEDMODEL_PREC_BITS)); + + alpha = mpp_round_pow2_signed(alpha, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS; + beta = mpp_round_pow2_signed(beta, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS; + gamma = mpp_round_pow2_signed(gamma, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS; + delta = mpp_round_pow2_signed(delta, AV1_WARP_PARAM_REDUCE_BITS) << AV1_WARP_PARAM_REDUCE_BITS; + + s->cur_frame.gm_params[idx].alpha = alpha; + s->cur_frame.gm_params[idx].beta = beta; + s->cur_frame.gm_params[idx].gamma = gamma; + s->cur_frame.gm_params[idx].delta = delta; + + // check shear params range + RK_U8 out_range_flag = ((4 * MPP_ABS(alpha) + 7 * MPP_ABS(beta)) >= (1 << AV1_WARPEDMODEL_PREC_BITS) || + (4 * MPP_ABS(gamma) + 4 * MPP_ABS(delta)) >= (1 << AV1_WARPEDMODEL_PREC_BITS)); + + return out_range_flag ? 0 : 1; +} + +static const AV1WarpedMotion default_warp_params = { + AV1_WARP_MODEL_IDENTITY, + { 0, 0, (1 << 16), 0, 0, (1 << 16) }, + { 0, 0, 0, 0, 0, 0 }, + (1 << 16), (1 << 16), (1 << 16), (1 << 16), +}; + +static MPP_RET set_current_global_motion_params(Av1Codec *s) +{ + const AV1FrameHeader *f = s->frame_header; + RK_S32 type, ref; + RK_S32 i = 0; + + for (ref = AV1_REF_FRAME_LAST; ref <= AV1_REF_FRAME_ALTREF; ref++) { + s->cur_frame.gm_params[ref].wmtype = AV1_WARP_MODEL_IDENTITY; + for (i = 0; i < 6; i++) + s->cur_frame.gm_params[ref].wmmat[i] = (i % 3 == 2) ? + 1 << AV1_WARPEDMODEL_PREC_BITS : 0; + } + if (f->frame_type == AV1_FRAME_KEY || + f->frame_type == AV1_FRAME_INTRA_ONLY) + return MPP_OK; + + for (ref = AV1_REF_FRAME_LAST; ref <= AV1_REF_FRAME_ALTREF; ref++) { + if (f->is_global[ref]) { + if (f->is_rot_zoom[ref]) { + type = AV1_WARP_MODEL_ROTZOOM; + } else { + type = f->is_translation[ref] ? AV1_WARP_MODEL_TRANSLATION + : AV1_WARP_MODEL_AFFINE; + } + } else { + type = AV1_WARP_MODEL_IDENTITY; + } + s->cur_frame.gm_params[ref].wmtype = type; + + if (type >= AV1_WARP_MODEL_ROTZOOM) { + set_current_global_param(s, type, ref, 2); + set_current_global_param(s, type, ref, 3); + if (type == AV1_WARP_MODEL_AFFINE) { + set_current_global_param(s, type, ref, 4); + set_current_global_param(s, type, ref, 5); + } else { + s->cur_frame.gm_params[ref].wmmat[4] = -s->cur_frame.gm_params[ref].wmmat[3]; + s->cur_frame.gm_params[ref].wmmat[5] = s->cur_frame.gm_params[ref].wmmat[2]; + } + } + if (type >= AV1_WARP_MODEL_TRANSLATION) { + set_current_global_param(s, type, ref, 0); + set_current_global_param(s, type, ref, 1); + } + // Validate shear params for affine and rotzoom models + { + RK_U32 shear_params_valid = 0; + RK_U8 ref_uses_scaling = s->frame_width != s->ref_s[ref].frame_width || + s->frame_height != s->ref_s[ref].frame_height; + + if (type <= AV1_WARP_MODEL_AFFINE) + shear_params_valid = is_shear_params_valid(s, ref); + + if (!shear_params_valid || ref_uses_scaling) + s->cur_frame.gm_params[ref] = default_warp_params; + } + + av1d_dbg(AV1D_DBG_HEADER, "ref %d alpa %d beta %d gamma %d delta %d\n", + ref, + s->cur_frame.gm_params[ref].alpha, + s->cur_frame.gm_params[ref].beta, + s->cur_frame.gm_params[ref].gamma, + s->cur_frame.gm_params[ref].delta); + } + return MPP_OK; +} + +static MPP_RET set_current_skip_mode_params(Av1Codec *s) +{ + const AV1SeqHeader *seq = s->seq_header; + const AV1FrameHeader *f = s->frame_header; + + RK_S32 forward_idx, backward_idx; + RK_S32 forward_hint, backward_hint; + RK_S32 second_forward_idx, second_forward_hint; + RK_S32 ref_hint, dist, i; + + if (!f->skip_mode_present) + return MPP_OK; + + forward_idx = -1; + backward_idx = -1; + forward_hint = -1; + backward_hint = -1; + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = s->ref[f->ref_frame_idx[i]].order_hint; + dist = av1d_get_relative_dist(seq, ref_hint, f->order_hint); + if (dist < 0) { + if (forward_idx < 0 || + av1d_get_relative_dist(seq, ref_hint, forward_hint) > 0) { + forward_idx = i; + forward_hint = ref_hint; + } + } else if (dist > 0) { + if (backward_idx < 0 || + av1d_get_relative_dist(seq, ref_hint, backward_hint) < 0) { + backward_idx = i; + backward_hint = ref_hint; + } + } + } + + if (forward_idx < 0) { + return MPP_OK; + } else if (backward_idx >= 0) { + s->cur_frame.skip_mode_frame_idx[0] = + AV1_REF_FRAME_LAST + MPP_MIN(forward_idx, backward_idx); + s->cur_frame.skip_mode_frame_idx[1] = + AV1_REF_FRAME_LAST + MPP_MAX(forward_idx, backward_idx); + return MPP_OK; + } + + second_forward_idx = -1; + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = s->ref[f->ref_frame_idx[i]].order_hint; + if (av1d_get_relative_dist(seq, ref_hint, forward_hint) < 0) { + if (second_forward_idx < 0 || + av1d_get_relative_dist(seq, ref_hint, second_forward_hint) > 0) { + second_forward_idx = i; + second_forward_hint = ref_hint; + } + } + } + + if (second_forward_idx < 0) + return MPP_OK; + + s->cur_frame.skip_mode_frame_idx[0] = + AV1_REF_FRAME_LAST + MPP_MIN(forward_idx, second_forward_idx); + s->cur_frame.skip_mode_frame_idx[1] = + AV1_REF_FRAME_LAST + MPP_MAX(forward_idx, second_forward_idx); + + return MPP_OK; +} + +static MPP_RET set_current_coded_lossless_param(Av1Codec *s) +{ + const AV1FrameHeader *f = s->frame_header; + + if (f->delta_q_y_dc || f->delta_q_u_ac || + f->delta_q_u_dc || f->delta_q_v_ac || f->delta_q_v_dc) { + s->cur_frame.coded_lossless = 0; + + return MPP_OK; + } + + s->cur_frame.coded_lossless = 1; + for (RK_S32 i = 0; i < AV1_MAX_SEGMENTS; i++) { + RK_S32 qindex; + if (f->feature_enabled[i][AV1_SEG_LVL_ALT_Q]) { + qindex = (f->base_q_idx + + f->feature_value[i][AV1_SEG_LVL_ALT_Q]); + } else { + qindex = f->base_q_idx; + } + qindex = mpp_clip_uint_pow2(qindex, 8); + + if (qindex) { + s->cur_frame.coded_lossless = 0; + return MPP_OK; + } + } + return MPP_OK; +} + +static MPP_RET set_current_read_grain_params(Av1Codec *s) +{ + + AV1FilmGrainParams *src, *dst; + const AV1FilmGrainParams *film_grain = &s->frame_header->film_grain; + + src = &s->ref[film_grain->film_grain_params_ref_idx].film_grain; + dst = &s->cur_frame.film_grain; + + if (!film_grain->apply_grain) + return MPP_OK; + + if (film_grain->update_grain) { + memcpy(dst, film_grain, sizeof(*dst)); + return MPP_OK; + } + + memcpy(dst, src, sizeof(*dst)); + dst->grain_seed = film_grain->grain_seed; + + return MPP_OK; +} + +static MPP_RET get_tiles_info(Av1DecCtx *ctx, const AV1TileGroup *tile_group) +{ + Av1Codec *s = ctx->priv_data; + BitReadCtx_t m_gb, *gb = &m_gb; + + // Initialize BitReadCtx_t + mpp_set_bitread_ctx(gb, tile_group->tile_data.data, tile_group->tile_data.data_size); + if (s->tile_offset) + s->tile_offset += tile_group->tile_data.offset; + + for (RK_S32 tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) { + RK_S32 used_bytes, left_bytes, size_bytes, size, i; + + if (tile_num == tile_group->tg_end) { + used_bytes = mpp_get_bits_count(gb) / 8; + left_bytes = mpp_get_bits_left(gb) / 8; + + s->tile_offset_start[tile_num] = used_bytes + s->tile_offset; + s->tile_offset_end[tile_num] = used_bytes + left_bytes + s->tile_offset; + s->tile_offset = s->tile_offset_end[tile_num]; + return MPP_OK; + } + + size_bytes = s->frame_header->tile_size_bytes_minus1 + 1; + left_bytes = mpp_get_bits_left(gb) / 8; + if (left_bytes < size_bytes) + return MPP_ERR_VALUE; + // Read the size_bytes bytes to get the size + size = 0; + for (i = 0; i < size_bytes; i++) { + RK_S32 val = 0; + READ_BITS(gb, 8, &val); + size |= val << 8 * i; + } + used_bytes = mpp_get_bits_count(gb) / 8; + left_bytes = mpp_get_bits_left(gb) / 8; + if (left_bytes <= size) + return MPP_ERR_VALUE; + size++; + s->tile_offset_start[tile_num] = used_bytes + s->tile_offset; + s->tile_offset_end[tile_num] = used_bytes + size + s->tile_offset; + + // skip the size bytes + for (i = 0; i < size; i++) + SKIP_BITS(gb, 8); + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET av1d_frame_unref(Av1DecCtx *ctx, AV1FrameIInfo *info) +{ + info->spatial_id = info->temporal_id = 0; + memset(info->skip_mode_frame_idx, 0, + 2 * sizeof(uint8_t)); + memset(&info->film_grain, 0, sizeof(info->film_grain)); + + info->coded_lossless = 0; + + if (!info->ref || info->ref->ref_count <= 0 || info->slot_index >= 0x7f) { + mpp_err("ref count alreay is zero"); + return MPP_ERR_VALUE; + } + info->ref->ref_count--; + av1d_dbg(AV1D_DBG_REF, "ref %p, info->ref->ref_count %d, info->ref->invisible= %d", + info->ref, info->ref->ref_count, info->ref->invisible); + if (!info->ref->ref_count) { + if (info->slot_index < 0x7f) { + av1d_dbg(AV1D_DBG_REF, "clr info->slot_index = %d", info->slot_index); + if (!info->ref->is_output) { + MppBuffer framebuf = NULL; + mpp_buf_slot_get_prop(ctx->slots, info->slot_index, SLOT_BUFFER, &framebuf); + av1d_dbg(AV1D_DBG_REF, "free framebuf prt %p", framebuf); + if (framebuf) + mpp_buffer_put(framebuf); + info->ref->invisible = 0; + } + mpp_buf_slot_clr_flag(ctx->slots, info->slot_index, SLOT_CODEC_USE); + } + info->slot_index = 0xff; + mpp_free(info->ref); + info->ref = NULL; + } + info->ref = NULL; + + return MPP_OK; +} + +static MPP_RET set_output_frame(Av1DecCtx *ctx) +{ + Av1Codec *s = ctx->priv_data; + MppFrame frame = NULL; + MPP_RET ret = MPP_OK; + + // TODO: all layers + if (s->operating_point_idc && + mpp_log2(s->operating_point_idc >> 8) > s->cur_frame.spatial_id) + return MPP_OK; + mpp_buf_slot_get_prop(ctx->slots, s->cur_frame.slot_index, SLOT_FRAME_PTR, &frame); + if (s->hdr_dynamic_meta && s->hdr_dynamic) { + mpp_frame_set_hdr_dynamic_meta(frame, s->hdr_dynamic_meta); + s->hdr_dynamic = 0; + if (s->frame_header->show_existing_frame) + fill_hdr_meta_to_frame(frame, MPP_VIDEO_CodingAV1); + } + mpp_frame_set_pts(frame, s->pts); + mpp_frame_set_dts(frame, s->dts); + mpp_buf_slot_set_flag(ctx->slots, s->cur_frame.slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(ctx->slots, s->cur_frame.slot_index, QUEUE_DISPLAY); + s->cur_frame.ref->is_output = 1; + + return ret; +} + +static MPP_RET av1d_frame_ref(Av1DecCtx *ctx, AV1FrameIInfo *dst, const AV1FrameIInfo *src) +{ + MppFrameImpl *impl_frm = (MppFrameImpl *)dst->f; + dst->spatial_id = src->spatial_id; + dst->temporal_id = src->temporal_id; + dst->order_hint = src->order_hint; + + memcpy(dst->gm_params, + src->gm_params, + sizeof(src->gm_params)); + memcpy(dst->skip_mode_frame_idx, + src->skip_mode_frame_idx, + 2 * sizeof(uint8_t)); + memcpy(&dst->film_grain, + &src->film_grain, + sizeof(dst->film_grain)); + dst->coded_lossless = src->coded_lossless; + + if (src->slot_index >= 0x7f) { + mpp_err("av1d_ref_frame is vaild"); + return MPP_ERR_VALUE; + } + + dst->slot_index = src->slot_index; + dst->ref = src->ref; + dst->ref->ref_count++; + + mpp_buf_slot_get_prop(ctx->slots, src->slot_index, SLOT_FRAME, &dst->f); + impl_frm->buffer = NULL; //parser no need process hal buf + + return MPP_OK; +} + +static MPP_RET update_reference_list(Av1DecCtx *ctx) +{ + Av1Codec *s = ctx->priv_data; + const AV1FrameHeader *f = s->frame_header; + MPP_RET ret = MPP_OK; + + for (RK_S32 i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (f->refresh_frame_flags & (1 << i)) { + s->ref_s[i].valid = 1; + s->ref_s[i].frame_id = f->current_frame_id; + s->ref_s[i].upscaled_width = s->upscaled_width; + s->ref_s[i].frame_width = s->frame_width; + s->ref_s[i].frame_height = s->frame_height; + s->ref_s[i].render_width = s->render_width; + s->ref_s[i].render_height = s->render_height; + s->ref_s[i].frame_type = f->frame_type; + s->ref_s[i].subsampling_x = s->seq_header->color_config.subsampling_x; + s->ref_s[i].subsampling_y = s->seq_header->color_config.subsampling_y; + s->ref_s[i].bit_depth = s->bit_depth; + s->ref_s[i].order_hint = s->order_hint; + + memcpy(s->ref_s[i].loop_filter_ref_deltas, f->loop_filter_ref_deltas, + sizeof(f->loop_filter_ref_deltas)); + memcpy(s->ref_s[i].loop_filter_mode_deltas, f->loop_filter_mode_deltas, + sizeof(f->loop_filter_mode_deltas)); + memcpy(s->ref_s[i].feature_enabled, f->feature_enabled, + sizeof(f->feature_enabled)); + memcpy(s->ref_s[i].feature_value, f->feature_value, + sizeof(f->feature_value)); + } + } + + if (!f->show_existing_frame) { + RK_S32 lst2_buf_idx = f->ref_frame_idx[AV1_REF_FRAME_LAST2 - AV1_REF_FRAME_LAST]; + RK_S32 lst3_buf_idx = f->ref_frame_idx[AV1_REF_FRAME_LAST3 - AV1_REF_FRAME_LAST]; + RK_S32 gld_buf_idx = f->ref_frame_idx[AV1_REF_FRAME_GOLDEN - AV1_REF_FRAME_LAST]; + RK_S32 alt_buf_idx = f->ref_frame_idx[AV1_REF_FRAME_ALTREF - AV1_REF_FRAME_LAST]; + RK_S32 lst_buf_idx = f->ref_frame_idx[AV1_REF_FRAME_LAST - AV1_REF_FRAME_LAST]; + RK_S32 bwd_buf_idx = f->ref_frame_idx[AV1_REF_FRAME_BWDREF - AV1_REF_FRAME_LAST]; + RK_S32 alt2_buf_idx = f->ref_frame_idx[AV1_REF_FRAME_ALTREF2 - AV1_REF_FRAME_LAST]; + + s->cur_frame.ref->lst2_frame_offset = s->ref[lst2_buf_idx].order_hint; + s->cur_frame.ref->lst3_frame_offset = s->ref[lst3_buf_idx].order_hint; + s->cur_frame.ref->gld_frame_offset = s->ref[gld_buf_idx].order_hint; + s->cur_frame.ref->alt_frame_offset = s->ref[alt_buf_idx].order_hint; + s->cur_frame.ref->lst_frame_offset = s->ref[lst_buf_idx].order_hint; + s->cur_frame.ref->bwd_frame_offset = s->ref[bwd_buf_idx].order_hint; + s->cur_frame.ref->alt2_frame_offset = s->ref[alt2_buf_idx].order_hint; + } + + for (RK_S32 i = 0; i < AV1_NUM_REF_FRAMES; i++) { + av1d_dbg(AV1D_DBG_REF, "header->refresh_frame_flags = %d", + f->refresh_frame_flags); + if (f->refresh_frame_flags & (1 << i)) { + av1d_dbg(AV1D_DBG_REF, "av1 ref idx %d s->ref[%d].slot_index %d", + i, i, s->ref[i].slot_index); + if (s->ref[i].ref) + av1d_frame_unref(ctx, &s->ref[i]); + + if ((ret = av1d_frame_ref(ctx, &s->ref[i], &s->cur_frame)) < 0) { + mpp_err_f("Failed to update frame %d in reference list\n", i); + return ret; + } + } + } + return MPP_OK; +} + +static MPP_RET set_current_frame(Av1DecCtx *ctx) +{ + Av1Codec *s = ctx->priv_data; + AV1FrameIInfo *frame = &s->cur_frame; + const AV1FrameHeader *f = s->frame_header; + RK_U32 value; + + if (frame->ref) + av1d_frame_unref(ctx, frame); + + mpp_frame_set_meta(frame->f, NULL); + mpp_frame_set_width(frame->f, s->frame_width); + mpp_frame_set_height(frame->f, s->frame_height); + + /* + * rk3588, user can set 8bit for 10bit source. + * If user config 8bit output when input video is 10bti, + * here should set hor_stride according to 8bit. + */ + if (MPP_FRAME_FMT_IS_YUV_10BIT(ctx->pix_fmt)) + mpp_frame_set_hor_stride(frame->f, MPP_ALIGN(s->frame_width * s->bit_depth / 8, 8)); + else + mpp_frame_set_hor_stride(frame->f, MPP_ALIGN(s->frame_width, 8)); + + mpp_frame_set_ver_stride(frame->f, MPP_ALIGN(s->frame_height, 8)); + mpp_frame_set_errinfo(frame->f, 0); + mpp_frame_set_discard(frame->f, 0); + mpp_frame_set_pts(frame->f, s->pts); + mpp_frame_set_dts(frame->f, s->dts); + + mpp_frame_set_color_trc(frame->f, ctx->color_trc); + mpp_frame_set_color_primaries(frame->f, ctx->color_primaries); + mpp_frame_set_colorspace(frame->f, ctx->colorspace); + mpp_frame_set_color_range(frame->f, ctx->color_range); + + mpp_frame_set_mastering_display(frame->f, s->mastering_display); + mpp_frame_set_content_light(frame->f, s->content_light); + + if (MPP_FRAME_FMT_IS_FBC(ctx->cfg->base.out_fmt)) { + RK_U32 fbc_hdr_stride = MPP_ALIGN(ctx->width, 64); + + mpp_slots_set_prop(ctx->slots, SLOTS_HOR_ALIGN, mpp_align_16); + if (s->bit_depth == 10) { + if ((ctx->pix_fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP || + (ctx->pix_fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP_10BIT) + ctx->pix_fmt = MPP_FMT_YUV420SP_10BIT; + else + mpp_err("422p 10bit no support"); + } + + ctx->pix_fmt |= ctx->cfg->base.out_fmt & (MPP_FRAME_FBC_MASK); + mpp_frame_set_offset_x(frame->f, 0); + mpp_frame_set_offset_y(frame->f, 0); + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) + mpp_frame_set_ver_stride(frame->f, MPP_ALIGN(ctx->height, 8) + 28); + + if (*compat_ext_fbc_hdr_256_odd) + fbc_hdr_stride = MPP_ALIGN(ctx->width, 256) | 256; + + mpp_frame_set_fbc_hdr_stride(frame->f, fbc_hdr_stride); + } else if (MPP_FRAME_FMT_IS_TILE(ctx->cfg->base.out_fmt)) { + ctx->pix_fmt |= ctx->cfg->base.out_fmt & (MPP_FRAME_TILE_FLAG); + } + + if (s->is_hdr) + ctx->pix_fmt |= MPP_FRAME_HDR; + + mpp_frame_set_fmt(frame->f, ctx->pix_fmt); + + if (ctx->cfg->base.enable_thumbnail && ctx->hw_info && ctx->hw_info->cap_down_scale) + mpp_frame_set_thumbnail_en(frame->f, ctx->cfg->base.enable_thumbnail); + else + mpp_frame_set_thumbnail_en(frame->f, 0); + + value = 4; + mpp_slots_set_prop(ctx->slots, SLOTS_NUMERATOR, &value); + value = 1; + mpp_slots_set_prop(ctx->slots, SLOTS_DENOMINATOR, &value); + mpp_buf_slot_get_unused(ctx->slots, &frame->slot_index); + av1d_dbg(AV1D_DBG_REF, "get frame->slot_index %d", frame->slot_index); + mpp_buf_slot_set_prop(ctx->slots, frame->slot_index, SLOT_FRAME, frame->f); + mpp_buf_slot_set_flag(ctx->slots, frame->slot_index, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(ctx->slots, frame->slot_index, SLOT_HAL_OUTPUT); + + frame->ref = mpp_calloc(Av1RefInfo, 1); + if (!frame->ref) { + mpp_err("av1d ref info malloc fail"); + return MPP_ERR_NOMEM; + } + frame->ref->ref_count++; + frame->ref->is_intra_frame = !f->frame_type; + frame->ref->intra_only = (f->frame_type == 2); + frame->ref->is_output = 0; + frame->ref->invisible = (!f->show_frame && !f->showable_frame); + set_current_global_motion_params(s); + set_current_skip_mode_params(s); + set_current_coded_lossless_param(s); + set_current_read_grain_params(s); + + return MPP_OK; +} + +static const RK_U32 av1_unit_types[] = { + AV1_OBU_TEMPORAL_DELIMITER, + AV1_OBU_SEQUENCE_HEADER, + AV1_OBU_FRAME_HEADER, + AV1_OBU_TILE_GROUP, + AV1_OBU_METADATA, + AV1_OBU_FRAME, +}; + +MPP_RET av1d_parser_init(Av1DecCtx *ctx, ParserCfg *init) +{ + MPP_RET ret = MPP_OK; + RK_S32 i = 0; + av1d_dbg_func("enter ctx %p\n", ctx); + Av1Codec *s = mpp_calloc(Av1Codec, 1); + ctx->priv_data = (void*)s; + if (!ctx->priv_data) { + mpp_err("av1d codec context malloc fail"); + return MPP_ERR_NOMEM; + } + + s->seq_ref = mpp_calloc(AV1SeqHeader, 1); + + s->unit_types = av1_unit_types; + s->nb_unit_types = MPP_ARRAY_ELEMS(av1_unit_types); + ctx->packet_slots = init->packet_slots; + ctx->slots = init->frame_slots; + ctx->cfg = init->cfg; + ctx->hw_info = init->hw_info; + mpp_buf_slot_setup(ctx->slots, 25); + + mpp_env_get_u32("av1d_debug", &av1d_debug, 0); + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + mpp_frame_init(&s->ref[i].f); + if (!s->ref[i].f) { + mpp_err("Failed to allocate frame buffer %d\n", i); + return MPP_ERR_NOMEM; + } + s->ref[i].slot_index = 0x7f; + s->ref[i].ref = NULL; + } + + mpp_frame_init(&s->cur_frame.f); + s->cur_frame.ref = NULL; + s->cur_frame.slot_index = 0xff; + if (!s->cur_frame.f) { + mpp_err("Failed to allocate frame buffer %d\n", i); + return MPP_ERR_NOMEM; + } + s->cdfs = &s->default_cdfs; + s->cdfs_ndvc = &s->default_cdfs_ndvc; + av1d_set_default_cdfs(s->cdfs, s->cdfs_ndvc); + + return MPP_OK; + + av1d_dbg_func("leave ctx %p\n", ctx); + + return ret; +} + +MPP_RET av1d_parser_deinit(Av1DecCtx *ctx) +{ + MPP_RET ret = MPP_OK; + RK_U32 i = 0; + + Av1Codec *s = ctx->priv_data; + for ( i = 0; i < MPP_ARRAY_ELEMS(s->ref); i++) { + if (s->ref[i].ref) { + av1d_frame_unref(ctx, &s->ref[i]); + } + mpp_frame_deinit(&s->ref[i].f); + s->ref[i].f = NULL; + } + if (s->cur_frame.ref) { + av1d_frame_unref(ctx, &s->cur_frame); + } + mpp_frame_deinit(&s->cur_frame.f); + + av1d_fragment_reset(&s->current_obu); + MPP_FREE(s->current_obu.units); + MPP_FREE(s->frame_header_data); + MPP_FREE(s->seq_ref); + MPP_FREE((s->hdr_dynamic_meta)); + MPP_FREE(ctx->priv_data); + return MPP_OK; + + av1d_dbg_func("leave ctx %p\n", ctx); + + return ret; +} + +static const unsigned char av1_remap_lr_type[4] = { + AV1_RESTORE_NONE, + AV1_RESTORE_SWITCHABLE, + AV1_RESTORE_WIENER, + AV1_RESTORE_SGRPROJ +}; +static MPP_RET av1d_parser2_syntax(Av1DecCtx *ctx) +{ + RK_S32 i, j, loop_cnt, uses_lr; + RK_U8 is_rk3588; + Av1Codec *h = ctx->priv_data; + const AV1SeqHeader *seq = h->seq_header; + const AV1FrameHeader *frame_header = h->frame_header; + const AV1FilmGrainParams *film_grain = &h->cur_frame.film_grain; + RK_S32 apply_grain = film_grain->apply_grain; + + DXVA_PicParams_AV1 *pp = &ctx->pic_params; + memset(pp, 0, sizeof(*pp)); + + pp->width = h->frame_width; + pp->height = h->frame_height; + + pp->max_width = seq->max_frame_width_minus_1 + 1; + pp->max_height = seq->max_frame_height_minus_1 + 1; + + pp->CurrPic.Index7Bits = h->cur_frame.slot_index; + pp->CurrPicTextureIndex = h->cur_frame.slot_index; + pp->superres_denom = frame_header->use_superres ? frame_header->coded_denom : AV1_SUPERRES_NUM; + pp->use_superres = frame_header->use_superres; + pp->bitdepth = h->bit_depth; + pp->seq_profile = seq->seq_profile; + pp->frame_header_size = h->frame_header_size; + + /* Tiling info */ + pp->tiles.cols = frame_header->tile_cols; + pp->tiles.rows = frame_header->tile_rows; + pp->tiles.context_update_id = frame_header->context_update_tile_id; + + for (i = 0; i < pp->tiles.cols; i++) + pp->tiles.widths[i] = frame_header->width_in_sbs_minus_1[i] + 1; + + for (i = 0; i < pp->tiles.rows; i++) + pp->tiles.heights[i] = frame_header->height_in_sbs_minus_1[i] + 1; + + for (i = 0; i < AV1_MAX_TILES; i++) { + pp->tiles.tile_offset_start[i] = h->tile_offset_start[i]; + pp->tiles.tile_offset_end[i] = h->tile_offset_end[i]; + } + + pp->tiles.tile_sz_mag = h->frame_header->tile_size_bytes_minus1; + /* Coding tools */ + pp->coding.current_operating_point = seq->operating_point_idc[h->operating_point_idc]; + pp->coding.use_128x128_superblock = seq->use_128x128_superblock; + pp->coding.intra_edge_filter = seq->enable_intra_edge_filter; + pp->coding.interintra_compound = seq->enable_interintra_compound; + pp->coding.masked_compound = seq->enable_masked_compound; + pp->coding.warped_motion = frame_header->allow_warped_motion; + pp->coding.dual_filter = seq->enable_dual_filter; + pp->coding.jnt_comp = seq->enable_jnt_comp; + pp->coding.screen_content_tools = frame_header->allow_screen_content_tools; + pp->coding.integer_mv = frame_header->force_integer_mv; + + pp->coding.cdef_en = seq->enable_cdef; + pp->coding.restoration = seq->enable_restoration; + pp->coding.film_grain_en = seq->film_grain_params_present ;//&& !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN); + pp->coding.intrabc = frame_header->allow_intrabc; + pp->coding.high_precision_mv = frame_header->allow_high_precision_mv; + pp->coding.switchable_motion_mode = frame_header->is_motion_mode_switchable; + pp->coding.filter_intra = seq->enable_filter_intra; + pp->coding.disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf; + pp->coding.disable_cdf_update = frame_header->disable_cdf_update; + pp->coding.reference_mode = frame_header->reference_select; + pp->coding.skip_mode = frame_header->skip_mode_present; + pp->coding.reduced_tx_set = frame_header->reduced_tx_set; + pp->coding.superres = frame_header->use_superres; + pp->coding.tx_mode = frame_header->tx_mode; + pp->coding.use_ref_frame_mvs = frame_header->use_ref_frame_mvs; + pp->coding.enable_ref_frame_mvs = seq->enable_ref_frame_mvs; + pp->coding.reference_frame_update = 1; // 0 for show_existing_frame with key frames, but those are not passed to the hwaccel + pp->coding.error_resilient_mode = frame_header->error_resilient_mode; + + /* Format & Picture Info flags */ + pp->format.frame_type = frame_header->frame_type; + pp->format.show_frame = frame_header->show_frame; + pp->format.showable_frame = frame_header->showable_frame; + pp->format.subsampling_x = seq->color_config.subsampling_x; + pp->format.subsampling_y = seq->color_config.subsampling_y; + pp->format.mono_chrome = seq->color_config.mono_chrome; + pp->coded_lossless = h->cur_frame.coded_lossless; + pp->all_lossless = h->all_lossless; + /* References */ + pp->primary_ref_frame = frame_header->primary_ref_frame; + pp->enable_order_hint = seq->enable_order_hint; + pp->order_hint = frame_header->order_hint; + pp->order_hint_bits = seq->enable_order_hint ? seq->order_hint_bits_minus_1 + 1 : 0; + + pp->ref_frame_valued = frame_header->ref_frame_valued; + for (i = 0; i < AV1_REFS_PER_FRAME; i++) + pp->ref_frame_idx[i] = frame_header->ref_frame_idx[i]; + + memset(pp->RefFrameMapTextureIndex, 0xFF, sizeof(pp->RefFrameMapTextureIndex)); + is_rk3588 = mpp_get_soc_type() == ROCKCHIP_SOC_RK3588; + loop_cnt = is_rk3588 ? AV1_REFS_PER_FRAME : AV1_NUM_REF_FRAMES; + for (i = 0; i < loop_cnt; i++) { + int8_t ref_idx = frame_header->ref_frame_idx[i]; + AV1FrameIInfo *ref_frame; + Av1RefInfo *ref_i; + + if (is_rk3588) + ref_frame = &h->ref[ref_idx]; + else + ref_frame = &h->ref[i]; + ref_i = ref_frame->ref; + + if (ref_frame->f) { + pp->frame_refs[i].width = mpp_frame_get_width(ref_frame->f); + pp->frame_refs[i].height = mpp_frame_get_height(ref_frame->f);; + } + pp->frame_refs[i].Index = ref_frame->slot_index; + pp->frame_refs[i].order_hint = ref_frame->order_hint; + if (ref_i) { + pp->frame_refs[i].lst_frame_offset = ref_i->lst_frame_offset; + pp->frame_refs[i].lst2_frame_offset = ref_i->lst2_frame_offset; + pp->frame_refs[i].lst3_frame_offset = ref_i->lst3_frame_offset; + pp->frame_refs[i].gld_frame_offset = ref_i->gld_frame_offset; + pp->frame_refs[i].bwd_frame_offset = ref_i->bwd_frame_offset; + pp->frame_refs[i].alt2_frame_offset = ref_i->alt2_frame_offset; + pp->frame_refs[i].alt_frame_offset = ref_i->alt_frame_offset ; + pp->frame_refs[i].is_intra_frame = ref_i->is_intra_frame; + pp->frame_refs[i].intra_only = ref_i->intra_only; + } + /* Global Motion */ + pp->frame_refs[i].wminvalid = (h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].wmtype == AV1_WARP_MODEL_IDENTITY); + pp->frame_refs[i].wmtype = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].wmtype; + for (j = 0; j < 6; ++j) { + pp->frame_refs[i].wmmat[j] = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].wmmat[j]; + pp->frame_refs[i].wmmat_val[j] = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].wmmat_val[j]; + } + pp->frame_refs[i].alpha = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].alpha; + pp->frame_refs[i].beta = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].beta; + pp->frame_refs[i].gamma = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].gamma; + pp->frame_refs[i].delta = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i].delta; + } + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + AV1FrameIInfo *ref_frame = &h->ref[i]; + + pp->frame_ref_state[i].valid = h->ref_s[i].valid ; + pp->frame_ref_state[i].frame_id = h->ref_s[i].frame_id ; + pp->frame_ref_state[i].upscaled_width = h->ref_s[i].upscaled_width; + pp->frame_ref_state[i].frame_width = h->ref_s[i].frame_width ; + pp->frame_ref_state[i].frame_height = h->ref_s[i].frame_height ; + pp->frame_ref_state[i].render_width = h->ref_s[i].render_width ; + pp->frame_ref_state[i].render_height = h->ref_s[i].render_height ; + pp->frame_ref_state[i].frame_type = h->ref_s[i].frame_type ; + pp->frame_ref_state[i].subsampling_x = h->ref_s[i].subsampling_x ; + pp->frame_ref_state[i].subsampling_y = h->ref_s[i].subsampling_y ; + pp->frame_ref_state[i].bit_depth = h->ref_s[i].bit_depth ; + pp->frame_ref_state[i].order_hint = h->ref_s[i].order_hint ; + + pp->ref_order_hint[i] = frame_header->ref_order_hint[i]; + + if (ref_frame->slot_index < 0x7f) + pp->RefFrameMapTextureIndex[i] = ref_frame->slot_index; + else + pp->RefFrameMapTextureIndex[i] = 0xff; + } + + /* Loop filter parameters */ + pp->loop_filter.filter_level[0] = frame_header->loop_filter_level[0]; + pp->loop_filter.filter_level[1] = frame_header->loop_filter_level[1]; + pp->loop_filter.filter_level_u = frame_header->loop_filter_level[2]; + pp->loop_filter.filter_level_v = frame_header->loop_filter_level[3]; + pp->loop_filter.sharpness_level = frame_header->loop_filter_sharpness; + pp->loop_filter.mode_ref_delta_enabled = frame_header->loop_filter_delta_enabled; + pp->loop_filter.mode_ref_delta_update = frame_header->loop_filter_delta_update; + pp->loop_filter.delta_lf_multi = frame_header->delta_lf_multi; + pp->loop_filter.delta_lf_present = frame_header->delta_lf_present; + pp->loop_filter.delta_lf_res = frame_header->delta_lf_res; + + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + pp->loop_filter.ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; + } + + pp->loop_filter.mode_deltas[0] = frame_header->loop_filter_mode_deltas[0]; + pp->loop_filter.mode_deltas[1] = frame_header->loop_filter_mode_deltas[1]; + pp->loop_filter.frame_restoration_type[0] = av1_remap_lr_type[frame_header->lr_type[0]]; + pp->loop_filter.frame_restoration_type[1] = av1_remap_lr_type[frame_header->lr_type[1]]; + pp->loop_filter.frame_restoration_type[2] = av1_remap_lr_type[frame_header->lr_type[2]]; + uses_lr = frame_header->lr_type[0] || frame_header->lr_type[1] || frame_header->lr_type[2]; + pp->loop_filter.log2_restoration_unit_size[0] = uses_lr ? (1 + frame_header->lr_unit_shift) : 3; + pp->loop_filter.log2_restoration_unit_size[1] = uses_lr ? (1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift) : 3; + pp->loop_filter.log2_restoration_unit_size[2] = uses_lr ? (1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift) : 3; + + /* Quantization */ + pp->quantization.delta_q_present = frame_header->delta_q_present; + pp->quantization.delta_q_res = frame_header->delta_q_res; + pp->quantization.base_qindex = frame_header->base_q_idx; + pp->quantization.y_dc_delta_q = frame_header->delta_q_y_dc; + pp->quantization.u_dc_delta_q = frame_header->delta_q_u_dc; + pp->quantization.v_dc_delta_q = frame_header->delta_q_v_dc; + pp->quantization.u_ac_delta_q = frame_header->delta_q_u_ac; + pp->quantization.v_ac_delta_q = frame_header->delta_q_v_ac; + pp->quantization.using_qmatrix = frame_header->using_qmatrix; + pp->quantization.qm_y = frame_header->using_qmatrix ? frame_header->qm_y : 0xFF; + pp->quantization.qm_u = frame_header->using_qmatrix ? frame_header->qm_u : 0xFF; + pp->quantization.qm_v = frame_header->using_qmatrix ? frame_header->qm_v : 0xFF; + + /* Cdef parameters */ + pp->cdef.damping = frame_header->cdef_damping_minus_3; + pp->cdef.bits = frame_header->cdef_bits; + for (i = 0; i < 8; i++) { + pp->cdef.y_strengths[i].primary = frame_header->cdef_y_pri_strength[i]; + pp->cdef.y_strengths[i].secondary = frame_header->cdef_y_sec_strength[i]; + pp->cdef.uv_strengths[i].primary = frame_header->cdef_uv_pri_strength[i]; + pp->cdef.uv_strengths[i].secondary = frame_header->cdef_uv_sec_strength[i]; + } + + /* Misc flags */ + pp->interp_filter = frame_header->interpolation_filter; + + /* Segmentation */ + pp->segmentation.enabled = frame_header->segmentation_enabled; + pp->segmentation.update_map = frame_header->segmentation_update_map; + pp->segmentation.update_data = frame_header->segmentation_update_data; + pp->segmentation.temporal_update = frame_header->segmentation_temporal_update; + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + pp->segmentation.feature_mask[i] |= frame_header->feature_enabled[i][j] << j; + pp->segmentation.feature_data[i][j] = frame_header->feature_value[i][j]; + } + } + pp->segmentation.last_active = frame_header->segmentation_id_last_active; + pp->segmentation.preskip = frame_header->segmentation_id_preskip; + + /* Film grain */ + pp->film_grain.matrix_coefficients = seq->color_config.matrix_coefficients; + if (apply_grain) { + pp->film_grain.apply_grain = 1; + pp->film_grain.scaling_shift_minus8 = film_grain->grain_scaling_minus_8; + pp->film_grain.chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma; + pp->film_grain.ar_coeff_lag = film_grain->ar_coeff_lag; + pp->film_grain.ar_coeff_shift_minus6 = film_grain->ar_coeff_shift_minus_6; + pp->film_grain.grain_scale_shift = film_grain->grain_scale_shift; + pp->film_grain.overlap_flag = film_grain->overlap_flag; + pp->film_grain.clip_to_restricted_range = film_grain->clip_to_restricted_range; + pp->film_grain.matrix_coeff_is_identity = (seq->color_config.matrix_coefficients == MPP_FRAME_SPC_RGB); + + pp->film_grain.grain_seed = film_grain->grain_seed; + pp->film_grain.update_grain = film_grain->update_grain; + pp->film_grain.num_y_points = film_grain->num_y_points; + for (i = 0; i < film_grain->num_y_points; i++) { + pp->film_grain.scaling_points_y[i][0] = film_grain->point_y_value[i]; + pp->film_grain.scaling_points_y[i][1] = film_grain->point_y_scaling[i]; + } + pp->film_grain.num_cb_points = film_grain->num_cb_points; + for (i = 0; i < film_grain->num_cb_points; i++) { + pp->film_grain.scaling_points_cb[i][0] = film_grain->point_cb_value[i]; + pp->film_grain.scaling_points_cb[i][1] = film_grain->point_cb_scaling[i]; + } + pp->film_grain.num_cr_points = film_grain->num_cr_points; + for (i = 0; i < film_grain->num_cr_points; i++) { + pp->film_grain.scaling_points_cr[i][0] = film_grain->point_cr_value[i]; + pp->film_grain.scaling_points_cr[i][1] = film_grain->point_cr_scaling[i]; + } + for (i = 0; i < 24; i++) { + pp->film_grain.ar_coeffs_y[i] = film_grain->ar_coeffs_y_plus_128[i]; + } + for (i = 0; i < 25; i++) { + pp->film_grain.ar_coeffs_cb[i] = film_grain->ar_coeffs_cb_plus_128[i]; + pp->film_grain.ar_coeffs_cr[i] = film_grain->ar_coeffs_cr_plus_128[i]; + } + pp->film_grain.cb_mult = film_grain->cb_mult; + pp->film_grain.cb_luma_mult = film_grain->cb_luma_mult; + pp->film_grain.cr_mult = film_grain->cr_mult; + pp->film_grain.cr_luma_mult = film_grain->cr_luma_mult; + pp->film_grain.cb_offset = film_grain->cb_offset; + pp->film_grain.cr_offset = film_grain->cr_offset; + pp->film_grain.cr_offset = film_grain->cr_offset; + } + pp->upscaled_width = h->upscaled_width; + pp->frame_to_show_map_idx = frame_header->frame_to_show_map_idx; + pp->show_existing_frame = frame_header->show_existing_frame; + pp->frame_tag_size = h->frame_tag_size; + pp->skip_ref0 = h->skip_ref0; + pp->skip_ref1 = h->skip_ref1; + pp->refresh_frame_flags = frame_header->refresh_frame_flags; + + pp->cdfs = h->cdfs; + pp->cdfs_ndvc = h->cdfs_ndvc; + pp->tile_cols_log2 = frame_header->tile_cols_log2; + pp->tile_rows_log2 = frame_header->tile_rows_log2; + + return MPP_OK; +} + +MPP_RET av1d_parser_frame(Av1DecCtx *ctx, HalDecTask *task) +{ + RK_U8 *data = NULL; + RK_S32 size = 0; + Av1Codec *s = ctx->priv_data; + AV1TileGroup *raw_tile_group = NULL; + MPP_RET ret = MPP_OK; + + + av1d_dbg_func("enter ctx %p\n", ctx); + task->valid = 0; + + data = (RK_U8 *)mpp_packet_get_pos(ctx->pkt); + size = (RK_S32)mpp_packet_get_length(ctx->pkt); + + s->pts = mpp_packet_get_pts(ctx->pkt); + s->dts = mpp_packet_get_dts(ctx->pkt); + + s->current_obu.data = data; + s->current_obu.data_size = size; + s->tile_offset = 0; + ret = av1d_get_fragment_units(&s->current_obu); + if (ret < 0) { + return ret; + } + ret = av1d_read_fragment_uints(s, &s->current_obu); + if (ret < 0) { + return ret; + } + + for (RK_S32 i = 0; i < s->current_obu.nb_units; i++) { + Av1ObuUnit *unit = &s->current_obu.units[i]; + AV1OBU *obu = &unit->obu; + const AV1OBUHeader *header = &obu->header; + if (!unit->data || !unit->data_size) + continue; + switch (unit->type) { + case AV1_OBU_SEQUENCE_HEADER: + memcpy(s->seq_ref, &obu->payload.seq_header, sizeof(AV1SeqHeader)); + s->seq_header = s->seq_ref; + ret = av1d_set_context_with_seq(ctx, s->seq_header); + if (ret < 0) { + mpp_err_f("Failed to set context.\n"); + s->seq_header = NULL; + goto end; + } + + s->operating_point_idc = s->seq_header->operating_point_idc[s->operating_point]; + + ret = get_pixel_format(ctx); + if (ret < 0) { + mpp_err_f("Failed to get pixel format.\n"); + s->seq_header = NULL; + goto end; + } + break; + case AV1_OBU_REDUNDANT_FRAME_HEADER: + if (s->frame_header) + break; + // fall-through + case AV1_OBU_FRAME: + case AV1_OBU_FRAME_HEADER: + if (!s->seq_header) { + mpp_err_f("Missing Sequence Header.\n"); + ret = MPP_ERR_VALUE; + goto end; + } + + if (unit->type == AV1_OBU_FRAME) + s->frame_header = &obu->payload.frame.header; + else + s->frame_header = &obu->payload.frame_header; + + if (s->frame_header->show_existing_frame) { + if (s->cur_frame.ref) { + av1d_frame_unref(ctx, &s->cur_frame); + } + + ret = av1d_frame_ref(ctx, &s->cur_frame, + &s->ref[s->frame_header->frame_to_show_map_idx]); + + if (ret < 0) { + mpp_err_f("Failed to get reference frame.\n"); + goto end; + } + + ret = update_reference_list(ctx); + if (ret < 0) { + mpp_err_f("Failed to update reference list.\n"); + goto end; + } + ret = set_output_frame(ctx); + if (ret < 0) + mpp_err_f("Set output frame error.\n"); + + s->frame_header = NULL; + + goto end; + } + ret = set_current_frame(ctx); + if (ret < 0) { + mpp_err_f("Get current frame error\n"); + goto end; + } + s->cur_frame.spatial_id = header->spatial_id; + s->cur_frame.temporal_id = header->temporal_id; + s->cur_frame.order_hint = s->frame_header->order_hint; + + if (unit->type != AV1_OBU_FRAME) + break; + // fall-through + case AV1_OBU_TILE_GROUP: + if (!s->frame_header) { + mpp_err_f("Missing Frame Header.\n"); + ret = MPP_ERR_VALUE; + goto end; + } + + if (unit->type == AV1_OBU_FRAME) + raw_tile_group = &obu->payload.frame.tile_group; + else + raw_tile_group = &obu->payload.tile_group; + + ret = get_tiles_info(ctx, raw_tile_group); + if (ret < 0) + goto end; + + break; + case AV1_OBU_TILE_LIST: + case AV1_OBU_TEMPORAL_DELIMITER: + case AV1_OBU_PADDING: + case AV1_OBU_METADATA: + break; + default: + av1d_dbg(AV1D_DBG_HEADER, "Unknown obu type: %d (%d bits).\n", + unit->type, unit->data_size); + } + // the last tile in the tile group + if (raw_tile_group && (s->tile_num == raw_tile_group->tg_end + 1)) { + RK_U32 j; + + av1d_parser2_syntax(ctx); + task->syntax.data = (void*)&ctx->pic_params; + task->syntax.number = 1; + task->valid = 1; + task->output = s->cur_frame.slot_index; + task->input_packet = ctx->pkt; + + for (j = 0; j < AV1_REFS_PER_FRAME; j++) { + int8_t ref_idx = s->frame_header->ref_frame_idx[j]; + if (s->ref[ref_idx].slot_index < 0x7f) { + mpp_buf_slot_set_flag(ctx->slots, s->ref[ref_idx].slot_index, SLOT_HAL_INPUT); + MppFrame mframe = NULL; + task->refer[j] = s->ref[ref_idx].slot_index; + mpp_buf_slot_get_prop(ctx->slots, task->refer[j], SLOT_FRAME_PTR, &mframe); + if (mframe) + task->flags.ref_err |= mpp_frame_get_errinfo(mframe); + } else { + task->refer[j] = -1; + } + } + ret = update_reference_list(ctx); + if (ret < 0) { + mpp_err_f("Failed to update reference list.\n"); + goto end; + } + + if (s->frame_header->show_frame) { + ret = set_output_frame(ctx); + if (ret < 0) { + mpp_err_f("Set output frame error\n"); + goto end; + } + } + raw_tile_group = NULL; + s->frame_header = NULL; + } + } + + if (s->eos) { + task->flags.eos = 1; + } +end: + av1d_fragment_reset(&s->current_obu); + if (ret < 0) + s->frame_header = NULL; + + av1d_dbg_func("leave ctx %p\n", ctx); + return ret; +} + +MPP_RET av1d_get_cdfs(Av1Codec *ctx, RK_U32 ref_idx) +{ + ctx->cdfs = &ctx->cdfs_last[ref_idx]; + ctx->cdfs_ndvc = &ctx->cdfs_last_ndvc[ref_idx]; + + return MPP_OK; +} + +MPP_RET av1d_store_cdfs(Av1Codec *ctx, RK_U32 refresh_frame_flags) +{ + RK_U32 i; + + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (refresh_frame_flags & (1 << i)) { + if (&ctx->cdfs_last[i] != ctx->cdfs) { + ctx->cdfs_last[i] = *ctx->cdfs; + ctx->cdfs_last_ndvc[i] = *ctx->cdfs_ndvc; + } + } + } + + return MPP_OK; +} + +MPP_RET av1d_parser_update(Av1DecCtx *ctx, void *info) +{ + Av1Codec* c_ctx = (Av1Codec*)ctx->priv_data; + DecCbHalDone *cb = (DecCbHalDone*)info; + RK_U8 *data = (RK_U8*)cb->task; + RK_U32 i; + const RK_U32 mv_cdf_offset = offsetof(AV1CDFs, mv_cdf); + const RK_U32 mv_cdf_size = sizeof(Av1MvCDFs); + const RK_U32 mv_cdf_end_offset = mv_cdf_offset + mv_cdf_size; + const RK_U32 cdf_size = sizeof(AV1CDFs); + + av1d_dbg_func("enter ctx %p\n", ctx); + if (!c_ctx->disable_frame_end_update_cdf) { + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (c_ctx->refresh_frame_flags & (1 << i)) { + /* 1. get cdfs */ + av1d_get_cdfs(c_ctx, i); + { + RK_U8 *cdf_base = (RK_U8 *)c_ctx->cdfs; + RK_U8 *cdf_ndvc_base = (RK_U8 *)c_ctx->cdfs_ndvc; + /* 2. read cdfs from memory*/ + if (c_ctx->frame_is_intra) { + memcpy(cdf_base, data, mv_cdf_offset); + // Read intrabc MV context + memcpy(cdf_ndvc_base, data + mv_cdf_offset, mv_cdf_size); + memcpy(cdf_base + mv_cdf_end_offset, data + mv_cdf_end_offset, + cdf_size - mv_cdf_end_offset); + } else { + memcpy(cdf_base, data, cdf_size); + } + } + /* 3. store cdfs*/ + av1d_store_cdfs(c_ctx, c_ctx->refresh_frame_flags); + break; + } + } + } + + av1d_dbg_func("leave ctx %p\n", ctx); + return MPP_OK; +} + +MPP_RET av1d_paser_reset(Av1DecCtx *ctx) +{ + (void)ctx; + MPP_RET ret = MPP_OK; + RK_U32 i = 0; + Av1Codec *s = ctx->priv_data; + + av1d_dbg_func("enter ctx %p\n", ctx); + for ( i = 0; i < MPP_ARRAY_ELEMS(s->ref); i++) { + AV1FrameIInfo *f = &s->ref[i]; + + if (f->ref) + av1d_frame_unref(ctx, &s->ref[i]); + } + + if (s->cur_frame.ref) { + av1d_frame_unref(ctx, &s->cur_frame); + } + + ctx->frame_header_cnt = 0; + ctx->stream_offset = 0; + ctx->eos = 0; + + av1d_dbg_func("leave ctx %p\n", ctx); + return ret; +} + +RK_S32 av1d_split_frame(Av1DecCtx *ctx, + RK_U8 **out_data, RK_S32 *out_size, + RK_U8 *data, RK_S32 data_size) +{ + RK_S32 err = MPP_NOK; + uint8_t *ptr = data, *end = data + data_size; + av1d_dbg_func("enter ctx %p\n", ctx); + + *out_data = data; + + while (ptr < end) { + AV1OBUHeader m_hdr; + BitReadCtx_t m_gb, *gb = &m_gb; + RK_U64 obu_size = 0, obu_length = 0; + + memset(&m_hdr, 0, sizeof(m_hdr)); + mpp_set_bitread_ctx(gb, ptr, data_size); + + err = av1d_read_obu_header(gb, &m_hdr); + if (err < 0) + break; + if (m_hdr.obu_has_size_field) + obu_size = m_hdr.obu_filed_size; + else + obu_size = data_size - 1 - m_hdr.obu_extension_flag; + + obu_length = mpp_get_bits_count(gb) / 8 + obu_size; + if (obu_length > (RK_U64)data_size) + break; + + av1d_dbg(AV1D_DBG_STRMIN, "obu_type: %d, temporal_id: %d, spatial_id: %d, payload size: %d\n", + m_hdr.obu_type, m_hdr.temporal_id, m_hdr.spatial_id, obu_size); + + if (m_hdr.obu_type == AV1_OBU_FRAME_HEADER || + m_hdr.obu_type == AV1_OBU_FRAME || + ((m_hdr.obu_type == AV1_OBU_TEMPORAL_DELIMITER || + m_hdr.obu_type == AV1_OBU_METADATA || + m_hdr.obu_type == AV1_OBU_SEQUENCE_HEADER) + && ctx->frame_header_cnt)) + ctx->frame_header_cnt ++; + if (ctx->frame_header_cnt == 2) { + *out_size = (RK_S32)(ptr - data); + ctx->is_new_frame = 1; + ctx->frame_header_cnt = 0; + return ptr - data; + } + if (m_hdr.obu_type == AV1_OBU_FRAME) { + ptr += obu_length; + data_size -= obu_length; + *out_size = (RK_S32)(ptr - data); + ctx->is_new_frame = 1; + ctx->frame_header_cnt = 0; + return ptr - data; + } + ptr += obu_length; + data_size -= obu_length; + } + RK_S32 out_len = (RK_S32)(ptr - data); + *out_size = out_len; + + av1d_dbg_func("leave ctx %p\n", ctx); + return out_len; +} + +MPP_RET av1d_get_frame_stream(Av1DecCtx *ctx, RK_U8 *buf, RK_S32 length) +{ + MPP_RET ret = MPP_OK; + av1d_dbg_func("enter ctx %p\n", ctx); + RK_S32 buff_size = 0; + RK_U8 *data = NULL; + RK_S32 size = 0; + RK_S32 offset = ctx->stream_offset; + + data = (RK_U8 *)mpp_packet_get_data(ctx->pkt); + size = (RK_S32)mpp_packet_get_size(ctx->pkt); + + if ((length + offset) > size) { + mpp_packet_deinit(&ctx->pkt); + buff_size = length + offset + 10 * 1024; + data = mpp_realloc(data, RK_U8, buff_size); + mpp_packet_init(&ctx->pkt, (void *)data, buff_size); + mpp_packet_set_size(ctx->pkt, buff_size); + ctx->stream_size = buff_size; + } + + memcpy(data + offset, buf, length); + ctx->stream_offset += length; + mpp_packet_set_length(ctx->pkt, ctx->stream_offset); + + av1d_dbg_func("leave ctx %p\n", ctx); + return ret; +} + +MPP_RET av1d_set_context_with_seq(Av1DecCtx *ctx, const AV1SeqHeader *seq) +{ + RK_S32 width = seq->max_frame_width_minus_1 + 1; + RK_S32 height = seq->max_frame_height_minus_1 + 1; + + ctx->profile = seq->seq_profile; + ctx->level = seq->seq_level_idx[0]; + + ctx->color_range = + seq->color_config.color_range ? MPP_FRAME_RANGE_JPEG : MPP_FRAME_RANGE_MPEG; + ctx->color_primaries = seq->color_config.color_primaries; + ctx->colorspace = seq->color_config.matrix_coefficients; + ctx->color_trc = seq->color_config.transfer_characteristics; + + switch (seq->color_config.chroma_sample_position) { + case AV1_CSP_VERTICAL: + ctx->chroma_sample_location = MPP_CHROMA_LOC_LEFT; + break; + case AV1_CSP_COLOCATED: + ctx->chroma_sample_location = MPP_CHROMA_LOC_TOPLEFT; + break; + } + // Update width and height if they have changed. + if (ctx->width != width || ctx->height != height) { + ctx->width = width; + ctx->height = height; + } + return MPP_OK; +} diff --git a/mpp/codec/dec/av1/av1d_parser.h b/mpp/codec/dec/av1/av1d_parser.h new file mode 100644 index 000000000..6d9c3813b --- /dev/null +++ b/mpp/codec/dec/av1/av1d_parser.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef AV1D_PARSER_H +#define AV1D_PARSER_H + +#include + +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_frame.h" +#include "parser_api.h" + +#include "av1d_ctx.h" +#include "av1d_syntax.h" +#include "av1d_common.h" + +extern RK_U32 av1d_debug; + +#define AV1D_DBG_FUNCTION (0x00000001) +#define AV1D_DBG_HEADER (0x00000002) +#define AV1D_DBG_REF (0x00000004) +#define AV1D_DBG_STRMIN (0x00000008) +#define AV1D_DBG_DUMP_RPU (0x10000000) + +#define av1d_dbg(flag, fmt, ...) mpp_dbg_f(av1d_debug, flag, fmt, ##__VA_ARGS__) +#define av1d_dbg_func(fmt, ...) av1d_dbg(AV1D_DBG_FUNCTION, fmt, ## __VA_ARGS__) + +//!< function return check +#define FUN_CHECK(val)\ +do{\ +if ((val) < 0) {\ + av1d_dbg_func("Function error(%d).\n", __LINE__); \ + return (val); \ +}} while (0) + +typedef struct Av1DecContext_t { + void *priv_data; // Av1Codec + + MppFrameFormat pix_fmt; + MppFrameColorSpace colorspace; + MppFrameColorRange color_range; + MppFrameColorPrimaries color_primaries; + MppFrameColorTransferCharacteristic color_trc; + MppFrameChromaLocation chroma_sample_location; + + RK_S32 width, height; + RK_S32 profile, level; + MppPacket pkt; + DXVA_PicParams_AV1 pic_params; + + // config info + MppBufSlots slots; + MppBufSlots packet_slots; + MppDecCfgSet *cfg; + HalDecTask *task; + const MppDecHwCap *hw_info; + + // split info + RK_U32 frame_header_cnt; + RK_U32 is_new_frame; + RK_U8 *stream_data; + RK_U32 stream_size; + RK_U32 stream_offset; + + RK_S32 eos; + MppFrameFormat usr_set_fmt; +} Av1DecCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET av1d_parser_init(Av1DecCtx *ctx, ParserCfg *init); +MPP_RET av1d_parser_deinit(Av1DecCtx *ctx); +MPP_RET av1d_parser_frame(Av1DecCtx *ctx, HalDecTask *in_task); +MPP_RET av1d_parser_update(Av1DecCtx *ctx, void *info); +MPP_RET av1d_paser_reset(Av1DecCtx *ctx); +RK_S32 av1d_split_frame(Av1DecCtx *ctx, RK_U8 **out_data, RK_S32 *out_size, + RK_U8 *data, RK_S32 size); +MPP_RET av1d_get_frame_stream(Av1DecCtx *ctx, RK_U8 *buf, RK_S32 length); +MPP_RET av1d_set_context_with_seq(Av1DecCtx *ctx, const AV1SeqHeader *seq); + +#ifdef __cplusplus +} +#endif + +#endif // AV1D_PARSER_H diff --git a/mpp/codec/dec/avs/CMakeLists.txt b/mpp/codec/dec/avs/CMakeLists.txt new file mode 100644 index 000000000..562176f35 --- /dev/null +++ b/mpp/codec/dec/avs/CMakeLists.txt @@ -0,0 +1,8 @@ +# vim: syntax=cmake +include_directories(.) + +# avs decoder sourse +add_library(avsd_api OBJECT + avsd_api.c + avsd_parse.c + ) diff --git a/mpp/codec/dec/avs/avsd_api.c b/mpp/codec/dec/avs/avsd_api.c new file mode 100644 index 000000000..c72b3448e --- /dev/null +++ b/mpp/codec/dec/avs/avsd_api.c @@ -0,0 +1,391 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "avsd_api" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_packet_impl.h" + +#include "mpp_parser.h" +#include "avsd_syntax.h" +#include "avsd_parse.h" +#include "mpp_dec_cb_param.h" + +/*! +*********************************************************************** +* \brief +* free all buffer +*********************************************************************** +*/ +MPP_RET avsd_deinit(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + + INP_CHECK(ret, !decoder); + AVSD_PARSE_TRACE("In."); + + mpp_packet_deinit(&p_dec->task_pkt); + MPP_FREE(p_dec->streambuf); + MPP_FREE(p_dec->mem); + +__RETURN: + (void)decoder; + AVSD_PARSE_TRACE("Out."); + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* alloc all buffer +*********************************************************************** +*/ + +static MPP_RET avsd_init(void *decoder, ParserCfg *init) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 i = 0; + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + + AVSD_PARSE_TRACE("In."); + INP_CHECK(ret, !p_dec); + + memset(p_dec, 0, sizeof(AvsdCtx_t)); + mpp_env_get_u32("avsd_debug", &avsd_debug, 0); + //!< restore init parameters + p_dec->init = *init; + p_dec->frame_slots = init->frame_slots; + p_dec->packet_slots = init->packet_slots; + //!< decoder parameters + mpp_buf_slot_setup(p_dec->frame_slots, 12); + p_dec->mem = mpp_calloc(AvsdMemory_t, 1); + MEM_CHECK(ret, p_dec->mem); + + p_dec->syn = &p_dec->mem->syntax; + p_dec->stream_size = MAX_STREAM_SIZE; + p_dec->streambuf = mpp_malloc(RK_U8, p_dec->stream_size); + MEM_CHECK(ret, p_dec->streambuf); + mpp_packet_init(&p_dec->task_pkt, p_dec->streambuf, p_dec->stream_size); + + mpp_packet_set_length(p_dec->task_pkt, 0); + MEM_CHECK(ret, p_dec->task_pkt); + for (i = 0; i < 3; i++) { + AvsdFrame_t *frm = &p_dec->mem->save[i]; + + memset(frm, 0, sizeof(*frm)); + frm->idx = i; + frm->slot_idx = -1; + } + p_dec->bx = &p_dec->mem->bitctx; + p_dec->need_split = 1; + +__RETURN: + AVSD_PARSE_TRACE("Out."); + return ret = MPP_OK; +__FAILED: + avsd_deinit(decoder); + + return ret; +} + +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +static MPP_RET avsd_reset(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + + AVSD_PARSE_TRACE("In."); + + avsd_reset_parameters(p_dec); + p_dec->got_vsh = 0; + p_dec->got_ph = 0; + p_dec->got_keyframe = 0; + p_dec->vec_flag = 0; + p_dec->got_eos = 0; + p_dec->left_length = 0; + p_dec->state = 0xFFFFFFFF; + p_dec->vop_header_found = 0; + + mpp_packet_set_length(p_dec->task_pkt, 0); + mpp_packet_set_flag(p_dec->task_pkt, 0); + + AVSD_PARSE_TRACE("Out."); + + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +static MPP_RET avsd_flush(void *decoder) +{ + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + + AVSD_PARSE_TRACE("In."); + + set_frame_output(p_dec, p_dec->dpb[1]); + set_frame_output(p_dec, p_dec->dpb[0]); + set_frame_output(p_dec, p_dec->cur); + + p_dec->got_eos = 0; + + AVSD_PARSE_TRACE("Out."); + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* control/perform +*********************************************************************** +*/ +static MPP_RET avsd_control(void *decoder, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + + AVSD_PARSE_TRACE("In."); + + switch (cmd_type) { + case MPP_DEC_SET_DISABLE_ERROR: { + p_dec->disable_error = *((RK_U32 *)param); + } break; + case MPP_DEC_SET_DIS_ERR_CLR_MARK: { + p_dec->dis_err_clr_mark = *((RK_U32 *)param); + } break; + default : { + } break; + } + + AVSD_PARSE_TRACE("Out."); + return ret = MPP_OK; +} + + +/*! +*********************************************************************** +* \brief +* prepare +*********************************************************************** +*/ +static MPP_RET avsd_prepare(void *decoder, MppPacket pkt, HalDecTask *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AVSD_PARSE_TRACE("In."); + INP_CHECK(ret, !decoder && !pkt && !task); + + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + RK_U8 *pos = mpp_packet_get_pos(pkt); + size_t length = mpp_packet_get_length(pkt); + RK_U32 eos = mpp_packet_get_eos(pkt); + + task->valid = 0; + if (p_dec->got_eos) { + AVSD_DBG(AVSD_DBG_INPUT, "got eos packet.\n"); + mpp_packet_set_length(pkt, 0); + goto __RETURN; + } + AVSD_DBG(AVSD_DBG_INPUT, "[pkt_in] pts=%lld, eos=%d, len=%d, pkt_no=%d\n", + mpp_packet_get_pts(pkt), eos, (RK_U32)length, (RK_U32)p_dec->pkt_no); + p_dec->pkt_no++; + + if (mpp_packet_get_eos(pkt)) { + if (mpp_packet_get_length(pkt) < 4) { + avsd_flush(decoder); + } + p_dec->got_eos = 1; + task->flags.eos = p_dec->got_eos; + goto __RETURN; + } + if (mpp_packet_get_length(pkt) > MAX_STREAM_SIZE) { + AVSD_DBG(AVSD_DBG_ERROR, "[pkt_in_timeUs] input error, stream too large"); + mpp_packet_set_length(pkt, 0); + ret = MPP_NOK; + goto __RETURN; + } + + mpp_packet_set_length(p_dec->task_pkt, p_dec->left_length); + + RK_U32 total_length = MPP_ALIGN(p_dec->left_length + length, 16) + 64; + if (total_length > p_dec->stream_size) { + do { + p_dec->stream_size <<= 1; + } while (total_length > p_dec->stream_size); + + RK_U8 *dst = mpp_malloc_size(RK_U8, p_dec->stream_size); + mpp_assert(dst); + + if (p_dec->left_length > 0) { + memcpy(dst, p_dec->streambuf, p_dec->left_length); + } + mpp_free(p_dec->streambuf); + p_dec->streambuf = dst; + + mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf); + mpp_packet_set_size(p_dec->task_pkt, p_dec->stream_size); + } + + if (!p_dec->need_split) { + p_dec->got_eos = eos; + // empty eos packet + if (eos && (length < 4)) { + avsd_flush(decoder); + goto __RETURN; + } + // copy packet direct + memcpy(p_dec->streambuf, pos, length); + mpp_packet_set_data(p_dec->task_pkt, p_dec->streambuf); + mpp_packet_set_length(p_dec->task_pkt, length); + mpp_packet_set_pts(p_dec->task_pkt, mpp_packet_get_pts(pkt)); + mpp_packet_set_dts(p_dec->task_pkt, mpp_packet_get_dts(pkt)); + // set input packet length to 0 here + mpp_packet_set_length(pkt, 0); + /* this step will enable the task and goto parse stage */ + task->valid = 1; + } else { + /* Split packet mode */ + if (MPP_OK == avsd_parser_split(p_dec, p_dec->task_pkt, pkt)) { + p_dec->left_length = 0; + task->valid = 1; + } else { + task->valid = 0; + p_dec->left_length = mpp_packet_get_length(p_dec->task_pkt); + } + p_dec->got_eos = mpp_packet_get_eos(p_dec->task_pkt); + } + task->input_packet = p_dec->task_pkt; + task->flags.eos = p_dec->got_eos; + +__RETURN: + AVSD_PARSE_TRACE("Out."); + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* parser +*********************************************************************** +*/ +static MPP_RET avsd_parse(void *decoder, HalDecTask *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + AVSD_PARSE_TRACE("In."); + + task->valid = 0; + memset(task->refer, -1, sizeof(task->refer)); + + avsd_parse_stream(p_dec, task); + if (task->valid) { + avsd_fill_parameters(p_dec, p_dec->syn); + avsd_set_dpb(p_dec, task); + + avsd_commit_syntaxs(p_dec->syn, task); + avsd_update_dpb(p_dec); + } + AVSD_PARSE_TRACE("Out."); + + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* callback +*********************************************************************** +*/ +static MPP_RET avsd_callback(void *decoder, void *info) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdCtx_t *p_dec = (AvsdCtx_t *)decoder; + DecCbHalDone *ctx = (DecCbHalDone *)info; + MppFrame mframe = NULL; + HalDecTask *task_dec = (HalDecTask *)ctx->task; + + AVSD_PARSE_TRACE("In."); + + mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + if (mframe) { + if (ctx->hard_err || task_dec->flags.ref_err) { + if (task_dec->flags.used_for_ref) { + mpp_frame_set_errinfo(mframe, MPP_FRAME_FLAG_PAIRED_FIELD); + } else { + mpp_frame_set_discard(mframe, MPP_FRAME_FLAG_PAIRED_FIELD); + } + } + } + + if (!ctx->hard_err && p_dec->ph.picture_coding_type == I_PICTURE) + p_dec->vsh.version_checked = 1; + + AVSD_PARSE_TRACE("Out."); + + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* api struct interface +*********************************************************************** +*/ +const ParserApi mpp_avsd = { + .name = "avsd_parse", + .coding = MPP_VIDEO_CodingAVS, + .ctx_size = sizeof(AvsdCtx_t), + .flag = 0, + .init = avsd_init, + .deinit = avsd_deinit, + .prepare = avsd_prepare, + .parse = avsd_parse, + .reset = avsd_reset, + .flush = avsd_flush, + .control = avsd_control, + .callback = avsd_callback, +}; + +const ParserApi mpp_avsd_plus = { + .name = "avsd_parse", + .coding = MPP_VIDEO_CodingAVSPLUS, + .ctx_size = sizeof(AvsdCtx_t), + .flag = 0, + .init = avsd_init, + .deinit = avsd_deinit, + .prepare = avsd_prepare, + .parse = avsd_parse, + .reset = avsd_reset, + .flush = avsd_flush, + .control = avsd_control, + .callback = avsd_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_avsd); +MPP_PARSER_API_REGISTER(mpp_avsd_plus); \ No newline at end of file diff --git a/mpp/codec/dec/avs/avsd_debug.h b/mpp/codec/dec/avs/avsd_debug.h new file mode 100644 index 000000000..57b2865db --- /dev/null +++ b/mpp/codec/dec/avs/avsd_debug.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef AVSD_DEBUG_H +#define AVSD_DEBUG_H + +#include "mpp_debug.h" + +#define AVSD_DBG_ERROR (0x00000001) +#define AVSD_DBG_ASSERT (0x00000002) +#define AVSD_DBG_WARNNING (0x00000004) +#define AVSD_DBG_LOG (0x00000008) + +#define AVSD_DBG_INPUT (0x00000010) +#define AVSD_DBG_TIME (0x00000020) +#define AVSD_DBG_SYNTAX (0x00000040) +#define AVSD_DBG_REF (0x00000080) + +#define AVSD_DBG_CALLBACK (0x00008000) + +#define AVSD_PARSE_TRACE(fmt, ...)\ +do {\ + if (AVSD_DBG_LOG & avsd_debug)\ + { mpp_log_f(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define AVSD_DBG(level, fmt, ...)\ +do {\ + if (level & avsd_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +//!< input check +#define INP_CHECK(ret, val, ...)\ +do{\ + if ((val)) {\ + ret = MPP_ERR_INIT; \ + AVSD_DBG(AVSD_DBG_WARNNING, "input empty(%d).\n", __LINE__); \ + goto __RETURN; \ +}} while (0) + +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do{\ + if(!(val)) {\ + ret = MPP_ERR_MALLOC;\ + mpp_err_f("malloc buffer error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + +//!< function return check +#define FUN_CHECK(val)\ +do{\ +if ((val) < 0) {\ + AVSD_DBG(AVSD_DBG_WARNNING, "Function error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + +extern RK_U32 avsd_debug; + +#endif /* AVSD_DEBUG_H */ diff --git a/mpp/codec/dec/avs/avsd_parse.c b/mpp/codec/dec/avs/avsd_parse.c new file mode 100644 index 000000000..748f0ee91 --- /dev/null +++ b/mpp/codec/dec/avs/avsd_parse.c @@ -0,0 +1,849 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "avsd_parse" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_packet_impl.h" +#include "hal_dec_task.h" + +#include "avsd_parse.h" + +static MPP_RET get_sequence_header(BitReadCtx_t *bitctx, AvsdSeqHeader_t *vsh) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 val_temp = 0; + + READ_BITS(bitctx, 8, &vsh->profile_id); + //!< check profile_id + if (vsh->profile_id != 0x20 && vsh->profile_id != 0x48) { + ret = MPP_NOK; + mpp_err_f("profile_id 0x%02x is not supported.\n", vsh->profile_id); + goto __FAILED; + } + READ_BITS(bitctx, 8, &vsh->level_id); + if (vsh->level_id > 0x42) { + ret = MPP_NOK; + mpp_err_f("level_id 0x%02x is not supported.\n", vsh->level_id); + goto __FAILED; + } + READ_ONEBIT(bitctx, &vsh->progressive_sequence); + READ_BITS(bitctx, 14, &vsh->horizontal_size); + READ_BITS(bitctx, 14, &vsh->vertical_size); + READ_BITS(bitctx, 2, &vsh->chroma_format); + READ_BITS(bitctx, 3, &vsh->sample_precision); + READ_BITS(bitctx, 4, &vsh->aspect_ratio); + READ_BITS(bitctx, 4, &vsh->frame_rate_code); + READ_BITS(bitctx, 18, &val_temp); //!< bit_rate_high_18 + vsh->bit_rate = val_temp << 12; + SKIP_BITS(bitctx, 1); + READ_BITS(bitctx, 12, &val_temp); //!< bit_rate_low_12 + vsh->bit_rate += val_temp; + READ_ONEBIT(bitctx, &vsh->low_delay); + SKIP_BITS(bitctx, 1); + READ_BITS(bitctx, 18, &vsh->bbv_buffer_size); + READ_BITS(bitctx, 3, &val_temp); //!< reserve 3bits 000 + if (val_temp) { + AVSD_DBG(AVSD_DBG_WARNNING, "reserver bits error.\n"); + } + return ret = MPP_OK; +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET gen_weight_quant_param(AvsdPicHeader_t *ph) +{ + RK_U32 i = 0; + RK_U32 *wqp = (RK_U32 *)ph->weighting_quant_param; + + RK_U32 weighting_quant_param_default[] = { 128, 98, 106, 116, 116, 128 }; + RK_U32 weighting_quant_param_base1[] = { 135, 143, 143, 160, 160, 213 }; + RK_U32 weighting_quant_param_base2[] = { 128, 98, 106, 116, 116, 128 }; + + if (ph->weighting_quant_flag == 0) { + //!< needn't generate this param + for (i = 0; i < 6; i++) { + wqp[i] = 128; + } + return MPP_OK; + } + + if (ph->weighting_quant_param_index == 0x0) { + for (i = 0; i < 6; i++) { + wqp[i] = weighting_quant_param_default[i]; + } + } else if (ph->weighting_quant_param_index == 0x1) { + for (i = 0; i < 6; i++) { + wqp[i] = weighting_quant_param_base1[i] + + ph->weighting_quant_param_delta1[i]; + } + } else if (ph->weighting_quant_param_index == 0x2) { + for (i = 0; i < 6; i++) { + wqp[i] = weighting_quant_param_base2[i] + + ph->weighting_quant_param_delta2[i]; + } + } else { + //!< shouldn't happen + AVSD_DBG(AVSD_DBG_WARNNING, "Something went wrong.\n"); + for (i = 0; i < 6; i++) { + wqp[i] = 128; + } + } + + return MPP_OK; +} + +static MPP_RET get_extend_header(BitReadCtx_t *bitctx, AvsdSeqHeader_t *vsh, AvsdPicHeader_t *ph) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 i = 0; + + READ_ONEBIT(bitctx, &ph->loop_filter_disable); + if (!ph->loop_filter_disable) { + READ_ONEBIT(bitctx, &ph->loop_filter_parameter_flag); + if (ph->loop_filter_parameter_flag) { + READ_SE(bitctx, &ph->alpha_c_offset); + READ_SE(bitctx, &ph->beta_offset); + } + } + ph->chroma_quant_param_delta_cb = 0; + ph->chroma_quant_param_delta_cr = 0; + for (i = 0; i < 6; i++) { + ph->weighting_quant_param_delta1[i] = 0; + ph->weighting_quant_param_delta2[i] = 0; + } + if (vsh->profile_id == 0x48) { + READ_ONEBIT(bitctx, &ph->weighting_quant_flag); + if (ph->weighting_quant_flag) { + SKIP_BITS(bitctx, 1); + READ_ONEBIT(bitctx, &ph->chroma_quant_param_disable); + if (!ph->chroma_quant_param_disable) { + READ_SE(bitctx, &ph->chroma_quant_param_delta_cb); + READ_SE(bitctx, &ph->chroma_quant_param_delta_cr); + } + READ_BITS(bitctx, 2, &ph->weighting_quant_param_index); + READ_BITS(bitctx, 2, &ph->weighting_quant_model); + if (ph->weighting_quant_param_index == 1) { + for (i = 0; i < 6; i++) { + READ_SE(bitctx, &ph->weighting_quant_param_delta1[i]); + } + } else if (ph->weighting_quant_param_index == 2) { + for (i = 0; i < 6; i++) { + READ_SE(bitctx, &ph->weighting_quant_param_delta2[i]); + } + } + } + gen_weight_quant_param(ph); //!< generate wqP[m][6] + + READ_ONEBIT(bitctx, &ph->aec_enable); + } + + return ret = MPP_OK; +__BITREAD_ERR: + return ret = bitctx->ret; +} + +static MPP_RET get_seq_dispay_ext_header(BitReadCtx_t *bitctx, AvsdSeqExtHeader_t *ext) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 val_temp = 0; + + READ_BITS(bitctx, 3, &ext->video_format); + READ_ONEBIT(bitctx, &ext->sample_range); + READ_ONEBIT(bitctx, &ext->color_description); + + if (ext->color_description) { + READ_BITS(bitctx, 8, &ext->color_primaries); + READ_BITS(bitctx, 8, &ext->transfer_characteristics); + READ_BITS(bitctx, 8, &ext->matrix_coefficients); + } + READ_BITS(bitctx, 14, &ext->display_horizontalSize); + SKIP_BITS(bitctx, 1); //!< marker bit + READ_BITS(bitctx, 14, &ext->display_verticalSize); + + READ_BITS(bitctx, 2, &val_temp); //!< reserve 2 bits + if (val_temp) { + AVSD_DBG(AVSD_DBG_WARNNING, "reserve bits not equal to zeros.\n"); + } + return ret = MPP_OK; +__BITREAD_ERR: + return ret = bitctx->ret; +} +static MPP_RET get_extension_header(BitReadCtx_t *bitctx, AvsdSeqExtHeader_t *ext) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 val_temp = 0; + + READ_BITS(bitctx, 4, &val_temp); //!< extension_start_code + switch (val_temp) { + case SEQUENCE_DISPLAY_EXTENTION: + FUN_CHECK(ret = get_seq_dispay_ext_header(bitctx, ext)); + break; + + default: + break; + } + + return ret = MPP_OK; +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET get_i_picture_header(BitReadCtx_t *bitctx, AvsdSeqHeader_t *vsh, AvsdPicHeader_t *ph) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 val_temp = 0; + ph->picture_coding_type = I_PICTURE; + + READ_BITS(bitctx, 16, &ph->bbv_delay); + if (vsh->profile_id == 0x48) { + SKIP_BITS(bitctx, 1); + READ_BITS(bitctx, 7, &ph->bbv_delay_extension); + } + READ_ONEBIT(bitctx, &ph->time_code_flag); + if (ph->time_code_flag) { + READ_BITS(bitctx, 24, &ph->time_code); + } + + /* NOTE: only check version on correct I frame not found */ + if (!vsh->version_checked) { + vsh->version = 0; + /* check stream version */ + if (vsh->low_delay) { + vsh->version = 1; + } else { + SHOW_BITS(bitctx, 9, &val_temp); + if (!(val_temp & 1)) { + vsh->version = 1; + } else { + SHOW_BITS(bitctx, 11, &val_temp); + if (val_temp & 3) + vsh->version = 1; + } + } + } + + if (vsh->version > 0) + SKIP_BITS(bitctx, 1); // marker bit + + READ_BITS(bitctx, 8, &ph->picture_distance); + + if (vsh->low_delay) + READ_UE(bitctx, &ph->bbv_check_times); + + READ_ONEBIT(bitctx, &ph->progressive_frame); + + ph->picture_structure = 1; // default frame + if (!ph->progressive_frame) + READ_ONEBIT(bitctx, &ph->picture_structure); + + READ_ONEBIT(bitctx, &ph->top_field_first); + READ_ONEBIT(bitctx, &ph->repeat_first_field); + READ_ONEBIT(bitctx, &ph->fixed_picture_qp); + READ_BITS(bitctx, 6, &ph->picture_qp); + ph->skip_mode_flag = 0; + if (!ph->progressive_frame && !ph->picture_structure) + READ_ONEBIT(bitctx, &ph->skip_mode_flag); + READ_BITS(bitctx, 4, &val_temp); //!< reserve 4 bits + if (val_temp) { + AVSD_DBG(AVSD_DBG_WARNNING, "reserve bits not equal to zeros.\n"); + } + ph->no_forward_reference_flag = 0; + ph->pb_field_enhanced_flag = 0; + ph->weighting_quant_flag = 0; + ph->aec_enable = 0; + + FUN_CHECK(ret = get_extend_header(bitctx, vsh, ph)); + + return ret = MPP_OK; +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET get_pb_picture_header(BitReadCtx_t *bitctx, AvsdSeqHeader_t *vsh, AvsdPicHeader_t *ph) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 val_temp = 0; + + READ_BITS(bitctx, 16, &ph->bbv_delay); + if (vsh->profile_id == 0x48) { + SKIP_BITS(bitctx, 1); + READ_BITS(bitctx, 7, &ph->bbv_delay_extension); + } + READ_BITS(bitctx, 2, &ph->picture_coding_type); + READ_BITS(bitctx, 8, &ph->picture_distance); + if (vsh->low_delay) { + READ_UE(bitctx, &ph->bbv_check_times); + } + READ_ONEBIT(bitctx, &ph->progressive_frame); + + if (!ph->progressive_frame) { + READ_ONEBIT(bitctx, &ph->picture_structure); + if (!ph->picture_structure) { + READ_ONEBIT(bitctx, &ph->advanced_pred_mode_disable); + } + } else { + ph->picture_structure = 1; //!< frame picture + } + READ_ONEBIT(bitctx, &ph->top_field_first); + READ_ONEBIT(bitctx, &ph->repeat_first_field); + READ_ONEBIT(bitctx, &ph->fixed_picture_qp); + READ_BITS(bitctx, 6, &ph->picture_qp); + if (!(ph->picture_coding_type == B_PICTURE && ph->picture_structure == P_PICTURE)) { + READ_ONEBIT(bitctx, &ph->picture_reference_flag); + } + READ_ONEBIT(bitctx, &ph->no_forward_reference_flag); + READ_ONEBIT(bitctx, &ph->pb_field_enhanced_flag); + if (vsh->profile_id != 0x48) { + ph->no_forward_reference_flag = 0; + ph->pb_field_enhanced_flag = 0; + } + ph->weighting_quant_flag = 0; + ph->aec_enable = 0; + + READ_BITS(bitctx, 2, &val_temp); //!< reserve bits + if (val_temp) { + AVSD_DBG(AVSD_DBG_WARNNING, "reserve bits not equal to zeros.\n"); + } + READ_ONEBIT(bitctx, &ph->skip_mode_flag); + + FUN_CHECK(ret = get_extend_header(bitctx, vsh, ph)); + + return ret = MPP_OK; +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +static void reset_one_save(AvsdFrame_t *p) +{ + if (p) { + RK_U32 idx = p->idx; + + memset(p, 0, sizeof(AvsdFrame_t)); + p->idx = idx; + p->slot_idx = -1; + } +} + +static AvsdFrame_t *get_one_save(AvsdCtx_t *p_dec, HalDecTask *task) +{ + RK_U32 i = 0; + AvsdFrame_t *p_cur = NULL; + + for (i = 0; i < MPP_ARRAY_ELEMS(p_dec->mem->save); i++) { + if (!p_dec->mem->save[i].valid) { + p_dec->mem->save[i].valid = 1; + p_cur = &p_dec->mem->save[i]; + break; + } + } + if (!p_cur) { + mpp_err("mem_save dpb %d slots has not get\n", MPP_ARRAY_ELEMS(p_dec->mem->save)); + goto __FAILED; + } + (void)task; + return p_cur; +__FAILED: + reset_one_save(p_cur); + + return NULL; +} + +static MPP_RET set_frame_unref(AvsdCtx_t *pdec, AvsdFrame_t *p) +{ + if (p && p->slot_idx >= 0) { + mpp_buf_slot_clr_flag(pdec->frame_slots, p->slot_idx, SLOT_CODEC_USE); + reset_one_save(p); + } + + return MPP_OK; +} + + +MPP_RET set_frame_output(AvsdCtx_t *p_dec, AvsdFrame_t *p) +{ + if (p && p->slot_idx >= 0 && !p->had_display) { + mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p_dec->frame_slots, p->slot_idx, QUEUE_DISPLAY); + p->had_display = 1; + } + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* reset decoder parameters +*********************************************************************** +*/ +MPP_RET avsd_reset_parameters(AvsdCtx_t *p_dec) +{ + RK_U32 i = 0; + + set_frame_output(p_dec, p_dec->dpb[1]); + set_frame_output(p_dec, p_dec->dpb[0]); + set_frame_output(p_dec, p_dec->cur); + set_frame_unref(p_dec, p_dec->dpb[1]); + set_frame_unref(p_dec, p_dec->dpb[0]); + set_frame_unref(p_dec, p_dec->cur); + + p_dec->cur = NULL; + p_dec->dpb[0] = NULL; + p_dec->dpb[1] = NULL; + + p_dec->vsh.version_checked = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(p_dec->mem->save); i++) { + AvsdFrame_t *frm = &p_dec->mem->save[i]; + + memset(frm, 0, sizeof(*frm)); + frm->idx = i; + frm->slot_idx = -1; + } + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* set refer +*********************************************************************** +*/ +MPP_RET avsd_set_dpb(AvsdCtx_t *p_dec, HalDecTask *task) +{ + MppFrame mframe = NULL; + RK_S32 slot_idx = -1; + AvsdFrame_t *p_cur = p_dec->cur; + + //!< set current dpb for decode + mpp_buf_slot_get_unused(p_dec->frame_slots, &slot_idx); + if (slot_idx < 0) { + AVSD_DBG(AVSD_DBG_WARNNING, "error, buf_slot has not get.\n"); + goto __FAILED; + } + //!< init current frame data + p_cur->slot_idx = slot_idx; + p_cur->pic_type = p_dec->ph.picture_coding_type; + p_cur->width = p_dec->vsh.horizontal_size; + p_cur->height = p_dec->vsh.vertical_size; + p_cur->hor_stride = MPP_ALIGN(p_dec->vsh.horizontal_size, 16); + p_cur->ver_stride = MPP_ALIGN(p_dec->vsh.vertical_size, 16); + p_cur->pts = mpp_packet_get_pts(task->input_packet); + p_cur->dts = mpp_packet_get_dts(task->input_packet); + //!< set frame info + mpp_frame_init(&mframe); + mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP); + mpp_frame_set_hor_stride(mframe, p_cur->hor_stride); // before crop + mpp_frame_set_ver_stride(mframe, p_cur->ver_stride); + mpp_frame_set_width(mframe, p_cur->width); // after crop + mpp_frame_set_height(mframe, p_cur->height); + mpp_frame_set_pts(mframe, p_cur->pts); + mpp_frame_set_dts(mframe, p_cur->dts); + if (p_dec->ph.picture_structure) { //!< data combine 2 field + p_cur->frame_mode = MPP_FRAME_FLAG_PAIRED_FIELD; + if (p_dec->ph.top_field_first) { + p_cur->frame_mode |= MPP_FRAME_FLAG_TOP_FIRST; + } else { + p_cur->frame_mode |= MPP_FRAME_FLAG_BOT_FIRST; + } + } else { //!< frame picture + p_cur->frame_mode = MPP_FRAME_FLAG_FRAME; + + if (p_dec->init.cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) { + p_cur->frame_mode |= MPP_FRAME_FLAG_DEINTERLACED; + } + } + mpp_frame_set_mode(mframe, p_cur->frame_mode); + mpp_buf_slot_set_prop(p_dec->frame_slots, slot_idx, SLOT_FRAME, mframe); + mpp_frame_deinit(&mframe); + + mpp_buf_slot_set_flag(p_dec->frame_slots, p_cur->slot_idx, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(p_dec->frame_slots, p_cur->slot_idx, SLOT_HAL_OUTPUT); + + //!< set task + task->output = p_dec->cur->slot_idx; + //!< set task refers + if (p_dec->dpb[0] && p_dec->dpb[0]->slot_idx >= 0 && + (p_dec->dpb[0]->slot_idx != p_dec->cur->slot_idx)) { + mpp_buf_slot_set_flag(p_dec->frame_slots, p_dec->dpb[0]->slot_idx, SLOT_HAL_INPUT); + if (p_dec->ph.picture_coding_type == B_PICTURE) { + task->refer[1] = p_dec->dpb[0]->slot_idx; + } else { + task->refer[0] = p_dec->dpb[0]->slot_idx; + } + } + if (p_dec->dpb[1] && p_dec->dpb[1]->slot_idx >= 0 && + (p_dec->dpb[1]->slot_idx != p_dec->cur->slot_idx)) { + mpp_buf_slot_set_flag(p_dec->frame_slots, p_dec->dpb[1]->slot_idx, SLOT_HAL_INPUT); + if (p_dec->ph.picture_coding_type == B_PICTURE) { + task->refer[0] = p_dec->dpb[1]->slot_idx; + } else { + task->refer[1] = p_dec->dpb[1]->slot_idx; + } + } + + //!< set ref flag and mark error + if (p_dec->ph.picture_coding_type == I_PICTURE) { + task->flags.used_for_ref = 1; + task->flags.ref_err = 0; + } else if (p_dec->ph.picture_coding_type == P_PICTURE) { + task->flags.used_for_ref = 1; + if (task->refer[0] >= 0) { + mpp_buf_slot_get_prop(p_dec->frame_slots, task->refer[0], SLOT_FRAME_PTR, &mframe); + if (mframe) + task->flags.ref_err |= mpp_frame_get_errinfo(mframe); + } + } else if (p_dec->ph.picture_coding_type == B_PICTURE) { + task->flags.used_for_ref = 0; + if (task->refer[0] >= 0) { + mpp_buf_slot_get_prop(p_dec->frame_slots, task->refer[0], SLOT_FRAME_PTR, &mframe); + if (mframe) + task->flags.ref_err |= mpp_frame_get_errinfo(mframe); + } + if (task->refer[1] >= 0) { + mpp_buf_slot_get_prop(p_dec->frame_slots, task->refer[1], SLOT_FRAME_PTR, &mframe); + if (mframe) + task->flags.ref_err |= mpp_frame_get_errinfo(mframe); + } + } + + return MPP_OK; +__FAILED: + return MPP_NOK; +} + +/*! +*********************************************************************** +* \brief +* commit buffer to hal +*********************************************************************** +*/ +MPP_RET avsd_commit_syntaxs(AvsdSyntax_t *syn, HalDecTask *task) +{ + task->syntax.number = 1; + task->syntax.data = syn; + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* commit buffer to hal +*********************************************************************** +*/ +MPP_RET avsd_update_dpb(AvsdCtx_t *p_dec) +{ + if (p_dec->ph.picture_coding_type != B_PICTURE) { + set_frame_output(p_dec, p_dec->dpb[0]); + set_frame_unref(p_dec, p_dec->dpb[1]); + p_dec->dpb[1] = p_dec->dpb[0]; + p_dec->dpb[0] = p_dec->cur; + p_dec->cur = NULL; + } else { + set_frame_output(p_dec, p_dec->cur); + set_frame_unref(p_dec, p_dec->cur); + p_dec->cur = NULL; + } + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* fill parameters +*********************************************************************** +*/ +MPP_RET avsd_fill_parameters(AvsdCtx_t *p_dec, AvsdSyntax_t *syn) +{ + RK_S32 i = 0; + PicParams_Avsd *pp = &syn->pp; + + //!< sequence header + pp->profileId = p_dec->vsh.profile_id; + pp->levelId = p_dec->vsh.level_id; + pp->progressiveSequence = p_dec->vsh.progressive_sequence; + pp->horizontalSize = p_dec->vsh.horizontal_size; + pp->verticalSize = p_dec->vsh.vertical_size; + pp->chromaFormat = p_dec->vsh.chroma_format; + pp->aspectRatio = p_dec->vsh.aspect_ratio; + pp->frameRateCode = p_dec->vsh.frame_rate_code; + pp->bitRateValue = p_dec->vsh.bit_rate; + pp->lowDelay = p_dec->vsh.low_delay; + pp->bbvBufferSize = p_dec->vsh.bbv_buffer_size; + + //!< sequence display extension header + pp->videoFormat = p_dec->ext.video_format; + pp->sampleRange = p_dec->ext.sample_range; + pp->colorDescription = p_dec->ext.color_description; + pp->colorPrimaries = p_dec->ext.color_primaries; + pp->transferCharacteristics = p_dec->ext.transfer_characteristics; + pp->matrixCoefficients = p_dec->ext.matrix_coefficients; + pp->displayHorizontalSize = p_dec->ext.display_horizontalSize; + pp->displayVerticalSize = p_dec->ext.display_verticalSize; + + //!< picture header + pp->picCodingType = p_dec->ph.picture_coding_type; + pp->bbvDelay = p_dec->ph.bbv_delay; + pp->bbvDelayExtension = p_dec->ph.bbv_delay_extension; + pp->timeCodeFlag = p_dec->ph.time_code_flag; + pp->timeCode = p_dec->ph.time_code; + + pp->pictureDistance = p_dec->ph.picture_distance; + pp->progressiveFrame = p_dec->ph.progressive_frame; + pp->pictureStructure = p_dec->ph.picture_structure; + pp->advancedPredModeDisable = p_dec->ph.advanced_pred_mode_disable; + pp->topFieldFirst = p_dec->ph.top_field_first; + pp->repeatFirstField = p_dec->ph.repeat_first_field; + pp->fixedPictureQp = p_dec->ph.fixed_picture_qp; + pp->pictureQp = p_dec->ph.picture_qp; + pp->pictureReferenceFlag = p_dec->ph.picture_reference_flag; + pp->skipModeFlag = p_dec->ph.skip_mode_flag; + pp->loopFilterDisable = p_dec->ph.loop_filter_disable; + pp->alphaOffset = p_dec->ph.alpha_c_offset; + pp->betaOffset = p_dec->ph.beta_offset; + + //!< weighting quant, AVS Plus stuff + pp->weightingQuantFlag = p_dec->ph.weighting_quant_flag; + pp->chromaQuantParamDisable = p_dec->ph.chroma_quant_param_disable; + pp->chromaQuantParamDeltaCb = p_dec->ph.chroma_quant_param_delta_cb; + pp->chromaQuantParamDeltaCr = p_dec->ph.chroma_quant_param_delta_cr; + pp->weightingQuantParamIndex = p_dec->ph.weighting_quant_param_index; + pp->weightingQuantModel = p_dec->ph.weighting_quant_model; + for (i = 0; i < 6; i++) { + pp->weightingQuantParamDelta1[i] = p_dec->ph.weighting_quant_param_delta1[i]; + pp->weightingQuantParamDelta2[i] = p_dec->ph.weighting_quant_param_delta2[i]; + pp->weightingQuantParam[i] = p_dec->ph.weighting_quant_param[i]; + } + //!< advance entropy coding + pp->aecEnable = p_dec->ph.aec_enable; + + //!< picture enhance + pp->noForwardReferenceFlag = p_dec->ph.no_forward_reference_flag; + pp->pbFieldEnhancedFlag = p_dec->ph.pb_field_enhanced_flag; + + //!< set stream offset + syn->bitstream_size = p_dec->cur->stream_len; + syn->bitstream_offset = p_dec->cur->stream_offset; + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* prepare function for parser +*********************************************************************** +*/ +MPP_RET avsd_parser_split(AvsdCtx_t *p, MppPacket *dst, MppPacket *src) +{ + MPP_RET ret = MPP_NOK; + AVSD_PARSE_TRACE("In.\n"); + + RK_U8 *src_buf = (RK_U8 *)mpp_packet_get_pos(src); + RK_U32 src_len = (RK_U32)mpp_packet_get_length(src); + RK_U32 src_eos = mpp_packet_get_eos(src); + RK_S64 src_pts = mpp_packet_get_pts(src); + RK_S64 src_dts = mpp_packet_get_dts(src); + RK_U8 *dst_buf = (RK_U8 *)mpp_packet_get_data(dst); + RK_U32 dst_len = (RK_U32)mpp_packet_get_length(dst); + RK_U32 src_pos = 0; + + // find the began of the vop + if (!p->vop_header_found) { + // add last startcode to the new frame data + if ((dst_len < sizeof(p->state)) + && ((p->state & 0x00FFFFFF) == 0x000001)) { + dst_buf[0] = 0; + dst_buf[1] = 0; + dst_buf[2] = 1; + dst_len = 3; + } + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + if (p->state == I_PICUTRE_START_CODE || + p->state == PB_PICUTRE_START_CODE) { + p->vop_header_found = 1; + mpp_packet_set_pts(dst, src_pts); + mpp_packet_set_dts(dst, src_dts); + break; + } + } + } + + // find the end of the vop + if (p->vop_header_found) { + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + if ((p->state & 0x00FFFFFF) == 0x000001) { + if (src_buf[src_pos] > (SLICE_MAX_START_CODE & 0xFF) && + src_buf[src_pos] != (USER_DATA_CODE & 0xFF)) { + dst_len -= 3; + p->vop_header_found = 0; + ret = MPP_OK; // split complete + break; + } + } + } + } + // the last packet + if (src_eos && src_pos >= src_len) { + mpp_packet_set_eos(dst); + ret = MPP_OK; + } + + AVSD_DBG(AVSD_DBG_INPUT, "[pkt_in] vop_header_found= %d, dst_len=%d, src_pos=%d\n", + p->vop_header_found, dst_len, src_pos); + // reset the src and dst + mpp_packet_set_length(dst, dst_len); + mpp_packet_set_pos(src, src_buf + src_pos); + + AVSD_PARSE_TRACE("out.\n"); + + return ret; +} +/*! +*********************************************************************** +* \brief +* parse stream which ha function for parser +*********************************************************************** +*/ +MPP_RET avsd_parse_stream(AvsdCtx_t *p_dec, HalDecTask *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 startcode = 0xFF; + RK_U32 pic_type = 0; + RK_U32 got_slice = 0; + + RK_U8 *data = (RK_U8 *)mpp_packet_get_data(task->input_packet); + RK_S32 length = (RK_S32)mpp_packet_get_length(task->input_packet); + + mpp_set_bitread_ctx(p_dec->bx, data, length); + AVSD_DBG(AVSD_DBG_SYNTAX, "bytes_left_=%d\n", p_dec->bx->bytes_left_); + while (p_dec->bx->bytes_left_ && !got_slice) { + RK_S32 tmp = 0; + mpp_align_get_bits(p_dec->bx); + mpp_read_bits(p_dec->bx, 8, &tmp); + startcode = (startcode << 8) | tmp; + if ((startcode & 0xFFFFFF00) != 0x100) + continue; + AVSD_DBG(AVSD_DBG_SYNTAX, "startcode=%08x\n", startcode); + + // when has not got sequence header, then do nothing + if (!p_dec->got_vsh && + startcode != VIDEO_SEQUENCE_START_CODE) { + AVSD_DBG(AVSD_DBG_WARNNING, "when has not got sequence header, then do nothing\n"); + continue; + } + //continue; + switch (startcode) { + case VIDEO_SEQUENCE_START_CODE: + ret = get_sequence_header(p_dec->bx, &p_dec->vsh); + if (ret == MPP_OK) { + p_dec->got_vsh = 1; + } + AVSD_DBG(AVSD_DBG_WARNNING, "got vsh %d\n", p_dec->got_vsh); + break; + case VIDEO_SEQUENCE_END_CODE: + break; + case USER_DATA_CODE: + break; + case VIDEO_EDIT_CODE: + p_dec->vec_flag = 0; + break; + case I_PICUTRE_START_CODE: + AVSD_DBG(AVSD_DBG_WARNNING, "got I picture start code\n"); + if (!p_dec->got_keyframe) { + avsd_reset_parameters(p_dec); + p_dec->got_keyframe = 1; + } + ret = get_i_picture_header(p_dec->bx, &p_dec->vsh, &p_dec->ph); + if (ret == MPP_OK) { + p_dec->cur = get_one_save(p_dec, task); + p_dec->got_ph = 1; + } + p_dec->cur->pic_type = pic_type = I_PICTURE; + p_dec->vec_flag++; + break; + case EXTENSION_START_CODE: + ret = get_extension_header(p_dec->bx, &p_dec->ext); + break; + case PB_PICUTRE_START_CODE: + AVSD_DBG(AVSD_DBG_WARNNING, "got PB picture start code\n"); + if (!p_dec->got_keyframe) { + avsd_reset_parameters(p_dec); + break; + } + ret = get_pb_picture_header(p_dec->bx, &p_dec->vsh, &p_dec->ph); + if (ret == MPP_OK) { + p_dec->cur = get_one_save(p_dec, task); + p_dec->got_ph = 1; + } + p_dec->cur->pic_type = pic_type = p_dec->ph.picture_coding_type; + p_dec->vec_flag += (p_dec->vec_flag == 1 && pic_type == P_PICTURE); + break; + default: + if (p_dec->cur + && startcode >= SLICE_MIN_START_CODE + && startcode <= SLICE_MAX_START_CODE) { + got_slice = 1; + p_dec->cur->stream_len = length; + p_dec->cur->stream_offset = p_dec->bx->used_bits / 8 - 4; + task->valid = p_dec->got_vsh && p_dec->got_ph; + AVSD_DBG(AVSD_DBG_SYNTAX, "offset=%d,got_vsh=%d, got_ph=%d, task->valid=%d\n", + p_dec->cur->stream_offset, p_dec->got_vsh, p_dec->got_ph, task->valid); + } + + if (p_dec->disable_error) + break; + + if ((pic_type == P_PICTURE && !p_dec->dpb[0]) || + (pic_type == B_PICTURE && !p_dec->dpb[0]) || + (pic_type == B_PICTURE && !p_dec->dpb[1] && !p_dec->vsh.low_delay) || + (pic_type == P_PICTURE && p_dec->vec_flag < 1) || + (pic_type == B_PICTURE && p_dec->vec_flag < 2)) { + AVSD_DBG(AVSD_DBG_REF, "missing refer frame.\n"); + if (!p_dec->disable_error) + goto __FAILED; + } + break; + } + } + + if (!task->valid) + goto __FAILED; + + return MPP_OK; +__FAILED: + task->valid = 0; + reset_one_save(p_dec->cur); + return MPP_NOK; +} diff --git a/mpp/codec/dec/avs/avsd_parse.h b/mpp/codec/dec/avs/avsd_parse.h new file mode 100644 index 000000000..c3c6a5322 --- /dev/null +++ b/mpp/codec/dec/avs/avsd_parse.h @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef AVSD_PARSE_H +#define AVSD_PARSE_H + +#include "parser_api.h" +#include "mpp_bitread.h" + +#include "avsd_debug.h" +#include "avsd_syntax.h" + +#define MAX_STREAM_SIZE (2*1024*1024) + +//!< NALU type +#define SEQUENCE_DISPLAY_EXTENTION 0x00000002 +#define COPYRIGHT_EXTENTION 0x00000004 +#define PICTURE_DISPLAY_EXTENTION 0x00000007 +#define CAMERA_PARAMETERS_EXTENTION 0x0000000B +#define SLICE_MIN_START_CODE 0x00000100 +#define SLICE_MAX_START_CODE 0x000001AF +#define VIDEO_SEQUENCE_START_CODE 0x000001B0 +#define VIDEO_SEQUENCE_END_CODE 0x000001B1 +#define USER_DATA_CODE 0x000001B2 +#define I_PICUTRE_START_CODE 0x000001B3 +#define EXTENSION_START_CODE 0x000001B5 +#define PB_PICUTRE_START_CODE 0x000001B6 +#define VIDEO_EDIT_CODE 0x000001B7 +#define VIDEO_TIME_CODE 0x000001E0 + + +#define EDGE_SIZE 16 +#define MB_SIZE 16 +#define YUV420 0 + +//!< picture type +enum avsd_picture_type_e { + I_PICTURE = 0, + P_PICTURE = 1, + B_PICTURE = 2 +}; + +typedef struct avsd_sequence_header_t { + RK_U8 profile_id; + RK_U8 level_id; + RK_U8 progressive_sequence; + RK_U8 version; + RK_U32 horizontal_size; + RK_U32 vertical_size; + + RK_U8 chroma_format; + RK_U8 sample_precision; + RK_U8 aspect_ratio; + RK_U8 frame_rate_code; + RK_U32 bit_rate; + RK_U8 low_delay; + RK_U8 version_checked; + RK_U32 bbv_buffer_size; +} AvsdSeqHeader_t; + +//!< sequence display extension header +typedef struct avsd_seqence_extension_header_t { + RK_U32 video_format; + RK_U32 sample_range; + RK_U32 color_description; + RK_U32 color_primaries; + RK_U32 transfer_characteristics; + RK_U32 matrix_coefficients; + RK_U32 display_horizontalSize; + RK_U32 display_verticalSize; +} AvsdSeqExtHeader_t; + +typedef struct avsd_picture_header { + RK_U16 bbv_delay; + RK_U16 bbv_delay_extension; + + RK_U8 picture_coding_type; + RK_U8 time_code_flag; + RK_U32 time_code; + RK_U8 picture_distance; // poc + RK_U32 bbv_check_times; + RK_U8 progressive_frame; + RK_U8 picture_structure; + RK_U8 advanced_pred_mode_disable; + RK_U8 top_field_first; + RK_U8 repeat_first_field; + RK_U8 fixed_picture_qp; + RK_U8 picture_qp; + RK_U8 picture_reference_flag; + + RK_U8 no_forward_reference_flag; + RK_U8 pb_field_enhanced_flag; + + RK_U8 skip_mode_flag; + RK_U8 loop_filter_disable; + RK_U8 loop_filter_parameter_flag; + RK_U32 alpha_c_offset; + RK_U32 beta_offset; + + RK_U8 weighting_quant_flag; + RK_U8 chroma_quant_param_disable; + RK_S32 chroma_quant_param_delta_cb; + RK_S32 chroma_quant_param_delta_cr; + RK_U32 weighting_quant_param_index; + RK_U32 weighting_quant_model; + RK_S32 weighting_quant_param_delta1[6]; + RK_S32 weighting_quant_param_delta2[6]; + RK_S32 weighting_quant_param[6]; + RK_U8 aec_enable; +} AvsdPicHeader_t; + +typedef struct avsd_frame_t { + RK_U32 valid; + RK_U32 idx; + + RK_U32 pic_type; + RK_U32 frame_mode; //!< set mpp frame flag + RK_U32 width; + RK_U32 height; + RK_U32 ver_stride; + RK_U32 hor_stride; + RK_S64 pts; + RK_S64 dts; + + RK_S32 stream_len; + RK_S32 stream_offset; + RK_U32 had_display; + RK_S32 slot_idx; +} AvsdFrame_t; + +typedef struct avsd_memory_t { + struct avsd_syntax_t syntax; + struct avsd_frame_t save[3]; + BitReadCtx_t bitctx; +} AvsdMemory_t; + +//!< decoder parameters +typedef struct avs_dec_ctx_t { + MppBufSlots frame_slots; + MppBufSlots packet_slots; + + MppPacket task_pkt; + RK_U32 frame_no; + ParserCfg init; + RK_U8 got_eos; + RK_U32 pkt_no; + + struct avsd_memory_t *mem; + RK_U8 *streambuf; + RK_U32 stream_len; + RK_U32 stream_size; + + BitReadCtx_t *bx; + RK_U32 left_length; + + AvsdSeqHeader_t vsh; + AvsdSeqExtHeader_t ext; + AvsdPicHeader_t ph; + AvsdSyntax_t *syn; + AvsdFrame_t *dpb[2]; //!< 2 refer frames or 4 refer field + AvsdFrame_t *cur; //!< for decoder field + + RK_U32 need_split; + RK_U32 state; + RK_U32 vop_header_found; + RK_U32 got_vsh; + RK_U32 got_ph; + RK_U32 got_keyframe; + RK_U32 mb_width; + RK_U32 mb_height; + RK_U32 vec_flag; //!< video_edit_code_flag + + RK_U32 disable_error; + RK_U32 dis_err_clr_mark; +} AvsdCtx_t; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET avsd_free_resource(AvsdCtx_t *p_dec); +MPP_RET avsd_reset_parameters(AvsdCtx_t *p_dec); +MPP_RET set_frame_output(AvsdCtx_t *p_dec, AvsdFrame_t *p); + +MPP_RET avsd_set_dpb(AvsdCtx_t *p_dec, HalDecTask *task); +MPP_RET avsd_commit_syntaxs(AvsdSyntax_t *syn, HalDecTask *task); +MPP_RET avsd_fill_parameters(AvsdCtx_t *p_dec, AvsdSyntax_t *syn); + +MPP_RET avsd_update_dpb(AvsdCtx_t *p_dec); + +MPP_RET avsd_parser_split(AvsdCtx_t *ctx, MppPacket *dst, MppPacket *src); +MPP_RET avsd_parse_stream(AvsdCtx_t *p_dec, HalDecTask *task); + +#ifdef __cplusplus +} +#endif + +#endif /* AVSD_PARSE_H */ diff --git a/mpp/codec/dec/avs2/CMakeLists.txt b/mpp/codec/dec/avs2/CMakeLists.txt new file mode 100644 index 000000000..12e0a99a2 --- /dev/null +++ b/mpp/codec/dec/avs2/CMakeLists.txt @@ -0,0 +1,10 @@ +# vim: syntax=cmake +include_directories(.) + +# avs2 decoder sourse +add_library(avs2d_api OBJECT + avs2d_api.c + avs2d_parse.c + avs2d_ps.c + avs2d_dpb.c + ) diff --git a/mpp/codec/dec/avs2/avs2d_api.c b/mpp/codec/dec/avs2/avs2d_api.c new file mode 100644 index 000000000..fe61f4b1e --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_api.c @@ -0,0 +1,350 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "avs2d_api" + +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_env.h" +#include "mpp_packet_impl.h" +#include "mpp_buffer_impl.h" + +#include "mpp_parser.h" + +#include "avs2d_syntax.h" +#include "avs2d_parse.h" +#include "avs2d_dpb.h" +#include "mpp_dec_cb_param.h" + +// for avs2d max ctu size 64 +static RK_U32 rkv_ctu_64_align(RK_U32 val) +{ + return MPP_ALIGN(val, 64); +} + +MPP_RET avs2d_deinit(void *decoder) +{ + MPP_RET ret = MPP_OK; + Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + + INP_CHECK(ret, !decoder); + AVS2D_PARSE_TRACE("In."); + + MPP_FREE(p_dec->p_stream->pbuf); + MPP_FREE(p_dec->p_header->pbuf); + MPP_FREE(p_dec->mem); + MPP_FREE(p_dec->p_nals); + mpp_packet_deinit(&p_dec->task_pkt); + avs2d_dpb_destroy(p_dec); + +__RETURN: + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +MPP_RET avs2d_init(void *decoder, ParserCfg *init) +{ + MPP_RET ret = MPP_OK; + Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + + AVS2D_PARSE_TRACE("In."); + INP_CHECK(ret, !p_dec); + + memset(p_dec, 0, sizeof(Avs2dCtx_t)); + mpp_env_get_u32("avs2d_debug", &avs2d_debug, 0); + //!< restore init parameters + p_dec->init = *init; + // p_dec->init.cfg->base.split_parse = 1; + p_dec->frame_slots = init->frame_slots; + p_dec->packet_slots = init->packet_slots; + //!< decoder parameters + mpp_buf_slot_setup(p_dec->frame_slots, AVS2_MAX_BUF_NUM); + + p_dec->mem = mpp_calloc(Avs2dMemory_t, 1); + MEM_CHECK(ret, p_dec->mem); + p_dec->p_header = &p_dec->mem->headerbuf; + p_dec->p_header->size = MAX_HEADER_SIZE; + p_dec->p_header->pbuf = mpp_calloc(RK_U8, p_dec->p_header->size); + MEM_CHECK(ret, p_dec->p_header->pbuf); + + p_dec->p_stream = &p_dec->mem->streambuf; + p_dec->p_stream->size = MAX_STREAM_SIZE; + p_dec->p_stream->pbuf = mpp_calloc(RK_U8, p_dec->p_stream->size); + MEM_CHECK(ret, p_dec->p_stream->pbuf); + + p_dec->p_nals = mpp_calloc(Avs2dNalu_t, MAX_NALU_NUM); + MEM_CHECK(ret, p_dec->p_nals); + p_dec->nal_allocated = MAX_NALU_NUM; + p_dec->nal_cnt = 0; + + mpp_packet_init(&p_dec->task_pkt, p_dec->p_stream->pbuf, p_dec->p_stream->size); + mpp_packet_set_length(p_dec->task_pkt, 0); + MEM_CHECK(ret, p_dec->task_pkt); + + mpp_slots_set_prop(p_dec->frame_slots, SLOTS_WIDTH_ALIGN, rkv_ctu_64_align); + +__RETURN: + AVS2D_PARSE_TRACE("Out."); + return ret; +__FAILED: + avs2d_deinit(decoder); + + return ret; +} + +MPP_RET avs2d_reset(void *decoder) +{ + MPP_RET ret = MPP_OK; + Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + + AVS2D_PARSE_TRACE("In."); + + //!< flush dpb + avs2d_dpb_flush(p_dec); + + //!< reset parser parameters + avs2d_reset_parser(p_dec); + + //!< reset decoder parameters + p_dec->pkt_no = 0; + p_dec->frame_no = 0; + p_dec->has_get_eos = 0; + + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +MPP_RET avs2d_flush(void *decoder) +{ + MPP_RET ret = MPP_OK; + Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + AVS2D_PARSE_TRACE("In."); + + dpb_remove_unused_frame(p_dec); + + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +MPP_RET avs2d_control(void *decoder, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_OK; + + AVS2D_PARSE_TRACE("In."); + (void)decoder; + (void)cmd_type; + (void)param; + AVS2D_PARSE_TRACE("Out."); + return ret; +} + + +MPP_RET avs2d_prepare(void *decoder, MppPacket pkt, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + RK_S64 pts = -1; + RK_S64 dts = -1; + RK_U32 length = 0; + RK_U32 pkt_eos = 0; + + AVS2D_PARSE_TRACE("In."); + INP_CHECK(ret, !decoder && !pkt && !task); + + task->valid = 0; + + pkt_eos = mpp_packet_get_eos(pkt); + + pts = mpp_packet_get_pts(pkt); + dts = mpp_packet_get_dts(pkt); + length = (RK_U32)mpp_packet_get_length(pkt); + + AVS2D_DBG(AVS2D_DBG_INPUT, "[pkt_in_timeUs] in_pts=%lld, dts=%lld, len=%d, eos=%d, pkt_no=%lld\n", + pts, dts, length, pkt_eos, p_dec->pkt_no); + p_dec->pkt_no++; + + AVS2D_DBG(AVS2D_DBG_INPUT, "packet length %d, eos %d\n", length, pkt_eos); + + if (pkt_eos) { + p_dec->has_get_eos = 1; + task->flags.eos = 1; + } + + if (!length) { + AVS2D_PARSE_TRACE("Input have no stream."); + task->valid = 0; + + if (pkt_eos) + avs2d_dpb_flush(p_dec); + + goto __RETURN; + } + + if (!p_dec->init.cfg->base.split_parse) { + ret = avs2d_parse_prepare_fast(p_dec, pkt, task); + } else { + ret = avs2d_parse_prepare_split(p_dec, pkt, task); + } + + if (task->valid) { + //!< bit stream + RK_U32 align_len = MPP_ALIGN(p_dec->p_stream->len + 32, 16); + + memset(p_dec->p_stream->pbuf + p_dec->p_stream->len, + 0, align_len - p_dec->p_stream->len); + + p_dec->syntax.bitstream_size = align_len; + p_dec->syntax.bitstream = p_dec->p_stream->pbuf; + + mpp_packet_set_data(p_dec->task_pkt, p_dec->syntax.bitstream); + mpp_packet_set_length(p_dec->task_pkt, p_dec->syntax.bitstream_size); + mpp_packet_set_size(p_dec->task_pkt, p_dec->p_stream->size); + + mpp_packet_set_pts(p_dec->task_pkt, mpp_packet_get_pts(pkt)); + mpp_packet_set_dts(p_dec->task_pkt, mpp_packet_get_dts(pkt)); + task->input_packet = p_dec->task_pkt; + + p_dec->p_stream->len = 0; + p_dec->p_header->len = 0; + } else { + task->input_packet = NULL; + } + +__RETURN: + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +MPP_RET avs2d_parse(void *decoder, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + AVS2D_PARSE_TRACE("In."); + + task->valid = 0; + + ret = avs2d_parse_stream(p_dec, task); + if (ret) { + mpp_err_f("Parse stream failed!"); + } + if (task->valid) { + AVS2D_PARSE_TRACE("-------- Frame %lld--------", p_dec->frame_no); + avs2d_dpb_insert(p_dec, task); + avs2d_fill_parameters(p_dec, &p_dec->syntax); + avs2d_commit_syntaxs(&p_dec->syntax, task); + AVS2D_PARSE_TRACE("--------------------------"); + } else { + task->flags.parse_err = 1; + } + + if (p_dec->has_get_eos) + avs2d_dpb_flush(p_dec); + + AVS2D_PARSE_TRACE("Out."); + + return ret; +} + +MPP_RET avs2d_callback(void *decoder, void *info) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Avs2dCtx_t *p_dec = (Avs2dCtx_t *)decoder; + DecCbHalDone *ctx = (DecCbHalDone *)info; + HalDecTask *task_dec = (HalDecTask *)ctx->task; + MppFrame mframe = NULL; + MppFrame ref_frm = NULL; + RK_U32 i = 0; + RK_U32 error = 0; + RK_U32 discard = 0; + RK_U32 ref_used = (task_dec->flags.ref_info_valid != 0) ? task_dec->flags.ref_used : 0xff; + RK_U32 ref_used_flag = 0; + + AVS2D_PARSE_TRACE("In."); + mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + + if (!mframe) { + ret = MPP_ERR_UNKNOW; + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: failed to get frame\n"); + goto __FAILED; + } + + if (ctx->hard_err || task_dec->flags.ref_err) { + if (task_dec->flags.used_for_ref) { + error = 1; + } else { + discard = 1; + } + } else { + if (task_dec->flags.ref_miss & ref_used) { + discard = 1; + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: fake ref used, miss 0x%x used 0x%x\n", + task_dec->flags.ref_miss, ref_used); + } + } + + for (i = 0; i < AVS2_MAX_REFS; i++) { + if (task_dec->refer[i] < 0) + continue; + + mpp_buf_slot_get_prop(p_dec->frame_slots, task_dec->refer[i], SLOT_FRAME_PTR, &ref_frm); + if (!ref_frm) + continue; + + ref_used_flag = (ref_used >> i) & 1; + //TODO: In fast mode, ref list isn't kept sync with task flag.ref_used + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: ref_frm poc %d, err %d, dis %d, ref_used %d\n", + mpp_frame_get_poc(ref_frm), mpp_frame_get_errinfo(ref_frm), + mpp_frame_get_discard(ref_frm), ref_used_flag); + + if (ref_used_flag) { + discard |= mpp_frame_get_discard(ref_frm); + error |= mpp_frame_get_errinfo(ref_frm); + } + } + + mpp_frame_set_errinfo(mframe, error); + mpp_frame_set_discard(mframe, discard); + + AVS2D_DBG(AVS2D_DBG_CALLBACK, "[CALLBACK]: frame poc %d, ref=%d, dpberr=%d, harderr=%d, err:dis=%d:%d\n", + mpp_frame_get_poc(mframe), task_dec->flags.used_for_ref, task_dec->flags.ref_err, + ctx->hard_err, error, discard); + +__FAILED: + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +const ParserApi mpp_avs2d = { + .name = "avs2d_parse", + .coding = MPP_VIDEO_CodingAVS2, + .ctx_size = sizeof(Avs2dCtx_t), + .flag = 0, + .init = avs2d_init, + .deinit = avs2d_deinit, + .prepare = avs2d_prepare, + .parse = avs2d_parse, + .reset = avs2d_reset, + .flush = avs2d_flush, + .control = avs2d_control, + .callback = avs2d_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_avs2d); diff --git a/mpp/codec/dec/avs2/avs2d_debug.h b/mpp/codec/dec/avs2/avs2d_debug.h new file mode 100644 index 000000000..995378b38 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_debug.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef AVS2D_DEBUG_H +#define AVS2D_DEBUG_H + +#include "mpp_debug.h" + +#define AVS2D_DBG_ERROR (0x00000001) +#define AVS2D_DBG_ASSERT (0x00000002) +#define AVS2D_DBG_WARNNING (0x00000004) +#define AVS2D_DBG_LOG (0x00000008) + +#define AVS2D_DBG_INPUT (0x00000010) //!< input packet +#define AVS2D_DBG_TIME (0x00000020) //!< input packet +#define AVS2D_DBG_DPB (0x00000040) + +#define AVS2D_DBG_CALLBACK (0x00008000) + +extern RK_U32 avs2d_debug; + +#define AVS2D_PARSE_TRACE(fmt, ...)\ +do {\ + if (AVS2D_DBG_LOG & avs2d_debug)\ + { mpp_log_f(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define avs2d_dbg_dpb(fmt, ...)\ +do {\ + if (AVS2D_DBG_DPB & avs2d_debug)\ + { mpp_log_f(fmt, ## __VA_ARGS__); }\ +} while (0) + + +#define AVS2D_DBG(level, fmt, ...)\ +do {\ + if (level & avs2d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +//!< input check +#define INP_CHECK(ret, val, ...)\ +do {\ + if ((val)) {\ + ret = MPP_ERR_INIT; \ + AVS2D_DBG(AVS2D_DBG_WARNNING, "input empty(%d).\n", __LINE__); \ + goto __RETURN; \ +}} while (0) + +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do {\ + if(!(val)) {\ + ret = MPP_ERR_MALLOC;\ + mpp_err_f("malloc buffer error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + +//!< function return check +#define FUN_CHECK(val)\ +do {\ + if ((val) < 0) {\ + AVS2D_DBG(AVS2D_DBG_WARNNING, "Function error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + +#endif /* AVS2D_DEBUG_H */ diff --git a/mpp/codec/dec/avs2/avs2d_dpb.c b/mpp/codec/dec/avs2/avs2d_dpb.c new file mode 100644 index 000000000..bac05d8e9 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_dpb.c @@ -0,0 +1,863 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "avs2d_dpb" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_compat_impl.h" + +#include "hal_task.h" +#include "avs2d_dpb.h" + +#ifndef INT_MAX +#define INT_MAX 2147483647 /* maximum (signed) int value */ +#endif + +/** + * @brief Calculate dpb size according to specification + * Some bitstream may require larger dpb than declaration, so the largest dpb + * size is used for all bitstream. And this function is commented to silence + * compiler's unused warnning. + */ +static RK_U32 dpb_get_size(Avs2dCtx_t *p_dec) +{ + RK_U32 mini_size = 8; + RK_U32 mini_cu_width, mini_cu_height; + RK_U32 pic_size = 0; + RK_U32 dpb_size = AVS2_MAX_DPB_SIZE; + + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + mini_cu_width = (vsh->horizontal_size + mini_size - 1) / mini_size; + if (vsh->progressive_sequence == 0 && vsh->field_coded_sequence == 0) { + mini_cu_height = (vsh->vertical_size + 2 * mini_size - 1) / (2 * mini_size); + } else { + mini_cu_height = (vsh->vertical_size + mini_size - 1) / mini_size; + } + pic_size = mini_cu_width * mini_size * mini_cu_height * mini_size; + avs2d_dbg_dpb("level_id %d, pic_size %d", vsh->level_id, pic_size); + + switch (vsh->level_id) { + case 0x10: + case 0x12: + case 0x14: + case 0x20: + case 0x22: + dpb_size = 15; + break; + case 0x40: + case 0x42: + case 0x44: + case 0x46: + case 0x48: + case 0x4A: + dpb_size = MPP_MIN(13369344 / pic_size, 16) - 1; + break; + case 0x50: + case 0x52: + case 0x54: + case 0x56: + case 0x58: + case 0x5A: + dpb_size = MPP_MIN(56623104 / pic_size, 16) - 1; + break; + case 0x60: + case 0x62: + case 0x64: + case 0x66: + case 0x68: + case 0x6A: + dpb_size = MPP_MIN(213909504 / pic_size, 16) - 1; + break; + default: + AVS2D_DBG(AVS2D_DBG_WARNNING, "invalid level id(%d)", vsh->level_id); + break; + } + + if (dpb_size < (RK_U32)(vsh->num_of_rps + 1)) { + dpb_size = (RK_U32)(vsh->num_of_rps + 1); + } + dpb_size = MPP_MIN(dpb_size, AVS2_MAX_DPB_SIZE); + + return dpb_size; +} + +static Avs2dFrame_t *new_frame() +{ + MPP_RET ret = MPP_OK; + + Avs2dFrame_t *f = mpp_calloc(Avs2dFrame_t, 1); + MEM_CHECK(ret, f); + f->slot_idx = NO_VAL; + f->doi = NO_VAL; + f->poi = NO_VAL; + + return f; +__FAILED: + (void)ret; + return NULL; +} + +static void dpb_init_management(Avs2dFrameMgr_t *mgr) +{ + mgr->num_of_ref = 0; + mgr->prev_doi = NO_VAL; + mgr->output_poi = NO_VAL; + mgr->tr_wrap_cnt = 0; + + mgr->scene_ref = NULL; + mgr->cur_frm = NULL; + mgr->used_size = 0; + memset(mgr->refs, 0, sizeof(mgr->refs)); + memset(&mgr->cur_rps, 0, sizeof(Avs2dRps_t)); +} + +MPP_RET avs2d_dpb_create(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + AVS2D_PARSE_TRACE("In."); + mgr->dpb_specific_size = dpb_get_size(p_dec); + mgr->dpb_size = 15; + avs2d_dbg_dpb("create dpb, size %d, specific_size %d\n", mgr->dpb_size, mgr->dpb_specific_size); + mgr->dpb = mpp_calloc(Avs2dFrame_t*, mgr->dpb_size); + for (i = 0; i < mgr->dpb_size; i++) { + mgr->dpb[i] = new_frame(); + MEM_CHECK(ret, mgr->dpb[i]); + mpp_frame_init(&mgr->dpb[i]->frame); + avs2d_dbg_dpb("DPB[%d], frame %p", i, mgr->dpb[i]->frame); + MEM_CHECK(ret, mgr->dpb[i]->frame); + } + + dpb_init_management(mgr); + mgr->initial_flag = 1; +__FAILED: + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +MPP_RET avs2d_dpb_destroy(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + AVS2D_PARSE_TRACE("In."); + for (i = 0; i < mgr->dpb_size; i++) { + mpp_frame_deinit(&mgr->dpb[i]->frame); + MPP_FREE(mgr->dpb[i]); + } + + MPP_FREE(mgr->dpb); + mgr->initial_flag = 0; + + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +static void recompute_cycle_order_index(Avs2dFrameMgr_t *mgr, Avs2dPicHeader_t *ph) +{ + RK_U32 i; + RK_S32 wrap_oi; + Avs2dFrame_t *p; + + if (ph->doi < (INT_MAX - 2 * AVS2_DOI_CYCLE)) { + return; + } + + wrap_oi = (mgr->tr_wrap_cnt - 1) * AVS2_DOI_CYCLE; + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + if (p->slot_idx == NO_VAL) { + continue; + } + p->doi -= wrap_oi; + p->poi -= wrap_oi; + } + + ph->doi -= wrap_oi; + if (mgr->output_poi != NO_VAL) { + mgr->output_poi -= wrap_oi; + } +} + +static void compute_frame_order_index(Avs2dCtx_t *p_dec) +{ + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + Avs2dPicHeader_t *ph = &p_dec->ph; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + RK_U32 i = 0; + Avs2dFrame_t *p; + + //!< DOI should be a periodically-repeated value from 0 to 255 + if (mgr->output_poi != -1 && + ph->doi != (mgr->prev_doi + 1) % AVS2_DOI_CYCLE) { + AVS2D_DBG(AVS2D_DBG_WARNNING, "discontinuous DOI (prev: %d --> curr: %d).", mgr->prev_doi, ph->doi); + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + if (p->slot_idx == NO_VAL) { + continue; + } + + if (MPP_ABS(ph->doi - (p->doi % AVS2_DOI_CYCLE)) > 1) { + p->refered_by_others = 0; + p->refered_by_scene = 0; + } + } + } + + //!< update DOI + if (ph->doi < mgr->prev_doi) { + mgr->tr_wrap_cnt++; + } + + mgr->prev_doi = ph->doi; + ph->doi += mgr->tr_wrap_cnt * AVS2_DOI_CYCLE; + recompute_cycle_order_index(mgr, ph); + + avs2d_dbg_dpb("low_delay %d, reorder_delay %d\n", vsh->low_delay, vsh->picture_reorder_delay); + if (vsh->low_delay == 0) { + ph->poi = ph->doi + ph->picture_output_delay - vsh->picture_reorder_delay; + } else { + ph->poi = ph->doi; + } + + mpp_assert(ph->doi >= 0 && ph->poi >= 0); + + if (mgr->output_poi == NO_VAL && ph->picture_type == I_PICTURE) { + mgr->output_poi = ph->poi; + } + + avs2d_dbg_dpb("picuture DOI %d, POI %d, out_delay %d, output_poi %d\n", ph->doi, ph->poi, ph->picture_output_delay, mgr->output_poi); +} + +static RK_S32 is_outputable_frame(Avs2dFrame_t *p) +{ + // if (p && p->slot_idx != NO_VAL && !p->invisible && !p->is_output && p->is_decoded) { + if (p && p->slot_idx != NO_VAL && !p->invisible && !p->is_output) { + return 1; + } + + return 0; +} + +static RK_S32 get_outputable_smallest_poi(Avs2dFrameMgr_t *mgr, RK_S32 *poi, RK_S32 *pos) +{ + RK_U32 i = 0; + RK_S32 find_flag = 0; + RK_S32 min_pos = -1; + RK_S32 min_poi = INT_MAX; + Avs2dFrame_t *p; + + *pos = -1; + *poi = INT_MAX; + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + if (!is_outputable_frame(p)) { + continue; + } + if (min_poi > p->poi) { + min_poi = p->poi; + min_pos = i; + } + if (*poi > p->poi && !p->is_output) { + *poi = p->poi; + *pos = i; + find_flag = 1; + } + } + if (!find_flag) { + *poi = min_poi; + *pos = min_pos; + } + + return find_flag; +} + +/** + * @brief Ouput frame to display queue + * Mark frame at DPB as output, but still remain at DPB + * + * @param p_dec + * @param p + * @return MPP_RET + */ +static MPP_RET output_display_frame(Avs2dCtx_t *p_dec, Avs2dFrame_t *p) +{ + MPP_RET ret = MPP_NOK; + + avs2d_dbg_dpb("In."); + mpp_assert(p); + // if (p->slot_idx >= 0 && !p->invisible && !p->is_output && p->is_decoded) { + if (p->slot_idx >= 0 && !p->invisible && !p->is_output) { + ret = MPP_OK; + p->is_output = 1; + p_dec->frm_mgr.output_poi = p->poi; + mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p_dec->frame_slots, p->slot_idx, QUEUE_DISPLAY); + avs2d_dbg_dpb("output display frame poi %d slot_idx %d, pts %lld", p->poi, p->slot_idx, + mpp_frame_get_pts(p->frame)); + } + + avs2d_dbg_dpb("Out. ret = %d", ret); + return ret; +} + +/** + * @brief Remove frame from DPB + * + * @param p_dec + * @param p + * @return MPP_RET + */ +static MPP_RET dpb_remove_frame(Avs2dCtx_t *p_dec, Avs2dFrame_t *p) +{ + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + MppFrame frame = p->frame; + + avs2d_dbg_dpb("In."); + + if (p->picture_type == GB_PICTURE || p->invisible) { + MppBuffer buffer = NULL; + mpp_buf_slot_get_prop(p_dec->frame_slots, p->slot_idx, SLOT_BUFFER, &buffer); + mpp_buffer_put(buffer); + } + + mpp_buf_slot_clr_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE); + avs2d_dbg_dpb("dpb remove frame slot_idx %d, doi %d poi %d, dpb used %d", + p->slot_idx, p->doi, p->poi, mgr->used_size); + + memset(p, 0, sizeof(Avs2dFrame_t)); + p->frame = frame; + p->slot_idx = NO_VAL; + p->doi = NO_VAL; + p->poi = NO_VAL; + mgr->used_size--; + + avs2d_dbg_dpb("Out."); + return MPP_OK; +} + +static RK_S32 is_refered(Avs2dFrame_t *p) +{ + mpp_assert(p); + if (p->refered_by_others || p->refered_by_scene) { + return 1; + } + + return 0; +} + +static void unmark_refered(Avs2dFrame_t *p) +{ + mpp_assert(p); + p->refered_by_scene = 0; + p->refered_by_others = 0; +} + +static void unmark_other_refered(Avs2dFrame_t *p) +{ + p->refered_by_others = 0; +} + +static MPP_RET dpb_remove_scene_frame(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + Avs2dFrame_t *p = NULL; + Avs2dPicHeader_t *ph = &p_dec->ph; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + avs2d_dbg_dpb("In."); + if (ph->picture_type == G_PICTURE || ph->picture_type == GB_PICTURE) { + if (mgr->scene_ref) { + p = mgr->scene_ref; + p->refered_by_scene = 0; + //!< remove GB frame directly + if (p->picture_type == GB_PICTURE) { + FUN_CHECK(ret = dpb_remove_frame(p_dec, p)); + } + mgr->scene_ref = NULL; + } + } + +__FAILED: + avs2d_dbg_dpb("Out."); + return ret; +} + +MPP_RET dpb_remove_unused_frame(Avs2dCtx_t *p_dec) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_OK; + Avs2dFrame_t *p = NULL; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + AVS2D_PARSE_TRACE("In."); + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + if (p->slot_idx == NO_VAL) { + continue; + } + + if ((MPP_ABS(p->poi - p_dec->ph.poi) >= AVS2_MAX_POC_DISTANCE)) { + p->refered_by_others = 0; + p->refered_by_scene = 0; + } + + if ((p->is_output || p->invisible) && !is_refered(p)) { + FUN_CHECK(ret = dpb_remove_frame(p_dec, p)); + } + } + +__FAILED: + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +static Avs2dFrame_t *dpb_get_one_frame(Avs2dFrameMgr_t *mgr, Avs2dSeqHeader_t *vsh, Avs2dPicHeader_t *ph) +{ + RK_U32 i; + Avs2dFrame_t *p = NULL; + + //!< get paired field frame + if (vsh->field_coded_sequence) { + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + if (p->slot_idx == NO_VAL) { + continue; + } + + if (p->poi == ph->poi) { + return p; + } + } + } + + //!< get unused frame + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + if (p->slot_idx == NO_VAL) { + break; + } + } + + return p; +} + +static Avs2dFrame_t *dpb_alloc_frame(Avs2dCtx_t *p_dec, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + MppFrame mframe = NULL; + Avs2dFrame_t *frm = NULL; + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + Avs2dPicHeader_t *ph = &p_dec->ph; + Avs2dSeqExtHeader_t *exh = &p_dec->exh; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + avs2d_dbg_dpb("In."); + frm = dpb_get_one_frame(mgr, vsh, ph); + if (!frm) { + mpp_err("Failed to get dpb buffer.\n"); + return NULL; + } + + mframe = frm->frame; + frm->doi = ph->doi; + frm->poi = ph->poi; + frm->out_delay = ph->picture_output_delay; + frm->picture_type = ph->picture_type; + frm->invisible = (frm->picture_type == GB_PICTURE); + frm->scene_frame_flag = (frm->picture_type == G_PICTURE || frm->picture_type == GB_PICTURE); + frm->intra_frame_flag = (frm->scene_frame_flag || frm->picture_type == I_PICTURE); + frm->refered_by_scene = frm->scene_frame_flag; + frm->refered_by_others = (frm->picture_type != GB_PICTURE && mgr->cur_rps.refered_by_others); + avs2d_dbg_dpb("frame picture type %d, ref by others %d\n", frm->picture_type, frm->refered_by_others); + if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 8) { + mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP); + } else if (vsh->chroma_format == CHROMA_420 && vsh->bit_depth == 10) { + mpp_frame_set_fmt(mframe, MPP_FMT_YUV420SP_10BIT); + } + + if (MPP_FRAME_FMT_IS_FBC(p_dec->init.cfg->base.out_fmt)) { + // fbc header alignment + RK_U32 fbc_hdr_stride = MPP_ALIGN(vsh->horizontal_size, 64); + + mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | (p_dec->init.cfg->base.out_fmt & (MPP_FRAME_FBC_MASK))); + + if (*compat_ext_fbc_hdr_256_odd) + fbc_hdr_stride = MPP_ALIGN(vsh->horizontal_size, 256) | 256; + + mpp_frame_set_fbc_hdr_stride(mframe, fbc_hdr_stride); + + if (mpp_get_soc_type() < ROCKCHIP_SOC_RK3576) { + RK_U32 ctu_size = 1 << (p_dec->vsh.lcu_size); + // fbc output frame update + mpp_frame_set_offset_y(mframe, 8); + mpp_frame_set_ver_stride(mframe, MPP_ALIGN(vsh->vertical_size, ctu_size) + 16); + } + } else if (MPP_FRAME_FMT_IS_TILE(p_dec->init.cfg->base.out_fmt)) + mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | (p_dec->init.cfg->base.out_fmt & (MPP_FRAME_TILE_FLAG))); + + if (p_dec->is_hdr) + mpp_frame_set_fmt(mframe, mpp_frame_get_fmt(mframe) | MPP_FRAME_HDR); + + if (p_dec->init.cfg->base.enable_thumbnail && p_dec->init.hw_info->cap_down_scale) + mpp_frame_set_thumbnail_en(mframe, p_dec->init.cfg->base.enable_thumbnail); + else + mpp_frame_set_thumbnail_en(mframe, 0); + + mpp_frame_set_width(mframe, vsh->horizontal_size); + mpp_frame_set_height(mframe, vsh->vertical_size); + mpp_frame_set_pts(mframe, mpp_packet_get_pts(task->input_packet)); + mpp_frame_set_dts(mframe, mpp_packet_get_dts(task->input_packet)); + mpp_frame_set_errinfo(mframe, 0); + mpp_frame_set_discard(mframe, 0); + mpp_frame_set_poc(mframe, frm->poi); + if (p_dec->got_exh) { + mpp_frame_set_color_primaries(mframe, exh->color_primaries); + mpp_frame_set_color_trc(mframe, exh->transfer_characteristics); + mpp_frame_set_colorspace(mframe, exh->matrix_coefficients); + } + mpp_frame_set_content_light(mframe, p_dec->content_light); + mpp_frame_set_mastering_display(mframe, p_dec->display_meta); + if (p_dec->hdr_dynamic_meta && p_dec->hdr_dynamic) { + mpp_frame_set_hdr_dynamic_meta(mframe, p_dec->hdr_dynamic_meta); + p_dec->hdr_dynamic = 0; + } + if (vsh->progressive_sequence) { + frm->frame_mode = MPP_FRAME_FLAG_FRAME; + frm->frame_coding_mode = MPP_FRAME_FLAG_FRAME; + + if (p_dec->init.cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) { + frm->frame_mode |= MPP_FRAME_FLAG_DEINTERLACED; + } + } else { + frm->frame_mode = MPP_FRAME_FLAG_PAIRED_FIELD; + if (vsh->field_coded_sequence) { + frm->frame_coding_mode = MPP_FRAME_FLAG_PAIRED_FIELD; + if (ph->top_field_first) { + frm->frame_mode |= MPP_FRAME_FLAG_TOP_FIRST; + frm->frame_coding_mode |= MPP_FRAME_FLAG_TOP_FIRST; + } else { + frm->frame_mode |= MPP_FRAME_FLAG_BOT_FIRST; + frm->frame_coding_mode |= MPP_FRAME_FLAG_BOT_FIRST; + } + } else { + frm->frame_coding_mode = MPP_FRAME_FLAG_FRAME; + if (ph->top_field_first) { + frm->frame_mode |= MPP_FRAME_FLAG_TOP_FIRST; + } else { + frm->frame_mode |= MPP_FRAME_FLAG_BOT_FIRST; + } + } + } + + mpp_frame_set_mode(mframe, frm->frame_mode); + ret = mpp_buf_slot_get_unused(p_dec->frame_slots, &frm->slot_idx); + mpp_assert(ret == MPP_OK); + mgr->used_size++; + avs2d_dbg_dpb("get unused buf slot %d, DPB used %d \n", frm->slot_idx, mgr->used_size); + avs2d_dbg_dpb("Out."); + return frm; +} + +static MPP_RET dpb_output_next_frame(Avs2dCtx_t *p_dec, RK_S32 continuous) +{ + MPP_RET ret = MPP_NOK; + RK_S32 poi, pos; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + AVS2D_PARSE_TRACE("In."); + if (get_outputable_smallest_poi(mgr, &poi, &pos)) { + avs2d_dbg_dpb("smallest poi %d, pos %d, output_poi %d\n", + poi, pos, mgr->output_poi); + + if ((poi - mgr->output_poi <= 1) || + (mgr->dpb[pos]->doi + mgr->dpb[pos]->out_delay < mgr->cur_frm->doi) || + !continuous) { + FUN_CHECK(ret = output_display_frame(p_dec, mgr->dpb[pos])); + if (!is_refered(mgr->dpb[pos])) { + FUN_CHECK(ret = dpb_remove_frame(p_dec, mgr->dpb[pos])); + } + } + } + + AVS2D_PARSE_TRACE("Out."); +__FAILED: + return ret; +} + +static Avs2dFrame_t *find_ref_frame(Avs2dFrameMgr_t *mgr, RK_S32 doi) +{ + RK_U32 i; + Avs2dFrame_t *p = NULL; + + avs2d_dbg_dpb("In."); + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + + if (p->slot_idx == NO_VAL || p->doi == NO_VAL) { + continue; + } + + if (p->doi >= 0 && doi == p->doi) { + if (!is_refered(p)) { + // DOI matched but not a referenced frame + p->error_flag = 1; + AVS2D_DBG(AVS2D_DBG_WARNNING, "invalid reference frame [doi: %d].\n", doi); + } + avs2d_dbg_dpb("found ref[%d] at slot_idx %d, doi %d", i, p->slot_idx, p->doi); + return p; + } + } + + AVS2D_DBG(AVS2D_DBG_ERROR, "reference frame [doi: %d] missed.\n", doi); + avs2d_dbg_dpb("Out."); + return NULL; +} + +MPP_RET dpb_update_refs(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + RK_S32 doi_of_remove; + Avs2dFrame_t *p; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + Avs2dRps_t *p_rps = &mgr->cur_rps; + avs2d_dbg_dpb("In."); + + if (!mgr->cur_frm) { + ret = MPP_NOK; + AVS2D_DBG(AVS2D_DBG_WARNNING, "No current frame to update dpb.\n"); + goto __FAILED; + } + + //!< update scene reference frame + if (mgr->cur_frm->refered_by_scene) { + mgr->scene_ref = mgr->cur_frm; + } + + //!< update reference frame flag + for (i = 0; i < p_rps->num_to_remove; i++) { + doi_of_remove = mgr->cur_frm->doi - p_rps->remove_pic[i]; + avs2d_dbg_dpb("current doi %d, remove_pic[%d]=%d", mgr->cur_frm->doi, i, p_rps->remove_pic[i]); + p = find_ref_frame(mgr, doi_of_remove); + if (p) { + unmark_other_refered(p); + avs2d_dbg_dpb("unmark picture refered, slot_idx %d, doi %d poi %d", + p->slot_idx, p->doi, p->poi); + } + } + +__FAILED: + avs2d_dbg_dpb("Out. ret %d", ret); + return ret; +} + +static MPP_RET dpb_set_frame_refs(Avs2dCtx_t *p_dec, Avs2dFrameMgr_t *mgr, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 i = 0; + RK_U8 error_flag = 0; + RK_U8 num_of_ref; + RK_S32 doi_of_ref; + Avs2dRps_t *p_rps; + Avs2dFrame_t *p_cur, *p; + RK_U8 replace_ref_flag = 0; + + (void) task; + + avs2d_dbg_dpb("In."); + memset(mgr->refs, 0, sizeof(mgr->refs)); + + p_cur = mgr->cur_frm; + mgr->num_of_ref = 0; + p_rps = &mgr->cur_rps; + num_of_ref = p_rps->num_of_ref; + task->flags.ref_miss = 0; + for (i = 0; i < num_of_ref; i++) { + doi_of_ref = p_cur->doi - p_rps->ref_pic[i]; + p = find_ref_frame(mgr, doi_of_ref); + if (!p) { + task->flags.ref_miss |= 1 << i; + avs2d_dbg_dpb("Missing ref doi %d", doi_of_ref); + } else { + mgr->refs[mgr->num_of_ref] = p; + mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_HAL_INPUT); + } + + mgr->num_of_ref++; + } + + if (mgr->num_of_ref < 1 && !p_cur->intra_frame_flag) { + error_flag = 1; + } else if (p_cur->picture_type == S_PICTURE) { + p_cur->refered_bg_frame = 1; + if (!mgr->scene_ref) { + error_flag = 1; + } else if (mgr->scene_ref != mgr->refs[0] || mgr->num_of_ref > 1) { + AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame(doi %ld ~ %ld) for S.\n", + mgr->scene_ref->doi, mgr->refs[0] ? mgr->refs[0]->doi : -1); + replace_ref_flag = 1; + p_dec->syntax.refp.scene_ref_replace_pos = 0; + } + } else if ((p_cur->picture_type == P_PICTURE || p_cur->picture_type == F_PICTURE) && + p_dec->ph.background_reference_flag) { + p_cur->refered_bg_frame = 1; + if (!mgr->scene_ref) { + error_flag = 1; + } else { + replace_ref_flag = 1; + p_dec->syntax.refp.scene_ref_replace_pos = mgr->num_of_ref - 1; + } + } else if (p_cur->picture_type == B_PICTURE && + (mgr->num_of_ref != 2 || (mgr->refs[0] && mgr->refs[0]->poi <= p_cur->poi) || + (mgr->refs[1] && mgr->refs[1]->poi >= p_cur->poi))) { + error_flag = 1; + } + + if (replace_ref_flag && mgr->scene_ref) { + p_dec->syntax.refp.scene_ref_enable = 1; + p_dec->syntax.refp.scene_ref_slot_idx = mgr->scene_ref->slot_idx; + } else { + p_dec->syntax.refp.scene_ref_enable = 0; + } + + if (error_flag) { + ret = MPP_NOK; + mpp_frame_set_errinfo(p_cur->frame, MPP_FRAME_ERR_UNKNOW); + AVS2D_DBG(AVS2D_DBG_ERROR, "Error reference frame for picture(%d).\n", p_cur->picture_type); + goto __FAILED; + } + +__FAILED: + avs2d_dbg_dpb("Out. ret %d", ret); + return ret; +} + +MPP_RET avs2d_dpb_insert(Avs2dCtx_t *p_dec, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + Avs2dFrame_t *p; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + AVS2D_PARSE_TRACE("In."); + + compute_frame_order_index(p_dec); + + //!< output frame from dpb + dpb_output_next_frame(p_dec, 1); + + //!< remove scene(G/GB) frame(scene dbp has only one G/GB) + dpb_remove_scene_frame(p_dec); + + //!< remove unused dpb frame + dpb_remove_unused_frame(p_dec); + + //!< set task with new frame + p = dpb_alloc_frame(p_dec, task); + p_dec->frame_no++; + avs2d_dbg_dpb("get unused frame from dpb %d", p->slot_idx); + if (!p) { + ret = MPP_ERR_NOMEM; + mpp_err("Failed to alloc dpb frame.\n"); + goto __FAILED; + } + + mgr->cur_frm = p; + mpp_buf_slot_set_prop(p_dec->frame_slots, p->slot_idx, SLOT_FRAME, p->frame); + mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(p_dec->frame_slots, p->slot_idx, SLOT_HAL_OUTPUT); + + //!< set task output + task->output = mgr->cur_frm->slot_idx; + avs2d_dbg_dpb("curframe slot_idx %d\n", mgr->cur_frm->slot_idx); + + //!< set task refers + ret = dpb_set_frame_refs(p_dec, mgr, task); + if (ret) + task->flags.ref_err = 0; + + for (i = 0; i < mgr->num_of_ref; i++) { + task->refer[i] = mgr->refs[i] ? mgr->refs[i]->slot_idx : -1; + if (mgr->refs[i]) { + task->refer[i] = mgr->refs[i]->slot_idx; + avs2d_dbg_dpb("task refer[%d] slot_idx %d doi %d poi %d", i, task->refer[i], mgr->refs[i]->doi, mgr->refs[i]->poi); + } else { + task->refer[i] = -1; + avs2d_dbg_dpb("task refer[%d] missing ref\n", i); + } + } + + //!< update dpb by rps + dpb_update_refs(p_dec); + + avs2d_dbg_dpb("--------DPB INFO--------"); + avs2d_dbg_dpb("dpb_idx slt_idx doi poi type out refered\n"); + Avs2dFrame_t *tmp; + for (i = 0; i < mgr->dpb_size; i++) { + tmp = mgr->dpb[i]; + avs2d_dbg_dpb("%02d %02d %02d %02d %c %d %d", + i, tmp->slot_idx, tmp->doi, tmp->poi, PICTURE_TYPE_TO_CHAR(tmp->picture_type), + tmp->is_output, tmp->refered_by_others | tmp->refered_by_scene); + } + avs2d_dbg_dpb("------------------------"); + +__FAILED: + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +MPP_RET avs2d_dpb_flush(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + Avs2dFrame_t *p; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + + AVS2D_PARSE_TRACE("In."); + //!< unmark all frames refered flag + for (i = 0; i < mgr->dpb_size; i++) { + p = mgr->dpb[i]; + if (p->slot_idx != NO_VAL) { + unmark_refered(p); + } + } + + //!< remove all unused frame + dpb_remove_unused_frame(p_dec); + + //!< output frames in POI order + while (mgr->used_size) { + if ((ret = dpb_output_next_frame(p_dec, 0)) != MPP_OK) { + break; + } + } + + //!< reset dpb management + dpb_init_management(mgr); + + AVS2D_PARSE_TRACE("Out."); + return ret; +} diff --git a/mpp/codec/dec/avs2/avs2d_dpb.h b/mpp/codec/dec/avs2/avs2d_dpb.h new file mode 100644 index 000000000..4a1776dc5 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_dpb.h @@ -0,0 +1,37 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AVS2D_DPB_H +#define AVS2D_DPB_H + +#include "avs2d_global.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET avs2d_dpb_create(Avs2dCtx_t *p_dec); +MPP_RET avs2d_dpb_destroy(Avs2dCtx_t *p_dec); +MPP_RET avs2d_dpb_insert(Avs2dCtx_t *p_dec, HalDecTask *task); +MPP_RET avs2d_dpb_flush(Avs2dCtx_t *p_dec); +MPP_RET dpb_remove_unused_frame(Avs2dCtx_t *p_dec); +Avs2dFrame_t* get_dpb_frm_by_slot_idx(Avs2dFrameMgr_t *mgr, RK_S32 slot_idx); + +#ifdef __cplusplus +} +#endif + +#endif /* AVS2D_DPB_H */ diff --git a/mpp/codec/dec/avs2/avs2d_global.h b/mpp/codec/dec/avs2/avs2d_global.h new file mode 100644 index 000000000..5162df457 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_global.h @@ -0,0 +1,345 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef AVS2D_GLOBAL_H +#define AVS2D_GLOBAL_H + +#include "mpp_list.h" +#include "parser_api.h" +#include "mpp_bitread.h" + +#include "avs2d_debug.h" +#include "avs2d_syntax.h" + +//!< read & check marker bit +#define READ_MARKER_BIT(bitctx)\ +do {\ + RK_U8 bval;\ + READ_ONEBIT(bitctx, &bval);\ + if ((bval) != 1) {\ + AVS2D_DBG(AVS2D_DBG_WARNNING, "expected marker_bit 1 while received 0(%d).\n", __LINE__); \ +}} while (0) + +#define MAX_NALU_NUM (20) +#define MAX_HEADER_SIZE (2*1024) +#define MAX_STREAM_SIZE (2*1024*1024) + +#define AVS2_START_CODE (0x00000100) + +//!< NALU type +#define AVS2_SLICE_MIN_START_CODE (AVS2_START_CODE | 0x00) +#define AVS2_SLICE_MAX_START_CODE (AVS2_START_CODE | 0x8F) +#define AVS2_VIDEO_SEQUENCE_START_CODE (AVS2_START_CODE | 0xb0) +#define AVS2_VIDEO_SEQUENCE_END_CODE 0x000001B1 +#define AVS2_USER_DATA_START_CODE 0x000001B2 +#define AVS2_I_PICTURE_START_CODE 0x000001B3 +#define AVS2_EXTENSION_START_CODE 0x000001B5 +#define AVS2_PB_PICTURE_START_CODE 0x000001B6 +#define AVS2_VIDEO_EDIT_CODE 0x000001B7 + +//!< SEQ/PIC EXTENSION 4bit +#define AVS2_SEQUENCE_DISPLAY_EXT_ID (0x2) +#define AVS2_TEMPORAL_SCALABLE_EXT_ID (0x3) +#define AVS2_COPYRIGHT_EXT_ID (0x4) +#define AVS2_HDR_DYNAMIC_METADATA_EXT_ID (0x5) +#define AVS2_PICTURE_DISPLAY_EXT_ID (0x7) +#define AVS2_MASTERING_DISPLAY_AND_CONTENT_METADATA_EXT_ID (0xA) +#define AVS2_CAMERA_PARAMETERS_EXT_ID (0xB) + +//!< profile +#define MAIN_PICTURE_PROFILE 0x12 +#define MAIN_PROFILE 0x20 +#define MAIN10_PROFILE 0x22 + +//!< max reference frame number +#define AVS2_MAX_REFS 7 +//!< max rps number +#define AVS2_MAX_RPS_NUM 32 +#define AVS2_MAX_BUF_NUM 19 +#define AVS2_MAX_DPB_SIZE 15 +#define AVS2_DOI_CYCLE 256 +#define AVS2_MAX_POC_DISTANCE 128 + +#define ALF_MAX_FILTERS 16 +#define ALF_MAX_COEFS 9 + +#define UNDETAILED 0 +#define DETAILED 1 +#define WQP_SIZE 6 +#define NO_VAL -1 + + +//!< chroma format +enum avs2d_chroma_format_e { + CHROMA_400 = 0, + CHROMA_420 = 1, + CHROMA_422 = 2, + CHROMA_444 = 3 +}; + +//!< picture type +typedef enum avs2d_picture_type_e { + I_PICTURE = 0, + P_PICTURE = 1, + B_PICTURE = 2, + F_PICTURE = 3, + G_PICTURE = 4, + GB_PICTURE = 5, + S_PICTURE = 6, +} Avs2dPicType; + +#define PICTURE_TYPE_TO_CHAR(x) ((x) == 0 ? 'I' : ((x) == 1 ? 'P' : ((x) == 2 ? 'B' : ((x) == 3 ? 'F' : ((x) == 4 ? 'G' : ((x) == 5 ? 'g' : ((x) == 6 ? 'S' : 'E'))))))) + +typedef struct avs2d_nalu_t { + RK_U32 header; + RK_U32 length; + RK_U32 data_pos; + RK_U8 eof; //!< end of frame stream +} Avs2dNalu_t; + +//!< reference picture set (RPS) +typedef struct avs2d_rps_t { + RK_U8 ref_pic[AVS2_MAX_REFS]; //!< delta DOI of ref pic + RK_U8 remove_pic[8]; //!< delta DOI of removed pic + RK_U8 num_of_ref; //!< number of reference picture + RK_U8 num_to_remove; //!< number of removed picture + RK_U8 refered_by_others; //!< referenced by others + RK_U32 reserved; //!< reserved 4 bytes +} Avs2dRps_t; + +//!< sequence set information +typedef struct avs2d_sequence_header_t { + RK_U8 profile_id; + RK_U8 level_id; + RK_U8 progressive_sequence; + RK_U8 field_coded_sequence; + RK_U32 horizontal_size; + RK_U32 vertical_size; + + RK_U8 chroma_format; + RK_U8 sample_precision; + RK_U8 encoding_precision; + RK_U8 bit_depth; + RK_U8 aspect_ratio; + RK_U8 frame_rate_code; + RK_U32 bit_rate; + RK_U8 low_delay; + RK_U8 enable_temporal_id; + RK_U32 bbv_buffer_size; + RK_U8 lcu_size; + + RK_U8 enable_weighted_quant; //!< weight quant enable? + RK_U8 enable_background_picture;//!< background picture enabled? + RK_U8 enable_mhp_skip; //!< mhpskip enabled? + RK_U8 enable_dhp; //!< dhp enabled? + RK_U8 enable_wsm; //!< wsm enabled? + RK_U8 enable_amp; //!< AMP(asymmetric motion partitions) enabled? + RK_U8 enable_nsqt; //!< use NSQT? + RK_U8 enable_nsip; //!< use NSIP? + RK_U8 enable_2nd_transform; //!< secondary transform enabled? + RK_U8 enable_sao; //!< SAO enabled? + RK_U8 enable_alf; //!< ALF enabled? + RK_U8 enable_pmvr; //!< PMVR enabled? + RK_U8 enable_clf; //!< cross loop filter flag + RK_U8 picture_reorder_delay; //!< picture reorder delay + RK_U8 num_of_rps; //!< rps set number + + Avs2dRps_t seq_rps[AVS2_MAX_RPS_NUM];//!< RPS at sequence level + RK_U32 seq_wq_matrix[2][64]; //!< sequence base weighting quantization matrix + +} Avs2dSeqHeader_t; + +//!< sequence display extension header +typedef struct avs2d_sequence_extension_header_t { + RK_U8 video_format; + RK_U8 sample_range; + RK_U8 color_description; + RK_U32 color_primaries; + RK_U32 transfer_characteristics; + RK_U32 matrix_coefficients; + RK_U32 display_horizontal_size; + RK_U32 display_vertical_size; + RK_U8 td_mode_flag; + RK_U32 td_packing_mode; + RK_U8 view_reverse_flag; +} Avs2dSeqExtHeader_t; + +//!< intra/inter picture header +typedef struct avs2d_picture_header { + Avs2dPicType picture_type; + RK_U8 picture_coding_type; + RK_U32 bbv_delay; + RK_U8 time_code_flag; + RK_U32 time_code; + RK_U8 background_picture_flag; + RK_U8 background_picture_output_flag; + RK_U8 background_pred_flag; + RK_U8 background_reference_flag; + + RK_S32 doi; + RK_S32 poi; + RK_U8 temporal_id; + RK_U8 picture_output_delay; + RK_U32 bbv_check_times; + RK_U8 progressive_frame; + RK_U8 picture_structure; + RK_U8 top_field_first; + RK_U8 repeat_first_field; + RK_U8 is_top_field; + RK_U8 fixed_picture_qp; + RK_U8 picture_qp; + + RK_U8 enable_random_decodable; + RK_U8 enable_loop_filter; + RK_U8 loop_filter_parameter_flag; + RK_S8 alpha_c_offset; + RK_S8 beta_offset; + RK_U8 enable_chroma_quant_param; + RK_S8 chroma_quant_param_delta_cb; + RK_S8 chroma_quant_param_delta_cr; + RK_U8 enable_pic_weight_quant; + RK_U8 pic_wq_data_index; + RK_U8 wq_param_index; + RK_U8 wq_model; + RK_S32 wq_param_delta1[WQP_SIZE]; + RK_S32 wq_param_delta2[WQP_SIZE]; + + RK_U8 enable_pic_alf_y; + RK_U8 enable_pic_alf_cb; + RK_U8 enable_pic_alf_cr; + RK_U8 alf_filter_num; + RK_U8 alf_filter_pattern[ALF_MAX_FILTERS]; + RK_U8 alf_coeff_idx_tab[ALF_MAX_FILTERS]; + RK_S32 alf_coeff_y[ALF_MAX_FILTERS][ALF_MAX_COEFS]; + RK_S32 alf_coeff_cb[ALF_MAX_COEFS]; + RK_S32 alf_coeff_cr[ALF_MAX_COEFS]; + + RK_U32 pic_wq_matrix[2][64]; //!< picture weighting quantization matrix + RK_U32 pic_wq_param[WQP_SIZE]; +} Avs2dPicHeader_t; + +typedef struct avs2d_frame_t { + MppFrame frame; + RK_U32 frame_mode; //!< mode used for display + RK_U32 frame_coding_mode; //!< mode used for decoding, Field/Frame + Avs2dPicType picture_type; //!< I/G/GB/P/F/B/S + RK_S32 slot_idx; + RK_S32 doi; + RK_S32 poi; + RK_S32 out_delay; + RK_U8 invisible; //!< GB visible = 0 + RK_U8 scene_frame_flag; //!< G/GB + RK_U8 intra_frame_flag; //!< I/G/GB + RK_U8 refered_bg_frame; //!< ref G/GB + RK_U8 refered_by_others; + RK_U8 refered_by_scene; + RK_U8 error_flag; + RK_U8 is_output; // mark for picture has been output to display queue +} Avs2dFrame_t; + +typedef enum avs2d_nal_type { + + NAL_SEQ_START = 0xb0, + NAL_SEQ_END = 0xb1, + NAL_USER_DATA = 0xb2, + NAL_INTRA_PIC = 0xb3, + NAL_EXTENSION = 0xb5, + NAL_INTER_PIC = 0xb6, + NAL_VIDEO_EDIT = 0xb7 +} Avs2dNalType; + +typedef struct avs2d_nal_t { + RK_U8 *data; + RK_U32 size; + RK_U32 nal_type; + RK_U32 start_found; + RK_U32 end_found; +} Avs2dNal; + +typedef struct avs2d_stream_buf_t { + RK_U8 *pbuf; + RK_U32 size; //Total buffer size + RK_U32 len; // Used length +} Avs2dStreamBuf_t; + +typedef struct avs2d_memory_t { + Avs2dStreamBuf_t nals_buf; + Avs2dStreamBuf_t headerbuf; + Avs2dStreamBuf_t streambuf; +} Avs2dMemory_t; + +typedef struct avs2d_frame_mgr_t { + RK_U32 dpb_size; + RK_U32 dpb_specific_size; + RK_U32 used_size; + Avs2dFrame_t **dpb; + RK_U8 num_of_ref; + Avs2dFrame_t *refs[AVS2_MAX_REFS]; + Avs2dFrame_t *scene_ref; + Avs2dFrame_t *cur_frm; + Avs2dRps_t cur_rps; + + RK_S32 prev_doi; + RK_S32 output_poi; + RK_S32 tr_wrap_cnt; + RK_U8 initial_flag; +} Avs2dFrameMgr_t; + +#define END_NOT_FOUND (-100) +#define START_NOT_FOUND (-101) +#define MPP_INPUT_BUFFER_PADDING_SIZE 8 +#define AVS2D_PACKET_SPLIT_LAST_KEPT_LENGTH (3) +#define AVS2D_PACKET_SPLIT_CHECKER_BUFFER_SIZE (7) +#define AVS2D_START_CODE_SIZE (4) + +//!< decoder parameters +typedef struct avs2_dec_ctx_t { + MppBufSlots frame_slots; + MppBufSlots packet_slots; + + MppPacket task_pkt; + Avs2dMemory_t *mem; //!< resotre slice data to decoder + Avs2dStreamBuf_t *p_stream; + Avs2dStreamBuf_t *p_header; + + //-------- input --------------- + ParserCfg init; + RK_U64 frame_no; + RK_U64 pkt_no; + RK_U8 has_get_eos; + + //-------- current -------------- + Avs2dNalu_t *p_nals; + RK_U32 nal_cnt; + RK_U32 nal_allocated; + + //-------- video -------------- + BitReadCtx_t bitctx; + Avs2dSeqHeader_t vsh; + Avs2dSeqExtHeader_t exh; + Avs2dPicHeader_t ph; + MppFrameMasteringDisplayMetadata display_meta; + MppFrameContentLightMetadata content_light; + MppFrameHdrDynamicMeta *hdr_dynamic_meta; + + Avs2dSyntax_t syntax; + Avs2dFrameMgr_t frm_mgr; + RK_U32 cur_wq_matrix[2][64]; + + //!<------------------------------------ + RK_U32 got_vsh; + RK_U32 got_exh; + RK_U32 got_keyframe; + RK_U8 enable_wq;//!< seq&pic weight quant enable + RK_U32 prev_start_code; + RK_U32 new_seq_flag; + RK_U8 prev_tail_data[AVS2D_PACKET_SPLIT_CHECKER_BUFFER_SIZE]; // store the last 3 bytes at the lowest addr + RK_U32 prev_state; + RK_U32 new_frame_flag; + RK_U32 is_hdr; + RK_U32 hdr_dynamic; +} Avs2dCtx_t; + +#endif /* AVS2D_GLOBAL_H */ diff --git a/mpp/codec/dec/avs2/avs2d_parse.c b/mpp/codec/dec/avs2/avs2d_parse.c new file mode 100644 index 000000000..cf29e04d9 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_parse.c @@ -0,0 +1,680 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "avs2d_parse" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_packet_impl.h" +#include "hal_task.h" + +#include "avs2d_dpb.h" +#include "avs2d_parse.h" +#include "avs2d_ps.h" +#include "avs2d_global.h" + +#define AVS2_ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define AVS2_ISUNIT(x) ((x) == 0xB0 || (x) == 0xB1 || (x) == 0xB2 || AVS2_ISPIC(x)) +#define AVS2_IS_START_CODE(x) (((x) & 0xffffff00) == 0x100) + +#define AVS2_IS_SLICE_START_CODE(x) ((x) >= AVS2_SLICE_MIN_START_CODE && (x) <= AVS2_SLICE_MAX_START_CODE) +#define AVS2_IS_HEADER(x) ((x) >= AVS2_VIDEO_SEQUENCE_START_CODE && (x) <= AVS2_VIDEO_EDIT_CODE) +#define AVS2_IS_PIC_START_CODE(x) ((x) == AVS2_I_PICTURE_START_CODE || (x) == AVS2_PB_PICTURE_START_CODE) + +/** + * @brief Find start code 00 00 01 xx + * + * Search 01 first and check the previous 2 bytes and the following 1 bytes. + * If it is start code, return the value of start code at U32 as 0x000001xx. + * + * @param buf_start the start of input buffer + * @param buf_end the end of input buffer + * @param pos output value, the position of start code + * @return RK_U32 + */ +static RK_U32 avs2_find_start_code(RK_U8 *buf_start, RK_U8* buf_end, RK_U8 **pos) +{ + RK_U8 *buf_ptr = NULL; + RK_U8 *ptr = buf_start; + RK_U32 remain_size = buf_end - buf_start + 1; + + while (ptr < buf_end) { + buf_ptr = memchr(ptr, 0x01, remain_size); + + if (!buf_ptr) { + return 0; + } + + //check the position of "01" + if ((buf_ptr < buf_end) && (buf_ptr - buf_start > 1) && + (*(buf_ptr - 1) == 0) && (*(buf_ptr - 2) == 0)) { + //found 00 00 01 xx + *pos = buf_ptr + 1; + return (AVS2_START_CODE | *(buf_ptr + 1)); + } else { + // keep search at remaining buffer + remain_size = remain_size - (buf_ptr - ptr + 1); + ptr = buf_ptr + 1; + } + } + + return 0; +} + +static MPP_RET avs2_add_nalu_header(Avs2dCtx_t *p_dec, RK_U32 header) +{ + MPP_RET ret = MPP_OK; + Avs2dNalu_t *p_nal = NULL; + + if (p_dec->nal_cnt + 1 > p_dec->nal_allocated) { + Avs2dNalu_t *new_buffer = mpp_realloc(p_dec->p_nals, Avs2dNalu_t, p_dec->nal_allocated + MAX_NALU_NUM); + + if (!new_buffer) { + mpp_err_f("Realloc NALU buffer failed, could not add more NALU!"); + ret = MPP_ERR_NOMEM; + } else { + p_dec->p_nals = new_buffer; + memset(&p_dec->p_nals[p_dec->nal_allocated], 0, MAX_NALU_NUM * sizeof(Avs2dNalu_t)); + p_dec->nal_allocated += MAX_NALU_NUM; + AVS2D_PARSE_TRACE("Realloc NALU buffer, current allocated %d", p_dec->nal_allocated); + } + } + + p_nal = p_dec->p_nals + p_dec->nal_cnt; + p_nal->header = header; + p_nal->length = 0; + p_nal->data_pos = 0; + p_nal->eof = 0; + + p_dec->nal_cnt++; + AVS2D_PARSE_TRACE("add header 0x%x, nal_cnt %d", header, p_dec->nal_cnt); + + return ret; +} + +/** + * @brief store nalu startcode and data + * TODO If nalu data isn't appear right after startcode, it may go wrong + * + * @param p_dec + * @param p_start + * @param len + * @param start_code + * @return MPP_RET + */ +static MPP_RET store_nalu(Avs2dCtx_t *p_dec, RK_U8 *p_start, RK_U32 len, RK_U32 start_code) +{ + MPP_RET ret = MPP_OK; + Avs2dNalu_t *p_nalu = &p_dec->p_nals[p_dec->nal_cnt - 1]; + Avs2dStreamBuf_t *p_header = NULL;; + RK_U32 add_size = SZ_1K; + RK_U8 *data_ptr = NULL; + + if (AVS2_IS_SLICE_START_CODE(start_code)) { + p_header = p_dec->p_stream; + add_size = SZ_512K; + } else if (AVS2_IS_HEADER(start_code)) { + p_header = p_dec->p_header; + add_size = SZ_1K; + } + + if ((p_header->len + len) > p_header->size) { + mpp_log_f("realloc %p p_header->pbuf, size %d, len %d %d", p_header->pbuf, p_header->size, p_header->len, len); + RK_U32 new_size = p_header->size + add_size + len; + RK_U8 * new_buffer = mpp_realloc(p_header->pbuf, RK_U8, new_size); + mpp_log_f("realloc %p, size %d", p_header->pbuf, new_size); + if (!new_buffer) { + mpp_err_f("Realloc header buffer with size %d failed", new_size); + return MPP_ERR_NOMEM; + } else { + p_header->pbuf = new_buffer; + memset(p_header->pbuf + p_header->size, 0, new_size - p_header->size); + p_header->size = new_size; + } + } + + data_ptr = p_header->pbuf + p_header->len; + + if (p_nalu->length == 0) { + p_nalu->data_pos = p_header->len; + } + + if (len > 0) { + memcpy(data_ptr, p_start, len); + p_nalu->length += len; + p_header->len += len; + } + + return ret; +} + +/** + * @brief Once got a new frame, reset previous stored nalu data an buffer + * + * @param p_dec + * @return MPP_RET + */ +static MPP_RET reset_nalu_buf(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + + AVS2D_PARSE_TRACE("In."); + p_dec->prev_start_code = 0; + p_dec->new_frame_flag = 0; + + memset(p_dec->prev_tail_data, 0xff, AVS2D_PACKET_SPLIT_CHECKER_BUFFER_SIZE); + + if (p_dec->p_stream) { + memset(p_dec->p_stream->pbuf, 0, p_dec->p_stream->size); + p_dec->p_stream->len = 0; + } + + if (p_dec->p_header) { + memset(p_dec->p_header->pbuf, 0, p_dec->p_header->size); + p_dec->p_header->len = 0; + } + + if (p_dec->p_nals) { + memset(p_dec->p_nals, 0, sizeof(Avs2dNalu_t) * p_dec->nal_allocated); + p_dec->nal_cnt = 0; + } + + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +static MPP_RET parse_seq_dispay_ext_header(BitReadCtx_t *bitctx, Avs2dSeqExtHeader_t *exh) +{ + MPP_RET ret = MPP_OK; + + READ_BITS(bitctx, 3, &exh->video_format); + READ_ONEBIT(bitctx, &exh->sample_range); + READ_ONEBIT(bitctx, &exh->color_description); + + if (exh->color_description) { + READ_BITS(bitctx, 8, &exh->color_primaries); + READ_BITS(bitctx, 8, &exh->transfer_characteristics); + READ_BITS(bitctx, 8, &exh->matrix_coefficients); + } + READ_BITS(bitctx, 14, &exh->display_horizontal_size); + READ_MARKER_BIT(bitctx); + READ_BITS(bitctx, 14, &exh->display_vertical_size); + + READ_ONEBIT(bitctx, &exh->td_mode_flag); + if (exh->td_mode_flag) { + READ_BITS(bitctx, 8, &exh->td_packing_mode); + READ_ONEBIT(bitctx, &exh->view_reverse_flag); + } + + return ret; +__BITREAD_ERR: + return ret = bitctx->ret; +} + +static MPP_RET parse_mastering_display_and_content_meta(BitReadCtx_t *bitctx, + MppFrameMasteringDisplayMetadata *display_meta, + MppFrameContentLightMetadata *content_light) +{ + MPP_RET ret = MPP_OK; + RK_U32 i = 0; + RK_U16 value; + + /* display metadata */ + for (i = 0; i < 3; i++) { + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + display_meta->display_primaries[i][0] = value; + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + display_meta->display_primaries[i][1] = value; + } + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + display_meta->white_point[0] = value; + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + display_meta->white_point[1] = value; + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + display_meta->max_luminance = value; + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + display_meta->min_luminance = value; + + /* content light */ + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + content_light->MaxCLL = value; + READ_BITS(bitctx, 16, &value); + READ_MARKER_BIT(bitctx); + content_light->MaxFALL = value; + + SKIP_BITS(bitctx, 16); + + return ret; +__BITREAD_ERR: + return ret = bitctx->ret; +} + +static MPP_RET parse_hdr_dynamic_meta_extension(BitReadCtx_t *bitctx, MppFrameHdrDynamicMeta *hdr_meta) +{ + MPP_RET ret = MPP_OK; + RK_S32 country_code, provider_code; + RK_U16 terminal_provide_oriented_code; + (void)hdr_meta; + /* hdr_dynamic_metadata_type */ + SKIP_BITS(bitctx, 4); + READ_BITS(bitctx, 8, &country_code); + READ_BITS(bitctx, 16, &provider_code); + READ_BITS(bitctx, 16, &terminal_provide_oriented_code); + AVS2D_PARSE_TRACE("country_code=%d provider_code=%d terminal_provider_code %d\n", + country_code, provider_code, terminal_provide_oriented_code); + + //TODO: copy dynamic data + + return ret; +__BITREAD_ERR: + return ret = bitctx->ret; +} + +static MPP_RET parse_extension_header(Avs2dCtx_t *p_dec, BitReadCtx_t *bitctx) +{ + MPP_RET ret = MPP_OK; + RK_U32 val_temp = 0; + + READ_BITS(bitctx, 4, &val_temp); //!< extension_start_code + switch (val_temp) { + case AVS2_SEQUENCE_DISPLAY_EXT_ID: + FUN_CHECK(ret = parse_seq_dispay_ext_header(bitctx, &p_dec->exh)); + p_dec->got_exh = 1; + if (p_dec->exh.transfer_characteristics == MPP_FRAME_TRC_BT2020_10 || + p_dec->exh.transfer_characteristics == MPP_FRAME_TRC_BT1361_ECG) + p_dec->is_hdr = 1; + break; + case AVS2_MASTERING_DISPLAY_AND_CONTENT_METADATA_EXT_ID: + FUN_CHECK(ret = parse_mastering_display_and_content_meta(bitctx, + &p_dec->display_meta, + &p_dec->content_light)); + p_dec->is_hdr = 1; + break; + case AVS2_HDR_DYNAMIC_METADATA_EXT_ID: + FUN_CHECK(ret = parse_hdr_dynamic_meta_extension(bitctx, p_dec->hdr_dynamic_meta)); + break; + default: + break; + } + + return ret; +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +MPP_RET avs2d_reset_parser(Avs2dCtx_t *p_dec) +{ + AVS2D_PARSE_TRACE("In."); + p_dec->got_vsh = 0; + p_dec->got_exh = 0; + p_dec->got_keyframe = 0; + p_dec->enable_wq = 0; + p_dec->new_frame_flag = 0; + p_dec->new_seq_flag = 0; + reset_nalu_buf(p_dec); + AVS2D_PARSE_TRACE("Out."); + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* commit buffer to hal +*********************************************************************** +*/ +MPP_RET avs2d_commit_syntaxs(Avs2dSyntax_t *syntax, HalDecTask *task) +{ + task->syntax.number = 1; + task->syntax.data = syntax; + + return MPP_OK; +} + +MPP_RET avs2d_fill_parameters(Avs2dCtx_t *p_dec, Avs2dSyntax_t *syntax) +{ + RK_S32 i = 0; + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + Avs2dPicHeader_t *ph = &p_dec->ph; + Avs2dFrameMgr_t *mgr = &p_dec->frm_mgr; + PicParams_Avs2d *pp = &syntax->pp; + RefParams_Avs2d *refp = &syntax->refp; + AlfParams_Avs2d *alfp = &syntax->alfp; + WqmParams_Avs2d *wqmp = &syntax->wqmp; + + //!< sequence header + pp->chroma_format_idc = vsh->chroma_format; + pp->pic_width_in_luma_samples = MPP_ALIGN(vsh->horizontal_size, 8); + pp->pic_height_in_luma_samples = MPP_ALIGN(vsh->vertical_size, 8); + pp->bit_depth_luma_minus8 = vsh->bit_depth - 8; + pp->bit_depth_chroma_minus8 = vsh->bit_depth - 8; + pp->lcu_size = vsh->lcu_size; + pp->progressive_sequence = vsh->progressive_sequence; + pp->field_coded_sequence = vsh->field_coded_sequence; + pp->multi_hypothesis_skip_enable_flag = vsh->enable_mhp_skip; + pp->dual_hypothesis_prediction_enable_flag = vsh->enable_dhp; + pp->weighted_skip_enable_flag = vsh->enable_wsm; + pp->asymmetrc_motion_partitions_enable_flag = vsh->enable_amp; + pp->nonsquare_quadtree_transform_enable_flag = vsh->enable_nsqt; + pp->nonsquare_intra_prediction_enable_flag = vsh->enable_nsip; + pp->secondary_transform_enable_flag = vsh->enable_2nd_transform; + pp->sample_adaptive_offset_enable_flag = vsh->enable_sao; + pp->adaptive_loop_filter_enable_flag = vsh->enable_alf; + pp->pmvr_enable_flag = vsh->enable_pmvr; + pp->cross_slice_loopfilter_enable_flag = vsh->enable_clf; + + //!< picture header + pp->picture_type = ph->picture_type; + pp->scene_reference_enable_flag = ph->background_reference_flag; + pp->bottom_field_picture_flag = (vsh->field_coded_sequence) && (!ph->is_top_field); + // pp->bottom_field_picture_flag = !ph->is_top_field; + pp->fixed_picture_qp = ph->fixed_picture_qp; + pp->picture_qp = ph->picture_qp; + pp->loop_filter_disable_flag = !ph->enable_loop_filter; + pp->alpha_c_offset = ph->alpha_c_offset; + pp->beta_offset = ph->beta_offset; + + //!< current poc + pp->cur_poc = ph->poi; + + //!< picture reference params + refp->ref_pic_num = mgr->num_of_ref; + memset(refp->ref_poc_list, -1, sizeof(refp->ref_poc_list)); + for (i = 0; i < mgr->num_of_ref; i++) { + refp->ref_poc_list[i] = mgr->refs[i] ? mgr->refs[i]->poi : -1; + } + + //!< picture alf params + alfp->enable_pic_alf_y = ph->enable_pic_alf_y; + alfp->enable_pic_alf_cb = ph->enable_pic_alf_cb; + alfp->enable_pic_alf_cr = ph->enable_pic_alf_cr; + alfp->alf_filter_num_minus1 = (ph->alf_filter_num > 0) ? (ph->alf_filter_num - 1) : 0; + memcpy(alfp->alf_coeff_idx_tab, ph->alf_coeff_idx_tab, sizeof(ph->alf_coeff_idx_tab)); + memcpy(alfp->alf_coeff_y, ph->alf_coeff_y, sizeof(ph->alf_coeff_y)); + memcpy(alfp->alf_coeff_cb, ph->alf_coeff_cb, sizeof(ph->alf_coeff_cb)); + memcpy(alfp->alf_coeff_cr, ph->alf_coeff_cr, sizeof(ph->alf_coeff_cr)); + + //!< picture wqm params + wqmp->pic_weight_quant_enable_flag = p_dec->enable_wq; + wqmp->chroma_quant_param_delta_cb = ph->chroma_quant_param_delta_cb; + wqmp->chroma_quant_param_delta_cr = ph->chroma_quant_param_delta_cr; + memcpy(wqmp->wq_matrix, p_dec->cur_wq_matrix, sizeof(p_dec->cur_wq_matrix)); + + return MPP_OK; +} + +MPP_RET avs2_split_nalu(Avs2dCtx_t *p_dec, RK_U8 *buf_start, RK_U32 buf_length, RK_U32 over_read, RK_U32 *remain) +{ + MPP_RET ret = MPP_OK; + + RK_U8 *start_code_ptr = NULL; + RK_U32 start_code = 0; + RK_U32 nalu_len = 0; + + RK_U8 *buf_end; + + buf_end = buf_start + buf_length - 1; + + start_code = avs2_find_start_code(buf_start, buf_end, &start_code_ptr); + + if (start_code_ptr) { + AVS2D_PARSE_TRACE("Found start_code 0x%08x at offset 0x%08x, prev_starcode 0x%08x\n", + start_code, start_code_ptr - buf_start, p_dec->prev_start_code); + if (!p_dec->new_seq_flag) { + if (start_code == AVS2_VIDEO_SEQUENCE_START_CODE) { + AVS2D_PARSE_TRACE("Found the first video_sequence_start_code"); + p_dec->nal_cnt = 0; + avs2_add_nalu_header(p_dec, AVS2_VIDEO_SEQUENCE_START_CODE); + p_dec->new_seq_flag = 1; + p_dec->prev_start_code = AVS2_VIDEO_SEQUENCE_START_CODE; + } else { + AVS2D_PARSE_TRACE("Skip start code before first video_sequence_start_code"); + } + + *remain = buf_end - start_code_ptr; + } else { + if (start_code == AVS2_VIDEO_SEQUENCE_START_CODE) { + AVS2D_PARSE_TRACE("Found repeated video_sequence_start_code"); + } + + if (AVS2_IS_START_CODE(p_dec->prev_start_code) && p_dec->prev_start_code != AVS2_USER_DATA_START_CODE) { + nalu_len = start_code_ptr - buf_start - 3; + if (nalu_len > over_read) { + store_nalu(p_dec, buf_start + over_read, nalu_len - over_read, p_dec->prev_start_code); + } + } + + if (AVS2_IS_SLICE_START_CODE(p_dec->prev_start_code) && !AVS2_IS_SLICE_START_CODE(start_code)) { + p_dec->new_frame_flag = 1; + p_dec->p_nals[p_dec->nal_cnt - 1].eof = 1; + *remain = buf_end - start_code_ptr + 4; + } else { + if (start_code != AVS2_USER_DATA_START_CODE) + avs2_add_nalu_header(p_dec, start_code); + + // need to put slice start code to stream buffer + if (AVS2_IS_SLICE_START_CODE(start_code)) { + store_nalu(p_dec, start_code_ptr - 3, 4, start_code); + } else if (start_code == AVS2_VIDEO_SEQUENCE_END_CODE) { + p_dec->p_nals[p_dec->nal_cnt - 1].eof = 1; + } + + *remain = buf_end - start_code_ptr; + } + + p_dec->prev_start_code = start_code; + } + } else { + if (!p_dec->new_seq_flag) { + AVS2D_PARSE_TRACE("Skip data code before first video_sequence_start_code"); + } else { + if (AVS2_IS_START_CODE(p_dec->prev_start_code)) { + nalu_len = buf_length; + if (nalu_len > over_read) { + store_nalu(p_dec, buf_start + over_read, nalu_len - over_read, p_dec->prev_start_code); + } + } + } + + *remain = 0; + } + + return ret; +} + +MPP_RET avs2d_parse_prepare_split(Avs2dCtx_t *p_dec, MppPacket *pkt, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + RK_U8 *p_curdata = NULL; + RK_U8 *p_start = NULL; + RK_U8 *p_end = NULL; + RK_U32 pkt_length = 0; + RK_U32 first_read_length = 0; + + AVS2D_PARSE_TRACE("In."); + + pkt_length = (RK_U32) mpp_packet_get_length(pkt); + + p_curdata = p_start = (RK_U8 *) mpp_packet_get_pos(pkt); + p_end = p_start + pkt_length - 1; + + // Combine last packet data + first_read_length = (pkt_length >= 4) ? 4 : pkt_length; + memcpy(p_dec->prev_tail_data + 3, p_curdata, first_read_length); + + RK_U32 remain = 0; + + AVS2D_PARSE_TRACE("previous data[0~3]=%02x %02x %02x, first_read_length %d\n", + p_dec->prev_tail_data[0], p_dec->prev_tail_data[1], + p_dec->prev_tail_data[2], first_read_length); + ret = avs2_split_nalu(p_dec, p_dec->prev_tail_data, + AVS2D_PACKET_SPLIT_CHECKER_BUFFER_SIZE, + AVS2D_PACKET_SPLIT_LAST_KEPT_LENGTH, + &remain); + p_curdata = p_start + first_read_length - remain; + AVS2D_PARSE_TRACE("remian length %d\n", remain); + + remain = 0; + + while (p_curdata < p_end) { + ret = avs2_split_nalu(p_dec, p_curdata, p_end - p_curdata + 1, 0, &remain); + + if (ret) { + break; + } else { + p_curdata = p_end - remain + 1; + } + + if (p_dec->new_frame_flag || (p_dec->nal_cnt > 1 && p_dec->p_nals[p_dec->nal_cnt - 1].eof == 1)) { + task->valid = 1; + break; + } + } + + mpp_packet_set_pos(pkt, p_curdata); + + if (remain == 0) { + memset(p_dec->prev_tail_data, 0xff, 3); + + if (pkt_length >= 3) { + p_dec->prev_tail_data[0] = p_end[0]; + p_dec->prev_tail_data[1] = p_end[-1]; + p_dec->prev_tail_data[2] = p_end[-2]; + } + } + + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +/** + * @brief Every packet is a complete frame. + * So we don't have to do combine data from different packet. + * + * @param p_dec + * @param pkt + * @param task + * @return MPP_RET + */ +MPP_RET avs2d_parse_prepare_fast(Avs2dCtx_t *p_dec, MppPacket *pkt, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + RK_U8 *p_curdata = NULL; + RK_U8 *p_start = NULL; + RK_U8 *p_end = NULL; + RK_U32 pkt_length = 0; + RK_U32 remain = 0; + + AVS2D_PARSE_TRACE("In."); + + pkt_length = (RK_U32) mpp_packet_get_length(pkt); + + p_curdata = p_start = (RK_U8 *) mpp_packet_get_pos(pkt); + p_end = p_start + pkt_length - 1; + + while (p_curdata < p_end) { + ret = avs2_split_nalu(p_dec, p_curdata, p_end - p_curdata + 1, 0, &remain); + + if (ret) { + break; + } else { + p_curdata = p_end - remain + 1; + } + + if (p_dec->new_frame_flag || (p_dec->nal_cnt && (p_dec->p_nals[p_dec->nal_cnt - 1].eof == 1)) + || p_curdata >= p_end) { + task->valid = 1; + break; + } + } + + // sequence_end_code and video_edit_code at the end of a packet will be ignored. + mpp_packet_set_pos(pkt, p_end + 1); + AVS2D_PARSE_TRACE("after split, remain %d, task->valid %d\n", remain, task->valid); + + AVS2D_PARSE_TRACE("Out."); + return ret; +} + +MPP_RET avs2d_parse_stream(Avs2dCtx_t *p_dec, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + Avs2dNalu_t *p_nalu = p_dec->p_nals; + AVS2D_PARSE_TRACE("In."); + RK_U32 i = 0; + for (i = 0 ; i < p_dec->nal_cnt; i++) { + RK_U32 startcode = p_nalu->header; + + AVS2D_PARSE_TRACE("start code[%d] 0x%08x\n", i, startcode); + if (!AVS2_IS_SLICE_START_CODE(startcode)) { + RK_U8 *data_ptr = p_dec->p_header->pbuf + p_nalu->data_pos; + memset(&p_dec->bitctx, 0, sizeof(BitReadCtx_t)); + AVS2D_PARSE_TRACE("bitread ctx, pos %d, length %d\n", p_nalu->data_pos, p_nalu->length); + mpp_set_bitread_ctx(&p_dec->bitctx, data_ptr, p_nalu->length); + mpp_set_bitread_pseudo_code_type(&p_dec->bitctx, PSEUDO_CODE_AVS2); + } + + switch (startcode) { + case AVS2_VIDEO_SEQUENCE_START_CODE: + ret = avs2d_parse_sequence_header(p_dec); + if (ret == MPP_OK) { + p_dec->got_vsh = 1; + + if (p_dec->new_seq_flag && !p_dec->frm_mgr.initial_flag) { + avs2d_dpb_create(p_dec); + } + } + p_dec->got_exh = 0; + break; + case AVS2_I_PICTURE_START_CODE: + case AVS2_PB_PICTURE_START_CODE: + ret = avs2d_parse_picture_header(p_dec, startcode); + break; + case AVS2_EXTENSION_START_CODE: + ret = parse_extension_header(p_dec, &p_dec->bitctx); + break; + case AVS2_USER_DATA_START_CODE: + case AVS2_VIDEO_SEQUENCE_END_CODE: + case AVS2_VIDEO_EDIT_CODE: + break; + default: + if (AVS2_IS_SLICE_START_CODE(startcode)) { + task->valid = 1; + } + + break; + } + + p_nalu++; + } + + reset_nalu_buf(p_dec); + + AVS2D_PARSE_TRACE("Out. task->valid = %d", task->valid); + return ret; +} diff --git a/mpp/codec/dec/avs2/avs2d_parse.h b/mpp/codec/dec/avs2/avs2d_parse.h new file mode 100644 index 000000000..156beaf50 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_parse.h @@ -0,0 +1,41 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AVS2D_PARSE_H +#define AVS2D_PARSE_H + +#include "avs2d_global.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET avs2d_reset_parser(Avs2dCtx_t *p_dec); + +MPP_RET avs2d_commit_syntaxs(Avs2dSyntax_t *syntax, HalDecTask *task); +MPP_RET avs2d_fill_parameters(Avs2dCtx_t *p_dec, Avs2dSyntax_t *syntax); + +MPP_RET avs2d_parse_prepare_fast(Avs2dCtx_t *p_dec, MppPacket *pkt, HalDecTask *task); +MPP_RET avs2d_parse_prepare_split(Avs2dCtx_t *p_dec, MppPacket *pkt, HalDecTask *task); +MPP_RET avs2d_parse_stream(Avs2dCtx_t *p_dec, HalDecTask *task); +RK_S32 avs2d_split_frame(void *sc, const RK_U8 **poutbuf, RK_S32 *poutbuf_size, + const RK_U8 *buf, RK_U32 buf_size, RK_S64 pts, RK_S64 dts); + +#ifdef __cplusplus +} +#endif + +#endif /* AVS2D_PARSE_H */ diff --git a/mpp/codec/dec/avs2/avs2d_ps.c b/mpp/codec/dec/avs2/avs2d_ps.c new file mode 100644 index 000000000..2531c0526 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_ps.c @@ -0,0 +1,823 @@ +/* +* +* Copyright 2021 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "avs2d_ps" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_packet_impl.h" +#include "hal_task.h" + +#include "avs2d_ps.h" + +static const RK_U32 wq_param_default[2][6] = { + { 67, 71, 71, 80, 80, 106}, + { 64, 49, 53, 58, 58, 64 } +}; + +static const RK_U32 g_WqMDefault4x4[16] = { + 64, 64, 64, 68, + 64, 64, 68, 72, + 64, 68, 76, 80, + 72, 76, 84, 96 +}; + +static const RK_U32 g_WqMDefault8x8[64] = { + 64, 64, 64, 64, 68, 68, 72, 76, + 64, 64, 64, 68, 72, 76, 84, 92, + 64, 64, 68, 72, 76, 80, 88, 100, + 64, 68, 72, 80, 84, 92, 100, 28, + 68, 72, 80, 84, 92, 104, 112, 128, + 76, 80, 84, 92, 104, 116, 132, 152, + 96, 100, 104, 116, 124, 140, 164, 188, + 104, 108, 116, 128, 152, 172, 192, 216 +}; + +static const RK_U8 WeightQuantModel[4][64] = { + // l a b c d h + // 0 1 2 3 4 5 + { + // Mode 0 + 0, 0, 0, 4, 4, 4, 5, 5, + 0, 0, 3, 3, 3, 3, 5, 5, + 0, 3, 2, 2, 1, 1, 5, 5, + 4, 3, 2, 2, 1, 5, 5, 5, + 4, 3, 1, 1, 5, 5, 5, 5, + 4, 3, 1, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5 + }, { + // Mode 1 + 0, 0, 0, 4, 4, 4, 5, 5, + 0, 0, 4, 4, 4, 4, 5, 5, + 0, 3, 2, 2, 2, 1, 5, 5, + 3, 3, 2, 2, 1, 5, 5, 5, + 3, 3, 2, 1, 5, 5, 5, 5, + 3, 3, 1, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5 + }, { + // Mode 2 + 0, 0, 0, 4, 4, 3, 5, 5, + 0, 0, 4, 4, 3, 2, 5, 5, + 0, 4, 4, 3, 2, 1, 5, 5, + 4, 4, 3, 2, 1, 5, 5, 5, + 4, 3, 2, 1, 5, 5, 5, 5, + 3, 2, 1, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5 + }, { + // Mode 3 + 0, 0, 0, 3, 2, 1, 5, 5, + 0, 0, 4, 3, 2, 1, 5, 5, + 0, 4, 4, 3, 2, 1, 5, 5, + 3, 3, 3, 3, 2, 5, 5, 5, + 2, 2, 2, 2, 5, 5, 5, 5, + 1, 1, 1, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5 + } +}; + +static const RK_U8 WeightQuantModel4x4[4][16] = { + // l a b c d h + // 0 1 2 3 4 5 + { + // Mode 0 + 0, 4, 3, 5, + 4, 2, 1, 5, + 3, 1, 1, 5, + 5, 5, 5, 5 + }, { + // Mode 1 + 0, 4, 4, 5, + 3, 2, 2, 5, + 3, 2, 1, 5, + 5, 5, 5, 5 + }, { + // Mode 2 + 0, 4, 3, 5, + 4, 3, 2, 5, + 3, 2, 1, 5, + 5, 5, 5, 5 + }, { + // Mode 3 + 0, 3, 1, 5, + 3, 4, 2, 5, + 1, 2, 2, 5, + 5, 5, 5, 5 + } +}; + +static const RK_U32 *wq_get_default_matrix(RK_U32 sizeId) +{ + return (sizeId == 0) ? g_WqMDefault4x4 : g_WqMDefault8x8; +} + +static void wq_init_frame_quant_param(Avs2dCtx_t *p_dec) +{ + RK_U32 i, j, k; + Avs2dPicHeader_t *ph = &p_dec->ph; + + if (!p_dec->enable_wq || ph->pic_wq_data_index != 1) { + return; + } + + //wq_param_index == 0) { + for (i = 0; i < WQP_SIZE; i++) { + ph->pic_wq_param[i] = wq_param_default[DETAILED][i]; + } + } else if (ph->wq_param_index == 1) { + for (i = 0; i < WQP_SIZE; i++) { + ph->pic_wq_param[i] = ph->wq_param_delta1[i] + wq_param_default[UNDETAILED][i]; + } + } else if (ph->wq_param_index == 2) { + for (i = 0; i < WQP_SIZE; i++) { + ph->pic_wq_param[i] = ph->wq_param_delta2[i] + wq_param_default[DETAILED][i]; + } + } + + //!< reconstruct the weighting matrix + for (j = 0; j < 8; j++) { + for (i = 0; i < 8; i++) { + k = WeightQuantModel[ph->wq_model][j * 8 + i]; + ph->pic_wq_matrix[1][j * 8 + i] = ph->pic_wq_param[k]; + } + } + + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) { + k = WeightQuantModel4x4[ph->wq_model][j * 4 + i]; + ph->pic_wq_matrix[0][j * 4 + i] = ph->pic_wq_param[k]; + } + } +} + +static void wq_update_frame_matrix(Avs2dCtx_t *p_dec) +{ + RK_U32 i, j; + RK_U32 size_id, wqm_size; + RK_U32 (*frm_wqm)[64]; + + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + Avs2dPicHeader_t *ph = &p_dec->ph; + RK_U32 (*cur_wqm)[64] = p_dec->cur_wq_matrix; + + mpp_assert(ph->pic_wq_data_index <= 2); + + if (!p_dec->enable_wq) { + for (size_id = 0; size_id < 2; size_id++) { + for (i = 0; i < 64; i++) { + cur_wqm[size_id][i] = 64; + } + } + } else { + if (ph->pic_wq_data_index == 0) { + frm_wqm = vsh->seq_wq_matrix; + } else { + frm_wqm = ph->pic_wq_matrix; + } + + for (size_id = 0; size_id < 2; size_id++) { + wqm_size = MPP_MIN(1 << (size_id + 2), 8); + for (i = 0; i < wqm_size; i++) { + for (j = 0; j < wqm_size; j++) { + cur_wqm[size_id][i * wqm_size + j] = frm_wqm[size_id][i * wqm_size + j]; + } + } + } + } +} + +static MPP_RET parse_sequence_wqm(BitReadCtx_t *bitctx, Avs2dSeqHeader_t *vsh) +{ + MPP_RET ret = MPP_OK; + RK_U8 load_seq_wquant_data_flag; + RK_U32 i, j, size_id, wqm_size; + const RK_U32 *seq_wqm; + + READ_ONEBIT(bitctx, &load_seq_wquant_data_flag); + + for (size_id = 0; size_id < 2; size_id++) { + wqm_size = MPP_MIN(1 << (size_id + 2), 8); + if (load_seq_wquant_data_flag == 1) { + for (j = 0; j < wqm_size; j++) { + for (i = 0; i < wqm_size; i++) { + READ_UE(bitctx, &vsh->seq_wq_matrix[size_id][j * wqm_size + i]); + } + } + } else if (load_seq_wquant_data_flag == 0) { + seq_wqm = wq_get_default_matrix(size_id); + for (i = 0; i < (wqm_size * wqm_size); i++) { + vsh->seq_wq_matrix[size_id][i] = seq_wqm[i]; + } + } + } + + return ret; +__BITREAD_ERR: + return ret = bitctx->ret; +} + +static MPP_RET parse_one_rps(BitReadCtx_t *bitctx, Avs2dRps_t *rps) +{ + MPP_RET ret = MPP_OK; + RK_U32 j; + + AVS2D_PARSE_TRACE("In"); + READ_ONEBIT(bitctx, &rps->refered_by_others); + + READ_BITS(bitctx, 3, &rps->num_of_ref); + AVS2D_PARSE_TRACE("refered_by_others_flag %d, num_Of_ref %d", rps->refered_by_others, rps->num_of_ref); + if (rps->num_of_ref > AVS2_MAX_REFS) { + ret = MPP_NOK; + mpp_err_f("invalid ref num(%d).\n", rps->num_of_ref); + goto __FAILED; + } + for (j = 0; j < rps->num_of_ref; j++) { + READ_BITS(bitctx, 6, &rps->ref_pic[j]); + AVS2D_PARSE_TRACE("delta_doi_of_ref_pic[%d]=%d", j, rps->ref_pic[j]); + } + + READ_BITS(bitctx, 3, &rps->num_to_remove); + for (j = 0; j < rps->num_to_remove; j++) { + READ_BITS(bitctx, 6, &rps->remove_pic[j]); + AVS2D_PARSE_TRACE("num_of_removed_pic[%d]=%d", j, rps->remove_pic[j]); + } + + READ_MARKER_BIT(bitctx); + AVS2D_PARSE_TRACE("Out ret %d\n", ret); + return ret; +__BITREAD_ERR: + AVS2D_PARSE_TRACE("Out Bit read Err\n"); + return ret = bitctx->ret; +__FAILED: + AVS2D_PARSE_TRACE("Out Failed\n"); + return ret; +} + +MPP_RET avs2d_parse_sequence_header(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + RK_U32 val_temp = 0; + Avs2dRps_t *rps = NULL; + BitReadCtx_t *bitctx = &p_dec->bitctx; + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + + AVS2D_PARSE_TRACE("Bitread buf %p, data %p, buf_len %d, left %d\n", bitctx->buf, bitctx->data_, bitctx->buf_len, bitctx->bytes_left_); + memset(vsh, 0, sizeof(Avs2dSeqHeader_t)); + READ_BITS(bitctx, 8, &vsh->profile_id); + //!< check profile_id + if (vsh->profile_id != 0x12 && vsh->profile_id != 0x20 && vsh->profile_id != 0x22) { + ret = MPP_NOK; + mpp_err_f("profile_id 0x%02x is not supported.\n", vsh->profile_id); + goto __FAILED; + } + READ_BITS(bitctx, 8, &vsh->level_id); + if (vsh->level_id > 0x6A) { + ret = MPP_NOK; + mpp_err_f("level_id 0x%02x is not supported.\n", vsh->level_id); + goto __FAILED; + } + READ_ONEBIT(bitctx, &vsh->progressive_sequence); + READ_ONEBIT(bitctx, &vsh->field_coded_sequence); + READ_BITS(bitctx, 14, &vsh->horizontal_size); + READ_BITS(bitctx, 14, &vsh->vertical_size); + if (vsh->horizontal_size < 16 || vsh->vertical_size < 16) { + ret = MPP_NOK; + mpp_err_f("invalid sequence width(%d), height(%d).\n", + vsh->horizontal_size, vsh->vertical_size); + goto __FAILED; + } + + READ_BITS(bitctx, 2, &vsh->chroma_format); + if (vsh->chroma_format != CHROMA_420) { + ret = MPP_NOK; + mpp_err_f("chroma_format 0x%02x is not supported.\n", vsh->chroma_format); + goto __FAILED; + } + READ_BITS(bitctx, 3, &vsh->sample_precision); + if (vsh->profile_id == MAIN10_PROFILE) { + READ_BITS(bitctx, 3, &vsh->encoding_precision); + } else { + vsh->encoding_precision = 1; + } + vsh->bit_depth = 6 + (vsh->encoding_precision << 1); + + if (vsh->sample_precision < 1 || vsh->sample_precision > 2) { + ret = MPP_NOK; + mpp_err_f("sample_precision 0x%02x is not supported.\n", vsh->sample_precision); + goto __FAILED; + } + if (vsh->encoding_precision < 1 || vsh->encoding_precision > 2) { + ret = MPP_NOK; + mpp_err_f("encoding_precision 0x%02x is not supported.\n", vsh->encoding_precision); + goto __FAILED; + } + + READ_BITS(bitctx, 4, &vsh->aspect_ratio); + READ_BITS(bitctx, 4, &vsh->frame_rate_code); + READ_BITS(bitctx, 18, &val_temp); //!< bit_rate_lower_18 + vsh->bit_rate = val_temp << 12; + READ_MARKER_BIT(bitctx); + READ_BITS(bitctx, 12, &val_temp); //!< bit_rate_upper_12 + vsh->bit_rate += val_temp; + READ_ONEBIT(bitctx, &vsh->low_delay); + READ_MARKER_BIT(bitctx); + READ_ONEBIT(bitctx, &vsh->enable_temporal_id); + READ_BITS(bitctx, 18, &vsh->bbv_buffer_size); + READ_BITS(bitctx, 3, &vsh->lcu_size); + if (vsh->lcu_size < 4 || vsh->lcu_size > 6) { + ret = MPP_NOK; + mpp_err_f("invalid lcu size: %d\n", vsh->lcu_size); + goto __FAILED; + } + + READ_ONEBIT(bitctx, &vsh->enable_weighted_quant); + if (vsh->enable_weighted_quant) { + parse_sequence_wqm(bitctx, vsh); + } + + READ_ONEBIT(bitctx, &val_temp); + vsh->enable_background_picture = val_temp ^ 0x01; + READ_ONEBIT(bitctx, &vsh->enable_mhp_skip); + READ_ONEBIT(bitctx, &vsh->enable_dhp); + READ_ONEBIT(bitctx, &vsh->enable_wsm); + READ_ONEBIT(bitctx, &vsh->enable_amp); + READ_ONEBIT(bitctx, &vsh->enable_nsqt); + READ_ONEBIT(bitctx, &vsh->enable_nsip); + READ_ONEBIT(bitctx, &vsh->enable_2nd_transform); + READ_ONEBIT(bitctx, &vsh->enable_sao); + READ_ONEBIT(bitctx, &vsh->enable_alf); + READ_ONEBIT(bitctx, &vsh->enable_pmvr); + READ_MARKER_BIT(bitctx); + + //!< parse rps + READ_BITS(bitctx, 6, &vsh->num_of_rps); + for (i = 0; i < vsh->num_of_rps; i++) { + rps = &vsh->seq_rps[i]; + AVS2D_PARSE_TRACE("--------rcs[%d]--------", i); + FUN_CHECK(ret = parse_one_rps(bitctx, rps)); + } + + if (vsh->low_delay == 0) { + READ_BITS(bitctx, 5, &vsh->picture_reorder_delay); + } else { + vsh->picture_reorder_delay = 0; + } + READ_ONEBIT(bitctx, &vsh->enable_clf); + READ_BITS(bitctx, 2, &val_temp); //!< reserved 2bits 00 + if (val_temp) { + AVS2D_DBG(AVS2D_DBG_WARNNING, "reserver bits error.\n"); + } + return ret; +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET read_pic_alf_coeff(BitReadCtx_t *bitctx, RK_S32 *alf_coeff) +{ + MPP_RET ret = MPP_OK; + RK_U32 j; + RK_S32 alf_sum = 0; + + for (j = 0; j < ALF_MAX_COEFS; j++) { + READ_SE(bitctx, &alf_coeff[j]); + if ((j <= 7 && (alf_coeff[j] < -64 || alf_coeff[j] > 63)) || + (j == 8 && (alf_coeff[j] < -1088 || alf_coeff[j] > 1071))) { + ret = MPP_NOK; + mpp_err_f("invalid alf coeff(%d).\n", alf_coeff[j]); + goto __FAILED; + } + + if (j <= 7) { + alf_sum += (2 * alf_coeff[j]); //!< avs2 9.12.2 + } + } + alf_coeff[8] += (64 - alf_sum); + +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET parse_pic_alf_params(BitReadCtx_t *bitctx, Avs2dPicHeader_t *ph) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + + READ_ONEBIT(bitctx, &ph->enable_pic_alf_y); + READ_ONEBIT(bitctx, &ph->enable_pic_alf_cb); + READ_ONEBIT(bitctx, &ph->enable_pic_alf_cr); + + if (ph->enable_pic_alf_y) { + RK_U32 pre_symbole = 0; + RK_U32 symbol = 0; + + READ_UE(bitctx, &ph->alf_filter_num); + ph->alf_filter_num += 1; + if (ph->alf_filter_num > ALF_MAX_FILTERS) { + ret = MPP_NOK; + mpp_err_f("invalid alf filter num(%d).\n", ph->alf_filter_num); + goto __FAILED; + } + + for (i = 0; i < ph->alf_filter_num; i++) { + if (i > 0) { + if (ph->alf_filter_num != 16) { + READ_UE(bitctx, &symbol); + } else { + symbol = 1; + } + ph->alf_filter_pattern[symbol + pre_symbole] = 1; + pre_symbole += symbol; + } + + FUN_CHECK(ret = read_pic_alf_coeff(bitctx, ph->alf_coeff_y[i])); + } + + if (pre_symbole > 15) { + ret = MPP_NOK; + mpp_err_f("invalid alf region distance.\n"); + goto __FAILED; + } + + //!< @see avs2 9.12.2 eg: 0000111222223333 + ph->alf_coeff_idx_tab[0] = 0; + for (i = 1; i < ALF_MAX_FILTERS; i++) { + ph->alf_coeff_idx_tab[i] = (ph->alf_filter_pattern[i] != 0) ? + (ph->alf_coeff_idx_tab[i - 1] + 1) : ph->alf_coeff_idx_tab[i - 1]; + } + } + + if (ph->enable_pic_alf_cb) { + FUN_CHECK(ret = read_pic_alf_coeff(bitctx, ph->alf_coeff_cb)); + } + + if (ph->enable_pic_alf_cr) { + FUN_CHECK(ret = read_pic_alf_coeff(bitctx, ph->alf_coeff_cr)); + } + +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET parse_picture_header_comm(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 i, j; + RK_U32 val_temp = 0; + + BitReadCtx_t *bitctx = &p_dec->bitctx; + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + Avs2dPicHeader_t *ph = &p_dec->ph; + + AVS2D_PARSE_TRACE("In"); + READ_ONEBIT(bitctx, &val_temp); + ph->enable_loop_filter = val_temp ^ 0x01; + if (ph->enable_loop_filter) { + READ_ONEBIT(bitctx, &ph->loop_filter_parameter_flag); + if (ph->loop_filter_parameter_flag) { + READ_SE(bitctx, &ph->alpha_c_offset); + READ_SE(bitctx, &ph->beta_offset); + if (ph->alpha_c_offset < -8 || ph->alpha_c_offset > 8 || + ph->beta_offset < -8 || ph->beta_offset > 8) { + ret = MPP_NOK; + mpp_err_f("invalid alpha_c_offset/beta_offset.\n"); + goto __FAILED; + } + } else { + ph->alpha_c_offset = 0; + ph->beta_offset = 0; + } + } + + READ_ONEBIT(bitctx, &val_temp); + ph->enable_chroma_quant_param = val_temp ^ 0x01; + if (ph->enable_chroma_quant_param) { + READ_SE(bitctx, &ph->chroma_quant_param_delta_cb); + READ_SE(bitctx, &ph->chroma_quant_param_delta_cr); + } else { + ph->chroma_quant_param_delta_cb = 0; + ph->chroma_quant_param_delta_cr = 0; + } + if (ph->chroma_quant_param_delta_cb < -16 || ph->chroma_quant_param_delta_cb > 16 || + ph->chroma_quant_param_delta_cr < -16 || ph->chroma_quant_param_delta_cr > 16) { + ret = MPP_NOK; + mpp_err_f("invalid chrome quant param delta.\n"); + goto __FAILED; + } + + p_dec->enable_wq = 0; + if (vsh->enable_weighted_quant) { + READ_ONEBIT(bitctx, &ph->enable_pic_weight_quant); + if (ph->enable_pic_weight_quant) { + p_dec->enable_wq = 1; + READ_BITS(bitctx, 2, &ph->pic_wq_data_index); + if (ph->pic_wq_data_index == 1) { + SKIP_BITS(bitctx, 1); + READ_BITS(bitctx, 2, &ph->wq_param_index); + READ_BITS(bitctx, 2, &ph->wq_model); + if (ph->wq_param_index == 1) { + for (i = 0; i < 6; i++) { + READ_SE(bitctx, &ph->wq_param_delta1[i]); + } + } else if (ph->wq_param_index == 2) { + for (i = 0; i < 6; i++) { + READ_SE(bitctx, &ph->wq_param_delta2[i]); + } + } + } else if (ph->pic_wq_data_index == 2) { + RK_U32 size_id, wqm_size; + for (size_id = 0; size_id < 2; size_id++) { + wqm_size = MPP_MIN(1 << (size_id + 2), 8); + for (j = 0; j < wqm_size; j++) { + for (i = 0; i < wqm_size; i++) { + READ_UE(bitctx, &ph->pic_wq_matrix[size_id][j * wqm_size + i]); + } + } + } + } + + } + } + + if (vsh->enable_alf) { + FUN_CHECK(ret = parse_pic_alf_params(bitctx, ph)); + } + + AVS2D_PARSE_TRACE("Out, ret %d\n", ret); + return ret; +__BITREAD_ERR: + AVS2D_PARSE_TRACE("Out, Bit read Err"); + return ret = bitctx->ret; +__FAILED: + AVS2D_PARSE_TRACE("Out, Failed"); + return ret; +} + +static MPP_RET parse_picture_header_intra(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 predict = 0; + + BitReadCtx_t *bitctx = &p_dec->bitctx; + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + Avs2dPicHeader_t *ph = &p_dec->ph; + RK_U32 last_pic_out_delay = ph->picture_output_delay; + + AVS2D_PARSE_TRACE("In."); + memset(ph, 0, sizeof(Avs2dPicHeader_t)); + ph->picture_type = I_PICTURE; + + AVS2D_PARSE_TRACE("Bitread buf %p, data %p, buf_len %d, left %d\n", bitctx->buf, bitctx->data_, bitctx->buf_len, bitctx->bytes_left_); + READ_BITS_LONG(bitctx, 32, &ph->bbv_delay); + AVS2D_PARSE_TRACE("bbv_delay %d\n", ph->bbv_delay); + READ_ONEBIT(bitctx, &ph->time_code_flag); + AVS2D_PARSE_TRACE("time_code_flag %d\n", ph->time_code_flag); + if (ph->time_code_flag) { + READ_BITS(bitctx, 24, &ph->time_code); + AVS2D_PARSE_TRACE("time_code %d\n", ph->time_code); + } + + if (vsh->enable_background_picture) { + READ_ONEBIT(bitctx, &ph->background_picture_flag); + AVS2D_PARSE_TRACE("background_picture_flag %d\n", ph->background_picture_flag); + if (ph->background_picture_flag) { + READ_ONEBIT(bitctx, &ph->background_picture_output_flag); + AVS2D_PARSE_TRACE("background_picture_output_flag %d\n", ph->background_picture_output_flag); + if (ph->background_picture_output_flag) { + ph->picture_type = G_PICTURE; + } else { + ph->picture_type = GB_PICTURE; + } + } + } + + READ_BITS(bitctx, 8, &ph->doi); + AVS2D_PARSE_TRACE("Picture type %d doi %d\n", ph->picture_type, ph->doi); + if (vsh->enable_temporal_id) { + READ_BITS(bitctx, 3, &ph->temporal_id); + AVS2D_PARSE_TRACE("temporal_id %d\n", ph->temporal_id); + } + + if (vsh->low_delay == 0 && !(ph->background_picture_flag && !ph->background_picture_output_flag)) { + READ_UE(bitctx, &ph->picture_output_delay); + AVS2D_PARSE_TRACE("picture_output_delay %d\n", ph->picture_output_delay); + if (ph->picture_output_delay >= 64) { + ret = MPP_NOK; + mpp_err_f("invalid picture output delay(%d) intra.\n", ph->picture_output_delay); + goto __FAILED; + } + } else { + ph->picture_output_delay = last_pic_out_delay; + } + + READ_ONEBIT(bitctx, &predict); + AVS2D_PARSE_TRACE("predict %d\n", predict); + if (predict) { + RK_U8 rcs_index = 0; + READ_BITS(bitctx, 5, &rcs_index); + AVS2D_PARSE_TRACE("rcs_index %d\n", rcs_index); + p_dec->frm_mgr.cur_rps = vsh->seq_rps[rcs_index]; + } else { + FUN_CHECK(ret = parse_one_rps(bitctx, &p_dec->frm_mgr.cur_rps)); + } + AVS2D_PARSE_TRACE("num_of_remove %d", p_dec->frm_mgr.cur_rps.num_to_remove); + + if (vsh->low_delay) { + READ_UE(bitctx, &ph->bbv_check_times); + AVS2D_PARSE_TRACE("bbv_check_time %d\n", ph->bbv_check_times); + } + + READ_ONEBIT(bitctx, &ph->progressive_frame); + AVS2D_PARSE_TRACE("progressive_frame %d\n", ph->progressive_frame); + if (!ph->progressive_frame) { + READ_ONEBIT(bitctx, &ph->picture_structure); + AVS2D_PARSE_TRACE("picture_structure %d\n", ph->picture_structure); + } else { + ph->picture_structure = 1; //!< frame picture + } + READ_ONEBIT(bitctx, &ph->top_field_first); + AVS2D_PARSE_TRACE("top_field_first %d\n", ph->top_field_first); + READ_ONEBIT(bitctx, &ph->repeat_first_field); + AVS2D_PARSE_TRACE("repeat_first_field %d\n", ph->repeat_first_field); + if (vsh->field_coded_sequence == 1) { //!< field picture + READ_ONEBIT(bitctx, &ph->is_top_field); + AVS2D_PARSE_TRACE("is_top_field %d\n", ph->is_top_field); + SKIP_BITS(bitctx, 1); + AVS2D_PARSE_TRACE("skip bits\n"); + } + READ_ONEBIT(bitctx, &ph->fixed_picture_qp); + AVS2D_PARSE_TRACE("fixed_picture_qp %d\n", ph->fixed_picture_qp); + READ_BITS(bitctx, 7, &ph->picture_qp); + AVS2D_PARSE_TRACE("picture_qp %d\n", ph->picture_qp); + if (ph->picture_qp > (63 + 8 * (vsh->bit_depth - 8))) { + ret = MPP_NOK; + mpp_err_f("invalid picture qp(%d).\n", ph->picture_qp); + goto __FAILED; + } + + FUN_CHECK(ret = parse_picture_header_comm(p_dec)); + + AVS2D_PARSE_TRACE("Out. ret %d", ret); + return ret; +__BITREAD_ERR: + AVS2D_PARSE_TRACE("Out. Bit read ERR"); + return ret = bitctx->ret; +__FAILED: + AVS2D_PARSE_TRACE("Out. Failed"); + return ret; +} + +static MPP_RET parse_picture_header_inter(Avs2dCtx_t *p_dec) +{ + MPP_RET ret = MPP_OK; + RK_U32 predict = 0; + + BitReadCtx_t *bitctx = &p_dec->bitctx; + Avs2dSeqHeader_t *vsh = &p_dec->vsh; + Avs2dPicHeader_t *ph = &p_dec->ph; + + memset(ph, 0, sizeof(Avs2dPicHeader_t)); + READ_BITS_LONG(bitctx, 32, &ph->bbv_delay); + READ_BITS(bitctx, 2, &ph->picture_coding_type); + if (vsh->enable_background_picture) { + if (ph->picture_coding_type == 1) { + READ_ONEBIT(bitctx, &ph->background_pred_flag); + } + + if (ph->picture_coding_type != 2 && !ph->background_pred_flag) { + READ_ONEBIT(bitctx, &ph->background_reference_flag); //!< P/F ref G/GB + } + } + + if (ph->picture_coding_type == 1) { + ph->picture_type = (ph->background_pred_flag != 0) ? S_PICTURE : P_PICTURE; + } else if (ph->picture_coding_type == 2) { + ph->picture_type = B_PICTURE; + } else if (ph->picture_coding_type == 3) { + ph->picture_type = F_PICTURE; + } else { + ret = MPP_NOK; + mpp_err_f("invalid picture coding type(0).\n"); + goto __FAILED; + } + + READ_BITS(bitctx, 8, &ph->doi); + AVS2D_PARSE_TRACE("Picture type %d doi %d\n", ph->picture_type, ph->doi); + if (vsh->enable_temporal_id) { + READ_BITS(bitctx, 3, &ph->temporal_id); + } + + if (vsh->low_delay == 0) { + READ_UE(bitctx, &ph->picture_output_delay); + AVS2D_PARSE_TRACE("picture_output_delay %d\n", ph->picture_output_delay); + if (ph->picture_output_delay >= 64) { + ret = MPP_NOK; + mpp_err_f("invalid picture output delay(%d) intra.\n", ph->picture_output_delay); + goto __FAILED; + } + } else { + ph->picture_output_delay = 0; + } + + READ_ONEBIT(bitctx, &predict); + AVS2D_PARSE_TRACE("predict %d\n", predict); + if (predict) { + RK_U8 rcs_index = 0; + READ_BITS(bitctx, 5, &rcs_index); + p_dec->frm_mgr.cur_rps = vsh->seq_rps[rcs_index]; + } else { + FUN_CHECK(ret = parse_one_rps(bitctx, &p_dec->frm_mgr.cur_rps)); + } + AVS2D_PARSE_TRACE("num_of_remove %d", p_dec->frm_mgr.cur_rps.num_to_remove); + + if (vsh->low_delay) { + READ_UE(bitctx, &ph->bbv_check_times); + } + + READ_ONEBIT(bitctx, &ph->progressive_frame); + if (!ph->progressive_frame) { + READ_ONEBIT(bitctx, &ph->picture_structure); + } else { + ph->picture_structure = 1; //!< frame picture + } + READ_ONEBIT(bitctx, &ph->top_field_first); + READ_ONEBIT(bitctx, &ph->repeat_first_field); + if (vsh->field_coded_sequence == 1) { //!< field picture + READ_ONEBIT(bitctx, &ph->is_top_field); + SKIP_BITS(bitctx, 1); + } + READ_ONEBIT(bitctx, &ph->fixed_picture_qp); + READ_BITS(bitctx, 7, &ph->picture_qp); + if (ph->picture_qp > (63 + 8 * (vsh->bit_depth - 8))) { + ret = MPP_NOK; + mpp_err_f("invalid picture qp(%d).\n", ph->picture_qp); + goto __FAILED; + } + if (ph->picture_coding_type != 2 || ph->picture_structure == 0) { + SKIP_BITS(bitctx, 1); + } + READ_ONEBIT(bitctx, &ph->enable_random_decodable); + + FUN_CHECK(ret = parse_picture_header_comm(p_dec)); + + return ret; +__BITREAD_ERR: + return ret = bitctx->ret; +__FAILED: + return ret; +} + +MPP_RET avs2d_parse_picture_header(Avs2dCtx_t *p_dec, RK_U32 startcode) +{ + MPP_RET ret = MPP_OK; + + AVS2D_PARSE_TRACE("In."); + switch (startcode) { + case AVS2_I_PICTURE_START_CODE: + ret = parse_picture_header_intra(p_dec); + break; + case AVS2_PB_PICTURE_START_CODE: + ret = parse_picture_header_inter(p_dec); + break; + default: + ret = MPP_NOK; + mpp_err_f("invalid picture startcode(%d).\n", startcode); + return ret; + } + + wq_init_frame_quant_param(p_dec); + wq_update_frame_matrix(p_dec); + + AVS2D_PARSE_TRACE("Out."); + return ret; +} + + diff --git a/mpp/codec/dec/avs2/avs2d_ps.h b/mpp/codec/dec/avs2/avs2d_ps.h new file mode 100644 index 000000000..312a50668 --- /dev/null +++ b/mpp/codec/dec/avs2/avs2d_ps.h @@ -0,0 +1,33 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AVS2D_PS_H +#define AVS2D_PS_H + +#include "avs2d_global.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET avs2d_parse_sequence_header(Avs2dCtx_t *p_dec); +MPP_RET avs2d_parse_picture_header(Avs2dCtx_t *p_dec, RK_U32 startcode); + +#ifdef __cplusplus +} +#endif + +#endif /* AVS2D_PS_H */ diff --git a/mpp/codec/dec/common/CMakeLists.txt b/mpp/codec/dec/common/CMakeLists.txt new file mode 100644 index 000000000..dc26a7938 --- /dev/null +++ b/mpp/codec/dec/common/CMakeLists.txt @@ -0,0 +1,7 @@ +# vim: syntax=cmake +include_directories(.) + +# h264 / h265 common decoder sourse +add_library(dec_common OBJECT + h2645d_sei.c + ) diff --git a/mpp/codec/dec/common/h2645d_sei.c b/mpp/codec/dec/common/h2645d_sei.c new file mode 100644 index 000000000..b9600a11c --- /dev/null +++ b/mpp/codec/dec/common/h2645d_sei.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "h2645d_sei" + +#include +#include + +#include "mpp_mem.h" +#include "h2645d_sei.h" + +static RK_U8 const deny_uuid[2][16] = {{ + 0xfa, 0x5e, 0xfe, 0x40, 0xa6, 0xaf, 0x11, 0xdd, + 0xa6, 0x59, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b + }, + { + 0x68, 0x55, 0x98, 0x4e, 0x49, 0x9c, 0x45, 0xc5, + 0x8e, 0x5b, 0xf2, 0x7b, 0xd1, 0xd4, 0xac, 0xe6 + } +}; + +static RK_U8 const deny_identity[3][4] = { + {0x44, 0x69, 0x76, 0x58}, + {0x50, 0x6C, 0x75, 0x73}, + {0x48, 0x45, 0x56, 0x43} +}; + +MPP_RET check_encoder_sei_info(BitReadCtx_t *gb, RK_S32 payload_size, RK_U32 *is_match) +{ + RK_S32 i = 0; + + RK_U8 *payload = NULL; + + if (payload_size < 25 || payload_size >= INT32_MAX - 1) + return MPP_ERR_STREAM; + + payload = mpp_calloc(RK_U8, payload_size); + + for (i = 0; i < payload_size; i++) + READ_BITS(gb, 8, &payload[i]); + + if ((!memcmp(payload, deny_uuid[0], 16) || + !memcmp(payload, deny_uuid[1], 16)) && + (!memcmp(payload + 16, deny_identity[0], 4)) && + (!memcmp(payload + 21, deny_identity[1], 4) || + !memcmp(payload + 21, deny_identity[2], 4))) { + *is_match = 1; + } + + mpp_free(payload); + return MPP_OK;; +__BITREAD_ERR: + mpp_free(payload); + return gb->ret; +} diff --git a/mpp/codec/dec/common/h2645d_sei.h b/mpp/codec/dec/common/h2645d_sei.h new file mode 100644 index 000000000..881729acf --- /dev/null +++ b/mpp/codec/dec/common/h2645d_sei.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#ifndef H2645D_SEI_H +#define H2645D_SEI_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_bitread.h" + +typedef struct SEI_Recovery_Point_t { + RK_U32 valid_flag; // Whether this SEI is valid or not + RK_S32 recovery_frame_cnt; // H.264: recovery_frame_cnt; H.265: recovery_poc_cnt + RK_S32 first_frm_id; // The frame_num or poc of the frame associated with this SEI + RK_U32 first_frm_valid; // The frame associated with this SEI is valid or not + RK_U32 first_frm_ref_missing; + RK_S32 recovery_pic_id; // first_frm_id + recovery_frame_cnt; +} RecoveryPoint; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET check_encoder_sei_info(BitReadCtx_t *gb, RK_S32 payload_size, RK_U32 *is_match); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of H2645D_SEI_H */ \ No newline at end of file diff --git a/mpp/codec/dec/dummy/CMakeLists.txt b/mpp/codec/dec/dummy/CMakeLists.txt deleted file mode 100644 index 20bf71a34..000000000 --- a/mpp/codec/dec/dummy/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# vim: syntax=cmake - -# dummy decoder api -set(DUMMY_API - ../../inc/dummy_dec_api.h - ) - - -# dummy decoder header -set(DUMMY_HDR - - ) - -# dummy decoder sourse -set(DUMMY_SRC - dummy_dec_api.c - ) - - -add_library(codec_dummy_dec STATIC - ${DUMMY_API} - ${DUMMY_HDR} - ${DUMMY_SRC} - ) - -set_target_properties(codec_dummy_dec PROPERTIES FOLDER "mpp/codec") - diff --git a/mpp/codec/dec/dummy/dummy_dec_api.c b/mpp/codec/dec/dummy/dummy_dec_api.c deleted file mode 100644 index 37c717258..000000000 --- a/mpp/codec/dec/dummy/dummy_dec_api.c +++ /dev/null @@ -1,202 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#define MODULE_TAG "dummy_dec_api" - -#include - -#include "mpp_log.h" - -#include "dummy_dec_api.h" - -#define DUMMY_DEC_FRAME_SIZE SZ_1M -#define DUMMY_DEC_FRAME_COUNT 16 -#define DUMMY_DEC_REF_COUNT 2 - -typedef struct DummyDec_t { - MppBufSlots slots; - RK_U32 task_count; - - RK_U32 slots_inited; - RK_U32 frame_count; - RK_S32 prev_index; - RK_S32 slot_index[DUMMY_DEC_REF_COUNT]; -} DummyDec; - -MPP_RET dummy_dec_init(void *dec, ParserCfg *cfg) -{ - DummyDec *p; - RK_S32 i; - if (NULL == dec) { - mpp_err_f("found NULL intput dec %p cfg %p\n", dec, cfg); - return MPP_ERR_NULL_PTR; - } - - p = (DummyDec *)dec; - p->slots = cfg->slots; - p->task_count = cfg->task_count = 2; - p->slots_inited = 0; - p->frame_count = 0; - for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) { - p->slot_index[i] = -1; - } - return MPP_OK; -} - -MPP_RET dummy_dec_deinit(void *dec) -{ - if (NULL == dec) { - mpp_err_f("found NULL intput\n"); - return MPP_ERR_NULL_PTR; - } - return MPP_OK; -} - -MPP_RET dummy_dec_reset(void *dec) -{ - if (NULL == dec) { - mpp_err_f("found NULL intput\n"); - return MPP_ERR_NULL_PTR; - } - return MPP_OK; -} - - -MPP_RET dummy_dec_flush(void *dec) -{ - if (NULL == dec) { - mpp_err_f("found NULL intput\n"); - return MPP_ERR_NULL_PTR; - } - return MPP_OK; -} - - -MPP_RET dummy_dec_control(void *dec, RK_S32 cmd_type, void *param) -{ - if (NULL == dec) { - mpp_err_f("found NULL intput\n"); - return MPP_ERR_NULL_PTR; - } - (void)cmd_type; - (void)param; - return MPP_OK; -} - - -MPP_RET dummy_dec_parse(void *dec, MppPacket pkt, HalDecTask *task) -{ - DummyDec *p; - RK_U32 output; - MppFrame frame; - RK_U32 frame_count; - MppBufSlots slots; - RK_S32 i; - - if (NULL == dec) { - mpp_err_f("found NULL intput\n"); - return MPP_ERR_NULL_PTR; - } - - p = (DummyDec *)dec; - // do packet decoding here - - slots = p->slots; - frame_count = p->frame_count; - - // set packet size - mpp_packet_set_size(pkt, 0); - - /* - * set slots information - * 1. output index MUST be set - * 2. get unused index for output if needed - * 3. set output index as decoding - * 4. set pts to output index - * 5. if one frame can be display, it SHOULD be set display - */ - if (!p->slots_inited) { - mpp_buf_slot_setup(slots, DUMMY_DEC_FRAME_COUNT, DUMMY_DEC_FRAME_SIZE, 0); - p->slots_inited = 1; - } - - mpp_frame_init(&frame); - mpp_frame_set_pts(frame, mpp_packet_get_pts(pkt)); - mpp_buf_slot_get_unused(slots, &output); - mpp_buf_slot_set_hw_dst(slots, output, frame); - mpp_frame_deinit(&frame); - mpp_assert(NULL == frame); - - /* - * setup output task - * 1. valid flag MUST be set if need hardware to run once - * 2. set output slot index - * 3. set reference slot index - */ - task->valid = 1; - task->output = output; - - memset(&task->refer, -1, sizeof(task->refer)); - for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) { - RK_S32 index = p->slot_index[i]; - if (index >= 0) { - task->refer[i] = index; - mpp_buf_slot_inc_hw_ref(slots, index); - mpp_buf_slot_set_dpb_ref(slots, index); - } - } - - /* - * update dpb status assuming that hw has decoded the frame - */ - mpp_buf_slot_set_display(slots, output); - - // add new reference buffer - if (mpp_packet_get_eos(pkt)) { - for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) { - mpp_buf_slot_clr_dpb_ref(slots, p->slot_index[i]); - p->slot_index[i] = -1; - } - } else { - // clear unreference buffer - if (p->slot_index[frame_count] >= 0) - mpp_buf_slot_clr_dpb_ref(slots, p->slot_index[frame_count]); - - p->slot_index[frame_count] = output; - mpp_buf_slot_set_dpb_ref(slots, output); - } - - frame_count++; - if (frame_count >= DUMMY_DEC_REF_COUNT) - frame_count = 0; - p->frame_count = frame_count; - - return MPP_OK; -} - -const ParserApi dummy_dec_parser = { - "dummy_dec_parser", - MPP_VIDEO_CodingUnused, - sizeof(DummyDec), - 0, - dummy_dec_init, - dummy_dec_deinit, - NULL, - dummy_dec_parse, - dummy_dec_reset, - dummy_dec_flush, - dummy_dec_control, -}; diff --git a/mpp/codec/dec/h263/CMakeLists.txt b/mpp/codec/dec/h263/CMakeLists.txt new file mode 100644 index 000000000..8e7c6faec --- /dev/null +++ b/mpp/codec/dec/h263/CMakeLists.txt @@ -0,0 +1,7 @@ +# vim: syntax=cmake + +# h264 decoder sourse +add_library(h263d_api OBJECT + h263d_api.c + h263d_parser.c + ) diff --git a/mpp/codec/dec/h263/h263d_api.c b/mpp/codec/dec/h263/h263d_api.c new file mode 100644 index 000000000..79e6d8303 --- /dev/null +++ b/mpp/codec/dec/h263/h263d_api.c @@ -0,0 +1,327 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h263d_api" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_parser.h" +#include "h263d_parser.h" + +#define h263d_INIT_STREAM_SIZE SZ_64K + +typedef struct { + // parameter interact with mpp_dec + MppBufSlots frame_slots; + MppBufSlots packet_slots; + MppDecCfgSet *cfg; + + RK_U8 *stream; + size_t stream_size; + MppPacket task_pkt; + RK_S64 task_pts; + RK_S64 task_dts; + RK_U32 task_eos; + + // runtime parameter + RK_U32 frame_count; + + // parser context + H263dParser parser; +} H263dCtx; + +MPP_RET h263d_init(void *dec, ParserCfg *cfg) +{ + H263dParser parser = NULL; + MppPacket task_pkt = NULL; + H263dCtx *p; + MPP_RET ret; + RK_U8 *stream; + size_t stream_size = h263d_INIT_STREAM_SIZE; + + if (NULL == dec) { + mpp_err_f("found NULL intput dec %p cfg %p\n", dec, cfg); + return MPP_ERR_NULL_PTR; + } + + stream = mpp_malloc_size(RK_U8, stream_size); + if (NULL == stream) { + mpp_err_f("failed to malloc stream buffer size %d\n", stream_size); + return MPP_ERR_MALLOC; + } + + ret = mpp_packet_init(&task_pkt, stream, stream_size); + if (ret) { + mpp_err_f("failed to create mpp_packet for task\n"); + goto ERR_RET; + } + + // reset task packet length to zero + // NOTE: set length must after set pos + mpp_packet_set_pos(task_pkt, stream); + mpp_packet_set_length(task_pkt, 0); + + ret = mpp_h263_parser_init(&parser, cfg->frame_slots); + if (ret) { + mpp_err_f("failed to init parser\n"); + goto ERR_RET; + } + + p = (H263dCtx *)dec; + p->frame_slots = cfg->frame_slots; + p->packet_slots = cfg->packet_slots; + p->cfg = cfg->cfg; + p->stream = stream; + p->stream_size = stream_size; + p->task_pkt = task_pkt; + p->parser = parser; + + return MPP_OK; +ERR_RET: + if (task_pkt) { + mpp_packet_deinit(&task_pkt); + } + if (stream) { + mpp_free(stream); + stream = NULL; + } + return ret; +} + +MPP_RET h263d_deinit(void *dec) +{ + H263dCtx *p; + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + + p = (H263dCtx *)dec; + if (p->parser) { + mpp_h263_parser_deinit(p->parser); + p->parser = NULL; + } + + if (p->task_pkt) { + mpp_packet_deinit(&p->task_pkt); + } + + if (p->stream) { + mpp_free(p->stream); + p->stream = NULL; + } + return MPP_OK; +} + +MPP_RET h263d_reset(void *dec) +{ + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + + H263dCtx *p = (H263dCtx *)dec; + return mpp_h263_parser_reset(p->parser); +} + + +MPP_RET h263d_flush(void *dec) +{ + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + + H263dCtx *p = (H263dCtx *)dec; + return mpp_h263_parser_flush(p->parser); +} + + +MPP_RET h263d_control(void *dec, MpiCmd cmd_type, void *param) +{ + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + (void)cmd_type; + (void)param; + return MPP_OK; +} + +MPP_RET h263d_prepare(void *dec, MppPacket pkt, HalDecTask *task) +{ + H263dCtx *p; + RK_U8 *pos; + size_t length; + RK_U32 eos; + + if (NULL == dec || NULL == pkt || NULL == task) { + mpp_err_f("found NULL intput dec %p pkt %p task %p\n", dec, pkt, task); + return MPP_ERR_NULL_PTR; + } + + p = (H263dCtx *)dec; + pos = mpp_packet_get_pos(pkt); + length = mpp_packet_get_length(pkt); + eos = mpp_packet_get_eos(pkt); + + if (eos && !length) { + task->valid = 0; + task->flags.eos = 1; + mpp_log("h263d flush eos"); + h263d_flush(dec); + return MPP_OK; + } + + if (NULL == p->stream) { + mpp_err("failed to malloc task buffer for hardware with size %d\n", length); + return MPP_ERR_UNKNOW; + } + + if (!p->cfg->base.split_parse) { + /* + * Copy packet mode: + * Decoder's user will insure each packet is one frame for process + * Parser will just copy packet to the beginning of stream buffer + */ + if (length > p->stream_size) { + // NOTE: here we double the buffer length to reduce frequency of realloc + do { + p->stream_size <<= 1; + } while (length > p->stream_size); + + mpp_free(p->stream); + p->stream = mpp_malloc_size(RK_U8, p->stream_size); + mpp_assert(p->stream); + mpp_packet_set_data(p->task_pkt, p->stream); + mpp_packet_set_size(p->task_pkt, p->stream_size); + } + + memcpy(p->stream, pos, length); + mpp_packet_set_pos(p->task_pkt, p->stream); + mpp_packet_set_length(p->task_pkt, length); + // set input packet length to 0 here + // indicate that the input packet has been all consumed + mpp_packet_set_pos(pkt, pos + length); + // always use latest pts for current packet + p->task_pts = mpp_packet_get_pts(pkt); + p->task_dts = mpp_packet_get_dts(pkt); + p->task_eos = mpp_packet_get_eos(pkt); + /* this step will enable the task and goto parse stage */ + task->valid = 1; + } else { + /* + * Split packet mode: + * Input packet can be any length and no need to be bound of on frame + * Parser will do split frame operation to find the beginning and end of one frame + */ + /* + * NOTE: on split mode total length is the left size plus the new incoming + * packet length. + */ + size_t remain_length = mpp_packet_get_length(p->task_pkt); + size_t total_length = remain_length + length; + if (total_length > p->stream_size) { + RK_U8 *dst; + do { + p->stream_size <<= 1; + } while (length > p->stream_size); + + // NOTE; split mode need to copy remaining stream to new buffer + dst = mpp_malloc_size(RK_U8, p->stream_size); + mpp_assert(dst); + + memcpy(dst, p->stream, remain_length); + mpp_free(p->stream); + p->stream = dst; + mpp_packet_set_data(p->task_pkt, p->stream); + mpp_packet_set_size(p->task_pkt, p->stream_size); + } + + // start parser split + if (MPP_OK == mpp_h263_parser_split(p->parser, p->task_pkt, pkt)) { + task->valid = 1; + } + p->task_pts = mpp_packet_get_pts(p->task_pkt); + p->task_dts = mpp_packet_get_dts(p->task_pkt); + p->task_eos = mpp_packet_get_eos(p->task_pkt); + } + + mpp_packet_set_pts(p->task_pkt, p->task_pts); + mpp_packet_set_dts(p->task_pkt, p->task_dts); + task->input_packet = p->task_pkt; + task->flags.eos = p->task_eos; + + return MPP_OK; +} + +MPP_RET h263d_parse(void *dec, HalDecTask *task) +{ + MPP_RET ret; + H263dCtx *p; + + if (NULL == dec || NULL == task) { + mpp_err_f("found NULL intput dec %p task %p\n", dec, task); + return MPP_ERR_NULL_PTR; + } + p = (H263dCtx *)dec; + ret = mpp_h263_parser_decode(p->parser, task->input_packet); + if (ret) { + // found error on decoding drop this task and clear remaining length + task->valid = 0; + task->output = -1; + mpp_packet_set_length(task->input_packet, 0); + return MPP_NOK; + } + + mpp_h263_parser_setup_syntax(p->parser, &task->syntax); + mpp_h263_parser_setup_hal_output(p->parser, &task->output); + mpp_h263_parser_setup_refer(p->parser, task->refer, MAX_DEC_REF_NUM); + mpp_h263_parser_update_dpb(p->parser); + + p->frame_count++; + + return MPP_OK; +} + +MPP_RET h263d_callback(void *dec, void *err_info) +{ + (void)dec; + (void)err_info; + return MPP_OK; +} + +const ParserApi mpp_h263d = { + .name = "api_h263d_parser", + .coding = MPP_VIDEO_CodingH263, + .ctx_size = sizeof(H263dCtx), + .flag = 0, + .init = h263d_init, + .deinit = h263d_deinit, + .prepare = h263d_prepare, + .parse = h263d_parse, + .reset = h263d_reset, + .flush = h263d_flush, + .control = h263d_control, + .callback = h263d_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_h263d); diff --git a/mpp/codec/dec/h263/h263d_parser.c b/mpp/codec/dec/h263/h263d_parser.c new file mode 100644 index 000000000..01e7a7ded --- /dev/null +++ b/mpp/codec/dec/h263/h263d_parser.c @@ -0,0 +1,579 @@ +/* + * + * Copyright 2010 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "mpp_bitread.h" +#include "h263d_parser.h" +#include "h263d_syntax.h" + +#define h263d_dbg(flag, fmt, ...) mpp_dbg(h263d_debug, flag, fmt, ## __VA_ARGS__) +#define h263d_dbg_f(flag, fmt, ...) mpp_dbg_f(h263d_debug, flag, fmt, ## __VA_ARGS__) + +#define h263d_dbg_func(fmt, ...) h263d_dbg_f(H263D_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define h263d_dbg_bit(fmt, ...) h263d_dbg(H263D_DBG_BITS, fmt, ## __VA_ARGS__) +#define h263d_dbg_status(fmt, ...) h263d_dbg(H263D_DBG_STATUS, fmt, ## __VA_ARGS__) + +extern RK_U32 h263d_debug; + +#define H263_STARTCODE 0x00000080 /* 17 zero and 1 one */ +#define H263_STARTCODE_MASK 0x00FFFF80 +#define H263_GOB_ZERO 0x00000000 +#define H263_GOB_ZERO_MASK 0x0000007C + +#define H263_SF_SQCIF 1 /* 001 */ +#define H263_SF_QCIF 2 /* 010 */ +#define H263_SF_CIF 3 /* 011 */ +#define H263_SF_4CIF 4 /* 100 */ +#define H263_SF_16CIF 5 /* 101 */ +#define H263_SF_CUSTOM 6 /* 110 */ +#define H263_EXTENDED_PTYPE 7 /* 111 */ +#define H263_EXTENDED_PAR 15 /* 1111 */ + +typedef struct H263Hdr_t { + H263VOPType pict_type; + RK_S32 width; + RK_S32 height; + RK_U32 TR; + RK_U32 quant; + + // frame related parameter + RK_S64 pts; + RK_S32 slot_idx; + RK_U32 enqueued; + RK_U32 hdr_bits; +} H263Hdr; + +typedef struct { + // global paramter + MppBufSlots frame_slots; + RK_U32 use_internal_pts; + RK_U32 found_i_vop; + + // frame size parameter + RK_S32 width; + RK_S32 height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_U32 info_change; + RK_U32 eos; + + // spliter parameter + RK_S32 pos_frm_start; // negtive - not found; non-negtive - position of frame start + RK_S32 pos_frm_end; // negtive - not found; non-negtive - position of frame end + + // bit read context + BitReadCtx_t *bit_ctx; + + // decoding parameter + H263Hdr hdr_curr; + H263Hdr hdr_ref0; + + // dpb/output information + RK_S32 output; + RK_S64 pts; + RK_S64 dts; + + // syntax for hal + h263d_dxva2_picture_context_t *syntax; +} H263dParserImpl; + +static RK_U32 h263d_fmt_to_dimension[8][2] = { + { 0, 0 }, /* invalid */ + { 128, 96 }, /* SQCIF */ + { 176, 144 }, /* QCIF */ + { 352, 288 }, /* CIF */ + { 704, 576 }, /* 4CIF */ + { 1408, 1152 }, /* 16CIF */ + { 0, 0 }, /* custorm */ + { 0, 0 }, /* extend */ +}; + +static void h263d_fill_picture_parameters(const H263dParserImpl *p, + DXVA_PicParams_H263 *pp) +{ + const H263Hdr *hdr_curr = &p->hdr_curr; + const H263Hdr *hdr_ref0 = &p->hdr_ref0; + + pp->short_video_header = 1; + pp->vop_coding_type = hdr_curr->pict_type; + pp->vop_quant = hdr_curr->quant; + pp->wDecodedPictureIndex = hdr_curr->slot_idx; + pp->wForwardRefPictureIndex = hdr_ref0->slot_idx; + pp->vop_time_increment_resolution = 30000; + pp->vop_width = hdr_curr->width; + pp->vop_height = hdr_curr->height; + + // Rockchip special data + pp->prev_coding_type = hdr_ref0->pict_type; + pp->header_bits = hdr_curr->hdr_bits; +} + +static void h263_syntax_init(h263d_dxva2_picture_context_t *syntax) +{ + DXVA2_DecodeBufferDesc *data = &syntax->desc[0]; + + //!< commit picture paramters + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_PictureParametersBufferType; + data->pvPVPState = (void *)&syntax->pp; + data->DataSize = sizeof(syntax->pp); + syntax->data[0] = data; + + //!< commit bitstream + data = &syntax->desc[1]; + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_BitStreamDateBufferType; + syntax->data[1] = data; +} + +static MPP_RET h263_parse_picture_header(H263dParserImpl *p, BitReadCtx_t *gb) +{ + RK_U32 val = 0; + H263Hdr *hdr_curr = &p->hdr_curr; + H263VOPType pict_type = H263_INVALID_VOP; + + /* start code */ + READ_BITS(gb, 17, &val); /* start code */ + mpp_assert(val == 1); + + /* gob */ + READ_BITS(gb, 5, &val); /* gob */ + mpp_assert(val == 0); + + /* time reference */ + READ_BITS(gb, 8, &hdr_curr->TR); + + /* first 5 bit of PTYPE */ + SKIP_BITS(gb, 5); + + /* source format */ + READ_BITS(gb, 3, &val); /* source format */ + hdr_curr->width = h263d_fmt_to_dimension[val][0]; + hdr_curr->height = h263d_fmt_to_dimension[val][1]; + if (!hdr_curr->width && !hdr_curr->height) { + mpp_err_f("unsupport source format %d\n", val); + return MPP_NOK; + } + + /* picture coding type: 0 - INTRA, 1 - INTER */ + READ_BITS(gb, 1, &val); + pict_type = val; + + /* last 4 bit for PTYPE: UMV, AP mode, PB frame */ + READ_BITS(gb, 4, &val); + if (val) { + mpp_err_f("unsupport PTYPE mode %x\n", val); + return MPP_NOK; + } + + READ_BITS(gb, 5, &val); + hdr_curr->quant = val; + + SKIP_BITS(gb, 1); + + READ_BITS(gb, 1, &val); + while (val) { + SKIP_BITS(gb, 8); + READ_BITS(gb, 1, &val); + } + + if (!p->found_i_vop) + p->found_i_vop = (pict_type == H263_I_VOP); + + if (!p->found_i_vop) + return MPP_NOK; + + hdr_curr->hdr_bits = gb->used_bits; + hdr_curr->pict_type = pict_type; + + return MPP_OK; +__BITREAD_ERR: + mpp_err_f("found error stream\n"); + return MPP_ERR_STREAM; +} + +MPP_RET mpp_h263_parser_init(H263dParser *ctx, MppBufSlots frame_slots) +{ + BitReadCtx_t *bit_ctx = mpp_calloc(BitReadCtx_t, 1); + H263dParserImpl *p = mpp_calloc(H263dParserImpl, 1); + h263d_dxva2_picture_context_t *syntax = mpp_calloc(h263d_dxva2_picture_context_t, 1); + + if (NULL == p || NULL == bit_ctx || NULL == syntax) { + mpp_err_f("malloc context failed\n"); + if (p) + mpp_free(p); + if (bit_ctx) + mpp_free(bit_ctx); + if (syntax) + mpp_free(syntax); + return MPP_NOK; + } + + mpp_buf_slot_setup(frame_slots, 4); + p->frame_slots = frame_slots; + p->pos_frm_start = -1; + p->pos_frm_end = -1; + p->bit_ctx = bit_ctx; + p->hdr_curr.slot_idx = H263_INVALID_VOP; + p->hdr_ref0.slot_idx = H263_INVALID_VOP; + h263_syntax_init(syntax); + p->syntax = syntax; + + mpp_env_get_u32("h263d_debug", &h263d_debug, 0); + + *ctx = p; + return MPP_OK; +} + +MPP_RET mpp_h263_parser_deinit(H263dParser ctx) +{ + H263dParserImpl *p = (H263dParserImpl *)ctx; + if (p) { + if (p->bit_ctx) { + mpp_free(p->bit_ctx); + p->bit_ctx = NULL; + } + if (p->syntax) { + mpp_free(p->syntax); + p->syntax = NULL; + } + mpp_free(p); + } + return MPP_OK; +} + +MPP_RET mpp_h263_parser_flush(H263dParser ctx) +{ + H263dParserImpl *p = (H263dParserImpl *)ctx; + MppBufSlots slots = p->frame_slots; + H263Hdr *hdr_curr = &p->hdr_ref0; + RK_S32 index = hdr_curr->slot_idx; + + h263d_dbg_func("in\n"); + + if (!hdr_curr->enqueued && index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + hdr_curr->enqueued = 1; + } + + h263d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_h263_parser_reset(H263dParser ctx) +{ + H263dParserImpl *p = (H263dParserImpl *)ctx; + MppBufSlots slots = p->frame_slots; + H263Hdr *hdr_curr = &p->hdr_ref0; + H263Hdr *hdr_ref0 = &p->hdr_ref0; + RK_S32 index = hdr_curr->slot_idx; + + h263d_dbg_func("in\n"); + + if (index >= 0) { + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + hdr_curr->slot_idx = -1; + } + + index = hdr_ref0->slot_idx; + if (index >= 0) { + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + hdr_ref0->slot_idx = -1; + } + + p->found_i_vop = 0; + + h263d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_h263_parser_split(H263dParser ctx, MppPacket dst, MppPacket src) +{ + MPP_RET ret = MPP_NOK; + H263dParserImpl *p = (H263dParserImpl *)ctx; + RK_U8 *dst_buf = mpp_packet_get_data(dst); + size_t dst_len = mpp_packet_get_length(dst); + RK_U8 *src_buf = mpp_packet_get_pos(src); + RK_S32 src_len = (RK_S32)mpp_packet_get_length(src); + RK_S32 pos_frm_start = p->pos_frm_start; + RK_S32 pos_frm_end = p->pos_frm_end; + RK_U32 src_eos = mpp_packet_get_eos(src); + RK_S32 src_pos = 0; + RK_U32 state = (RK_U32) - 1; + + h263d_dbg_func("in\n"); + + mpp_assert(src_len); + + if (dst_len) { + mpp_assert(dst_len >= 4); + state = ((RK_U32)(dst_buf[dst_len - 1]) << 0) | + ((RK_U32)(dst_buf[dst_len - 2]) << 8) | + ((RK_U32)(dst_buf[dst_len - 3]) << 16) | + ((RK_U32)(dst_buf[dst_len - 4]) << 24); + } + + if (pos_frm_start < 0) { + // scan for frame start + for (src_pos = 0; src_pos < src_len; src_pos++) { + state = (state << 8) | src_buf[src_pos]; + if ((state & H263_STARTCODE_MASK) == H263_STARTCODE && + (state & H263_GOB_ZERO_MASK) == H263_GOB_ZERO) { + pos_frm_start = src_pos - 2; + src_pos++; + break; + } + } + } + + if (pos_frm_start >= 0) { + // scan for frame end + for (; src_pos < src_len; src_pos++) { + state = (state << 8) | src_buf[src_pos]; + + if ((state & H263_STARTCODE_MASK) == H263_STARTCODE && + (state & H263_GOB_ZERO_MASK) == H263_GOB_ZERO) { + pos_frm_end = src_pos - 2; + break; + } + } + if (src_eos && src_pos == src_len) { + pos_frm_end = src_len; + mpp_packet_set_eos(dst); + } + } + + //mpp_log("pkt pos: start %d end %d len: left %d in %d\n", + // pos_frm_start, pos_frm_end, dst_len, src_len); + + if (pos_frm_start < 0 || pos_frm_end < 0) { + // do not found frame start or do not found frame end, just copy the hold buffer to dst + memcpy(dst_buf + dst_len, src_buf, src_len); + // update dst buffer length + mpp_packet_set_length(dst, dst_len + src_len); + // set src buffer pos to end to src buffer + mpp_packet_set_pos(src, src_buf + src_len); + } else { + // found both frame start and frame end - only copy frame + memcpy(dst_buf + dst_len, src_buf, pos_frm_end); + mpp_packet_set_length(dst, dst_len + pos_frm_end); + + // set src buffer pos to end to src buffer + mpp_packet_set_pos(src, src_buf + pos_frm_end); + mpp_assert((RK_S32)mpp_packet_get_length(src) == (src_len - pos_frm_end)); + mpp_packet_set_length(src, src_len - pos_frm_end); + + // return ok indicate the frame is ready and reset frame start/end position + ret = MPP_OK; + pos_frm_start = -1; + pos_frm_end = -1; + } + + p->pos_frm_start = pos_frm_start; + p->pos_frm_end = pos_frm_end; + + h263d_dbg_func("out\n"); + + return ret; +} + +MPP_RET mpp_h263_parser_decode(H263dParser ctx, MppPacket pkt) +{ + MPP_RET ret = MPP_NOK; + H263dParserImpl *p = (H263dParserImpl *)ctx; + BitReadCtx_t *gb = p->bit_ctx; + RK_U8 *buf = mpp_packet_get_data(pkt); + RK_S32 len = (RK_S32)mpp_packet_get_length(pkt); + RK_U32 startcode = 0xff; + RK_S32 i = 0; + + h263d_dbg_func("in\n"); + + while (i < len) { + startcode = (startcode << 8) | buf[i++]; + + if (startcode >> (32 - 22) == 0x20) { + i -= 4; + h263d_dbg_bit("found startcode at byte %d\n", i); + break; + } + } + + if (i == len) { + mpp_err_f("can not found start code in len %d packet\n", len); + goto __BITREAD_ERR; + } + + // setup bit read context + mpp_set_bitread_ctx(gb, buf + i, len - i); + + ret = h263_parse_picture_header(p, gb); + if (ret) + goto __BITREAD_ERR; + + p->width = p->hdr_curr.width; + p->height = p->hdr_curr.height; + p->pts = mpp_packet_get_pts(pkt); + p->dts = mpp_packet_get_dts(pkt); +__BITREAD_ERR: + h263d_dbg_status("found i_frame %d frame_type %d ret %d\n", + p->found_i_vop, p->hdr_curr.pict_type, ret); + + mpp_packet_set_pos(pkt, buf); + mpp_packet_set_length(pkt, 0); + p->eos = mpp_packet_get_eos(pkt); + + h263d_dbg_func("out\n"); + + return ret; +} + +MPP_RET mpp_h263_parser_setup_syntax(H263dParser ctx, MppSyntax *syntax) +{ + H263dParserImpl *p = (H263dParserImpl *)ctx; + h263d_dxva2_picture_context_t *syn = p->syntax; + + h263d_dbg_func("in\n"); + + h263d_fill_picture_parameters(p, &syn->pp); + + // fill bit stream parameter + syn->data[1]->DataSize = p->bit_ctx->buf_len; + syn->data[1]->DataOffset = p->hdr_curr.hdr_bits; + syn->data[1]->pvPVPState = p->bit_ctx->buf; + + syntax->number = 2; + syntax->data = syn->data; + + h263d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_h263_parser_setup_hal_output(H263dParser ctx, RK_S32 *output) +{ + H263dParserImpl *p = (H263dParserImpl *)ctx; + RK_S32 index = -1; + + h263d_dbg_func("in\n"); + + if (p->found_i_vop) { + H263Hdr *hdr_curr = &p->hdr_curr; + MppBufSlots slots = p->frame_slots; + MppFrame frame = NULL; + + mpp_frame_init(&frame); + mpp_frame_set_width(frame, p->width); + mpp_frame_set_height(frame, p->height); + mpp_frame_set_hor_stride(frame, MPP_ALIGN(p->width, 16)); + mpp_frame_set_ver_stride(frame, MPP_ALIGN(p->height, 16)); + + /* + * set slots information + * 1. output index MUST be set + * 2. get unused index for output if needed + * 3. set output index as hal_input + * 4. set frame information to output index + * 5. if one frame can be display, it SHOULD be enqueued to display queue + */ + mpp_buf_slot_get_unused(slots, &index); + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_OUTPUT); + mpp_frame_set_pts(frame, p->pts); + mpp_frame_set_dts(frame, p->dts); + mpp_frame_set_mode(frame, MPP_FRAME_FLAG_FRAME); + + mpp_buf_slot_set_prop(slots, index, SLOT_FRAME, frame); + mpp_frame_deinit(&frame); + mpp_assert(NULL == frame); + + hdr_curr->slot_idx = index; + } + + p->output = index; + *output = index; + + h263d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_h263_parser_setup_refer(H263dParser ctx, RK_S32 *refer, RK_S32 max_ref) +{ + H263dParserImpl *p = (H263dParserImpl *)ctx; + H263Hdr *hdr_curr = &p->hdr_curr; + MppBufSlots slots = p->frame_slots; + RK_S32 index; + + h263d_dbg_func("in\n"); + + memset(refer, -1, sizeof(max_ref * sizeof(*refer))); + if (hdr_curr->pict_type == H263_P_VOP) { + index = p->hdr_ref0.slot_idx; + if (index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT); + refer[0] = index; + } + } + + h263d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_h263_parser_update_dpb(H263dParser ctx) +{ + H263dParserImpl *p = (H263dParserImpl *)ctx; + MppBufSlots slots = p->frame_slots; + H263Hdr *hdr_curr = &p->hdr_curr; + H263Hdr *hdr_ref0 = &p->hdr_ref0; + RK_S32 index = hdr_curr->slot_idx; + + h263d_dbg_func("in\n"); + + mpp_assert(index >= 0); + mpp_buf_slot_set_flag(slots, index, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + hdr_curr->enqueued = 1; + + index = hdr_ref0->slot_idx; + if (index >= 0) { + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + hdr_ref0->slot_idx = -1; + } + + // swap current to ref0 + *hdr_ref0 = *hdr_curr; + hdr_curr->slot_idx = H263_INVALID_VOP; + hdr_curr->pts = 0; + hdr_curr->enqueued = 0; + + h263d_dbg_func("out\n"); + + return MPP_OK; +} + + + diff --git a/mpp/codec/dec/h263/h263d_parser.h b/mpp/codec/dec/h263/h263d_parser.h new file mode 100644 index 000000000..c41700281 --- /dev/null +++ b/mpp/codec/dec/h263/h263d_parser.h @@ -0,0 +1,53 @@ +/* + * + * Copyright 2010 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H263D_PARSER_H +#define H263D_PARSER_H + +#include "mpp_packet.h" +#include "mpp_buf_slot.h" +#include "hal_dec_task.h" + +#define H263D_DBG_FUNCTION (0x00000001) +#define H263D_DBG_STARTCODE (0x00000002) +#define H263D_DBG_BITS (0x00000004) +#define H263D_DBG_STATUS (0x00000008) +#define H263D_DBG_TIME (0x00000100) + +typedef void* H263dParser; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_h263_parser_init(H263dParser *ctx, MppBufSlots frame_slots); +MPP_RET mpp_h263_parser_deinit(H263dParser ctx); +MPP_RET mpp_h263_parser_flush(H263dParser ctx); +MPP_RET mpp_h263_parser_reset(H263dParser ctx); + +MPP_RET mpp_h263_parser_split(H263dParser ctx, MppPacket dst, MppPacket src); +MPP_RET mpp_h263_parser_decode(H263dParser ctx, MppPacket pkt); +MPP_RET mpp_h263_parser_setup_syntax(H263dParser ctx, MppSyntax *syntax); +MPP_RET mpp_h263_parser_setup_hal_output(H263dParser ctx, RK_S32 *output); +MPP_RET mpp_h263_parser_setup_refer(H263dParser ctx, RK_S32 *refer, RK_S32 max_ref); +MPP_RET mpp_h263_parser_update_dpb(H263dParser ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* H263D_PAESER_H */ diff --git a/mpp/codec/dec/h264/CMakeLists.txt b/mpp/codec/dec/h264/CMakeLists.txt index ba53bf14d..6e29808da 100644 --- a/mpp/codec/dec/h264/CMakeLists.txt +++ b/mpp/codec/dec/h264/CMakeLists.txt @@ -1,59 +1,17 @@ # vim: syntax=cmake include_directories(.) +include_directories(../common) -# h264 decoder api -set(H264D_API - ../../inc/h264d_api.h - ) -set(H264D_COMMON - ../../../common/h264d_log.h - ../../../common/h264d_syntax.h - ) - -# h264 decoder header -set(H264D_HDR - h264d_global.h - h264d_bitread.h - h264d_parse.h - h264d_slice.h - h264d_sps.h - h264d_pps.h - h264d_scalist.h - h264d_sei.h - h264d_dpb.h - h264d_init.h - h264d_fill.h - - - ) - # h264 decoder sourse -set(H264D_SRC - h264d_api.c - h264d_log.c - h264d_bitread.c - h264d_parse.c - h264d_slice.c - h264d_sps.c - h264d_pps.c - h264d_scalist.c - h264d_sei.c - h264d_dpb.c - h264d_init.c - h264d_fill.c - - - ) - - -add_library(codec_h264d STATIC - ${H264D_API} - ${H264D_COMMON} - ${H264D_HDR} - ${H264D_SRC} - ) -target_link_libraries(codec_h264d - mpp - ) -set_target_properties(codec_h264d PROPERTIES FOLDER "mpp/codec") - +add_library(h264d_api OBJECT + h264d_api.c + h264d_parse.c + h264d_slice.c + h264d_sps.c + h264d_pps.c + h264d_scalist.c + h264d_sei.c + h264d_dpb.c + h264d_init.c + h264d_fill.c + ) diff --git a/mpp/codec/dec/h264/h264d_api.c b/mpp/codec/dec/h264/h264d_api.c index 64a37fa4b..55874d68d 100644 --- a/mpp/codec/dec/h264/h264d_api.c +++ b/mpp/codec/dec/h264/h264d_api.c @@ -1,555 +1,780 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include - -#include "mpp_packet.h" -#include "mpp_packet_impl.h" -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "h264d_api.h" -#include "h264d_global.h" -#include "h264d_parse.h" -#include "h264d_sps.h" -#include "h264d_slice.h" -#include "h264d_dpb.h" - - -#define MODULE_TAG "h264d_api" - - -static void close_log_files(LogEnv_t *env) -{ - FCLOSE(env->fp_syn_parse); - FCLOSE(env->fp_run_parse); -} - -static MPP_RET open_log_files(LogEnv_t *env, LogFlag_t *pflag) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - char fname[128] = { 0 }; - - INP_CHECK(ret, ctx, !pflag->write_en); - set_log_outpath(env); - //!< runlog file - if (GetBitVal(env->ctrl, LOG_DEBUG)) { - sprintf(fname, "%s/h264d_parse_runlog.dat", env->outpath); - FLE_CHECK(ret, env->fp_run_parse = fopen(fname, "wb")); - } - //!< read syntax - if ( GetBitVal(env->ctrl, LOG_READ_NALU ) - || GetBitVal(env->ctrl, LOG_READ_SPS ) - || GetBitVal(env->ctrl, LOG_READ_SUBSPS) - || GetBitVal(env->ctrl, LOG_READ_PPS ) - || GetBitVal(env->ctrl, LOG_READ_SLICE ) ) { - sprintf(fname, "%s/h264d_read_syntax.dat", env->outpath); - FLE_CHECK(ret, env->fp_syn_parse = fopen(fname, "wb")); - } -__RETURN: - return MPP_OK; - -__FAILED: - return ret; -} - -static MPP_RET logctx_deinit(H264dLogCtx_t *logctx) -{ - close_log_files(&logctx->env); - - return MPP_OK; -} - -static MPP_RET logctx_init(H264dLogCtx_t *logctx, LogCtx_t *logbuf) -{ - RK_U8 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - LogCtx_t *pcur = NULL; - - FUN_CHECK(ret = get_logenv(&logctx->env)); - if (logctx->env.help) { - print_env_help(&logctx->env); - } - if (logctx->env.show) { - show_env_flags(&logctx->env); - } - FUN_CHECK(ret = explain_ctrl_flag(logctx->env.ctrl, &logctx->log_flag)); - if ( !logctx->log_flag.debug_en - && !logctx->log_flag.print_en && !logctx->log_flag.write_en ) { - logctx->log_flag.debug_en = 0; - goto __RETURN; - } - logctx->log_flag.level = (1 << logctx->env.level) - 1; - //!< open file - FUN_CHECK(ret = open_log_files(&logctx->env, &logctx->log_flag)); - //!< set logctx - while (i < LOG_MAX) { - if (GetBitVal(logctx->env.ctrl, i)) { - pcur = logctx->parr[i] = &logbuf[i]; - pcur->tag = logctrl_name[i]; - pcur->flag = &logctx->log_flag; - - switch (i) { - case RUN_PARSE: - pcur->fp = logctx->env.fp_run_parse; - break; - case LOG_READ_NALU: - case LOG_READ_SPS: - case LOG_READ_SUBSPS: - case LOG_READ_PPS: - case LOG_READ_SLICE: - pcur->fp = logctx->env.fp_syn_parse; - break; - default: - break; - } - } - i++; - } - -__RETURN: - return ret = MPP_OK; -__FAILED: - logctx->log_flag.debug_en = 0; - logctx_deinit(logctx); - - return ret; -} - -static MPP_RET free_input_ctx(H264dInputCtx_t *p_Inp) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_Inp); - FunctionIn(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); - - (void)p_Inp; - - FunctionOut(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -} -static MPP_RET init_input_ctx(H264dInputCtx_t *p_Inp, ParserCfg *init) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_Inp && !init); - FunctionIn(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); - - p_Inp->init = *init; - - FunctionOut(p_Inp->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -} - - -static MPP_RET free_cur_ctx(H264dCurCtx_t *p_Cur) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_Cur); - FunctionIn(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); - if (p_Cur) { - recycle_slice(&p_Cur->slice); - for (i = 0; i < 2; i++) { - mpp_free(p_Cur->listP[i]); - mpp_free(p_Cur->listB[i]); - } - mpp_free(p_Cur->strm.buf); - } - FunctionOut(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -} -static MPP_RET init_cur_ctx(H264dCurCtx_t *p_Cur) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_Cur); - FunctionIn(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); - p_Cur->strm.buf = mpp_malloc_size(RK_U8, NALU_BUF_MAX_SIZE); - MEM_CHECK(ret, p_Cur->strm.buf); - p_Cur->strm.max_size = NALU_BUF_MAX_SIZE; - p_Cur->strm.prefixdata[0] = 0xff; - p_Cur->strm.prefixdata[1] = 0xff; - p_Cur->strm.prefixdata[2] = 0xff; - for (i = 0; i < 2; i++) { - p_Cur->listP[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*)); - p_Cur->listB[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*)); - MEM_CHECK(ret, p_Cur->listP[i] && p_Cur->listB[i]); // +1 for reordering - } - FunctionOut(p_Cur->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -__FAILED: - free_cur_ctx(p_Cur); - - return ret; -} - - -static MPP_RET free_vid_ctx(H264dVideoCtx_t *p_Vid) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_Vid); - FunctionIn(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); - - for (i = 0; i < MAXSPS; i++) { - recycle_subsps(&p_Vid->subspsSet[i]); - } - for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { - free_dpb(p_Vid->p_Dpb_layer[i]); - mpp_free(p_Vid->p_Dpb_layer[i]); - } - free_storable_picture(p_Vid->dec_picture); - //free_frame_store(&p_Vid->out_buffer); - - FunctionOut(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -} -static MPP_RET init_vid_ctx(H264dVideoCtx_t *p_Vid) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_Vid); - FunctionIn(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); - for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { - p_Vid->p_Dpb_layer[i] = mpp_calloc(H264_DpbBuf_t, 1); - MEM_CHECK(ret, p_Vid->p_Dpb_layer[i]); - p_Vid->p_Dpb_layer[i]->layer_id = i; - p_Vid->p_Dpb_layer[i]->p_Vid = p_Vid; - p_Vid->p_Dpb_layer[i]->init_done = 0; - } - //!< init video pars - for (i = 0; i < MAXSPS; i++) { - p_Vid->spsSet[i].seq_parameter_set_id = -1; - p_Vid->subspsSet[i].sps.seq_parameter_set_id = -1; - } - for (i = 0; i < MAXPPS; i++) { - p_Vid->ppsSet[i].pic_parameter_set_id = -1; - p_Vid->ppsSet[i].seq_parameter_set_id = -1; - } - //!< init active_sps - p_Vid->active_sps = NULL; - p_Vid->active_subsps = NULL; - p_Vid->active_sps_id[0] = -1; - p_Vid->active_sps_id[1] = -1; - //!< init subspsSet - for (i = 0; i < MAXSPS; i++) { - p_Vid->subspsSet[i].sps.seq_parameter_set_id = -1; - p_Vid->subspsSet[i].num_views_minus1 = -1; - p_Vid->subspsSet[i].num_level_values_signalled_minus1 = -1; - } - FunctionOut(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -__FAILED: - free_vid_ctx(p_Vid); - - return ret; -} - -static MPP_RET free_dxva_ctx(H264dDxvaCtx_t *p_dxva) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, NULL == p_dxva); - FunctionIn(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); - - mpp_free(p_dxva->slice_long); - mpp_free(p_dxva->bitstream); - mpp_free(p_dxva->syn.buf); - - FunctionOut(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -} - -static MPP_RET init_dxva_ctx(H264dDxvaCtx_t *p_dxva) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_dxva); - FunctionIn(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); - - p_dxva->max_slice_size = MAX_SLICE_SIZE; - p_dxva->max_strm_size = FRAME_BUF_MAX_SIZE; - p_dxva->slice_long = mpp_calloc(DXVA_Slice_H264_Long, p_dxva->max_slice_size); - MEM_CHECK(ret, p_dxva->slice_long); - p_dxva->bitstream = mpp_malloc(RK_U8, p_dxva->max_strm_size); - p_dxva->syn.buf = mpp_calloc(DXVA2_DecodeBufferDesc, SYNTAX_BUF_SIZE); - MEM_CHECK(ret, p_dxva->bitstream && p_dxva->syn.buf); - FunctionOut(p_dxva->p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; - -__FAILED: - return ret; -} - -static MPP_RET free_dec_ctx(H264_DecCtx_t *p_Dec) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, NULL == p_Dec); - FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - if (p_Dec->mem) { - for (i = 0; i < MAX_TASK_SIZE; i++) { - free_dxva_ctx(&p_Dec->mem->dxva_ctx[i]); - } - mpp_free(p_Dec->mem); - } - FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -} -static MPP_RET init_dec_ctx(H264_DecCtx_t *p_Dec) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, !p_Dec); - FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - p_Dec->mem = mpp_calloc(H264_DecMem_t, 1); - MEM_CHECK(ret, p_Dec->mem); - p_Dec->dpb_mark = p_Dec->mem->dpb_mark; //!< for write out, MAX_DPB_SIZE - p_Dec->dpb_info = p_Dec->mem->dpb_info; //!< 16 - p_Dec->refpic_info_p = p_Dec->mem->refpic_info_p; //!< 32 - p_Dec->refpic_info[0] = p_Dec->mem->refpic_info[0]; //!< [2][32] - p_Dec->refpic_info[1] = p_Dec->mem->refpic_info[1]; //!< [2][32] - //!< MAX_TASK_SIZE - for (i = 0; i < MAX_TASK_SIZE; i++) { - p_Dec->mem->dxva_ctx[i].p_Dec = p_Dec; - FUN_CHECK(ret = init_dxva_ctx(&p_Dec->mem->dxva_ctx[i])); - } - p_Dec->dxva_idx = 0; - p_Dec->dxva_ctx = p_Dec->mem->dxva_ctx; - //!< init Dpb_memory Mark - for (i = 0; i < MAX_DPB_SIZE; i++) { - p_Dec->dpb_mark[i].index = i; - } - //!< set Dec support decoder method - p_Dec->spt_decode_mtds = MPP_DEC_BY_FRAME | MPP_DEC_BY_SLICE; - p_Dec->next_state = SliceSTATE_ResetSlice; - p_Dec->nalu_ret = NALU_NULL; - p_Dec->first_frame_flag = 1; -__RETURN: - return ret = MPP_OK; - -__FAILED: - free_dec_ctx(p_Dec); - - return ret; -} - - - - -/*! -*********************************************************************** -* \brief -* alloc all buffer -*********************************************************************** -*/ - -MPP_RET h264d_init(void *decoder, ParserCfg *init) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; - INP_CHECK(ret, ctx, !p_Dec); - memset(p_Dec, 0, sizeof(H264_DecCtx_t)); - // init logctx - FUN_CHECK(ret = logctx_init(&p_Dec->logctx, p_Dec->logctxbuf)); - FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - - p_Dec->p_Inp = mpp_calloc(H264dInputCtx_t, 1); - p_Dec->p_Cur = mpp_calloc(H264dCurCtx_t, 1); - p_Dec->p_Vid = mpp_calloc(H264dVideoCtx_t, 1); - MEM_CHECK(ret, p_Dec->p_Inp && p_Dec->p_Cur && p_Dec->p_Vid); - - p_Dec->p_Inp->p_Dec = p_Dec; - p_Dec->p_Inp->p_Cur = p_Dec->p_Cur; - p_Dec->p_Inp->p_Vid = p_Dec->p_Vid; - FUN_CHECK(ret = init_input_ctx(p_Dec->p_Inp, init)); - p_Dec->p_Cur->p_Dec = p_Dec; - p_Dec->p_Cur->p_Inp = p_Dec->p_Inp; - p_Dec->p_Cur->p_Vid = p_Dec->p_Vid; - FUN_CHECK(ret = init_cur_ctx(p_Dec->p_Cur)); - p_Dec->p_Vid->p_Dec = p_Dec; - p_Dec->p_Vid->p_Inp = p_Dec->p_Inp; - p_Dec->p_Vid->p_Cur = p_Dec->p_Cur; - FUN_CHECK(ret = init_vid_ctx(p_Dec->p_Vid)); - FUN_CHECK(ret = init_dec_ctx(p_Dec)); - - //!< return max task size - init->task_count = MAX_TASK_SIZE; // return - FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); - -__RETURN: - return ret = MPP_OK; -__FAILED: - h264d_deinit(decoder); - - return ret; -} -/*! -*********************************************************************** -* \brief -* free all buffer -*********************************************************************** -*/ -MPP_RET h264d_deinit(void *decoder) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; - - INP_CHECK(ret, ctx, !decoder); - FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - - free_input_ctx(p_Dec->p_Inp); - mpp_free(p_Dec->p_Inp); - free_cur_ctx(p_Dec->p_Cur); - mpp_free(p_Dec->p_Cur); - free_vid_ctx(p_Dec->p_Vid); - mpp_free(p_Dec->p_Vid); - free_dec_ctx(p_Dec); - - FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); - logctx_deinit(&p_Dec->logctx); -__RETURN: - return ret = MPP_OK; -} -/*! -*********************************************************************** -* \brief -* reset -*********************************************************************** -*/ -MPP_RET h264d_reset(void *decoder) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, decoder); - - (void)decoder; -__RETURN: - return ret = MPP_OK; -} - -/*! -*********************************************************************** -* \brief -* flush -*********************************************************************** -*/ -MPP_RET h264d_flush(void *decoder) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, decoder); - - (void)decoder; -__RETURN: - return ret = MPP_OK; -} - -/*! -*********************************************************************** -* \brief -* control/perform -*********************************************************************** -*/ -MPP_RET h264d_control(void *decoder, RK_S32 cmd_type, void *param) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - INP_CHECK(ret, ctx, decoder); - - - (void)decoder; - (void)cmd_type; - (void)param; - - -__RETURN: - return ret = MPP_OK; -} - -/*! -*********************************************************************** -* \brief -* parser -*********************************************************************** -*/ -MPP_RET h264d_parse(void *decoder, MppPacket in_pkt, HalDecTask *in_task) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; - MppPacketImpl *pkt = (MppPacketImpl *)in_pkt; - - INP_CHECK(ret, ctx, !decoder && !in_pkt && !in_task); - FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - - p_Dec->p_Inp->in_buf = (RK_U8 *)pkt->pos; - p_Dec->p_Inp->in_size = &pkt->size; - p_Dec->p_Inp->is_eos = pkt->flag & MPP_PACKET_FLAG_EOS; - - FUN_CHECK(ret = parse_loop(p_Dec)); - if (p_Dec->parser_end_flag) { - in_task->valid = 1; - in_task->syntax.number = p_Dec->dxva_ctx->syn.num; - in_task->syntax.data = (void *)p_Dec->dxva_ctx->syn.buf; - FUN_CHECK(ret = update_dpb(p_Dec)); - p_Dec->dxva_idx = (p_Dec->dxva_idx + 1) % MAX_TASK_SIZE; - p_Dec->dxva_ctx = &p_Dec->mem->dxva_ctx[p_Dec->dxva_idx]; - } - - FunctionOut(p_Dec->logctx.parr[RUN_PARSE]); -__RETURN: - return ret = MPP_OK; -__FAILED: - return ret; -} - -/*! -*********************************************************************** -* \brief -* api struct interface -*********************************************************************** -*/ - -const ParserApi api_h264d_parser = { - "h264d_parse", - MPP_VIDEO_CodingAVC, - sizeof(H264_DecCtx_t), - 0, - h264d_init, - h264d_deinit, - NULL, - h264d_parse, - h264d_reset, - h264d_flush, - h264d_control, -}; +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_api" + +#include + +#include "mpp_env.h" +#include "mpp_platform.h" +#include "mpp_packet_impl.h" +#include "mpp_frame_impl.h" + +#include "mpp_parser.h" +#include "h264d_global.h" +#include "h264d_parse.h" +#include "h264d_sps.h" +#include "h264d_slice.h" +#include "h264d_dpb.h" +#include "h264d_init.h" +#include "h2645d_sei.h" +#include "mpp_dec_cb_param.h" + +// for mblock 16 coded width align +static RK_U32 rkv_mblock_width_align(RK_U32 val) +{ + return MPP_ALIGN(val, 16); +} + +static MPP_RET free_input_ctx(H264dInputCtx_t *p_Inp) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Inp); + close_stream_file(p_Inp); + MPP_FREE(p_Inp->spspps_buf); + +__RETURN: + return ret = MPP_OK; +} +static MPP_RET init_input_ctx(H264dInputCtx_t *p_Inp, ParserCfg *init) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Inp && !init); + + open_stream_file(p_Inp, "/sdcard"); + if (h264d_debug & H264D_DBG_WRITE_ES_EN) { + p_Inp->spspps_size = HEAD_BUF_MAX_SIZE; + p_Inp->spspps_buf = mpp_malloc_size(RK_U8, p_Inp->spspps_size); + MEM_CHECK(ret, p_Inp->spspps_buf); + } + +__RETURN: + return ret = MPP_OK; +__FAILED: + free_input_ctx(p_Inp); + return ret; +} + + +static MPP_RET free_cur_ctx(H264dCurCtx_t *p_Cur) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Cur); + + if (p_Cur) { + for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { + MPP_FREE(p_Cur->listP[i]); + MPP_FREE(p_Cur->listB[i]); + } + MPP_FREE(p_Cur->strm.nalu_buf); + MPP_FREE(p_Cur->strm.head_buf); + MPP_FREE(p_Cur->strm.tmp_buf); + + for (i = 0; i < MAX_MARKING_TIMES; i++) + MPP_FREE(p_Cur->dec_ref_pic_marking_buffer[i]); + + MPP_FREE(p_Cur->subsps); + MPP_FREE(p_Cur->sei); + MPP_FREE(p_Cur->hdr_dynamic_meta); + } + +__RETURN: + return ret = MPP_OK; +} +static MPP_RET init_cur_ctx(H264dCurCtx_t *p_Cur) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dCurStream_t *p_strm = NULL; + + INP_CHECK(ret, !p_Cur); + + p_strm = &p_Cur->strm; + p_strm->nalu_max_size = NALU_BUF_MAX_SIZE; + p_strm->nalu_buf = mpp_malloc_size(RK_U8, p_strm->nalu_max_size); + p_strm->head_max_size = HEAD_BUF_MAX_SIZE; + p_strm->head_buf = mpp_malloc_size(RK_U8, p_strm->head_max_size); + p_strm->tmp_max_size = HEAD_BUF_MAX_SIZE; + p_strm->tmp_buf = mpp_malloc_size(RK_U8, p_strm->head_max_size); + MEM_CHECK(ret, p_strm->nalu_buf && p_strm->head_buf); + p_strm->prefixdata = 0xffffffff; + for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { + p_Cur->listP[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*)); + p_Cur->listB[i] = mpp_malloc_size(H264_StorePic_t*, MAX_LIST_SIZE * sizeof(H264_StorePic_t*)); + MEM_CHECK(ret, p_Cur->listP[i] && p_Cur->listB[i]); // +1 for reordering + } + reset_cur_slice(p_Cur, &p_Cur->slice); + +__RETURN: + return ret = MPP_OK; +__FAILED: + free_cur_ctx(p_Cur); + + return ret; +} + + +static MPP_RET free_vid_ctx(H264dVideoCtx_t *p_Vid) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Vid); + + for (i = 0; i < MAXSPS; i++) { + MPP_FREE(p_Vid->spsSet[i]); + if (p_Vid->subspsSet[i]) + recycle_subsps(p_Vid->subspsSet[i]); + MPP_FREE(p_Vid->subspsSet[i]); + } + + for (i = 0; i < MAXPPS; i++) + MPP_FREE(p_Vid->ppsSet[i]); + + for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { + free_dpb(p_Vid->p_Dpb_layer[i]); + MPP_FREE(p_Vid->p_Dpb_layer[i]); + } + + free_storable_picture(p_Vid->p_Dec, p_Vid->dec_pic); + + if (p_Vid->pic_st) { + mpp_mem_pool_deinit_f(p_Vid->pic_st); + p_Vid->pic_st = NULL; + } + +__RETURN: + return ret = MPP_OK; +} +static MPP_RET init_vid_ctx(H264dVideoCtx_t *p_Vid) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Vid); + + for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { + p_Vid->p_Dpb_layer[i] = mpp_calloc(H264_DpbBuf_t, 1); + MEM_CHECK(ret, p_Vid->p_Dpb_layer[i]); + p_Vid->p_Dpb_layer[i]->layer_id = i; + p_Vid->p_Dpb_layer[i]->p_Vid = p_Vid; + p_Vid->p_Dpb_layer[i]->init_done = 0; + p_Vid->p_Dpb_layer[i]->poc_interval = 2; + } + + //!< init active_sps + p_Vid->active_sps = NULL; + p_Vid->active_subsps = NULL; + p_Vid->active_sps_id[0] = -1; + p_Vid->active_sps_id[1] = -1; + p_Vid->pic_st = mpp_mem_pool_init_f("h264d_pic_st", sizeof(H264_StorePic_t)); +__RETURN: + return ret = MPP_OK; +__FAILED: + free_vid_ctx(p_Vid); + + return ret; +} + +static MPP_RET free_dxva_ctx(H264dDxvaCtx_t *p_dxva) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, NULL == p_dxva); + + MPP_FREE(p_dxva->slice_long); + MPP_FREE(p_dxva->bitstream); + MPP_FREE(p_dxva->syn.buf); + +__RETURN: + return ret = MPP_OK; +} + +static MPP_RET init_dxva_ctx(H264dDxvaCtx_t *p_dxva) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_dxva); + + p_dxva->slice_count = 0; + p_dxva->max_slice_size = MAX_SLICE_NUM; + p_dxva->max_strm_size = BITSTREAM_MAX_SIZE; + p_dxva->slice_long = mpp_calloc(DXVA_Slice_H264_Long, p_dxva->max_slice_size); + MEM_CHECK(ret, p_dxva->slice_long); + p_dxva->bitstream = mpp_malloc(RK_U8, p_dxva->max_strm_size); + p_dxva->syn.buf = mpp_calloc(DXVA2_DecodeBufferDesc, SYNTAX_BUF_SIZE); + MEM_CHECK(ret, p_dxva->bitstream && p_dxva->syn.buf); + +__RETURN: + return ret = MPP_OK; + +__FAILED: + return ret; +} + +static MPP_RET free_dec_ctx(H264_DecCtx_t *p_Dec) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, NULL == p_Dec); + + if (p_Dec->mem) { + free_dxva_ctx(&p_Dec->mem->dxva_ctx); + MPP_FREE(p_Dec->mem); + } + //!< free mpp packet + mpp_packet_deinit(&p_Dec->task_pkt); + +__RETURN: + return ret = MPP_OK; +} +static MPP_RET init_dec_ctx(H264_DecCtx_t *p_Dec) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Dec); + + p_Dec->mem = mpp_calloc(H264_DecMem_t, 1); + MEM_CHECK(ret, p_Dec->mem); + p_Dec->dpb_mark = p_Dec->mem->dpb_mark; //!< for write out, MAX_DPB_SIZE + p_Dec->dpb_info = p_Dec->mem->dpb_info; //!< 16 + p_Dec->refpic_info_p = p_Dec->mem->refpic_info_p; //!< 32 + p_Dec->refpic_info_b[0] = p_Dec->mem->refpic_info_b[0]; //!< [2][32] + p_Dec->refpic_info_b[1] = p_Dec->mem->refpic_info_b[1]; //!< [2][32] + //!< init dxva memory + p_Dec->mem->dxva_ctx.p_Dec = p_Dec; + FUN_CHECK(ret = init_dxva_ctx(&p_Dec->mem->dxva_ctx)); + p_Dec->dxva_ctx = &p_Dec->mem->dxva_ctx; + //!< init Dpb_memory Mark + for (i = 0; i < MAX_MARK_SIZE; i++) { + reset_dpb_mark(&p_Dec->dpb_mark[i]); + p_Dec->dpb_mark[i].mark_idx = i; + } + mpp_buf_slot_setup(p_Dec->frame_slots, MAX_MARK_SIZE); + //!< malloc mpp packet + mpp_packet_init(&p_Dec->task_pkt, p_Dec->dxva_ctx->bitstream, p_Dec->dxva_ctx->max_strm_size); + MEM_CHECK(ret, p_Dec->task_pkt); + //!< set Dec support decoder method + p_Dec->spt_decode_mtds = MPP_DEC_BY_FRAME; + p_Dec->next_state = SliceSTATE_ResetSlice; + p_Dec->nalu_ret = NALU_NULL; + p_Dec->have_slice_data = 0; + p_Dec->last_frame_slot_idx = -1; + memset(&p_Dec->errctx, 0, sizeof(H264dErrCtx_t)); +__RETURN: + return ret = MPP_OK; + +__FAILED: + free_dec_ctx(p_Dec); + + return ret; +} + +static MPP_RET h264d_flush_dpb_eos(H264_DecCtx_t *p_Dec) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + INP_CHECK(ret, !p_Dec->p_Vid); + + FUN_CHECK(ret = flush_dpb(p_Dec->p_Vid->p_Dpb_layer[0], 1)); + FUN_CHECK(ret = init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], 1)); + if (p_Dec->mvc_valid) { + // layer_id == 1 + FUN_CHECK(ret = flush_dpb(p_Dec->p_Vid->p_Dpb_layer[1], 1)); + FUN_CHECK(ret = init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[1], 2)); + FUN_CHECK(ret = check_mvc_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], p_Dec->p_Vid->p_Dpb_layer[1])); + } + + flush_dpb_buf_slot(p_Dec); + +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret = MPP_NOK; +} + +/*! +*********************************************************************** +* \brief +* free all buffer +*********************************************************************** +*/ +MPP_RET h264d_deinit(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + + INP_CHECK(ret, !decoder); + + mpp_frame_deinit(&p_Dec->curframe); + free_input_ctx(p_Dec->p_Inp); + MPP_FREE(p_Dec->p_Inp); + free_cur_ctx(p_Dec->p_Cur); + MPP_FREE(p_Dec->p_Cur); + free_vid_ctx(p_Dec->p_Vid); + MPP_FREE(p_Dec->p_Vid); + free_dec_ctx(p_Dec); + +__RETURN: + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* alloc all buffer +*********************************************************************** +*/ +MPP_RET h264d_init(void *decoder, ParserCfg *init) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + INP_CHECK(ret, !p_Dec); + memset(p_Dec, 0, sizeof(H264_DecCtx_t)); + + mpp_env_get_u32("h264d_debug", &h264d_debug, H264D_DBG_ERROR); + + //!< get init frame_slots and packet_slots + p_Dec->frame_slots = init->frame_slots; + p_Dec->packet_slots = init->packet_slots; + p_Dec->cfg = init->cfg; + mpp_frame_init(&p_Dec->curframe); + //!< malloc decoder buffer + p_Dec->p_Inp = mpp_calloc(H264dInputCtx_t, 1); + p_Dec->p_Cur = mpp_calloc(H264dCurCtx_t, 1); + p_Dec->p_Vid = mpp_calloc(H264dVideoCtx_t, 1); + MEM_CHECK(ret, p_Dec->p_Inp && p_Dec->p_Cur && p_Dec->p_Vid); + p_Dec->p_Inp->p_Dec = p_Dec; + p_Dec->p_Inp->p_Cur = p_Dec->p_Cur; + p_Dec->p_Inp->p_Vid = p_Dec->p_Vid; + + p_Dec->p_Cur->p_Dec = p_Dec; + p_Dec->p_Cur->p_Inp = p_Dec->p_Inp; + p_Dec->p_Cur->p_Vid = p_Dec->p_Vid; + + p_Dec->p_Vid->p_Dec = p_Dec; + p_Dec->p_Vid->p_Inp = p_Dec->p_Inp; + p_Dec->p_Vid->p_Cur = p_Dec->p_Cur; + p_Dec->hw_info = init->hw_info; + FUN_CHECK(ret = init_input_ctx(p_Dec->p_Inp, init)); + FUN_CHECK(ret = init_cur_ctx(p_Dec->p_Cur)); + FUN_CHECK(ret = init_vid_ctx(p_Dec->p_Vid)); + FUN_CHECK(ret = init_dec_ctx(p_Dec)); + p_Dec->immediate_out = p_Dec->cfg->base.fast_out; + mpp_env_get_u32("force_fast_play_mode", &p_Dec->cfg->base.enable_fast_play, + p_Dec->cfg->base.enable_fast_play); + p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play; + H264D_LOG("fast play mode: %d", p_Dec->cfg->base.enable_fast_play); + p_Dec->p_Vid->dpb_first_fast_played = 0; + mpp_slots_set_prop(p_Dec->frame_slots, SLOTS_WIDTH_ALIGN, rkv_mblock_width_align); +__RETURN: + return ret = MPP_OK; +__FAILED: + h264d_deinit(decoder); + + return ret; +} + +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +MPP_RET h264d_reset(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + H264dCurStream_t *p_strm = NULL; + + INP_CHECK(ret, !decoder); + + flush_dpb(p_Dec->p_Vid->p_Dpb_layer[0], 1); + init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], 1); + if (p_Dec->mvc_valid) { + // layer_id == 1 + flush_dpb(p_Dec->p_Vid->p_Dpb_layer[1], 1); + init_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[1], 2); + check_mvc_dpb(p_Dec->p_Vid, p_Dec->p_Vid->p_Dpb_layer[0], p_Dec->p_Vid->p_Dpb_layer[1]); + } + flush_dpb_buf_slot(p_Dec); + //!< reset input parameter + p_Dec->p_Inp->in_buf = NULL; + p_Dec->p_Inp->pkt_eos = 0; + p_Dec->p_Inp->task_eos = 0; + p_Dec->p_Inp->in_pts = 0; + p_Dec->p_Inp->in_dts = 0; + p_Dec->p_Inp->has_get_eos = 0; + //!< reset video parameter + p_Dec->p_Vid->have_outpicture_flag = 0; + p_Dec->p_Vid->exit_picture_flag = 0; + p_Dec->p_Vid->active_mvc_sps_flag = 0; + p_Dec->p_Vid->g_framecnt = 0; + p_Dec->p_Vid->dec_pic = NULL; + p_Dec->p_Vid->last_pic = NULL; + memset(&p_Dec->p_Vid->recovery, 0, sizeof(RecoveryPoint)); + memset(&p_Dec->p_Vid->old_pic, 0, sizeof(H264_StorePic_t)); + memset(&p_Dec->errctx, 0, sizeof(H264dErrCtx_t)); + //!< reset current time stamp + p_Dec->p_Cur->last_dts = 0; + p_Dec->p_Cur->last_pts = 0; + p_Dec->p_Cur->curr_dts = 0; + p_Dec->p_Cur->curr_pts = 0; + //!< reset current stream + p_strm = &p_Dec->p_Cur->strm; + p_strm->prefixdata = 0xffffffff; + p_strm->nalu_offset = 0; + p_strm->nalu_len = 0; + p_strm->tmp_offset = 0; + p_strm->first_mb_in_slice = 0; + p_strm->endcode_found = 0; + p_strm->startcode_found = p_Dec->p_Inp->is_nalff; + //!< reset decoder parameter + p_Dec->next_state = SliceSTATE_ResetSlice; + p_Dec->nalu_ret = NALU_NULL; + p_Dec->have_slice_data = 0; + p_Dec->is_new_frame = 0; + p_Dec->is_parser_end = 0; + p_Dec->dxva_ctx->strm_offset = 0; + p_Dec->dxva_ctx->slice_count = 0; + p_Dec->last_frame_slot_idx = -1; + mpp_env_get_u32("force_fast_play_mode", &p_Dec->cfg->base.enable_fast_play, + p_Dec->cfg->base.enable_fast_play); + p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play; + H264D_LOG("fast play mode: %d", p_Dec->cfg->base.enable_fast_play); + p_Dec->p_Vid->dpb_first_fast_played = 0; + +__RETURN: + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +MPP_RET h264d_flush(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + + INP_CHECK(ret, !decoder); + INP_CHECK(ret, !p_Dec->p_Inp); + INP_CHECK(ret, !p_Dec->p_Vid); + + FUN_CHECK(ret = output_dpb(p_Dec, p_Dec->p_Vid->p_Dpb_layer[0])); + if (p_Dec->mvc_valid) { + FUN_CHECK(ret = output_dpb(p_Dec, p_Dec->p_Vid->p_Dpb_layer[1])); + } + +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret = MPP_NOK; +} + +/*! +*********************************************************************** +* \brief +* control/perform +*********************************************************************** +*/ +MPP_RET h264d_control(void *decoder, MpiCmd cmd_type, void *param) +{ + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + + switch (cmd_type) { + case MPP_DEC_SET_ENABLE_FAST_PLAY: + p_Dec->cfg->base.enable_fast_play = (param) ? (*((RK_U32 *)param)) : (1); + mpp_env_get_u32("force_fast_play_mode", &p_Dec->cfg->base.enable_fast_play, + p_Dec->cfg->base.enable_fast_play); + p_Dec->p_Vid->dpb_fast_out = p_Dec->cfg->base.enable_fast_play; + H264D_LOG("fast play mode: %d", p_Dec->cfg->base.enable_fast_play); + break; + case MPP_DEC_SET_MAX_USE_BUFFER_SIZE : + p_Dec->p_Inp->max_buf_size = (param) ? (*((RK_U32 *)param)) : (0); + break; + default: + break; + } + + return MPP_OK; +} + + +/*! +*********************************************************************** +* \brief +* prepare +*********************************************************************** +*/ +#define MAX_STREM_IN_SIZE (10*1024*1024) +MPP_RET h264d_prepare(void *decoder, MppPacket pkt, HalDecTask *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dInputCtx_t *p_Inp = NULL; + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + + INP_CHECK(ret, !decoder && !pkt && !task); + + p_Inp = p_Dec->p_Inp; + if (p_Inp->has_get_eos) { + mpp_packet_set_length(pkt, 0); + task->flags.eos = mpp_packet_get_eos(pkt); + goto __RETURN; + } + p_Inp->in_pkt = pkt; + p_Inp->in_pts = mpp_packet_get_pts(pkt); + p_Inp->in_dts = mpp_packet_get_dts(pkt); + p_Inp->in_length = mpp_packet_get_length(pkt); + p_Inp->pkt_eos = mpp_packet_get_eos(pkt); + p_Inp->in_buf = (RK_U8 *)mpp_packet_get_pos(pkt); + + if (p_Inp->pkt_eos && p_Inp->in_length < 4) { + p_Inp->has_get_eos = 1; + p_Inp->in_buf = NULL; + p_Inp->in_length = 0; + mpp_packet_set_length(p_Inp->in_pkt, 0); + task->flags.eos = p_Inp->pkt_eos; + } + + if (p_Inp->in_length > MAX_STREM_IN_SIZE) { + H264D_ERR("[pkt_in_timeUs] input error, stream too large, pts=%lld, eos=%d, len=%d, pkt_no=%d", + p_Inp->in_pts, p_Inp->pkt_eos, p_Inp->in_length, p_Dec->p_Vid->g_framecnt); + mpp_packet_set_length(pkt, 0); + ret = MPP_NOK; + goto __FAILED; + } + //!< avcC stream + if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) { + RK_U8 *pdata = p_Inp->in_buf; + + p_Inp->is_nalff = (p_Inp->in_length > 3) && (pdata[0] == 1); + mpp_log("is_avcC=%d\n", p_Inp->is_nalff); + if (p_Inp->is_nalff) { + (ret = parse_prepare_avcC_header(p_Inp, p_Dec->p_Cur)); + goto __RETURN; + } + } + H264D_DBG(H264D_DBG_INPUT, "[pkt_in_timeUs] is_avcC=%d, in_pts=%lld, pkt_eos=%d, len=%d, pkt_no=%d", + p_Inp->is_nalff, p_Inp->in_pts, p_Inp->pkt_eos, p_Inp->in_length, p_Dec->p_Vid->g_framecnt); + if (p_Inp->is_nalff) { + (ret = parse_prepare_avcC_data(p_Inp, p_Dec->p_Cur)); + task->valid = p_Inp->task_valid; //!< prepare valid flag + } else { + fwrite_stream_to_file(p_Inp, p_Inp->in_buf, (RK_U32)p_Inp->in_length); + do { + if (p_Dec->cfg->base.split_parse) { + ret = parse_prepare(p_Inp, p_Dec->p_Cur); + } else { + ret = parse_prepare_fast(p_Inp, p_Dec->p_Cur); + } + task->valid = p_Inp->task_valid; //!< prepare valid flag + } while (mpp_packet_get_length(pkt) && !task->valid); + } + if (p_Inp->in_length < 4) + task->flags.eos = p_Inp->pkt_eos; + if (task->valid) { + memset(p_Dec->dxva_ctx->bitstream + p_Dec->dxva_ctx->strm_offset, 0, + MPP_ALIGN(p_Dec->dxva_ctx->strm_offset, 16) - p_Dec->dxva_ctx->strm_offset); + mpp_packet_set_data(p_Dec->task_pkt, p_Dec->dxva_ctx->bitstream); + mpp_packet_set_length(p_Dec->task_pkt, MPP_ALIGN(p_Dec->dxva_ctx->strm_offset, 16)); + mpp_packet_set_size(p_Dec->task_pkt, p_Dec->dxva_ctx->max_strm_size); + task->input_packet = p_Dec->task_pkt; + } else { + task->input_packet = NULL; + /* + * During split_parse, the empty EOS will endcode and decode the + * last complete packet. + * When sending EOS in split mode, dpb can not be flushed + * before split process. + */ + if (p_Inp->pkt_eos && p_Inp->in_length < 4) + h264d_flush_dpb_eos(p_Dec); + } +__RETURN: + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +/*! +*********************************************************************** +* \brief +* parser +*********************************************************************** +*/ +MPP_RET h264d_parse(void *decoder, HalDecTask *in_task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + H264dErrCtx_t *p_err = &p_Dec->errctx; + + in_task->valid = 0; + p_Dec->in_task = in_task; + p_err->cur_err_flag = 0; + p_err->used_ref_flag = 0; + p_Dec->is_parser_end = 0; + if (p_Dec->p_Cur->sei) + memset(p_Dec->p_Cur->sei, 0, sizeof(*p_Dec->p_Cur->sei)); + + ret = parse_loop(p_Dec); + if (ret) { + in_task->flags.parse_err = 1; + } + + if (p_Dec->is_parser_end) { + p_Dec->is_parser_end = 0; + p_Dec->p_Vid->g_framecnt++; + ret = update_dpb(p_Dec); + if (ret) { + in_task->flags.ref_err = 1; + } + if (in_task->flags.eos) { + h264d_flush_dpb_eos(p_Dec); + } + } + in_task->valid = 1; + if (!in_task->flags.parse_err) { + in_task->syntax.number = p_Dec->dxva_ctx->syn.num; + in_task->syntax.data = (void *)p_Dec->dxva_ctx->syn.buf; + in_task->flags.used_for_ref = p_err->used_ref_flag; + in_task->flags.ref_err |= ((p_err->dpb_err_flag | p_err->cur_err_flag) != 0) ? 1 : 0; + } + + return ret; +} + +/*! +*********************************************************************** +* \brief +* callback +*********************************************************************** +*/ +MPP_RET h264d_callback(void *decoder, void *errinfo) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = (H264_DecCtx_t *)decoder; + DecCbHalDone *ctx = (DecCbHalDone *)errinfo; + HalDecTask *task_dec = (HalDecTask *)ctx->task; + RK_U32 task_err = task_dec->flags.parse_err || task_dec->flags.ref_err; + RK_U32 ref_used = (task_dec->flags.ref_info_valid != 0) ? task_dec->flags.ref_used : 0; + RK_U32 hw_dec_err = ctx->hard_err; + RK_S32 output = task_dec->output; + RK_U32 err_mark = 0; + MppFrame frame = NULL; + + INP_CHECK(ret, !decoder); + + if (output >= 0) + mpp_buf_slot_get_prop(p_Dec->frame_slots, output, SLOT_FRAME_PTR, &frame); + + if (!frame) + goto __RETURN; + + /* check and mark current frame */ + if (task_err) { + err_mark |= MPP_FRAME_ERR_DEC_INVALID; + goto DONE; + } + + if (hw_dec_err) { + err_mark |= MPP_FRAME_ERR_DEC_HW_ERR; + goto DONE; + } + + if (ref_used) { + RK_S32 *refer = task_dec->refer; + RK_U32 i; + + for (i = 0; i < 16; i++) { + RK_U32 mask = 1 << i; + RK_U32 error = 0; + MppFrameImpl *tmp = NULL; + + /* not used frame or non-refer frame skip */ + if (!(ref_used & mask) || (refer[i] < 0)) + continue; + + /* check and mark error for error reference frame */ + mpp_buf_slot_get_prop(p_Dec->frame_slots, refer[i], + SLOT_FRAME_PTR, &tmp); + + error = tmp->errinfo; + H264D_DBG(H264D_DBG_DPB_REF_ERR, + "cur_poc %d frm slot %d refer %d slot %d poc %d errinfo %x\n", + mpp_frame_get_poc(frame), output, i, refer[i], tmp->poc, error); + + if (error) { + mpp_log_f("cur_poc %d mark error ref slot %d:%d poc %d err %x\n", + mpp_frame_get_poc(frame), i, refer[i], tmp->poc, error); + err_mark |= MPP_FRAME_ERR_UNKNOW; + break; + } + } + } + +DONE: + if (err_mark) { + if (task_dec->flags.used_for_ref) { + mpp_frame_set_errinfo(frame, err_mark); + } else { + mpp_frame_set_discard(frame, err_mark); + } + } + + H264D_DBG(H264D_DBG_CALLBACK, + "[CALLBACK] g_no %d, out_idx %d, dpberr %d, harderr %d, ref_flag %d, " + "errinfo %x, discard %x poc %d view_id %d\n", + p_Dec->p_Vid->g_framecnt, output, task_err, ctx->hard_err, + task_dec->flags.used_for_ref, mpp_frame_get_errinfo(frame), + mpp_frame_get_discard(frame), mpp_frame_get_poc(frame), + mpp_frame_get_viewid(frame)); + +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* api struct interface +*********************************************************************** +*/ + +const ParserApi mpp_h264d = { + .name = "h264d_parse", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264_DecCtx_t), + .flag = 0, + .init = h264d_init, + .deinit = h264d_deinit, + .prepare = h264d_prepare, + .parse = h264d_parse, + .reset = h264d_reset, + .flush = h264d_flush, + .control = h264d_control, + .callback = h264d_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_h264d); diff --git a/mpp/codec/dec/h264/h264d_bitread.c b/mpp/codec/dec/h264/h264d_bitread.c deleted file mode 100644 index 93f7a620b..000000000 --- a/mpp/codec/dec/h264/h264d_bitread.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include -#include -#include "mpp_err.h" -#include "h264d_bitread.h" - -#define MODULE_TAG "" - - -static MPP_RET update_currbyte(BitReadCtx_t *bitctx) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - VAL_CHECK(ret, bitctx->bytes_left_ > 0); - // Emulation prevention three-byte detection. - // If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03). - if (*bitctx->data_ == 0x03 && (bitctx->prev_two_bytes_ & 0xffff) == 0) { - // Detected 0x000003, skip last byte. - ++bitctx->data_; - --bitctx->bytes_left_; - ++bitctx->emulation_prevention_bytes_; - // Need another full three bytes before we can detect the sequence again. - bitctx->prev_two_bytes_ = 0xffff; - VAL_CHECK(ret, bitctx->bytes_left_ > 0); - } - // Load a new byte and advance pointers. - bitctx->curr_byte_ = *bitctx->data_++ & 0xff; - --bitctx->bytes_left_; - bitctx->num_remaining_bits_in_curr_byte_ = 8; - bitctx->prev_two_bytes_ = (bitctx->prev_two_bytes_ << 8) | bitctx->curr_byte_; - - return ret = MPP_OK; -__FAILED: - return ret; -} - -/*! -*********************************************************************** -* \brief -* Read |num_bits| (1 to 31 inclusive) from the stream and return them -* in |out|, with first bit in the stream as MSB in |out| at position -* (|num_bits| - 1) -*********************************************************************** -*/ - -MPP_RET read_bits(BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - RK_S32 bits_left = num_bits; - - *out = 0; - VAL_CHECK(ret, num_bits < 32); - while (bitctx->num_remaining_bits_in_curr_byte_ < bits_left) { - // Take all that's left in current byte, shift to make space for the rest. - *out |= (bitctx->curr_byte_ << (bits_left - bitctx->num_remaining_bits_in_curr_byte_)); - bits_left -= bitctx->num_remaining_bits_in_curr_byte_; - - FUN_CHECK(ret = update_currbyte(bitctx)); - } - - *out |= (bitctx->curr_byte_ >> (bitctx->num_remaining_bits_in_curr_byte_ - bits_left)); - *out &= ((1 << num_bits) - 1); - bitctx->num_remaining_bits_in_curr_byte_ -= bits_left; - bitctx->used_bits += num_bits; - - return ret = MPP_OK; -__FAILED: - return ret = MPP_ERR_READ_BIT; -} -/*! -*********************************************************************** -* \brief -* read one bit -*********************************************************************** -*/ -MPP_RET read_one_bit(BitReadCtx_t *bitctx, RK_S32 *out) -{ - return read_bits(bitctx, 1, out); -} -/*! -*********************************************************************** -* \brief -* read ue -*********************************************************************** -*/ -MPP_RET read_ue(BitReadCtx_t *bitctx, RK_U32 *val) -{ - RK_S32 num_bits = -1; - RK_S32 bit; - RK_S32 rest; - MPP_RET ret = MPP_ERR_UNKNOW; - // Count the number of contiguous zero bits. - do { - FUN_CHECK(ret = read_bits(bitctx, 1, &bit)); - num_bits++; - } while (bit == 0); - - VAL_CHECK(ret, num_bits < 32); - // Calculate exp-Golomb code value of size num_bits. - *val = (1 << num_bits) - 1; - - if (num_bits > 0) { - FUN_CHECK(ret = read_bits(bitctx, num_bits, &rest)); - *val += rest; - } - - return ret = MPP_OK; -__FAILED: - return ret = MPP_ERR_READ_BIT; -} -/*! -*********************************************************************** -* \brief -* read se -*********************************************************************** -*/ -MPP_RET read_se(BitReadCtx_t *bitctx, RK_S32 *val) -{ - RK_U32 ue; - MPP_RET ret = MPP_ERR_UNKNOW; - - FUN_CHECK(ret = read_ue(bitctx, &ue)); - - if (ue % 2 == 0) { // odd - *val = -(RK_S32)(ue >> 1); - } else { - *val = (RK_S32)((ue >> 1) + 1); - } - - return ret = MPP_OK; -__FAILED: - return ret = MPP_ERR_READ_BIT; -} - -/*! -*********************************************************************** -* \brief -* check has more rbsp data in read pps syntax -*********************************************************************** -*/ -RET_tpye has_more_rbsp_data(BitReadCtx_t * bitctx) -{ - // Make sure we have more bits, if we are at 0 bits in current byte - // and updating current byte fails, we don't have more data anyway. - if (bitctx->num_remaining_bits_in_curr_byte_ == 0 && update_currbyte(bitctx)) - return RET_FALSE; - // On last byte? - if (bitctx->bytes_left_) - return RET_TURE; - // Last byte, look for stop bit; - // We have more RBSP data if the last non-zero bit we find is not the - // first available bit. - return (RET_tpye)((bitctx->curr_byte_ & ((1 << (bitctx->num_remaining_bits_in_curr_byte_ - 1)) - 1)) != 0); -} - -/*! -*********************************************************************** -* \brief -* set bitread context -*********************************************************************** -*/ -void set_bitread_ctx(BitReadCtx_t *bitctx, RK_U8 *data, RK_S32 size) -{ - memset(bitctx, 0, sizeof(BitReadCtx_t)); - bitctx->data_ = data; - bitctx->bytes_left_ = size; - bitctx->num_remaining_bits_in_curr_byte_ = 0; - // Initially set to 0xffff to accept all initial two-byte sequences. - bitctx->prev_two_bytes_ = 0xffff; - bitctx->emulation_prevention_bytes_ = 0; - // add - bitctx->buf = data; - bitctx->buf_len = size; - bitctx->used_bits = 0; -} -/*! -*********************************************************************** -* \brief -* set bitread log context -*********************************************************************** -*/ -void set_bitread_logctx(BitReadCtx_t *bitctx, LogCtx_t *p_ctx) -{ - bitctx->ctx = p_ctx; -} - -/*! -*********************************************************************** -* \brief -* get current data value, used in read sei syntax -*********************************************************************** -*/ -RK_U8 get_currdata_value(BitReadCtx_t *bitctx) -{ - return (*bitctx->data_); -} - - - - diff --git a/mpp/codec/dec/h264/h264d_bitread.h b/mpp/codec/dec/h264/h264d_bitread.h deleted file mode 100644 index 169a4ec72..000000000 --- a/mpp/codec/dec/h264/h264d_bitread.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __H264D_BITREAD_H__ -#define __H264D_BITREAD_H__ -#include -#include -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_log.h" - -#define __BITREAD_ERR __bitread_error - -#define WRITE_LOG(bitctx, name)\ - do {\ - LogInfo(bitctx->ctx, "%s", name);\ - } while (0) - -#define SKIP_BITS(ret, bitctx, num_bits)\ - do {\ - RK_S32 _out;\ - ret = read_bits(bitctx, num_bits, &_out);\ - LogInfo(bitctx->ctx, "%48s = %10d", "skip", _out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - } while (0) - - -#define READ_BITS(ret, bitctx, num_bits, out, name)\ - do {\ - ret = read_bits(bitctx, num_bits, (RK_S32 *)out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - } while (0) - -#define READ_ONEBIT(ret, bitctx, out, name)\ - do {\ - ret = read_bits(bitctx, 1, (RK_S32 *)out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - } while (0) - - -#define READ_UE(ret, bitctx, out, name)\ - do {\ - ret = read_ue(bitctx, (RK_U32 *)out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - } while (0) - - -#define READ_SE(ret, bitctx, out, name)\ - do {\ - ret = read_se(bitctx, (RK_S32 *)out);\ - LogInfo(bitctx->ctx, "%48s = %10d", name, *out);\ - if (ret) { ASSERT(0); goto __FAILED; }\ - } while (0) - -#define CHECK_RANGE(ret, bitctx, val, _min, _max)\ - do {\ - if ((val) < (_min) || (val) > (_max)) {\ - LogError(bitctx->ctx, "%d[%d,%d]", val, _min, _max);\ - ret = MPP_ERR_VALUE;\ - ASSERT(0); goto __FAILED;\ - } } while (0) - - -typedef struct getbit_ctx_t { - // Pointer to the next unread (not in curr_byte_) byte in the stream. - RK_U8 *data_; - // Bytes left in the stream (without the curr_byte_). - RK_U32 bytes_left_; - // Contents of the current byte; first unread bit starting at position - // 8 - num_remaining_bits_in_curr_byte_ from MSB. - RK_S64 curr_byte_; - // Number of bits remaining in curr_byte_ - RK_S32 num_remaining_bits_in_curr_byte_; - // Used in emulation prevention three byte detection (see spec). - // Initially set to 0xffff to accept all initial two-byte sequences. - RK_S64 prev_two_bytes_; - // Number of emulation preventation bytes (0x000003) we met. - RK_S64 emulation_prevention_bytes_; - // file to debug - LogCtx_t *ctx; - // count PPS SPS SEI read bits - RK_S32 used_bits; - RK_U8 *buf; - RK_S32 buf_len; -} BitReadCtx_t; - - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET read_bits( BitReadCtx_t *bitctx, RK_S32 num_bits, RK_S32 *out); -MPP_RET read_one_bit(BitReadCtx_t *bitctx, RK_S32 *out); -MPP_RET read_ue(BitReadCtx_t *bitctx, RK_U32* val); -MPP_RET read_se(BitReadCtx_t *bitctx, RK_S32* val); -void set_bitread_ctx(BitReadCtx_t *bitctx, RK_U8 *data, RK_S32 size); -RET_tpye has_more_rbsp_data(BitReadCtx_t * bitctx); -void set_bitread_logctx(BitReadCtx_t *bitctx, LogCtx_t *p_ctx); - -#ifdef __cplusplus -} -#endif - - -#endif /* __H264D_BITREAD_H__ */ diff --git a/mpp/codec/dec/h264/h264d_dpb.c b/mpp/codec/dec/h264/h264d_dpb.c index f062867f2..10f1a7fdb 100644 --- a/mpp/codec/dec/h264/h264d_dpb.c +++ b/mpp/codec/dec/h264/h264d_dpb.c @@ -1,1989 +1,2103 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include - -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "h264d_scalist.h" - - -#include "h264d_dpb.h" - - - -#define MODULE_TAG "h264d_dpb" - - - -#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */ -#define INT_MAX 2147483647 /* maximum (signed) int value */ - -static RK_S32 RoundLog2(RK_S32 iValue) -{ - RK_S32 iRet = 0; - RK_S32 iValue_square = iValue * iValue; - - while ((1 << (iRet + 1)) <= iValue_square) { - ++iRet; - } - iRet = (iRet + 1) >> 1; - - return iRet; -} - -static RK_S32 getDpbSize(H264dVideoCtx_t *p_Vid, H264_SPS_t *active_sps) -{ - RK_S32 size = 0, num_views = 0; - RK_S32 pic_size = (active_sps->pic_width_in_mbs_minus1 + 1) - * (active_sps->pic_height_in_map_units_minus1 + 1) * (active_sps->frame_mbs_only_flag ? 1 : 2) * 384; - - switch (active_sps->level_idc) { - case 9: - size = 152064; - break; - case 10: - size = 152064; - break; - case 11: - if (!is_prext_profile(active_sps->profile_idc) && (active_sps->constrained_set3_flag == 1)) - size = 152064; - else - size = 345600; - break; - case 12: - size = 912384; - break; - case 13: - size = 912384; - break; - case 20: - size = 912384; - break; - case 21: - size = 1824768; - break; - case 22: - size = 3110400; - break; - case 30: - size = 3110400; - break; - case 31: - size = 6912000; - break; - case 32: - size = 7864320; - break; - case 40: - size = 12582912; - break; - case 41: - size = 12582912; - break; - case 42: - size = 13369344; - break; - case 50: - size = 42393600; - break; - case 51: - size = 70778880; - break; - case 52: - size = 70778880; - break; - default: - ASSERT(0); - break; - } - size /= pic_size; - if (p_Vid->active_mvc_sps_flag && - (p_Vid->profile_idc == MVC_HIGH || p_Vid->profile_idc == STEREO_HIGH)) { - num_views = p_Vid->active_subsps->num_views_minus1 + 1; - size = min(2 * size, max(1, RoundLog2(num_views)) * 16) / num_views; - } else { - size = min(size, 16); - } - - return size; -} - -static RK_S32 get_pic_num_x(H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1) -{ - RK_S32 currPicNum; - - if (p->structure == FRAME) - currPicNum = p->frame_num; - else - currPicNum = 2 * p->frame_num + 1; - - return currPicNum - (difference_of_pic_nums_minus1 + 1); -} - -static void unmark_for_reference(H264_FrameStore_t* fs) -{ - if (fs->is_used & 1) { - if (fs->top_field) { - fs->top_field->used_for_reference = 0; - } - } - if (fs->is_used & 2) { - if (fs->bottom_field) { - fs->bottom_field->used_for_reference = 0; - } - } - if (fs->is_used == 3) { - if (fs->top_field && fs->bottom_field) { - fs->top_field->used_for_reference = 0; - fs->bottom_field->used_for_reference = 0; - } - fs->frame->used_for_reference = 0; - } - fs->is_reference = 0; -} - -static RK_U32 is_short_term_reference(H264_FrameStore_t* fs) -{ - if (fs->is_used == 3) { // frame - if ((fs->frame->used_for_reference) && (!fs->frame->is_long_term)) { - return 1; - } - } - - if (fs->is_used & 1) { // top field - if (fs->top_field) { - if ((fs->top_field->used_for_reference) && (!fs->top_field->is_long_term)) { - return 1; - } - } - } - - if (fs->is_used & 2) { // bottom field - if (fs->bottom_field) { - if ((fs->bottom_field->used_for_reference) && (!fs->bottom_field->is_long_term)) { - return 1; - } - } - } - return 0; -} - -static RK_U32 is_long_term_reference(H264_FrameStore_t* fs) -{ - - if (fs->is_used == 3) { // frame - if ((fs->frame->used_for_reference) && (fs->frame->is_long_term)) { - return 1; - } - } - - if (fs->is_used & 1) { // top field - if (fs->top_field) { - if ((fs->top_field->used_for_reference) && (fs->top_field->is_long_term)) { - return 1; - } - } - } - - if (fs->is_used & 2) { // bottom field - if (fs->bottom_field) { - if ((fs->bottom_field->used_for_reference) && (fs->bottom_field->is_long_term)) { - return 1; - } - } - } - return 0; -} - -static void unmark_for_long_term_reference(H264_FrameStore_t* fs) -{ - if (fs->is_used & 1) { - if (fs->top_field) { - fs->top_field->used_for_reference = 0; - fs->top_field->is_long_term = 0; - } - } - if (fs->is_used & 2) { - if (fs->bottom_field) { - fs->bottom_field->used_for_reference = 0; - fs->bottom_field->is_long_term = 0; - } - } - if (fs->is_used == 3) { - if (fs->top_field && fs->bottom_field) { - fs->top_field->used_for_reference = 0; - fs->top_field->is_long_term = 0; - fs->bottom_field->used_for_reference = 0; - fs->bottom_field->is_long_term = 0; - } - fs->frame->used_for_reference = 0; - fs->frame->is_long_term = 0; - } - - fs->is_reference = 0; - fs->is_long_term = 0; -} - -static void mm_unmark_short_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1) -{ - RK_S32 picNumX = 0; - RK_U32 i = 0; - - picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p->structure == FRAME) { - if ((p_Dpb->fs_ref[i]->is_reference == 3) && (p_Dpb->fs_ref[i]->is_long_term == 0)) { - if (p_Dpb->fs_ref[i]->frame->pic_num == picNumX) { - unmark_for_reference(p_Dpb->fs_ref[i]); - return; - } - } - } else { - if ((p_Dpb->fs_ref[i]->is_reference & 1) && (!(p_Dpb->fs_ref[i]->is_long_term & 1))) { - if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) { - p_Dpb->fs_ref[i]->top_field->used_for_reference = 0; - p_Dpb->fs_ref[i]->is_reference &= 2; - if (p_Dpb->fs_ref[i]->is_used == 3) { - p_Dpb->fs_ref[i]->frame->used_for_reference = 0; - } - return; - } - } - if ((p_Dpb->fs_ref[i]->is_reference & 2) && (!(p_Dpb->fs_ref[i]->is_long_term & 2))) { - if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) { - p_Dpb->fs_ref[i]->bottom_field->used_for_reference = 0; - p_Dpb->fs_ref[i]->is_reference &= 1; - if (p_Dpb->fs_ref[i]->is_used == 3) { - p_Dpb->fs_ref[i]->frame->used_for_reference = 0; - } - return; - } - } - } - } -} - -static void mm_unmark_long_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_pic_num) -{ - RK_U32 i = 0; - - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p->structure == FRAME) { - if ((p_Dpb->fs_ltref[i]->is_reference == 3) && (p_Dpb->fs_ltref[i]->is_long_term == 3)) { - if (p_Dpb->fs_ltref[i]->frame->long_term_pic_num == long_term_pic_num) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } - } else { - if ((p_Dpb->fs_ltref[i]->is_reference & 1) && ((p_Dpb->fs_ltref[i]->is_long_term & 1))) { - if (p_Dpb->fs_ltref[i]->top_field->long_term_pic_num == long_term_pic_num) { - p_Dpb->fs_ltref[i]->top_field->used_for_reference = 0; - p_Dpb->fs_ltref[i]->top_field->is_long_term = 0; - p_Dpb->fs_ltref[i]->is_reference &= 2; - p_Dpb->fs_ltref[i]->is_long_term &= 2; - if (p_Dpb->fs_ltref[i]->is_used == 3) { - p_Dpb->fs_ltref[i]->frame->used_for_reference = 0; - p_Dpb->fs_ltref[i]->frame->is_long_term = 0; - } - return; - } - } - if ((p_Dpb->fs_ltref[i]->is_reference & 2) && ((p_Dpb->fs_ltref[i]->is_long_term & 2))) { - if (p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num == long_term_pic_num) { - p_Dpb->fs_ltref[i]->bottom_field->used_for_reference = 0; - p_Dpb->fs_ltref[i]->bottom_field->is_long_term = 0; - p_Dpb->fs_ltref[i]->is_reference &= 1; - p_Dpb->fs_ltref[i]->is_long_term &= 1; - if (p_Dpb->fs_ltref[i]->is_used == 3) { - p_Dpb->fs_ltref[i]->frame->used_for_reference = 0; - p_Dpb->fs_ltref[i]->frame->is_long_term = 0; - } - return; - } - } - } - } -} - -static void unmark_long_term_frame_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 long_term_frame_idx) -{ - RK_U32 i = 0; - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } -} - -static MPP_RET unmark_long_term_field_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, PictureStructure structure, - RK_S32 long_term_frame_idx, RK_S32 mark_current, RK_U32 curr_frame_num, RK_S32 curr_pic_num) -{ - RK_U8 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; - - VAL_CHECK(ret, structure != FRAME); - if (curr_pic_num < 0) - curr_pic_num += (2 * p_Vid->max_frame_num); - - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) { - if (structure == TOP_FIELD) { - if (p_Dpb->fs_ltref[i]->is_long_term == 3) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - if (p_Dpb->fs_ltref[i]->is_long_term == 1) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - if (mark_current) { - if (p_Dpb->last_picture) { - if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num) - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } else { - if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } - } - } - } - if (structure == BOTTOM_FIELD) { - if (p_Dpb->fs_ltref[i]->is_long_term == 3) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - if (p_Dpb->fs_ltref[i]->is_long_term == 2) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - if (mark_current) { - if (p_Dpb->last_picture) { - if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num) - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } else { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } else { - if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } - } - } - } - } - } - return ret = MPP_OK; -__FAILED: - return ret; -} - -static void mark_pic_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 long_term_frame_idx, RK_S32 picNumX) -{ - RK_U32 i = 0; - RK_S32 add_top = 0, add_bottom = 0; - LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; - - if (p->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_reference == 3) { - if ((!p_Dpb->fs_ref[i]->frame->is_long_term) && (p_Dpb->fs_ref[i]->frame->pic_num == picNumX)) { - p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_frame_idx = long_term_frame_idx; - p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; - p_Dpb->fs_ref[i]->frame->is_long_term = 1; - - if (p_Dpb->fs_ref[i]->top_field && p_Dpb->fs_ref[i]->bottom_field) { - p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx = long_term_frame_idx; - p_Dpb->fs_ref[i]->top_field->long_term_pic_num = long_term_frame_idx; - p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = long_term_frame_idx; - p_Dpb->fs_ref[i]->top_field->is_long_term = p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1; - } - p_Dpb->fs_ref[i]->is_long_term = 3; - return; - } - } - } - LogWarnning(runlog, "reference frame for long term marking not found."); - } else { - if (p->structure == TOP_FIELD) { - add_top = 1; - add_bottom = 0; - } else { - add_top = 0; - add_bottom = 1; - } - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_reference & 1) { - if ((!p_Dpb->fs_ref[i]->top_field->is_long_term) && (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX)) { - if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) { - LogWarnning(runlog, "assigning long_term_frame_idx different from other field."); - } - p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = long_term_frame_idx; - p_Dpb->fs_ref[i]->top_field->long_term_pic_num = 2 * long_term_frame_idx + add_top; - p_Dpb->fs_ref[i]->top_field->is_long_term = 1; - p_Dpb->fs_ref[i]->is_long_term |= 1; - if (p_Dpb->fs_ref[i]->is_long_term == 3) { - p_Dpb->fs_ref[i]->frame->is_long_term = 1; - p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; - } - return; - } - } - if (p_Dpb->fs_ref[i]->is_reference & 2) { - if ((!p_Dpb->fs_ref[i]->bottom_field->is_long_term) && (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX)) { - if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) { - LogWarnning(runlog, "assigning long_term_frame_idx different from other field."); - } - - p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx - = long_term_frame_idx; - p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = 2 * long_term_frame_idx + add_bottom; - p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1; - p_Dpb->fs_ref[i]->is_long_term |= 2; - if (p_Dpb->fs_ref[i]->is_long_term == 3) { - p_Dpb->fs_ref[i]->frame->is_long_term = 1; - p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; - } - return; - } - } - } - LogWarnning(runlog, "reference field for long term marking not found."); - } -} - -static MPP_RET mm_assign_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 difference_of_pic_nums_minus1, RK_S32 long_term_frame_idx) -{ - RK_S32 picNumX = 0; - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); - //!< remove frames/fields with same long_term_frame_idx - if (p->structure == FRAME) { - unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx); - } else { - PictureStructure structure = FRAME; - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_reference & 1) { - if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) { - structure = TOP_FIELD; - break; - } - } - if (p_Dpb->fs_ref[i]->is_reference & 2) { - if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) { - structure = BOTTOM_FIELD; - break; - } - } - } - VAL_CHECK(ret, structure != FRAME); - FUN_CHECK(ret = unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, structure, long_term_frame_idx, 0, 0, picNumX)); - } - mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX); - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static void mm_update_max_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 max_long_term_frame_idx_plus1) -{ - RK_U32 i = 0; - - p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1; - - // check for invalid frames - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->long_term_frame_idx > p_Dpb->max_long_term_pic_idx) { - unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); - } - } -} - -static void mm_unmark_all_short_term_for_reference(H264_DpbBuf_t *p_Dpb) -{ - RK_U32 i = 0; - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - unmark_for_reference(p_Dpb->fs_ref[i]); - } - update_ref_list(p_Dpb); -} - -static void mm_unmark_all_long_term_for_reference(H264_DpbBuf_t *p_Dpb) -{ - mm_update_max_long_term_frame_idx(p_Dpb, 0); -} - -static void mm_mark_current_picture_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_frame_idx) -{ - // remove long term pictures with same long_term_frame_idx - if (p->structure == FRAME) { - unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx); - } else { - unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, p->structure, long_term_frame_idx, 1, p->pic_num, 0); - } - - p->is_long_term = 1; - p->long_term_frame_idx = long_term_frame_idx; -} - -static void sliding_window_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p) -{ - RK_U32 i = 0; - - // if this is a reference pic with sliding window, unmark first ref frame - if (p_Dpb->ref_frames_in_buffer == max(1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer) { - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term))) { - unmark_for_reference(p_Dpb->fs[i]); - update_ref_list(p_Dpb); - break; - } - } - } - (void)p; -} - -static void check_num_ref(H264_DpbBuf_t *p_Dpb) -{ - LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; - - if ((RK_S32)(p_Dpb->ltref_frames_in_buffer + p_Dpb->ref_frames_in_buffer) > max(1, p_Dpb->num_ref_frames)) { - if ((RK_S32)(p_Dpb->ltref_frames_in_buffer + p_Dpb->ref_frames_in_buffer) > max(1, p_Dpb->num_ref_frames)) { - sliding_window_memory_management(p_Dpb, NULL); - LogWarnning(runlog, "Max number of reference frames exceeded"); - } - } -} - -static RK_U32 is_used_for_reference(H264_FrameStore_t* fs) -{ - RK_U8 is_used_flag = 0; - - if (fs->is_reference) { - return is_used_flag = 1; - } - - if (fs->is_used == 3) { // frame - if (fs->frame->used_for_reference) { - return is_used_flag = 1; - } - } - - if (fs->is_used & 1) { // top field - if (fs->top_field) { - if (fs->top_field->used_for_reference) { - return is_used_flag = 1; - } - } - } - - if (fs->is_used & 2) { // bottom field - if (fs->bottom_field) { - if (fs->bottom_field->used_for_reference) { - return is_used_flag = 1; - } - } - } - return is_used_flag = 0; -} - -static void free_dpb_memory_index(H264_DpbMark_t *p, RK_S32 structure, RK_U8 layer_id) -{ - if (structure == FRAME) { - p->top_used = (p->top_used > 0) ? (p->top_used - 1) : 0; - p->bot_used = (p->bot_used > 0) ? (p->bot_used - 1) : 0; - } else if (structure == TOP_FIELD) { - p->top_used = (p->top_used > 0) ? (p->top_used - 1) : 0; - } else if (structure == BOTTOM_FIELD) { - p->bot_used = (p->bot_used > 0) ? (p->bot_used - 1) : 0; - } - (void)layer_id; -} - -static MPP_RET remove_frame_from_dpb(H264_DpbBuf_t *p_Dpb, RK_S32 pos) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264_FrameStore_t* fs = p_Dpb->fs[pos]; - H264_FrameStore_t* tmp = NULL; - LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; - - switch (fs->is_used) { - case 3: - if (fs->frame) free_storable_picture(fs->frame); - if (fs->top_field) free_storable_picture(fs->top_field); - if (fs->bottom_field) free_storable_picture(fs->bottom_field); - fs->frame = NULL; - fs->top_field = NULL; - fs->bottom_field = NULL; - break; - case 2: - if (fs->bottom_field) free_storable_picture(fs->bottom_field); - fs->bottom_field = NULL; - break; - case 1: - if (fs->top_field) free_storable_picture(fs->top_field); - fs->top_field = NULL; - break; - case 0: - break; - default: - LogError(runlog, "invalid frame store type."); - goto __FAILED; - } - fs->is_used = 0; - fs->is_long_term = 0; - fs->is_reference = 0; - fs->is_orig_reference = 0; - - // move empty framestore to end of buffer - tmp = p_Dpb->fs[pos]; - - for (i = pos; i < p_Dpb->used_size - 1; i++) { - p_Dpb->fs[i] = p_Dpb->fs[i + 1]; - } - p_Dpb->fs[p_Dpb->used_size - 1] = tmp; - p_Dpb->used_size--; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret = MPP_NOK; -} - -static MPP_RET remove_unused_frame_from_dpb(H264_DpbBuf_t *p_Dpb) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - // check for frames that were already output and no longer used for reference - for (i = 0; i < p_Dpb->used_size; i++) { - if (p_Dpb->fs[i]->is_output && (!is_used_for_reference(p_Dpb->fs[i]))) { - FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, i)); - return MPP_OK; - } - } -__FAILED: - return ret; -} - -static MPP_RET get_smallest_poc(H264_DpbBuf_t *p_Dpb, RK_S32 *poc, RK_S32 *pos) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - VAL_CHECK(ret, p_Dpb->used_size > 0); //!< "Cannot determine smallest POC, DPB empty." - *pos = -1; - *poc = INT_MAX; - for (i = 0; i < p_Dpb->used_size; i++) { - if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) { - *poc = p_Dpb->fs[i]->poc; - *pos = i; - } - } - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static H264_FrameStore_t *alloc_frame_store() -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_FrameStore_t *f = mpp_calloc(H264_FrameStore_t, 1); - MEM_CHECK(ret, f); - - f->is_used = 0; - f->is_reference = 0; - f->is_long_term = 0; - f->is_orig_reference = 0; - f->is_output = 0; - - f->frame = NULL; - f->top_field = NULL; - f->bottom_field = NULL; - - return f; -__FAILED: - (void)ret; - return NULL; -} - -static MPP_RET dpb_combine_field_yuv(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - if (!fs->frame) { - fs->frame = alloc_storable_picture(p_Vid, FRAME); - MEM_CHECK(ret, fs->frame); - ASSERT(fs->top_field->colmv_no_used_flag == fs->bottom_field->colmv_no_used_flag); - fs->frame->colmv_no_used_flag = fs->top_field->colmv_no_used_flag; - if (combine_flag) { - ASSERT(fs->top_field->mem_mark->index = fs->bottom_field->mem_mark->index); - fs->frame->mem_malloc_type = fs->top_field->mem_malloc_type; - fs->frame->mem_mark = fs->top_field->mem_mark; - } else if (fs->is_used == 0x1) { // unpaired, have top - ASSERT(fs->bottom_field->mem_malloc_type == Mem_UnPaired); - fs->frame->mem_mark = fs->top_field->mem_mark; - } else if (fs->is_used == 0x02) { // unpaired, have bottom - ASSERT(fs->top_field->mem_malloc_type == Mem_UnPaired); - fs->frame->mem_mark = fs->bottom_field->mem_mark; - } else { - ASSERT(fs->is_used == 0x03); - } - } - fs->poc = fs->frame->poc = fs->frame->frame_poc = min(fs->top_field->poc, fs->bottom_field->poc); - fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; - fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; - fs->top_field->bottom_poc = fs->frame->bottom_poc = fs->bottom_field->poc; - fs->frame->used_for_reference = (fs->top_field->used_for_reference && fs->bottom_field->used_for_reference); - fs->frame->is_long_term = (fs->top_field->is_long_term && fs->bottom_field->is_long_term); - if (fs->frame->is_long_term) { - fs->frame->long_term_frame_idx = fs->long_term_frame_idx; - } - fs->frame->top_field = fs->top_field; - fs->frame->bottom_field = fs->bottom_field; - fs->frame->frame = fs->frame; - fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc; - - fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag; - if (fs->frame->frame_cropping_flag) { - fs->frame->frame_crop_top_offset = fs->top_field->frame_crop_top_offset; - fs->frame->frame_crop_bottom_offset = fs->top_field->frame_crop_bottom_offset; - fs->frame->frame_crop_left_offset = fs->top_field->frame_crop_left_offset; - fs->frame->frame_crop_right_offset = fs->top_field->frame_crop_right_offset; - } - fs->top_field->frame = fs->bottom_field->frame = fs->frame; - fs->top_field->top_field = fs->top_field; - fs->top_field->bottom_field = fs->bottom_field; - fs->bottom_field->top_field = fs->top_field; - fs->bottom_field->bottom_field = fs->bottom_field; - - fs->frame->is_mmco_5 = fs->top_field->is_mmco_5 || fs->bottom_field->is_mmco_5; - fs->frame->poc_mmco5 = min(fs->top_field->top_poc_mmco5, fs->bottom_field->bot_poc_mmco5); - fs->frame->top_poc_mmco5 = fs->top_field->top_poc_mmco5; - fs->frame->bot_poc_mmco5 = fs->top_field->bot_poc_mmco5; - - return ret = MPP_OK; -__FAILED: - return ret ; -} - -static void write_picture(H264_StorePic_t *p, H264dVideoCtx_t *p_Vid) -{ - (void)p; - (void)p_Vid; -} - -static MPP_RET write_unpaired_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_StorePic_t *p = NULL; - - VAL_CHECK(ret, fs->is_used < 3); - if (fs->is_used & 0x01) { // we have a top field, construct an empty bottom field - p = fs->top_field; - fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD); - MEM_CHECK(ret, fs->bottom_field); - fs->bottom_field->mem_malloc_type = Mem_UnPaired; - fs->bottom_field->chroma_format_idc = p->chroma_format_idc; - FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0)); - fs->frame->view_id = fs->view_id; - write_picture(fs->frame, p_Vid); - } - - if (fs->is_used & 0x02) { // we have a bottom field, construct an empty top field - p = fs->bottom_field; - fs->top_field = alloc_storable_picture(p_Vid, TOP_FIELD); - MEM_CHECK(ret, fs->top_field); - fs->top_field->mem_malloc_type = Mem_UnPaired; - fs->top_field->chroma_format_idc = p->chroma_format_idc; - fs->top_field->frame_cropping_flag = fs->bottom_field->frame_cropping_flag; - if (fs->top_field->frame_cropping_flag) { - fs->top_field->frame_crop_top_offset = fs->bottom_field->frame_crop_top_offset; - fs->top_field->frame_crop_bottom_offset = fs->bottom_field->frame_crop_bottom_offset; - fs->top_field->frame_crop_left_offset = fs->bottom_field->frame_crop_left_offset; - fs->top_field->frame_crop_right_offset = fs->bottom_field->frame_crop_right_offset; - } - FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0)); - fs->frame->view_id = fs->view_id; - write_picture(fs->frame, p_Vid); - } - fs->is_used = 3; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET flush_direct_output(H264dVideoCtx_t *p_Vid) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - FUN_CHECK(ret = write_unpaired_field(p_Vid, &p_Vid->out_buffer)); - free_storable_picture(p_Vid->out_buffer.frame); - p_Vid->out_buffer.frame = NULL; - free_storable_picture(p_Vid->out_buffer.top_field); - p_Vid->out_buffer.top_field = NULL; - free_storable_picture(p_Vid->out_buffer.bottom_field); - p_Vid->out_buffer.bottom_field = NULL; - p_Vid->out_buffer.is_used = 0; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET write_stored_frame(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - //!< make sure no direct output field is pending - FUN_CHECK(ret = flush_direct_output(p_Vid)); - - if (fs->is_used < 3) { - FUN_CHECK(ret = write_unpaired_field(p_Vid, fs)); - } else { - write_picture(fs->frame, p_Vid); - } - - fs->is_output = 1; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET output_one_frame_from_dpb(H264_DpbBuf_t *p_Dpb) -{ - RK_S32 poc = 0, pos = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; - - //!< diagnostics - VAL_CHECK(ret, p_Dpb->used_size > 0); //!< Cannot output frame, DPB empty - //!< find smallest POC - FUN_CHECK(ret = get_smallest_poc(p_Dpb, &poc, &pos)); - VAL_CHECK(ret, pos != -1); - //!< JVT-P072 ends - FUN_CHECK(ret = write_stored_frame(p_Vid, p_Dpb->fs[pos])); - //!< free frame store and move empty store to end of buffer - if (!is_used_for_reference(p_Dpb->fs[pos])) { - FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, pos)); - } - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET adaptive_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) -{ - H264_DRPM_t *tmp_drpm = NULL; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; - - p_Vid->last_has_mmco_5 = 0; - VAL_CHECK(ret, !p->idr_flag && p->adaptive_ref_pic_buffering_flag); - while (p->dec_ref_pic_marking_buffer) { - tmp_drpm = p->dec_ref_pic_marking_buffer; - switch (tmp_drpm->memory_management_control_operation) { - case 0: - VAL_CHECK(ret, tmp_drpm->Next == NULL); - break; - case 1: - mm_unmark_short_term_for_reference(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1); - update_ref_list(p_Dpb); - break; - case 2: - mm_unmark_long_term_for_reference(p_Dpb, p, tmp_drpm->long_term_pic_num); - update_ltref_list(p_Dpb); - break; - case 3: - mm_assign_long_term_frame_idx(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1, tmp_drpm->long_term_frame_idx); - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - break; - case 4: - mm_update_max_long_term_frame_idx(p_Dpb, tmp_drpm->max_long_term_frame_idx_plus1); - update_ltref_list(p_Dpb); - break; - case 5: - mm_unmark_all_short_term_for_reference(p_Dpb); - mm_unmark_all_long_term_for_reference(p_Dpb); - p_Vid->last_has_mmco_5 = 1; - break; - case 6: - mm_mark_current_picture_long_term(p_Dpb, p, tmp_drpm->long_term_frame_idx); - check_num_ref(p_Dpb); - break; - default: - ret = MPP_NOK; - goto __FAILED; - } - p->dec_ref_pic_marking_buffer = tmp_drpm->Next; - mpp_free(tmp_drpm); - } - if (p_Vid->last_has_mmco_5) { //!< similar IDR frame - p->pic_num = p->frame_num = 0; - switch (p->structure) { - case TOP_FIELD: - p->is_mmco_5 = 1; - p->top_poc_mmco5 = p->top_poc; - p->poc = p->top_poc = 0; - break; - - case BOTTOM_FIELD: - p->is_mmco_5 = 1; - p->bot_poc_mmco5 = p->bottom_poc; - p->poc = p->bottom_poc = 0; - break; - - case FRAME: - p->is_mmco_5 = 1; - p->top_poc_mmco5 = p->top_poc; - p->bot_poc_mmco5 = p->bottom_poc; - p->poc_mmco5 = min(p->top_poc, p->bottom_poc); - p->top_poc -= p->poc; - p->bottom_poc -= p->poc; - - p->poc = min(p->top_poc, p->bottom_poc); - p->frame_poc = p->poc; - break; - - } - if (p->layer_id == 0) { - FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0])); - } else { - FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1])); - } - - } - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET dpb_split_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_StorePic_t *frame = fs->frame; - H264_StorePic_t *fs_top = NULL, *fs_btm = NULL; - - fs->poc = frame->poc; - if (!frame->frame_mbs_only_flag) { - fs_top = fs->top_field = alloc_storable_picture(p_Vid, TOP_FIELD); - fs_btm = fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD); - MEM_CHECK(ret, fs_top && fs_btm); - fs_top->colmv_no_used_flag = frame->colmv_no_used_flag; - fs_btm->colmv_no_used_flag = frame->colmv_no_used_flag; - - if (frame->mem_malloc_type == Mem_Malloc || frame->mem_malloc_type == Mem_Clone) { - fs_top->mem_mark = frame->mem_mark; - fs_btm->mem_mark = frame->mem_mark; - fs_top->mem_malloc_type = frame->mem_malloc_type; - fs_btm->mem_malloc_type = frame->mem_malloc_type; - frame->mem_mark->bot_used += 1; // picture memory add 1 - frame->mem_mark->top_used += 1; - } - fs_top->poc = frame->top_poc; - fs_btm->poc = frame->bottom_poc; - fs_top->layer_id = frame->layer_id; - fs_btm->layer_id = frame->layer_id; - - fs_top->view_id = frame->view_id; - fs_btm->view_id = frame->view_id; - fs_top->frame_poc = frame->frame_poc; - - fs_top->bottom_poc = fs_btm->bottom_poc = frame->bottom_poc; - fs_top->top_poc = fs_btm->top_poc = frame->top_poc; - fs_btm->frame_poc = frame->frame_poc; - - fs_top->used_for_reference = fs_btm->used_for_reference = frame->used_for_reference; - fs_top->is_long_term = fs_btm->is_long_term = frame->is_long_term; - fs->long_term_frame_idx = fs_top->long_term_frame_idx = fs_btm->long_term_frame_idx = frame->long_term_frame_idx; - fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag = frame->mb_aff_frame_flag; - - frame->top_field = fs_top; - frame->bottom_field = fs_btm; - frame->frame = frame; - fs_top->bottom_field = fs_btm; - fs_top->frame = frame; - fs_top->top_field = fs_top; - fs_btm->top_field = fs_top; - fs_btm->frame = frame; - fs_btm->bottom_field = fs_btm; - - fs_top->is_mmco_5 = frame->is_mmco_5; - fs_btm->is_mmco_5 = frame->is_mmco_5; - fs_top->poc_mmco5 = frame->poc_mmco5; - fs_btm->poc_mmco5 = frame->poc_mmco5; - fs_top->top_poc_mmco5 = frame->top_poc_mmco5; - fs_btm->bot_poc_mmco5 = frame->bot_poc_mmco5; - - fs_top->view_id = fs_btm->view_id = fs->view_id; - fs_top->inter_view_flag = fs->inter_view_flag[0]; - fs_btm->inter_view_flag = fs->inter_view_flag[1]; - - fs_top->chroma_format_idc = fs_btm->chroma_format_idc = frame->chroma_format_idc; - fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType; - } else { - fs->top_field = NULL; - fs->bottom_field = NULL; - frame->top_field = NULL; - frame->bottom_field = NULL; - frame->frame = frame; - } - return ret = MPP_OK; -__FAILED: - mpp_free(fs->top_field); - mpp_free(fs->bottom_field); - ASSERT(0); - - return ret; -} - -static MPP_RET dpb_combine_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, combine_flag)); - fs->frame->layer_id = fs->layer_id; - fs->frame->view_id = fs->view_id; - fs->frame->iCodingType = fs->top_field->iCodingType; //FIELD_CODING; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET direct_output(H264dVideoCtx_t *p_Vid, H264_StorePic_t *p) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - if (p->structure == FRAME) { - //!< we have a frame (or complementary field pair), so output it directly - FUN_CHECK(ret = flush_direct_output(p_Vid)); - write_picture(p, p_Vid); - free_storable_picture(p); - goto __RETURN; - } - - if (p->structure == TOP_FIELD) { - if (p_Vid->out_buffer.is_used & 1) { - FUN_CHECK(ret = flush_direct_output(p_Vid)); - } - p_Vid->out_buffer.top_field = p; - p_Vid->out_buffer.is_used |= 1; - } - - if (p->structure == BOTTOM_FIELD) { - if (p_Vid->out_buffer.is_used & 2) { - FUN_CHECK(ret = flush_direct_output(p_Vid)); - } - p_Vid->out_buffer.bottom_field = p; - p_Vid->out_buffer.is_used |= 2; - } - - if (p_Vid->out_buffer.is_used == 3) { - //!< we have both fields, so output them - FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, &p_Vid->out_buffer, 0)); - p_Vid->out_buffer.frame->view_id = p_Vid->out_buffer.view_id; - write_picture(p_Vid->out_buffer.frame, p_Vid); - free_storable_picture(p_Vid->out_buffer.frame); - p_Vid->out_buffer.frame = NULL; - free_storable_picture(p_Vid->out_buffer.top_field); - p_Vid->out_buffer.top_field = NULL; - free_storable_picture(p_Vid->out_buffer.bottom_field); - p_Vid->out_buffer.bottom_field = NULL; - p_Vid->out_buffer.is_used = 0; - } - -__RETURN: - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET store_picture_in_dpb(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) -{ - RK_S32 poc = 0, pos = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; - - VAL_CHECK(ret, NULL != p); //!< if frame, check for new store - p_Vid->last_has_mmco_5 = 0; - p_Vid->last_pic_bottom_field = p->structure == BOTTOM_FIELD; - if (p->idr_flag) { - FUN_CHECK(ret = idr_memory_management(p_Dpb, p)); - } else { //!< adaptive memory management - if (p->used_for_reference && p->adaptive_ref_pic_buffering_flag) { - FUN_CHECK(ret = adaptive_memory_management(p_Dpb, p)); - } - } - if (get_filed_dpb_combine_flag(p_Dpb, p)) { - FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->last_picture, p, 1)); //!< field_dpb_combine - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - p_Dpb->last_picture = NULL; - goto __RETURN; - } - //!< sliding window, if necessary - if (!p->idr_flag && p->used_for_reference && !p->adaptive_ref_pic_buffering_flag) { - ASSERT(!p->idr_flag); - sliding_window_memory_management(p_Dpb, p); - p->is_long_term = 0; - } - //!< first try to remove unused frames - if (p_Dpb->used_size == p_Dpb->size) { - remove_unused_frame_from_dpb(p_Dpb); - } - //!< then output frames until one can be removed - while (p_Dpb->used_size == p_Dpb->size) { - //!< non-reference frames may be output directly - FUN_CHECK(ret = get_smallest_poc(p_Dpb, &poc, &pos)); - if (!p->used_for_reference) { - if ((-1 == pos) || (p->poc < poc)) { - FUN_CHECK(ret = direct_output(p_Vid, p)); - goto __RETURN; - } - } - //!< flush a frame - if ((-1 == pos) || (p->poc < poc)) { - FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, 0)); - } - FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb)); - } - - //!< store at end of buffer - FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->fs[p_Dpb->used_size], p, 0)); - if (p->structure != FRAME) { - p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size]; - } else { - p_Dpb->last_picture = NULL; - } - p_Dpb->used_size++; - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - -__RETURN: - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -/*! -*********************************************************************** -* \brief -* free frame store picture -*********************************************************************** -*/ -//extern "C" -void free_frame_store(H264_FrameStore_t* f) -{ - if (f) { - if (f->frame) { - free_storable_picture(f->frame); - f->frame = NULL; - } - if (f->top_field) { - free_storable_picture(f->top_field); - f->top_field = NULL; - } - if (f->bottom_field) { - free_storable_picture(f->bottom_field); - f->bottom_field = NULL; - } - mpp_free(f); - } -} - -/*! -*********************************************************************** -* \brief -* free dpb -*********************************************************************** -*/ -//extern "C" -void free_dpb(H264_DpbBuf_t *p_Dpb) -{ - RK_U32 i = 0; - H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; - - if (p_Dpb->fs) { - for (i = 0; i < p_Dpb->size; i++) { - free_frame_store(p_Dpb->fs[i]); - } - mpp_free(p_Dpb->fs); - } - mpp_free(p_Dpb->fs_ref); - mpp_free(p_Dpb->fs_ltref); - if (p_Dpb->fs_ilref) { - for (i = 0; i < 1; i++) { - free_frame_store(p_Dpb->fs_ilref[i]); - } - mpp_free(p_Dpb->fs_ilref); - } - p_Dpb->last_output_view_id = -1; - p_Dpb->last_output_poc = INT_MIN; - p_Dpb->init_done = 0; - if (p_Vid->no_reference_picture) { - free_storable_picture(p_Vid->no_reference_picture); - p_Vid->no_reference_picture = NULL; - } -} - -/*! -*********************************************************************** -* \brief -* alloc one picture -*********************************************************************** -*/ -//extern "C" -void update_ref_list(H264_DpbBuf_t *p_Dpb) -{ - RK_U8 i = 0, j = 0; - for (i = 0, j = 0; i < p_Dpb->used_size; i++) { - if (is_short_term_reference(p_Dpb->fs[i])) { - p_Dpb->fs_ref[j++] = p_Dpb->fs[i]; - } - } - - p_Dpb->ref_frames_in_buffer = j; - - while (j < p_Dpb->size) { - p_Dpb->fs_ref[j++] = NULL; - } -} -/*! -*********************************************************************** -* \brief -* alloc one picture -*********************************************************************** -*/ -//extern "C" -void update_ltref_list(H264_DpbBuf_t *p_Dpb) -{ - RK_U8 i = 0, j = 0; - for (i = 0, j = 0; i < p_Dpb->used_size; i++) { - if (is_long_term_reference(p_Dpb->fs[i])) { - p_Dpb->fs_ltref[j++] = p_Dpb->fs[i]; - } - } - - p_Dpb->ltref_frames_in_buffer = j; - - while (j < p_Dpb->size) { - p_Dpb->fs_ltref[j++] = NULL; - } -} - -/*! -*********************************************************************** -* \brief -* alloc one picture -*********************************************************************** -*/ -//extern "C" -MPP_RET idr_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - if (p->no_output_of_prior_pics_flag) { - //!< free all stored pictures - for (i = 0; i < p_Dpb->used_size; i++) { - //!< reset all reference settings - free_frame_store(p_Dpb->fs[i]); - p_Dpb->fs[i] = alloc_frame_store(); - MEM_CHECK(ret, p_Dpb->fs[i]); - } - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - p_Dpb->fs_ref[i] = NULL; - } - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - p_Dpb->fs_ltref[i] = NULL; - } - p_Dpb->used_size = 0; - } else { - FUN_CHECK(ret = flush_dpb(p_Dpb)); - } - p_Dpb->last_picture = NULL; - - update_ref_list(p_Dpb); - update_ltref_list(p_Dpb); - p_Dpb->last_output_poc = INT_MIN; - - if (p->long_term_reference_flag) { - p_Dpb->max_long_term_pic_idx = 0; - p->is_long_term = 1; - p->long_term_frame_idx = 0; - } else { - p_Dpb->max_long_term_pic_idx = -1; - p->is_long_term = 0; - } - p_Dpb->last_output_view_id = -1; - - return ret = MPP_OK; - -__FAILED: - for (i = 0; i < p_Dpb->used_size; i++) { // when error and free malloc buf - free_frame_store(p_Dpb->fs[i]); - } - ASSERT(0); - return ret; -} - - -/*! -*********************************************************************** -* \brief -* alloc one picture -*********************************************************************** -*/ -//extern "C" -MPP_RET insert_picture_in_dpb(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, H264_StorePic_t* p, RK_U8 combine_flag) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - ASSERT(p != NULL); - ASSERT(fs != NULL); - switch (p->structure) { - case FRAME: - fs->frame = p; - fs->is_used = 3; - if (p->used_for_reference) { - fs->is_reference = 3; - fs->is_orig_reference = 3; - if (p->is_long_term) { - fs->is_long_term = 3; - fs->long_term_frame_idx = p->long_term_frame_idx; - } - } - fs->layer_id = p->layer_id; - fs->view_id = p->view_id; - fs->inter_view_flag[0] = fs->inter_view_flag[1] = p->inter_view_flag; - fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] = p->anchor_pic_flag; - FUN_CHECK(ret = dpb_split_field(p_Vid, fs)); - break; - case TOP_FIELD: - fs->top_field = p; - fs->is_used |= 1; - fs->layer_id = p->layer_id; - fs->view_id = p->view_id; - fs->inter_view_flag[0] = p->inter_view_flag; - fs->anchor_pic_flag[0] = p->anchor_pic_flag; - if (p->used_for_reference) { - fs->is_reference |= 1; - fs->is_orig_reference |= 1; - if (p->is_long_term) { - fs->is_long_term |= 1; - fs->long_term_frame_idx = p->long_term_frame_idx; - } - } - if (fs->is_used == 3) { - FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag)); - } else { - fs->poc = p->poc; - } - break; - case BOTTOM_FIELD: - fs->bottom_field = p; - fs->is_used |= 2; - fs->layer_id = p->layer_id; - fs->view_id = p->view_id; - fs->inter_view_flag[1] = p->inter_view_flag; - fs->anchor_pic_flag[1] = p->anchor_pic_flag; - if (p->used_for_reference) { - fs->is_reference |= 2; - fs->is_orig_reference |= 2; - if (p->is_long_term) { - fs->is_long_term |= 2; - fs->long_term_frame_idx = p->long_term_frame_idx; - } - } - if (fs->is_used == 3) { - FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag)); - } else { - fs->poc = p->poc; - } - break; - } - fs->frame_num = p->pic_num; - fs->is_output = p->is_output; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - - -/*! -*********************************************************************** -* \brief -* alloc one picture -*********************************************************************** -*/ -//extern "C" -void free_storable_picture(H264_StorePic_t *p) -{ - if (p) { - if (p->mem_malloc_type == Mem_Malloc || p->mem_malloc_type == Mem_Clone) { - free_dpb_memory_index(p->mem_mark, p->structure, p->layer_id); - } - - mpp_free(p); - } -} - -/*! -*********************************************************************** -* \brief -* alloc one picture -*********************************************************************** -*/ -//extern "C" -H264_StorePic_t *alloc_storable_picture(H264dVideoCtx_t *p_Vid, RK_S32 structure) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_StorePic_t *s = mpp_calloc(H264_StorePic_t, 1); - - MEM_CHECK(ret, s); - s->view_id = -1; - s->structure = structure; - (void)p_Vid; - - return s; -__FAILED: - (void)ret; - return NULL; -} - -/*! -*********************************************************************** -* \brief -* alloc one picture -*********************************************************************** -*/ -//extern "C" - -RK_U32 get_filed_dpb_combine_flag(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) -{ - RK_U32 combine_flag = 0; - - if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) { - // check for frame store with same pic_number - if (p_Dpb->last_picture) { - if ((RK_S32)p_Dpb->last_picture->frame_num == p->pic_num) { - if (((p->structure == TOP_FIELD) && (p_Dpb->last_picture->is_used == 2)) || ((p->structure == BOTTOM_FIELD) && (p_Dpb->last_picture->is_used == 1))) { - if ((p->used_for_reference && (p_Dpb->last_picture->is_orig_reference != 0)) || - (!p->used_for_reference && (p_Dpb->last_picture->is_orig_reference == 0))) { - return combine_flag = 1; - } - } - } - } - } - - return combine_flag = 0; -} - -/*! -*********************************************************************** -* \brief -* init dpb -*********************************************************************** -*/ -//extern "C" -MPP_RET init_dpb(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, RK_S32 type) // type=1 AVC type=2 MVC -{ - RK_U32 i = 0; - RK_S32 PicSizeInMbs = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264_SPS_t *active_sps = p_Vid->active_sps; - LogCtx_t *runlog = p_Dpb->p_Vid->p_Dec->logctx.parr[RUN_PARSE]; - - p_Dpb->p_Vid = p_Vid; - if (p_Dpb->init_done) { - free_dpb(p_Dpb); - } - p_Dpb->size = getDpbSize(p_Vid, active_sps) + (type == 2 ? 0 : 1); - p_Dpb->num_ref_frames = active_sps->max_num_ref_frames; - if (active_sps->max_dec_frame_buffering < active_sps->max_num_ref_frames) { - LogError(runlog, "DPB size at specified level is smaller than reference frames"); - goto __FAILED; - } - p_Dpb->used_size = 0; - p_Dpb->last_picture = NULL; - p_Dpb->ref_frames_in_buffer = 0; - p_Dpb->ltref_frames_in_buffer = 0; - //-------- - p_Dpb->fs = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - p_Dpb->fs_ref = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - p_Dpb->fs_ltref = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - p_Dpb->fs_ilref = mpp_calloc(H264_FrameStore_t*, 1); - MEM_CHECK(ret, p_Dpb->fs && p_Dpb->fs_ref && p_Dpb->fs_ltref && p_Dpb->fs_ilref); - for (i = 0; i < p_Dpb->size; i++) { - p_Dpb->fs[i] = alloc_frame_store(); - MEM_CHECK(ret, p_Dpb->fs[i]); - p_Dpb->fs_ref[i] = NULL; - p_Dpb->fs_ltref[i] = NULL; - p_Dpb->fs[i]->layer_id = MVC_INIT_VIEW_ID; - p_Dpb->fs[i]->view_id = MVC_INIT_VIEW_ID; - p_Dpb->fs[i]->inter_view_flag[0] = p_Dpb->fs[i]->inter_view_flag[1] = 0; - p_Dpb->fs[i]->anchor_pic_flag[0] = p_Dpb->fs[i]->anchor_pic_flag[1] = 0; - } - if (type == 2) { - p_Dpb->fs_ilref[0] = alloc_frame_store(); - MEM_CHECK(ret, p_Dpb->fs_ilref[0]); - //!< These may need some cleanups - p_Dpb->fs_ilref[0]->view_id = MVC_INIT_VIEW_ID; - p_Dpb->fs_ilref[0]->inter_view_flag[0] = p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0; - p_Dpb->fs_ilref[0]->anchor_pic_flag[0] = p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0; - //!< given that this is in a different buffer, do we even need proc_flag anymore? - } else { - p_Dpb->fs_ilref[0] = NULL; - } - //!< allocate a dummy storable picture - if (!p_Vid->no_reference_picture) { - PicSizeInMbs = (p_Vid->active_sps->pic_height_in_map_units_minus1 + 1) * (p_Vid->active_sps->pic_width_in_mbs_minus1 + 1); - p_Vid->no_reference_picture = alloc_storable_picture(p_Vid, FRAME); - MEM_CHECK(ret, p_Vid->no_reference_picture); - p_Vid->no_reference_picture->top_field = p_Vid->no_reference_picture; - p_Vid->no_reference_picture->bottom_field = p_Vid->no_reference_picture; - p_Vid->no_reference_picture->frame = p_Vid->no_reference_picture; - } - p_Dpb->last_output_poc = INT_MIN; - p_Dpb->last_output_view_id = -1; - p_Vid->last_has_mmco_5 = 0; - p_Dpb->init_done = 1; - (void)PicSizeInMbs; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} -/*! -*********************************************************************** -* \brief -* flush dpb -*********************************************************************** -*/ -//extern "C" - -MPP_RET flush_dpb(H264_DpbBuf_t *p_Dpb) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - //!< diagnostics - if (!p_Dpb->init_done) { - goto __RETURN; - } - //!< mark all frames unused - for (i = 0; i < p_Dpb->used_size; i++) { - VAL_CHECK(ret, p_Dpb->fs[i]->layer_id == p_Dpb->layer_id); - unmark_for_reference(p_Dpb->fs[i]); - } - while (!remove_unused_frame_from_dpb(p_Dpb)); - //!< output frames in POC order - while (p_Dpb->used_size) { - FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb)); - } - p_Dpb->last_output_poc = INT_MIN; -__RETURN: - return ret = MPP_OK; -__FAILED: - return ret; -} - -/*! -*********************************************************************** -* \brief -* parse sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET exit_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t **dec_picture) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - //!< return if the last picture has already been finished - if (!(*dec_picture) || !p_Vid->exit_picture_flag - || !p_Vid->have_outpicture_flag || !p_Vid->iNumOfSlicesDecoded) { - goto __RETURN; - } - -#if 0 - set_curframe_poc((*dec_picture), &p_Vid->p_Dec->regs); -#endif - FUN_CHECK(ret = store_picture_in_dpb(p_Vid->p_Dpb_layer[(*dec_picture)->layer_id], *dec_picture)); - mpp_log("--rkv_h264_decoder ending, g_framecnt=%d \n", p_Vid->g_framecnt++); -#if 0 - update_all_logctx_framenum(&p_Vid->p_Dec->logctx, p_Vid->g_framecnt); -#endif - *dec_picture = NULL; - -__RETURN: - return ret = MPP_OK; - -__FAILED: - ASSERT(0); - return ret; -} - -/*! -*********************************************************************** -* \brief -* prepare dpb info for regsiter syntax -*********************************************************************** -*/ -//extern "C" -MPP_RET prepare_init_dpb_info(H264_SLICE_t *currSlice) -{ - void *picbuf = NULL; - RK_U32 i = 0, j = 0, k = 0; - RK_S32 poc = 0, TOP_POC = 0, BOT_POC = 0; - RK_S32 layer_id = 0, voidx = 0, is_used = 0; - H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; - H264_DecCtx_t *p_Dec = currSlice->p_Dec; - - memset(p_Dec->dpb_info, 0, DPB_INFO_SIZE * sizeof(H264_DpbInfo_t)); - memset(p_Dec->refpic_info_p, 0, REFPIC_INFO_SIZE * sizeof(H264_RefPicInfo_t)); - memset(p_Dec->refpic_info[0], 0, REFPIC_INFO_SIZE * sizeof(H264_RefPicInfo_t)); - memset(p_Dec->refpic_info[1], 0, REFPIC_INFO_SIZE * sizeof(H264_RefPicInfo_t)); - - if (currSlice->idr_flag && !currSlice->layer_id) { // idr_flag==1 && layer_id==0 - goto __RETURN; - } - //!<---- reference - for (i = 0, j = 0; j < p_Dpb->ref_frames_in_buffer; i++, j++) { - if (p_Dpb->fs_ref[j]->is_used == 3) { - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ref[j]->frame; - if (p_Dpb->fs_ref[j]->frame->iCodingType == FIELD_CODING) { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->top_field->poc; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->bottom_field->poc; - } else { - if (p_Dpb->fs_ref[j]->frame->frame_poc != p_Dpb->fs_ref[j]->frame->poc) { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->frame->top_poc - p_Dpb->fs_ref[j]->frame->frame_poc; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->frame->bottom_poc - p_Dpb->fs_ref[j]->frame->frame_poc; - } else { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->frame->top_poc; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->frame->bottom_poc; - } - } - p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ref[j]->frame->iCodingType == FIELD_CODING; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ref[j]->frame->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ref[j]->frame->colmv_no_used_flag ? 0 : 1); - } else if (p_Dpb->fs_ref[j]->is_used) { - if (p_Dpb->fs_ref[j]->is_used & 0x1) { // top - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ref[j]->top_field; - - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->top_field->poc; - p_Dec->dpb_info[i].BOT_POC = 0; - p_Dec->dpb_info[i].field_flag = 1; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ref[j]->top_field->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ref[j]->top_field->colmv_no_used_flag ? 0 : 1); - } else { // if(p_Dpb->fs_ref[j]->is_used & 0x2) // bottom - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ref[j]->bottom_field; - p_Dec->dpb_info[i].TOP_POC = 0; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->bottom_field->poc; - p_Dec->dpb_info[i].field_flag = 1; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ref[j]->bottom_field->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ref[j]->bottom_field->colmv_no_used_flag ? 0 : 1); - - } - } - p_Dec->dpb_info[i].frame_num_wrap = p_Dpb->fs_ref[j]->frame_num_wrap; - p_Dec->dpb_info[i].is_long_term = 0; - p_Dec->dpb_info[i].voidx = p_Dpb->fs_ref[j]->layer_id; - p_Dec->dpb_info[i].view_id = p_Dpb->fs_ref[j]->view_id; - p_Dec->dpb_info[i].is_used = p_Dpb->fs_ref[j]->is_used; - } - //!<---- long term reference - for (j = 0; j < p_Dpb->ltref_frames_in_buffer; i++, j++) { - if (p_Dpb->fs_ltref[j]->is_used == 3) { - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ltref[j]->frame; - - if (p_Dpb->fs_ltref[j]->frame->iCodingType == FIELD_CODING) { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->top_field->poc; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->bottom_field->poc; - } else { - if (p_Dpb->fs_ltref[j]->frame->frame_poc != p_Dpb->fs_ltref[j]->frame->poc) { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->frame->top_poc - p_Dpb->fs_ltref[j]->frame->frame_poc; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->frame->bottom_poc - p_Dpb->fs_ltref[j]->frame->frame_poc; - } else { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->frame->top_poc; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->frame->bottom_poc; - } - - } - p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ltref[j]->frame->iCodingType == FIELD_CODING; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ltref[j]->frame->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ltref[j]->frame->colmv_no_used_flag ? 0 : 1); - } else if (p_Dpb->fs_ltref[j]->is_used) { - if (p_Dpb->fs_ltref[j]->is_used & 0x1) { - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ltref[j]->top_field; - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->top_field->poc; - p_Dec->dpb_info[i].BOT_POC = 0; - p_Dec->dpb_info[i].field_flag = 1; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ltref[j]->top_field->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ltref[j]->top_field->colmv_no_used_flag ? 0 : 1); - - } else { // if(p_Dpb->fs_ref[j]->is_used & 0x2) - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ltref[j]->bottom_field; - p_Dec->dpb_info[i].TOP_POC = 0; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->bottom_field->poc; - p_Dec->dpb_info[i].field_flag = 1; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ltref[j]->bottom_field->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ltref[j]->bottom_field->colmv_no_used_flag ? 0 : 1); - } - } - p_Dec->dpb_info[i].frame_num_wrap = p_Dpb->fs_ltref[j]->long_term_frame_idx;//long term use long_term_frame_idx - p_Dec->dpb_info[i].is_long_term = 1; - p_Dec->dpb_info[i].voidx = p_Dpb->fs_ltref[j]->layer_id; - p_Dec->dpb_info[i].view_id = p_Dpb->fs_ltref[j]->view_id; - p_Dec->dpb_info[i].is_used = p_Dpb->fs_ltref[j]->is_used; - } - //!<---- short term reference - for (j = 0; j < p_Dpb->used_size_il; i++, j++) { - if (currSlice->structure == FRAME && p_Dpb->fs_ilref[j]->is_used == 3) { - if (p_Dpb->fs_ilref[j]->inter_view_flag[0] == 0 && p_Dpb->fs_ilref[j]->inter_view_flag[1] == 0) - break; - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ilref[j]->frame; - - if (p_Dpb->fs_ilref[j]->frame->is_mmco_5) { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->frame->top_poc_mmco5; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->frame->bot_poc_mmco5; - } else { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->frame->top_poc; - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->frame->bottom_poc; - } - p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ilref[j]->frame->iCodingType == FIELD_CODING; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->frame->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->frame->colmv_no_used_flag ? 0 : 1); - - } else if (currSlice->structure != FRAME && p_Dpb->fs_ilref[j]->is_used) { - if (p_Dpb->fs_ilref[j]->is_used == 0x3) { - if (p_Dpb->fs_ilref[j]->inter_view_flag[currSlice->structure == BOTTOM_FIELD] == 0) - break; - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ilref[j]->top_field; - - if (p_Dpb->fs_ilref[j]->top_field->is_mmco_5) { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc_mmco5; - } else { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc; - } - if (p_Dpb->fs_ilref[j]->bottom_field->is_mmco_5) { - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bot_poc_mmco5; - } else { - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bottom_poc; - } - p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ilref[j]->frame->iCodingType == FIELD_CODING; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->frame->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->frame->colmv_no_used_flag ? 0 : 1); - } - if (p_Dpb->fs_ilref[j]->is_used & 0x1) { - if (p_Dpb->fs_ilref[j]->inter_view_flag[0] == 0) - break; - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ilref[j]->top_field; - - if (p_Dpb->fs_ilref[j]->top_field->is_mmco_5) { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc_mmco5; - } else { - p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc; - } - p_Dec->dpb_info[i].BOT_POC = 0; - p_Dec->dpb_info[i].field_flag = 1; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->top_field->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->top_field->colmv_no_used_flag ? 0 : 1); - - } else { // if(p_Dpb->fs_ref[j]->is_used & 0x2) - if (p_Dpb->fs_ilref[j]->inter_view_flag[1] == 0) - break; - p_Dec->dpb_info[i].picbuf = (void *)p_Dpb->fs_ilref[j]->bottom_field; - - p_Dec->dpb_info[i].TOP_POC = 0; - if (p_Dpb->fs_ilref[j]->bottom_field->is_mmco_5) { - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bot_poc_mmco5; - } else { - p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bottom_poc; - } - p_Dec->dpb_info[i].field_flag = 1; - p_Dec->dpb_info[i].mem_mark_idx = p_Dpb->fs_ilref[j]->bottom_field->mem_mark->index; - p_Dec->dpb_info[i].colmv_is_used = (p_Dpb->fs_ilref[j]->bottom_field->colmv_no_used_flag ? 0 : 1); - } - } - p_Dec->dpb_info[i].frame_num_wrap = p_Dpb->fs_ilref[j]->frame_num_wrap; - p_Dec->dpb_info[i].is_long_term = 0; - p_Dec->dpb_info[i].voidx = p_Dpb->fs_ilref[j]->layer_id; - p_Dec->dpb_info[i].view_id = p_Dpb->fs_ilref[j]->view_id; - p_Dec->dpb_info[i].is_used = p_Dpb->fs_ilref[j]->is_used; - } - //!<------ set listP ------- - for (j = 0; j < 32; j++) { - poc = 0; - layer_id = currSlice->listP[0][j]->layer_id; - if (j < currSlice->listXsizeP[0]) { - if (currSlice->listP[0][j]->structure == FRAME) { - poc = (currSlice->listP[0][j]->is_mmco_5 && currSlice->layer_id && currSlice->listP[0][j]->layer_id == 0) - ? currSlice->listP[0][j]->poc_mmco5 : currSlice->listP[0][j]->poc; - } else if (currSlice->listP[0][j]->structure == TOP_FIELD) { - - poc = (currSlice->listP[0][j]->is_mmco_5 && currSlice->layer_id && currSlice->listP[0][j]->layer_id == 0) - ? currSlice->listP[0][j]->top_poc_mmco5 : currSlice->listP[0][j]->top_poc; - } else { - poc = (currSlice->listP[0][j]->is_mmco_5 && currSlice->layer_id && currSlice->listP[0][j]->layer_id == 0) - ? currSlice->listP[0][j]->bot_poc_mmco5 : currSlice->listP[0][j]->bottom_poc; - } - for (i = 0; i < 16; i++) { - picbuf = p_Dec->dpb_info[i].picbuf; - TOP_POC = p_Dec->dpb_info[i].TOP_POC; - BOT_POC = p_Dec->dpb_info[i].BOT_POC; - voidx = p_Dec->dpb_info[i].voidx; - is_used = p_Dec->dpb_info[i].is_used; - if (currSlice->structure == FRAME && picbuf) { - if (poc == min(TOP_POC, BOT_POC) && (layer_id == voidx)) - break; - } else { - if (is_used == 3) { - if ((poc == BOT_POC || poc == TOP_POC) && layer_id == voidx) - break; - } else if (is_used & 1) { - if (poc == TOP_POC && layer_id == voidx) - break; - } else if (is_used & 2) { - if (poc == BOT_POC && layer_id == voidx) - break; - } - } - } - ASSERT(i < 16); - p_Dec->refpic_info_p[j].dpb_idx = i; - - if (currSlice->listP[0][j]->structure == BOTTOM_FIELD) { - p_Dec->refpic_info_p[j].bottom_flag = 1; - } else { - p_Dec->refpic_info_p[j].bottom_flag = 0; - } - p_Dec->refpic_info_p[j].valid = 1; - } else { - p_Dec->refpic_info_p[j].valid = 0; - p_Dec->refpic_info_p[j].dpb_idx = 0; - p_Dec->refpic_info_p[j].bottom_flag = 0; - } - } - //!<------ set listB ------- - for (k = 0; k < 2; k++) { - for (j = 0; j < 32; j++) { - poc = 0; - layer_id = currSlice->listB[k][j]->layer_id; - if (j < currSlice->listXsizeB[k]) { - if (currSlice->listB[k][j]->structure == FRAME) { - poc = (currSlice->listB[k][j]->is_mmco_5 && currSlice->layer_id && currSlice->listB[k][j]->layer_id == 0) - ? currSlice->listB[k][j]->poc_mmco5 : currSlice->listB[k][j]->poc; - } else if (currSlice->listB[k][j]->structure == TOP_FIELD) { - poc = (currSlice->listB[k][j]->is_mmco_5 && currSlice->layer_id && currSlice->listB[k][j]->layer_id == 0) - ? currSlice->listB[k][j]->top_poc_mmco5 : currSlice->listB[k][j]->top_poc; - } else { - poc = (currSlice->listB[k][j]->is_mmco_5 && currSlice->layer_id && currSlice->listB[k][j]->layer_id == 0) - ? currSlice->listB[k][j]->bot_poc_mmco5 : currSlice->listB[k][j]->bottom_poc; - } - for (i = 0; i < 16; i++) { - picbuf = p_Dec->dpb_info[i].picbuf; - TOP_POC = p_Dec->dpb_info[i].TOP_POC; - BOT_POC = p_Dec->dpb_info[i].BOT_POC; - voidx = p_Dec->dpb_info[i].voidx; - is_used = p_Dec->dpb_info[i].is_used; - if (currSlice->structure == FRAME && picbuf) { - if (poc == min(TOP_POC, BOT_POC) && (layer_id == voidx)) - break; - } else { - if (is_used == 3) { - if ((poc == BOT_POC || poc == TOP_POC) && layer_id == voidx) - break; - } else if (is_used & 1) { - if (poc == TOP_POC && (layer_id == voidx || (layer_id != voidx && !currSlice->bottom_field_flag))) - break; - } else if (is_used & 2) { - if (poc == BOT_POC && (layer_id == voidx || (layer_id != voidx && currSlice->bottom_field_flag))) - break; - } - } - } - ASSERT(i < 16); - p_Dec->refpic_info[k][j].dpb_idx = i; - - if (currSlice->listB[k][j]->structure == BOTTOM_FIELD) { - p_Dec->refpic_info[k][j].bottom_flag = 1; - } else { - p_Dec->refpic_info[k][j].bottom_flag = 0; - } - - p_Dec->refpic_info[k][j].valid = 1; - } else { - p_Dec->refpic_info[k][j].valid = 0; - p_Dec->refpic_info[k][j].dpb_idx = 0; - p_Dec->refpic_info[k][j].bottom_flag = 0; - } - } - } -__RETURN: - return MPP_OK; -} -/*! -*********************************************************************** -* \brief -* update dpb -*********************************************************************** -*/ -//extern "C" -MPP_RET update_dpb(H264_DecCtx_t *p_Dec) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - p_Dec->parser_end_flag = 0; - p_Dec->p_Vid->exit_picture_flag = 1; - p_Dec->p_Vid->have_outpicture_flag = 1; - FUN_CHECK(ret = exit_picture(p_Dec->p_Vid, &p_Dec->p_Vid->dec_picture)); - p_Dec->p_Vid->iNumOfSlicesDecoded = 0; - p_Dec->p_Vid->exit_picture_flag = 0; - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264d_dpb" + +#include +#include + +#include "mpp_common.h" +#include "mpp_buf_slot.h" + +#include "h264d_scalist.h" +#include "h264d_dpb.h" +#include "h264d_init.h" + +#ifndef INT_MIN +#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */ +#endif +#ifndef INT_MAX +#define INT_MAX 2147483647 /* maximum (signed) int value */ +#endif +static RK_S32 RoundLog2(RK_S32 iValue) +{ + RK_S32 iRet = 0; + RK_S32 iValue_square = iValue * iValue; + + while ((1 << (iRet + 1)) <= iValue_square) { + ++iRet; + } + iRet = (iRet + 1) >> 1; + + return iRet; +} + +static RK_S32 getDpbSize(H264dVideoCtx_t *p_Vid, H264_SPS_t *active_sps) +{ + RK_S32 size = 0, num_views = 0; + RK_S32 pic_size = (active_sps->pic_width_in_mbs_minus1 + 1) + * (active_sps->pic_height_in_map_units_minus1 + 1) * (active_sps->frame_mbs_only_flag ? 1 : 2) * 384; + + switch (active_sps->level_idc) { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + if (!is_prext_profile(active_sps->profile_idc) && (active_sps->constrained_set3_flag == 1)) + size = 152064; + else + size = 345600; + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + size = 70778880; + break; + case 52: + size = 70778880; + break; + default: + size = 0; + break; + } + size /= pic_size; + if (p_Vid->active_mvc_sps_flag && + (p_Vid->profile_idc == H264_PROFILE_MVC_HIGH || p_Vid->profile_idc == H264_PROFILE_STEREO_HIGH)) { + num_views = p_Vid->active_subsps->num_views_minus1 + 1; + size = MPP_MIN(2 * size, MPP_MAX(1, RoundLog2(num_views)) * 16) / num_views; + } else { + size = MPP_MIN(size, 16); + } + if (active_sps->vui_parameters_present_flag && active_sps->vui_seq_parameters.bitstream_restriction_flag) { + RK_S32 size_vui = 0; + if ((RK_S32)active_sps->vui_seq_parameters.max_dec_frame_buffering > size) { + H264D_WARNNING("warnnig: max_dec_frame_buffering larger than MaxDpbSize"); + } + size_vui = MPP_MAX(1, active_sps->vui_seq_parameters.max_dec_frame_buffering); + if (size_vui < size) { + H264D_WARNNING("warning: max_dec_frame_buffering(%d) is less than dpb_size(%d) calculated from Profile/Level.\n", size_vui, size); + } + size = size_vui; + } + + if (size < active_sps->max_num_ref_frames) { + H264D_WARNNING("warnning: DPB size is less than max_num_ref_frames, level(%d), pic_size(%d), max_num_ref_frames(%d).\n", + active_sps->level_idc, pic_size, active_sps->max_num_ref_frames); + size = MPP_MIN(active_sps->max_num_ref_frames, 16); + } + + return size; +} + +static RK_S32 get_pic_num_x(H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1) +{ + RK_S32 currPicNum; + + if (p->structure == FRAME) + currPicNum = p->frame_num; + else + currPicNum = 2 * p->frame_num + 1; + + return currPicNum - (difference_of_pic_nums_minus1 + 1); +} + +static void unmark_for_reference(H264_DecCtx_t *p_Dec, H264_FrameStore_t* fs) +{ + H264_StorePic_t *cur_pic = NULL; + if (fs->is_used & 1) { + if (fs->top_field) { + fs->top_field->used_for_reference = 0; + cur_pic = fs->top_field; + } + } + if (fs->is_used & 2) { + if (fs->bottom_field) { + fs->bottom_field->used_for_reference = 0; + cur_pic = fs->bottom_field; + } + } + if (fs->is_used == 3) { + if (fs->top_field && fs->bottom_field) { + fs->top_field->used_for_reference = 0; + fs->bottom_field->used_for_reference = 0; + } + fs->frame->used_for_reference = 0; + cur_pic = fs->frame; + } + fs->is_reference = 0; + (void)cur_pic; + (void)p_Dec; +} + +static RK_U32 is_short_term_reference(H264_FrameStore_t* fs) +{ + if (fs->is_used == 3) { // frame + if ((fs->frame->used_for_reference) && (!fs->frame->is_long_term)) { + return 1; + } + } + + if (fs->is_used & 1) { // top field + if (fs->top_field) { + if ((fs->top_field->used_for_reference) && (!fs->top_field->is_long_term)) { + return 1; + } + } + } + + if (fs->is_used & 2) { // bottom field + if (fs->bottom_field) { + if ((fs->bottom_field->used_for_reference) && (!fs->bottom_field->is_long_term)) { + return 1; + } + } + } + return 0; +} + +static RK_U32 is_long_term_reference(H264_FrameStore_t* fs) +{ + + if (fs->is_used == 3) { // frame + if ((fs->frame->used_for_reference) && (fs->frame->is_long_term)) { + return 1; + } + } + + if (fs->is_used & 1) { // top field + if (fs->top_field) { + if ((fs->top_field->used_for_reference) && (fs->top_field->is_long_term)) { + return 1; + } + } + } + + if (fs->is_used & 2) { // bottom field + if (fs->bottom_field) { + if ((fs->bottom_field->used_for_reference) && (fs->bottom_field->is_long_term)) { + return 1; + } + } + } + return 0; +} + +static void unmark_for_long_term_reference(H264_FrameStore_t* fs) +{ + if (fs->is_used & 1) { + if (fs->top_field) { + fs->top_field->used_for_reference = 0; + fs->top_field->is_long_term = 0; + } + } + if (fs->is_used & 2) { + if (fs->bottom_field) { + fs->bottom_field->used_for_reference = 0; + fs->bottom_field->is_long_term = 0; + } + } + if (fs->is_used == 3) { + if (fs->top_field && fs->bottom_field) { + fs->top_field->used_for_reference = 0; + fs->top_field->is_long_term = 0; + fs->bottom_field->used_for_reference = 0; + fs->bottom_field->is_long_term = 0; + } + fs->frame->used_for_reference = 0; + fs->frame->is_long_term = 0; + } + + fs->is_reference = 0; + fs->is_long_term = 0; +} + +static void mm_unmark_short_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 difference_of_pic_nums_minus1) +{ + RK_S32 picNumX = 0; + RK_U32 i = 0; + + picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p->structure == FRAME) { + if ((p_Dpb->fs_ref[i]->is_reference == 3) && (p_Dpb->fs_ref[i]->is_long_term == 0)) { + if (p_Dpb->fs_ref[i]->frame->pic_num == picNumX) { + unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs_ref[i]); + return; + } + } + } else { + if ((p_Dpb->fs_ref[i]->is_reference & 1) && (!(p_Dpb->fs_ref[i]->is_long_term & 1))) { + if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) { + p_Dpb->fs_ref[i]->top_field->used_for_reference = 0; + p_Dpb->fs_ref[i]->is_reference &= 2; + if (p_Dpb->fs_ref[i]->is_used == 3) { + p_Dpb->fs_ref[i]->frame->used_for_reference = 0; + } + return; + } + } + if ((p_Dpb->fs_ref[i]->is_reference & 2) && (!(p_Dpb->fs_ref[i]->is_long_term & 2))) { + if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) { + p_Dpb->fs_ref[i]->bottom_field->used_for_reference = 0; + p_Dpb->fs_ref[i]->is_reference &= 1; + if (p_Dpb->fs_ref[i]->is_used == 3) { + p_Dpb->fs_ref[i]->frame->used_for_reference = 0; + } + return; + } + } + } + } +} + +static void mm_unmark_long_term_for_reference(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_pic_num) +{ + RK_U32 i = 0; + + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p->structure == FRAME) { + if ((p_Dpb->fs_ltref[i]->is_reference == 3) && (p_Dpb->fs_ltref[i]->is_long_term == 3)) { + if (p_Dpb->fs_ltref[i]->frame->long_term_pic_num == long_term_pic_num) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + } else { + if ((p_Dpb->fs_ltref[i]->is_reference & 1) && ((p_Dpb->fs_ltref[i]->is_long_term & 1))) { + if (p_Dpb->fs_ltref[i]->top_field->long_term_pic_num == long_term_pic_num) { + p_Dpb->fs_ltref[i]->top_field->used_for_reference = 0; + p_Dpb->fs_ltref[i]->top_field->is_long_term = 0; + p_Dpb->fs_ltref[i]->is_reference &= 2; + p_Dpb->fs_ltref[i]->is_long_term &= 2; + if (p_Dpb->fs_ltref[i]->is_used == 3) { + p_Dpb->fs_ltref[i]->frame->used_for_reference = 0; + p_Dpb->fs_ltref[i]->frame->is_long_term = 0; + } + return; + } + } + if ((p_Dpb->fs_ltref[i]->is_reference & 2) && ((p_Dpb->fs_ltref[i]->is_long_term & 2))) { + if (p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num == long_term_pic_num) { + p_Dpb->fs_ltref[i]->bottom_field->used_for_reference = 0; + p_Dpb->fs_ltref[i]->bottom_field->is_long_term = 0; + p_Dpb->fs_ltref[i]->is_reference &= 1; + p_Dpb->fs_ltref[i]->is_long_term &= 1; + if (p_Dpb->fs_ltref[i]->is_used == 3) { + p_Dpb->fs_ltref[i]->frame->used_for_reference = 0; + p_Dpb->fs_ltref[i]->frame->is_long_term = 0; + } + return; + } + } + } + } +} + +static void unmark_long_term_frame_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 long_term_frame_idx) +{ + RK_U32 i = 0; + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } +} + +static MPP_RET unmark_long_term_field_for_reference_by_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 structure, + RK_S32 long_term_frame_idx, RK_S32 mark_current, RK_U32 curr_frame_num, RK_S32 curr_pic_num) +{ + RK_U8 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + VAL_CHECK(ret, structure != FRAME); + if (curr_pic_num < 0) + curr_pic_num += (2 * p_Vid->max_frame_num); + + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx == long_term_frame_idx) { + if (structure == TOP_FIELD) { + if (p_Dpb->fs_ltref[i]->is_long_term == 3) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + if (p_Dpb->fs_ltref[i]->is_long_term == 1) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + if (mark_current) { + if (p_Dpb->last_picture) { + if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num) + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } else { + if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + } + } + } + if (structure == BOTTOM_FIELD) { + if (p_Dpb->fs_ltref[i]->is_long_term == 3) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + if (p_Dpb->fs_ltref[i]->is_long_term == 2) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + if (mark_current) { + if (p_Dpb->last_picture) { + if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) || p_Dpb->last_picture->frame_num != curr_frame_num) + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } else { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } else { + if ((p_Dpb->fs_ltref[i]->frame_num) != (unsigned)(curr_pic_num >> 1)) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } + } + } + } + } + } + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void mark_pic_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 long_term_frame_idx, RK_S32 picNumX) +{ + RK_U32 i = 0; + RK_S32 add_top = 0, add_bottom = 0; + + if (p->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference == 3) { + if ((!p_Dpb->fs_ref[i]->frame->is_long_term) && (p_Dpb->fs_ref[i]->frame->pic_num == picNumX)) { + p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_frame_idx = long_term_frame_idx; + p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; + p_Dpb->fs_ref[i]->frame->is_long_term = 1; + + if (p_Dpb->fs_ref[i]->top_field && p_Dpb->fs_ref[i]->bottom_field) { + p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx = long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field->long_term_pic_num = long_term_frame_idx; + p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field->is_long_term = p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1; + } + p_Dpb->fs_ref[i]->is_long_term = 3; + return; + } + } + } + H264D_WARNNING("reference frame for long term marking not found."); + } else { + if (p->structure == TOP_FIELD) { + add_top = 1; + add_bottom = 0; + } else { + add_top = 0; + add_bottom = 1; + } + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference & 1) { + if ((!p_Dpb->fs_ref[i]->top_field->is_long_term) && (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX)) { + if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) { + H264D_WARNNING("assigning long_term_frame_idx different from other field."); + } + p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->top_field->long_term_frame_idx = long_term_frame_idx; + p_Dpb->fs_ref[i]->top_field->long_term_pic_num = 2 * long_term_frame_idx + add_top; + p_Dpb->fs_ref[i]->top_field->is_long_term = 1; + p_Dpb->fs_ref[i]->is_long_term |= 1; + if (p_Dpb->fs_ref[i]->is_long_term == 3) { + p_Dpb->fs_ref[i]->frame->is_long_term = 1; + p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; + } + return; + } + } + if (p_Dpb->fs_ref[i]->is_reference & 2) { + if ((!p_Dpb->fs_ref[i]->bottom_field->is_long_term) && (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX)) { + if ((p_Dpb->fs_ref[i]->is_long_term) && (p_Dpb->fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) { + H264D_WARNNING("assigning long_term_frame_idx different from other field."); + } + + p_Dpb->fs_ref[i]->long_term_frame_idx = p_Dpb->fs_ref[i]->bottom_field->long_term_frame_idx + = long_term_frame_idx; + p_Dpb->fs_ref[i]->bottom_field->long_term_pic_num = 2 * long_term_frame_idx + add_bottom; + p_Dpb->fs_ref[i]->bottom_field->is_long_term = 1; + p_Dpb->fs_ref[i]->is_long_term |= 2; + if (p_Dpb->fs_ref[i]->is_long_term == 3) { + p_Dpb->fs_ref[i]->frame->is_long_term = 1; + p_Dpb->fs_ref[i]->frame->long_term_frame_idx = p_Dpb->fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; + } + return; + } + } + } + H264D_WARNNING("reference field for long term marking not found."); + } +} + +static MPP_RET mm_assign_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, H264_StorePic_t* p, RK_S32 difference_of_pic_nums_minus1, RK_S32 long_term_frame_idx) +{ + RK_S32 picNumX = 0; + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); + //!< remove frames/fields with same long_term_frame_idx + if (p->structure == FRAME) { + unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx); + } else { + PictureStructure structure = FRAME; + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference & 1) { + if (p_Dpb->fs_ref[i]->top_field->pic_num == picNumX) { + structure = TOP_FIELD; + break; + } + } + if (p_Dpb->fs_ref[i]->is_reference & 2) { + if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNumX) { + structure = BOTTOM_FIELD; + break; + } + } + } + VAL_CHECK(ret, structure != FRAME); + FUN_CHECK(ret = unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, structure, long_term_frame_idx, 0, 0, picNumX)); + } + mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX); + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void mm_update_max_long_term_frame_idx(H264_DpbBuf_t *p_Dpb, RK_S32 max_long_term_frame_idx_plus1) +{ + RK_U32 i = 0; + + p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1; + + // check for invalid frames + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->long_term_frame_idx > p_Dpb->max_long_term_pic_idx) { + unmark_for_long_term_reference(p_Dpb->fs_ltref[i]); + } + } +} + +static void mm_unmark_all_short_term_for_reference(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs_ref[i]); + } + update_ref_list(p_Dpb); +} + +static void mm_unmark_all_long_term_for_reference(H264_DpbBuf_t *p_Dpb) +{ + mm_update_max_long_term_frame_idx(p_Dpb, 0); +} + +static void mm_mark_current_picture_long_term(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p, RK_S32 long_term_frame_idx) +{ + // remove long term pictures with same long_term_frame_idx + if (p->structure == FRAME) { + unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb, long_term_frame_idx); + } else { + unmark_long_term_field_for_reference_by_frame_idx(p_Dpb, p->structure, long_term_frame_idx, 1, p->pic_num, 0); + } + + p->is_long_term = 1; + p->long_term_frame_idx = long_term_frame_idx; +} + +static void sliding_window_memory_management(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + + // if this is a reference pic with sliding window, unmark first ref frame + if (p_Dpb->ref_frames_in_buffer == MPP_MAX(1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer) { + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i]->is_reference && (!(p_Dpb->fs[i]->is_long_term))) { + unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs[i]); + update_ref_list(p_Dpb); + break; + } + } + } +} + +static void check_num_ref(H264_DpbBuf_t *p_Dpb) +{ + + if ((RK_S32)(p_Dpb->ltref_frames_in_buffer + p_Dpb->ref_frames_in_buffer) > MPP_MAX(1, p_Dpb->num_ref_frames)) { + sliding_window_memory_management(p_Dpb); + H264D_WARNNING("Max number of reference frames exceeded"); + } +} + +static RK_U32 is_used_for_reference(H264_FrameStore_t* fs) +{ + RK_U8 is_used_flag = 0; + + if (!fs) { + return 0; + } + if (fs->is_reference) { + return is_used_flag = 1; + } + + if (fs->is_used == 3) { // frame + if (fs->frame->used_for_reference) { + return is_used_flag = 1; + } + } + + if (fs->is_used & 1) { // top field + if (fs->top_field) { + if (fs->top_field->used_for_reference) { + return is_used_flag = 1; + } + } + } + + if (fs->is_used & 2) { // bottom field + if (fs->bottom_field) { + if (fs->bottom_field->used_for_reference) { + return is_used_flag = 1; + } + } + } + return is_used_flag = 0; +} + +static void free_dpb_mark(H264_DecCtx_t *p_Dec, H264_DpbMark_t *p_mark, RK_S32 structure) +{ + if (structure == FRAME) { + p_mark->top_used = (p_mark->top_used > 0) ? (p_mark->top_used - 1) : 0; + p_mark->bot_used = (p_mark->bot_used > 0) ? (p_mark->bot_used - 1) : 0; + } else if (structure == TOP_FIELD) { + p_mark->top_used = (p_mark->top_used > 0) ? (p_mark->top_used - 1) : 0; + } else if (structure == BOTTOM_FIELD) { + p_mark->bot_used = (p_mark->bot_used > 0) ? (p_mark->bot_used - 1) : 0; + } + if (p_mark->top_used == 0 && p_mark->bot_used == 0 + && p_mark->out_flag == 0 && (p_mark->slot_idx >= 0)) { + mpp_buf_slot_clr_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_CODEC_USE); + reset_dpb_mark(p_mark); + } +} + +static MPP_RET remove_frame_from_dpb(H264_DpbBuf_t *p_Dpb, RK_S32 pos) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_FrameStore_t* tmp = NULL; + H264_FrameStore_t* fs = NULL; + H264_DecCtx_t *p_Dec = NULL; + + INP_CHECK(ret, !p_Dpb); + fs = p_Dpb->fs[pos]; + INP_CHECK(ret, !fs); + INP_CHECK(ret, !p_Dpb->p_Vid); + p_Dec = p_Dpb->p_Vid->p_Dec; + INP_CHECK(ret, !p_Dec); + + switch (fs->is_used) { + case 3: + if (fs->frame) free_storable_picture(p_Dec, fs->frame); + if (fs->top_field) free_storable_picture(p_Dec, fs->top_field); + if (fs->bottom_field) free_storable_picture(p_Dec, fs->bottom_field); + fs->frame = NULL; + fs->top_field = NULL; + fs->bottom_field = NULL; + break; + case 2: + if (fs->bottom_field) free_storable_picture(p_Dec, fs->bottom_field); + fs->bottom_field = NULL; + break; + case 1: + if (fs->top_field) free_storable_picture(p_Dec, fs->top_field); + fs->top_field = NULL; + break; + case 0: + break; + default: + H264D_ERR("invalid frame store type."); + goto __FAILED; + } + + fs->is_used = 0; + fs->is_long_term = 0; + fs->is_reference = 0; + fs->is_orig_reference = 0; + + // move empty framestore to end of buffer + tmp = p_Dpb->fs[pos]; + + for (i = pos; i < p_Dpb->used_size - 1; i++) { + p_Dpb->fs[i] = p_Dpb->fs[i + 1]; + } + p_Dpb->fs[p_Dpb->used_size - 1] = tmp; + p_Dpb->used_size--; + + return ret = MPP_OK; +__RETURN: + return ret; +__FAILED: + return ret = MPP_NOK; + + +} + +static MPP_RET remove_unused_frame_from_dpb(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + INP_CHECK(ret, !p_Dpb); + // check for frames that were already output and no longer used for reference + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i]) { + if (p_Dpb->fs[i]->is_output && (!is_used_for_reference(p_Dpb->fs[i]))) { + FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, i)); + return MPP_OK; + } + } + } +__RETURN: + return ret; +__FAILED: + return ret; +} + +static RK_S32 get_smallest_poc(H264_DpbBuf_t *p_Dpb, RK_S32 *poc, RK_S32 *pos) +{ + RK_U32 i = 0; + RK_S32 find_flag = 0; + RK_S32 min_pos = -1; + RK_S32 min_poc = INT_MAX; + + *pos = -1; + *poc = INT_MAX; + for (i = 0; i < p_Dpb->used_size; i++) { + if (min_poc > p_Dpb->fs[i]->poc) { + min_poc = p_Dpb->fs[i]->poc; + min_pos = i; + } + if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) { + *poc = p_Dpb->fs[i]->poc; + *pos = i; + find_flag = 1; + } + } + if (!find_flag) { + *poc = min_poc; + *pos = min_pos; + } + + return find_flag; +} + +static H264_FrameStore_t *alloc_frame_store() +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_FrameStore_t *f = mpp_calloc(H264_FrameStore_t, 1); + MEM_CHECK(ret, f); + + f->is_used = 0; + f->is_reference = 0; + f->is_long_term = 0; + f->is_orig_reference = 0; + f->is_output = 0; + + f->frame = NULL; + f->top_field = NULL; + f->bottom_field = NULL; + + return f; +__FAILED: + (void)ret; + return NULL; +} + +static MPP_RET dpb_combine_field_yuv(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (!fs->frame) { + fs->frame = alloc_storable_picture(p_Vid, FRAME); + MEM_CHECK(ret, fs->frame); + ASSERT(fs->top_field->colmv_no_used_flag == fs->bottom_field->colmv_no_used_flag); + fs->frame->colmv_no_used_flag = fs->top_field->colmv_no_used_flag; + if (combine_flag) { + ASSERT(fs->top_field->mem_mark->mark_idx == fs->bottom_field->mem_mark->mark_idx); + ASSERT(fs->top_field->mem_mark->slot_idx == fs->bottom_field->mem_mark->slot_idx); + fs->frame->mem_malloc_type = fs->top_field->mem_malloc_type; + fs->frame->mem_mark = fs->top_field->mem_mark; + } else if (fs->is_used == 0x01) { // unpaired, have top + ASSERT(fs->bottom_field->mem_malloc_type == Mem_UnPaired); + fs->frame->mem_mark = fs->top_field->mem_mark; + } else if (fs->is_used == 0x02) { // unpaired, have bottom + ASSERT(fs->top_field->mem_malloc_type == Mem_UnPaired); + fs->frame->mem_mark = fs->bottom_field->mem_mark; + } else { + ASSERT(fs->is_used == 0x03); + fs->frame->mem_malloc_type = fs->top_field->mem_malloc_type; + fs->frame->mem_mark = fs->top_field->mem_mark; + } + } + fs->poc = fs->frame->poc = fs->frame->frame_poc = MPP_MIN(fs->top_field->poc, fs->bottom_field->poc); + fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc; + fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc; + fs->top_field->bottom_poc = fs->frame->bottom_poc = fs->bottom_field->poc; + fs->frame->used_for_reference = (fs->top_field->used_for_reference && fs->bottom_field->used_for_reference); + fs->frame->is_long_term = (fs->top_field->is_long_term && fs->bottom_field->is_long_term); + if (fs->frame->is_long_term) { + fs->frame->long_term_frame_idx = fs->long_term_frame_idx; + } + fs->frame->top_field = fs->top_field; + fs->frame->bottom_field = fs->bottom_field; + fs->frame->frame = fs->frame; + fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc; + + fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag; + if (fs->frame->frame_cropping_flag) { + fs->frame->frame_crop_top_offset = fs->top_field->frame_crop_top_offset; + fs->frame->frame_crop_bottom_offset = fs->top_field->frame_crop_bottom_offset; + fs->frame->frame_crop_left_offset = fs->top_field->frame_crop_left_offset; + fs->frame->frame_crop_right_offset = fs->top_field->frame_crop_right_offset; + } + fs->top_field->frame = fs->bottom_field->frame = fs->frame; + fs->top_field->top_field = fs->top_field; + fs->top_field->bottom_field = fs->bottom_field; + fs->bottom_field->top_field = fs->top_field; + fs->bottom_field->bottom_field = fs->bottom_field; + + fs->frame->is_mmco_5 = fs->top_field->is_mmco_5 || fs->bottom_field->is_mmco_5; + fs->frame->poc_mmco5 = MPP_MIN(fs->top_field->top_poc_mmco5, fs->bottom_field->bot_poc_mmco5); + fs->frame->top_poc_mmco5 = fs->top_field->top_poc_mmco5; + fs->frame->bot_poc_mmco5 = fs->top_field->bot_poc_mmco5; + + return ret = MPP_OK; +__FAILED: + return ret ; +} + +static void write_picture(H264_StorePic_t *p, H264dVideoCtx_t *p_Vid) +{ + MppFrame mframe = NULL; + H264_DpbMark_t *p_mark = NULL; + H264dErrCtx_t *p_err = &p_Vid->p_Dec->errctx; + + p_mark = p->mem_mark; + if ((p->mem_malloc_type == Mem_Malloc + || p->mem_malloc_type == Mem_TopOnly + || p->mem_malloc_type == Mem_BotOnly) + && p->structure == FRAME && p_mark->out_flag) { + mpp_buf_slot_get_prop(p_Vid->p_Dec->frame_slots, p_mark->slot_idx, SLOT_FRAME_PTR, &mframe); + + //!< discard unpaired + if (p->mem_malloc_type == Mem_TopOnly || p->mem_malloc_type == Mem_BotOnly) { + if (p_err->used_ref_flag) { + mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW); + } else { + mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW); + } + } + //!< discard less than first i frame poc + if ((p_err->i_slice_no < 2) && (p->poc < p_err->first_iframe_poc)) { + if (p_err->used_ref_flag && p_err->first_iframe_is_output) { + if ((p->slice_type % 5) == H264_B_SLICE) + mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW); + else + mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW); + } else { + if (p_Vid->dpb_fast_out) + mpp_frame_set_discard(mframe, MPP_FRAME_ERR_UNKNOW); + } + } + + if (p_Vid->p_Dec->mvc_valid) { + H264_DpbMark_t *match_mark = NULL; + H264_DpbMark_t *out_mark_list[2] = {NULL, NULL}; + RK_U32 i = 0; + RK_S32 match_flag = 0; + RK_U32 is_base_view = p_mark->pic->layer_id == 0 ? 1 : 0; + + // find pic with the same poc at base view + for (i = 0; i < MAX_MARK_SIZE; i++) { + match_mark = &p_Vid->p_Dec->dpb_mark[i]; + + if (!match_mark || !match_mark->pic || !match_mark->out_flag || match_mark->slot_idx < 0) + continue; + + if (match_mark->pic->layer_id != p_mark->pic->layer_id) { + if (match_mark->pic->poc < p_mark->pic->poc) { + match_flag = 1; + break; + } else if (match_mark->pic->poc == p_mark->pic->poc) { + match_flag = 2; + break; + } else { + match_flag = 0; + } + } + } + + if (!match_flag) { + H264D_DBG(H264D_DBG_DPB_INFO, "no other view matched with current view_id %d, poc %d", + p_mark->pic->layer_id, p_mark->pic->poc); + out_mark_list[0] = p_mark; + } else if (match_flag == 1) { + H264D_DBG(H264D_DBG_DPB_INFO, "find match view at %d, slot_idx %d, view_id %d, poc %d", + i, match_mark->slot_idx, match_mark->pic->layer_id, match_mark->pic->poc); + out_mark_list[0] = match_mark; + out_mark_list[1] = p_mark; + } else if (match_flag == 2) { + H264D_DBG(H264D_DBG_DPB_INFO, "find match view at %d, slot_idx %d, view_id %d, poc %d", + i, match_mark->slot_idx, match_mark->pic->layer_id, match_mark->pic->poc); + if (is_base_view) { + out_mark_list[0] = p_mark; + out_mark_list[1] = match_mark; + } else { + out_mark_list[0] = match_mark; + out_mark_list[1] = p_mark; + } + } + + for (i = 0; i < 2; i++) { + if (out_mark_list[i]) { + mpp_buf_slot_set_flag(p_Vid->p_Dec->frame_slots, out_mark_list[i]->slot_idx, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p_Vid->p_Dec->frame_slots, out_mark_list[i]->slot_idx, QUEUE_DISPLAY); + out_mark_list[i]->out_flag = 0; + p_Vid->p_Dec->last_frame_slot_idx = out_mark_list[i]->slot_idx; + } + } + } else { + H264D_DBG(H264D_DBG_DPB_INFO, "display frame view_id %d slot_idx %d poc %d", + p_mark->pic->layer_id, p_mark->slot_idx, p_mark->pic->poc); + mpp_buf_slot_set_flag(p_Vid->p_Dec->frame_slots, p_mark->slot_idx, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p_Vid->p_Dec->frame_slots, p_mark->slot_idx, QUEUE_DISPLAY); + p_Vid->p_Dec->last_frame_slot_idx = p_mark->slot_idx; + p_mark->out_flag = 0; + } + } +} + +static MPP_RET write_unpaired_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *p = NULL; + + VAL_CHECK(ret, fs->is_used < 3); + if (fs->is_used & 0x01) { // we have a top field, construct an empty bottom field + p = fs->top_field; + fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD); + MEM_CHECK(ret, fs->bottom_field); + fs->bottom_field->mem_malloc_type = Mem_UnPaired; + fs->bottom_field->chroma_format_idc = p->chroma_format_idc; + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0)); + fs->frame->view_id = fs->view_id; + fs->frame->mem_malloc_type = Mem_TopOnly; + H264D_WARNNING("write frame, line %d", __LINE__); + write_picture(fs->frame, p_Vid); + } + + if (fs->is_used & 0x02) { // we have a bottom field, construct an empty top field + p = fs->bottom_field; + fs->top_field = alloc_storable_picture(p_Vid, TOP_FIELD); + MEM_CHECK(ret, fs->top_field); + fs->top_field->mem_malloc_type = Mem_UnPaired; + fs->top_field->chroma_format_idc = p->chroma_format_idc; + fs->top_field->frame_cropping_flag = fs->bottom_field->frame_cropping_flag; + if (fs->top_field->frame_cropping_flag) { + fs->top_field->frame_crop_top_offset = fs->bottom_field->frame_crop_top_offset; + fs->top_field->frame_crop_bottom_offset = fs->bottom_field->frame_crop_bottom_offset; + fs->top_field->frame_crop_left_offset = fs->bottom_field->frame_crop_left_offset; + fs->top_field->frame_crop_right_offset = fs->bottom_field->frame_crop_right_offset; + } + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, 0)); + fs->frame->view_id = fs->view_id; + fs->frame->mem_malloc_type = Mem_BotOnly; + H264D_WARNNING("write frame, line %d", __LINE__); + write_picture(fs->frame, p_Vid); + } + fs->is_used = 3; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET flush_direct_output(H264dVideoCtx_t *p_Vid) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + FUN_CHECK(ret = write_unpaired_field(p_Vid, &p_Vid->out_buffer)); + free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.frame); + p_Vid->out_buffer.frame = NULL; + free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.top_field); + p_Vid->out_buffer.top_field = NULL; + free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.bottom_field); + p_Vid->out_buffer.bottom_field = NULL; + p_Vid->out_buffer.is_used = 0; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET write_stored_frame(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + INP_CHECK(ret, !p_Vid); + INP_CHECK(ret, !fs); + //!< make sure no direct output field is pending + FUN_CHECK(ret = flush_direct_output(p_Vid)); + + if (fs->is_used < 3) { + FUN_CHECK(ret = write_unpaired_field(p_Vid, fs)); + if (fs->top_field) free_storable_picture(p_Vid->p_Dec, fs->top_field); + if (fs->bottom_field) free_storable_picture(p_Vid->p_Dec, fs->bottom_field); + fs->top_field = NULL; + fs->bottom_field = NULL; + } else { + H264D_WARNNING("write frame, line %d", __LINE__); + write_picture(fs->frame, p_Vid); + } + p_Dpb->last_output_poc = fs->poc; + fs->is_output = 1; + + return ret = MPP_OK; +__RETURN: + return ret; +__FAILED: + return ret; +} + +static MPP_RET output_one_frame_from_dpb(H264_DpbBuf_t *p_Dpb) +{ + RK_S32 poc = 0, pos = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + //!< find smallest POC + if (get_smallest_poc(p_Dpb, &poc, &pos)) { + //!< JVT-P072 ends + H264D_WARNNING("write_stored_frame, line %d", __LINE__); + FUN_CHECK(ret = write_stored_frame(p_Vid, p_Dpb, p_Dpb->fs[pos])); + //!< free frame store and move empty store to end of buffer + if (!is_used_for_reference(p_Dpb->fs[pos])) { + FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, pos)); + } + } + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET adaptive_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + H264_DRPM_t *tmp_drpm = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + p_Vid->last_has_mmco_5 = 0; + VAL_CHECK(ret, !p->idr_flag && p->adaptive_ref_pic_buffering_flag); + while (p->dec_ref_pic_marking_buffer) { + tmp_drpm = p->dec_ref_pic_marking_buffer; + switch (tmp_drpm->memory_management_control_operation) { + case 0: + VAL_CHECK(ret, tmp_drpm->Next == NULL); + break; + case 1: + mm_unmark_short_term_for_reference(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1); + update_ref_list(p_Dpb); + break; + case 2: + mm_unmark_long_term_for_reference(p_Dpb, p, tmp_drpm->long_term_pic_num); + update_ltref_list(p_Dpb); + break; + case 3: + mm_assign_long_term_frame_idx(p_Dpb, p, tmp_drpm->difference_of_pic_nums_minus1, tmp_drpm->long_term_frame_idx); + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + break; + case 4: + mm_update_max_long_term_frame_idx(p_Dpb, tmp_drpm->max_long_term_frame_idx_plus1); + update_ltref_list(p_Dpb); + break; + case 5: + mm_unmark_all_short_term_for_reference(p_Dpb); + mm_unmark_all_long_term_for_reference(p_Dpb); + p_Vid->last_has_mmco_5 = 1; + break; + case 6: + //!< conceal max_long_term_frame_idx_plus1 + if (!tmp_drpm->max_long_term_frame_idx_plus1) { + tmp_drpm->max_long_term_frame_idx_plus1 = p_Dpb->num_ref_frames; + } + mm_mark_current_picture_long_term(p_Dpb, p, tmp_drpm->long_term_frame_idx); + check_num_ref(p_Dpb); + break; + default: + ret = MPP_NOK; + goto __FAILED; + } + p->dec_ref_pic_marking_buffer = tmp_drpm->Next; + } + if (p_Vid->last_has_mmco_5) { //!< similar IDR frame + p->pic_num = p->frame_num = 0; + switch (p->structure) { + case TOP_FIELD: + p->is_mmco_5 = 1; + p->top_poc_mmco5 = p->top_poc; + p->poc = p->top_poc = 0; + break; + + case BOTTOM_FIELD: + p->is_mmco_5 = 1; + p->bot_poc_mmco5 = p->bottom_poc; + p->poc = p->bottom_poc = 0; + break; + + case FRAME: + p->is_mmco_5 = 1; + p->top_poc_mmco5 = p->top_poc; + p->bot_poc_mmco5 = p->bottom_poc; + p->poc_mmco5 = MPP_MIN(p->top_poc, p->bottom_poc); + p->top_poc -= p->poc; + p->bottom_poc -= p->poc; + + p->poc = MPP_MIN(p->top_poc, p->bottom_poc); + p->frame_poc = p->poc; + break; + + } + if (p->layer_id == 0) { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0], 1)); + } else { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1], 2)); + } + } + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET dpb_split_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *frame = fs->frame; + H264_StorePic_t *fs_top = NULL, *fs_btm = NULL; + + fs->poc = frame->poc; + if (!frame->frame_mbs_only_flag) { + fs_top = fs->top_field = alloc_storable_picture(p_Vid, TOP_FIELD); + fs_btm = fs->bottom_field = alloc_storable_picture(p_Vid, BOTTOM_FIELD); + MEM_CHECK(ret, fs_top && fs_btm); + fs_top->colmv_no_used_flag = frame->colmv_no_used_flag; + fs_btm->colmv_no_used_flag = frame->colmv_no_used_flag; + + if (frame->mem_malloc_type == Mem_Malloc || frame->mem_malloc_type == Mem_Clone) { + fs_top->mem_mark = frame->mem_mark; + fs_btm->mem_mark = frame->mem_mark; + fs_top->mem_malloc_type = frame->mem_malloc_type; + fs_btm->mem_malloc_type = frame->mem_malloc_type; + frame->mem_mark->bot_used += 1; // picture memory add 1 + frame->mem_mark->top_used += 1; + } + fs_top->poc = frame->top_poc; + fs_btm->poc = frame->bottom_poc; + fs_top->layer_id = frame->layer_id; + fs_btm->layer_id = frame->layer_id; + + fs_top->view_id = frame->view_id; + fs_btm->view_id = frame->view_id; + fs_top->frame_poc = frame->frame_poc; + + fs_top->bottom_poc = fs_btm->bottom_poc = frame->bottom_poc; + fs_top->top_poc = fs_btm->top_poc = frame->top_poc; + fs_btm->frame_poc = frame->frame_poc; + + fs_top->used_for_reference = fs_btm->used_for_reference = frame->used_for_reference; + fs_top->is_long_term = fs_btm->is_long_term = frame->is_long_term; + fs->long_term_frame_idx = fs_top->long_term_frame_idx = fs_btm->long_term_frame_idx = frame->long_term_frame_idx; + fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag = frame->mb_aff_frame_flag; + + frame->top_field = fs_top; + frame->bottom_field = fs_btm; + frame->frame = frame; + fs_top->bottom_field = fs_btm; + fs_top->frame = frame; + fs_top->top_field = fs_top; + fs_btm->top_field = fs_top; + fs_btm->frame = frame; + fs_btm->bottom_field = fs_btm; + + fs_top->is_mmco_5 = frame->is_mmco_5; + fs_btm->is_mmco_5 = frame->is_mmco_5; + fs_top->poc_mmco5 = frame->poc_mmco5; + fs_btm->poc_mmco5 = frame->poc_mmco5; + fs_top->top_poc_mmco5 = frame->top_poc_mmco5; + fs_btm->bot_poc_mmco5 = frame->bot_poc_mmco5; + + fs_top->view_id = fs_btm->view_id = fs->view_id; + fs_top->inter_view_flag = fs->inter_view_flag[0]; + fs_btm->inter_view_flag = fs->inter_view_flag[1]; + + fs_top->chroma_format_idc = fs_btm->chroma_format_idc = frame->chroma_format_idc; + fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType; + fs_top->slice_type = fs_btm->slice_type = frame->slice_type; + } else { + fs->top_field = NULL; + fs->bottom_field = NULL; + frame->top_field = NULL; + frame->bottom_field = NULL; + frame->frame = frame; + } + return ret = MPP_OK; +__FAILED: + mpp_mem_pool_put_f(p_Vid->pic_st, fs->top_field); + mpp_mem_pool_put_f(p_Vid->pic_st, fs->bottom_field); + fs->top_field = NULL; + fs->bottom_field = NULL; + return ret; +} + +static MPP_RET dpb_combine_field(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, RK_U8 combine_flag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, fs, combine_flag)); + fs->frame->layer_id = fs->layer_id; + fs->frame->view_id = fs->view_id; + fs->frame->iCodingType = fs->top_field->iCodingType; //FIELD_CODING; + fs->frame->frame_num = fs->top_field->frame_num; + fs->frame->is_output = fs->is_output; + fs->frame->slice_type = fs->slice_type; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET direct_output(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + memcpy(&p_Vid->old_pic, p, sizeof(H264_StorePic_t)); + p_Vid->last_pic = &p_Vid->old_pic; + if (p->structure == FRAME) { + //!< we have a frame (or complementary field pair), so output it directly + FUN_CHECK(ret = flush_direct_output(p_Vid)); + H264D_WARNNING("write frame, line %d", __LINE__); + write_picture(p, p_Vid); + p_Dpb->last_output_poc = p->poc; + free_storable_picture(p_Vid->p_Dec, p); + p_Dpb->last_picture = NULL; + p_Vid->out_buffer.is_used = 0; + p_Vid->out_buffer.is_directout = 0; + goto __RETURN; + } + + if (p->structure == TOP_FIELD) { + if (p_Vid->out_buffer.is_used & 1) { + FUN_CHECK(ret = flush_direct_output(p_Vid)); + } + p_Vid->out_buffer.top_field = p; + p_Vid->out_buffer.is_used |= 1; + p_Vid->out_buffer.frame_num = p->pic_num; + p_Vid->out_buffer.is_directout = 1; + p_Dpb->last_picture = &p_Vid->out_buffer; + } + + if (p->structure == BOTTOM_FIELD) { + if (p_Vid->out_buffer.is_used & 2) { + FUN_CHECK(ret = flush_direct_output(p_Vid)); + } + p_Vid->out_buffer.bottom_field = p; + p_Vid->out_buffer.is_used |= 2; + p_Vid->out_buffer.frame_num = p->pic_num; + p_Vid->out_buffer.is_directout = 1; + p_Dpb->last_picture = &p_Vid->out_buffer; + } + + if (p_Vid->out_buffer.is_used == 3) { + //!< we have both fields, so output them + FUN_CHECK(ret = dpb_combine_field_yuv(p_Vid, &p_Vid->out_buffer, 0)); + p_Vid->out_buffer.frame->view_id = p_Vid->out_buffer.view_id; + H264D_WARNNING("write frame, line %d", __LINE__); + write_picture(p_Vid->out_buffer.frame, p_Vid); + free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.frame); + p_Vid->out_buffer.frame = NULL; + free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.top_field); + p_Vid->out_buffer.top_field = NULL; + free_storable_picture(p_Vid->p_Dec, p_Vid->out_buffer.bottom_field); + p_Vid->out_buffer.bottom_field = NULL; + p_Vid->out_buffer.is_used = 0; + p_Vid->out_buffer.is_directout = 0; + p_Dpb->last_output_poc = p->poc; + p_Dpb->last_picture = NULL; + } + +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET output_dpb_normal(H264_DpbBuf_t *p_Dpb) +{ + MPP_RET ret = MPP_NOK; + RK_S32 min_poc = 0; + RK_S32 min_pos = 0; + RK_S32 poc_inc = 0; + + while ((p_Dpb->last_output_poc > INT_MIN) + && (get_smallest_poc(p_Dpb, &min_poc, &min_pos))) { + poc_inc = min_poc - p_Dpb->last_output_poc; + if ((p_Dpb->last_output_poc > INT_MIN) && (abs(poc_inc) & 0x1)) + p_Dpb->poc_interval = 1; + if ((min_poc - p_Dpb->last_output_poc) <= p_Dpb->poc_interval) { + FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, p_Dpb->fs[min_pos])); + } else { + break; + } + } + while (!remove_unused_frame_from_dpb(p_Dpb)); + + return MPP_OK; +__FAILED: + return ret; +} +static MPP_RET output_dpb_fastplay(H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs, RK_U32 is_i_frm) +{ + MPP_RET ret = MPP_NOK; + + if ((p_Dpb->p_Vid->dpb_fast_out && is_i_frm)) { + FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs)); + } else + output_dpb_normal(p_Dpb); + + return MPP_OK; +__FAILED: + return ret; +} +static MPP_RET output_dpb_fastplay_once(H264_DpbBuf_t *p_Dpb, H264_FrameStore_t *fs, RK_U32 is_i_frm) +{ + MPP_RET ret = MPP_NOK; + + if (p_Dpb->p_Vid->dpb_fast_out && is_i_frm && !p_Dpb->p_Vid->dpb_first_fast_played) { + FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs)); + p_Dpb->p_Vid->dpb_first_fast_played = 1; + } else { + // disable fast play once in the second gop + if (p_Dpb->p_Vid->dpb_fast_out && is_i_frm && p_Dpb->p_Vid->dpb_first_fast_played) { + p_Dpb->p_Vid->dpb_fast_out = MPP_DISABLE_FAST_PLAY; + } + output_dpb_normal(p_Dpb); + } + + return MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET scan_dpb_output(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + MPP_RET ret = MPP_NOK; + H264_FrameStore_t *fs = p_Dpb->fs[p_Dpb->used_size - 1]; + + if (fs->is_used == 3) { + H264dErrCtx_t *p_err = &p_Dpb->p_Vid->p_Dec->errctx; + RK_U32 is_i_frm = p_err->i_slice_no < 2 && p_Dpb->last_output_poc == INT_MIN; + + if (p_Dpb->p_Vid->p_Dec->cfg->base.fast_out) + FUN_CHECK(ret = write_stored_frame(p_Dpb->p_Vid, p_Dpb, fs)); + else { + switch (p_Dpb->p_Vid->p_Dec->cfg->base.enable_fast_play) { + case MPP_DISABLE_FAST_PLAY: + FUN_CHECK(ret = output_dpb_normal(p_Dpb)); + break; + case MPP_ENABLE_FAST_PLAY: + FUN_CHECK(ret = output_dpb_fastplay(p_Dpb, fs, is_i_frm)); + break; + case MPP_ENABLE_FAST_PLAY_ONCE: + FUN_CHECK(ret = output_dpb_fastplay_once(p_Dpb, fs, is_i_frm)); + break; + default: + H264D_ERR("unsupport output mode"); + } + } + + if (is_i_frm) + p_err->first_iframe_is_output = fs->is_output; + } + (void )p; + return MPP_OK; +__FAILED: + return ret; +} + +static void flush_one_dpb_mark(H264_DecCtx_t *p_Dec, H264_DpbMark_t *p_mark) +{ + if (NULL == p_mark) + return; + if (p_mark->out_flag && (p_mark->slot_idx >= 0)) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(p_Dec->frame_slots, p_mark->slot_idx, SLOT_FRAME_PTR, &mframe); + if (mframe) { + H264D_DBG(H264D_DBG_SLOT_FLUSH, "[DPB_BUF_FLUSH] slot_idx=%d, top_used=%d, bot_used=%d", + p_mark->slot_idx, p_mark->top_used, p_mark->bot_used); + mpp_frame_set_discard(mframe, 1); + mpp_buf_slot_set_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p_Dec->frame_slots, p_mark->slot_idx, QUEUE_DISPLAY); + mpp_buf_slot_clr_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_CODEC_USE); + p_Dec->last_frame_slot_idx = p_mark->slot_idx; + } + reset_dpb_mark(p_mark); + return; + } + H264D_DBG(H264D_DBG_WARNNING, "out_flag %d slot_idx %d\n", p_mark->out_flag, p_mark->slot_idx); +} + +/*! +*********************************************************************** +* \brief +* store picture to dpb +*********************************************************************** +*/ +//extern "C" +MPP_RET store_picture_in_dpb(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + RK_U32 max_buf_size = 0; + + VAL_CHECK(ret, NULL != p); //!< if frame, check for new store + //!< set use flag + if (p->mem_mark && (p->mem_mark->slot_idx >= 0)) { + mpp_buf_slot_set_flag(p_Vid->p_Dec->frame_slots, p->mem_mark->slot_idx, SLOT_CODEC_USE); + } else { + H264D_ERR("error, p->mem_mark == NULL"); + } + //!< deal with all frames in dpb + p_Vid->last_has_mmco_5 = 0; + p_Vid->last_pic_bottom_field = p->structure == BOTTOM_FIELD; + if (p->idr_flag) { + FUN_CHECK(ret = idr_memory_management(p_Dpb, p)); + } else { //!< adaptive memory management + if (p->used_for_reference && p->adaptive_ref_pic_buffering_flag) { + FUN_CHECK(ret = adaptive_memory_management(p_Dpb, p)); + } + } + //!< if necessary, combine top and botteom to frame + if (get_field_dpb_combine_flag(p_Dpb->last_picture, p)) { + if (p_Dpb->last_picture->is_directout) { + FUN_CHECK(ret = direct_output(p_Vid, p_Dpb, p)); //!< output frame + } else { + FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->last_picture, p, 1)); //!< field_dpb_combine + scan_dpb_output(p_Dpb, p); + } + memcpy(&p_Vid->old_pic, p, sizeof(H264_StorePic_t)); + p_Vid->last_pic = &p_Vid->old_pic; + p_Dpb->last_picture = NULL; + goto __RETURN; + } + //!< sliding window + if (!p->idr_flag && p->used_for_reference && !p->adaptive_ref_pic_buffering_flag) { + ASSERT(!p->idr_flag); + sliding_window_memory_management(p_Dpb); + p->is_long_term = 0; + } + while (!remove_unused_frame_from_dpb(p_Dpb)); + H264D_DBG(H264D_DBG_DPB_INFO, "before out, dpb[%d] used_size %d, size %d", + p_Dpb->layer_id, p_Dpb->used_size, p_Dpb->size); + //!< when full output one frame or more then setting max_buf_size + max_buf_size = p_Vid->p_Inp->max_buf_size; + if (max_buf_size) + H264D_DBG(H264D_DBG_DPB_INFO, "max_buf_size=%d\n", max_buf_size); + while (p_Dpb->used_size >= p_Dpb->size || + (max_buf_size && p_Dpb->used_size >= max_buf_size)) { + RK_S32 min_poc = 0, min_pos = 0; + RK_S32 find_flag = 0; + + remove_unused_frame_from_dpb(p_Dpb); + find_flag = get_smallest_poc(p_Dpb, &min_poc, &min_pos); + if (!p->used_for_reference) { + if ((!find_flag) || (p->poc < min_poc)) { + FUN_CHECK(ret = direct_output(p_Vid, p_Dpb, p)); //!< output frame + goto __RETURN; + } + } + //!< used for reference, but not find, then flush a frame in the first + if ((!find_flag) || (p->poc < min_poc)) { + min_pos = 0; + unmark_for_reference(p_Vid->p_Dec, p_Dpb->fs[min_pos]); + if (!p_Dpb->fs[min_pos]->is_output) { + H264D_WARNNING("write_stored_frame, line %d", __LINE__); + FUN_CHECK(ret = write_stored_frame(p_Vid, p_Dpb, p_Dpb->fs[min_pos])); + } + FUN_CHECK(ret = remove_frame_from_dpb(p_Dpb, min_pos)); + p->is_long_term = 0; + } else { + FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb)); + } + } + H264D_DBG(H264D_DBG_DPB_INFO, "after out, dpb[%d] used_size %d, size %d", + p_Dpb->layer_id, p_Dpb->used_size, p_Dpb->size); + //!< store current decoder picture at end of dpb + FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, p_Dpb->fs[p_Dpb->used_size], p, 0)); + if (p->structure != FRAME) { + p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size]; + } else { + p_Dpb->last_picture = NULL; + } + memcpy(&p_Vid->old_pic, p, sizeof(H264_StorePic_t)); + p_Vid->last_pic = &p_Vid->old_pic; + + p_Dpb->used_size++; + H264D_DBG(H264D_DBG_DPB_INFO, "[DPB_size] p_Dpb->used_size=%d", p_Dpb->used_size); + if (!p_Vid->p_Dec->mvc_valid) + scan_dpb_output(p_Dpb, p); + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + +__RETURN: + return ret = MPP_OK; +__FAILED: + flush_one_dpb_mark(p_Vid->p_Dec, p->mem_mark); + return ret; +} + +/*! +*********************************************************************** +* \brief +* free frame store picture +*********************************************************************** +*/ +//extern "C" +void free_frame_store(H264_DecCtx_t *p_Dec, H264_FrameStore_t* f) +{ + if (f) { + if (f->frame) { + free_storable_picture(p_Dec, f->frame); + f->frame = NULL; + } + if (f->top_field) { + free_storable_picture(p_Dec, f->top_field); + f->top_field = NULL; + } + if (f->bottom_field) { + free_storable_picture(p_Dec, f->bottom_field); + f->bottom_field = NULL; + } + MPP_FREE(f); + } +} + +/*! +*********************************************************************** +* \brief +* free dpb +*********************************************************************** +*/ +//extern "C" +void free_dpb(H264_DpbBuf_t *p_Dpb) +{ + RK_U32 i = 0; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + if (p_Dpb->fs) { + for (i = 0; i < p_Dpb->allocated_size; i++) { + free_frame_store(p_Vid->p_Dec, p_Dpb->fs[i]); + p_Dpb->fs[i] = NULL; + } + MPP_FREE(p_Dpb->fs); + } + MPP_FREE(p_Dpb->fs_ref); + MPP_FREE(p_Dpb->fs_ltref); + if (p_Dpb->fs_ilref) { + for (i = 0; i < 1; i++) { + free_frame_store(p_Vid->p_Dec, p_Dpb->fs_ilref[i]); + p_Dpb->fs_ilref[i] = NULL; + } + MPP_FREE(p_Dpb->fs_ilref); + } + p_Dpb->last_output_view_id = -1; + p_Dpb->last_output_poc = INT_MIN; + p_Dpb->init_done = 0; + if (p_Vid->no_ref_pic) { + free_storable_picture(p_Vid->p_Dec, p_Vid->no_ref_pic); + p_Vid->no_ref_pic = NULL; + } +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +void update_ref_list(H264_DpbBuf_t *p_Dpb) +{ + RK_U8 i = 0, j = 0; + for (i = 0, j = 0; i < p_Dpb->used_size; i++) { + if (is_short_term_reference(p_Dpb->fs[i])) { + p_Dpb->fs_ref[j++] = p_Dpb->fs[i]; + } + } + + p_Dpb->ref_frames_in_buffer = j; + + while (j < p_Dpb->size) { + p_Dpb->fs_ref[j++] = NULL; + } +} +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +void update_ltref_list(H264_DpbBuf_t *p_Dpb) +{ + RK_U8 i = 0, j = 0; + for (i = 0, j = 0; i < p_Dpb->used_size; i++) { + if (is_long_term_reference(p_Dpb->fs[i])) { + p_Dpb->fs_ltref[j++] = p_Dpb->fs[i]; + } + } + + p_Dpb->ltref_frames_in_buffer = j; + + while (j < p_Dpb->size) { + p_Dpb->fs_ltref[j++] = NULL; + } +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +MPP_RET idr_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + RK_U32 i = 0; + RK_S32 type = -1; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dErrCtx_t *p_err = &p_Dpb->p_Vid->p_Dec->errctx; + + if (p->no_output_of_prior_pics_flag) { + //!< free all stored pictures + for (i = 0; i < p_Dpb->used_size; i++) { + //!< reset all reference settings + //Set is_output flag to true to avoid real output this frame to + //display queue. These frames will be mark as unused and remove from + //dpb at flush_dpb + p_Dpb->fs[i]->is_output = 1; + } + } + + type = (p->layer_id == 0) ? 1 : 2; + FUN_CHECK(ret = flush_dpb(p_Dpb, type)); + + p_Dpb->last_picture = NULL; + + update_ref_list(p_Dpb); + update_ltref_list(p_Dpb); + p_Dpb->last_output_poc = INT_MIN; + p_err->i_slice_no = 1; + + if (p->long_term_reference_flag) { + p_Dpb->max_long_term_pic_idx = 0; + p->is_long_term = 1; + p->long_term_frame_idx = 0; + } else { + p_Dpb->max_long_term_pic_idx = -1; + p->is_long_term = 0; + } + p_Dpb->last_output_view_id = -1; + + return ret = MPP_OK; + +__FAILED: + for (i = 0; i < p_Dpb->used_size; i++) { // when error and free malloc buf + free_frame_store(p_Dpb->p_Vid->p_Dec, p_Dpb->fs[i]); + } + return ret; +} + + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +MPP_RET insert_picture_in_dpb(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, H264_StorePic_t *p, RK_U8 combine_flag) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + ASSERT(p != NULL); + ASSERT(fs != NULL); + + switch (p->structure) { + case FRAME: + fs->frame = p; + fs->is_used = 3; + if (p->used_for_reference) { + fs->is_reference = 3; + fs->is_orig_reference = 3; + if (p->is_long_term) { + fs->is_long_term = 3; + fs->long_term_frame_idx = p->long_term_frame_idx; + } + } + fs->inter_view_flag[0] = fs->inter_view_flag[1] = p->inter_view_flag; + fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] = p->anchor_pic_flag; + FUN_CHECK(ret = dpb_split_field(p_Vid, fs)); + fs->poc = p->poc; + break; + case TOP_FIELD: + fs->top_field = p; + fs->is_used |= 1; + fs->inter_view_flag[0] = p->inter_view_flag; + fs->anchor_pic_flag[0] = p->anchor_pic_flag; + if (p->used_for_reference) { + fs->is_reference |= 1; + fs->is_orig_reference |= 1; + if (p->is_long_term) { + fs->is_long_term |= 1; + fs->long_term_frame_idx = p->long_term_frame_idx; + } + } + if (fs->is_used == 3) { + FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag)); + } else { + fs->poc = p->poc; + } + break; + case BOTTOM_FIELD: + fs->bottom_field = p; + fs->is_used |= 2; + fs->inter_view_flag[1] = p->inter_view_flag; + fs->anchor_pic_flag[1] = p->anchor_pic_flag; + if (p->used_for_reference) { + fs->is_reference |= 2; + fs->is_orig_reference |= 2; + if (p->is_long_term) { + fs->is_long_term |= 2; + fs->long_term_frame_idx = p->long_term_frame_idx; + } + } + if (fs->is_used == 3) { + FUN_CHECK(ret = dpb_combine_field(p_Vid, fs, combine_flag)); + } else { + fs->poc = p->poc; + } + break; + } + fs->layer_id = p->layer_id; + fs->view_id = p->view_id; + fs->frame_num = p->pic_num; + fs->is_output = p->is_output; + fs->slice_type = p->slice_type; + fs->structure = p->structure; + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +void free_storable_picture(H264_DecCtx_t *p_Dec, H264_StorePic_t *p) +{ + if (p) { + if (p->mem_malloc_type == Mem_Malloc + || p->mem_malloc_type == Mem_Clone) { + free_dpb_mark(p_Dec, p->mem_mark, p->structure); + } + if (p->mem_malloc_type == Mem_TopOnly) { + free_dpb_mark(p_Dec, p->mem_mark, TOP_FIELD); + } + if (p->mem_malloc_type == Mem_BotOnly) { + free_dpb_mark(p_Dec, p->mem_mark, BOTTOM_FIELD); + } + mpp_mem_pool_put_f(p_Dec->p_Vid->pic_st, p); + } +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +H264_StorePic_t *alloc_storable_picture(H264dVideoCtx_t *p_Vid, RK_S32 structure) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *s = mpp_mem_pool_get_f(p_Vid->pic_st); + + MEM_CHECK(ret, s); + s->view_id = -1; + s->structure = structure; + (void)p_Vid; + + return s; +__FAILED: + (void)ret; + return NULL; +} + +/*! +*********************************************************************** +* \brief +* alloc one picture +*********************************************************************** +*/ +//extern "C" +RK_U32 get_field_dpb_combine_flag(H264_FrameStore_t *p_last, H264_StorePic_t *p) +{ + RK_U32 combine_flag = 0; + + if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) { + // check for frame store with same pic_number + if (p_last) { + if ((RK_S32)p_last->frame_num == p->pic_num) { + if (((p->structure == TOP_FIELD) && (p_last->is_used == 2)) + || ((p->structure == BOTTOM_FIELD) && (p_last->is_used == 1))) { +#if 1 + if ((p->used_for_reference && p_last->is_orig_reference) || + (!p->used_for_reference && !p_last->is_orig_reference)) { + combine_flag = 1; + } +#else + combine_flag = 1; +#endif + } + } + /* set err to unpaired filed */ + if (!combine_flag) { + struct h264_store_pic_t *pic = NULL; + + pic = p_last->structure == TOP_FIELD ? p_last->top_field : p_last->bottom_field; + if (pic && pic->mem_mark->mframe && !pic->combine_flag) + mpp_frame_set_errinfo(pic->mem_mark->mframe, 1); + } + } + } + return combine_flag; +} + +static MPP_RET enlarge_dpb(H264_DpbBuf_t *p_Dpb, RK_U32 size) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + void *tmp; + + if (!p_Dpb || !size || !p_Dpb->init_done) + return MPP_ERR_VALUE; + + if (p_Dpb->size >= size) { + H264D_WARNNING("DPB could not be shrinked!\n"); + return MPP_ERR_VALUE; + } + + tmp = mpp_calloc(H264_FrameStore_t*, size); + memcpy(tmp, p_Dpb->fs, sizeof(H264_FrameStore_t*) * p_Dpb->size); + mpp_free(p_Dpb->fs); + p_Dpb->fs = tmp; + + tmp = mpp_calloc(H264_FrameStore_t*, size); + memcpy(tmp, p_Dpb->fs_ref, sizeof(H264_FrameStore_t*) * p_Dpb->size); + mpp_free(p_Dpb->fs_ref); + p_Dpb->fs_ref = tmp; + + tmp = mpp_calloc(H264_FrameStore_t*, size); + memcpy(tmp, p_Dpb->fs_ltref, sizeof(H264_FrameStore_t*) * p_Dpb->size); + mpp_free(p_Dpb->fs_ltref); + p_Dpb->fs_ltref = tmp; + + tmp = mpp_calloc(H264_FrameStore_t*, size); + memcpy(tmp, p_Dpb->fs_ilref, sizeof(H264_FrameStore_t*) * p_Dpb->size); + mpp_free(p_Dpb->fs_ilref); + p_Dpb->fs_ilref = tmp; + + for (i = p_Dpb->size; i < size; i++) { + p_Dpb->fs[i] = alloc_frame_store(); + MEM_CHECK(ret, p_Dpb->fs[i]); + p_Dpb->fs_ref[i] = NULL; + p_Dpb->fs_ltref[i] = NULL; + p_Dpb->fs[i]->layer_id = -1; + p_Dpb->fs[i]->view_id = -1; + p_Dpb->fs[i]->inter_view_flag[0] = p_Dpb->fs[i]->inter_view_flag[1] = 0; + p_Dpb->fs[i]->anchor_pic_flag[0] = p_Dpb->fs[i]->anchor_pic_flag[1] = 0; + } + + p_Dpb->size = size; + p_Dpb->allocated_size = size; + return ret = MPP_OK; + +__FAILED: + return ret; +} + +MPP_RET check_mvc_dpb(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb_layer_0, H264_DpbBuf_t* p_Dpb_layer_1) +{ + MPP_RET ret = MPP_OK; + + if (!p_Vid || !p_Dpb_layer_0 || !p_Dpb_layer_1 || !p_Dpb_layer_0->init_done) { + return ret = MPP_ERR_VALUE; + } + + H264D_DBG(H264D_DBG_DPB_INFO, "p_Dpb[0].size %d vs p_Dpb[1].size %d\n", + p_Dpb_layer_0->size, p_Dpb_layer_1->size); + + p_Dpb_layer_0->size = MPP_MIN(p_Dpb_layer_0->size, MAX_DPB_SIZE / 2); + p_Dpb_layer_1->size = MPP_MIN(p_Dpb_layer_1->size, MAX_DPB_SIZE / 2); + + if (p_Dpb_layer_0->size == p_Dpb_layer_1->size) { + ret = MPP_OK; + } else if (p_Dpb_layer_0->size > p_Dpb_layer_1->size) { + ret = enlarge_dpb(p_Dpb_layer_1, p_Dpb_layer_0->size); + H264D_DBG(H264D_DBG_DPB_INFO, "Enlarge DPB[1] to %d", p_Dpb_layer_0->size); + } else { + ret = enlarge_dpb(p_Dpb_layer_0, p_Dpb_layer_1->size); + H264D_DBG(H264D_DBG_DPB_INFO, "Enlarge DPB[0] to %d", p_Dpb_layer_1->size); + } + + p_Vid->dpb_size[0] = p_Dpb_layer_0->size; + p_Vid->dpb_size[1] = p_Dpb_layer_1->size; + + return ret; +} + +/*! +*********************************************************************** +* \brief +* init dpb +*********************************************************************** +*/ +//extern "C" +MPP_RET init_dpb(H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, RK_S32 type) // type=1 AVC type=2 MVC +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_SPS_t *active_sps = p_Vid->active_sps; + RK_U32 dpb_size; + + if (!active_sps) { + ret = MPP_NOK; + goto __FAILED; + } + p_Dpb->p_Vid = p_Vid; + if (p_Dpb->init_done) { + free_dpb(p_Dpb); + } + dpb_size = getDpbSize(p_Vid, active_sps); + p_Dpb->size = MPP_MAX(1, dpb_size); + p_Dpb->allocated_size = p_Dpb->size; + p_Dpb->num_ref_frames = active_sps->max_num_ref_frames; + if (active_sps->max_dec_frame_buffering < active_sps->max_num_ref_frames) { + H264D_WARNNING("DPB size at specified level is smaller than reference frames"); + } + p_Dpb->used_size = 0; + p_Dpb->last_picture = NULL; + p_Dpb->ref_frames_in_buffer = 0; + p_Dpb->ltref_frames_in_buffer = 0; + //-------- + p_Dpb->fs = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + p_Dpb->fs_ref = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + p_Dpb->fs_ltref = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + p_Dpb->fs_ilref = mpp_calloc(H264_FrameStore_t*, 1); //!< inter-layer reference (for multi-layered codecs) + MEM_CHECK(ret, p_Dpb->fs && p_Dpb->fs_ref && p_Dpb->fs_ltref && p_Dpb->fs_ilref); + for (i = 0; i < p_Dpb->size; i++) { + p_Dpb->fs[i] = alloc_frame_store(); + MEM_CHECK(ret, p_Dpb->fs[i]); + p_Dpb->fs_ref[i] = NULL; + p_Dpb->fs_ltref[i] = NULL; + p_Dpb->fs[i]->layer_id = -1; + p_Dpb->fs[i]->view_id = -1; + p_Dpb->fs[i]->inter_view_flag[0] = p_Dpb->fs[i]->inter_view_flag[1] = 0; + p_Dpb->fs[i]->anchor_pic_flag[0] = p_Dpb->fs[i]->anchor_pic_flag[1] = 0; + } + if (type == 2) { + p_Dpb->fs_ilref[0] = alloc_frame_store(); + MEM_CHECK(ret, p_Dpb->fs_ilref[0]); + //!< These may need some cleanups + p_Dpb->fs_ilref[0]->view_id = -1; + p_Dpb->fs_ilref[0]->inter_view_flag[0] = p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0; + p_Dpb->fs_ilref[0]->anchor_pic_flag[0] = p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0; + //!< given that this is in a different buffer, do we even need proc_flag anymore? + } else { + p_Dpb->fs_ilref[0] = NULL; + } + //!< allocate a dummy storable picture + if (!p_Vid->no_ref_pic) { + p_Vid->no_ref_pic = alloc_storable_picture(p_Vid, FRAME); + MEM_CHECK(ret, p_Vid->no_ref_pic); + p_Vid->no_ref_pic->top_field = p_Vid->no_ref_pic; + p_Vid->no_ref_pic->bottom_field = p_Vid->no_ref_pic; + p_Vid->no_ref_pic->frame = p_Vid->no_ref_pic; + } + p_Dpb->last_output_poc = INT_MIN; + p_Dpb->last_output_view_id = -1; + p_Vid->last_has_mmco_5 = 0; + p_Dpb->init_done = 1; + + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief +* flush dpb +*********************************************************************** +*/ +//extern "C" +MPP_RET flush_dpb(H264_DpbBuf_t *p_Dpb, RK_S32 type) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Dpb); + //!< diagnostics + if (!p_Dpb->init_done) { + goto __RETURN; + } + H264D_DBG(H264D_DBG_DPB_INFO, "dpb layer %d, used_size %d", + p_Dpb->layer_id, p_Dpb->used_size); + //!< mark all frames unused + for (i = 0; i < p_Dpb->used_size; i++) { + if (p_Dpb->fs[i] && p_Dpb->p_Vid) { + VAL_CHECK(ret, p_Dpb->fs[i]->layer_id == p_Dpb->layer_id); + unmark_for_reference(p_Dpb->p_Vid->p_Dec, p_Dpb->fs[i]); + } + } + while (!remove_unused_frame_from_dpb(p_Dpb)); + //!< output frames in POC order + while (p_Dpb->used_size) { + FUN_CHECK(ret = output_one_frame_from_dpb(p_Dpb)); + } + p_Dpb->last_output_poc = INT_MIN; + (void)type; +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief +* write out all frames +*********************************************************************** +*/ +//extern "C" +MPP_RET output_dpb(H264_DecCtx_t *p_Dec, H264_DpbBuf_t *p_Dpb) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + while (!remove_unused_frame_from_dpb(p_Dpb)); + + (void)p_Dec; + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET exit_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t **dec_pic) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + //!< return if the last picture has already been finished + if (!(*dec_pic) || !p_Vid->exit_picture_flag + || !p_Vid->have_outpicture_flag || !p_Vid->iNumOfSlicesDecoded) { + goto __RETURN; + } + FUN_CHECK(ret = store_picture_in_dpb(p_Vid->p_Dpb_layer[(*dec_pic)->layer_id], *dec_pic)); + *dec_pic = NULL; + +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_dpb.h b/mpp/codec/dec/h264/h264d_dpb.h index 128c2b0ec..9387bed9c 100644 --- a/mpp/codec/dec/h264/h264d_dpb.h +++ b/mpp/codec/dec/h264/h264d_dpb.h @@ -1,54 +1,57 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef _H264D_DPB_H_ -#define _H264D_DPB_H_ - - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_global.h" - - -#ifdef __cplusplus -extern "C" { -#endif -void update_ref_list(H264_DpbBuf_t *p_Dpb); -void update_ltref_list(H264_DpbBuf_t *p_Dpb); -void free_storable_picture(H264_StorePic_t *p); -void free_frame_store(H264_FrameStore_t *f); - -MPP_RET idr_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p); -MPP_RET insert_picture_in_dpb(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, H264_StorePic_t *p, RK_U8 combine_flag); - -MPP_RET init_dpb (H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, RK_S32 type); -MPP_RET flush_dpb(H264_DpbBuf_t *p_Dpb); -MPP_RET update_dpb(H264_DecCtx_t *p_Dec); -void free_dpb (H264_DpbBuf_t *p_Dpb); -MPP_RET exit_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t **dec_picture); -MPP_RET prepare_init_dpb_info(H264_SLICE_t *currSlice); - -RK_U32 get_filed_dpb_combine_flag(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p); -H264_StorePic_t *alloc_storable_picture(H264dVideoCtx_t *p_Vid, RK_S32 structure); - -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of _H264D_DPB_H_ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_DPB_H +#define H264D_DPB_H + + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +void update_ref_list(H264_DpbBuf_t *p_Dpb); +void update_ltref_list(H264_DpbBuf_t *p_Dpb); +void free_storable_picture(H264_DecCtx_t *p_Dec, H264_StorePic_t *p); +void free_frame_store(H264_DecCtx_t *p_Dec, H264_FrameStore_t *f); + +MPP_RET idr_memory_management(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p); +MPP_RET insert_picture_in_dpb(H264dVideoCtx_t *p_Vid, H264_FrameStore_t *fs, H264_StorePic_t *p, RK_U8 combine_flag); +MPP_RET store_picture_in_dpb (H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p); + +MPP_RET check_mvc_dpb(H264dVideoCtx_t*p_Vid, H264_DpbBuf_t *p_Dpb_layer_0, H264_DpbBuf_t* p_Dpb_layer_1); +MPP_RET init_dpb (H264dVideoCtx_t *p_Vid, H264_DpbBuf_t *p_Dpb, RK_S32 type); +MPP_RET flush_dpb (H264_DpbBuf_t *p_Dpb, RK_S32 type); +MPP_RET output_dpb (H264_DecCtx_t *p_Dec, H264_DpbBuf_t *p_Dpb); + +void free_dpb (H264_DpbBuf_t *p_Dpb); +MPP_RET exit_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t **dec_pic); + +RK_U32 get_field_dpb_combine_flag(H264_FrameStore_t *p_last, H264_StorePic_t *p); +H264_StorePic_t *alloc_storable_picture(H264dVideoCtx_t *p_Vid, RK_S32 structure); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* H264D_DPB_H */ + diff --git a/mpp/codec/dec/h264/h264d_fill.c b/mpp/codec/dec/h264/h264d_fill.c index 303314301..1690f1d7c 100644 --- a/mpp/codec/dec/h264/h264d_fill.c +++ b/mpp/codec/dec/h264/h264d_fill.c @@ -1,383 +1,401 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include - -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "h264d_fill.h" - -#define MODULE_TAG "h264d_fill" - -#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) -#define ALIGN(x, a) ( ((x) + (a) - 1) & (~((a) - 1)) ) - -static const RK_U8 start_code[3] = { 0, 0, 1 }; - - -static MPP_RET realloc_slice_list(H264dDxvaCtx_t *dxva_ctx) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - dxva_ctx->max_slice_size += ADD_SLICE_SIZE; - dxva_ctx->slice_long = mpp_realloc(dxva_ctx->slice_long, DXVA_Slice_H264_Long, dxva_ctx->max_slice_size); - MEM_CHECK(ret, dxva_ctx->slice_long); - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - - -static MPP_RET realloc_stream_buffer(H264dDxvaCtx_t *dxva_ctx, RK_U32 stream_add) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - if (stream_add > FRAME_BUF_ADD_SIZE) { - dxva_ctx->max_strm_size += ALIGN(stream_add, 128); - } else { - dxva_ctx->max_strm_size += FRAME_BUF_ADD_SIZE; - } - dxva_ctx->bitstream = mpp_realloc(dxva_ctx->bitstream, RK_U8, dxva_ctx->max_strm_size); - MEM_CHECK (ret, dxva_ctx->bitstream); - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET fill_stream_data(H264dDxvaCtx_t *dxva_ctx, H264_Nalu_t *p_nal) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - RK_U32 stream_offset = 0; - RK_U32 streamlen_add = 0; - DXVA_Slice_H264_Long *p_long = NULL; - - if (dxva_ctx->slice_count >= dxva_ctx->max_slice_size) { - FUN_CHECK(ret = realloc_slice_list(dxva_ctx)); - } - streamlen_add = p_nal->sodb_len + sizeof(start_code); - stream_offset = dxva_ctx->strm_offset + streamlen_add; - if (stream_offset > dxva_ctx->max_strm_size) { - FUN_CHECK (ret = realloc_stream_buffer(dxva_ctx, streamlen_add)); - } - p_long = &dxva_ctx->slice_long[dxva_ctx->slice_count]; - memset(p_long, 0, sizeof(DXVA_Slice_H264_Long)); - p_long->BSNALunitDataLocation = dxva_ctx->strm_offset; - p_long->wBadSliceChopping = 0; //!< set to 0 in Rock-Chip RKVDEC IP - memcpy(&dxva_ctx->bitstream[dxva_ctx->strm_offset], start_code, sizeof(start_code)); - dxva_ctx->strm_offset += sizeof(start_code); - memcpy(&dxva_ctx->bitstream[dxva_ctx->strm_offset], p_nal->sodb_buf, p_nal->sodb_len); - dxva_ctx->strm_offset += p_nal->sodb_len; - p_long->SliceBytesInBuffer = dxva_ctx->strm_offset - p_long->BSNALunitDataLocation; - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static void fill_picture_entry(DXVA_PicEntry_H264 *pic, RK_U32 index, RK_U32 flag) -{ - ASSERT((index & 0x7f) == index && (flag & 0x01) == flag); - pic->bPicEntry = index | (flag << 7); -} - - -/*! -*********************************************************************** -* \brief -* fill picture parameters -*********************************************************************** -*/ -//extern "C" -void fill_qmatrix(H264dVideoCtx_t *p_Vid, DXVA_Qmatrix_H264 *qm) -{ - RK_S32 i = 0, j = 0; - - memset(qm, 0, sizeof(DXVA_Qmatrix_H264)); - for (i = 0; i < 6; ++i) { //!< 4x4, 6 lists - for (j = 0; j < H264ScalingList4x4Length; j++) { - qm->bScalingLists4x4[i][j] = p_Vid->qmatrix[i][j]; - } - } - for (i = 6; i < ((p_Vid->active_sps->chroma_format_idc != YUV444) ? 8 : 12); ++i) { - for (j = 0; j < H264ScalingList8x8Length; j++) { - qm->bScalingLists8x8[i - 6][j] = p_Vid->qmatrix[i][j]; - } - } -} -/*! -*********************************************************************** -* \brief -* fill picture parameters -*********************************************************************** -*/ -//extern "C" -void fill_picparams(H264dVideoCtx_t *p_Vid, DXVA_PicParams_H264_MVC *pp) -{ - RK_U32 i = 0, j = 0, num_views = 0; - H264_StorePic_t *dec_picture = p_Vid->dec_picture; - H264_DpbInfo_t *dpb_info = p_Vid->p_Dec->dpb_info; - - memset(pp, 0, sizeof(DXVA_PicParams_H264_MVC)); - //!< Configure current picture - fill_picture_entry(&pp->CurrPic, dec_picture->mem_mark->index, dec_picture->structure == BOTTOM_FIELD); - - //!< Configure the set of references - pp->UsedForReferenceFlags = 0; - pp->NonExistingFrameFlags = 0; - - for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) { - if (dpb_info[i].picbuf) { - fill_picture_entry(&pp->RefFrameList[i], dpb_info[i].mem_mark_idx, dpb_info[i].is_long_term); - pp->FieldOrderCntList[i][0] = dpb_info[i].TOP_POC; - pp->FieldOrderCntList[i][1] = dpb_info[i].BOT_POC; - pp->FrameNumList[i] = dpb_info[i].frame_num_wrap; - if (dpb_info[i].is_used & 0x01) { //!< top_field - pp->UsedForReferenceFlags |= 1 << (2 * i + 0); - } - if (dpb_info[i].is_used & 0x02) { //!< bot_field - pp->UsedForReferenceFlags |= 1 << (2 * i + 1); - } - } else { - pp->RefFrameList[i].bPicEntry = 0xff; - pp->FieldOrderCntList[i][0] = 0; - pp->FieldOrderCntList[i][1] = 0; - pp->FrameNumList[i] = 0; - } - } - pp->wFrameWidthInMbsMinus1 = p_Vid->active_sps->pic_width_in_mbs_minus1; - pp->wFrameHeightInMbsMinus1 = p_Vid->active_sps->pic_height_in_map_units_minus1; - pp->num_ref_frames = p_Vid->active_sps->max_num_ref_frames; - - pp->wBitFields = ((dec_picture->iCodingType == FIELD_CODING) << 0) //!< field_pic_flag - | (dec_picture->mb_aff_frame_flag << 1) //!< MbaffFrameFlag - | (0 << 2) //!< residual_colour_transform_flag - | (0 << 3) //!< sp_for_switch_flag - | (p_Vid->active_sps->chroma_format_idc << 4) //!< chroma_format_idc - | (dec_picture->used_for_reference << 6) //!< RefPicFlag - | (p_Vid->active_pps->constrained_intra_pred_flag << 7) //!< constrained_intra_pred_flag - | (p_Vid->active_pps->weighted_pred_flag << 8) //!< weighted_pred_flag - | (p_Vid->active_pps->weighted_bipred_idc << 9) //!< weighted_bipred_idc - | (1 << 11) //!< MbsConsecutiveFlag - | (p_Vid->active_sps->frame_mbs_only_flag << 12) //!< frame_mbs_only_flag - | (p_Vid->active_pps->transform_8x8_mode_flag << 13) //!< transform_8x8_mode_flag - | ((p_Vid->active_sps->level_idc >= 31) << 14) //!< MinLumaBipredSize8x8Flag - | (1 << 15); //!< IntraPicFlag (Modified if we detect a non-intra slice in dxva2_h264_decode_slice) - - pp->bit_depth_luma_minus8 = p_Vid->active_sps->bit_depth_luma_minus8; - pp->bit_depth_chroma_minus8 = p_Vid->active_sps->bit_depth_chroma_minus8; - pp->Reserved16Bits = 3; //!< FIXME is there a way to detect the right mode - - pp->StatusReportFeedbackNumber = 1 /*+ ctx->report_id++*/; - - pp->CurrFieldOrderCnt[0] = 0; - if (dec_picture->structure == TOP_FIELD || dec_picture->structure == FRAME) { - pp->CurrFieldOrderCnt[0] = dec_picture->top_poc; - } - pp->CurrFieldOrderCnt[1] = 0; - if (dec_picture->structure == BOTTOM_FIELD || dec_picture->structure == FRAME) { - pp->CurrFieldOrderCnt[1] = dec_picture->bottom_poc; - } - pp->pic_init_qs_minus26 = p_Vid->active_pps->pic_init_qs_minus26; - pp->chroma_qp_index_offset = p_Vid->active_pps->chroma_qp_index_offset; - pp->second_chroma_qp_index_offset = p_Vid->active_pps->second_chroma_qp_index_offset; - pp->ContinuationFlag = 1; - pp->pic_init_qp_minus26 = p_Vid->active_pps->pic_init_qp_minus26; - pp->num_ref_idx_l0_active_minus1 = p_Vid->active_pps->num_ref_idx_l0_default_active_minus1; - pp->num_ref_idx_l1_active_minus1 = p_Vid->active_pps->num_ref_idx_l1_default_active_minus1; - pp->Reserved8BitsA = 0; - - pp->frame_num = dec_picture->frame_num; - pp->log2_max_frame_num_minus4 = p_Vid->active_sps->log2_max_frame_num_minus4; - pp->pic_order_cnt_type = p_Vid->active_sps->pic_order_cnt_type; - if (pp->pic_order_cnt_type == 0) { - pp->log2_max_pic_order_cnt_lsb_minus4 = p_Vid->active_sps->log2_max_pic_order_cnt_lsb_minus4; - } else if (pp->pic_order_cnt_type == 1) { - pp->delta_pic_order_always_zero_flag = p_Vid->active_sps->delta_pic_order_always_zero_flag; - } - pp->direct_8x8_inference_flag = p_Vid->active_sps->direct_8x8_inference_flag; - pp->entropy_coding_mode_flag = p_Vid->active_pps->entropy_coding_mode_flag; - pp->pic_order_present_flag = p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag; - pp->num_slice_groups_minus1 = p_Vid->active_pps->num_slice_groups_minus1; - pp->slice_group_map_type = p_Vid->active_pps->slice_group_map_type; - pp->deblocking_filter_control_present_flag = p_Vid->active_pps->deblocking_filter_control_present_flag; - pp->redundant_pic_cnt_present_flag = p_Vid->active_pps->redundant_pic_cnt_present_flag; - pp->Reserved8BitsB = 0; - pp->slice_group_change_rate_minus1 = 0; //!< XXX not implemented by FFmpeg - //pp->SliceGroupMap[810]; //!< XXX not implemented by FFmpeg - - //!< Following are H.264 MVC Specific parameters - if (p_Vid->active_subsps) { - pp->num_views_minus1 = p_Vid->active_subsps->num_views_minus1; - num_views = 1 + pp->num_views_minus1; - ASSERT(num_views <= 16); - for (i = 0; i < num_views; i++) { - pp->view_id[i] = p_Vid->active_subsps->view_id[i]; - pp->num_anchor_refs_l0[i] = p_Vid->active_subsps->num_anchor_refs_l0[i]; - for (j = 0; j < pp->num_anchor_refs_l0[i]; j++) { - pp->anchor_ref_l0[i][j] = p_Vid->active_subsps->anchor_ref_l0[i][j]; - } - pp->num_anchor_refs_l1[i] = p_Vid->active_subsps->num_anchor_refs_l1[i]; - for (j = 0; j < pp->num_anchor_refs_l1[i]; j++) { - pp->anchor_ref_l1[i][j] = p_Vid->active_subsps->anchor_ref_l1[i][j]; - } - pp->num_non_anchor_refs_l0[i] = p_Vid->active_subsps->num_non_anchor_refs_l0[i]; - for (j = 0; j < pp->num_non_anchor_refs_l0[i]; j++) { - pp->non_anchor_ref_l0[i][j] = p_Vid->active_subsps->non_anchor_ref_l0[i][j]; - } - pp->num_non_anchor_refs_l1[i] = p_Vid->active_subsps->num_non_anchor_refs_l1[i]; - for (j = 0; j < pp->num_non_anchor_refs_l1[i]; j++) { - pp->non_anchor_ref_l1[i][j] = p_Vid->active_subsps->non_anchor_ref_l1[i][j]; - } - } - for (i = num_views; i < 16; i++) { - pp->view_id[i] = 0xffff; - } - } - pp->curr_view_id = dec_picture->view_id; - pp->anchor_pic_flag = dec_picture->anchor_pic_flag; - pp->inter_view_flag = dec_picture->inter_view_flag; - for (i = 0; i < 16; i++) { - pp->ViewIDList[i] = p_Vid->p_Dec->dpb_info[i].view_id; - } - //!< add in Rock-chip RKVDEC IP - for (i = 0; i < 16; i++) { - if (p_Vid->p_Dec->dpb_info[i].colmv_is_used) { - pp->RefPicColmvUsedFlags |= 1 << i; - } - if (p_Vid->p_Dec->dpb_info[i].field_flag) { - pp->RefPicFiledFlags |= 1 << i; - } - pp->RefPicLayerIdList[i] = p_Vid->p_Dec->dpb_info[i].voidx; - } - if (p_Vid->active_pps->pic_scaling_matrix_present_flag - || p_Vid->active_sps->seq_scaling_matrix_present_flag) { - pp->scaleing_list_enable_flag = 1; - } else { - pp->scaleing_list_enable_flag = 0; - } -} - -/*! -*********************************************************************** -* \brief -* fill slice short struct -*********************************************************************** -*/ -//extern "C" -MPP_RET fill_slice(H264_SLICE_t *currSlice, H264dDxvaCtx_t *dxva_ctx) -{ - RK_U32 list = 0, i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - DXVA_Slice_H264_Long *p_long = NULL; - RK_S32 dpb_idx = 0, dpb_valid = 0, bottom_flag = 0; - - FUN_CHECK(ret = fill_stream_data(dxva_ctx, &currSlice->p_Cur->nalu)); - p_long = &dxva_ctx->slice_long[dxva_ctx->slice_count]; - //!< fill slice long contents - p_long->first_mb_in_slice = currSlice->start_mb_nr; - p_long->NumMbsForSlice = 0; //!< XXX it is set once we have all slices - p_long->slice_type = currSlice->slice_type; - p_long->num_ref_idx_l0_active_minus1 = currSlice->active_pps->num_ref_idx_l0_default_active_minus1; - p_long->num_ref_idx_l1_active_minus1 = currSlice->active_pps->num_ref_idx_l1_default_active_minus1; - p_long->redundant_pic_cnt = currSlice->redundant_pic_cnt; - p_long->direct_spatial_mv_pred_flag = currSlice->direct_spatial_mv_pred_flag; - p_long->slice_id = dxva_ctx->slice_count; - - for (i = 0; i < FF_ARRAY_ELEMS(p_long->RefPicList[0]); i++) { - dpb_idx = currSlice->p_Dec->refpic_info_p[i].dpb_idx; - dpb_valid = (currSlice->p_Dec->dpb_info[dpb_idx].picbuf ? 1 : 0); - if (dpb_valid) { - bottom_flag = currSlice->p_Dec->refpic_info_p[i].bottom_flag; - fill_picture_entry(&p_long->RefPicList[0][i], dpb_idx, bottom_flag); - } else { - p_long->RefPicList[0][i].bPicEntry = 0xff; - } - } - - for (list = 0; list < 2; list++) { - for (i = 0; i < FF_ARRAY_ELEMS(p_long->RefPicList[list + 1]); i++) { - dpb_idx = currSlice->p_Dec->refpic_info[list][i].dpb_idx; - dpb_valid = (currSlice->p_Dec->dpb_info[dpb_idx].picbuf ? 1 : 0); - if (dpb_valid) { - bottom_flag = currSlice->p_Dec->refpic_info[list][i].bottom_flag; - fill_picture_entry(&p_long->RefPicList[list + 1][i], dpb_idx, bottom_flag); - } else { - p_long->RefPicList[list + 1][i].bPicEntry = 0xff; - } - } - } - dxva_ctx->slice_count++; - - return ret = MPP_OK; -__FAILED: - return ret; -} - - -/*! -*********************************************************************** -* \brief -* check parser is end and then configure register -*********************************************************************** -*/ -//extern "C" -void commit_buffer(H264dDxvaCtx_t *dxva_ctx) -{ - H264dSyntax_t *p_syn = &dxva_ctx->syn; - DXVA2_DecodeBufferDesc *p_dec = NULL; - - p_syn->num = 0; - //!< commit picture paramters - p_dec = &p_syn->buf[p_syn->num++]; - memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); - p_dec->CompressedBufferType = DXVA2_PictureParametersBufferType; - p_dec->pvPVPState = (void *)&dxva_ctx->pp; - p_dec->DataSize = sizeof(DXVA_PicParams_H264_MVC); - p_dec->NumMBsInBuffer = 0; - //!< commit scanlist Qmatrix - p_dec = &p_syn->buf[p_syn->num++]; - memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); - p_dec->CompressedBufferType = DXVA2_InverseQuantizationMatrixBufferType; - p_dec->pvPVPState = (void *)&dxva_ctx->qm; - p_dec->DataSize = sizeof(DXVA_Qmatrix_H264); - p_dec->NumMBsInBuffer = 0; - //!< commit bitstream - p_dec = &p_syn->buf[p_syn->num++]; - memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); - p_dec->CompressedBufferType = DXVA2_BitStreamDateBufferType; - p_dec->DataSize = ALIGN(dxva_ctx->strm_offset, 16); - memset(dxva_ctx->bitstream + dxva_ctx->strm_offset, 0, p_dec->DataSize - dxva_ctx->strm_offset); - p_dec->pvPVPState = (void *)dxva_ctx->bitstream; - //!< commit slice control, DXVA_Slice_H264_Long - p_dec = &p_syn->buf[p_syn->num++]; - memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); - p_dec->CompressedBufferType = DXVA2_SliceControlBufferType; - p_dec->NumMBsInBuffer = (dxva_ctx->pp.wFrameHeightInMbsMinus1 + 1) - * (dxva_ctx->pp.wFrameWidthInMbsMinus1 + 1); - p_dec->pvPVPState = dxva_ctx->slice_long; - p_dec->DataSize = dxva_ctx->slice_count * sizeof(DXVA_Slice_H264_Long); - - //!< reset dxva parameters - dxva_ctx->slice_count = 0; - dxva_ctx->strm_offset = 0; -} \ No newline at end of file +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_fill" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "h264d_fill.h" + +static MPP_RET realloc_slice_list(H264dDxvaCtx_t *dxva_ctx) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + dxva_ctx->max_slice_size += ADD_SLICE_SIZE; + dxva_ctx->slice_long = mpp_realloc(dxva_ctx->slice_long, + DXVA_Slice_H264_Long, + dxva_ctx->max_slice_size); + MEM_CHECK(ret, dxva_ctx->slice_long); + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET fill_slice_stream(H264dDxvaCtx_t *dxva_ctx, H264_Nalu_t *p_nal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + DXVA_Slice_H264_Long *p_long = NULL; + + if (dxva_ctx->slice_count >= dxva_ctx->max_slice_size) { + FUN_CHECK(ret = realloc_slice_list(dxva_ctx)); + } + p_long = &dxva_ctx->slice_long[dxva_ctx->slice_count]; + memset(p_long, 0, sizeof(DXVA_Slice_H264_Long)); + p_long->BSNALunitDataLocation = dxva_ctx->strm_offset; + p_long->wBadSliceChopping = 0; //!< set to 0 in Rock-Chip RKVDEC IP + + (void)p_nal; + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void fill_picture_entry(DXVA_PicEntry_H264 *pic, RK_U32 index, RK_U32 flag) +{ + ASSERT((index & 0x7f) == index && (flag & 0x01) == flag); + pic->bPicEntry = index | (flag << 7); +} + + +/*! +*********************************************************************** +* \brief +* fill picture parameters +*********************************************************************** +*/ +//extern "C" +void fill_scanlist(H264dVideoCtx_t *p_Vid, DXVA_Qmatrix_H264 *qm) +{ + RK_S32 i = 0, j = 0; + + memset(qm, 0, sizeof(DXVA_Qmatrix_H264)); + for (i = 0; i < 6; ++i) { //!< 4x4, 6 lists + for (j = 0; j < H264ScalingList4x4Length; j++) { + qm->bScalingLists4x4[i][j] = p_Vid->qmatrix[i][j]; + } + } + for (i = 6; i < ((p_Vid->active_sps->chroma_format_idc != H264_CHROMA_444) ? 8 : 12); ++i) { + for (j = 0; j < H264ScalingList8x8Length; j++) { + qm->bScalingLists8x8[i - 6][j] = p_Vid->qmatrix[i][j]; + } + } +} +/*! +*********************************************************************** +* \brief +* fill picture parameters +*********************************************************************** +*/ +//extern "C" +void fill_picparams(H264dVideoCtx_t *p_Vid, DXVA_PicParams_H264_MVC *pp) +{ + RK_U32 i = 0, j = 0; + H264_StorePic_t *dec_pic = p_Vid->dec_pic; + H264_DpbInfo_t *dpb_info = p_Vid->p_Dec->dpb_info; + + // memset(pp, 0, sizeof(DXVA_PicParams_H264_MVC)); + //!< Configure current picture + fill_picture_entry(&pp->CurrPic, dec_pic->mem_mark->slot_idx, dec_pic->structure == BOTTOM_FIELD); + //!< Configure the set of references + pp->UsedForReferenceFlags = 0; + pp->NonExistingFrameFlags = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefFrameList); i++) { + if (dpb_info[i].refpic) { + fill_picture_entry(&pp->RefFrameList[i], dpb_info[i].slot_index, dpb_info[i].is_long_term); + pp->FieldOrderCntList[i][0] = dpb_info[i].TOP_POC; + pp->FieldOrderCntList[i][1] = dpb_info[i].BOT_POC; + pp->FrameNumList[i] = (dpb_info[i].is_long_term != 0) ? dpb_info[i].long_term_frame_idx : dpb_info[i].frame_num; + pp->LongTermPicNumList[i] = dpb_info[i].long_term_pic_num; + if (dpb_info[i].is_used & 0x01) { //!< top_field + pp->UsedForReferenceFlags |= 1 << (2 * i + 0); + } + if (dpb_info[i].is_used & 0x02) { //!< bot_field + pp->UsedForReferenceFlags |= 1 << (2 * i + 1); + } + } else { + pp->RefFrameList[i].bPicEntry = 0xff; + pp->FieldOrderCntList[i][0] = 0; + pp->FieldOrderCntList[i][1] = 0; + pp->FrameNumList[i] = 0; + } + } + + pp->spspps_update = p_Vid->spspps_update; + if (pp->spspps_update) { + pp->wFrameWidthInMbsMinus1 = p_Vid->active_sps->pic_width_in_mbs_minus1; + pp->wFrameHeightInMbsMinus1 = p_Vid->active_sps->pic_height_in_map_units_minus1; + pp->num_ref_frames = p_Vid->active_sps->max_num_ref_frames; + + pp->residual_colour_transform_flag = 0; + pp->sp_for_switch_flag = 0; + pp->chroma_format_idc = p_Vid->active_sps->chroma_format_idc; + pp->constrained_intra_pred_flag = p_Vid->active_pps->constrained_intra_pred_flag; + pp->weighted_pred_flag = p_Vid->active_pps->weighted_pred_flag; + pp->weighted_bipred_idc = p_Vid->active_pps->weighted_bipred_idc; + pp->MbsConsecutiveFlag = 1; + pp->frame_mbs_only_flag = p_Vid->active_sps->frame_mbs_only_flag; + pp->transform_8x8_mode_flag = p_Vid->active_pps->transform_8x8_mode_flag; + pp->MinLumaBipredSize8x8Flag = (p_Vid->active_sps->level_idc >= 31); + pp->IntraPicFlag = 1; //(Modified if we detect a non-intra slice in dxva2_h264_decode_slice) + + pp->bit_depth_luma_minus8 = p_Vid->active_sps->bit_depth_luma_minus8; + pp->bit_depth_chroma_minus8 = p_Vid->active_sps->bit_depth_chroma_minus8; + pp->Reserved16Bits = 3; //!< FIXME is there a way to detect the right mode + + pp->StatusReportFeedbackNumber = 1 /*+ ctx->report_id++*/; + } + pp->MbaffFrameFlag = dec_pic->mb_aff_frame_flag; + pp->field_pic_flag = (dec_pic->iCodingType == FIELD_CODING); + pp->RefPicFlag = dec_pic->used_for_reference; + //!< for current poc + pp->CurrFieldOrderCnt[0] = 0; + if (dec_pic->structure == TOP_FIELD || dec_pic->structure == FRAME) { + pp->CurrFieldOrderCnt[0] = dec_pic->top_poc; + } + pp->CurrFieldOrderCnt[1] = 0; + if (dec_pic->structure == BOTTOM_FIELD || dec_pic->structure == FRAME) { + pp->CurrFieldOrderCnt[1] = dec_pic->bottom_poc; + } + pp->frame_num = dec_pic->frame_num; + + if (pp->spspps_update) { + pp->pic_init_qs_minus26 = p_Vid->active_pps->pic_init_qs_minus26; + pp->chroma_qp_index_offset = p_Vid->active_pps->chroma_qp_index_offset; + pp->second_chroma_qp_index_offset = p_Vid->active_pps->second_chroma_qp_index_offset; + pp->ContinuationFlag = 1; + pp->pic_init_qp_minus26 = p_Vid->active_pps->pic_init_qp_minus26; + pp->num_ref_idx_l0_active_minus1 = p_Vid->active_pps->num_ref_idx_l0_default_active_minus1; + pp->num_ref_idx_l1_active_minus1 = p_Vid->active_pps->num_ref_idx_l1_default_active_minus1; + pp->Reserved8BitsA = 0; + + pp->log2_max_frame_num_minus4 = p_Vid->active_sps->log2_max_frame_num_minus4; + pp->pic_order_cnt_type = p_Vid->active_sps->pic_order_cnt_type; + if (pp->pic_order_cnt_type == 0) { + pp->log2_max_pic_order_cnt_lsb_minus4 = p_Vid->active_sps->log2_max_pic_order_cnt_lsb_minus4; + } else if (pp->pic_order_cnt_type == 1) { + pp->delta_pic_order_always_zero_flag = p_Vid->active_sps->delta_pic_order_always_zero_flag; + } + pp->direct_8x8_inference_flag = p_Vid->active_sps->direct_8x8_inference_flag; + pp->entropy_coding_mode_flag = p_Vid->active_pps->entropy_coding_mode_flag; + pp->pic_order_present_flag = p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag; + pp->num_slice_groups_minus1 = p_Vid->active_pps->num_slice_groups_minus1; + pp->slice_group_map_type = p_Vid->active_pps->slice_group_map_type; + pp->deblocking_filter_control_present_flag = p_Vid->active_pps->deblocking_filter_control_present_flag; + pp->redundant_pic_cnt_present_flag = p_Vid->active_pps->redundant_pic_cnt_present_flag; + pp->Reserved8BitsB = 0; + /* FMO is not implemented and is not implemented by FF neither */ + pp->slice_group_change_rate_minus1 = 0; + } + + //!< scaleing list flag + if (p_Vid->active_pps->pic_scaling_matrix_present_flag + || p_Vid->active_sps->seq_scaling_matrix_present_flag) { + pp->scaleing_list_enable_flag = 1; + } else { + pp->scaleing_list_enable_flag = 0; + } + + //!< add in Rock-chip RKVDEC IP + pp->RefPicFiledFlags = 0; + pp->RefPicColmvUsedFlags = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefFrameList); i++) { + if (dpb_info[i].refpic) { + if (dpb_info[i].colmv_is_used) { + pp->RefPicColmvUsedFlags |= 1 << i; + } + if (dpb_info[i].field_flag) { + pp->RefPicFiledFlags |= 1 << i; + } + } + } + + //!< Following are H.264 MVC Specific parameters + if (p_Vid->active_subsps) { + RK_S32 num_views = 0; + pp->num_views_minus1 = p_Vid->active_subsps->num_views_minus1; + num_views = 1 + pp->num_views_minus1; + ASSERT(num_views <= 16); + ASSERT(num_views >= 0); + + for (i = 0; i < (RK_U32)num_views; i++) { + pp->view_id[i] = p_Vid->active_subsps->view_id[i]; + pp->num_anchor_refs_l0[i] = p_Vid->active_subsps->num_anchor_refs_l0[i]; + for (j = 0; j < pp->num_anchor_refs_l0[i]; j++) { + pp->anchor_ref_l0[i][j] = p_Vid->active_subsps->anchor_ref_l0[i][j]; + } + pp->num_anchor_refs_l1[i] = p_Vid->active_subsps->num_anchor_refs_l1[i]; + for (j = 0; j < pp->num_anchor_refs_l1[i]; j++) { + pp->anchor_ref_l1[i][j] = p_Vid->active_subsps->anchor_ref_l1[i][j]; + } + pp->num_non_anchor_refs_l0[i] = p_Vid->active_subsps->num_non_anchor_refs_l0[i]; + for (j = 0; j < pp->num_non_anchor_refs_l0[i]; j++) { + pp->non_anchor_ref_l0[i][j] = p_Vid->active_subsps->non_anchor_ref_l0[i][j]; + } + pp->num_non_anchor_refs_l1[i] = p_Vid->active_subsps->num_non_anchor_refs_l1[i]; + for (j = 0; j < pp->num_non_anchor_refs_l1[i]; j++) { + pp->non_anchor_ref_l1[i][j] = p_Vid->active_subsps->non_anchor_ref_l1[i][j]; + } + } + + for (i = num_views; i < 16; i++) + pp->view_id[i] = 0xffff; + + pp->curr_view_id = dec_pic->view_id; + pp->anchor_pic_flag = dec_pic->anchor_pic_flag; + pp->inter_view_flag = dec_pic->inter_view_flag; + for (i = 0; i < 16; i++) { + pp->ViewIDList[i] = dpb_info[i].view_id; + } + //!< add in Rock-chip RKVDEC IP + pp->curr_layer_id = dec_pic->layer_id; + pp->UsedForInTerviewflags = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefFrameList); i++) { + if (dpb_info[i].is_ilt_flag) { + pp->UsedForInTerviewflags |= 1 << i; + } + pp->RefPicLayerIdList[i] = dpb_info[i].voidx; + } + } else { + pp->num_views_minus1 = 0; + pp->curr_layer_id = dec_pic->layer_id; + memset(pp->view_id, 0, sizeof(pp->view_id)); + memset(pp->ViewIDList, 0, sizeof(pp->ViewIDList)); + memset(pp->RefPicLayerIdList, 0, sizeof(pp->RefPicLayerIdList)); + } + + p_Vid->spspps_update = 0; + + //!< for fpga test + pp->seq_parameter_set_id = p_Vid->active_sps->seq_parameter_set_id; + pp->pps_seq_parameter_set_id = p_Vid->active_pps->seq_parameter_set_id; + pp->pps_pic_parameter_set_id = p_Vid->active_pps->pic_parameter_set_id; + pp->profile_idc = p_Vid->active_sps->profile_idc; + pp->constraint_set3_flag = p_Vid->active_sps->constrained_set3_flag; + pp->qpprime_y_zero_transform_bypass_flag = p_Vid->active_sps->qpprime_y_zero_transform_bypass_flag;; + pp->mvc_extension_enable = p_Vid->active_subsps ? 1 : 0; +} + +/*! +*********************************************************************** +* \brief +* fill slice short struct +*********************************************************************** +*/ +//extern "C" +MPP_RET fill_slice_syntax(H264_SLICE_t *currSlice, H264dDxvaCtx_t *dxva_ctx) +{ + RK_U32 list = 0, i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + DXVA_Slice_H264_Long *p_long = NULL; + RK_S32 dpb_idx = 0, dpb_valid = 0, bottom_flag = 0; + + FUN_CHECK(ret = fill_slice_stream(dxva_ctx, &currSlice->p_Cur->nalu)); + p_long = &dxva_ctx->slice_long[dxva_ctx->slice_count]; + //!< fill slice long contents + p_long->first_mb_in_slice = currSlice->start_mb_nr; + p_long->NumMbsForSlice = 0; //!< XXX it is set once we have all slices + p_long->slice_type = currSlice->slice_type; + p_long->num_ref_idx_l0_active_minus1 = currSlice->active_pps->num_ref_idx_l0_default_active_minus1; + p_long->num_ref_idx_l1_active_minus1 = currSlice->active_pps->num_ref_idx_l1_default_active_minus1; + p_long->redundant_pic_cnt = currSlice->redundant_pic_cnt; + p_long->direct_spatial_mv_pred_flag = currSlice->direct_spatial_mv_pred_flag; + p_long->slice_id = dxva_ctx->slice_count; + //!< add parameters + p_long->active_sps_id = currSlice->active_sps->seq_parameter_set_id; + p_long->active_pps_id = currSlice->active_pps->pic_parameter_set_id; + p_long->idr_pic_id = currSlice->idr_pic_id; + p_long->idr_flag = currSlice->idr_flag; + p_long->drpm_used_bitlen = currSlice->drpm_used_bitlen; + p_long->poc_used_bitlen = currSlice->poc_used_bitlen; + p_long->nal_ref_idc = currSlice->nal_reference_idc; + p_long->profileIdc = currSlice->active_sps->profile_idc; + + for (i = 0; i < MPP_ARRAY_ELEMS(p_long->RefPicList[0]); i++) { + dpb_idx = currSlice->p_Dec->refpic_info_p[i].dpb_idx; + dpb_valid = currSlice->p_Dec->refpic_info_p[i].valid; + //dpb_valid = (currSlice->p_Dec->dpb_info[dpb_idx].refpic ? 1 : 0); + if (dpb_valid) { + bottom_flag = currSlice->p_Dec->refpic_info_p[i].bottom_flag; + fill_picture_entry(&p_long->RefPicList[0][i], dpb_idx, bottom_flag); + } else { + p_long->RefPicList[0][i].bPicEntry = 0xff; + } + } + + for (list = 0; list < 2; list++) { + for (i = 0; i < MPP_ARRAY_ELEMS(p_long->RefPicList[list + 1]); i++) { + dpb_idx = currSlice->p_Dec->refpic_info_b[list][i].dpb_idx; + dpb_valid = currSlice->p_Dec->refpic_info_b[list][i].valid; + //dpb_valid = (currSlice->p_Dec->dpb_info[dpb_idx].refpic ? 1 : 0); + if (dpb_valid) { + bottom_flag = currSlice->p_Dec->refpic_info_b[list][i].bottom_flag; + fill_picture_entry(&p_long->RefPicList[list + 1][i], dpb_idx, bottom_flag); + } else { + p_long->RefPicList[list + 1][i].bPicEntry = 0xff; + } + } + } + dxva_ctx->slice_count++; + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +/*! +*********************************************************************** +* \brief +* check parser is end and then configure register +*********************************************************************** +*/ +//extern "C" +void commit_buffer(H264dDxvaCtx_t *dxva_ctx) +{ + H264dSyntax_t *p_syn = &dxva_ctx->syn; + DXVA2_DecodeBufferDesc *p_dec = NULL; + + p_syn->num = 0; + //!< commit picture paramters + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_PictureParametersBufferType; + p_dec->pvPVPState = (void *)&dxva_ctx->pp; + p_dec->DataSize = sizeof(DXVA_PicParams_H264_MVC); + p_dec->NumMBsInBuffer = 0; + //!< commit scanlist Qmatrix + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_InverseQuantizationMatrixBufferType; + p_dec->pvPVPState = (void *)&dxva_ctx->qm; + p_dec->DataSize = sizeof(DXVA_Qmatrix_H264); + p_dec->NumMBsInBuffer = 0; + //!< commit bitstream + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_BitStreamDateBufferType; + p_dec->DataSize = MPP_ALIGN(dxva_ctx->strm_offset, 16); + memset(dxva_ctx->bitstream + dxva_ctx->strm_offset, 0, p_dec->DataSize - dxva_ctx->strm_offset); + p_dec->pvPVPState = (void *)dxva_ctx->bitstream; + //!< commit slice control, DXVA_Slice_H264_Long + p_dec = &p_syn->buf[p_syn->num++]; + memset(p_dec, 0, sizeof(DXVA2_DecodeBufferDesc)); + p_dec->CompressedBufferType = DXVA2_SliceControlBufferType; + p_dec->NumMBsInBuffer = (dxva_ctx->pp.wFrameHeightInMbsMinus1 + 1) + * (dxva_ctx->pp.wFrameWidthInMbsMinus1 + 1); + p_dec->pvPVPState = dxva_ctx->slice_long; + p_dec->DataSize = dxva_ctx->slice_count * sizeof(DXVA_Slice_H264_Long); + + //!< reset dxva parameters + dxva_ctx->slice_count = 0; + dxva_ctx->strm_offset = 0; +} diff --git a/mpp/codec/dec/h264/h264d_fill.h b/mpp/codec/dec/h264/h264d_fill.h index 8e0db1634..8dae1fb49 100644 --- a/mpp/codec/dec/h264/h264d_fill.h +++ b/mpp/codec/dec/h264/h264d_fill.h @@ -1,43 +1,43 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef _H264D_FILL_H_ -#define _H264D_FILL_H_ - -#include "rk_type.h" -#include "mpp_err.h" -#include "dxva_syntax.h" -#include "h264d_syntax.h" -#include "h264d_global.h" - - - -#ifdef __cplusplus -extern "C" { -#endif - -void fill_picparams(H264dVideoCtx_t *p_Vid, DXVA_PicParams_H264_MVC *pp); -void fill_qmatrix(H264dVideoCtx_t *p_Vid, DXVA_Qmatrix_H264 *qm); -void commit_buffer(H264dDxvaCtx_t *dxva); -MPP_RET fill_slice(H264_SLICE_t *currSlice, H264dDxvaCtx_t *dxva_ctx); -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of _RKV_H264_DECODER_FILL_H_ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_FILL_H +#define H264D_FILL_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "dxva_syntax.h" +#include "h264d_syntax.h" +#include "h264d_global.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_picparams(H264dVideoCtx_t *p_Vid, DXVA_PicParams_H264_MVC *pp); +void fill_scanlist(H264dVideoCtx_t *p_Vid, DXVA_Qmatrix_H264 *qm); +void commit_buffer(H264dDxvaCtx_t *dxva); +MPP_RET fill_slice_syntax(H264_SLICE_t *currSlice, H264dDxvaCtx_t *dxva_ctx); +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* H264D_FILL_H */ + diff --git a/mpp/codec/dec/h264/h264d_global.h b/mpp/codec/dec/h264/h264d_global.h index 979fe692e..647684429 100644 --- a/mpp/codec/dec/h264/h264d_global.h +++ b/mpp/codec/dec/h264/h264d_global.h @@ -1,1005 +1,1169 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __H264D_GLOBAL_H__ -#define __H264D_GLOBAL_H__ - -#include -#include "rk_type.h" -#include "rk_mpi.h" - -#include "h264d_api.h" -#include "h264d_log.h" -#include "h264d_bitread.h" -#include "h264d_syntax.h" - -//!< define -#define MAXSPS 32 -#define MAXPPS 256 -#define START_PREFIX_3BYTE 3 - -#define MVC_INIT_VIEW_ID -1 -#define MAX_VIEW_NUM 1024 -#define BASE_VIEW_IDX 0 -#define MAX_NUM_DPB_LAYERS 2 -#define MAX_DPB_SIZE 35 -#define MAX_NUM_DECSLICES 16 -#define MAX_LIST_SIZE 33 -#define MB_BLOCK_SIZE 16 - -#define DPB_INFO_SIZE 16 -#define REFPIC_INFO_SIZE 32 -#define MAX_TASK_SIZE 2 -#define NALU_BUF_MAX_SIZE 64//512*1024 -#define NALU_BUF_ADD_SIZE 32//512 - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -//!< AVC Profile IDC definitions -typedef enum { - FREXT_CAVLC444 = 44, //!< YUV 4:4:4/14 "CAVLC 4:4:4" - BASELINE = 66, //!< YUV 4:2:0/8 "Baseline" - H264_MAIN = 77, //!< YUV 4:2:0/8 "Main" - EXTENDED = 88, //!< YUV 4:2:0/8 "Extended" - FREXT_HP = 100, //!< YUV 4:2:0/8 "High" - FREXT_Hi10P = 110, //!< YUV 4:2:0/10 "High 10" - FREXT_Hi422 = 122, //!< YUV 4:2:2/10 "High 4:2:2" - FREXT_Hi444 = 244, //!< YUV 4:4:4/14 "High 4:4:4" - MVC_HIGH = 118, //!< YUV 4:2:0/8 "Multiview High" - STEREO_HIGH = 128 //!< YUV 4:2:0/8 "Stereo High" -} ProfileIDC; - -//!< values for nal_unit_type -typedef enum { - NALU_TYPE_NULL = 0, - NALU_TYPE_SLICE = 1, - NALU_TYPE_DPA = 2, - NALU_TYPE_DPB = 3, - NALU_TYPE_DPC = 4, - NALU_TYPE_IDR = 5, - NALU_TYPE_SEI = 6, - NALU_TYPE_SPS = 7, - NALU_TYPE_PPS = 8, - NALU_TYPE_AUD = 9, // Access Unit Delimiter - NALU_TYPE_EOSEQ = 10, // end of sequence - NALU_TYPE_EOSTREAM = 11, // end of stream - NALU_TYPE_FILL = 12, - NALU_TYPE_SPSEXT = 13, - NALU_TYPE_PREFIX = 14, // prefix - NALU_TYPE_SUB_SPS = 15, - NALU_TYPE_SLICE_AUX = 19, - NALU_TYPE_SLC_EXT = 20, // slice extensive - NALU_TYPE_VDRD = 24 // View and Dependency Representation Delimiter NAL Unit -} Nalu_type; - -//!< values for nal_ref_idc -typedef enum { - NALU_PRIORITY_HIGHEST = 3, - NALU_PRIORITY_HIGH = 2, - NALU_PRIORITY_LOW = 1, - NALU_PRIORITY_DISPOSABLE = 0 -} NalRefIdc_type; - -//!< PPS parameters -#define MAXnum_slice_groups_minus1 8 -enum { - H264ScalingList4x4Length = 16, - H264ScalingList8x8Length = 64, -} ScalingListLength; - -typedef enum { - YUV400 = 0, //!< Monochrome - YUV420 = 1, //!< 4:2:0 - YUV422 = 2, //!< 4:2:2 - YUV444 = 3 //!< 4:4:4 -} ColorFormat; - -typedef enum { - FRAME = 0, - TOP_FIELD, - BOTTOM_FIELD -} PictureStructure; //!< New enum for field processing - -//!< Field Coding Types -typedef enum { - FRAME_CODING = 0, - FIELD_CODING = 1, - ADAPTIVE_CODING = 2, - FRAME_MB_PAIR_CODING = 3 -} CodingType; - -typedef enum { - P_SLICE = 0, - B_SLICE = 1, - I_SLICE = 2, - SP_SLICE = 3, - SI_SLICE = 4, - NUM_SLICE_TYPES = 5 -} SliceType; - -typedef enum { - LIST_0 = 0, - LIST_1 = 1, - BI_PRED = 2, - BI_PRED_L0 = 3, - BI_PRED_L1 = 4 -} ListType; - -//!< NAL Unit structure -typedef struct h264_nalu_t { - RK_S32 startcodeprefix_len; //!< 4 for parameter sets and first slice in picture, 3 for everything else (suggested) - RK_U32 sodb_len; //!< Length of the NAL unit (Excluding the start code, which does not belong to the NALU) - RK_S32 forbidden_bit; //!< should be always FALSE - Nalu_type nal_unit_type; //!< NALU_TYPE_xxxx - NalRefIdc_type nal_reference_idc; //!< NALU_PRIORITY_xxxx - RK_U8 *sodb_buf; //!< Data of the NAL unit (Excluding the start code, which does not belong to the NALU) - RK_U16 lost_packets; //!< true, if packet loss is detected, used in RTPNALU - //---- MVC extension - RK_S32 svc_extension_flag; //!< should be always 0, for MVC - RK_S32 non_idr_flag; //!< 0 = current is IDR - RK_S32 priority_id; //!< a lower value of priority_id specifies a higher priority - RK_S32 view_id; //!< view identifier for the NAL unit - RK_S32 temporal_id; //!< temporal identifier for the NAL unit - RK_S32 anchor_pic_flag; //!< anchor access unit - RK_S32 inter_view_flag; //!< inter-view prediction enable - RK_S32 reserved_one_bit; //!< shall be equal to 1 - RK_S32 MVCExt_is_valid; - RK_S32 MVCExt_is_prefixNALU; - //------ - RK_U8 ualu_header_bytes; //!< for rbsp start - RK_S32 UsedBits; - -} H264_Nalu_t; - -typedef struct h264_nalu_mvc_ext_t { - RK_U32 valid; - RK_U32 non_idr_flag; - RK_U32 priority_id; - RK_U32 view_id; - RK_U32 temporal_id; - RK_U32 anchor_pic_flag; - RK_U32 inter_view_flag; - RK_U32 reserved_one_bit; - RK_U32 iPrefixNALU; -} H264_NaluMvcExt_t; - -//!< decoder refence picture marking -typedef struct h264_drpm_t { - RK_U32 memory_management_control_operation; - RK_U32 difference_of_pic_nums_minus1; - RK_U32 long_term_pic_num; - RK_U32 long_term_frame_idx; - RK_U32 max_long_term_frame_idx_plus1; - struct h264_drpm_t *Next; -} H264_DRPM_t; - -typedef enum { - Mem_NULL = 0, - Mem_Malloc = 1, - Mem_Clone = 2, - Mem_UnPaired = 3, - Mem_Max, -} H264_Mem_type; - -//!< decoder picture memory -typedef struct h264_dpb_mark_t { - RK_U8 top_used; - RK_U8 bot_used; - RK_U8 index; - RK_U8 *pbuf; - -} H264_DpbMark_t; - -//!< decoder picture buffer information -typedef struct h264_dpb_info_t { - RK_U8 colmv_is_used; - RK_U8 mem_mark_idx; - - void *picbuf; - RK_S32 TOP_POC; - RK_S32 BOT_POC; - RK_U16 frame_num_wrap; - RK_U32 field_flag; - RK_U32 is_long_term; - RK_U32 voidx; - RK_U32 view_id; - RK_U32 is_used; - RK_U32 top_valid; - RK_U32 bot_valid; - -} H264_DpbInfo_t; - -//!< refence picture information -typedef struct h264_refpic_info_t { - RK_U32 valid; - RK_S32 dpb_idx; - RK_S32 bottom_flag; -} H264_RefPicInfo_t; - -//!< definition a picture (field or frame) -typedef struct h264_store_pic_t { - RK_S32 structure; - RK_S32 poc; - RK_S32 top_poc; - RK_S32 bottom_poc; - RK_S32 frame_poc; - RK_S32 ThisPOC; - RK_S32 pic_num; - RK_S32 long_term_pic_num; - RK_S32 long_term_frame_idx; - - RK_U32 frame_num; - RK_U32 dec_no; - RK_U8 is_long_term; - RK_S32 used_for_reference; - RK_S32 is_output; - RK_S32 non_existing; - RK_S16 max_slice_id; - RK_S32 mb_aff_frame_flag; - RK_U32 PicWidthInMbs; - RK_U8 colmv_no_used_flag; - struct h264_store_pic_t *top_field; // for mb aff, if frame for referencing the top field - struct h264_store_pic_t *bottom_field; // for mb aff, if frame for referencing the bottom field - struct h264_store_pic_t *frame; // for mb aff, if field for referencing the combined frame - - RK_S32 slice_type; - RK_S32 idr_flag; - RK_S32 no_output_of_prior_pics_flag; - RK_S32 long_term_reference_flag; - RK_S32 adaptive_ref_pic_buffering_flag; - RK_S32 chroma_format_idc; - RK_S32 frame_mbs_only_flag; - RK_S32 frame_cropping_flag; - RK_S32 frame_crop_left_offset; - RK_S32 frame_crop_right_offset; - RK_S32 frame_crop_top_offset; - RK_S32 frame_crop_bottom_offset; - struct h264_drpm_t *dec_ref_pic_marking_buffer; //!< stores the memory management control operations - RK_S32 proc_flag; - RK_S32 view_id; - RK_S32 inter_view_flag; - RK_S32 anchor_pic_flag; - RK_S32 iCodingType; - - RK_S32 layer_id; - RK_U8 is_mmco_5; - RK_S32 poc_mmco5; - RK_S32 top_poc_mmco5; - RK_S32 bot_poc_mmco5; - H264_Mem_type mem_malloc_type; - struct h264_dpb_mark_t *mem_mark; -} H264_StorePic_t; - -//!< Frame Stores for Decoded Picture Buffer -typedef struct h264_frame_store_t { - RK_S32 is_used; //!< 0=empty; 1=top; 2=bottom; 3=both fields (or frame) - RK_S32 is_reference; //!< 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used - RK_S32 is_long_term; //!< 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used - RK_S32 is_orig_reference; //!< original marking by nal_ref_idc: 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used - RK_S32 is_non_existent; - RK_S32 frame_num_wrap; - RK_S32 long_term_frame_idx; - RK_S32 is_output; - RK_S32 poc; - RK_S32 view_id; - RK_S32 inter_view_flag[2]; - RK_S32 anchor_pic_flag[2]; - RK_S32 layer_id; - - RK_U32 frame_num; - struct h264_store_pic_t *frame; - struct h264_store_pic_t *top_field; - struct h264_store_pic_t *bottom_field; - -} H264_FrameStore_t; - -//!< decode picture buffer -typedef struct h264_dpb_buf_t { - RK_U32 size; - RK_U32 used_size; - RK_U32 ref_frames_in_buffer; - RK_U32 ltref_frames_in_buffer; - RK_U32 used_size_il; - - RK_S32 last_output_poc; - RK_S32 last_output_view_id; - RK_S32 max_long_term_pic_idx; - RK_S32 init_done; - RK_S32 num_ref_frames; - RK_S32 layer_id; - - struct h264_frame_store_t **fs; - struct h264_frame_store_t **fs_ref; - struct h264_frame_store_t **fs_ltref; - struct h264_frame_store_t **fs_ilref; //!< inter-layer reference (for multi-layered codecs) - struct h264_frame_store_t *last_picture; - - struct h264d_video_ctx_t *p_Vid; -} H264_DpbBuf_t; - -//!< HRD -#define MAXIMUMVALUEOFcpb_cnt 32 -typedef struct h264_hrd_t { - RK_U32 cpb_cnt_minus1; // ue(v) - RK_U32 bit_rate_scale; // u(4) - RK_U32 cpb_size_scale; // u(4) - RK_U32 bit_rate_value_minus1[MAXIMUMVALUEOFcpb_cnt]; // ue(v) - RK_U32 cpb_size_value_minus1[MAXIMUMVALUEOFcpb_cnt]; // ue(v) - RK_U32 cbr_flag[MAXIMUMVALUEOFcpb_cnt]; // u(1) - RK_U32 initial_cpb_removal_delay_length_minus1; // u(5) - RK_U32 cpb_removal_delay_length_minus1; // u(5) - RK_U32 dpb_output_delay_length_minus1; // u(5) - RK_U32 time_offset_length; // u(5) -} H264_HRD_t; - -//!< VUI -typedef struct h264_vui_t { - RK_S32 aspect_ratio_info_present_flag; // u(1) - RK_U32 aspect_ratio_idc; // u(8) - RK_U16 sar_width; // u(16) - RK_U16 sar_height; // u(16) - RK_S32 overscan_info_present_flag; // u(1) - RK_S32 overscan_appropriate_flag; // u(1) - RK_S32 video_signal_type_present_flag; // u(1) - RK_U32 video_format; // u(3) - RK_S32 video_full_range_flag; // u(1) - RK_S32 colour_description_present_flag; // u(1) - RK_U32 colour_primaries; // u(8) - RK_U32 transfer_characteristics; // u(8) - RK_U32 matrix_coefficients; // u(8) - RK_S32 chroma_location_info_present_flag; // u(1) - RK_U32 chroma_sample_loc_type_top_field; // ue(v) - RK_U32 chroma_sample_loc_type_bottom_field; // ue(v) - RK_S32 timing_info_present_flag; // u(1) - RK_U32 num_units_in_tick; // u(32) - RK_U32 time_scale; // u(32) - RK_S32 fixed_frame_rate_flag; // u(1) - RK_S32 nal_hrd_parameters_present_flag; // u(1) - struct h264_hrd_t nal_hrd_parameters; // hrd_paramters_t - RK_S32 vcl_hrd_parameters_present_flag; // u(1) - struct h264_hrd_t vcl_hrd_parameters; // hrd_paramters_t - // if ((nal_hrd_parameters_present_flag || (vcl_hrd_parameters_present_flag)) - RK_S32 low_delay_hrd_flag; // u(1) - RK_S32 pic_struct_present_flag; // u(1) - RK_S32 bitstream_restriction_flag; // u(1) - RK_S32 motion_vectors_over_pic_boundaries_flag; // u(1) - RK_U32 max_bytes_per_pic_denom; // ue(v) - RK_U32 max_bits_per_mb_denom; // ue(v) - RK_U32 log2_max_mv_length_vertical; // ue(v) - RK_U32 log2_max_mv_length_horizontal; // ue(v) - RK_U32 num_reorder_frames; // ue(v) - RK_U32 max_dec_frame_buffering; // ue(v) -} H264_VUI_t; - -//!< MVC_VUI -typedef struct h264_mvc_vui_t { - RK_S32 num_ops_minus1; - RK_S8 *temporal_id; - RK_S32 *num_target_output_views_minus1; - RK_S32 **view_id; - RK_S8 *timing_info_present_flag; - RK_S32 *num_units_in_tick; - RK_S32 *time_scale; - RK_S8 *fixed_frame_rate_flag; - RK_S8 *nal_hrd_parameters_present_flag; - RK_S8 *vcl_hrd_parameters_present_flag; - RK_S8 *low_delay_hrd_flag; - RK_S8 *pic_struct_present_flag; - - //hrd parameters; - RK_S8 cpb_cnt_minus1; - RK_S8 bit_rate_scale; - RK_S8 cpb_size_scale; - RK_S32 bit_rate_value_minus1[32]; - RK_S32 cpb_size_value_minus1[32]; - RK_S8 cbr_flag[32]; - RK_S8 initial_cpb_removal_delay_length_minus1; - RK_S8 cpb_removal_delay_length_minus1; - RK_S8 dpb_output_delay_length_minus1; - RK_S8 time_offset_length; -} H264_mvcVUI_t; - -//!< SPS -#define MAXnum_ref_frames_in_POC_cycle 256 - -typedef struct h264_sps_t { - RK_S32 Valid; // indicates the parameter set is valid - - RK_S32 profile_idc; // u(8) - RK_S32 constrained_set0_flag; // u(1) - RK_S32 constrained_set1_flag; // u(1) - RK_S32 constrained_set2_flag; // u(1) - RK_S32 constrained_set3_flag; // u(1) - RK_S32 constrained_set4_flag; // u(1) - RK_S32 constrained_set5_flag; // u(2) - - RK_S32 level_idc; // u(8) - RK_S32 seq_parameter_set_id; // ue(v) - RK_S32 chroma_format_idc; // ue(v) - - RK_S32 seq_scaling_matrix_present_flag; // u(1) - RK_S32 seq_scaling_list_present_flag[12]; // u(1) - RK_S32 ScalingList4x4[6][H264ScalingList4x4Length]; // se(v) - RK_S32 ScalingList8x8[6][H264ScalingList8x8Length]; // se(v) - RK_S32 UseDefaultScalingMatrix4x4Flag[6]; - RK_S32 UseDefaultScalingMatrix8x8Flag[6]; - - RK_S32 bit_depth_luma_minus8; // ue(v) - RK_S32 bit_depth_chroma_minus8; // ue(v) - RK_S32 log2_max_frame_num_minus4; // ue(v) - RK_S32 pic_order_cnt_type; - // if( pic_order_cnt_type == 0 ) - RK_S32 log2_max_pic_order_cnt_lsb_minus4; // ue(v) - // else if( pic_order_cnt_type == 1 ) - RK_S32 delta_pic_order_always_zero_flag; // u(1) - RK_S32 offset_for_non_ref_pic; // se(v) - RK_S32 offset_for_top_to_bottom_field; // se(v) - RK_S32 num_ref_frames_in_pic_order_cnt_cycle; // ue(v) - // for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ ) - RK_S32 offset_for_ref_frame[MAXnum_ref_frames_in_POC_cycle]; // se(v) - RK_S32 max_num_ref_frames; // ue(v) - RK_S32 gaps_in_frame_num_value_allowed_flag; // u(1) - RK_S32 pic_width_in_mbs_minus1; // ue(v) - RK_S32 pic_height_in_map_units_minus1; // ue(v) - RK_S32 frame_mbs_only_flag; // u(1) - // if( !frame_mbs_only_flag ) - RK_S32 mb_adaptive_frame_field_flag; // u(1) - RK_S32 direct_8x8_inference_flag; // u(1) - RK_S32 frame_cropping_flag; // u(1) - RK_S32 frame_crop_left_offset; // ue(v) - RK_S32 frame_crop_right_offset; // ue(v) - RK_S32 frame_crop_top_offset; // ue(v) - RK_S32 frame_crop_bottom_offset; // ue(v) - RK_S32 vui_parameters_present_flag; // u(1) - struct h264_vui_t vui_seq_parameters; // vui_seq_parameters_t - RK_S32 separate_colour_plane_flag; // u(1) - RK_S32 max_dec_frame_buffering; - RK_S32 qpprime_y_zero_transform_bypass_flag; - //---- - RK_S32 expected_delta_per_pic_order_cnt_cycle; - -} H264_SPS_t; - -//!< subSPS -typedef struct h264_subsps_t { - struct h264_sps_t sps; - - RK_S32 bit_equal_to_one; - RK_S32 num_views_minus1; - RK_S32 *view_id; - RK_S32 *num_anchor_refs_l0; - RK_S32 **anchor_ref_l0; - RK_S32 *num_anchor_refs_l1; - RK_S32 **anchor_ref_l1; - - RK_S32 *num_non_anchor_refs_l0; - RK_S32 **non_anchor_ref_l0; - RK_S32 *num_non_anchor_refs_l1; - RK_S32 **non_anchor_ref_l1; - - RK_S32 num_level_values_signalled_minus1; - RK_S32 *level_idc; - RK_S32 *num_applicable_ops_minus1; - RK_S32 **applicable_op_temporal_id; - RK_S32 **applicable_op_num_target_views_minus1; - RK_S32 ***applicable_op_target_view_id; - RK_S32 **applicable_op_num_views_minus1; - - RK_S32 mvc_vui_parameters_present_flag; - RK_S32 Valid; // indicates the parameter set is valid - -} H264_subSPS_t; - -//!< PPS - -typedef struct h264_pps_t { - RK_S32 Valid; // indicates the parameter set is valid - RK_S32 pic_parameter_set_id; // ue(v) - RK_S32 seq_parameter_set_id; // ue(v) - RK_S32 entropy_coding_mode_flag; // u(1) - RK_S32 transform_8x8_mode_flag; // u(1) - - RK_S32 pic_scaling_matrix_present_flag; // u(1) - RK_S32 pic_scaling_list_present_flag[12]; // u(1) - RK_S32 ScalingList4x4[6][H264ScalingList4x4Length]; // se(v) - RK_S32 ScalingList8x8[6][H264ScalingList8x8Length]; // se(v) - RK_S32 UseDefaultScalingMatrix4x4Flag[6]; - RK_S32 UseDefaultScalingMatrix8x8Flag[6]; - - // if( pic_order_cnt_type < 2 ) in the sequence parameter set - RK_S32 bottom_field_pic_order_in_frame_present_flag; // u(1) - RK_S32 num_slice_groups_minus1; // ue(v) - RK_S32 slice_group_map_type; // ue(v) - // if( slice_group_map_type = = 0 ) - RK_S32 run_length_minus1[MAXnum_slice_groups_minus1]; // ue(v) - // else if( slice_group_map_type = = 2 ) - RK_S32 top_left[MAXnum_slice_groups_minus1]; // ue(v) - RK_S32 bottom_right[MAXnum_slice_groups_minus1]; // ue(v) - // else if( slice_group_map_type = = 3 || 4 || 5 - RK_S32 slice_group_change_direction_flag; // u(1) - RK_S32 slice_group_change_rate_minus1; // ue(v) - // else if( slice_group_map_type = = 6 ) - RK_S32 pic_size_in_map_units_minus1; // ue(v) - RK_U8 *slice_group_id; // complete MBAmap u(v) - - RK_S32 num_ref_idx_l0_default_active_minus1; // ue(v) - RK_S32 num_ref_idx_l1_default_active_minus1; // ue(v) - RK_S32 weighted_pred_flag; // u(1) - RK_S32 weighted_bipred_idc; // u(2) - RK_S32 pic_init_qp_minus26; // se(v) - RK_S32 pic_init_qs_minus26; // se(v) - RK_S32 chroma_qp_index_offset; // se(v) - - RK_S32 cb_qp_index_offset; // se(v) - RK_S32 cr_qp_index_offset; // se(v) - RK_S32 second_chroma_qp_index_offset; // se(v) - - RK_S32 deblocking_filter_control_present_flag; // u(1) - RK_S32 constrained_intra_pred_flag; // u(1) - RK_S32 redundant_pic_cnt_present_flag; // u(1) - RK_S32 vui_pic_parameters_flag; // u(1) - RK_S32 scaleing_list_enable_flag; - RK_U32 scaleing_list_address; - -} H264_PPS_t; - -//!< SEI -typedef enum { - SEI_BUFFERING_PERIOD = 0, - SEI_PIC_TIMING, - SEI_PAN_SCAN_RECT, - SEI_FILLER_PAYLOAD, - SEI_USER_DATA_REGISTERED_ITU_T_T35, - SEI_USER_DATA_UNREGISTERED, - SEI_RECOVERY_POINT, - SEI_DEC_REF_PIC_MARKING_REPETITION, - SEI_SPARE_PIC, - SEI_SCENE_INFO, - SEI_SUB_SEQ_INFO, - SEI_SUB_SEQ_LAYER_CHARACTERISTICS, - SEI_SUB_SEQ_CHARACTERISTICS, - SEI_FULL_FRAME_FREEZE, - SEI_FULL_FRAME_FREEZE_RELEASE, - SEI_FULL_FRAME_SNAPSHOT, - SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START, - SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END, - SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET, - SEI_FILM_GRAIN_CHARACTERISTICS, - SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE, - SEI_STEREO_VIDEO_INFO, - SEI_POST_FILTER_HINTS, - SEI_TONE_MAPPING, - SEI_SCALABILITY_INFO, - SEI_SUB_PIC_SCALABLE_LAYER, - SEI_NON_REQUIRED_LAYER_REP, - SEI_PRIORITY_LAYER_INFO, - SEI_LAYERS_NOT_PRESENT, - SEI_LAYER_DEPENDENCY_CHANGE, - SEI_SCALABLE_NESTING, - SEI_BASE_LAYER_TEMPORAL_HRD, - SEI_QUALITY_LAYER_INTEGRITY_CHECK, - SEI_REDUNDANT_PIC_PROPERTY, - SEI_TL0_DEP_REP_INDEX, - SEI_TL_SWITCHING_POINT, - SEI_PARALLEL_DECODING_INFO, - SEI_MVC_SCALABLE_NESTING, - SEI_VIEW_SCALABILITY_INFO, - SEI_MULTIVIEW_SCENE_INFO, - SEI_MULTIVIEW_ACQUISITION_INFO, - SEI_NON_REQUIRED_VIEW_COMPONENT, - SEI_VIEW_DEPENDENCY_CHANGE, - SEI_OPERATION_POINTS_NOT_PRESENT, - SEI_BASE_VIEW_TEMPORAL_HRD, - SEI_FRAME_PACKING_ARRANGEMENT, - - SEI_MAX_ELEMENTS //!< number of maximum syntax elements -} RKV_H264SEI_Type; - -//!< MVC_scalable_nesting -typedef struct { - RK_S32 operation_point_flag; - RK_S32 all_view_components_in_au_flag; - RK_S32 num_view_components_minus1; - RK_S32 *sei_view_id; - RK_S32 num_view_components_op_minus1; - RK_S32 *sei_op_view_id; - RK_S32 sei_op_temporal_id; - RK_S32 Valid; -} MVC_scalable_nesting_t; - -//!< MVC_scalability_info -typedef struct { - RK_S32 num_operation_points_minus1; - RK_S32 *operation_point_id; - RK_S32 *priority_id; - RK_S32 *temporal_id; - RK_S32 *num_target_output_views_minus1; - RK_S32 **view_id; - RK_S32 *profile_level_info_present_flag; - RK_S32 *bitrate_info_present_flag; - RK_S32 *frm_rate_info_present_flag; - - RK_S32 *view_dependency_info_present_flag; - RK_S32 *parameter_sets_info_present_flag; - RK_S32 *bitstream_restriction_info_present_flag; - RK_S32 *op_profile_level_idc; - RK_S32 *avg_bitrate; - RK_S32 *max_bitrate; - RK_S32 *max_bitrate_calc_window; - RK_S32 *constant_frm_rate_idc; - RK_S32 *avg_frm_rate; - RK_S32 *num_directly_dependent_views; - RK_S32 **directly_dependent_view_id; - RK_S32 *view_dependency_info_src_op_id; - RK_S32 *num_seq_parameter_sets; - RK_S32 **seq_parameter_set_id_delta; - RK_S32 *num_subset_seq_parameter_sets; - RK_S32 **subset_seq_parameter_set_id_delta; - RK_S32 *num_pic_parameter_sets_minus1; - RK_S32 **pic_parameter_set_id_delta; - RK_S32 *parameter_sets_info_src_op_id; - RK_S32 *motion_vectors_over_pic_boundaries_flag; - RK_S32 *max_bytes_per_pic_denom; - RK_S32 *max_bits_per_mb_denom; - RK_S32 *log2_max_mv_length_horizontal; - RK_S32 *log2_max_mv_length_vertical; - RK_S32 *max_num_reorder_frames; - RK_S32 *max_dec_frame_buffering; -} MVC_scalability_info_t; - -//!< SEI struct -typedef struct h264_sei_t { - RK_S32 type; - RK_S32 payload_size; - struct { - RK_U32 recovery_frame_cnt; - RK_S32 exact_match_flag; - RK_S32 broken_link_flag; - RK_S32 changing_slice_group_idc; - } recovery_point; - struct { - RK_S32 operation_point_flag; - //-- for adding - } scalable_nesting; - - // Placeholder; in future more supported types will contribute to more - //---- follow is used in other parts - RK_S32 mvc_scalable_nesting_flag; - RK_S32 seq_parameter_set_id; -} H264_SEI_t; - -//!< SLICE -typedef struct h264_slice_t { - //--- slice data - RK_U32 sodb_offset; - struct h264_nalu_mvc_ext_t mvcExt; - //--- slice property; - RK_S32 layer_id; - RK_S32 idr_flag; - RK_U32 idr_pic_id; - RK_S32 nal_reference_idc; //!< nal_reference_idc from NAL unit - RK_U32 start_mb_nr; //!< MUST be set by NAL even in case of ei_flag == 1 - RK_S32 slice_type; //!< slice type - RK_U32 pic_parameter_set_id; - RK_S32 colour_plane_id; - RK_S32 frame_num; - RK_S32 field_pic_flag; - RK_S32 bottom_field_flag; - RK_S32 structure; - RK_S32 mb_aff_frame_flag; - RK_S32 pic_order_cnt_lsb; // for poc mode 0 - RK_S32 delta_pic_order_cnt_bottom; - RK_S32 delta_pic_order_cnt[2]; // for poc mode 1 - RK_U32 redundant_pic_cnt; - RK_S32 direct_spatial_mv_pred_flag; - RK_U32 num_ref_idx_active[2]; //!< number of available list references - RK_S32 num_ref_idx_override_flag; - RK_S32 ref_pic_list_reordering_flag[2]; - RK_S32 *modification_of_pic_nums_idc[2]; - RK_U32 *abs_diff_pic_num_minus1[2]; - RK_U32 *long_term_pic_idx[2]; - RK_U32 *abs_diff_view_idx_minus1[2]; - struct h264_drpm_t *dec_ref_pic_marking_buffer; - RK_S32 no_output_of_prior_pics_flag; - RK_S32 long_term_reference_flag; - RK_S32 adaptive_ref_pic_buffering_flag; - RK_U32 model_number; - RK_S32 slice_qp_delta; - RK_S32 qp; - RK_S32 current_mb_nr; - RK_S32 ThisPOC; - RK_S32 toppoc; //poc for this top field - RK_S32 bottompoc; //poc of bottom field of frame - RK_S32 framepoc; //poc of this frame - RK_U32 AbsFrameNum; - RK_S32 PicOrderCntMsb; - RK_S32 is_new_picture_flag; - struct h264_sps_t *active_sps; - struct h264_subsps_t *active_subsps; - struct h264_pps_t *active_pps; - - struct h264_dpb_buf_t *p_Dpb; - struct h264_dpb_buf_t *p_Dpb_layer[MAX_NUM_DPB_LAYERS]; - //---- - RK_S32 listinterviewidx0; - RK_S32 listinterviewidx1; - - //RK_U8 listXsize[6]; - RK_U8 listXsizeP[2]; - RK_U8 listXsizeB[2]; - - struct h264_frame_store_t **fs_listinterview0; - struct h264_frame_store_t **fs_listinterview1; - //struct h264_store_pic_t **listX[6]; - struct h264_store_pic_t **listP[2]; - struct h264_store_pic_t **listB[2]; - - //---- MVC extend ---- - RK_S32 svc_extension_flag; // should be always 0, for MVC - RK_S32 non_idr_flag; // 0 = current is IDR - RK_S32 priority_id; // a lower value of priority_id specifies a higher priority - RK_S32 view_id; // view identifier for the NAL unit - RK_S32 temporal_id; // temporal identifier for the NAL unit - RK_S32 anchor_pic_flag; // anchor access unit - RK_S32 inter_view_flag; // inter-view prediction enable - RK_S32 reserved_one_bit; // shall be equal to 1 - RK_S32 MVCExt_is_valid; - RK_S32 MVCExt_is_prefixNALU; - - struct h264_dec_ctx_t *p_Dec; // H264_DecCtx_t - struct h264d_input_ctx_t *p_Inp; // H264_InputParameters - struct h264d_cur_ctx_t *p_Cur; // H264_CurParameters - struct h264d_video_ctx_t *p_Vid; - struct h264d_logctx_t *logctx; // debug log file - -} H264_SLICE_t; - -//!< Old slice parameter for check new frame -typedef struct h264_old_slice_par_t { - RK_U32 current_mb_nr; - RK_U8 field_pic_flag; - RK_U8 frame_num; - RK_S32 nal_ref_idc; - RK_U8 pic_oder_cnt_lsb; - RK_S32 delta_pic_oder_cnt_bottom; - RK_S32 delta_pic_order_cnt[2]; - RK_U8 bottom_field_flag; - RK_U8 idr_flag; - RK_S32 idr_pic_id; - RK_S32 pps_id; - RK_S32 view_id; - RK_S32 inter_view_flag; - RK_S32 anchor_pic_flag; - RK_S32 layer_id; -} H264_OldSlice_t; - -//!< DXVA context -#define MAX_SLICE_SIZE 1//1024 -#define ADD_SLICE_SIZE 1//32 -#define FRAME_BUF_MAX_SIZE 64//512*1024 -#define FRAME_BUF_ADD_SIZE 32//512 -#define SYNTAX_BUF_SIZE 5 -typedef struct h264d_dxva_ctx_t { - RK_U8 cfgBitstrmRaw; - struct _DXVA_PicParams_H264_MVC pp; - struct _DXVA_Qmatrix_H264 qm; - RK_U32 max_slice_size; - RK_U32 slice_count; - struct _DXVA_Slice_H264_Long *slice_long; //!< MAX_SLICES - RK_U8 *bitstream; - RK_U32 max_strm_size; - RK_U32 strm_offset; - struct h264d_syntax_t syn; - struct h264_dec_ctx_t *p_Dec; -} H264dDxvaCtx_t; - -//!< input parameter -typedef struct h264d_input_ctx_t { - RK_U8 is_eos; - struct h264_dec_ctx_t *p_Dec; - struct h264d_cur_ctx_t *p_Cur; //!< current parameters, use in read nalu - struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder - enum mpp_decmtd_type dec_mtd; - ParserCfg init; - //!< input data - RK_U8 *in_buf; - size_t *in_size; - RK_S64 *in_timestamp; - //!< output data - RK_U8 *out_buf; - RK_U32 *out_length; - -} H264dInputCtx_t; - -//!< current stream -typedef struct h264d_curstrm_t { - RK_U32 offset; //!< The offset of the input stream - RK_U32 max_size; //!< Cur Unit Buffer size - RK_U8 *buf; //!< store read nalu data - RK_U8 prefixdata[START_PREFIX_3BYTE]; - RK_U8 startcode_found; - RK_U8 endcode_found; -} H264dCurStream_t; - -//!< current parameters -typedef struct h264d_cur_ctx_t { - struct h264_sps_t sps; - struct h264_subsps_t subsps; - struct h264_pps_t pps; - struct h264_sei_t sei; - struct h264_nalu_t nalu; - struct getbit_ctx_t bitctx; //!< for control bit_read - struct h264d_curstrm_t strm; - struct h264_slice_t slice; - - struct h264_store_pic_t **listP[2]; - struct h264_store_pic_t **listB[2]; - struct h264d_input_ctx_t *p_Inp; - struct h264_dec_ctx_t *p_Dec; - struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder -} H264dCurCtx_t; - -//!< parameters for video decoder -typedef struct h264d_video_ctx_t { - struct h264_sps_t spsSet[MAXSPS]; //!< MAXSPS, all sps storage - struct h264_subsps_t subspsSet[MAXSPS]; //!< MAXSPS, all subpps storage - struct h264_pps_t ppsSet[MAXPPS]; //!< MAXPPS, all pps storage - struct h264_sps_t *active_sps; - struct h264_subsps_t *active_subsps; - struct h264_pps_t *active_pps; - struct h264_dec_ctx_t *p_Dec; //!< H264_DecCtx_t - struct h264d_input_ctx_t *p_Inp; //!< H264_InputParameters - struct h264d_cur_ctx_t *p_Cur; //!< H264_CurParameters - struct h264_dpb_buf_t *p_Dpb_layer[MAX_NUM_DPB_LAYERS]; - struct h264_store_pic_t *dec_picture; - struct h264_store_pic_t *no_reference_picture; - struct h264_frame_store_t out_buffer; - struct h264_dpb_mark_t *active_dpb_mark[MAX_NUM_DPB_LAYERS]; //!< acitve_dpb_memory - struct h264_slice_t *ppSliceList[MAX_NUM_DECSLICES]; //!< H264_SLICE_t - struct h264_old_slice_par_t old_slice; - RK_S32 *qmatrix[12]; //!< scanlist pointer - RK_U32 stream_size; - RK_S32 last_toppoc[MAX_NUM_DPB_LAYERS]; - RK_S32 last_bottompoc[MAX_NUM_DPB_LAYERS]; - RK_S32 last_framepoc[MAX_NUM_DPB_LAYERS]; - RK_S32 last_thispoc[MAX_NUM_DPB_LAYERS]; - //!< - RK_S32 profile_idc; // u(8) - RK_S32 slice_type; - RK_S32 structure; - RK_S32 iNumOfSlicesDecoded; - RK_S32 no_output_of_prior_pics_flag; - RK_S32 last_has_mmco_5; - RK_S32 max_frame_num; - RK_S32 active_sps_id[MAX_NUM_DPB_LAYERS]; - RK_U32 PicWidthInMbs; - RK_U32 FrameHeightInMbs; - RK_S32 yuv_format; - RK_S32 width; - RK_S32 height; - RK_S32 width_cr; //!< width chroma - RK_S32 height_cr; //!< height chroma - RK_S32 last_pic_structure; - RK_S32 last_pic_bottom_field; - RK_S32 last_pic_width_in_mbs_minus1[2]; - RK_S32 last_pic_height_in_map_units_minus1[2]; - RK_S32 last_profile_idc[2]; - RK_S32 last_level_idc[2]; - RK_S32 PrevPicOrderCntMsb; - RK_S32 PrevPicOrderCntLsb; - RK_U32 PreviousFrameNum; - RK_U32 FrameNumOffset; - RK_S32 PreviousFrameNumOffset; - RK_S32 ExpectedDeltaPerPicOrderCntCycle; - RK_S32 ExpectedPicOrderCnt; - RK_S32 PicOrderCntCycleCnt; - RK_S32 FrameNumInPicOrderCntCycle; - RK_S32 ThisPOC; - RK_S32 type; - RK_U32 dec_no; - //!< for control running - RK_S32 have_outpicture_flag; - RK_S32 exit_picture_flag; - RK_S32 active_mvc_sps_flag; - - RK_U32 g_framecnt; - -} H264dVideoCtx_t; - -typedef struct h264d_mem_t { - struct h264_dpb_mark_t dpb_mark[MAX_DPB_SIZE]; //!< for write out, MAX_DPB_SIZE - struct h264_dpb_info_t dpb_info[DPB_INFO_SIZE]; //!< 16 - struct h264_refpic_info_t refpic_info_p[REFPIC_INFO_SIZE]; //!< 32 - struct h264_refpic_info_t refpic_info[2][REFPIC_INFO_SIZE]; //!< [2][32] - struct h264d_dxva_ctx_t dxva_ctx[MAX_TASK_SIZE]; -} H264_DecMem_t; - -//!< nalu state used in read nalu -typedef enum nalu_state_tpye { - NALU_NULL = 0, - - //StreamError, - HaveNoStream, - NaluNotSupport, - //ReadNaluError, - //StartofNalu, - EndofStream, - //ReallocBufError, - MidOfNalu, - EndOfNalu, - StartOfPicture, - StartOfSlice, - SkipNALU, - NALU_SPS, - NALU_SubSPS, - NALU_PPS, - NALU_SEI, - - NALU_MAX, -} NALU_STATUS; - -//!< slice state used in parse loop -typedef enum slice_state_type { - SliceSTATE_NULL = 0, - SliceSTATE_IDLE, - - SliceSTATE_ResetSlice, - SliceSTATE_ReadNalu, - SliceSTATE_ParseNalu, - SliceSTATE_InitPicture, - ////SliceSTATE_InitSlice, - SliceSTATE_GetSliceData, - //SliceSTATE_RegisterOneSlice, - SliceSTATE_RegisterOneFrame, - SliceSTATE_Error, - SliceSTATE_MAX, - -} SLICE_STATUS; - - - -//!< decoder video parameter -typedef struct h264_dec_ctx_t { - struct h264d_mem_t *mem; - struct h264_dpb_mark_t *dpb_mark; //!< for write out, MAX_DPB_SIZE - struct h264_dpb_info_t *dpb_info; //!< 16 - struct h264_refpic_info_t *refpic_info_p; //!< 32 - struct h264_refpic_info_t *refpic_info[2]; //!< [2][32] - struct h264d_dxva_ctx_t *dxva_ctx; - - struct h264d_input_ctx_t *p_Inp; - struct h264d_cur_ctx_t *p_Cur; //!< current parameters, use in read nalu - struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder - RK_U32 spt_decode_mtds; //!< support decoder methods - NALU_STATUS nalu_ret; //!< current nalu state - SLICE_STATUS next_state; //!< RKV_SLICE_STATUS - RK_U8 first_frame_flag; - RK_U8 parser_end_flag; - RK_U8 dxva_idx; - struct h264d_logctx_t logctx; //!< debug log file - struct log_ctx_t logctxbuf[LOG_MAX]; -} H264_DecCtx_t; - - - -#endif /* __H264D_GLOBAL_H__ */ \ No newline at end of file +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264D_GLOBAL_H +#define H264D_GLOBAL_H + +#include + +#include "mpp_soc.h" +#include "mpp_debug.h" +#include "mpp_frame.h" +#include "mpp_bitread.h" +#include "mpp_mem_pool.h" +#include "mpp_buf_slot.h" +#include "mpp_dec_cfg.h" + +#include "h264d_syntax.h" +#include "h2645d_sei.h" +#include "hal_dec_task.h" + +#define H264D_DBG_ERROR (0x00000001) +#define H264D_DBG_ASSERT (0x00000002) +#define H264D_DBG_WARNNING (0x00000004) +#define H264D_DBG_LOG (0x00000008) + +#define H264D_DBG_INPUT (0x00000010) //!< input packet +#define H264D_DBG_PPS_SPS (0x00000020) +#define H264D_DBG_LOOP_STATE (0x00000040) +#define H264D_DBG_PARSE_NALU (0x00000080) + +#define H264D_DBG_DPB_INFO (0x00000100) //!< dpb size +#define H264D_DBG_DPB_MALLIC (0x00000200) //!< malloc + +#define H264D_DBG_DPB_REF_ERR (0x00001000) +#define H264D_DBG_SLOT_FLUSH (0x00002000) //!< dpb buffer slot remain +#define H264D_DBG_SEI (0x00004000) +#define H264D_DBG_CALLBACK (0x00008000) + +#define H264D_DBG_WRITE_ES_EN (0x00010000) //!< write input ts stream +#define H264D_DBG_FIELD_PAIRED (0x00020000) +#define H264D_DBG_DISCONTINUOUS (0x00040000) + +extern RK_U32 h264d_debug; + +#define H264D_DBG(level, fmt, ...)\ +do {\ + if (level & h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + + +#define H264D_ERR(fmt, ...)\ +do {\ + if (H264D_DBG_ERROR & h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define ASSERT(val)\ +do {\ + if (H264D_DBG_ASSERT & h264d_debug)\ + { mpp_assert(val); }\ +} while (0) + +#define H264D_WARNNING(fmt, ...)\ +do {\ + if (H264D_DBG_WARNNING & h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define H264D_LOG(fmt, ...)\ +do {\ + if (H264D_DBG_LOG & h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + + +//!< vaule check +#define VAL_CHECK(ret, val, ...)\ +do{\ + if (!(val)){\ + ret = MPP_ERR_VALUE; \ + H264D_WARNNING("value error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do{\ + if (!(val)) {\ + ret = MPP_ERR_MALLOC; \ + H264D_ERR("malloc buffer error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + + +//!< input check +#define INP_CHECK(ret, val, ...)\ +do{\ +if ((val)) {\ + ret = MPP_ERR_INIT; \ + H264D_WARNNING("input empty(%d).\n", __LINE__); \ + goto __RETURN; \ +}} while (0) +//!< function return check +#define FUN_CHECK(val)\ +do{\ +if ((val) < 0) {\ + H264D_WARNNING("Function error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + + +#define START_PREFIX_3BYTE 3 +#define MAX_NUM_DPB_LAYERS 2 //!< must >= 2 +#define MAX_LIST_SIZE 33 //!< for init list reorder +#define MAX_DPB_SIZE 16 //!< for prepare dpb info +#define MAX_REF_SIZE 32 //!< for prepare ref pic info + + +#define MAX_MARK_SIZE 35 //!< for malloc buffer mark, can be changed + +#define HEAD_BUF_MAX_SIZE (1*1024*1024) +#define HEAD_BUF_ADD_SIZE (512) +#define NALU_BUF_MAX_SIZE (2*1024*1024) +#define NALU_BUF_ADD_SIZE (512) +#define SODB_BUF_MAX_SIZE (2*1024*1024) +#define SODB_BUF_ADD_SIZE (512) + +//!< PPS parameters +#define MAXnum_slice_groups_minus1 8 +typedef enum { + H264ScalingList4x4Length = 16, + H264ScalingList8x8Length = 64, +} ScalingListLength; + +typedef enum { + STRUCT_NULL = 0, + TOP_FIELD = 0x1, + BOTTOM_FIELD = 0x2, + FRAME = 0x3, + STRUCT_MAX, +} PictureStructure; //!< New enum for field processing + +typedef enum { + PIC_ERR_NULL = 0, + PIC_ERR_TOP = 0x1, + PIC_ERR_BOT = 0x2, + PIC_ERR_FRAME = 0x3, + PIC_ERR_WHOLE = 0x3, + PIC_ERR_MAX, +} PictureError; + +typedef enum { + FIELD_ORDER_NULL, + FIELD_ORDER_TOP_FIRST, + FIELD_ORDER_BOT_FIRST, + FIELD_ORDER_SAME, + FIELD_ORDER_MAX +} FieldOrder; + +//!< Field Coding Types +typedef enum { + FRAME_CODING = 0, + FIELD_CODING = 1, + ADAPTIVE_CODING = 2, + FRAME_MB_PAIR_CODING = 3 +} CodingType; + +typedef enum { + LIST_0 = 0, + LIST_1 = 1, + BI_PRED = 2, + BI_PRED_L0 = 3, + BI_PRED_L1 = 4 +} ListType; + +typedef enum mpp_decmtd_type { + MPP_DEC_NULL = 0, + MPP_DEC_BY_SLICE = 0x1, + MPP_DEC_BY_FRAME = 0x2, + MPP_DEC_MAX, +} MppDecMtd_type; + +//!< NAL Unit structure +typedef struct h264_nalu_t { + RK_S32 startcodeprefix_len; //!< 4 for parameter sets and first slice in picture, 3 for everything else (suggested) + RK_U32 sodb_len; //!< Length of the NAL unit (Excluding the start code, which does not belong to the NALU) + RK_S32 forbidden_bit; //!< should be always FALSE + H264NaluType nalu_type; //!< NALU_TYPE_xxxx + H264NalRefIdcType nal_reference_idc; //!< NALU_PRIORITY_xxxx + RK_U8 *sodb_buf; //!< Data of the NAL unit (Excluding the start code, which does not belong to the NALU) + RK_U16 lost_packets; //!< true, if packet loss is detected, used in RTPNALU + //---- MVC extension + RK_S32 svc_extension_flag; //!< should be always 0, for MVC + RK_S32 non_idr_flag; //!< 0 = current is IDR + RK_S32 priority_id; //!< a lower value of priority_id specifies a higher priority + RK_S32 view_id; //!< view identifier for the NAL unit + RK_S32 temporal_id; //!< temporal identifier for the NAL unit + RK_S32 anchor_pic_flag; //!< anchor access unit + RK_S32 inter_view_flag; //!< inter-view prediction enable + RK_S32 reserved_one_bit; //!< shall be equal to 1 + RK_S32 MVCExt_is_valid; + RK_S32 MVCExt_is_prefixNALU; + //------ + RK_U8 ualu_header_bytes; //!< for rbsp start + RK_S32 used_bits; + +} H264_Nalu_t; + +typedef struct h264_nalu_svc_ext_t { + RK_U32 valid; + RK_U32 idr_flag; + RK_U32 priority_id; + RK_U32 no_inter_layer_pred_flag; + RK_U32 dependency_id; + RK_U32 quality_id; + RK_U32 temporal_id; + RK_U32 use_ref_base_pic_flag; + RK_U32 discardable_flag; + RK_U32 output_flag; +} H264_NaluSvcExt_t; + +typedef struct h264_nalu_mvc_ext_t { + RK_U32 valid; + RK_U32 non_idr_flag; + RK_U32 priority_id; + RK_U32 view_id; + RK_U32 temporal_id; + RK_U32 anchor_pic_flag; + RK_U32 inter_view_flag; + RK_U32 reserved_one_bit; + RK_U32 iPrefixNALU; +} H264_NaluMvcExt_t; + +//!< decoder refence picture marking +typedef struct h264_drpm_t { + RK_S32 memory_management_control_operation; + RK_S32 difference_of_pic_nums_minus1; + RK_S32 long_term_pic_num; + RK_S32 long_term_frame_idx; + RK_S32 max_long_term_frame_idx_plus1; + struct h264_drpm_t *Next; +} H264_DRPM_t; + +typedef enum { + Mem_NULL = 0, + Mem_Malloc = 1, + Mem_Clone = 2, + Mem_UnPaired = 3, + Mem_TopOnly = 4, + Mem_BotOnly = 5, + Mem_Fake = 6, + Mem_Max, +} H264_Mem_type; + +//!< decoder picture memory +typedef struct h264_dpb_mark_t { + RK_U8 top_used; + RK_U8 bot_used; + RK_U8 out_flag; + RK_U8 mark_idx; + MppFrame mframe; + RK_S32 slot_idx; + struct h264_store_pic_t *pic; +} H264_DpbMark_t; + +//!< decoder picture buffer information +typedef struct h264_dpb_info_t { + RK_U8 colmv_is_used; + RK_S32 slot_index; + + RK_S32 TOP_POC; + RK_S32 BOT_POC; + RK_U16 frame_num; + RK_U32 field_flag; + RK_U32 is_long_term; + RK_U32 is_ilt_flag; + RK_U32 long_term_frame_idx; + RK_U32 long_term_pic_num; + RK_U32 voidx; + RK_U32 view_id; + RK_U32 is_used; + RK_U32 top_valid; + RK_U32 bot_valid; + struct h264_store_pic_t *refpic; + + RK_U32 have_same; +} H264_DpbInfo_t; + +//!< refence picture information +typedef struct h264_refpic_info_t { + RK_U32 valid; + RK_S32 dpb_idx; + RK_S32 bottom_flag; +} H264_RefPicInfo_t; + +//!< definition a picture (field or frame) +typedef struct h264_store_pic_t { + RK_S32 structure; + RK_S32 poc; + RK_S32 top_poc; + RK_S32 bottom_poc; + RK_S32 frame_poc; + RK_S32 ThisPOC; + RK_S32 pic_num; + RK_S32 long_term_pic_num; + RK_S32 long_term_frame_idx; + + RK_U32 frame_num; + RK_U8 is_long_term; + RK_S32 used_for_reference; + RK_S32 is_output; + RK_S32 non_existing; + RK_S16 max_slice_id; + RK_S32 mb_aff_frame_flag; + RK_U32 PicWidthInMbs; + RK_U8 colmv_no_used_flag; + struct h264_store_pic_t *top_field; //!< for mb aff, if frame for referencing the top field + struct h264_store_pic_t *bottom_field; //!< for mb aff, if frame for referencing the bottom field + struct h264_store_pic_t *frame; //!< for mb aff, if field for referencing the combined frame + + RK_S32 slice_type; + RK_S32 idr_flag; + RK_S32 no_output_of_prior_pics_flag; + RK_S32 long_term_reference_flag; + RK_S32 adaptive_ref_pic_buffering_flag; + RK_S32 chroma_format_idc; + RK_S32 frame_mbs_only_flag; + RK_S32 frame_cropping_flag; + + RK_S32 frame_crop_left_offset; + RK_S32 frame_crop_right_offset; + RK_S32 frame_crop_top_offset; + RK_S32 frame_crop_bottom_offset; + RK_S32 width; + RK_S32 height; + RK_U32 width_after_crop; + RK_U32 height_after_crop; + + struct h264_drpm_t *dec_ref_pic_marking_buffer; //!< stores the memory management control operations + RK_S32 proc_flag; + RK_S32 view_id; + RK_S32 inter_view_flag; + RK_S32 anchor_pic_flag; + RK_S32 iCodingType; + + RK_S32 layer_id; + RK_U8 is_mmco_5; + RK_S32 poc_mmco5; + RK_S32 top_poc_mmco5; + RK_S32 bot_poc_mmco5; + RK_S32 combine_flag; // top && bottom field combined flag + H264_Mem_type mem_malloc_type; + struct h264_dpb_mark_t *mem_mark; +} H264_StorePic_t; + +//!< Frame Stores for Decoded Picture Buffer +typedef struct h264_frame_store_t { + RK_S32 is_used; //!< 0=empty; 1=top; 2=bottom; 3=both fields (or frame) + RK_S32 is_reference; //!< 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used + RK_S32 is_long_term; //!< 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used + RK_S32 is_orig_reference; //!< original marking by nal_ref_idc: 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used + RK_S32 is_non_existent; + RK_S32 frame_num_wrap; + RK_S32 long_term_frame_idx; + RK_S32 is_output; + RK_S32 poc; + RK_S32 view_id; + RK_S32 inter_view_flag[2]; + RK_S32 anchor_pic_flag[2]; + RK_S32 layer_id; + RK_S32 slice_type; + RK_U32 frame_num; + RK_S32 structure; + RK_U32 is_directout; + struct h264_store_pic_t *frame; + struct h264_store_pic_t *top_field; + struct h264_store_pic_t *bottom_field; + +} H264_FrameStore_t; + +//!< decode picture buffer +typedef struct h264_dpb_buf_t { + RK_U32 size; + RK_U32 used_size; + RK_U32 allocated_size; + RK_U32 ref_frames_in_buffer; + RK_U32 ltref_frames_in_buffer; + RK_U32 used_size_il; + + RK_S32 poc_interval; + RK_S32 last_output_poc; + RK_S32 last_output_view_id; + RK_S32 max_long_term_pic_idx; + RK_S32 init_done; + RK_S32 num_ref_frames; + RK_S32 layer_id; + + struct h264_frame_store_t **fs; + struct h264_frame_store_t **fs_ref; + struct h264_frame_store_t **fs_ltref; + struct h264_frame_store_t **fs_ilref; //!< inter-layer reference (for multi-layered codecs) + struct h264_frame_store_t *last_picture; + + struct h264d_video_ctx_t *p_Vid; +} H264_DpbBuf_t; + +//!< HRD +#define MAXIMUMVALUEOFcpb_cnt 32 +typedef struct h264_hrd_t { + RK_U32 cpb_cnt_minus1; // ue(v) + RK_U32 bit_rate_scale; // u(4) + RK_U32 cpb_size_scale; // u(4) + RK_U32 bit_rate_value_minus1[MAXIMUMVALUEOFcpb_cnt]; // ue(v) + RK_U32 cpb_size_value_minus1[MAXIMUMVALUEOFcpb_cnt]; // ue(v) + RK_U32 cbr_flag[MAXIMUMVALUEOFcpb_cnt]; // u(1) + RK_U32 initial_cpb_removal_delay_length_minus1; // u(5) + RK_U32 cpb_removal_delay_length_minus1; // u(5) + RK_U32 dpb_output_delay_length_minus1; // u(5) + RK_U32 time_offset_length; // u(5) +} H264_HRD_t; + +//!< VUI +typedef struct h264_vui_t { + RK_S32 aspect_ratio_info_present_flag; // u(1) + RK_U32 aspect_ratio_idc; // u(8) + RK_U16 sar_width; // u(16) + RK_U16 sar_height; // u(16) + RK_S32 overscan_info_present_flag; // u(1) + RK_S32 overscan_appropriate_flag; // u(1) + RK_S32 video_signal_type_present_flag; // u(1) + RK_U32 video_format; // u(3) + RK_S32 video_full_range_flag; // u(1) + RK_S32 colour_description_present_flag; // u(1) + RK_U32 colour_primaries; // u(8) + RK_U32 transfer_characteristics; // u(8) + RK_U32 matrix_coefficients; // u(8) + RK_S32 chroma_location_info_present_flag; // u(1) + RK_U32 chroma_sample_loc_type_top_field; // ue(v) + RK_U32 chroma_sample_loc_type_bottom_field; // ue(v) + RK_S32 timing_info_present_flag; // u(1) + RK_U32 num_units_in_tick; // u(32) + RK_U32 time_scale; // u(32) + RK_S32 fixed_frame_rate_flag; // u(1) + RK_S32 nal_hrd_parameters_present_flag; // u(1) + struct h264_hrd_t nal_hrd_parameters; // hrd_paramters_t + RK_S32 vcl_hrd_parameters_present_flag; // u(1) + struct h264_hrd_t vcl_hrd_parameters; // hrd_paramters_t + // if ((nal_hrd_parameters_present_flag || (vcl_hrd_parameters_present_flag)) + RK_S32 low_delay_hrd_flag; // u(1) + RK_S32 pic_struct_present_flag; // u(1) + RK_S32 bitstream_restriction_flag; // u(1) + RK_S32 motion_vectors_over_pic_boundaries_flag; // u(1) + RK_U32 max_bytes_per_pic_denom; // ue(v) + RK_U32 max_bits_per_mb_denom; // ue(v) + RK_U32 log2_max_mv_length_vertical; // ue(v) + RK_U32 log2_max_mv_length_horizontal; // ue(v) + RK_U32 num_reorder_frames; // ue(v) + RK_U32 max_dec_frame_buffering; // ue(v) +} H264_VUI_t; + +//!< MVC_VUI +typedef struct h264_mvc_vui_t { + RK_S32 num_ops_minus1; + RK_S8 *temporal_id; + RK_S32 *num_target_output_views_minus1; + RK_S32 **view_id; + RK_S8 *timing_info_present_flag; + RK_S32 *num_units_in_tick; + RK_S32 *time_scale; + RK_S8 *fixed_frame_rate_flag; + RK_S8 *nal_hrd_parameters_present_flag; + RK_S8 *vcl_hrd_parameters_present_flag; + RK_S8 *low_delay_hrd_flag; + RK_S8 *pic_struct_present_flag; + + //hrd parameters; + RK_S8 cpb_cnt_minus1; + RK_S8 bit_rate_scale; + RK_S8 cpb_size_scale; + RK_S32 bit_rate_value_minus1[32]; + RK_S32 cpb_size_value_minus1[32]; + RK_S8 cbr_flag[32]; + RK_S8 initial_cpb_removal_delay_length_minus1; + RK_S8 cpb_removal_delay_length_minus1; + RK_S8 dpb_output_delay_length_minus1; + RK_S8 time_offset_length; +} H264_mvcVUI_t; + +//!< PREFIX + +typedef struct h264_prefix_t { + RK_S32 Valid; // indicates the prefix set is valid + // nal svc syntax + RK_S32 store_ref_base_pic_flag; // u(1) + // svc base pic marking + RK_S32 adaptive_ref_base_pic_marking_mode_flag; + RK_S32 memory_management_base_control_operation; + RK_S32 difference_of_base_pic_nums_minus1; + RK_S32 long_term_base_pic_num; + + RK_S32 additional_prefix_nal_unit_extension_flag; // u(1) + RK_S32 additional_prefix_nal_unit_extension_data_flag; // u(1) +} H264_PREFIX_t; + +//!< SPS +#define MAXnum_ref_frames_in_POC_cycle 256 + +typedef struct h264_sps_t { + RK_S32 Valid; // indicates the parameter set is valid + + RK_S32 profile_idc; // u(8) + RK_S32 constrained_set0_flag; // u(1) + RK_S32 constrained_set1_flag; // u(1) + RK_S32 constrained_set2_flag; // u(1) + RK_S32 constrained_set3_flag; // u(1) + RK_S32 constrained_set4_flag; // u(1) + RK_S32 constrained_set5_flag; // u(2) + + RK_S32 level_idc; // u(8) + RK_U32 seq_parameter_set_id; // ue(v) + RK_S32 chroma_format_idc; // ue(v) + + RK_S32 seq_scaling_matrix_present_flag; // u(1) + RK_S32 seq_scaling_list_present_flag[12]; // u(1) + RK_S32 ScalingList4x4[6][H264ScalingList4x4Length]; // se(v) + RK_S32 ScalingList8x8[6][H264ScalingList8x8Length]; // se(v) + RK_S32 UseDefaultScalingMatrix4x4Flag[6]; + RK_S32 UseDefaultScalingMatrix8x8Flag[6]; + + RK_S32 bit_depth_luma_minus8; // ue(v) + RK_S32 bit_depth_chroma_minus8; // ue(v) + RK_S32 log2_max_frame_num_minus4; // ue(v) + RK_S32 pic_order_cnt_type; + // if( pic_order_cnt_type == 0 ) + RK_S32 log2_max_pic_order_cnt_lsb_minus4; // ue(v) + // else if( pic_order_cnt_type == 1 ) + RK_S32 delta_pic_order_always_zero_flag; // u(1) + RK_S32 offset_for_non_ref_pic; // se(v) + RK_S32 offset_for_top_to_bottom_field; // se(v) + RK_S32 num_ref_frames_in_pic_order_cnt_cycle; // ue(v) + // for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ ) + RK_S32 offset_for_ref_frame[MAXnum_ref_frames_in_POC_cycle]; // se(v) + RK_S32 max_num_ref_frames; // ue(v) + RK_S32 gaps_in_frame_num_value_allowed_flag; // u(1) + RK_S32 pic_width_in_mbs_minus1; // ue(v) + RK_S32 pic_height_in_map_units_minus1; // ue(v) + RK_S32 frame_mbs_only_flag; // u(1) + // if( !frame_mbs_only_flag ) + RK_S32 mb_adaptive_frame_field_flag; // u(1) + RK_S32 direct_8x8_inference_flag; // u(1) + RK_S32 frame_cropping_flag; // u(1) + RK_S32 frame_crop_left_offset; // ue(v) + RK_S32 frame_crop_right_offset; // ue(v) + RK_S32 frame_crop_top_offset; // ue(v) + RK_S32 frame_crop_bottom_offset; // ue(v) + RK_S32 vui_parameters_present_flag; // u(1) + struct h264_vui_t vui_seq_parameters; // vui_seq_parameters_t + RK_S32 separate_colour_plane_flag; // u(1) + RK_S32 max_dec_frame_buffering; + RK_S32 qpprime_y_zero_transform_bypass_flag; + //---- + RK_S32 expected_delta_per_pic_order_cnt_cycle; + +} H264_SPS_t; + +//!< subSPS +typedef struct h264_subsps_t { + struct h264_sps_t sps; + + RK_S32 bit_equal_to_one; + RK_S32 num_views_minus1; + RK_S32 *view_id; + RK_S32 *num_anchor_refs_l0; + RK_S32 **anchor_ref_l0; + RK_S32 *num_anchor_refs_l1; + RK_S32 **anchor_ref_l1; + + RK_S32 *num_non_anchor_refs_l0; + RK_S32 **non_anchor_ref_l0; + RK_S32 *num_non_anchor_refs_l1; + RK_S32 **non_anchor_ref_l1; + + RK_S32 num_level_values_signalled_minus1; + RK_S32 *level_idc; + RK_S32 *num_applicable_ops_minus1; + RK_S32 **applicable_op_temporal_id; + RK_S32 **applicable_op_num_target_views_minus1; + RK_S32 ***applicable_op_target_view_id; + RK_S32 **applicable_op_num_views_minus1; + + RK_S32 mvc_vui_parameters_present_flag; + RK_S32 Valid; // indicates the parameter set is valid + +} H264_subSPS_t; + +//!< PPS + +typedef struct h264_pps_t { + RK_S32 Valid; // indicates the parameter set is valid + RK_U32 pic_parameter_set_id; // ue(v) + RK_U32 seq_parameter_set_id; // ue(v) + RK_S32 entropy_coding_mode_flag; // u(1) + RK_S32 transform_8x8_mode_flag; // u(1) + + RK_S32 pic_scaling_matrix_present_flag; // u(1) + RK_S32 pic_scaling_list_present_flag[12]; // u(1) + RK_S32 ScalingList4x4[6][H264ScalingList4x4Length]; // se(v) + RK_S32 ScalingList8x8[6][H264ScalingList8x8Length]; // se(v) + RK_S32 UseDefaultScalingMatrix4x4Flag[6]; + RK_S32 UseDefaultScalingMatrix8x8Flag[6]; + + // if( pic_order_cnt_type < 2 ) in the sequence parameter set + RK_S32 bottom_field_pic_order_in_frame_present_flag; // u(1) + RK_S32 num_slice_groups_minus1; // ue(v) + RK_S32 slice_group_map_type; // ue(v) + // if( slice_group_map_type = = 0 ) + RK_S32 run_length_minus1[MAXnum_slice_groups_minus1]; // ue(v) + // else if( slice_group_map_type = = 2 ) + RK_S32 top_left[MAXnum_slice_groups_minus1]; // ue(v) + RK_S32 bottom_right[MAXnum_slice_groups_minus1]; // ue(v) + // else if( slice_group_map_type = = 3 || 4 || 5 + RK_S32 slice_group_change_direction_flag; // u(1) + RK_S32 slice_group_change_rate_minus1; // ue(v) + // else if( slice_group_map_type = = 6 ) + RK_S32 pic_size_in_map_units_minus1; // ue(v) + RK_U8 *slice_group_id; // complete MBAmap u(v) + + RK_S32 num_ref_idx_l0_default_active_minus1; // ue(v) + RK_S32 num_ref_idx_l1_default_active_minus1; // ue(v) + RK_S32 weighted_pred_flag; // u(1) + RK_S32 weighted_bipred_idc; // u(2) + RK_S32 pic_init_qp_minus26; // se(v) + RK_S32 pic_init_qs_minus26; // se(v) + RK_S32 chroma_qp_index_offset; // se(v) + + RK_S32 cb_qp_index_offset; // se(v) + RK_S32 cr_qp_index_offset; // se(v) + RK_S32 second_chroma_qp_index_offset; // se(v) + + RK_S32 deblocking_filter_control_present_flag; // u(1) + RK_S32 constrained_intra_pred_flag; // u(1) + RK_S32 redundant_pic_cnt_present_flag; // u(1) + RK_S32 vui_pic_parameters_flag; // u(1) + RK_S32 scaleing_list_enable_flag; + RK_U32 scaleing_list_address; + +} H264_PPS_t; + +//!< MVC_scalable_nesting +typedef struct { + RK_S32 operation_point_flag; + RK_S32 all_view_components_in_au_flag; + RK_S32 num_view_components_minus1; + RK_S32 *sei_view_id; + RK_S32 num_view_components_op_minus1; + RK_S32 *sei_op_view_id; + RK_S32 sei_op_temporal_id; + RK_S32 Valid; +} MVC_scalable_nesting_t; + +//!< MVC_scalability_info +typedef struct { + RK_S32 num_operation_points_minus1; + RK_S32 *operation_point_id; + RK_S32 *priority_id; + RK_S32 *temporal_id; + RK_S32 *num_target_output_views_minus1; + RK_S32 **view_id; + RK_S32 *profile_level_info_present_flag; + RK_S32 *bitrate_info_present_flag; + RK_S32 *frm_rate_info_present_flag; + + RK_S32 *view_dependency_info_present_flag; + RK_S32 *parameter_sets_info_present_flag; + RK_S32 *bitstream_restriction_info_present_flag; + RK_S32 *op_profile_level_idc; + RK_S32 *avg_bitrate; + RK_S32 *max_bitrate; + RK_S32 *max_bitrate_calc_window; + RK_S32 *constant_frm_rate_idc; + RK_S32 *avg_frm_rate; + RK_S32 *num_directly_dependent_views; + RK_S32 **directly_dependent_view_id; + RK_S32 *view_dependency_info_src_op_id; + RK_S32 *num_seq_parameter_sets; + RK_S32 **seq_parameter_set_id_delta; + RK_S32 *num_subset_seq_parameter_sets; + RK_S32 **subset_seq_parameter_set_id_delta; + RK_S32 *num_pic_parameter_sets_minus1; + RK_S32 **pic_parameter_set_id_delta; + RK_S32 *parameter_sets_info_src_op_id; + RK_S32 *motion_vectors_over_pic_boundaries_flag; + RK_S32 *max_bytes_per_pic_denom; + RK_S32 *max_bits_per_mb_denom; + RK_S32 *log2_max_mv_length_horizontal; + RK_S32 *log2_max_mv_length_vertical; + RK_S32 *max_num_reorder_frames; + RK_S32 *max_dec_frame_buffering; +} MVC_scalability_info_t; + +typedef struct h264_sei_pic_timing_t { + RK_S32 cpb_removal_delay; + RK_S32 dpb_output_delay; + RK_S32 pic_struct; + RK_S32 clock_timestamp_flag[3]; + RK_S32 clock_timestamp[3]; + RK_S32 ct_type[3]; + RK_S32 nuit_field_based_flag[3]; + RK_S32 counting_type[3]; + RK_S32 full_timestamp_flag[3]; + RK_S32 discontinuity_flag[3]; + RK_S32 cnt_dropped_flag[3]; + RK_S32 n_frames[3]; + RK_S32 seconds_flag[3]; + RK_S32 seconds_value[3]; + RK_S32 minutes_flag[3]; + RK_S32 minutes_value[3]; + RK_S32 hours_flag[3]; + RK_S32 hours_value[3]; + RK_S32 time_offset[3]; +} H264_SEI_PIC_TIMING_t; + +//!< SEI struct +typedef struct h264_sei_t { + RK_S32 type; + RK_S32 payload_size; + struct { + RK_U32 recovery_frame_cnt; + RK_S32 exact_match_flag; + RK_S32 broken_link_flag; + RK_S32 changing_slice_group_idc; + } recovery_point; + struct { + RK_S32 operation_point_flag; + //-- for adding + } scalable_nesting; + + // Placeholder; in future more supported types will contribute to more + //---- follow is used in other parts + RK_S32 mvc_scalable_nesting_flag; + RK_U32 seq_parameter_set_id; + + H264_SEI_PIC_TIMING_t pic_timing; + + struct h264_dec_ctx_t *p_Dec; +} H264_SEI_t; + +//!< SLICE +typedef struct h264_slice_t { + struct h264_nalu_svc_ext_t svcExt; + struct h264_nalu_mvc_ext_t mvcExt; + //--- slice property; + RK_S32 layer_id; + RK_S32 idr_flag; + RK_S32 idr_pic_id; + RK_S32 nal_reference_idc; //!< nal_reference_idc from NAL unit + RK_U32 start_mb_nr; //!< MUST be set by NAL even in case of ei_flag == 1 + RK_S32 slice_type; //!< slice type + RK_U32 pic_parameter_set_id; + RK_S32 colour_plane_id; + RK_S32 frame_num; + RK_S32 field_pic_flag; + RK_S32 bottom_field_flag; + RK_S32 structure; + RK_S32 mb_aff_frame_flag; + RK_S32 pic_order_cnt_lsb; // for poc mode 0 + RK_S32 delta_pic_order_cnt_bottom; + RK_S32 delta_pic_order_cnt[2]; // for poc mode 1 + RK_U32 poc_used_bitlen; + RK_S32 redundant_pic_cnt; + RK_S32 direct_spatial_mv_pred_flag; + RK_S32 num_ref_idx_active[2]; //!< number of available list references + RK_S32 num_ref_idx_override_flag; + RK_S32 ref_pic_list_reordering_flag[2]; + RK_S32 *modification_of_pic_nums_idc[2]; + RK_S32 *abs_diff_pic_num_minus1[2]; + RK_S32 *long_term_pic_idx[2]; + RK_S32 *abs_diff_view_idx_minus1[2]; + struct h264_drpm_t *dec_ref_pic_marking_buffer; + RK_U32 drpm_used_bitlen; + RK_S32 no_output_of_prior_pics_flag; + RK_S32 long_term_reference_flag; + RK_S32 adaptive_ref_pic_buffering_flag; + RK_U32 model_number; + RK_S32 slice_qp_delta; + RK_S32 qp; + RK_S32 current_mb_nr; + RK_S32 ThisPOC; + RK_S32 toppoc; //poc for this top field + RK_S32 bottompoc; //poc of bottom field of frame + RK_S32 framepoc; //poc of this frame + RK_U32 AbsFrameNum; + RK_S32 PicOrderCntMsb; + //RK_S32 new_frame_flag; + struct h264_sps_t *active_sps; + struct h264_subsps_t *active_subsps; + struct h264_pps_t *active_pps; + + struct h264_dpb_buf_t *p_Dpb; + struct h264_dpb_buf_t *p_Dpb_layer[MAX_NUM_DPB_LAYERS]; + //---- + RK_S32 listinterviewidx0; + RK_S32 listinterviewidx1; + + RK_U8 listXsizeP[2]; + RK_U8 listXsizeB[2]; + + struct h264_frame_store_t **fs_listinterview0; + struct h264_frame_store_t **fs_listinterview1; + //struct h264_store_pic_t **listX[6]; + struct h264_store_pic_t **listP[MAX_NUM_DPB_LAYERS]; + struct h264_store_pic_t **listB[MAX_NUM_DPB_LAYERS]; + + //---- MVC extend ---- + RK_S32 svc_extension_flag; // should be always 0, for MVC + RK_S32 non_idr_flag; // 0 = current is IDR + RK_S32 priority_id; // a lower value of priority_id specifies a higher priority + RK_S32 view_id; // view identifier for the NAL unit + RK_S32 temporal_id; // temporal identifier for the NAL unit + RK_S32 anchor_pic_flag; // anchor access unit + RK_S32 inter_view_flag; // inter-view prediction enable + RK_S32 reserved_one_bit; // shall be equal to 1 + RK_S32 MVCExt_is_valid; + RK_S32 MVCExt_is_prefixNALU; + + struct h264_dec_ctx_t *p_Dec; // H264_DecCtx_t + struct h264d_input_ctx_t *p_Inp; // H264_InputParameters + struct h264d_cur_ctx_t *p_Cur; // H264_CurParameters + struct h264d_video_ctx_t *p_Vid; +} H264_SLICE_t; + +//!< Old slice parameter for check new frame +typedef struct h264_old_slice_par_t { + RK_U32 current_mb_nr; + RK_U8 field_pic_flag; + RK_U8 frame_num; + RK_S32 nal_ref_idc; + RK_U8 pic_oder_cnt_lsb; + RK_S32 delta_pic_oder_cnt_bottom; + RK_S32 delta_pic_order_cnt[2]; + RK_U8 bottom_field_flag; + RK_U8 idr_flag; + RK_S32 idr_pic_id; + RK_U32 pps_id; + RK_S32 view_id; + RK_S32 inter_view_flag; + RK_S32 anchor_pic_flag; + RK_S32 layer_id; +} H264_OldSlice_t; + +//!< DXVA context +#define MAX_SLICE_NUM (20) +#define ADD_SLICE_SIZE (5) +#define BITSTREAM_MAX_SIZE (2*1024*1024) +#define BITSTREAM_ADD_SIZE (512) +#define SYNTAX_BUF_SIZE (5) +typedef struct h264d_dxva_ctx_t { + RK_U8 cfgBitstrmRaw; + struct DXVA_PicParams_H264_MVC_t pp; + struct DXVA_Qmatrix_H264_t qm; + RK_U32 max_slice_size; + RK_U32 slice_count; + struct DXVA_Slice_H264_Long_t *slice_long; //!< MAX_SLICES + RK_U8 *bitstream; + RK_U32 max_strm_size; + RK_U32 strm_offset; + struct h264d_syntax_t syn; + struct h264_dec_ctx_t *p_Dec; +} H264dDxvaCtx_t; + +//!< input parameter +typedef struct h264d_input_ctx_t { + struct h264_dec_ctx_t *p_Dec; + struct h264d_cur_ctx_t *p_Cur; //!< current parameters, use in read nalu + struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder + enum mpp_decmtd_type dec_mtd; + + //!< input data + RK_U8 *in_buf; + size_t in_length; + RK_U32 pkt_eos; + + MppPacket in_pkt; + + RK_S64 in_pts; + RK_S64 in_dts; + RK_U8 has_get_eos; + RK_U32 max_buf_size; + //!< output data + RK_U8 task_valid; + RK_U32 task_eos; + + //!< have extradata + RK_U8 is_nalff; + RK_U8 profile; + RK_U8 level; + RK_U32 nal_size; + RK_S32 sps_num; + RK_S32 pps_num; + //!< write stream + char fname[2][512]; + FILE *fp; + RK_U8 *spspps_buf; + RK_U32 spspps_size; + RK_U32 spspps_len; + RK_U32 spspps_offset; + RK_U32 spspps_update_flag; + +} H264dInputCtx_t; + + +//!< current stream +typedef struct h264d_curstrm_t { + RK_U32 nalu_offset; //!< The offset of the input stream + RK_U32 nalu_max_size; //!< Cur Unit Buffer size + RK_U8 *curdata; + + RK_S32 nalu_type; + RK_U32 nalu_len; + RK_U8 *nalu_buf; //!< store read nalu data + + RK_U32 head_offset; + RK_U32 head_max_size; + RK_U8 *head_buf; //!< store header data, sps/pps/slice header + + RK_U32 first_mb_in_slice; //!< mark current slice + RK_U32 tmp_offset; + RK_U32 tmp_max_size; + RK_U8 *tmp_buf; //!< store temporary header data + + RK_U32 prefixdata; + RK_U8 startcode_found; + RK_U8 endcode_found; + +} H264dCurStream_t; + +#define MAX_REORDER_TIMES 33 // MVC: 2 * H264_MAX_REFS + 1 +#define MAX_MARKING_TIMES 35 +//!< current parameters +typedef struct h264d_cur_ctx_t { + struct h264_sps_t sps; + struct h264_subsps_t *subsps; + struct h264_pps_t pps; + struct h264_prefix_t prefix; + struct h264_sei_t *sei; + struct h264_nalu_t nalu; + struct bitread_ctx_t bitctx; //!< for control bit_read + struct h264d_curstrm_t strm; + struct h264_slice_t slice; + + struct h264_store_pic_t **listP[MAX_NUM_DPB_LAYERS]; + struct h264_store_pic_t **listB[MAX_NUM_DPB_LAYERS]; + struct h264d_input_ctx_t *p_Inp; + struct h264_dec_ctx_t *p_Dec; + struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder + + RK_S64 last_pts; + RK_S64 last_dts; + RK_S64 curr_pts; + RK_S64 curr_dts; + //!< malloc buffer for current slice + RK_S32 modification_of_pic_nums_idc[2][MAX_REORDER_TIMES]; + RK_S32 abs_diff_pic_num_minus1[2][MAX_REORDER_TIMES]; + RK_S32 long_term_pic_idx[2][MAX_REORDER_TIMES]; + RK_S32 abs_diff_view_idx_minus1[2][MAX_REORDER_TIMES]; + + struct h264_drpm_t *dec_ref_pic_marking_buffer[MAX_MARKING_TIMES]; + MppFrameHdrDynamicMeta *hdr_dynamic_meta; + RK_U32 hdr_dynamic; +} H264dCurCtx_t; + +//!< parameters for video decoder +typedef struct h264d_video_ctx_t { + struct h264_sps_t *spsSet[MAXSPS]; //!< MAXSPS, all sps storage + struct h264_subsps_t *subspsSet[MAXSPS]; //!< MAXSPS, all subpps storage + struct h264_pps_t *ppsSet[MAXPPS]; //!< MAXPPS, all pps storage + struct h264_sps_t *active_sps; + struct h264_subsps_t *active_subsps; + struct h264_pps_t *active_pps; + struct h264_dec_ctx_t *p_Dec; //!< H264_DecCtx_t + struct h264d_input_ctx_t *p_Inp; //!< H264_InputParameters + struct h264d_cur_ctx_t *p_Cur; //!< H264_CurParameters + struct h264_dpb_buf_t *p_Dpb_layer[MAX_NUM_DPB_LAYERS]; + struct h264_store_pic_t *dec_pic; //!< current decoder picture + struct h264_store_pic_t *last_pic; + + struct h264_store_pic_t *no_ref_pic; //!< no reference picture + struct h264_frame_store_t out_buffer; + struct h264_dpb_mark_t *active_dpb_mark[MAX_NUM_DPB_LAYERS]; //!< acitve_dpb_memory + + struct h264_store_pic_t old_pic; + + RK_S32 *qmatrix[12]; //!< scanlist pointer + RK_U32 stream_size; + RK_S32 last_toppoc[MAX_NUM_DPB_LAYERS]; + RK_S32 last_bottompoc[MAX_NUM_DPB_LAYERS]; + RK_S32 last_framepoc[MAX_NUM_DPB_LAYERS]; + RK_S32 last_thispoc[MAX_NUM_DPB_LAYERS]; + //!< + RK_S32 profile_idc; // u(8) + RK_S32 slice_type; + RK_S32 structure; + RK_S32 iNumOfSlicesDecoded; + RK_S32 no_output_of_prior_pics_flag; + RK_S32 last_has_mmco_5; + RK_S32 max_frame_num; + RK_U32 active_sps_id[MAX_NUM_DPB_LAYERS]; + RK_U32 PicWidthInMbs; + RK_U32 FrameHeightInMbs; + RK_S32 frame_mbs_only_flag; + RK_S32 yuv_format; + RK_U32 bit_depth_chroma; + RK_U32 bit_depth_luma; + RK_S32 width; + RK_S32 height; + RK_U32 width_after_crop; + RK_U32 height_after_crop; + RK_S32 width_cr; //!< width chroma + RK_S32 height_cr; //!< height chroma + RK_S32 last_pic_structure; + RK_S32 last_pic_bottom_field; + RK_S32 last_pic_width_in_mbs_minus1[2]; + RK_S32 last_pic_height_in_map_units_minus1[2]; + RK_S32 last_profile_idc[2]; + RK_S32 last_level_idc[2]; + RK_U32 last_sps_id; + RK_U32 last_pps_id; + RK_S32 PrevPicOrderCntMsb; + RK_S32 PrevPicOrderCntLsb; + RK_U32 PreviousFrameNum; + RK_U32 FrameNumOffset; + RK_S32 PreviousFrameNumOffset; + RK_S32 ExpectedDeltaPerPicOrderCntCycle; + RK_S32 ExpectedPicOrderCnt; + RK_S32 PicOrderCntCycleCnt; + RK_S32 FrameNumInPicOrderCntCycle; + RK_S32 ThisPOC; + RK_S32 type; + //!< for control running + RK_S32 have_outpicture_flag; + RK_S32 exit_picture_flag; + RK_S32 active_mvc_sps_flag; + //!< for error tolerance + RK_U32 g_framecnt; + RK_U32 dpb_size[MAX_NUM_DPB_LAYERS]; + + MppMemPool pic_st; + //!< spspps data update + RK_U32 spspps_update; + + RK_U32 dpb_fast_out; + RK_U32 dpb_first_fast_played; + RK_U32 last_ref_frame_num; + RK_U32 deny_flag; + RecoveryPoint recovery; +} H264dVideoCtx_t; + +typedef struct h264d_mem_t { + struct h264_dpb_mark_t dpb_mark[MAX_MARK_SIZE]; //!< for fpga register check, dpb mark + struct h264_dpb_info_t dpb_info[MAX_DPB_SIZE]; //!< 16 + struct h264_refpic_info_t refpic_info_p[MAX_REF_SIZE]; //!< 32 + struct h264_refpic_info_t refpic_info_b[2][MAX_REF_SIZE]; //!< [2][32] + struct h264d_dxva_ctx_t dxva_ctx; +} H264_DecMem_t; + +//!< nalu state used in read nalu +typedef enum nalu_state_tpye { + NALU_NULL = 0, + + StreamError, + HaveNoStream, + NaluNotSupport, + ReadNaluError, + StartofNalu, + EndofStream, + MvcDisAble, + MidOfNalu, + EndOfNalu, + StartOfPicture, + StartOfSlice, + SkipNALU, + NALU_SPS, + NALU_SubSPS, + NALU_PPS, + NALU_SEI, + + NALU_MAX, +} NALU_STATUS; + +//!< slice state used in parse loop +typedef enum slice_state_type { + SliceSTATE_NULL = 0, + SliceSTATE_IDLE, + + SliceSTATE_ResetSlice, + SliceSTATE_ReadNalu, + SliceSTATE_ParseNalu, + SliceSTATE_InitPicture, + ////SliceSTATE_InitSlice, + SliceSTATE_GetSliceData, + //SliceSTATE_RegisterOneSlice, + SliceSTATE_RegisterOneFrame, + SliceSTATE_Error, + SliceSTATE_MAX, + +} SLICE_STATUS; + +typedef struct h264_err_ctx_t { + RK_U32 un_spt_flag; + RK_U32 cur_err_flag; //!< current decoded picture error + RK_U32 used_ref_flag; + RK_U32 dpb_err_flag; //!< dpb storage had error + + RK_U32 i_slice_no; + RK_S32 first_iframe_poc; + RK_S32 first_iframe_is_output; +} H264dErrCtx_t; +//!< decoder video parameter +typedef struct h264_dec_ctx_t { + struct h264d_mem_t *mem; + struct h264_dpb_mark_t *dpb_mark; //!< for write out, MAX_DPB_SIZE + struct h264_dpb_info_t *dpb_info; //!< 16 + struct h264_refpic_info_t *refpic_info_p; //!< 32 + struct h264_refpic_info_t *refpic_info_b[2]; //!< [2][32] + struct h264d_dxva_ctx_t *dxva_ctx; + + struct h264d_input_ctx_t *p_Inp; + struct h264d_cur_ctx_t *p_Cur; //!< current parameters, use in read nalu + struct h264d_video_ctx_t *p_Vid; //!< parameters for video decoder + RK_U32 spt_decode_mtds; //!< support decoder methods + NALU_STATUS nalu_ret; //!< current nalu state + SLICE_STATUS next_state; //!< RKV_SLICE_STATUS + RK_U8 have_slice_data; + RK_U8 is_new_frame; + RK_U8 is_parser_end; + RK_U8 svc_valid; + RK_U8 mvc_valid; + //!< add + MppBufSlots frame_slots; //!< corresponding to dpb_mark + MppBufSlots packet_slots; + MppDecCfgSet *cfg; + const MppDecHwCap *hw_info; + + MppFrame curframe; + MppPacket task_pkt; + + RK_S64 task_pts; + RK_U32 task_eos; + HalDecTask *in_task; + RK_S32 last_frame_slot_idx; + RK_U32 immediate_out; + struct h264_err_ctx_t errctx; +} H264_DecCtx_t; + +#endif /* H264D_GLOBAL_H */ diff --git a/mpp/codec/dec/h264/h264d_init.c b/mpp/codec/dec/h264/h264d_init.c index 74beb7653..572ea8309 100644 --- a/mpp/codec/dec/h264/h264d_init.c +++ b/mpp/codec/dec/h264/h264d_init.c @@ -1,1167 +1,2134 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include - -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "h264d_init.h" -#include "h264d_dpb.h" -#include "h264d_scalist.h" -#include "h264d_fill.h" - -#define MODULE_TAG "h264d_init" - - - -static MPP_RET decode_poc(H264dVideoCtx_t *p_Vid, H264_SLICE_t *pSlice) -{ - RK_S32 i = 0; - RK_U32 MaxPicOrderCntLsb = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264_SPS_t *active_sps = p_Vid->active_sps; - // for POC mode 0: - MaxPicOrderCntLsb = (1 << (active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); - - switch (active_sps->pic_order_cnt_type) { - case 0: // POC MODE 0 - // 1st - if (pSlice->idr_flag) { - p_Vid->PrevPicOrderCntMsb = 0; - p_Vid->PrevPicOrderCntLsb = 0; - } else { - if (p_Vid->last_has_mmco_5) { - if (p_Vid->last_pic_bottom_field) { - p_Vid->PrevPicOrderCntMsb = 0; - p_Vid->PrevPicOrderCntLsb = 0; - } else { - p_Vid->PrevPicOrderCntMsb = 0; - p_Vid->PrevPicOrderCntLsb = pSlice->toppoc; - } - } - } - // Calculate the MSBs of current picture - if (pSlice->pic_order_cnt_lsb < p_Vid->PrevPicOrderCntLsb && - (p_Vid->PrevPicOrderCntLsb - pSlice->pic_order_cnt_lsb) >= (RK_S32)(MaxPicOrderCntLsb / 2)) { - pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb + MaxPicOrderCntLsb; - } else if (pSlice->pic_order_cnt_lsb > p_Vid->PrevPicOrderCntLsb && - (pSlice->pic_order_cnt_lsb - p_Vid->PrevPicOrderCntLsb) > (RK_S32)(MaxPicOrderCntLsb / 2)) { - pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb - MaxPicOrderCntLsb; - } else { - pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb; - } - // 2nd - if (pSlice->field_pic_flag == 0) { - //frame pix - pSlice->toppoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; - pSlice->bottompoc = pSlice->toppoc + pSlice->delta_pic_order_cnt_bottom; - pSlice->ThisPOC = pSlice->framepoc = (pSlice->toppoc < pSlice->bottompoc) ? pSlice->toppoc : pSlice->bottompoc; // POC200301 - } else if (pSlice->bottom_field_flag == 0) { - //top field - pSlice->ThisPOC = pSlice->toppoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; - } else { - //bottom field - pSlice->ThisPOC = pSlice->bottompoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; - } - pSlice->framepoc = pSlice->ThisPOC; - p_Vid->ThisPOC = pSlice->ThisPOC; - //if ( pSlice->frame_num != p_Vid->PreviousFrameNum) //Seems redundant - p_Vid->PreviousFrameNum = pSlice->frame_num; - if (pSlice->nal_reference_idc) { - p_Vid->PrevPicOrderCntLsb = pSlice->pic_order_cnt_lsb; - p_Vid->PrevPicOrderCntMsb = pSlice->PicOrderCntMsb; - } - break; - - case 1: // POC MODE 1 - // 1st - if (pSlice->idr_flag) { - p_Vid->FrameNumOffset = 0; // first pix of IDRGOP, - VAL_CHECK(ret, 0 == pSlice->frame_num); - } else { - if (p_Vid->last_has_mmco_5) { - p_Vid->PreviousFrameNumOffset = 0; - p_Vid->PreviousFrameNum = 0; - } - if (pSlice->frame_num < (RK_S32)p_Vid->PreviousFrameNum) { - //not first pix of IDRGOP - p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset + p_Vid->max_frame_num; - } else { - p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset; - } - } - // 2nd - if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) { - pSlice->AbsFrameNum = p_Vid->FrameNumOffset + pSlice->frame_num; - } else { - pSlice->AbsFrameNum = 0; - } - if ((!pSlice->nal_reference_idc) && pSlice->AbsFrameNum > 0) { - pSlice->AbsFrameNum--; - } - // 3rd - p_Vid->ExpectedDeltaPerPicOrderCntCycle = 0; - if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) { - for (i = 0; i < (RK_S32)active_sps->num_ref_frames_in_pic_order_cnt_cycle; i++) { - p_Vid->ExpectedDeltaPerPicOrderCntCycle += active_sps->offset_for_ref_frame[i]; - } - } - if (pSlice->AbsFrameNum) { - p_Vid->PicOrderCntCycleCnt = (pSlice->AbsFrameNum - 1) / active_sps->num_ref_frames_in_pic_order_cnt_cycle; - p_Vid->FrameNumInPicOrderCntCycle = (pSlice->AbsFrameNum - 1) % active_sps->num_ref_frames_in_pic_order_cnt_cycle; - p_Vid->ExpectedPicOrderCnt = p_Vid->PicOrderCntCycleCnt * p_Vid->ExpectedDeltaPerPicOrderCntCycle; - for (i = 0; i <= (RK_S32)p_Vid->FrameNumInPicOrderCntCycle; i++) - p_Vid->ExpectedPicOrderCnt += active_sps->offset_for_ref_frame[i]; - } else { - p_Vid->ExpectedPicOrderCnt = 0; - } - if (!pSlice->nal_reference_idc) { - p_Vid->ExpectedPicOrderCnt += active_sps->offset_for_non_ref_pic; - } - if (pSlice->field_pic_flag == 0) { - //frame pix - pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + pSlice->delta_pic_order_cnt[0]; - pSlice->bottompoc = pSlice->toppoc + active_sps->offset_for_top_to_bottom_field + pSlice->delta_pic_order_cnt[1]; - pSlice->ThisPOC = pSlice->framepoc = (pSlice->toppoc < pSlice->bottompoc) ? pSlice->toppoc : pSlice->bottompoc; // POC200301 - } else if (pSlice->bottom_field_flag == 0) { - //top field - pSlice->ThisPOC = pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + pSlice->delta_pic_order_cnt[0]; - } else { - //bottom field - pSlice->ThisPOC = pSlice->bottompoc = p_Vid->ExpectedPicOrderCnt + active_sps->offset_for_top_to_bottom_field + pSlice->delta_pic_order_cnt[0]; - } - pSlice->framepoc = pSlice->ThisPOC; - p_Vid->PreviousFrameNum = pSlice->frame_num; - p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; - break; - - - case 2: // POC MODE 2 - if (pSlice->idr_flag) { // IDR picture - p_Vid->FrameNumOffset = 0; // first pix of IDRGOP, - pSlice->ThisPOC = pSlice->framepoc = pSlice->toppoc = pSlice->bottompoc = 0; - VAL_CHECK(ret, 0 == pSlice->frame_num); - } else { - if (p_Vid->last_has_mmco_5) { - p_Vid->PreviousFrameNum = 0; - p_Vid->PreviousFrameNumOffset = 0; - } - if (pSlice->frame_num < (RK_S32)p_Vid->PreviousFrameNum) { - p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset + p_Vid->max_frame_num; - } else { - p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset; - } - pSlice->AbsFrameNum = p_Vid->FrameNumOffset + pSlice->frame_num; - if (!pSlice->nal_reference_idc) { - pSlice->ThisPOC = (2 * pSlice->AbsFrameNum - 1); - } else { - pSlice->ThisPOC = (2 * pSlice->AbsFrameNum); - } - if (pSlice->field_pic_flag == 0) { - pSlice->toppoc = pSlice->bottompoc = pSlice->framepoc = pSlice->ThisPOC; - } else if (pSlice->bottom_field_flag == 0) { - pSlice->toppoc = pSlice->framepoc = pSlice->ThisPOC; - } else { - pSlice->bottompoc = pSlice->framepoc = pSlice->ThisPOC; - } - } - p_Vid->PreviousFrameNum = pSlice->frame_num; - p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; - break; - default: - ret = MPP_NOK; - goto __FAILED; - } - return ret = MPP_OK; - -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET store_proc_picture_in_dpb(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; - H264_FrameStore_t *fs = p_Dpb->fs_ilref[0]; - - VAL_CHECK(ret, NULL != p); - if (p_Dpb->used_size_il > 0) { - if (fs->frame) { - free_storable_picture(fs->frame); - fs->frame = NULL; - } - if (fs->top_field) { - free_storable_picture(fs->top_field); - fs->top_field = NULL; - } - if (fs->bottom_field) { - free_storable_picture(fs->bottom_field); - fs->bottom_field = NULL; - } - fs->is_used = 0; - fs->is_reference = 0; - p_Dpb->used_size_il--; - } - if (fs->is_used > 0) { //checking; - if (p->structure == FRAME) { - VAL_CHECK(ret, fs->frame == NULL); - } else if (p->structure == TOP_FIELD) { - VAL_CHECK(ret, fs->top_field == NULL); - } else if (p->structure == BOTTOM_FIELD) { - VAL_CHECK(ret, fs->bottom_field == NULL); - } - } - FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, fs, p, 0)); - if ((p->structure == FRAME && fs->is_used == 3) - || (p->structure != FRAME && fs->is_used && fs->is_used < 3)) { - p_Dpb->used_size_il++; - } - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static void clone_dpb_memory_index(H264_DpbMark_t *pmem_dpb, RK_S32 structure, RK_S32 layer_id, RK_S32 framecnt) -{ - //!<---- index add ---- - if (structure == FRAME || structure == TOP_FIELD) { - pmem_dpb->top_used += 1; - } - if (structure == FRAME || structure == BOTTOM_FIELD) { - pmem_dpb->bot_used += 1; - } - (void)layer_id; - (void)framecnt; -} - -static H264_StorePic_t* clone_storable_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t *p_pic) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_StorePic_t *p_stored_pic = alloc_storable_picture(p_Vid, p_Vid->structure); - - MEM_CHECK(ret, p_stored_pic); - p_stored_pic->mem_malloc_type = Mem_Clone; - p_stored_pic->mem_mark = p_pic->mem_mark; - clone_dpb_memory_index(p_stored_pic->mem_mark, p_stored_pic->structure, p_pic->layer_id, p_Vid->g_framecnt); - p_stored_pic->colmv_no_used_flag = 1; // clone, colmv is not be used - - p_stored_pic->pic_num = p_pic->pic_num; - p_stored_pic->frame_num = p_pic->frame_num; - p_stored_pic->long_term_frame_idx = p_pic->long_term_frame_idx; - p_stored_pic->long_term_pic_num = p_pic->long_term_pic_num; - p_stored_pic->is_long_term = 0; - p_stored_pic->non_existing = p_pic->non_existing; - p_stored_pic->max_slice_id = p_pic->max_slice_id; - p_stored_pic->structure = p_pic->structure; - - p_stored_pic->mb_aff_frame_flag = p_pic->mb_aff_frame_flag; - p_stored_pic->poc = p_pic->poc; - p_stored_pic->top_poc = p_pic->top_poc; - p_stored_pic->bottom_poc = p_pic->bottom_poc; - p_stored_pic->frame_poc = p_pic->frame_poc; - p_stored_pic->is_mmco_5 = p_pic->is_mmco_5; - p_stored_pic->poc_mmco5 = p_pic->poc_mmco5; - p_stored_pic->top_poc_mmco5 = p_pic->top_poc_mmco5; - p_stored_pic->bot_poc_mmco5 = p_pic->bot_poc_mmco5; - p_stored_pic->pic_num = p_pic->pic_num; - p_stored_pic->frame_num = p_pic->frame_num; - p_stored_pic->slice_type = p_pic->slice_type; - p_stored_pic->idr_flag = p_pic->idr_flag; - p_stored_pic->no_output_of_prior_pics_flag = p_pic->no_output_of_prior_pics_flag; - p_stored_pic->long_term_reference_flag = 0; - p_stored_pic->adaptive_ref_pic_buffering_flag = 0; - p_stored_pic->dec_ref_pic_marking_buffer = NULL; - p_stored_pic->PicWidthInMbs = p_pic->PicWidthInMbs; - - p_stored_pic->chroma_format_idc = p_pic->chroma_format_idc; - p_stored_pic->frame_mbs_only_flag = p_pic->frame_mbs_only_flag; - p_stored_pic->frame_cropping_flag = p_pic->frame_cropping_flag; - if (p_stored_pic->frame_cropping_flag) { - p_stored_pic->frame_crop_left_offset = p_pic->frame_crop_left_offset; - p_stored_pic->frame_crop_right_offset = p_pic->frame_crop_right_offset; - p_stored_pic->frame_crop_top_offset = p_pic->frame_crop_top_offset; - p_stored_pic->frame_crop_bottom_offset = p_pic->frame_crop_bottom_offset; - } - // MVC-related parameters - p_stored_pic->inter_view_flag = p_pic->inter_view_flag; - p_stored_pic->anchor_pic_flag = 0; - p_stored_pic->view_id = p_pic->view_id; - p_stored_pic->layer_id = p_pic->layer_id; - p_stored_pic->proc_flag = 1; - p_stored_pic->is_output = 1; - p_stored_pic->used_for_reference = 1; - - return p_stored_pic; -__FAILED: - (void)ret; - ASSERT(0); - return NULL; -} - -static MPP_RET init_mvc_picture(H264_SLICE_t *currSlice) -{ - RK_U32 i = 0; - RK_S32 poc = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264_DpbBuf_t *p_Dpb = p_Vid->p_Dpb_layer[0]; - H264_StorePic_t *p_pic = NULL; - H264_FrameStore_t *fs = NULL; - H264_StorePic_t *p_clone = NULL; - - // find BL reconstructed picture - if (currSlice->structure == FRAME) { - for (i = 0; i < p_Dpb->used_size; i++) { - fs = p_Dpb->fs[i]; - if (fs->frame) { - poc = fs->frame->is_mmco_5 ? fs->frame->poc_mmco5 : fs->frame->poc; - } - if (fs->frame && (fs->frame->layer_id == 0) && (poc == currSlice->framepoc)) { - p_pic = fs->frame; - if (!fs->frame->is_mmco_5) { - break; - } - } - } - } else if (currSlice->structure == TOP_FIELD) { - for (i = 0; i < p_Dpb->used_size; i++) { - fs = p_Dpb->fs[i]; - if (fs->top_field) { - poc = fs->top_field->is_mmco_5 ? fs->top_field->top_poc_mmco5 : fs->top_field->top_poc; - } - if (fs->top_field && (fs->top_field->layer_id == 0) && (poc == currSlice->toppoc)) { - p_pic = fs->top_field; - if (!fs->top_field->is_mmco_5) { - break; - } - } - } - } else { - for (i = 0; i < p_Dpb->used_size; i++) { - fs = p_Dpb->fs[i]; - if (fs->bottom_field) { - poc = fs->bottom_field->is_mmco_5 ? fs->bottom_field->bot_poc_mmco5 : fs->bottom_field->bottom_poc; - } - if (fs->bottom_field && (fs->bottom_field->layer_id == 0) && (poc == currSlice->bottompoc)) { - p_pic = fs->bottom_field; - if (!fs->bottom_field->is_mmco_5) { - break; - } - } - } - } - if (p_pic) { - p_clone = clone_storable_picture(p_Vid, p_pic); - MEM_CHECK(ret, p_clone); - FUN_CHECK(ret = store_proc_picture_in_dpb(currSlice->p_Dpb, p_clone)); - } - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static void malloc_dpb_memory_index(H264dVideoCtx_t *p_Vid, RK_S32 structure, RK_U8 combine_flag, RK_S32 layer_id) -{ - RK_U8 idx = 1; - H264_DpbMark_t *pmem_dpb = p_Vid->p_Dec->dpb_mark; - - if (!combine_flag) { //--- malloc - while (pmem_dpb[idx].top_used || pmem_dpb[idx].bot_used) { - idx++; - } - ASSERT(idx <= MAX_DPB_SIZE); - p_Vid->active_dpb_mark[layer_id] = &pmem_dpb[idx]; - } - //--- index add ---- - if (structure == FRAME || structure == TOP_FIELD) { - p_Vid->active_dpb_mark[layer_id]->top_used += 1; - } - if (structure == FRAME || structure == BOTTOM_FIELD) { - p_Vid->active_dpb_mark[layer_id]->bot_used += 1; - } -} - -static MPP_RET alloc_decpic(H264_SLICE_t *currSlice) -{ - RK_S32 combine_flag = 0; - H264_StorePic_t *dec_picture = NULL; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264_SPS_t *active_sps = p_Vid->active_sps; - H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; - - dec_picture = alloc_storable_picture(p_Vid, currSlice->structure); - MEM_CHECK(ret, dec_picture); - currSlice->toppoc = p_Vid->last_toppoc[currSlice->layer_id]; - currSlice->bottompoc = p_Vid->last_bottompoc[currSlice->layer_id]; - currSlice->framepoc = p_Vid->last_framepoc[currSlice->layer_id]; - currSlice->ThisPOC = p_Vid->last_thispoc[currSlice->layer_id]; - FUN_CHECK(ret = decode_poc(p_Vid, currSlice)); //!< calculate POC - - dec_picture->top_poc = currSlice->toppoc; - dec_picture->bottom_poc = currSlice->bottompoc; - dec_picture->frame_poc = currSlice->framepoc; - dec_picture->ThisPOC = currSlice->ThisPOC; - - p_Vid->last_toppoc[currSlice->layer_id] = currSlice->toppoc; - p_Vid->last_bottompoc[currSlice->layer_id] = currSlice->bottompoc; - p_Vid->last_framepoc[currSlice->layer_id] = currSlice->framepoc; - p_Vid->last_thispoc[currSlice->layer_id] = currSlice->ThisPOC; - - if (currSlice->structure == FRAME) { - if (currSlice->mb_aff_frame_flag) { - dec_picture->iCodingType = FRAME_MB_PAIR_CODING; - } else { - dec_picture->iCodingType = FRAME_CODING; - } - } else { - dec_picture->iCodingType = FIELD_CODING; - } - dec_picture->layer_id = currSlice->layer_id; - dec_picture->view_id = currSlice->view_id; - dec_picture->inter_view_flag = currSlice->inter_view_flag; - dec_picture->anchor_pic_flag = currSlice->anchor_pic_flag; - if (dec_picture->layer_id == 1) { - if ((p_Vid->profile_idc == MVC_HIGH) || (p_Vid->profile_idc == STEREO_HIGH)) { - FUN_CHECK(ret = init_mvc_picture(currSlice)); - } - } - if (currSlice->structure == TOP_FIELD) { - dec_picture->poc = currSlice->toppoc; - } else if (currSlice->structure == BOTTOM_FIELD) { - dec_picture->poc = currSlice->bottompoc; - } else if (currSlice->structure == FRAME) { - dec_picture->poc = currSlice->framepoc; - } else { - ret = MPP_OK; - goto __FAILED; - } - dec_picture->slice_type = p_Vid->type; - dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0); - dec_picture->idr_flag = currSlice->idr_flag; - dec_picture->no_output_of_prior_pics_flag = currSlice->no_output_of_prior_pics_flag; - dec_picture->long_term_reference_flag = currSlice->long_term_reference_flag; - dec_picture->adaptive_ref_pic_buffering_flag = currSlice->adaptive_ref_pic_buffering_flag; - dec_picture->dec_ref_pic_marking_buffer = currSlice->dec_ref_pic_marking_buffer; - - currSlice->dec_ref_pic_marking_buffer = NULL; - dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag; - dec_picture->PicWidthInMbs = p_Vid->PicWidthInMbs; - dec_picture->pic_num = currSlice->frame_num; - dec_picture->frame_num = currSlice->frame_num; - dec_picture->chroma_format_idc = active_sps->chroma_format_idc; - - dec_picture->frame_mbs_only_flag = active_sps->frame_mbs_only_flag; - dec_picture->frame_cropping_flag = active_sps->frame_cropping_flag; - if (dec_picture->frame_cropping_flag) { - dec_picture->frame_crop_left_offset = active_sps->frame_crop_left_offset; - dec_picture->frame_crop_right_offset = active_sps->frame_crop_right_offset; - dec_picture->frame_crop_top_offset = active_sps->frame_crop_top_offset; - dec_picture->frame_crop_bottom_offset = active_sps->frame_crop_bottom_offset; - } - combine_flag = get_filed_dpb_combine_flag(p_Dpb, dec_picture); - dec_picture->mem_malloc_type = Mem_Malloc; - malloc_dpb_memory_index(p_Vid, dec_picture->structure, combine_flag, dec_picture->layer_id); // malloc dpb_memory - dec_picture->mem_mark = p_Vid->active_dpb_mark[currSlice->layer_id]; - dec_picture->colmv_no_used_flag = 0; - - p_Vid->last_pic_structure = dec_picture->structure; - p_Vid->dec_picture = dec_picture; - - return ret = MPP_OK; -__FAILED: - mpp_free(dec_picture); - ASSERT(0); - - return ret; -} - -static void update_pic_num(H264_SLICE_t *currSlice) -{ - RK_U32 i = 0; - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; - H264_SPS_t *active_sps = p_Vid->active_sps; - - RK_S32 add_top = 0, add_bottom = 0; - RK_S32 max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4); - - if (currSlice->idr_flag) { - return; - } - if (currSlice->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_used == 3) { - if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { - if ((RK_S32)p_Dpb->fs_ref[i]->frame_num > currSlice->frame_num) { - p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num - max_frame_num; - } else { - p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num; - } - p_Dpb->fs_ref[i]->frame->pic_num = p_Dpb->fs_ref[i]->frame_num_wrap; - } - } - } - //!< update long_term_pic_num - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->is_used == 3) { - if (p_Dpb->fs_ltref[i]->frame->is_long_term) { - p_Dpb->fs_ltref[i]->frame->long_term_pic_num = p_Dpb->fs_ltref[i]->frame->long_term_frame_idx; - } - } - } - } else { - if (currSlice->structure == TOP_FIELD) { - add_top = 1; - add_bottom = 0; - } else { - add_top = 0; - add_bottom = 1; - } - - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_reference) { - if ((RK_S32)p_Dpb->fs_ref[i]->frame_num > currSlice->frame_num) { - p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num - max_frame_num; - } else { - p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num; - } - if (p_Dpb->fs_ref[i]->is_reference & 1) { - p_Dpb->fs_ref[i]->top_field->pic_num = (2 * p_Dpb->fs_ref[i]->frame_num_wrap) + add_top; - } - if (p_Dpb->fs_ref[i]->is_reference & 2) { - p_Dpb->fs_ref[i]->bottom_field->pic_num = (2 * p_Dpb->fs_ref[i]->frame_num_wrap) + add_bottom; - } - } - } - //!< update long_term_pic_num - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->is_long_term & 1) { - p_Dpb->fs_ltref[i]->top_field->long_term_pic_num = 2 * p_Dpb->fs_ltref[i]->top_field->long_term_frame_idx + add_top; - } - if (p_Dpb->fs_ltref[i]->is_long_term & 2) { - p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num = 2 * p_Dpb->fs_ltref[i]->bottom_field->long_term_frame_idx + add_bottom; - } - } - } -} - -static MPP_RET init_picture_decoding(H264dVideoCtx_t *p_Vid, H264_SLICE_t *pSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - if (pSlice->layer_id && !pSlice->svc_extension_flag && !pSlice->mvcExt.non_idr_flag) { //!< MVC idr_flag==1 - ASSERT(pSlice->layer_id == 1); - FUN_CHECK(ret = idr_memory_management(p_Vid->p_Dpb_layer[pSlice->layer_id], p_Vid->dec_picture)); - } - update_ref_list(p_Vid->p_Dpb_layer[pSlice->layer_id]); - update_ltref_list(p_Vid->p_Dpb_layer[pSlice->layer_id]); - update_pic_num(pSlice); - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - - -static RK_S32 compare_pic_by_pic_num_desc(const void *arg1, const void *arg2) -{ - RK_S32 pic_num1 = (*(H264_StorePic_t**)arg1)->pic_num; - RK_S32 pic_num2 = (*(H264_StorePic_t**)arg2)->pic_num; - - if (pic_num1 < pic_num2) - return 1; - if (pic_num1 > pic_num2) - return -1; - else - return 0; -} - -static RK_S32 compare_pic_by_lt_pic_num_asc(const void *arg1, const void *arg2) -{ - RK_S32 long_term_pic_num1 = (*(H264_StorePic_t**)arg1)->long_term_pic_num; - RK_S32 long_term_pic_num2 = (*(H264_StorePic_t**)arg2)->long_term_pic_num; - - if (long_term_pic_num1 < long_term_pic_num2) - return -1; - if (long_term_pic_num1 > long_term_pic_num2) - return 1; - else - return 0; -} - -static RK_S32 compare_fs_by_frame_num_desc(const void *arg1, const void *arg2) -{ - RK_S32 frame_num_wrap1 = (*(H264_FrameStore_t**)arg1)->frame_num_wrap; - RK_S32 frame_num_wrap2 = (*(H264_FrameStore_t**)arg2)->frame_num_wrap; - if (frame_num_wrap1 < frame_num_wrap2) - return 1; - if (frame_num_wrap1 > frame_num_wrap2) - return -1; - else - return 0; -} - -static RK_S32 compare_fs_by_lt_pic_idx_asc(const void *arg1, const void *arg2) -{ - RK_S32 long_term_frame_idx1 = (*(H264_FrameStore_t**)arg1)->long_term_frame_idx; - RK_S32 long_term_frame_idx2 = (*(H264_FrameStore_t**)arg2)->long_term_frame_idx; - - if (long_term_frame_idx1 < long_term_frame_idx2) - return -1; - else if (long_term_frame_idx1 > long_term_frame_idx2) - return 1; - else - return 0; -} - -static RK_U32 is_long_ref(H264_StorePic_t *s) -{ - return ((s->used_for_reference) && (s->is_long_term)); -} - -static RK_U32 is_short_ref(H264_StorePic_t *s) -{ - return ((s->used_for_reference) && (!(s->is_long_term))); -} - -static void gen_pic_list_from_frame_list(RK_S32 currStructure, H264_FrameStore_t **fs_list, - RK_S32 list_idx, H264_StorePic_t **list, RK_U8 *list_size, RK_U32 long_term) -{ - RK_S32 top_idx = 0; - RK_S32 bot_idx = 0; - - RK_U32(*is_ref)(H264_StorePic_t *s) = (long_term) ? is_long_ref : is_short_ref; - - if (currStructure == TOP_FIELD) { - while ((top_idx < list_idx) || (bot_idx < list_idx)) { - for (; top_idx < list_idx; top_idx++) { - if (fs_list[top_idx]->is_used & 1) { - if (is_ref(fs_list[top_idx]->top_field)) { - //top_field; - (*list_size)++; - top_idx++; - break; - } - } - } - for (; bot_idx < list_idx; bot_idx++) { - if (fs_list[bot_idx]->is_used & 2) { - if (is_ref(fs_list[bot_idx]->bottom_field)) { - //bottom_field; - (*list_size)++; - bot_idx++; - break; - } - } - } - } - } - if (currStructure == BOTTOM_FIELD) { - while ((top_idx < list_idx) || (bot_idx < list_idx)) { - for (; bot_idx < list_idx; bot_idx++) { - if (fs_list[bot_idx]->is_used & 2) { - if (is_ref(fs_list[bot_idx]->bottom_field)) { - // short term ref pic - list[(RK_S16)*list_size] = fs_list[bot_idx]->bottom_field; - (*list_size)++; - bot_idx++; - break; - } - } - } - for (; top_idx < list_idx; top_idx++) { - if (fs_list[top_idx]->is_used & 1) { - if (is_ref(fs_list[top_idx]->top_field)) { - //!< short term ref pic - list[(RK_S16)*list_size] = fs_list[top_idx]->top_field; - (*list_size)++; - top_idx++; - break; - } - } - } - } - } -} - -static RK_U32 is_view_id_in_ref_view_list(RK_S32 view_id, RK_S32 *ref_view_id, RK_S32 num_ref_views) -{ - RK_S32 i; - for (i = 0; i < num_ref_views; i++) { - if (view_id == ref_view_id[i]) - break; - } - - return (num_ref_views && (i < num_ref_views)); -} - -static MPP_RET append_interview_list(H264_DpbBuf_t *p_Dpb, - PictureStructure currPicStructure, RK_S32 list_idx, H264_FrameStore_t **list, - RK_S32 *listXsize, RK_S32 currPOC, RK_S32 curr_layer_id, RK_S32 anchor_pic_flag) -{ - RK_S32 poc = 0; - RK_S32 fld_idx = 0; - RK_U32 pic_avail = 0; - RK_S32 num_ref_views = 0; - RK_S32 *ref_view_id = NULL; - MPP_RET ret = MPP_ERR_UNKNOW; - RK_S32 iVOIdx = curr_layer_id; - H264_FrameStore_t *fs = p_Dpb->fs_ilref[0]; - H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; - - VAL_CHECK(ret, iVOIdx >= 0); //!< Error: iVOIdx: %d is not less than 0 - if (anchor_pic_flag) { - num_ref_views = list_idx ? p_Vid->active_subsps->num_anchor_refs_l1[iVOIdx] : p_Vid->active_subsps->num_anchor_refs_l0[iVOIdx]; - ref_view_id = list_idx ? p_Vid->active_subsps->anchor_ref_l1[iVOIdx] : p_Vid->active_subsps->anchor_ref_l0[iVOIdx]; - } else { - num_ref_views = list_idx ? p_Vid->active_subsps->num_non_anchor_refs_l1[iVOIdx] : p_Vid->active_subsps->num_non_anchor_refs_l0[iVOIdx]; - ref_view_id = list_idx ? p_Vid->active_subsps->non_anchor_ref_l1[iVOIdx] : p_Vid->active_subsps->non_anchor_ref_l0[iVOIdx]; - } - - if (currPicStructure == BOTTOM_FIELD) - fld_idx = 1; - else - fld_idx = 0; - - if (currPicStructure == FRAME) { - pic_avail = (fs->is_used == 3); - if (pic_avail) { - poc = fs->frame->is_mmco_5 ? fs->frame->poc_mmco5 : fs->frame->poc; - } - } else if (currPicStructure == TOP_FIELD) { - pic_avail = fs->is_used & 1; - if (pic_avail) { - poc = fs->top_field->is_mmco_5 ? fs->top_field->top_poc_mmco5 : fs->top_field->poc; - } - } else if (currPicStructure == BOTTOM_FIELD) { - pic_avail = fs->is_used & 2; - if (pic_avail) { - poc = fs->bottom_field->is_mmco_5 ? fs->bottom_field->bot_poc_mmco5 : fs->bottom_field->poc; - } - } else { - pic_avail = 0; - } - - if (pic_avail && fs->inter_view_flag[fld_idx]) { - if (poc == currPOC) { - if (is_view_id_in_ref_view_list(fs->view_id, ref_view_id, num_ref_views)) { - //!< add one inter-view reference; - list[*listXsize] = fs; - //!< next; - (*listXsize)++; - } - } - } - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static void gen_pic_list_from_frame_interview_list(RK_S32 currStructure, - H264_FrameStore_t **fs_list, RK_S32 list_idx, H264_StorePic_t **list, RK_U8 *list_size) -{ - RK_S32 i; - - if (currStructure == TOP_FIELD) { - for (i = 0; i < list_idx; i++) { - list[(RK_S32)(*list_size)] = fs_list[i]->top_field; - (*list_size)++; - } - } - if (currStructure == BOTTOM_FIELD) { - for (i = 0; i < list_idx; i++) { - list[(RK_S32)(*list_size)] = fs_list[i]->bottom_field; - (*list_size)++; - } - } -} - -static RK_S32 compare_pic_by_poc_desc(const void *arg1, const void *arg2) -{ - RK_S32 poc1 = (*(H264_StorePic_t**)arg1)->poc; - RK_S32 poc2 = (*(H264_StorePic_t**)arg2)->poc; - - if (poc1 < poc2) - return 1; - if (poc1 > poc2) - return -1; - else - return 0; -} - -static RK_S32 compare_pic_by_poc_asc(const void *arg1, const void *arg2) -{ - RK_S32 poc1 = (*(H264_StorePic_t**)arg1)->poc; - RK_S32 poc2 = (*(H264_StorePic_t**)arg2)->poc; - - if (poc1 < poc2) - return -1; - if (poc1 > poc2) - return 1; - else - return 0; -} - -static RK_S32 compare_fs_by_poc_desc(const void *arg1, const void *arg2) -{ - RK_S32 poc1 = (*(H264_FrameStore_t**)arg1)->poc; - RK_S32 poc2 = (*(H264_FrameStore_t**)arg2)->poc; - - if (poc1 < poc2) - return 1; - else if (poc1 > poc2) - return -1; - else - return 0; -} - -static RK_S32 compare_fs_by_poc_asc(const void *arg1, const void *arg2) -{ - RK_S32 poc1 = (*(H264_FrameStore_t**)arg1)->poc; - RK_S32 poc2 = (*(H264_FrameStore_t**)arg2)->poc; - - if (poc1 < poc2) - return -1; - else if (poc1 > poc2) - return 1; - else - return 0; -} - -static MPP_RET init_lists_p_slice_mvc(H264_SLICE_t *currSlice) -{ - RK_U32 i = 0; - RK_S32 list0idx = 0; - RK_S32 listltidx = 0; - H264_FrameStore_t **fs_list0 = 0; - H264_FrameStore_t **fs_listlt = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; - RK_S32 currPOC = currSlice->ThisPOC; - RK_S32 anchor_pic_flag = currSlice->anchor_pic_flag; - - currSlice->listinterviewidx0 = 0; - currSlice->listinterviewidx1 = 0; - - if (currSlice->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_used == 3) { - if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { - currSlice->listP[0][list0idx++] = p_Dpb->fs_ref[i]->frame; - } - } - } - // order list 0 by PicNum - qsort((void *)currSlice->listP[0], list0idx, sizeof(H264_StorePic_t*), compare_pic_by_pic_num_desc); - currSlice->listXsizeP[0] = (RK_U8)list0idx; - // long term handling - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->is_used == 3) { - if (p_Dpb->fs_ltref[i]->frame->is_long_term) { - currSlice->listP[0][list0idx++] = p_Dpb->fs_ltref[i]->frame; - } - } - } - qsort((void *)&currSlice->listP[0][(RK_S16)currSlice->listXsizeP[0]], - list0idx - currSlice->listXsizeP[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); - currSlice->listXsizeP[0] = (RK_U8)list0idx; - } else { - fs_list0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - fs_listlt = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - MEM_CHECK(ret, fs_list0 && fs_listlt); - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_reference) { - fs_list0[list0idx++] = p_Dpb->fs_ref[i]; - } - } - qsort((void *)fs_list0, list0idx, sizeof(H264_FrameStore_t*), compare_fs_by_frame_num_desc); - currSlice->listXsizeP[0] = 0; - gen_pic_list_from_frame_list(currSlice->structure, fs_list0, list0idx, currSlice->listP[0], &currSlice->listXsizeP[0], 0); - // long term handling - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; - } - qsort((void *)fs_listlt, listltidx, sizeof(H264_FrameStore_t*), compare_fs_by_lt_pic_idx_asc); - gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listP[0], &currSlice->listXsizeP[0], 1); - mpp_free(fs_list0); - mpp_free(fs_listlt); - } - - currSlice->listXsizeP[1] = 0; - if (currSlice->svc_extension_flag == 0) { - RK_S32 curr_layer_id = currSlice->layer_id; - currSlice->fs_listinterview0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - MEM_CHECK(ret, currSlice->fs_listinterview0); - list0idx = currSlice->listXsizeP[0]; - if (currSlice->structure == FRAME) { - FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], 0, 0, - currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); - for (i = 0; i < (RK_U32)currSlice->listinterviewidx0; i++) { - currSlice->listP[0][list0idx++] = currSlice->fs_listinterview0[i]->frame; - } - currSlice->listXsizeP[0] = (RK_U8)list0idx; - } else { - FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, - currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); - gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview0, - currSlice->listinterviewidx0, currSlice->listP[0], &currSlice->listXsizeP[0]); - } - } - // set the unused list entries to NULL - for (i = currSlice->listXsizeP[0]; i < (MAX_LIST_SIZE); i++) { - currSlice->listP[0][i] = p_Vid->no_reference_picture; - } - for (i = currSlice->listXsizeP[1]; i < (MAX_LIST_SIZE); i++) { - currSlice->listP[1][i] = p_Vid->no_reference_picture; - } - mpp_free(currSlice->fs_listinterview0); - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - mpp_free(fs_list0); - mpp_free(fs_listlt); - mpp_free(currSlice->fs_listinterview0); - - return ret; -} - -static MPP_RET init_lists_b_slice_mvc(H264_SLICE_t *currSlice) -{ - RK_U32 i = 0; - RK_S32 j = 0; - RK_S32 list0idx = 0; - RK_S32 list0idx_1 = 0; - RK_S32 listltidx = 0; - H264_FrameStore_t **fs_list0 = NULL; - H264_FrameStore_t **fs_list1 = NULL; - H264_FrameStore_t **fs_listlt = NULL; - MPP_RET ret = MPP_ERR_UNKNOW; - - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; - RK_S32 currPOC = currSlice->ThisPOC; - RK_S32 anchor_pic_flag = currSlice->anchor_pic_flag; - - currSlice->listinterviewidx0 = 0; - currSlice->listinterviewidx1 = 0; - // B-Slice - if (currSlice->structure == FRAME) { - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_used == 3) { - if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { - if (currSlice->framepoc >= p_Dpb->fs_ref[i]->frame->poc) { - currSlice->listB[0][list0idx++] = p_Dpb->fs_ref[i]->frame; - } - } - } - } - qsort((void *)currSlice->listB[0], list0idx, sizeof(H264_StorePic_t*), compare_pic_by_poc_desc); - list0idx_1 = list0idx; - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_used == 3) { - if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { - if (currSlice->framepoc < p_Dpb->fs_ref[i]->frame->poc) { - currSlice->listB[0][list0idx++] = p_Dpb->fs_ref[i]->frame; - } - } - } - } - qsort((void *)&currSlice->listB[0][list0idx_1], list0idx - list0idx_1, sizeof(H264_StorePic_t*), compare_pic_by_poc_asc); - - for (j = 0; j < list0idx_1; j++) { - currSlice->listB[1][list0idx - list0idx_1 + j] = currSlice->listB[0][j]; - } - for (j = list0idx_1; j < list0idx; j++) { - currSlice->listB[1][j - list0idx_1] = currSlice->listB[0][j]; - } - currSlice->listXsizeB[0] = currSlice->listXsizeB[1] = (RK_U8)list0idx; - // long term handling - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - if (p_Dpb->fs_ltref[i]->is_used == 3) { - if (p_Dpb->fs_ltref[i]->frame->is_long_term) { - currSlice->listB[0][list0idx] = p_Dpb->fs_ltref[i]->frame; - currSlice->listB[1][list0idx++] = p_Dpb->fs_ltref[i]->frame; - } - } - } - qsort((void *)&currSlice->listB[0][(RK_S16)currSlice->listXsizeB[0]], - list0idx - currSlice->listXsizeB[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); - qsort((void *)&currSlice->listB[1][(RK_S16)currSlice->listXsizeB[0]], - list0idx - currSlice->listXsizeB[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); - currSlice->listXsizeB[0] = currSlice->listXsizeB[1] = (RK_U8)list0idx; - } else { - fs_list0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - fs_list1 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - fs_listlt = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - MEM_CHECK(ret, fs_list0 && fs_list1 && fs_listlt); - currSlice->listXsizeB[0] = 0; - currSlice->listXsizeB[1] = 1; - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_used) { - if (currSlice->ThisPOC >= p_Dpb->fs_ref[i]->poc) { - fs_list0[list0idx++] = p_Dpb->fs_ref[i]; - } - } - } - qsort((void *)fs_list0, list0idx, sizeof(H264_FrameStore_t*), compare_fs_by_poc_desc); - list0idx_1 = list0idx; - for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { - if (p_Dpb->fs_ref[i]->is_used) { - if (currSlice->ThisPOC < p_Dpb->fs_ref[i]->poc) { - fs_list0[list0idx++] = p_Dpb->fs_ref[i]; - } - } - } - qsort((void *)&fs_list0[list0idx_1], list0idx - list0idx_1, sizeof(H264_FrameStore_t*), compare_fs_by_poc_asc); - - for (j = 0; j < list0idx_1; j++) { - fs_list1[list0idx - list0idx_1 + j] = fs_list0[j]; - } - for (j = list0idx_1; j < list0idx; j++) { - fs_list1[j - list0idx_1] = fs_list0[j]; - } - currSlice->listXsizeB[0] = 0; - currSlice->listXsizeB[1] = 0; - gen_pic_list_from_frame_list(currSlice->structure, fs_list0, list0idx, currSlice->listB[0], &currSlice->listXsizeB[0], 0); - gen_pic_list_from_frame_list(currSlice->structure, fs_list1, list0idx, currSlice->listB[1], &currSlice->listXsizeB[1], 0); - - // long term handling - for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { - fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; - } - qsort((void *)fs_listlt, listltidx, sizeof(H264_FrameStore_t*), compare_fs_by_lt_pic_idx_asc); - - gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listB[0], &currSlice->listXsizeB[0], 1); - gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listB[1], &currSlice->listXsizeB[1], 1); - - mpp_free(fs_list0); - mpp_free(fs_list1); - mpp_free(fs_listlt); - } - if ((currSlice->listXsizeB[0] == currSlice->listXsizeB[1]) && (currSlice->listXsizeB[0] > 1)) { - // check if lists are identical, if yes swap first two elements of currSlice->listX[1] - RK_S32 diff = 0; - for (j = 0; j < currSlice->listXsizeB[0]; j++) { - if (currSlice->listB[0][j] != currSlice->listB[1][j]) { - diff = 1; - break; - } - } - if (!diff) { - H264_StorePic_t *tmp_s = currSlice->listB[1][0]; - currSlice->listB[1][0] = currSlice->listB[1][1]; - currSlice->listB[1][1] = tmp_s; - } - } - if (currSlice->svc_extension_flag == 0) { - RK_S32 curr_layer_id = currSlice->layer_id; - // B-Slice - currSlice->fs_listinterview0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - currSlice->fs_listinterview1 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); - MEM_CHECK(ret, currSlice->fs_listinterview0 && currSlice->fs_listinterview1); - list0idx = currSlice->listXsizeB[0]; - if (currSlice->structure == FRAME) { - FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], 0, 0, - currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); - FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], 0, 1, - currSlice->fs_listinterview1, &currSlice->listinterviewidx1, currPOC, curr_layer_id, anchor_pic_flag)); - - for (i = 0; i < (RK_U32)currSlice->listinterviewidx0; i++) { - currSlice->listB[0][list0idx++] = currSlice->fs_listinterview0[i]->frame; - } - currSlice->listXsizeB[0] = (RK_U8)list0idx; - list0idx = currSlice->listXsizeB[1]; - for (i = 0; i < (RK_U32)currSlice->listinterviewidx1; i++) { - currSlice->listB[1][list0idx++] = currSlice->fs_listinterview1[i]->frame; - } - currSlice->listXsizeB[1] = (RK_U8)list0idx; - } else { - FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, - currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); - gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview0, - currSlice->listinterviewidx0, currSlice->listB[0], &currSlice->listXsizeB[0]); - FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 1, - currSlice->fs_listinterview1, &currSlice->listinterviewidx1, currPOC, curr_layer_id, anchor_pic_flag)); - gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview1, - currSlice->listinterviewidx1, currSlice->listB[1], &currSlice->listXsizeB[1]); - } - } - // set the unused list entries to NULL - for (i = currSlice->listXsizeB[0]; i < (MAX_LIST_SIZE); i++) { - currSlice->listB[0][i] = p_Vid->no_reference_picture; - } - for (i = currSlice->listXsizeB[1]; i < (MAX_LIST_SIZE); i++) { - currSlice->listB[1][i] = p_Vid->no_reference_picture; - } - mpp_free(currSlice->fs_listinterview0); - mpp_free(currSlice->fs_listinterview1); - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - mpp_free(fs_list0); - mpp_free(fs_list1); - mpp_free(fs_listlt); - mpp_free(currSlice->fs_listinterview0); - mpp_free(currSlice->fs_listinterview1); - - return ret; -} - -/*! -*********************************************************************** -* \brief -* check parser is end and then configure register -*********************************************************************** -*/ -//extern "C" -MPP_RET init_picture(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_DecCtx_t *p_Dec = currSlice->p_Vid->p_Dec; - - FUN_CHECK(ret = alloc_decpic(currSlice)); - //!< idr_memory_management MVC_layer, idr_flag==1 - FUN_CHECK(ret = init_picture_decoding(currSlice->p_Vid, currSlice)); - //!< except (idr_flag ==1 && layer_id==0) - if (!currSlice->idr_flag || currSlice->layer_id) { - FUN_CHECK(ret = init_lists_p_slice_mvc(currSlice)); - FUN_CHECK(ret = init_lists_b_slice_mvc(currSlice)); - } - prepare_init_dpb_info(currSlice); - fill_picparams(currSlice->p_Vid, &p_Dec->dxva_ctx->pp); - prepare_init_scanlist(currSlice); - fill_qmatrix(currSlice->p_Vid, &p_Dec->dxva_ctx->qm); - - return ret = MPP_OK; -__FAILED: - return ret; -} - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_init" + +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_compat_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_common.h" + +#include "h264d_global.h" +#include "h264d_init.h" +#include "h264d_dpb.h" +#include "h264d_scalist.h" +#include "h264d_fill.h" +#include "h264d_slice.h" + +static MPP_RET decode_poc(H264dVideoCtx_t *p_Vid, H264_SLICE_t *pSlice) +{ + RK_S32 i = 0; + RK_U32 MaxPicOrderCntLsb = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_SPS_t *active_sps = p_Vid->active_sps; + // for POC mode 0: + MaxPicOrderCntLsb = (1 << (active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4)); + + switch (active_sps->pic_order_cnt_type) { + case 0: // POC MODE 0 + // 1st + if (pSlice->idr_flag) { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = 0; + } else { + if (p_Vid->last_has_mmco_5) { + if (p_Vid->last_pic_bottom_field) { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = 0; + } else { + p_Vid->PrevPicOrderCntMsb = 0; + p_Vid->PrevPicOrderCntLsb = pSlice->toppoc; + } + } + } + // Calculate the MSBs of current picture + if (pSlice->pic_order_cnt_lsb < p_Vid->PrevPicOrderCntLsb && + (p_Vid->PrevPicOrderCntLsb - pSlice->pic_order_cnt_lsb) >= (RK_S32)(MaxPicOrderCntLsb / 2)) { + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb + MaxPicOrderCntLsb; + } else if (pSlice->pic_order_cnt_lsb > p_Vid->PrevPicOrderCntLsb && + (pSlice->pic_order_cnt_lsb - p_Vid->PrevPicOrderCntLsb) > (RK_S32)(MaxPicOrderCntLsb / 2)) { + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb - MaxPicOrderCntLsb; + } else { + pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb; + } + // 2nd + if (pSlice->field_pic_flag == 0) { + //frame pix + pSlice->toppoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; + pSlice->bottompoc = pSlice->toppoc + pSlice->delta_pic_order_cnt_bottom; + pSlice->ThisPOC = pSlice->framepoc = (pSlice->toppoc < pSlice->bottompoc) ? pSlice->toppoc : pSlice->bottompoc; // POC200301 + } else if (pSlice->bottom_field_flag == 0) { + //top field + pSlice->ThisPOC = pSlice->toppoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; + } else { + //bottom field + pSlice->ThisPOC = pSlice->bottompoc = pSlice->PicOrderCntMsb + pSlice->pic_order_cnt_lsb; + } + pSlice->framepoc = pSlice->ThisPOC; + p_Vid->ThisPOC = pSlice->ThisPOC; + //if ( pSlice->frame_num != p_Vid->PreviousFrameNum) //Seems redundant + p_Vid->PreviousFrameNum = pSlice->frame_num; + if (pSlice->nal_reference_idc) { + p_Vid->PrevPicOrderCntLsb = pSlice->pic_order_cnt_lsb; + p_Vid->PrevPicOrderCntMsb = pSlice->PicOrderCntMsb; + } + break; + + case 1: // POC MODE 1 + // 1st + if (pSlice->idr_flag) { + p_Vid->FrameNumOffset = 0; // first pix of IDRGOP, + VAL_CHECK(ret, 0 == pSlice->frame_num); + } else { + if (p_Vid->last_has_mmco_5) { + p_Vid->PreviousFrameNumOffset = 0; + p_Vid->PreviousFrameNum = 0; + } + if (pSlice->frame_num < (RK_S32)p_Vid->PreviousFrameNum) { + //not first pix of IDRGOP + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset + p_Vid->max_frame_num; + } else { + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset; + } + } + // 2nd + if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) { + pSlice->AbsFrameNum = p_Vid->FrameNumOffset + pSlice->frame_num; + } else { + pSlice->AbsFrameNum = 0; + } + if ((!pSlice->nal_reference_idc) && pSlice->AbsFrameNum > 0) { + pSlice->AbsFrameNum--; + } + // 3rd + p_Vid->ExpectedDeltaPerPicOrderCntCycle = 0; + if (active_sps->num_ref_frames_in_pic_order_cnt_cycle) { + for (i = 0; i < (RK_S32)active_sps->num_ref_frames_in_pic_order_cnt_cycle; i++) { + p_Vid->ExpectedDeltaPerPicOrderCntCycle += active_sps->offset_for_ref_frame[i]; + } + } + if (pSlice->AbsFrameNum) { + p_Vid->PicOrderCntCycleCnt = (pSlice->AbsFrameNum - 1) / active_sps->num_ref_frames_in_pic_order_cnt_cycle; + p_Vid->FrameNumInPicOrderCntCycle = (pSlice->AbsFrameNum - 1) % active_sps->num_ref_frames_in_pic_order_cnt_cycle; + p_Vid->ExpectedPicOrderCnt = p_Vid->PicOrderCntCycleCnt * p_Vid->ExpectedDeltaPerPicOrderCntCycle; + for (i = 0; i <= (RK_S32)p_Vid->FrameNumInPicOrderCntCycle; i++) + p_Vid->ExpectedPicOrderCnt += active_sps->offset_for_ref_frame[i]; + } else { + p_Vid->ExpectedPicOrderCnt = 0; + } + if (!pSlice->nal_reference_idc) { + p_Vid->ExpectedPicOrderCnt += active_sps->offset_for_non_ref_pic; + } + if (pSlice->field_pic_flag == 0) { + //frame pix + pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + pSlice->delta_pic_order_cnt[0]; + pSlice->bottompoc = pSlice->toppoc + active_sps->offset_for_top_to_bottom_field + pSlice->delta_pic_order_cnt[1]; + pSlice->ThisPOC = pSlice->framepoc = (pSlice->toppoc < pSlice->bottompoc) ? pSlice->toppoc : pSlice->bottompoc; // POC200301 + } else if (pSlice->bottom_field_flag == 0) { + //top field + pSlice->ThisPOC = pSlice->toppoc = p_Vid->ExpectedPicOrderCnt + pSlice->delta_pic_order_cnt[0]; + } else { + //bottom field + pSlice->ThisPOC = pSlice->bottompoc = p_Vid->ExpectedPicOrderCnt + active_sps->offset_for_top_to_bottom_field + pSlice->delta_pic_order_cnt[0]; + } + pSlice->framepoc = pSlice->ThisPOC; + p_Vid->PreviousFrameNum = pSlice->frame_num; + p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; + break; + + + case 2: // POC MODE 2 + if (pSlice->idr_flag) { // IDR picture + p_Vid->FrameNumOffset = 0; // first pix of IDRGOP, + pSlice->ThisPOC = pSlice->framepoc = pSlice->toppoc = pSlice->bottompoc = 0; + VAL_CHECK(ret, 0 == pSlice->frame_num); + } else { + if (p_Vid->last_has_mmco_5) { + p_Vid->PreviousFrameNum = 0; + p_Vid->PreviousFrameNumOffset = 0; + } + if (pSlice->frame_num < (RK_S32)p_Vid->PreviousFrameNum) { + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset + p_Vid->max_frame_num; + } else { + p_Vid->FrameNumOffset = p_Vid->PreviousFrameNumOffset; + } + pSlice->AbsFrameNum = p_Vid->FrameNumOffset + pSlice->frame_num; + if (!pSlice->nal_reference_idc) { + pSlice->ThisPOC = (2 * pSlice->AbsFrameNum - 1); + } else { + pSlice->ThisPOC = (2 * pSlice->AbsFrameNum); + } + if (pSlice->field_pic_flag == 0) { + pSlice->toppoc = pSlice->bottompoc = pSlice->framepoc = pSlice->ThisPOC; + } else if (pSlice->bottom_field_flag == 0) { + pSlice->toppoc = pSlice->framepoc = pSlice->ThisPOC; + } else { + pSlice->bottompoc = pSlice->framepoc = pSlice->ThisPOC; + } + } + p_Vid->PreviousFrameNum = pSlice->frame_num; + p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset; + break; + default: + ret = MPP_NOK; + goto __FAILED; + } + return ret = MPP_OK; + +__FAILED: + return ret; +} + +static MPP_RET store_proc_picture_in_dpb(H264_DpbBuf_t *p_Dpb, H264_StorePic_t *p) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + H264_FrameStore_t *fs = p_Dpb->fs_ilref[0]; + H264_DecCtx_t *p_Dec = p_Dpb->p_Vid->p_Dec; + + VAL_CHECK(ret, NULL != p); + if (p_Dpb->used_size_il > 0) { + if (fs->frame) { + free_storable_picture(p_Dec, fs->frame); + fs->frame = NULL; + } + if (fs->top_field) { + free_storable_picture(p_Dec, fs->top_field); + fs->top_field = NULL; + } + if (fs->bottom_field) { + free_storable_picture(p_Dec, fs->bottom_field); + fs->bottom_field = NULL; + } + fs->is_used = 0; + fs->is_reference = 0; + p_Dpb->used_size_il--; + } + if (fs->is_used > 0) { //checking; + if (p->structure == FRAME) { + VAL_CHECK(ret, fs->frame == NULL); + } else if (p->structure == TOP_FIELD) { + VAL_CHECK(ret, fs->top_field == NULL); + } else if (p->structure == BOTTOM_FIELD) { + VAL_CHECK(ret, fs->bottom_field == NULL); + } + } + FUN_CHECK(ret = insert_picture_in_dpb(p_Vid, fs, p, 0)); + if ((p->structure == FRAME && fs->is_used == 3) + || (p->structure != FRAME && fs->is_used && fs->is_used < 3)) { + p_Dpb->used_size_il++; + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void dpb_mark_add_used(H264_DpbMark_t *p_mark, RK_S32 structure) +{ + //!<---- index add ---- + if (structure == FRAME || structure == TOP_FIELD) { + p_mark->top_used += 1; + } + if (structure == FRAME || structure == BOTTOM_FIELD) { + p_mark->bot_used += 1; + } +} + +static H264_StorePic_t* clone_storable_picture(H264dVideoCtx_t *p_Vid, H264_StorePic_t *p_pic) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *p_stored_pic = alloc_storable_picture(p_Vid, p_Vid->structure); + + MEM_CHECK(ret, p_stored_pic); + p_stored_pic->mem_malloc_type = Mem_Clone; + p_stored_pic->mem_mark = p_pic->mem_mark; + dpb_mark_add_used(p_stored_pic->mem_mark, p_stored_pic->structure); + p_stored_pic->colmv_no_used_flag = 1; // clone, colmv is not be used + + p_stored_pic->pic_num = p_pic->pic_num; + p_stored_pic->frame_num = p_pic->frame_num; + p_stored_pic->long_term_frame_idx = p_pic->long_term_frame_idx; + p_stored_pic->long_term_pic_num = p_pic->long_term_pic_num; + p_stored_pic->is_long_term = 0; + p_stored_pic->non_existing = p_pic->non_existing; + p_stored_pic->max_slice_id = p_pic->max_slice_id; + p_stored_pic->structure = p_pic->structure; + + p_stored_pic->mb_aff_frame_flag = p_pic->mb_aff_frame_flag; + p_stored_pic->poc = p_pic->poc; + p_stored_pic->top_poc = p_pic->top_poc; + p_stored_pic->bottom_poc = p_pic->bottom_poc; + p_stored_pic->frame_poc = p_pic->frame_poc; + p_stored_pic->is_mmco_5 = p_pic->is_mmco_5; + p_stored_pic->poc_mmco5 = p_pic->poc_mmco5; + p_stored_pic->top_poc_mmco5 = p_pic->top_poc_mmco5; + p_stored_pic->bot_poc_mmco5 = p_pic->bot_poc_mmco5; + p_stored_pic->pic_num = p_pic->pic_num; + p_stored_pic->frame_num = p_pic->frame_num; + p_stored_pic->slice_type = p_pic->slice_type; + p_stored_pic->idr_flag = p_pic->idr_flag; + p_stored_pic->no_output_of_prior_pics_flag = p_pic->no_output_of_prior_pics_flag; + p_stored_pic->long_term_reference_flag = 0; + p_stored_pic->adaptive_ref_pic_buffering_flag = 0; + p_stored_pic->dec_ref_pic_marking_buffer = NULL; + p_stored_pic->PicWidthInMbs = p_pic->PicWidthInMbs; + + p_stored_pic->chroma_format_idc = p_pic->chroma_format_idc; + p_stored_pic->frame_mbs_only_flag = p_pic->frame_mbs_only_flag; + p_stored_pic->frame_cropping_flag = p_pic->frame_cropping_flag; + if (p_stored_pic->frame_cropping_flag) { + p_stored_pic->frame_crop_left_offset = p_pic->frame_crop_left_offset; + p_stored_pic->frame_crop_right_offset = p_pic->frame_crop_right_offset; + p_stored_pic->frame_crop_top_offset = p_pic->frame_crop_top_offset; + p_stored_pic->frame_crop_bottom_offset = p_pic->frame_crop_bottom_offset; + } + // MVC-related parameters + p_stored_pic->inter_view_flag = p_pic->inter_view_flag; + p_stored_pic->anchor_pic_flag = 0; + p_stored_pic->view_id = p_pic->view_id; + p_stored_pic->layer_id = p_pic->layer_id; + p_stored_pic->proc_flag = 1; + p_stored_pic->is_output = 1; + p_stored_pic->used_for_reference = 1; + + return p_stored_pic; +__FAILED: + (void)ret; + return NULL; +} + +static MPP_RET init_mvc_picture(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + RK_S32 poc = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = p_Vid->p_Dpb_layer[0]; + H264_StorePic_t *p_pic = NULL; + H264_FrameStore_t *fs = NULL; + H264_StorePic_t *p_clone = NULL; + + // find BL reconstructed picture + if (currSlice->structure == FRAME) { + for (i = 0; i < p_Dpb->used_size; i++) { + fs = p_Dpb->fs[i]; + if (fs->frame) { + poc = (fs->frame->is_mmco_5 != 0) ? fs->frame->poc_mmco5 : fs->frame->poc; + } + if (fs->frame && (fs->frame->layer_id == 0) && (poc == currSlice->framepoc)) { + p_pic = fs->frame; + if (!fs->frame->is_mmco_5) { + break; + } + } + } + } else if (currSlice->structure == TOP_FIELD) { + for (i = 0; i < p_Dpb->used_size; i++) { + fs = p_Dpb->fs[i]; + if (fs->top_field) { + poc = (fs->top_field->is_mmco_5 != 0) ? fs->top_field->top_poc_mmco5 : fs->top_field->top_poc; + } + if (fs->top_field && (fs->top_field->layer_id == 0) && (poc == currSlice->toppoc)) { + p_pic = fs->top_field; + if (!fs->top_field->is_mmco_5) { + break; + } + } + } + } else { + for (i = 0; i < p_Dpb->used_size; i++) { + fs = p_Dpb->fs[i]; + if (fs->bottom_field) { + poc = (fs->bottom_field->is_mmco_5 != 0) ? fs->bottom_field->bot_poc_mmco5 : fs->bottom_field->bottom_poc; + } + if (fs->bottom_field && (fs->bottom_field->layer_id == 0) && (poc == currSlice->bottompoc)) { + p_pic = fs->bottom_field; + if (!fs->bottom_field->is_mmco_5) { + break; + } + } + } + } + if (p_pic) { + p_clone = clone_storable_picture(p_Vid, p_pic); + MEM_CHECK(ret, p_clone); + FUN_CHECK(ret = store_proc_picture_in_dpb(currSlice->p_Dpb, p_clone)); + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET dpb_mark_malloc(H264dVideoCtx_t *p_Vid, H264_StorePic_t *dec_pic) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DpbMark_t *cur_mark = NULL; + H264_DecCtx_t *p_Dec = p_Vid->p_Dec; + H264_DpbMark_t *p_mark = p_Vid->p_Dec->dpb_mark; + RK_S32 structure = dec_pic->structure; + RK_S32 layer_id = dec_pic->layer_id; + + if (!dec_pic->combine_flag) { + RK_U8 idx = 0; + while (p_mark[idx].out_flag || p_mark[idx].top_used + || p_mark[idx].bot_used) { + idx++; + ASSERT(MAX_MARK_SIZE > idx); + } + + mpp_buf_slot_get_unused(p_Vid->p_Dec->frame_slots, &p_mark[idx].slot_idx); + if (p_mark[idx].slot_idx < 0) { + H264D_WARNNING("[dpb_mark_malloc] error, buf_slot has not get."); + ret = MPP_NOK; + goto __FAILED; + } + cur_mark = &p_mark[idx]; + + cur_mark->out_flag = 1; + { + RK_U32 hor_stride, ver_stride; + MppFrameFormat fmt = MPP_FMT_YUV_BUTT; + MppFrameFormat out_fmt = p_Dec->cfg->base.out_fmt; + MppFrameImpl *impl = (MppFrameImpl *)p_Dec->curframe; + + if ((H264_CHROMA_400 == p_Vid->yuv_format) && (8 == p_Vid->bit_depth_luma)) { + fmt = MPP_FMT_YUV400; + } else if ((H264_CHROMA_420 == p_Vid->yuv_format) && (8 == p_Vid->bit_depth_luma)) { + fmt = MPP_FMT_YUV420SP; + } else if ((H264_CHROMA_420 == p_Vid->yuv_format) && (10 == p_Vid->bit_depth_luma)) { + fmt = MPP_FMT_YUV420SP_10BIT; + } else if ((H264_CHROMA_422 == p_Vid->yuv_format) && (8 == p_Vid->bit_depth_luma)) { + fmt = MPP_FMT_YUV422SP; + mpp_slots_set_prop(p_Dec->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } else if ((H264_CHROMA_422 == p_Vid->yuv_format) && (10 == p_Vid->bit_depth_luma)) { + fmt = MPP_FMT_YUV422SP_10BIT; + mpp_slots_set_prop(p_Dec->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } + + if (MPP_FRAME_FMT_IS_FBC(out_fmt)) { + do { + /* + * field mode can not use FBC, but VOP only support fbc fmt for 10bit source. + * Generally, there is no 10bit field source. + */ + if (!p_Vid->frame_mbs_only_flag && p_Vid->bit_depth_luma < 10) + break; + + /* + * When iep working on detection mode disable fbc output mode + */ + if ((p_Dec->cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) && + p_Vid->width <= 1920 && p_Vid->height <= 1088 && p_Vid->bit_depth_luma == 8) + break; + + mpp_slots_set_prop(p_Dec->frame_slots, SLOTS_HOR_ALIGN, mpp_align_64); + fmt |= (out_fmt & MPP_FRAME_FBC_MASK); + } while (0); + + p_Dec->cfg->base.out_fmt = fmt; + out_fmt = fmt; + } else if (MPP_FRAME_FMT_IS_TILE(out_fmt)) { + fmt |= (out_fmt & MPP_FRAME_TILE_FLAG); + p_Dec->cfg->base.out_fmt = fmt; + out_fmt = fmt; + } + impl->fmt = fmt; + + hor_stride = MPP_ALIGN(p_Vid->width * p_Vid->bit_depth_luma, 8) / 8; + ver_stride = p_Vid->height; + /* Before cropping */ + impl->hor_stride = hor_stride; + impl->ver_stride = ver_stride; + + /* After cropped */ + impl->width = p_Vid->width_after_crop; + impl->height = p_Vid->height_after_crop; + impl->pts = p_Vid->p_Cur->last_pts; + impl->dts = p_Vid->p_Cur->last_dts; + + if (MPP_FRAME_FMT_IS_FBC(out_fmt)) { + impl->offset_x = 0; + impl->offset_y = 4; + + if (*compat_ext_fbc_buf_size) + impl->ver_stride += 16; + + impl->fbc_hdr_stride = MPP_ALIGN(impl->width, 64); + if (*compat_ext_fbc_hdr_256_odd) + impl->fbc_hdr_stride = MPP_ALIGN(impl->width, 256) | 256; + } + + /* Setting the interlace mode for the picture */ + switch (structure) { + case FRAME: + impl->mode = MPP_FRAME_FLAG_FRAME; + /* When vproc detection is enabled set frame to field mode */ + if ((p_Dec->cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) && + p_Vid->width <= 1920 && p_Vid->height <= 1088 && p_Vid->bit_depth_luma == 8) + impl->mode = MPP_FRAME_FLAG_DEINTERLACED; + break; + case TOP_FIELD: + impl->mode = MPP_FRAME_FLAG_PAIRED_FIELD | MPP_FRAME_FLAG_TOP_FIRST; + break; + case BOTTOM_FIELD: + impl->mode = MPP_FRAME_FLAG_PAIRED_FIELD | MPP_FRAME_FLAG_BOT_FIRST; + break; + default: + H264D_DBG(H264D_DBG_FIELD_PAIRED, "Unknown interlace mode"); + mpp_assert(0); + } + + if (p_Dec->svc_valid) { + struct h264_slice_t *slice = &p_Dec->p_Cur->slice; + struct h264_nalu_svc_ext_t *svcExt = &slice->svcExt; + + if (svcExt->valid && impl->meta) + mpp_meta_set_s32(impl->meta, KEY_TEMPORAL_ID, svcExt->temporal_id); + } + + if (p_Vid->p_Cur->sei && + ((p_Vid->active_sps->vui_parameters_present_flag && + p_Vid->active_sps->vui_seq_parameters.pic_struct_present_flag && + p_Vid->p_Cur->sei->type == H264_SEI_PIC_TIMING) || + p_Vid->p_Cur->sei->pic_timing.pic_struct != 0)) { + if (p_Vid->p_Cur->sei->pic_timing.pic_struct == 3 || + p_Vid->p_Cur->sei->pic_timing.pic_struct == 5) + impl->mode = MPP_FRAME_FLAG_PAIRED_FIELD | MPP_FRAME_FLAG_TOP_FIRST; + if (p_Vid->p_Cur->sei->pic_timing.pic_struct == 4 || + p_Vid->p_Cur->sei->pic_timing.pic_struct == 6) + impl->mode = MPP_FRAME_FLAG_PAIRED_FIELD | MPP_FRAME_FLAG_BOT_FIRST; + } + + if (p_Dec->cfg->base.enable_thumbnail && p_Dec->hw_info->cap_down_scale) + mpp_frame_set_thumbnail_en(p_Dec->curframe, p_Dec->cfg->base.enable_thumbnail); + else + mpp_frame_set_thumbnail_en(p_Dec->curframe, 0); + + //!< set display parameter + if (p_Vid->active_sps->vui_parameters_present_flag) { + H264_VUI_t *p = &p_Vid->active_sps->vui_seq_parameters; + + if (p->video_signal_type_present_flag && p->video_full_range_flag) + impl->color_range = MPP_FRAME_RANGE_JPEG; + else + impl->color_range = MPP_FRAME_RANGE_MPEG; + + if (p->colour_description_present_flag) { + impl->color_primaries = p->colour_primaries; + impl->color_trc = p->transfer_characteristics; + impl->colorspace = p->matrix_coefficients; + if (impl->color_trc == MPP_FRAME_TRC_SMPTEST2084) + impl->fmt |= MPP_FRAME_HDR; + } else { + impl->color_primaries = MPP_FRAME_PRI_UNSPECIFIED; + impl->color_trc = MPP_FRAME_TRC_UNSPECIFIED; + impl->colorspace = MPP_FRAME_SPC_UNSPECIFIED; + } + } + + if (p_Vid->p_Cur->hdr_dynamic && p_Vid->p_Cur->hdr_dynamic_meta) { + impl->hdr_dynamic_meta = p_Vid->p_Cur->hdr_dynamic_meta; + p_Vid->p_Cur->hdr_dynamic = 0; + impl->fmt |= MPP_FRAME_HDR; + } + + impl->poc = dec_pic->poc; + impl->viewid = dec_pic->layer_id; + impl->status.is_intra = dec_pic->slice_type == H264_I_SLICE; + impl->status.is_idr = dec_pic->idr_flag; + impl->status.is_non_ref = !dec_pic->used_for_reference; + impl->status.is_lt_ref = dec_pic->long_term_reference_flag; + impl->status.is_b_frame = ((dec_pic->slice_type % 5) == H264_B_SLICE); + + mpp_buf_slot_set_prop(p_Dec->frame_slots, cur_mark->slot_idx, SLOT_FRAME, p_Dec->curframe); + mpp_buf_slot_get_prop(p_Dec->frame_slots, cur_mark->slot_idx, SLOT_FRAME_PTR, &cur_mark->mframe); + } + + p_Vid->active_dpb_mark[layer_id] = cur_mark; + } + cur_mark = p_Vid->active_dpb_mark[layer_id]; + if (cur_mark->slot_idx < 0) { + H264D_WARNNING("[dpb_mark_malloc] error, current mark slot idx is nagative."); + ret = MPP_NOK; + goto __FAILED; + } + if (structure == FRAME || structure == TOP_FIELD) { + cur_mark->top_used += 1; + } + if (structure == FRAME || structure == BOTTOM_FIELD) { + cur_mark->bot_used += 1; + } + H264D_DBG(H264D_DBG_DPB_MALLIC, + "[DPB_malloc] g_framecnt=%d, com_flag=%d, mark_idx=%d, slot_idx=%d, slice_type=%d, struct=%d, lay_id=%d\n", + p_Vid->g_framecnt, dec_pic->combine_flag, cur_mark->mark_idx, + cur_mark->slot_idx, dec_pic->slice_type, dec_pic->structure, + layer_id); + + p_Vid->p_Dec->in_task->output = cur_mark->slot_idx; + mpp_buf_slot_set_flag(p_Dec->frame_slots, cur_mark->slot_idx, SLOT_HAL_OUTPUT); + p_Dec->last_frame_slot_idx = cur_mark->slot_idx; + dec_pic->mem_mark = p_Vid->active_dpb_mark[layer_id]; + dec_pic->mem_mark->pic = dec_pic; + + return ret = MPP_OK; +__FAILED: + dec_pic->mem_mark = NULL; + return ret; +} + +static MPP_RET check_dpb_discontinuous(H264_StorePic_t *p_last, H264_StorePic_t *dec_pic, H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if (p_last && dec_pic && (dec_pic->slice_type != H264_I_SLICE) + && (currSlice->p_Cur->sps.gaps_in_frame_num_value_allowed_flag == 0)) { + RK_U32 error_flag = 0; + + if (dec_pic->combine_flag) { + if (dec_pic->frame_num != p_last->frame_num) + error_flag = 1; + } else { + RK_U32 frame_num = currSlice->p_Vid->last_ref_frame_num; + + if (dec_pic->frame_num != frame_num && + dec_pic->frame_num != ((frame_num + 1) % currSlice->p_Vid->max_frame_num)) + error_flag = 1; + } + + currSlice->p_Dec->errctx.cur_err_flag |= (error_flag != 0) ? 1 : 0; + currSlice->p_Dec->errctx.dpb_err_flag |= (error_flag != 0) ? 1 : 0; + + H264D_DBG(H264D_DBG_DISCONTINUOUS, "[discontinuous] last_slice=%d, cur_slice=%d, last_fnum=%d, cur_fnum=%d, last_poc=%d, cur_poc=%d", + p_last->slice_type, dec_pic->slice_type, p_last->frame_num, dec_pic->frame_num, p_last->poc, dec_pic->poc); + } + + if (dec_pic->idr_flag || dec_pic->used_for_reference) + currSlice->p_Vid->last_ref_frame_num = dec_pic->frame_num; + return ret = MPP_OK; +} + +static MPP_RET alloc_decpic(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_StorePic_t *dec_pic = NULL; + + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_SPS_t *active_sps = p_Vid->active_sps; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + H264_DecCtx_t *p_Dec = p_Vid->p_Dec; + + dec_pic = alloc_storable_picture(p_Vid, currSlice->structure); + MEM_CHECK(ret, dec_pic); + currSlice->toppoc = p_Vid->last_toppoc[currSlice->layer_id]; + currSlice->bottompoc = p_Vid->last_bottompoc[currSlice->layer_id]; + currSlice->framepoc = p_Vid->last_framepoc[currSlice->layer_id]; + currSlice->ThisPOC = p_Vid->last_thispoc[currSlice->layer_id]; + FUN_CHECK(ret = decode_poc(p_Vid, currSlice)); //!< calculate POC + + dec_pic->top_poc = currSlice->toppoc; + dec_pic->bottom_poc = currSlice->bottompoc; + dec_pic->frame_poc = currSlice->framepoc; + dec_pic->ThisPOC = currSlice->ThisPOC; + + p_Vid->last_toppoc[currSlice->layer_id] = currSlice->toppoc; + p_Vid->last_bottompoc[currSlice->layer_id] = currSlice->bottompoc; + p_Vid->last_framepoc[currSlice->layer_id] = currSlice->framepoc; + p_Vid->last_thispoc[currSlice->layer_id] = currSlice->ThisPOC; + + if (currSlice->structure == FRAME) { + if (currSlice->mb_aff_frame_flag) { + dec_pic->iCodingType = FRAME_MB_PAIR_CODING; + } else { + dec_pic->iCodingType = FRAME_CODING; + } + } else { + dec_pic->iCodingType = FIELD_CODING; + } + dec_pic->layer_id = currSlice->layer_id; + dec_pic->view_id = currSlice->view_id; + dec_pic->inter_view_flag = currSlice->inter_view_flag; + dec_pic->anchor_pic_flag = currSlice->anchor_pic_flag; + if (dec_pic->layer_id == 1) { + if ((p_Vid->profile_idc == H264_PROFILE_MVC_HIGH) || (p_Vid->profile_idc == H264_PROFILE_STEREO_HIGH)) { + FUN_CHECK(ret = init_mvc_picture(currSlice)); + } + } + if (currSlice->structure == TOP_FIELD) { + dec_pic->poc = currSlice->toppoc; + } else if (currSlice->structure == BOTTOM_FIELD) { + dec_pic->poc = currSlice->bottompoc; + } else if (currSlice->structure == FRAME) { + dec_pic->poc = currSlice->framepoc; + } else { + ret = MPP_NOK; + goto __FAILED; + } + dec_pic->slice_type = p_Vid->type; + dec_pic->used_for_reference = (currSlice->nal_reference_idc != 0); + dec_pic->idr_flag = currSlice->idr_flag; + dec_pic->no_output_of_prior_pics_flag = currSlice->no_output_of_prior_pics_flag; + dec_pic->long_term_reference_flag = currSlice->long_term_reference_flag; + dec_pic->adaptive_ref_pic_buffering_flag = currSlice->adaptive_ref_pic_buffering_flag; + dec_pic->dec_ref_pic_marking_buffer = currSlice->dec_ref_pic_marking_buffer; + + currSlice->dec_ref_pic_marking_buffer = NULL; + dec_pic->mb_aff_frame_flag = currSlice->mb_aff_frame_flag; + dec_pic->PicWidthInMbs = p_Vid->PicWidthInMbs; + dec_pic->pic_num = currSlice->frame_num; + dec_pic->frame_num = currSlice->frame_num; + dec_pic->chroma_format_idc = active_sps->chroma_format_idc; + + dec_pic->frame_mbs_only_flag = active_sps->frame_mbs_only_flag; + dec_pic->frame_cropping_flag = active_sps->frame_cropping_flag; + if (dec_pic->frame_cropping_flag) { + dec_pic->frame_crop_left_offset = active_sps->frame_crop_left_offset; + dec_pic->frame_crop_right_offset = active_sps->frame_crop_right_offset; + dec_pic->frame_crop_top_offset = active_sps->frame_crop_top_offset; + dec_pic->frame_crop_bottom_offset = active_sps->frame_crop_bottom_offset; + } else { + dec_pic->frame_crop_left_offset = 0; + dec_pic->frame_crop_right_offset = 0; + dec_pic->frame_crop_top_offset = 0; + dec_pic->frame_crop_bottom_offset = 0; + } + dec_pic->width = p_Vid->width; + dec_pic->height = p_Vid->height; + dec_pic->width_after_crop = p_Vid->width_after_crop; + dec_pic->height_after_crop = p_Vid->height_after_crop; + dec_pic->combine_flag = get_field_dpb_combine_flag(p_Dpb->last_picture, dec_pic); + /* malloc dpb_memory */ + FUN_CHECK(ret = dpb_mark_malloc(p_Vid, dec_pic)); + if (!p_Dec->cfg->base.disable_dpb_chk) { + FUN_CHECK(ret = check_dpb_discontinuous(p_Vid->last_pic, dec_pic, currSlice)); + } + dec_pic->mem_malloc_type = Mem_Malloc; + dec_pic->colmv_no_used_flag = 0; + p_Vid->dec_pic = dec_pic; + + return ret = MPP_OK; +__FAILED: + mpp_mem_pool_put_f(p_Vid->pic_st, dec_pic); + p_Vid->dec_pic = NULL; + + return ret; +} + +static void update_pic_num(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + H264_SPS_t *active_sps = p_Vid->active_sps; + + RK_S32 add_top = 0, add_bottom = 0; + RK_S32 max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4); + + if (currSlice->idr_flag) { + return; + } + if (currSlice->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used == 3) { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { + if ((RK_S32)p_Dpb->fs_ref[i]->frame_num > currSlice->frame_num) { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num - max_frame_num; + } else { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num; + } + p_Dpb->fs_ref[i]->frame->pic_num = p_Dpb->fs_ref[i]->frame_num_wrap; + } + } + } + //!< update long_term_pic_num + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_used == 3) { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) { + p_Dpb->fs_ltref[i]->frame->long_term_pic_num = p_Dpb->fs_ltref[i]->frame->long_term_frame_idx; + } + } + } + } else { + if (currSlice->structure == TOP_FIELD) { + add_top = 1; + add_bottom = 0; + } else { + add_top = 0; + add_bottom = 1; + } + + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference) { + if ((RK_S32)p_Dpb->fs_ref[i]->frame_num > currSlice->frame_num) { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num - max_frame_num; + } else { + p_Dpb->fs_ref[i]->frame_num_wrap = p_Dpb->fs_ref[i]->frame_num; + } + if (p_Dpb->fs_ref[i]->is_reference & 1) { + p_Dpb->fs_ref[i]->top_field->pic_num = (2 * p_Dpb->fs_ref[i]->frame_num_wrap) + add_top; + } + if (p_Dpb->fs_ref[i]->is_reference & 2) { + p_Dpb->fs_ref[i]->bottom_field->pic_num = (2 * p_Dpb->fs_ref[i]->frame_num_wrap) + add_bottom; + } + } + } + //!< update long_term_pic_num + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_long_term & 1) { + p_Dpb->fs_ltref[i]->top_field->long_term_pic_num = 2 * p_Dpb->fs_ltref[i]->top_field->long_term_frame_idx + add_top; + } + if (p_Dpb->fs_ltref[i]->is_long_term & 2) { + p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num = 2 * p_Dpb->fs_ltref[i]->bottom_field->long_term_frame_idx + add_bottom; + } + } + } +} + + + + +static RK_S32 compare_pic_by_pic_num_desc(const void *arg1, const void *arg2) +{ + RK_S32 pic_num1 = (*(H264_StorePic_t**)arg1)->pic_num; + RK_S32 pic_num2 = (*(H264_StorePic_t**)arg2)->pic_num; + + if (pic_num1 < pic_num2) + return 1; + if (pic_num1 > pic_num2) + return -1; + else + return 0; +} + +static RK_S32 compare_pic_by_lt_pic_num_asc(const void *arg1, const void *arg2) +{ + RK_S32 long_term_pic_num1 = (*(H264_StorePic_t**)arg1)->long_term_pic_num; + RK_S32 long_term_pic_num2 = (*(H264_StorePic_t**)arg2)->long_term_pic_num; + + if (long_term_pic_num1 < long_term_pic_num2) + return -1; + if (long_term_pic_num1 > long_term_pic_num2) + return 1; + else + return 0; +} + +static RK_S32 compare_fs_by_frame_num_desc(const void *arg1, const void *arg2) +{ + RK_S32 frame_num_wrap1 = (*(H264_FrameStore_t**)arg1)->frame_num_wrap; + RK_S32 frame_num_wrap2 = (*(H264_FrameStore_t**)arg2)->frame_num_wrap; + if (frame_num_wrap1 < frame_num_wrap2) + return 1; + if (frame_num_wrap1 > frame_num_wrap2) + return -1; + else + return 0; +} + +static RK_S32 compare_fs_by_lt_pic_idx_asc(const void *arg1, const void *arg2) +{ + RK_S32 long_term_frame_idx1 = (*(H264_FrameStore_t**)arg1)->long_term_frame_idx; + RK_S32 long_term_frame_idx2 = (*(H264_FrameStore_t**)arg2)->long_term_frame_idx; + + if (long_term_frame_idx1 < long_term_frame_idx2) + return -1; + else if (long_term_frame_idx1 > long_term_frame_idx2) + return 1; + else + return 0; +} + +static RK_U32 is_long_ref(H264_StorePic_t *s) +{ + return ((s->used_for_reference) && (s->is_long_term)); +} + +static RK_U32 is_short_ref(H264_StorePic_t *s) +{ + return ((s->used_for_reference) && (!(s->is_long_term))); +} + +static void gen_pic_list_from_frame_list(RK_S32 currStructure, H264_FrameStore_t **fs_list, + RK_S32 list_idx, H264_StorePic_t **list, RK_U8 *list_size, RK_U32 long_term) +{ + RK_S32 top_idx = 0; + RK_S32 bot_idx = 0; + + RK_U32(*is_ref)(H264_StorePic_t * s) = (long_term != 0) ? is_long_ref : is_short_ref; + + if (currStructure == TOP_FIELD) { + while ((top_idx < list_idx) || (bot_idx < list_idx)) { + for (; top_idx < list_idx; top_idx++) { + if (fs_list[top_idx]->is_used & 1) { + if (is_ref(fs_list[top_idx]->top_field)) { + //top_field; + (*list_size)++; + top_idx++; + break; + } + } + } + for (; bot_idx < list_idx; bot_idx++) { + if (fs_list[bot_idx]->is_used & 2) { + if (is_ref(fs_list[bot_idx]->bottom_field)) { + //bottom_field; + (*list_size)++; + bot_idx++; + break; + } + } + } + } + } + if (currStructure == BOTTOM_FIELD) { + while ((top_idx < list_idx) || (bot_idx < list_idx)) { + for (; bot_idx < list_idx; bot_idx++) { + if (fs_list[bot_idx]->is_used & 2) { + if (is_ref(fs_list[bot_idx]->bottom_field)) { + // short term ref pic + list[(RK_S16)*list_size] = fs_list[bot_idx]->bottom_field; + (*list_size)++; + bot_idx++; + break; + } + } + } + for (; top_idx < list_idx; top_idx++) { + if (fs_list[top_idx]->is_used & 1) { + if (is_ref(fs_list[top_idx]->top_field)) { + //!< short term ref pic + list[(RK_S16)*list_size] = fs_list[top_idx]->top_field; + (*list_size)++; + top_idx++; + break; + } + } + } + } + } +} + +static RK_U32 is_view_id_in_ref_view_list(RK_S32 view_id, RK_S32 *ref_view_id, RK_S32 num_ref_views) +{ + RK_S32 i; + for (i = 0; i < num_ref_views; i++) { + if (view_id == ref_view_id[i]) + break; + } + + return (num_ref_views && (i < num_ref_views)); +} + +static MPP_RET append_interview_list(H264_DpbBuf_t *p_Dpb, + RK_S32 currPicStructure, RK_S32 list_idx, H264_FrameStore_t **list, + RK_S32 *listXsize, RK_S32 currPOC, RK_S32 curr_layer_id, RK_S32 anchor_pic_flag) +{ + RK_S32 poc = 0; + RK_S32 fld_idx = 0; + RK_U32 pic_avail = 0; + RK_S32 num_ref_views = 0; + RK_S32 *ref_view_id = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 iVOIdx = curr_layer_id; + H264_FrameStore_t *fs = p_Dpb->fs_ilref[0]; + H264dVideoCtx_t *p_Vid = p_Dpb->p_Vid; + + VAL_CHECK(ret, iVOIdx >= 0); //!< Error: iVOIdx: %d is not less than 0 + if (anchor_pic_flag) { + num_ref_views = (list_idx != 0) ? p_Vid->active_subsps->num_anchor_refs_l1[iVOIdx] : p_Vid->active_subsps->num_anchor_refs_l0[iVOIdx]; + ref_view_id = (list_idx != 0) ? p_Vid->active_subsps->anchor_ref_l1[iVOIdx] : p_Vid->active_subsps->anchor_ref_l0[iVOIdx]; + } else { + num_ref_views = (list_idx != 0) ? p_Vid->active_subsps->num_non_anchor_refs_l1[iVOIdx] : p_Vid->active_subsps->num_non_anchor_refs_l0[iVOIdx]; + ref_view_id = (list_idx != 0) ? p_Vid->active_subsps->non_anchor_ref_l1[iVOIdx] : p_Vid->active_subsps->non_anchor_ref_l0[iVOIdx]; + } + + if (currPicStructure == BOTTOM_FIELD) + fld_idx = 1; + else + fld_idx = 0; + + if (currPicStructure == FRAME) { + pic_avail = (fs->is_used == 3); + if (pic_avail) { + poc = (fs->frame->is_mmco_5 != 0) ? fs->frame->poc_mmco5 : fs->frame->poc; + } + } else if (currPicStructure == TOP_FIELD) { + pic_avail = fs->is_used & 1; + if (pic_avail) { + poc = (fs->top_field->is_mmco_5 != 0) ? fs->top_field->top_poc_mmco5 : fs->top_field->poc; + } + } else if (currPicStructure == BOTTOM_FIELD) { + pic_avail = fs->is_used & 2; + if (pic_avail) { + poc = (fs->bottom_field->is_mmco_5 != 0) ? fs->bottom_field->bot_poc_mmco5 : fs->bottom_field->poc; + } + } else { + pic_avail = 0; + } + + if (pic_avail && fs->inter_view_flag[fld_idx]) { + if (poc == currPOC) { + if (is_view_id_in_ref_view_list(fs->view_id, ref_view_id, num_ref_views)) { + //!< add one inter-view reference; + list[*listXsize] = fs; + //!< next; + (*listXsize)++; + } + } + } + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void gen_pic_list_from_frame_interview_list(RK_S32 currStructure, + H264_FrameStore_t **fs_list, RK_S32 list_idx, H264_StorePic_t **list, RK_U8 *list_size) +{ + RK_S32 i; + + if (currStructure == TOP_FIELD) { + for (i = 0; i < list_idx; i++) { + list[(RK_S32)(*list_size)] = fs_list[i]->top_field; + (*list_size)++; + } + } + if (currStructure == BOTTOM_FIELD) { + for (i = 0; i < list_idx; i++) { + list[(RK_S32)(*list_size)] = fs_list[i]->bottom_field; + (*list_size)++; + } + } +} + +static RK_S32 compare_pic_by_poc_desc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_StorePic_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_StorePic_t**)arg2)->poc; + + if (poc1 < poc2) + return 1; + if (poc1 > poc2) + return -1; + else + return 0; +} + +static RK_S32 compare_pic_by_poc_asc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_StorePic_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_StorePic_t**)arg2)->poc; + + if (poc1 < poc2) + return -1; + if (poc1 > poc2) + return 1; + else + return 0; +} + +static RK_S32 compare_fs_by_poc_desc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_FrameStore_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_FrameStore_t**)arg2)->poc; + + if (poc1 < poc2) + return 1; + else if (poc1 > poc2) + return -1; + else + return 0; +} + +static RK_S32 compare_fs_by_poc_asc(const void *arg1, const void *arg2) +{ + RK_S32 poc1 = (*(H264_FrameStore_t**)arg1)->poc; + RK_S32 poc2 = (*(H264_FrameStore_t**)arg2)->poc; + + if (poc1 < poc2) + return -1; + else if (poc1 > poc2) + return 1; + else + return 0; +} + +static MPP_RET init_lists_p_slice_mvc(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + RK_S32 list0idx = 0; + RK_S32 listltidx = 0; + H264_FrameStore_t **fs_list0 = 0; + H264_FrameStore_t **fs_listlt = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + RK_S32 currPOC = currSlice->ThisPOC; + RK_S32 anchor_pic_flag = currSlice->anchor_pic_flag; + + currSlice->listXsizeP[0] = 0; + currSlice->listXsizeP[1] = 0; + currSlice->listinterviewidx0 = 0; + currSlice->listinterviewidx1 = 0; + + if (currSlice->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used == 3) { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { + currSlice->listP[0][list0idx++] = p_Dpb->fs_ref[i]->frame; + } + } + } + // order list 0 by PicNum + qsort((void *)currSlice->listP[0], list0idx, sizeof(H264_StorePic_t*), compare_pic_by_pic_num_desc); + currSlice->listXsizeP[0] = (RK_U8)list0idx; + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_used == 3) { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) { + currSlice->listP[0][list0idx++] = p_Dpb->fs_ltref[i]->frame; + } + } + } + qsort((void *)&currSlice->listP[0][(RK_S16)currSlice->listXsizeP[0]], + list0idx - currSlice->listXsizeP[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); + currSlice->listXsizeP[0] = (RK_U8)list0idx; + } else { + fs_list0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + fs_listlt = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, fs_list0 && fs_listlt); + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_reference) { + fs_list0[list0idx++] = p_Dpb->fs_ref[i]; + } + } + qsort((void *)fs_list0, list0idx, sizeof(H264_FrameStore_t*), compare_fs_by_frame_num_desc); + currSlice->listXsizeP[0] = 0; + gen_pic_list_from_frame_list(currSlice->structure, fs_list0, list0idx, currSlice->listP[0], &currSlice->listXsizeP[0], 0); + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; + } + qsort((void *)fs_listlt, listltidx, sizeof(H264_FrameStore_t*), compare_fs_by_lt_pic_idx_asc); + gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listP[0], &currSlice->listXsizeP[0], 1); + MPP_FREE(fs_list0); + MPP_FREE(fs_listlt); + } + + currSlice->listXsizeP[1] = 0; + if (currSlice->mvcExt.valid && p_Vid->active_mvc_sps_flag && currSlice->svc_extension_flag == 0) { + RK_S32 curr_layer_id = currSlice->layer_id; + currSlice->fs_listinterview0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, currSlice->fs_listinterview0); + list0idx = currSlice->listXsizeP[0]; + if (currSlice->structure == FRAME) { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + for (i = 0; i < (RK_U32)currSlice->listinterviewidx0; i++) { + currSlice->listP[0][list0idx++] = currSlice->fs_listinterview0[i]->frame; + } + currSlice->listXsizeP[0] = (RK_U8)list0idx; + } else { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview0, + currSlice->listinterviewidx0, currSlice->listP[0], &currSlice->listXsizeP[0]); + } + } + // set the unused list entries to NULL + for (i = currSlice->listXsizeP[0]; i < (MAX_LIST_SIZE); i++) { + currSlice->listP[0][i] = p_Vid->no_ref_pic; + } + for (i = currSlice->listXsizeP[1]; i < (MAX_LIST_SIZE); i++) { + currSlice->listP[1][i] = p_Vid->no_ref_pic; + } + MPP_FREE(currSlice->fs_listinterview0); + + return ret = MPP_OK; +__FAILED: + MPP_FREE(fs_list0); + MPP_FREE(fs_listlt); + MPP_FREE(currSlice->fs_listinterview0); + + return ret; +} + +static MPP_RET init_lists_b_slice_mvc(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + RK_S32 j = 0; + RK_S32 list0idx = 0; + RK_S32 list0idx_1 = 0; + RK_S32 listltidx = 0; + H264_FrameStore_t **fs_list0 = NULL; + H264_FrameStore_t **fs_list1 = NULL; + H264_FrameStore_t **fs_listlt = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + RK_S32 currPOC = currSlice->ThisPOC; + RK_S32 anchor_pic_flag = currSlice->anchor_pic_flag; + + currSlice->listXsizeB[0] = 0; + currSlice->listXsizeB[1] = 0; + currSlice->listinterviewidx0 = 0; + currSlice->listinterviewidx1 = 0; + // B-Slice + if (currSlice->structure == FRAME) { + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used == 3) { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { + if (currSlice->framepoc >= p_Dpb->fs_ref[i]->frame->poc) { + currSlice->listB[0][list0idx++] = p_Dpb->fs_ref[i]->frame; + } + } + } + } + qsort((void *)currSlice->listB[0], list0idx, sizeof(H264_StorePic_t*), compare_pic_by_poc_desc); + list0idx_1 = list0idx; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used == 3) { + if ((p_Dpb->fs_ref[i]->frame->used_for_reference) && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { + if (currSlice->framepoc < p_Dpb->fs_ref[i]->frame->poc) { + currSlice->listB[0][list0idx++] = p_Dpb->fs_ref[i]->frame; + } + } + } + } + qsort((void *)&currSlice->listB[0][list0idx_1], list0idx - list0idx_1, sizeof(H264_StorePic_t*), compare_pic_by_poc_asc); + + for (j = 0; j < list0idx_1; j++) { + currSlice->listB[1][list0idx - list0idx_1 + j] = currSlice->listB[0][j]; + } + for (j = list0idx_1; j < list0idx; j++) { + currSlice->listB[1][j - list0idx_1] = currSlice->listB[0][j]; + } + currSlice->listXsizeB[0] = currSlice->listXsizeB[1] = (RK_U8)list0idx; + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (p_Dpb->fs_ltref[i]->is_used == 3) { + if (p_Dpb->fs_ltref[i]->frame->is_long_term) { + currSlice->listB[0][list0idx] = p_Dpb->fs_ltref[i]->frame; + currSlice->listB[1][list0idx++] = p_Dpb->fs_ltref[i]->frame; + } + } + } + qsort((void *)&currSlice->listB[0][(RK_S16)currSlice->listXsizeB[0]], + list0idx - currSlice->listXsizeB[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); + qsort((void *)&currSlice->listB[1][(RK_S16)currSlice->listXsizeB[0]], + list0idx - currSlice->listXsizeB[0], sizeof(H264_StorePic_t*), compare_pic_by_lt_pic_num_asc); + currSlice->listXsizeB[0] = currSlice->listXsizeB[1] = (RK_U8)list0idx; + } else { + fs_list0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + fs_list1 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + fs_listlt = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, fs_list0 && fs_list1 && fs_listlt); + currSlice->listXsizeB[0] = 0; + currSlice->listXsizeB[1] = 1; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used) { + if (currSlice->ThisPOC >= p_Dpb->fs_ref[i]->poc) { + fs_list0[list0idx++] = p_Dpb->fs_ref[i]; + } + } + } + qsort((void *)fs_list0, list0idx, sizeof(H264_FrameStore_t*), compare_fs_by_poc_desc); + list0idx_1 = list0idx; + for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) { + if (p_Dpb->fs_ref[i]->is_used) { + if (currSlice->ThisPOC < p_Dpb->fs_ref[i]->poc) { + fs_list0[list0idx++] = p_Dpb->fs_ref[i]; + } + } + } + qsort((void *)&fs_list0[list0idx_1], list0idx - list0idx_1, sizeof(H264_FrameStore_t*), compare_fs_by_poc_asc); + + for (j = 0; j < list0idx_1; j++) { + fs_list1[list0idx - list0idx_1 + j] = fs_list0[j]; + } + for (j = list0idx_1; j < list0idx; j++) { + fs_list1[j - list0idx_1] = fs_list0[j]; + } + currSlice->listXsizeB[0] = 0; + currSlice->listXsizeB[1] = 0; + gen_pic_list_from_frame_list(currSlice->structure, fs_list0, list0idx, currSlice->listB[0], &currSlice->listXsizeB[0], 0); + gen_pic_list_from_frame_list(currSlice->structure, fs_list1, list0idx, currSlice->listB[1], &currSlice->listXsizeB[1], 0); + + // long term handling + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + fs_listlt[listltidx++] = p_Dpb->fs_ltref[i]; + } + qsort((void *)fs_listlt, listltidx, sizeof(H264_FrameStore_t*), compare_fs_by_lt_pic_idx_asc); + + gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listB[0], &currSlice->listXsizeB[0], 1); + gen_pic_list_from_frame_list(currSlice->structure, fs_listlt, listltidx, currSlice->listB[1], &currSlice->listXsizeB[1], 1); + + MPP_FREE(fs_list0); + MPP_FREE(fs_list1); + MPP_FREE(fs_listlt); + } + if ((currSlice->listXsizeB[0] == currSlice->listXsizeB[1]) && (currSlice->listXsizeB[0] > 1)) { + // check if lists are identical, if yes swap first two elements of currSlice->listX[1] + RK_S32 diff = 0; + for (j = 0; j < currSlice->listXsizeB[0]; j++) { + if (currSlice->listB[0][j] != currSlice->listB[1][j]) { + diff = 1; + break; + } + } + if (!diff) { + H264_StorePic_t *tmp_s = currSlice->listB[1][0]; + currSlice->listB[1][0] = currSlice->listB[1][1]; + currSlice->listB[1][1] = tmp_s; + } + } + if (currSlice->mvcExt.valid && p_Vid->active_mvc_sps_flag && currSlice->svc_extension_flag == 0) { + RK_S32 curr_layer_id = currSlice->layer_id; + // B-Slice + currSlice->fs_listinterview0 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + currSlice->fs_listinterview1 = mpp_calloc(H264_FrameStore_t*, p_Dpb->size); + MEM_CHECK(ret, currSlice->fs_listinterview0 && currSlice->fs_listinterview1); + list0idx = currSlice->listXsizeB[0]; + if (currSlice->structure == FRAME) { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 1, + currSlice->fs_listinterview1, &currSlice->listinterviewidx1, currPOC, curr_layer_id, anchor_pic_flag)); + + for (i = 0; i < (RK_U32)currSlice->listinterviewidx0; i++) { + currSlice->listB[0][list0idx++] = currSlice->fs_listinterview0[i]->frame; + } + currSlice->listXsizeB[0] = (RK_U8)list0idx; + list0idx = currSlice->listXsizeB[1]; + for (i = 0; i < (RK_U32)currSlice->listinterviewidx1; i++) { + currSlice->listB[1][list0idx++] = currSlice->fs_listinterview1[i]->frame; + } + currSlice->listXsizeB[1] = (RK_U8)list0idx; + } else { + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 0, + currSlice->fs_listinterview0, &currSlice->listinterviewidx0, currPOC, curr_layer_id, anchor_pic_flag)); + gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview0, + currSlice->listinterviewidx0, currSlice->listB[0], &currSlice->listXsizeB[0]); + FUN_CHECK(ret = append_interview_list(p_Vid->p_Dpb_layer[1], currSlice->structure, 1, + currSlice->fs_listinterview1, &currSlice->listinterviewidx1, currPOC, curr_layer_id, anchor_pic_flag)); + gen_pic_list_from_frame_interview_list(currSlice->structure, currSlice->fs_listinterview1, + currSlice->listinterviewidx1, currSlice->listB[1], &currSlice->listXsizeB[1]); + } + } + // set the unused list entries to NULL + for (i = currSlice->listXsizeB[0]; i < (MAX_LIST_SIZE); i++) { + currSlice->listB[0][i] = p_Vid->no_ref_pic; + } + for (i = currSlice->listXsizeB[1]; i < (MAX_LIST_SIZE); i++) { + currSlice->listB[1][i] = p_Vid->no_ref_pic; + } + MPP_FREE(currSlice->fs_listinterview0); + MPP_FREE(currSlice->fs_listinterview1); + + return ret = MPP_OK; +__FAILED: + MPP_FREE(fs_list0); + MPP_FREE(fs_list1); + MPP_FREE(fs_listlt); + MPP_FREE(currSlice->fs_listinterview0); + MPP_FREE(currSlice->fs_listinterview1); + + return ret; +} + +static RK_U32 get_short_term_pic(H264_SLICE_t *currSlice, RK_S32 picNum, H264_StorePic_t **find_pic) +{ + RK_S32 i = 0; + H264_StorePic_t *ret_pic = NULL; + H264_StorePic_t *near_pic = NULL; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + + for (i = p_Dpb->ref_frames_in_buffer - 1; i >= 0; i--) { + if (currSlice->structure == FRAME) { + if ((p_Dpb->fs_ref[i]->is_reference == 3) + && (!p_Dpb->fs_ref[i]->frame->is_long_term)) { + if (p_Dpb->fs_ref[i]->frame->pic_num == picNum) { + ret_pic = p_Dpb->fs_ref[i]->frame; + break; + } else { + near_pic = p_Dpb->fs_ref[i]->frame; + } + } + } else { + if ((p_Dpb->fs_ref[i]->is_reference & 1) + && (!p_Dpb->fs_ref[i]->top_field->is_long_term)) { + if (p_Dpb->fs_ref[i]->top_field->pic_num == picNum) { + ret_pic = p_Dpb->fs_ref[i]->top_field; + break; + } else { + near_pic = p_Dpb->fs_ref[i]->top_field; + } + } + if ((p_Dpb->fs_ref[i]->is_reference & 2) + && (!p_Dpb->fs_ref[i]->bottom_field->is_long_term)) { + if (p_Dpb->fs_ref[i]->bottom_field->pic_num == picNum) { + ret_pic = p_Dpb->fs_ref[i]->bottom_field; + break; + } else { + near_pic = p_Dpb->fs_ref[i]->bottom_field; + } + } + } + } + *find_pic = ret_pic ? ret_pic : near_pic; + return (ret_pic ? 1 : 0); +} + + +static H264_StorePic_t *get_long_term_pic(H264_SLICE_t *currSlice, RK_S32 LongtermPicNum) +{ + RK_U32 i = 0; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + + for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) { + if (currSlice->structure == FRAME) { + if (p_Dpb->fs_ltref[i]->is_reference == 3) + if ((p_Dpb->fs_ltref[i]->frame->is_long_term) + && (p_Dpb->fs_ltref[i]->frame->long_term_pic_num == LongtermPicNum)) + return p_Dpb->fs_ltref[i]->frame; + } else { + if (p_Dpb->fs_ltref[i]->is_reference & 1) + if ((p_Dpb->fs_ltref[i]->top_field->is_long_term) + && (p_Dpb->fs_ltref[i]->top_field->long_term_pic_num == LongtermPicNum)) + return p_Dpb->fs_ltref[i]->top_field; + if (p_Dpb->fs_ltref[i]->is_reference & 2) + if ((p_Dpb->fs_ltref[i]->bottom_field->is_long_term) + && (p_Dpb->fs_ltref[i]->bottom_field->long_term_pic_num == LongtermPicNum)) + return p_Dpb->fs_ltref[i]->bottom_field; + } + } + return NULL; +} +static RK_U32 check_ref_pic_list(H264_SLICE_t *currSlice, RK_S32 cur_list) +{ + RK_S32 i = 0; + RK_U32 dpb_error_flag = 0; + RK_S32 maxPicNum = 0, currPicNum = 0; + RK_S32 picNumLXNoWrap = 0, picNumLXPred = 0, picNumLX = 0; + + RK_S32 *modification_of_pic_nums_idc = currSlice->modification_of_pic_nums_idc[cur_list]; + RK_S32 *abs_diff_pic_num_minus1 = currSlice->abs_diff_pic_num_minus1[cur_list]; + RK_S32 *long_term_pic_idx = currSlice->long_term_pic_idx[cur_list]; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + + if (currSlice->structure == FRAME) { + maxPicNum = p_Vid->max_frame_num; + currPicNum = currSlice->frame_num; + } else { + maxPicNum = 2 * p_Vid->max_frame_num; + currPicNum = 2 * currSlice->frame_num + 1; + } + picNumLXPred = currPicNum; + for (i = 0; modification_of_pic_nums_idc[i] != 3 && i < MAX_REORDER_TIMES; i++) { + H264_StorePic_t *tmp = NULL; + RK_U32 error_flag = 0; + if (modification_of_pic_nums_idc[i] > 3) + continue; + if (modification_of_pic_nums_idc[i] < 2) { + if (modification_of_pic_nums_idc[i] == 0) { + if ( (picNumLXPred - (abs_diff_pic_num_minus1[i] + 1)) < 0) + picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1) + maxPicNum; + else + picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1); + } else { //!< (modification_of_pic_nums_idc[i] == 1) + if (picNumLXPred + (abs_diff_pic_num_minus1[i] + 1) >= maxPicNum) + picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1) - maxPicNum; + else + picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1); + } + picNumLXPred = picNumLXNoWrap; + picNumLX = (picNumLXNoWrap > currPicNum) ? (picNumLXNoWrap - maxPicNum) : picNumLXNoWrap; + error_flag = 1; + if (get_short_term_pic(currSlice, picNumLX, &tmp)) { //!< find short reference + MppFrame mframe = NULL; + H264D_DBG(H264D_DBG_DPB_REF_ERR, "find short reference, slot_idx=%d.\n", tmp->mem_mark->slot_idx); + if (tmp && tmp->mem_mark && tmp->mem_mark->slot_idx >= 0) { + mpp_buf_slot_get_prop(p_Vid->p_Dec->frame_slots, tmp->mem_mark->slot_idx, SLOT_FRAME_PTR, &mframe); + if (mframe && !mpp_frame_get_errinfo(mframe)) { + error_flag = 0; + } + } + } + + } else { //!< (modification_of_pic_nums_idc[i] == 2) + tmp = get_long_term_pic(currSlice, long_term_pic_idx[i]); + } + dpb_error_flag |= error_flag; + } + + return dpb_error_flag; +} + +static RK_U32 check_ref_dbp_err(H264_DecCtx_t *p_Dec, H264_RefPicInfo_t *pref, RK_U32 active_refs) +{ + RK_U32 i = 0; + RK_U32 dpb_error_flag = 0; + + for (i = 0; i < MAX_REF_SIZE; i++) { + if (pref[i].valid) { + MppFrame mframe = NULL; + RK_S32 slot_idx = p_Dec->dpb_info[pref[i].dpb_idx].slot_index; + if (slot_idx < 0) { + dpb_error_flag |= 1; + break; + } + mpp_buf_slot_get_prop(p_Dec->frame_slots, slot_idx, SLOT_FRAME_PTR, &mframe); + if (mframe) { + if (i < active_refs + && (!p_Dec->p_Vid->recovery.valid_flag + || p_Dec->dpb_info[pref[i].dpb_idx].frame_num < p_Dec->p_Vid->recovery.first_frm_valid + || p_Dec->dpb_info[pref[i].dpb_idx].frame_num >= p_Dec->p_Vid->recovery.recovery_pic_id)) { + dpb_error_flag |= mpp_frame_get_errinfo(mframe); + } + H264D_DBG(H264D_DBG_DPB_REF_ERR, "[DPB_REF_ERR] slot_idx=%d, dpb_err[%d]=%d", slot_idx, i, mpp_frame_get_errinfo(mframe)); + } + } + } + return dpb_error_flag; +} + +static void check_refer_picture_lists(H264_SLICE_t *currSlice) +{ + H264_DecCtx_t *p_Dec = currSlice->p_Dec; + H264dErrCtx_t *p_err = &p_Dec->errctx; + + if (H264_I_SLICE == currSlice->slice_type) { + p_err->dpb_err_flag = 0; + return; + } +#if 1 + + if ((currSlice->slice_type % 5) != H264_I_SLICE + && (currSlice->slice_type % 5) != H264_SI_SLICE) { + if (currSlice->ref_pic_list_reordering_flag[LIST_0]) { + p_err->cur_err_flag |= (check_ref_pic_list(currSlice, 0) != 0) ? 1 : 0; + } else { + RK_S32 pps_refs = currSlice->active_pps->num_ref_idx_l0_default_active_minus1 + 1; + RK_S32 over_flag = currSlice->num_ref_idx_override_flag; + RK_S32 active_l0 = (over_flag != 0) ? currSlice->num_ref_idx_active[LIST_0] : pps_refs; + if (currSlice->slice_type % 5 == H264_B_SLICE) + p_err->cur_err_flag |= (check_ref_dbp_err(p_Dec, p_Dec->refpic_info_b[0], active_l0) != 0) ? 1 : 0; + else + p_err->cur_err_flag |= (check_ref_dbp_err(p_Dec, p_Dec->refpic_info_p, active_l0) != 0) ? 1 : 0; + H264D_DBG(H264D_DBG_DPB_REF_ERR, "list0 dpb: cur_err_flag=%d, pps_refs=%d, over_flag=%d, num_ref_l0=%d\n", + p_err->cur_err_flag, pps_refs, over_flag, active_l0); + } + } + if (currSlice->slice_type % 5 == H264_B_SLICE) { + if (currSlice->ref_pic_list_reordering_flag[LIST_1]) { + p_err->cur_err_flag |= (check_ref_pic_list(currSlice, 1) != 0) ? 1 : 0; + } else { + RK_S32 pps_refs = currSlice->active_pps->num_ref_idx_l1_default_active_minus1 + 1; + RK_S32 over_flag = currSlice->num_ref_idx_override_flag; + RK_S32 active_l1 = (over_flag != 0) ? currSlice->num_ref_idx_active[LIST_1] : pps_refs; + p_err->cur_err_flag |= (check_ref_dbp_err(p_Dec, p_Dec->refpic_info_b[1], active_l1) != 0) ? 1 : 0; + H264D_DBG(H264D_DBG_DPB_REF_ERR, "list1 dpb: cur_err_flag=%d, pps_refs=%d, over_flag=%d, num_ref_l1=%d\n", + p_err->cur_err_flag, pps_refs, over_flag, active_l1); + } + } + +#endif + +} + +static void reset_dpb_info(H264_DpbInfo_t *p) +{ + p->refpic = NULL; + p->TOP_POC = 0; + p->BOT_POC = 0; + p->field_flag = 0; + p->slot_index = -1; + p->colmv_is_used = 0; + p->frame_num = 0; + p->is_long_term = 0; + p->long_term_pic_num = 0; + p->voidx = 0; + p->view_id = 0; + p->is_used = 0; +} + +static MPP_RET prepare_init_dpb_info(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0, j = 0; + H264_DpbBuf_t *p_Dpb = currSlice->p_Dpb; + H264_DecCtx_t *p_Dec = currSlice->p_Dec; + + //!< reset parameters + for (i = 0; i < MAX_DPB_SIZE; i++) { + reset_dpb_info(&p_Dec->dpb_info[i]); + } + //!< reference +#if 1 + for (i = 0, j = 0; j < p_Dpb->ref_frames_in_buffer; i++, j++) { + if (p_Dpb->fs_ref[j]->is_used == 3) { + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ref[j]->frame; + if (p_Dpb->fs_ref[j]->frame->iCodingType == FIELD_CODING) { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->bottom_field->poc; + } else { + if (p_Dpb->fs_ref[j]->frame->frame_poc != p_Dpb->fs_ref[j]->frame->poc) { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->frame->top_poc - p_Dpb->fs_ref[j]->frame->frame_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->frame->bottom_poc - p_Dpb->fs_ref[j]->frame->frame_poc; + } else { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->frame->top_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->frame->bottom_poc; + } + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ref[j]->frame->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ref[j]->frame->colmv_no_used_flag != 0) ? 0 : 1); + } else if (p_Dpb->fs_ref[j]->is_used) { + if (p_Dpb->fs_ref[j]->is_used & 0x1) { // top + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ref[j]->top_field; + + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = 0; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ref[j]->top_field->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ref[j]->top_field->colmv_no_used_flag != 0) ? 0 : 1); + } else { // if(p_Dpb->fs_ref[j]->is_used & 0x2) // bottom + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ref[j]->bottom_field; + p_Dec->dpb_info[i].TOP_POC = 0; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ref[j]->bottom_field->poc; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ref[j]->bottom_field->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ref[j]->bottom_field->colmv_no_used_flag != 0) ? 0 : 1); + } + } + p_Dec->dpb_info[i].frame_num = p_Dpb->fs_ref[j]->frame_num; + p_Dec->dpb_info[i].is_long_term = 0; + p_Dec->dpb_info[i].long_term_pic_num = 0; + p_Dec->dpb_info[i].long_term_frame_idx = 0; + p_Dec->dpb_info[i].voidx = p_Dpb->fs_ref[j]->layer_id; + p_Dec->dpb_info[i].view_id = p_Dpb->fs_ref[j]->view_id; + p_Dec->dpb_info[i].is_used = p_Dpb->fs_ref[j]->is_used; + } +#endif + //!<---- long term reference +#if 1 + for (j = 0; j < p_Dpb->ltref_frames_in_buffer; i++, j++) { + if (p_Dpb->fs_ltref[j]->is_used == 3) { + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ltref[j]->frame; + + if (p_Dpb->fs_ltref[j]->frame->iCodingType == FIELD_CODING) { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->bottom_field->poc; + } else { + if (p_Dpb->fs_ltref[j]->frame->frame_poc != p_Dpb->fs_ltref[j]->frame->poc) { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->frame->top_poc - p_Dpb->fs_ltref[j]->frame->frame_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->frame->bottom_poc - p_Dpb->fs_ltref[j]->frame->frame_poc; + } else { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->frame->top_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->frame->bottom_poc; + } + + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ltref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ltref[j]->frame->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ltref[j]->frame->colmv_no_used_flag != 0) ? 0 : 1); + p_Dec->dpb_info[i].long_term_pic_num = p_Dpb->fs_ltref[j]->frame->long_term_pic_num; + } else if (p_Dpb->fs_ltref[j]->is_used) { + if (p_Dpb->fs_ltref[j]->is_used & 0x1) { + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ltref[j]->top_field; + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ltref[j]->top_field->poc; + p_Dec->dpb_info[i].BOT_POC = 0; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ltref[j]->top_field->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ltref[j]->top_field->colmv_no_used_flag != 0) ? 0 : 1); + p_Dec->dpb_info[i].long_term_pic_num = p_Dpb->fs_ltref[j]->top_field->long_term_pic_num; + } else { // if(p_Dpb->fs_ref[j]->is_used & 0x2) + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ltref[j]->bottom_field; + p_Dec->dpb_info[i].TOP_POC = 0; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ltref[j]->bottom_field->poc; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ltref[j]->bottom_field->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ltref[j]->bottom_field->colmv_no_used_flag != 0) ? 0 : 1); + p_Dec->dpb_info[i].long_term_pic_num = p_Dpb->fs_ltref[j]->bottom_field->long_term_pic_num; + } + } + p_Dec->dpb_info[i].frame_num = p_Dpb->fs_ltref[j]->long_term_frame_idx; //long term use long_term_frame_idx + p_Dec->dpb_info[i].is_long_term = 1; + p_Dec->dpb_info[i].long_term_frame_idx = p_Dpb->fs_ltref[j]->long_term_frame_idx; + p_Dec->dpb_info[i].voidx = p_Dpb->fs_ltref[j]->layer_id; + p_Dec->dpb_info[i].view_id = p_Dpb->fs_ltref[j]->view_id; + p_Dec->dpb_info[i].is_used = p_Dpb->fs_ltref[j]->is_used; + } +#endif + //!< inter-layer reference (for multi-layered codecs) +#if 1 + for (j = 0; j < p_Dpb->used_size_il; i++, j++) { + if (currSlice->structure == FRAME && p_Dpb->fs_ilref[j]->is_used == 3) { + if (p_Dpb->fs_ilref[j]->inter_view_flag[0] == 0 && p_Dpb->fs_ilref[j]->inter_view_flag[1] == 0) + break; + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ilref[j]->frame; + + if (p_Dpb->fs_ilref[j]->frame->is_mmco_5) { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->frame->top_poc_mmco5; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->frame->bot_poc_mmco5; + } else { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->frame->top_poc; + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->frame->bottom_poc; + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ilref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ilref[j]->frame->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ilref[j]->frame->colmv_no_used_flag != 0) ? 0 : 1); + } else if (currSlice->structure != FRAME && p_Dpb->fs_ilref[j]->is_used) { + if (p_Dpb->fs_ilref[j]->is_used == 0x3) { + if (p_Dpb->fs_ilref[j]->inter_view_flag[currSlice->structure == BOTTOM_FIELD] == 0) + break; + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ilref[j]->top_field; + + if (p_Dpb->fs_ilref[j]->top_field->is_mmco_5) { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc_mmco5; + } else { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc; + } + if (p_Dpb->fs_ilref[j]->bottom_field->is_mmco_5) { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bot_poc_mmco5; + } else { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bottom_poc; + } + p_Dec->dpb_info[i].field_flag = p_Dpb->fs_ilref[j]->frame->iCodingType == FIELD_CODING; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ilref[j]->frame->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ilref[j]->frame->colmv_no_used_flag != 0) ? 0 : 1); + } + if (p_Dpb->fs_ilref[j]->is_used & 0x1) { + if (p_Dpb->fs_ilref[j]->inter_view_flag[0] == 0) + break; + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ilref[j]->top_field; + + if (p_Dpb->fs_ilref[j]->top_field->is_mmco_5) { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc_mmco5; + } else { + p_Dec->dpb_info[i].TOP_POC = p_Dpb->fs_ilref[j]->top_field->top_poc; + } + p_Dec->dpb_info[i].BOT_POC = 0; + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ilref[j]->top_field->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ilref[j]->top_field->colmv_no_used_flag != 0) ? 0 : 1); + } else { // if(p_Dpb->fs_ref[j]->is_used & 0x2) + if (p_Dpb->fs_ilref[j]->inter_view_flag[1] == 0) + break; + p_Dec->dpb_info[i].refpic = p_Dpb->fs_ilref[j]->bottom_field; + + p_Dec->dpb_info[i].TOP_POC = 0; + if (p_Dpb->fs_ilref[j]->bottom_field->is_mmco_5) { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bot_poc_mmco5; + } else { + p_Dec->dpb_info[i].BOT_POC = p_Dpb->fs_ilref[j]->bottom_field->bottom_poc; + } + p_Dec->dpb_info[i].field_flag = 1; + p_Dec->dpb_info[i].slot_index = p_Dpb->fs_ilref[j]->bottom_field->mem_mark->slot_idx; + p_Dec->dpb_info[i].colmv_is_used = ((p_Dpb->fs_ilref[j]->bottom_field->colmv_no_used_flag != 0) ? 0 : 1); + } + } + p_Dec->dpb_info[i].frame_num = p_Dpb->fs_ilref[j]->frame_num; + p_Dec->dpb_info[i].is_long_term = 0;//p_Dpb->fs_ilref[j]->is_long_term; + p_Dec->dpb_info[i].is_ilt_flag = 1; + p_Dec->dpb_info[i].long_term_pic_num = 0; + p_Dec->dpb_info[i].long_term_frame_idx = 0; + p_Dec->dpb_info[i].voidx = p_Dpb->fs_ilref[j]->layer_id; + p_Dec->dpb_info[i].view_id = p_Dpb->fs_ilref[j]->view_id; + p_Dec->dpb_info[i].is_used = p_Dpb->fs_ilref[j]->is_used; + } +#endif + + return MPP_OK; +} + +static MPP_RET prepare_init_ref_info(H264_SLICE_t *currSlice) +{ + void *refpic = NULL; + RK_U32 i = 0, j = 0, k = 0; + RK_S32 poc = 0, TOP_POC = 0, BOT_POC = 0; + RK_S32 min_poc = 0, max_poc = 0; + RK_S32 layer_id = 0, voidx = 0, is_used = 0, near_dpb_idx = 0; + RK_U32 mmco5_flag = 0; + H264_DecCtx_t *p_Dec = currSlice->p_Dec; + + memset(p_Dec->refpic_info_p, 0, MAX_REF_SIZE * sizeof(H264_RefPicInfo_t)); + memset(p_Dec->refpic_info_b[0], 0, MAX_REF_SIZE * sizeof(H264_RefPicInfo_t)); + memset(p_Dec->refpic_info_b[1], 0, MAX_REF_SIZE * sizeof(H264_RefPicInfo_t)); + + if (currSlice->idr_flag && (currSlice->layer_id == 0)) { // idr_flag==1 && layer_id==0 + goto __RETURN; + } + //!<------ set listP ------- + near_dpb_idx = 0; + for (j = 0; j < 32; j++) { + if (j >= currSlice->listXsizeP[0]) + break; + poc = 0; + layer_id = currSlice->listP[0][j]->layer_id; + mmco5_flag = (currSlice->listP[0][j]->is_mmco_5 && currSlice->layer_id && !currSlice->listP[0][j]->layer_id) ? 1 : 0; + if (currSlice->listP[0][j]->structure == FRAME) { + poc = (mmco5_flag != 0) ? currSlice->listP[0][j]->poc_mmco5 : currSlice->listP[0][j]->poc; + } else if (currSlice->listP[0][j]->structure == TOP_FIELD) { + poc = (mmco5_flag != 0) ? currSlice->listP[0][j]->top_poc_mmco5 : currSlice->listP[0][j]->top_poc; + } else { + poc = (mmco5_flag != 0) ? currSlice->listP[0][j]->bot_poc_mmco5 : currSlice->listP[0][j]->bottom_poc; + } + for (i = 0; i < 16; i++) { + refpic = p_Dec->dpb_info[i].refpic; + TOP_POC = p_Dec->dpb_info[i].TOP_POC; + BOT_POC = p_Dec->dpb_info[i].BOT_POC; + voidx = p_Dec->dpb_info[i].voidx; + is_used = p_Dec->dpb_info[i].is_used; + if (currSlice->structure == FRAME && refpic) { + if (poc == MPP_MIN(TOP_POC, BOT_POC) && (layer_id == voidx)) + break; + } else { + if (is_used == 3) { + if ((poc == BOT_POC || poc == TOP_POC) && layer_id == voidx) + break; + } else if (is_used & 1) { + if (poc == TOP_POC && layer_id == voidx) + break; + } else if (is_used & 2) { + if (poc == BOT_POC && layer_id == voidx) + break; + } + } + } + if (i < 16) { + near_dpb_idx = i; + p_Dec->refpic_info_p[j].dpb_idx = i; + } else { + ASSERT(near_dpb_idx >= 0); + p_Dec->refpic_info_p[j].dpb_idx = near_dpb_idx; + p_Dec->errctx.cur_err_flag |= 1; + } + if (currSlice->listP[0][j]->structure == BOTTOM_FIELD) { + p_Dec->refpic_info_p[j].bottom_flag = 1; + } else { + p_Dec->refpic_info_p[j].bottom_flag = 0; + } + p_Dec->refpic_info_p[j].valid = 1; + } + //!<------ set listB ------- + for (k = 0; k < 2; k++) { + RK_U32 tmp[16] = {0}; + + min_poc = 0xFFFF; + max_poc = -0xFFFF; + near_dpb_idx = 0; + for (j = 0; j < 32; j++) { + if (j >= currSlice->listXsizeB[k]) + break; + + poc = 0; + layer_id = currSlice->listB[k][j]->layer_id; + mmco5_flag = (currSlice->listB[k][j]->is_mmco_5 && currSlice->layer_id && !currSlice->listB[k][j]->layer_id) ? 1 : 0; + if (currSlice->listB[k][j]->structure == FRAME) { + poc = (mmco5_flag != 0) ? currSlice->listB[k][j]->poc_mmco5 : currSlice->listB[k][j]->poc; + } else if (currSlice->listB[k][j]->structure == TOP_FIELD) { + poc = (mmco5_flag != 0) ? currSlice->listB[k][j]->top_poc_mmco5 : currSlice->listB[k][j]->top_poc; + } else { + poc = (mmco5_flag != 0) ? currSlice->listB[k][j]->bot_poc_mmco5 : currSlice->listB[k][j]->bottom_poc; + } + + min_poc = MPP_MIN(min_poc, poc); + max_poc = MPP_MAX(max_poc, poc); + for (i = 0; i < 16; i++) { + refpic = p_Dec->dpb_info[i].refpic; + TOP_POC = p_Dec->dpb_info[i].TOP_POC; + BOT_POC = p_Dec->dpb_info[i].BOT_POC; + voidx = p_Dec->dpb_info[i].voidx; + is_used = p_Dec->dpb_info[i].is_used; + if (currSlice->structure == FRAME && refpic) { + if (poc == MPP_MIN(TOP_POC, BOT_POC) && (layer_id == voidx) && !tmp[i]) { + tmp[i] = 1; + break; + } + } else { + if (is_used == 3) { + if ((poc == BOT_POC || poc == TOP_POC) && layer_id == voidx) + break; + } else if (is_used & 1) { + if (poc == TOP_POC && (layer_id == voidx || (layer_id != voidx && !currSlice->bottom_field_flag))) + break; + } else if (is_used & 2) { + if (poc == BOT_POC && (layer_id == voidx || (layer_id != voidx && currSlice->bottom_field_flag))) + break; + } + } + } + if (i < 16) { + near_dpb_idx = i; + p_Dec->refpic_info_b[k][j].dpb_idx = i; + } else { + ASSERT(near_dpb_idx >= 0); + p_Dec->refpic_info_b[k][j].dpb_idx = near_dpb_idx; + p_Dec->errctx.cur_err_flag |= 1; + } + if (currSlice->listB[k][j]->structure == BOTTOM_FIELD) { + p_Dec->refpic_info_b[k][j].bottom_flag = 1; + } else { + p_Dec->refpic_info_b[k][j].bottom_flag = 0; + } + p_Dec->refpic_info_b[k][j].valid = 1; + } + + } + //!< check dpb list poc +#if 0 + { + RK_S32 cur_poc = p_Dec->p_Vid->dec_pic->poc; + if ((currSlice->slice_type % 5) != H264_I_SLICE + && (currSlice->slice_type % 5) != H264_SI_SLICE) { + if (cur_poc < min_poc) { + p_Dec->errctx.cur_err_flag |= 1; + H264D_DBG(H264D_DBG_DPB_REF_ERR, "[DPB_REF_ERR] min_poc=%d, dec_poc=%d", min_poc, cur_poc); + } + } + if (currSlice->slice_type % 5 == H264_B_SLICE) { + if (cur_poc > max_poc) { + p_Dec->errctx.cur_err_flag |= 1; + H264D_DBG(H264D_DBG_DPB_REF_ERR, "[DPB_REF_ERR] max_poc=%d, dec_poc=%d", max_poc, cur_poc); + } + } + } +#endif +__RETURN: + return MPP_OK; +} + +extern MPP_RET h264d_reset(void *decoder); + +static MPP_RET check_refer_dpb_buf_slots(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + RK_S32 slot_idx = 0; + RK_U32 dpb_used = 0; + H264_DecCtx_t *p_Dec = NULL; + H264_DpbMark_t *p_mark = NULL; + + p_Dec = currSlice->p_Dec; + //!< set buf slot flag + for (i = 0; i < MAX_DPB_SIZE; i++) { + if ((NULL != p_Dec->dpb_info[i].refpic) && (p_Dec->dpb_info[i].slot_index >= 0)) { + p_Dec->in_task->refer[i] = p_Dec->dpb_info[i].slot_index; + mpp_buf_slot_set_flag(p_Dec->frame_slots, p_Dec->dpb_info[i].slot_index, SLOT_HAL_INPUT); + mpp_buf_slot_set_flag(p_Dec->frame_slots, p_Dec->dpb_info[i].slot_index, SLOT_CODEC_USE); + } else { + p_Dec->in_task->refer[i] = -1; + } + } + //!< dpb info + if (h264d_debug & H264D_DBG_DPB_INFO) { + H264D_DBG(H264D_DBG_DPB_INFO, "[DPB_INFO] cur_slot_idx=%d", p_Dec->in_task->output); + for (i = 0; i < MAX_DPB_SIZE; i++) { + slot_idx = p_Dec->in_task->refer[i]; + if (slot_idx >= 0) { + H264D_DBG(H264D_DBG_DPB_INFO, "[DPB_INFO] ref_slot_idx[%d]=%d", i, slot_idx); + } + } + } + //!< mark info + for (i = 0; i < MAX_MARK_SIZE; i++) { + p_mark = &p_Dec->dpb_mark[i]; + if (p_mark->out_flag && (p_mark->slot_idx >= 0)) { + dpb_used++; + if (h264d_debug & H264D_DBG_DPB_INFO) { + RK_S32 fd = 0; + MppFrame mframe = NULL; + MppBuffer mbuffer = NULL; + mpp_buf_slot_get_prop(p_Dec->frame_slots, p_mark->slot_idx, SLOT_FRAME_PTR, &mframe); + mbuffer = mframe ? mpp_frame_get_buffer(mframe) : NULL; + fd = mbuffer ? mpp_buffer_get_fd(mbuffer) : 0xFF; + H264D_DBG(H264D_DBG_DPB_INFO, "[DPB_MARK_INFO] slot_idx=%d, top_used=%d, bot_used=%d, out_flag=%d, fd=0x%02x, poc=%d, view_id=%d", + p_mark->slot_idx, p_mark->top_used, p_mark->bot_used, + p_mark->out_flag, fd, p_mark->pic->poc, p_mark->pic->layer_id); + } + } + } + H264D_DBG(H264D_DBG_DPB_INFO, "[DPB_MARK_INFO] ---------- cur_slot=%d --------------------", p_Dec->in_task->output); + + if (dpb_used > MPP_MIN(p_Dec->p_Vid->dpb_size[0] + p_Dec->p_Vid->dpb_size[1], 16) + 2) { + H264D_ERR("[h264d_reset_error]"); + h264d_reset((void *)p_Dec); + return MPP_NOK; + } + + return MPP_OK; +} + + +/*! +*********************************************************************** +* \brief +* flush dpb buffer slot +*********************************************************************** +*/ +//extern "C" +void flush_dpb_buf_slot(H264_DecCtx_t *p_Dec) +{ + RK_U32 i = 0; + H264_DpbMark_t *p_mark = NULL; + + for (i = 0; i < MAX_MARK_SIZE; i++) { + p_mark = &p_Dec->dpb_mark[i]; + if (p_mark && p_mark->out_flag && (p_mark->slot_idx >= 0)) { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(p_Dec->frame_slots, p_mark->slot_idx, SLOT_FRAME_PTR, &mframe); + if (mframe) { + H264D_DBG(H264D_DBG_SLOT_FLUSH, "[DPB_BUF_FLUSH] slot_idx=%d, top_used=%d, bot_used=%d", + p_mark->slot_idx, p_mark->top_used, p_mark->bot_used); + mpp_frame_set_discard(mframe, 1); + mpp_buf_slot_set_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p_Dec->frame_slots, p_mark->slot_idx, QUEUE_DISPLAY); + mpp_buf_slot_clr_flag(p_Dec->frame_slots, p_mark->slot_idx, SLOT_CODEC_USE); + p_Dec->last_frame_slot_idx = p_mark->slot_idx; + } + } + reset_dpb_mark(p_mark); + } +} + +/*! +*********************************************************************** +* \brief +* reset dpb mark +*********************************************************************** +*/ +//extern "C" +MPP_RET reset_dpb_mark(H264_DpbMark_t *p_mark) +{ + if (p_mark) { + p_mark->top_used = 0; + p_mark->bot_used = 0; + p_mark->out_flag = 0; + p_mark->slot_idx = -1; + p_mark->pic = NULL; + p_mark->mframe = NULL; + } + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* init picture +*********************************************************************** +*/ +//extern "C" +MPP_RET init_picture(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_DecCtx_t *p_Dec = currSlice->p_Vid->p_Dec; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264dErrCtx_t *p_err = &p_Dec->errctx; + + //!< discard stream before I_SLICE + if (!p_err->i_slice_no && p_Vid->recovery.valid_flag && p_Vid->recovery.first_frm_valid && + p_Vid->recovery.first_frm_id == currSlice->frame_num) { + p_err->i_slice_no += (!currSlice->layer_id) ? 1 : 0; + } else { + p_err->i_slice_no += ((!currSlice->layer_id) && (H264_I_SLICE == currSlice->slice_type)) ? 1 : 0; + } + + if (!p_err->i_slice_no) { + H264D_WARNNING("[Discard] Discard slice before I Slice. \n"); + ret = MPP_NOK; + goto __FAILED; + } + FUN_CHECK(ret = alloc_decpic(currSlice)); + if (((p_err->i_slice_no < 2) && (!currSlice->layer_id) && (H264_I_SLICE == currSlice->slice_type)) || + currSlice->idr_flag) { + p_err->first_iframe_poc = p_Vid->dec_pic->poc; //!< recoder first i frame poc + p_err->first_iframe_is_output = 0; + } + //!< idr_memory_management MVC_layer, idr_flag==1 + if (currSlice->layer_id && !currSlice->svc_extension_flag && !currSlice->mvcExt.non_idr_flag) { + ASSERT(currSlice->layer_id == 1); + FUN_CHECK(ret = idr_memory_management(p_Vid->p_Dpb_layer[currSlice->layer_id], p_Vid->dec_pic)); + } + + // if cur pic i frame poc & frame_num <= last pic, flush dpb. + if (p_Vid->last_pic != NULL && p_Vid->dec_pic->poc != 0) { + if (p_Vid->last_pic->frame_num >= p_Vid->dec_pic->frame_num + && p_Vid->last_pic->poc >= p_Vid->dec_pic->poc + && p_Vid->dec_pic->slice_type == H264_I_SLICE + && p_Vid->dec_pic->structure == 3) { + if (currSlice->layer_id == 0) { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0], 1)); + } else { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1], 2)); + } + } + } + update_ref_list(p_Vid->p_Dpb_layer[currSlice->layer_id]); + update_ltref_list(p_Vid->p_Dpb_layer[currSlice->layer_id]); + update_pic_num(currSlice); + //!< reorder + if (!currSlice->idr_flag || currSlice->layer_id) { + FUN_CHECK(ret = init_lists_p_slice_mvc(currSlice)); + FUN_CHECK(ret = init_lists_b_slice_mvc(currSlice)); + } + prepare_init_dpb_info(currSlice); + prepare_init_ref_info(currSlice); + + FUN_CHECK(ret = check_refer_dpb_buf_slots(currSlice)); + check_refer_picture_lists(currSlice); + { + H264dDxvaCtx_t *dxva_ctx = p_Dec->dxva_ctx; + + fill_picparams(currSlice->p_Vid, &dxva_ctx->pp); + if (dxva_ctx->pp.scaleing_list_enable_flag) { + prepare_init_scanlist(currSlice); + fill_scanlist(currSlice->p_Vid, &dxva_ctx->qm); + } + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* update dpb +*********************************************************************** +*/ +//extern "C" +MPP_RET update_dpb(H264_DecCtx_t *p_Dec) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + p_Dec->p_Vid->exit_picture_flag = 1; + p_Dec->p_Vid->have_outpicture_flag = 1; + ret = exit_picture(p_Dec->p_Vid, &p_Dec->p_Vid->dec_pic); + + p_Dec->p_Vid->iNumOfSlicesDecoded = 0; + p_Dec->p_Vid->exit_picture_flag = 0; + + return ret; +} + diff --git a/mpp/codec/dec/h264/h264d_init.h b/mpp/codec/dec/h264/h264d_init.h index 54f856f2a..efbd6d4de 100644 --- a/mpp/codec/dec/h264/h264d_init.h +++ b/mpp/codec/dec/h264/h264d_init.h @@ -1,39 +1,42 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef _H264D_INIT_H_ -#define _H264D_INIT_H_ - - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_global.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET init_picture (H264_SLICE_t *currSlice); - -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of _RKV_H264_DECODER_INIT_H_ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_INIT_H +#define H264D_INIT_H + + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET update_dpb (H264_DecCtx_t *p_Dec); +MPP_RET init_picture (H264_SLICE_t *currSlice); +MPP_RET reset_dpb_mark(H264_DpbMark_t *p_mark); +void flush_dpb_buf_slot(H264_DecCtx_t *p_Dec); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* H264D_INIT_H */ + diff --git a/mpp/codec/dec/h264/h264d_log.c b/mpp/codec/dec/h264/h264d_log.c deleted file mode 100644 index 4016de23f..000000000 --- a/mpp/codec/dec/h264/h264d_log.c +++ /dev/null @@ -1,218 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include -#include - -#include "mpp_log.h" -#include "mpp_env.h" -#include "mpp_mem.h" -#include "mpp_common.h" - -#include "h264d_log.h" - -#define MODULE_TAG "" - -#define LOG_BUF_SIZE 512 - -RK_U32 g_nalu_cnt = 0; - -const LogEnvStr_t logenv_name = { - "h264d_log_help", - "h264d_log_show", - "h264d_log_ctrl", - "h264d_log_level", - "h264d_log_outpath", - "h264d_log_cmppath", - "h264d_log_decframe", - "h264d_log_begframe", - "h264d_log_endframe", -}; - -const char *loglevel_name[LOG_LEVEL_MAX] = { - "SILENT ", - "FATAL ", - "ERROR ", - "WARNNING", - "INFO ", - "TRACE ", -}; - -const char *logctrl_name[LOG_MAX] = { - "DEBUG_EN ", - "FPGA_MODE ", - "LOG_PRINT ", - "LOG_WRITE ", - "RUN_PAESE ", - "RUN_HAL ", - "READ_NALU ", - "READ_SPS ", - "READ_SUBSPS ", - "READ_PPS ", - "READ_SLICE ", - "WRITE_SPSPPS ", - "WRITE_RPS ", - "WRITE_SCANLIST", - "WRITE_STEAM ", - "WRITE_REG ", -}; - -/*! -*********************************************************************** -* \brief -* get log env -*********************************************************************** -*/ - -MPP_RET get_logenv(LogEnv_t *env) -{ - //!< read env - mpp_env_get_u32(logenv_name.help, &env->help, 0); - mpp_env_get_u32(logenv_name.show, &env->show, 0); - mpp_env_get_u32(logenv_name.ctrl, &env->ctrl, 0); - mpp_env_get_u32(logenv_name.level, &env->level, 0); - mpp_env_get_u32(logenv_name.decframe, &env->decframe, 0); - mpp_env_get_u32(logenv_name.begframe, &env->begframe, 0); - mpp_env_get_u32(logenv_name.endframe, &env->endframe, 0); - mpp_env_get_str(logenv_name.outpath, &env->outpath, NULL); - - return MPP_OK; -} - -/*! -*********************************************************************** -* \brief -* print env help -*********************************************************************** -*/ -void print_env_help(LogEnv_t *env) -{ - RK_U8 i = 0; - (void)env; - - mpp_log("--------------- h264d help -------------------- \n"); - mpp_log("h264d_log_help :[num] (0/1) show help content \n"); - mpp_log("h264d_log_show :[num] (0/1) show current log setting \n"); - mpp_log("h264d_log_outpath :[str] \n"); - mpp_log("h264d_log_decframe :[num] \n"); - mpp_log("h264d_log_begframe :[num] \n"); - mpp_log("h264d_log_endframe :[num] \n"); - mpp_log("h264d_log_level :[num] \n"); - for (i = 0; i < LOG_LEVEL_MAX; i++) { - mpp_log(" (%2d) -- %s \n", i, loglevel_name[i]); - } - mpp_log("h264d_log_ctrl :[32bit] \n"); - for (i = 0; i < LOG_MAX; i++) { - mpp_log(" (%2d)bit -- %s \n", i, logctrl_name[i]); - } - mpp_log("------------------------------------------------- \n"); -} -/*! -*********************************************************************** -* \brief -* show env flags -*********************************************************************** -*/ -void show_env_flags(LogEnv_t *env) -{ - RK_U8 i = 0; - mpp_log("------------- h264d debug setting ------------- \n"); - mpp_log("outputpath : %s \n", env->outpath); - mpp_log("DecodeFrame : %d \n", env->decframe); - mpp_log("LogBeginFrame : %d \n", env->begframe); - mpp_log("LogEndFrame : %d \n", env->endframe); - mpp_log("LogLevel : %s \n", loglevel_name[env->level]); - for (i = 0; i < LOG_MAX; i++) { - mpp_log("%s: %d (%d)\n", logctrl_name[i], GetBitVal(env->ctrl, i), i); - } - mpp_log("------------------------------------------------- \n"); -} -/*! -*********************************************************************** -* \brief -* explain log ctrl flag -*********************************************************************** -*/ -MPP_RET explain_ctrl_flag(RK_U32 ctrl_val, LogFlag_t *pflag) -{ - pflag->print_en = GetBitVal(ctrl_val, LOG_PRINT ); - pflag->write_en = GetBitVal(ctrl_val, LOG_WRITE ); - pflag->debug_en = GetBitVal(ctrl_val, LOG_DEBUG ) - || GetBitVal(ctrl_val, LOG_READ_NALU ) - || GetBitVal(ctrl_val, LOG_READ_SPS ) - || GetBitVal(ctrl_val, LOG_READ_SUBSPS ) - || GetBitVal(ctrl_val, LOG_READ_PPS ) - || GetBitVal(ctrl_val, LOG_READ_SLICE ) - || GetBitVal(ctrl_val, LOG_WRITE_SPSPPS ) - || GetBitVal(ctrl_val, LOG_WRITE_RPS ) - || GetBitVal(ctrl_val, LOG_WRITE_SCANLIST) - || GetBitVal(ctrl_val, LOG_WRITE_STEAM ) - || GetBitVal(ctrl_val, LOG_WRITE_REG ); - - return MPP_OK; -} -/*! -*********************************************************************** -* \brief -* set log outpath -*********************************************************************** -*/ -void set_log_outpath(LogEnv_t *env) -{ - if (NULL == env->outpath) { - mpp_env_set_str(logenv_name.outpath, "./h264d_dat" ); - mpp_env_get_str(logenv_name.outpath, &env->outpath, NULL); - } - if (access(env->outpath, 0)) { - if (mkdir(env->outpath)) { - mpp_log("ERROR: create folder,%s \n", env->outpath); - } - } -} -/*! -*********************************************************************** -* \brief -* write log function -*********************************************************************** -*/ -void writelog(LogCtx_t *ctx, char *filename, RK_U32 line, char *loglevel, const char *msg, ...) -{ -#if __DEBUG_EN - - va_list argptr; - char argbuf[LOG_BUF_SIZE] = { 0 }; - char *pfn = NULL, *pfn0 = NULL, *pfn1 = NULL; - - va_start(argptr, msg); - vsnprintf(argbuf, sizeof(argbuf), msg, argptr); - - pfn0 = strrchr(filename, '/'); - pfn1 = strrchr(filename, '\\'); - pfn = pfn0 ? (pfn0 + 1) : (pfn1 ? (pfn1 + 1) : filename); - if (ctx->flag->print_en) { - mpp_log("[TAG=%s] file: %s:%d, [ %s ], %s \n", ctx->tag, pfn, line, loglevel, argbuf); - } - if (ctx->fp && ctx->flag->write_en) { - fprintf(ctx->fp, "%s \n", argbuf); - //fprintf(ctx->fp, "[ TAG = %s ], file: %s, line: %d, [ %s ], %s \n", ctx->tag, pfn, line, loglevel, argbuf); - fflush(ctx->fp); - } - va_end(argptr); - -#endif -} diff --git a/mpp/codec/dec/h264/h264d_parse.c b/mpp/codec/dec/h264/h264d_parse.c index 564cc70cc..ff19e013b 100644 --- a/mpp/codec/dec/h264/h264d_parse.c +++ b/mpp/codec/dec/h264/h264d_parse.c @@ -1,364 +1,1096 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include -#include - -#include "mpp_mem.h" -#include "mpp_packet.h" -#include "mpp_packet_impl.h" -#include "hal_task.h" - -#include "h264d_parse.h" -#include "h264d_slice.h" -#include "h264d_sps.h" -#include "h264d_pps.h" -#include "h264d_sei.h" -#include "h264d_init.h" -#include "h264d_fill.h" - -#define MODULE_TAG "h264d_parse" - -static void reset_slice(H264dVideoCtx_t *p_Vid) -{ - RK_U32 i = 0, j = 0; - H264_SLICE_t *currSlice = &p_Vid->p_Cur->slice; - FunctionIn(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); - memset(currSlice, 0, sizeof(H264_SLICE_t)); - //-- re-init parameters - currSlice->view_id = -1; - currSlice->p_Vid = p_Vid; - currSlice->p_Dec = p_Vid->p_Dec; - currSlice->p_Cur = p_Vid->p_Cur; - currSlice->p_Inp = p_Vid->p_Inp; - currSlice->logctx = &p_Vid->p_Dec->logctx; - - //--- reset listP listB - for (i = 0; i < 2; i++) { - currSlice->listP[i] = p_Vid->p_Cur->listP[i]; - currSlice->listB[i] = p_Vid->p_Cur->listB[i]; - for (j = 0; j < MAX_LIST_SIZE; j++) { - currSlice->listP[i][j] = NULL; - currSlice->listB[i][j] = NULL; - } - currSlice->listXsizeP[i] = 0; - currSlice->listXsizeB[i] = 0; - } - FunctionOut(p_Vid->p_Dec->logctx.parr[RUN_PARSE]); -} - -static MPP_RET realloc_curstrearm_buffer(H264dCurStream_t *p_strm) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - p_strm->buf = mpp_realloc(p_strm->buf, RK_U8, p_strm->max_size + NALU_BUF_ADD_SIZE); - MEM_CHECK(ret, p_strm->buf); - p_strm->max_size += NALU_BUF_ADD_SIZE; - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static void reset_nalu(H264_Nalu_t*p_nal, H264dCurStream_t *p_strm) -{ - if (p_strm->endcode_found) { - p_strm->startcode_found = p_strm->endcode_found; - memset(p_nal, 0, sizeof(H264_Nalu_t)); - p_strm->endcode_found = 0; - } - p_nal->sodb_buf = p_strm->buf; -} - -static void find_prefix_code(RK_U8 *p_data, H264dCurStream_t *p_strm) -{ - p_strm->prefixdata[0] = p_strm->prefixdata[1]; - p_strm->prefixdata[1] = p_strm->prefixdata[2]; - p_strm->prefixdata[2] = *p_data; - - if (p_strm->prefixdata[0] == 0x00 - && p_strm->prefixdata[1] == 0x00 - && p_strm->prefixdata[2] == 0x01) { - if (p_strm->startcode_found) { - p_strm->endcode_found = 1; - } else { - p_strm->startcode_found = 1; - } - } -} - -static MPP_RET read_nalu(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - RK_U8 *p_curdata = NULL; - H264dLogCtx_t *logctx = currSlice->logctx; - H264_DecCtx_t *p_Dec = currSlice->p_Dec; - H264dCurCtx_t *p_Cur = currSlice->p_Cur; - H264dInputCtx_t *p_Inp = currSlice->p_Inp; - - FunctionIn(logctx->parr[RUN_PARSE]); - reset_nalu(&p_Cur->nalu, &p_Cur->strm); - while ((*p_Inp->in_size) > 0) { - p_curdata = &p_Inp->in_buf[p_Cur->strm.offset++]; - (*p_Inp->in_size) -= 1; - - if (p_Cur->strm.startcode_found) { - if (p_Cur->nalu.sodb_len >= p_Cur->strm.max_size) { - FUN_CHECK(ret = realloc_curstrearm_buffer(&p_Cur->strm)); - p_Cur->nalu.sodb_buf = p_Cur->strm.buf; - } - p_Cur->nalu.sodb_buf[p_Cur->nalu.sodb_len++] = *p_curdata; - } - find_prefix_code(p_curdata, &p_Cur->strm); - if (p_Cur->strm.endcode_found) { - p_Cur->nalu.sodb_len -= START_PREFIX_3BYTE; - while (p_Cur->nalu.sodb_buf[p_Cur->nalu.sodb_len - 1] == 0x00) { //!< find non-zeros byte - p_Cur->nalu.sodb_len--; - } - p_Dec->nalu_ret = EndOfNalu; - break; - } - } - if (!(*p_Inp->in_size)) { //!< check input - p_Cur->strm.offset = 0; - p_Cur->strm.endcode_found = (p_Inp->is_eos && p_Cur->nalu.sodb_len) ? 1 : p_Cur->strm.endcode_found; - p_Dec->nalu_ret = p_Inp->is_eos ? (p_Cur->nalu.sodb_len ? EndOfNalu : EndofStream) : HaveNoStream; - } - - FunctionIn(logctx->parr[RUN_PARSE]); - - return ret = MPP_OK; -__FAILED: - - return ret; -} - -static MPP_RET parser_nalu_header(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - H264dLogCtx_t *logctx = currSlice->logctx; - H264dCurCtx_t *p_Cur = currSlice->p_Cur; - BitReadCtx_t *p_bitctx = &p_Cur->bitctx; - H264_Nalu_t *cur_nal = &p_Cur->nalu; - - FunctionIn(logctx->parr[RUN_PARSE]); - set_bitread_ctx(p_bitctx, cur_nal->sodb_buf, cur_nal->sodb_len); - set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_NALU]); - WRITE_LOG(p_bitctx, "================== NAL begin ==================="); - READ_BITS(ret, p_bitctx, 1, &cur_nal->forbidden_bit, "forbidden_bit"); - ASSERT(cur_nal->forbidden_bit == 0); - READ_BITS(ret, p_bitctx, 2, (RK_S32 *)&cur_nal->nal_reference_idc, "nal_ref_idc"); - READ_BITS(ret, p_bitctx, 5, (RK_S32 *)&cur_nal->nal_unit_type, "nal_unit_type"); - //if (g_nalu_cnt == 321) { - // g_nalu_cnt = g_nalu_cnt; - //} - cur_nal->ualu_header_bytes = 1; - currSlice->svc_extension_flag = -1; //!< initialize to -1 - if ((cur_nal->nal_unit_type == NALU_TYPE_PREFIX) || (cur_nal->nal_unit_type == NALU_TYPE_SLC_EXT)) { - READ_ONEBIT(ret, p_bitctx, &currSlice->svc_extension_flag, "svc_extension_flag"); - if (currSlice->svc_extension_flag) { - //FPRINT(logctx->parr[LOG_READ_NALU]->fp, "g_nalu_cnt=%d, nalu_type=%d, len=%d \n", g_nalu_cnt++, cur_nal->nal_unit_type, cur_nal->sodb_len); - currSlice->mvcExt.valid = 0; - LogInfo(logctx->parr[RUN_PARSE], "svc_extension is not supported."); - goto __FAILED; - } else { //!< MVC - currSlice->mvcExt.valid = 1; - READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.non_idr_flag, "nalu_type"); - READ_BITS(ret, p_bitctx, 6, &currSlice->mvcExt.priority_id, "priority_id"); - READ_BITS(ret, p_bitctx, 10, &currSlice->mvcExt.view_id, "view_id"); - READ_BITS(ret, p_bitctx, 3, &currSlice->mvcExt.temporal_id, "temporal_id"); - READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.anchor_pic_flag, "anchor_pic_flag"); - READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.inter_view_flag, "inter_view_flag"); - READ_ONEBIT(ret, p_bitctx, &currSlice->mvcExt.reserved_one_bit, "reserved_one_bit"); - ASSERT(currSlice->mvcExt.reserved_one_bit == 1); - currSlice->mvcExt.iPrefixNALU = (cur_nal->nal_unit_type == NALU_TYPE_PREFIX) ? 1 : 0; - //!< combine NALU_TYPE_SLC_EXT into NALU_TYPE_SLICE - if (cur_nal->nal_unit_type == NALU_TYPE_SLC_EXT) { - cur_nal->nal_unit_type = NALU_TYPE_SLICE; - } - //FPRINT(logctx->parr[LOG_READ_NALU]->fp, "g_nalu_cnt=%d, nalu_type=%d, len=%d \n", g_nalu_cnt++, cur_nal->nal_unit_type, cur_nal->sodb_len); - } - cur_nal->ualu_header_bytes += 3; - } else { - //FPRINT(logctx->parr[LOG_READ_NALU]->fp, "g_nalu_cnt=%d, nalu_type=%d, len=%d \n", g_nalu_cnt++, cur_nal->nal_unit_type, cur_nal->sodb_len); - } - set_bitread_ctx(p_bitctx, (cur_nal->sodb_buf + cur_nal->ualu_header_bytes), (cur_nal->sodb_len - cur_nal->ualu_header_bytes)); // reset - - FunctionOut(logctx->parr[RUN_PARSE]); - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static MPP_RET parser_nalu(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - LogCtx_t *runlog = currSlice->logctx->parr[RUN_PARSE]; - FunctionIn(runlog); - FUN_CHECK(ret = parser_nalu_header(currSlice)); - //!< nalu_parse - switch (currSlice->p_Cur->nalu.nal_unit_type) { - case NALU_TYPE_SLICE: - case NALU_TYPE_IDR: - FUN_CHECK(ret = process_slice(currSlice)); - if (currSlice->is_new_picture_flag) { - currSlice->p_Dec->nalu_ret = StartOfPicture; - } else { - currSlice->p_Dec->nalu_ret = StartOfSlice; - } - LogTrace(runlog, "nalu_type=SLICE."); - break; - case NALU_TYPE_SPS: - FUN_CHECK(ret = process_sps(currSlice)); - currSlice->p_Dec->nalu_ret = NALU_SPS; - LogTrace(runlog, "nalu_type=SPS"); - break; - case NALU_TYPE_PPS: - FUN_CHECK(ret = process_pps(currSlice)); - currSlice->p_Dec->nalu_ret = NALU_PPS; - LogTrace(runlog, "nalu_type=PPS"); - break; - case NALU_TYPE_SUB_SPS: - FUN_CHECK(ret = process_subsps(currSlice)); - currSlice->p_Dec->nalu_ret = NALU_SubSPS; - LogTrace(runlog, "nalu_type=SUB_SPS"); - break; - case NALU_TYPE_SEI: - FUN_CHECK(ret = process_sei(currSlice)); - LogTrace(runlog, "nalu_type=SEI"); - currSlice->p_Dec->nalu_ret = NALU_SEI; - break; - case NALU_TYPE_SLC_EXT: - LogTrace(runlog, "Found NALU_TYPE_SLC_EXT."); - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - case NALU_TYPE_PREFIX: - LogTrace(runlog, "Found NALU_TYPE_PREFIX."); - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - case NALU_TYPE_AUD: - LogTrace(runlog, "Found NALU_TYPE_AUD."); - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - case NALU_TYPE_EOSEQ: - LogTrace(runlog, "Found NALU_TYPE_EOSEQ."); - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - case NALU_TYPE_EOSTREAM: - LogTrace(runlog, "Found NALU_TYPE_EOSTREAM."); - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - case NALU_TYPE_FILL: - LogTrace(runlog, "Found NALU_TYPE_FILL."); - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - case NALU_TYPE_VDRD: - LogTrace(runlog, "Found NALU_TYPE_VDRD."); - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - case NALU_TYPE_DPA: - case NALU_TYPE_DPB: - case NALU_TYPE_DPC: - LogError(runlog, "Found NALU_TYPE_DPA DPB DPC, and not supported."); - currSlice->p_Dec->nalu_ret = NaluNotSupport; - break; - default: - currSlice->p_Dec->nalu_ret = SkipNALU; - break; - } - FunctionIn(runlog); - - return ret = MPP_OK; -__FAILED: - - return ret; -} - -/*! -*********************************************************************** -* \brief -* loop function for parser -*********************************************************************** -*/ -MPP_RET parse_loop(H264_DecCtx_t *p_Dec) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - RK_U32 while_loop_flag = 1; - - - FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); - //!< ==== parse loop ==== - while (while_loop_flag) { - switch (p_Dec->next_state) { - case SliceSTATE_ResetSlice: - reset_slice(p_Dec->p_Vid); - p_Dec->next_state = SliceSTATE_ReadNalu; - break; - case SliceSTATE_ReadNalu: - (ret = read_nalu(&p_Dec->p_Cur->slice)); - if (p_Dec->nalu_ret == EndOfNalu) { - p_Dec->next_state = SliceSTATE_ParseNalu; - } else if (p_Dec->nalu_ret == EndofStream) { - p_Dec->next_state = SliceSTATE_RegisterOneFrame; - } else if (p_Dec->nalu_ret == HaveNoStream) { - while_loop_flag = 0; - } - break; - case SliceSTATE_ParseNalu: - (ret = parser_nalu(&p_Dec->p_Cur->slice)); - if (p_Dec->nalu_ret == StartOfSlice) { - p_Dec->next_state = SliceSTATE_GetSliceData; - } else if (p_Dec->nalu_ret == StartOfPicture) { - if (p_Dec->first_frame_flag) { - p_Dec->next_state = SliceSTATE_InitPicture; - p_Dec->first_frame_flag = 0; - } else { - p_Dec->next_state = SliceSTATE_RegisterOneFrame; - } - } else { - p_Dec->next_state = SliceSTATE_ReadNalu; - } - break; - case SliceSTATE_InitPicture: - (ret = init_picture(&p_Dec->p_Cur->slice)); - p_Dec->next_state = SliceSTATE_GetSliceData; - break; - case SliceSTATE_GetSliceData: - (ret = fill_slice(&p_Dec->p_Cur->slice, p_Dec->dxva_ctx)); - p_Dec->p_Vid->iNumOfSlicesDecoded++; - p_Dec->next_state = SliceSTATE_ResetSlice; - break; - case SliceSTATE_RegisterOneFrame: - commit_buffer(p_Dec->dxva_ctx); - while_loop_flag = 0; - p_Dec->parser_end_flag = 1; - p_Dec->next_state = SliceSTATE_InitPicture; - break; - default: - ret = MPP_NOK; - goto __FAILED; - } - } - FunctionIn(p_Dec->logctx.parr[RUN_PARSE]); -//__RETURN: - return ret = MPP_OK; -__FAILED: - - return ret; -} - - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_parse" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_packet_impl.h" +#include "hal_dec_task.h" + +#include "h264d_global.h" +#include "h264d_parse.h" +#include "h264d_slice.h" +#include "h264d_sps.h" +#include "h264d_pps.h" +#include "h264d_sei.h" +#include "h264d_init.h" +#include "h264d_fill.h" +#include "rk_hdr_meta_com.h" + +#define HEAD_SYNTAX_MAX_SIZE (12800) +#define NALU_TYPE_NORMAL_LENGTH (1) +#define NALU_TYPE_EXT_LENGTH (5) + +static const RK_U8 g_start_precode[3] = {0, 0, 1}; + +typedef struct h264d_nalu_head_t { + RK_U16 is_frame_end; + RK_U16 nalu_type; + RK_U32 sodb_len; +} H264dNaluHead_t; + + +static RK_U16 U16_AT(const RK_U8 *ptr) +{ + return ptr[0] << 8 | ptr[1]; +} + +static RK_U32 U32_AT(const RK_U8 *ptr) +{ + return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; +} + +static RK_U32 parse_nal_size(RK_U8 nal_size, RK_U8 *data) +{ + switch (nal_size) { + case 1: + return *data; + case 2: + return U16_AT(data); + case 3: + return ((RK_U64)data[0] << 16) | U16_AT(&data[1]); + case 4: + return U32_AT(data); + } + return 0; +} + +static void reset_slice(H264dVideoCtx_t *p_Vid) +{ + RK_U32 i = 0, j = 0; + H264_SLICE_t *currSlice = &p_Vid->p_Cur->slice; + + memset(currSlice, 0, sizeof(H264_SLICE_t)); + //-- re-init parameters + currSlice->view_id = -1; + currSlice->p_Vid = p_Vid; + currSlice->p_Dec = p_Vid->p_Dec; + currSlice->p_Cur = p_Vid->p_Cur; + currSlice->p_Inp = p_Vid->p_Inp; + currSlice->active_sps = p_Vid->active_sps; + currSlice->active_pps = p_Vid->active_pps; + currSlice->active_subsps = p_Vid->active_subsps; + //--- reset listP listB + for (i = 0; i < MAX_NUM_DPB_LAYERS; i++) { + currSlice->listP[i] = p_Vid->p_Cur->listP[i]; + currSlice->listB[i] = p_Vid->p_Cur->listB[i]; + for (j = 0; j < MAX_LIST_SIZE; j++) { + currSlice->listP[i][j] = NULL; + currSlice->listB[i][j] = NULL; + } + currSlice->listXsizeP[i] = 0; + currSlice->listXsizeB[i] = 0; + } + reset_cur_slice(p_Vid->p_Cur, currSlice); +} + +static MPP_RET realloc_buffer(RK_U8 **buf, RK_U32 *max_size, RK_U32 add_size) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + if ((*buf) == NULL) { + H264D_ERR("[realloc_buffer] pointer is null, %p \n", (*buf)); + ret = MPP_ERR_MALLOC; + goto __FAILED; + } + + add_size = MPP_ALIGN(add_size, 16); + + (*buf) = mpp_realloc((*buf), RK_U8, ((*max_size) + add_size)); + if ((*buf) == NULL) { + H264D_ERR("[realloc_buffer] ERROR: max_size=%d, add_size=%d \n", (*max_size), add_size); + ret = MPP_ERR_MALLOC; + goto __FAILED; + } + (*max_size) += add_size; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static void reset_nalu(H264dCurStream_t *p_strm) +{ + if (p_strm->endcode_found) { + p_strm->startcode_found = p_strm->endcode_found; + p_strm->nalu_len = 0; + p_strm->nalu_type = H264_NALU_TYPE_NULL; + p_strm->endcode_found = 0; + } +} + +static void find_prefix_code(RK_U8 *p_data, H264dCurStream_t *p_strm) +{ + (void)p_data; + + if ((p_strm->prefixdata & 0x00FFFFFF) == 0x00000001) { + if (p_strm->startcode_found) { + p_strm->endcode_found = 1; + } else { + p_strm->startcode_found = 1; + } + } +} + +static MPP_RET parser_nalu_header(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + H264_Nalu_t *cur_nal = &p_Cur->nalu; + + mpp_set_bitread_ctx(p_bitctx, cur_nal->sodb_buf, cur_nal->sodb_len); + mpp_set_bitread_pseudo_code_type(p_bitctx, PSEUDO_CODE_H264_H265); + + READ_BITS(p_bitctx, 1, &cur_nal->forbidden_bit); + ASSERT(cur_nal->forbidden_bit == 0); + { + RK_S32 *ptmp = NULL; + ptmp = (RK_S32 *)&cur_nal->nal_reference_idc; + READ_BITS(p_bitctx, 2, ptmp); //!< nal_ref_idc + ptmp = (RK_S32 *)&cur_nal->nalu_type; + READ_BITS(p_bitctx, 5, ptmp); //!< nalu_type + } + cur_nal->ualu_header_bytes = 1; + currSlice->svc_extension_flag = -1; //!< initialize to -1 + if (cur_nal->nalu_type == H264_NALU_TYPE_PREFIX + || cur_nal->nalu_type == H264_NALU_TYPE_SLC_EXT) { + READ_ONEBIT(p_bitctx, &currSlice->svc_extension_flag); + if (currSlice->svc_extension_flag) { + currSlice->svcExt.valid = 1; + p_Cur->p_Dec->svc_valid = 1; + READ_ONEBIT(p_bitctx, &currSlice->svcExt.idr_flag); + READ_BITS(p_bitctx, 6, &currSlice->svcExt.priority_id); + READ_ONEBIT(p_bitctx, &currSlice->svcExt.no_inter_layer_pred_flag); + READ_BITS(p_bitctx, 3, &currSlice->svcExt.dependency_id); + READ_BITS(p_bitctx, 4, &currSlice->svcExt.quality_id); + READ_BITS(p_bitctx, 3, &currSlice->svcExt.temporal_id); + READ_ONEBIT(p_bitctx, &currSlice->svcExt.use_ref_base_pic_flag); + READ_ONEBIT(p_bitctx, &currSlice->svcExt.discardable_flag); + READ_ONEBIT(p_bitctx, &currSlice->svcExt.output_flag); + + ASSERT(currSlice->svcExt.no_inter_layer_pred_flag == 1); + ASSERT(currSlice->svcExt.dependency_id == 0); + ASSERT(currSlice->svcExt.quality_id == 0); + ASSERT(currSlice->svcExt.use_ref_base_pic_flag == 0); + } else { //!< MVC + currSlice->mvcExt.valid = 1; + p_Cur->p_Dec->mvc_valid = 1; + READ_ONEBIT(p_bitctx, &currSlice->mvcExt.non_idr_flag); + READ_BITS(p_bitctx, 6, &currSlice->mvcExt.priority_id); + READ_BITS(p_bitctx, 10, &currSlice->mvcExt.view_id); + READ_BITS(p_bitctx, 3, &currSlice->mvcExt.temporal_id); + READ_ONEBIT(p_bitctx, &currSlice->mvcExt.anchor_pic_flag); + READ_ONEBIT(p_bitctx, &currSlice->mvcExt.inter_view_flag); + READ_ONEBIT(p_bitctx, &currSlice->mvcExt.reserved_one_bit); + ASSERT(currSlice->mvcExt.reserved_one_bit == 1); + currSlice->mvcExt.iPrefixNALU = (cur_nal->nalu_type == H264_NALU_TYPE_PREFIX) ? 1 : 0; + //!< combine H264_NALU_TYPE_SLC_EXT into H264_NALU_TYPE_SLICE + if (cur_nal->nalu_type == H264_NALU_TYPE_SLC_EXT) { + cur_nal->nalu_type = H264_NALU_TYPE_SLICE; + } + } + cur_nal->ualu_header_bytes += 3; + } + /* Move forward the bitread offset */ + mpp_set_bitread_ctx(p_bitctx, + cur_nal->sodb_buf + cur_nal->ualu_header_bytes, + cur_nal->sodb_len - cur_nal->ualu_header_bytes); + mpp_set_bitread_pseudo_code_type(p_bitctx, PSEUDO_CODE_H264_H265); + p_Cur->p_Dec->nalu_ret = StartofNalu; + + return ret = MPP_OK; +__BITREAD_ERR: + p_Cur->p_Dec->nalu_ret = ReadNaluError; + return ret = p_bitctx->ret; +} + +static MPP_RET parser_one_nalu(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + FUN_CHECK(ret = parser_nalu_header(currSlice)); + + if (currSlice->p_Vid->deny_flag && + currSlice->p_Cur->nalu.nalu_type != H264_NALU_TYPE_SPS) { + currSlice->p_Dec->nalu_ret = NaluNotSupport; + return MPP_OK; + } + //!< check whether supprot mvc + if (currSlice->mvcExt.view_id && currSlice->mvcExt.valid && + !currSlice->p_Dec->cfg->base.enable_mvc) { + currSlice->p_Dec->nalu_ret = MvcDisAble; + return MPP_OK; + } + + //!< nalu_parse + switch (currSlice->p_Cur->nalu.nalu_type) { + case H264_NALU_TYPE_SLICE: + case H264_NALU_TYPE_IDR: + H264D_DBG(H264D_DBG_PARSE_NALU, "nalu_type=SLICE."); + FUN_CHECK(ret = process_slice(currSlice)); + currSlice->p_Dec->nalu_ret = StartOfPicture; + break; + case H264_NALU_TYPE_SPS: + H264D_DBG(H264D_DBG_PARSE_NALU, "nalu_type=SPS"); + FUN_CHECK(ret = process_sps(currSlice)); + currSlice->p_Dec->nalu_ret = NALU_SPS; + currSlice->p_Vid->deny_flag = 0; + break; + case H264_NALU_TYPE_PPS: + H264D_DBG(H264D_DBG_PARSE_NALU, "nalu_type=PPS"); + if (process_pps(currSlice) < 0) + H264D_WARNNING("Function error(%d).\n", __LINE__); + currSlice->p_Dec->nalu_ret = NALU_PPS; + break; + case H264_NALU_TYPE_SUB_SPS: + H264D_DBG(H264D_DBG_PARSE_NALU, "nalu_type=SUB_SPS"); + if (process_subsps(currSlice) < 0) + H264D_WARNNING("Function error(%d).\n", __LINE__); + currSlice->p_Dec->nalu_ret = NALU_SubSPS; + break; + case H264_NALU_TYPE_SEI: + H264D_DBG(H264D_DBG_PARSE_NALU, "nalu_type=SEI"); + ret = process_sei(currSlice); + currSlice->p_Dec->nalu_ret = NALU_SEI; + break; + case H264_NALU_TYPE_SLC_EXT: + H264D_DBG(H264D_DBG_PARSE_NALU, "Found H264_NALU_TYPE_SLC_EXT."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case H264_NALU_TYPE_PREFIX: + H264D_DBG(H264D_DBG_PARSE_NALU, "Found H264_NALU_TYPE_PREFIX."); + process_prefix(currSlice); + break; + case H264_NALU_TYPE_AUD: + H264D_DBG(H264D_DBG_PARSE_NALU, "Found H264_NALU_TYPE_AUD."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case H264_NALU_TYPE_EOSEQ: + H264D_DBG(H264D_DBG_PARSE_NALU, "Found H264_NALU_TYPE_EOSEQ."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case H264_NALU_TYPE_EOSTREAM: + H264D_DBG(H264D_DBG_PARSE_NALU, "Found H264_NALU_TYPE_EOSTREAM."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case H264_NALU_TYPE_FILL: + H264D_DBG(H264D_DBG_PARSE_NALU, "Found H264_NALU_TYPE_FILL."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case H264_NALU_TYPE_VDRD: + H264D_DBG(H264D_DBG_PARSE_NALU, "Found H264_NALU_TYPE_VDRD."); + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + case H264_NALU_TYPE_DPA: + case H264_NALU_TYPE_DPB: + case H264_NALU_TYPE_DPC: + H264D_DBG(H264D_DBG_PARSE_NALU, + "Found H264_NALU_TYPE_DPA DPB DPC, and not supported."); + currSlice->p_Dec->nalu_ret = NaluNotSupport; + break; + default: + currSlice->p_Dec->nalu_ret = SkipNALU; + break; + } + + return ret = MPP_OK; +__FAILED: + H264D_DBG(H264D_DBG_PARSE_NALU, "parser_one_nalu error."); + currSlice->p_Dec->nalu_ret = ReadNaluError; + return ret; +} + +static MPP_RET add_empty_nalu(H264dCurStream_t *p_strm) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U8 *p_des = NULL; + RK_U32 add_size = sizeof(H264dNaluHead_t); + + if ((p_strm->head_offset + add_size) >= p_strm->head_max_size) { + FUN_CHECK(ret = realloc_buffer(&p_strm->head_buf, &p_strm->head_max_size, HEAD_BUF_ADD_SIZE)); + } + p_des = &p_strm->head_buf[p_strm->head_offset]; + ((H264dNaluHead_t *)p_des)->is_frame_end = 1; + ((H264dNaluHead_t *)p_des)->nalu_type = 0; + ((H264dNaluHead_t *)p_des)->sodb_len = 0; + p_strm->head_offset += add_size; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +void mpp_h264d_fill_dynamic_meta(H264dCurCtx_t *p_Cur, const RK_U8 *data, RK_U32 size, RK_U32 hdr_fmt) +{ + MppFrameHdrDynamicMeta *hdr_dynamic_meta = p_Cur->hdr_dynamic_meta; + + if (hdr_fmt == DLBY) + size += 4; + + if (hdr_dynamic_meta && (hdr_dynamic_meta->size < size)) { + mpp_free(hdr_dynamic_meta); + hdr_dynamic_meta = NULL; + } + + if (!hdr_dynamic_meta) { + hdr_dynamic_meta = mpp_calloc_size(MppFrameHdrDynamicMeta, + sizeof(MppFrameHdrDynamicMeta) + size); + if (!hdr_dynamic_meta) { + mpp_err_f("malloc hdr dynamic data failed!\n"); + return; + } + } + if (size && data) { + if (hdr_fmt == DLBY) { + RK_U8 start_code[4] = {0, 0, 0, 1}; + + memcpy((RK_U8*)hdr_dynamic_meta->data, start_code, 4); + memcpy((RK_U8*)hdr_dynamic_meta->data + 4, (RK_U8*)data, size - 4); + } else + memcpy((RK_U8*)hdr_dynamic_meta->data, (RK_U8*)data, size); + hdr_dynamic_meta->size = size; + hdr_dynamic_meta->hdr_fmt = hdr_fmt; + } + p_Cur->hdr_dynamic_meta = hdr_dynamic_meta; + p_Cur->hdr_dynamic = 1; +} + +static MPP_RET store_cur_nalu(H264dCurCtx_t *p_Cur, H264dCurStream_t *p_strm, H264dDxvaCtx_t *dxva_ctx) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U8 *p_des = NULL; + + //!< fill head buffer + if ( (p_strm->nalu_type == H264_NALU_TYPE_SLICE) + || (p_strm->nalu_type == H264_NALU_TYPE_IDR) + || (p_strm->nalu_type == H264_NALU_TYPE_SPS) + || (p_strm->nalu_type == H264_NALU_TYPE_PPS) + || (p_strm->nalu_type == H264_NALU_TYPE_SUB_SPS) + || (p_strm->nalu_type == H264_NALU_TYPE_SEI) + || (p_strm->nalu_type == H264_NALU_TYPE_PREFIX) + || (p_strm->nalu_type == H264_NALU_TYPE_SLC_EXT)) { + + RK_U32 head_size = MPP_MIN(HEAD_SYNTAX_MAX_SIZE, p_strm->nalu_len); + RK_U32 add_size = head_size + sizeof(H264dNaluHead_t); + + //!< judge new frame + if (p_strm->tmp_offset && !p_strm->head_offset) { + memcpy(p_strm->head_buf, p_strm->tmp_buf, p_strm->tmp_offset); + p_strm->head_offset += p_strm->tmp_offset; + p_strm->tmp_offset = 0; + + H264D_LOG("copy tmp header to empty header of new frame"); + } + + if ((p_strm->head_offset + add_size) >= p_strm->head_max_size) { + FUN_CHECK(ret = realloc_buffer(&p_strm->head_buf, &p_strm->head_max_size, add_size)); + } + p_des = &p_strm->head_buf[p_strm->head_offset]; + ((H264dNaluHead_t *)p_des)->is_frame_end = 0; + ((H264dNaluHead_t *)p_des)->nalu_type = p_strm->nalu_type; + ((H264dNaluHead_t *)p_des)->sodb_len = head_size; + memcpy(p_des + sizeof(H264dNaluHead_t), p_strm->nalu_buf, head_size); + p_strm->head_offset += add_size; + + H264D_LOG("store current header, NAL type %d", p_strm->nalu_type); + + // store NAL header except slice NAL + if (p_Cur->p_Dec->have_slice_data && p_strm->nalu_type != H264_NALU_TYPE_IDR && + p_strm->nalu_type != H264_NALU_TYPE_SLICE) { + RK_U8 *p_tmp = NULL; + + if ((p_strm->tmp_offset + add_size) >= p_strm->tmp_max_size) { + FUN_CHECK(ret = realloc_buffer(&p_strm->tmp_buf, &p_strm->tmp_max_size, add_size)); + } + + p_tmp = &p_strm->tmp_buf[p_strm->tmp_offset]; + memcpy(p_tmp, p_des, add_size); + p_strm->tmp_offset += add_size; + + H264D_LOG("store current header to tmp header, NAL type %d", p_strm->nalu_type); + } + } //!< fill sodb buffer + if ((p_strm->nalu_type == H264_NALU_TYPE_SLICE) + || (p_strm->nalu_type == H264_NALU_TYPE_IDR)) { + + RK_U32 add_size = p_strm->nalu_len + sizeof(g_start_precode); + + if ((dxva_ctx->strm_offset + add_size) >= dxva_ctx->max_strm_size) { + FUN_CHECK(ret = realloc_buffer(&dxva_ctx->bitstream, &dxva_ctx->max_strm_size, add_size)); + } + + p_des = &dxva_ctx->bitstream[dxva_ctx->strm_offset]; + memcpy(p_des, g_start_precode, sizeof(g_start_precode)); + memcpy(p_des + sizeof(g_start_precode), p_strm->nalu_buf, p_strm->nalu_len); + dxva_ctx->strm_offset += add_size; + } + + /* Dlby Vision RPUs masquerade as unregistered NALs of type 28. */ + if (p_Cur->p_Dec->cfg->base.enable_hdr_meta && p_strm->nalu_type == H264_NALU_TYPE_UNSPECIFIED28) + mpp_h264d_fill_dynamic_meta(p_Cur, p_strm->nalu_buf + 2, p_strm->nalu_len - 2, DLBY); + + if (h264d_debug & H264D_DBG_WRITE_ES_EN) { + H264dInputCtx_t *p_Inp = p_Cur->p_Inp; + if ((p_strm->nalu_type == H264_NALU_TYPE_SPS) + || (p_strm->nalu_type == H264_NALU_TYPE_PPS)) { + if (p_Inp->spspps_update_flag) { + p_des = &p_Inp->spspps_buf[p_Inp->spspps_offset]; + memcpy(p_des, g_start_precode, sizeof(g_start_precode)); + memcpy(p_des + sizeof(g_start_precode), p_strm->nalu_buf, p_strm->nalu_len); + p_Inp->spspps_offset += p_strm->nalu_len + sizeof(g_start_precode); + p_Inp->spspps_len = p_Inp->spspps_offset; + } + } else if ((p_strm->nalu_type == H264_NALU_TYPE_SLICE) + || (p_strm->nalu_type == H264_NALU_TYPE_IDR)) { + p_Cur->p_Inp->spspps_update_flag = 1; + p_Inp->spspps_offset = 0; + } + } + + return ret = MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET judge_is_new_frame(H264dCurCtx_t *p_Cur, H264dCurStream_t *p_strm) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 nalu_header_bytes = 0; + + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + memset(p_bitctx, 0, sizeof(BitReadCtx_t)); + { + RK_U32 forbidden_bit = -1; + RK_U32 nal_reference_idc = -1; + mpp_set_bitread_ctx(p_bitctx, p_strm->nalu_buf, 4); + mpp_set_bitread_pseudo_code_type(p_bitctx, PSEUDO_CODE_H264_H265); + + READ_BITS(p_bitctx, 1, &forbidden_bit); + ASSERT(forbidden_bit == 0); + READ_BITS(p_bitctx, 2, &nal_reference_idc); + READ_BITS(p_bitctx, 5, &p_strm->nalu_type); + + nalu_header_bytes = 1; + if ((p_strm->nalu_type == H264_NALU_TYPE_PREFIX) + || (p_strm->nalu_type == H264_NALU_TYPE_SLC_EXT)) { + if (p_strm->nalu_type == H264_NALU_TYPE_SLC_EXT) { + p_strm->nalu_type = H264_NALU_TYPE_SLICE; + } + nalu_header_bytes += 3; + } + } + if ((p_strm->nalu_len == 1) + && (p_strm->nalu_type == H264_NALU_TYPE_SEI + || p_strm->nalu_type == H264_NALU_TYPE_SPS + || p_strm->nalu_type == H264_NALU_TYPE_PPS + || p_strm->nalu_type == H264_NALU_TYPE_SUB_SPS + || p_strm->nalu_type == H264_NALU_TYPE_AUD + /*|| p_strm->nalu_type == H264_NALU_TYPE_PREFIX*/)) { // prefix may insert in slices of one frame + p_Cur->last_dts = p_Cur->curr_dts; + p_Cur->last_pts = p_Cur->curr_pts; + p_Cur->curr_dts = p_Cur->p_Inp->in_dts; + p_Cur->curr_pts = p_Cur->p_Inp->in_pts; + if (p_Cur->p_Dec->have_slice_data) { + p_Cur->p_Dec->is_new_frame = 1; + } + p_Cur->p_Dec->have_slice_data = 0; + } else if ((p_strm->nalu_len > 1) + && (p_strm->nalu_type == H264_NALU_TYPE_SLICE + || p_strm->nalu_type == H264_NALU_TYPE_IDR)) { + RK_U32 first_mb_in_slice = 0; + mpp_set_bitread_ctx(p_bitctx, (p_strm->nalu_buf + nalu_header_bytes), 4); // reset + mpp_set_bitread_pseudo_code_type(p_bitctx, PSEUDO_CODE_H264_H265); + READ_UE(p_bitctx, &first_mb_in_slice); + if (first_mb_in_slice == 0) { + p_Cur->last_dts = p_Cur->curr_dts; + p_Cur->last_pts = p_Cur->curr_pts; + p_Cur->curr_dts = p_Cur->p_Inp->in_dts; + p_Cur->curr_pts = p_Cur->p_Inp->in_pts; + if (p_Cur->p_Dec->have_slice_data) { + p_Cur->p_Dec->is_new_frame = 1; + } + p_Cur->p_Dec->have_slice_data = 1; + } else if (p_strm->tmp_offset != 0 && + first_mb_in_slice != p_Cur->strm.first_mb_in_slice) { + p_strm->tmp_offset = 0; + H264D_LOG("reset temporary header"); + } + p_Cur->strm.first_mb_in_slice = first_mb_in_slice; + } + + return ret = MPP_OK; +__BITREAD_ERR: + return ret = p_bitctx->ret; +} + +#define MAX_ES_FILE_SIZE (100*1024*1024) +static RK_U32 global_file_fid = 0; +static RK_U64 global_flie_size = 0; +/*! +*********************************************************************** +* \brief +* open stream file to store packet +*********************************************************************** +*/ +MPP_RET open_stream_file(H264dInputCtx_t *p_Inp, char *path) +{ + if (h264d_debug & H264D_DBG_WRITE_ES_EN) { + + sprintf(p_Inp->fname[0], "%s/rkv_h264d_file_00.h264", path); + sprintf(p_Inp->fname[1], "%s/rkv_h264d_file_01.h264", path); + + p_Inp->fp = fopen(p_Inp->fname[global_file_fid], "ab"); { + if (p_Inp->fp == NULL) { + H264D_WARNNING("[open_stream_file] can not open stream file, %s.", p_Inp->fname[global_file_fid]); + } + } + } + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* write stream file +*********************************************************************** +*/ +MPP_RET fwrite_stream_to_file(H264dInputCtx_t *p_Inp, RK_U8 *pdata, RK_U32 len) +{ + if (p_Inp->fp && (h264d_debug & H264D_DBG_WRITE_ES_EN)) { + if (p_Inp->fp) { + fwrite(pdata, sizeof(RK_U8), len, p_Inp->fp); + fflush(p_Inp->fp); + } + global_flie_size += len; + if (global_flie_size > MAX_ES_FILE_SIZE) { + MPP_FCLOSE(p_Inp->fp); + global_file_fid = 1 - global_file_fid; + global_flie_size = 0; + p_Inp->fp = fopen(p_Inp->fname[global_file_fid], "wb"); + if (p_Inp->fp == NULL) { + H264D_WARNNING("[open_stream_file] can not open stream file, %s", p_Inp->fname[global_file_fid]); + } else { + fwrite(p_Inp->spspps_buf, sizeof(RK_U8), p_Inp->spspps_len, p_Inp->fp); + fflush(p_Inp->fp); + } + } + } + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* close stream file +*********************************************************************** +*/ +MPP_RET close_stream_file(H264dInputCtx_t *p_Inp) +{ + if (h264d_debug & H264D_DBG_WRITE_ES_EN) { + if (p_Inp->fp) { + fflush(p_Inp->fp); + MPP_FCLOSE(p_Inp->fp); + } + } + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* clear last redundancy header if exist +*********************************************************************** +*/ +static MPP_RET clear_extra_header(H264dCurStream_t *p_strm) +{ + MPP_RET ret = MPP_OK; + + if (p_strm->tmp_offset >= p_strm->head_offset) { + H264D_WARNNING("tmp header data is too long! skip clear operation"); + ret = MPP_NOK; + } else { + RK_U32 pos = p_strm->head_offset - p_strm->tmp_offset; + RK_U8 *p_des = &p_strm->head_buf[pos]; + + memset(p_des, 0, p_strm->tmp_offset); + p_strm->head_offset -= p_strm->tmp_offset; + + H264D_LOG("clear last redundancy header in slice"); + } + + return ret; +} +/*! +*********************************************************************** +* \brief +* prepare function for parser +*********************************************************************** +*/ +MPP_RET parse_prepare(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264_DecCtx_t *p_Dec = p_Inp->p_Dec; + H264dCurStream_t *p_strm = &p_Cur->strm; + MppPacketImpl *pkt_impl = (MppPacketImpl *)p_Inp->in_pkt; + + p_Dec->nalu_ret = NALU_NULL; + p_Inp->task_valid = 0; + + //!< check eos + if (p_Inp->pkt_eos && !p_Inp->in_length) { + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Dec->dxva_ctx)); + FUN_CHECK(ret = add_empty_nalu(p_strm)); + p_Dec->p_Inp->task_valid = (p_Dec->p_Inp->task_eos != 0) ? 0 : 1; + p_Dec->p_Inp->task_eos = 1; + H264D_LOG("----- end of stream ----"); + goto __RETURN; + } + //!< check input + if (!p_Inp->in_length) { + p_Dec->nalu_ret = HaveNoStream; + goto __RETURN; + } + + while (pkt_impl->length > 0) { + p_strm->curdata = &p_Inp->in_buf[p_strm->nalu_offset++]; + pkt_impl->length--; + p_strm->prefixdata = (p_strm->prefixdata << 8) | (*p_strm->curdata); + if (p_strm->startcode_found) { + if (p_strm->nalu_len >= p_strm->nalu_max_size) { + FUN_CHECK(ret = realloc_buffer(&p_strm->nalu_buf, &p_strm->nalu_max_size, NALU_BUF_ADD_SIZE)); + } + p_strm->nalu_buf[p_strm->nalu_len++] = *p_strm->curdata; + if ((p_strm->nalu_len == NALU_TYPE_NORMAL_LENGTH) + || (p_strm->nalu_len == NALU_TYPE_EXT_LENGTH)) { + FUN_CHECK(ret = judge_is_new_frame(p_Cur, p_strm)); + if (p_Cur->p_Dec->is_new_frame) { + if (p_strm->tmp_offset) + clear_extra_header(p_strm); + FUN_CHECK(ret = add_empty_nalu(p_strm)); + p_strm->head_offset = 0; + p_strm->first_mb_in_slice = 0; + p_Cur->p_Inp->task_valid = 1; + p_Cur->p_Dec->is_new_frame = 0; + + H264D_LOG("new frame is found"); + break; + } + } + } + + find_prefix_code(p_strm->curdata, p_strm); + + if (p_strm->endcode_found) { + p_strm->nalu_len -= START_PREFIX_3BYTE; + if (p_strm->nalu_len > START_PREFIX_3BYTE) { + while ((p_strm->nalu_len > 0) && + (p_strm->nalu_buf[p_strm->nalu_len - 1] == 0x00)) { + p_strm->nalu_len--; + } + } + p_Dec->nalu_ret = EndOfNalu; + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Dec->dxva_ctx)); + reset_nalu(p_strm); + break; + } + } + p_Inp->in_length = pkt_impl->length; + //!< check input + if (!p_Inp->in_length) { + p_strm->nalu_offset = 0; + p_Dec->nalu_ret = HaveNoStream; + } + + if (p_Inp->pkt_eos && p_Inp->in_length < 4) { + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Dec->dxva_ctx)); + FUN_CHECK(ret = add_empty_nalu(p_strm)); + p_Dec->p_Inp->task_valid = 1; + p_Dec->p_Inp->task_eos = 1; + H264D_LOG("----- found eos in last non-empty packet ----"); + } + +__RETURN: + + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* prepare function for parser +*********************************************************************** +*/ +MPP_RET parse_prepare_fast(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264_DecCtx_t *p_Dec = p_Inp->p_Dec; + H264dCurStream_t *p_strm = &p_Cur->strm; + MppPacketImpl *pkt_impl = (MppPacketImpl *)p_Inp->in_pkt; + + p_Dec->nalu_ret = NALU_NULL; + p_Inp->task_valid = 0; + + while (pkt_impl->length > 0) { + p_strm->curdata = &p_Inp->in_buf[p_strm->nalu_offset++]; + pkt_impl->length--; + p_strm->prefixdata = (p_strm->prefixdata << 8) | (*p_strm->curdata); + if (p_strm->startcode_found) { + if (p_strm->nalu_len >= p_strm->nalu_max_size) { + FUN_CHECK(ret = realloc_buffer(&p_strm->nalu_buf, &p_strm->nalu_max_size, NALU_BUF_ADD_SIZE)); + } + p_strm->nalu_buf[p_strm->nalu_len++] = *p_strm->curdata; + if (p_strm->nalu_len == 1) { + p_strm->nalu_type = p_strm->nalu_buf[0] & 0x1F; + + if (p_strm->nalu_type == H264_NALU_TYPE_SLICE + || p_strm->nalu_type == H264_NALU_TYPE_IDR || p_strm->nalu_type == H264_NALU_TYPE_SLC_EXT) { + + if (p_strm->nalu_type == H264_NALU_TYPE_SLC_EXT) + p_strm->nalu_type = H264_NALU_TYPE_SLICE; + + p_strm->nalu_len += (RK_U32)pkt_impl->length; + if (p_strm->nalu_len >= p_strm->nalu_max_size) { + RK_U32 add_size = pkt_impl->length + 1 - p_strm->nalu_max_size; + FUN_CHECK(ret = realloc_buffer(&p_strm->nalu_buf, &p_strm->nalu_max_size, MPP_MAX(NALU_BUF_ADD_SIZE, add_size))); + } + memcpy(&p_strm->nalu_buf[0], p_strm->curdata, pkt_impl->length + 1); + pkt_impl->length = 0; + p_Cur->p_Inp->task_valid = 1; + break; + } + } + } + + find_prefix_code(p_strm->curdata, p_strm); + + if (p_strm->endcode_found) { + p_strm->nalu_len -= START_PREFIX_3BYTE; + while (p_strm->nalu_len > 0 && p_strm->nalu_buf[p_strm->nalu_len - 1] == 0x00) { + p_strm->nalu_len--; + } + p_Dec->nalu_ret = EndOfNalu; + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Dec->dxva_ctx)); + reset_nalu(p_strm); + break; + } + } + if (p_Cur->p_Inp->task_valid) { + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Dec->dxva_ctx)); + FUN_CHECK(ret = add_empty_nalu(p_strm)); + p_strm->head_offset = 0; + p_Cur->last_dts = p_Cur->p_Inp->in_dts; + p_Cur->last_pts = p_Cur->p_Inp->in_pts; + } + p_Inp->in_length = pkt_impl->length; + //!< check input + if (!p_Inp->in_length) { + if (!p_Cur->p_Inp->task_valid) { + p_Dec->nalu_ret = EndOfNalu; + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Dec->dxva_ctx)); + } else { + p_Dec->nalu_ret = HaveNoStream; + } + p_strm->nalu_offset = 0; + p_strm->endcode_found = 1; + + reset_nalu(p_strm); + p_strm->startcode_found = 0; + } + + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief +* main function for parser avcC header +*********************************************************************** +*/ +MPP_RET parse_prepare_avcC_header(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur) +{ + RK_S32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dCurStream_t *p_strm = &p_Cur->strm; + RK_U8 *pdata = p_Inp->in_buf; + MppPacketImpl *pkt_impl = (MppPacketImpl *)p_Inp->in_pkt; + + //!< free nalu_buffer + MPP_FREE(p_strm->nalu_buf); + if (p_Inp->in_length < 7) { + H264D_ERR("avcC too short, len=%d \n", p_Inp->in_length); + goto __FAILED; + } + if (pdata[0] != 1) { + goto __FAILED; + } + p_Inp->profile = pdata[1]; + p_Inp->level = pdata[3]; + p_Inp->nal_size = 1 + (pdata[4] & 3); + p_Inp->sps_num = pdata[5] & 31; + + pdata += 6; + for (i = 0; i < p_Inp->sps_num; ++i) { + p_strm->nalu_len = U16_AT(pdata); + pdata += 2; + p_strm->nalu_type = H264_NALU_TYPE_SPS; + p_strm->nalu_buf = pdata; + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Cur->p_Dec->dxva_ctx)); + pdata += p_strm->nalu_len; + } + p_strm->nalu_buf = NULL; + p_Inp->pps_num = *pdata; + ++pdata; + for (i = 0; i < p_Inp->pps_num; ++i) { + p_strm->nalu_len = U16_AT(pdata); + pdata += 2; + p_strm->nalu_type = H264_NALU_TYPE_PPS; + p_strm->nalu_buf = pdata; + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Cur->p_Dec->dxva_ctx)); + pdata += p_strm->nalu_len; + } + pkt_impl->length = 0; + p_strm->nalu_buf = NULL; + p_strm->startcode_found = 1; + + ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief +* main function for parser avcC data +*********************************************************************** +*/ +MPP_RET parse_prepare_avcC_data(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dCurStream_t *p_strm = &p_Cur->strm; + MppPacketImpl *pkt_impl = (MppPacketImpl *)p_Inp->in_pkt; + + p_strm->nalu_buf = NULL; + p_Inp->task_valid = 0; + if (p_Inp->pkt_eos) { + p_Inp->task_eos = 1; + if (p_Inp->in_length) + p_Inp->task_valid = 1; + return MPP_OK; + } + VAL_CHECK(ret, (p_Inp->nal_size > 0)); + p_strm->curdata = &p_Inp->in_buf[p_strm->nalu_offset]; + while (p_Inp->in_length > 0) { + if (p_strm->startcode_found) { + p_strm->nalu_len = parse_nal_size(p_Inp->nal_size, p_strm->curdata); + if (p_strm->nalu_len <= 0 || p_strm->nalu_len >= p_Inp->in_length) { + p_Cur->p_Dec->is_new_frame = 1; + p_Cur->p_Dec->have_slice_data = 0; + pkt_impl->length = 0; + p_Inp->in_length = 0; + p_strm->nalu_len = 0; + p_strm->nalu_offset = 0; + p_strm->startcode_found = 1; + p_strm->endcode_found = 0; + p_strm->nalu_buf = NULL; + goto __FAILED; + } + + p_strm->nalu_buf = p_strm->curdata + p_Inp->nal_size; + judge_is_new_frame(p_Cur, p_strm); + if (p_Cur->p_Dec->is_new_frame) { + p_Cur->p_Dec->have_slice_data = 0; + p_strm->startcode_found = 1; + p_strm->endcode_found = 0; + break; + } + + p_strm->curdata += p_Inp->nal_size; + p_strm->nalu_offset += p_Inp->nal_size; + pkt_impl->length -= p_Inp->nal_size; + p_Inp->in_length -= p_Inp->nal_size; + + p_strm->nalu_buf = p_strm->curdata; + p_strm->nalu_type = p_strm->nalu_buf[0] & 0x1F; + p_strm->startcode_found = 0; + p_strm->endcode_found = 1; + + FUN_CHECK(ret = store_cur_nalu(p_Cur, p_strm, p_Cur->p_Dec->dxva_ctx)); + p_strm->curdata += p_strm->nalu_len; + p_strm->nalu_offset += p_strm->nalu_len; + pkt_impl->length -= p_strm->nalu_len; + p_Inp->in_length -= p_strm->nalu_len; + p_strm->startcode_found = 1; + p_strm->endcode_found = 0; + p_strm->nalu_len = 0; + } + + if (p_Inp->in_length < p_Inp->nal_size) { + p_Cur->p_Dec->is_new_frame = 1; + p_Cur->p_Dec->have_slice_data = 0; + pkt_impl->length = 0; + p_Inp->in_length = 0; + p_strm->nalu_len = 0; + p_strm->nalu_offset = 0; + p_strm->startcode_found = 1; + p_strm->endcode_found = 0; + p_strm->nalu_buf = NULL; + break; + } + } + //!< one frame end + if (p_Cur->p_Dec->is_new_frame) { + if (p_strm->tmp_offset) + clear_extra_header(p_strm); + //!< add an empty nalu to tell frame end + FUN_CHECK(ret = add_empty_nalu(p_strm)); + //!< reset curstream parameters + p_strm->head_offset = 0; + p_strm->first_mb_in_slice = 0; + p_Cur->p_Inp->task_valid = 1; + p_Cur->p_Dec->is_new_frame = 0; + + p_Cur->last_dts = p_Inp->in_dts; + p_Cur->last_pts = p_Inp->in_pts; + } + p_strm->nalu_buf = NULL; + ret = MPP_OK; +__FAILED: + //p_strm->nalu_len = 0; + p_Cur->last_dts = p_Inp->in_dts; + p_Cur->last_pts = p_Inp->in_pts; + p_Inp->p_Dec->nalu_ret = HaveNoStream; + + return ret; +} + + + +/*! +*********************************************************************** +* \brief +* main function for parser +*********************************************************************** +*/ +MPP_RET parse_loop(H264_DecCtx_t *p_Dec) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U8 *p_curdata = NULL; + RK_U8 while_loop_flag = 1; + H264dNaluHead_t *p_head = NULL; + + INP_CHECK(ret, !p_Dec); + //!< ==== loop ==== + p_Dec->next_state = SliceSTATE_ResetSlice; + p_curdata = p_Dec->p_Cur->strm.head_buf; + + while (while_loop_flag) { + switch (p_Dec->next_state) { + case SliceSTATE_ResetSlice: + reset_slice(p_Dec->p_Vid); + p_Dec->next_state = SliceSTATE_ReadNalu; + H264D_DBG(H264D_DBG_LOOP_STATE, "SliceSTATE_ResetSlice"); + break; + case SliceSTATE_ReadNalu: + p_head = (H264dNaluHead_t *)p_curdata; + if (p_head->is_frame_end) { + p_Dec->next_state = SliceSTATE_RegisterOneFrame; + p_Dec->nalu_ret = HaveNoStream; + } else { + p_curdata += sizeof(H264dNaluHead_t); + memset(&p_Dec->p_Cur->nalu, 0, sizeof(H264_Nalu_t)); + p_Dec->p_Cur->nalu.sodb_buf = p_curdata; + p_Dec->p_Cur->nalu.sodb_len = p_head->sodb_len; + p_curdata += p_head->sodb_len; + p_Dec->nalu_ret = EndOfNalu; + p_Dec->next_state = SliceSTATE_ParseNalu; + } + H264D_DBG(H264D_DBG_LOOP_STATE, "SliceSTATE_ReadNalu"); + break; + case SliceSTATE_ParseNalu: + FUN_CHECK(ret = parser_one_nalu(&p_Dec->p_Cur->slice)); + if (p_Dec->nalu_ret == StartOfSlice) { + p_Dec->next_state = SliceSTATE_GetSliceData; + } else if (p_Dec->nalu_ret == StartOfPicture) { + p_Dec->next_state = SliceSTATE_InitPicture; + } else if (p_Dec->nalu_ret == MvcDisAble) { + H264D_LOG("xxxxxxxx MVC disable"); + goto __FAILED; + } else if (p_Dec->nalu_ret == NaluNotSupport) { + H264D_LOG("NALU not support, abort decoding"); + goto __FAILED; + } else { + p_Dec->next_state = SliceSTATE_ReadNalu; + } + H264D_DBG(H264D_DBG_LOOP_STATE, "SliceSTATE_ParseNalu"); + break; + case SliceSTATE_InitPicture: + if (!p_Dec->p_Vid->iNumOfSlicesDecoded) { + FUN_CHECK(ret = init_picture(&p_Dec->p_Cur->slice)); + p_Dec->is_parser_end = 1; + } + p_Dec->next_state = SliceSTATE_GetSliceData; + H264D_DBG(H264D_DBG_LOOP_STATE, "SliceSTATE_InitPicture"); + break; + case SliceSTATE_GetSliceData: + FUN_CHECK(ret = fill_slice_syntax(&p_Dec->p_Cur->slice, p_Dec->dxva_ctx)); + p_Dec->p_Vid->iNumOfSlicesDecoded++; + if (p_Dec->is_parser_end) { + p_Dec->next_state = SliceSTATE_RegisterOneFrame; + } else { + p_Dec->next_state = SliceSTATE_ResetSlice; + } + H264D_DBG(H264D_DBG_LOOP_STATE, "SliceSTATE_GetSliceData"); + break; + case SliceSTATE_RegisterOneFrame: + if (!p_Dec->is_parser_end) { + ret = MPP_NOK; + goto __FAILED; + } + commit_buffer(p_Dec->dxva_ctx); + while_loop_flag = 0; + p_Dec->next_state = SliceSTATE_ReadNalu; + H264D_DBG(H264D_DBG_LOOP_STATE, "SliceSTATE_RegisterOneFrame"); + break; + default: + ret = MPP_NOK; + break; + } + } + +__RETURN: + return ret = MPP_OK; +__FAILED: + p_Dec->nalu_ret = NALU_NULL; + p_Dec->dxva_ctx->slice_count = 0; + p_Dec->dxva_ctx->strm_offset = 0; + p_Dec->p_Vid->iNumOfSlicesDecoded = 0; + p_Dec->p_Vid->exit_picture_flag = 0; + + return ret; +} + + diff --git a/mpp/codec/dec/h264/h264d_parse.h b/mpp/codec/dec/h264/h264d_parse.h index 357349126..12b0bc9cb 100644 --- a/mpp/codec/dec/h264/h264d_parse.h +++ b/mpp/codec/dec/h264/h264d_parse.h @@ -1,42 +1,45 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __H264D_PARSE_H__ -#define __H264D_PARSE_H__ -#include "rk_type.h" -#include "mpp_err.h" - -#include "h264d_global.h" - - - -#ifdef __cplusplus -extern "C" { -#endif - - -MPP_RET parse_loop(H264_DecCtx_t *p_Dec); - - - - -#ifdef __cplusplus -} -#endif - - -#endif /* __H264D_PARSE_H__ */ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_PARSE_H +#define H264D_PARSE_H +#include "rk_type.h" +#include "mpp_err.h" + +#include "h264d_global.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET open_stream_file(H264dInputCtx_t *p_Inp, char *path); +MPP_RET fwrite_stream_to_file(H264dInputCtx_t *p_Inp, RK_U8 *pdata, RK_U32 len); +MPP_RET close_stream_file(H264dInputCtx_t *p_Inp); +MPP_RET parse_loop(H264_DecCtx_t *p_Dec); +MPP_RET parse_prepare(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur); +MPP_RET parse_prepare_fast(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur); +MPP_RET parse_prepare_avcC_header(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur); +MPP_RET parse_prepare_avcC_data(H264dInputCtx_t *p_Inp, H264dCurCtx_t *p_Cur); + +#ifdef __cplusplus +} +#endif + + +#endif /* H264D_PARSE_H */ diff --git a/mpp/codec/dec/h264/h264d_pps.c b/mpp/codec/dec/h264/h264d_pps.c index 2628a4856..398ed3f53 100644 --- a/mpp/codec/dec/h264/h264d_pps.c +++ b/mpp/codec/dec/h264/h264d_pps.c @@ -1,172 +1,208 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include - -#include "mpp_err.h" - -#include "h264d_log.h" -#include "h264d_bitread.h" -#include "h264d_pps.h" -#include "h264d_scalist.h" -#include "h264d_dpb.h" - -#define MODULE_TAG "h264d_pps" - -static void reset_curpps_data(H264_PPS_t *cur_pps) -{ - memset(cur_pps, 0, sizeof(H264_PPS_t)); - cur_pps->seq_parameter_set_id = -1; // reset - cur_pps->pic_parameter_set_id = -1; -} - -static MPP_RET parse_pps_calingLists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps, H264_PPS_t *pps) -{ - RK_S32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - for (i = 0; i < 6; ++i) { - READ_ONEBIT(ret, p_bitctx, &pps->pic_scaling_list_present_flag[i], "pic_scaling_list_present_flag"); - - if (pps->pic_scaling_list_present_flag[i]) { - FUN_CHECK (ret = parse_scalingList(p_bitctx, H264ScalingList4x4Length, - pps->ScalingList4x4[i], &pps->UseDefaultScalingMatrix4x4Flag[i])); - } - } - if (pps->transform_8x8_mode_flag) { - for (i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) { - READ_ONEBIT(ret, p_bitctx, &pps->pic_scaling_list_present_flag[i + 6], "pic_scaling_list_present_flag"); - if (pps->pic_scaling_list_present_flag[i + 6]) { - FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList8x8Length, - pps->ScalingList8x8[i], &pps->UseDefaultScalingMatrix8x8Flag[i])); - } - } - } - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET parser_pps(BitReadCtx_t *p_bitctx, H264_SPS_t *cur_sps, H264_PPS_t *cur_pps) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - WRITE_LOG(p_bitctx, "----------------------------- PPS begin --------------------------------"); - READ_UE(ret, p_bitctx, &cur_pps->pic_parameter_set_id, "pic_parameter_set_id"); - READ_UE(ret, p_bitctx, &cur_pps->seq_parameter_set_id, "seq_parameter_set_id"); - VAL_CHECK(ret, cur_pps->seq_parameter_set_id < 32); - - READ_ONEBIT(ret, p_bitctx, &cur_pps->entropy_coding_mode_flag, "entropy_coding_mode_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_pps->bottom_field_pic_order_in_frame_present_flag, "bottom_field_pic_order_in_frame_present_flag"); - - READ_UE(ret, p_bitctx, &cur_pps->num_slice_groups_minus1, "num_slice_groups_minus1"); - VAL_CHECK(ret, cur_pps->num_slice_groups_minus1 <= 1); - READ_UE(ret, p_bitctx, &cur_pps->num_ref_idx_l0_default_active_minus1, "num_ref_idx_l0_default_active_minus1"); - VAL_CHECK(ret, cur_pps->num_ref_idx_l0_default_active_minus1 < 32); - READ_UE(ret, p_bitctx, &cur_pps->num_ref_idx_l1_default_active_minus1, "num_ref_idx_l1_default_active_minus1"); - VAL_CHECK(ret, cur_pps->num_ref_idx_l1_default_active_minus1 < 32); - READ_ONEBIT(ret, p_bitctx, &cur_pps->weighted_pred_flag, "weighted_pred_flag"); - READ_BITS(ret, p_bitctx, 2, &cur_pps->weighted_bipred_idc, "weighted_bipred_idc"); - VAL_CHECK(ret, cur_pps->weighted_bipred_idc < 3); - READ_SE(ret, p_bitctx, &cur_pps->pic_init_qp_minus26, "pic_init_qp_minus26"); - CHECK_RANGE(ret, p_bitctx, cur_pps->pic_init_qp_minus26, -26, 25); - READ_SE(ret, p_bitctx, &cur_pps->pic_init_qs_minus26, "pic_init_qs_minus26"); - CHECK_RANGE(ret, p_bitctx, cur_pps->pic_init_qs_minus26, -26, 25); - READ_SE(ret, p_bitctx, &cur_pps->chroma_qp_index_offset, "chroma_qp_index_offset"); - CHECK_RANGE(ret, p_bitctx, cur_pps->chroma_qp_index_offset, -12, 12); - cur_pps->second_chroma_qp_index_offset = cur_pps->chroma_qp_index_offset; - READ_ONEBIT(ret, p_bitctx, &cur_pps->deblocking_filter_control_present_flag, "deblocking_filter_control_present_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_pps->constrained_intra_pred_flag, "constrained_intra_pred_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_pps->redundant_pic_cnt_present_flag, "redundant_pic_cnt_present_flag"); - VAL_CHECK(ret , cur_pps->redundant_pic_cnt_present_flag == 0); - - if (has_more_rbsp_data(p_bitctx)) { - READ_ONEBIT(ret, p_bitctx, &cur_pps->transform_8x8_mode_flag, "transform_8x8_mode_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_pps->pic_scaling_matrix_present_flag, "pic_scaling_matrix_present_flag"); - if (cur_pps->pic_scaling_matrix_present_flag) { - LogInfo(p_bitctx->ctx, "Picture scaling matrix present."); - FUN_CHECK(ret = parse_pps_calingLists(p_bitctx, cur_sps, cur_pps)); - } - READ_SE(ret, p_bitctx, &cur_pps->second_chroma_qp_index_offset, "second_chroma_qp_index_offset"); - } else { - cur_pps->transform_8x8_mode_flag = 0; - cur_pps->second_chroma_qp_index_offset = cur_pps->chroma_qp_index_offset; - } - cur_pps->Valid = 1; - - return ret = MPP_OK; - -__FAILED: - ASSERT(0); - return ret; -} - - -/*! -*********************************************************************** -* \brief -* parser pps and process pps -*********************************************************************** -*/ -//extern "C" -MPP_RET process_pps(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dLogCtx_t *logctx = currSlice->logctx; - H264dCurCtx_t *p_Cur = currSlice->p_Cur; - BitReadCtx_t *p_bitctx = &p_Cur->bitctx; - H264_PPS_t *cur_pps = &p_Cur->pps; - - FunctionIn(logctx->parr[RUN_PARSE]); - reset_curpps_data(cur_pps);// reset - set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_PPS]); - FUN_CHECK(ret = parser_pps(p_bitctx, &p_Cur->sps, cur_pps)); - //!< MakePPSavailable - ASSERT(cur_pps->Valid == 1); - memcpy(&currSlice->p_Vid->ppsSet[cur_pps->pic_parameter_set_id], cur_pps, sizeof(H264_PPS_t)); - - FunctionOut(logctx->parr[RUN_PARSE]); - - return ret = MPP_OK; -__FAILED: - return ret; -} - -/*! -*********************************************************************** -* \brief -* prase sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET activate_pps(H264dVideoCtx_t *p_Vid, H264_PPS_t *pps) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - if (p_Vid->active_pps != pps) { - if (p_Vid->dec_picture) { - //!< return if the last picture has already been finished - FUN_CHECK(ret = exit_picture(p_Vid, &p_Vid->dec_picture)); - } - p_Vid->active_pps = pps; - } - - return ret = MPP_OK; -__FAILED: - return ret; -} +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_pps" + +#include + +#include "mpp_err.h" + +#include "h264d_pps.h" +#include "h264d_scalist.h" +#include "h264d_dpb.h" + +static void reset_curpps_data(H264_PPS_t *cur_pps) +{ + memset(cur_pps, 0, sizeof(H264_PPS_t)); + cur_pps->seq_parameter_set_id = 0; // reset + cur_pps->pic_parameter_set_id = 0; +} + +static MPP_RET parse_pps_calingLists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps, H264_PPS_t *pps) +{ + RK_S32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + for (i = 0; i < 6; ++i) { + READ_ONEBIT(p_bitctx, &pps->pic_scaling_list_present_flag[i]); + + if (pps->pic_scaling_list_present_flag[i]) { + FUN_CHECK (ret = parse_scalingList(p_bitctx, H264ScalingList4x4Length, + pps->ScalingList4x4[i], &pps->UseDefaultScalingMatrix4x4Flag[i])); + } + } + if (pps->transform_8x8_mode_flag) { + for (i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) { + READ_ONEBIT(p_bitctx, &pps->pic_scaling_list_present_flag[i + 6]); + if (pps->pic_scaling_list_present_flag[i + 6]) { + FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList8x8Length, + pps->ScalingList8x8[i], &pps->UseDefaultScalingMatrix8x8Flag[i])); + } + } + } + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET parser_pps(BitReadCtx_t *p_bitctx, H264_SPS_t *cur_sps, H264_PPS_t *cur_pps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + READ_UE(p_bitctx, &cur_pps->pic_parameter_set_id); + READ_UE(p_bitctx, &cur_pps->seq_parameter_set_id); + //VAL_CHECK(ret, cur_pps->seq_parameter_set_id < 32); + if (cur_pps->seq_parameter_set_id >= MAXSPS) { + cur_pps->seq_parameter_set_id = 0; + } + if (cur_pps->pic_parameter_set_id >= MAXPPS) { + cur_pps->pic_parameter_set_id = 0; + } + READ_ONEBIT(p_bitctx, &cur_pps->entropy_coding_mode_flag); + READ_ONEBIT(p_bitctx, &cur_pps->bottom_field_pic_order_in_frame_present_flag); + + READ_UE(p_bitctx, &cur_pps->num_slice_groups_minus1); + VAL_CHECK(ret, cur_pps->num_slice_groups_minus1 <= 1); + READ_UE(p_bitctx, &cur_pps->num_ref_idx_l0_default_active_minus1); + VAL_CHECK(ret, cur_pps->num_ref_idx_l0_default_active_minus1 < 32); + READ_UE(p_bitctx, &cur_pps->num_ref_idx_l1_default_active_minus1); + VAL_CHECK(ret, cur_pps->num_ref_idx_l1_default_active_minus1 < 32); + READ_ONEBIT(p_bitctx, &cur_pps->weighted_pred_flag); + READ_BITS(p_bitctx, 2, &cur_pps->weighted_bipred_idc); + VAL_CHECK(ret, cur_pps->weighted_bipred_idc < 3); + READ_SE(p_bitctx, &cur_pps->pic_init_qp_minus26); + READ_SE(p_bitctx, &cur_pps->pic_init_qs_minus26); + READ_SE(p_bitctx, &cur_pps->chroma_qp_index_offset); + cur_pps->second_chroma_qp_index_offset = cur_pps->chroma_qp_index_offset; + READ_ONEBIT(p_bitctx, &cur_pps->deblocking_filter_control_present_flag); + READ_ONEBIT(p_bitctx, &cur_pps->constrained_intra_pred_flag); + READ_ONEBIT(p_bitctx, &cur_pps->redundant_pic_cnt_present_flag); + VAL_CHECK(ret , cur_pps->redundant_pic_cnt_present_flag == 0); + + if (mpp_has_more_rbsp_data(p_bitctx)) { + READ_ONEBIT(p_bitctx, &cur_pps->transform_8x8_mode_flag); + READ_ONEBIT(p_bitctx, &cur_pps->pic_scaling_matrix_present_flag); + if (cur_pps->pic_scaling_matrix_present_flag) { + H264D_WARNNING("Picture scaling matrix present."); + FUN_CHECK(ret = parse_pps_calingLists(p_bitctx, cur_sps, cur_pps)); + } + READ_SE(p_bitctx, &cur_pps->second_chroma_qp_index_offset); + } else { + cur_pps->transform_8x8_mode_flag = 0; + cur_pps->second_chroma_qp_index_offset = cur_pps->chroma_qp_index_offset; + } + cur_pps->Valid = 1; + + return ret = MPP_OK; + +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + + return ret; +} + + +/*! +*********************************************************************** +* \brief +* parser pps and process pps +*********************************************************************** +*/ +//extern "C" +MPP_RET process_pps(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + H264_PPS_t *cur_pps = &p_Cur->pps; + + reset_curpps_data(cur_pps);// reset + + FUN_CHECK(ret = parser_pps(p_bitctx, &p_Cur->sps, cur_pps)); + //!< MakePPSavailable + ASSERT(cur_pps->Valid == 1); + if (!currSlice->p_Vid->ppsSet[cur_pps->pic_parameter_set_id]) { + currSlice->p_Vid->ppsSet[cur_pps->pic_parameter_set_id] = mpp_calloc(H264_PPS_t, 1); + } + + memcpy(currSlice->p_Vid->ppsSet[cur_pps->pic_parameter_set_id], cur_pps, sizeof(H264_PPS_t)); + p_Cur->p_Vid->spspps_update = 1; + + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET activate_pps(H264dVideoCtx_t *p_Vid, H264_PPS_t *pps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, !p_Vid && !pps); + if (p_Vid->active_pps != pps) { + if (p_Vid->dec_pic) { + //!< return if the last picture has already been finished + FUN_CHECK(ret = exit_picture(p_Vid, &p_Vid->dec_pic)); + } + p_Vid->active_pps = pps; + } +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* parser nal prefix +*********************************************************************** +*/ +//extern "C" +MPP_RET process_prefix(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + H264_PREFIX_t *cur_prefix = &p_Cur->prefix; + + if (currSlice->nal_reference_idc) { + READ_ONEBIT(p_bitctx, &cur_prefix->store_ref_base_pic_flag); + + if ((currSlice->svcExt.use_ref_base_pic_flag || + cur_prefix->store_ref_base_pic_flag) && + !currSlice->svcExt.idr_flag) { + H264D_LOG("read dec_ref_base_pic_marking\n"); + } + } + + return ret = MPP_OK; +__BITREAD_ERR: + return p_bitctx->ret; +} diff --git a/mpp/codec/dec/h264/h264d_pps.h b/mpp/codec/dec/h264/h264d_pps.h index 4789254dc..614100dc9 100644 --- a/mpp/codec/dec/h264/h264d_pps.h +++ b/mpp/codec/dec/h264/h264d_pps.h @@ -1,39 +1,39 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef _H264D_PPS_H_ -#define _H264D_PPS_H_ - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_global.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET process_pps(H264_SLICE_t *currSlice); -MPP_RET activate_pps(H264dVideoCtx_t *p_Vid, H264_PPS_t *pps); - -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of _H264D_PPS_H_ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_PPS_H +#define H264D_PPS_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET process_pps(H264_SLICE_t *currSlice); +MPP_RET activate_pps(H264dVideoCtx_t *p_Vid, H264_PPS_t *pps); +MPP_RET process_prefix(H264_SLICE_t *currSlice); +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of H264D_PPS_H */ + diff --git a/mpp/codec/dec/h264/h264d_scalist.c b/mpp/codec/dec/h264/h264d_scalist.c index f2b690aad..bc4e96763 100644 --- a/mpp/codec/dec/h264/h264d_scalist.c +++ b/mpp/codec/dec/h264/h264d_scalist.c @@ -1,347 +1,357 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include - -#include "h264d_bitread.h" -#include "h264d_scalist.h" - - - -static RK_U8 ZZ_SCAN[16] = -{ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 }; - -static RK_U8 ZZ_SCAN8[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 -}; - -static RK_S32 Default4x4Intra[H264ScalingList4x4Length] = -{ 6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42 }; - -static RK_S32 Default4x4Inter[H264ScalingList4x4Length] = -{ 10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34 }; - -static RK_S32 Default8x8Intra[H264ScalingList8x8Length] = { - 6, 10, 13, 16, 18, 23, 25, 27, 10, 11, 16, 18, 23, 25, 27, 29, - 13, 16, 18, 23, 25, 27, 29, 31, 16, 18, 23, 25, 27, 29, 31, 33, - 18, 23, 25, 27, 29, 31, 33, 36, 23, 25, 27, 29, 31, 33, 36, 38, - 25, 27, 29, 31, 33, 36, 38, 40, 27, 29, 31, 33, 36, 38, 40, 42 -}; - -static RK_S32 Default8x8Inter[H264ScalingList8x8Length] = { - 9, 13, 15, 17, 19, 21, 22, 24, 13, 13, 17, 19, 21, 22, 24, 25, - 15, 17, 19, 21, 22, 24, 25, 27, 17, 19, 21, 22, 24, 25, 27, 28, - 19, 21, 22, 24, 25, 27, 28, 30, 21, 22, 24, 25, 27, 28, 30, 32, - 22, 24, 25, 27, 28, 30, 32, 33, 24, 25, 27, 28, 30, 32, 33, 35 -}; - -static RK_S32 Default4x4[16] = -{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; - -static RK_S32 Default8x8[64] = { - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 -}; - - -static void set_sps_scanlist_matrix(H264_SPS_t *sps, H264dVideoCtx_t *p_Vid) -{ - RK_S32 i = 0; - - for (i = 0; i < 6; ++i) { - if (!sps->seq_scaling_list_present_flag[i]) { // fall-back rule A - if (i == 0) { - p_Vid->qmatrix[i] = Default4x4Intra; - } else if (i == 3) { - p_Vid->qmatrix[i] = Default4x4Inter; - } else { - p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 1]; - } - } else { - if (sps->UseDefaultScalingMatrix4x4Flag[i]) { - - p_Vid->qmatrix[i] = (i < 3) ? Default4x4Intra : Default4x4Inter; - } else { - p_Vid->qmatrix[i] = sps->ScalingList4x4[i]; - } - } - } - - for (i = 6; i < ((sps->chroma_format_idc != YUV444) ? 8 : 12); ++i) { - if (!sps->seq_scaling_list_present_flag[i]) { // fall-back rule A - if (i == 6) { - p_Vid->qmatrix[i] = Default8x8Intra; - } else if (i == 7) { - p_Vid->qmatrix[i] = Default8x8Inter; - } else { - p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 2]; - } - } else { - if (sps->UseDefaultScalingMatrix8x8Flag[i - 6]) { - - p_Vid->qmatrix[i] = (i == 6 || i == 8 || i == 10) ? Default8x8Intra : Default8x8Inter; - } else { - p_Vid->qmatrix[i] = sps->ScalingList8x8[i - 6]; - } - } - } -} - -static void set_pps_scanlist_matrix(H264_SPS_t *sps, H264_PPS_t *pps, H264dVideoCtx_t *p_Vid) -{ - RK_S32 i = 0; - - for (i = 0; i < 6; ++i) { - if (!pps->pic_scaling_list_present_flag[i]) { // fall-back rule B - if (i == 0) { - if (!sps->seq_scaling_matrix_present_flag) { - p_Vid->qmatrix[i] = Default4x4Intra; - } - } else if (i == 3) { - if (!sps->seq_scaling_matrix_present_flag) { - p_Vid->qmatrix[i] = Default4x4Inter; - } - } else { - p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 1]; - } - } else { - if (pps->UseDefaultScalingMatrix4x4Flag[i]) { - p_Vid->qmatrix[i] = (i < 3) ? Default4x4Intra : Default4x4Inter; - } else { - p_Vid->qmatrix[i] = pps->ScalingList4x4[i]; - } - } - } - for (i = 6; i < ((sps->chroma_format_idc != YUV444) ? 8 : 12); ++i) { - if (!pps->pic_scaling_list_present_flag[i]) { // fall-back rule B - if (i == 6) { - if (!sps->seq_scaling_matrix_present_flag) { - p_Vid->qmatrix[i] = Default8x8Intra; - } - } else if (i == 7) { - if (!sps->seq_scaling_matrix_present_flag) - p_Vid->qmatrix[i] = Default8x8Inter; - } else - p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 2]; - } else { - if (pps->UseDefaultScalingMatrix8x8Flag[i - 6]) { - p_Vid->qmatrix[i] = (i == 6 || i == 8 || i == 10) ? Default8x8Intra : Default8x8Inter; - } else { - p_Vid->qmatrix[i] = pps->ScalingList8x8[i - 6]; - } - } - } -} - -/*! -*********************************************************************** -* \brief -* check profile -*********************************************************************** -*/ -//extern "C" -RK_U32 is_prext_profile(RK_U32 profile_idc) -{ - return (profile_idc >= FREXT_HP || profile_idc == FREXT_CAVLC444) ? 1 : 0; -} - -/*! -*********************************************************************** -* \brief -* parse sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET parse_scalingList(BitReadCtx_t *p_bitctx, RK_S32 size, RK_S32 *scaling_list, RK_S32 *use_default) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - RK_S32 last_scale = 8; - RK_S32 next_scale = 8; - RK_S32 delta_scale = 0; - RK_S32 j = 0, scanj = 0; - - RK_U8 *zz_scan = (size > 16) ? ZZ_SCAN8 : ZZ_SCAN; - - *use_default = 0; - for (j = 0; j < size; ++j) { - scanj = zz_scan[j]; - if (next_scale != 0) { - READ_SE(ret, p_bitctx, &delta_scale, "delta_scale"); - CHECK_RANGE(ret, p_bitctx, delta_scale, -128, 127); - next_scale = (last_scale + delta_scale + 256) & 0xff; - *use_default = (scanj == 0 && next_scale == 0) ? 1 : 0; - } - scaling_list[scanj] = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list[scanj]; - } - - return ret = MPP_OK; -__FAILED: - return ret; -} - - -/*! -*********************************************************************** -* \brief -* parse sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET get_max_dec_frame_buf_size(H264_SPS_t *sps) -{ - RK_S32 size = 0; - RK_S32 pic_size = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - - switch (sps->level_idc) { - case 9: - size = 152064; - break; - case 10: - size = 152064; - break; - case 11: - if (sps->constrained_set3_flag && !is_prext_profile(sps->profile_idc)) { - size = 152064; - } else { - size = 345600; - } - break; - case 12: - size = 912384; - break; - case 13: - size = 912384; - break; - case 20: - size = 912384; - break; - case 21: - size = 1824768; - break; - case 22: - size = 3110400; - break; - case 30: - size = 3110400; - break; - case 31: - size = 6912000; - break; - case 32: - size = 7864320; - break; - case 40: - size = 12582912; - break; - case 41: - size = 12582912; - break; - case 42: - size = 13369344; - break; - case 50: - size = 42393600; - break; - case 51: - size = 70778880; - break; - case 52: - size = 70778880; - break; - default: - ASSERT(0); // undefined level - return ret = MPP_NOK; - } - pic_size = (sps->pic_width_in_mbs_minus1 + 1) - * (sps->pic_height_in_map_units_minus1 + 1) - * (sps->frame_mbs_only_flag ? 1 : 2) * 384; - size /= pic_size; - size = min(size, 16); - sps->max_dec_frame_buffering = size; - - return ret = MPP_OK; -} - -/*! -*********************************************************************** -* \brief -* parse sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET parse_sps_scalinglists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps) -{ - RK_S32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - // Parse scaling_list4x4. - for (i = 0; i < 6; ++i) { - READ_ONEBIT(ret, p_bitctx, &sps->seq_scaling_list_present_flag[i], "seq_scaling_list_present_flag"); - - if (sps->seq_scaling_list_present_flag[i]) { - FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList4x4Length, - sps->ScalingList4x4[i], &sps->UseDefaultScalingMatrix4x4Flag[i])); - } - } - // Parse scaling_list8x8. - for (i = 0; i < ((sps->chroma_format_idc != YUV444) ? 2 : 6); ++i) { - READ_ONEBIT(ret, p_bitctx, &sps->seq_scaling_list_present_flag[6 + i], "seq_scaling_list_present_flag"); - if (sps->seq_scaling_list_present_flag[6 + i]) { - FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList8x8Length, - sps->ScalingList8x8[i], &sps->UseDefaultScalingMatrix8x8Flag[i])); - } - } - - return ret = MPP_OK; -__FAILED: - return ret; -} -/*! -*********************************************************************** -* \brief -* prepare scanlist info to register syntax -*********************************************************************** -*/ -//extern "C" -MPP_RET prepare_init_scanlist(H264_SLICE_t *currSlice) -{ - RK_S32 i = 0; - H264_SPS_t *sps = currSlice->p_Vid->active_sps; - H264_PPS_t *pps = currSlice->p_Vid->active_pps; - - if (!pps->pic_scaling_matrix_present_flag && !sps->seq_scaling_matrix_present_flag) { - for (i = 0; i < 12; i++) { - currSlice->p_Vid->qmatrix[i] = (i < 6) ? Default4x4 : Default8x8; - } - } else { - if (sps->seq_scaling_matrix_present_flag) { // check sps first - set_sps_scanlist_matrix(sps, currSlice->p_Vid); - } - if (pps->pic_scaling_matrix_present_flag) { // then check pps - set_pps_scanlist_matrix(sps, pps, currSlice->p_Vid); - } - } - return MPP_OK; -} +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include + +#include "h264d_scalist.h" + + + +static RK_U8 ZZ_SCAN[16] = +{ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 }; + +static RK_U8 ZZ_SCAN8[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +static RK_S32 Default4x4Intra[H264ScalingList4x4Length] = +{ 6, 13, 20, 28, 13, 20, 28, 32, 20, 28, 32, 37, 28, 32, 37, 42 }; + +static RK_S32 Default4x4Inter[H264ScalingList4x4Length] = +{ 10, 14, 20, 24, 14, 20, 24, 27, 20, 24, 27, 30, 24, 27, 30, 34 }; + +static RK_S32 Default8x8Intra[H264ScalingList8x8Length] = { + 6, 10, 13, 16, 18, 23, 25, 27, 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static RK_S32 Default8x8Inter[H264ScalingList8x8Length] = { + 9, 13, 15, 17, 19, 21, 22, 24, 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, 24, 25, 27, 28, 30, 32, 33, 35 +}; + +static RK_S32 Default4x4[16] = +{ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; + +static RK_S32 Default8x8[64] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + + +static void set_sps_scanlist_matrix(H264_SPS_t *sps, H264dVideoCtx_t *p_Vid) +{ + RK_S32 i = 0; + + for (i = 0; i < 6; ++i) { + if (!sps->seq_scaling_list_present_flag[i]) { // fall-back rule A + if (i == 0) { + p_Vid->qmatrix[i] = Default4x4Intra; + } else if (i == 3) { + p_Vid->qmatrix[i] = Default4x4Inter; + } else { + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 1]; + } + } else { + if (sps->UseDefaultScalingMatrix4x4Flag[i]) { + + p_Vid->qmatrix[i] = (i < 3) ? Default4x4Intra : Default4x4Inter; + } else { + p_Vid->qmatrix[i] = sps->ScalingList4x4[i]; + } + } + } + + for (i = 6; i < ((sps->chroma_format_idc != H264_CHROMA_444) ? 8 : 12); ++i) { + if (!sps->seq_scaling_list_present_flag[i]) { // fall-back rule A + if (i == 6) { + p_Vid->qmatrix[i] = Default8x8Intra; + } else if (i == 7) { + p_Vid->qmatrix[i] = Default8x8Inter; + } else { + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 2]; + } + } else { + if (sps->UseDefaultScalingMatrix8x8Flag[i - 6]) { + + p_Vid->qmatrix[i] = (i == 6 || i == 8 || i == 10) ? Default8x8Intra : Default8x8Inter; + } else { + p_Vid->qmatrix[i] = sps->ScalingList8x8[i - 6]; + } + } + } +} + +static void set_pps_scanlist_matrix(H264_SPS_t *sps, H264_PPS_t *pps, H264dVideoCtx_t *p_Vid) +{ + RK_S32 i = 0; + + for (i = 0; i < 6; ++i) { + if (!pps->pic_scaling_list_present_flag[i]) { // fall-back rule B + if (i == 0) { + if (!sps->seq_scaling_matrix_present_flag) { + p_Vid->qmatrix[i] = Default4x4Intra; + } + } else if (i == 3) { + if (!sps->seq_scaling_matrix_present_flag) { + p_Vid->qmatrix[i] = Default4x4Inter; + } + } else { + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 1]; + } + } else { + if (pps->UseDefaultScalingMatrix4x4Flag[i]) { + p_Vid->qmatrix[i] = (i < 3) ? Default4x4Intra : Default4x4Inter; + } else { + p_Vid->qmatrix[i] = pps->ScalingList4x4[i]; + } + } + } + for (i = 6; i < ((sps->chroma_format_idc != H264_CHROMA_444) ? 8 : 12); ++i) { + if (!pps->pic_scaling_list_present_flag[i]) { // fall-back rule B + if (i == 6) { + if (!sps->seq_scaling_matrix_present_flag) { + p_Vid->qmatrix[i] = Default8x8Intra; + } + } else if (i == 7) { + if (!sps->seq_scaling_matrix_present_flag) + p_Vid->qmatrix[i] = Default8x8Inter; + } else + p_Vid->qmatrix[i] = p_Vid->qmatrix[i - 2]; + } else { + if (pps->UseDefaultScalingMatrix8x8Flag[i - 6]) { + p_Vid->qmatrix[i] = (i == 6 || i == 8 || i == 10) ? Default8x8Intra : Default8x8Inter; + } else { + p_Vid->qmatrix[i] = pps->ScalingList8x8[i - 6]; + } + } + } +} + +/*! +*********************************************************************** +* \brief +* check profile +*********************************************************************** +*/ +//extern "C" +RK_U32 is_prext_profile(RK_U32 profile_idc) +{ + return (profile_idc >= H264_PROFILE_HIGH || profile_idc == H264_PROFILE_FREXT_CAVLC444) ? 1 : 0; +} + +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET parse_scalingList(BitReadCtx_t *p_bitctx, RK_S32 size, RK_S32 *scaling_list, RK_S32 *use_default) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 last_scale = 8; + RK_S32 next_scale = 8; + RK_S32 delta_scale = 0; + RK_S32 j = 0, scanj = 0; + + RK_U8 *zz_scan = (size > 16) ? ZZ_SCAN8 : ZZ_SCAN; + + *use_default = 0; + for (j = 0; j < size; ++j) { + scanj = zz_scan[j]; + if (next_scale != 0) { + READ_SE(p_bitctx, &delta_scale); + next_scale = (last_scale + delta_scale + 256) & 0xff; + *use_default = (scanj == 0 && next_scale == 0) ? 1 : 0; + } + scaling_list[scanj] = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list[scanj]; + } + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; + return ret; +} + + +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET get_max_dec_frame_buf_size(H264_SPS_t *sps) +{ + RK_S32 size = 0; + RK_S32 pic_size = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + + + switch (sps->level_idc) { + case 9: + size = 152064; + break; + case 10: + size = 152064; + break; + case 11: + if (sps->constrained_set3_flag && !is_prext_profile(sps->profile_idc)) { + size = 152064; + } else { + size = 345600; + } + break; + case 12: + size = 912384; + break; + case 13: + size = 912384; + break; + case 20: + size = 912384; + break; + case 21: + size = 1824768; + break; + case 22: + size = 3110400; + break; + case 30: + size = 3110400; + break; + case 31: + size = 6912000; + break; + case 32: + size = 7864320; + break; + case 40: + size = 12582912; + break; + case 41: + size = 12582912; + break; + case 42: + size = 13369344; + break; + case 50: + size = 42393600; + break; + case 51: + size = 70778880; + break; + case 52: + size = 70778880; + break; + case 60: + size = 267386880; + break; + case 61: + size = 267386880; + break; + case 62: + size = 267386880; + break; + default: + ASSERT(0); // undefined level + return ret = MPP_NOK; + } + pic_size = (sps->pic_width_in_mbs_minus1 + 1) + * (sps->pic_height_in_map_units_minus1 + 1) + * (sps->frame_mbs_only_flag ? 1 : 2) * 384; + size /= pic_size; + size = MPP_MIN(size, 16); + sps->max_dec_frame_buffering = size; + + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* parse sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET parse_sps_scalinglists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps) +{ + RK_S32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + // Parse scaling_list4x4. + for (i = 0; i < 6; ++i) { + READ_ONEBIT(p_bitctx, &sps->seq_scaling_list_present_flag[i]); + + if (sps->seq_scaling_list_present_flag[i]) { + FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList4x4Length, + sps->ScalingList4x4[i], &sps->UseDefaultScalingMatrix4x4Flag[i])); + } + } + // Parse scaling_list8x8. + for (i = 0; i < ((sps->chroma_format_idc != H264_CHROMA_444) ? 2 : 6); ++i) { + READ_ONEBIT(p_bitctx, &sps->seq_scaling_list_present_flag[6 + i]); + if (sps->seq_scaling_list_present_flag[6 + i]) { + FUN_CHECK(ret = parse_scalingList(p_bitctx, H264ScalingList8x8Length, + sps->ScalingList8x8[i], &sps->UseDefaultScalingMatrix8x8Flag[i])); + } + } + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief +* prepare scanlist info to register syntax +*********************************************************************** +*/ +//extern "C" +MPP_RET prepare_init_scanlist(H264_SLICE_t *currSlice) +{ + RK_S32 i = 0; + H264_SPS_t *sps = currSlice->p_Vid->active_sps; + H264_PPS_t *pps = currSlice->p_Vid->active_pps; + + if (!pps->pic_scaling_matrix_present_flag && !sps->seq_scaling_matrix_present_flag) { + for (i = 0; i < 12; i++) { + currSlice->p_Vid->qmatrix[i] = (i < 6) ? Default4x4 : Default8x8; + } + } else { + if (sps->seq_scaling_matrix_present_flag) { // check sps first + set_sps_scanlist_matrix(sps, currSlice->p_Vid); + } + if (pps->pic_scaling_matrix_present_flag) { // then check pps + set_pps_scanlist_matrix(sps, pps, currSlice->p_Vid); + } + } + return MPP_OK; +} diff --git a/mpp/codec/dec/h264/h264d_scalist.h b/mpp/codec/dec/h264/h264d_scalist.h index 6744e89c6..7eca15b16 100644 --- a/mpp/codec/dec/h264/h264d_scalist.h +++ b/mpp/codec/dec/h264/h264d_scalist.h @@ -1,41 +1,41 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#ifndef _H264D_SCALIST_H_ -#define _H264D_SCALIST_H_ - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_global.h" - - -#ifdef __cplusplus -extern "C" { -#endif -RK_U32 is_prext_profile(RK_U32 profile_idc); -MPP_RET get_max_dec_frame_buf_size(H264_SPS_t *sps); -MPP_RET parse_scalingList(BitReadCtx_t *p_bitctx, RK_S32 size, RK_S32 *scaling_list, RK_S32 *use_default); -MPP_RET parse_sps_scalinglists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps); -MPP_RET prepare_init_scanlist(H264_SLICE_t *currSlice); -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of _H264D_SCALIST_H_ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef H264D_SCALIST_H +#define H264D_SCALIST_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif +RK_U32 is_prext_profile(RK_U32 profile_idc); +MPP_RET get_max_dec_frame_buf_size(H264_SPS_t *sps); +MPP_RET parse_scalingList(BitReadCtx_t *p_bitctx, RK_S32 size, RK_S32 *scaling_list, RK_S32 *use_default); +MPP_RET parse_sps_scalinglists(BitReadCtx_t *p_bitctx, H264_SPS_t *sps); +MPP_RET prepare_init_scanlist(H264_SLICE_t *currSlice); +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of H264D_SCALIST_H */ + diff --git a/mpp/codec/dec/h264/h264d_sei.c b/mpp/codec/dec/h264/h264d_sei.c index 6a48d8a5d..2ae3b7192 100644 --- a/mpp/codec/dec/h264/h264d_sei.c +++ b/mpp/codec/dec/h264/h264d_sei.c @@ -1,394 +1,321 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#include -#include - -#include "h264d_log.h" -#include "h264d_bitread.h" -#include "h264d_sps.h" -#include "h264d_sei.h" - -#define MODULE_TAG "h264d_sei" - -static void interpret_spare_pic() -{ - -} -static void interpret_subsequence_info() -{ - -} -static void interpret_subsequence_layer_characteristics_info() -{ - -} -static void interpret_subsequence_characteristics_info() -{ - -} -static void interpret_scene_information() -{ - -} -static void interpret_user_data_registered_itu_t_t35_info() -{ - -} -static void interpret_user_data_unregistered_info() -{ - -} -static void interpret_pan_scan_rect_info() -{ - -} -static void interpret_filler_payload_info() -{ - -} -static void interpret_dec_ref_pic_marking_repetition_info() -{ - -} -static void interpret_full_frame_freeze_info() -{ - -} -static void interpret_full_frame_freeze_release_info() -{ - -} -static void interpret_full_frame_snapshot_info() -{ - -} -static void interpret_progressive_refinement_start_info() -{ - -} -static void interpret_progressive_refinement_end_info() -{ - -} -static void interpret_motion_constrained_slice_group_set_info() -{ - -} -static void interpret_picture_timing_info() -{ - -} -static void interpret_film_grain_characteristics_info() -{ - -} -static void interpret_deblocking_filter_display_preference_info() -{ - -} -static void interpret_stereo_video_info_info() -{ - -} -static void interpret_post_filter_hints_info() -{ - -} -static void interpret_tone_mapping() -{ - -} -static void interpret_frame_packing_arrangement_info() -{ - -} -static void interpret_mvc_scalability_info() -{ - -} - -static MPP_RET interpret_recovery_point_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - set_bitread_ctx(p_bitctx, payload, size); - - READ_UE(ret, p_bitctx, &sei_msg->recovery_point.recovery_frame_cnt, "recovery_frame_cnt"); - READ_ONEBIT(ret, p_bitctx, &sei_msg->recovery_point.exact_match_flag, "exact_match_flag"); - READ_ONEBIT(ret, p_bitctx, &sei_msg->recovery_point.broken_link_flag, "broken_link_flag"); - READ_BITS(ret, p_bitctx, 2, &sei_msg->recovery_point.changing_slice_group_idc, "changing_slice_group_idc"); - - return ret = MPP_OK; -__FAILED: - return ret; -} - - -static MPP_RET interpret_mvc_scalable_nesting_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) -{ - RK_S32 i; - RK_U32 operation_point_flag; - RK_U32 all_view_components_in_au_flag; - RK_S32 num_view_components_minus1; - RK_S32 sei_view_id; - RK_S32 num_view_components_op_minus1; - RK_S32 sei_op_view_id; - RK_S32 sei_op_temporal_id; - MPP_RET ret = MPP_ERR_UNKNOW; - - BitReadCtx_t tmp_strmdata = { 0 }; - BitReadCtx_t *p_strm = &tmp_strmdata; - set_bitread_ctx(p_strm, payload, size); - - READ_ONEBIT(ret, p_strm, &operation_point_flag, "operation_point_flag"); - if (!operation_point_flag) { - READ_ONEBIT(ret, p_strm, &all_view_components_in_au_flag, "all_view_components_in_au_flag"); - READ_UE(ret, p_strm, &num_view_components_minus1, "num_view_components_minus1"); - for (i = 0; i <= num_view_components_minus1; i++) { - READ_BITS(ret, p_strm, 10, &sei_view_id, "sei_view_id"); - } - } else { - READ_UE(ret, p_strm, &num_view_components_op_minus1, "num_view_components_op_minus1"); - for (i = 0; i <= num_view_components_op_minus1; i++) { - READ_BITS(ret, p_strm, 10, &sei_op_view_id, "sei_op_view_id"); - } - READ_BITS(ret, p_strm, 3, &sei_op_temporal_id, "sei_op_temporal_id"); - } - - p_bitctx->used_bits = p_strm->used_bits; - sei_msg->mvc_scalable_nesting_flag = 1; - return ret = MPP_OK; -__FAILED: - return ret; -} - -static MPP_RET interpret_buffering_period_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - BitReadCtx_t tmp_strmdata = { 0 }; - - p_bitctx = &tmp_strmdata; - set_bitread_ctx(p_bitctx, payload, size); - READ_UE(ret, p_bitctx, &sei_msg->seq_parameter_set_id, "seq_parameter_set_id"); - - return ret = MPP_OK; -__FAILED: - return ret; - -} - -static void interpret_reserved_info(RK_U8 *payload, RK_S32 size, BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg) -{ - RK_S32 offset = 0; - RK_U8 payload_byte = 0; - - while (offset < size) { - payload_byte = payload[offset]; - offset++; - } - (void)p_bitctx; - (void)sei_msg; - (void)payload_byte; -} - -static MPP_RET parserSEI(BitReadCtx_t *p_bitctx, H264_SEI_t *sei_msg, RK_U8 *msg) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - //!< sei_payload( type, size ); - switch (sei_msg->type) { - case SEI_BUFFERING_PERIOD: - FUN_CHECK(ret = interpret_buffering_period_info(msg, sei_msg->payload_size, p_bitctx, sei_msg)); - break; - case SEI_PIC_TIMING: - interpret_picture_timing_info(); - break; - case SEI_PAN_SCAN_RECT: - interpret_pan_scan_rect_info(); - break; - case SEI_FILLER_PAYLOAD: - interpret_filler_payload_info(); - break; - case SEI_USER_DATA_REGISTERED_ITU_T_T35: - interpret_user_data_registered_itu_t_t35_info(); - break; - case SEI_USER_DATA_UNREGISTERED: - interpret_user_data_unregistered_info(); - break; - case SEI_RECOVERY_POINT: - FUN_CHECK(ret = interpret_recovery_point_info(msg, sei_msg->payload_size, p_bitctx, sei_msg)); - break; - case SEI_DEC_REF_PIC_MARKING_REPETITION: - interpret_dec_ref_pic_marking_repetition_info(); - break; - case SEI_SPARE_PIC: - interpret_spare_pic(); - break; - case SEI_SCENE_INFO: - interpret_scene_information(); - break; - case SEI_SUB_SEQ_INFO: - interpret_subsequence_info(); - break; - case SEI_SUB_SEQ_LAYER_CHARACTERISTICS: - interpret_subsequence_layer_characteristics_info(); - break; - case SEI_SUB_SEQ_CHARACTERISTICS: - interpret_subsequence_characteristics_info(); - break; - case SEI_FULL_FRAME_FREEZE: - interpret_full_frame_freeze_info(); - break; - case SEI_FULL_FRAME_FREEZE_RELEASE: - interpret_full_frame_freeze_release_info(); - break; - case SEI_FULL_FRAME_SNAPSHOT: - interpret_full_frame_snapshot_info(); - break; - case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START: - interpret_progressive_refinement_start_info(); - break; - case SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END: - interpret_progressive_refinement_end_info(); - break; - case SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET: - interpret_motion_constrained_slice_group_set_info(); - case SEI_FILM_GRAIN_CHARACTERISTICS: - interpret_film_grain_characteristics_info(); - break; - case SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE: - interpret_deblocking_filter_display_preference_info(); - break; - case SEI_STEREO_VIDEO_INFO: - interpret_stereo_video_info_info(); - break; - case SEI_TONE_MAPPING: - interpret_tone_mapping(); - break; - case SEI_POST_FILTER_HINTS: - interpret_post_filter_hints_info(); - break; - case SEI_FRAME_PACKING_ARRANGEMENT: - interpret_frame_packing_arrangement_info(); - break; - case SEI_MVC_SCALABLE_NESTING: - FUN_CHECK(ret = interpret_mvc_scalable_nesting_info(msg, sei_msg->payload_size, p_bitctx, sei_msg)); - break; - case SEI_VIEW_SCALABILITY_INFO: - interpret_mvc_scalability_info(); - break; - default: - interpret_reserved_info(msg, sei_msg->payload_size, p_bitctx, sei_msg); - break; - } - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static MPP_RET analysisSEI(H264_SLICE_t *cur_slice) -{ - H264_SPS_t *sps = NULL; - H264_subSPS_t *subset_sps = NULL; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dVideoCtx_t *p_Vid = cur_slice->p_Vid; - H264_SEI_t *sei_msg = &cur_slice->p_Cur->sei; - - switch (sei_msg->type) { // sei_payload( type, size ) - case SEI_BUFFERING_PERIOD: - if (sei_msg->mvc_scalable_nesting_flag) { - p_Vid->active_mvc_sps_flag = 1; - sps = NULL; - subset_sps = &p_Vid->subspsSet[sei_msg->seq_parameter_set_id]; - } else { - p_Vid->active_mvc_sps_flag = 0; - sps = &p_Vid->spsSet[sei_msg->seq_parameter_set_id]; - subset_sps = NULL; - } - p_Vid->exit_picture_flag = 1; - FUN_CHECK(ret = activate_sps(p_Vid, sps, subset_sps)); - break; - default: - - break; - } - - return ret = MPP_OK; - -__FAILED: - return ret; -} - -/*! -*********************************************************************** -* \brief -* parse SEI information -*********************************************************************** -*/ -//extern "C" -MPP_RET process_sei(H264_SLICE_t *currSlice) -{ - RK_S32 nn = 0; - RK_S32 tmp_byte = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264_SEI_t *sei_msg = &currSlice->p_Cur->sei; - BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; - - FunctionIn(currSlice->logctx->parr[RUN_PARSE]); - memset(sei_msg, 0, sizeof(*sei_msg)); - sei_msg->mvc_scalable_nesting_flag = 0; //init to false - - do { - sei_msg->type = 0; - READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_byte"); - while (tmp_byte == 0xFF) { - sei_msg->type += 255; - READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_type"); - } - sei_msg->type += tmp_byte; // this is the last byte - - sei_msg->payload_size = 0; - READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_type"); - while (tmp_byte == 0xFF) { - sei_msg->payload_size += 255; - READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_type"); - } - sei_msg->payload_size += tmp_byte; // this is the last byte - - //--- read sei info - FUN_CHECK(ret = parserSEI(p_bitctx, sei_msg, p_bitctx->data_)); - //--- analysis sei info - FUN_CHECK(ret = analysisSEI(currSlice)); - //--- set offset to read next sei nal - if (SEI_MVC_SCALABLE_NESTING == sei_msg->type) { - sei_msg->payload_size = ((p_bitctx->used_bits + 0x07) >> 3); - } - for (nn = 0; nn < sei_msg->payload_size; nn++) { // read bytes - READ_BITS(ret, p_bitctx, 8, &tmp_byte, "tmp_byte"); - } - - } while ((p_bitctx->data_[0] != 0x80) && (p_bitctx->bytes_left_ > 1)); // more_rbsp_data() msg[offset] != 0x80 - - FunctionOut(currSlice->logctx->parr[RUN_PARSE]); - - return ret = MPP_OK; - -__FAILED: - ASSERT(0); - return ret; -} +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_sei" + +#include +#include +#include + +#include "h264d_global.h" +#include "h264d_sps.h" +#include "h264d_sei.h" +#include "h2645d_sei.h" + +static MPP_RET interpret_picture_timing_info( + BitReadCtx_t *p_bitctx, + H264_SEI_t *sei_msg, + H264dVideoCtx_t *p_videoctx) +{ + RK_S32 cpb_removal_delay_length = 0; + RK_S32 dpb_output_delay_length = 0; + RK_S32 time_offset_length = 0; + RK_S32 cpb_dpb_delays_present_flag = 0; + RK_U32 i = 0; + H264_SEI_PIC_TIMING_t *pic_timing = NULL; + RK_U32 num_clock_ts[9] = {1, 1, 1, 2, 2, 3, 3, 2, 3}; + struct h264_vui_t *vui_seq_parameters = NULL; + RK_U32 seq_parameter_set_id = sei_msg->seq_parameter_set_id; + + if (seq_parameter_set_id >= MAXSPS || !p_videoctx->spsSet[seq_parameter_set_id]) { + H264D_ERR("seq_parameter_set_id %d may be invalid\n", seq_parameter_set_id); + goto __BITREAD_ERR; + } + vui_seq_parameters = &(p_videoctx->spsSet[sei_msg->seq_parameter_set_id]->vui_seq_parameters); + pic_timing = &(sei_msg->pic_timing); + + if (vui_seq_parameters->nal_hrd_parameters_present_flag) { + cpb_removal_delay_length = + vui_seq_parameters->nal_hrd_parameters.cpb_removal_delay_length_minus1; + dpb_output_delay_length = + vui_seq_parameters->nal_hrd_parameters.dpb_output_delay_length_minus1; + time_offset_length = + vui_seq_parameters->nal_hrd_parameters.time_offset_length; + cpb_dpb_delays_present_flag = 1; + } else if (vui_seq_parameters->vcl_hrd_parameters_present_flag) { + cpb_removal_delay_length = + vui_seq_parameters->vcl_hrd_parameters.cpb_removal_delay_length_minus1; + dpb_output_delay_length = + vui_seq_parameters->vcl_hrd_parameters.dpb_output_delay_length_minus1; + time_offset_length = + vui_seq_parameters->vcl_hrd_parameters.time_offset_length; + cpb_dpb_delays_present_flag = 1; + } + + if (cpb_dpb_delays_present_flag) { + READ_BITS(p_bitctx, cpb_removal_delay_length, &pic_timing->cpb_removal_delay); + READ_BITS(p_bitctx, dpb_output_delay_length, &pic_timing->dpb_output_delay); + } + + if (vui_seq_parameters->pic_struct_present_flag) { + READ_BITS(p_bitctx, 4, &pic_timing->pic_struct); + if (pic_timing->pic_struct > 8 || pic_timing->pic_struct < 0) { + goto __BITREAD_ERR; + } + + for (i = 0; i < num_clock_ts[pic_timing->pic_struct]; i++) { + READ_BITS(p_bitctx, 1, &pic_timing->clock_timestamp_flag[i]); + + if (pic_timing->clock_timestamp_flag[i]) { + READ_BITS(p_bitctx, 2, &pic_timing->ct_type[i]); + READ_BITS(p_bitctx, 1, &pic_timing->nuit_field_based_flag[i]); + + READ_BITS(p_bitctx, 5, &pic_timing->counting_type[i]); + if (pic_timing->counting_type[i] > 6 + || pic_timing->counting_type[i] < 0) { + goto __BITREAD_ERR; + } + + READ_BITS(p_bitctx, 1, &pic_timing->full_timestamp_flag[i]); + READ_BITS(p_bitctx, 1, &pic_timing->discontinuity_flag[i]); + READ_BITS(p_bitctx, 1, &pic_timing->cnt_dropped_flag[i]); + + READ_BITS(p_bitctx, 8, &pic_timing->n_frames[i]); + + if (pic_timing->full_timestamp_flag[i]) { + READ_BITS(p_bitctx, 6, &pic_timing->seconds_value[i]); + if (pic_timing->seconds_value[i] > 59) { + goto __BITREAD_ERR; + } + + READ_BITS(p_bitctx, 6, &pic_timing->minutes_value[i]); + if (pic_timing->minutes_value[i] > 59) { + goto __BITREAD_ERR; + } + + READ_BITS(p_bitctx, 5, &pic_timing->hours_value[i]); + if (pic_timing->hours_value[i] > 23) { + goto __BITREAD_ERR; + } + } else { + READ_BITS(p_bitctx, 1, &pic_timing->seconds_flag[i]); + if (pic_timing->seconds_flag[i]) { + READ_BITS(p_bitctx, 6, &pic_timing->seconds_value[i]); + if (pic_timing->seconds_value[i] > 59) { + goto __BITREAD_ERR; + } + + READ_BITS(p_bitctx, 1, &pic_timing->minutes_flag[i]); + if (pic_timing->minutes_flag[i]) { + READ_BITS(p_bitctx, 6, &pic_timing->minutes_value[i]); + if (pic_timing->minutes_value[i] > 59) { + goto __BITREAD_ERR; + } + + READ_BITS(p_bitctx, 1, &pic_timing->hours_flag[i]); + if (pic_timing->hours_flag[i]) { + READ_BITS(p_bitctx, 5, &pic_timing->hours_value[i]); + if (pic_timing->hours_value[i] > 23) { + goto __BITREAD_ERR; + } + } + } + } + } + if (time_offset_length) { + RK_S32 tmp; + READ_BITS(p_bitctx, time_offset_length, &tmp); + /* following "converts" timeOffsetLength-bit signed + * integer into i32 */ + /*lint -save -e701 -e702 */ + tmp <<= (32 - time_offset_length); + tmp >>= (32 - time_offset_length); + /*lint -restore */ + pic_timing->time_offset[i] = tmp; + } else + pic_timing->time_offset[i] = 0; + } + } + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET interpret_buffering_period_info( + BitReadCtx_t *p_bitctx, + H264_SEI_t *sei_msg, + H264dVideoCtx_t *p_videoctx) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 i = 0; + RK_U32 seq_parameter_set_id = sei_msg->seq_parameter_set_id; + struct h264_vui_t *vui_seq_parameters = NULL; + + READ_UE(p_bitctx, &seq_parameter_set_id); + + if (seq_parameter_set_id >= MAXSPS || !p_videoctx->spsSet[seq_parameter_set_id]) { + H264D_ERR("seq_parameter_set_id %d may be invalid\n", seq_parameter_set_id); + goto __BITREAD_ERR; + } + + sei_msg->seq_parameter_set_id = seq_parameter_set_id; + vui_seq_parameters = &(p_videoctx->spsSet[sei_msg->seq_parameter_set_id]->vui_seq_parameters); + + if (vui_seq_parameters->nal_hrd_parameters_present_flag) { + for (i = 0; i < vui_seq_parameters->nal_hrd_parameters.cpb_cnt_minus1; i++) { + SKIP_BITS(p_bitctx, + vui_seq_parameters->nal_hrd_parameters.initial_cpb_removal_delay_length_minus1); //initial_cpb_removal_delay + SKIP_BITS(p_bitctx, + vui_seq_parameters->nal_hrd_parameters.initial_cpb_removal_delay_length_minus1); //initial_cpb_removal_delay_offset + } + } + + if (vui_seq_parameters->vcl_hrd_parameters_present_flag) { + for (i = 0; i < vui_seq_parameters->vcl_hrd_parameters.cpb_cnt_minus1; i++) { + SKIP_BITS(p_bitctx, + vui_seq_parameters->vcl_hrd_parameters.initial_cpb_removal_delay_length_minus1); //initial_cpb_removal_delay + SKIP_BITS(p_bitctx, + vui_seq_parameters->vcl_hrd_parameters.initial_cpb_removal_delay_length_minus1); //initial_cpb_removal_delay_offset + } + } + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; + return ret; + +} + +static MPP_RET interpret_recovery_point(BitReadCtx_t *p_bitctx, H264dVideoCtx_t *p_videoctx) +{ + RK_S32 recovery_frame_cnt = 0; + + READ_UE(p_bitctx, &recovery_frame_cnt); + + if (recovery_frame_cnt >= (1 << 16) || recovery_frame_cnt < 0) { + H264D_DBG(H264D_DBG_SEI, "recovery_frame_cnt %d, is out of range %d", + recovery_frame_cnt, p_videoctx->max_frame_num); + return MPP_ERR_STREAM; + } + + memset(&p_videoctx->recovery, 0, sizeof(RecoveryPoint)); + + p_videoctx->recovery.valid_flag = 1; + p_videoctx->recovery.recovery_frame_cnt = recovery_frame_cnt; + H264D_DBG(H264D_DBG_SEI, "Recovery point: frame_cnt %d", p_videoctx->recovery.recovery_frame_cnt); + return MPP_OK; +__BITREAD_ERR: + return p_bitctx->ret; +} + +/*! +*********************************************************************** +* \brief +* parse SEI information +*********************************************************************** +*/ +//extern "C" +MPP_RET process_sei(H264_SLICE_t *currSlice) +{ + RK_S32 tmp_byte = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264_SEI_t *sei_msg = NULL; + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + BitReadCtx_t payload_bitctx; + RK_S32 i = 0; + + if (!currSlice->p_Cur->sei) + currSlice->p_Cur->sei = mpp_calloc(H264_SEI_t, 1); + + sei_msg = currSlice->p_Cur->sei; + sei_msg->mvc_scalable_nesting_flag = 0; //init to false + sei_msg->p_Dec = currSlice->p_Dec; + do { + tmp_byte = 0xFF; + sei_msg->type = 0; + while (tmp_byte == 0xFF) { + if (p_bitctx->bytes_left_ < 2 || sei_msg->type > INT_MAX - 255) { + mpp_err("parse payload_type error: byte_left %d payload_type %d\n", + p_bitctx->bytes_left_, sei_msg->type); + return MPP_ERR_STREAM; + } + + READ_BITS(p_bitctx, 8, &tmp_byte); + sei_msg->type += tmp_byte; + } + + tmp_byte = 0xFF; + sei_msg->payload_size = 0; + while (tmp_byte == 0xFF) { + if ((RK_S32)p_bitctx->bytes_left_ < sei_msg->payload_size + 1) { + mpp_err("parse payload_size error: byte_left %d payload_size %d\n", + p_bitctx->bytes_left_, sei_msg->payload_size + 1); + return MPP_ERR_STREAM; + } + + READ_BITS(p_bitctx, 8, &tmp_byte); + sei_msg->payload_size += tmp_byte; + } + + if ((RK_S32)p_bitctx->bytes_left_ < sei_msg->payload_size) { + mpp_err("parse payload_size error: byte_left %d payload_size %d\n", + p_bitctx->bytes_left_, sei_msg->payload_size); + return MPP_ERR_STREAM; + } + + H264D_DBG(H264D_DBG_SEI, "SEI type %d, payload size: %d\n", sei_msg->type, sei_msg->payload_size); + + memset(&payload_bitctx, 0, sizeof(payload_bitctx)); + mpp_set_bitread_ctx(&payload_bitctx, p_bitctx->data_, sei_msg->payload_size); + mpp_set_bitread_pseudo_code_type(&payload_bitctx, PSEUDO_CODE_H264_H265_SEI); + + switch (sei_msg->type) { + case H264_SEI_BUFFERING_PERIOD: + FUN_CHECK(ret = interpret_buffering_period_info(&payload_bitctx, sei_msg, currSlice->p_Vid)); + break; + case H264_SEI_PIC_TIMING: + FUN_CHECK(interpret_picture_timing_info(&payload_bitctx, sei_msg, currSlice->p_Vid)); + break; + case H264_SEI_USER_DATA_UNREGISTERED: + FUN_CHECK(check_encoder_sei_info(&payload_bitctx, sei_msg->payload_size, &currSlice->p_Vid->deny_flag)); + + if (currSlice->p_Vid->deny_flag) + H264D_DBG(H264D_DBG_SEI, "Bitstream is encoded by special encoder."); + break; + case H264_SEI_RECOVERY_POINT: + FUN_CHECK(interpret_recovery_point(&payload_bitctx, currSlice->p_Vid)); + break; + default: + H264D_DBG(H264D_DBG_SEI, "Skip parsing SEI type %d\n", sei_msg->type); + break; + } + + H264D_DBG(H264D_DBG_SEI, "After parsing SEI %d, bits left int cur byte %d, bits_used %d, bytes left %d", + sei_msg->type, payload_bitctx.num_remaining_bits_in_curr_byte_, payload_bitctx.used_bits, + payload_bitctx.bytes_left_); + + for (i = 0; i < sei_msg->payload_size; i++) + SKIP_BITS(p_bitctx, 8); + } while (mpp_has_more_rbsp_data(p_bitctx)); // more_rbsp_data() msg[offset] != 0x80 + + return ret = MPP_OK; +__BITREAD_ERR: +__FAILED: + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_sei.h b/mpp/codec/dec/h264/h264d_sei.h index fd1fcefbd..b2049452a 100644 --- a/mpp/codec/dec/h264/h264d_sei.h +++ b/mpp/codec/dec/h264/h264d_sei.h @@ -1,37 +1,37 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef _H264D_SEI_H_ -#define _H264D_SEI_H_ - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_global.h" - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET process_sei(H264_SLICE_t *currSlice); - -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of _H264D_SEI_H_ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_SEI_H +#define H264D_SEI_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET process_sei(H264_SLICE_t *currSlice); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* H264D_SEI_H */ + diff --git a/mpp/codec/dec/h264/h264d_slice.c b/mpp/codec/dec/h264/h264d_slice.c index 4ce0cab35..83035dbf5 100644 --- a/mpp/codec/dec/h264/h264d_slice.c +++ b/mpp/codec/dec/h264/h264d_slice.c @@ -1,540 +1,605 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "h264d_slice.h" -#include "h264d_sps.h" -#include "h264d_pps.h" - -#define MODULE_TAG "h264d_slice" - -static void free_slice_drpm_buffer(H264_SLICE_t *currSlice) // dec_ref_pic_marking -{ - H264_DRPM_t *tmp_drpm = NULL; - - while (currSlice->dec_ref_pic_marking_buffer) { - tmp_drpm = currSlice->dec_ref_pic_marking_buffer; - currSlice->dec_ref_pic_marking_buffer = tmp_drpm->Next; - mpp_free(tmp_drpm); - } -} - -static RK_S32 get_voidx(H264_subSPS_t *subset_spsSet, H264_subSPS_t **subset_sps, RK_S32 iViewId) -{ - RK_S32 i = 0, iVOIdx = -1; - RK_S32 *piViewIdMap = NULL; - H264_subSPS_t *active_subset_sps = *subset_sps; - - if (active_subset_sps) { - piViewIdMap = active_subset_sps->view_id; - for (iVOIdx = active_subset_sps->num_views_minus1; iVOIdx >= 0; iVOIdx--) - if (piViewIdMap[iVOIdx] == iViewId) - break; - } else { - for (i = 0; i < MAXSPS; i++) { - if (subset_spsSet[i].num_views_minus1 >= 0 && subset_spsSet[i].sps.Valid) { - break; - } - } - - if (i < MAXSPS) { - *subset_sps = active_subset_sps = &subset_spsSet[i]; - piViewIdMap = active_subset_sps->view_id; - for (iVOIdx = active_subset_sps->num_views_minus1; iVOIdx >= 0; iVOIdx--) - if (piViewIdMap[iVOIdx] == iViewId) - break; - - return iVOIdx; - } else { - iVOIdx = 0; - } - } - - return iVOIdx; -} - -static RK_U32 is_new_picture(H264_SLICE_t *currSlice) -{ - RK_U32 is_new_pic_flag = 0; - RK_S32 result = 0, result1 = 0; - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264_OldSlice_t *p_old_slice = &currSlice->p_Vid->old_slice; - - currSlice->is_new_picture_flag = 0; - if (p_old_slice == NULL) { // fist slice - is_new_pic_flag = 1; - goto __Updata; - } else { - result |= (currSlice->start_mb_nr == 0); - result |= (p_old_slice->pps_id != (RK_S32)currSlice->pic_parameter_set_id); - result |= (p_old_slice->frame_num != currSlice->frame_num); - result |= (p_old_slice->field_pic_flag != currSlice->field_pic_flag); - if (currSlice->field_pic_flag && p_old_slice->field_pic_flag) { - result |= (p_old_slice->bottom_field_flag != currSlice->bottom_field_flag); - } - if (p_Vid->old_slice.current_mb_nr != 0) { - if (currSlice->mb_aff_frame_flag) - result |= (currSlice->start_mb_nr << 1) < (p_Vid->old_slice.current_mb_nr); - else - result |= currSlice->start_mb_nr < p_Vid->old_slice.current_mb_nr; - } - result |= (p_old_slice->nal_ref_idc != currSlice->nal_reference_idc) - && ((p_old_slice->nal_ref_idc == 0) || (currSlice->nal_reference_idc == 0)); - result |= (p_old_slice->idr_flag != currSlice->idr_flag); - if (currSlice->idr_flag && p_old_slice->idr_flag) { - result |= (p_old_slice->idr_pic_id != (RK_S32)currSlice->idr_pic_id); - } - if (p_Vid->active_sps->pic_order_cnt_type == 0) { - result1 |= (p_old_slice->pic_oder_cnt_lsb != currSlice->pic_order_cnt_lsb); - if (p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag && !currSlice->field_pic_flag) { - result1 |= (p_old_slice->delta_pic_oder_cnt_bottom != currSlice->delta_pic_order_cnt_bottom); - } - } else if (p_Vid->active_sps->pic_order_cnt_type == 1) { - if (!p_Vid->active_sps->delta_pic_order_always_zero_flag) { - result1 |= (p_old_slice->delta_pic_order_cnt[0] != currSlice->delta_pic_order_cnt[0]); - if (p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag && !currSlice->field_pic_flag) { - result1 |= (p_old_slice->delta_pic_order_cnt[1] != currSlice->delta_pic_order_cnt[1]); - } - } - } else { - result1 |= (p_old_slice->frame_num != currSlice->frame_num); - } - result |= (currSlice->view_id != p_old_slice->view_id); - result |= (currSlice->inter_view_flag != p_old_slice->inter_view_flag); - result |= (currSlice->anchor_pic_flag != p_old_slice->anchor_pic_flag); - result |= (currSlice->layer_id != p_old_slice->layer_id); - } - if (result) { - is_new_pic_flag = 1; - goto __Updata; - } else { - return is_new_pic_flag = 0; - } -__Updata: - currSlice->is_new_picture_flag = 1; - p_old_slice->current_mb_nr = currSlice->current_mb_nr; - p_old_slice->pps_id = currSlice->pic_parameter_set_id; - p_old_slice->frame_num = currSlice->frame_num; //p_Vid->frame_num; - p_old_slice->field_pic_flag = currSlice->field_pic_flag; //p_Vid->field_pic_flag; - - if (currSlice->field_pic_flag) { - p_old_slice->bottom_field_flag = currSlice->bottom_field_flag; - } - - p_old_slice->nal_ref_idc = currSlice->nal_reference_idc; - p_old_slice->idr_flag = currSlice->idr_flag; - - if (currSlice->idr_flag) { - p_old_slice->idr_pic_id = currSlice->idr_pic_id; - } - - if (p_Vid->active_sps->pic_order_cnt_type == 0) { - p_old_slice->pic_oder_cnt_lsb = currSlice->pic_order_cnt_lsb; - p_old_slice->delta_pic_oder_cnt_bottom = currSlice->delta_pic_order_cnt_bottom; - } - - if (p_Vid->active_sps->pic_order_cnt_type == 1) { - p_old_slice->delta_pic_order_cnt[0] = currSlice->delta_pic_order_cnt[0]; - p_old_slice->delta_pic_order_cnt[1] = currSlice->delta_pic_order_cnt[1]; - } - p_old_slice->view_id = currSlice->view_id; - p_old_slice->inter_view_flag = currSlice->inter_view_flag; - p_old_slice->anchor_pic_flag = currSlice->anchor_pic_flag; - p_old_slice->layer_id = currSlice->layer_id; - - return is_new_pic_flag; -} - -static MPP_RET ref_pic_list_mvc_modification(H264_SLICE_t *currSlice) -{ - RK_U32 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - RK_U32 modification_of_pic_nums_idc = 0; - RK_U32 abs_diff_pic_num_minus1 = 0; - RK_U32 long_term_pic_idx = 0; - RK_U32 abs_diff_view_idx_minus1 = 0; - BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; - - if ((currSlice->slice_type % 5) != I_SLICE && (currSlice->slice_type % 5) != SI_SLICE) { - READ_ONEBIT(ret, p_bitctx, &currSlice->ref_pic_list_reordering_flag[LIST_0], "ref_pic_list_reordering_flag"); - if (currSlice->ref_pic_list_reordering_flag[LIST_0]) { - i = 0; - do { - READ_UE(ret, p_bitctx, &modification_of_pic_nums_idc, "modification_of_pic_nums_idc"); - if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) { - READ_UE(ret, p_bitctx, &abs_diff_pic_num_minus1, "abs_diff_pic_num_minus1_lx"); - } else { - if (modification_of_pic_nums_idc == 2) { - READ_UE(ret, p_bitctx, &long_term_pic_idx, "long_term_pic_idx"); - } else if (modification_of_pic_nums_idc == 4 || modification_of_pic_nums_idc == 5) { - READ_UE(ret, p_bitctx, &abs_diff_view_idx_minus1, "abs_diff_view_idx_minus1"); - } - } - i++; - } while (modification_of_pic_nums_idc != 3); - } - } - if (currSlice->slice_type % 5 == B_SLICE) { - READ_ONEBIT(ret, p_bitctx, &currSlice->ref_pic_list_reordering_flag[LIST_1], "ref_pic_list_reordering_flag"); - if (currSlice->ref_pic_list_reordering_flag[LIST_1]) { - i = 0; - do { - READ_UE(ret, p_bitctx, &modification_of_pic_nums_idc, "modification_of_pic_nums_idc"); - if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) { - READ_UE(ret, p_bitctx, &abs_diff_pic_num_minus1, "abs_diff_pic_num_minus1_lx"); - } else { - if (modification_of_pic_nums_idc == 2) { - READ_UE(ret, p_bitctx, &long_term_pic_idx, "long_term_pic_idx"); - } else if (modification_of_pic_nums_idc == 4 || modification_of_pic_nums_idc == 5) { - READ_UE(ret, p_bitctx, &abs_diff_view_idx_minus1, "abs_diff_view_idx_minus1"); - } - } - i++; - } while (modification_of_pic_nums_idc != 3); - } - } - ASSERT(currSlice->redundant_pic_cnt == 0); //!< not support reference index of redundant slices - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static MPP_RET pred_weight_table(H264_SLICE_t *currSlice) -{ - RK_S32 se_tmp = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - RK_U32 i = 0, j = 0, temp = 0; - BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; - - READ_UE(ret, p_bitctx, &temp, "log2_weight_denom"); - if (currSlice->active_sps->chroma_format_idc) { - READ_UE(ret, p_bitctx, &temp, "log2_weight_denom"); - } - for (i = 0; i < currSlice->num_ref_idx_active[LIST_0]; i++) { - READ_ONEBIT(ret, p_bitctx, &temp, "luma_weight_flag_l0"); - if (temp) { - READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_0][i][0] - READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_0][i][0] - } - if (currSlice->active_sps->chroma_format_idc) { - READ_ONEBIT(ret, p_bitctx, &temp, "chroma_weight_flag_l0"); - for (j = 1; j < 3; j++) { - if (temp) { //!< chroma_weight_flag_l0 - READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_0][i][j] - READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_0][i][j] - } - } - } - } - - if ((currSlice->slice_type == B_SLICE) && currSlice->p_Vid->active_pps->weighted_bipred_idc == 1) { - for (i = 0; i < currSlice->num_ref_idx_active[LIST_1]; i++) { - READ_ONEBIT(ret, p_bitctx, &temp, "luma_weight_flag_l1"); - if (temp) { - READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_1][i][0] - READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_1][i][0] - } - if (currSlice->active_sps->chroma_format_idc) { - READ_ONEBIT(ret, p_bitctx, &temp, "chroma_weight_flag_l1"); - for (j = 1; j < 3; j++) { - if (temp) { // chroma_weight_flag_l1 - READ_SE(ret, p_bitctx, &se_tmp, "pred_weight"); //!< slice->wp_weight[LIST_1][i][j] - READ_SE(ret, p_bitctx, &se_tmp, "pred_offset"); //!< slice->wp_offset[LIST_1][i][j] - } - } - } - } - } - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static MPP_RET dec_ref_pic_marking(H264_SLICE_t *pSlice) -{ - RK_U32 val = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264_DRPM_t *tmp_drpm = NULL, *tmp_drpm2 = NULL; - H264dVideoCtx_t *p_Vid = pSlice->p_Vid; - BitReadCtx_t *p_bitctx = &pSlice->p_Cur->bitctx; - //!< free old buffer content - free_slice_drpm_buffer(pSlice); - if (pSlice->idr_flag || - (pSlice->svc_extension_flag == 0 && pSlice->mvcExt.non_idr_flag == 0)) { - READ_ONEBIT(ret, p_bitctx, &pSlice->no_output_of_prior_pics_flag, "no_output_of_prior_pics_flag"); - p_Vid->no_output_of_prior_pics_flag = pSlice->no_output_of_prior_pics_flag; - READ_ONEBIT(ret, p_bitctx, &pSlice->long_term_reference_flag, "long_term_reference_flag"); - } else { - READ_ONEBIT(ret, p_bitctx, &pSlice->adaptive_ref_pic_buffering_flag, "adaptive_ref_pic_buffering_flag"); - - if (pSlice->adaptive_ref_pic_buffering_flag) { - do { //!< read Memory Management Control Operation - tmp_drpm = mpp_calloc(H264_DRPM_t, 1); - MEM_CHECK(ret, tmp_drpm); - tmp_drpm->Next = NULL; - READ_UE(ret, p_bitctx, &val, "memory_management_control_operation"); - tmp_drpm->memory_management_control_operation = val; - - if ((val == 1) || (val == 3)) { - READ_UE(ret, p_bitctx, &tmp_drpm->difference_of_pic_nums_minus1, "difference_of_pic_nums_minus1"); - } - if (val == 2) { - READ_UE(ret, p_bitctx, &tmp_drpm->long_term_pic_num, "long_term_pic_num"); - } - if ((val == 3) || (val == 6)) { - READ_UE(ret, p_bitctx, &tmp_drpm->long_term_frame_idx, "long_term_frame_idx"); - } - if (val == 4) { - READ_UE(ret, p_bitctx, &tmp_drpm->max_long_term_frame_idx_plus1, "max_long_term_frame_idx_plus1"); - } - // add command - if (pSlice->dec_ref_pic_marking_buffer == NULL) { - pSlice->dec_ref_pic_marking_buffer = tmp_drpm; - } else { - tmp_drpm2 = pSlice->dec_ref_pic_marking_buffer; - while (tmp_drpm2->Next != NULL) { - tmp_drpm2 = tmp_drpm2->Next; - } - tmp_drpm2->Next = tmp_drpm; - } - - } while (val != 0); - } - } - - return ret = MPP_OK; -__FAILED: - - return ret; -} - -static void init_slice_parmeters(H264_SLICE_t *currSlice) -{ - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264_Nalu_t *cur_nalu = &currSlice->p_Cur->nalu; - - //--- init slice syntax - currSlice->idr_flag = ((cur_nalu->nal_unit_type == NALU_TYPE_IDR) - || (currSlice->mvcExt.valid && !currSlice->mvcExt.non_idr_flag)); - currSlice->nal_reference_idc = cur_nalu->nal_reference_idc; - if ((!currSlice->svc_extension_flag) || currSlice->mvcExt.iPrefixNALU) { // MVC or have prefixNALU - currSlice->view_id = currSlice->mvcExt.view_id; - currSlice->inter_view_flag = currSlice->mvcExt.inter_view_flag; - currSlice->anchor_pic_flag = currSlice->mvcExt.anchor_pic_flag; - } else if (currSlice->svc_extension_flag == -1) { // normal AVC - currSlice->view_id = currSlice->mvcExt.valid ? p_Vid->active_subsps->view_id[0] : 0; - currSlice->inter_view_flag = 1; - currSlice->anchor_pic_flag = currSlice->idr_flag; - } - currSlice->layer_id = get_voidx(p_Vid->subspsSet, &p_Vid->active_subsps, currSlice->view_id); - if (currSlice->layer_id >= 0) { // if not found, layer_id == -1 - currSlice->p_Dpb = p_Vid->p_Dpb_layer[currSlice->layer_id]; - } -} - -static MPP_RET set_slice_user_parmeters(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264_PPS_t *cur_pps = NULL; - H264_SPS_t *cur_sps = NULL; - H264_subSPS_t *cur_subsps = NULL; - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - //!< use parameter set - cur_pps = &p_Vid->ppsSet[currSlice->pic_parameter_set_id]; - ASSERT(cur_pps != NULL); - if (currSlice->mvcExt.valid) { - cur_sps = &p_Vid->subspsSet[cur_pps->seq_parameter_set_id].sps; - cur_subsps = &p_Vid->subspsSet[cur_pps->seq_parameter_set_id]; - if (cur_subsps->Valid) { - if ((RK_S32)currSlice->mvcExt.view_id == cur_subsps->view_id[0]) { // combine subsps to sps - p_Vid->active_mvc_sps_flag = 0; - cur_subsps = NULL; - cur_sps = &p_Vid->spsSet[cur_pps->seq_parameter_set_id]; - } else if ((RK_S32)currSlice->mvcExt.view_id == cur_subsps->view_id[1]) { - p_Vid->active_mvc_sps_flag = 1; - } - } else { - p_Vid->active_mvc_sps_flag = 0; - cur_sps = &p_Vid->spsSet[cur_pps->seq_parameter_set_id]; - cur_subsps = NULL; - } - } else { - p_Vid->active_mvc_sps_flag = 0; - cur_sps = &p_Vid->spsSet[cur_pps->seq_parameter_set_id]; - cur_subsps = NULL; - } - ASSERT(cur_sps->separate_colour_plane_flag == 0); - FUN_CHECK(ret = activate_sps(p_Vid, cur_sps, cur_subsps)); - FUN_CHECK(ret = activate_pps(p_Vid, cur_pps)); - //!< Set SPS to the subset SPS parameters - if (currSlice->svc_extension_flag == 0) { - p_Vid->active_subsps = &p_Vid->subspsSet[cur_pps->seq_parameter_set_id]; - } - currSlice->active_sps = p_Vid->active_sps; - currSlice->active_pps = p_Vid->active_pps; - - return MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -/*! -*********************************************************************** -* \brief -* parse SEI information -*********************************************************************** -*/ -//extern "C" -void recycle_slice(H264_SLICE_t *currSlice) -{ - if (currSlice) { - free_slice_drpm_buffer(currSlice); - } -} -/*! -*********************************************************************** -* \brief -* parse SEI information -*********************************************************************** -*/ -//extern "C" -MPP_RET process_slice(H264_SLICE_t *currSlice) -{ - RK_U32 temp = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - H264dLogCtx_t *logctx = currSlice->logctx; - H264dVideoCtx_t *p_Vid = currSlice->p_Vid; - H264dCurCtx_t *p_Cur = currSlice->p_Cur; - BitReadCtx_t *p_bitctx = &p_Cur->bitctx; - - FunctionIn(logctx->parr[RUN_PARSE]); - //--- initial value ---- - currSlice->p_Dpb_layer[0] = p_Vid->p_Dpb_layer[0]; - currSlice->p_Dpb_layer[1] = p_Vid->p_Dpb_layer[1]; - set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_SLICE]); - init_slice_parmeters(currSlice); - WRITE_LOG(p_bitctx, "----------------------------- SLICE begin --------------------------------"); - //------- read slice head syntax -------- - READ_UE(ret, p_bitctx, &currSlice->start_mb_nr, "first_mb_in_slice"); - READ_UE(ret, p_bitctx, &temp, "slice_type"); - p_Vid->slice_type = currSlice->slice_type = temp % 5; - READ_UE(ret, p_bitctx, &currSlice->pic_parameter_set_id, "slice_pic_parameter_set_id"); - - FUN_CHECK(ret = set_slice_user_parmeters(currSlice)); - //!< read rest slice header syntax - READ_BITS(ret, p_bitctx, currSlice->active_sps->log2_max_frame_num_minus4 + 4, &currSlice->frame_num, "frame_num"); - if (currSlice->active_sps->frame_mbs_only_flag) { //!< user in_slice info - p_Vid->structure = FRAME; - currSlice->field_pic_flag = 0; - currSlice->bottom_field_flag = 0; - } else { - READ_ONEBIT(ret, p_bitctx, &currSlice->field_pic_flag, "field_pic_flag"); - if (currSlice->field_pic_flag) { - READ_ONEBIT(ret, p_bitctx, &currSlice->bottom_field_flag, "field_pic_flag"); - p_Vid->structure = currSlice->bottom_field_flag ? BOTTOM_FIELD : TOP_FIELD; - } else { - p_Vid->structure = FRAME; - currSlice->bottom_field_flag = 0; - } - } - currSlice->structure = p_Vid->structure; - currSlice->mb_aff_frame_flag = (currSlice->active_sps->mb_adaptive_frame_field_flag && (currSlice->field_pic_flag == 0)); - if (currSlice->idr_flag) { - READ_UE(ret, p_bitctx, &currSlice->idr_pic_id, "idr_pic_id"); - } else if (currSlice->svc_extension_flag == 0 && currSlice->mvcExt.non_idr_flag == 0) { - READ_UE(ret, p_bitctx, &currSlice->idr_pic_id, "idr_pic_id"); - } - if (currSlice->active_sps->pic_order_cnt_type == 0) { - READ_BITS(ret, p_bitctx, currSlice->active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4, &currSlice->pic_order_cnt_lsb, "pic_order_cnt_lsb"); - if (currSlice->p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 - && !currSlice->field_pic_flag) { - READ_SE(ret, p_bitctx, &currSlice->delta_pic_order_cnt_bottom, "delta_pic_order_cnt_bottom"); - } else { - currSlice->delta_pic_order_cnt_bottom = 0; - } - } - if (currSlice->active_sps->pic_order_cnt_type == 1) { - if (!currSlice->active_sps->delta_pic_order_always_zero_flag) { - READ_SE(ret, p_bitctx, &currSlice->delta_pic_order_cnt[0], "delta_pic_order_cnt[0]"); - - if (currSlice->p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 && !currSlice->field_pic_flag) { - READ_SE(ret, p_bitctx, &currSlice->delta_pic_order_cnt[1], "delta_pic_order_cnt[1]"); - } else { - currSlice->delta_pic_order_cnt[1] = 0; // set to zero if not in stream - } - } else { - currSlice->delta_pic_order_cnt[0] = 0; - currSlice->delta_pic_order_cnt[1] = 0; - } - } - //! redundant_pic_cnt is missing here - ASSERT(currSlice->p_Vid->active_pps->redundant_pic_cnt_present_flag == 0); // add by dw, high 4:2:2 profile not support - if (currSlice->p_Vid->active_pps->redundant_pic_cnt_present_flag) { - READ_UE(ret, p_bitctx, &currSlice->redundant_pic_cnt, "redundant_pic_cnt"); - } - - if (currSlice->slice_type == B_SLICE) { - READ_ONEBIT(ret, p_bitctx, &currSlice->direct_spatial_mv_pred_flag, "direct_spatial_mv_pred_flag"); - } else { - currSlice->direct_spatial_mv_pred_flag = 0; - } - currSlice->num_ref_idx_active[LIST_0] = currSlice->p_Vid->active_pps->num_ref_idx_l0_default_active_minus1 + 1; - currSlice->num_ref_idx_active[LIST_1] = currSlice->p_Vid->active_pps->num_ref_idx_l1_default_active_minus1 + 1; - - if (currSlice->slice_type == P_SLICE - || currSlice->slice_type == SP_SLICE || currSlice->slice_type == B_SLICE) { - //!< "direct_spatial_mv_pred_flag" - READ_ONEBIT(ret, p_bitctx, &currSlice->num_ref_idx_override_flag, "num_ref_idx_override_flag"); - if (currSlice->num_ref_idx_override_flag) { - READ_UE(ret, p_bitctx, &currSlice->num_ref_idx_active[LIST_0], "num_ref_idx_active0"); - currSlice->num_ref_idx_active[LIST_0] += 1; - if (currSlice->slice_type == B_SLICE) { - READ_UE(ret, p_bitctx, &currSlice->num_ref_idx_active[LIST_1], "num_ref_idx_active1"); - currSlice->num_ref_idx_active[LIST_1] += 1; - } - } - } - if (currSlice->slice_type != B_SLICE) { - currSlice->num_ref_idx_active[LIST_1] = 0; - } - - if (is_new_picture(currSlice)) { - FUN_CHECK(ret = ref_pic_list_mvc_modification(currSlice)); - if ((currSlice->p_Vid->active_pps->weighted_pred_flag - && (currSlice->slice_type == P_SLICE || currSlice->slice_type == SP_SLICE)) - || (currSlice->p_Vid->active_pps->weighted_bipred_idc == 1 && (currSlice->slice_type == B_SLICE))) { - FUN_CHECK(ret = pred_weight_table(currSlice)); - } - if (currSlice->nal_reference_idc) { - FUN_CHECK(ret = dec_ref_pic_marking(currSlice)); - } - currSlice->is_new_picture_flag = 1; - } - - FunctionOut(logctx->parr[RUN_PARSE]); - - return ret = MPP_OK; -__FAILED: - recycle_slice(currSlice); - - return ret; -} +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_slice" + +#include + +#include "mpp_mem.h" + +#include "h264d_global.h" +#include "h264d_slice.h" +#include "h264d_sps.h" +#include "h264d_pps.h" +#include "h2645d_sei.h" + +#define PIXW_1080P (1920) +#define PIXH_1080P (1088) +#define PIXW_4Kx2K (4096) +#define PIXH_4Kx2K (2304) +#define PIXW_8Kx4K (8192) +#define PIXH_8Kx4K (4320) + +#define MAX_MBW_1080P (((PIXW_1080P) / 16) - 1) /* 119 */ +#define MAX_MBH_1080P (((PIXH_1080P) / 16) - 1) /* 67 */ +#define MAX_MBW_4Kx2K (((PIXW_4Kx2K) / 16) - 1) /* 255 */ +#define MAX_MBH_4Kx2K (((PIXH_4Kx2K) / 16) - 1) /* 143 */ +#define MAX_MBW_8Kx4K (((PIXW_8Kx4K) / 16) - 1) /* 511 */ +#define MAX_MBH_8Kx4K (((PIXH_8Kx4K) / 16) - 1) /* 269 */ + +static MPP_RET ref_pic_list_mvc_modification(H264_SLICE_t *currSlice) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 modification_of_pic_nums_idc = 0; + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + + if ((currSlice->slice_type % 5) != H264_I_SLICE && (currSlice->slice_type % 5) != H264_SI_SLICE) { + READ_ONEBIT(p_bitctx, &currSlice->ref_pic_list_reordering_flag[LIST_0]); + if (currSlice->ref_pic_list_reordering_flag[LIST_0]) { + RK_U32 size = currSlice->num_ref_idx_active[LIST_0] + 1; + i = 0; + do { + if (i >= size || i >= MAX_REORDER_TIMES) { + ret = MPP_NOK; + H264D_WARNNING("ref_pic_list_reordering error, i >= num_ref_idx_active[LIST_0](%d)", size); + goto __BITREAD_ERR; + } + READ_UE(p_bitctx, &modification_of_pic_nums_idc); + currSlice->modification_of_pic_nums_idc[LIST_0][i] = modification_of_pic_nums_idc; + if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) { + READ_UE(p_bitctx, &currSlice->abs_diff_pic_num_minus1[LIST_0][i]); + } else { + if (modification_of_pic_nums_idc == 2) { + READ_UE(p_bitctx, &currSlice->long_term_pic_idx[LIST_0][i]); + } else if (modification_of_pic_nums_idc == 4 || modification_of_pic_nums_idc == 5) { + READ_UE(p_bitctx, &currSlice->abs_diff_view_idx_minus1[LIST_0][i]); + } + } + i++; + } while (modification_of_pic_nums_idc != 3); + } + } + if (currSlice->slice_type % 5 == H264_B_SLICE) { + READ_ONEBIT(p_bitctx, &currSlice->ref_pic_list_reordering_flag[LIST_1]); + if (currSlice->ref_pic_list_reordering_flag[LIST_1]) { + RK_U32 size = currSlice->num_ref_idx_active[LIST_1] + 1; + i = 0; + do { + if (i >= size || i >= MAX_REORDER_TIMES) { + ret = MPP_NOK; + H264D_WARNNING("ref_pic_list_reordering error, i >= num_ref_idx_active[LIST_1](%d)", size); + goto __BITREAD_ERR; + } + READ_UE(p_bitctx, &modification_of_pic_nums_idc); + currSlice->modification_of_pic_nums_idc[LIST_1][i] = modification_of_pic_nums_idc; + if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) { + READ_UE(p_bitctx, &currSlice->abs_diff_pic_num_minus1[LIST_1][i]); + } else { + if (modification_of_pic_nums_idc == 2) { + READ_UE(p_bitctx, &currSlice->long_term_pic_idx[LIST_1][i]); + } else if (modification_of_pic_nums_idc == 4 || modification_of_pic_nums_idc == 5) { + READ_UE(p_bitctx, &currSlice->abs_diff_view_idx_minus1[LIST_1][i]); + } + } + i++; + } while (modification_of_pic_nums_idc != 3); + } + } + ASSERT(currSlice->redundant_pic_cnt == 0); //!< not support reference index of redundant slices + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; + + return ret; +} + +static MPP_RET pred_weight_table(H264_SLICE_t *currSlice) +{ + RK_S32 se_tmp = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 i = 0, j = 0, temp = 0; + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + + READ_UE(p_bitctx, &temp); //!< log2_weight_denom + if (currSlice->active_sps->chroma_format_idc) { + READ_UE(p_bitctx, &temp); //!< log2_weight_denom + } + for (i = 0; i < currSlice->num_ref_idx_active[LIST_0]; i++) { + READ_ONEBIT(p_bitctx, &temp); //!< luma_weight_flag_l0 + if (temp) { + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_weight[LIST_0][i][0] + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_offset[LIST_0][i][0] + } + if (currSlice->active_sps->chroma_format_idc) { + READ_ONEBIT(p_bitctx, &temp); //!< chroma_weight_flag_l0 + for (j = 1; j < 3; j++) { + if (temp) { //!< chroma_weight_flag_l0 + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_weight[LIST_0][i][j] + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_offset[LIST_0][i][j] + } + } + } + } + + if ((currSlice->slice_type == H264_B_SLICE) && currSlice->p_Vid->active_pps->weighted_bipred_idc == 1) { + for (i = 0; i < currSlice->num_ref_idx_active[LIST_1]; i++) { + READ_ONEBIT(p_bitctx, &temp); //!< luma_weight_flag_l1 + if (temp) { + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_weight[LIST_1][i][0] + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_offset[LIST_1][i][0] + } + if (currSlice->active_sps->chroma_format_idc) { + READ_ONEBIT(p_bitctx, &temp); //!< chroma_weight_flag_l1 + for (j = 1; j < 3; j++) { + if (temp) { // chroma_weight_flag_l1 + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_weight[LIST_1][i][j] + READ_SE(p_bitctx, &se_tmp); //!< slice->wp_offset[LIST_1][i][j] + } + } + } + } + } + + return ret = MPP_OK; +__BITREAD_ERR: + return ret = p_bitctx->ret; +} + +static MPP_RET dec_ref_pic_marking(H264_SLICE_t *pSlice) +{ + RK_U32 val = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 drpm_used_bits = 0; + RK_U32 emulation_prevention = 0; + H264_DRPM_t *tmp_drpm = NULL, *tmp_drpm2 = NULL; + H264dVideoCtx_t *p_Vid = pSlice->p_Vid; + BitReadCtx_t *p_bitctx = &pSlice->p_Cur->bitctx; + + drpm_used_bits = p_bitctx->used_bits; + emulation_prevention = p_bitctx->emulation_prevention_bytes_; + pSlice->drpm_used_bitlen = 0; + + if (pSlice->idr_flag || + (pSlice->svc_extension_flag == 0 && pSlice->mvcExt.non_idr_flag == 0)) { + READ_ONEBIT(p_bitctx, &pSlice->no_output_of_prior_pics_flag); + p_Vid->no_output_of_prior_pics_flag = pSlice->no_output_of_prior_pics_flag; + READ_ONEBIT(p_bitctx, &pSlice->long_term_reference_flag); + } else { + READ_ONEBIT(p_bitctx, &pSlice->adaptive_ref_pic_buffering_flag); + + if (pSlice->adaptive_ref_pic_buffering_flag) { + RK_U32 i = 0; + + for (i = 0; i < MAX_MARKING_TIMES; i++) { + if (!pSlice->p_Cur->dec_ref_pic_marking_buffer[i]) + pSlice->p_Cur->dec_ref_pic_marking_buffer[i] = mpp_calloc(H264_DRPM_t, 1); + tmp_drpm = pSlice->p_Cur->dec_ref_pic_marking_buffer[i]; + tmp_drpm->Next = NULL; + READ_UE(p_bitctx, &val); //!< mmco + tmp_drpm->memory_management_control_operation = val; + if (val == 0) + break; + + if ((val == 1) || (val == 3)) { + READ_UE(p_bitctx, &tmp_drpm->difference_of_pic_nums_minus1); + } + if (val == 2) { + READ_UE(p_bitctx, &tmp_drpm->long_term_pic_num); + } + if ((val == 3) || (val == 6)) { + READ_UE(p_bitctx, &tmp_drpm->long_term_frame_idx); + } + if (val == 4) { + READ_UE(p_bitctx, &tmp_drpm->max_long_term_frame_idx_plus1); + } + // add command + if (pSlice->dec_ref_pic_marking_buffer == NULL) { + pSlice->dec_ref_pic_marking_buffer = tmp_drpm; + } else { + tmp_drpm2 = pSlice->dec_ref_pic_marking_buffer; + while (tmp_drpm2->Next != NULL) { + tmp_drpm2 = tmp_drpm2->Next; + } + tmp_drpm2->Next = tmp_drpm; + } + } + if (i >= MAX_MARKING_TIMES) { + H264D_ERR("Too many memory management control operations."); + goto __BITREAD_ERR; + } + } + } + + // need to minus emulation prevention bytes(0x000003) we met + emulation_prevention = p_bitctx->emulation_prevention_bytes_ - emulation_prevention; + pSlice->drpm_used_bitlen = p_bitctx->used_bits - drpm_used_bits - (emulation_prevention * 8); + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; + + return ret; +} + +static void init_slice_parmeters(H264_SLICE_t *currSlice) +{ + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264_Nalu_t *cur_nalu = &currSlice->p_Cur->nalu; + + //--- init slice syntax + currSlice->idr_flag = cur_nalu->nalu_type == H264_NALU_TYPE_IDR; + currSlice->nal_reference_idc = cur_nalu->nal_reference_idc; + //!< set ref flag and dpb error flag + { + p_Vid->p_Dec->errctx.used_ref_flag = (currSlice->nal_reference_idc != 0) ? 1 : 0; + if (currSlice->slice_type == H264_I_SLICE) { + p_Vid->p_Dec->errctx.dpb_err_flag = 0; + } + } + if ((!currSlice->svc_extension_flag) || currSlice->mvcExt.iPrefixNALU) { // MVC or have prefixNALU + currSlice->view_id = currSlice->mvcExt.view_id; + currSlice->inter_view_flag = currSlice->mvcExt.inter_view_flag; + currSlice->anchor_pic_flag = currSlice->mvcExt.anchor_pic_flag; + } else if (currSlice->svc_extension_flag == -1) { // normal AVC + currSlice->view_id = (currSlice->mvcExt.valid != 0) ? p_Vid->active_subsps->view_id[0] : 0; + currSlice->inter_view_flag = 1; + currSlice->anchor_pic_flag = currSlice->idr_flag; + } + currSlice->layer_id = currSlice->view_id; + if (currSlice->layer_id >= 0) { // if not found, layer_id == -1 + currSlice->p_Dpb = p_Vid->p_Dpb_layer[currSlice->layer_id]; + } +} + +static MPP_RET check_sps_pps(H264_SPS_t *sps, H264_subSPS_t *subset_sps, + H264_PPS_t *pps, const MppDecHwCap *hw_info) +{ + RK_U32 ret = 0; + RK_S32 max_mb_width = MAX_MBW_1080P; + + ret |= (sps->seq_parameter_set_id > 31); + ret |= (sps->separate_colour_plane_flag == 1); + ret |= (sps->chroma_format_idc >= 3); + ret |= (sps->bit_depth_luma_minus8 > 2); + ret |= (sps->bit_depth_chroma_minus8 > 2); + ret |= (sps->log2_max_frame_num_minus4 > 12); + ret |= (sps->pic_order_cnt_type > 2); + ret |= (sps->log2_max_pic_order_cnt_lsb_minus4 > 12); + ret |= (sps->num_ref_frames_in_pic_order_cnt_cycle > 255); + ret |= (sps->max_num_ref_frames > 16); + ret |= (sps->qpprime_y_zero_transform_bypass_flag == 1); + + if (ret) { + H264D_ERR("sps has error, sps_id=%d", sps->seq_parameter_set_id); + goto __FAILED; + } + + if (hw_info && hw_info->cap_8k) + max_mb_width = MAX_MBW_8Kx4K * hw_info->cap_core_num; + else if (hw_info && hw_info->cap_4k) + max_mb_width = MAX_MBW_4Kx2K; + + ret |= (sps->pic_width_in_mbs_minus1 < 3); + if (ret) { + H264D_ERR("sps %d too small width %d\n", sps->seq_parameter_set_id, + (sps->pic_width_in_mbs_minus1 + 1) * 16); + goto __FAILED; + } + ret |= (sps->pic_width_in_mbs_minus1 > max_mb_width); + if (ret) { + H264D_ERR("width %d is larger than soc max support %d\n", + (sps->pic_width_in_mbs_minus1 + 1) * 16, max_mb_width * 16); + goto __FAILED; + } + + if (subset_sps) { //!< MVC + ret |= (subset_sps->num_views_minus1 != 1); + if (subset_sps->num_anchor_refs_l0[0] > 0) + ret |= (subset_sps->anchor_ref_l0[0][0] != subset_sps->view_id[0]); + if (subset_sps->num_anchor_refs_l1[0] > 0) + ret |= (subset_sps->anchor_ref_l1[0][0] != subset_sps->view_id[1]); + if (subset_sps->num_non_anchor_refs_l0[0] > 0) + ret |= (subset_sps->non_anchor_ref_l0[0][0] != subset_sps->view_id[0]); + if (subset_sps->num_non_anchor_refs_l1[0] > 0) + ret |= (subset_sps->non_anchor_ref_l1[0][0] != subset_sps->view_id[1]); + if (ret) { + H264D_ERR("subsps has error, sps_id=%d", sps->seq_parameter_set_id); + goto __FAILED; + } + } + //!< check PPS + ret |= (pps->pic_parameter_set_id > 255); + ret |= (pps->seq_parameter_set_id > 31); + ret |= (pps->num_slice_groups_minus1 > 0); + ret |= (pps->num_ref_idx_l0_default_active_minus1 > 31); + ret |= (pps->num_ref_idx_l1_default_active_minus1 > 31); + ret |= (pps->pic_init_qp_minus26 > 25 || pps->pic_init_qp_minus26 < -(26 + 6 * (RK_S32)sps->bit_depth_luma_minus8)); + ret |= (pps->pic_init_qs_minus26 > 25 || pps->pic_init_qs_minus26 < -26); + ret |= (pps->chroma_qp_index_offset > 12 || pps->chroma_qp_index_offset < -12); + ret |= (pps->redundant_pic_cnt_present_flag == 1); + if (ret) { + H264D_ERR("pps has error, sps_id=%d, pps_id", sps->seq_parameter_set_id, pps->pic_parameter_set_id); + goto __FAILED; + } + return MPP_OK; +__FAILED: + return MPP_NOK; +} + + +static MPP_RET set_slice_user_parmeters(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264_PPS_t *cur_pps = NULL; + H264_SPS_t *cur_sps = NULL; + H264_subSPS_t *cur_subsps = NULL; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + + //!< use parameter set + if (currSlice->pic_parameter_set_id < MAXPPS) { + cur_pps = p_Vid->ppsSet[currSlice->pic_parameter_set_id]; + cur_pps = (cur_pps && cur_pps->Valid) ? cur_pps : NULL; + } + VAL_CHECK(ret, cur_pps != NULL); + + if (currSlice->mvcExt.valid) { + cur_subsps = p_Vid->subspsSet[cur_pps->seq_parameter_set_id]; + // only num view(except base view) > 0, need to combine view id + if (cur_subsps && cur_subsps->Valid && cur_subsps->num_views_minus1 > 0) { + cur_sps = &cur_subsps->sps; + if ((RK_S32)currSlice->mvcExt.view_id == cur_subsps->view_id[0]) { // combine subsps to sps + p_Vid->active_mvc_sps_flag = 0; + cur_subsps = NULL; + cur_sps = p_Vid->spsSet[cur_pps->seq_parameter_set_id]; + } else if ((RK_S32)currSlice->mvcExt.view_id == cur_subsps->view_id[1]) { + p_Vid->active_mvc_sps_flag = 1; + } + } else { + p_Vid->active_mvc_sps_flag = 0; + cur_sps = p_Vid->spsSet[cur_pps->seq_parameter_set_id]; + cur_subsps = NULL; + } + } else { + p_Vid->active_mvc_sps_flag = 0; + cur_sps = p_Vid->spsSet[cur_pps->seq_parameter_set_id]; + cur_subsps = NULL; + } + + if (p_Vid->active_mvc_sps_flag) { // layer_id == 1 + cur_subsps = (cur_subsps && cur_subsps->Valid) ? cur_subsps : NULL; + VAL_CHECK(ret, cur_subsps != NULL); + cur_sps = &cur_subsps->sps; + } else { //!< layer_id == 0 + cur_subsps = NULL; + cur_sps = (cur_sps && cur_sps->Valid) ? cur_sps : NULL; + } + VAL_CHECK(ret, cur_sps); + VAL_CHECK(ret, check_sps_pps(cur_sps, cur_subsps, cur_pps, p_Vid->p_Dec->hw_info) != MPP_NOK); + + FUN_CHECK(ret = activate_sps(p_Vid, cur_sps, cur_subsps)); + FUN_CHECK(ret = activate_pps(p_Vid, cur_pps)); + + if (p_Vid->last_sps_id != cur_sps->seq_parameter_set_id || + p_Vid->last_pps_id != cur_pps->pic_parameter_set_id) { + p_Vid->last_sps_id = cur_sps->seq_parameter_set_id; + p_Vid->last_pps_id = cur_pps->pic_parameter_set_id; + p_Vid->spspps_update = 1; + } + + /* NOTE: the SVC is not supported by hardware, so it is dropped. + * Or svc_extension_flag doesn't equal to -1, it should apply the + * subset_seq_parameter_set_rbsp(). + */ + if (p_Vid->p_Dec->mvc_valid) { + struct h264_subsps_t *active_subsps = NULL; + + active_subsps = p_Vid->subspsSet[cur_pps->seq_parameter_set_id]; + if (active_subsps && active_subsps->Valid) + p_Vid->active_subsps = active_subsps; + else + p_Vid->active_subsps = NULL; + } + + currSlice->active_sps = p_Vid->active_sps; + currSlice->active_pps = p_Vid->active_pps; + + p_Vid->type = currSlice->slice_type; + return MPP_OK; +__FAILED: + return ret; +} + + +/*! +*********************************************************************** +* \brief +* reset current slice buffer +*********************************************************************** +*/ +//extern "C" +MPP_RET reset_cur_slice(H264dCurCtx_t *p_Cur, H264_SLICE_t *p) +{ + if (p) { + p->modification_of_pic_nums_idc[LIST_0] = p_Cur->modification_of_pic_nums_idc[LIST_0]; + p->abs_diff_pic_num_minus1[LIST_0] = p_Cur->abs_diff_pic_num_minus1[LIST_0]; + p->long_term_pic_idx[LIST_0] = p_Cur->long_term_pic_idx[LIST_0]; + p->abs_diff_view_idx_minus1[LIST_0] = p_Cur->abs_diff_view_idx_minus1[LIST_0]; + + p->modification_of_pic_nums_idc[LIST_1] = p_Cur->modification_of_pic_nums_idc[LIST_1]; + p->abs_diff_pic_num_minus1[LIST_1] = p_Cur->abs_diff_pic_num_minus1[LIST_1]; + p->long_term_pic_idx[LIST_1] = p_Cur->long_term_pic_idx[LIST_1]; + p->abs_diff_view_idx_minus1[LIST_1] = p_Cur->abs_diff_view_idx_minus1[LIST_1]; + + p->dec_ref_pic_marking_buffer = NULL; + } + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* parse SEI information +*********************************************************************** +*/ +//extern "C" +MPP_RET process_slice(H264_SLICE_t *currSlice) +{ + RK_U32 temp = 0; + RK_U32 poc_used_bits = 0; + RK_U32 emulation_prevention = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + H264dVideoCtx_t *p_Vid = currSlice->p_Vid; + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + RecoveryPoint *recovery = &p_Vid->recovery; + + //!< initial value + currSlice->p_Dpb_layer[0] = p_Vid->p_Dpb_layer[0]; + currSlice->p_Dpb_layer[1] = p_Vid->p_Dpb_layer[1]; + + //!< read slice head syntax + READ_UE(p_bitctx, &currSlice->start_mb_nr); //!< first_mb_in_slice + READ_UE(p_bitctx, &temp); //!< slice_type + p_Vid->slice_type = currSlice->slice_type = temp % 5; + if (p_Vid->slice_type == H264_SP_SLICE || p_Vid->slice_type == H264_SI_SLICE) { + H264D_WARNNING("sp or si slice not support\n"); + goto __FAILED; + } + READ_UE(p_bitctx, &currSlice->pic_parameter_set_id); + init_slice_parmeters(currSlice); + FUN_CHECK(ret = set_slice_user_parmeters(currSlice)); + //!< read rest slice header syntax + { + READ_BITS(p_bitctx, currSlice->active_sps->log2_max_frame_num_minus4 + 4, &currSlice->frame_num); + + if (recovery->valid_flag) { + if (!recovery->first_frm_valid) { + recovery->first_frm_id = currSlice->frame_num; + recovery->first_frm_valid = 1; + recovery->recovery_pic_id = recovery->first_frm_id + recovery->recovery_frame_cnt; + H264D_DBG(H264D_DBG_SEI, "First recovery frame found, frame_num %d", currSlice->frame_num); + } else { + // It may be too early to reset recovery point info when frame_num is wrapped + if (recovery->recovery_pic_id % p_Vid->max_frame_num < currSlice->frame_num) + memset(&p_Vid->recovery, 0, sizeof(RecoveryPoint)); + } + } + + if (currSlice->active_sps->frame_mbs_only_flag) { //!< user in_slice info + p_Vid->structure = FRAME; + currSlice->field_pic_flag = 0; + currSlice->bottom_field_flag = 0; + } else { + READ_ONEBIT(p_bitctx, &currSlice->field_pic_flag); + if (currSlice->field_pic_flag) { + READ_ONEBIT(p_bitctx, &currSlice->bottom_field_flag); + p_Vid->structure = (currSlice->bottom_field_flag != 0) ? BOTTOM_FIELD : TOP_FIELD; + } else { + p_Vid->structure = FRAME; + currSlice->bottom_field_flag = 0; + } + } + currSlice->structure = p_Vid->structure; + currSlice->mb_aff_frame_flag = currSlice->active_sps->mb_adaptive_frame_field_flag && + !currSlice->field_pic_flag; + if (currSlice->idr_flag) { + READ_UE(p_bitctx, &currSlice->idr_pic_id); + } else if (currSlice->svc_extension_flag == 0 && currSlice->mvcExt.non_idr_flag == 0) { + READ_UE(p_bitctx, &currSlice->idr_pic_id); + } + poc_used_bits = p_bitctx->used_bits; //!< init poc used bits + emulation_prevention = p_bitctx->emulation_prevention_bytes_; + if (currSlice->active_sps->pic_order_cnt_type == 0) { + READ_BITS(p_bitctx, currSlice->active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4, &currSlice->pic_order_cnt_lsb); + if (currSlice->p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 + && !currSlice->field_pic_flag) { + READ_SE(p_bitctx, &currSlice->delta_pic_order_cnt_bottom); + } else { + currSlice->delta_pic_order_cnt_bottom = 0; + } + } + if (currSlice->active_sps->pic_order_cnt_type == 1) { + if (!currSlice->active_sps->delta_pic_order_always_zero_flag) { + READ_SE(p_bitctx, &currSlice->delta_pic_order_cnt[0]); + + if (currSlice->p_Vid->active_pps->bottom_field_pic_order_in_frame_present_flag == 1 && !currSlice->field_pic_flag) { + READ_SE(p_bitctx, &currSlice->delta_pic_order_cnt[1]); + } else { + currSlice->delta_pic_order_cnt[1] = 0; //!< set to zero if not in stream + } + } else { + currSlice->delta_pic_order_cnt[0] = 0; + currSlice->delta_pic_order_cnt[1] = 0; + } + } + + // need to minus emulation prevention bytes(0x000003) we met + emulation_prevention = p_bitctx->emulation_prevention_bytes_ - emulation_prevention; + currSlice->poc_used_bitlen = p_bitctx->used_bits - poc_used_bits - (emulation_prevention * 8); //!< calculate poc used bit length + //!< redundant_pic_cnt is missing here + ASSERT(currSlice->p_Vid->active_pps->redundant_pic_cnt_present_flag == 0); // add by dw, high 4:2:2 profile not support + if (currSlice->p_Vid->active_pps->redundant_pic_cnt_present_flag) { + READ_UE(p_bitctx, &currSlice->redundant_pic_cnt); + } + + if (currSlice->slice_type == H264_B_SLICE) { + READ_ONEBIT(p_bitctx, &currSlice->direct_spatial_mv_pred_flag); + } else { + currSlice->direct_spatial_mv_pred_flag = 0; + } + currSlice->num_ref_idx_active[LIST_0] = currSlice->p_Vid->active_pps->num_ref_idx_l0_default_active_minus1 + 1; + currSlice->num_ref_idx_active[LIST_1] = currSlice->p_Vid->active_pps->num_ref_idx_l1_default_active_minus1 + 1; + + if (currSlice->slice_type == H264_P_SLICE + || currSlice->slice_type == H264_SP_SLICE || currSlice->slice_type == H264_B_SLICE) { + READ_ONEBIT(p_bitctx, &currSlice->num_ref_idx_override_flag); + if (currSlice->num_ref_idx_override_flag) { + READ_UE(p_bitctx, &currSlice->num_ref_idx_active[LIST_0]); + currSlice->num_ref_idx_active[LIST_0] += 1; + if (currSlice->slice_type == H264_B_SLICE) { + READ_UE(p_bitctx, &currSlice->num_ref_idx_active[LIST_1]); + currSlice->num_ref_idx_active[LIST_1] += 1; + } + } + } + if (currSlice->slice_type != H264_B_SLICE) { + currSlice->num_ref_idx_active[LIST_1] = 0; + } + FUN_CHECK(ret = ref_pic_list_mvc_modification(currSlice)); + if ((currSlice->p_Vid->active_pps->weighted_pred_flag + && (currSlice->slice_type == H264_P_SLICE || currSlice->slice_type == H264_SP_SLICE)) + || (currSlice->p_Vid->active_pps->weighted_bipred_idc == 1 && (currSlice->slice_type == H264_B_SLICE))) { + FUN_CHECK(ret = pred_weight_table(currSlice)); + } + currSlice->drpm_used_bitlen = 0; + if (currSlice->nal_reference_idc) { + FUN_CHECK(ret = dec_ref_pic_marking(currSlice)); + } + H264D_DBG(H264D_DBG_PPS_SPS, "[SLICE_HEAD] type=%d, layer_id=%d,sps_id=%d, pps_id=%d, struct=%d, frame_num=%d", + currSlice->slice_type, currSlice->layer_id, currSlice->active_sps->seq_parameter_set_id, + currSlice->active_pps->pic_parameter_set_id, currSlice->structure, currSlice->frame_num); + } + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_slice.h b/mpp/codec/dec/h264/h264d_slice.h index 8558615f6..b7d00d9e2 100644 --- a/mpp/codec/dec/h264/h264d_slice.h +++ b/mpp/codec/dec/h264/h264d_slice.h @@ -1,39 +1,42 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __H264D_SLICE_H__ -#define __H264D_SLICE_H__ - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_global.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -void recycle_slice(H264_SLICE_t *currSlice); -MPP_RET process_slice(H264_SLICE_t *currSlice); - -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of __H264D_SLICE_H__ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_SLICE_H +#define H264D_SLICE_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + + + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET process_slice(H264_SLICE_t *currSlice); + +MPP_RET reset_cur_slice(H264dCurCtx_t *p_Cur, H264_SLICE_t *p); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* H264D_SLICE_H */ + diff --git a/mpp/codec/dec/h264/h264d_sps.c b/mpp/codec/dec/h264/h264d_sps.c index 04a608167..13e432a35 100644 --- a/mpp/codec/dec/h264/h264d_sps.c +++ b/mpp/codec/dec/h264/h264d_sps.c @@ -1,537 +1,628 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include - -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "h264d_bitread.h" -#include "h264d_sps.h" -#include "h264d_scalist.h" -#include "h264d_dpb.h" - - -#define MODULE_TAG "h264d_sps" - -static void reset_cur_sps_data(H264_SPS_t *cur_sps) -{ - memset(cur_sps, 0, sizeof(H264_SPS_t)); - cur_sps->seq_parameter_set_id = -1; // reset -} - -static void reset_cur_subpps_data(H264_subSPS_t *cur_subpps) -{ - memset(cur_subpps, 0, sizeof(H264_subSPS_t)); - cur_subpps->sps.seq_parameter_set_id = -1; // reset - cur_subpps->num_views_minus1 = -1; - cur_subpps->num_level_values_signalled_minus1 = -1; -} - -static MPP_RET read_hrd_parameters(BitReadCtx_t *p_bitctx, H264_HRD_t *hrd) -{ - RK_U32 SchedSelIdx = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - - READ_UE(ret, p_bitctx, &hrd->cpb_cnt_minus1, "cpb_cnt_minus1"); - READ_BITS(ret, p_bitctx, 4, &hrd->bit_rate_scale, "bit_rate_scale"); - READ_BITS(ret, p_bitctx, 4, &hrd->cpb_size_scale, "cpb_size_scale"); - for (SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) { - READ_UE(ret, p_bitctx, &hrd->bit_rate_value_minus1[SchedSelIdx], "VUI: bit_rate_value_minus1"); - READ_UE(ret, p_bitctx, &hrd->cpb_size_value_minus1[SchedSelIdx], "VUI: cpb_size_value_minus1"); - READ_ONEBIT(ret, p_bitctx, &hrd->cbr_flag[SchedSelIdx], "VUI: cbr_flag"); - } - READ_BITS(ret, p_bitctx, 5, &hrd->initial_cpb_removal_delay_length_minus1, "initial_cpb_removal_delay_length_minus1"); - READ_BITS(ret, p_bitctx, 5, &hrd->cpb_removal_delay_length_minus1, "cpb_removal_delay_length_minus1"); - READ_BITS(ret, p_bitctx, 5, &hrd->dpb_output_delay_length_minus1, "dpb_output_delay_length_minus1"); - READ_BITS(ret, p_bitctx, 5, &hrd->time_offset_length, "time_offset_length"); - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static void init_VUI(H264_VUI_t *vui) -{ - vui->matrix_coefficients = 2; -} - -static MPP_RET read_VUI(BitReadCtx_t *p_bitctx, H264_VUI_t *vui) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - READ_ONEBIT(ret, p_bitctx, &vui->aspect_ratio_info_present_flag, "vui.aspect_ratio_info_present_flag"); - if (vui->aspect_ratio_info_present_flag) { - READ_BITS(ret, p_bitctx, 8, &vui->aspect_ratio_idc, "vui.aspect_ratio_idc"); - if (255 == vui->aspect_ratio_idc) { - READ_BITS(ret, p_bitctx, 16, &vui->sar_width, "VUI: sar_width"); - READ_BITS(ret, p_bitctx, 16, &vui->sar_height, "VUI: sar_height"); - } - } - READ_ONEBIT(ret, p_bitctx, &vui->overscan_info_present_flag, "VUI: overscan_info_present_flag"); - if (vui->overscan_info_present_flag) { - READ_ONEBIT(ret, p_bitctx, &vui->overscan_appropriate_flag, "VUI: overscan_appropriate_flag"); - } - READ_ONEBIT(ret, p_bitctx, &vui->video_signal_type_present_flag, "VUI: video_signal_type_present_flag"); - if (vui->video_signal_type_present_flag) { - READ_BITS(ret, p_bitctx, 3, &vui->video_format, "VUI: video_format"); - READ_ONEBIT(ret, p_bitctx, &vui->video_full_range_flag, "VUI: video_full_range_flag"); - READ_ONEBIT(ret, p_bitctx, &vui->colour_description_present_flag, "VUI: color_description_present_flag"); - if (vui->colour_description_present_flag) { - READ_BITS(ret, p_bitctx, 8, &vui->colour_primaries, "VUI: colour_primaries"); - READ_BITS(ret, p_bitctx, 8, &vui->transfer_characteristics, "VUI: transfer_characteristics"); - READ_BITS(ret, p_bitctx, 8, &vui->matrix_coefficients, "VUI: matrix_coefficients"); - } - } - READ_ONEBIT(ret, p_bitctx, &vui->chroma_location_info_present_flag, "VUI: chroma_location_info_present_flag"); - if (vui->chroma_location_info_present_flag) { - READ_UE(ret, p_bitctx, &vui->chroma_sample_loc_type_top_field, "VUI: chroma_sample_loc_type_top_field"); - READ_UE(ret, p_bitctx, &vui->chroma_sample_loc_type_bottom_field, "VUI: chroma_sample_loc_type_bottom_field"); - } - READ_ONEBIT(ret, p_bitctx, &vui->timing_info_present_flag, "VUI: timing_info_present_flag"); - if (vui->timing_info_present_flag) { - READ_BITS(ret, p_bitctx, 16, &vui->num_units_in_tick, "VUI: num_units_in_tick(high 16bit)"); - READ_BITS(ret, p_bitctx, 16, &vui->num_units_in_tick, "VUI: num_units_in_tick(low 16bit)"); - READ_BITS(ret, p_bitctx, 16, &vui->time_scale, "VUI: time_scale(high 16bit)"); - READ_BITS(ret, p_bitctx, 16, &vui->time_scale, "VUI: time_scale(low 16bit)"); - READ_ONEBIT(ret, p_bitctx, &vui->fixed_frame_rate_flag, "VUI: fixed_frame_rate_flag"); - } - READ_ONEBIT(ret, p_bitctx, &vui->nal_hrd_parameters_present_flag, "VUI: nal_hrd_parameters_present_flag"); - if (vui->nal_hrd_parameters_present_flag) { - FUN_CHECK(ret = read_hrd_parameters(p_bitctx, &vui->nal_hrd_parameters)); - } - READ_ONEBIT(ret, p_bitctx, &vui->vcl_hrd_parameters_present_flag, "VUI: vcl_hrd_parameters_present_flag"); - if (vui->vcl_hrd_parameters_present_flag) { - FUN_CHECK(ret = read_hrd_parameters(p_bitctx, &vui->vcl_hrd_parameters)); - } - if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) { - READ_ONEBIT(ret, p_bitctx, &vui->low_delay_hrd_flag, "VUI: low_delay_hrd_flag"); - } - READ_ONEBIT(ret, p_bitctx, &vui->pic_struct_present_flag, "VUI: pic_struct_present_flag"); - READ_ONEBIT(ret, p_bitctx, &vui->bitstream_restriction_flag, "VUI: bitstream_restriction_flag"); - if (vui->bitstream_restriction_flag) { - READ_ONEBIT(ret, p_bitctx, &vui->motion_vectors_over_pic_boundaries_flag, "VUI: motion_vectors_over_pic_boundaries_flag"); - READ_UE(ret, p_bitctx, &vui->max_bytes_per_pic_denom, "VUI: max_bytes_per_pic_denom"); - READ_UE(ret, p_bitctx, &vui->max_bits_per_mb_denom, "VUI: max_bits_per_mb_denom"); - READ_UE(ret, p_bitctx, &vui->log2_max_mv_length_horizontal, "VUI: log2_max_mv_length_horizontal"); - READ_UE(ret, p_bitctx, &vui->log2_max_mv_length_vertical, "VUI: log2_max_mv_length_vertical"); - READ_UE(ret, p_bitctx, &vui->num_reorder_frames, "VUI: num_reorder_frames"); - READ_UE(ret, p_bitctx, &vui->max_dec_frame_buffering, "VUI: max_dec_frame_buffering"); - } - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static MPP_RET parser_sps(BitReadCtx_t *p_bitctx, H264_SPS_t *cur_sps) -{ - RK_S32 i = 0, temp = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - //!< init Fidelity Range Extensions stuff - cur_sps->chroma_format_idc = 1; - cur_sps->bit_depth_luma_minus8 = 0; - cur_sps->bit_depth_chroma_minus8 = 0; - cur_sps->qpprime_y_zero_transform_bypass_flag = 0; - cur_sps->separate_colour_plane_flag = 0; - cur_sps->log2_max_pic_order_cnt_lsb_minus4 = 0; - cur_sps->delta_pic_order_always_zero_flag = 0; - WRITE_LOG(p_bitctx, "----------------------------- SPS begin --------------------------------"); - READ_BITS(ret, p_bitctx, 8, &cur_sps->profile_idc, "profile_idc"); - VAL_CHECK (ret, (cur_sps->profile_idc == BASELINE) || (cur_sps->profile_idc == H264_MAIN) - || (cur_sps->profile_idc == EXTENDED) || (cur_sps->profile_idc == FREXT_HP) - || (cur_sps->profile_idc == FREXT_Hi10P) || (cur_sps->profile_idc == FREXT_Hi422) - || (cur_sps->profile_idc == FREXT_Hi444) || (cur_sps->profile_idc == FREXT_CAVLC444) - || (cur_sps->profile_idc == MVC_HIGH) || (cur_sps->profile_idc == STEREO_HIGH) - ); - READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set0_flag, "constrained_set0_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set1_flag, "constrained_set1_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set2_flag, "constrained_set2_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set3_flag, "constrained_set3_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set4_flag, "constrained_set4_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->constrained_set5_flag, "constrained_set5_flag"); - READ_BITS(ret, p_bitctx, 2, &temp, "reserved_zero_2bits"); // reserved_zero_2bits - ASSERT(temp == 0); - READ_BITS(ret, p_bitctx, 8, &cur_sps->level_idc, "level_idc"); - READ_UE(ret, p_bitctx, &cur_sps->seq_parameter_set_id, "seq_parameter_set_id"); - ASSERT(cur_sps->seq_parameter_set_id < 32); - - if (cur_sps->profile_idc == 100 || cur_sps->profile_idc == 110 - || cur_sps->profile_idc == 122 || cur_sps->profile_idc == 244 - || cur_sps->profile_idc == 44 || cur_sps->profile_idc == 83 - || cur_sps->profile_idc == 86 || cur_sps->profile_idc == 118 - || cur_sps->profile_idc == 128 || cur_sps->profile_idc == 138) { - READ_UE(ret, p_bitctx, &cur_sps->chroma_format_idc, "chroma_format_idc"); - ASSERT(cur_sps->chroma_format_idc < 4); - - if (cur_sps->chroma_format_idc == 3) { - READ_ONEBIT(ret, p_bitctx, &cur_sps->separate_colour_plane_flag, "separate_colour_plane_flag"); - LogError(p_bitctx->ctx, "Not support YUV444 format current."); - } - - READ_UE(ret, p_bitctx, &cur_sps->bit_depth_luma_minus8, "bit_depth_luma_minus8"); - ASSERT(cur_sps->bit_depth_luma_minus8 < 7); - READ_UE(ret, p_bitctx, &cur_sps->bit_depth_chroma_minus8, "bit_depth_chroma_minus8"); - ASSERT(cur_sps->bit_depth_chroma_minus8 < 7); - READ_ONEBIT(ret, p_bitctx, &cur_sps->qpprime_y_zero_transform_bypass_flag, "qpprime_y_zero_transform_bypass_flag"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->seq_scaling_matrix_present_flag, "seq_scaling_matrix_present_flag"); - if (cur_sps->seq_scaling_matrix_present_flag) { - LogInfo(p_bitctx->ctx, "Scaling matrix present."); - if (parse_sps_scalinglists(p_bitctx, cur_sps)) { - LogError(p_bitctx->ctx, "rkv_parse_sps_scalinglists error."); - } - } - } - READ_UE(ret, p_bitctx, &cur_sps->log2_max_frame_num_minus4, "log2_max_frame_num_minus4"); - ASSERT(cur_sps->log2_max_frame_num_minus4 < 13); - READ_UE(ret, p_bitctx, &cur_sps->pic_order_cnt_type, "pic_order_cnt_type"); - ASSERT(cur_sps->pic_order_cnt_type < 3); - - cur_sps->log2_max_pic_order_cnt_lsb_minus4 = 0; - cur_sps->delta_pic_order_always_zero_flag = RET_FALSE; - if (0 == cur_sps->pic_order_cnt_type) { - READ_UE(ret, p_bitctx, &cur_sps->log2_max_pic_order_cnt_lsb_minus4, "log2_max_pic_order_cnt_lsb_minus4"); - ASSERT(cur_sps->log2_max_pic_order_cnt_lsb_minus4 < 13); - } else if (1 == cur_sps->pic_order_cnt_type) { - READ_ONEBIT(ret, p_bitctx, &cur_sps->delta_pic_order_always_zero_flag, "delta_pic_order_always_zero_flag"); - READ_SE(ret, p_bitctx, &cur_sps->offset_for_non_ref_pic, "offset_for_non_ref_pic"); - READ_SE(ret, p_bitctx, &cur_sps->offset_for_top_to_bottom_field, "offset_for_top_to_bottom_field"); - READ_UE(ret, p_bitctx, &cur_sps->num_ref_frames_in_pic_order_cnt_cycle, "num_ref_frames_in_pic_order_cnt_cycle"); - ASSERT(cur_sps->num_ref_frames_in_pic_order_cnt_cycle < 256); - for (i = 0; i < cur_sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) { - READ_SE(ret, p_bitctx, &cur_sps->offset_for_ref_frame[i], "offset_for_ref_frame"); - cur_sps->expected_delta_per_pic_order_cnt_cycle += cur_sps->offset_for_ref_frame[i]; - } - } - READ_UE(ret, p_bitctx, &cur_sps->max_num_ref_frames, "max_num_ref_frames"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->gaps_in_frame_num_value_allowed_flag, "gaps_in_frame_num_value_allowed_flag"); - READ_UE(ret, p_bitctx, &cur_sps->pic_width_in_mbs_minus1, "pic_width_in_mbs_minus1"); - READ_UE(ret, p_bitctx, &cur_sps->pic_height_in_map_units_minus1, "pic_height_in_map_units_minus1"); - READ_ONEBIT(ret, p_bitctx, &cur_sps->frame_mbs_only_flag, "frame_mbs_only_flag"); - if (!cur_sps->frame_mbs_only_flag) { - READ_ONEBIT(ret, p_bitctx, &cur_sps->mb_adaptive_frame_field_flag, "mb_adaptive_frame_field_flag"); - } - READ_ONEBIT(ret, p_bitctx, &cur_sps->direct_8x8_inference_flag, "direct_8x8_inference_flag"); - - READ_ONEBIT(ret, p_bitctx, &cur_sps->frame_cropping_flag, "frame_cropping_flag"); - if (cur_sps->frame_cropping_flag) { - READ_UE(ret, p_bitctx, &cur_sps->frame_crop_left_offset, "frame_crop_left_offset"); - READ_UE(ret, p_bitctx, &cur_sps->frame_crop_right_offset, "frame_crop_right_offset"); - READ_UE(ret, p_bitctx, &cur_sps->frame_crop_top_offset, "frame_crop_top_offset"); - READ_UE(ret, p_bitctx, &cur_sps->frame_crop_bottom_offset, "frame_crop_bottom_offset"); - } - READ_ONEBIT(ret, p_bitctx, &cur_sps->vui_parameters_present_flag, "vui_parameters_present_flag"); - - init_VUI(&cur_sps->vui_seq_parameters); - if (cur_sps->vui_parameters_present_flag) { - FUN_CHECK(ret = read_VUI(p_bitctx, &cur_sps->vui_seq_parameters)); - } - cur_sps->Valid = 1; - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static MPP_RET sps_mvc_extension(BitReadCtx_t *p_bitctx, H264_subSPS_t *subset_sps) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - RK_S32 i = 0, j = 0, num_views = 0; - - READ_UE(ret, p_bitctx, &subset_sps->num_views_minus1, "SPS_MVC_EXT:num_views_minus1"); - num_views = 1 + subset_sps->num_views_minus1; - //======================== - if (num_views > 0) { - subset_sps->view_id = mpp_calloc(RK_S32, num_views); - subset_sps->num_anchor_refs_l0 = mpp_calloc(RK_S32, num_views); - subset_sps->num_anchor_refs_l1 = mpp_calloc(RK_S32, num_views); - subset_sps->anchor_ref_l0 = mpp_calloc(RK_S32*, num_views); - subset_sps->anchor_ref_l1 = mpp_calloc(RK_S32*, num_views); - subset_sps->num_non_anchor_refs_l0 = mpp_calloc(RK_S32, num_views); - subset_sps->num_non_anchor_refs_l1 = mpp_calloc(RK_S32, num_views); - subset_sps->non_anchor_ref_l0 = mpp_calloc(RK_S32*, num_views); - subset_sps->non_anchor_ref_l1 = mpp_calloc(RK_S32*, num_views); - MEM_CHECK(ret, subset_sps->view_id && subset_sps->num_anchor_refs_l0 - && subset_sps->num_anchor_refs_l1 && subset_sps->anchor_ref_l0 - && subset_sps->anchor_ref_l1 && subset_sps->num_non_anchor_refs_l0 - && subset_sps->num_non_anchor_refs_l1 && subset_sps->non_anchor_ref_l0 - && subset_sps->non_anchor_ref_l1); - } - for (i = 0; i < num_views; i++) { - READ_UE(ret, p_bitctx, &subset_sps->view_id[i], "SPS_MVC_EXT: view_id"); - } - for (i = 1; i < num_views; i++) { - READ_UE(ret, p_bitctx, &subset_sps->num_anchor_refs_l0[i], "SPS_MVC_EXT: num_anchor_refs_l0"); - if (subset_sps->num_anchor_refs_l0[i]) { - subset_sps->anchor_ref_l0[i] = mpp_calloc(RK_S32, subset_sps->num_anchor_refs_l0[i]); - MEM_CHECK(ret, subset_sps->anchor_ref_l0[i]); - for (j = 0; j < subset_sps->num_anchor_refs_l0[i]; j++) { - READ_UE(ret, p_bitctx, &subset_sps->anchor_ref_l0[i][j], "SPS_MVC_EXT: anchor_ref_l0"); - } - } - READ_UE(ret, p_bitctx, &subset_sps->num_anchor_refs_l1[i], "SPS_MVC_EXT: num_anchor_refs_l1"); - if (subset_sps->num_anchor_refs_l1[i]) { - subset_sps->anchor_ref_l1[i] = mpp_calloc(RK_S32, subset_sps->num_anchor_refs_l1[i]); - MEM_CHECK(ret, subset_sps->anchor_ref_l1[i]); - for (j = 0; j < subset_sps->num_anchor_refs_l1[i]; j++) { - READ_UE(ret, p_bitctx, &subset_sps->anchor_ref_l1[i][j], "SPS_MVC_EXT: anchor_ref_l0"); - } - } - } - for (i = 1; i < num_views; i++) { - READ_UE(ret, p_bitctx, &subset_sps->num_non_anchor_refs_l0[i], "SPS_MVC_EXT: num_non_anchor_refs_l0"); - if (subset_sps->num_non_anchor_refs_l0[i]) { - subset_sps->non_anchor_ref_l0[i] = mpp_calloc(RK_S32, subset_sps->num_non_anchor_refs_l0[i]); - MEM_CHECK(ret, subset_sps->non_anchor_ref_l0[i]); - for (j = 0; j < subset_sps->num_non_anchor_refs_l0[i]; j++) { - READ_UE(ret, p_bitctx, &subset_sps->non_anchor_ref_l0[i][j], "SPS_MVC_EXT: non_anchor_ref_l0"); - } - } - READ_UE(ret, p_bitctx, &subset_sps->num_non_anchor_refs_l1[i], "SPS_MVC_EXT: num_non_anchor_refs_l1"); - if (subset_sps->num_non_anchor_refs_l1[i]) { - subset_sps->non_anchor_ref_l1[i] = mpp_calloc(RK_S32, subset_sps->num_non_anchor_refs_l1[i]); - MEM_CHECK(ret, subset_sps->non_anchor_ref_l1[i]); - - for (j = 0; j < subset_sps->num_non_anchor_refs_l1[i]; j++) { - READ_UE(ret, p_bitctx, &subset_sps->non_anchor_ref_l1[i][j], "SPS_MVC_EXT: non_anchor_ref_l1"); - } - } - } - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - -static MPP_RET parser_subsps_ext(BitReadCtx_t *p_bitctx, H264_subSPS_t *cur_subsps) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - if ((cur_subsps->sps.profile_idc == MVC_HIGH) - || (cur_subsps->sps.profile_idc == STEREO_HIGH)) { - READ_ONEBIT(ret, p_bitctx, &cur_subsps->bit_equal_to_one, "bit_equal_to_one"); - ASSERT(cur_subsps->bit_equal_to_one == 1); - FUN_CHECK(ret = sps_mvc_extension(p_bitctx, cur_subsps)); - - READ_ONEBIT(ret, p_bitctx, &cur_subsps->mvc_vui_parameters_present_flag, "mvc_vui_parameters_present_flag"); - } - - return ret = MPP_OK; -__FAILED: - return ret; -} - -static void update_video_pars(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps) -{ - p_Vid->max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); - p_Vid->PicWidthInMbs = (sps->pic_width_in_mbs_minus1 + 1); - p_Vid->FrameHeightInMbs = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1); - p_Vid->yuv_format = sps->chroma_format_idc; - - p_Vid->width = p_Vid->PicWidthInMbs * MB_BLOCK_SIZE; - p_Vid->height = p_Vid->FrameHeightInMbs * MB_BLOCK_SIZE; - - if (p_Vid->yuv_format == YUV420) { - p_Vid->width_cr = (p_Vid->width >> 1); - p_Vid->height_cr = (p_Vid->height >> 1); - } else if (p_Vid->yuv_format == YUV422) { - p_Vid->width_cr = (p_Vid->width >> 1); - p_Vid->height_cr = p_Vid->height; - } -} - -static RK_U32 video_pars_changed(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, RK_U8 layer_id) -{ - RK_U32 ret = 0; - - ret |= p_Vid->p_Dpb_layer[layer_id]->num_ref_frames != sps->max_num_ref_frames; - ret |= p_Vid->last_pic_width_in_mbs_minus1[layer_id] != sps->pic_width_in_mbs_minus1; - ret |= p_Vid->last_pic_height_in_map_units_minus1[layer_id] != sps->pic_height_in_map_units_minus1; - ret |= p_Vid->last_profile_idc[layer_id] != sps->profile_idc; - ret |= p_Vid->last_level_idc[layer_id] != sps->level_idc; - ret |= !p_Vid->p_Dpb_layer[layer_id]->init_done; - - return ret; -} - -static void update_last_video_pars(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, RK_U8 layer_id) -{ - p_Vid->last_pic_width_in_mbs_minus1[layer_id] = sps->pic_width_in_mbs_minus1; - p_Vid->last_pic_height_in_map_units_minus1[layer_id] = sps->pic_height_in_map_units_minus1; - p_Vid->last_profile_idc[layer_id] = sps->profile_idc; - p_Vid->last_level_idc[layer_id] = sps->level_idc; -} - -/*! -*********************************************************************** -* \brief -* prase sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET process_sps(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dLogCtx_t *logctx = currSlice->logctx; - H264dCurCtx_t *p_Cur = currSlice->p_Cur; - BitReadCtx_t *p_bitctx = &p_Cur->bitctx; - H264_SPS_t *cur_sps = &p_Cur->sps; - - FunctionIn(logctx->parr[RUN_PARSE]); - reset_cur_sps_data(cur_sps); // reset - set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_SPS]); - //!< parse sps - FUN_CHECK(ret = parser_sps(p_bitctx, cur_sps)); - //!< decide "max_dec_frame_buffering" for DPB - FUN_CHECK(ret = get_max_dec_frame_buf_size(cur_sps)); - //!< make SPS available, copy - if (cur_sps->Valid) { - memcpy(&currSlice->p_Vid->spsSet[cur_sps->seq_parameter_set_id], cur_sps, sizeof(H264_SPS_t)); - } - FunctionOut(logctx->parr[RUN_PARSE]); - - return ret = MPP_OK; -__FAILED: - ASSERT(0); - return ret; -} - - -/*! -*********************************************************************** -* \brief -* prase sps and process sps -*********************************************************************** -*/ -//extern "C" -void recycle_subsps(H264_subSPS_t *subset_sps) -{ - RK_S32 i = 0, num_views = 0; - - num_views = 1 + subset_sps->num_views_minus1; - for (i = 1; i < num_views; i++) { - if (subset_sps->num_anchor_refs_l0[i] > 0) { - mpp_free(subset_sps->anchor_ref_l0[i]); - } - if (subset_sps->num_anchor_refs_l1[i] > 0) { - mpp_free(subset_sps->anchor_ref_l1[i]); - } - if (subset_sps->num_non_anchor_refs_l0[i] > 0) { - mpp_free(subset_sps->non_anchor_ref_l0[i]); - } - if (subset_sps->num_non_anchor_refs_l1[i] > 0) { - mpp_free(subset_sps->non_anchor_ref_l1[i]); - } - } - if (num_views > 0) { - mpp_free(subset_sps->view_id); - mpp_free(subset_sps->num_anchor_refs_l0); - mpp_free(subset_sps->num_anchor_refs_l1); - mpp_free(subset_sps->anchor_ref_l0); - mpp_free(subset_sps->anchor_ref_l1); - mpp_free(subset_sps->num_non_anchor_refs_l0); - mpp_free(subset_sps->num_non_anchor_refs_l1); - mpp_free(subset_sps->non_anchor_ref_l0); - mpp_free(subset_sps->non_anchor_ref_l1); - } - subset_sps->Valid = 0; -} - -/*! -*********************************************************************** -* \brief -* prase sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET process_subsps(H264_SLICE_t *currSlice) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dLogCtx_t *logctx = currSlice->logctx; - BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; - H264_subSPS_t *cur_subsps = &currSlice->p_Cur->subsps; - H264_subSPS_t *p_subset = NULL; - - FunctionIn(logctx->parr[RUN_PARSE]); - reset_cur_subpps_data(cur_subsps); //reset - set_bitread_logctx(p_bitctx, logctx->parr[LOG_READ_SUBSPS]); - WRITE_LOG(p_bitctx, "----------------------------- subSPS begin --------------------------------"); - FUN_CHECK(ret = parser_sps(p_bitctx, &cur_subsps->sps)); - FUN_CHECK(ret = parser_subsps_ext(p_bitctx, cur_subsps)); - if (cur_subsps->sps.Valid) { - cur_subsps->Valid = 1; - currSlice->p_Vid->profile_idc = cur_subsps->sps.profile_idc; - } - get_max_dec_frame_buf_size(&cur_subsps->sps); - //!< make subSPS available - p_subset = &currSlice->p_Vid->subspsSet[cur_subsps->sps.seq_parameter_set_id]; - if (p_subset->Valid) { - recycle_subsps(p_subset); - } - memcpy(p_subset, cur_subsps, sizeof(H264_subSPS_t)); - FunctionOut(logctx->parr[RUN_PARSE]); - - return ret = MPP_OK; -__FAILED: - recycle_subsps(&currSlice->p_Cur->subsps); - //ASSERT(0); - - return ret; -} - -/*! -*********************************************************************** -* \brief -* prase sps and process sps -*********************************************************************** -*/ -//extern "C" -MPP_RET activate_sps(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, H264_subSPS_t *subset_sps) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - if (p_Vid->dec_picture) { - FUN_CHECK(ret = exit_picture(p_Vid, &p_Vid->dec_picture)); - } - if (p_Vid->active_mvc_sps_flag) { // layer_id == 1 - p_Vid->active_sps = &subset_sps->sps; - p_Vid->active_subsps = subset_sps; - p_Vid->active_sps_id[0] = 0; - p_Vid->active_sps_id[1] = subset_sps->sps.seq_parameter_set_id; - if (video_pars_changed(p_Vid, p_Vid->active_sps, 1)) { - FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1])); - FUN_CHECK(ret = init_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2)); - update_last_video_pars(p_Vid, p_Vid->active_sps, 1); - } - } else { //!< layer_id == 0 - p_Vid->active_sps = sps; - p_Vid->active_subsps = NULL; - p_Vid->active_sps_id[0] = sps->seq_parameter_set_id; - p_Vid->active_sps_id[1] = 0; - if (video_pars_changed(p_Vid, p_Vid->active_sps, 0)) { - if (!p_Vid->no_output_of_prior_pics_flag) { - FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0])); - } - FUN_CHECK(ret = init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1)); - update_last_video_pars(p_Vid, p_Vid->active_sps, 0); - } - } - update_video_pars(p_Vid, p_Vid->active_sps); - - return ret = MPP_OK; -__FAILED: - return ret; -} +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "h264d_sps" + +#include + +#include "mpp_mem.h" + +#include "h264d_global.h" +#include "h264d_sps.h" +#include "h264d_scalist.h" +#include "h264d_dpb.h" + +#define MAX_CPB 240000 /* for level 5.1 */ +#define MAX_BR 240000 /* for level 5.1 */ + +static void reset_cur_sps_data(H264_SPS_t *cur_sps) +{ + memset(cur_sps, 0, sizeof(H264_SPS_t)); + cur_sps->seq_parameter_set_id = 0; // reset +} + +static void reset_cur_subpps_data(H264_subSPS_t *cur_subpps) +{ + memset(cur_subpps, 0, sizeof(H264_subSPS_t)); + cur_subpps->sps.seq_parameter_set_id = 0; // reset + cur_subpps->num_views_minus1 = -1; + cur_subpps->num_level_values_signalled_minus1 = -1; +} + +static MPP_RET read_hrd_parameters(BitReadCtx_t *p_bitctx, H264_HRD_t *hrd) +{ + RK_U32 SchedSelIdx = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + READ_UE(p_bitctx, &hrd->cpb_cnt_minus1); + VAL_CHECK(ret, hrd->cpb_cnt_minus1 < MAXIMUMVALUEOFcpb_cnt); + hrd->cpb_cnt_minus1 += 1; + READ_BITS(p_bitctx, 4, &hrd->bit_rate_scale); + READ_BITS(p_bitctx, 4, &hrd->cpb_size_scale); + for (SchedSelIdx = 0; SchedSelIdx < hrd->cpb_cnt_minus1; SchedSelIdx++) { + READ_UE(p_bitctx, &hrd->bit_rate_value_minus1[SchedSelIdx]); + READ_UE(p_bitctx, &hrd->cpb_size_value_minus1[SchedSelIdx]); + READ_ONEBIT(p_bitctx, &hrd->cbr_flag[SchedSelIdx]); + } + READ_BITS(p_bitctx, 5, &hrd->initial_cpb_removal_delay_length_minus1); + hrd->initial_cpb_removal_delay_length_minus1 += 1; + READ_BITS(p_bitctx, 5, &hrd->cpb_removal_delay_length_minus1); + hrd->cpb_removal_delay_length_minus1 += 1; + READ_BITS(p_bitctx, 5, &hrd->dpb_output_delay_length_minus1); + hrd->dpb_output_delay_length_minus1 += 1; + READ_BITS(p_bitctx, 5, &hrd->time_offset_length); + + return ret = MPP_OK; +__BITREAD_ERR: + return ret = p_bitctx->ret; +__FAILED: + return ret; +} + +static void init_VUI(H264_VUI_t *vui) +{ + vui->matrix_coefficients = 2; +} + +static MPP_RET read_VUI(BitReadCtx_t *p_bitctx, H264_VUI_t *vui) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + READ_ONEBIT(p_bitctx, &vui->aspect_ratio_info_present_flag); + if (vui->aspect_ratio_info_present_flag) { + READ_BITS(p_bitctx, 8, &vui->aspect_ratio_idc); + if (255 == vui->aspect_ratio_idc) { + READ_BITS(p_bitctx, 16, &vui->sar_width); + READ_BITS(p_bitctx, 16, &vui->sar_height); + } + } + READ_ONEBIT(p_bitctx, &vui->overscan_info_present_flag); + if (vui->overscan_info_present_flag) { + READ_ONEBIT(p_bitctx, &vui->overscan_appropriate_flag); + } + READ_ONEBIT(p_bitctx, &vui->video_signal_type_present_flag); + if (vui->video_signal_type_present_flag) { + READ_BITS(p_bitctx, 3, &vui->video_format); + READ_ONEBIT(p_bitctx, &vui->video_full_range_flag); + READ_ONEBIT(p_bitctx, &vui->colour_description_present_flag); + if (vui->colour_description_present_flag) { + READ_BITS(p_bitctx, 8, &vui->colour_primaries); + READ_BITS(p_bitctx, 8, &vui->transfer_characteristics); + READ_BITS(p_bitctx, 8, &vui->matrix_coefficients); + if (vui->matrix_coefficients >= MPP_FRAME_SPC_NB) + vui->matrix_coefficients = MPP_FRAME_SPC_UNSPECIFIED; + } + } + READ_ONEBIT(p_bitctx, &vui->chroma_location_info_present_flag); + if (vui->chroma_location_info_present_flag) { + READ_UE(p_bitctx, &vui->chroma_sample_loc_type_top_field); + READ_UE(p_bitctx, &vui->chroma_sample_loc_type_bottom_field); + } + READ_ONEBIT(p_bitctx, &vui->timing_info_present_flag); + if (vui->timing_info_present_flag) { + READ_BITS_LONG(p_bitctx, 32, &vui->num_units_in_tick); + READ_BITS_LONG(p_bitctx, 32, &vui->time_scale); + READ_ONEBIT(p_bitctx, &vui->fixed_frame_rate_flag); + } + READ_ONEBIT(p_bitctx, &vui->nal_hrd_parameters_present_flag); + if (vui->nal_hrd_parameters_present_flag) { + FUN_CHECK(ret = read_hrd_parameters(p_bitctx, &vui->nal_hrd_parameters)); + } else { + vui->nal_hrd_parameters.cpb_cnt_minus1 = 1; + /* MaxBR and MaxCPB should be the values correspondig to the levelIdc + * in the SPS containing these VUI parameters. However, these values + * are not used anywhere and maximum for any level will be used here */ + vui->nal_hrd_parameters.bit_rate_value_minus1[0] = 1000 * MAX_BR + 1; + vui->nal_hrd_parameters.cpb_size_value_minus1[0] = 1000 * MAX_CPB + 1; + vui->nal_hrd_parameters.initial_cpb_removal_delay_length_minus1 = 24; + vui->nal_hrd_parameters.cpb_removal_delay_length_minus1 = 24; + vui->nal_hrd_parameters.dpb_output_delay_length_minus1 = 24; + vui->nal_hrd_parameters.time_offset_length = 24; + } + + READ_ONEBIT(p_bitctx, &vui->vcl_hrd_parameters_present_flag); + if (vui->vcl_hrd_parameters_present_flag) { + FUN_CHECK(ret = read_hrd_parameters(p_bitctx, &vui->vcl_hrd_parameters)); + } else { + vui->vcl_hrd_parameters.cpb_cnt_minus1 = 0; + /* MaxBR and MaxCPB should be the values correspondig to the levelIdc + * in the SPS containing these VUI parameters. However, these values + * are not used anywhere and maximum for any level will be used here */ + vui->vcl_hrd_parameters.bit_rate_value_minus1[0] = 1000 * MAX_BR + 1; + vui->vcl_hrd_parameters.cpb_size_value_minus1[0] = 1000 * MAX_CPB + 1; + vui->vcl_hrd_parameters.initial_cpb_removal_delay_length_minus1 = 24; + vui->vcl_hrd_parameters.cpb_removal_delay_length_minus1 = 24; + vui->vcl_hrd_parameters.dpb_output_delay_length_minus1 = 24; + vui->vcl_hrd_parameters.time_offset_length = 24; + } + if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) { + READ_ONEBIT(p_bitctx, &vui->low_delay_hrd_flag); + } + READ_ONEBIT(p_bitctx, &vui->pic_struct_present_flag); + READ_ONEBIT(p_bitctx, &vui->bitstream_restriction_flag); + if (vui->bitstream_restriction_flag) { + READ_ONEBIT(p_bitctx, &vui->motion_vectors_over_pic_boundaries_flag); + READ_UE(p_bitctx, &vui->max_bytes_per_pic_denom); + READ_UE(p_bitctx, &vui->max_bits_per_mb_denom); + READ_UE(p_bitctx, &vui->log2_max_mv_length_horizontal); + READ_UE(p_bitctx, &vui->log2_max_mv_length_vertical); + READ_UE(p_bitctx, &vui->num_reorder_frames); + READ_UE(p_bitctx, &vui->max_dec_frame_buffering); + } + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET parser_sps(BitReadCtx_t *p_bitctx, H264_SPS_t *cur_sps, H264_DecCtx_t *p_Dec) +{ + RK_S32 i = 0, temp = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + //!< init Fidelity Range Extensions stuff + cur_sps->chroma_format_idc = 1; + cur_sps->bit_depth_luma_minus8 = 0; + cur_sps->bit_depth_chroma_minus8 = 0; + cur_sps->qpprime_y_zero_transform_bypass_flag = 0; + cur_sps->separate_colour_plane_flag = 0; + cur_sps->log2_max_pic_order_cnt_lsb_minus4 = 0; + cur_sps->delta_pic_order_always_zero_flag = 0; + p_Dec->errctx.un_spt_flag = 0; // init unspport flag first + + READ_BITS(p_bitctx, 8, &cur_sps->profile_idc); + VAL_CHECK (ret, (cur_sps->profile_idc == H264_PROFILE_BASELINE) + || (cur_sps->profile_idc == H264_PROFILE_MAIN) + || (cur_sps->profile_idc == H264_PROFILE_EXTENDED) + || (cur_sps->profile_idc == H264_PROFILE_HIGH) + || (cur_sps->profile_idc == H264_PROFILE_HIGH10) + || (cur_sps->profile_idc == H264_PROFILE_HIGH422) + || (cur_sps->profile_idc == H264_PROFILE_HIGH444) + || (cur_sps->profile_idc == H264_PROFILE_FREXT_CAVLC444) + || (cur_sps->profile_idc == H264_PROFILE_MVC_HIGH) + || (cur_sps->profile_idc == H264_PROFILE_STEREO_HIGH) + ); + READ_ONEBIT(p_bitctx, &cur_sps->constrained_set0_flag); + READ_ONEBIT(p_bitctx, &cur_sps->constrained_set1_flag); + READ_ONEBIT(p_bitctx, &cur_sps->constrained_set2_flag); + READ_ONEBIT(p_bitctx, &cur_sps->constrained_set3_flag); + READ_ONEBIT(p_bitctx, &cur_sps->constrained_set4_flag); + READ_ONEBIT(p_bitctx, &cur_sps->constrained_set5_flag); + READ_BITS(p_bitctx, 2, &temp); //!< reserved_zero_2bits + ASSERT(temp == 0); + READ_BITS(p_bitctx, 8, &cur_sps->level_idc); + READ_UE(p_bitctx, &cur_sps->seq_parameter_set_id); + if (cur_sps->seq_parameter_set_id >= MAXSPS) { + cur_sps->seq_parameter_set_id = 0; + } + if (cur_sps->profile_idc == 100 || cur_sps->profile_idc == 110 + || cur_sps->profile_idc == 122 || cur_sps->profile_idc == 244 + || cur_sps->profile_idc == 44 || cur_sps->profile_idc == 83 + || cur_sps->profile_idc == 86 || cur_sps->profile_idc == 118 + || cur_sps->profile_idc == 128 || cur_sps->profile_idc == 138) { + READ_UE(p_bitctx, &cur_sps->chroma_format_idc); + /* check invalid chroma format idc */ + VAL_CHECK (ret, (cur_sps->chroma_format_idc <= H264_CHROMA_444)); + /* TODO: check unsupport chroma format by hardware capacity */ + if (cur_sps->chroma_format_idc > H264_CHROMA_422) { + H264D_ERR("ERROR: Not support chroma_format_idc %d", cur_sps->chroma_format_idc); + p_Dec->errctx.un_spt_flag = MPP_FRAME_ERR_UNSUPPORT; + goto __FAILED; + } + READ_UE(p_bitctx, &cur_sps->bit_depth_luma_minus8); + ASSERT(cur_sps->bit_depth_luma_minus8 < 7); + READ_UE(p_bitctx, &cur_sps->bit_depth_chroma_minus8); + ASSERT(cur_sps->bit_depth_chroma_minus8 < 7); + READ_ONEBIT(p_bitctx, &cur_sps->qpprime_y_zero_transform_bypass_flag); + if (cur_sps->qpprime_y_zero_transform_bypass_flag == 1) { + H264D_ERR("ERROR: Not support high 4:4:4 lossless mode"); + p_Dec->errctx.un_spt_flag = MPP_FRAME_ERR_UNSUPPORT; + goto __FAILED; + } + READ_ONEBIT(p_bitctx, &cur_sps->seq_scaling_matrix_present_flag); + if (cur_sps->seq_scaling_matrix_present_flag) { + H264D_WARNNING("Scaling matrix present."); + if (parse_sps_scalinglists(p_bitctx, cur_sps)) { + mpp_log_f(" parse_sps_scaling_list error."); + } + } + } + READ_UE(p_bitctx, &cur_sps->log2_max_frame_num_minus4); + ASSERT(cur_sps->log2_max_frame_num_minus4 < 13); + READ_UE(p_bitctx, &cur_sps->pic_order_cnt_type); + ASSERT(cur_sps->pic_order_cnt_type < 3); + + cur_sps->log2_max_pic_order_cnt_lsb_minus4 = 0; + cur_sps->delta_pic_order_always_zero_flag = 0; + if (0 == cur_sps->pic_order_cnt_type) { + READ_UE(p_bitctx, &cur_sps->log2_max_pic_order_cnt_lsb_minus4); + ASSERT(cur_sps->log2_max_pic_order_cnt_lsb_minus4 < 13); + } else if (1 == cur_sps->pic_order_cnt_type) { + READ_ONEBIT(p_bitctx, &cur_sps->delta_pic_order_always_zero_flag); + READ_SE(p_bitctx, &cur_sps->offset_for_non_ref_pic); + READ_SE(p_bitctx, &cur_sps->offset_for_top_to_bottom_field); + READ_UE(p_bitctx, &cur_sps->num_ref_frames_in_pic_order_cnt_cycle); + VAL_CHECK(ret, cur_sps->num_ref_frames_in_pic_order_cnt_cycle < 256); + for (i = 0; i < cur_sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) { + READ_SE(p_bitctx, &cur_sps->offset_for_ref_frame[i]); + cur_sps->expected_delta_per_pic_order_cnt_cycle += cur_sps->offset_for_ref_frame[i]; + } + } + READ_UE(p_bitctx, &cur_sps->max_num_ref_frames); + READ_ONEBIT(p_bitctx, &cur_sps->gaps_in_frame_num_value_allowed_flag); + READ_UE(p_bitctx, &cur_sps->pic_width_in_mbs_minus1); + READ_UE(p_bitctx, &cur_sps->pic_height_in_map_units_minus1); + READ_ONEBIT(p_bitctx, &cur_sps->frame_mbs_only_flag); + if (!cur_sps->frame_mbs_only_flag) { + READ_ONEBIT(p_bitctx, &cur_sps->mb_adaptive_frame_field_flag); + } + READ_ONEBIT(p_bitctx, &cur_sps->direct_8x8_inference_flag); + + READ_ONEBIT(p_bitctx, &cur_sps->frame_cropping_flag); + if (cur_sps->frame_cropping_flag) { + READ_UE(p_bitctx, &cur_sps->frame_crop_left_offset); + READ_UE(p_bitctx, &cur_sps->frame_crop_right_offset); + READ_UE(p_bitctx, &cur_sps->frame_crop_top_offset); + READ_UE(p_bitctx, &cur_sps->frame_crop_bottom_offset); + } + READ_ONEBIT(p_bitctx, &cur_sps->vui_parameters_present_flag); + + if (cur_sps->vui_parameters_present_flag) { + init_VUI(&cur_sps->vui_seq_parameters); + ret = read_VUI(p_bitctx, &cur_sps->vui_seq_parameters); + } + cur_sps->Valid = 1; + (void)p_Dec; + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET sps_mvc_extension(BitReadCtx_t *p_bitctx, H264_subSPS_t *subset_sps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 i = 0, j = 0, num_views = 0; + + READ_UE(p_bitctx, &subset_sps->num_views_minus1); + VAL_CHECK(ret, subset_sps->num_views_minus1 < 16); + num_views = 1 + subset_sps->num_views_minus1; + //======================== + if (num_views > 0) { + subset_sps->view_id = mpp_calloc(RK_S32, num_views); + subset_sps->num_anchor_refs_l0 = mpp_calloc(RK_S32, num_views); + subset_sps->num_anchor_refs_l1 = mpp_calloc(RK_S32, num_views); + subset_sps->anchor_ref_l0 = mpp_calloc(RK_S32*, num_views); + subset_sps->anchor_ref_l1 = mpp_calloc(RK_S32*, num_views); + subset_sps->num_non_anchor_refs_l0 = mpp_calloc(RK_S32, num_views); + subset_sps->num_non_anchor_refs_l1 = mpp_calloc(RK_S32, num_views); + subset_sps->non_anchor_ref_l0 = mpp_calloc(RK_S32*, num_views); + subset_sps->non_anchor_ref_l1 = mpp_calloc(RK_S32*, num_views); + MEM_CHECK(ret, subset_sps->view_id && subset_sps->num_anchor_refs_l0 + && subset_sps->num_anchor_refs_l1 && subset_sps->anchor_ref_l0 + && subset_sps->anchor_ref_l1 && subset_sps->num_non_anchor_refs_l0 + && subset_sps->num_non_anchor_refs_l1 && subset_sps->non_anchor_ref_l0 + && subset_sps->non_anchor_ref_l1); + } + for (i = 0; i < num_views; i++) { + READ_UE(p_bitctx, &subset_sps->view_id[i]); + } + for (i = 1; i < num_views; i++) { + READ_UE(p_bitctx, &subset_sps->num_anchor_refs_l0[i]); + if (subset_sps->num_anchor_refs_l0[i]) { + subset_sps->anchor_ref_l0[i] = mpp_calloc(RK_S32, subset_sps->num_anchor_refs_l0[i]); + MEM_CHECK(ret, subset_sps->anchor_ref_l0[i]); + for (j = 0; j < subset_sps->num_anchor_refs_l0[i]; j++) { + READ_UE(p_bitctx, &subset_sps->anchor_ref_l0[i][j]); + } + } + READ_UE(p_bitctx, &subset_sps->num_anchor_refs_l1[i]); + if (subset_sps->num_anchor_refs_l1[i]) { + subset_sps->anchor_ref_l1[i] = mpp_calloc(RK_S32, subset_sps->num_anchor_refs_l1[i]); + MEM_CHECK(ret, subset_sps->anchor_ref_l1[i]); + for (j = 0; j < subset_sps->num_anchor_refs_l1[i]; j++) { + READ_UE(p_bitctx, &subset_sps->anchor_ref_l1[i][j]); + } + } + } + for (i = 1; i < num_views; i++) { + READ_UE(p_bitctx, &subset_sps->num_non_anchor_refs_l0[i]); + if (subset_sps->num_non_anchor_refs_l0[i]) { + subset_sps->non_anchor_ref_l0[i] = mpp_calloc(RK_S32, subset_sps->num_non_anchor_refs_l0[i]); + MEM_CHECK(ret, subset_sps->non_anchor_ref_l0[i]); + for (j = 0; j < subset_sps->num_non_anchor_refs_l0[i]; j++) { + READ_UE(p_bitctx, &subset_sps->non_anchor_ref_l0[i][j]); + } + } + READ_UE(p_bitctx, &subset_sps->num_non_anchor_refs_l1[i]); + if (subset_sps->num_non_anchor_refs_l1[i]) { + subset_sps->non_anchor_ref_l1[i] = mpp_calloc(RK_S32, subset_sps->num_non_anchor_refs_l1[i]); + MEM_CHECK(ret, subset_sps->non_anchor_ref_l1[i]); + + for (j = 0; j < subset_sps->num_non_anchor_refs_l1[i]; j++) { + READ_UE(p_bitctx, &subset_sps->non_anchor_ref_l1[i][j]); + } + } + } + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + return ret; +} + +static MPP_RET parser_subsps_ext(BitReadCtx_t *p_bitctx, H264_subSPS_t *cur_subsps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + if ((cur_subsps->sps.profile_idc == H264_PROFILE_MVC_HIGH) + || (cur_subsps->sps.profile_idc == H264_PROFILE_STEREO_HIGH)) { + READ_ONEBIT(p_bitctx, &cur_subsps->bit_equal_to_one); + ASSERT(cur_subsps->bit_equal_to_one == 1); + FUN_CHECK(ret = sps_mvc_extension(p_bitctx, cur_subsps)); + + READ_ONEBIT(p_bitctx, &cur_subsps->mvc_vui_parameters_present_flag); + } + + return ret = MPP_OK; +__BITREAD_ERR: + ret = p_bitctx->ret; +__FAILED: + return ret; +} + +static void update_video_pars(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps) +{ + RK_U32 crop_left = 0, crop_right = 0; + RK_U32 crop_top = 0, crop_bottom = 0; + static const RK_U32 SubWidthC [4] = { 1, 2, 2, 1}; + static const RK_U32 SubHeightC [4] = { 1, 2, 1, 1}; + + + p_Vid->max_frame_num = 1 << (sps->log2_max_frame_num_minus4 + 4); + p_Vid->PicWidthInMbs = (sps->pic_width_in_mbs_minus1 + 1); + p_Vid->FrameHeightInMbs = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1); + p_Vid->yuv_format = sps->chroma_format_idc; + p_Vid->frame_mbs_only_flag = sps->frame_mbs_only_flag; + + p_Vid->width = p_Vid->PicWidthInMbs * 16; + p_Vid->height = p_Vid->FrameHeightInMbs * 16; + p_Vid->bit_depth_luma = sps->bit_depth_luma_minus8 + 8; + p_Vid->bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8; + + if (p_Vid->yuv_format == H264_CHROMA_420) { + p_Vid->width_cr = (p_Vid->width >> 1); + p_Vid->height_cr = (p_Vid->height >> 1); + } else if (p_Vid->yuv_format == H264_CHROMA_422) { + p_Vid->width_cr = (p_Vid->width >> 1); + p_Vid->height_cr = p_Vid->height; + } + //!< calculate frame_width_after_crop && frame_height_after_crop + if (sps->frame_cropping_flag) { + crop_left = SubWidthC [sps->chroma_format_idc] * sps->frame_crop_left_offset; + crop_right = SubWidthC [sps->chroma_format_idc] * sps->frame_crop_right_offset; + crop_top = SubHeightC[sps->chroma_format_idc] * ( 2 - sps->frame_mbs_only_flag ) * sps->frame_crop_top_offset; + crop_bottom = SubHeightC[sps->chroma_format_idc] * ( 2 - sps->frame_mbs_only_flag ) * sps->frame_crop_bottom_offset; + } else { + crop_left = crop_right = crop_top = crop_bottom = 0; + } + p_Vid->width_after_crop = p_Vid->width - crop_left - crop_right; + p_Vid->height_after_crop = p_Vid->height - crop_top - crop_bottom; +} + +static RK_U32 video_pars_changed(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, RK_U8 layer_id) +{ + RK_U32 ret = 0; + + ret |= p_Vid->p_Dpb_layer[layer_id]->num_ref_frames != sps->max_num_ref_frames; + ret |= p_Vid->last_pic_width_in_mbs_minus1[layer_id] != sps->pic_width_in_mbs_minus1; + ret |= p_Vid->last_pic_height_in_map_units_minus1[layer_id] != sps->pic_height_in_map_units_minus1; + ret |= p_Vid->last_profile_idc[layer_id] != sps->profile_idc; + ret |= p_Vid->last_level_idc[layer_id] != sps->level_idc; + ret |= !p_Vid->p_Dpb_layer[layer_id]->init_done; + + return ret; +} + +static void update_last_video_pars(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, RK_U8 layer_id) +{ + p_Vid->last_pic_width_in_mbs_minus1[layer_id] = sps->pic_width_in_mbs_minus1; + p_Vid->last_pic_height_in_map_units_minus1[layer_id] = sps->pic_height_in_map_units_minus1; + p_Vid->last_profile_idc[layer_id] = sps->profile_idc; + p_Vid->last_level_idc[layer_id] = sps->level_idc; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET process_sps(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dCurCtx_t *p_Cur = currSlice->p_Cur; + BitReadCtx_t *p_bitctx = &p_Cur->bitctx; + H264_SPS_t *cur_sps = &p_Cur->sps; + + reset_cur_sps_data(cur_sps); // reset + //!< parse sps + FUN_CHECK(ret = parser_sps(p_bitctx, cur_sps, currSlice->p_Dec)); + //!< decide "max_dec_frame_buffering" for DPB + FUN_CHECK(ret = get_max_dec_frame_buf_size(cur_sps)); + //!< make SPS available, copy + if (cur_sps->Valid) { + if (!currSlice->p_Vid->spsSet[cur_sps->seq_parameter_set_id]) { + currSlice->p_Vid->spsSet[cur_sps->seq_parameter_set_id] = mpp_calloc(H264_SPS_t, 1); + } + memcpy(currSlice->p_Vid->spsSet[cur_sps->seq_parameter_set_id], + cur_sps, sizeof(H264_SPS_t)); + } + p_Cur->p_Vid->spspps_update = 1; + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +void recycle_subsps(H264_subSPS_t *subset_sps) +{ + RK_S32 i = 0, num_views = 0; + + num_views = 1 + subset_sps->num_views_minus1; + for (i = 1; i < num_views; i++) { + if (subset_sps->num_anchor_refs_l0[i] > 0) { + MPP_FREE(subset_sps->anchor_ref_l0[i]); + } + if (subset_sps->num_anchor_refs_l1[i] > 0) { + MPP_FREE(subset_sps->anchor_ref_l1[i]); + } + if (subset_sps->num_non_anchor_refs_l0[i] > 0) { + MPP_FREE(subset_sps->non_anchor_ref_l0[i]); + } + if (subset_sps->num_non_anchor_refs_l1[i] > 0) { + MPP_FREE(subset_sps->non_anchor_ref_l1[i]); + } + } + if (num_views > 0) { + MPP_FREE(subset_sps->view_id); + MPP_FREE(subset_sps->num_anchor_refs_l0); + MPP_FREE(subset_sps->num_anchor_refs_l1); + MPP_FREE(subset_sps->anchor_ref_l0); + MPP_FREE(subset_sps->anchor_ref_l1); + MPP_FREE(subset_sps->num_non_anchor_refs_l0); + MPP_FREE(subset_sps->num_non_anchor_refs_l1); + MPP_FREE(subset_sps->non_anchor_ref_l0); + MPP_FREE(subset_sps->non_anchor_ref_l1); + } + subset_sps->Valid = 0; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET process_subsps(H264_SLICE_t *currSlice) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + BitReadCtx_t *p_bitctx = &currSlice->p_Cur->bitctx; + H264_subSPS_t *cur_subsps = NULL; + H264_subSPS_t *p_subset = NULL; + + if (!currSlice->p_Cur->subsps) + currSlice->p_Cur->subsps = mpp_calloc(H264_subSPS_t, 1); + + cur_subsps = currSlice->p_Cur->subsps; + reset_cur_subpps_data(cur_subsps); //reset + + FUN_CHECK(ret = parser_sps(p_bitctx, &cur_subsps->sps, currSlice->p_Dec)); + FUN_CHECK(ret = parser_subsps_ext(p_bitctx, cur_subsps)); + if (cur_subsps->sps.Valid) { + cur_subsps->Valid = 1; + currSlice->p_Vid->profile_idc = cur_subsps->sps.profile_idc; + } + get_max_dec_frame_buf_size(&cur_subsps->sps); + //!< make subSPS available + if (!currSlice->p_Vid->subspsSet[cur_subsps->sps.seq_parameter_set_id]) + currSlice->p_Vid->subspsSet[cur_subsps->sps.seq_parameter_set_id] = mpp_calloc(H264_subSPS_t, 1); + p_subset = currSlice->p_Vid->subspsSet[cur_subsps->sps.seq_parameter_set_id]; + if (p_subset->Valid) { + recycle_subsps(p_subset); + } + memcpy(p_subset, cur_subsps, sizeof(H264_subSPS_t)); + + return ret = MPP_OK; +__FAILED: + recycle_subsps(currSlice->p_Cur->subsps); + + return ret; +} + +/*! +*********************************************************************** +* \brief +* prase sps and process sps +*********************************************************************** +*/ +//extern "C" +MPP_RET activate_sps(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, H264_subSPS_t *subset_sps) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + INP_CHECK(ret, !p_Vid && !sps && !subset_sps); + if (p_Vid->dec_pic) { + FUN_CHECK(ret = exit_picture(p_Vid, &p_Vid->dec_pic)); + } + if (p_Vid->active_mvc_sps_flag) { // layer_id == 1 + p_Vid->active_sps = &subset_sps->sps; + p_Vid->active_subsps = subset_sps; + p_Vid->active_sps_id[0] = 0; + p_Vid->active_sps_id[1] = subset_sps->sps.seq_parameter_set_id; + if (video_pars_changed(p_Vid, p_Vid->active_sps, 1)) { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[1], 2)); + FUN_CHECK(ret = init_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2)); + FUN_CHECK(ret = check_mvc_dpb(p_Vid, p_Vid->p_Dpb_layer[0], p_Vid->p_Dpb_layer[1])); + update_last_video_pars(p_Vid, p_Vid->active_sps, 1); + //!< init frame slots, store frame buffer size + p_Vid->dpb_size[1] = p_Vid->p_Dpb_layer[1]->size; + p_Vid->spspps_update = 1; + if (p_Vid->p_Dec->mvc_valid && p_Vid->p_Dpb_layer[1]->size > 0) { + p_Vid->p_Dpb_layer[0]->size = MPP_MIN(p_Vid->p_Dpb_layer[1]->size, MAX_DPB_SIZE / 2); + p_Vid->dpb_size[0] = p_Vid->p_Dpb_layer[0]->size; + } + } + VAL_CHECK(ret, p_Vid->dpb_size[1] > 0); + } else { //!< layer_id == 0 + p_Vid->active_sps = sps; + p_Vid->active_subsps = NULL; + p_Vid->active_sps_id[0] = sps->seq_parameter_set_id; + p_Vid->active_sps_id[1] = 0; + if (video_pars_changed(p_Vid, p_Vid->active_sps, 0)) { + if (!p_Vid->no_output_of_prior_pics_flag) { + FUN_CHECK(ret = flush_dpb(p_Vid->p_Dpb_layer[0], 1)); + } + FUN_CHECK(ret = init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1)); + update_last_video_pars(p_Vid, p_Vid->active_sps, 0); + //!< init frame slots, store frame buffer size + p_Vid->dpb_size[0] = p_Vid->p_Dpb_layer[0]->size; + p_Vid->spspps_update = 1; + } + VAL_CHECK(ret, p_Vid->dpb_size[0] > 0); + } + H264D_DBG(H264D_DBG_DPB_INFO, "[DPB_size] dpb_size[0]=%d, mvc_flag=%d, dpb_size[1]=%d", + p_Vid->dpb_size[0], p_Vid->active_mvc_sps_flag, p_Vid->dpb_size[1]); + update_video_pars(p_Vid, p_Vid->active_sps); +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} diff --git a/mpp/codec/dec/h264/h264d_sps.h b/mpp/codec/dec/h264/h264d_sps.h index 0f336bd73..879c11325 100644 --- a/mpp/codec/dec/h264/h264d_sps.h +++ b/mpp/codec/dec/h264/h264d_sps.h @@ -1,41 +1,41 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef _H264D_SPS_H_ -#define _H264D_SPS_H_ - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_global.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET process_sps (H264_SLICE_t *currSlice); -void recycle_subsps(H264_subSPS_t *subset_sps); -MPP_RET process_subsps(H264_SLICE_t *currSlice); -MPP_RET activate_sps(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, H264_subSPS_t *subset_sps); - -#ifdef __cplusplus -} -#endif - -//======================================== -#endif /* end of _H264D_SPS_H_ */ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef H264D_SPS_H +#define H264D_SPS_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "h264d_global.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET process_sps (H264_SLICE_t *currSlice); +void recycle_subsps(H264_subSPS_t *subset_sps); +MPP_RET process_subsps(H264_SLICE_t *currSlice); +MPP_RET activate_sps(H264dVideoCtx_t *p_Vid, H264_SPS_t *sps, H264_subSPS_t *subset_sps); + +#ifdef __cplusplus +} +#endif + +//======================================== +#endif /* end of H264D_SPS_H */ + diff --git a/mpp/codec/dec/h265/CMakeLists.txt b/mpp/codec/dec/h265/CMakeLists.txt index b66fe4acf..9b9e2290c 100644 --- a/mpp/codec/dec/h265/CMakeLists.txt +++ b/mpp/codec/dec/h265/CMakeLists.txt @@ -1 +1,15 @@ # vim: syntax=cmake +include_directories(../common) + +# h265 decoder source +add_library(h265d_api OBJECT + h265d_api.c + h265d_spliter.c + h265d_flow.c + h265d_vps.c + h265d_sps.c + h265d_pps.c + h265d_sei.c + h265d_dpb.c + h265d_syntax.c + ) diff --git a/mpp/codec/dec/h265/h265d_api.c b/mpp/codec/dec/h265/h265d_api.c new file mode 100644 index 000000000..b82bb65d7 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_api.c @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "H265d" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_packet_impl.h" +#include "rk_hdr_meta_com.h" + +#include "mpp_parser.h" +#include "h265d_debug.h" +#include "h265d_spliter.h" +#include "h265d_dpb.h" +#include "h265d_syntax.h" + +#ifdef dump +FILE *fp = NULL; +#endif + +MPP_RET h265d_init(void *ctx, ParserCfg *parser_cfg) +{ + H265dCtx *p = (H265dCtx *)ctx; + H265dPrs *s = (H265dPrs *)p->parser; + RK_S32 ret; + + mpp_env_get_u32("h265d_debug", &h265d_debug, 0); + + p->parser_cfg = parser_cfg; + p->cfg = parser_cfg->cfg; + + if (p->cfg->base.split_parse) + h265d_spliter_init(&p->spliter); + + if (s == NULL) { + ret = h265d_parser_init(&p->parser, p); + if (ret < 0) + return ret; + + s = p->parser; + } + + if (p->extradata_size > 0 && p->extradata) { + ret = h265d_extradata(s); + if (ret < 0) + return ret; + } + + mpp_buf_slot_setup(s->slots, 25); + + s->hw_info = parser_cfg->hw_info; + + mpp_slots_set_prop(s->slots, SLOTS_WIDTH_ALIGN, mpp_align_64); + + s->cap_hw_h265_rps = s->hw_info->cap_hw_h265_rps; + +#ifdef dump + fp = fopen("/data/dump1.bin", "wb+"); +#endif + return 0; +} + +MPP_RET h265d_deinit(void *ctx) +{ + H265dCtx *p = (H265dCtx *)ctx; + + h265d_parser_deinit(p->parser); + h265d_spliter_deinit(p->spliter); + + return MPP_OK; +} + +MPP_RET h265d_prepare(void *ctx, MppPacket pkt, HalDecTask *task) +{ + H265dCtx *p = (H265dCtx *)ctx; + H265dPrs *s = (H265dPrs *)p->parser; + H265dSpliter spl = p->spliter; + RK_S64 pts = -1, dts = -1; + RK_U8 *buf = NULL; + void *pos = NULL; + RK_S32 length = 0; + RK_S32 orig_length = 0; + MPP_RET ret = MPP_OK; + + task->valid = 0; + s->eos = mpp_packet_get_eos(pkt); + + if (p->cfg->base.split_parse && NULL == spl) { + h265d_spliter_init(&p->spliter); + spl = p->spliter; + } + + h265d_spliter_set_eos(spl, s->eos); + + buf = (RK_U8 *)mpp_packet_get_pos(pkt); + pts = mpp_packet_get_pts(pkt); + dts = mpp_packet_get_dts(pkt); + h265d_dbg_pts("prepare get pts %lld", pts); + length = (RK_S32)mpp_packet_get_length(pkt); + orig_length = length; + + if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) { + p->extradata_size = length; + p->extradata = buf; + s->extra_has_frame = 0; + s->task = NULL; + h265d_extradata(s); + if (!s->extra_has_frame) { + pos = buf + length; + mpp_packet_set_pos(pkt, pos); + return MPP_OK; + } + } + + if (p->cfg->base.split_parse && !s->is_nalff) { + RK_S32 consume = 0; + RK_U8 *split_out_buf = NULL; + RK_S32 split_size = 0; + + consume = h265d_spliter_frame(spl, (const RK_U8**)&split_out_buf, &split_size, + (const RK_U8*)buf, length, pts, dts); + pos = buf + consume; + mpp_packet_set_pos(pkt, pos); + if (split_size) { + buf = split_out_buf; + length = split_size; + s->pts = h265d_spliter_get_pts(spl); + s->dts = h265d_spliter_get_dts(spl); + s->eos = (s->eos && (mpp_packet_get_length(pkt) < 4)) ? 1 : 0; + h265d_dbg_pts("split frame get pts %lld", s->pts); + } else { + return MPP_FAIL_SPLIT_FRAME; + } + } else { + pos = buf + length; + s->pts = pts; + s->dts = dts; + mpp_packet_set_pos(pkt, pos); + if (s->eos && !length) { + task->valid = 0; + task->flags.eos = 1; + h265d_flush(ctx); + return ret; + } + } +#ifdef dump + if (s->nb_frame < 10 && fp != NULL) { + fwrite(buf, 1, length, fp); + } +#endif + ret = (MPP_RET)h265d_split_nal(s, buf, length); + + if (MPP_OK == ret) { + if (s->is_nalff) { + RK_S32 consumed = s->consumed_bytes; + + if (consumed > orig_length || consumed < 0) + consumed = orig_length; + if (consumed == 0 && orig_length > 0) { + mpp_loge_f("skip %d bytes with no progress\n", orig_length); + consumed = orig_length; + } + pos = buf + consumed; + mpp_packet_set_pos(pkt, pos); + } + + if (MPP_OK == h265d_syntax_fill_slice(s->ctx, task->input)) { + task->valid = 1; + task->input_packet = s->input_packet; + } + } + return ret; + +} + +MPP_RET h265d_parse(void *ctx, HalDecTask *task) +{ + H265dCtx *p = (H265dCtx *)ctx; + H265dPrs *s = p->parser; + MPP_RET ret; + + task->valid = 0; + s->task = task; + s->ref = NULL; + ret = h265d_nal_units(s); + if (ret < 0) { + if (ret == MPP_ERR_STREAM) { + mpp_log("current stream is no right skip it %p\n", s->ref); + ret = 0; + } + task->flags.parse_err = 1; + } + if (s->ref) { + if (!task->flags.parse_err) + h265d_parser2_syntax(p); + + s->task->syntax.data = s->hal_pic_private; + s->task->syntax.number = 1; + s->task->valid = 1; + s->ps_need_upate = 0; + s->rps_need_upate = 0; + } + if (s->eos) { + h265d_flush(ctx); + s->task->flags.eos = 1; + } + s->nb_frame++; + if (s->is_decoded) { + h265d_dbg_global("frame %d decoded\n", s->poc); + s->is_decoded = 0; + } + h265d_dpb_output(ctx, 0); + return MPP_OK; +} + +MPP_RET h265d_reset(void *ctx) +{ + H265dCtx *p = (H265dCtx *)ctx; + H265dPrs *s = (H265dPrs *)p->parser; + RK_S32 ret = 0; + RK_U32 i; + + do { + ret = h265d_dpb_output(ctx, 1); + } while (ret); + + h265d_dpb_flush(s); + + h265d_spliter_reset(p->spliter); + + /* Clear RPS pointers to prevent dangling references */ + for (i = 0; i < 5; i++) { + s->rps[i].nb_refs = 0; + memset(s->rps[i].ref, 0, sizeof(s->rps[i].ref)); + memset(s->rps[i].list, 0, sizeof(s->rps[i].list)); + } + + s->max_ra = INT_MAX; + s->eos = 0; + s->first_i_fast_play = 0; + return MPP_OK; +} + +MPP_RET h265d_flush(void *ctx) +{ + RK_S32 ret = 0; + do { + ret = h265d_dpb_output(ctx, 1); + } while (ret); + return MPP_OK; +} + +MPP_RET h265d_sync(void *ctx, RK_S32 frame_id) +{ + H265dCtx *p = (H265dCtx *)ctx; + + if (p && p->spliter) + h265d_spliter_sync(p->spliter, frame_id); + + return MPP_OK; +} + +MPP_RET h265d_control(void *ctx, MpiCmd cmd, void *param) +{ + (void) ctx; + (void) cmd; + (void) param; + return MPP_OK; +} + +MPP_RET h265d_callback(void *ctx, void *err_info) +{ + H265dCtx *p = (H265dCtx *)ctx; + HalDecTask *task_dec = (HalDecTask *)err_info; + H265dPrs *s = (H265dPrs *)p->parser; + + if (!p->cfg->base.disable_error) { + MppFrame frame = NULL; + RK_U32 i = 0; + + if (s->first_nal_type >= 16 && s->first_nal_type <= 23) { + mpp_log("IS_IRAP frame found error"); + s->max_ra = INT_MAX; + } + mpp_buf_slot_get_prop(s->slots, task_dec->output, SLOT_FRAME_PTR, &frame); + mpp_frame_set_errinfo(frame, MPP_FRAME_ERR_UNKNOW); + h265d_dbg_ref("set decoded frame error, poc %d, slot %d\n", + mpp_frame_get_poc(frame), task_dec->output); + + for (i = 0; i < MPP_ARRAY_ELEMS(s->dpb); i++) { + H265dFrame *frm = &s->dpb[i]; + + if (frm->slot_index == task_dec->output) { + frm->err_status.has_err = 1; + h265d_dbg_ref("mark dpb idx %d poc %d slot_idx %d has_err %d err_info %d discard %d\n", + i, mpp_frame_get_poc(frm->frame), frm->slot_index, frm->err_status.has_err, + mpp_frame_get_errinfo(frm->frame), mpp_frame_get_discard(frm->frame)); + } + } + } + + if (!task_dec->flags.parse_err) { + s->ps_need_upate = 0; + s->rps_need_upate = 0; + } + + (void) err_info; + + return MPP_OK; +} + +const ParserApi mpp_h265d = { + .name = "h265d_parse", + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(H265dCtx), + .flag = 0, + .init = h265d_init, + .deinit = h265d_deinit, + .prepare = h265d_prepare, + .parse = h265d_parse, + .reset = h265d_reset, + .flush = h265d_flush, + .control = h265d_control, + .callback = h265d_callback, + .sync = h265d_sync, +}; + +MPP_PARSER_API_REGISTER(mpp_h265d); diff --git a/mpp/codec/dec/h265/h265d_ctx.h b/mpp/codec/dec/h265/h265d_ctx.h new file mode 100644 index 000000000..72b218819 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_ctx.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_PARSER_H +#define H265D_PARSER_H + +#include +#include + +#include "mpp_bitread.h" +#include "mpp_buf_slot.h" +#include "mpp_mem_pool.h" +#include "mpp_ref_pool.h" + +#include "parser_api.h" + +#include "hal_dec_task.h" +#include "h265d_slice.h" +#include "h2645d_sei.h" +#include "h265d_spliter.h" + +/* Frame flags - values match bit field positions in H265dFrame */ +#define H265D_FRM_FLAG_OUTPUT (1 << 0) /* ref_status->output */ +#define H265D_FRM_FLAG_SHORT_REF (1 << 1) /* ref_status->st_ref */ +#define H265D_FRM_FLAG_LONG_REF (1 << 2) /* ref_status->lt_ref */ +#define H265D_FRM_FLAG_ERROR (1 << 3) /* err_status->has_err */ + +typedef void* H265dParser; + +typedef struct H265dCtx_t { + ParserCfg *parser_cfg; + MppDecCfgSet *cfg; + + RK_S32 width; + RK_S32 height; + RK_S32 coded_width; + RK_S32 coded_height; + RK_U32 pix_fmt; + RK_U32 bit_depth; + + MppFrameColorSpace colorspace; + MppFrameColorRange color_range; + + RK_U8 *extradata; + RK_U32 extradata_size; + + H265dSpliter spliter; + H265dParser parser; +} H265dCtx; + +/* Frame reference/output status - used by h265d_frame_unref */ +typedef union { + RK_U8 flags; + struct { + RK_U8 output : 1; + RK_U8 st_ref : 1; + RK_U8 lt_ref : 1; + }; +} H265dFrmRefStatus; + +/* Frame error status - managed independently */ +typedef union { + RK_U8 flags; + struct { + RK_U8 has_err : 1; + }; +} H265dFrmErrStatus; + +typedef struct H265dFrame_t { + MppFrame frame; + + RK_S32 poc; + RK_S32 slot_index; + RK_S32 hdr_meta_index; /* HDR metadata index in pool (-1 = none) */ + + RK_U16 sequence; + H265dFrmRefStatus ref_status; /* Reference/output status */ + H265dFrmErrStatus err_status; /* Error status */ +} H265dFrame; + +typedef struct H265dRefList_t { + H265dFrame *ref[MAX_REFS]; + RK_S32 list[MAX_REFS]; + RK_S32 isLongTerm[MAX_REFS]; + RK_S32 nb_refs; +} H265dRefList; + +typedef struct H265dNal_t { + RK_S32 size; /* NAL data size (without start code) */ + RK_S32 bitstream_offset; /* offset in the prepared bitstream */ +} H265dNal; + +typedef struct HEVCSEIAlternativeTransfer { + RK_S32 present; + RK_S32 preferred_transfer_characteristics; +} HEVCSEIAlternativeTransfer; + +typedef struct H265dPrs_t { + H265dCtx *ctx; + MppBufSlots slots; + MppBufSlots packet_slots; + const MppDecHwCap *hw_info; + + HalDecTask *task; + MppPacket input_packet; + void *hal_pic_private; + + BitReadCtx_t bit; + + MppFrame frame; + + const H265dVps *vps; + const H265dSps *sps; + const H265dPps *pps; + H265dVps *vps_list[MAX_VPS_COUNT]; + H265dSps *sps_list[MAX_SPS_COUNT]; + H265dPps *pps_list[MAX_PPS_COUNT]; + + MppMemPool vps_pool; + MppMemPool sps_pool; + + H265dSlice slice; + + H265dRefList rps[5]; + + enum NALUnitType nal_unit_type; + RK_S32 temporal_id; + H265dFrame *ref; + H265dFrame dpb[MAX_DPB_SIZE]; + RK_S32 poc; + RK_S32 pocTid0; + RK_S32 slice_idx; + RK_S32 slice_cnt; + RK_S32 eos; + RK_S32 max_ra; + + RK_S32 is_decoded; + + RK_U16 seq_decode; + RK_U16 seq_output; + + H265dNal *nals; + RK_S32 nb_nals; + RK_S32 nals_allocated; + enum NALUnitType first_nal_type; + + RK_U8 *bitstream; /* prepared bitstream with start codes */ + RK_S32 bitstream_size; /* size of allocated bitstream buffer */ + RK_S32 bitstream_pos; /* current position in bitstream */ + + RK_U8 is_nalff; + RK_S32 temporal_layer_id; + + RK_S32 active_seq_parameter_set_id; + + RK_S32 nal_length_size; + RK_S32 nuh_layer_id; + + RK_U8 slice_initialized; + + RK_U32 nb_frame; + RK_U32 extra_has_frame; + + MppFrameMasteringDisplayMetadata mastering_display; + MppFrameContentLightMetadata content_light; + MppRefPool hdr_meta_pool; /* HDR dynamic metadata pool */ + RK_S32 hdr_meta_current; /* current active meta index in pool */ + HEVCSEIAlternativeTransfer alternative_transfer; + + RK_S64 pts; + RK_S64 dts; + RK_U8 miss_ref_flag; + RK_U8 pre_pps_id; + RK_U8 ps_need_upate; + RK_U8 rps_need_upate; + + /* Bitmap to track which SPS/PPS IDs have been (re)parsed since last check */ + RK_U32 sps_update_mask; /* Bit i set means SPS i was (re)parsed */ + RK_U64 pps_update_mask; /* Bit i set means PPS i was (re)parsed */ + + RK_S32 nb_refs; /* number of reference frames for current frame */ + + RK_U32 start_bit; + RK_U32 end_bit; + RK_S32 first_i_fast_play; + RK_U32 is_hdr; + RK_U32 hdr_dynamic; + + RK_U32 deny_flag; + RecoveryPoint recovery; + RK_U32 cap_hw_h265_rps; + RK_U32 consumed_bytes; +} H265dPrs; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h265d_flush(void *ctx); + +RK_S32 h265d_parser_init(H265dParser *s, H265dCtx *ctx); +RK_S32 h265d_parser_deinit(H265dParser s); + +RK_S32 h265d_extradata(H265dPrs *p); +RK_S32 H265d_nal_head(H265dPrs *p); +RK_S32 h265d_nal_units(H265dPrs *p); +RK_S32 h265d_nal_unit(H265dPrs *p, const RK_U8 *nal, RK_S32 length); + +RK_S32 h265d_split_nal(H265dPrs *p, RK_U8 *buf, RK_S32 length); + +void h265d_fill_dynamic_meta(H265dPrs *p, const RK_U8 *data, RK_U32 size, RK_U32 hdr_fmt); + +RK_S32 h265d_parser2_syntax(H265dCtx *ctx); +RK_S32 h265d_syntax_fill_slice(H265dCtx *ctx, RK_S32 input_index); + +#ifdef __cplusplus +} +#endif + +#endif /* H265D_PARSER_H */ diff --git a/mpp/codec/dec/h265/h265d_debug.h b/mpp/codec/dec/h265/h265d_debug.h new file mode 100644 index 000000000..aec2ff1c4 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_debug.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_DEBUG_H +#define H265D_DEBUG_H + +#include "mpp_debug.h" + +extern RK_U32 h265d_debug; + +#define H265D_DBG_FUNCTION (0x00000001) +#define H265D_DBG_SPLIT (0x00000002) +#define H265D_DBG_PTS (0x00000004) + +#define H265D_DBG_VPS (0x00000010) +#define H265D_DBG_SPS (0x00000020) +#define H265D_DBG_PPS (0x00000040) +#define H265D_DBG_SLICE (0x00000080) +#define H265D_DBG_SEI (0x00000100) +#define H265D_DBG_GLOBAL (0x00001000) +#define H265D_DBG_REF (0x00002000) +#define H265D_DBG_DETAIL (0x00004000) + +#define h265d_dbg(flag, fmt, ...) mpp_dbg(h265d_debug, flag, fmt, ## __VA_ARGS__) + +#define h265d_dbg_func(fmt, ...) h265d_dbg(H265D_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define h265d_dbg_split(fmt, ...) h265d_dbg(H265D_DBG_SPLIT, fmt, ## __VA_ARGS__) +#define h265d_dbg_pts(fmt, ...) h265d_dbg(H265D_DBG_PTS, fmt, ## __VA_ARGS__) +#define h265d_dbg_vps(fmt, ...) h265d_dbg(H265D_DBG_VPS, fmt, ## __VA_ARGS__) +#define h265d_dbg_sps(fmt, ...) h265d_dbg(H265D_DBG_SPS, fmt, ## __VA_ARGS__) +#define h265d_dbg_pps(fmt, ...) h265d_dbg(H265D_DBG_PPS, fmt, ## __VA_ARGS__) +#define h265d_dbg_slice(fmt, ...) h265d_dbg(H265D_DBG_SLICE, fmt, ## __VA_ARGS__) +#define h265d_dbg_sei(fmt, ...) h265d_dbg(H265D_DBG_SEI, fmt, ## __VA_ARGS__) +#define h265d_dbg_global(fmt, ...) h265d_dbg(H265D_DBG_GLOBAL, fmt, ## __VA_ARGS__) +#define h265d_dbg_ref(fmt, ...) h265d_dbg(H265D_DBG_REF, fmt, ## __VA_ARGS__) +#define h265d_dbg_detail(fmt, ...) h265d_dbg(H265D_DBG_DETAIL, fmt, ## __VA_ARGS__) + +#endif /* H265D_DEBUG_H */ diff --git a/mpp/codec/dec/h265/h265d_dpb.c b/mpp/codec/dec/h265/h265d_dpb.c new file mode 100644 index 000000000..30f256cb0 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_dpb.c @@ -0,0 +1,363 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "h265d" + +#include "mpp_log.h" +#include "mpp_bit.h" +#include "mpp_compat_impl.h" +#include "mpp_ref_pool.h" + +#include "h265d_debug.h" +#include "h265d_dpb.h" + +#define HEVC_ALIGN(value, x) ((value + (x-1)) & (~(x-1))) + +void h265d_frame_unref(H265dPrs *p, RK_U32 dpb_idx, H265dFrmRefStatus clear_mask) +{ + H265dFrame *frame = &p->dpb[dpb_idx]; + + if (!frame->frame || (frame->slot_index == 0xff)) + return; + + /* Clear reference status */ + if (clear_mask.st_ref) + frame->ref_status.st_ref = 0; + if (clear_mask.lt_ref) + frame->ref_status.lt_ref = 0; + if (clear_mask.output) + frame->ref_status.output = 0; + + /* When frame is fully unreferenced, clear error status */ + if (!frame->ref_status.flags) { + RK_S32 hdr_meta_index = frame->hdr_meta_index; + + if (frame->slot_index <= 0x7f) { + h265d_dbg_ref("poc %d clr ref index %d", frame->poc, frame->slot_index); + mpp_buf_slot_clr_flag(p->slots, frame->slot_index, SLOT_CODEC_USE); + } + + /* Release HDR metadata reference */ + if (hdr_meta_index >= 0) { + mpp_ref_pool_put(&p->hdr_meta_pool, hdr_meta_index); + frame->hdr_meta_index = -1; + } + + h265d_dbg_ref("unref_frame poc %d slot_index %d\n", frame->poc, frame->slot_index); + frame->poc = INT_MAX; + frame->slot_index = 0xff; + /* Clear error status when frame is fully unreferenced */ + frame->err_status.has_err = 0; + } +} + +void h265d_frame_unref_all(H265dPrs *p) +{ + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrmRefStatus mask = {.st_ref = 1, .lt_ref = 1}; + h265d_frame_unref(p, i, mask); + } +} + +void h265d_dpb_flush(H265dPrs *p) +{ + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrmRefStatus mask = {.flags = 0x07}; + h265d_frame_unref(p, i, mask); + } +} + +static H265dFrame *h265d_frame_create(H265dPrs *p, RK_S32 poc, RK_U32 ref_only) +{ + H265dCtx *ctx = p->ctx; + MppFrameFormat fmt = ctx->cfg->base.out_fmt & (~MPP_FRAME_FMT_MASK); + MPP_RET ret = MPP_OK; + H265dFrame *frame = NULL; + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + frame = &p->dpb[i]; + + if (frame->slot_index != 0xff) + continue; + + mpp_frame_set_width(frame->frame, ctx->width); + mpp_frame_set_height(frame->frame, ctx->height); + mpp_frame_set_hor_stride(frame->frame, + (MPP_ALIGN(ctx->coded_width, 64) * ctx->bit_depth) >> 3); + mpp_frame_set_ver_stride(frame->frame, ctx->coded_height); + ctx->pix_fmt &= MPP_FRAME_FMT_MASK; + if (p->is_hdr) { + p->ctx->pix_fmt |= MPP_FRAME_HDR; + } + ctx->pix_fmt |= fmt; + mpp_frame_set_fmt(frame->frame, ctx->pix_fmt); + + if (MPP_FRAME_FMT_IS_FBC(ctx->pix_fmt)) { + RK_U32 fbc_hdr_stride = MPP_ALIGN(ctx->width, 64); + + mpp_slots_set_prop(p->slots, SLOTS_HOR_ALIGN, mpp_align_64); + mpp_frame_set_offset_x(frame->frame, 0); + mpp_frame_set_offset_y(frame->frame, 4); + + if (*compat_ext_fbc_buf_size) + mpp_frame_set_ver_stride(frame->frame, ctx->coded_height + 16); + + if (*compat_ext_fbc_hdr_256_odd) + fbc_hdr_stride = MPP_ALIGN(ctx->width, 256) | 256; + + mpp_frame_set_fbc_hdr_stride(frame->frame, fbc_hdr_stride); + } else if (MPP_FRAME_FMT_IS_TILE(p->ctx->pix_fmt)) { + } else { + if ((ctx->cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) && + ctx->width <= 1920 && ctx->height <= 1088) + mpp_frame_set_mode(frame->frame, MPP_FRAME_FLAG_DEINTERLACED); + } + + if (ctx->cfg->base.enable_thumbnail && p->hw_info->cap_down_scale) + mpp_frame_set_thumbnail_en(frame->frame, p->ctx->cfg->base.enable_thumbnail); + else + mpp_frame_set_thumbnail_en(frame->frame, 0); + + mpp_frame_set_errinfo(frame->frame, ref_only ? 1 : 0); + mpp_frame_set_discard(frame->frame, 0); + mpp_frame_set_pts(frame->frame, p->pts); + mpp_frame_set_dts(frame->frame, p->dts); + mpp_frame_set_poc(frame->frame, poc); + mpp_frame_set_color_range(frame->frame, ctx->color_range); + mpp_frame_set_color_primaries(frame->frame, p->sps->vui.colour_primaries); + if (p->alternative_transfer.present) + mpp_frame_set_color_trc(frame->frame, + p->alternative_transfer.preferred_transfer_characteristics); + else + mpp_frame_set_color_trc(frame->frame, p->sps->vui.transfer_characteristic); + mpp_frame_set_colorspace(frame->frame, ctx->colorspace); + mpp_frame_set_mastering_display(frame->frame, p->mastering_display); + mpp_frame_set_content_light(frame->frame, p->content_light); + + h265d_dbg_global("width:height [%d:%d] [%d:%d] poc %d\n", + ctx->width, ctx->height, ctx->coded_width, ctx->coded_height, poc); + + ret = mpp_buf_slot_get_unused(p->slots, &frame->slot_index); + mpp_assert(ret == MPP_OK); + + frame->poc = poc; + frame->sequence = p->seq_decode; + + /* Initialize HDR metadata index */ + frame->hdr_meta_index = -1; + + if (ref_only) { + mpp_buf_slot_set_prop(p->slots, frame->slot_index, SLOT_FRAME, frame->frame); + mpp_buf_slot_set_flag(p->slots, frame->slot_index, SLOT_CODEC_READY); + mpp_buf_slot_set_flag(p->slots, frame->slot_index, SLOT_CODEC_USE); + h265d_dbg_ref("h265d_frame_create ref_only poc %d slot_index %d", poc, frame->slot_index); + frame->ref_status.output = 0; + frame->ref_status.st_ref = 0; + frame->ref_status.lt_ref = 0; + } else { + /* Use index-based HDR metadata reference */ + RK_S32 hdr_meta_index = p->hdr_meta_current; + MppRefPool *hdr_meta_pool = &p->hdr_meta_pool; + + if (hdr_meta_index >= 0 && p->hdr_dynamic) { + frame->hdr_meta_index = hdr_meta_index; + mpp_ref_pool_ref(hdr_meta_pool, hdr_meta_index); + mpp_frame_set_hdr_dynamic_meta(frame->frame, + (MppFrameHdrDynamicMeta*)mpp_ref_pool_ptr(hdr_meta_pool, hdr_meta_index)); + h265d_dbg_ref("h265d_frame_create poc %d slot %d hdr_meta_index %d", + poc, frame->slot_index, hdr_meta_index); + } + + h265d_dbg_ref("h265d_frame_create poc %d slot_index %d", poc, frame->slot_index); + frame->ref_status.output = 1; + frame->ref_status.st_ref = 1; + mpp_buf_slot_set_flag(p->slots, frame->slot_index, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(p->slots, frame->slot_index, SLOT_HAL_OUTPUT); + p->task->output = frame->slot_index; + p->ref = frame; + } + + return frame; + } + mpp_loge("refs: dpb full, cannot allocate frame\n"); + return NULL; +} + +RK_S32 h265d_build_refs(H265dPrs *p, MppFrame *mframe, RK_S32 poc) +{ + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *frame = &p->dpb[i]; + + if ((frame->slot_index != 0xff) && frame->sequence == p->seq_decode && + frame->poc == poc && !p->nuh_layer_id) { + mpp_loge("refs: duplicate poc %d\n", poc); + return MPP_ERR_STREAM; + } + } + + H265dFrame *ref = h265d_frame_create(p, poc, 0); + if (!ref) { + mpp_loge("refs: frame create failed\n"); + return MPP_ERR_NOMEM; + } + + *mframe = ref->frame; + return 0; +} + +static H265dFrame *h265d_frame_find_by_poc(H265dPrs *p, RK_S32 poc) +{ + RK_S32 lt_mask = (1 << p->sps->log2_max_poc_lsb) - 1; + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *ref = &p->dpb[i]; + + if ((ref->slot_index != 0xff) && (ref->sequence == p->seq_decode)) { + if ((ref->poc & lt_mask) == poc) + return ref; + } + } + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *ref = &p->dpb[i]; + + if ((ref->slot_index != 0xff) && ref->sequence == p->seq_decode) { + if (ref->poc == poc || (ref->poc & lt_mask) == poc) + return ref; + } + } + + mpp_loge("refs: cur_frm %d missing ref poc %d\n", p->poc, poc); + return NULL; +} + +static void h265d_set_frame_ref_type(H265dFrame *frame, RK_S32 ref_type) +{ + frame->ref_status.lt_ref = (ref_type == H265D_FRM_FLAG_LONG_REF) ? 1 : 0; + frame->ref_status.st_ref = (ref_type == H265D_FRM_FLAG_SHORT_REF) ? 1 : 0; +} + +static RK_S32 h265d_ref_list_add(H265dPrs *p, H265dRefList *list, + RK_S32 poc, RK_S32 ref_flag, RK_U32 cur_used) +{ + H265dFrame *ref = h265d_frame_find_by_poc(p, poc); + + if (!ref) { + ref = h265d_frame_create(p, poc, 1); + if (!ref) + return MPP_ERR_NOMEM; + + ref->err_status.has_err = 1; + } + + list->list[list->nb_refs] = ref->poc; + list->ref[list->nb_refs] = ref; + list->nb_refs++; + if (ref_flag) { + h265d_dbg_ref("set ref poc %d slot_index %d", ref->poc, ref->slot_index); + mpp_buf_slot_set_flag(p->slots, ref->slot_index, SLOT_CODEC_USE); + } + h265d_set_frame_ref_type(ref, ref_flag); + if (ref->err_status.has_err && cur_used) { + p->miss_ref_flag = 1; + } + return 0; +} + +RK_S32 h265d_build_rps(H265dPrs *p) +{ + const H265dStRps *st_rps = p->slice.st_rps_using; + const H265dLtRps *lt_prs = &p->slice.lt_rps; + H265dRefList *rps = p->rps; + RK_S32 type; + RK_S32 ret; + RK_U32 i; + + type = p->nal_unit_type; + + if (!st_rps) { + rps[0].nb_refs = rps[1].nb_refs = 0; + return 0; + } + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *frame = &p->dpb[i]; + + h265d_set_frame_ref_type(frame, 0); + } + + for (i = 0; i < NB_RPS_TYPE; i++) { + rps[i].nb_refs = 0; + memset(rps[i].ref, 0, sizeof(rps[i].ref)); + memset(rps[i].list, 0, sizeof(rps[i].list)); + } + + for (i = 0; st_rps && (RK_S32)i < st_rps->num_deltas; i++) { + RK_S32 poc = p->poc + st_rps->poc_delta[i]; + RK_S32 list; + + if (!MPP_GET_BIT(st_rps->flags, i)) + list = ST_FOLL; + else if (i < st_rps->num_neg) + list = ST_CURR_BEF; + else + list = ST_CURR_AFT; + + ret = h265d_ref_list_add(p, &rps[list], poc, H265D_FRM_FLAG_SHORT_REF, ST_FOLL != list); + if (ret < 0) + return ret; + } + + for (i = 0; lt_prs && i < lt_prs->nb_refs; i++) { + RK_S32 poc = lt_prs->poc[i]; + RK_S32 list = MPP_GET_BIT(lt_prs->used, i) ? LT_CURR : LT_FOLL; + + ret = h265d_ref_list_add(p, &rps[list], poc, H265D_FRM_FLAG_LONG_REF, LT_FOLL != list); + if (ret < 0) + return ret; + } + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrmRefStatus mask = {0}; + h265d_frame_unref(p, i, mask); + } + if (IS_CRA(type)) { + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *ref = &p->dpb[i]; + + if ((ref->slot_index != 0xff) && (ref->poc > p->poc)) { + h265d_flush(p->ctx); + break; + } + } + } + + /* Calculate and store number of reference frames */ + if (p->slice.slice_type == I_SLICE) { + p->nb_refs = 0; + } else { + RK_S32 nb_refs = 0; + if (st_rps) { + for (i = 0; i < st_rps->num_neg; i++) + nb_refs += MPP_GET_BIT(st_rps->flags, i); + for (i = st_rps->num_neg; (RK_S32)i < st_rps->num_deltas; i++) + nb_refs += MPP_GET_BIT(st_rps->flags, i); + } + if (lt_prs) { + for (i = 0; i < lt_prs->nb_refs; i++) + nb_refs += MPP_GET_BIT(lt_prs->used, i); + } + p->nb_refs = nb_refs; + } + + return 0; +} diff --git a/mpp/codec/dec/h265/h265d_dpb.h b/mpp/codec/dec/h265/h265d_dpb.h new file mode 100644 index 000000000..e0407440a --- /dev/null +++ b/mpp/codec/dec/h265/h265d_dpb.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_DPB_H +#define H265D_DPB_H + +#include "h265d_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void h265d_frame_unref(H265dPrs *p, RK_U32 dpb_idx, H265dFrmRefStatus clear_mask); +void h265d_frame_unref_all(H265dPrs *p); + +RK_S32 h265d_dpb_output(void *ctx, RK_S32 flush); +RK_S32 h265d_build_refs(H265dPrs *p, MppFrame *frame, RK_S32 poc); +void h265d_dpb_flush(H265dPrs *p); + +RK_S32 h265d_build_rps(H265dPrs *p); + +#ifdef __cplusplus +} +#endif + +#endif /* H265D_DPB_H */ diff --git a/mpp/codec/dec/h265/h265d_flow.c b/mpp/codec/dec/h265/h265d_flow.c new file mode 100644 index 000000000..6ab290474 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_flow.c @@ -0,0 +1,1702 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "h265d" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bit.h" +#include "mpp_packet_impl.h" +#include "rk_hdr_meta_com.h" +#include "mpp_ref_pool.h" + +#include "mpp_parser.h" +#include "h265d_debug.h" +#include "h265d_ctx.h" +#include "h265d_syntax.h" +#include "h2645d_sei.h" +#include "h265d_sei.h" +#include "h265d_dpb.h" + +#define START_CODE 0x000001 + +static RK_S32 pred_weight_table(BitReadCtx_t *gb, RK_S32 chroma_format_idc, + const RK_U32 nb_refs[2], SliceType slice_type) +{ + RK_U32 luma_log2_weight_denom; + RK_U8 luma_weight_l0_flag[16]; + RK_U8 chroma_weight_l0_flag[16]; + RK_U8 luma_weight_l1_flag[16]; + RK_U8 chroma_weight_l1_flag[16]; + RK_U32 i = 0; + RK_U32 j = 0; + + READ_UE(gb, &luma_log2_weight_denom); + if (chroma_format_idc != 0) { + RK_S32 delta = 0; + READ_SE(gb, &delta); + (void)delta; + + } + + for (i = 0; i < nb_refs[L0]; i++) { + READ_ONEBIT(gb, &luma_weight_l0_flag[i]); + } + + if (chroma_format_idc != 0) { + for (i = 0; i < nb_refs[L0]; i++) { + READ_ONEBIT(gb, &chroma_weight_l0_flag[i]); + } + } else { + for (i = 0; i < nb_refs[L0]; i++) + chroma_weight_l0_flag[i] = 0; + } + + for (i = 0; i < nb_refs[L0]; i++) { + if (luma_weight_l0_flag[i]) { + RK_S32 delta_luma_weight_l0 = 0; + RK_S32 luma_offset_l0 = 0; + READ_SE(gb, &delta_luma_weight_l0); + (void)delta_luma_weight_l0; + READ_SE(gb, &luma_offset_l0); + (void)luma_offset_l0; + + } + if (chroma_weight_l0_flag[i]) { + for (j = 0; j < 2; j++) { + RK_S32 delta_chroma_weight_l0 = 0; + RK_S32 delta_chroma_offset_l0 = 0; + READ_SE(gb, &delta_chroma_weight_l0); + READ_SE(gb, &delta_chroma_offset_l0); + (void)delta_chroma_weight_l0; + (void)delta_chroma_offset_l0; + } + + } + } + + if (slice_type == B_SLICE) { + for (i = 0; i < nb_refs[L1]; i++) { + READ_ONEBIT(gb, &luma_weight_l1_flag[i]); + } + if (chroma_format_idc != 0) { + for (i = 0; i < nb_refs[L1]; i++) + READ_ONEBIT(gb, &chroma_weight_l1_flag[i]); + } else { + for (i = 0; i < nb_refs[L1]; i++) + chroma_weight_l1_flag[i] = 0; + } + for (i = 0; i < nb_refs[L1]; i++) { + if (luma_weight_l1_flag[i]) { + RK_S32 delta_luma_weight_l1 = 0; + RK_S32 luma_offset_l1 = 0; + READ_UE(gb, &delta_luma_weight_l1); + (void)delta_luma_weight_l1; + READ_SE(gb, &luma_offset_l1); + (void)luma_offset_l1; + + } + if (chroma_weight_l1_flag[i]) { + for (j = 0; j < 2; j++) { + RK_S32 delta_chroma_weight_l1 = 0; + RK_S32 delta_chroma_offset_l1 = 0; + READ_SE(gb, &delta_chroma_weight_l1); + READ_SE(gb, &delta_chroma_offset_l1); + (void)delta_chroma_weight_l1; + (void)delta_chroma_offset_l1; + } + + } + } + } + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 h265d_lt_rps(H265dPrs *p, H265dLtRps *rps, BitReadCtx_t *gb) +{ + const H265dSps *sps = p->sps; + RK_S32 poc_lsb_max = 1 << sps->log2_max_poc_lsb; + RK_S32 msb_delta_prev = 0; + RK_U32 num_sps = 0, num_slc; + RK_U32 has_msb; + RK_U32 used_tmp = 0; + RK_U32 i; + + rps->nb_refs = 0; + rps->used = 0; + if (!sps->lt_rps_sps.valid) + return 0; + + if (sps->lt_rps_sps.num_refs > 0) + READ_UE(gb, &num_sps); + + READ_UE(gb, &num_slc); + + if (num_slc + num_sps > MPP_ARRAY_ELEMS(rps->poc)) + return MPP_ERR_STREAM; + + rps->nb_refs = num_slc + num_sps; + + for (i = 0; i < (RK_U32)rps->nb_refs; i++) { + if ((RK_U32)i < num_sps) { + RK_U32 sps_idx = 0; + + if (sps->lt_rps_sps.num_refs > 1) + READ_BITS(gb, mpp_ceil_log2(sps->lt_rps_sps.num_refs), &sps_idx); + + rps->poc[i] = sps->lt_rps_sps.poc_lsb[sps_idx]; + MPP_MOD_BIT(rps->used, i, MPP_GET_BIT(sps->lt_rps_sps.used_flag, sps_idx)); + } else { + READ_BITS(gb, sps->log2_max_poc_lsb, &rps->poc[i]); + READ_ONEBIT(gb, &used_tmp); + MPP_MOD_BIT(rps->used, i, used_tmp); + } + + READ_ONEBIT(gb, &has_msb); + if (has_msb) { + RK_S32 msb_delta = 0; + + READ_UE(gb, &msb_delta); + + if (i && i != num_sps) + msb_delta += msb_delta_prev; + + rps->poc[i] += p->poc - (msb_delta * poc_lsb_max) - p->slice.pic_order_cnt_lsb; + msb_delta_prev = msb_delta; + } + } + + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 set_sps(H265dPrs *p, const H265dSps *sps) +{ + MppFrameFormat fmt = p->ctx->cfg->base.out_fmt & (~MPP_FRAME_FMT_MASK); + + p->ctx->coded_width = sps->width; + p->ctx->coded_height = sps->height; + p->ctx->width = sps->output_width; + p->ctx->height = sps->output_height; + p->ctx->pix_fmt = fmt | sps->pix_fmt; + p->ctx->bit_depth = sps->bit_depth; + + if (sps->vui.video_signal_type_present_flag) + p->ctx->color_range = sps->vui.video_full_range_flag ? + MPP_FRAME_RANGE_JPEG : MPP_FRAME_RANGE_MPEG; + else + p->ctx->color_range = MPP_FRAME_RANGE_MPEG; + + if (sps->vui.colour_description_present_flag) { + p->ctx->colorspace = sps->vui.matrix_coeffs; + } else { + p->ctx->colorspace = MPP_FRAME_SPC_UNSPECIFIED; + } + + p->sps = sps; + p->vps = p->vps_list[p->sps->vps_id]; + + return 0; +} + +static RK_S32 h265d_slice_head(H265dPrs *p) +{ + BitReadCtx_t *gb = &p->bit; + H265dSlice *slice = &p->slice; + RK_S32 type = p->nal_unit_type; + RK_U32 pps_id; + RK_S32 bit_begin; + RK_U32 val_u32; + RK_S32 val_s32; + RK_S32 ret; + RK_S32 i; + + READ_ONEBIT(gb, &slice->first_slice_in_pic_flag); + if ((IS_IDR(type) || IS_BLA(type)) && slice->first_slice_in_pic_flag) { + h265d_dbg_ref("seq_decode %d -> %d (type %d IDR/BLA)\n", + p->seq_decode, (p->seq_decode + 1) & 0xff, type); + p->seq_decode = (p->seq_decode + 1) & 0xff; + p->max_ra = INT_MAX; + if (IS_IDR(type)) + h265d_frame_unref_all(p); + } + if (IS_IRAP(type)) { + /* no_output_of_prior_pics_flag */ + READ_ONEBIT(gb, &val_u32); + } + + if (IS_IRAP(type) && p->miss_ref_flag && slice->first_slice_in_pic_flag) { + p->max_ra = INT_MAX; + p->miss_ref_flag = 0; + } + READ_UE(gb, &pps_id); + + if (pps_id >= MAX_PPS_COUNT || !p->pps_list[pps_id]) { + mpp_loge("pps: invalid pps id %d\n", pps_id); + return MPP_ERR_STREAM; + } else { + slice->pps_id = pps_id; + if (pps_id != p->pre_pps_id) { + p->ps_need_upate = 1; + p->pre_pps_id = pps_id; + } + } + + if (!slice->first_slice_in_pic_flag && + p->pps != (H265dPps*)p->pps_list[slice->pps_id]) { + mpp_loge("pps: changed between slices\n"); + return MPP_ERR_STREAM; + } + p->pps = (H265dPps*)p->pps_list[slice->pps_id]; + + /* Check if SPS changed using bitmap - bit set means SPS was (re)parsed */ + RK_U32 sps_id = p->pps->sps_id; + if (MPP_GET_BIT(p->sps_update_mask, sps_id)) { + h265d_dbg_ref("seq_decode %d -> %d (SPS updated sps_id %u)\n", + p->seq_decode, (p->seq_decode + 1) & 0xff, sps_id); + p->sps = p->sps_list[sps_id]; + h265d_frame_unref_all(p); + p->ps_need_upate = 1; + ret = set_sps(p, p->sps); + if (ret < 0) + return ret; + p->seq_decode = (p->seq_decode + 1) & 0xff; + p->max_ra = INT_MAX; + MPP_CLR_BIT(p->sps_update_mask, sps_id); /* Clear bit after processing */ + } + + slice->dependent_slice_segment_flag = 0; + if (!slice->first_slice_in_pic_flag) { + RK_S32 slice_address_length; + + if (p->pps->dependent_slice_segments_enabled_flag) + READ_ONEBIT(gb, &slice->dependent_slice_segment_flag); + + slice_address_length = mpp_ceil_log2(p->sps->ctb_width * + p->sps->ctb_height); + + READ_BITS(gb, slice_address_length, &slice->slice_segment_addr); + + if (slice->slice_segment_addr >= (RK_U32)(p->sps->ctb_width * p->sps->ctb_height)) { + mpp_loge( + "slice: address over ctb count %u\n", + slice->slice_segment_addr); + return MPP_ERR_STREAM; + } + + if (!slice->dependent_slice_segment_flag) { + p->slice_idx++; + } + } else { + slice->slice_segment_addr = 0; + p->slice_idx = 0; + p->slice_initialized = 0; + } + + if (!slice->dependent_slice_segment_flag) { + RK_U32 slice_sample_adaptive_offset_flag[3] = {0}; + RK_U32 disable_deblocking_filter_flag = 0; + RK_U32 collocated_list = 0; + RK_U32 slice_temporal_mvp_enabled_flag = 0; + RK_U32 nb_refs[2] = {0}; + + p->slice_initialized = 0; + + for (i = 0; i < p->pps->num_extra_slice_header_bits; i++) + SKIP_BITS(gb, 1); + + READ_UE(gb, &slice->slice_type); + if (!(slice->slice_type == I_SLICE || + slice->slice_type == P_SLICE || + slice->slice_type == B_SLICE)) { + mpp_loge("slice: unknown type %d\n", + slice->slice_type); + return MPP_ERR_STREAM; + } + if (IS_IRAP(type) && slice->slice_type != I_SLICE) { + mpp_loge("slice: irap frame has non-i slice\n"); + return MPP_ERR_STREAM; + } + + if (p->pps->output_flag_present_flag) { + /* pic_output_flag */ + READ_ONEBIT(gb, &val_u32); + } + + if (p->sps->separate_colour_plane_flag) { + /* colour_plane_id */ + READ_BITS(gb, 2, &val_u32); + } + + if (!IS_IDR(type)) { + RK_S32 poc; + RK_S32 max_poc_lsb; + RK_S32 prev_poc_lsb; + RK_S32 prev_poc_msb; + RK_S32 poc_msb; + + /* pic_order_cnt_lsb */ + READ_BITS(gb, p->sps->log2_max_poc_lsb, &slice->pic_order_cnt_lsb); + + max_poc_lsb = 1 << p->sps->log2_max_poc_lsb; + prev_poc_lsb = p->pocTid0 % max_poc_lsb; + prev_poc_msb = p->pocTid0 - prev_poc_lsb; + + if (slice->pic_order_cnt_lsb < prev_poc_lsb && prev_poc_lsb - slice->pic_order_cnt_lsb >= max_poc_lsb / 2) + poc_msb = prev_poc_msb + max_poc_lsb; + else if (slice->pic_order_cnt_lsb > prev_poc_lsb && slice->pic_order_cnt_lsb - prev_poc_lsb > max_poc_lsb / 2) + poc_msb = prev_poc_msb - max_poc_lsb; + else + poc_msb = prev_poc_msb; + + if (IS_BLA(type)) + poc_msb = 0; + + poc = poc_msb + slice->pic_order_cnt_lsb; + + if (!slice->first_slice_in_pic_flag && poc != p->poc) { + mpp_log("Ignoring POC change between slices: %d -> %d\n", p->poc, poc); + poc = p->poc; + } + p->poc = poc; + + /* short_term_ref_pic_set_sps_flag */ + READ_ONEBIT(gb, &slice->short_term_ref_pic_set_sps_flag); + + bit_begin = gb->used_bits; + + if (!slice->short_term_ref_pic_set_sps_flag) { + ret = h265d_st_rps(gb, &slice->st_rps_slice, p->sps, 1, &p->rps_need_upate); + if (ret < 0) + return ret; + + slice->st_rps_using = &slice->st_rps_slice; + } else { + RK_S32 numbits, rps_idx; + + if (!p->sps->nb_st_rps) { + mpp_loge("sps: missing reference lists\n"); + return MPP_ERR_STREAM; + } + + numbits = mpp_ceil_log2(p->sps->nb_st_rps); + rps_idx = 0; + if (numbits > 0) + /* short_term_ref_pic_set_idx */ + READ_BITS(gb, numbits, &rps_idx); + + if (slice->st_rps_using != &p->sps->st_rps_sps[rps_idx]) + p->rps_need_upate = 1; + slice->st_rps_using = &p->sps->st_rps_sps[rps_idx]; + } + + slice->short_term_ref_pic_set_size = gb->used_bits - bit_begin; + + ret = h265d_lt_rps(p, &slice->lt_rps, gb); + if (ret < 0) { + mpp_log("Invalid long term RPS.\n"); + } + + if (p->sps->sps_temporal_mvp_enabled_flag) + /* slice_temporal_mvp_enabled_flag */ + READ_ONEBIT(gb, &slice_temporal_mvp_enabled_flag); + else + slice_temporal_mvp_enabled_flag = 0; + } else { + slice->st_rps_using = NULL; + p->poc = 0; + } + + /* Calculate number of reference frames */ + if (slice->slice_type == I_SLICE) { + p->nb_refs = 0; + } else { + RK_S32 nb_refs = 0; + const H265dStRps *st_rps = slice->st_rps_using; + const H265dLtRps *lt_rps = &slice->lt_rps; + RK_U32 i; + + if (st_rps) { + for (i = 0; i < (RK_U32)st_rps->num_neg; i++) + nb_refs += MPP_GET_BIT(st_rps->flags, i); + for (i = (RK_U32)st_rps->num_neg; i < (RK_U32)st_rps->num_deltas; i++) + nb_refs += MPP_GET_BIT(st_rps->flags, i); + } + if (lt_rps) { + for (i = 0; i < (RK_U32)lt_rps->nb_refs; i++) + nb_refs += MPP_GET_BIT(lt_rps->used, i); + } + p->nb_refs = nb_refs; + } + + if (p->temporal_id == 0 && + type != NAL_TRAIL_N && type != NAL_TSA_N && + type != NAL_STSA_N && type != NAL_RADL_N && + type != NAL_RADL_R && type != NAL_RASL_N && + type != NAL_RASL_R) + p->pocTid0 = p->poc; + + if (p->sps->sao_enabled) { + /* slice_sao_luma_flag */ + READ_ONEBIT(gb, &slice_sample_adaptive_offset_flag[0]); + if (p->sps->chroma_format_idc) { + /* slice_sao_chroma_flag */ + READ_ONEBIT(gb, &slice_sample_adaptive_offset_flag[1]); + slice_sample_adaptive_offset_flag[2] = + slice_sample_adaptive_offset_flag[1]; + } else { + slice_sample_adaptive_offset_flag[1] = 0; + slice_sample_adaptive_offset_flag[2] = 0; + } + } else { + slice_sample_adaptive_offset_flag[0] = 0; + slice_sample_adaptive_offset_flag[1] = 0; + slice_sample_adaptive_offset_flag[2] = 0; + } + + nb_refs[L0] = nb_refs[L1] = 0; + if (slice->slice_type == P_SLICE || slice->slice_type == B_SLICE) { + RK_S32 total_nb_refs; + + nb_refs[L0] = p->pps->num_ref_idx_l0_default_active; + if (slice->slice_type == B_SLICE) + nb_refs[L1] = p->pps->num_ref_idx_l1_default_active; + + /* num_ref_idx_active_override_flag */ + READ_ONEBIT(gb, &val_u32); + + if (val_u32) { + /* num_ref_idx_l0_active_minus1 */ + READ_UE(gb, &val_u32); + nb_refs[L0] = val_u32 + 1; + if (slice->slice_type == B_SLICE) { + /* num_ref_idx_l1_active_minus1 */ + READ_UE(gb, &val_u32); + nb_refs[L1] = val_u32 + 1; + } + } + if (nb_refs[L0] > MAX_REFS || nb_refs[L1] > MAX_REFS) { + mpp_loge("slice: reference count over limit %d %d\n", + nb_refs[L0], nb_refs[L1]); + return MPP_ERR_STREAM; + } + + total_nb_refs = p->nb_refs; + if (!total_nb_refs) { + mpp_loge("slice: p/b slice has no references\n"); + return MPP_ERR_STREAM; + } + + if (p->pps->lists_modification_present_flag && total_nb_refs > 1) { + RK_U32 rpl_modification_flag; + /* ref_pic_list_modification_flag_l0 */ + READ_ONEBIT(gb, &rpl_modification_flag); + if (rpl_modification_flag) { + for (i = 0; (RK_U32)i < nb_refs[L0]; i++) { + /* list_entry_l0 */ + READ_BITS(gb, mpp_ceil_log2(total_nb_refs), &val_u32); + } + } + + if (slice->slice_type == B_SLICE) { + /* ref_pic_list_modification_flag_l1 */ + READ_ONEBIT(gb, &rpl_modification_flag); + if (rpl_modification_flag) + for (i = 0; (RK_U32)i < nb_refs[L1]; i++) { + /* list_entry_l1 */ + READ_BITS(gb, mpp_ceil_log2(total_nb_refs), &val_u32); + } + } + } + + if (slice->slice_type == B_SLICE) { + /* mvd_l1_zero_flag */ + READ_ONEBIT(gb, &val_u32); + } + + if (p->pps->cabac_init_present_flag) { + /* cabac_init_flag */ + READ_ONEBIT(gb, &val_u32); + } + + if (slice_temporal_mvp_enabled_flag) { + RK_U32 collocated_ref_idx = 0; + collocated_list = L0; + if (slice->slice_type == B_SLICE) { + /* collocated_from_l0_flag */ + READ_ONEBIT(gb, &val_u32); + collocated_list = !val_u32; + } + + if (nb_refs[collocated_list] > 1) { + /* collocated_ref_idx */ + READ_UE(gb, &collocated_ref_idx); + if (collocated_ref_idx >= nb_refs[collocated_list]) { + mpp_loge("slice: collocated_ref_idx %d invalid\n", + collocated_ref_idx); + return MPP_ERR_STREAM; + } + } + } + + if ((p->pps->weighted_pred_flag && slice->slice_type == P_SLICE) || + (p->pps->weighted_bipred_flag && slice->slice_type == B_SLICE)) { + pred_weight_table(gb, p->sps->chroma_format_idc, nb_refs, slice->slice_type); + } + + /* five_minus_max_num_merge_cand */ + READ_UE(gb, &val_u32); + if (val_u32 > 4) { + mpp_loge("slice: five_minus_max_num_merge_cand %u invalid\n", val_u32); + return MPP_ERR_STREAM; + } + } + /* slice_qp_delta */ + READ_SE(gb, &val_s32); + + slice->slice_qp = 26U + p->pps->pic_init_qp_minus26 + val_s32; + if (slice->slice_qp > 51 || + slice->slice_qp < -p->sps->qp_bd_offset) { + mpp_loge("The slice_qp %d is outside the valid range [%d, 51].\n", + slice->slice_qp, -p->sps->qp_bd_offset); + return MPP_ERR_STREAM; + } + + if (p->pps->pic_slice_level_chroma_qp_offsets_present_flag) { + /* slice_cb_qp_offset */ + READ_SE(gb, &val_s32); + /* slice_cr_qp_offset */ + READ_SE(gb, &val_s32); + } + + if (p->pps->deblocking_filter_control_present_flag) { + RK_S32 deblocking_filter_override_flag = 0; + + if (p->pps->deblocking_filter_override_enabled_flag) + /* deblocking_filter_override_flag */ + READ_ONEBIT(gb, &deblocking_filter_override_flag); + + if (deblocking_filter_override_flag) { + /* slice_deblocking_filter_disabled_flag */ + READ_ONEBIT(gb, &disable_deblocking_filter_flag); + if (!disable_deblocking_filter_flag) { + /* slice_beta_offset_div2 */ + READ_SE(gb, &val_s32); + /* slice_tc_offset_div2 */ + READ_SE(gb, &val_s32); + } + } else { + disable_deblocking_filter_flag = p->pps->disable_dbf; + } + } else { + disable_deblocking_filter_flag = 0; + } + + if (p->pps->seq_loop_filter_across_slices_enabled_flag && + (slice_sample_adaptive_offset_flag[0] || + slice_sample_adaptive_offset_flag[1] || + !disable_deblocking_filter_flag)) { + /* slice_loop_filter_across_slices_enabled_flag */ + READ_ONEBIT(gb, &val_u32); + } + } else if (!p->slice_initialized) { + mpp_loge("slice: dependent slice without independent\n"); + return MPP_ERR_STREAM; + } + + if (p->pps->tiles_enabled_flag || p->pps->entropy_coding_sync_enabled_flag) { + RK_S32 num_entry_point_offsets = 0; + /* num_entry_point_offsets */ + READ_UE(gb, &num_entry_point_offsets); + + if (p->pps->entropy_coding_sync_enabled_flag) { + if (num_entry_point_offsets > p->sps->ctb_height || num_entry_point_offsets < 0) { + mpp_loge("slice: entry count %d over ctb rows %d\n", + num_entry_point_offsets, + p->sps->ctb_height); + return MPP_ERR_STREAM; + } + } else { + if (num_entry_point_offsets > p->sps->ctb_height * p->sps->ctb_width || num_entry_point_offsets < 0) { + mpp_loge("slice: entry count %d over ctb count %d\n", + num_entry_point_offsets, + p->sps->ctb_height * p->sps->ctb_width); + return MPP_ERR_STREAM; + } + } + if (num_entry_point_offsets) { + RK_U32 offset_len_minus1 = 0; + + /* offset_len_minus1 */ + READ_UE(gb, &offset_len_minus1); + for (i = 0; i < num_entry_point_offsets; i++) + SKIP_BITS(gb, offset_len_minus1 + 1); + } + } + if (p->pps->slice_header_extension_present_flag) { + RK_U32 length = 0; + + p->start_bit = gb->used_bits; + /* slice_header_extension_length */ + READ_UE(gb, &length); + for (i = 0; (RK_U32)i < length; i++) { + SKIP_BITS(gb, 8); + } + p->end_bit = gb->used_bits; + } + + if (!slice->slice_segment_addr && slice->dependent_slice_segment_flag) { + mpp_loge("slice: invalid segment\n"); + return MPP_ERR_STREAM; + } + + p->slice_initialized = 1; + + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +RK_S32 H265d_nal_head(H265dPrs *p) +{ + BitReadCtx_t *gb = &p->bit; + RK_S32 value = 0; + + READ_ONEBIT(gb, &value); + + READ_BITS(gb, 6, &p->nal_unit_type); + READ_BITS(gb, 6, &p->nuh_layer_id); + READ_BITS(gb, 3, &p->temporal_id); + + p->temporal_id = p->temporal_id - 1; + + h265d_dbg_global("nal_unit_type: %d, nuh_layer_id: %d temporal_id: %d\n", + p->nal_unit_type, p->nuh_layer_id, p->temporal_id); + + if (p->temporal_id < 0) + return MPP_ERR_STREAM; + + return (p->nuh_layer_id); +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 h265d_out_dec_order(void *ctx) +{ + H265dCtx *h265dctx = (H265dCtx *)ctx; + H265dPrs *p = (H265dPrs *)h265dctx->parser; + + if (p->ref && p->ref->ref_status.output) { + p->ref->ref_status.output = 0; + mpp_buf_slot_set_flag(p->slots, p->ref->slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->slots, p->ref->slot_index, QUEUE_DISPLAY); + } + + return 0; +} + +RK_S32 h265d_dpb_output(void *ctx, RK_S32 flush) +{ + H265dCtx *h265dctx = (H265dCtx *)ctx; + H265dPrs *p = (H265dPrs *)h265dctx->parser; + MppDecCfgSet *cfg = h265dctx->cfg; + RK_S32 type = p->nal_unit_type; + RK_U32 find_next_ready = 0; + + if (cfg->base.fast_out) + return h265d_out_dec_order(ctx); + + do { + RK_S32 nb_output = 0; + RK_S32 min_poc = INT_MAX; + RK_S32 min_idx = 0; + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *frame = &p->dpb[i]; + + if (frame->ref_status.output && + frame->sequence == p->seq_output) { + nb_output++; + if (frame->poc < min_poc) { + min_poc = frame->poc; + min_idx = i; + } + } + } + + if (!flush && p->seq_output == p->seq_decode && p->sps && + nb_output <= (RK_S32)p->sps->layers[p->sps->max_sub_layers - 1].num_reorder_pics) { + if (cfg->base.enable_fast_play && (IS_IDR(type) || + (IS_BLA(type) && !p->first_i_fast_play))) { + p->first_i_fast_play = 1; + } else { + return 0; + } + } + + if (nb_output) { + H265dFrame *frame = &p->dpb[min_idx]; + + frame->ref_status.output = 0; + + mpp_buf_slot_set_flag(p->slots, frame->slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->slots, frame->slot_index, QUEUE_DISPLAY); + + h265d_dbg_ref("output frame poc %d slot_index %d\n", frame->poc, frame->slot_index); + + do { + find_next_ready = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *next = &p->dpb[i]; + + if (next->ref_status.output && + next->sequence == p->seq_output) { + if (next->poc == frame->poc + 1) { + find_next_ready = 1; + next->ref_status.output = 0; + frame = next; + mpp_buf_slot_set_flag(p->slots, frame->slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->slots, frame->slot_index, QUEUE_DISPLAY); + h265d_dbg_ref("output frame poc %d slot_index %d\n", + next->poc, next->slot_index); + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrmRefStatus mask = {0}; + h265d_frame_unref(p, i, mask); + } + } + } + } + } while (find_next_ready); + + return 1; + } + + if (p->seq_output != p->seq_decode) + p->seq_output = (p->seq_output + 1) & 0xff; + else + break; + } while (1); + + return 0; +} + +static RK_S32 h265d_frame_new(H265dPrs *p) +{ + RK_S32 type = p->nal_unit_type; + RK_S32 ret; + + if (p->ref) { + mpp_log_f("found two frame in one packet do nothing!\n"); + return 0; + } + + p->is_decoded = 0; + p->first_nal_type = type; + p->miss_ref_flag = 0; + + ret = h265d_build_rps(p); + if (ret < 0) { + mpp_loge("rps: failed to build\n"); + goto fail; + } + + ret = h265d_build_refs(p, &p->frame, p->poc); + if (ret < 0) + goto fail; + + if (!p->ctx->cfg->base.disable_error && p->recovery.valid_flag && + p->recovery.first_frm_valid && p->recovery.first_frm_ref_missing && + p->poc < p->recovery.recovery_pic_id && p->poc >= p->recovery.first_frm_id) { + mpp_frame_set_discard(p->frame, 1); + h265d_dbg_ref("mark recovery frame discard poc %d\n", mpp_frame_get_poc(p->frame)); + } + + if (!p->ctx->cfg->base.disable_error && p->miss_ref_flag) { + if (!IS_IRAP(type)) { + if (p->recovery.valid_flag && p->recovery.first_frm_valid && p->recovery.first_frm_id == p->poc) { + p->recovery.first_frm_ref_missing = 1; + mpp_frame_set_discard(p->frame, 1); + h265d_dbg_ref("recovery frame missing ref mark discard poc %d\n", + mpp_frame_get_poc(p->frame)); + } else { + mpp_frame_set_errinfo(p->frame, MPP_FRAME_ERR_UNKNOW); + p->ref->err_status.has_err = 1; + h265d_dbg_ref("missing ref mark error poc %d\n", mpp_frame_get_poc(p->frame)); + } + } else { + H265dFrame *frame = NULL; + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + frame = &p->dpb[i]; + if (frame->poc == p->poc ) { + frame->ref_status.output = 0; + break; + } else { + frame = NULL; + } + } + do { + ret = h265d_dpb_output(p->ctx, 1); + } while (ret); + if (frame) { + frame->ref_status.output = 1; + } + } + } + + mpp_buf_slot_set_prop(p->slots, p->ref->slot_index, SLOT_FRAME, p->ref->frame); + + return 0; + +fail: + p->ref = NULL; + return ret; +} + +RK_S32 h265d_nal_unit(H265dPrs *p, const RK_U8 *nal, RK_S32 length) +{ + BitReadCtx_t *gb = &p->bit; + RK_S32 type; + RK_S32 ret; + + mpp_set_bitread_ctx(gb, (RK_U8*)nal, length); + mpp_set_bitread_pseudo_code_type(gb, PSEUDO_CODE_H264_H265); + + ret = H265d_nal_head(p); + type = p->nal_unit_type; + if (ret < 0) { + mpp_loge("nal: unit type %d invalid skip\n", type); + goto fail; + } else if (ret && type != NAL_VPS) + return 0; + + if (p->temporal_id > p->temporal_layer_id) + return 0; + + p->nuh_layer_id = ret; + + h265d_dbg_global("nal_unit_type %d len %d\n", type, length); + + if (p->deny_flag && (type != NAL_VPS && type != NAL_SPS)) { + ret = MPP_ERR_STREAM; + goto fail; + } + + switch (type) { + case NAL_VPS: { + MppMemPool *pool = p->vps_pool; + H265dVps *vps = (H265dVps *)mpp_mem_pool_get_f(pool); + + if (!vps) { + ret = MPP_ERR_NOMEM; + goto fail; + } + ret = h265d_nal_vps(&p->bit, vps); + if (ret < 0) { + mpp_mem_pool_put_f(pool, vps); + if (!p->is_decoded) { + mpp_loge("h265d_nal_vps ret %d", ret); + goto fail; + } + } else { + RK_U32 vps_id = vps->vps_id; + H265dVps *vps_old = p->vps_list[vps_id]; + + if (vps_old && !memcmp(vps_old, vps, sizeof(H265dVps))) { + mpp_mem_pool_put_f(pool, vps); + } else { + if (vps_old != NULL) { + mpp_mem_pool_put_f(pool, vps_old); + } + p->vps_list[vps_id] = vps; + p->ps_need_upate = 1; + } + } + } break; + case NAL_SPS: { + H265dSps *sps = (H265dSps *)mpp_mem_pool_get_f(p->sps_pool); + H265dSps *old_sps; + RK_S32 i; + RK_S32 sps_changed = 0; + + if (!sps) { + ret = MPP_ERR_NOMEM; + goto fail; + } + + ret = h265d_nal_sps(&p->bit, sps, (const H265dVps **)p->vps_list); + if (ret < 0) { + mpp_mem_pool_put_f(p->sps_pool, sps); + if (!p->is_decoded) { + mpp_loge("h265d_nal_sps ret %d", ret); + goto fail; + } + } else { + RK_U32 sps_id = sps->sps_id; + + h265d_dbg_split("h265d_nal_unit: SPS %u parsed successfully, size %dx%d\n", + sps_id, sps->output_width, sps->output_height); + + old_sps = p->sps_list[sps_id]; + + /* Compare SPS content to detect actual changes */ + if (old_sps) { + sps_changed = (memcmp(old_sps, sps, sizeof(H265dSps)) != 0); + } else { + sps_changed = 1; /* New SPS */ + } + + for (i = 0; i < MAX_PPS_COUNT; i++) { + if (p->pps_list[i] && p->pps_list[i]->sps_id == sps_id) { + MPP_FREE(p->pps_list[i]); + p->pps_list[i] = NULL; + } + } + + if (old_sps) + mpp_mem_pool_put_f(p->sps_pool, old_sps); + + p->sps_list[sps_id] = sps; + + /* Only set update bit if SPS actually changed */ + if (sps_changed) + MPP_SET_BIT(p->sps_update_mask, sps_id); + + p->ctx->width = sps->output_width; + p->ctx->height = sps->output_height; + + if (sps->vui.transfer_characteristic == MPP_FRAME_TRC_SMPTEST2084 || + sps->vui.transfer_characteristic == MPP_FRAME_TRC_ARIB_STD_B67) + p->is_hdr = 1; + + switch (sps->chroma_format_idc) { + case H265_CHROMA_422 : { + mpp_slots_set_prop(p->slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } break; + case H265_CHROMA_444 : { + mpp_slots_set_prop(p->slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv444); + } break; + default : { + } break; + } + } + + p->deny_flag = 0; + } break; + case NAL_PPS : { + H265dPps *pps = h265d_nal_pps(&p->bit, (const H265dSps **)p->sps_list); + + if (!pps) { + if (!p->is_decoded) { + mpp_loge("h265d_nal_pps failed\n"); + goto fail; + } + } else { + RK_U32 pps_id = pps->pps_id; + H265dPps *old_pps = p->pps_list[pps_id]; + H265dSps *sps = (H265dSps *)p->sps_list[pps->sps_id]; + RK_S32 pps_changed = 0; + + ret = h265d_pps_check(pps, sps, p->hw_info); + if (ret < 0) { + MPP_FREE(pps); + if (!p->is_decoded) { + mpp_loge("h265d_pps_check ret %d", ret); + goto fail; + } + } else { + /* Compare PPS content to detect actual changes */ + if (old_pps) { + /* Use total_size for direct memcmp comparison */ + if (old_pps->total_size == pps->total_size) { + pps_changed = (memcmp(old_pps, pps, pps->total_size) != 0); + } else { + pps_changed = 1; /* Size changed */ + } + } else { + pps_changed = 1; /* New PPS */ + } + + MPP_FREE(old_pps); + p->pps_list[pps_id] = pps; + + /* Only set update bit if PPS actually changed */ + if (pps_changed) + MPP_SET_BIT64(p->pps_update_mask, pps_id); + } + } + } break; + case NAL_SEI_PREFIX : + case NAL_SEI_SUFFIX : { + ret = h265d_nal_sei(p); + if (ret < 0) { + mpp_loge("h265d_decode_nal_sei ret %d", ret); + } + } break; + case NAL_TRAIL_R : + case NAL_TRAIL_N : + case NAL_TSA_N : + case NAL_TSA_R : + case NAL_STSA_N : + case NAL_STSA_R : + case NAL_BLA_W_LP : + case NAL_BLA_W_RADL : + case NAL_BLA_N_LP : + case NAL_IDR_W_RADL : + case NAL_IDR_N_LP : + case NAL_CRA_NUT : + case NAL_RADL_N : + case NAL_RADL_R : + case NAL_RASL_N : + case NAL_RASL_R : { + if (p->task == NULL) { + p->extra_has_frame = 1; + break; + } + + ret = h265d_slice_head(p); + if (ret < 0) { + h265d_dbg_slice("h265d_slice_head ret %d", ret); + if ((p->first_nal_type != type) && (p->first_nal_type != NAL_INIT_VALUE)) + return 0; + + return ret; + } + + if (p->recovery.valid_flag) { + if (!p->recovery.first_frm_valid) { + p->recovery.first_frm_id = p->poc; + p->recovery.first_frm_valid = 1; + p->recovery.recovery_pic_id = p->recovery.first_frm_id + p->recovery.recovery_frame_cnt; + h265d_dbg_sei( "First recovery frame found, poc %d", p->recovery.first_frm_id); + } else { + if (p->recovery.recovery_pic_id < p->poc) + memset(&p->recovery, 0, sizeof(RecoveryPoint)); + } + } + + if (p->max_ra == INT_MAX) { + if (type == NAL_CRA_NUT || IS_BLA(type) || + (p->recovery.valid_flag && p->recovery.first_frm_valid && + p->recovery.first_frm_id == p->poc)) { + p->max_ra = p->poc; + } else { + if (IS_IDR(type)) + p->max_ra = INT_MIN; + } + } + + if ((type == NAL_RASL_R || type == NAL_RASL_N) && + p->poc <= p->max_ra) { + p->is_decoded = 0; + break; + } else if (!p->ctx->cfg->base.disable_error && + (p->poc < p->max_ra) && !IS_IRAP(type)) { + p->is_decoded = 0; + break; + } else { + if (type == NAL_RASL_R && p->poc > p->max_ra) + p->max_ra = INT_MIN; + } + + if (p->slice.first_slice_in_pic_flag) { + ret = h265d_frame_new(p); + if (ret < 0) { + mpp_loge("h265d_frame_new %d", ret); + return ret; + } + } else if (!p->ref) { + mpp_loge("slice: missing first slice\n"); + goto fail; + } + + if (type != p->first_nal_type) { + mpp_loge("nal: type mismatch %d %d\n", + p->first_nal_type, type); + goto fail; + } + + if (!p->slice.dependent_slice_segment_flag && + p->slice.slice_type != I_SLICE) { + if (ret < 0) { + mpp_loge("ref lists: failed to build\n"); + goto fail; + } + } + + p->is_decoded = 1; + + if (p->pps && p->pps->slice_header_extension_present_flag) { + h265d_dxva2_picture_context_t *syn = (h265d_dxva2_picture_context_t *)p->hal_pic_private; + DXVA_Slice_HEVC_Cut_Param *param = &syn->slice_cut_param[p->slice_cnt]; + + param->start_bit = p->start_bit; + param->end_bit = p->end_bit; + param->is_enable = 1; + } + p->slice_cnt++; + } break; + case NAL_EOS_NUT : + case NAL_EOB_NUT : { + h265d_dbg_ref("seq_decode %d -> %d (EOS/EOB type %d)\n", + p->seq_decode, (p->seq_decode + 1) & 0xff, type); + p->seq_decode = (p->seq_decode + 1) & 0xff; + p->max_ra = INT_MAX; + } break; + case NAL_AUD : + case NAL_FD_NUT : { + } break; + case NAL_UNSPEC62: { + if (length > 2) { + h265d_fill_dynamic_meta(p, nal + 2, length - 2, DLBY); + } + } break; + default : { + mpp_log("Skipping NAL unit %d\n", type); + } break; + } + + return 0; +fail: + + return ret; +} + + +typedef union { + RK_U32 u32; + RK_U16 u16[2]; + RK_U8 u8 [4]; + float f32; +} mpp_alias32; + +#define MPP_FAST_UNALIGNED 1 + + +#ifndef MPP_RN32A +#define MPP_RN32A(p) (((const mpp_alias32*)(p))->u32) +#endif + +void h265d_fill_dynamic_meta(H265dPrs *p, const RK_U8 *data, RK_U32 size, RK_U32 hdr_fmt) +{ + MppRefPool *pool = &p->hdr_meta_pool; + RK_S32 idx; + MppFrameHdrDynamicMeta *meta; + + /* Cleanup unused slots in pool */ + mpp_ref_pool_cleanup(pool); + + /* Allocate a new slot from pool (include struct header size) */ + idx = mpp_ref_pool_get(pool, sizeof(MppFrameHdrDynamicMeta) + size); + if (idx < 0) { + mpp_loge_f("failed to allocate hdr meta slot\n"); + return; + } + + meta = (MppFrameHdrDynamicMeta *)mpp_ref_pool_ptr(pool, idx); + if (size && data) { + switch (hdr_fmt) { + case DLBY: { + RK_U8 start_code[4] = {0, 0, 0, 1}; + + memcpy((RK_U8*)meta->data, start_code, 4); + memcpy((RK_U8*)meta->data + 4, (RK_U8*)data, size - 4); + } break; + case HDRVIVID: + case HDR10PLUS: { + memcpy((RK_U8*)meta->data, (RK_U8*)data, size); + } break; + default: + break; + } + meta->size = size; + meta->hdr_fmt = hdr_fmt; + } + /* Update current active meta index */ + p->hdr_meta_current = idx; + p->hdr_dynamic = 1; + p->is_hdr = 1; + +} + +RK_S32 h265d_nal_units(H265dPrs *p) +{ + RK_S32 ret = 0; + RK_S32 i; + + p->slice_cnt = 0; + + for (i = 0; i < p->nb_nals; i++) { + const RK_U8 *nal_data = p->bitstream + p->nals[i].bitstream_offset + 3; + RK_S32 nal_size = p->nals[i].size; + + ret = h265d_nal_unit(p, nal_data, nal_size); + if (ret < 0) { + mpp_loge("nal: parse unit #%d failed ret %d\n", i, ret); + break; + } + } + + return ret; +} + +static RK_S32 find_embedded_start_code(const RK_U8 *buf, RK_S32 length) +{ + RK_S32 i; + RK_S32 actual_length = length; + +#define STARTCODE_TEST \ + if (i + 2 < actual_length && buf[i + 1] == 0 && buf[i + 2] == 1) { \ + actual_length = i; \ + break; \ + } + +#if MPP_FAST_UNALIGNED +#define FIND_FIRST_ZERO \ + if (i > 0 && !buf[i]) \ + i--; \ + while (buf[i]) \ + i++ + + for (i = 0; i + 1 < (RK_S32)actual_length; i += 5) { + if (!((~MPP_RN32A(buf + i) & + (MPP_RN32A(buf + i) - 0x01000101U)) & + 0x80008080U)) + continue; + + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 3; + } +#else + for (i = 0; i + 1 < (RK_S32)actual_length; i += 2) { + if (buf[i]) + continue; + if (i > 0 && buf[i - 1] == 0) + i--; + STARTCODE_TEST; + } +#endif + + return actual_length; +} + +static RK_S32 h265d_locate_start_code(const RK_U8 *buf, RK_U32 length) +{ + RK_U32 i; + RK_U32 state = (RK_U32) - 1; + + for (i = 0; i < length; i++) { + state = (state << 8) | buf[i]; + if (((state >> 8) & 0xFFFFFF) == START_CODE) { + return (i >= 3) ? (i - 3) : 0; + } + } + + return -1; +} + +static RK_S32 process_one_nal(H265dPrs *p, const RK_U8 *nal_data, RK_S32 nal_size) +{ + H265dNal *nal = &p->nals[p->nb_nals]; + static const RK_U8 start_code[] = { 0, 0, 1 }; + RK_S32 actual_size; + + actual_size = find_embedded_start_code(nal_data, nal_size); + nal->size = actual_size; + + if (p->bitstream_pos + 3 > p->bitstream_size) { + mpp_loge("bitstream overflow\n"); + return -1; + } + memcpy(p->bitstream + p->bitstream_pos, start_code, 3); + nal->bitstream_offset = p->bitstream_pos; + p->bitstream_pos += 3; + + if (p->bitstream_pos + actual_size > p->bitstream_size) { + mpp_loge("bitstream overflow\n"); + return -1; + } + memcpy(p->bitstream + p->bitstream_pos, nal_data, actual_size); + p->bitstream_pos += actual_size; + + return actual_size; +} + +RK_S32 h265d_split_nal(H265dPrs *p, RK_U8 *buf, RK_S32 length) +{ + RK_S32 max_bitstream_size = length + (length / 100) * 3 + 1024; + RK_U32 total_consumed = 0; + RK_S32 consumed; + MPP_RET ret = MPP_OK; + RK_S32 i; + + if (p->bitstream_size < max_bitstream_size) { + mpp_free(p->bitstream); + p->bitstream = mpp_malloc(RK_U8, max_bitstream_size); + if (!p->bitstream) { + ret = MPP_ERR_NOMEM; + goto fail; + } + p->bitstream_size = max_bitstream_size; + } + p->bitstream_pos = 0; + p->nb_nals = 0; + + while (length >= 4) { + H265dNal *nal; + RK_S32 extract_length = 0; + const RK_U8 *nal_data; + + if (p->is_nalff) { + for (i = 0; i < p->nal_length_size; i++) + extract_length = (extract_length << 8) | buf[i]; + + buf += p->nal_length_size; + length -= p->nal_length_size; + total_consumed += p->nal_length_size; + + nal_data = buf; + + /* + * Use unsigned comparison to correctly handle corrupted data. + * When stream data is corrupted (e.g., during seeking), extract_length + * may become a large negative value like -1347309641 (0xAFAFFB11). + * Signed comparison would incorrectly treat this as less than length, + * bypassing the check and causing memcpy to crash. + */ + if ((RK_U32)extract_length > (RK_U32)length) { + mpp_loge("nal: unit size invalid extract_length %d length %d\n", + extract_length, length); + ret = MPP_ERR_STREAM; + goto fail; + } + } else { + if (buf[2] == 0) { + length--; + buf++; + continue; + } + if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { + h265d_dbg_split("buf[0-2] not start code, searching... buf[0-7] %02x %02x %02x %02x %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); + RK_S32 offset = h265d_locate_start_code(buf, length); + h265d_dbg_split("h265d_locate_start_code returned %d\n", offset); + if (offset >= 0) { + length -= offset; + buf += offset; + h265d_dbg_split("Found start code at offset %d, buf[0-2] %02x %02x %02x\n", + offset, buf[0], buf[1], buf[2]); + continue; + } + + if (p->nb_nals) { + h265d_dbg_split("No more start code found, returning OK with %d NALs\n", p->nb_nals); + return MPP_OK; + } else { + ret = MPP_ERR_STREAM; + goto fail; + } + } + + buf += 3; + length -= 3; + extract_length = length; + nal_data = buf; + h265d_dbg_split("Found start code, extract_length %d\n", extract_length); + } + + if (!extract_length) { + return MPP_OK; + } + if (p->nals_allocated < p->nb_nals + 1) { + RK_S32 old_size = p->nals_allocated; + RK_S32 new_size = old_size + 10; + + if (new_size < 10) + new_size = 10; + + p->nals = mpp_realloc(p->nals, H265dNal, new_size); + if (!p->nals) { + mpp_loge("realloc nals failed new_size %d", new_size); + ret = MPP_ERR_NOMEM; + goto fail; + } + memset(p->nals + old_size, 0, (new_size - old_size) * sizeof(H265dNal)); + p->nals_allocated = new_size; + } + + consumed = process_one_nal(p, nal_data, extract_length); + if (consumed < 0) { + ret = MPP_ERR_NOMEM; + goto fail; + } + + p->nb_nals++; + nal = &p->nals[p->nb_nals - 1]; + mpp_set_bitread_ctx(&p->bit, p->bitstream + nal->bitstream_offset + 3, nal->size); + mpp_set_bitread_pseudo_code_type(&p->bit, PSEUDO_CODE_H264_H265); + if (H265d_nal_head(p) < 0) { + p->nb_nals--; + } + + buf += consumed; + length -= consumed; + total_consumed += consumed; + + if (p->is_nalff && p->nb_nals > 0 && length >= p->nal_length_size + 3) { + RK_S32 next_nal_length = 0; + + for (i = 0; i < p->nal_length_size; i++) + next_nal_length = (next_nal_length << 8) | buf[i]; + + if (next_nal_length >= 3 && p->nal_length_size + next_nal_length <= (RK_S32)length) { + const RK_U8 *next_nal_header = buf + p->nal_length_size; + RK_U8 next_nal_unit_type = (next_nal_header[0] >> 1) & 0x3F; + RK_U8 next_first_slice_flag = next_nal_header[2] >> 7; + + if (next_nal_unit_type <= NAL_RASL_R || + (next_nal_unit_type >= NAL_BLA_W_LP && next_nal_unit_type <= NAL_CRA_NUT)) { + if (next_first_slice_flag) { + h265d_dbg_func( + "Detected NEXT frame: NAL type %d, first_slice=1, " + "stopping at NAL #%d\n", + next_nal_unit_type, p->nb_nals); + break; + } + } + } + } + } + + p->consumed_bytes = total_consumed; + +fail: + + return (p->nb_nals) ? MPP_OK : ret; +} + +static RK_U16 U16_AT(const RK_U8 *ptr) +{ + return ptr[0] << 8 | ptr[1]; +} + +RK_S32 h265d_extradata(H265dPrs *p) +{ + H265dCtx *h265dctx = p->ctx; + RK_S32 ret = MPP_SUCCESS; + + p->slice_cnt = 0; + + if (h265dctx->extradata_size > 3 && + (h265dctx->extradata[0] || h265dctx->extradata[1] || + h265dctx->extradata[2] > 1)) { + const RK_U8 *ptr = (const RK_U8 *)h265dctx->extradata; + RK_U32 size = h265dctx->extradata_size; + RK_U32 numofArrays = 0, numofNals = 0; + RK_U32 j = 0, i = 0; + + if (size < 7) { + return MPP_NOK; + } + + mpp_log("extradata is encoded as hvcC format"); + p->is_nalff = 1; + p->nal_length_size = 1 + (ptr[14 + 7] & 3); + ptr += 22; + size -= 22; + numofArrays = (char)ptr[0]; + ptr += 1; + size -= 1; + for (i = 0; i < numofArrays; i++) { + ptr += 1; + size -= 1; + numofNals = U16_AT(ptr); + ptr += 2; + size -= 2; + + for (j = 0; j < numofNals; j++) { + RK_U32 length = 0; + if (size < 2) { + return MPP_NOK; + } + + length = U16_AT(ptr); + + ptr += 2; + size -= 2; + if (size < length) { + return MPP_NOK; + } + h265d_nal_unit(p, ptr, length); + ptr += length; + size -= length; + } + } + } else { + p->is_nalff = 0; + ret = h265d_split_nal(p, h265dctx->extradata, h265dctx->extradata_size); + if (ret < 0) + return ret; + ret = h265d_nal_units(p); + if (ret < 0) + return ret; + } + return ret; +} + +RK_S32 h265d_parser_init(H265dParser *s, H265dCtx* ctx) +{ + H265dPrs *p = NULL; + RK_U8 *buf = NULL; + RK_S32 size = SZ_512K; + RK_S32 ret = MPP_OK; + RK_U32 i; + + if (NULL == s || NULL == ctx) { + mpp_loge_f("invalid parser %p ctx %p\n", s, ctx); + return MPP_ERR_NULL_PTR; + } + + *s = NULL; + + p = mpp_calloc(H265dPrs, 1); + if (NULL == p) { + mpp_loge("malloc H265dPrs failed\n"); + return MPP_ERR_MALLOC; + } + + p->ctx = ctx; + + for (i = 0; i < MPP_ARRAY_ELEMS(p->dpb); i++) { + H265dFrame *frm = &p->dpb[i]; + + frm->slot_index = 0xff; + frm->poc = INT_MAX; + frm->err_status.has_err = 0; + + mpp_frame_init(&frm->frame); + + if (!frm->frame) + return MPP_ERR_NOMEM; + } + + p->max_ra = INT_MAX; + p->temporal_layer_id = 8; + p->first_nal_type = NAL_INIT_VALUE; + + p->hal_pic_private = mpp_calloc_size(void, sizeof(h265d_dxva2_picture_context_t)); + if (p->hal_pic_private) { + h265d_dxva2_picture_context_t *syn = (h265d_dxva2_picture_context_t *)p->hal_pic_private; + + syn->slice_short = (DXVA_Slice_HEVC_Short *)mpp_malloc(DXVA_Slice_HEVC_Short, MAX_SLICES); + if (!syn->slice_short) + return MPP_ERR_NOMEM; + + syn->slice_cut_param = (DXVA_Slice_HEVC_Cut_Param *)mpp_malloc(DXVA_Slice_HEVC_Cut_Param, MAX_SLICES); + if (!syn->slice_cut_param) + return MPP_ERR_NOMEM; + syn->max_slice_num = MAX_SLICES; + } else { + return MPP_ERR_NOMEM; + } + + p->slots = ctx->parser_cfg->frame_slots; + p->packet_slots = ctx->parser_cfg->packet_slots; + p->hw_info = ctx->parser_cfg->hw_info; + + buf = mpp_malloc(RK_U8, size); + if (buf == NULL) + return MPP_ERR_NOMEM; + + if (MPP_OK != mpp_packet_init(&p->input_packet, (void*)buf, size)) + return MPP_ERR_NOMEM; + + p->pre_pps_id = -1; + + /* Initialize update bitmasks */ + p->sps_update_mask = 0; + p->pps_update_mask = 0; + + p->vps_pool = mpp_mem_pool_init_f("h265d_vps", sizeof(H265dVps)); + p->sps_pool = mpp_mem_pool_init_f("h265d_sps", sizeof(H265dSps)); + + /* Initialize HDR metadata pool */ + ret = mpp_ref_pool_init(&p->hdr_meta_pool, 4); + if (ret != MPP_OK) { + mpp_loge_f("failed to init hdr meta pool\n"); + return ret; + } + p->hdr_meta_current = -1; + + *s = p; + + return MPP_OK; +} + +RK_S32 h265d_parser_deinit(H265dParser ctx) +{ + H265dPrs *p = (H265dPrs *)ctx; + RK_U8 *buf = NULL; + RK_S32 i; + + if (NULL == p) + return MPP_OK; + + for (i = 0; i < MAX_DPB_SIZE; i++) { + H265dFrmRefStatus mask = {.flags = 0x07}; + h265d_frame_unref(p, i, mask); + mpp_frame_deinit(&p->dpb[i].frame); + } + + for (i = 0; i < MAX_VPS_COUNT; i++) { + if (p->vps_list[i]) + mpp_mem_pool_put_f(p->vps_pool, p->vps_list[i]); + } + for (i = 0; i < MAX_SPS_COUNT; i++) { + if (p->sps_list[i]) + mpp_mem_pool_put_f(p->sps_pool, p->sps_list[i]); + } + for (i = 0; i < MAX_PPS_COUNT; i++) + MPP_FREE(p->pps_list[i]); + + MPP_FREE(p->nals); + MPP_FREE(p->bitstream); + + p->nals_allocated = 0; + p->bitstream_size = 0; + p->bitstream_pos = 0; + + if (p->hal_pic_private) { + h265d_dxva2_picture_context_t *ctx_pic = (h265d_dxva2_picture_context_t *)p->hal_pic_private; + + MPP_FREE(ctx_pic->slice_short); + MPP_FREE(ctx_pic->slice_cut_param); + mpp_free(p->hal_pic_private); + } + + if (p->input_packet) { + buf = mpp_packet_get_data(p->input_packet); + mpp_free(buf); + mpp_packet_deinit(&p->input_packet); + } + + if (p->vps_pool) + mpp_mem_pool_deinit_f(p->vps_pool); + if (p->sps_pool) + mpp_mem_pool_deinit_f(p->sps_pool); + + /* Deinitialize HDR metadata pool */ + mpp_ref_pool_deinit(&p->hdr_meta_pool); + + mpp_free(p); + + return MPP_OK; +} diff --git a/mpp/codec/dec/h265/h265d_pps.c b/mpp/codec/dec/h265/h265d_pps.c new file mode 100644 index 000000000..5c5e8cc94 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_pps.c @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "h265d" + +#include "mpp_mem.h" + +#include "h265d_debug.h" +#include "h265d_ctx.h" + +H265dPps *h265d_nal_pps(BitReadCtx_t *bit, const H265dSps *sps_list[]) +{ + H265dSps *sps = NULL; + H265dPps *pps = NULL; + RK_U32 pps_id = 0; + RK_S32 ret = 0; + RK_S32 i; + + h265d_dbg_func("Decoding PPS\n"); + + pps = (H265dPps *)mpp_calloc(H265dPps, 1); + if (!pps) + return NULL; + + READ_UE(bit, &pps_id); + if (pps_id >= MAX_PPS_COUNT) { + mpp_loge_f("pps: pps_id %d over MAX_PPS_COUNT\n", pps_id); + goto err; + } + + pps->pps_id = pps_id; + h265d_dbg_pps("pps: pps_id %d", pps->pps_id); + pps->loop_filter_across_tiles_enabled_flag = 1; + pps->num_tile_columns = 1; + pps->num_tile_rows = 1; + pps->uniform_spacing_flag = 1; + + READ_UE(bit, &pps->sps_id); + if (pps->sps_id >= MAX_SPS_COUNT) { + mpp_loge_f("pps: sps_id %d over MAX_SPS_COUNT\n", pps->sps_id); + goto err; + } + h265d_dbg_pps("pps: sps_id %d", pps->sps_id); + if (!sps_list[pps->sps_id]) { + mpp_loge_f("pps: sps %u missing\n", pps->sps_id); + goto err; + } + sps = (H265dSps *)sps_list[pps->sps_id]; + + READ_ONEBIT(bit, &pps->dependent_slice_segments_enabled_flag); + READ_ONEBIT(bit, &pps->output_flag_present_flag ); + READ_BITS(bit, 3, &pps->num_extra_slice_header_bits); + + READ_ONEBIT(bit, &pps->sign_data_hiding_flag); + + READ_ONEBIT(bit, &pps->cabac_init_present_flag); + + READ_UE(bit, &pps->num_ref_idx_l0_default_active); + pps->num_ref_idx_l0_default_active += 1; + READ_UE(bit, &pps->num_ref_idx_l1_default_active); + pps->num_ref_idx_l1_default_active += 1; + h265d_dbg_pps("pps: num_ref_idx_l0_default_active %d", pps->num_ref_idx_l0_default_active); + h265d_dbg_pps("pps: num_ref_idx_l1_default_active %d", pps->num_ref_idx_l1_default_active); + + READ_SE(bit, &pps->pic_init_qp_minus26); + h265d_dbg_pps("pps: pic_init_qp_minus26 %d", pps->pic_init_qp_minus26); + + READ_ONEBIT(bit, &pps->constrained_intra_pred_flag); + READ_ONEBIT(bit, &pps->transform_skip_enabled_flag); + + READ_ONEBIT(bit, &pps->cu_qp_delta_enabled_flag); + pps->diff_cu_qp_delta_depth = 0; + if (pps->cu_qp_delta_enabled_flag) + READ_UE(bit, &pps->diff_cu_qp_delta_depth); + + READ_SE(bit, &pps->cb_qp_offset); + h265d_dbg_pps("pps: cb_qp_offset %d", pps->cb_qp_offset); + if (pps->cb_qp_offset < -12 || pps->cb_qp_offset > 12) { + mpp_loge_f("pps: cb_qp_offset invalid %d\n", + pps->cb_qp_offset); + goto err; + } + READ_SE(bit, &pps->cr_qp_offset); + h265d_dbg_pps("pps: cr_qp_offset %d", pps->cr_qp_offset); + if (pps->cr_qp_offset < -12 || pps->cr_qp_offset > 12) { + mpp_loge_f("pps: cr_qp_offset invalid %d\n", + pps->cr_qp_offset); + goto err; + } + + READ_ONEBIT(bit, &pps->pic_slice_level_chroma_qp_offsets_present_flag); + READ_ONEBIT(bit, &pps->weighted_pred_flag); + READ_ONEBIT(bit, &pps->weighted_bipred_flag); + READ_ONEBIT(bit, &pps->transquant_bypass_enable_flag); + READ_ONEBIT(bit, &pps->tiles_enabled_flag); + READ_ONEBIT(bit, &pps->entropy_coding_sync_enabled_flag); + + if (pps->tiles_enabled_flag) { + RK_U32 *column_width; + RK_U32 *row_height; + + READ_UE(bit, &pps->num_tile_columns); + pps->num_tile_columns += 1; + READ_UE(bit, &pps->num_tile_rows); + pps->num_tile_rows += 1; + if (pps->num_tile_columns == 0 || pps->num_tile_columns >= sps->width) { + mpp_loge_f("pps: num_tile_columns %d invalid\n", + pps->num_tile_columns); + goto err; + } + if (pps->num_tile_rows == 0 || pps->num_tile_rows >= sps->height) { + mpp_loge_f("pps: num_tile_rows %d invalid\n", + pps->num_tile_rows); + goto err; + } + h265d_dbg_pps("pps: num_tile_columns %d", pps->num_tile_columns); + h265d_dbg_pps("pps: num_tile_rows %d", pps->num_tile_rows); + + RK_S32 column_buf_size = MPP_ALIGN(pps->num_tile_columns * sizeof(RK_U32), 8); + RK_S32 row_buf_size = pps->num_tile_rows * sizeof(RK_U32); + RK_S32 total_size = sizeof(H265dPps) + column_buf_size + row_buf_size; + + pps = (H265dPps *)mpp_realloc_size(pps, RK_U8, total_size); + if (!pps) + goto err; + + /* Calculate offsets from struct start to tile data */ + pps->column_width_offset = 0; + pps->row_height_offset = column_buf_size; + pps->column_width_size = pps->num_tile_columns; + pps->row_height_size = pps->num_tile_rows; + pps->total_size = total_size; + + /* Get pointers using offsets */ + column_width = H265D_PPS_COLUMN_WIDTH(pps); + row_height = H265D_PPS_ROW_HEIGHT(pps); + + READ_ONEBIT(bit, &pps->uniform_spacing_flag); + + if (!pps->uniform_spacing_flag) { + RK_S32 sum = 0; + + for (i = 0; i < pps->num_tile_columns - 1; i++) { + READ_UE(bit, &column_width[i]); + column_width[i] += 1; + sum += column_width[i]; + } + if (sum >= sps->ctb_width) { + mpp_loge_f("pps: invalid tile widths\n"); + goto err; + } + column_width[pps->num_tile_columns - 1] = sps->ctb_width - sum; + + sum = 0; + for (i = 0; i < pps->num_tile_rows - 1; i++) { + READ_UE(bit, &row_height[i]); + row_height[i] += 1; + sum += row_height[i]; + } + if (sum >= sps->ctb_height) { + mpp_loge_f("pps: invalid tile heights\n"); + goto err; + } + row_height[pps->num_tile_rows - 1] = sps->ctb_height - sum; + } else { + for (i = 0; i < pps->num_tile_columns; i++) { + column_width[i] = ((i + 1) * sps->ctb_width) / pps->num_tile_columns - + (i * sps->ctb_width) / pps->num_tile_columns; + } + for (i = 0; i < pps->num_tile_rows; i++) { + row_height[i] = ((i + 1) * sps->ctb_height) / pps->num_tile_rows - + (i * sps->ctb_height) / pps->num_tile_rows; + } + } + READ_ONEBIT(bit, &pps->loop_filter_across_tiles_enabled_flag); + } else { + /* No tiles, set total_size to struct size only */ + pps->total_size = sizeof(H265dPps); + } + + READ_ONEBIT(bit, &pps->seq_loop_filter_across_slices_enabled_flag); + READ_ONEBIT(bit, &pps->deblocking_filter_control_present_flag); + if (pps->deblocking_filter_control_present_flag) { + READ_ONEBIT(bit, &pps->deblocking_filter_override_enabled_flag); + READ_ONEBIT(bit, &pps->disable_dbf); + if (!pps->disable_dbf) { + READ_SE(bit, &pps->beta_offset); + pps->beta_offset = pps->beta_offset * 2; + h265d_dbg_pps("pps: beta_offset %d", pps->beta_offset); + if (pps->beta_offset < -12 || pps->beta_offset > 12) { + mpp_loge_f("pps: beta_offset invalid %d\n", pps->beta_offset / 2); + goto err; + } + READ_SE(bit, &pps->tc_offset); + pps->tc_offset = pps->tc_offset * 2; + h265d_dbg_pps("pps: tc_offset %d", pps->tc_offset); + if (pps->tc_offset < -12 || pps->tc_offset > 12) { + mpp_loge_f("pps: tc_offset invalid %d\n", pps->tc_offset / 2); + goto err; + } + } + } + + READ_ONEBIT(bit, &pps->scaling_list_data_present_flag); + if (pps->scaling_list_data_present_flag) { + h265d_set_default_scaling_list(&pps->scaling_list); + ret = h265d_scaling_list_data(bit, &pps->scaling_list, sps); + if (ret < 0) + goto err; + } + + READ_ONEBIT(bit, &pps->lists_modification_present_flag); + + READ_UE(bit, &pps->log2_parallel_merge_level); + pps->log2_parallel_merge_level += 2; + h265d_dbg_pps("pps: log2_parallel_merge_level %d", pps->log2_parallel_merge_level); + if (pps->log2_parallel_merge_level > sps->log2_ctb_size) { + mpp_loge_f("pps: log2_parallel_merge_level %d over limit\n", + pps->log2_parallel_merge_level); + goto err; + } + READ_ONEBIT(bit, &pps->slice_header_extension_present_flag); + READ_ONEBIT(bit, &pps->pps_extension_flag); + h265d_dbg_pps("pps: pps_extension_flag %d", pps->pps_extension_flag); + if (pps->pps_extension_flag) { + READ_ONEBIT(bit, &pps->pps_range_extensions_flag); + SKIP_BITS(bit, 7); + } + + return pps; +__BITREAD_ERR: +err: + MPP_FREE(pps); + return NULL; +} + +RK_S32 h265d_pps_check(const H265dPps *pps, const H265dSps *sps, + const MppDecHwCap *hw_info) +{ + if (!sps) { + mpp_loge("pps: sps %u unavailable\n", pps->sps_id); + return MPP_ERR_STREAM; + } + + if (!hw_info) + return 0; + + if (hw_info->cap_lmt_linebuf) { + RK_S32 max_supt_width = PIXW_1080P; + RK_S32 max_supt_height = (pps->tiles_enabled_flag != 0) ? PIXH_1080P : PIXW_1080P; + + if (hw_info->cap_8k) { + max_supt_width = PIXW_8Kx4K; + max_supt_height = (pps->tiles_enabled_flag != 0) ? PIXH_8Kx4K : PIXW_8Kx4K; + } else if (hw_info->cap_4k) { + max_supt_width = PIXW_4Kx2K; + max_supt_height = (pps->tiles_enabled_flag != 0) ? PIXH_4Kx2K : PIXW_4Kx2K; + } + + if (sps->width > max_supt_width || + (sps->height > max_supt_height && pps->tiles_enabled_flag) || + sps->width * sps->height > max_supt_width * max_supt_width) { + mpp_loge("pps: unsupported %dx%d max %dx%d\n", + sps->width, sps->height, max_supt_width, max_supt_height); + return MPP_ERR_STREAM; + } + } else { + if (sps->width * sps->height > PIXW_8Kx4K * PIXW_8Kx4K * hw_info->cap_core_num) { + mpp_loge("pps: unsupported %dx%d max %dx%d\n", + sps->width, sps->height, PIXW_8Kx4K, PIXW_8Kx4K); + return MPP_ERR_STREAM; + } + } + + return 0; +} diff --git a/mpp/codec/dec/h265/h265d_pps.h b/mpp/codec/dec/h265/h265d_pps.h new file mode 100644 index 000000000..d4f668a6b --- /dev/null +++ b/mpp/codec/dec/h265/h265d_pps.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_PPS_H +#define H265D_PPS_H + +#include "h265d_sps.h" +#include "mpp_soc.h" + +typedef struct H265dPps_t { + RK_U32 sps_id; + RK_U32 pps_id; + + RK_U32 sign_data_hiding_flag; + RK_U32 cabac_init_present_flag; + + RK_S32 num_ref_idx_l0_default_active; + RK_S32 num_ref_idx_l1_default_active; + RK_S32 pic_init_qp_minus26; + + RK_U32 constrained_intra_pred_flag; + RK_U32 transform_skip_enabled_flag; + + RK_U32 cu_qp_delta_enabled_flag; + RK_S32 diff_cu_qp_delta_depth; + + RK_S32 cb_qp_offset; + RK_S32 cr_qp_offset; + RK_U32 pic_slice_level_chroma_qp_offsets_present_flag; + RK_U32 weighted_pred_flag; + RK_U32 weighted_bipred_flag; + RK_U32 output_flag_present_flag; + RK_U32 transquant_bypass_enable_flag; + + RK_U32 dependent_slice_segments_enabled_flag; + RK_U32 tiles_enabled_flag; + RK_U32 entropy_coding_sync_enabled_flag; + + RK_S32 num_tile_columns; + RK_S32 num_tile_rows; + RK_U32 uniform_spacing_flag; + RK_U32 loop_filter_across_tiles_enabled_flag; + + RK_U32 seq_loop_filter_across_slices_enabled_flag; + + RK_U32 deblocking_filter_control_present_flag; + RK_U32 deblocking_filter_override_enabled_flag; + RK_U32 disable_dbf; + RK_S32 beta_offset; + RK_S32 tc_offset; + + RK_U32 scaling_list_data_present_flag; + H265dScalingList scaling_list; + + RK_U32 lists_modification_present_flag; + RK_S32 log2_parallel_merge_level; + RK_S32 num_extra_slice_header_bits; + RK_U32 slice_header_extension_present_flag; + + RK_U32 pps_extension_flag; + RK_U32 pps_range_extensions_flag; + RK_U32 log2_max_transform_skip_block_size; + RK_U32 cross_component_prediction_enabled_flag; + RK_U32 chroma_qp_offset_list_enabled_flag; + RK_U32 diff_cu_chroma_qp_offset_depth; + RK_U32 chroma_qp_offset_list_len_minus1; + RK_S8 cb_qp_offset_list[6]; + RK_S8 cr_qp_offset_list[6]; + RK_U32 log2_sao_offset_scale_luma; + RK_U32 log2_sao_offset_scale_chroma; + + RK_S32 column_width_size; + RK_S32 row_height_size; + RK_U32 column_width_offset; /* Offset from struct start to tile data */ + RK_U32 row_height_offset; /* Offset from struct start to tile data */ + RK_U32 total_size; /* Total size including tile data for memcmp */ +} H265dPps; + +/* Helper macros to access tile data via offsets */ +#define H265D_PPS_TILE_DATA(pps) ((RK_U8*)(pps) + sizeof(H265dPps)) +#define H265D_PPS_COLUMN_WIDTH(pps) ((RK_U32*)(H265D_PPS_TILE_DATA(pps) + (pps)->column_width_offset)) +#define H265D_PPS_ROW_HEIGHT(pps) ((RK_U32*)(H265D_PPS_TILE_DATA(pps) + (pps)->row_height_offset)) + +#ifdef __cplusplus +extern "C" { +#endif + +H265dPps *h265d_nal_pps(BitReadCtx_t *bit, const H265dSps *sps_list[]); +RK_S32 h265d_pps_check(const H265dPps *pps, const H265dSps *sps, + const MppDecHwCap *hw_info); + +#ifdef __cplusplus +} +#endif + +#endif /* H265D_PPS_H */ diff --git a/mpp/codec/dec/h265/h265d_sei.c b/mpp/codec/dec/h265/h265d_sei.c new file mode 100644 index 000000000..4a73b8693 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_sei.c @@ -0,0 +1,512 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "h265d" + +#include "mpp_bitread.h" +#include "rk_hdr_meta_com.h" + +#include "h265d_debug.h" +#include "h2645d_sei.h" +#include "h265d_sei.h" + +static RK_S32 decode_nal_sei_decoded_picture_hash(BitReadCtx_t *gb) +{ + RK_S32 cIdx, i; + RK_U8 hash_type; + READ_BITS(gb, 8, &hash_type); + + for (cIdx = 0; cIdx < 3; cIdx++) { + if (hash_type == 0) { + for (i = 0; i < 16; i++) + SKIP_BITS(gb, 8); + } else if (hash_type == 1) { + SKIP_BITS(gb, 16); + } else if (hash_type == 2) { + SKIP_BITS(gb, 32); + } + } + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 decode_nal_sei_frame_packing_arrangement(BitReadCtx_t *gb) +{ + RK_S32 value = 0; + + READ_UE(gb, &value); + READ_ONEBIT(gb, &value); + + if (!value) { + /* frame_packing_arrangement_type */ + READ_BITS(gb, 7, &value); + /* quincunx_subsampling */ + READ_ONEBIT(gb, &value); + /* content_interpretation_type */ + READ_BITS(gb, 6, &value); + + SKIP_BITS(gb, 6); + + /* spatiotemporal_idle_flag */ + READ_ONEBIT(gb, &value); + if (value != 3) + SKIP_BITS(gb, 16); + SKIP_BITS(gb, 8); + SKIP_BITS(gb, 1); + } + /* extension_flag */ + SKIP_BITS(gb, 1); + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 decode_pic_timing(H265dPrs *p, BitReadCtx_t *gb) +{ + H265dSps *sps; + RK_S32 value; + + if (!p->sps_list[p->active_seq_parameter_set_id]) + return MPP_ERR_NOMEM; + + sps = p->sps_list[p->active_seq_parameter_set_id]; + if (sps->vui.frame_field_info_present_flag) { + /* pic_struct */ + READ_BITS(gb, 4, &value); + (void)value; + SKIP_BITS(gb, 2); + SKIP_BITS(gb, 1); + } + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 active_parameter_sets(H265dPrs *p, BitReadCtx_t *gb) +{ + RK_S32 num_sps_ids_minus1; + RK_S32 i, value; + RK_U32 active_seq_parameter_set_id; + + SKIP_BITS(gb, 4); + SKIP_BITS(gb, 1); + SKIP_BITS(gb, 1); + READ_UE(gb, &num_sps_ids_minus1); + + READ_UE(gb, &active_seq_parameter_set_id); + if (active_seq_parameter_set_id >= MAX_SPS_COUNT) { + mpp_loge("sei: active param set id %d invalid\n", active_seq_parameter_set_id); + return MPP_ERR_STREAM; + } + p->active_seq_parameter_set_id = active_seq_parameter_set_id; + + for (i = 1; i <= num_sps_ids_minus1; i++) + READ_UE(gb, &value); + + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 mastering_display_colour_volume(H265dPrs *p, BitReadCtx_t *gb) +{ + RK_U32 value = 0; + RK_U32 lum = 0; + RK_S32 i = 0; + + for (i = 0; i < 3; i++) { + READ_BITS(gb, 16, &value); + p->mastering_display.display_primaries[i][0] = value; + READ_BITS(gb, 16, &value); + p->mastering_display.display_primaries[i][1] = value; + } + READ_BITS(gb, 16, &value); + p->mastering_display.white_point[0] = value; + READ_BITS(gb, 16, &value); + p->mastering_display.white_point[1] = value; + mpp_read_longbits(gb, 32, &lum); + p->mastering_display.max_luminance = lum; + mpp_read_longbits(gb, 32, &lum); + p->mastering_display.min_luminance = lum; + + h265d_dbg_sei("dis_prim [%d %d] [%d %d] [%d %d] white point %d %d luminance %d %d\n", + p->mastering_display.display_primaries[0][0], + p->mastering_display.display_primaries[0][1], + p->mastering_display.display_primaries[1][0], + p->mastering_display.display_primaries[1][1], + p->mastering_display.display_primaries[2][0], + p->mastering_display.display_primaries[2][1], + p->mastering_display.white_point[0], + p->mastering_display.white_point[1], + p->mastering_display.max_luminance, + p->mastering_display.min_luminance); + + return 0; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 content_light_info(H265dPrs *p, BitReadCtx_t *gb) +{ + RK_U32 value = 0; + + mpp_read_longbits(gb, 16, &value); + p->content_light.MaxCLL = value; + mpp_read_longbits(gb, 16, &value); + p->content_light.MaxFALL = value; + return 0; +} + +static RK_S32 colour_remapping_info(BitReadCtx_t *gb) +{ + RK_U32 in_bit_depth = 0; + RK_U32 out_bit_depth = 0; + RK_U32 value = 0; + RK_U32 i = 0, j = 0; + + READ_UE(gb, &value); + READ_ONEBIT(gb, &value); + if (!value) { + READ_ONEBIT(gb, &value); + READ_ONEBIT(gb, &value); + if (value) { + READ_ONEBIT(gb, &value); + READ_BITS(gb, 8, &value); + READ_BITS(gb, 8, &value); + READ_BITS(gb, 8, &value); + } + + READ_BITS(gb, 8, &in_bit_depth); + READ_BITS(gb, 8, &out_bit_depth); + for (i = 0; i < 3; i++) { + RK_U32 pre_lut_num_val_minus1 = 0; + RK_U32 in_bit = ((in_bit_depth + 7) >> 3) << 3; + RK_U32 out_bit = ((out_bit_depth + 7) >> 3) << 3; + READ_BITS(gb, 8, &pre_lut_num_val_minus1); + if (pre_lut_num_val_minus1 > 0) { + for (j = 0; j <= pre_lut_num_val_minus1; j++) { + READ_BITS(gb, in_bit, &value); + READ_BITS(gb, out_bit, &value); + } + } + } + READ_ONEBIT(gb, &value); + if (value) { + READ_BITS(gb, 4, &value); + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) + READ_SE(gb, &value); + } + } + for (i = 0; i < 3; i++) { + RK_U32 post_lut_num_val_minus1 = 0; + RK_U32 in_bit = ((in_bit_depth + 7) >> 3) << 3; + RK_U32 out_bit = ((out_bit_depth + 7) >> 3) << 3; + READ_BITS(gb, 8, &post_lut_num_val_minus1); + if (post_lut_num_val_minus1 > 0) { + for (j = 0; j <= post_lut_num_val_minus1; j++) { + READ_BITS(gb, in_bit, &value); + READ_BITS(gb, out_bit, &value); + } + } + } + + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 tone_mapping_info(BitReadCtx_t *gb) +{ + RK_U32 codec_bit_depth = 0; + RK_U32 target_bit_depth = 0; + RK_U32 value = 0; + RK_U32 i = 0; + + READ_UE(gb, &value); + READ_ONEBIT(gb, &value); + if (!value) { + RK_U32 tone_map_model_id; + + READ_ONEBIT(gb, &value); + READ_BITS(gb, 8, &codec_bit_depth); + READ_BITS(gb, 8, &target_bit_depth); + READ_UE(gb, &tone_map_model_id); + switch (tone_map_model_id) { + case 0: { + mpp_read_longbits(gb, 32, &value); + mpp_read_longbits(gb, 32, &value); + break; + } + case 1: { + mpp_read_longbits(gb, 32, &value); + mpp_read_longbits(gb, 32, &value); + break; + } + case 2: { + RK_U32 in_bit = ((codec_bit_depth + 7) >> 3) << 3; + + for (i = 0; i < (RK_U32)(1 << target_bit_depth); i++) { + READ_BITS(gb, in_bit, &value); + } + break; + } + case 3: { + RK_U32 num_pivots; + RK_U32 in_bit = ((codec_bit_depth + 7) >> 3) << 3; + RK_U32 out_bit = ((target_bit_depth + 7) >> 3) << 3; + + READ_BITS(gb, 16, &num_pivots); + for (i = 0; i < num_pivots; i++) { + READ_BITS(gb, in_bit, &value); + READ_BITS(gb, out_bit, &value); + } + break; + } + case 4: { + RK_U32 camera_iso_speed_idc; + RK_U32 exposure_index_idc; + + READ_BITS(gb, 8, &camera_iso_speed_idc); + if (camera_iso_speed_idc == 255) { + mpp_read_longbits(gb, 32, &value); + + } + READ_BITS(gb, 8, &exposure_index_idc); + if (exposure_index_idc == 255) { + mpp_read_longbits(gb, 32, &value); + } + READ_ONEBIT(gb, &value); + READ_BITS(gb, 16, &value); + READ_BITS(gb, 16, &value); + READ_BITS_LONG(gb, 32, &value); + READ_BITS_LONG(gb, 32, &value); + READ_BITS(gb, 16, &value); + READ_BITS(gb, 16, &value); + READ_BITS(gb, 16, &value); + break; + } + default: + break; + } + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 vivid_display_info(H265dPrs *p, BitReadCtx_t *gb, RK_U32 size) +{ + if (gb) + h265d_fill_dynamic_meta(p, gb->data_, size, HDRVIVID); + return 0; +} + +static RK_S32 hdr10plus_dynamic_data(H265dPrs *p, BitReadCtx_t *gb, RK_U32 size) +{ + if (gb) + h265d_fill_dynamic_meta(p, gb->data_, size, HDR10PLUS); + return 0; +} + +static RK_S32 user_data_registered_itu_t_t35(H265dPrs *p, BitReadCtx_t *gb, RK_S32 size) +{ + RK_S32 country_code, provider_code; + RK_U16 provider_oriented_code; + + if (size < 3) + return 0; + + READ_BITS(gb, 8, &country_code); + if (country_code == 0xFF) { + if (size < 1) + return 0; + + SKIP_BITS(gb, 8); + } + + if (country_code != 0xB5 && country_code != 0x26) { + mpp_log("Unsupported User Data Registered ITU-T T35 SEI message (country_code %d)", country_code); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 16, &provider_code); + READ_BITS(gb, 16, &provider_oriented_code); + h265d_dbg_sei("country_code=%d provider_code %d terminal_provider_code %d\n", + country_code, provider_code, provider_oriented_code); + switch (provider_code) { + case 0x4: { + vivid_display_info(p, gb, mpp_get_bits_left(gb) >> 3); + } break; + case 0x3c: { + const RK_U16 smpte2094_40_provider_oriented_code = 0x0001; + const RK_U8 smpte2094_40_application_identifier = 0x04; + RK_U8 application_identifier; + + READ_BITS(gb, 8, &application_identifier); + if (provider_oriented_code == smpte2094_40_provider_oriented_code && + application_identifier == smpte2094_40_application_identifier) + hdr10plus_dynamic_data(p, gb, mpp_get_bits_left(gb) >> 3); + } break; + default: + break; + } + + return 0; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 decode_nal_sei_alternative_transfer(H265dPrs *p, BitReadCtx_t *gb) +{ + HEVCSEIAlternativeTransfer *alternative_transfer = &p->alternative_transfer; + RK_S32 val; + + READ_BITS(gb, 8, &val); + alternative_transfer->present = 1; + alternative_transfer->preferred_transfer_characteristics = val; + p->is_hdr = 1; + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +MPP_RET decode_recovery_point(BitReadCtx_t *gb, H265dPrs *p) +{ + RK_S32 val = -1; + + READ_SE(gb, &val); + if (val > 32767 || val < -32767) { + h265d_dbg_sei("recovery_poc_cnt %d, is out of range"); + return MPP_ERR_STREAM; + } + + memset(&p->recovery, 0, sizeof(RecoveryPoint)); + p->recovery.valid_flag = 1; + p->recovery.recovery_frame_cnt = val; + + h265d_dbg_sei("Recovery point: poc_cnt %d", p->recovery.recovery_frame_cnt); + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +MPP_RET h265d_nal_sei(H265dPrs *p) +{ + BitReadCtx_t payload_bitctx; + BitReadCtx_t *gb = &p->bit; + RK_S32 payload_type = 0; + RK_S32 payload_size = 0; + RK_S32 byte = 0xFF; + MPP_RET ret = MPP_OK; + RK_S32 i = 0; + + h265d_dbg_sei("Decoding SEI\n"); + + do { + payload_type = 0; + payload_size = 0; + byte = 0xFF; + while (byte == 0xFF) { + if (gb->bytes_left_ < 2 || payload_type > INT_MAX - 255) { + mpp_err("parse payload_type error: byte_left %d payload_type %d\n", + gb->bytes_left_, payload_type); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 8, &byte); + payload_type += byte; + } + byte = 0xFF; + while (byte == 0xFF) { + if ((RK_S32)gb->bytes_left_ < payload_size + 1) { + mpp_err("parse payload_size error: byte_left %d payload_size %d\n", + gb->bytes_left_, payload_size + 1); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 8, &byte); + payload_size += byte; + } + + if ((RK_S32)gb->bytes_left_ < payload_size) { + mpp_err("parse payload_size error: byte_left %d payload_size %d\n", + gb->bytes_left_, payload_size); + return MPP_ERR_STREAM; + } + + memset(&payload_bitctx, 0, sizeof(payload_bitctx)); + mpp_set_bitread_ctx(&payload_bitctx, p->bit.data_, payload_size); + mpp_set_bitread_pseudo_code_type(&payload_bitctx, PSEUDO_CODE_H264_H265_SEI); + + h265d_dbg_sei("s->nal_unit_type %d payload_type %d payload_size %d\n", p->nal_unit_type, payload_type, payload_size); + + if (p->nal_unit_type == NAL_SEI_PREFIX) { + if (payload_type == 256) { + ret = decode_nal_sei_decoded_picture_hash(&payload_bitctx); + } else if (payload_type == 45) { + ret = decode_nal_sei_frame_packing_arrangement(&payload_bitctx); + } else if (payload_type == 1) { + ret = decode_pic_timing(p, &payload_bitctx); + h265d_dbg_sei("Skipped PREFIX SEI %d\n", payload_type); + } else if (payload_type == 4) { + ret = user_data_registered_itu_t_t35(p, &payload_bitctx, payload_size); + } else if (payload_type == 5) { + ret = check_encoder_sei_info(&payload_bitctx, payload_size, &p->deny_flag); + + if (p->deny_flag) + h265d_dbg_sei("Bitstream is encoded by special encoder."); + } else if (payload_type == 129) { + ret = active_parameter_sets(p, &payload_bitctx); + h265d_dbg_sei("Skipped PREFIX SEI %d\n", payload_type); + } else if (payload_type == 137) { + h265d_dbg_sei("mastering_display_colour_volume in\n"); + ret = mastering_display_colour_volume(p, &payload_bitctx); + p->is_hdr = 1; + } else if (payload_type == 144) { + h265d_dbg_sei("content_light_info in\n"); + ret = content_light_info(p, &payload_bitctx); + } else if (payload_type == 143) { + h265d_dbg_sei("colour_remapping_info in\n"); + ret = colour_remapping_info(&payload_bitctx); + } else if (payload_type == 23) { + h265d_dbg_sei("tone_mapping_info in\n"); + ret = tone_mapping_info(&payload_bitctx); + } else if (payload_type == 6) { + h265d_dbg_sei("recovery point in\n"); + p->max_ra = INT_MIN; + ret = decode_recovery_point(&payload_bitctx, p); + } else if (payload_type == 147) { + h265d_dbg_sei("alternative_transfer in\n"); + ret = decode_nal_sei_alternative_transfer(p, &payload_bitctx); + } else { + h265d_dbg_sei("Skipped PREFIX SEI %d\n", payload_type); + } + } else { + if (payload_type == 132) + ret = decode_nal_sei_decoded_picture_hash(&payload_bitctx); + else { + h265d_dbg_sei("Skipped SUFFIX SEI %d\n", payload_type); + } + } + + for (i = 0; i < payload_size; i++) + SKIP_BITS(gb, 8); + + if (ret) + return ret; + } while (gb->bytes_left_ > 1 && gb->data_[0] != 0x80); + + return ret; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} diff --git a/mpp/codec/dec/h265/h265d_sei.h b/mpp/codec/dec/h265/h265d_sei.h new file mode 100644 index 000000000..e4a882467 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_sei.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_SEI_H +#define H265D_SEI_H + +#include "h265d_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h265d_nal_sei(H265dPrs *p); + +#ifdef __cplusplus +} +#endif + +#endif /* H265D_SEI_H */ diff --git a/mpp/codec/dec/h265/h265d_slice.h b/mpp/codec/dec/h265/h265d_slice.h new file mode 100644 index 000000000..15c519f8d --- /dev/null +++ b/mpp/codec/dec/h265/h265d_slice.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_SLICE_H +#define H265D_SLICE_H + +#include "h265d_pps.h" +#include "h265d_sps.h" + +typedef struct H265dSlice_t { + RK_U32 pps_id; + + RK_U32 slice_segment_addr; + + SliceType slice_type; + + RK_S32 pic_order_cnt_lsb; + + RK_U32 first_slice_in_pic_flag; + RK_U32 dependent_slice_segment_flag; + + RK_S32 short_term_ref_pic_set_sps_flag; + RK_S32 short_term_ref_pic_set_size; + H265dStRps st_rps_slice; + const H265dStRps *st_rps_using; + H265dLtRps lt_rps; + + RK_S32 slice_qp; +} H265dSlice; + +#endif /* H265D_SLICE_H */ diff --git a/mpp/codec/dec/h265/h265d_spliter.c b/mpp/codec/dec/h265/h265d_spliter.c new file mode 100644 index 000000000..42012bba8 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_spliter.c @@ -0,0 +1,590 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "H265d" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_packet_impl.h" +#include "rk_hdr_meta_com.h" + +#include "mpp_parser.h" +#include "mpp_ring.h" +#include "h265d_debug.h" +#include "h265d_ctx.h" +#include "h265d_syntax.h" + +#define MAX_FRAME_SIZE 2048000 +#define START_CODE 0x000001 +#define INIT_RING_SIZE (512 * 1024) + +#define MPP_PARSER_PTS_NB 4 +#define H265D_STREAM_NOT_END (-10) +#define MAX_PENDING_FRAMES 4 + +typedef struct FrameSeg_t { + RK_U32 data_start; + RK_U32 data_size; +} FrameSeg; + +typedef struct H265dSpl_t { + MppRing ring; + RK_U32 ring_size; + RK_U32 write_pos; + RK_U32 data_start; + RK_U32 data_size; + RK_U64 scan_state; + RK_S32 nal_boundary_detected; + RK_S32 overlap_bytes; + RK_S32 overlap_offset; + RK_S64 pts; + RK_S64 dts; + RK_S64 pic_offset; + RK_S64 cur_offset; + RK_S64 next_pic_offset; + RK_S64 last_pts; + RK_S64 last_dts; + RK_S32 need_fetch_ts; + + RK_S32 cur_frame_start_index; + RK_S64 frame_pos_offset[MPP_PARSER_PTS_NB]; + RK_U32 frame_pos_end[MPP_PARSER_PTS_NB]; + RK_S64 frame_pos_pts[MPP_PARSER_PTS_NB]; + RK_S64 frame_pos_dts[MPP_PARSER_PTS_NB]; + + // Pending frames tracking (for FIFO sync) + FrameSeg pending_frames[MAX_PENDING_FRAMES]; + RK_S32 pending_frame_count; + + // Track actual output data start position (for spliter_frame comparison) + RK_U32 last_output_data_start; + + RK_S32 eos; +} H265dSpl; + +RK_S32 h265d_spliter_init(H265dSpliter *ctx) +{ + H265dSpl *p = (H265dSpl *)ctx; + RK_S32 ret; + + if (ctx == NULL) { + mpp_loge_f("ctx is NULL\n"); + return MPP_ERR_NULL_PTR; + } + + *ctx = NULL; + + p = mpp_calloc(H265dSpl, 1); + if (NULL == p) { + mpp_loge_f("malloc spliter failed\n"); + return MPP_ERR_MALLOC; + } + + ret = mpp_ring_get(&p->ring, INIT_RING_SIZE, "h265d_spliter"); + if (ret < 0) { + mpp_loge_f("mpp_ring_get failed\n"); + mpp_free(p); + return ret; + } + + p->ring_size = INIT_RING_SIZE; + p->write_pos = 0; + p->data_start = 0; + p->data_size = 0; + p->need_fetch_ts = 1; + p->pending_frame_count = 0; + + *ctx = p; + + return MPP_OK; +} + +RK_S32 h265d_spliter_deinit(H265dSpliter ctx) +{ + H265dSpl *p = (H265dSpl *)ctx; + + if (p) { + if (p->ring) + mpp_ring_put(p->ring); + mpp_free(p); + } + + return MPP_OK; +} + +RK_S32 h265d_spliter_reset(H265dSpliter ctx) +{ + H265dSpl *p = (H265dSpl *)ctx; + + if (p) { + p->write_pos = 0; + p->data_start = 0; + p->data_size = 0; + p->scan_state = 0; + p->nal_boundary_detected = 0; + p->overlap_bytes = 0; + p->overlap_offset = 0; + p->pts = 0; + p->dts = 0; + p->pic_offset = 0; + p->cur_offset = 0; + p->next_pic_offset = 0; + p->last_pts = 0; + p->last_dts = 0; + p->need_fetch_ts = 1; + p->cur_frame_start_index = 0; + memset(p->frame_pos_offset, 0, sizeof(p->frame_pos_offset)); + memset(p->frame_pos_end, 0, sizeof(p->frame_pos_end)); + memset(p->frame_pos_pts, 0, sizeof(p->frame_pos_pts)); + memset(p->frame_pos_dts, 0, sizeof(p->frame_pos_dts)); + p->pending_frame_count = 0; + p->eos = 0; + } + + return MPP_OK; +} + +void h265d_spliter_set_eos(H265dSpliter ctx, RK_S32 eos) +{ + H265dSpl *p = (H265dSpl *)ctx; + + if (p) + p->eos = eos; +} + +RK_S64 h265d_spliter_get_pts(H265dSpliter ctx) +{ + H265dSpl *p = (H265dSpl *)ctx; + + return (p != NULL) ? p->pts : 0; +} + +RK_S64 h265d_spliter_get_dts(H265dSpliter ctx) +{ + H265dSpl *p = (H265dSpl *)ctx; + + return (p != NULL) ? p->dts : 0; +} + +RK_S32 h265d_find_frame_end(H265dSpliter ctx, const RK_U8 *buf, RK_S32 buf_size) +{ + H265dSpl *p = (H265dSpl *)ctx; + RK_S32 i; + + for (i = 0; i < buf_size; i++) { + RK_S32 nut; + RK_S32 layer_id; + + p->scan_state = (p->scan_state << 8) | buf[i]; + + if (((p->scan_state >> 3 * 8) & 0xFFFFFF) != START_CODE) + continue; + + nut = (p->scan_state >> (2 * 8 + 1)) & 0x3F; + layer_id = (((p->scan_state >> 2 * 8) & 0x01) << 5) + (((p->scan_state >> 1 * 8) & 0xF8) >> 3); + + if ((nut >= NAL_VPS && nut <= NAL_AUD) || nut == NAL_SEI_PREFIX || + (nut >= 41 && nut <= 44) || (nut >= 48 && nut <= 55)) { + if (p->nal_boundary_detected && !layer_id) { + p->nal_boundary_detected = 0; + return i - 5; + } + } else if (nut <= NAL_RASL_R || + (nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT)) { + RK_S32 first_slice_segment_in_pic_flag = buf[i] >> 7; + + if (first_slice_segment_in_pic_flag && !layer_id) { + if (!p->nal_boundary_detected) { + p->nal_boundary_detected = 1; + } else { + p->nal_boundary_detected = 0; + return i - 5; + } + } + } + } + + return H265D_STREAM_NOT_END; +} + +static RK_S32 h265d_combine_frame(H265dSpl *p, RK_S32 next, const RK_U8 **buf, RK_S32 *buf_size) +{ + void *ring_ptr; + RK_U32 output_size = 0; + + h265d_dbg_split("combine_frame next %d buf_size %d data_size %u write_pos %u data_start %u\n", + next, *buf_size, p->data_size, p->write_pos, p->data_start); + + if (p->overlap_bytes) { + h265d_dbg_split("overlap %d bytes state %llx pos %d offset %d\n", + p->overlap_bytes, p->scan_state & 0xFFFFFFFF, next, p->overlap_offset); + h265d_dbg_split("overlap data %X %X %X %X\n", (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); + } + + if (!*buf_size && next == H265D_STREAM_NOT_END) + next = 0; + + if (next == H265D_STREAM_NOT_END) { + RK_U32 needed = p->data_size + *buf_size + MPP_INPUT_BUFFER_PADDING_SIZE; + + h265d_dbg_split("accumulate data_size %u buf_size %d needed %u ring_size %u\n", + p->data_size, *buf_size, needed, p->ring_size); + + if (needed > p->ring_size) { + RK_U32 old_size = p->ring_size; + RK_U32 new_size = MPP_MAX(needed * 3 / 2, p->ring_size * 2); + void *old_ring_ptr = mpp_ring_get_ptr(p->ring); + + h265d_dbg_split("resize ring_size %u -> %u\n", old_size, new_size); + h265d_dbg_split("resize before data_start %u data_size %u write_pos %u\n", + p->data_start, p->data_size, p->write_pos); + + // Check if data wraps around the old ring boundary BEFORE resize + RK_U8 *saved_wrap_data = NULL; + RK_U32 wrap_size = 0; + + if (p->data_start + p->data_size > old_size) { + RK_U32 tail_size = old_size - p->data_start; + wrap_size = p->data_size - tail_size; + + h265d_dbg_split("resize wrapped data_start %u data_size %u tail %u wrap %u\n", + p->data_start, p->data_size, tail_size, wrap_size); + + // Save wrapped data from OLD ring pointer BEFORE resize + saved_wrap_data = mpp_calloc(RK_U8, wrap_size); + if (saved_wrap_data) { + memcpy(saved_wrap_data, (RK_U8 *)old_ring_ptr, wrap_size); + h265d_dbg_split("resize saved wrap_data [%u:%u] from old_ring_ptr %p\n", + 0, wrap_size, old_ring_ptr); + } else { + mpp_loge_f("hal: alloc saved_wrap_data %u failed\n", wrap_size); + } + } + + // Resize first to get new memory + if (mpp_ring_resize(p->ring, new_size)) { + mpp_loge_f("hal: resize ring to %u failed\n", new_size); + if (saved_wrap_data) + mpp_free(saved_wrap_data); + return MPP_ERR_NOMEM; + } + p->ring_size = new_size; + + // Get new pointer after resize + ring_ptr = mpp_ring_get_ptr(p->ring); + h265d_dbg_split("resize old_ring_ptr %p new_ring_ptr %p\n", + old_ring_ptr, ring_ptr); + + // Verify data integrity after resize and move wrapped data + if (saved_wrap_data && wrap_size > 0) { + // Verify: data at new ring_ptr should match saved data + if (memcmp(ring_ptr, saved_wrap_data, wrap_size) == 0) { + h265d_dbg_split("resize verify memfd data preserved after resize\n"); + } else { + mpp_loge_f("hal: resize memfd data corrupted\n"); + } + + // Move wrapped data to make it contiguous + memcpy(ring_ptr + old_size, ring_ptr, wrap_size); + p->write_pos = old_size + wrap_size; + + // Verify: moved data matches saved data + if (memcmp(ring_ptr + old_size, saved_wrap_data, wrap_size) == 0) { + h265d_dbg_split("resize verify move success\n"); + } else { + mpp_loge_f("hal: resize move data corrupted\n"); + } + + h265d_dbg_split("resize move [%u:%u] -> [%u:%u]\n", + 0, wrap_size, old_size, old_size + wrap_size); + h265d_dbg_split("resize after data_start %u write_pos %u\n", + p->data_start, p->write_pos); + + mpp_free(saved_wrap_data); + } else { + h265d_dbg_split("resize no_wrap data_start %u data_size %u\n", + p->data_start, p->data_size); + } + } + + ring_ptr = mpp_ring_get_ptr(p->ring); + memcpy(ring_ptr + p->write_pos, *buf, *buf_size); + p->write_pos += *buf_size; + if (p->write_pos >= p->ring_size) + p->write_pos -= p->ring_size; + p->data_size += *buf_size; + + h265d_dbg_split("accumulate done data_size %u write_pos %u\n", p->data_size, p->write_pos); + + return -1; + } + + // Frame boundary found - need to output frame + h265d_dbg_split("frame_boundary next %d data_size %u\n", next, p->data_size); + + ring_ptr = mpp_ring_get_ptr(p->ring); + + if (p->data_size) { + RK_S32 frame_size = p->data_size + next; // next can be negative + + h265d_dbg_split("output frame_size %d data_size %u next %d\n", + frame_size, p->data_size, next); + + // Save frame data location before modifying ring state + RK_U8 *frame_data = ring_ptr + p->data_start; + RK_U32 output_data_start = p->data_start; // Save for pending_frames + + // Append new data (first 'next' bytes) to ring for current frame + if (next > 0) { + memcpy(ring_ptr + p->write_pos, *buf, next); + p->write_pos += next; + if (p->write_pos >= p->ring_size) { + h265d_dbg_split("write_pos_wrap before %u -> after %u\n", + p->write_pos, p->write_pos - p->ring_size); + p->write_pos -= p->ring_size; + } + p->data_size += next; + h265d_dbg_split("append bytes %d data_size %u write_pos %u\n", + next, p->data_size, p->write_pos); + } + + // Save remaining new input data for next frame + // NOTE: For zero-copy, remaining data stays in input buffer (not copied to ring) + // This prevents overwriting the zero-copy output frame + if (next > 0 && *buf_size > next) { + // Remaining data stays in input buffer + // Don't copy to ring, just clear ring state + p->data_size = 0; + p->data_start = 0; + p->write_pos = 0; + h265d_dbg_split("keep_remain in_input_buf %u\n", *buf_size - next); + } else { + p->data_size = 0; + p->data_start = 0; + p->write_pos = 0; + h265d_dbg_split("ring_clear data_size 0 data_start 0 write_pos 0\n"); + } + + // Zero-copy output: directly return ring pointer + // Save frame info for sync release (FIFO) + if (p->pending_frame_count < MAX_PENDING_FRAMES) { + p->pending_frames[p->pending_frame_count].data_start = output_data_start; + p->pending_frames[p->pending_frame_count].data_size = frame_size; + p->pending_frame_count++; + } + + *buf = frame_data; + *buf_size = p->overlap_offset = frame_size; + + // Save actual output data start for spliter_frame comparison + p->last_output_data_start = output_data_start; + + h265d_dbg_split("zero_copy_output frame_size %d pending_count %d output_data_start %u\n", + frame_size, p->pending_frame_count, output_data_start); + } else { + // No accumulated data - output new input directly + output_size = next; + *buf_size = p->overlap_offset = next; + h265d_dbg_split("no_accum output_size %d\n", next); + } + + if (next < -8) { + p->overlap_bytes += (-8 - next); + next = -8; + h265d_dbg_split("overlap_adjust overlap_bytes %d next %d\n", p->overlap_bytes, next); + } + + // Calculate overlap position for scan_state update + // Scan from the output frame data + RK_U32 scan_pos = 0; + if (p->data_size) { + scan_pos = p->data_size; + } else { + scan_pos = output_size; + } + + while (next < 0) { + RK_S32 pos = scan_pos + next; + const RK_U8 *data_ptr; + + if (p->data_size || output_size) { + // Read from output frame (from *buf which was set above) + data_ptr = (const RK_U8 *)*buf; + } else { + ring_ptr = mpp_ring_get_ptr(p->ring); + data_ptr = (const RK_U8 *)ring_ptr + p->data_start; + } + p->scan_state = (p->scan_state << 8) | data_ptr[pos]; + p->overlap_bytes++; + next++; + } + + if (p->overlap_bytes) { + h265d_dbg_split("overlap_final bytes %d state %llX\n", + p->overlap_bytes, p->scan_state & 0xFFFFFFFF); + } + + return 0; +} + +void h265d_spliter_sync(H265dSpliter ctx, RK_S32 frame_id) +{ + H265dSpl *p = (H265dSpl *)ctx; + + if (!p || p->pending_frame_count == 0) + return; + + (void)frame_id; // frame_id is not used in FIFO mode + + h265d_dbg_split("sync pending_count %d\n", p->pending_frame_count); + + // FIFO: Release the oldest frame (index 0) + RK_U32 old_data_start = p->pending_frames[0].data_start; + RK_U32 old_data_size = p->pending_frames[0].data_size; + + // Skip the released frame's data from data_start + // Note: data_size is already updated during output, only update data_start here + RK_U32 prev_data_start = p->data_start; + p->data_start += old_data_size; + if (p->data_start >= p->ring_size) + p->data_start -= p->ring_size; + + // Sync write_pos with data_start to maintain ring buffer consistency + // When data_size is 0 (entire frame was output), ring was cleared. + // In this case, sync write_pos to match data_start for next accumulation. + if (p->data_size == 0) { + p->write_pos = p->data_start; + } else if (p->data_start > prev_data_start && p->write_pos < p->data_start) { + // data_start moved forward without wrap, sync write_pos if needed + p->write_pos = p->data_start; + } + + h265d_dbg_split("sync_release old_start %u old_size %u new_start %u data_size %u write_pos %u\n", + old_data_start, old_data_size, p->data_start, p->data_size, p->write_pos); + + // Remove processed frame from pending_frames (shift left) + for (RK_S32 i = 0; i < p->pending_frame_count - 1; i++) { + p->pending_frames[i] = p->pending_frames[i + 1]; + } + p->pending_frame_count--; +} + +static void h265d_get_timestamp(H265dSpl *p, RK_S32 off) +{ + RK_S32 i; + + p->pts = -1; + p->dts = -1; + + for (i = 0; i < MPP_PARSER_PTS_NB; i++) { + h265d_dbg_pts("cur_offset %lld frame_pos_offset[%d] %lld pic_offset %lld next_pic_offset %lld", + p->cur_offset, i, p->frame_pos_offset[i], p->pic_offset, p->next_pic_offset); + if (p->cur_offset + off >= p->frame_pos_offset[i] + && (p->pic_offset < p->frame_pos_offset[i] || + (!p->pic_offset && !p->next_pic_offset)) + && p->frame_pos_end[i]) { + p->dts = p->frame_pos_dts[i]; + p->pts = p->frame_pos_pts[i]; + if (p->cur_offset + off < p->frame_pos_end[i]) + break; + } + } +} + +RK_S32 h265d_spliter_frame(H265dSpliter ctx, const RK_U8 **buf_out, RK_S32 *buf_size_out, + const RK_U8 *buf, RK_S32 buf_size, RK_S64 pts, RK_S64 dts) +{ + H265dSpl *p = (H265dSpl*)ctx; + RK_S32 next; + RK_S32 i; + + if (p->cur_offset + buf_size != + p->frame_pos_end[p->cur_frame_start_index]) { + i = p->cur_frame_start_index + 1; + + if (i >= MPP_PARSER_PTS_NB) + i = 0; + + p->cur_frame_start_index = i; + p->frame_pos_offset[i] = p->cur_offset; + p->frame_pos_end[i] = p->cur_offset + buf_size; + p->frame_pos_pts[i] = pts; + p->frame_pos_dts[i] = dts; + + h265d_dbg_pts("cur_frame_start_index %d frame_pos_offset %lld frame_pos_end %lld pts %lld", + p->cur_frame_start_index, p->frame_pos_offset[i], p->frame_pos_end[i], pts); + } + + if (p->need_fetch_ts) { + p->need_fetch_ts = 0; + p->last_pts = p->pts; + p->last_dts = p->dts; + h265d_get_timestamp(p, 0); + } + + if (p->eos && !buf_size) { + void *ring_ptr = mpp_ring_get_ptr(p->ring); + + *buf_out = ring_ptr + p->data_start; + *buf_size_out = p->data_size; + return 0; + } + + next = h265d_find_frame_end(p, buf, buf_size); + if (p->eos && buf_size && next == H265D_STREAM_NOT_END) { + next = buf_size; + } + + // old_data_start is no longer used - we use last_output_data_start from combine_frame + + if (h265d_combine_frame(p, next, &buf, &buf_size) < 0) { + *buf_out = NULL; + *buf_size_out = 0; + p->cur_offset += buf_size; + return buf_size; + } + + *buf_out = buf; + *buf_size_out = buf_size; + + if (next < 0) + next = 0; + + if (*buf_size_out) { + void *ring_ptr; + p->pic_offset = p->next_pic_offset; + p->next_pic_offset = p->cur_offset + next; + p->need_fetch_ts = 1; + + // Check if output is from temporary buffer or ring + ring_ptr = mpp_ring_get_ptr(p->ring); + if ((const RK_U8 *)*buf_out < (const RK_U8 *)ring_ptr || + (const RK_U8 *)*buf_out >= (const RK_U8 *)ring_ptr + p->ring_size * 2) { + // Output is from temporary buffer - ring state was already updated + h265d_dbg_split("output_src temp_buf data_size %u data_start %u\n", + p->data_size, p->data_start); + } else if ((const RK_U8 *)*buf_out == (const RK_U8 *)ring_ptr + p->last_output_data_start) { + // Output is from old ring position (normal frame output) + // Ring state was already updated in h265d_combine_frame + h265d_dbg_split("output_src old_ring data_size %u data_start %u\n", + p->data_size, p->data_start); + } else { + // Output is from current ring position (EOS case) - need to update ring state + RK_U32 old_data_size = p->data_size; + RK_U32 old_data_start = p->data_start; + p->data_size -= *buf_size_out; + p->data_start += *buf_size_out; + if (p->data_start >= p->ring_size) + p->data_start -= p->ring_size; + h265d_dbg_split("output_src curr_ring data_size %u->%u data_start %u->%u\n", + old_data_size, p->data_size, old_data_start, p->data_start); + } + } + + p->cur_offset += next; + + return next; +} diff --git a/mpp/codec/dec/h265/h265d_spliter.h b/mpp/codec/dec/h265/h265d_spliter.h new file mode 100644 index 000000000..ce81666a4 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_spliter.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_SPLITER_H +#define H265D_SPLITER_H + +#include "rk_type.h" + +typedef void* H265dSpliter; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 h265d_spliter_init(H265dSpliter *ctx); +RK_S32 h265d_spliter_deinit(H265dSpliter ctx); + +RK_S32 h265d_spliter_reset(H265dSpliter ctx); + +void h265d_spliter_set_eos(H265dSpliter ctx, RK_S32 eos); +RK_S64 h265d_spliter_get_pts(H265dSpliter ctx); +RK_S64 h265d_spliter_get_dts(H265dSpliter ctx); +void h265d_spliter_sync(H265dSpliter ctx, RK_S32 frame_id); + +RK_S32 h265d_spliter_frame(H265dSpliter ctx, const RK_U8 **poutbuf, RK_S32 *poutbuf_size, + const RK_U8 *buf, RK_S32 buf_size, RK_S64 pts, RK_S64 dts); + +#ifdef __cplusplus +} +#endif + +#endif /* H265D_SPLITER_H */ diff --git a/mpp/codec/dec/h265/h265d_sps.c b/mpp/codec/dec/h265/h265d_sps.c new file mode 100644 index 000000000..9c06c2cc0 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_sps.c @@ -0,0 +1,895 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "H265d" + +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bit.h" + +#include "h265d_debug.h" +#include "h265d_ctx.h" + +static const RK_U8 default_scaling_list_intra[] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115, +}; + +static const RK_U8 default_scaling_list_inter[] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91, +}; + +const RK_U8 h265d_diag_scan4x4_map[16] = { + 0, 4, 1, 8, + 5, 2, 12, 9, + 6, 3, 13, 10, + 7, 14, 11, 15, +}; + +const RK_U8 h265d_diag_scan8x8_map[64] = { + 0, 8, 1, 16, 9, 2, 24, 17, + 10, 3, 32, 25, 18, 11, 4, 40, + 33, 26, 19, 12, 5, 48, 41, 34, + 27, 20, 13, 6, 56, 49, 42, 35, + 28, 21, 14, 7, 57, 50, 43, 36, + 29, 22, 15, 58, 51, 44, 37, 30, + 23, 59, 52, 45, 38, 31, 60, 53, + 46, 39, 61, 54, 47, 62, 55, 63, +}; + +static void h265d_sort_delta_poc(H265dStRps *rps) +{ + RK_S32 i; + + if (rps->num_deltas <= 1) + return; + + for (i = 1; i < rps->num_deltas; i++) { + RK_S32 delta_poc = rps->poc_delta[i]; + RK_U32 used_val = MPP_GET_BIT(rps->flags, i); + RK_S32 j; + + for (j = i - 1; j >= 0 && rps->poc_delta[j] > delta_poc; j--) { + rps->poc_delta[j + 1] = rps->poc_delta[j]; + MPP_MOD_BIT(rps->flags, j + 1, MPP_GET_BIT(rps->flags, j)); + } + + rps->poc_delta[j + 1] = delta_poc; + MPP_MOD_BIT(rps->flags, j + 1, used_val); + } +} + +static void h265d_flip_negative_pics(H265dStRps *rps) +{ + RK_S32 left = 0; + RK_S32 right = rps->num_neg - 1; + RK_S32 tmp_poc; + RK_U8 tmp_used; + + while (left < right) { + tmp_poc = rps->poc_delta[left]; + tmp_used = MPP_GET_BIT(rps->flags, left); + + rps->poc_delta[left] = rps->poc_delta[right]; + MPP_MOD_BIT(rps->flags, left, MPP_GET_BIT(rps->flags, right)); + rps->poc_delta[right] = tmp_poc; + MPP_MOD_BIT(rps->flags, right, tmp_used); + + left++; + right--; + } +} + +static RK_S32 h265d_rps_direct(BitReadCtx_t *bit, H265dStRps *rps) +{ + RK_U32 num_positive; + RK_S32 delta_poc; + RK_U32 prev_poc; + RK_S32 i; + + READ_UE(bit, &rps->num_neg); + READ_UE(bit, &num_positive); + + if (rps->num_neg >= MAX_REFS || num_positive >= MAX_REFS) { + mpp_loge("sps: short term rps refs count over max\n"); + return MPP_ERR_STREAM; + } + + rps->num_deltas = rps->num_neg + num_positive; + rps->flags = 0; + + if (rps->num_deltas == 0) + return 0; + + prev_poc = 0; + for (i = 0; (RK_U32)i < rps->num_neg; i++) { + READ_UE(bit, &delta_poc); + delta_poc += 1; + prev_poc -= delta_poc; + rps->poc_delta[i] = prev_poc; + { + RK_S32 _bit; bit->ret = mpp_read_bits(bit, 1, &_bit); + if (bit->ret) goto __BITREAD_ERR; + if (_bit) rps->flags |= MPP_BIT(i); + } + } + + prev_poc = 0; + for (i = 0; (RK_U32)i < num_positive; i++) { + RK_U32 idx = rps->num_neg + i; + RK_S32 _bit; + + READ_UE(bit, &delta_poc); + delta_poc += 1; + prev_poc += delta_poc; + rps->poc_delta[idx] = prev_poc; + + bit->ret = mpp_read_bits(bit, 1, &_bit); + if (bit->ret) + goto __BITREAD_ERR; + if (_bit) + rps->flags |= MPP_BIT(idx); + } + + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 h265d_rps_prediction(BitReadCtx_t *bit, H265dStRps *rps, + const H265dSps *sps, RK_S32 is_slice_header) +{ + const H265dStRps *ref_rps; + RK_U32 delta_idx = 0; + RK_U32 sign_flag; + RK_U32 abs_delta; + RK_S32 ref_delta; + RK_S32 pic_count = 0; + RK_S32 neg_count = 0; + RK_U8 used_array[32] = {0}; + RK_S32 i; + + rps->flags = 0; + + if (is_slice_header) { + READ_UE(bit, &delta_idx); + delta_idx++; + if (delta_idx > sps->nb_st_rps) { + mpp_loge("sps: delta_idx %u over nb_st_rps %u\n", + delta_idx, sps->nb_st_rps); + return MPP_ERR_STREAM; + } + ref_rps = &sps->st_rps_sps[sps->nb_st_rps - delta_idx]; + } else { + ref_rps = &sps->st_rps_sps[rps - sps->st_rps_sps - 1]; + } + + READ_BITS(bit, 1, &sign_flag); + READ_UE(bit, &abs_delta); + abs_delta++; + + ref_delta = sign_flag ? -((RK_S32)abs_delta) : (RK_S32)abs_delta; + + for (i = 0; i <= ref_rps->num_deltas; i++) { + RK_U8 used_flag = 0; + RK_U8 include_flag = 0; + RK_S32 cur_poc; + + READ_ONEBIT(bit, &used_flag); + + if (!used_flag) + READ_ONEBIT(bit, &include_flag); + + if (used_flag || include_flag) { + if (i < ref_rps->num_deltas) + cur_poc = ref_delta + ref_rps->poc_delta[i]; + else + cur_poc = ref_delta; + + rps->poc_delta[pic_count] = cur_poc; + used_array[pic_count] = used_flag; + + if (cur_poc < 0) + neg_count++; + + pic_count++; + } + } + + rps->num_deltas = pic_count; + rps->num_neg = neg_count; + + if (pic_count > 0) { + h265d_sort_delta_poc(rps); + h265d_flip_negative_pics(rps); + + for (i = 0; i < pic_count; i++) + if (used_array[i]) + rps->flags |= MPP_BIT(i); + } + + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +RK_S32 h265d_st_rps(BitReadCtx_t *bit, H265dStRps *rps, const H265dSps *sps, + RK_S32 is_slice_header, RK_U8 *rps_need_update) +{ + RK_U32 use_prediction = 0; + RK_S32 ret; + + if (rps != sps->st_rps_sps && sps->nb_st_rps) + READ_ONEBIT(bit, &use_prediction); + + if (use_prediction) { + ret = h265d_rps_prediction(bit, rps, sps, is_slice_header); + } else { + ret = h265d_rps_direct(bit, rps); + } + + if (ret == 0 && rps_need_update) + *rps_need_update = 1; + + return ret; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static void h265d_vui_init(H265dVui *vui) +{ + vui->sar_den = 1; + + vui->colour_primaries = MPP_FRAME_PRI_UNSPECIFIED; + vui->transfer_characteristic = MPP_FRAME_TRC_UNSPECIFIED; + vui->matrix_coeffs = MPP_FRAME_SPC_UNSPECIFIED; +} + +static RK_S32 h265d_vui(BitReadCtx_t *bit, H265dSps *sps) +{ + static const RK_S32 vui_sar[17][2] = { + { 0, 1 }, + { 1, 1 }, + { 12, 11 }, + { 10, 11 }, + { 16, 11 }, + { 40, 33 }, + { 24, 11 }, + { 20, 11 }, + { 32, 11 }, + { 80, 33 }, + { 18, 11 }, + { 15, 11 }, + { 64, 33 }, + { 160, 99 }, + { 4, 3 }, + { 3, 2 }, + { 2, 1 }, + }; + H265dVui *vui = &sps->vui; + RK_S32 sar_present; + + h265d_dbg_func("Parsing vui data\n"); + + vui->vui_present = 1; + + READ_ONEBIT(bit, &sar_present); + if (sar_present) { + RK_U32 sar_idx = 0; + + READ_BITS(bit, 8, &sar_idx); + if (sar_idx < MPP_ARRAY_ELEMS(vui_sar)) { + vui->sar_num = vui_sar[sar_idx][0]; + vui->sar_den = vui_sar[sar_idx][1]; + } else if (sar_idx == 255) { + READ_BITS(bit, 16, &vui->sar_num); + READ_BITS(bit, 16, &vui->sar_den); + } else + mpp_log("sps: invalid sample aspect ratio index %u\n", sar_idx); + } + + READ_ONEBIT(bit, &vui->overscan_info_present_flag); + if (vui->overscan_info_present_flag) + READ_ONEBIT(bit, &vui->overscan_appropriate_flag); + + READ_ONEBIT(bit, &vui->video_signal_type_present_flag); + if (vui->video_signal_type_present_flag) { + READ_BITS(bit, 3, & vui->video_format); + READ_ONEBIT(bit, &vui->video_full_range_flag); + READ_ONEBIT(bit, &vui->colour_description_present_flag); + + if (vui->colour_description_present_flag) { + READ_BITS(bit, 8, &vui->colour_primaries); + READ_BITS(bit, 8, &vui->transfer_characteristic); + READ_BITS(bit, 8, &vui->matrix_coeffs); + + if (vui->matrix_coeffs >= MPP_FRAME_SPC_NB) + vui->matrix_coeffs = MPP_FRAME_SPC_UNSPECIFIED; + } + } + + READ_ONEBIT(bit, &vui->chroma_loc_info_present_flag ); + if (vui->chroma_loc_info_present_flag) { + READ_UE(bit, &vui->chroma_sample_loc_type_top_field); + READ_UE(bit, &vui->chroma_sample_loc_type_bottom_field); + } + + READ_ONEBIT(bit, &vui->neutra_chroma_indication_flag); + READ_ONEBIT(bit, &vui->field_seq_flag); + READ_ONEBIT(bit, &vui->frame_field_info_present_flag); + + READ_ONEBIT(bit, &vui->default_display_window_flag); + if (vui->default_display_window_flag) { + READ_UE(bit, &vui->def_disp_win.left_offset); + READ_UE(bit, &vui->def_disp_win.right_offset); + READ_UE(bit, &vui->def_disp_win.top_offset); + READ_UE(bit, &vui->def_disp_win.bottom_offset); + if (sps) { + if (sps->chroma_format_idc == H265_CHROMA_420) { + vui->def_disp_win.left_offset *= 2; + vui->def_disp_win.right_offset *= 2; + vui->def_disp_win.top_offset *= 2; + vui->def_disp_win.bottom_offset *= 2; + } else if (sps->chroma_format_idc == H265_CHROMA_422) { + vui->def_disp_win.left_offset *= 2; + vui->def_disp_win.right_offset *= 2; + } + } + } + + READ_ONEBIT(bit, &vui->vui_timing_info_present_flag); + + if (vui->vui_timing_info_present_flag) { + mpp_read_longbits(bit, 32, &vui->vui_num_units_in_tick); + mpp_read_longbits(bit, 32, &vui->vui_time_scale); + READ_ONEBIT(bit, &vui->vui_poc_proportional_to_timing_flag); + if (vui->vui_poc_proportional_to_timing_flag) + READ_UE(bit, &vui->vui_num_ticks_poc_diff_one_minus1); + READ_ONEBIT(bit, &vui->vui_hrd_parameters_present_flag); + if (vui->vui_hrd_parameters_present_flag) + h265d_hrd_info(bit, 1, sps->max_sub_layers); + } + + READ_ONEBIT(bit, &vui->bitstream_restriction_flag); + if (vui->bitstream_restriction_flag) { + READ_ONEBIT(bit, &vui->tiles_fixed_structure_flag); + READ_ONEBIT(bit, &vui->motion_vectors_over_pic_boundaries_flag); + READ_ONEBIT(bit, &vui->restricted_ref_pic_lists_flag); + READ_UE(bit, &vui->min_spatial_segmentation_idc); + READ_UE(bit, &vui->max_bytes_per_pic_denom); + READ_UE(bit, &vui->max_bits_per_min_cu_denom); + READ_UE(bit, &vui->log2_max_mv_length_horizontal); + READ_UE(bit, &vui->log2_max_mv_length_vertical); + } + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +void h265d_set_default_scaling_list(H265dScalingList *sl) +{ + RK_S32 matrixId; + + for (matrixId = 0; matrixId < 6; matrixId++) { + memset(sl->scaling_lists[SCALE_4X4_COPY][matrixId], 16, 16); + sl->scaling_list_dc[0][matrixId] = 16; + sl->scaling_list_dc[1][matrixId] = 16; + } + memcpy(sl->scaling_lists[SCALE_4X4][0], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_4X4][1], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_4X4][2], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_4X4][3], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_4X4][4], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_4X4][5], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_8X8][0], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_8X8][1], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_8X8][2], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_8X8][3], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_8X8][4], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_8X8][5], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_16X16][0], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_16X16][1], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_16X16][2], default_scaling_list_intra, 64); + memcpy(sl->scaling_lists[SCALE_16X16][3], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_16X16][4], default_scaling_list_inter, 64); + memcpy(sl->scaling_lists[SCALE_16X16][5], default_scaling_list_inter, 64); +} + +RK_S32 h265d_scaling_list_data(BitReadCtx_t *bit, H265dScalingList *sl, H265dSps *sps) +{ + RK_S32 sl_dc_coef[2][6]; + RK_S32 sz_id, mat_id, pos; + RK_S32 coef_count, idx; + RK_U8 pred_flag; + + for (sz_id = 0; sz_id < 4; sz_id++) { + RK_U32 mat_step = (sz_id == 3) ? 3 : 1; + for (mat_id = 0; mat_id < 6; mat_id += mat_step) { + READ_ONEBIT(bit, &pred_flag); + + if (!pred_flag) { + RK_U32 delta = 0; + READ_UE(bit, &delta); + if (delta) { + delta *= mat_step; + if ((RK_U32)mat_id < delta) { + mpp_loge("sps: scaling list delta %u over matrix_id %u\n", delta, mat_id); + return MPP_ERR_STREAM; + } + + memcpy(sl->scaling_lists[sz_id][mat_id], + sl->scaling_lists[sz_id][mat_id - delta], + sz_id > 0 ? 64 : 16); + if (sz_id > 1) + sl->scaling_list_dc[sz_id - 2][mat_id] = sl->scaling_list_dc[sz_id - 2][mat_id - delta]; + } + } else { + RK_S32 coef_val = 8; + RK_S32 delta_coef; + + coef_count = MPP_MIN(64, 1 << (4 + (sz_id << 1))); + + if (sz_id > 1) { + RK_S32 dc_minus8; + READ_SE(bit, &dc_minus8); + if (dc_minus8 < -7 || dc_minus8 > 247) { + mpp_loge("sps: dc coeff out of range %d\n", dc_minus8); + return MPP_ERR_STREAM; + } + sl_dc_coef[sz_id - 2][mat_id] = dc_minus8 + 8; + coef_val = sl_dc_coef[sz_id - 2][mat_id]; + sl->scaling_list_dc[sz_id - 2][mat_id] = coef_val; + } + + for (idx = 0; idx < coef_count; idx++) { + if (sz_id == 0) + pos = h265d_diag_scan4x4_map[idx]; + else + pos = h265d_diag_scan8x8_map[idx]; + + READ_SE(bit, &delta_coef); + coef_val = (coef_val + delta_coef + 256) % 256; + sl->scaling_lists[sz_id][mat_id][pos] = coef_val; + } + } + } + } + + if (sps->chroma_format_idc == H265_CHROMA_444) { + for (idx = 0; idx < 64; idx++) { + sl->scaling_lists[SCALE_16X16][1][idx] = sl->scaling_lists[SCALE_8X8][1][idx]; + sl->scaling_lists[SCALE_16X16][2][idx] = sl->scaling_lists[SCALE_8X8][2][idx]; + sl->scaling_lists[SCALE_16X16][4][idx] = sl->scaling_lists[SCALE_8X8][4][idx]; + sl->scaling_lists[SCALE_16X16][5][idx] = sl->scaling_lists[SCALE_8X8][5][idx]; + } + sl->scaling_list_dc[1][1] = sl->scaling_list_dc[0][1]; + sl->scaling_list_dc[1][2] = sl->scaling_list_dc[0][2]; + sl->scaling_list_dc[1][4] = sl->scaling_list_dc[0][4]; + sl->scaling_list_dc[1][5] = sl->scaling_list_dc[0][5]; + } + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +RK_S32 h265d_nal_sps(BitReadCtx_t *bit, H265dSps *sps, const H265dVps *vps_list[]) +{ + RK_U32 sps_id = 0; + RK_S32 log2_diff_max_min_transform_block_size; + RK_U32 bit_depth_chroma; + RK_S32 start; + RK_S32 sublayer_ordering_info; + RK_S32 value = 0; + RK_S32 ret = 0; + RK_S32 i; + + h265d_dbg_func("Parsing sps data\n"); + + READ_BITS(bit, 4, &sps->vps_id); + h265d_dbg_sps("sps: vps_id %d", sps->vps_id); + if (sps->vps_id >= MAX_VPS_COUNT) { + mpp_loge("sps: invalid vps_id %d over MAX_VPS_COUNT\n", sps->vps_id); + ret = MPP_ERR_STREAM; + goto err; + } + + if (!vps_list[sps->vps_id]) { + mpp_loge("sps: vps_id %d missing in list\n", sps->vps_id); + } + + READ_BITS(bit, 3, &sps->max_sub_layers); + sps->max_sub_layers += 1; + + if (sps->max_sub_layers > MAX_SUB_LAYERS) { + mpp_loge("sps: max_sub_layers %d over limit %d\n", + sps->max_sub_layers, MAX_SUB_LAYERS); + ret = MPP_ERR_STREAM; + goto err; + } + + SKIP_BITS(bit, 1); + + h265d_layer_info(bit, sps->layers, sps->max_sub_layers); + + READ_UE(bit, &sps_id); + sps->sps_id = sps_id; + h265d_dbg_sps("sps: sps_id %d", sps->sps_id); + if (sps_id >= MAX_SPS_COUNT) { + mpp_loge("sps: sps_id %d over MAX_SPS_COUNT\n", sps_id); + ret = MPP_ERR_STREAM; + goto err; + } + + READ_UE(bit, &sps->chroma_format_idc); + h265d_dbg_sps("sps: chroma_format_idc %d", sps->chroma_format_idc); + + if (sps->chroma_format_idc == H265_CHROMA_444) + READ_ONEBIT(bit, &sps->separate_colour_plane_flag); + + READ_UE(bit, &sps->width); + h265d_dbg_sps("sps: width %d", sps->width); + READ_UE(bit, &sps->height); + h265d_dbg_sps("sps: height %d", sps->height); + + READ_ONEBIT(bit, &value); + + if (value) { + READ_UE(bit, &sps->conf_win.left_offset); + READ_UE(bit, &sps->conf_win.right_offset); + READ_UE(bit, &sps->conf_win.top_offset); + READ_UE(bit, &sps->conf_win.bottom_offset); + if (sps->chroma_format_idc == H265_CHROMA_420) { + sps->conf_win.left_offset *= 2; + sps->conf_win.right_offset *= 2; + sps->conf_win.top_offset *= 2; + sps->conf_win.bottom_offset *= 2; + } else if (sps->chroma_format_idc == H265_CHROMA_422) { + sps->conf_win.left_offset *= 2; + sps->conf_win.right_offset *= 2; + } + } + + READ_UE(bit, &sps->bit_depth); + + sps->bit_depth = sps->bit_depth + 8; + h265d_dbg_sps("sps: bit_depth %d", sps->bit_depth); + READ_UE(bit, &bit_depth_chroma); + bit_depth_chroma = bit_depth_chroma + 8; + if (bit_depth_chroma != sps->bit_depth) { + mpp_loge("sps: bit depth luma %d chroma %d mismatch\n", + sps->bit_depth, bit_depth_chroma); + ret = MPP_ERR_STREAM; + goto err; + } + + switch (sps->chroma_format_idc) { + case H265_CHROMA_400 : { + sps->pix_fmt = MPP_FMT_YUV400; + } break; + case H265_CHROMA_420 : { + switch (sps->bit_depth) { + case 8: sps->pix_fmt = MPP_FMT_YUV420SP; break; + case 10: sps->pix_fmt = MPP_FMT_YUV420SP_10BIT; break; + default: + mpp_loge("sps: unsupported bit depth %d\n", sps->bit_depth); + ret = MPP_ERR_PROTOL; + goto err; + } + } break; + case H265_CHROMA_422 : { + switch (sps->bit_depth) { + case 8: sps->pix_fmt = MPP_FMT_YUV422SP; break; + case 10: sps->pix_fmt = MPP_FMT_YUV422SP_10BIT; break; + default: + mpp_loge("sps: unsupported bit depth %d\n", sps->bit_depth); + ret = MPP_ERR_PROTOL; + goto err; + } + } break; + case H265_CHROMA_444 : { + switch (sps->bit_depth) { + case 8: sps->pix_fmt = MPP_FMT_YUV444SP; break; + case 10: sps->pix_fmt = MPP_FMT_YUV444SP_10BIT; break; + default: + mpp_loge("sps: unsupported bit depth %d\n", sps->bit_depth); + ret = MPP_ERR_PROTOL; + goto err; + } + } break; + } + + READ_UE(bit, &sps->log2_max_poc_lsb); + sps->log2_max_poc_lsb += 4; + if (sps->log2_max_poc_lsb > 16) { + mpp_loge("sps: log2_max_pic_order_cnt_lsb_minus4 out range: %d\n", + sps->log2_max_poc_lsb - 4); + ret = MPP_ERR_STREAM; + goto err; + } + + READ_ONEBIT(bit, &sublayer_ordering_info); + start = (sublayer_ordering_info != 0) ? 0 : sps->max_sub_layers - 1; + for (i = start; i < sps->max_sub_layers; i++) { + READ_UE(bit, &sps->layers[i].max_dec_pic_buffering) ; + sps->layers[i].max_dec_pic_buffering += 1; + READ_UE(bit, &sps->layers[i].num_reorder_pics); + READ_UE(bit, &sps->layers[i].max_latency_increase ); + sps->layers[i].max_latency_increase -= 1; + if (sps->layers[i].max_dec_pic_buffering > MAX_DPB_SIZE) { + mpp_loge("sps: dpb size %d over max %d\n", + sps->layers[i].max_dec_pic_buffering, MAX_DPB_SIZE); + ret = MPP_ERR_STREAM; + goto err; + } + if (sps->layers[i].num_reorder_pics > sps->layers[i].max_dec_pic_buffering - 1) { + mpp_loge("sps: reorder pics %d over dpb limit %d\n", + sps->layers[i].num_reorder_pics, sps->layers[i].max_dec_pic_buffering - 1); + if (sps->layers[i].num_reorder_pics > MAX_DPB_SIZE - 1) { + ret = MPP_ERR_STREAM; + goto err; + } + sps->layers[i].max_dec_pic_buffering = sps->layers[i].num_reorder_pics + 1; + } + } + + if (!sublayer_ordering_info) { + for (i = 0; i < start; i++) { + sps->layers[i].max_dec_pic_buffering = sps->layers[start].max_dec_pic_buffering; + sps->layers[i].num_reorder_pics = sps->layers[start].num_reorder_pics; + sps->layers[i].max_latency_increase = sps->layers[start].max_latency_increase; + } + } + + if (!sps->layers[0].ptl_info.progressive_source_flag && + sps->layers[0].ptl_info.interlaced_source_flag) { + for (i = 0; i < sps->max_sub_layers; i++) { + sps->layers[i].num_reorder_pics += 2; + } + } + + READ_UE(bit, &sps->log2_min_cb_size) ; + if (sps->log2_min_cb_size > (LOG2_MAX_CU_SIZE - 3)) { + mpp_loge("sps: log2_min_cb_size over LOG2_MAX_CU_SIZE\n"); + ret = MPP_ERR_STREAM; + goto err; + } + sps->log2_min_cb_size += 3; + + h265d_dbg_sps("sps: log2_min_cb_size %d", sps->log2_min_cb_size); + READ_UE(bit, &sps->log2_diff_max_min_coding_block_size); + if (sps->log2_diff_max_min_coding_block_size > (LOG2_MAX_CU_SIZE - LOG2_MIN_CU_SIZE)) { + mpp_loge("sps: log2_diff_max_min_coding_block_size over limit\n"); + ret = MPP_ERR_STREAM; + goto err; + } + + h265d_dbg_sps("sps: log2_diff_max_min_coding_block_size %d", + sps->log2_diff_max_min_coding_block_size); + READ_UE(bit, &sps->log2_min_tb_size); + if (sps->log2_min_tb_size > (LOG2_MAX_TU_SIZE - 2)) { + mpp_loge("sps: log2_min_tb_size over LOG2_MAX_TU_SIZE\n"); + ret = MPP_ERR_STREAM; + goto err; + } + sps->log2_min_tb_size += 2; + + h265d_dbg_sps("sps: log2_min_tb_size %d", sps->log2_min_tb_size); + READ_UE(bit, &log2_diff_max_min_transform_block_size); + if (log2_diff_max_min_transform_block_size > (LOG2_MAX_TU_SIZE - LOG2_MIN_TU_SIZE)) { + mpp_loge("sps: log2_diff_max_min_transform_block_size over limit\n"); + ret = MPP_ERR_STREAM; + goto err; + } + + h265d_dbg_sps("sps: log2_diff_max_min_transform_block_size %d", + log2_diff_max_min_transform_block_size); + sps->log2_max_trafo_size = log2_diff_max_min_transform_block_size + + sps->log2_min_tb_size; + + h265d_dbg_sps("sps: log2_max_trafo_size %d", sps->log2_max_trafo_size); + + if (sps->log2_min_tb_size >= sps->log2_min_cb_size) { + mpp_loge("sps: log2_min_tb_size over LOG2_MAX_TU_SIZE\n"); + ret = MPP_ERR_STREAM; + goto err; + } + + READ_UE(bit, &sps->max_transform_hierarchy_depth_inter); + READ_UE(bit, &sps->max_transform_hierarchy_depth_intra); + + READ_ONEBIT(bit, &sps->scaling_list_enable_flag ); + + if (sps->scaling_list_enable_flag) { + value = 0; + h265d_set_default_scaling_list(&sps->scaling_list); + READ_ONEBIT(bit, &value); + if (value) { + ret = h265d_scaling_list_data(bit, &sps->scaling_list, sps); + if (ret < 0) + goto err; + } + } + + READ_ONEBIT(bit, &sps->amp_enabled_flag); + READ_ONEBIT(bit, &sps->sao_enabled); + READ_ONEBIT(bit, &sps->pcm_enabled_flag); + + h265d_dbg_sps("sps: amp_enabled_flag %d", sps->amp_enabled_flag); + h265d_dbg_sps("sps: sao_enabled %d", sps->sao_enabled); + h265d_dbg_sps("sps: pcm_enabled_flag %d", sps->pcm_enabled_flag); + + if (sps->pcm_enabled_flag) { + READ_BITS(bit, 4, &sps->pcm.bit_depth); + sps->pcm.bit_depth += 1; + READ_BITS(bit, 4, &sps->pcm.bit_depth_chroma); + sps->pcm.bit_depth_chroma += 1; + READ_UE(bit, &sps->pcm.log2_min_pcm_cb_size ); + sps->pcm.log2_min_pcm_cb_size += 3; + READ_UE(bit, &value); + sps->pcm.log2_max_pcm_cb_size = sps->pcm.log2_min_pcm_cb_size + value; + + if (sps->pcm.bit_depth > sps->bit_depth) { + mpp_loge("PCM bit depth %d over normal bit depth %d\n", + sps->pcm.bit_depth, sps->bit_depth); + ret = MPP_ERR_STREAM; + goto err; + } + READ_ONEBIT(bit, &sps->pcm.loop_filter_disable_flag); + } + + READ_UE(bit, &sps->nb_st_rps); + h265d_dbg_sps("sps: nb_st_rps %d", sps->nb_st_rps); + if (sps->nb_st_rps > MAX_SHORT_TERM_RPS_COUNT) { + mpp_loge("sps: short term rps count %d over MAX_SHORT_TERM_RPS_COUNT\n", + sps->nb_st_rps); + ret = MPP_ERR_STREAM; + goto err; + } + for (i = 0; i < (RK_S32)sps->nb_st_rps; i++) { + if ((ret = h265d_st_rps(bit, &sps->st_rps_sps[i], + sps, 0, NULL)) < 0) + goto err; + } + + READ_ONEBIT(bit, &sps->lt_rps_sps.valid); + if (sps->lt_rps_sps.valid) { + RK_U8 used_tmp = 0; + + READ_UE(bit, &sps->lt_rps_sps.num_refs); + sps->lt_rps_sps.used_flag = 0; + for (i = 0; i < (RK_S32)sps->lt_rps_sps.num_refs; i++) { + READ_BITS(bit, sps->log2_max_poc_lsb, &sps->lt_rps_sps.poc_lsb[i]); + READ_ONEBIT(bit, &used_tmp); + MPP_MOD_BIT(sps->lt_rps_sps.used_flag, i, used_tmp); + } + } + + READ_ONEBIT(bit, &sps->sps_temporal_mvp_enabled_flag); + READ_ONEBIT(bit, &sps->sps_strong_intra_smoothing_enable_flag); + + h265d_vui_init(&sps->vui); + READ_ONEBIT(bit, &sps->vui.vui_present); + if (sps->vui.vui_present) { + ret = h265d_vui(bit, sps); + if (ret < 0) + goto err; + } + + sps->output_window = sps->conf_win; + if (sps->vui.default_display_window_flag) { + sps->output_window.left_offset += sps->vui.def_disp_win.left_offset; + sps->output_window.right_offset += sps->vui.def_disp_win.right_offset; + sps->output_window.top_offset += sps->vui.def_disp_win.top_offset; + sps->output_window.bottom_offset += sps->vui.def_disp_win.bottom_offset; + } + + READ_ONEBIT(bit, &sps->sps_extension_flag); + if (sps->sps_extension_flag) { + READ_ONEBIT(bit, &sps->sps_range_extension_flag); + SKIP_BITS(bit, 7); + if (sps->sps_range_extension_flag) { + READ_ONEBIT(bit, &sps->transform_skip_rotation_enabled_flag); + READ_ONEBIT(bit, &sps->transform_skip_context_enabled_flag); + READ_ONEBIT(bit, &sps->implicit_rdpcm_enabled_flag); + READ_ONEBIT(bit, &sps->explicit_rdpcm_enabled_flag); + + READ_ONEBIT(bit, &sps->extended_precision_processing_flag); + if (sps->extended_precision_processing_flag) + mpp_log("sps: extended precision not implemented\n"); + + READ_ONEBIT(bit, &sps->intra_smoothing_disabled_flag); + READ_ONEBIT(bit, &sps->high_precision_offsets_enabled_flag); + if (sps->high_precision_offsets_enabled_flag) + mpp_log("sps: high precision offsets not implemented\n"); + + READ_ONEBIT(bit, &sps->persistent_rice_adaptation_enabled_flag); + + READ_ONEBIT(bit, &sps->cabac_bypass_alignment_enabled_flag); + if (sps->cabac_bypass_alignment_enabled_flag) + mpp_log("sps: cabac bypass alignment not implemented\n"); + } + } + + sps->output_width = sps->width - + (sps->output_window.left_offset + sps->output_window.right_offset); + sps->output_height = sps->height - + (sps->output_window.top_offset + sps->output_window.bottom_offset); + h265d_dbg_sps("sps: output_width %d", sps->output_width); + h265d_dbg_sps("sps: output_height %d", sps->output_height); + if (sps->output_width <= 0 || sps->output_height <= 0) { + mpp_log("sps: invalid visible frame dimensions %dx%d\n", + sps->output_width, sps->output_height); + sps->conf_win.left_offset = 0; + sps->conf_win.right_offset = 0; + sps->conf_win.top_offset = 0; + sps->conf_win.bottom_offset = 0; + sps->output_window.left_offset = 0; + sps->output_window.right_offset = 0; + sps->output_window.top_offset = 0; + sps->output_window.bottom_offset = 0; + sps->output_width = sps->width; + sps->output_height = sps->height; + } + + sps->log2_ctb_size = sps->log2_min_cb_size + sps->log2_diff_max_min_coding_block_size; + h265d_dbg_sps("sps: log2_ctb_size %d", sps->log2_ctb_size); + + sps->ctb_width = (sps->width + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; + h265d_dbg_sps("sps: ctb_width %d", sps->ctb_width); + sps->ctb_height = (sps->height + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; + h265d_dbg_sps("sps: ctb_height %d", sps->ctb_height); + + sps->min_cb_width = sps->width >> sps->log2_min_cb_size; + sps->min_cb_height = sps->height >> sps->log2_min_cb_size; + + sps->qp_bd_offset = 6 * (sps->bit_depth - 8); + + if (sps->width & ((1 << sps->log2_min_cb_size) - 1) || + sps->height & ((1 << sps->log2_min_cb_size) - 1)) { + mpp_loge("sps: invalid frame dimensions\n"); + goto err; + } + + if (sps->log2_ctb_size > MAX_LOG2_CTB_SIZE) { + mpp_loge("sps: ctb size invalid 2^%d\n", sps->log2_ctb_size); + goto err; + } + if (sps->max_transform_hierarchy_depth_inter > + (RK_S32)(sps->log2_ctb_size - sps->log2_min_tb_size)) { + mpp_loge("transform_hierarchy_depth_inter %d over limit\n", + sps->max_transform_hierarchy_depth_inter); + goto err; + } + if (sps->max_transform_hierarchy_depth_intra > + (RK_S32)(sps->log2_ctb_size - sps->log2_min_tb_size)) { + mpp_loge("sps: transform_hierarchy_depth_intra %d over limit\n", + sps->max_transform_hierarchy_depth_intra); + goto err; + } + if (sps->log2_max_trafo_size > (RK_U32)MPP_MIN(sps->log2_ctb_size, 5)) { + mpp_loge("sps: log2_max_trafo_size %d over limit\n", + sps->log2_max_trafo_size); + goto err; + } + + return 0; +__BITREAD_ERR: + ret = MPP_ERR_STREAM; +err: + return ret; +} diff --git a/mpp/codec/dec/h265/h265d_sps.h b/mpp/codec/dec/h265/h265d_sps.h new file mode 100644 index 000000000..ff40d9e16 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_sps.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_SPS_H +#define H265D_SPS_H + +#include "h265d_syntax.h" +#include "h265d_vps.h" + +typedef enum ScaleSizeId_e { + SCALE_4X4_COPY = 0, + SCALE_4X4, + SCALE_8X8, + SCALE_16X16 +} ScaleSizeId; + +typedef struct H265dCrop_t { + RK_S32 left_offset; + RK_S32 right_offset; + RK_S32 top_offset; + RK_S32 bottom_offset; +} H265dCrop; + +typedef struct H265dScalingList_t { + RK_U8 scaling_lists[4][6][64]; + RK_U8 scaling_list_dc[2][6]; +} H265dScalingList; + +typedef struct H265dVui_t { + RK_S32 vui_present; + + RK_S32 sar_num; + RK_S32 sar_den; + + RK_S32 overscan_info_present_flag; + RK_S32 overscan_appropriate_flag; + + RK_S32 video_signal_type_present_flag; + RK_S32 video_format; + RK_S32 video_full_range_flag; + RK_S32 colour_description_present_flag; + RK_U32 colour_primaries; + RK_U32 transfer_characteristic; + RK_U32 matrix_coeffs; + + RK_S32 chroma_loc_info_present_flag; + RK_S32 chroma_sample_loc_type_top_field; + RK_S32 chroma_sample_loc_type_bottom_field; + RK_S32 neutra_chroma_indication_flag; + + RK_S32 field_seq_flag; + RK_S32 frame_field_info_present_flag; + + RK_S32 default_display_window_flag; + H265dCrop def_disp_win; + + RK_S32 vui_timing_info_present_flag; + RK_U32 vui_num_units_in_tick; + RK_U32 vui_time_scale; + RK_S32 vui_poc_proportional_to_timing_flag; + RK_S32 vui_num_ticks_poc_diff_one_minus1; + RK_S32 vui_hrd_parameters_present_flag; + + RK_S32 bitstream_restriction_flag; + RK_S32 tiles_fixed_structure_flag; + RK_S32 motion_vectors_over_pic_boundaries_flag; + RK_S32 restricted_ref_pic_lists_flag; + RK_S32 min_spatial_segmentation_idc; + RK_S32 max_bytes_per_pic_denom; + RK_S32 max_bits_per_min_cu_denom; + RK_S32 log2_max_mv_length_horizontal; + RK_S32 log2_max_mv_length_vertical; +} H265dVui; + +typedef struct H265dSps_t { + RK_U32 vps_id; + RK_U32 sps_id; + RK_S32 max_sub_layers; + LayerInfo layers[MAX_SUB_LAYERS]; + + RK_S32 chroma_format_idc; + RK_U32 separate_colour_plane_flag; + + RK_S32 width; + RK_S32 height; + + H265dCrop conf_win; + + RK_U32 bit_depth; + RK_U32 log2_max_poc_lsb; + RK_U32 log2_min_cb_size; + RK_U32 log2_diff_max_min_coding_block_size; + RK_U32 log2_min_tb_size; + RK_U32 log2_max_trafo_size; + + RK_S32 max_transform_hierarchy_depth_inter; + RK_S32 max_transform_hierarchy_depth_intra; + + RK_U32 scaling_list_enable_flag; + H265dScalingList scaling_list; + + RK_U32 amp_enabled_flag; + RK_U32 sao_enabled; + + RK_S32 pcm_enabled_flag; + + struct { + RK_U32 bit_depth; + RK_U32 bit_depth_chroma; + RK_U32 log2_min_pcm_cb_size; + RK_U32 log2_max_pcm_cb_size; + RK_U32 loop_filter_disable_flag; + } pcm; + + RK_U32 nb_st_rps; + H265dStRps st_rps_sps[MAX_SHORT_TERM_RPS_COUNT]; + H265dLtRpsSps lt_rps_sps; + + RK_U8 sps_temporal_mvp_enabled_flag; + RK_U8 sps_strong_intra_smoothing_enable_flag; + + H265dVui vui; + + RK_S32 sps_extension_flag; + RK_S32 sps_range_extension_flag; + RK_S32 transform_skip_rotation_enabled_flag; + RK_S32 transform_skip_context_enabled_flag; + RK_S32 implicit_rdpcm_enabled_flag; + RK_S32 explicit_rdpcm_enabled_flag; + RK_S32 extended_precision_processing_flag; + RK_S32 intra_smoothing_disabled_flag; + RK_S32 high_precision_offsets_enabled_flag; + RK_S32 persistent_rice_adaptation_enabled_flag; + RK_S32 cabac_bypass_alignment_enabled_flag; + + RK_S32 pix_fmt; + RK_S32 output_width; + RK_S32 output_height; + H265dCrop output_window; + RK_S32 log2_ctb_size; + RK_S32 ctb_width; + RK_S32 ctb_height; + RK_S32 min_cb_width; + RK_S32 min_cb_height; + RK_S32 qp_bd_offset; +} H265dSps; + +#ifdef __cplusplus +extern "C" { +#endif + +void h265d_set_default_scaling_list(H265dScalingList *sl); +RK_S32 h265d_scaling_list_data(BitReadCtx_t *bit, H265dScalingList *sl, H265dSps *sps); +RK_S32 h265d_st_rps(BitReadCtx_t *bit, H265dStRps *rps, const H265dSps *sps, + RK_S32 is_slice_header, RK_U8 *rps_need_update); +RK_S32 h265d_nal_sps(BitReadCtx_t *bit, H265dSps *sps, const H265dVps *vps_list[]); + +#ifdef __cplusplus +} +#endif + +#endif /* H265D_SPS_H */ diff --git a/mpp/codec/dec/h265/h265d_syntax.c b/mpp/codec/dec/h265/h265d_syntax.c new file mode 100644 index 000000000..06f093d07 --- /dev/null +++ b/mpp/codec/dec/h265/h265d_syntax.c @@ -0,0 +1,463 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "h265d" + +#include "mpp_debug.h" +#include "mpp_bit.h" + +#include "h265d_ctx.h" +#include "h265d_pps.h" +#include "h265d_syntax.h" + +static void fill_picture_entry(DXVA_PicEntry_HEVC *pic, RK_U32 index, RK_U32 flag) +{ + mpp_assert((index & 0x7f) == index && (flag & 0x01) == flag); + pic->bPicEntry = index | (flag << 7); +} + +static RK_S32 get_refpic_index(const DXVA_PicParams_HEVC *pp, RK_S32 surface_index) +{ + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefPicList); i++) { + if ((pp->RefPicList[i].bPicEntry & 0x7f) == surface_index) { + return i; + } + } + return 0xff; +} + +static void fill_ref_pic_set(const DXVA_PicParams_HEVC *pp, + const H265dPrs *p, + RK_U32 rps_idx, + RK_U8 *target_array) +{ + const H265dRefList *src = &p->rps[rps_idx]; + RK_U32 write_pos = 0; + RK_U32 read_pos = 0; + + for (write_pos = 0; write_pos < 15; write_pos++) { + RK_S32 idx = 0xff; + while (read_pos < (RK_U32)src->nb_refs && idx == 0xff) { + H265dFrame *frm = src->ref[read_pos++]; + if (frm && frm->slot_index != 0xff) + idx = get_refpic_index(pp, frm->slot_index); + } + target_array[write_pos] = idx; + } +} + +static void fill_picture_parameters(const H265dPrs *p, DXVA_PicParams_HEVC *pp) +{ + const H265dFrame *current_picture = p->ref; + const H265dPps *pps = (H265dPps *)p->pps_list[p->slice.pps_id]; + const H265dSps *sps = (H265dSps *)p->sps_list[pps->sps_id]; + const H265dStRps *src_rps = sps->st_rps_sps; + Short_SPS_RPS_HEVC *dst_rps = pp->sps_st_rps; + const H265dStRps *cur_src_rps = p->slice.st_rps_using; + Short_SPS_RPS_HEVC *cur_dst_rps = &pp->cur_st_rps; + RK_U32 rps_used[16]; + RK_U32 nb_rps_used; + RK_U32 i, j; + + memset(pp, 0, sizeof(*pp)); + + pp->PicWidthInMinCbsY = sps->min_cb_width; + pp->PicHeightInMinCbsY = sps->min_cb_height; + pp->pps_id = p->slice.pps_id; + pp->sps_id = pps->sps_id; + pp->vps_id = sps->vps_id; + + pp->wFormatAndSequenceInfoFlags = (sps->chroma_format_idc << 0) | + (sps->separate_colour_plane_flag << 2) | + ((sps->bit_depth - 8) << 3) | + ((sps->bit_depth - 8) << 6) | + ((sps->log2_max_poc_lsb - 4) << 9) | + (0 << 13) | + (0 << 14) | + (0 << 15); + + fill_picture_entry(&pp->CurrPic, current_picture->slot_index, 0); + + pp->sps_max_dec_pic_buffering_minus1 = sps->layers[sps->max_sub_layers - 1].max_dec_pic_buffering - 1; + pp->log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3; + pp->log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size; + pp->log2_min_transform_block_size_minus2 = sps->log2_min_tb_size - 2; + pp->log2_diff_max_min_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size; + pp->max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter; + pp->max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra; + pp->num_short_term_ref_pic_sets = sps->nb_st_rps; + pp->num_long_term_ref_pics_sps = sps->lt_rps_sps.num_refs; + + pp->num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1; + pp->num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1; + pp->init_qp_minus26 = pps->pic_init_qp_minus26; + + if (p->slice.short_term_ref_pic_set_sps_flag == 0 && p->slice.st_rps_using) { + pp->ucNumDeltaPocsOfRefRpsIdx = p->slice.st_rps_using->ref_delta_cnt; + pp->wNumBitsForShortTermRPSInSlice = p->slice.short_term_ref_pic_set_size; + } + + RK_U32 tool_flags = 0; + RK_U32 pcm_flags = 0; + RK_U32 rps_flags = 0; + + // SPS tool flags + tool_flags |= (sps->scaling_list_enable_flag & 1) << 0; + tool_flags |= (sps->amp_enabled_flag & 1) << 1; + tool_flags |= (sps->sao_enabled & 1) << 2; + tool_flags |= (sps->pcm_enabled_flag & 1) << 3; + + // PCM specific flags + if (sps->pcm_enabled_flag) { + pcm_flags |= ((sps->pcm.bit_depth - 1) & 0x0F) << 4; + pcm_flags |= ((sps->pcm.bit_depth_chroma - 1) & 0x0F) << 8; + pcm_flags |= ((sps->pcm.log2_min_pcm_cb_size - 3) & 0x03) << 12; + pcm_flags |= ((sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size) & 0x03) << 14; + } + + // RPS flags + rps_flags |= (sps->pcm.loop_filter_disable_flag & 1) << 16; + rps_flags |= (sps->lt_rps_sps.valid & 1) << 17; + rps_flags |= (sps->sps_temporal_mvp_enabled_flag & 1) << 18; + rps_flags |= (sps->sps_strong_intra_smoothing_enable_flag & 1) << 19; + + // PPS flags + tool_flags |= (pps->dependent_slice_segments_enabled_flag & 1) << 20; + tool_flags |= (pps->output_flag_present_flag & 1) << 21; + tool_flags |= ((pps->num_extra_slice_header_bits & 0x07) << 22); + tool_flags |= (pps->sign_data_hiding_flag & 1) << 25; + tool_flags |= (pps->cabac_init_present_flag & 1) << 26; + + pp->dwCodingParamToolFlags = tool_flags | pcm_flags | rps_flags; + + pp->dwCodingSettingPicturePropertyFlags = (pps->constrained_intra_pred_flag << 0) | + (pps->transform_skip_enabled_flag << 1) | + (pps->cu_qp_delta_enabled_flag << 2) | + (pps->pic_slice_level_chroma_qp_offsets_present_flag << 3) | + (pps->weighted_pred_flag << 4) | + (pps->weighted_bipred_flag << 5) | + (pps->transquant_bypass_enable_flag << 6) | + (pps->tiles_enabled_flag << 7) | + (pps->entropy_coding_sync_enabled_flag << 8) | + (pps->uniform_spacing_flag << 9) | + (pps->loop_filter_across_tiles_enabled_flag << 10) | + (pps->seq_loop_filter_across_slices_enabled_flag << 11) | + (pps->deblocking_filter_override_enabled_flag << 12) | + (pps->disable_dbf << 13) | + (pps->lists_modification_present_flag << 14) | + (pps->slice_header_extension_present_flag << 15) | + (0 << 19); + + pp->IdrPicFlag = (p->first_nal_type == 19 || p->first_nal_type == 20); + pp->IrapPicFlag = (p->first_nal_type >= 16 && p->first_nal_type <= 23); + pp->IntraPicFlag = (p->first_nal_type >= 16 && p->first_nal_type <= 23) || p->slice.slice_type == I_SLICE; + pp->pps_cb_qp_offset = pps->cb_qp_offset; + pp->pps_cr_qp_offset = pps->cr_qp_offset; + if (pps->tiles_enabled_flag) { + const RK_U32 *column_width = H265D_PPS_COLUMN_WIDTH(pps); + const RK_U32 *row_height = H265D_PPS_ROW_HEIGHT(pps); + + pp->num_tile_columns_minus1 = pps->num_tile_columns - 1; + pp->num_tile_rows_minus1 = pps->num_tile_rows - 1; + + if (!pps->uniform_spacing_flag) { + for (i = 0; i < (RK_U32)pps->num_tile_columns; i++) + pp->column_width_minus1[i] = column_width[i] - 1; + + for (i = 0; i < (RK_U32)pps->num_tile_rows; i++) + pp->row_height_minus1[i] = row_height[i] - 1; + } + } + + pp->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth; + pp->pps_beta_offset_div2 = pps->beta_offset / 2; + pp->pps_tc_offset_div2 = pps->tc_offset / 2; + pp->log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2; + pp->slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag; + pp->CurrPicOrderCntVal = p->poc; + pp->ps_update_flag = p->ps_need_upate; + pp->rps_update_flag = p->rps_need_upate || p->ps_need_upate; + + if (pp->rps_update_flag) { + for (i = 0; i < 32; i++) { + pp->sps_lt_rps[i].lt_ref_pic_poc_lsb = sps->lt_rps_sps.poc_lsb[i]; + pp->sps_lt_rps[i].used_by_curr_pic_lt_flag = MPP_GET_BIT(sps->lt_rps_sps.used_flag, i); + } + + if (cur_src_rps) { + RK_U32 n_pics = p->slice.st_rps_using->num_neg; + cur_dst_rps->num_negative_pics = n_pics; + cur_dst_rps->num_positive_pics = cur_src_rps->num_deltas - n_pics; + for (i = 0; i < cur_dst_rps->num_negative_pics; i++) { + cur_dst_rps->delta_poc_s0[i] = cur_src_rps->poc_delta[i]; + cur_dst_rps->s0_used_flag[i] = MPP_GET_BIT(cur_src_rps->flags, i); + } + for (i = 0; i < cur_dst_rps->num_positive_pics; i++) { + cur_dst_rps->delta_poc_s1[i] = cur_src_rps->poc_delta[i + n_pics]; + cur_dst_rps->s1_used_flag[i] = MPP_GET_BIT(cur_src_rps->flags, i + n_pics); + } + } + + for (i = 0; i < 64; i++) { + if (i < sps->nb_st_rps) { + + RK_U32 n_pics = src_rps[i].num_neg; + dst_rps[i].num_negative_pics = n_pics; + dst_rps[i].num_positive_pics = src_rps[i].num_deltas - n_pics; + for (j = 0; j < dst_rps[i].num_negative_pics; j++) { + dst_rps[i].delta_poc_s0[j] = src_rps[i].poc_delta[j]; + dst_rps[i].s0_used_flag[j] = MPP_GET_BIT(src_rps[i].flags, j); + } + + for ( j = 0; j < dst_rps[i].num_positive_pics; j++) { + dst_rps[i].delta_poc_s1[j] = src_rps[i].poc_delta[j + n_pics]; + dst_rps[i].s1_used_flag[j] = MPP_GET_BIT(src_rps[i].flags, j + n_pics); + } + } + } + } + + nb_rps_used = 0; + for (i = 0; i < NB_RPS_TYPE; i++) { + for (j = 0; j < (RK_U32)p->rps[i].nb_refs; j++) { + if ((i == ST_FOLL) || (i == LT_FOLL)) { + ; + } else { + rps_used[nb_rps_used++] = p->rps[i].list[j]; + } + } + } + pp->current_poc = current_picture->poc; + + // First pass: collect valid reference frames + RK_U32 ref_idx = 0; + for (RK_U32 dpb_idx = 0; dpb_idx < MPP_ARRAY_ELEMS(p->dpb) && ref_idx < 15; dpb_idx++) { + const H265dFrame *frm = &p->dpb[dpb_idx]; + if (frm == current_picture || frm->slot_index == 0xff) + continue; + if (!frm->ref_status.st_ref && !frm->ref_status.lt_ref) + continue; + + // Check if this frame is in rps_used + RK_BOOL is_used = RK_FALSE; + for (RK_U32 k = 0; k < nb_rps_used; k++) { + if (rps_used[k] == (RK_U32)frm->poc) { + is_used = RK_TRUE; + break; + } + } + if (!is_used) + continue; + + RK_U32 long_term = frm->ref_status.lt_ref ? 1 : 0; + fill_picture_entry(&pp->RefPicList[ref_idx], frm->slot_index, long_term); + pp->PicOrderCntValList[ref_idx] = frm->poc; + mpp_buf_slot_set_flag(p->slots, frm->slot_index, SLOT_HAL_INPUT); + p->task->refer[ref_idx] = frm->slot_index; + ref_idx++; + } + + // Fill remaining slots with 0xff + while (ref_idx < MPP_ARRAY_ELEMS(pp->RefPicList)) { + pp->RefPicList[ref_idx].bPicEntry = 0xff; + pp->PicOrderCntValList[ref_idx] = 0; + p->task->refer[ref_idx] = -1; + ref_idx++; + } + + fill_ref_pic_set(pp, p, ST_CURR_BEF, pp->RefPicSetStCurrBefore); + fill_ref_pic_set(pp, p, ST_CURR_AFT, pp->RefPicSetStCurrAfter); + fill_ref_pic_set(pp, p, LT_CURR, pp->RefPicSetLtCurr); + + pp->sps_extension_flag = sps->sps_extension_flag;; + pp->sps_range_extension_flag = sps->sps_range_extension_flag;; + pp->transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag;; + pp->transform_skip_context_enabled_flag = sps->transform_skip_context_enabled_flag;; + pp->implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled_flag;; + pp->explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled_flag;; + pp->extended_precision_processing_flag = sps->extended_precision_processing_flag;; + pp->intra_smoothing_disabled_flag = sps->intra_smoothing_disabled_flag;; + pp->high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag;; + pp->persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled_flag;; + pp->cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled_flag;; + + pp->cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag; + pp->chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag; + + pp->log2_max_transform_skip_block_size = pps->log2_max_transform_skip_block_size; + pp->diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth; + pp->chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1; + for (i = 0; i < 6; i++) { + pp->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i]; + pp->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i]; + } +} +extern RK_U8 h265d_diag_scan4x4_map[16]; +extern RK_U8 h265d_diag_scan8x8_map[64]; + +static void fill_scaling_lists(const H265dPrs *p, DXVA_Qmatrix_HEVC *qm) +{ + const H265dPps *pps = (H265dPps *)p->pps_list[p->slice.pps_id]; + const H265dSps *sps = (H265dSps *)p->sps_list[pps->sps_id]; + const H265dScalingList *sl = (pps->scaling_list_data_present_flag != 0) ? + &pps->scaling_list : &sps->scaling_list; + RK_U32 i, j, pos; + + if (!sps->scaling_list_enable_flag) + return; + + memset(qm, 0, sizeof(DXVA_Qmatrix_HEVC)); + for (i = 0; i < 6; i++) { + for (j = 0; j < 16; j++) { + pos = h265d_diag_scan4x4_map[j]; + qm->ucScalingLists0[i][j] = sl->scaling_lists[SCALE_4X4_COPY][i][pos]; + } + + for (j = 0; j < 64; j++) { + pos = h265d_diag_scan8x8_map[j]; + qm->ucScalingLists1[i][j] = sl->scaling_lists[SCALE_4X4][i][pos]; + qm->ucScalingLists2[i][j] = sl->scaling_lists[SCALE_8X8][i][pos]; + + if (i < 2) + qm->ucScalingLists3[i][j] = sl->scaling_lists[SCALE_16X16][i * 3][pos]; + } + + qm->ucScalingListDCCoefSizeID2[i] = sl->scaling_list_dc[0][i]; + + if (i < 2) + qm->ucScalingListDCCoefSizeID3[i] = sl->scaling_list_dc[1][i * 3]; + } +} + +static void fill_slice_short(DXVA_Slice_HEVC_Short *slice, + RK_U32 position, RK_U32 size) +{ + memset(slice, 0, sizeof(*slice)); + slice->BSNALunitDataLocation = position; + slice->SliceBytesInBuffer = size; + slice->wBadSliceChopping = 0; +} + +static void init_slice_cut_param(DXVA_Slice_HEVC_Cut_Param *slice) +{ + memset(slice, 0, sizeof(*slice)); +} + +RK_S32 h265d_parser2_syntax(H265dCtx *ctx) +{ + const H265dPrs *p = (const H265dPrs *)ctx->parser; + h265d_dxva2_picture_context_t *ctx_pic = (h265d_dxva2_picture_context_t *)p->hal_pic_private; + + fill_picture_parameters(p, &ctx_pic->pp); + + fill_scaling_lists(p, &ctx_pic->qm); + + return 0; +} + +RK_S32 h265d_syntax_fill_slice(H265dCtx *ctx, RK_S32 input_index) +{ + const H265dPrs *p = (const H265dPrs *)ctx->parser; + h265d_dxva2_picture_context_t *ctx_pic = (h265d_dxva2_picture_context_t *)p->hal_pic_private; + MppBuffer streambuf = NULL; + RK_U8 *ptr = NULL; + RK_U8 *current = NULL; + RK_U32 position = 0; + RK_U32 size = 0; + RK_U32 length = 0; + RK_S32 count = 0; + RK_S32 i; + + if (-1 != input_index) { + mpp_buf_slot_get_prop(p->packet_slots, input_index, SLOT_BUFFER, &streambuf); + current = ptr = (RK_U8 *)mpp_buffer_get_ptr(streambuf); + if (current == NULL) + return MPP_ERR_NULL_PTR; + } else { + RK_S32 buff_size = 0; + + current = (RK_U8 *)mpp_packet_get_data(p->input_packet); + size = (RK_U32)mpp_packet_get_size(p->input_packet); + for (i = 0; i < p->nb_nals; i++) { + length += p->nals[i].size + 4; + } + length = MPP_ALIGN(length, 16) + 64; + if (length > size) { + mpp_free(current); + buff_size = MPP_ALIGN(length + 10 * 1024, 1024); + current = mpp_malloc(RK_U8, buff_size); + mpp_packet_set_data(p->input_packet, (void*)current); + mpp_packet_set_size(p->input_packet, buff_size); + } + } + + if (ctx_pic->max_slice_num < p->nb_nals) { + MPP_FREE(ctx_pic->slice_short); + + ctx_pic->slice_short = (DXVA_Slice_HEVC_Short *)mpp_malloc(DXVA_Slice_HEVC_Short, p->nb_nals); + if (!ctx_pic->slice_short) + return MPP_ERR_NOMEM; + + MPP_FREE(ctx_pic->slice_cut_param); + + ctx_pic->slice_cut_param = (DXVA_Slice_HEVC_Cut_Param *)mpp_malloc(DXVA_Slice_HEVC_Cut_Param, p->nb_nals); + if (!ctx_pic->slice_cut_param) + return MPP_ERR_NOMEM; + + ctx_pic->max_slice_num = p->nb_nals; + } + + for (i = 0; i < p->nb_nals; i++) { + static const RK_U8 start_code[] = {0, 0, 1 }; + static const RK_U32 start_code_size = sizeof(start_code); + BitReadCtx_t gb_cxt, *gb; + RK_S32 value; + RK_U32 nal_type; + RK_U8 *nal_data = p->bitstream + p->nals[i].bitstream_offset + 3; + + mpp_set_bitread_ctx(&gb_cxt, nal_data, p->nals[i].size); + mpp_set_bitread_pseudo_code_type(&gb_cxt, PSEUDO_CODE_H264_H265); + + gb = &gb_cxt; + + READ_ONEBIT(gb, &value); + + READ_BITS(gb, 6, &nal_type); + + if (nal_type >= 32) { + continue; + } + + memcpy(current, start_code, start_code_size); + current += start_code_size; + position += start_code_size; + + memcpy(current, nal_data, p->nals[i].size); + fill_slice_short(&ctx_pic->slice_short[count], position, p->nals[i].size); + init_slice_cut_param(&ctx_pic->slice_cut_param[count]); + current += p->nals[i].size; + position += p->nals[i].size; + count++; + } + + ctx_pic->slice_count = count; + ctx_pic->bitstream_size = position; + + if (-1 != input_index) { + ctx_pic->bitstream = (RK_U8*)ptr; + + mpp_buf_slot_set_flag(p->packet_slots, input_index, SLOT_CODEC_READY); + mpp_buf_slot_set_flag(p->packet_slots, input_index, SLOT_HAL_INPUT); + } else { + ctx_pic->bitstream = NULL; + mpp_packet_set_length(p->input_packet, position); + } + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} diff --git a/mpp/codec/dec/h265/h265d_vps.c b/mpp/codec/dec/h265/h265d_vps.c new file mode 100644 index 000000000..90be744de --- /dev/null +++ b/mpp/codec/dec/h265/h265d_vps.c @@ -0,0 +1,265 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "H265d" + +#include "mpp_mem.h" + +#include "h265d_debug.h" +#include "h265d_ctx.h" + +static RK_S32 h265d_ptl(BitReadCtx_t *bit, PTLInfo *info) +{ + RK_S32 i; + + READ_BITS(bit, 2, &info->profile_space); + READ_ONEBIT(bit, &info->tier_flag); + READ_BITS(bit, 5, &info->profile_idc); + + if (info->profile_idc == MPP_PROFILE_HEVC_MAIN) + h265d_dbg_global("Main profile\n"); + else if (info->profile_idc == MPP_PROFILE_HEVC_MAIN_10) + h265d_dbg_global("Main 10 profile\n"); + else if (info->profile_idc == MPP_PROFILE_HEVC_MAIN_STILL_PICTURE) + h265d_dbg_global("Main Still Picture profile\n"); + else if (info->profile_idc == MPP_PROFILE_HEVC_FORMAT_RANGE_EXTENDIONS) + h265d_dbg_global("Main 4:4:4 profile\n"); + else + mpp_log("Unknown profile: %d\n", info->profile_idc); + + for (i = 0; i < 32; i++) + READ_ONEBIT(bit, & info->profile_compatibility_flag[i]); + READ_ONEBIT(bit, &info->progressive_source_flag); + READ_ONEBIT(bit, &info->interlaced_source_flag); + READ_ONEBIT(bit, &info->non_packed_constraint_flag); + READ_ONEBIT(bit, &info->frame_only_constraint_flag); + + info->bit_depth_constraint = (info->profile_idc == MPP_PROFILE_HEVC_MAIN_10) ? 10 : 8; + info->chroma_format_constraint = H265_CHROMA_420; + info->intra_constraint_flag = 0; + info->lower_bitrate_constraint_flag = 1; + + SKIP_BITS(bit, 16); + SKIP_BITS(bit, 16); + SKIP_BITS(bit, 12); + + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +RK_S32 h265d_layer_info(BitReadCtx_t *bit, LayerInfo *layers, RK_S32 max_num_sub_layers) +{ + RK_U32 profile_present_flag[MAX_SUB_LAYERS - 1]; + RK_U32 level_present_flag[MAX_SUB_LAYERS - 1]; + RK_S32 i; + + h265d_ptl(bit, &layers[0].ptl_info); + READ_BITS(bit, 8, &layers[0].ptl_info.level_idc); + + for (i = 0; i < max_num_sub_layers - 1; i++) { + READ_ONEBIT(bit, &profile_present_flag[i]); + READ_ONEBIT(bit, &level_present_flag[i]); + } + if (max_num_sub_layers - 1 > 0) + SKIP_BITS(bit, (8 - (max_num_sub_layers - 1)) * 2); + for (i = 0; i < max_num_sub_layers - 1; i++) { + if (profile_present_flag[i]) + h265d_ptl(bit, &layers[i + 1].ptl_info); + if (level_present_flag[i]) + READ_BITS(bit, 8, &layers[i + 1].ptl_info.level_idc); + } + + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static RK_S32 h265d_sublayer_hrd(BitReadCtx_t *bit, RK_U32 nb_cpb, RK_S32 subpic_params_present) +{ + RK_U32 i, value; + + for (i = 0; i < nb_cpb; i++) { + READ_UE(bit, &value); + READ_UE(bit, &value); + + if (subpic_params_present) { + READ_UE(bit, &value); + READ_UE(bit, &value); + } + SKIP_BITS(bit, 1); + } + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +RK_S32 h265d_hrd_info(BitReadCtx_t *bit, RK_S32 common_inf_present, RK_S32 max_sublayers) +{ + RK_S32 nal_params_present = 0; + RK_S32 vcl_params_present = 0; + RK_S32 subpic_params_present = 0; + RK_S32 i; + + if (common_inf_present) { + READ_ONEBIT(bit, &nal_params_present); + READ_ONEBIT(bit, &vcl_params_present); + + if (nal_params_present || vcl_params_present) { + READ_ONEBIT(bit, &subpic_params_present); + + if (subpic_params_present) { + SKIP_BITS(bit, 8); + SKIP_BITS(bit, 5); + SKIP_BITS(bit, 1); + SKIP_BITS(bit, 5); + } + + SKIP_BITS(bit, 4); + SKIP_BITS(bit, 4); + + if (subpic_params_present) + SKIP_BITS(bit, 4); + + SKIP_BITS(bit, 5); + SKIP_BITS(bit, 5); + SKIP_BITS(bit, 5); + } + } + + for (i = 0; i < max_sublayers; i++) { + RK_S32 low_delay = 0; + RK_U32 nb_cpb = 1; + RK_S32 fixed_rate = 0; + RK_S32 value = 0; + + READ_ONEBIT(bit, &fixed_rate); + + if (!fixed_rate) + READ_ONEBIT(bit, &fixed_rate); + + if (fixed_rate) + READ_UE(bit, &value); + else + READ_ONEBIT(bit, &low_delay); + + if (!low_delay) { + READ_UE(bit, &nb_cpb); + nb_cpb = nb_cpb + 1; + } + + if (nal_params_present) + h265d_sublayer_hrd(bit, nb_cpb, subpic_params_present); + if (vcl_params_present) + h265d_sublayer_hrd(bit, nb_cpb, subpic_params_present); + } + return 0; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +RK_S32 h265d_nal_vps(BitReadCtx_t *gb, H265dVps *vps) +{ + RK_U32 vps_id = 0; + RK_S32 value = 0; + RK_S32 i; + RK_S32 j; + + h265d_dbg_func("Parsing vps data\n"); + + READ_BITS(gb, 4, &vps_id); + vps->vps_id = vps_id; + + h265d_dbg_vps("vps: vps_id %d", vps->vps_id); + + if (vps_id >= MAX_VPS_COUNT) { + mpp_loge("vps: vps_id %d over MAX_VPS_COUNT\n", vps_id); + goto err; + } + READ_BITS(gb, 2, &value); + if (value != 3) { + mpp_loge("vps: invalid reserved bits (expected 3)\n"); + goto err; + } + + READ_BITS(gb, 6, &vps->vps_max_layers); + vps->vps_max_layers = vps->vps_max_layers + 1; + + READ_BITS(gb, 3, &vps->vps_max_sub_layers); + vps->vps_max_sub_layers = vps->vps_max_sub_layers + 1; + + READ_ONEBIT(gb, & vps->vps_temporal_id_nesting_flag); + READ_BITS(gb, 16, &value); + + if (value != 0xffff) { + mpp_loge("vps: invalid reserved 16-bit field\n"); + goto err; + } + + if (vps->vps_max_sub_layers > MAX_SUB_LAYERS) { + mpp_loge("vps: invalid max_sub_layers %d, limit is MAX_SUB_LAYERS\n", + vps->vps_max_sub_layers); + goto err; + } + + h265d_layer_info(gb, vps->layers, vps->vps_max_sub_layers); + + READ_ONEBIT(gb, &vps->vps_sub_layer_ordering_info_present_flag); + + i = (vps->vps_sub_layer_ordering_info_present_flag != 0) ? 0 : vps->vps_max_sub_layers - 1; + for (; i < vps->vps_max_sub_layers; i++) { + LayerInfo *layer = &vps->layers[i]; + + READ_UE(gb, &layer->max_dec_pic_buffering); + layer->max_dec_pic_buffering = layer->max_dec_pic_buffering + 1; + READ_UE(gb, &layer->num_reorder_pics); + READ_UE(gb, &layer->max_latency_increase); + layer->max_latency_increase = layer->max_latency_increase - 1; + + if (layer->max_dec_pic_buffering > MAX_DPB_SIZE) { + mpp_loge("vps: dpb size %d over MAX_DPB_SIZE\n", + layer->max_dec_pic_buffering); + goto err; + } + if (layer->num_reorder_pics > layer->max_dec_pic_buffering - 1) { + mpp_loge("vps: reorder pics %d over DPB-1\n", + layer->num_reorder_pics); + goto err; + } + } + + READ_BITS(gb, 6, &vps->vps_max_layer_id); + READ_UE(gb, &vps->vps_num_layer_sets); + vps->vps_num_layer_sets += 1; + for (i = 1; i < vps->vps_num_layer_sets; i++) + for (j = 0; j <= vps->vps_max_layer_id; j++) + SKIP_BITS(gb, 1); + + READ_ONEBIT(gb, &vps->vps_timing_info_present_flag); + if (vps->vps_timing_info_present_flag) { + mpp_read_longbits(gb, 32, &vps->vps_num_units_in_tick); + mpp_read_longbits(gb, 32, &vps->vps_time_scale); + READ_ONEBIT(gb, &vps->vps_poc_proportional_to_timing_flag); + if (vps->vps_poc_proportional_to_timing_flag) { + READ_UE(gb, &vps->vps_num_ticks_poc_diff_one); + vps->vps_num_ticks_poc_diff_one += 1; + } + READ_UE(gb, &vps->vps_num_hrd_parameters); + for (i = 0; i < vps->vps_num_hrd_parameters; i++) { + RK_S32 common_inf_present = 1; + RK_S32 hrd_layer_set_idx = 0; + + READ_UE(gb, &hrd_layer_set_idx); + if (i) + READ_ONEBIT(gb, &common_inf_present); + h265d_hrd_info(gb, common_inf_present, vps->vps_max_sub_layers); + } + } + + return 0; +__BITREAD_ERR: +err: + return MPP_ERR_STREAM; +} diff --git a/mpp/codec/dec/h265/h265d_vps.h b/mpp/codec/dec/h265/h265d_vps.h new file mode 100644 index 000000000..75433985f --- /dev/null +++ b/mpp/codec/dec/h265/h265d_vps.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_VPS_H +#define H265D_VPS_H + +#include "mpp_bitread.h" +#include "h265_syntax.h" + +typedef struct PTLInfo_t { + RK_U32 profile_space; + RK_U32 tier_flag; + RK_U32 profile_idc; + RK_U32 profile_compatibility_flag[32]; + RK_U32 level_idc; + RK_U32 progressive_source_flag; + RK_U32 interlaced_source_flag; + RK_U32 non_packed_constraint_flag; + RK_U32 frame_only_constraint_flag; + RK_S32 bit_depth_constraint; + H265ChromaFmt chroma_format_constraint; + RK_U32 intra_constraint_flag; + RK_U32 one_picture_only_constraint_flag; + RK_U32 lower_bitrate_constraint_flag; +} PTLInfo; + +typedef struct LayerInfo_t { + PTLInfo ptl_info; + RK_U32 max_dec_pic_buffering; + RK_U32 num_reorder_pics; + RK_S32 max_latency_increase; +} LayerInfo; + +typedef struct H265dVps_t { + RK_U32 vps_id; + RK_U32 vps_temporal_id_nesting_flag; + RK_S32 vps_max_layers; + RK_S32 vps_max_sub_layers; + LayerInfo layers[MAX_SUB_LAYERS]; + RK_S32 vps_sub_layer_ordering_info_present_flag; + RK_S32 vps_max_layer_id; + RK_S32 vps_num_layer_sets; + RK_U32 vps_timing_info_present_flag; + RK_U32 vps_num_units_in_tick; + RK_U32 vps_time_scale; + RK_U32 vps_poc_proportional_to_timing_flag; + RK_S32 vps_num_ticks_poc_diff_one; + RK_S32 vps_num_hrd_parameters; + RK_S32 vps_extension_flag; +} H265dVps; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 h265d_layer_info(BitReadCtx_t *bit, LayerInfo *layers, RK_S32 max_num_sub_layers); +RK_S32 h265d_hrd_info(BitReadCtx_t *bit, RK_S32 common_inf_present, RK_S32 max_sublayers); +RK_S32 h265d_nal_vps(BitReadCtx_t *bit, H265dVps *vps); + +#ifdef __cplusplus +} +#endif + +#endif /* H265D_VPS_H */ diff --git a/mpp/codec/dec/jpeg/CMakeLists.txt b/mpp/codec/dec/jpeg/CMakeLists.txt new file mode 100644 index 000000000..4e83791ee --- /dev/null +++ b/mpp/codec/dec/jpeg/CMakeLists.txt @@ -0,0 +1,6 @@ +# vim: syntax=cmake + +# jpeg decoder source +add_library(jpegd_api OBJECT + jpegd_parser.c + ) diff --git a/mpp/codec/dec/jpeg/jpegd_parser.c b/mpp/codec/dec/jpeg/jpegd_parser.c new file mode 100644 index 000000000..88662dd0f --- /dev/null +++ b/mpp/codec/dec/jpeg/jpegd_parser.c @@ -0,0 +1,1333 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "jpegd_parser" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_debug.h" +#include "mpp_bitread.h" +#include "mpp_packet_impl.h" + +#include "mpp_parser.h" +#include "jpegd_parser.h" +#include "mpp_dec_cb_param.h" + +/* return the 8 bit start code value and update the search + state. Return 0 if no start code found */ +static RK_U8 jpegd_find_marker(const RK_U8 **pbuf_ptr, const RK_U8 *buf_end) +{ + const RK_U8 *buf_ptr = NULL; + RK_U8 val = 0; + RK_U8 start_code = 0xff; + RK_U32 strm_len = buf_end - *pbuf_ptr + 1; + + while (*pbuf_ptr < buf_end) { + buf_ptr = memchr(*pbuf_ptr, start_code, strm_len); + + if (!buf_ptr) { + mpp_err("Start codec not found!\n"); + return 0; + } + + RK_U8 marker = *(buf_ptr + 1); + if (marker >= 0xc0 && marker <= 0xfe) { + val = *(buf_ptr + 1); + jpegd_dbg_marker("find_marker skipped %d bytes\n", buf_ptr - *pbuf_ptr); + *pbuf_ptr = buf_ptr; + return val; + } else { + jpegd_dbg_marker("0x%x is not a marker\n", marker); + (*pbuf_ptr)++; + } + } + return 0; +} + +static MPP_RET jpegd_find_eoi(const RK_U8 **pbuf_ptr, const RK_U8 *buf_end) +{ + const RK_U8 *buf_ptr = NULL; + RK_S32 eoi = 0xffd9; + RK_U32 strm_len = buf_end - *pbuf_ptr + 1; + + if (*pbuf_ptr >= buf_end) { + mpp_err("buf ptr %p is overflow the buf end %p.", *pbuf_ptr, buf_end); + return MPP_NOK; + } + + buf_ptr = memchr(*pbuf_ptr, eoi, strm_len); + + if (buf_ptr && (buf_end > buf_ptr)) { + return MPP_OK; + } + + return MPP_NOK; +} + +static MPP_RET jpeg_judge_yuv_mode(JpegdCtx *ctx) +{ + MPP_RET ret = MPP_OK; + JpegdSyntax *s = ctx->syntax; + + /* check input format */ + if (s->nb_components == 3) { + if (s->h_count[0] == 2 && s->v_count[0] == 2 && + s->h_count[1] == 1 && s->v_count[1] == 1 && + s->h_count[2] == 1 && s->v_count[2] == 1) { + jpegd_dbg_marker("YCbCr Format: YUV420(2*2:1*1:1*1)\n"); + s->yuv_mode = JPEGDEC_YUV420; + s->output_fmt = MPP_FMT_YUV420SP; + } else if (s->h_count[0] == 2 && s->v_count[0] == 1 && + s->h_count[1] == 1 && s->v_count[1] == 1 && + s->h_count[2] == 1 && s->v_count[2] == 1) { + jpegd_dbg_marker("YCbCr Format: YUV422(2*1:1*1:1*1)\n"); + s->yuv_mode = JPEGDEC_YUV422; + s->output_fmt = MPP_FMT_YUV422SP; + + /* check if fill needed */ + if ((s->height & 0xf) && ((s->height & 0xf) <= 8)) { + s->fill_bottom = 1; + } + } else if (s->h_count[0] == 1 && s->v_count[0] == 2 && + s->h_count[1] == 1 && s->v_count[1] == 1 && + s->h_count[2] == 1 && s->v_count[2] == 1) { + jpegd_dbg_marker("YCbCr Format: YUV440(1*2:1*1:1*1)\n"); + s->yuv_mode = JPEGDEC_YUV440; + s->output_fmt = MPP_FMT_YUV440SP; + + /* check if fill needed */ + if ((s->width & 0xf) && ((s->width & 0xf) <= 8)) { + s->fill_right = 1; + } + } else if (s->h_count[0] == 1 && s->v_count[0] == 1 && + s->h_count[1] == 1 && s->v_count[1] == 1 && + s->h_count[2] == 1 && s->v_count[2] == 1) { + jpegd_dbg_marker("YCbCr Format: YUV444(1*1:1*1:1*1)\n"); + s->yuv_mode = JPEGDEC_YUV444; + s->output_fmt = MPP_FMT_YUV444SP; + + /* check if fill needed */ + if ((s->width & 0xf) && ((s->width & 0xf) <= 8)) { + s->fill_right = 1; + } + + if ((s->height & 0xf) && ((s->height & 0xf) <= 8)) { + s->fill_bottom = 1; + } + } else if (s->h_count[0] == 4 && s->v_count[0] == 1 && + s->h_count[1] == 1 && s->v_count[1] == 1 && + s->h_count[2] == 1 && s->v_count[2] == 1) { + jpegd_dbg_marker("YCbCr Format: YUV411(4*1:1*1:1*1)\n"); + s->yuv_mode = JPEGDEC_YUV411; + s->output_fmt = MPP_FMT_YUV411SP; + + /* check if fill needed */ + if ((s->height & 0xf) && ((s->height & 0xf) <= 8)) { + s->fill_bottom = 1; + } + } else { + mpp_err_f("Unsupported YCbCr Format: (%d*%d:%d*%d:%d*%d)\n", + s->h_count[0], s->v_count[0], + s->h_count[1], s->v_count[1], + s->h_count[2], s->v_count[2]); + ret = MPP_ERR_STREAM; + } + } else if (s->nb_components == 1) { + if (s->h_count[0] == s->v_count[0] && s->h_count[0] != 0) { + s->yuv_mode = JPEGDEC_YUV400; + s->output_fmt = MPP_FMT_YUV400; + /* check if fill needed */ + if ((s->width & 0xf) && ((s->width & 0xf) <= 8)) { + s->fill_right = 1; + } + + if ((s->height & 0xf) && ((s->height & 0xf) <= 8)) { + s->fill_bottom = 1; + } + } else { + mpp_err_f("unsupported format(%d*%d)\n", s->h_count[0], + s->v_count[0]); + ret = MPP_ERR_STREAM; + } + } else { + mpp_err_f("unsupported format, nb_components=%d\n", s->nb_components); + ret = MPP_ERR_STREAM; + } + + return ret; +} + +static inline RK_U16 jpegd_read_len(BitReadCtx_t *gb) +{ + RK_U8 lh, ll; + READ_BITS(gb, 8, &lh); + READ_BITS(gb, 8, &ll); + return (((RK_U16)lh) << 8) | ((RK_U16)ll); + +__BITREAD_ERR: + return 0; +} + +static MPP_RET jpegd_skip_section(JpegdCtx *ctx) +{ + BitReadCtx_t *gb = ctx->bit_ctx; + RK_U16 len = 0; + + if (gb->bytes_left_ < 2) + return MPP_ERR_READ_BIT; + len = jpegd_read_len(gb); + if (len < 2 /* invalid marker */ || (RK_U32)len - 2 > gb->bytes_left_) { + /* too short length or bytes is not enough */ + return MPP_ERR_READ_BIT; + } + if (len > 2) + SKIP_BITS(gb, (len - 2) * 8); + + return MPP_OK; + +__BITREAD_ERR: + return MPP_NOK; +} + +static MPP_RET jpegd_decode_dht(JpegdCtx *ctx) +{ + MPP_RET ret = MPP_NOK; + BitReadCtx_t *gb = ctx->bit_ctx; + JpegdSyntax *syntax = ctx->syntax; + RK_U32 len, num, value; + RK_U32 table_type, table_id; + RK_U32 i, code_max; + + len = jpegd_read_len(gb); + len -= 2; /* Huffman Table Length */ + + if (len > gb->bytes_left_) { + mpp_err_f("dht: len %d is too large\n", len); + return MPP_ERR_STREAM; + } + jpegd_dbg_marker("dht: huffman tables length=%d\n", len); + + while (len > 0) { + if (len < MAX_HUFFMAN_CODE_BIT_LENGTH + 1) { + mpp_err_f("dht: len %d is too small\n", len); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 4, &table_type); /* 0 - DC; 1 - AC */ + if (table_type >= HUFFMAN_TABLE_TYPE_BUTT) { + mpp_err_f("table type %d error\n", table_type); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 4, &table_id); + if (table_id >= HUFFMAN_TABLE_ID_TWO) { + mpp_err_f("table id %d is unsupported for baseline\n", table_id); + return MPP_ERR_STREAM; + } + + num = 0; + if (table_type == HUFFMAN_TABLE_TYPE_DC) { + DcTable *ptr = &(syntax->dc_table[table_id]); + for (i = 0; i < MAX_HUFFMAN_CODE_BIT_LENGTH; i++) { + READ_BITS(gb, 8, &value); + ptr->bits[i] = value; + num += value; + } + + ptr->actual_length = num; + } else { + AcTable *ptr = &(syntax->ac_table[table_id]); + for (i = 0; i < MAX_HUFFMAN_CODE_BIT_LENGTH; i++) { + READ_BITS(gb, 8, &value); + ptr->bits[i] = value; + num += value; + } + + ptr->actual_length = num; + } + + len -= 17; + if (len < num || + (num > MAX_DC_HUFFMAN_TABLE_LENGTH && table_type == HUFFMAN_TABLE_TYPE_DC) || + (num > MAX_AC_HUFFMAN_TABLE_LENGTH && table_type == HUFFMAN_TABLE_TYPE_AC)) { + mpp_err_f("table type %d, code word number %d error\n", table_type, num); + return MPP_ERR_STREAM; + } + + code_max = 0; + if (table_type == HUFFMAN_TABLE_TYPE_DC) { + DcTable *ptr = &(syntax->dc_table[table_id]); + + syntax->htbl_entry |= 1 << (table_id * 2); + + for (i = 0; i < num; i++) { + READ_BITS(gb, 8, &value); + ptr->vals[i] = value; + if (ptr->vals[i] > code_max) + code_max = ptr->vals[i]; + } + } else { + AcTable *ptr = &(syntax->ac_table[table_id]); + + syntax->htbl_entry |= 1 << ((table_id * 2) + 1); + + for (i = 0; i < num; i++) { + READ_BITS(gb, 8, &value); + ptr->vals[i] = value; + if (ptr->vals[i] > code_max) + code_max = ptr->vals[i]; + } + } + len -= num; + + jpegd_dbg_marker("dht: type=%d id=%d code_word_num=%d, code_max=%d, len=%d\n", + table_type, table_id, num, code_max, len); + } + ret = MPP_OK; + +__BITREAD_ERR: + if (ret != MPP_OK) + jpegd_dbg_syntax("bit read error!\n"); + + return ret; +} + +/* quantize tables */ +static MPP_RET jpegd_decode_dqt(JpegdCtx *ctx) +{ + MPP_RET ret = MPP_NOK; + BitReadCtx_t *gb = ctx->bit_ctx; + JpegdSyntax *syntax = ctx->syntax; + RK_U32 len; + int index, i; + RK_U16 value; + + len = jpegd_read_len(gb); + len -= 2; /* quantize tables length */ + + if (len > gb->bytes_left_) { + mpp_err_f("dqt: len %d is too large\n", len); + return MPP_ERR_STREAM; + } + + while (len >= 65) { + RK_U16 pr; + READ_BITS(gb, 4, &pr); + if (pr > 1) { + mpp_err_f("dqt: invalid precision\n"); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 4, &index); + if (index >= QUANTIZE_TABLE_ID_BUTT) { + mpp_err_f("dqt: invalid quantize tables ID\n"); + return MPP_ERR_STREAM; + } + jpegd_dbg_marker("quantize tables ID=%d\n", index); + + /* read quant table */ + for (i = 0; i < QUANTIZE_TABLE_LENGTH; i++) { + READ_BITS(gb, (pr != 0) ? 16 : 8, &value); + syntax->quant_matrixes[index][i] = value; + } + syntax->qtbl_entry++; + if (syntax->qtbl_entry > MAX_COMPONENTS) + mpp_err_f("%d entries qtbl is not supported\n", syntax->qtbl_entry); + + if (jpegd_debug & JPEGD_DBG_TABLE) { + /* debug code */ + mpp_log("******Start to print quantize table %d******\n", index); + + for (i = 0; i < QUANTIZE_TABLE_LENGTH; i += 8) { + mpp_log("%2d~%2d 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + i, i + 7, + syntax->quant_matrixes[index][i + 0], + syntax->quant_matrixes[index][i + 1], + syntax->quant_matrixes[index][i + 2], + syntax->quant_matrixes[index][i + 3], + syntax->quant_matrixes[index][i + 4], + syntax->quant_matrixes[index][i + 5], + syntax->quant_matrixes[index][i + 7], + syntax->quant_matrixes[index][i + 7]); + } + mpp_log("******Quantize table %d End******\n", index); + } + + // XXX FIXME fine-tune, and perhaps add dc too + syntax->qscale[index] = MPP_MAX(syntax->quant_matrixes[index][1], + syntax->quant_matrixes[index][8]) >> 1; + + jpegd_dbg_marker("qscale[%d]: %d\n", index, syntax->qscale[index]); + len -= 1 + 64 * (1 + pr); + } + ret = MPP_OK; + +__BITREAD_ERR: + if (ret != MPP_OK) + jpegd_dbg_syntax("bit read error!\n"); + + return ret; +} + +static MPP_RET jpegd_decode_sof(JpegdCtx *ctx) +{ + MPP_RET ret = MPP_NOK; + BitReadCtx_t *gb = ctx->bit_ctx; + JpegdSyntax *syntax = ctx->syntax; + RK_U32 len, bits, i; + RK_U32 width, height; + RK_U32 nb_components, value; + + len = jpegd_read_len(gb); + if (len > gb->bytes_left_) { + mpp_err_f("len %d is too large\n", len); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 8, &bits); + if (bits > 16 || bits < 1) { + /* usually bits is 8 */ + mpp_err_f("bits %d is invalid\n", bits); + return MPP_ERR_STREAM; + } + syntax->sample_precision = bits; + + READ_BITS(gb, 16, &height); + READ_BITS(gb, 16, &width); + syntax->height = height; + syntax->width = width; + syntax->hor_stride = MPP_ALIGN(width, 16); + syntax->ver_stride = MPP_ALIGN(height, 16); + + jpegd_dbg_marker("sof0: picture: %dx%d, stride: %dx%d\n", width, height, + syntax->hor_stride, syntax->ver_stride); + + READ_BITS(gb, 8 , &nb_components); + if ((nb_components != 1) && (nb_components != MAX_COMPONENTS)) { + mpp_err_f("components number %d error\n", nb_components); + return MPP_ERR_STREAM; + } + + if (len != (8 + (3 * nb_components))) + mpp_err_f("decode_sof0: error, len(%d) mismatch nb_components(%d)\n", + len, nb_components); + + syntax->nb_components = nb_components; + syntax->h_max = 1; + syntax->v_max = 1; + for (i = 0; i < nb_components; i++) { + /* component id */ + READ_BITS(gb, 8 , &value); + syntax->component_id[i] = value - 1; /* start from zero */ + + READ_BITS(gb, 4, &value); + syntax->h_count[i] = value; /* Horizontal sampling factor */ + + READ_BITS(gb, 4, &value); + syntax->v_count[i] = value; /* Vertical sampling factor */ + + if (!syntax->h_count[i] || !syntax->v_count[i]) { + mpp_err_f("Invalid sampling factor in component %d %d:%d\n", + i, syntax->h_count[i], syntax->v_count[i]); + return MPP_ERR_STREAM; + } + + /* compute hmax and vmax (only used in interleaved case) */ + if (syntax->h_count[i] > syntax->h_max) + syntax->h_max = syntax->h_count[i]; + if (syntax->v_count[i] > syntax->v_max) + syntax->v_max = syntax->v_count[i]; + + /* Quantization table destination selector */ + READ_BITS(gb, 8, &value); + syntax->quant_index[i] = value; + + if (syntax->quant_index[i] >= QUANTIZE_TABLE_ID_BUTT) { + mpp_err_f("quant_index %d is invalid\n", syntax->quant_index[i]); + return MPP_ERR_STREAM; + } + + jpegd_dbg_marker("component %d %d:%d id: %d quant_id:%d\n", + i, syntax->h_count[i], syntax->v_count[i], + syntax->component_id[i], syntax->quant_index[i]); + } + + /* judge yuv mode from sampling factor */ + ret = jpeg_judge_yuv_mode(ctx); + +__BITREAD_ERR: + if (ret != MPP_OK) + jpegd_dbg_syntax("bit read error!\n"); + + return ret; +} + +static MPP_RET jpegd_decode_sos(JpegdCtx *ctx) +{ + MPP_RET ret = MPP_NOK; + BitReadCtx_t *gb = ctx->bit_ctx; + JpegdSyntax *syntax = ctx->syntax; + RK_U32 len, nb_components, value; + RK_U32 id, i, index; + + len = jpegd_read_len(gb); + if (len > gb->bytes_left_) { + mpp_err_f("len %d is too large\n", len); + return MPP_ERR_STREAM; + } + syntax->sos_len = len; /* used for calculating stream offset */ + + READ_BITS(gb, 8, &nb_components); + if ((nb_components != 1) && (nb_components != MAX_COMPONENTS)) { + mpp_err_f("decode_sos: nb_components %d unsupported\n", nb_components); + return MPP_ERR_STREAM; + } + + if (len != 6 + 2 * nb_components) { + mpp_err_f("decode_sos: invalid len (%d), nb_components:%d\n", + len, nb_components); + return MPP_ERR_STREAM; + } + syntax->qtable_cnt = nb_components; + + for (i = 0; i < nb_components; i++) { + READ_BITS(gb, 8, &value); + id = value - 1; + jpegd_dbg_marker("sos component: %d\n", id); + + /* find component index */ + for (index = 0; index < syntax->nb_components; index++) + if (id == syntax->component_id[index]) + break; + + if (index == syntax->nb_components) { + mpp_err_f("decode_sos: index(%d) out of components\n", index); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 4, &value); + syntax->dc_index[i] = value; + + READ_BITS(gb, 4, &value); + syntax->ac_index[i] = value; + + jpegd_dbg_marker("component:%d, dc_index:%d, ac_index:%d\n", + id, syntax->dc_index[i], syntax->ac_index[i]); + + if (syntax->dc_index[i] > HUFFMAN_TABLE_ID_ONE || + syntax->ac_index[i] > HUFFMAN_TABLE_ID_ONE) { + /* for baseline */ + mpp_err_f("Huffman table id error\n"); + return MPP_ERR_STREAM; + } + } + + READ_BITS(gb, 8, &value); + syntax->scan_start = value; + + READ_BITS(gb, 8, &value); + syntax->scan_end = value; + + READ_BITS(gb, 4, &value); + syntax->prev_shift = value; + + READ_BITS(gb, 4, &value); + syntax->point_transform = value; + + if (syntax->scan_start != 0 || syntax->scan_end != 0x3F || + syntax->prev_shift != 0 || syntax->point_transform != 0) { + /* for baseline */ + mpp_err_f("unsupported sos parameter: scan_start:%d,\n" + "\t\tscan_end:%d, prev_shift:%d, point_transform:%d\n", + syntax->scan_start, syntax->scan_end, + syntax->prev_shift, syntax->point_transform); + return MPP_ERR_STREAM; + } + ret = MPP_OK; + +__BITREAD_ERR: + if (ret != MPP_OK) + jpegd_dbg_syntax("bit read error!\n"); + + return ret; +} + +static MPP_RET jpegd_decode_dri(JpegdCtx *ctx) +{ + MPP_RET ret = MPP_NOK; + BitReadCtx_t *gb = ctx->bit_ctx; + JpegdSyntax *s = ctx->syntax; + RK_U32 len; + + len = jpegd_read_len(gb); + if (len != DRI_MARKER_LENGTH) { + mpp_err_f("DRI length %d error\n", len); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 16, &s->restart_interval); + jpegd_dbg_marker("restart interval: %d\n", s->restart_interval); + + ret = MPP_OK; + +__BITREAD_ERR: + if (ret != MPP_OK) + jpegd_dbg_syntax("bit read error!\n"); + + return ret; +} + +static MPP_RET jpegd_setup_default_dht(JpegdCtx *ctx) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = ctx->syntax; + AcTable *ac_ptr = NULL; + DcTable *dc_ptr = NULL; + const RK_U8 *bits_tmp = NULL; + const RK_U8 *val_tmp = NULL; + RK_U32 tmp_len = 0; + RK_U32 i, k; + + /* Set up the standard Huffman tables (cf. JPEG standard section K.3) + * IMPORTANT: these are only valid for 8-bit data precision! + */ + static const RK_U8 bits_dc_luminance[MAX_HUFFMAN_CODE_BIT_LENGTH] = + { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + + /* luminance and chrominance all use it */ + static const RK_U8 val_dc[MAX_DC_HUFFMAN_TABLE_LENGTH] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const RK_U8 bits_dc_chrominance[MAX_HUFFMAN_CODE_BIT_LENGTH] = + { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + + static const RK_U8 bits_ac_luminance[MAX_HUFFMAN_CODE_BIT_LENGTH] = + { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + + /* 162 Bytes */ + static const RK_U8 val_ac_luminance[MAX_AC_HUFFMAN_TABLE_LENGTH] = { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + static const RK_U8 bits_ac_chrominance[MAX_HUFFMAN_CODE_BIT_LENGTH] = + { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + + static const RK_U8 val_ac_chrominance[MAX_AC_HUFFMAN_TABLE_LENGTH] = { + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + const RK_U8 *bits_table[4] = { + bits_ac_luminance, + bits_ac_chrominance, + bits_dc_luminance, + bits_dc_chrominance + }; + + const RK_U8 *val_table[4] = { + val_ac_luminance, + val_ac_chrominance, + val_dc, + val_dc + }; + + /* AC Table */ + for (k = 0; k < 2; k++) { + ac_ptr = &(s->ac_table[k]); + bits_tmp = bits_table[k]; + val_tmp = val_table[k]; + + tmp_len = 0; + for (i = 0; i < MAX_HUFFMAN_CODE_BIT_LENGTH; i++) { + /* read in the values of list BITS */ + tmp_len += ac_ptr->bits[i] = bits_tmp[i]; + } + + ac_ptr->actual_length = tmp_len; /* set the table length */ + for (i = 0; i < tmp_len; i++) { + /* read in the HUFFVALs */ + ac_ptr->vals[i] = val_tmp[i]; + } + } + + /* DC Table */ + for (k = 0; k < 2; k++) { + dc_ptr = &(s->dc_table[k]); + bits_tmp = bits_table[k + 2]; + val_tmp = val_table[k + 2]; + + tmp_len = 0; + for (i = 0; i < MAX_HUFFMAN_CODE_BIT_LENGTH; i++) { + /* read in the values of list BITS */ + tmp_len += dc_ptr->bits[i] = bits_tmp[i]; + } + + dc_ptr->actual_length = tmp_len; /* set the table length */ + for (i = 0; i < tmp_len; i++) { + /* read in the HUFFVALs */ + dc_ptr->vals[i] = val_tmp[i]; + } + } + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET jpegd_decode_frame(JpegdCtx *ctx) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + const RK_U8 *const buf = ctx->buffer; + RK_U32 strm_len = ctx->streamLength; + BitReadCtx_t *gb = ctx->bit_ctx; + JpegdSyntax *syntax = ctx->syntax; + RK_S32 start_code = 0xffd8; + + const RK_U8 *buf_ptr = buf; + const RK_U8 *const buf_end = buf + strm_len; + + syntax->htbl_entry = 0; + syntax->qtbl_entry = 0; + + if (strm_len < 8 || !memchr(buf_ptr, start_code, 8)) { + // not jpeg + ret = MPP_ERR_STREAM; + goto fail; + } + + while (buf_ptr < buf_end) { + /* find start marker */ + start_code = jpegd_find_marker(&buf_ptr, buf_end); + if (start_code <= 0) { + jpegd_dbg_marker("start code not found\n"); + ret = MPP_ERR_STREAM; + break; + } else { + buf_ptr += 2; + } + + jpegd_dbg_marker("marker = 0x%x, avail_size_in_buf = %d\n", + start_code, buf_end - buf_ptr); + ctx->start_code = start_code; + + /* setup bit read context */ + mpp_set_bitread_ctx(gb, (RK_U8 *)buf_ptr, buf_end - buf_ptr); + + /* process markers */ + if (start_code >= RST0 && start_code <= RST7) { + /* nothing to do with RSTn */ + jpegd_dbg_syntax("restart marker: %d\n", start_code & 0x0f); + } + + if (start_code > SOF0 && start_code <= SOF15 && start_code != DHT) { + mpp_err_f("Only baseline DCT is supported, unsupported entropy encoding 0x%x", start_code); + ret = MPP_ERR_STREAM; + goto fail; + } + + switch (start_code) { + case SOI: + /* nothing to do on SOI */ + syntax->dht_found = 0; + syntax->eoi_found = 0; + syntax->sof0_found = 0; + syntax->qtable_cnt = 0; + syntax->qtbl_entry = 0; + syntax->htbl_entry = 0; + break; + case DHT: + if ((ret = jpegd_decode_dht(ctx)) != MPP_OK) { + mpp_err_f("huffman table decode error\n"); + goto fail; + } + syntax->dht_found = 1; + break; + case DQT: + if ((ret = jpegd_decode_dqt(ctx)) != MPP_OK) { + mpp_err_f("quantize tables decode error\n"); + goto fail; + } + break; + case SOF0: + if ((ret = jpegd_decode_sof(ctx)) != MPP_OK) { + mpp_err_f("sof0 decode error\n"); + goto fail; + } + if (ctx->syntax->sample_precision != 8) { + mpp_err_f("Illegal sample precision %d.\n\ + For baseline, it should be 8\n", ctx->syntax->sample_precision); + goto fail; + } + + syntax->sof0_found = 1; + break; + case EOI: + syntax->eoi_found = 1; + jpegd_dbg_marker("still exists %d bytes behind EOI marker\n", + buf_end - buf_ptr); + goto done; + break; + case SOS: + if (!syntax->sof0_found) { + mpp_err_f("Warning: only support baseline type\n"); + goto fail; + } + + if ((ret = jpegd_decode_sos(ctx)) != MPP_OK) { + mpp_err_f("sos decode error\n"); + goto fail; + } + + /* stream behind SOS is decoded by hardware */ + syntax->strm_offset = buf_ptr - buf + syntax->sos_len; + syntax->cur_pos = (RK_U8 *)buf + syntax->strm_offset; + syntax->pkt_len = ctx->streamLength; + jpegd_dbg_marker("This packet owns %d bytes with length %zu\n" + "\t\thas been decoded %d bytes by software\n" + "\t\tbuf_ptr:%p, buf:%p, sos_len:%d\n" + "\t\thardware start address:%p", + mpp_packet_get_size(ctx->input_packet), + syntax->pkt_len, + syntax->strm_offset, buf_ptr, buf, + syntax->sos_len, syntax->cur_pos); + + if (syntax->strm_offset >= ctx->streamLength) { + mpp_err_f("stream offset %d is larger than buffer size %d\n", + syntax->strm_offset, ctx->streamLength); + ret = MPP_ERR_UNKNOW; + goto fail; + } + + if ((syntax->strm_offset + 2) < ctx->streamLength && + buf_ptr[syntax->sos_len] == 0xff && buf_ptr[syntax->sos_len + 1] == 0xd8) { + jpegd_dbg_marker("Encontered SOI again, parse again!\n"); + break; + } + if (!ctx->scan_all_marker) { + jpegd_dbg_marker("just scan parts of markers!\n"); + goto done; + } + + break; + case DRI: + if ((ret = jpegd_decode_dri(ctx)) != MPP_OK) { + mpp_err_f("dri decode error\n"); + goto fail; + } + break; + default: + jpegd_dbg_marker("unhandled coding type(0x%x) in switch..case..\n", + start_code); + if ((ret = jpegd_skip_section(ctx)) != MPP_OK) { + jpegd_dbg_marker("Fail to skip section 0xFF%02x!\n", + start_code); + goto fail; + } + break; + } + + buf_ptr = ctx->bit_ctx->data_; + } + +done: + if (!syntax->dht_found) { + jpegd_dbg_marker("sorry, DHT is not found!\n"); + jpegd_setup_default_dht(ctx); + syntax->htbl_entry = 0x0f; + } + if (!syntax->sof0_found) { + mpp_err_f("sof marker not found!\n"); + ret = MPP_ERR_STREAM; + } + if (!syntax->eoi_found) { + if (MPP_OK != jpegd_find_eoi(&buf_ptr, buf_end)) { + mpp_err_f("EOI marker not found!\n"); + ret = MPP_ERR_STREAM; + } + } + jpegd_dbg_func("exit\n"); + return ret; + +fail: + ret = MPP_ERR_STREAM; + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET +jpegd_split_frame(RK_U8 *src, RK_U32 src_size, + RK_U8 *dst, RK_U32 dst_size, RK_U32 *copy_length) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + if (NULL == src || NULL == dst || src_size <= 0) { + mpp_err_f("NULL pointer or wrong src_size(%d)", src_size); + return MPP_ERR_NULL_PTR; + } + RK_U8 *tmp; + RK_U32 str_size = (src_size + 255) & (~255); + + if (src[6] == 0x41 && src[7] == 0x56 && src[8] == 0x49 && src[9] == 0x31) { + //distinguish 310 from 210 camera + RK_U32 i; + RK_U32 copy_len = 0; + tmp = src; + jpegd_dbg_parser("distinguish 310 from 210 camera"); + + for (i = 0; i < src_size - 4; i++) { + if (tmp[i] == 0xff) { + if (tmp[i + 1] == 0x00 && tmp[i + 2] == 0xff && ((tmp[i + 3] & 0xf0) == 0xd0)) + i += 2; + } + *dst++ = tmp[i]; + copy_len++; + } + for (; i < src_size; i++) { + *dst++ = tmp[i]; + copy_len++; + } + if (copy_len < src_size) + memset(dst, 0, src_size - copy_len); + *copy_length = copy_len; + } else { + memcpy(dst, src, src_size); + memset(dst + src_size, 0, str_size > dst_size ? dst_size - src_size : str_size - src_size); + *copy_length = src_size; + } + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET jpegd_prepare(void *ctx, MppPacket pkt, HalDecTask *task) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdCtx *JpegCtx = (JpegdCtx *)ctx; + if (!JpegCtx->copy_flag) { + /* no need to copy stream, handle packet from upper application directly*/ + JpegCtx->input_packet = pkt; + } + + MppPacket input_packet = JpegCtx->input_packet; + RK_U32 copy_length = 0; + void *base = mpp_packet_get_pos(pkt); + RK_U8 *pos = base; + RK_U32 pkt_length = (RK_U32)mpp_packet_get_length(pkt); + RK_U32 eos = (pkt_length != 0) ? (mpp_packet_get_eos(pkt)) : (1); + + JpegCtx->pts = mpp_packet_get_pts(pkt); + + task->valid = 0; + task->flags.eos = eos; + JpegCtx->eos = eos; + + jpegd_dbg_parser("pkt_length %d eos %d\n", pkt_length, eos); + + if (!pkt_length) { + jpegd_dbg_parser("it is end of stream."); + return ret; + } + + if (pkt_length > JpegCtx->bufferSize) { + jpegd_dbg_parser("Huge Frame(%d Bytes)! bufferSize:%d", + pkt_length, JpegCtx->bufferSize); + mpp_free(JpegCtx->recv_buffer); + JpegCtx->recv_buffer = NULL; + + JpegCtx->recv_buffer = mpp_calloc(RK_U8, pkt_length + 1024); + if (NULL == JpegCtx->recv_buffer) { + mpp_err_f("no memory!"); + return MPP_ERR_NOMEM; + } + + JpegCtx->bufferSize = pkt_length + 1024; + } + + if (JpegCtx->copy_flag) + jpegd_split_frame(base, pkt_length, JpegCtx->recv_buffer, + JpegCtx->bufferSize, ©_length); + + pos += pkt_length; + mpp_packet_set_pos(pkt, pos); + if (copy_length != pkt_length) { + jpegd_dbg_parser("packet prepare, pkt_length:%d, copy_length:%d\n", + pkt_length, copy_length); + } + + /* debug information */ + if (jpegd_debug & JPEGD_DBG_IO) { + static FILE *jpg_file; + static char name[32]; + + snprintf(name, sizeof(name) - 1, "/data/input%02d.jpg", + JpegCtx->input_jpeg_count); + jpg_file = fopen(name, "wb+"); + if (jpg_file) { + jpegd_dbg_io("frame_%02d input jpeg(%d Bytes) saving to %s\n", + JpegCtx->input_jpeg_count, pkt_length, name); + fwrite(base, pkt_length, 1, jpg_file); + fclose(jpg_file); + JpegCtx->input_jpeg_count++; + } + } + + if (JpegCtx->copy_flag) { + mpp_packet_set_data(input_packet, JpegCtx->recv_buffer); + mpp_packet_set_size(input_packet, pkt_length); + mpp_packet_set_length(input_packet, pkt_length); + memcpy(base, JpegCtx->recv_buffer, pkt_length); + } + + JpegCtx->streamLength = pkt_length; + task->input_packet = input_packet; + task->valid = 1; + jpegd_dbg_parser("input_packet:%p, recv_buffer:%p, pkt_length:%d", + input_packet, + JpegCtx->recv_buffer, pkt_length); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET jpegd_allocate_frame(JpegdCtx *ctx) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = ctx->syntax; + MppBufSlots slots = ctx->frame_slots; + MppFrame output = ctx->output_frame; + RK_S32 slot_idx = ctx->frame_slot_index; + + if (slot_idx == -1) { + RK_U32 value; + MppFrameFormat fmt = 0 != ctx->usr_out_fmt_valid ? ctx->usr_out_fmt : s->output_fmt; + + mpp_frame_set_fmt(output, fmt); + mpp_frame_set_width(output, s->width); + mpp_frame_set_height(output, s->height); + mpp_frame_set_hor_stride(output, s->hor_stride); + mpp_frame_set_ver_stride(output, s->ver_stride); + mpp_frame_set_pts(output, ctx->pts); + + if (ctx->eos) + mpp_frame_set_eos(output, 1); + + mpp_buf_slot_get_unused(slots, &slot_idx); + ctx->frame_slot_index = slot_idx; + jpegd_dbg_parser("frame_slot_index:%d\n", slot_idx); + + value = 2; + mpp_slots_set_prop(slots, SLOTS_NUMERATOR, &value); + value = 1; + mpp_slots_set_prop(slots, SLOTS_DENOMINATOR, &value); + if (mpp_buf_slot_set_prop(slots, slot_idx, SLOT_FRAME, output)) + return MPP_ERR_VALUE; + mpp_buf_slot_set_flag(slots, slot_idx, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(slots, slot_idx, SLOT_HAL_OUTPUT); + } + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET jpegd_update_frame(JpegdCtx *ctx) +{ + jpegd_dbg_func("enter\n"); + + mpp_buf_slot_clr_flag(ctx->frame_slots, ctx->frame_slot_index, + SLOT_CODEC_USE); + ctx->frame_slot_index = -1; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET jpegd_parse(void *ctx, HalDecTask *task) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdCtx *JpegCtx = (JpegdCtx *)ctx; + task->valid = 0; + + JpegCtx->buffer = (RK_U8 *)mpp_packet_get_data(JpegCtx->input_packet); + + memset(JpegCtx->syntax, 0, sizeof(JpegdSyntax)); + + ret = jpegd_decode_frame(JpegCtx); + if (MPP_OK == ret) { + if (jpegd_allocate_frame(JpegCtx)) + return MPP_ERR_VALUE; + + task->syntax.data = (void *)JpegCtx->syntax; + task->syntax.number = sizeof(JpegdSyntax); + task->output = JpegCtx->frame_slot_index; + task->valid = 1; + + jpegd_update_frame(JpegCtx); + } else + task->flags.parse_err = 1; + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET jpegd_deinit(void *ctx) +{ + jpegd_dbg_func("enter\n"); + JpegdCtx *JpegCtx = (JpegdCtx *)ctx; + + if (JpegCtx->recv_buffer) { + mpp_free(JpegCtx->recv_buffer); + JpegCtx->recv_buffer = NULL; + } + + if (JpegCtx->output_frame) { + mpp_frame_deinit(&JpegCtx->output_frame); + } + + if (JpegCtx->copy_flag) { + if (JpegCtx->input_packet) { + mpp_packet_deinit(&JpegCtx->input_packet); + } + } else { + JpegCtx->input_packet = NULL; + } + + if (JpegCtx->bit_ctx) { + mpp_free(JpegCtx->bit_ctx); + JpegCtx->bit_ctx = NULL; + } + + if (JpegCtx->syntax) { + mpp_free(JpegCtx->syntax); + JpegCtx->syntax = NULL; + } + + JpegCtx->pts = 0; + JpegCtx->eos = 0; + JpegCtx->input_jpeg_count = 0; + + jpegd_dbg_func("exit\n"); + return 0; +} + +static MPP_RET jpegd_init(void *ctx, ParserCfg *parser_cfg) +{ + JpegdCtx *JpegCtx = (JpegdCtx *)ctx; + const MppDecHwCap *hw_info = parser_cfg->hw_info; + + jpegd_dbg_func("enter\n"); + + if (NULL == JpegCtx) { + JpegCtx = (JpegdCtx *)mpp_calloc(JpegdCtx, 1); + if (NULL == JpegCtx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + } + + mpp_env_get_u32("jpegd_debug", &jpegd_debug, 0); + // mpp only support baseline + JpegCtx->scan_all_marker = 0; + + if (hw_info && hw_info->cap_hw_jpg_fix) { + /* + * no need to copy stream when decoding jpeg; + * just scan parts of markers to reduce CPU's occupancy + */ + JpegCtx->copy_flag = 0; + } else { + // TODO: do not copy if input provides valid fd and virtual ptr + JpegCtx->copy_flag = 1; + } + + JpegCtx->frame_slots = parser_cfg->frame_slots; + JpegCtx->packet_slots = parser_cfg->packet_slots; + JpegCtx->frame_slot_index = -1; + mpp_buf_slot_setup(JpegCtx->frame_slots, 1); + + JpegCtx->recv_buffer = mpp_calloc(RK_U8, JPEGD_STREAM_BUFF_SIZE); + if (NULL == JpegCtx->recv_buffer) { + mpp_err_f("no memory!"); + return MPP_ERR_NOMEM; + } + JpegCtx->bufferSize = JPEGD_STREAM_BUFF_SIZE; + if (JpegCtx->copy_flag) { + mpp_packet_init(&JpegCtx->input_packet, + JpegCtx->recv_buffer, JPEGD_STREAM_BUFF_SIZE); + } else { + JpegCtx->input_packet = NULL; + } + + mpp_frame_init(&JpegCtx->output_frame); + if (!JpegCtx->output_frame) { + mpp_err_f("Failed to allocate output frame buffer"); + return MPP_ERR_NOMEM; + } + + JpegCtx->bit_ctx = mpp_calloc(BitReadCtx_t, 1); + if (JpegCtx->bit_ctx == NULL) { + mpp_err_f("allocate bit_ctx failed\n"); + return MPP_ERR_MALLOC; + } + + JpegCtx->syntax = mpp_calloc(JpegdSyntax, 1); + if (JpegCtx->syntax == NULL) { + mpp_err_f("allocate syntax failed\n"); + return MPP_ERR_MALLOC; + } + memset(JpegCtx->syntax, 0, sizeof(JpegdSyntax)); + + JpegCtx->pts = 0; + JpegCtx->eos = 0; + JpegCtx->input_jpeg_count = 0; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET jpegd_flush(void *ctx) +{ + jpegd_dbg_func("enter\n"); + JpegdCtx *JpegCtx = (JpegdCtx *)ctx; + (void)JpegCtx; + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET jpegd_reset(void *ctx) +{ + jpegd_dbg_func("enter\n"); + JpegdCtx *JpegCtx = (JpegdCtx *)ctx; + + (void)JpegCtx; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET jpegd_control(void *ctx, MpiCmd cmd, void *param) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdCtx *JpegCtx = (JpegdCtx *)ctx; + + if (NULL == JpegCtx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + + switch (cmd) { + case MPP_DEC_SET_OUTPUT_FORMAT: { + JpegCtx->usr_out_fmt = *(MppFrameFormat *)param; + JpegCtx->usr_out_fmt_valid = 1; + } break; + default : + break; + } + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET jpegd_callback(void *decoder, void *err_info) +{ + JpegdCtx *JpegCtx = (JpegdCtx *)decoder; + DecCbHalDone *ctx = (DecCbHalDone *)err_info; + HalDecTask *task_dec = (HalDecTask *)ctx->task; + RK_U32 task_err = task_dec->flags.parse_err; + RK_U32 hw_dec_err = ctx->hard_err; + RK_S32 output = task_dec->output; + RK_U32 err_mark = 0; + MppFrame frame = NULL; + + if (output >= 0) + mpp_buf_slot_get_prop(JpegCtx->frame_slots, output, SLOT_FRAME_PTR, &frame); + + if (!frame) + goto __RETURN; + + /* check and mark current frame */ + if (task_err) + err_mark |= MPP_FRAME_ERR_DEC_INVALID; + else if (hw_dec_err) + err_mark |= MPP_FRAME_ERR_DEC_HW_ERR; + if (err_mark) + mpp_frame_set_errinfo(frame, err_mark); + +__RETURN: + return MPP_OK; +} + +const ParserApi mpp_jpegd = { + .name = "jpegd_parse", + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegdCtx), + .flag = 0, + .init = jpegd_init, + .deinit = jpegd_deinit, + .prepare = jpegd_prepare, + .parse = jpegd_parse, + .reset = jpegd_reset, + .flush = jpegd_flush, + .control = jpegd_control, + .callback = jpegd_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_jpegd); diff --git a/mpp/codec/dec/jpeg/jpegd_parser.h b/mpp/codec/dec/jpeg/jpegd_parser.h new file mode 100644 index 000000000..66d839213 --- /dev/null +++ b/mpp/codec/dec/jpeg/jpegd_parser.h @@ -0,0 +1,153 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JPEGD_PARSER_H +#define JPEGD_PARSER_H + +#include +#include + +#include "mpp_bitread.h" + +#include "jpegd_syntax.h" + +#define JPEG_IDENTIFIER(a, b, c, d) \ + ((RK_U32)(d) | ((RK_U32)(c) << 8) | \ + ((RK_U32)(b) << 16) | ((RK_U32)(a) << 24)) + + +/* JPEG marker codes */ +enum JpegMarker { + /* start of frame */ + SOF0 = 0xc0, /* baseline */ + SOF1 = 0xc1, /* extended sequential, huffman */ + SOF2 = 0xc2, /* progressive, huffman */ + SOF3 = 0xc3, /* lossless, huffman */ + + SOF5 = 0xc5, /* differential sequential, huffman */ + SOF6 = 0xc6, /* differential progressive, huffman */ + SOF7 = 0xc7, /* differential lossless, huffman */ + JPG = 0xc8, /* reserved for JPEG extension */ + SOF9 = 0xc9, /* extended sequential, arithmetic */ + SOF10 = 0xca, /* progressive, arithmetic */ + SOF11 = 0xcb, /* lossless, arithmetic */ + + SOF13 = 0xcd, /* differential sequential, arithmetic */ + SOF14 = 0xce, /* differential progressive, arithmetic */ + SOF15 = 0xcf, /* differential lossless, arithmetic */ + + DHT = 0xc4, /* define huffman tables */ + + DAC = 0xcc, /* define arithmetic-coding conditioning */ + + /* restart with modulo 8 count "m" */ + RST0 = 0xd0, + RST1 = 0xd1, + RST2 = 0xd2, + RST3 = 0xd3, + RST4 = 0xd4, + RST5 = 0xd5, + RST6 = 0xd6, + RST7 = 0xd7, + + SOI = 0xd8, /* start of image */ + EOI = 0xd9, /* end of image */ + SOS = 0xda, /* start of scan */ + DQT = 0xdb, /* define quantization tables */ + DNL = 0xdc, /* define number of lines */ + DRI = 0xdd, /* define restart interval */ + DHP = 0xde, /* define hierarchical progression */ + EXP = 0xdf, /* expand reference components */ + + APP0 = 0xe0, + APP1 = 0xe1, + APP2 = 0xe2, + APP3 = 0xe3, + APP4 = 0xe4, + APP5 = 0xe5, + APP6 = 0xe6, + APP7 = 0xe7, + APP8 = 0xe8, + APP9 = 0xe9, + APP10 = 0xea, + APP11 = 0xeb, + APP12 = 0xec, + APP13 = 0xed, + APP14 = 0xee, + APP15 = 0xef, + + JPG0 = 0xf0, + JPG1 = 0xf1, + JPG2 = 0xf2, + JPG3 = 0xf3, + JPG4 = 0xf4, + JPG5 = 0xf5, + JPG6 = 0xf6, + SOF48 = 0xf7, ///< JPEG-LS + LSE = 0xf8, ///< JPEG-LS extension parameters + JPG9 = 0xf9, + JPG10 = 0xfa, + JPG11 = 0xfb, + JPG12 = 0xfc, + JPG13 = 0xfd, + + COM = 0xfe, /* comment */ + + TEM = 0x01, /* temporary private use for arithmetic coding */ + + /* 0x02 -> 0xbf reserved */ +}; + +typedef struct JpegdCtx { + MppBufSlots packet_slots; + MppBufSlots frame_slots; + + /* slot index for output */ + RK_S32 frame_slot_index; + RK_U8 *recv_buffer; + + /* input stream length or buffer size */ + RK_U32 streamLength; + + /* input stream buffer size */ + RK_U32 bufferSize; + + MppPacket input_packet; + MppFrame output_frame; + RK_U32 usr_out_fmt; + RK_U32 usr_out_fmt_valid; + + RK_S64 pts; + RK_U32 eos; + RK_U32 input_jpeg_count; + + /* 0 - no need to copy stream; 1 - need to copy */ + RK_S32 copy_flag; + /* 0 - just scan parts of markers; 1 - scan all markers */ + RK_S32 scan_all_marker; + + RK_U8 *buffer; + + /* current start code */ + RK_S32 start_code; + + /* bit read context */ + BitReadCtx_t *bit_ctx; + JpegdSyntax *syntax; +} JpegdCtx; + +#endif /* JPEGD_PARSER_H */ diff --git a/mpp/codec/dec/m2v/CMakeLists.txt b/mpp/codec/dec/m2v/CMakeLists.txt new file mode 100644 index 000000000..19ac1017b --- /dev/null +++ b/mpp/codec/dec/m2v/CMakeLists.txt @@ -0,0 +1,8 @@ +# vim: syntax=cmake +include_directories(.) + +# mpeg2 decoder source +add_library(mpeg2d_api OBJECT + m2vd_api.c + m2vd_parser.c + ) diff --git a/mpp/codec/dec/m2v/m2vd_api.c b/mpp/codec/dec/m2v/m2vd_api.c new file mode 100644 index 000000000..328d0aa20 --- /dev/null +++ b/mpp/codec/dec/m2v/m2vd_api.c @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "m2vd_api" + +#include + +#include "mpp_parser.h" +#include "m2vd_parser.h" +#include "m2vd_codec.h" + +const ParserApi mpp_m2vd = { + .name = "m2vd_parse", + .coding = MPP_VIDEO_CodingMPEG2, + .ctx_size = sizeof(M2VDContext), + .flag = 0, + .init = m2vd_parser_init, + .deinit = m2vd_parser_deinit, + .prepare = m2vd_parser_prepare, + .parse = m2vd_parser_parse, + .reset = m2vd_parser_reset, + .flush = m2vd_parser_flush, + .control = m2vd_parser_control, + .callback = m2vd_parser_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_m2vd); diff --git a/mpp/codec/dec/m2v/m2vd_codec.h b/mpp/codec/dec/m2v/m2vd_codec.h new file mode 100644 index 000000000..f97f80110 --- /dev/null +++ b/mpp/codec/dec/m2v/m2vd_codec.h @@ -0,0 +1,27 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef M2VD_CODEC_H +#define M2VD_CODEC_H + +#include "mpp_common.h" + +typedef struct M2VDContext_t { + void *parse_ctx; + +} M2VDContext; + +#endif diff --git a/mpp/codec/dec/m2v/m2vd_com.h b/mpp/codec/dec/m2v/m2vd_com.h new file mode 100644 index 000000000..9406c5924 --- /dev/null +++ b/mpp/codec/dec/m2v/m2vd_com.h @@ -0,0 +1,124 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef M2VD_COM_H +#define M2VD_COM_H + +#include +#include + +#include "mpp_debug.h" + +#define M2VD_DEMO_MODE 0 + +//------------------------ temp --------------------------------- +#define M2VD_TEST_TRACE (0x00000001) +#define M2VD_TEST_TIME (0x00000002) +#define M2VD_TEST_MUTI_THREAD (0x00000004) +#define M2VD_TEST_DUMPYUV (0x00000008) +#define M2VD_TEST_FPGA (0x00000010) + +//log of diff +#define M2VD_DBG_FUNCTION (0x00000001) +#define M2VD_DBG_ASSERT (0x00000002) +#define M2VD_DBG_WARNNING (0x00000004) +#define M2VD_DBG_LOG (0x00000008) +#define M2VD_DBG_SEC_HEADER (0x00000010) +#define M2VD_DBG_DUMP_REG (0x00000020) + + + + +extern RK_U32 m2vd_debug; + +#define M2VD_ERR(fmt, ...)\ +do {\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define M2VD_ASSERT(val)\ +do {\ + if (M2VD_DBG_ASSERT & m2vd_debug)\ + { mpp_assert(val); }\ +} while (0) + +#define M2VD_WARNNING(fmt, ...)\ +do {\ + if (M2VD_DBG_WARNNING & m2vd_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define M2VD_LOG(fmt, ...)\ +do {\ + if (M2VD_DBG_LOG & m2vd_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + + +//check function return +#define M2VD_CHK_F(val) \ + do{ \ + if((val) < 0) { \ + ret = (val); \ + M2VD_WARNNING("func return error(L%d), ret:%d\n", __LINE__, ret); \ + goto __FAILED; \ + } \ + } while (0) + +//check value if is zero or NULL +#define M2VD_CHK_V(val, ...)\ + do{ if(!(val)){\ + ret = MPP_ERR_VALUE;\ + M2VD_WARNNING("value error(L%d), val:%d\n", __LINE__, val);\ + goto __FAILED;\ + } } while (0) + +//memory malloc check +#define M2VD_CHK_M(val, ...)\ + do{ if(!(val)) {\ + ret = MPP_ERR_MALLOC;\ + M2VD_ERR("malloc buffer error(%d), pointer:%p\n", __LINE__, val);\ + M2VD_ASSERT(0); goto __FAILED;\ + } } while (0) + +//file check +#define M2VD_CHK_FILE(val, path, ...)\ + do{ if(!(val)) {\ + ret = MPP_ERR_OPEN_FILE;\ + M2VD_WARNNING("open file error(line%d): %s\n", __LINE__, path);\ + M2VD_ASSERT(0); goto __FAILED;\ + } } while (0) + +//!< input check +#define M2VD_CHK_I(val, ...)\ + do{ if(!(val)) {\ + ret = MPP_ERR_INIT;\ + M2VD_WARNNING("input empty(%d), val:%d\n", __LINE__, val);\ + goto __FAILED;\ + } } while (0) + +#define m2vd_dbg_func(tag) \ + do {\ + if (M2VD_DBG_FUNCTION & m2vd_debug)\ + { mpp_log("%s: line(%d), func(%s)", tag, __LINE__, __FUNCTION__); }\ + } while (0) + + + + +#define M2VD_FCLOSE(fp) do{ if(fp) fclose(fp); fp = NULL; } while (0) + +#endif diff --git a/mpp/codec/dec/m2v/m2vd_parser.c b/mpp/codec/dec/m2v/m2vd_parser.c new file mode 100644 index 000000000..be86625db --- /dev/null +++ b/mpp/codec/dec/m2v/m2vd_parser.c @@ -0,0 +1,1582 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "m2vd_parser" + +#include +#include + +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_packet_impl.h" + +#include "m2vd_parser.h" +#include "m2vd_codec.h" + +#define VPU_BITSTREAM_START_CODE (0x42564b52) /* RKVB, rockchip video bitstream */ + +/* ignore unofficial frame poriod */ +#define MIN_FRAME_PERIOD_27M 449000 /* more than 60 fps a little*/ +#define MAX_FRAME_PERIOD_27M 1130000 /* less than 23.976 fps a little */ +#define MAX_FRAME_PERIOD_DIFF 13500 /* 500us */ + +static RK_U8 scanOrder[2][64] = { + { /* zig-zag */ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 + }, + + { /* Alternate */ + 0, 8, 16, 24, 1, 9, 2, 10, + 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, + 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, + 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, + 38, 46, 54, 62, 39, 47, 55, 63 + } +}; + +static RK_U8 intraDefaultQMatrix[64] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +static int frame_period_Table_27M[16] = { + 1, + 1126125, /* 23.976 fps */ + 1125000, /* 24 fps */ + 1080000, /* 25 fps */ + 900900, /* 29.97 fps */ + 900000, /* 30 fps */ + 540000, /* 50 fps */ + 450450, /* 59.94 fps */ + 450000, /* 60 fps */ + 1800000, /* unofficial: xing 15 fps */ + /* unofficial: libmpeg3 "Unofficial economy rates" 5/10/12/15 fps */ + 5400000, + 2700000, + 2250000, + 1800000, + 1, + 1 +}; + +static const MppFrameRational mpeg2_aspect[16] = { + {0, 1}, + {1, 1}, + {4, 3}, + {16, 9}, + {221, 100}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, +}; + +static inline RK_S32 m2vd_get_readbits(BitReadCtx_t *bx) +{ + return bx->used_bits; +} + +static inline RK_S32 m2vd_get_leftbits(BitReadCtx_t *bx) +{ + return (bx->bytes_left_ * 8 + bx->num_remaining_bits_in_curr_byte_); +} + +static RK_S32 m2vd_read_bits(BitReadCtx_t *bx, RK_U32 bits) +{ + RK_S32 ret = 0; + if (bits < 32) + mpp_read_bits(bx, bits, &ret); + else + mpp_read_longbits(bx, bits, (RK_U32 *)&ret); + return ret; +} + +static RK_S32 m2vd_show_bits(BitReadCtx_t *bx, RK_U32 bits) +{ + RK_S32 ret = 0; + mpp_show_bits(bx, bits, &ret); + return ret; +} + +static MPP_RET m2vd_parser_init_ctx(M2VDParserContext *ctx, ParserCfg *cfg) +{ + MPP_RET ret = MPP_OK; + RK_S32 i = 0; + m2vd_dbg_func("FUN_I"); + + M2VD_CHK_I(ctx); + memset(ctx, 0, sizeof(*ctx)); + + ctx->cfg = cfg->cfg; + ctx->dxva_ctx = mpp_calloc(M2VDDxvaParam, 1); + ctx->bitread_ctx = mpp_calloc(BitReadCtx_t, 1); + + ctx->packet_slots = cfg->packet_slots; + ctx->frame_slots = cfg->frame_slots; + + mpp_buf_slot_setup(ctx->frame_slots, 16); + + ctx->initFlag = 0; + ctx->info_changed = 0; + + /* copy from mpeg2decoder::mpeg2decoder */ + memset(&ctx->Framehead, 0, 3 * sizeof(M2VDFrameHead)); + + ctx->frame_ref0 = &ctx->Framehead[0]; + ctx->frame_ref1 = &ctx->Framehead[1]; + ctx->frame_cur = &ctx->Framehead[2]; + for (i = 0; i < 3; i++) { + mpp_frame_init(&ctx->Framehead[i].f); + if (!ctx->Framehead[i].f) { + mpp_err("Failed to allocate frame buffer %d\n", i); + return MPP_ERR_NOMEM; + } + ctx->Framehead[i].picCodingType = 0xffffffff; + ctx->Framehead[i].slot_index = -1; + } +#if M2VD_SKIP_ERROR_FRAME_EN + ctx->mHwDecStatus = MPP_OK; +#endif + ctx->resetFlag = 0; + ctx->flush_dpb_eos = 0; + ctx->pic_head.pre_temporal_reference = 0; + ctx->pic_head.pre_picture_coding_type = 0; + ctx->pic_head.picture_coding_type = 0; + + /* copy form mpeg2decoder::decoder_init */ + //---------------------------------------------------- + ctx->bitstream_sw_buf = mpp_calloc(RK_U8, M2VD_BUF_SIZE_BITMEM); + mpp_packet_init(&ctx->input_packet, ctx->bitstream_sw_buf, M2VD_BUF_SIZE_BITMEM); + + ctx->qp_tab_sw_buf = mpp_calloc(RK_U8, M2VD_BUF_SIZE_QPTAB); + ctx->seq_head.pIntra_table = ctx->qp_tab_sw_buf; + ctx->seq_head.pInter_table = ctx->seq_head.pIntra_table + 64; + + ctx->MPEG2_Flag = 0; + ctx->seq_ext_head.progressive_sequence = 1; + ctx->pic_code_ext_head.progressive_frame = 1; + ctx->pic_code_ext_head.picture_structure = M2VD_PIC_STRUCT_FRAME; + ctx->pic_head.pre_picture_coding_type = M2VD_CODING_TYPE_D; + ctx->top_first_cnt = 0; + ctx->bottom_first_cnt = 0; + ctx->pic_code_ext_head.frame_pred_frame_dct = 1; + ctx->seq_ext_head.chroma_format = 1; + ctx->seq_disp_ext_head.matrix_coefficients = 5; + ctx->pre_pts_27M = 0; + ctx->maxFrame_inGOP = 0; + ctx->preframe_period = 0; + ctx->mHeaderDecFlag = 0; + ctx->mExtraHeaderDecFlag = 0; + ctx->max_stream_size = M2VD_BUF_SIZE_BITMEM; + ctx->ref_frame_cnt = 0; + ctx->left_length = 0; + ctx->vop_header_found = 0; + + if (M2VD_DBG_DUMP_REG & m2vd_debug) { + RK_S32 k = 0; + for (k = 0; k < M2VD_DBG_FILE_NUM; k++) + ctx->fp_dbg_file[k] = NULL; + + ctx->fp_dbg_file[0] = fopen("/sdcard/m2vd_dbg_stream.txt", "wb"); + if (!ctx->fp_dbg_file[0]) + mpp_log("open file failed: %s", "/sdcard/m2vd_dbg_stream.txt"); + + ctx->fp_dbg_yuv = fopen("/sdcard/m2vd_dbg_yuv_out.txt", "wb"); + if (!ctx->fp_dbg_yuv) + mpp_log("open file failed: %s", "/sdcard/m2vd_dbg_yuv_out.txt"); + } else { + RK_S32 k = 0; + for (k = 0; k < M2VD_DBG_FILE_NUM; k++) + ctx->fp_dbg_file[k] = NULL; + } + + + m2vd_dbg_func("FUN_O"); +__FAILED: + + return ret; +} + +MPP_RET m2vd_parser_init(void *ctx, ParserCfg *parser_cfg) +{ + MPP_RET ret = MPP_OK; + M2VDContext *c = (M2VDContext *)ctx; + M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx; + m2vd_dbg_func("FUN_I"); + if (p == NULL) { + M2VD_CHK_M(p = (M2VDParserContext*)mpp_calloc(M2VDParserContext, 1)); + c->parse_ctx = p; + } + + M2VD_CHK_F(m2vd_parser_init_ctx(p, parser_cfg)); + + mpp_env_get_u32("m2vd_debug", &m2vd_debug, 0); + + m2vd_dbg_func("FUN_O"); +__FAILED: + return ret; +} + +MPP_RET m2vd_parser_deinit(void *ctx) +{ + RK_U32 k = 0; + MPP_RET ret = MPP_OK; + M2VDContext *c = (M2VDContext *)ctx; + M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx; + + m2vd_dbg_func("FUN_I"); + + for (k = 0; k < M2VD_DBG_FILE_NUM; k++) { + M2VD_FCLOSE(p->fp_dbg_file[k]); + } + M2VD_FCLOSE(p->fp_dbg_yuv); + + if (p->bitstream_sw_buf) { + mpp_free(p->bitstream_sw_buf); + p->bitstream_sw_buf = NULL; + } + if (p->qp_tab_sw_buf) { + mpp_free(p->qp_tab_sw_buf); + p->qp_tab_sw_buf = NULL; + } + + if (p->input_packet) { + mpp_packet_deinit(&p->input_packet); + } + + if (p->dxva_ctx) { + mpp_free(p->dxva_ctx); + p->dxva_ctx = NULL; + } + if (p->bitread_ctx) { + mpp_free(p->bitread_ctx); + p->bitread_ctx = NULL; + } + + for (k = 0; k < 3; k++) { + mpp_frame_deinit(&p->Framehead[k].f); + } + + if (p) { + mpp_free(p); + } + + m2vd_dbg_func("FUN_O"); + return ret; +} + +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +MPP_RET m2vd_parser_reset(void *ctx) +{ + MPP_RET ret = MPP_OK; + M2VDContext *c = (M2VDContext *)ctx; + M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx; + m2vd_dbg_func("FUN_I"); + if (p->frame_cur->slot_index >= 0) + mpp_buf_slot_clr_flag(p->frame_slots, p->frame_cur->slot_index, + SLOT_CODEC_USE); + + if (p->frame_ref0->slot_index >= 0) { + if (p->frame_ref0->flags) { + mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index, + SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->frame_slots, p->frame_ref0->slot_index, + QUEUE_DISPLAY); + p->frame_ref0->flags = 0; + } + mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref0->slot_index, + SLOT_CODEC_USE); + } + + if (p->frame_ref1->slot_index >= 0) + mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref1->slot_index, + SLOT_CODEC_USE); + + if (p->input_packet) { + mpp_packet_clr_eos(p->input_packet); + } + + p->frame_cur->slot_index = -1; + p->frame_ref0->slot_index = -1; + p->frame_ref1->slot_index = -1; + p->ref_frame_cnt = 0; + p->resetFlag = 1; + p->eos = 0; + p->left_length = 0; + p->vop_header_found = 0; + m2vd_dbg_func("FUN_O"); + return ret; +} + +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +MPP_RET m2vd_parser_flush(void *ctx) +{ + MPP_RET ret = MPP_OK; + M2VDContext *c = (M2VDContext *)ctx; + M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx; + m2vd_dbg_func("FUN_I"); + + if ((p->frame_ref0->slot_index >= 0) && p->frame_ref0->flags) { + mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index, + SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->frame_slots, p->frame_ref0->slot_index, + QUEUE_DISPLAY); + p->frame_ref0->flags = 0; + } + + m2vd_dbg_func("FUN_O"); + return ret; +} + +/*! +*********************************************************************** +* \brief +* control/perform +*********************************************************************** +*/ +MPP_RET m2vd_parser_control(void *ctx, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_OK; + m2vd_dbg_func("FUN_I"); + (void)ctx; + (void)cmd_type; + (void)param; + m2vd_dbg_func("FUN_O"); + return ret; +} + +/*! +*********************************************************************** +* \brief +* prepare +*********************************************************************** +*/ +MPP_RET mpp_m2vd_parser_split(M2VDParserContext *ctx, MppPacket dst, MppPacket src) +{ + MPP_RET ret = MPP_NOK; + M2VDParserContext *p = ctx; + RK_U8 *src_buf = (RK_U8 *)mpp_packet_get_pos(src); + RK_U32 src_len = (RK_U32)mpp_packet_get_length(src); + RK_U32 src_eos = mpp_packet_get_eos(src); + RK_U8 *dst_buf = (RK_U8 *)mpp_packet_get_data(dst); + RK_U32 dst_len = (RK_U32)mpp_packet_get_length(dst); + RK_U32 src_pos = 0; + + if (!p->vop_header_found) { + if ((dst_len < sizeof(p->state)) && + ((p->state & 0x00FFFFFF) == 0x000001)) { + dst_buf[0] = 0; + dst_buf[1] = 0; + dst_buf[2] = 1; + dst_len = 3; + } + + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + + /* + * 0x1b3 : sequence header + * 0x100 : frame header + * we see all 0x1b3 and 0x100 as boundary + */ + if (p->state == SEQUENCE_HEADER_CODE || p->state == PICTURE_START_CODE) { + p->pts = mpp_packet_get_pts(src); + p->dts = mpp_packet_get_dts(src); + p->vop_header_found = 1; + break; + } + } + } + + if (p->vop_header_found) { + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + + if (((p->state & 0x00FFFFFF) == 0x000001) && (src_pos < src_len) && + (src_buf[src_pos] == (SEQUENCE_HEADER_CODE & 0xFF) || + src_buf[src_pos] == (PICTURE_START_CODE & 0xFF))) { + dst_len -= 3; + p->vop_header_found = 0; + ret = MPP_OK; + break; + } + } + } + + if (src_eos && src_pos >= src_len) { + mpp_packet_set_eos(dst); + ret = MPP_OK; + } + + mpp_packet_set_length(dst, dst_len); + mpp_packet_set_pos(src, src_buf + src_pos); + + return ret; +} + +MPP_RET m2vd_parser_prepare(void *ctx, MppPacket pkt, HalDecTask *task) +{ + M2VDContext *c = (M2VDContext *)ctx; + M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx; + RK_U8 *pos = NULL; + size_t length = 0; + RK_U32 eos = 0; + + if (ctx == NULL || pkt == NULL || task == NULL) { + mpp_err_f("found NULL input ctx %p pkt %p task %p\n", ctx, pkt, task); + return MPP_ERR_NULL_PTR; + } + + pos = mpp_packet_get_pos(pkt); + length = mpp_packet_get_length(pkt); + eos = mpp_packet_get_eos(pkt); + + if (eos && !length && !p->left_length) { + task->valid = 0; + task->flags.eos = 1; + m2vd_parser_flush(ctx); + return MPP_OK; + } + + if (p->bitstream_sw_buf == NULL) { + mpp_err("failed to malloc task buffer for hardware with size %d\n", length); + return MPP_ERR_UNKNOW; + } + + mpp_packet_set_length(p->input_packet, p->left_length); + + size_t total_length = MPP_ALIGN(p->left_length + length, 16) + 64; + + if (total_length > p->max_stream_size) { + RK_U8 *dst = NULL; + + do { + p->max_stream_size <<= 1; + } while (total_length > p->max_stream_size); + + dst = mpp_malloc_size(RK_U8, p->max_stream_size); + mpp_assert(dst); + + if (p->left_length > 0) { + memcpy(dst, p->bitstream_sw_buf, p->left_length); + } + mpp_free(p->bitstream_sw_buf); + p->bitstream_sw_buf = dst; + + mpp_packet_set_data(p->input_packet, p->bitstream_sw_buf); + mpp_packet_set_size(p->input_packet, p->max_stream_size); + } + + if (!p->cfg->base.split_parse) { + RK_U32 *val = (RK_U32 *)mpp_packet_get_pos(pkt); + /* if input data is rk format styl skip those 32 byte */ + RK_S32 offset = (VPU_BITSTREAM_START_CODE == val[0]) ? 32 : 0; + memcpy(p->bitstream_sw_buf, pos + offset, length - offset); + + mpp_packet_set_length(p->input_packet, length - offset); + mpp_packet_set_data(p->input_packet, p->bitstream_sw_buf); + mpp_packet_set_size(p->input_packet, p->max_stream_size); + + if (mpp_packet_get_eos(pkt)) + mpp_packet_set_eos(p->input_packet); + + p->pts = mpp_packet_get_pts(pkt); + p->dts = mpp_packet_get_dts(pkt); + task->valid = 1; + mpp_packet_set_length(pkt, 0); + } else { + if (MPP_OK == mpp_m2vd_parser_split(p, p->input_packet, pkt)) { + p->left_length = 0; + task->valid = 1; + } else { + task->valid = 0; + p->left_length = mpp_packet_get_length(p->input_packet); + } + } + + if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) { + mpp_packet_set_extra_data(p->input_packet); + } + + p->eos = mpp_packet_get_eos(p->input_packet); + mpp_packet_set_pts(p->input_packet, p->pts); + mpp_packet_set_dts(p->input_packet, p->dts); + task->input_packet = p->input_packet; + task->flags.eos = p->eos; + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* parser +*********************************************************************** +*/ + +static RK_U32 m2vd_search_header(BitReadCtx_t *bx) +{ + mpp_align_get_bits(bx); + while (m2vd_show_bits(bx, 24) != 0x01) { + mpp_skip_bits(bx, 8); + if (m2vd_get_leftbits(bx) < 32) { + if (M2VD_DBG_SEC_HEADER & m2vd_debug) { + mpp_log("[m2v]: seach_header: str.leftbit()[%d] < 32", m2vd_get_leftbits(bx)); + } + return NO_MORE_STREAM; + } + } + return m2vd_show_bits(bx, 32); +} + +static int m2vd_decode_seq_ext_header(M2VDParserContext *ctx) +{ + BitReadCtx_t *bx = ctx->bitread_ctx; + m2vd_dbg_func("FUN_I"); + ctx->MPEG2_Flag = 1; + ctx->seq_ext_head.profile_and_level_indication = m2vd_read_bits(bx, 8); + ctx->seq_ext_head.progressive_sequence = m2vd_read_bits(bx, 1); + ctx->seq_ext_head.chroma_format = m2vd_read_bits(bx, 2); + if (ctx->seq_ext_head.chroma_format != 1) + return M2VD_DEC_UNSURPORT; + ctx->seq_ext_head.horizontal_size_extension = m2vd_read_bits(bx, 2); + ctx->seq_ext_head.vertical_size_extension = m2vd_read_bits(bx, 2); + ctx->seq_ext_head.bit_rate_extension = m2vd_read_bits(bx, 12); + mpp_skip_bits(bx, 1); + ctx->seq_ext_head.vbv_buffer_size_extension = m2vd_read_bits(bx, 8); + ctx->seq_ext_head.low_delay = m2vd_read_bits(bx, 1); + ctx->seq_ext_head.frame_rate_extension_n = m2vd_read_bits(bx, 2); + ctx->seq_ext_head.frame_rate_extension_d = m2vd_read_bits(bx, 5); + + ctx->seq_head.bit_rate_value |= (ctx->seq_ext_head.bit_rate_extension << 18); + ctx->seq_head.vbv_buffer_size += (ctx->seq_ext_head.vbv_buffer_size_extension << 10); + + m2vd_dbg_func("FUN_O"); + return M2VD_DEC_OK; +} + +static int m2vd_decode_seqdisp_ext_header(M2VDParserContext *ctx) +{ + BitReadCtx_t *bx = ctx->bitread_ctx; + ctx->seq_disp_ext_head.video_format = m2vd_read_bits(bx, 3); + ctx->seq_disp_ext_head.color_description = m2vd_read_bits(bx, 1); + + if (ctx->seq_disp_ext_head.color_description) { + ctx->seq_disp_ext_head.color_primaries = m2vd_read_bits(bx, 8); + ctx->seq_disp_ext_head.transfer_characteristics = m2vd_read_bits(bx, 8); + ctx->seq_disp_ext_head.matrix_coefficients = m2vd_read_bits(bx, 8); + } + + m2vd_read_bits(bx, 14); + mpp_skip_bits(bx, 1); + m2vd_read_bits(bx, 14); + return M2VD_DEC_OK; +} + +static int m2vd_decode_matrix_ext_header(M2VDParserContext *ctx) +{ + RK_U32 load_intra_quantizer_matrix; + RK_U32 load_non_intra_quantizer_matrix; + RK_U32 load_chroma_intra_quantizer_matrix; + RK_U32 load_chroma_non_intra_quantizer_matrix; + RK_U32 i; + BitReadCtx_t *bx = ctx->bitread_ctx; + + load_intra_quantizer_matrix = m2vd_read_bits(bx, 1); + if (load_intra_quantizer_matrix) { + for (i = 0; i < 64; i++) + ctx->seq_head.pIntra_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8); + + } + load_non_intra_quantizer_matrix = m2vd_read_bits(bx, 1); + if (load_non_intra_quantizer_matrix) { + for (i = 0; i < 64; i++) + ctx->seq_head.pInter_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8); + } + load_chroma_intra_quantizer_matrix = m2vd_read_bits(bx, 1); + if (load_chroma_intra_quantizer_matrix) { + return M2VD_DEC_UNSURPORT; + } + load_chroma_non_intra_quantizer_matrix = m2vd_read_bits(bx, 1); + if (load_chroma_non_intra_quantizer_matrix) { + return M2VD_DEC_UNSURPORT; + } + return M2VD_DEC_OK; +} + +static int m2vd_decode_scalable_ext_header(M2VDParserContext *ctx) +{ + /* ISO/IEC 13818-2 section 6.2.2.5: sequence_scalable_extension() header */ + int layer_id; + int lower_layer_prediction_horizontal_size; + int lower_layer_prediction_vertical_size; + int horizontal_subsampling_factor_m; + int horizontal_subsampling_factor_n; + int vertical_subsampling_factor_m; + int vertical_subsampling_factor_n; + int scalable_mode; + BitReadCtx_t *bx = ctx->bitread_ctx; + + /* scalable_mode */ +#define SC_NONE 0 +#define SC_DP 1 +#define SC_SPAT 2 +#define SC_SNR 3 +#define SC_TEMP 4 + + scalable_mode = m2vd_read_bits(bx, 2) + 1; /* add 1 to make SC_DP != SC_NONE */ + + layer_id = m2vd_read_bits(bx, 4); + + if (scalable_mode == SC_SPAT) { + lower_layer_prediction_horizontal_size = m2vd_read_bits(bx, 14); + mpp_skip_bits(bx, 1); + lower_layer_prediction_vertical_size = m2vd_read_bits(bx, 14); + horizontal_subsampling_factor_m = m2vd_read_bits(bx, 5); + horizontal_subsampling_factor_n = m2vd_read_bits(bx, 5); + vertical_subsampling_factor_m = m2vd_read_bits(bx, 5); + vertical_subsampling_factor_n = m2vd_read_bits(bx, 5); + } + + (void)layer_id; + (void)lower_layer_prediction_horizontal_size; + (void)lower_layer_prediction_vertical_size; + (void)horizontal_subsampling_factor_m; + (void)horizontal_subsampling_factor_n; + (void)vertical_subsampling_factor_m; + (void)vertical_subsampling_factor_n; + + + if (scalable_mode == SC_TEMP) + return M2VD_DEC_UNSURPORT; + else + return M2VD_DEC_OK; +} + +static int m2vd_decode_picdisp_ext_header(M2VDParserContext *ctx) +{ + int i; + int number_of_frame_center_offsets; + BitReadCtx_t *bx = ctx->bitread_ctx; + /* based on ISO/IEC 13818-2 section 6.3.12 + (November 1994) Picture display extensions */ + + /* derive number_of_frame_center_offsets */ + if (ctx->seq_ext_head.progressive_sequence) { + if (ctx->pic_code_ext_head.repeat_first_field) { + if (ctx->pic_code_ext_head.top_field_first) + number_of_frame_center_offsets = 3; + else + number_of_frame_center_offsets = 2; + } else { + number_of_frame_center_offsets = 1; + } + } else { + if (ctx->pic_code_ext_head.picture_structure != M2VD_PIC_STRUCT_FRAME) { + number_of_frame_center_offsets = 1; + } else { + if (ctx->pic_code_ext_head.repeat_first_field) + number_of_frame_center_offsets = 3; + else + number_of_frame_center_offsets = 2; + } + } + + /* now parse */ + for (i = 0; i < number_of_frame_center_offsets; i++) { + ctx->pic_disp_ext_head.frame_center_horizontal_offset[i] = m2vd_read_bits(bx, 16); + mpp_skip_bits(bx, 1); + + ctx->pic_disp_ext_head.frame_center_vertical_offset[i] = m2vd_read_bits(bx, 16); + mpp_skip_bits(bx, 1); + } + return M2VD_DEC_OK; +} + +static int m2vd_decode_spatial_ext_header(M2VDParserContext *ctx) +{ + /* ISO/IEC 13818-2 section 6.2.3.5: picture_spatial_scalable_extension() header */ + int lower_layer_temporal_reference; + int lower_layer_horizontal_offset; + int lower_layer_vertical_offset; + int spatial_temporal_weight_code_table_index; + int lower_layer_progressive_frame; + int lower_layer_deinterlaced_field_select; + BitReadCtx_t *bx = ctx->bitread_ctx; + + lower_layer_temporal_reference = m2vd_read_bits(bx, 10); + mpp_skip_bits(bx, 1); + lower_layer_horizontal_offset = m2vd_read_bits(bx, 15); + if (lower_layer_horizontal_offset >= 16384) + lower_layer_horizontal_offset -= 32768; + mpp_skip_bits(bx, 1); + lower_layer_vertical_offset = m2vd_read_bits(bx, 15); + if (lower_layer_vertical_offset >= 16384) + lower_layer_vertical_offset -= 32768; + spatial_temporal_weight_code_table_index = m2vd_read_bits(bx, 2); + lower_layer_progressive_frame = m2vd_read_bits(bx, 1); + lower_layer_deinterlaced_field_select = m2vd_read_bits(bx, 1); + + (void)lower_layer_temporal_reference; + (void)lower_layer_vertical_offset; + (void)spatial_temporal_weight_code_table_index; + (void)lower_layer_progressive_frame; + (void)lower_layer_deinterlaced_field_select; + + return M2VD_DEC_OK; +} + +static int m2vd_decode_pic_ext_header(M2VDParserContext *ctx) +{ + BitReadCtx_t *bx = ctx->bitread_ctx; + ctx->pic_code_ext_head.f_code[0][0] = m2vd_read_bits(bx, 4); + ctx->pic_code_ext_head.f_code[0][1] = m2vd_read_bits(bx, 4); + ctx->pic_code_ext_head.f_code[1][0] = m2vd_read_bits(bx, 4); + ctx->pic_code_ext_head.f_code[1][1] = m2vd_read_bits(bx, 4); + if (ctx->MPEG2_Flag) { + ctx->pic_head.full_pel_forward_vector = ctx->pic_code_ext_head.f_code[0][0]; + ctx->pic_head.forward_f_code = ctx->pic_code_ext_head.f_code[0][1]; + ctx->pic_head.full_pel_backward_vector = ctx->pic_code_ext_head.f_code[1][0]; + ctx->pic_head.backward_f_code = ctx->pic_code_ext_head.f_code[1][1]; + } + + ctx->pic_code_ext_head.intra_dc_precision = m2vd_read_bits(bx, 2); + ctx->pic_code_ext_head.picture_structure = m2vd_read_bits(bx, 2); + if (ctx->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_FRAME) + ctx->pic_code_ext_head.top_field_first = m2vd_read_bits(bx, 1); + else { + m2vd_read_bits(bx, 1); + if ((ctx->pic_head.pre_picture_coding_type != ctx->pic_head.picture_coding_type) && + (ctx->pic_head.pre_picture_coding_type != M2VD_CODING_TYPE_I)) { + if (ctx->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) + ctx->top_first_cnt++; + else + ctx->bottom_first_cnt++; + } + if (ctx->top_first_cnt >= ctx->bottom_first_cnt) + ctx->pic_code_ext_head.top_field_first = 1; + else + ctx->pic_code_ext_head.top_field_first = 0; + } + ctx->pic_code_ext_head.frame_pred_frame_dct = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.concealment_motion_vectors = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.q_scale_type = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.intra_vlc_format = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.alternate_scan = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.repeat_first_field = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.chroma_420_type = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.progressive_frame = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.composite_display_flag = m2vd_read_bits(bx, 1); + if (ctx->pic_code_ext_head.composite_display_flag) { + ctx->pic_code_ext_head.v_axis = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.field_sequence = m2vd_read_bits(bx, 3); + ctx->pic_code_ext_head.sub_carrier = m2vd_read_bits(bx, 1); + ctx->pic_code_ext_head.burst_amplitude = m2vd_read_bits(bx, 7); + ctx->pic_code_ext_head.sub_carrier_phase = m2vd_read_bits(bx, 8); + } + return M2VD_DEC_OK; +} + +static inline int m2vd_decode_temp_ext_header(void) +{ + return M2VD_DEC_UNSURPORT; +} + +static int m2vd_decode_copyright_ext_header(M2VDParserContext *ctx) +{ + int copyright_flag; + int copyright_identifier; + int original_or_copy; + int copyright_number_1; + int copyright_number_2; + int copyright_number_3; + int reserved_data; + BitReadCtx_t *bx = ctx->bitread_ctx; + + copyright_flag = m2vd_read_bits(bx, 1); + copyright_identifier = m2vd_read_bits(bx, 8); + original_or_copy = m2vd_read_bits(bx, 1); + + /* reserved */ + reserved_data = m2vd_read_bits(bx, 7); + + mpp_skip_bits(bx, 1); + copyright_number_1 = m2vd_read_bits(bx, 20); + mpp_skip_bits(bx, 1); + copyright_number_2 = m2vd_read_bits(bx, 22); + mpp_skip_bits(bx, 1); + copyright_number_3 = m2vd_read_bits(bx, 22); + + (void)copyright_flag; + (void)copyright_identifier; + (void)original_or_copy; + (void)copyright_number_1; + (void)copyright_number_2; + (void)copyright_number_3; + (void)reserved_data; + + return M2VD_DEC_OK; +} + +static int m2vd_decode_ext_header(M2VDParserContext *ctx) +{ + RK_U32 code; + RK_U32 ext_ID; + int result; + BitReadCtx_t *bx = ctx->bitread_ctx; + + code = m2vd_search_header(bx); + + if (M2VD_DBG_SEC_HEADER & m2vd_debug) { + mpp_log("[m2v]: decoder_ext_header : seach_header return code: %#03x", code); + } + while (code == EXTENSION_START_CODE || code == USER_DATA_START_CODE) { + if (code == EXTENSION_START_CODE) { + mpp_skip_bits(bx, 32); + ext_ID = m2vd_read_bits(bx, 4); + if (M2VD_DBG_SEC_HEADER & m2vd_debug) { + mpp_log("[m2v]: decoder_ext_header : ext_ID: %d", ext_ID); + } + switch (ext_ID) { + case SEQUENCE_EXTENSION_ID: + result = m2vd_decode_seq_ext_header(ctx); + break; + case SEQUENCE_DISPLAY_EXTENSION_ID: + result = m2vd_decode_seqdisp_ext_header(ctx); + break; + case QUANT_MATRIX_EXTENSION_ID: + result = m2vd_decode_matrix_ext_header(ctx); + break; + case SEQUENCE_SCALABLE_EXTENSION_ID: + result = m2vd_decode_scalable_ext_header(ctx); + break; + case PICTURE_DISPLAY_EXTENSION_ID: + result = m2vd_decode_picdisp_ext_header(ctx); + break; + case PICTURE_CODING_EXTENSION_ID: + result = m2vd_decode_pic_ext_header(ctx); + break; + case PICTURE_SPATIAL_SCALABLE_EXTENSION_ID: + result = m2vd_decode_spatial_ext_header(ctx); + break; + case PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID: + result = m2vd_decode_temp_ext_header(); + break; + case COPYRIGHT_EXTENSION_ID: + result = m2vd_decode_copyright_ext_header(ctx); + break; + case NO_MORE_STREAM: + break; + default: + break; + } + + if (M2VD_DBG_SEC_HEADER & m2vd_debug) { + mpp_log("[m2v]: decoder_ext_header result: %d", result); + } + if (result) + return result; + } else { + mpp_skip_bits(bx, 32); + } + code = m2vd_search_header(bx); + } + + return MPP_OK; +} + +static int m2vd_decode_gop_header(M2VDParserContext *ctx) +{ + BitReadCtx_t *bx = ctx->bitread_ctx; + + ctx->gop_head.drop_flag = m2vd_read_bits(bx, 1); + ctx->gop_head.hour = m2vd_read_bits(bx, 5); + ctx->gop_head.minute = m2vd_read_bits(bx, 6); + + mpp_skip_bits(bx, 1); + + ctx->gop_head.sec = m2vd_read_bits(bx, 6); + ctx->gop_head.frame = m2vd_read_bits(bx, 6); + ctx->gop_head.closed_gop = m2vd_read_bits(bx, 1); + ctx->gop_head.broken_link = m2vd_read_bits(bx, 1); + + return m2vd_decode_ext_header(ctx); +} + +static int m2vd_decode_seq_header(M2VDParserContext *ctx) +{ + RK_U32 i; + RK_S32 pre_frame_rate_code = ctx->seq_head.frame_rate_code; + BitReadCtx_t *bx = ctx->bitread_ctx; + RK_U32 width = m2vd_read_bits(bx, 12); + RK_U32 height = m2vd_read_bits(bx, 12); + + ctx->display_width = width; + ctx->display_height = height; + + height = MPP_ALIGN(height, 16); + width = MPP_ALIGN(width, 16); + + if (ctx->seq_head.decode_width && ctx->seq_head.decode_height) { + if (width != ctx->seq_head.decode_width || + height != ctx->seq_head.decode_height) + ctx->info_changed = 1; + } + + ctx->seq_head.decode_width = width; + ctx->seq_head.decode_height = height; + ctx->seq_head.aspect_ratio_information = m2vd_read_bits(bx, 4); + ctx->seq_head.frame_rate_code = m2vd_read_bits(bx, 4); + if (!ctx->frame_period || pre_frame_rate_code != ctx->seq_head.frame_rate_code) + ctx->frame_period = frame_period_Table_27M[ctx->seq_head.frame_rate_code]; + ctx->seq_head.bit_rate_value = m2vd_read_bits(bx, 18); + mpp_skip_bits(bx, 1); + ctx->seq_head.vbv_buffer_size = m2vd_read_bits(bx, 10); + ctx->seq_head.constrained_parameters_flag = m2vd_read_bits(bx, 1); + ctx->seq_head.load_intra_quantizer_matrix = m2vd_read_bits(bx, 1); + if (ctx->seq_head.load_intra_quantizer_matrix) { + for (i = 0; i < 64; i++) + ctx->seq_head.pIntra_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8); + } else { + for (i = 0; i < 64; i++) + ctx->seq_head.pIntra_table[i] = intraDefaultQMatrix[i]; + } + + ctx->seq_head.load_non_intra_quantizer_matrix = m2vd_read_bits(bx, 1); + if (ctx->seq_head.load_non_intra_quantizer_matrix) { + for (i = 0; i < 64; i++) + ctx->seq_head.pInter_table[scanOrder[0][i]] = (unsigned char)m2vd_read_bits(bx, 8); + } else { + for (i = 0; i < 64; i++) + ctx->seq_head.pInter_table[i] = 16; + } + + return m2vd_decode_ext_header(ctx); +} + +static int m2vd_extra_bit_information(M2VDParserContext *ctx) +{ + BitReadCtx_t *bx = ctx->bitread_ctx; + while (m2vd_read_bits(bx, 1)) { + mpp_skip_bits(bx, 8); + } + return M2VD_DEC_OK; +} + +static int m2vd_decode_pic_header(M2VDParserContext *ctx) +{ + BitReadCtx_t *bx = ctx->bitread_ctx; + ctx->pic_head.temporal_reference = m2vd_read_bits(bx, 10); + ctx->pic_head.picture_coding_type = m2vd_read_bits(bx, 3); + ctx->pic_head.vbv_delay = m2vd_read_bits(bx, 16); + if (ctx->pic_head.temporal_reference > 50) { + ctx->pic_head.temporal_reference = ctx->pretemporal_reference; + } + //if ((maxFrame_inGOP < temporal_reference)&&(temporal_reference<60)) + // maxFrame_inGOP = temporal_reference; + if (((RK_S32)ctx->maxFrame_inGOP < ctx->pic_head.temporal_reference) && (ctx->pic_head.temporal_reference < 60)) + ctx->maxFrame_inGOP = ctx->pic_head.temporal_reference; + + + if (ctx->pic_head.picture_coding_type == M2VD_CODING_TYPE_P || + ctx->pic_head.picture_coding_type == M2VD_CODING_TYPE_B) { + ctx->pic_head.full_pel_forward_vector = m2vd_read_bits(bx, 1); + ctx->pic_head.forward_f_code = m2vd_read_bits(bx, 3); + } + if (ctx->pic_head.picture_coding_type == M2VD_CODING_TYPE_B) { + ctx->pic_head.full_pel_backward_vector = m2vd_read_bits(bx, 1); + ctx->pic_head.backward_f_code = m2vd_read_bits(bx, 3); + } + + m2vd_extra_bit_information(ctx); + + return m2vd_decode_ext_header(ctx); +} + +static MPP_RET m2vd_decode_head(M2VDParserContext *ctx) +{ + RK_U32 code; + int ret = 0; + BitReadCtx_t *bx = ctx->bitread_ctx; + + m2vd_dbg_func("FUN_I"); + while (1) { + code = m2vd_search_header(bx); + if (M2VD_DBG_SEC_HEADER & m2vd_debug) { + mpp_log("[m2v]: decoder_header : seach_header return code: 0x%3x", code); + } + if (code == NO_MORE_STREAM) + return M2VD_DEC_FILE_END; + code = m2vd_read_bits(bx, 32); + + switch (code) { + case SEQUENCE_HEADER_CODE: + ret = m2vd_decode_seq_header(ctx); + if (!ret) { + MppPacket pkt = ctx->input_packet; + if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) { + ctx->mExtraHeaderDecFlag = 1; + } else { + ctx->mHeaderDecFlag = 1; + } + } + break; + case GROUP_START_CODE: + ret = m2vd_decode_gop_header(ctx); + break; + case PICTURE_START_CODE: + ret = m2vd_decode_pic_header(ctx); + ret = M2VD_DEC_PICHEAD_OK; + break; + case SEQUENCE_END_CODE: + ret = M2VD_DEC_STREAM_END; + break; + default: + if (M2VD_DBG_SEC_HEADER & m2vd_debug) { + mpp_log("code=%x,leftbit=%d", code, m2vd_get_leftbits(bx)); + } + break; + } + if (ret) + break; + } + m2vd_dbg_func("FUN_O"); + + return ret; +} + +static MPP_RET m2v_update_ref_frame(M2VDParserContext *p, RK_S32 force) +{ + //push frame + if (force || (p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_FRAME) || + ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) && p->pic_code_ext_head.top_field_first ) || + ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) && (!p->pic_code_ext_head.top_field_first))) { + if (p->frame_cur->picCodingType == M2VD_CODING_TYPE_B) { + mpp_buf_slot_set_flag(p->frame_slots, p->frame_cur->slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->frame_slots, p->frame_cur->slot_index, QUEUE_DISPLAY); + mpp_buf_slot_clr_flag(p->frame_slots, p->frame_cur->slot_index, SLOT_CODEC_USE); + p->frame_cur->slot_index = -1; + } else if (p->frame_cur->picCodingType != 0xffffffff) { + M2VDFrameHead *tmpHD = NULL; + p->ref_frame_cnt++; + if (p->frame_ref0->slot_index >= 0) { + if (p->frame_ref0->flags) { + mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->frame_slots, p->frame_ref0->slot_index, QUEUE_DISPLAY); + p->frame_ref0->flags = 0; + } + + if (p->info_changed) { + mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref0->slot_index, SLOT_CODEC_USE); + p->frame_ref0->slot_index = -1; + p->info_changed = 0; + } + } + + if (p->frame_ref1->slot_index >= 0) { + mpp_buf_slot_clr_flag(p->frame_slots, p->frame_ref1->slot_index, SLOT_CODEC_USE); + p->frame_ref1->slot_index = -1; + } + tmpHD = p->frame_ref1; + p->frame_ref1 = p->frame_ref0; + p->frame_ref0 = p->frame_cur; + p->frame_cur = tmpHD; + } + } + + return MPP_OK; +} + +static MPP_RET m2vd_alloc_frame(M2VDParserContext *ctx) +{ + M2VDHeadPic *pic_head = &ctx->pic_head; + M2VDHeadPicCodeExt *pic_code_ext_head = &ctx->pic_code_ext_head; + RK_U64 pts_27M = ctx->pts; + + if (ctx->resetFlag && pic_head->picture_coding_type != M2VD_CODING_TYPE_I) { + mpp_log("[m2v]: resetFlag[%d] && picture_coding_type[%d] != I_TYPE", ctx->resetFlag, pic_head->picture_coding_type); + return MPP_NOK; + } + + ctx->resetFlag = 0; + + if ((ctx->ref_frame_cnt < 2) && (pic_head->picture_coding_type == M2VD_CODING_TYPE_B)) { + mpp_log("[m2v]: (ref_frame_cnt[%d] < 2) && (frame_cur->picCodingType[%d] == B_TYPE)", + ctx->ref_frame_cnt, pic_head->picture_coding_type); + return MPP_NOK; + } + + if ((pic_code_ext_head->picture_structure == M2VD_PIC_STRUCT_FRAME ) || + ((pic_code_ext_head->picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) && pic_code_ext_head->top_field_first) || + ((pic_code_ext_head->picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) && (!pic_code_ext_head->top_field_first))) { + RK_S64 frm_pts = 0; + RK_U32 frametype = 0; + + if (ctx->pts_is_90K) { + pts_27M = ctx->pts * 300; + } else { + pts_27M = ctx->pts * 27; + } + + if (ctx->frame_cur->slot_index >= 0) { + MppFrame frame = NULL; + + mpp_buf_slot_get_prop(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_FRAME_PTR, &frame); + if (ctx->cfg->base.disable_error) + mpp_frame_set_discard(frame, 1); + else + mpp_frame_set_errinfo(frame, 1); + + mpp_log("[m2v]: miss match field order at ref_frame_cnt[%d] picture_structure %d top_field_first %d\n", + ctx->ref_frame_cnt, pic_head->picture_coding_type, pic_code_ext_head->top_field_first); + + m2v_update_ref_frame(ctx, 1); + } + + if (ctx->pre_pts_27M != pts_27M) { + RK_S64 tmp_frame_period; + + if (ctx->group_frm_cnt) { + ctx->group_frm_cnt = ctx->group_frm_cnt + pic_head->temporal_reference; + } else if (pic_head->temporal_reference == (RK_S32)ctx->prechange_temporal_ref) + ctx->group_frm_cnt = ctx->max_temporal_reference + 1; + else if (pic_head->temporal_reference) + ctx->group_frm_cnt = pic_head->temporal_reference - ctx->prechange_temporal_ref; + else + ctx->group_frm_cnt = ctx->max_temporal_reference - ctx->prechange_temporal_ref + 1; + + tmp_frame_period = pts_27M - ctx->pre_pts_27M; + + if ((pts_27M > ctx->pre_pts_27M) + && (pic_head->temporal_reference > (RK_S32)ctx->prechange_temporal_ref)) { + RK_S32 theshold_frame_period = tmp_frame_period * 2; + RK_S32 last_frame_period = ctx->preframe_period ? ctx->preframe_period : ctx->frame_period; + RK_S32 predict_frame_period = + (pic_head->temporal_reference - ctx->prechange_temporal_ref) * last_frame_period; + if (theshold_frame_period < predict_frame_period) { + // check pts is 90KHZ raw pts + RK_S64 diff_90K_frame_period = tmp_frame_period * 1000 / 90 - predict_frame_period; + + if (!ctx->pts_is_90K && llabs(diff_90K_frame_period) <= 300) { + mpp_log("judge result pts is base in 90KHZ.\n"); + ctx->pts_is_90K = 1; + // pre pts is 1MHZ, so need convert to 90KHZ + pts_27M = ctx->pre_pts_27M * 1000 / 90 + predict_frame_period; + } else { + pts_27M = ctx->pre_pts_27M + predict_frame_period; + } + tmp_frame_period = predict_frame_period; + } + } + + if ((pts_27M > ctx->pre_pts_27M) && (ctx->group_frm_cnt > 0)) { + tmp_frame_period = tmp_frame_period / ctx->group_frm_cnt; + // judge frame rate changed + if ((tmp_frame_period > MIN_FRAME_PERIOD_27M) + && (tmp_frame_period < MAX_FRAME_PERIOD_27M) && + (llabs(ctx->frame_period - tmp_frame_period) > MAX_FRAME_PERIOD_DIFF)) { + if (llabs(ctx->preframe_period - tmp_frame_period) > MAX_FRAME_PERIOD_DIFF) { + ctx->preframe_period = tmp_frame_period; + } else { + ctx->frame_period = tmp_frame_period; + ctx->preframe_period = 0; + } + } else { + ctx->preframe_period = 0; + } + } + + ctx->group_start_time_27M = pts_27M - pic_head->temporal_reference * ctx->frame_period; + if (ctx->group_start_time_27M <= -ctx->frame_period) + ctx->group_start_time_27M = 0; + ctx->pre_pts_27M = pts_27M; + ctx->prechange_temporal_ref = pic_head->temporal_reference; + ctx->group_frm_cnt = 0; + } else if ((RK_S32)ctx->pretemporal_reference > pic_head->temporal_reference + 5) { + ctx->group_start_time_27M += (ctx->max_temporal_reference + 1) * ctx->frame_period; + ctx->group_frm_cnt = ctx->max_temporal_reference - ctx->prechange_temporal_ref + 1; + ctx->max_temporal_reference = 0; + } + if ((RK_S32)ctx->pretemporal_reference > pic_head->temporal_reference + 5) + ctx->max_temporal_reference = 0; + if (pic_head->temporal_reference > (RK_S32)ctx->max_temporal_reference) + ctx->max_temporal_reference = pic_head->temporal_reference; + ctx->pretemporal_reference = pic_head->temporal_reference; + frm_pts = ctx->group_start_time_27M; + frm_pts += pic_head->temporal_reference * ctx->frame_period; + if (frm_pts < 0) { + frm_pts = 0; + } + if (ctx->pts_is_90K) { + frm_pts = frm_pts / 300; + } else { + frm_pts = frm_pts / 27; + } + + /* + mpp_log("picture_coding_type %d picture_structure %d top_field_first %d frame slot %d ref_frame_cnt %d pts %lld\n", + pic_head->picture_coding_type, pic_code_ext_head->picture_structure, + pic_code_ext_head->top_field_first, ctx->frame_cur->slot_index, ctx->ref_frame_cnt, frm_pts); + */ + + //base.Current_frame->ShowTime = Time;//Video_Bitsream.Slice_Time.low_part; + //!< mark current slot error + if (pic_head->picture_coding_type != M2VD_CODING_TYPE_I + && pic_head->pre_picture_coding_type == pic_head->picture_coding_type) { + if ((pic_head->temporal_reference - pic_head->pre_temporal_reference > 3) + || (pic_head->temporal_reference - pic_head->pre_temporal_reference < -3)) { + mpp_frame_set_errinfo(ctx->frame_cur->f, 1); + } else { + mpp_frame_set_errinfo(ctx->frame_cur->f, 0); + } + } + pic_head->pre_temporal_reference = pic_head->temporal_reference; + pic_head->pre_picture_coding_type = pic_head->picture_coding_type; + ctx->frame_cur->picCodingType = pic_head->picture_coding_type; + + mpp_frame_set_width(ctx->frame_cur->f, ctx->display_width); + mpp_frame_set_height(ctx->frame_cur->f, ctx->display_height); + mpp_frame_set_hor_stride(ctx->frame_cur->f, 0); + mpp_frame_set_ver_stride(ctx->frame_cur->f, 0); + mpp_frame_set_errinfo(ctx->frame_cur->f, 0); + mpp_frame_set_pts(ctx->frame_cur->f, frm_pts); + mpp_frame_set_dts(ctx->frame_cur->f, ctx->dts); + ctx->frame_cur->flags = M2V_OUT_FLAG; + + if (ctx->seq_ext_head.progressive_sequence) { + frametype = MPP_FRAME_FLAG_FRAME; + } else { + frametype = MPP_FRAME_FLAG_PAIRED_FIELD; + if (pic_code_ext_head->top_field_first) + frametype |= MPP_FRAME_FLAG_TOP_FIRST; + else + frametype |= MPP_FRAME_FLAG_BOT_FIRST; + } + if ((ctx->cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) && + frametype == MPP_FRAME_FLAG_FRAME) + frametype = MPP_FRAME_FLAG_DEINTERLACED; + + mpp_frame_set_mode(ctx->frame_cur->f, frametype); + + if (ctx->seq_head.aspect_ratio_information >= 0 && ctx->seq_head.aspect_ratio_information < 16) + mpp_frame_set_sar(ctx->frame_cur->f, mpeg2_aspect[ctx->seq_head.aspect_ratio_information]); + + //alloc frame space + mpp_buf_slot_get_unused(ctx->frame_slots, &ctx->frame_cur->slot_index); + mpp_buf_slot_set_prop(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_FRAME, ctx->frame_cur->f); + mpp_buf_slot_set_flag(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_HAL_OUTPUT); + } else { + if (ctx->frame_cur->slot_index >= 0) + mpp_buf_slot_set_flag(ctx->frame_slots, ctx->frame_cur->slot_index, SLOT_HAL_OUTPUT); + else { + /* + * frame alloc failed cause by stream error, such as: + * receive top field while top_field_first = 0, + * or bottom filed while top_field_first = 1; + * mark resetFlag to wait for another I frame + */ + mpp_log("frame alloc failed, need reset\n"); + ctx->resetFlag = 1; + return MPP_NOK; + } + } + + return MPP_OK; +} + +static MPP_RET m2vd_convert_to_dxva(M2VDParserContext *p) +{ + MPP_RET ret = MPP_OK; + m2vd_dbg_func("FUN_I"); + M2VDDxvaParam *dst = p->dxva_ctx; + M2VDFrameHead *pfw = p->frame_ref1; + M2VDFrameHead *pbw = p->frame_ref0; + BitReadCtx_t *bx = p->bitread_ctx; + RK_U32 i = 0; + RK_U32 error_info = 0; + + RK_S32 readbits = m2vd_get_readbits(bx); + + dst->seq.decode_width = p->seq_head.decode_width; + dst->seq.decode_height = p->seq_head.decode_height; + dst->seq.aspect_ratio_information = p->seq_head.aspect_ratio_information; + dst->seq.frame_rate_code = p->seq_head.frame_rate_code; + dst->seq.bit_rate_value = p->seq_head.bit_rate_value; + dst->seq.vbv_buffer_size = p->seq_head.vbv_buffer_size; + dst->seq.constrained_parameters_flag = p->seq_head.constrained_parameters_flag; + dst->seq.load_intra_quantizer_matrix = p->seq_head.load_intra_quantizer_matrix; + dst->seq.load_non_intra_quantizer_matrix = p->seq_head.load_non_intra_quantizer_matrix; + + dst->seq_ext.profile_and_level_indication = p->seq_ext_head.profile_and_level_indication; + dst->seq_ext.progressive_sequence = p->seq_ext_head.progressive_sequence; + dst->seq_ext.chroma_format = p->seq_ext_head.chroma_format; + dst->seq_ext.low_delay = p->seq_ext_head.low_delay; + dst->seq_ext.frame_rate_extension_n = p->seq_ext_head.frame_rate_extension_n; + dst->seq_ext.frame_rate_extension_d = p->seq_ext_head.frame_rate_extension_d; + + + dst->gop.drop_flag = p->gop_head.drop_flag; + dst->gop.hour = p->gop_head.hour; + dst->gop.minute = p->gop_head.minute; + dst->gop.sec = p->gop_head.sec; + dst->gop.frame = p->gop_head.frame; + dst->gop.closed_gop = p->gop_head.closed_gop; + dst->gop.broken_link = p->gop_head.broken_link; + + + dst->pic.temporal_reference = p->pic_head.temporal_reference; + dst->pic.picture_coding_type = p->pic_head.picture_coding_type; + dst->pic.pre_picture_coding_type = p->pic_head.pre_picture_coding_type; + dst->pic.vbv_delay = p->pic_head.vbv_delay; + dst->pic.full_pel_forward_vector = p->pic_head.full_pel_forward_vector; + dst->pic.forward_f_code = p->pic_head.forward_f_code; + dst->pic.full_pel_backward_vector = p->pic_head.full_pel_backward_vector; + dst->pic.backward_f_code = p->pic_head.backward_f_code; + dst->pic.pre_temporal_reference = p->pic_head.pre_temporal_reference; + + dst->seq_disp_ext.video_format = p->seq_disp_ext_head.video_format; + dst->seq_disp_ext.color_description = p->seq_disp_ext_head.color_description; + dst->seq_disp_ext.color_primaries = p->seq_disp_ext_head.color_primaries; + dst->seq_disp_ext.transfer_characteristics = p->seq_disp_ext_head.transfer_characteristics; + dst->seq_disp_ext.matrix_coefficients = p->seq_disp_ext_head.matrix_coefficients; + + memcpy(dst->pic_code_ext.f_code, p->pic_code_ext_head.f_code, 2 * 2 * sizeof(RK_S32)); + dst->pic_code_ext.intra_dc_precision = p->pic_code_ext_head.intra_dc_precision; + dst->pic_code_ext.picture_structure = p->pic_code_ext_head.picture_structure; + dst->pic_code_ext.top_field_first = p->pic_code_ext_head.top_field_first; + dst->pic_code_ext.frame_pred_frame_dct = p->pic_code_ext_head.frame_pred_frame_dct; + dst->pic_code_ext.concealment_motion_vectors = p->pic_code_ext_head.concealment_motion_vectors; + dst->pic_code_ext.q_scale_type = p->pic_code_ext_head.q_scale_type; + dst->pic_code_ext.intra_vlc_format = p->pic_code_ext_head.intra_vlc_format; + dst->pic_code_ext.alternate_scan = p->pic_code_ext_head.alternate_scan; + dst->pic_code_ext.repeat_first_field = p->pic_code_ext_head.repeat_first_field; + dst->pic_code_ext.chroma_420_type = p->pic_code_ext_head.chroma_420_type; + dst->pic_code_ext.progressive_frame = p->pic_code_ext_head.progressive_frame; + dst->pic_code_ext.composite_display_flag = p->pic_code_ext_head.composite_display_flag; + dst->pic_code_ext.v_axis = p->pic_code_ext_head.v_axis; + dst->pic_code_ext.field_sequence = p->pic_code_ext_head.field_sequence; + dst->pic_code_ext.sub_carrier = p->pic_code_ext_head.sub_carrier; + dst->pic_code_ext.burst_amplitude = p->pic_code_ext_head.burst_amplitude; + dst->pic_code_ext.sub_carrier_phase = p->pic_code_ext_head.sub_carrier_phase; + + memcpy(dst->pic_disp_ext.frame_center_horizontal_offset, p->pic_disp_ext_head.frame_center_horizontal_offset, 3 * sizeof(RK_S32)); + memcpy(dst->pic_disp_ext.frame_center_vertical_offset, p->pic_disp_ext_head.frame_center_vertical_offset, 3 * sizeof(RK_S32)); + + dst->bitstream_length = p->frame_size - ((readbits >> 3) & (~7)); + dst->bitstream_offset = ((readbits >> 3) & (~7)); + dst->bitstream_start_bit = readbits & 0x3f; + dst->qp_tab = p->qp_tab_sw_buf; + dst->CurrPic.Index7Bits = p->frame_cur->slot_index; + p->cur_slot_index = p->frame_cur->slot_index; + + if (p->frame_ref0->slot_index < 0) + pbw = p->frame_cur; + + if (p->frame_ref1->slot_index < 0) + pfw = pbw; + + for (i = 0; i < 4; i++) { + dst->frame_refs[i].bPicEntry = 0xff; + } + if (p->pic_head.picture_coding_type == M2VD_CODING_TYPE_B) { + MppFrame frame0 = NULL; + MppFrame frame1 = NULL; + dst->frame_refs[0].Index7Bits = pfw->slot_index; + dst->frame_refs[1].Index7Bits = pfw->slot_index; + dst->frame_refs[2].Index7Bits = pbw->slot_index; + dst->frame_refs[3].Index7Bits = pbw->slot_index; + mpp_buf_slot_get_prop(p->frame_slots, pfw->slot_index, SLOT_FRAME_PTR, &frame0); + mpp_buf_slot_get_prop(p->frame_slots, pbw->slot_index, SLOT_FRAME_PTR, &frame1); + error_info = mpp_frame_get_errinfo(frame0) | mpp_frame_get_errinfo(frame1); + } else { + MppFrame frame = NULL; + if ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_FRAME) || + ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) && p->pic_code_ext_head.top_field_first) || + ((p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) && (!p->pic_code_ext_head.top_field_first))) { + dst->frame_refs[0].Index7Bits = pbw->slot_index; + dst->frame_refs[1].Index7Bits = pbw->slot_index; + } else if (p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) { + dst->frame_refs[0].Index7Bits = pbw->slot_index; + dst->frame_refs[1].Index7Bits = p->frame_cur->slot_index; + } else if (p->pic_code_ext_head.picture_structure == M2VD_PIC_STRUCT_BOTTOM_FIELD) { + dst->frame_refs[0].Index7Bits = p->frame_cur->slot_index; + dst->frame_refs[1].Index7Bits = pbw->slot_index; + } + dst->frame_refs[2].Index7Bits = p->frame_cur->slot_index; + dst->frame_refs[3].Index7Bits = p->frame_cur->slot_index; + mpp_buf_slot_get_prop(p->frame_slots, pbw->slot_index, SLOT_FRAME_PTR, &frame); + error_info = mpp_frame_get_errinfo(frame); + } + if (p->frame_cur->picCodingType == M2VD_CODING_TYPE_I) { + error_info = 0; + } + dst->seq_ext_head_dec_flag = p->MPEG2_Flag; + { + MppFrame frame = NULL; + mpp_buf_slot_get_prop(p->frame_slots, p->cur_slot_index, SLOT_FRAME_PTR, &frame); + mpp_frame_set_errinfo(frame, error_info); + } + m2vd_dbg_func("FUN_O"); + return ret; +} + +MPP_RET m2vd_parser_parse(void *ctx, HalDecTask *in_task) +{ + MPP_RET ret = MPP_OK; + int rev = 0; + M2VDContext *c = (M2VDContext *)ctx; + M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx; + m2vd_dbg_func("FUN_I"); + + M2VD_CHK_I(in_task->valid); + + in_task->valid = 0; + + p->flush_dpb_eos = 0; + + p->frame_size = (RK_U32)mpp_packet_get_length(in_task->input_packet); + + mpp_set_bitread_ctx(p->bitread_ctx, p->bitstream_sw_buf, p->frame_size); + + rev = m2vd_decode_head(p); + + if (!p->mHeaderDecFlag) { + if (p->mExtraHeaderDecFlag && + p->pic_head.picture_coding_type == M2VD_CODING_TYPE_I) { + p->mHeaderDecFlag = 1; + if (M2VD_DBG_SEC_HEADER & m2vd_debug) + mpp_log("[m2v]: use extra data sequence header"); + } else { + if (M2VD_DBG_SEC_HEADER & m2vd_debug) + mpp_log("[m2v]: !mHeaderDecFlag"); + goto __FAILED; + } + } + + if (p->seq_head.decode_width > 1920 || p->seq_head.decode_height > 1088) { + mpp_err("Warning: unsupport larger than 1920x1088\n"); + goto __FAILED; + } + + p->mb_width = (p->seq_head.decode_width + 15) >> 4; + p->mb_height = (p->seq_head.decode_height + 15) >> 4; + + if (rev < M2VD_DEC_OK) { + if (M2VD_DBG_SEC_HEADER & m2vd_debug) { + mpp_log("decoder_header error rev %d", rev); + } + goto __FAILED; + } + + if (rev == M2VD_DEC_PICHEAD_OK) { + if (m2vd_alloc_frame(p)) { + goto __FAILED; + } + m2vd_convert_to_dxva(p); + in_task->syntax.data = (void *)p->dxva_ctx; + in_task->syntax.number = sizeof(M2VDDxvaParam); + in_task->output = p->frame_cur->slot_index; + p->pic_head.pre_picture_coding_type = p->pic_head.picture_coding_type; + + if (p->frame_ref0->slot_index >= 0 && + (p->frame_ref0->slot_index != p->frame_cur->slot_index)) { + mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref0->slot_index, SLOT_HAL_INPUT); + in_task->refer[0] = p->frame_ref0->slot_index; + } + + if (p->frame_ref1->slot_index >= 0 && (p->frame_ref1->slot_index != p->frame_cur->slot_index)) { + mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref1->slot_index, SLOT_HAL_INPUT); + in_task->refer[1] = p->frame_ref1->slot_index; + } + + MppFrame frame = NULL; + mpp_buf_slot_get_prop(p->frame_slots, p->cur_slot_index, SLOT_FRAME_PTR, &frame); + mpp_frame_set_poc(frame, p->pic_head.temporal_reference); + + if (p->dxva_ctx->seq_disp_ext.color_description) { + mpp_frame_set_color_primaries(frame, p->dxva_ctx->seq_disp_ext.color_primaries); + mpp_frame_set_color_trc(frame, p->dxva_ctx->seq_disp_ext.transfer_characteristics); + mpp_frame_set_colorspace(frame, p->dxva_ctx->seq_disp_ext.matrix_coefficients); + } else { + mpp_frame_set_color_primaries(frame, MPP_FRAME_PRI_UNSPECIFIED); + mpp_frame_set_color_trc(frame, MPP_FRAME_TRC_UNSPECIFIED); + mpp_frame_set_colorspace(frame, MPP_FRAME_SPC_UNSPECIFIED); + } + + in_task->valid = 1; + m2v_update_ref_frame(p, 0); + } + +__FAILED: + if (p->eos) + m2vd_parser_flush(ctx); + + m2vd_dbg_func("FUN_O"); + + return ret; +} + +MPP_RET m2vd_parser_callback(void *ctx, void *errinfo) +{ + MPP_RET ret = MPP_OK; + M2VDContext *c = (M2VDContext *)ctx; + M2VDParserContext *p = (M2VDParserContext *)c->parse_ctx; + MppFrame frame = NULL; + (void)errinfo; + + m2vd_dbg_func("FUN_I"); + mpp_buf_slot_get_prop(p->frame_slots, p->cur_slot_index, SLOT_FRAME_PTR, &frame); + mpp_frame_set_errinfo(frame, 1); + m2vd_dbg_func("FUN_O"); + + return ret; +} diff --git a/mpp/codec/dec/m2v/m2vd_parser.h b/mpp/codec/dec/m2v/m2vd_parser.h new file mode 100644 index 000000000..90df5b695 --- /dev/null +++ b/mpp/codec/dec/m2v/m2vd_parser.h @@ -0,0 +1,310 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file m2vd_parser.h + * @brief + * @author lks(lks@rock-chips.com) + + * @version 1.0.0 + * @history + * 2015.7.15 : Create + */ + +#ifndef M2VD_PARSER_H +#define M2VD_PARSER_H + +#include "mpp_mem.h" +#include "mpp_bitread.h" + +#include "parser_api.h" +#include "m2vd_syntax.h" +#include "m2vd_com.h" + +#define M2VD_SKIP_ERROR_FRAME_EN 1 +#define M2VD_DEC_OK 0 +#define M2VD_IFNO_CHG 0x10 +#define M2VD_DEC_UNSURPORT -1 +#define M2VD_DEC_MEMORY_FAIL -2 +#define M2VD_DEC_FILE_END -3 +#define M2VD_HW_DEC_UNKNOW_ERROR -4 +#define M2VD_DEC_PICHEAD_OK 1 +#define M2VD_DEC_STREAM_END 2 + +#define TEMP_DBG_FM 0 + + +#define PICTURE_START_CODE 0x100 +#define SLICE_START_CODE_MIN 0x101 +#define SLICE_START_CODE_MAX 0x1AF +#define USER_DATA_START_CODE 0x1B2 +#define SEQUENCE_HEADER_CODE 0x1B3 +#define SEQUENCE_ERROR_CODE 0x1B4 +#define EXTENSION_START_CODE 0x1B5 +#define SEQUENCE_END_CODE 0x1B7 +#define GROUP_START_CODE 0x1B8 +#define SYSTEM_START_CODE_MIN 0x1B9 +#define SYSTEM_START_CODE_MAX 0x1FF + +#define ISO_END_CODE 0x1B9 +#define PACK_START_CODE 0x1BA +#define SYSTEM_START_CODE 0x1BB + +#define VIDEO_ELEMENTARY_STREAM 0x1e0 +#define NO_MORE_STREAM 0xffffffff + +#define SEQUENCE_EXTENSION_ID 1 +#define SEQUENCE_DISPLAY_EXTENSION_ID 2 +#define QUANT_MATRIX_EXTENSION_ID 3 +#define COPYRIGHT_EXTENSION_ID 4 +#define SEQUENCE_SCALABLE_EXTENSION_ID 5 +#define PICTURE_DISPLAY_EXTENSION_ID 7 +#define PICTURE_CODING_EXTENSION_ID 8 +#define PICTURE_SPATIAL_SCALABLE_EXTENSION_ID 9 +#define PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID 10 + + +typedef enum M2VDPicCodingType_e { + M2VD_CODING_TYPE_I = 1, + M2VD_CODING_TYPE_P = 2, + M2VD_CODING_TYPE_B = 3, + M2VD_CODING_TYPE_D = 4 +} M2VDPicCodingType; + +typedef enum M2VDPicStruct_e { + M2VD_PIC_STRUCT_TOP_FIELD = 1, + M2VD_PIC_STRUCT_BOTTOM_FIELD = 2, + M2VD_PIC_STRUCT_FRAME = 3 +} M2VDPicStruct; + +#define M2VD_DBG_FILE_NUM 1 +#define M2VD_DBG_FILE_W 1 +#define M2VD_BUF_SIZE_BITMEM (512 * 1024) +#define M2VD_BUF_SIZE_QPTAB (256) +#define M2V_OUT_FLAG 0x1; + +typedef enum M2VDBufGrpIdx_t { + M2VD_BUF_GRP_BITMEM, + M2VD_BUF_GRP_QPTAB, + M2VD_BUF_GRP_BUTT, +} M2VDBufGrpIdx; + +typedef struct M2VFrameHead_t { + RK_U32 frameNumber; + RK_U32 tr; + RK_U32 picCodingType; + RK_U32 totalMbInFrame; + RK_U32 frameWidth; /* in macro blocks */ + RK_U32 frameHeight; /* in macro blocks */ + RK_U32 mb_width; + RK_U32 mb_height; + RK_U32 vlcSet; + RK_U32 qp; + RK_U32 frame_codelen; + // VPU_FRAME *frame_space; + MppFrame f; + RK_U32 flags; + RK_S32 slot_index; + //RK_U32 error_info; +} M2VDFrameHead; + + +/* ISO/IEC 13818-2 section 6.2.2.1: sequence_header() */ +typedef struct M2VDHeadSeq_t { + RK_U32 decode_width; //horizontal_size_value + RK_U32 decode_height; //vertical_size_value + RK_S32 aspect_ratio_information; + RK_S32 frame_rate_code; + RK_S32 bit_rate_value; + RK_S32 vbv_buffer_size; + RK_S32 constrained_parameters_flag; + RK_U32 load_intra_quantizer_matrix; //[TEMP] + RK_U32 load_non_intra_quantizer_matrix; //[TEMP] + RK_U8 *pIntra_table; //intra_quantiser_matrix[64] + RK_U8 *pInter_table; //non_intra_quantiser_matrix[64] +} M2VDHeadSeq; + +/* ISO/IEC 13818-2 section 6.2.2.3: sequence_extension() */ +typedef struct M2VDHeadSeqExt_t { + RK_U32 horizontal_size_extension; //[TEMP] + RK_U32 vertical_size_extension; //[TEMP] + RK_U32 bit_rate_extension; //[TEMP] + RK_U32 vbv_buffer_size_extension; //[TEMP] + RK_S32 profile_and_level_indication; + RK_S32 progressive_sequence; + RK_S32 chroma_format; + RK_S32 low_delay; + RK_S32 frame_rate_extension_n; + RK_S32 frame_rate_extension_d; +} M2VDHeadSeqExt; + +/* ISO/IEC 13818-2 section 6.2.2.6: group_of_pictures_header() */ +typedef struct M2VDHeadGop_t { + RK_S32 drop_flag; + RK_S32 hour; + RK_S32 minute; + RK_S32 sec; + RK_S32 frame; + RK_S32 closed_gop; + RK_S32 broken_link; +} M2VDHeadGop; + + +/* ISO/IEC 13818-2 section 6.2.3: picture_header() */ +typedef struct M2VDHeadPic_t { + RK_S32 temporal_reference; + RK_S32 picture_coding_type; + RK_S32 pre_picture_coding_type; + RK_S32 vbv_delay; + RK_S32 full_pel_forward_vector; + RK_S32 forward_f_code; + RK_S32 full_pel_backward_vector; + RK_S32 backward_f_code; + RK_S32 pre_temporal_reference; +} M2VDHeadPic; + + +/* ISO/IEC 13818-2 section 6.2.2.4: sequence_display_extension() */ +typedef struct M2VDHeadSeqDispExt_t { + RK_S32 video_format; + RK_S32 color_description; + RK_S32 color_primaries; + RK_S32 transfer_characteristics; + RK_S32 matrix_coefficients; +} M2VDHeadSeqDispExt; + +/* ISO/IEC 13818-2 section 6.2.3.1: picture_coding_extension() header */ +typedef struct M2VDHeadPicCodeExt_t { + RK_S32 f_code[2][2]; + RK_S32 intra_dc_precision; + RK_S32 picture_structure; + RK_S32 top_field_first; + RK_S32 frame_pred_frame_dct; + RK_S32 concealment_motion_vectors; + RK_S32 q_scale_type; + RK_S32 intra_vlc_format; + RK_S32 alternate_scan; + RK_S32 repeat_first_field; + RK_S32 chroma_420_type; + RK_S32 progressive_frame; + RK_S32 composite_display_flag; + RK_S32 v_axis; + RK_S32 field_sequence; + RK_S32 sub_carrier; + RK_S32 burst_amplitude; + RK_S32 sub_carrier_phase; +} M2VDHeadPicCodeExt; + + +/* ISO/IEC 13818-2 section 6.2.3.3: picture_display_extension() header */ +typedef struct M2VDHeadPicDispExt_t { + RK_S32 frame_center_horizontal_offset[3]; + RK_S32 frame_center_vertical_offset[3]; +} M2VDHeadPicDispExt; + +typedef struct M2VDCombMem_t { + MppBuffer hw_buf; + RK_U8* sw_buf; + RK_U8 buf_size; + RK_U8* sw_pos; + RK_U32 length; +} M2VDCombMem; + +typedef struct M2VDParserContext_t { + MppDecCfgSet *cfg; + M2VDDxvaParam *dxva_ctx; + BitReadCtx_t *bitread_ctx; + RK_U8 *bitstream_sw_buf; + RK_U8 *qp_tab_sw_buf; + RK_U32 max_stream_size; + RK_U32 left_length; + RK_U32 state; + RK_U32 vop_header_found; + + RK_U32 frame_size; + + RK_U32 display_width; + RK_U32 display_height; + RK_U32 frame_width; + RK_U32 frame_height; + RK_U32 mb_width; + RK_U32 mb_height; + RK_U32 MPEG2_Flag; + + RK_U32 info_changed; + M2VDHeadSeq seq_head; + M2VDHeadSeqExt seq_ext_head; + M2VDHeadGop gop_head; + M2VDHeadPic pic_head; + M2VDHeadSeqDispExt seq_disp_ext_head; + M2VDHeadPicCodeExt pic_code_ext_head; + M2VDHeadPicDispExt pic_disp_ext_head; + + RK_S32 resetFlag; + + RK_U64 pre_pts_27M; + RK_S64 group_start_time_27M; + RK_U32 group_frm_cnt; + RK_U32 pretemporal_reference; + RK_U32 pretime_temporal; + RK_U32 max_temporal_reference; + RK_U32 prechange_temporal_ref; + RK_S32 frame_period; + RK_S32 preframe_period; + RK_U32 maxFrame_inGOP; + RK_U32 pts_is_90K; + RK_U32 ref_frame_cnt; + long long top_first_cnt; + long long bottom_first_cnt; + RK_S32 mHeaderDecFlag; + RK_S32 mExtraHeaderDecFlag; + M2VDFrameHead Framehead[3]; + M2VDFrameHead *frame_ref0; + M2VDFrameHead *frame_ref1; + M2VDFrameHead *frame_cur; +#if M2VD_SKIP_ERROR_FRAME_EN + RK_S32 mHwDecStatus; +#endif + RK_S32 flush_dpb_eos; + + MppPacket input_packet; + RK_U32 eos; + + RK_S32 initFlag; + RK_S32 decoder_err; + + MppBufSlots packet_slots; + MppBufSlots frame_slots; + RK_U32 cur_slot_index; + MppDecCfgSet *dec_cfg; + + RK_U64 pts; + RK_U64 dts; + + FILE *fp_dbg_file[M2VD_DBG_FILE_NUM]; + FILE *fp_dbg_yuv; +} M2VDParserContext; + +MPP_RET m2vd_parser_init (void *ctx, ParserCfg *cfg); +MPP_RET m2vd_parser_deinit (void *ctx); +MPP_RET m2vd_parser_reset (void *ctx); +MPP_RET m2vd_parser_flush (void *ctx); +MPP_RET m2vd_parser_control(void *ctx, MpiCmd cmd_type, void *param); +MPP_RET m2vd_parser_prepare(void *ctx, MppPacket pkt, HalDecTask *task); +MPP_RET m2vd_parser_parse (void *ctx, HalDecTask *task); +MPP_RET m2vd_parser_callback(void *ctx, void *err_info); + +#endif diff --git a/mpp/codec/dec/mpg4/CMakeLists.txt b/mpp/codec/dec/mpg4/CMakeLists.txt new file mode 100644 index 000000000..c85c51a88 --- /dev/null +++ b/mpp/codec/dec/mpg4/CMakeLists.txt @@ -0,0 +1,7 @@ +# vim: syntax=cmake + +# mpeg4 decoder sourse +add_library(mpeg4d_api OBJECT + mpg4d_api.c + mpg4d_parser.c + ) diff --git a/mpp/codec/dec/mpg4/mpg4d_api.c b/mpp/codec/dec/mpg4/mpg4d_api.c new file mode 100644 index 000000000..40865b01b --- /dev/null +++ b/mpp/codec/dec/mpg4/mpg4d_api.c @@ -0,0 +1,360 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "mpg4d_api" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_parser.h" +#include "mpg4d_parser.h" +#include "mpp_packet_impl.h" +#include "mpp_dec_cb_param.h" + +#define MPG4D_INIT_STREAM_SIZE SZ_64K + +typedef struct { + // parameter interact with mpp_dec + MppBufSlots frame_slots; + MppBufSlots packet_slots; + RK_S32 task_count; + RK_U8 *stream; + size_t stream_size; + size_t left_length; + MppPacket task_pkt; + RK_U32 got_eos; + + // runtime parameter + RK_U32 frame_count; + MppDecCfgSet *dec_cfg; + + // parser context + Mpg4dParser parser; +} Mpg4dCtx; + +static MPP_RET mpg4d_init(void *dec, ParserCfg *cfg) +{ + Mpg4dParser parser = NULL; + MppPacket task_pkt = NULL; + Mpg4dCtx *p; + MPP_RET ret; + RK_U8 *stream; + size_t stream_size = MPG4D_INIT_STREAM_SIZE; + + if (NULL == dec) { + mpp_err_f("found NULL intput dec %p cfg %p\n", dec, cfg); + return MPP_ERR_NULL_PTR; + } + + stream = mpp_malloc_size(RK_U8, stream_size); + if (NULL == stream) { + mpp_err_f("failed to malloc stream buffer size %d\n", stream_size); + return MPP_ERR_MALLOC; + } + + ret = mpp_packet_init(&task_pkt, stream, stream_size); + if (ret) { + mpp_err_f("failed to create mpp_packet for task\n"); + goto ERR_RET; + } + + // reset task packet length to zero + // NOTE: set length must after set pos + mpp_packet_set_pos(task_pkt, stream); + mpp_packet_set_length(task_pkt, 0); + + ret = mpp_mpg4_parser_init(&parser, cfg); + if (ret) { + mpp_err_f("failed to init parser\n"); + goto ERR_RET; + } + + p = (Mpg4dCtx *)dec; + p->frame_slots = cfg->frame_slots; + p->packet_slots = cfg->packet_slots; + p->task_count = 2; + p->dec_cfg = cfg->cfg; + p->stream = stream; + p->stream_size = stream_size; + p->task_pkt = task_pkt; + p->parser = parser; + p->left_length = 0; + return MPP_OK; +ERR_RET: + if (task_pkt) { + mpp_packet_deinit(&task_pkt); + } + if (stream) { + mpp_free(stream); + stream = NULL; + } + return ret; +} + +static MPP_RET mpg4d_deinit(void *dec) +{ + Mpg4dCtx *p; + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + + p = (Mpg4dCtx *)dec; + if (p->parser) { + mpp_mpg4_parser_deinit(p->parser); + p->parser = NULL; + } + + if (p->task_pkt) { + mpp_packet_deinit(&p->task_pkt); + } + + if (p->stream) { + mpp_free(p->stream); + p->stream = NULL; + } + return MPP_OK; +} + +static MPP_RET mpg4d_reset(void *dec) +{ + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + + Mpg4dCtx *p = (Mpg4dCtx *)dec; + p->left_length = 0; + p->got_eos = 0; + mpp_packet_set_length(p->task_pkt, 0); + mpp_packet_set_flag(p->task_pkt, 0); + + return mpp_mpg4_parser_reset(p->parser); +} + +static MPP_RET mpg4d_flush(void *dec) +{ + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + + Mpg4dCtx *p = (Mpg4dCtx *)dec; + return mpp_mpg4_parser_flush(p->parser); +} + +static MPP_RET mpg4d_control(void *dec, MpiCmd cmd_type, void *param) +{ + if (NULL == dec) { + mpp_err_f("found NULL intput\n"); + return MPP_ERR_NULL_PTR; + } + (void)cmd_type; + (void)param; + return MPP_OK; +} + +static MPP_RET mpg4d_prepare(void *dec, MppPacket pkt, HalDecTask *task) +{ + Mpg4dCtx *p; + RK_U8 *pos; + size_t length; + RK_U32 eos; + + if (NULL == dec || NULL == pkt || NULL == task) { + mpp_err_f("found NULL intput dec %p pkt %p task %p\n", dec, pkt, task); + return MPP_ERR_NULL_PTR; + } + + task->valid = 0; + p = (Mpg4dCtx *)dec; + pos = mpp_packet_get_pos(pkt); + length = mpp_packet_get_length(pkt); + eos = mpp_packet_get_eos(pkt); + + if (p->got_eos) { + mpp_log_f("has got eos packet.\n"); + mpp_packet_set_length(pkt, 0); + return MPP_OK; + } + + if (NULL == p->stream) { + mpp_err("failed to malloc task buffer for hardware with size %d\n", length); + return MPP_ERR_UNKNOW; + } + mpp_packet_set_length(p->task_pkt, p->left_length); + + /* + * Check have enough buffer to store stream + * NOTE: total length is the left size plus the new incoming + * packet length. + */ + size_t total_length = MPP_ALIGN(p->left_length + length, 16) + 64; // add extra 64 bytes in tails + + if (total_length > p->stream_size) { + RK_U8 *dst = NULL; + do { + p->stream_size <<= 1; + } while (total_length > p->stream_size); + + dst = mpp_malloc_size(RK_U8, p->stream_size); + mpp_assert(dst); + // NOTE: copy remaining stream to new buffer + if (p->left_length > 0) { + memcpy(dst, p->stream, p->left_length); + } + mpp_free(p->stream); + p->stream = dst; + mpp_packet_set_data(p->task_pkt, p->stream); + mpp_packet_set_size(p->task_pkt, p->stream_size); + } + + if (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA) { + if (p->left_length > 0) { + p->left_length = 0; + task->valid = 1; + return MPP_OK; + } + } + + if (!p->dec_cfg->base.split_parse || + (mpp_packet_get_flag(pkt) & MPP_PACKET_FLAG_EXTRA_DATA)) { + p->got_eos = eos; + task->flags.eos = eos; + // NOTE: empty eos packet + if (eos && !length) { + mpg4d_flush(dec); + return MPP_OK; + } + /* + * Copy packet mode: + * Decoder's user will insure each packet is one frame for process + * Parser will just copy packet to the beginning of stream buffer + */ + memcpy(p->stream, pos, length); + mpp_packet_set_pos(p->task_pkt, p->stream); + mpp_packet_set_length(p->task_pkt, length); + mpp_packet_set_pts(p->task_pkt, mpp_packet_get_pts(pkt)); + mpp_packet_set_dts(p->task_pkt, mpp_packet_get_dts(pkt)); + // set input packet length to 0 here + // indicate that the input packet has been all consumed + mpp_packet_set_pos(pkt, pos + length); + mpp_packet_set_length(pkt, 0); + /* this step will enable the task and goto parse stage */ + task->valid = 1; + } else { + /* + * Split packet mode: + * Input packet can be any length and no need to be bound of on frame + * Parser will do split frame operation to find the beginning and end of one frame + */ + if (MPP_OK == mpp_mpg4_parser_split(p->parser, p->task_pkt, pkt)) { + p->left_length = 0; + task->valid = 1; + } else { + task->valid = 0; + p->left_length = mpp_packet_get_length(p->task_pkt); + } + p->got_eos = mpp_packet_get_eos(p->task_pkt); + task->flags.eos = p->got_eos; + } + task->input_packet = p->task_pkt; + + return MPP_OK; +} + +static MPP_RET mpg4d_parse(void *dec, HalDecTask *task) +{ + MPP_RET ret; + Mpg4dCtx *p; + + if (NULL == dec || NULL == task) { + mpp_err_f("found NULL intput dec %p task %p\n", dec, task); + return MPP_ERR_NULL_PTR; + } + p = (Mpg4dCtx *)dec; + ret = mpp_mpg4_parser_decode(p->parser, task->input_packet); + if (ret) { + // found error on decoding drop this task and clear remaining length + task->valid = 0; + task->output = -1; + mpp_packet_set_length(task->input_packet, 0); + + return MPP_NOK; + } + + mpp_mpg4_parser_setup_syntax(p->parser, &task->syntax); + mpp_mpg4_parser_setup_hal_output(p->parser, &task->output); + mpp_mpg4_parser_setup_refer(p->parser, task->refer, MAX_DEC_REF_NUM); + mpp_mpg4_parser_update_dpb(p->parser); + + if (p->got_eos) { + task->flags.eos = 1; + mpg4d_flush(dec); + return MPP_OK; + } + + p->frame_count++; + + return MPP_OK; +} + +static MPP_RET mpg4d_callback(void *dec, void *err_info) +{ + Mpg4dCtx *p_Dec = (Mpg4dCtx *)dec; + DecCbHalDone *ctx = (DecCbHalDone *)err_info; + + if (NULL == dec || NULL == err_info) { + mpp_err_f("found NULL input dec %p err_info %p\n", dec, err_info); + return MPP_ERR_NULL_PTR; + } + + MppFrame mframe = NULL; + HalDecTask *task_dec = (HalDecTask *)ctx->task; + + mpp_buf_slot_get_prop(p_Dec->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + if (mframe) { + RK_U32 task_err = task_dec->flags.parse_err || task_dec->flags.ref_err; + if (ctx->hard_err || task_err) { + mpp_frame_set_errinfo(mframe, MPP_FRAME_ERR_UNKNOW); + mpp_log_f("[CALLBACK] g_no=%d, out_idx=%d, dpberr=%d, harderr=%d, ref_flag=%d, errinfo=%d, discard=%d\n", + p_Dec->frame_count, task_dec->output, task_err, ctx->hard_err, task_dec->flags.used_for_ref, + mpp_frame_get_errinfo(mframe), mpp_frame_get_discard(mframe)); + } + } + return MPP_OK; +} + +const ParserApi mpp_mpg4d = { + .name = "api_mpg4d_parser", + .coding = MPP_VIDEO_CodingMPEG4, + .ctx_size = sizeof(Mpg4dCtx), + .flag = 0, + .init = mpg4d_init, + .deinit = mpg4d_deinit, + .prepare = mpg4d_prepare, + .parse = mpg4d_parse, + .reset = mpg4d_reset, + .flush = mpg4d_flush, + .control = mpg4d_control, + .callback = mpg4d_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_mpg4d); diff --git a/mpp/codec/dec/mpg4/mpg4d_parser.c b/mpp/codec/dec/mpg4/mpg4d_parser.c new file mode 100644 index 000000000..99e2e1fa9 --- /dev/null +++ b/mpp/codec/dec/mpg4/mpg4d_parser.c @@ -0,0 +1,1563 @@ +/* + * + * Copyright 2010 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpg4d_parser" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_bitread.h" + +#include "mpg4d_parser.h" +#include "mpg4d_syntax.h" + +#define mpg4d_dbg(flag, fmt, ...) mpp_dbg(mpg4d_debug, flag, fmt, ## __VA_ARGS__) +#define mpg4d_dbg_f(flag, fmt, ...) mpp_dbg_f(mpg4d_debug, flag, fmt, ## __VA_ARGS__) + +#define mpg4d_dbg_func(fmt, ...) mpg4d_dbg_f(MPG4D_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define mpg4d_dbg_bit(fmt, ...) mpg4d_dbg(MPG4D_DBG_BITS, fmt, ## __VA_ARGS__) +#define mpg4d_dbg_result(fmt, ...) mpg4d_dbg(MPG4D_DBG_RESULT, fmt, ## __VA_ARGS__) + +extern RK_U32 mpg4d_debug; + +#define MPEG4_VIDOBJ_START_CODE 0x00000100 /* ..0x0000011f */ +#define MPEG4_VIDOBJLAY_START_CODE 0x00000120 /* ..0x0000012f */ +#define MPEG4_VISOBJSEQ_START_CODE 0x000001b0 +#define MPEG4_VISOBJSEQ_STOP_CODE 0x000001b1 +#define MPEG4_USERDATA_START_CODE 0x000001b2 +#define MPEG4_GRPOFVOP_START_CODE 0x000001b3 +#define MPEG4_VISOBJ_START_CODE 0x000001b5 +#define MPEG4_VOP_START_CODE 0x000001b6 + +#define MPG4_VOL_STARTCODE 0x120 +#define MPG4_VOL_STOPCODE 0x12F +#define MPG4_VOS_STARTCODE 0x1B0 +#define MPG4_VOS_STOPCODE 0x1B1 +#define MPG4_USER_DATA_STARTCODE 0x1B2 +#define MPG4_GOP_STARTCODE 0x1B3 +#define MPG4_VISUAL_OBJ_STARTCODE 0x1B5 +#define MPG4_VOP_STARTCODE 0x1B6 + +typedef struct { + RK_S32 method; + + RK_S32 opaque; + RK_S32 transparent; + RK_S32 intra_cae; + RK_S32 inter_cae; + RK_S32 no_update; + RK_S32 upsampling; + + RK_S32 intra_blocks; + RK_S32 inter_blocks; + RK_S32 inter4v_blocks; + RK_S32 gmc_blocks; + RK_S32 not_coded_blocks; + + RK_S32 dct_coefs; + RK_S32 dct_lines; + RK_S32 vlc_symbols; + RK_S32 vlc_bits; + + RK_S32 apm; + RK_S32 npm; + RK_S32 interpolate_mc_q; + RK_S32 forw_back_mc_q; + RK_S32 halfpel2; + RK_S32 halfpel4; + + RK_S32 sadct; + RK_S32 quarterpel; +} Mpeg4Estimation; + +typedef struct Mp4HdrVol_t { + RK_S32 vo_type; + RK_U32 low_delay; + RK_U32 shape; + RK_S32 time_inc_resolution; + RK_U32 time_inc_bits; + RK_S32 width; + RK_S32 height; + RK_U32 mb_width; + RK_U32 mb_height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_U32 totalMbInVop; + RK_U32 interlacing; + RK_S32 sprite_enable; + RK_U32 quant_bits; + RK_U32 quant_type; + RK_S32 quarter_sample; + RK_S32 complexity_estimation_disable; + RK_U32 resync_marker_disable; + RK_S32 newpred_enable; + RK_S32 reduced_resolution_enable; + RK_S32 scalability; + RK_S32 ver_id; +} Mp4HdrVol; + +typedef struct Mp4HdrUserData_t { + RK_S32 packed_mode; /* bframes packed bits? (1 = yes) */ +} Mp4HdrUserData; + +typedef struct Mp4HdrVop_t { + RK_S32 coding_type; + RK_U32 frameNumber; + RK_U32 rounding; + RK_U32 intra_dc_vlc_threshold; + RK_U32 top_field_first; + RK_U32 alternate_vertical_scan; + RK_U32 fcode_forward; + RK_U32 fcode_backward; + RK_U32 quant; // OFFSET_OF_QUANT_IN_DEC + RK_U32 hdr_bits; +} Mp4HdrVop; + +typedef struct Mpg4Hdr_t { + // vol parameter + Mp4HdrVol vol; + + // user data parameter + Mp4HdrUserData usr; + + // vop header parameter + Mp4HdrVop vop; + + // frame related parameter + RK_S64 pts; + RK_S32 slot_idx; + RK_U32 enqueued; + + RK_U32 last_time_base; + RK_U32 time_base; + RK_U32 time; + RK_U32 time_pp; + RK_U32 time_bp; + RK_U32 last_non_b_time; +} Mpg4Hdr; + + +typedef struct { + // global paramter + MppBufSlots frame_slots; + RK_U32 found_vol; + RK_U32 found_vop; + RK_U32 found_i_vop; + + // frame size parameter + RK_S32 width; + RK_S32 height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_U32 info_change; + RK_U32 eos; + + // spliter parameter + RK_U32 state; + RK_U32 vop_header_found; // flag: visual object plane header found + + // bit read context + BitReadCtx_t *bit_ctx; + // vos infomation + RK_U32 profile; + RK_U32 level; + RK_U32 custorm_version; + // commom buffer for header information + /* + * NOTE: We assume that quant matrix only used for current frame decoding + * So we use only one quant matrix buffer and only support + */ + RK_U32 new_qm[2]; // [0] - intra [1] - inter + RK_U8 quant_matrices[128]; // 0-63: intra 64-127: inter + Mpeg4Estimation estimation; + Mpg4Hdr hdr_curr; /* header for current decoding frame */ + Mpg4Hdr hdr_ref0; /* header for reference frame 0 */ + Mpg4Hdr hdr_ref1; /* header for reference frame 1 */ + + // dpb/output information + RK_S32 output; + RK_S64 last_pts; + RK_S64 pts_inc; + RK_S64 pts; + RK_S64 dts; + RK_U32 frame_num; + MppDecCfgSet *dec_cfg; + + // syntax for hal + mpeg4d_dxva2_picture_context_t *syntax; +} Mpg4dParserImpl; + +static RK_S32 log2bin(RK_U32 value) +{ + RK_S32 n = 0; + + while (value) { + value >>= 1; + n++; + } + + return n; +} + +static MPP_RET mpg4d_parse_matrix(BitReadCtx_t *gb, RK_U8 * matrix) +{ + RK_S32 i = 0; + RK_S32 last, value = 0; + + do { + last = value; + READ_BITS(gb, 8, &value); + matrix[i++] = value; + } while (value != 0 && i < 64); + + if (value != 0) + return MPP_ERR_STREAM; + + i--; + + while (i < 64) { + matrix[i++ ] = last; + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static void mpg4d_set_intra_matrix(RK_U8 * quant_matrices, RK_U8 * matrix) +{ + RK_S32 i; + RK_U8 *intra_matrix = quant_matrices + 0 * 64; + + for (i = 0; i < 64; i++) { + intra_matrix[i] = (!i) ? (RK_U8)8 : (RK_U8)matrix[i]; + } +} + +static void mpg4d_set_inter_matrix(RK_U8 * quant_matrices, RK_U8 * matrix) +{ + RK_S32 i; + RK_U8 *inter_matrix = quant_matrices + 1 * 64; + + for (i = 0; i < 64; i++) { + inter_matrix[i] = (RK_U8) (matrix[i]); + } +} + +static MPP_RET read_vol_complexity_estimation_header(Mpeg4Estimation *e, BitReadCtx_t *gb) +{ + RK_U32 val; + + READ_BITS(gb, 2, &(e->method)); /* estimation_method */ + + if (e->method == 0 || e->method == 1) { + READ_BITS(gb, 1, &val); + if (!val) { /* shape_complexity_estimation_disable */ + READ_BITS(gb, 1, &(e->opaque)); /* opaque */ + READ_BITS(gb, 1, &(e->transparent)); /* transparent */ + READ_BITS(gb, 1, &(e->intra_cae)); /* intra_cae */ + READ_BITS(gb, 1, &(e->inter_cae)); /* inter_cae */ + READ_BITS(gb, 1, &(e->no_update)); /* no_update */ + READ_BITS(gb, 1, &(e->upsampling)); /* upsampling */ + } + + READ_BITS(gb, 1, &val); + if (!val) { /* texture_complexity_estimation_set_1_disable */ + READ_BITS(gb, 1, &(e->intra_blocks)); /* intra_blocks */ + READ_BITS(gb, 1, &(e->inter_blocks)); /* inter_blocks */ + READ_BITS(gb, 1, &(e->inter4v_blocks)); /* inter4v_blocks */ + READ_BITS(gb, 1, &(e->not_coded_blocks)); /* not_coded_blocks */ + } + } + + SKIP_BITS(gb, 1); + + READ_BITS(gb, 1, &val); + if (!val) { /* texture_complexity_estimation_set_2_disable */ + READ_BITS(gb, 1, &(e->dct_coefs)); /* dct_coefs */ + READ_BITS(gb, 1, &(e->dct_lines)); /* dct_lines */ + READ_BITS(gb, 1, &(e->vlc_symbols)); /* vlc_symbols */ + READ_BITS(gb, 1, &(e->vlc_bits)); /* vlc_bits */ + } + + READ_BITS(gb, 1, &val); + if (!val) { /* motion_compensation_complexity_disable */ + READ_BITS(gb, 1, &(e->apm)); /* apm */ + READ_BITS(gb, 1, &(e->npm)); /* npm */ + READ_BITS(gb, 1, &(e->interpolate_mc_q)); /* interpolate_mc_q */ + READ_BITS(gb, 1, &(e->forw_back_mc_q)); /* forw_back_mc_q */ + READ_BITS(gb, 1, &(e->halfpel2)); /* halfpel2 */ + READ_BITS(gb, 1, &(e->halfpel4)); /* halfpel4 */ + } + + SKIP_BITS(gb, 1); + + if (e->method == 1) { + READ_BITS(gb, 1, &val); + if (!val) { /* version2_complexity_estimation_disable */ + READ_BITS(gb, 1, &(e->sadct)); /* sadct */ + READ_BITS(gb, 1, &(e->quarterpel)); /* quarterpel */ + } + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +/* vop estimation header */ +static MPP_RET read_vop_complexity_estimation_header(Mpeg4Estimation *e, BitReadCtx_t *gb, Mpg4Hdr *mp4Hdr, int coding_type) +{ + if (e->method == 0 || e->method == 1) { + if (coding_type == MPEG4_I_VOP) { + if (e->opaque) SKIP_BITS(gb, 8); /* dcecs_opaque */ + if (e->transparent) SKIP_BITS(gb, 8); /* */ + if (e->intra_cae) SKIP_BITS(gb, 8); /* */ + if (e->inter_cae) SKIP_BITS(gb, 8); /* */ + if (e->no_update) SKIP_BITS(gb, 8); /* */ + if (e->upsampling) SKIP_BITS(gb, 8); /* */ + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->sadct) SKIP_BITS(gb, 8); /* */ + } + + if (coding_type == MPEG4_P_VOP) { + if (e->opaque) SKIP_BITS(gb, 8); /* */ + if (e->transparent) SKIP_BITS(gb, 8); /* */ + if (e->intra_cae) SKIP_BITS(gb, 8); /* */ + if (e->inter_cae) SKIP_BITS(gb, 8); /* */ + if (e->no_update) SKIP_BITS(gb, 8); /* */ + if (e->upsampling) SKIP_BITS(gb, 8); /* */ + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->inter_blocks) SKIP_BITS(gb, 8); /* */ + if (e->inter4v_blocks) SKIP_BITS(gb, 8); /* */ + if (e->apm) SKIP_BITS(gb, 8); /* */ + if (e->npm) SKIP_BITS(gb, 8); /* */ + if (e->forw_back_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->halfpel2) SKIP_BITS(gb, 8); /* */ + if (e->halfpel4) SKIP_BITS(gb, 8); /* */ + if (e->sadct) SKIP_BITS(gb, 8); /* */ + if (e->quarterpel) SKIP_BITS(gb, 8); /* */ + } + + if (coding_type == MPEG4_B_VOP) { + if (e->opaque) SKIP_BITS(gb, 8); /* */ + if (e->transparent) SKIP_BITS(gb, 8); /* */ + if (e->intra_cae) SKIP_BITS(gb, 8); /* */ + if (e->inter_cae) SKIP_BITS(gb, 8); /* */ + if (e->no_update) SKIP_BITS(gb, 8); /* */ + if (e->upsampling) SKIP_BITS(gb, 8); /* */ + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->inter_blocks) SKIP_BITS(gb, 8); /* */ + if (e->inter4v_blocks) SKIP_BITS(gb, 8); /* */ + if (e->apm) SKIP_BITS(gb, 8); /* */ + if (e->npm) SKIP_BITS(gb, 8); /* */ + if (e->forw_back_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->halfpel2) SKIP_BITS(gb, 8); /* */ + if (e->halfpel4) SKIP_BITS(gb, 8); /* */ + if (e->interpolate_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->sadct) SKIP_BITS(gb, 8); /* */ + if (e->quarterpel) SKIP_BITS(gb, 8); /* */ + } + +#ifdef GMC_SUPPORT + if (coding_type == MPEG4_S_VOP && mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_STATIC) { + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->inter_blocks) SKIP_BITS(gb, 8); /* */ + if (e->inter4v_blocks) SKIP_BITS(gb, 8); /* */ + if (e->apm) SKIP_BITS(gb, 8); /* */ + if (e->npm) SKIP_BITS(gb, 8); /* */ + if (e->forw_back_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->halfpel2) SKIP_BITS(gb, 8); /* */ + if (e->halfpel4) SKIP_BITS(gb, 8); /* */ + if (e->interpolate_mc_q) SKIP_BITS(gb, 8); /* */ + } +#else + (void)mp4Hdr; +#endif + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static void init_mpg4_hdr_vol(Mpg4Hdr *header) +{ + memset(&header->vol, 0, sizeof(header->vol)); + header->vol.ver_id = 1; +} + +static void init_mpg4_hdr_vop(Mpg4Hdr *header) +{ + memset(&header->vop, 0, sizeof(header->vop)); + header->vop.coding_type = MPEG4_INVALID_VOP; +} + +static void init_mpg4_header(Mpg4Hdr *header) +{ + init_mpg4_hdr_vol(header); + header->usr.packed_mode = 0; + init_mpg4_hdr_vop(header); + header->pts = 0; + header->slot_idx = -1; + header->enqueued = 0; +} + +static MPP_RET mpg4d_parse_vol_header(Mpg4dParserImpl *p, BitReadCtx_t *cb) +{ + RK_U32 val = 0; + Mpg4Hdr *mp4Hdr = &p->hdr_curr; + RK_S32 vol_ver_id; + RK_S32 aspect_ratio; + RK_S32 vol_control_parameters; + + SKIP_BITS(cb, 1); /* random_accessible_vol */ + READ_BITS(cb, 8, &(mp4Hdr->vol.vo_type)); + + READ_BITS(cb, 1, &val); /* is_object_layer_identifier */ + if (val) { + READ_BITS(cb, 4, &vol_ver_id); /* video_object_layer_verid */ + SKIP_BITS(cb, 3); /* video_object_layer_priority */ + } else { + vol_ver_id = mp4Hdr->vol.ver_id; + } + + READ_BITS(cb, 4, &aspect_ratio); + + if (aspect_ratio == MPEG4_VIDOBJLAY_AR_EXTPAR) { /* aspect_ratio_info */ + RK_S32 par_width, par_height; + + READ_BITS(cb, 8, &par_width); /* par_width */ + READ_BITS(cb, 8, &par_height); /* par_height */ + } + + READ_BITS(cb, 1, &vol_control_parameters); + + if (vol_control_parameters) { /* vol_control_parameters */ + SKIP_BITS(cb, 2); /* chroma_format */ + READ_BITS(cb, 1, &(mp4Hdr->vol.low_delay)); /* low_delay flage (1 means no B_VOP) */ + + READ_BITS(cb, 1, &val); /* vbv_parameters */ + if (val) { + RK_U32 bitrate; + RK_U32 buffer_size; + RK_U32 occupancy; + + READ_BITS(cb, 15, &val); /* first_half_bit_rate */ + bitrate = val << 15; + SKIP_BITS(cb, 1); + READ_BITS(cb, 15, &val); /* latter_half_bit_rate */ + bitrate |= val; + SKIP_BITS(cb, 1); + + READ_BITS(cb, 15, &val); /* first_half_vbv_buffer_size */ + buffer_size = val << 3; + SKIP_BITS(cb, 1); + READ_BITS(cb, 3, &val); + buffer_size |= val; /* latter_half_vbv_buffer_size */ + + READ_BITS(cb, 11, &val); + occupancy = val << 15; /* first_half_vbv_occupancy */ + SKIP_BITS(cb, 1); + READ_BITS(cb, 15, &val); + occupancy |= val; /* latter_half_vbv_occupancy */ + SKIP_BITS(cb, 1); + mpg4d_dbg_bit("bitrate %d, buffer_size %d, occupancy %d", bitrate, buffer_size, occupancy); + } + } else { + mp4Hdr->vol.low_delay = 0; + } + + if (mp4Hdr->vol.vo_type == 0 && vol_control_parameters == 0 && mp4Hdr->vop.frameNumber == 0) { + mpp_log("looks like this file was encoded with (divx4/(old)xvid/opendivx)\n"); + return MPP_NOK; + } + + READ_BITS(cb, 2, &(mp4Hdr->vol.shape)); /* video_object_layer_shape */ + + if (mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) { + mpp_log("unsupported shape %d\n", mp4Hdr->vol.shape); + return MPP_NOK; + } + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE && vol_ver_id != 1) { + SKIP_BITS(cb, 4); /* video_object_layer_shape_extension */ + } + + SKIP_BITS(cb, 1); + + READ_BITS(cb, 16, &(mp4Hdr->vol.time_inc_resolution)); /* vop_time_increment_resolution */ + + if (mp4Hdr->vol.time_inc_resolution > 0) { + mp4Hdr->vol.time_inc_bits = MPP_MAX(log2bin(mp4Hdr->vol.time_inc_resolution - 1), 1); + } else { + /* for "old" xvid compatibility, set time_inc_bits = 1 */ + mp4Hdr->vol.time_inc_bits = 1; + } + + SKIP_BITS(cb, 1); + + READ_BITS(cb, 1, &val); + if (val) { /* fixed_vop_rate */ + SKIP_BITS(cb, mp4Hdr->vol.time_inc_bits); /* fixed_vop_time_increment */ + } + + if (mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY) { + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) { + RK_S32 width, height; + + SKIP_BITS(cb, 1); + READ_BITS(cb, 13, &width); /* video_object_layer_width */ + SKIP_BITS(cb, 1); + READ_BITS(cb, 13, &height); /* video_object_layer_height */ + SKIP_BITS(cb, 1); + + mpg4d_dbg_bit("width %4d height %4d\n", width, height); + + if (width > 1920 || height > 1088) { + mpp_err("Warning: unsupport larger than 1920x1088\n"); + return MPP_NOK; + } + + mp4Hdr->vol.width = width; + mp4Hdr->vol.height = height; + mp4Hdr->vol.mb_width = (mp4Hdr->vol.width + 15) >> 4; + mp4Hdr->vol.mb_height = (mp4Hdr->vol.height + 15) >> 4; + mp4Hdr->vol.totalMbInVop = mp4Hdr->vol.mb_width * mp4Hdr->vol.mb_height; + mp4Hdr->vol.hor_stride = 16 * mp4Hdr->vol.mb_width; + mp4Hdr->vol.ver_stride = 16 * mp4Hdr->vol.mb_height; + } + + READ_BITS(cb, 1, &(mp4Hdr->vol.interlacing)); + + READ_BITS(cb, 1, &val); + if (!val) { /* obmc_disable */ + /* TODO */ + /* fucking divx4.02 has this enabled */ + } + + /* sprite_enable */ + READ_BITS(cb, (vol_ver_id == 1 ? 1 : 2), &(mp4Hdr->vol.sprite_enable)); + + if (mp4Hdr->vol.sprite_enable != MPEG4_SPRITE_NONE) { + mpp_err("GMC is not supported\n"); + return MPP_ERR_PROTOL; + } + + if (vol_ver_id != 1 && + mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) { + SKIP_BITS(cb, 1); /* sadct_disable */ + } + + READ_BITS(cb, 1, &val); + if (val) { /* not_8_bit */ + READ_BITS(cb, 4, &(mp4Hdr->vol.quant_bits));/* quant_precision */ + SKIP_BITS(cb, 4); /* bits_per_pixel */ + } else { + mp4Hdr->vol.quant_bits = 5; + } + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE) { + SKIP_BITS(cb, 1); /* no_gray_quant_update */ + SKIP_BITS(cb, 1); /* composition_method */ + SKIP_BITS(cb, 1); /* linear_composition */ + } + + READ_BITS(cb, 1, &(mp4Hdr->vol.quant_type)); /* quant_type */ + + if (mp4Hdr->vol.quant_type) { + RK_U8 matrix[64]; + + READ_BITS(cb, 1, &val); + p->new_qm[0] = val; + if (val) { /* load_intra_quant_mat */ + mpg4d_parse_matrix(cb, matrix); + mpg4d_set_intra_matrix(p->quant_matrices, matrix); + } + + READ_BITS(cb, 1, &val); + p->new_qm[1] = val; + if (val) { /* load_inter_quant_mat */ + mpg4d_parse_matrix(cb, matrix); + mpg4d_set_inter_matrix(p->quant_matrices, matrix); + } + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE) { + mpp_err("SHAPE_GRAYSCALE is not supported\n"); + return MPP_NOK; + } + } else { + p->new_qm[0] = 0; + p->new_qm[1] = 0; + } + + if (vol_ver_id != 1) { + READ_BITS(cb, 1, &(mp4Hdr->vol.quarter_sample)); + } else + mp4Hdr->vol.quarter_sample = 0; + + /* complexity estimation disable */ + READ_BITS(cb, 1, &(mp4Hdr->vol.complexity_estimation_disable)); + + if (!mp4Hdr->vol.complexity_estimation_disable) { + mpg4d_dbg_bit("read_vol_complexity_estimation_header\n"); + if (read_vol_complexity_estimation_header(&p->estimation, cb)) + return MPP_ERR_STREAM; + } + + /* resync_marker_disable */ + READ_BITS(cb, 1, &(mp4Hdr->vol.resync_marker_disable)); + if (!mp4Hdr->vol.resync_marker_disable) { + mpp_log("resync marker enabled\n"); + // return MPEG4_RESYNC_VOP; + } + + READ_BITS(cb, 1, &val); + if (val) { /* data_partitioned */ + SKIP_BITS(cb, 1); /* reversible_vlc */ + } + + if (vol_ver_id != 1) { + READ_BITS(cb, 1, &(mp4Hdr->vol.newpred_enable)); + + if (mp4Hdr->vol.newpred_enable) { /* newpred_enable */ + SKIP_BITS(cb, 2); /* requested_upstream_message_type */ + SKIP_BITS(cb, 1); /* newpred_segment_type */ + } + + /* reduced_resolution_vop_enable */ + READ_BITS(cb, 1, &(mp4Hdr->vol.reduced_resolution_enable)); + } else { + mp4Hdr->vol.newpred_enable = 0; + mp4Hdr->vol.reduced_resolution_enable = 0; + } + + READ_BITS(cb, 1, &mp4Hdr->vol.scalability); /* scalability */ + + if (mp4Hdr->vol.scalability) { + SKIP_BITS(cb, 1); /* hierarchy_type */ + SKIP_BITS(cb, 4); /* ref_layer_id */ + SKIP_BITS(cb, 1); /* ref_layer_sampling_direc */ + SKIP_BITS(cb, 5); /* hor_sampling_factor_n */ + SKIP_BITS(cb, 5); /* hor_sampling_factor_m */ + SKIP_BITS(cb, 5); /* vert_sampling_factor_n */ + SKIP_BITS(cb, 5); /* vert_sampling_factor_m */ + SKIP_BITS(cb, 1); /* enhancement_type */ + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_BINARY /* && hierarchy_type==0 */) { + /* use_ref_shape and so on*/ + SKIP_BITS(cb, ( 1 + 1 + 1 + 5 + 5 + 5 + 5)); + } + + mpp_err("scalability is not supported\n"); + return MPP_NOK; + } + } else { /* mp4Hdr->shape == BINARY_ONLY */ + mpp_err("shape %d is not supported\n"); + return MPP_NOK; + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpg4d_parse_user_data(Mpg4dParserImpl *p, BitReadCtx_t *gb) +{ + RK_U8 tmp[256]; + Mpg4Hdr *mp4Hdr = &p->hdr_curr; + RK_U32 remain_bit = gb->bytes_left_ * 8 + gb->num_remaining_bits_in_curr_byte_; + RK_S32 i; + + memset(tmp, 0, 256); + + for (i = 0; i < 255 && gb->bytes_left_; i++) { + RK_U32 show_bit = MPP_MIN(remain_bit, 23); + RK_U32 val; + + SHOW_BITS(gb, show_bit, &val); + if (val == 0) + break; + + READ_BITS(gb, 8, &val); + tmp[i] = val; + remain_bit -= 8; + } + + /* + * The value of i in the for loop above must be less than 255 otherwise it will cause + * tmp [256] = 0 which is overflow + */ + tmp[i] = 0; + + if (!mp4Hdr->usr.packed_mode) { + RK_U32 packed = 0; + + if ((tmp[0] == 'D') && + (tmp[1] == 'i') && + (tmp[2] == 'v') && + (tmp[3] == 'X')) { + RK_U32 j = 4; + + if (tmp[j] <= '4') { + p->custorm_version = 4; + } else { + p->custorm_version = 5; + } + + while ((tmp[j] >= '0') && + (tmp[j] <= '9')) + j++; + + if (tmp[j] == 'b') { + j++; + + while ((tmp[j] >= '0') && + (tmp[j] <= '9')) + j++; + + packed = tmp[j]; + } else if ((tmp[j + 0] == 'B') && + (tmp[j + 1] == 'u') && + (tmp[j + 2] == 'i') && + (tmp[j + 3] == 'l') && + (tmp[j + 4] == 'd')) { + j += 5; + + while ((tmp[j] >= '0') && (tmp[j] <= '9')) + j++; + + packed = tmp[j]; + } + + mp4Hdr->usr.packed_mode = ((packed == 'p') ? (1) : (0)); + } else { + mp4Hdr->usr.packed_mode = 0; + } + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpeg4_parse_gop_header(Mpg4dParserImpl *p, BitReadCtx_t *gb) +{ + (void) p; + RK_S32 hours, minutes, seconds; + + READ_BITS(gb, 5, &hours); + READ_BITS(gb, 6, &minutes); + SKIP_BITS(gb, 1); + READ_BITS(gb, 6, &seconds); + + SKIP_BITS(gb, 1); /* closed_gov */ + SKIP_BITS(gb, 1); /* broken_link */ + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpeg4_parse_profile_level(Mpg4dParserImpl *p, BitReadCtx_t *bc) +{ + READ_BITS(bc, 4, &p->profile); + READ_BITS(bc, 4, &p->level); + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpeg4_parse_vop_header(Mpg4dParserImpl *p, BitReadCtx_t *gb) +{ + RK_U32 val; + RK_U32 time_incr = 0; + RK_S32 time_increment = 0; + Mpg4Hdr *mp4Hdr = &p->hdr_curr; + + READ_BITS(gb, 2, &(mp4Hdr->vop.coding_type)); /* vop_coding_type */ + + READ_BITS(gb, 1, &val); + while (val != 0) { + time_incr++; /* time_base */ + READ_BITS(gb, 1, &val); + } + + SKIP_BITS(gb, 1); + + if (mp4Hdr->vol.time_inc_bits) { + /* vop_time_increment */ + READ_BITS(gb, mp4Hdr->vol.time_inc_bits, &time_increment); + } + + if (mp4Hdr->vop.coding_type != MPEG4_B_VOP) { + mp4Hdr->last_time_base = mp4Hdr->time_base; + mp4Hdr->time_base += time_incr; + mp4Hdr->time = mp4Hdr->time_base * mp4Hdr->vol.time_inc_resolution + time_increment; + mp4Hdr->time_pp = (RK_S32)(mp4Hdr->time - mp4Hdr->last_non_b_time); + mp4Hdr->last_non_b_time = mp4Hdr->time; + } else { + mp4Hdr->time = (mp4Hdr->last_time_base + time_incr) * mp4Hdr->vol.time_inc_resolution + time_increment; + mp4Hdr->time_bp = mp4Hdr->time_pp - (RK_S32)(mp4Hdr->last_non_b_time - mp4Hdr->time); + } + + SKIP_BITS(gb, 1); + + READ_BITS(gb, 1, &val); + if (!val) { /* vop_coded */ + mp4Hdr->vop.coding_type = MPEG4_N_VOP; + mpg4d_dbg_result("found N frame\n"); + return MPP_OK; + } + /* do coding_type detection here in order to save time_bp / time_pp */ + if (mp4Hdr->vop.coding_type == MPEG4_B_VOP && + (p->hdr_ref0.slot_idx == -1 || p->hdr_ref1.slot_idx == -1)) { + mpg4d_dbg_result("MPEG4 DIVX 5 PBBI case found!\n"); + return MPP_NOK; + } + if (mp4Hdr->vop.coding_type == MPEG4_I_VOP) + p->found_i_vop = 1; + + if (mp4Hdr->vol.newpred_enable) { + RK_S32 vop_id; + RK_S32 vop_id_for_prediction; + + READ_BITS(gb, (MPP_MIN(mp4Hdr->vol.time_inc_bits + 3, 15)), &vop_id); + + READ_BITS(gb, 1, &val); + if (val) { + /* vop_id_for_prediction_indication */ + READ_BITS(gb, MPP_MIN(mp4Hdr->vol.time_inc_bits + 3, 15), &vop_id_for_prediction); + } + + SKIP_BITS(gb, 1); + } + + if ((mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY) && + ((mp4Hdr->vop.coding_type == MPEG4_P_VOP) || + (mp4Hdr->vop.coding_type == MPEG4_S_VOP && + mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_GMC))) { + READ_BITS(gb, 1, &(mp4Hdr->vop.rounding)); /* rounding_type */ + } + + if (mp4Hdr->vol.reduced_resolution_enable && + mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR && + (mp4Hdr->vop.coding_type == MPEG4_P_VOP || mp4Hdr->vop.coding_type == MPEG4_I_VOP)) { + + READ_BITS(gb, 1, &val); + } + + mpp_assert(mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR); + + if (mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY) { + if (!mp4Hdr->vol.complexity_estimation_disable) { + read_vop_complexity_estimation_header(&p->estimation, gb, mp4Hdr, mp4Hdr->vop.coding_type); + } + + READ_BITS(gb, 3, &val); + /* intra_dc_vlc_threshold */ + mp4Hdr->vop.intra_dc_vlc_threshold = val; + mp4Hdr->vop.top_field_first = 0; + mp4Hdr->vop.alternate_vertical_scan = 0; + + if (mp4Hdr->vol.interlacing) { + READ_BITS(gb, 1, &(mp4Hdr->vop.top_field_first)); + READ_BITS(gb, 1, &(mp4Hdr->vop.alternate_vertical_scan)); + } + } + + if ((mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_STATIC || + mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_GMC) && + mp4Hdr->vop.coding_type == MPEG4_S_VOP) { + mpp_err("unsupport split mode %d coding type %d\n", + mp4Hdr->vol.sprite_enable, mp4Hdr->vop.coding_type); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, mp4Hdr->vol.quant_bits, &(mp4Hdr->vop.quant)); + if (mp4Hdr->vop.quant < 1) /* vop_quant */ + mp4Hdr->vop.quant = 1; + + if (mp4Hdr->vop.coding_type != MPEG4_I_VOP) { + READ_BITS(gb, 3, &(mp4Hdr->vop.fcode_forward)); /* fcode_forward */ + } + + if (mp4Hdr->vop.coding_type == MPEG4_B_VOP) { + READ_BITS(gb, 3, &(mp4Hdr->vop.fcode_backward)); /* fcode_backward */ + } + + if (!mp4Hdr->vol.scalability) { + if ((mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) && + (mp4Hdr->vop.coding_type != MPEG4_I_VOP)) { + SKIP_BITS(gb, 1); /* vop_shape_coding_type */ + } + } + + // NOTE: record header used bits here + mp4Hdr->vop.hdr_bits = gb->used_bits; + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static void mpg4d_fill_picture_parameters(const Mpg4dParserImpl *p, + DXVA_PicParams_MPEG4_PART2 *pp) +{ + const Mpg4Hdr *hdr_curr = &p->hdr_curr; + const Mpg4Hdr *hdr_ref0 = &p->hdr_ref0; + const Mpg4Hdr *hdr_ref1 = &p->hdr_ref1; + + pp->short_video_header = 0; + pp->vop_coding_type = hdr_curr->vop.coding_type; + pp->vop_quant = hdr_curr->vop.quant; + pp->wDecodedPictureIndex = hdr_curr->slot_idx; + pp->wForwardRefPictureIndex = hdr_ref0->slot_idx; + pp->wBackwardRefPictureIndex = hdr_ref1->slot_idx; + pp->vop_time_increment_resolution = hdr_curr->vol.time_inc_resolution; + pp->TRB[0] = 0; /* FIXME: */ + pp->TRD[0] = 0; /* FIXME: */ + pp->unPicPostProc = 0; /* FIXME: */ + pp->interlaced = hdr_curr->vol.interlacing; + pp->quant_type = hdr_curr->vol.quant_type; + pp->quarter_sample = hdr_curr->vol.quarter_sample; + pp->resync_marker_disable = 0; /* FIXME: */ + pp->data_partitioned = 0; /* FIXME: */ + pp->reversible_vlc = 0; /* FIXME: */ + pp->reduced_resolution_vop_enable = hdr_curr->vol.reduced_resolution_enable; + pp->vop_coded = (hdr_curr->vop.coding_type != MPEG4_N_VOP); + pp->vop_rounding_type = hdr_curr->vop.rounding; + pp->intra_dc_vlc_thr = hdr_curr->vop.intra_dc_vlc_threshold; + pp->top_field_first = hdr_curr->vop.top_field_first; + pp->alternate_vertical_scan_flag = hdr_curr->vop.alternate_vertical_scan; + pp->profile_and_level_indication = (p->profile << 4) | p->level; + pp->video_object_layer_verid = hdr_curr->vol.ver_id; + pp->vop_width = hdr_curr->vol.width; + pp->vop_height = hdr_curr->vol.height; + pp->sprite_enable = hdr_curr->vol.sprite_enable; + pp->no_of_sprite_warping_points = 0; /* FIXME: */ + pp->sprite_warping_accuracy = 0; /* FIXME: */ + memset(pp->warping_mv, 0, sizeof(pp->warping_mv)); + pp->vop_fcode_forward = hdr_curr->vop.fcode_forward; + pp->vop_fcode_backward = hdr_curr->vop.fcode_backward; + pp->StatusReportFeedbackNumber = 0; /* FIXME: */ + pp->Reserved16BitsA = 0; /* FIXME: */ + pp->Reserved16BitsB = 0; /* FIXME: */ + + // Rockchip special data + pp->custorm_version = p->custorm_version; + pp->prev_coding_type = (hdr_ref0->vop.coding_type == MPEG4_INVALID_VOP) ? (0) : (hdr_ref0->vop.coding_type); + pp->time_bp = hdr_curr->time_bp; + pp->time_pp = hdr_curr->time_pp; + pp->header_bits = hdr_curr->vop.hdr_bits; +} + +static void mpg4d_fill_quantization_matrices(const Mpg4dParserImpl *p, + DXVA_QmatrixData *qm) +{ + RK_S32 i = 0; + + qm->bNewQmatrix[0] = p->new_qm[0]; + qm->bNewQmatrix[1] = p->new_qm[1]; + qm->bNewQmatrix[2] = 0; + qm->bNewQmatrix[3] = 0; + + // intra Y + if (p->new_qm[0]) { + for (i = 0; i < 64; i++) { + qm->Qmatrix[0][i] = p->quant_matrices[i]; + } + } else { + memset(qm->Qmatrix[0], 0, sizeof(qm->Qmatrix[0])); + } + + // inter Y + if (p->new_qm[1]) { + for (i = 0; i < 64; i++) { + qm->Qmatrix[1][i] = p->quant_matrices[64 + i]; + } + } else { + memset(qm->Qmatrix[1], 0, sizeof(qm->Qmatrix[1])); + } + + memset(qm->Qmatrix[2], 0, sizeof(qm->Qmatrix[2])); + memset(qm->Qmatrix[3], 0, sizeof(qm->Qmatrix[3])); +} + +static void mpg4_syntax_init(mpeg4d_dxva2_picture_context_t *syntax) +{ + DXVA2_DecodeBufferDesc *data = &syntax->desc[0]; + + //!< commit picture paramters + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_PictureParametersBufferType; + data->pvPVPState = (void *)&syntax->pp; + data->DataSize = sizeof(syntax->pp); + syntax->data[0] = data; + + //!< commit Qmatrix + data = &syntax->desc[1]; + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_InverseQuantizationMatrixBufferType; + data->pvPVPState = (void *)&syntax->qm; + data->DataSize = sizeof(syntax->qm); + data->NumMBsInBuffer = 0; + syntax->data[1] = data; + + //!< commit bitstream + data = &syntax->desc[2]; + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_BitStreamDateBufferType; + syntax->data[2] = data; +} + +MPP_RET mpp_mpg4_parser_init(Mpg4dParser *ctx, ParserCfg *cfg) +{ + BitReadCtx_t *bit_ctx = mpp_calloc(BitReadCtx_t, 1); + Mpg4dParserImpl *p = mpp_calloc(Mpg4dParserImpl, 1); + mpeg4d_dxva2_picture_context_t *syntax = mpp_calloc(mpeg4d_dxva2_picture_context_t, 1); + MppBufSlots frame_slots = cfg->frame_slots; + + p->dec_cfg = cfg->cfg; + + if (NULL == p || NULL == bit_ctx || NULL == syntax) { + mpp_err_f("malloc context failed\n"); + if (p) + mpp_free(p); + if (bit_ctx) + mpp_free(bit_ctx); + if (syntax) + mpp_free(syntax); + return MPP_NOK; + } + + mpg4d_dbg_func("in\n"); + + mpp_buf_slot_setup(frame_slots, 8); + p->frame_slots = frame_slots; + p->state = -1; + p->vop_header_found = 0; + p->bit_ctx = bit_ctx; + init_mpg4_header(&p->hdr_curr); + init_mpg4_header(&p->hdr_ref0); + init_mpg4_header(&p->hdr_ref1); + mpg4_syntax_init(syntax); + p->syntax = syntax; + + mpp_env_get_u32("mpg4d_debug", &mpg4d_debug, 0); + + mpg4d_dbg_func("out\n"); + + *ctx = p; + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_deinit(Mpg4dParser ctx) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + + mpg4d_dbg_func("in\n"); + + if (p) { + if (p->bit_ctx) { + mpp_free(p->bit_ctx); + p->bit_ctx = NULL; + } + if (p->syntax) { + mpp_free(p->syntax); + p->syntax = NULL; + } + mpp_free(p); + } + + mpg4d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_flush(Mpg4dParser ctx) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + MppBufSlots slots = p->frame_slots; + Mpg4Hdr *hdr_ref0 = &p->hdr_ref0; + RK_S32 index = hdr_ref0->slot_idx; + + mpg4d_dbg_func("in\n"); + + if (!hdr_ref0->enqueued && index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + hdr_ref0->enqueued = 1; + } + + mpg4d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_reset(Mpg4dParser ctx) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + MppBufSlots slots = p->frame_slots; + Mpg4Hdr *hdr_ref0 = &p->hdr_ref0; + Mpg4Hdr *hdr_ref1 = &p->hdr_ref1; + RK_S32 index = hdr_ref0->slot_idx; + + mpg4d_dbg_func("in\n"); + + if (index >= 0) { + if (!hdr_ref0->enqueued) { + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + hdr_ref0->enqueued = 1; + } + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + hdr_ref0->slot_idx = -1; + } + + index = hdr_ref1->slot_idx; + if (index >= 0) { + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + hdr_ref1->slot_idx = -1; + } + + p->found_i_vop = 0; + p->found_vop = 0; + p->state = -1; + p->vop_header_found = 0; + + mpg4d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_split(Mpg4dParser ctx, MppPacket dst, MppPacket src) +{ + MPP_RET ret = MPP_NOK; + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + RK_U8 *src_buf = (RK_U8 *)mpp_packet_get_pos(src); + RK_U32 src_len = (RK_U32)mpp_packet_get_length(src); + RK_U32 src_eos = mpp_packet_get_eos(src); + RK_S64 src_pts = mpp_packet_get_pts(src); + RK_U8 *dst_buf = (RK_U8 *)mpp_packet_get_data(dst); + RK_U32 dst_len = (RK_U32)mpp_packet_get_length(dst); + RK_U32 src_pos = 0; + + mpg4d_dbg_func("in\n"); + + // find the began of the vop + if (!p->vop_header_found) { + // add last startcode to the new frame data + if ((dst_len < sizeof(p->state)) + && ((p->state & 0x00FFFFFF) == 0x000001)) { + dst_buf[0] = 0; + dst_buf[1] = 0; + dst_buf[2] = 1; + dst_len = 3; + } + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + if (p->state == MPG4_VOP_STARTCODE) { + p->vop_header_found = 1; + mpp_packet_set_pts(dst, src_pts); + break; + } + } + } + // find the end of the vop + if (p->vop_header_found) { + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + if ((p->state & 0x00FFFFFF) == 0x000001) { + dst_len -= 3; + p->vop_header_found = 0; + ret = MPP_OK; // split complete + break; + } + } + } + // the last packet + if (src_eos && src_pos >= src_len) { + mpp_packet_set_eos(dst); + ret = MPP_OK; + } + // reset the src and dst + mpp_packet_set_length(dst, dst_len); + mpp_packet_set_pos(src, src_buf + src_pos); + + mpg4d_dbg_func("out\n"); + + return ret; +} + +MPP_RET mpp_mpg4_parser_decode(Mpg4dParser ctx, MppPacket pkt) +{ + MPP_RET ret = MPP_OK; + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + BitReadCtx_t *gb = p->bit_ctx; + RK_U8 *buf = mpp_packet_get_data(pkt); + RK_S32 len = (RK_S32)mpp_packet_get_length(pkt); + RK_U32 startcode = 0xff; + + mpg4d_dbg_func("in\n"); + + // setup bit read context + mpp_set_bitread_ctx(gb, buf, len); + p->found_vop = 0; + + while (gb->bytes_left_) { + RK_U32 val = 0; + + READ_BITS(gb, 8, &val); + startcode = (startcode << 8) | val; + + if ((startcode & 0xFFFFFF00) != 0x100) + continue; + + mpg4d_dbg_bit("found startcode at byte %d\n", gb->used_bits >> 3); + + if (mpg4d_debug & MPG4D_DBG_STARTCODE) { + mpp_log_f("start code %03x\n", startcode); + if (startcode <= 0x11F) + mpp_log_f("Video Object Start"); + else if (startcode <= 0x12F) + mpp_log_f("Video Object Layer Start"); + else if (startcode <= 0x13F) + mpp_log_f("Reserved"); + else if (startcode <= 0x15F) + mpp_log_f("FGS bp start"); + else if (startcode <= 0x1AF) + mpp_log_f("Reserved"); + else if (startcode == 0x1B0) + mpp_log_f("Visual Object Seq Start"); + else if (startcode == 0x1B1) + mpp_log_f("Visual Object Seq End"); + else if (startcode == 0x1B2) + mpp_log_f("User Data"); + else if (startcode == 0x1B3) + mpp_log_f("Group of VOP start"); + else if (startcode == 0x1B4) + mpp_log_f("Video Session Error"); + else if (startcode == 0x1B5) + mpp_log_f("Visual Object Start"); + else if (startcode == 0x1B6) + mpp_log_f("Video Object Plane start"); + else if (startcode == 0x1B7) + mpp_log_f("slice start"); + else if (startcode == 0x1B8) + mpp_log_f("extension start"); + else if (startcode == 0x1B9) + mpp_log_f("fgs start"); + else if (startcode == 0x1BA) + mpp_log_f("FBA Object start"); + else if (startcode == 0x1BB) + mpp_log_f("FBA Object Plane start"); + else if (startcode == 0x1BC) + mpp_log_f("Mesh Object start"); + else if (startcode == 0x1BD) + mpp_log_f("Mesh Object Plane start"); + else if (startcode == 0x1BE) + mpp_log_f("Still Texture Object start"); + else if (startcode == 0x1BF) + mpp_log_f("Texture Spatial Layer start"); + else if (startcode == 0x1C0) + mpp_log_f("Texture SNR Layer start"); + else if (startcode == 0x1C1) + mpp_log_f("Texture Tile start"); + else if (startcode == 0x1C2) + mpp_log_f("Texture Shape Layer start"); + else if (startcode == 0x1C3) + mpp_log_f("stuffing start"); + else if (startcode <= 0x1C5) + mpp_log_f("reserved"); + else if (startcode <= 0x1FF) + mpp_log_f("System start"); + } + + if (startcode >= MPG4_VOL_STARTCODE && startcode <= MPG4_VOL_STOPCODE) { + ret = mpg4d_parse_vol_header(p, gb); + if (!p->found_vol) + p->found_vol = (ret == MPP_OK); + } else if (startcode == MPG4_USER_DATA_STARTCODE) { + ret = mpg4d_parse_user_data(p, gb); + } else if (startcode == MPG4_GOP_STARTCODE) { + ret = mpeg4_parse_gop_header(p, gb); + } else if (startcode == MPG4_VOS_STARTCODE) { + ret = mpeg4_parse_profile_level(p, gb); + } else if (startcode == MPG4_VOP_STARTCODE) { + ret = mpeg4_parse_vop_header(p, gb); + if (MPP_OK == ret) { + RK_S32 coding_type = p->hdr_curr.vop.coding_type; + mpg4d_dbg_bit("frame %d coding_type %d\n", p->frame_num, coding_type); + p->frame_num++; + + if (coding_type == MPEG4_N_VOP) { + ret = MPP_OK; + mpp_align_get_bits(gb); + continue; + } + + p->found_vop = p->found_i_vop; + } + } + + if (ret) + goto __BITREAD_ERR; + + mpp_align_get_bits(gb); + + if (p->found_vol && p->found_vop) + break; + } + + if (p->found_vol) { + mpg4d_dbg_result("found vol w %d h %d\n", p->hdr_curr.vol.width, p->hdr_curr.vol.height); + p->width = p->hdr_curr.vol.width; + p->height = p->hdr_curr.vol.height; + } + + p->pts = mpp_packet_get_pts(pkt); + p->dts = mpp_packet_get_dts(pkt); + + ret = (p->found_vol && p->found_vop) ? (MPP_OK) : (MPP_NOK); + +__BITREAD_ERR: + mpg4d_dbg_result("found vol %d vop %d ret %d\n", p->found_vol, p->found_vop, ret); + + if (ret) { + mpp_packet_set_pos(pkt, buf); + mpp_packet_set_length(pkt, 0); + } else { + RK_U32 used_bytes = gb->used_bits >> 3; + mpp_packet_set_pos(pkt, buf + used_bytes); + } + + p->eos = mpp_packet_get_eos(pkt); + + mpg4d_dbg_func("out\n"); + + return ret; +} + +MPP_RET mpp_mpg4_parser_setup_syntax(Mpg4dParser ctx, MppSyntax *syntax) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + mpeg4d_dxva2_picture_context_t *syn = p->syntax; + + mpg4d_dbg_func("in\n"); + + mpg4d_fill_picture_parameters(p, &syn->pp); + mpg4d_fill_quantization_matrices(p, &syn->qm); + + // fill bit stream parameter + syn->data[2]->DataSize = p->bit_ctx->buf_len; + syn->data[2]->DataOffset = p->hdr_curr.vop.hdr_bits; + syn->data[2]->pvPVPState = p->bit_ctx->buf; + + syntax->number = 3; + syntax->data = syn->data; + + mpg4d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_setup_hal_output(Mpg4dParser ctx, RK_S32 *output) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + Mpg4Hdr *hdr_curr = &p->hdr_curr; + RK_S32 index = -1; + + mpg4d_dbg_func("in\n"); + + if (p->found_i_vop && hdr_curr->vop.coding_type != MPEG4_N_VOP) { + MppBufSlots slots = p->frame_slots; + RK_U32 frame_mode = MPP_FRAME_FLAG_FRAME; + MppFrame frame = NULL; + + mpp_frame_init(&frame); + mpp_frame_set_width(frame, p->width); + mpp_frame_set_height(frame, p->height); + mpp_frame_set_hor_stride(frame, MPP_ALIGN(p->width, 16)); + mpp_frame_set_ver_stride(frame, MPP_ALIGN(p->height, 16)); + + /* + * set slots information + * 1. output index MUST be set + * 2. get unused index for output if needed + * 3. set output index as hal_input + * 4. set frame information to output index + * 5. if one frame can be display, it SHOULD be enqueued to display queue + */ + mpp_buf_slot_get_unused(slots, &index); + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_OUTPUT); + mpp_frame_set_pts(frame, p->pts); + mpp_frame_set_dts(frame, p->dts); + + if (hdr_curr->vol.interlacing) { + frame_mode = MPP_FRAME_FLAG_PAIRED_FIELD; + if (hdr_curr->vop.top_field_first) + frame_mode |= MPP_FRAME_FLAG_TOP_FIRST; + else + frame_mode |= MPP_FRAME_FLAG_BOT_FIRST; + } + + if ((p->dec_cfg->base.enable_vproc & MPP_VPROC_MODE_DETECTION) && + frame_mode == MPP_FRAME_FLAG_FRAME) + frame_mode = MPP_FRAME_FLAG_DEINTERLACED; + + mpp_frame_set_mode(frame, frame_mode); + + mpp_buf_slot_set_prop(slots, index, SLOT_FRAME, frame); + mpp_frame_deinit(&frame); + mpp_assert(NULL == frame); + + hdr_curr->slot_idx = index; + } + + p->output = index; + *output = index; + + mpg4d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_setup_refer(Mpg4dParser ctx, RK_S32 *refer, RK_S32 max_ref) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + Mpg4Hdr *hdr_curr = &p->hdr_curr; + MppBufSlots slots = p->frame_slots; + RK_S32 index; + + mpg4d_dbg_func("in\n"); + + memset(refer, -1, sizeof(max_ref * sizeof(*refer))); + if (hdr_curr->vop.coding_type != MPEG4_N_VOP) { + index = p->hdr_ref0.slot_idx; + if (index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT); + refer[0] = index; + } + index = p->hdr_ref1.slot_idx; + if (index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT); + refer[1] = index; + } + } + + mpg4d_dbg_func("out\n"); + + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_update_dpb(Mpg4dParser ctx) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + MppBufSlots slots = p->frame_slots; + Mpg4Hdr *hdr_curr = &p->hdr_curr; + Mpg4Hdr *hdr_ref0 = &p->hdr_ref0; + Mpg4Hdr *hdr_ref1 = &p->hdr_ref1; + RK_S32 coding_type = hdr_curr->vop.coding_type; + RK_S32 index = p->output; + + mpg4d_dbg_func("in\n"); + + // update pts increacement + if (p->pts != p->last_pts) + p->pts_inc = p->pts - p->last_pts; + + switch (coding_type) { + case MPEG4_B_VOP : { + mpp_assert((hdr_ref0->slot_idx >= 0) && (hdr_ref1->slot_idx >= 0)); + // B frame -> index current frame + // output current frame and do not change ref0 and ref1 + index = hdr_curr->slot_idx; + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + } + /* + * NOTE: here fallback to N vop - do nothing + */ + case MPEG4_INVALID_VOP : + case MPEG4_N_VOP : { + } break; + case MPEG4_I_VOP : + case MPEG4_P_VOP : + case MPEG4_S_VOP : + // the other case -> index reference 0 + index = hdr_ref0->slot_idx; + if (!hdr_ref0->enqueued && index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + } + // non B frame send this frame to reference queue + mpp_buf_slot_set_flag(slots, hdr_curr->slot_idx, SLOT_CODEC_USE); + + // release ref1 + index = hdr_ref1->slot_idx; + if (index >= 0) + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + + // swap ref0 to ref1, current to ref0 + *hdr_ref1 = *hdr_ref0; + *hdr_ref0 = *hdr_curr; + hdr_curr->pts = 0; + } + + init_mpg4_hdr_vop(hdr_curr); + hdr_curr->slot_idx = -1; + p->last_pts = p->pts; + + mpg4d_dbg_func("out\n"); + + return MPP_OK; +} + + + diff --git a/mpp/codec/dec/mpg4/mpg4d_parser.h b/mpp/codec/dec/mpg4/mpg4d_parser.h new file mode 100644 index 000000000..d81d4cb9c --- /dev/null +++ b/mpp/codec/dec/mpg4/mpg4d_parser.h @@ -0,0 +1,54 @@ +/* + * + * Copyright 2010 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPG4D_PARSER_H +#define MPG4D_PARSER_H + +#include "mpp_packet.h" +#include "mpp_buf_slot.h" +#include "hal_dec_task.h" +#include "parser_api.h" + +#define MPG4D_DBG_FUNCTION (0x00000001) +#define MPG4D_DBG_STARTCODE (0x00000002) +#define MPG4D_DBG_BITS (0x00000004) +#define MPG4D_DBG_RESULT (0x00000008) +#define MPG4D_DBG_TIME (0x00000100) + +typedef void* Mpg4dParser; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_mpg4_parser_init(Mpg4dParser *ctx, ParserCfg *cfg); +MPP_RET mpp_mpg4_parser_deinit(Mpg4dParser ctx); +MPP_RET mpp_mpg4_parser_flush(Mpg4dParser ctx); +MPP_RET mpp_mpg4_parser_reset(Mpg4dParser ctx); + +MPP_RET mpp_mpg4_parser_split(Mpg4dParser ctx, MppPacket dst, MppPacket src); +MPP_RET mpp_mpg4_parser_decode(Mpg4dParser ctx, MppPacket pkt); +MPP_RET mpp_mpg4_parser_setup_syntax(Mpg4dParser ctx, MppSyntax *syntax); +MPP_RET mpp_mpg4_parser_setup_hal_output(Mpg4dParser ctx, RK_S32 *output); +MPP_RET mpp_mpg4_parser_setup_refer(Mpg4dParser ctx, RK_S32 *refer, RK_S32 max_ref); +MPP_RET mpp_mpg4_parser_update_dpb(Mpg4dParser ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* MPG4D_PAESER_H */ diff --git a/mpp/codec/dec/vp8/CMakeLists.txt b/mpp/codec/dec/vp8/CMakeLists.txt new file mode 100644 index 000000000..958ebed0b --- /dev/null +++ b/mpp/codec/dec/vp8/CMakeLists.txt @@ -0,0 +1,8 @@ +# vim: syntax=cmake +include_directories(.) + +# vp8 decoder source +add_library(vp8d_api OBJECT + vp8d_api.c + vp8d_parser.c + ) diff --git a/mpp/codec/dec/vp8/vp8d_api.c b/mpp/codec/dec/vp8/vp8d_api.c new file mode 100644 index 000000000..49a6f4aed --- /dev/null +++ b/mpp/codec/dec/vp8/vp8d_api.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vp8d_api" + +#include + +#include "mpp_parser.h" +#include "vp8d_parser.h" +#include "vp8d_codec.h" + +const ParserApi mpp_vp8d = { + .name = "vp8d_parse", + .coding = MPP_VIDEO_CodingVP8, + .ctx_size = sizeof(VP8DContext), + .flag = 0, + .init = vp8d_parser_init, + .deinit = vp8d_parser_deinit, + .prepare = vp8d_parser_prepare, + .parse = vp8d_parser_parse, + .reset = vp8d_parser_reset, + .flush = vp8d_parser_flush, + .control = vp8d_parser_control, + .callback = vp8d_parser_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_vp8d); diff --git a/mpp/codec/inc/h265d_api.h b/mpp/codec/dec/vp8/vp8d_codec.h similarity index 76% rename from mpp/codec/inc/h265d_api.h rename to mpp/codec/dec/vp8/vp8d_codec.h index 33c900740..dfedbcb96 100644 --- a/mpp/codec/inc/h265d_api.h +++ b/mpp/codec/dec/vp8/vp8d_codec.h @@ -1,22 +1,26 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __H265D_API_H__ -#define __H265D_API_H__ - - - -#endif /*__H265D_API_H__*/ \ No newline at end of file +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VP8D_CODEC_H +#define VP8D_CODEC_H + +typedef struct VP8DContext_t { + void *parse_ctx; + +} VP8DContext; + +#endif diff --git a/mpp/codec/dec/vp8/vp8d_data.h b/mpp/codec/dec/vp8/vp8d_data.h new file mode 100644 index 000000000..ae16d207f --- /dev/null +++ b/mpp/codec/dec/vp8/vp8d_data.h @@ -0,0 +1,406 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VP8D_DATA_H +#define VP8D_DATA_H + +#include +#include "rk_type.h" + +#define VP7_MV_PROBS_PER_COMPONENT (17) +#define VP8_MV_PROBS_PER_COMPONENT (19) + + +#define swap32bit(x) ((x>>24)|((x>>8)&0xff00)|((x<<8)&0xff0000)|(x<<24)) + +static const RK_U8 MvUpdateProbs[2][VP8_MV_PROBS_PER_COMPONENT] = { + { + 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 RK_U8 Vp8DefaultMvProbs[2][VP8_MV_PROBS_PER_COMPONENT] = { + { + 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 RK_U8 Vp7DefaultMvProbs[2][VP7_MV_PROBS_PER_COMPONENT] = { + { + 162, 128, 225, 146, 172, 147, 214, 39, 156, + 247, 210, 135, 68, 138, 220, 239, 246 + }, + { + 164, 128, 204, 170, 119, 235, 140, 230, 228, + 244, 184, 201, 44, 173, 221, 239, 253 + } +}; + +static const RK_U8 CoeffUpdateProbs[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 RK_U8 DefaultCoeffProbs [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} + } + } +}; + +#endif diff --git a/mpp/codec/dec/vp8/vp8d_parser.c b/mpp/codec/dec/vp8/vp8d_parser.c new file mode 100644 index 000000000..ed865272c --- /dev/null +++ b/mpp/codec/dec/vp8/vp8d_parser.c @@ -0,0 +1,1357 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "vp8d_parser" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_frame.h" + +#include "vp8d_parser.h" +#include "vp8d_codec.h" + +#define FUN_T(tag) \ + do {\ + if (VP8D_DBG_FUNCTION & vp8d_debug)\ + { mpp_log("%s: line(%d), func(%s)", tag, __LINE__, __FUNCTION__); }\ + } while (0) + +extern RK_U32 vp8d_debug; + +static void vp8hwdBoolStart(vpBoolCoder_t *bit_ctx, RK_U8 *buffer, RK_U32 len) +{ + FUN_T("FUN_IN"); + bit_ctx->lowvalue = 0; + bit_ctx->range = 255; + bit_ctx->count = 8; + bit_ctx->buffer = buffer; + bit_ctx->pos = 0; + + bit_ctx->value = (bit_ctx->buffer[0] << 24) + (bit_ctx->buffer[1] << 16) + + (bit_ctx->buffer[2] << 8) + (bit_ctx->buffer[3]); + + bit_ctx->pos += 4; + + bit_ctx->streamEndPos = len; + bit_ctx->strmError = bit_ctx->pos > bit_ctx->streamEndPos; + + FUN_T("FUN_OUT"); +} + +static RK_U32 vp8hwdDecodeBool(vpBoolCoder_t *bit_ctx, RK_S32 probability) +{ + RK_U32 bit = 0; + RK_U32 split; + RK_U32 bigsplit; + RK_U32 count = bit_ctx->count; + RK_U32 range = bit_ctx->range; + RK_U32 value = bit_ctx->value; + + FUN_T("FUN_IN"); + split = 1 + (((range - 1) * probability) >> 8); + bigsplit = (split << 24); + range = split; + + if (value >= bigsplit) { + range = bit_ctx->range - split; + value = value - bigsplit; + bit = 1; + } + + if (range >= 0x80) { + bit_ctx->value = value; + bit_ctx->range = range; + return bit; + } else { + do { + range += range; + value += value; + + if (!--count) { + /* no more stream to read? */ + if (bit_ctx->pos >= bit_ctx->streamEndPos) { + bit_ctx->strmError = 1; + mpp_log("vp8hwdDecodeBool read end"); + break; + } + count = 8; + value |= bit_ctx->buffer[bit_ctx->pos]; + bit_ctx->pos++; + } + } while (range < 0x80); + } + + + bit_ctx->count = count; + bit_ctx->value = value; + bit_ctx->range = range; + + FUN_T("FUN_OUT"); + return bit; +} + +static RK_U32 vp8hwdDecodeBool128(vpBoolCoder_t *bit_ctx) +{ + RK_U32 bit = 0; + RK_U32 split; + RK_U32 bigsplit; + RK_U32 count = bit_ctx->count; + RK_U32 range = bit_ctx->range; + RK_U32 value = bit_ctx->value; + + FUN_T("FUN_IN"); + split = (range + 1) >> 1; + bigsplit = (split << 24); + range = split; + + if (value >= bigsplit) { + range = (bit_ctx->range - split); + value = (value - bigsplit); + bit = 1; + } + + if (range >= 0x80) { + bit_ctx->value = value; + bit_ctx->range = range; + + FUN_T("FUN_OUT"); + return bit; + } else { + range <<= 1; + value <<= 1; + + if (!--count) { + /* no more stream to read? */ + if (bit_ctx->pos >= bit_ctx->streamEndPos) { + bit_ctx->strmError = 1; + mpp_log("vp8hwdDecodeBool128 read end"); + return 0; /* any value, not valid */ + } + count = 8; + value |= bit_ctx->buffer[bit_ctx->pos]; + bit_ctx->pos++; + } + } + + bit_ctx->count = count; + bit_ctx->value = value; + bit_ctx->range = range; + + FUN_T("FUN_OUT"); + return bit; +} + +static RK_U32 vp8hwdReadBits(vpBoolCoder_t *bit_ctx, RK_S32 bits) +{ + RK_U32 z = 0; + RK_S32 bit; + + FUN_T("FUN_IN"); + for (bit = bits - 1; bit >= 0; bit--) { + z |= (vp8hwdDecodeBool128(bit_ctx) << bit); + } + + FUN_T("FUN_OUT"); + return z; +} + +static RK_U32 ScaleDimension( RK_U32 orig, RK_U32 scale ) +{ + + FUN_T("FUN_IN"); + switch (scale) { + case 0: + return orig; + break; + case 1: /* 5/4 */ + return (5 * orig) / 4; + break; + case 2: /* 5/3 */ + return (5 * orig) / 3; + break; + case 3: /* 2 */ + return 2 * orig; + break; + } + + FUN_T("FUN_OUT"); + return orig; +} + +static RK_S32 DecodeQuantizerDelta(vpBoolCoder_t *bit_ctx) +{ + RK_S32 result = 0; + + FUN_T("FUN_IN"); + if (vp8hwdDecodeBool128(bit_ctx)) { + result = vp8hwdReadBits(bit_ctx, 4); + if (vp8hwdDecodeBool128(bit_ctx)) + result = -result; + } + + FUN_T("FUN_OUT"); + return result; +} + +MPP_RET vp8d_parser_init(void *ctx, ParserCfg *parser_cfg) +{ + MPP_RET ret = MPP_OK; + VP8DContext *c = (VP8DContext *)ctx; + VP8DParserContext_t *p = (VP8DParserContext_t *)c->parse_ctx; + + mpp_env_get_u32("vp8d_debug", &vp8d_debug, 0); + FUN_T("FUN_IN"); + if (p == NULL) { + p = (VP8DParserContext_t*)mpp_calloc(VP8DParserContext_t, 1); + if (NULL == p) { + mpp_err("vp8d malloc VP8DParserContext_t fail"); + FUN_T("FUN_OUT"); + return MPP_ERR_NOMEM; + } + c->parse_ctx = p; + } + p->packet_slots = parser_cfg->packet_slots; + p->frame_slots = parser_cfg->frame_slots; + + mpp_buf_slot_setup(p->frame_slots, 15); + + p->dxva_ctx = mpp_calloc(DXVA_PicParams_VP8, 1); + + if (NULL == p->dxva_ctx) { + mpp_err("vp8d malloc dxva_ctx fail"); + FUN_T("FUN_OUT"); + return MPP_ERR_NOMEM; + } + p->decMode = VP8HWD_VP8; + p->bitstream_sw_buf = mpp_malloc(RK_U8, VP8D_BUF_SIZE_BITMEM); + mpp_packet_init(&p->input_packet, p->bitstream_sw_buf, + VP8D_BUF_SIZE_BITMEM); + p->max_stream_size = VP8D_BUF_SIZE_BITMEM; + + FUN_T("FUN_OUT"); + return ret; +} + +static void vp8d_unref_frame(VP8DParserContext_t *p, VP8Frame *frame) +{ + + FUN_T("FUN_IN"); + if (NULL == frame || frame->ref_count <= 0 + || frame->slot_index >= 0x7f) { + mpp_err("ref count alreay is zero"); + FUN_T("FUN_OUT"); + return; + } + + frame->ref_count--; + if (!frame->ref_count) { + if (frame->slot_index < 0x7f) { + MppBuffer framebuf = NULL; + if (frame->invisible) { + mpp_buf_slot_get_prop(p->frame_slots, frame->slot_index, SLOT_BUFFER, &framebuf); + mpp_buffer_put(framebuf); + frame->invisible = 0; + } + mpp_buf_slot_clr_flag(p->frame_slots, frame->slot_index, SLOT_CODEC_USE); + } + frame->slot_index = 0xff; + mpp_frame_deinit(&frame->f); + mpp_free(frame); + frame = NULL; + } + + FUN_T("FUN_OUT"); + return; +} + +static void vp8d_unref_allframe(VP8DParserContext_t *p) +{ + + FUN_T("FUN_IN"); + if (NULL != p->frame_out) { + vp8d_unref_frame(p, p->frame_out); + p->frame_out = NULL; + } + + if (NULL != p->frame_ref) { + vp8d_unref_frame(p, p->frame_ref); + p->frame_ref = NULL; + } + + if (NULL != p->frame_golden) { + vp8d_unref_frame(p, p->frame_golden); + p->frame_golden = NULL; + } + + if (NULL != p->frame_alternate) { + vp8d_unref_frame(p, p->frame_alternate); + p->frame_alternate = NULL; + } + + FUN_T("FUN_OUT"); + return; +} + +MPP_RET vp8d_parser_deinit(void *ctx) +{ + MPP_RET ret = MPP_OK; + VP8DContext *c = (VP8DContext *)ctx; + VP8DParserContext_t *p = (VP8DParserContext_t *)c->parse_ctx; + + FUN_T("FUN_IN"); + + if (NULL != p->bitstream_sw_buf) { + mpp_free(p->bitstream_sw_buf); + p->bitstream_sw_buf = NULL; + } + + if (NULL != p->dxva_ctx) { + mpp_free(p->dxva_ctx); + p->dxva_ctx = NULL; + } + + vp8d_unref_allframe(p); + + if (p->input_packet) { + mpp_packet_deinit(&p->input_packet); + p->input_packet = NULL; + } + + if (p->stream_fp) + fclose(p->stream_fp); + + if ( NULL != p) { + mpp_free(p); + } + FUN_T("FUN_OUT"); + return ret; +} +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +MPP_RET vp8d_parser_reset(void *ctx) +{ + MPP_RET ret = MPP_OK; + VP8DContext *c = (VP8DContext *)ctx; + VP8DParserContext_t *p = (VP8DParserContext_t *)c->parse_ctx; + + FUN_T("FUN_IN"); + vp8d_unref_allframe(p); + p->needKeyFrame = 0; + p->eos = 0; + FUN_T("FUN_OUT"); + return ret; +} + +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +MPP_RET vp8d_parser_flush(void *ctx) +{ + MPP_RET ret = MPP_OK; + + FUN_T("FUN_IN"); + (void) ctx; + FUN_T("FUN_OUT"); + return ret; +} + +/*! +*********************************************************************** +* \brief +* control/perform +*********************************************************************** +*/ +MPP_RET vp8d_parser_control(void *ctx, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_OK; + + FUN_T("FUN_IN"); + (void)ctx; + (void)cmd_type; + (void)param; + + FUN_T("FUN_OUT"); + return ret; +} + + +/*! +*********************************************************************** +* \brief +* prepare +*********************************************************************** +*/ + +static MPP_RET vp8d_parser_split_frame(RK_U8 *src, RK_U32 src_size, + RK_U8 *dst, RK_U32 *dst_size) +{ + MPP_RET ret = MPP_OK; + + FUN_T("FUN_IN"); + memcpy(dst, src, src_size);; + *dst_size = src_size; + + (void)dst; + + FUN_T("FUN_OUT"); + return ret; +} + + +MPP_RET vp8d_parser_prepare(void *ctx, MppPacket pkt, HalDecTask *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 out_size = 0, len_in = 0; + RK_U8 * pos = NULL; + RK_U8 *buf = NULL; + VP8DContext *c = (VP8DContext *)ctx; + + VP8DParserContext_t *p = (VP8DParserContext_t *)c->parse_ctx; + MppPacket input_packet = p->input_packet; + + FUN_T("FUN_IN"); + task->valid = 0; + + + buf = pos = mpp_packet_get_pos(pkt); + p->pts = mpp_packet_get_pts(pkt); + p->dts = mpp_packet_get_dts(pkt); + + len_in = (RK_U32)mpp_packet_get_length(pkt), + p->eos = mpp_packet_get_eos(pkt); + // mpp_log("len_in = %d",len_in); + if (len_in > p->max_stream_size) { + mpp_free(p->bitstream_sw_buf); + p->bitstream_sw_buf = NULL; + p->bitstream_sw_buf = mpp_malloc(RK_U8, (len_in + 1024)); + if (NULL == p->bitstream_sw_buf) { + mpp_err("vp8d_parser realloc fail"); + return MPP_ERR_NOMEM; + } + p->max_stream_size = len_in + 1024; + } + + vp8d_parser_split_frame(buf, + len_in, + p->bitstream_sw_buf, + &out_size); + pos += out_size; + + mpp_packet_set_pos(pkt, pos); + + if (out_size == 0 && p->eos) { + task->flags.eos = p->eos; + return ret; + } + + + + // mpp_log("p->bitstream_sw_buf = 0x%x", p->bitstream_sw_buf); + // mpp_log("out_size = 0x%x", out_size); + mpp_packet_set_data(input_packet, p->bitstream_sw_buf); + mpp_packet_set_size(input_packet, p->max_stream_size); + mpp_packet_set_length(input_packet, out_size); + p->stream_size = out_size; + task->input_packet = input_packet; + task->valid = 1; + + FUN_T("FUN_OUT"); + return ret; +} + +static MPP_RET +vp8d_convert_to_syntx( VP8DParserContext_t *p, HalDecTask *in_task) +{ + MPP_RET ret = MPP_OK; + RK_U32 i, tmp; + RK_U32 byteOffset = 0, extraBytesPacked = 0; + DXVA_PicParams_VP8 *pic_param = p->dxva_ctx; + + FUN_T("FUN_IN"); + tmp = (p->bitstr.pos) * 8 + (8 - p->bitstr.count); + + if (p->frameTagSize == 4) + tmp += 8; + + if (p->decMode == VP8HWD_VP8 && p->keyFrame) + extraBytesPacked += 7; + + tmp += extraBytesPacked * 8; + byteOffset = tmp / 8; + pic_param->stream_start_bit = (byteOffset & 0x07U) * 8; + byteOffset &= (~0x07U); /* align the base */ + pic_param->stream_start_offset = byteOffset; + + pic_param->stream_start_bit += (tmp & 0x7); + + pic_param->frame_type = !p->keyFrame; + pic_param->stVP8Segments.segmentation_enabled = p->segmentationEnabled; + pic_param->stVP8Segments.update_mb_segmentation_map = + p->segmentationMapUpdate; + pic_param->mode_ref_lf_delta_enabled = p->modeRefLfEnabled; + pic_param->mb_no_coeff_skip = p->coeffSkipMode; + pic_param->width = p->width; + pic_param->height = p->height; + pic_param->decMode = p->decMode; + pic_param->filter_type = p->loopFilterType; + pic_param->sharpness = p->loopFilterSharpness; + pic_param->filter_level = p->loopFilterLevel; + pic_param->stVP8Segments.update_mb_segmentation_data = + p->segmentFeatureMode; + pic_param->version = p->vpVersion; + pic_param->bool_value = ((p->bitstr.value >> 24) & (0xFFU)); + pic_param->bool_range = (p->bitstr.range & (0xFFU)); + pic_param->frameTagSize = p->frameTagSize; + pic_param->streamEndPos = p->bitstr.streamEndPos; + pic_param->log2_nbr_of_dct_partitions = p->nbrDctPartitions; + pic_param->offsetToDctParts = p->offsetToDctParts; + + pic_param->y1ac_delta_q = p->qpYAc; + pic_param->y1dc_delta_q = p->qpYDc; + pic_param->y2ac_delta_q = p->qpY2Ac; + pic_param->y2dc_delta_q = p->qpY2Dc; + pic_param->uvac_delta_q = p->qpChAc; + pic_param->uvdc_delta_q = p->qpChDc; + pic_param->probe_skip_false = p->probMbSkipFalse; + pic_param->prob_intra = p->probIntra; + pic_param->prob_last = p->probRefLast; + pic_param->prob_golden = p->probRefGolden; + + memcpy(pic_param->vp8_coef_update_probs, p->entropy.probCoeffs, + sizeof(pic_param->vp8_coef_update_probs)); + memcpy(pic_param->vp8_mv_update_probs, p->entropy.probMvContext, + sizeof(pic_param->vp8_mv_update_probs)); + + for ( i = 0; i < 3; i++) { + pic_param->intra_chroma_prob[i] = p->entropy.probChromaPredMode[i]; + pic_param->stVP8Segments.mb_segment_tree_probs[i] = p->probSegment[i]; + } + + pic_param->ref_frame_sign_bias_golden = p->refFrameSignBias[0]; + pic_param->ref_frame_sign_bias_altref = p->refFrameSignBias[1]; + + + for (i = 0; i < 4; i++) { + pic_param->stVP8Segments.segment_feature_data[0][i] = p->segmentQp[i]; + pic_param->ref_lf_deltas[i] = p->mbRefLfDelta[i]; + pic_param->mode_lf_deltas[i] = p->mbModeLfDelta[i]; + pic_param->stVP8Segments.segment_feature_data[1][i] = + p->segmentLoopfilter[i]; + pic_param->intra_16x16_prob[i] = p->entropy.probLuma16x16PredMode[i]; + } + + p->dxva_ctx->CurrPic.Index7Bits = p->frame_out->slot_index; + memset(in_task->refer, -1, sizeof(in_task->refer)); + + if (p->frame_ref != NULL) { + pic_param->lst_fb_idx.Index7Bits = p->frame_ref->slot_index; + mpp_buf_slot_set_flag(p->frame_slots, p->frame_ref->slot_index, + SLOT_HAL_INPUT); + in_task->refer[0] = p->frame_ref->slot_index; + } else { + pic_param->lst_fb_idx.Index7Bits = 0x7f; + } + + if (p->frame_golden != NULL) { + pic_param->gld_fb_idx.Index7Bits = p->frame_golden->slot_index; + mpp_buf_slot_set_flag(p->frame_slots, p->frame_golden->slot_index, + SLOT_HAL_INPUT); + in_task->refer[1] = p->frame_golden->slot_index; + } else { + pic_param->gld_fb_idx.Index7Bits = 0x7f; + } + + if (p->frame_alternate != NULL) { + pic_param->alt_fb_idx.Index7Bits = p->frame_alternate->slot_index; + mpp_buf_slot_set_flag(p->frame_slots, p->frame_alternate->slot_index, + SLOT_HAL_INPUT); + in_task->refer[2] = p->frame_alternate->slot_index; + } else { + pic_param->alt_fb_idx.Index7Bits = 0x7f; + } + + memcpy(pic_param->dctPartitionOffsets, p->dctPartitionOffsets, + sizeof(p->dctPartitionOffsets)); + + FUN_T("FUN_OUT"); + return ret; +} + +static MPP_RET vp8d_alloc_frame(VP8DParserContext_t *p) +{ + MPP_RET ret = MPP_OK; + + FUN_T("FUN_IN"); + if (NULL == p->frame_out) { + p->frame_out = mpp_calloc(VP8Frame, 1); + if (NULL == p->frame_out) { + mpp_err("alloc vp8 frame fail"); + return MPP_ERR_NOMEM; + } + + if (NULL == p->frame_out->f) { + mpp_frame_init(&p->frame_out->f); + if (NULL == p->frame_out->f) { + mpp_err("alloc vp8 mpp frame fail"); + return MPP_ERR_NOMEM; + } + } + p->frame_out->slot_index = 0xff; + p->frame_out->invisible = !p->showFrame; + } + + if (p->frame_out->slot_index == 0xff) { + mpp_frame_set_width(p->frame_out->f, p->width); + mpp_frame_set_height(p->frame_out->f, p->height); + mpp_frame_set_hor_stride(p->frame_out->f, 0); + mpp_frame_set_ver_stride(p->frame_out->f, 0); + mpp_frame_set_errinfo(p->frame_out->f, 0); + mpp_frame_set_pts(p->frame_out->f, p->pts); + mpp_frame_set_dts(p->frame_out->f, p->dts); + ret = mpp_buf_slot_get_unused(p->frame_slots, + &p->frame_out->slot_index); + if (MPP_OK != ret) { + mpp_err("vp8 buf_slot_get_unused get fail"); + return ret; + } + mpp_buf_slot_set_prop(p->frame_slots, p->frame_out->slot_index, + SLOT_FRAME, p->frame_out->f); + mpp_buf_slot_set_flag(p->frame_slots, p->frame_out->slot_index, + SLOT_CODEC_USE); + mpp_buf_slot_set_flag(p->frame_slots, p->frame_out->slot_index, + SLOT_HAL_OUTPUT); + mpp_frame_set_mode(p->frame_out->f, 0); + + if (p->showFrame) { + mpp_buf_slot_set_flag(p->frame_slots, p->frame_out->slot_index, + SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(p->frame_slots, p->frame_out->slot_index, + QUEUE_DISPLAY); + } + p->frame_out->ref_count++; + } + + FUN_T("FUN_OUT"); + return ret; +} + +static void vp8d_ref_frame(VP8Frame *frame) +{ + + FUN_T("FUN_IN"); + if ((NULL == frame) || (frame->slot_index >= 0x7f)) { + mpp_err("frame is null or slot_index is no valid"); + return; + } + frame->ref_count++; + + FUN_T("FUN_OUT"); +} + + +static MPP_RET vp8d_ref_update(VP8DParserContext_t *p) +{ + + FUN_T("FUN_IN"); + if (p->decMode != VP8HWD_WEBP) { + if (p->copyBufferToAlternate == 1) { + if (NULL != p->frame_alternate) { + vp8d_unref_frame(p, p->frame_alternate); + p->frame_alternate = NULL; + } + p->frame_alternate = p->frame_ref; + vp8d_ref_frame(p->frame_alternate); + } else if (p->copyBufferToAlternate == 2) { + if (NULL != p->frame_alternate) { + vp8d_unref_frame(p, p->frame_alternate); + p->frame_alternate = NULL; + } + p->frame_alternate = p->frame_golden; + vp8d_ref_frame(p->frame_alternate); + } + + if (p->copyBufferToGolden == 1) { + if (NULL != p->frame_golden) { + vp8d_unref_frame(p, p->frame_golden); + p->frame_golden = NULL; + } + p->frame_golden = p->frame_ref; + vp8d_ref_frame(p->frame_golden); + } else if (p->copyBufferToGolden == 2) { + if (NULL != p->frame_golden) { + vp8d_unref_frame(p, p->frame_golden); + p->frame_golden = NULL; + } + p->frame_golden = p->frame_alternate; + vp8d_ref_frame(p->frame_golden); + } + + if (p->refreshGolden) { + if (NULL != p->frame_golden) { + vp8d_unref_frame(p, p->frame_golden); + p->frame_golden = NULL; + } + p->frame_golden = p->frame_out; + vp8d_ref_frame(p->frame_golden); + } + + if (p->refreshAlternate) { + if (NULL != p->frame_alternate) { + vp8d_unref_frame(p, p->frame_alternate); + p->frame_alternate = NULL; + } + p->frame_alternate = p->frame_out; + vp8d_ref_frame(p->frame_out); + } + + if (p->refreshLast) { + if (NULL != p->frame_ref) { + vp8d_unref_frame(p, p->frame_ref); + p->frame_ref = NULL; + } + p->frame_ref = p->frame_out; + vp8d_ref_frame(p->frame_ref); + } + vp8d_unref_frame(p, p->frame_out); + p->frame_out = NULL; + } + + FUN_T("FUN_OUT"); + return 0; +} + +static void vp8hwdResetProbs(VP8DParserContext_t *p) +{ + RK_U32 i, j, k, l; + static const RK_U32 Vp7DefaultScan[] = { + 0, 1, 4, 8, 5, 2, 3, 6, + 9, 12, 13, 10, 7, 11, 14, 15, + }; + + FUN_T("FUN_IN"); + for ( i = 0 ; i < 16 ; ++i ) + p->vp7ScanOrder[i] = Vp7DefaultScan[i]; + + + /* Intra-prediction modes */ + p->entropy.probLuma16x16PredMode[0] = 112; + p->entropy.probLuma16x16PredMode[1] = 86; + p->entropy.probLuma16x16PredMode[2] = 140; + p->entropy.probLuma16x16PredMode[3] = 37; + p->entropy.probChromaPredMode[0] = 162; + p->entropy.probChromaPredMode[1] = 101; + p->entropy.probChromaPredMode[2] = 204; + + for (i = 0; i < MAX_NBR_OF_MB_REF_LF_DELTAS; i++) + p->mbRefLfDelta[i] = 0; + + for (i = 0; i < MAX_NBR_OF_MB_MODE_LF_DELTAS; i++) + p->mbModeLfDelta[i] = 0; + + /* MV context */ + k = 0; + if (p->decMode == VP8HWD_VP8) { + for ( i = 0 ; i < 2 ; ++i ) + for ( j = 0 ; j < VP8_MV_PROBS_PER_COMPONENT ; ++j, ++k ) + p->entropy.probMvContext[i][j] = Vp8DefaultMvProbs[i][j]; + } else { + for ( i = 0 ; i < 2 ; ++i ) + for ( j = 0 ; j < VP7_MV_PROBS_PER_COMPONENT ; ++j, ++k ) + p->entropy.probMvContext[i][j] = Vp7DefaultMvProbs[i][j]; + } + + /* Coefficients */ + for ( i = 0 ; i < 4 ; ++i ) + for ( j = 0 ; j < 8 ; ++j ) + for ( k = 0 ; k < 3 ; ++k ) + for ( l = 0 ; l < 11 ; ++l ) + p->entropy.probCoeffs[i][j][k][l] = + DefaultCoeffProbs[i][j][k][l]; + + FUN_T("FUN_OUT"); +} + +static void vp8hwdDecodeCoeffUpdate(VP8DParserContext_t *p) +{ + RK_U32 i, j, k, l; + + FUN_T("FUN_IN"); + for ( i = 0; i < 4; i++ ) { + for ( j = 0; j < 8; j++ ) { + for ( k = 0; k < 3; k++ ) { + for ( l = 0; l < 11; l++ ) { + if (vp8hwdDecodeBool(&p->bitstr, + CoeffUpdateProbs[i][j][k][l])) + p->entropy.probCoeffs[i][j][k][l] = + vp8hwdReadBits(&p->bitstr, 8); + } + } + } + } + FUN_T("FUN_OUT"); +} + +static MPP_RET vp8_header_parser(VP8DParserContext_t *p, RK_U8 *pbase, + RK_U32 size) +{ + RK_U32 tmp; + int i, j; + vpBoolCoder_t *bit_ctx = &p->bitstr; + + FUN_T("FUN_IN"); + if (p->keyFrame) { + tmp = (pbase[0] << 16) | (pbase[1] << 8) | (pbase[2] << 0); + if (tmp != VP8_KEY_FRAME_START_CODE) + return MPP_ERR_PROTOL; + tmp = (pbase[3] << 0) | (pbase[4] << 8); + p->width = tmp & 0x3fff; + p->scaledWidth = ScaleDimension(p->width, tmp >> 14); + tmp = (pbase[5] << 0) | (pbase[6] << 8); + p->height = tmp & 0x3fff; + p->scaledHeight = ScaleDimension(p->height, tmp >> 14); + pbase += 7; + size -= 7; + } + vp8hwdBoolStart(bit_ctx, pbase, size); + if (p->keyFrame) { + p->colorSpace = (vpColorSpace_e)vp8hwdDecodeBool128(bit_ctx); + p->clamping = vp8hwdDecodeBool128(bit_ctx); + } + p->segmentationEnabled = vp8hwdDecodeBool128(bit_ctx); + p->segmentationMapUpdate = 0; + if (p->segmentationEnabled) { + p->segmentationMapUpdate = vp8hwdDecodeBool128(bit_ctx); + if (vp8hwdDecodeBool128(bit_ctx)) { /* Segmentation map update */ + p->segmentFeatureMode = vp8hwdDecodeBool128(bit_ctx); + memset(&p->segmentQp[0], 0, MAX_NBR_OF_SEGMENTS * sizeof(RK_S32)); + memset(&p->segmentLoopfilter[0], 0, + MAX_NBR_OF_SEGMENTS * sizeof(RK_S32)); + for (i = 0; i < MAX_NBR_OF_SEGMENTS; i++) { + if (vp8hwdDecodeBool128(bit_ctx)) { + p->segmentQp[i] = vp8hwdReadBits(bit_ctx, 7); + if (vp8hwdDecodeBool128(bit_ctx)) + p->segmentQp[i] = -p->segmentQp[i]; + } + } + for (i = 0; i < MAX_NBR_OF_SEGMENTS; i++) { + if (vp8hwdDecodeBool128(bit_ctx)) { + p->segmentLoopfilter[i] = vp8hwdReadBits(bit_ctx, 6); + if (vp8hwdDecodeBool128(bit_ctx)) + p->segmentLoopfilter[i] = -p->segmentLoopfilter[i]; + } + } + } + if (p->segmentationMapUpdate) { + p->probSegment[0] = 255; + p->probSegment[1] = 255; + p->probSegment[2] = 255; + for (i = 0; i < 3; i++) { + if (vp8hwdDecodeBool128(bit_ctx)) { + p->probSegment[i] = vp8hwdReadBits(bit_ctx, 8); + } + } + } + if (bit_ctx->strmError) { + mpp_err_f("paser header stream no enough"); + FUN_T("FUN_OUT"); + return MPP_ERR_STREAM; + } + } + p->loopFilterType = vp8hwdDecodeBool128(bit_ctx); + p->loopFilterLevel = vp8hwdReadBits(bit_ctx, 6); + p->loopFilterSharpness = vp8hwdReadBits(bit_ctx, 3); + p->modeRefLfEnabled = vp8hwdDecodeBool128(bit_ctx); + if (p->modeRefLfEnabled) { + if (vp8hwdDecodeBool128(bit_ctx)) { + for (i = 0; i < MAX_NBR_OF_MB_REF_LF_DELTAS; i++) { + if (vp8hwdDecodeBool128(bit_ctx)) { + p->mbRefLfDelta[i] = vp8hwdReadBits(bit_ctx, 6); + if (vp8hwdDecodeBool128(bit_ctx)) + p->mbRefLfDelta[i] = -p->mbRefLfDelta[i]; + } + } + for (i = 0; i < MAX_NBR_OF_MB_MODE_LF_DELTAS; i++) { + if (vp8hwdDecodeBool128(&p->bitstr)) { + p->mbModeLfDelta[i] = vp8hwdReadBits(bit_ctx, 6); + if (vp8hwdDecodeBool128(bit_ctx)) + p->mbModeLfDelta[i] = -p->mbModeLfDelta[i]; + } + } + } + } + if (bit_ctx->strmError) { + mpp_err_f("paser header stream no enough"); + FUN_T("FUN_OUT"); + return MPP_ERR_STREAM; + } + p->nbrDctPartitions = vp8hwdReadBits(bit_ctx, 2); + p->qpYAc = vp8hwdReadBits(bit_ctx, 7); + p->qpYDc = DecodeQuantizerDelta(bit_ctx); + p->qpY2Dc = DecodeQuantizerDelta(bit_ctx); + p->qpY2Ac = DecodeQuantizerDelta(bit_ctx); + p->qpChDc = DecodeQuantizerDelta(bit_ctx); + p->qpChAc = DecodeQuantizerDelta(bit_ctx); + if (p->keyFrame) { + p->refreshGolden = 1; + p->refreshAlternate = 1; + p->copyBufferToGolden = 0; + p->copyBufferToAlternate = 0; + + /* Refresh entropy probs */ + p->refreshEntropyProbs = vp8hwdDecodeBool128(bit_ctx); + + p->refFrameSignBias[0] = 0; + p->refFrameSignBias[1] = 0; + p->refreshLast = 1; + } else { + /* Refresh golden */ + p->refreshGolden = vp8hwdDecodeBool128(bit_ctx); + /* Refresh alternate */ + p->refreshAlternate = vp8hwdDecodeBool128(bit_ctx); + if ( p->refreshGolden == 0 ) { + /* Copy to golden */ + p->copyBufferToGolden = vp8hwdReadBits(bit_ctx, 2); + } else + p->copyBufferToGolden = 0; + + if ( p->refreshAlternate == 0 ) { + /* Copy to alternate */ + p->copyBufferToAlternate = vp8hwdReadBits(bit_ctx, 2); + } else + p->copyBufferToAlternate = 0; + + /* Sign bias for golden frame */ + p->refFrameSignBias[0] = vp8hwdDecodeBool128(bit_ctx); + /* Sign bias for alternate frame */ + p->refFrameSignBias[1] = vp8hwdDecodeBool128(bit_ctx); + /* Refresh entropy probs */ + p->refreshEntropyProbs = vp8hwdDecodeBool128(bit_ctx); + /* Refresh last */ + p->refreshLast = vp8hwdDecodeBool128(bit_ctx); + } + + /* Make a "backup" of current entropy probabilities if refresh is not set */ + if (p->refreshEntropyProbs == 0) { + memcpy((void*)&p->entropyLast, (void*)&p->entropy, + (unsigned long)sizeof(vp8EntropyProbs_t)); + memcpy( (void*)p->vp7PrevScanOrder, (void*)p->vp7ScanOrder, + (unsigned long)sizeof(p->vp7ScanOrder)); + } + + vp8hwdDecodeCoeffUpdate(p); + p->coeffSkipMode = vp8hwdDecodeBool128(bit_ctx); + if (!p->keyFrame) { + RK_U32 mvProbs; + if (p->coeffSkipMode) + p->probMbSkipFalse = vp8hwdReadBits(bit_ctx, 8); + p->probIntra = vp8hwdReadBits(bit_ctx, 8); + p->probRefLast = vp8hwdReadBits(bit_ctx, 8); + p->probRefGolden = vp8hwdReadBits(bit_ctx, 8); + if (vp8hwdDecodeBool128(bit_ctx)) { + for (i = 0; i < 4; i++) + p->entropy.probLuma16x16PredMode[i] = vp8hwdReadBits(bit_ctx, 8); + } + if (vp8hwdDecodeBool128(bit_ctx)) { + for (i = 0; i < 3; i++) + p->entropy.probChromaPredMode[i] = vp8hwdReadBits(bit_ctx, 8); + } + mvProbs = VP8_MV_PROBS_PER_COMPONENT; + for ( i = 0 ; i < 2 ; ++i ) { + for ( j = 0 ; j < (RK_S32)mvProbs ; ++j ) { + if (vp8hwdDecodeBool(bit_ctx, MvUpdateProbs[i][j]) == 1) { + tmp = vp8hwdReadBits(bit_ctx, 7); + if ( tmp ) + tmp = tmp << 1; + else + tmp = 1; + p->entropy.probMvContext[i][j] = tmp; + } + } + } + } else { + if (p->coeffSkipMode) + p->probMbSkipFalse = vp8hwdReadBits(bit_ctx, 8); + } + if (bit_ctx->strmError) { + mpp_err_f("paser header stream no enough"); + FUN_T("FUN_OUT"); + return MPP_ERR_STREAM; + } + FUN_T("FUN_OUT"); + return MPP_OK; +} + +static MPP_RET +vp7_header_parser(VP8DParserContext_t *p, RK_U8 *pbase, RK_U32 size) +{ + RK_U32 tmp; + int i, j; + + FUN_T("FUN_IN"); + vpBoolCoder_t *bit_ctx = &p->bitstr; + vp8hwdBoolStart(bit_ctx, pbase, size); + + if (p->keyFrame) { + p->width = vp8hwdReadBits(bit_ctx, 12); + p->height = vp8hwdReadBits(bit_ctx, 12); + tmp = vp8hwdReadBits(bit_ctx, 2); + p->scaledWidth = ScaleDimension(p->width, tmp); + tmp = vp8hwdReadBits(bit_ctx, 2); + p->scaledHeight = ScaleDimension(p->height, tmp); + } + { + const RK_U32 vp70FeatureBits[4] = { 7, 6, 0, 8 }; + const RK_U32 vp71FeatureBits[4] = { 7, 6, 0, 5 }; + const RK_U32 *featureBits; + if (p->vpVersion == 0) + featureBits = vp70FeatureBits; + else + featureBits = vp71FeatureBits; + for (i = 0; i < MAX_NBR_OF_VP7_MB_FEATURES; i++) { + if (vp8hwdDecodeBool128(bit_ctx)) { + tmp = vp8hwdReadBits(bit_ctx, 8); + for (j = 0; j < 3; j++) { + if (vp8hwdDecodeBool128(bit_ctx)) + tmp = vp8hwdReadBits(bit_ctx, 8); + } + if (featureBits[i]) { + for (j = 0; j < 4; j++) { + if (vp8hwdDecodeBool128(bit_ctx)) + tmp = vp8hwdReadBits(bit_ctx, featureBits[i]); + } + } + FUN_T("FUN_OUT"); + return MPP_ERR_PROTOL; + } + + } + p->nbrDctPartitions = 0; + } + p->qpYAc = (RK_S32)vp8hwdReadBits(bit_ctx, 7 ); + p->qpYDc = (vp8hwdReadBits(bit_ctx, 1) != 0) + ? (RK_S32)vp8hwdReadBits(bit_ctx, 7 ) : p->qpYAc; + p->qpY2Dc = (vp8hwdReadBits(bit_ctx, 1) != 0) + ? (RK_S32)vp8hwdReadBits(bit_ctx, 7 ) : p->qpYAc; + p->qpY2Ac = (vp8hwdReadBits(bit_ctx, 1) != 0) + ? (RK_S32)vp8hwdReadBits(bit_ctx, 7 ) : p->qpYAc; + p->qpChDc = (vp8hwdReadBits(bit_ctx, 1) != 0) + ? (RK_S32)vp8hwdReadBits(bit_ctx, 7 ) : p->qpYAc; + p->qpChAc = (vp8hwdReadBits(bit_ctx, 1) != 0) + ? (RK_S32)vp8hwdReadBits(bit_ctx, 7 ) : p->qpYAc; + if (!p->keyFrame) { + p->refreshGolden = vp8hwdDecodeBool128(bit_ctx); + if (p->vpVersion >= 1) { + p->refreshEntropyProbs = vp8hwdDecodeBool128(bit_ctx); + p->refreshLast = vp8hwdDecodeBool128(bit_ctx); + } else { + p->refreshEntropyProbs = 1; + p->refreshLast = 1; + } + } else { + p->refreshGolden = 1; + p->refreshAlternate = 1; + p->copyBufferToGolden = 0; + p->copyBufferToAlternate = 0; + if (p->vpVersion >= 1) + p->refreshEntropyProbs = vp8hwdDecodeBool128(bit_ctx); + else + p->refreshEntropyProbs = 1; + p->refFrameSignBias[0] = 0; + p->refFrameSignBias[1] = 0; + p->refreshLast = 1; + } + + if (!p->refreshEntropyProbs) { + memcpy(&p->entropyLast, &p->entropy, + (unsigned long)sizeof(vp8EntropyProbs_t)); + memcpy(p->vp7PrevScanOrder, p->vp7ScanOrder, + (unsigned long)sizeof(p->vp7ScanOrder)); + } + if (p->refreshLast) { + if (vp8hwdDecodeBool128(bit_ctx)) { + tmp = vp8hwdReadBits(bit_ctx, 8); + tmp = vp8hwdReadBits(bit_ctx, 8); + FUN_T("FUN_OUT"); + return MPP_ERR_STREAM; + } + } + if (p->vpVersion == 0) { + p->loopFilterType = vp8hwdDecodeBool128(bit_ctx); + } + if (vp8hwdDecodeBool128(bit_ctx)) { + static const RK_U32 Vp7DefaultScan[] = { + 0, 1, 4, 8, 5, 2, 3, 6, + 9, 12, 13, 10, 7, 11, 14, 15, + }; + p->vp7ScanOrder[0] = 0; + for (i = 1; i < 16; i++) + p->vp7ScanOrder[i] = Vp7DefaultScan[vp8hwdReadBits(bit_ctx, 4)]; + } + if (p->vpVersion >= 1) + p->loopFilterType = vp8hwdDecodeBool128(bit_ctx); + p->loopFilterLevel = vp8hwdReadBits(bit_ctx, 6); + p->loopFilterSharpness = vp8hwdReadBits(bit_ctx, 3); + vp8hwdDecodeCoeffUpdate(p); + if (!p->keyFrame) { + p->probIntra = vp8hwdReadBits(bit_ctx, 8); + p->probRefLast = vp8hwdReadBits(bit_ctx, 8); + if (vp8hwdDecodeBool128(bit_ctx)) { + for (i = 0; i < 4; i++) + p->entropy.probLuma16x16PredMode[i] = + vp8hwdReadBits(bit_ctx, 8); + } + if (vp8hwdDecodeBool128(bit_ctx)) { + for (i = 0; i < 3; i++) + p->entropy.probChromaPredMode[i] = vp8hwdReadBits(bit_ctx, 8); + } + for ( i = 0 ; i < 2 ; ++i ) { + for ( j = 0 ; j < VP7_MV_PROBS_PER_COMPONENT ; ++j ) { + if (vp8hwdDecodeBool(bit_ctx, MvUpdateProbs[i][j])) { + tmp = vp8hwdReadBits(bit_ctx, 7); + if ( tmp ) + tmp = tmp << 1; + else + tmp = 1; + p->entropy.probMvContext[i][j] = tmp; + } + } + } + } + if (bit_ctx->strmError) { + FUN_T("FUN_OUT"); + return MPP_ERR_PROTOL; + } + + FUN_T("FUN_OUT"); + return MPP_OK; +} + +static MPP_RET +vp8hwdSetPartitionOffsets(VP8DParserContext_t *p, RK_U8 *stream, RK_U32 len) +{ + RK_U32 i = 0; + RK_U32 offset = 0; + RK_U32 baseOffset; + RK_U32 extraBytesPacked = 0; + + FUN_T("FUN_IN"); + if (p->decMode == VP8HWD_VP8 && p->keyFrame) + extraBytesPacked += 7; + + stream += p->frameTagSize; + + baseOffset = p->frameTagSize + p->offsetToDctParts + + 3 * ( (1 << p->nbrDctPartitions) - 1); + + stream += p->offsetToDctParts + extraBytesPacked; + for ( i = 0 ; i < (RK_U32)(1 << p->nbrDctPartitions) - 1 ; ++i ) { + RK_U32 tmp; + + p->dctPartitionOffsets[i] = baseOffset + offset; + tmp = stream[0] | (stream[1] << 8) | (stream[2] << 16); + offset += tmp; + stream += 3; + } + p->dctPartitionOffsets[i] = baseOffset + offset; + + return (p->dctPartitionOffsets[i] < len ? MPP_OK : MPP_ERR_STREAM); +} + +static MPP_RET +decoder_frame_header(VP8DParserContext_t *p, RK_U8 *pbase, RK_U32 size) +{ + MPP_RET ret; + + FUN_T("FUN_IN"); + p->keyFrame = !(pbase[0] & 1); + p->vpVersion = (pbase[0] >> 1) & 7; + p->showFrame = 1; + if (p->keyFrame && !p->needKeyFrame) { + p->needKeyFrame = 1; + } else { + if (!p->needKeyFrame) { + mpp_err("no found key frame"); + return MPP_NOK; + } + } + if (p->decMode == VP8HWD_VP7) { + p->offsetToDctParts = (pbase[0] >> 4) | (pbase[1] << 4) | (pbase[2] << 12); + p->frameTagSize = p->vpVersion >= 1 ? 3 : 4; + } else { + p->offsetToDctParts = (pbase[0] >> 5) | (pbase[1] << 3) | (pbase[2] << 11); +#if 0 + mpp_log("offsetToDctParts %d pbase[0] = 0x%x pbase[1] = 0x%x pbase[2] = 0x%x ", + p->offsetToDctParts, pbase[0], pbase[1], pbase[2]); +#endif + p->showFrame = (pbase[0] >> 4) & 1; + p->frameTagSize = 3; + } + pbase += p->frameTagSize; + size -= p->frameTagSize; + if (p->keyFrame) + vp8hwdResetProbs(p); + //mpp_log_f("p->decMode = %d", p->decMode); + if (p->decMode == VP8HWD_VP8) { + ret = vp8_header_parser(p, pbase, size); + } else { + ret = vp7_header_parser(p, pbase, size); + } + if (ret != MPP_OK) { + return ret; + } + return MPP_OK; +} + +#define IVF_HDR_BYTES 32 +#define IVF_FRM_BYTES 12 + +static void write_ivf_header(VP8DParserContext_t *ctx, FILE *fp) +{ + RK_U8 data[IVF_HDR_BYTES] = {0}; + + data[0] = 'D'; + data[1] = 'K'; + data[2] = 'I'; + data[3] = 'F'; + + data[6] = 32; + + data[8] = 'V'; + data[9] = 'P'; + data[10] = '8'; + data[11] = '0'; + + data[12] = ctx->width & 0xff; + data[13] = (ctx->width >> 8) & 0xff; + data[14] = ctx->height & 0xff; + data[15] = (ctx->height >> 8) & 0xff; + + data[16] = 30; + data[17] = data[18] = data[19] = 0; + + data[20] = 1; + data[21] = data[22] = data[23] = 0; + + data[24] = data[25] = data[26] = data[27] = 0xff; + + fwrite(data, IVF_HDR_BYTES, 1, fp); +} + +static void write_ivf_frame(FILE *fp, RK_U32 frame_size, RK_U64 frame_cnt) +{ + RK_U8 data[IVF_FRM_BYTES]; + + data[0] = frame_size & 0xff; + data[1] = (frame_size >> 8) & 0xff; + data[2] = (frame_size >> 16) & 0xff; + data[3] = (frame_size >> 24) & 0xff; + + data[4] = frame_cnt & 0xff; + data[5] = (frame_cnt >> 8) & 0xff; + data[6] = (frame_cnt >> 16) & 0xff; + data[7] = (frame_cnt >> 24) & 0xff; + data[8] = (frame_cnt >> 32) & 0xff; + data[9] = (frame_cnt >> 40) & 0xff; + data[10] = (frame_cnt >> 48) & 0xff; + data[11] = (frame_cnt >> 56) & 0xff; + + fwrite(data, IVF_FRM_BYTES, 1, fp); +} + +MPP_RET vp8d_parser_parse(void *ctx, HalDecTask *in_task) +{ + MPP_RET ret = MPP_OK; + VP8DContext *c = (VP8DContext *)ctx; + VP8DParserContext_t *p = (VP8DParserContext_t *)c->parse_ctx; + FUN_T("FUN_IN"); + + ret = decoder_frame_header(p, p->bitstream_sw_buf, p->stream_size); + + if (MPP_OK != ret) { + mpp_err("decoder_frame_header err ret %d", ret); + FUN_T("FUN_OUT"); + return ret; + } + + vp8hwdSetPartitionOffsets(p, p->bitstream_sw_buf, p->stream_size); + + ret = vp8d_alloc_frame(p); + if (MPP_OK != ret) { + mpp_err("vp8d_alloc_frame err ret %d", ret); + FUN_T("FUN_OUT"); + return ret; + } + + vp8d_convert_to_syntx(p, in_task); + /* Rollback entropy probabilities if refresh is not set */ + if (p->refreshEntropyProbs == 0) { + memcpy((void*)&p->entropy, (void*)&p->entropyLast, + (unsigned long)sizeof(vp8EntropyProbs_t)); + memcpy((void*)p->vp7ScanOrder, (void*)p->vp7PrevScanOrder, + (unsigned long)sizeof(p->vp7ScanOrder)); + } + in_task->syntax.data = (void *)p->dxva_ctx; + in_task->syntax.number = 1; + in_task->output = p->frame_out->slot_index; + in_task->valid = 1; + if (p->eos) { + in_task->flags.eos = p->eos; + } + vp8d_ref_update(p); + + if (vp8d_debug & VP8D_DBG_DUMP_STREAM) { + if (!p->stream_fp) { + char name[256]; + + sprintf(name, "/data/video/mpp_dec_vp8_%d.bin", getpid()); + p->stream_fp = fopen(name, "wb"); + } + if (p->stream_fp) { + if (!p->ivf_header_flag) { + write_ivf_header(p, p->stream_fp); + p->ivf_header_flag = 1; + } + write_ivf_frame(p->stream_fp, p->stream_size, p->frame_cnt); + fwrite(p->bitstream_sw_buf, 1, p->stream_size, p->stream_fp); + fflush(p->stream_fp); + } + } + p->frame_cnt++; + + FUN_T("FUN_OUT"); + return ret; +} + +MPP_RET vp8d_parser_callback(void *ctx, void *hal_info) +{ + MPP_RET ret = MPP_OK; + FUN_T("FUN_IN"); + (void)ctx; + (void)hal_info; + FUN_T("FUN_OUT"); + return ret; +} diff --git a/mpp/codec/dec/vp8/vp8d_parser.h b/mpp/codec/dec/vp8/vp8d_parser.h new file mode 100644 index 000000000..8ab02fce1 --- /dev/null +++ b/mpp/codec/dec/vp8/vp8d_parser.h @@ -0,0 +1,197 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VP8D_PARSER_H +#define VP8D_PARSER_H + +#include + +#include "parser_api.h" +#include "vp8d_syntax.h" +#include "vp8d_data.h" + +#define VP8HWD_VP7 1 +#define VP8HWD_VP8 2 +#define VP8HWD_WEBP 3 + +#define DEC_MODE_VP7 9 +#define DEC_MODE_VP8 10 + +#define MAX_NBR_OF_SEGMENTS (4) +#define MAX_NBR_OF_MB_REF_LF_DELTAS (4) +#define MAX_NBR_OF_MB_MODE_LF_DELTAS (4) + +#define MAX_NBR_OF_DCT_PARTITIONS (8) + +#define MAX_NBR_OF_VP7_MB_FEATURES (4) + +#define VP8D_BUF_SIZE_BITMEM (512 * 1024) +#define VP8D_PROB_TABLE_SIZE (1<<16) /* TODO */ +#define VP8D_MAX_SEGMAP_SIZE (2048 + 1024) //1920*1080 +#define VP8_KEY_FRAME_START_CODE 0x9d012a + +#define VP8D_DBG_FUNCTION (0x00000001) +#define VP8D_DBG_WARNNING (0x00000004) +#define VP8D_DBG_LOG (0x00000008) +#define VP8D_DBG_SEC_HEADER (0x00000010) +#define VP8D_DBG_DUMP_STREAM (0x00001000) + + +typedef enum { + VP8_YCbCr_BT601, + VP8_CUSTOM +} vpColorSpace_e; + +typedef struct { + RK_U32 lowvalue; + RK_U32 range; + RK_U32 value; + RK_S32 count; + RK_U32 pos; + RK_U8 *buffer; + RK_U32 BitCounter; + RK_U32 streamEndPos; + RK_U32 strmError; +} vpBoolCoder_t; + +typedef struct { + RK_U8 probLuma16x16PredMode[4]; + RK_U8 probChromaPredMode[3]; + RK_U8 probMvContext[2][VP8_MV_PROBS_PER_COMPONENT]; + RK_U8 probCoeffs[4][8][3][11]; +} vp8EntropyProbs_t; + +typedef struct VP8Frame { + MppFrame f; + RK_S32 slot_index; + RK_S8 ref_count; + RK_U8 invisible; +} VP8Frame; + + +typedef struct VP8DParserContext { + DXVA_PicParams_VP8 *dxva_ctx; + RK_U8 *bitstream_sw_buf; + RK_U32 max_stream_size; + RK_U32 stream_size; + + VP8Frame *frame_out; + VP8Frame *frame_ref; + VP8Frame *frame_golden; + VP8Frame *frame_alternate; + + vpBoolCoder_t bitstr; + + RK_U32 decMode; + + /* Current frame dimensions */ + RK_U32 width; + RK_U32 height; + RK_U32 scaledWidth; + RK_U32 scaledHeight; + + RK_U8 vpVersion; + RK_U32 vpProfile; + + RK_U32 keyFrame; + + RK_U8 coeffSkipMode; + + /* DCT coefficient partitions */ + RK_U32 offsetToDctParts; + RK_U32 nbrDctPartitions; + RK_U32 dctPartitionOffsets[MAX_NBR_OF_DCT_PARTITIONS]; + + vpColorSpace_e colorSpace; + RK_U32 clamping; + RK_U32 showFrame; + + + RK_U32 refreshGolden; + RK_U32 refreshAlternate; + RK_U32 refreshLast; + RK_U32 refreshEntropyProbs; + RK_U32 copyBufferToGolden; + RK_U32 copyBufferToAlternate; + + RK_U32 refFrameSignBias[2]; + RK_U32 useAsReference; + RK_U32 loopFilterType; + RK_U32 loopFilterLevel; + RK_U32 loopFilterSharpness; + + /* Quantization parameters */ + RK_S8 qpYAc, qpYDc, qpY2Ac, qpY2Dc, qpChAc, qpChDc; + + /* From here down, frame-to-frame persisting stuff */ + RK_U32 vp7ScanOrder[16]; + RK_U32 vp7PrevScanOrder[16]; + + /* Probabilities */ + RK_U32 probIntra; + RK_U32 probRefLast; + RK_U32 probRefGolden; + RK_U32 probMbSkipFalse; + RK_U32 probSegment[3]; + vp8EntropyProbs_t entropy, entropyLast; + + /* Segment and macroblock specific values */ + RK_U32 segmentationEnabled; + RK_U32 segmentationMapUpdate; + RK_U32 segmentFeatureMode; /* delta/abs */ + RK_S32 segmentQp[MAX_NBR_OF_SEGMENTS]; + RK_S32 segmentLoopfilter[MAX_NBR_OF_SEGMENTS]; + RK_U32 modeRefLfEnabled; + RK_S32 mbRefLfDelta[MAX_NBR_OF_MB_REF_LF_DELTAS]; + RK_S32 mbModeLfDelta[MAX_NBR_OF_MB_MODE_LF_DELTAS]; + + RK_U32 frameTagSize; + + /* Value to remember last frames prediction for hits into most + * probable reference frame */ + RK_U32 refbuPredHits; + + + RK_S32 dcPred[2]; + RK_S32 dcMatch[2]; + + RK_U32 frame_cnt; + RK_U64 pts; + RK_U64 dts; + + RK_U32 needKeyFrame; + MppPacket input_packet; + RK_U32 eos; + + MppBufSlots packet_slots; + MppBufSlots frame_slots; + /* for debug */ + FILE *stream_fp; + RK_U32 ivf_header_flag; +} VP8DParserContext_t; + +MPP_RET vp8d_parser_init (void *ctx, ParserCfg *cfg); +MPP_RET vp8d_parser_deinit (void *ctx); +MPP_RET vp8d_parser_reset (void *ctx); +MPP_RET vp8d_parser_flush (void *ctx); +MPP_RET vp8d_parser_control(void *ctx, MpiCmd cmd_type, void *param); +MPP_RET vp8d_parser_prepare(void *ctx, MppPacket pkt, HalDecTask *task); +MPP_RET vp8d_parser_parse (void *ctx, HalDecTask *task); +MPP_RET vp8d_parser_callback(void *ctx, void *hal_info); + +#endif + diff --git a/mpp/codec/dec/vp9/CMakeLists.txt b/mpp/codec/dec/vp9/CMakeLists.txt index b66fe4acf..c4570c954 100644 --- a/mpp/codec/dec/vp9/CMakeLists.txt +++ b/mpp/codec/dec/vp9/CMakeLists.txt @@ -1 +1,9 @@ # vim: syntax=cmake +include_directories(.) + +# vp9 decoder sourse +add_library(vp9d_api OBJECT + vp9d_api.c + vp9d.c + vp9d_codec.c + ) diff --git a/mpp/codec/dec/vp9/vp9d.c b/mpp/codec/dec/vp9/vp9d.c new file mode 100644 index 000000000..9297d5b86 --- /dev/null +++ b/mpp/codec/dec/vp9/vp9d.c @@ -0,0 +1,1942 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#include + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_bitread.h" +#include "mpp_packet_impl.h" +#include "mpp_compat_impl.h" + +#include "vp9d_ctx.h" +#include "vp9d.h" +#include "mpp_frame_impl.h" + +//#define dump +#ifdef dump +static FILE *vp9_p_fp = NULL; +static FILE *vp9_p_fp1 = NULL; +static FILE *vp9_p_fp2 = NULL; +static RK_S32 dec_num = 0; +static RK_S32 count = 0; +#endif + +static void split_parse_frame(VP9SplitCtx *ctx, RK_U8 *buf, RK_S32 size) +{ + VP9ParseCtx *s = (VP9ParseCtx *)ctx->priv_data; + + if (buf[0] & 0x4) { + ctx->key_frame = 0; + } else { + ctx->key_frame = 1; + } + + if (buf[0] & 0x2) { + if (ctx->pts == -1) + ctx->pts = s->pts; + s->pts = -1; + } else { + s->pts = ctx->pts; + ctx->pts = -1; + } + + (void)size; +} + +RK_S32 vp9d_split_frame(VP9SplitCtx *ctx, RK_U8 **out_data, RK_S32 *out_size, + RK_U8 *data, RK_S32 size) +{ + VP9ParseCtx *s = (VP9ParseCtx *)ctx->priv_data; + RK_S32 full_size = size; + RK_S32 marker; + + if (size <= 0) { + *out_size = 0; + *out_data = data; + + return 0; + } + + if (s->n_frames > 0) { + *out_data = data; + *out_size = s->size[--s->n_frames]; + split_parse_frame(ctx, *out_data, *out_size); + + return s->n_frames > 0 ? *out_size : size; + } + + marker = data[size - 1]; + if ((marker & 0xe0) == 0xc0) { + RK_S32 nbytes = 1 + ((marker >> 3) & 0x3); + RK_S32 n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes; + + if (size >= idx_sz && data[size - idx_sz] == marker) { + RK_U8 *idx = data + size + 1 - idx_sz; + RK_S32 first = 1; + + switch (nbytes) { +#define case_n(a, rd) \ + case a: \ + while (n_frames--) { \ + RK_U32 sz = rd; \ + idx += a; \ + if (sz == 0 || sz > (RK_U32)size) { \ + s->n_frames = 0; \ + *out_size = size > full_size ? full_size : size; \ + *out_data = data; \ + mpp_err("Superframe packet size too big: %u > %d\n", \ + sz, size); \ + return full_size; \ + } \ + if (first) { \ + first = 0; \ + *out_data = data; \ + *out_size = sz; \ + s->n_frames = n_frames; \ + } else { \ + s->size[n_frames] = sz; \ + } \ + data += sz; \ + size -= sz; \ + } \ + split_parse_frame(ctx, *out_data, *out_size); \ + return *out_size + + case_n(1, *idx); + case_n(2, MPP_RL16(idx)); + case_n(3, MPP_RL24(idx)); + case_n(4, MPP_RL32(idx)); + } + } + } + + *out_data = data; + *out_size = size; + split_parse_frame(ctx, data, size); + return size; +} + +MPP_RET vp9d_get_frame_stream(Vp9DecCtx *ctx, RK_U8 *buf, RK_S32 length) +{ + RK_U8 *data = (RK_U8 *)mpp_packet_get_data(ctx->pkt); + RK_S32 size = (RK_S32)mpp_packet_get_size(ctx->pkt); + RK_S32 buff_size = 0; + + if (length > size) { + mpp_free(data); + mpp_packet_deinit(&ctx->pkt); + buff_size = length + 10 * 1024; + data = mpp_malloc(RK_U8, buff_size); + mpp_packet_init(&ctx->pkt, (void *)data, length); + mpp_packet_set_size(ctx->pkt, buff_size); + } + + memcpy(data, buf, length); + mpp_packet_set_length(ctx->pkt, length); + + return MPP_OK; +} + +MPP_RET vp9d_split_init(Vp9DecCtx *vp9_ctx) +{ + VP9SplitCtx *ps; + VP9ParseCtx *sc; + + ps = (VP9SplitCtx *)mpp_calloc(VP9SplitCtx, 1); + if (!ps) { + mpp_err("vp9 parser malloc fail"); + return MPP_ERR_NOMEM; + } + + sc = (VP9ParseCtx *)mpp_calloc(VP9ParseCtx, 1); + if (!sc) { + mpp_err("vp9 parser context malloc fail"); + mpp_free(ps); + return MPP_ERR_NOMEM; + } + + ps->priv_data = (void*)sc; + vp9_ctx->priv_data2 = (void*)ps; + + return MPP_OK; +} + +MPP_RET vp9d_split_deinit(Vp9DecCtx *vp9_ctx) +{ + VP9SplitCtx *ps = (VP9SplitCtx *)vp9_ctx->priv_data2; + + if (ps) + MPP_FREE(ps->priv_data); + MPP_FREE(vp9_ctx->priv_data2); + + return MPP_OK; +} + +static RK_S32 vp9_ref_frame(Vp9DecCtx *ctx, VP9Frame *dst, VP9Frame *src) +{ + VP9Context *s = ctx->priv_data; + MppFrameImpl *impl_frm = (MppFrameImpl *)dst->f; + + if (src->ref == NULL || src->slot_index >= 0x7f) { + mpp_err("vp9_ref_frame is vaild"); + return -1; + } + dst->slot_index = src->slot_index; + dst->ref = src->ref; + dst->ref->show_frame_flag = src->ref->show_frame_flag; + dst->ref->ref_count++; + vp9d_dbg(VP9D_DBG_REF, "get prop slot frame %p count %d", dst->f, dst->ref->ref_count); + mpp_buf_slot_get_prop(s->slots, src->slot_index, SLOT_FRAME, &dst->f); + impl_frm->buffer = NULL; //parser no need process hal buf + vp9d_dbg(VP9D_DBG_REF, "get prop slot frame after %p", dst->f); + return 0; +} + +static void vp9_unref_frame( VP9Context *s, VP9Frame *f) +{ + if (f->ref->ref_count <= 0 || f->slot_index >= 0x7f) { + mpp_err("ref count alreay is zero"); + return; + } + f->ref->ref_count--; + if (!f->ref->ref_count) { + if (f->slot_index <= 0x7f) { + if (f->ref->show_frame_flag && !f->ref->is_output) { + MppBuffer framebuf = NULL; + + mpp_buf_slot_get_prop(s->slots, f->slot_index, SLOT_BUFFER, &framebuf); + mpp_buffer_put(framebuf); + f->ref->show_frame_flag = 0; + } + mpp_buf_slot_clr_flag(s->slots, f->slot_index, SLOT_CODEC_USE); + } + mpp_free(f->ref); + f->slot_index = 0xff; + f->ref = NULL; + } + f->ref = NULL; + return; +} + +static RK_S32 vp9_frame_free(VP9Context *s) +{ + RK_S32 i; + + for (i = 0; i < 3; i++) { + if (s->frames[i].ref) { + vp9_unref_frame(s, &s->frames[i]); + } + mpp_frame_deinit(&s->frames[i].f); + } + for (i = 0; i < 8; i++) { + if (s->refs[i].ref) { + vp9_unref_frame(s, &s->refs[i]); + } + mpp_frame_deinit(&s->refs[i].f); + } + return 0; +} + +static RK_S32 vp9_frame_init(VP9Context *s) +{ + RK_S32 i; + + for (i = 0; i < 3; i++) { + mpp_frame_init(&s->frames[i].f); + if (!s->frames[i].f) { + vp9_frame_free(s); + mpp_err("Failed to allocate frame buffer %d\n", i); + return MPP_ERR_NOMEM; + } + s->frames[i].slot_index = 0x7f; + s->frames[i].ref = NULL; + } + + for (i = 0; i < 8; i++) { + mpp_frame_init(&(s->refs[i].f)); + if (!s->refs[i].f) { + vp9_frame_free(s); + mpp_err("Failed to allocate frame buffer %d\n", i); + return MPP_ERR_NOMEM; + } + s->refs[i].slot_index = 0x7f; + s->refs[i].ref = NULL; + } + + return MPP_OK; +} + +MPP_RET vp9d_parser_init(Vp9DecCtx *vp9_ctx, ParserCfg *init) +{ + VP9Context *s = mpp_calloc(VP9Context, 1); + + vp9_ctx->priv_data = (void*)s; + if (!vp9_ctx->priv_data) { + mpp_err("vp9 codec context malloc fail"); + return MPP_ERR_NOMEM; + } + + vp9_frame_init(s); + s->last_bpp = 0; + s->filter.sharpness = -1; + +#ifdef dump + count = 0; +#endif + + s->packet_slots = init->packet_slots; + s->slots = init->frame_slots; + s->cfg = init->cfg; + s->hw_info = init->hw_info; + mpp_buf_slot_setup(s->slots, 25); + + mpp_env_get_u32("vp9d_debug", &vp9d_debug, 0); + + return MPP_OK; +} + +MPP_RET vp9d_parser_deinit(Vp9DecCtx *vp9_ctx) +{ + VP9Context *s = vp9_ctx->priv_data; + + vp9_frame_free(s); + mpp_free(s->c_b); + s->c_b_size = 0; + MPP_FREE(vp9_ctx->priv_data); + return MPP_OK; +} + +static RK_S32 vp9_alloc_frame(Vp9DecCtx *ctx, VP9Frame *frame) +{ + VP9Context *s = ctx->priv_data; + + mpp_frame_set_width(frame->f, ctx->width); + mpp_frame_set_height(frame->f, ctx->height); + + mpp_frame_set_hor_stride(frame->f, 0); + mpp_frame_set_ver_stride(frame->f, 0); + mpp_frame_set_errinfo(frame->f, 0); + mpp_frame_set_discard(frame->f, 0); + mpp_frame_set_pts(frame->f, s->pts); + mpp_frame_set_dts(frame->f, s->dts); + // set current poc + s->cur_poc++; + mpp_frame_set_poc(frame->f, s->cur_poc); + + if (MPP_FRAME_FMT_IS_FBC(s->cfg->base.out_fmt)) { + RK_U32 fbc_hdr_stride = mpp_align_64(ctx->width); + + mpp_slots_set_prop(s->slots, SLOTS_HOR_ALIGN, mpp_align_64); + mpp_frame_set_fmt(frame->f, ctx->pix_fmt | ((s->cfg->base.out_fmt & (MPP_FRAME_FBC_MASK)))); + + if (*compat_ext_fbc_hdr_256_odd) + fbc_hdr_stride = mpp_align_256_odd(ctx->width); + + mpp_frame_set_fbc_hdr_stride(frame->f, fbc_hdr_stride); + } else { + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3576) + mpp_slots_set_prop(s->slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + else + mpp_slots_set_prop(s->slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + mpp_slots_set_prop(s->slots, SLOTS_VER_ALIGN, mpp_align_64); + if (MPP_FRAME_FMT_IS_TILE(s->cfg->base.out_fmt)) + mpp_frame_set_fmt(frame->f, ctx->pix_fmt | ((s->cfg->base.out_fmt & (MPP_FRAME_TILE_FLAG)))); + else + mpp_frame_set_fmt(frame->f, ctx->pix_fmt); + } + + if (s->cfg->base.enable_thumbnail && s->hw_info->cap_down_scale) + mpp_frame_set_thumbnail_en(frame->f, s->cfg->base.enable_thumbnail); + else + mpp_frame_set_thumbnail_en(frame->f, 0); + + mpp_buf_slot_get_unused(s->slots, &frame->slot_index); + mpp_buf_slot_set_prop(s->slots, frame->slot_index, SLOT_FRAME, frame->f); + mpp_buf_slot_set_flag(s->slots, frame->slot_index, SLOT_CODEC_USE); + mpp_buf_slot_set_flag(s->slots, frame->slot_index, SLOT_HAL_OUTPUT); + frame->ref = mpp_calloc(VP9RefInfo, 1); + frame->ref->ref_count++; + frame->ref->show_frame_flag = s->show_frame_flag; + frame->ref->is_output = 0; + + return 0; +} + +static MPP_RET update_size(Vp9DecCtx *ctx, RK_S32 w, RK_S32 h, RK_S32 fmt) +{ + VP9Context *s = ctx->priv_data; + + if (w == ctx->width && h == ctx->height && ctx->pix_fmt == fmt) + return MPP_OK; + + ctx->width = w; + ctx->height = h; + ctx->pix_fmt = fmt; + s->sb_cols = (w + 63) >> 6; + s->sb_rows = (h + 63) >> 6; + s->cols = (w + 7) >> 3; + s->rows = (h + 7) >> 3; + + // these will be re-allocated a little later + if (s->bpp != s->last_bpp) { + s->last_bpp = s->bpp; + } + + return MPP_OK; +} + +static inline RK_S32 read_synccode(BitReadCtx_t *gb) +{ + RK_S32 code0, code1, code2; + + READ_BITS(gb, 8, &code0); // sync code0 + READ_BITS(gb, 8, &code1); // sync code1 + READ_BITS(gb, 8, &code2); // sync code2 + return ((code0 == 0x49) && (code1 == 0x83) && (code2 == 0x42)); +__BITREAD_ERR: + return 0; +} + +static const MppFrameColorSpace colorspaces_table[8] = { + MPP_FRAME_SPC_UNSPECIFIED, MPP_FRAME_SPC_BT470BG, MPP_FRAME_SPC_BT709, MPP_FRAME_SPC_SMPTE170M, + MPP_FRAME_SPC_SMPTE240M, MPP_FRAME_SPC_BT2020_NCL, MPP_FRAME_SPC_RESERVED, MPP_FRAME_SPC_RGB, +}; +static MPP_RET read_uncompressed_header(Vp9DecCtx *ctx, const RK_U8 *data, RK_S32 size, + RK_S32 *refo) +{ + VP9Context *s = ctx->priv_data; + RK_S32 fmt = ctx->pix_fmt; + BitReadCtx_t *gb = &s->gb; + RK_S32 i; + RK_U32 w, h; + RK_S32 val; + + /* general header */ + mpp_set_bitread_ctx(gb, (RK_U8*)data, size); + +#define VP9_FRAME_MARKER 0x2 + READ_BITS(gb, 2, &val); // frame marker + if (val != VP9_FRAME_MARKER) { + mpp_err("Invalid frame marker\n"); + return MPP_ERR_STREAM; + } + // read profile + READ_ONEBIT(gb, &val); + ctx->profile = val; + READ_ONEBIT(gb, &val); + ctx->profile |= val << 1; + if (ctx->profile > 2) { + READ_ONEBIT(gb, &val); + ctx->profile += val; + } + if (ctx->profile != VP9_PROFILE_0 && ctx->profile != VP9_PROFILE_2) { + mpp_err("Profile %d is not yet supported\n", ctx->profile); + return MPP_ERR_STREAM; + } + vp9d_dbg(VP9D_DBG_HEADER, "profile %d", ctx->profile); + + READ_ONEBIT(gb, &s->show_existing_frame); + vp9d_dbg(VP9D_DBG_HEADER, "show_existing_frame %d", s->show_existing_frame); + if (s->show_existing_frame) { + READ_BITS(gb, 3, refo); + vp9d_dbg(VP9D_DBG_HEADER, "frame_to_show %d", *refo); + return 0; + } + + s->last_keyframe = s->keyframe; + READ_ONEBIT(gb, &val); + s->keyframe = !val; + vp9d_dbg(VP9D_DBG_HEADER, "keyframe %d", s->keyframe); + RK_S32 last_invisible = s->show_frame_flag; + READ_ONEBIT(gb, &val); + s->show_frame_flag = !val; + vp9d_dbg(VP9D_DBG_HEADER, "show_frame_flag %d", s->show_frame_flag); + READ_ONEBIT(gb, &s->error_res_mode); + vp9d_dbg(VP9D_DBG_HEADER, "error_resilient_mode %d", s->error_res_mode); + s->use_last_frame_mvs = !s->error_res_mode && !last_invisible; + s->got_keyframes += s->keyframe ? 1 : 0; + vp9d_dbg(VP9D_DBG_HEADER, "keyframe=%d, intraonly=%d, got_keyframes=%d\n", + s->keyframe, s->intraonly, s->got_keyframes); + + if (!s->got_keyframes) { + mpp_err_f("have not got keyframe.\n"); + return MPP_ERR_STREAM; + } + + /* set mvscale default */ + for (i = 0; i < 3; i++) { + s->mvscale[i][0] = 16; + s->mvscale[i][1] = 16; + } + + if (s->keyframe) { + if (!read_synccode(gb)) { + mpp_err("Invalid sync code\n"); + return MPP_ERR_STREAM; + } + // read bitdepth colorspace sampling + { + RK_S32 bits = 0; // 0:8, 1:10, 2:12 + if (ctx->profile == VP9_PROFILE_2) { + READ_ONEBIT(gb, &bits); + bits += 1; + } + fmt = bits ? MPP_FMT_YUV420SP_10BIT : MPP_FMT_YUV420SP; + vp9d_dbg(VP9D_DBG_HEADER, "bit_depth %d", 8 + bits * 2); + s->bpp_index = bits; + s->bpp = 8 + bits * 2; + s->bytesperpixel = (7 + s->bpp) >> 3; + READ_BITS(gb, 3, &val); // color_space + ctx->colorspace = colorspaces_table[val]; + vp9d_dbg(VP9D_DBG_HEADER, "color_space %d", ctx->colorspace); + if (ctx->colorspace == MPP_FRAME_SPC_RGB) { // RGB = profile 1 VP9_CS_SRGB + mpp_err("RGB not supported in profile %d\n", ctx->profile); + return MPP_ERR_STREAM; + } else { // profile 0/2 + READ_ONEBIT(gb, &val); + ctx->color_range = val ? MPP_FRAME_RANGE_JPEG : MPP_FRAME_RANGE_MPEG; + vp9d_dbg(VP9D_DBG_HEADER, "color_range %d", ctx->color_range); + s->extra_plane = 0; + s->subsampling_x = s->subsampling_y = 1; + } + } + + s->refresh_frame_flags = 0xff; + READ_BITS(gb, 16, &w); + w += 1; + vp9d_dbg(VP9D_DBG_HEADER, "frame_size_width %d", w); + READ_BITS(gb, 16, &h); + h += 1; + vp9d_dbg(VP9D_DBG_HEADER, "frame_size_height %d", h); + // display size + READ_ONEBIT(gb, &val); + if (val) { + RK_S32 dw, dh; + vp9d_dbg(VP9D_DBG_HEADER, "display_info_flag %d", 1); + READ_BITS(gb, 16, &dw); + dw += 1; + vp9d_dbg(VP9D_DBG_HEADER, "display_size_width %d", dw); + READ_BITS(gb, 16, &dh); + dh += 1; + vp9d_dbg(VP9D_DBG_HEADER, "display_size_height %d", dh); + } else + vp9d_dbg(VP9D_DBG_HEADER, "display_info_flag %d", 0); + } else { + s->intraonly = 0; + if (s->show_frame_flag) + READ_ONEBIT(gb, &s->intraonly); + vp9d_dbg(VP9D_DBG_HEADER, "intra_only %d", s->intraonly); + s->resetctx = 0; + if (!s->error_res_mode) { + READ_BITS(gb, 2, &s->resetctx); + } + vp9d_dbg(VP9D_DBG_HEADER, "reset_frame_context_value %d", s->resetctx); + if (s->intraonly) { + if (!read_synccode(gb)) { // synccode + mpp_err("Invalid sync code\n"); + return MPP_ERR_STREAM; + } + s->subsampling_x = 1; + s->subsampling_y = 1; + s->bpp = 8; + s->bpp_index = 0; + s->bytesperpixel = 1; + fmt = MPP_FMT_YUV420SP; + ctx->colorspace = MPP_FRAME_SPC_BT470BG; + ctx->color_range = MPP_FRAME_RANGE_JPEG; + + READ_BITS(gb, 8, &s->refresh_frame_flags); + vp9d_dbg(VP9D_DBG_HEADER, "refresh_frame_flags %d", s->refresh_frame_flags); + READ_BITS(gb, 16, &w); + w += 1; + vp9d_dbg(VP9D_DBG_HEADER, "frame_size_width %d", w); + READ_BITS(gb, 16, &h); + h += 1; + vp9d_dbg(VP9D_DBG_HEADER, "frame_size_height %d", h); + // display size + READ_ONEBIT(gb, &val); + vp9d_dbg(VP9D_DBG_HEADER, "display_info_flag %d", val); + if (val) { + RK_S32 dw, dh; + READ_BITS(gb, 16, &dw); + dw += 1; + vp9d_dbg(VP9D_DBG_HEADER, "display_size_width %d", dw); + READ_BITS(gb, 16, &dh); + dh += 1; + vp9d_dbg(VP9D_DBG_HEADER, "display_size_height %d", dh); + } + } else { + READ_BITS(gb, 8, &s->refresh_frame_flags); + vp9d_dbg(VP9D_DBG_HEADER, "refresh_frame_flags %d", s->refresh_frame_flags); + for (i = 0; i < 3; i++) { + READ_BITS(gb, 3, &s->refidx[i]); + READ_ONEBIT(gb, &s->signbias[i]); + s->signbias[i] = s->signbias[i] && !s->error_res_mode; + vp9d_dbg(VP9D_DBG_HEADER, "[%d] refidx %d, signbias %d", i, s->refidx[i], s->signbias[i]); + if (!s->refs[s->refidx[i]].ref) + mpp_err("refidx %d not available\n", s->refidx[i]); + } + // setup frame size with refs + RK_S32 found = 0; + for (i = 0; i < 3; i++) { + READ_ONEBIT(gb, &val); + vp9d_dbg(VP9D_DBG_HEADER, "ref_flag %d", i); + if (val) { + w = mpp_frame_get_width(s->refs[s->refidx[i]].f); + h = mpp_frame_get_height(s->refs[s->refidx[i]].f); + found = 1; + break; + } + } + if (!found) { + READ_BITS(gb, 16, &w); + w += 1; + vp9d_dbg(VP9D_DBG_HEADER, "frame_size_width %d", w); + READ_BITS(gb, 16, &h); + h += 1; + vp9d_dbg(VP9D_DBG_HEADER, "frame_size_height %d", h); + } + + if (w == 0 || h == 0) { + mpp_err("ref frame w:%d h:%d\n", w, h); + return MPP_ERR_STREAM; + } + // set use_last_frame_mvs + s->use_last_frame_mvs &= mpp_frame_get_width(s->frames[VP9_CUR_FRAME].f) == w && + mpp_frame_get_height(s->frames[VP9_CUR_FRAME].f) == h; + // display size + READ_ONEBIT(gb, &val); + vp9d_dbg(VP9D_DBG_HEADER, "display_info_flag %d", val); + if (val) { + RK_S32 dw, dh; + READ_BITS(gb, 16, &dw); + dw += 1; + vp9d_dbg(VP9D_DBG_HEADER, "display_size_width %d", dw); + READ_BITS(gb, 16, &dh); + dh += 1; + vp9d_dbg(VP9D_DBG_HEADER, "display_size_height %d", dh); + } + READ_ONEBIT(gb, &s->allow_high_precision_mv); + vp9d_dbg(VP9D_DBG_HEADER, "allow_high_precision_mv %d", s->allow_high_precision_mv); + // read interp filter + READ_ONEBIT(gb, &val); + if (val) { + s->interp_filter = VP9_FILTER_SWITCHABLE; + } else { + READ_BITS(gb, 2, &s->interp_filter); + } + vp9d_dbg(VP9D_DBG_HEADER, "interp_filter %d", s->interp_filter); + for (i = 0; i < 3; i++) { + RK_U32 refw = mpp_frame_get_width(s->refs[s->refidx[i]].f); + RK_U32 refh = mpp_frame_get_height(s->refs[s->refidx[i]].f); + RK_S32 reffmt = mpp_frame_get_fmt(s->refs[s->refidx[i]].f) & MPP_FRAME_FMT_MASK; + + vp9d_dbg(VP9D_DBG_REF, "ref get width frame slot %p", s->refs[s->refidx[i]].f); + if (reffmt != fmt) { + /* TODO */ + + } else if (refw == w && refh == h) { + s->mvscale[i][0] = (refw << 14) / w; + s->mvscale[i][1] = (refh << 14) / h; + } else { + if (w * 2 < refw || h * 2 < refh || + w > 16 * refw || h > 16 * refh) { + mpp_err("Invalid ref frame dimensions %dx%d for frame size %dx%d\n", + refw, refh, w, h); + return MPP_ERR_VALUE; + } + s->mvscale[i][0] = (refw << 14) / w; + s->mvscale[i][1] = (refh << 14) / h; + s->mvstep[i][0] = 16 * s->mvscale[i][0] >> 14; + s->mvstep[i][1] = 16 * s->mvscale[i][1] >> 14; + } + } + } + } + + if (s->error_res_mode) { + s->refresh_frame_context = 0; + s->frame_parallel_mode = 1; + } else { + READ_ONEBIT(gb, &s->refresh_frame_context); + READ_ONEBIT(gb, &s->frame_parallel_mode); + } + vp9d_dbg(VP9D_DBG_HEADER, "refresh_frame_context_flag %d", s->refresh_frame_context); + vp9d_dbg(VP9D_DBG_HEADER, "frame_parallel_decoding_mode %d", s->frame_parallel_mode); + + READ_BITS(gb, 2, &s->frame_context_idx); + vp9d_dbg(VP9D_DBG_HEADER, "frame_context_idx %d", s->frame_context_idx); + + // set default loopfilter deltas + if (s->keyframe || s->intraonly || s->error_res_mode) { + s->lf_delta.enabled = 1; + s->lf_delta.update = 1; + s->lf_delta.ref[0] = 1; + s->lf_delta.ref[1] = 0; + s->lf_delta.ref[2] = -1; + s->lf_delta.ref[3] = -1; + s->lf_delta.mode[0] = 0; + s->lf_delta.mode[1] = 0; + } + // set loopfilter deltas + READ_BITS(gb, 6, &s->filter.level); + vp9d_dbg(VP9D_DBG_HEADER, "filter_level %d", s->filter.level); + { + RK_S32 sharpness_level; + READ_BITS(gb, 3, &sharpness_level); + vp9d_dbg(VP9D_DBG_HEADER, "sharpness_level %d", sharpness_level); + // update sharpness + if (s->filter.sharpness != sharpness_level) + memset(s->filter.lim_lut, 0, sizeof(s->filter.lim_lut)); + s->filter.sharpness = sharpness_level; + } + READ_ONEBIT(gb, &s->lf_delta.enabled); + if (s->lf_delta.enabled) { + vp9d_dbg(VP9D_DBG_HEADER, "mode_ref_delta_enabled=1"); + READ_ONEBIT(gb, &s->lf_delta.update); + if (s->lf_delta.update) { + vp9d_dbg(VP9D_DBG_HEADER, "mode_ref_delta_update=1"); + for (i = 0; i < 4; i++) { + READ_ONEBIT(gb, &val); + if (val) + READ_SIGNBITS(gb, 6, &s->lf_delta.ref[i]); + vp9d_dbg(VP9D_DBG_HEADER, "ref_deltas %d", s->lf_delta.ref[i]); + } + for (i = 0; i < 2; i++) { + READ_ONEBIT(gb, &val); + if (val) + READ_SIGNBITS(gb, 6, &s->lf_delta.mode[i]); + vp9d_dbg(VP9D_DBG_HEADER, "mode_deltas %d", s->lf_delta.mode[i]); + } + } + } + + // read quantization header data + READ_BITS(gb, 8, &s->base_qindex); + vp9d_dbg(VP9D_DBG_HEADER, "base_qindex %d", s->base_qindex); + s->y_dc_delta_q = 0; + READ_ONEBIT(gb, &val); + if (val) + READ_SIGNBITS(gb, 4, &s->y_dc_delta_q); + vp9d_dbg(VP9D_DBG_HEADER, "y_dc_delta_q %d", s->y_dc_delta_q); + s->uv_dc_delta_q = 0; + READ_ONEBIT(gb, &val); + if (val) + READ_SIGNBITS(gb, 4, &s->uv_dc_delta_q); + vp9d_dbg(VP9D_DBG_HEADER, "uv_dc_delta_q %d", s->uv_dc_delta_q); + s->uv_ac_delta_q = 0; + READ_ONEBIT(gb, &val); + if (val) + READ_SIGNBITS(gb, 4, &s->uv_ac_delta_q); + vp9d_dbg(VP9D_DBG_HEADER, "uv_ac_delta_q %d", s->uv_ac_delta_q); + s->lossless = s->base_qindex == 0 && s->y_dc_delta_q == 0 && + s->uv_dc_delta_q == 0 && s->uv_ac_delta_q == 0; + + // Segmentation map update + s->segmentation.update_map = 0; + s->segmentation.ignore_refmap = 0; + READ_ONEBIT(gb, &s->segmentation.enabled); + vp9d_dbg(VP9D_DBG_HEADER, "segmentation_enabled %d", s->segmentation.enabled); + if (s->segmentation.enabled) { + READ_ONEBIT(gb, &s->segmentation.update_map); + vp9d_dbg(VP9D_DBG_HEADER, "update_map %d", s->segmentation.update_map); + if (s->segmentation.update_map) { + for (i = 0; i < 7; i++) { + s->prob.seg[i] = 255; + READ_ONEBIT(gb, &val); + if (val) + READ_BITS(gb, 8, &s->prob.seg[i]); + vp9d_dbg(VP9D_DBG_HEADER, "tree_probs %d value 0x%x", i, s->prob.seg[i]); + } + READ_ONEBIT(gb, &s->segmentation.temporal); + vp9d_dbg(VP9D_DBG_HEADER, "tempora_update %d", s->segmentation.temporal); + if (s->segmentation.temporal) { + for (i = 0; i < 3; i++) { + s->prob.segpred[i] = 255; + READ_ONEBIT(gb, &val); + if (val) + READ_BITS(gb, 8, &s->prob.segpred[i]); + vp9d_dbg(VP9D_DBG_HEADER, "pred_probs %d value 0x%x", i, s->prob.segpred[i]); + } + } else { + for (i = 0; i < 3; i++) + s->prob.segpred[i] = 0xff; + } + } + if ((!s->segmentation.update_map || s->segmentation.temporal) && + (w != mpp_frame_get_width(s->frames[VP9_CUR_FRAME].f) || + h != mpp_frame_get_height(s->frames[VP9_CUR_FRAME].f))) { + + /* TODO */ + //return -1; + } + // segmentation data update + READ_ONEBIT(gb, &val); + vp9d_dbg(VP9D_DBG_HEADER, "update_data %d", val); + if (val) { + READ_ONEBIT(gb, &s->segmentation.absolute_vals); + vp9d_dbg(VP9D_DBG_HEADER, "abs_delta %d", s->segmentation.absolute_vals); + for (i = 0; i < 8; i++) { + READ_ONEBIT(gb, &s->segmentation.feat[i].q_enabled); + if (s->segmentation.feat[i].q_enabled) + READ_SIGNBITS(gb, 8, &s->segmentation.feat[i].q_val); + vp9d_dbg(VP9D_DBG_HEADER, "q_enabled %d frame_qp_delta %d", + s->segmentation.feat[i].q_enabled, s->segmentation.feat[i].q_val); + READ_ONEBIT(gb, &s->segmentation.feat[i].lf_enabled); + if (s->segmentation.feat[i].lf_enabled) + READ_SIGNBITS(gb, 6, &s->segmentation.feat[i].lf_val); + vp9d_dbg(VP9D_DBG_HEADER, "lf_enabled %d frame_loopfilter_value %d", + s->segmentation.feat[i].lf_enabled, s->segmentation.feat[i].lf_val); + READ_ONEBIT(gb, &s->segmentation.feat[i].ref_enabled); + if (s->segmentation.feat[i].ref_enabled) + READ_BITS(gb, 2, &s->segmentation.feat[i].ref_val); + vp9d_dbg(VP9D_DBG_HEADER, "ref_enabled %d frame_reference_info %d", + s->segmentation.feat[i].ref_enabled, s->segmentation.feat[i].ref_val); + READ_ONEBIT(gb, &s->segmentation.feat[i].skip_enabled); + vp9d_dbg(VP9D_DBG_HEADER, "skip_enabled %d", s->segmentation.feat[i].skip_enabled); + } + } + } else { + s->segmentation.feat[0].q_enabled = 0; + s->segmentation.feat[0].lf_enabled = 0; + s->segmentation.feat[0].ref_enabled = 0; + s->segmentation.feat[0].skip_enabled = 0; + } + + // Build y/uv dequant values based on segmentation + for (i = 0; i < (s->segmentation.enabled ? 8 : 1); i++) { + RK_S32 y_ac_q, y_dc_q, uv_ac_q, uv_dc_q; + + if (s->segmentation.feat[i].q_enabled) { + if (s->segmentation.absolute_vals) + y_ac_q = s->segmentation.feat[i].q_val; + else + y_ac_q = s->base_qindex + s->segmentation.feat[i].q_val; + } else { + y_ac_q = s->base_qindex; + } + y_dc_q = mpp_clip_uint_pow2(y_ac_q + s->y_dc_delta_q, 8); + uv_dc_q = mpp_clip_uint_pow2(y_ac_q + s->uv_dc_delta_q, 8); + uv_ac_q = mpp_clip_uint_pow2(y_ac_q + s->uv_ac_delta_q, 8); + y_ac_q = mpp_clip_uint_pow2(y_ac_q, 8); + + s->segmentation.feat[i].qmul[0][0] = vp9_dc_qlookup[s->bpp_index][y_dc_q]; + s->segmentation.feat[i].qmul[0][1] = vp9_ac_qlookup[s->bpp_index][y_ac_q]; + s->segmentation.feat[i].qmul[1][0] = vp9_dc_qlookup[s->bpp_index][uv_dc_q]; + s->segmentation.feat[i].qmul[1][1] = vp9_ac_qlookup[s->bpp_index][uv_ac_q]; + } + + // update size + update_size(ctx, w, h, fmt); + + // get min log2 tile cols + for (s->tiling.log2_tile_cols = 0; + (s->sb_cols >> s->tiling.log2_tile_cols) > 64; + s->tiling.log2_tile_cols++) ; + // get max log2 tile cols + RK_S32 max_log2 = 0; + for (max_log2 = 0; (s->sb_cols >> max_log2) >= 4; max_log2++) ; + max_log2 = MPP_MAX(0, max_log2 - 1); + while ((RK_U32)max_log2 > s->tiling.log2_tile_cols) { + RK_S32 log2_tile_col_end_flag; + READ_ONEBIT(gb, &log2_tile_col_end_flag); + vp9d_dbg(VP9D_DBG_HEADER, "log2_tile_col_end_flag %d", log2_tile_col_end_flag); + if (log2_tile_col_end_flag) { + s->tiling.log2_tile_cols++; + } else { + break; + } + } + // read tile_rows + READ_ONEBIT(gb, &s->tiling.log2_tile_rows); + if (s->tiling.log2_tile_rows) { + READ_ONEBIT(gb, &val); + s->tiling.log2_tile_rows += val; + } + vp9d_dbg(VP9D_DBG_HEADER, "log2_tile_rows %d", s->tiling.log2_tile_rows); + + s->tiling.tile_rows = 1 << s->tiling.log2_tile_rows; + if (s->tiling.tile_cols != (1U << s->tiling.log2_tile_cols)) { + s->tiling.tile_cols = 1 << s->tiling.log2_tile_cols; + { + RK_U32 min_size = sizeof(Vp9dReader) * s->tiling.tile_cols; + if (min_size > s->c_b_size) { + s->c_b = (Vp9dReader *)mpp_malloc(RK_U8, min_size); + s->c_b_size = min_size; + } + } + if (!s->c_b) { + mpp_err("Ran out of memory during range coder init\n"); + return MPP_ERR_NOMEM; + } + } + // set frame context + RK_S32 cidx = s->frame_context_idx; + if (s->keyframe || s->error_res_mode || (s->intraonly && s->resetctx == 3)) { + for (i = 0; i < 4; i++) { + s->prob_ctx[i].p = vp9_default_probs; + memcpy(s->prob_ctx[i].coef, vp9_default_coef_probs, sizeof(vp9_default_coef_probs)); + } + } else if (s->intraonly && s->resetctx == 2) { + s->prob_ctx[cidx].p = vp9_default_probs; + memcpy(s->prob_ctx[cidx].coef, vp9_default_coef_probs, sizeof(vp9_default_coef_probs)); + } + if (s->keyframe || s->error_res_mode || s->intraonly) // reset context + s->frame_context_idx = 0; + + // next 16 bits is size of the rest of the header (arith-coded) + READ_BITS(gb, 16, &s->first_partition_size); + vp9d_dbg(VP9D_DBG_HEADER, "first_partition_size %d", s->first_partition_size); + + const RK_U8 *aligned_data = mpp_align_get_bits(gb); + vp9d_dbg(VP9D_DBG_HEADER, "offset %d", aligned_data - data); + s->uncompress_head_size_in_byte = aligned_data - data; + vp9d_dbg(VP9D_DBG_HEADER, "uncompress_head_size_in_byte %d", s->uncompress_head_size_in_byte); + if (s->first_partition_size > size - s->uncompress_head_size_in_byte) { + mpp_err("invalid: compressed_header_size %d, size %d, uncompress_head_size_in_byte %d \n", + s->first_partition_size, size, s->uncompress_head_size_in_byte); + return MPP_ERR_STREAM; + } + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET read_compressed_header(VP9Context *s, const RK_U8 *aligned_data, + RK_S32 first_partition_size) +{ + RK_S32 c, i, j, k, l, m, n; + + vp9d_reader_init(&s->c, aligned_data, first_partition_size); + + if (vp9d_read(&s->c, 128)) { // marker bit + mpp_err("Marker bit was set\n"); + return MPP_ERR_STREAM; + } + + if (s->keyframe || s->intraonly) { + memset(s->counts.coef, 0, sizeof(s->counts.coef)); + memset(s->counts.eob, 0, sizeof(s->counts.eob)); + } else { + memset(&s->counts, 0, sizeof(s->counts)); + } + + // set prob context + c = s->frame_context_idx; + s->prob.p = s->prob_ctx[c].p; + memset(&s->prob_flag_delta, 0, sizeof(s->prob_flag_delta)); + // txfm updates + if (s->lossless) { + s->txfmmode = VP9_TX_4X4; + } else { + s->txfmmode = vp9d_read_bits(&s->c, 2); + if (s->txfmmode == VP9_TX_32X32) + s->txfmmode += vp9d_read_bit(&s->c); + + if (s->txfmmode == VP9_TX_SWITCHABLE) { + for (i = 0; i < 2; i++) { + + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.tx8p[i] = 1; + s->prob.p.tx8p[i] = vp9d_diff_update_prob(&s->c, s->prob.p.tx8p[i], + &s->prob_flag_delta.p_delta.tx8p[i]); + } + + } + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) { + + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.tx16p[i][j] = 1; + s->prob.p.tx16p[i][j] = + vp9d_diff_update_prob(&s->c, s->prob.p.tx16p[i][j], + &s->prob_flag_delta.p_delta.tx16p[i][j]); + } + } + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) { + + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.tx32p[i][j] = 1; + s->prob.p.tx32p[i][j] = + vp9d_diff_update_prob(&s->c, s->prob.p.tx32p[i][j], + &s->prob_flag_delta.p_delta.tx32p[i][j]); + } + } + } + } + + // coef updates + for (i = 0; i < 4; i++) { + RK_U8 (*ref)[2][6][6][3] = s->prob_ctx[c].coef[i]; + + if (vp9d_read_bit(&s->c)) { + for (j = 0; j < 2; j++) + for (k = 0; k < 2; k++) + for (l = 0; l < 6; l++) + for (m = 0; m < 6; m++) { + RK_U8 *p = s->prob.coef[i][j][k][l][m]; + RK_U8 *p_flag = s->prob_flag_delta.coef_flag[i][j][k][l][m]; + RK_U8 *p_delta = s->prob_flag_delta.coef_delta[i][j][k][l][m]; + RK_U8 *r = ref[j][k][l][m]; + if (l == 0 && m >= 3) // dc only has 3 pt + break; + for (n = 0; n < 3; n++) { + if (vp9d_read(&s->c, 252)) { + p_flag[n] = 1; + p[n] = vp9d_diff_update_prob(&s->c, r[n], &p_delta[n]); + } else { + p_flag[n] = 0; + p[n] = r[n]; + } + } + } + } else { + for (j = 0; j < 2; j++) + for (k = 0; k < 2; k++) + for (l = 0; l < 6; l++) + for (m = 0; m < 6; m++) { + RK_U8 *p = s->prob.coef[i][j][k][l][m]; + RK_U8 *r = ref[j][k][l][m]; + if (m >= 3 && l == 0) // dc only has 3 pt + break; + memcpy(p, r, 3); + } + } + if (s->txfmmode == (RK_U32)i) + break; + } + + // mode updates + for (i = 0; i < 3; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.skip[i] = 1; + s->prob.p.skip[i] = vp9d_diff_update_prob(&s->c, s->prob.p.skip[i], + &s->prob_flag_delta.p_delta.skip[i]); + } + } + + if (!s->keyframe && !s->intraonly) { + for (i = 0; i < 7; i++) + for (j = 0; j < 3; j++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_mode[i][j] = 1; + s->prob.p.mv_mode[i][j] = + vp9d_diff_update_prob(&s->c, s->prob.p.mv_mode[i][j], + &s->prob_flag_delta.p_delta.mv_mode[i][j]); + } + } + + if (s->interp_filter == VP9_FILTER_SWITCHABLE) + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.filter[i][j] = 1; + s->prob.p.filter[i][j] = + vp9d_diff_update_prob(&s->c, s->prob.p.filter[i][j], + &s->prob_flag_delta.p_delta.filter[i][j]); + } + } + + for (i = 0; i < 4; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.intra[i] = 1; + s->prob.p.intra[i] = vp9d_diff_update_prob(&s->c, s->prob.p.intra[i], + &s->prob_flag_delta.p_delta.intra[i]); + } + } + s->allowcompinter = (s->signbias[0] != s->signbias[1] || + s->signbias[0] != s->signbias[2]); + if (s->allowcompinter) { + s->comppredmode = vp9d_read_bit(&s->c); + if (s->comppredmode) + s->comppredmode += vp9d_read_bit(&s->c); + if (s->comppredmode == VP9_PRED_SWITCHABLE) + for (i = 0; i < 5; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.comp[i] = 1; + s->prob.p.comp[i] = + vp9d_diff_update_prob(&s->c, s->prob.p.comp[i], + &s->prob_flag_delta.p_delta.comp[i]); + } + } + } else { + s->comppredmode = VP9_PRED_SINGLEREF; + } + + if (s->comppredmode != VP9_PRED_COMPREF) { + for (i = 0; i < 5; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.single_ref[i][0] = 1; + s->prob.p.single_ref[i][0] = + vp9d_diff_update_prob(&s->c, s->prob.p.single_ref[i][0], + &s->prob_flag_delta.p_delta.single_ref[i][0]); + } + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.single_ref[i][1] = 1; + s->prob.p.single_ref[i][1] = + vp9d_diff_update_prob(&s->c, s->prob.p.single_ref[i][1], + &s->prob_flag_delta.p_delta.single_ref[i][1]); + } + } + } + + if (s->comppredmode != VP9_PRED_SINGLEREF) { + for (i = 0; i < 5; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.comp_ref[i] = 1; + s->prob.p.comp_ref[i] = + vp9d_diff_update_prob(&s->c, s->prob.p.comp_ref[i], + &s->prob_flag_delta.p_delta.comp_ref[i]); + } + } + } + + for (i = 0; i < 4; i++) + for (j = 0; j < 9; j++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.y_mode[i][j] = 1; + s->prob.p.y_mode[i][j] = + vp9d_diff_update_prob(&s->c, s->prob.p.y_mode[i][j], + &s->prob_flag_delta.p_delta.y_mode[i][j]); + } + } + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + for (k = 0; k < 3; k++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.partition[3 - i][j][k] = 1; + s->prob.p.partition[3 - i][j][k] = + vp9d_diff_update_prob(&s->c, s->prob.p.partition[3 - i][j][k], + &s->prob_flag_delta.p_delta.partition[3 - i][j][k]); + } + } + + for (i = 0; i < 3; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_joint[i] = 1; + s->prob_flag_delta.p_delta.mv_joint[i] = + s->prob.p.mv_joint[i] = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + } + + for (i = 0; i < 2; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].sign = 1; + s->prob_flag_delta.p_delta.mv_comp[i].sign = + s->prob.p.mv_comp[i].sign = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + + for (j = 0; j < 10; j++) + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].classes[j] = 1; + s->prob_flag_delta.p_delta.mv_comp[i].classes[j] = + s->prob.p.mv_comp[i].classes[j] = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].class0 = 1; + s->prob_flag_delta.p_delta.mv_comp[i].class0 = + s->prob.p.mv_comp[i].class0 = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + + for (j = 0; j < 10; j++) + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].bits[j] = 1; + s->prob_flag_delta.p_delta.mv_comp[i].bits[j] = + s->prob.p.mv_comp[i].bits[j] = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + } + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) + for (k = 0; k < 3; k++) + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].class0_fp[j][k] = 1; + s->prob_flag_delta.p_delta.mv_comp[i].class0_fp[j][k] = + s->prob.p.mv_comp[i].class0_fp[j][k] = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + + for (j = 0; j < 3; j++) + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].fp[j] = 1; + s->prob_flag_delta.p_delta.mv_comp[i].fp[j] = + s->prob.p.mv_comp[i].fp[j] = + (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + } + + if (s->allow_high_precision_mv) { + for (i = 0; i < 2; i++) { + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].class0_hp = 1; + s->prob_flag_delta.p_delta.mv_comp[i].class0_hp = + s->prob.p.mv_comp[i].class0_hp = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + + if (vp9d_read(&s->c, 252)) { + s->prob_flag_delta.p_flag.mv_comp[i].hp = 1; + s->prob_flag_delta.p_delta.mv_comp[i].hp = + s->prob.p.mv_comp[i].hp = (vp9d_read_bits(&s->c, 7) << 1) | 1; + } + } + } + } + return MPP_OK; +} + +static MPP_RET decode_parser_header(Vp9DecCtx *ctx, + const RK_U8 *data, RK_S32 size) +{ + RK_S32 ref = 0; + MPP_RET ret = MPP_NOK; + VP9Context *s = ctx->priv_data; + +#ifdef dump + char filename[20] = "data/acoef"; + if (vp9_p_fp2 != NULL) { + fclose(vp9_p_fp2); + + } + sprintf(&filename[10], "%d.bin", dec_num); + vp9_p_fp2 = fopen(filename, "wb"); +#endif + + ret = read_uncompressed_header(ctx, data, size, &ref); + if (ret < 0) { + mpp_err("read uncompressed header failed\n"); + return ret; + } + + if (s->show_existing_frame) { + MppFrame frame = NULL; + + if (!s->refs[ref].ref) { + //mpp_err("Requested reference %d not available\n", ref); + return MPP_ERR_NULL_PTR; + } + mpp_buf_slot_get_prop(s->slots, s->refs[ref].slot_index, SLOT_FRAME_PTR, &frame); + mpp_frame_set_pts(frame, s->pts); + mpp_frame_set_dts(frame, s->dts); + mpp_buf_slot_set_flag(s->slots, s->refs[ref].slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(s->slots, s->refs[ref].slot_index, QUEUE_DISPLAY); + s->refs[ref].ref->is_output = 1; + vp9d_dbg(VP9D_DBG_HEADER, "out repeat num %d", s->outframe_num++); + + return MPP_OK; + } else { + const RK_U8 *aligned_data = mpp_align_get_bits(&s->gb); + ret = read_compressed_header(s, aligned_data, s->first_partition_size); + if (ret < 0) { + mpp_err("read compressed header failed\n"); + return ret; + } + } + + return MPP_OK; +} + +#define TRANS_TO_HW_STYLE(uv_mode) \ +do{ \ + RK_U8 *uv_ptr = NULL; \ + RK_U8 uv_mode_prob[10][9]; \ + for (i = 0; i < 10; i++) { \ + if (i == 0) { \ + uv_ptr = uv_mode[2]; \ + } else if ( i == 1) { \ + uv_ptr = uv_mode[0]; \ + } else if ( i == 2) { \ + uv_ptr = uv_mode[1]; \ + } else if ( i == 7) { \ + uv_ptr = uv_mode[8]; \ + } else if (i == 8) { \ + uv_ptr = uv_mode[7]; \ + } else { \ + uv_ptr = uv_mode[i]; \ + } \ + memcpy(&uv_mode_prob[i], uv_ptr, 9); \ + } \ + memcpy(uv_mode, uv_mode_prob, sizeof(uv_mode_prob)); \ +}while(0) + +static RK_S32 vp9d_fill_segmentation(VP9Context *s, DXVA_segmentation_VP9 *seg) +{ + RK_S32 i; + + seg->enabled = s->segmentation.enabled; + seg->update_map = s->segmentation.update_map; + seg->temporal_update = s->segmentation.temporal; + seg->abs_delta = s->segmentation.absolute_vals; + seg->ReservedSegmentFlags4Bits = 0; + + for (i = 0; i < 7; i++) { + seg->tree_probs[i] = s->prob.seg[i]; + } + + seg->pred_probs[0] = s->prob.segpred[0]; + seg->pred_probs[1] = s->prob.segpred[1]; + seg->pred_probs[2] = s->prob.segpred[2]; + + for (i = 0; i < 8; i++) { + seg->feature_data[i][0] = s->segmentation.feat[i].q_val; + seg->feature_data[i][1] = s->segmentation.feat[i].lf_val; + seg->feature_data[i][2] = s->segmentation.feat[i].ref_val; + seg->feature_data[i][3] = s->segmentation.feat[i].skip_enabled; + seg->feature_mask[i] = s->segmentation.feat[i].q_enabled + | (s->segmentation.feat[i].lf_enabled << 1) + | (s->segmentation.feat[i].ref_enabled << 2) + | (s->segmentation.feat[i].skip_enabled << 3); +#if 0 + mpp_log("seg->feature_data[%d][0] = 0x%x", i, seg->feature_data[i][0]); + + mpp_log("seg->feature_data[%d][1] = 0x%x", i, seg->feature_data[i][0]); + + mpp_log("seg->feature_data[%d][2] = 0x%x", i, seg->feature_data[i][0]); + + mpp_log("seg->feature_data[%d][3] = 0x%x", i, seg->feature_data[i][0]); + mpp_log("seg->feature_mask[%d] = 0x%x", i, seg->feature_mask[i]); +#endif + } + + return 0; +} + +static RK_S32 vp9d_fill_picparams(Vp9DecCtx *ctx, DXVA_PicParams_VP9 *pic) +{ + VP9Context *s = ctx->priv_data; + RK_U8 partition_probs[16][3]; + RK_U8 partition_probs_flag[16][3]; + RK_U8 partition_probs_delata[16][3]; + DXVA_prob_vp9* prob_flag = &pic->prob_flag_delta.p_flag; + DXVA_prob_vp9* prob_delta = &pic->prob_flag_delta.p_delta; + RK_S32 i; + + pic->profile = ctx->profile; + pic->show_existing_frame = s->show_existing_frame; + pic->frame_type = !s->keyframe; + pic->show_frame = !s->show_frame_flag; + pic->error_resilient_mode = s->error_res_mode; + pic->subsampling_x = s->subsampling_x; + pic->subsampling_y = s->subsampling_y; + pic->extra_plane = s->extra_plane; + pic->refresh_frame_context = s->refresh_frame_context; + pic->intra_only = s->intraonly; + pic->frame_context_idx = s->frame_context_idx; + pic->reset_frame_context = s->resetctx; + pic->allow_high_precision_mv = s->allow_high_precision_mv; + pic->parallelmode = s->frame_parallel_mode; + pic->width = ctx->width; + pic->height = ctx->height; + pic->BitDepthMinus8Luma = s->bpp - 8; + pic->BitDepthMinus8Chroma = s->bpp - 8; + pic->interp_filter = s->interp_filter; + pic->CurrPic.Index7Bits = s->frames[VP9_CUR_FRAME].slot_index; + + for (i = 0; i < 8; i++) { + pic->ref_frame_map[i].Index7Bits = s->refs[i].slot_index; + pic->ref_frame_coded_width[i] = mpp_frame_get_width(s->refs[i].f); + pic->ref_frame_coded_height[i] = mpp_frame_get_height(s->refs[i].f); + } + pic->frame_refs[0].Index7Bits = s->refidx[0]; + pic->frame_refs[1].Index7Bits = s->refidx[1]; + pic->frame_refs[2].Index7Bits = s->refidx[2]; + pic->ref_frame_sign_bias[1] = s->signbias[0]; + pic->ref_frame_sign_bias[2] = s->signbias[1]; + pic->ref_frame_sign_bias[3] = s->signbias[2]; + pic->filter_level = s->filter.level; + pic->sharpness_level = s->filter.sharpness; + pic->mode_ref_delta_enabled = s->lf_delta.enabled; + pic->mode_ref_delta_update = s->lf_delta.update; + pic->use_prev_in_find_mv_refs = s->use_last_frame_mvs; + pic->ref_deltas[0] = s->lf_delta.ref[0]; + pic->ref_deltas[1] = s->lf_delta.ref[1]; + pic->ref_deltas[2] = s->lf_delta.ref[2]; + pic->ref_deltas[3] = s->lf_delta.ref[3]; + pic->mode_deltas[0] = s->lf_delta.mode[0]; + pic->mode_deltas[1] = s->lf_delta.mode[1]; + pic->base_qindex = s->base_qindex; + pic->y_dc_delta_q = s->y_dc_delta_q; + pic->uv_dc_delta_q = s->uv_dc_delta_q; + pic->uv_ac_delta_q = s->uv_ac_delta_q; + pic->txmode = s->txfmmode; + pic->refmode = s->comppredmode; + vp9d_fill_segmentation(s, &pic->stVP9Segments); + pic->log2_tile_cols = s->tiling.log2_tile_cols; + pic->log2_tile_rows = s->tiling.log2_tile_rows; + pic->first_partition_size = s->first_partition_size; + pic->uncompressed_header_size_byte_aligned = s->uncompress_head_size_in_byte; + memcpy(pic->mvscale, s->mvscale, sizeof(s->mvscale)); + memcpy(&pic->prob, &s->prob, sizeof(pic->prob)); + memcpy(&pic->prob_flag_delta, &s->prob_flag_delta, sizeof(pic->prob_flag_delta)); + { + /*change partition to hardware need style*/ + /* + hardware syntax + *+++++8x8+++++* *++++64x64++++* + *+++++16x16+++* *++++32x32++++* + *+++++32x32+++* *++++16x16++++* + *+++++64x64+++* *++++8x8++++++* + */ + RK_U32 m = 0; + RK_U32 len = sizeof(pic->prob.partition[0]); + RK_U32 step = len / sizeof(partition_probs[0]); + + for (i = MPP_ARRAY_ELEMS(pic->prob.partition) - 1; i >= 0; i--) { + memcpy(&partition_probs[m][0], &pic->prob.partition[i][0][0], len); + memcpy(&partition_probs_flag[m][0], &prob_flag->partition[i][0][0], len); + memcpy(&partition_probs_delata[m][0], &prob_delta->partition[i][0][0], len); + m += step; + } + memcpy(pic->prob.partition, partition_probs, sizeof(partition_probs)); + memcpy(prob_flag->partition, partition_probs_flag, sizeof(partition_probs_flag)); + memcpy(prob_delta->partition, partition_probs_delata, sizeof(partition_probs_delata)); + + /*change uv_mode to hardware need style*/ + /* + hardware syntax + *+++++ dc ++++* *++++ v ++++* + *+++++ v ++++* *++++ h ++++* + *+++++ h ++++* *++++ dc ++++* + *+++++ d45 ++++* *++++ d45 ++++* + *+++++ d135++++* *++++ d135++++* + *+++++ d117++++* *++++ d117++++* + *+++++ d153++++* *++++ d153++++* + *+++++ d207++++* *++++ d63 ++++* + *+++++ d63 ++++* *++++ d207++++* + *+++++ tm ++++* *++++ tm ++++* + */ + + TRANS_TO_HW_STYLE(pic->prob.uv_mode); + TRANS_TO_HW_STYLE(prob_flag->uv_mode); + TRANS_TO_HW_STYLE(prob_delta->uv_mode); + } + return 0; +} + +RK_S32 vp9_parser_frame(Vp9DecCtx *ctx, HalDecTask *task) +{ + const RK_U8 *data = NULL; + RK_S32 size = 0; + VP9Context *s = (VP9Context *)ctx->priv_data; + RK_S32 ret; + RK_S32 i; + + vp9d_dbg(VP9D_DBG_FUNCTION, "%s", __FUNCTION__); + task->valid = -1; +#ifdef dump + dec_num++; +#endif + data = (const RK_U8 *)mpp_packet_get_pos(ctx->pkt); + size = (RK_S32)mpp_packet_get_length(ctx->pkt); + + s->pts = mpp_packet_get_pts(ctx->pkt); + s->dts = mpp_packet_get_dts(ctx->pkt); + + vp9d_dbg(VP9D_DBG_HEADER, "data size %d", size); + if (size <= 0) { + return MPP_OK; + } + ret = decode_parser_header(ctx, data, size); + if (ret < 0) + return ret; + + if (s->show_existing_frame) { + return size; + } else { + RK_S32 head_size = s->first_partition_size + (RK_S32)s->uncompress_head_size_in_byte; + vp9d_dbg(VP9D_DBG_HEADER, "%s end, head_size %d\n", __FUNCTION__, head_size); + // move to frame data + data += head_size; + size -= head_size; + } + + if (s->frames[VP9_REF_FRAME_MVPAIR].ref) + vp9_unref_frame(s, &s->frames[VP9_REF_FRAME_MVPAIR]); + + if (!s->intraonly && !s->keyframe && !s->error_res_mode && s->frames[VP9_CUR_FRAME].ref) { + ret = vp9_ref_frame(ctx, &s->frames[VP9_REF_FRAME_MVPAIR], &s->frames[VP9_CUR_FRAME]); + if (ret < 0) + return ret; + } + + if (s->frames[VP9_CUR_FRAME].ref) + vp9_unref_frame(s, &s->frames[VP9_CUR_FRAME]); + + ret = vp9_alloc_frame(ctx, &s->frames[VP9_CUR_FRAME]); + if (ret < 0) + return ret; + + // if context need refresh, copy prob_ctx + if (s->refresh_frame_context && s->frame_parallel_mode) { + RK_S32 j, k, l, m; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 2; j++) + for (k = 0; k < 2; k++) + for (l = 0; l < 6; l++) + for (m = 0; m < 6; m++) + memcpy(s->prob_ctx[s->frame_context_idx].coef[i][j][k][l][m], + s->prob.coef[i][j][k][l][m], 3); + if ((RK_S32)s->txfmmode == i) + break; + } + s->prob_ctx[s->frame_context_idx].p = s->prob.p; + } + + vp9d_fill_picparams(ctx, &ctx->pic_params); + // set task + task->syntax.data = (void*)&ctx->pic_params; + task->syntax.number = 1; + task->valid = 1; + task->output = s->frames[VP9_CUR_FRAME].slot_index; + task->input_packet = ctx->pkt; + + for (i = 0; i < 3; i++) { + if (s->refs[s->refidx[i]].slot_index < 0x7f) { + MppFrame mframe = NULL; + + mpp_buf_slot_set_flag(s->slots, s->refs[s->refidx[i]].slot_index, SLOT_HAL_INPUT); + task->refer[i] = s->refs[s->refidx[i]].slot_index; + mpp_buf_slot_get_prop(s->slots, task->refer[i], SLOT_FRAME_PTR, &mframe); + if (mframe && !s->keyframe && !s->intraonly) + task->flags.ref_err |= mpp_frame_get_errinfo(mframe); + } else { + task->refer[i] = -1; + } + } + + vp9d_dbg(VP9D_DBG_REF, "ref_errinfo=%d\n", task->flags.ref_err); + if (s->eos) { + task->flags.eos = 1; + } + + if (!s->show_frame_flag) { + mpp_buf_slot_set_flag(s->slots, s->frames[VP9_CUR_FRAME].slot_index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(s->slots, s->frames[VP9_CUR_FRAME].slot_index, QUEUE_DISPLAY); + } + vp9d_dbg(VP9D_DBG_REF, "s->refresh_frame_flags = %d s->frames[VP9_CUR_FRAME] = %d", + s->refresh_frame_flags, s->frames[VP9_CUR_FRAME].slot_index); + for (i = 0; i < 3; i++) { + if (s->refs[s->refidx[i]].ref != NULL) { + vp9d_dbg(VP9D_DBG_REF, "ref buf select %d", s->refs[s->refidx[i]].slot_index); + } + } + // ref frame setup + for (i = 0; i < 8; i++) { + vp9d_dbg(VP9D_DBG_REF, "s->refresh_frame_flags = 0x%x", s->refresh_frame_flags); + ret = 0; + if (s->refresh_frame_flags & (1 << i)) { + if (s->refs[i].ref) + vp9_unref_frame(s, &s->refs[i]); + vp9d_dbg(VP9D_DBG_REF, "update ref index in %d", i); + ret = vp9_ref_frame(ctx, &s->refs[i], &s->frames[VP9_CUR_FRAME]); + } + + if (s->refs[i].ref) + vp9d_dbg(VP9D_DBG_REF, "s->refs[%d] = %d", i, s->refs[i].slot_index); + if (ret < 0) + return 0/*ret*/; + } + return 0; +} + +MPP_RET vp9d_paser_reset(Vp9DecCtx *ctx) +{ + VP9Context *s = ctx->priv_data; + VP9SplitCtx *ps = (VP9SplitCtx *)ctx->priv_data2; + VP9ParseCtx *pc = (VP9ParseCtx *)ps->priv_data; + RK_S32 i; + + s->got_keyframes = 0; + s->cur_poc = 0; + for (i = 0; i < 3; i++) { + if (s->frames[i].ref) { + vp9_unref_frame(s, &s->frames[i]); + } + } + for (i = 0; i < 8; i++) { + if (s->refs[i].ref) { + vp9_unref_frame(s, &s->refs[i]); + } + } + memset(pc, 0, sizeof(VP9ParseCtx)); + + s->eos = 0; + if (ps) { + ps->eos = 0; + } + return MPP_OK; +} +static void inv_count_data(VP9Context *s) +{ + RK_U32 partition_probs[4][4][4]; + RK_U32 count_uv[10][10]; + RK_U32 count_y_mode[4][10]; + RK_U32 *dst_uv = NULL; + RK_S32 i, j; + + /* + syntax hardware + *+++++64x64+++++* *++++8x8++++* + *+++++32x32+++* *++++16x16++++* + *+++++16x16+++* *++++32x32++++* + *+++++8x8+++* *++++64x64++++++* + */ + + memcpy(&partition_probs, s->counts.partition, sizeof(s->counts.partition)); + j = 0; + for (i = 3; i >= 0; i--) { + memcpy(&s->counts.partition[j], &partition_probs[i], 64); + j++; + } + if (!(s->keyframe || s->intraonly)) { + memcpy(count_y_mode, s->counts.y_mode, sizeof(s->counts.y_mode)); + for (i = 0; i < 4; i++) { + RK_U32 value = 0; + for (j = 0; j < 10; j++) { + value = count_y_mode[i][j]; + if (j == 0) + s->counts.y_mode[i][2] = value; + else if (j == 1) + s->counts.y_mode[i][0] = value; + else if (j == 2) + s->counts.y_mode[i][1] = value; + else if (j == 7) + s->counts.y_mode[i][8] = value; + else if (j == 8) + s->counts.y_mode[i][7] = value; + else + s->counts.y_mode[i][j] = value; + + } + } + + memcpy(count_uv, s->counts.uv_mode, sizeof(s->counts.uv_mode)); + + /*change uv_mode to hardware need style*/ + /* + syntax hardware + *+++++ v ++++* *++++ dc ++++* + *+++++ h ++++* *++++ v ++++* + *+++++ dc ++++* *++++ h ++++* + *+++++ d45 ++++* *++++ d45 ++++* + *+++++ d135++++* *++++ d135++++* + *+++++ d117++++* *++++ d117++++* + *+++++ d153++++* *++++ d153++++* + *+++++ d63 ++++* *++++ d207++++* + *+++++ d207 ++++* *++++ d63 ++++* + *+++++ tm ++++* *++++ tm ++++* + */ + for (i = 0; i < 10; i++) { + RK_U32 *src_uv = (RK_U32 *)(count_uv[i]); + RK_U32 value = 0; + + if (i == 0) { + dst_uv = s->counts.uv_mode[2]; //dc + } else if ( i == 1) { + dst_uv = s->counts.uv_mode[0]; //h + } else if ( i == 2) { + dst_uv = s->counts.uv_mode[1]; //h + } else if ( i == 7) { + dst_uv = s->counts.uv_mode[8]; //d207 + } else if (i == 8) { + dst_uv = s->counts.uv_mode[7]; //d63 + } else { + dst_uv = s->counts.uv_mode[i]; + } + for (j = 0; j < 10; j++) { + value = src_uv[j]; + if (j == 0) + dst_uv[2] = value; + else if (j == 1) + dst_uv[0] = value; + else if (j == 2) + dst_uv[1] = value; + else if (j == 7) + dst_uv[8] = value; + else if (j == 8) + dst_uv[7] = value; + else + dst_uv[j] = value; + } + + } + } +} + +static void adapt_coef_probs(VP9Context *s) +{ + Vp9ProbCtx *p = &s->prob_ctx[s->frame_context_idx].p; + RK_S32 uf = (s->keyframe || s->intraonly || !s->last_keyframe) ? 112 : 128; + RK_S32 i, j, k, l, m; + + // coefficients + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) + for (k = 0; k < 2; k++) + for (l = 0; l < 6; l++) + for (m = 0; m < 6; m++) { + RK_U8 *pp = s->prob_ctx[s->frame_context_idx].coef[i][j][k][l][m]; + RK_U32 *e = s->counts.eob[i][j][k][l][m]; + RK_U32 *c = s->counts.coef[i][j][k][l][m]; + + if (l == 0 && m >= 3) // dc only has 3 pt + break; + vp9d_merge_prob(&pp[0], e[0], e[1], 24, uf); + vp9d_merge_prob(&pp[1], c[0], c[1] + c[2], 24, uf); + vp9d_merge_prob(&pp[2], c[1], c[2], 24, uf); + } +#ifdef dump + fwrite(&s->counts, 1, sizeof(s->counts), vp9_p_fp); + fflush(vp9_p_fp); +#endif + + if (s->keyframe || s->intraonly) { + memcpy(p->skip, s->prob.p.skip, sizeof(p->skip)); + memcpy(p->tx32p, s->prob.p.tx32p, sizeof(p->tx32p)); + memcpy(p->tx16p, s->prob.p.tx16p, sizeof(p->tx16p)); + memcpy(p->tx8p, s->prob.p.tx8p, sizeof(p->tx8p)); + return; + } + + // skip flag + for (i = 0; i < 3; i++) + vp9d_merge_prob(&p->skip[i], s->counts.skip[i][0], s->counts.skip[i][1], 20, 128); + + // intra/inter flag + for (i = 0; i < 4; i++) + vp9d_merge_prob(&p->intra[i], s->counts.intra[i][0], s->counts.intra[i][1], 20, 128); + + // comppred flag + if (s->comppredmode == VP9_PRED_SWITCHABLE) { + for (i = 0; i < 5; i++) + vp9d_merge_prob(&p->comp[i], s->counts.comp[i][0], s->counts.comp[i][1], 20, 128); + } + + // reference frames + if (s->comppredmode != VP9_PRED_SINGLEREF) { + for (i = 0; i < 5; i++) + vp9d_merge_prob(&p->comp_ref[i], s->counts.comp_ref[i][0], + s->counts.comp_ref[i][1], 20, 128); + } + + if (s->comppredmode != VP9_PRED_COMPREF) { + for (i = 0; i < 5; i++) { + RK_U8 *pp = p->single_ref[i]; + RK_U32 (*c)[2] = s->counts.single_ref[i]; + + vp9d_merge_prob(&pp[0], c[0][0], c[0][1], 20, 128); + vp9d_merge_prob(&pp[1], c[1][0], c[1][1], 20, 128); + } + } + + // block partitioning + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) { + RK_U8 *pp = p->partition[i][j]; + RK_U32 *c = s->counts.partition[i][j]; + + vp9d_merge_prob(&pp[0], c[0], c[1] + c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[1], c[1], c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[2], c[2], c[3], 20, 128); + } + + // tx size + if (s->txfmmode == VP9_TX_SWITCHABLE) { + for (i = 0; i < 2; i++) { + RK_U32 *c16 = s->counts.tx16p[i], *c32 = s->counts.tx32p[i]; + + vp9d_merge_prob(&p->tx8p[i], s->counts.tx8p[i][0], s->counts.tx8p[i][1], 20, 128); + vp9d_merge_prob(&p->tx16p[i][0], c16[0], c16[1] + c16[2], 20, 128); + vp9d_merge_prob(&p->tx16p[i][1], c16[1], c16[2], 20, 128); + vp9d_merge_prob(&p->tx32p[i][0], c32[0], c32[1] + c32[2] + c32[3], 20, 128); + vp9d_merge_prob(&p->tx32p[i][1], c32[1], c32[2] + c32[3], 20, 128); + vp9d_merge_prob(&p->tx32p[i][2], c32[2], c32[3], 20, 128); + } + } + + // interpolation filter + if (s->interp_filter == VP9_FILTER_SWITCHABLE) { + for (i = 0; i < 4; i++) { + RK_U8 *pp = p->filter[i]; + RK_U32 *c = s->counts.filter[i]; + + vp9d_merge_prob(&pp[0], c[0], c[1] + c[2], 20, 128); + vp9d_merge_prob(&pp[1], c[1], c[2], 20, 128); + } + } + + // inter modes + for (i = 0; i < 7; i++) { + RK_U8 *pp = p->mv_mode[i]; + RK_U32 *c = s->counts.mv_mode[i]; + + vp9d_merge_prob(&pp[0], c[2], c[1] + c[0] + c[3], 20, 128); + vp9d_merge_prob(&pp[1], c[0], c[1] + c[3], 20, 128); + vp9d_merge_prob(&pp[2], c[1], c[3], 20, 128); + } + + // mv joints + { + RK_U8 *pp = p->mv_joint; + RK_U32 *c = s->counts.mv_joint; + + vp9d_merge_prob(&pp[0], c[0], c[1] + c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[1], c[1], c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[2], c[2], c[3], 20, 128); + } + + // mv components + for (i = 0; i < 2; i++) { + RK_U8 *pp; + RK_U32 *c, (*c2)[2], sum; + + vp9d_merge_prob(&p->mv_comp[i].sign, s->counts.sign[i][0], + s->counts.sign[i][1], 20, 128); + + pp = p->mv_comp[i].classes; + c = s->counts.classes[i]; + sum = c[1] + c[2] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + c[9] + c[10]; + vp9d_merge_prob(&pp[0], c[0], sum, 20, 128); + sum -= c[1]; + vp9d_merge_prob(&pp[1], c[1], sum, 20, 128); + sum -= c[2] + c[3]; + vp9d_merge_prob(&pp[2], c[2] + c[3], sum, 20, 128); + vp9d_merge_prob(&pp[3], c[2], c[3], 20, 128); + sum -= c[4] + c[5]; + vp9d_merge_prob(&pp[4], c[4] + c[5], sum, 20, 128); + vp9d_merge_prob(&pp[5], c[4], c[5], 20, 128); + sum -= c[6]; + vp9d_merge_prob(&pp[6], c[6], sum, 20, 128); + vp9d_merge_prob(&pp[7], c[7] + c[8], c[9] + c[10], 20, 128); + vp9d_merge_prob(&pp[8], c[7], c[8], 20, 128); + vp9d_merge_prob(&pp[9], c[9], c[10], 20, 128); + + vp9d_merge_prob(&p->mv_comp[i].class0, s->counts.class0[i][0], + s->counts.class0[i][1], 20, 128); + pp = p->mv_comp[i].bits; + c2 = s->counts.bits[i]; + for (j = 0; j < 10; j++) + vp9d_merge_prob(&pp[j], c2[j][0], c2[j][1], 20, 128); + + for (j = 0; j < 2; j++) { + pp = p->mv_comp[i].class0_fp[j]; + c = s->counts.class0_fp[i][j]; + vp9d_merge_prob(&pp[0], c[0], c[1] + c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[1], c[1], c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[2], c[2], c[3], 20, 128); + } + pp = p->mv_comp[i].fp; + c = s->counts.fp[i]; + vp9d_merge_prob(&pp[0], c[0], c[1] + c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[1], c[1], c[2] + c[3], 20, 128); + vp9d_merge_prob(&pp[2], c[2], c[3], 20, 128); + + if (s->allow_high_precision_mv) { + vp9d_merge_prob(&p->mv_comp[i].class0_hp, s->counts.class0_hp[i][0], + s->counts.class0_hp[i][1], 20, 128); + vp9d_merge_prob(&p->mv_comp[i].hp, s->counts.hp[i][0], + s->counts.hp[i][1], 20, 128); + } + } + + // y intra modes + for (i = 0; i < 4; i++) { + RK_U8 *pp = p->y_mode[i]; + RK_U32 *c = s->counts.y_mode[i], sum, s2; + + sum = c[0] + c[1] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + c[9]; + vp9d_merge_prob(&pp[0], c[VP9_DC_PRED], sum, 20, 128); + sum -= c[VP9_TM_VP8_PRED]; + vp9d_merge_prob(&pp[1], c[VP9_TM_VP8_PRED], sum, 20, 128); + sum -= c[VP9_VERT_PRED]; + vp9d_merge_prob(&pp[2], c[VP9_VERT_PRED], sum, 20, 128); + s2 = c[VP9_HOR_PRED] + c[VP9_DIAG_DOWN_RIGHT_PRED] + c[VP9_VERT_RIGHT_PRED]; + sum -= s2; + vp9d_merge_prob(&pp[3], s2, sum, 20, 128); + s2 -= c[VP9_HOR_PRED]; + vp9d_merge_prob(&pp[4], c[VP9_HOR_PRED], s2, 20, 128); + vp9d_merge_prob(&pp[5], c[VP9_DIAG_DOWN_RIGHT_PRED], c[VP9_VERT_RIGHT_PRED], 20, 128); + sum -= c[VP9_DIAG_DOWN_LEFT_PRED]; + vp9d_merge_prob(&pp[6], c[VP9_DIAG_DOWN_LEFT_PRED], sum, 20, 128); + sum -= c[VP9_VERT_LEFT_PRED]; + vp9d_merge_prob(&pp[7], c[VP9_VERT_LEFT_PRED], sum, 20, 128); + vp9d_merge_prob(&pp[8], c[VP9_HOR_DOWN_PRED], c[VP9_HOR_UP_PRED], 20, 128); + } + + // uv intra modes + for (i = 0; i < 10; i++) { + RK_U8 *pp = p->uv_mode[i]; + RK_U32 *c = s->counts.uv_mode[i], sum, s2; + + sum = c[0] + c[1] + c[3] + c[4] + c[5] + c[6] + c[7] + c[8] + c[9]; + vp9d_merge_prob(&pp[0], c[VP9_DC_PRED], sum, 20, 128); + sum -= c[VP9_TM_VP8_PRED]; + vp9d_merge_prob(&pp[1], c[VP9_TM_VP8_PRED], sum, 20, 128); + sum -= c[VP9_VERT_PRED]; + vp9d_merge_prob(&pp[2], c[VP9_VERT_PRED], sum, 20, 128); + s2 = c[VP9_HOR_PRED] + c[VP9_DIAG_DOWN_RIGHT_PRED] + c[VP9_VERT_RIGHT_PRED]; + sum -= s2; + vp9d_merge_prob(&pp[3], s2, sum, 20, 128); + s2 -= c[VP9_HOR_PRED]; + vp9d_merge_prob(&pp[4], c[VP9_HOR_PRED], s2, 20, 128); + vp9d_merge_prob(&pp[5], c[VP9_DIAG_DOWN_RIGHT_PRED], c[VP9_VERT_RIGHT_PRED], 20, 128); + sum -= c[VP9_DIAG_DOWN_LEFT_PRED]; + vp9d_merge_prob(&pp[6], c[VP9_DIAG_DOWN_LEFT_PRED], sum, 20, 128); + sum -= c[VP9_VERT_LEFT_PRED]; + vp9d_merge_prob(&pp[7], c[VP9_VERT_LEFT_PRED], sum, 20, 128); + vp9d_merge_prob(&pp[8], c[VP9_HOR_DOWN_PRED], c[VP9_HOR_UP_PRED], 20, 128); + } +#if 0 //def dump + fwrite(s->counts.y_mode, 1, sizeof(s->counts.y_mode), vp9_p_fp1); + fwrite(s->counts.uv_mode, 1, sizeof(s->counts.uv_mode), vp9_p_fp1); + fflush(vp9_p_fp1); +#endif +} + +MPP_RET vp9_parser_update(Vp9DecCtx *ctx, void *count_info) +{ + VP9Context *s = ctx->priv_data; + +#ifdef dump + char filename[20] = "data/pcout"; + char filename1[20] = "data/uppor"; + if (vp9_p_fp != NULL) { + fclose(vp9_p_fp); + + } + if (vp9_p_fp1 != NULL) { + fclose(vp9_p_fp1); + + } + sprintf(&filename[10], "%d.bin", count); + sprintf(&filename1[10], "%d.bin", count); + mpp_log("filename %s", filename); + vp9_p_fp = fopen(filename, "wb"); + vp9_p_fp1 = fopen(filename1, "wb"); +#endif + //update count from hardware + if (count_info != NULL) { + + memcpy((void *)&s->counts, count_info, sizeof(s->counts)); + + if (s->refresh_frame_context && !s->frame_parallel_mode) { +#ifdef dump + count++; +#endif + inv_count_data(s); + adapt_coef_probs(s); + + } + } + + return MPP_OK; +} diff --git a/mpp/codec/dec/vp9/vp9d.h b/mpp/codec/dec/vp9/vp9d.h new file mode 100644 index 000000000..221607393 --- /dev/null +++ b/mpp/codec/dec/vp9/vp9d.h @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef VP9D_PARSER_H +#define VP9D_PARSER_H + +#include + +#include "mpp_debug.h" +#include "mpp_bitread.h" + +#include "parser_api.h" +#include "vp9d_ctx.h" +#include "vp9d_syntax.h" + +extern RK_U32 vp9d_debug; + +#define VP9D_DBG_FUNCTION (0x00000001) +#define VP9D_DBG_HEADER (0x00000002) +#define VP9D_DBG_REF (0x00000004) +#define VP9D_DBG_PORBE (0x00000008) +#define VP9D_DBG_STRMIN (0x00000010) + +#define vp9d_dbg(flag, fmt, ...) mpp_dbg(vp9d_debug, flag, fmt, ##__VA_ARGS__) + +typedef struct VP9RefInfo_t { + RK_S32 ref_count; + RK_U32 show_frame_flag; + RK_U32 segMapIndex; + RK_U32 is_output; +} VP9RefInfo; + +typedef struct VP9Frame_t { + MppFrame f; + RK_S32 slot_index; + VP9RefInfo *ref; +} VP9Frame; + +#define VP9_CUR_FRAME 0 +#define VP9_REF_FRAME_MVPAIR 1 + +#define MAX_SEGMENT 8 +typedef struct VP9Context_t { + BitReadCtx_t gb; + Vp9dReader c; + Vp9dReader *c_b; + RK_U32 c_b_size; + RK_S32 pass; + RK_S32 row, row7, col, col7; + RK_U8 *dst[3]; + RK_S32 y_stride, uv_stride; + + // bitstream header + RK_U8 show_existing_frame; + RK_U8 keyframe, last_keyframe; + RK_U8 last_bpp, bpp, bpp_index, bytesperpixel; + RK_U8 show_frame_flag; + RK_U8 use_last_frame_mvs; + RK_U8 error_res_mode; + RK_U8 subsampling_x; + RK_U8 subsampling_y; + RK_U8 extra_plane; + RK_U8 intraonly; + RK_U8 resetctx; + RK_U8 refresh_frame_flags; + RK_U8 allow_high_precision_mv; + VP9FilterMode interp_filter; + RK_U8 allowcompinter; + RK_U8 fixcompref; + RK_U8 refresh_frame_context; + RK_U8 frame_parallel_mode; + RK_U8 frame_context_idx; + RK_U8 refidx[3]; + RK_U8 signbias[3]; + RK_U8 varcompref[2]; + VP9Frame frames[3]; + VP9Frame refs[8]; + RK_U32 got_keyframes; + + struct { + RK_U8 level; + RK_S8 sharpness; + RK_U8 lim_lut[64]; + RK_U8 mblim_lut[64]; + } filter; + struct { + RK_U8 enabled; + RK_U8 update; + RK_S8 mode[2]; + RK_S8 ref[4]; + } lf_delta; + RK_U8 base_qindex; + RK_U8 y_dc_delta_q; + RK_U8 uv_dc_delta_q; + RK_U8 uv_ac_delta_q; + RK_U8 lossless; + + struct { + RK_U8 enabled; + RK_U8 temporal; + RK_U8 absolute_vals; + RK_U8 update_map; + RK_U8 ignore_refmap; + struct { + RK_U8 q_enabled; + RK_U8 lf_enabled; + RK_U8 ref_enabled; + RK_U8 skip_enabled; + RK_U8 ref_val; + RK_S16 q_val; + RK_S8 lf_val; + RK_S16 qmul[2][2]; + RK_U8 lflvl[4][2]; + } feat[MAX_SEGMENT]; + } segmentation; + struct { + RK_U32 log2_tile_cols; + RK_U32 log2_tile_rows; + RK_U32 tile_cols; + RK_U32 tile_rows; + RK_U32 tile_row_start; + RK_U32 tile_row_end; + RK_U32 tile_col_start; + RK_U32 tile_col_end; + } tiling; + RK_U32 sb_cols, sb_rows, rows, cols; + struct { + Vp9ProbCtx p; + RK_U8 coef[4][2][2][6][6][3]; + } prob_ctx[4]; + struct { + Vp9ProbCtx p; + RK_U8 coef[4][2][2][6][6][3]; + RK_U8 seg[7]; + RK_U8 segpred[3]; + } prob; + struct { + Vp9ProbCtx p_flag; + Vp9ProbCtx p_delta; + RK_U8 coef_flag[4][2][2][6][6][3]; + RK_U8 coef_delta[4][2][2][6][6][3]; + } prob_flag_delta; + struct { + RK_U32 partition[4][4][4]; + RK_U32 skip[3][2]; + RK_U32 intra[4][2]; + RK_U32 tx32p[2][4]; + RK_U32 tx16p[2][4]; //orign tx16p + RK_U32 tx8p[2][2]; + RK_U32 y_mode[4][10]; + RK_U32 uv_mode[10][10]; + RK_U32 comp[5][2]; + RK_U32 comp_ref[5][2]; + RK_U32 single_ref[5][2][2]; + RK_U32 mv_mode[7][4]; + RK_U32 filter[4][3]; + RK_U32 mv_joint[4]; + RK_U32 sign[2][2]; + RK_U32 classes[2][12]; // orign classes[12] + RK_U32 class0[2][2]; + RK_U32 bits[2][10][2]; + RK_U32 class0_fp[2][2][4]; + RK_U32 fp[2][4]; + RK_U32 class0_hp[2][2]; + RK_U32 hp[2][2]; + RK_U32 coef[4][2][2][6][6][3]; + RK_U32 eob[4][2][2][6][6][2]; + } counts; + VP9TxfmMode txfmmode; + VP9CompPredMode comppredmode; + + // block reconstruction intermediates + RK_U16 mvscale[3][2]; + RK_U8 mvstep[3][2]; + + RK_S32 uncompress_head_size_in_byte; + RK_S32 first_partition_size; + MppBufSlots slots; + MppBufSlots packet_slots; + MppDecCfgSet *cfg; + const MppDecHwCap *hw_info; + HalDecTask *task; + RK_S32 eos; + RK_S64 pts; + RK_S64 dts; + RK_S32 upprobe_num; + RK_S32 outframe_num; + RK_U32 cur_poc; +} VP9Context; + +typedef struct VP9ParseCtx_t { + RK_S32 n_frames; // 1-8 + RK_S32 size[8]; + RK_S64 pts; +} VP9ParseCtx; + +#define MPP_PARSER_PTS_NB 4 +typedef struct VP9SplitCtx_t { + RK_U8 *buffer; + RK_U32 buffer_size; + RK_S32 index; + RK_S32 last_index; + RK_U32 state; + RK_S32 frame_start_found; + RK_S32 overread; + RK_S32 overread_index; + RK_U64 state64; + RK_S64 pts; // pts of the current frame + RK_S64 dts; // dts of the current frame + RK_S64 frame_offset; + RK_S64 cur_offset; + RK_S64 next_frame_offset; + + /* private data */ + void *priv_data; + RK_S64 last_pts; + RK_S64 last_dts; + RK_S32 fetch_timestamp; + + RK_S32 cur_frame_start_index; + RK_S64 cur_frame_offset[MPP_PARSER_PTS_NB]; + RK_S64 cur_frame_pts[MPP_PARSER_PTS_NB]; + RK_S64 cur_frame_dts[MPP_PARSER_PTS_NB]; + RK_S64 offset; // byte offset from starting packet start + RK_S64 cur_frame_end[MPP_PARSER_PTS_NB]; + + RK_S32 key_frame; + RK_S32 eos; +} VP9SplitCtx; + +typedef struct Vp9DecCtx_t { + void *priv_data; // VP9ParseCtx + void *priv_data2; // VP9SplitCtx + + RK_S32 pix_fmt; + RK_S32 profile; + RK_S32 level; + MppFrameColorSpace colorspace; + MppFrameColorRange color_range; + RK_S32 width, height; + MppPacket pkt; + + DXVA_PicParams_VP9 pic_params; + RK_S32 eos; +} Vp9DecCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vp9d_parser_init(Vp9DecCtx *vp9_ctx, ParserCfg *init); +MPP_RET vp9d_parser_deinit(Vp9DecCtx *vp9_ctx); +RK_S32 vp9_parser_frame(Vp9DecCtx *ctx, HalDecTask *in_task); +MPP_RET vp9_parser_update(Vp9DecCtx *ctx, void *count_info); +MPP_RET vp9d_paser_reset(Vp9DecCtx *ctx); +RK_S32 vp9d_split_frame(VP9SplitCtx *ctx, RK_U8 **out_data, RK_S32 *out_size, + RK_U8 *data, RK_S32 size); + +MPP_RET vp9d_get_frame_stream(Vp9DecCtx *ctx, RK_U8 *buf, RK_S32 length); +MPP_RET vp9d_split_init(Vp9DecCtx *vp9_ctx); +MPP_RET vp9d_split_deinit(Vp9DecCtx *vp9_ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* VP9D_PARSER_H */ diff --git a/mpp/codec/dec/vp9/vp9d_api.c b/mpp/codec/dec/vp9/vp9d_api.c new file mode 100644 index 000000000..5dfa1a40e --- /dev/null +++ b/mpp/codec/dec/vp9/vp9d_api.c @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vp9d_api" + +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_packet_impl.h" + +#include "mpp_parser.h" +#include "vp9d_ctx.h" +#include "vp9d.h" + +/*! +*********************************************************************** +* \brief +* free all buffer +*********************************************************************** +*/ +MPP_RET vp9d_deinit(void *ctx) +{ + Vp9DecCtx *vp9_ctx = (Vp9DecCtx *)ctx; + + if (vp9_ctx) { + vp9d_parser_deinit(vp9_ctx); + vp9d_split_deinit(vp9_ctx); + if (vp9_ctx->pkt) { + RK_U8 *buf; + + buf = mpp_packet_get_data(vp9_ctx->pkt); + MPP_FREE(buf); + mpp_packet_deinit(&vp9_ctx->pkt); + } + } + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* alloc all buffer +*********************************************************************** +*/ +MPP_RET vp9d_init(void *ctx, ParserCfg *init) +{ + Vp9DecCtx *vp9_ctx = (Vp9DecCtx *)ctx; + RK_U8 *buf = NULL; + RK_S32 size = SZ_512K; + MPP_RET ret = MPP_OK; + + if (!vp9_ctx || !init) { + mpp_err("vp9d init fail"); + return MPP_ERR_NULL_PTR; + } + + if ((ret = vp9d_parser_init(vp9_ctx, init)) != MPP_OK) + goto _err_exit; + + if ((ret = vp9d_split_init(vp9_ctx)) != MPP_OK) + goto _err_exit; + + buf = mpp_malloc(RK_U8, size); + if (!buf) { + mpp_err("vp9 init malloc stream buffer fail"); + ret = MPP_ERR_NOMEM; + goto _err_exit; + } + + if ((ret = mpp_packet_init(&vp9_ctx->pkt, (void *)buf, size)) != MPP_OK) + goto _err_exit; + + return ret; + +_err_exit: + vp9d_deinit(vp9_ctx); + return ret; +} + +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +MPP_RET vp9d_reset(void *ctx) +{ + Vp9DecCtx *vp9_ctx = (Vp9DecCtx *)ctx; + + return vp9d_paser_reset(vp9_ctx); +} + +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +MPP_RET vp9d_flush(void *ctx) +{ + (void)ctx; + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* prepare +*********************************************************************** +*/ +MPP_RET vp9d_prepare(void *ctx, MppPacket pkt, HalDecTask *task) +{ + Vp9DecCtx *vp9_ctx = (Vp9DecCtx *)ctx; + VP9SplitCtx *ps = (VP9SplitCtx *)vp9_ctx->priv_data2; + RK_S64 pts = mpp_packet_get_pts(pkt); + RK_S64 dts = mpp_packet_get_dts(pkt); + RK_U8 *buf = NULL; + RK_S32 length = (RK_S32)mpp_packet_get_length(pkt); + RK_U8 *out_data = NULL; + RK_S32 out_size = -1; + RK_S32 consumed = 0; + RK_U8 *pos = NULL; + + task->valid = -1; + + vp9_ctx->eos = mpp_packet_get_eos(pkt); + buf = pos = mpp_packet_get_pos(pkt); + consumed = vp9d_split_frame(ps, &out_data, &out_size, buf, length); + pos += (consumed >= 0) ? consumed : length; + + mpp_packet_set_pos(pkt, pos); + vp9d_dbg(VP9D_DBG_STRMIN, "pkt_len=%d, pts=%lld\n", length, pts); + if (out_size > 0) { + vp9d_get_frame_stream(vp9_ctx, out_data, out_size); + task->input_packet = vp9_ctx->pkt; + task->valid = 1; + mpp_packet_set_pts(vp9_ctx->pkt, pts); + mpp_packet_set_dts(vp9_ctx->pkt, dts); + task->flags.eos = vp9_ctx->eos; + } else { + task->valid = 0; + task->flags.eos = vp9_ctx->eos; + } + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* parser +*********************************************************************** +*/ +MPP_RET vp9d_parse(void *ctx, HalDecTask *in_task) +{ + Vp9DecCtx *vp9_ctx = (Vp9DecCtx *)ctx; + + vp9_parser_frame(vp9_ctx, in_task); + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* callback +*********************************************************************** +*/ +MPP_RET vp9d_callback(void *decoder, void *info) +{ + Vp9DecCtx *vp9_ctx = (Vp9DecCtx *)decoder; + + vp9_parser_update(vp9_ctx, info); + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* api struct interface +*********************************************************************** +*/ +const ParserApi mpp_vp9d = { + .name = "vp9d_parse", + .coding = MPP_VIDEO_CodingVP9, + .ctx_size = sizeof(Vp9DecCtx), + .flag = 0, + .init = vp9d_init, + .deinit = vp9d_deinit, + .prepare = vp9d_prepare, + .parse = vp9d_parse, + .reset = vp9d_reset, + .flush = vp9d_flush, + .control = NULL, + .callback = vp9d_callback, +}; + +MPP_PARSER_API_REGISTER(mpp_vp9d); diff --git a/mpp/codec/dec/vp9/vp9d_codec.c b/mpp/codec/dec/vp9/vp9d_codec.c new file mode 100644 index 000000000..379fdd229 --- /dev/null +++ b/mpp/codec/dec/vp9/vp9d_codec.c @@ -0,0 +1,1245 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#include "mpp_common.h" +#include "vp9d_ctx.h" + +const RK_S16 vp9_dc_qlookup[3][256] = { + { + 4, 8, 8, 9, 10, 11, 12, 12, + 13, 14, 15, 16, 17, 18, 19, 19, + 20, 21, 22, 23, 24, 25, 26, 26, + 27, 28, 29, 30, 31, 32, 32, 33, + 34, 35, 36, 37, 38, 38, 39, 40, + 41, 42, 43, 43, 44, 45, 46, 47, + 48, 48, 49, 50, 51, 52, 53, 53, + 54, 55, 56, 57, 57, 58, 59, 60, + 61, 62, 62, 63, 64, 65, 66, 66, + 67, 68, 69, 70, 70, 71, 72, 73, + 74, 74, 75, 76, 77, 78, 78, 79, + 80, 81, 81, 82, 83, 84, 85, 85, + 87, 88, 90, 92, 93, 95, 96, 98, + 99, 101, 102, 104, 105, 107, 108, 110, + 111, 113, 114, 116, 117, 118, 120, 121, + 123, 125, 127, 129, 131, 134, 136, 138, + 140, 142, 144, 146, 148, 150, 152, 154, + 156, 158, 161, 164, 166, 169, 172, 174, + 177, 180, 182, 185, 187, 190, 192, 195, + 199, 202, 205, 208, 211, 214, 217, 220, + 223, 226, 230, 233, 237, 240, 243, 247, + 250, 253, 257, 261, 265, 269, 272, 276, + 280, 284, 288, 292, 296, 300, 304, 309, + 313, 317, 322, 326, 330, 335, 340, 344, + 349, 354, 359, 364, 369, 374, 379, 384, + 389, 395, 400, 406, 411, 417, 423, 429, + 435, 441, 447, 454, 461, 467, 475, 482, + 489, 497, 505, 513, 522, 530, 539, 549, + 559, 569, 579, 590, 602, 614, 626, 640, + 654, 668, 684, 700, 717, 736, 755, 775, + 796, 819, 843, 869, 896, 925, 955, 988, + 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336, + }, { + 4, 9, 10, 13, 15, 17, 20, 22, + 25, 28, 31, 34, 37, 40, 43, 47, + 50, 53, 57, 60, 64, 68, 71, 75, + 78, 82, 86, 90, 93, 97, 101, 105, + 109, 113, 116, 120, 124, 128, 132, 136, + 140, 143, 147, 151, 155, 159, 163, 166, + 170, 174, 178, 182, 185, 189, 193, 197, + 200, 204, 208, 212, 215, 219, 223, 226, + 230, 233, 237, 241, 244, 248, 251, 255, + 259, 262, 266, 269, 273, 276, 280, 283, + 287, 290, 293, 297, 300, 304, 307, 310, + 314, 317, 321, 324, 327, 331, 334, 337, + 343, 350, 356, 362, 369, 375, 381, 387, + 394, 400, 406, 412, 418, 424, 430, 436, + 442, 448, 454, 460, 466, 472, 478, 484, + 490, 499, 507, 516, 525, 533, 542, 550, + 559, 567, 576, 584, 592, 601, 609, 617, + 625, 634, 644, 655, 666, 676, 687, 698, + 708, 718, 729, 739, 749, 759, 770, 782, + 795, 807, 819, 831, 844, 856, 868, 880, + 891, 906, 920, 933, 947, 961, 975, 988, + 1001, 1015, 1030, 1045, 1061, 1076, 1090, 1105, + 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, + 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, + 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, + 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717, + 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, + 1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197, + 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, + 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102, + 3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, + 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347, + }, { + 4, 12, 18, 25, 33, 41, 50, 60, + 70, 80, 91, 103, 115, 127, 140, 153, + 166, 180, 194, 208, 222, 237, 251, 266, + 281, 296, 312, 327, 343, 358, 374, 390, + 405, 421, 437, 453, 469, 484, 500, 516, + 532, 548, 564, 580, 596, 611, 627, 643, + 659, 674, 690, 706, 721, 737, 752, 768, + 783, 798, 814, 829, 844, 859, 874, 889, + 904, 919, 934, 949, 964, 978, 993, 1008, + 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, + 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, + 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, + 1368, 1393, 1419, 1444, 1469, 1494, 1519, 1544, + 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, + 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, + 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, + 2233, 2267, 2300, 2334, 2367, 2400, 2434, 2467, + 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, + 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, + 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, + 3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951, + 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, + 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, + 5013, 5083, 5153, 5222, 5291, 5367, 5442, 5517, + 5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, + 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, + 6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, + 7832, 7958, 8085, 8214, 8352, 8492, 8635, 8788, + 8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, + 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, + 12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, + 16356, 16943, 17575, 18237, 18949, 19718, 20521, 21387, + } +}; + +const RK_S16 vp9_ac_qlookup[3][256] = { + { + 4, 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, 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, + 104, 106, 108, 110, 112, 114, 116, 118, + 120, 122, 124, 126, 128, 130, 132, 134, + 136, 138, 140, 142, 144, 146, 148, 150, + 152, 155, 158, 161, 164, 167, 170, 173, + 176, 179, 182, 185, 188, 191, 194, 197, + 200, 203, 207, 211, 215, 219, 223, 227, + 231, 235, 239, 243, 247, 251, 255, 260, + 265, 270, 275, 280, 285, 290, 295, 300, + 305, 311, 317, 323, 329, 335, 341, 347, + 353, 359, 366, 373, 380, 387, 394, 401, + 408, 416, 424, 432, 440, 448, 456, 465, + 474, 483, 492, 501, 510, 520, 530, 540, + 550, 560, 571, 582, 593, 604, 615, 627, + 639, 651, 663, 676, 689, 702, 715, 729, + 743, 757, 771, 786, 801, 816, 832, 848, + 864, 881, 898, 915, 933, 951, 969, 988, + 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, + 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, + 1369, 1396, 1423, 1451, 1479, 1508, 1537, 1567, + 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, + }, { + 4, 9, 11, 13, 16, 18, 21, 24, + 27, 30, 33, 37, 40, 44, 48, 51, + 55, 59, 63, 67, 71, 75, 79, 83, + 88, 92, 96, 100, 105, 109, 114, 118, + 122, 127, 131, 136, 140, 145, 149, 154, + 158, 163, 168, 172, 177, 181, 186, 190, + 195, 199, 204, 208, 213, 217, 222, 226, + 231, 235, 240, 244, 249, 253, 258, 262, + 267, 271, 275, 280, 284, 289, 293, 297, + 302, 306, 311, 315, 319, 324, 328, 332, + 337, 341, 345, 349, 354, 358, 362, 367, + 371, 375, 379, 384, 388, 392, 396, 401, + 409, 417, 425, 433, 441, 449, 458, 466, + 474, 482, 490, 498, 506, 514, 523, 531, + 539, 547, 555, 563, 571, 579, 588, 596, + 604, 616, 628, 640, 652, 664, 676, 688, + 700, 713, 725, 737, 749, 761, 773, 785, + 797, 809, 825, 841, 857, 873, 889, 905, + 922, 938, 954, 970, 986, 1002, 1018, 1038, + 1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, + 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, + 1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, + 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, + 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, + 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, + 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915, + 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, + 3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952, + 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, + 4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372, + 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, + 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312, + }, { + 4, 13, 19, 27, 35, 44, 54, 64, + 75, 87, 99, 112, 126, 139, 154, 168, + 183, 199, 214, 230, 247, 263, 280, 297, + 314, 331, 349, 366, 384, 402, 420, 438, + 456, 475, 493, 511, 530, 548, 567, 586, + 604, 623, 642, 660, 679, 698, 716, 735, + 753, 772, 791, 809, 828, 846, 865, 884, + 902, 920, 939, 957, 976, 994, 1012, 1030, + 1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, + 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, + 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, + 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, + 1627, 1660, 1693, 1725, 1758, 1791, 1824, 1856, + 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, + 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, + 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, + 2798, 2847, 2895, 2943, 2992, 3040, 3088, 3137, + 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, + 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, + 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, + 4871, 4967, 5064, 5160, 5256, 5352, 5448, 5544, + 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, + 6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, + 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, + 8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028, + 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, + 11885, 12109, 12333, 12573, 12813, 13053, 13309, 13565, + 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, + 16110, 16414, 16734, 17054, 17390, 17726, 18062, 18414, + 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, + 21902, 22334, 22766, 23214, 23662, 24126, 24590, 25070, + 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247, + } +}; + +const Vp9ProbCtx vp9_default_probs = { + { /* y_mode */ + { 65, 32, 18, 144, 162, 194, 41, 51, 98 } /* bsize < 8x8 */, + { 132, 68, 18, 165, 217, 196, 45, 40, 78 } /* bsize < 16x16 */, + { 173, 80, 19, 176, 240, 193, 64, 35, 46 } /* bsize < 32x32 */, + { 221, 135, 38, 194, 248, 121, 96, 85, 29 } /* bsize >= 32x32 */ + }, { /* uv_mode */ + { 48, 12, 154, 155, 139, 90, 34, 117, 119 } /* y = v */, + { 67, 6, 25, 204, 243, 158, 13, 21, 96 } /* y = h */, + { 120, 7, 76, 176, 208, 126, 28, 54, 103 } /* y = dc */, + { 97, 5, 44, 131, 176, 139, 48, 68, 97 } /* y = d45 */, + { 83, 5, 42, 156, 111, 152, 26, 49, 152 } /* y = d135 */, + { 80, 5, 58, 178, 74, 83, 33, 62, 145 } /* y = d117 */, + { 86, 5, 32, 154, 192, 168, 14, 22, 163 } /* y = d153 */, + { 77, 7, 64, 116, 132, 122, 37, 126, 120 } /* y = d63 */, + { 85, 5, 32, 156, 216, 148, 19, 29, 73 } /* y = d207 */, + { 101, 21, 107, 181, 192, 103, 19, 67, 125 } /* y = tm */ + }, { /* filter */ + { 235, 162, }, + { 36, 255, }, + { 34, 3, }, + { 149, 144, }, + }, { /* mv_mode */ + { 2, 173, 34}, // 0 = both zero mv + { 7, 145, 85}, // 1 = one zero mv + one a predicted mv + { 7, 166, 63}, // 2 = two predicted mvs + { 7, 94, 66}, // 3 = one predicted/zero and one new mv + { 8, 64, 46}, // 4 = two new mvs + { 17, 81, 31}, // 5 = one intra neighbour + x + { 25, 29, 30}, // 6 = two intra neighbours + }, { /* intra */ + 9, 102, 187, 225 + }, { /* comp */ + 239, 183, 119, 96, 41 + }, { /* single_ref */ + { 33, 16 }, + { 77, 74 }, + { 142, 142 }, + { 172, 170 }, + { 238, 247 } + }, { /* comp_ref */ + 50, 126, 123, 221, 226 + }, { /* tx32p */ + { 3, 136, 37, }, + { 5, 52, 13, }, + }, { /* tx16p */ + { 20, 152, }, + { 15, 101, }, + }, { /* tx8p */ + 100, 66 + }, { /* skip */ + 192, 128, 64 + }, { /* mv_joint */ + 32, 64, 96 + }, { + { /* mv vertical component */ + 128, /* sign */ + { 224, 144, 192, 168, 192, 176, 192, 198, 198, 245 }, /* class */ + 216, /* class0 */ + { 136, 140, 148, 160, 176, 192, 224, 234, 234, 240}, /* bits */ + { /* class0_fp */ + { 128, 128, 64 }, + { 96, 112, 64 } + }, + { 64, 96, 64 }, /* fp */ + 160, /* class0_hp bit */ + 128, /* hp */ + }, { /* mv horizontal component */ + 128, /* sign */ + { 216, 128, 176, 160, 176, 176, 192, 198, 198, 208 }, /* class */ + 208, /* class0 */ + { 136, 140, 148, 160, 176, 192, 224, 234, 234, 240 }, /* bits */ + { /* class0_fp */ + { 128, 128, 64 }, + { 96, 112, 64 } + }, + { 64, 96, 64 }, /* fp */ + 160, /* class0_hp bit */ + 128, /* hp */ + } + }, { /* partition */ + { /* 64x64 -> 32x32 */ + { 222, 34, 30 } /* a/l both not split */, + { 72, 16, 44 } /* a split, l not split */, + { 58, 32, 12 } /* l split, a not split */, + { 10, 7, 6 } /* a/l both split */, + }, { /* 32x32 -> 16x16 */ + { 177, 58, 59 } /* a/l both not split */, + { 68, 26, 63 } /* a split, l not split */, + { 52, 79, 25 } /* l split, a not split */, + { 17, 14, 12 } /* a/l both split */, + }, { /* 16x16 -> 8x8 */ + { 174, 73, 87 } /* a/l both not split */, + { 92, 41, 83 } /* a split, l not split */, + { 82, 99, 50 } /* l split, a not split */, + { 53, 39, 39 } /* a/l both split */, + }, { /* 8x8 -> 4x4 */ + { 199, 122, 141 } /* a/l both not split */, + { 147, 63, 159 } /* a split, l not split */, + { 148, 133, 118 } /* l split, a not split */, + { 121, 104, 114 } /* a/l both split */, + } + }, +}; + +const RK_U8 vp9_default_coef_probs[4][2][2][6][6][3] = { + { /* tx = 4x4 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 195, 29, 183 }, + { 84, 49, 136 }, + { 8, 42, 71 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 31, 107, 169 }, + { 35, 99, 159 }, + { 17, 82, 140 }, + { 8, 66, 114 }, + { 2, 44, 76 }, + { 1, 19, 32 } + }, { /* Coeff Band 2 */ + { 40, 132, 201 }, + { 29, 114, 187 }, + { 13, 91, 157 }, + { 7, 75, 127 }, + { 3, 58, 95 }, + { 1, 28, 47 } + }, { /* Coeff Band 3 */ + { 69, 142, 221 }, + { 42, 122, 201 }, + { 15, 91, 159 }, + { 6, 67, 121 }, + { 1, 42, 77 }, + { 1, 17, 31 } + }, { /* Coeff Band 4 */ + { 102, 148, 228 }, + { 67, 117, 204 }, + { 17, 82, 154 }, + { 6, 59, 114 }, + { 2, 39, 75 }, + { 1, 15, 29 } + }, { /* Coeff Band 5 */ + { 156, 57, 233 }, + { 119, 57, 212 }, + { 58, 48, 163 }, + { 29, 40, 124 }, + { 12, 30, 81 }, + { 3, 12, 31 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 191, 107, 226 }, + { 124, 117, 204 }, + { 25, 99, 155 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 29, 148, 210 }, + { 37, 126, 194 }, + { 8, 93, 157 }, + { 2, 68, 118 }, + { 1, 39, 69 }, + { 1, 17, 33 } + }, { /* Coeff Band 2 */ + { 41, 151, 213 }, + { 27, 123, 193 }, + { 3, 82, 144 }, + { 1, 58, 105 }, + { 1, 32, 60 }, + { 1, 13, 26 } + }, { /* Coeff Band 3 */ + { 59, 159, 220 }, + { 23, 126, 198 }, + { 4, 88, 151 }, + { 1, 66, 114 }, + { 1, 38, 71 }, + { 1, 18, 34 } + }, { /* Coeff Band 4 */ + { 114, 136, 232 }, + { 51, 114, 207 }, + { 11, 83, 155 }, + { 3, 56, 105 }, + { 1, 33, 65 }, + { 1, 17, 34 } + }, { /* Coeff Band 5 */ + { 149, 65, 234 }, + { 121, 57, 215 }, + { 61, 49, 166 }, + { 28, 36, 114 }, + { 12, 25, 76 }, + { 3, 16, 42 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 214, 49, 220 }, + { 132, 63, 188 }, + { 42, 65, 137 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 85, 137, 221 }, + { 104, 131, 216 }, + { 49, 111, 192 }, + { 21, 87, 155 }, + { 2, 49, 87 }, + { 1, 16, 28 } + }, { /* Coeff Band 2 */ + { 89, 163, 230 }, + { 90, 137, 220 }, + { 29, 100, 183 }, + { 10, 70, 135 }, + { 2, 42, 81 }, + { 1, 17, 33 } + }, { /* Coeff Band 3 */ + { 108, 167, 237 }, + { 55, 133, 222 }, + { 15, 97, 179 }, + { 4, 72, 135 }, + { 1, 45, 85 }, + { 1, 19, 38 } + }, { /* Coeff Band 4 */ + { 124, 146, 240 }, + { 66, 124, 224 }, + { 17, 88, 175 }, + { 4, 58, 122 }, + { 1, 36, 75 }, + { 1, 18, 37 } + }, { /* Coeff Band 5 */ + { 141, 79, 241 }, + { 126, 70, 227 }, + { 66, 58, 182 }, + { 30, 44, 136 }, + { 12, 34, 96 }, + { 2, 20, 47 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 229, 99, 249 }, + { 143, 111, 235 }, + { 46, 109, 192 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 82, 158, 236 }, + { 94, 146, 224 }, + { 25, 117, 191 }, + { 9, 87, 149 }, + { 3, 56, 99 }, + { 1, 33, 57 } + }, { /* Coeff Band 2 */ + { 83, 167, 237 }, + { 68, 145, 222 }, + { 10, 103, 177 }, + { 2, 72, 131 }, + { 1, 41, 79 }, + { 1, 20, 39 } + }, { /* Coeff Band 3 */ + { 99, 167, 239 }, + { 47, 141, 224 }, + { 10, 104, 178 }, + { 2, 73, 133 }, + { 1, 44, 85 }, + { 1, 22, 47 } + }, { /* Coeff Band 4 */ + { 127, 145, 243 }, + { 71, 129, 228 }, + { 17, 93, 177 }, + { 3, 61, 124 }, + { 1, 41, 84 }, + { 1, 21, 52 } + }, { /* Coeff Band 5 */ + { 157, 78, 244 }, + { 140, 72, 231 }, + { 69, 58, 184 }, + { 31, 44, 137 }, + { 14, 38, 105 }, + { 8, 23, 61 } + } + } + } + }, { /* tx = 8x8 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 125, 34, 187 }, + { 52, 41, 133 }, + { 6, 31, 56 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 37, 109, 153 }, + { 51, 102, 147 }, + { 23, 87, 128 }, + { 8, 67, 101 }, + { 1, 41, 63 }, + { 1, 19, 29 } + }, { /* Coeff Band 2 */ + { 31, 154, 185 }, + { 17, 127, 175 }, + { 6, 96, 145 }, + { 2, 73, 114 }, + { 1, 51, 82 }, + { 1, 28, 45 } + }, { /* Coeff Band 3 */ + { 23, 163, 200 }, + { 10, 131, 185 }, + { 2, 93, 148 }, + { 1, 67, 111 }, + { 1, 41, 69 }, + { 1, 14, 24 } + }, { /* Coeff Band 4 */ + { 29, 176, 217 }, + { 12, 145, 201 }, + { 3, 101, 156 }, + { 1, 69, 111 }, + { 1, 39, 63 }, + { 1, 14, 23 } + }, { /* Coeff Band 5 */ + { 57, 192, 233 }, + { 25, 154, 215 }, + { 6, 109, 167 }, + { 3, 78, 118 }, + { 1, 48, 69 }, + { 1, 21, 29 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 202, 105, 245 }, + { 108, 106, 216 }, + { 18, 90, 144 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 33, 172, 219 }, + { 64, 149, 206 }, + { 14, 117, 177 }, + { 5, 90, 141 }, + { 2, 61, 95 }, + { 1, 37, 57 } + }, { /* Coeff Band 2 */ + { 33, 179, 220 }, + { 11, 140, 198 }, + { 1, 89, 148 }, + { 1, 60, 104 }, + { 1, 33, 57 }, + { 1, 12, 21 } + }, { /* Coeff Band 3 */ + { 30, 181, 221 }, + { 8, 141, 198 }, + { 1, 87, 145 }, + { 1, 58, 100 }, + { 1, 31, 55 }, + { 1, 12, 20 } + }, { /* Coeff Band 4 */ + { 32, 186, 224 }, + { 7, 142, 198 }, + { 1, 86, 143 }, + { 1, 58, 100 }, + { 1, 31, 55 }, + { 1, 12, 22 } + }, { /* Coeff Band 5 */ + { 57, 192, 227 }, + { 20, 143, 204 }, + { 3, 96, 154 }, + { 1, 68, 112 }, + { 1, 42, 69 }, + { 1, 19, 32 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 212, 35, 215 }, + { 113, 47, 169 }, + { 29, 48, 105 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 74, 129, 203 }, + { 106, 120, 203 }, + { 49, 107, 178 }, + { 19, 84, 144 }, + { 4, 50, 84 }, + { 1, 15, 25 } + }, { /* Coeff Band 2 */ + { 71, 172, 217 }, + { 44, 141, 209 }, + { 15, 102, 173 }, + { 6, 76, 133 }, + { 2, 51, 89 }, + { 1, 24, 42 } + }, { /* Coeff Band 3 */ + { 64, 185, 231 }, + { 31, 148, 216 }, + { 8, 103, 175 }, + { 3, 74, 131 }, + { 1, 46, 81 }, + { 1, 18, 30 } + }, { /* Coeff Band 4 */ + { 65, 196, 235 }, + { 25, 157, 221 }, + { 5, 105, 174 }, + { 1, 67, 120 }, + { 1, 38, 69 }, + { 1, 15, 30 } + }, { /* Coeff Band 5 */ + { 65, 204, 238 }, + { 30, 156, 224 }, + { 7, 107, 177 }, + { 2, 70, 124 }, + { 1, 42, 73 }, + { 1, 18, 34 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 225, 86, 251 }, + { 144, 104, 235 }, + { 42, 99, 181 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 85, 175, 239 }, + { 112, 165, 229 }, + { 29, 136, 200 }, + { 12, 103, 162 }, + { 6, 77, 123 }, + { 2, 53, 84 } + }, { /* Coeff Band 2 */ + { 75, 183, 239 }, + { 30, 155, 221 }, + { 3, 106, 171 }, + { 1, 74, 128 }, + { 1, 44, 76 }, + { 1, 17, 28 } + }, { /* Coeff Band 3 */ + { 73, 185, 240 }, + { 27, 159, 222 }, + { 2, 107, 172 }, + { 1, 75, 127 }, + { 1, 42, 73 }, + { 1, 17, 29 } + }, { /* Coeff Band 4 */ + { 62, 190, 238 }, + { 21, 159, 222 }, + { 2, 107, 172 }, + { 1, 72, 122 }, + { 1, 40, 71 }, + { 1, 18, 32 } + }, { /* Coeff Band 5 */ + { 61, 199, 240 }, + { 27, 161, 226 }, + { 4, 113, 180 }, + { 1, 76, 129 }, + { 1, 46, 80 }, + { 1, 23, 41 } + } + } + } + }, { /* tx = 16x16 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 7, 27, 153 }, + { 5, 30, 95 }, + { 1, 16, 30 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 50, 75, 127 }, + { 57, 75, 124 }, + { 27, 67, 108 }, + { 10, 54, 86 }, + { 1, 33, 52 }, + { 1, 12, 18 } + }, { /* Coeff Band 2 */ + { 43, 125, 151 }, + { 26, 108, 148 }, + { 7, 83, 122 }, + { 2, 59, 89 }, + { 1, 38, 60 }, + { 1, 17, 27 } + }, { /* Coeff Band 3 */ + { 23, 144, 163 }, + { 13, 112, 154 }, + { 2, 75, 117 }, + { 1, 50, 81 }, + { 1, 31, 51 }, + { 1, 14, 23 } + }, { /* Coeff Band 4 */ + { 18, 162, 185 }, + { 6, 123, 171 }, + { 1, 78, 125 }, + { 1, 51, 86 }, + { 1, 31, 54 }, + { 1, 14, 23 } + }, { /* Coeff Band 5 */ + { 15, 199, 227 }, + { 3, 150, 204 }, + { 1, 91, 146 }, + { 1, 55, 95 }, + { 1, 30, 53 }, + { 1, 11, 20 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 19, 55, 240 }, + { 19, 59, 196 }, + { 3, 52, 105 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 41, 166, 207 }, + { 104, 153, 199 }, + { 31, 123, 181 }, + { 14, 101, 152 }, + { 5, 72, 106 }, + { 1, 36, 52 } + }, { /* Coeff Band 2 */ + { 35, 176, 211 }, + { 12, 131, 190 }, + { 2, 88, 144 }, + { 1, 60, 101 }, + { 1, 36, 60 }, + { 1, 16, 28 } + }, { /* Coeff Band 3 */ + { 28, 183, 213 }, + { 8, 134, 191 }, + { 1, 86, 142 }, + { 1, 56, 96 }, + { 1, 30, 53 }, + { 1, 12, 20 } + }, { /* Coeff Band 4 */ + { 20, 190, 215 }, + { 4, 135, 192 }, + { 1, 84, 139 }, + { 1, 53, 91 }, + { 1, 28, 49 }, + { 1, 11, 20 } + }, { /* Coeff Band 5 */ + { 13, 196, 216 }, + { 2, 137, 192 }, + { 1, 86, 143 }, + { 1, 57, 99 }, + { 1, 32, 56 }, + { 1, 13, 24 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 211, 29, 217 }, + { 96, 47, 156 }, + { 22, 43, 87 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 78, 120, 193 }, + { 111, 116, 186 }, + { 46, 102, 164 }, + { 15, 80, 128 }, + { 2, 49, 76 }, + { 1, 18, 28 } + }, { /* Coeff Band 2 */ + { 71, 161, 203 }, + { 42, 132, 192 }, + { 10, 98, 150 }, + { 3, 69, 109 }, + { 1, 44, 70 }, + { 1, 18, 29 } + }, { /* Coeff Band 3 */ + { 57, 186, 211 }, + { 30, 140, 196 }, + { 4, 93, 146 }, + { 1, 62, 102 }, + { 1, 38, 65 }, + { 1, 16, 27 } + }, { /* Coeff Band 4 */ + { 47, 199, 217 }, + { 14, 145, 196 }, + { 1, 88, 142 }, + { 1, 57, 98 }, + { 1, 36, 62 }, + { 1, 15, 26 } + }, { /* Coeff Band 5 */ + { 26, 219, 229 }, + { 5, 155, 207 }, + { 1, 94, 151 }, + { 1, 60, 104 }, + { 1, 36, 62 }, + { 1, 16, 28 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 233, 29, 248 }, + { 146, 47, 220 }, + { 43, 52, 140 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 100, 163, 232 }, + { 179, 161, 222 }, + { 63, 142, 204 }, + { 37, 113, 174 }, + { 26, 89, 137 }, + { 18, 68, 97 } + }, { /* Coeff Band 2 */ + { 85, 181, 230 }, + { 32, 146, 209 }, + { 7, 100, 164 }, + { 3, 71, 121 }, + { 1, 45, 77 }, + { 1, 18, 30 } + }, { /* Coeff Band 3 */ + { 65, 187, 230 }, + { 20, 148, 207 }, + { 2, 97, 159 }, + { 1, 68, 116 }, + { 1, 40, 70 }, + { 1, 14, 29 } + }, { /* Coeff Band 4 */ + { 40, 194, 227 }, + { 8, 147, 204 }, + { 1, 94, 155 }, + { 1, 65, 112 }, + { 1, 39, 66 }, + { 1, 14, 26 } + }, { /* Coeff Band 5 */ + { 16, 208, 228 }, + { 3, 151, 207 }, + { 1, 98, 160 }, + { 1, 67, 117 }, + { 1, 41, 74 }, + { 1, 17, 31 } + } + } + } + }, { /* tx = 32x32 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 17, 38, 140 }, + { 7, 34, 80 }, + { 1, 17, 29 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 37, 75, 128 }, + { 41, 76, 128 }, + { 26, 66, 116 }, + { 12, 52, 94 }, + { 2, 32, 55 }, + { 1, 10, 16 } + }, { /* Coeff Band 2 */ + { 50, 127, 154 }, + { 37, 109, 152 }, + { 16, 82, 121 }, + { 5, 59, 85 }, + { 1, 35, 54 }, + { 1, 13, 20 } + }, { /* Coeff Band 3 */ + { 40, 142, 167 }, + { 17, 110, 157 }, + { 2, 71, 112 }, + { 1, 44, 72 }, + { 1, 27, 45 }, + { 1, 11, 17 } + }, { /* Coeff Band 4 */ + { 30, 175, 188 }, + { 9, 124, 169 }, + { 1, 74, 116 }, + { 1, 48, 78 }, + { 1, 30, 49 }, + { 1, 11, 18 } + }, { /* Coeff Band 5 */ + { 10, 222, 223 }, + { 2, 150, 194 }, + { 1, 83, 128 }, + { 1, 48, 79 }, + { 1, 27, 45 }, + { 1, 11, 17 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 36, 41, 235 }, + { 29, 36, 193 }, + { 10, 27, 111 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 85, 165, 222 }, + { 177, 162, 215 }, + { 110, 135, 195 }, + { 57, 113, 168 }, + { 23, 83, 120 }, + { 10, 49, 61 } + }, { /* Coeff Band 2 */ + { 85, 190, 223 }, + { 36, 139, 200 }, + { 5, 90, 146 }, + { 1, 60, 103 }, + { 1, 38, 65 }, + { 1, 18, 30 } + }, { /* Coeff Band 3 */ + { 72, 202, 223 }, + { 23, 141, 199 }, + { 2, 86, 140 }, + { 1, 56, 97 }, + { 1, 36, 61 }, + { 1, 16, 27 } + }, { /* Coeff Band 4 */ + { 55, 218, 225 }, + { 13, 145, 200 }, + { 1, 86, 141 }, + { 1, 57, 99 }, + { 1, 35, 61 }, + { 1, 13, 22 } + }, { /* Coeff Band 5 */ + { 15, 235, 212 }, + { 1, 132, 184 }, + { 1, 84, 139 }, + { 1, 57, 97 }, + { 1, 34, 56 }, + { 1, 14, 23 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 181, 21, 201 }, + { 61, 37, 123 }, + { 10, 38, 71 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 47, 106, 172 }, + { 95, 104, 173 }, + { 42, 93, 159 }, + { 18, 77, 131 }, + { 4, 50, 81 }, + { 1, 17, 23 } + }, { /* Coeff Band 2 */ + { 62, 147, 199 }, + { 44, 130, 189 }, + { 28, 102, 154 }, + { 18, 75, 115 }, + { 2, 44, 65 }, + { 1, 12, 19 } + }, { /* Coeff Band 3 */ + { 55, 153, 210 }, + { 24, 130, 194 }, + { 3, 93, 146 }, + { 1, 61, 97 }, + { 1, 31, 50 }, + { 1, 10, 16 } + }, { /* Coeff Band 4 */ + { 49, 186, 223 }, + { 17, 148, 204 }, + { 1, 96, 142 }, + { 1, 53, 83 }, + { 1, 26, 44 }, + { 1, 11, 17 } + }, { /* Coeff Band 5 */ + { 13, 217, 212 }, + { 2, 136, 180 }, + { 1, 78, 124 }, + { 1, 50, 83 }, + { 1, 29, 49 }, + { 1, 14, 23 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 197, 13, 247 }, + { 82, 17, 222 }, + { 25, 17, 162 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, { /* Coeff Band 1 */ + { 126, 186, 247 }, + { 234, 191, 243 }, + { 176, 177, 234 }, + { 104, 158, 220 }, + { 66, 128, 186 }, + { 55, 90, 137 } + }, { /* Coeff Band 2 */ + { 111, 197, 242 }, + { 46, 158, 219 }, + { 9, 104, 171 }, + { 2, 65, 125 }, + { 1, 44, 80 }, + { 1, 17, 91 } + }, { /* Coeff Band 3 */ + { 104, 208, 245 }, + { 39, 168, 224 }, + { 3, 109, 162 }, + { 1, 79, 124 }, + { 1, 50, 102 }, + { 1, 43, 102 } + }, { /* Coeff Band 4 */ + { 84, 220, 246 }, + { 31, 177, 231 }, + { 2, 115, 180 }, + { 1, 79, 134 }, + { 1, 55, 77 }, + { 1, 60, 79 } + }, { /* Coeff Band 5 */ + { 43, 243, 240 }, + { 8, 180, 217 }, + { 1, 115, 166 }, + { 1, 84, 121 }, + { 1, 51, 67 }, + { 1, 16, 6 } + } + } + } + } +}; + +static const RK_U8 norm_shift_table[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +RK_S32 vp9d_reader_init(Vp9dReader *r, const uint8_t *buf, RK_S32 buf_size) +{ + r->range = 255; + r->bits_left = -16; // minus 16 before read + r->buffer = buf; + r->buffer_end = buf + buf_size; + r->value = MPP_RB24(r->buffer); + r->buffer += 3; + + return 0; +} + +RK_S32 vp9d_read(Vp9dReader *r, RK_S32 prob) +{ + RK_U8 shift = norm_shift_table[r->range]; + RK_S32 bits = r->bits_left; + RK_U32 val = r->value; + + // shift value to make room for more bits + // and add more bits from buffer + r->range <<= shift; + val <<= shift; + bits += shift; + if (bits >= 0 && r->buffer < r->buffer_end) { + val |= MPP_RB16(r->buffer) << bits; + r->buffer += 2; // 2 bytes + bits -= 16; // minus 16 bits + } + r->bits_left = bits; + + // shift low to make room for more bits + RK_U32 low = 1 + (((r->range - 1) * prob) >> 8); + RK_U32 low_shift = low << 16; + + if (val >= low_shift) { + r->range -= low; + r->value = val - low_shift; + return 1; + } + + r->range = low; + r->value = val; + return 0; +} + +RK_S32 vp9d_read_bit(Vp9dReader *r) +{ + return vp9d_read(r, 128); +} + +RK_S32 vp9d_read_bits(Vp9dReader *r, RK_S32 bits) +{ + RK_S32 val = 0; + + while (bits--) { + val = (val << 1) | vp9d_read(r, 128); + } + + return val; +} + +static RK_S32 inv_recenter_nonneg(RK_S32 v, RK_S32 m) +{ + return v > 2 * m ? v : v & 1 ? m - ((v + 1) >> 1) : m + (v >> 1); +} + +static const RK_S32 inv_map_table[255] = { + 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, + 189, 202, 215, 228, 241, 254, 1, 2, 3, 4, 5, 6, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 253, +}; + +RK_S32 vp9d_diff_update_prob(Vp9dReader *r, RK_S32 prob, RK_U8 *delta) +{ + RK_S32 delp; + + if (!vp9d_read_bit(r)) { + delp = vp9d_read_bits(r, 4) + 0; + } else if (!vp9d_read_bit(r)) { + delp = vp9d_read_bits(r, 4) + 16; + } else if (!vp9d_read_bit(r)) { + delp = vp9d_read_bits(r, 5) + 32; + } else { + delp = vp9d_read_bits(r, 7); + if (delp < 65) { + delp += 64; + } else { + delp = (delp << 1) - 1 + vp9d_read_bit(r); + } + } + *delta = delp; + if (prob <= 128) { + delp = inv_recenter_nonneg(inv_map_table[delp], prob - 1); + } else { + delp = 255 - inv_recenter_nonneg(inv_map_table[delp], 255 - prob); + } + return delp; +} + +/* a*inverse[b]>>32 == a/b */ +#define FASTDIV(a,b) ((RK_U32)((((RK_U64)a) * div_inverse[b]) >> 32)) + +const RK_U32 div_inverse[257] = { + 0, 4294967295U, 2147483648U, 1431655766, 1073741824, 858993460, 715827883, 613566757, + 536870912, 477218589, 429496730, 390451573, 357913942, 330382100, 306783379, 286331154, + 268435456, 252645136, 238609295, 226050911, 214748365, 204522253, 195225787, 186737709, + 178956971, 171798692, 165191050, 159072863, 153391690, 148102321, 143165577, 138547333, + 134217728, 130150525, 126322568, 122713352, 119304648, 116080198, 113025456, 110127367, + 107374183, 104755300, 102261127, 99882961, 97612894, 95443718, 93368855, 91382283, + 89478486, 87652394, 85899346, 84215046, 82595525, 81037119, 79536432, 78090315, + 76695845, 75350304, 74051161, 72796056, 71582789, 70409300, 69273667, 68174085, + 67108864, 66076420, 65075263, 64103990, 63161284, 62245903, 61356676, 60492498, + 59652324, 58835169, 58040099, 57266231, 56512728, 55778797, 55063684, 54366675, + 53687092, 53024288, 52377650, 51746594, 51130564, 50529028, 49941481, 49367441, + 48806447, 48258060, 47721859, 47197443, 46684428, 46182445, 45691142, 45210183, + 44739243, 44278014, 43826197, 43383509, 42949673, 42524429, 42107523, 41698712, + 41297763, 40904451, 40518560, 40139882, 39768216, 39403370, 39045158, 38693400, + 38347923, 38008561, 37675152, 37347542, 37025581, 36709123, 36398028, 36092163, + 35791395, 35495598, 35204650, 34918434, 34636834, 34359739, 34087043, 33818641, + 33554432, 33294321, 33038210, 32786010, 32537632, 32292988, 32051995, 31814573, + 31580642, 31350127, 31122952, 30899046, 30678338, 30460761, 30246249, 30034737, + 29826162, 29620465, 29417585, 29217465, 29020050, 28825284, 28633116, 28443493, + 28256364, 28071682, 27889399, 27709467, 27531842, 27356480, 27183338, 27012373, + 26843546, 26676816, 26512144, 26349493, 26188825, 26030105, 25873297, 25718368, + 25565282, 25414008, 25264514, 25116768, 24970741, 24826401, 24683721, 24542671, + 24403224, 24265352, 24129030, 23994231, 23860930, 23729102, 23598722, 23469767, + 23342214, 23216040, 23091223, 22967740, 22845571, 22724695, 22605092, 22486740, + 22369622, 22253717, 22139007, 22025474, 21913099, 21801865, 21691755, 21582751, + 21474837, 21367997, 21262215, 21157475, 21053762, 20951060, 20849356, 20748635, + 20648882, 20550083, 20452226, 20355296, 20259280, 20164166, 20069941, 19976593, + 19884108, 19792477, 19701685, 19611723, 19522579, 19434242, 19346700, 19259944, + 19173962, 19088744, 19004281, 18920561, 18837576, 18755316, 18673771, 18592933, + 18512791, 18433337, 18354562, 18276457, 18199014, 18122225, 18046082, 17970575, + 17895698, 17821442, 17747799, 17674763, 17602325, 17530479, 17459217, 17388532, + 17318417, 17248865, 17179870, 17111424, 17043522, 16976156, 16909321, 16843010, + 16777216 +}; + +RK_S32 vp9d_merge_prob(RK_U8 *prob, RK_U32 cout0, RK_U32 cout1, + RK_S32 max_count, RK_S32 factor) +{ + RK_U32 cout = cout0 + cout1; + + if (cout) { + RK_U32 prob2, prob1; + + prob1 = *prob; + prob2 = ((cout0 << 8) + (cout >> 1)) / cout; + prob2 = mpp_clip(prob2, 1, 255); + + cout = MPP_MIN(cout, (RK_U32)max_count); + factor = FASTDIV(factor * cout, max_count); + + // weighted prob: function (v1 * (256 - w) + v2 * w + 128) >> 8 + *prob = prob1 + (((prob2 - prob1) * factor + 128) >> 8); + } + + return 0; +} diff --git a/mpp/codec/dec/vp9/vp9d_ctx.h b/mpp/codec/dec/vp9/vp9d_ctx.h new file mode 100644 index 000000000..8e7642aef --- /dev/null +++ b/mpp/codec/dec/vp9/vp9d_ctx.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef VP9D_CODEC_H +#define VP9D_CODEC_H + +#include "mpp_frame.h" +#include "hal_dec_task.h" + +#include "vp9d_syntax.h" + +typedef enum VP9Profile_e { + VP9_PROFILE_0 = 0, + VP9_PROFILE_1 = 1, + VP9_PROFILE_2 = 2, + VP9_PROFILE_3 = 3, + VP9_MAX_PROFILES +} VP9Profile; + +typedef enum VP9TxfmMode_e { + VP9_TX_4X4 = 0, + VP9_TX_8X8 = 1, + VP9_TX_16X16 = 2, + VP9_TX_32X32 = 3, + VP9_TX_SWITCHABLE = 4, + VP9_N_TXFM_MODES +} VP9TxfmMode; + +typedef enum VP9TxfmType_e { + VP9_DCT_DCT = 0, + VP9_DCT_ADST = 1, + VP9_ADST_DCT = 2, + VP9_ADST_ADST = 3, + VP9_N_TXFM_TYPES +} VP9TxfmType; + +typedef enum VP9IntraPredMode_e { + VP9_VERT_PRED = 0, + VP9_HOR_PRED = 1, + VP9_DC_PRED = 2, + VP9_DIAG_DOWN_LEFT_PRED = 3, + VP9_DIAG_DOWN_RIGHT_PRED = 4, + VP9_VERT_RIGHT_PRED = 5, + VP9_HOR_DOWN_PRED = 6, + VP9_VERT_LEFT_PRED = 7, + VP9_HOR_UP_PRED = 8, + VP9_TM_VP8_PRED = 9, + VP9_LEFT_DC_PRED = 10, + VP9_TOP_DC_PRED = 11, + VP9_DC_128_PRED = 12, + VP9_DC_127_PRED = 13, + VP9_DC_129_PRED = 14, + VP9_N_INTRA_PRED_MODES +} VP9IntraPredMode; + +typedef enum VP9FilterMode_e { + VP9_FILTER_8TAP_SMOOTH = 0, + VP9_FILTER_8TAP_REGULAR = 1, + VP9_FILTER_8TAP_SHARP = 2, + VP9_FILTER_BILINEAR = 3, + VP9_FILTER_SWITCHABLE = 4, +} VP9FilterMode; + + +typedef enum VP9CompPredMode_e { + VP9_PRED_SINGLEREF = 0, + VP9_PRED_COMPREF = 1, + VP9_PRED_SWITCHABLE = 2, +} VP9CompPredMode; + +typedef enum VP9BlockLevel_e { + VP9_BL_64X64 = 0, + VP9_BL_32X32 = 1, + VP9_BL_16X16 = 2, + VP9_BL_8X8 = 3, +} VP9BlockLevel; + +typedef enum VP9BlockSize_e { + VP9_BS_64x64 = 0, + VP9_BS_64x32 = 1, + VP9_BS_32x64 = 2, + VP9_BS_32x32 = 3, + VP9_BS_32x16 = 4, + VP9_BS_16x32 = 5, + VP9_BS_16x16 = 6, + VP9_BS_16x8 = 7, + VP9_BS_8x16 = 8, + VP9_BS_8x8 = 9, + VP9_BS_8x4 = 10, + VP9_BS_4x8 = 11, + VP9_BS_4x4 = 12, + N_BS_SIZES = 13, +} VP9BlockSize; + +typedef struct Vp9dReader_t { + RK_S32 range; + RK_S32 bits_left; + const RK_U8 *buffer; + const RK_U8 *buffer_end; + RK_U32 value; +} Vp9dReader; + +typedef struct Vp9ProbCtx_t { + RK_U8 y_mode[4][9]; + RK_U8 uv_mode[10][9]; + RK_U8 filter[4][2]; + RK_U8 mv_mode[7][3]; + RK_U8 intra[4]; + RK_U8 comp[5]; + RK_U8 single_ref[5][2]; + RK_U8 comp_ref[5]; + RK_U8 tx32p[2][3]; + RK_U8 tx16p[2][2]; + RK_U8 tx8p[2]; + RK_U8 skip[3]; + RK_U8 mv_joint[3]; + struct { + RK_U8 sign; + RK_U8 classes[10]; + RK_U8 class0; + RK_U8 bits[10]; + RK_U8 class0_fp[2][3]; + RK_U8 fp[3]; + RK_U8 class0_hp; + RK_U8 hp; + } mv_comp[2]; + RK_U8 partition[4][4][3]; +} Vp9ProbCtx; + +// extern const variables +extern const RK_S16 vp9_dc_qlookup[3][256]; +extern const RK_S16 vp9_ac_qlookup[3][256]; +extern const Vp9ProbCtx vp9_default_probs; +extern const RK_U8 vp9_default_coef_probs[4][2][2][6][6][3]; + +#ifdef __cplusplus +extern "C" { +#endif + +// vp9 specific bitread range decoder +RK_S32 vp9d_reader_init(Vp9dReader *r, const uint8_t *buf, RK_S32 buf_size); +RK_S32 vp9d_read(Vp9dReader *r, RK_S32 prob); +RK_S32 vp9d_read_bit(Vp9dReader *r); +RK_S32 vp9d_read_bits(Vp9dReader *r, RK_S32 bits); +RK_S32 vp9d_diff_update_prob(Vp9dReader *r, RK_S32 prob, RK_U8 *delta); +RK_S32 vp9d_merge_prob(RK_U8 *prob, RK_U32 cout0, RK_U32 cout1, RK_S32 max_count, RK_S32 factor); + +#ifdef __cplusplus +} +#endif + +#endif /* VP9D_CODEC_H */ diff --git a/mpp/codec/enc/CMakeLists.txt b/mpp/codec/enc/CMakeLists.txt index 9d2f11611..7a8552467 100644 --- a/mpp/codec/enc/CMakeLists.txt +++ b/mpp/codec/enc/CMakeLists.txt @@ -1,3 +1,20 @@ # vim: syntax=cmake add_subdirectory(dummy) + +if(HAVE_H264E) +add_subdirectory(h264) +endif() + +if(HAVE_JPEGE) +add_subdirectory(jpeg) +endif() + +if(HAVE_H265E) +add_subdirectory(h265) +endif() + +if(HAVE_VP8E) +add_subdirectory(vp8) +endif() + diff --git a/mpp/codec/enc/dummy/CMakeLists.txt b/mpp/codec/enc/dummy/CMakeLists.txt index 862be4259..7ab71768f 100644 --- a/mpp/codec/enc/dummy/CMakeLists.txt +++ b/mpp/codec/enc/dummy/CMakeLists.txt @@ -1,27 +1,5 @@ # vim: syntax=cmake -# dummy decoder api -set(DUMMY_API - ../../inc/dummy_enc_api.h - ) - - -# dummy decoder header -set(DUMMY_HDR - - ) - -# dummy decoder sourse -set(DUMMY_SRC +add_library(codec_dummy_enc OBJECT dummy_enc_api.c - ) - - -add_library(codec_dummy_enc STATIC - ${DUMMY_API} - ${DUMMY_HDR} - ${DUMMY_SRC} - ) - -set_target_properties(codec_dummy_enc PROPERTIES FOLDER "mpp/codec") - + ) diff --git a/mpp/codec/enc/dummy/dummy_enc_api.c b/mpp/codec/enc/dummy/dummy_enc_api.c index 29cc8693e..5d05d1f76 100644 --- a/mpp/codec/enc/dummy/dummy_enc_api.c +++ b/mpp/codec/enc/dummy/dummy_enc_api.c @@ -1,22 +1,22 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#define MODULE_TAG "dummy_enc_api" - -#include "dummy_enc_api.h" - - - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define MODULE_TAG "dummy_enc_api" + +#include "dummy_enc_api.h" + + + diff --git a/mpp/codec/enc/h264/CMakeLists.txt b/mpp/codec/enc/h264/CMakeLists.txt new file mode 100644 index 000000000..ef222c0b1 --- /dev/null +++ b/mpp/codec/enc/h264/CMakeLists.txt @@ -0,0 +1,13 @@ +# vim: syntax=cmake +include_directories(.) +include_directories(include) + +# h264 encoder api +add_library(h264e_api OBJECT + h264e_api_v2.c + h264e_sps.c + h264e_pps.c + h264e_sei.c + h264e_dpb.c + h264e_slice.c + ) diff --git a/mpp/codec/enc/h264/h264e_api_v2.c b/mpp/codec/enc/h264/h264e_api_v2.c new file mode 100644 index 000000000..cd907254b --- /dev/null +++ b/mpp/codec/enc/h264/h264e_api_v2.c @@ -0,0 +1,630 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_api_v2" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "mpp_packet_impl.h" +#include "mpp_enc_refs.h" + +#include "h264e_debug.h" +#include "h264e_syntax.h" +#include "h264e_sps.h" +#include "h264e_pps.h" +#include "h264e_sei.h" +#include "h264e_dpb.h" +#include "h264e_slice.h" +#include "h264e_api_v2.h" +#include "rc.h" +#include "mpp_rc.h" +#include "mpp_soc.h" + +#include "enc_impl_api.h" +#include "mpp_enc_cfg.h" +#include "mpp_enc_impl.h" + +RK_U32 h264e_debug = 0; + +typedef struct { + /* config from mpp_enc */ + MppClientType type; + MppEncCfgSet *cfg; + MppEncRefs refs; + RK_U32 idr_request; + RK_U32 pre_ref_idx; + + /* H.264 high level syntax */ + H264eSps sps; + H264ePps pps; + + /* + * H.264 low level syntax + * + * NOTE: two dpb is for dpb roll-back and reencode + */ + H264eDpb dpb; + H264eDpb dpb_bak; + H264eSlice slice; + H264eReorderInfo reorder; + H264eMarkingInfo marking; + /* H.264 frame status syntax */ + H264eFrmInfo frms; + /* header generation */ + MppPacket hdr_pkt; + void *hdr_buf; + size_t hdr_size; + size_t hdr_len; + RK_S32 sps_offset; + RK_S32 sps_len; + RK_S32 pps_offset; + RK_S32 pps_len; + RK_S32 prefix_offset; + RK_S32 prefix_len; + H264ePrefixNal prefix; + + /* rate control config */ + RcCtx rc_ctx; + + /* output to hal */ + RK_S32 syn_num; + H264eSyntaxDesc syntax[H264E_SYN_BUTT]; +} H264eCtx; + +static void init_h264e_cfg_set(MppEncCfgSet *cfg, MppClientType type) +{ + MppEncRcCfg *rc_cfg = &cfg->rc; + MppEncPrepCfg *prep = &cfg->prep; + MppEncH264Cfg *h264 = &cfg->h264; + + /* + * default codec: + * High Profile + * frame mode + * all flag enabled + */ + memset(h264, 0, sizeof(*h264)); + h264->profile = H264_PROFILE_BASELINE; + h264->level = H264_LEVEL_3_1; + h264->vui.vui_en = 1; + cfg->tune.scene_mode = MPP_ENC_SCENE_MODE_DEFAULT; + cfg->tune.deblur_en = 0; + cfg->tune.vmaf_opt = 0; + + switch (type) { + case VPU_CLIENT_VEPU1 : + case VPU_CLIENT_VEPU2 : { + h264->poc_type = 2; + h264->log2_max_poc_lsb = 12; + h264->log2_max_frame_num = 12; + h264->hw_cfg.hw_poc_type = 2; + h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12; + h264->hw_cfg.hw_split_out = 0; + } break; + case VPU_CLIENT_RKVENC : { + h264->poc_type = 0; + h264->log2_max_poc_lsb = 12; + h264->log2_max_frame_num = 12; + h264->chroma_cb_qp_offset = -6; + h264->chroma_cr_qp_offset = -6; + h264->hw_cfg.hw_poc_type = 0; + h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12; + h264->hw_cfg.hw_split_out = 0; + } break; + default : { + h264->poc_type = 0; + h264->log2_max_poc_lsb = 12; + h264->log2_max_frame_num = 12; + h264->hw_cfg.hw_poc_type = 0; + h264->hw_cfg.hw_log2_max_frame_num_minus4 = 12; + h264->hw_cfg.hw_split_out = 0; + } break; + } + + /* + * default prep: + * 720p + * YUV420SP + */ + prep->width = 1280; + prep->height = 720; + prep->hor_stride = 1280; + prep->ver_stride = 720; + prep->format = MPP_FMT_YUV420SP; + prep->rotation = MPP_ENC_ROT_0; + prep->rotation_ext = MPP_ENC_ROT_0; + prep->color = MPP_FRAME_SPC_UNSPECIFIED; + prep->colorprim = MPP_FRAME_PRI_UNSPECIFIED; + prep->colortrc = MPP_FRAME_TRC_UNSPECIFIED; + prep->range = MPP_FRAME_RANGE_UNSPECIFIED; + prep->mirroring = 0; + prep->mirroring_ext = 0; + prep->denoise = 0; + prep->flip = 0; + + /* + * default rc_cfg: + * CBR + * 2Mbps +-25% + * 30fps + * gop 60 + */ + rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM; + rc_cfg->bps_target = 2000 * 1000; + rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4; + rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4; + rc_cfg->fps_in_flex = 0; + rc_cfg->fps_in_num = 30; + rc_cfg->fps_in_denom = 1; + rc_cfg->fps_out_flex = 0; + rc_cfg->fps_out_num = 30; + rc_cfg->fps_out_denom = 1; + rc_cfg->gop = 60; + rc_cfg->max_reenc_times = 1; + rc_cfg->max_i_prop = 30; + rc_cfg->min_i_prop = 10; + rc_cfg->init_ip_ratio = 160; + rc_cfg->qp_init = 26; + rc_cfg->qp_max = 48; + rc_cfg->qp_min = 8; + /* default max/min intra qp is not set */ + rc_cfg->qp_max_i = 0; + rc_cfg->qp_min_i = 0; + rc_cfg->qp_delta_ip = 2; + rc_cfg->fqp_min_i = INT_MAX; + rc_cfg->fqp_min_p = INT_MAX; + rc_cfg->fqp_max_i = INT_MAX; + rc_cfg->fqp_max_p = INT_MAX; + + cfg->tune.lambda_idx_i = 6; + cfg->tune.lambda_idx_p = 6; + cfg->tune.atl_str = 1; + cfg->tune.atr_str_i = 1; + cfg->tune.atr_str_p = 1; + cfg->tune.anti_flicker_str = 1; + cfg->tune.deblur_str = 3; + + /* smart v3 parameters */ + cfg->tune.bg_delta_qp_i = -10; + cfg->tune.bg_delta_qp_p = -10; + cfg->tune.fg_delta_qp_i = 3; + cfg->tune.fg_delta_qp_p = 1; + cfg->tune.bmap_qpmin_i = 30; + cfg->tune.bmap_qpmin_p = 30; + cfg->tune.bmap_qpmax_i = 45; + cfg->tune.bmap_qpmax_p = 47; + cfg->tune.min_bg_fqp = 30; + cfg->tune.max_bg_fqp = 45; + cfg->tune.min_fg_fqp = 25; + cfg->tune.max_fg_fqp = 35; +} + +static void h264e_add_syntax(H264eCtx *ctx, H264eSyntaxType type, void *p) +{ + ctx->syntax[ctx->syn_num].type = type; + ctx->syntax[ctx->syn_num].p = p; + ctx->syn_num++; +} + +static MPP_RET h264e_init(void *ctx, EncImplCfg *ctrl_cfg) +{ + MPP_RET ret = MPP_OK; + H264eCtx *p = (H264eCtx *)ctx; + + mpp_env_get_u32("h264e_debug", &h264e_debug, 0); + + h264e_dbg_func("enter\n"); + + p->type = ctrl_cfg->type; + p->hdr_size = SZ_1K; + p->hdr_buf = mpp_malloc_size(void, p->hdr_size); + mpp_assert(p->hdr_buf); + mpp_packet_init(&p->hdr_pkt, p->hdr_buf, p->hdr_size); + mpp_assert(p->hdr_pkt); + + p->cfg = ctrl_cfg->cfg; + p->refs = ctrl_cfg->refs; + p->idr_request = 0; + + h264e_reorder_init(&p->reorder); + h264e_marking_init(&p->marking); + + h264e_dpb_init(&p->dpb, &p->reorder, &p->marking); + h264e_slice_init(&p->slice, &p->reorder, &p->marking); + + init_h264e_cfg_set(p->cfg, p->type); + + mpp_env_get_u32("h264e_debug", &h264e_debug, 0); + + h264e_dbg_func("leave\n"); + return ret; +} + +static MPP_RET h264e_deinit(void *ctx) +{ + H264eCtx *p = (H264eCtx *)ctx; + + h264e_dbg_func("enter\n"); + + if (p->hdr_pkt) + mpp_packet_deinit(&p->hdr_pkt); + + MPP_FREE(p->hdr_buf); + + h264e_dbg_func("leave\n"); + return MPP_OK; +} + +static void h264e_check_cfg(MppEncCfgSet *cfg) +{ + MppEncRcCfg *rc = &cfg->rc; + MppEncH264Cfg *h264 = &cfg->h264; + + if (rc->drop_mode == MPP_ENC_RC_DROP_FRM_PSKIP && + rc->drop_gap == 0 && + h264->poc_type == 2) { + mpp_err("poc type 2 is conflict with successive non-reference pskip mode\n"); + mpp_err("set drop gap to 1\n"); + rc->drop_gap = 1; + } +} + +static MPP_RET h264e_proc_cfg(void *ctx, MpiCmd cmd, void *param) +{ + MPP_RET ret = MPP_OK; + H264eCtx *p = (H264eCtx *)ctx; + MppEncCfgSet *cfg = p->cfg; + + h264e_dbg_func("enter ctx %p cmd %x param %p\n", ctx, cmd, param); + + switch (cmd) { + case MPP_ENC_SET_CFG : { + h264e_check_cfg(cfg); + } break; + case MPP_ENC_SET_SEI_CFG : { + } break; + case MPP_ENC_SET_SPLIT : { + } break; + default: + mpp_err("No correspond cmd found, and can not config!"); + ret = MPP_NOK; + break; + } + + h264e_dbg_func("leave ret %d\n", ret); + + return ret; +} + +static MPP_RET h264e_gen_hdr(void *ctx, MppPacket pkt) +{ + H264eCtx *p = (H264eCtx *)ctx; + + h264e_dbg_func("enter\n"); + + h264e_sps_update(&p->sps, p->cfg); + h264e_pps_update(&p->pps, p->cfg); + + /* + * NOTE: When sps/pps is update we need to update dpb and slice info + */ + if (!p->dpb.total_cnt) + h264e_dpb_setup(&p->dpb, p->cfg, &p->sps); + + mpp_packet_reset(p->hdr_pkt); + + h264e_sps_to_packet(&p->sps, p->hdr_pkt, &p->sps_offset, &p->sps_len, p->cfg); + h264e_pps_to_packet(&p->pps, p->hdr_pkt, &p->pps_offset, &p->pps_len); + p->hdr_len = mpp_packet_get_length(p->hdr_pkt); + + if (pkt) { + mpp_packet_write(pkt, 0, p->hdr_buf, p->hdr_len); + mpp_packet_set_length(pkt, p->hdr_len); + + mpp_packet_add_segment_info(pkt, H264_NALU_TYPE_SPS, + p->sps_offset, p->sps_len); + mpp_packet_add_segment_info(pkt, H264_NALU_TYPE_PPS, + p->pps_offset, p->pps_len); + } + + h264e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET h264e_start(void *ctx, HalEncTask *task) +{ + h264e_dbg_func("enter\n"); + + if (mpp_frame_has_meta(task->frame)) { + MppEncRefFrmUsrCfg *frm_cfg = task->frm_cfg; + EncRcForceCfg *rc_force = &task->rc_task->force; + MppMeta meta = mpp_frame_get_meta(task->frame); + RK_S32 force_lt_idx = -1; + RK_S32 force_use_lt_idx = -1; + RK_S32 force_frame_qp = -1; + RK_S32 base_layer_pid = -1; + RK_S32 force_tid = -1; + + mpp_meta_get_s32(meta, KEY_ENC_MARK_LTR, &force_lt_idx); + mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &force_use_lt_idx); + mpp_meta_get_s32(meta, KEY_ENC_FRAME_QP, &force_frame_qp); + mpp_meta_get_s32(meta, KEY_ENC_BASE_LAYER_PID, &base_layer_pid); + mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &force_tid); + + if (force_lt_idx >= 0) { + frm_cfg->force_flag |= ENC_FORCE_LT_REF_IDX; + frm_cfg->force_lt_idx = force_lt_idx; + } + + if (force_use_lt_idx >= 0) { + frm_cfg->force_flag |= ENC_FORCE_REF_MODE; + frm_cfg->force_ref_mode = REF_TO_LT_REF_IDX; + frm_cfg->force_ref_arg = force_use_lt_idx; + } + + if (force_tid >= 0) { + frm_cfg->force_flag |= ENC_FORCE_TEMPORAL_ID; + frm_cfg->force_temporal_id = force_tid; + } + + if (force_frame_qp >= 0) { + rc_force->force_flag = ENC_RC_FORCE_QP; + rc_force->force_qp = force_frame_qp; + } else { + rc_force->force_flag &= (~ENC_RC_FORCE_QP); + rc_force->force_qp = -1; + } + + if (base_layer_pid >= 0) { + H264eCtx *p = (H264eCtx *)ctx; + MppEncH264Cfg *h264 = &p->cfg->h264; + + h264->base_layer_pid = base_layer_pid; + } + } + + h264e_dbg_func("leave\n"); + + return MPP_OK; +} + +MPP_RET h264e_pskip_ref_check(H264eDpb *dpb, H264eFrmInfo *frms) +{ + H264eDpbFrm *curr = NULL; + H264eDpbFrm *refr = NULL; + RK_U32 i; + MPP_RET ret = MPP_OK; + + curr = dpb->curr; + refr = dpb->refr; + + if (curr->status.force_pskip_is_ref) { + H264eDpbFrm *temp_frm; + for (i = 0; i < H264E_MAX_REFS_CNT; i++) { + temp_frm = &dpb->frames[i]; + if (temp_frm->slot_idx != frms->refr_idx) { + temp_frm->as_pskip_ref = 0; + } else { + temp_frm->as_pskip_ref = 1; + } + } + } + + if (!refr->status.force_pskip_is_ref && !curr->status.force_pskip_is_ref) { + H264eDpbFrm *temp_frm; + for (i = 0; i < H264E_MAX_REFS_CNT; i++) { + temp_frm = &dpb->frames[i]; + if (temp_frm) { + temp_frm->as_pskip_ref = 0; + } + } + } + + return ret; +} + +static MPP_RET h264e_proc_dpb(void *ctx, HalEncTask *task) +{ + H264eCtx *p = (H264eCtx *)ctx; + H264eDpb *dpb = &p->dpb; + H264eFrmInfo *frms = &p->frms; + EncCpbStatus *cpb = &task->rc_task->cpb; + EncFrmStatus *frm = &task->rc_task->frm; + H264eDpbFrm *curr = NULL; + H264eDpbFrm *refr = NULL; + RK_S32 i; + + h264e_dbg_func("enter\n"); + + // update dpb + h264e_dpb_proc(dpb, cpb); + + curr = dpb->curr; + refr = dpb->refr; + + // update slice info + h264e_slice_update(&p->slice, p->cfg, &p->sps, &p->pps, dpb->curr); + + // update frame usage + frms->seq_idx = curr->seq_idx; + frms->curr_idx = curr->slot_idx; + + if (refr) { + if (refr->status.force_pskip_is_ref) + frms->refr_idx = refr->prev_ref_idx; + else + frms->refr_idx = refr->slot_idx; + } else { + frms->refr_idx = curr->slot_idx; + } + + // mark actual refs buf when force pskip is ref + h264e_pskip_ref_check(dpb, frms); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(frms->usage); i++) + frms->usage[i] = dpb->frames[i].on_used; + + // update dpb to after encoding status + h264e_dpb_check(dpb, cpb); + + frm->val = curr->status.val; + + h264e_dbg_func("leave\n"); + + return MPP_OK; +} + +static MPP_RET h264e_proc_hal(void *ctx, HalEncTask *task) +{ + H264eCtx *p = (H264eCtx *)ctx; + MppEncH264Cfg *h264 = &p->cfg->h264; + + h264e_dbg_func("enter\n"); + + p->syn_num = 0; + h264e_add_syntax(p, H264E_SYN_CFG, p->cfg); + h264e_add_syntax(p, H264E_SYN_SPS, &p->sps); + h264e_add_syntax(p, H264E_SYN_PPS, &p->pps); + h264e_add_syntax(p, H264E_SYN_DPB, &p->dpb); + h264e_add_syntax(p, H264E_SYN_SLICE, &p->slice); + h264e_add_syntax(p, H264E_SYN_FRAME, &p->frms); + + /* check max temporal layer id */ + { + MppEncCpbInfo *cpb_info = mpp_enc_ref_cfg_get_cpb_info(p->cfg->ref_cfg); + RK_S32 cpb_max_tid = cpb_info->max_st_tid; + RK_S32 cfg_max_tid = h264->max_tid; + + if (cpb_max_tid != cfg_max_tid) { + mpp_log("max tid is update to match cpb %d -> %d\n", + cfg_max_tid, cpb_max_tid); + h264->max_tid = cpb_max_tid; + } + } + + /* NOTE: prefix nal is added after SEI packet and before hw_stream */ + if (h264->prefix_mode || h264->max_tid) { + H264ePrefixNal *prefix = &p->prefix; + H264eSlice *slice = &p->slice; + EncFrmStatus *frm = &task->rc_task->frm; + MppPacket packet = task->packet; + MppMeta meta = mpp_packet_get_meta(packet); + + prefix->idr_flag = slice->idr_flag; + prefix->nal_ref_idc = slice->nal_reference_idc; + prefix->priority_id = h264->base_layer_pid + frm->temporal_id; + prefix->no_inter_layer_pred_flag = 1; + prefix->dependency_id = 0; + prefix->quality_id = 0; + prefix->temporal_id = frm->temporal_id; + prefix->use_ref_base_pic_flag = 0; + prefix->discardable_flag = 0; + prefix->output_flag = 1; + + h264e_add_syntax(p, H264E_SYN_PREFIX, &p->prefix); + mpp_meta_set_s32(meta, KEY_TEMPORAL_ID, frm->temporal_id); + if (!frm->is_non_ref && frm->is_lt_ref) + mpp_meta_set_s32(meta, KEY_LONG_REF_IDX, frm->lt_idx); + } else + h264e_add_syntax(p, H264E_SYN_PREFIX, NULL); + + task->valid = 1; + task->syntax.data = &p->syntax[0]; + task->syntax.number = p->syn_num; + + h264e_dbg_func("leave\n"); + + return MPP_OK; +} + +static MPP_RET h264e_sw_enc(void *ctx, HalEncTask *task) +{ + H264eCtx *p = (H264eCtx *)ctx; + MppEncH264Cfg *h264 = &p->cfg->h264; + EncRcTaskInfo *rc_info = &task->rc_task->info; + MppPacket packet = task->packet; + void *pos = mpp_packet_get_pos(packet); + void *data = mpp_packet_get_data(packet); + size_t size = mpp_packet_get_size(packet); + size_t length = mpp_packet_get_length(packet); + void *base = pos + length; + RK_S32 buf_size = (data + size) - (pos + length); + RK_S32 slice_len = 0; + RK_S32 final_len = 0; + + if (h264->prefix_mode || h264->max_tid) { + /* add prefix first */ + RK_S32 prefix_bit = h264e_slice_write_prefix_nal_unit_svc(&p->prefix, base, buf_size); + + prefix_bit = (prefix_bit + 7) / 8; + + base += prefix_bit; + buf_size -= prefix_bit; + final_len += prefix_bit; + } + + /* write slice header */ + slice_len = h264e_slice_write_pskip(&p->slice, base, buf_size); + slice_len = (slice_len + 7) / 8; + final_len += slice_len; + + task->length += final_len; + + rc_info->bit_real = task->length * 8; + rc_info->quality_real = rc_info->quality_target; + p->dpb.curr->prev_ref_idx = p->frms.refr_idx; + mpp_packet_add_segment_info(packet, H264_NALU_TYPE_SLICE, length, final_len); + mpp_buffer_sync_partial_end(mpp_packet_get_buffer(packet), length, final_len); + + return MPP_OK; +} + +MPP_RET h264e_add_sei(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16], + const void *data, RK_S32 size) +{ + if (uuid == uuid_refresh_cfg) { + return h264e_sei_recovery_point_to_packet(pkt, length, ((RK_U32 *)data)[0] - 1); + } else + return h264e_sei_to_packet(pkt, length, H264_SEI_USER_DATA_UNREGISTERED, + uuid, data, size); +} + +/*! +*********************************************************************** +* \brief +* api struct interface +*********************************************************************** +*/ +const EncImplApi api_h264e = { + "h264e_control", + MPP_VIDEO_CodingAVC, + sizeof(H264eCtx), + 0, + h264e_init, + h264e_deinit, + h264e_proc_cfg, + h264e_gen_hdr, + h264e_start, + h264e_proc_dpb, + h264e_proc_hal, + h264e_add_sei, + h264e_sw_enc, +}; diff --git a/mpp/codec/enc/h264/h264e_debug.h b/mpp/codec/enc/h264/h264e_debug.h new file mode 100644 index 000000000..4eec0df38 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_debug.h @@ -0,0 +1,55 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_DEBUG_H +#define H264E_DEBUG_H + +#include "mpp_debug.h" + +#define H264E_DBG_FUNCTION (0x00000001) +#define H264E_DBG_FLOW (0x00000002) +#define H264E_DBG_CTRL (0x00000004) +#define H264E_DBG_DETAIL (0x00000008) + +#define H264E_DBG_SPS (0x00000010) +#define H264E_DBG_PPS (0x00000020) +#define H264E_DBG_SLICE (0x00000040) +#define H264E_DBG_SEI (0x00000080) + +#define H264E_DBG_DPB (0x00000100) +#define H264E_DBG_LIST (0x00000200) +#define H264E_DBG_MMCO (0x00000400) + +#define h264e_dbg(flag, fmt, ...) mpp_dbg(h264e_debug, flag, fmt, ## __VA_ARGS__) +#define h264e_dbg_f(flag, fmt, ...) mpp_dbg_f(h264e_debug, flag, fmt, ## __VA_ARGS__) + +#define h264e_dbg_func(fmt, ...) h264e_dbg_f(H264E_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define h264e_dbg_flow(fmt, ...) h264e_dbg_f(H264E_DBG_FLOW, fmt, ## __VA_ARGS__) +#define h264e_dbg_ctrl(fmt, ...) h264e_dbg_f(H264E_DBG_CTRL, fmt, ## __VA_ARGS__) +#define h264e_dbg_detail(fmt, ...) h264e_dbg_f(H264E_DBG_DETAIL, fmt, ## __VA_ARGS__) + +#define h264e_dbg_sps(fmt, ...) h264e_dbg_f(H264E_DBG_SPS, fmt, ## __VA_ARGS__) +#define h264e_dbg_pps(fmt, ...) h264e_dbg_f(H264E_DBG_PPS, fmt, ## __VA_ARGS__) +#define h264e_dbg_slice(fmt, ...) h264e_dbg_f(H264E_DBG_SLICE, fmt, ## __VA_ARGS__) +#define h264e_dbg_sei(fmt, ...) h264e_dbg_f(H264E_DBG_SEI, fmt, ## __VA_ARGS__) + +#define h264e_dbg_dpb(fmt, ...) h264e_dbg_f(H264E_DBG_DPB, fmt, ## __VA_ARGS__) +#define h264e_dbg_list(fmt, ...) h264e_dbg_f(H264E_DBG_LIST, fmt, ## __VA_ARGS__) +#define h264e_dbg_mmco(fmt, ...) h264e_dbg_f(H264E_DBG_MMCO, fmt, ## __VA_ARGS__) + +extern RK_U32 h264e_debug; + +#endif /* H264E_DEBUG_H */ diff --git a/mpp/codec/enc/h264/h264e_dpb.c b/mpp/codec/enc/h264/h264e_dpb.c new file mode 100644 index 000000000..59c67b7c0 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_dpb.c @@ -0,0 +1,751 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_dpb" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "h264e_debug.h" +#include "h264e_dpb.h" +#include "h264e_slice.h" + +void h264e_dpb_dump_usage(H264eDpb *dpb, const char *fmt) +{ + RK_S32 i = 0; + char buf[256]; + RK_S32 pos = 0; + + pos += snprintf(buf, sizeof(buf) - 1, "total %2d ", dpb->total_cnt); + + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *frm = &dpb->frames[i]; + + pos += snprintf(buf + pos, sizeof(buf) - 1 - pos, "%04x ", frm->on_used); + } + mpp_log("%s %s", fmt, buf); +} + +void h264e_dpb_dump_frm(H264eDpb *dpb, const char *caller, RK_S32 line) +{ + RK_S32 i = 0; + + mpp_log_f("dump dpb frame info in %s line %d\n", caller, line); + + mpp_log_f("dpb %p total count %d size %d\n", dpb, dpb->total_cnt, dpb->dpb_size); + mpp_log_f("dpb %5s %5s %5s %5s %5s %5s %5s %5s %5s\n", + "slot", "use", "seq", "type", "tid", "ref", "idx", "mode", "arg"); + + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *frm = &dpb->frames[i]; + EncFrmStatus *status = &frm->status; + + mpp_log_f("frm %5d %5d %5d %5s %5d %5s %5d %5x %5d\n", + i, frm->on_used, status->seq_idx, + (status->is_intra != 0) ? ((status->is_idr != 0) ? "I" : "i" ) : + (status->is_non_ref != 0) ? "p" : "P", + status->temporal_id, + (status->is_non_ref != 0) ? "non" : (status->is_lt_ref != 0) ? "lt" : "st", + status->lt_idx, + status->ref_mode, + status->ref_arg); + } +} + +void h264e_dpb_dump_listX(H264eDpbFrm **list, RK_S32 count) +{ + RK_S32 i; + + for (i = 0; i < count; i++) { + H264eDpbFrm *frm = list[i]; + EncFrmStatus *status = &frm->status; + + mpp_log_f("frm %2d %d %-3d %s %-3d %-3s %-3d %-4x %-3d\n", + i, frm->on_used, status->seq_idx, + (status->is_intra != 0) ? ((status->is_idr != 0) ? "I" : "i" ) : + (status->is_non_ref != 0) ? "p" : "P", + status->temporal_id, + (status->is_non_ref != 0) ? "non" : (status->is_lt_ref != 0) ? "lt" : "st", + status->lt_idx, + status->ref_mode, + status->ref_arg); + } +} + +void h264e_dpb_dump_list(H264eDpb *dpb) +{ + mpp_log_f("dump dpb list info\n"); + + mpp_log_f("dpb size %d used %d st %d lt %d\n", + dpb->dpb_size, dpb->used_size, dpb->st_size, dpb->lt_size); + + if (dpb->st_size + dpb->lt_size) { + mpp_log_f("list slot use seq type tid ref idx mode arg\n", dpb, dpb->total_cnt); + + h264e_dpb_dump_listX(dpb->list, dpb->st_size + dpb->lt_size); + } +} + +MPP_RET h264e_dpb_init(H264eDpb *dpb, H264eReorderInfo *reorder, H264eMarkingInfo *marking) +{ + RK_S32 i; + + h264e_dbg_dpb("enter %p\n", dpb); + + memset(dpb, 0, sizeof(*dpb)); + + dpb->reorder = reorder; + dpb->marking = marking; + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dpb->frames); i++) + dpb->frames[i].slot_idx = i; + + h264e_dbg_dpb("leave %p\n", dpb); + + return MPP_OK; +} + +MPP_RET h264e_dpb_setup(H264eDpb *dpb, MppEncCfgSet* cfg, H264eSps *sps) +{ + MPP_RET ret = MPP_OK; + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(cfg->ref_cfg); + + h264e_dbg_dpb("enter %p\n", dpb); + + RK_S32 ref_frm_num = sps->num_ref_frames; + RK_S32 log2_max_frm_num = sps->log2_max_frame_num_minus4 + 4; + RK_S32 log2_max_poc_lsb = sps->log2_max_poc_lsb_minus4 + 4; + + /* NOTE: new configure needs to clear dpb first */ + h264e_dpb_init(dpb, dpb->reorder, dpb->marking); + + memcpy(&dpb->info, info, sizeof(dpb->info)); + dpb->dpb_size = info->dpb_size; + dpb->total_cnt = info->dpb_size + 1; + dpb->max_frm_num = 1 << log2_max_frm_num; + dpb->max_poc_lsb = (1 << log2_max_poc_lsb); + dpb->poc_type = sps->pic_order_cnt_type; + + if (cfg->hw.extra_buf) + dpb->total_cnt++; + + h264e_dbg_dpb("max ref frm num %d total slot %d\n", + ref_frm_num, dpb->total_cnt); + h264e_dbg_dpb("log2 max frm num %d -> %d\n", + log2_max_frm_num, dpb->max_frm_num); + h264e_dbg_dpb("log2 max poc lsb %d -> %d\n", + log2_max_poc_lsb, dpb->max_poc_lsb); + + h264e_dbg_dpb("leave %p\n", dpb); + + return ret; +} + +H264eDpbFrm *find_cpb_frame(H264eDpb *dpb, EncFrmStatus *frm) +{ + H264eDpbFrm *frms = dpb->frames; + RK_S32 seq_idx = frm->seq_idx; + RK_S32 cnt = dpb->total_cnt; + RK_S32 i; + + if (!frm->valid) + return NULL; + + h264e_dbg_dpb("frm %d start finding slot\n", frm->seq_idx); + + for (i = 0; i < cnt; i++) { + EncFrmStatus *p = &frms[i].status; + + if (p->valid && p->seq_idx == seq_idx) { + h264e_dbg_dpb("frm %d match slot %d valid %d\n", + p->seq_idx, i, p->valid); + + mpp_assert(p->is_non_ref == frm->is_non_ref); + mpp_assert(p->is_lt_ref == frm->is_lt_ref); + mpp_assert(p->lt_idx == frm->lt_idx); + mpp_assert(p->temporal_id == frm->temporal_id); + return &frms[i]; + } + } + + mpp_err_f("can not find match frm %d\n", seq_idx); + h264e_dpb_dump_frms(dpb); + abort(); + + return NULL; +} + + +static int cmp_st_list(const void *p0, const void *p1) +{ + H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0; + H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1; + + if (frm0->frame_num == frm1->frame_num) + return 0; + if (frm0->frame_num < frm1->frame_num) + return 1; + else + return -1; +} + +static int cmp_lt_list(const void *p0, const void *p1) +{ + H264eDpbFrm *frm0 = *(H264eDpbFrm **)p0; + H264eDpbFrm *frm1 = *(H264eDpbFrm **)p1; + + if (frm0->lt_idx == frm1->lt_idx) + return 0; + if (frm0->lt_idx > frm1->lt_idx) + return 1; + else + return -1; +} + +/* + * Build list function + * + * This function should build the default list for current frame. + * Then check the reference frame is the default one or not. + * Reorder command is need if the reference frame is not match. + */ +void h264e_dpb_build_list(H264eDpb *dpb, EncCpbStatus *cpb) +{ + RK_S32 i, j; + RK_S32 st_size = 0; + RK_S32 lt_size = 0; + + h264e_dbg_dpb("enter %p\n", dpb); + + /* clear list */ + memset(dpb->list, 0, sizeof(dpb->list)); + + if (cpb->curr.is_intra) { + h264e_dbg_dpb("leave %p\n", dpb); + return ; + } + + // 2.1 init list + // 2.1.1 found all short term and long term ref + h264e_dbg_list("cpb init scaning start\n"); + + for (i = 0; i < MAX_CPB_REFS; i++) { + EncFrmStatus *frm = &cpb->init[i]; + + if (!frm->valid) + continue; + + mpp_assert(!frm->is_non_ref); + + h264e_dbg_list("idx %d frm %d valid %d is_non_ref %d lt_ref %d\n", + i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref); + + H264eDpbFrm *p = find_cpb_frame(dpb, frm); + if (!frm->is_lt_ref) { + dpb->stref[st_size++] = p; + p->status.val = frm->val; + h264e_dbg_list("found st %d st_size %d %p\n", i, st_size, frm); + } else { + dpb->ltref[lt_size++] = p; + p->status.val = frm->val; + h264e_dbg_list("found lt %d lt_size %d %p\n", i, lt_size, frm); + } + } + + h264e_dbg_list("cpb init scaning done\n"); + h264e_dbg_dpb("dpb_size %d st_size %d lt_size %d\n", dpb->dpb_size, st_size, lt_size); + + // sort st list + if (st_size > 1) { + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb st list before sort\n"); + h264e_dpb_dump_listX(dpb->stref, st_size); + } + + qsort(dpb->stref, st_size, sizeof(dpb->stref[0]), cmp_st_list); + + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb st list after sort\n"); + h264e_dpb_dump_listX(dpb->stref, st_size); + } + } + + if (lt_size > 1) { + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb lt list before sort\n"); + h264e_dpb_dump_listX(dpb->ltref, lt_size); + } + + qsort(dpb->ltref, lt_size, sizeof(dpb->ltref[0]), cmp_lt_list); + + if (h264e_debug & H264E_DBG_LIST) { + mpp_log_f("dpb lt list after sort\n"); + h264e_dpb_dump_listX(dpb->ltref, lt_size); + } + } + + // generate list before reorder + memset(dpb->list, 0, sizeof(dpb->list)); + j = 0; + for (i = 0; i < st_size; i++) + dpb->list[j++] = dpb->stref[i]; + + for (i = 0; i < lt_size; i++) + dpb->list[j++] = dpb->ltref[i]; + + dpb->st_size = st_size; + dpb->lt_size = lt_size; + + mpp_assert(dpb->dpb_size >= st_size + lt_size); + + if (h264e_debug & H264E_DBG_LIST) + h264e_dpb_dump_list(dpb); + + /* generate syntax */ + h264e_reorder_wr_rewind(dpb->reorder); + + if (dpb->st_size + dpb->lt_size) { + H264eDpbFrm *curr = dpb->curr; + H264eDpbFrm *refr = dpb->refr; + H264eDpbFrm *def_ref = dpb->list[0]; + + RK_S32 curr_frm_cnt = curr->status.seq_idx; + RK_S32 set_ref_frm_cnt = refr->status.seq_idx; + RK_S32 def_ref_frm_cnt = def_ref->status.seq_idx; + + h264e_dbg_list("refer curr %d def %d set %d reorder %d\n", + curr_frm_cnt, def_ref_frm_cnt, set_ref_frm_cnt, + (def_ref_frm_cnt != set_ref_frm_cnt)); + + if (def_ref_frm_cnt != set_ref_frm_cnt) { + H264eRplmo op; + + h264e_dbg_list("reorder to frm %d\n", refr->status.seq_idx); + + mpp_assert(!refr->status.is_non_ref); + + op.modification_of_pic_nums_idc = (refr->status.is_lt_ref != 0) ? (2) : (0); + if (refr->status.is_lt_ref) { + op.modification_of_pic_nums_idc = 2; + op.long_term_pic_idx = refr->status.lt_idx; + + h264e_dbg_list("reorder lt idx %d \n", op.long_term_pic_idx); + } else { + op.modification_of_pic_nums_idc = curr->frame_num > refr->frame_num ? 0 : 1; + op.abs_diff_pic_num_minus1 = MPP_ABS(curr->frame_num - refr->frame_num) - 1; + + h264e_dbg_list("reorder st cur %d refr %d diff - 1 %d\n", + curr->frame_num, refr->frame_num, + op.abs_diff_pic_num_minus1); + } + + h264e_reorder_wr_op(dpb->reorder, &op); + } + } else { + h264e_dbg_list("refer NULL\n"); + } + + h264e_dbg_dpb("leave %p\n", dpb); +} + +void h264e_dpb_build_marking(H264eDpb *dpb) +{ + H264eDpbFrm *frm = dpb->curr; + H264eMarkingInfo *marking = dpb->marking; + + h264e_dbg_dpb("enter %p\n", dpb); + + h264e_marking_wr_rewind(marking); + + // refernce frame can not mark itself as unreferenced. + if (frm->status.is_idr) { + marking->idr_flag = 1; + marking->no_output_of_prior_pics = 0; + marking->long_term_reference_flag = frm->status.is_lt_ref; + goto DONE; + } + + marking->idr_flag = 0; + marking->long_term_reference_flag = 0; + marking->adaptive_ref_pic_buffering = 0; + + h264e_dbg_dpb("frm %d ref %d lt %d T%d\n", + frm->status.seq_idx, !frm->status.is_non_ref, + frm->status.is_lt_ref, frm->status.temporal_id); + + if (frm->status.is_non_ref) + goto DONE; + + // When current frame is lt_ref update max_lt_idx + if (frm->status.is_lt_ref) { + H264eMmco op; + + dpb->next_max_lt_idx = dpb->info.max_lt_idx; + + if (dpb->next_max_lt_idx != dpb->curr_max_lt_idx) { + RK_S32 max_lt_idx_p1 = dpb->next_max_lt_idx + 1; + + op.mmco = 4; + op.max_long_term_frame_idx_plus1 = max_lt_idx_p1; + + h264e_marking_wr_op(marking, &op); + h264e_dbg_mmco("add mmco 4 %d\n", max_lt_idx_p1); + + dpb->curr_max_lt_idx = dpb->next_max_lt_idx; + } + + op.mmco = 6; + op.long_term_frame_idx = frm->lt_idx; + + h264e_marking_wr_op(marking, &op); + h264e_dbg_mmco("add mmco 6 %d\n", frm->lt_idx); + } + + // TODO: check and mark used frame +DONE: + h264e_dbg_dpb("dpb size %d used %d\n", dpb->dpb_size, dpb->used_size); + h264e_dbg_dpb("leave %p\n", dpb); +} + +MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb) +{ + EncFrmStatus *curr = &cpb->curr; + EncFrmStatus *refr = &cpb->refr; + EncFrmStatus *init = cpb->init; + H264eDpbFrm *frames = dpb->frames; + H264eDpbRt *rt = &dpb->rt; + RK_S32 used_size = 0; + RK_S32 seq_idx = curr->seq_idx; + RK_S32 i; + + h264e_dbg_dpb("enter %p total %d\n", dpb, dpb->total_cnt); + + if (curr->is_idr) { + for (i = 0; i < H264E_MAX_REFS_CNT + 1; i++) { + frames[i].dpb_used = 0; + frames[i].status.valid = 0; + } + dpb->used_size = 0; + dpb->curr_max_lt_idx = 0; + dpb->next_max_lt_idx = 0; + } else { + if (curr->seq_idx == rt->last_seq_idx) { + h264e_dbg_dpb("NOTE: reenc found at %d\n", curr->seq_idx); + memcpy(rt, &dpb->rt_bak, sizeof(*rt)); + memcpy(frames, dpb->frm_bak, sizeof(dpb->frm_bak)); + } + } + + if (h264e_debug & H264E_DBG_DPB) + h264e_dpb_dump_frms(dpb); + /* + * 1. scan and map cpb to internal cpb h264edpb is bridge from + * user defined cpb to hal slot index + */ + for (i = 0; i < MAX_CPB_REFS; i++) { + H264eDpbFrm *frm = find_cpb_frame(dpb, &init[i]); + dpb->map[i] = frm; + if (frm) { + if (!frm->on_used && !frm->status.force_pskip_is_ref) + mpp_err_f("warning frm %d is used by cpb but on not used status\n", + frm->seq_idx); + frm->dpb_used = 1; + used_size++; + } + } + + mpp_assert(dpb->used_size == used_size); + h264e_dbg_dpb("frm %d init cpb used size %d vs %d\n", seq_idx, + used_size, dpb->used_size); + + /* backup current runtime status */ + memcpy(&dpb->rt_bak, rt, sizeof(dpb->rt_bak)); + memcpy(dpb->frm_bak, frames, sizeof(dpb->frm_bak)); + + /* mark current cpb */ + RK_S32 found_curr = 0; + + /* 2. scan all slot for used map and find a slot for current */ + dpb->curr = NULL; + + h264e_dbg_dpb("frm %d start finding slot for storage\n", seq_idx); + for (i = 0; i < H264E_MAX_REFS_CNT + 1; i++) { + H264eDpbFrm *p = &frames[i]; + RK_S32 curr_frm_num = rt->last_frm_num + rt->last_is_ref; + RK_S32 curr_poc_lsb = rt->last_poc_lsb; + RK_S32 curr_poc_msb = rt->last_poc_msb; + RK_S32 valid = 0; + RK_S32 j; + + for (j = 0; j < MAX_CPB_REFS; j++) { + if (p == dpb->map[j] || p->as_pskip_ref) { + valid = 1; + break; + } + } + + h264e_dbg_dpb("slot %2d check in cpb init valid %d used %04x\n", + i, valid, p->on_used); + + if (valid) { + if ((!p->as_pskip_ref) && + (!p->on_used || !p->status.valid)) { + mpp_assert(p->on_used); + mpp_assert(p->status.valid); + h264e_dpb_dump_frms(dpb); + } + continue; + } + + h264e_dbg_dpb("slot %2d used %04x checking\n", i, p->on_used); + + if (p->hal_used) + continue; + + if (found_curr) { + p->dpb_used = 0; + p->status.valid = 0; + continue; + } + + h264e_dbg_dpb("slot %2d used %04x mark as current\n", i, p->on_used); + + dpb->curr = p; + p->status.val = curr->val; + p->seq_idx = curr->seq_idx; + if (curr->is_idr) { + p->frame_num = 0; + p->poc = 0; + curr_frm_num = 0; + curr_poc_lsb = 0; + curr_poc_msb = 0; + } else { + if (curr_frm_num >= dpb->max_frm_num) + curr_frm_num = 0; + + p->frame_num = curr_frm_num; + + if (dpb->poc_type == 0) + curr_poc_lsb += 2; + else if (dpb->poc_type == 2) + curr_poc_lsb += 1 + rt->last_is_ref; + else + mpp_err_f("do not support poc type 1\n"); + + if (curr_poc_lsb >= dpb->max_poc_lsb) { + curr_poc_lsb = 0; + curr_poc_msb++; + } + + p->poc = curr_poc_lsb + curr_poc_msb * dpb->max_poc_lsb; + + } + p->lt_idx = curr->lt_idx; + p->dpb_used = 1; + + rt->last_seq_idx = curr->seq_idx; + rt->last_is_ref = !curr->is_non_ref; + rt->last_frm_num = curr_frm_num; + rt->last_poc_lsb = curr_poc_lsb; + rt->last_poc_msb = curr_poc_msb; + + found_curr = 1; + h264e_dbg_dpb("frm %d update slot %d with frame_num %d poc %d\n", + seq_idx, i, p->frame_num, p->poc); + } + + mpp_assert(dpb->curr); + + if (NULL == dpb->curr) + mpp_err_f("frm %d failed to find a slot for curr %d\n", seq_idx); + + h264e_dbg_dpb("frm %d start finding slot for refr %d\n", seq_idx, refr->seq_idx); + dpb->refr = find_cpb_frame(dpb, refr); + if (NULL == dpb->refr) + dpb->refr = dpb->curr; + + h264e_dbg_dpb("frm %d curr %d refr %d start building list\n", + seq_idx, dpb->curr->slot_idx, dpb->refr->slot_idx); + + h264e_dpb_build_list(dpb, cpb); + + if (h264e_debug & H264E_DBG_DPB) + h264e_dpb_dump_frms(dpb); + + h264e_dpb_build_marking(dpb); + + if (h264e_debug & H264E_DBG_DPB) + h264e_dpb_dump_frms(dpb); + + h264e_dbg_dpb("leave %p\n", dpb); + + return MPP_OK; +} + +void h264e_dpb_check(H264eDpb *dpb, EncCpbStatus *cpb) +{ + H264eDpbFrm *curr = dpb->curr; + H264eDpbFrm *refr = dpb->refr; + RK_S32 i; + + h264e_dbg_dpb("enter %p\n", dpb); + + h264e_dbg_dpb("frm %d refr -> frm %d ready\n", + curr->seq_idx, refr->seq_idx); + + if (curr->status.is_non_ref) { + curr->dpb_used = 0; + curr->status.valid = 0; + } else { + /* sliding window process */ + RK_S32 used_size = dpb->used_size; + RK_S32 dpb_size = dpb->dpb_size; + + h264e_dbg_dpb("frm %d %s insert dpb used %d max %d\n", + curr->seq_idx, (curr->status.is_lt_ref != 0) ? "lt" : "st", + used_size, dpb_size); + + used_size++; + + /* replace lt ref with same lt_idx */ + if (curr->status.is_lt_ref) { + RK_S32 lt_idx = curr->lt_idx; + + dpb->lt_size++; + + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + if (tmp == curr) + continue; + + if (!tmp->dpb_used) + continue; + + if (!tmp->status.valid) + continue; + + mpp_assert(!tmp->status.is_non_ref); + + if (!tmp->status.is_lt_ref) + continue; + + if (tmp->lt_idx == lt_idx) { + tmp->dpb_used = 0; + tmp->status.valid = 0; + h264e_dbg_dpb("frm %d lt_idx %d replace %d\n", + curr->seq_idx, curr->lt_idx, tmp->slot_idx); + dpb->lt_size--; + used_size--; + } + } + } else { + dpb->st_size++; + } + + if (used_size > dpb_size) { + mpp_assert(dpb->lt_size <= dpb_size); + + while (used_size > dpb_size) { + RK_S32 small_poc = 0x7fffffff; + H264eDpbFrm *unref = NULL; + + h264e_dbg_dpb("sliding window cpb proc: st %d lt %d max %d\n", + dpb->st_size, dpb->lt_size, dpb_size); + + for (i = 0; i < dpb->total_cnt; i++) { + H264eDpbFrm *tmp = &dpb->frames[i]; + + h264e_dbg_dpb("frm %d num %d poc %d\n", + tmp->seq_idx, tmp->frame_num, tmp->poc); + + if (tmp->as_pskip_ref) + continue; + + if (!tmp->on_used) + continue; + + if (!tmp->status.valid) + continue; + + mpp_assert(!tmp->status.is_non_ref); + + if (tmp->status.is_lt_ref) + continue; + + if (tmp->poc < small_poc) { + unref = tmp; + small_poc = tmp->poc; + + h264e_dbg_dpb("frm %d update smallest poc to %d\n", + tmp->seq_idx, tmp->poc); + } + } + + if (unref) { + h264e_dbg_dpb("removing frm %d poc %d\n", + unref->seq_idx, unref->poc); + + unref->dpb_used = 0; + dpb->st_size--; + mpp_assert(dpb->st_size >= 0); + used_size--; + } else + break; + } + } + + dpb->used_size = used_size; + if (used_size > dpb_size) { + mpp_err_f("error found used_size %d > dpb_size %d\n", used_size, dpb_size); + mpp_assert(used_size <= dpb_size); + } + } + + h264e_dbg_dpb("curr %d done used_size %d\n", curr->seq_idx, dpb->used_size); + + RK_S32 used_size = 0; + for (i = 0; i < MAX_CPB_REFS; i++) { + dpb->map[i] = find_cpb_frame(dpb, &cpb->final[i]); + if (dpb->map[i]) + used_size++; + } + + h264e_dbg_dpb("curr %d cpb final used_size %d vs %d\n", + curr->seq_idx, used_size, dpb->used_size); + mpp_assert(dpb->used_size == used_size); + + h264e_dbg_dpb("leave %p\n", dpb); +} + +MPP_RET h264e_dpb_hal_start(H264eDpb *dpb, RK_S32 slot_idx) +{ + H264eDpbFrm *frm = &dpb->frames[slot_idx]; + + frm->hal_used++; + //h264e_dpb_dump_usage(dpb, __FUNCTION__); + return MPP_OK; +} + +MPP_RET h264e_dpb_hal_end(H264eDpb *dpb, RK_S32 slot_idx) +{ + H264eDpbFrm *frm = &dpb->frames[slot_idx]; + + frm->hal_used--; + //h264e_dpb_dump_usage(dpb, __FUNCTION__); + return MPP_OK; +} diff --git a/mpp/codec/enc/h264/h264e_dpb.h b/mpp/codec/enc/h264/h264e_dpb.h new file mode 100644 index 000000000..b41d299f8 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_dpb.h @@ -0,0 +1,171 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_DPB_H +#define H264E_DPB_H + +#include "h264e_syntax.h" +#include "h264e_sps.h" +#include "h264e_slice.h" +#include "mpp_enc_ref.h" + +/* + * H.264 encoder dpb structure info + * + * +----------+ DPB +-> build list +-> REF_LIST + * | + + + * v v v + * FRM_BUF_GRP DPB_FRM +------+------> get_reorder + * + + | + * | v | + * +--------> FRM_BUF +------> get_mmco + * + * H264eDpb is overall structure contain the whole dpb info. + * It is composed H264eDpbFrm and H264eDpbList. + * + */ + +#define MAX_GOP_SIZE 8 +#define MAX_GOP_FMT_CNT (MAX_GOP_SIZE+1) +#define MAX_GOP_FMT_SIZE 5 +#define MAX_GOP_FMT_BUF_STUFF 16 +#define MAX_GOP_FMT_BUF_SIZE (MAX_GOP_FMT_CNT * MAX_GOP_FMT_SIZE + MAX_GOP_FMT_BUF_STUFF) + +#define H264E_ST_GOP_FLAG (0x00000001) +#define H264E_ST_GOP_WITH_LT_REF (0x00000002) +#define H264E_LT_GOP_FLAG (0x00000010) + +#define REF_BY_RECN(idx) (0x00000001 << idx) +#define REF_BY_REFR(idx) (0x00000001 << idx) + +typedef struct H264eDpbFrm_t { + RK_S32 slot_idx; + // frame index in frames + RK_S32 seq_idx; + + union { + RK_U32 on_used; + struct { + RK_U32 dpb_used : 8; + RK_U32 hal_used : 8; + }; + }; + + /* frame status */ + EncFrmStatus status; + RK_S32 prev_ref_idx; + RK_S32 as_pskip_ref; + + /* frame number from H264eSlice */ + RK_S32 frame_num; + RK_S32 lt_idx; + /* poc from H264eSlice */ + RK_S32 poc; + /* pts from input MppFrame */ + RK_S64 pts; +} H264eDpbFrm; + +/* runtime status record */ +typedef struct H264eDpbRt_t { + RK_S32 last_seq_idx; + RK_S32 last_is_ref; + RK_S32 last_frm_num; + RK_S32 last_poc_lsb; + RK_S32 last_poc_msb; +} H264eDpbRt; + +/* + * dpb frame arrangement + * + * If dpb size is 3 then dpb frame will be total 4 frames. + * Then the frame 3 is always current frame and frame 0~2 is reference frame + * in the gop structure. + * + * When one frame is encoded all it info will be moved to its gop position for + * next frame encoding. + */ +typedef struct H264eDpb_t { + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + + MppEncCpbInfo info; + RK_S32 next_max_lt_idx; + RK_S32 curr_max_lt_idx; + RK_S32 st_size; + RK_S32 lt_size; + RK_S32 used_size; + + RK_S32 dpb_size; + RK_S32 total_cnt; + + /* status on dpb rebuild is needed */ + RK_S32 max_frm_num; + RK_S32 max_poc_lsb; + RK_S32 poc_type; + + RK_S32 last_frm_num; + RK_S32 last_poc_lsb; + RK_S32 last_poc_msb; + + H264eDpbFrm *curr; + H264eDpbFrm *refr; + H264eDpbFrm *list[H264E_MAX_REFS_CNT]; + H264eDpbFrm *stref[H264E_MAX_REFS_CNT]; + H264eDpbFrm *ltref[H264E_MAX_REFS_CNT]; + H264eDpbFrm *map[H264E_MAX_REFS_CNT + 1]; + + // frame storage + H264eDpbRt rt; + H264eDpbRt rt_bak; + H264eDpbFrm frames[H264E_MAX_REFS_CNT + 1]; + H264eDpbFrm frm_bak[H264E_MAX_REFS_CNT + 1]; +} H264eDpb; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h264e_dpb_init(H264eDpb *dpb, H264eReorderInfo *reorder, H264eMarkingInfo *marking); +MPP_RET h264e_dpb_deinit(H264eDpb *dpb); + +MPP_RET h264e_dpb_setup(H264eDpb *dpb, MppEncCfgSet* cfg, H264eSps *sps); + +/* + * Setup current frame config using flags + * This config function will be called before each frame is encoded: + * + * idr - current frame is force to IDR or not + * lt_ref - current frame is marked as longterm reference + */ +MPP_RET h264e_dpb_proc(H264eDpb *dpb, EncCpbStatus *cpb); + +/* + * hal usage flag mark / unmark function + */ +MPP_RET h264e_dpb_hal_start(H264eDpb *dpb, RK_S32 slot_idx); +MPP_RET h264e_dpb_hal_end(H264eDpb *dpb, RK_S32 slot_idx); + +void h264e_dpb_check(H264eDpb *dpb, EncCpbStatus *cpb); + +#define h264e_dpb_dump_frms(dpb) h264e_dpb_dump_frm(dpb, __FUNCTION__, __LINE__) + +void h264e_dpb_dump_frm(H264eDpb *dpb, const char *caller, RK_S32 line); + +#ifdef __cplusplus +} +#endif + +#endif /* H264E_DPB_H */ diff --git a/mpp/codec/enc/h264/h264e_pps.c b/mpp/codec/enc/h264/h264e_pps.c new file mode 100644 index 000000000..63d533149 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_pps.c @@ -0,0 +1,238 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_sps" + +#include "mpp_common.h" + +#include "mpp_bitwrite.h" +#include "h264e_debug.h" +#include "h264e_pps.h" + +static const uint8_t zigzag[64] = { + 0, 8, 1, 2, 9, 16, 24, 17, 10, 3, 4, 11, 18, 25, 32, 40, + 33, 26, 19, 12, 5, 6, 13, 20, 27, 34, 41, 48, 56, 49, 42, 35, + 28, 21, 14, 7, 15, 22, 29, 36, 43, 50, 57, 58, 51, 44, 37, 30, + 23, 31, 38, 45, 52, 59, 60, 53, 46, 39, 47, 54, 61, 62, 55, 63 +}; + +static const uint8_t intra_scl[64] = { + 10, 11, 14, 16, 17, 19, 21, 23, + 11, 12, 16, 17, 19, 21, 23, 25, + 14, 16, 17, 19, 21, 23, 25, 27, + 16, 17, 19, 21, 23, 25, 27, 28, + 17, 19, 21, 23, 25, 27, 28, 29, + 19, 21, 23, 25, 27, 28, 29, 30, + 21, 23, 25, 27, 28, 29, 30, 31, + 23, 25, 27, 28, 29, 30, 31, 32, +}; + +static const uint8_t inter_scl[64] = { + 12, 13, 15, 16, 17, 19, 20, 21, + 13, 14, 16, 17, 19, 20, 21, 22, + 15, 16, 17, 19, 20, 21, 22, 23, + 16, 17, 19, 20, 21, 22, 23, 25, + 17, 19, 20, 21, 22, 23, 25, 27, + 19, 20, 21, 22, 23, 25, 27, 28, + 20, 21, 22, 23, 25, 27, 28, 29, + 21, 22, 23, 25, 27, 28, 29, 30, +}; + +MPP_RET h264e_pps_update(H264ePps *pps, MppEncCfgSet *cfg) +{ + MppEncH264Cfg *codec = &cfg->h264; + + pps->pps_id = 0; + pps->sps_id = 0; + + pps->entropy_coding_mode = codec->entropy_coding_mode; + pps->bottom_field_pic_order_in_frame_present = 0; + pps->num_slice_groups = 1; + + pps->num_ref_idx_l0_default_active = 1; + pps->num_ref_idx_l1_default_active = 1; + + pps->weighted_pred = 0; + pps->weighted_bipred_idc = 0; + + pps->pic_init_qp = 26; + pps->pic_init_qs = pps->pic_init_qp; + + pps->chroma_qp_index_offset = codec->chroma_cb_qp_offset; + pps->second_chroma_qp_index_offset = codec->chroma_cb_qp_offset; + pps->deblocking_filter_control = 1; + pps->constrained_intra_pred = codec->constrained_intra_pred_mode; + pps->redundant_pic_cnt = 0; + + // if (more_rbsp_data()) + pps->transform_8x8_mode = codec->transform8x8_mode; + mpp_assert(codec->scaling_list_mode == 0 || codec->scaling_list_mode == 1); + pps->pic_scaling_matrix_present = codec->scaling_list_mode; + if (codec->scaling_list_mode) { + /* NOTE: H.264 current encoder do NOT split detail matrix case */ + pps->use_default_scaling_matrix[H264_INTRA_4x4_Y] = 1; + pps->use_default_scaling_matrix[H264_INTRA_4x4_U] = 1; + pps->use_default_scaling_matrix[H264_INTRA_4x4_V] = 1; + pps->use_default_scaling_matrix[H264_INTER_4x4_Y] = 1; + pps->use_default_scaling_matrix[H264_INTER_4x4_U] = 1; + pps->use_default_scaling_matrix[H264_INTER_4x4_V] = 1; + pps->use_default_scaling_matrix[H264_INTRA_8x8_Y] = 1; + pps->use_default_scaling_matrix[H264_INTER_8x8_Y] = 1; + } + + if (codec->profile < H264_PROFILE_HIGH) { + pps->second_chroma_qp_index_offset_present = 0; + if (pps->transform_8x8_mode) { + pps->transform_8x8_mode = 0; + mpp_log_f("warning: for profile %d transform_8x8_mode should be 0\n", + codec->profile); + } + if (pps->pic_scaling_matrix_present) { + pps->pic_scaling_matrix_present = 0; + mpp_log_f("warning: for profile %d pic_scaling_matrix_present should be 0\n", + codec->profile); + } + } else { + pps->second_chroma_qp_index_offset_present = 1; + pps->second_chroma_qp_index_offset = codec->chroma_cr_qp_offset; + } + + if (codec->profile == H264_PROFILE_BASELINE && pps->entropy_coding_mode) { + mpp_log_f("warning: for baseline profile entropy_coding_mode should be 0\n"); + pps->entropy_coding_mode = 0; + } + + return MPP_OK; +} + +RK_S32 h264e_pps_to_packet(H264ePps *pps, MppPacket packet, RK_S32 *offset, RK_S32 *len) +{ + void *pos = mpp_packet_get_pos(packet); + void *data = mpp_packet_get_data(packet); + size_t size = mpp_packet_get_size(packet); + size_t length = mpp_packet_get_length(packet); + void *p = pos + length; + RK_S32 buf_size = (data + size) - (pos + length); + MppWriteCtx bit_ctx; + MppWriteCtx *bit = &bit_ctx; + RK_S32 pps_size = 0; + + mpp_writer_init(bit, p, buf_size); + + /* start_code_prefix 00 00 00 01 */ + mpp_writer_put_raw_bits(bit, 0, 24); + mpp_writer_put_raw_bits(bit, 1, 8); + /* forbidden_zero_bit */ + mpp_writer_put_raw_bits(bit, 0, 1); + /* nal_ref_idc */ + mpp_writer_put_raw_bits(bit, H264_NALU_PRIORITY_HIGHEST, 2); + /* nal_unit_type */ + mpp_writer_put_raw_bits(bit, H264_NALU_TYPE_PPS, 5); + + /* pic_parameter_set_id */ + mpp_writer_put_ue(bit, pps->pps_id); + /* seq_parameter_set_id */ + mpp_writer_put_ue(bit, pps->sps_id); + /* entropy_coding_mode_flag */ + mpp_writer_put_bits(bit, pps->entropy_coding_mode, 1); + /* bottom_field_pic_order_in_frame_present */ + mpp_writer_put_bits(bit, pps->bottom_field_pic_order_in_frame_present, 1); + /* num_slice_groups_minus1 */ + mpp_writer_put_ue(bit, pps->num_slice_groups - 1); + /* num_ref_idx_l0_active_minus1 */ + mpp_writer_put_ue(bit, pps->num_ref_idx_l0_default_active - 1); + /* num_ref_idx_l1_active_minus1 */ + mpp_writer_put_ue(bit, pps->num_ref_idx_l1_default_active - 1); + /* weighted_pred_flag */ + mpp_writer_put_bits(bit, pps->weighted_pred, 1); + /* weighted_bipred_idc */ + mpp_writer_put_bits(bit, pps->weighted_bipred_idc, 2); + /* pic_init_qp_minus26 */ + mpp_writer_put_se(bit, pps->pic_init_qp - 26); + /* pic_init_qs_minus26 */ + mpp_writer_put_se(bit, pps->pic_init_qs - 26); + /* chroma_qp_index_offset */ + mpp_writer_put_se(bit, pps->chroma_qp_index_offset); + /* deblocking_filter_control_present_flag */ + mpp_writer_put_bits(bit, pps->deblocking_filter_control, 1); + /* constrained_intra_pred_flag */ + mpp_writer_put_bits(bit, pps->constrained_intra_pred, 1); + /* redundant_pic_cnt_present_flag */ + mpp_writer_put_bits(bit, pps->redundant_pic_cnt, 1); + + if (pps->transform_8x8_mode || + pps->second_chroma_qp_index_offset_present || + pps->pic_scaling_matrix_present) { + /* transform_8x8_mode_flag */ + mpp_writer_put_bits(bit, pps->transform_8x8_mode, 1); + + /* TODO: scaling_list_mode */ + mpp_writer_put_bits(bit, pps->pic_scaling_matrix_present != 0, 1); + if (pps->pic_scaling_matrix_present) + mpp_writer_put_bits(bit, 0, 6); + + if (1 == pps->pic_scaling_matrix_present) + mpp_writer_put_bits(bit, 0, 2); /* default scaling list */ + else if (2 == pps->pic_scaling_matrix_present) { + /* user defined scaling list */ + if (pps->transform_8x8_mode) { + RK_S32 run = 0; + RK_S32 len2 = 64; + RK_S32 j = 0; + + mpp_writer_put_bits(bit, 1, 1); + for (run = len2; run > 1; run --) + if (intra_scl[zigzag[run - 1]] != intra_scl[zigzag[run - 2]]) + break; + for (j = 0; j < run; j ++) + mpp_writer_put_se(bit, (int8_t)(intra_scl[zigzag[j]] - (j > 0 ? intra_scl[zigzag[j - 1]] : 8))); + if (run < len2) + mpp_writer_put_se(bit, (int8_t) - intra_scl[zigzag[run]]); + + mpp_writer_put_bits(bit, 1, 1); + for (run = len2; run > 1; run --) + if (inter_scl[zigzag[run - 1]] != inter_scl[zigzag[run - 2]]) + break; + for (j = 0; j < run; j ++) + mpp_writer_put_se(bit, (int8_t)(inter_scl[zigzag[j]] - (j > 0 ? inter_scl[zigzag[j - 1]] : 8))); + if (run < len2) + mpp_writer_put_se(bit, (int8_t) - inter_scl[zigzag[run]]); + } else + mpp_writer_put_bits(bit, 0, 2); + } + + /* second_chroma_qp_index_offset */ + mpp_writer_put_se(bit, pps->second_chroma_qp_index_offset); + } + + mpp_writer_trailing(bit); + + pps_size = mpp_writer_bytes(bit); + if (len) + *len = pps_size; + if (offset) + *offset = length; + + mpp_packet_set_length(packet, length + pps_size); + + return pps_size; +} + +MPP_RET h264e_pps_dump(H264ePps *pps) +{ + (void) pps; + return MPP_OK; +} diff --git a/mpp/codec/enc/h264/h264e_pps.h b/mpp/codec/enc/h264/h264e_pps.h new file mode 100644 index 000000000..8a1d7ed8a --- /dev/null +++ b/mpp/codec/enc/h264/h264e_pps.h @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_PPS_H +#define H264E_PPS_H + +#include "mpp_packet.h" +#include "mpp_enc_cfg.h" + +#include "h264_syntax.h" + +typedef struct H264ePps_t { + RK_U32 pps_id; + RK_U32 sps_id; + + // 0 - CAVLC 1 - CABAC + RK_S32 entropy_coding_mode; + + RK_S32 bottom_field_pic_order_in_frame_present; + RK_S32 num_slice_groups; + + RK_S32 num_ref_idx_l0_default_active; + RK_S32 num_ref_idx_l1_default_active; + + RK_S32 weighted_pred; + RK_S32 weighted_bipred_idc; + + RK_S32 pic_init_qp; + RK_S32 pic_init_qs; + + RK_S32 chroma_qp_index_offset; + RK_S32 second_chroma_qp_index_offset_present; + RK_S32 second_chroma_qp_index_offset; + + RK_S32 deblocking_filter_control; + RK_S32 constrained_intra_pred; + RK_S32 redundant_pic_cnt; + + RK_S32 transform_8x8_mode; + + // Only support flat and default scaling list + RK_S32 pic_scaling_matrix_present; //TODO: replaced with scaling_list_mode + RK_S32 use_default_scaling_matrix[H264_SCALING_MATRIX_TYPE_BUTT]; +} H264ePps; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h264e_pps_update(H264ePps *pps, MppEncCfgSet *cfg); +MPP_RET h264e_pps_to_packet(H264ePps *pps, MppPacket packet, RK_S32 *offset, RK_S32 *len); +MPP_RET h264e_pps_dump(H264ePps *pps); + +#ifdef __cplusplus +} +#endif + +#endif /* H264E_PPS_H */ diff --git a/mpp/codec/enc/h264/h264e_sei.c b/mpp/codec/enc/h264/h264e_sei.c new file mode 100644 index 000000000..2c248a1a8 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_sei.c @@ -0,0 +1,169 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_sei" + +#include + +#include "mpp_common.h" + +#include "mpp_bitwrite.h" +#include "mpp_packet_impl.h" +#include "h264e_debug.h" + +#include "h264_syntax.h" +#include "h264e_sei.h" + +static MPP_RET write_recovery_point(MppWriteCtx *bit, RK_U32 recovery_frame_cnt) +{ + mpp_writer_put_ue(bit, recovery_frame_cnt); + mpp_writer_put_bits(bit, 1, 1); + mpp_writer_put_bits(bit, 0, 1); + mpp_writer_put_bits(bit, 0, 2); + mpp_writer_trailing(bit); + return MPP_OK; +} + +MPP_RET h264e_sei_recovery_point_to_packet(MppPacket packet, RK_S32 *len, RK_U32 recovery_frame_cnt) +{ + MPP_RET ret = MPP_OK; + void *pos = mpp_packet_get_pos(packet); + void *pkt_base = mpp_packet_get_data(packet); + size_t pkt_size = mpp_packet_get_size(packet); + size_t length = mpp_packet_get_length(packet); + void *dst = pos + length; + RK_S32 buf_size = (pkt_base + pkt_size) - (pos + length); + MppWriteCtx bit_ctx; + MppWriteCtx *bit = &bit_ctx; + RK_S32 payload_size = 0; + RK_S32 type = H264_SEI_RECOVERY_POINT; + RK_U8 src[100] = {0}; + RK_S32 sei_size = 0; + RK_S32 i; + mpp_writer_init(bit, src, 100); + write_recovery_point(bit, recovery_frame_cnt); + payload_size = mpp_writer_bytes(bit); + + mpp_writer_init(bit, dst, buf_size); + + /* start_code_prefix 00 00 00 01 */ + mpp_writer_put_raw_bits(bit, 0, 24); + mpp_writer_put_raw_bits(bit, 1, 8); + /* forbidden_zero_bit */ + mpp_writer_put_raw_bits(bit, 0, 1); + /* nal_ref_idc */ + mpp_writer_put_raw_bits(bit, H264_NALU_PRIORITY_DISPOSABLE, 2); + /* nal_unit_type */ + mpp_writer_put_raw_bits(bit, H264_NALU_TYPE_SEI, 5); + + /* sei_payload_type_ff_byte */ + for (i = 0; i <= type - 255; i += 255) + mpp_writer_put_bits(bit, 0xff, 8); + + /* sei_last_payload_type_byte */ + mpp_writer_put_bits(bit, type - i, 8); + + /* sei_payload_size_ff_byte */ + for (i = 0; i <= payload_size - 255; i += 255) + mpp_writer_put_bits(bit, 0xff, 8); + + /* sei_last_payload_size_byte */ + mpp_writer_put_bits(bit, payload_size - i, 8); + + write_recovery_point(bit, recovery_frame_cnt); + + sei_size = mpp_writer_bytes(bit); + if (len) + *len = sei_size; + + mpp_packet_set_length(packet, length + sei_size); + mpp_packet_add_segment_info(packet, H264_NALU_TYPE_SEI, length, sei_size); + + h264e_dbg_sei("sei data length %d pkt len %d -> %d\n", sei_size, + length, length + sei_size); + + return ret; + +} + +MPP_RET h264e_sei_to_packet(MppPacket packet, RK_S32 *len, RK_S32 type, + RK_U8 uuid[16], const void *data, RK_S32 size) +{ + void *pos = mpp_packet_get_pos(packet); + void *pkt_base = mpp_packet_get_data(packet); + size_t pkt_size = mpp_packet_get_size(packet); + size_t length = mpp_packet_get_length(packet); + const RK_U8 *src = (RK_U8 *)data; + void *dst = pos + length; + RK_S32 buf_size = (pkt_base + pkt_size) - (pos + length); + MppWriteCtx bit_ctx; + MppWriteCtx *bit = &bit_ctx; + RK_S32 uuid_size = uuid ? 16 : 0; + RK_S32 payload_size = size + uuid_size; + RK_S32 sei_size = 0; + RK_S32 i; + + h264e_dbg_sei("write sei to pkt [%p:%u] [%p:%u]\n", pkt_base, pkt_size, + pos, length); + + mpp_writer_init(bit, dst, buf_size); + + /* start_code_prefix 00 00 00 01 */ + mpp_writer_put_raw_bits(bit, 0, 24); + mpp_writer_put_raw_bits(bit, 1, 8); + /* forbidden_zero_bit */ + mpp_writer_put_raw_bits(bit, 0, 1); + /* nal_ref_idc */ + mpp_writer_put_raw_bits(bit, H264_NALU_PRIORITY_DISPOSABLE, 2); + /* nal_unit_type */ + mpp_writer_put_raw_bits(bit, H264_NALU_TYPE_SEI, 5); + + /* sei_payload_type_ff_byte */ + for (i = 0; i <= type - 255; i += 255) + mpp_writer_put_bits(bit, 0xff, 8); + + /* sei_last_payload_type_byte */ + mpp_writer_put_bits(bit, type - i, 8); + + /* sei_payload_size_ff_byte */ + for (i = 0; i <= payload_size - 255; i += 255) + mpp_writer_put_bits(bit, 0xff, 8); + + /* sei_last_payload_size_byte */ + mpp_writer_put_bits(bit, payload_size - i, 8); + + /* uuid_iso_iec_11578 */ + for (i = 0; i < uuid_size; i++) + mpp_writer_put_bits(bit, uuid[i], 8); + + /* sei_payload_data */ + for (i = 0; i < size; i++) + mpp_writer_put_bits(bit, src[i], 8); + + mpp_writer_trailing(bit); + + sei_size = mpp_writer_bytes(bit); + if (len) + *len = sei_size; + + mpp_packet_set_length(packet, length + sei_size); + mpp_packet_add_segment_info(packet, H264_NALU_TYPE_SEI, length, sei_size); + + h264e_dbg_sei("sei data length %d pkt len %d -> %d\n", sei_size, + length, length + sei_size); + + return MPP_OK; +} diff --git a/mpp/codec/enc/h264/h264e_sei.h b/mpp/codec/enc/h264/h264e_sei.h new file mode 100644 index 000000000..6ee9f6040 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_sei.h @@ -0,0 +1,34 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_SEI_H +#define H264E_SEI_H + +#include "mpp_packet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h264e_sei_recovery_point_to_packet(MppPacket packet, RK_S32 *len, RK_U32 recovery_frame_cnt); +MPP_RET h264e_sei_to_packet(MppPacket packet, RK_S32 *len, RK_S32 type, + RK_U8 uuid[16], const void *data, RK_S32 size); + +#ifdef __cplusplus +} +#endif + +#endif /* H264E_SEI_H */ diff --git a/mpp/codec/enc/h264/h264e_slice.c b/mpp/codec/enc/h264/h264e_slice.c new file mode 100644 index 000000000..48c43bc41 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_slice.c @@ -0,0 +1,1168 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_slice" + +#include + +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bitwrite.h" + +#include "h264e_debug.h" +#include "h264e_slice.h" +#include "h264e_dpb.h" + +#define FP_FIFO_IS_FULL + +void h264e_slice_init(H264eSlice *slice, H264eReorderInfo *reorder, + H264eMarkingInfo *marking) +{ + memset(slice, 0, sizeof(*slice)); + + slice->num_ref_idx_active = 1; + + slice->reorder = reorder; + slice->marking = marking; +} + +RK_S32 h264e_slice_update(H264eSlice *slice, MppEncCfgSet *cfg, + H264eSps *sps, H264ePps *pps, H264eDpbFrm *frm) +{ + MppEncH264Cfg *h264 = &cfg->h264; + RK_S32 is_idr = frm->status.is_idr; + + slice->mb_w = sps->pic_width_in_mbs; + slice->mb_h = sps->pic_height_in_mbs; + slice->max_num_ref_frames = sps->num_ref_frames; + slice->log2_max_frame_num = sps->log2_max_frame_num_minus4 + 4; + slice->log2_max_poc_lsb = sps->log2_max_poc_lsb_minus4 + 4; + slice->entropy_coding_mode = h264->entropy_coding_mode; + slice->pic_order_cnt_type = sps->pic_order_cnt_type; + slice->qp_init = pps->pic_init_qp; + + slice->nal_reference_idc = (frm->status.is_non_ref != 0) ? (H264_NALU_PRIORITY_DISPOSABLE) : + (is_idr != 0) ? (H264_NALU_PRIORITY_HIGHEST) : + (H264_NALU_PRIORITY_HIGH); + slice->nalu_type = (is_idr != 0) ? (H264_NALU_TYPE_IDR) : (H264_NALU_TYPE_SLICE); + + slice->first_mb_in_slice = 0; + slice->slice_type = (is_idr != 0) ? (H264_I_SLICE) : (H264_P_SLICE); + slice->pic_parameter_set_id = 0; + slice->frame_num = frm->frame_num; + slice->num_ref_idx_override = 0; + slice->qp_delta = 0; + slice->cabac_init_idc = (h264->entropy_coding_mode != 0) ? h264->cabac_init_idc : -1; + slice->disable_deblocking_filter_idc = h264->deblock_disable; + slice->slice_alpha_c0_offset_div2 = h264->deblock_offset_alpha; + slice->slice_beta_offset_div2 = h264->deblock_offset_beta; + + slice->idr_flag = is_idr; + + if (slice->idr_flag) { + slice->idr_pic_id = slice->next_idr_pic_id; + slice->next_idr_pic_id++; + if (slice->next_idr_pic_id >= 16) + slice->next_idr_pic_id = 0; + } + + slice->pic_order_cnt_lsb = frm->poc & ((1 << slice->log2_max_poc_lsb) - 1); + slice->num_ref_idx_active = 1; + slice->no_output_of_prior_pics = 0; + if (slice->idr_flag) + slice->long_term_reference_flag = frm->status.is_lt_ref; + else + slice->long_term_reference_flag = 0; + + return MPP_OK; +} + +MPP_RET h264e_reorder_init(H264eReorderInfo *reorder) +{ + reorder->size = H264E_MAX_REFS_CNT; + reorder->rd_cnt = 0; + reorder->wr_cnt = 0; + + return MPP_OK; +} + +MPP_RET h264e_reorder_wr_rewind(H264eReorderInfo *info) +{ + info->wr_cnt = 0; + return MPP_OK; +} + +MPP_RET h264e_reorder_rd_rewind(H264eReorderInfo *info) +{ + info->rd_cnt = 0; + return MPP_OK; +} + +MPP_RET h264e_reorder_wr_op(H264eReorderInfo *info, H264eRplmo *op) +{ + if (info->wr_cnt >= info->size) { + mpp_err_f("write too many reorder op %d vs %d\n", + info->wr_cnt, info->size); + return MPP_NOK; + } + + info->ops[info->wr_cnt++] = *op; + return MPP_OK; +} + +MPP_RET h264e_reorder_rd_op(H264eReorderInfo *info, H264eRplmo *op) +{ + if (info->rd_cnt >= info->wr_cnt) + return MPP_NOK; + + *op = info->ops[info->rd_cnt++]; + return MPP_OK; +} + +MPP_RET h264e_marking_init(H264eMarkingInfo *marking) +{ + marking->idr_flag = 0; + marking->no_output_of_prior_pics = 0; + marking->long_term_reference_flag = 0; + marking->adaptive_ref_pic_buffering = 0; + marking->size = MAX_H264E_MMCO_CNT; + marking->wr_cnt = 0; + marking->rd_cnt = 0; + + return MPP_OK; +} + +RK_S32 h264e_marking_is_empty(H264eMarkingInfo *info) +{ + return info->rd_cnt >= info->wr_cnt; +} + +MPP_RET h264e_marking_wr_rewind(H264eMarkingInfo *marking) +{ + marking->wr_cnt = 0; + return MPP_OK; +} + +MPP_RET h264e_marking_rd_rewind(H264eMarkingInfo *marking) +{ + marking->rd_cnt = 0; + return MPP_OK; +} + +MPP_RET h264e_marking_wr_op(H264eMarkingInfo *info, H264eMmco *op) +{ + if (info->wr_cnt >= info->size) { + mpp_err_f("write too many mmco op %d vs %d\n", + info->wr_cnt, info->size); + return MPP_NOK; + } + + info->ops[info->wr_cnt++] = *op; + return MPP_OK; +} + +MPP_RET h264e_marking_rd_op(H264eMarkingInfo *info, H264eMmco *op) +{ + if (h264e_marking_is_empty(info)) + return MPP_NOK; + + *op = info->ops[info->rd_cnt++]; + return MPP_OK; +} + +void write_marking(MppWriteCtx *s, H264eMarkingInfo *marking) +{ + if (marking->idr_flag) { + /* no_output_of_prior_pics_flag */ + mpp_writer_put_bits(s, marking->no_output_of_prior_pics, 1); + h264e_dbg_slice("used bit %2d no_output_of_prior_pics_flag %d\n", + mpp_writer_bits(s), marking->no_output_of_prior_pics); + + /* long_term_reference_flag */ + mpp_writer_put_bits(s, marking->long_term_reference_flag, 1); + h264e_dbg_slice("used bit %2d long_term_reference_flag %d\n", + mpp_writer_bits(s), marking->long_term_reference_flag); + } else { + h264e_dbg_mmco("mmco count %d\n", marking->wr_cnt); + + h264e_marking_rd_rewind(marking); + + if (!h264e_marking_is_empty(marking)) { + H264eMmco mmco; + + /* adaptive_ref_pic_marking_mode_flag */ + mpp_writer_put_bits(s, 1, 1); + h264e_dbg_slice("used bit %2d adaptive_ref_pic_marking_mode_flag 1\n", + mpp_writer_bits(s)); + + while (MPP_OK == h264e_marking_rd_op(marking, &mmco)) { + /* memory_management_control_operation */ + mpp_writer_put_ue(s, mmco.mmco); + h264e_dbg_slice("used bit %2d memory_management_control_operation %d\n", + mpp_writer_bits(s), mmco.mmco); + + switch (mmco.mmco) { + case 1 : { + /* difference_of_pic_nums_minus1 */ + mpp_writer_put_ue(s, mmco.difference_of_pic_nums_minus1); + h264e_dbg_slice("used bit %2d difference_of_pic_nums_minus1 %d\n", + mpp_writer_bits(s), mmco.difference_of_pic_nums_minus1); + } break; + case 2 : { + /* long_term_pic_num */ + mpp_writer_put_ue(s, mmco.long_term_pic_num ); + h264e_dbg_slice("used bit %2d long_term_pic_num %d\n", + mpp_writer_bits(s), mmco.long_term_pic_num); + } break; + case 3 : { + /* difference_of_pic_nums_minus1 */ + mpp_writer_put_ue(s, mmco.difference_of_pic_nums_minus1); + h264e_dbg_slice("used bit %2d difference_of_pic_nums_minus1 %d\n", + mpp_writer_bits(s), mmco.difference_of_pic_nums_minus1); + + /* long_term_frame_idx */ + mpp_writer_put_ue(s, mmco.long_term_frame_idx ); + h264e_dbg_slice("used bit %2d long_term_frame_idx %d\n", + mpp_writer_bits(s), mmco.long_term_frame_idx); + } break; + case 4 : { + /* max_long_term_frame_idx_plus1 */ + mpp_writer_put_ue(s, mmco.max_long_term_frame_idx_plus1); + h264e_dbg_slice("used bit %2d max_long_term_frame_idx_plus1 %d\n", + mpp_writer_bits(s), mmco.max_long_term_frame_idx_plus1); + } break; + case 5 : { + } break; + case 6 : { + /* long_term_frame_idx */ + mpp_writer_put_ue(s, mmco.long_term_frame_idx); + h264e_dbg_slice("used bit %2d long_term_frame_idx %d\n", + mpp_writer_bits(s), mmco.long_term_frame_idx); + } break; + default : { + mpp_err_f("invalid mmco %d\n", mmco.mmco); + } break; + } + } + + /* memory_management_control_operation */ + mpp_writer_put_ue(s, 0); + h264e_dbg_slice("used bit %2d memory_management_control_operation 0\n", + mpp_writer_bits(s)); + } else { + /* adaptive_ref_pic_marking_mode_flag */ + mpp_writer_put_bits(s, 0, 1); + h264e_dbg_slice("used bit %2d adaptive_ref_pic_marking_mode_flag 0\n", + mpp_writer_bits(s)); + } + } +} + +/* vepu read slice */ +RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size) +{ + BitReadCtx_t bit; + RK_S32 ret = 0; + RK_S32 val = 0; + RK_S32 bit_cnt = 0; + + mpp_set_bitread_ctx(&bit, p, size); + /* enable remove 03 */ + mpp_set_bitread_pseudo_code_type(&bit, PSEUDO_CODE_H264_H265); + + /* start_code */ + ret |= mpp_read_longbits(&bit, 32, (RK_U32 *)&val); + h264e_dbg_slice("used bit %2d start_code %x\n", + bit.used_bits, val); + + /* forbidden_zero_bit */ + ret |= mpp_read_bits(&bit, 1, &val); + h264e_dbg_slice("used bit %2d forbidden_zero_bit %x\n", + bit.used_bits, val); + + /* nal_ref_idc */ + ret |= mpp_read_bits(&bit, 2, &slice->nal_reference_idc); + h264e_dbg_slice("used bit %2d nal_reference_idc %d\n", + bit.used_bits, slice->nal_reference_idc); + + /* nal_unit_type */ + ret |= mpp_read_bits(&bit, 5, &slice->nalu_type); + h264e_dbg_slice("used bit %2d nal_unit_type %d\n", + bit.used_bits, slice->nalu_type); + + /* first_mb_nr */ + ret = mpp_read_ue(&bit, &slice->first_mb_in_slice); + h264e_dbg_slice("used bit %2d first_mb_in_slice %d\n", + bit.used_bits, slice->first_mb_in_slice); + + /* slice_type */ + ret |= mpp_read_ue(&bit, &slice->slice_type); + h264e_dbg_slice("used bit %2d slice_type %d\n", + bit.used_bits, slice->slice_type); + + /* pic_parameter_set_id */ + ret |= mpp_read_ue(&bit, &slice->pic_parameter_set_id); + h264e_dbg_slice("used bit %2d pic_parameter_set_id %d\n", + bit.used_bits, slice->pic_parameter_set_id); + + /* frame_num */ + /* NOTE: vpu hardware fix 16 bit frame_num */ + ret |= mpp_read_bits(&bit, slice->log2_max_frame_num, &slice->frame_num); + h264e_dbg_slice("used bit %2d frame_num %d\n", + bit.used_bits, slice->frame_num); + + slice->idr_flag = (slice->nalu_type == 5); + if (slice->idr_flag) { + /* idr_pic_id */ + ret |= mpp_read_ue(&bit, &slice->idr_pic_id); + h264e_dbg_slice("used bit %2d idr_pic_id %d\n", + bit.used_bits, slice->idr_pic_id); + } + + /* pic_order_cnt_type */ + if (slice->pic_order_cnt_type == 0) { + /* pic_order_cnt_lsb */ + ret |= mpp_read_bits(&bit, slice->log2_max_poc_lsb, + (RK_S32 *)&slice->pic_order_cnt_lsb); + h264e_dbg_slice("used bit %2d pic_order_cnt_lsb %d\n", + bit.used_bits, slice->pic_order_cnt_lsb); + } + + // NOTE: Only P slice has num_ref_idx_override flag and ref_pic_list_modification flag + if (slice->slice_type == H264_P_SLICE) { + /* num_ref_idx_override */ + ret |= mpp_read_bits(&bit, 1, &slice->num_ref_idx_override); + h264e_dbg_slice("used bit %2d num_ref_idx_override %d\n", + bit.used_bits, slice->num_ref_idx_override); + + mpp_assert(slice->num_ref_idx_override == 0); + + // NOTE: vpu hardware is always zero + /* ref_pic_list_modification_flag */ + ret |= mpp_read_bits(&bit, 1, &slice->ref_pic_list_modification_flag); + h264e_dbg_slice("used bit %2d ref_pic_list_modification_flag %d\n", + bit.used_bits, slice->ref_pic_list_modification_flag); + + if (slice->ref_pic_list_modification_flag) { + RK_U32 modification_of_pic_nums_idc = 0; + H264eRplmo ops; + + h264e_reorder_wr_rewind(slice->reorder); + + do { + /* modification_of_pic_nums_idc */ + ret |= mpp_read_ue(&bit, &modification_of_pic_nums_idc); + ops.modification_of_pic_nums_idc = modification_of_pic_nums_idc; + h264e_dbg_slice("used bit %2d modification_of_pic_nums_idc %d\n", + bit.used_bits, modification_of_pic_nums_idc); + + switch (modification_of_pic_nums_idc) { + case 0 : + case 1 : { + /* abs_diff_pic_num_minus1 */ + RK_U32 abs_diff_pic_num_minus1 = 0; + + ret |= mpp_read_ue(&bit, &abs_diff_pic_num_minus1); + ops.abs_diff_pic_num_minus1 = abs_diff_pic_num_minus1; + h264e_dbg_slice("used bit %2d abs_diff_pic_num_minus1 %d\n", + bit.used_bits, abs_diff_pic_num_minus1); + } break; + case 2 : { + /* long_term_pic_idx */ + RK_U32 long_term_pic_idx = 0; + + ret |= mpp_read_ue(&bit, &long_term_pic_idx); + ops.long_term_pic_idx = long_term_pic_idx; + h264e_dbg_slice("used bit %2d long_term_pic_idx %d\n", + bit.used_bits, long_term_pic_idx); + } break; + case 3 : { + } break; + default : { + mpp_err_f("invalid modification_of_pic_nums_idc %d\n", + modification_of_pic_nums_idc); + } break; + } + + h264e_reorder_wr_op(slice->reorder, &ops); + memset(&ops, 0, sizeof(ops)); + } while (modification_of_pic_nums_idc != 3); + } + } + + if (slice->nal_reference_idc) { + if (slice->idr_flag) { + /* no_output_of_prior_pics */ + ret |= mpp_read_bits(&bit, 1, &slice->no_output_of_prior_pics); + slice->marking->no_output_of_prior_pics = slice->no_output_of_prior_pics; + h264e_dbg_slice("used bit %2d no_output_of_prior_pics %d\n", + bit.used_bits, slice->no_output_of_prior_pics); + + /* long_term_reference_flag */ + ret |= mpp_read_bits(&bit, 1, &slice->long_term_reference_flag); + slice->marking->long_term_reference_flag = slice->long_term_reference_flag; + h264e_dbg_slice("used bit %2d long_term_reference_flag %d\n", + bit.used_bits, slice->long_term_reference_flag); + } else { + /* adaptive_ref_pic_buffering */ + ret |= mpp_read_bits(&bit, 1, &slice->adaptive_ref_pic_buffering); + slice->marking->adaptive_ref_pic_buffering = slice->adaptive_ref_pic_buffering; + h264e_dbg_slice("used bit %2d adaptive_ref_pic_buffering %d\n", + bit.used_bits, slice->adaptive_ref_pic_buffering); + + if (slice->adaptive_ref_pic_buffering) { + RK_U32 mmco; + H264eMmco opt; + + h264e_marking_wr_rewind(slice->marking); + + do { + ret |= mpp_read_ue(&bit, &mmco); + opt.mmco = mmco; + h264e_dbg_slice("used bit %2d memory_management_control_operation %d\n", + bit.used_bits, mmco); + + // avoidance of writing extra struct H264eMmco + if (mmco == 0) + break; + + if (mmco == 1 || mmco == 3) { + RK_U32 difference_of_pic_nums_minus1; + + ret |= mpp_read_ue(&bit, &difference_of_pic_nums_minus1); + opt.difference_of_pic_nums_minus1 = difference_of_pic_nums_minus1; + h264e_dbg_slice("used bit %2d difference_of_pic_nums_minus1 %d\n", + bit.used_bits, difference_of_pic_nums_minus1); + } + + if (mmco == 2) { + RK_U32 long_term_pic_num; + + ret |= mpp_read_ue(&bit, &long_term_pic_num); + opt.long_term_pic_num = long_term_pic_num; + h264e_dbg_slice("used bit %2d long_term_pic_num %d\n", + bit.used_bits, long_term_pic_num); + } + + if (mmco == 3 || mmco == 6) { + RK_U32 long_term_frame_idx; + + ret |= mpp_read_ue(&bit, &long_term_frame_idx); + opt.long_term_frame_idx = long_term_frame_idx; + h264e_dbg_slice("used bit %2d long_term_frame_idx %d\n", + bit.used_bits, long_term_frame_idx); + } + + if (mmco == 4) { + RK_U32 max_long_term_frame_idx_plus1; + + ret |= mpp_read_ue(&bit, &max_long_term_frame_idx_plus1); + opt.max_long_term_frame_idx_plus1 = max_long_term_frame_idx_plus1; + h264e_dbg_slice("used bit %2d max_long_term_frame_idx_plus1 %d\n", + bit.used_bits, max_long_term_frame_idx_plus1); + } + + h264e_marking_wr_op(slice->marking, &opt); + memset(&opt, 0, sizeof(opt)); + } while (mmco); + } + } + } + + if (slice->entropy_coding_mode && slice->slice_type != H264_I_SLICE) { + /* cabac_init_idc */ + ret |= mpp_read_ue(&bit, &slice->cabac_init_idc); + h264e_dbg_slice("used bit %2d cabac_init_idc %d\n", + bit.used_bits, slice->cabac_init_idc); + } + + /* qp_delta */ + ret |= mpp_read_se(&bit, &slice->qp_delta); + h264e_dbg_slice("used bit %2d qp_delta %d\n", + bit.used_bits, slice->qp_delta); + + /* disable_deblocking_filter_idc */ + ret |= mpp_read_ue(&bit, &slice->disable_deblocking_filter_idc); + h264e_dbg_slice("used bit %2d disable_deblocking_filter_idc %d\n", + bit.used_bits, slice->disable_deblocking_filter_idc); + + /* slice_alpha_c0_offset_div2 */ + ret |= mpp_read_se(&bit, &slice->slice_alpha_c0_offset_div2); + h264e_dbg_slice("used bit %2d slice_alpha_c0_offset_div2 %d\n", + bit.used_bits, slice->slice_alpha_c0_offset_div2); + + /* slice_beta_offset_div2 */ + ret |= mpp_read_se(&bit, &slice->slice_beta_offset_div2); + h264e_dbg_slice("used bit %2d slice_beta_offset_div2 %d\n", + bit.used_bits, slice->slice_beta_offset_div2); + + h264e_dbg_slice("used bit %2d non-aligned length\n", bit.used_bits); + + if (slice->entropy_coding_mode) { + if (bit.num_remaining_bits_in_curr_byte_) { + RK_U32 tmp = bit.num_remaining_bits_in_curr_byte_; + + /* cabac_aligned_bit */ + ret |= mpp_read_bits(&bit, tmp, &val); + h264e_dbg_slice("used bit %2d cabac_aligned_bit %x\n", + bit.used_bits, val); + } + } + bit_cnt = bit.used_bits; + + h264e_dbg_slice("used bit %2d total aligned length, read result %d\n", bit.used_bits, ret); + + if (h264e_debug & H264E_DBG_SLICE) { + RK_S32 pos = 0; + RK_S32 i; + char log[256]; + RK_U8 *tmp = (RK_U8 *)p; + + pos = sprintf(log + pos, "hw stream: "); + for (i = 0; i < 16; i++) { + pos += sprintf(log + pos, "%02x ", tmp[i]); + } + pos += sprintf(log + pos, "\n"); + h264e_dbg_slice(log); + } + + return bit_cnt; +} + +void h264e_slice_write_header(H264eSlice *slice, MppWriteCtx *s) +{ + H264eMarkingInfo *marking = slice->marking; + H264eRplmo rplmo; + MPP_RET ret = MPP_OK; + + /* nal header */ + /* start_code_prefix 00 00 00 01 */ + mpp_writer_put_raw_bits(s, 0, 24); + mpp_writer_put_raw_bits(s, 1, 8); + h264e_dbg_slice("used bit %2d start_code_prefix\n", + mpp_writer_bits(s)); + + /* forbidden_zero_bit */ + mpp_writer_put_raw_bits(s, 0, 1); + h264e_dbg_slice("used bit %2d forbidden_zero_bit\n", + mpp_writer_bits(s)); + + /* nal_reference_idc */ + mpp_writer_put_raw_bits(s, slice->nal_reference_idc, 2); + h264e_dbg_slice("used bit %2d nal_reference_idc %d\n", + mpp_writer_bits(s), slice->nal_reference_idc); + /* nalu_type */ + mpp_writer_put_raw_bits(s, slice->nalu_type, 5); + h264e_dbg_slice("used bit %2d nalu_type %d\n", + mpp_writer_bits(s), slice->nalu_type); + + /* slice header */ + /* start_mb_nr */ + mpp_writer_put_ue(s, slice->first_mb_in_slice); + h264e_dbg_slice("used bit %2d first_mb_in_slice %d\n", + mpp_writer_bits(s), slice->first_mb_in_slice); + + /* slice_type */ + mpp_writer_put_ue(s, slice->slice_type); + h264e_dbg_slice("used bit %2d slice_type %d\n", + mpp_writer_bits(s), slice->slice_type); + + /* pic_parameter_set_id */ + mpp_writer_put_ue(s, slice->pic_parameter_set_id); + h264e_dbg_slice("used bit %2d pic_parameter_set_id %d\n", + mpp_writer_bits(s), slice->pic_parameter_set_id); + + /* frame_num */ + mpp_writer_put_bits(s, slice->frame_num, slice->log2_max_frame_num); + h264e_dbg_slice("used bit %2d frame_num %d\n", + mpp_writer_bits(s), slice->frame_num); + + if (slice->nalu_type == 5) { + /* idr_pic_id */ + mpp_writer_put_ue(s, slice->idr_pic_id); + h264e_dbg_slice("used bit %2d idr_pic_id %d\n", + mpp_writer_bits(s), slice->idr_pic_id); + marking->idr_flag = 1; + } else + marking->idr_flag = 0; + + // Force to use poc type 0 here + if (slice->pic_order_cnt_type == 0) { + RK_S32 pic_order_cnt_lsb = slice->pic_order_cnt_lsb; + RK_S32 max_poc_lsb = (1 << slice->log2_max_poc_lsb); + + if (pic_order_cnt_lsb >= max_poc_lsb) + pic_order_cnt_lsb &= (max_poc_lsb - 1); + + /* pic_order_cnt_lsb */ + mpp_writer_put_bits(s, pic_order_cnt_lsb, slice->log2_max_poc_lsb); + h264e_dbg_slice("used bit %2d pic_order_cnt_lsb %d\n", + mpp_writer_bits(s), pic_order_cnt_lsb); + } else { + mpp_assert(slice->pic_order_cnt_type == 2); + } + + /* num_ref_idx_override */ + slice->ref_pic_list_modification_flag = 0; + + h264e_reorder_rd_rewind(slice->reorder); + + if (slice->slice_type == H264_P_SLICE) { + mpp_assert(slice->num_ref_idx_override == 0); + + mpp_writer_put_bits(s, slice->num_ref_idx_override, 1); + h264e_dbg_slice("used bit %2d num_ref_idx_override %d\n", + mpp_writer_bits(s), slice->num_ref_idx_override); + + + /* read reorder and check */ + ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + /* ref_pic_list_modification_flag */ + slice->ref_pic_list_modification_flag = (ret == MPP_OK); + mpp_writer_put_bits(s, slice->ref_pic_list_modification_flag, 1); + h264e_dbg_slice("used bit %2d ref_pic_list_modification_flag %d\n", + mpp_writer_bits(s), slice->ref_pic_list_modification_flag); + + if (slice->ref_pic_list_modification_flag) { + /* modification_of_pic_nums_idc */ + mpp_writer_put_ue(s, rplmo.modification_of_pic_nums_idc); + h264e_dbg_slice("used bit %2d modification_of_pic_nums_idc %d\n", + mpp_writer_bits(s), + rplmo.modification_of_pic_nums_idc); + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + /* abs_diff_pic_num_minus1 */ + mpp_writer_put_ue(s, rplmo.abs_diff_pic_num_minus1); + h264e_dbg_slice("used bit %2d abs_diff_pic_num_minus1 %d\n", + mpp_writer_bits(s), + rplmo.abs_diff_pic_num_minus1); + } break; + case 2 : { + /* long_term_pic_idx */ + mpp_writer_put_ue(s, rplmo.long_term_pic_idx); + h264e_dbg_slice("used bit %2d long_term_pic_idx %d\n", + mpp_writer_bits(s), + rplmo.long_term_pic_idx); + } break; + default : { + mpp_err_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + + /* modification_of_pic_nums_idc */ + mpp_writer_put_ue(s, 3); + h264e_dbg_slice("used bit %2d modification_of_pic_nums_idc 3\n", + mpp_writer_bits(s)); + + } + } + + // NOTE: ignore nal ref idc here + h264e_dbg_mmco("nal_reference_idc %d idr_flag %d\n", + slice->nal_reference_idc, slice->idr_flag); + + if (slice->nal_reference_idc) { + /* In VEPU1/2, lt_ref_flag is fixed to 0, so it must be replaced by data in slice. */ + if (slice->long_term_reference_flag != marking->long_term_reference_flag) { + marking->long_term_reference_flag = slice->long_term_reference_flag; + h264e_dbg_slice("warning: update lt_ref_flag from %d to %d\n", + marking->long_term_reference_flag, slice->long_term_reference_flag); + } + + h264e_dbg_slice("get marking %p\n", marking); + write_marking(s, marking); + } + + if (slice->entropy_coding_mode && slice->slice_type != H264_I_SLICE) { + /* cabac_init_idc */ + mpp_writer_put_ue(s, slice->cabac_init_idc); + h264e_dbg_slice("used bit %2d cabac_init_idc %d\n", + mpp_writer_bits(s), slice->cabac_init_idc); + } + + /* qp_delta */ + mpp_writer_put_se(s, slice->qp_delta); + h264e_dbg_slice("used bit %2d qp_delta %d\n", + mpp_writer_bits(s), slice->qp_delta); + + /* disable_deblocking_filter_idc */ + mpp_writer_put_ue(s, slice->disable_deblocking_filter_idc); + h264e_dbg_slice("used bit %2d disable_deblocking_filter_idc %d\n", + mpp_writer_bits(s), slice->disable_deblocking_filter_idc); + + /* slice_alpha_c0_offset_div2 */ + mpp_writer_put_se(s, slice->slice_alpha_c0_offset_div2); + h264e_dbg_slice("used bit %2d slice_alpha_c0_offset_div2 %d\n", + mpp_writer_bits(s), slice->slice_alpha_c0_offset_div2); + + /* slice_beta_offset_div2 */ + mpp_writer_put_se(s, slice->slice_beta_offset_div2); + h264e_dbg_slice("used bit %2d slice_beta_offset_div2 %d\n", + mpp_writer_bits(s), slice->slice_beta_offset_div2); + + /* cabac_alignment_one_bit */ + if (slice->entropy_coding_mode) { + mpp_writer_align_one(s); + h264e_dbg_slice("used bit %2d align_bit 1\n", + mpp_writer_bits(s)); + } + + mpp_writer_flush(s); +} + +RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size) +{ + MppWriteCtx stream; + MppWriteCtx *s = &stream; + RK_S32 bitCnt = 0; + + mpp_writer_init(s, p, size); + + h264e_slice_write_header(slice, s); + + bitCnt = s->buffered_bits + s->byte_cnt * 8; + + // update on cabac mode + if (slice->entropy_coding_mode) + bitCnt = s->buffered_bits + s->byte_cnt * 8; + + if (h264e_debug & H264E_DBG_SLICE) { + RK_S32 i; + RK_U8 *tmp = p; + RK_S32 pos = 0; + char log[256]; + + pos = sprintf(log + pos, "sw stream: "); + for (i = 0; i < 16; i ++) { + pos += sprintf(log + pos, "%02x ", tmp[i]); + } + pos += sprintf(log + pos, "\n"); + h264e_dbg_slice(log); + } + + return bitCnt; +} + +/* + * For software force skip stream writing + * 3 contexts state for skip flag + * end_of_slice flag is equal to write bypass 1 + */ +typedef struct H264eCabac_t { + RK_S32 state; + + RK_S32 low; + RK_S32 range; + RK_S32 queue; + RK_S32 bytes_outstanding; + + MppWriteCtx *s; +} H264eCabac; + +static const RK_S8 skip_init_state[3][2] = { + // skip_flag ctx 11 + /* model 0 */ { 23, 33 }, + /* model 1 */ { 22, 25 }, + /* model 2 */ { 29, 16 }, +}; + +static void init_context(H264eCabac *ctx, RK_S32 qp, RK_S32 model, MppWriteCtx *s) +{ + const RK_S8 *init = &skip_init_state[model][0]; + RK_S32 state = MPP_CLIP3(1, 126, ((init[0] * qp) >> 4) + init[1]); + + ctx->state = (MPP_MIN(state, 127 - state) << 1) | (state >> 6); + + ctx->low = 0; + ctx->range = 0x01FE; + ctx->queue = -9; + ctx->bytes_outstanding = 0; + ctx->s = s; +} + +static inline void h264e_cabac_putbyte(H264eCabac *ctx) +{ + if (ctx->queue >= 0) { + RK_S32 out = ctx->low >> (ctx->queue + 10); + + ctx->low &= (0x400 << ctx->queue) - 1; + ctx->queue -= 8; + + if ((out & 0xff) == 0xff) { + ctx->bytes_outstanding++; + } else { + MppWriteCtx *s = ctx->s; + RK_S32 carry = out >> 8; + RK_S32 bytes_outstanding = ctx->bytes_outstanding; + + if (ctx->queue > 0) + mpp_writer_put_bits(s, carry, ctx->queue & 0x7); + + while (bytes_outstanding > 0) { + mpp_writer_put_bits(s, carry - 1, 8); + bytes_outstanding--; + } + + mpp_writer_put_bits(s, out, MPP_MIN(8, 8 - ctx->queue)); + ctx->bytes_outstanding = 0; + } + } +} + +static inline void h264e_cabac_renorm(H264eCabac *ctx) +{ + static const RK_U8 x264_cabac_renorm_shift[64] = { + 6, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + RK_S32 shift = x264_cabac_renorm_shift[ctx->range >> 3]; + + ctx->range <<= shift; + ctx->low <<= shift; + ctx->queue += shift; + + h264e_cabac_putbyte(ctx); +} + +static void h264e_cabac_write_skip_flag(H264eCabac *ctx) +{ + static const RK_U8 h264e_cabac_range_lps[64][4] = { + { 2, 2, 2, 2}, { 6, 7, 8, 9}, { 6, 7, 9, 10}, { 6, 8, 9, 11}, + { 7, 8, 10, 11}, { 7, 9, 10, 12}, { 7, 9, 11, 12}, { 8, 9, 11, 13}, + { 8, 10, 12, 14}, { 9, 11, 12, 14}, { 9, 11, 13, 15}, { 10, 12, 14, 16}, + { 10, 12, 15, 17}, { 11, 13, 15, 18}, { 11, 14, 16, 19}, { 12, 14, 17, 20}, + { 12, 15, 18, 21}, { 13, 16, 19, 22}, { 14, 17, 20, 23}, { 14, 18, 21, 24}, + { 15, 19, 22, 25}, { 16, 20, 23, 27}, { 17, 21, 25, 28}, { 18, 22, 26, 30}, + { 19, 23, 27, 31}, { 20, 24, 29, 33}, { 21, 26, 30, 35}, { 22, 27, 32, 37}, + { 23, 28, 33, 39}, { 24, 30, 35, 41}, { 26, 31, 37, 43}, { 27, 33, 39, 45}, + { 29, 35, 41, 48}, { 30, 37, 43, 50}, { 32, 39, 46, 53}, { 33, 41, 48, 56}, + { 35, 43, 51, 59}, { 37, 45, 54, 62}, { 39, 48, 56, 65}, { 41, 50, 59, 69}, + { 43, 53, 63, 72}, { 46, 56, 66, 76}, { 48, 59, 69, 80}, { 51, 62, 73, 85}, + { 53, 65, 77, 89}, { 56, 69, 81, 94}, { 59, 72, 86, 99}, { 62, 76, 90, 104}, + { 66, 80, 95, 110}, { 69, 85, 100, 116}, { 73, 89, 105, 122}, { 77, 94, 111, 128}, + { 81, 99, 117, 135}, { 85, 104, 123, 142}, { 90, 110, 130, 150}, { 95, 116, 137, 158}, + {100, 122, 144, 166}, {105, 128, 152, 175}, {111, 135, 160, 185}, {116, 142, 169, 195}, + {123, 150, 178, 205}, {128, 158, 187, 216}, {128, 167, 197, 227}, {128, 176, 208, 240} + }; + + static const RK_U8 h264e_cabac_transition[128][2] = { + { 0, 0}, { 1, 1}, { 2, 50}, { 51, 3}, { 2, 50}, { 51, 3}, { 4, 52}, { 53, 5}, + { 6, 52}, { 53, 7}, { 8, 52}, { 53, 9}, { 10, 54}, { 55, 11}, { 12, 54}, { 55, 13}, + { 14, 54}, { 55, 15}, { 16, 56}, { 57, 17}, { 18, 56}, { 57, 19}, { 20, 56}, { 57, 21}, + { 22, 58}, { 59, 23}, { 24, 58}, { 59, 25}, { 26, 60}, { 61, 27}, { 28, 60}, { 61, 29}, + { 30, 60}, { 61, 31}, { 32, 62}, { 63, 33}, { 34, 62}, { 63, 35}, { 36, 64}, { 65, 37}, + { 38, 66}, { 67, 39}, { 40, 66}, { 67, 41}, { 42, 66}, { 67, 43}, { 44, 68}, { 69, 45}, + { 46, 68}, { 69, 47}, { 48, 70}, { 71, 49}, { 50, 72}, { 73, 51}, { 52, 72}, { 73, 53}, + { 54, 74}, { 75, 55}, { 56, 74}, { 75, 57}, { 58, 76}, { 77, 59}, { 60, 78}, { 79, 61}, + { 62, 78}, { 79, 63}, { 64, 80}, { 81, 65}, { 66, 82}, { 83, 67}, { 68, 82}, { 83, 69}, + { 70, 84}, { 85, 71}, { 72, 84}, { 85, 73}, { 74, 88}, { 89, 75}, { 76, 88}, { 89, 77}, + { 78, 90}, { 91, 79}, { 80, 90}, { 91, 81}, { 82, 94}, { 95, 83}, { 84, 94}, { 95, 85}, + { 86, 96}, { 97, 87}, { 88, 96}, { 97, 89}, { 90, 100}, {101, 91}, { 92, 100}, {101, 93}, + { 94, 102}, {103, 95}, { 96, 104}, {105, 97}, { 98, 104}, {105, 99}, {100, 108}, {109, 101}, + {102, 108}, {109, 103}, {104, 110}, {111, 105}, {106, 112}, {113, 107}, {108, 114}, {115, 109}, + {110, 116}, {117, 111}, {112, 118}, {119, 113}, {114, 118}, {119, 115}, {116, 122}, {123, 117}, + {118, 122}, {123, 119}, {120, 124}, {125, 121}, {122, 126}, {127, 123}, {124, 127}, {126, 125} + }; + + RK_S32 skip = 1; + RK_S32 state = ctx->state; + RK_S32 range_lps = h264e_cabac_range_lps[state >> 1][(ctx->range >> 6) - 4]; + + ctx->range -= range_lps; + if (skip != (state & 1) ) { + ctx->low += ctx->range; + ctx->range = range_lps; + } + + ctx->state = h264e_cabac_transition[state][skip]; + + h264e_cabac_renorm(ctx); +} + +static void h264e_cabac_terminal(H264eCabac *ctx) +{ + ctx->range -= 2; + h264e_cabac_renorm(ctx); +} + +static void h264e_cabac_flush(H264eCabac *ctx) +{ + /* end_of_slice_flag = 1 */ + ctx->low += ctx->range - 2; + ctx->low |= 1; + ctx->low <<= 9; + ctx->queue += 9; + + h264e_cabac_putbyte( ctx ); + h264e_cabac_putbyte( ctx ); + + ctx->low <<= -ctx->queue; + ctx->low |= 1 << 10; + ctx->queue = 0; + + h264e_cabac_putbyte( ctx ); + + while (ctx->bytes_outstanding > 0) { + mpp_writer_put_bits(ctx->s, 0xff, 8); + ctx->bytes_outstanding--; + } +} + +RK_S32 h264e_slice_write_pskip(H264eSlice *slice, void *p, RK_U32 size) +{ + MppWriteCtx stream; + MppWriteCtx *s = &stream; + RK_S32 bitCnt = 0; + + mpp_writer_init(s, p, size); + + h264e_slice_write_header(slice, s); + if (slice->entropy_coding_mode) { + /* cabac */ + H264eCabac ctx; + RK_S32 i; + + init_context(&ctx, slice->qp_init, slice->cabac_init_idc, s); + + for (i = 0; i < slice->mb_w * slice->mb_h; i++) { + /* end_of_slice_flag = 0 */ + if (i) + h264e_cabac_terminal(&ctx); + + /* skip flag */ + h264e_cabac_write_skip_flag(&ctx); + } + + /* end_of_slice_flag = 1 and flush */ + h264e_cabac_flush(&ctx); + } else { + /* cavlc */ + /* mb skip run */ + mpp_writer_put_ue(s, slice->mb_w * slice->mb_h); + h264e_dbg_slice("used bit %d mb_skip_run %d\n", + mpp_writer_bits(s), slice->mb_w * slice->mb_h); + + /* rbsp_stop_one_bit */ + mpp_writer_trailing(s); + h264e_dbg_slice("used bit %d tailing %d\n", mpp_writer_bits(s)); + } + mpp_writer_flush(s); + + bitCnt = s->buffered_bits + s->byte_cnt * 8; + return bitCnt; +} + +RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit, RK_S32 src_size) +{ + RK_S32 dst_byte = dst_bit / 8; + RK_S32 src_byte = src_bit / 8; + RK_S32 dst_bit_r = dst_bit & 7; + RK_S32 src_bit_r = src_bit & 7; + RK_S32 src_len = src_size - src_byte; + RK_S32 diff_len = 0; + static RK_S32 frame_no = 0; + + if (src_bit_r == 0 && dst_bit_r == 0) { + // direct copy + if (h264e_debug & H264E_DBG_SLICE) + mpp_log_f("direct copy %p -> %p %d\n", src, dst, src_len); + + h264e_dbg_slice("bit [%d %d] [%d %d] [%d %d] len %d\n", + src_bit, dst_bit, src_byte, dst_byte, + src_bit_r, dst_bit_r, src_len); + + memcpy(dst + dst_byte, src + src_byte, src_len); + return diff_len; + } + + RK_U8 *psrc = src + src_byte; + RK_U8 *pdst = dst + dst_byte; + + RK_U16 tmp16a, tmp16b, tmp16c, last_tmp, dst_mask; + RK_U8 tmp0, tmp1; + RK_U32 loop = src_len + (src_bit_r > 0); + RK_U32 i = 0; + RK_U32 src_zero_cnt = 0; + RK_U32 dst_zero_cnt = 0; + RK_U32 dst_len = 0; + + last_tmp = (RK_U16)pdst[0]; + dst_mask = 0xFFFF << (8 - dst_bit_r); + + h264e_dbg_slice("bit [%d %d] [%d %d] [%d %d] loop %d mask %04x last %04x\n", + src_bit, dst_bit, src_byte, dst_byte, + src_bit_r, dst_bit_r, loop, dst_mask, last_tmp); + + for (i = 0; i < loop; i++) { + if (psrc[0] == 0) { + src_zero_cnt++; + } else { + src_zero_cnt = 0; + } + + // tmp0 tmp1 is next two non-aligned bytes from src + tmp0 = psrc[0]; + tmp1 = (i < loop - 1) ? psrc[1] : 0; + + if (src_zero_cnt >= 2 && tmp1 == 3) { + if (h264e_debug & H264E_DBG_SLICE) + mpp_log("found 03 at src pos %d %02x %02x %02x %02x %02x %02x %02x %02x\n", + i, psrc[-2], psrc[-1], psrc[0], psrc[1], psrc[2], + psrc[3], psrc[4], psrc[5]); + + psrc++; + i++; + tmp1 = psrc[1]; + src_zero_cnt = 0; + diff_len--; + } + // get U16 data + tmp16a = ((RK_U16)tmp0 << 8) | (RK_U16)tmp1; + + if (src_bit_r) { + tmp16b = tmp16a << src_bit_r; + } else { + tmp16b = tmp16a; + } + + if (dst_bit_r) + tmp16c = tmp16b >> dst_bit_r | ((last_tmp << 8) & dst_mask); + else + tmp16c = tmp16b; + + pdst[0] = (tmp16c >> 8) & 0xFF; + pdst[1] = tmp16c & 0xFF; + + if (h264e_debug & H264E_DBG_SLICE) { + if (i < 10) { + mpp_log("%03d src [%04x] -> [%04x] + last [%04x] -> %04x\n", i, tmp16a, tmp16b, last_tmp, tmp16c); + } + if (i >= loop - 10) { + mpp_log("%03d src [%04x] -> [%04x] + last [%04x] -> %04x\n", i, tmp16a, tmp16b, last_tmp, tmp16c); + } + } + + if (dst_zero_cnt == 2 && pdst[0] <= 0x3) { + if (h264e_debug & H264E_DBG_SLICE) + mpp_log("found 03 at dst frame %d pos %d\n", frame_no, dst_len); + + pdst[2] = pdst[1]; + pdst[1] = pdst[0]; + pdst[0] = 0x3; + pdst++; + diff_len++; + dst_len++; + dst_zero_cnt = 0; + } + + if (pdst[0] == 0) + dst_zero_cnt++; + else + dst_zero_cnt = 0; + + last_tmp = tmp16c; + + psrc++; + pdst++; + dst_len++; + } + + frame_no++; + + return diff_len; +} + +RK_S32 h264e_slice_write_prefix_nal_unit_svc(H264ePrefixNal *prefix, void *p, RK_S32 size) +{ + MppWriteCtx stream; + MppWriteCtx *s = &stream; + RK_S32 bitCnt = 0; + + mpp_writer_init(s, p, size); + + /* nal header */ + /* start_code_prefix 00 00 00 01 */ + mpp_writer_put_raw_bits(s, 0, 24); + mpp_writer_put_raw_bits(s, 1, 8); + + /* forbidden_zero_bit */ + mpp_writer_put_raw_bits(s, 0, 1); + + /* nal_reference_idc */ + mpp_writer_put_raw_bits(s, prefix->nal_ref_idc, 2); + + /* nalu_type */ + mpp_writer_put_raw_bits(s, 14, 5); + + /* svc_extension_flag */ + mpp_writer_put_raw_bits(s, 1, 1); + + /* nal_unit_header_svc_extension */ + /* idr_flag */ + mpp_writer_put_raw_bits(s, prefix->idr_flag, 1); + + /* priority_id */ + mpp_writer_put_raw_bits(s, prefix->priority_id , 6); + + /* no_inter_layer_pred_flag */ + mpp_writer_put_raw_bits(s, prefix->no_inter_layer_pred_flag , 1); + + /* dependency_id */ + mpp_writer_put_raw_bits(s, prefix->dependency_id, 3); + + /* quality_id */ + mpp_writer_put_raw_bits(s, prefix->quality_id, 4); + + /* temporal_id */ + mpp_writer_put_raw_bits(s, prefix->temporal_id, 3); + + /* use_ref_base_pic_flag */ + mpp_writer_put_raw_bits(s, prefix->use_ref_base_pic_flag, 1); + + /* discardable_flag */ + mpp_writer_put_raw_bits(s, prefix->discardable_flag, 1); + + /* output_flag */ + mpp_writer_put_raw_bits(s, prefix->output_flag, 1); + + /* reserved_three_2bits */ + mpp_writer_put_raw_bits(s, 3, 2); + + /* prefix_nal_unit_svc */ + if (prefix->nal_ref_idc) { + /* store_ref_base_pic_flag */ + mpp_writer_put_raw_bits(s, 0, 1); + + /* additional_prefix_nal_unit_extension_flag */ + mpp_writer_put_raw_bits(s, 0, 1); + + /* rbsp_trailing_bits */ + mpp_writer_trailing(s); + } + + mpp_writer_flush(s); + + bitCnt = s->buffered_bits + s->byte_cnt * 8; + + return bitCnt; +} diff --git a/mpp/codec/enc/h264/h264e_slice.h b/mpp/codec/enc/h264/h264e_slice.h new file mode 100644 index 000000000..f217e6b5c --- /dev/null +++ b/mpp/codec/enc/h264/h264e_slice.h @@ -0,0 +1,184 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_SLICE_H +#define H264E_SLICE_H + +#include "mpp_enc_cfg.h" + +#include "h264e_syntax.h" +#include "h264e_sps.h" +#include "h264e_pps.h" + +/* + * For H.264 encoder slice header process. + * Remove some syntax that encoder not supported. + * Field, mbaff, B slice are not supported yet. + * + * The reorder and mmco syntax will be create by dpb and attach to slice. + * Then slice syntax will be passed to hal to config hardware or modify the + * hardware stream. + */ + +/* reference picture list modification operation */ +typedef struct H264eRplmo_t { + RK_S32 modification_of_pic_nums_idc; + RK_S32 abs_diff_pic_num_minus1; + RK_S32 long_term_pic_idx; + RK_S32 abs_diff_view_idx_minus1; +} H264eRplmo; + +typedef struct H264eReorderInfo_t { + RK_S32 rd_cnt; + RK_S32 wr_cnt; + RK_S32 size; + H264eRplmo ops[H264E_MAX_REFS_CNT]; +} H264eReorderInfo; + +/* + * mmco (Memory management control operation) value + * 0 - End memory_management_control_operation syntax element loop + * 1 - Mark a short-term reference picture as "unused for reference" + * 2 - Mark a long-term reference picture as "unused for reference" + * 3 - Mark a short-term reference picture as "used for long-term + * reference" and assign a long-term frame index to it + * 4 - Specify the maximum long-term frame index and mark all long-term + * reference pictures having long-term frame indices greater than + * the maximum value as "unused for reference" + * 5 - Mark all reference pictures as "unused for reference" and set the + * MaxLongTermFrameIdx variable to "no long-term frame indices" + * 6 - Mark the current picture as "used for long-term reference" and + * assign a long-term frame index to it + */ +typedef struct H264eMmco_t { + RK_S32 mmco; + RK_S32 difference_of_pic_nums_minus1; // for MMCO 1 & 3 + RK_S32 long_term_pic_num; // for MMCO 2 + RK_S32 long_term_frame_idx; // for MMCO 3 & 6 + RK_S32 max_long_term_frame_idx_plus1; // for MMCO 4 +} H264eMmco; + +#define MAX_H264E_MMCO_CNT 8 + +typedef struct H264eMarkingInfo_t { + RK_S32 idr_flag; + /* idr marking flag */ + RK_S32 no_output_of_prior_pics; + RK_S32 long_term_reference_flag; + /* non-idr marking flag */ + RK_S32 adaptive_ref_pic_buffering; + RK_S32 rd_cnt; + RK_S32 wr_cnt; + RK_S32 size; + H264eMmco ops[MAX_H264E_MMCO_CNT]; +} H264eMarkingInfo; + +typedef struct H264eSlice_t { + /* Copy of sps/pps parameter */ + RK_S32 mb_w; + RK_S32 mb_h; + RK_U32 max_num_ref_frames; + RK_U32 entropy_coding_mode; + RK_S32 log2_max_frame_num; + RK_S32 log2_max_poc_lsb; + RK_S32 pic_order_cnt_type; + RK_S32 qp_init; + + /* Nal parameters */ + RK_S32 nal_reference_idc; + RK_S32 nalu_type; + + /* Unchanged parameters */ + RK_U32 first_mb_in_slice; + RK_U32 slice_type; + RK_U32 pic_parameter_set_id; + RK_S32 frame_num; + RK_S32 num_ref_idx_override; + RK_S32 qp_delta; + RK_U32 cabac_init_idc; + RK_U32 disable_deblocking_filter_idc; + RK_S32 slice_alpha_c0_offset_div2; + RK_S32 slice_beta_offset_div2; + + /* reorder parameter */ + RK_S32 ref_pic_list_modification_flag; + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + + RK_S32 idr_flag; + RK_U32 idr_pic_id; + RK_U32 next_idr_pic_id; + /* for poc mode 0 */ + RK_U32 pic_order_cnt_lsb; + RK_S32 num_ref_idx_active; + /* idr mmco flag */ + RK_S32 no_output_of_prior_pics; + RK_S32 long_term_reference_flag; + + /* Changable parameters */ + RK_S32 adaptive_ref_pic_buffering; + + /* for multi-slice writing */ + RK_S32 is_multi_slice; +} H264eSlice; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * reorder context for both dpb and slice + */ +MPP_RET h264e_reorder_init(H264eReorderInfo *reorder); +MPP_RET h264e_reorder_wr_rewind(H264eReorderInfo *info); +MPP_RET h264e_reorder_rd_rewind(H264eReorderInfo *info); +MPP_RET h264e_reorder_wr_op(H264eReorderInfo *info, H264eRplmo *op); +MPP_RET h264e_reorder_rd_op(H264eReorderInfo *info, H264eRplmo *op); + +/* mmco context for both dpb and slice */ +MPP_RET h264e_marking_init(H264eMarkingInfo *marking); +RK_S32 h264e_marking_is_empty(H264eMarkingInfo *info); +MPP_RET h264e_marking_wr_rewind(H264eMarkingInfo *marking); +MPP_RET h264e_marking_rd_rewind(H264eMarkingInfo *marking); +MPP_RET h264e_marking_wr_op(H264eMarkingInfo *info, H264eMmco *op); +MPP_RET h264e_marking_rd_op(H264eMarkingInfo *info, H264eMmco *op); + +/* + * h264e_slice_update is called only on cfg is update. + * When cfg has no changes just use slice next to setup + */ +void h264e_slice_init(H264eSlice *slice, H264eReorderInfo *reorder, + H264eMarkingInfo *marking); + +typedef struct H264eDpbFrm_t H264eDpbFrm; + +RK_S32 h264e_slice_update(H264eSlice *slice, MppEncCfgSet *cfg, + H264eSps *sps, H264ePps *pps, + H264eDpbFrm *frm); + +RK_S32 h264e_slice_read(H264eSlice *slice, void *p, RK_S32 size); +RK_S32 h264e_slice_write(H264eSlice *slice, void *p, RK_U32 size); +RK_S32 h264e_slice_write_pskip(H264eSlice *slice, void *p, RK_U32 size); +RK_S32 h264e_slice_move(RK_U8 *dst, RK_U8 *src, RK_S32 dst_bit, RK_S32 src_bit, + RK_S32 src_size); + +RK_S32 h264e_slice_write_prefix_nal_unit_svc(H264ePrefixNal *nal, void *p, RK_S32 size); + +#ifdef __cplusplus +} +#endif + +#endif /* H264E_SLICE_H */ diff --git a/mpp/codec/enc/h264/h264e_sps.c b/mpp/codec/enc/h264/h264e_sps.c new file mode 100644 index 000000000..2e9454eae --- /dev/null +++ b/mpp/codec/enc/h264/h264e_sps.c @@ -0,0 +1,466 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_sps" + +#include + +#include "mpp_common.h" + +#include "mpp_enc_ref.h" +#include "mpp_bitwrite.h" +#include "h264e_debug.h" +#include "h264e_sps.h" + +typedef struct H264eLevelInfo_t { + H264Level level; + RK_S32 max_MBPS; /* Max macroblock rate per second */ + RK_S32 max_MBs; /* Max frame size */ + RK_S32 max_DpbMBs; /* Max decoded picture buffer size */ + RK_S32 max_BR; /* Max video bitrate */ + const char *name; +} H264eLevelInfo; + +H264eLevelInfo level_infos[] = { + /* level max_MBs max_MBPS max_DpbMBs max_BR name */ + { H264_LEVEL_1_0, 1485, 99, 396, 64, "1" }, + { H264_LEVEL_1_b, 1485, 99, 396, 128, "1.b" }, + { H264_LEVEL_1_1, 3000, 396, 900, 192, "1.1" }, + { H264_LEVEL_1_2, 6000, 396, 2376, 384, "1.2" }, + { H264_LEVEL_1_3, 11880, 396, 2376, 768, "1.3" }, + { H264_LEVEL_2_0, 11880, 396, 2376, 2000, "2" }, + { H264_LEVEL_2_1, 19800, 792, 4752, 4000, "2.1" }, + { H264_LEVEL_2_2, 20250, 1620, 8100, 4000, "2.2" }, + { H264_LEVEL_3_0, 40500, 1620, 8100, 10000, "3" }, + { H264_LEVEL_3_1, 108000, 3600, 18000, 14000, "3.1" }, + { H264_LEVEL_3_2, 216000, 5120, 20480, 20000, "3.2" }, + { H264_LEVEL_4_0, 245760, 8192, 32768, 20000, "4" }, + { H264_LEVEL_4_1, 245760, 8192, 32768, 50000, "4.1" }, + { H264_LEVEL_4_2, 522240, 8704, 34816, 50000, "4.2" }, + { H264_LEVEL_5_0, 589824, 22080, 110400, 135000, "5" }, + { H264_LEVEL_5_1, 983040, 36864, 184320, 240000, "5.1" }, + { H264_LEVEL_5_2, 2073600, 36864, 184320, 240000, "5.2" }, + { H264_LEVEL_6_0, 4177920, 139264, 696320, 240000, "6" }, + { H264_LEVEL_6_1, 8355840, 139264, 696320, 480000, "6.1" }, + { H264_LEVEL_6_2, 16711680, 139264, 696320, 800000, "6.2" }, +}; + +MPP_RET h264e_sps_update(H264eSps *sps, MppEncCfgSet *cfg) +{ + H264eVui *vui = &sps->vui; + MppEncPrepCfg *prep = &cfg->prep; + MppEncRcCfg *rc = &cfg->rc; + MppEncH264Cfg *h264 = &cfg->h264; + MppEncRefCfg ref = cfg->ref_cfg; + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref); + MppFrameFormat fmt = prep->format & MPP_FRAME_FMT_MASK; + RK_S32 gop = rc->gop; + RK_S32 width = prep->width; + RK_S32 height = prep->height; + RK_S32 aligned_w = MPP_ALIGN(width, 16); + RK_S32 aligned_h = MPP_ALIGN(height, 16); + RK_S32 crop_right = MPP_ALIGN(width, 16) - width; + RK_S32 crop_bottom = MPP_ALIGN(height, 16) - height; + /* default 720p */ + H264Level level_idc = h264->level; + + // default sps + // profile baseline + sps->profile_idc = h264->profile; + switch (sps->profile_idc) { + case H264_PROFILE_BASELINE : { + sps->constraint_set0 = 1; + sps->constraint_set1 = 1; + sps->constraint_set2 = 0; + sps->constraint_set3 = 0; + sps->constraint_set4 = 0; + sps->constraint_set5 = 0; + } break; + case H264_PROFILE_MAIN : { + sps->constraint_set0 = 0; + sps->constraint_set1 = 1; + sps->constraint_set2 = 0; + sps->constraint_set3 = 0; + sps->constraint_set4 = 0; + sps->constraint_set5 = 0; + } break; + case H264_PROFILE_HIGH : + case H264_PROFILE_HIGH10 : + case H264_PROFILE_HIGH422 : + case H264_PROFILE_HIGH444 : { + sps->constraint_set0 = 0; + sps->constraint_set1 = 0; + sps->constraint_set2 = 0; + sps->constraint_set3 = 0; + sps->constraint_set4 = 0; + sps->constraint_set5 = 0; + } break; + default : { + sps->constraint_set0 = 0; + sps->constraint_set1 = 0; + sps->constraint_set2 = 0; + sps->constraint_set3 = 0; + sps->constraint_set4 = 0; + sps->constraint_set5 = 0; + } break; + } + + //updata constraint_set0~5 + RK_U32 set = h264->constraint_set; + RK_U8 constraint_force = (set >> 0) & 0x3f; + RK_U8 force_flag = (set >> 16) & 0x3f; + + if (force_flag & 1) + sps->constraint_set0 = (constraint_force & 1) ? 1 : 0; + if (force_flag & 2) + sps->constraint_set1 = (constraint_force & 2) ? 1 : 0; + if (force_flag & 4) + sps->constraint_set2 = (constraint_force & 4) ? 1 : 0; + if (force_flag & 8) + sps->constraint_set3 = (constraint_force & 8) ? 1 : 0; + if (force_flag & 16) + sps->constraint_set4 = (constraint_force & 16) ? 1 : 0; + if (force_flag & 32) + sps->constraint_set5 = (constraint_force & 32) ? 1 : 0; + + // level_idc is connected with frame size + { + RK_S32 mbs = (aligned_w * aligned_h) >> 8; + RK_S32 i; + RK_S32 min_level = 10; + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(level_infos); i++) { + if (level_infos[i].max_MBs >= mbs) { + min_level = level_infos[i].level; + + if (min_level > (RK_S32)level_idc && + min_level != H264_LEVEL_1_b) { + level_idc = min_level; + h264e_dbg_sps("set level to %s\n", level_infos[i].name); + } + + break; + } + } + } + sps->level_idc = level_idc; + + sps->sps_id = 0; + sps->chroma_format_idc = (fmt == MPP_FMT_YUV400) ? H264_CHROMA_400 : H264_CHROMA_420; + + // set max frame number and poc lsb according to gop size + sps->pic_order_cnt_type = h264->hw_cfg.hw_poc_type; + sps->log2_max_poc_lsb_minus4 = h264->log2_max_poc_lsb; + sps->log2_max_frame_num_minus4 = h264->log2_max_frame_num; + + mpp_assert(gop >= 0); + if (gop == 0) { + // only one I then all P frame + sps->log2_max_frame_num_minus4 = 12; + sps->log2_max_poc_lsb_minus4 = 12; + } else if (gop == 1) { + // all I frame + sps->log2_max_frame_num_minus4 = 12; + sps->log2_max_poc_lsb_minus4 = 12; + } else { + // normal case + RK_S32 log2_gop = MPP_MIN(mpp_log2(gop), 16); + RK_S32 log2_frm_num = (log2_gop <= 4) ? (0) : (log2_gop - 4); + RK_S32 log2_poc_lsb = (log2_gop <= 3) ? (0) : (log2_gop - 3); + + if (sps->log2_max_frame_num_minus4 < log2_frm_num) + sps->log2_max_frame_num_minus4 = log2_frm_num; + + if (log2_poc_lsb > 12) + log2_poc_lsb = 12; + + if (sps->log2_max_poc_lsb_minus4 < log2_poc_lsb) + sps->log2_max_poc_lsb_minus4 = log2_poc_lsb; + } + + // max one reference frame + sps->num_ref_frames = info->dpb_size; + + sps->gaps_in_frame_num_value_allowed = !h264->gaps_not_allowed; + + // default 720p without cropping + sps->pic_width_in_mbs = aligned_w >> 4; + sps->pic_height_in_mbs = aligned_h >> 4; + sps->frame_mbs_only = 1; + + // baseline disable 8x8 + sps->direct8x8_inference = h264->transform8x8_mode; + if (crop_right || crop_bottom) { + sps->cropping = 1; + sps->crop.left = 0; + sps->crop.right = crop_right; + sps->crop.top = 0; + sps->crop.bottom = crop_bottom; + } else { + sps->cropping = 0; + memset(&sps->crop, 0, sizeof(sps->crop)); + } + + memset(vui, 0, sizeof(*vui)); + vui->vui_en = h264->vui.vui_en; + vui->timing_info_present = 1; + vui->time_scale = rc->fps_out_num * 2; + vui->num_units_in_tick = rc->fps_out_denom; + vui->fixed_frame_rate = !rc->fps_out_flex; + vui->vidformat = MPP_FRAME_VIDEO_FMT_UNSPECIFIED; + + if (prep->range == MPP_FRAME_RANGE_JPEG) { + vui->signal_type_present = 1; + vui->fullrange = 1; + } + + if ((prep->colorprim <= MPP_FRAME_PRI_JEDEC_P22 && + prep->colorprim != MPP_FRAME_PRI_UNSPECIFIED) || + (prep->colortrc <= MPP_FRAME_TRC_ARIB_STD_B67 && + prep->colortrc != MPP_FRAME_TRC_UNSPECIFIED) || + (prep->color <= MPP_FRAME_SPC_ICTCP && + prep->color != MPP_FRAME_SPC_UNSPECIFIED)) { + vui->signal_type_present = 1; + vui->color_description_present = 1; + vui->colorprim = prep->colorprim; + vui->colortrc = prep->colortrc; + vui->colmatrix = prep->color; + } + + vui->bitstream_restriction = 1; + vui->motion_vectors_over_pic_boundaries = 1; + /* the max and default value has been changed to 15 since the 2016 standard */ + vui->log2_max_mv_length_horizontal = 15; + vui->log2_max_mv_length_vertical = 15; + vui->max_dec_frame_buffering = info->dpb_size; + + return MPP_OK; +} + +MPP_RET h264e_sps_to_packet(H264eSps *sps, MppPacket packet, RK_S32 *offset, + RK_S32 *len, MppEncCfgSet *cfg) +{ + void *pos = mpp_packet_get_pos(packet); + void *data = mpp_packet_get_data(packet); + size_t size = mpp_packet_get_size(packet); + size_t length = mpp_packet_get_length(packet); + void *p = pos + length; + RK_S32 buf_size = (data + size) - (pos + length); + MppWriteCtx bit_ctx; + MppWriteCtx *bit = &bit_ctx; + RK_S32 sps_size = 0; + static const RK_U32 SubWidthC[4] = { 1, 2, 2, 1}; + static const RK_U32 SubHeightC[4] = { 1, 2, 1, 1}; + + mpp_writer_init(bit, p, buf_size); + + /* start_code_prefix 00 00 00 01 */ + mpp_writer_put_raw_bits(bit, 0, 24); + mpp_writer_put_raw_bits(bit, 1, 8); + /* forbidden_zero_bit */ + mpp_writer_put_raw_bits(bit, 0, 1); + /* nal_ref_idc */ + mpp_writer_put_raw_bits(bit, H264_NALU_PRIORITY_HIGHEST, 2); + /* nal_unit_type */ + mpp_writer_put_raw_bits(bit, H264_NALU_TYPE_SPS, 5); + + /* profile_idc */ + mpp_writer_put_bits(bit, sps->profile_idc, 8); + /* constraint_set0_flag */ + mpp_writer_put_bits(bit, sps->constraint_set0, 1); + /* constraint_set1_flag */ + mpp_writer_put_bits(bit, sps->constraint_set1, 1); + /* constraint_set2_flag */ + mpp_writer_put_bits(bit, sps->constraint_set2, 1); + /* constraint_set3_flag */ + mpp_writer_put_bits(bit, sps->constraint_set3, 1); + /* constraint_set4_flag */ + mpp_writer_put_bits(bit, sps->constraint_set4, 1); + /* constraint_set5_flag */ + mpp_writer_put_bits(bit, sps->constraint_set5, 1); + /* reserved_zero_2bits */ + mpp_writer_put_bits(bit, 0, 2); + + /* level_idc */ + mpp_writer_put_bits(bit, sps->level_idc, 8); + /* seq_parameter_set_id */ + mpp_writer_put_ue(bit, sps->sps_id); + + if (sps->profile_idc >= H264_PROFILE_HIGH) { + /* chroma_format_idc */ + mpp_writer_put_ue(bit, sps->chroma_format_idc); + /* bit_depth_luma_minus8 */ + mpp_writer_put_ue(bit, 0); + /* bit_depth_chroma_minus8 */ + mpp_writer_put_ue(bit, 0); + /* qpprime_y_zero_transform_bypass_flag */ + mpp_writer_put_bits(bit, 0, 1); + /* seq_scaling_matrix_present_flag */ + mpp_writer_put_bits(bit, 0, 1); + } + + /* log2_max_frame_num_minus4 */ + mpp_writer_put_ue(bit, sps->log2_max_frame_num_minus4); + /* pic_order_cnt_type */ + /* accodring usr cfg cfg->h264.poc_type, hw may no support + will convert after get stream + */ + mpp_writer_put_ue(bit, cfg->h264.poc_type); + if (cfg->h264.poc_type == 0) { + /* log2_max_pic_order_cnt_lsb_minus4 */ + mpp_writer_put_ue(bit, sps->log2_max_poc_lsb_minus4); + } + + /* max_num_ref_frames */ + mpp_writer_put_ue(bit, sps->num_ref_frames); + /* gaps_in_frame_num_value_allowed_flag */ + mpp_writer_put_bits(bit, sps->gaps_in_frame_num_value_allowed, 1); + + /* pic_width_in_mbs_minus1 */ + mpp_writer_put_ue(bit, sps->pic_width_in_mbs - 1); + /* pic_height_in_map_units_minus1 */ + mpp_writer_put_ue(bit, sps->pic_height_in_mbs - 1); + + /* frame_mbs_only_flag */ + mpp_writer_put_bits(bit, sps->frame_mbs_only, 1); + /* direct_8x8_inference_flag */ + mpp_writer_put_bits(bit, sps->direct8x8_inference, 1); + /* frame_cropping_flag */ + mpp_writer_put_bits(bit, sps->cropping, 1); + if (sps->cropping) { + /* frame_crop_left_offset */ + mpp_writer_put_ue(bit, sps->crop.left / SubWidthC[sps->chroma_format_idc]); + /* frame_crop_right_offset */ + mpp_writer_put_ue(bit, sps->crop.right / SubWidthC[sps->chroma_format_idc]); + /* frame_crop_top_offset */ + mpp_writer_put_ue(bit, sps->crop.top / SubHeightC[sps->chroma_format_idc]); + /* frame_crop_bottom_offset */ + mpp_writer_put_ue(bit, sps->crop.bottom / SubHeightC[sps->chroma_format_idc]); + } + + /* vui_parameters_present_flag */ + mpp_writer_put_bits(bit, sps->vui.vui_en, 1); + if (sps->vui.vui_en) { + H264eVui *vui = &sps->vui; + + /* aspect_ratio_info_present_flag */ + mpp_writer_put_bits(bit, vui->aspect_ratio_info_present, 1); + if (vui->aspect_ratio_info_present) { + /* aspect_ratio_idc */ + mpp_writer_put_bits(bit, vui->aspect_ratio_idc, 8); + if (H264_EXTENDED_SAR == vui->aspect_ratio_idc) { + /* sar_width */ + mpp_writer_put_bits(bit, vui->sar_width, 16); + /* sar_height */ + mpp_writer_put_bits(bit, vui->sar_height, 16); + } + } + + /* overscan_info_present */ + mpp_writer_put_bits(bit, vui->overscan_info_present, 1); + if (vui->overscan_info_present) { + /* overscan_appropriate_flag */ + mpp_writer_put_bits(bit, vui->overscan_appropriate_flag, 1); + } + + /* video_signal_type_present_flag */ + mpp_writer_put_bits(bit, vui->signal_type_present, 1); + if (vui->signal_type_present) { + /* video_format */ + mpp_writer_put_bits(bit, vui->vidformat, 3); + /* video_full_range_flag */ + mpp_writer_put_bits(bit, vui->fullrange, 1); + /* colour_description_present_flag */ + mpp_writer_put_bits(bit, vui->color_description_present, 1); + if (vui->color_description_present) { + /* colour_primaries */ + mpp_writer_put_bits(bit, vui->colorprim, 8); + /* transfer_characteristics */ + mpp_writer_put_bits(bit, vui->colortrc, 8); + /* matrix_coefficients */ + mpp_writer_put_bits(bit, vui->colmatrix, 8); + } + } + + /* chroma_loc_info_present_flag */ + mpp_writer_put_bits(bit, vui->chroma_loc_info_present, 1); + if (vui->chroma_loc_info_present) { + /* chroma_sample_loc_type_top_field */ + mpp_writer_put_ue(bit, vui->chroma_loc_top); + /* chroma_sample_loc_type_bottom_field */ + mpp_writer_put_ue(bit, vui->chroma_loc_bottom); + } + + /* timing_info_present_flag */ + mpp_writer_put_bits(bit, vui->timing_info_present, 1); + if (vui->timing_info_present) { + /* num_units_in_tick msb */ + mpp_writer_put_bits(bit, vui->num_units_in_tick >> 16, 16); + /* num_units_in_tick lsb */ + mpp_writer_put_bits(bit, vui->num_units_in_tick & 0xffff, 16); + /* time_scale msb */ + mpp_writer_put_bits(bit, vui->time_scale >> 16, 16); + /* time_scale lsb */ + mpp_writer_put_bits(bit, vui->time_scale & 0xffff, 16); + /* fixed_frame_rate_flag */ + mpp_writer_put_bits(bit, vui->fixed_frame_rate, 1); + } + + /* nal_hrd_parameters_present_flag */ + mpp_writer_put_bits(bit, vui->nal_hrd_parameters_present, 1); + /* vcl_hrd_parameters_present_flag */ + mpp_writer_put_bits(bit, vui->vcl_hrd_parameters_present, 1); + /* pic_struct_present_flag */ + mpp_writer_put_bits(bit, vui->pic_struct_present, 1); + + /* bit_stream_restriction_flag */ + mpp_writer_put_bits(bit, vui->bitstream_restriction, 1); + if (vui->bitstream_restriction) { + /* motion_vectors_over_pic_boundaries */ + mpp_writer_put_bits(bit, vui->motion_vectors_over_pic_boundaries, 1); + /* max_bytes_per_pic_denom */ + mpp_writer_put_ue(bit, vui->max_bytes_per_pic_denom); + /* max_bits_per_mb_denom */ + mpp_writer_put_ue(bit, vui->max_bits_per_mb_denom); + /* log2_mv_length_horizontal */ + mpp_writer_put_ue(bit, vui->log2_max_mv_length_horizontal); + /* log2_mv_length_vertical */ + mpp_writer_put_ue(bit, vui->log2_max_mv_length_vertical); + /* num_reorder_frames */ + mpp_writer_put_ue(bit, vui->num_reorder_frames); + /* max_dec_frame_buffering */ + mpp_writer_put_ue(bit, vui->max_dec_frame_buffering); + } + } + + mpp_writer_trailing(bit); + + sps_size = mpp_writer_bytes(bit); + if (len) + *len = sps_size; + if (offset) + *offset = length; + + mpp_packet_set_length(packet, length + sps_size); + + return MPP_OK; +} + +MPP_RET h264e_sps_dump(H264eSps *sps) +{ + (void) sps; + return MPP_OK; +} diff --git a/mpp/codec/enc/h264/h264e_sps.h b/mpp/codec/enc/h264/h264e_sps.h new file mode 100644 index 000000000..b20933205 --- /dev/null +++ b/mpp/codec/enc/h264/h264e_sps.h @@ -0,0 +1,137 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_SPS_H +#define H264E_SPS_H + +#include "mpp_packet.h" +#include "mpp_enc_cfg.h" + +#include "h264_syntax.h" + +typedef struct H264eVui_t { + RK_U32 vui_en; + + RK_S32 aspect_ratio_info_present; + RK_S32 aspect_ratio_idc; + RK_S32 sar_width; + RK_S32 sar_height; + + RK_S32 overscan_info_present; + RK_S32 overscan_appropriate_flag; + + RK_S32 signal_type_present; + RK_S32 vidformat; + RK_S32 fullrange; + RK_S32 color_description_present; + RK_S32 colorprim; + RK_S32 colortrc; + RK_S32 colmatrix; + + RK_S32 chroma_loc_info_present; + RK_S32 chroma_loc_top; + RK_S32 chroma_loc_bottom; + + RK_S32 timing_info_present; + RK_U32 num_units_in_tick; + RK_U32 time_scale; + RK_S32 fixed_frame_rate; + + RK_S32 nal_hrd_parameters_present; + RK_S32 vcl_hrd_parameters_present; + + struct { + RK_S32 cpb_cnt; + RK_S32 bit_rate_scale; + RK_S32 cpb_size_scale; + RK_S32 bit_rate_value; + RK_S32 cpb_size_value; + RK_S32 bit_rate_unscaled; + RK_S32 cpb_size_unscaled; + RK_S32 cbr_hrd; + + RK_S32 initial_cpb_removal_delay_length; + RK_S32 cpb_removal_delay_length; + RK_S32 dpb_output_delay_length; + RK_S32 time_offset_length; + } hrd; + + RK_S32 pic_struct_present; + RK_S32 bitstream_restriction; + RK_S32 motion_vectors_over_pic_boundaries; + RK_S32 max_bytes_per_pic_denom; + RK_S32 max_bits_per_mb_denom; + RK_S32 log2_max_mv_length_horizontal; + RK_S32 log2_max_mv_length_vertical; + RK_S32 num_reorder_frames; + RK_S32 max_dec_frame_buffering; +} H264eVui; + +typedef struct H264eSps_t { + RK_S32 profile_idc; + + RK_S32 constraint_set0; + RK_S32 constraint_set1; + RK_S32 constraint_set2; + RK_S32 constraint_set3; + RK_S32 constraint_set4; + RK_S32 constraint_set5; + + RK_S32 level_idc; + RK_U32 sps_id; + + RK_S32 chroma_format_idc; + /* scaling list is in pps */ + + RK_S32 log2_max_frame_num_minus4; + RK_S32 pic_order_cnt_type; + /* poc type 0 */ + RK_S32 log2_max_poc_lsb_minus4; + + RK_S32 num_ref_frames; + RK_S32 gaps_in_frame_num_value_allowed; + RK_S32 pic_width_in_mbs; + RK_S32 pic_height_in_mbs; + + // alway frame encoding + RK_S32 frame_mbs_only; + RK_S32 direct8x8_inference; + + RK_S32 cropping; + struct { + RK_S32 left; + RK_S32 right; + RK_S32 top; + RK_S32 bottom; + } crop; + + H264eVui vui; +} H264eSps; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h264e_sps_update(H264eSps *sps, MppEncCfgSet *cfg); +MPP_RET h264e_sps_to_packet(H264eSps *sps, MppPacket packet, RK_S32 *offset, + RK_S32 *len, MppEncCfgSet *cfg); +MPP_RET h264e_sps_dump(H264eSps *sps); + +#ifdef __cplusplus +} +#endif + +#endif /* H264E_SPS_H */ diff --git a/mpp/codec/enc/h265/CMakeLists.txt b/mpp/codec/enc/h265/CMakeLists.txt new file mode 100644 index 000000000..1d0a31d1c --- /dev/null +++ b/mpp/codec/enc/h265/CMakeLists.txt @@ -0,0 +1,14 @@ +# vim: syntax=cmake +include_directories(.) + +# h265 encoder sourse +add_library(h265e_api OBJECT + h265e_api.c + h265e_dpb.c + h265e_ps.c + h265e_slice.c + h265e_header_gen.c + h265e_stream.c + h265e_syntax.c + h265e_enctropy.c + ) diff --git a/mpp/codec/enc/h265/h265e_api.c b/mpp/codec/enc/h265/h265e_api.c new file mode 100644 index 000000000..8f65bdd09 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_api.c @@ -0,0 +1,462 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_api" + +#include +#include + +#include "mpp_common.h" +#include "mpp_env.h" +#include "mpp_mem.h" + +#include "mpp_soc.h" +#include "mpp_enc_cfg.h" +#include "mpp_packet_impl.h" +#include "mpp_enc_impl.h" + +#include "h265e_api.h" +#include "h265e_codec.h" +#include "h265e_ps.h" +#include "h265e_header_gen.h" +#include "h265e_slice.h" + +RK_U32 h265e_debug = 0; + +static MPP_RET h265e_init(void *ctx, EncImplCfg *ctrlCfg) +{ + H265eCtx *p = (H265eCtx *)ctx; + MPP_RET ret = MPP_OK; + MppEncRcCfg *rc_cfg = &ctrlCfg->cfg->rc; + MppEncPrepCfg *prep = &ctrlCfg->cfg->prep; + MppEncH265Cfg *h265 = NULL; + RockchipSocType soc_type; + + if (ctx == NULL) { + mpp_err_f("invalid NULL ctx\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_env_get_u32("h265e_debug", &h265e_debug, 0); + h265e_dbg_func("enter ctx %p\n", ctx); + + mpp_assert(ctrlCfg->coding == MPP_VIDEO_CodingHEVC); + p->cfg = ctrlCfg->cfg; + + memset(&p->syntax, 0, sizeof(p->syntax)); + + p->extra_info = mpp_calloc(H265eExtraInfo, 1); + + h265e_init_extra_info(p->extra_info); + /* set defualt value of codec */ + h265 = &p->cfg->h265; + h265->intra_qp = 26; + h265->qpmap_mode = 1; + + h265->profile = MPP_PROFILE_HEVC_MAIN; + h265->level = 120; + h265->const_intra_pred = 0; /* constraint intra prediction flag */ + + soc_type = mpp_get_soc_type(); + if (soc_type == ROCKCHIP_SOC_RK3528 || + soc_type == ROCKCHIP_SOC_RK3576 || + soc_type == ROCKCHIP_SOC_RV1126B || + soc_type == ROCKCHIP_SOC_RK3572) + h265->max_cu_size = 32; + else + h265->max_cu_size = 64; + + h265->tmvp_enable = 0; + h265->amp_enable = 0; + h265->sao_enable = 1; + + h265->num_ref = 1; + + h265->slice_cfg.split_enable = 0; + h265->entropy_cfg.cabac_init_flag = 1; + h265->sao_cfg.slice_sao_chroma_disable = 0; + h265->sao_cfg.slice_sao_luma_disable = 0; + h265->sao_cfg.sao_bit_ratio = 5; + h265->dblk_cfg.slice_deblocking_filter_disabled_flag = 0; + h265->cu_cfg.strong_intra_smoothing_enabled_flag = 1; + h265->merge_cfg.max_mrg_cnd = 2; + h265->merge_cfg.merge_left_flag = 1; + h265->merge_cfg.merge_up_flag = 1; + h265->trans_cfg.diff_cu_qp_delta_depth = 0; + h265->vui.vui_en = 1; + p->cfg->tune.scene_mode = MPP_ENC_SCENE_MODE_DEFAULT; + p->cfg->tune.lambda_idx_i = 2; + p->cfg->tune.lambda_idx_p = 4; + p->cfg->tune.anti_flicker_str = 2; + p->cfg->tune.atr_str_i = 3; + p->cfg->tune.atr_str_p = 0; + p->cfg->tune.atl_str = 1; + p->cfg->tune.sao_str_i = 0; + p->cfg->tune.sao_str_p = 1; + p->cfg->tune.deblur_str = 3; + p->cfg->tune.deblur_en = 0; + p->cfg->tune.rc_container = 0; + p->cfg->tune.vmaf_opt = 0; + + /* smart v3 parameters */ + p->cfg->tune.bg_delta_qp_i = -10; + p->cfg->tune.bg_delta_qp_p = -10; + p->cfg->tune.fg_delta_qp_i = 3; + p->cfg->tune.fg_delta_qp_p = 1; + p->cfg->tune.bmap_qpmin_i = 30; + p->cfg->tune.bmap_qpmin_p = 30; + p->cfg->tune.bmap_qpmax_i = 45; + p->cfg->tune.bmap_qpmax_p = 47; + p->cfg->tune.min_bg_fqp = 30; + p->cfg->tune.max_bg_fqp = 45; + p->cfg->tune.min_fg_fqp = 25; + p->cfg->tune.max_fg_fqp = 35; + + /* + * default prep: + * 720p + * YUV420SP + */ + prep->width = 1280; + prep->height = 720; + prep->hor_stride = 1280; + prep->ver_stride = 720; + prep->format = MPP_FMT_YUV420SP; + prep->color = MPP_FRAME_SPC_UNSPECIFIED; + prep->colorprim = MPP_FRAME_PRI_UNSPECIFIED; + prep->colortrc = MPP_FRAME_TRC_UNSPECIFIED; + prep->range = MPP_FRAME_RANGE_UNSPECIFIED; + prep->rotation = MPP_ENC_ROT_0; + prep->rotation_ext = MPP_ENC_ROT_0; + prep->mirroring = 0; + prep->mirroring_ext = 0; + prep->denoise = 0; + prep->flip = 0; + + /* + * default rc_cfg: + * CBR + * 2Mbps +-25% + * 30fps + * gop 60 + */ + rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM; + rc_cfg->bps_target = 2000 * 1000; + rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4; + rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4; + rc_cfg->fps_in_flex = 0; + rc_cfg->fps_in_num = 30; + rc_cfg->fps_in_denom = 1; + rc_cfg->fps_out_flex = 0; + rc_cfg->fps_out_num = 30; + rc_cfg->fps_out_denom = 1; + rc_cfg->gop = 60; + rc_cfg->max_reenc_times = 1; + rc_cfg->max_i_prop = 30; + rc_cfg->min_i_prop = 10; + rc_cfg->init_ip_ratio = 160; + rc_cfg->qp_init = 26; + rc_cfg->qp_max = 51; + rc_cfg->qp_min = 10; + rc_cfg->qp_max_i = 51; + rc_cfg->qp_min_i = 15; + rc_cfg->qp_delta_ip = 4; + rc_cfg->qp_delta_vi = 2; + rc_cfg->fqp_min_i = INT_MAX; + rc_cfg->fqp_min_p = INT_MAX; + rc_cfg->fqp_max_i = INT_MAX; + rc_cfg->fqp_max_p = INT_MAX; + + h265e_dbg_func("leave ctx %p\n", ctx); + return ret; +} + +static MPP_RET h265e_deinit(void *ctx) +{ + H265eCtx *p = (H265eCtx *)ctx; + + h265e_dbg_func("enter ctx %p\n", ctx); + + if (ctx == NULL) { + mpp_err_f("invalid NULL ctx\n"); + return MPP_ERR_NULL_PTR; + } + + h265e_deinit_extra_info(p->extra_info); + + MPP_FREE(p->extra_info); + + h265e_dpb_deinit(p->dpb); + + h265e_dbg_func("leave ctx %p\n", ctx); + return MPP_OK; +} + +static MPP_RET h265e_gen_hdr(void *ctx, MppPacket pkt) +{ + H265eCtx *p = (H265eCtx *)ctx; + + h265e_dbg_func("enter ctx %p\n", ctx); + + h265e_set_extra_info(p); + h265e_get_extra_info(p, pkt); + + if (NULL == p->dpb) + h265e_dpb_init(&p->dpb); + + h265e_dbg_func("leave ctx %p\n", ctx); + + return MPP_OK; +} + +static MPP_RET h265e_start(void *ctx, HalEncTask *task) +{ + h265e_dbg_func("enter\n"); + + if (mpp_frame_has_meta(task->frame)) { + MppEncRefFrmUsrCfg *frm_cfg = task->frm_cfg; + EncRcForceCfg *rc_force = &task->rc_task->force; + MppMeta meta = mpp_frame_get_meta(task->frame); + RK_S32 force_lt_idx = -1; + RK_S32 force_use_lt_idx = -1; + RK_S32 force_frame_qp = -1; + RK_S32 base_layer_pid = -1; + RK_S32 force_tid = -1; + + mpp_meta_get_s32(meta, KEY_ENC_MARK_LTR, &force_lt_idx); + mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &force_use_lt_idx); + mpp_meta_get_s32(meta, KEY_ENC_FRAME_QP, &force_frame_qp); + mpp_meta_get_s32(meta, KEY_ENC_BASE_LAYER_PID, &base_layer_pid); + mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &force_tid); + + if (force_lt_idx >= 0) { + frm_cfg->force_flag |= ENC_FORCE_LT_REF_IDX; + frm_cfg->force_lt_idx = force_lt_idx; + } + + if (force_use_lt_idx >= 0) { + frm_cfg->force_flag |= ENC_FORCE_REF_MODE; + frm_cfg->force_ref_mode = REF_TO_LT_REF_IDX; + frm_cfg->force_ref_arg = force_use_lt_idx; + } + + if (force_tid >= 0) { + frm_cfg->force_flag |= ENC_FORCE_TEMPORAL_ID; + frm_cfg->force_temporal_id = force_tid; + } + + if (force_frame_qp >= 0) { + rc_force->force_flag = ENC_RC_FORCE_QP; + rc_force->force_qp = force_frame_qp; + } else { + rc_force->force_flag &= (~ENC_RC_FORCE_QP); + rc_force->force_qp = -1; + } + + if (base_layer_pid >= 0) { + H265eCtx *p = (H265eCtx *)ctx; + MppEncH265Cfg *h265 = &p->cfg->h265; + + h265->base_layer_pid = base_layer_pid; + } + } + + /* + * Step 2: Fps conversion + * + * Determine current frame which should be encoded or not according to + * input and output frame rate. + */ + + if (!task->valid) + mpp_log_f("drop one frame\n"); + + /* + * Step 3: Backup dpb for reencode + */ + //h265e_dpb_copy(&p->dpb_bak, p->dpb); + h265e_dbg_func("leave\n"); + + return MPP_OK; +} + +static MPP_RET h265e_proc_dpb(void *ctx, HalEncTask *task) +{ + H265eCtx *p = (H265eCtx *)ctx; + EncRcTask *rc_task = task->rc_task; + EncCpbStatus *cpb = &task->rc_task->cpb; + + h265e_dbg_func("enter\n"); + h265e_dpb_proc_cpb(p->dpb, cpb); + h265e_dpb_get_curr(p->dpb); + h265e_slice_init(ctx, cpb->curr); + h265e_dpb_build_list(p->dpb, cpb); + + rc_task->frm = p->dpb->curr->status; + + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET h265e_proc_hal(void *ctx, HalEncTask *task) +{ + H265eCtx *p = (H265eCtx *)ctx; + MppEncH265Cfg *h265 = &p->cfg->h265; + + if (ctx == NULL) { + mpp_err_f("invalid NULL ctx\n"); + return MPP_ERR_NULL_PTR; + } + + /* check max temporal layer id */ + { + MppEncCpbInfo *cpb_info = mpp_enc_ref_cfg_get_cpb_info(p->cfg->ref_cfg); + RK_S32 cpb_max_tid = cpb_info->max_st_tid; + RK_S32 cfg_max_tid = h265->max_tid; + + if (cpb_max_tid != cfg_max_tid) { + mpp_log("max tid is update to match cpb %d -> %d\n", + cfg_max_tid, cpb_max_tid); + h265->max_tid = cpb_max_tid; + } + } + + if (h265->max_tid) { + EncFrmStatus *frm = &task->rc_task->frm; + MppPacket packet = task->packet; + MppMeta meta = mpp_packet_get_meta(packet); + + mpp_meta_set_s32(meta, KEY_TEMPORAL_ID, frm->temporal_id); + if (!frm->is_non_ref && frm->is_lt_ref) + mpp_meta_set_s32(meta, KEY_LONG_REF_IDX, frm->lt_idx); + } + + h265e_dbg_func("enter ctx %p \n", ctx); + + h265e_syntax_fill(ctx); + + task->valid = 1; + task->syntax.number = 1; + task->syntax.data = &p->syntax; + + h265e_dbg_func("leave ctx %p \n", ctx); + return MPP_OK; +} + +static MPP_RET h265e_proc_enc_skip(void *ctx, HalEncTask *task) +{ + H265eCtx *p = (H265eCtx *)ctx; + MppPacket pkt = task->packet; + H265eSyntax_new *syntax = &p->syntax; + RK_U8 *ptr = mpp_packet_get_pos(pkt); + RK_U32 offset = mpp_packet_get_length(pkt); + RK_U32 len = mpp_packet_get_size(pkt) - offset; + RK_U32 new_length = 0; + + h265e_dbg_func("enter\n"); + ptr += offset; + p->slice->m_sliceQp = task->rc_task->info.quality_target; + new_length = h265e_code_slice_skip_frame(ctx, p->slice, ptr, len); + task->length = new_length; + task->rc_task->info.bit_real = 8 * new_length; + p->dpb->curr->prev_ref_idx = syntax->sp.recon_pic.slot_idx; + mpp_packet_add_segment_info(pkt, NAL_TRAIL_R, offset, new_length); + mpp_buffer_sync_partial_end(mpp_packet_get_buffer(pkt), offset, new_length); + + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET h265e_add_sei(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16], + const void *data, RK_S32 size) +{ + RK_U8 *ptr = mpp_packet_get_pos(pkt); + RK_U32 offset = mpp_packet_get_length(pkt); + RK_U32 new_length = 0; + + ptr += offset; + + if (uuid == uuid_refresh_cfg) { + RK_U32 recovery_frame_cnt = ((RK_U32 *)data)[0] - 1; + new_length = h265e_sei_recovery_point(ptr, uuid, &recovery_frame_cnt, 0); + } else { + new_length = h265e_data_to_sei(ptr, uuid, data, size); + } + *length = new_length; + + mpp_packet_set_length(pkt, offset + new_length); + mpp_packet_add_segment_info(pkt, NAL_SEI_PREFIX, offset, new_length); + + return MPP_OK; +} + +static MPP_RET h265e_proc_cfg(void *ctx, MpiCmd cmd, void *param) +{ + H265eCtx *p = (H265eCtx *)ctx; + MppEncCfgSet *cfg = p->cfg; + MPP_RET ret = MPP_OK; + + h265e_dbg_func("enter ctx %p cmd %08x\n", ctx, cmd); + + switch (cmd) { + case MPP_ENC_SET_CFG : { + } break; + case MPP_ENC_GET_EXTRA_INFO: { + MppPacket pkt_out = (MppPacket )param; + h265e_set_extra_info(p); + h265e_get_extra_info(p, pkt_out); + } break; + case MPP_ENC_SET_SEI_CFG: { + } break; + case MPP_ENC_SET_SPLIT : { + MppEncSliceSplit *src = (MppEncSliceSplit *)param; + MppEncH265SliceCfg *slice_cfg = &cfg->h265.slice_cfg; + + if (src->split_mode > MPP_ENC_SPLIT_NONE) { + slice_cfg->split_enable = 1; + slice_cfg->split_mode = 0; + if (src->split_mode == MPP_ENC_SPLIT_BY_CTU) + slice_cfg->split_mode = 1; + slice_cfg->slice_size = src->split_arg; + } else { + slice_cfg->split_enable = 0; + } + } break; + default: + mpp_err("No correspond %08x found, and can not config!\n", cmd); + ret = MPP_NOK; + break; + } + + h265e_dbg_func("leave ctx %p\n", ctx); + return ret; +} + +const EncImplApi api_h265e = { + "h265e_control", + MPP_VIDEO_CodingHEVC, + sizeof(H265eCtx), + 0, + h265e_init, + h265e_deinit, + h265e_proc_cfg, + h265e_gen_hdr, + h265e_start, + h265e_proc_dpb, + h265e_proc_hal, + h265e_add_sei, + h265e_proc_enc_skip, +}; diff --git a/mpp/codec/enc/h265/h265e_codec.h b/mpp/codec/enc/h265/h265e_codec.h new file mode 100644 index 000000000..25d17fa80 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_codec.h @@ -0,0 +1,53 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef H265E_CODEC_H +#define H265E_CODEC_H + +#include "mpp_debug.h" + +#define H265E_DBG_FUNCTION (0x00000001) +#define H265E_DBG_INPUT (0x00000010) +#define H265E_DBG_OUTPUT (0x00000020) +#define H265E_DBG_PS (0x00000040) +#define H265E_DBG_DPB (0x00000080) +#define H265E_DBG_DPB_REF (0x000000c0) + +#define H265E_DBG_SLICE (0x00000100) +#define H265E_DBG_HEADER (0x00000200) +#define H265E_DBG_API (0x00000400) +#define H265E_DBG_SKIP (0x00000800) + +#define H265E_PS_BUF_SIZE 512 +#define H265E_SEI_BUF_SIZE 1024 +#define H265E_EXTRA_INFO_BUF_SIZE (H265E_PS_BUF_SIZE + H265E_SEI_BUF_SIZE) + +extern RK_U32 h265e_debug; + +#define h265e_dbg(flag, fmt, ...) mpp_dbg(h265e_debug, flag, fmt, ## __VA_ARGS__) +#define h265e_dbg_f(flag, fmt, ...) mpp_dbg_f(h265e_debug, flag, fmt, ## __VA_ARGS__) + +#define h265e_dbg_func(fmt, ...) h265e_dbg_f(H265E_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define h265e_dbg_input(fmt, ...) h265e_dbg(H265E_DBG_INPUT, fmt, ## __VA_ARGS__) +#define h265e_dbg_output(fmt, ...) h265e_dbg(H265E_DBG_OUTPUT, fmt, ## __VA_ARGS__) + +#define h265e_dbg_ps(fmt, ...) h265e_dbg(H265E_DBG_PS, fmt, ## __VA_ARGS__) +#define h265e_dbg_dpb(fmt, ...) h265e_dbg(H265E_DBG_DPB, fmt, ## __VA_ARGS__) +#define h265e_dbg_slice(fmt, ...) h265e_dbg(H265E_DBG_SLICE, fmt, ## __VA_ARGS__) +#define h265e_dbg_skip(fmt, ...) h265e_dbg(H265E_DBG_SKIP, fmt, ## __VA_ARGS__) + +#define h265e_dbg_dpb_ref(fmt, ...) h265e_dbg(H265E_DBG_DPB_REF, fmt, ## __VA_ARGS__) + +#endif diff --git a/mpp/codec/enc/h265/h265e_context_table.h b/mpp/codec/enc/h265/h265e_context_table.h new file mode 100644 index 000000000..55c970c5a --- /dev/null +++ b/mpp/codec/enc/h265/h265e_context_table.h @@ -0,0 +1,64 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_CONTEXT_TABLE_H +#define H265E_CONTEXT_TABLE_H + +#include "rk_type.h" + +#define NUM_SPLIT_FLAG_CTX 3 ///< number of context models for split flag +#define NUM_SKIP_FLAG_CTX 3 ///< number of context models for skip flag +#define NUM_MERGE_FLAG_EXT_CTX 1 ///< number of context models for merge flag of merge extended +#define NUM_MERGE_IDX_EXT_CTX 1 ///< number of context models for merge index of merge extended + +#define OFF_SPLIT_FLAG_CTX (0) +#define OFF_SKIP_FLAG_CTX (OFF_SPLIT_FLAG_CTX + NUM_SPLIT_FLAG_CTX)//3 +#define OFF_MERGE_FLAG_EXT_CTX (OFF_SKIP_FLAG_CTX + NUM_SKIP_FLAG_CTX)//3 +#define OFF_MERGE_IDX_EXT_CTX (OFF_MERGE_FLAG_EXT_CTX + NUM_MERGE_FLAG_EXT_CTX)//1 +#define MAX_OFF_CTX_MOD (OFF_MERGE_IDX_EXT_CTX + NUM_MERGE_IDX_EXT_CTX) +#define CNU 154 ///< dummy initialization value for unused context models 'Context model Not Used' + +extern const uint8_t g_nextState[128][2]; + +#define sbacGetMps(S) ((S) & 1) +#define sbacGetState(S) ((S) >> 1) +#define sbacNext(S, V) (g_nextState[(S)][(V)]) + +static const RK_U8 INIT_SPLIT_FLAG[3][NUM_SPLIT_FLAG_CTX] = { + { 107, 139, 126, }, + { 107, 139, 126, }, + { 139, 141, 157, }, +}; + +static const RK_U8 INIT_SKIP_FLAG[3][NUM_SKIP_FLAG_CTX] = { + { 197, 185, 201, }, + { 197, 185, 201, }, + { CNU, CNU, CNU, }, +}; + +static const RK_U8 INIT_MERGE_FLAG_EXT[3][NUM_MERGE_FLAG_EXT_CTX] = { + { 154, }, + { 110, }, + { CNU, }, +}; + +static const RK_U8 INIT_MERGE_IDX_EXT[3][NUM_MERGE_IDX_EXT_CTX] = { + { 137, }, + { 122, }, + { CNU, }, +}; + +#endif /* H265E_CONTEXT_TABLE_H */ \ No newline at end of file diff --git a/mpp/codec/enc/h265/h265e_dpb.c b/mpp/codec/enc/h265/h265e_dpb.c new file mode 100644 index 000000000..b033cb823 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_dpb.c @@ -0,0 +1,947 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_dpb" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "h265e_codec.h" +#include "h265e_dpb.h" +#include "h265e_slice.h" + +void h265e_dpb_dump_frm(H265eDpb *dpb, const char *fmt) +{ + RK_S32 i = 0; + char buf[256]; + RK_S32 pos = 0; + RK_S32 frm_cnt = MPP_ARRAY_ELEMS(dpb->frame_list); + + pos += snprintf(buf, sizeof(buf) - 1, "total %2d ", frm_cnt); + + for (i = 0; i < frm_cnt; i++) { + H265eDpbFrm *frm = &dpb->frame_list[i]; + + pos += snprintf(buf + pos, sizeof(buf) - 1 - pos, "%04x ", frm->on_used); + } + mpp_log("%20s %s", fmt, buf); +} + +MPP_RET calc_ref_pic_set_idxl0(H265eDpb *dpb, H265eSlice *slice, RK_S32 ref_idx) +{ + H265eReferencePictureSet * rps = (H265eReferencePictureSet*)&slice->m_localRPS; + H265eDpbFrm *frame_list = dpb->frame_list; + H265eRpsList *RpsList = &dpb->RpsList; + RK_S32 poc_idx = rps->m_RealPoc[ref_idx]; + H265eDpbFrm* refPicSetLtCurr[MAX_REFS]; + H265eDpbFrm* refPic = NULL; + RK_S32 numPocLtCurr = 0; + RK_S32 i = 0; + + for (i = rps->num_negative_pic + rps->num_positive_pic + rps->num_long_term_pic - 1; + i > rps->num_negative_pic + rps->num_positive_pic - 1; i--) { + if (rps->m_used[i]) { + refPic = get_lt_ref_pic(frame_list, slice, rps->m_RealPoc[i], rps->check_lt_msb[i]); + refPicSetLtCurr[numPocLtCurr] = refPic; + numPocLtCurr++; + } + } + + RpsList->m_RefPicListModification->m_RefPicSetIdxL0[0] = ref_idx; + for (i = 0; i < numPocLtCurr; i++) { + if (poc_idx == refPicSetLtCurr[i]->poc) + RpsList->m_RefPicListModification->m_RefPicSetIdxL0[0] = rps->m_numberOfPictures - rps->num_long_term_pic + i; + } + + return MPP_OK; +} + +void h265e_dpb_set_ref_list(H265eDpb *dpb, H265eSlice *slice, RK_S32 delta_poc) +{ + RK_S32 i; + RK_S32 ref_idx = -1; + RK_S32 lt_cnt = 0, st_cnt = 0; + H265eRpsList *RpsList = &dpb->RpsList; + H265eReferencePictureSet * m_pRps = (H265eReferencePictureSet*)&slice->m_localRPS; + H265eRefPicListModification* refPicListModification = RpsList->m_RefPicListModification; + + h265e_dbg_func("enter\n"); + refPicListModification->m_refPicListModificationFlagL0 = 0; + refPicListModification->m_refPicListModificationFlagL1 = 0; + + for (i = 0; i < REF_PIC_LIST_NUM_IDX; i ++) { + refPicListModification->m_RefPicSetIdxL0[i] = 0; + refPicListModification->m_RefPicSetIdxL0[i] = 0; + } + + refPicListModification->m_refPicListModificationFlagL0 = 0; + + if (m_pRps->m_numberOfPictures > 1) { + for (i = 0; i < m_pRps->m_numberOfPictures; i++) { + h265e_dbg_dpb("m_pRps->delta_poc[%d] = %d", i, m_pRps->delta_poc[i]); + if (m_pRps->delta_poc[i] == delta_poc) { + ref_idx = i; + if (i > m_pRps->m_numberOfPictures - m_pRps->num_long_term_pic - 1) + lt_cnt++; + else + st_cnt++; + h265e_dbg_dpb("get %s ref ref_idx %d delta_poc %d", (st_cnt != 0) ? "st" : "lt", ref_idx, delta_poc); + } + } + if (lt_cnt != 1 && st_cnt == 0) { + mpp_err("Warning: Did not find the right long term reference picture or more than one."); + return; + } else if (ref_idx != 0) { + refPicListModification->m_refPicListModificationFlagL0 = 1; + calc_ref_pic_set_idxl0(dpb, slice, ref_idx); + } + } + refPicListModification->m_refPicListModificationFlagL1 = 0; + h265e_dbg_func("leave\n"); +} + +/* get buffer at init */ +MPP_RET h265e_dpb_init_curr(H265eDpb *dpb, H265eDpbFrm *frm) +{ + h265e_dbg_func("enter\n"); + mpp_assert(!frm->on_used); + + frm->dpb = dpb; + + if (!frm->slice) { + frm->slice = mpp_calloc(H265eSlice, 1); + } + + frm->inited = 1; + frm->dpb_used = 1; + frm->seq_idx = dpb->seq_idx; + dpb->seq_idx++; + + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +MPP_RET h265e_dpb_get_curr(H265eDpb *dpb) +{ + RK_U32 i; + + h265e_dbg_func("enter\n"); + for (i = 0; i < MPP_ARRAY_ELEMS(dpb->frame_list); i++) { + if (!dpb->frame_list[i].on_used) { + dpb->curr = &dpb->frame_list[i]; + h265e_dbg_dpb("get free dpb slot_index %d", dpb->curr->slot_idx); + break; + } + } + h265e_dpb_init_curr(dpb, dpb->curr); + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +/* put buffer at deinit */ +MPP_RET h265e_dpb_frm_deinit(H265eDpbFrm *frm) +{ + MPP_FREE(frm->slice); + frm->inited = 0; + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +MPP_RET h265e_dpb_init(H265eDpb **dpb) +{ + MPP_RET ret = MPP_OK; + H265eDpb *p = NULL; + RK_U32 i; + + h265e_dbg_func("enter\n"); + if (NULL == dpb) { + mpp_err_f("invalid parameter %p \n", dpb); + return MPP_ERR_VALUE; + } + + p = mpp_calloc_size(H265eDpb, sizeof(H265eDpb)); + + if (NULL == p) + return MPP_ERR_MALLOC; + + p->last_idr = 0; + p->poc_cra = 0; + p->max_ref_l0 = 1; + p->max_ref_l1 = 0; + + H265eRpsList *rps_list = &p->RpsList; + + rps_list->lt_num = 0; + rps_list->st_num = 0; + + memset(rps_list->poc, 0, sizeof(rps_list->poc)); + + rps_list->m_RefPicListModification = mpp_calloc(H265eRefPicListModification, 1); + + + for (i = 0; i < MPP_ARRAY_ELEMS(p->frame_list); i++) + p->frame_list[i].slot_idx = i; + + mpp_assert(dpb); + *dpb = p; + h265e_dbg_func("leave\n"); + return ret; +} + +MPP_RET h265e_dpb_deinit(H265eDpb *dpb) +{ + RK_U32 i; + + if (NULL == dpb) + return MPP_OK; + + h265e_dbg_func("enter\n"); + for (i = 0; i < MPP_ARRAY_ELEMS(dpb->frame_list); i++) { + if (dpb->frame_list[i].inited) + h265e_dpb_frm_deinit(&dpb->frame_list[i]); + } + + MPP_FREE(dpb->RpsList.m_RefPicListModification); + + MPP_FREE(dpb); + + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +enum NALUnitType get_nal_unit_type(H265eDpb *dpb, int curPOC) +{ + h265e_dbg_func("enter\n"); + if (curPOC == 0) { + return NAL_IDR_W_RADL; + } + if (dpb->curr->is_key_frame) { + return NAL_IDR_W_RADL; + } + if (dpb->poc_cra > 0) { + if (curPOC < dpb->poc_cra) { + // All leading pictures are being marked as TFD pictures here since current encoder uses all + // reference pictures while encoding leading pictures. An encoder can ensure that a leading + // picture can be still decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by + // controlling the reference pictures used for encoding that leading picture. Such a leading + // picture need not be marked as a TFD picture. + return NAL_RASL_R; + } + } + if (dpb->last_idr > 0) { + if (curPOC < dpb->last_idr) { + return NAL_RADL_R; + } + } + + h265e_dbg_func("leave\n"); + return NAL_TRAIL_R; +} + +static inline int getLSB(int poc, int maxLSB) +{ + if (poc >= 0) { + return poc % maxLSB; + } else { + return (maxLSB - ((-poc) % maxLSB)) % maxLSB; + } +} + +void sort_delta_poc(H265eReferencePictureSet *rps) +{ + // sort in increasing order (smallest first) + RK_S32 j, k; + for (j = 1; j < rps->m_numberOfPictures; j++) { + RK_S32 deltaPOC = rps->delta_poc[j]; + RK_U32 used = rps->m_used[j]; + RK_U32 refed = rps->m_ref[j]; + + for (k = j - 1; k >= 0; k--) { + int temp = rps->delta_poc[k]; + if (deltaPOC < temp) { + rps->delta_poc[k + 1] = temp; + rps->m_used[k + 1] = rps->m_used[k]; + rps->m_ref[k + 1] = rps->m_ref[k]; + rps->delta_poc[k] = deltaPOC; + rps->m_used[k] = used; + rps->m_ref[k] = refed; + } + } + } + + // flip the negative values to largest first + RK_S32 numNegPics = rps->num_negative_pic; + for (j = 0, k = numNegPics - 1; j < numNegPics >> 1; j++, k--) { + RK_S32 deltaPOC = rps->delta_poc[j]; + RK_U32 used = rps->m_used[j]; + RK_U32 refed = rps->m_ref[j]; + rps->delta_poc[j] = rps->delta_poc[k]; + rps->m_used[j] = rps->m_used[k]; + rps->m_ref[j] = rps->m_ref[k]; + rps->delta_poc[k] = deltaPOC; + rps->m_used[k] = used; + rps->m_ref[k] = refed; + } +} + +void h265e_dpb_apply_rps(H265eDpb *dpb, H265eReferencePictureSet *rps, int curPoc) +{ + H265eDpbFrm *outPic = NULL; + RK_S32 i; + // loop through all pictures in the reference picture buffer + RK_U32 index = 0; + H265eDpbFrm *frame_list = &dpb->frame_list[0]; + + h265e_dbg_func("enter\n"); + + for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) { + outPic = &frame_list[index]; + if (!outPic->inited || !outPic->slice->is_referenced) { + continue; + } + + // loop through all pictures in the Reference Picture Set + // to see if the picture should be kept as reference picture + for (i = 0; i < rps->num_positive_pic + rps->num_negative_pic; i++) { + h265e_dbg_dpb("outPic->slice->poc %d,curPoc %d dealt %d", outPic->slice->poc, curPoc, rps->delta_poc[i]); + if (!outPic->is_long_term && outPic->slice->poc == curPoc + rps->delta_poc[i]) { + outPic->used_by_cur = (rps->m_used[i] == 1); + outPic->is_long_term = 0; + } + } + + for (; i < rps->m_numberOfPictures; i++) { + if (rps->check_lt_msb[i] == 0) { + if (outPic->is_long_term && (outPic->slice->poc == rps->m_RealPoc[i])) { + outPic->used_by_cur = (rps->m_used[i] == 1); + } + } else { + if (outPic->is_long_term && (outPic->slice->poc == rps->m_RealPoc[i])) { + outPic->used_by_cur = (rps->m_used[i] == 1); + } + } + } + } + + h265e_dbg_func("leave\n"); +} + +void h265e_dpb_dec_refresh_marking(H265eDpb *dpb, RK_S32 poc_cur, enum NALUnitType nalUnitType) +{ + RK_U32 index = 0; + + h265e_dbg_func("enter\n"); + + if (nalUnitType == NAL_BLA_W_LP + || nalUnitType == NAL_BLA_W_RADL + || nalUnitType == NAL_BLA_N_LP + || nalUnitType == NAL_IDR_W_RADL + || nalUnitType == NAL_IDR_N_LP) { // IDR or BLA picture + // mark all pictures as not used for reference + H265eDpbFrm *frame_List = &dpb->frame_list[0]; + for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) { + H265eDpbFrm *frame = &frame_List[index]; + if (frame->inited && (frame->poc != poc_cur)) { + frame->slice->is_referenced = 0; + frame->is_long_term = 0; + if (frame->poc < poc_cur) { + frame->used_by_cur = 0; + frame->dpb_used = 0; + frame->status.val = 0; + } + } + } + + if (nalUnitType == NAL_BLA_W_LP + || nalUnitType == NAL_BLA_W_RADL + || nalUnitType == NAL_BLA_N_LP) { + dpb->poc_cra = poc_cur; + } + } else { // CRA or No DR + if (dpb->refresh_pending == 1 && poc_cur > dpb->poc_cra) { // CRA reference marking pending + H265eDpbFrm *frame_list = &dpb->frame_list[0]; + for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) { + + H265eDpbFrm *frame = &frame_list[index]; + if (frame->inited && frame->poc != poc_cur && frame->poc != dpb->poc_cra) { + frame->slice->is_referenced = 0; + frame->dpb_used = 0; + } + } + + dpb->refresh_pending = 0; + } + if (nalUnitType == NAL_CRA_NUT) { // CRA picture found + dpb->refresh_pending = 1; + dpb->poc_cra = poc_cur; + } + } + h265e_dbg_func("leave\n"); +} + +// Function will arrange the long-term pictures in the decreasing order of poc_lsb_lt, +// and among the pictures with the same lsb, it arranges them in increasing delta_poc_msb_cycle_lt value +void h265e_dpb_arrange_lt_rps(H265eDpb *dpb, H265eSlice *slice) +{ + H265eReferencePictureSet *rps = slice->m_rps; + RK_U32 tempArray[MAX_REFS]; + RK_S32 offset = rps->num_negative_pic + rps->num_positive_pic; + RK_S32 i, j, ctr = 0; + RK_S32 maxPicOrderCntLSB = 1 << slice->m_sps->m_bitsForPOC; + RK_S32 numLongPics; + RK_S32 currMSB = 0, currLSB = 0; + (void)dpb; + + // Arrange long-term reference pictures in the correct order of LSB and MSB, + // and assign values for pocLSBLT and MSB present flag + RK_S32 longtermPicsPoc[MAX_REFS], longtermPicsLSB[MAX_REFS], indices[MAX_REFS]; + RK_S32 longtermPicsRealPoc[MAX_REFS]; + RK_S32 longtermPicsMSB[MAX_REFS]; + RK_U32 mSBPresentFlag[MAX_REFS]; + + h265e_dbg_func("enter\n"); + if (!rps->num_long_term_pic) { + return; + } + memset(longtermPicsPoc, 0, sizeof(longtermPicsPoc)); // Store POC values of LTRP + memset(longtermPicsLSB, 0, sizeof(longtermPicsLSB)); // Store POC LSB values of LTRP + memset(longtermPicsMSB, 0, sizeof(longtermPicsMSB)); // Store POC LSB values of LTRP + memset(longtermPicsRealPoc, 0, sizeof(longtermPicsRealPoc)); + memset(indices, 0, sizeof(indices)); // Indices to aid in tracking sorted LTRPs + memset(mSBPresentFlag, 0, sizeof(mSBPresentFlag)); // Indicate if MSB needs to be present + + // Get the long-term reference pictures + + for (i = rps->m_numberOfPictures - 1; i >= offset; i--, ctr++) { + longtermPicsPoc[ctr] = rps->poc[i]; // LTRP POC + longtermPicsRealPoc[ctr] = rps->m_RealPoc[i]; + longtermPicsLSB[ctr] = getLSB(longtermPicsPoc[ctr], maxPicOrderCntLSB); // LTRP POC LSB + indices[ctr] = i; + longtermPicsMSB[ctr] = longtermPicsPoc[ctr] - longtermPicsLSB[ctr]; + } + + numLongPics = rps->num_long_term_pic; + mpp_assert(ctr == numLongPics); + + // Arrange pictures in decreasing order of MSB; + for (i = 0; i < numLongPics; i++) { + for (j = 0; j < numLongPics - 1; j++) { + if (longtermPicsMSB[j] < longtermPicsMSB[j + 1]) { + MPP_SWAP(RK_S32, longtermPicsPoc[j], longtermPicsPoc[j + 1]); + MPP_SWAP(RK_S32, longtermPicsRealPoc[j], longtermPicsRealPoc[j + 1]); + MPP_SWAP(RK_S32, longtermPicsLSB[j], longtermPicsLSB[j + 1]); + MPP_SWAP(RK_S32, longtermPicsMSB[j], longtermPicsMSB[j + 1]); + MPP_SWAP(RK_S32, indices[j], indices[j + 1]); + } + } + } + + for (i = 0; i < numLongPics; i++) { + if (slice->gop_idx / maxPicOrderCntLSB > 0) { + mSBPresentFlag[i] = 1; + } + } + + // tempArray for usedByCurr flag + memset(tempArray, 0, sizeof(tempArray)); + for (i = 0; i < numLongPics; i++) { + tempArray[i] = (rps->m_used[indices[i]] != 0) ? 1 : 0; + } + + // Now write the final values; + ctr = 0; + // currPicPoc = currMSB + currLSB + currLSB = getLSB(slice->gop_idx, maxPicOrderCntLSB); + currMSB = slice->gop_idx - currLSB; + + for (i = rps->m_numberOfPictures - 1; i >= offset; i--, ctr++) { + rps->poc[i] = longtermPicsPoc[ctr]; + rps->delta_poc[i] = -slice->poc + longtermPicsRealPoc[ctr]; + + rps->m_used[i] = tempArray[ctr]; + rps->m_pocLSBLT[i] = longtermPicsLSB[ctr]; + rps->m_deltaPOCMSBCycleLT[i] = (currMSB - (longtermPicsPoc[ctr] - longtermPicsLSB[ctr])) / maxPicOrderCntLSB; + rps->m_deltaPocMSBPresentFlag[i] = mSBPresentFlag[ctr]; + + mpp_assert(rps->m_deltaPOCMSBCycleLT[i] >= 0); // Non-negative value + } + + for (i = rps->m_numberOfPictures - 1, ctr = 1; i >= offset; i--, ctr++) { + for (j = rps->m_numberOfPictures - 1 - ctr; j >= offset; j--) { + // Here at the encoder we know that we have set the full POC value for the LTRPs, hence we + // don't have to check the MSB present flag values for this constraint. + mpp_assert(rps->m_RealPoc[i] != rps->m_RealPoc[j]); // If assert fails, LTRP entry repeated in RPS!!! + } + } + + h265e_dbg_func("leave\n"); +} + +static H265eDpbFrm *h265e_find_cpb_in_dpb(H265eDpbFrm *frms, RK_S32 cnt, EncFrmStatus *frm) +{ + RK_S32 seq_idx = frm->seq_idx; + RK_S32 i; + + if (!frm->valid) + return NULL; + + h265e_dbg_dpb("frm %d start finding slot \n", frm->seq_idx); + for (i = 0; i < cnt; i++) { + if (!frms[i].inited) { + continue; + } + EncFrmStatus *p = &frms[i].status; + + if (p->valid && p->seq_idx == seq_idx) { + h265e_dbg_dpb("frm %d match slot %d valid %d\n", + p->seq_idx, i, p->valid); + return &frms[i]; + } + } + mpp_err_f("can not find match frm %d\n", seq_idx); + return NULL; +} + +static H265eDpbFrm *h265e_find_cpb_frame(H265eDpbFrm *frms, RK_S32 cnt, EncFrmStatus *frm) +{ + RK_S32 seq_idx = frm->seq_idx; + RK_S32 i; + + if (!frm->valid) + return NULL; + + h265e_dbg_dpb("frm %d start finding slot \n", frm->seq_idx); + for (i = 0; i < cnt; i++) { + if (!frms[i].dpb_used) { + continue; + } + + EncFrmStatus *p = &frms[i].status; + + if (p->valid && p->seq_idx == seq_idx) { + h265e_dbg_dpb("frm %d match slot %d valid %d\n", + p->seq_idx, i, p->valid); + if (frm->save_pass1) + return &frms[i]; + mpp_assert(p->is_non_ref == frm->is_non_ref); + mpp_assert(p->is_lt_ref == frm->is_lt_ref); + mpp_assert(p->lt_idx == frm->lt_idx); + mpp_assert(p->temporal_id == frm->temporal_id); + return &frms[i]; + } + } + + mpp_err_f("can not find match frm %d\n", seq_idx); + + return NULL; +} + +static MPP_RET h265e_check_frame_cpb(H265eDpbFrm *frm, RK_S32 cnt, EncFrmStatus *frms) +{ + EncFrmStatus *p = &frm->status; + RK_S32 seq_idx, i; + MPP_RET ret = MPP_NOK; + h265e_dbg_func("enter\n"); + + seq_idx = p->seq_idx; + for (i = 0; i < cnt; i++) { + + if (!frms[i].valid) { + continue; + } + + if (frms[i].seq_idx == seq_idx) { + ret = MPP_OK; + } + } + + h265e_dbg_func("leave\n"); + return ret; +} + + +void h265e_dpb_cpb2rps(H265eDpb *dpb, RK_S32 curPoc, H265eSlice *slice, EncCpbStatus *cpb) +{ + h265e_dbg_func("enter\n"); + RK_S32 i; + RK_S32 st_size = 0; + RK_S32 lt_size = 0; + RK_S32 nLongTermRefPicPoc[MAX_NUM_LONG_TERM_REF_PIC_POC]; + RK_S32 nLongTermRefPicRealPoc[MAX_NUM_LONG_TERM_REF_PIC_POC]; + RK_S32 nLongTermDealtPoc[MAX_NUM_LONG_TERM_REF_PIC_POC]; + RK_U32 isMsbValid[MAX_NUM_LONG_TERM_REF_PIC_POC]; + RK_U32 isShortTermValid[MAX_REFS]; + H265eRpsList *RpsList = &dpb->RpsList; + H265eReferencePictureSet * rps = (H265eReferencePictureSet*)&slice->m_localRPS; + RK_S32 idx_rps; + H265eDpbFrm *p = NULL; + RK_S32 ref_dealt_poc = 0; + slice->m_bdIdx = -1; + + memset(isShortTermValid, 1, sizeof(RK_U32)*MAX_REFS); + memset(rps, 0, sizeof(H265eReferencePictureSet)); + for (idx_rps = 0; idx_rps < 16; idx_rps++) { + rps->delta_poc[idx_rps] = 0; + rps->m_used[idx_rps] = 0; + rps->m_ref[idx_rps] = 0; + } + + memset(rps->delta_poc, 0, MAX_REFS * sizeof(int)); + + if (cpb->curr.is_lt_ref) + mpp_assert(slice->m_sps->m_bLongTermRefsPresent); + + idx_rps = 0; + for (i = 0; i < MAX_CPB_REFS; i++) { + EncFrmStatus *frm = &cpb->init[i]; + + if (!frm->valid) + continue; + + mpp_assert(!frm->is_non_ref); + + h265e_dbg_dpb("idx %d frm %d valid %d is_non_ref %d lt_ref %d\n", + i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref); + + p = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, frm); + if (p) { + if (!frm->is_lt_ref) { + p->status.val = frm->val; + rps->delta_poc[idx_rps] = p->poc - curPoc; + rps->m_used[idx_rps] = 1; + idx_rps++; + st_size++; + h265e_dbg_dpb("found st %d st_size %d %p deat_poc %d\n", i, st_size, + frm, rps->delta_poc[idx_rps - 1]); + } else { + nLongTermRefPicPoc[lt_size] = p->gop_idx; + nLongTermRefPicRealPoc[lt_size] = p->poc; + nLongTermDealtPoc[lt_size] = p->poc - curPoc; + isMsbValid[lt_size] = p->gop_idx >= (RK_S32)(1 << p->slice->m_sps->m_bitsForPOC); + p->status.val = frm->val; + h265e_dbg_dpb("found lt %d lt_size %d %p dealt poc %d\n", i, lt_size, + frm, nLongTermDealtPoc[lt_size]); + lt_size++; + } + } + } + sort_delta_poc(rps); + + if (slice->m_sliceType == I_SLICE) { + rps->m_interRPSPrediction = 0; + rps->num_long_term_pic = 0; + rps->num_negative_pic = 0; + rps->num_positive_pic = 0; + rps->m_numberOfPictures = 0; + + } else { + p = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, &cpb->refr); + if (p == NULL) { + mpp_err("ref frame no found in refer index %d", cpb->refr.seq_idx); + } else { + ref_dealt_poc = p->poc - curPoc; + } + + for (i = 0; i < st_size; i++) { + rps->m_ref[i] = (rps->delta_poc[i] == ref_dealt_poc); + } + } + + if (lt_size > 0) { + for ( i = 0; i < lt_size; i++) { + h265e_dbg_dpb("numLongTermRefPic %d nShortTerm %d", lt_size, st_size); + rps->poc[i + st_size] = nLongTermRefPicPoc[i]; + rps->m_RealPoc[i + st_size] = nLongTermRefPicRealPoc[i]; + rps->m_used[i + st_size] = 1; + rps->delta_poc[i + st_size] = nLongTermDealtPoc[i]; + rps->check_lt_msb[i + st_size] = isMsbValid[i]; + if (cpb->refr.seq_idx == rps->poc[i + st_size]) + rps->m_ref[i + st_size] = 1; + else + rps->m_ref[i + st_size] = 0; + } + } + + rps->num_negative_pic = st_size; + rps->num_positive_pic = 0; + rps->num_long_term_pic = lt_size; + rps->m_numberOfPictures = st_size + lt_size; + slice->m_rps = rps; + h265e_dpb_apply_rps(dpb, slice->m_rps, curPoc); + h265e_dpb_arrange_lt_rps(dpb, slice); + h265e_dpb_set_ref_list(dpb, slice, ref_dealt_poc); + memcpy(&slice->m_RefPicListModification, RpsList->m_RefPicListModification, + sizeof(H265eRefPicListModification)); + h265e_dbg_func("leave\n"); +} + +MPP_RET h265e_pskip_ref_check(H265eDpb *dpb, EncCpbStatus *cpb, H265eDpbFrm *frm) +{ + MPP_RET ret = MPP_OK; + + h265e_dbg_func("enter\n"); + + if ((cpb->curr.force_pskip_is_ref) && (frm->slot_idx == dpb->curr->slice->m_refPicList[0][0]->slot_idx)) { + h265e_dbg_dpb("hold refr buf as skip frm recon buf, poc %d slot idx %d.", frm->slice->poc, frm->slot_idx); + ret = MPP_NOK; + } + + if ((cpb->refr.force_pskip_is_ref) && (frm->slot_idx == dpb->curr->slice->m_refPicList[0][0]->prev_ref_idx)) { + h265e_dbg_dpb("hold refr buf as skip frm recon buf, poc %d slot idx %d.", frm->slice->poc, frm->slot_idx); + ret = MPP_NOK; + } + + h265e_dbg_func("leave\n"); + return ret; +} + +void h265e_dpb_free_unsed(H265eDpb *dpb, EncCpbStatus *cpb) +{ + RK_S32 i = 0; + + h265e_dbg_func("enter\n"); + + if (cpb->curr.is_non_ref) { + H265eDpbFrm *frm = h265e_find_cpb_frame(dpb->frame_list, MAX_REFS, &cpb->curr); + if (frm) { + h265e_dbg_dpb("free curr unreference buf poc %d", frm->slice->poc); + frm->is_long_term = 0; + frm->used_by_cur = 0; + frm->dpb_used = 0; + frm->slice->is_referenced = 0; + } + } + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dpb->frame_list); i++) { + H265eDpbFrm *frm = &dpb->frame_list[i]; + if (!frm->dpb_used) + continue; + if (h265e_check_frame_cpb(frm, MAX_REFS, &cpb->final[0])) { + if (!h265e_pskip_ref_check(dpb, cpb, frm)) { + h265e_dbg_dpb("cpb final unreference buf poc %d", frm->slice->poc); + frm->is_long_term = 0; + frm->used_by_cur = 0; + frm->dpb_used = 0; + frm->slice->is_referenced = 0; + } + } + } + + h265e_dbg_func("leave\n"); +} + +void h265e_dpb_proc_cpb(H265eDpb *dpb, EncCpbStatus *cpb) +{ + EncFrmStatus *curr = &cpb->curr; + RK_U32 index = 0, i = 0; + H265eDpbFrm *p = NULL; + RK_U32 need_rebuild = 0; + RK_S32 max_gop_id = 0, max_poc = 0; + + if (!dpb || !cpb) + return; + + if (curr->is_idr) { + for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) { + H265eDpbFrm *frame = &dpb->frame_list[index]; + if (frame->inited) { + frame->slice->is_referenced = 0; + frame->is_long_term = 0; + frame->used_by_cur = 0; + frame->dpb_used = 0; + frame->status.val = 0; + } + } + return; + } + + for (i = 0; i < MAX_CPB_REFS; i++) { + EncFrmStatus *frm = &cpb->init[i]; + + if (!frm->valid) + continue; + + mpp_assert(!frm->is_non_ref); + + h265e_dbg_dpb("idx %d frm %d valid %d is_non_ref %d lt_ref %d\n", + i, frm->seq_idx, frm->valid, frm->is_non_ref, frm->is_lt_ref); + + p = h265e_find_cpb_in_dpb(dpb->frame_list, MAX_REFS, frm); + if (!p->dpb_used) { + p->dpb_used = 1; + p->status.val = frm->val; + p->slice->is_referenced = 1; + need_rebuild = 1; + } + } + + if (need_rebuild) { + h265e_dbg_dpb("cpb roll back found"); + for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) { + H265eDpbFrm *frame = &dpb->frame_list[index]; + + if (frame->dpb_used) { + if (max_poc < frame->slice->poc) { + max_poc = frame->slice->poc; + } + if (max_gop_id < frame->slice->gop_idx) { + max_gop_id = frame->slice->gop_idx; + } + } + } + + H265eDpbFrm *frame = dpb->curr; + + if (frame->inited) { + frame->slice->is_referenced = 0; + frame->is_long_term = 0; + frame->used_by_cur = 0; + frame->dpb_used = 0; + frame->status.val = 0; + } + dpb->seq_idx = max_poc; + dpb->gop_idx = max_gop_id; + } + + for (index = 0; index < MPP_ARRAY_ELEMS(dpb->frame_list); index++) { + H265eDpbFrm *frame = &dpb->frame_list[index]; + + if (frame->inited && !frame->dpb_used) { + h265e_dbg_dpb("reset index %d frame->inited %d rame->on_used %x", + index, frame->inited, frame->on_used); + frame->status.val = 0; + } + } +} + +void h265e_dpb_build_list(H265eDpb *dpb, EncCpbStatus *cpb) +{ + RK_S32 poc_cur = dpb->curr->slice->poc; + H265eSlice* slice = dpb->curr->slice; + RK_U32 bGPBcheck = 0; + RK_S32 i; + + h265e_dbg_func("enter\n"); + if (get_nal_unit_type(dpb, poc_cur) == NAL_IDR_W_RADL || + get_nal_unit_type(dpb, poc_cur) == NAL_IDR_N_LP) { + dpb->last_idr = poc_cur; + } + + slice->last_idr = dpb->last_idr; + slice->m_temporalLayerNonReferenceFlag = !slice->is_referenced; + // Set the nal unit type + slice->m_nalUnitType = get_nal_unit_type(dpb, poc_cur); + + // If the slice is un-referenced, change from _R "referenced" to _N "non-referenced" NAL unit type + if (slice->m_temporalLayerNonReferenceFlag) { + switch (slice->m_nalUnitType) { + case NAL_TRAIL_R: + slice->m_nalUnitType = NAL_TRAIL_N; + break; + case NAL_RADL_R: + slice->m_nalUnitType = NAL_RADL_N; + break; + case NAL_RASL_R: + slice->m_nalUnitType = NAL_RASL_N; + break; + default: + break; + } + } + + // Do decoding refresh marking if any + h265e_dpb_dec_refresh_marking(dpb, poc_cur, slice->m_nalUnitType); + h265e_dpb_cpb2rps(dpb, poc_cur, slice, cpb); + + slice->m_numRefIdx[L0] = MPP_MIN(dpb->max_ref_l0, slice->m_rps->m_numberOfPictures); // Ensuring L0 contains just the -ve POC + slice->m_numRefIdx[L1] = MPP_MIN(dpb->max_ref_l1, slice->m_rps->m_numberOfPictures); + + h265e_slice_set_ref_list(dpb->frame_list, slice); + + // Slice type refinement + if ((slice->m_sliceType == B_SLICE) && (slice->m_numRefIdx[L1] == 0)) { + slice->m_sliceType = P_SLICE; + } + + if (slice->m_sliceType == B_SLICE) { + // TODO: Can we estimate this from lookahead? + slice->m_colFromL0Flag = 0; + + RK_U32 bLowDelay = 1; + RK_S32 curPOC = slice->poc; + RK_S32 refIdx = 0; + + for (refIdx = 0; refIdx < slice->m_numRefIdx[L0] && bLowDelay; refIdx++) { + if (slice->m_refPicList[L0][refIdx]->poc > curPOC) { + bLowDelay = 0; + } + } + + for (refIdx = 0; refIdx < slice->m_numRefIdx[L1] && bLowDelay; refIdx++) { + if (slice->m_refPicList[L1][refIdx]->poc > curPOC) { + bLowDelay = 0; + } + } + + slice->m_bCheckLDC = bLowDelay; + } else { + slice->m_bCheckLDC = 1; + } + + h265e_slice_set_ref_poc_list(slice); + if (slice->m_sliceType == B_SLICE) { + if (slice->m_numRefIdx[L0] == slice->m_numRefIdx[L1]) { + bGPBcheck = 0; + for (i = 0; i < slice->m_numRefIdx[L1]; i++) { + if (slice->m_refPOCList[L1][i] != slice->m_refPOCList[L0][i]) { + bGPBcheck = 0; + break; + } + } + } + } + + slice->m_bLMvdL1Zero = bGPBcheck; + slice->m_nextSlice = 0; + if (slice->m_sliceType == I_SLICE) { + slice->tot_poc_num = 0; + } else { + slice->tot_poc_num = slice->m_localRPS.m_numberOfPictures; + } + h265e_dpb_free_unsed(dpb, cpb); + h265e_dbg_func("leave\n"); +} + +MPP_RET h265e_dpb_hal_start(H265eDpb *dpb, RK_S32 slot_idx) +{ + H265eDpbFrm *frm = &dpb->frame_list[slot_idx]; + + frm->hal_used++; + //h265e_dpb_dump_frms(dpb); + return MPP_OK; +} + +MPP_RET h265e_dpb_hal_end(H265eDpb *dpb, RK_S32 slot_idx) +{ + H265eDpbFrm *frm = &dpb->frame_list[slot_idx]; + + frm->hal_used--; + //h265e_dpb_dump_frms(dpb); + return MPP_OK; +} diff --git a/mpp/codec/enc/h265/h265e_dpb.h b/mpp/codec/enc/h265/h265e_dpb.h new file mode 100644 index 000000000..b1fc61b23 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_dpb.h @@ -0,0 +1,159 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_DPB_H +#define H265E_DPB_H + +#include "mpp_buffer.h" +#include "h265_syntax.h" +#include "mpp_enc_cfg.h" + +/* + * H.265 encoder dpb structure info + * + * +----------+ DPB +-> build list +-> REF_LIST + * | + + + * v v v + * FRM_BUF_GRP DPB_FRM +------+------> RPS + * + + + * | v + * +--------> FRM_BUF + * + * H265eDpb is overall structure contain the whole dpb info. + * It is composed H265eDpbFrm and H265eRpsList. + * + */ + +#define H265E_MAX_BUF_CNT 8 +#define H265_MAX_GOP 64 ///< max. value of hierarchical GOP size +#define H265_MAX_GOP_CNT (H265_MAX_GOP + 1) + +#define RPSLIST_MAX (H265_MAX_GOP * 3) + +typedef struct H265eDpb_t H265eDpb; +typedef struct H265eReferencePictureSet_e H265eReferencePictureSet; +typedef struct H265eRefPicListModification_e H265eRefPicListModification; +typedef struct H265eSlice_e H265eSlice; + + +typedef struct H265eDpb_t H265eDpb; + +/* + * Split reference frame configure to two parts + * The first part is slice depended info like poc / frame_num, and frame + * type and flags. + * The other part is gop structure depended info like gop index, ref_status + * and ref_frm_index. This part is inited from dpb gop hierarchy info. + */ + +typedef struct H265eDpbFrm_t { + H265eDpb *dpb; + + RK_S32 slot_idx; + RK_S32 seq_idx; + RK_S32 gop_idx; + RK_S32 gop_cnt; + RK_S32 prev_ref_idx; + EncFrmStatus status; + + union { + RK_U32 on_used; + struct { + RK_U32 dpb_used : 8; + RK_U32 hal_used : 8; + }; + }; + RK_U32 inited; + + RK_U32 is_long_term; + RK_U32 used_by_cur; + RK_U32 check_lt_msb; + RK_S32 poc; + + H265eSlice *slice; + + RK_S64 pts; + RK_S64 dts; + + RK_U32 is_key_frame; +} H265eDpbFrm; + +typedef struct H265eRpsList_e { + RK_S32 lt_num; + RK_S32 st_num; + RK_S32 poc_cur_list; + + RK_S32 poc[RPSLIST_MAX]; + + RK_U32 used_by_cur[MAX_REFS]; + + H265eRefPicListModification *m_RefPicListModification; +} H265eRpsList; + + +/* + * dpb frame arrangement + * + * If dpb size is 3 then dpb frame will be total 4 frames. + * Then the frame 3 is always current frame and frame 0~2 is reference frame + * in the gop structure. + * + * When one frame is encoded all it info will be moved to its gop position for + * next frame encoding. + */ +typedef struct H265eDpb_t { + RK_S32 seq_idx; + RK_S32 gop_idx; + + // status and count for one gop structure + RK_S32 last_idr; + RK_S32 poc_cra; + RK_U32 refresh_pending; + RK_S32 max_ref_l0; + RK_S32 max_ref_l1; + + H265eRpsList RpsList; + H265eDpbFrm *curr; + H265eDpbFrm frame_list[MAX_REFS + 1]; +} H265eDpb; + +#ifdef __cplusplus +extern "C" { +#endif + +void h265e_set_ref_list(H265eRpsList *RpsList, H265eReferencePictureSet *m_pRps); +MPP_RET h265e_dpb_init(H265eDpb **dpb); +MPP_RET h265e_dpb_deinit(H265eDpb *dpb); +MPP_RET h265e_dpb_setup_buf_size(H265eDpb *dpb, RK_U32 size[], RK_U32 count); +MPP_RET h265e_dpb_get_curr(H265eDpb *dpb); +void h265e_dpb_build_list(H265eDpb *dpb, EncCpbStatus *cpb); +void h265e_dpb_proc_cpb(H265eDpb *dpb, EncCpbStatus *cpb); + +/* + * hal usage flag mark / unmark function + */ +MPP_RET h265e_dpb_hal_start(H265eDpb *dpb, RK_S32 slot_idx); +MPP_RET h265e_dpb_hal_end(H265eDpb *dpb, RK_S32 slot_idx); + +#define h265e_dpb_dump_frms(dpb) h265e_dpb_dump_frm(dpb, __FUNCTION__) + +void h265e_dpb_dump_frm(H265eDpb *dpb, const char *caller); + +#ifdef __cplusplus +} +#endif + +#endif /* H265E_DPB_H */ diff --git a/mpp/codec/enc/h265/h265e_enctropy.c b/mpp/codec/enc/h265/h265e_enctropy.c new file mode 100644 index 000000000..bd0ffa0c2 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_enctropy.c @@ -0,0 +1,353 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_cabac" + +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "h265e_slice.h" +#include "h265e_codec.h" +#include "h265e_enctropy.h" + +#ifdef __GNUC__ /* GCCs builtin atomics */ +#define CLZ32(id, x) id = (unsigned long)__builtin_clz(x) ^ 31 +#elif defined(_MSC_VER) /* Windows atomic intrinsics */ +#define CLZ32(id, x) _BitScanReverse(&id, x) +#endif + +const RK_U8 g_lpsTable[64][4] = { + { 128, 176, 208, 240 }, + { 128, 167, 197, 227 }, + { 128, 158, 187, 216 }, + { 123, 150, 178, 205 }, + { 116, 142, 169, 195 }, + { 111, 135, 160, 185 }, + { 105, 128, 152, 175 }, + { 100, 122, 144, 166 }, + { 95, 116, 137, 158 }, + { 90, 110, 130, 150 }, + { 85, 104, 123, 142 }, + { 81, 99, 117, 135 }, + { 77, 94, 111, 128 }, + { 73, 89, 105, 122 }, + { 69, 85, 100, 116 }, + { 66, 80, 95, 110 }, + { 62, 76, 90, 104 }, + { 59, 72, 86, 99 }, + { 56, 69, 81, 94 }, + { 53, 65, 77, 89 }, + { 51, 62, 73, 85 }, + { 48, 59, 69, 80 }, + { 46, 56, 66, 76 }, + { 43, 53, 63, 72 }, + { 41, 50, 59, 69 }, + { 39, 48, 56, 65 }, + { 37, 45, 54, 62 }, + { 35, 43, 51, 59 }, + { 33, 41, 48, 56 }, + { 32, 39, 46, 53 }, + { 30, 37, 43, 50 }, + { 29, 35, 41, 48 }, + { 27, 33, 39, 45 }, + { 26, 31, 37, 43 }, + { 24, 30, 35, 41 }, + { 23, 28, 33, 39 }, + { 22, 27, 32, 37 }, + { 21, 26, 30, 35 }, + { 20, 24, 29, 33 }, + { 19, 23, 27, 31 }, + { 18, 22, 26, 30 }, + { 17, 21, 25, 28 }, + { 16, 20, 23, 27 }, + { 15, 19, 22, 25 }, + { 14, 18, 21, 24 }, + { 14, 17, 20, 23 }, + { 13, 16, 19, 22 }, + { 12, 15, 18, 21 }, + { 12, 14, 17, 20 }, + { 11, 14, 16, 19 }, + { 11, 13, 15, 18 }, + { 10, 12, 15, 17 }, + { 10, 12, 14, 16 }, + { 9, 11, 13, 15 }, + { 9, 11, 12, 14 }, + { 8, 10, 12, 14 }, + { 8, 9, 11, 13 }, + { 7, 9, 11, 12 }, + { 7, 9, 10, 12 }, + { 7, 8, 10, 11 }, + { 6, 8, 9, 11 }, + { 6, 7, 9, 10 }, + { 6, 7, 8, 9 }, + { 2, 2, 2, 2 } +}; + +const RK_U8 g_nextState[128][2] = { + { 2, 1 }, { 0, 3 }, { 4, 0 }, { 1, 5 }, { 6, 2 }, { 3, 7 }, { 8, 4 }, { 5, 9 }, + { 10, 4 }, { 5, 11 }, { 12, 8 }, { 9, 13 }, { 14, 8 }, { 9, 15 }, { 16, 10 }, { 11, 17 }, + { 18, 12 }, { 13, 19 }, { 20, 14 }, { 15, 21 }, { 22, 16 }, { 17, 23 }, { 24, 18 }, { 19, 25 }, + { 26, 18 }, { 19, 27 }, { 28, 22 }, { 23, 29 }, { 30, 22 }, { 23, 31 }, { 32, 24 }, { 25, 33 }, + { 34, 26 }, { 27, 35 }, { 36, 26 }, { 27, 37 }, { 38, 30 }, { 31, 39 }, { 40, 30 }, { 31, 41 }, + { 42, 32 }, { 33, 43 }, { 44, 32 }, { 33, 45 }, { 46, 36 }, { 37, 47 }, { 48, 36 }, { 37, 49 }, + { 50, 38 }, { 39, 51 }, { 52, 38 }, { 39, 53 }, { 54, 42 }, { 43, 55 }, { 56, 42 }, { 43, 57 }, + { 58, 44 }, { 45, 59 }, { 60, 44 }, { 45, 61 }, { 62, 46 }, { 47, 63 }, { 64, 48 }, { 49, 65 }, + { 66, 48 }, { 49, 67 }, { 68, 50 }, { 51, 69 }, { 70, 52 }, { 53, 71 }, { 72, 52 }, { 53, 73 }, + { 74, 54 }, { 55, 75 }, { 76, 54 }, { 55, 77 }, { 78, 56 }, { 57, 79 }, { 80, 58 }, { 59, 81 }, + { 82, 58 }, { 59, 83 }, { 84, 60 }, { 61, 85 }, { 86, 60 }, { 61, 87 }, { 88, 60 }, { 61, 89 }, + { 90, 62 }, { 63, 91 }, { 92, 64 }, { 65, 93 }, { 94, 64 }, { 65, 95 }, { 96, 66 }, { 67, 97 }, + { 98, 66 }, { 67, 99 }, { 100, 66 }, { 67, 101 }, { 102, 68 }, { 69, 103 }, { 104, 68 }, { 69, 105 }, + { 106, 70 }, { 71, 107 }, { 108, 70 }, { 71, 109 }, { 110, 70 }, { 71, 111 }, { 112, 72 }, { 73, 113 }, + { 114, 72 }, { 73, 115 }, { 116, 72 }, { 73, 117 }, { 118, 74 }, { 75, 119 }, { 120, 74 }, { 75, 121 }, + { 122, 74 }, { 75, 123 }, { 124, 76 }, { 77, 125 }, { 124, 76 }, { 77, 125 }, { 126, 126 }, { 127, 127 } +}; + +RK_U8 sbacInit(RK_S32 qp, RK_S32 initValue) +{ + RK_S32 slope = (initValue >> 4) * 5 - 45; + RK_S32 offset = ((initValue & 15) << 3) - 16; + RK_S32 initState = MPP_MIN(MPP_MAX(1, (((slope * qp) >> 4) + offset)), 126); + RK_U32 mpState = (initState >= 64); + RK_U8 m_state = (((mpState != 0) ? (initState - 64) : (63 - initState)) << 1) + mpState; + + return m_state; +} + +static void initBuffer(H265eContextModel_t* contextModel, SliceType sliceType, RK_U8 cabacIntFlag, RK_S32 qp, RK_U8* ctxModel, RK_S32 size) +{ + RK_S8 initType = 0; + RK_S32 n = 0; + h265e_dbg_skip("sliceType = %d", sliceType); + if (sliceType == I_SLICE) + initType = 0; + else if (sliceType == P_SLICE) + initType = (cabacIntFlag != 0) ? 2 : 1; + else + initType = (cabacIntFlag != 0) ? 1 : 2; + + ctxModel += (2 - initType) * size; + + for (n = 0; n < size; n++) { + contextModel[n].m_state = sbacInit(qp, ctxModel[n]); + //mpp_log("contextModel[%d].m_state = %d", n, contextModel[n].m_state); + contextModel[n].bBinsCoded = 0; + } +} + +void h265e_reset_enctropy(void *slice_ctx) +{ + H265eSlice *slice = (H265eSlice *)slice_ctx; + RK_U8 cabacInitFlag = slice->m_cabacInitFlag; + RK_S32 qp = slice->m_sliceQp; + SliceType sliceType = slice->m_sliceType; + + h265e_dbg_func("enter\n"); + initBuffer(&slice->m_contextModels[OFF_SPLIT_FLAG_CTX], sliceType, cabacInitFlag, qp, (RK_U8*)INIT_SPLIT_FLAG, NUM_SPLIT_FLAG_CTX); + initBuffer(&slice->m_contextModels[OFF_SKIP_FLAG_CTX], sliceType, cabacInitFlag, qp, (RK_U8*)INIT_SKIP_FLAG, NUM_SKIP_FLAG_CTX); + initBuffer(&slice->m_contextModels[OFF_MERGE_FLAG_EXT_CTX], sliceType, cabacInitFlag, qp, (RK_U8*)INIT_MERGE_FLAG_EXT, NUM_MERGE_FLAG_EXT_CTX); + initBuffer(&slice->m_contextModels[OFF_MERGE_IDX_EXT_CTX], sliceType, cabacInitFlag, qp, (uint8_t*)INIT_MERGE_IDX_EXT, NUM_MERGE_IDX_EXT_CTX); + + h265e_dbg_func("leave\n"); +} + +void h265e_cabac_resetBits(H265eCabacCtx *cabac_ctx) +{ + h265e_dbg_func("enter\n"); + + cabac_ctx->m_low = 0; + cabac_ctx->m_bitsLeft = -12; + cabac_ctx->m_numBufferedBytes = 0; + cabac_ctx->m_bufferedByte = 0xff; + cabac_ctx->m_fracBits = 0; + + h265e_dbg_func("leave\n"); +} + +void h265e_cabac_start(H265eCabacCtx *cabac_ctx) +{ + h265e_dbg_func("enter\n"); + cabac_ctx->m_low = 0; + cabac_ctx->m_range = 510; + cabac_ctx->m_bitsLeft = -12; + cabac_ctx->m_numBufferedBytes = 0; + cabac_ctx->m_bufferedByte = 0xff; +} + +void h265e_cabac_init(H265eCabacCtx *cabac_ctx, MppWriteCtx * bitIf) +{ + h265e_dbg_func("enter\n"); + cabac_ctx->m_bitIf = bitIf; + h265e_cabac_start(cabac_ctx); + h265e_dbg_func("leave\n"); +} + +void h265e_cabac_writeOut(H265eCabacCtx *cabac_ctx) +{ + MppWriteCtx* s = cabac_ctx->m_bitIf; + RK_U32 leadByte = cabac_ctx->m_low >> (13 + cabac_ctx->m_bitsLeft); + RK_U32 low_mask = (RK_U32)(~0) >> (11 + 8 - cabac_ctx->m_bitsLeft); + h265e_dbg_func("enter\n"); + + cabac_ctx->m_bitsLeft -= 8; + cabac_ctx->m_low &= low_mask; + + if (leadByte == 0xff) { + cabac_ctx->m_numBufferedBytes++; + } else { + RK_U32 numBufferedBytes = cabac_ctx->m_numBufferedBytes; + if (numBufferedBytes > 0) { + RK_U32 carry = leadByte >> 8; + RK_U32 byteTowrite = cabac_ctx->m_bufferedByte + carry; + mpp_writer_put_bits(s, byteTowrite, 8); + h265e_dbg_skip("byteTowrite = %x", byteTowrite); + byteTowrite = (0xff + carry) & 0xff; + while (numBufferedBytes > 1) { + h265e_dbg_skip("byteTowrite = %x", byteTowrite); + mpp_writer_put_bits(s, byteTowrite, 8); + numBufferedBytes--; + } + } + cabac_ctx->m_numBufferedBytes = 1; + cabac_ctx->m_bufferedByte = (uint8_t)leadByte; + } + + h265e_dbg_func("leave\n"); +} + +/** + * \brief Encode bin + * + * \param binValue bin value + * \param rcCtxModel context model + */ +void h265e_cabac_encodeBin(H265eCabacCtx *cabac_ctx, H265eContextModel_t *ctxModel, RK_U32 binValue) +{ + RK_U32 mstate = ctxModel->m_state; + + h265e_dbg_func("enter\n"); + + // mpp_log("before m_low %d ctxModel.m_state %d m_range %d \n", cabac_ctx->m_low, ctxModel->m_state,cabac_ctx->m_range); + ctxModel->m_state = sbacNext(mstate, binValue); + + ctxModel->bBinsCoded = 1; + RK_U32 range = cabac_ctx->m_range; + RK_U32 state = sbacGetState(mstate); + RK_U32 lps = g_lpsTable[state][((uint8_t)range >> 6)]; + range -= lps; + + // mpp_log("ctxModel.m_state %d binValue %d \n", ctxModel->m_state, binValue); + // assert(lps >= 2); + + RK_S32 numBits = (RK_U32)(range - 256) >> 31; + RK_U32 low = cabac_ctx->m_low; + + // NOTE: MPS must be LOWEST bit in mstate + // assert(((binValue ^ mstate) & 1) == (binValue != sbacGetMps(mstate))); + if ((binValue ^ mstate) & 1) { + unsigned long idx; + CLZ32(idx, lps); + // assert(state != 63 || idx == 1); + + numBits = 8 - idx; + if (state >= 63) + numBits = 6; + // assert(numBits <= 6); + + low += range; + range = lps; + } + cabac_ctx->m_low = (low << numBits); + cabac_ctx->m_range = (range << numBits); + cabac_ctx->m_bitsLeft += numBits; + + // mpp_log("after m_low %d ctxModel.m_state %d m_range %d \n", cabac_ctx->m_low, ctxModel->m_state,cabac_ctx->m_range); + if (cabac_ctx->m_bitsLeft >= 0) { + h265e_cabac_writeOut(cabac_ctx); + } + + h265e_dbg_func("leave\n"); +} + +void h265e_cabac_encodeBinTrm(H265eCabacCtx *cabac_ctx, RK_U32 binValue) +{ + h265e_dbg_func("enter\n"); + + // mpp_log("encodeBinTrm m_range %d binValue %d \n", cabac_ctx->m_range, binValue); + cabac_ctx->m_range -= 2; + if (binValue) { + cabac_ctx->m_low += cabac_ctx->m_range; + cabac_ctx->m_low <<= 7; + cabac_ctx->m_range = 2 << 7; + cabac_ctx->m_bitsLeft += 7; + } else if (cabac_ctx->m_range >= 256) { + return; + } else { + cabac_ctx->m_low <<= 1; + cabac_ctx->m_range <<= 1; + cabac_ctx->m_bitsLeft++; + } + + if (cabac_ctx->m_bitsLeft >= 0) { + h265e_cabac_writeOut(cabac_ctx); + } + + h265e_dbg_func("leave\n"); +} + +void h265e_cabac_finish(H265eCabacCtx *cabac_ctx) +{ + MppWriteCtx* s = cabac_ctx->m_bitIf; + + h265e_dbg_func("enter\n"); + + if (cabac_ctx->m_low >> (21 + cabac_ctx->m_bitsLeft)) { + + mpp_writer_put_bits(s, cabac_ctx->m_bufferedByte + 1, 8); + while (cabac_ctx->m_numBufferedBytes > 1) { + mpp_writer_put_bits(s, 0, 8); + cabac_ctx->m_numBufferedBytes--; + } + + cabac_ctx->m_low -= 1 << (21 + cabac_ctx->m_bitsLeft); + } else { + if (cabac_ctx->m_numBufferedBytes > 0) { + + mpp_writer_put_bits(s, cabac_ctx->m_bufferedByte , 8); + } + while (cabac_ctx->m_numBufferedBytes > 1) { + mpp_writer_put_bits(s, 0xff , 8); + cabac_ctx->m_numBufferedBytes--; + } + } + mpp_writer_put_bits(s, cabac_ctx->m_low >> 8 , 13 + cabac_ctx->m_bitsLeft); + + h265e_dbg_func("leave\n"); +} + +void h265e_cabac_flush(H265eCabacCtx *cabac_ctx) +{ + MppWriteCtx* s = cabac_ctx->m_bitIf; + + h265e_dbg_func("enter\n"); + + h265e_cabac_encodeBinTrm(cabac_ctx, 1); + h265e_cabac_finish(cabac_ctx); + mpp_writer_put_bits(s, 1, 1); + mpp_writer_align_zero(s); + h265e_cabac_start(cabac_ctx); + + h265e_dbg_func("leave\n"); +} diff --git a/mpp/codec/enc/h265/h265e_enctropy.h b/mpp/codec/enc/h265/h265e_enctropy.h new file mode 100644 index 000000000..fafd72b1d --- /dev/null +++ b/mpp/codec/enc/h265/h265e_enctropy.h @@ -0,0 +1,55 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_ENCTROPY_H +#define H265E_ENCTROPY_H + +#include "mpp_bitwrite.h" + +typedef struct H265eContextModel { + RK_U8 m_state; ///< internal state variable + RK_U8 bBinsCoded; +} H265eContextModel_t; + +typedef struct H265eCabacCtx { + MppWriteCtx *m_bitIf; + RK_U32 m_low; + RK_U32 m_range; + RK_U32 m_bufferedByte; + RK_S32 m_numBufferedBytes; + RK_S32 m_bitsLeft; + RK_U64 m_fracBits; + RK_U8 m_bIsCounter; +} H265eCabacCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +void h265e_cabac_init(H265eCabacCtx *cabac_ctx, MppWriteCtx * bitIf); +void h265e_reset_enctropy(void *slice_ctx); +void h265e_cabac_resetBits(H265eCabacCtx *cabac_ctx); +void h265e_cabac_encodeBin(H265eCabacCtx *cabac_ctx, H265eContextModel_t *ctxModel, RK_U32 binValue); +void h265e_cabac_encodeBinTrm(H265eCabacCtx *cabac_ctx, RK_U32 binValue); +void h265e_cabac_start(H265eCabacCtx *cabac_ctx); +void h265e_cabac_finish(H265eCabacCtx *cabac_ctx); +void h265e_cabac_flush(H265eCabacCtx *cabac_ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/codec/enc/h265/h265e_header_gen.c b/mpp/codec/enc/h265/h265e_header_gen.c new file mode 100644 index 000000000..99a2a41d2 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_header_gen.c @@ -0,0 +1,789 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_header_gen" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "mpp_packet_impl.h" + +#include "h265e_ps.h" +#include "h265e_header_gen.h" + +static void h265e_nals_init(H265eExtraInfo *out) +{ + out->nal_buf = mpp_calloc(RK_U8, H265E_EXTRA_INFO_BUF_SIZE); + out->nal_num = 0; +} + +static void h265e_nals_deinit(H265eExtraInfo *out) +{ + MPP_FREE(out->nal_buf); + + out->nal_num = 0; +} + +static RK_U8 *h265e_nal_escape_c(RK_U8 *dst, RK_U8 *src, RK_U8 *end) +{ + if (src < end) *dst++ = *src++; + if (src < end) *dst++ = *src++; + while (src < end) { + // if (src[0] <= 0x03 && !dst[-2] && !dst[-1]) + // *dst++ = 0x03; + *dst++ = *src++; + } + return dst; +} + +static void h265e_nal_encode(RK_U8 *dst, H265eNal *nal) +{ + RK_S32 b_annexb = 1; + RK_S32 size = 0; + RK_U8 *src = nal->p_payload; + RK_U8 *end = nal->p_payload + nal->i_payload; + RK_U8 *orig_dst = dst; + MppWriteCtx s; + + if (b_annexb) { + *dst++ = 0x00; + *dst++ = 0x00; + *dst++ = 0x00; + *dst++ = 0x01; + } else /* save room for size later */ + dst += 4; + + /* nal header */ + mpp_writer_init(&s, dst, 10); + mpp_writer_put_bits(&s, 0, 1); //forbidden_zero_bit + mpp_writer_put_bits(&s, nal->i_type, 6);//nal_unit_type + mpp_writer_put_bits(&s, 0, 6); //nuh_reserved_zero_6bits + mpp_writer_put_bits(&s, nal->temporal_id + 1, 3); //nuh_temporal_id_plus1 + dst += 2; + dst = h265e_nal_escape_c(dst, src, end); + size = (RK_S32)((dst - orig_dst) - 4); + + /* Write the size header for mp4/etc */ + if (!b_annexb) { + /* Size doesn't include the size of the header we're writing now. */ + orig_dst[0] = size >> 24; + orig_dst[1] = size >> 16; + orig_dst[2] = size >> 8; + orig_dst[3] = size >> 0; + } + + nal->i_payload = size + 4; + nal->p_payload = orig_dst; +} + +static MPP_RET h265e_encapsulate_nals(H265eExtraInfo *out) +{ + RK_S32 i = 0; + RK_S32 i_avcintra_class = 0; + RK_S32 nal_size = 0; + RK_S32 necessary_size = 0; + RK_U8 *nal_buffer = out->nal_buf; + RK_S32 nal_num = out->nal_num; + H265eNal *nal = out->nal; + + h265e_dbg_func("enter\n"); + for (i = 0; i < nal_num; i++) + nal_size += nal[i].i_payload; + + /* Worst-case NAL unit escaping: reallocate the buffer if it's too small. */ + necessary_size = nal_size * 3 / 2 + nal_num * 4 + 4 + 64; + for (i = 0; i < nal_num; i++) + necessary_size += nal[i].i_padding; + + for (i = 0; i < nal_num; i++) { + nal[i].b_long_startcode = !i || + nal[i].i_type == NAL_VPS || + nal[i].i_type == NAL_SPS || + nal[i].i_type == NAL_PPS || + i_avcintra_class; + h265e_nal_encode(nal_buffer, &nal[i]); + nal_buffer += nal[i].i_payload; + } + + h265e_dbg(H265E_DBG_HEADER, "nals total size: %d bytes, necessary_size %d", + nal_buffer - out->nal_buf, necessary_size); + + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET h265e_write_recovery_point(H265eStream * s, RK_U32 recovery_frame_cnt) +{ + h265e_stream_write_se_with_log(s, recovery_frame_cnt, NULL); + h265e_stream_write1_with_log(s, 1, NULL); + h265e_stream_write1_with_log(s, 0, NULL); + h265e_stream_rbsp_trailing(s); + return MPP_OK; +} + +static MPP_RET h265e_sei_write(H265eStream *s, RK_U8 uuid[16], const RK_U8 *payload, + RK_S32 payload_size, RK_S32 payload_type) +{ + RK_S32 i = 0; + RK_S32 uuid_len = H265E_UUID_LENGTH; + RK_S32 data_len = payload_size; + + h265e_dbg_func("enter\n"); + + h265e_stream_realign(s); + + switch (payload_type) { + case H265_SEI_USER_DATA_UNREGISTERED : { + payload_size += uuid_len; + } break; + case H265_SEI_RECOVERY_POINT: { + H265eStream stream; + h265e_stream_init(&stream); + h265e_write_recovery_point(&stream, ((RK_U32 *)payload)[0]); + payload_size = stream.enc_stream.byte_cnt; + h265e_stream_deinit(&stream); + } break; + default: { + mpp_err_f("payload_type %d is no process ", payload_type); + } break; + } + + for (i = 0; i <= payload_type - 255; i += 255) + h265e_stream_write_with_log(s, 0xff, 8, + "sei_payload_type_ff_byte"); + + h265e_stream_write_with_log(s, payload_type - i, 8, + "sei_last_payload_type_byte"); + + for (i = 0; i <= payload_size - 255; i += 255) + h265e_stream_write_with_log(s, 0xff, 8, + "sei_payload_size_ff_byte"); + + h265e_stream_write_with_log(s, payload_size - i, 8, + "sei_last_payload_size_byte"); + + switch (payload_type) { + case H265_SEI_USER_DATA_UNREGISTERED : { + for (i = 0; i < uuid_len; i++) + h265e_stream_write_with_log(s, uuid[i], 8, NULL); + for (i = 0; i < data_len; i++) + h265e_stream_write_with_log(s, (RK_U32) payload[i], 8, NULL); + h265e_stream_rbsp_trailing(s); + } break; + case H265_SEI_RECOVERY_POINT: { + h265e_write_recovery_point(s, ((RK_U32 *)payload)[0]); + } break; + default: { + mpp_err_f("payload_type %d is no process ", payload_type); + } break; + } + + h265e_dbg_func("leave\n"); + + return MPP_OK; +} + +MPP_RET h265e_sei_recovery_point(void *dst, RK_U8 uuid[16], const void *payload, + RK_S32 size) +{ + H265eNal sei_nal; + H265eStream stream; + RK_U8 *end = 0; + + h265e_dbg_func("enter\n"); + + h265e_stream_init(&stream); + memset(&sei_nal, 0, sizeof(H265eNal)); + + sei_nal.i_type = NAL_SEI_PREFIX; + sei_nal.p_payload = &stream.buf[stream.enc_stream.byte_cnt]; + + h265e_sei_write(&stream, uuid, payload, size, + H265_SEI_RECOVERY_POINT); + + end = &stream.buf[stream.enc_stream.byte_cnt]; + sei_nal.i_payload = (RK_S32) (end - sei_nal.p_payload); + + h265e_nal_encode(dst, &sei_nal); + + h265e_stream_deinit(&stream); + + h265e_dbg_func("leave\n"); + return sei_nal.i_payload; + + return MPP_OK; +} + +void codeProfileTier(H265eStream *s, ProfileTierLevel* ptl) +{ + RK_S32 j; + h265e_stream_write_with_log(s, ptl->m_profileSpace, 2, "profile_space[]"); + h265e_stream_write1_with_log(s, ptl->m_tierFlag, "tier_flag[]"); + h265e_stream_write_with_log(s, ptl->m_profileIdc, 5, "profile_idc[]"); + for (j = 0; j < 32; j++) { + h265e_stream_write1_with_log(s, ptl->m_profileCompatibilityFlag[j], "profile_compatibility_flag[][j]"); + } + + h265e_stream_write1_with_log(s, ptl->m_progressiveSourceFlag, "general_progressive_source_flag"); + h265e_stream_write1_with_log(s, ptl->m_interlacedSourceFlag, "general_interlaced_source_flag"); + h265e_stream_write1_with_log(s, ptl->m_nonPackedConstraintFlag, "general_non_packed_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_frameOnlyConstraintFlag, "general_frame_only_constraint_flag"); + + if (ptl->m_profileIdc == MPP_PROFILE_HEVC_FORMAT_RANGE_EXTENDIONS) { + h265e_stream_write1_with_log(s, ptl->m_max12bitConstraintFlag , "general_max_12_bit_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_max10bitConstraintFlag, "general_max_10_bit_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_max8bitConstraintFlag, "general_max_8_bit_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_max422chromaConstraintFlag, "general_max_422chroma_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_max420chromaConstraintFlag, "general_max_420chroma_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_maxMonochromaConstraintFlag, "general_max_monochroma_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_intraConstraintFlag, "general_intra_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_onePictureConstraintFlag, "general_one_picture_constraint_flag"); + h265e_stream_write1_with_log(s, ptl->m_lowerBitRateConstraintFlag, "general_lower_bit_rate_constraint_flag"); + h265e_stream_write_with_log(s, 0, 16, "reserved_zero_35bits[0..15]"); + h265e_stream_write_with_log(s, 0, 16, "reserved_zero_35bits[16..31]"); + h265e_stream_write_with_log(s, 0, 3, "eserved_zero_35bits[32..34]"); + } else { + h265e_stream_write_with_log(s, 0, 16, "reserved_zero_44bits[0..15]"); + h265e_stream_write_with_log(s, 0, 16, "reserved_zero_44bits[16..31]"); + h265e_stream_write_with_log(s, 0, 12, "eserved_zero_44bits[32..43]"); + } +} + +void codePTL(H265eStream *s, H265ePTL* ptl, RK_U32 profilePresentFlag, int maxNumSubLayersMinus1) +{ + RK_S32 i; + if (profilePresentFlag) { + codeProfileTier(s, &ptl->m_generalPTL); + } + h265e_stream_write_with_log(s, ptl->m_generalPTL.m_levelIdc, 8, "general_level_idc"); + + for (i = 0; i < maxNumSubLayersMinus1; i++) { + if (profilePresentFlag) { + h265e_stream_write1_with_log(s, ptl->m_subLayerProfilePresentFlag[i], "sub_layer_profile_present_flag[i]"); + } + + h265e_stream_write1_with_log(s, ptl->m_subLayerLevelPresentFlag[i], "sub_layer_level_present_flag[i]"); + } + + if (maxNumSubLayersMinus1 > 0) { + for (i = maxNumSubLayersMinus1; i < 8; i++) { + h265e_stream_write_with_log(s, 0, 2, "reserved_zero_2bits"); + } + } + + for (i = 0; i < maxNumSubLayersMinus1; i++) { + if (profilePresentFlag && ptl->m_subLayerProfilePresentFlag[i]) { + codeProfileTier(s, &ptl->m_subLayerPTL[i]); // sub_layer_... + } + if (ptl->m_subLayerLevelPresentFlag[i]) { + h265e_stream_write_with_log(s, ptl->m_subLayerPTL[i].m_levelIdc, 8, "sub_layer_level_idc[i]"); + } + } +} + +static MPP_RET h265e_vps_write(H265eVps *vps, H265eStream *s) +{ + RK_S32 vps_byte_start = 0; + RK_U32 i, opsIdx; + + h265e_dbg_func("enter\n"); + h265e_stream_realign(s); + vps_byte_start = s->enc_stream.byte_cnt; + h265e_stream_write_with_log(s, vps->m_VPSId, 4, "vps_video_parameter_set_id"); + h265e_stream_write_with_log(s, 3, 2, "vps_reserved_three_2bits"); + h265e_stream_write_with_log(s, 0, 6, "vps_reserved_zero_6bits"); + h265e_stream_write_with_log(s, vps->m_maxTLayers - 1, 3, "vps_max_sub_layers_minus1"); + h265e_stream_write1_with_log(s, vps->m_bTemporalIdNestingFlag, "vps_temporal_id_nesting_flag"); + + h265e_stream_write_with_log(s, 0xffff, 16, "vps_reserved_ffff_16bits"); + + codePTL(s, &vps->m_ptl, 1, vps->m_maxTLayers - 1); + + h265e_stream_write1_with_log(s, 1, "vps_sub_layer_ordering_info_present_flag"); + for (i = 0; i <= vps->m_maxTLayers - 1; i++) { + h265e_stream_write_ue_with_log(s, vps->m_maxDecPicBuffering[i] - 1, "vps_max_dec_pic_buffering_minus1[i]"); + h265e_stream_write_ue_with_log(s, vps->m_numReorderPics[i], "vps_num_reorder_pics[i]"); + h265e_stream_write_ue_with_log(s, vps->m_maxLatencyIncrease[i], "vps_max_latency_increase_plus1[i]"); + } + + mpp_assert(vps->m_numHrdParameters <= MAX_VPS_NUM_HRD_PARAMETERS); + mpp_assert(vps->m_maxNuhReservedZeroLayerId < MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1); + h265e_stream_write_with_log(s, vps->m_maxNuhReservedZeroLayerId, 6, "vps_max_nuh_reserved_zero_layer_id"); + vps->m_numOpSets = 1; + h265e_stream_write_ue_with_log(s, vps->m_numOpSets - 1, "vps_max_op_sets_minus1"); + for (opsIdx = 1; opsIdx <= (vps->m_numOpSets - 1); opsIdx++) { + // Operation point set + for (i = 0; i <= vps->m_maxNuhReservedZeroLayerId; i++) { + // Only applicable for version 1 + vps->m_layerIdIncludedFlag[opsIdx][i] = 1; + h265e_stream_write1_with_log(s, (vps->m_layerIdIncludedFlag[opsIdx][i] != 0) ? 1 : 0, "layer_id_included_flag[opsIdx][i]"); + } + } + + TimingInfo *timingInfo = &vps->m_timingInfo; + h265e_stream_write1_with_log(s, timingInfo->m_timingInfoPresentFlag, "vps_timing_info_present_flag"); + if (timingInfo->m_timingInfoPresentFlag) { + h265e_stream_write_with_log(s, timingInfo->m_numUnitsInTick, 32, "vps_num_units_in_tick"); + h265e_stream_write_with_log(s, timingInfo->m_timeScale, 32, "vps_time_scale"); + h265e_stream_write1_with_log(s, timingInfo->m_pocProportionalToTimingFlag, "vps_poc_proportional_to_timing_flag"); + if (timingInfo->m_pocProportionalToTimingFlag) { + h265e_stream_write_ue_with_log(s, timingInfo->m_numTicksPocDiffOneMinus1, "vps_num_ticks_poc_diff_one_minus1"); + } + vps->m_numHrdParameters = 0; + h265e_stream_write_ue_with_log(s, vps->m_numHrdParameters, "vps_num_hrd_parameters"); +#if 0 + if (vps->m_numHrdParameters > 0) { + vps->createHrdParamBuffer(); + } + for (uint32_t i = 0; i < vps->getNumHrdParameters(); i++) { + // Only applicable for version 1 + vps->setHrdOpSetIdx(0, i); + h265e_stream_write_ue_with_log(s, vps->getHrdOpSetIdx(i), "hrd_op_set_idx"); + if (i > 0) { + h265e_stream_write1_with_log(s, vps->getCprmsPresentFlag(i) ? 1 : 0, "cprms_present_flag[i]"); + } + codeHrdParameters(vps->getHrdParameters(i), vps->getCprmsPresentFlag(i), vps->getMaxTLayers() - 1); + } +#endif + } + h265e_stream_write1_with_log(s, 0, "vps_extension_flag"); + h265e_stream_rbsp_trailing(s); + h265e_stream_flush(s); + h265e_dbg(H265E_DBG_HEADER, "write pure vps head size: %d bits", (s->enc_stream.byte_cnt - vps_byte_start) * 8); + //future extensions here.. + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +void codeVUI(H265eStream *s, H265eVuiInfo *vui) +{ + h265e_stream_write1_with_log(s, vui->m_aspectRatioInfoPresentFlag, "aspect_ratio_info_present_flag"); + if (vui->m_aspectRatioInfoPresentFlag) { + h265e_stream_write_with_log(s, vui->m_aspectRatioIdc, 8, "aspect_ratio_idc"); + if (vui->m_aspectRatioIdc == 255) { + h265e_stream_write_with_log(s, vui->m_sarWidth, 16, "sar_width"); + h265e_stream_write_with_log(s, vui->m_sarHeight, 16, "sar_height"); + } + } + h265e_stream_write1_with_log(s, vui->m_overscanInfoPresentFlag, "overscan_info_present_flag"); + if (vui->m_overscanInfoPresentFlag) { + h265e_stream_write1_with_log(s, vui->m_overscanAppropriateFlag, "overscan_appropriate_flag"); + } + h265e_stream_write1_with_log(s, vui->m_videoSignalTypePresentFlag, "video_signal_type_present_flag"); + if (vui->m_videoSignalTypePresentFlag) { + h265e_stream_write_with_log(s, vui->m_videoFormat, 3, "video_format"); + h265e_stream_write1_with_log(s, vui->m_videoFullRangeFlag, "video_full_range_flag"); + h265e_stream_write1_with_log(s, vui->m_colourDescriptionPresentFlag, "colour_description_present_flag"); + if (vui->m_colourDescriptionPresentFlag) { + h265e_stream_write_with_log(s, vui->m_colourPrimaries, 8, "colour_primaries"); + h265e_stream_write_with_log(s, vui->m_transferCharacteristics, 8, "transfer_characteristics"); + h265e_stream_write_with_log(s, vui->m_matrixCoefficients, 8, "matrix_coefficients"); + } + } + + h265e_stream_write1_with_log(s, vui->m_chromaLocInfoPresentFlag, "chroma_loc_info_present_flag"); + if (vui->m_chromaLocInfoPresentFlag) { + h265e_stream_write_ue_with_log(s, vui->m_chromaSampleLocTypeTopField, "chroma_sample_loc_type_top_field"); + h265e_stream_write_ue_with_log(s, vui->m_chromaSampleLocTypeBottomField, "chroma_sample_loc_type_bottom_field"); + } + + h265e_stream_write1_with_log(s, vui->m_neutralChromaIndicationFlag, "neutral_chroma_indication_flag"); + h265e_stream_write1_with_log(s, vui->m_fieldSeqFlag, "field_seq_flag"); + h265e_stream_write1_with_log(s, vui->m_frameFieldInfoPresentFlag, "frame_field_info_present_flag"); + + H265eCropInfo defaultDisplayWindow = vui->m_defaultDisplayWindow; + h265e_stream_write1_with_log(s, defaultDisplayWindow.m_enabledFlag, "default_display_window_flag"); + if (defaultDisplayWindow.m_enabledFlag) { + h265e_stream_write_ue_with_log(s, defaultDisplayWindow.m_winLeftOffset, "def_disp_win_left_offset"); + h265e_stream_write_ue_with_log(s, defaultDisplayWindow.m_winRightOffset, "def_disp_win_right_offset"); + h265e_stream_write_ue_with_log(s, defaultDisplayWindow.m_winTopOffset, "def_disp_win_top_offset"); + h265e_stream_write_ue_with_log(s, defaultDisplayWindow.m_winBottomOffset, "def_disp_win_bottom_offset"); + } + TimingInfo *timingInfo = &vui->m_timingInfo; + h265e_stream_write1_with_log(s, timingInfo->m_timingInfoPresentFlag, "vui_timing_info_present_flag"); + if (timingInfo->m_timingInfoPresentFlag) { + h265e_stream_write32(s, timingInfo->m_numUnitsInTick, "vui_num_units_in_tick"); + h265e_stream_write32(s, timingInfo->m_timeScale, "vui_time_scale"); + h265e_stream_write1_with_log(s, timingInfo->m_pocProportionalToTimingFlag, "vui_poc_proportional_to_timing_flag"); + if (timingInfo->m_pocProportionalToTimingFlag) { + h265e_stream_write_ue_with_log(s, timingInfo->m_numTicksPocDiffOneMinus1, "vui_num_ticks_poc_diff_one_minus1"); + } + h265e_stream_write1_with_log(s, vui->m_hrdParametersPresentFlag, "hrd_parameters_present_flag"); + if (vui->m_hrdParametersPresentFlag) { + // codeHrdParameters(vui->getHrdParameters(), 1, sps->getMaxTLayers() - 1); //todo + } + } + h265e_stream_write1_with_log(s, vui->m_bitstreamRestrictionFlag, "bitstream_restriction_flag"); + if (vui->m_bitstreamRestrictionFlag) { + h265e_stream_write1_with_log(s, vui->m_tilesFixedStructureFlag, "tiles_fixed_structure_flag"); + h265e_stream_write1_with_log(s, vui->m_motionVectorsOverPicBoundariesFlag, "motion_vectors_over_pic_boundaries_flag"); + h265e_stream_write1_with_log(s, vui->m_restrictedRefPicListsFlag, "restricted_ref_pic_lists_flag"); + h265e_stream_write_ue_with_log(s, vui->m_minSpatialSegmentationIdc, "min_spatial_segmentation_idc"); + h265e_stream_write_ue_with_log(s, vui->m_maxBytesPerPicDenom, "max_bytes_per_pic_denom"); + h265e_stream_write_ue_with_log(s, vui->m_maxBitsPerMinCuDenom, "max_bits_per_mincu_denom"); + h265e_stream_write_ue_with_log(s, vui->m_log2MaxMvLengthHorizontal, "log2_max_mv_length_horizontal"); + h265e_stream_write_ue_with_log(s, vui->m_log2MaxMvLengthHorizontal, "log2_max_mv_length_vertical"); + } +} + +static MPP_RET h265e_sps_write(H265eSps *sps, H265eStream *s) +{ + RK_S32 sps_byte_start = 0; + RK_U32 i, k; + const RK_S32 winUnitX[] = { 1, 2, 2, 1 }; + const RK_S32 winUnitY[] = { 1, 2, 1, 1 }; + H265eCropInfo *conf = &sps->m_conformanceWindow; + + h265e_dbg_func("enter\n"); + h265e_stream_realign(s); + sps_byte_start = s->enc_stream.byte_cnt; + + h265e_stream_write_with_log(s, sps->m_VPSId, 4, "sps_video_parameter_set_id"); + h265e_stream_write_with_log(s, sps->m_maxTLayers - 1, 3, "sps_max_sub_layers_minus1"); + h265e_stream_write1_with_log(s, (sps->m_bTemporalIdNestingFlag != 0) ? 1 : 0, "sps_temporal_id_nesting_flag"); + codePTL(s, sps->m_ptl, 1, sps->m_maxTLayers - 1); + h265e_stream_write_ue_with_log(s, sps->m_SPSId, "sps_seq_parameter_set_id"); + h265e_stream_write_ue_with_log(s, sps->m_chromaFormatIdc, "chroma_format_idc"); + + if (sps->m_chromaFormatIdc == 4) { + h265e_stream_write1_with_log(s, 0, "separate_colour_plane_flag"); + } + + h265e_stream_write_ue_with_log(s, sps->m_picWidthInLumaSamples, "pic_width_in_luma_samples"); + h265e_stream_write_ue_with_log(s, sps->m_picHeightInLumaSamples, "pic_height_in_luma_samples"); + + h265e_stream_write1_with_log(s, conf->m_enabledFlag, "conformance_window_flag"); + if (conf->m_enabledFlag) { + h265e_stream_write_ue_with_log(s, conf->m_winLeftOffset / winUnitX[sps->m_chromaFormatIdc], "conf_win_left_offset"); + h265e_stream_write_ue_with_log(s, conf->m_winRightOffset / winUnitX[sps->m_chromaFormatIdc], "conf_win_right_offset"); + h265e_stream_write_ue_with_log(s, conf->m_winTopOffset / winUnitY[sps->m_chromaFormatIdc], "conf_win_top_offset"); + h265e_stream_write_ue_with_log(s, conf->m_winBottomOffset / winUnitY[sps->m_chromaFormatIdc], "conf_win_bottom_offset"); + } + + h265e_stream_write_ue_with_log(s, sps->m_bitDepthY - 8, "bit_depth_luma_minus8"); + h265e_stream_write_ue_with_log(s, sps->m_bitDepthC - 8, "bit_depth_chroma_minus8"); + + h265e_stream_write_ue_with_log(s, sps->m_bitsForPOC - 4, "log2_max_pic_order_cnt_lsb_minus4"); + + h265e_stream_write1_with_log(s, 1, "sps_sub_layer_ordering_info_present_flag"); + for (i = 0; i <= sps->m_maxTLayers - 1; i++) { + h265e_stream_write_ue_with_log(s, sps->m_maxDecPicBuffering[i] - 1, "sps_max_dec_pic_buffering_minus1[i]"); + h265e_stream_write_ue_with_log(s, sps->m_numReorderPics[i], "sps_num_reorder_pics[i]"); + h265e_stream_write_ue_with_log(s, sps->m_maxLatencyIncrease[i], "sps_max_latency_increase_plus1[i]"); + } + + h265e_stream_write_ue_with_log(s, sps->m_log2MinCodingBlockSize - 3, "log2_min_coding_block_size_minus3"); + h265e_stream_write_ue_with_log(s, sps->m_log2DiffMaxMinCodingBlockSize, "log2_diff_max_min_coding_block_size"); + h265e_stream_write_ue_with_log(s, sps->m_quadtreeTULog2MinSize - 2, "log2_min_transform_block_size_minus2"); + h265e_stream_write_ue_with_log(s, sps->m_quadtreeTULog2MaxSize - sps->m_quadtreeTULog2MinSize, "log2_diff_max_min_transform_block_size"); + h265e_stream_write_ue_with_log(s, sps->m_quadtreeTUMaxDepthInter - 1, "max_transform_hierarchy_depth_inter"); + h265e_stream_write_ue_with_log(s, sps->m_quadtreeTUMaxDepthIntra - 1, "max_transform_hierarchy_depth_intra"); + h265e_stream_write1_with_log(s, (sps->m_scalingListEnabledFlag != 0) ? 1 : 0, "scaling_list_enabled_flag"); + if (sps->m_scalingListEnabledFlag == 1) + h265e_stream_write1_with_log(s, 0, "sps_scaling_list_data_present_flag"); + else if (sps->m_scalingListEnabledFlag == 2) { + //TODO: + mpp_err_f("m_scalingListEnabledFlag == 2 not supported yet\n"); + } + h265e_stream_write1_with_log(s, (sps->m_useAMP != 0) ? 1 : 0, "amp_enabled_flag"); + h265e_stream_write1_with_log(s, (sps->m_bUseSAO != 0) ? 1 : 0, "sample_adaptive_offset_enabled_flag"); + + h265e_stream_write1_with_log(s, (sps->m_usePCM != 0) ? 1 : 0, "pcm_enabled_flag"); + if (sps->m_usePCM) { + h265e_stream_write_with_log(s, sps->m_pcmBitDepthLuma - 1, 4, "pcm_sample_bit_depth_luma_minus1"); + h265e_stream_write_with_log(s, sps->m_pcmBitDepthChroma - 1, 4, "pcm_sample_bit_depth_chroma_minus1"); + h265e_stream_write_ue_with_log(s, sps->m_pcmLog2MinSize - 3, "log2_min_pcm_luma_coding_block_size_minus3"); + h265e_stream_write_ue_with_log(s, sps->m_pcmLog2MaxSize - sps->m_pcmLog2MinSize, "log2_diff_max_min_pcm_luma_coding_block_size"); + h265e_stream_write1_with_log(s, (sps->m_bPCMFilterDisableFlag != 0) ? 1 : 0, "pcm_loop_filter_disable_flag"); + } + + mpp_assert(sps->m_maxTLayers > 0); + + H265eRPSList* rpsList = &sps->m_RPSList; + // H265eReferencePictureSet* rps; + + h265e_stream_write_ue_with_log(s, rpsList->m_numberOfReferencePictureSets, "num_short_term_ref_pic_sets"); + for ( i = 0; i < (RK_U32)rpsList->m_numberOfReferencePictureSets; i++) { + mpp_log("todo m_numberOfReferencePictureSets"); + //rps = &rpsList->m_referencePictureSets[i]; + // codeShortTermRefPicSet(rps, false, i); //todo no support + } + h265e_stream_write1_with_log(s, (sps->m_bLongTermRefsPresent != 0) ? 1 : 0, "long_term_ref_pics_present_flag"); + if (sps->m_bLongTermRefsPresent) { + h265e_stream_write_ue_with_log(s, sps->m_numLongTermRefPicSPS, "num_long_term_ref_pic_sps"); + for (k = 0; k < sps->m_numLongTermRefPicSPS; k++) { + h265e_stream_write_with_log(s, sps->m_ltRefPicPocLsbSps[k], sps->m_bitsForPOC, "lt_ref_pic_poc_lsb_sps"); + h265e_stream_write1_with_log(s, sps->m_usedByCurrPicLtSPSFlag[k], "used_by_curr_pic_lt_sps_flag"); + } + } + h265e_stream_write1_with_log(s, (sps->m_TMVPFlagsPresent != 0) ? 1 : 0, "sps_temporal_mvp_enable_flag"); + + h265e_stream_write1_with_log(s, sps->m_useStrongIntraSmoothing, "sps_strong_intra_smoothing_enable_flag"); + + h265e_stream_write1_with_log(s, sps->m_vuiParametersPresentFlag, "vui_parameters_present_flag"); + if (sps->m_vuiParametersPresentFlag) { + codeVUI(s, &sps->vui); + } + h265e_stream_write1_with_log(s, 0, "sps_extension_flag"); + h265e_stream_rbsp_trailing(s); + h265e_stream_flush(s); + h265e_dbg(H265E_DBG_HEADER, "write pure sps head size: %d bits", (s->enc_stream.byte_cnt - sps_byte_start) * 8); + + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +#if 0 +static void h265e_rkv_scaling_list_write( H265eRkvStream *s, + H265ePps *pps, RK_S32 idx ) +{ + +} +#endif + +static MPP_RET h265e_pps_write(H265ePps *pps, H265eSps *sps, H265eStream *s) +{ + (void) sps; + RK_S32 pps_byte_start = 0; + RK_S32 i; + h265e_stream_realign(s); + pps_byte_start = s->enc_stream.byte_cnt; + + h265e_dbg_func("enter\n"); + h265e_stream_write_ue_with_log(s, pps->m_PPSId, "pps_pic_parameter_set_id"); + h265e_stream_write_ue_with_log(s, pps->m_SPSId, "pps_seq_parameter_set_id"); + h265e_stream_write1_with_log(s, 0, "dependent_slice_segments_enabled_flag"); + h265e_stream_write1_with_log(s, (pps->m_outputFlagPresentFlag != 0) ? 1 : 0, "output_flag_present_flag"); + h265e_stream_write_with_log(s, pps->m_numExtraSliceHeaderBits, 3, "num_extra_slice_header_bits"); + h265e_stream_write1_with_log(s, pps->m_signHideFlag, "sign_data_hiding_flag"); + h265e_stream_write1_with_log(s, (pps->m_cabacInitPresentFlag != 0) ? 1 : 0, "cabac_init_present_flag"); + h265e_stream_write_ue_with_log(s, pps->m_numRefIdxL0DefaultActive - 1, "num_ref_idx_l0_default_active_minus1"); + h265e_stream_write_ue_with_log(s, pps->m_numRefIdxL1DefaultActive - 1, "num_ref_idx_l1_default_active_minus1"); + + h265e_stream_write_se_with_log(s, pps->m_picInitQPMinus26, "init_qp_minus26"); + h265e_stream_write1_with_log(s, (pps->m_bConstrainedIntraPred != 0) ? 1 : 0, "constrained_intra_pred_flag"); + h265e_stream_write1_with_log(s, (pps->m_useTransformSkip != 0) ? 1 : 0, "transform_skip_enabled_flag"); + h265e_stream_write1_with_log(s, (pps->m_useDQP != 0) ? 1 : 0, "cu_qp_delta_enabled_flag"); + if (pps->m_useDQP) { + h265e_stream_write_ue_with_log(s, pps->m_maxCuDQPDepth, "diff_cu_qp_delta_depth"); + } + h265e_stream_write_se_with_log(s, pps->m_chromaCbQpOffset, "pps_cb_qp_offset"); + h265e_stream_write_se_with_log(s, pps->m_chromaCrQpOffset, "pps_cr_qp_offset"); + h265e_stream_write1_with_log(s, (pps->m_bSliceChromaQpFlag != 0) ? 1 : 0, "pps_slice_chroma_qp_offsets_present_flag"); + + h265e_stream_write1_with_log(s, (pps->m_bUseWeightPred != 0) ? 1 : 0, "weighted_pred_flag"); // Use of Weighting Prediction (P_SLICE) + h265e_stream_write1_with_log(s, (pps->m_useWeightedBiPred != 0) ? 1 : 0, "weighted_bipred_flag"); // Use of Weighting Bi-Prediction (B_SLICE) + h265e_stream_write1_with_log(s, (pps->m_transquantBypassEnableFlag != 0) ? 1 : 0, "transquant_bypass_enable_flag"); + h265e_stream_write1_with_log(s, pps->m_tiles_enabled_flag, "tiles_enabled_flag"); + h265e_stream_write1_with_log(s, (pps->m_entropyCodingSyncEnabledFlag != 0) ? 1 : 0, "entropy_coding_sync_enabled_flag"); + if (pps->m_tiles_enabled_flag) { + h265e_stream_write_ue_with_log(s, pps->m_nNumTileColumnsMinus1, "num_tile_columns_minus1"); + h265e_stream_write_ue_with_log(s, pps->m_nNumTileRowsMinus1, "num_tile_rows_minus1"); + h265e_stream_write1_with_log(s, pps->m_bTileUniformSpacing, "uniform_spacing_flag"); + if (!pps->m_bTileUniformSpacing) { + for ( i = 0; i < pps->m_nNumTileColumnsMinus1; i++) { + h265e_stream_write_ue_with_log(s, pps->m_nTileColumnWidthArray[i] - 1, "column_width_minus1"); + } + for (i = 0; i < pps->m_nNumTileRowsMinus1; i++) { + h265e_stream_write_ue_with_log(s, pps->m_nTileRowHeightArray[i] - 1, "row_height_minus1"); + } + } + mpp_assert((pps->m_nNumTileColumnsMinus1 + pps->m_nNumTileRowsMinus1) != 0); + h265e_stream_write1_with_log(s, (pps->m_loopFilterAcrossTilesEnabledFlag != 0) ? 1 : 0, "loop_filter_across_tiles_enabled_flag"); + } + h265e_stream_write1_with_log(s, (pps->m_LFCrossSliceBoundaryFlag != 0) ? 1 : 0, "loop_filter_across_slices_enabled_flag"); + + // TODO: Here have some time sequence problem, we set below field in initEncSlice(), but use them in getStreamHeaders() early + h265e_stream_write1_with_log(s, (pps->m_deblockingFilterControlPresentFlag != 0) ? 1 : 0, "deblocking_filter_control_present_flag"); + if (pps->m_deblockingFilterControlPresentFlag) { + h265e_stream_write1_with_log(s, (pps->m_deblockingFilterOverrideEnabledFlag != 0) ? 1 : 0, "deblocking_filter_override_enabled_flag"); + h265e_stream_write1_with_log(s, (pps->m_picDisableDeblockingFilterFlag != 0) ? 1 : 0, "pps_disable_deblocking_filter_flag"); + if (!pps->m_picDisableDeblockingFilterFlag) { + h265e_stream_write_se_with_log(s, pps->m_deblockingFilterBetaOffsetDiv2, "pps_beta_offset_div2"); + h265e_stream_write_se_with_log(s, pps->m_deblockingFilterTcOffsetDiv2, "pps_tc_offset_div2"); + } + } + h265e_stream_write1_with_log(s, (pps->m_scalingListPresentFlag != 0) ? 1 : 0, "pps_scaling_list_data_present_flag"); + if (pps->m_scalingListPresentFlag) { + ;//codeScalingList(m_slice->getScalingList()); //todo + } + h265e_stream_write1_with_log(s, pps->m_listsModificationPresentFlag, "lists_modification_present_flag"); + h265e_stream_write_ue_with_log(s, pps->m_log2ParallelMergeLevelMinus2, "log2_parallel_merge_level_minus2"); + h265e_stream_write1_with_log(s, (pps->m_sliceHeaderExtensionPresentFlag != 0) ? 1 : 0, "slice_segment_header_extension_present_flag"); + h265e_stream_write1_with_log(s, 0, "pps_extension_flag"); + + h265e_stream_rbsp_trailing( s ); + h265e_stream_flush( s ); + + h265e_dbg(H265E_DBG_HEADER, "write pure pps size: %d bits", (s->enc_stream.byte_cnt - pps_byte_start) * 8); + h265e_dbg_func("leave\n"); + + return MPP_OK; +} + +void h265e_nal_start(H265eExtraInfo *out, RK_S32 i_type, + RK_S32 i_ref_idc) +{ + H265eStream *s = &out->stream; + H265eNal *nal = &out->nal[out->nal_num]; + + nal->i_ref_idc = i_ref_idc; + nal->i_type = i_type; + nal->b_long_startcode = 1; + + nal->i_payload = 0; + /* NOTE: consistent with stream_init */ + nal->p_payload = &s->buf[s->enc_stream.byte_cnt]; + nal->i_padding = 0; + + nal->temporal_id = out->temporal_id; +} + +void h265e_nal_end(H265eExtraInfo *out) +{ + H265eNal *nal = &(out->nal[out->nal_num]); + H265eStream *s = &out->stream; + /* NOTE: consistent with stream_init */ + RK_U8 *end = &s->buf[s->enc_stream.byte_cnt]; + nal->i_payload = (RK_S32)(end - nal->p_payload); + /* + * Assembly implementation of nal_escape reads past the end of the input. + * While undefined padding wouldn't actually affect the output, + * it makes valgrind unhappy. + */ + memset(end, 0xff, 64); + out->nal_num++; +} + +MPP_RET h265e_init_extra_info(void *extra_info) +{ + + H265eExtraInfo *info = (H265eExtraInfo *)extra_info; + // random ID number generated according to ISO-11578 + // NOTE: any element of h264e_sei_uuid should NOT be 0x00, + // otherwise the string length of sei_buf will always be the distance between the + // element 0x00 address and the sei_buf start address. + static const RK_U8 h265e_sei_uuid[H265E_UUID_LENGTH] = { + 0x67, 0xfc, 0x6a, 0x3c, 0xd8, 0x5c, 0x44, 0x1e, + 0x87, 0xfb, 0x3f, 0xab, 0xec, 0xb3, 0x36, 0x77 + }; + + h265e_nals_init(info); + h265e_stream_init(&info->stream); + + info->sei_buf = mpp_calloc_size(RK_U8, H265E_SEI_BUF_SIZE); + memcpy(info->sei_buf, h265e_sei_uuid, H265E_UUID_LENGTH); + + return MPP_OK; +} + +MPP_RET h265e_deinit_extra_info(void *extra_info) +{ + H265eExtraInfo *info = (H265eExtraInfo *)extra_info; + h265e_stream_deinit(&info->stream); + h265e_nals_deinit(info); + + MPP_FREE(info->sei_buf); + + return MPP_OK; +} + +MPP_RET h265e_set_extra_info(H265eCtx *ctx) +{ + H265eExtraInfo *info = (H265eExtraInfo *)ctx->extra_info; + H265eSps *sps = &ctx->sps; + H265ePps *pps = &ctx->pps; + H265eVps *vps = &ctx->vps; + + h265e_dbg_func("enter\n"); + info->nal_num = 0; + info->temporal_id = 0; + h265e_stream_reset(&info->stream); + + h265e_nal_start(info, NAL_VPS, H265_NAL_PRIORITY_HIGHEST); + h265e_set_vps(ctx, vps); + h265e_vps_write(vps, &info->stream); + h265e_nal_end(info); + + h265e_nal_start(info, NAL_SPS, H265_NAL_PRIORITY_HIGHEST); + h265e_set_sps(ctx, sps, vps); + h265e_sps_write(sps, &info->stream); + h265e_nal_end(info); + + h265e_nal_start(info, NAL_PPS, H265_NAL_PRIORITY_HIGHEST); + h265e_set_pps(ctx, pps, sps); + h265e_pps_write(pps, sps, &info->stream); + h265e_nal_end(info); + + h265e_encapsulate_nals(info); + + h265e_dbg_func("leave\n"); + return MPP_OK; +} + +RK_U32 h265e_data_to_sei(void *dst, RK_U8 uuid[16], const void *payload, RK_S32 size) +{ + H265eNal sei_nal; + H265eStream stream; + + h265e_dbg_func("enter\n"); + + h265e_stream_init(&stream); + memset(&sei_nal, 0 , sizeof(H265eNal)); + + sei_nal.i_type = NAL_SEI_PREFIX; + sei_nal.p_payload = &stream.buf[stream.enc_stream.byte_cnt]; + + h265e_sei_write(&stream, uuid, payload, size, H265_SEI_USER_DATA_UNREGISTERED); + + RK_U8 *end = &stream.buf[stream.enc_stream.byte_cnt]; + sei_nal.i_payload = (RK_S32)(end - sei_nal.p_payload); + + h265e_nal_encode(dst, &sei_nal); + + h265e_stream_deinit(&stream); + + h265e_dbg_func("leave\n"); + return sei_nal.i_payload; +} + +MPP_RET h265e_get_extra_info(H265eCtx *ctx, MppPacket pkt_out) +{ + RK_S32 k = 0; + size_t offset = 0; + + if (pkt_out == NULL) + return MPP_NOK; + + h265e_dbg_func("enter\n"); + + H265eExtraInfo *src = (H265eExtraInfo *)ctx->extra_info; + + for (k = 0; k < src->nal_num; k++) { + h265e_dbg(H265E_DBG_HEADER, "get extra info nal type %d, size %d bytes", + src->nal[k].i_type, src->nal[k].i_payload); + mpp_packet_write(pkt_out, offset, src->nal[k].p_payload, src->nal[k].i_payload); + mpp_packet_add_segment_info(pkt_out, src->nal[k].i_type, + offset, src->nal[k].i_payload); + offset += src->nal[k].i_payload; + } + mpp_packet_set_length(pkt_out, offset); + + h265e_dbg_func("leave\n"); + return MPP_OK; +} diff --git a/mpp/codec/enc/h265/h265e_header_gen.h b/mpp/codec/enc/h265/h265e_header_gen.h new file mode 100644 index 000000000..5493cd2f5 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_header_gen.h @@ -0,0 +1,113 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_HEADER_GEN_H +#define H265E_HEADER_GEN_H + +#include "h265e_stream.h" +#define H265E_UUID_LENGTH 16 + +typedef enum H265eNalIdx_t { + H265E_NAL_IDX_VPS, + H265E_NAL_IDX_SPS, + H265E_NAL_IDX_PPS, + H265E_NAL_IDX_SEI, + H265E_NAL_IDX_BUTT, +} H265eNalIdx; + +typedef enum H265SeiType_e { + H265_SEI_BUFFERING_PERIOD = 0, + H265_SEI_PICTURE_TIMING = 1, + H265_SEI_PAN_SCAN_RECT = 2, + H265_SEI_FILLER_PAYLOAD = 3, + H265_SEI_USER_DATA_REGISTERED_ITU_T_T35 = 4, + H265_SEI_USER_DATA_UNREGISTERED = 5, + H265_SEI_RECOVERY_POINT = 6, + H265_SEI_SCENE_INFO = 9, + H265_SEI_FULL_FRAME_SNAPSHOT = 15, + H265_SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, + H265_SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, + H265_SEI_FILM_GRAIN_CHARACTERISTICS = 19, + H265_SEI_POST_FILTER_HINT = 22, + H265_SEI_TONE_MAPPING_INFO = 23, + H265_SEI_FRAME_PACKING = 45, + H265_SEI_DISPLAY_ORIENTATION = 47, + H265_SEI_SOP_DESCRIPTION = 128, + H265_SEI_ACTIVE_PARAMETER_SETS = 129, + H265_SEI_DECODING_UNIT_INFO = 130, + H265_SEI_TEMPORAL_LEVEL0_INDEX = 131, + H265_SEI_DECODED_PICTURE_HASH = 132, + H265_SEI_SCALABLE_NESTING = 133, + H265_SEI_REGION_REFRESH_INFO = 134, + H265_SEI_MAX_ELEMENTS = 255, //!< number of maximum syntax elements +} H265SeiType; + +typedef struct H265eNal_t { + RK_S32 i_ref_idc; /* nal_priority_e */ + RK_S32 i_type; /* nal_unit_type_e */ + RK_S32 b_long_startcode; + RK_S32 i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */ + RK_S32 i_last_mb; /* If this NAL is a slice, the index of the last MB in the slice. */ + + /* Size of payload (including any padding) in bytes. */ + RK_S32 i_payload; + /* If param->b_annexb is set, Annex-B bytestream with startcode. + * Otherwise, startcode is replaced with a 4-byte size. + * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */ + RK_U8 *p_payload; + + /* Size of padding in bytes. */ + RK_S32 i_padding; + RK_S32 sh_head_len; + RK_S32 temporal_id; +} H265eNal; + +typedef struct H265eExtraInfo_t { + RK_S32 nal_num; + H265eNal nal[H265E_NAL_IDX_BUTT]; + RK_U8 *nal_buf; + RK_U8 *sei_buf; + RK_U32 sei_change_flg; + H265eStream stream; +// H265eSei sei; + RK_S32 temporal_id; +} H265eExtraInfo; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h265e_init_extra_info(void *extra_info); +MPP_RET h265e_deinit_extra_info(void *extra_info); +void h265e_rkv_nal_start(H265eExtraInfo *out, RK_S32 i_type, + RK_S32 i_ref_idc); + +void h265e_nal_end(H265eExtraInfo *out); + +RK_U32 h265e_data_to_sei(void *dst, RK_U8 uuid[16], const void *payload, RK_S32 size); +MPP_RET h265e_sei_recovery_point(void *dst, RK_U8 uuid[16], const void *payload, + RK_S32 size); + +typedef struct H265eCtx_t H265eCtx; + +MPP_RET h265e_set_extra_info(H265eCtx *ctx); +MPP_RET h265e_get_extra_info(H265eCtx *ctx, MppPacket pkt_out); + +#ifdef __cplusplus +} +#endif + +#endif /* H265E_HEADER_GEN_H */ diff --git a/mpp/codec/enc/h265/h265e_ps.c b/mpp/codec/enc/h265/h265e_ps.c new file mode 100644 index 000000000..c1ae06c25 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_ps.c @@ -0,0 +1,503 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_ps" + +#include + +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_common.h" + +#include "h265e_ps.h" +#include "mpp_enc_ref.h" + +#define MAX_UINT 0xFFFFFFFFU + +typedef struct H265levelspec_t { + RK_U32 maxLumaSamples; + RK_U32 maxLumaSamplesPerSecond; + RK_U32 maxBitrateMain; + RK_U32 maxBitrateHigh; + RK_U32 maxCpbSizeMain; + RK_U32 maxCpbSizeHigh; + RK_U32 minCompressionRatio; + RK_S32 levelEnum; + const char* name; + RK_S32 levelIdc; +} H265levelspec; + +H265levelspec levels[] = { + { 36864, 552960, 128, MAX_UINT, 350, MAX_UINT, 2, H265_LEVEL1, "1", 10 }, + { 122880, 3686400, 1500, MAX_UINT, 1500, MAX_UINT, 2, H265_LEVEL2, "2", 20 }, + { 245760, 7372800, 3000, MAX_UINT, 3000, MAX_UINT, 2, H265_LEVEL2_1, "2.1", 21 }, + { 552960, 16588800, 6000, MAX_UINT, 6000, MAX_UINT, 2, H265_LEVEL3, "3", 30 }, + { 983040, 33177600, 10000, MAX_UINT, 10000, MAX_UINT, 2, H265_LEVEL3_1, "3.1", 31 }, + { 2228224, 66846720, 12000, 30000, 12000, 30000, 4, H265_LEVEL4, "4", 40 }, + { 2228224, 133693440, 20000, 50000, 20000, 50000, 4, H265_LEVEL4_1, "4.1", 41 }, + { 8912896, 267386880, 25000, 100000, 25000, 100000, 6, H265_LEVEL5, "5", 50 }, + { 8912896, 534773760, 40000, 160000, 40000, 160000, 8, H265_LEVEL5_1, "5.1", 51 }, + { 8912896, 1069547520, 60000, 240000, 60000, 240000, 8, H265_LEVEL5_2, "5.2", 52 }, + { 35651584, 1069547520, 60000, 240000, 60000, 240000, 8, H265_LEVEL6, "6", 60 }, + { 35651584, 2139095040, 120000, 480000, 120000, 480000, 8, H265_LEVEL6_1, "6.1", 61 }, + { 35651584, 4278190080U, 240000, 800000, 240000, 800000, 6, H265_LEVEL6_2, "6.2", 62 }, + { MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, MAX_UINT, 1, H265_LEVEL8_5, "8.5", 85 }, +}; + +void init_zscan2raster(RK_S32 maxDepth, RK_S32 depth, RK_U32 startVal, RK_U32** curIdx) +{ + RK_S32 stride = 1 << (maxDepth - 1); + if (depth == maxDepth) { + (*curIdx)[0] = startVal; + (*curIdx)++; + } else { + RK_S32 step = stride >> depth; + init_zscan2raster(maxDepth, depth + 1, startVal, curIdx); + init_zscan2raster(maxDepth, depth + 1, startVal + step, curIdx); + init_zscan2raster(maxDepth, depth + 1, startVal + step * stride, curIdx); + init_zscan2raster(maxDepth, depth + 1, startVal + step * stride + step, curIdx); + } +} + +void init_raster2zscan(RK_U32 maxCUSize, RK_U32 maxDepth, RK_U32 *raster2zscan, RK_U32 *zscan2raster) +{ + RK_U32 unitSize = maxCUSize >> (maxDepth - 1); + RK_U32 numPartInCUSize = (RK_U32)maxCUSize / unitSize; + RK_U32 i; + + for ( i = 0; i < numPartInCUSize * numPartInCUSize; i++) { + raster2zscan[zscan2raster[i]] = i; + } +} + +void init_raster2pelxy(RK_U32 maxCUSize, RK_U32 maxDepth, RK_U32 *raster2pelx, RK_U32 *raster2pely) +{ + RK_U32 i; + + RK_U32* tempx = &raster2pelx[0]; + RK_U32* tempy = &raster2pely[0]; + + RK_U32 unitSize = maxCUSize >> (maxDepth - 1); + + RK_U32 numPartInCUSize = maxCUSize / unitSize; + + tempx[0] = 0; + tempx++; + for (i = 1; i < numPartInCUSize; i++) { + tempx[0] = tempx[-1] + unitSize; + tempx++; + } + + for (i = 1; i < numPartInCUSize; i++) { + memcpy(tempx, tempx - numPartInCUSize, sizeof(RK_U32) * numPartInCUSize); + tempx += numPartInCUSize; + } + + for (i = 1; i < numPartInCUSize * numPartInCUSize; i++) { + tempy[i] = (i / numPartInCUSize) * unitSize; + } +} + +MPP_RET h265e_set_vps(H265eCtx *ctx, H265eVps *vps) +{ + RK_S32 i; + MppEncH265Cfg *codec = &ctx->cfg->h265; + ProfileTierLevel *profileTierLevel = &vps->m_ptl.m_generalPTL; + MppEncPrepCfg *prep = &ctx->cfg->prep; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + RK_U32 maxlumas = prep->width * prep->height; + RK_S32 level_idc = H265_LEVEL_NONE; + MppEncRefCfgImpl *refs = (MppEncRefCfgImpl *)ref_cfg; + + vps->m_VPSId = 0; + vps->m_maxTLayers = refs->max_tlayers ? refs->max_tlayers : 1; + vps->m_maxLayers = vps->m_maxTLayers; + vps->m_bTemporalIdNestingFlag = 1; + vps->m_numHrdParameters = 0; + vps->m_maxNuhReservedZeroLayerId = 0; + vps->m_hrdParameters = NULL; + vps->m_hrdOpSetIdx = NULL; + vps->m_cprmsPresentFlag = NULL; + for (i = 0; i < MAX_SUB_LAYERS; i++) { + vps->m_numReorderPics[i] = 0; + vps->m_maxDecPicBuffering[i] = MPP_MIN(MAX_REFS, MPP_MAX((vps->m_numReorderPics[i] + 3), codec->num_ref) + vps->m_numReorderPics[i]); + vps->m_maxLatencyIncrease[i] = 0; + } + memset(profileTierLevel->m_profileCompatibilityFlag, 0, sizeof(profileTierLevel->m_profileCompatibilityFlag)); + memset(vps->m_ptl.m_subLayerProfilePresentFlag, 0, sizeof(vps->m_ptl.m_subLayerProfilePresentFlag)); + memset(vps->m_ptl.m_subLayerLevelPresentFlag, 0, sizeof(vps->m_ptl.m_subLayerLevelPresentFlag)); + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(levels); i++) { + if (levels[i].maxLumaSamples >= maxlumas) { + level_idc = levels[i].levelEnum; + break; + } + } + + profileTierLevel->m_profileSpace = 0; + if (codec->level < level_idc) { + profileTierLevel->m_levelIdc = level_idc; + } else { + profileTierLevel->m_levelIdc = codec->level; + } + profileTierLevel->m_tierFlag = codec->tier ? 1 : 0; + + if ((prep->format & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV400) { + /* general_profile_idc == 4 */ + codec->profile = MPP_PROFILE_HEVC_FORMAT_RANGE_EXTENDIONS; + profileTierLevel->m_max12bitConstraintFlag = 1; + profileTierLevel->m_max10bitConstraintFlag = 1; + profileTierLevel->m_max8bitConstraintFlag = 1; + profileTierLevel->m_max422chromaConstraintFlag = 1; + profileTierLevel->m_max420chromaConstraintFlag = 1; + profileTierLevel->m_maxMonochromaConstraintFlag = 1; + profileTierLevel->m_lowerBitRateConstraintFlag = 1; + } else { + /* general_profile_idc == 2 */ + profileTierLevel->m_profileCompatibilityFlag[2] = 1; + } + + profileTierLevel->m_profileIdc = codec->profile; + profileTierLevel->m_profileCompatibilityFlag[codec->profile] = 1; + profileTierLevel->m_progressiveSourceFlag = 1; + profileTierLevel->m_nonPackedConstraintFlag = 0; + profileTierLevel->m_frameOnlyConstraintFlag = 0; + return MPP_OK; +} + +MPP_RET h265e_set_sps(H265eCtx *ctx, H265eSps *sps, H265eVps *vps) +{ + RK_U32 i, c; + MppEncH265Cfg *codec = &ctx->cfg->h265; + MppEncPrepCfg *prep = &ctx->cfg->prep; + MppEncRcCfg *rc = &ctx->cfg->rc; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + MppEncVuiCfg *vui = &codec->vui; + MppFrameFormat fmt = prep->format & MPP_FRAME_FMT_MASK; + RK_S32 i_timebase_num = rc->fps_out_denom; + RK_S32 i_timebase_den = rc->fps_out_num; + RK_U8 convertToBit[MAX_CU_SIZE + 1]; + RK_U32 maxCUDepth, minCUDepth, addCUDepth; + RK_S32 pad[2] = {0}; + RK_S32 minCUSize, log2MinCUSize; + RK_S32 tuQTMinLog2Size = 2, tuQTMaxLog2Size; + MppEncCpbInfo *cpb_info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + RockchipSocType soc_type; + RK_U32 *tmp = &sps->zscan2raster[0]; + + memset(convertToBit, -1, sizeof(convertToBit)); + c = 0; + for (i = 4; i <= MAX_CU_SIZE; i *= 2) { + convertToBit[i] = c; + c++; + } + + maxCUDepth = (uint32_t)convertToBit[codec->max_cu_size]; + + minCUDepth = (codec->max_cu_size >> (maxCUDepth - 1)); + + tuQTMaxLog2Size = convertToBit[codec->max_cu_size] + 2 - 1; + soc_type = mpp_get_soc_type(); + if (soc_type == ROCKCHIP_SOC_RK3576 || + soc_type == ROCKCHIP_SOC_RV1126B || + soc_type == ROCKCHIP_SOC_RK3572) { + tuQTMaxLog2Size = tuQTMaxLog2Size + 1; + } + + addCUDepth = 0; + while ((RK_U32)(codec->max_cu_size >> maxCUDepth) > (1u << (tuQTMinLog2Size + addCUDepth))) { + addCUDepth++; + } + + maxCUDepth += addCUDepth; + addCUDepth++; + init_zscan2raster(maxCUDepth + 1, 1, 0, &tmp ); + init_raster2zscan(codec->max_cu_size, maxCUDepth + 1, &sps->raster2zscan[0], &sps->zscan2raster[0]); + init_raster2pelxy(codec->max_cu_size, maxCUDepth + 1, &sps->raster2pelx[0], &sps->raster2pely[0]); + + memset(&sps->m_conformanceWindow, 0, sizeof(H265eCropInfo)); + if ((prep->width % minCUDepth) != 0) { + RK_U32 padsize = 0; + RK_U32 rem = prep->width % minCUDepth; + padsize = minCUDepth - rem; + pad[0] = padsize; //pad width + + /* set the confirmation window offsets */ + sps->m_conformanceWindow.m_enabledFlag = 1; + sps->m_conformanceWindow.m_winRightOffset = pad[0]; + } + + if ((prep->height % minCUDepth) != 0) { + RK_U32 padsize = 0; + RK_U32 rem = prep->height % minCUDepth; + padsize = minCUDepth - rem; + pad[1] = padsize; //pad height + + /* set the confirmation window offsets */ + sps->m_conformanceWindow.m_enabledFlag = 1; + sps->m_conformanceWindow.m_winBottomOffset = pad[1]; + } + // pad[0] = p->sourceWidth - p->oldSourceWidth; + // pad[1] = p->sourceHeight - p->oldSourceHeight; + + sps->m_SPSId = 0; + sps->m_VPSId = 0; + sps->m_chromaFormatIdc = (fmt == MPP_FMT_YUV400) ? H265_CHROMA_400 : H265_CHROMA_420; + sps->m_maxTLayers = vps->m_maxLayers; + sps->m_picWidthInLumaSamples = prep->width + pad[0]; + sps->m_picHeightInLumaSamples = prep->height + pad[1]; + sps->m_log2MinCodingBlockSize = 0; + sps->m_log2DiffMaxMinCodingBlockSize = 0 ; + sps->m_maxCUSize = codec->max_cu_size; + sps->m_maxCUDepth = maxCUDepth; + sps->m_addCUDepth = addCUDepth; + sps->m_RPSList.m_numberOfReferencePictureSets = 0; + sps->m_RPSList.m_referencePictureSets = NULL; + + minCUSize = sps->m_maxCUSize >> (sps->m_maxCUDepth - addCUDepth); + log2MinCUSize = 0; + while (minCUSize > 1) { + minCUSize >>= 1; + log2MinCUSize++; + } + sps->m_log2MinCodingBlockSize = log2MinCUSize; + sps->m_log2DiffMaxMinCodingBlockSize = sps->m_maxCUDepth - addCUDepth; + + sps->m_pcmLog2MaxSize = 5; + sps->m_usePCM = 0; + sps->m_pcmLog2MinSize = 3; + + + sps->m_bLongTermRefsPresent = 0; + sps->m_quadtreeTULog2MaxSize = tuQTMaxLog2Size; + sps->m_quadtreeTULog2MinSize = tuQTMinLog2Size; + sps->m_quadtreeTUMaxDepthInter = 1; //tuQTMaxInterDepth + sps->m_quadtreeTUMaxDepthIntra = 1; //tuQTMaxIntraDepth + sps->m_useLossless = 0; + + for (i = 0; i < (maxCUDepth - addCUDepth); i++) { + sps->m_iAMPAcc[i] = codec->amp_enable; + } + sps->m_useAMP = codec->amp_enable; + for (i = maxCUDepth - addCUDepth; i < maxCUDepth; i++) { + sps->m_iAMPAcc[i] = codec->amp_enable; + } + + sps->m_bitDepthY = 8; + sps->m_bitDepthC = 8; + sps->m_qpBDOffsetY = 0; + sps->m_qpBDOffsetC = 0; + + sps->m_bUseSAO = codec->sao_enable; + sps->m_bTemporalIdNestingFlag = 1; + + for (i = 0; i < sps->m_maxTLayers; i++) { + sps->m_maxDecPicBuffering[i] = vps->m_maxDecPicBuffering[i]; + sps->m_numReorderPics[i] = vps->m_numReorderPics[i]; + } + + sps->m_pcmBitDepthLuma = 8; + sps->m_pcmBitDepthChroma = 8; + + sps->m_bPCMFilterDisableFlag = 0; + sps->m_scalingListEnabledFlag = codec->trans_cfg.scaling_list_mode == 0 ? 0 : 1; + + sps->m_bitsForPOC = 16; + sps->m_numLongTermRefPicSPS = 0; + sps->m_maxTrSize = 32; + sps->m_bLongTermRefsPresent = 0; + sps->m_TMVPFlagsPresent = codec->tmvp_enable; + sps->m_useStrongIntraSmoothing = codec->cu_cfg.strong_intra_smoothing_enabled_flag; + if (cpb_info->max_lt_cnt) { + sps->m_numLongTermRefPicSPS = cpb_info->max_lt_cnt; + sps->m_bLongTermRefsPresent = 1; + sps->m_TMVPFlagsPresent = 0; + codec->tmvp_enable = 0; + } else if (cpb_info->max_st_tid) { + sps->m_TMVPFlagsPresent = 0; + } + + if (rc->drop_mode == MPP_ENC_RC_DROP_FRM_PSKIP) { + codec->tmvp_enable = 0; + sps->m_TMVPFlagsPresent = 0; + codec->sao_enable = 0; + sps->m_bUseSAO = 0; + } + + sps->m_ptl = &vps->m_ptl; + sps->m_vuiParametersPresentFlag = vui->vui_en; + if (sps->m_vuiParametersPresentFlag) { + sps->vui.m_aspectRatioInfoPresentFlag = 0; + sps->vui.m_aspectRatioIdc = 0; + sps->vui.m_sarWidth = 0; + sps->vui.m_sarHeight = 0; + sps->vui.m_overscanInfoPresentFlag = 0; + sps->vui.m_overscanAppropriateFlag = 0; + sps->vui.m_videoSignalTypePresentFlag = 0; + sps->vui.m_videoFormat = MPP_FRAME_VIDEO_FMT_UNSPECIFIED; + if (prep->range == MPP_FRAME_RANGE_JPEG) { + sps->vui.m_videoFullRangeFlag = 1; + sps->vui.m_videoSignalTypePresentFlag = 1; + } + + if ((prep->colorprim <= MPP_FRAME_PRI_JEDEC_P22 && + prep->colorprim != MPP_FRAME_PRI_UNSPECIFIED) || + (prep->colortrc <= MPP_FRAME_TRC_ARIB_STD_B67 && + prep->colortrc != MPP_FRAME_TRC_UNSPECIFIED) || + (prep->color <= MPP_FRAME_SPC_ICTCP && + prep->color != MPP_FRAME_SPC_UNSPECIFIED)) { + sps->vui.m_videoSignalTypePresentFlag = 1; + sps->vui.m_colourDescriptionPresentFlag = 1; + sps->vui.m_colourPrimaries = prep->colorprim; + sps->vui.m_transferCharacteristics = prep->colortrc; + sps->vui.m_matrixCoefficients = prep->color; + } + + sps->vui.m_chromaLocInfoPresentFlag = 0; + sps->vui.m_chromaSampleLocTypeTopField = 0; + sps->vui.m_chromaSampleLocTypeBottomField = 0; + sps->vui.m_neutralChromaIndicationFlag = 0; + sps->vui.m_fieldSeqFlag = 0; + sps->vui.m_frameFieldInfoPresentFlag = 0; + sps->vui.m_hrdParametersPresentFlag = 0; + sps->vui.m_bitstreamRestrictionFlag = 0; + sps->vui.m_tilesFixedStructureFlag = 0; + sps->vui.m_motionVectorsOverPicBoundariesFlag = 1; + sps->vui.m_restrictedRefPicListsFlag = 1; + sps->vui.m_minSpatialSegmentationIdc = 0; + sps->vui.m_maxBytesPerPicDenom = 2; + sps->vui.m_maxBitsPerMinCuDenom = 1; + sps->vui.m_log2MaxMvLengthHorizontal = 15; + sps->vui.m_log2MaxMvLengthVertical = 15; + if (vui->vui_aspect_ratio) { + sps->vui.m_aspectRatioInfoPresentFlag = !!vui->vui_aspect_ratio; + sps->vui.m_aspectRatioIdc = vui->vui_aspect_ratio; + } + sps->vui.m_timingInfo.m_timingInfoPresentFlag = 1; + sps->vui.m_timingInfo.m_numUnitsInTick = i_timebase_num; + sps->vui.m_timingInfo.m_timeScale = i_timebase_den; + } + + + + for (i = 0; i < MAX_SUB_LAYERS; i++) { + sps->m_maxLatencyIncrease[i] = 0; + } + // sps->m_scalingList = NULL; + memset(sps->m_ltRefPicPocLsbSps, 0, sizeof(sps->m_ltRefPicPocLsbSps)); + memset(sps->m_usedByCurrPicLtSPSFlag, 0, sizeof(sps->m_usedByCurrPicLtSPSFlag)); + return 0; +} + +MPP_RET h265e_set_pps(H265eCtx *ctx, H265ePps *pps, H265eSps *sps) +{ + MppEncH265Cfg *codec = &ctx->cfg->h265; + + pps->m_bConstrainedIntraPred = codec->const_intra_pred; + pps->m_PPSId = 0; + pps->m_SPSId = 0; + pps->m_picInitQPMinus26 = 0; + pps->m_useDQP = 1; + pps->m_maxCuDQPDepth = codec->trans_cfg.diff_cu_qp_delta_depth; + pps->m_minCuDQPSize = (sps->m_maxCUSize >> pps->m_maxCuDQPDepth); + + pps->m_sps = sps; + pps->m_bSliceChromaQpFlag = 0; + pps->m_chromaCbQpOffset = codec->trans_cfg.cb_qp_offset; + /* rkvenc hw only support one color qp offset. Set all offset to cb offset*/ + pps->m_chromaCrQpOffset = codec->trans_cfg.cb_qp_offset; + + pps->m_entropyCodingSyncEnabledFlag = 0; + pps->m_bUseWeightPred = 0; + pps->m_useWeightedBiPred = 0; + pps->m_outputFlagPresentFlag = 0; + pps->m_signHideFlag = 0; + pps->m_picInitQPMinus26 = codec->intra_qp - 26; + pps->m_LFCrossSliceBoundaryFlag = codec->lpf_acs_sli_en; + pps->m_deblockingFilterControlPresentFlag = !codec->dblk_cfg.slice_deblocking_filter_disabled_flag; + if (pps->m_deblockingFilterControlPresentFlag) { + pps->m_deblockingFilterOverrideEnabledFlag = 0; + pps->m_picDisableDeblockingFilterFlag = 0; + if (!pps->m_picDisableDeblockingFilterFlag) { + pps->m_deblockingFilterBetaOffsetDiv2 = codec->dblk_cfg.slice_beta_offset_div2; + pps->m_deblockingFilterTcOffsetDiv2 = codec->dblk_cfg.slice_tc_offset_div2; + } + } else { + pps->m_deblockingFilterOverrideEnabledFlag = 0; + pps->m_picDisableDeblockingFilterFlag = 1; + pps->m_deblockingFilterBetaOffsetDiv2 = 0; + pps->m_deblockingFilterTcOffsetDiv2 = 0; + } + + pps->m_listsModificationPresentFlag = 1; + pps->m_log2ParallelMergeLevelMinus2 = 0; + pps->m_numRefIdxL0DefaultActive = 1; + pps->m_numRefIdxL1DefaultActive = 1; + pps->m_transquantBypassEnableFlag = codec->trans_cfg.transquant_bypass_enabled_flag; + pps->m_useTransformSkip = codec->trans_cfg.transform_skip_enabled_flag; + + pps->m_entropyCodingSyncEnabledFlag = 0; + pps->m_signHideFlag = 0; + pps->m_cabacInitPresentFlag = codec->entropy_cfg.cabac_init_flag; + pps->m_encCABACTableIdx = I_SLICE; + pps->m_sliceHeaderExtensionPresentFlag = 0; + pps->m_numExtraSliceHeaderBits = 0; + pps->m_tiles_enabled_flag = 0; + pps->m_bTileUniformSpacing = 0; + pps->m_nNumTileRowsMinus1 = 0; + pps->m_nNumTileColumnsMinus1 = 0; + pps->m_loopFilterAcrossTilesEnabledFlag = !codec->lpf_acs_tile_disable; + { + RockchipSocType soc_type = mpp_get_soc_type(); + RK_S32 index; + RK_S32 mb_w = (sps->m_picWidthInLumaSamples + sps->m_maxCUSize - 1) / sps->m_maxCUSize; + RK_S32 mb_h = (sps->m_picHeightInLumaSamples + sps->m_maxCUSize - 1) / sps->m_maxCUSize; + RK_S32 tile_width; + + /* check tile support on rk3566 and rk3568 */ + if (soc_type == ROCKCHIP_SOC_RK3566 || soc_type == ROCKCHIP_SOC_RK3568) { + pps->m_nNumTileColumnsMinus1 = (sps->m_picWidthInLumaSamples - 1) / 1920 ; + } else if (soc_type == ROCKCHIP_SOC_RK3588) { + if (sps->m_picWidthInLumaSamples > 8192) { + /* 4 tile for over 8k encoding */ + pps->m_nNumTileColumnsMinus1 = 3; + } else if (sps->m_picWidthInLumaSamples > 4096) { + /* 2 tile for 4k ~ 8k encoding */ + pps->m_nNumTileColumnsMinus1 = 1; + } else { + /* 1 tile for less 4k encoding and use 2 tile on auto tile enabled */ + pps->m_nNumTileColumnsMinus1 = codec->auto_tile ? 1 : 0; + } + } + if (pps->m_nNumTileColumnsMinus1) { + pps->m_tiles_enabled_flag = 1; + pps->m_bTileUniformSpacing = 1; + pps->m_loopFilterAcrossTilesEnabledFlag = !codec->lpf_acs_tile_disable; + + /* calc width per tile */ + for (index = 0; index < pps->m_nNumTileColumnsMinus1; index++) { + tile_width = (index + 1) * mb_w / (pps->m_nNumTileColumnsMinus1 + 1) - + index * mb_w / (pps->m_nNumTileColumnsMinus1 + 1); + pps->m_nTileColumnWidthArray[index] = tile_width; + pps->m_nTileRowHeightArray[index] = mb_h; + } + tile_width = mb_w - index * mb_w / (pps->m_nNumTileColumnsMinus1 + 1); + pps->m_nTileColumnWidthArray[index] = tile_width; + pps->m_nTileRowHeightArray[index] = mb_h; + } + } + + return 0; +} diff --git a/mpp/codec/enc/h265/h265e_ps.h b/mpp/codec/enc/h265/h265e_ps.h new file mode 100644 index 000000000..c1e188159 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_ps.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_PS_H +#define H265E_PS_H + +#include "h265e_slice.h" +#include "h265e_codec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h265e_set_sps(H265eCtx *ctx, H265eSps *sps, H265eVps *vps); +MPP_RET h265e_set_pps(H265eCtx *ctx, H265ePps *pps, H265eSps *sps); +MPP_RET h265e_set_vps(H265eCtx *ctx, H265eVps *vps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/codec/enc/h265/h265e_slice.c b/mpp/codec/enc/h265/h265e_slice.c new file mode 100644 index 000000000..6de3f65b1 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_slice.c @@ -0,0 +1,899 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_slice" + +#include + +#include "mpp_debug.h" +#include "h265e_codec.h" +#include "h265e_slice.h" + +H265eDpbFrm* get_ref_pic(H265eDpbFrm *frame_list, RK_S32 poc) +{ + RK_S32 index = 0; + H265eDpbFrm *frame = NULL; + + h265e_dbg_func("enter\n"); + for (index = 0; index < MAX_REFS; index++) { + frame = &frame_list[index]; + if (frame->inited && frame->poc == poc) { + break; + } + } + h265e_dbg_func("leave\n"); + return frame; +} + +H265eDpbFrm* get_lt_ref_pic(H265eDpbFrm *frame_list, H265eSlice *slice, RK_S32 poc, RK_U32 pocHasMsb) +{ + RK_S32 index = 0; + H265eDpbFrm *frame = NULL; + H265eDpbFrm* stPic = &frame_list[MAX_REFS - 1]; + RK_S32 pocCycle = 1 << slice->m_sps->m_bitsForPOC; + + h265e_dbg_func("enter\n"); + if (!pocHasMsb) { + poc = poc % pocCycle; + } + + for (index = MAX_REFS - 1 ; index >= 0; index--) { + frame = &frame_list[index]; + if (frame->on_used && frame->poc != slice->poc && frame->slice->is_referenced) { + RK_S32 picPoc = frame->poc; + if (!pocHasMsb) { + picPoc = picPoc % pocCycle; + } + + if (poc == picPoc) { + if (frame->is_long_term) { + return frame; + } else { + stPic = frame; + } + } + } + + } + h265e_dbg_func("leave\n"); + return stPic; +} + +void h265e_slice_set_ref_list(H265eDpbFrm *frame_list, H265eSlice *slice) +{ + H265eReferencePictureSet *rps = slice->m_rps; + H265eDpbFrm* refPic = NULL; + H265eDpbFrm* refPicSetStCurr0[MAX_REFS]; + H265eDpbFrm* refPicSetStCurr1[MAX_REFS]; + H265eDpbFrm* refPicSetLtCurr[MAX_REFS]; + RK_S32 numPocStCurr0 = 0; + RK_S32 numPocStCurr1 = 0; + RK_S32 numPocLtCurr = 0; + RK_S32 i, cIdx = 0, rIdx = 0; + + h265e_dbg_func("enter\n"); + if (slice->m_sliceType == I_SLICE) { + memset(slice->m_refPicList, 0, sizeof(slice->m_refPicList)); + memset(slice->m_numRefIdx, 0, sizeof(slice->m_numRefIdx)); + return; + } + for (i = 0; i < rps->num_negative_pic; i++) { + if (rps->m_used[i]) { + refPic = get_ref_pic(frame_list, slice->poc + rps->delta_poc[i]); + refPic->is_long_term = 0; + refPicSetStCurr0[numPocStCurr0] = refPic; + numPocStCurr0++; + refPic->check_lt_msb = 0; + } + } + + for (; i < rps->num_negative_pic + rps->num_positive_pic; i++) { + if (rps->m_used[i]) { + refPic = get_ref_pic(frame_list, slice->poc + rps->delta_poc[i]); + refPic->is_long_term = 0; + refPicSetStCurr1[numPocStCurr1] = refPic; + numPocStCurr1++; + refPic->check_lt_msb = 0; + } + } + + for (i = rps->num_negative_pic + rps->num_positive_pic + rps->num_long_term_pic - 1; + i > rps->num_negative_pic + rps->num_positive_pic - 1; i--) { + if (rps->m_used[i]) { + refPic = get_lt_ref_pic(frame_list, slice, rps->m_RealPoc[i], rps->check_lt_msb[i]); + refPic->is_long_term = 1; + /*due to only one ref if num_negative_pic > 0 set lt not used*/ + /* if (rps->num_negative_pic > 0) { + rps->m_used[i] = 0; + }*/ + refPicSetLtCurr[numPocLtCurr] = refPic; + numPocLtCurr++; + } + if (refPic == NULL) { + refPic = get_lt_ref_pic(frame_list, slice, rps->m_RealPoc[i], rps->check_lt_msb[i]); + } + refPic->check_lt_msb = rps->check_lt_msb[i]; + } + + // ref_pic_list_init + H265eDpbFrm* rpsCurrList0[MAX_REFS + 1]; + H265eDpbFrm* rpsCurrList1[MAX_REFS + 1]; + RK_S32 numPocTotalCurr = numPocStCurr0 + numPocStCurr1 + numPocLtCurr; + + for (i = 0; i < numPocStCurr0; i++, cIdx++) { + rpsCurrList0[cIdx] = refPicSetStCurr0[i]; + } + + for (i = 0; i < numPocStCurr1; i++, cIdx++) { + rpsCurrList0[cIdx] = refPicSetStCurr1[i]; + } + + for (i = 0; i < numPocLtCurr; i++, cIdx++) { + rpsCurrList0[cIdx] = refPicSetLtCurr[i]; + } + + mpp_assert(cIdx == numPocTotalCurr); + + if (slice->m_sliceType == B_SLICE) { + cIdx = 0; + for (i = 0; i < numPocStCurr1; i++, cIdx++) { + rpsCurrList1[cIdx] = refPicSetStCurr1[i]; + } + + for (i = 0; i < numPocStCurr0; i++, cIdx++) { + rpsCurrList1[cIdx] = refPicSetStCurr0[i]; + } + + for (i = 0; i < numPocLtCurr; i++, cIdx++) { + rpsCurrList1[cIdx] = refPicSetLtCurr[i]; + } + + mpp_assert(cIdx == numPocTotalCurr); + } + + memset(slice->m_bIsUsedAsLongTerm, 0, sizeof(slice->m_bIsUsedAsLongTerm)); + + for ( rIdx = 0; rIdx < slice->m_numRefIdx[0]; rIdx++) { + cIdx = (slice->m_RefPicListModification.m_refPicListModificationFlagL0 != 0) ? slice->m_RefPicListModification.m_RefPicSetIdxL0[rIdx] : (RK_U32)rIdx % numPocTotalCurr; + mpp_assert(cIdx >= 0 && cIdx < numPocTotalCurr); + slice->m_refPicList[0][rIdx] = rpsCurrList0[cIdx]; + slice->m_bIsUsedAsLongTerm[0][rIdx] = (cIdx >= numPocStCurr0 + numPocStCurr1); + } + + if (slice->m_sliceType != B_SLICE) { + slice->m_numRefIdx[1] = 0; + memset(slice->m_refPicList[1], 0, sizeof(slice->m_refPicList[1])); + } else { + for (rIdx = 0; rIdx < slice->m_numRefIdx[1]; rIdx++) { + cIdx = (slice->m_RefPicListModification.m_refPicListModificationFlagL1 != 0) ? slice->m_RefPicListModification.m_RefPicSetIdxL1[rIdx] : (RK_U32)rIdx % numPocTotalCurr; + mpp_assert(cIdx >= 0 && cIdx < numPocTotalCurr); + slice->m_refPicList[1][rIdx] = rpsCurrList1[cIdx]; + slice->m_bIsUsedAsLongTerm[1][rIdx] = (cIdx >= numPocStCurr0 + numPocStCurr1); + } + } + + h265e_dbg_func("leave\n"); +} + +void h265e_slice_set_ref_poc_list(H265eSlice *slice) +{ + RK_S32 dir, numRefIdx; + + h265e_dbg_func("enter\n"); + + for (dir = 0; dir < 2; dir++) { + for (numRefIdx = 0; numRefIdx < slice->m_numRefIdx[dir]; numRefIdx++) { + slice->m_refPOCList[dir][numRefIdx] = slice->m_refPicList[dir][numRefIdx]->poc; + } + } + + h265e_dbg_func("leave\n"); +} + +void h265e_slice_init(void *ctx, EncFrmStatus curr) +{ + H265eCtx *p = (H265eCtx *)ctx; + H265eVps *vps = &p->vps; + H265eSps *sps = &p->sps; + H265ePps *pps = &p->pps; + MppEncCfgSet *cfg = p->cfg; + MppEncH265Cfg *codec = &cfg->h265; + MppEncPrepCfg *prep_cfg = &cfg->prep; + H265eSlice *slice = p->dpb->curr->slice; + MppFrameFormat fmt = prep_cfg->format & MPP_FRAME_FMT_MASK; + + p->slice = p->dpb->curr->slice; + h265e_dbg_func("enter\n"); + memset(slice, 0, sizeof(H265eSlice)); + slice->m_sps = sps; + slice->m_vps = vps; + slice->m_pps = pps; + slice->m_numRefIdx[0] = 0; + slice->m_numRefIdx[1] = 0; + slice->m_colFromL0Flag = 1; + slice->m_colRefIdx = 0; + slice->m_bCheckLDC = 0; + slice->m_sliceQpDeltaCb = 0; + slice->m_sliceQpDeltaCr = 0; + slice->m_maxNumMergeCand = 5; + slice->m_bFinalized = 0; + + slice->m_cabacInitFlag = 0; + slice->m_numEntryPointOffsets = 0; + slice->m_enableTMVPFlag = sps->m_TMVPFlagsPresent; + slice->m_picOutputFlag = 1; + p->dpb->curr->is_key_frame = 0; + if (curr.is_idr) { + slice->m_sliceType = I_SLICE; + p->dpb->curr->is_key_frame = 1; + p->dpb->curr->status.is_intra = 1; + p->dpb->gop_idx = 0; + } else { + slice->m_sliceType = P_SLICE; + p->dpb->curr->status.is_intra = 0; + } + + p->dpb->curr->status.val = curr.val; + + if (slice->m_sliceType != B_SLICE && !curr.non_recn) + slice->is_referenced = 1; + + if (slice->m_pps->m_deblockingFilterOverrideEnabledFlag) { + h265e_dbg_slice("to do in this case"); + } else { + slice->m_deblockingFilterDisable = pps->m_picDisableDeblockingFilterFlag; + slice->m_deblockingFilterBetaOffsetDiv2 = pps->m_deblockingFilterBetaOffsetDiv2; + slice->m_deblockingFilterTcOffsetDiv2 = pps->m_deblockingFilterTcOffsetDiv2; + } + slice->m_saoEnabledFlag = !codec->sao_cfg.slice_sao_luma_disable; + slice->m_saoEnabledFlagChroma = (fmt == MPP_FMT_YUV400) ? 0 : + !codec->sao_cfg.slice_sao_chroma_disable; + slice->m_maxNumMergeCand = codec->merge_cfg.max_mrg_cnd; + slice->m_cabacInitFlag = codec->entropy_cfg.cabac_init_flag; + slice->m_picOutputFlag = 1; + slice->m_ppsId = pps->m_PPSId; + if (slice->m_pps->m_bSliceChromaQpFlag) { + slice->m_sliceQpDeltaCb = codec->trans_cfg.cb_qp_offset; + slice->m_sliceQpDeltaCr = codec->trans_cfg.cr_qp_offset; + } + + slice->poc = p->dpb->curr->seq_idx; + slice->gop_idx = p->dpb->gop_idx; + slice->temporal_id = p->dpb->curr->status.temporal_id; + p->dpb->curr->gop_idx = p->dpb->gop_idx++; + p->dpb->curr->poc = slice->poc; + if (curr.is_lt_ref) + p->dpb->curr->is_long_term = 1; + + h265e_dbg_slice("slice->m_sliceType = %d slice->is_referenced = %d \n", + slice->m_sliceType, slice->is_referenced); + h265e_dbg_func("leave\n"); +} + +void code_st_refpic_set(MppWriteCtx *bitIf, H265eReferencePictureSet* rps, RK_S32 idx) +{ + if (idx > 0) { + mpp_writer_put_bits(bitIf, rps->m_interRPSPrediction, 1); // inter_RPS_prediction_flag + } + if (rps->m_interRPSPrediction) { + RK_S32 deltaRPS = rps->m_deltaRPS; + RK_S32 j; + + mpp_writer_put_ue(bitIf, rps->m_deltaRIdxMinus1); // delta index of the Reference Picture Set used for prediction minus 1 + + mpp_writer_put_bits(bitIf, (deltaRPS >= 0 ? 0 : 1), 1); //delta_rps_sign + mpp_writer_put_ue(bitIf, abs(deltaRPS) - 1); // absolute delta RPS minus 1 + + for (j = 0; j < rps->m_numRefIdc; j++) { + RK_S32 refIdc = rps->m_refIdc[j]; + mpp_writer_put_bits(bitIf, (refIdc == 1 ? 1 : 0), 1); //first bit is "1" if Idc is 1 + if (refIdc != 1) { + mpp_writer_put_bits(bitIf, refIdc >> 1, 1); //second bit is "1" if Idc is 2, "0" otherwise. + } + } + } else { + mpp_writer_put_ue(bitIf, rps->num_negative_pic); + mpp_writer_put_ue(bitIf, rps->num_positive_pic); + RK_S32 prev = 0; + RK_S32 j; + + for (j = 0; j < rps->num_negative_pic; j++) { + mpp_writer_put_ue(bitIf, prev - rps->delta_poc[j] - 1); + prev = rps->delta_poc[j]; + mpp_writer_put_bits(bitIf, rps->m_used[j], 1); + } + + prev = 0; + for (j = rps->num_negative_pic; j < rps->num_negative_pic + rps->num_positive_pic; j++) { + mpp_writer_put_ue(bitIf, rps->delta_poc[j] - prev - 1); + prev = rps->delta_poc[j]; + mpp_writer_put_bits(bitIf, rps->m_used[j], 1); + } + } +} + +RK_U8 find_matching_ltrp(H265eSlice* slice, RK_U32 *ltrpsIndex, RK_S32 ltrpPOC, RK_U32 usedFlag) +{ + RK_U32 lsb = ltrpPOC % (1 << slice->m_sps->m_bitsForPOC); + RK_U32 k; + for (k = 0; k < slice->m_sps->m_numLongTermRefPicSPS; k++) { + if ((lsb == slice->m_sps->m_ltRefPicPocLsbSps[k]) && (usedFlag == slice->m_sps->m_usedByCurrPicLtSPSFlag[k])) { + *ltrpsIndex = k; + return 1; + } + } + + return 0; +} + +RK_S32 get_num_rps_cur_templist(H265eReferencePictureSet* rps) +{ + RK_S32 numRpsCurrTempList = 0; + RK_S32 i; + for ( i = 0; i < rps->num_negative_pic + rps->num_positive_pic + rps->num_long_term_pic; i++) { + if (rps->m_used[i]) { + numRpsCurrTempList++; + } + } + + return numRpsCurrTempList; +} + + +void h265e_code_slice_header(H265eSlice *slice, MppWriteCtx *bitIf, + RK_U32 slice_segment_addr) +{ + RK_U32 i = 0; + RK_U32 slice_address_addr_bits = 0; + H265eSps *sps = slice->m_sps; + RK_U32 pic_width_in_ctb = (sps->m_picWidthInLumaSamples + sps->m_maxCUSize - 1) / + sps->m_maxCUSize; + RK_U32 pic_height_in_ctb = (sps->m_picHeightInLumaSamples + sps->m_maxCUSize - 1) / + sps->m_maxCUSize; + RK_U32 max_ctu_num = pic_width_in_ctb * pic_height_in_ctb; + + mpp_writer_put_bits(bitIf, (slice_segment_addr == 0), 1); //first_slice_segment_in_pic_flag + mpp_writer_put_ue(bitIf, slice->m_ppsId); + + if (slice_segment_addr != 0) { + while (max_ctu_num > (RK_U32)(1 << slice_address_addr_bits)) { + slice_address_addr_bits++; + } + //slice_segment_address + mpp_writer_put_bits(bitIf, slice_segment_addr, slice_address_addr_bits); + } + + H265eReferencePictureSet* rps = slice->m_rps; + slice->m_enableTMVPFlag = 0; + if (!slice->m_dependentSliceSegmentFlag) { + for (i = 0; i < (RK_U32)slice->m_pps->m_numExtraSliceHeaderBits; i++) { + mpp_writer_put_bits(bitIf, (slice->slice_reserved_flag >> i) & 0x1, 1); + } + + mpp_writer_put_ue(bitIf, slice->m_sliceType); + + if (slice->m_pps->m_outputFlagPresentFlag) { + mpp_writer_put_bits(bitIf, (slice->m_picOutputFlag != 0) ? 1 : 0, 1); + } + + if (slice->m_sliceType != I_SLICE) { // skip frame can't iDR + RK_S32 picOrderCntLSB = (slice->poc - slice->last_idr + (1 << slice->m_sps->m_bitsForPOC)) % (1 << slice->m_sps->m_bitsForPOC); + mpp_writer_put_bits(bitIf, picOrderCntLSB, slice->m_sps->m_bitsForPOC); + if (slice->m_bdIdx < 0) { + mpp_writer_put_bits(bitIf, 0, 1); + code_st_refpic_set(bitIf, rps, slice->m_sps->m_RPSList.m_numberOfReferencePictureSets); + } else { + mpp_writer_put_bits(bitIf, 1, 1); + RK_S32 numBits = 0; + while ((1 << numBits) < slice->m_sps->m_RPSList.m_numberOfReferencePictureSets) { + numBits++; + } + + if (numBits > 0) { + mpp_writer_put_bits(bitIf, slice->m_bdIdx, numBits); + } + } + if (slice->m_sps->m_bLongTermRefsPresent) { + + RK_S32 numLtrpInSH = rps->m_numberOfPictures; + RK_S32 ltrpInSPS[MAX_REFS]; + RK_S32 numLtrpInSPS = 0; + RK_U32 ltrpIndex; + RK_S32 counter = 0; + RK_S32 k; + for (k = rps->m_numberOfPictures - 1; k > rps->m_numberOfPictures - rps->num_long_term_pic - 1; k--) { + if (find_matching_ltrp(slice, <rpIndex, rps->poc[k], rps->m_used[k])) { + ltrpInSPS[numLtrpInSPS] = ltrpIndex; + numLtrpInSPS++; + } else { + counter++; + } + } + + numLtrpInSH -= rps->m_numberOfPictures - rps->num_long_term_pic; + + RK_S32 bitsForLtrpInSPS = 0; + while (slice->m_sps->m_numLongTermRefPicSPS > (RK_U32)(1 << bitsForLtrpInSPS)) { + bitsForLtrpInSPS++; + } + + if (slice->m_sps->m_numLongTermRefPicSPS > 0) { + mpp_writer_put_ue(bitIf, numLtrpInSPS); + } + mpp_writer_put_ue(bitIf, numLtrpInSH); + // Note that the LSBs of the LT ref. pic. POCs must be sorted before. + // Not sorted here because LT ref indices will be used in setRefPicList() + RK_S32 prevDeltaMSB = 0; + RK_S32 offset = rps->num_negative_pic + rps->num_positive_pic; + for ( k = rps->m_numberOfPictures - 1; k > offset - 1; k--) { + if (counter < numLtrpInSPS) { + if (bitsForLtrpInSPS > 0) { + mpp_writer_put_bits(bitIf, ltrpInSPS[counter], bitsForLtrpInSPS); + } + } else { + mpp_writer_put_bits(bitIf, rps->m_pocLSBLT[k], slice->m_sps->m_bitsForPOC); + mpp_writer_put_bits(bitIf, rps->m_used[k], 1); + } + mpp_writer_put_bits(bitIf, rps->m_deltaPocMSBPresentFlag[k], 1); + + if (rps->m_deltaPocMSBPresentFlag[k]) { + RK_U32 deltaFlag = 0; + if ((k == rps->m_numberOfPictures - 1) || (k == rps->m_numberOfPictures - 1 - numLtrpInSPS)) { + deltaFlag = 1; + } + if (deltaFlag) { + mpp_writer_put_ue(bitIf, rps->m_deltaPOCMSBCycleLT[k]); + } else { + RK_S32 differenceInDeltaMSB = rps->m_deltaPOCMSBCycleLT[k] - prevDeltaMSB; + mpp_writer_put_ue(bitIf, differenceInDeltaMSB); + } + prevDeltaMSB = rps->m_deltaPOCMSBCycleLT[k]; + } + } + } + if (slice->m_sps->m_TMVPFlagsPresent) { + mpp_writer_put_bits(bitIf, (slice->m_enableTMVPFlag != 0) ? 1 : 0, 1); + } + } + + if (slice->m_sps->m_bUseSAO) { //skip frame close sao + mpp_writer_put_bits(bitIf, 0, 1); + mpp_writer_put_bits(bitIf, 0, 1); + + } + //check if numrefidxes match the defaults. If not, override + + if (slice->m_sliceType != I_SLICE) { + RK_U32 overrideFlag = (slice->m_numRefIdx[0] != (RK_S32)slice->m_pps->m_numRefIdxL0DefaultActive); + mpp_writer_put_bits(bitIf, (overrideFlag != 0) ? 1 : 0, 1); + if (overrideFlag) { + mpp_writer_put_ue(bitIf, slice->m_numRefIdx[0] - 1); + slice->m_numRefIdx[1] = 0; + } + } + + if (slice->m_pps->m_listsModificationPresentFlag && get_num_rps_cur_templist(rps) > 1) { + H265eRefPicListModification* refPicListModification = &slice->m_RefPicListModification; + mpp_writer_put_bits(bitIf, (refPicListModification->m_refPicListModificationFlagL0 != 0) ? 1 : 0, 1); + if (refPicListModification->m_refPicListModificationFlagL0) { + RK_S32 numRpsCurrTempList0 = get_num_rps_cur_templist(rps); + if (numRpsCurrTempList0 > 1) { + RK_S32 length = 1; + numRpsCurrTempList0--; + while (numRpsCurrTempList0 >>= 1) { + length++; + } + for (i = 0; i < (RK_U32)slice->m_numRefIdx[0]; i++) { + mpp_writer_put_bits(bitIf, refPicListModification->m_RefPicSetIdxL0[i], length); + } + } + } + } + + if (slice->m_pps->m_cabacInitPresentFlag) { + mpp_writer_put_bits(bitIf, slice->m_cabacInitFlag, 1); + } + + if (slice->m_enableTMVPFlag) { + + if (slice->m_sliceType != I_SLICE && + ((slice->m_colFromL0Flag == 1 && slice->m_numRefIdx[0] > 1) || + (slice->m_colFromL0Flag == 0 && slice->m_numRefIdx[1] > 1))) { + mpp_writer_put_ue(bitIf, slice->m_colRefIdx); + } + } + + if (slice->m_sliceType != I_SLICE) { + RK_S32 flag = MRG_MAX_NUM_CANDS - slice->m_maxNumMergeCand; + flag = flag == 5 ? 4 : flag; + mpp_writer_put_ue(bitIf, flag); + } + RK_S32 code = slice->m_sliceQp - (slice->m_pps->m_picInitQPMinus26 + 26); + mpp_writer_put_se(bitIf, code); + if (slice->m_pps->m_bSliceChromaQpFlag) { + code = slice->m_sliceQpDeltaCb; + mpp_writer_put_se(bitIf, code); + code = slice->m_sliceQpDeltaCr; + mpp_writer_put_se(bitIf, code); + } + if (slice->m_pps->m_deblockingFilterControlPresentFlag) { + if (slice->m_pps->m_deblockingFilterOverrideEnabledFlag) { + mpp_writer_put_bits(bitIf, slice->m_deblockingFilterOverrideFlag, 1); + } + if (slice->m_deblockingFilterOverrideFlag) { + mpp_writer_put_bits(bitIf, slice->m_deblockingFilterDisable, 1); + if (!slice->m_deblockingFilterDisable) { + mpp_writer_put_se(bitIf, slice->m_deblockingFilterBetaOffsetDiv2); + mpp_writer_put_se(bitIf, slice->m_deblockingFilterTcOffsetDiv2); + } + } + } + } + if (slice->m_pps->m_tiles_enabled_flag) { + mpp_writer_put_ue(bitIf, 0); // num_entry_point_offsets + } + if (slice->m_pps->m_sliceHeaderExtensionPresentFlag) { + mpp_writer_put_ue(bitIf, slice->slice_header_extension_length); + for (i = 0; i < slice->slice_header_extension_length; i++) { + mpp_writer_put_bits(bitIf, 0, 8); + } + } + h265e_dbg_func("leave\n"); +} + +void code_skip_flag(H265eSlice *slice, RK_U32 abs_part_idx, DataCu *cu) +{ + // get context function is here + H265eCabacCtx *cabac_ctx = &slice->m_cabac; + H265eSps *sps = slice->m_sps; + RK_U32 ctxSkip; + RK_U32 tpelx = cu->pixelX + sps->raster2pelx[sps->zscan2raster[abs_part_idx]]; + RK_U32 tpely = cu->pixelY + sps->raster2pely[sps->zscan2raster[abs_part_idx]]; + //RK_U32 ctxSkip = cu->getCtxSkipFlag(abs_part_idx); + + h265e_dbg_skip("tpelx = %d", tpelx); + if (cu->cur_addr == 0 ) { + ctxSkip = 0; + } else if ((tpely == 0) || (tpelx == cu->tile_start_x)) { + ctxSkip = 1; + } else { + ctxSkip = 2; + } + h265e_dbg_skip("ctxSkip = %d", ctxSkip); + h265e_cabac_encodeBin(cabac_ctx, &slice->m_contextModels[OFF_SKIP_FLAG_CTX + ctxSkip], 1); +} + +static void code_merge_index(H265eSlice *slice) +{ + H265eCabacCtx *cabac_ctx = &slice->m_cabac; + + h265e_cabac_encodeBin(cabac_ctx, &slice->m_contextModels[OFF_MERGE_IDX_EXT_CTX], 0); +} + +static void code_split_flag(H265eSlice *slice, RK_U32 abs_part_idx, RK_U32 depth, DataCu *cu) +{ + H265eSps *sps = slice->m_sps; + + if (depth == slice->m_sps->m_maxCUDepth - slice->m_sps->m_addCUDepth) + return; + + h265e_dbg_skip("depth %d cu->m_cuDepth %d", depth, cu->m_cuDepth[sps->zscan2raster[abs_part_idx]]); + + H265eCabacCtx *cabac_ctx = &slice->m_cabac; + RK_U32 currSplitFlag = (cu->m_cuDepth[sps->zscan2raster[abs_part_idx]] > depth) ? 1 : 0; + + h265e_cabac_encodeBin(cabac_ctx, &slice->m_contextModels[OFF_SPLIT_FLAG_CTX], currSplitFlag); +} + +static void encode_cu(H265eSlice *slice, RK_U32 abs_part_idx, RK_U32 depth, DataCu *cu) +{ + H265eSps *sps = slice->m_sps; + RK_U32 bBoundary = 0; + RK_U32 lpelx = cu->pixelX + sps->raster2pelx[sps->zscan2raster[abs_part_idx]]; + RK_U32 rpelx = lpelx + (sps->m_maxCUSize >> depth) - 1; + RK_U32 tpely = cu->pixelY + sps->raster2pely[sps->zscan2raster[abs_part_idx]]; + RK_U32 bpely = tpely + (sps->m_maxCUSize >> depth) - 1; + + h265e_dbg_skip("EncodeCU depth %d, abs_part_idx %d", depth, abs_part_idx); + + if ((rpelx <= cu->tile_end_x) && (bpely <= cu->tile_end_y)) { + h265e_dbg_skip("code_split_flag in depth %d", depth); + code_split_flag(slice, abs_part_idx, depth, cu); + } else { + h265e_dbg_skip("boundary flag found"); + bBoundary = 1; + } + + h265e_dbg_skip("m_cuDepth[%d] = %d maxCUDepth %d, m_addCUDepth %d", abs_part_idx, cu->m_cuDepth[sps->zscan2raster[abs_part_idx]], sps->m_maxCUDepth, sps->m_addCUDepth); + + if ((depth < cu->m_cuDepth[sps->zscan2raster[abs_part_idx]] && (depth < (sps->m_maxCUDepth - sps->m_addCUDepth))) || bBoundary) { + RK_U32 numPartions = 1 << (sps->m_maxCUDepth << 1); + RK_U32 qNumParts = (numPartions >> (depth << 1)) >> 2; + RK_U32 partUnitIdx = 0; + + for (partUnitIdx = 0; partUnitIdx < 4; partUnitIdx++, abs_part_idx += qNumParts) { + h265e_dbg_skip("depth %d partUnitIdx = %d, qNumParts %d, abs_part_idx %d", depth, partUnitIdx, qNumParts, abs_part_idx); + lpelx = cu->pixelX + sps->raster2pelx[sps->zscan2raster[abs_part_idx]]; + tpely = cu->pixelY + sps->raster2pely[sps->zscan2raster[abs_part_idx]]; + if ((lpelx <= cu->tile_end_x) && (tpely <= cu->tile_end_y)) { + encode_cu(slice, abs_part_idx, depth + 1, cu); + } + } + return; + } + + h265e_dbg_skip("code_skip_flag in depth %d", depth); + code_skip_flag(slice, abs_part_idx, cu); + h265e_dbg_skip("code_merge_index in depth %d", depth); + code_merge_index(slice); + return; +} + +static void proc_cu8(DataCu *cu, RK_S32 nSubPart, RK_S32 cuDepth, RK_S32 puIdx) +{ + h265e_dbg_skip("8 ctu puIdx %d no need split", puIdx); + + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); +} + +static void proc_cu16(DataCu *cu, RK_U32 pos_x, RK_U32 pos_y, + RK_S32 nSubPart, RK_S32 cuDepth, RK_S32 puIdx) +{ + RK_U32 m; + RK_S32 newPuIdx; + + h265e_dbg_skip("cu 16 pos_x %d pos_y %d", pos_x, pos_y); + + if ((cu->pixelX + pos_x + 15 <= cu->tile_end_x) && + (cu->pixelY + pos_y + 15 <= cu->tile_end_y)) { + h265e_dbg_skip("16 ctu puIdx %d no need split", puIdx); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); + return; + } else if ((cu->pixelX + pos_x > cu->tile_end_x) || + (cu->pixelY + pos_y > cu->tile_end_y)) { + h265e_dbg_skip("16 ctu puIdx %d out of pic", puIdx); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); + return; + } + + for (m = 0; m < 4; m ++) { + newPuIdx = puIdx * 4 + m; + proc_cu8(cu, nSubPart / 4, cuDepth + 1, newPuIdx); + } +} + +static void proc_cu32(DataCu *cu, RK_U32 pos_x, RK_U32 pos_y, + RK_S32 nSubPart, RK_S32 cuDepth, RK_S32 puIdx) +{ + RK_U32 m; + RK_S32 nSize = 32; + RK_U32 cu_x_1, cu_y_1; + RK_S32 newPuIdx; + + h265e_dbg_skip("cu 32 pos_x %d pos_y %d", pos_x, pos_y); + + if ((cu->pixelX + pos_x + 31 <= cu->tile_end_x) && + (cu->pixelY + pos_y + 31 <= cu->tile_end_y)) { + h265e_dbg_skip("32 ctu puIdx %d no need split", puIdx); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); + return; + } else if ((cu->pixelX + pos_x > cu->tile_end_x) || + (cu->pixelY + pos_y > cu->tile_end_y)) { + h265e_dbg_skip("32 ctu puIdx %d out of pic", puIdx); + memset(cu->m_cuDepth + puIdx * nSubPart, cuDepth, nSubPart); + return; + } + + for (m = 0; m < 4; m ++) { + cu_x_1 = pos_x + (m & 1) * (nSize >> 1); + cu_y_1 = pos_y + (m >> 1) * (nSize >> 1); + newPuIdx = puIdx * 4 + m; + proc_cu16(cu, cu_x_1, cu_y_1, nSubPart / 4, cuDepth + 1, newPuIdx); + } +} + +static void proc_ctu64(H265eSlice *slice, DataCu *cu) +{ + H265eSps *sps = slice->m_sps; + RK_U32 k, m; + RK_U32 cu_x_1, cu_y_1; + RK_U32 m_nCtuSize = sps->m_maxCUSize; + RK_U32 lpelx = cu->pixelX; + RK_U32 rpelx = lpelx + m_nCtuSize - 1; + RK_U32 tpely = cu->pixelY; + RK_U32 bpely = tpely + m_nCtuSize - 1; + RK_U32 numPartions = 1 << (sps->m_maxCUDepth << 1); + RK_S32 cuDepth = 0; + + for (k = 0; k < numPartions; k++) { + cu->m_cuDepth[k] = 0; + cu->m_cuSize[k] = m_nCtuSize; + } + if ((rpelx <= cu->tile_end_x) && (bpely <= cu->tile_end_y)) + return; + + for (m = 0; m < 4; m ++) { + cu_x_1 = (m & 1) * (m_nCtuSize >> 1); + cu_y_1 = (m >> 1) * (m_nCtuSize >> 1); + proc_cu32(cu, cu_x_1, cu_y_1, numPartions / 4, cuDepth + 1, m); + } + + for (k = 0; k < numPartions; k++) { + switch (cu->m_cuDepth[k]) { + case 0: cu->m_cuSize[k] = 64; break; + case 1: cu->m_cuSize[k] = 32; break; + case 2: cu->m_cuSize[k] = 16; break; + case 3: cu->m_cuSize[k] = 8; break; + } + } +} + +static void h265e_write_nal(MppWriteCtx *bitIf, RK_S32 temporal_id) +{ + h265e_dbg_func("enter\n"); + + mpp_writer_put_raw_bits(bitIf, 0x0, 24); + mpp_writer_put_raw_bits(bitIf, 0x01, 8); + mpp_writer_put_bits(bitIf, 0, 1); //forbidden_zero_bit + mpp_writer_put_bits(bitIf, 1, 6); //nal_unit_type + mpp_writer_put_bits(bitIf, 0, 6); //nuh_reserved_zero_6bits + mpp_writer_put_bits(bitIf, temporal_id + 1, 3); //nuh_temporal_id_plus1 + + h265e_dbg_func("leave\n"); +} + +static void h265e_write_algin(MppWriteCtx *bitIf) +{ + h265e_dbg_func("enter\n"); + mpp_writer_put_bits(bitIf, 1, 1); + mpp_writer_align_zero(bitIf); + h265e_dbg_func("leave\n"); +} + +static void proc_ctu32(H265eSlice *slice, DataCu *cu) +{ + H265eSps *sps = slice->m_sps; + RK_U32 k, m; + RK_U32 cu_x_1, cu_y_1; + RK_U32 m_nCtuSize = sps->m_maxCUSize; + RK_U32 lpelx = cu->pixelX; + RK_U32 rpelx = lpelx + m_nCtuSize - 1; + RK_U32 tpely = cu->pixelY; + RK_U32 bpely = tpely + m_nCtuSize - 1; + RK_U32 numPartions = 1 << (sps->m_maxCUDepth << 1); + RK_S32 cuDepth = 0; + + for (k = 0; k < numPartions; k++) { + cu->m_cuDepth[k] = 0; + cu->m_cuSize[k] = m_nCtuSize; + } + if ((rpelx <= cu->tile_end_x) && (bpely <= cu->tile_end_y)) + return; + + for (m = 0; m < 4; m ++) { + cu_x_1 = (m & 1) * (m_nCtuSize >> 1); + cu_y_1 = (m >> 1) * (m_nCtuSize >> 1); + proc_cu16(cu, cu_x_1, cu_y_1, numPartions / 4, cuDepth + 1, m); + } + + for (k = 0; k < numPartions; k++) { + switch (cu->m_cuDepth[k]) { + case 0: cu->m_cuSize[k] = 32; break; + case 1: cu->m_cuSize[k] = 16; break; + case 2: cu->m_cuSize[k] = 8; break; + } + } +} + +static void h265e_code_skip_tile(void *ctx, H265eSlice *slice, MppWriteCtx *bitIf, TileInfo *tile) +{ + DataCu cu; + void (*proc_ctu)(H265eSlice *, DataCu *); + H265eCtx *p = (H265eCtx *)ctx; + H265eSps *sps = &p->sps; + H265eCabacCtx *cabac_ctx = &slice->m_cabac; + RK_U32 cu_cnt; + RK_U32 offset_x = tile->tile_start_x; + RK_U32 offset_y = tile->tile_start_y; + + if (sps->m_maxCUSize == 32) + /* rk3528 maxCUSize[32] depth[3], other chips maxCUSize[64] depth[4], + So special handling is required */ + proc_ctu = proc_ctu32; + else + proc_ctu = proc_ctu64; + + h265e_write_nal(bitIf, slice->temporal_id); + h265e_code_slice_header(slice, bitIf, tile->ctu_addr); + h265e_write_algin(bitIf); + h265e_reset_enctropy((void*)slice); + h265e_cabac_init(cabac_ctx, bitIf); + + slice->is_referenced = 0; + cu.tile_start_x = tile->tile_start_x; + cu.tile_end_x = tile->tile_end_x; + cu.tile_end_y = tile->tile_end_y; + for (cu_cnt = 0; cu_cnt < tile->mb_total - 1; cu_cnt++) { + cu.pixelX = offset_x; + cu.pixelY = offset_y; + cu.cur_addr = cu_cnt; + proc_ctu(slice, &cu); + encode_cu(slice, 0, 0, &cu); + h265e_cabac_encodeBinTrm(cabac_ctx, 0); + offset_x += sps->m_maxCUSize; + if (offset_x > tile->tile_end_x) { + offset_x = tile->tile_start_x; + offset_y += sps->m_maxCUSize; + } + } + /* The last CTU handled independently, reducing the cost */ + cu.pixelX = offset_x; + cu.pixelY = offset_y; + cu.cur_addr = cu_cnt; + proc_ctu(slice, &cu); + encode_cu(slice, 0, 0, &cu); + h265e_cabac_encodeBinTrm(cabac_ctx, 1); + h265e_cabac_finish(cabac_ctx); + h265e_write_algin(bitIf); +} + +RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_S32 len) +{ + H265eCtx *p = (H265eCtx *)ctx; + H265eSps *sps = &p->sps; + H265ePps *pps = &p->pps; + TileInfo tile; + MppWriteCtx bitIf; + RK_U32 mb_wd; + RK_U32 mb_h; + RK_S32 i; + + h265e_dbg_func("enter\n"); + if (!buf || !len) { + mpp_err("buf or size no set"); + return MPP_NOK; + } + + mpp_writer_init(&bitIf, buf, len); + tile.ctu_addr = 0; + tile.tile_start_y = 0; + tile.tile_end_y = sps->m_picHeightInLumaSamples - 1; + + if (pps->m_nNumTileColumnsMinus1) { + tile.tile_start_x = 0; + for (i = 0; i <= pps->m_nNumTileColumnsMinus1; i++) { + tile.mb_total = pps->m_nTileColumnWidthArray[i] * pps->m_nTileRowHeightArray[i]; + if (i != pps->m_nNumTileColumnsMinus1) + tile.tile_end_x = tile.tile_start_x + + (pps->m_nTileColumnWidthArray[i] * sps->m_maxCUSize) - 1; + else + tile.tile_end_x = sps->m_picWidthInLumaSamples - 1; + h265e_code_skip_tile(ctx, slice, &bitIf, &tile); + tile.tile_start_x += (pps->m_nTileColumnWidthArray[i] * sps->m_maxCUSize); + tile.ctu_addr += pps->m_nTileColumnWidthArray[i]; + } + } else { + mb_wd = (sps->m_picWidthInLumaSamples + sps->m_maxCUSize - 1) / sps->m_maxCUSize; + mb_h = (sps->m_picHeightInLumaSamples + sps->m_maxCUSize - 1) / sps->m_maxCUSize; + tile.mb_total = mb_wd * mb_h; + tile.tile_start_x = 0; + tile.tile_end_x = sps->m_picWidthInLumaSamples - 1; + h265e_code_skip_tile(ctx, slice, &bitIf, &tile); + } + + h265e_dbg_func("leave\n"); + return mpp_writer_bytes(&bitIf); +} diff --git a/mpp/codec/enc/h265/h265e_slice.h b/mpp/codec/enc/h265/h265e_slice.h new file mode 100644 index 000000000..70a48f159 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_slice.h @@ -0,0 +1,475 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_SLICE_H +#define H265E_SLICE_H + +#include "rk_type.h" +#include "mpp_err.h" + +#include "h265e_syntax.h" +#include "h265e_syntax_new.h" +#include "h265_syntax.h" +#include "h265e_enctropy.h" +#include "h265e_context_table.h" +#include "h265e_dpb.h" + +#define MIN_PU_SIZE 4 +#define MIN_TU_SIZE 4 +#define MAX_NUM_SPU_W (64 / MIN_PU_SIZE) // maximum number of SPU in horizontal line + +/* + * For H.265 encoder slice header process. + * Remove some syntax that encoder not supported. + * Field, mbaff, B slice are not supported yet. + */ +typedef struct H265eDpbFrm_t H265eDpbFrm; + +typedef struct DataCu_t { + RK_U8 m_cuSize[256]; + RK_U8 m_cuDepth[256]; + RK_U32 pixelX; + RK_U32 pixelY; + RK_U32 cur_addr; + RK_U32 tile_start_x; + RK_U32 tile_end_x; + RK_U32 tile_end_y; +} DataCu; + +typedef struct TileInfo_t { + RK_U32 tile_start_x; + RK_U32 tile_end_x; + RK_U32 tile_start_y; + RK_U32 tile_end_y; + RK_U32 mb_total; + RK_U32 ctu_addr; +} TileInfo; + +typedef struct H265eReferencePictureSet_e { + RK_S32 m_deltaRIdxMinus1; + RK_S32 m_deltaRPS; + RK_S32 m_numRefIdc; + RK_S32 m_refIdc[MAX_REFS + 1]; + + // Parameters for long term references + RK_U32 check_lt_msb[MAX_REFS]; + RK_S32 m_pocLSBLT[MAX_REFS]; + RK_S32 m_deltaPOCMSBCycleLT[MAX_REFS]; + RK_U32 m_deltaPocMSBPresentFlag[MAX_REFS]; + + RK_S32 m_numberOfPictures; + RK_S32 num_negative_pic; + RK_S32 num_positive_pic; + RK_S32 delta_poc[MAX_REFS]; + RK_U32 m_used[MAX_REFS]; + RK_U32 m_ref[MAX_REFS]; + RK_S32 poc[MAX_REFS]; + RK_S32 m_RealPoc[MAX_REFS]; + + RK_U32 m_interRPSPrediction; + RK_S32 num_long_term_pic; // Zero when disabled +} H265eReferencePictureSet; + +typedef struct H265eRPSList_e { + RK_S32 m_numberOfReferencePictureSets; + H265eReferencePictureSet *m_referencePictureSets; +} H265eRPSList; + +typedef struct H265eRefPicListModification_e { + RK_U32 m_refPicListModificationFlagL0; + RK_U32 m_refPicListModificationFlagL1; + RK_U32 m_RefPicSetIdxL0[REF_PIC_LIST_NUM_IDX]; + RK_U32 m_RefPicSetIdxL1[REF_PIC_LIST_NUM_IDX]; +} H265eRefPicListModification; + +typedef struct ProfileTierLevel_e { + RK_S32 m_profileSpace; + RK_S32 m_tierFlag; + RK_S32 m_profileIdc; + RK_S32 m_profileCompatibilityFlag[32]; + RK_S32 m_levelIdc; + RK_S32 m_progressiveSourceFlag; + RK_S32 m_interlacedSourceFlag; + RK_S32 m_nonPackedConstraintFlag; + RK_S32 m_frameOnlyConstraintFlag; + RK_S32 m_max12bitConstraintFlag; + RK_S32 m_max10bitConstraintFlag; + RK_S32 m_max8bitConstraintFlag; + RK_S32 m_max422chromaConstraintFlag; + RK_S32 m_max420chromaConstraintFlag; + RK_S32 m_maxMonochromaConstraintFlag; + RK_S32 m_intraConstraintFlag; + RK_S32 m_onePictureConstraintFlag; + RK_S32 m_lowerBitRateConstraintFlag; +} ProfileTierLevel; + +typedef struct H265ePTL_e { + ProfileTierLevel m_generalPTL; + ProfileTierLevel m_subLayerPTL[6]; // max. value of max_sub_layers_minus1 is 6 + RK_S32 m_subLayerProfilePresentFlag[6]; + RK_S32 m_subLayerLevelPresentFlag[6]; +} H265ePTL; + +typedef struct TimeingInfo_e { + RK_U32 m_timingInfoPresentFlag; + RK_U32 m_numUnitsInTick; + RK_U32 m_timeScale; + RK_U32 m_pocProportionalToTimingFlag; + RK_U32 m_numTicksPocDiffOneMinus1; +} TimingInfo; + +typedef struct H265HrdSubLayerInfo_e { + RK_U32 fixedPicRateFlag; + RK_U32 fixedPicRateWithinCvsFlag; + RK_U32 picDurationInTcMinus1; + RK_U32 lowDelayHrdFlag; + RK_U32 cpbCntMinus1; + RK_U32 bitRateValueMinus1[MAX_CPB_CNT][2]; + RK_U32 cpbSizeValue[MAX_CPB_CNT][2]; + RK_U32 ducpbSizeValue[MAX_CPB_CNT][2]; + RK_U32 cbrFlag[MAX_CPB_CNT][2]; + RK_U32 duBitRateValue[MAX_CPB_CNT][2]; +} H265eHrdSubLayerInfo; + +typedef struct H265eHrdParameters_e { + RK_U32 m_nalHrdParametersPresentFlag; + RK_U32 m_vclHrdParametersPresentFlag; + RK_U32 m_subPicHrdParamsPresentFlag; + RK_U32 m_tickDivisorMinus2; + RK_U32 m_duCpbRemovalDelayLengthMinus1; + RK_U32 m_subPicCpbParamsInPicTimingSEIFlag; + RK_U32 m_dpbOutputDelayDuLengthMinus1; + RK_U32 m_bitRateScale; + RK_U32 m_cpbSizeScale; + RK_U32 m_ducpbSizeScale; + RK_U32 m_initialCpbRemovalDelayLengthMinus1; + RK_U32 m_cpbRemovalDelayLengthMinus1; + RK_U32 m_dpbOutputDelayLengthMinus1; + H265eHrdSubLayerInfo m_HRD[MAX_SUB_LAYERS]; +} H265eHrdParameters; + +typedef struct H265eVps_e { + RK_S32 m_VPSId; + RK_U32 m_maxTLayers; + RK_U32 m_maxLayers; + RK_U32 m_bTemporalIdNestingFlag; + + RK_U32 m_numReorderPics[MAX_SUB_LAYERS]; + RK_U32 m_maxDecPicBuffering[MAX_SUB_LAYERS]; + RK_U32 m_maxLatencyIncrease[MAX_SUB_LAYERS]; // Really max latency increase plus 1 (value 0 expresses no limit) + + RK_U32 m_numHrdParameters; + RK_U32 m_maxNuhReservedZeroLayerId; + H265eHrdParameters *m_hrdParameters; + RK_U32 *m_hrdOpSetIdx; + RK_U32 *m_cprmsPresentFlag; + RK_U32 m_numOpSets; + RK_U32 m_layerIdIncludedFlag[MAX_VPS_OP_SETS_PLUS1][MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1]; + + H265ePTL m_ptl; + TimingInfo m_timingInfo; +} H265eVps; + +typedef struct H265eCropInfo_e { + RK_U32 m_enabledFlag; + RK_S32 m_winLeftOffset; + RK_S32 m_winRightOffset; + RK_S32 m_winTopOffset; + RK_S32 m_winBottomOffset; +} H265eCropInfo; + +typedef struct H265eVuiInfo_e { + RK_U32 m_aspectRatioInfoPresentFlag; + RK_S32 m_aspectRatioIdc; + RK_S32 m_sarWidth; + RK_S32 m_sarHeight; + RK_U32 m_overscanInfoPresentFlag; + RK_U32 m_overscanAppropriateFlag; + RK_U32 m_videoSignalTypePresentFlag; + RK_S32 m_videoFormat; + RK_U32 m_videoFullRangeFlag; + RK_U32 m_colourDescriptionPresentFlag; + RK_S32 m_colourPrimaries; + RK_S32 m_transferCharacteristics; + RK_S32 m_matrixCoefficients; + RK_U32 m_chromaLocInfoPresentFlag; + RK_S32 m_chromaSampleLocTypeTopField; + RK_S32 m_chromaSampleLocTypeBottomField; + RK_U32 m_neutralChromaIndicationFlag; + RK_U32 m_fieldSeqFlag; + + H265eCropInfo m_defaultDisplayWindow; + RK_U32 m_frameFieldInfoPresentFlag; + RK_U32 m_hrdParametersPresentFlag; + RK_U32 m_bitstreamRestrictionFlag; + RK_U32 m_tilesFixedStructureFlag; + RK_U32 m_motionVectorsOverPicBoundariesFlag; + RK_U32 m_restrictedRefPicListsFlag; + RK_S32 m_minSpatialSegmentationIdc; + RK_S32 m_maxBytesPerPicDenom; + RK_S32 m_maxBitsPerMinCuDenom; + RK_S32 m_log2MaxMvLengthHorizontal; + RK_S32 m_log2MaxMvLengthVertical; + H265eHrdParameters m_hrdParameters; + TimingInfo m_timingInfo; +} H265eVuiInfo; + +typedef struct H265eSps_e { + + RK_S32 m_SPSId; + RK_S32 m_VPSId; + RK_S32 m_chromaFormatIdc; + RK_U32 m_colorPlaneFlag; + RK_U32 m_maxTLayers; // maximum number of temporal layers + + // Structure + RK_U32 m_picWidthInLumaSamples; + RK_U32 m_picHeightInLumaSamples; + + RK_S32 m_log2MinCodingBlockSize; + RK_S32 m_log2DiffMaxMinCodingBlockSize; + RK_U32 m_maxCUSize; + RK_U32 m_maxCUDepth; + RK_U32 m_addCUDepth; + + H265eCropInfo m_conformanceWindow; + + H265eRPSList m_RPSList; + RK_U32 m_bLongTermRefsPresent; + RK_U32 m_TMVPFlagsPresent; + RK_S32 m_numReorderPics[MAX_SUB_LAYERS]; + + // Tool list + RK_U32 m_quadtreeTULog2MaxSize; + RK_U32 m_quadtreeTULog2MinSize; + RK_U32 m_quadtreeTUMaxDepthInter; + RK_U32 m_quadtreeTUMaxDepthIntra; + RK_U32 m_usePCM; + RK_U32 m_pcmLog2MaxSize; + RK_U32 m_pcmLog2MinSize; + RK_U32 m_useAMP; + + // Parameter + RK_S32 m_bitDepthY; + RK_S32 m_bitDepthC; + RK_S32 m_qpBDOffsetY; + RK_S32 m_qpBDOffsetC; + + RK_U32 m_useLossless; + + RK_U32 m_pcmBitDepthLuma; + RK_U32 m_pcmBitDepthChroma; + RK_U32 m_bPCMFilterDisableFlag; + + RK_U32 m_bitsForPOC; + RK_U32 m_numLongTermRefPicSPS; + RK_U32 m_ltRefPicPocLsbSps[33]; + RK_U32 m_usedByCurrPicLtSPSFlag[33]; + + // Max physical transform size + RK_U32 m_maxTrSize; + + RK_S32 m_iAMPAcc[MAX_CU_DEPTH]; + RK_U32 m_bUseSAO; + + RK_U32 m_bTemporalIdNestingFlag; // temporal_id_nesting_flag + + RK_U32 m_scalingListEnabledFlag; //TODO: replaced with scaling_list_mode + RK_U32 m_scalingListPresentFlag; + RK_U32 m_maxDecPicBuffering[MAX_SUB_LAYERS]; + + RK_U32 m_maxLatencyIncrease[MAX_SUB_LAYERS]; // Really max latency increase plus 1 (value 0 expresses no limit) + + RK_U32 m_useDF; + RK_U32 m_useStrongIntraSmoothing; + + RK_S32 m_vuiParametersPresentFlag; + H265eVuiInfo vui; + H265ePTL *m_ptl; + RK_U32 zscan2raster[MAX_NUM_SPU_W * MAX_NUM_SPU_W]; + RK_U32 raster2zscan[MAX_NUM_SPU_W * MAX_NUM_SPU_W]; + RK_U32 raster2pelx[MAX_NUM_SPU_W * MAX_NUM_SPU_W]; + RK_U32 raster2pely[MAX_NUM_SPU_W * MAX_NUM_SPU_W]; +} H265eSps; + +typedef struct H265ePps_e { + RK_U32 m_PPSId; // pic_parameter_set_id + RK_U32 m_SPSId; // seq_parameter_set_id + RK_S32 m_picInitQPMinus26; + RK_U32 m_useDQP; + RK_U32 m_bConstrainedIntraPred; // constrained_intra_pred_flag + RK_U32 m_bSliceChromaQpFlag; // slicelevel_chroma_qp_flag + + // access channel + H265eSps *m_sps; + RK_U32 m_maxCuDQPDepth; + RK_U32 m_minCuDQPSize; + + RK_S32 m_chromaCbQpOffset; + RK_S32 m_chromaCrQpOffset; + + RK_U32 m_numRefIdxL0DefaultActive; + RK_U32 m_numRefIdxL1DefaultActive; + + RK_U32 m_bUseWeightPred; // Use of Weighting Prediction (P_SLICE) + RK_U32 m_useWeightedBiPred; // Use of Weighting Bi-Prediction (B_SLICE) + RK_U32 m_outputFlagPresentFlag; // Indicates the presence of output_flag in slice header + + RK_U32 m_transquantBypassEnableFlag; // Indicates presence of cu_transquant_bypass_flag in CUs. + RK_U32 m_useTransformSkip; + RK_U32 m_entropyCodingSyncEnabledFlag; //!< Indicates the presence of wavefronts + + + RK_S32 m_signHideFlag; + RK_S32 m_tiles_enabled_flag; + RK_U32 m_bTileUniformSpacing; + RK_S32 m_nNumTileColumnsMinus1; + RK_S32 m_nTileColumnWidthArray[33]; + RK_S32 m_nNumTileRowsMinus1; + RK_S32 m_nTileRowHeightArray[128]; + RK_U32 m_loopFilterAcrossTilesEnabledFlag; + + RK_U32 m_cabacInitPresentFlag; + RK_U32 m_encCABACTableIdx; // Used to transmit table selection across slices + + RK_U32 m_sliceHeaderExtensionPresentFlag; + RK_U32 m_deblockingFilterControlPresentFlag; + RK_U32 m_LFCrossSliceBoundaryFlag; + RK_U32 m_deblockingFilterOverrideEnabledFlag; + RK_U32 m_picDisableDeblockingFilterFlag; + RK_S32 m_deblockingFilterBetaOffsetDiv2; //< beta offset for deblocking filter + RK_S32 m_deblockingFilterTcOffsetDiv2; //< tc offset for deblocking filter + RK_U32 m_scalingListPresentFlag; + +// TComScalingList* m_scalingList; //!< ScalingList class pointer + RK_U32 m_listsModificationPresentFlag; + RK_U32 m_log2ParallelMergeLevelMinus2; + RK_S32 m_numExtraSliceHeaderBits; +} H265ePps; + +typedef struct H265eSlice_e { + + RK_U32 m_saoEnabledFlag; + RK_U32 m_saoEnabledFlagChroma; ///< SAO Cb&Cr enabled flag + RK_S32 m_ppsId; ///< picture parameter set ID + RK_U32 m_picOutputFlag; ///< pic_output_flag + RK_S32 poc; + RK_S32 gop_idx; + RK_S32 last_idr; + + H265eReferencePictureSet *m_rps; + H265eReferencePictureSet m_localRPS; + RK_S32 m_bdIdx; + H265eRefPicListModification m_RefPicListModification; + H265eContextModel_t m_contextModels[MAX_OFF_CTX_MOD]; + H265eCabacCtx m_cabac; + + enum NALUnitType m_nalUnitType; ///< Nal unit type for the slice + SliceType m_sliceType; + + RK_S32 temporal_id; + RK_U32 m_IsGenB; + RK_S32 m_sliceQp; + RK_U32 m_dependentSliceSegmentFlag; + RK_U32 m_deblockingFilterDisable; + RK_U32 m_deblockingFilterOverrideFlag; //< offsets for deblocking filter inherit from PPS + RK_S32 m_deblockingFilterBetaOffsetDiv2; //< beta offset for deblocking filter + RK_S32 m_deblockingFilterTcOffsetDiv2; //< tc offset for deblocking filter + RK_S32 m_numRefIdx[2]; // for multiple reference of current slice + + RK_U32 m_bCheckLDC; + + // Data + RK_S32 m_sliceQpDelta; + RK_S32 m_sliceQpDeltaCb; + RK_S32 m_sliceQpDeltaCr; + H265eDpbFrm *m_refPicList[2][MAX_REFS + 1]; + RK_S32 m_refPOCList[2][MAX_REFS + 1]; + RK_U32 m_bIsUsedAsLongTerm[2][MAX_REFS + 1]; + + // referenced slice? + RK_U32 is_referenced; + + // access channel + H265eSps* m_sps; + H265ePps* m_pps; + H265eVps* m_vps; + RK_U32 m_colFromL0Flag; // collocated picture from List0 flag + + RK_U32 m_colRefIdx; + RK_U32 m_maxNumMergeCand; + + RK_U32 m_sliceCurEndCUAddr; + RK_U32 m_nextSlice; + RK_U32 m_sliceBits; + RK_U32 m_sliceSegmentBits; + RK_U32 m_bFinalized; + + RK_U32 m_tileOffstForMultES; + + RK_U32* m_substreamSizes; + +// TComScalingList* m_scalingList; //!< pointer of quantization matrix + RK_U32 m_cabacInitFlag; + + RK_U32 m_bLMvdL1Zero; + RK_S32 m_numEntryPointOffsets; + RK_U32 m_temporalLayerNonReferenceFlag; + RK_U32 m_LFCrossSliceBoundaryFlag; + RK_U32 m_enableTMVPFlag; + + RK_U32 slice_reserved_flag; + RK_U32 no_output_of_prior_pics_flag; + RK_U32 slice_header_extension_length; + RK_U32 ref_pic_list_modification_flag_l0; + RK_U32 lst_entry_l0; + RK_U32 tot_poc_num; + RK_U32 num_long_term_sps; + RK_U32 num_long_term_pics; +} H265eSlice; + +typedef struct H265eCtx_t { + MppEncCfgSet *cfg; + RK_U32 rc_ready; + RK_S32 idr_request; + + H265eVps vps; + H265eSps sps; + H265ePps pps; + H265eSlice *slice; + H265eDpb *dpb; + RK_U32 plt_flag; + + void *extra_info; + H265eSyntax_new syntax; + H265eFeedback feedback; +} H265eCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +void h265e_slice_set_ref_list(H265eDpbFrm *frame_list, H265eSlice *slice); +void h265e_slice_set_ref_poc_list(H265eSlice *slice); +void h265e_slice_init(void *ctx, EncFrmStatus curr); +RK_S32 h265e_code_slice_skip_frame(void *ctx, H265eSlice *slice, RK_U8 *buf, RK_S32 len); +H265eDpbFrm* get_lt_ref_pic(H265eDpbFrm *frame_list, H265eSlice *slice, RK_S32 poc, RK_U32 pocHasMsb); + +#ifdef __cplusplus +} +#endif + +#endif /* H265E_SLICE_H */ diff --git a/mpp/codec/enc/h265/h265e_stream.c b/mpp/codec/enc/h265/h265e_stream.c new file mode 100644 index 000000000..431f42afc --- /dev/null +++ b/mpp/codec/enc/h265/h265e_stream.c @@ -0,0 +1,181 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_stream" + +#include "mpp_common.h" +#include "mpp_mem.h" + +#include "h265e_stream.h" +#include "h265e_codec.h" + +static const RK_U8 ue_size_tab[256] = { + 1, 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +}; + +MPP_RET h265e_stream_init(H265eStream *s) +{ + s->buf = mpp_calloc(RK_U8, H265E_EXTRA_INFO_BUF_SIZE); + s->size = H265E_EXTRA_INFO_BUF_SIZE; + mpp_writer_init(&s->enc_stream, s->buf, s->size); + return MPP_OK; +} + +MPP_RET h265e_stream_deinit(H265eStream *s) +{ + MPP_FREE(s->buf); + mpp_writer_reset(&s->enc_stream); + return MPP_OK; +} + +MPP_RET h265e_stream_reset(H265eStream *s) +{ + mpp_writer_reset(&s->enc_stream); + return MPP_OK; +} + +MPP_RET h265e_stream_realign(H265eStream *s) +{ + if (s->enc_stream.buffered_bits) + mpp_writer_trailing(&s->enc_stream); + return MPP_OK; +} + +MPP_RET h265e_stream_write_with_log(H265eStream *s, + RK_U32 val, RK_S32 i_count, char *name) +{ + + h265e_dbg(H265E_DBG_HEADER, "write bits name %s, count %d, val %d", + name, i_count, val); + + mpp_writer_put_bits(&s->enc_stream, val, i_count); + return MPP_OK; +} + +MPP_RET h265e_stream_write1_with_log(H265eStream *s, + RK_U32 val, char *name) +{ + h265e_dbg(H265E_DBG_HEADER, "write 1 bit name %s, val %d", name, val); + + mpp_writer_put_bits(&s->enc_stream, val, 1); + + return MPP_OK; +} + +MPP_RET h265e_stream_write_ue_with_log(H265eStream *s, + RK_U32 val, char *name) +{ + + h265e_dbg(H265E_DBG_HEADER, + "write UE bits name %s, val %d ", + name, val); +#if 1 + RK_S32 size = 0; + RK_S32 tmp = ++val; + + h265e_dbg(H265E_DBG_HEADER, + "write UE bits name %s, val %d ", + name, val); + if (tmp >= 0x10000) { + size = 32; + tmp >>= 16; + } + if (tmp >= 0x100) { + size += 16; + tmp >>= 8; + } + size += ue_size_tab[tmp]; + + h265e_stream_write_with_log(s, 0, size >> 1, name); + h265e_stream_write_with_log(s, val, (size >> 1) + 1, name); +#else + mpp_writer_write_ue(&s->enc_stream, val, name); +#endif + return MPP_OK; +} + +MPP_RET h265e_stream_write_se_with_log(H265eStream *s, + RK_S32 val, char *name) +{ + RK_S32 size = 0; + RK_S32 tmp = 1 - val * 2; + if (tmp < 0) + tmp = val * 2; + + val = tmp; + if (tmp >= 0x100) { + size = 16; + tmp >>= 8; + } + size += ue_size_tab[tmp]; + + h265e_dbg(H265E_DBG_HEADER, + "write SE bits name %s, val %d ", + name, val); + + return h265e_stream_write_with_log(s, val, size, name);; +} + +MPP_RET h265e_stream_write32(H265eStream *s, RK_U32 i_bits, + char *name) +{ + h265e_stream_write_with_log(s, i_bits >> 16, 16, name); + h265e_stream_write_with_log(s, i_bits, 16, name); + return MPP_OK; +} + +RK_S32 h265e_stream_size_se( RK_S32 val ) +{ + RK_S32 tmp = 1 - val * 2; + if ( tmp < 0 ) tmp = val * 2; + if ( tmp < 256 ) + return ue_size_tab[tmp]; + else + return ue_size_tab[tmp >> 8] + 16; +} + +MPP_RET h265e_stream_rbsp_trailing(H265eStream *s) +{ + //align bits, 1+N zeros. + mpp_writer_trailing(&s->enc_stream); + return MPP_OK; +} + +/* + * Write the rest of cur_bits to the bitstream; + * results in a bitstream no longer 32-bit aligned. + */ +MPP_RET h265e_stream_flush(H265eStream *s) +{ + if (s->enc_stream.buffered_bits) + mpp_writer_trailing(&s->enc_stream); + return MPP_OK; +} diff --git a/mpp/codec/enc/h265/h265e_stream.h b/mpp/codec/enc/h265/h265e_stream.h new file mode 100644 index 000000000..3243186d4 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_stream.h @@ -0,0 +1,54 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_STREAM_H +#define H265E_STREAM_H + +#include "mpp_bitwrite.h" + +typedef struct H265eStream_t { + RK_U8 *buf; + RK_S32 size; + MppWriteCtx enc_stream; +} H265eStream; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET h265e_stream_init(H265eStream *s); +MPP_RET h265e_stream_deinit(H265eStream *s); +MPP_RET h265e_stream_reset(H265eStream *s); +MPP_RET h265e_stream_realign(H265eStream *s); +MPP_RET h265e_stream_write_with_log(H265eStream *s, + RK_U32 val, RK_S32 i_count, char *name); +MPP_RET h265e_stream_write1_with_log(H265eStream *s, + RK_U32 val, char *name); +MPP_RET h265e_stream_write_ue_with_log(H265eStream *s, + RK_U32 val, char *name); +MPP_RET h265e_stream_write_se_with_log(H265eStream *s, + RK_S32 val, char *name); +MPP_RET h265e_stream_write32(H265eStream *s, RK_U32 i_bits, + char *name); +RK_S32 h265e_stream_size_se( RK_S32 val ); +MPP_RET h265e_stream_rbsp_trailing(H265eStream *s); +MPP_RET h265e_stream_flush(H265eStream *s); + +#ifdef __cplusplus +} +#endif + +#endif /* H265E_STREAM_H */ diff --git a/mpp/codec/enc/h265/h265e_syntax.c b/mpp/codec/enc/h265/h265e_syntax.c new file mode 100644 index 000000000..c7017e940 --- /dev/null +++ b/mpp/codec/enc/h265/h265e_syntax.c @@ -0,0 +1,380 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "H265E_SYNTAX" + +#include + +#include "h265e_codec.h" +#include "h265e_slice.h" +#include "h265e_syntax_new.h" + +RK_S32 h265e_get_nal_type(H265eSlicParams* sp, RK_S32 frame_type) +{ + RK_U32 nal_type = 0; + + if (sp->temporal_id > 0) { + nal_type = (sp->non_reference_flag != 0) ? NAL_TSA_N : NAL_TSA_R; + } else if (frame_type == INTRA_FRAME) { + nal_type = NAL_IDR_W_RADL; + } else { + nal_type = (sp->non_reference_flag != 0) ? NAL_TRAIL_N : NAL_TRAIL_R; + } + + return nal_type; +} + +static void fill_picture_parameters(const H265eCtx *h, + H265ePicParams *pp) +{ + const H265ePps *pps = (H265ePps *)&h->pps; + const H265eSps *sps = (H265eSps *)&h->sps; + MppEncCfgSet *cfg = h->cfg; + memset(pp, 0, sizeof(H265ePicParams)); + + pp->pic_width = h->cfg->prep.width; + pp->pic_height = h->cfg->prep.height; + pp->hor_stride = h->cfg->prep.hor_stride; + pp->ver_stride = h->cfg->prep.ver_stride; + pp->pps_id = h->slice->m_ppsId; + pp->sps_id = pps->m_SPSId; + pp->vps_id = sps->m_VPSId; + pp->mpp_format = cfg->prep.format; + + pp->wFormatAndSequenceInfoFlags = (sps->m_chromaFormatIdc << 0) | + (sps->m_colorPlaneFlag << 2) | + ((sps->m_bitDepthY - 8) << 3) | + ((sps->m_bitDepthC - 8) << 6) | + ((sps->m_bitsForPOC - 4) << 9) | + (0 << 13) | + (0 << 14) | + (0 << 15); + + + pp->sps_max_dec_pic_buffering_minus1 = sps->m_maxDecPicBuffering[sps->m_maxTLayers - 1] - 1; + pp->log2_min_luma_coding_block_size_minus3 = sps->m_log2MinCodingBlockSize - 3; + pp->log2_diff_max_min_luma_coding_block_size = sps->m_log2DiffMaxMinCodingBlockSize; + + pp->log2_min_transform_block_size_minus2 = sps->m_quadtreeTULog2MinSize - 2; + pp->log2_diff_max_min_transform_block_size = sps->m_quadtreeTULog2MaxSize - sps->m_quadtreeTULog2MinSize; + + pp->max_transform_hierarchy_depth_inter = sps->m_quadtreeTUMaxDepthInter; + pp->max_transform_hierarchy_depth_intra = sps->m_quadtreeTUMaxDepthIntra; + + pp->num_short_term_ref_pic_sets = sps->m_RPSList.m_numberOfReferencePictureSets; + pp->num_long_term_ref_pics_sps = sps->m_numLongTermRefPicSPS; + + pp->sample_adaptive_offset_enabled_flag = sps->m_bUseSAO; + + pp->num_ref_idx_l0_default_active_minus1 = pps->m_numRefIdxL0DefaultActive - 1; + pp->num_ref_idx_l1_default_active_minus1 = pps->m_numRefIdxL1DefaultActive - 1; + pp->init_qp_minus26 = pps->m_picInitQPMinus26; + + + pp->CodingParamToolFlags = (sps->m_scalingListEnabledFlag << 0) | + (sps->m_useAMP << 1) | + (sps->m_bUseSAO << 2) | + (sps->m_usePCM << 3) | + (((sps->m_usePCM != 0) ? (sps->m_pcmBitDepthLuma - 1) : 0) << 4) | + (((sps->m_usePCM != 0) ? (sps->m_pcmBitDepthChroma - 1) : 0) << 8) | + (((sps->m_usePCM != 0) ? (sps->m_pcmLog2MinSize - 3) : 0) << 12) | + (((sps->m_usePCM != 0) ? (sps->m_pcmLog2MaxSize - sps->m_pcmLog2MinSize) : 0) << 14) | + (sps->m_bPCMFilterDisableFlag << 16) | + (sps->m_bLongTermRefsPresent << 17) | + (sps->m_TMVPFlagsPresent << 18) | + (sps->m_useStrongIntraSmoothing << 19) | + (0 << 20) | + (pps->m_outputFlagPresentFlag << 21) | + (pps->m_numExtraSliceHeaderBits << 22) | + (pps->m_signHideFlag << 25) | + (pps->m_cabacInitPresentFlag << 26) | + (0 << 27); + + pp->CodingSettingPicturePropertyFlags = (pps->m_bConstrainedIntraPred << 0) | + (pps->m_useTransformSkip << 1) | + (pps->m_useDQP << 2) | + (pps->m_bSliceChromaQpFlag << 3) | + (pps->m_bUseWeightPred << 4) | + (pps->m_useWeightedBiPred << 5) | + (pps->m_transquantBypassEnableFlag << 6) | + (pps->m_tiles_enabled_flag << 7) | + (pps->m_entropyCodingSyncEnabledFlag << 8) | + (pps->m_bTileUniformSpacing << 9) | + (pps->m_loopFilterAcrossTilesEnabledFlag << 10) | + (pps->m_LFCrossSliceBoundaryFlag << 11) | + (pps->m_deblockingFilterOverrideEnabledFlag << 12) | + (pps->m_picDisableDeblockingFilterFlag << 13) | + (pps->m_listsModificationPresentFlag << 14) | + (pps->m_sliceHeaderExtensionPresentFlag << 15); + + pp->pps_cb_qp_offset = pps->m_chromaCbQpOffset; + pp->pps_cr_qp_offset = pps->m_chromaCrQpOffset; + pp->diff_cu_qp_delta_depth = pps->m_maxCuDQPDepth; + pp->pps_beta_offset_div2 = pps->m_deblockingFilterBetaOffsetDiv2; + pp->pps_tc_offset_div2 = pps->m_deblockingFilterTcOffsetDiv2; + pp->log2_parallel_merge_level_minus2 = pps->m_log2ParallelMergeLevelMinus2 - 2; + if (pps->m_tiles_enabled_flag) { + RK_U8 i = 0; + + mpp_assert(pps->m_nNumTileColumnsMinus1 <= 19); + mpp_assert(pps->m_nNumTileRowsMinus1 <= 21); + + pp->num_tile_columns_minus1 = pps->m_nNumTileColumnsMinus1; + pp->num_tile_rows_minus1 = pps->m_nNumTileRowsMinus1; + + for (i = 0; i <= pp->num_tile_columns_minus1; i++) + pp->column_width_minus1[i] = pps->m_nTileColumnWidthArray[i] - 1; + + for (i = 0; i <= pp->num_tile_rows_minus1; i++) + pp->row_height_minus1[i] = pps->m_nTileRowHeightArray[i] - 1; + } +} + +static void fill_slice_parameters( const H265eCtx *h, + H265eSlicParams *sp) +{ + MppEncH265Cfg *codec = &h->cfg->h265; + H265eSlice *slice = h->slice; + memset(sp, 0, sizeof(H265eSlicParams)); + if (codec->slice_cfg.split_enable) { + sp->sli_splt_cpst = 1; + sp->sli_splt = 1; + sp->sli_splt_mode = codec->slice_cfg.split_mode; + if (codec->slice_cfg.split_mode) { + sp->sli_splt_cnum_m1 = codec->slice_cfg.slice_size - 1; + } else { + sp->sli_splt_byte = codec->slice_cfg.slice_size; + } + sp->sli_max_num_m1 = 50; + sp->sli_flsh = 1; + } + + sp->cbc_init_flg = slice->m_cabacInitFlag; + sp->mvd_l1_zero_flg = slice->m_bLMvdL1Zero; + sp->merge_up_flag = codec->merge_cfg.merge_up_flag; + sp->merge_left_flag = codec->merge_cfg.merge_left_flag; + sp->ref_pic_lst_mdf_l0 = slice->ref_pic_list_modification_flag_l0; + + sp->num_refidx_l1_act = 0; + sp->num_refidx_l0_act = 0; + + sp->num_refidx_act_ovrd = (((RK_U32)slice->m_numRefIdx[0] != slice->m_pps->m_numRefIdxL0DefaultActive) + || (slice->m_sliceType == B_SLICE && + (RK_U32)slice->m_numRefIdx[1] != slice->m_pps->m_numRefIdxL1DefaultActive)); + + sp->sli_sao_chrm_flg = slice->m_sps->m_bUseSAO && slice->m_saoEnabledFlagChroma; + sp->sli_sao_luma_flg = slice->m_sps->m_bUseSAO && slice->m_saoEnabledFlag; + sp->sli_tmprl_mvp_en = slice->m_enableTMVPFlag; + + sp->pic_out_flg = slice->m_picOutputFlag; + sp->slice_type = slice->m_sliceType; + sp->slice_rsrv_flg = 0; + sp->dpdnt_sli_seg_flg = 0; + sp->sli_pps_id = slice->m_pps->m_PPSId; + sp->no_out_pri_pic = slice->no_output_of_prior_pics_flag; + + sp->sli_tc_ofst_div2 = slice->m_deblockingFilterTcOffsetDiv2; + sp->sli_beta_ofst_div2 = slice->m_deblockingFilterBetaOffsetDiv2; + sp->sli_lp_fltr_acrs_sli = slice->m_LFCrossSliceBoundaryFlag; + sp->sli_dblk_fltr_dis = slice->m_deblockingFilterDisable; + sp->dblk_fltr_ovrd_flg = slice->m_deblockingFilterOverrideFlag; + sp->sli_cb_qp_ofst = slice->m_sliceQpDeltaCb; + sp->sli_qp = slice->m_sliceQp; + sp->max_mrg_cnd = slice->m_maxNumMergeCand; + sp->temporal_id = slice->temporal_id; + sp->non_reference_flag = slice->m_temporalLayerNonReferenceFlag; + sp->col_ref_idx = 0; + sp->col_frm_l0_flg = slice->m_colFromL0Flag; + sp->sli_poc_lsb = (slice->poc - slice->last_idr + (1 << slice->m_sps->m_bitsForPOC)) % + (1 << slice->m_sps->m_bitsForPOC); + sp->sli_hdr_ext_len = slice->slice_header_extension_length; +} + +RK_S32 fill_ref_parameters(const H265eCtx *h, H265eSlicParams *sp) +{ + H265eSlice *slice = h->slice; + H265eReferencePictureSet* rps = slice->m_rps; + RK_U32 numRpsCurrTempList = 0; + RK_S32 ref_num = 0; + H265eDpbFrm *ref_frame; + RK_S32 i, j, k; + sp->dlt_poc_msb_prsnt0 = 0; + sp->dlt_poc_msb_cycl0 = 0; + sp->tot_poc_num = 0; + if (slice->m_bdIdx < 0) { + RK_S32 prev = 0; + sp->st_ref_pic_flg = 0; + sp->num_neg_pic = rps->num_negative_pic; + sp->num_pos_pic = rps->num_positive_pic; + for (j = 0; j < rps->num_negative_pic; j++) { + if (0 == j) { + sp->dlt_poc_s0_m10 = prev - rps->delta_poc[j] - 1; + sp->used_by_s0_flg = rps->m_ref[j]; + } else if (1 == j) { + sp->dlt_poc_s0_m11 = prev - rps->delta_poc[j] - 1; + sp->used_by_s0_flg |= rps->m_ref[j] << 1; + } else if (2 == j) { + sp->dlt_poc_s0_m12 = prev - rps->delta_poc[j] - 1; + sp->used_by_s0_flg |= rps->m_ref[j] << 2; + } else if (3 == j) { + sp->dlt_poc_s0_m13 = prev - rps->delta_poc[j] - 1; + sp->used_by_s0_flg |= rps->m_ref[j] << 3; + } + prev = rps->delta_poc[j]; + } + } + + for (i = 0; i < rps->m_numberOfPictures; i++) { + if (rps->m_ref[i]) { + sp->tot_poc_num++; + } + } + + if (slice->m_sps->m_bLongTermRefsPresent) { + RK_S32 numLtrpInSH = rps->num_long_term_pic; + RK_S32 numLtrpInSPS = 0; + RK_U32 poc_lsb_lt[3] = { 0, 0, 0 }; + RK_U32 used_by_lt_flg[3] = { 0, 0, 0 }; + RK_U32 dlt_poc_msb_prsnt[3] = { 0, 0, 0 }; + RK_U32 dlt_poc_msb_cycl[3] = { 0, 0, 0 }; + RK_S32 prevDeltaMSB = 0; + RK_S32 offset = rps->num_negative_pic + rps->num_positive_pic; + RK_S32 numLongTerm = rps->m_numberOfPictures - offset; + RK_S32 bitsForLtrpInSPS = 0; + for (k = rps->m_numberOfPictures - 1; k > rps->m_numberOfPictures - rps->num_long_term_pic - 1; k--) { + RK_U32 lsb = rps->poc[k] % (1 << slice->m_sps->m_bitsForPOC); + RK_U32 find_flag = 0; + for (i = 0; i < (RK_S32)slice->m_sps->m_numLongTermRefPicSPS; i++) { + if ((lsb == slice->m_sps->m_ltRefPicPocLsbSps[i]) && (rps->m_used[k] == slice->m_sps->m_usedByCurrPicLtSPSFlag[i])) { + find_flag = 1; + break; + } + } + + if (find_flag) + numLtrpInSPS++; + } + + numLtrpInSH -= numLtrpInSPS; + + while (slice->m_sps->m_numLongTermRefPicSPS > (RK_U32)(1 << bitsForLtrpInSPS)) { + bitsForLtrpInSPS++; + } + + if (slice->m_sps->m_numLongTermRefPicSPS > 0) { + sp->num_lt_sps = numLtrpInSPS; + } + sp->num_lt_pic = numLtrpInSH; + // Note that the LSBs of the LT ref. pic. POCs must be sorted before. + // Not sorted here because LT ref indices will be used in setRefPicList() + sp->poc_lsb_lt0 = 0; + sp->used_by_lt_flg0 = 0; + sp->dlt_poc_msb_prsnt0 = 0; + sp->dlt_poc_msb_cycl0 = 0; + sp->poc_lsb_lt1 = 0; + sp->used_by_lt_flg1 = 0; + sp->dlt_poc_msb_prsnt1 = 0; + sp->dlt_poc_msb_cycl1 = 0; + sp->poc_lsb_lt2 = 0; + sp->used_by_lt_flg2 = 0; + sp->dlt_poc_msb_prsnt2 = 0; + sp->dlt_poc_msb_cycl2 = 0; + + for ( i = rps->m_numberOfPictures - 1; i > offset - 1; i--) { + RK_U32 deltaFlag = 0; + if ((i == rps->m_numberOfPictures - 1) || (i == rps->m_numberOfPictures - 1 - numLtrpInSPS)) { + deltaFlag = 1; + } + poc_lsb_lt[numLongTerm - 1 - (i - offset)] = rps->m_pocLSBLT[i]; + used_by_lt_flg[numLongTerm - 1 - (i - offset)] = rps->m_ref[i]; + dlt_poc_msb_prsnt[numLongTerm - 1 - (i - offset)] = rps->m_deltaPocMSBPresentFlag[i]; + + if (rps->m_deltaPocMSBPresentFlag[i]) { + if (deltaFlag) { + dlt_poc_msb_cycl[numLongTerm - 1 - (i - offset)] = rps->m_deltaPOCMSBCycleLT[i]; + } else { + RK_S32 differenceInDeltaMSB = rps->m_deltaPOCMSBCycleLT[i] - prevDeltaMSB; + mpp_assert(differenceInDeltaMSB >= 0); + dlt_poc_msb_cycl[numLongTerm - 1 - (i - offset)] = differenceInDeltaMSB; + } + } + prevDeltaMSB = rps->m_deltaPOCMSBCycleLT[i]; + } + + sp->poc_lsb_lt0 = poc_lsb_lt[0]; + sp->used_by_lt_flg0 = used_by_lt_flg[0]; + sp->dlt_poc_msb_prsnt0 = dlt_poc_msb_prsnt[0]; + sp->dlt_poc_msb_cycl0 = dlt_poc_msb_cycl[0]; + sp->poc_lsb_lt1 = poc_lsb_lt[1]; + sp->used_by_lt_flg1 = used_by_lt_flg[1]; + sp->dlt_poc_msb_prsnt1 = dlt_poc_msb_prsnt[1]; + sp->dlt_poc_msb_cycl1 = dlt_poc_msb_cycl[1]; + sp->poc_lsb_lt2 = poc_lsb_lt[2]; + sp->used_by_lt_flg2 = used_by_lt_flg[2]; + sp->dlt_poc_msb_prsnt2 = dlt_poc_msb_prsnt[2]; + sp->dlt_poc_msb_cycl2 = dlt_poc_msb_cycl[2]; + } + + sp->lst_entry_l0 = 0; + sp->ref_pic_lst_mdf_l0 = 0; + + if (slice->m_sliceType == I_SLICE) { + numRpsCurrTempList = 0; + } else { + ref_num = rps->num_negative_pic + rps->num_positive_pic + rps->num_long_term_pic; + for (i = 0; i < ref_num; i++) { + if (rps->m_used[i]) { + numRpsCurrTempList++; + } + } + } + + if (slice->m_pps->m_listsModificationPresentFlag && numRpsCurrTempList > 1) { + H265eRefPicListModification* refPicListModification = &slice->m_RefPicListModification; + if (slice->m_sliceType != I_SLICE) { + sp->ref_pic_lst_mdf_l0 = (refPicListModification->m_refPicListModificationFlagL0 != 0) ? 1 : 0; + if (sp->ref_pic_lst_mdf_l0) { + sp->lst_entry_l0 = refPicListModification->m_RefPicSetIdxL0[0]; + } + } + } + + sp->recon_pic.slot_idx = h->dpb->curr->slot_idx; + ref_frame = slice->m_refPicList[0][0]; + + if (ref_frame) { + if (ref_frame->status.force_pskip_is_ref) + sp->ref_pic.slot_idx = slice->m_refPicList[0][0]->prev_ref_idx; + else + sp->ref_pic.slot_idx = ref_frame->slot_idx; + } else { + sp->ref_pic.slot_idx = h->dpb->curr->slot_idx; + } + return 0; +} + +RK_S32 h265e_syntax_fill(void *ctx) +{ + H265eCtx *h = (H265eCtx *)ctx; + H265eSyntax_new *syn = (H265eSyntax_new*)&h->syntax; + + fill_picture_parameters(h, &syn->pp); + fill_slice_parameters(h, &syn->sp); + fill_ref_parameters(h, &syn->sp); + syn->dpb = h->dpb; + return 0; +} diff --git a/mpp/codec/enc/jpeg/CMakeLists.txt b/mpp/codec/enc/jpeg/CMakeLists.txt new file mode 100644 index 000000000..504a1ec53 --- /dev/null +++ b/mpp/codec/enc/jpeg/CMakeLists.txt @@ -0,0 +1,7 @@ +# vim: syntax=cmake +include_directories(.) + +# jpeg encoder sourse +add_library(jpege_api OBJECT + jpege_api_v2.c + ) diff --git a/mpp/codec/enc/jpeg/jpege_api_v2.c b/mpp/codec/enc/jpeg/jpege_api_v2.c new file mode 100644 index 000000000..13513613b --- /dev/null +++ b/mpp/codec/enc/jpeg/jpege_api_v2.c @@ -0,0 +1,351 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "jpege_api_v2" + +#include + +#include "mpp_err.h" +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_2str.h" +#include "mpp_enc_cfg.h" +#include "mpp_bitwrite.h" +#include "mpp_soc.h" + +#include "jpege_debug.h" +#include "jpege_api_v2.h" +#include "jpege_syntax.h" + +typedef struct { + MppEncCfgSet *cfg; + JpegeSyntax syntax; +} JpegeCtx; + +/* + * from RFC435 spec. + */ + +RK_U32 jpege_debug = 0; + +static MPP_RET jpege_init_v2(void *ctx, EncImplCfg *cfg) +{ + JpegeCtx *p = (JpegeCtx *)ctx; + + mpp_env_get_u32("jpege_debug", &jpege_debug, 0); + jpege_dbg_func("enter ctx %p\n", ctx); + + p->cfg = cfg->cfg; + + mpp_assert(cfg->coding = MPP_VIDEO_CodingMJPEG); + + { + /* init default rc config */ + MppEncRcCfg *rc = &p->cfg->rc; + MppEncJpegCfg *jpeg_cfg = &p->cfg->jpeg; + + rc->fps_in_flex = 0; + rc->fps_in_num = 30; + rc->fps_in_denom = 1; + rc->fps_out_flex = 0; + rc->fps_out_num = 30; + rc->fps_out_denom = 1; + rc->rc_mode = MPP_ENC_RC_MODE_FIXQP; + + /* set quant to invalid value */ + jpeg_cfg->quant = -1; + jpeg_cfg->quant_ext = -1; + } + + jpege_dbg_func("leave ctx %p\n", ctx); + return MPP_OK; +} + +static MPP_RET jpege_deinit_v2(void *ctx) +{ + jpege_dbg_func("enter ctx %p\n", ctx); + + jpege_dbg_func("leave ctx %p\n", ctx); + return MPP_OK; +} + +static MPP_RET jpege_proc_cfg(void *ctx, MpiCmd cmd, void *param) +{ + MPP_RET ret = MPP_OK; + + jpege_dbg_func("enter ctx %p cmd %x param %p\n", ctx, cmd, param); + + switch (cmd) { + case MPP_ENC_SET_CFG : + case MPP_ENC_SET_IDR_FRAME : + case MPP_ENC_SET_OSD_PLT_CFG : + case MPP_ENC_SET_OSD_DATA_CFG : + case MPP_ENC_GET_SEI_DATA : + case MPP_ENC_SET_SEI_CFG : { + } break; + default: + mpp_err_f("No correspond cmd(%08x) found, and can not config!", cmd); + ret = MPP_NOK; + break; + } + + jpege_dbg_func("leave ret %d\n", ret); + return ret; +} + +static MPP_RET jpege_start(void *ctx, HalEncTask *task) +{ + JpegeCtx *p = (JpegeCtx *)ctx; + JpegeSyntax syntax = p->syntax; + MppPacket pkt = task->packet; + RK_U8 *ptr = mpp_packet_get_pos(pkt); + size_t buf_size = mpp_packet_get_size(pkt); + RK_S32 size = 0; + MppWriteCtx bit_ctx; + MppWriteCtx *bits = &bit_ctx; + + mpp_writer_init(bits, ptr, buf_size); + + /* add SOI and APP0 data */ + /* SOI */ + mpp_writer_put_raw_bits(bits, 0xFFD8, 16); + /* APP0 */ + mpp_writer_put_raw_bits(bits, 0xFFE0, 16); + /* length */ + mpp_writer_put_raw_bits(bits, 0x0010, 16); + /* "JFIF" ID */ + /* Ident1 */ + mpp_writer_put_raw_bits(bits, 0x4A46, 16); + /* Ident2 */ + mpp_writer_put_raw_bits(bits, 0x4946, 16); + /* Ident3 */ + mpp_writer_put_raw_bits(bits, 0x00, 8); + /* Version */ + mpp_writer_put_raw_bits(bits, 0x0102, 16); + + if (syntax.density_x && syntax.density_y) { + /* Units */ + mpp_writer_put_raw_bits(bits, syntax.units_type, 8); + /* Xdensity */ + mpp_writer_put_raw_bits(bits, syntax.density_x, 16); + /* Ydensity */ + mpp_writer_put_raw_bits(bits, syntax.density_y, 16); + } else { + /* Units */ + mpp_writer_put_raw_bits(bits, 0, 8); + /* Xdensity */ + mpp_writer_put_raw_bits(bits, 0, 8); + mpp_writer_put_raw_bits(bits, 1, 8); + /* Ydensity */ + mpp_writer_put_raw_bits(bits, 1, 16); + } + /* XThumbnail */ + mpp_writer_put_raw_bits(bits, 0x00, 8); + /* YThumbnail */ + mpp_writer_put_raw_bits(bits, 0x00, 8); + /* Do NOT write thumbnail */ + size = mpp_writer_bytes(bits); + mpp_packet_set_length(pkt, size); + task->length += size; + + return MPP_OK; +} + +static MPP_RET init_jpeg_component_info(JpegeSyntax *syntax) +{ + MPP_RET ret = MPP_OK; + JPEGCompInfo *comp_info = (JPEGCompInfo *)syntax->comp_info; + + jpege_dbg_input("Chroma format %d\n", syntax->format_out); + + if (syntax->format_out == MPP_CHROMA_UNSPECIFIED) + syntax->format_out = MPP_CHROMA_420; + + memset(comp_info, 0, sizeof(JPEGCompInfo) * MAX_NUMBER_OF_COMPONENTS); + + switch (syntax->format_out) { + case MPP_CHROMA_400: + syntax->nb_components = 1; + comp_info[0].val = 1 | 1 << 8 | 1 << 16; + break; + case MPP_CHROMA_420: + syntax->nb_components = 3; + comp_info[0].val = 1 | 2 << 8 | 2 << 16; + comp_info[1].val = 2 | 1 << 8 | 1 << 16 | 1 << 24; + comp_info[2].val = 3 | 1 << 8 | 1 << 16 | 1 << 24; + break; + case MPP_CHROMA_422: + syntax->nb_components = 3; + comp_info[0].val = 1 | 2 << 8 | 1 << 16; + comp_info[1].val = 2 | 1 << 8 | 1 << 16 | 1 << 24; + comp_info[2].val = 3 | 1 << 8 | 1 << 16 | 1 << 24; + break; + case MPP_CHROMA_444: + syntax->nb_components = 3; + comp_info[0].val = 1 | 1 << 8 | 1 << 16; + comp_info[1].val = 2 | 1 << 8 | 1 << 16 | 1 << 24; + comp_info[2].val = 3 | 1 << 8 | 1 << 16 | 1 << 24; + break; + default: + syntax->nb_components = 1; + comp_info[0].val = 1 | 1 << 8 | 1 << 16; + mpp_err("Unsupported chroma format %d\n", syntax->format_out); + ret = MPP_ERR_VALUE; + break; + } + + syntax->mcu_width = comp_info[0].h_sample_factor * DCT_SIZE; + syntax->mcu_height = comp_info[0].v_sample_factor * DCT_SIZE; + syntax->mcu_hor_cnt = (syntax->width + syntax->mcu_width - 1) / syntax->mcu_width; + syntax->mcu_ver_cnt = (syntax->height + syntax->mcu_height - 1) / syntax->mcu_height; + syntax->mcu_cnt = syntax->mcu_hor_cnt * syntax->mcu_ver_cnt; + + return ret; +} + +static MPP_RET jpege_proc_hal(void *ctx, HalEncTask *task) +{ + JpegeCtx *p = (JpegeCtx *)ctx; + MppFrame frame = task->frame; + JpegeSyntax *syntax = &p->syntax; + MppEncCfgSet *cfg = p->cfg; + MppEncPrepCfg *prep = &cfg->prep; + MppEncJpegCfg *jpeg = &cfg->jpeg; + MppEncSliceSplit *split = &cfg->split; + + jpege_dbg_func("enter ctx %p\n", ctx); + + syntax->width = prep->width; + syntax->height = prep->height; + syntax->hor_stride = prep->hor_stride; + syntax->ver_stride = prep->ver_stride; + syntax->format = prep->format; + syntax->format_out = prep->format_out; + syntax->color = prep->color; + syntax->rotation = prep->rotation; + syntax->mirroring = prep->mirroring; + syntax->offset_x = mpp_frame_get_offset_x(frame); + syntax->offset_y = mpp_frame_get_offset_y(frame); + syntax->q_mode = jpeg->q_mode; + syntax->quant = jpeg->quant; + syntax->q_factor = jpeg->q_factor; + syntax->qf_min = jpeg->qf_min; + syntax->qf_max = jpeg->qf_max; + syntax->qtable_y = jpeg->qtable_y; + syntax->qtable_u = jpeg->qtable_u; + syntax->qtable_v = jpeg->qtable_v; + syntax->part_rows = 0; + syntax->restart_ri = 0; + syntax->low_delay = 0; + + init_jpeg_component_info(syntax); + + if (split->split_mode) { + RK_U32 mb_w = syntax->mcu_hor_cnt; + RK_U32 mb_h = syntax->mcu_ver_cnt; + RK_U32 part_rows = 0; + + if (split->split_mode == MPP_ENC_SPLIT_BY_CTU) { + RK_U32 part_mbs = split->split_arg; + + if (part_mbs > 0 && part_mbs <= syntax->mcu_cnt) { + part_rows = (part_mbs + mb_w - 1) / mb_w; + if (part_rows >= mb_h) + part_rows = 0; + } else { + mpp_err_f("warning: invalid split arg %d > max %d\n", + part_mbs, syntax->mcu_cnt); + } + } else { + mpp_err_f("warning: only mcu split is supported\n"); + } + + if (part_rows) { + syntax->part_rows = part_rows; + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3576 && split->split_arg <= syntax->mcu_cnt) + syntax->restart_ri = split->split_arg; + else + syntax->restart_ri = syntax->mcu_hor_cnt * part_rows; + syntax->low_delay = cfg->base.low_delay && part_rows; + jpege_dbg_func("Split by CTU, part_rows %d, restart_ri %d", + syntax->part_rows, syntax->restart_ri); + } + } + + task->valid = 1; + task->syntax.data = syntax; + task->syntax.number = 1; + + jpege_dbg_func("leave ctx %p\n", ctx); + return MPP_OK; +} + +static MPP_RET jpege_add_Prefix(MppPacket pkt, RK_S32 *len, RK_U8 uuid[16], + const void *data, RK_S32 size) +{ + RK_U8 *ptr = mpp_packet_get_pos(pkt); + size_t length = mpp_packet_get_length(pkt); + size_t buf_size = mpp_packet_get_size(pkt); + MppWriteCtx bit_ctx; + MppWriteCtx *bits = &bit_ctx; + const RK_U8 *user_data = data; + RK_S32 i = 0, app_size = 0; + + mpp_writer_init(bits, ptr + length, buf_size - length); + + if ((size > 8) && user_data[0] == 0xFF && user_data[1] == 0xE1 && + user_data[4] == 0x45 && user_data[5] == 0x78 && + user_data[6] == 0x69 && user_data[7] == 0x66) { + jpege_dbg_func("write EXIF data, total length %d\n", size); + } else if ((size > 8) && user_data[0] == 0xFF && user_data[1] == 0xE2 && + user_data[4] == 0x4D && user_data[5] == 0x50 && + user_data[6] == 0x46 && user_data[7] == 0x00) { + jpege_dbg_func("write MPF data, total length %d\n", size); + } else { + /* add user data to APP7 */ + mpp_writer_put_raw_bits(bits, 0xFFE7, 16); + /* length */ + mpp_writer_put_raw_bits(bits, size + 2, 16); + } + + /* data */ + for (i = 0; i < size; i++) + mpp_writer_put_raw_bits(bits, user_data[i], 8); + + app_size = mpp_writer_bytes(bits); + *len = app_size; + length += app_size; + mpp_packet_set_length(pkt, length); + (void)uuid; + return MPP_OK; +} + +const EncImplApi api_jpege = { + .name = "jpege_control", + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegeCtx), + .flag = 0, + .init = jpege_init_v2, + .deinit = jpege_deinit_v2, + .proc_cfg = jpege_proc_cfg, + .gen_hdr = NULL, + .start = jpege_start, + .proc_dpb = NULL, + .proc_hal = jpege_proc_hal, + .add_prefix = jpege_add_Prefix, + .sw_enc = NULL, +}; diff --git a/mpp/codec/enc/jpeg/jpege_debug.h b/mpp/codec/enc/jpeg/jpege_debug.h new file mode 100644 index 000000000..9f6556d44 --- /dev/null +++ b/mpp/codec/enc/jpeg/jpege_debug.h @@ -0,0 +1,37 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JPEGE_DEBUG_H +#define JPEGE_DEBUG_H + +#include "mpp_debug.h" + +#define JPEGE_DBG_FUNCTION (0x00000001) +#define JPEGE_DBG_INPUT (0x00000010) +#define JPEGE_DBG_OUTPUT (0x00000020) +#define JPEGE_DBG_CTRL (0x00000040) + +#define jpege_dbg(flag, fmt, ...) mpp_dbg(jpege_debug, flag, fmt, ## __VA_ARGS__) +#define jpege_dbg_f(flag, fmt, ...) mpp_dbg_f(jpege_debug, flag, fmt, ## __VA_ARGS__) + +#define jpege_dbg_func(fmt, ...) jpege_dbg_f(JPEGE_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define jpege_dbg_input(fmt, ...) jpege_dbg(JPEGE_DBG_INPUT, fmt, ## __VA_ARGS__) +#define jpege_dbg_output(fmt, ...) jpege_dbg(JPEGE_DBG_OUTPUT, fmt, ## __VA_ARGS__) +#define jpege_dbg_ctrl(fmt, ...) jpege_dbg(JPEGE_DBG_CTRL, fmt, ## __VA_ARGS__) + +extern RK_U32 jpege_debug; + +#endif /* JPEGE_DEBUG_H */ diff --git a/mpp/codec/enc/vp8/CMakeLists.txt b/mpp/codec/enc/vp8/CMakeLists.txt new file mode 100644 index 000000000..03f4440c7 --- /dev/null +++ b/mpp/codec/enc/vp8/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(.) + +# vp8 encoder sourse +add_library(vp8e_api OBJECT + vp8e_api_v2.c + ) diff --git a/mpp/codec/enc/vp8/vp8e_api_v2.c b/mpp/codec/enc/vp8/vp8e_api_v2.c new file mode 100644 index 000000000..b65347648 --- /dev/null +++ b/mpp/codec/enc/vp8/vp8e_api_v2.c @@ -0,0 +1,208 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "vp8e_api_v2" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_rc.h" +#include "mpp_enc_cfg.h" + +#include "vp8e_api_v2.h" +#include "vp8e_syntax.h" + +#define VP8E_DBG_FUNCTION (0x00000001) +#define VP8E_DBG_CFG (0x00000002) + +#define vp8e_dbg_cfg(fmt, ...) mpp_dbg_f(vp8e_debug, VP8E_DBG_CFG, fmt, ## __VA_ARGS__) +#define vp8e_dbg_fun(fmt, ...) mpp_dbg_f(vp8e_debug, VP8E_DBG_FUNCTION, fmt, ## __VA_ARGS__) + +RK_U32 vp8e_debug = 0; +#define VP8E_SYN_BUTT 2 + +typedef struct { + /* config from mpp_enc */ + MppEncCfgSet *cfg; + + /* internal rate control config*/ + Vp8eRc *rc; + + Vp8eSyntax vp8e_syntax[VP8E_SYN_BUTT]; +} Vp8eCtx; + +static MPP_RET vp8e_init(void *ctx, EncImplCfg *ctrl_cfg) +{ + MPP_RET ret = MPP_OK; + Vp8eCtx *p = (Vp8eCtx *)ctx; + + MppEncRcCfg *rc_cfg = &ctrl_cfg->cfg->rc; + MppEncPrepCfg *prep = &ctrl_cfg->cfg->prep; + + vp8e_dbg_fun("enter\n"); + if (NULL == ctx || NULL == ctrl_cfg) { + mpp_err_f("Init failed, contex or controller cfg is null!\n"); + ret = MPP_NOK; + goto __ERR_RET; + } + + p->cfg = ctrl_cfg->cfg; + + /* + * default prep: + * 720p + * YUV420SP + */ + prep->width = 1280; + prep->height = 720; + prep->hor_stride = 1280; + prep->ver_stride = 720; + prep->format = MPP_FMT_YUV420SP; + prep->rotation = MPP_ENC_ROT_0; + prep->rotation_ext = MPP_ENC_ROT_0; + prep->mirroring = 0; + prep->mirroring_ext = 0; + prep->denoise = 0; + + /* + * default rc_cfg: + * CBR + * 2Mbps +-25% + * 30fps + * gop 60 + */ + rc_cfg->rc_mode = MPP_ENC_RC_MODE_CBR; + rc_cfg->quality = MPP_ENC_RC_QUALITY_MEDIUM; + rc_cfg->bps_target = 2000 * 1000; + rc_cfg->bps_max = rc_cfg->bps_target * 5 / 4; + rc_cfg->bps_min = rc_cfg->bps_target * 3 / 4; + rc_cfg->fps_in_flex = 0; + rc_cfg->fps_in_num = 30; + rc_cfg->fps_in_denom = 1; + rc_cfg->fps_out_flex = 0; + rc_cfg->fps_out_num = 30; + rc_cfg->fps_out_denom = 1; + rc_cfg->gop = 60; + rc_cfg->max_reenc_times = 1; + rc_cfg->fqp_min_i = INT_MAX; + rc_cfg->fqp_min_p = INT_MAX; + rc_cfg->fqp_max_i = INT_MAX; + rc_cfg->fqp_max_p = INT_MAX; + + p->rc = mpp_calloc(Vp8eRc, 1); + memset(p->rc, 0, sizeof(Vp8eRc)); + p->rc->frame_coded = 1; + if (NULL == p->rc) { + mpp_err_f("failed to malloc vp8_rc\n"); + ret = MPP_ERR_MALLOC; + goto __ERR_RET; + } + + mpp_env_get_u32("vp8e_debug", &vp8e_debug, 0); + + vp8e_dbg_fun("leave ret %d\n", ret); + return ret; + +__ERR_RET: + vp8e_dbg_fun("leave ret %d\n", ret); + return ret; +} + +static MPP_RET vp8e_deinit(void *ctx) +{ + Vp8eCtx *p = (Vp8eCtx *)ctx; + + vp8e_dbg_fun("enter\n"); + + if (p->rc) + mpp_free(p->rc); + + vp8e_dbg_fun("leave\n"); + return MPP_OK; +} + +static MPP_RET vp8e_start(void *ctx, HalEncTask *task) +{ + (void)ctx; + (void)task; + + return MPP_OK; +} + +static MPP_RET vp8e_proc_dpb(void *ctx, HalEncTask *task) +{ + (void)ctx; + EncRcTask *rc_task = task->rc_task; + EncCpbStatus *cpb = &task->rc_task->cpb; + rc_task->frm.val = cpb->curr.val; + return MPP_OK; +} + +static MPP_RET vp8e_proc_cfg(void *ctx, MpiCmd cmd, void *param) +{ + MPP_RET ret = MPP_OK; + + vp8e_dbg_fun("enter ctx %p cmd %x param %p\n", ctx, cmd, param); + switch (cmd) { + case MPP_ENC_SET_CFG : { + } break; + default: { + mpp_err("No correspond cmd found, and can not config!"); + ret = MPP_NOK; + } break; + } + + vp8e_dbg_fun("leave ret %d\n", ret); + return ret; +} + +static MPP_RET vp8e_proc_hal(void *ctx, HalEncTask *task) +{ + Vp8eCtx *p = (Vp8eCtx *)ctx; + Vp8eSyntax *syntax = &p->vp8e_syntax[0]; + RK_U32 syn_num = 0; + + syntax[syn_num].type = VP8E_SYN_CFG; + syntax[syn_num].data = p->cfg; + syn_num++; + syntax[syn_num].type = VP8E_SYN_RC; + syntax[syn_num].data = p->rc; + syn_num++; + task->syntax.data = syntax; + task->syntax.number = syn_num; + + task->valid = 1; + return MPP_OK; +} + +const EncImplApi api_vp8e = { + .name = "vp8_control", + .coding = MPP_VIDEO_CodingVP8, + .ctx_size = sizeof(Vp8eCtx), + .flag = 0, + .init = vp8e_init, + .deinit = vp8e_deinit, + .proc_cfg = vp8e_proc_cfg, + .gen_hdr = NULL, + .start = vp8e_start, + .proc_dpb = vp8e_proc_dpb, + .proc_hal = vp8e_proc_hal, + .add_prefix = NULL, + .sw_enc = NULL, +}; diff --git a/mpp/codec/enc/vp8/vp8e_debug.h b/mpp/codec/enc/vp8/vp8e_debug.h new file mode 100644 index 000000000..66251150d --- /dev/null +++ b/mpp/codec/enc/vp8/vp8e_debug.h @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VP8E_DEBUG_H +#define VP8E_DEBUG_H + +#include "mpp_debug.h" + +#define VP8E_DBG_RC_FUNCTION (0x00010000) +#define VP8E_DBG_RC_BPS (0x00020000) +#define VP8E_DBG_RC (0x00040000) +#define VP8E_DBG_RC_CFG (0x00080000) + +#define VP8E_DBG(flag, fmt, ...) mpp_dbg(vp8e_rc_debug, flag, fmt, ## __VA_ARGS__) +#define VP8E_DBG_F(flag, fmt, ...) mpp_dbg_f(vp8e_rc_debug, flag, fmt, ## __VA_ARGS__) + + +#define vp8e_rc_dbg_func(fmt, ...) VP8E_DBG_F(VP8E_DBG_RC_FUNCTION, fmt, ## __VA_ARGS__) +#define vp8e_rc_dbg_bps(fmt, ...) VP8E_DBG(VP8E_DBG_RC_BPS, fmt, ## __VA_ARGS__) +#define vp8e_rc_dbg_rc(fmt, ...) VP8E_DBG(VP8E_DBG_RC, fmt, ## __VA_ARGS__) +#define vp8e_rc_dbg_cfg(fmt, ...) VP8E_DBG(VP8E_DBG_RC_CFG, fmt, ## __VA_ARGS__) + +extern RK_U32 vp8e_rc_debug; + +#endif // VP8E_DEBUG_H diff --git a/mpp/codec/enc_impl.c b/mpp/codec/enc_impl.c new file mode 100644 index 000000000..d9d4b3700 --- /dev/null +++ b/mpp/codec/enc_impl.c @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2010 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "enc_impl" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_packet_impl.h" + +#include "h264e_api_v2.h" +#include "jpege_api_v2.h" +#include "h265e_api.h" +#include "vp8e_api_v2.h" +#include "enc_impl.h" + +/* + * all encoder controller static register here + */ +static const EncImplApi *enc_apis[] = { +#if HAVE_H264E + &api_h264e, +#endif +#if HAVE_H265E + &api_h265e, +#endif +#if HAVE_JPEGE + &api_jpege, +#endif +#if HAVE_VP8E + &api_vp8e, +#endif +}; + +typedef struct EncImplCtx_t { + EncImplCfg cfg; + const EncImplApi *api; + void *ctx; +} EncImplCtx; + +MPP_RET enc_impl_init(EncImpl *impl, EncImplCfg *cfg) +{ + if (NULL == impl || NULL == cfg) { + mpp_err_f("found NULL input controller %p config %p\n", impl, cfg); + return MPP_ERR_NULL_PTR; + } + + *impl = NULL; + + RK_U32 i; + const EncImplApi **apis = enc_apis; + RK_U32 api_cnt = MPP_ARRAY_ELEMS(enc_apis); + + for (i = 0; i < api_cnt; i++) { + const EncImplApi *api = apis[i]; + + if (cfg->coding == api->coding) { + EncImplCtx *p = mpp_calloc(EncImplCtx, 1); + void *ctx = mpp_calloc_size(void, api->ctx_size); + + if (NULL == ctx || NULL == p) { + mpp_err_f("failed to alloc encoder context\n"); + mpp_free(p); + mpp_free(ctx); + return MPP_ERR_MALLOC; + } + + MPP_RET ret = api->init(ctx, cfg); + if (MPP_OK != ret) { + mpp_err_f("failed to init controller\n"); + mpp_free(p); + mpp_free(ctx); + return ret; + } + + p->api = api; + p->ctx = ctx; + memcpy(&p->cfg, cfg, sizeof(p->cfg)); + *impl = p; + return MPP_OK; + } + } + + return MPP_NOK; +} + +MPP_RET enc_impl_deinit(EncImpl impl) +{ + if (NULL == impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + EncImplCtx *p = (EncImplCtx *)impl; + if (p->api->deinit) + p->api->deinit(p->ctx); + + mpp_free(p->ctx); + mpp_free(p); + return MPP_OK; +} + +MPP_RET enc_impl_proc_cfg(EncImpl impl, MpiCmd cmd, void *para) +{ + if (NULL == impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + EncImplCtx *p = (EncImplCtx *)impl; + if (p->api->proc_cfg) + ret = p->api->proc_cfg(p->ctx, cmd, para); + + return ret; +} + +MPP_RET enc_impl_gen_hdr(EncImpl impl, MppPacket pkt) +{ + if (NULL == impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + EncImplCtx *p = (EncImplCtx *)impl; + + if (p->api->gen_hdr) { + if (pkt) + mpp_packet_reset_segment(pkt); + + ret = p->api->gen_hdr(p->ctx, pkt); + } + + return ret; +} + +MPP_RET enc_impl_start(EncImpl impl, HalEncTask *task) +{ + if (NULL == impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + EncImplCtx *p = (EncImplCtx *)impl; + if (p->api->start) + ret = p->api->start(p->ctx, task); + + return ret; +} + +MPP_RET enc_impl_proc_dpb(EncImpl impl, HalEncTask *task) +{ + if (NULL == impl) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + EncImplCtx *p = (EncImplCtx *)impl; + if (p->api->proc_dpb) + ret = p->api->proc_dpb(p->ctx, task); + + return ret; +} + +MPP_RET enc_impl_proc_hal(EncImpl impl, HalEncTask *task) +{ + if (NULL == impl || NULL == task) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + EncImplCtx *p = (EncImplCtx *)impl; + if (p->api->proc_hal) + ret = p->api->proc_hal(p->ctx, task); + + return ret; +} + +MPP_RET enc_impl_add_prefix(EncImpl impl, MppPacket pkt, RK_S32 *length, + RK_U8 uuid[16], const void *data, RK_S32 size) +{ + if (NULL == pkt || NULL == data) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + EncImplCtx *p = (EncImplCtx *)impl; + + if (NULL == p->api->add_prefix) + return ret; + + if (p->api->add_prefix) + ret = p->api->add_prefix(pkt, length, uuid, data, size); + + return ret; +} + +MPP_RET enc_impl_sw_enc(EncImpl impl, HalEncTask *task) +{ + if (NULL == impl || NULL == task) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + EncImplCtx *p = (EncImplCtx *)impl; + if (p->api->sw_enc) + ret = p->api->sw_enc(p->ctx, task); + + return ret; +} diff --git a/mpp/codec/inc/dummy_enc_api.h b/mpp/codec/inc/dummy_enc_api.h index e3e73b906..4f5303e58 100644 --- a/mpp/codec/inc/dummy_enc_api.h +++ b/mpp/codec/inc/dummy_enc_api.h @@ -1,31 +1,29 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __DUMMY_ENC_API_H__ -#define __DUMMY_ENC_API_H__ - -#include "mpp_enc.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /*__DUMMY_ENC_API_H__*/ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DUMMY_ENC_API_H +#define DUMMY_ENC_API_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* DUMMY_ENC_API_H */ diff --git a/mpp/codec/inc/enc_impl.h b/mpp/codec/inc/enc_impl.h new file mode 100644 index 000000000..2426e486d --- /dev/null +++ b/mpp/codec/inc/enc_impl.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ENC_IMPL_H +#define ENC_IMPL_H + +#include "enc_impl_api.h" + +typedef void* EncImpl; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET enc_impl_init(EncImpl *impl, EncImplCfg *cfg); +MPP_RET enc_impl_deinit(EncImpl impl); + +MPP_RET enc_impl_proc_cfg(EncImpl impl, MpiCmd cmd, void *para); +MPP_RET enc_impl_gen_hdr(EncImpl impl, MppPacket pkt); + +MPP_RET enc_impl_start(EncImpl impl, HalEncTask *task); +MPP_RET enc_impl_proc_dpb(EncImpl impl, HalEncTask *task); +MPP_RET enc_impl_proc_hal(EncImpl impl, HalEncTask *task); + +MPP_RET enc_impl_add_prefix(EncImpl impl, MppPacket pkt, RK_S32 *length, + RK_U8 uuid[16], const void *data, RK_S32 size); + +MPP_RET enc_impl_sw_enc(EncImpl impl, HalEncTask *task); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENC_IMPL_H */ diff --git a/mpp/codec/inc/enc_impl_api.h b/mpp/codec/inc/enc_impl_api.h new file mode 100644 index 000000000..b193c4c43 --- /dev/null +++ b/mpp/codec/inc/enc_impl_api.h @@ -0,0 +1,77 @@ +/* + * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ENC_IMPL_API_H +#define ENC_IMPL_API_H + +#include "rk_mpi_cmd.h" + +#include "hal_enc_task.h" +#include "mpp_enc_cfg.h" +#include "mpp_enc_refs.h" +#include "mpp_dev_defs.h" + +/* + * the reset wait for extension + */ +typedef struct EncImplCfg_t { + // input + MppCodingType coding; + MppClientType type; + MppEncCfgSet *cfg; + MppEncRefs refs; +} EncImplCfg; + +/* + * EncImplApi is the data structure provided from different encoders + * + * They will be static register to mpp_enc for scaning + * name - encoder name + * coding - encoder coding type + * ctx_size - encoder context size, mpp_dec will use this to malloc memory + * flag - reserve + * + * init - encoder initialization function + * deinit - encoder de-initialization function + * proc_cfg - encoder processs control function + * gen_hdr - encoder generate hearder function + * proc_dpb - encoder dpb process function (approach one frame) + * proc_hal - encoder prepare hal info function + * add_prefix - encoder generate user data / sei to packet as prefix + */ +typedef struct EncImplApi_t { + char *name; + MppCodingType coding; + RK_U32 ctx_size; + RK_U32 flag; + + MPP_RET (*init)(void *ctx, EncImplCfg *ctrlCfg); + MPP_RET (*deinit)(void *ctx); + + MPP_RET (*proc_cfg)(void *ctx, MpiCmd cmd, void *param); + MPP_RET (*gen_hdr)(void *ctx, MppPacket pkt); + + MPP_RET (*start)(void *ctx, HalEncTask *task); + MPP_RET (*proc_dpb)(void *ctx, HalEncTask *task); + MPP_RET (*proc_hal)(void *ctx, HalEncTask *task); + + MPP_RET (*add_prefix)(MppPacket pkt, RK_S32 *length, RK_U8 uuid[16], + const void *data, RK_S32 size); + + MPP_RET (*sw_enc)(void *ctx, HalEncTask *task); +} EncImplApi; + +#endif /* ENC_IMPL_API_H */ diff --git a/mpp/codec/inc/h264d_api.h b/mpp/codec/inc/h264d_api.h deleted file mode 100644 index 927a2fcb7..000000000 --- a/mpp/codec/inc/h264d_api.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __H264D_API_H__ -#define __H264D_API_H__ - -#include "parser_api.h" - - - -typedef enum mpp_decmtd_type { - MPP_DEC_NULL = 0, - MPP_DEC_BY_SLICE = 0x1, - MPP_DEC_BY_FRAME = 0x2, - MPP_DEC_MAX, -} MppDecMtd_type; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const ParserApi api_h264d_parser; - -MPP_RET h264d_init (void *decoder, ParserCfg *cfg); -MPP_RET h264d_deinit (void *decoder); -MPP_RET h264d_reset (void *decoder); -MPP_RET h264d_flush (void *decoder); -MPP_RET h264d_control(void *decoder, RK_S32 cmd_type, void *param); -MPP_RET h264d_parse (void *decoder, MppPacket pkt, HalDecTask *task); - -#ifdef __cplusplus -} -#endif - -#endif /*__H264D_API_H__*/ diff --git a/mpp/codec/inc/h264e_api_v2.h b/mpp/codec/inc/h264e_api_v2.h new file mode 100644 index 000000000..febc05e20 --- /dev/null +++ b/mpp/codec/inc/h264e_api_v2.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_API_V2_H +#define H264E_API_V2_H + +#include "enc_impl_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const EncImplApi api_h264e; + +#ifdef __cplusplus +} +#endif + +#endif /* H264E_API_V2_H */ diff --git a/mpp/test/mpp_info_test.c b/mpp/codec/inc/h265e_api.h similarity index 70% rename from mpp/test/mpp_info_test.c rename to mpp/codec/inc/h265e_api.h index 8e875b6da..28fb28d89 100644 --- a/mpp/test/mpp_info_test.c +++ b/mpp/codec/inc/h265e_api.h @@ -1,28 +1,32 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_info_test" - -#include "mpp_log.h" -#include "mpp_info.h" - -int main() -{ - mpp_log("mpp revision is %d\n", get_mpp_revision()); - - return 0; -} - +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_API_H +#define H265E_API_H + +#include "enc_impl_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const EncImplApi api_h265e; + +#ifdef __cplusplus +} +#endif + +#endif /* H265E_API_H */ diff --git a/mpp/codec/inc/jpege_api_v2.h b/mpp/codec/inc/jpege_api_v2.h new file mode 100644 index 000000000..1e6fbf204 --- /dev/null +++ b/mpp/codec/inc/jpege_api_v2.h @@ -0,0 +1,31 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef JPEGE_API_V2_H +#define JPEGE_API_V2_H + +#include "enc_impl_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const EncImplApi api_jpege; + +#ifdef __cplusplus +} +#endif + +#endif /* JPEGE_API_V2_H */ diff --git a/mpp/codec/inc/mpp_dec.h b/mpp/codec/inc/mpp_dec.h index 81f780614..f264bb065 100644 --- a/mpp/codec/inc/mpp_dec.h +++ b/mpp/codec/inc/mpp_dec.h @@ -1,63 +1,73 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_DEC_H__ -#define __MPP_DEC_H__ - -#include "rk_mpi.h" -#include "mpp_parser.h" -#include "mpp_hal.h" - - -typedef struct MppDec_t MppDec; - -struct MppDec_t { - MppCodingType coding; - - Parser parser; - MppHal hal; - - // common resource - MppBufSlots slots; - HalTaskGroup tasks; -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * main thread for all decoder. This thread will connect parser / hal / mpp - */ -void *mpp_dec_parser_thread(void *data); -void *mpp_dec_hal_thread(void *data); - -/* - * - */ -MPP_RET mpp_dec_init(MppDec **dec, MppCodingType coding); -MPP_RET mpp_dec_deinit(MppDec *dec); - -MPP_RET mpp_dec_reset(MppDec *dec); -MPP_RET mpp_dec_flush(MppDec *dec); -MPP_RET mpp_dec_control(MppDec *dec, RK_S32 cmd, void *para); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_DEC_H__*/ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_DEC_H +#define MPP_DEC_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "rk_mpi_cmd.h" +#include "mpp_dec_cfg.h" + +typedef enum MppDecEvent_e { + MPP_DEC_EVENT_ON_PKT_RELEASE, + MPP_DEC_EVENT_ON_FRM_READY, + + MPP_DEC_EVENT_BUTT, +} MppDecEvent; + +typedef void* MppDec; + +typedef struct { + MppCodingType coding; + void *mpp; + + MppDecCfg cfg; +} MppDecInitCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_dec_init(MppDec *ctx, MppDecInitCfg *cfg); +MPP_RET mpp_dec_deinit(MppDec ctx); + +MPP_RET mpp_dec_start(MppDec ctx); +MPP_RET mpp_dec_stop(MppDec ctx); + +MPP_RET mpp_dec_reset(MppDec ctx); +MPP_RET mpp_dec_flush(MppDec ctx); +MPP_RET mpp_dec_control(MppDec ctx, MpiCmd cmd, void *param); +MPP_RET mpp_dec_notify(MppDec ctx, RK_U32 flag); +MPP_RET mpp_dec_callback(MppDec ctx, MppDecEvent event, void *arg); + +/* update init cfg before init */ +MPP_RET mpp_dec_set_cfg_by_cmd(MppDecCfg cfg, MpiCmd cmd, void *param); + +/* + * return positive value for the number of decoded frame + * return zero for decoding success but no frame decoded + * return negtive value for decoding flow failed + */ +MPP_RET mpp_dec_decode(MppDec ctx, MppPacket packet); + +MppDecCfg mpp_dec_to_cfg(MppDec ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEC_H */ diff --git a/mpp/codec/inc/mpp_dec_impl.h b/mpp/codec/inc/mpp_dec_impl.h new file mode 100644 index 000000000..8feab3b11 --- /dev/null +++ b/mpp/codec/inc/mpp_dec_impl.h @@ -0,0 +1,250 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_DEC_IMPL_H +#define MPP_DEC_IMPL_H + +#include "mpp_time.h" +#include "mpp_mem_pool.h" +#include "mpp_lock.h" +#include "hal_info.h" + +#include "mpp.h" +#include "mpp_dec_cfg.h" +#include "mpp_callback.h" + +#include "mpp_parser.h" +#include "mpp_hal.h" + +// for timing record +typedef enum MppDecTimingType_e { + DEC_PRS_TOTAL, + DEC_PRS_WAIT, + DEC_PRS_PROC, + DEC_PRS_PREPARE, + DEC_PRS_PARSE, + DEC_HAL_GEN_REG, + DEC_HW_START, + + DEC_HAL_TOTAL, + DEC_HAL_WAIT, + DEC_HAL_PROC, + DEC_HW_WAIT, + DEC_TIMING_BUTT, +} MppDecTimingType; + + +typedef enum MppDecMode_e { + MPP_DEC_MODE_DEFAULT, + MPP_DEC_MODE_NO_THREAD, + + MPP_DEC_MODE_BUTT, +} MppDecMode; + +typedef struct MppDecImpl_t MppDecImpl; + +typedef struct MppDecModeApi_t { + MPP_RET (*start)(MppDecImpl *dec); + MPP_RET (*stop)(MppDecImpl *dec); + MPP_RET (*reset)(MppDecImpl *dec); + MPP_RET (*notify)(MppDecImpl *dec, RK_U32 flag); + MPP_RET (*control)(MppDecImpl *dec, MpiCmd cmd, void *param); +} MppDecModeApi; + +struct MppDecImpl_t { + MppCodingType coding; + + MppDecMode mode; + MppDecModeApi *api; + + Parser parser; + MppHal hal; + + // worker thread + MppThread *thread_parser; + MppThread *thread_hal; + + // common resource + MppBufSlots frame_slots; + MppBufSlots packet_slots; + MppCbCtx dec_cb; + const MppDecHwCap *hw_info; + MppDev dev; + HalInfo hal_info; + RK_U32 info_updated; + + HalTaskGroup tasks; + HalTaskGroup vproc_tasks; + + // runtime configure set + MppDecCfg cfg_obj; + MppDecCfgSet *cfg; + + /* control process */ + MppMutexCond cmd_lock; + RK_U32 cmd_send; + RK_U32 cmd_recv; + MpiCmd cmd; + void *param; + MPP_RET *cmd_ret; + sem_t cmd_start; + sem_t cmd_done; + + // status flags + RK_U32 parser_work_count; + RK_U32 parser_wait_count; + RK_U32 parser_status_flag; + RK_U32 parser_wait_flag; + RK_U32 parser_notify_flag; + RK_U32 hal_notify_flag; + + // reset process: + // 1. mpp_dec set reset flag and signal parser + // 2. mpp_dec wait on parser_reset sem + // 3. parser wait hal reset done + // 4. hal wait vproc reset done + // 5. vproc do reset and signal hal + // 6. hal do reset and signal parser + // 7. parser do reset and signal mpp_dec + // 8. mpp_dec reset done + RK_U32 reset_flag; + + RK_U32 hal_reset_post; + RK_U32 hal_reset_done; + sem_t parser_reset; + sem_t hal_reset; + + // work mode flags + RK_U32 parser_fast_mode; + RK_U32 disable_error; + RK_U32 dis_err_clr_mark; + RK_U32 enable_deinterlace; + + // dec parser thread runtime resource context + MppPacket mpp_pkt_in; + void *mpp; + void *vproc; + + // statistics data + RK_U32 statistics_en; + MppClock clocks[DEC_TIMING_BUTT]; + + // query data + RK_U32 dec_in_pkt_count; + RK_U32 dec_hw_run_count; + RK_U32 dec_out_frame_count; + + MppMemPool ts_pool; + struct list_head ts_link; + spinlock_t ts_lock; + void *task_single; +}; + +/* external wait state */ +#define MPP_DEC_WAIT_PKT_IN (0x00000001) /* input packet not ready */ +#define MPP_DEC_WAIT_FRM_OUT (0x00000002) /* frame output queue full */ + +#define MPP_DEC_WAIT_INFO_CHG (0x00000020) /* wait info change ready */ +#define MPP_DEC_WAIT_BUF_RDY (0x00000040) /* wait valid frame buffer */ +#define MPP_DEC_WAIT_TSK_ALL_DONE (0x00000080) /* wait all task done */ + +#define MPP_DEC_WAIT_TSK_HND_RDY (0x00000100) /* wait task handle ready */ +#define MPP_DEC_WAIT_TSK_PREV_DONE (0x00000200) /* wait previous task done */ +#define MPP_DEC_WAIT_BUF_GRP_RDY (0x00000200) /* wait buffer group change ready */ + +/* internal wait state */ +#define MPP_DEC_WAIT_BUF_SLOT_RDY (0x00001000) /* wait buffer slot ready */ +#define MPP_DEC_WAIT_PKT_BUF_RDY (0x00002000) /* wait packet buffer ready */ +#define MPP_DEC_WAIT_BUF_SLOT_KEEP (0x00004000) /* wait buffer slot reservation */ + +typedef union PaserTaskWait_u { + RK_U32 val; + struct { + RK_U32 dec_pkt_in : 1; // 0x0001 MPP_DEC_NOTIFY_PACKET_ENQUEUE + RK_U32 dis_que_full : 1; // 0x0002 MPP_DEC_NOTIFY_FRAME_DEQUEUE + RK_U32 reserv0004 : 1; // 0x0004 + RK_U32 reserv0008 : 1; // 0x0008 + + RK_U32 ext_buf_grp : 1; // 0x0010 MPP_DEC_NOTIFY_EXT_BUF_GRP_READY + RK_U32 info_change : 1; // 0x0020 MPP_DEC_NOTIFY_INFO_CHG_DONE + RK_U32 dec_pic_unusd : 1; // 0x0040 MPP_DEC_NOTIFY_BUFFER_VALID + RK_U32 dec_all_done : 1; // 0x0080 MPP_DEC_NOTIFY_TASK_ALL_DONE + + RK_U32 task_hnd : 1; // 0x0100 MPP_DEC_NOTIFY_TASK_HND_VALID + RK_U32 prev_task : 1; // 0x0200 MPP_DEC_NOTIFY_TASK_PREV_DONE + RK_U32 dec_pic_match : 1; // 0x0400 MPP_DEC_NOTIFY_BUFFER_MATCH + RK_U32 reserv0800 : 1; // 0x0800 + + RK_U32 dec_pkt_idx : 1; // 0x1000 + RK_U32 dec_pkt_buf : 1; // 0x2000 + RK_U32 dec_slot_idx : 1; // 0x4000 MPP_DEC_NOTIFY_SLOT_VALID + }; +} PaserTaskWait; + +typedef union DecTaskStatus_u { + RK_U32 val; + struct { + RK_U32 task_hnd_rdy : 1; + RK_U32 mpp_pkt_in_rdy : 1; + RK_U32 dec_pkt_idx_rdy : 1; + RK_U32 dec_pkt_buf_rdy : 1; + RK_U32 task_valid_rdy : 1; + RK_U32 dec_pkt_copy_rdy : 1; + RK_U32 prev_task_rdy : 1; + RK_U32 info_task_gen_rdy : 1; + RK_U32 curr_task_rdy : 1; + RK_U32 task_parsed_rdy : 1; + RK_U32 mpp_in_frm_at_pkt : 1; + }; +} DecTaskStatus; + +typedef struct MppPktTimestamp_t { + struct list_head link; + RK_S64 pts; + RK_S64 dts; +} MppPktTs; + +typedef struct DecTask_t { + HalTaskHnd hnd; + + DecTaskStatus status; + PaserTaskWait wait; + + HalTaskInfo info; + MppPktTs ts_cur; + + MppBuffer hal_pkt_buf_in; + MppBuffer hal_frm_buf_out; +} DecTask; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET dec_task_info_init(HalTaskInfo *task); +void dec_task_init(DecTask *task); + +MPP_RET mpp_dec_proc_cfg(MppDecImpl *dec, MpiCmd cmd, void *param); + +MPP_RET update_dec_hal_info(MppDecImpl *dec, MppFrame frame); +void mpp_dec_put_frame(Mpp *mpp, RK_S32 index, HalDecTaskFlag flags); +RK_S32 mpp_dec_push_display(Mpp *mpp, HalDecTaskFlag flags); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEC_IMPL_H */ diff --git a/mpp/codec/inc/mpp_dec_no_thread.h b/mpp/codec/inc/mpp_dec_no_thread.h new file mode 100644 index 000000000..df6f2f4aa --- /dev/null +++ b/mpp/codec/inc/mpp_dec_no_thread.h @@ -0,0 +1,32 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_DEC_NO_THREAD_H +#define MPP_DEC_NO_THREAD_H + +#include "mpp_dec_impl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern MppDecModeApi dec_api_no_thread; + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEC_NO_THREAD_H */ diff --git a/mpp/codec/inc/mpp_dec_normal.h b/mpp/codec/inc/mpp_dec_normal.h new file mode 100644 index 000000000..1672b3d9f --- /dev/null +++ b/mpp/codec/inc/mpp_dec_normal.h @@ -0,0 +1,32 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_DEC_NORMAL_H +#define MPP_DEC_NORMAL_H + +#include "mpp_dec_impl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern MppDecModeApi dec_api_normal; + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEC_NORMAL_H */ diff --git a/mpp/codec/inc/mpp_enc.h b/mpp/codec/inc/mpp_enc.h index 1b7eb1447..740ff4a7d 100644 --- a/mpp/codec/inc/mpp_enc.h +++ b/mpp/codec/inc/mpp_enc.h @@ -1,36 +1,181 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_ENC_H__ -#define __MPP_ENC_H__ - -#include "rk_type.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * main thread for all encoder. This thread will connect encoder / hal / mpp - */ -void *mpp_enc_control_thread(void *data); -void *mpp_enc_hal_thread(void *data); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_ENC_H__*/ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_ENC_H +#define MPP_ENC_H + +#include "rk_type.h" +#include "mpp_err.h" +#include "rk_mpi_cmd.h" + +/* + * Configure of encoder is separated into four parts. + * + * 1. Rate control parameter + * This is quality and bitrate request from user. + * For controller only + * + * 2. Data source MppFrame parameter + * This is data source buffer information. + * For both controller and hal + * + * 3. Video codec infomation + * This is user custormized stream information. + * For hal only + * + * 4. Extra parameter + * including: + * PreP : encoder Preprocess configuration + * ROI : Region Of Interest + * OSD : On Screen Display + * MD : Motion Detection + * extra : SEI for h.264 / Exif for mjpeg + * For hal only + * + * The module transcation flow is as follows: + * + * + + + * User | Mpi/Mpp | EncImpl + * | | Hal + * | | + * +----------+ | +---------+ | +------------+ + * | | | | +-----RcCfg-----> | + * | RcCfg +---------> | | | EncImpl | + * | | | | | +-Frame-----> | + * +----------+ | | | | | +---+-----^--+ + * | | | | | | | + * | | | | | | | + * +----------+ | | | | | syntax | + * | | | | | | | | | + * | MppFrame +---------> MppEnc +---+ | | result + * | | | | | | | | | + * +----------+ | | | | | | | + * | | | | | +---v-----+--+ + * | | | +-Frame-----> | + * +----------+ | | | | | | + * | | | | +---CodecCfg----> Hal | + * | CodecCfg +---------> | | | | + * | | | | <-----Extra-----> | + * +----------+ | +---------+ | +------------+ + * | | + * | | + * + + + * + * The function call flow is shown below: + * + * mpi mpp_enc controller hal + * + + + + + * | | | | + * | | | | + * +----------init------------> | | + * | | | | + * | | | | + * | PrepCfg | | | + * +---------control----------> PrepCfg | | + * | +-----control-----> | + * | | | PrepCfg | + * | +--------------------------control--------> + * | | | allocate + * | | | buffer + * | | | | + * | RcCfg | | | + * +---------control----------> RcCfg | | + * | +-----control-----> | + * | | rc_init | + * | | | | + * | | | | + * | CodecCfg | | | + * +---------control----------> | CodecCfg | + * | +--------------------------control--------> + * | | | generate + * | | | sps/pps + * | | | Get extra info | + * | +--------------------------control--------> + * | Get extra info | | | + * +---------control----------> | | + * | | | | + * | | | | + * | ROICfg | | | + * +---------control----------> | ROICfg | + * | +--------------------------control--------> + * | | | | + * | OSDCfg | | | + * +---------control----------> | OSDCfg | + * | +--------------------------control--------> + * | | | | + * | MDCfg | | | + * +---------control----------> | MDCfg | + * | +--------------------------control--------> + * | | | | + * | Set extra info | | | + * +---------control----------> | Set extra info | + * | +--------------------------control--------> + * | | | | + * | task | | | + * +----------encode----------> task | | + * | +-----encode------> | + * | | encode | + * | | | syntax | + * | +--------------------------gen_reg--------> + * | | | | + * | | | | + * | +---------------------------start---------> + * | | | | + * | | | | + * | +---------------------------wait----------> + * | | | | + * | | callback | | + * | +-----------------> | + * +--OSD-MD--encode----------> | | + * | . | | | + * | . | | | + * | . | | | + * +--OSD-MD--encode----------> | | + * | | | | + * +----------deinit----------> | | + * + + + + + */ + +typedef void* MppEnc; + +typedef struct MppEncInitCfg_t { + MppCodingType coding; + RK_S32 task_cnt; + void *mpp; +} MppEncInitCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_enc_init_v2(MppEnc *ctx, MppEncInitCfg *cfg); +MPP_RET mpp_enc_deinit_v2(MppEnc ctx); + +MPP_RET mpp_enc_start_v2(MppEnc ctx); +MPP_RET mpp_enc_start_async(MppEnc ctx); +MPP_RET mpp_enc_stop_v2(MppEnc ctx); + +MPP_RET mpp_enc_control_v2(MppEnc ctx, MpiCmd cmd, void *param); +MPP_RET mpp_enc_notify_v2(MppEnc ctx, RK_U32 flag); +MPP_RET mpp_enc_reset_v2(MppEnc ctx); + +MppEncCfg mpp_enc_to_cfg(MppEnc ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENC_H */ diff --git a/mpp/codec/inc/mpp_enc_impl.h b/mpp/codec/inc/mpp_enc_impl.h new file mode 100644 index 000000000..77c63351a --- /dev/null +++ b/mpp/codec/inc/mpp_enc_impl.h @@ -0,0 +1,169 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_ENC_IMPL_H +#define MPP_ENC_IMPL_H + +#include "enc_impl.h" +#include "mpp_enc_hal.h" +#include "mpp_enc_ref.h" +#include "mpp_enc_refs.h" +#include "mpp_device.h" +#include "mpp_task_impl.h" + +#include "rc.h" +#include "hal_info.h" + +#define HDR_ADDED_MASK 0xe + +typedef struct MppPskipMode_t { + RK_S32 pskip_is_ref; + RK_S32 pskip_is_non_ref; +} MppPskipMode; + +typedef union MppEncHeaderStatus_u { + RK_U32 val; + struct { + RK_U32 ready : 1; + + RK_U32 added_by_ctrl : 1; + RK_U32 added_by_mode : 1; + RK_U32 added_by_change : 1; + }; +} MppEncHeaderStatus; + +typedef struct RcApiStatus_t { + RK_U32 rc_api_inited : 1; + RK_U32 rc_api_updated : 1; + RK_U32 rc_api_user_cfg : 1; +} RcApiStatus; + +typedef struct MppEncImpl_t { + MppCodingType coding; + EncImpl impl; + MppEncHal enc_hal; + + /* device from hal */ + MppDev dev; + HalInfo hal_info; + RK_S64 time_base; + RK_S64 time_end; + RK_S32 frame_count; + RK_S32 hal_info_updated; + + /* + * Rate control plugin parameters + */ + RcApiStatus rc_status; + RK_S32 rc_api_updated; + RK_S32 rc_cfg_updated; + RcApiBrief rc_brief; + RcCtx rc_ctx; + + /* + * thread input / output context + */ + MppThread *thread_enc; + void *mpp; + + MppPort input; + MppPort output; + MppTask task_in; + MppTask task_out; + MppFrame frame; + MppPacket packet; + RK_U32 low_delay_part_mode; + RK_U32 low_delay_output; + /* output callback for slice output */ + MppCbCtx output_cb; + + /* base task information */ + HalTaskGroup tasks; + HalTaskHnd hnd; + EncAsyncTaskInfo *async; + RK_U32 task_idx; + RK_S64 task_pts; + MppBuffer frm_buf; + MppBuffer pkt_buf; + MppBuffer md_info; + + // internal status and protection + MppMutex lock; + RK_U32 reset_flag; + sem_t enc_reset; + + RK_U32 wait_count; + RK_U32 work_count; + RK_U32 status_flag; + RK_U32 notify_flag; + RK_U32 enc_failed_drop; + + /* control process */ + RK_U32 cmd_send; + RK_U32 cmd_recv; + MpiCmd cmd; + void *param; + MPP_RET *cmd_ret; + sem_t cmd_start; + sem_t cmd_done; + + // legacy support for MPP_ENC_GET_EXTRA_INFO + MppPacket hdr_pkt; + void *hdr_buf; + RK_U32 hdr_len; + MppEncHeaderStatus hdr_status; + MppEncHeaderMode hdr_mode; + MppEncSeiMode sei_mode; + + /* information for debug prefix */ + const char *version_info; + RK_S32 version_length; + char *rc_cfg_info; + RK_S32 rc_cfg_pos; + RK_S32 rc_cfg_length; + RK_S32 rc_cfg_size; + + /* cpb parameters */ + MppEncRefs refs; + MppEncRefFrmUsrCfg frm_cfg; + + /* two-pass deflicker parameters */ + RK_U32 support_hw_deflicker; + EncRcTaskInfo rc_info_prev; + + /* encoder config object for external setup */ + MppEncCfg set_obj; + MppEncCfgSet *set; + /* encoder config object for internal usage */ + MppEncCfg cfg_obj; + MppEncCfgSet *cfg; +} MppEncImpl; + +extern RK_U8 uuid_refresh_cfg[16]; + +#ifdef __cplusplus +extern "C" { +#endif + +void *mpp_enc_thread(void *data); +void *mpp_enc_async_thread(void *data); +MPP_RET mpp_enc_callback(const char *caller, void *ctx, RK_S32 cmd, void *param); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENC_IMPL_H */ diff --git a/mpp/codec/inc/mpp_parser.h b/mpp/codec/inc/mpp_parser.h index cb802c64e..726dae975 100644 --- a/mpp/codec/inc/mpp_parser.h +++ b/mpp/codec/inc/mpp_parser.h @@ -1,41 +1,44 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_PARSER_H__ -#define __MPP_PARSER_H__ - -#include "parser_api.h" - -typedef void* Parser; - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET parser_init(Parser *prs, ParserCfg *cfg); -MPP_RET parser_deinit(Parser prs); - -MPP_RET parser_parse(Parser prs, MppPacket pkt, HalDecTask *task); - -MPP_RET parser_reset(Parser prs); -MPP_RET parser_flush(Parser prs); -MPP_RET parser_control(Parser prs, RK_S32 cmd, void *para); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_PARSER_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_PARSER_H +#define MPP_PARSER_H + +#include "mpp_singleton.h" + +#include "parser_api.h" + +typedef void* Parser; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_parser_init(Parser *prs, ParserCfg *cfg); +MPP_RET mpp_parser_deinit(Parser prs); + +MPP_RET mpp_parser_prepare(Parser prs, MppPacket pkt, HalDecTask *task); +MPP_RET mpp_parser_parse(Parser prs, HalDecTask *task); + +MPP_RET mpp_parser_reset(Parser prs); +MPP_RET mpp_parser_flush(Parser prs); +MPP_RET mpp_parser_control(Parser prs, MpiCmd cmd, void *para); +MPP_RET mpp_parser_callback(void* prs, void *err_info); +MPP_RET mpp_parser_sync(Parser prs, RK_S32 frame_id); + +MPP_RET mpp_parser_api_register(const ParserApi *api); + +#define MPP_PARSER_API_REGISTER(api) \ + static void mpp_parser_api_register_##api##_wrapper(void) \ + { \ + mpp_parser_api_register(&api); \ + } \ + MPP_MODULE_ADD(api, mpp_parser_api_register_##api##_wrapper, NULL); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_PARSER_H */ diff --git a/mpp/codec/inc/mpp_rc.h b/mpp/codec/inc/mpp_rc.h new file mode 100644 index 000000000..b834c32c3 --- /dev/null +++ b/mpp/codec/inc/mpp_rc.h @@ -0,0 +1,138 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_RC_H +#define MPP_RC_H + +#include "rk_venc_cmd.h" + +#include "mpp_list.h" + +/* + * mpp rate control contain common caculation methd + * + * 1. MppData - data statistic struct + * size - max valid data number + * len - valid data number + * pos - current load/store position + * val - buffer array pointer + */ +typedef struct { + RK_S32 size; + RK_S32 len; + RK_S32 pos; + RK_S32 *val; +} MppData; + +/* + * 2. Proportion Integration Differentiation (PID) control + */ +typedef struct { + RK_S32 p; + RK_S32 i; + RK_S32 d; + RK_S32 coef_p; + RK_S32 coef_i; + RK_S32 coef_d; + RK_S32 div; + RK_S32 len; + RK_S32 count; +} MppPIDCtx; + +/* + * MppRateControl has three steps work: + * + * 1. translate user requirement to bit rate parameters + * 2. calculate target bit from bit parameters + * 3. calculate qstep from target bit + * + * That is user setting -> target bit -> qstep. + * + * This struct will be used in both controller and hal. + * EncImpl provide step 1 and step 2. Hal provide step 3. + * + */ +typedef enum MppEncGopMode_e { + /* gop == 0 */ + MPP_GOP_ALL_INTER, + /* gop == 1 */ + MPP_GOP_ALL_INTRA, + /* gop < fps */ + MPP_GOP_SMALL, + /* gop >= fps */ + MPP_GOP_LARGE, + MPP_GOP_MODE_BUTT, +} MppEncGopMode; + +typedef enum RC_PARAM_OPS { + RC_RECORD_REAL_BITS, + RC_RECORD_QP_SUM, + RC_RECORD_QP_MIN, + RC_RECORD_QP_MAX, + RC_RECORD_SET_QP, + RC_RECORD_REAL_QP, + RC_RECORD_SSE_SUM, + RC_RECORD_WIN_LEN +} RC_PARAM_OPS; + +typedef struct RecordNode_t { + struct list_head list; + /* @frm_cnt starts from ONE */ + RK_U32 frm_cnt; + RK_U32 bps; + RK_U32 fps; + RK_S32 gop; + RK_S32 bits_per_pic; + RK_S32 bits_per_intra; + RK_S32 bits_per_inter; + RK_U32 tgt_bits; + RK_U32 bit_min; + RK_U32 bit_max; + RK_U32 real_bits; + RK_S32 acc_intra_bits_in_fps; + RK_S32 acc_inter_bits_in_fps; + RK_S32 last_fps_bits; + float last_intra_percent; + + /* hardware result */ + RK_S32 qp_sum; + RK_S64 sse_sum; + RK_S32 set_qp; + RK_S32 qp_min; + RK_S32 qp_max; + RK_S32 real_qp; + RK_S32 wlen; +} RecordNode; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_data_init(MppData **p, RK_S32 len); +void mpp_data_deinit(MppData *p); +void mpp_data_update(MppData *p, RK_S32 val); +RK_S32 mpp_data_avg(MppData *p, RK_S32 len, RK_S32 num, RK_S32 denom); + +void mpp_pid_reset(MppPIDCtx *p); +void mpp_pid_set_param(MppPIDCtx *p, RK_S32 coef_p, RK_S32 coef_i, RK_S32 coef_d, RK_S32 div_val, RK_S32 len); +void mpp_pid_update(MppPIDCtx *p, RK_S32 val, RK_S32 is_reset); +RK_S32 mpp_pid_calc(MppPIDCtx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_RC_H */ diff --git a/mpp/codec/inc/parser_api.h b/mpp/codec/inc/parser_api.h index 9aafa3801..bc939f7d1 100644 --- a/mpp/codec/inc/parser_api.h +++ b/mpp/codec/inc/parser_api.h @@ -1,75 +1,78 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __PARSER_API_H__ -#define __PARSER_API_H__ - -#include "rk_mpi.h" -#include "mpp_packet.h" -#include "mpp_buf_slot.h" -#include "hal_task.h" - -/* - * slots - all decoder need a slots interface to sync its internal dpb management - * with buffer group in mpp_dec - * - * the reset wait for extension - */ -typedef struct DecParserInitCfg_t { - // input - MppCodingType coding; - MppBufSlots slots; - - // output - RK_U32 task_count; -} ParserCfg; - - -/* - * Parser is the data structure provided from different decoders - * - * They will be static register to mpp_dec for scaning - * name - decoder name - * coding - decoder coding type - * ctx_size - decoder context size, mpp_dec will use this to malloc memory - * flag - reserve - * - * init - decoder initialization function - * deinit - decoder de-initialization function - * parse - decoder main working function, mpp_dec will input packet and get output syntax - * reset - decoder reset function - * flush - decoder output all frames - * control - decoder configure function - */ -typedef struct ParserApi_t { - char *name; - MppCodingType coding; - RK_U32 ctx_size; - RK_U32 flag; - - MPP_RET (*init)(void *ctx, ParserCfg *cfg); - MPP_RET (*deinit)(void *ctx); - - MPP_RET (*prepare)(void *ctx, MppPacket pkt); - MPP_RET (*parse)(void *ctx, MppPacket pkt, HalDecTask *task); - - MPP_RET (*reset)(void *ctx); - MPP_RET (*flush)(void *ctx); - MPP_RET (*control)(void *ctx, RK_S32 cmd, void *param); -} ParserApi; - - -#endif /*__PARSER_API_H__*/ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PARSER_API_H +#define PARSER_API_H + +#include "rk_mpi_cmd.h" +#include "mpp_packet.h" +#include "mpp_buf_slot.h" +#include "mpp_dec_cfg.h" +#include "hal_dec_task.h" +#include "mpp_soc.h" + +/* + * slots - all decoder need a slots interface to sync its internal dpb management + * with buffer group in mpp_dec + * + * the reset wait for extension + */ +typedef struct DecParserInitCfg_t { + MppCodingType coding; + MppBufSlots frame_slots; + MppBufSlots packet_slots; + MppDecCfgSet *cfg; + const MppDecHwCap *hw_info; +} ParserCfg; + + +/* + * Parser is the data structure provided from different decoders + * + * They will be static register to mpp_dec for scaning + * name - decoder name + * coding - decoder coding type + * ctx_size - decoder context size, mpp_dec will use this to malloc memory + * flag - reserve + * + * init - decoder initialization function + * deinit - decoder de-initialization function + * parse - decoder main working function, mpp_dec will input packet and get output syntax + * reset - decoder reset function + * flush - decoder output all frames + * control - decoder configure function + */ +typedef struct ParserApi_t { + char *name; + MppCodingType coding; + RK_U32 ctx_size; + RK_U32 flag; + + MPP_RET (*init)(void *ctx, ParserCfg *cfg); + MPP_RET (*deinit)(void *ctx); + + MPP_RET (*prepare)(void *ctx, MppPacket pkt, HalDecTask *task); + MPP_RET (*parse)(void *ctx, HalDecTask *task); + + MPP_RET (*reset)(void *ctx); + MPP_RET (*flush)(void *ctx); + MPP_RET (*control)(void *ctx, MpiCmd cmd, void *param); + MPP_RET (*callback)(void *ctx, void *err_info); + MPP_RET (*sync)(void *ctx, RK_S32 frame_id); +} ParserApi; + + +#endif /* PARSER_API_H */ diff --git a/mpp/codec/inc/rc.h b/mpp/codec/inc/rc.h new file mode 100644 index 000000000..5c582438e --- /dev/null +++ b/mpp/codec/inc/rc.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#ifndef RC_H +#define RC_H + +#include "mpp_err.h" + +#include "mpp_rc_api.h" + +/* + * Mpp rate control principle + * + * 1. Rate control information is composed by these parts: + * a. configuration from mpp user. + * b. frame level target bitrate calculated by different RC model. + * c. block level hardware related configuration to hardware. + * d. statistic information from hardware after one frame is encoded. + * + * 2. All the above informatioin is storaged and managed by RcDataCtx in mpp + * framework. All these information is shared in encoder and hal module. + * + * 3. User (no matter developer or end user) defined rate control should based + * on these Rate control information and implement its own rate control + * strategy module by providing their own RcImplApi. + */ + +/* + * Relation between mpp_enc / enc_impl / hal / RcApi / RcImplApi / RcData + * + * +-----------+ + * | mpp_enc | + * +-----+-----+ + * | + * +-----+-----+ +-----------+ +-----------+ + * | enc_impl +---> RcApi +---> RcImplApi | + * +-----+-----+ +-----+-----+ +-----+-----+ + * | \ / | | + * | + | | + * | / \ | | + * +-----v-----+ +-----v-----+ | + * | hal +---> RcData <---------+ + * +-----------+ +-----------+ + */ + +typedef void* RcCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET rc_init(RcCtx *ctx, MppCodingType type, const char **request_name); +MPP_RET rc_deinit(RcCtx ctx); + +/* update rc control */ +MPP_RET rc_update_usr_cfg(RcCtx ctx, RcCfg *cfg); + +/* Frame rate convertion */ +MPP_RET rc_frm_check_drop(RcCtx ctx, EncRcTask *task); +/* Frame reenc check */ +MPP_RET rc_check_reenc(RcCtx ctx, EncRcTask *task); + +/* Frame level rate and quality control */ +MPP_RET rc_frm_start(RcCtx ctx, EncRcTask *task); +MPP_RET rc_frm_end(RcCtx ctx, EncRcTask *task); + +MPP_RET rc_hal_start(RcCtx ctx, EncRcTask *task); +MPP_RET rc_hal_end(RcCtx ctx, EncRcTask *task); + +#ifdef __cplusplus +} +#endif + +#endif /* RC_H */ diff --git a/mpp/codec/inc/rc/rc_vepu.h b/mpp/codec/inc/rc/rc_vepu.h new file mode 100644 index 000000000..97f421255 --- /dev/null +++ b/mpp/codec/inc/rc/rc_vepu.h @@ -0,0 +1,62 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RC_VEPU_H +#define RC_VEPU_H + +#include "rk_type.h" + +#define VEPU_BLK_RC_CTRL_LEVELS 7 +#define VEPU_BLK_RC_CHECK_POINTS_MAX 10 + +typedef struct RcVepuSet_t { + RK_S32 qp_init; + RK_S32 qp_min; + RK_S32 qp_max; + + RK_S32 mad_qp_delta; + RK_S32 mad_threshold; + + /* + * cp = checkpoint + * + * vepu1 and vepu2 use check point to control qp change accoring to runtime + * bit rate change in one frame. + * + * cp_distance_mbs defines how many the mb number between two checkpoints + * + * cp_target define the target bitrate on each checkpoint + * + * target_error and delta_qp define the qp delta value on the checkpoint when + * the bitrate error different to cp_target is happened. + */ + RK_S32 cp_distance_mbs; + RK_S32 cp_target[VEPU_BLK_RC_CHECK_POINTS_MAX]; + RK_S32 target_error[VEPU_BLK_RC_CTRL_LEVELS]; + RK_S32 delta_qp[VEPU_BLK_RC_CTRL_LEVELS]; +} RcVepuSet; + +typedef struct RcVepuRet_t { + RK_S32 stream_size; + + RK_S32 qp_sum; + RK_S32 mad_count; + RK_S32 rlc_count; + + RK_S32 cp_bits[VEPU_BLK_RC_CHECK_POINTS_MAX]; +} RcVepuRet; + +#endif /* RC_VEPU_H */ diff --git a/mpp/codec/inc/rc/rc_vepu540.h b/mpp/codec/inc/rc/rc_vepu540.h new file mode 100644 index 000000000..53d9adecc --- /dev/null +++ b/mpp/codec/inc/rc/rc_vepu540.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RC_VEPU_540_H +#define RC_VEPU_540_H + +#include "rk_type.h" + +#define VEPU540_BLK_RC_CTRL_LEVELS 9 + +typedef struct RcVepu540Set_t { + RK_S32 rc_en; + RK_S32 rc_mode; + + RK_S32 ctu_num; + RK_S32 ctu_ebits; + + RK_S32 qp_pic; + RK_S32 qp_min; + RK_S32 qp_max; + RK_S32 qp_range; + + RK_S32 aqmode_en; + RK_S32 aq_strength; + RK_S32 rc_fact0; + RK_S32 rc_fact1; + + RK_S32 target_error[VEPU_BLK_RC_CTRL_LEVELS]; + RK_S32 delta_qp[VEPU_BLK_RC_CTRL_LEVELS]; +} RcVepu540Set; + +typedef struct RcVepu540Ret_t { + RK_S32 stream_size; + + RK_U32 qp_sum; + RK_U64 sse_sum; +} RcVepu540Ret; + +#endif /* RC_VEPU_540_H */ diff --git a/mpp/codec/inc/rc_hal.h b/mpp/codec/inc/rc_hal.h new file mode 100644 index 000000000..b05e21689 --- /dev/null +++ b/mpp/codec/inc/rc_hal.h @@ -0,0 +1,49 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RC_HAL_H +#define RC_HAL_H + +#include "mpp_platform.h" + +#include "rc/rc_vepu.h" +#include "rc/rc_vepu540.h" + +/* parameters to set to hardware */ +typedef struct RcHalSet_t { + /* unique sequential id */ + RK_S32 seq_id; + RK_S32 target_bit; + + union { + RcVepuSet vepu; + RcVepu540Set vepu540; + }; +} RcHalSet; + +/* parameters returned from hardware */ +typedef struct RcHalRet_t { + /* unique sequential id */ + RK_S32 seq_id; + RK_S32 stream_size; + + union { + RcVepuRet vepu; + RcVepu540Ret vepu540; + }; +} RcHalRet; + +#endif /* RC_HAL_H */ diff --git a/mpp/codec/inc/vp8e_api_v2.h b/mpp/codec/inc/vp8e_api_v2.h new file mode 100644 index 000000000..53a393a9c --- /dev/null +++ b/mpp/codec/inc/vp8e_api_v2.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VP8E_API_V2_H +#define VP8E_API_V2_H + +#include "enc_impl_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const EncImplApi api_vp8e; + +#ifdef __cplusplus +} +#endif + +#endif /* VP8E_API_H */ diff --git a/mpp/codec/inc/vp9d_api.h b/mpp/codec/inc/vp9d_api.h deleted file mode 100644 index 380077e7b..000000000 --- a/mpp/codec/inc/vp9d_api.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VP9D_API_H__ -#define __VP9D_API_H__ - - - -#endif /*__VP9D_API_H__*/ \ No newline at end of file diff --git a/mpp/codec/mpp_buf_slot.cpp b/mpp/codec/mpp_buf_slot.cpp deleted file mode 100644 index 2aa215a8d..000000000 --- a/mpp/codec/mpp_buf_slot.cpp +++ /dev/null @@ -1,640 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_buf_slot" - -#include - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_env.h" -#include "mpp_list.h" -#include "mpp_common.h" - -#include "mpp_frame_impl.h" -#include "mpp_buf_slot.h" - - -#define BUF_SLOT_DBG_FUNCTION (0x00000001) -#define BUF_SLOT_DBG_SETUP (0x00000002) -#define BUF_SLOT_DBG_OPS_RUNTIME (0x00000010) -#define BUF_SLOT_DBG_BUFFER (0x00000100) -#define BUF_SLOT_DBG_FRAME (0x00000200) -#define BUF_SLOT_DBG_OPS_HISTORY (0x10000000) - -#define buf_slot_dbg(flag, fmt, ...) _mpp_dbg(buf_slot_debug, flag, fmt, ## __VA_ARGS__) - -static RK_U32 buf_slot_debug = 0; - -#define slot_assert(impl, cond) do { \ - if (!(cond)) { \ - dump_slots(impl); \ - mpp_err("Assertion %s failed at %s:%d\n", \ - MPP_STRINGS(cond), __FILE__, __LINE__); \ - abort(); \ - } \ -} while (0) - - -#define MPP_SLOT_UNUSED (0x00000000) -#define MPP_SLOT_USED (0x00010000) -#define MPP_SLOT_NOT_FILLED (0x00010000) -#define MPP_SLOT_USED_AS_DPB_REF (0x00020000) -#define MPP_SLOT_USED_AS_DISPLAY (0x00040000) -#define MPP_SLOT_USED_AS_HW_DST (0x00080000) -#define MPP_SLOT_WITH_FRAME (0x01000000) -#define MPP_SLOT_WITH_BUFFER (0x02000000) -#define MPP_SLOT_HW_REF_MASK (0x0000ffff) -#define MPP_SLOT_RELEASE_MASK (0x00ffffff) - -#define SLOT_CAN_RELEASE(slot) ((slot->status&MPP_SLOT_RELEASE_MASK)==MPP_SLOT_UNUSED) - -typedef struct MppBufSlotEntry_t { - struct list_head list; - RK_U32 status; - RK_S32 index; - MppFrame frame; -} MppBufSlotEntry; - -#define SLOT_OPS_MAX_COUNT 1024 - -typedef enum MppBufSlotOps_e { - SLOT_INIT, - SLOT_SET_NOT_READY, - SLOT_CLR_NOT_READY, - SLOT_SET_DPB_REF, - SLOT_CLR_DPB_REF, - SLOT_SET_DISPLAY, - SLOT_CLR_DISPLAY, - SLOT_SET_HW_DST, - SLOT_CLR_HW_DST, - SLOT_INC_HW_REF, - SLOT_DEC_HW_REF, - SLOT_SET_FRAME, - SLOT_CLR_FRAME, - SLOT_SET_BUFFER, - SLOT_CLR_BUFFER, -} MppBufSlotOps; - -static const char op_string[][16] = { - "init ", - "set not ready", - "set ready ", - "set dpb ref ", - "clr dpb ref ", - "set display ", - "clr display ", - "set hw dst ", - "clr hw dst ", - "inc hw ref ", - "dec hw ref ", - "set frame ", - "clr frame ", - "set buffer ", - "clr buffer ", -}; - -typedef struct MppBufSlotLog_t { - RK_U32 index; - MppBufSlotOps ops; - RK_U32 status_in; - RK_U32 status_out; -} MppBufSlotLog; - -typedef struct MppBufSlotsImpl_t { - Mutex *lock; - RK_U32 count; - RK_U32 size; - - // status tracing - RK_U32 decode_count; - RK_U32 display_count; - RK_U32 unrefer_count; - - // if slot changed, all will be hold until all slot is unused - RK_U32 info_changed; - RK_U32 new_count; - RK_U32 new_size; - - // to record current output slot index - RK_S32 output; - - // list for display - struct list_head display; - - // list for log - mpp_list *logs; - - MppBufSlotEntry *slots; -} MppBufSlotsImpl; - -static void add_slot_log(mpp_list *logs, RK_U32 index, MppBufSlotOps op, RK_U32 before, RK_U32 after) -{ - if (logs) { - MppBufSlotLog log = { - index, - op, - before, - after, - }; - if (logs->list_size() >= SLOT_OPS_MAX_COUNT) - logs->del_at_head(NULL, sizeof(log)); - logs->add_at_tail(&log, sizeof(log)); - } -} - -static void slot_ops_with_log(mpp_list *logs, MppBufSlotEntry *slot, MppBufSlotOps op) -{ - RK_U32 index = slot->index; - RK_U32 status = slot->status; - RK_U32 before = status; - switch (op) { - case SLOT_INIT : { - status = MPP_SLOT_UNUSED; - } break; - case SLOT_SET_NOT_READY : { - status |= MPP_SLOT_USED; - } break; - case SLOT_CLR_NOT_READY : { - status &= ~MPP_SLOT_USED; - } break; - case SLOT_SET_DPB_REF : { - status |= MPP_SLOT_USED_AS_DPB_REF; - } break; - case SLOT_CLR_DPB_REF : { - status &= ~MPP_SLOT_USED_AS_DPB_REF; - } break; - case SLOT_SET_DISPLAY : { - status |= MPP_SLOT_USED_AS_DISPLAY; - } break; - case SLOT_CLR_DISPLAY : { - status &= ~MPP_SLOT_USED_AS_DISPLAY; - } break; - case SLOT_SET_HW_DST : { - status |= MPP_SLOT_USED_AS_HW_DST; - } break; - case SLOT_CLR_HW_DST : { - status &= ~MPP_SLOT_USED_AS_HW_DST; - } break; - case SLOT_INC_HW_REF : { - status++; - } break; - case SLOT_DEC_HW_REF : { - status--; - } break; - case SLOT_SET_FRAME : { - status |= MPP_SLOT_WITH_FRAME; - } break; - case SLOT_CLR_FRAME : { - status &= ~MPP_SLOT_WITH_FRAME; - } break; - case SLOT_SET_BUFFER : { - status |= MPP_SLOT_WITH_BUFFER; - } break; - case SLOT_CLR_BUFFER : { - status &= ~MPP_SLOT_WITH_BUFFER; - } break; - default : { - mpp_err("found invalid operation code %d\n", op); - } break; - } - mpp_assert((RK_S16)(status&MPP_SLOT_HW_REF_MASK) >= 0); - slot->status = status; - buf_slot_dbg(BUF_SLOT_DBG_OPS_RUNTIME, "index %2d op: %s status in %08x out %08x", - index, op_string[op], before, status); - add_slot_log(logs, index, op, before, status); -} - -static void dump_slots(MppBufSlotsImpl *impl) -{ - RK_U32 i; - MppBufSlotEntry *slot = impl->slots; - - mpp_log("\ndumping slots %p count %d size %d\n", impl, impl->count, impl->size); - mpp_log("decode count %d\n", impl->decode_count); - mpp_log("display count %d\n", impl->display_count); - - for (i = 0; i < impl->count; i++, slot++) { - RK_U32 used = (slot->status & MPP_SLOT_USED) ? (1) : (0); - RK_U32 refer = (slot->status & MPP_SLOT_USED_AS_DPB_REF) ? (1) : (0); - RK_U32 decoding = (slot->status & MPP_SLOT_USED_AS_HW_DST) ? (1) : (0); - RK_U32 display = (slot->status & MPP_SLOT_USED_AS_DISPLAY) ? (1) : (0); - - mpp_log("slot %2d used %d refer %d decoding %d display %d\n", - i, used, refer, decoding, display); - } - - mpp_log("\nslot operation history:\n\n"); - - mpp_list *logs = impl->logs; - if (logs) { - while (logs->list_size()) { - MppBufSlotLog log; - logs->del_at_head(&log, sizeof(log)); - mpp_log("index %2d op: %s status in %08x out %08x", - log.index, op_string[log.ops], log.status_in, log.status_out); - } - } - -} - -static void init_slot_entry(mpp_list *logs, MppBufSlotEntry *slot, RK_S32 pos, RK_S32 count) -{ - for (RK_S32 i = 0; i < count; i++, slot++) { - INIT_LIST_HEAD(&slot->list); - slot->index = pos + i; - slot->frame = NULL; - slot_ops_with_log(logs, slot, SLOT_INIT); - } -} - -/* - * only called on unref / displayed / decoded - * - * NOTE: MppFrame will be destroyed outside mpp - * but MppBuffer must dec_ref here - */ -static MppFrame check_entry_unused(MppBufSlotsImpl *impl, MppBufSlotEntry *entry) -{ - if (SLOT_CAN_RELEASE(entry)) { - slot_assert(impl, entry->frame); - mpp_frame_deinit(&entry->frame); - slot_ops_with_log(impl->logs, entry, SLOT_CLR_BUFFER); - slot_ops_with_log(impl->logs, entry, SLOT_CLR_FRAME); - } - return entry->frame; -} - -MPP_RET mpp_buf_slot_init(MppBufSlots *slots) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - MppBufSlotsImpl *impl = mpp_calloc(MppBufSlotsImpl, 1); - if (NULL == impl) { - *slots = NULL; - return MPP_NOK; - } - - mpp_env_get_u32("buf_slot_debug", &buf_slot_debug, 0); - - impl->lock = new Mutex(); - INIT_LIST_HEAD(&impl->display); - - if (buf_slot_debug & BUF_SLOT_DBG_OPS_HISTORY) - impl->logs = new mpp_list(NULL); - - *slots = impl; - return MPP_OK; -} - -MPP_RET mpp_buf_slot_deinit(MppBufSlots slots) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - mpp_assert(list_empty(&impl->display)); - MppBufSlotEntry *slot = (MppBufSlotEntry *)impl->slots; - RK_U32 i; - for (i = 0; i < impl->count; i++, slot++) - mpp_assert(MPP_SLOT_UNUSED == slot->status); - - if (impl->logs) - delete impl->logs; - - delete impl->lock; - mpp_free(impl->slots); - mpp_free(slots); - return MPP_OK; -} - -MPP_RET mpp_buf_slot_setup(MppBufSlots slots, RK_U32 count, RK_U32 size, RK_U32 changed) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p setup: count %d size %d changed %d\n", - slots, count, size, changed); - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - if (NULL == impl->slots) { - // first slot setup - impl->count = count; - impl->size = size; - impl->slots = mpp_calloc(MppBufSlotEntry, count); - init_slot_entry(impl->logs, impl->slots, 0, count); - } else { - // need to check info change or not - if (!changed) { - slot_assert(impl, size == impl->size); - if (count > impl->count) { - mpp_realloc(impl->slots, MppBufSlotEntry, count); - init_slot_entry(impl->logs, impl->slots, impl->count, (count - impl->count)); - } - } else { - // info changed, even size is the same we still need to wait for new configuration - impl->new_count = count; - impl->new_size = size; - impl->info_changed = 1; - } - } - - return MPP_OK; -} - -RK_U32 mpp_buf_slot_is_changed(MppBufSlots slots) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return 0; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - return impl->info_changed; -} - -MPP_RET mpp_buf_slot_ready(MppBufSlots slots) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - buf_slot_dbg(BUF_SLOT_DBG_SETUP, "slot %p is ready now\n", slots); - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, impl->info_changed); - slot_assert(impl, impl->slots); - - impl->info_changed = 0; - impl->size = impl->new_size; - if (impl->count != impl->new_count) { - mpp_realloc(impl->slots, MppBufSlotEntry, impl->new_count); - init_slot_entry(impl->logs, impl->slots, 0, impl->new_count); - } - impl->count = impl->new_count; - if (impl->logs) { - mpp_list *logs = impl->logs; - while (logs->list_size()) - logs->del_at_head(NULL, sizeof(MppBufSlotLog)); - } - return MPP_OK; -} - -RK_U32 mpp_buf_slot_get_size(MppBufSlots slots) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return 0; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - return impl->size; -} - -MPP_RET mpp_buf_slot_get_unused(MppBufSlots slots, RK_U32 *index) -{ - if (NULL == slots || NULL == index) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - RK_U32 i; - MppBufSlotEntry *slot = impl->slots; - for (i = 0; i < impl->count; i++, slot++) { - if (MPP_SLOT_UNUSED == slot->status) { - *index = i; - slot_ops_with_log(impl->logs, slot, SLOT_SET_NOT_READY); - return MPP_OK; - } - } - - *index = -1; - mpp_err_f("failed to get a unused slot\n"); - dump_slots(impl); - slot_assert(impl, 0); - return MPP_NOK; -} - -MPP_RET mpp_buf_slot_set_dpb_ref(MppBufSlots slots, RK_U32 index) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - slot_ops_with_log(impl->logs, &impl->slots[index], SLOT_SET_DPB_REF); - return MPP_OK; -} - -MPP_RET mpp_buf_slot_clr_dpb_ref(MppBufSlots slots, RK_U32 index) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - slot_ops_with_log(impl->logs, slot, SLOT_CLR_DPB_REF); - check_entry_unused(impl, slot); - return MPP_OK; -} - -MPP_RET mpp_buf_slot_set_display(MppBufSlots slots, RK_U32 index) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - slot_ops_with_log(impl->logs, slot, SLOT_SET_DISPLAY); - - // add slot to display list - list_del_init(&slot->list); - list_add_tail(&slot->list, &impl->display); - return MPP_OK; -} - -MPP_RET mpp_buf_slot_set_hw_dst(MppBufSlots slots, RK_U32 index, MppFrame frame) -{ - if (NULL == slots || NULL == frame) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - slot_ops_with_log(impl->logs, slot, SLOT_SET_HW_DST); - - slot_assert(impl, slot->status & MPP_SLOT_NOT_FILLED); - if (NULL == slot->frame) - mpp_frame_init(&slot->frame); - - mpp_frame_copy(slot->frame, frame); - slot_ops_with_log(impl->logs, slot, SLOT_SET_FRAME); - impl->output = index; - return MPP_OK; -} - -MPP_RET mpp_buf_slot_clr_hw_dst(MppBufSlots slots, RK_U32 index) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - slot_ops_with_log(impl->logs, slot, SLOT_CLR_HW_DST); - slot_ops_with_log(impl->logs, slot, SLOT_CLR_NOT_READY); - impl->decode_count++; - check_entry_unused(impl, slot); - return MPP_OK; -} - -MPP_RET mpp_buf_slot_get_hw_dst(MppBufSlots slots, RK_U32 *index) -{ - if (NULL == slots || NULL == index) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - *index = impl->output; - return MPP_OK; -} - -MPP_RET mpp_buf_slot_inc_hw_ref(MppBufSlots slots, RK_U32 index) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - slot_ops_with_log(impl->logs, slot, SLOT_INC_HW_REF); - return MPP_OK; -} - -MPP_RET mpp_buf_slot_dec_hw_ref(MppBufSlots slots, RK_U32 index) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - slot_ops_with_log(impl->logs, slot, SLOT_DEC_HW_REF); - check_entry_unused(impl, slot); - return MPP_OK; -} - -MPP_RET mpp_buf_slot_set_buffer(MppBufSlots slots, RK_U32 index, MppBuffer buffer) -{ - if (NULL == slots || NULL == buffer) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - slot_assert(impl, slot->frame); - mpp_frame_set_buffer(slot->frame, buffer); - mpp_buffer_inc_ref(buffer); - slot_ops_with_log(impl->logs, slot, SLOT_SET_BUFFER); - return MPP_OK; -} - -MppBuffer mpp_buf_slot_get_buffer(MppBufSlots slots, RK_U32 index) -{ - if (NULL == slots) { - mpp_err_f("found NULL input\n"); - return NULL; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - slot_assert(impl, index < impl->count); - MppBufSlotEntry *slot = &impl->slots[index]; - return mpp_frame_get_buffer(slot->frame); -} - -MPP_RET mpp_buf_slot_get_display(MppBufSlots slots, MppFrame *frame) -{ - if (NULL == slots || NULL == frame) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppBufSlotsImpl *impl = (MppBufSlotsImpl *)slots; - Mutex::Autolock auto_lock(impl->lock); - if (list_empty(&impl->display)) - return MPP_NOK; - - MppBufSlotEntry *slot = list_entry(impl->display.next, MppBufSlotEntry, list); - if (slot->status & MPP_SLOT_NOT_FILLED) - return MPP_NOK; - - // make sure that this slot is just the next display slot - list_del_init(&slot->list); - - MppFrame display; - mpp_frame_init(&display); - mpp_frame_copy(display, slot->frame); - *frame = display; - - RK_U32 index = slot->index; - slot_assert(impl, index < impl->count); - slot_ops_with_log(impl->logs, slot, SLOT_CLR_DISPLAY); - check_entry_unused(impl, slot); - impl->display_count++; - return MPP_OK; -} - - diff --git a/mpp/codec/mpp_dec.c b/mpp/codec/mpp_dec.c new file mode 100644 index 000000000..bacf4f370 --- /dev/null +++ b/mpp/codec/mpp_dec.c @@ -0,0 +1,984 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dec" + +#include + +#include "mpp_env.h" + +#include "mpp_buffer_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_dec_cfg.h" + +#include "mpp_dec_debug.h" +#include "mpp_dec_vproc.h" +#include "mpp_dec_cb_param.h" +#include "mpp_dec_normal.h" +#include "mpp_dec_no_thread.h" + +RK_U32 mpp_dec_debug = 0; + +MPP_RET dec_task_info_init(HalTaskInfo *task) +{ + HalDecTask *p = &task->dec; + + p->valid = 0; + p->flags.val = 0; + p->flags.eos = 0; + p->input_packet = NULL; + p->output = -1; + p->input = -1; + memset(&task->dec.syntax, 0, sizeof(task->dec.syntax)); + memset(task->dec.refer, -1, sizeof(task->dec.refer)); + + return MPP_OK; +} + +void dec_task_init(DecTask *task) +{ + task->hnd = NULL; + task->status.val = 0; + task->wait.val = 0; + task->status.prev_task_rdy = 1; + INIT_LIST_HEAD(&task->ts_cur.link); + + dec_task_info_init(&task->info); +} + +static MPP_RET mpp_dec_update_cfg(MppDecImpl *p) +{ + MppDecCfgSet *cfg = p->cfg; + MppDecBaseCfg *base = &cfg->base; + MppDecStatusCfg *status = &cfg->status; + + if (status->hal_task_count && !status->hal_support_fast_mode) { + if (!p->parser_fast_mode && base->fast_parse) { + mpp_err("can not enable fast parse while hal not support\n"); + base->fast_parse = 0; + } + } + + p->parser_fast_mode = base->fast_parse; + p->enable_deinterlace = base->enable_vproc; + p->disable_error = base->disable_error; + p->dis_err_clr_mark = base->dis_err_clr_mark; + + mpp_env_get_u32("enable_deinterlace", &p->enable_deinterlace, base->enable_vproc); + + return MPP_OK; +} + +static MPP_RET mpp_dec_check_fbc_cap(MppDecImpl *p) +{ + MppDecBaseCfg *base = &p->cfg->base; + + if (MPP_FRAME_FMT_IS_FBC(base->out_fmt)) { + RK_U32 fbc = (RK_U32)base->out_fmt & MPP_FRAME_FBC_MASK; + RK_U32 fmt = base->out_fmt - fbc; + + if (p->hw_info && p->hw_info->cap_fbc) + fmt |= fbc; + + base->out_fmt = (MppFrameFormat)fmt; + } + + return MPP_OK; +} + +MPP_RET mpp_dec_proc_cfg(MppDecImpl *dec, MpiCmd cmd, void *param) +{ + MPP_RET ret = MPP_OK; + + mpp_parser_control(dec->parser, cmd, param); + + ret = mpp_hal_control(dec->hal, cmd, param); + + if (ret) + goto RET; + + switch (cmd) { + case MPP_DEC_SET_FRAME_INFO : { + MppFrame frame = (MppFrame)param; + + /* update output frame format */ + dec->cfg->base.out_fmt = mpp_frame_get_fmt(frame); + mpp_log_f("found MPP_DEC_SET_FRAME_INFO fmt %x\n", dec->cfg->base.out_fmt); + + mpp_slots_set_prop(dec->frame_slots, SLOTS_FRAME_INFO, frame); + + mpp_log("setting default w %4d h %4d h_str %4d v_str %4d\n", + mpp_frame_get_width(frame), + mpp_frame_get_height(frame), + mpp_frame_get_hor_stride(frame), + mpp_frame_get_ver_stride(frame)); + + } break; + case MPP_DEC_SET_INFO_CHANGE_READY: { + ret = mpp_buf_slot_ready(dec->frame_slots); + } break; + case MPP_DEC_GET_VPUMEM_USED_COUNT: { + RK_S32 *p = (RK_S32 *)param; + *p = mpp_slots_get_used_count(dec->frame_slots); + dec_dbg_func("used count %d\n", *p); + } break; + case MPP_DEC_SET_PRESENT_TIME_ORDER : + case MPP_DEC_SET_PARSER_SPLIT_MODE : + case MPP_DEC_SET_PARSER_FAST_MODE : + case MPP_DEC_SET_IMMEDIATE_OUT : + case MPP_DEC_SET_OUTPUT_FORMAT : + case MPP_DEC_SET_DISABLE_ERROR : + case MPP_DEC_SET_DIS_ERR_CLR_MARK : + case MPP_DEC_SET_ENABLE_DEINTERLACE : + case MPP_DEC_SET_ENABLE_FAST_PLAY : + case MPP_DEC_SET_ENABLE_MVC : + case MPP_DEC_SET_DISABLE_DPB_CHECK: { + ret = mpp_dec_set_cfg_by_cmd(dec->cfg_obj, cmd, param); + mpp_dec_update_cfg(dec); + mpp_dec_check_fbc_cap(dec); + } break; + case MPP_DEC_QUERY: { + MppDecQueryCfg *query = (MppDecQueryCfg *)param; + RK_U32 flag = query->query_flag; + + dec_dbg_func("query %x\n", flag); + + if (flag & MPP_DEC_QUERY_STATUS) + query->rt_status = dec->parser_status_flag; + + if (flag & MPP_DEC_QUERY_WAIT) + query->rt_wait = dec->parser_wait_flag; + + if (flag & MPP_DEC_QUERY_FPS) + query->rt_fps = 0; + + if (flag & MPP_DEC_QUERY_BPS) + query->rt_bps = 0; + + if (flag & MPP_DEC_QUERY_DEC_IN_PKT) + query->dec_in_pkt_cnt = dec->dec_in_pkt_count; + + if (flag & MPP_DEC_QUERY_DEC_WORK) + query->dec_hw_run_cnt = dec->dec_hw_run_count; + + if (flag & MPP_DEC_QUERY_DEC_OUT_FRM) + query->dec_out_frm_cnt = dec->dec_out_frame_count; + } break; + case MPP_DEC_SET_CFG: { + if (param) { + kmpp_obj_update(dec->cfg_obj, (KmppObj)param); + mpp_dec_update_cfg(dec); + mpp_dec_check_fbc_cap(dec); + } + + dec_dbg_func("set dec cfg\n"); + } break; + case MPP_DEC_GET_CFG: { + if (param) + ret = (MPP_RET)kmpp_obj_copy_entry(param, dec->cfg_obj); + + dec_dbg_func("get dec cfg\n"); + } break; + default : { + } break; + } + +RET: + return ret; +} + +/* Overall mpp_dec output frame function */ +void mpp_dec_put_frame(Mpp *mpp, RK_S32 index, HalDecTaskFlag flags) +{ + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppBufSlots slots = dec->frame_slots; + MppFrame frame = NULL; + RK_U32 eos = flags.eos; + RK_U32 change = flags.info_change; + RK_U32 error = flags.parse_err || flags.ref_err; + RK_U32 refer = flags.used_for_ref; + RK_U32 fake_frame = 0; + + if (index >= 0) { + RK_U32 mode = 0; + + mpp_buf_slot_get_prop(slots, index, SLOT_FRAME_PTR, &frame); + + mode = mpp_frame_get_mode(frame); + if (mode && dec->enable_deinterlace && NULL == dec->vproc) { + MppDecVprocCfg cfg = { mpp, NULL }; + MPP_RET ret = dec_vproc_init(&dec->vproc, &cfg); + if (ret) { + // When iep is failed to open disable deinterlace function to + // avoid noisy log. + dec->enable_deinterlace = 0; + dec->vproc = NULL; + } else { + if (dec_vproc_get_version(dec->vproc) == 1 && mode == MPP_FRAME_FLAG_DEINTERLACED) { + mpp_frame_set_mode(frame, MPP_FRAME_FLAG_FRAME); + /*iep 1 can't no detect DEINTERLACED, direct disable*/ + dec->cfg->base.enable_vproc &= (~MPP_VPROC_MODE_DETECTION); + dec->enable_deinterlace = dec->cfg->base.enable_vproc; + if (dec->vproc && !dec->enable_deinterlace) { + dec_vproc_deinit(dec->vproc); + dec->vproc = NULL; + } + dec->vproc = NULL; + } else { + /* store current IEP mode */ + dec_vproc_set_mode(dec->vproc, (MppVprocMode)dec->enable_deinterlace); + + dec->vproc_tasks = cfg.task_group; + dec_vproc_start(dec->vproc); + } + } + } + } else { + // when post-process is needed and eos without slot index case + // we need to create a slot index for it + mpp_assert(eos); + mpp_assert(!change); + + if (dec->vproc) { + HalTaskGroup group = dec->vproc_tasks; + HalTaskHnd hnd = NULL; + HalTaskInfo task; + HalDecVprocTask *vproc_task = &task.dec_vproc; + MPP_RET ret = MPP_OK; + + do { + ret = hal_task_get_hnd(group, TASK_IDLE, &hnd); + if (ret) { + if (dec->reset_flag) { + return; + } else { + msleep(10); + } + } + } while (ret); + vproc_task->flags.val = 0; + vproc_task->flags.eos = eos; + vproc_task->input = index; + + hal_task_hnd_set_info(hnd, &task); + hal_task_hnd_set_status(hnd, TASK_PROCESSING); + dec_vproc_signal(dec->vproc); + + return ; + } else { + mpp_frame_init(&frame); + fake_frame = 1; + index = 0; + } + + mpp_frame_set_eos(frame, eos); + } + + mpp_assert(index >= 0); + mpp_assert(frame); + + if (dec->cfg->base.disable_error && dec->cfg->base.dis_err_clr_mark) { + mpp_frame_set_errinfo(frame, 0); + mpp_frame_set_discard(frame, 0); + } + + if (!change) { + if (dec->cfg->base.sort_pts) { + MppPktTs *pkt_ts; + + mpp_spinlock_lock(&dec->ts_lock); + pkt_ts = list_first_entry_or_null(&dec->ts_link, MppPktTs, link); + if (pkt_ts) + list_del_init(&pkt_ts->link); + mpp_spinlock_unlock(&dec->ts_lock); + if (pkt_ts) { + mpp_frame_set_dts(frame, pkt_ts->dts); + mpp_frame_set_pts(frame, pkt_ts->pts); + mpp_mem_pool_put_f(dec->ts_pool, pkt_ts); + } + } + } + mpp_frame_set_info_change(frame, change); + + if (eos) { + mpp_frame_set_eos(frame, 1); + if (error) { + if (refer) + mpp_frame_set_errinfo(frame, 1); + else + mpp_frame_set_discard(frame, 1); + } + } + + dec->dec_out_frame_count++; + dec_dbg_detail("detail: %p put frm pts %llu fd %d\n", dec, + mpp_frame_get_pts(frame), + (NULL == mpp_frame_get_buffer(frame)) ? (-1) : + mpp_buffer_get_fd(mpp_frame_get_buffer(frame))); + + if (dec->vproc) { + HalTaskGroup group = dec->vproc_tasks; + HalTaskHnd hnd = NULL; + HalTaskInfo task; + HalDecVprocTask *vproc_task = &task.dec_vproc; + MPP_RET ret = MPP_OK; + + do { + ret = hal_task_get_hnd(group, TASK_IDLE, &hnd); + if (ret) { + if (dec->reset_flag) { + MppBuffer buffer = NULL; + mpp_buf_slot_get_prop(slots, index, SLOT_BUFFER, &buffer); + if (buffer) + mpp_buffer_put(buffer); + return; + } else { + msleep(10); + } + } + } while (ret); + + mpp_assert(ret == MPP_OK); + + vproc_task->flags.eos = eos; + vproc_task->flags.info_change = change; + vproc_task->input = index; + + if (!change) { + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DEINTERLACE); + } + + hal_task_hnd_set_info(hnd, &task); + hal_task_hnd_set_status(hnd, TASK_PROCESSING); + + dec_vproc_signal(dec->vproc); + } else { + // direct output -> copy a new MppFrame and output + MppList *list = mpp->mFrmOut; + MppFrame out = NULL; + + mpp_frame_init(&out); + mpp_frame_copy(out, frame); + + sys_dbg_pts("output frame pts %lld\n", mpp_frame_get_pts(out)); + + mpp_mutex_cond_lock(&list->cond_lock); + mpp_list_add_at_tail(list, &out, sizeof(out)); + mpp->mFramePutCount++; + mpp_list_signal(list); + mpp_mutex_cond_unlock(&list->cond_lock); + + if (fake_frame) + mpp_frame_deinit(&frame); + + mpp_dec_callback(dec, MPP_DEC_EVENT_ON_FRM_READY, out); + } +} + +RK_S32 mpp_dec_push_display(Mpp *mpp, HalDecTaskFlag flags) +{ + RK_S32 index = -1; + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppBufSlots frame_slots = dec->frame_slots; + RK_U32 eos = flags.eos; + HalDecTaskFlag tmp = flags; + RK_S32 ret = 0; + + tmp.eos = 0; + /** + * After info_change is encountered by parser thread, HalDecTaskFlag will + * have this flag set. Although mpp_dec_flush is called there may be some + * frames still remaining in display queue and waiting to be output. So + * these frames shouldn't have info_change set since their resolution and + * bit depth are the same as before. What's more, the info_change flag has + * nothing to do with frames being output. + */ + tmp.info_change = 0; + + if (dec->thread_hal) + mpp_thread_lock(dec->thread_hal, THREAD_OUTPUT); + + while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) { + /* deal with current frame */ + if (eos && mpp_slots_is_empty(frame_slots, QUEUE_DISPLAY)) + tmp.eos = 1; + + mpp_dec_put_frame(mpp, index, tmp); + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE); + ret++; + } + + if (dec->thread_hal) + mpp_thread_unlock(dec->thread_hal, THREAD_OUTPUT); + + return ret; +} + +MPP_RET update_dec_hal_info(MppDecImpl *dec, MppFrame frame) +{ + HalInfo hal_info = dec->hal_info; + MppDevInfoCfg data[DEC_INFO_BUTT]; + RK_S32 size = sizeof(data); + RK_U64 val = 0; + RK_S32 i; + + hal_info_set(hal_info, DEC_INFO_WIDTH, CODEC_INFO_FLAG_NUMBER, + mpp_frame_get_width(frame)); + + hal_info_set(hal_info, DEC_INFO_HEIGHT, CODEC_INFO_FLAG_NUMBER, + mpp_frame_get_height(frame)); + + val = hal_info_to_string(hal_info, DEC_INFO_FORMAT, &dec->coding); + hal_info_set(hal_info, DEC_INFO_FORMAT, CODEC_INFO_FLAG_STRING, val); + + hal_info_get(hal_info, data, &size); + + if (size) { + size /= sizeof(data[0]); + for (i = 0; i < size; i++) + mpp_dev_ioctl(dec->dev, MPP_DEV_SET_INFO, &data[i]); + } + + return MPP_OK; +} + +static MppDecModeApi *dec_api[] = { + &dec_api_normal, + &dec_api_no_thread, +}; + +static const char *timing_str[DEC_TIMING_BUTT] = { + "prs thread", + "prs wait ", + "prs proc ", + "prepare ", + "parse ", + "gen reg ", + "hw start ", + + "hal thread", + "hal wait ", + "hal proc ", + "hw wait ", +}; + +MPP_RET mpp_dec_callback_hal_to_parser(const char *caller, void *ctx, + RK_S32 cmd, void *param) +{ + MppDecImpl *p = (MppDecImpl *)ctx; + MPP_RET ret = MPP_OK; + (void) caller; + + mpp_assert(cmd == DEC_PARSER_CALLBACK); + + if (p->parser) + ret = mpp_parser_callback(p->parser, param); + + return ret; +} + +MPP_RET mpp_dec_callback_slot(const char *caller, void *ctx, RK_S32 cmd, void *param) +{ + (void) caller; + (void) cmd; + (void) param; + return mpp_dec_notify((MppDec)ctx, MPP_DEC_NOTIFY_SLOT_VALID); +} + +MPP_RET mpp_dec_init(MppDec *dec, MppDecInitCfg *cfg) +{ + RK_S32 i; + MPP_RET ret; + MppCodingType coding; + MppBufSlots frame_slots = NULL; + MppBufSlots packet_slots = NULL; + Mpp *mpp = (Mpp *)cfg->mpp; + MppDecImpl *p = NULL; + MppDecCfgSet *dec_cfg = NULL; + RK_U32 hal_task_count = 2; + RK_U32 support_fast_mode = 0; + SlotHalFbcAdjCfg hal_fbc_adj_cfg; + + mpp_env_get_u32("mpp_dec_debug", &mpp_dec_debug, 0); + + dec_dbg_func("in\n"); + + if (NULL == dec || NULL == cfg) { + mpp_err_f("invalid input dec %p cfg %p\n", dec, cfg); + return MPP_ERR_NULL_PTR; + } + + *dec = NULL; + + p = mpp_calloc(MppDecImpl, 1); + if (NULL == p) { + mpp_err_f("failed to malloc context\n"); + return MPP_ERR_MALLOC; + } + + p->mpp = mpp; + mpp_dec_cfg_init(&p->cfg_obj); + dec_cfg = (MppDecCfgSet *)kmpp_obj_to_entry(p->cfg_obj); + p->cfg = dec_cfg; + coding = cfg->coding; + + mpp_assert(cfg->cfg); + kmpp_obj_update(p->cfg_obj, cfg->cfg); + mpp_dec_update_cfg(p); + + p->dec_cb.callBack = mpp_dec_callback_hal_to_parser; + p->dec_cb.ctx = p; + p->dec_cb.cmd = DEC_PARSER_CALLBACK; + + do { + ret = mpp_buf_slot_init(&p->frame_slots); + if (ret) { + mpp_err_f("could not init frame buffer slot\n"); + break; + } + frame_slots = p->frame_slots; + + MppCbCtx cb_ctx = { + mpp_dec_callback_slot, + (void *)p, + 0, + }; + + mpp_buf_slot_set_callback(frame_slots, &cb_ctx); + mpp_buf_slot_set_dec_cfg(frame_slots, p->cfg_obj); + + ret = mpp_buf_slot_init(&p->packet_slots); + if (ret) { + mpp_err_f("could not init packet buffer slot\n"); + break; + } + packet_slots = p->packet_slots; + + MppHalCfg hal_cfg = { + .type = MPP_CTX_DEC, + .coding = coding, + .frame_slots = frame_slots, + .packet_slots = packet_slots, + .cfg = dec_cfg, + .dec_cb = &p->dec_cb, + .hw_info = NULL, + .dev = NULL, + .support_fast_mode = 0, + .hal_fbc_adj_cfg = &hal_fbc_adj_cfg, + .buf_group = NULL, + }; + + memset(&hal_fbc_adj_cfg, 0, sizeof(hal_fbc_adj_cfg)); + + ret = mpp_hal_init(&p->hal, &hal_cfg); + if (ret) { + mpp_err_f("could not init hal\n"); + break; + } + + if (hal_fbc_adj_cfg.func) + mpp_slots_set_prop(frame_slots, SLOTS_HAL_FBC_ADJ, &hal_fbc_adj_cfg); + + support_fast_mode = hal_cfg.support_fast_mode; + + if (dec_cfg->base.fast_parse && support_fast_mode) { + hal_task_count = (dec_cfg->status.hal_task_count != 0) ? + dec_cfg->status.hal_task_count : 3; + } else { + dec_cfg->base.fast_parse = 0; + p->parser_fast_mode = 0; + } + dec_cfg->status.hal_support_fast_mode = support_fast_mode; + dec_cfg->status.hal_task_count = hal_task_count; + + ret = hal_task_group_init(&p->tasks, TASK_BUTT, hal_task_count, sizeof(HalDecTask)); + if (ret) { + mpp_err_f("hal_task_group_init failed ret %d\n", ret); + break; + } + + mpp_buf_slot_setup(packet_slots, hal_task_count); + mpp_slots_set_prop(packet_slots, SLOTS_CODING_TYPE, &coding); + mpp_slots_set_prop(frame_slots, SLOTS_CODING_TYPE, &coding); + + p->hw_info = hal_cfg.hw_info; + p->dev = hal_cfg.dev; + /* check fbc cap after hardware info is valid */ + mpp_dec_check_fbc_cap(p); + + ParserCfg parser_cfg = { + coding, + frame_slots, + packet_slots, + dec_cfg, + p->hw_info, + }; + + ret = mpp_parser_init(&p->parser, &parser_cfg); + if (ret) { + mpp_err_f("could not init parser\n"); + break; + } + + ret = hal_info_init(&p->hal_info, MPP_CTX_DEC, coding); + if (ret) { + mpp_err_f("could not init hal info\n"); + break; + } + + p->coding = coding; + p->statistics_en = ((mpp_dec_debug & MPP_DEC_DBG_TIMING) != 0) ? 1 : 0; + + for (i = 0; i < DEC_TIMING_BUTT; i++) { + p->clocks[i] = mpp_clock_get(timing_str[i]); + mpp_assert(p->clocks[i]); + mpp_clock_enable(p->clocks[i], p->statistics_en); + } + + mpp_mutex_cond_init(&p->cmd_lock); + sem_init(&p->parser_reset, 0, 0); + sem_init(&p->hal_reset, 0, 0); + sem_init(&p->cmd_start, 0, 0); + sem_init(&p->cmd_done, 0, 0); + + if (p->cfg->base.disable_thread) { + DecTask *task = mpp_calloc(DecTask, 1); + + mpp_assert(task); + + p->task_single = task; + dec_task_info_init(&task->info); + + p->mode = MPP_DEC_MODE_NO_THREAD; + } + + p->api = dec_api[p->mode]; + + // init timestamp for record and sort pts + mpp_spinlock_init(&p->ts_lock); + INIT_LIST_HEAD(&p->ts_link); + p->ts_pool = mpp_mem_pool_init_f("ts_pool", sizeof(MppPktTs)); + if (!p->ts_pool) { + mpp_err_f("malloc ts pool failed!\n"); + break; + } + + *dec = p; + dec_dbg_func("%p out\n", p); + return MPP_OK; + } while (0); + + mpp_dec_deinit(p); + return MPP_NOK; +} + +MPP_RET mpp_dec_deinit(MppDec ctx) +{ + RK_S32 i; + MppDecImpl *dec = (MppDecImpl *)ctx; + + dec_dbg_func("%p in\n", dec); + if (NULL == dec) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + if (dec->statistics_en) { + mpp_log("%p work %lu wait %lu\n", dec, + dec->parser_work_count, dec->parser_wait_count); + + for (i = 0; i < DEC_TIMING_BUTT; i++) { + MppClock timer = dec->clocks[i]; + RK_S32 base = (i < DEC_HAL_TOTAL) ? (DEC_PRS_TOTAL) : (DEC_HAL_TOTAL); + RK_S64 time = mpp_clock_get_sum(timer); + RK_S64 total = mpp_clock_get_sum(dec->clocks[base]); + + if (!time || !total) + continue; + + mpp_log("%p %s - %6.2f %-12lld avg %-12lld\n", dec, + mpp_clock_get_name(timer), time * 100.0 / total, time, + time / mpp_clock_get_count(timer)); + } + } + + for (i = 0; i < DEC_TIMING_BUTT; i++) { + if (dec->clocks[i]) { + mpp_clock_put(dec->clocks[i]); + dec->clocks[i] = NULL; + } + } + + if (dec->hal_info) { + hal_info_deinit(dec->hal_info); + dec->hal_info = NULL; + } + + if (dec->parser) { + mpp_parser_deinit(dec->parser); + dec->parser = NULL; + } + + if (dec->tasks) { + hal_task_group_deinit(dec->tasks); + dec->tasks = NULL; + } + + if (dec->hal) { + mpp_hal_deinit(dec->hal); + dec->hal = NULL; + } + + if (dec->vproc) { + dec_vproc_deinit(dec->vproc); + dec->vproc = NULL; + } + + if (dec->frame_slots) { + mpp_buf_slot_deinit(dec->frame_slots); + dec->frame_slots = NULL; + } + + if (dec->packet_slots) { + mpp_buf_slot_deinit(dec->packet_slots); + dec->packet_slots = NULL; + } + + mpp_mutex_cond_destroy(&dec->cmd_lock); + + sem_destroy(&dec->parser_reset); + sem_destroy(&dec->hal_reset); + sem_destroy(&dec->cmd_start); + sem_destroy(&dec->cmd_done); + + if (dec->ts_pool) { + mpp_mem_pool_deinit_f(dec->ts_pool); + dec->ts_pool = NULL; + } + + if (dec->cfg_obj) { + mpp_dec_cfg_deinit(dec->cfg_obj); + dec->cfg_obj = NULL; + } + dec->cfg = NULL; + + MPP_FREE(dec->task_single); + mpp_free(dec); + dec_dbg_func("%p out\n", dec); + return MPP_OK; +} + +MPP_RET mpp_dec_start(MppDec ctx) +{ + MppDecImpl *dec = (MppDecImpl *)ctx; + MPP_RET ret = MPP_OK; + + dec_dbg_func("%p in\n", dec); + + if (dec->api && dec->api->start) + ret = dec->api->start(dec); + + dec_dbg_func("%p out ret %d\n", dec, ret); + return ret; +} + +MPP_RET mpp_dec_stop(MppDec ctx) +{ + MPP_RET ret = MPP_OK; + MppDecImpl *dec = (MppDecImpl *)ctx; + + dec_dbg_func("%p in\n", dec); + + if (dec->thread_parser) + mpp_thread_stop(dec->thread_parser); + + if (dec->thread_hal) + mpp_thread_stop(dec->thread_hal); + + if (dec->thread_parser) { + mpp_thread_destroy(dec->thread_parser); + dec->thread_parser = NULL; + } + + if (dec->thread_hal) { + mpp_thread_destroy(dec->thread_hal); + dec->thread_hal = NULL; + } + + dec_dbg_func("%p out\n", dec); + return ret; +} + +MPP_RET mpp_dec_reset(MppDec ctx) +{ + MppDecImpl *dec = (MppDecImpl *)ctx; + MPP_RET ret = MPP_OK; + + if (NULL == dec) { + mpp_err_f("found NULL input dec %p\n", dec); + return MPP_ERR_NULL_PTR; + } + + dec_dbg_func("%p in\n", dec); + + if (dec->api && dec->api->reset) + ret = dec->api->reset(dec); + + dec_dbg_func("%p out ret %d\n", dec, ret); + + return ret; +} + +MPP_RET mpp_dec_flush(MppDec ctx) +{ + MppDecImpl *dec = (MppDecImpl *)ctx; + + dec_dbg_func("%p in\n", dec); + if (NULL == dec) { + mpp_err_f("found NULL input dec %p\n", dec); + return MPP_ERR_NULL_PTR; + } + + mpp_parser_flush(dec->parser); + mpp_hal_flush(dec->hal); + + dec_dbg_func("%p out\n", dec); + return MPP_OK; +} + +MPP_RET mpp_dec_notify(MppDec ctx, RK_U32 flag) +{ + MppDecImpl *dec = (MppDecImpl *)ctx; + MPP_RET ret = MPP_OK; + + dec_dbg_func("%p in flag %08x\n", dec, flag); + + if (dec->vproc && (flag & MPP_DEC_NOTIFY_BUFFER_MATCH)) + dec_vproc_signal(dec->vproc); + + if (dec->api && dec->api->notify) + ret = dec->api->notify(dec, flag); + + dec_dbg_func("%p out ret %d\n", dec, ret); + + return ret; +} + +MPP_RET mpp_dec_callback(MppDec ctx, MppDecEvent event, void *arg) +{ + MppDecImpl *dec = (MppDecImpl *)ctx; + MppDecCbCfg *cb = &dec->cfg->cb; + Mpp *mpp = (Mpp *)dec->mpp; + MPP_RET ret = MPP_OK; + + switch (event) { + case MPP_DEC_EVENT_ON_PKT_RELEASE : { + if (cb->pkt_rdy_cb) + ret = cb->pkt_rdy_cb(cb->pkt_rdy_ctx, mpp->mCtx, cb->pkt_rdy_cmd, arg); + } break; + case MPP_DEC_EVENT_ON_FRM_READY : { + if (cb->frm_rdy_cb) + ret = cb->frm_rdy_cb(cb->frm_rdy_ctx, mpp->mCtx, cb->frm_rdy_cmd, arg); + } break; + default : { + } break; + } + + return ret; +} + +MPP_RET mpp_dec_control(MppDec ctx, MpiCmd cmd, void *param) +{ + MPP_RET ret = MPP_OK; + MppDecImpl *dec = (MppDecImpl *)ctx; + + if (NULL == dec) { + mpp_err_f("found NULL input dec %p\n", dec); + return MPP_ERR_NULL_PTR; + } + + dec_dbg_func("%p in %08x %p\n", dec, cmd, param); + dec_dbg_detail("detail: %p control cmd %08x param %p start\n", dec, cmd, param); + + if (dec->api && dec->api->control) + ret = dec->api->control(dec, cmd, param); + + dec_dbg_detail("detail: %p control cmd %08x param %p ret %d\n", dec, cmd, param, ret); + dec_dbg_func("%p out ret %d\n", dec, ret); + + return ret; +} + +MPP_RET mpp_dec_set_cfg_by_cmd(MppDecCfg cfg, MpiCmd cmd, void *param) +{ + MppDecCfgSet *dst = (MppDecCfgSet *)kmpp_obj_to_entry(cfg); + MppDecBaseCfg *base = &dst->base; + MPP_RET ret = MPP_OK; + + switch (cmd) { + case MPP_DEC_SET_PRESENT_TIME_ORDER : { + ret = mpp_dec_cfg_set_u32(cfg, "base:sort_pts", (param) ? (*((RK_U32 *)param)) : (1)); + dec_dbg_func("sort time order %d\n", base->sort_pts); + } break; + case MPP_DEC_SET_PARSER_SPLIT_MODE : { + ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", (param) ? (*((RK_U32 *)param)) : (0)); + dec_dbg_func("split parse mode %d\n", base->split_parse); + } break; + case MPP_DEC_SET_PARSER_FAST_MODE : { + ret = mpp_dec_cfg_set_u32(cfg, "base:fast_parse", (param) ? (*((RK_U32 *)param)) : (0)); + dec_dbg_func("fast parse mode %d\n", base->fast_parse); + } break; + case MPP_DEC_SET_OUTPUT_FORMAT : { + ret = mpp_dec_cfg_set_u32(cfg, "base:out_fmt", (param) ? (*((RK_U32 *)param)) : (RK_U32)(MPP_FMT_YUV420SP)); + dec_dbg_func("fast out_fmt %d\n", base->out_fmt); + } break; + case MPP_DEC_SET_DISABLE_ERROR: { + ret = mpp_dec_cfg_set_u32(cfg, "base:disable_error", (param) ? (*((RK_U32 *)param)) : (1)); + dec_dbg_func("disable error %d\n", base->disable_error); + } break; + case MPP_DEC_SET_DIS_ERR_CLR_MARK: { + ret = mpp_dec_cfg_set_u32(cfg, "base:dis_err_clr_mark", (param) ? (*((RK_U32 *)param)) : (1)); + dec_dbg_func("disable error mark %x\n", base->dis_err_clr_mark); + } break; + case MPP_DEC_SET_IMMEDIATE_OUT : { + ret = mpp_dec_cfg_set_u32(cfg, "base:fast_out", (param) ? (*((RK_U32 *)param)) : (0)); + dec_dbg_func("fast output mode %d\n", base->fast_out); + } break; + case MPP_DEC_SET_ENABLE_DEINTERLACE: { + ret = mpp_dec_cfg_set_u32(cfg, "base:enable_vproc", (param) ? (*((RK_U32 *)param)) : (MPP_VPROC_MODE_DEINTELACE)); + dec_dbg_func("enable dec_vproc %x\n", base->enable_vproc); + } break; + case MPP_DEC_SET_ENABLE_FAST_PLAY : { + ret = mpp_dec_cfg_set_u32(cfg, "base:enable_fast_play", (param) ? (*((RK_U32 *)param)) : (0)); + dec_dbg_func("disable idr immediately output %d\n", base->enable_fast_play); + } break; + case MPP_DEC_SET_ENABLE_MVC : { + ret = mpp_dec_cfg_set_u32(cfg, "base:enable_mvc", (param) ? (*((RK_U32 *)param)) : (0)); + dec_dbg_func("enable MVC decoder %d\n", base->enable_mvc); + } break; + case MPP_DEC_SET_DISABLE_DPB_CHECK : { + ret = mpp_dec_cfg_set_u32(cfg, "base:disable_dpb_chk", (param) ? (*((RK_U32 *)param)) : (0)); + dec_dbg_func("disable dpb discontinuous check %d\n", base->disable_dpb_chk); + } break; + case MPP_DEC_SET_CODEC_MODE : { + ret = mpp_dec_cfg_set_u32(cfg, "base:codec_mode", (param) ? (*((RK_U32 *)param)) : (0)); + dec_dbg_func("force use codec device %d\n", base->codec_mode); + } break; + default : { + mpp_err_f("unsupported cfg update cmd %x\n", cmd); + ret = MPP_NOK; + } break; + } + + return ret; +} + +MppDecCfg mpp_dec_to_cfg(MppDec ctx) +{ + MppDecImpl *dec = (MppDecImpl *)ctx; + + return (NULL != dec) ? dec->cfg_obj : NULL; +} diff --git a/mpp/codec/mpp_dec.cpp b/mpp/codec/mpp_dec.cpp deleted file mode 100644 index 1d4b5d4bb..000000000 --- a/mpp/codec/mpp_dec.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_dec" - -#include - -#include "mpp_mem.h" -#include "mpp_log.h" -#include "mpp_common.h" - -#include "mpp.h" -#include "mpp_dec.h" -#include "mpp_packet_impl.h" -#include "mpp_frame_impl.h" - -void *mpp_dec_parser_thread(void *data) -{ - Mpp *mpp = (Mpp*)data; - MppThread *parser = mpp->mThreadCodec; - MppDec *dec = mpp->mDec; - MppBufSlots slots = dec->slots; - HalTaskGroup tasks = dec->tasks; - MppPacketImpl packet; - - /* - * parser thread need to wait at cases below: - * 1. no task slot for output - * 2. no packet for parsing - * 3. info change on progress - * 3. no buffer on analyzing output task - */ - RK_U32 wait_on_packet = 0; - RK_U32 wait_on_task = 0; - RK_U32 wait_on_change = 0; - RK_U32 wait_on_buffer = 0; - - RK_U32 packet_ready = 0; - RK_U32 task_ready = 0; - - HalTask task_local; - HalDecTask *task_dec = &task_local.dec; - - while (MPP_THREAD_RUNNING == parser->get_status()) { - /* - * wait for stream input - */ - parser->lock(); - if (wait_on_task || wait_on_packet || wait_on_change || wait_on_buffer) - parser->wait(); - parser->unlock(); - - /* - * 1. get task handle from hal for parsing one frame - */ - wait_on_task = (MPP_OK != hal_task_can_put(tasks)); - if (wait_on_task) - continue; - - /* - * 2. get packet to parse - */ - if (!packet_ready) { - mpp_list *packets = mpp->mPackets; - Mutex::Autolock autoLock(packets->mutex()); - if (packets->list_size()) { - /* - * packet will be destroyed outside, here just copy the content - */ - packets->del_at_head(&packet, sizeof(packet)); - mpp->mPacketGetCount++; - packet_ready = 1; - wait_on_packet = 0; - } else { - wait_on_packet = 1; - continue; - } - } - - /* - * 3. send packet data to parser - * - * parser functioin input / output - * input: packet data - * output: dec task output information (with dxva output slot) - * buffer slot usage informatioin - * - * NOTE: - * 1. dpb slot will be set internally in parser process. - * 2. parse function need to set valid flag when one frame is ready. - * 3. if packet size is zero then next packet is needed. - * - */ - if (!task_ready) { - hal_task_init(&task_local, MPP_CTX_DEC); - parser_parse(dec->parser, (MppPacket)&packet, task_dec); - if (0 == packet.size) { - mpp_packet_reset(&packet); - packet_ready = 0; - } - } - - task_ready = task_dec->valid; - if (!task_ready) - continue; - - /* - * 4. parse local task and slot to check whether new buffer or info change is needed. - * - * a. first detect info change - * b. then detect whether output index has MppBuffer - */ - wait_on_change = mpp_buf_slot_is_changed(slots); - if (wait_on_change) - continue; - - /* - * 5. do buffer operation according to usage information - * - * possible case: - * a. normal case - * - wait and alloc a normal frame buffer - * b. field mode case - * - two field may reuse a same buffer, no need to alloc - * c. info change case - * - need buffer in different side, need to send a info change - * frame to hal loop. - */ - RK_U32 output; - mpp_buf_slot_get_hw_dst(slots, &output); - if (NULL == mpp_buf_slot_get_buffer(slots, output)) { - MppBuffer buffer = NULL; - RK_U32 size = mpp_buf_slot_get_size(slots); - mpp_buffer_get(mpp->mFrameGroup, &buffer, size); - if (buffer) - mpp_buf_slot_set_buffer(slots, output, buffer); - } - - wait_on_buffer = (NULL == mpp_buf_slot_get_buffer(slots, output)); - if (wait_on_buffer) - continue; - - /* - * 6. send dxva output information and buffer information to hal thread - * combinate video codec dxva output and buffer information - */ - hal_task_put(tasks, &task_local); - mpp->mTaskPutCount++; - - task_ready = 0; - mpp->mThreadHal->signal(); - } - - return NULL; -} - -void *mpp_dec_hal_thread(void *data) -{ - Mpp *mpp = (Mpp*)data; - MppThread *hal = mpp->mThreadHal; - MppDec *dec = mpp->mDec; - MppBufSlots slots = dec->slots; - HalTaskGroup tasks = dec->tasks; - mpp_list *frames = mpp->mFrames; - - /* - * hal thread need to wait at cases below: - * 1. no task slot for work - */ - RK_U32 wait_on_task = 0; - - HalTask task_local; - HalDecTask *task_dec = &task_local.dec; - memset(&task_local, 0, sizeof(task_local)); - - while (MPP_THREAD_RUNNING == hal->get_status()) { - /* - * hal thread wait for dxva interface intput firt - */ - hal->lock(); - if (wait_on_task) - hal->wait(); - hal->unlock(); - - // get hw task first - wait_on_task = (MPP_OK != hal_task_can_get(tasks)); - if (wait_on_task) - continue; - - mpp->mTaskGetCount++; - - hal_task_get(tasks, &task_local); - - // register genertation - mpp_hal_reg_gen(dec->hal, &task_local); - mpp->mThreadCodec->signal(); - - /* - * wait previous register set done - */ - //mpp_hal_hw_wait(dec->hal_ctx, &task_local); - - /* - * send current register set to hardware - */ - //mpp_hal_hw_start(dec->hal_ctx, &task_local); - - mpp_hal_hw_start(dec->hal, &task_local); - mpp_hal_hw_wait(dec->hal, &task_local); - - /* - * when hardware decoding is done: - * 1. clear decoding flag (mark buffer is ready) - * 2. use get_display to get a new frame with buffer - * 3. add frame to output list - * repeat 2 and 3 until not frame can be output - */ - mpp_buf_slot_clr_hw_dst(slots, task_dec->output); - for (RK_U32 i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) { - RK_S32 index = task_dec->refer[i]; - if (index >= 0) - mpp_buf_slot_dec_hw_ref(slots, index); - } - - MppFrame frame = NULL; - while (MPP_OK == mpp_buf_slot_get_display(slots, &frame)) { - frames->lock(); - frames->add_at_tail(&frame, sizeof(frame)); - mpp->mFramePutCount++; - frames->signal(); - frames->unlock(); - } - } - - return NULL; -} - -MPP_RET mpp_dec_init(MppDec **dec, MppCodingType coding) -{ - MPP_RET ret; - MppBufSlots slots = NULL; - Parser parser = NULL; - MppHal hal = NULL; - - MppDec *p = mpp_calloc(MppDec, 1); - if (NULL == p) { - mpp_err_f("failed to malloc context\n"); - return MPP_ERR_NULL_PTR; - } - - do { - ret = mpp_buf_slot_init(&slots); - if (ret) { - mpp_err_f("could not init buffer slot\n"); - break; - } - - ParserCfg parser_cfg = { - coding, - slots, - 2, - }; - - ret = parser_init(&parser, &parser_cfg); - if (ret) { - mpp_err_f("could not init parser\n"); - break; - } - - // then init hal with task count from parser - MppHalCfg hal_cfg = { - MPP_CTX_DEC, - coding, - HAL_MODE_LIBVPU, - p->slots, - NULL, - parser_cfg.task_count, - }; - - ret = mpp_hal_init(&hal, &hal_cfg); - if (ret) { - mpp_err_f("could not init hal\n"); - break; - } - - p->coding = coding; - p->parser = parser; - p->hal = hal; - p->slots = slots; - p->tasks = hal_cfg.tasks; - *dec = p; - return MPP_OK; - } while (0); - - mpp_dec_deinit(p); - *dec = NULL; - return MPP_NOK; -} - -MPP_RET mpp_dec_deinit(MppDec *dec) -{ - if (NULL == dec) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - if (dec->parser) { - parser_deinit(dec->parser); - dec->parser = NULL; - } - - if (dec->hal) { - mpp_hal_deinit(dec->hal); - dec->hal = NULL; - } - - if (dec->slots) { - mpp_buf_slot_deinit(dec->slots); - dec->slots = NULL; - } - - mpp_free(dec); - return MPP_OK; -} - -MPP_RET mpp_dec_reset(MppDec *dec) -{ - if (NULL == dec) { - mpp_err_f("found NULL input dec %p\n", dec); - return MPP_ERR_NULL_PTR; - } - - parser_reset(dec->parser); - mpp_hal_reset(dec->hal); - - return MPP_OK; -} - -MPP_RET mpp_dec_flush(MppDec *dec) -{ - if (NULL == dec) { - mpp_err_f("found NULL input dec %p\n", dec); - return MPP_ERR_NULL_PTR; - } - - parser_flush(dec->parser); - mpp_hal_flush(dec->hal); - - return MPP_OK; -} - -MPP_RET mpp_dec_control(MppDec *dec, RK_S32 cmd, void *param) -{ - if (NULL == dec) { - mpp_err_f("found NULL input dec %p\n", dec); - return MPP_ERR_NULL_PTR; - } - - parser_control(dec->parser, cmd, param); - mpp_hal_control(dec->hal, cmd, param); - - return MPP_OK; -} - diff --git a/mpp/codec/mpp_dec_debug.h b/mpp/codec/mpp_dec_debug.h new file mode 100644 index 000000000..1bfb60d13 --- /dev/null +++ b/mpp/codec/mpp_dec_debug.h @@ -0,0 +1,40 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_DEC_DEBUG_H +#define MPP_DEC_DEBUG_H + +#include "mpp_debug.h" + +#define MPP_DEC_DBG_FUNCTION (0x00000001) +#define MPP_DEC_DBG_TIMING (0x00000002) +#define MPP_DEC_DBG_STATUS (0x00000010) +#define MPP_DEC_DBG_DETAIL (0x00000020) +#define MPP_DEC_DBG_RESET (0x00000040) +#define MPP_DEC_DBG_NOTIFY (0x00000080) + +#define mpp_dec_dbg(flag, fmt, ...) mpp_dbg(mpp_dec_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_dec_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_dec_debug, flag, fmt, ## __VA_ARGS__) + +#define dec_dbg_func(fmt, ...) mpp_dec_dbg_f(MPP_DEC_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define dec_dbg_status(fmt, ...) mpp_dec_dbg_f(MPP_DEC_DBG_STATUS, fmt, ## __VA_ARGS__) +#define dec_dbg_detail(fmt, ...) mpp_dec_dbg_f(MPP_DEC_DBG_DETAIL, fmt, ## __VA_ARGS__) +#define dec_dbg_reset(fmt, ...) mpp_dec_dbg(MPP_DEC_DBG_RESET, fmt, ## __VA_ARGS__) +#define dec_dbg_notify(fmt, ...) mpp_dec_dbg_f(MPP_DEC_DBG_NOTIFY, fmt, ## __VA_ARGS__) + +extern RK_U32 mpp_dec_debug; + +#endif /* MPP_DEC_DEBUG_H */ diff --git a/mpp/codec/mpp_dec_no_thread.c b/mpp/codec/mpp_dec_no_thread.c new file mode 100644 index 000000000..95ad81027 --- /dev/null +++ b/mpp/codec/mpp_dec_no_thread.c @@ -0,0 +1,454 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dec_nt" + +#include + +#include "mpp_buffer_impl.h" + +#include "mpp_dec_debug.h" +#include "mpp_dec_vproc.h" +#include "mpp_dec_no_thread.h" +#include "rk_hdr_meta_com.h" + +MPP_RET mpp_dec_decode(MppDec ctx, MppPacket packet) +{ + MppDecImpl *dec = (MppDecImpl *)ctx; + Mpp *mpp = (Mpp *)dec->mpp; + DecTask *task = (DecTask *)dec->task_single; + DecTaskStatus *status = &task->status; + MppBufSlots frame_slots = dec->frame_slots; + MppBufSlots packet_slots = dec->packet_slots; + HalDecTask *task_dec = &task->info.dec; + MppMutexCond *cmd_lock = &dec->cmd_lock; + MppPacket input = dec->mpp_pkt_in; + size_t stream_size = 0; + RK_S32 output = 0; + RK_U32 i; + + mpp_mutex_cond_lock(cmd_lock); + + /* + * 1. task no ready and last packet is done try process new input packet + */ + if (input == NULL && !status->curr_task_rdy) { + input = packet; + + if (input == NULL) { + mpp_mutex_cond_unlock(cmd_lock); + return MPP_OK; + } + } + + if (input) + dec_dbg_detail("detail: %p input pkt %p len %d task ready %d\n", dec, + input, mpp_packet_get_length(input), status->curr_task_rdy); + else + dec_dbg_detail("detail: %p input pkt NULL task ready %d\n", dec, + input, status->curr_task_rdy); + + /* + * 2. prepare stream to generate task + */ + if (!status->curr_task_rdy) { + mpp_parser_prepare(dec->parser, input, task_dec); + + dec_dbg_detail("detail: %p prepare pkt %p get task %d\n", dec, + input, task_dec->valid); + + /* record remaining packet */ + if (task_dec->valid) { + status->curr_task_rdy = 1; + dec->mpp_pkt_in = input; + } + + if (input && !mpp_packet_get_length(input)) + dec->mpp_pkt_in = NULL; + } + + /* + * 3. when task not ready check eos empty task + */ + if (!status->curr_task_rdy) { + if (task_dec->flags.eos) { + mpp_dec_flush(dec); + output += mpp_dec_push_display(mpp, task_dec->flags); + /* + * Use -1 as invalid buffer slot index. + * Reason: the last task maybe is a empty task with eos flag + * only but this task may go through vproc process also. We need + * create a buffer slot index for it. + */ + mpp_dec_put_frame(mpp, -1, task_dec->flags); + output++; + } + mpp_mutex_cond_unlock(cmd_lock); + return (MPP_RET)output; + } + + // NOTE: packet in task should be ready now + mpp_assert(task_dec->input_packet); + + dec_dbg_detail("detail: %p hw pkt %p process start\n", dec, task_dec->input_packet); + + /* + * 4. look for a unused packet slot index + * 5. malloc hardware buffer for the packet slot index + */ + dec_dbg_detail("detail: %p hal_pkt_buf_in %p\n", dec, task->hal_pkt_buf_in); + if (!task->hal_pkt_buf_in) { + MppBuffer hal_buf_in = mpp_packet_get_buffer(task_dec->input_packet); + RK_S32 slot_pkt = -1; + + mpp_buf_slot_get_unused(packet_slots, &slot_pkt); + mpp_assert(slot_pkt >= 0); + stream_size = mpp_packet_get_size(task_dec->input_packet); + + if (NULL == hal_buf_in) { + mpp_buf_slot_get_prop(packet_slots, slot_pkt, SLOT_BUFFER, &hal_buf_in); + } else { + /* use external buffer and set to slot */ + task_dec->input_no_copy = 1; + + mpp_buf_slot_set_prop(packet_slots, slot_pkt, SLOT_BUFFER, hal_buf_in); + mpp_buffer_attach_dev(hal_buf_in, dec->dev); + } + + if (NULL == hal_buf_in) { + mpp_buffer_get(mpp->mPacketGroup, &hal_buf_in, stream_size); + if (hal_buf_in) { + mpp_buf_slot_set_prop(packet_slots, slot_pkt, SLOT_BUFFER, hal_buf_in); + mpp_buffer_attach_dev(hal_buf_in, dec->dev); + mpp_buffer_put(hal_buf_in); + } + } else { + MppBufferImpl *buf = (MppBufferImpl *)hal_buf_in; + mpp_assert(buf->info.size >= stream_size); + } + + dec_dbg_detail("detail: %p hw pkt %p get buf %p slot %d\n", dec, + task_dec->input_packet, hal_buf_in, slot_pkt); + + task_dec->input = slot_pkt; + task->hal_pkt_buf_in = hal_buf_in; + } + + /* + * 6. copy data to hardware buffer + */ + if (!status->dec_pkt_copy_rdy) { + if (!task_dec->input_no_copy) { + void *src = mpp_packet_get_data(task_dec->input_packet); + size_t length = mpp_packet_get_length(task_dec->input_packet); + + mpp_assert(task->hal_pkt_buf_in); + mpp_assert(task_dec->input_packet); + + dec_dbg_detail("detail: %p copy to hw length %d\n", dec, length); + mpp_buffer_write(task->hal_pkt_buf_in, 0, src, length); + mpp_buffer_sync_partial_end(task->hal_pkt_buf_in, 0, length); + + } + + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY); + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + + status->dec_pkt_copy_rdy = 1; + } + + /* + * 7. parse the stream in input buffer and generate task + */ + if (!status->task_parsed_rdy) { + mpp_clock_start(dec->clocks[DEC_PRS_PARSE]); + mpp_parser_parse(dec->parser, task_dec); + mpp_clock_pause(dec->clocks[DEC_PRS_PARSE]); + status->task_parsed_rdy = 1; + + /* add extra output slot operaton for jpeg decoding */ + if (task_dec->input_no_copy && task_dec->output >= 0) { + mpp_buf_slot_set_flag(frame_slots, task_dec->output, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(frame_slots, task_dec->output, QUEUE_DISPLAY); + } + } + + dec_dbg_detail("detail: %p parse output slot %d valid %d\n", dec, + task_dec->output, task_dec->valid); + /* + * 8. check task generate failure + */ + if (task_dec->output < 0 || !task_dec->valid) { + /* + * We may meet an eos in parser step and there will be no anymore vaild + * task generated. So here we try push eos task to hal, hal will push + * all frame(s) to display, a frame of them with a eos flag will be + * used to inform that all frame have decoded + */ + if (task_dec->flags.eos) { + mpp_dec_flush(dec); + output += mpp_dec_push_display(mpp, task_dec->flags); + } + + if (status->dec_pkt_copy_rdy) { + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + status->dec_pkt_copy_rdy = 0; + } + status->curr_task_rdy = 0; + status->task_parsed_rdy = 0; + dec_task_info_init(&task->info); + task->hal_pkt_buf_in = NULL; + + dec_dbg_detail("detail: %p parse return no task with output %d\n", dec, output); + mpp_mutex_cond_unlock(cmd_lock); + return (MPP_RET)output; + } + dec_dbg_detail("detail: %p check output index pass\n", dec); + + /* + * 9. parse local task and slot to check whether new buffer or info change is needed. + * + * detect info change from frame slot + */ + if (mpp_buf_slot_is_changed(frame_slots)) { + if (!status->info_task_gen_rdy) { + RK_U32 eos = task_dec->flags.eos; + // NOTE: info change should not go with eos flag + task_dec->flags.info_change = 1; + task_dec->flags.eos = 0; + mpp_dec_flush(dec); + output += mpp_dec_push_display(mpp, task_dec->flags); + mpp_dec_put_frame(mpp, task_dec->output, task_dec->flags); + output++; + task_dec->flags.eos = eos; + status->info_task_gen_rdy = 1; + dec_dbg_detail("detail: %p info change found return frame %d\n", + dec, output); + mpp_mutex_cond_unlock(cmd_lock); + return (MPP_RET)output; + } + dec->info_updated = 0; + } + + task->wait.info_change = mpp_buf_slot_is_changed(frame_slots); + if (task->wait.info_change) { + mpp_mutex_cond_unlock(cmd_lock); + return MPP_OK; + } else { + status->info_task_gen_rdy = 0; + task_dec->flags.info_change = 0; + } + + /* 10. whether the frame buffer group is internal or external */ + if (NULL == mpp->mFrameGroup) { + mpp_log("mpp_dec use internal frame buffer group\n"); + mpp_buffer_group_get_internal(&mpp->mFrameGroup, MPP_BUFFER_TYPE_ION); + } + + /* 10.1 look for a unused hardware buffer for output */ + if (mpp->mFrameGroup) { + RK_S32 unused = mpp_buffer_group_unused(mpp->mFrameGroup); + + // NOTE: When dec post-process is enabled reserve 2 buffer for it. + task->wait.dec_pic_unusd = (dec->vproc) ? (unused < 3) : (unused < 1); + if (task->wait.dec_pic_unusd) { + mpp_mutex_cond_wait(cmd_lock); + /* return here and process all the flow again */ + mpp_mutex_cond_unlock(cmd_lock); + return MPP_OK; + } + } + dec_dbg_detail("detail: %p check frame group count pass\n", dec); + + /* if dec_task is reset quit decoding and mark current packet is done */ + if (task_dec->output < 0 || !task_dec->valid) + return MPP_OK; + + if (!task->hal_frm_buf_out) { + MppBuffer hal_buf_out = NULL; + + output = task_dec->output; + mpp_buf_slot_get_prop(frame_slots, output, SLOT_BUFFER, &hal_buf_out); + if (NULL == hal_buf_out) { + size_t size = mpp_buf_slot_get_size(frame_slots); + mpp_buffer_get(mpp->mFrameGroup, &hal_buf_out, size); + if (hal_buf_out) + mpp_buf_slot_set_prop(frame_slots, output, SLOT_BUFFER, + hal_buf_out); + } + if (!dec->info_updated && dec->dev) { + MppFrame slot_frm = NULL; + + mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &slot_frm); + update_dec_hal_info(dec, slot_frm); + dec->info_updated = 1; + } + + task->hal_frm_buf_out = hal_buf_out; + } + + { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + + if (MPP_FRAME_FMT_IS_HDR(mpp_frame_get_fmt(mframe)) && + dec->cfg->base.enable_hdr_meta) { + fill_hdr_meta_to_frame(mframe, dec->coding); + } + } + + task->wait.dec_pic_match = (NULL == task->hal_frm_buf_out); + if (task->wait.dec_pic_match) { + mpp_mutex_cond_unlock(cmd_lock); + return MPP_NOK; + } + + mpp_hal_reg_gen(dec->hal, &task->info); + mpp_hal_hw_start(dec->hal, &task->info); + mpp_hal_hw_wait(dec->hal, &task->info); + dec->dec_hw_run_count++; + + /* + * when hardware decoding is done: + * 1. clear decoding flag (mark buffer is ready) + * 2. use get_display to get a new frame with buffer + * 3. add frame to output list + * repeat 2 and 3 until not frame can be output + */ + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + + if (task_dec->output >= 0) + mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT); + + for (i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) { + RK_S32 index = task_dec->refer[i]; + if (index >= 0) + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT); + } + if (task_dec->flags.eos) + mpp_dec_flush(dec); + + output += mpp_dec_push_display(mpp, task_dec->flags); + + status->dec_pkt_copy_rdy = 0; + status->curr_task_rdy = 0; + status->task_parsed_rdy = 0; + status->prev_task_rdy = 0; + dec_task_info_init(&task->info); + task->hal_pkt_buf_in = NULL; + task->hal_frm_buf_out = NULL; + mpp_mutex_cond_unlock(cmd_lock); + + return (MPP_RET)output; +} + +MPP_RET mpp_dec_reset_no_thread(MppDecImpl *dec) +{ + DecTask *task = (DecTask *)dec->task_single; + MppBufSlots frame_slots = dec->frame_slots; + MppMutexCond *cmd_lock = &dec->cmd_lock; + HalDecTask *task_dec = &task->info.dec; + RK_S32 index; + RK_U32 i; + + mpp_mutex_cond_lock(cmd_lock); + + task->status.curr_task_rdy = 0; + task->status.prev_task_rdy = 1; + task_dec->valid = 0; + mpp_parser_reset(dec->parser); + mpp_hal_reset(dec->hal); + if (dec->vproc) { + dec_dbg_reset("reset: vproc reset start\n"); + dec_vproc_reset(dec->vproc); + dec_dbg_reset("reset: vproc reset done\n"); + } + + // wait hal thread reset ready + if (task->wait.info_change) { + mpp_log("reset at info change status\n"); + mpp_buf_slot_reset(frame_slots, task_dec->output); + } + + if (task->status.task_parsed_rdy) { + mpp_log("task no send to hal que must clr current frame hal status\n"); + mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT); + for (i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) { + index = task_dec->refer[i]; + if (index >= 0) + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT); + } + task->status.task_parsed_rdy = 0; + } + + while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) { + /* release extra ref in slot's MppBuffer */ + MppBuffer buffer = NULL; + + mpp_buf_slot_get_prop(frame_slots, index, SLOT_BUFFER, &buffer); + if (buffer) + mpp_buffer_put(buffer); + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE); + } + + if (task->status.dec_pkt_copy_rdy) { + mpp_buf_slot_clr_flag(dec->packet_slots, task_dec->input, SLOT_HAL_INPUT); + mpp_buf_slot_clr_flag(dec->packet_slots, task_dec->input, SLOT_CODEC_READY); + task->status.dec_pkt_copy_rdy = 0; + task->hal_pkt_buf_in = NULL; + task_dec->input = -1; + } + + // external packet release by user + dec->mpp_pkt_in = NULL; + + task->status.task_parsed_rdy = 0; + dec_task_init(task); + + dec_dbg_reset("reset: parser reset all done\n"); + + dec->dec_in_pkt_count = 0; + dec->dec_hw_run_count = 0; + dec->dec_out_frame_count = 0; + dec->info_updated = 0; + + mpp_mutex_cond_signal(cmd_lock); + mpp_mutex_cond_unlock(cmd_lock); + + return MPP_OK; +} + +MPP_RET mpp_dec_notify_no_thread(MppDecImpl *dec, RK_U32 flag) +{ + // Only notify buffer group control + if (flag == (MPP_DEC_NOTIFY_BUFFER_VALID | MPP_DEC_NOTIFY_BUFFER_MATCH)) { + mpp_mutex_cond_signal(&dec->cmd_lock); + return MPP_OK; + } + + return MPP_OK; +} + +MPP_RET mpp_dec_control_no_thread(MppDecImpl *dec, MpiCmd cmd, void *param) +{ + // cmd_lock is used to sync all async operations + MPP_RET ret = MPP_NOK; + + mpp_mutex_cond_lock(&dec->cmd_lock); + dec->cmd_send++; + ret = mpp_dec_proc_cfg(dec, cmd, param); + mpp_mutex_cond_unlock(&dec->cmd_lock); + + return ret; +} + +MppDecModeApi dec_api_no_thread = { + NULL, + NULL, + mpp_dec_reset_no_thread, + mpp_dec_notify_no_thread, + mpp_dec_control_no_thread, +}; diff --git a/mpp/codec/mpp_dec_normal.c b/mpp/codec/mpp_dec_normal.c new file mode 100644 index 000000000..5ac5d22d7 --- /dev/null +++ b/mpp/codec/mpp_dec_normal.c @@ -0,0 +1,1250 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dec" + +#include + +#include "mpp_buffer_impl.h" + +#include "mpp_dec_debug.h" +#include "mpp_dec_vproc.h" +#include "mpp_dec_normal.h" +#include "rk_hdr_meta_com.h" + +static RK_S32 ts_cmp(void *priv, const struct list_head *a, const struct list_head *b) +{ + MppPktTs *ts1, *ts2; + (void)priv; + + ts1 = container_of(a, MppPktTs, link); + ts2 = container_of(b, MppPktTs, link); + + return ts1->pts - ts2->pts; +} + +/* + * return MPP_OK for not wait + * return MPP_NOK for wait + */ +static MPP_RET check_task_wait(MppDecImpl *dec, DecTask *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 notify = dec->parser_notify_flag; + RK_U32 last_wait = dec->parser_wait_flag; + RK_U32 curr_wait = task->wait.val; + RK_U32 wait_chg = last_wait & (~curr_wait); + RK_U32 keep_notify = 0; + + do { + if (dec->reset_flag) + break; + + // NOTE: User control should always be processed + if (notify & MPP_DEC_CONTROL) { + keep_notify = notify & (~MPP_DEC_CONTROL); + break; + } + + // NOTE: When condition is not fulfilled check nofify flag again + if (!curr_wait || (curr_wait & notify)) + break; + + // wait for condition + ret = MPP_NOK; + } while (0); + + dec_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", dec, + last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work")); + + dec->parser_status_flag = task->status.val; + dec->parser_wait_flag = task->wait.val; + dec->parser_notify_flag = keep_notify; + + if (ret) { + dec->parser_wait_count++; + } else { + dec->parser_work_count++; + } + + return ret; +} + +static MPP_RET dec_release_task_in_port(MppPort port) +{ + MPP_RET ret = MPP_OK; + MppPacket packet = NULL; + MppFrame frame = NULL; + MppTask mpp_task; + + do { + ret = mpp_port_poll(port, MPP_POLL_NON_BLOCK); + if (ret < 0) + break; + + ret = mpp_port_dequeue(port, &mpp_task); + if (ret || mpp_task == NULL) + break; + + packet = NULL; + frame = NULL; + ret = mpp_task_meta_get_frame(mpp_task, KEY_OUTPUT_FRAME, &frame); + if (frame) { + mpp_frame_deinit(&frame); + frame = NULL; + } + ret = mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet); + if (packet && NULL == mpp_packet_get_buffer(packet)) { + mpp_packet_deinit(&packet); + packet = NULL; + } + + mpp_port_enqueue(port, mpp_task); + mpp_task = NULL; + } while (1); + + return ret; +} + +static void dec_release_input_packet(MppDecImpl *dec, RK_S32 force) +{ + if (dec->mpp_pkt_in) { + if (force || 0 == mpp_packet_get_length(dec->mpp_pkt_in)) { + mpp_packet_deinit(&dec->mpp_pkt_in); + + mpp_dec_callback(dec, MPP_DEC_EVENT_ON_PKT_RELEASE, dec->mpp_pkt_in); + dec->mpp_pkt_in = NULL; + } + } +} + +static RK_U32 reset_parser_thread(Mpp *mpp, DecTask *task) +{ + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppThread *hal = dec->thread_hal; + HalTaskGroup tasks = dec->tasks; + MppBufSlots frame_slots = dec->frame_slots; + MppBufSlots packet_slots = dec->packet_slots; + HalDecTask *task_dec = &task->info.dec; + + dec_dbg_reset("reset: parser reset start\n"); + dec_dbg_reset("reset: parser wait hal proc reset start\n"); + + dec_release_task_in_port(mpp->mMppInPort); + + mpp_assert(hal); + + mpp_thread_lock(hal, THREAD_WORK); + dec->hal_reset_post++; + mpp_thread_signal(hal, THREAD_WORK); + mpp_thread_unlock(hal, THREAD_WORK); + + sem_wait(&dec->hal_reset); + + dec_dbg_reset("reset: parser check hal proc task empty start\n"); + + if (hal_task_check_empty(tasks, TASK_PROCESSING)) { + mpp_err_f("found task not processed put %d get %d\n", + mpp->mTaskPutCount, mpp->mTaskGetCount); + mpp_abort(); + } + + dec_dbg_reset("reset: parser check hal proc task empty done\n"); + + // do parser reset process + { + RK_S32 index; + RK_U32 i; + + task->status.curr_task_rdy = 0; + task->status.prev_task_rdy = 1; + task_dec->valid = 0; + mpp_parser_reset(dec->parser); + mpp_hal_reset(dec->hal); + if (dec->vproc) { + dec_dbg_reset("reset: vproc reset start\n"); + dec_vproc_reset(dec->vproc); + dec_dbg_reset("reset: vproc reset done\n"); + } + + if (task->status.task_parsed_rdy) { + mpp_log("task no send to hal que must clr current frame hal status\n"); + if (task_dec->output >= 0) + mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT); + + for (i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) { + index = task_dec->refer[i]; + if (index >= 0) + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT); + } + task->status.task_parsed_rdy = 0; + } + + dec_release_input_packet(dec, 1); + + while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) { + /* release extra ref in slot's MppBuffer */ + MppBuffer buffer = NULL; + mpp_buf_slot_get_prop(frame_slots, index, SLOT_BUFFER, &buffer); + if (buffer) + mpp_buffer_put(buffer); + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE); + } + + if (dec->cfg->base.sort_pts) { + // flush + MppPktTs *ts, *pos; + + mpp_spinlock_lock(&dec->ts_lock); + list_for_each_entry_safe(ts, pos, &dec->ts_link, MppPktTs, link) { + list_del_init(&ts->link); + mpp_mem_pool_put_f(dec->ts_pool, ts); + } + mpp_spinlock_unlock(&dec->ts_lock); + } + + if (task->status.dec_pkt_copy_rdy) { + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + task->status.dec_pkt_copy_rdy = 0; + task_dec->input = -1; + } + + // wait hal thread reset ready + if (task->wait.info_change) + mpp_log("reset at info change\n"); + + task->status.task_parsed_rdy = 0; + // IMPORTANT: clear flag in MppDec context + dec->parser_status_flag = 0; + dec->parser_wait_flag = 0; + } + + dec_task_init(task); + + dec_dbg_reset("reset: parser reset all done\n"); + + return MPP_OK; +} + +static void mpp_dec_put_task(Mpp *mpp, DecTask *task) +{ + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + + hal_task_hnd_set_info(task->hnd, &task->info); + mpp_thread_lock(dec->thread_hal, THREAD_WORK); + hal_task_hnd_set_status(task->hnd, TASK_PROCESSING); + mpp->mTaskPutCount++; + mpp_thread_signal(dec->thread_hal, THREAD_WORK); + mpp_thread_unlock(dec->thread_hal, THREAD_WORK); + task->hnd = NULL; +} + +static void reset_hal_thread(Mpp *mpp) +{ + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + HalTaskGroup tasks = dec->tasks; + MppBufSlots frame_slots = dec->frame_slots; + HalDecTaskFlag flag; + RK_S32 index = -1; + HalTaskHnd task = NULL; + + /* when hal thread reset output all frames */ + flag.val = 0; + mpp_dec_flush(dec); + + mpp_thread_lock(dec->thread_hal, THREAD_OUTPUT); + while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) { + mpp_dec_put_frame(mpp, index, flag); + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE); + } + + // Need to set processed task to idle status + while (MPP_OK == hal_task_get_hnd(tasks, TASK_PROC_DONE, &task)) { + if (task) { + hal_task_hnd_set_status(task, TASK_IDLE); + task = NULL; + } + } + + mpp_thread_unlock(dec->thread_hal, THREAD_OUTPUT); +} + +static MPP_RET try_get_input_packet(Mpp *mpp, DecTask *task) +{ + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppPort input = mpp->mMppInPort; + MppTask mpp_task = NULL; + MppPacket packet = NULL; + MPP_RET ret = MPP_OK; + + ret = mpp_port_poll(input, MPP_POLL_NON_BLOCK); + if (ret < 0) { + task->wait.dec_pkt_in = 1; + return MPP_NOK; + } + + ret = mpp_port_dequeue(input, &mpp_task); + mpp_assert(ret == MPP_OK && mpp_task); + mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet); + mpp_assert(packet); + + /* when it is copy buffer return packet right here */ + if (NULL == mpp_packet_get_buffer(packet)) + mpp_port_enqueue(input, mpp_task); + + dec->mpp_pkt_in = packet; + mpp->mPacketGetCount++; + dec->dec_in_pkt_count++; + + task->status.mpp_pkt_in_rdy = 1; + task->wait.dec_pkt_in = 0; + + return MPP_OK; +} + +static MPP_RET try_proc_dec_task(Mpp *mpp, DecTask *task) +{ + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + HalTaskGroup tasks = dec->tasks; + MppBufSlots frame_slots = dec->frame_slots; + MppBufSlots packet_slots = dec->packet_slots; + HalDecTask *task_dec = &task->info.dec; + MppBuffer hal_buf_in = NULL; + MppBuffer hal_buf_out = NULL; + size_t stream_size = 0; + RK_S32 output = 0; + + /* + * 1. get task handle from hal for parsing one frame + */ + if (!task->hnd) { + hal_task_get_hnd(tasks, TASK_IDLE, &task->hnd); + if (task->hnd) { + task->wait.task_hnd = 0; + } else { + task->wait.task_hnd = 1; + return MPP_NOK; + } + } + + /* + * 2. get packet for parser preparing + */ + if (!dec->mpp_pkt_in && !task->status.curr_task_rdy) { + if (try_get_input_packet(mpp, task)) + return MPP_NOK; + + mpp_assert(dec->mpp_pkt_in); + + dec_dbg_detail("detail: %p get pkt pts %llu len %d\n", dec, + mpp_packet_get_pts(dec->mpp_pkt_in), + mpp_packet_get_length(dec->mpp_pkt_in)); + } + + /* + * 3. send packet data to parser for prepare + * + * mpp_parser_prepare functioin input / output + * input: input MppPacket data from user + * output: one packet which contains one frame for hardware processing + * output information will be stored in task_dec->input_packet + * output data can be stored inside of parser. + * + * NOTE: + * 1. Prepare process is controlled by need_split flag + * If need_split flag is zero prepare function is just copy the input + * packet to task_dec->input_packet + * If need_split flag is non-zero prepare function will call split function + * of different coding type and find the start and end of one frame. Then + * copy data to task_dec->input_packet + * 2. On need_split mode if one input MppPacket contain multiple frame for + * decoding one mpp_parser_prepare call will only frame for task. Then input + * MppPacket->pos/length will be updated. The input MppPacket will not be + * released until it is totally consumed. + * 3. On spliting frame if one frame contain multiple slices and these multiple + * slices have different pts/dts the output frame will use the last pts/dts + * as the output frame's pts/dts. + * + */ + if (!task->status.curr_task_rdy) { + sys_dbg_pts("input packet pts %lld\n", mpp_packet_get_pts(dec->mpp_pkt_in)); + + mpp_clock_start(dec->clocks[DEC_PRS_PREPARE]); + mpp_parser_prepare(dec->parser, dec->mpp_pkt_in, task_dec); + mpp_clock_pause(dec->clocks[DEC_PRS_PREPARE]); + if (dec->cfg->base.sort_pts && task_dec->valid) { + task->ts_cur.pts = mpp_packet_get_pts(dec->mpp_pkt_in); + task->ts_cur.dts = mpp_packet_get_dts(dec->mpp_pkt_in); + } + dec_release_input_packet(dec, 0); + } + + task->status.curr_task_rdy = task_dec->valid; + /* + * We may find eos in prepare step and there will be no anymore vaild task generated. + * So here we try push eos task to hal, hal will push all frame to display then + * push a eos frame to tell all frame decoded + */ + if (task_dec->flags.eos && !task_dec->valid) + mpp_dec_put_task(mpp, task); + + if (!task->status.curr_task_rdy) + return MPP_NOK; + + // NOTE: packet in task should be ready now + mpp_assert(task_dec->input_packet); + + /* + * 4. look for a unused packet slot index + */ + if (task_dec->input < 0) { + mpp_buf_slot_get_unused(packet_slots, &task_dec->input); + } + + task->wait.dec_pkt_idx = (task_dec->input < 0); + if (task->wait.dec_pkt_idx) + return MPP_NOK; + + /* + * 5. malloc hardware buffer for the packet slot index + */ + stream_size = mpp_packet_get_size(task_dec->input_packet); + + mpp_buf_slot_get_prop(packet_slots, task_dec->input, SLOT_BUFFER, &hal_buf_in); + if (NULL == hal_buf_in) { + mpp_buffer_get(mpp->mPacketGroup, &hal_buf_in, stream_size); + if (hal_buf_in) { + mpp_buf_slot_set_prop(packet_slots, task_dec->input, SLOT_BUFFER, hal_buf_in); + mpp_buffer_attach_dev(hal_buf_in, dec->dev); + mpp_buffer_put(hal_buf_in); + } + } else { + MppBufferImpl *buf = (MppBufferImpl *)hal_buf_in; + mpp_assert(buf->info.size >= stream_size); + } + + task->wait.dec_pkt_buf = (NULL == hal_buf_in); + if (task->wait.dec_pkt_buf) + return MPP_NOK; + + /* + * 6. copy prepared stream to hardware buffer + */ + if (!task->status.dec_pkt_copy_rdy) { + void *src = mpp_packet_get_data(task_dec->input_packet); + size_t length = mpp_packet_get_length(task_dec->input_packet); + + mpp_buffer_write(hal_buf_in, 0, src, length); + mpp_buffer_sync_partial_end(hal_buf_in, 0, length); + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY); + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + task->status.dec_pkt_copy_rdy = 1; + + // Sync parser to release zero-copy data after hardware copy is done + mpp_parser_sync(dec->parser, task_dec->input); + } + + /* 7.1 if not fast mode wait previous task done here */ + if (!dec->parser_fast_mode) { + // wait previous task done + if (!task->status.prev_task_rdy) { + HalTaskHnd task_prev = NULL; + hal_task_get_hnd(tasks, TASK_PROC_DONE, &task_prev); + if (task_prev) { + task->status.prev_task_rdy = 1; + task->wait.prev_task = 0; + hal_task_hnd_set_status(task_prev, TASK_IDLE); + task_prev = NULL; + } else { + task->wait.prev_task = 1; + return MPP_NOK; + } + } + } + + // for vp9 only wait all task is processed + if (task->wait.dec_all_done) { + if (!hal_task_check_empty(dec->tasks, TASK_PROCESSING)) + task->wait.dec_all_done = 0; + else + return MPP_NOK; + } + + dec_dbg_detail("detail: %p check prev task pass\n", dec); + + /* too many frame delay in dispaly queue */ + if (mpp->mFrmOut) { + task->wait.dis_que_full = (mpp_list_size(mpp->mFrmOut) > 4) ? 1 : 0; + if (task->wait.dis_que_full) + return MPP_ERR_DISPLAY_FULL; + } + dec_dbg_detail("detail: %p check mframes pass\n", dec); + + /* 7.3 wait for a unused slot index for decoder parse operation */ + task->wait.dec_slot_idx = (mpp_slots_get_unused_count(frame_slots) != 0) ? (0) : (1); + if (task->wait.dec_slot_idx) + return MPP_ERR_BUFFER_FULL; + + /* + * 8. send packet data to parser + * + * parser prepare functioin input / output + * input: packet data + * output: dec task output information (with dxva output slot) + * buffer slot usage informatioin + * + * NOTE: + * 1. dpb slot will be set internally in parser process. + * 2. parse function need to set valid flag when one frame is ready. + * 3. if packet size is zero then next packet is needed. + * 4. detect whether output index has MppBuffer and task valid + */ + if (!task->status.task_parsed_rdy) { + mpp_clock_start(dec->clocks[DEC_PRS_PARSE]); + mpp_parser_parse(dec->parser, task_dec); + mpp_clock_pause(dec->clocks[DEC_PRS_PARSE]); + task->status.task_parsed_rdy = 1; + } + + if (task_dec->output < 0 || !task_dec->valid) { + /* + * We may meet an eos in parser step and there will be no anymore vaild + * task generated. So here we try push eos task to hal, hal will push + * all frame(s) to display, a frame of them with a eos flag will be + * used to inform that all frame have decoded + */ + if (task_dec->flags.eos) { + mpp_dec_put_task(mpp, task); + } else { + hal_task_hnd_set_status(task->hnd, TASK_IDLE); + task->hnd = NULL; + } + + if (task->status.dec_pkt_copy_rdy) { + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + task->status.dec_pkt_copy_rdy = 0; + } + task->status.curr_task_rdy = 0; + task->status.task_parsed_rdy = 0; + dec_task_info_init(&task->info); + return MPP_NOK; + } + dec_dbg_detail("detail: %p check output index pass\n", dec); + + /* + * 9. parse local task and slot to check whether new buffer or info change is needed. + * + * detect info change from frame slot + */ + if (mpp_buf_slot_is_changed(frame_slots)) { + if (!task->status.info_task_gen_rdy) { + RK_U32 eos = task_dec->flags.eos; + + // NOTE: info change should not go with eos flag + task_dec->flags.info_change = 1; + task_dec->flags.eos = 0; + mpp_dec_put_task(mpp, task); + task_dec->flags.eos = eos; + + task->status.info_task_gen_rdy = 1; + return MPP_ERR_STREAM; + } + dec->info_updated = 0; + } + + task->wait.info_change = mpp_buf_slot_is_changed(frame_slots); + if (task->wait.info_change) { + return MPP_ERR_STREAM; + } else { + task->status.info_task_gen_rdy = 0; + task_dec->flags.info_change = 0; + // NOTE: check the task must be ready + mpp_assert(task->hnd); + } + + /* 10. whether the frame buffer group is internal or external */ + if (NULL == mpp->mFrameGroup) { + mpp_log("mpp_dec use internal frame buffer group\n"); + mpp_buffer_group_get_internal(&mpp->mFrameGroup, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE); + } + + /* 10.1 look for a unused hardware buffer for output */ + if (mpp->mFrameGroup) { + RK_S32 unused = mpp_buffer_group_unused(mpp->mFrameGroup); + + // NOTE: When dec post-process is enabled reserve 2 buffer for it. + task->wait.dec_pic_unusd = (dec->vproc) ? (unused < 3) : (unused < 1); + if (task->wait.dec_pic_unusd) + return MPP_ERR_BUFFER_FULL; + } + dec_dbg_detail("detail: %p check frame group count pass\n", dec); + + /* + * 11. do buffer operation according to usage information + * + * possible case: + * a. normal case + * - wait and alloc(or fetch) a normal frame buffer + * b. field mode case + * - two field may reuse a same buffer, no need to alloc + * c. info change case + * - need buffer in different side, need to send a info change + * frame to hal loop. + */ + output = task_dec->output; + mpp_buf_slot_get_prop(frame_slots, output, SLOT_BUFFER, &hal_buf_out); + if (NULL == hal_buf_out) { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(frame_slots, output, + SLOT_FRAME_PTR, &mframe); + size_t size = mpp_buf_slot_get_size(frame_slots); + + if (mframe && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + // only for 8K thumbnail downscale to 4K 8bit mode + RK_U32 downscale_width = mpp_frame_get_width(mframe) / 2; + RK_U32 downscale_height = mpp_frame_get_height(mframe) / 2; + + size = downscale_width * downscale_height * 3 / 2; + } + mpp_buffer_get(mpp->mFrameGroup, &hal_buf_out, size); + if (hal_buf_out) + mpp_buf_slot_set_prop(frame_slots, output, SLOT_BUFFER, + hal_buf_out); + } + + dec_dbg_detail("detail: %p check output buffer %p\n", dec, hal_buf_out); + + { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &mframe); + + if (MPP_FRAME_FMT_IS_HDR(mpp_frame_get_fmt(mframe)) && + dec->cfg->base.enable_hdr_meta) { + fill_hdr_meta_to_frame(mframe, dec->coding); + } + } + + // update codec info + if (!dec->info_updated && dec->dev) { + MppFrame frame = NULL; + + mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &frame); + update_dec_hal_info(dec, frame); + dec->info_updated = 1; + } + + task->wait.dec_pic_match = (NULL == hal_buf_out); + if (task->wait.dec_pic_match) + return MPP_NOK; + + if (dec->cfg->base.sort_pts) { + MppFrame frame = NULL; + MppPktTs *pkt_ts = (MppPktTs *)mpp_mem_pool_get_f(dec->ts_pool); + + mpp_assert(pkt_ts); + mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &frame); + pkt_ts->pts = task->ts_cur.pts; + pkt_ts->dts = task->ts_cur.dts; + INIT_LIST_HEAD(&pkt_ts->link); + if (frame && mpp_frame_get_pts(frame) == pkt_ts->pts) { + mpp_spinlock_lock(&dec->ts_lock); + list_add_tail(&pkt_ts->link, &dec->ts_link); + list_sort(NULL, &dec->ts_link, ts_cmp); + mpp_spinlock_unlock(&dec->ts_lock); + } + } + + /* generating registers table */ + mpp_clock_start(dec->clocks[DEC_HAL_GEN_REG]); + mpp_hal_reg_gen(dec->hal, &task->info); + mpp_clock_pause(dec->clocks[DEC_HAL_GEN_REG]); + + /* send current register set to hardware */ + mpp_clock_start(dec->clocks[DEC_HW_START]); + mpp_hal_hw_start(dec->hal, &task->info); + mpp_clock_pause(dec->clocks[DEC_HW_START]); + + /* + * 12. send dxva output information and buffer information to hal thread + * combinate video codec dxva output and buffer information + */ + mpp_dec_put_task(mpp, task); + + task->wait.dec_all_done = (dec->parser_fast_mode && + task_dec->flags.wait_done) ? 1 : 0; + + task->status.dec_pkt_copy_rdy = 0; + task->status.curr_task_rdy = 0; + task->status.task_parsed_rdy = 0; + task->status.prev_task_rdy = 0; + dec_task_info_init(&task->info); + + dec_dbg_detail("detail: %p one task ready\n", dec); + + return MPP_OK; +} + +void *mpp_dec_parser_thread(void *data) +{ + Mpp *mpp = (Mpp*)data; + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppThread *parser = dec->thread_parser; + MppBufSlots packet_slots = dec->packet_slots; + + DecTask task; + HalDecTask *task_dec = &task.info.dec; + + dec_task_init(&task); + + mpp_clock_start(dec->clocks[DEC_PRS_TOTAL]); + + while (1) { + mpp_thread_lock(parser, THREAD_WORK); + if (MPP_THREAD_RUNNING != mpp_thread_get_status(parser, THREAD_WORK)) { + mpp_thread_unlock(parser, THREAD_WORK); + break; + } + + /* + * parser thread need to wait at cases below: + * 1. no task slot for output + * 2. no packet for parsing + * 3. info change on progress + * 3. no buffer on analyzing output task + */ + if (check_task_wait(dec, &task)) { + mpp_clock_start(dec->clocks[DEC_PRS_WAIT]); + mpp_thread_wait(parser, THREAD_WORK); + mpp_clock_pause(dec->clocks[DEC_PRS_WAIT]); + } + mpp_thread_unlock(parser, THREAD_WORK); + + // process user control + if (dec->cmd_send != dec->cmd_recv) { + dec_dbg_detail("ctrl proc %d cmd %08x\n", dec->cmd_recv, dec->cmd); + sem_wait(&dec->cmd_start); + *dec->cmd_ret = mpp_dec_proc_cfg(dec, dec->cmd, dec->param); + dec->cmd_recv++; + dec_dbg_detail("ctrl proc %d done send %d\n", dec->cmd_recv, + dec->cmd_send); + mpp_assert(dec->cmd_send == dec->cmd_send); + dec->param = NULL; + dec->cmd = (MpiCmd)0; + dec->cmd_ret = NULL; + sem_post(&dec->cmd_done); + continue; + } + + if (dec->reset_flag) { + reset_parser_thread(mpp, &task); + + mpp_thread_lock(parser, THREAD_CONTROL); + dec->reset_flag = 0; + sem_post(&dec->parser_reset); + mpp_thread_unlock(parser, THREAD_CONTROL); + continue; + } + + // NOTE: ignore return value here is to fast response to reset. + // Otherwise we can loop all dec task until it is failed. + mpp_clock_start(dec->clocks[DEC_PRS_PROC]); + try_proc_dec_task(mpp, &task); + mpp_clock_pause(dec->clocks[DEC_PRS_PROC]); + } + + mpp_clock_pause(dec->clocks[DEC_PRS_TOTAL]); + + sys_dbg_info("mpp_dec_parser_thread is going to exit\n"); + if (task.hnd && task_dec->valid) { + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY); + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + } + mpp_buffer_group_clear(mpp->mPacketGroup); + dec_release_task_in_port(mpp->mMppInPort); + sys_dbg_info("mpp_dec_parser_thread exited\n"); + return NULL; +} + +void *mpp_dec_hal_thread(void *data) +{ + Mpp *mpp = (Mpp*)data; + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppThread *hal = dec->thread_hal; + HalTaskGroup tasks = dec->tasks; + MppBufSlots frame_slots = dec->frame_slots; + MppBufSlots packet_slots = dec->packet_slots; + + HalTaskHnd task = NULL; + HalTaskInfo task_info; + HalDecTask *task_dec = &task_info.dec; + RK_U32 i; + + mpp_clock_start(dec->clocks[DEC_HAL_TOTAL]); + + while (1) { + /* hal thread wait for dxva interface intput first */ + mpp_thread_lock(hal, THREAD_WORK); + if (MPP_THREAD_RUNNING != mpp_thread_get_status(hal, THREAD_WORK)) { + mpp_thread_unlock(hal, THREAD_WORK); + break; + } + + if (hal_task_get_hnd(tasks, TASK_PROCESSING, &task)) { + // process all task then do reset process + if (dec->hal_reset_post != dec->hal_reset_done) { + dec_dbg_reset("reset: hal reset start\n"); + reset_hal_thread(mpp); + dec_dbg_reset("reset: hal reset done\n"); + dec->hal_reset_done++; + sem_post(&dec->hal_reset); + mpp_thread_unlock(hal, THREAD_WORK); + continue; + } + + mpp_dec_notify(dec, MPP_DEC_NOTIFY_TASK_ALL_DONE); + mpp_clock_start(dec->clocks[DEC_HAL_WAIT]); + mpp_thread_wait(hal, THREAD_WORK); + mpp_clock_pause(dec->clocks[DEC_HAL_WAIT]); + mpp_thread_unlock(hal, THREAD_WORK); + continue; + } + mpp_thread_unlock(hal, THREAD_WORK); + + if (task) { + RK_U32 notify_flag = MPP_DEC_NOTIFY_TASK_HND_VALID; + + mpp_clock_start(dec->clocks[DEC_HAL_PROC]); + mpp->mTaskGetCount++; + + hal_task_hnd_get_info(task, &task_info); + + /* + * check info change flag + * if this is a frame with that flag, only output an empty + * MppFrame without any image data for info change. + */ + if (task_dec->flags.info_change) { + mpp_dec_flush(dec); + mpp_dec_push_display(mpp, task_dec->flags); + mpp_dec_put_frame(mpp, task_dec->output, task_dec->flags); + + hal_task_hnd_set_status(task, TASK_IDLE); + task = NULL; + mpp_dec_notify(dec, notify_flag); + mpp_clock_pause(dec->clocks[DEC_HAL_PROC]); + continue; + } + /* + * check eos task + * if this task is invalid while eos flag is set, we will + * flush display queue then push the eos frame to info that + * all frames have decoded. + */ + if (task_dec->flags.eos && + (!task_dec->valid || task_dec->output < 0)) { + HalDecTaskFlag flag = task_dec->flags; + + flag.eos = 0; + mpp_dec_push_display(mpp, flag); + /* + * Use -1 as invalid buffer slot index. + * Reason: the last task maybe is a empty task with eos flag + * only but this task may go through vproc process also. We need + * create a buffer slot index for it. + */ + mpp_dec_put_frame(mpp, -1, task_dec->flags); + + hal_task_hnd_set_status(task, TASK_IDLE); + task = NULL; + mpp_dec_notify(dec, notify_flag); + mpp_clock_pause(dec->clocks[DEC_HAL_PROC]); + continue; + } + + mpp_clock_start(dec->clocks[DEC_HW_WAIT]); + mpp_hal_hw_wait(dec->hal, &task_info); + mpp_clock_pause(dec->clocks[DEC_HW_WAIT]); + dec->dec_hw_run_count++; + + /* + * when hardware decoding is done: + * 1. clear decoding flag (mark buffer is ready) + * 2. use get_display to get a new frame with buffer + * 3. add frame to output list + * repeat 2 and 3 until not frame can be output + */ + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, + SLOT_HAL_INPUT); + + hal_task_hnd_set_status(task, (dec->parser_fast_mode != 0) ? + (TASK_IDLE) : (TASK_PROC_DONE)); + + if (dec->parser_fast_mode) + notify_flag |= MPP_DEC_NOTIFY_TASK_HND_VALID; + else + notify_flag |= MPP_DEC_NOTIFY_TASK_PREV_DONE; + + task = NULL; + + if (task_dec->output >= 0) + mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT); + + for (i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) { + RK_S32 index = task_dec->refer[i]; + if (index >= 0) + mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT); + } + if (task_dec->flags.eos) + mpp_dec_flush(dec); + mpp_dec_push_display(mpp, task_dec->flags); + + mpp_dec_notify(dec, notify_flag); + mpp_clock_pause(dec->clocks[DEC_HAL_PROC]); + } + } + + mpp_clock_pause(dec->clocks[DEC_HAL_TOTAL]); + + mpp_assert(mpp->mTaskPutCount == mpp->mTaskGetCount); + sys_dbg_info("mpp_dec_hal_thread exited\n"); + return NULL; +} + +void *mpp_dec_advanced_thread(void *data) +{ + Mpp *mpp = (Mpp*)data; + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppBufSlots frame_slots = dec->frame_slots; + MppBufSlots packet_slots = dec->packet_slots; + MppThread *thd_dec = dec->thread_parser; + DecTask task; /* decoder task */ + DecTask *pTask = &task; + dec_task_init(pTask); + HalDecTask *task_dec = &pTask->info.dec; + MppPort input = mpp->mMppInPort; + MppPort output = mpp->mMppOutPort; + MppTask mpp_task = NULL; + MPP_RET ret = MPP_OK; + MppFrame frame = NULL; + MppPacket packet = NULL; + + while (1) { + mpp_thread_lock(thd_dec, THREAD_WORK); + if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd_dec, THREAD_WORK)) { + mpp_thread_unlock(thd_dec, THREAD_WORK); + break; + } + + if (check_task_wait(dec, &task)) + mpp_thread_wait(thd_dec, THREAD_WORK); + mpp_thread_unlock(thd_dec, THREAD_WORK); + + // process user control + if (dec->cmd_send != dec->cmd_recv) { + dec_dbg_detail("ctrl proc %d cmd %08x\n", dec->cmd_recv, dec->cmd); + sem_wait(&dec->cmd_start); + *dec->cmd_ret = mpp_dec_proc_cfg(dec, dec->cmd, dec->param); + dec->cmd_recv++; + dec_dbg_detail("ctrl proc %d done send %d\n", dec->cmd_recv, + dec->cmd_send); + mpp_assert(dec->cmd_send == dec->cmd_send); + dec->param = NULL; + dec->cmd = (MpiCmd)0; + dec->cmd_ret = NULL; + sem_post(&dec->cmd_done); + continue; + } + + // 1. check task in + dec_dbg_detail("mpp_pkt_in_rdy %d\n", task.status.mpp_pkt_in_rdy); + if (!task.status.mpp_pkt_in_rdy) { + ret = mpp_port_poll(input, MPP_POLL_NON_BLOCK); + if (ret < 0) { + task.wait.dec_pkt_in = 1; + continue; + } + + dec_dbg_detail("poll ready\n"); + + task.status.mpp_pkt_in_rdy = 1; + task.wait.dec_pkt_in = 0; + + ret = mpp_port_dequeue(input, &mpp_task); + mpp_assert(ret == MPP_OK); + } + dec_dbg_detail("task in ready\n"); + + mpp_assert(mpp_task); + + mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet); + mpp_task_meta_get_frame (mpp_task, KEY_OUTPUT_FRAME, &frame); + + if (!frame && packet) { + MppMeta meta = mpp_packet_get_meta(packet); + + if (meta) { + mpp_meta_get_frame(meta, KEY_OUTPUT_FRAME, &frame); + if (frame) + task.status.mpp_in_frm_at_pkt = 1; + } + } + + if (NULL == packet || NULL == frame) { + mpp_port_enqueue(input, mpp_task); + task.status.mpp_pkt_in_rdy = 0; + continue; + } + + if (mpp_packet_get_buffer(packet)) { + /* + * if there is available buffer in the input packet do decoding + */ + MppBuffer input_buffer = mpp_packet_get_buffer(packet); + MppBuffer output_buffer = mpp_frame_get_buffer(frame); + + mpp_parser_prepare(dec->parser, packet, task_dec); + + /* + * We may find eos in prepare step and there will be no anymore vaild task generated. + * So here we try push eos task to hal, hal will push all frame to display then + * push a eos frame to tell all frame decoded + */ + if (task_dec->flags.eos && !task_dec->valid) { + mpp_frame_set_eos(frame, 1); + goto DEC_OUT; + } + + /* + * look for a unused packet slot index + */ + if (task_dec->input < 0) { + mpp_buf_slot_get_unused(packet_slots, &task_dec->input); + } + mpp_buf_slot_set_prop(packet_slots, task_dec->input, SLOT_BUFFER, input_buffer); + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY); + mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + + ret = mpp_parser_parse(dec->parser, task_dec); + if (ret != MPP_OK) { + mpp_err_f("something wrong with mpp_parser_parse!\n"); + mpp_frame_set_errinfo(frame, 1); /* 0 - OK; 1 - error */ + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + goto DEC_OUT; + } + + dec_dbg_detail("slot change %d\n", mpp_buf_slot_is_changed(frame_slots)); + if (mpp_buf_slot_is_changed(frame_slots)) { + size_t slot_size = mpp_buf_slot_get_size(frame_slots); + size_t buffer_size = mpp_buffer_get_size(output_buffer); + + dec_dbg_detail("change size required %d vs input %d\n", slot_size, buffer_size); + if (slot_size == buffer_size) { + mpp_buf_slot_ready(frame_slots); + } + + mpp_assert(slot_size <= buffer_size); + + if (slot_size > buffer_size) { + mpp_err_f("required buffer size %d is larger than input buffer size %d\n", + slot_size, buffer_size); + } + } + + mpp_buf_slot_set_prop(frame_slots, task_dec->output, SLOT_BUFFER, output_buffer); + // update codec info + if (!dec->info_updated && dec->dev) { + MppFrame tmp = NULL; + + mpp_buf_slot_get_prop(frame_slots, task_dec->output, SLOT_FRAME_PTR, &tmp); + update_dec_hal_info(dec, tmp); + dec->info_updated = 1; + } + // register genertation + mpp_hal_reg_gen(dec->hal, &pTask->info); + mpp_hal_hw_start(dec->hal, &pTask->info); + mpp_hal_hw_wait(dec->hal, &pTask->info); + + MppFrame tmp = NULL; + mpp_buf_slot_get_prop(frame_slots, task_dec->output, SLOT_FRAME_PTR, &tmp); + mpp_frame_set_width(frame, mpp_frame_get_width(tmp)); + mpp_frame_set_height(frame, mpp_frame_get_height(tmp)); + mpp_frame_set_hor_stride(frame, mpp_frame_get_hor_stride(tmp)); + mpp_frame_set_ver_stride(frame, mpp_frame_get_ver_stride(tmp)); + mpp_frame_set_hor_stride_pixel(frame, mpp_frame_get_hor_stride_pixel(tmp)); + mpp_frame_set_pts(frame, mpp_frame_get_pts(tmp)); + mpp_frame_set_fmt(frame, mpp_frame_get_fmt(tmp)); + mpp_frame_set_errinfo(frame, mpp_frame_get_errinfo(tmp)); + mpp_frame_set_buf_size(frame, mpp_frame_get_buf_size(tmp)); + + mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT); + mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT); + } else { + /* + * else init a empty frame for output + */ + mpp_log_f("line(%d): Error! Get no buffer from input packet\n", __LINE__); + mpp_frame_init(&frame); + mpp_frame_set_errinfo(frame, 1); + } + + /* + * first clear output packet + * then enqueue task back to input port + * final user will release the mpp_frame they had input + */ + DEC_OUT: + if (task.status.mpp_in_frm_at_pkt) { + MppList *list = mpp->mFrmOut; + MppMeta meta = mpp_frame_get_meta(frame); + + if (meta) + mpp_meta_set_packet(meta, KEY_INPUT_PACKET, packet); + + sys_dbg_pts("output frame pts %lld\n", mpp_frame_get_pts(frame)); + + mpp_mutex_cond_lock(&list->cond_lock); + mpp_list_add_at_tail(list, &frame, sizeof(frame)); + mpp->mFramePutCount++; + mpp_list_signal(list); + mpp_mutex_cond_unlock(&list->cond_lock); + + mpp_port_enqueue(input, mpp_task); + mpp_task = NULL; + + task.status.mpp_in_frm_at_pkt = 0; + } else { + mpp_task_meta_set_packet(mpp_task, KEY_INPUT_PACKET, packet); + mpp_port_enqueue(input, mpp_task); + mpp_task = NULL; + + // send finished task to output port + mpp_port_poll(output, MPP_POLL_BLOCK); + mpp_port_dequeue(output, &mpp_task); + mpp_task_meta_set_frame(mpp_task, KEY_OUTPUT_FRAME, frame); + mpp_buffer_sync_ro_begin(mpp_frame_get_buffer(frame)); + + // setup output task here + mpp_port_enqueue(output, mpp_task); + mpp_task = NULL; + } + + packet = NULL; + frame = NULL; + + dec_task_info_init(&pTask->info); + + task.status.mpp_pkt_in_rdy = 0; + } + + // clear remain task in output port + dec_release_task_in_port(input); + dec_release_task_in_port(mpp->mUsrInPort); + dec_release_task_in_port(mpp->mUsrOutPort); + + return NULL; +} + +MPP_RET mpp_dec_start_normal(MppDecImpl *dec) +{ + if (dec->coding != MPP_VIDEO_CodingMJPEG) { + dec->thread_parser = mpp_thread_create(mpp_dec_parser_thread, + dec->mpp, "mpp_dec_parser"); + mpp_thread_start(dec->thread_parser); + dec->thread_hal = mpp_thread_create(mpp_dec_hal_thread, + dec->mpp, "mpp_dec_hal"); + + mpp_thread_start(dec->thread_hal); + } else { + dec->thread_parser = mpp_thread_create(mpp_dec_advanced_thread, + dec->mpp, "mpp_dec_parser"); + mpp_thread_start(dec->thread_parser); + } + + return MPP_OK; +} + +MPP_RET mpp_dec_reset_normal(MppDecImpl *dec) +{ + MppThread *parser = dec->thread_parser; + + if (dec->coding != MPP_VIDEO_CodingMJPEG) { + // set reset flag + mpp_thread_lock(parser, THREAD_CONTROL); + dec->reset_flag = 1; + // signal parser thread to reset + mpp_dec_notify(dec, MPP_DEC_RESET); + mpp_thread_unlock(parser, THREAD_CONTROL); + sem_wait(&dec->parser_reset); + } + + dec->dec_in_pkt_count = 0; + dec->dec_hw_run_count = 0; + dec->dec_out_frame_count = 0; + dec->info_updated = 0; + + return MPP_OK; +} + +MPP_RET mpp_dec_notify_normal(MppDecImpl *dec, RK_U32 flag) +{ + MppThread *thd_dec = dec->thread_parser; + RK_U32 notify = 0; + + if (!thd_dec) + return MPP_NOK; + + mpp_thread_lock(thd_dec, THREAD_WORK); + if (flag == MPP_DEC_CONTROL) { + dec->parser_notify_flag |= flag; + notify = 1; + } else { + RK_U32 old_flag = dec->parser_notify_flag; + + dec->parser_notify_flag |= flag; + if ((old_flag != dec->parser_notify_flag) && + (dec->parser_notify_flag & dec->parser_wait_flag)) + notify = 1; + } + + if (notify) { + dec_dbg_notify("%p status %08x notify control signal\n", dec, + dec->parser_wait_flag, dec->parser_notify_flag); + mpp_thread_signal(thd_dec, THREAD_WORK); + } + mpp_thread_unlock(thd_dec, THREAD_WORK); + + return MPP_OK; +} + +MPP_RET mpp_dec_control_normal(MppDecImpl *dec, MpiCmd cmd, void *param) +{ + MPP_RET ret = MPP_OK; + mpp_mutex_cond_lock(&dec->cmd_lock); + + dec->cmd = cmd; + dec->param = param; + dec->cmd_ret = &ret; + dec->cmd_send++; + + dec_dbg_detail("detail: %p control cmd %08x param %p start disable_thread %d \n", + dec, cmd, param, dec->cfg->base.disable_thread); + + mpp_dec_notify_normal(dec, MPP_DEC_CONTROL); + sem_post(&dec->cmd_start); + sem_wait(&dec->cmd_done); + mpp_mutex_cond_unlock(&dec->cmd_lock); + + return ret; +} + +MppDecModeApi dec_api_normal = { + mpp_dec_start_normal, + NULL, + mpp_dec_reset_normal, + mpp_dec_notify_normal, + mpp_dec_control_normal, +}; diff --git a/mpp/codec/mpp_enc.cpp b/mpp/codec/mpp_enc.cpp deleted file mode 100644 index 66ab68c86..000000000 --- a/mpp/codec/mpp_enc.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_enc" - -#include "mpp_log.h" -#include "mpp_mem.h" - -#include "mpp.h" -#include "mpp_enc.h" -#include "mpp_frame_impl.h" -#include "mpp_packet.h" -#include "mpp_packet_impl.h" - -#define MPP_TEST_FRAME_SIZE SZ_1M - -void *mpp_enc_control_thread(void *data) -{ - Mpp *mpp = (Mpp*)data; - MppThread *thd_enc = mpp->mThreadCodec; - mpp_list *packets = mpp->mPackets; - mpp_list *frames = mpp->mFrames; - MppFrameImpl frame; - MppPacket packet; - size_t size = SZ_1M; - char *buf = mpp_malloc(char, size); - - while (MPP_THREAD_RUNNING == thd_enc->get_status()) { - Mutex::Autolock auto_lock(frames->mutex()); - if (frames->list_size()) { - frames->del_at_head(&frame, sizeof(frame)); - - mpp_packet_init(&packet, buf, size); - packets->lock(); - packets->add_at_tail(&packet, sizeof(packet)); - packets->unlock(); - } - } - mpp_free(buf); - return NULL; -} - -void *mpp_enc_hal_thread(void *data) -{ - Mpp *mpp = (Mpp*)data; - MppThread *hal = mpp->mThreadHal; - mpp_list *frames = mpp->mFrames; - mpp_list *tasks = mpp->mTasks; - - while (MPP_THREAD_RUNNING == hal->get_status()) { - /* - * hal thread wait for dxva interface intput firt - */ - hal->lock(); - if (0 == tasks->list_size()) - hal->wait(); - hal->unlock(); - - // get_config - // register genertation - if (tasks->list_size()) { - HalDecTask *task; - tasks->lock(); - tasks->del_at_head(&task, sizeof(task)); - mpp->mTaskGetCount++; - tasks->unlock(); - - // hal->mpp_hal_reg_gen(current); - - /* - * wait previous register set done - */ - // hal->mpp_hal_hw_wait(previous); - - /* - * send current register set to hardware - */ - // hal->mpp_hal_hw_start(current); - - /* - * mark previous buffer is complete - */ - // change dpb slot status - // signal() - // mark frame in output queue - // wait up output thread to get a output frame - - // for test - MppBuffer buffer; - mpp_buffer_get(mpp->mFrameGroup, &buffer, MPP_TEST_FRAME_SIZE); - - MppFrame frame; - mpp_frame_init(&frame); - mpp_frame_set_buffer(frame, buffer); - frames->lock(); - frames->add_at_tail(&frame, sizeof(frame)); - mpp->mFramePutCount++; - frames->signal(); - frames->unlock(); - } - } - - return NULL; -} - diff --git a/mpp/codec/mpp_enc_debug.h b/mpp/codec/mpp_enc_debug.h new file mode 100644 index 000000000..5faddd909 --- /dev/null +++ b/mpp/codec/mpp_enc_debug.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_ENC_DEBUG_H +#define MPP_ENC_DEBUG_H + +#include "mpp_debug.h" + +#define MPP_ENC_DBG_FUNCTION (0x00000001) +#define MPP_ENC_DBG_CONTROL (0x00000002) +#define MPP_ENC_DBG_CFG (0x00000004) +#define MPP_ENC_DBG_STATUS (0x00000010) +#define MPP_ENC_DBG_DETAIL (0x00000020) +#define MPP_ENC_DBG_RESET (0x00000040) +#define MPP_ENC_DBG_NOTIFY (0x00000080) +#define MPP_ENC_DBG_REENC (0x00000100) +#define MPP_ENC_DBG_SLICE (0x00000200) + +#define MPP_ENC_DBG_FRM_STATUS (0x00010000) + +#define mpp_enc_dbg(flag, fmt, ...) mpp_dbg(mpp_enc_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_enc_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_enc_debug, flag, fmt, ## __VA_ARGS__) + +#define enc_dbg_func(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define enc_dbg_ctrl(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_CONTROL, fmt, ## __VA_ARGS__) +#define enc_dbg_cfg(fmt, ...) mpp_enc_dbg(MPP_ENC_DBG_CFG, fmt, ## __VA_ARGS__) +#define enc_dbg_status(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_STATUS, fmt, ## __VA_ARGS__) +#define enc_dbg_detail(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_DETAIL, fmt, ## __VA_ARGS__) +#define enc_dbg_notify(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_NOTIFY, fmt, ## __VA_ARGS__) +#define enc_dbg_reenc(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_REENC, fmt, ## __VA_ARGS__) +#define enc_dbg_slice(fmt, ...) mpp_enc_dbg(MPP_ENC_DBG_SLICE, fmt, ## __VA_ARGS__) +#define enc_dbg_frm_status(fmt, ...) mpp_enc_dbg_f(MPP_ENC_DBG_FRM_STATUS, fmt, ## __VA_ARGS__) + +extern RK_U32 mpp_enc_debug; + +#endif /* MPP_ENC_DEBUG_H */ diff --git a/mpp/codec/mpp_enc_impl.c b/mpp/codec/mpp_enc_impl.c new file mode 100644 index 000000000..f6bbeccc2 --- /dev/null +++ b/mpp/codec/mpp_enc_impl.c @@ -0,0 +1,3701 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_enc" + +#include +#include +#include + +#include "mpp_2str.h" +#include "mpp_time.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_buffer_impl.h" + +#include "mpp_enc_refs.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" + +#include "mpp.h" +#include "mpp_soc.h" +#include "mpp_enc_debug.h" +#include "mpp_enc_cfg.h" +#include "mpp_enc_impl.h" +#include "mpp_enc_cb_param.h" + +#include "h264_syntax.h" + +typedef union EncAsyncWait_u { + RK_U32 val; + struct { + RK_U32 enc_frm_in : 1; // 0x0001 MPP_ENC_NOTIFY_FRAME_ENQUEUE + RK_U32 reserv0002 : 1; // 0x0002 + RK_U32 reserv0004 : 1; // 0x0004 + RK_U32 enc_pkt_out : 1; // 0x0008 MPP_ENC_NOTIFY_PACKET_ENQUEUE + + RK_U32 task_hnd : 1; // 0x0010 + RK_U32 reserv0020 : 1; // 0x0020 + RK_U32 reserv0040 : 1; // 0x0040 + RK_U32 reserv0080 : 1; // 0x0080 + + RK_U32 reserv0100 : 1; // 0x0100 + RK_U32 reserv0200 : 1; // 0x0200 + RK_U32 reserv0400 : 1; // 0x0400 + RK_U32 reserv0800 : 1; // 0x0800 + + RK_U32 reserv1000 : 1; // 0x1000 + RK_U32 reserv2000 : 1; // 0x2000 + RK_U32 reserv4000 : 1; // 0x4000 + RK_U32 reserv8000 : 1; // 0x8000 + }; +} EncAsyncWait; + +static RK_U8 uuid_version[16] = { + 0x3d, 0x07, 0x6d, 0x45, 0x73, 0x0f, 0x41, 0xa8, + 0xb1, 0xc4, 0x25, 0xd7, 0x97, 0x6b, 0xf1, 0xac, +}; + +static RK_U8 uuid_rc_cfg[16] = { + 0xd7, 0xdc, 0x03, 0xc3, 0xc5, 0x6f, 0x40, 0xe0, + 0x8e, 0xa9, 0x17, 0x1a, 0xd2, 0xef, 0x5e, 0x23, +}; + +static RK_U8 uuid_usr_data[16] = { + 0xfe, 0x39, 0xac, 0x4c, 0x4a, 0x8e, 0x4b, 0x4b, + 0x85, 0xd9, 0xb2, 0xa2, 0x4f, 0xa1, 0x19, 0x5b, +}; + +static RK_U8 uuid_debug_info[16] = { + 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65, + 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a +}; + +RK_U8 uuid_refresh_cfg[16] = { + 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x00 +}; + +static MPP_RET enc_async_wait_task(MppEncImpl *enc, EncAsyncTaskInfo *info); +static void reset_hal_enc_task(HalEncTask *task) +{ + memset(task, 0, sizeof(*task)); +} + +static void reset_enc_rc_task(EncRcTask *task) +{ + memset(task, 0, sizeof(*task)); +} + +static void reset_enc_task(MppEncImpl *enc) +{ + enc->task_in = NULL; + enc->task_out = NULL; + enc->packet = NULL; + enc->frame = NULL; + + enc->frm_buf = NULL; + enc->pkt_buf = NULL; + + /* NOTE: clear add_by flags */ + enc->hdr_status.val = enc->hdr_status.ready; +} + +static void update_enc_hal_info(MppEncImpl *enc) +{ + MppDevInfoCfg data[32]; + RK_S32 size = sizeof(data); + RK_S32 i; + + if (NULL == enc->hal_info || NULL == enc->dev) + return ; + + hal_info_from_enc_cfg(enc->hal_info, enc->cfg); + hal_info_get(enc->hal_info, data, &size); + + if (size) { + size /= sizeof(data[0]); + for (i = 0; i < size; i++) + mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &data[i]); + } +} + +static void update_hal_info_fps(MppEncImpl *enc) +{ + MppDevInfoCfg cfg; + + RK_S32 time_diff = ((RK_S32)(enc->time_end - enc->time_base) / 1000); + RK_U64 fps = hal_info_to_float(enc->frame_count * 1000, time_diff); + + cfg.type = ENC_INFO_FPS_CALC; + cfg.flag = CODEC_INFO_FLAG_STRING; + cfg.data = fps; + + mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &cfg); + + enc->time_base = enc->time_end; + enc->frame_count = 0; +} + +static MPP_RET release_task_in_port(MppPort port) +{ + MPP_RET ret = MPP_OK; + MppPacket packet = NULL; + MppFrame frame = NULL; + MppTask mpp_task; + + do { + ret = mpp_port_poll(port, MPP_POLL_NON_BLOCK); + if (ret < 0) + break; + + mpp_port_dequeue(port, &mpp_task); + mpp_assert(mpp_task); + if (mpp_task) { + packet = NULL; + frame = NULL; + ret = mpp_task_meta_get_frame(mpp_task, KEY_INPUT_FRAME, &frame); + if (frame) { + mpp_frame_deinit(&frame); + frame = NULL; + } + ret = mpp_task_meta_get_packet(mpp_task, KEY_OUTPUT_PACKET, &packet); + if (packet) { + mpp_packet_deinit(&packet); + packet = NULL; + } + + mpp_port_enqueue(port, mpp_task); + mpp_task = NULL; + } else + break; + } while (1); + + return ret; +} + +static void check_hal_task_pkt_len(HalEncTask *task, const char *reason) +{ + RK_U32 task_length = task->length; + RK_U32 packet_length = mpp_packet_get_length(task->packet); + + if (task_length != packet_length) { + mpp_err_f("%s check failed: task length is not match to packet length %d vs %d\n", + reason, task_length, packet_length); + } +} + +static MPP_RET check_enc_task_wait(MppEncImpl *enc, EncAsyncWait *wait) +{ + MPP_RET ret = MPP_OK; + RK_U32 notify = enc->notify_flag; + RK_U32 last_wait = enc->status_flag; + RK_U32 curr_wait = wait->val; + RK_U32 wait_chg = last_wait & (~curr_wait); + RK_U32 keep_notify = 0; + + do { + if (enc->reset_flag) + break; + + // NOTE: User control should always be processed + if (notify & MPP_ENC_CONTROL) { + keep_notify = notify & (~MPP_ENC_CONTROL); + break; + } + + // NOTE: When condition is not fulfilled check nofify flag again + if (!curr_wait || (curr_wait & notify)) + break; + + ret = MPP_NOK; + } while (0); + + enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc, + last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work")); + + enc->status_flag = wait->val; + enc->notify_flag = keep_notify; + + if (ret) { + enc->wait_count++; + } else { + enc->work_count++; + } + + return ret; +} + +static RK_S32 check_hal_info_update(MpiCmd cmd) +{ + if (cmd == MPP_ENC_SET_CFG || + cmd == MPP_ENC_SET_REF_CFG) { + return 1; + } + + return 0; +} + +static void check_low_delay_part_mode(MppEncImpl *enc) +{ + MppEncCfgSet *cfg = enc->cfg; + + enc->low_delay_part_mode = 0; + + if (!(cfg->base.low_delay)) + return; + + if (!cfg->split.split_mode) + return; + + if (mpp_enc_hal_check_part_mode(enc->enc_hal)) + return; + + enc->low_delay_part_mode = 1; +} + +static void check_low_delay_output(MppEncImpl *enc) +{ + MppEncCfgSet *cfg = enc->cfg; + + enc->low_delay_output = 0; + + if (!cfg->split.split_mode || !(cfg->split.split_out & MPP_ENC_SPLIT_OUT_LOWDELAY)) + return; + + if (cfg->rc.max_reenc_times) { + mpp_log_f("can not enable lowdelay output with reencode enabled\n"); + cfg->rc.max_reenc_times = 0; + } + + if (cfg->rc.drop_mode) { + mpp_log_f("can not enable lowdelay output with drop mode enabled\n"); + cfg->rc.drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED; + } + + if (cfg->rc.super_mode) { + mpp_log_f("can not enable lowdelay output with super frame mode enabled\n"); + cfg->rc.super_mode = MPP_ENC_RC_SUPER_FRM_NONE; + } + + enc->low_delay_output = 1; +} + +MPP_RET mpp_enc_callback(const char *caller, void *ctx, RK_S32 cmd, void *param) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + EncOutParam *out = (EncOutParam *)param; + HalEncTask *task = NULL; + MppPacket packet = NULL; + MppPacketImpl *impl = NULL; + RK_U8 *last_pos = NULL; + RK_S32 slice_length = 0; + RK_U32 part_first = 0; + MPP_RET ret = MPP_OK; + Mpp *mpp = (Mpp*)enc->mpp; + (void) caller; + + if (!enc->low_delay_output) + return ret; + + task = (HalEncTask *)out->task; + mpp_assert(task); + part_first = task->part_first; + packet = task->packet; + + if (part_first) { + task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet); + task->part_length = mpp_packet_get_length(packet); + + enc_dbg_slice("first slice previous length %d\n", task->part_length); + mpp_assert(task->part_pos); + task->part_first = 0; + slice_length = task->part_length; + } + + last_pos = (RK_U8 *)task->part_pos; + slice_length += out->length; + + enc_dbg_slice("last_pos %p len %d:%d\n", last_pos, out->length, slice_length); + + switch (cmd) { + case ENC_OUTPUT_FINISH : { + enc_dbg_slice("slice pos %p len %5d last\n", last_pos, slice_length); + + impl = (MppPacketImpl *)packet; + + impl->pos = last_pos; + impl->length = slice_length; + impl->status.val = 0; + impl->status.partition = 1; + impl->status.soi = part_first; + impl->status.eoi = 1; + + task->part_pos += slice_length; + task->part_length += slice_length; + task->part_count++; + task->part_last = 1; + } break; + case ENC_OUTPUT_SLICE : { + enc_dbg_slice("slice pos %p len %5d\n", last_pos, slice_length); + + mpp_packet_new((MppPacket *)&impl); + mpp_assert(impl); + + /* copy the source data */ + memcpy(impl, packet, sizeof(*impl)); + + impl->pos = last_pos; + impl->length = slice_length; + impl->status.val = 0; + impl->status.partition = 1; + impl->status.soi = part_first; + impl->status.eoi = 0; + + if (impl->buffer) + mpp_buffer_inc_ref(impl->buffer); + + mpp_meta_get(&impl->meta); + if (impl->meta) { + EncFrmStatus *frm = &task->rc_task->frm; + + mpp_meta_set_s32(impl->meta, KEY_OUTPUT_INTRA, frm->is_intra); + } + + mpp_packet_copy_segment_info(impl, packet); + mpp_packet_reset_segment(packet); + + enc_dbg_detail("pkt %d new pos %p len %d\n", task->part_count, + last_pos, slice_length); + + task->part_pos += slice_length; + task->part_length += slice_length; + task->part_count++; + if (!mpp->mEncAyncProc) { + mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, impl); + mpp_port_enqueue(enc->output, enc->task_out); + + ret = mpp_port_poll(enc->output, MPP_POLL_BLOCK); + mpp_assert(ret > 0); + ret = mpp_port_dequeue(enc->output, &enc->task_out); + mpp_assert(enc->task_out); + } else { + if (mpp->mPktOut) { + MppList *pkt_out = mpp->mPktOut; + + mpp_mutex_cond_lock(&pkt_out->cond_lock); + mpp_list_add_at_tail(pkt_out, &impl, sizeof(impl)); + mpp->mPacketPutCount++; + mpp_list_signal(pkt_out); + mpp_mutex_cond_unlock(&pkt_out->cond_lock); + } + } + } break; + default : { + } break; + } + + return ret; +} + +static void enc_set_rc_updated(MppEncImpl *enc, const char *log_str) +{ + if (!enc->rc_status.rc_api_user_cfg) { + enc->rc_status.rc_api_user_cfg = 1; + if (log_str) + enc_dbg_cfg("rc cfg updated for %s\n", log_str); + } +} + +static void enc_set_resend_hdr(MppEncImpl *enc, const char *log_str) +{ + if (enc->coding != MPP_VIDEO_CodingAVC && enc->coding != MPP_VIDEO_CodingHEVC) + return; + + if (!(enc->frm_cfg.force_flag & ENC_FORCE_IDR)) { + enc->frm_cfg.force_flag |= ENC_FORCE_IDR; + if (log_str) + enc_dbg_cfg("resend header and force idr for %s\n", log_str); + } + enc->hdr_status.val = 0; +} + +static void show_prep_update(MppEncPrepCfg *cfg, MppEncPrepCfg *set) +{ + char str[256]; + rk_s32 len; + rk_s32 base; + + len = snprintf(str, sizeof(str) - 1, "set prep cfg "); + base = len; + + if (set->width != cfg->width || set->height != cfg->height) { + len += snprintf(str + len, sizeof(str) - len - 1, + "w:h [%d:%d] -> [%d:%d] ", + cfg->width, cfg->height, set->width, set->height); + } + + if (set->hor_stride != cfg->hor_stride || set->ver_stride != cfg->ver_stride) { + len += snprintf(str + len, sizeof(str) - len - 1, + "stride [%d:%d] -> [%d:%d] ", + cfg->hor_stride, cfg->ver_stride, + set->hor_stride, set->ver_stride); + } + + if (set->format != cfg->format) { + len += snprintf(str + len, sizeof(str) - len - 1, + "fmt %d -> %d ", cfg->format, set->format); + } + + if (set->rotation != cfg->rotation) { + len += snprintf(str + len, sizeof(str) - len - 1, + "rotate %d -> %d ", cfg->rotation, set->rotation); + } + + if (set->mirroring != cfg->mirroring) { + len += snprintf(str + len, sizeof(str) - len - 1, + "mirror %d -> %d ", cfg->mirroring, set->mirroring); + } + + if (len > base) + enc_dbg_cfg("%s\n", str); + + mpp_logi("set prep cfg w:h [%d:%d] stride [%d:%d] fmt %d rotate %d mirror %d\n", + set->width, set->height, set->hor_stride, set->ver_stride, + set->format, set->rotation, set->mirroring); +} + +static void proc_prep_cfg(MppEncImpl *enc) +{ + MppEncPrepCfg *cfg = &enc->cfg->prep; + MppEncPrepCfg *set = &enc->set->prep; + rk_u32 flag = *mpp_enc_cfg_prep_change(enc->set); + rk_u32 change_res = 0; + rk_u32 change_rot = 0; + rk_u32 restore = 0; + rk_s32 mirroring; + rk_s32 rotation; + + enc_dbg_cfg("prep cfg change 0x%x\n", flag); + + if (!flag) + return; + + { /* chekc input and format change */ + static KmppObjDef def = NULL; + static KmppEntry *tbl_input = NULL; + static KmppEntry *tbl_format = NULL; + static KmppEntry *tbl_rotation = NULL; + static rk_s32 once = 1; + + if (!def && once) { + def = kmpp_obj_to_objdef(enc->set_obj); + kmpp_objdef_get_entry(def, "prep:width", &tbl_input); + kmpp_objdef_get_entry(def, "prep:format", &tbl_format); + kmpp_objdef_get_entry(def, "prep:rotation", &tbl_rotation); + + if (!tbl_input || !tbl_format || !tbl_rotation) + mpp_loge("failed to get input and format table\n"); + + once = 0; + } + + if (kmpp_obj_tbl_test(enc->set_obj, tbl_input) || + kmpp_obj_tbl_test(enc->set_obj, tbl_format)) { + change_res = 1; + } + if (kmpp_obj_tbl_test(enc->set_obj, tbl_input) || + kmpp_obj_tbl_test(enc->set_obj, tbl_rotation)) { + change_rot = 1; + } + } + + if (set->rotation_ext >= MPP_ENC_ROT_BUTT || set->rotation_ext < 0 || + set->mirroring_ext < 0 || set->flip < 0) { + mpp_loge("invalid rotation %d mirroring %d flip %d\n", + set->rotation_ext, set->mirroring_ext, set->flip); + mpp_loge("restore rotation %d mirroring %d flip %d\n", + cfg->rotation_ext, cfg->mirroring_ext, cfg->flip); + set->rotation_ext = cfg->rotation_ext; + set->mirroring_ext = cfg->mirroring_ext; + set->flip = cfg->flip; + } + + /* + * For unifying the encoder's params used by CFG_SET and CFG_GET command, + * there is distinction between user's set and set in hal. + * User can externally set rotation_ext, mirroring_ext and flip, + * which should be transformed to mirroring and rotation in hal. + */ + rotation = set->rotation_ext; + mirroring = set->mirroring_ext; + + if (set->flip) { + mirroring = !mirroring; + rotation += MPP_ENC_ROT_180; + rotation &= MPP_ENC_ROT_270; + } + + set->mirroring = mirroring; + set->rotation = (MppEncRotationCfg)rotation; + + if (MPP_FRAME_FMT_IS_FBC(set->format) && (set->mirroring || set->rotation)) { + mpp_loge("conflict fbc input format %x with mirror %d or rotaion %d\n", + set->format, set->mirroring, set->rotation); + mpp_loge("disable mirror and rotation\n"); + set->mirroring = 0; + set->rotation = MPP_ENC_ROT_0; + } + + if (set->range >= MPP_FRAME_RANGE_NB || + set->color >= MPP_FRAME_SPC_NB || + set->colorprim >= MPP_FRAME_PRI_NB || + set->colortrc >= MPP_FRAME_TRC_NB) { + mpp_loge("invalid color range %d colorspace %d primaries %d transfer characteristic %d\n", + set->range, set->color, set->colorprim, set->colortrc); + mpp_loge("restore color range %d colorspace %d primaries %d transfer characteristic %d\n", + cfg->range, cfg->color, cfg->colorprim, cfg->colortrc); + set->range = cfg->range; + set->color = cfg->color; + set->colorprim = cfg->colorprim; + set->colortrc = cfg->colortrc; + } + + if (set->rotation == MPP_ENC_ROT_90 || set->rotation == MPP_ENC_ROT_270) { + set->height = set->width_set; + set->width = set->height_set; + + if (set->height > set->hor_stride || set->width > set->ver_stride) + restore = 1; + } else { + set->width = set->width_set; + set->height = set->height_set; + + if (set->width > set->hor_stride || set->height > set->ver_stride) + restore = 1; + } + + if (restore) { + mpp_loge("invalid set w:h [%d:%d] stride [%d:%d] rotation %d\n", + set->width, set->height, set->hor_stride, set->ver_stride, set->rotation); + mpp_loge("restore cfg w:h [%d:%d] stride [%d:%d] rotation %d\n", + cfg->width, cfg->height, cfg->hor_stride, cfg->ver_stride, cfg->rotation); + set->width = cfg->width; + set->height = cfg->height; + set->width_set = cfg->width; + set->height_set = cfg->height; + set->hor_stride = cfg->hor_stride; + set->ver_stride = cfg->ver_stride; + set->rotation = cfg->rotation; + } + + if (!set->max_height || !set->max_width) { + set->max_width = set->width; + set->max_height = set->height; + } + + show_prep_update(cfg, set); + memcpy(cfg, set, sizeof(*cfg)); + enc_set_resend_hdr(enc, "change prep cfg"); + + /* NOTE: only set change res flag and NOT clear */ + if (change_res || change_rot) { + cfg->change_res = 1; + } +} + +#define RC_CHANGE_MODE (1 << 0) +#define RC_CHANGE_BPS (1 << 1) +#define RC_CHANGE_FPS_IN (1 << 2) +#define RC_CHANGE_FPS_OUT (1 << 3) +#define RC_CHANGE_GOP (1 << 4) +#define RC_CHANGE_DEBREATH (1 << 5) + +static MPP_RET mpp_enc_control_set_ref_cfg(MppEncImpl *enc, void *param); +static void show_rc_update(MppEncRcCfg *cfg, MppEncRcCfg *set, rk_u32 change) +{ + char str[256]; + rk_s32 len; + rk_s32 base; + + len = snprintf(str, sizeof(str) - 1, "set rc cfg "); + base = len; + + if (change & RC_CHANGE_MODE) { + len += snprintf(str + len, sizeof(str) - len - 1, "mode %s -> %s ", + strof_rc_mode(cfg->rc_mode), strof_rc_mode(set->rc_mode)); + } + + if (change & RC_CHANGE_BPS) { + len += snprintf(str + len, sizeof(str) - len - 1, + "bps [%d:%d:%d] -> [%d:%d:%d] ", + cfg->bps_target, cfg->bps_max, cfg->bps_min, + set->bps_target, set->bps_max, set->bps_min); + } + + if (len > base) { + enc_dbg_cfg("%s\n", str); + len = base; + } + + if (change & RC_CHANGE_FPS_IN) { + len += snprintf(str + len, sizeof(str) - len - 1, + "fps in [%d:%d:%s] -> [%d:%d:%s] ", + cfg->fps_in_num, cfg->fps_in_denom, + cfg->fps_in_flex ? "flex" : "fix", + set->fps_in_num, set->fps_in_denom, + set->fps_in_flex ? "flex" : "fix"); + } + + if (change & RC_CHANGE_FPS_OUT) { + len += snprintf(str + len, sizeof(str) - len - 1, + "fps out [%d:%d:%s] -> [%d:%d:%s] ", + cfg->fps_out_num, cfg->fps_out_denom, + cfg->fps_out_flex ? "flex" : "fix", + set->fps_out_num, set->fps_out_denom, + set->fps_out_flex ? "flex" : "fix"); + } + + if (change & RC_CHANGE_GOP) { + len += snprintf(str + len, sizeof(str) - len - 1, + "gop %d -> %d ", cfg->gop, set->gop); + } + + if (len > base) + enc_dbg_cfg("%s\n", str); + + mpp_logi("set rc %s bps [%d:%d:%d] fps [%d:%d:%s] - [%d:%d:%s] gop %d\n", + strof_rc_mode(set->rc_mode), set->bps_target, set->bps_max, set->bps_min, + set->fps_in_num, set->fps_in_denom, set->fps_in_flex ? "flex" : "fix", + set->fps_out_num, set->fps_out_denom, set->fps_out_flex ? "flex" : "fix", + set->gop); +} + +static void proc_rc_cfg(MppEncImpl *enc) +{ + MppEncRcCfg *cfg = &enc->cfg->rc; + MppEncRcCfg *set = &enc->set->rc; + rk_u32 flag = *mpp_enc_cfg_rc_change(enc->set); + rk_u32 change = 0; + rk_s32 i; + + enc_dbg_cfg("rc cfg change 0x%x\n", flag); + + if (!flag) + return; + + /* 1. check input rc config for invalid value and revert to valid value */ + if (set->rc_priority >= MPP_ENC_RC_PRIORITY_BUTT) { + mpp_loge("invalid rc_priority %d should be in range [%d:%d]\n", + set->rc_priority, MPP_ENC_RC_BY_BITRATE_FIRST, MPP_ENC_RC_PRIORITY_BUTT); + mpp_loge("restore rc_priority to %d\n", cfg->rc_priority); + set->rc_priority = cfg->rc_priority; + } + + if (set->super_mode >= MPP_ENC_RC_SUPER_FRM_BUTT) { + mpp_loge("invalid super_mode %d should be in range [%d:%d]\n", + set->super_mode, MPP_ENC_RC_SUPER_FRM_NONE, MPP_ENC_RC_SUPER_FRM_BUTT); + mpp_loge("restore super_mode to %d\n", cfg->super_mode); + set->super_mode = cfg->super_mode; + } + + if (set->debreath_en && set->debre_strength > 35) { + mpp_loge("invalid debre_strength %d should be in range [%d:%d]\n", + set->debre_strength, 0, 35, cfg->debre_strength); + mpp_loge("restore debre_strength to %d\n", cfg->debre_strength); + set->debre_strength = cfg->debre_strength; + } + + if (set->rc_mode >= MPP_ENC_RC_MODE_BUTT) { + mpp_loge("invalid rc mode %d must be in range [0:%d]\n", + set->rc_mode, MPP_ENC_RC_MODE_BUTT - 1); + + for (i = 0; i < MPP_ENC_RC_MODE_BUTT; i++) + mpp_loge("%d - %s\n", i, strof_rc_mode((MppEncRcMode)i)); + + mpp_loge("restore rc mode to %d\n", cfg->rc_mode); + set->rc_mode = cfg->rc_mode; + } + + if (set->quality >= MPP_ENC_RC_QUALITY_BUTT) { + mpp_loge("invalid quality %d must be in ranget [0:%d]\n", + set->quality, MPP_ENC_RC_QUALITY_BUTT - 1); + mpp_loge("0 - MPP_ENC_RC_QUALITY_WORST\n"); + mpp_loge("1 - MPP_ENC_RC_QUALITY_BAD\n"); + mpp_loge("2 - MPP_ENC_RC_QUALITY_MEDIUM\n"); + mpp_loge("3 - MPP_ENC_RC_QUALITY_BETTER\n"); + mpp_loge("4 - MPP_ENC_RC_QUALITY_BEST\n"); + mpp_loge("5 - MPP_ENC_RC_QUALITY_CQP\n"); + mpp_loge("6 - MPP_ENC_RC_QUALITY_AQ_ONLY\n"); + mpp_loge("restore quality to %d\n", cfg->quality); + set->quality = cfg->quality; + } + + if (set->rc_mode != MPP_ENC_RC_MODE_FIXQP) { + if ((set->bps_target >= 100 * SZ_1M || set->bps_target <= 1 * SZ_1K) || + (set->bps_max >= 100 * SZ_1M || set->bps_max <= 1 * SZ_1K) || + (set->bps_min >= 100 * SZ_1M || set->bps_min <= 1 * SZ_1K)) { + mpp_loge("invalid bit per second (bps) %d [%d:%d] out of range 1K~100M\n", + set->bps_target, set->bps_min, set->bps_max); + mpp_loge("restore bps to %d [%d:%d]\n", + cfg->bps_target, cfg->bps_min, cfg->bps_max); + set->bps_target = cfg->bps_target; + set->bps_max = cfg->bps_max; + set->bps_min = cfg->bps_min; + } + } + + // if I frame min/max is not set use normal case + if (set->qp_min_i <= 0) + set->qp_min_i = set->qp_min; + if (set->qp_max_i <= 0) + set->qp_max_i = set->qp_max; + if (set->qp_min < 0 || set->qp_max < 0 || + set->qp_min > set->qp_max || set->qp_min_i < 0 || + set->qp_max_i < 0 || set->qp_min_i > set->qp_max_i || + (set->qp_init > 0 && (set->qp_init > set->qp_max_i || + set->qp_init < set->qp_min_i))) { + mpp_loge("invalid qp range: init %d i [%d:%d] p [%d:%d]\n", + set->qp_init, set->qp_min_i, set->qp_max_i, + set->qp_min, set->qp_max); + + mpp_loge("restore qp range: init %d i [%d:%d] p [%d:%d]\n", + set->qp_init, set->qp_min_i, set->qp_max_i, + set->qp_min, set->qp_max); + + set->qp_init = cfg->qp_init; + set->qp_min_i = cfg->qp_min_i; + set->qp_max_i = cfg->qp_max_i; + set->qp_min = cfg->qp_min; + set->qp_max = cfg->qp_max; + } + + if (MPP_ABS(set->qp_delta_ip) > 8) { + mpp_loge("invalid qp delta ip %d restore to %d\n", + set->qp_delta_ip, cfg->qp_delta_ip); + set->qp_delta_ip = cfg->qp_delta_ip; + } + if (MPP_ABS(set->qp_delta_vi) > 6) { + mpp_loge("invalid qp delta vi %d restore to %d\n", + set->qp_delta_vi, cfg->qp_delta_vi); + set->qp_delta_vi = cfg->qp_delta_vi; + } + if (set->qp_max_step < 0) { + mpp_loge("invalid qp max step %d restore to %d\n", + set->qp_max_step, cfg->qp_max_step); + set->qp_max_step = cfg->qp_max_step; + } + if (set->stats_time && set->stats_time > 60) { + mpp_loge("warning: bitrate statistic time %d is larger than 60s\n", + set->stats_time); + } + + /* 2. check rc cfg done now check rc cfg change */ + if (set->rc_mode != cfg->rc_mode) + change |= RC_CHANGE_MODE; + if (set->bps_target != cfg->bps_target || + set->bps_max != cfg->bps_max || + set->bps_min != cfg->bps_min) + change |= RC_CHANGE_BPS; + if (set->fps_in_num != cfg->fps_in_num || + set->fps_in_denom != cfg->fps_in_denom || + set->fps_in_flex != cfg->fps_in_flex) + change |= RC_CHANGE_FPS_IN; + if (set->fps_out_num != cfg->fps_out_num || + set->fps_out_denom != cfg->fps_out_denom || + set->fps_out_flex != cfg->fps_out_flex) + change |= RC_CHANGE_FPS_OUT; + if (set->gop != cfg->gop) + change |= RC_CHANGE_GOP; + if (set->debreath_en != cfg->debreath_en) + change |= RC_CHANGE_DEBREATH; + + if (change & (RC_CHANGE_MODE | RC_CHANGE_FPS_IN | RC_CHANGE_FPS_OUT | RC_CHANGE_GOP)) + enc_set_resend_hdr(enc, "change rc_mode/fps/gop"); + + /* NOTE: some rc change no need to (quality) */ + if (flag) + enc_set_rc_updated(enc, "rc cfg changed"); + + show_rc_update(cfg, set, change); + memcpy(cfg, set, sizeof(*cfg)); + + if (change & RC_CHANGE_GOP) + mpp_enc_refs_set_rc_igop(enc->refs, cfg->gop); + + if (change & RC_CHANGE_DEBREATH) + mpp_enc_refs_force_recon(enc->refs, !!cfg->debreath_en); + + if (set->ref_cfg) + mpp_enc_control_set_ref_cfg(enc, set->ref_cfg); +} + +static void proc_split_cfg(MppEncSliceSplit *cfg, MppEncSliceSplit *set) +{ + if (set->split_mode >= MPP_ENC_SPLIT_MODE_BUTT) { + mpp_loge("invalid split mode %d should be in range [%d:%d]\n", + set->split_mode, MPP_ENC_SPLIT_NONE, MPP_ENC_SPLIT_MODE_BUTT); + mpp_loge("restore split mode %d\n", cfg->split_mode); + set->split_mode = cfg->split_mode; + } + + if (!set->split_mode) { + set->split_arg = 0; + set->split_out = 0; + } + + memcpy(cfg, set, sizeof(*cfg)); +} + +static void proc_hw_cfg(MppEncImpl *enc) +{ + MppEncHwCfg *cfg = &enc->cfg->hw; + MppEncHwCfg *set = &enc->set->hw; + rk_u32 flag = *mpp_enc_cfg_hw_change(enc->set); + + enc_dbg_cfg("hw cfg change 0x%x\n", flag); + + if (!flag) + return; + + if (set->qp_delta_row < 0 || set->qp_delta_row_i < 0) { + mpp_loge("invalid hw qp delta row [%d:%d] restore to [%d:%d]\n", + set->qp_delta_row_i, set->qp_delta_row, + cfg->qp_delta_row_i, cfg->qp_delta_row); + set->qp_delta_row = cfg->qp_delta_row; + set->qp_delta_row_i = cfg->qp_delta_row_i; + } + + if (set->qbias_en < 0) { + mpp_loge("invalid hw qbias_en %d restore to %d\n", + set->qbias_en, cfg->qbias_en); + set->qbias_en = cfg->qbias_en; + } + + if (set->qbias_i < 0 || set->qbias_p < 0) { + mpp_loge("invalid hw qp bias [%d:%d] restore to [%d:%d]\n", + set->qbias_i, set->qbias_p, cfg->qbias_i, cfg->qbias_p); + set->qbias_i = cfg->qbias_i; + } + + if (set->flt_str_i < 0 || set->flt_str_p < 0) { + mpp_loge("invalid filter strength [%d:%d] restore to [%d:%d]\n", + set->flt_str_i, set->flt_str_p, + cfg->flt_str_i, cfg->flt_str_p); + set->flt_str_i = cfg->flt_str_i; + } + + memcpy(cfg, set, sizeof(*cfg)); +} + +static void proc_tune_cfg(MppEncImpl *enc) +{ + MppEncFineTuneCfg *cfg = &enc->cfg->tune; + MppEncFineTuneCfg *set = &enc->set->tune; + rk_u32 flag = *mpp_enc_cfg_tune_change(enc->set); + + enc_dbg_cfg("tune cfg change 0x%x\n", flag); + + if (!flag) + return; + + if (set->scene_mode < MPP_ENC_SCENE_MODE_DEFAULT || + set->scene_mode >= MPP_ENC_SCENE_MODE_BUTT) { + mpp_loge("invalid scene mode %d not in range [%d:%d]\n", set->scene_mode, + MPP_ENC_SCENE_MODE_DEFAULT, MPP_ENC_SCENE_MODE_BUTT - 1); + mpp_loge("restore scene mode %d\n", cfg->scene_mode); + set->scene_mode = cfg->scene_mode; + } + + if (set->motion_static_switch_enable < 0 || set->motion_static_switch_enable > 1) { + mpp_loge("invalid motion static switch enable not in range [%d : %d]\n", 0, 1); + mpp_loge("restore motion static switch enable %d\n", cfg->motion_static_switch_enable); + set->motion_static_switch_enable = cfg->motion_static_switch_enable; + } + + if (set->deblur_str < 0 || set->deblur_str > 7) { + mpp_loge("invalid deblur strength not in range [0 : 7]\n"); + mpp_loge("restore deblur strength %d\n", cfg->deblur_str); + set->deblur_str = cfg->deblur_str; + } + + if (set->atr_str_i < 0 || set->atr_str_i > 3) { + mpp_loge("invalid anti ring strength of I frame not in range [0 : 3]\n"); + mpp_loge("restore anti ring strength of I frame %d\n", cfg->atr_str_i); + set->atr_str_i = cfg->atr_str_i; + } + + if (set->atr_str_p < 0 || set->atr_str_p > 3) { + mpp_loge("invalid anti ring strength of P frame not in range [0 : 3]\n"); + mpp_loge("restore anti ring strength of P frame %d\n", cfg->atr_str_p); + set->atr_str_p = cfg->atr_str_p; + } + + if (set->atl_str < 0 || set->atl_str > 3) { + mpp_loge("invalid anti line strength not in range [0 : 3]\n"); + mpp_loge("restore anti line strength %d\n", cfg->atl_str); + set->atl_str = cfg->atl_str; + } + + if (set->lambda_idx_p < 0 || set->lambda_idx_p > 8) { + mpp_loge("invalid lambda idx not in range [0 : 8]\n"); + mpp_loge("restore lambda idx %d\n", cfg->lambda_idx_p); + set->lambda_idx_p = cfg->lambda_idx_p; + } + + if (set->lambda_idx_i < 0 || set->lambda_idx_i > 8) { + mpp_loge("invalid I frame lambda idx not in range [0 : 8]\n"); + mpp_loge("restore I frame lambda idx %d\n", cfg->lambda_idx_i); + set->lambda_idx_i = cfg->lambda_idx_i; + } + + if (set->atf_str < 0 || set->atf_str > 3) { + mpp_loge("invalid anti flick strength not in range [0 : 3]\n"); + mpp_loge("restore anti flick strength %d\n", cfg->atf_str); + set->atf_str = cfg->atf_str; + } + + if (set->lgt_chg_lvl < 0 || set->lgt_chg_lvl > 7) { + mpp_loge("invalid lgt_chg_lvl %d not in range [0, 7]\n", set->lgt_chg_lvl); + mpp_loge("restore lgt_chg_lvl %d\n", cfg->lgt_chg_lvl); + set->lgt_chg_lvl = cfg->lgt_chg_lvl; + } + + if (set->static_frm_num < 0 || set->static_frm_num > 7) { + mpp_loge("invalid static_frm_num %d not in range [0, 7]\n", set->static_frm_num); + mpp_loge("restore static_frm_num %d\n", cfg->static_frm_num); + set->static_frm_num = cfg->static_frm_num; + } + + if (set->madp16_th < 0 || set->madp16_th > 63) { + mpp_loge("invalid madp16_th %d not in range [0, 255]\n", set->madp16_th); + mpp_loge("restore madp16_th %d\n", cfg->madp16_th); + set->madp16_th = cfg->madp16_th; + } + + if (!(set->skip16_wgt == 0 || (set->skip16_wgt >= 3 && set->skip16_wgt <= 8))) { + mpp_loge("invalid skip16_wgt %d not in range [3, 8] or 0\n", set->skip16_wgt); + mpp_loge("restore skip16_wgt %d\n", cfg->skip16_wgt); + set->skip16_wgt = cfg->skip16_wgt; + } + + if (!(set->skip32_wgt == 0 || (set->skip32_wgt >= 3 && set->skip32_wgt <= 8))) { + mpp_loge("invalid skip32_wgt %d not in range [3, 8] or 0\n", set->skip32_wgt); + mpp_loge("restore skip32_wgt %d\n", cfg->skip32_wgt); + set->skip32_wgt = cfg->skip32_wgt; + } + + set->bmap_qpmin_i = mpp_clip(set->bmap_qpmin_i, 1, 51); + set->bmap_qpmin_p = mpp_clip(set->bmap_qpmin_p, 1, 51); + set->bmap_qpmax_i = mpp_clip(set->bmap_qpmax_i, 1, 51); + set->bmap_qpmax_p = mpp_clip(set->bmap_qpmax_p, 1, 51); + set->min_bg_fqp = mpp_clip(set->min_bg_fqp, 1, 51); + set->max_bg_fqp = mpp_clip(set->max_bg_fqp, 1, 51); + set->min_fg_fqp = mpp_clip(set->min_fg_fqp, 1, 51); + set->max_fg_fqp = mpp_clip(set->max_fg_fqp, 1, 51); + set->bg_delta_qp_i = mpp_clip(set->bg_delta_qp_i, -32, 32); + set->bg_delta_qp_p = mpp_clip(set->bg_delta_qp_p, -32, 32); + set->fg_delta_qp_i = mpp_clip(set->fg_delta_qp_i, -32, 32); + set->fg_delta_qp_p = mpp_clip(set->fg_delta_qp_p, -32, 32); + set->fg_area = mpp_clip(set->fg_area, -1, 100); + + if (set->scene_mode != cfg->scene_mode || + set->motion_static_switch_enable != cfg->motion_static_switch_enable || + set->deblur_str != cfg->deblur_str) + enc_set_rc_updated(enc, "tune cfg changed"); + + memcpy(cfg, set, sizeof(*cfg)); +} + +static void proc_h264_cfg(MppEncImpl *enc) +{ + MppEncH264Cfg *cfg = &enc->cfg->h264; + MppEncH264Cfg *set = &enc->set->h264; + rk_u32 flag = *mpp_enc_cfg_h264_change(enc->set); + rk_s32 profile = set->profile; + rk_s32 entropy_coding_mode = set->entropy_coding_mode_ex; + rk_s32 cabac_init_idc = set->cabac_init_idc_ex; + rk_s32 transform8x8_mode = set->transform8x8_mode_ex; + rk_s32 disable_cabac = (H264_PROFILE_FREXT_CAVLC444 == profile || + H264_PROFILE_BASELINE == profile || + H264_PROFILE_EXTENDED == profile); + + enc_dbg_cfg("h264 cfg change 0x%x\n", flag); + + if (enc->cfg->rc.refresh_en) { + RK_U32 mb_rows; + + if (!enc->cfg->rc.refresh_mode) + mb_rows = MPP_ALIGN(enc->cfg->prep.height, 16) / 16; + else + mb_rows = MPP_ALIGN(enc->cfg->prep.width, 16) / 16; + + enc->cfg->rc.refresh_length = (mb_rows + enc->cfg->rc.refresh_num - 1) / + enc->cfg->rc.refresh_num; + if (enc->cfg->rc.gop < enc->cfg->rc.refresh_length) + enc->cfg->rc.refresh_length = enc->cfg->rc.gop; + } + + if (!flag) + return; + + /* 1. check input h264 config */ + if (disable_cabac) { + if (entropy_coding_mode) { + mpp_loge("Warning: invalid cabac_en %d for h264 profile %d, set to 0.\n", + entropy_coding_mode, profile); + entropy_coding_mode = 0; + } + + if (cabac_init_idc >= 0) { + mpp_loge("Warning: invalid cabac_init_idc %d for h264 profile %d, set to -1.\n", + cabac_init_idc, profile); + + cabac_init_idc = -1; + } + } + + if (profile < H264_PROFILE_HIGH && transform8x8_mode) { + mpp_loge("Warning: invalid transform8x8_mode %d for h264 profile %d, set to 0.\n", + transform8x8_mode, profile); + + transform8x8_mode = 0; + } + + set->entropy_coding_mode = entropy_coding_mode; + set->cabac_init_idc = cabac_init_idc; + set->transform8x8_mode = transform8x8_mode; + + memcpy(cfg, set, sizeof(*cfg)); + enc_set_resend_hdr(enc, "h264 cfg changed"); +} + +static void proc_h265_cfg(MppEncImpl *enc) +{ + MppEncH265Cfg *cfg = &enc->cfg->h265; + MppEncH265Cfg *set = &enc->set->h265; + rk_u32 flag = *mpp_enc_cfg_h265_change(enc->set); + + enc_dbg_cfg("h265 cfg change 0x%x\n", flag); + + if (enc->cfg->rc.refresh_en) { + RK_U32 mb_rows; + + if (!enc->cfg->rc.refresh_mode) + mb_rows = MPP_ALIGN(enc->cfg->prep.height, 32) / 32; + else + mb_rows = MPP_ALIGN(enc->cfg->prep.width, 32) / 32; + + enc->cfg->rc.refresh_length = (mb_rows + enc->cfg->rc.refresh_num - 1) / + enc->cfg->rc.refresh_num; + if (enc->cfg->rc.gop < enc->cfg->rc.refresh_length) + enc->cfg->rc.refresh_length = enc->cfg->rc.gop; + } + + if (!flag) + return; + + if (set->const_intra_pred) { + RockchipSocType soc_type = mpp_get_soc_type(); + + if (soc_type >= ROCKCHIP_SOC_RK3576) { + set->const_intra_pred = 0; + + mpp_logw("warning: Only rk3576's HEVC encoder support constraint intra prediction flag = 1."); + } + } + + if (set->trans_cfg.cb_qp_offset != set->trans_cfg.cr_qp_offset) { + mpp_loge("h265 cr_qp_offset %d MUST equal to cb_qp_offset %d. FORCE to same value\n", + set->trans_cfg.cb_qp_offset, set->trans_cfg.cr_qp_offset); + + set->trans_cfg.cr_qp_offset = set->trans_cfg.cb_qp_offset; + } + + if (set->trans_cfg.diff_cu_qp_delta_depth > 2 || set->trans_cfg.diff_cu_qp_delta_depth < 0) { + mpp_loge("h265 diff_cu_qp_delta_depth must be in [0, 2] restore to 1\n"); + set->trans_cfg.diff_cu_qp_delta_depth = 1; + } + + memcpy(cfg, set, sizeof(*cfg)); + enc_set_resend_hdr(enc, "h265 cfg changed"); +} + +static void proc_jpeg_cfg(MppEncImpl *enc) +{ + MppEncRcCfg *rc_cfg = &enc->cfg->rc; + MppEncRcCfg *rc_set = &enc->set->rc; + MppEncJpegCfg *cfg = &enc->cfg->jpeg; + MppEncJpegCfg *set = &enc->set->jpeg; + rk_u32 flag = *mpp_enc_cfg_jpeg_change(enc->set); + rk_u32 update = 1; + rk_u32 update_rc = 0; + + enc_dbg_cfg("jpeg cfg change 0x%x\n", flag); + + if (!flag) + return; + + /* check input change then check validity */ + if (set->quant != set->quant_ext) { + /* quant is set */ + if (set->quant_ext < 0 || set->quant_ext > 10) { + mpp_loge("invalid quant %d not in range [0, 10] restore to 10 (best quality)\n", set->quant_ext); + set->quant_ext = 10; + } + + rc_set->rc_mode = MPP_ENC_RC_MODE_FIXQP; + update_rc = 1; + set->quant = set->quant_ext; + set->q_mode = JPEG_QUANT; + mpp_logi("set jpeg quant %d\n", set->quant); + } else if (set->q_factor != set->q_factor_ext || + set->qf_max != set->qf_max_ext || + set->qf_min != set->qf_min_ext) { + if (set->q_factor_ext < 1 || set->q_factor_ext > 99) { + mpp_loge("invalid q_factor %d out of range [1, 99] restore to 80\n", set->q_factor_ext); + set->q_factor_ext = 80; + } + if (set->qf_min_ext < 1 || set->qf_min_ext > 99) { + mpp_loge("invalid qf_min %d out of range [1, 99] restore to 1\n", set->qf_min_ext); + set->qf_min_ext = 1; + } + if (set->qf_max_ext < 1 || set->qf_max_ext > 99) { + mpp_loge("invalid qf_max %d out of range [1, 99] restore to 99\n", set->qf_max_ext); + set->qf_max_ext = 99; + } + + /* generate q_factor */ + set->q_factor = set->q_factor_ext; + set->qf_max = set->qf_max_ext; + set->qf_min = set->qf_min_ext; + set->q_mode = JPEG_QFACTOR; + mpp_logi("set jpeg qfactor [%d:%d:%d]\n", set->q_factor, set->qf_min, set->qf_max); + } else { + /* check qtable direct update */ + static KmppObjDef def = NULL; + static KmppEntry *tbl_qtable = NULL; + static rk_s32 once = 1; + + if (!tbl_qtable && once) { + def = kmpp_obj_to_objdef(enc->set_obj); + kmpp_objdef_get_entry(def, "jpeg:qtable_y", &tbl_qtable); + + if (!tbl_qtable) + mpp_loge("failed to get jpeg qtable update flag\n"); + + once = 0; + } + + if (kmpp_obj_tbl_test(enc->set_obj, tbl_qtable)) { + rc_set->rc_mode = MPP_ENC_RC_MODE_FIXQP; + update_rc = 1; + set->q_mode = JPEG_QTABLE; + mpp_logi("set jpeg qtable\n"); + } else { + update = 0; + } + } + + if (!update) { + set->q_mode = JPEG_QUANT; + set->quant = 10; + rc_set->rc_mode = MPP_ENC_RC_MODE_FIXQP; + update_rc = 1; + + mpp_loge("set jpeg invalid cfg, use default quant 10\n"); + } + memcpy(cfg, set, sizeof(*cfg)); + + if (update_rc) + rc_cfg->rc_mode = rc_set->rc_mode; + cfg->update = 1; + enc_set_rc_updated(enc, "jpeg cfg changed"); +} + +static void proc_vp8_cfg(MppEncImpl *enc) +{ + MppEncH265Cfg *cfg = &enc->cfg->h265; + MppEncH265Cfg *set = &enc->set->h265; + rk_u32 flag = *mpp_enc_cfg_vp8_change(enc->set); + + enc_dbg_cfg("vp8 cfg change 0x%x\n", flag); + + if (!flag) + return; + + memcpy(cfg, set, sizeof(*cfg)); +} + +static MPP_RET mpp_enc_control_set_ref_cfg(MppEncImpl *enc, void *param) +{ + MPP_RET ret = MPP_OK; + MppEncRefCfg src = (MppEncRefCfg)param; + MppEncRefCfg dst = enc->cfg->ref_cfg; + + if (NULL == src) + src = mpp_enc_ref_default(); + + if (NULL == dst) { + mpp_enc_ref_cfg_init(&dst); + enc->cfg->ref_cfg = dst; + } + + ret = mpp_enc_ref_cfg_copy(dst, src); + if (ret) { + mpp_err_f("failed to copy ref cfg ret %d\n", ret); + } + + ret = mpp_enc_refs_set_cfg(enc->refs, dst); + if (ret) { + mpp_err_f("failed to set ref cfg ret %d\n", ret); + } + + if (mpp_enc_refs_update_hdr(enc->refs)) + enc->hdr_status.val = 0; + + return ret; +} + +MPP_RET mpp_enc_proc_cfg(MppEncImpl *enc, MpiCmd cmd, void *param) +{ + MppEncCfgSet *cfg = enc->cfg; + MPP_RET ret = MPP_OK; + + switch (cmd) { + case MPP_ENC_SET_CFG : { + KmppObj in_obj = (KmppObj)param; + MppEncCfgSet *set = enc->set; + MPP_RET ret_tmp = MPP_OK; + + /* update all element to temporal storage */ + ret = (MPP_RET)kmpp_obj_update(enc->set_obj, in_obj); + if (ret) { + mpp_loge_f("failed to update set_obj\n"); + break; + } + + /* fix for cfg not setup coding */ + if (set->base.coding != enc->coding) { + set->base.coding = enc->coding; + } + + /* check all date status in set_obj */ + /* 1. base cfg -> no check */ + memcpy(&cfg->base, &set->base, sizeof(cfg->base)); + + /* 2. prep cfg -> chech and show resolution update */ + proc_prep_cfg(enc); + + /* 3. rc cfg -> check and show bps update */ + proc_rc_cfg(enc); + + /* 4. split cfg -> check with restore */ + proc_split_cfg(&cfg->split, &set->split); + + /* 5. hw cfg -> check with restore */ + proc_hw_cfg(enc); + + /* 6. tune cfg -> check with restore */ + proc_tune_cfg(enc); + + /* 7. codec config */ + switch (enc->coding) { + case MPP_VIDEO_CodingAVC : { + proc_h264_cfg(enc); + } break; + case MPP_VIDEO_CodingHEVC : { + proc_h265_cfg(enc); + } break; + case MPP_VIDEO_CodingMJPEG : { + proc_jpeg_cfg(enc); + } break; + case MPP_VIDEO_CodingVP8 : { + proc_vp8_cfg(enc); + } break; + default : { + mpp_loge_f("unsupport coding %d\n", enc->coding); + } break; + } + + if (enc->cfg->rc.refresh_en) + mpp_enc_refs_set_refresh_length(enc->refs, enc->cfg->rc.refresh_length); + + /* Then process the rest config */ + ret_tmp = enc_impl_proc_cfg(enc->impl, cmd, param); + if (ret_tmp != MPP_OK) + ret = ret_tmp; + } break; + case MPP_ENC_SET_IDR_FRAME : { + enc->frm_cfg.force_flag |= ENC_FORCE_IDR; + enc->frm_cfg.force_idr++; + } break; + case MPP_ENC_GET_HDR_SYNC : + case MPP_ENC_GET_EXTRA_INFO : { + /* + * NOTE: get stream header should use user's MppPacket + * If we provide internal MppPacket to external user + * we do not known when the buffer usage is finished. + * So encoder always write its header to external buffer + * which is provided by user. + */ + if (!enc->hdr_status.ready) { + enc_impl_gen_hdr(enc->impl, enc->hdr_pkt); + enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt); + enc->hdr_status.ready = 1; + } + + if (cmd == MPP_ENC_GET_EXTRA_INFO) { + mpp_err("Please use MPP_ENC_GET_HDR_SYNC instead of unsafe MPP_ENC_GET_EXTRA_INFO\n"); + mpp_err("NOTE: MPP_ENC_GET_HDR_SYNC needs MppPacket input\n"); + + *(MppPacket *)param = enc->hdr_pkt; + } else { + mpp_packet_copy((MppPacket)param, enc->hdr_pkt); + } + + if (enc->hdr_pkt) { + Mpp *mpp = (Mpp *)enc->mpp; + // dump output + mpp_ops_enc_get_pkt(mpp->mDump, enc->hdr_pkt); + } + + enc->hdr_status.added_by_ctrl = 1; + } break; + case MPP_ENC_PRE_ALLOC_BUFF : { + /* deprecated control */ + mpp_log("deprecated MPP_ENC_PRE_ALLOC_BUFF control\n"); + } break; + case MPP_ENC_GET_RC_API_ALL : { + RcApiQueryAll *query = (RcApiQueryAll *)param; + + rc_brief_get_all(query); + } break; + case MPP_ENC_GET_RC_API_BY_TYPE : { + RcApiQueryType *query = (RcApiQueryType *)param; + + rc_brief_get_by_type(query); + } break; + case MPP_ENC_SET_RC_API_CFG : { + const RcImplApi *api = (const RcImplApi *)param; + + rc_api_add(api); + } break; + case MPP_ENC_GET_RC_API_CURRENT : { + RcApiBrief *dst = (RcApiBrief *)param; + + *dst = enc->rc_brief; + } break; + case MPP_ENC_SET_RC_API_CURRENT : { + RcApiBrief *src = (RcApiBrief *)param; + + mpp_assert(src->type == enc->coding); + enc->rc_brief = *src; + enc->rc_status.rc_api_user_cfg = 1; + enc->rc_status.rc_api_updated = 1; + } break; + case MPP_ENC_SET_HEADER_MODE : { + if (param) { + MppEncHeaderMode mode = *((MppEncHeaderMode *)param); + + if (mode < MPP_ENC_HEADER_MODE_BUTT) { + enc->hdr_mode = mode; + enc_dbg_ctrl("header mode set to %d\n", mode); + } else { + mpp_err_f("invalid header mode %d\n", mode); + ret = MPP_NOK; + } + } else { + mpp_err_f("invalid NULL ptr on setting header mode\n"); + ret = MPP_NOK; + } + } break; + case MPP_ENC_SET_SEI_CFG : { + if (param) { + MppEncSeiMode mode = *((MppEncSeiMode *)param); + + if (mode <= MPP_ENC_SEI_MODE_ONE_FRAME) { + enc->sei_mode = mode; + enc_dbg_ctrl("sei mode set to %d\n", mode); + } else { + mpp_err_f("invalid sei mode %d\n", mode); + ret = MPP_NOK; + } + } else { + mpp_err_f("invalid NULL ptr on setting header mode\n"); + ret = MPP_NOK; + } + } break; + case MPP_ENC_SET_REF_CFG : { + ret = mpp_enc_control_set_ref_cfg(enc, param); + enc_set_rc_updated(enc, "ref cfg update"); + } break; + case MPP_ENC_SET_OSD_PLT_CFG : { + MppEncOSDPltCfg *src = (MppEncOSDPltCfg *)param; + MppEncOSDPltCfg *dst = &enc->cfg->plt_cfg; + RK_U32 change = src->change; + + if (change) { + RK_S32 cfg_err = 0; + + if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_MODE) { + if (src->type >= MPP_ENC_OSD_PLT_TYPE_BUTT) { + mpp_err_f("invalid osd plt type %d\n", src->type); + cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_MODE; + } else + dst->type = src->type; + } + + if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL) { + if (src->plt == NULL) { + mpp_err_f("invalid osd plt NULL pointer\n"); + cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL; + } else { + memcpy(dst->plt, src->plt, sizeof(MppEncOSDPlt)); + } + } + + dst->change = cfg_err ? 0 : change; + enc_dbg_ctrl("plt type %d data %p\n", dst->type, src->plt); + } + } break; + default : { + ret = enc_impl_proc_cfg(enc->impl, cmd, param); + } break; + } + + if (check_hal_info_update(cmd)) + enc->hal_info_updated = 0; + + check_low_delay_part_mode(enc); + check_low_delay_output(enc); + + return ret; +} + +static const char *name_of_rc_mode[] = { + "vbr", + "cbr", + "fixqp", + "avbr", + "smtrc", + "sp_enc" +}; + +static void update_rc_cfg_log(MppEncImpl *impl, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + + RK_S32 size = impl->rc_cfg_size; + RK_S32 length = impl->rc_cfg_length; + char *base = impl->rc_cfg_info + length; + + length += vsnprintf(base, size - length, fmt, args); + if (length >= size) + mpp_log_f("rc cfg log is full\n"); + + impl->rc_cfg_length = length; + + va_end(args); +} + +static void update_user_datas(EncImpl impl, MppPacket packet, MppFrame frame, HalEncTask *hal_task) +{ + MppMeta frm_meta = mpp_frame_get_meta(frame); + MppEncUserData *user_data = NULL; + MppEncUserDataSet *user_datas = NULL; + RK_S32 length = 0; + + mpp_meta_get_ptr(frm_meta, KEY_USER_DATA, (void**)&user_data); + if (user_data) { + if (user_data->pdata && user_data->len) { + enc_impl_add_prefix(impl, packet, &length, uuid_usr_data, + user_data->pdata, user_data->len); + + hal_task->sei_length += length; + hal_task->length += length; + } else + mpp_err_f("failed to insert user data %p len %d\n", + user_data->pdata, user_data->len); + } + + mpp_meta_get_ptr(frm_meta, KEY_USER_DATAS, (void**)&user_datas); + if (user_datas && user_datas->count) { + RK_U32 i = 0; + + for (i = 0; i < user_datas->count; i++) { + MppEncUserDataFull *user_data_v2 = &user_datas->datas[i]; + if (user_data_v2->pdata && user_data_v2->len) { + if (user_data_v2->uuid) + enc_impl_add_prefix(impl, packet, &length, user_data_v2->uuid, + user_data_v2->pdata, user_data_v2->len); + else + enc_impl_add_prefix(impl, packet, &length, uuid_debug_info, + user_data_v2->pdata, user_data_v2->len); + + hal_task->sei_length += length; + hal_task->length += length; + } + } + } +} + +static void set_rc_cfg(RcCfg *cfg, MppEncCfgSet *cfg_set) +{ + MppEncRcCfg *rc = &cfg_set->rc; + MppEncPrepCfg *prep = &cfg_set->prep; + MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg_set->ref_cfg; + MppEncCpbInfo *info = &ref->cpb_info; + MppCodingType coding = cfg_set->base.coding; + + cfg->width = prep->width; + cfg->height = prep->height; + + switch (rc->rc_mode) { + case MPP_ENC_RC_MODE_CBR : { + cfg->mode = RC_CBR; + } break; + case MPP_ENC_RC_MODE_VBR : { + cfg->mode = RC_VBR; + } break; + case MPP_ENC_RC_MODE_AVBR : { + cfg->mode = RC_AVBR; + } break; + case MPP_ENC_RC_MODE_FIXQP: { + cfg->mode = RC_FIXQP; + } break; + case MPP_ENC_RC_MODE_SMTRC: { + cfg->mode = RC_SMT; + } break; + case MPP_ENC_RC_MODE_SE: { + cfg->mode = RC_SE; + } break; + default : { + cfg->mode = RC_AVBR; + } break; + } + + cfg->fps.fps_in_flex = rc->fps_in_flex; + cfg->fps.fps_in_num = rc->fps_in_num; + cfg->fps.fps_in_denom = rc->fps_in_denom; + cfg->fps.fps_out_flex = rc->fps_out_flex; + cfg->fps.fps_out_num = rc->fps_out_num; + cfg->fps.fps_out_denom = rc->fps_out_denom; + cfg->igop = rc->gop; + cfg->max_i_bit_prop = rc->max_i_prop; + cfg->min_i_bit_prop = rc->min_i_prop; + cfg->init_ip_ratio = rc->init_ip_ratio; + + cfg->bps_target = rc->bps_target; + cfg->bps_max = rc->bps_max; + cfg->bps_min = rc->bps_min; + cfg->scene_mode = cfg_set->tune.scene_mode; + cfg->rc_container = cfg_set->tune.rc_container; + + cfg->hier_qp_cfg.hier_qp_en = rc->hier_qp_en; + memcpy(cfg->hier_qp_cfg.hier_frame_num, rc->hier_frame_num, sizeof(rc->hier_frame_num)); + memcpy(cfg->hier_qp_cfg.hier_qp_delta, rc->hier_qp_delta, sizeof(rc->hier_qp_delta)); + + mpp_assert(rc->fps_out_num); + cfg->stats_time = rc->stats_time ? rc->stats_time : 3; + cfg->stats_time = mpp_clip(cfg->stats_time, 1, 60); + + /* quality configure */ + switch (coding) { + case MPP_VIDEO_CodingAVC : + case MPP_VIDEO_CodingHEVC : + case MPP_VIDEO_CodingVP8 : { + cfg->init_quality = rc->qp_init; + cfg->max_quality = rc->qp_max; + cfg->min_quality = rc->qp_min; + cfg->max_i_quality = rc->qp_max_i ? rc->qp_max_i : rc->qp_max; + cfg->min_i_quality = rc->qp_min_i ? rc->qp_min_i : rc->qp_min; + cfg->i_quality_delta = rc->qp_delta_ip; + cfg->vi_quality_delta = rc->qp_delta_vi; + cfg->fqp_min_p = rc->fqp_min_p == INT_MAX ? cfg->min_quality : rc->fqp_min_p; + cfg->fqp_min_i = rc->fqp_min_i == INT_MAX ? cfg->min_i_quality : rc->fqp_min_i; + cfg->fqp_max_p = rc->fqp_max_p == INT_MAX ? cfg->max_quality : rc->fqp_max_p; + cfg->fqp_max_i = rc->fqp_max_i == INT_MAX ? cfg->max_i_quality : rc->fqp_max_i; + } break; + case MPP_VIDEO_CodingMJPEG : { + MppEncJpegCfg *jpeg = &cfg_set->jpeg; + + cfg->init_quality = 100 - jpeg->q_factor; + cfg->max_quality = 100 - jpeg->qf_max; + cfg->min_quality = 100 - jpeg->qf_min; + cfg->max_i_quality = 100 - jpeg->qf_max; + cfg->min_i_quality = 100 - jpeg->qf_min; + cfg->fqp_min_i = 100 - jpeg->qf_max; + cfg->fqp_max_i = 100 - jpeg->qf_min; + cfg->fqp_min_p = 100 - jpeg->qf_max; + cfg->fqp_max_p = 100 - jpeg->qf_min; + } break; + default : { + mpp_err_f("unsupport coding type %d\n", coding); + } break; + } + + cfg->layer_bit_prop[0] = 256; + cfg->layer_bit_prop[1] = 0; + cfg->layer_bit_prop[2] = 0; + cfg->layer_bit_prop[3] = 0; + + cfg->max_reencode_times = rc->max_reenc_times; + cfg->drop_mode = rc->drop_mode; + cfg->drop_thd = rc->drop_threshold; + cfg->drop_gap = rc->drop_gap; + + cfg->super_cfg.rc_priority = rc->rc_priority; + cfg->super_cfg.super_mode = rc->super_mode; + cfg->super_cfg.super_i_thd = rc->super_i_thd; + cfg->super_cfg.super_p_thd = rc->super_p_thd; + + cfg->debreath_cfg.enable = rc->debreath_en; + cfg->debreath_cfg.strength = rc->debre_strength; + + cfg->refresh_len = rc->refresh_length; + + if (info->st_gop) { + cfg->vgop = info->st_gop; + if (cfg->vgop >= rc->fps_out_num / rc->fps_out_denom && + cfg->vgop < cfg->igop ) { + cfg->gop_mode = SMART_P; + if (!cfg->vi_quality_delta) + cfg->vi_quality_delta = 2; + } + } + + if (coding == MPP_VIDEO_CodingAVC || coding == MPP_VIDEO_CodingHEVC) { + mpp_log("mode %s bps [%d:%d:%d] fps %s [%d/%d] -> %s [%d/%d] gop i [%d] v [%d]\n", + name_of_rc_mode[cfg->mode], + rc->bps_min, rc->bps_target, rc->bps_max, + cfg->fps.fps_in_flex ? "flex" : "fix", + cfg->fps.fps_in_num, cfg->fps.fps_in_denom, + cfg->fps.fps_out_flex ? "flex" : "fix", + cfg->fps.fps_out_num, cfg->fps.fps_out_denom, + cfg->igop, cfg->vgop); + } +} + +MPP_RET mpp_enc_proc_rc_update(MppEncImpl *enc) +{ + MPP_RET ret = MPP_OK; + + // check and update rate control api + if (!enc->rc_status.rc_api_inited || enc->rc_status.rc_api_updated) { + RcApiBrief *brief = &enc->rc_brief; + + if (enc->rc_ctx) { + enc_dbg_detail("rc deinit %p\n", enc->rc_ctx); + rc_deinit(enc->rc_ctx); + enc->rc_ctx = NULL; + } + + /* NOTE: default name is NULL */ + ret = rc_init(&enc->rc_ctx, enc->coding, &brief->name); + if (ret) + mpp_err("enc %p fail to init rc %s\n", enc, brief->name); + else + enc->rc_status.rc_api_inited = 1; + + enc_dbg_detail("rc init %p name %s ret %d\n", enc->rc_ctx, brief->name, ret); + enc->rc_status.rc_api_updated = 0; + + enc->rc_cfg_length = 0; + update_rc_cfg_log(enc, "%s:", brief->name); + enc->rc_cfg_pos = enc->rc_cfg_length; + } + + // check and update rate control config + if (enc->rc_status.rc_api_user_cfg) { + MppEncCfgSet *cfg = enc->cfg; + RcCfg usr_cfg; + + enc_dbg_detail("rc update cfg start\n"); + + memset(&usr_cfg, 0 , sizeof(usr_cfg)); + set_rc_cfg(&usr_cfg, cfg); + ret = rc_update_usr_cfg(enc->rc_ctx, &usr_cfg); + + enc_dbg_detail("rc update cfg done\n"); + enc->rc_status.rc_api_user_cfg = 0; + + enc->rc_cfg_length = enc->rc_cfg_pos; + update_rc_cfg_log(enc, "%s-b:%d[%d:%d]-g:%d-q:%d:[%d:%d]:[%d:%d]:%d\n", + name_of_rc_mode[usr_cfg.mode], + usr_cfg.bps_target, + usr_cfg.bps_min, usr_cfg.bps_max, usr_cfg.igop, + usr_cfg.init_quality, + usr_cfg.min_quality, usr_cfg.max_quality, + usr_cfg.min_i_quality, usr_cfg.max_i_quality, + usr_cfg.i_quality_delta); + } + + return ret; +} + +#define ENC_RUN_FUNC2(func, ctx, task, mpp, ret) \ + ret = func(ctx, task); \ + if (ret) { \ + mpp_err("mpp %p "#func":%-4d failed return %d", \ + mpp, __LINE__, ret); \ + goto TASK_DONE; \ + } + +static MPP_RET mpp_enc_check_frm_pkt(MppEncImpl *enc) +{ + enc->frm_buf = NULL; + enc->pkt_buf = NULL; + + if (enc->packet) + enc->pkt_buf = mpp_packet_get_buffer(enc->packet); + else + mpp_packet_new(&enc->packet); + + if (enc->frame) { + RK_S64 pts = mpp_frame_get_pts(enc->frame); + MppBuffer frm_buf = mpp_frame_get_buffer(enc->frame); + + enc->task_pts = pts; + enc->frm_buf = frm_buf; + + mpp_packet_set_pts(enc->packet, pts); + mpp_packet_set_dts(enc->packet, mpp_frame_get_dts(enc->frame)); + + if (mpp_frame_get_eos(enc->frame)) + mpp_packet_set_eos(enc->packet); + else + mpp_packet_clr_eos(enc->packet); + } + + return (NULL == enc->frame || NULL == enc->frm_buf) ? MPP_NOK : MPP_OK; +} + +static MPP_RET mpp_enc_check_pkt_buf(MppEncImpl *enc) +{ + if (NULL == enc->pkt_buf) { + /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */ + Mpp *mpp = (Mpp *)enc->mpp; + MppEncPrepCfg *prep = &enc->cfg->prep; + RK_U32 width = MPP_ALIGN(prep->width, 16); + RK_U32 height = MPP_ALIGN(prep->height, 16); + RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ? + (width * height * 3 / 2) : (width * height); + MppPacketImpl *pkt = (MppPacketImpl *)enc->packet; + MppBuffer buffer = NULL; + + mpp_assert(size); + mpp_buffer_get(mpp->mPacketGroup, &buffer, size); + mpp_buffer_attach_dev(buffer, enc->dev); + mpp_assert(buffer); + enc->pkt_buf = buffer; + pkt->data = mpp_buffer_get_ptr(buffer); + pkt->pos = pkt->data; + pkt->size = mpp_buffer_get_size(buffer); + pkt->length = 0; + pkt->buffer = buffer; + + enc_dbg_detail("create output pkt %p buf %p\n", enc->packet, buffer); + } else { + enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n", + enc->packet, enc->pkt_buf, + mpp_packet_get_pos(enc->packet), + mpp_packet_get_length(enc->packet)); + } + + return MPP_OK; +} + +static MPP_RET mpp_enc_proc_two_pass(Mpp *mpp, EncAsyncTaskInfo *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + MPP_RET ret = MPP_OK; + + if (mpp_enc_refs_next_frm_is_intra(enc->refs)) { + EncRcTask *rc_task = &task->rc; + EncFrmStatus frm_bak = rc_task->frm; + EncRcTaskInfo rc_info = rc_task->info; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->task; + EncImpl impl = enc->impl; + MppEncHal hal = enc->enc_hal; + MppPacket packet = hal_task->packet; + RK_S32 task_len = hal_task->length; + RK_S32 hw_len = hal_task->hw_length; + RK_S32 pkt_len = mpp_packet_get_length(packet); + + enc_dbg_detail("task %d two pass mode enter\n", frm->seq_idx); + rc_task->info = enc->rc_info_prev; + hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet); + + enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx); + mpp_enc_refs_get_cpb_pass1(enc->refs, cpb); + + enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal get task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal wait\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal ret task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); + + //recover status & packet + mpp_packet_set_length(packet, pkt_len); + mpp_packet_set_segment_nb(packet, hal_task->segment_nb); + hal_task->hw_length = hw_len; + hal_task->length = task_len; + + *frm = frm_bak; + rc_task->info = rc_info; + + enc_dbg_detail("task %d two pass mode leave\n", frm->seq_idx); + } +TASK_DONE: + return ret; +} + +static void mpp_enc_rc_info_backup(MppEncImpl *enc, EncAsyncTaskInfo *task) +{ + if (!enc->support_hw_deflicker || !enc->cfg->rc.debreath_en) + return; + + enc->rc_info_prev = task->rc.info; +} + +static MPP_RET mpp_enc_force_pskip_check(Mpp *mpp, EncAsyncTaskInfo *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + EncRcTask *rc_task = &task->rc; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + MppEncCpbInfo cpb_info; + RK_U32 max_tid = 0; + MPP_RET ret = MPP_OK; + + mpp_enc_refs_get_cpb_info(enc->refs, &cpb_info); + max_tid = cpb_info.max_st_tid; + + if (task->usr.force_flag & ENC_FORCE_IDR) { + enc_dbg_detail("task %d, FORCE IDR should not be set as pskip frames", frm->seq_idx); + ret = MPP_NOK; + } + if (cpb->curr.is_idr) { + enc_dbg_detail("task %d, IDR frames should not be set as pskip frames", frm->seq_idx); + ret = MPP_NOK; + } + if (cpb->curr.is_lt_ref) { + enc_dbg_detail("task %d, LTR frames should not be set as pskip frames", frm->seq_idx); + ret = MPP_NOK; + } + if (cpb->curr.temporal_id != max_tid) { + enc_dbg_detail("task %d, Only top-layer frames can be set as pskip frames in TSVC mode", frm->seq_idx); + ret = MPP_NOK; + } + if (cpb->curr.ref_mode != REF_TO_PREV_REF_FRM) { + enc_dbg_detail("task %d, Only frames with reference mode set to prev_ref can be set as pskip frames", frm->seq_idx); + ret = MPP_NOK; + } + + return ret; +} + +static MPP_RET mpp_enc_force_pskip(Mpp *mpp, EncAsyncTaskInfo *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + EncImpl impl = enc->impl; + MppEncRefFrmUsrCfg *frm_cfg = &task->usr; + EncRcTask *rc_task = &task->rc; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->task; + MPP_RET ret = MPP_OK; + + enc_dbg_func("enter\n"); + + frm_cfg->force_pskip++; + if (frm->force_pskip) + frm_cfg->force_flag |= ENC_FORCE_PSKIP_NON_REF; + else if (frm->force_pskip_is_ref) + frm_cfg->force_flag |= ENC_FORCE_PSKIP_IS_REF; + + /* NOTE: in some condition the pskip should not happen */ + mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg); + + enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx); + mpp_enc_refs_get_cpb(enc->refs, cpb); + + ret = mpp_enc_force_pskip_check(mpp, task); + + if (ret) { + mpp_enc_refs_rollback(enc->refs); + frm_cfg->force_pskip--; + if (frm->force_pskip) + frm_cfg->force_flag &= ~ENC_FORCE_PSKIP_NON_REF; + else if (frm->force_pskip_is_ref) + frm_cfg->force_flag &= ~ENC_FORCE_PSKIP_IS_REF; + return MPP_NOK; + } + + enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc frame start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d rc hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d enc sw enc start\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_sw_enc, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc hal end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d rc frame end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret); + +TASK_DONE: + enc_dbg_func("leave\n"); + return ret; +} + +static MPP_RET mpp_enc_get_pskip_mode(Mpp *mpp, EncAsyncTaskInfo *task, MppPskipMode *skip_mode) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + EncRcTask *rc_task = &task->rc; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->task; + MPP_RET ret = MPP_OK; + + skip_mode->pskip_is_ref = 0; + skip_mode->pskip_is_non_ref = 0; + enc->frame = hal_task->frame; + + if (mpp_frame_has_meta(enc->frame)) { + MppMeta frm_meta = mpp_frame_get_meta(enc->frame); + if (frm_meta) { + mpp_meta_get_s32(frm_meta, KEY_INPUT_PSKIP, &skip_mode->pskip_is_ref); + mpp_meta_get_s32(frm_meta, KEY_INPUT_PSKIP_NON_REF, &skip_mode->pskip_is_non_ref); + } + } + + if (skip_mode->pskip_is_ref == 1 && skip_mode->pskip_is_non_ref == 1) { + mpp_err("task %d, Don't cfg pskip frame to be both a ref and non-ref at the same time"); + ret = MPP_NOK; + } else { + frm->force_pskip = skip_mode->pskip_is_non_ref; + frm->force_pskip_is_ref = skip_mode->pskip_is_ref; + ret = MPP_OK; + } + + return ret; +} + + +static void mpp_enc_add_sw_header(MppEncImpl *enc, HalEncTask *hal_task) +{ + EncImpl impl = enc->impl; + MppEncHeaderStatus *hdr_status = &enc->hdr_status; + EncRcTask *rc_task = hal_task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + MppPacket packet = hal_task->packet; + MppFrame frame = hal_task->frame; + + if (!(hdr_status->val & HDR_ADDED_MASK)) { + RK_U32 add_header = 0; + + if (enc->hdr_mode == MPP_ENC_HEADER_MODE_EACH_IDR && frm->is_intra) + add_header |= 1; + + if (enc->cfg->rc.refresh_en && frm->is_i_recovery && !frm->is_idr) + add_header |= 2; + + if (add_header) { + enc_dbg_detail("task %d IDR header length %d\n", + frm->seq_idx, enc->hdr_len); + + mpp_packet_append(packet, enc->hdr_pkt); + + hal_task->header_length = enc->hdr_len; + hal_task->length += enc->hdr_len; + hdr_status->added_by_mode = 1; + } + + if ((add_header & 2) && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) { + RK_S32 length = 0; + + enc_impl_add_prefix(impl, packet, &length, uuid_refresh_cfg, + &enc->cfg->rc.refresh_length, 0); + + if (length) { + enc_dbg_detail("task %d refresh header length %d\n", + frm->seq_idx, enc->hdr_len); + + hal_task->sei_length += length; + hal_task->length += length; + } + } + } + + // check for header adding + check_hal_task_pkt_len(hal_task, "header adding"); + + /* 17. Add all prefix info before encoding */ + if (frm->is_idr && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) { + RK_S32 length = 0; + + enc_impl_add_prefix(impl, packet, &length, uuid_version, + enc->version_info, enc->version_length); + + hal_task->sei_length += length; + hal_task->length += length; + + length = 0; + enc_impl_add_prefix(impl, packet, &length, uuid_rc_cfg, + enc->rc_cfg_info, enc->rc_cfg_length); + + hal_task->sei_length += length; + hal_task->length += length; + } + + if (mpp_frame_has_meta(frame)) { + update_user_datas(impl, packet, frame, hal_task); + } + + // check for user data adding + check_hal_task_pkt_len(hal_task, "user data adding"); +} + +static MPP_RET mpp_enc_normal(Mpp *mpp, EncAsyncTaskInfo *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + EncImpl impl = enc->impl; + MppEncHal hal = enc->enc_hal; + EncRcTask *rc_task = &task->rc; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->task; + MPP_RET ret = MPP_OK; + EncAsyncStatus *status = &task->status; + + if (enc->support_hw_deflicker && enc->cfg->rc.debreath_en) { + ret = mpp_enc_proc_two_pass(mpp, task); + if (ret) + return ret; + } + + enc_dbg_detail("task %d check force pskip start\n", frm->seq_idx); + if (!status->check_frm_pskip) { + MppPskipMode skip_mode; + status->check_frm_pskip = 1; + + mpp_enc_get_pskip_mode((Mpp*)enc->mpp, task, &skip_mode); + if (skip_mode.pskip_is_ref || skip_mode.pskip_is_non_ref) { + ret = mpp_enc_force_pskip((Mpp*)enc->mpp, task); + if (ret) + enc_dbg_detail("task %d set force pskip failed.", frm->seq_idx); + else + goto TASK_DONE; + } + } + + enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx); + mpp_enc_refs_get_cpb(enc->refs, cpb); + + enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + + enc_dbg_frm_status("frm %d compare\n", cpb->curr.seq_idx); + enc_dbg_frm_status("seq_idx %d vs %d\n", frm->seq_idx, cpb->curr.seq_idx); + enc_dbg_frm_status("is_idr %d vs %d\n", frm->is_idr, cpb->curr.is_idr); + enc_dbg_frm_status("is_intra %d vs %d\n", frm->is_intra, cpb->curr.is_intra); + enc_dbg_frm_status("is_non_ref %d vs %d\n", frm->is_non_ref, cpb->curr.is_non_ref); + enc_dbg_frm_status("is_lt_ref %d vs %d\n", frm->is_lt_ref, cpb->curr.is_lt_ref); + enc_dbg_frm_status("lt_idx %d vs %d\n", frm->lt_idx, cpb->curr.lt_idx); + enc_dbg_frm_status("temporal_id %d vs %d\n", frm->temporal_id, cpb->curr.temporal_id); + enc_dbg_frm_status("frm %d done ***********************************\n", cpb->curr.seq_idx); + + enc_dbg_detail("task %d rc frame start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret); + + // 16. generate header before hardware stream + mpp_enc_add_sw_header(enc, hal_task); + + enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal get task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); + + hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet); + mpp_stopwatch_record(hal_task->stopwatch, "encode hal start"); + enc_dbg_detail("task %d hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal wait\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret); + + mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish"); + + enc_dbg_detail("task %d rc hal end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d hal ret task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_check_reenc, enc->rc_ctx, rc_task, mpp, ret); + +TASK_DONE: + return ret; +} + +static void mpp_enc_clr_rc_cb_info(EncRcTask *rc_task) +{ + EncRcTaskInfo *hal_rc = (EncRcTaskInfo *) &rc_task->info; + EncRcTaskInfo bak = rc_task->info; + + memset(hal_rc, 0, sizeof(rc_task->info)); + + hal_rc->frame_type = bak.frame_type; + hal_rc->bit_target = bak.bit_target; + hal_rc->bit_max = bak.bit_max; + hal_rc->bit_min = bak.bit_min; + hal_rc->quality_target = bak.quality_target; + hal_rc->quality_max = bak.quality_max; + hal_rc->quality_min = bak.quality_min; +} + +static MPP_RET mpp_enc_reenc_simple(Mpp *mpp, EncAsyncTaskInfo *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + MppEncHal hal = enc->enc_hal; + EncRcTask *rc_task = &task->rc; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->task; + MPP_RET ret = MPP_OK; + + enc_dbg_func("enter\n"); + + mpp_enc_clr_rc_cb_info(rc_task); + + enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_hal, enc->impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal get task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal wait\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc hal end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d hal ret task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_check_reenc, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times); + enc_dbg_func("leave\n"); + +TASK_DONE: + return ret; +} + +static MPP_RET mpp_enc_reenc_drop(Mpp *mpp, EncAsyncTaskInfo *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + EncRcTask *rc_task = &task->rc; + EncRcTaskInfo *info = &rc_task->info; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->task; + MPP_RET ret = MPP_OK; + + enc_dbg_func("enter\n"); + mpp_enc_refs_rollback(enc->refs); + + info->bit_real = hal_task->length; + info->quality_real = info->quality_target; + + enc_dbg_detail("task %d rc frame end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret); + +TASK_DONE: + enc_dbg_func("leave\n"); + return ret; +} + +static MPP_RET mpp_enc_reenc_force_pskip(Mpp *mpp, EncAsyncTaskInfo *task) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + EncImpl impl = enc->impl; + MppEncRefFrmUsrCfg *frm_cfg = &task->usr; + EncRcTask *rc_task = &task->rc; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + HalEncTask *hal_task = &task->task; + MPP_RET ret = MPP_OK; + + enc_dbg_func("enter\n"); + + frm_cfg->force_pskip++; + frm_cfg->force_flag |= ENC_FORCE_PSKIP_NON_REF; + + /* NOTE: in some condition the pskip should not happen */ + + mpp_enc_refs_rollback(enc->refs); + mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg); + + enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx); + mpp_enc_refs_get_cpb(enc->refs, cpb); + + enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d enc sw enc start\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_sw_enc, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc frame end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret); + +TASK_DONE: + enc_dbg_func("leave\n"); + return ret; +} + +static void mpp_enc_terminate_task(MppEncImpl *enc, EncAsyncTaskInfo *task) +{ + HalEncTask *hal_task = &task->task; + EncFrmStatus *frm = &task->rc.frm; + + mpp_stopwatch_record(hal_task->stopwatch, "encode task done"); + + if (enc->packet) { + /* setup output packet and meta data */ + mpp_packet_set_length(enc->packet, hal_task->length); + + /* + * First return output packet. + * Then enqueue task back to input port. + * Final user will release the mpp_frame they had input. + */ + enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts); + + mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, enc->packet); + mpp_port_enqueue(enc->output, enc->task_out); + } + + if (enc->task_in) { + enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts); + + mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame); + mpp_port_enqueue(enc->input, enc->task_in); + } + + reset_enc_task(enc); + task->status.val = 0; +} + +static MPP_RET try_get_enc_task(MppEncImpl *enc, EncAsyncTaskInfo *task, EncAsyncWait *wait) +{ + EncRcTask *rc_task = &task->rc; + EncFrmStatus *frm = &rc_task->frm; + MppEncRefFrmUsrCfg *frm_cfg = &task->usr; + MppEncHeaderStatus *hdr_status = &enc->hdr_status; + EncAsyncStatus *status = &task->status; + HalEncTask *hal_task = &task->task; + MppStopwatch stopwatch = NULL; + MPP_RET ret = MPP_OK; + + if (!status->task_in_rdy) { + ret = mpp_port_poll(enc->input, MPP_POLL_NON_BLOCK); + if (ret < 0) { + wait->enc_frm_in = 1; + return ret; + } + + status->task_in_rdy = 1; + wait->enc_frm_in = 0; + enc_dbg_detail("task in ready\n"); + } + + // 5. check output task + if (!status->task_out_rdy) { + ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK); + if (ret < 0) { + wait->enc_pkt_out = 1; + return ret; + } + + status->task_out_rdy = 1; + wait->enc_pkt_out = 0; + enc_dbg_detail("task out ready\n"); + } + + /* + * 6. get frame and packet for one task + * If there is no input frame just return empty packet task + */ + if (!status->frm_pkt_rdy) { + // get tasks from both input and output + ret = mpp_port_dequeue(enc->input, &enc->task_in); + mpp_assert(enc->task_in); + + ret = mpp_port_dequeue(enc->output, &enc->task_out); + mpp_assert(enc->task_out); + + /* + * frame will be return to input. + * packet will be sent to output. + */ + mpp_task_meta_get_frame (enc->task_in, KEY_INPUT_FRAME, &enc->frame); + mpp_task_meta_get_packet(enc->task_in, KEY_OUTPUT_PACKET, &enc->packet); + mpp_task_meta_get_buffer(enc->task_in, KEY_MOTION_INFO, &enc->md_info); + + enc_dbg_detail("task dequeue done frm %p pkt %p\n", enc->frame, enc->packet); + + stopwatch = mpp_frame_get_stopwatch(enc->frame); + mpp_stopwatch_record(stopwatch, "encode task start"); + + if (mpp_enc_check_frm_pkt(enc)) { + mpp_stopwatch_record(stopwatch, "invalid on check frm pkt"); + reset_hal_enc_task(hal_task); + ret = MPP_NOK; + goto TASK_DONE; + } + + status->frm_pkt_rdy = 1; + enc_dbg_detail("task frame packet ready\n"); + } + + // 8. all task ready start encoding one frame + if (!status->hal_task_reset_rdy) { + reset_hal_enc_task(hal_task); + reset_enc_rc_task(rc_task); + task->usr = enc->frm_cfg; + enc->frm_cfg.force_flag = 0; + + hal_task->rc_task = rc_task; + hal_task->frm_cfg = frm_cfg; + hal_task->frame = enc->frame; + hal_task->input = enc->frm_buf; + hal_task->packet = enc->packet; + hal_task->output = enc->pkt_buf; + hal_task->md_info = enc->md_info; + hal_task->stopwatch = stopwatch; + + frm->seq_idx = task->seq_idx++; + rc_task->frame = enc->frame; + enc_dbg_detail("task seq idx %d start\n", frm->seq_idx); + } + + // 9. check frame drop by frame rate conversion + if (!status->rc_check_frm_drop) { + ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret); + status->rc_check_frm_drop = 1; + enc_dbg_detail("task %d drop %d\n", frm->seq_idx, frm->drop); + + hal_task->valid = 1; + // when the frame should be dropped just return empty packet + if (frm->drop) { + mpp_stopwatch_record(stopwatch, "invalid on frame rate drop"); + hal_task->length = 0; + hal_task->flags.drop_by_fps = 1; + status->enc_start = 1; + if (!status->refs_force_update) { + if (frm_cfg->force_flag) + mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg); + + status->refs_force_update = 1; + } + ret = MPP_OK; + goto TASK_DONE; + } + } + + // start encoder task process here + mpp_assert(hal_task->valid); + + // 10. check and create packet for output + if (!status->pkt_buf_rdy) { + mpp_enc_check_pkt_buf(enc); + status->pkt_buf_rdy = 1; + + hal_task->output = enc->pkt_buf; + } + mpp_assert(enc->packet); + mpp_assert(enc->pkt_buf); + + // 11. check hal info update + if (!enc->hal_info_updated) { + update_enc_hal_info(enc); + enc->hal_info_updated = 1; + } + + // 12. generate header before hardware stream + if (!hdr_status->ready) { + /* config cpb before generating header */ + enc_impl_gen_hdr(enc->impl, enc->hdr_pkt); + enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt); + hdr_status->ready = 1; + + enc_dbg_detail("task %d update header length %d\n", + frm->seq_idx, enc->hdr_len); + + mpp_packet_append(enc->packet, enc->hdr_pkt); + hal_task->header_length = enc->hdr_len; + hal_task->length += enc->hdr_len; + hdr_status->added_by_change = 1; + } + + check_hal_task_pkt_len(hal_task, "gen_hdr and adding"); + + // 13. check frm_meta data force key in input frame and start one frame + if (!status->enc_start) { + enc_dbg_detail("task %d enc start\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret); + status->enc_start = 1; + } + + // 14. setup user_cfg to dpb + if (!status->refs_force_update) { + if (frm_cfg->force_flag) + mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg); + + status->refs_force_update = 1; + } + + // 15. backup dpb + if (!status->enc_backup) { + mpp_enc_refs_stash(enc->refs); + status->enc_backup = 1; + } + +TASK_DONE: + if (ret) + mpp_enc_terminate_task(enc, task); + return ret; +} + +static MPP_RET try_proc_low_deley_task(Mpp *mpp, EncAsyncTaskInfo *task, EncAsyncWait *wait) +{ + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + EncImpl impl = enc->impl; + MppEncHal hal = enc->enc_hal; + EncRcTask *rc_task = &task->rc; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + EncAsyncStatus *status = &task->status; + HalEncTask *hal_task = &task->task; + MppPacket packet = hal_task->packet; + MPP_RET ret = MPP_OK; + + if (hal_task->flags.drop_by_fps) + goto TASK_DONE; + + if (status->low_delay_again) + goto GET_OUTPUT_TASK; + + enc_dbg_detail("task %d check force pskip start\n", frm->seq_idx); + if (!status->check_frm_pskip) { + MppPskipMode skip_mode; + status->check_frm_pskip = 1; + + mpp_enc_get_pskip_mode((Mpp*)enc->mpp, task, &skip_mode); + if (skip_mode.pskip_is_ref || skip_mode.pskip_is_non_ref) { + ret = mpp_enc_force_pskip((Mpp*)enc->mpp, task); + if (ret) + enc_dbg_detail("task %d set force pskip failed.", frm->seq_idx); + else + goto TASK_DONE; + } + } + + enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx); + mpp_enc_refs_get_cpb(enc->refs, cpb); + + enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc frame start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret); + + // 16. generate header before hardware stream + mpp_enc_add_sw_header(enc, hal_task); + + enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal get task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); + + hal_task->part_first = 0; + hal_task->part_last = 0; + + do { + enc_dbg_detail("task %d hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_part_start, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal wait\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_part_wait, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal ret task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); + + if (hal_task->part_first) { + hal_task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet); + hal_task->part_length = 0; + } + + mpp_packet_set_length(packet, hal_task->length); + + enc_dbg_detail("task %d task_out %p\n", frm->seq_idx, enc->task_out); + + GET_OUTPUT_TASK: + /* output task as soon as */ + if (NULL == enc->task_out) { + enc_dbg_detail("task %d poll new task for part output\n", frm->seq_idx); + ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK); + if (ret < 0) { + wait->enc_pkt_out = 1; + status->low_delay_again = 1; + return MPP_NOK; + } + + status->task_out_rdy = 1; + wait->enc_pkt_out = 0; + enc_dbg_detail("task out ready\n"); + + ret = mpp_port_dequeue(enc->output, &enc->task_out); + } + + mpp_assert(enc->task_out); + + /* copy new packet for multiple packet output */ + if (!hal_task->part_last) { + RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet); + RK_U32 part_length = hal_task->length; + RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos; + RK_U32 pkt_len = 0; + MppPacketImpl *part_pkt = NULL; + + enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count, + last_pos, part_pos, part_length); + + part_pos += part_length; + pkt_len = (RK_U32)(part_pos - last_pos); + + mpp_packet_copy_init((MppPacket *)&part_pkt, packet); + part_pkt->pos = last_pos; + part_pkt->length = pkt_len; + part_pkt->status.val = 0; + part_pkt->status.partition = 1; + part_pkt->status.soi = hal_task->part_first; + part_pkt->status.eoi = hal_task->part_last; + + enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count, + last_pos, pkt_len); + + hal_task->part_pos = part_pos; + + enc_dbg_detail("task %d enqueue packet pts %lld part %d\n", + frm->seq_idx, enc->task_pts, hal_task->part_count); + mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, part_pkt); + mpp_port_enqueue(enc->output, enc->task_out); + enc->task_out = NULL; + hal_task->part_count++; + } + } while (!hal_task->part_last); + +TASK_DONE: + /* output last task */ + { + RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet); + size_t part_length = hal_task->length; + RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos; + RK_U32 pkt_len = 0; + MppPacketImpl *pkt = (MppPacketImpl *)packet; + + enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count, + last_pos, part_pos, part_length); + + part_pos += part_length; + pkt_len = part_pos - last_pos; + + enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count, + last_pos, pkt_len); + + pkt->length = pkt_len; + pkt->pos = last_pos; + pkt->status.val = 0; + pkt->status.partition = 1; + pkt->status.soi = hal_task->part_first; + pkt->status.eoi = hal_task->part_last; + + enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count, + last_pos, pkt_len); + + hal_task->part_pos = part_pos; + + enc_dbg_detail("task %d enqueue packet pts %lld part %d\n", + frm->seq_idx, enc->task_pts, hal_task->part_count); + mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet); + mpp_port_enqueue(enc->output, enc->task_out); + enc->task_out = NULL; + hal_task->part_count = 0; + } + status->low_delay_again = 0; + + enc->time_end = mpp_time(); + enc->frame_count++; + + if (enc->dev && enc->time_base && enc->time_end && + ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000))) + update_hal_info_fps(enc); + + enc_dbg_detail("task %d rc hal end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts); + + mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame); + mpp_port_enqueue(enc->input, enc->task_in); + + reset_enc_task(enc); + status->val = 0; + task->usr.force_flag = 0; + + return ret; +} + +static MPP_RET set_enc_info_to_packet(MppEncImpl *enc, HalEncTask *hal_task) +{ + Mpp *mpp = (Mpp*)enc->mpp; + EncRcTask *rc_task = hal_task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + MppPacket packet = hal_task->packet; + MppMeta meta = mpp_packet_get_meta(packet); + + if (!meta) { + mpp_err_f("failed to get meta from packet\n"); + return MPP_NOK; + } + + if (enc->coding == MPP_VIDEO_CodingHEVC || enc->coding == MPP_VIDEO_CodingAVC) { + RK_U32 is_pskip = !(rc_task->info.lvl64_inter_num || + rc_task->info.lvl32_inter_num || + rc_task->info.lvl16_inter_num || + rc_task->info.lvl8_inter_num || + rc_task->info.lvl32_intra_num || + rc_task->info.lvl16_intra_num || + rc_task->info.lvl8_intra_num || + rc_task->info.lvl4_intra_num); + + /* num of inter different size predicted block */ + mpp_meta_set_s32(meta, KEY_LVL64_INTER_NUM, rc_task->info.lvl64_inter_num); + mpp_meta_set_s32(meta, KEY_LVL32_INTER_NUM, rc_task->info.lvl32_inter_num); + mpp_meta_set_s32(meta, KEY_LVL16_INTER_NUM, rc_task->info.lvl16_inter_num); + mpp_meta_set_s32(meta, KEY_LVL8_INTER_NUM, rc_task->info.lvl8_inter_num); + /* num of intra different size predicted block */ + mpp_meta_set_s32(meta, KEY_LVL32_INTRA_NUM, rc_task->info.lvl32_intra_num); + mpp_meta_set_s32(meta, KEY_LVL16_INTRA_NUM, rc_task->info.lvl16_intra_num); + mpp_meta_set_s32(meta, KEY_LVL8_INTRA_NUM, rc_task->info.lvl8_intra_num); + mpp_meta_set_s32(meta, KEY_LVL4_INTRA_NUM, rc_task->info.lvl4_intra_num); + + mpp_meta_set_s64(meta, KEY_ENC_SSE, rc_task->info.sse); + mpp_meta_set_s32(meta, KEY_OUTPUT_PSKIP, frm->force_pskip || is_pskip); + mpp_meta_set_s32(meta, KEY_ENC_BPS_RT, rc_task->info.rt_bits); + + if (rc_task->info.frame_type == INTER_VI_FRAME) + mpp_meta_set_s32(meta, KEY_ENC_USE_LTR, rc_task->cpb.refr.lt_idx); + } + /* frame type */ + mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, frm->is_intra); + + /* start qp and average qp */ + mpp_meta_set_s32(meta, KEY_ENC_START_QP, rc_task->info.quality_target); + mpp_meta_set_s32(meta, KEY_ENC_AVERAGE_QP, rc_task->info.quality_real); + + if (hal_task->md_info) + mpp_meta_set_buffer(meta, KEY_MOTION_INFO, hal_task->md_info); + + if (mpp->mEncAyncIo) + mpp_meta_set_frame(meta, KEY_INPUT_FRAME, hal_task->frame); + + return MPP_OK; +} + +static MPP_RET try_proc_normal_task(MppEncImpl *enc, EncAsyncTaskInfo *task) +{ + Mpp *mpp = (Mpp*)enc->mpp; + EncRcTask *rc_task = &task->rc; + EncFrmStatus *frm = &rc_task->frm; + MppEncRefFrmUsrCfg *frm_cfg = &task->usr; + HalEncTask *hal_task = &task->task; + MppPacket packet = hal_task->packet; + MPP_RET ret = MPP_OK; + + if (hal_task->flags.drop_by_fps) + goto TASK_DONE; + + // 17. normal encode + ENC_RUN_FUNC2(mpp_enc_normal, mpp, task, mpp, ret); + + // 18. drop, force pskip and reencode process + while (frm->reencode && frm->reencode_times < enc->cfg->rc.max_reenc_times) { + hal_task->length -= hal_task->hw_length; + hal_task->hw_length = 0; + + mpp_packet_set_segment_nb(hal_task->packet, hal_task->segment_nb); + + enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times); + + if (frm->drop) { + mpp_enc_reenc_drop(mpp, task); + break; + } + + if (frm->force_pskip && !frm->is_idr && !frm->is_lt_ref) { + mpp_enc_reenc_force_pskip(mpp, task); + break; + } + frm->force_pskip = 0; + mpp_enc_reenc_simple(mpp, task); + } + enc_dbg_detail("task %d rc frame end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret); + + enc->time_end = mpp_time(); + enc->frame_count++; + + if (enc->dev && enc->time_base && enc->time_end && + ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000))) + update_hal_info_fps(enc); + + frm->reencode = 0; + frm->reencode_times = 0; + frm_cfg->force_flag = 0; + +TASK_DONE: + mpp_stopwatch_record(hal_task->stopwatch, "encode task done"); + + if (!mpp_packet_is_partition(packet)) { + /* setup output packet and meta data */ + mpp_packet_set_length(packet, hal_task->length); + } + + /* enc failed force idr */ + if (ret) { + enc->frm_cfg.force_flag |= ENC_FORCE_IDR; + enc->hdr_status.val = 0; + mpp_packet_set_length(packet, 0); + mpp_err_f("enc failed force idr!\n"); + } else + set_enc_info_to_packet(enc, hal_task); + /* + * First return output packet. + * Then enqueue task back to input port. + * Final user will release the mpp_frame they had input. + */ + enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts); + + mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet); + mpp_port_enqueue(enc->output, enc->task_out); + + enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts); + + mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame); + mpp_port_enqueue(enc->input, enc->task_in); + + mpp_enc_rc_info_backup(enc, task); + reset_enc_task(enc); + task->status.val = 0; + + return ret; +} + +void *mpp_enc_thread(void *data) +{ + Mpp *mpp = (Mpp*)data; + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + MppThread *thd_enc = enc->thread_enc; + EncAsyncTaskInfo task; + EncAsyncWait wait; + EncAsyncStatus *status = &task.status; + MPP_RET ret = MPP_OK; + + memset(&task, 0, sizeof(task)); + wait.val = 0; + + enc->time_base = mpp_time(); + + while (1) { + mpp_thread_lock(thd_enc, THREAD_WORK); + + if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd_enc, THREAD_WORK)) { + mpp_thread_unlock(thd_enc, THREAD_WORK); + break; + } + + if (check_enc_task_wait(enc, &wait)) + mpp_thread_wait(thd_enc, THREAD_WORK); + + mpp_thread_unlock(thd_enc, THREAD_WORK); + + // When encoder is not on encoding process external config and reset + if (!status->enc_start) { + // 1. process user control + if (enc->cmd_send != enc->cmd_recv) { + enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd); + sem_wait(&enc->cmd_start); + ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param); + if (ret) + *enc->cmd_ret = ret; + enc->cmd_recv++; + enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv, + enc->cmd_send); + mpp_assert(enc->cmd_send == enc->cmd_send); + enc->param = NULL; + enc->cmd = (MpiCmd)0; + sem_post(&enc->cmd_done); + + // async cfg update process for hal + // mainly for buffer prepare + mpp_enc_hal_prepare(enc->enc_hal); + + /* NOTE: here will clear change flag of rc and prep cfg */ + mpp_enc_proc_rc_update(enc); + wait.val = 0; + continue; + } + + // 2. process reset + if (enc->reset_flag) { + enc_dbg_detail("thread reset start\n"); + + mpp_thread_lock(thd_enc, THREAD_WORK); + enc->status_flag = 0; + mpp_thread_unlock(thd_enc, THREAD_WORK); + + enc->frm_cfg.force_flag |= ENC_FORCE_IDR; + enc->frm_cfg.force_idr++; + + mpp_thread_lock(thd_enc, THREAD_CONTROL); + enc->reset_flag = 0; + sem_post(&enc->enc_reset); + enc_dbg_detail("thread reset done\n"); + wait.val = 0; + mpp_thread_unlock(thd_enc, THREAD_CONTROL); + continue; + } + + // 3. try get a task to encode + ret = try_get_enc_task(enc, &task, &wait); + if (ret) + continue; + } + + mpp_assert(status->enc_start); + if (!status->enc_start) + continue; + + // check partition low delay encoding + /* + * NOTE: Only when both split encoding and low delay mode are set then + * use special low delay path + */ + if (enc->low_delay_part_mode) + try_proc_low_deley_task(mpp, &task, &wait); + else + try_proc_normal_task(enc, &task); + } + + // clear remain task in enc->output port + release_task_in_port(enc->input); + release_task_in_port(mpp->mUsrOutPort); + + return NULL; +} + +static void async_task_reset(EncAsyncTaskInfo *task) +{ + memset(task, 0, sizeof(*task)); + task->task.rc_task = &task->rc; + task->task.frm_cfg = &task->usr; + task->usr.force_flag = 0; +} + +static void async_task_terminate(MppEncImpl *enc, EncAsyncTaskInfo *async) +{ + HalEncTask *hal_task = &async->task; + EncFrmStatus *frm = &async->rc.frm; + Mpp *mpp = (Mpp *)enc->mpp; + + mpp_stopwatch_record(hal_task->stopwatch, "encode task done"); + + if (hal_task->packet) { + MppPacket pkt = hal_task->packet; + + /* setup output packet and meta data */ + mpp_packet_set_length(pkt, hal_task->length); + + /* + * First return output packet. + * Then enqueue task back to input port. + * Final user will release the mpp_frame they had input. + */ + enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts); + + if (mpp->mPktOut) { + MppList *pkt_out = mpp->mPktOut; + + if (enc->frame) { + MppMeta meta = mpp_packet_get_meta(pkt); + MppStopwatch stopwatch = mpp_frame_get_stopwatch(enc->frame); + + mpp_stopwatch_record(stopwatch, "encode task terminate"); + + mpp_meta_set_frame(meta, KEY_INPUT_FRAME, enc->frame); + enc->frame = NULL; + } + + mpp_mutex_cond_lock(&pkt_out->cond_lock); + + mpp_list_add_at_tail(pkt_out, &pkt, sizeof(pkt)); + mpp->mPacketPutCount++; + mpp_list_signal(pkt_out); + mpp_assert(pkt); + + mpp_mutex_cond_unlock(&pkt_out->cond_lock); + enc_dbg_detail("packet out ready\n"); + } + } + + async_task_reset(async); +} + +static void async_task_skip(MppEncImpl *enc) +{ + Mpp *mpp = (Mpp*)enc->mpp; + MppStopwatch stopwatch = NULL; + MppMeta meta = NULL; + MppFrame frm = NULL; + MppPacket pkt = NULL; + + mpp_list_del_at_head(mpp->mFrmIn, &frm, sizeof(frm)); + mpp->mFrameGetCount++; + + mpp_assert(frm); + + enc_dbg_detail("skip input frame start\n"); + + stopwatch = mpp_frame_get_stopwatch(frm); + mpp_stopwatch_record(stopwatch, "skip task start"); + + if (mpp_frame_has_meta(frm)) { + meta = mpp_frame_get_meta(frm); + if (meta) + mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &pkt); + } + + if (NULL == pkt) + mpp_packet_new(&pkt); + + mpp_assert(pkt); + + mpp_packet_set_length(pkt, 0); + mpp_packet_set_pts(pkt, mpp_frame_get_pts(frm)); + mpp_packet_set_dts(pkt, mpp_frame_get_dts(frm)); + + if (mpp_frame_get_eos(frm)) + mpp_packet_set_eos(pkt); + else + mpp_packet_clr_eos(pkt); + + meta = mpp_packet_get_meta(pkt); + mpp_assert(meta); + + mpp_meta_set_frame(meta, KEY_INPUT_FRAME, frm); + + if (mpp->mPktOut) { + MppList *pkt_out = mpp->mPktOut; + + mpp_mutex_cond_lock(&pkt_out->cond_lock); + mpp_stopwatch_record(stopwatch, "skip task output"); + mpp_list_add_at_tail(pkt_out, &pkt, sizeof(pkt)); + mpp->mPacketPutCount++; + mpp_list_signal(pkt_out); + mpp_mutex_cond_unlock(&pkt_out->cond_lock); + } + + enc_dbg_detail("packet skip ready\n"); +} + +static MPP_RET check_async_frm_pkt(EncAsyncTaskInfo *async) +{ + HalEncTask *hal_task = &async->task; + MppPacket packet = hal_task->packet; + MppFrame frame = hal_task->frame; + + hal_task->input = NULL; + hal_task->output = NULL; + + if (packet) + hal_task->output = mpp_packet_get_buffer(packet); + else { + mpp_packet_new(&packet); + hal_task->packet = packet; + } + + if (frame) { + RK_S64 pts = mpp_frame_get_pts(frame); + MppBuffer frm_buf = mpp_frame_get_buffer(frame); + + hal_task->input = frm_buf; + + mpp_packet_set_pts(packet, pts); + mpp_packet_set_dts(packet, mpp_frame_get_dts(frame)); + + if (mpp_frame_get_eos(frame)) + mpp_packet_set_eos(packet); + else + mpp_packet_clr_eos(packet); + } + + return (NULL == frame || NULL == hal_task->input) ? MPP_NOK : MPP_OK; +} + +static MPP_RET check_async_pkt_buf(MppEncImpl *enc, EncAsyncTaskInfo *async) +{ + HalEncTask *hal_task = &async->task; + + if (NULL == hal_task->output) { + /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */ + Mpp *mpp = (Mpp *)enc->mpp; + MppEncPrepCfg *prep = &enc->cfg->prep; + RK_U32 width = MPP_ALIGN(prep->width, 16); + RK_U32 height = MPP_ALIGN(prep->height, 16); + RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ? + (width * height * 3 / 2) : (width * height); + MppPacketImpl *pkt = (MppPacketImpl *)hal_task->packet; + MppBuffer buffer = NULL; + + mpp_assert(size); + mpp_buffer_get(mpp->mPacketGroup, &buffer, size); + mpp_buffer_attach_dev(buffer, enc->dev); + mpp_assert(buffer); + enc->pkt_buf = buffer; + pkt->data = mpp_buffer_get_ptr(buffer); + pkt->pos = pkt->data; + pkt->size = mpp_buffer_get_size(buffer); + pkt->length = 0; + pkt->buffer = buffer; + hal_task->output = buffer; + + enc_dbg_detail("create output pkt %p buf %p\n", hal_task->packet, buffer); + } else { + enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n", + hal_task->packet, hal_task->output, + mpp_packet_get_pos(hal_task->packet), + mpp_packet_get_length(hal_task->packet)); + } + + return MPP_OK; +} + +static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncWait *wait) +{ + Mpp *mpp = (Mpp *)enc->mpp; + EncAsyncTaskInfo *async = enc->async; + EncRcTask *rc_task = NULL; + MppEncHeaderStatus *hdr_status = &enc->hdr_status; + HalEncTask *hal_task = NULL; + EncAsyncStatus *status = NULL; + MppStopwatch stopwatch = NULL; + MppPacket packet = NULL; + MppFrame frame = NULL; + RK_U32 seq_idx = 0; + MPP_RET ret = MPP_OK; + + if (NULL == enc->hnd) { + hal_task_get_hnd(enc->tasks, TASK_IDLE, &enc->hnd); + if (enc->hnd) { + wait->task_hnd = 0; + enc_dbg_detail("get hnd success\n"); + + mpp_assert(enc->async == NULL); + async = (EncAsyncTaskInfo *)hal_task_hnd_get_data(enc->hnd); + async_task_reset(async); + enc->async = async; + } else { + wait->task_hnd = 1; + enc_dbg_detail("get hnd failed\n"); + return MPP_NOK; + } + } + + mpp_assert(enc->hnd); + mpp_assert(enc->async); + + hal_task = &async->task; + rc_task = &async->rc; + status = &async->status; + packet = hal_task->packet; + frame = hal_task->frame; + + if (NULL == frame) { + if (mpp->mFrmIn) { + MppList *frm_in = mpp->mFrmIn; + + mpp_mutex_cond_lock(&frm_in->cond_lock); + + if (mpp_list_size(frm_in)) { + mpp_list_del_at_head(frm_in, &frame, sizeof(frame)); + mpp_list_signal(frm_in); + + mpp->mFrameGetCount++; + + mpp_assert(frame); + + status->task_in_rdy = 1; + wait->enc_frm_in = 0; + + enc_dbg_detail("get input frame success\n"); + + stopwatch = mpp_frame_get_stopwatch(frame); + mpp_stopwatch_record(stopwatch, "encode task start"); + + hal_task->frame = frame; + } + + mpp_mutex_cond_unlock(&frm_in->cond_lock); + } + + if (NULL == frame) { + enc_dbg_detail("get input frame failed\n"); + wait->enc_frm_in = 1; + return MPP_NOK; + } + } + + if (NULL == packet) { + if (mpp_frame_has_meta(frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet); + } + + if (packet) { + status->task_out_rdy = 1; + wait->enc_pkt_out = 0; + + enc_dbg_detail("get output packet success\n"); + + hal_task->packet = packet; + } + } + + mpp_assert(frame); + + stopwatch = mpp_frame_get_stopwatch(frame); + + /* + * 6. get frame and packet for one task + * If there is no input frame just return empty packet task + */ + if (!status->frm_pkt_rdy) { + async->seq_idx = enc->task_idx++; + async->pts = mpp_frame_get_pts(hal_task->frame); + + hal_task->stopwatch = stopwatch; + rc_task->frame = async->task.frame; + + enc_dbg_detail("task seq idx %d start\n", seq_idx); + + if (check_async_frm_pkt(async)) { + mpp_stopwatch_record(stopwatch, "empty frame on check frm pkt"); + hal_task->valid = 1; + hal_task->length = 0; + hal_task->flags.drop_by_fps = 1; + ret = MPP_OK; + goto TASK_DONE; + } + + status->frm_pkt_rdy = 1; + enc_dbg_detail("task frame packet ready\n"); + } + + seq_idx = async->seq_idx; + + // 9. check frame drop by frame rate conversion + if (!status->rc_check_frm_drop) { + EncFrmStatus *frm = &rc_task->frm; + + ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret); + status->rc_check_frm_drop = 1; + enc_dbg_detail("task %d drop %d\n", seq_idx, frm->drop); + + // when the frame should be dropped just return empty packet + hal_task->valid = 1; + if (frm->drop) { + mpp_stopwatch_record(stopwatch, "invalid on frame rate drop"); + hal_task->length = 0; + hal_task->flags.drop_by_fps = 1; + ret = MPP_OK; + goto TASK_DONE; + } + + *hal_task->frm_cfg = enc->frm_cfg; + enc->frm_cfg.force_flag = 0; + } + + // start encoder task process here + mpp_assert(hal_task->valid); + + // 10. check and create packet for output + if (!status->pkt_buf_rdy) { + check_async_pkt_buf(enc, async); + status->pkt_buf_rdy = 1; + + enc_dbg_detail("task %d check pkt buffer success\n", seq_idx); + } + mpp_assert(hal_task->packet); + mpp_assert(hal_task->output); + + // 11. check hal info update + if (!enc->hal_info_updated) { + update_enc_hal_info(enc); + enc->hal_info_updated = 1; + + enc_dbg_detail("task %d update enc hal info success\n", seq_idx); + } + + // 12. generate header before hardware stream + if (!hdr_status->ready) { + /* config cpb before generating header */ + enc_impl_gen_hdr(enc->impl, enc->hdr_pkt); + enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt); + hdr_status->ready = 1; + + enc_dbg_detail("task %d update header length %d\n", + seq_idx, enc->hdr_len); + + mpp_packet_append(hal_task->packet, enc->hdr_pkt); + hal_task->header_length = enc->hdr_len; + hal_task->length += enc->hdr_len; + hdr_status->added_by_change = 1; + } + + check_hal_task_pkt_len(hal_task, "gen_hdr and adding"); + + // 13. check frm_meta data force key in input frame and start one frame + if (!status->enc_start) { + enc_dbg_detail("task %d enc start\n", seq_idx); + ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret); + status->enc_start = 1; + } + + // 14. setup user_cfg to dpb + if (!status->refs_force_update) { + MppEncRefFrmUsrCfg *frm_cfg = &async->usr; + + if (frm_cfg->force_flag) { + mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg); + frm_cfg->force_flag = 0; + } + + enc_dbg_detail("task %d refs force update success\n", seq_idx); + status->refs_force_update = 1; + } + + // 15. backup dpb + if (!status->enc_backup) { + mpp_enc_refs_stash(enc->refs); + enc_dbg_detail("task %d refs stash success\n", seq_idx); + status->enc_backup = 1; + } + +TASK_DONE: + if (ret) { + enc_dbg_detail("task %d terminate\n", seq_idx); + async_task_terminate(enc, async); + } + + return ret; +} + +static MPP_RET try_proc_processing_task(MppEncImpl *enc, EncAsyncWait *wait) +{ + HalTaskHnd hnd = NULL; + EncAsyncTaskInfo *info = NULL; + MPP_RET ret = MPP_NOK; + + ret = hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd); + if (ret) + return ret; + + info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd); + + mpp_assert(!info->status.enc_done); + + enc_async_wait_task(enc, info); + hal_task_hnd_set_status(hnd, TASK_IDLE); + wait->task_hnd = 0; + + return MPP_OK; +} + +static MPP_RET proc_async_task(MppEncImpl *enc, EncAsyncWait *wait) +{ + Mpp *mpp = (Mpp*)enc->mpp; + EncImpl impl = enc->impl; + MppEncHal hal = enc->enc_hal; + EncAsyncTaskInfo *async = enc->async; + EncAsyncStatus *status = &async->status; + HalEncTask *hal_task = &async->task; + EncRcTask *rc_task = hal_task->rc_task; + EncCpbStatus *cpb = &rc_task->cpb; + EncFrmStatus *frm = &rc_task->frm; + RK_U32 seq_idx = async->seq_idx; + MPP_RET ret = MPP_OK; + + mpp_assert(hal_task->valid); + + if (hal_task->flags.drop_by_fps) + goto SEND_TASK_INFO; + + if (!status->check_frm_pskip) { + MppPskipMode skip_mode; + status->check_frm_pskip = 1; + + mpp_enc_get_pskip_mode((Mpp*)enc->mpp, async, &skip_mode); + if (skip_mode.pskip_is_ref || skip_mode.pskip_is_non_ref) { + ret = mpp_enc_force_pskip((Mpp*)enc->mpp, async); + if (ret) + enc_dbg_detail("task %d set force pskip failed.", frm->seq_idx); + else + goto SEND_TASK_INFO; + } + } + + if (enc->support_hw_deflicker && enc->cfg->rc.debreath_en) { + bool two_pass_en = mpp_enc_refs_next_frm_is_intra(enc->refs); + + if (two_pass_en) { + /* wait all tasks done */ + while (MPP_OK == try_proc_processing_task(enc, wait)); + + ret = mpp_enc_proc_two_pass(mpp, async); + if (ret) + return ret; + } + } + + enc_dbg_detail("task %d enc proc dpb\n", seq_idx); + mpp_enc_refs_get_cpb(enc->refs, cpb); + + enc_dbg_frm_status("frm %d start ***********************************\n", seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc frame start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret); + + // 16. generate header before hardware stream + mpp_enc_add_sw_header(enc, hal_task); + + enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx); + ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret); + + enc_dbg_detail("task %d hal get task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret); + + mpp_stopwatch_record(hal_task->stopwatch, "encode hal start"); + enc_dbg_detail("task %d hal start\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret); + +SEND_TASK_INFO: + status->enc_done = 0; + hal_task_hnd_set_status(enc->hnd, TASK_PROCESSING); + enc_dbg_detail("task %d on processing ret %d\n", frm->seq_idx, ret); + + enc->hnd = NULL; + enc->async = NULL; + +TASK_DONE: + + /* NOTE: clear add_by flags */ + enc->hdr_status.val = enc->hdr_status.ready; + + return ret; +} + +static MPP_RET check_enc_async_wait(MppEncImpl *enc, EncAsyncWait *wait) +{ + MPP_RET ret = MPP_OK; + RK_U32 notify = enc->notify_flag; + RK_U32 last_wait = enc->status_flag; + RK_U32 curr_wait = wait->val; + RK_U32 wait_chg = last_wait & (~curr_wait); + RK_U32 keep_notify = 0; + + do { + if (enc->reset_flag) + break; + + // NOTE: User control should always be processed + if (notify & MPP_ENC_CONTROL) { + keep_notify = notify & (~MPP_ENC_CONTROL); + break; + } + + // NOTE: When condition is not fulfilled check nofify flag again + if (!curr_wait || (curr_wait & notify)) + break; + + ret = MPP_NOK; + } while (0); + + enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc, + last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work")); + + enc->status_flag = wait->val; + enc->notify_flag = keep_notify; + + if (ret) { + enc->wait_count++; + } else { + enc->work_count++; + } + + return ret; +} + +static MPP_RET enc_async_wait_task(MppEncImpl *enc, EncAsyncTaskInfo *info) +{ + Mpp *mpp = (Mpp*)enc->mpp; + MppEncHal hal = enc->enc_hal; + HalEncTask *hal_task = &info->task; + EncRcTask *rc_task = hal_task->rc_task; + EncFrmStatus *frm = &info->rc.frm; + MppPacket pkt = hal_task->packet; + MPP_RET ret = MPP_OK; + + if (hal_task->flags.drop_by_fps || hal_task->frm_cfg->force_pskip) + goto TASK_DONE; + + enc_dbg_detail("task %d hal wait\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret); + + mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish"); + + enc_dbg_detail("task %d rc hal end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret); + + enc_dbg_detail("task %d hal ret task\n", frm->seq_idx); + ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret); + + enc_dbg_detail("task %d rc frame end\n", frm->seq_idx); + ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret); + +TASK_DONE: + if (!mpp_packet_is_partition(pkt)) { + /* setup output packet and meta data */ + mpp_packet_set_length(pkt, hal_task->length); + + check_hal_task_pkt_len(hal_task, "hw finish"); + } + + enc_dbg_detail("task %d output packet pts %lld\n", info->seq_idx, info->pts); + + /* + * async encode process, there may have multiple frames encoding. + * if last frame enc failed, drop non-idr frames and force idr for next frame. + */ + if (enc->enc_failed_drop && !hal_task->rc_task->frm.is_idr) { + mpp_packet_set_length(pkt, 0); + mpp_err_f("last frame enc failed, drop this P frame\n"); + enc->frm_cfg.force_flag |= ENC_FORCE_IDR; + enc->hdr_status.val = 0; + } else + enc->enc_failed_drop = 0; + /* enc failed, force idr for next frame */ + if (ret) { + enc->frm_cfg.force_flag |= ENC_FORCE_IDR; + enc->hdr_status.val = 0; + mpp_packet_set_length(pkt, 0); + enc->enc_failed_drop = 1; + + mpp_err_f("enc failed force idr!\n"); + } else + set_enc_info_to_packet(enc, hal_task); + + if (mpp->mPktOut) { + MppList *pkt_out = mpp->mPktOut; + + mpp_mutex_cond_lock(&pkt_out->cond_lock); + + mpp_list_add_at_tail(pkt_out, &pkt, sizeof(pkt)); + mpp->mPacketPutCount++; + mpp_list_signal(pkt_out); + + mpp_mutex_cond_unlock(&pkt_out->cond_lock); + } + + return ret; +} + +void *mpp_enc_async_thread(void *data) +{ + Mpp *mpp = (Mpp*)data; + MppEncImpl *enc = (MppEncImpl *)mpp->mEnc; + MppThread *thd_enc = enc->thread_enc; + EncAsyncWait wait; + MPP_RET ret = MPP_OK; + + enc_dbg_func("thread start\n"); + + wait.val = 0; + + while (1) { + mpp_thread_lock(thd_enc, THREAD_WORK); + if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd_enc, THREAD_WORK)) { + mpp_thread_unlock(thd_enc, THREAD_WORK); + break; + } + + if (check_enc_async_wait(enc, &wait)) { + enc_dbg_detail("wait start\n"); + mpp_thread_wait(thd_enc, THREAD_WORK); + enc_dbg_detail("wait done\n"); + } + mpp_thread_unlock(thd_enc, THREAD_WORK); + + // When encoder is not on encoding process external config and reset + // 1. process user control and reset flag + if (enc->cmd_send != enc->cmd_recv || enc->reset_flag) { + MppList *frm_in = mpp->mFrmIn; + + /* when process cmd or reset hold frame input */ + mpp_mutex_cond_lock(&frm_in->cond_lock); + + enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd); + + // wait all tasks done + while (MPP_OK == try_proc_processing_task(enc, &wait)); + + if (enc->cmd_send != enc->cmd_recv) { + sem_wait(&enc->cmd_start); + ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param); + if (ret) + *enc->cmd_ret = ret; + enc->cmd_recv++; + enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv, + enc->cmd_send); + mpp_assert(enc->cmd_send == enc->cmd_send); + enc->param = NULL; + enc->cmd = (MpiCmd)0; + sem_post(&enc->cmd_done); + + // async cfg update process for hal + // mainly for buffer prepare + mpp_enc_hal_prepare(enc->enc_hal); + + /* NOTE: here will clear change flag of rc and prep cfg */ + mpp_enc_proc_rc_update(enc); + goto SYNC_DONE; + } + + if (enc->reset_flag) { + enc_dbg_detail("thread reset start\n"); + + /* skip the frames in input queue */ + while (mpp_list_size(frm_in)) + async_task_skip(enc); + + { + mpp_thread_lock(thd_enc, THREAD_WORK); + enc->status_flag = 0; + mpp_thread_unlock(thd_enc, THREAD_WORK); + } + + enc->frm_cfg.force_flag |= ENC_FORCE_IDR; + enc->frm_cfg.force_idr++; + + mpp_thread_lock(thd_enc, THREAD_CONTROL); + enc->reset_flag = 0; + sem_post(&enc->enc_reset); + enc_dbg_detail("thread reset done\n"); + mpp_thread_unlock(thd_enc, THREAD_CONTROL); + } + SYNC_DONE: + mpp_mutex_cond_unlock(&frm_in->cond_lock); + wait.val = 0; + continue; + } + + // 2. try get a task to encode + ret = try_get_async_task(enc, &wait); + enc_dbg_detail("try_get_async_task ret %d\n", ret); + if (ret) { + try_proc_processing_task(enc, &wait); + continue; + } + + mpp_assert(enc->async); + mpp_assert(enc->async->task.valid); + + proc_async_task(enc, &wait); + } + /* wait all task done */ + while (MPP_OK == try_proc_processing_task(enc, &wait)); + + enc_dbg_func("thread finish\n"); + + return NULL; +} diff --git a/mpp/codec/mpp_enc_v2.c b/mpp/codec/mpp_enc_v2.c new file mode 100644 index 000000000..daa59d18c --- /dev/null +++ b/mpp/codec/mpp_enc_v2.c @@ -0,0 +1,456 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_enc" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_info.h" +#include "mpp_common.h" +#include "mpp_2str.h" + +#include "mpp.h" +#include "mpp_enc_debug.h" +#include "mpp_enc_cfg.h" +#include "mpp_enc_impl.h" +#include "mpp_enc_cb_param.h" + +#include "kmpp_obj.h" + +RK_U32 mpp_enc_debug = 0; + +static void copy_enc_cfg(KmppObj dst, KmppObj src) +{ + MppEncCfgSet *_dst = (MppEncCfgSet *)kmpp_obj_to_entry(dst); + MppEncCfgSet *_src = (MppEncCfgSet *)kmpp_obj_to_entry(src); + + memcpy(_dst, _src, sizeof(*_dst)); + + /* cleanup output change flag to avoid extra change flag bit when user resend the cfg */ + { + void *p = kmpp_obj_to_flags(dst); + rk_s32 size = kmpp_obj_to_flags_size(dst); + + if (p && size) + memset(p, 0, size); + } +} + +MPP_RET mpp_enc_init_v2(MppEnc *enc, MppEncInitCfg *cfg) +{ + MPP_RET ret; + MppCodingType coding = cfg->coding; + EncImpl impl = NULL; + MppEncImpl *p = NULL; + MppEncHal enc_hal = NULL; + MppEncHalCfg enc_hal_cfg; + EncImplCfg ctrl_cfg; + + mpp_env_get_u32("mpp_enc_debug", &mpp_enc_debug, 0); + + if (NULL == enc) { + mpp_err_f("failed to malloc context\n"); + return MPP_ERR_NULL_PTR; + } + + *enc = NULL; + + p = mpp_calloc(MppEncImpl, 1); + if (NULL == p) { + mpp_err_f("failed to malloc context\n"); + return MPP_ERR_MALLOC; + } + + mpp_enc_cfg_get(&p->set_obj); + mpp_enc_cfg_get(&p->cfg_obj); + if (!p->set_obj || !p->cfg_obj) { + mpp_err_f("failed to get cfg set\n"); + ret = MPP_ERR_MALLOC; + goto ERR_RET; + } + + p->set = (MppEncCfgSet *)kmpp_obj_to_entry(p->set_obj); + p->cfg = (MppEncCfgSet *)kmpp_obj_to_entry(p->cfg_obj); + + ret = mpp_enc_refs_init(&p->refs); + if (ret) { + mpp_err_f("could not init enc refs\n"); + goto ERR_RET; + } + + p->output_cb.callBack = mpp_enc_callback; + p->output_cb.ctx = p; + p->output_cb.cmd = ENC_CALLBACK_BASE; + + // H.264 encoder use mpp_enc_hal path + // create hal first + enc_hal_cfg.coding = coding; + enc_hal_cfg.cfg = p->cfg; + enc_hal_cfg.output_cb = &p->output_cb; + enc_hal_cfg.task_cnt = cfg->task_cnt; + enc_hal_cfg.type = VPU_CLIENT_BUTT; + enc_hal_cfg.dev = NULL; + enc_hal_cfg.cap_recn_out = 0; + + ctrl_cfg.coding = coding; + ctrl_cfg.type = VPU_CLIENT_BUTT; + ctrl_cfg.cfg = p->cfg; + ctrl_cfg.refs = p->refs; + + ret = mpp_enc_hal_init(&enc_hal, &enc_hal_cfg); + if (ret) { + mpp_err_f("could not init enc hal\n"); + goto ERR_RET; + } + + ctrl_cfg.type = enc_hal_cfg.type; + + ret = enc_impl_init(&impl, &ctrl_cfg); + if (ret) { + mpp_err_f("could not init impl\n"); + goto ERR_RET; + } + + ret = hal_info_init(&p->hal_info, MPP_CTX_ENC, coding); + if (ret) { + mpp_err_f("could not init hal info\n"); + goto ERR_RET; + } + + p->coding = coding; + p->impl = impl; + p->enc_hal = enc_hal; + p->dev = enc_hal_cfg.dev; + p->mpp = cfg->mpp; + p->tasks = enc_hal_cfg.tasks; + p->sei_mode = MPP_ENC_SEI_MODE_ONE_SEQ; + p->version_info = get_mpp_version(); + p->version_length = strlen(p->version_info); + p->rc_cfg_size = SZ_1K; + p->rc_cfg_info = mpp_calloc_size(char, p->rc_cfg_size); + + if (enc_hal_cfg.cap_recn_out) + p->support_hw_deflicker = 1; + + { + // create header packet storage + size_t size = SZ_4K; + p->hdr_buf = mpp_calloc_size(void, size); + + mpp_packet_init(&p->hdr_pkt, p->hdr_buf, size); + mpp_packet_set_length(p->hdr_pkt, 0); + } + { + Mpp *mpp = (Mpp *)p->mpp; + + p->input = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_OUTPUT); + p->output = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_INPUT); + } + + /* NOTE: setup configure coding for check */ + p->cfg->base.coding = coding; + p->cfg->plt_cfg.plt = &p->cfg->plt_data; + copy_enc_cfg(p->set_obj, p->cfg_obj); + + mpp_enc_ref_cfg_init(&p->cfg->ref_cfg); + mpp_enc_ref_cfg_init(&p->set->ref_cfg); + ret = mpp_enc_ref_cfg_copy(p->cfg->ref_cfg, mpp_enc_ref_default()); + ret = mpp_enc_ref_cfg_copy(p->set->ref_cfg, mpp_enc_ref_default()); + + ret = mpp_enc_refs_set_cfg(p->refs, mpp_enc_ref_default()); + mpp_enc_refs_set_rc_igop(p->refs, p->cfg->rc.gop); + + sem_init(&p->enc_reset, 0, 0); + sem_init(&p->cmd_start, 0, 0); + sem_init(&p->cmd_done, 0, 0); + mpp_mutex_init(&p->lock); + + *enc = p; + return ret; +ERR_RET: + mpp_enc_deinit_v2(p); + return ret; +} + +MPP_RET mpp_enc_deinit_v2(MppEnc ctx) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + + if (NULL == enc) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_destroy(&enc->lock); + + if (enc->hal_info) { + hal_info_deinit(enc->hal_info); + enc->hal_info = NULL; + } + + if (enc->impl) { + enc_impl_deinit(enc->impl); + enc->impl = NULL; + } + + if (enc->enc_hal) { + mpp_enc_hal_deinit(enc->enc_hal); + enc->enc_hal = NULL; + } + + if (enc->hdr_pkt) + mpp_packet_deinit(&enc->hdr_pkt); + + MPP_FREE(enc->hdr_buf); + + if (enc->set->ref_cfg) { + mpp_enc_ref_cfg_deinit(&enc->set->ref_cfg); + enc->set->ref_cfg = NULL; + } + + if (enc->cfg->ref_cfg) { + mpp_enc_ref_cfg_deinit(&enc->cfg->ref_cfg); + enc->cfg->ref_cfg = NULL; + } + + if (enc->refs) { + mpp_enc_refs_deinit(&enc->refs); + enc->refs = NULL; + } + + if (enc->set_obj) { + kmpp_obj_put_f(enc->set_obj); + enc->set_obj = NULL; + } + + if (enc->cfg_obj) { + kmpp_obj_put_f(enc->cfg_obj); + enc->cfg_obj = NULL; + } + + if (enc->rc_ctx) { + rc_deinit(enc->rc_ctx); + enc->rc_ctx = NULL; + } + + MPP_FREE(enc->rc_cfg_info); + enc->rc_cfg_size = 0; + enc->rc_cfg_length = 0; + + sem_destroy(&enc->enc_reset); + sem_destroy(&enc->cmd_start); + sem_destroy(&enc->cmd_done); + + mpp_free(enc); + return MPP_OK; +} + +MPP_RET mpp_enc_start_v2(MppEnc ctx) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + char name[16]; + + enc_dbg_func("%p in\n", enc); + + snprintf(name, sizeof(name) - 1, "mpp_%se_%d", + strof_coding_type(enc->coding), getpid()); + + enc->thread_enc = mpp_thread_create(mpp_enc_thread, enc->mpp, name); + mpp_thread_start(enc->thread_enc); + + enc_dbg_func("%p out\n", enc); + + return MPP_OK; +} + +MPP_RET mpp_enc_start_async(MppEnc ctx) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + char name[16]; + + enc_dbg_func("%p in\n", enc); + + snprintf(name, sizeof(name) - 1, "mpp_%se_%d", + strof_coding_type(enc->coding), getpid()); + + enc->thread_enc = mpp_thread_create(mpp_enc_async_thread, enc->mpp, name); + mpp_thread_start(enc->thread_enc); + + enc_dbg_func("%p out\n", enc); + + return MPP_OK; +} + +MPP_RET mpp_enc_stop_v2(MppEnc ctx) +{ + MPP_RET ret = MPP_OK; + MppEncImpl *enc = (MppEncImpl *)ctx; + + enc_dbg_func("%p in\n", enc); + + if (enc->thread_enc) { + mpp_thread_stop(enc->thread_enc); + mpp_thread_destroy(enc->thread_enc); + enc->thread_enc = NULL; + } + + enc_dbg_func("%p out\n", enc); + return ret; + +} + +MPP_RET mpp_enc_reset_v2(MppEnc ctx) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + MppThread *thd; + + enc_dbg_func("%p in\n", enc); + + if (NULL == enc) { + mpp_err_f("found NULL input enc\n"); + return MPP_ERR_NULL_PTR; + } + + thd = enc->thread_enc; + + mpp_thread_lock(thd, THREAD_CONTROL); + enc->reset_flag = 1; + mpp_enc_notify_v2(enc, MPP_ENC_RESET); + mpp_thread_unlock(thd, THREAD_CONTROL); + + sem_wait(&enc->enc_reset); + mpp_assert(enc->reset_flag == 0); + + return MPP_OK; +} + +MPP_RET mpp_enc_notify_v2(MppEnc ctx, RK_U32 flag) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + MppThread *thd = enc->thread_enc; + + enc_dbg_func("%p in flag %08x\n", enc, flag); + + mpp_thread_lock(thd, THREAD_WORK); + if (flag == MPP_ENC_CONTROL) { + enc->notify_flag |= flag; + enc_dbg_notify("%p status %08x notify control signal\n", enc, + enc->status_flag); + mpp_thread_signal(thd, THREAD_WORK); + } else { + RK_U32 old_flag = enc->notify_flag; + + enc->notify_flag |= flag; + if ((old_flag != enc->notify_flag) && + (enc->notify_flag & enc->status_flag)) { + enc_dbg_notify("%p status %08x notify %08x signal\n", enc, + enc->status_flag, enc->notify_flag); + mpp_thread_signal(thd, THREAD_WORK); + } + } + mpp_thread_unlock(thd, THREAD_WORK); + enc_dbg_func("%p out\n", enc); + return MPP_OK; +} + +/* + * preprocess config and rate-control config is common config then they will + * be done in mpp_enc layer + * + * codec related config will be set in each hal component + */ +MPP_RET mpp_enc_control_v2(MppEnc ctx, MpiCmd cmd, void *param) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + MPP_RET ret = MPP_OK; + + if (NULL == enc) { + mpp_err_f("found NULL enc\n"); + return MPP_ERR_NULL_PTR; + } + + if (NULL == param && cmd != MPP_ENC_SET_IDR_FRAME && cmd != MPP_ENC_SET_REF_CFG) { + mpp_err_f("found NULL param enc %p cmd %x\n", enc, cmd); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_lock(&enc->lock); + + enc_dbg_ctrl("sending cmd %d param %p\n", cmd, param); + + switch (cmd) { + case MPP_ENC_GET_CFG : { + enc_dbg_ctrl("get enc config start\n"); + copy_enc_cfg(param, enc->cfg_obj); + enc_dbg_ctrl("get enc config done\n"); + } break; + case MPP_ENC_SET_PREP_CFG : + case MPP_ENC_GET_PREP_CFG : + case MPP_ENC_SET_RC_CFG : + case MPP_ENC_GET_RC_CFG : + case MPP_ENC_SET_CODEC_CFG : + case MPP_ENC_GET_CODEC_CFG : + case MPP_ENC_SET_SPLIT : + case MPP_ENC_GET_SPLIT : { + mpp_loge("deprecated %s control use MPP_ENC_GET_CFG / MPP_ENC_SET_CFG instead\n", + cmd == MPP_ENC_SET_PREP_CFG ? "MPP_ENC_SET_PREP_CFG" : + cmd == MPP_ENC_GET_PREP_CFG ? "MPP_ENC_GET_PREP_CFG" : + cmd == MPP_ENC_SET_RC_CFG ? "MPP_ENC_SET_RC_CFG" : + cmd == MPP_ENC_GET_RC_CFG ? "MPP_ENC_GET_RC_CFG" : + cmd == MPP_ENC_SET_CODEC_CFG ? "MPP_ENC_SET_CODEC_CFG" : + cmd == MPP_ENC_GET_CODEC_CFG ? "MPP_ENC_GET_CODEC_CFG" : + cmd == MPP_ENC_SET_SPLIT ? "MPP_ENC_SET_SPLIT" : + cmd == MPP_ENC_GET_SPLIT ? "MPP_ENC_GET_SPLIT" : "unknown"); + ret = MPP_NOK; + } break; + case MPP_ENC_GET_HEADER_MODE : { + enc_dbg_ctrl("get header mode\n"); + memcpy(param, &enc->hdr_mode, sizeof(enc->hdr_mode)); + } break; + case MPP_ENC_GET_OSD_PLT_CFG : { + enc_dbg_ctrl("get osd plt cfg\n"); + memcpy(param, &enc->cfg->plt_cfg, sizeof(enc->cfg->plt_cfg)); + } break; + default : { + // Cmd which is not get configure will handle by enc_impl + if (cmd == MPP_ENC_SET_CFG) { + KmppObj obj = (KmppObj)param; + + if (kmpp_obj_is_kobj(obj)) { + mpp_loge("can not MPP_ENC_SET_CFG by kobj %p\n", obj); + ret = MPP_NOK; + break; + } + } + + enc->cmd = cmd; + enc->param = param; + enc->cmd_ret = &ret; + enc->cmd_send++; + mpp_enc_notify_v2(ctx, MPP_ENC_CONTROL); + sem_post(&enc->cmd_start); + sem_wait(&enc->cmd_done); + + /* check the command is processed */ + mpp_assert(!enc->cmd); + mpp_assert(!enc->param); + } break; + } + + mpp_mutex_unlock(&enc->lock); + + enc_dbg_ctrl("sending cmd %d done\n", cmd); + + return ret; +} + +MppEncCfg mpp_enc_to_cfg(MppEnc ctx) +{ + MppEncImpl *enc = (MppEncImpl *)ctx; + + return (NULL != enc) ? enc->cfg_obj : NULL; +} diff --git a/mpp/codec/mpp_parser.c b/mpp/codec/mpp_parser.c new file mode 100644 index 000000000..0dcca11ef --- /dev/null +++ b/mpp/codec/mpp_parser.c @@ -0,0 +1,247 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dec" + +#include + +#include "mpp_2str.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_parser.h" + +#define parser_DBG_FLOW (0x00000001) +#define parser_DBG_API (0x00000002) + +#define parser_dbg(flag, fmt, ...) mpp_dbg(mpp_parser_debug, flag, fmt, ## __VA_ARGS__) +#define parser_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_parser_debug, flag, fmt, ## __VA_ARGS__) + +#define parser_dbg_flow(fmt, ...) parser_dbg_f(parser_DBG_FLOW, fmt, ## __VA_ARGS__) +#define parser_dbg_api(fmt, ...) parser_dbg(parser_DBG_API, fmt, ## __VA_ARGS__) + +typedef struct ParserImpl_t { + const ParserApi *api; + void *ctx; +} ParserImpl; + +static const ParserApi *parser_apis[32] = { 0 }; + +static RK_U32 mpp_parser_debug = 0; +RK_U32 avsd_debug = 0; +RK_U32 avs2d_debug = 0; +RK_U32 h263d_debug = 0; +RK_U32 h264d_debug = 0; +RK_U32 h265d_debug = 0; +RK_U32 jpegd_debug = 0; +RK_U32 m2vd_debug = 0; +RK_U32 mpg4d_debug = 0; +RK_U32 vp8d_debug = 0; +RK_U32 vp9d_debug = 0; +RK_U32 av1d_debug = 0; + +MPP_RET mpp_parser_api_register(const ParserApi *api) +{ + const char *str; + RK_S32 index; + + if (NULL == api) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + str = strof_coding_type(api->coding); + + parser_dbg_api("parser %s adding api %s\n", str, api->name); + + index = mpp_coding_to_index(api->coding); + if (index < 0 || index >= MPP_ARRAY_ELEMS_S(parser_apis)) + return MPP_NOK; + + if (NULL != parser_apis[index]) { + mpp_logw("parser %s replaced %p -> %p\n", + str, parser_apis[index], api); + } + + parser_apis[index] = api; + return MPP_OK; +} + +MPP_RET mpp_parser_init(Parser *prs, ParserCfg *cfg) +{ + ParserImpl *p; + const ParserApi *api; + MPP_RET ret; + RK_S32 index; + RK_S32 size; + + if (NULL == prs || NULL == cfg) { + mpp_loge_f("found NULL input parser %p config %p\n", prs, cfg); + return MPP_ERR_NULL_PTR; + } + + *prs = NULL; + index = mpp_coding_to_index(cfg->coding); + if (index < 0 || index >= MPP_ARRAY_ELEMS_S(parser_apis)) { + mpp_loge_f("invalid coding type %d\n", cfg->coding); + return MPP_NOK; + } + + if (!parser_apis[index]) { + mpp_loge_f("parser %s is not registered\n", strof_coding_type(cfg->coding)); + return MPP_NOK; + } + + api = parser_apis[index]; + size = sizeof(ParserImpl) + api->ctx_size; + p = mpp_calloc_size(ParserImpl, size); + if (NULL == p) { + mpp_loge_f("failed to alloc parser ctx size %d\n", api->ctx_size); + return MPP_NOK; + } + + p->api = api; + p->ctx = (void *)(p + 1); + ret = api->init(p->ctx, cfg); + if (MPP_OK != ret) { + mpp_loge_f("failed to init parser\n"); + mpp_free(p); + return ret; + } + + *prs = p; + return MPP_OK; +} + +MPP_RET mpp_parser_deinit(Parser prs) +{ + ParserImpl *p; + + if (NULL == prs) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (p->api && p->api->deinit) + p->api->deinit(p->ctx); + + mpp_free(p); + return MPP_OK; +} + +MPP_RET mpp_parser_prepare(Parser prs, MppPacket pkt, HalDecTask *task) +{ + ParserImpl *p; + + if (NULL == prs || NULL == pkt) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (!p->api || !p->api->prepare) + return MPP_OK; + + return p->api->prepare(p->ctx, pkt, task); +} + +MPP_RET mpp_parser_parse(Parser prs, HalDecTask *task) +{ + ParserImpl *p; + + if (NULL == prs || NULL == task) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (!p->api || !p->api->parse) + return MPP_OK; + + return p->api->parse(p->ctx, task); +} + +MPP_RET mpp_parser_callback(void *prs, void *err_info) +{ + ParserImpl *p; + + if (NULL == prs) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (!p->api || !p->api->callback) + return MPP_OK; + + return p->api->callback(p->ctx, err_info); +} + +MPP_RET mpp_parser_reset(Parser prs) +{ + ParserImpl *p; + + if (NULL == prs) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (!p->api || !p->api->reset) + return MPP_OK; + + return p->api->reset(p->ctx); +} + +MPP_RET mpp_parser_flush(Parser prs) +{ + ParserImpl *p; + + if (NULL == prs) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (!p->api || !p->api->flush) + return MPP_OK; + + return p->api->flush(p->ctx); +} + +MPP_RET mpp_parser_control(Parser prs, MpiCmd cmd, void *para) +{ + ParserImpl *p; + + if (NULL == prs) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (!p->api || !p->api->control) + return MPP_OK; + + return p->api->control(p->ctx, cmd, para); +} + +MPP_RET mpp_parser_sync(Parser prs, RK_S32 frame_id) +{ + ParserImpl *p; + + if (NULL == prs) { + mpp_loge_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (ParserImpl *)prs; + if (!p->api || !p->api->sync) + return MPP_OK; + + return p->api->sync(p->ctx, frame_id); +} + diff --git a/mpp/codec/mpp_parser.cpp b/mpp/codec/mpp_parser.cpp deleted file mode 100644 index dc88d41aa..000000000 --- a/mpp/codec/mpp_parser.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_dec" - -#include - -#include "mpp_mem.h" -#include "mpp_log.h" -#include "mpp_common.h" - -#include "mpp_parser.h" - -#include "h264d_api.h" -#include "h265d_api.h" - -// for test and demo -#include "dummy_dec_api.h" - -/* - * all decoder static register here - */ -static const ParserApi *parsers[] = { - &api_h264d_parser, - &dummy_dec_parser, -}; - -typedef struct ParserImpl_t { - ParserCfg cfg; - - const ParserApi *api; - void *ctx; -} ParserImpl; - -MPP_RET parser_init(Parser *prs, ParserCfg *cfg) -{ - if (NULL == prs || NULL == cfg) { - mpp_err_f("found NULL input parser %p config %p\n", prs, cfg); - return MPP_ERR_NULL_PTR; - } - - *prs = NULL; - - RK_U32 i; - for (i = 0; i < MPP_ARRAY_ELEMS(parsers); i++) { - const ParserApi *api = parsers[i]; - if (cfg->coding == api->coding) { - ParserImpl *p = mpp_malloc(ParserImpl, 1); - void *ctx = mpp_calloc_size(void, api->ctx_size); - if (NULL == ctx || NULL == p) { - mpp_err_f("failed to alloc parser context\n"); - mpp_free(p); - mpp_free(ctx); - return MPP_ERR_MALLOC; - } - - MPP_RET ret = api->init(ctx, cfg); - if (MPP_OK != ret) { - mpp_err_f("failed to init parser\n"); - mpp_free(p); - mpp_free(ctx); - return ret; - } - - p->cfg = *cfg; - p->api = api; - p->ctx = ctx; - *prs = p; - return MPP_OK; - } - } - return MPP_NOK; -} - -MPP_RET parser_deinit(Parser prs) -{ - if (NULL == prs) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - ParserImpl *p = (ParserImpl *)prs; - if (p->api->deinit) - p->api->deinit(p->ctx); - - mpp_free(p->ctx); - mpp_free(p); - return MPP_OK; -} - -MPP_RET parser_prepare(Parser prs, MppPacket pkt) -{ - if (NULL == prs || NULL == pkt) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - ParserImpl *p = (ParserImpl *)prs; - if (!p->api->prepare) - return MPP_OK; - - return p->api->prepare(p->ctx, pkt); -} - -MPP_RET parser_parse(Parser prs, MppPacket pkt, HalDecTask *task) -{ - if (NULL == prs || NULL == pkt || NULL == task) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - ParserImpl *p = (ParserImpl *)prs; - if (!p->api->parse) - return MPP_OK; - - return p->api->parse(p->ctx, pkt, task); -} - -MPP_RET parser_reset(Parser prs) -{ - if (NULL == prs) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - ParserImpl *p = (ParserImpl *)prs; - if (!p->api->reset) - return MPP_OK; - - return p->api->reset(p->ctx); -} - -MPP_RET parser_flush(Parser prs) -{ - if (NULL == prs) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - ParserImpl *p = (ParserImpl *)prs; - if (!p->api->flush) - return MPP_OK; - - return p->api->flush(p->ctx); -} - -MPP_RET parser_control(Parser prs, RK_S32 cmd, void *para) -{ - if (NULL == prs) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - ParserImpl *p = (ParserImpl *)prs; - if (!p->api->control) - return MPP_OK; - - return p->api->control(p->ctx, cmd, para); -} - diff --git a/mpp/codec/mpp_rc.c b/mpp/codec/mpp_rc.c new file mode 100644 index 000000000..fb6ffe530 --- /dev/null +++ b/mpp/codec/mpp_rc.c @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_rc" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_rc.h" + +#define MPP_RC_DBG_FUNCTION (0x00000001) +#define MPP_RC_DBG_BPS (0x00000010) +#define MPP_RC_DBG_RC (0x00000020) +#define MPP_RC_DBG_CFG (0x00000100) +#define MPP_RC_DBG_RECORD (0x00001000) +#define MPP_RC_DBG_VBV (0x00002000) + + +#define mpp_rc_dbg(flag, fmt, ...) mpp_dbg(mpp_rc_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_rc_debug, flag, fmt, ## __VA_ARGS__) + +#define mpp_rc_dbg_func(fmt, ...) mpp_rc_dbg_f(MPP_RC_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_bps(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_BPS, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_rc(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_RC, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_cfg(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_CFG, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_vbv(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_VBV, fmt, ## __VA_ARGS__) + + +#define SIGN(a) ((a) < (0) ? (-1) : (1)) +#define DIV(a, b) (((a) + (SIGN(a) * (b)) / 2) / (b)) + +static RK_U32 mpp_rc_debug = 0; + +MPP_RET mpp_data_init(MppData **data, RK_S32 size) +{ + if (NULL == data || size <= 0) { + mpp_err_f("invalid data %p size %d\n", data, size); + return MPP_ERR_NULL_PTR; + } + + *data = NULL; + MppData *p = mpp_malloc_size(MppData, sizeof(MppData) + sizeof(RK_S32) * size); + if (NULL == p) { + mpp_err_f("malloc size %d failed\n", size); + return MPP_ERR_MALLOC; + } + p->size = size; + p->len = 0; + p->pos = 0; + p->val = (RK_S32 *)(p + 1); + *data = p; + + return MPP_OK; +} + +void mpp_data_deinit(MppData *p) +{ + if (p) + mpp_free(p); +} + +void mpp_data_update(MppData *p, RK_S32 val) +{ + mpp_assert(p); + + p->val[p->pos] = val; + + if (++p->pos >= p->size) + p->pos = 0; + + if (p->len < p->size) + p->len++; +} + +RK_S32 mpp_data_avg(MppData *p, RK_S32 len, RK_S32 num, RK_S32 denom) +{ + mpp_assert(p); + + RK_S32 i; + RK_S32 sum = 0; + RK_S32 pos = p->pos; + + if (!p->len) + return 0; + + if (len < 0 || len > p->len) + len = p->len; + + if (num == denom) { + i = len; + while (i--) { + if (pos) + pos--; + else + pos = p->len - 1; + + sum += p->val[pos]; + } + } else { + /* This case is not used so far, but may be useful in the future */ + mpp_assert(num > denom); + RK_S32 acc_num = num; + RK_S32 acc_denom = denom; + + i = len - 1; + sum = p->val[--pos]; + while (i--) { + if (pos) + pos--; + else + pos = p->len - 1; + + sum += p->val[pos] * acc_num / acc_denom; + acc_num *= num; + acc_denom *= denom; + } + } + return DIV(sum, len); +} + +void mpp_pid_reset(MppPIDCtx *p) +{ + p->p = 0; + p->i = 0; + p->d = 0; + p->count = 0; +} + +void mpp_pid_set_param(MppPIDCtx *ctx, RK_S32 coef_p, RK_S32 coef_i, RK_S32 coef_d, RK_S32 div_val, RK_S32 len) +{ + ctx->coef_p = coef_p; + ctx->coef_i = coef_i; + ctx->coef_d = coef_d; + ctx->div = div_val; + ctx->len = len; + ctx->count = 0; + + mpp_rc_dbg_rc("RC: pid ctx %p coef: P %d I %d D %d div %d len %d\n", + ctx, coef_p, coef_i, coef_d, div_val, len); +} + +void mpp_pid_update(MppPIDCtx *ctx, RK_S32 val, RK_S32 is_reset) +{ + mpp_rc_dbg_rc("RC: pid ctx %p update val %d\n", ctx, val); + mpp_rc_dbg_rc("RC: pid ctx %p before update P %d I %d D %d\n", ctx, ctx->p, ctx->i, ctx->d); + + ctx->d = val - ctx->p; /* Derivative */ + ctx->i = val + ctx->i; /* Integral */ + ctx->p = val; /* Proportional */ + + mpp_rc_dbg_rc("RC: pid ctx %p after update P %d I %d D %d\n", ctx, ctx->p, ctx->i, ctx->d); + ctx->count++; + /* + * pid control is a short time control, it needs periodically reset + */ + if (is_reset && ctx->count >= ctx->len) + mpp_pid_reset(ctx); +} + +RK_S32 mpp_pid_calc(MppPIDCtx *p) +{ + RK_S32 a = p->p * p->coef_p + p->i * p->coef_i + p->d * p->coef_d; + RK_S32 b = p->div; + + mpp_rc_dbg_rc("RC: pid ctx %p p %10d coef %d\n", p, p->p, p->coef_p); + mpp_rc_dbg_rc("RC: pid ctx %p i %10d coef %d\n", p, p->i, p->coef_i); + mpp_rc_dbg_rc("RC: pid ctx %p d %10d coef %d\n", p, p->d, p->coef_d); + mpp_rc_dbg_rc("RC: pid ctx %p a %10d b %d\n", p, a, b); + + return DIV(a, b); +} + +MPP_RET mpp_rc_param_ops(struct list_head *head, RK_U32 frm_cnt, + RC_PARAM_OPS ops, void *arg) +{ + MPP_RET ret = MPP_OK; + + if (mpp_rc_debug & MPP_RC_DBG_RECORD) { + RecordNode *pos, *n; + RK_U32 found_match = 0; + + list_for_each_entry_safe(pos, n, head, RecordNode, list) { + if (frm_cnt == pos->frm_cnt) { + found_match = 1; + break; + } + } + + if (!found_match) { + mpp_err("frame %d is not found in list_head %p!\n", frm_cnt, head); + ret = MPP_NOK; + } else { + switch (ops) { + case RC_RECORD_REAL_BITS : { + pos->real_bits = *((RK_U32*)arg); + } break; + case RC_RECORD_QP_SUM : { + pos->qp_sum = *((RK_S32*)arg); + } break; + case RC_RECORD_QP_MIN : { + pos->qp_min = *((RK_S32*)arg); + } break; + case RC_RECORD_QP_MAX : { + pos->qp_max = *((RK_S32*)arg); + } break; + case RC_RECORD_WIN_LEN : { + pos->wlen = *((RK_S32*)arg); + } break; + case RC_RECORD_SET_QP : { + pos->set_qp = *((RK_S32*)arg); + } break; + case RC_RECORD_REAL_QP : { + pos->real_qp = *((RK_S32*)arg); + } break; + case RC_RECORD_SSE_SUM : { + pos->sse_sum = *((RK_S64*)arg); + } break; + default : { + mpp_err("frame %d found invalid operation code %d\n", frm_cnt, ops); + ret = MPP_NOK; + } + } + } + } + + return ret; +} + + diff --git a/mpp/codec/rc/CMakeLists.txt b/mpp/codec/rc/CMakeLists.txt new file mode 100644 index 000000000..b4955074d --- /dev/null +++ b/mpp/codec/rc/CMakeLists.txt @@ -0,0 +1,19 @@ +# vim: syntax=cmake +include_directories(.) + +# ---------------------------------------------------------------------------- +# add mpp rate control function +# ---------------------------------------------------------------------------- +add_library(enc_rc OBJECT + h264e_rc.c + h265e_rc.c + jpege_rc.c + vp8e_rc.c + rc_model_v2_smt.c + rc_model_v2.c + rc_api.c + rc.c + rc_base.c + ) + +add_subdirectory(test) diff --git a/mpp/codec/rc/h264e_rc.c b/mpp/codec/rc/h264e_rc.c new file mode 100644 index 000000000..bb6b05a40 --- /dev/null +++ b/mpp/codec/rc/h264e_rc.c @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h264e_rc" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "rc_debug.h" +#include "rc_ctx.h" +#include "rc_model_v2.h" + +const RcImplApi default_h264e = { + "default", + MPP_VIDEO_CodingAVC, + sizeof(RcModelV2Ctx), + rc_model_v2_init, + rc_model_v2_deinit, + NULL, + rc_model_v2_check_reenc, + rc_model_v2_start, + rc_model_v2_end, + rc_model_v2_hal_start, + rc_model_v2_hal_end, +}; diff --git a/mpp/codec/rc/h264e_rc.h b/mpp/codec/rc/h264e_rc.h new file mode 100644 index 000000000..15cd22d2b --- /dev/null +++ b/mpp/codec/rc/h264e_rc.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef H264E_RC_H +#define H264E_RC_H + +#include "mpp_rc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const RcImplApi default_h264e; + +#ifdef __cplusplus +} +#endif + +#endif /* H264E_RC_H */ diff --git a/mpp/codec/rc/h265e_rc.c b/mpp/codec/rc/h265e_rc.c new file mode 100644 index 000000000..d64d8f0e0 --- /dev/null +++ b/mpp/codec/rc/h265e_rc.c @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "h265e_rc" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "rc_debug.h" +#include "rc_ctx.h" +#include "rc_model_v2.h" + +const RcImplApi default_h265e = { + "default", + MPP_VIDEO_CodingHEVC, + sizeof(RcModelV2Ctx), + rc_model_v2_init, + rc_model_v2_deinit, + NULL, + rc_model_v2_check_reenc, + rc_model_v2_start, + rc_model_v2_end, + rc_model_v2_hal_start, + rc_model_v2_hal_end, +}; diff --git a/mpp/codec/rc/h265e_rc.h b/mpp/codec/rc/h265e_rc.h new file mode 100644 index 000000000..50d0dff57 --- /dev/null +++ b/mpp/codec/rc/h265e_rc.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef H265E_RC_H +#define H265E_RC_H + +#include "mpp_rc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const RcImplApi default_h265e; + +#ifdef __cplusplus +} +#endif + +#endif /* H265E_RC_H */ diff --git a/mpp/codec/rc/jpege_rc.c b/mpp/codec/rc/jpege_rc.c new file mode 100644 index 000000000..b8514f663 --- /dev/null +++ b/mpp/codec/rc/jpege_rc.c @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "jpege_rc" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "rc_debug.h" +#include "rc_ctx.h" +#include "rc_model_v2.h" + +const RcImplApi default_jpege = { + "default", + MPP_VIDEO_CodingMJPEG, + sizeof(RcModelV2Ctx), + rc_model_v2_init, + rc_model_v2_deinit, + NULL, + rc_model_v2_check_reenc, + rc_model_v2_start, + rc_model_v2_end, + rc_model_v2_hal_start, + rc_model_v2_hal_end, +}; diff --git a/mpp/codec/rc/jpege_rc.h b/mpp/codec/rc/jpege_rc.h new file mode 100644 index 000000000..4a01f1436 --- /dev/null +++ b/mpp/codec/rc/jpege_rc.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef JPEGE_RC_H +#define JPEGE_RC_H + +#include "mpp_rc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const RcImplApi default_jpege; + +#ifdef __cplusplus +} +#endif + +#endif /* JPEGE_RC_H */ diff --git a/mpp/codec/rc/rc.c b/mpp/codec/rc/rc.c new file mode 100644 index 000000000..c60d41838 --- /dev/null +++ b/mpp/codec/rc/rc.c @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "rc" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_common.h" + +#include "rc_debug.h" +#include "rc.h" +#include "rc_api.h" +#include "rc_base.h" + +typedef struct MppRcImpl_t { + void *ctx; + const RcImplApi *api; + RcCfg cfg; + + RcFpsCfg fps; + RK_S32 frm_cnt; + + RK_U32 frm_send; + RK_U32 frm_done; +} MppRcImpl; + +RK_U32 rc_debug = 0; + +static const char default_rc_api[] = "default"; + +MPP_RET rc_init(RcCtx *ctx, MppCodingType type, const char **request_name) +{ + MPP_RET ret = MPP_NOK; + MppRcImpl *p = NULL; + RcImplApi *api = NULL; + const char *name = NULL; + + mpp_env_get_u32("rc_debug", &rc_debug, 0); + + if (NULL == request_name || NULL == *request_name) + name = default_rc_api; + else + name = *request_name; + + rc_dbg_func("enter type %x name %s\n", type, name); + + api = rc_api_get(type, name); + + mpp_assert(api); + + if (api) { + void *rc_ctx = mpp_calloc_size(void, api->ctx_size); + + p = mpp_calloc(MppRcImpl, 1); + if (NULL == p || NULL == rc_ctx) { + mpp_err_f("failed to create context size %d\n", api->ctx_size); + MPP_FREE(p); + MPP_FREE(rc_ctx); + ret = MPP_ERR_MALLOC; + } else { + p->ctx = rc_ctx; + p->api = api; + p->frm_cnt = -1; + if (request_name && *request_name) + mpp_log("using rc impl %s\n", api->name); + ret = MPP_OK; + } + } + + *ctx = p; + if (request_name) + *request_name = name; + + rc_dbg_func("leave %p\n", p); + + return ret; +} + +MPP_RET rc_deinit(RcCtx ctx) +{ + MppRcImpl *p = (MppRcImpl *)ctx; + const RcImplApi *api = p->api; + MPP_RET ret = MPP_OK; + + rc_dbg_func("enter %p\n", ctx); + + if (api && api->deinit && p->ctx) { + ret = api->deinit(p->ctx); + MPP_FREE(p->ctx); + } + + MPP_FREE(p); + + rc_dbg_func("leave %p\n", ctx); + + return ret; +} + +MPP_RET rc_update_usr_cfg(RcCtx ctx, RcCfg *cfg) +{ + MppRcImpl *p = (MppRcImpl *)ctx; + const RcImplApi *api = p->api; + MPP_RET ret = MPP_OK; + + rc_dbg_func("enter %p\n", ctx); + + p->cfg = *cfg; + p->fps = cfg->fps; + + if (api && api->init && p->ctx) + api->init(p->ctx, &p->cfg); + + rc_dbg_func("leave %p\n", ctx); + + return ret; +} + +MPP_RET rc_frm_check_drop(RcCtx ctx, EncRcTask *task) +{ + MppRcImpl *p = (MppRcImpl *)ctx; + const RcImplApi *api = p->api; + MPP_RET ret = MPP_OK; + + rc_dbg_func("enter %p\n", ctx); + + if (api && api->check_drop && p->ctx && task) { + ret = api->check_drop(p->ctx, task); + return ret; + } else { + RcFpsCfg *cfg = &p->fps; + RK_S32 frm_cnt = p->frm_cnt; + RK_S32 rate_in = cfg->fps_in_num * cfg->fps_out_denom; + RK_S32 rate_out = cfg->fps_out_num * cfg->fps_in_denom; + RK_S32 drop = 0; + + mpp_assert(cfg->fps_in_denom >= 1); + mpp_assert(cfg->fps_out_denom >= 1); + mpp_assert(rate_in >= rate_out); + + // frame counter is inited to (rate_in - rate_out) to encode first frame + if (frm_cnt < 0) + frm_cnt = rate_in - rate_out; + + frm_cnt += rate_out; + + if (frm_cnt < rate_in) + drop = 1; + else + frm_cnt -= rate_in; + + p->frm_cnt = frm_cnt; + task->frm.drop = drop; + } + + rc_dbg_func("leave %p drop %d\n", ctx, task->frm.drop); + + return ret; +} + +#define MPP_ENC_RC_FUNC(flow, func) \ + MPP_RET rc_##flow##_##func(RcCtx ctx, EncRcTask *task) \ + { \ + MppRcImpl *p = (MppRcImpl *)ctx; \ + const RcImplApi *api = p->api; \ + if (!api || !api->flow##_##func || !p->ctx || !task) \ + return MPP_OK; \ + return api->flow##_##func(p->ctx, task); \ + } + +MPP_ENC_RC_FUNC(check, reenc) +MPP_ENC_RC_FUNC(frm, start) +MPP_ENC_RC_FUNC(frm, end) +MPP_ENC_RC_FUNC(hal, start) +MPP_ENC_RC_FUNC(hal, end) diff --git a/mpp/codec/rc/rc_api.c b/mpp/codec/rc/rc_api.c new file mode 100644 index 000000000..7049532fc --- /dev/null +++ b/mpp/codec/rc/rc_api.c @@ -0,0 +1,309 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "rc_api" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_2str.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "rc_debug.h" +#include "rc_api.h" + +#include "h264e_rc.h" +#include "h265e_rc.h" +#include "jpege_rc.h" +#include "vp8e_rc.h" +#include "rc_model_v2_smt.h" + +#define get_srv_rc_api_srv(caller) \ + ({ \ + MppRcApiSrv *__tmp; \ + if (!rc_api_srv) { \ + rc_api_srv_init(); \ + } \ + if (rc_api_srv) { \ + __tmp = rc_api_srv; \ + } else { \ + mpp_err("mpp rc api srv not init at %s : %s\n", __FUNCTION__, caller); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +// use class to register RcImplApi +typedef struct RcImplApiNode_t { + /* list to list in MppRcApiSrv */ + struct list_head list; + char name[64]; + MppCodingType type; + RcApiBrief brief; + RcImplApi api; +} RcImplApiNode; + +typedef struct MppRcApiSrv_t { + MppMutex lock; + RK_U32 api_cnt; + /* list for list in RcImplApiNode */ + struct list_head list; +} MppRcApiSrv; + +static MppRcApiSrv *rc_api_srv = NULL; + +static void rc_api_srv_init() +{ + MppRcApiSrv *srv = rc_api_srv; + + mpp_env_get_u32("rc_debug", &rc_debug, 0); + + if (srv) + return; + + srv = mpp_malloc(MppRcApiSrv, 1); + if (!srv) { + mpp_err_f("failed to create rc api srv\n"); + return; + } + + rc_api_srv = srv; + + mpp_mutex_init(&srv->lock); + INIT_LIST_HEAD(&srv->list); + srv->api_cnt = 0; + + /* add all default rc apis */ + rc_api_add(&default_h264e); + rc_api_add(&default_h265e); + rc_api_add(&default_jpege); + rc_api_add(&default_vp8e); + rc_api_add(&smt_h264e); + rc_api_add(&smt_h265e); +} + +static void rc_api_srv_deinit() +{ + MppRcApiSrv *srv = rc_api_srv; + + if (!srv) + return; + + mpp_mutex_lock(&srv->lock); + + if (srv->api_cnt) { + RcImplApiNode *pos, *n; + + list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) { + rc_dbg_impl("%-5s rc api %s is removed\n", + strof_coding_type(pos->type), pos->name); + + list_del_init(&pos->list); + MPP_FREE(pos); + srv->api_cnt--; + } + + mpp_assert(srv->api_cnt == 0); + } + + mpp_mutex_unlock(&srv->lock); + mpp_mutex_destroy(&srv->lock); + MPP_FREE(srv); + rc_api_srv = NULL; +} + +static RcImplApi *_rc_api_get(MppRcApiSrv *srv, MppCodingType type, const char *name) +{ + if (!srv->api_cnt) + return NULL; + + if (name) { + RcImplApiNode *pos, *n; + + list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) { + if (type == pos->type && + !strncmp(name, pos->name, sizeof(pos->name) - 1)) { + rc_dbg_impl("%-5s rc api %s is selected\n", + strof_coding_type(type), pos->name); + return &pos->api; + } + } + } + + rc_dbg_impl("%-5s rc api %s can not be found\n", strof_coding_type(type), name); + + return NULL; +} + +static void set_node_api(RcImplApiNode *node, const RcImplApi *api) +{ + node->api = *api; + node->type = api->type; + + strncpy(node->name, api->name, sizeof(node->name) - 1); + node->api.name = api->name; + + node->brief.type = api->type; + node->brief.name = api->name; +} + +MPP_RET rc_api_add(const RcImplApi *api) +{ + MppRcApiSrv *srv = get_srv_rc_api_srv(__FUNCTION__); + RcImplApiNode *node = NULL; + RcImplApi *node_api = NULL; + + if (!api) { + mpp_err_f("unable to register NULL api\n"); + return MPP_NOK; + } + + if (!srv) + return MPP_NOK; + + mpp_mutex_lock(&srv->lock); + + /* search for same node for replacement */ + node_api = _rc_api_get(srv, api->type, api->name); + + if (!node_api) { + node = mpp_malloc(RcImplApiNode, 1); + if (!node) { + mpp_err_f("failed to create api node\n"); + mpp_mutex_unlock(&srv->lock); + return MPP_NOK; + } + + INIT_LIST_HEAD(&node->list); + list_add_tail(&node->list, &srv->list); + + srv->api_cnt++; + rc_dbg_impl("%-5s rc api %s is added\n", strof_coding_type(api->type), api->name); + } else { + node = container_of(node_api, RcImplApiNode, api); + rc_dbg_impl("%-5s rc api %s is updated\n", strof_coding_type(api->type), api->name); + } + + set_node_api(node, api); + mpp_mutex_unlock(&srv->lock); + + return MPP_OK; +} + +RcImplApi *rc_api_get(MppCodingType type, const char *name) +{ + MppRcApiSrv *srv = get_srv_rc_api_srv(__FUNCTION__); + + if (!srv) + return NULL; + + return _rc_api_get(srv, type, name); +} + +MPP_RET rc_api_get_all(MppRcApiSrv *srv, RcApiBrief *brief, RK_S32 *count, RK_S32 max_count) +{ + RcImplApiNode *pos, *n; + RK_S32 cnt = 0; + + mpp_mutex_lock(&srv->lock); + + list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) { + if (cnt >= max_count) + break; + + brief[cnt++] = pos->brief; + } + + *count = cnt; + mpp_mutex_unlock(&srv->lock); + + return MPP_OK; +} + +MPP_RET rc_api_get_by_type(MppRcApiSrv *srv, RcApiBrief *brief, RK_S32 *count, + RK_S32 max_count, MppCodingType type) +{ + RcImplApiNode *pos, *n; + RK_S32 cnt = 0; + + mpp_mutex_lock(&srv->lock); + + list_for_each_entry_safe(pos, n, &srv->list, RcImplApiNode, list) { + if (cnt >= max_count) + break; + + if (pos->type != type) + continue; + + brief[cnt++] = pos->brief; + } + + *count = cnt; + mpp_mutex_unlock(&srv->lock); + + return MPP_OK; +} + +MPP_RET rc_brief_get_all(RcApiQueryAll *query) +{ + MppRcApiSrv *srv = rc_api_srv; + RcApiBrief *brief; + RK_S32 *count; + RK_S32 max_count; + + if (!srv) + return MPP_NOK; + + if (!query) { + mpp_err_f("invalide NULL query input\n"); + return MPP_ERR_NULL_PTR; + } + + brief = query->brief; + count = &query->count; + max_count = query->max_count; + + if (!brief || max_count <= 0) { + mpp_err_f("invalide brief buffer %p max count %d\n", brief, max_count); + return MPP_NOK; + } + + return rc_api_get_all(srv, brief, count, max_count); +} + +MPP_RET rc_brief_get_by_type(RcApiQueryType *query) +{ + MppRcApiSrv *srv = rc_api_srv; + RcApiBrief *brief; + RK_S32 *count; + RK_S32 max_count; + MppCodingType type; + + if (!srv) + return MPP_NOK; + + if (!query) { + mpp_err_f("invalide NULL query input\n"); + return MPP_ERR_NULL_PTR; + } + + brief = query->brief; + count = &query->count; + max_count = query->max_count; + type = query->type; + + if (!brief || max_count <= 0) { + mpp_err_f("invalide brief buffer %p max count %d type %x\n", + brief, max_count, type); + return MPP_NOK; + } + + return rc_api_get_by_type(srv, brief, count, max_count, type); +} + +MPP_SINGLETON(MPP_SGLN_ENC_RC_API, rc_api, rc_api_srv_init, rc_api_srv_deinit) diff --git a/mpp/codec/rc/rc_api.h b/mpp/codec/rc/rc_api.h new file mode 100644 index 000000000..57290076e --- /dev/null +++ b/mpp/codec/rc/rc_api.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#ifndef RC_IMPL_H +#define RC_IMPL_H + +#include "mpp_rc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +RcImplApi *rc_api_get(MppCodingType type, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* RC_IMPL_H */ diff --git a/mpp/codec/rc/rc_base.c b/mpp/codec/rc/rc_base.c new file mode 100644 index 000000000..383146343 --- /dev/null +++ b/mpp/codec/rc/rc_base.c @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "rc_base" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "rc_base.h" + +#define MPP_RC_DBG_FUNCTION (0x00000001) +#define MPP_RC_DBG_BPS (0x00000010) +#define MPP_RC_DBG_RC (0x00000020) +#define MPP_RC_DBG_CFG (0x00000100) +#define MPP_RC_DBG_RECORD (0x00001000) +#define MPP_RC_DBG_VBV (0x00002000) + +#define mpp_rc_dbg(flag, fmt, ...) mpp_dbg(mpp_rc_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_rc_debug, flag, fmt, ## __VA_ARGS__) + +#define mpp_rc_dbg_func(fmt, ...) mpp_rc_dbg_f(MPP_RC_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_bps(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_BPS, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_rc(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_RC, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_cfg(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_CFG, fmt, ## __VA_ARGS__) +#define mpp_rc_dbg_vbv(fmt, ...) mpp_rc_dbg(MPP_RC_DBG_VBV, fmt, ## __VA_ARGS__) + +#define SIGN(a) ((a) < (0) ? (-1) : (1)) +#define DIV(a, b) (((a) + (SIGN(a) * (b)) / 2) / (b)) + +MPP_RET mpp_data_init_v2(MppDataV2 **data, RK_S32 size, RK_S32 value) +{ + MppDataV2 *p; + + if (!data || size <= 0) { + mpp_err_f("invalid data %p size %d\n", data, size); + return MPP_ERR_NULL_PTR; + } + + *data = NULL; + p = mpp_malloc_size(MppDataV2, sizeof(MppDataV2) + sizeof(RK_S32) * size); + if (!p) { + mpp_err_f("malloc size %d failed\n", size); + return MPP_ERR_MALLOC; + } + p->size = size; + p->pos_r = 0; + p->pos_pw = 0; + p->pos_w = 0; + p->pos_ahead = 0; + p->sum = 0; + *data = p; + + mpp_data_reset_v2(p, value); + return MPP_OK; +} + +void mpp_data_deinit_v2(MppDataV2 *p) +{ + MPP_FREE(p); +} + +void mpp_data_reset_v2(MppDataV2 *p, RK_S32 val) +{ + RK_S32 *data = p->val; + RK_S32 i; + + p->pos_pw = 0; + p->pos_w = 0; + p->pos_r = p->size; + p->sum = val * p->size; + + for (i = 0; i < p->size; i++) + *data++ = val; +} + +void mpp_data_preset_v2(MppDataV2 *p, RK_S32 val) +{ + mpp_assert(p); + if (p->pos_r == p->size) { + p->pos_r--; + p->sum -= p->val[p->pos_pw]; + } + mpp_assert(p->pos_r < p->size); + p->val[p->pos_pw] = val; + p->sum += p->val[p->pos_pw]; + p->pos_pw++; + p->pos_r++; + if (p->pos_pw >= p->size) { + p->pos_pw = 0; + } + p->pos_ahead++; +} + +void mpp_data_update_v2(MppDataV2 *p, RK_S32 val) +{ + if (p->pos_ahead) { + p->sum += val - p->val[p->pos_w]; + p->val[p->pos_w] = val; + p->pos_w++; + if (p->pos_w >= p->size) + p->pos_w = 0; + + p->pos_ahead--; + + return; + } + + mpp_assert(p); + if (p->pos_r == p->size) { + p->pos_r--; + p->sum -= p->val[p->pos_w]; + } + mpp_assert(p->pos_r < p->size); + p->val[p->pos_w] = val; + p->sum += p->val[p->pos_w]; + p->pos_w++; + p->pos_r++; + if (p->pos_w >= p->size) + p->pos_w = 0; +} + +RK_S32 mpp_data_get_pre_val_v2(MppDataV2 *p, RK_S32 idx) +{ + RK_S32 pos = 0; + + if (idx < 0) { + idx = p->size + idx; + } + mpp_assert(p->pos_w < p->size); + mpp_assert(idx < p->size); + + pos = p->pos_w - 1; + if (pos - idx < 0) { + RK_S32 pos1 = idx - pos; + + mpp_assert(p->pos_r == p->size); + pos = p->size - pos1; + } else { + pos = pos - idx; + } + mpp_assert(pos < p->size); + return p->val[pos]; +} + +RK_S32 mpp_data_sum_v2(MppDataV2 *p) +{ + return (RK_S32)p->sum; +} +RK_S32 mpp_data_mean_v2(MppDataV2 *p) +{ + RK_S32 mean = (RK_S32)p->sum / p->size; + + return mean; +} + +RK_S32 mpp_data_sum_with_ratio_v2(MppDataV2 *p, RK_S32 len, RK_S32 num, RK_S32 denom) +{ + RK_S32 i; + RK_S64 sum = 0; + RK_S32 *data = p->val; + + mpp_assert(len <= p->size); + + if (num == denom) { + for (i = 0; i < len; i++) + sum += *data++; + } else { + // NOTE: use 64bit to avoid 0 in 32bit + RK_S64 acc_num = 1; + RK_S64 acc_denom = 1; + + for (i = 0; i < len; i++) { + sum += p->val[i] * acc_num / acc_denom; + acc_num *= num; + acc_denom *= denom; + } + } + + return DIV(sum, len); +} diff --git a/mpp/codec/rc/rc_base.h b/mpp/codec/rc/rc_base.h new file mode 100644 index 000000000..70fa5cff0 --- /dev/null +++ b/mpp/codec/rc/rc_base.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2016 Rockchip Electronics Co., Ltd. + */ + +#ifndef RC_BASE_H +#define RC_BASE_H + +#include "mpp_list.h" +#include "mpp_enc_cfg.h" +#include "mpp_rc.h" + +/* + * mpp rate control contain common caculation methd + */ + +/* + * 1. MppData - data statistic struct + * size - max valid data number + * pos_pw - current data preset write position + * pos_w - current data write position + * pos_r - current data read position + * val - buffer array pointer + * + * When statistic length is less than 8 use direct save mode which will move + * all the data on each update. + * When statistic length is larger than 8 use loop save mode which will + * cyclically reuse the data position. + */ +typedef struct MppDataV2_t { + RK_S32 size; + RK_S32 pos_r; + RK_S32 pos_pw; + RK_S32 pos_w; + RK_S32 pos_ahead; + RK_S64 sum; + RK_S32 val[0]; +} MppDataV2; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_data_init_v2(MppDataV2 **p, RK_S32 len, RK_S32 value); +void mpp_data_deinit_v2(MppDataV2 *p); +void mpp_data_reset_v2(MppDataV2 *p, RK_S32 val); +void mpp_data_preset_v2(MppDataV2 *p, RK_S32 val); +void mpp_data_update_v2(MppDataV2 *p, RK_S32 val); +RK_S32 mpp_data_sum_v2(MppDataV2 *p); +RK_S32 mpp_data_mean_v2(MppDataV2 *p); +RK_S32 mpp_data_get_pre_val_v2(MppDataV2 *p, RK_S32 idx); +RK_S32 mpp_data_sum_with_ratio_v2(MppDataV2 *p, RK_S32 len, RK_S32 num, RK_S32 denom); + +#ifdef __cplusplus +} +#endif + +#endif /* RC_BASE_H */ diff --git a/mpp/codec/rc/rc_ctx.h b/mpp/codec/rc/rc_ctx.h new file mode 100644 index 000000000..4c646930a --- /dev/null +++ b/mpp/codec/rc/rc_ctx.h @@ -0,0 +1,134 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RC_CTX_H +#define RC_CTX_H + +#include "mpp_rc_api.h" +#include "rc_base.h" + +typedef struct RcModelV2Ctx_t { + RcCfg usr_cfg; + + RK_U32 last_frame_type; + RK_S64 gop_total_bits; + RK_U32 bit_per_frame; + RK_U32 first_frm_flg; + RK_S64 avg_gbits; + RK_S64 real_gbits; + + MppDataV2 *i_bit; + RK_U32 i_sumbits; + RK_U32 i_scale; + + MppDataV2 *idr_bit; + RK_U32 idr_sumbits; + RK_U32 idr_scale; + + MppDataV2 *vi_bit; + RK_U32 vi_sumbits; + RK_U32 vi_scale; + RK_U32 i_refresh_scale; + MppDataV2 *p_bit; + RK_U32 p_sumbits; + RK_U32 i_refresh_sumbits; + RK_U32 p_scale; + + MppDataV2 *pre_p_bit; + MppDataV2 *pre_i_bit; + MppDataV2 *i_refresh_bit; + MppDataV2 *pre_i_mean_qp; + MppDataV2 *madi; + MppDataV2 *madp; + MppDataV2 *motion_level; + MppDataV2 *complex_level; + + RK_S32 target_bps; + RK_S32 pre_target_bits; + RK_S32 pre_target_bits_fix; + RK_S64 pre_target_bits_fix_count; + RK_S64 pre_real_bits_count; + RK_S32 pre_real_bits; + RK_S32 frm_bits_thr; + RK_S32 ins_bps; + RK_S32 last_inst_bps; + + RK_U32 motion_sensitivity; + RK_U32 min_still_percent; + RK_U32 max_still_qp; + RK_S32 moving_ratio; + RK_U32 pre_mean_qp; + RK_U32 pre_i_scale; + RK_S32 cur_super_thd; + MppDataV2 *stat_bits; + MppDataV2 *gop_bits; + MppDataV2 *stat_rate; + RK_S32 watl_thrd; + RK_S32 stat_watl; + RK_S32 watl_base; + + RK_S32 next_i_ratio; // scale 64 + RK_S32 next_ratio; // scale 64 + RK_S32 pre_i_qp; + RK_S32 pre_p_qp; + RK_U32 scale_qp; // scale 64 + MppDataV2 *means_qp; + RK_U32 frm_num; + + /* qp decision */ + RK_S32 cur_scale_qp; + RK_S32 start_qp; + RK_S32 prev_quality; + RK_S32 prev_md_prop; + RK_S32 gop_qp_sum; + RK_S32 gop_frm_cnt; + RK_S32 pre_iblk4_prop; + + RK_S32 reenc_cnt; + RK_U32 drop_cnt; + RK_S32 on_drop; + RK_S32 on_pskip; + RK_S32 qp_layer_id; + RK_S32 hier_frm_cnt[4]; + + RK_S64 time_base; + RK_S64 time_end; + RK_S32 frm_cnt; + RK_S32 last_fps; + + MPP_RET (*calc_ratio)(void* ctx, EncRcTaskInfo *cfg); + MPP_RET (*re_calc_ratio)(void* ctx, EncRcTaskInfo *cfg); +} RcModelV2Ctx; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* basic helper function */ +MPP_RET bits_model_init(RcModelV2Ctx *ctx); +MPP_RET bits_model_deinit(RcModelV2Ctx *ctx); + +MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bits); +MPP_RET bits_model_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg); + +MPP_RET calc_next_i_ratio(RcModelV2Ctx *ctx); +MPP_RET check_re_enc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* RC_CTX_H */ diff --git a/mpp/codec/rc/rc_debug.h b/mpp/codec/rc/rc_debug.h new file mode 100644 index 000000000..af8e0a38c --- /dev/null +++ b/mpp/codec/rc/rc_debug.h @@ -0,0 +1,49 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RC_DEBUG_H +#define RC_DEBUG_H + +#include "mpp_debug.h" + +#define RC_DBG_FUNCTION (0x00000001) +#define RC_DBG_API_IMPL (0x00000002) +#define RC_DBG_FPS (0x00000010) +#define RC_DBG_BPS (0x00000020) +#define RC_DBG_RC (0x00000040) +#define RC_DBG_QP (0x00000080) +#define RC_DBG_CFG (0x00000100) +#define RC_DBG_DROP (0x00000200) +#define RC_DBG_RECORD (0x00001000) +#define RC_DBG_VBV (0x00002000) + +#define rc_dbg(flag, fmt, ...) mpp_dbg(rc_debug, flag, fmt, ## __VA_ARGS__) +#define rc_dbg_f(flag, fmt, ...) mpp_dbg_f(rc_debug, flag, fmt, ## __VA_ARGS__) + +#define rc_dbg_func(fmt, ...) rc_dbg_f(RC_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define rc_dbg_impl(fmt, ...) rc_dbg(RC_DBG_API_IMPL, fmt, ## __VA_ARGS__) +#define rc_dbg_fps(fmt, ...) rc_dbg_f(RC_DBG_FPS, fmt, ## __VA_ARGS__) +#define rc_dbg_bps(fmt, ...) rc_dbg_f(RC_DBG_BPS, fmt, ## __VA_ARGS__) +#define rc_dbg_rc(fmt, ...) rc_dbg_f(RC_DBG_RC, fmt, ## __VA_ARGS__) +#define rc_dbg_qp(fmt, ...) rc_dbg_f(RC_DBG_QP, fmt, ## __VA_ARGS__) + +#define rc_dbg_cfg(fmt, ...) rc_dbg(RC_DBG_CFG, fmt, ## __VA_ARGS__) +#define rc_dbg_drop(fmt, ...) rc_dbg(RC_DBG_DROP, fmt, ## __VA_ARGS__) +#define rc_dbg_vbv(fmt, ...) rc_dbg(RC_DBG_VBV, fmt, ## __VA_ARGS__) + +extern RK_U32 rc_debug; + +#endif /* RC_DEBUG_H */ diff --git a/mpp/codec/rc/rc_model_v2.c b/mpp/codec/rc/rc_model_v2.c new file mode 100644 index 000000000..4b96de1a8 --- /dev/null +++ b/mpp/codec/rc/rc_model_v2.c @@ -0,0 +1,1842 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "rc_model_v2" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_time.h" +#include "rc_debug.h" +#include "rc_ctx.h" +#include "rc_model_v2.h" + +#define I_WINDOW_LEN 2 +#define P_WINDOW1_LEN 5 +#define P_WINDOW2_LEN 8 +#define MAX_BIT_COUNT_VALUE 1000000000000000 + +static const RK_S32 max_i_delta_qp[51] = { + 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, + 576, 576, 512, 512, 448, 448, 384, 384, 320, 320, 320, 256, 256, 256, + 192, 192, 192, 192, 192, 128, 128, 128, 128, 128, 128, 64, 64, 64, + 64, 64, 64, 0, 0, 0, 0, 0, 0, +}; + +RK_S32 tab_lnx[64] = { + -1216, -972, -830, -729, -651, -587, -533, -486, + -445, -408, -374, -344, -316, -290, -265, -243, + -221, -201, -182, -164, -147, -131, -115, -100, + -86, -72, -59, -46, -34, -22, -11, 0, + 10, 21, 31, 41, 50, 60, 69, 78, + 86, 95, 87, 103, 111, 119, 127, 134, + 142, 149, 156, 163, 170, 177, 183, 190, + 196, 202, 208, 214, 220, 226, 232, 237, +}; + +RK_S32 mean_qp2scale[16] = { + 14, 15, 16, 18, 20, 22, 25, 28, + 32, 36, 40, 44, 50, 56, 64, 72 +}; +const RK_S8 max_ip_qp_dealt[8] = { + 7, 7, 6, 6, 5, 5, 4, 4 +}; +RK_U32 bit2percent[100] = { + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 95, 90, 85, 80, 75, 72, 69, 66, 64, + 62, 59, 58, 57, 56, 55, 54, 53, 52, 51, + 50, 49, 48, 47, 47, 46, 46, 45, 45, 44, + 44, 43, 43, 43, 42, 42, 42, 41, 41, 41, + 40, 40, 40, 39, 39, 39, 38, 38, 38, 37, + 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, + 36, 36, 36, 35, 35, 35, 34, 34, 34, 34, + 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, +}; + +RK_S8 intra_qp_map[8] = { + 0, 0, 1, 1, 2, 2, 2, 2, +}; + +MPP_RET bits_model_param_deinit(RcModelV2Ctx *ctx) +{ + rc_dbg_func("enter %p\n", ctx); + + if (ctx->i_bit != NULL) { + mpp_data_deinit_v2(ctx->i_bit); + ctx->i_bit = NULL; + } + + if (ctx->p_bit != NULL) { + mpp_data_deinit_v2(ctx->p_bit); + ctx->p_bit = NULL; + } + + if (ctx->vi_bit != NULL) { + mpp_data_deinit_v2(ctx->vi_bit); + ctx->vi_bit = NULL; + } + + if (ctx->pre_p_bit != NULL) { + mpp_data_deinit_v2(ctx->pre_p_bit); + ctx->pre_p_bit = NULL; + } + + if (ctx->pre_i_bit != NULL) { + mpp_data_deinit_v2(ctx->pre_i_bit); + ctx->pre_i_bit = NULL; + } + + if (ctx->pre_i_mean_qp != NULL) { + mpp_data_deinit_v2(ctx->pre_i_mean_qp); + ctx->pre_i_mean_qp = NULL; + } + + if (ctx->madi != NULL) { + mpp_data_deinit_v2(ctx->madi); + ctx->madi = NULL; + } + if (ctx->madp != NULL) { + mpp_data_deinit_v2(ctx->madp); + ctx->madp = NULL; + } + + if (ctx->stat_rate != NULL) { + mpp_data_deinit_v2(ctx->stat_rate); + ctx->stat_rate = NULL; + } + + if (ctx->stat_bits != NULL) { + mpp_data_deinit_v2(ctx->stat_bits); + ctx->stat_bits = NULL; + } + if (ctx->gop_bits != NULL) { + mpp_data_deinit_v2(ctx->gop_bits); + ctx->gop_bits = NULL; + } + if (ctx->motion_level != NULL) { + mpp_data_deinit_v2(ctx->motion_level); + ctx->motion_level = NULL; + } + if (ctx->complex_level != NULL) { + mpp_data_deinit_v2(ctx->complex_level); + ctx->complex_level = NULL; + } + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET bits_model_param_init(RcModelV2Ctx *ctx) +{ + RK_S32 gop_len = ctx->usr_cfg.igop; + RcFpsCfg *fps = &ctx->usr_cfg.fps; + RK_S32 mad_len = 10; + RK_U32 stat_len = fps->fps_out_num * ctx->usr_cfg.stats_time / fps->fps_out_denom; + stat_len = (stat_len != 0) ? stat_len : 1; + + bits_model_param_deinit(ctx); + mpp_data_init_v2(&ctx->i_bit, I_WINDOW_LEN, 0); + if (ctx->i_bit == NULL) { + mpp_err("i_bit init fail"); + return MPP_ERR_MALLOC; + } + + mpp_data_init_v2(&ctx->vi_bit, I_WINDOW_LEN, 0); + if (ctx->vi_bit == NULL) { + mpp_err("vi_bit init fail"); + return MPP_ERR_MALLOC; + } + mpp_data_init_v2(&ctx->p_bit, P_WINDOW1_LEN, 0); + if (ctx->p_bit == NULL) { + mpp_err("p_bit init fail"); + return MPP_ERR_MALLOC; + } + + mpp_data_init_v2(&ctx->pre_p_bit, P_WINDOW2_LEN, 0); + if (ctx->pre_p_bit == NULL) { + mpp_err("pre_p_bit init fail"); + return MPP_ERR_MALLOC; + } + + mpp_data_init_v2(&ctx->pre_i_bit, I_WINDOW_LEN, 0); + if (ctx->pre_i_bit == NULL) { + mpp_err("pre_i_bit init fail"); + return MPP_ERR_MALLOC; + } + + mpp_data_init_v2(&ctx->pre_i_mean_qp, I_WINDOW_LEN, -1); + if (ctx->pre_i_mean_qp == NULL) { + mpp_err("pre_i_mean_qp init fail"); + return MPP_ERR_MALLOC; + } + mpp_data_init_v2(&ctx->madi, P_WINDOW2_LEN, 0); + if (ctx->madi == NULL) { + mpp_err("madi init fail"); + return MPP_ERR_MALLOC; + } + mpp_data_init_v2(&ctx->madp, P_WINDOW2_LEN, 0); + if (ctx->madp == NULL) { + mpp_err("madp init fail"); + return MPP_ERR_MALLOC; + } + mpp_data_init_v2(&ctx->stat_rate, fps->fps_out_num, 0); + if (ctx->stat_rate == NULL) { + mpp_err("stat_rate init fail fps_out_num %d", fps->fps_out_num); + return MPP_ERR_MALLOC; + } + + mpp_data_init_v2(&ctx->stat_bits, stat_len, ctx->bit_per_frame); + if (ctx->stat_bits == NULL) { + mpp_err("stat_bits init fail stat_len %d", stat_len); + return MPP_ERR_MALLOC; + } + + mpp_data_init_v2(&ctx->gop_bits, gop_len, 0); + if (ctx->gop_bits == NULL) { + mpp_err("gop_bits init fail gop_len %d", gop_len); + return MPP_ERR_MALLOC; + } + + if (ctx->usr_cfg.refresh_len) { + mpp_data_init_v2(&ctx->i_refresh_bit, ctx->usr_cfg.refresh_len, 0); + if (ctx->i_refresh_bit == NULL) { + mpp_err("i_refresh_bit init fail refresh_len %d", ctx->usr_cfg.refresh_len); + return MPP_ERR_MALLOC; + } + } + + mpp_data_init_v2(&ctx->motion_level, mad_len, 0); + if (ctx->motion_level == NULL) { + mpp_err("motion_level init fail mad_len %d\n", mad_len); + return MPP_ERR_MALLOC; + } + + mpp_data_init_v2(&ctx->complex_level, mad_len, 0); + if (ctx->complex_level == NULL) { + mpp_err("complex_level init fail mad_len %d\n", mad_len); + return MPP_ERR_MALLOC; + } + + return MPP_OK; +} + +void bits_frm_init(RcModelV2Ctx *ctx) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_U32 gop_len = usr_cfg->igop; + RK_U32 p_bit = 0; + RK_U32 refresh_bit = 0; + + rc_dbg_func("enter %p\n", ctx); + + switch (usr_cfg->gop_mode) { + case NORMAL_P: { + ctx->i_scale = ctx->usr_cfg.init_ip_ratio; + ctx->p_scale = 16; + if (gop_len <= 1) + p_bit = ctx->gop_total_bits * 16; + else + p_bit = ctx->gop_total_bits * 16 / (ctx->i_scale + ctx->p_scale * (gop_len - 1)); + mpp_data_reset_v2(ctx->p_bit, p_bit); + ctx->p_sumbits = 5 * p_bit; + mpp_data_reset_v2(ctx->i_bit, p_bit * ctx->i_scale / 16); + ctx->i_sumbits = 2 * p_bit * ctx->i_scale / 16; + if (usr_cfg->refresh_len) { + ctx->i_refresh_scale = ctx->i_scale / usr_cfg->refresh_len + ctx->p_scale; + refresh_bit = ctx->gop_total_bits * 16 / (ctx->i_refresh_scale * usr_cfg->refresh_len + + ctx->p_scale * (gop_len - usr_cfg->refresh_len)); + mpp_data_reset_v2(ctx->i_refresh_bit, refresh_bit); + ctx->i_refresh_sumbits = usr_cfg->refresh_len * refresh_bit; + } + } break; + case SMART_P: { + RK_U32 vi_num = 0; + mpp_assert(usr_cfg->vgop > 1); + ctx->i_scale = 320; + ctx->p_scale = 16; + ctx->vi_scale = 32; + vi_num = gop_len / usr_cfg->vgop; + if (vi_num > 0) { + vi_num = vi_num - 1; + } + p_bit = ctx->gop_total_bits * 16 / (ctx->i_scale + ctx->vi_scale * vi_num + ctx->p_scale * (gop_len - vi_num)); + mpp_data_reset_v2(ctx->p_bit, p_bit); + ctx->p_sumbits = 5 * p_bit; + + mpp_data_reset_v2(ctx->i_bit, p_bit * ctx->i_scale / 16); + ctx->i_sumbits = 2 * p_bit * ctx->i_scale / 16; + + mpp_data_reset_v2(ctx->vi_bit, p_bit * ctx->vi_scale / 16); + ctx->vi_sumbits = 2 * p_bit * ctx->vi_scale / 16; + } break; + default: + break; + } + rc_dbg_rc("p_sumbits %d i_sumbits %d vi_sumbits %d\n", ctx->p_sumbits, ctx->i_sumbits, ctx->vi_sumbits); + rc_dbg_func("leave %p\n", ctx); +} + +RK_S32 moving_judge_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) +{ + switch (cfg->frame_type) { + case INTRA_FRAME: { + mpp_data_update_v2(ctx->pre_i_bit, cfg->bit_real); + mpp_data_update_v2(ctx->pre_i_mean_qp, cfg->quality_real); + } break; + + case INTER_P_FRAME: { + mpp_data_update_v2(ctx->pre_p_bit, cfg->bit_real); + mpp_data_update_v2(ctx->madp, cfg->madp); + } break; + + default: + break; + } + return 0; +} + +void bit_statics_update(RcModelV2Ctx *ctx, RK_U32 real_bit) +{ + RK_S32 mean_pbits, mean_ibits; + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_U32 gop_len = usr_cfg->igop; + + mpp_data_update_v2(ctx->gop_bits, real_bit); + mean_pbits = mpp_data_mean_v2(ctx->pre_p_bit); + mean_ibits = mpp_data_mean_v2(ctx->pre_i_bit); + ctx->real_gbits = mpp_data_sum_v2(ctx->gop_bits); + ctx->avg_gbits = (gop_len - 1) * (RK_S64)mean_pbits + mean_ibits; +} + +MPP_RET bits_model_preset(RcModelV2Ctx *ctx, EncRcTaskInfo *info) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 preset_bit = info->bit_target; + RK_S32 water_level = 0; + + mpp_data_preset_v2(ctx->stat_rate, preset_bit != 0); + mpp_data_preset_v2(ctx->stat_bits, preset_bit); + + ctx->ins_bps = mpp_data_sum_v2(ctx->stat_bits) / usr_cfg->stats_time; + if (preset_bit + ctx->stat_watl > ctx->watl_thrd) + water_level = ctx->watl_thrd - ctx->bit_per_frame; + else + water_level = preset_bit + ctx->stat_watl - ctx->bit_per_frame; + + if (water_level < 0) { + water_level = 0; + } + ctx->stat_watl = water_level; + switch (info->frame_type) { + case INTRA_FRAME : { + mpp_data_preset_v2(ctx->i_bit, preset_bit); + ctx->i_sumbits = mpp_data_sum_v2(ctx->i_bit); + ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits); + rc_dbg_rc("i_sumbits %d p_sumbits %d i_scale %d\n", + ctx->i_sumbits, ctx->p_sumbits, ctx->i_scale); + } break; + case INTER_P_FRAME : { + mpp_data_preset_v2(ctx->p_bit, preset_bit); + ctx->p_sumbits = mpp_data_sum_v2(ctx->p_bit); + + /* Avoid div zero when P frame successive drop */ + if (!ctx->p_sumbits) + ctx->p_sumbits = 1; + + ctx->p_scale = 16; + } break; + case INTER_VI_FRAME : { + mpp_data_preset_v2(ctx->vi_bit, preset_bit); + ctx->vi_sumbits = mpp_data_sum_v2(ctx->vi_bit); + ctx->vi_scale = 80 * ctx->vi_sumbits / (2 * ctx->p_sumbits); + /* NOTE: vi_scale may be set to zero. So we should limit the range */ + ctx->vi_scale = mpp_clip(ctx->vi_scale, 16, 320); + } break; + case INTRA_RFH_FRAME: { + mpp_data_update_v2(ctx->i_refresh_bit, preset_bit); + mpp_data_update_v2(ctx->madi, info->madi); + ctx->i_refresh_sumbits = mpp_data_sum_v2(ctx->i_refresh_bit); + ctx->i_refresh_scale = 80 * ctx->i_refresh_sumbits / (usr_cfg->refresh_len * ctx->p_sumbits); + ctx->i_refresh_scale = mpp_clip(ctx->i_refresh_scale, 16, 64); + } break; + default : { + } break; + } + return MPP_OK; +} + +MPP_RET bits_model_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 real_bit = cfg->bit_real; + RK_U32 madi = cfg->madi; + RK_S32 water_level = 0; + + rc_dbg_func("enter %p\n", ctx); + + mpp_data_update_v2(ctx->stat_rate, real_bit != 0); + mpp_data_update_v2(ctx->stat_bits, real_bit); + + ctx->ins_bps = mpp_data_sum_v2(ctx->stat_bits) / usr_cfg->stats_time; + if (real_bit + ctx->stat_watl > ctx->watl_thrd) + water_level = ctx->watl_thrd - ctx->bit_per_frame; + else + water_level = real_bit + ctx->stat_watl - ctx->bit_per_frame; + + if (water_level < 0) + water_level = 0; + + ctx->stat_watl = water_level; + + switch (cfg->frame_type) { + case INTRA_FRAME : { + mpp_data_update_v2(ctx->i_bit, real_bit); + ctx->i_sumbits = mpp_data_sum_v2(ctx->i_bit); + ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits); + rc_dbg_rc("i_sumbits %d p_sumbits %d i_scale %d\n", + ctx->i_sumbits, ctx->p_sumbits, ctx->i_scale); + } break; + case INTER_P_FRAME : { + mpp_data_update_v2(ctx->p_bit, real_bit); + mpp_data_update_v2(ctx->madi, madi); + ctx->p_sumbits = mpp_data_sum_v2(ctx->p_bit); + + /* Avoid div zero when P frame successive drop */ + if (!ctx->p_sumbits) + ctx->p_sumbits = 1; + + ctx->p_scale = 16; + } break; + case INTER_VI_FRAME: { + mpp_data_update_v2(ctx->vi_bit, real_bit); + ctx->vi_sumbits = mpp_data_sum_v2(ctx->vi_bit); + ctx->vi_scale = 80 * ctx->vi_sumbits / (2 * ctx->p_sumbits); + /* NOTE: vi_scale may be set to zero. So we should limit the range */ + ctx->vi_scale = mpp_clip(ctx->vi_scale, 16, 320); + } break; + case INTRA_RFH_FRAME: { + mpp_data_update_v2(ctx->i_refresh_bit, real_bit); + mpp_data_update_v2(ctx->madi, madi); + ctx->i_refresh_sumbits = mpp_data_sum_v2(ctx->i_refresh_bit); + ctx->i_refresh_scale = 80 * ctx->i_refresh_sumbits / (usr_cfg->refresh_len * ctx->p_sumbits); + ctx->i_refresh_scale = mpp_clip(ctx->i_refresh_scale, 16, 64); + } break; + default : { + } break; + } + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bits) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_U32 max_i_prop = usr_cfg->max_i_bit_prop * 16; + RK_S32 gop_len = usr_cfg->igop; + RK_S32 i_scale = ctx->i_scale; + RK_S32 vi_scale = ctx->vi_scale; + RK_S32 alloc_bits = 0; + RK_S32 super_bit_thr = 0x7fffffff; + RK_S64 total_bits_fix = total_bits; + + ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits); + i_scale = ctx->i_scale; + + rc_dbg_func("enter %p\n", ctx); + rc_dbg_rc("frame_type %d max_i_prop %d i_scale %d total_bits %lld\n", + cfg->frame_type, max_i_prop, i_scale, total_bits); + if (usr_cfg->super_cfg.super_mode) { + super_bit_thr = usr_cfg->super_cfg.super_p_thd; + } + if (usr_cfg->gop_mode == SMART_P) { + RK_U32 vi_num = 0; + mpp_assert(usr_cfg->vgop > 1); + vi_num = gop_len / usr_cfg->vgop; + if (vi_num > 0) { + vi_num = vi_num - 1; + } + switch (cfg->frame_type) { + case INTRA_FRAME: { + i_scale = mpp_clip(i_scale, 16, 16000); + total_bits = total_bits * i_scale; + if (usr_cfg->super_cfg.super_mode) { + super_bit_thr = usr_cfg->super_cfg.super_i_thd; + } + } break; + case INTER_P_FRAME: { + i_scale = mpp_clip(i_scale, 16, max_i_prop); + total_bits = total_bits * 16; + } break; + case INTER_VI_FRAME: { + i_scale = mpp_clip(i_scale, 16, max_i_prop); + total_bits = total_bits * vi_scale; + } break; + default: + break; + } + + alloc_bits = total_bits / (i_scale + 16 * (gop_len - vi_num) + vi_num * vi_scale); + + if (!alloc_bits) { + mpp_log_f("found zero alloc bits\n"); + mpp_log_f("total_bits %lld, i_scale %d, gop_len %d, vi_num %d, vi_scale %d", + total_bits, i_scale, gop_len, vi_num, vi_scale); + mpp_log_f("gop_total_bits %lld, i_sumbits %d, p_sumbits %d, vgop %d igop %d", + ctx->gop_total_bits, ctx->i_sumbits, ctx->p_sumbits, usr_cfg->vgop, usr_cfg->igop); + } + } else { + switch (cfg->frame_type) { + case INTRA_FRAME: { + i_scale = mpp_clip(i_scale, 16, 16000); + total_bits = total_bits * i_scale; + if (usr_cfg->super_cfg.super_mode) { + super_bit_thr = usr_cfg->super_cfg.super_i_thd; + } + } break; + + case INTER_P_FRAME: { + i_scale = mpp_clip(i_scale, 16, max_i_prop); + total_bits = total_bits * 16; + } break; + case INTRA_RFH_FRAME: { + i_scale = mpp_clip(i_scale, 16, max_i_prop); + total_bits = total_bits * ctx->i_refresh_scale; + rc_dbg_rc("ctx->i_refresh_scale = %d", ctx->i_refresh_scale); + } break; + default: + break; + } + if (gop_len > 1) { + if (!usr_cfg->refresh_len || cfg->frame_type == INTRA_FRAME) + alloc_bits = total_bits / (i_scale + 16 * (gop_len - 1)); + else + alloc_bits = total_bits / + (ctx->i_refresh_scale * usr_cfg->refresh_len + + 16 * (gop_len - usr_cfg->refresh_len)); + } else { + alloc_bits = total_bits / i_scale; + } + } + rc_dbg_rc("i_scale %d, total_bits %lld", i_scale, total_bits); + if (alloc_bits > super_bit_thr && + (usr_cfg->super_cfg.rc_priority == MPP_ENC_RC_BY_FRM_SIZE_FIRST)) { + alloc_bits = super_bit_thr - (super_bit_thr >> 4); + rc_dbg_rc("alloc bits max then super_bit_thr %d", super_bit_thr); + } + + ctx->cur_super_thd = super_bit_thr; + cfg->bit_target = alloc_bits; + if (cfg->frame_type == INTRA_FRAME) + cfg->bit_target_fix = total_bits_fix * 240 / (240 + 16 * (gop_len - 1)); + else + cfg->bit_target_fix = total_bits_fix * 16 / (240 + 16 * (gop_len - 1)); + + mpp_assert(alloc_bits); + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET calc_next_i_ratio(RcModelV2Ctx *ctx) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 max_i_prop = usr_cfg->max_i_bit_prop * 16; + RK_S32 gop_len = usr_cfg->igop; + RK_S32 pre_qp = ctx->pre_i_qp; + RK_S32 bits_alloc; + + rc_dbg_func("enter %p\n", ctx); + if (gop_len > 1) { + bits_alloc = ctx->gop_total_bits * max_i_prop / (max_i_prop + 16 * (gop_len - 1)); + } else { + bits_alloc = ctx->gop_total_bits * max_i_prop / max_i_prop; + } + + if (ctx->pre_real_bits > bits_alloc || ctx->next_i_ratio) { + RK_S32 ratio = ((ctx->pre_real_bits - bits_alloc) << 8) / bits_alloc; + + ratio = mpp_clip(ratio, -256, 256); + ratio = ctx->next_i_ratio + ratio; + if (ratio >= 0) { + if (ratio > max_i_delta_qp[pre_qp]) + ratio = max_i_delta_qp[pre_qp]; + } else { + ratio = 0; + } + ctx->next_i_ratio = ratio; + rc_dbg_rc("ctx->next_i_ratio %d", ctx->next_i_ratio); + } + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; + +} + +MPP_RET calc_debreath_qp(RcModelV2Ctx *ctx) +{ + rc_dbg_func("enter %p\n", ctx); + RcDebreathCfg *debreath_cfg = &ctx->usr_cfg.debreath_cfg; + RK_S32 qp_start_sum = 0; + RK_S32 new_start_qp = 0; + RK_U8 idx2 = MPP_MIN(ctx->pre_iblk4_prop >> 5, (RK_S32)sizeof(intra_qp_map) - 1); + + static RK_S8 strength_map[36] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, + 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, + 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12 + }; + + qp_start_sum = MPP_MIN(ctx->gop_qp_sum / ctx->gop_frm_cnt, (RK_S32)sizeof(strength_map) - 1); + + rc_dbg_qp("i start_qp %d, qp_start_sum = %d, intra_lv4_prop %d", + ctx->start_qp, qp_start_sum, ctx->pre_iblk4_prop); + + RK_S32 dealt_qp = strength_map[debreath_cfg->strength] - intra_qp_map[idx2]; + if (qp_start_sum > dealt_qp) + new_start_qp = qp_start_sum - dealt_qp; + else + new_start_qp = qp_start_sum; + + ctx->start_qp = mpp_clip(new_start_qp, ctx->usr_cfg.min_i_quality, ctx->usr_cfg.max_i_quality); + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET calc_cbr_ratio(void *ctx, EncRcTaskInfo *cfg) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + RK_S32 target_bps = p->target_bps; + RK_S32 ins_bps = p->ins_bps; + RK_S32 pre_target_bits = p->pre_target_bits; + RK_S32 pre_real_bits = p->pre_real_bits; + RK_S32 pre_ins_bps = p->last_inst_bps; + RK_S32 idx1, idx2; + RK_S32 bit_diff_ratio, ins_ratio, bps_ratio, wl_ratio; + RK_S32 fluc_l = 3; + + rc_dbg_func("enter %p\n", p); + + rc_dbg_bps("%10s|%10s|%10s|%10s|%10s|%8s", "r_bits", "t_bits", "ins_bps", "p_ins_bps", "target_bps", "watl"); + rc_dbg_bps("%10d %10d %10d %10d %10d %8d", pre_real_bits, pre_target_bits, ins_bps, pre_ins_bps, target_bps, p->stat_watl >> 10); + + bits_model_alloc(p, cfg, p->gop_total_bits); + + mpp_assert(target_bps > 0); + + p->pre_real_bits_count = p->pre_real_bits_count + pre_real_bits; + p->pre_target_bits_fix_count = p->pre_target_bits_fix_count + p->pre_target_bits_fix; + if (p->pre_real_bits_count > MAX_BIT_COUNT_VALUE || p->pre_target_bits_fix_count > MAX_BIT_COUNT_VALUE) { + p->pre_real_bits_count = 0; + p->pre_target_bits_fix_count = 0; + } + + if (pre_target_bits > pre_real_bits) + bit_diff_ratio = 52 * (pre_real_bits - pre_target_bits) / pre_target_bits; + else + bit_diff_ratio = 64 * (pre_real_bits - pre_target_bits) / pre_target_bits; + + idx1 = (ins_bps << 5) / target_bps; + idx2 = (pre_ins_bps << 5) / target_bps; + + idx1 = mpp_clip(idx1, 0, 63); + idx2 = mpp_clip(idx2, 0, 63); + ins_ratio = tab_lnx[idx1] - tab_lnx[idx2]; // %3 + + /*ins_bps is increase and pre_ins > target_bps*15/16 will raise up ins_ratio to decrease bit + *ins_bps is decresase and pre_ins < target_bps*17/16 will decrease ins_ratio to increase bit + */ + + if (ins_bps > pre_ins_bps && target_bps - pre_ins_bps < (target_bps >> 4)) { // %6 + ins_ratio = 6 * ins_ratio; + } else if ( ins_bps < pre_ins_bps && pre_ins_bps - target_bps < (target_bps >> 4)) { + ins_ratio = 4 * ins_ratio; + } else { + ins_ratio = 0; + } + + bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256); + + ins_ratio = mpp_clip(ins_ratio, -128, 256); + + bps_ratio = (ins_bps - target_bps) * fluc_l / (target_bps >> 4); + wl_ratio = 4 * (p->stat_watl - p->watl_base) * fluc_l / p->watl_base; + bps_ratio = mpp_clip(bps_ratio, -32, 32); + wl_ratio = mpp_clip(wl_ratio, -16, 32); + p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio + wl_ratio; + + rc_dbg_qp("%10s|%10s|%10s|%10s|%10s|%10s", "diff_ratio", "ins_ratio", "bps_ratio", + "wl_ratio", "next_ratio", "cur_qp_s"); + rc_dbg_qp("%10d %10d %10d %10d %10d|%10d", bit_diff_ratio, ins_ratio - bit_diff_ratio, + bps_ratio, wl_ratio, p->next_ratio, p->cur_scale_qp); + + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +MPP_RET reenc_calc_super_frm_ratio(void *ctx, EncRcTaskInfo *cfg) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + + rc_dbg_func("enter %p\n", p); + p->next_ratio = 160 * (4 * (cfg->bit_real - p->cur_super_thd) / cfg->bit_target); + p->next_ratio = mpp_clip(p->next_ratio, 128, 640); + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +MPP_RET reenc_calc_cbr_ratio(void *ctx, EncRcTaskInfo *cfg) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + RcCfg *usr_cfg = &p->usr_cfg; + RK_S32 stat_time = usr_cfg->stats_time; + RK_S32 pre_ins_bps = mpp_data_sum_v2(p->stat_bits) / stat_time; + RK_S32 ins_bps = (pre_ins_bps * stat_time - mpp_data_get_pre_val_v2(p->stat_bits, -1) + cfg->bit_real) / stat_time; + RK_S32 real_bit = cfg->bit_real; + RK_S32 target_bit = cfg->bit_target; + RK_S32 target_bps = p->target_bps; + RK_S32 water_level = 0; + RK_S32 idx1, idx2; + RK_S32 bit_diff_ratio, ins_ratio, bps_ratio, wl_ratio; + RK_S32 mb_w = MPP_ALIGN(usr_cfg->width, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(usr_cfg->height, 16) / 16; + + rc_dbg_func("enter %p\n", p); + + if (p->cur_super_thd <= cfg->bit_real && + usr_cfg->super_cfg.rc_priority == MPP_ENC_RC_BY_FRM_SIZE_FIRST) { + return reenc_calc_super_frm_ratio(ctx, cfg); + } + + if (real_bit + p->stat_watl > p->watl_thrd) + water_level = p->watl_thrd - p->bit_per_frame; + else + water_level = real_bit + p->stat_watl - p->bit_per_frame; + + if (water_level < 0) { + water_level = 0; + } + + if (target_bit > real_bit) + bit_diff_ratio = 32 * (real_bit - target_bit) / real_bit; + else + bit_diff_ratio = 32 * (real_bit - target_bit) / target_bit; + + idx1 = ins_bps / (target_bps >> 5); + idx2 = pre_ins_bps / (target_bps >> 5); + + idx1 = mpp_clip(idx1, 0, 63); + idx2 = mpp_clip(idx2, 0, 63); + ins_ratio = tab_lnx[idx1] - tab_lnx[idx2]; + + bps_ratio = 96 * (ins_bps - target_bps) / target_bps; + wl_ratio = 32 * (water_level - p->watl_base) / p->watl_base; + if (pre_ins_bps < ins_bps && target_bps != pre_ins_bps) { + ins_ratio = 6 * ins_ratio; + ins_ratio = mpp_clip(ins_ratio, -192, 256); + } else { + if (cfg->frame_type == INTRA_FRAME) { + ins_ratio = 3 * ins_ratio; + ins_ratio = mpp_clip(ins_ratio, -192, 256); + } else { + ins_ratio = 0; + } + } + + bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256); + bps_ratio = mpp_clip(bps_ratio, -32, 32); + wl_ratio = mpp_clip(wl_ratio, -32, 32); + p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio + wl_ratio; + if (cfg->frame_type == INTRA_FRAME && (cfg->madi > 0)) { + RK_U32 tar_bpp = target_bit / (mb_w * mb_h); + float lnb_t = log(tar_bpp); + float c = 6.7204, a = -0.1435, b = 0.0438; + float start_qp = (p->cur_scale_qp >> 6); + int qp_c = ((lnb_t - cfg->madi * b - c) / a + 14); + if (qp_c > start_qp) + p->next_ratio = (qp_c << 6) - p->cur_scale_qp; + } + rc_dbg_rc("cbr target_bit %d real_bit %d reenc next ratio %d", target_bit, real_bit, p->next_ratio); + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +void rc_hier_calc_dealt_qp(RcModelV2Ctx *p, EncRcTaskInfo *info) +{ + RcHierQPCfg *hier_qp_cfg = &p->usr_cfg.hier_qp_cfg; + + if (!hier_qp_cfg->hier_qp_en) + return; + + if (info->frame_type == INTRA_FRAME || info->frame_type == INTER_VI_FRAME) { + p->hier_frm_cnt[3] = 0; + p->hier_frm_cnt[2] = 0; + p->hier_frm_cnt[1] = 0; + p->hier_frm_cnt[0] = 0; + p->qp_layer_id = 0; + } else { + if (p->hier_frm_cnt[3] < hier_qp_cfg->hier_frame_num[3]) { + p->hier_frm_cnt[3]++; + p->qp_layer_id = 4; + } else if (p->hier_frm_cnt[2] < hier_qp_cfg->hier_frame_num[2]) { + p->hier_frm_cnt[2]++; + p->hier_frm_cnt[3] = 0; + p->qp_layer_id = 3; + } else if (p->hier_frm_cnt[1] < hier_qp_cfg->hier_frame_num[1]) { + p->hier_frm_cnt[1]++; + p->hier_frm_cnt[3] = 0; + p->hier_frm_cnt[2] = 0; + p->qp_layer_id = 2; + } else if (p->hier_frm_cnt[0] < hier_qp_cfg->hier_frame_num[0]) { + p->hier_frm_cnt[0]++; + p->hier_frm_cnt[3] = 0; + p->hier_frm_cnt[2] = 0; + p->hier_frm_cnt[1] = 0; + p->qp_layer_id = 1; + } else { + p->hier_frm_cnt[3] = 0; + p->hier_frm_cnt[2] = 0; + p->hier_frm_cnt[1] = 0; + p->hier_frm_cnt[0] = 0; + p->qp_layer_id = 0; + } + } + + return; +} + +MPP_RET calc_vbr_ratio(void *ctx, EncRcTaskInfo *cfg) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + RcCfg *usr_cfg = &p->usr_cfg; + RK_S32 bps_change = p->target_bps; + RK_S32 max_bps_target = usr_cfg->bps_max; + RK_S32 ins_bps = p->ins_bps; + RK_S32 pre_target_bits = p->pre_target_bits; + RK_S32 pre_real_bits = p->pre_real_bits; + RK_S32 pre_ins_bps = p->last_inst_bps; + + RK_S32 idx1, idx2; + RK_S32 bit_diff_ratio, ins_ratio, bps_ratio; + + rc_dbg_func("enter %p\n", p); + + bits_model_alloc(p, cfg, p->gop_total_bits); + if (pre_target_bits > pre_real_bits) + bit_diff_ratio = 32 * (pre_real_bits - pre_target_bits) / pre_target_bits; + else + bit_diff_ratio = 64 * (pre_real_bits - pre_target_bits) / pre_target_bits; + + idx1 = ins_bps / (max_bps_target >> 5); + idx2 = pre_ins_bps / (max_bps_target >> 5); + + idx1 = mpp_clip(idx1, 0, 63); + idx2 = mpp_clip(idx2, 0, 63); + ins_ratio = tab_lnx[idx1] - tab_lnx[idx2]; + + rc_dbg_bps("%10s|%10s|%10s|%10s|%10s|%10s", "r_bits", "t_bits", "ins_bps", "p_ins_bps", + "bps_ch", "max_bps"); + rc_dbg_bps("%10d %10d %10d %10d %10d %10d", pre_real_bits, pre_target_bits, ins_bps, + pre_ins_bps, bps_change, max_bps_target); + + + if (ins_bps > bps_change && ins_bps > pre_ins_bps) { + ins_ratio = 6 * ins_ratio; + } else if (ins_bps <= pre_ins_bps && bps_change > pre_ins_bps) { + ins_ratio = 3 * ins_ratio; + } else { + ins_ratio = 0; + } + + bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256); + ins_ratio = mpp_clip(ins_ratio, -128, 256); + bps_ratio = 3 * (ins_bps - bps_change) / (max_bps_target >> 4); + bps_ratio = mpp_clip(bps_ratio, -16, 32); + if (p->i_scale > 640) { + bit_diff_ratio = mpp_clip(bit_diff_ratio, -16, 32); + ins_ratio = mpp_clip(ins_ratio, -16, 32); + } + + p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio; + + rc_dbg_qp("%10s|%10s|%10s|%10s|%10s", "diff_ratio", "ins_ratio", "bps_ratio", "next_ratio", "cur_qp_s"); + rc_dbg_qp("%10d %10d %10d %10d|%10d", bit_diff_ratio, ins_ratio, bps_ratio, p->next_ratio, p->cur_scale_qp); + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +MPP_RET reenc_calc_vbr_ratio(void *ctx, EncRcTaskInfo *cfg) +{ + + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + RcCfg *usr_cfg = &p->usr_cfg; + RK_S32 stat_time = usr_cfg->stats_time; + RK_S32 pre_ins_bps = mpp_data_sum_v2(p->stat_bits) / stat_time; + RK_S32 ins_bps = (pre_ins_bps * stat_time - mpp_data_get_pre_val_v2(p->stat_bits, -1) + cfg->bit_real) / stat_time; + RK_S32 bps_change = p->target_bps; + RK_S32 max_bps_target = usr_cfg->bps_max; + + RK_S32 real_bit = cfg->bit_real; + RK_S32 target_bit = cfg->bit_target; + RK_S32 idx1, idx2; + RK_S32 bit_diff_ratio, ins_ratio, bps_ratio; + + rc_dbg_func("enter %p\n", p); + + if (p->cur_super_thd <= cfg->bit_real && + usr_cfg->super_cfg.rc_priority == MPP_ENC_RC_BY_FRM_SIZE_FIRST) { + return reenc_calc_super_frm_ratio(ctx, cfg); + } + + if (target_bit <= real_bit) + bit_diff_ratio = 32 * (real_bit - target_bit) / target_bit; + else + bit_diff_ratio = 32 * (real_bit - target_bit) / real_bit; + + idx1 = ins_bps / (max_bps_target >> 5); + idx2 = pre_ins_bps / (max_bps_target >> 5); + idx1 = mpp_clip(idx1, 0, 63); + idx2 = mpp_clip(idx2, 0, 63); + if (pre_ins_bps < ins_bps && bps_change < ins_bps) { + ins_ratio = 6 * (tab_lnx[idx1] - tab_lnx[idx2]); + ins_ratio = mpp_clip(ins_ratio, -192, 256); + } else { + ins_ratio = 0; + } + + bps_ratio = 96 * (ins_bps - bps_change) / bps_change; + bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256); + bps_ratio = mpp_clip(bps_ratio, -32, 32); + + p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio; + rc_dbg_rc("vbr reenc next ratio %d", p->next_ratio); + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +RK_S32 moving_ratio_calc(RcModelV2Ctx *ctx) +{ + RK_S32 motion_sensitivity = ctx->motion_sensitivity; + RK_S32 scale = 0, i; + RK_S32 total_bit = 0, pbit_sum = 0; + RK_S32 madi_sum = 0, madp_sum = 0; + RK_S32 percent = 0; + + for (i = 0; i < 2; i++) { + RK_S32 pre_I_bit = mpp_data_get_pre_val_v2(ctx->pre_i_bit, i); + RK_S32 pre_mean_qp = mpp_data_get_pre_val_v2(ctx->pre_i_mean_qp, i); + if (pre_mean_qp == -1) { + scale = 32; + } else { + RK_S32 index = pre_mean_qp + 8 - ctx->pre_mean_qp; + if (index >= 0) { + index = mpp_clip(index, 0 , 15); + scale = mean_qp2scale[index]; + } else { + scale = 14; + } + } + total_bit += (scale * pre_I_bit >> 5); + rc_dbg_rc("pre_mean_qp = %d, ctx->pre_mean_qp %d", pre_mean_qp, ctx->pre_mean_qp); + rc_dbg_rc("scale = %d, pre_I_bit %d", scale, pre_I_bit); + } + + pbit_sum = mpp_data_sum_v2(ctx->pre_p_bit); + madi_sum = mpp_data_sum_v2(ctx->madi); + madp_sum = mpp_data_sum_v2(ctx->madp); + rc_dbg_rc("pbit_sum %d,madi_sum = %d, madp_sum = %d", pbit_sum, madi_sum, madp_sum); + if ( pbit_sum == 0 || total_bit == 0) { + percent = 255; + } else { + RK_S32 index = (total_bit << 6) / pbit_sum; + index = mpp_clip(index >> 4, 1, 99); + percent = (bit2percent[index] << 8) / 100; + } + rc_dbg_rc("means qp percent %d min_still_percent %d", percent, ctx->min_still_percent); + RK_S32 percent_a = (ctx->min_still_percent - 30) << 8; + RK_S32 percent_b = 100 - ctx->min_still_percent; + + percent = (percent_a + percent * percent_b) / 70; + rc_dbg_rc("percent_a = %d percent_b %d", percent_a, percent_b); + RK_S32 mv_percnt = (ctx->prev_md_prop * 100) >> 8; + RK_S32 mv_ratio = (percent_a + 7680 + mv_percnt * percent_b) / 100; + rc_dbg_rc("mv_ratio = %d", mv_ratio); + RK_S32 mad_ratio = 256; + if (madi_sum) { + mad_ratio = 20 * madp_sum / madi_sum; + mad_ratio = mpp_clip(mad_ratio, 5, 100); + rc_dbg_rc("mad_ratio = %d", mad_ratio); + mad_ratio = (mad_ratio << 8) / 100; + } + mad_ratio = (percent_a + 7680 + percent_b * mad_ratio) / 100; + + RK_S32 moving_ratio = (percent + 1 + (mv_ratio * motion_sensitivity + (100 - motion_sensitivity) * mad_ratio) / 100) >> 1; + rc_dbg_rc("moving_ratio = %d, motion_sensitivity = %d", moving_ratio, motion_sensitivity); + rc_dbg_rc("percent %d mad_ratio %d hr_ratio %d, moving_ratio %d", percent, mad_ratio, mv_ratio, moving_ratio); + return moving_ratio; +} + +MPP_RET calc_avbr_ratio(void *ctx, EncRcTaskInfo *cfg) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + RcCfg *usr_cfg = &p->usr_cfg; + RK_S32 bps_change = p->target_bps; + RK_S32 max_bps_target = usr_cfg->bps_max; + RK_S32 ins_bps = p->ins_bps; + RK_S32 pre_target_bits = p->pre_target_bits; + RK_S32 pre_real_bits = p->pre_real_bits; + RK_S32 pre_ins_bps = p->last_inst_bps; + RK_S32 idx1, idx2; + RK_S32 bit_diff_ratio, ins_ratio, agop_dratio, rgop_dratio; + RK_S32 moving_ratio = 0, moving_percent; + RK_S32 gop_bits = 0, gop_kbits = 0; + RK_S32 i_ratio, max_bps; + RK_S32 qratio, final_qratio; + + rc_dbg_func("enter %p\n", p); + + moving_ratio = moving_ratio_calc(p); + if (p->moving_ratio - 2 >= moving_ratio) + moving_ratio = p->moving_ratio - 2; + + if (p->moving_ratio > moving_ratio && (p->max_still_qp << 6) <= p->scale_qp) { + p->moving_ratio = mpp_clip(p->moving_ratio + 1, 1, 255); + } else { + p->moving_ratio = moving_ratio; + } + rc_dbg_rc("final moving_ratio = %d", moving_ratio); + + if (moving_ratio <= 0) + moving_ratio = 1; + + gop_bits = moving_ratio * p->gop_total_bits >> 8; + gop_kbits = gop_bits >> 10; + if (gop_kbits < 1) + gop_kbits = 1; + + bits_model_alloc(p, cfg, gop_bits); + bps_change = moving_ratio * bps_change >> 8; + if (moving_ratio < 0) { + moving_ratio += 255; + } + moving_percent = 100 * moving_ratio >> 8; + + rc_dbg_bps("%10s|%10s|%10s|%10s|%10s", "m_ratio", "r_bits", "t_bits", "ins_bps", "p_ins_bps"); + rc_dbg_bps("%10d %10d %10d %10d %10d", p->moving_ratio, pre_real_bits, pre_target_bits, ins_bps, pre_ins_bps); + + if (pre_target_bits > pre_real_bits) + bit_diff_ratio = 32 * (pre_real_bits - pre_target_bits) / pre_target_bits; + else + bit_diff_ratio = 64 * (pre_real_bits - pre_target_bits) / pre_target_bits * moving_percent; + + i_ratio = mpp_clip(p->pre_i_scale >> 4, 10, 200); + idx1 = ins_bps / (max_bps_target >> 5); + idx2 = pre_ins_bps / (max_bps_target >> 5); + idx1 = mpp_clip(idx1, 0, 63); + idx2 = mpp_clip(idx2, 0, 63); + ins_ratio = tab_lnx[idx2] - tab_lnx[idx1]; + max_bps = bps_change; + + if (max_bps < pre_ins_bps) { + max_bps = pre_ins_bps; + } + + if (ins_bps > max_bps) { + ins_ratio = 6 * ins_ratio; + } else if (ins_bps < pre_ins_bps && bps_change > pre_ins_bps) { + ins_ratio = 3 * ins_ratio; + } else { + ins_ratio = 0; + } + + ins_ratio = mpp_clip(ins_ratio >> 2, -128, 256); + bit_diff_ratio = mpp_clip(10 * bit_diff_ratio / i_ratio, -128, 256); + rgop_dratio = mpp_clip(24 * ((p->real_gbits - gop_bits) >> 10) / gop_kbits, -1, 1); + agop_dratio = mpp_clip(48 * ((p->avg_gbits - gop_bits) >> 10) / gop_kbits , -1, 1); + if (p->pre_i_scale > 640) { + bit_diff_ratio = mpp_clip(bit_diff_ratio, -16, 32); + ins_ratio = mpp_clip(ins_ratio, -16, 32); + } + qratio = 0; + final_qratio = ins_ratio + bit_diff_ratio + agop_dratio + rgop_dratio; + if (max_bps_target >= ins_bps) { + if (final_qratio > 0) { + if (p->scale_qp >= (p->max_still_qp << 6)) { + final_qratio = ins_ratio + agop_dratio + rgop_dratio; + qratio = -6; + } + } + } + p->next_ratio = qratio + final_qratio; + + rc_dbg_qp("%10s|%10s|%10s|%10s|%10s|%10s|%10s", "diff_ratio", "ins_ratio", "rg_ratio", + "ag_ratio", "qratio", "next_ratio", "cur_qp_s"); + rc_dbg_qp("%10d %10d %10d %10d %10d %10d %10d", bit_diff_ratio, ins_ratio, rgop_dratio, + agop_dratio, qratio, p->next_ratio, p->cur_scale_qp); + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +MPP_RET bits_model_init(RcModelV2Ctx *ctx) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 gop_len = ctx->usr_cfg.igop; + RcFpsCfg *fps = &ctx->usr_cfg.fps; + RK_S64 gop_bits = 0; + RK_U32 target_bps = 0; + + rc_dbg_func("enter %p\n", ctx); + + usr_cfg->min_i_bit_prop = mpp_clip(usr_cfg->min_i_bit_prop, 10, 100); + usr_cfg->max_i_bit_prop = mpp_clip(usr_cfg->max_i_bit_prop, + usr_cfg->min_i_bit_prop, 100); + usr_cfg->init_ip_ratio = mpp_clip(usr_cfg->init_ip_ratio, 160, 640); + + rc_dbg_rc("min_i_bit_prop %d max_i_bit_prop %d, init_ip_ratio %d", + usr_cfg->min_i_bit_prop, usr_cfg->max_i_bit_prop, usr_cfg->init_ip_ratio); + + if (!gop_len) { + rc_dbg_rc("infinte gop, set default for rc bit calc\n"); + usr_cfg->igop = gop_len = 500; + } else if (gop_len == 1) { + rc_dbg_rc("all intra gop \n"); + usr_cfg->init_ip_ratio = 16; + + /* disable debreath on all intra case */ + if (usr_cfg->debreath_cfg.enable) + usr_cfg->debreath_cfg.enable = 0; + + usr_cfg->igop = gop_len = 500; + } else { + usr_cfg->igop = gop_len = mpp_clip(usr_cfg->igop, usr_cfg->igop, 500); + } + ctx->max_still_qp = 35; + ctx->motion_sensitivity = 90; + + ctx->first_frm_flg = 1; + ctx->gop_frm_cnt = 0; + ctx->gop_qp_sum = 0; + + if (!usr_cfg->fps_chg_prop) { + usr_cfg->fps_chg_prop = 25; + } + + target_bps = ctx->usr_cfg.bps_max; + ctx->re_calc_ratio = reenc_calc_vbr_ratio; + switch (ctx->usr_cfg.mode) { + case RC_CBR: { + ctx->calc_ratio = calc_cbr_ratio; + ctx->re_calc_ratio = reenc_calc_cbr_ratio; + target_bps = ctx->usr_cfg.bps_target; + } break; + case RC_VBR: { + ctx->calc_ratio = calc_vbr_ratio; + } break; + case RC_FIXQP: { + return MPP_OK; + } + case RC_AVBR: { + ctx->calc_ratio = calc_avbr_ratio; + if (usr_cfg->bps_min && usr_cfg->bps_max) { + ctx->min_still_percent = (RK_S64)usr_cfg->bps_min * 100 / usr_cfg->bps_max; + } else { + ctx->min_still_percent = 25; + } + rc_dbg_rc("min_still_percent %d", ctx->min_still_percent); + } break; + case RC_SMT: { + mpp_log("rc mode is smart"); + } break; + case RC_SE: { + mpp_log("rc mode is super-encode"); + } break; + default: + mpp_log("rc mode set error"); + break; + } + + ctx->target_bps = ctx->usr_cfg.bps_target; + + if (gop_len >= 1) + gop_bits = (RK_S64)gop_len * target_bps * fps->fps_out_denom; + else + gop_bits = (RK_S64)fps->fps_out_num * target_bps * fps->fps_out_denom; + + ctx->gop_total_bits = gop_bits / fps->fps_out_num; + ctx->bit_per_frame = target_bps * fps->fps_out_denom / fps->fps_out_num; + ctx->watl_thrd = 3 * target_bps; + ctx->stat_watl = ctx->watl_thrd >> 3; + ctx->watl_base = ctx->stat_watl; + ctx->last_fps = fps->fps_out_num / fps->fps_out_denom; + + rc_dbg_rc("gop %d total bit %lld per_frame %d statistics time %d second\n", + ctx->usr_cfg.igop, ctx->gop_total_bits, ctx->bit_per_frame, + ctx->usr_cfg.stats_time); + + if (bits_model_param_init(ctx)) { + return MPP_NOK; + } + ctx->time_base = mpp_time(); + bits_frm_init(ctx); + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +static MPP_RET update_mode_param(RcModelV2Ctx *ctx, RK_U32 fps) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 gop_len = ctx->usr_cfg.igop; + RK_S64 gop_bits = 0; + RK_U32 target_bps; + RK_U32 stat_len = fps * usr_cfg->stats_time; + + target_bps = ctx->usr_cfg.bps_max; + if (ctx->usr_cfg.mode == RC_CBR) { + target_bps = ctx->usr_cfg.bps_target; + } + + if (gop_len >= 1) + gop_bits = (RK_S64)gop_len * target_bps; + else + gop_bits = (RK_S64)target_bps; + + ctx->gop_total_bits = gop_bits / fps; + + ctx->bit_per_frame = target_bps / fps; + + if (ctx->stat_bits != NULL) { + mpp_data_deinit_v2(ctx->stat_bits); + ctx->stat_bits = NULL; + } + mpp_data_init_v2(&ctx->stat_bits, stat_len , ctx->bit_per_frame); + if (ctx->stat_bits == NULL) { + mpp_err("stat_bits init fail stat_len %d", stat_len); + return MPP_ERR_MALLOC; + } + return MPP_OK; +} + +static MPP_RET fps_chg_update_mode(RcModelV2Ctx *ctx) +{ + ctx->time_end = mpp_time(); + ctx->frm_cnt++; + + if (ctx->time_base && ctx->time_end && + ((ctx->time_end - ctx->time_base) >= (RK_S64)(250 * 1000))) { + + RK_S32 time_diff = ((RK_S32)(ctx->time_end - ctx->time_base) / 1000); + RK_U32 fps = ctx->frm_cnt * 1000 / time_diff; + + if (ctx->last_fps > 0 && fps && + abs(ctx->last_fps - (RK_S32)fps) * 100 / ctx->last_fps > (RK_S32)ctx->usr_cfg.fps_chg_prop) { + update_mode_param(ctx, fps); + mpp_log("fps chg from %d -> %d", ctx->last_fps, fps); + ctx->last_fps = fps; + } + ctx->time_base = ctx->time_end; + ctx->frm_cnt = 0; + } + + return MPP_OK; +} + +MPP_RET bits_mode_reset(RcModelV2Ctx *ctx) +{ + rc_dbg_func("enter %p\n", ctx); + (void) ctx; + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET check_super_frame(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) +{ + MPP_RET ret = MPP_OK; + RK_S32 frame_type = cfg->frame_type; + RK_U32 bits_thr = 0; + RcCfg *usr_cfg = &ctx->usr_cfg; + + rc_dbg_func("enter %p\n", ctx); + if (usr_cfg->super_cfg.super_mode) { + bits_thr = usr_cfg->super_cfg.super_p_thd; + if (frame_type == INTRA_FRAME) { + bits_thr = usr_cfg->super_cfg.super_i_thd; + } + + if ((RK_U32)cfg->bit_real >= bits_thr) { + if (usr_cfg->super_cfg.super_mode == MPP_ENC_RC_SUPER_FRM_DROP) { + rc_dbg_rc("super frame drop current frame"); + usr_cfg->drop_mode = MPP_ENC_RC_DROP_FRM_NORMAL; + usr_cfg->drop_gap = 0; + } + ret = MPP_NOK; + } + } + rc_dbg_func("leave %p\n", ctx); + return ret; +} + +MPP_RET check_re_enc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 frame_type = cfg->frame_type; + RK_S32 bit_thr = 0; + RK_S32 stat_time = usr_cfg->stats_time; + RK_S32 last_ins_bps = mpp_data_sum_v2(ctx->stat_bits) / stat_time; + RK_S32 ins_bps = (last_ins_bps * stat_time - mpp_data_get_pre_val_v2(ctx->stat_bits, -1) + + cfg->bit_real) / stat_time; + RK_S32 target_bps; + RK_S32 ret = MPP_OK; + + rc_dbg_func("enter %p\n", ctx); + rc_dbg_rc("reenc check target_bps %d last_ins_bps %d ins_bps %d", + usr_cfg->bps_target, last_ins_bps, ins_bps); + + if (ctx->reenc_cnt >= usr_cfg->max_reencode_times) + return MPP_OK; + + if (check_super_frame(ctx, cfg)) + return MPP_NOK; + + if (usr_cfg->debreath_cfg.enable && !ctx->first_frm_flg) + return MPP_OK; + + rc_dbg_drop("drop mode %d frame_type %d\n", usr_cfg->drop_mode, frame_type); + if (usr_cfg->drop_mode && frame_type == INTER_P_FRAME) { + bit_thr = (RK_S32)(usr_cfg->bps_max * (100 + usr_cfg->drop_thd) / (float)100); + rc_dbg_drop("drop mode %d check max_bps %d bit_thr %d ins_bps %d", + usr_cfg->drop_mode, usr_cfg->bps_target, bit_thr, ins_bps); + return (ins_bps > bit_thr) ? MPP_NOK : MPP_OK; + } + + switch (frame_type) { + case INTRA_FRAME: + bit_thr = 3 * cfg->bit_target / 2; + break; + case INTER_P_FRAME: + bit_thr = 3 * cfg->bit_target; + break; + default: + break; + } + + if (cfg->bit_real > bit_thr) { + if (usr_cfg->mode == RC_CBR) { + target_bps = usr_cfg->bps_target; + if (target_bps / 20 < ins_bps - last_ins_bps && + (target_bps + target_bps / 10 < ins_bps + || target_bps - target_bps / 10 > ins_bps)) { + ret = MPP_NOK; + } + } else { + target_bps = usr_cfg->bps_max; + if ((target_bps - (target_bps >> 3) < ins_bps) && + (target_bps / 20 < ins_bps - last_ins_bps)) { + ret = MPP_NOK; + } + } + } + + rc_dbg_func("leave %p ret %d\n", ctx, ret); + return ret; +} + + +MPP_RET rc_model_v2_init(void *ctx, RcCfg *cfg) +{ + RcModelV2Ctx *p = (RcModelV2Ctx*)ctx; + + rc_dbg_func("enter %p\n", ctx); + + memcpy(&p->usr_cfg, cfg, sizeof(RcCfg)); + rc_dbg_rc("init rc param: fqp %d:%d:%d:%d\n", cfg->fqp_min_i, cfg->fqp_max_i, + cfg->fqp_min_p, cfg->fqp_max_p); + + bits_model_init(p); + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET rc_model_v2_deinit(void *ctx) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + + rc_dbg_func("enter %p\n", ctx); + bits_model_param_deinit(p); + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task) +{ + RcModelV2Ctx *p = (RcModelV2Ctx*)ctx; + EncFrmStatus *frm = &task->frm; + EncRcTaskInfo *info = &task->info; + RcCfg *usr_cfg = &p->usr_cfg; + + rc_dbg_func("enter %p\n", ctx); + + if (usr_cfg->mode == RC_FIXQP) { + if (usr_cfg->init_quality <= 0) { + mpp_log("invalid fix %d qp found set default qp 26\n", + usr_cfg->init_quality); + usr_cfg->init_quality = 26; + } + + if (usr_cfg->max_quality <= 0) + usr_cfg->max_quality = usr_cfg->init_quality; + if (usr_cfg->min_quality <= 0) + usr_cfg->min_quality = usr_cfg->init_quality; + if (usr_cfg->max_i_quality <= 0) + usr_cfg->max_i_quality = usr_cfg->max_quality; + if (usr_cfg->min_i_quality <= 0) + usr_cfg->min_i_quality = usr_cfg->min_quality; + + if (frm->is_intra) { + info->quality_max = usr_cfg->max_i_quality; + info->quality_min = usr_cfg->min_i_quality; + info->quality_target = usr_cfg->init_quality; + } else { + info->quality_max = usr_cfg->max_quality; + info->quality_min = usr_cfg->min_quality; + info->quality_target = usr_cfg->init_quality; + } + + rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra); + rc_dbg_rc("bitrate [%d : %d : %d]\n", info->bit_min, info->bit_target, info->bit_max); + rc_dbg_rc("quality [%d : %d : %d]\n", info->quality_min, info->quality_target, info->quality_max); + + return MPP_OK; + } + + if (usr_cfg->fps.fps_out_flex) { + fps_chg_update_mode(ctx); + } + + info->frame_type = (frm->is_intra != 0) ? (INTRA_FRAME) : (INTER_P_FRAME); + + if (frm->ref_mode == REF_TO_PREV_INTRA) + info->frame_type = INTER_VI_FRAME; + + if (frm->is_i_refresh) + info->frame_type = INTRA_RFH_FRAME; + + p->next_ratio = 0; + if (p->last_frame_type == INTRA_FRAME) { + calc_next_i_ratio(p); + } + + if (!p->first_frm_flg) { + if (p->calc_ratio) + p->calc_ratio(p, info); + } else { + bits_model_alloc(p, info, p->gop_total_bits); + /* quality determination */ + info->quality_target = (usr_cfg->init_quality <= 0) ? -1 : usr_cfg->init_quality; + } + + if (frm->is_intra) { + info->quality_max = usr_cfg->max_i_quality; + info->quality_min = usr_cfg->min_i_quality; + } else { + info->quality_max = usr_cfg->max_quality; + info->quality_min = usr_cfg->min_quality; + } + + bits_model_preset(p, info); + + rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra); + rc_dbg_rc("bitrate [%d : %d : %d]\n", info->bit_min, info->bit_target, info->bit_max); + rc_dbg_rc("quality [%d : %d : %d]\n", info->quality_min, info->quality_target, info->quality_max); + + p->reenc_cnt = 0; + p->last_frame_type = info->frame_type; + + rc_dbg_func("leave %p\n", ctx); + + return MPP_OK; +} + +static RK_S32 cal_first_i_start_qp(RK_S32 target_bit, RK_U32 total_mb) +{ + static RK_U32 mb_num[9] = { + 0, 200, 700, 1200, + 2000, 4000, 8000, 16000, + 20000 + }; + + static RK_U32 tab_bit[9] = { + 3780, 3570, 3150, 2940, + 2730, 3780, 2100, 1680, + 2100 + }; + + static RK_U8 qscale2qp[96] = { + 15, 15, 15, 15, 15, 16, 18, 20, 21, 22, 23, 24, + 25, 25, 26, 27, 28, 28, 29, 29, 30, 30, 30, 31, + 31, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, + 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, + 38, 38, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, + 40, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, + 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, + 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, + }; + + RK_S32 cnt = 0; + RK_S32 index; + RK_S32 i; + + for (i = 0; i < 8; i++) { + if (mb_num[i] > total_mb) + break; + cnt++; + } + + index = (total_mb * tab_bit[cnt] - 350) / target_bit; // qscale + index = mpp_clip(index, 4, 95); + + return qscale2qp[index]; +} + +static RK_S32 derive_min_qp_from_complexity(RcModelV2Ctx *ctx, EncRcTaskInfo *info, RK_U32 is_intra) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RcMode rc_mode = usr_cfg->mode; + RK_S32 qp_min = info->quality_min; + RK_S32 fqp_min_i = usr_cfg->fqp_min_i; + RK_S32 fqp_min_p = usr_cfg->fqp_min_p; + RK_S32 cplx = mpp_data_sum_v2(ctx->complex_level); + RK_S32 md = mpp_data_sum_v2(ctx->motion_level); + RK_S32 md3 = mpp_data_get_pre_val_v2(ctx->motion_level, 0) + + mpp_data_get_pre_val_v2(ctx->motion_level, 1) + + mpp_data_get_pre_val_v2(ctx->motion_level, 2); + + if (RC_AVBR == rc_mode || RC_VBR == rc_mode || RC_CBR == rc_mode) { + if (md >= 700) { + qp_min = (is_intra != 0) ? fqp_min_i : fqp_min_p; + if (md >= 1400) + qp_min += md3 > 300 ? 3 : 2; + else + qp_min += md3 > 300 ? 2 : 1; + + if (cplx >= 15) + qp_min++; + } else if (RC_CBR != rc_mode) { + if (md > 100) { + if (cplx >= 16) + qp_min = ((is_intra != 0) ? fqp_min_i : fqp_min_p) + 1; + else if (cplx >= 10) + qp_min = ((is_intra != 0) ? fqp_min_i : fqp_min_p) + 0; + } else { + qp_min = ((is_intra != 0) ? fqp_min_i : fqp_min_p); + qp_min += (cplx >= 15) ? 3 : (cplx >= 10) ? 2 : (cplx >= 5) ? 1 : 0; + } + } + + qp_min = mpp_clip(qp_min, info->quality_min, info->quality_max); + + rc_dbg_rc("frame %d complex_level %d motion_level %d md3 %d qp_min %d\n", + ctx->frm_num, cplx, md, md3, qp_min); + } + + return qp_min; +} + +MPP_RET rc_model_v2_hal_start(void *ctx, EncRcTask *task) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + EncFrmStatus *frm = &task->frm; + EncRcTaskInfo *info = &task->info; + EncRcForceCfg *force = &task->force; + RcCfg *usr_cfg = &p->usr_cfg; + RK_S32 mb_w = MPP_ALIGN(usr_cfg->width, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(usr_cfg->height, 16) / 16; + RK_S32 bit_min = info->bit_min; + RK_S32 bit_max = info->bit_max; + RK_S32 bit_target = info->bit_target; + RK_S32 quality_min = info->quality_min; + RK_S32 quality_max = info->quality_max; + RK_S32 quality_target = info->quality_target; + + rc_dbg_func("enter p %p task %p\n", p, task); + rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra); + + if (force->force_flag & ENC_RC_FORCE_QP) { + RK_S32 qp = force->force_qp; + info->quality_target = qp; + info->quality_max = qp; + info->quality_min = qp; + return MPP_OK; + } + + if (usr_cfg->mode == RC_FIXQP) { + RK_S32 i_quality_delta = usr_cfg->i_quality_delta; + + if (frm->is_intra && i_quality_delta) + p->start_qp = quality_target - i_quality_delta; + else + p->start_qp = quality_target; + + info->quality_target = p->start_qp; + + return MPP_OK; + } + + /* setup quality parameters */ + if (p->first_frm_flg && frm->is_intra) { + RK_S32 i_quality_delta = usr_cfg->i_quality_delta; + p->pre_target_bits_fix_count = 0; + p->pre_real_bits_count = 0; + + if (info->quality_target < 0) { + if (info->bit_target) { + info->quality_target = cal_first_i_start_qp(info->bit_target, mb_w * mb_h); + } else { + mpp_log("init qp not set on fix qp mode, use default qp\n"); + info->quality_target = 26; + } + } + + if (p->reenc_cnt) { + p->cur_scale_qp += p->next_ratio; + p->start_qp = (p->cur_scale_qp >> 6) - i_quality_delta; + } else { + p->start_qp = info->quality_target; + p->cur_scale_qp = (info->quality_target + i_quality_delta) << 6; + } + + rc_dbg_rc("qp: start %2d cur_scale %d next_ratio %d reenc %d\n", + p->start_qp, p->cur_scale_qp, p->next_ratio, p->reenc_cnt); + + p->cur_scale_qp = mpp_clip(p->cur_scale_qp, (info->quality_min << 6), (info->quality_max << 6)); + } else { + RK_S32 qp_scale = p->cur_scale_qp + p->next_ratio; + RK_S32 start_qp = 0; + RK_S32 qpmin = derive_min_qp_from_complexity(p, info, frm->is_intra); + + if (frm->is_intra && !frm->is_i_refresh) { + RK_S32 i_quality_delta = usr_cfg->i_quality_delta; + RK_S32 qp_scale_t = qp_scale = + mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6)); + + qp_scale_t = (qp_scale + p->next_i_ratio) >> 6; + if (qp_scale_t >= 35 && p->pre_i_qp <= 33) + start_qp = (p->pre_i_qp * 307 + qp_scale_t * 717) >> 10; + else + start_qp = (p->pre_i_qp + qp_scale_t) >> 1; + + if (i_quality_delta) { + RK_U32 index = mpp_clip(mpp_data_mean_v2(p->madi) / 4, 0, 7); + RK_S32 max_ip_delta = max_ip_qp_dealt[index]; + + if (i_quality_delta > max_ip_delta) + i_quality_delta = max_ip_delta; + + rc_dbg_rc("qp prev %d:%d curr %d - %d (max %d) -> %d reenc %d\n", + p->pre_i_qp, qp_scale >> 6, start_qp, + usr_cfg->i_quality_delta, max_ip_delta, + start_qp - i_quality_delta, p->reenc_cnt); + + //if (!p->reenc_cnt) { + start_qp -= i_quality_delta; + //} + } + + start_qp = mpp_clip(start_qp, qpmin, usr_cfg->fqp_max_i); + start_qp = mpp_clip(start_qp, info->quality_min, info->quality_max); + p->start_qp = start_qp; + + if (!p->reenc_cnt) { + p->cur_scale_qp = qp_scale; + if (p->usr_cfg.debreath_cfg.enable) { + calc_debreath_qp(ctx); + } + } + + p->gop_frm_cnt = 0; + p->gop_qp_sum = 0; + } else { + qp_scale = mpp_clip(qp_scale, (qpmin << 6), (info->quality_max << 6)); + qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6)); + p->cur_scale_qp = qp_scale; + rc_dbg_rc("qp %d -> %d\n", p->start_qp, qp_scale >> 6); + p->start_qp = qp_scale >> 6; + if (frm->ref_mode == REF_TO_PREV_INTRA && usr_cfg->vi_quality_delta) { + rc_dbg_rc("qp %d -> %d (vi)\n", p->start_qp, p->start_qp - usr_cfg->vi_quality_delta); + p->start_qp -= usr_cfg->vi_quality_delta; + } + p->start_qp = mpp_clip(p->start_qp, qpmin, usr_cfg->fqp_max_p); + } + if (p->pre_target_bits_fix_count * 90 / 100 > p->pre_real_bits_count) { + p->start_qp = mpp_clip(p->start_qp, info->quality_min, 35); + } else if (p->pre_target_bits_fix_count * 100 / 100 > p->pre_real_bits_count) { + p->start_qp = mpp_clip(p->start_qp, info->quality_min, 37); + } else if (p->pre_target_bits_fix_count * 107 / 100 > p->pre_real_bits_count) { + p->start_qp = mpp_clip(p->start_qp, info->quality_min, 39); + } + p->start_qp = mpp_clip(p->start_qp, qpmin, 51); + } + + if (usr_cfg->hier_qp_cfg.hier_qp_en && !p->reenc_cnt) { + rc_hier_calc_dealt_qp(p, info); + if (p->qp_layer_id) { + RK_S32 hier_qp_delta = usr_cfg->hier_qp_cfg.hier_qp_delta[p->qp_layer_id - 1]; + + p->start_qp -= hier_qp_delta; + rc_dbg_qp("hier_qp: layer %d delta %d", p->qp_layer_id, hier_qp_delta); + } + } + + if (frm->is_intra) + p->start_qp = mpp_clip(p->start_qp, usr_cfg->fqp_min_i, usr_cfg->fqp_max_i); + else + p->start_qp = mpp_clip(p->start_qp, usr_cfg->fqp_min_p, usr_cfg->fqp_max_p); + info->quality_target = p->start_qp; + + rc_dbg_rc("bitrate [%d : %d : %d] -> [%d : %d : %d]\n", + bit_min, bit_target, bit_max, + info->bit_min, info->bit_target, info->bit_max); + rc_dbg_rc("quality [%d : %d : %d] -> [%d : %d : %d]\n", + quality_min, quality_target, quality_max, + info->quality_min, info->quality_target, info->quality_max); + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +MPP_RET rc_model_v2_hal_end(void *ctx, EncRcTask *task) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + EncFrmStatus *frm = &task->frm; + + rc_dbg_func("enter ctx %p task %p\n", ctx, task); + + if (frm->is_intra) + p->pre_i_qp = p->cur_scale_qp >> 6; + else + p->pre_p_qp = p->cur_scale_qp >> 6; + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET rc_model_v2_check_reenc(void *ctx, EncRcTask *task) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + EncRcTaskInfo *cfg = (EncRcTaskInfo *)&task->info; + EncFrmStatus *frm = &task->frm; + RcCfg *usr_cfg = &p->usr_cfg; + + rc_dbg_func("enter ctx %p cfg %p\n", ctx, cfg); + + frm->reencode = 0; + + if ((usr_cfg->mode == RC_FIXQP) || + (task->force.force_flag & ENC_RC_FORCE_QP) || + p->on_drop || p->on_pskip) + return MPP_OK; + + if (check_re_enc(p, cfg)) { + MppEncRcDropFrmMode drop_mode = usr_cfg->drop_mode; + + if (frm->is_intra) + drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED; + + if (usr_cfg->drop_gap && p->drop_cnt >= usr_cfg->drop_gap) + drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED; + + rc_dbg_drop("reenc drop_mode %d drop_cnt %d\n", drop_mode, p->drop_cnt); + + switch (drop_mode) { + case MPP_ENC_RC_DROP_FRM_NORMAL : { + frm->drop = 1; + frm->reencode = 1; + p->on_drop = 1; + p->drop_cnt++; + rc_dbg_drop("drop\n"); + } break; + case MPP_ENC_RC_DROP_FRM_PSKIP : { + frm->force_pskip = 1; + frm->reencode = 1; + p->on_pskip = 1; + p->drop_cnt++; + rc_dbg_drop("force_pskip\n"); + } break; + case MPP_ENC_RC_DROP_FRM_DISABLED : + default : { + if (p->re_calc_ratio) + p->re_calc_ratio(p, cfg); + + if (p->next_ratio != 0 && cfg->quality_target < cfg->quality_max) { + p->reenc_cnt++; + frm->reencode = 1; + } + p->drop_cnt = 0; + } break; + } + } + + return MPP_OK; +} + +MPP_RET rc_model_v2_end(void *ctx, EncRcTask *task) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + EncRcTaskInfo *cfg = (EncRcTaskInfo *)&task->info; + RcCfg *usr_cfg = &p->usr_cfg; + + rc_dbg_func("enter ctx %p cfg %p\n", ctx, cfg); + + rc_dbg_rc("bits_mode_update real_bit %d", cfg->bit_real); + + if (usr_cfg->mode == RC_FIXQP) + goto DONE; + + rc_dbg_rc("motion_level %u, complex_level %u\n", cfg->motion_level, cfg->complex_level); + mpp_data_update_v2(p->motion_level, cfg->motion_level); + mpp_data_update_v2(p->complex_level, cfg->complex_level); + cfg->rt_bits = p->ins_bps; + p->last_inst_bps = p->ins_bps; + p->first_frm_flg = 0; + + bits_model_update(p, cfg); + if (usr_cfg->mode == RC_AVBR) { + moving_judge_update(p, cfg); + bit_statics_update(p, cfg->bit_real); + } + + p->gop_frm_cnt++; + p->gop_qp_sum += p->start_qp; + + p->pre_mean_qp = cfg->quality_real; + p->pre_iblk4_prop = cfg->iblk4_prop; + p->scale_qp = p->cur_scale_qp; + p->prev_md_prop = 0; + p->pre_target_bits = cfg->bit_target; + p->pre_target_bits_fix = cfg->bit_target_fix; + p->pre_real_bits = cfg->bit_real; + + p->on_drop = 0; + p->on_pskip = 0; + +DONE: + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} diff --git a/mpp/codec/inc/dummy_dec_api.h b/mpp/codec/rc/rc_model_v2.h similarity index 53% rename from mpp/codec/inc/dummy_dec_api.h rename to mpp/codec/rc/rc_model_v2.h index 05379c7ab..246182f5a 100644 --- a/mpp/codec/inc/dummy_dec_api.h +++ b/mpp/codec/rc/rc_model_v2.h @@ -1,39 +1,40 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __DUMMY_DEC_API_H__ -#define __DUMMY_DEC_API_H__ - -#include "parser_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern const ParserApi dummy_dec_parser; - -MPP_RET dummy_dec_init (void *dec, ParserCfg *cfg); -MPP_RET dummy_dec_deinit (void *dec); -MPP_RET dummy_dec_reset (void *dec); -MPP_RET dummy_dec_flush (void *dec); -MPP_RET dummy_dec_control(void *dec, RK_S32 cmd_type, void *param); -MPP_RET dummy_dec_parse (void *dec, MppPacket pkt, HalDecTask *task); - -#ifdef __cplusplus -} -#endif - -#endif /*__DUMMY_DEC_API_H__*/ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RC_MODEL_V2_H +#define RC_MODEL_V2_H + +#include "mpp_rc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET rc_model_v2_init(void *ctx, RcCfg *cfg); +MPP_RET rc_model_v2_deinit(void *ctx); + +MPP_RET rc_model_v2_check_reenc(void *ctx, EncRcTask *task); + +MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task); +MPP_RET rc_model_v2_end(void *ctx, EncRcTask *task); + +MPP_RET rc_model_v2_hal_start(void *ctx, EncRcTask *task); +MPP_RET rc_model_v2_hal_end(void *ctx, EncRcTask *task); + +#ifdef __cplusplus +} +#endif + +#endif /* RC_MODEL_V2_H */ diff --git a/mpp/codec/rc/rc_model_v2_smt.c b/mpp/codec/rc/rc_model_v2_smt.c new file mode 100644 index 000000000..c2f764072 --- /dev/null +++ b/mpp/codec/rc/rc_model_v2_smt.c @@ -0,0 +1,1228 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "rc_model_v2_smt" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "rc_base.h" +#include "rc_debug.h" +#include "rc_model_v2_smt.h" +#include "mpp_rc.h" + +#define LOW_QP 34 +#define LOW_LOW_QP 35 + +typedef struct RcModelV2SmtCtx_t { + RcCfg usr_cfg; + RK_U32 frame_type; + RK_U32 last_frame_type; + RK_U32 first_frm_flg; + RK_S64 frm_num; + RK_S32 qp_min; + RK_S32 qp_max; + MppEncGopMode gop_mode; + RK_S64 acc_intra_count; + RK_S64 acc_inter_count; + RK_S32 last_fps_bits; + RK_S32 pre_gop_left_bit; + MppData *qp_p; + MppDataV2 *motion_level; + MppDataV2 *complex_level; + MppDataV2 *stat_bits; + MppDataV2 *rt_bits; /* real time bits */ + MppPIDCtx pid_fps; + RK_S64 count_real_bit; + RK_S64 count_pred_bit; + RK_S64 count_frame; + RK_S64 fixed_i_pred_bit; + RK_S64 fixed_p_pred_bit; + RK_S32 change_bit_flag; + + RK_S32 bits_tgt_lower; /* bits target lower limit */ + RK_S32 bits_tgt_upper; /* bits target upper limit */ + RK_S32 bits_per_lower_i; /* bits per intra frame in low rate */ + RK_S32 bits_per_upper_i; /* bits per intra frame in high rate */ + RK_S32 bits_per_lower_p; /* bits per P frame in low rate */ + RK_S32 bits_per_upper_p; /* bits per P frame in high rate */ + + RK_S32 pre_diff_bit_lower; + RK_S32 pre_diff_bit_upper; + RK_S32 igop; + MppPIDCtx pid_lower_i; + MppPIDCtx pid_upper_i; + MppPIDCtx pid_lower_all; + MppPIDCtx pid_upper_all; + MppDataV2 *pid_lower_p; + MppDataV2 *pid_upper_p; + RK_S32 qp_out; + RK_S32 qp_prev_out; + RK_S32 pre_real_bit_i; /* real bit of last intra frame */ + RK_S32 pre_qp_i; /* qp of last intra frame */ + RK_S32 gop_qp_sum; + RK_S32 gop_frm_cnt; + RK_S32 pre_iblk4_prop; + RK_S32 reenc_cnt; + RK_U32 drop_cnt; + RK_S32 on_drop; + RK_S32 on_pskip; +} RcModelV2SmtCtx; + +// rc_container_bitrate_thd2 +static RK_S32 rc_ctnr_qp_thd1[6] = { 51, 42, 42, 51, 38, 38 }; +static RK_S32 rc_ctnr_qp_thd2[6] = { 51, 44, 44, 51, 40, 40 }; +static RK_S32 rc_ctnr_br_thd1[6] = { 100, 110, 110, 100, 110, 110 }; +static RK_S32 rc_ctnr_br_thd2[6] = { 100, 120, 120, 100, 125, 125 }; + +MPP_RET bits_model_smt_deinit(RcModelV2SmtCtx *ctx) +{ + rc_dbg_func("enter %p\n", ctx); + + if (ctx->qp_p) { + mpp_data_deinit(ctx->qp_p); + ctx->qp_p = NULL; + } + + if (ctx->motion_level != NULL) { + mpp_data_deinit_v2(ctx->motion_level); + ctx->motion_level = NULL; + } + + if (ctx->complex_level != NULL) { + mpp_data_deinit_v2(ctx->complex_level); + ctx->complex_level = NULL; + } + + if (ctx->stat_bits != NULL) { + mpp_data_deinit_v2(ctx->stat_bits); + ctx->stat_bits = NULL; + } + + if (ctx->rt_bits != NULL) { + mpp_data_deinit_v2(ctx->rt_bits); + ctx->rt_bits = NULL; + } + + if (ctx->pid_lower_p != NULL) { + mpp_data_deinit_v2(ctx->pid_lower_p); + ctx->pid_lower_p = NULL; + } + + if (ctx->pid_upper_p != NULL) { + mpp_data_deinit_v2(ctx->pid_upper_p); + ctx->pid_upper_p = NULL; + } + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET bits_model_smt_init(RcModelV2SmtCtx *ctx) +{ + RK_S32 gop_len = ctx->usr_cfg.igop; + RcFpsCfg *fps = &ctx->usr_cfg.fps; + RK_S32 mad_len = 10; + RK_S32 ave_bits_lower = 0, ave_bits_uppper = 0; + RK_S32 bits_lower_i, bits_upper_i; + RK_S32 bits_lower_p, bits_upper_p; + RK_S32 bit_ratio[5] = { 7, 8, 9, 10, 11 }; + RK_S32 nfps = fps->fps_out_num / fps->fps_out_denom; + RK_S32 win_len = mpp_clip(MPP_MAX3(gop_len, nfps, 10), 1, nfps); + RK_S32 rt_stat_len = fps->fps_out_num / fps->fps_out_denom; /* real time stat len */ + RK_S32 stat_len = fps->fps_out_num * ctx->usr_cfg.stats_time / fps->fps_out_denom; + stat_len = (stat_len != 0) ? stat_len : (fps->fps_out_num * 8 / fps->fps_out_denom); + + rc_dbg_func("enter %p\n", ctx); + ctx->frm_num = 0; + ctx->first_frm_flg = 1; + ctx->gop_frm_cnt = 0; + ctx->gop_qp_sum = 0; + + // smt + ctx->igop = gop_len; + ctx->qp_min = 10; + ctx->qp_max = 51; + + if (ctx->motion_level) + mpp_data_deinit_v2(ctx->motion_level); + mpp_data_init_v2(&ctx->motion_level, mad_len, 0); + + if (ctx->complex_level) + mpp_data_deinit_v2(ctx->complex_level); + mpp_data_init_v2(&ctx->complex_level, mad_len, 0); + + if (ctx->pid_lower_p) + mpp_data_deinit_v2(ctx->pid_lower_p); + mpp_data_init_v2(&ctx->pid_lower_p, stat_len, 0); + + if (ctx->pid_upper_p) + mpp_data_deinit_v2(ctx->pid_upper_p); + mpp_data_init_v2(&ctx->pid_upper_p, stat_len, 0); + + mpp_pid_reset(&ctx->pid_fps); + mpp_pid_reset(&ctx->pid_lower_i); + mpp_pid_reset(&ctx->pid_upper_i); + mpp_pid_reset(&ctx->pid_lower_all); + mpp_pid_reset(&ctx->pid_upper_all); + + mpp_pid_set_param(&ctx->pid_fps, 4, 6, 0, 90, win_len); + mpp_pid_set_param(&ctx->pid_lower_i, 4, 6, 0, 100, win_len); + mpp_pid_set_param(&ctx->pid_upper_i, 4, 6, 0, 100, win_len); + mpp_pid_set_param(&ctx->pid_lower_all, 4, 6, 0, 100, gop_len); + mpp_pid_set_param(&ctx->pid_upper_all, 4, 6, 0, 100, gop_len); + + ave_bits_lower = (RK_S64)ctx->usr_cfg.bps_min * fps->fps_out_denom / fps->fps_out_num; + ave_bits_uppper = (RK_S64)ctx->usr_cfg.bps_max * fps->fps_out_denom / fps->fps_out_num; + + ctx->acc_intra_count = 0; + ctx->acc_inter_count = 0; + ctx->last_fps_bits = 0; + + if (gop_len == 0) { + ctx->gop_mode = MPP_GOP_ALL_INTER; + bits_lower_p = ave_bits_lower; + bits_lower_i = ave_bits_lower * 10; + bits_upper_p = ave_bits_uppper; + bits_upper_i = ave_bits_uppper * 10; + } else if (gop_len == 1) { + ctx->gop_mode = MPP_GOP_ALL_INTRA; + bits_lower_p = 0; + bits_lower_i = ave_bits_lower; + bits_upper_p = 0; + bits_upper_i = ave_bits_uppper; + /* disable debreath on all intra case */ + if (ctx->usr_cfg.debreath_cfg.enable) + ctx->usr_cfg.debreath_cfg.enable = 0; + } else if (gop_len < win_len) { + ctx->gop_mode = MPP_GOP_SMALL; + bits_lower_p = ave_bits_lower >> 1; + bits_lower_i = bits_lower_p * (gop_len + 1); + bits_upper_p = ave_bits_uppper >> 1; + bits_upper_i = bits_upper_p * (gop_len + 1); + } else { + RK_S32 g = gop_len; + RK_S32 idx = g <= 50 ? 0 : (g <= 100 ? 1 : (g <= 200 ? 2 : (g <= 300 ? 3 : 4))); + + ctx->gop_mode = MPP_GOP_LARGE; + bits_lower_i = ave_bits_lower * bit_ratio[idx] / 2; + bits_upper_i = ave_bits_uppper * bit_ratio[idx] / 2; + bits_lower_p = ave_bits_lower - bits_lower_i / (nfps - 1); + bits_upper_p = ave_bits_uppper - bits_upper_i / (nfps - 1); + ctx->fixed_i_pred_bit = (ctx->usr_cfg.bps_max / nfps * 8) / 8; + ctx->fixed_p_pred_bit = ((ctx->usr_cfg.bps_max * g / nfps - ctx->fixed_i_pred_bit) / (g - 1)) / 8; + } + + ctx->bits_per_lower_i = bits_lower_i; + ctx->bits_per_upper_i = bits_upper_i; + ctx->bits_per_lower_p = bits_lower_p; + ctx->bits_per_upper_p = bits_upper_p; + + rc_dbg_rc("bits_per_lower_i %d, bits_per_upper_i %d, " + "bits_per_lower_p %d, bits_per_upper_p %d\n", + bits_lower_i, bits_upper_i, bits_lower_p, bits_upper_p); + + if (ctx->stat_bits) + mpp_data_deinit_v2(ctx->stat_bits); + mpp_data_init_v2(&ctx->stat_bits, stat_len, bits_upper_p); + + if (ctx->rt_bits) + mpp_data_deinit_v2(ctx->rt_bits); + mpp_data_init_v2(&ctx->rt_bits, rt_stat_len, bits_upper_p); + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET bits_model_update_smt(RcModelV2SmtCtx *ctx, RK_S32 real_bit) +{ + rc_dbg_func("enter %p\n", ctx); + RcFpsCfg *fps = &ctx->usr_cfg.fps; + RK_S32 bps_target_tmp = 0; + RK_S32 mod = 0; + + rc_dbg_func("enter %p\n", ctx); + + mpp_data_update_v2(ctx->stat_bits, real_bit); + ctx->pre_diff_bit_lower = ctx->bits_tgt_lower - real_bit; + ctx->pre_diff_bit_upper = ctx->bits_tgt_upper - real_bit; + + ctx->count_real_bit = ctx->count_real_bit + real_bit / 8; + if (ctx->frame_type == INTRA_FRAME) { + ctx->count_pred_bit = ctx->count_pred_bit + ctx->fixed_i_pred_bit; + } else { + ctx->count_pred_bit = ctx->count_pred_bit + ctx->fixed_p_pred_bit; + } + ctx->count_frame ++; + if (ctx->count_real_bit > 72057594037927935 || ctx->count_pred_bit > 72057594037927935) { + ctx->count_real_bit = 0; + ctx->count_pred_bit = 0; + } + + if (ctx->change_bit_flag == 1) { + real_bit = real_bit * 8 / 10; + } + + if (ctx->frame_type == INTRA_FRAME) { + ctx->acc_intra_count++; + mpp_pid_update(&ctx->pid_lower_i, real_bit - ctx->bits_tgt_lower, 1); + mpp_pid_update(&ctx->pid_upper_i, real_bit - ctx->bits_tgt_upper, 1); + } else { + ctx->acc_inter_count++; + mpp_data_update_v2(ctx->pid_lower_p, real_bit - ctx->bits_tgt_lower); + mpp_data_update_v2(ctx->pid_upper_p, real_bit - ctx->bits_tgt_upper); + } + mpp_pid_update(&ctx->pid_lower_all, real_bit - ctx->bits_tgt_lower, 1); + mpp_pid_update(&ctx->pid_upper_all, real_bit - ctx->bits_tgt_upper, 1); + + ctx->last_fps_bits += real_bit; + /* new fps start */ + mod = ctx->acc_intra_count + ctx->acc_inter_count; + mod = mod % (fps->fps_out_num / fps->fps_out_denom); + if (0 == mod) { + bps_target_tmp = (ctx->usr_cfg.bps_min + ctx->usr_cfg.bps_max) >> 1; + if (bps_target_tmp * 3 > (ctx->last_fps_bits * 2)) + mpp_pid_update(&ctx->pid_fps, bps_target_tmp - ctx->last_fps_bits, 0); + else { + bps_target_tmp = ctx->usr_cfg.bps_min * 4 / 10 + ctx->usr_cfg.bps_max * 6 / 10; + mpp_pid_update(&ctx->pid_fps, bps_target_tmp - ctx->last_fps_bits, 0); + } + ctx->last_fps_bits = 0; + } + + /* new frame start */ + ctx->qp_prev_out = ctx->qp_out; + + rc_dbg_func("leave %p\n", ctx); + + return MPP_OK; +} + +MPP_RET rc_model_v2_smt_h265_init(void *ctx, RcCfg *cfg) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx*)ctx; + + rc_dbg_func("enter %p\n", ctx); + + memcpy(&p->usr_cfg, cfg, sizeof(RcCfg)); + bits_model_smt_init(p); + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET rc_model_v2_smt_h264_init(void *ctx, RcCfg *cfg) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx*)ctx; + + rc_dbg_func("enter %p\n", ctx); + + memcpy(&p->usr_cfg, cfg, sizeof(RcCfg)); + bits_model_smt_init(p); + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + + +MPP_RET rc_model_v2_smt_deinit(void *ctx) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *)ctx; + rc_dbg_func("enter %p\n", ctx); + bits_model_smt_deinit(p); + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +static void set_coef(void *ctx, RK_S32 *coef, RK_S32 val) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx*)ctx; + RK_S32 cplx_lvl_0 = mpp_data_get_pre_val_v2(p->complex_level, 0); + RK_S32 cplx_lvl_1 = mpp_data_get_pre_val_v2(p->complex_level, 1); + RK_S32 cplx_lvl_sum = mpp_data_sum_v2(p->complex_level); + + if (cplx_lvl_sum == 0) + *coef = val + 0; + else if (cplx_lvl_sum == 1) { + if (cplx_lvl_0 == 0) + *coef = val + 10; + else + *coef = val + 25; + } else if (cplx_lvl_sum == 2) { + if (cplx_lvl_0 == 0) + *coef = val + 25; + else + *coef = val + 35; + } else if (cplx_lvl_sum == 3) { + if (cplx_lvl_0 == 0) + *coef = val + 35; + else + *coef = val + 51; + } else if (cplx_lvl_sum >= 4 && cplx_lvl_sum <= 6) { + if (cplx_lvl_0 == 0) { + if (cplx_lvl_1 == 0) + *coef = val + 35; + else + *coef = val + 51; + } else + *coef = val + 64; + } else if (cplx_lvl_sum >= 7 && cplx_lvl_sum <= 9) { + if (cplx_lvl_0 == 0) { + if (cplx_lvl_1 == 0) + *coef = val + 64; + else + *coef = val + 72; + } else + *coef = val + 72; + } else + *coef = val + 80; +} + +static RK_U32 mb_num[9] = { + 0, 200, 700, 1200, 2000, 4000, 8000, 16000, 20000 +}; + +static RK_U32 tab_bit[9] = { + 3780, 3570, 3150, 2940, 2730, 3780, 2100, 1680, 2100 +}; + +static RK_U8 qscale2qp[96] = { + 15, 15, 15, 15, 15, 16, 18, 20, 21, 22, 23, + 24, 25, 25, 26, 27, 28, 28, 29, 29, 30, 30, + 30, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, + 34, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, + 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, 41, + 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, + 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, + 44, 44, 44, 44, 45, 45, 45, 45, +}; + +static RK_U8 inter_pqp0[52] = { + 1, 1, 1, 1, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 17, 18, 19, 20, 21, + 21, 21, 22, 23, 24, 25, 26, 26, + 27, 28, 28, 29, 29, 29, 30, 31, + 31, 32, 32, 33, 33, 34, 35, 35, + 35, 36, 36, 36 +}; + +static RK_U8 inter_pqp1[52] = { + 1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 20, 21, 22, + 23, 24, 25, 26, 26, 27, 28, 29, + 29, 30, 31, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 42, + 42, 43, 43, 44 +}; + +static RK_U8 intra_pqp0[3][52] = { + { + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 23, 24, 25, 26, 27, 27, 28, + 28, 29, 30, 31, 32, 32, 33, 34, + 34, 34, 35, 35, 36, 36, 36, 36, + 37, 37, 37, 38 + }, + + { + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 17, 18, 18, 19, 19, + 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 32, 33, 34, + 34, 34, 35, 35, 36, 36, 36, 36, + 37, 37, 37, 38 + }, + + { + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 14, 15, 15, 16, 16, 17, 17, 18, + 16, 16, 16, 17, 18, 19, 20, 21, + 23, 24, 26, 28, 30, 31, 32, 33, + 34, 34, 35, 35, 36, 36, 36, 36, + 37, 37, 37, 38 + }, +}; + +static RK_U8 intra_pqp1[52] = { + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 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, 51, 51, 51 +}; + +static RK_S32 cal_smt_first_i_start_qp(RK_S32 target_bit, RK_U32 total_mb) +{ + RK_S32 cnt = 0; + RK_S32 index; + RK_S32 i; + + for (i = 0; i < 8; i++) { + if (mb_num[i] > total_mb) + break; + cnt++; + } + + index = (total_mb * tab_bit[cnt] - 350) / target_bit; // qscale + index = mpp_clip(index, 4, 95); + + return qscale2qp[index]; +} + +static MPP_RET calc_smt_debreath_qp(RcModelV2SmtCtx * ctx) +{ + RK_S32 fm_qp_sum = 0; + RK_S32 new_fm_qp = 0; + RcDebreathCfg *debreath_cfg = &ctx->usr_cfg.debreath_cfg; + RK_S32 dealt_qp = 0; + RK_S32 gop_qp_sum = ctx->gop_qp_sum; + RK_S32 gop_frm_cnt = ctx->gop_frm_cnt; + static RK_S8 intra_qp_map[8] = { + 0, 0, 1, 1, 2, 2, 2, 2, + }; + RK_U8 idx2 = MPP_MIN(ctx->pre_iblk4_prop >> 5, (RK_S32)sizeof(intra_qp_map) - 1); + + static RK_S8 strength_map[36] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, + 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, + 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12 + }; + + rc_dbg_func("enter %p\n", ctx); + + fm_qp_sum = MPP_MIN(gop_qp_sum / gop_frm_cnt, (RK_S32)sizeof(strength_map) - 1); + + rc_dbg_qp("i qp_out %d, qp_start_sum = %d, intra_lv4_prop %d", + ctx->qp_out, fm_qp_sum, ctx->pre_iblk4_prop); + + dealt_qp = strength_map[debreath_cfg->strength] - intra_qp_map[idx2]; + if (fm_qp_sum > dealt_qp) + new_fm_qp = fm_qp_sum - dealt_qp; + else + new_fm_qp = fm_qp_sum; + + ctx->qp_out = mpp_clip(new_fm_qp, ctx->usr_cfg.min_i_quality, ctx->usr_cfg.max_i_quality); + ctx->gop_frm_cnt = 0; + ctx->gop_qp_sum = 0; + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +static MPP_RET smt_start_prepare(void *ctx, EncRcTask *task) +{ + EncFrmStatus *frm = &task->frm; + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; + EncRcTaskInfo *info = &task->info; + RcFpsCfg *fps = &p->usr_cfg.fps; + RK_S32 fps_out = fps->fps_out_num / fps->fps_out_denom; + RK_S32 b_min = p->usr_cfg.bps_min; + RK_S32 b_max = p->usr_cfg.bps_max; + RK_S32 bits_lower, bits_upper; + + p->frame_type = (frm->is_intra != 0) ? INTRA_FRAME : INTER_P_FRAME; + if (frm->ref_mode == REF_TO_PREV_INTRA) + p->frame_type = info->frame_type = INTER_VI_FRAME; + + switch (p->gop_mode) { + case MPP_GOP_ALL_INTER: { + if (p->frame_type == INTRA_FRAME) { + bits_lower = p->bits_per_lower_i; + bits_upper = p->bits_per_upper_i; + } else { + bits_lower = p->bits_per_lower_p - mpp_data_mean_v2(p->pid_lower_p); + bits_upper = p->bits_per_upper_p - mpp_data_mean_v2(p->pid_upper_p); + } + } break; + case MPP_GOP_ALL_INTRA: { + bits_lower = p->bits_per_lower_i - mpp_pid_calc(&p->pid_lower_i); + bits_upper = p->bits_per_upper_i - mpp_pid_calc(&p->pid_upper_i); + } break; + default: { + if (p->frame_type == INTRA_FRAME) { + RK_S32 diff_bit = mpp_pid_calc(&p->pid_fps); + + p->pre_gop_left_bit = p->pid_fps.i - diff_bit; + mpp_pid_reset(&p->pid_fps); + if (p->acc_intra_count) { + bits_lower = (p->bits_per_lower_i + diff_bit); + bits_upper = (p->bits_per_upper_i + diff_bit); + } else { + bits_lower = p->bits_per_lower_i - mpp_pid_calc(&p->pid_lower_i); + bits_upper = p->bits_per_upper_i - mpp_pid_calc(&p->pid_upper_i); + } + } else { + if (p->last_frame_type == INTRA_FRAME) { + RK_S32 bits_prev_i = p->pre_real_bit_i; + + bits_lower = p->bits_per_lower_p + = ((RK_S64)b_min * p->igop / fps_out - bits_prev_i + + p->pre_gop_left_bit) / (p->igop - 1); + + bits_upper = p->bits_per_upper_p + = ((RK_S64)b_max * p->igop / fps_out - bits_prev_i + + p->pre_gop_left_bit) / (p->igop - 1); + + } else { + RK_S32 diff_bit_lr = mpp_data_mean_v2(p->pid_lower_p); + RK_S32 diff_bit_hr = mpp_data_mean_v2(p->pid_upper_p); + RK_S32 lr = (RK_S64)b_min * fps->fps_out_denom / fps->fps_out_num; + RK_S32 hr = (RK_S64)b_max * fps->fps_out_denom / fps->fps_out_num; + + bits_lower = p->bits_per_lower_p - diff_bit_lr; + if (bits_lower > 2 * lr) + bits_lower = 2 * lr; + + bits_upper = p->bits_per_upper_p - diff_bit_hr; + if (bits_upper > 2 * hr) + bits_upper = 2 * hr; + } + + } + } break; + } + + p->bits_tgt_lower = bits_lower; + p->bits_tgt_upper = bits_upper; + info->bit_max = (bits_lower + bits_upper) / 2; + if (info->bit_max < 100) + info->bit_max = 100; + + if (NULL == p->qp_p) { + RK_S32 nfps = fps_out < 15 ? 4 * fps_out : (fps_out < 25 ? 3 * fps_out : 2 * fps_out); + mpp_data_init(&p->qp_p, mpp_clip(MPP_MAX(p->igop, nfps), 20, 50)); + } + + rc_dbg_rc("bits_tgt_lower %d, bits_tgt_upper %d, bit_max %d, qp_out %d", + p->bits_tgt_lower, p->bits_tgt_upper, info->bit_max, p->qp_out); + + return MPP_OK; +} + +static RK_S32 smt_calc_coef(void *ctx) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; + RK_S32 coef = 1024; + RK_S32 coef2 = 512; + RK_S32 md_lvl_sum = mpp_data_sum_v2(p->motion_level); + RK_S32 md_lvl_0 = mpp_data_get_pre_val_v2(p->motion_level, 0); + RK_S32 md_lvl_1 = mpp_data_get_pre_val_v2(p->motion_level, 1); + + if (md_lvl_sum < 100) + set_coef(ctx, &coef, 0); + else if (md_lvl_sum < 200) { + if (md_lvl_0 < 100) + set_coef(ctx, &coef, 102); + else + set_coef(ctx, &coef, 154); + } else if (md_lvl_sum < 300) { + if (md_lvl_0 < 100) + set_coef(ctx, &coef, 154); + else if (md_lvl_0 == 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 205); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 256); + else + set_coef(ctx, &coef, 307); + } else + set_coef(ctx, &coef, 307); + } else if (md_lvl_sum < 600) { + if (md_lvl_0 < 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 307); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 358); + else + set_coef(ctx, &coef, 410); + } else if (md_lvl_0 == 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 358); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 410); + else + set_coef(ctx, &coef, 461); + } else + set_coef(ctx, &coef, 461); + } else if (md_lvl_sum < 900) { + if (md_lvl_0 < 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 410); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 461); + else + set_coef(ctx, &coef, 512); + } else if (md_lvl_0 == 100) { + if (md_lvl_1 < 100) + set_coef(ctx, &coef, 512); + else if (md_lvl_1 == 100) + set_coef(ctx, &coef, 563); + else + set_coef(ctx, &coef, 614); + } else + set_coef(ctx, &coef, 614); + } else if (md_lvl_sum < 1500) + set_coef(ctx, &coef, 666); + else if (md_lvl_sum < 1900) + set_coef(ctx, &coef, 768); + else + set_coef(ctx, &coef, 900); + + if (coef > 1024) + coef = 1024; + + if (coef >= 900) + coef2 = 1024; + else if (coef >= 307) // 0.7~0.3 --> 1.0~0.5 + coef2 = 512 + (coef - 307) * (1024 - 512) / (717 - 307); + else // 0.3~0.0 --> 0.5~0.0 + coef2 = 0 + coef * (512 - 0) / (307 - 0); + if (coef2 >= 1024) + coef2 = 1024; + + return coef2; +} + +/* bit_target_use: average of bits_tgt_lower and bits_tgt_upper */ +static RK_S32 derive_iframe_qp_by_bitrate(RcModelV2SmtCtx *p, RK_S32 bit_target_use) +{ + RcFpsCfg *fps = &p->usr_cfg.fps; + RK_S32 avg_bps = (p->usr_cfg.bps_min + p->usr_cfg.bps_max) / 2; + RK_S32 fps_out = fps->fps_out_num / fps->fps_out_denom; + RK_S32 avg_pqp = mpp_data_avg(p->qp_p, -1, 1, 1); + RK_S32 avg_qp = mpp_clip(avg_pqp, p->qp_min, p->qp_max); + RK_S32 prev_iqp = p->pre_qp_i; + RK_S32 prev_pqp = p->qp_prev_out; + RK_S32 pre_bits_i = p->pre_real_bit_i; + RK_S32 qp_out_i = 0; + + if (bit_target_use <= pre_bits_i) { + qp_out_i = (bit_target_use * 5 < pre_bits_i) ? prev_iqp + 3 : + (bit_target_use * 2 < pre_bits_i) ? prev_iqp + 2 : + (bit_target_use * 3 < pre_bits_i * 2) ? prev_iqp + 1 : prev_iqp; + } else { + qp_out_i = (pre_bits_i * 3 < bit_target_use) ? prev_iqp - 3 : + (pre_bits_i * 2 < bit_target_use) ? prev_iqp - 2 : + (pre_bits_i * 3 < bit_target_use * 2) ? prev_iqp - 1 : prev_iqp; + } + rc_dbg_rc("frame %lld bit_target_use %d pre_bits_i %d prev_iqp %d qp_out_i %d\n", + p->frm_num, bit_target_use, pre_bits_i, prev_iqp, qp_out_i); + + //FIX: may be invalid(2025.01.06) + if (!p->reenc_cnt && p->usr_cfg.debreath_cfg.enable) + calc_smt_debreath_qp(p); + + qp_out_i = mpp_clip(qp_out_i, inter_pqp0[avg_qp], inter_pqp1[avg_qp]); + qp_out_i = mpp_clip(qp_out_i, inter_pqp0[prev_pqp], inter_pqp1[prev_pqp]); + if (qp_out_i > 27) + qp_out_i = mpp_clip(qp_out_i, intra_pqp0[0][prev_iqp], intra_pqp1[prev_iqp]); + else if (qp_out_i > 22) + qp_out_i = mpp_clip(qp_out_i, intra_pqp0[1][prev_iqp], intra_pqp1[prev_iqp]); + else + qp_out_i = mpp_clip(qp_out_i, intra_pqp0[2][prev_iqp], intra_pqp1[prev_iqp]); + + rc_dbg_rc("frame %lld qp_out_i %d avg_qp %d prev_pqp %d prev_iqp %d qp_out_i %d\n", + p->frm_num, qp_out_i, avg_qp, prev_pqp, prev_iqp, qp_out_i); + + if (p->pre_gop_left_bit < 0) { + if (abs(p->pre_gop_left_bit) * 5 > avg_bps * (p->igop / fps_out)) + qp_out_i = mpp_clip(qp_out_i, 20, 51); + else if (abs(p->pre_gop_left_bit) * 20 > avg_bps * (p->igop / fps_out)) + qp_out_i = mpp_clip(qp_out_i, 15, 51); + + rc_dbg_rc("frame %lld pre_gop_left_bit %d avg_bps %d qp_out_i %d\n", + p->frm_num, p->pre_gop_left_bit, avg_bps, qp_out_i); + } + + return qp_out_i; +} + +static RK_S32 derive_pframe_qp_by_bitrate(RcModelV2SmtCtx *p) +{ + RcFpsCfg *fps = &p->usr_cfg.fps; + RK_S32 avg_bps = (p->usr_cfg.bps_min + p->usr_cfg.bps_max) / 2; + RK_S32 fps_out = fps->fps_out_num / fps->fps_out_denom; + RK_S32 bits_target_use = 0; + RK_S32 pre_diff_bit_use = 0; + RK_S32 coef = smt_calc_coef(p); + RK_S32 m_tbr = p->bits_tgt_upper - p->bits_tgt_lower; + RK_S32 m_dbr = p->pre_diff_bit_upper - p->pre_diff_bit_lower; + RK_S32 diff_bit = (p->pid_lower_all.i + p->pid_upper_all.i) >> 1; + RK_S32 prev_pqp = p->qp_prev_out; + RK_S32 qp_out = p->qp_out; + RK_S32 qp_add = 0, qp_minus = 0; + + bits_target_use = ((RK_S64)m_tbr * coef + (RK_S64)p->bits_tgt_lower * 1024) >> 10; + pre_diff_bit_use = ((RK_S64)m_dbr * coef + (RK_S64)p->pre_diff_bit_lower * 1024) >> 10; + + if (bits_target_use < 100) + bits_target_use = 100; + + rc_dbg_rc("frame %lld bits_target_use %d m_tbr %d coef %d bits_tgt_lower %d\n" + "pre_diff_bit_use %d m_dbr %d pre_diff_bit_lower %d " + "bits_tgt_upper %d pre_diff_bit_upper %d qp_out_0 %d\n", + p->frm_num, bits_target_use, m_tbr, coef, p->bits_tgt_lower, + pre_diff_bit_use, m_dbr, p->pre_diff_bit_lower, + p->bits_tgt_upper, p->pre_diff_bit_upper, qp_out); + + if (abs(pre_diff_bit_use) * 100 <= bits_target_use * 3) + qp_out = prev_pqp - 1; + else if (pre_diff_bit_use * 100 > bits_target_use * 3) { + if (pre_diff_bit_use >= bits_target_use) + qp_out = qp_out >= 30 ? prev_pqp - 4 : prev_pqp - 3; + else if (pre_diff_bit_use * 4 >= bits_target_use * 1) + qp_out = qp_out >= 30 ? prev_pqp - 3 : prev_pqp - 2; + else if (pre_diff_bit_use * 10 > bits_target_use * 1) + qp_out = prev_pqp - 2; + else + qp_out = prev_pqp - 1; + } else { + RK_S32 qp_add_tmp = (prev_pqp >= 36) ? 0 : 1; + pre_diff_bit_use = abs(pre_diff_bit_use); + qp_out = (pre_diff_bit_use >= 2 * bits_target_use) ? prev_pqp + 2 + qp_add_tmp : + (pre_diff_bit_use * 3 >= bits_target_use * 2) ? prev_pqp + 1 + qp_add_tmp : + (pre_diff_bit_use * 5 > bits_target_use) ? prev_pqp + 1 : prev_pqp; + } + rc_dbg_rc("frame %lld prev_pqp %d qp_out_1 %d\n", p->frm_num, prev_pqp, qp_out); + + qp_out = mpp_clip(qp_out, p->qp_min, p->qp_max); + if (qp_out > LOW_QP) { + pre_diff_bit_use = ((RK_S64)m_dbr * coef + (RK_S64)p->pre_diff_bit_lower * 1024) >> 10; + bits_target_use = avg_bps / fps_out; + bits_target_use = -bits_target_use / 5; + coef += pre_diff_bit_use <= 2 * bits_target_use ? 205 : + ((pre_diff_bit_use <= bits_target_use) ? 102 : 51); + + if (coef >= 1024 || qp_out > LOW_LOW_QP) + coef = 1024; + rc_dbg_rc("frame %lld pre_diff_bit_use %d bits_target_use %d coef %d\n", + p->frm_num, pre_diff_bit_use, bits_target_use, coef); + + pre_diff_bit_use = ((RK_S64)m_dbr * coef + (RK_S64)p->pre_diff_bit_lower * 1024) >> 10; + bits_target_use = ((RK_S64)m_tbr * coef + (RK_S64)p->bits_tgt_lower * 1024) >> 10; + if (bits_target_use < 100) + bits_target_use = 100; + + if (abs(pre_diff_bit_use) * 100 <= bits_target_use * 3) + qp_out = prev_pqp; + else if (pre_diff_bit_use * 100 > bits_target_use * 3) { + if (pre_diff_bit_use >= bits_target_use) + qp_out = qp_out >= 30 ? prev_pqp - 3 : prev_pqp - 2; + else if (pre_diff_bit_use * 4 >= bits_target_use * 1) + qp_out = qp_out >= 30 ? prev_pqp - 2 : prev_pqp - 1; + else if (pre_diff_bit_use * 10 > bits_target_use * 1) + qp_out = prev_pqp - 1; + else + qp_out = prev_pqp; + } else { + pre_diff_bit_use = abs(pre_diff_bit_use); + qp_out = prev_pqp + (pre_diff_bit_use * 3 >= bits_target_use * 2 ? 1 : 0); + } + rc_dbg_rc("frame %lld pre_diff_bit_use %d bits_target_use %d prev_pqp %d qp_out_2 %d\n", + p->frm_num, pre_diff_bit_use, bits_target_use, prev_pqp, qp_out); + } + + qp_out = mpp_clip(qp_out, p->qp_min, p->qp_max); + + //Add rc_container + p->change_bit_flag = 0; + if (p->usr_cfg.rc_container) { + RK_S32 cnt = p->usr_cfg.scene_mode * 3 + p->usr_cfg.rc_container; + if (p->count_real_bit < p->count_pred_bit * rc_ctnr_br_thd1[cnt] / 100) { + if (qp_out > rc_ctnr_qp_thd1[cnt]) { + p->change_bit_flag = 1; + } + + qp_out = mpp_clip(qp_out, 10, rc_ctnr_qp_thd1[cnt]); + } else if (p->count_real_bit < p->count_pred_bit * rc_ctnr_br_thd2[cnt] / 100) { + if (qp_out > rc_ctnr_qp_thd2[cnt]) { + p->change_bit_flag = 1; + } + qp_out = mpp_clip(qp_out, 10, rc_ctnr_qp_thd2[cnt]); + } + } + + qp_add = qp_out > 36 ? 1 : (qp_out > 33 ? 2 : (qp_out > 30 ? 3 : 4)); + qp_minus = qp_out > 40 ? 4 : (qp_out > 36 ? 3 : (qp_out > 33 ? 2 : 1)); + qp_out = mpp_clip(qp_out, prev_pqp - qp_minus, prev_pqp + qp_add); + rc_dbg_rc("frame %lld qp_out_3 %d qp_add %d qp_minus %d\n", + p->frm_num, qp_out, qp_add, qp_minus); + + if (diff_bit > 0) { + if (avg_bps * 5 > avg_bps) //FIXME: avg_bps is typo error?(2025.01.06) + qp_out = mpp_clip(qp_out, 25, 51); + else if (avg_bps * 20 > avg_bps) + qp_out = mpp_clip(qp_out, 21, 51); + rc_dbg_rc("frame %lld avg_bps %d qp_out_4 %d\n", p->frm_num, avg_bps, qp_out); + } + + return qp_out; +} + +static RK_S32 revise_qp_by_complexity(RcModelV2SmtCtx *p, RK_S32 fm_min_iqp, + RK_S32 fm_min_pqp, RK_S32 fm_max_iqp, RK_S32 fm_max_pqp) +{ + RK_S32 md_lvl_sum = mpp_data_sum_v2(p->motion_level); + RK_S32 md_lvl_0 = mpp_data_get_pre_val_v2(p->motion_level, 0); + RK_S32 cplx_lvl_sum = mpp_data_sum_v2(p->complex_level); + RK_S32 qp_add = 0, qp_add_p = 0; + RK_S32 qp_final = p->qp_out; + + qp_add = 4; + qp_add_p = 4; + if (md_lvl_sum >= 700 || md_lvl_0 == 200) { + qp_add = 6; + qp_add_p = 6; + } else if (md_lvl_sum >= 400 || md_lvl_0 == 100) { + qp_add = 5; + qp_add_p = 5; + } + if (cplx_lvl_sum >= 12) { + qp_add++; + qp_add_p++; + } + + rc_dbg_rc("frame %lld md_lvl_sum %d md_lvl_0 %d cplx_lvl_sum %d " + "qp_add_cplx %d qp_add_p %d qp_final_0 %d\n", + p->frm_num, md_lvl_sum, md_lvl_0, cplx_lvl_sum, + qp_add, qp_add_p, qp_final); + + if (p->frame_type == INTRA_FRAME) + qp_final = mpp_clip(qp_final, fm_min_iqp + qp_add, fm_max_iqp); + else if (p->frame_type == INTER_VI_FRAME) { + RK_S32 vi_max_qp = (fm_max_pqp > 42) ? (fm_max_pqp - 5) : + (fm_max_pqp > 39) ? (fm_max_pqp - 3) : + (fm_max_pqp > 35) ? (fm_max_pqp - 2) : fm_max_pqp; + qp_final -= 1; + qp_final = mpp_clip(qp_final, fm_min_pqp + qp_add - 1, fm_max_pqp); + qp_final = mpp_clip(qp_final, qp_final, vi_max_qp); + } else + qp_final = mpp_clip(qp_final, fm_min_pqp + qp_add_p, fm_max_pqp); + + qp_final = mpp_clip(qp_final, p->qp_min, p->qp_max); + rc_dbg_rc("frame %lld frm_type %d frm_qp %d:%d:%d:%d blk_qp %d:%d qp_final_1 %d\n", + p->frm_num, p->frame_type, fm_min_iqp, fm_max_iqp, + fm_min_pqp, fm_max_pqp, p->qp_min, p->qp_max, qp_final); + + return qp_final; +} + +MPP_RET rc_model_v2_smt_start(void *ctx, EncRcTask * task) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; + EncFrmStatus *frm = &task->frm; + EncRcTaskInfo *info = &task->info; + RcFpsCfg *fps = &p->usr_cfg.fps; + RK_S32 fps_out = fps->fps_out_num / fps->fps_out_denom; + RK_S32 avg_pqp = 0; + RK_S32 fm_min_iqp = p->usr_cfg.fqp_min_i; + RK_S32 fm_min_pqp = p->usr_cfg.fqp_min_p; + RK_S32 fm_max_iqp = p->usr_cfg.fqp_max_i; + RK_S32 fm_max_pqp = p->usr_cfg.fqp_max_p; + + if (frm->reencode) + return MPP_OK; + + smt_start_prepare(ctx, task); + avg_pqp = mpp_data_avg(p->qp_p, -1, 1, 1); + + if (p->frm_num == 0) { + RK_S32 mb_w = MPP_ALIGN(p->usr_cfg.width, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(p->usr_cfg.height, 16) / 16; + RK_S32 ratio = mpp_clip(fps_out / 10 + 1, 1, 3); + RK_S32 qp_out_f0 = 0; + if (p->usr_cfg.init_quality < 0) { + qp_out_f0 = cal_smt_first_i_start_qp(p->bits_tgt_upper * ratio, mb_w * mb_h); + qp_out_f0 = (fm_min_iqp > 31) ? mpp_clip(qp_out_f0, fm_min_iqp, p->qp_max) : + mpp_clip(qp_out_f0, 31, p->qp_max); + } else + qp_out_f0 = p->usr_cfg.init_quality; + + p->qp_out = qp_out_f0; + p->count_real_bit = 0; + p->count_pred_bit = 0; + p->count_frame = 0; + rc_dbg_rc("first frame init_quality %d bits_tgt_upper %d " + "mb_w %d mb_h %d ratio %d qp_out %d\n", + p->usr_cfg.init_quality, p->bits_tgt_upper, + mb_w, mb_h, ratio, p->qp_out); + } else if (p->frame_type == INTRA_FRAME) { + // if (p->frm_num > 0) + p->qp_out = derive_iframe_qp_by_bitrate(p, info->bit_max); + } else { + if (p->last_frame_type == INTRA_FRAME) { + RK_S32 prev_qp = p->qp_prev_out; + p->qp_out = prev_qp + (prev_qp < 33 ? 3 : (prev_qp < 35 ? 2 : 1)); + } else + p->qp_out = derive_pframe_qp_by_bitrate(p); + } + + p->qp_out = revise_qp_by_complexity(p, fm_min_iqp, fm_min_pqp, fm_max_iqp, fm_max_pqp); + + info->quality_target = p->qp_out; + info->complex_scene = 0; + if (p->frame_type == INTER_P_FRAME && avg_pqp >= fm_max_pqp - 1 && + p->qp_out == fm_max_pqp && p->qp_prev_out == fm_max_pqp) + info->complex_scene = 1; + + info->quality_max = p->usr_cfg.max_quality; + info->quality_min = p->usr_cfg.min_quality; + + rc_dbg_rc("frame %lld quality [%d : %d : %d] complex_scene %d\n", + p->frm_num, info->quality_min, info->quality_target, + info->quality_max, info->complex_scene); + + p->frm_num++; + p->reenc_cnt = 0; + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET check_super_frame_smt(RcModelV2SmtCtx *ctx, EncRcTaskInfo *cfg) +{ + MPP_RET ret = MPP_OK; + RK_S32 frame_type = ctx->frame_type; + RK_U32 bits_thr = 0; + RcCfg *usr_cfg = &ctx->usr_cfg; + + rc_dbg_func("enter %p\n", ctx); + if (usr_cfg->super_cfg.super_mode) { + bits_thr = usr_cfg->super_cfg.super_p_thd; + if (frame_type == INTRA_FRAME) + bits_thr = usr_cfg->super_cfg.super_i_thd; + + if ((RK_U32)cfg->bit_real >= bits_thr) { + if (usr_cfg->super_cfg.super_mode == MPP_ENC_RC_SUPER_FRM_DROP) { + rc_dbg_rc("super frame drop current frame"); + usr_cfg->drop_mode = MPP_ENC_RC_DROP_FRM_NORMAL; + usr_cfg->drop_gap = 0; + } + ret = MPP_NOK; + } + } + rc_dbg_func("leave %p\n", ctx); + return ret; +} + +MPP_RET check_re_enc_smt(RcModelV2SmtCtx *ctx, EncRcTaskInfo *cfg) +{ + RcCfg *usr_cfg = &ctx->usr_cfg; + RK_S32 frame_type = ctx->frame_type; + RK_S32 bit_thr = 0; + RK_S32 stat_time = usr_cfg->stats_time; + RK_S32 last_ins_bps = mpp_data_sum_v2(ctx->stat_bits) / stat_time; + RK_S32 ins_bps = (last_ins_bps * stat_time - mpp_data_get_pre_val_v2(ctx->stat_bits, -1) + + cfg->bit_real) / stat_time; + RK_S32 bps; + RK_S32 ret = MPP_OK; + + rc_dbg_func("enter %p\n", ctx); + rc_dbg_rc("reenc check target_bps %d last_ins_bps %d ins_bps %d", + usr_cfg->bps_target, last_ins_bps, ins_bps); + + if (ctx->reenc_cnt >= usr_cfg->max_reencode_times) + return MPP_OK; + + if (check_super_frame_smt(ctx, cfg)) + return MPP_NOK; + + if (usr_cfg->debreath_cfg.enable && !ctx->first_frm_flg) + return MPP_OK; + + rc_dbg_drop("drop mode %d frame_type %d\n", usr_cfg->drop_mode, frame_type); + if (usr_cfg->drop_mode && frame_type == INTER_P_FRAME) { + bit_thr = (RK_S32)(usr_cfg->bps_max * (100 + usr_cfg->drop_thd) / (float)100); + rc_dbg_drop("drop mode %d check max_bps %d bit_thr %d ins_bps %d", + usr_cfg->drop_mode, usr_cfg->bps_target, bit_thr, ins_bps); + return (ins_bps > bit_thr) ? MPP_NOK : MPP_OK; + } + + switch (frame_type) { + case INTRA_FRAME: + bit_thr = 3 * cfg->bit_max / 2; + break; + case INTER_P_FRAME: + bit_thr = 3 * cfg->bit_max; + break; + default: + break; + } + + if (cfg->bit_real > bit_thr) { + bps = usr_cfg->bps_max; + if ((bps - (bps >> 3) < ins_bps) && (bps / 20 < ins_bps - last_ins_bps)) + ret = MPP_NOK; + } + + rc_dbg_func("leave %p ret %d\n", ctx, ret); + return ret; +} + +MPP_RET rc_model_v2_smt_check_reenc(void *ctx, EncRcTask *task) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *)ctx; + EncRcTaskInfo *cfg = (EncRcTaskInfo *)&task->info; + EncFrmStatus *frm = &task->frm; + RcCfg *usr_cfg = &p->usr_cfg; + + rc_dbg_func("enter ctx %p cfg %p\n", ctx, cfg); + + frm->reencode = 0; + + if ((usr_cfg->mode == RC_FIXQP) || + (task->force.force_flag & ENC_RC_FORCE_QP) || + p->on_drop || p->on_pskip) + return MPP_OK; + + if (check_re_enc_smt(p, cfg)) { + MppEncRcDropFrmMode drop_mode = usr_cfg->drop_mode; + + if (frm->is_intra) + drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED; + + if (usr_cfg->drop_gap && p->drop_cnt >= usr_cfg->drop_gap) + drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED; + + rc_dbg_drop("reenc drop_mode %d drop_cnt %d\n", drop_mode, p->drop_cnt); + + switch (drop_mode) { + case MPP_ENC_RC_DROP_FRM_NORMAL : { + frm->drop = 1; + frm->reencode = 1; + p->on_drop = 1; + p->drop_cnt++; + rc_dbg_drop("drop\n"); + } break; + case MPP_ENC_RC_DROP_FRM_PSKIP : { + frm->force_pskip = 1; + frm->reencode = 1; + p->on_pskip = 1; + p->drop_cnt++; + rc_dbg_drop("force_pskip\n"); + } break; + case MPP_ENC_RC_DROP_FRM_DISABLED : + default : { + RK_S32 bits_thr = usr_cfg->super_cfg.super_p_thd; + if (p->frame_type == INTRA_FRAME) + bits_thr = usr_cfg->super_cfg.super_i_thd; + + if (cfg->bit_real > bits_thr * 2) + cfg->quality_target += 3; + else if (cfg->bit_real > bits_thr * 3 / 2) + cfg->quality_target += 2; + else if (cfg->bit_real > bits_thr) + cfg->quality_target ++; + + if (cfg->quality_target < cfg->quality_max) { + p->reenc_cnt++; + frm->reencode = 1; + } + p->drop_cnt = 0; + } break; + } + } + + return MPP_OK; +} + +MPP_RET rc_model_v2_smt_end(void *ctx, EncRcTask * task) +{ + RcModelV2SmtCtx *p = (RcModelV2SmtCtx *) ctx; + EncRcTaskInfo *cfg = (EncRcTaskInfo *) & task->info; + RK_S32 bit_real = cfg->bit_real; + + rc_dbg_func("enter ctx %p cfg %p\n", ctx, cfg); + rc_dbg_rc("motion_level %u, complex_level %u\n", cfg->motion_level, cfg->complex_level); + + mpp_data_update_v2(p->rt_bits, bit_real); + cfg->rt_bits = mpp_data_sum_v2(p->rt_bits); + rc_dbg_rc("frame %lld real_bit %d real time bits %d\n", + p->frm_num - 1, bit_real, cfg->rt_bits); + + mpp_data_update_v2(p->motion_level, cfg->motion_level); + mpp_data_update_v2(p->complex_level, cfg->complex_level); + p->first_frm_flg = 0; + + if (p->frame_type == INTER_P_FRAME || p->gop_mode == MPP_GOP_ALL_INTRA) + mpp_data_update(p->qp_p, p->qp_out); + else { + p->pre_qp_i = p->qp_out; + p->pre_real_bit_i = bit_real; + } + + bits_model_update_smt(p, bit_real); + p->qp_prev_out = p->qp_out; + p->last_frame_type = p->frame_type; + p->pre_iblk4_prop = cfg->iblk4_prop; + p->gop_frm_cnt++; + p->gop_qp_sum += p->qp_out; + + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET rc_model_v2_smt_hal_start(void *ctx, EncRcTask *task) +{ + rc_dbg_func("smt_hal_start enter ctx %p task %p\n", ctx, task); + return MPP_OK; +} + +MPP_RET rc_model_v2_smt_hal_end(void *ctx, EncRcTask *task) +{ + rc_dbg_func("smt_hal_end enter ctx %p task %p\n", ctx, task); + rc_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +const RcImplApi smt_h264e = { + "smart", + MPP_VIDEO_CodingAVC, + sizeof(RcModelV2SmtCtx), + rc_model_v2_smt_h264_init, + rc_model_v2_smt_deinit, + NULL, + rc_model_v2_smt_check_reenc, + rc_model_v2_smt_start, + rc_model_v2_smt_end, + rc_model_v2_smt_hal_start, + rc_model_v2_smt_hal_end, +}; + +const RcImplApi smt_h265e = { + "smart", + MPP_VIDEO_CodingHEVC, + sizeof(RcModelV2SmtCtx), + rc_model_v2_smt_h265_init, + rc_model_v2_smt_deinit, + NULL, + rc_model_v2_smt_check_reenc, + rc_model_v2_smt_start, + rc_model_v2_smt_end, + rc_model_v2_smt_hal_start, + rc_model_v2_smt_hal_end, +}; diff --git a/mpp/mpi_impl.cpp b/mpp/codec/rc/rc_model_v2_smt.h similarity index 66% rename from mpp/mpi_impl.cpp rename to mpp/codec/rc/rc_model_v2_smt.h index cdf17dda4..829f03834 100644 --- a/mpp/mpi_impl.cpp +++ b/mpp/codec/rc/rc_model_v2_smt.h @@ -1,30 +1,32 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpi" - -#include "rk_mpi.h" -#include "mpp_log.h" -#include "mpp_env.h" -#include "mpi_impl.h" - -RK_U32 mpi_debug = 0; - -void get_mpi_debug() -{ - mpp_env_get_u32("mpi_debug", &mpi_debug, 0); -} - +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RC_MODEL_V2_SMT_H +#define RC_MODEL_V2_SMT_H + +#include "mpp_rc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const RcImplApi smt_h264e; +extern const RcImplApi smt_h265e; + +#ifdef __cplusplus +} +#endif + +#endif /* RC_MODEL_V2_SMT_H */ diff --git a/mpp/codec/rc/test/CMakeLists.txt b/mpp/codec/rc/test/CMakeLists.txt new file mode 100644 index 000000000..3eb767a11 --- /dev/null +++ b/mpp/codec/rc/test/CMakeLists.txt @@ -0,0 +1,26 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# rate control built-in unit test case +# ---------------------------------------------------------------------------- + +include_directories(..) + +# macro for adding osal sub-module unit test +macro(add_mpp_rc_test module) + set(test_name ${module}_test) + string(TOUPPER ${test_name} test_tag) + + option(${test_tag} "Build rc ${module} unit test" ${BUILD_TEST}) + if(${test_tag}) + add_executable(${test_name} ${test_name}.c) + target_link_libraries(${test_name} ${MPP_SHARED} ${ASAN_LIB}) + set_target_properties(${test_name} PROPERTIES FOLDER "osal/test") + add_test(NAME ${test_name} COMMAND ${test_name}) + endif() +endmacro() + +# mpp rc unit test +add_mpp_rc_test(rc_base) + +# mpp rc api test +add_mpp_rc_test(rc_api) diff --git a/mpp/codec/rc/test/rc_api_test.c b/mpp/codec/rc/test/rc_api_test.c new file mode 100644 index 000000000..fa48aaddf --- /dev/null +++ b/mpp/codec/rc/test/rc_api_test.c @@ -0,0 +1,87 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_api_test" + +#include + +#include "mpp_log.h" +#include "mpp_rc_api.h" + +#define MAX_QUERY_COUNT 16 + +const RcImplApi test_h264_api = { + "test_h264e_rc", + MPP_VIDEO_CodingAVC, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +const RcImplApi test_h265_api = { + "test_h265e_rc", + MPP_VIDEO_CodingHEVC, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +int main(void) +{ + RcApiQueryAll query; + RcApiBrief briefs[MAX_QUERY_COUNT]; + RK_S32 i; + + mpp_log("rc api test start\n"); + + query.brief = briefs; + query.max_count = MAX_QUERY_COUNT; + query.count = 0; + + rc_brief_get_all(&query); + + mpp_log("default rc api query result:\n"); + for (i = 0; i < query.count; i++) + mpp_log("rc api %s type %x\n", briefs[i].name, briefs[i].type); + + mpp_log("add test rc api\n"); + + rc_api_add(&test_h264_api); + rc_api_add(&test_h265_api); + + rc_brief_get_all(&query); + + mpp_log("rc api query result after adding\n"); + for (i = 0; i < query.count; i++) + mpp_log("rc api %s type %x\n", briefs[i].name, briefs[i].type); + + mpp_log("mpp rc api test done\n"); + + return 0; +} + diff --git a/mpp/codec/rc/test/rc_base_test.c b/mpp/codec/rc/test/rc_base_test.c new file mode 100644 index 000000000..67fb747b2 --- /dev/null +++ b/mpp/codec/rc/test/rc_base_test.c @@ -0,0 +1,69 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "mpp_rc_test" + +#include + +#include "mpp_log.h" +#include "rc_base.h" + +int main(void) +{ + MPP_RET ret = MPP_OK; + MppDataV2 *data_2 = NULL; + MppDataV2 *data_5 = NULL; + MppDataV2 *data_8 = NULL; + MppDataV2 *data_30 = NULL; + RK_S32 val = 0; + RK_S32 i; + + mpp_log("mpp rc test start\n"); + + mpp_data_init_v2(&data_2, 2, 0); + mpp_data_init_v2(&data_5, 5, 0); + mpp_data_init_v2(&data_8, 8, 0); + mpp_data_init_v2(&data_30, 30, 0); + + for (i = 0; i < 50; i++) { + val = i; + + mpp_data_update_v2(data_2, val); + mpp_data_update_v2(data_5, val); + mpp_data_update_v2(data_8, val); + mpp_data_update_v2(data_30, val); + + mpp_log("sum %4d %4d %4d %4d mean %2d %2d %2d %2d ratio sum %2d %2d %2d %2d\n", + mpp_data_sum_v2(data_2), mpp_data_sum_v2(data_5), + mpp_data_sum_v2(data_8), mpp_data_sum_v2(data_30), + mpp_data_mean_v2(data_2), mpp_data_mean_v2(data_5), + mpp_data_mean_v2(data_8), mpp_data_mean_v2(data_30), + mpp_data_sum_with_ratio_v2(data_2, data_2->size, 3, 4), + mpp_data_sum_with_ratio_v2(data_5, data_5->size, 3, 4), + mpp_data_sum_with_ratio_v2(data_8, data_8->size, 3, 4), + mpp_data_sum_with_ratio_v2(data_30, data_30->size, 3, 4)); + } + + mpp_data_deinit_v2(data_5); + mpp_data_deinit_v2(data_8); + mpp_data_deinit_v2(data_30); + mpp_data_deinit_v2(data_2); + + mpp_log("mpp rc test success\n"); + + return ret; +} + diff --git a/mpp/codec/rc/vp8e_rc.c b/mpp/codec/rc/vp8e_rc.c new file mode 100644 index 000000000..314af8eca --- /dev/null +++ b/mpp/codec/rc/vp8e_rc.c @@ -0,0 +1,167 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vp8e_rc" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "rc_debug.h" +#include "rc_ctx.h" +#include "rc_model_v2.h" + +#define UPSCALE 8000 + +static RK_S32 vp8_initial_qp(RK_S32 bits, RK_S32 pels) +{ + RK_S32 i = -1; + static const RK_S32 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} + }; + + if (bits > 1000000) + return 10; + + pels >>= 8; + bits >>= 5; + + bits *= pels + 250; + bits /= 350 + (3 * pels) / 4; + bits = axb_div_c(bits, UPSCALE, pels << 6); + + while (qp_tbl[0][++i] < bits); + + return qp_tbl[1][i]; +} + +MPP_RET rc_model_v2_vp8_hal_start(void *ctx, EncRcTask *task) +{ + RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; + EncFrmStatus *frm = &task->frm; + EncRcTaskInfo *info = &task->info; + EncRcForceCfg *force = &task->force; + RcCfg *usr_cfg = &p->usr_cfg; + RK_S32 mb_w = MPP_ALIGN(usr_cfg->width, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(usr_cfg->height, 16) / 16; + RK_S32 bit_min = info->bit_min; + RK_S32 bit_max = info->bit_max; + RK_S32 bit_target = info->bit_target; + RK_S32 quality_min = info->quality_min; + RK_S32 quality_max = info->quality_max; + RK_S32 quality_target = info->quality_target; + + rc_dbg_func("enter p %p task %p\n", p, task); + + rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra); + + if (force->force_flag & ENC_RC_FORCE_QP) { + RK_S32 qp = force->force_qp; + info->quality_target = qp; + info->quality_max = qp; + info->quality_min = qp; + return MPP_OK; + } + + if (usr_cfg->mode == RC_FIXQP) + return MPP_OK; + + /* setup quality parameters */ + if (p->first_frm_flg && frm->is_intra) { + if (info->quality_target < 0) { + if (info->bit_target) { + p->start_qp = vp8_initial_qp(info->bit_target, mb_w * mb_h * 16 * 16); + p->cur_scale_qp = (p->start_qp) << 6; + } else { + mpp_log("fix qp case but init qp no set"); + info->quality_target = 40; + p->start_qp = 40; + p->cur_scale_qp = (p->start_qp) << 6; + } + } else { + p->start_qp = info->quality_target; + p->cur_scale_qp = (p->start_qp) << 6; + } + + if (p->reenc_cnt > 0) { + p->cur_scale_qp += p->next_ratio; + p->start_qp = p->cur_scale_qp >> 6; + rc_dbg_rc("p->start_qp = %d, p->cur_scale_qp %d,p->next_ratio %d ", p->start_qp, p->cur_scale_qp, p->next_ratio); + } else { + p->start_qp -= usr_cfg->i_quality_delta; + } + p->cur_scale_qp = mpp_clip(p->cur_scale_qp, (info->quality_min << 6), (info->quality_max << 6)); + p->pre_i_qp = p->cur_scale_qp >> 6; + p->pre_p_qp = p->cur_scale_qp >> 6; + } else { + RK_S32 qp_scale = p->cur_scale_qp + p->next_ratio; + RK_S32 start_qp = 0; + RK_S32 dealt_qp = 0; + + if (frm->is_intra) { + qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6)); + + start_qp = ((p->pre_i_qp + ((qp_scale + p->next_i_ratio) >> 6)) >> 1); + + start_qp = mpp_clip(start_qp, info->quality_min, info->quality_max); + p->pre_i_qp = start_qp; + p->start_qp = start_qp; + p->cur_scale_qp = qp_scale; + + if (usr_cfg->i_quality_delta && !p->reenc_cnt) + p->start_qp -= dealt_qp; + } else { + qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6)); + p->cur_scale_qp = qp_scale; + p->start_qp = qp_scale >> 6; + if (frm->ref_mode == REF_TO_PREV_INTRA && usr_cfg->vi_quality_delta) { + p->start_qp -= usr_cfg->vi_quality_delta; + } + } + rc_dbg_rc("i_quality_delta %d, vi_quality_delta %d", dealt_qp, usr_cfg->vi_quality_delta); + } + + p->start_qp = mpp_clip(p->start_qp, info->quality_min, info->quality_max); + info->quality_target = p->start_qp; + + rc_dbg_rc("bitrate [%d : %d : %d] -> [%d : %d : %d]\n", + bit_min, bit_target, bit_max, + info->bit_min, info->bit_target, info->bit_max); + rc_dbg_rc("quality [%d : %d : %d] -> [%d : %d : %d]\n", + quality_min, quality_target, quality_max, + info->quality_min, info->quality_target, info->quality_max); + + rc_dbg_func("leave %p\n", p); + return MPP_OK; +} + +const RcImplApi default_vp8e = { + "default", + MPP_VIDEO_CodingVP8, + sizeof(RcModelV2Ctx), + rc_model_v2_init, + rc_model_v2_deinit, + NULL, + rc_model_v2_check_reenc, + rc_model_v2_start, + rc_model_v2_end, + rc_model_v2_vp8_hal_start, + rc_model_v2_hal_end, +}; diff --git a/mpp/codec/rc/vp8e_rc.h b/mpp/codec/rc/vp8e_rc.h new file mode 100644 index 000000000..049d6ee6a --- /dev/null +++ b/mpp/codec/rc/vp8e_rc.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef VP8E_RC_H +#define VP8E_RC_H + +#include "mpp_rc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const RcImplApi default_vp8e; + +#ifdef __cplusplus +} +#endif + +#endif /* VP8E_RC_H */ diff --git a/mpp/codecs.cmake b/mpp/codecs.cmake new file mode 100644 index 000000000..c89936e99 --- /dev/null +++ b/mpp/codecs.cmake @@ -0,0 +1,142 @@ +# This file setup the enable flag of all supported codecs + +# AVS decoder +option(ENABLE_AVSD "Enable avs decoder" ${ENABLE_AVSD_DEFAULT}) +if( ENABLE_AVSD AND + EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/codec/dec/avs" ) + set(HAVE_AVSD true) + set(CODEC_AVSD codec_avsd) + set(HAL_AVSD hal_avsd) + add_definitions(-DHAVE_AVSD) +endif() + +# AVS2 decoder +option(ENABLE_AVS2D "Enable avs2 decoder" ${ENABLE_AVS2D_DEFAULT}) +if( ENABLE_AVS2D AND + EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/codec/dec/avs2" ) + set(HAVE_AVS2D true) + set(CODEC_AVS2D codec_avs2d) + set(HAL_AVS2D hal_avs2d) + add_definitions(-DHAVE_AVS2D) +endif() + +# H.263 decoder +option(ENABLE_H263D "Enable h.263 decoder" ${ENABLE_H263D_DEFAULT}) +if( ENABLE_H263D ) + set(HAVE_H263D true) + set(CODEC_H263D codec_h263d) + set(HAL_H263D hal_h263d) + add_definitions(-DHAVE_H263D) +endif() + +# H.264 decoder +option(ENABLE_H264D "Enable h.264 decoder" ${ENABLE_H264D_DEFAULT}) +if( ENABLE_H264D ) + set(HAVE_H264D true) + set(CODEC_H264D codec_h264d) + set(HAL_H264D hal_h264d) + add_definitions(-DHAVE_H264D) +endif() +option(ENABLE_FASTPLAY_ONCE "Enable h.264 decoder fast play once" OFF) +if( ENABLE_FASTPLAY_ONCE OR ANDROID) + add_definitions(-DENABLE_FASTPLAY_ONCE) +endif() + +# H.265 decoder +option(ENABLE_H265D "Enable h.265 decoder" ${ENABLE_H265D_DEFAULT}) +if( ENABLE_H265D ) + set(HAVE_H265D true) + set(CODEC_H265D codec_h265d) + set(HAL_H265D hal_h265d) + add_definitions(-DHAVE_H265D) +endif() + +# mpeg2 decoder +option(ENABLE_MPEG2D "Enable mpeg2 decoder" ${ENABLE_MPEG2D_DEFAULT}) +if( ENABLE_MPEG2D ) + set(HAVE_MPEG2D true) + set(CODEC_MPEG2D codec_mpeg2d) + set(HAL_MPEG2D hal_mpeg2d) + add_definitions(-DHAVE_MPEG2D) +endif() + +# mpeg4 decoder +option(ENABLE_MPEG4D "Enable mpeg4 decoder" ${ENABLE_MPEG4D_DEFAULT}) +if( ENABLE_MPEG4D ) + set(HAVE_MPEG4D true) + set(CODEC_MPEG4D codec_mpeg4d) + set(HAL_MPEG4D hal_mpeg4d) + add_definitions(-DHAVE_MPEG4D) +endif() + +# VP8 decoder +option(ENABLE_VP8D "Enable vp8 decoder" ${ENABLE_VP8D_DEFAULT}) +if( ENABLE_VP8D ) + set(HAVE_VP8D true) + set(CODEC_VP8D codec_vp8d) + set(HAL_VP8D hal_vp8d) + add_definitions(-DHAVE_VP8D) +endif() + +# VP9 decoder +option(ENABLE_VP9D "Enable vp9 decoder" ${ENABLE_VP9D_DEFAULT}) +if( ENABLE_VP9D ) + set(HAVE_VP9D true) + set(CODEC_VP9D codec_vp9d) + set(HAL_VP9D hal_vp9d) + add_definitions(-DHAVE_VP9D) +endif() + +# jpeg decoder +option(ENABLE_JPEGD "Enable jpeg decoder" ${ENABLE_JPEGD_DEFAULT}) +if( ENABLE_JPEGD ) + set(HAVE_JPEGD true) + set(CODEC_JPEGD codec_jpegd) + set(HAL_JPEGD hal_jpegd) + add_definitions(-DHAVE_JPEGD) +endif() + +# AV1 decoder +option(ENABLE_AV1D "Enable av1 decoder" ${ENABLE_AV1D_DEFAULT}) +if( ENABLE_AV1D ) + set(HAVE_AV1D true) + set(CODEC_AV1D codec_av1d) + set(HAL_AV1D hal_av1d) + add_definitions(-DHAVE_AV1D) +endif() + +# H.264 encoder +option(ENABLE_H264E "Enable h.264 encoder" ${ENABLE_H264E_DEFAULT}) +if( ENABLE_H264E ) + set(HAVE_H264E true) + set(CODEC_H264E codec_h264e) + set(HAL_H264E hal_h264e) + add_definitions(-DHAVE_H264E) +endif() + +# jpeg encoder +option(ENABLE_JPEGE "Enable jpeg encoder" ${ENABLE_JPEGE_DEFAULT}) +if( ENABLE_JPEGE ) + set(HAVE_JPEGE true) + set(CODEC_JPEGE codec_jpege) + set(HAL_JPEGE hal_jpege) + add_definitions(-DHAVE_JPEGE) +endif() + +# h265 encoder +option(ENABLE_H265E "Enable h265 encoder" ${ENABLE_H265E_DEFAULT}) +if( ENABLE_H265E ) + set(HAVE_H265E true) + set(CODEC_H265E codec_h265e) + set(HAL_H265E hal_h265e) + add_definitions(-DHAVE_H265E) +endif() + +# vp8 encoder +option(ENABLE_VP8E "Enable vp8 encoder" ${ENABLE_VP8E_DEFAULT}) +if( ENABLE_VP8E ) + set(HAVE_VP8E true) + set(CODEC_VP8E codec_vp8e) + set(HAL_VP8E hal_vp8e) + add_definitions(-DHAVE_VP8E) +endif() diff --git a/mpp/common/av1d_common.h b/mpp/common/av1d_common.h new file mode 100644 index 000000000..2e38bcc82 --- /dev/null +++ b/mpp/common/av1d_common.h @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef AV1D_COMMON_H +#define AV1D_COMMON_H + +#include "mpp_common.h" + +// Max tiles for AV1 (custom size) for Level <= 6.x +#define AV1_MAX_TILES 128 +#define AV1_MAX_TILE_COLS 64 +#define AV1_MAX_TILE_ROWS 64 +#define AV1_MAX_TILE_WIDTH 4096 +#define AV1_MAX_TILE_AREA (4096 * 2304) + +// Pixels per Mode Info (MI) unit +#define AV1_MI_SIZE_LOG2 2 + +#define AV1_PREDICTION_PROBS 3 +#define AV1_MBSKIP_CONTEXTS 3 +#define AV1_MAX_MODE_LF_DELTAS 2 + +#define AV1_SWITCHABLE_FILTERS 3 /* number of switchable filters */ +#define AV1_SWITCHABLE_FILTER_CONTEXTS ((AV1_SWITCHABLE_FILTERS + 1) * 4) + +#define AV1_INTER_MODE_CONTEXTS 15 + +#define AV1_CFL_JOINT_SIGNS 8 +#define AV1_CFL_ALPHA_CONTEXTS 6 +#define AV1_CFL_ALPHABET_SIZE 16 + +#define AV1_NEWMV_MODE_CONTEXTS 6 +#define AV1_ZEROMV_MODE_CONTEXTS 2 +#define AV1_GLOBALMV_MODE_CONTEXTS 2 +#define AV1_REFMV_MODE_CONTEXTS 9 +#define AV1_DRL_MODE_CONTEXTS 3 +#define AV1_INTRA_INTER_CONTEXTS 4 +#define AV1_COMP_INTER_CONTEXTS 5 +#define AV1_REF_CONTEXTS 3 +#define AV1_FWD_REFS 4 +#define AV1_BWD_REFS 3 +#define AV1_SINGLE_REFS 7 + +#define AV1_INTERINTRA_MODES 4 +#define INTER_COMPOUND_MODES 8 +#define AV1_COMPOUND_TYPES 3 + +#define AV1_BLOCK_SIZE_GROUPS 4 + +// AV1 extended transforms (ext_tx) +#define AV1_EXTTX_SIZES 4 // ext_tx experiment tx sizes +#define AV1_EXT_TX_TYPES 16 + +// Frame Restoration types (section 6.10.15) +enum { + AV1_RESTORE_NONE = 0, + AV1_RESTORE_WIENER = 1, + AV1_RESTORE_SGRPROJ = 2, + AV1_RESTORE_SWITCHABLE = 3, +}; + +// Frame types (section 6.8.2). +enum { + AV1_FRAME_KEY = 0, + AV1_FRAME_INTER = 1, + AV1_FRAME_INTRA_ONLY = 2, + AV1_FRAME_SWITCH = 3, +}; + +#define AV1_MAX_SEGMENTS 8 +enum Av1SegLevelFeatures { + AV1_SEG_LVL_ALT_Q = 0, // Use alternate Quantizer .... + AV1_SEG_LVL_ALT_LF_Y_V = 1, // Use alternate loop filter value on y plane + // vertical + AV1_SEG_LVL_ALT_LF_Y_H = 2, // Use alternate loop filter value on y plane + // horizontal + AV1_SEG_LVL_ALT_LF_U = 3, // Use alternate loop filter value on u plane + AV1_SEG_LVL_ALT_LF_V = 4, // Use alternate loop filter value on v plane + AV1_SEG_LVL_REF_FRAME = 5, // Optional Segment reference frame + AV1_SEG_LVL_SKIP = 6, // Optional Segment (0,0) + skip mode + AV1_SEG_LVL_GLOBALMV = 7, + AV1_SEG_LVL_MAX = 8 +}; + +#define AV1_ACTIVE_REFS_EX 7 +#define AV1_REF_LIST_SIZE 8 +#define AV1_REF_SCALE_SHIFT 14 + +enum Av1MvReferenceFrame { + AV1_REF_NONE = -1, + AV1_REF_FRAME_INTRA = 0, + AV1_REF_FRAME_LAST = 1, + AV1_REF_FRAME_LAST2 = 2, + AV1_REF_FRAME_LAST3 = 3, + AV1_REF_FRAME_GOLDEN = 4, + AV1_REF_FRAME_BWDREF = 5, + AV1_REF_FRAME_ALTREF2 = 6, + AV1_REF_FRAME_ALTREF = 7, + AV1_NUM_REF_FRAMES = 8, + + AV1_REFS_PER_FRAME = 7, + AV1_TOTAL_REFS_PER_FRAME = 8, + AV1_PRIMARY_REF_NONE = 7, +}; + +enum Av1BlockSizeType { + AV1_BLOCK_SIZE_AB4X4 = 0, + AV1_BLOCK_SIZE_SB4X8 = 1, + AV1_BLOCK_SIZE_SB8X4 = 2, + AV1_BLOCK_SIZE_SB8X8 = 3, + AV1_BLOCK_SIZE_SB8X16 = 4, + AV1_BLOCK_SIZE_SB16X8 = 5, + AV1_BLOCK_SIZE_MB16X16 = 6, + AV1_BLOCK_SIZE_SB16X32 = 7, + AV1_BLOCK_SIZE_SB32X16 = 8, + AV1_BLOCK_SIZE_SB32X32 = 9, + AV1_BLOCK_SIZE_SB32X64 = 10, + AV1_BLOCK_SIZE_SB64X32 = 11, + AV1_BLOCK_SIZE_SB64X64 = 12, + AV1_BLOCK_SIZE_SB64X128 = 13, + AV1_BLOCK_SIZE_SB128X64 = 14, + AV1_BLOCK_SIZE_SB128X128 = 15, + AV1_BLOCK_SIZE_SB4X16 = 16, + AV1_BLOCK_SIZE_SB16X4 = 17, + AV1_BLOCK_SIZE_SB8X32 = 18, + AV1_BLOCK_SIZE_SB32X8 = 19, + AV1_BLOCK_SIZE_SB16X64 = 20, + AV1_BLOCK_SIZE_SB64X16 = 21, + AV1_BLOCK_SIZES_ALL = 22 +}; + +enum Av1FrameType { + AV1_KEY_FRAME = 0, + AV1_INTER_FRAME = 1, + AV1_INTRA_ONLY_FRAME = 2, // replaces intra-only + AV1_S_FRAME = 3, + AV1_NUM_FRAME_TYPES = 4, +}; + +#define AV1_INTRA_MODES 13 +#define AV1_DIRECTIONAL_MODES 8 +#define AV1_MAX_ANGLE_DELTA 3 + +enum Av1FilterIntraModeType { + AV1_FILTER_DC_PRED = 0, + AV1_FILTER_V_PRED = 1, + AV1_FILTER_H_PRED = 2, + AV1_FILTER_D153_PRED = 3, + AV1_FILTER_PAETH_PRED = 4, + AV1_FILTER_INTRA_MODES = 5, + + AV1_FILTER_INTRA_UNUSED = 7 +}; + +#define AV1_TX_SIZE_CONTEXTS 3 +#define AV1_VARTX_PART_CONTEXTS 22 +#define AV1_TXFM_PARTITION_CONTEXTS 22 + +enum InterpolationFilterType { + AV1_INTERP_EIGHTTAP_SMOOTH = 0, + AV1_INTERP_EIGHTTAP = 1, + AV1_INTERP_EIGHTTAP_SHARP = 2, + AV1_INTERP_BILINEAR = 3, + AV1_INTERP_SWITCHABLE = 4, // should be the last one +}; + +enum Av1TxfmMode { + AV1_ONLY_4X4 = 0, + AV1_TX_MODE_LARGEST = 1, + AV1_TX_MODE_SELECT = 2, + AV1_NB_TXFM_MODES = 3, +}; + +#define AV1_MAX_TX_DEPTH 2 + +#define AV1_CDF_SIZE(x) ((x)-1) + +#define AV1_PALETTE_BLOCK_SIZES 7 +#define AV1_PALETTE_SIZES 7 +#define AV1_PALETTE_Y_MODE_CONTEXTS 3 +#define AV1_PALETTE_UV_MODE_CONTEXTS 2 +#define AV1_PALETTE_IDX_CONTEXTS 18 +#define AV1_KF_MODE_CONTEXTS 5 + +#define AV1_PLANE_TYPES 2 +#define AV1_TX_SIZES 5 +#define AV1_TXB_SKIP_CONTEXTS 13 +#define AV1_DC_SIGN_CONTEXTS 3 +#define AV1_SIG_COEF_CONTEXTS_EOB 4 +#define AV1_SIG_COEF_CONTEXTS 42 + +#define AV1_EOB_COEF_CONTEXTS 9 +#define AV1_LEVEL_CONTEXTS 21 +#define AV1_NUM_BASE_LEVELS 2 +#define AV1_BR_CDF_SIZE 4 +#define AV1_MOTION_MODES 3 +#define AV1_DELTA_Q_PROBS 3 +#define AV1_COMP_REF_TYPE_CONTEXTS 5 +#define AV1_UNI_COMP_REF_CONTEXTS 3 +#define AV1_UNIDIR_COMP_REFS 4 + +#define AV1_SKIP_MODE_CONTEXTS 3 +#define AV1_SKIP_CONTEXTS 3 +#define AV1_COMP_INDEX_CONTEXTS 6 +#define AV1_COMP_GROUP_IDX_CONTEXTS 7 +#define AV1_MAX_TX_CATS 4 +#define AV1_CFL_ALLOWED_TYPES 2 +#define AV1_UV_INTRA_MODES 14 + +#define AV1_DELTA_LF_PROBS 3 +#define AV1_FRAME_LF_COUNT 4 + +#define AV1_TOKEN_CDF_Q_CTXS 4 +#define AV1_SEG_TEMPORAL_PRED_CTXS 3 +#define AV1_SPATIAL_PREDICTION_PROBS 3 + +typedef struct { + RK_U16 joint_cdf[3]; + RK_U16 sign_cdf[2]; + RK_U16 clsss_cdf[2][10]; + RK_U16 clsss0_fp_cdf[2][2][3]; + RK_U16 fp_cdf[2][3]; + RK_U16 class0_hp_cdf[2]; + RK_U16 hp_cdf[2]; + RK_U16 class0_cdf[2]; + RK_U16 bits_cdf[2][10]; +} Av1MvCDFs; + +typedef struct { + RK_U16 partition_cdf[13][16]; + // 64 + RK_U16 kf_ymode_cdf[AV1_KF_MODE_CONTEXTS][AV1_KF_MODE_CONTEXTS][AV1_CDF_SIZE(AV1_INTRA_MODES)]; + RK_U16 segment_pred_cdf[AV1_PREDICTION_PROBS]; + RK_U16 spatial_pred_seg_tree_cdf[AV1_SPATIAL_PREDICTION_PROBS][AV1_CDF_SIZE(AV1_MAX_SEGMENTS)]; + RK_U16 mbskip_cdf[AV1_MBSKIP_CONTEXTS]; + RK_U16 delta_q_cdf[AV1_DELTA_Q_PROBS]; + RK_U16 delta_lf_multi_cdf[AV1_FRAME_LF_COUNT][AV1_DELTA_LF_PROBS]; + RK_U16 delta_lf_cdf[AV1_DELTA_LF_PROBS]; + RK_U16 skip_mode_cdf[AV1_SKIP_MODE_CONTEXTS]; + RK_U16 vartx_part_cdf[AV1_VARTX_PART_CONTEXTS][1]; + RK_U16 tx_size_cdf[AV1_MAX_TX_CATS][AV1_TX_SIZE_CONTEXTS][AV1_MAX_TX_DEPTH]; + RK_U16 if_ymode_cdf[AV1_BLOCK_SIZE_GROUPS][AV1_CDF_SIZE(AV1_INTRA_MODES)]; + RK_U16 uv_mode_cdf[2][AV1_INTRA_MODES][AV1_CDF_SIZE(AV1_UV_INTRA_MODES)]; + RK_U16 intra_inter_cdf[AV1_INTRA_INTER_CONTEXTS]; + RK_U16 comp_inter_cdf[AV1_COMP_INTER_CONTEXTS]; + RK_U16 single_ref_cdf[AV1_REF_CONTEXTS][AV1_SINGLE_REFS - 1]; + RK_U16 comp_ref_type_cdf[AV1_COMP_REF_TYPE_CONTEXTS][1]; + RK_U16 uni_comp_ref_cdf[AV1_UNI_COMP_REF_CONTEXTS][AV1_UNIDIR_COMP_REFS - 1][AV1_CDF_SIZE(2)]; + RK_U16 comp_ref_cdf[AV1_REF_CONTEXTS][AV1_FWD_REFS - 1]; + RK_U16 comp_bwdref_cdf[AV1_REF_CONTEXTS][AV1_BWD_REFS - 1]; + RK_U16 newmv_cdf[AV1_NEWMV_MODE_CONTEXTS]; + RK_U16 zeromv_cdf[AV1_ZEROMV_MODE_CONTEXTS]; + RK_U16 refmv_cdf[AV1_REFMV_MODE_CONTEXTS]; + RK_U16 drl_cdf[AV1_DRL_MODE_CONTEXTS]; + RK_U16 interp_filter_cdf[AV1_SWITCHABLE_FILTER_CONTEXTS][AV1_CDF_SIZE(AV1_SWITCHABLE_FILTERS)]; + + Av1MvCDFs mv_cdf; + + RK_U16 obmc_cdf[AV1_BLOCK_SIZES_ALL]; + RK_U16 motion_mode_cdf[AV1_BLOCK_SIZES_ALL][2]; + + RK_U16 inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS][AV1_CDF_SIZE(INTER_COMPOUND_MODES)]; + RK_U16 compound_type_cdf[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(AV1_COMPOUND_TYPES - 1)]; + RK_U16 interintra_cdf[AV1_BLOCK_SIZE_GROUPS]; + RK_U16 interintra_mode_cdf[AV1_BLOCK_SIZE_GROUPS][AV1_CDF_SIZE(AV1_INTERINTRA_MODES)]; + RK_U16 wedge_interintra_cdf[AV1_BLOCK_SIZES_ALL]; + RK_U16 wedge_idx_cdf[AV1_BLOCK_SIZES_ALL][AV1_CDF_SIZE(16)]; + + RK_U16 palette_y_mode_cdf[AV1_PALETTE_BLOCK_SIZES][AV1_PALETTE_Y_MODE_CONTEXTS][1]; + RK_U16 palette_uv_mode_cdf[AV1_PALETTE_UV_MODE_CONTEXTS][1]; + RK_U16 palette_y_size_cdf[AV1_PALETTE_BLOCK_SIZES][AV1_CDF_SIZE(AV1_PALETTE_SIZES)]; + RK_U16 palette_uv_size_cdf[AV1_PALETTE_BLOCK_SIZES][AV1_CDF_SIZE(AV1_PALETTE_SIZES)]; + + RK_U16 cfl_sign_cdf[AV1_CDF_SIZE(AV1_CFL_JOINT_SIGNS)]; + RK_U16 cfl_alpha_cdf[AV1_CFL_ALPHA_CONTEXTS][AV1_CDF_SIZE(AV1_CFL_ALPHABET_SIZE)]; + + RK_U16 intrabc_cdf[1]; + RK_U16 angle_delta_cdf[AV1_DIRECTIONAL_MODES][AV1_CDF_SIZE(2 * AV1_MAX_ANGLE_DELTA + 1)]; + + RK_U16 filter_intra_mode_cdf[AV1_CDF_SIZE(AV1_FILTER_INTRA_MODES)]; + RK_U16 filter_intra_cdf[AV1_BLOCK_SIZES_ALL]; + RK_U16 comp_group_idx_cdf[AV1_COMP_GROUP_IDX_CONTEXTS][AV1_CDF_SIZE(2)]; + RK_U16 compound_idx_cdf[AV1_COMP_INDEX_CONTEXTS][AV1_CDF_SIZE(2)]; + + RK_U16 dummy0[14]; + + // Palette index contexts; sizes 1/7, 2/6, 3/5 packed together + RK_U16 palette_y_color_index_cdf[AV1_PALETTE_IDX_CONTEXTS][8]; + RK_U16 palette_uv_color_index_cdf[AV1_PALETTE_IDX_CONTEXTS][8]; + // RK_U16 dummy1[0]; + + // Note: cdf space can be optimized (most sets have fewer than EXT_TX_TYPES symbols) + RK_U16 tx_type_intra0_cdf[AV1_EXTTX_SIZES][AV1_INTRA_MODES][8]; + RK_U16 tx_type_intra1_cdf[AV1_EXTTX_SIZES][AV1_INTRA_MODES][4]; + RK_U16 tx_type_inter_cdf[2][AV1_EXTTX_SIZES][AV1_EXT_TX_TYPES]; + + RK_U16 txb_skip_cdf[AV1_TX_SIZES][AV1_TXB_SKIP_CONTEXTS][AV1_CDF_SIZE(2)]; + RK_U16 eob_extra_cdf[AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_EOB_COEF_CONTEXTS][AV1_CDF_SIZE(2)]; + RK_U16 dummy_[5]; + + RK_U16 eob_flag_cdf16[AV1_PLANE_TYPES][2][4]; + RK_U16 eob_flag_cdf32[AV1_PLANE_TYPES][2][8]; + RK_U16 eob_flag_cdf64[AV1_PLANE_TYPES][2][8]; + RK_U16 eob_flag_cdf128[AV1_PLANE_TYPES][2][8]; + RK_U16 eob_flag_cdf256[AV1_PLANE_TYPES][2][8]; + RK_U16 eob_flag_cdf512[AV1_PLANE_TYPES][2][16]; + RK_U16 eob_flag_cdf1024[AV1_PLANE_TYPES][2][16]; + RK_U16 coeff_base_eob_cdf[AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_SIG_COEF_CONTEXTS_EOB][AV1_CDF_SIZE(3)]; + RK_U16 coeff_base_cdf[AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_SIG_COEF_CONTEXTS][AV1_CDF_SIZE(4) + 1]; + RK_U16 dc_sign_cdf[AV1_PLANE_TYPES][AV1_DC_SIGN_CONTEXTS][AV1_CDF_SIZE(2)]; + RK_U16 dummy_2[2]; + RK_U16 coeff_br_cdf[AV1_TX_SIZES][AV1_PLANE_TYPES][AV1_LEVEL_CONTEXTS][AV1_CDF_SIZE(AV1_BR_CDF_SIZE) + 1]; + RK_U16 dummy2[16]; +} AV1CDFs; + +typedef struct { + RK_U8 scaling_lut_y[256]; + RK_U8 scaling_lut_cb[256]; + RK_U8 scaling_lut_cr[256]; + RK_S16 cropped_luma_grain_block[4096]; + RK_S16 cropped_chroma_grain_block[1024 * 2]; +} AV1FilmGrainMemory; + +#endif // AV1COMMONDEC_H diff --git a/mpp/common/av1d_syntax.h b/mpp/common/av1d_syntax.h new file mode 100644 index 000000000..c9f281e35 --- /dev/null +++ b/mpp/common/av1d_syntax.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef AV1D_SYNTAX_H +#define AV1D_SYNTAX_H + +#include "av1d_common.h" + +typedef struct DXVA_PicEntry_AV1_t { + union { + struct { + RK_U8 Index7Bits : 7; + RK_U8 AssociatedFlag : 1; + }; + RK_U8 bPicEntry; + }; +} DXVA_PicEntry_AV1, *LPDXVA_PicEntry_AV1; + +typedef struct DXVA_PicParams_AV1_t { + DXVA_PicEntry_AV1 CurrPic; + RK_U16 width ; + RK_U16 height ; + RK_U16 max_width ; + RK_U16 max_height ; + RK_U16 CurrPicTextureIndex ; + RK_U16 use_superres ; + RK_U16 superres_denom ; + RK_U16 bitdepth ; + RK_U16 seq_profile ; + RK_U16 frame_header_size ; + union { + struct { + RK_U32 current_operating_point : 12; + RK_U32 use_128x128_superblock : 1; + RK_U32 intra_edge_filter : 1; + RK_U32 interintra_compound : 1; + RK_U32 masked_compound : 1; + RK_U32 warped_motion : 1; + RK_U32 dual_filter : 1; + RK_U32 jnt_comp : 1; + RK_U32 screen_content_tools : 1; + RK_U32 integer_mv : 2; + RK_U32 cdef_en : 1; + RK_U32 restoration : 1; + RK_U32 film_grain_en : 1; + RK_U32 intrabc : 1; + RK_U32 high_precision_mv : 1; + RK_U32 switchable_motion_mode : 1; + RK_U32 filter_intra : 1; + RK_U32 disable_frame_end_update_cdf : 1; + RK_U32 disable_cdf_update : 1; + RK_U32 reference_mode : 1; + RK_U32 skip_mode : 1; + RK_U32 reduced_tx_set : 1; + RK_U32 superres : 1; + RK_U32 tx_mode : 3; + RK_U32 use_ref_frame_mvs : 1; + RK_U32 enable_ref_frame_mvs : 1; + RK_U32 reference_frame_update : 1; + RK_U32 error_resilient_mode : 1; + } coding; + }; + + struct { + RK_U16 cols; + RK_U16 rows; + RK_U16 context_update_id; + RK_U16 widths[64]; + RK_U16 heights[64]; + RK_U32 tile_offset_start[128]; + RK_U32 tile_offset_end[128]; + RK_U8 tile_sz_mag; + } tiles; + + struct { + RK_U8 frame_type ; + RK_U8 show_frame ; + RK_U8 showable_frame; + RK_U8 subsampling_x ; + RK_U8 subsampling_y ; + RK_U8 mono_chrome ; + } format; + + RK_U8 primary_ref_frame; + RK_U8 enable_order_hint; + RK_U8 order_hint; + RK_U8 order_hint_bits; + + struct { + RK_U8 filter_level[2] ; + RK_U8 filter_level_u ; + RK_U8 filter_level_v ; + RK_U8 sharpness_level ; + RK_U8 mode_ref_delta_enabled ; + RK_U8 mode_ref_delta_update ; + RK_U8 delta_lf_multi ; + RK_U8 delta_lf_present ; + RK_U8 delta_lf_res ; + RK_S8 ref_deltas[8] ; + RK_S8 mode_deltas[2] ; + RK_U8 frame_restoration_type[3] ; + RK_U8 log2_restoration_unit_size[3]; + } loop_filter; + + struct { + RK_U8 delta_q_present; + RK_U8 delta_q_res ; + RK_U8 base_qindex ; + RK_S8 y_dc_delta_q ; + RK_S8 u_dc_delta_q ; + RK_S8 v_dc_delta_q ; + RK_S8 u_ac_delta_q ; + RK_S8 v_ac_delta_q ; + RK_S8 using_qmatrix ; + RK_U8 qm_y ; + RK_U8 qm_u ; + RK_U8 qm_v ; + } quantization; + + struct { + RK_U8 damping; + RK_U8 bits; + + struct { + RK_U8 primary; + RK_U8 secondary; + } y_strengths[8]; + struct { + RK_U8 primary; + RK_U8 secondary; + } uv_strengths[8]; + } cdef; + + struct { + RK_U8 enabled ; + RK_U8 update_map ; + RK_U8 update_data ; + RK_U8 temporal_update ; + RK_U8 feature_mask[8] ; + RK_S32 feature_data[8][8] ; + RK_U8 last_active ; + RK_U8 preskip ; + } segmentation; + + struct { + RK_U8 apply_grain ; + RK_U8 scaling_shift_minus8 ; + RK_U8 chroma_scaling_from_luma ; + RK_U8 ar_coeff_lag ; + RK_U8 ar_coeff_shift_minus6 ; + RK_U8 grain_scale_shift ; + RK_U8 overlap_flag ; + RK_U8 clip_to_restricted_range ; + RK_U8 matrix_coefficients ; + RK_U8 matrix_coeff_is_identity ; + RK_U8 num_y_points ; + RK_U8 num_cb_points ; + RK_U8 num_cr_points ; + RK_U8 scaling_points_y[14][2] ; + RK_U8 scaling_points_cb[10][2] ; + RK_U8 scaling_points_cr[10][2] ; + RK_U8 ar_coeffs_y[24] ; + RK_U8 ar_coeffs_cb[25] ; + RK_U8 ar_coeffs_cr[25] ; + RK_U8 cb_mult ; + RK_U8 cb_luma_mult ; + RK_U8 cr_mult ; + RK_U8 cr_luma_mult ; + + RK_U16 grain_seed ; + RK_U16 update_grain ; + RK_U16 cb_offset ; + RK_U16 cr_offset ; + } film_grain; + + RK_U32 ref_frame_valued; + RK_U32 ref_frame_idx[7]; + + RK_U32 ref_order_hint[8]; + struct { + RK_U32 width; + RK_U32 height; + RK_U32 order_hint; + RK_U32 lst_frame_offset; + RK_U32 lst2_frame_offset; + RK_U32 lst3_frame_offset; + RK_U32 gld_frame_offset; + RK_U32 bwd_frame_offset; + RK_U32 alt2_frame_offset; + RK_U32 alt_frame_offset; + RK_U32 is_intra_frame; + RK_U32 intra_only; + RK_S8 Index; + RK_U8 wminvalid; + RK_U8 wmtype; + RK_S32 wmmat[6]; + RK_S32 wmmat_val[6]; + RK_U16 alpha, beta, gamma, delta; + } frame_refs[8]; + + struct { + RK_S32 valid; // RefValid + RK_S32 frame_id; // RefFrameId + RK_S32 upscaled_width; // RefUpscaledWidth + RK_S32 frame_width; // RefFrameWidth + RK_S32 frame_height; // RefFrameHeight + RK_S32 render_width; // RefRenderWidth + RK_S32 render_height; // RefRenderHeight + RK_S32 frame_type; // RefFrameType + RK_S32 subsampling_x; // RefSubsamplingX + RK_S32 subsampling_y; // RefSubsamplingY + RK_S32 bit_depth; // RefBitDepth + RK_S32 order_hint; // RefOrderHint + } frame_ref_state[8]; + + RK_U8 ref_frame_sign_bias[8]; + + RK_U8 coded_lossless; + RK_S32 all_lossless; + RK_U8 interp_filter; + RK_U8 RefFrameMapTextureIndex[8]; + RK_U32 upscaled_width; + RK_U32 frame_to_show_map_idx; + RK_U32 show_existing_frame; + RK_U32 frame_tag_size; + RK_U32 offset_to_dct_parts; + RK_U8 skip_ref0; + RK_U8 skip_ref1; + RK_U8 refresh_frame_flags; + void *cdfs; + void *cdfs_ndvc; + RK_U8 tile_cols_log2; + RK_U8 tile_rows_log2; +} DXVA_PicParams_AV1, *LPDXVA_PicParams_AV1; + +typedef struct DXVA_Slice_AV1_Short_t { + RK_U32 BSNALunitDataLocation; + RK_U32 SliceByteInBuffer; + RK_U16 wBadSliceChopping; +} DXVA_Slice_AV1_Short, *LPDXVA_Slice_AV1_Short; + +#endif diff --git a/mpp/common/avs2d_syntax.h b/mpp/common/avs2d_syntax.h new file mode 100644 index 000000000..ed0d68d50 --- /dev/null +++ b/mpp/common/avs2d_syntax.h @@ -0,0 +1,91 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AVS2D_SYNTAX_H +#define AVS2D_SYNTAX_H + +#include "rk_type.h" + +//!< avs2 decoder picture parameters structure +typedef struct DXVA_PicParams_AVS2_t { + //!< sequence header + RK_U32 chroma_format_idc : 2; + RK_U32 pic_width_in_luma_samples : 16; + RK_U32 pic_height_in_luma_samples : 16; + RK_U32 bit_depth_luma_minus8 : 3; + RK_U32 bit_depth_chroma_minus8 : 3; + RK_U32 lcu_size : 3; + RK_U32 progressive_sequence : 1; + RK_U32 field_coded_sequence : 1; + RK_U32 multi_hypothesis_skip_enable_flag : 1; + RK_U32 dual_hypothesis_prediction_enable_flag : 1; + RK_U32 weighted_skip_enable_flag : 1; + RK_U32 asymmetrc_motion_partitions_enable_flag : 1; + RK_U32 nonsquare_quadtree_transform_enable_flag : 1; + RK_U32 nonsquare_intra_prediction_enable_flag : 1; + RK_U32 secondary_transform_enable_flag : 1; + RK_U32 sample_adaptive_offset_enable_flag : 1; + RK_U32 adaptive_loop_filter_enable_flag : 1; + RK_U32 pmvr_enable_flag : 1; + RK_U32 cross_slice_loopfilter_enable_flag : 1; + //!< picture header + RK_U32 picture_type : 3; + RK_U32 scene_reference_enable_flag : 1; + RK_U32 bottom_field_picture_flag : 1; + RK_U32 fixed_picture_qp : 1; + RK_U32 picture_qp : 7; + RK_U32 loop_filter_disable_flag : 1; + RK_S8 alpha_c_offset; //!< 5bits signed + RK_S8 beta_offset; //!< 5bits signed + RK_S32 cur_poc; +} PicParams_Avs2d, *LP_PicParams_Avs2d; + +typedef struct DXVA_RefParams_AVS2_t { + RK_U8 ref_pic_num; + RK_S32 ref_poc_list[32]; + RK_S32 scene_ref_slot_idx; + RK_S32 scene_ref_enable; + RK_S32 scene_ref_replace_pos; +} RefParams_Avs2d, *LP_RefParams_Avs2d; + +typedef struct DXVA_AlfParams_AVS2_t { + RK_U8 enable_pic_alf_y; //!< 1bits + RK_U8 enable_pic_alf_cb; //!< 1bits + RK_U8 enable_pic_alf_cr; //!< 1bits + RK_U8 alf_filter_num_minus1; //!< 4bits + RK_U8 alf_coeff_idx_tab[16]; + RK_S32 alf_coeff_y[16][9]; + RK_S32 alf_coeff_cb[9]; + RK_S32 alf_coeff_cr[9]; +} AlfParams_Avs2d, *LP_AlfParams_Avs2d; + +typedef struct DXVA_WqmParams_AVS2_t { + RK_U8 pic_weight_quant_enable_flag; + RK_S8 chroma_quant_param_delta_cb; //!< 6bits + RK_S8 chroma_quant_param_delta_cr; //!< 6bits + RK_U32 wq_matrix[2][64]; +} WqmParams_Avs2d, *LP_WqmParams_Avs2d; + +typedef struct avs2d_syntax_t { + PicParams_Avs2d pp; + RefParams_Avs2d refp; + AlfParams_Avs2d alfp; + WqmParams_Avs2d wqmp; + RK_U8 *bitstream; + RK_U32 bitstream_size; +} Avs2dSyntax_t; + +#endif /* AVS2D_SYNTAX_H */ diff --git a/mpp/common/avsd_syntax.h b/mpp/common/avsd_syntax.h new file mode 100644 index 000000000..69816df8b --- /dev/null +++ b/mpp/common/avsd_syntax.h @@ -0,0 +1,100 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AVSD_SYNTAX_H +#define AVSD_SYNTAX_H + +#include "rk_type.h" + + +//!< cavs decoder picture parameters structure +typedef struct PicParams_Avsd_t { + //!< sequence header + RK_U32 profileId; + RK_U32 levelId; + RK_U32 progressiveSequence; + RK_U32 horizontalSize; + RK_U32 verticalSize; + RK_U32 chromaFormat; + RK_U32 aspectRatio; + RK_U32 frameRateCode; + RK_U32 bitRateValue; + RK_U32 lowDelay; + RK_U32 bbvBufferSize; + //!< sequence display extension header + RK_U32 videoFormat; + RK_U32 sampleRange; + RK_U32 colorDescription; + RK_U32 colorPrimaries; + RK_U32 transferCharacteristics; + RK_U32 matrixCoefficients; + RK_U32 displayHorizontalSize; + RK_U32 displayVerticalSize; + + //!< picture header + RK_U32 picCodingType; + RK_U32 bbvDelay; + RK_U16 bbvDelayExtension; + RK_U8 timeCodeFlag; + RK_U32 timeCode; + + RK_U32 pictureDistance; + RK_U32 progressiveFrame; + RK_U32 pictureStructure; + RK_U32 advancedPredModeDisable; + RK_U32 topFieldFirst; + RK_U32 repeatFirstField; + RK_U32 fixedPictureQp; + RK_U32 pictureQp; + RK_U32 pictureReferenceFlag; + RK_U32 skipModeFlag; + RK_U32 loopFilterDisable; + RK_S32 alphaOffset; + RK_S32 betaOffset; + + //!< weighting quant, AVS Plus stuff + RK_U32 weightingQuantFlag; + RK_U32 chromaQuantParamDisable; + RK_S32 chromaQuantParamDeltaCb; + RK_S32 chromaQuantParamDeltaCr; + RK_U32 weightingQuantParamIndex; + RK_U32 weightingQuantModel; + RK_S32 weightingQuantParamDelta1[6]; + RK_S32 weightingQuantParamDelta2[6]; + RK_U32 weightingQuantParam[6]; // wqP[m][6] + + //!< advance entropy coding + RK_U32 aecEnable; + + //!< picture enhance + RK_U32 noForwardReferenceFlag; + RK_U32 pbFieldEnhancedFlag; + +} PicParams_Avsd, *LP_PicParams_Avsd; + + + +typedef struct avsd_syntax_t { + PicParams_Avsd pp; + RK_U8 *bitstream; + RK_U32 bitstream_offset; + RK_U32 bitstream_size; +} AvsdSyntax_t; + + + +#endif /* AVSD_SYNTAX_H */ + diff --git a/mpp/common/dxva_syntax.h b/mpp/common/dxva_syntax.h index c48c8687f..8e38a828a 100644 --- a/mpp/common/dxva_syntax.h +++ b/mpp/common/dxva_syntax.h @@ -1,70 +1,58 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __DXVA_SYNTAX_H__ -#define __DXVA_SYNTAX_H__ - -#include "rk_type.h" - -enum __MIDL___MIDL_itf_dxva2api_0000_0000_0012 { - DXVA2_PictureParametersBufferType = 0, - DXVA2_MacroBlockControlBufferType = 1, - DXVA2_ResidualDifferenceBufferType = 2, - DXVA2_DeblockingControlBufferType = 3, - DXVA2_InverseQuantizationMatrixBufferType = 4, - DXVA2_SliceControlBufferType = 5, - DXVA2_BitStreamDateBufferType = 6, - DXVA2_MotionVectorBuffer = 7, - DXVA2_FilmGrainBuffer = 8 -}; - -typedef struct _DXVA2_ConfigPictureDecode { - //GUID guidConfigBitstreamEncryption; - //GUID guidConfigMBcontrolEncryption; - //GUID guidConfigResidDiffEncryption; - RK_U32 ConfigBitstreamRaw; - //UINT ConfigMBcontrolRasterOrder; - //UINT ConfigResidDiffHost; - //UINT ConfigSpatialResid8; - //UINT ConfigResid8Subtraction; - //UINT ConfigSpatialHost8or9Clipping; - //UINT ConfigSpatialResidInterleaved; - //UINT ConfigIntraResidUnsigned; - //UINT ConfigResidDiffAccelerator; - //UINT ConfigHostInverseScan; - //UINT ConfigSpecificIDCT; - //UINT Config4GroupedCoefs; - //USHORT ConfigMinRenderTargetBuffCount; - //USHORT ConfigDecoderSpecific; -} DXVA2_ConfigPictureDecode; - -typedef struct _DXVA2_DecodeBufferDesc { - RK_U32 CompressedBufferType; - RK_U32 BufferIndex; - RK_U32 DataOffset; - RK_U32 DataSize; - RK_U32 FirstMBaddress; - RK_U32 NumMBsInBuffer; - RK_U32 Width; - RK_U32 Height; - RK_U32 Stride; - RK_U32 ReservedBits; - void *pvPVPState; -} DXVA2_DecodeBufferDesc; - -#endif /*__DXVA_SYNTAX_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef DXVA_SYNTAX_H +#define DXVA_SYNTAX_H + +#include "rk_type.h" + +enum MIDL___MIDL_itf_dxva2_e { + DXVA2_PictureParametersBufferType = 0, + DXVA2_MacroBlockControlBufferType = 1, + DXVA2_ResidualDifferenceBufferType = 2, + DXVA2_DeblockingControlBufferType = 3, + DXVA2_InverseQuantizationMatrixBufferType = 4, + DXVA2_SliceControlBufferType = 5, + DXVA2_BitStreamDateBufferType = 6, + DXVA2_MotionVectorBuffer = 7, + DXVA2_FilmGrainBuffer = 8 +}; + +typedef struct DXVA2_ConfigPictureDecode_t { + //GUID guidConfigBitstreamEncryption; + //GUID guidConfigMBcontrolEncryption; + //GUID guidConfigResidDiffEncryption; + RK_U32 ConfigBitstreamRaw; + //RK_U32 ConfigMBcontrolRasterOrder; + //RK_U32 ConfigResidDiffHost; + //RK_U32 ConfigSpatialResid8; + //RK_U32 ConfigResid8Subtraction; + //RK_U32 ConfigSpatialHost8or9Clipping; + //RK_U32 ConfigSpatialResidInterleaved; + //RK_U32 ConfigIntraResidUnsigned; + //RK_U32 ConfigResidDiffAccelerator; + //RK_U32 ConfigHostInverseScan; + //RK_U32 ConfigSpecificIDCT; + //RK_U32 Config4GroupedCoefs; + //RK_U16 ConfigMinRenderTargetBuffCount; + //RK_U16 ConfigDecoderSpecific; +} DXVA2_ConfigPictureDecode; + +typedef struct DXVA2_DecodeBufferDesc_t { + RK_U32 CompressedBufferType; + RK_U32 BufferIndex; + RK_U32 DataOffset; + RK_U32 DataSize; + RK_U32 FirstMBaddress; + RK_U32 NumMBsInBuffer; + RK_U32 Width; + RK_U32 Height; + RK_U32 Stride; + RK_U32 ReservedBits; + void *pvPVPState; +} DXVA2_DecodeBufferDesc; + +#endif /* DXVA_SYNTAX_H */ + diff --git a/mpp/common/h263d_syntax.h b/mpp/common/h263d_syntax.h new file mode 100644 index 000000000..721d2347e --- /dev/null +++ b/mpp/common/h263d_syntax.h @@ -0,0 +1,98 @@ +/* + * + * Copyright 2010 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H263D_SYNTAX_H +#define H263D_SYNTAX_H + +#include "dxva_syntax.h" + +/*video vop specific*/ +typedef enum { + H263_INVALID_VOP = -1, + H263_I_VOP = 0, + H263_P_VOP = 1, +} H263VOPType; + +/* H263PT2 Picture Parameter structure */ +typedef struct DXVA_PicParams_H263_t { + RK_U8 short_video_header; + RK_U8 vop_coding_type; + RK_U8 vop_quant; + RK_U16 wDecodedPictureIndex; + RK_U16 wDeblockedPictureIndex; + RK_U16 wForwardRefPictureIndex; + RK_U16 wBackwardRefPictureIndex; + RK_U16 vop_time_increment_resolution; + RK_U32 TRB[2]; + RK_U32 TRD[2]; + + union { + struct { + RK_U16 unPicPostProc : 2; + RK_U16 interlaced : 1; + RK_U16 quant_type : 1; + RK_U16 quarter_sample : 1; + RK_U16 resync_marker_disable : 1; + RK_U16 data_partitioned : 1; + RK_U16 reversible_vlc : 1; + RK_U16 reduced_resolution_vop_enable : 1; + RK_U16 vop_coded : 1; + RK_U16 vop_rounding_type : 1; + RK_U16 intra_dc_vlc_thr : 3; + RK_U16 top_field_first : 1; + RK_U16 alternate_vertical_scan_flag : 1; + }; + RK_U16 wPicFlagBitFields; + }; + RK_U8 profile_and_level_indication; + RK_U8 video_object_layer_verid; + RK_U16 vop_width; + RK_U16 vop_height; + union { + struct { + RK_U16 sprite_enable : 2; + RK_U16 no_of_sprite_warping_points : 6; + RK_U16 sprite_warping_accuracy : 2; + }; + RK_U16 wSpriteBitFields; + }; + RK_S16 warping_mv[4][2]; + union { + struct { + RK_U8 vop_fcode_forward : 3; + RK_U8 vop_fcode_backward : 3; + }; + RK_U8 wFcodeBitFields; + }; + RK_U16 StatusReportFeedbackNumber; + RK_U16 Reserved16BitsA; + RK_U16 Reserved16BitsB; + + // FIXME: added for rockchip hardware information + RK_U32 prev_coding_type; + RK_U32 header_bits; +} DXVA_PicParams_H263, *LPDXVA_PicParams_H263; + +typedef struct h263d_dxva2_picture_context { + DXVA_PicParams_H263 pp; + + // pointer and storage for buffer descriptor + DXVA2_DecodeBufferDesc *data[2]; + DXVA2_DecodeBufferDesc desc[2]; +} h263d_dxva2_picture_context_t; + +#endif /* H263D_SYNTAX_H */ diff --git a/mpp/common/h264_syntax.h b/mpp/common/h264_syntax.h new file mode 100644 index 000000000..494e015af --- /dev/null +++ b/mpp/common/h264_syntax.h @@ -0,0 +1,183 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef H264_SYNTAX_H +#define H264_SYNTAX_H + +/* H.264/AVC-specific definition */ + +//!< define +#define MAXSPS 32 +#define MAXPPS 256 + +//!< aspect ratio explicitly specified as width:height +#define H264_EXTENDED_SAR 255 + +//!< values for nal_ref_idc +typedef enum H264NalRefIdcType_e { + H264_NALU_PRIORITY_DISPOSABLE = 0, + H264_NALU_PRIORITY_LOW = 1, + H264_NALU_PRIORITY_HIGH = 2, + H264_NALU_PRIORITY_HIGHEST = 3 +} H264NalRefIdcType; + +//!< AVC Profile IDC definitions +typedef enum h264e_profile_t { + H264_PROFILE_FREXT_CAVLC444 = 44, //!< YUV 4:4:4/14 "CAVLC 4:4:4" + H264_PROFILE_BASELINE = 66, //!< YUV 4:2:0/8 "Baseline" + H264_PROFILE_MAIN = 77, //!< YUV 4:2:0/8 "Main" + H264_PROFILE_EXTENDED = 88, //!< YUV 4:2:0/8 "Extended" + H264_PROFILE_HIGH = 100, //!< YUV 4:2:0/8 "High" + H264_PROFILE_HIGH10 = 110, //!< YUV 4:2:0/10 "High 10" + H264_PROFILE_HIGH422 = 122, //!< YUV 4:2:2/10 "High 4:2:2" + H264_PROFILE_HIGH444 = 244, //!< YUV 4:4:4/14 "High 4:4:4" + H264_PROFILE_MVC_HIGH = 118, //!< YUV 4:2:0/8 "Multiview High" + H264_PROFILE_STEREO_HIGH = 128 //!< YUV 4:2:0/8 "Stereo High" +} H264Profile; + +//!< AVC Level IDC definitions +typedef enum { + H264_LEVEL_1_0 = 10, //!< qcif@15fps + H264_LEVEL_1_b = 99, //!< qcif@15fps + H264_LEVEL_1_1 = 11, //!< cif@7.5fps + H264_LEVEL_1_2 = 12, //!< cif@15fps + H264_LEVEL_1_3 = 13, //!< cif@30fps + H264_LEVEL_2_0 = 20, //!< cif@30fps + H264_LEVEL_2_1 = 21, //!< half-D1@@25fps + H264_LEVEL_2_2 = 22, //!< D1@12.5fps + H264_LEVEL_3_0 = 30, //!< D1@25fps + H264_LEVEL_3_1 = 31, //!< 720p@30fps + H264_LEVEL_3_2 = 32, //!< 720p@60fps + H264_LEVEL_4_0 = 40, //!< 1080p@30fps + H264_LEVEL_4_1 = 41, //!< 1080p@30fps + H264_LEVEL_4_2 = 42, //!< 1080p@60fps + H264_LEVEL_5_0 = 50, //!< 3K@30fps + H264_LEVEL_5_1 = 51, //!< 4K@30fps + H264_LEVEL_5_2 = 52, //!< 4K@60fps + H264_LEVEL_6_0 = 60, //!< 8K@30fps + H264_LEVEL_6_1 = 61, //!< 8K@60fps + H264_LEVEL_6_2 = 62, //!< 8K@120fps +} H264Level; + +//!< values for nalu_type +typedef enum H264NaluType_e { + H264_NALU_TYPE_NULL = 0, + H264_NALU_TYPE_SLICE = 1, + H264_NALU_TYPE_DPA = 2, + H264_NALU_TYPE_DPB = 3, + H264_NALU_TYPE_DPC = 4, + H264_NALU_TYPE_IDR = 5, + H264_NALU_TYPE_SEI = 6, + H264_NALU_TYPE_SPS = 7, + H264_NALU_TYPE_PPS = 8, + H264_NALU_TYPE_AUD = 9, // Access Unit Delimiter + H264_NALU_TYPE_EOSEQ = 10, // end of sequence + H264_NALU_TYPE_EOSTREAM = 11, // end of stream + H264_NALU_TYPE_FILL = 12, + H264_NALU_TYPE_SPSEXT = 13, + H264_NALU_TYPE_PREFIX = 14, // prefix + H264_NALU_TYPE_SUB_SPS = 15, + H264_NALU_TYPE_SLICE_AUX = 19, + H264_NALU_TYPE_SLC_EXT = 20, // slice extensive + H264_NALU_TYPE_VDRD = 24, // View and Dependency Representation Delimiter NAL Unit + H264_NALU_TYPE_UNSPECIFIED28 = 28, +} H264NaluType; + +typedef enum H264ChromaFmt_e { + H264_CHROMA_400 = 0, //!< Monochrome + H264_CHROMA_420 = 1, //!< 4:2:0 + H264_CHROMA_422 = 2, //!< 4:2:2 + H264_CHROMA_444 = 3 //!< 4:4:4 +} H264ChromaFmt; + +typedef enum H264SliceType_e { + H264_P_SLICE = 0, + H264_B_SLICE = 1, + H264_I_SLICE = 2, + H264_SP_SLICE = 3, + H264_SI_SLICE = 4, + H264_NUM_SLICE_TYPES = 5 +} H264SliceType; + +//!< SEI +typedef enum H264SeiType_e { + H264_SEI_BUFFERING_PERIOD = 0, + H264_SEI_PIC_TIMING, + H264_SEI_PAN_SCAN_RECT, + H264_SEI_FILLER_PAYLOAD, + H264_SEI_USER_DATA_REGISTERED_ITU_T_T35, + H264_SEI_USER_DATA_UNREGISTERED, + H264_SEI_RECOVERY_POINT, + H264_SEI_DEC_REF_PIC_MARKING_REPETITION, + H264_SEI_SPARE_PIC, + H264_SEI_SCENE_INFO, + H264_SEI_SUB_SEQ_INFO, + H264_SEI_SUB_SEQ_LAYER_CHARACTERISTICS, + H264_SEI_SUB_SEQ_CHARACTERISTICS, + H264_SEI_FULL_FRAME_FREEZE, + H264_SEI_FULL_FRAME_FREEZE_RELEASE, + H264_SEI_FULL_FRAME_SNAPSHOT, + H264_SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START, + H264_SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END, + H264_SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET, + H264_SEI_FILM_GRAIN_CHARACTERISTICS, + H264_SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE, + H264_SEI_STEREO_VIDEO_INFO, + H264_SEI_POST_FILTER_HINTS, + H264_SEI_TONE_MAPPING, + H264_SEI_SCALABILITY_INFO, + H264_SEI_SUB_PIC_SCALABLE_LAYER, + H264_SEI_NON_REQUIRED_LAYER_REP, + H264_SEI_PRIORITY_LAYER_INFO, + H264_SEI_LAYERS_NOT_PRESENT, + H264_SEI_LAYER_DEPENDENCY_CHANGE, + H264_SEI_SCALABLE_NESTING, + H264_SEI_BASE_LAYER_TEMPORAL_HRD, + H264_SEI_QUALITY_LAYER_INTEGRITY_CHECK, + H264_SEI_REDUNDANT_PIC_PROPERTY, + H264_SEI_TL0_DEP_REP_INDEX, + H264_SEI_TL_SWITCHING_POINT, + H264_SEI_PARALLEL_DECODING_INFO, + H264_SEI_MVC_SCALABLE_NESTING, + H264_SEI_VIEW_SCALABILITY_INFO, + H264_SEI_MULTIVIEW_SCENE_INFO, + H264_SEI_MULTIVIEW_ACQUISITION_INFO, + H264_SEI_NON_REQUIRED_VIEW_COMPONENT, + H264_SEI_VIEW_DEPENDENCY_CHANGE, + H264_SEI_OPERATION_POINTS_NOT_PRESENT, + H264_SEI_BASE_VIEW_TEMPORAL_HRD, + H264_SEI_FRAME_PACKING_ARRANGEMENT, + + H264_SEI_MAX_ELEMENTS //!< number of maximum syntax elements +} H264SeiType; + +typedef enum H264ScalingListType_e { + H264_INTRA_4x4_Y, + H264_INTRA_4x4_U, + H264_INTRA_4x4_V, + H264_INTER_4x4_Y, + H264_INTER_4x4_U, + H264_INTER_4x4_V, + H264_INTRA_8x8_Y, + H264_INTER_8x8_Y, + H264_SCALING_MATRIX_TYPE_BUTT, +} H264ScalingMatrixType; + +#define H264E_MAX_REFS_CNT 16 + +#endif /* H264_SYNTAX_H */ diff --git a/mpp/common/h264d_log.h b/mpp/common/h264d_log.h deleted file mode 100644 index a0e33c146..000000000 --- a/mpp/common/h264d_log.h +++ /dev/null @@ -1,228 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#ifndef __H264D_LOG_H__ -#define __H264D_LOG_H__ - -#include -#include - -#include "rk_type.h" -#include "mpp_err.h" -#include "mpp_log.h" - -//!< undefine tag -#ifdef MODULE_TAG -#undef MODULE_TAG -#endif -//!< debug -#define __DEBUG_EN 1 -//!< return -typedef enum { - RET_FALSE = 0, - RET_TURE = 1, -} RET_tpye; - -//!< get bit value -#define GetBitVal(val, pos) ( ( (val)>>(pos) ) & 0x1 & (val) ) -//!< marco -#define ASSERT assert -#define FCLOSE(fp) do{ if(fp) fclose(fp); fp = NULL; } while (0) - -typedef enum { - LOG_LEVEL_SILENT = 0, - LOG_LEVEL_FATAL , - LOG_LEVEL_ERROR , - LOG_LEVEL_WARNNING , - LOG_LEVEL_INFO , - LOG_LEVEL_TRACE , - LOG_LEVEL_MAX , -} LogLevel_type; - -typedef enum { - LOG_DEBUG = 0, - LOG_FPGA , - LOG_PRINT , - LOG_WRITE , - RUN_PARSE , - RUN_HAL , - LOG_READ_NALU , - LOG_READ_SPS , - LOG_READ_SUBSPS , - LOG_READ_PPS , - LOG_READ_SLICE , - LOG_WRITE_SPSPPS , - LOG_WRITE_RPS , - LOG_WRITE_SCANLIST , - LOG_WRITE_STEAM , - LOG_WRITE_REG , - LOG_MAX , -} LogCtrl_type; - -typedef struct log_flag_t { - RK_U8 debug_en; - RK_U8 print_en; - RK_U8 write_en; - RK_U32 level; -} LogFlag_t; - -typedef struct log_ctx_t { - const char *tag; - LogFlag_t *flag; - FILE *fp; -} LogCtx_t; - -typedef struct log_env_str_t { - char *help; - char *show; - char *ctrl; - char *level; - char *outpath; - char *cmppath; - char *decframe; - char *begframe; - char *endframe; -} LogEnvStr_t; - - -typedef struct log_env_ctx_t { - RK_U32 help; - RK_U32 show; - RK_U32 ctrl; - RK_U32 level; - RK_U32 decframe; - RK_U32 begframe; - RK_U32 endframe; - char *outpath; - //!< files - FILE *fp_driver; - FILE *fp_syn_parse; - FILE *fp_syn_hal; - FILE *fp_run_parse; - FILE *fp_run_hal; - -} LogEnv_t; - -typedef struct h264d_logctx_t { - LogEnv_t env; - LogFlag_t log_flag; - LogCtx_t *parr[LOG_MAX]; -} H264dLogCtx_t; - -//!< write log -#define LogEnable(ctx, loglevel) ( ctx && ctx->flag->debug_en && (ctx->flag->level & loglevel) ) - -#define LogTrace(ctx, ...)\ - do{ if(LogEnable(ctx, LOG_LEVEL_TRACE)) {\ - writelog(ctx, __FILE__, __LINE__, "TRACE", __VA_ARGS__);\ - } }while (0) -#define LogInfo(ctx, ...)\ - do{ if(LogEnable(ctx, LOG_LEVEL_INFO)) {\ - writelog(ctx, __FILE__, __LINE__, "INFO", __VA_ARGS__);\ - } }while (0) - -#define LogWarnning(ctx, ...)\ - do{ if(LogEnable(ctx, LOG_LEVEL_WARNNING)) {\ - writelog(ctx, __FILE__, __LINE__, "WARNNING", __VA_ARGS__);\ - } }while (0) - -#define LogError(ctx, ...)\ - do{ if(LogEnable(ctx, LOG_LEVEL_ERROR)) {\ - writelog(ctx, __FILE__, __LINE__, "ERROR", __VA_ARGS__);\ - ASSERT(0);\ - } }while (0) -#define LogFatal(ctx, ...)\ - do{ if(LogEnable(ctx, LOG_LEVEL_ERROR)) {\ - writelog(ctx, __FILE__, __LINE__, "FATAL", __VA_ARGS__);\ - ASSERT(0);\ - } }while (0) - -#define FunctionIn(ctx)\ - do{ if(LogEnable(ctx, LOG_LEVEL_TRACE)) {\ - writelog(ctx, __FILE__, __LINE__, "FunIn", __FUNCTION__);\ - } } while (0) - -#define FunctionOut(ctx)\ - do{if(LogEnable(ctx, LOG_LEVEL_TRACE)) {\ - writelog(ctx, __FILE__, __LINE__, "FunOut", __FUNCTION__);\ - } } while (0) - - -#define __RETURN __Return -#define __FAILED __failed - - -#define VAL_CHECK(ret, val)\ - do{ if(!(val)){\ - ret = MPP_ERR_VALUE;\ - mpp_log("ERROR: value error.\n");\ - goto __FAILED;\ - } } while (0) //!< vaule check - -//!< memory malloc check -#define MEM_CHECK(ret, val)\ - do{ if(!(val)) {\ - ret = MPP_ERR_MALLOC;\ - mpp_log("ERROR: malloc buffer.\n");\ - ASSERT(0); goto __FAILED;\ - } } while (0) -//!< file check -#define FLE_CHECK(ret, val)\ - do{ if(!(val)) {\ - ret = MPP_ERR_OPEN_FILE;\ - mpp_log("ERROR: open file.\n");\ - ASSERT(0); goto __FAILED;\ - } } while (0) - -//!< input check -#define INP_CHECK(ret, ctx, val)\ - do{ if((val)) {\ - ret = MPP_ERR_INIT;\ - mpp_log("WARNNING: input empty.\n");\ - goto __RETURN;\ - } } while (0) -//!< function return check -#define FUN_CHECK(val)\ - do{ if((val) < 0) {\ - goto __FAILED;\ - } } while (0) - -#define FPRINT(fp, ...) { if (fp) { fprintf(fp, ## __VA_ARGS__); fflush(fp);} } - -extern RK_U32 g_nalu_cnt; - - - -#ifdef __cplusplus -extern "C" { -#endif -extern const LogEnvStr_t logenv_name; -extern const char *logctrl_name[LOG_MAX]; -extern const char *loglevel_name[LOG_LEVEL_MAX]; - -MPP_RET get_logenv(LogEnv_t *env); -void print_env_help(LogEnv_t *env); -void show_env_flags(LogEnv_t *env); -MPP_RET explain_ctrl_flag(RK_U32 ctrl_val, LogFlag_t *pflag); -void set_log_outpath(LogEnv_t *env); - -void writelog(LogCtx_t *ctx, char *fname, RK_U32 line, char *loglevel, const char *msg, ...); - -#ifdef __cplusplus -} -#endif - -#endif /* __H264D_LOG_H__ */ \ No newline at end of file diff --git a/mpp/common/h264d_syntax.h b/mpp/common/h264d_syntax.h index ebc498192..1189e6468 100644 --- a/mpp/common/h264d_syntax.h +++ b/mpp/common/h264d_syntax.h @@ -1,419 +1,438 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#ifndef __H264D_SYNTAX_H__ -#define __H264D_SYNTAX_H__ - -#include "dxva_syntax.h" - -/* H.264/AVC-specific structures */ - -/* H.264/AVC picture entry data structure */ -typedef struct _DXVA_PicEntry_H264 { - union { - struct { - RK_U8 Index7Bits : 7; - RK_U8 AssociatedFlag : 1; - }; - RK_U8 bPicEntry; - }; -} DXVA_PicEntry_H264, *LPDXVA_PicEntry_H264; /* 1 byte */ - -/* H.264/AVC picture parameters structure */ -typedef struct _DXVA_PicParams_H264 { - RK_U16 wFrameWidthInMbsMinus1; - RK_U16 wFrameHeightInMbsMinus1; - DXVA_PicEntry_H264 CurrPic; /* flag is bot field flag */ - RK_U8 num_ref_frames; - - union { - struct { - RK_U16 field_pic_flag : 1; - RK_U16 MbaffFrameFlag : 1; - RK_U16 residual_colour_transform_flag : 1; - RK_U16 sp_for_switch_flag : 1; - RK_U16 chroma_format_idc : 2; - RK_U16 RefPicFlag : 1; - RK_U16 constrained_intra_pred_flag : 1; - - RK_U16 weighted_pred_flag : 1; - RK_U16 weighted_bipred_idc : 2; - RK_U16 MbsConsecutiveFlag : 1; - RK_U16 frame_mbs_only_flag : 1; - RK_U16 transform_8x8_mode_flag : 1; - RK_U16 MinLumaBipredSize8x8Flag : 1; - RK_U16 IntraPicFlag : 1; - }; - RK_U16 wBitFields; - }; - RK_U8 bit_depth_luma_minus8; - RK_U8 bit_depth_chroma_minus8; - - RK_U16 Reserved16Bits; - RK_U32 StatusReportFeedbackNumber; - - DXVA_PicEntry_H264 RefFrameList[16]; /* flag LT */ - RK_S32 CurrFieldOrderCnt[2]; - RK_S32 FieldOrderCntList[16][2]; - - RK_S8 pic_init_qs_minus26; - RK_S8 chroma_qp_index_offset; /* also used for QScb */ - RK_S8 second_chroma_qp_index_offset; /* also for QScr */ - RK_U8 ContinuationFlag; - - /* remainder for parsing */ - RK_S8 pic_init_qp_minus26; - RK_U8 num_ref_idx_l0_active_minus1; - RK_U8 num_ref_idx_l1_active_minus1; - RK_U8 Reserved8BitsA; - - RK_U16 FrameNumList[16]; - RK_U32 UsedForReferenceFlags; - RK_U16 NonExistingFrameFlags; - RK_U16 frame_num; - - RK_U8 log2_max_frame_num_minus4; - RK_U8 pic_order_cnt_type; - RK_U8 log2_max_pic_order_cnt_lsb_minus4; - RK_U8 delta_pic_order_always_zero_flag; - - RK_U8 direct_8x8_inference_flag; - RK_U8 entropy_coding_mode_flag; - RK_U8 pic_order_present_flag; - RK_U8 num_slice_groups_minus1; - - RK_U8 slice_group_map_type; - RK_U8 deblocking_filter_control_present_flag; - RK_U8 redundant_pic_cnt_present_flag; - RK_U8 Reserved8BitsB; - - RK_U16 slice_group_change_rate_minus1; - - RK_U8 SliceGroupMap[810]; /* 4b/sgmu, Size BT.601 */ - -} DXVA_PicParams_H264, *LPDXVA_PicParams_H264; - -/* H.264/AVC quantization weighting matrix data structure */ -typedef struct _DXVA_Qmatrix_H264 { - RK_U8 bScalingLists4x4[6][16]; - RK_U8 bScalingLists8x8[2][64]; - -} DXVA_Qmatrix_H264, *LPDXVA_Qmatrix_H264; - -/* H.264/AVC slice control data structure - short form */ -typedef struct _DXVA_Slice_H264_Short { - RK_U32 BSNALunitDataLocation; /* type 1..5 */ - RK_U32 SliceBytesInBuffer; /* for off-host parse */ - RK_U16 wBadSliceChopping; /* for off-host parse */ -} DXVA_Slice_H264_Short, *LPDXVA_Slice_H264_Short; - -/* H.264/AVC picture entry data structure - long form */ -typedef struct _DXVA_Slice_H264_Long { - RK_U32 BSNALunitDataLocation; /* type 1..5 */ - RK_U32 SliceBytesInBuffer; /* for off-host parse */ - RK_U16 wBadSliceChopping; /* for off-host parse */ - - RK_U16 first_mb_in_slice; - RK_U16 NumMbsForSlice; - - RK_U16 BitOffsetToSliceData; /* after CABAC alignment */ - - RK_U8 slice_type; - RK_U8 luma_log2_weight_denom; - RK_U8 chroma_log2_weight_denom; - RK_U8 num_ref_idx_l0_active_minus1; - RK_U8 num_ref_idx_l1_active_minus1; - RK_S8 slice_alpha_c0_offset_div2; - RK_S8 slice_beta_offset_div2; - RK_U8 Reserved8Bits; - DXVA_PicEntry_H264 RefPicList[3][32]; /* L0 & L1 */ - RK_S16 Weights[2][32][3][2]; /* L0 & L1; Y, Cb, Cr */ - RK_S8 slice_qs_delta; - /* rest off-host parse */ - RK_S8 slice_qp_delta; - RK_U8 redundant_pic_cnt; - RK_U8 direct_spatial_mv_pred_flag; - RK_U8 cabac_init_idc; - RK_U8 disable_deblocking_filter_idc; - RK_U16 slice_id; -} DXVA_Slice_H264_Long, *LPDXVA_Slice_H264_Long; - -/* H.264/AVC macro block control command data structure */ -typedef struct _DXVA_MBctrl_H264 { - union { - struct { - RK_U32 bSliceID : 8; /* 1 byte */ - RK_U32 MbType5Bits : 5; - RK_U32 IntraMbFlag : 1; - RK_U32 mb_field_decoding_flag : 1; - RK_U32 transform_size_8x8_flag : 1; /* 2 bytes */ - RK_U32 HostResidDiff : 1; - RK_U32 DcBlockCodedCrFlag : 1; - RK_U32 DcBlockCodedCbFlag : 1; - RK_U32 DcBlockCodedYFlag : 1; - RK_U32 FilterInternalEdgesFlag : 1; - RK_U32 FilterLeftMbEdgeFlag : 1; - RK_U32 FilterTopMbEdgeFlag : 1; - RK_U32 ReservedBit : 1; - RK_U32 bMvQuantity : 8; /* 4 bytes */ - }; - RK_U32 dwMBtype; /* 4 bytes so far */ - }; - RK_U16 CurrMbAddr; /* 6 bytes so far */ - RK_U16 wPatternCode[3];/* YCbCr, 16 4x4 blks, 1b each */ - /* 12 bytes so far */ - RK_U8 bQpPrime[3]; /* Y, Cb, Cr, need just 7b QpY */ - RK_U8 bMBresidDataQuantity; - RK_U32 dwMBdataLocation; /* offset into resid buffer */ - /* 20 bytes so far */ - union { - struct { - /* start here for Intra MB's (9 useful bytes in branch) */ - RK_U16 LumaIntraPredModes[4];/* 16 blocks, 4b each */ - /* 28 bytes so far */ - union { - struct { - RK_U8 intra_chroma_pred_mode : 2; - RK_U8 IntraPredAvailFlags : 5; - RK_U8 ReservedIntraBit : 1; - }; - RK_U8 bMbIntraStruct; /* 29 bytes so far */ - }; - RK_U8 ReservedIntra24Bits[3]; /* 32 bytes total */ - }; - struct { - /* start here for non-Intra MB's (12 bytes in branch) */ - RK_U8 bSubMbShapes; /* 4 subMbs, 2b each */ - RK_U8 bSubMbPredModes; /* 4 subMBs, 2b each */ - /* 22 bytes so far */ - RK_U16 wMvBuffOffset; /* offset into MV buffer */ - RK_U8 bRefPicSelect[2][4]; /* 32 bytes total */ - }; - }; -} DXVA_MBctrl_H264, *LPDXVA_MBctrl_H264; - -/* H.264/AVC IndexA and IndexB data structure */ -typedef struct _DXVA_DeblockIndexAB_H264 { - RK_U8 bIndexAinternal; /* 6b - could get from MB CC */ - RK_U8 bIndexBinternal; /* 6b - could get from MB CC */ - - RK_U8 bIndexAleft0; - RK_U8 bIndexBleft0; - - RK_U8 bIndexAleft1; - RK_U8 bIndexBleft1; - - RK_U8 bIndexAtop0; - RK_U8 bIndexBtop0; - - RK_U8 bIndexAtop1; - RK_U8 bIndexBtop1; -} DXVA_DeblockIndexAB_H264, *LPDXVA_DeblockIndexAB_H264; -/* 10 bytes in struct */ - -/* H.264/AVC deblocking filter control data structure */ -typedef struct _DXVA_Deblock_H264 { - RK_U16 CurrMbAddr; /* dup info */ /* 2 bytes so far */ - union { - struct { - RK_U8 ReservedBit : 1; - RK_U8 FieldModeCurrentMbFlag : 1; /* dup info */ - RK_U8 FieldModeLeftMbFlag : 1; - RK_U8 FieldModeAboveMbFlag : 1; - RK_U8 FilterInternal8x8EdgesFlag : 1; - RK_U8 FilterInternal4x4EdgesFlag : 1; - RK_U8 FilterLeftMbEdgeFlag : 1; - RK_U8 FilterTopMbEdgeFlag : 1; - }; - RK_U8 FirstByte; - }; - RK_U8 Reserved8Bits; /* 4 bytes so far */ - - RK_U8 bbSinternalLeftVert; /* 2 bits per bS */ - RK_U8 bbSinternalMidVert; - - RK_U8 bbSinternalRightVert; - RK_U8 bbSinternalTopHorz; /* 8 bytes so far */ - - RK_U8 bbSinternalMidHorz; - RK_U8 bbSinternalBotHorz; /* 10 bytes so far */ - - RK_U16 wbSLeft0; /* 4 bits per bS (1 wasted) */ - RK_U16 wbSLeft1; /* 4 bits per bS (1 wasted) */ - - RK_U16 wbSTop0; /* 4 bits per bS (1 wasted) */ - RK_U16 wbSTop1; /* 4b (2 wasted) 18 bytes so far*/ - - DXVA_DeblockIndexAB_H264 IndexAB[3]; /* Y, Cb, Cr */ - -} DXVA_Deblock_H264, *LPDXVA_Deblock_H264;/* 48 bytes */ - -/* H.264/AVC film grain characteristics data structure */ -typedef struct _DXVA_FilmGrainCharacteristics { - - RK_U16 wFrameWidthInMbsMinus1; - RK_U16 wFrameHeightInMbsMinus1; - - DXVA_PicEntry_H264 InPic; /* flag is bot field flag */ - DXVA_PicEntry_H264 OutPic; /* flag is field pic flag */ - - RK_U16 PicOrderCnt_offset; - RK_S32 CurrPicOrderCnt; - RK_U32 StatusReportFeedbackNumber; - - RK_U8 model_id; - RK_U8 separate_colour_description_present_flag; - RK_U8 film_grain_bit_depth_luma_minus8; - RK_U8 film_grain_bit_depth_chroma_minus8; - - RK_U8 film_grain_full_range_flag; - RK_U8 film_grain_colour_primaries; - RK_U8 film_grain_transfer_characteristics; - RK_U8 film_grain_matrix_coefficients; - - RK_U8 blending_mode_id; - RK_U8 log2_scale_factor; - - RK_U8 comp_model_present_flag[4]; - RK_U8 num_intensity_intervals_minus1[4]; - RK_U8 num_model_values_minus1[4]; - - RK_U8 intensity_interval_lower_bound[3][16]; - RK_U8 intensity_interval_upper_bound[3][16]; - RK_S16 comp_model_value[3][16][8]; -} DXVA_FilmGrainChar_H264, *LPDXVA_FilmGrainChar_H264; - -/* H.264/AVC status reporting data structure */ -typedef struct _DXVA_Status_H264 { - RK_U32 StatusReportFeedbackNumber; - DXVA_PicEntry_H264 CurrPic; /* flag is bot field flag */ - RK_U8 field_pic_flag; - RK_U8 bDXVA_Func; - RK_U8 bBufType; - RK_U8 bStatus; - RK_U8 bReserved8Bits; - RK_U16 wNumMbsAffected; -} DXVA_Status_H264, *LPDXVA_Status_H264; - -/* H.264 MVC picture parameters structure */ -typedef struct _DXVA_PicParams_H264_MVC { - RK_U16 wFrameWidthInMbsMinus1; - RK_U16 wFrameHeightInMbsMinus1; - DXVA_PicEntry_H264 CurrPic; /* flag is bot field flag */ - RK_U8 num_ref_frames; - - union { - struct { - RK_U16 field_pic_flag : 1; - RK_U16 MbaffFrameFlag : 1; - RK_U16 residual_colour_transform_flag : 1; - RK_U16 sp_for_switch_flag : 1; - RK_U16 chroma_format_idc : 2; - RK_U16 RefPicFlag : 1; - RK_U16 constrained_intra_pred_flag : 1; - - RK_U16 weighted_pred_flag : 1; - RK_U16 weighted_bipred_idc : 2; - RK_U16 MbsConsecutiveFlag : 1; - RK_U16 frame_mbs_only_flag : 1; - RK_U16 transform_8x8_mode_flag : 1; - RK_U16 MinLumaBipredSize8x8Flag : 1; - RK_U16 IntraPicFlag : 1; - }; - RK_U16 wBitFields; - }; - RK_U8 bit_depth_luma_minus8; - RK_U8 bit_depth_chroma_minus8; - - RK_U16 Reserved16Bits; - RK_U32 StatusReportFeedbackNumber; - - DXVA_PicEntry_H264 RefFrameList[16]; /* flag LT */ - RK_S32 CurrFieldOrderCnt[2]; - RK_S32 FieldOrderCntList[16][2]; - - RK_S8 pic_init_qs_minus26; - RK_S8 chroma_qp_index_offset; /* also used for QScb */ - RK_S8 second_chroma_qp_index_offset; /* also for QScr */ - RK_U8 ContinuationFlag; - - /* remainder for parsing */ - RK_S8 pic_init_qp_minus26; - RK_U8 num_ref_idx_l0_active_minus1; - RK_U8 num_ref_idx_l1_active_minus1; - RK_U8 Reserved8BitsA; - - RK_U16 FrameNumList[16]; - RK_U32 UsedForReferenceFlags; - RK_U16 NonExistingFrameFlags; - RK_U16 frame_num; - - RK_U8 log2_max_frame_num_minus4; - RK_U8 pic_order_cnt_type; - RK_U8 log2_max_pic_order_cnt_lsb_minus4; - RK_U8 delta_pic_order_always_zero_flag; - - RK_U8 direct_8x8_inference_flag; - RK_U8 entropy_coding_mode_flag; - RK_U8 pic_order_present_flag; - RK_U8 num_slice_groups_minus1; - - RK_U8 slice_group_map_type; - RK_U8 deblocking_filter_control_present_flag; - RK_U8 redundant_pic_cnt_present_flag; - RK_U8 Reserved8BitsB; - /* SliceGroupMap is not needed for MVC, as MVC is for high profile only */ - RK_U16 slice_group_change_rate_minus1; - /* Following are H.264 MVC Specific parameters */ - RK_U8 num_views_minus1; - RK_U16 view_id[16]; - RK_U8 num_anchor_refs_l0[16]; - RK_U16 anchor_ref_l0[16][16]; - RK_U8 num_anchor_refs_l1[16]; - RK_U16 anchor_ref_l1[16][16]; - RK_U8 num_non_anchor_refs_l0[16]; - RK_U16 non_anchor_ref_l0[16][16]; - RK_U8 num_non_anchor_refs_l1[16]; - RK_U16 non_anchor_ref_l1[16][16]; - - RK_U16 curr_view_id; - RK_U8 anchor_pic_flag; - RK_U8 inter_view_flag; - RK_U16 ViewIDList[16]; - //!< add in Rock-Chip RKVDEC IP - RK_U16 RefPicColmvUsedFlags; - RK_U16 RefPicFiledFlags; - RK_U8 RefPicLayerIdList[16]; - RK_U8 scaleing_list_enable_flag; - ////!< for fpga test - //USHORT seq_parameter_set_id; - //USHORT pps_seq_parameter_set_id; - //USHORT profile_idc; - //UCHAR constraint_set3_flag; - //UCHAR qpprime_y_zero_transform_bypass_flag; - //UCHAR mvc_extension_enable; - -} DXVA_PicParams_H264_MVC, *LPDXVA_PicParams_H264_MVC; - -typedef struct h264d_syntax_t { - RK_U32 num; - DXVA2_DecodeBufferDesc *buf; -} H264dSyntax_t; - -#endif /*__H264D_SYNTAX_H__*/ - +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef H264D_SYNTAX_H +#define H264D_SYNTAX_H + +#include "h264_syntax.h" +#include "dxva_syntax.h" + +/* H.264/AVC-specific structures */ + +/* H.264/AVC picture entry data structure */ +typedef struct DXVA_PicEntry_H264_t { + union { + struct { + RK_U8 Index7Bits : 7; + RK_U8 AssociatedFlag : 1; + }; + RK_U8 bPicEntry; + }; +} DXVA_PicEntry_H264, *LPDXVA_PicEntry_H264; /* 1 byte */ + +/* H.264/AVC picture parameters structure */ +typedef struct DXVA_PicParams_H264_t { + RK_U16 wFrameWidthInMbsMinus1; + RK_U16 wFrameHeightInMbsMinus1; + DXVA_PicEntry_H264 CurrPic; /* flag is bot field flag */ + RK_U8 num_ref_frames; + + union { + struct { + RK_U16 field_pic_flag : 1; + RK_U16 MbaffFrameFlag : 1; + RK_U16 residual_colour_transform_flag : 1; + RK_U16 sp_for_switch_flag : 1; + RK_U16 chroma_format_idc : 2; + RK_U16 RefPicFlag : 1; + RK_U16 constrained_intra_pred_flag : 1; + + RK_U16 weighted_pred_flag : 1; + RK_U16 weighted_bipred_idc : 2; + RK_U16 MbsConsecutiveFlag : 1; + RK_U16 frame_mbs_only_flag : 1; + RK_U16 transform_8x8_mode_flag : 1; + RK_U16 MinLumaBipredSize8x8Flag : 1; + RK_U16 IntraPicFlag : 1; + }; + RK_U16 wBitFields; + }; + RK_U8 bit_depth_luma_minus8; + RK_U8 bit_depth_chroma_minus8; + + RK_U16 Reserved16Bits; + RK_U32 StatusReportFeedbackNumber; + + DXVA_PicEntry_H264 RefFrameList[16]; /* flag LT */ + RK_S32 CurrFieldOrderCnt[2]; + RK_S32 FieldOrderCntList[16][2]; + + RK_S8 pic_init_qs_minus26; + RK_S8 chroma_qp_index_offset; /* also used for QScb */ + RK_S8 second_chroma_qp_index_offset; /* also for QScr */ + RK_U8 ContinuationFlag; + + /* remainder for parsing */ + RK_S8 pic_init_qp_minus26; + RK_U8 num_ref_idx_l0_active_minus1; + RK_U8 num_ref_idx_l1_active_minus1; + RK_U8 Reserved8BitsA; + + RK_U16 FrameNumList[16]; + RK_U32 UsedForReferenceFlags; + RK_U16 NonExistingFrameFlags; + RK_U16 frame_num; + + RK_U8 log2_max_frame_num_minus4; + RK_U8 pic_order_cnt_type; + RK_U8 log2_max_pic_order_cnt_lsb_minus4; + RK_U8 delta_pic_order_always_zero_flag; + + RK_U8 direct_8x8_inference_flag; + RK_U8 entropy_coding_mode_flag; + RK_U8 pic_order_present_flag; + RK_U8 num_slice_groups_minus1; + + RK_U8 slice_group_map_type; + RK_U8 deblocking_filter_control_present_flag; + RK_U8 redundant_pic_cnt_present_flag; + RK_U8 Reserved8BitsB; + + RK_U16 slice_group_change_rate_minus1; +} DXVA_PicParams_H264, *LPDXVA_PicParams_H264; + +/* H.264/AVC quantization weighting matrix data structure */ +typedef struct DXVA_Qmatrix_H264_t { + RK_U8 bScalingLists4x4[6][16]; + RK_U8 bScalingLists8x8[6][64]; + +} DXVA_Qmatrix_H264, *LPDXVA_Qmatrix_H264; + +/* H.264/AVC slice control data structure - short form */ +typedef struct DXVA_Slice_H264_Short_t { + RK_U32 BSNALunitDataLocation; /* type 1..5 */ + RK_U32 SliceBytesInBuffer; /* for off-host parse */ + RK_U16 wBadSliceChopping; /* for off-host parse */ +} DXVA_Slice_H264_Short, *LPDXVA_Slice_H264_Short; + +/* H.264/AVC picture entry data structure - long form */ +typedef struct DXVA_Slice_H264_Long_t { + RK_U32 BSNALunitDataLocation; /* type 1..5 */ + RK_U32 SliceBytesInBuffer; /* for off-host parse */ + RK_U16 wBadSliceChopping; /* for off-host parse */ + + RK_U16 first_mb_in_slice; + RK_U16 NumMbsForSlice; + + + RK_U8 slice_type; + RK_U8 num_ref_idx_l0_active_minus1; + RK_U8 num_ref_idx_l1_active_minus1; + DXVA_PicEntry_H264 RefPicList[3][32]; /* L0 & L1 */ +#if 0 + RK_U16 BitOffsetToSliceData; /* after CABAC alignment */ + RK_U8 luma_log2_weight_denom; + RK_U8 chroma_log2_weight_denom; + RK_S8 slice_alpha_c0_offset_div2; + RK_S8 slice_beta_offset_div2; + RK_U8 Reserved8Bits; + RK_S16 Weights[2][32][3][2]; /* L0 & L1; Y, Cb, Cr */ + RK_S8 slice_qs_delta; + /* rest off-host parse */ + RK_S8 slice_qp_delta; +#endif + RK_U8 redundant_pic_cnt; + RK_U8 direct_spatial_mv_pred_flag; + RK_U8 cabac_init_idc; + RK_U8 disable_deblocking_filter_idc; + RK_U16 slice_id; + /* add parameter for setting hardware */ + RK_U32 active_sps_id; + RK_U32 active_pps_id; + RK_U32 idr_pic_id; + RK_U32 idr_flag; + RK_U32 drpm_used_bitlen; + RK_U32 poc_used_bitlen; + RK_U32 nal_ref_idc; + RK_U32 profileIdc; +} DXVA_Slice_H264_Long, *LPDXVA_Slice_H264_Long; + +/* H.264/AVC macro block control command data structure */ +typedef struct DXVA_MBctrl_H264_t { + union { + struct { + RK_U32 bSliceID : 8; /* 1 byte */ + RK_U32 MbType5Bits : 5; + RK_U32 IntraMbFlag : 1; + RK_U32 mb_field_decoding_flag : 1; + RK_U32 transform_size_8x8_flag : 1; /* 2 bytes */ + RK_U32 HostResidDiff : 1; + RK_U32 DcBlockCodedCrFlag : 1; + RK_U32 DcBlockCodedCbFlag : 1; + RK_U32 DcBlockCodedYFlag : 1; + RK_U32 FilterInternalEdgesFlag : 1; + RK_U32 FilterLeftMbEdgeFlag : 1; + RK_U32 FilterTopMbEdgeFlag : 1; + RK_U32 ReservedBit : 1; + RK_U32 bMvQuantity : 8; /* 4 bytes */ + }; + RK_U32 dwMBtype; /* 4 bytes so far */ + }; + RK_U16 CurrMbAddr; /* 6 bytes so far */ + RK_U16 wPatternCode[3];/* YCbCr, 16 4x4 blks, 1b each */ + /* 12 bytes so far */ + RK_U8 bQpPrime[3]; /* Y, Cb, Cr, need just 7b QpY */ + RK_U8 bMBresidDataQuantity; + RK_U32 dwMBdataLocation; /* offset into resid buffer */ + /* 20 bytes so far */ + union { + struct { + /* start here for Intra MB's (9 useful bytes in branch) */ + RK_U16 LumaIntraPredModes[4];/* 16 blocks, 4b each */ + /* 28 bytes so far */ + union { + struct { + RK_U8 intra_chroma_pred_mode : 2; + RK_U8 IntraPredAvailFlags : 5; + RK_U8 ReservedIntraBit : 1; + }; + RK_U8 bMbIntraStruct; /* 29 bytes so far */ + }; + RK_U8 ReservedIntra24Bits[3]; /* 32 bytes total */ + }; + struct { + /* start here for non-Intra MB's (12 bytes in branch) */ + RK_U8 bSubMbShapes; /* 4 subMbs, 2b each */ + RK_U8 bSubMbPredModes; /* 4 subMBs, 2b each */ + /* 22 bytes so far */ + RK_U16 wMvBuffOffset; /* offset into MV buffer */ + RK_U8 bRefPicSelect[2][4]; /* 32 bytes total */ + }; + }; +} DXVA_MBctrl_H264, *LPDXVA_MBctrl_H264; + +/* H.264/AVC IndexA and IndexB data structure */ +typedef struct DXVA_DeblockIndexAB_H264_t { + RK_U8 bIndexAinternal; /* 6b - could get from MB CC */ + RK_U8 bIndexBinternal; /* 6b - could get from MB CC */ + + RK_U8 bIndexAleft0; + RK_U8 bIndexBleft0; + + RK_U8 bIndexAleft1; + RK_U8 bIndexBleft1; + + RK_U8 bIndexAtop0; + RK_U8 bIndexBtop0; + + RK_U8 bIndexAtop1; + RK_U8 bIndexBtop1; +} DXVA_DeblockIndexAB_H264, *LPDXVA_DeblockIndexAB_H264; +/* 10 bytes in struct */ + +/* H.264/AVC deblocking filter control data structure */ +typedef struct DXVA_Deblock_H264_t { + RK_U16 CurrMbAddr; /* dup info */ /* 2 bytes so far */ + union { + struct { + RK_U8 ReservedBit : 1; + RK_U8 FieldModeCurrentMbFlag : 1; /* dup info */ + RK_U8 FieldModeLeftMbFlag : 1; + RK_U8 FieldModeAboveMbFlag : 1; + RK_U8 FilterInternal8x8EdgesFlag : 1; + RK_U8 FilterInternal4x4EdgesFlag : 1; + RK_U8 FilterLeftMbEdgeFlag : 1; + RK_U8 FilterTopMbEdgeFlag : 1; + }; + RK_U8 FirstByte; + }; + RK_U8 Reserved8Bits; /* 4 bytes so far */ + + RK_U8 bbSinternalLeftVert; /* 2 bits per bS */ + RK_U8 bbSinternalMidVert; + + RK_U8 bbSinternalRightVert; + RK_U8 bbSinternalTopHorz; /* 8 bytes so far */ + + RK_U8 bbSinternalMidHorz; + RK_U8 bbSinternalBotHorz; /* 10 bytes so far */ + + RK_U16 wbSLeft0; /* 4 bits per bS (1 wasted) */ + RK_U16 wbSLeft1; /* 4 bits per bS (1 wasted) */ + + RK_U16 wbSTop0; /* 4 bits per bS (1 wasted) */ + RK_U16 wbSTop1; /* 4b (2 wasted) 18 bytes so far*/ + + DXVA_DeblockIndexAB_H264 IndexAB[3]; /* Y, Cb, Cr */ + +} DXVA_Deblock_H264, *LPDXVA_Deblock_H264;/* 48 bytes */ + +/* H.264/AVC film grain characteristics data structure */ +typedef struct DXVA_FilmGrainCharacteristics_t { + + RK_U16 wFrameWidthInMbsMinus1; + RK_U16 wFrameHeightInMbsMinus1; + + DXVA_PicEntry_H264 InPic; /* flag is bot field flag */ + DXVA_PicEntry_H264 OutPic; /* flag is field pic flag */ + + RK_U16 PicOrderCnt_offset; + RK_S32 CurrPicOrderCnt; + RK_U32 StatusReportFeedbackNumber; + + RK_U8 model_id; + RK_U8 separate_colour_description_present_flag; + RK_U8 film_grain_bit_depth_luma_minus8; + RK_U8 film_grain_bit_depth_chroma_minus8; + + RK_U8 film_grain_full_range_flag; + RK_U8 film_grain_colour_primaries; + RK_U8 film_grain_transfer_characteristics; + RK_U8 film_grain_matrix_coefficients; + + RK_U8 blending_mode_id; + RK_U8 log2_scale_factor; + + RK_U8 comp_model_present_flag[4]; + RK_U8 num_intensity_intervals_minus1[4]; + RK_U8 num_model_values_minus1[4]; + + RK_U8 intensity_interval_lower_bound[3][16]; + RK_U8 intensity_interval_upper_bound[3][16]; + RK_S16 comp_model_value[3][16][8]; +} DXVA_FilmGrainChar_H264, *LPDXVA_FilmGrainChar_H264; + +/* H.264/AVC status reporting data structure */ +typedef struct DXVA_Status_H264_t { + RK_U32 StatusReportFeedbackNumber; + DXVA_PicEntry_H264 CurrPic; /* flag is bot field flag */ + RK_U8 field_pic_flag; + RK_U8 bDXVA_Func; + RK_U8 bBufType; + RK_U8 bStatus; + RK_U8 bReserved8Bits; + RK_U16 wNumMbsAffected; +} DXVA_Status_H264, *LPDXVA_Status_H264; + +/* H.264 MVC picture parameters structure */ +typedef struct DXVA_PicParams_H264_MVC_t { + RK_U16 wFrameWidthInMbsMinus1; + RK_U16 wFrameHeightInMbsMinus1; + DXVA_PicEntry_H264 CurrPic; /* flag is bot field flag */ + RK_U8 num_ref_frames; + + union { + struct { + RK_U16 field_pic_flag : 1; + RK_U16 MbaffFrameFlag : 1; + RK_U16 residual_colour_transform_flag : 1; + RK_U16 sp_for_switch_flag : 1; + RK_U16 chroma_format_idc : 2; + RK_U16 RefPicFlag : 1; + RK_U16 constrained_intra_pred_flag : 1; + + RK_U16 weighted_pred_flag : 1; + RK_U16 weighted_bipred_idc : 2; + RK_U16 MbsConsecutiveFlag : 1; + RK_U16 frame_mbs_only_flag : 1; + RK_U16 transform_8x8_mode_flag : 1; + RK_U16 MinLumaBipredSize8x8Flag : 1; + RK_U16 IntraPicFlag : 1; + }; + RK_U16 wBitFields; + }; + RK_U8 bit_depth_luma_minus8; + RK_U8 bit_depth_chroma_minus8; + + RK_U16 Reserved16Bits; + RK_U32 StatusReportFeedbackNumber; + + DXVA_PicEntry_H264 RefFrameList[16]; /* flag LT */ + RK_S32 CurrFieldOrderCnt[2]; + RK_S32 FieldOrderCntList[16][2]; + + RK_S8 pic_init_qs_minus26; + RK_S8 chroma_qp_index_offset; /* also used for QScb */ + RK_S8 second_chroma_qp_index_offset; /* also for QScr */ + RK_U8 ContinuationFlag; + + /* remainder for parsing */ + RK_S8 pic_init_qp_minus26; + RK_U8 num_ref_idx_l0_active_minus1; + RK_U8 num_ref_idx_l1_active_minus1; + RK_U8 Reserved8BitsA; + + RK_U16 FrameNumList[16]; + RK_U16 LongTermPicNumList[16]; + RK_U32 UsedForReferenceFlags; + RK_U16 NonExistingFrameFlags; + RK_U16 frame_num; + + RK_U8 log2_max_frame_num_minus4; + RK_U8 pic_order_cnt_type; + RK_U8 log2_max_pic_order_cnt_lsb_minus4; + RK_U8 delta_pic_order_always_zero_flag; + + RK_U8 direct_8x8_inference_flag; + RK_U8 entropy_coding_mode_flag; + RK_U8 pic_order_present_flag; + RK_U8 num_slice_groups_minus1; + + RK_U8 slice_group_map_type; + RK_U8 deblocking_filter_control_present_flag; + RK_U8 redundant_pic_cnt_present_flag; + RK_U8 Reserved8BitsB; + /* SliceGroupMap is not needed for MVC, as MVC is for high profile only */ + RK_U16 slice_group_change_rate_minus1; + /* Following are H.264 MVC Specific parameters */ + RK_S8 num_views_minus1; + RK_U16 view_id[16]; + RK_U8 num_anchor_refs_l0[16]; + RK_U16 anchor_ref_l0[16][16]; + RK_U8 num_anchor_refs_l1[16]; + RK_U16 anchor_ref_l1[16][16]; + RK_U8 num_non_anchor_refs_l0[16]; + RK_U16 non_anchor_ref_l0[16][16]; + RK_U8 num_non_anchor_refs_l1[16]; + RK_U16 non_anchor_ref_l1[16][16]; + + RK_U16 curr_view_id; + RK_U8 anchor_pic_flag; + RK_U8 inter_view_flag; + RK_U16 ViewIDList[16]; + //!< add in Rock-Chip RKVDEC IP + RK_U16 curr_layer_id; + RK_U16 RefPicColmvUsedFlags; + RK_U16 RefPicFiledFlags; + RK_U8 RefPicLayerIdList[16]; + RK_U8 scaleing_list_enable_flag; + RK_U16 UsedForInTerviewflags; + + //!< extensive + RK_U32 spspps_update; + + //!< for fpga test + RK_U16 seq_parameter_set_id; + RK_U16 pps_seq_parameter_set_id; + RK_U16 pps_pic_parameter_set_id; + RK_U16 profile_idc; + RK_U8 constraint_set3_flag; + RK_U8 qpprime_y_zero_transform_bypass_flag; + RK_U8 mvc_extension_enable; + +} DXVA_PicParams_H264_MVC, *LPDXVA_PicParams_H264_MVC; + + + +typedef struct h264d_syntax_t { + RK_U32 num; + DXVA2_DecodeBufferDesc *buf; +} H264dSyntax_t; + +#endif /* H264D_SYNTAX_H */ + diff --git a/mpp/common/h264e_syntax.h b/mpp/common/h264e_syntax.h new file mode 100644 index 000000000..63c30d6c2 --- /dev/null +++ b/mpp/common/h264e_syntax.h @@ -0,0 +1,82 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H264E_SYNTAX_H +#define H264E_SYNTAX_H + +#include "mpp_rc_api.h" +#include "h264_syntax.h" + +typedef enum H264eSyntaxType_e { + H264E_SYN_CFG, + H264E_SYN_SPS, + H264E_SYN_PPS, + H264E_SYN_DPB, + H264E_SYN_SLICE, + H264E_SYN_FRAME, + H264E_SYN_PREFIX, + H264E_SYN_RC_RET, + H264E_SYN_BUTT, +} H264eSyntaxType; + +#define SYN_TYPE_FLAG(type) (1 << (type)) + +typedef struct H264eSyntaxDesc_t { + H264eSyntaxType type; + void *p; +} H264eSyntaxDesc; + +typedef struct H264ePrefixNal_t { + RK_S32 nal_ref_idc; + + /* svc extension header */ + RK_S32 idr_flag; + RK_S32 priority_id; + RK_S32 no_inter_layer_pred_flag; + RK_S32 dependency_id; + RK_S32 quality_id; + RK_S32 temporal_id; + RK_S32 use_ref_base_pic_flag; + RK_S32 discardable_flag; + RK_S32 output_flag; +} H264ePrefixNal; + + +/* + * Split reference frame configure to two parts + * The first part is slice depended info like poc / frame_num, and frame + * type and flags. + * The other part is gop structure depended info like gop index, ref_status + * and ref_frm_index. This part is inited from dpb gop hierarchy info. + */ +typedef struct H264eFrmInfo_s { + RK_S32 seq_idx; + + RK_S32 curr_idx; + RK_S32 refr_idx; + + RK_S32 usage[H264E_MAX_REFS_CNT + 1]; +} H264eFrmInfo; + +/* macro to add syntax to description array */ +#define H264E_ADD_SYNTAX(desc, number, syn_type, syn_ptr) \ + do { \ + desc[number].type = syn_type; \ + desc[number].p = syn_ptr; \ + number++; \ + } while (0) + +#endif /* H264E_SYNTAX_H */ diff --git a/mpp/common/h265_syntax.h b/mpp/common/h265_syntax.h new file mode 100644 index 000000000..3eddd6af5 --- /dev/null +++ b/mpp/common/h265_syntax.h @@ -0,0 +1,209 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265_SYNTAX_H +#define H265_SYNTAX_H + +#define PIXW_1080P (1920) +#define PIXH_1080P (1088) +#define PIXW_4Kx2K (4096) +#define PIXH_4Kx2K (2304) +#define PIXW_8Kx4K (8192) +#define PIXH_8Kx4K (4320) + +#if 0 + +#define REF_PIC_LIST_NUM_IDX 32 +#define H265E_UUID_LENGTH 16 + +#define MAX_CPB_CNT 32 ///< Upper bound of (cpb_cnt_minus1 + 1) +#define MAX_NUM_LAYER_IDS 64 +#define MAX_NUM_VPS 16 +#define MAX_NUM_SPS 16 +#define MAX_NUM_PPS 64 +#define MAX_TLAYER 7 ///< max number of temporal layer +#define MAX_VPS_NUM_HRD_PARAMETERS 1 +#define MAX_VPS_OP_SETS_PLUS1 1024 +#define MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 1 +#define MAX_NUM_REF_PICS 16 ///< max. number of pictures used for reference +#define MAX_NUM_REF 16 ///< max. number of entries in picture reference list +#define MAX_CU_DEPTH 6 // log2(LCUSize) + +#define REF_PIC_LIST_0 0 +#define REF_PIC_LIST_1 1 +#define REF_PIC_LIST_X 100 +#define REF_BY_RECN(idx) (0x00000001 << idx) +#define REF_BY_REFR(idx) (0x00000001 << idx) +#define MAX_NUM_REF_PICS 16 + +#endif + +#define MAX_DPB_SIZE 17 // A.4.1 +#define MAX_REFS 16 + +/** + * 7.4.2.1 + */ +#define MAX_SUB_LAYERS 7 +#define MAX_VPS_COUNT 16 +#define MAX_SPS_COUNT 16 +#define MAX_PPS_COUNT 64 +#define MAX_SHORT_TERM_RPS_COUNT 64 +#define MAX_CU_SIZE 128 + +#define MAX_TRANSFORM_DEPTH 5 + +#define MAX_TB_SIZE 32 +#define MAX_PB_SIZE 64 +#define MAX_LOG2_CTB_SIZE 6 +#define MAX_QP 51 +#define DEFAULT_INTRA_TC_OFFSET 2 + +#define HEVC_CONTEXTS 183 + +#define MRG_MAX_NUM_CANDS 5 + +#define L0 0 +#define L1 1 + +#define REF_PIC_LIST_NUM_IDX 32 +#define MAX_CPB_CNT 32 +#define MAX_CU_DEPTH 6 +#define MAX_VPS_NUM_HRD_PARAMETERS 1 +#define MAX_VPS_OP_SETS_PLUS1 1024 +#define MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 1 +#define MAX_NUM_LONG_TERM_REF_PIC_POC 20 +#define REF_BY_RECN(idx) (0x00000001 << idx) +#define REF_BY_REFR(idx) (0x00000001 << idx) + + + + +#define EPEL_EXTRA_BEFORE 1 +#define EPEL_EXTRA_AFTER 2 +#define EPEL_EXTRA 3 +#define QPEL_EXTRA_BEFORE 3 +#define QPEL_EXTRA_AFTER 4 +#define QPEL_EXTRA 7 + +#define EDGE_EMU_BUFFER_STRIDE 80 + +#define MPP_INPUT_BUFFER_PADDING_SIZE 8 + +#define MPP_PROFILE_HEVC_MAIN 1 +#define MPP_PROFILE_HEVC_MAIN_10 2 +#define MPP_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define MPP_PROFILE_HEVC_FORMAT_RANGE_EXTENDIONS 4 + +#define LOG2_MAX_CTB_SIZE 6 +#define LOG2_MIN_CTB_SIZE 4 +#define LOG2_MAX_PU_SIZE 6 +#define LOG2_MIN_PU_SIZE 2 +#define LOG2_MAX_TU_SIZE 5 +#define LOG2_MIN_TU_SIZE 2 +#define LOG2_MAX_CU_SIZE 6 +#define LOG2_MIN_CU_SIZE 3 + +/** + * Value of the luma sample at position (x, y) in the 2D array tab. + */ +#define IS_IDR(type) (type == NAL_IDR_W_RADL || type == NAL_IDR_N_LP) +#define IS_BLA(type) (type == NAL_BLA_W_RADL || type == NAL_BLA_W_LP || \ + type == NAL_BLA_N_LP) +#define IS_IRAP(type) (type >= NAL_BLA_W_LP && type <= NAL_CRA_NUT) +#define IS_CRA(type) (type == NAL_CRA_NUT) + +/** + * Table 7-3: NAL unit type codes + */ +enum NALUnitType { + NAL_INIT_VALUE = -1, + NAL_TRAIL_N = 0, + NAL_TRAIL_R = 1, + NAL_TSA_N = 2, + NAL_TSA_R = 3, + NAL_STSA_N = 4, + NAL_STSA_R = 5, + NAL_RADL_N = 6, + NAL_RADL_R = 7, + NAL_RASL_N = 8, + NAL_RASL_R = 9, + NAL_BLA_W_LP = 16, + NAL_BLA_W_RADL = 17, + NAL_BLA_N_LP = 18, + NAL_IDR_W_RADL = 19, + NAL_IDR_N_LP = 20, + NAL_CRA_NUT = 21, + NAL_VPS = 32, + NAL_SPS = 33, + NAL_PPS = 34, + NAL_AUD = 35, + NAL_EOS_NUT = 36, + NAL_EOB_NUT = 37, + NAL_FD_NUT = 38, + NAL_SEI_PREFIX = 39, + NAL_SEI_SUFFIX = 40, + NAL_UNSPEC62 = 62, +}; + +typedef enum H265NalPriority_t { + H265_NAL_PRIORITY_DISPOSABLE = 0, + H265_NAL_PRIORITY_LOW = 1, + H265_NAL_PRIORITY_HIGH = 2, + H265_NAL_PRIORITY_HIGHEST = 3, +} H265NalPriority; + +typedef enum { + H265_LEVEL_NONE = 0, + H265_LEVEL1 = 30, + H265_LEVEL2 = 60, + H265_LEVEL2_1 = 63, + H265_LEVEL3 = 90, + H265_LEVEL3_1 = 93, + H265_LEVEL4 = 120, + H265_LEVEL4_1 = 123, + H265_LEVEL5 = 150, + H265_LEVEL5_1 = 153, + H265_LEVEL5_2 = 156, + H265_LEVEL6 = 180, + H265_LEVEL6_1 = 183, + H265_LEVEL6_2 = 186, + H265_LEVEL8_5 = 255, +} H265Level; + +typedef enum H265ChromaFmt_e { + H265_CHROMA_400 = 0, //!< Monochrome + H265_CHROMA_420 = 1, //!< 4:2:0 + H265_CHROMA_422 = 2, //!< 4:2:2 + H265_CHROMA_444 = 3 //!< 4:4:4 +} H265ChromaFmt; + +typedef enum SliceType_t { + B_SLICE = 0, + P_SLICE = 1, + I_SLICE = 2, +} SliceType; + +enum RPSType { + ST_CURR_BEF = 0, + ST_CURR_AFT, + ST_FOLL, + LT_CURR, + LT_FOLL, + NB_RPS_TYPE, +}; + +#endif diff --git a/mpp/common/h265d_syntax.h b/mpp/common/h265d_syntax.h new file mode 100644 index 000000000..6fa2b210e --- /dev/null +++ b/mpp/common/h265d_syntax.h @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef H265D_SYNTAX_H +#define H265D_SYNTAX_H + +#include "rk_type.h" + +/* HEVC Picture Entry structure */ +#define MAX_SLICES 600 + +/* Short-Term Reference Picture Set structure */ +typedef struct H265dStRps_t { + RK_U32 num_neg; /* number of negative pictures */ + RK_S32 num_deltas; /* number of delta POCs */ + RK_S32 ref_delta_cnt; /* reference delta count */ + RK_S32 poc_delta[32]; /* POC delta values */ + RK_U32 flags; /* flags for each picture (bit field) */ +} H265dStRps; + +/* Long-Term Reference Picture Set in SPS */ +typedef struct H265dLtRpsSps_t { + RK_U32 valid; + RK_U16 poc_lsb[32]; + RK_U32 used_flag; + RK_U32 num_refs; +} H265dLtRpsSps; + +/* Long-Term Reference Picture Set for Slice */ +typedef struct H265dLtRps_t { + RK_S32 poc[32]; + RK_U32 used; + RK_U32 nb_refs; +} H265dLtRps; + +typedef struct DXVA_PicEntry_HEVC_t { + union { + struct { + RK_U8 Index7Bits : 7; + RK_U8 AssociatedFlag : 1; + }; + RK_U8 bPicEntry; + }; +} DXVA_PicEntry_HEVC, *LPDXVA_PicEntry_HEVC; + +typedef struct Short_SPS_RPS_HEVC_t { + RK_U8 num_negative_pics; + RK_U8 num_positive_pics; + RK_S16 delta_poc_s0[16]; + RK_U8 s0_used_flag[16]; + RK_S16 delta_poc_s1[16]; + RK_U8 s1_used_flag[16]; +} Short_SPS_RPS_HEVC; + +typedef struct LT_SPS_RPS_HEVC_t { + RK_U16 lt_ref_pic_poc_lsb; + RK_U8 used_by_curr_pic_lt_flag; +} LT_SPS_RPS_HEVC; + +/* HEVC Picture Parameter structure */ +typedef struct DXVA_PicParams_HEVC_t { + RK_U16 PicWidthInMinCbsY; + RK_U16 PicHeightInMinCbsY; + union { + struct { + RK_U16 chroma_format_idc : 2; + RK_U16 separate_colour_plane_flag : 1; + RK_U16 bit_depth_luma_minus8 : 3; + RK_U16 bit_depth_chroma_minus8 : 3; + RK_U16 log2_max_pic_order_cnt_lsb_minus4 : 4; + RK_U16 NoPicReorderingFlag : 1; + RK_U16 NoBiPredFlag : 1; + RK_U16 ReservedBits1 : 1; + }; + RK_U16 wFormatAndSequenceInfoFlags; + }; + DXVA_PicEntry_HEVC CurrPic; + RK_U8 sps_max_dec_pic_buffering_minus1; + RK_U8 log2_min_luma_coding_block_size_minus3; + RK_U8 log2_diff_max_min_luma_coding_block_size; + RK_U8 log2_min_transform_block_size_minus2; + RK_U8 log2_diff_max_min_transform_block_size; + RK_U8 max_transform_hierarchy_depth_inter; + RK_U8 max_transform_hierarchy_depth_intra; + RK_U8 num_short_term_ref_pic_sets; + RK_U8 num_long_term_ref_pics_sps; + RK_U8 num_ref_idx_l0_default_active_minus1; + RK_U8 num_ref_idx_l1_default_active_minus1; + RK_S8 init_qp_minus26; + RK_U8 ucNumDeltaPocsOfRefRpsIdx; + RK_U16 wNumBitsForShortTermRPSInSlice; + RK_U16 ReservedBits2; + + union { + struct { + RK_U32 scaling_list_enabled_flag : 1; + RK_U32 amp_enabled_flag : 1; + RK_U32 sample_adaptive_offset_enabled_flag : 1; + RK_U32 pcm_enabled_flag : 1; + RK_U32 pcm_sample_bit_depth_luma_minus1 : 4; + RK_U32 pcm_sample_bit_depth_chroma_minus1 : 4; + RK_U32 log2_min_pcm_luma_coding_block_size_minus3 : 2; + RK_U32 log2_diff_max_min_pcm_luma_coding_block_size : 2; + RK_U32 pcm_loop_filter_disabled_flag : 1; + RK_U32 long_term_ref_pics_present_flag : 1; + RK_U32 sps_temporal_mvp_enabled_flag : 1; + RK_U32 strong_intra_smoothing_enabled_flag : 1; + RK_U32 dependent_slice_segments_enabled_flag : 1; + RK_U32 output_flag_present_flag : 1; + RK_U32 num_extra_slice_header_bits : 3; + RK_U32 sign_data_hiding_enabled_flag : 1; + RK_U32 cabac_init_present_flag : 1; + RK_U32 ReservedBits3 : 5; + }; + RK_U32 dwCodingParamToolFlags; + }; + + union { + struct { + RK_U32 constrained_intra_pred_flag : 1; + RK_U32 transform_skip_enabled_flag : 1; + RK_U32 cu_qp_delta_enabled_flag : 1; + RK_U32 pps_slice_chroma_qp_offsets_present_flag : 1; + RK_U32 weighted_pred_flag : 1; + RK_U32 weighted_bipred_flag : 1; + RK_U32 transquant_bypass_enabled_flag : 1; + RK_U32 tiles_enabled_flag : 1; + RK_U32 entropy_coding_sync_enabled_flag : 1; + RK_U32 uniform_spacing_flag : 1; + RK_U32 loop_filter_across_tiles_enabled_flag : 1; + RK_U32 pps_loop_filter_across_slices_enabled_flag : 1; + RK_U32 deblocking_filter_override_enabled_flag : 1; + RK_U32 pps_deblocking_filter_disabled_flag : 1; + RK_U32 lists_modification_present_flag : 1; + RK_U32 slice_segment_header_extension_present_flag : 1; + RK_U32 IrapPicFlag : 1; + RK_U32 IdrPicFlag : 1; + RK_U32 IntraPicFlag : 1; + // sps exension flags + RK_U32 sps_extension_flag : 1; + RK_U32 sps_range_extension_flag : 1; + RK_U32 transform_skip_rotation_enabled_flag : 1; + RK_U32 transform_skip_context_enabled_flag : 1; + RK_U32 implicit_rdpcm_enabled_flag : 1; + RK_U32 explicit_rdpcm_enabled_flag : 1; + RK_U32 extended_precision_processing_flag : 1; + RK_U32 intra_smoothing_disabled_flag : 1; + RK_U32 high_precision_offsets_enabled_flag : 1; + RK_U32 persistent_rice_adaptation_enabled_flag : 1; + RK_U32 cabac_bypass_alignment_enabled_flag : 1; + // pps exension flags + RK_U32 cross_component_prediction_enabled_flag : 1; + RK_U32 chroma_qp_offset_list_enabled_flag : 1; + }; + RK_U32 dwCodingSettingPicturePropertyFlags; + }; + RK_S8 pps_cb_qp_offset; + RK_S8 pps_cr_qp_offset; + RK_U8 num_tile_columns_minus1; + RK_U8 num_tile_rows_minus1; + RK_U16 column_width_minus1[19]; + RK_U16 row_height_minus1[21]; + RK_U8 diff_cu_qp_delta_depth; + RK_S8 pps_beta_offset_div2; + RK_S8 pps_tc_offset_div2; + RK_U8 log2_parallel_merge_level_minus2; + RK_S32 CurrPicOrderCntVal; + DXVA_PicEntry_HEVC RefPicList[16]; + RK_U8 ReservedBits5; + RK_S32 PicOrderCntValList[16]; + RK_U8 RefPicSetStCurrBefore[8]; + RK_U8 RefPicSetStCurrAfter[8]; + RK_U8 RefPicSetLtCurr[8]; + RK_U16 ReservedBits6; + RK_U16 ReservedBits7; + RK_U32 StatusReportFeedbackNumber; + RK_U32 vps_id; + RK_U32 pps_id; + RK_U32 sps_id; + RK_S32 current_poc; + + Short_SPS_RPS_HEVC cur_st_rps; + Short_SPS_RPS_HEVC sps_st_rps[64]; + LT_SPS_RPS_HEVC sps_lt_rps[32]; + + // PPS exentison + RK_U8 log2_max_transform_skip_block_size; + RK_U8 diff_cu_chroma_qp_offset_depth; + RK_S8 cb_qp_offset_list[6]; + RK_S8 cr_qp_offset_list[6]; + RK_U8 chroma_qp_offset_list_len_minus1; + + RK_U8 scaling_list_data_present_flag; + RK_U8 ps_update_flag; + RK_U8 rps_update_flag; +} DXVA_PicParams_HEVC, *LPDXVA_PicParams_HEVC; + +/* HEVC Quantizatiuon Matrix structure */ +typedef struct DXVA_Qmatrix_HEVC_t { + RK_U8 ucScalingLists0[6][16]; + RK_U8 ucScalingLists1[6][64]; + RK_U8 ucScalingLists2[6][64]; + RK_U8 ucScalingLists3[2][64]; + RK_U8 ucScalingListDCCoefSizeID2[6]; + RK_U8 ucScalingListDCCoefSizeID3[2]; +} DXVA_Qmatrix_HEVC, *LPDXVA_Qmatrix_HEVC; + +/* HEVC Slice Control Structure */ +typedef struct DXVA_Slice_HEVC_Short_t { + RK_U32 BSNALunitDataLocation; + RK_U32 SliceBytesInBuffer; + RK_U16 wBadSliceChopping; +} DXVA_Slice_HEVC_Short, *LPDXVA_Slice_HEVC_Short; + +/* just use in the case of pps->slice_header_extension_present_flag is 1 */ +typedef struct DXVA_Slice_HEVC_Cut_Param_t { + RK_U32 start_bit; + RK_U32 end_bit; + RK_U16 is_enable; +} DXVA_Slice_HEVC_Cut_Param, *LPDXVA_Slice_HEVC_Cut_Param; + +typedef struct h265d_dxva2_picture_context { + DXVA_PicParams_HEVC pp; + DXVA_Qmatrix_HEVC qm; + RK_U32 slice_count; + DXVA_Slice_HEVC_Short *slice_short; + const RK_U8 *bitstream; + RK_U32 bitstream_size; + DXVA_Slice_HEVC_Cut_Param *slice_cut_param; + RK_S32 max_slice_num; +} h265d_dxva2_picture_context_t; + +#endif /* H265D_SYNTAX_H */ diff --git a/osal/mpp_allocator_impl.h b/mpp/common/h265e_syntax.h similarity index 56% rename from osal/mpp_allocator_impl.h rename to mpp/common/h265e_syntax.h index d162478ba..ae678c0bd 100644 --- a/osal/mpp_allocator_impl.h +++ b/mpp/common/h265e_syntax.h @@ -1,32 +1,38 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_ALLOCATOR_IMPL_H__ -#define __MPP_ALLOCATOR_IMPL_H__ - -#include "mpp_thread.h" -#include "os_allocator.h" - -typedef struct MppAllocatorImpl_t { - pthread_mutex_t lock; - MppBufferType type; - size_t alignment; - os_allocator os_api; - void *ctx; -} MppAllocatorImpl; - -#endif /*__MPP_ALLOCATOR_IMPL_H__*/ - +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_SYNTAX_H +#define H265E_SYNTAX_H + +#include "rk_type.h" + +typedef struct H265eSyntax_t { + RK_S32 idr_request; +// RK_S32 eos; +} H265eSyntax; + +typedef struct H265eFeedback_t { + RK_U32 bs_size; + RK_U32 enc_pic_cnt; + RK_U32 pic_type; + RK_U32 avg_ctu_qp; + RK_U32 gop_idx; + RK_U32 poc; + RK_U32 src_idx; + RK_U32 status; +} H265eFeedback; + +#endif diff --git a/mpp/common/h265e_syntax_new.h b/mpp/common/h265e_syntax_new.h new file mode 100644 index 000000000..724b29a76 --- /dev/null +++ b/mpp/common/h265e_syntax_new.h @@ -0,0 +1,229 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef H265E_SYNTAX_NEW_H +#define H265E_SYNTAX_NEW_H +#include "mpp_rc.h" +#include "h265_syntax.h" +#include "rc.h" + +typedef struct H265PicEntry_t { + RK_U8 slot_idx; +} H265ePicEntry; + +typedef struct H265ePicParams_t { + RK_U16 pic_width; + RK_U16 pic_height; + RK_U16 hor_stride; + RK_U16 ver_stride; + RK_U16 pic_ofsty; + RK_U16 pic_oftx; + RK_U32 mpp_format; + union { + struct { + RK_U16 chroma_format_idc : 2; + RK_U16 separate_colour_plane_flag : 1; + RK_U16 bit_depth_luma_minus8 : 3; + RK_U16 bit_depth_chroma_minus8 : 3; + RK_U16 log2_max_pic_order_cnt_lsb_minus4 : 4; + RK_U16 NoPicReorderingFlag : 1; + RK_U16 NoBiPredFlag : 1; + RK_U16 ReservedBits1 : 1; + }; + RK_U16 wFormatAndSequenceInfoFlags; + }; + RK_U8 sps_max_dec_pic_buffering_minus1; + RK_U8 log2_min_luma_coding_block_size_minus3; + RK_U8 log2_diff_max_min_luma_coding_block_size; + RK_U8 log2_min_transform_block_size_minus2; + RK_U8 log2_diff_max_min_transform_block_size; + RK_U8 max_transform_hierarchy_depth_inter; + RK_U8 max_transform_hierarchy_depth_intra; + RK_U8 num_short_term_ref_pic_sets; + RK_U8 num_long_term_ref_pics_sps; + RK_U8 num_ref_idx_l0_default_active_minus1; + RK_U8 num_ref_idx_l1_default_active_minus1; + RK_S8 init_qp_minus26; + RK_U16 ReservedBits2; + + union { + struct { + RK_U32 scaling_list_enabled_flag : 1; + RK_U32 amp_enabled_flag : 1; + RK_U32 sample_adaptive_offset_enabled_flag : 1; + RK_U32 pcm_enabled_flag : 1; + RK_U32 pcm_sample_bit_depth_luma_minus1 : 4; + RK_U32 pcm_sample_bit_depth_chroma_minus1 : 4; + RK_U32 log2_min_pcm_luma_coding_block_size_minus3 : 2; + RK_U32 log2_diff_max_min_pcm_luma_coding_block_size : 2; + RK_U32 pcm_loop_filter_disabled_flag : 1; + RK_U32 long_term_ref_pics_present_flag : 1; + RK_U32 sps_temporal_mvp_enabled_flag : 1; + RK_U32 strong_intra_smoothing_enabled_flag : 1; + RK_U32 dependent_slice_segments_enabled_flag : 1; + RK_U32 output_flag_present_flag : 1; + RK_U32 num_extra_slice_header_bits : 3; + RK_U32 sign_data_hiding_enabled_flag : 1; + RK_U32 cabac_init_present_flag : 1; + RK_U32 ReservedBits3 : 5; + }; + RK_U32 CodingParamToolFlags; + }; + + union { + struct { + RK_U32 constrained_intra_pred_flag : 1; + RK_U32 transform_skip_enabled_flag : 1; + RK_U32 cu_qp_delta_enabled_flag : 1; + RK_U32 pps_slice_chroma_qp_offsets_present_flag : 1; + RK_U32 weighted_pred_flag : 1; + RK_U32 weighted_bipred_flag : 1; + RK_U32 transquant_bypass_enabled_flag : 1; + RK_U32 tiles_enabled_flag : 1; + RK_U32 entropy_coding_sync_enabled_flag : 1; + RK_U32 uniform_spacing_flag : 1; + RK_U32 loop_filter_across_tiles_enabled_flag : 1; + RK_U32 pps_loop_filter_across_slices_enabled_flag : 1; + RK_U32 deblocking_filter_override_enabled_flag : 1; + RK_U32 pps_deblocking_filter_disabled_flag : 1; + RK_U32 lists_modification_present_flag : 1; + RK_U32 slice_segment_header_extension_present_flag : 1; + RK_U32 ReservedBits4 : 16; + }; + RK_U32 CodingSettingPicturePropertyFlags; + }; + RK_S8 pps_cb_qp_offset; + RK_S8 pps_cr_qp_offset; + RK_U8 num_tile_columns_minus1; + RK_U8 num_tile_rows_minus1; + RK_S32 column_width_minus1[19]; + RK_S32 row_height_minus1[21]; + RK_U8 diff_cu_qp_delta_depth; + RK_S8 pps_beta_offset_div2; + RK_S8 pps_tc_offset_div2; + RK_U8 log2_parallel_merge_level_minus2; + RK_U32 vps_id; + RK_U32 pps_id; + RK_U32 sps_id; + RK_U8 scaling_list_data_present_flag; +} H265ePicParams; + +typedef struct H265eSlicParams_t { + union { + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 sli_flsh : 1; + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 merge_up_flag : 1; + RK_U32 merge_left_flag : 1; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_en : 1; + RK_U32 pic_out_flg : 1; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 no_out_pri_pic : 1; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sli_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 st_ref_pic_flg : 1; + RK_U32 num_pos_pic : 1; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + RK_U32 ReservedBits : 3; + }; + RK_U32 CodingSliceFlags; + }; + + H265ePicEntry recon_pic; + H265ePicEntry ref_pic; + RK_S8 sli_tc_ofst_div2; + RK_S8 sli_beta_ofst_div2; + RK_S8 sli_cb_qp_ofst; + RK_U8 sli_qp; + RK_U8 max_mrg_cnd; + RK_U8 lst_entry_l0; + RK_U8 num_refidx_l1_act; + RK_U8 num_refidx_l0_act; + RK_U8 slice_type; + RK_U8 slice_rsrv_flg; + RK_U8 sli_pps_id; + RK_U8 lt_idx_sps; + RK_U8 num_lt_pic; + RK_U8 st_ref_pic_idx; + RK_U8 num_lt_sps; + RK_U8 used_by_s0_flg; + RK_U8 num_neg_pic; + RK_U16 sli_poc_lsb; + RK_U16 sli_hdr_ext_len; + RK_U16 poc_lsb_lt0; + RK_U16 sli_max_num_m1; + RK_U16 sli_splt_cnum_m1; + RK_U16 dlt_poc_msb_cycl0; + RK_U16 dlt_poc_s0_m10; + RK_U16 dlt_poc_s0_m11; + RK_U16 dlt_poc_s0_m12; + RK_U16 dlt_poc_s0_m13; + RK_U16 poc_lsb_lt1; + RK_U16 poc_lsb_lt2; + RK_U16 dlt_poc_msb_cycl1; + RK_U16 dlt_poc_msb_cycl2; + RK_U32 sli_splt_byte; + RK_U32 tot_poc_num; + RK_U32 non_reference_flag; + RK_S32 temporal_id; +} H265eSlicParams; +/* + * Split reference frame configure to two parts + * The first part is slice depended info like poc / frame_num, and frame + * type and flags. + * The other part is gop structure depended info like gop index, ref_status + * and ref_frm_index. This part is inited from dpb gop hierarchy info. + */ + +typedef struct UserDatas_t { + void *plt_data; +} UserDatas; + +typedef struct H265eSyntax_new_t { + RK_S32 idr_request; + H265ePicParams pp; + H265eSlicParams sp; + void *dpb; +} H265eSyntax_new; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 h265e_syntax_fill(void *ctx); +RK_S32 h265e_get_nal_type(H265eSlicParams* sp, RK_S32 frame_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/common/jpegd_syntax.h b/mpp/common/jpegd_syntax.h new file mode 100644 index 000000000..cd779da42 --- /dev/null +++ b/mpp/common/jpegd_syntax.h @@ -0,0 +1,193 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JPEGD_SYNTAX_H +#define JPEGD_SYNTAX_H + +#include "mpp_frame.h" + +#define JPEGDEC_YUV400 (0) +#define JPEGDEC_YUV420 (2) +#define JPEGDEC_YUV422 (3) +#define JPEGDEC_YUV444 (4) +#define JPEGDEC_YUV440 (5) +#define JPEGDEC_YUV411 (6) + +#define DCT_SAMPLE_PRECISION_8 (8) + +#define JPEGD_STREAM_BUFF_SIZE (512*1024) +#define MAX_COMPONENTS (3) /* for JFIF: YCbCr */ +#define DRI_MARKER_LENGTH (4) /* must be 4 bytes */ +#define QUANTIZE_TABLE_LENGTH (64) +#define MAX_AC_HUFFMAN_TABLE_LENGTH (162) /* for baseline */ +#define MAX_DC_HUFFMAN_TABLE_LENGTH (12) /* for baseline */ +#define MAX_HUFFMAN_CODE_BIT_LENGTH (16) /* The longest code word is 16 bits */ +#define ZERO_PADDING_LENGTH (4) /* 4 Bytes */ +#define JPEGD_BASELINE_TABLE_SIZE (QUANTIZE_TABLE_LENGTH * 3 \ + + MAX_AC_HUFFMAN_TABLE_LENGTH * 2 \ + + MAX_DC_HUFFMAN_TABLE_LENGTH * 2 \ + + ZERO_PADDING_LENGTH) /* 544 Bytes */ + +#define JPEGD_DBG_FUNCTION (0x00000001) +#define JPEGD_DBG_STARTCODE (0x00000002) +#define JPEGD_DBG_TABLE (0x00000004) +#define JPEGD_DBG_RESULT (0x00000008) +#define JPEGD_DBG_IO (0x00000010) /* input and output write file */ +#define JPEGD_DBG_PARSER_INFO (0x00000020) /* parser information */ +#define JPEGD_DBG_SYNTAX_ERR (0x00000040) /* syntax error */ +#define JPEGD_DBG_HAL_INFO (0x00000080) /* hal information */ +#define JPEGD_DBG_HAL_TBL (0x00000100) /* hal information */ + +extern RK_U32 jpegd_debug; + +#define jpegd_dbg(flag, fmt, ...) mpp_dbg(jpegd_debug, flag, fmt, ## __VA_ARGS__) +#define jpegd_dbg_f(flag, fmt, ...) mpp_dbg_f(jpegd_debug, flag, fmt, ## __VA_ARGS__) + +#define jpegd_dbg_func(fmt, ...) jpegd_dbg_f(JPEGD_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define jpegd_dbg_marker(fmt, ...) jpegd_dbg(JPEGD_DBG_STARTCODE, fmt, ## __VA_ARGS__) +#define jpegd_dbg_table(fmt, ...) jpegd_dbg(JPEGD_DBG_TABLE, fmt, ## __VA_ARGS__) +#define jpegd_dbg_result(fmt, ...) jpegd_dbg(JPEGD_DBG_RESULT, fmt, ## __VA_ARGS__) +#define jpegd_dbg_io(fmt, ...) jpegd_dbg(JPEGD_DBG_IO, fmt, ## __VA_ARGS__) +#define jpegd_dbg_parser(fmt, ...) jpegd_dbg(JPEGD_DBG_PARSER_INFO, fmt, ## __VA_ARGS__) +#define jpegd_dbg_syntax(fmt, ...) jpegd_dbg(JPEGD_DBG_SYNTAX_ERR, fmt, ## __VA_ARGS__) +#define jpegd_dbg_hal(fmt, ...) jpegd_dbg(JPEGD_DBG_HAL_INFO, fmt, ## __VA_ARGS__) + + +enum huffman_table_type { + HUFFMAN_TABLE_TYPE_DC = 0, + HUFFMAN_TABLE_TYPE_AC = 1, + HUFFMAN_TABLE_TYPE_BUTT = 2, +}; + +enum huffman_table_id { + HUFFMAN_TABLE_ID_ZERO = 0, + HUFFMAN_TABLE_ID_ONE = 1, + HUFFMAN_TABLE_ID_TWO = 2, + HUFFMAN_TABLE_ID_THREE = 3, + HUFFMAN_TABLE_ID_BUTT = 4, +}; + +enum quantize_table_id { + QUANTIZE_TABLE_ID_ZERO = 0, + QUANTIZE_TABLE_ID_ONE = 1, + QUANTIZE_TABLE_ID_TWO = 2, + QUANTIZE_TABLE_ID_THREE = 3, + QUANTIZE_TABLE_ID_BUTT = 4, +}; + +/* Alternating Current Table */ +typedef struct { + RK_U32 bits[MAX_HUFFMAN_CODE_BIT_LENGTH]; + RK_U32 vals[MAX_AC_HUFFMAN_TABLE_LENGTH]; + RK_U32 actual_length; /* calculate based on actual stream */ +} AcTable; + +/* Direct Current Table */ +typedef struct { + RK_U32 bits[MAX_HUFFMAN_CODE_BIT_LENGTH]; + RK_U32 vals[MAX_DC_HUFFMAN_TABLE_LENGTH]; + RK_U32 actual_length; /* calculate based on actual stream */ +} DcTable; + +typedef struct JpegdSyntax { + /* just 16 bits because quantization parameters are much less than 2^16 */ + RK_U16 quant_matrixes[4][QUANTIZE_TABLE_LENGTH]; + + /* only two ac table for baseline */ + AcTable ac_table[2]; + + /* only two dc table for baseline */ + DcTable dc_table[2]; + + /* quantizer scale calculated from quant_matrixes */ + RK_U32 qscale[4]; + + /* output format */ + MppFrameFormat output_fmt; + + /* especially for jpeg */ + RK_U32 yuv_mode; + RK_U8 fill_bottom; + RK_U8 fill_right; + + /* syntax in SOS */ + RK_U8 scan_start; + RK_U8 scan_end; + RK_U8 prev_shift; /* Ah */ + RK_U8 point_transform; /* Al */ + + /* 0 - not found; 1 - found */ + RK_U8 dht_found; + RK_U8 eoi_found; + RK_U8 sof0_found; + + /* amount of quantize tables: 1 or 3 */ + RK_U8 qtable_cnt; + + /* length of sos segment */ + RK_U32 sos_len; + + /* decoded bytes by software */ + RK_U32 strm_offset; + + /* hardware decode start address */ + RK_U8 *cur_pos; + + /* length of a jpeg packet */ + RK_U32 pkt_len; + + /* Horizontal pixel density */ + RK_U16 hor_density; + + /* Vertical pixel density */ + RK_U16 ver_density; + + RK_U32 width, height; + RK_U32 hor_stride, ver_stride; + + /* Number of components in frame */ + RK_U32 nb_components; + + /* Component id */ + RK_U32 component_id[MAX_COMPONENTS]; + + /* Horizontal sampling factor */ + RK_U32 h_count[MAX_COMPONENTS]; + + /* Vertical sampling factor */ + RK_U32 v_count[MAX_COMPONENTS]; + + /* Huffman Table ID used by DC */ + RK_U32 dc_index[MAX_COMPONENTS]; + + /* Huffman Table ID used by AC */ + RK_U32 ac_index[MAX_COMPONENTS]; + + /* maximum h and v counts */ + RK_U32 h_max, v_max; + + /* quant table index for each component */ + RK_U32 quant_index[MAX_COMPONENTS]; + + RK_U32 restart_interval; + + RK_U8 sample_precision; + RK_U8 qtbl_entry; + RK_U8 htbl_entry; +} JpegdSyntax; + +#endif /* JPEGD_SYNTAX_H */ diff --git a/mpp/common/jpege_syntax.h b/mpp/common/jpege_syntax.h new file mode 100644 index 000000000..b30144e35 --- /dev/null +++ b/mpp/common/jpege_syntax.h @@ -0,0 +1,118 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JPEGE_SYNTAX_H +#define JPEGE_SYNTAX_H + +#include "mpp_frame.h" +#include "rk_venc_cmd.h" + +#define MAX_NUMBER_OF_COMPONENTS 3 +#define DCT_SIZE 8 + +typedef enum EntroyTblClass_t { + TABLE_DC = 0, + TABLE_AC = 1, +} EntroyTblClass; + +typedef union JPEGCompInfo_t { + struct { + RK_U32 component_id : 8; + RK_U32 h_sample_factor : 8; + RK_U32 v_sample_factor : 8; + RK_U32 tbl_selector : 8; + }; + RK_U32 val; +} JPEGCompInfo; + +typedef struct JpegeSyntax_t { + RK_U32 width; + RK_U32 height; + RK_U32 hor_stride; + RK_U32 ver_stride; + RK_U32 mcu_hor_cnt; + RK_U32 mcu_ver_cnt; + RK_U32 mcu_cnt; + RK_U32 mcu_width; + RK_U32 mcu_height; + MppFrameFormat format; + MppFrameChromaFormat format_out; + MppFrameColorSpace color; + MppEncRotationCfg rotation; + RK_S32 mirroring; + RK_U32 offset_x; + RK_U32 offset_y; + + /* For quantization table */ + RK_S32 q_mode; + RK_S32 quant; + RK_S32 q_factor; + RK_S32 qf_min; + RK_S32 qf_max; + RK_U8 *qtable_y; + RK_U8 *qtable_u; + RK_U8 *qtable_v; + + /* + * For color conversion + * + * 0 = bt601 + * 1 = bt709 + * 2 = user defined + */ + RK_U32 color_conversion_type; + RK_U32 coeffA; + RK_U32 coeffB; + RK_U32 coeffC; + RK_U32 coeffE; + RK_U32 coeffF; + + /* For slice encoding mode */ + RK_U32 slice_enable; + RK_U32 slice_size_mb_rows; + + /* + * For unit type and density + * + * units_type 0 - no unit + * 1 - dots per inch + * 2 - dots per cm + * + * X/Y density specify the pixel aspect ratio + */ + RK_U32 units_type; + RK_U32 density_x; + RK_U32 density_y; + + /* For comment header */ + RK_U32 comment_length; + RK_U8 *comment_data; + + /* For jpeg low delay slice encoding */ + RK_U32 low_delay; + RK_U32 part_rows; + RK_U32 restart_ri; + + RK_U32 nb_components; + JPEGCompInfo comp_info[MAX_NUMBER_OF_COMPONENTS]; +} JpegeSyntax; + +typedef struct JpegeFeedback_t { + RK_U32 hw_status; /* zero -> correct; non-zero -> error */ + RK_U32 stream_length; +} JpegeFeedback; + +#endif diff --git a/mpp/common/m2vd_syntax.h b/mpp/common/m2vd_syntax.h new file mode 100644 index 000000000..e6bb9a4b3 --- /dev/null +++ b/mpp/common/m2vd_syntax.h @@ -0,0 +1,141 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef M2VD_SYNTAX_H +#define M2VD_SYNTAX_H + +#include "rk_type.h" + +typedef struct DXVA_PicEntry_M2V_t { + union { + struct { + RK_U8 Index7Bits : 7; + RK_U8 AssociatedFlag : 1; + }; + RK_U8 bPicEntry; + }; +} DXVA_PicEntry_M2V; + + +/* ISO/IEC 13818-2 section 6.2.2.1: sequence_Dxvaer() */ +typedef struct M2VDDxvaSeq_t { + RK_U32 decode_width; //horizontal_size_value + RK_U32 decode_height; //vertical_size_value + RK_S32 aspect_ratio_information; + RK_S32 frame_rate_code; + RK_S32 bit_rate_value; + RK_S32 vbv_buffer_size; + RK_S32 constrained_parameters_flag; + RK_U32 load_intra_quantizer_matrix; //[TEMP] + RK_U32 load_non_intra_quantizer_matrix; //[TEMP] +} M2VDDxvaSeq; + +/* ISO/IEC 13818-2 section 6.2.2.3: sequence_extension() */ +typedef struct M2VDDxvaSeqExt_t { + RK_S32 profile_and_level_indication; + RK_S32 progressive_sequence; + RK_S32 chroma_format; + RK_S32 low_delay; + RK_S32 frame_rate_extension_n; + RK_S32 frame_rate_extension_d; +} M2VDDxvaSeqExt; + +/* ISO/IEC 13818-2 section 6.2.2.6: group_of_pictures_Dxvaer() */ +typedef struct M2VDDxvaGop_t { + RK_S32 drop_flag; + RK_S32 hour; + RK_S32 minute; + RK_S32 sec; + RK_S32 frame; + RK_S32 closed_gop; + RK_S32 broken_link; +} M2VDDxvaGop; + + +/* ISO/IEC 13818-2 section 6.2.3: picture_Dxvaer() */ +typedef struct M2VDDxvaPic_t { + RK_S32 temporal_reference; + RK_S32 picture_coding_type; + RK_S32 pre_picture_coding_type; + RK_S32 vbv_delay; + RK_S32 full_pel_forward_vector; + RK_S32 forward_f_code; + RK_S32 full_pel_backward_vector; + RK_S32 backward_f_code; + RK_S32 pre_temporal_reference; +} M2VDDxvaPic; + + +/* ISO/IEC 13818-2 section 6.2.2.4: sequence_display_extension() */ +typedef struct M2VDDxvaSeqDispExt_t { + RK_S32 video_format; + RK_S32 color_description; + RK_S32 color_primaries; + RK_S32 transfer_characteristics; + RK_S32 matrix_coefficients; +} M2VDDxvaSeqDispExt; + +/* ISO/IEC 13818-2 section 6.2.3.1: picture_coding_extension() Dxvaer */ +typedef struct M2VDDxvaPicCodeExt_t { + RK_S32 f_code[2][2]; + RK_S32 intra_dc_precision; + RK_S32 picture_structure; + RK_S32 top_field_first; + RK_S32 frame_pred_frame_dct; + RK_S32 concealment_motion_vectors; + RK_S32 q_scale_type; + RK_S32 intra_vlc_format; + RK_S32 alternate_scan; + RK_S32 repeat_first_field; + RK_S32 chroma_420_type; + RK_S32 progressive_frame; + RK_S32 composite_display_flag; + RK_S32 v_axis; + RK_S32 field_sequence; + RK_S32 sub_carrier; + RK_S32 burst_amplitude; + RK_S32 sub_carrier_phase; +} M2VDDxvaPicCodeExt; + + +/* ISO/IEC 13818-2 section 6.2.3.3: picture_display_extension() Dxvaer */ +typedef struct M2VDDxvaPicDispExt_t { + RK_S32 frame_center_horizontal_offset[3]; + RK_S32 frame_center_vertical_offset[3]; +} M2VDDxvaPicDispExt; + + +typedef struct M2VDDxvaParam_t { + RK_U32 bitstream_length; + RK_U32 bitstream_start_bit; + RK_U32 bitstream_offset; + RK_U8 *qp_tab; + + DXVA_PicEntry_M2V CurrPic; + DXVA_PicEntry_M2V frame_refs[4]; + + RK_U32 seq_ext_head_dec_flag; + + M2VDDxvaSeq seq; + M2VDDxvaSeqExt seq_ext; + M2VDDxvaGop gop; + M2VDDxvaPic pic; + M2VDDxvaSeqDispExt seq_disp_ext; + M2VDDxvaPicCodeExt pic_code_ext; + M2VDDxvaPicDispExt pic_disp_ext; +} M2VDDxvaParam; + +#endif diff --git a/mpp/common/mpg4d_syntax.h b/mpp/common/mpg4d_syntax.h new file mode 100644 index 000000000..bf7dd9b6c --- /dev/null +++ b/mpp/common/mpg4d_syntax.h @@ -0,0 +1,148 @@ +/* + * + * Copyright 2010 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file mpeg4d_syntax.h + * @brief + * @author gzl(gzl@rock-chips.com) + * @version 1.0.0 + * @history + * 2016.04.06 : Create + */ +#ifndef MPG4D_SYNTAX_H +#define MPG4D_SYNTAX_H + +#include "dxva_syntax.h" + +#define MPEG4_VIDOBJLAY_AR_SQUARE 1 +#define MPEG4_VIDOBJLAY_AR_625TYPE_43 2 +#define MPEG4_VIDOBJLAY_AR_525TYPE_43 3 +#define MPEG4_VIDOBJLAY_AR_625TYPE_169 8 +#define MPEG4_VIDOBJLAY_AR_525TYPE_169 9 +#define MPEG4_VIDOBJLAY_AR_EXTPAR 15 + +#define MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR 0 +#define MPEG4_VIDOBJLAY_SHAPE_BINARY 1 +#define MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY 2 +#define MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE 3 + +/*video sprite specific*/ +#define MPEG4_SPRITE_NONE 0 +#define MPEG4_SPRITE_STATIC 1 +#define MPEG4_SPRITE_GMC 2 + +/*video vop specific*/ +typedef enum { + MPEG4_RESYNC_VOP = -2, + MPEG4_INVALID_VOP = -1, + MPEG4_I_VOP = 0, + MPEG4_P_VOP = 1, + MPEG4_B_VOP = 2, + MPEG4_S_VOP = 3, + MPEG4_N_VOP = 4, + MPEG4_D_VOP = 5, /*Drop Frame*/ +} MPEG4VOPType; + +#define MPEG4_HDR_ERR -2 +#define MPEG4_DEC_ERR -4 +#define MPEG4_VLD_ERR -5 +#define MPEG4_FORMAT_ERR -6 +#define MPEG4_DIVX_PBBI -7 +#define MPEG4_INFO_CHANGE -10 + +/* MPEG4PT2 Picture Parameter structure */ +typedef struct DXVA_PicParams_MPEG4_PART2 { + RK_U8 short_video_header; + RK_U8 vop_coding_type; + RK_U8 vop_quant; + RK_U16 wDecodedPictureIndex; + RK_U16 wDeblockedPictureIndex; + RK_U16 wForwardRefPictureIndex; + RK_U16 wBackwardRefPictureIndex; + RK_U16 vop_time_increment_resolution; + RK_U32 TRB[2]; + RK_U32 TRD[2]; + + union { + struct { + RK_U16 unPicPostProc : 2; + RK_U16 interlaced : 1; + RK_U16 quant_type : 1; + RK_U16 quarter_sample : 1; + RK_U16 resync_marker_disable : 1; + RK_U16 data_partitioned : 1; + RK_U16 reversible_vlc : 1; + RK_U16 reduced_resolution_vop_enable : 1; + RK_U16 vop_coded : 1; + RK_U16 vop_rounding_type : 1; + RK_U16 intra_dc_vlc_thr : 3; + RK_U16 top_field_first : 1; + RK_U16 alternate_vertical_scan_flag : 1; + }; + RK_U16 wPicFlagBitFields; + }; + RK_U8 profile_and_level_indication; + RK_U8 video_object_layer_verid; + RK_U16 vop_width; + RK_U16 vop_height; + union { + struct { + RK_U16 sprite_enable : 2; + RK_U16 no_of_sprite_warping_points : 6; + RK_U16 sprite_warping_accuracy : 2; + }; + RK_U16 wSpriteBitFields; + }; + RK_S16 warping_mv[4][2]; + union { + struct { + RK_U8 vop_fcode_forward : 3; + RK_U8 vop_fcode_backward : 3; + }; + RK_U8 wFcodeBitFields; + }; + RK_U16 StatusReportFeedbackNumber; + RK_U16 Reserved16BitsA; + RK_U16 Reserved16BitsB; + + // FIXME: added for rockchip hardware information + RK_U32 custorm_version; + RK_U32 prev_coding_type; + RK_U32 time_bp; + RK_U32 time_pp; + RK_U32 header_bits; +} DXVA_PicParams_MPEG4_PART2, *LPDXVA_PicParams_MPEG4_PART2; + +typedef struct DXVA_QmatrixData { + RK_U8 bNewQmatrix[4]; // intra Y, inter Y, intra chroma, inter chroma + RK_U8 Qmatrix[4][64]; // NOTE: here we change U16 to U8 +} DXVA_QmatrixData, *LPDXVA_QmatrixData; + +typedef struct mpeg4d_dxva2_picture_context { + DXVA_PicParams_MPEG4_PART2 pp; + DXVA_QmatrixData qm; + + // pointer and storage for buffer descriptor + DXVA2_DecodeBufferDesc *data[3]; + DXVA2_DecodeBufferDesc desc[3]; + + RK_U32 frame_count; + const RK_U8 *bitstream; + RK_U32 bitstream_size; +} mpeg4d_dxva2_picture_context_t; + +#endif /* MPG4D_SYNTAX_H */ diff --git a/mpp/common/vp8d_syntax.h b/mpp/common/vp8d_syntax.h new file mode 100644 index 000000000..8de81408c --- /dev/null +++ b/mpp/common/vp8d_syntax.h @@ -0,0 +1,170 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VP8D_SYNTAX_H +#define VP8D_SYNTAX_H + +#include "rk_type.h" + +typedef struct DXVA_PicEntry_VP8_t { + union { + struct { + RK_U8 Index7Bits : 7; + RK_U8 AssociatedFlag : 1; + }; + RK_U8 bPicEntry; + }; +} DXVA_PicEntry_VP8; +typedef struct DXVA_segmentation_Vp8_t { + union { + struct { + RK_U8 segmentation_enabled : 1; + RK_U8 update_mb_segmentation_map : 1; + RK_U8 update_mb_segmentation_data : 1; + RK_U8 mb_segement_abs_delta : 1; + RK_U8 ReservedSegmentFlags4Bits : 4; + }; + RK_U8 wSegmentFlags; + }; + RK_S8 segment_feature_data[2][4]; + RK_U8 mb_segment_tree_probs[3]; +} DXVA_segmentation_VP8; + +typedef struct VP8DDxvaParam_t { + RK_U32 first_part_size; + RK_U32 width; + RK_U32 height; + DXVA_PicEntry_VP8 CurrPic; + union { + struct { + RK_U8 frame_type : 1; + RK_U8 version : 3; + RK_U8 show_frame : 1; + RK_U8 clamp_type : 1; + RK_U8 ReservedFrameTag2Bits: 2; + }; + RK_U8 wFrameTagFlags; + }; + DXVA_segmentation_VP8 stVP8Segments; + RK_U8 filter_type; + RK_U8 filter_level; + RK_U8 sharpness; + RK_U8 mode_ref_lf_delta_enabled; + RK_U8 mode_ref_lf_delta_update; + RK_S8 ref_lf_deltas[4]; + RK_S8 mode_lf_deltas[4]; + RK_U8 log2_nbr_of_dct_partitions; + RK_U8 base_qindex; + RK_S8 y1dc_delta_q; + RK_S8 y1ac_delta_q; + RK_S8 y2dc_delta_q; + RK_S8 y2ac_delta_q; + RK_S8 uvdc_delta_q; + RK_S8 uvac_delta_q; + + DXVA_PicEntry_VP8 alt_fb_idx; + DXVA_PicEntry_VP8 gld_fb_idx; + DXVA_PicEntry_VP8 lst_fb_idx; + + RK_U8 ref_frame_sign_bias_golden; + RK_U8 ref_frame_sign_bias_altref; + RK_U8 refresh_entropy_probs; + + RK_U8 vp8_coef_update_probs[4][8][3][11]; + RK_U8 probe_skip_false; + RK_U8 mb_no_coeff_skip; + RK_U8 prob_intra; + RK_U8 prob_last; + RK_U8 prob_golden; + RK_U8 intra_16x16_prob[4]; + RK_U8 intra_chroma_prob[3]; + RK_U8 vp8_mv_update_probs[2][19]; + + RK_U32 decMode; + RK_U32 bool_value; + RK_U32 bool_range; + RK_U32 stream_start_offset; + RK_U32 dctPartitionOffsets[8]; + RK_U32 bitstream_length; + RK_U32 stream_start_bit; + RK_U32 frameTagSize; + RK_U32 streamEndPos; + RK_U32 offsetToDctParts; +} DXVA_PicParams_VP8; + +#if 0 +typedef struct VP8DDxvaParam_t { + RK_U32 first_part_size; + RK_U32 width; + RK_U32 height; + DXVA_PicEntry_VP8 CurrPic; + union { + struct { + RK_U8 key_frame : 1; + RK_U8 segmentationEnabled : 1; + RK_U8 segmentationMapUpdate : 1; + RK_U8 modeRefLfEnabled : 1; + RK_U8 coeffSkipMode: 1; + RK_U8 reservedFormatInfo: 3; + }; + RK_U8 wFormatAndPictureInfoFlags; + }; + RK_U32 decMode; + RK_U32 loopFilterType; + RK_U32 loopFilterSharpness; + RK_U32 loopFilterLevel; + RK_U32 segmentFeatureMode; + RK_U32 vpVersion; + RK_U32 bool_value; + RK_U32 bool_range; + RK_U32 stream_start_offset; + RK_U32 stream_start_bit; + RK_U32 frameTagSize; + RK_U32 streamEndPos; + RK_U32 nbrDctPartitions; + RK_U32 offsetToDctParts; + + RK_S8 qpYAc; + RK_S8 qpYDc; + RK_S8 qpY2Ac; + RK_S8 qpY2Dc; + RK_S8 qpChAc; + RK_S8 qpChDc; + RK_U8 vp8_coef_update_probs[4][8][3][11]; + RK_U8 probe_skip_false; + RK_U8 prob_intra; + RK_U8 prob_last; + RK_U8 prob_golden; + RK_U8 intra_16x16_prob[4]; + RK_U8 intra_chroma_prob[3]; + RK_U8 vp8_mv_update_probs[2][19]; + RK_U8 vp8_segment_prob[3]; + + RK_U32 refFrameSignBias[2]; + RK_S32 dcPred[2]; + RK_S32 dcMatch[2]; + RK_S32 segmentQp[4]; + RK_S32 mbRefLfDelta[4]; + RK_S32 mbModeLfDelta[4]; + RK_U32 vp7ScanOrder[16]; + RK_S32 segmentLoopfilter[4]; + RK_U32 dctPartitionOffsets[8]; + RK_U32 bitstream_length; + DXVA_PicEntry_VP8 frame_refs[3]; +} DXVA_PicParams_VP8; +#endif +#endif diff --git a/mpp/common/vp8e_syntax.h b/mpp/common/vp8e_syntax.h new file mode 100644 index 000000000..ad9c500a9 --- /dev/null +++ b/mpp/common/vp8e_syntax.h @@ -0,0 +1,112 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VP8E_SYNTAX_H +#define VP8E_SYNTAX_H + +#include "rk_type.h" +#include "mpp_enc_cfg.h" + +typedef struct { + RK_S32 a1; + RK_S32 a2; + RK_S32 qp_prev; + RK_S32 qs[15]; + RK_S32 bits[15]; + RK_S32 pos; + RK_S32 len; + RK_S32 zero_div; +} Vp8eLinReg; + + +typedef struct vp8e_feedback_t { + /* rc */ + void *result; + RK_U32 hw_status; /* 0:corret, 1:error */ + + RK_S32 qp_sum; + RK_S32 cp[10]; + RK_S32 mad_count; + RK_S32 rlc_count; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; +} Vp8eFeedback; + +typedef struct vp8e_virture_buffer_t { + RK_S32 buffer_size; + RK_S32 bit_rate; //MppEncRcCfg.bps_target + RK_S32 bps_max; + RK_S32 bps_min; + RK_S32 bit_per_pic; + RK_S32 pic_time_inc; + RK_S32 time_scale; + RK_S32 units_in_tic; + RK_S32 virtual_bit_cnt; + RK_S32 real_bit_cnt; + RK_S32 buffer_occupancy; + RK_S32 skip_frame_target; + RK_S32 skipped_frames; + RK_S32 bucket_fullness; + RK_S32 gop_rem; +} Vp8eVirBuf; + +typedef struct { + RK_U8 pic_rc_enable; + RK_U8 pic_skip; + RK_U8 frame_coded; + RK_S32 mb_per_pic; + RK_S32 mb_rows; + RK_S32 curr_frame_intra; + RK_S32 prev_frame_intra; + RK_S32 fixed_qp; + RK_S32 qp_hdr; + RK_S32 qp_min; + RK_S32 qp_max; + RK_S32 qp_hdr_prev; + RK_S32 fps_out_num; //MppEncRcCfg.fps_out_num + RK_S32 fps_out_denom; //MppEncRcCfg.fps_out_denom + RK_S32 fps_out; + + RK_S32 target_pic_size; + RK_S32 frame_bit_cnt; + RK_S32 gop_qp_sum; + RK_S32 gop_qp_div; + RK_S32 frame_cnt; + RK_S32 gop_len; + RK_S32 intra_qp_delta; + RK_S32 fixed_intra_qp; + RK_S32 mb_qp_adjustment; + RK_S32 intra_picture_rate; + RK_S32 golden_picture_rate; + RK_S32 altref_picture_rate; + RK_U32 time_inc; + + Vp8eLinReg lin_reg; + Vp8eLinReg r_error; + Vp8eVirBuf virbuf; +} Vp8eRc; + +typedef enum Vp8eSyntaxType_e { + VP8E_SYN_CFG, + VP8E_SYN_RC, +} Vp8eSyntaxType; + +typedef struct { + Vp8eSyntaxType type; + void *data; +} Vp8eSyntax; +#endif /* VP8E_SYNTAX_H */ diff --git a/mpp/common/vp9d_syntax.h b/mpp/common/vp9d_syntax.h new file mode 100644 index 000000000..ada133615 --- /dev/null +++ b/mpp/common/vp9d_syntax.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef VP9D_SYNTAX_H +#define VP9D_SYNTAX_H + +#include "rk_type.h" + +typedef struct DXVA_PicEntry_VPx_t { + union { + struct { + RK_U8 Index7Bits : 7; + RK_U8 AssociatedFlag : 1; + }; + RK_U8 bPicEntry; + }; +} DXVA_PicEntry_VPx, *LPDXVA_PicEntry_Vpx; + +typedef struct DXVA_segmentation_VP9_t { + union { + struct { + RK_U8 enabled : 1; + RK_U8 update_map : 1; + RK_U8 temporal_update : 1; + RK_U8 abs_delta : 1; + RK_U8 ReservedSegmentFlags4Bits : 4; + }; + RK_U8 wSegmentInfoFlags; + }; + RK_U8 tree_probs[7]; + RK_U8 pred_probs[3]; + RK_S16 feature_data[8][4]; + RK_U8 feature_mask[8]; +} DXVA_segmentation_VP9; + +typedef struct { + RK_U8 y_mode[4][9]; + RK_U8 uv_mode[10][9]; + RK_U8 filter[4][2]; + RK_U8 mv_mode[7][3]; + RK_U8 intra[4]; + RK_U8 comp[5]; + RK_U8 single_ref[5][2]; + RK_U8 comp_ref[5]; + RK_U8 tx32p[2][3]; + RK_U8 tx16p[2][2]; + RK_U8 tx8p[2]; + RK_U8 skip[3]; + RK_U8 mv_joint[3]; + struct { + RK_U8 sign; + RK_U8 classes[10]; + RK_U8 class0; + RK_U8 bits[10]; + RK_U8 class0_fp[2][3]; + RK_U8 fp[3]; + RK_U8 class0_hp; + RK_U8 hp; + } mv_comp[2]; + RK_U8 partition[4][4][3]; +} DXVA_prob_vp9; + +typedef struct DXVA_PicParams_VP9_t { + DXVA_PicEntry_VPx CurrPic; + RK_U8 profile; + union { + struct { + RK_U16 frame_type : 1; + RK_U16 show_frame : 1; + RK_U16 error_resilient_mode : 1; + RK_U16 subsampling_x : 1; + RK_U16 subsampling_y : 1; + RK_U16 extra_plane : 1; + RK_U16 refresh_frame_context : 1; + RK_U16 intra_only : 1; + RK_U16 frame_context_idx : 2; + RK_U16 reset_frame_context : 2; + RK_U16 allow_high_precision_mv : 1; + RK_U16 parallelmode : 1; + RK_U16 show_existing_frame : 1; + }; + RK_U16 wFormatAndPictureInfoFlags; + }; + RK_U32 width; + RK_U32 height; + RK_U8 BitDepthMinus8Luma; + RK_U8 BitDepthMinus8Chroma; + RK_U8 interp_filter; + RK_U8 Reserved8Bits; + DXVA_PicEntry_VPx ref_frame_map[8]; + RK_U32 ref_frame_coded_width[8]; + RK_U32 ref_frame_coded_height[8]; + DXVA_PicEntry_VPx frame_refs[3]; + RK_S8 ref_frame_sign_bias[4]; + RK_S8 filter_level; + RK_S8 sharpness_level; + union { + struct { + RK_U8 mode_ref_delta_enabled : 1; + RK_U8 mode_ref_delta_update : 1; + RK_U8 use_prev_in_find_mv_refs : 1; + RK_U8 ReservedControlInfo5Bits : 5; + }; + RK_U8 wControlInfoFlags; + }; + RK_S8 ref_deltas[4]; + RK_S8 mode_deltas[2]; + RK_S16 base_qindex; + RK_S8 y_dc_delta_q; + RK_S8 uv_dc_delta_q; + RK_S8 uv_ac_delta_q; + DXVA_segmentation_VP9 stVP9Segments; + RK_U8 log2_tile_cols; + RK_U8 log2_tile_rows; + RK_U16 uncompressed_header_size_byte_aligned; + RK_U16 first_partition_size; + RK_U16 Reserved16Bits; + RK_U16 Reserved32Bits; + RK_U32 StatusReportFeedbackNumber; + struct { + RK_U8 y_mode[4][9]; + RK_U8 uv_mode[10][9]; + RK_U8 filter[4][2]; + RK_U8 mv_mode[7][3]; + RK_U8 intra[4]; + RK_U8 comp[5]; + RK_U8 single_ref[5][2]; + RK_U8 comp_ref[5]; + RK_U8 tx32p[2][3]; + RK_U8 tx16p[2][2]; + RK_U8 tx8p[2]; + RK_U8 skip[3]; + RK_U8 mv_joint[3]; + struct { + RK_U8 sign; + RK_U8 classes[10]; + RK_U8 class0; + RK_U8 bits[10]; + RK_U8 class0_fp[2][3]; + RK_U8 fp[3]; + RK_U8 class0_hp; + RK_U8 hp; + } mv_comp[2]; + RK_U8 partition[4][4][3]; + RK_U8 coef[4][2][2][6][6][3]; + } prob; + struct { + RK_U32 partition[4][4][4]; + RK_U32 skip[3][2]; + RK_U32 intra[4][2]; + RK_U32 tx32p[2][4]; + RK_U32 tx16p[2][4]; + RK_U32 tx8p[2][2]; + RK_U32 y_mode[4][10]; + RK_U32 uv_mode[10][10]; + RK_U32 comp[5][2]; + RK_U32 comp_ref[5][2]; + RK_U32 single_ref[5][2][2]; + RK_U32 mv_mode[7][4]; + RK_U32 filter[4][3]; + RK_U32 mv_joint[4]; + RK_U32 sign[2][2]; + RK_U32 classes[2][12]; // orign classes[12] + RK_U32 class0[2][2]; + RK_U32 bits[2][10][2]; + RK_U32 class0_fp[2][2][4]; + RK_U32 fp[2][4]; + RK_U32 class0_hp[2][2]; + RK_U32 hp[2][2]; + RK_U32 coef[4][2][2][6][6][3]; + RK_U32 eob[4][2][2][6][6][2]; + } counts; + struct { + DXVA_prob_vp9 p_flag; + DXVA_prob_vp9 p_delta; + RK_U8 coef_flag[4][2][2][6][6][3]; + RK_U8 coef_delta[4][2][2][6][6][3]; + } prob_flag_delta; + RK_U16 mvscale[3][2]; + RK_S8 txmode; + RK_S8 refmode; +} DXVA_PicParams_VP9, *LPDXVA_PicParams_VP9; + +typedef struct DXVA_Slice_VPx_Short_t { + RK_U32 BSNALunitDataLocation; + RK_U32 SliceByteInBuffer; + RK_U16 wBadSliceChopping; +} DXVA_Slice_VPx_Short, *LPDXVA_Slice_VPx_Short; + +#endif diff --git a/mpp/hal/CMakeLists.txt b/mpp/hal/CMakeLists.txt index 37506973e..06a806875 100644 --- a/mpp/hal/CMakeLists.txt +++ b/mpp/hal/CMakeLists.txt @@ -1,28 +1,69 @@ # vim: syntax=cmake include_directories(worker/inc) +include_directories(common) + +# Macro to conditionally add source files +# Usage: add_hal_source(SRC_LIST CONDITION SOURCE_FILE) +macro(add_hal_source SRC_LIST CONDITION SOURCE_FILE) + if (${CONDITION}) + list(APPEND ${SRC_LIST} ${SOURCE_FILE}) + endif() +endmacro() # ---------------------------------------------------------------------------- -# add mpp_hal implement +# add hardware hal # ---------------------------------------------------------------------------- -add_library(mpp_hal STATIC - hal_task.cpp - mpp_hal.cpp - ) - -set_target_properties(mpp_hal PROPERTIES FOLDER "mpp/hal") - -add_subdirectory(dummy) +add_subdirectory(vpu) +add_subdirectory(rkdec) +add_subdirectory(rkenc) +add_subdirectory(common) -add_subdirectory(rkdec/h264d) +merge_objects("${HAL_H263D}" hal_h263d_api) +merge_objects("${HAL_JPEGD}" hal_jpegd_api) +merge_objects("${HAL_MPEG2D}" hal_mpeg2d_api) +merge_objects("${HAL_MPEG4D}" hal_mpeg4d_api) +merge_objects("${HAL_VP8D}" hal_vp8d_api) +merge_objects("${HAL_VP9D}" hal_vp9d_api) +merge_objects("${HAL_AV1D}" hal_av1d_com hal_av1d_rkv hal_av1d_vpu) +merge_objects("${HAL_AVSD}" hal_avsd_api) +merge_objects("${HAL_AVS2D}" hal_avs2d_api) +merge_objects("${HAL_H264D}" hal_h264d_api) +merge_objects("${HAL_H265D}" hal_h265d_api) -add_subdirectory(rkdec/h265d) - -add_subdirectory(rkdec/vp9d) +merge_objects("${HAL_H264E}" hal_h264e_com hal_h264e_vepu5xx hal_h264e_vpu) +merge_objects("${HAL_H265E}" hal_h265e_com hal_h265e_vepu5xx) +merge_objects("${HAL_JPEGE}" hal_jpege_com hal_jpege_rkv hal_jpege_vpu) +merge_objects("${HAL_VP8E}" hal_vp8e_api) # ---------------------------------------------------------------------------- -# add hardware worker implement +# add mpp_hal implement # ---------------------------------------------------------------------------- -add_subdirectory(worker/libvpu) -add_subdirectory(worker/libv4l2) +add_library(mpp_hal STATIC + mpp_enc_hal.c + hal_task.c + mpp_hal.c + ) -target_link_libraries(mpp_hal hal_h264d hal_dummy) \ No newline at end of file +set_target_properties(mpp_hal PROPERTIES FOLDER "mpp/hal") + +target_link_libraries(mpp_hal + hal_common + hal_vepu5xx_common + hal_vepu_common + hal_rkvdec_com + ${HAL_AVSD} + ${HAL_AVS2D} + ${HAL_H263D} + ${HAL_H264D} + ${HAL_H265D} + ${HAL_MPEG2D} + ${HAL_MPEG4D} + ${HAL_VP8D} + ${HAL_VP9D} + ${HAL_JPEGD} + ${HAL_AV1D} + ${HAL_H264E} + ${HAL_JPEGE} + ${HAL_H265E} + ${HAL_VP8E} + ) diff --git a/mpp/hal/common/CMakeLists.txt b/mpp/hal/common/CMakeLists.txt new file mode 100644 index 000000000..22ba415e8 --- /dev/null +++ b/mpp/hal/common/CMakeLists.txt @@ -0,0 +1,26 @@ +# vim: syntax=cmake +include_directories(.) + +# ---------------------------------------------------------------------------- +# add hal common file +# ---------------------------------------------------------------------------- +add_library(hal_common OBJECT + hal_info.c + hal_bufs.c + ) + +if( HAVE_H264E ) + add_subdirectory(h264) +endif() + +if( HAVE_H265E ) + add_subdirectory(h265) +endif() + +if( HAVE_JPEGE ) + add_subdirectory(jpeg) +endif() + +if( HAVE_AV1D ) + add_subdirectory(av1) +endif() diff --git a/mpp/hal/common/av1/CMakeLists.txt b/mpp/hal/common/av1/CMakeLists.txt new file mode 100644 index 000000000..e40c71bd7 --- /dev/null +++ b/mpp/hal/common/av1/CMakeLists.txt @@ -0,0 +1,8 @@ +# vim: syntax=cmake +include_directories(../../rkdec/av1d/) +include_directories(../../rkdec/inc/) +include_directories(../../vpu/av1d/) + +add_library(hal_av1d_com OBJECT + film_grain_noise_table.c + ) diff --git a/mpp/hal/common/av1/film_grain_noise_table.c b/mpp/hal/common/av1/film_grain_noise_table.c new file mode 100644 index 000000000..9bd5379c3 --- /dev/null +++ b/mpp/hal/common/av1/film_grain_noise_table.c @@ -0,0 +1,374 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "film_grain_noise_table.h" +#include +#include + +static const RK_S32 gaussian_sequence[2048] = { + 56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820, + 224, 1248, 996, 272, -8, -916, -388, -732, -104, -188, 800, + 112, -652, -320, -376, 140, -252, 492, -168, 44, -788, 588, + -584, 500, -228, 12, 680, 272, -476, 972, -100, 652, 368, + 432, -196, -720, -192, 1000, -332, 652, -136, -552, -604, -4, + 192, -220, -136, 1000, -52, 372, -96, -624, 124, -24, 396, + 540, -12, -104, 640, 464, 244, -208, -84, 368, -528, -740, + 248, -968, -848, 608, 376, -60, -292, -40, -156, 252, -292, + 248, 224, -280, 400, -244, 244, -60, 76, -80, 212, 532, + 340, 128, -36, 824, -352, -60, -264, -96, -612, 416, -704, + 220, -204, 640, -160, 1220, -408, 900, 336, 20, -336, -96, + -792, 304, 48, -28, -1232, -1172, -448, 104, -292, -520, 244, + 60, -948, 0, -708, 268, 108, 356, -548, 488, -344, -136, + 488, -196, -224, 656, -236, -1128, 60, 4, 140, 276, -676, + -376, 168, -108, 464, 8, 564, 64, 240, 308, -300, -400, + -456, -136, 56, 120, -408, -116, 436, 504, -232, 328, 844, + -164, -84, 784, -168, 232, -224, 348, -376, 128, 568, 96, + -1244, -288, 276, 848, 832, -360, 656, 464, -384, -332, -356, + 728, -388, 160, -192, 468, 296, 224, 140, -776, -100, 280, + 4, 196, 44, -36, -648, 932, 16, 1428, 28, 528, 808, + 772, 20, 268, 88, -332, -284, 124, -384, -448, 208, -228, + -1044, -328, 660, 380, -148, -300, 588, 240, 540, 28, 136, + -88, -436, 256, 296, -1000, 1400, 0, -48, 1056, -136, 264, + -528, -1108, 632, -484, -592, -344, 796, 124, -668, -768, 388, + 1296, -232, -188, -200, -288, -4, 308, 100, -168, 256, -500, + 204, -508, 648, -136, 372, -272, -120, -1004, -552, -548, -384, + 548, -296, 428, -108, -8, -912, -324, -224, -88, -112, -220, + -100, 996, -796, 548, 360, -216, 180, 428, -200, -212, 148, + 96, 148, 284, 216, -412, -320, 120, -300, -384, -604, -572, + -332, -8, -180, -176, 696, 116, -88, 628, 76, 44, -516, + 240, -208, -40, 100, -592, 344, -308, -452, -228, 20, 916, + -1752, -136, -340, -804, 140, 40, 512, 340, 248, 184, -492, + 896, -156, 932, -628, 328, -688, -448, -616, -752, -100, 560, + -1020, 180, -800, -64, 76, 576, 1068, 396, 660, 552, -108, + -28, 320, -628, 312, -92, -92, -472, 268, 16, 560, 516, + -672, -52, 492, -100, 260, 384, 284, 292, 304, -148, 88, + -152, 1012, 1064, -228, 164, -376, -684, 592, -392, 156, 196, + -524, -64, -884, 160, -176, 636, 648, 404, -396, -436, 864, + 424, -728, 988, -604, 904, -592, 296, -224, 536, -176, -920, + 436, -48, 1176, -884, 416, -776, -824, -884, 524, -548, -564, + -68, -164, -96, 692, 364, -692, -1012, -68, 260, -480, 876, + -1116, 452, -332, -352, 892, -1088, 1220, -676, 12, -292, 244, + 496, 372, -32, 280, 200, 112, -440, -96, 24, -644, -184, + 56, -432, 224, -980, 272, -260, 144, -436, 420, 356, 364, + -528, 76, 172, -744, -368, 404, -752, -416, 684, -688, 72, + 540, 416, 92, 444, 480, -72, -1416, 164, -1172, -68, 24, + 424, 264, 1040, 128, -912, -524, -356, 64, 876, -12, 4, + -88, 532, 272, -524, 320, 276, -508, 940, 24, -400, -120, + 756, 60, 236, -412, 100, 376, -484, 400, -100, -740, -108, + -260, 328, -268, 224, -200, -416, 184, -604, -564, -20, 296, + 60, 892, -888, 60, 164, 68, -760, 216, -296, 904, -336, + -28, 404, -356, -568, -208, -1480, -512, 296, 328, -360, -164, + -1560, -776, 1156, -428, 164, -504, -112, 120, -216, -148, -264, + 308, 32, 64, -72, 72, 116, 176, -64, -272, 460, -536, + -784, -280, 348, 108, -752, -132, 524, -540, -776, 116, -296, + -1196, -288, -560, 1040, -472, 116, -848, -1116, 116, 636, 696, + 284, -176, 1016, 204, -864, -648, -248, 356, 972, -584, -204, + 264, 880, 528, -24, -184, 116, 448, -144, 828, 524, 212, + -212, 52, 12, 200, 268, -488, -404, -880, 824, -672, -40, + 908, -248, 500, 716, -576, 492, -576, 16, 720, -108, 384, + 124, 344, 280, 576, -500, 252, 104, -308, 196, -188, -8, + 1268, 296, 1032, -1196, 436, 316, 372, -432, -200, -660, 704, + -224, 596, -132, 268, 32, -452, 884, 104, -1008, 424, -1348, + -280, 4, -1168, 368, 476, 696, 300, -8, 24, 180, -592, + -196, 388, 304, 500, 724, -160, 244, -84, 272, -256, -420, + 320, 208, -144, -156, 156, 364, 452, 28, 540, 316, 220, + -644, -248, 464, 72, 360, 32, -388, 496, -680, -48, 208, + -116, -408, 60, -604, -392, 548, -840, 784, -460, 656, -544, + -388, -264, 908, -800, -628, -612, -568, 572, -220, 164, 288, + -16, -308, 308, -112, -636, -760, 280, -668, 432, 364, 240, + -196, 604, 340, 384, 196, 592, -44, -500, 432, -580, -132, + 636, -76, 392, 4, -412, 540, 508, 328, -356, -36, 16, + -220, -64, -248, -60, 24, -192, 368, 1040, 92, -24, -1044, + -32, 40, 104, 148, 192, -136, -520, 56, -816, -224, 732, + 392, 356, 212, -80, -424, -1008, -324, 588, -1496, 576, 460, + -816, -848, 56, -580, -92, -1372, -112, -496, 200, 364, 52, + -140, 48, -48, -60, 84, 72, 40, 132, -356, -268, -104, + -284, -404, 732, -520, 164, -304, -540, 120, 328, -76, -460, + 756, 388, 588, 236, -436, -72, -176, -404, -316, -148, 716, + -604, 404, -72, -88, -888, -68, 944, 88, -220, -344, 960, + 472, 460, -232, 704, 120, 832, -228, 692, -508, 132, -476, + 844, -748, -364, -44, 1116, -1104, -1056, 76, 428, 552, -692, + 60, 356, 96, -384, -188, -612, -576, 736, 508, 892, 352, + -1132, 504, -24, -352, 324, 332, -600, -312, 292, 508, -144, + -8, 484, 48, 284, -260, -240, 256, -100, -292, -204, -44, + 472, -204, 908, -188, -1000, -256, 92, 1164, -392, 564, 356, + 652, -28, -884, 256, 484, -192, 760, -176, 376, -524, -452, + -436, 860, -736, 212, 124, 504, -476, 468, 76, -472, 552, + -692, -944, -620, 740, -240, 400, 132, 20, 192, -196, 264, + -668, -1012, -60, 296, -316, -828, 76, -156, 284, -768, -448, + -832, 148, 248, 652, 616, 1236, 288, -328, -400, -124, 588, + 220, 520, -696, 1032, 768, -740, -92, -272, 296, 448, -464, + 412, -200, 392, 440, -200, 264, -152, -260, 320, 1032, 216, + 320, -8, -64, 156, -1016, 1084, 1172, 536, 484, -432, 132, + 372, -52, -256, 84, 116, -352, 48, 116, 304, -384, 412, + 924, -300, 528, 628, 180, 648, 44, -980, -220, 1320, 48, + 332, 748, 524, -268, -720, 540, -276, 564, -344, -208, -196, + 436, 896, 88, -392, 132, 80, -964, -288, 568, 56, -48, + -456, 888, 8, 552, -156, -292, 948, 288, 128, -716, -292, + 1192, -152, 876, 352, -600, -260, -812, -468, -28, -120, -32, + -44, 1284, 496, 192, 464, 312, -76, -516, -380, -456, -1012, + -48, 308, -156, 36, 492, -156, -808, 188, 1652, 68, -120, + -116, 316, 160, -140, 352, 808, -416, 592, 316, -480, 56, + 528, -204, -568, 372, -232, 752, -344, 744, -4, 324, -416, + -600, 768, 268, -248, -88, -132, -420, -432, 80, -288, 404, + -316, -1216, -588, 520, -108, 92, -320, 368, -480, -216, -92, + 1688, -300, 180, 1020, -176, 820, -68, -228, -260, 436, -904, + 20, 40, -508, 440, -736, 312, 332, 204, 760, -372, 728, + 96, -20, -632, -520, -560, 336, 1076, -64, -532, 776, 584, + 192, 396, -728, -520, 276, -188, 80, -52, -612, -252, -48, + 648, 212, -688, 228, -52, -260, 428, -412, -272, -404, 180, + 816, -796, 48, 152, 484, -88, -216, 988, 696, 188, -528, + 648, -116, -180, 316, 476, 12, -564, 96, 476, -252, -364, + -376, -392, 556, -256, -576, 260, -352, 120, -16, -136, -260, + -492, 72, 556, 660, 580, 616, 772, 436, 424, -32, -324, + -1268, 416, -324, -80, 920, 160, 228, 724, 32, -516, 64, + 384, 68, -128, 136, 240, 248, -204, -68, 252, -932, -120, + -480, -628, -84, 192, 852, -404, -288, -132, 204, 100, 168, + -68, -196, -868, 460, 1080, 380, -80, 244, 0, 484, -888, + 64, 184, 352, 600, 460, 164, 604, -196, 320, -64, 588, + -184, 228, 12, 372, 48, -848, -344, 224, 208, -200, 484, + 128, -20, 272, -468, -840, 384, 256, -720, -520, -464, -580, + 112, -120, 644, -356, -208, -608, -528, 704, 560, -424, 392, + 828, 40, 84, 200, -152, 0, -144, 584, 280, -120, 80, + -556, -972, -196, -472, 724, 80, 168, -32, 88, 160, -688, + 0, 160, 356, 372, -776, 740, -128, 676, -248, -480, 4, + -364, 96, 544, 232, -1032, 956, 236, 356, 20, -40, 300, + 24, -676, -596, 132, 1120, -104, 532, -1096, 568, 648, 444, + 508, 380, 188, -376, -604, 1488, 424, 24, 756, -220, -192, + 716, 120, 920, 688, 168, 44, -460, 568, 284, 1144, 1160, + 600, 424, 888, 656, -356, -320, 220, 316, -176, -724, -188, + -816, -628, -348, -228, -380, 1012, -452, -660, 736, 928, 404, + -696, -72, -268, -892, 128, 184, -344, -780, 360, 336, 400, + 344, 428, 548, -112, 136, -228, -216, -820, -516, 340, 92, + -136, 116, -300, 376, -244, 100, -316, -520, -284, -12, 824, + 164, -548, -180, -128, 116, -924, -828, 268, -368, -580, 620, + 192, 160, 0, -1676, 1068, 424, -56, -360, 468, -156, 720, + 288, -528, 556, -364, 548, -148, 504, 316, 152, -648, -620, + -684, -24, -376, -384, -108, -920, -1032, 768, 180, -264, -508, + -1268, -260, -60, 300, -240, 988, 724, -376, -576, -212, -736, + 556, 192, 1092, -620, -880, 376, -56, -4, -216, -32, 836, + 268, 396, 1332, 864, -600, 100, 56, -412, -92, 356, 180, + 884, -468, -436, 292, -388, -804, -704, -840, 368, -348, 140, + -724, 1536, 940, 372, 112, -372, 436, -480, 1136, 296, -32, + -228, 132, -48, -220, 868, -1016, -60, -1044, -464, 328, 916, + 244, 12, -736, -296, 360, 468, -376, -108, -92, 788, 368, + -56, 544, 400, -672, -420, 728, 16, 320, 44, -284, -380, + -796, 488, 132, 204, -596, -372, 88, -152, -908, -636, -572, + -624, -116, -692, -200, -56, 276, -88, 484, -324, 948, 864, + 1000, -456, -184, -276, 292, -296, 156, 676, 320, 160, 908, + -84, -1236, -288, -116, 260, -372, -644, 732, -756, -96, 84, + 344, -520, 348, -688, 240, -84, 216, -1044, -136, -676, -396, + -1500, 960, -40, 176, 168, 1516, 420, -504, -344, -364, -360, + 1216, -940, -380, -212, 252, -660, -708, 484, -444, -152, 928, + -120, 1112, 476, -260, 560, -148, -344, 108, -196, 228, -288, + 504, 560, -328, -88, 288, -1008, 460, -228, 468, -836, -196, + 76, 388, 232, 412, -1168, -716, -644, 756, -172, -356, -504, + 116, 432, 528, 48, 476, -168, -608, 448, 160, -532, -272, + 28, -676, -12, 828, 980, 456, 520, 104, -104, 256, -344, + -4, -28, -368, -52, -524, -572, -556, -200, 768, 1124, -208, + -512, 176, 232, 248, -148, -888, 604, -600, -304, 804, -156, + -212, 488, -192, -804, -256, 368, -360, -916, -328, 228, -240, + -448, -472, 856, -556, -364, 572, -12, -156, -368, -340, 432, + 252, -752, -152, 288, 268, -580, -848, -592, 108, -76, 244, + 312, -716, 592, -80, 436, 360, 4, -248, 160, 516, 584, + 732, 44, -468, -280, -292, -156, -588, 28, 308, 912, 24, + 124, 156, 180, -252, 944, -924, -772, -520, -428, -624, 300, + -212, -1144, 32, -724, 800, -1128, -212, -1288, -848, 180, -416, + 440, 192, -576, -792, -76, -1080, 80, -532, -352, -132, 380, + -820, 148, 1112, 128, 164, 456, 700, -924, 144, -668, -384, + 648, -832, 508, 552, -52, -100, -656, 208, -568, 748, -88, + 680, 232, 300, 192, -408, -1012, -152, -252, -268, 272, -876, + -664, -648, -332, -136, 16, 12, 1152, -28, 332, -536, 320, + -672, -460, -316, 532, -260, 228, -40, 1052, -816, 180, 88, + -496, -556, -672, -368, 428, 92, 356, 404, -408, 252, 196, + -176, -556, 792, 268, 32, 372, 40, 96, -332, 328, 120, + 372, -900, -40, 472, -264, -592, 952, 128, 656, 112, 664, + -232, 420, 4, -344, -464, 556, 244, -416, -32, 252, 0, + -412, 188, -696, 508, -476, 324, -1096, 656, -312, 560, 264, + -136, 304, 160, -64, -580, 248, 336, -720, 560, -348, -288, + -276, -196, -500, 852, -544, -236, -1128, -992, -776, 116, 56, + 52, 860, 884, 212, -12, 168, 1020, 512, -552, 924, -148, + 716, 188, 164, -340, -520, -184, 880, -152, -680, -208, -1156, + -300, -528, -472, 364, 100, -744, -1056, -32, 540, 280, 144, + -676, -32, -232, -280, -224, 96, 568, -76, 172, 148, 148, + 104, 32, -296, -32, 788, -80, 32, -16, 280, 288, 944, + 428, -484 +}; + +static inline RK_S32 Clamp(RK_S32 value, RK_S32 low, RK_S32 high) +{ + return value < low ? low : (value > high ? high : value); +} + +static inline RK_S32 RoundPowerOfTwo(const RK_S32 val, RK_S32 n) +{ + const RK_S32 a = (RK_S32)1 << (n - 1); + return (val + a) >> n; +} + +// Reset random_register +static void InitRandomGenerator(RK_U8 luma_num, RK_U16 seed, RK_U16 *random_register) +{ + RK_U16 random_reg = seed; + random_reg ^= ((luma_num * 37 + 178) & 255) << 8; + random_reg ^= ((luma_num * 173 + 105) & 255); + *random_register = random_reg; +} + +// Update random_register as LFSR +static inline void UpdateRandomRegister(RK_U16 *random_register) +{ + RK_U16 bit; + RK_U16 random_reg = *random_register; + bit = ((random_reg >> 0) ^ (random_reg >> 1) ^ (random_reg >> 3) ^ + (random_reg >> 12)) & + 1; + *random_register = (random_reg >> 1) | (bit << 15); +} + +static inline RK_S32 GetRandomNumber(RK_U16 random_register) +{ + return (random_register >> 5) & ((1 << 11) - 1); +} + +void GenerateLumaGrainBlock(RK_S32 luma_grain_block[][82], RK_S32 bitdepth, + RK_U8 num_y_points, RK_S32 grain_scale_shift, + RK_S32 ar_coeff_lag, RK_S32 ar_coeffs_y[], + RK_S32 ar_coeff_shift, RK_S32 grain_min, RK_S32 grain_max, + RK_U16 random_seed) +{ + RK_S32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift; + RK_U16 grain_random_register = random_seed; + RK_S32 i, j; + for (i = 0; i < 73; i++) { + for (j = 0; j < 82; j++) { + if (num_y_points > 0) { + UpdateRandomRegister(&grain_random_register); + luma_grain_block[i][j] = RoundPowerOfTwo( + gaussian_sequence[GetRandomNumber(grain_random_register)], + gauss_sec_shift); + } else { + luma_grain_block[i][j] = 0; + } + } + } + + for (i = 3; i < 73; i++) + for (j = 3; j < 82 - 3; j++) { + RK_S32 pos = 0; + RK_S32 wsum = 0; + RK_S32 deltaRow, deltaCol; + for (deltaRow = -ar_coeff_lag; deltaRow <= 0; deltaRow++) { + for (deltaCol = -ar_coeff_lag; deltaCol <= ar_coeff_lag; + deltaCol++) { + if (deltaRow == 0 && deltaCol == 0) break; + wsum = wsum + ar_coeffs_y[pos] * + luma_grain_block[i + deltaRow][j + deltaCol]; + ++pos; + } + } + luma_grain_block[i][j] = + Clamp(luma_grain_block[i][j] + RoundPowerOfTwo(wsum, ar_coeff_shift), + grain_min, grain_max); + } +} + +// Calculate chroma grain noise once per frame +void GenerateChromaGrainBlock( + RK_S32 luma_grain_block[][82], RK_S32 cb_grain_block[][44], + RK_S32 cr_grain_block[][44], RK_S32 bitdepth, RK_U8 num_y_points, RK_U8 num_cb_points, + RK_U8 num_cr_points, RK_S32 grain_scale_shift, RK_S32 ar_coeff_lag, + RK_S32 ar_coeffs_cb[], RK_S32 ar_coeffs_cr[], RK_S32 ar_coeff_shift, RK_S32 grain_min, + RK_S32 grain_max, RK_U8 chroma_scaling_from_luma, RK_U16 random_seed) +{ + RK_S32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift; + RK_U16 grain_random_register = 0; + RK_S32 i, j; + + InitRandomGenerator(7, random_seed, &grain_random_register); + for ( i = 0; i < 38; i++) { + for (j = 0; j < 44; j++) { + if (num_cb_points || chroma_scaling_from_luma) { + UpdateRandomRegister(&grain_random_register); + cb_grain_block[i][j] = RoundPowerOfTwo( + gaussian_sequence[GetRandomNumber(grain_random_register)], + gauss_sec_shift); + } else { + cb_grain_block[i][j] = 0; + } + } + } + + InitRandomGenerator(11, random_seed, &grain_random_register); + for (i = 0; i < 38; i++) { + for (j = 0; j < 44; j++) { + if (num_cr_points || chroma_scaling_from_luma) { + UpdateRandomRegister(&grain_random_register); + cr_grain_block[i][j] = RoundPowerOfTwo( + gaussian_sequence[GetRandomNumber(grain_random_register)], + gauss_sec_shift); + } else { + cr_grain_block[i][j] = 0; + } + } + } + + for (i = 3; i < 38; i++) + for (j = 3; j < 44 - 3; j++) { + RK_S32 wsum_cb = 0; + RK_S32 wsum_cr = 0; + RK_S32 pos = 0; + RK_S32 deltaRow, deltaCol; + + for ( deltaRow = -ar_coeff_lag; deltaRow <= 0; deltaRow++) { + for ( deltaCol = -ar_coeff_lag; deltaCol <= ar_coeff_lag; + deltaCol++) { + if (deltaRow == 0 && deltaCol == 0) break; + wsum_cb = wsum_cb + ar_coeffs_cb[pos] * + cb_grain_block[i + deltaRow][j + deltaCol]; + wsum_cr = wsum_cr + ar_coeffs_cr[pos] * + cr_grain_block[i + deltaRow][j + deltaCol]; + ++pos; + } + } + + if (num_y_points > 0) { + RK_S32 av_luma = 0; + RK_S32 luma_coord_y = (i << 1) - 3; + RK_S32 luma_coord_x = (j << 1) - 3; + + av_luma += luma_grain_block[luma_coord_y][luma_coord_x]; + av_luma += luma_grain_block[luma_coord_y][luma_coord_x + 1]; + av_luma += luma_grain_block[luma_coord_y + 1][luma_coord_x]; + av_luma += luma_grain_block[luma_coord_y + 1][luma_coord_x + 1]; + av_luma = RoundPowerOfTwo(av_luma, 2); + + wsum_cb = wsum_cb + ar_coeffs_cb[pos] * av_luma; + wsum_cr = wsum_cr + ar_coeffs_cr[pos] * av_luma; + } + + if (num_cb_points || chroma_scaling_from_luma) { + cb_grain_block[i][j] = Clamp( + cb_grain_block[i][j] + RoundPowerOfTwo(wsum_cb, ar_coeff_shift), + grain_min, grain_max); + } + if (num_cr_points || chroma_scaling_from_luma) { + cr_grain_block[i][j] = Clamp( + cr_grain_block[i][j] + RoundPowerOfTwo(wsum_cr, ar_coeff_shift), + grain_min, grain_max); + } + } +} diff --git a/mpp/hal/common/av1/film_grain_noise_table.h b/mpp/hal/common/av1/film_grain_noise_table.h new file mode 100644 index 000000000..bd8fe99f7 --- /dev/null +++ b/mpp/hal/common/av1/film_grain_noise_table.h @@ -0,0 +1,33 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FILM_GRAIN_NOISE_TABLE_H +#define FILM_GRAIN_NOISE_TABLE_H +#include "rk_type.h" + +void GenerateLumaGrainBlock(RK_S32 luma_grain_block[][82], RK_S32 bitdepth, + RK_U8 num_y_points, RK_S32 grain_scale_shift, + RK_S32 ar_coeff_lag, RK_S32 ar_coeffs_y[], + RK_S32 ar_coeff_shift, RK_S32 grain_min, RK_S32 grain_max, + RK_U16 random_seed); + +void GenerateChromaGrainBlock( + RK_S32 luma_grain_block[][82], RK_S32 cb_grain_block[][44], + RK_S32 cr_grain_block[][44], RK_S32 bitdepth, RK_U8 num_y_points, RK_U8 num_cb_points, + RK_U8 num_cr_points, RK_S32 grain_scale_shift, RK_S32 ar_coeff_lag, + RK_S32 ar_coeffs_cb[], RK_S32 ar_coeffs_cr[], RK_S32 ar_coeff_shift, RK_S32 grain_min, + RK_S32 grain_max, RK_U8 chroma_scaling_from_luma, RK_U16 random_seed); + +#endif // FILM_GRAIN_NOISE_TABLE_H \ No newline at end of file diff --git a/mpp/hal/common/av1/hal_av1d_common.h b/mpp/hal/common/av1/hal_av1d_common.h new file mode 100644 index 000000000..997271e8d --- /dev/null +++ b/mpp/hal/common/av1/hal_av1d_common.h @@ -0,0 +1,133 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef HAL_AV1D_GLOBAL_H +#define HAL_AV1D_GLOBAL_H + +#include "mpp_hal.h" +#include "mpp_debug.h" +#include "mpp_device.h" +#include "hal_bufs.h" + +#include "dxva_syntax.h" + +#define AV1D_DBG_ERROR (0x00000001) +#define AV1D_DBG_ASSERT (0x00000002) +#define AV1D_DBG_WARNNING (0x00000004) +#define AV1D_DBG_LOG (0x00000008) + +#define AV1D_DBG_HARD_MODE (0x00000010) +#define AV1D_DBG_REG (0x00000020) + +extern RK_U32 hal_av1d_debug; + +#define AV1D_DBG(level, fmt, ...)\ +do {\ + if (level & hal_av1d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + + +#define AV1D_ERR(fmt, ...)\ +do {\ + if (AV1D_DBG_ERROR & hal_av1d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define ASSERT(val)\ +do {\ + if (AV1D_DBG_ASSERT & hal_av1d_debug)\ + { mpp_assert(val); }\ +} while (0) + +#define AV1D_WARNNING(fmt, ...)\ +do {\ + if (AV1D_DBG_WARNNING & hal_av1d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define AV1D_LOG(fmt, ...)\ +do {\ + if (AV1D_DBG_LOG & hal_av1d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + + +//!< vaule check +#define VAL_CHECK(ret, val, ...)\ +do{\ + if (!(val)){\ + ret = MPP_ERR_VALUE; \ + AV1D_WARNNING("value error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do{\ + if (!(val)) {\ + ret = MPP_ERR_MALLOC; \ + AV1D_ERR("malloc buffer error(%d).\n", __LINE__); \ + ASSERT(0); goto __FAILED; \ +}} while (0) + +#define BUF_CHECK(ret, val, ...)\ +do{\ + if (val) {\ + ret = MPP_ERR_BUFFER_FULL; \ + AV1D_ERR("buffer get error(%d).\n", __LINE__); \ + ASSERT(0); goto __FAILED; \ +}} while (0) + +#define BUF_PUT(val, ...)\ +do{\ + if (val) {\ + if (mpp_buffer_put(val)) {\ + AV1D_ERR("buffer put error(%d).\n", __LINE__); \ + ASSERT(0); \ + }\ +}} while (0) + +//!< input check +#define INP_CHECK(ret, val, ...)\ +do{\ + if ((val)) {\ + ret = MPP_ERR_INIT; \ + AV1D_WARNNING("input empty(%d).\n", __LINE__); \ + goto __RETURN; \ +}} while (0) +//!< function return check +#define FUN_CHECK(val)\ +do{\ + if ((val) < 0) {\ + AV1D_WARNNING("Function error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + +#define AV1DEC_MAX_PIC_BUFFERS 24 + +typedef struct av1d_hal_ctx_t { + RK_U8 *bitstream; + RK_U32 strm_len; + + HalDecTask *in_task; + MppHalCfg *cfg; + + void *reg_ctx; + RK_U32 fast_mode; +} Av1dHalCtx; + +#endif /* HAL_AV1D_GLOBAL_H */ diff --git a/mpp/hal/common/h264/CMakeLists.txt b/mpp/hal/common/h264/CMakeLists.txt new file mode 100644 index 000000000..7b36b227b --- /dev/null +++ b/mpp/hal/common/h264/CMakeLists.txt @@ -0,0 +1,10 @@ +# vim: syntax=cmake +include_directories(.) +include_directories(../../rkenc/h264e/) +include_directories(../../vpu/h264e/) +include_directories(../../../codec/enc/h264/) + +# hal h264 encoder common +add_library(hal_h264e_com OBJECT + hal_h264e_stream_amend.c + ) diff --git a/mpp/hal/common/h264/hal_h264e_debug.h b/mpp/hal/common/h264/hal_h264e_debug.h new file mode 100644 index 000000000..763a12ecc --- /dev/null +++ b/mpp/hal/common/h264/hal_h264e_debug.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_DEBUG_H +#define HAL_H264E_DEBUG_H + +#include "mpp_debug.h" + +#define HAL_H264E_DBG_SIMPLE (0x00000001) +#define HAL_H264E_DBG_FUNCTION (0x00000002) +#define HAL_H264E_DBG_FLOW (0x00000004) +#define HAL_H264E_DBG_DETAIL (0x00000008) + +#define HAL_H264E_DBG_BUFFER (0x00000010) +#define HAL_H264E_DBG_REGS (0x00000020) +#define HAL_H264E_DBG_AMEND (0x00000040) + +#define HAL_H264E_DBG_RC (0x00000100) +#define HAL_H264E_DBG_SMART_V3 (0x00000200) + +#define hal_h264e_dbg(flag, fmt, ...) mpp_dbg(hal_h264e_debug, flag, fmt, ## __VA_ARGS__) +#define hal_h264e_dbg_f(flag, fmt, ...) mpp_dbg_f(hal_h264e_debug, flag, fmt, ## __VA_ARGS__) + +#define hal_h264e_dbg_func(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define hal_h264e_dbg_flow(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_FLOW, fmt, ## __VA_ARGS__) +#define hal_h264e_dbg_detail(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_DETAIL, fmt, ## __VA_ARGS__) + +#define hal_h264e_dbg_buffer(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_BUFFER, fmt, ## __VA_ARGS__) +#define hal_h264e_dbg_regs(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_REGS, fmt, ## __VA_ARGS__) +#define hal_h264e_dbg_amend(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_AMEND, fmt, ## __VA_ARGS__) + +#define hal_h264e_dbg_rc(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_RC, fmt, ## __VA_ARGS__) +#define hal_h264e_dbg_smartv3(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_SMART_V3, fmt, ## __VA_ARGS__) + +#define hal_h264e_enter() hal_h264e_dbg_func("enter\n"); +#define hal_h264e_leave() hal_h264e_dbg_func("leave\n"); + +extern RK_U32 hal_h264e_debug; + +#endif /* HAL_H264E_DEBUG_H */ diff --git a/mpp/hal/common/h264/hal_h264e_stream_amend.c b/mpp/hal/common/h264/hal_h264e_stream_amend.c new file mode 100644 index 000000000..88dd864a3 --- /dev/null +++ b/mpp/hal/common/h264/hal_h264e_stream_amend.c @@ -0,0 +1,401 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264e_amend" + +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_dmabuf.h" +#include "mpp_packet_impl.h" + +#include "mpp_enc_cfg.h" +#include "mpp_enc_refs.h" + +#include "hal_h264e_debug.h" +#include "hal_h264e_stream_amend.h" + +#include "h264e_sps.h" +#include "h264e_pps.h" +#include "h264e_slice.h" + +#define START_CODE 0x000001 ///< start_code_prefix_one_3bytes + +static RK_S32 get_next_nal(RK_U8 *buf, RK_S32 *length) +{ + RK_S32 i, consumed = 0; + RK_S32 len = *length; + RK_U8 *tmp_buf = buf; + + /* search start code */ + while (len >= 4) { + if (tmp_buf[2] == 0) { + len--; + tmp_buf++; + continue; + } + + if (tmp_buf[0] != 0 || tmp_buf[1] != 0 || tmp_buf[2] != 1) { + RK_U32 state = (RK_U32) - 1; + RK_S32 has_nal = 0; + + for (i = 0; i < (RK_S32)len; i++) { + state = (state << 8) | tmp_buf[i]; + if (((state >> 8) & 0xFFFFFF) == START_CODE) { + has_nal = 1; + i = i - 3; + break; + } + } + + if (has_nal) { + len -= i; + tmp_buf += i; + consumed = *length - len - 1; + break; + } + + consumed = *length; + break; + } + tmp_buf += 3; + len -= 3; + } + + *length = *length - consumed; + return consumed; +} + +MPP_RET h264e_vepu_stream_amend_init(HalH264eVepuStreamAmend *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->buf_size = SZ_128K; + return MPP_OK; +} + +MPP_RET h264e_vepu_stream_amend_deinit(HalH264eVepuStreamAmend *ctx) +{ + MPP_FREE(ctx->src_buf); + MPP_FREE(ctx->dst_buf); + return MPP_OK; +} + +MPP_RET h264e_vepu_stream_amend_config(HalH264eVepuStreamAmend *ctx, + MppPacket packet, MppEncCfgSet *cfg, + H264eSlice *slice, H264ePrefixNal *prefix) +{ + MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg->ref_cfg; + MppEncH264Cfg *h264 = &cfg->h264; + MppEncH264HwCfg *hw_cfg = &h264->hw_cfg; + + if (ref->lt_cfg_cnt || ref->st_cfg_cnt > 1 || + hw_cfg->hw_poc_type != h264->poc_type || + hw_cfg->hw_log2_max_frame_num_minus4 != h264->log2_max_frame_num) { + ctx->enable = 1; + ctx->slice_enabled = 0; + + if (NULL == ctx->dst_buf) + ctx->dst_buf = mpp_calloc(RK_U8, ctx->buf_size); + if (NULL == ctx->src_buf) + ctx->src_buf = mpp_calloc(RK_U8, ctx->buf_size); + } else { + MPP_FREE(ctx->dst_buf); + MPP_FREE(ctx->src_buf); + h264e_vepu_stream_amend_init(ctx); + } + + slice->pic_order_cnt_type = cfg->h264.poc_type; + + ctx->slice = slice; + if (ref->lt_cfg_cnt || ref->st_cfg_cnt > 1) + ctx->prefix = prefix; + + ctx->packet = packet; + ctx->buf_base = mpp_packet_get_length(packet); + ctx->old_length = 0; + ctx->new_length = 0; + + return MPP_OK; +} + +MPP_RET h264e_vepu_stream_amend_proc(HalH264eVepuStreamAmend *ctx, MppEncH264HwCfg *hw_cfg) +{ + H264ePrefixNal *prefix = ctx->prefix; + H264eSlice *slice = ctx->slice; + MppPacket pkt = ctx->packet; + RK_U8 *p = mpp_packet_get_pos(pkt); + RK_S32 base = ctx->buf_base; + RK_S32 len = ctx->old_length; + RK_S32 hw_len_bit = 0; + RK_S32 sw_len_bit = 0; + RK_S32 hw_len_byte = 0; + RK_S32 sw_len_byte = 0; + RK_S32 diff_size = 0; + RK_S32 tail_0bit = 0; + RK_U8 tail_byte = 0; + RK_U8 tail_tmp = 0; + RK_U8 *dst_buf = NULL; + RK_S32 buf_size; + RK_S32 final_len = 0; + RK_S32 last_slice = 0; + const MppPktSeg *seg = mpp_packet_get_segment_info(pkt); + MppPacket pkt_tmp; + RK_S32 offset = 0; + RK_U32 is_cabac = ctx->slice->entropy_coding_mode; + + mpp_packet_new(&pkt_tmp); + + if (seg) { + while (seg && seg->type != 1 && seg->type != 5) { + mpp_packet_add_segment_info(pkt_tmp, seg->type, offset, seg->len); + offset += seg->len; + + seg = seg->next; + } + } + + { + MppBuffer buf = mpp_packet_get_buffer(pkt); + RK_S32 fd = mpp_buffer_get_fd(buf); + + mpp_dmabuf_sync_partial_begin(fd, 1, base, len, __FUNCTION__); + } + + { + RK_S32 more_buf = 0; + while (len > ctx->buf_size - 16) { + ctx->buf_size *= 2; + more_buf = 1; + } + + if (more_buf) { + MPP_FREE(ctx->src_buf); + MPP_FREE(ctx->dst_buf); + ctx->src_buf = mpp_malloc(RK_U8, ctx->buf_size); + ctx->dst_buf = mpp_malloc(RK_U8, ctx->buf_size); + } + } + + memset(ctx->dst_buf, 0, ctx->buf_size); + memset(ctx->src_buf, 0, ctx->buf_size); + dst_buf = ctx->dst_buf; + buf_size = ctx->buf_size; + p += base; + + do { + RK_U32 nal_len = 0; + + tail_0bit = 0; + // copy hw stream to stream buffer first + if (slice->is_multi_slice) { + if ((!seg) || !hw_cfg->hw_split_out || !is_cabac) { + nal_len = get_next_nal(p, &len); + last_slice = (len == 0); + } else { + nal_len = seg->len; + len -= seg->len; + seg = seg->next; + if (!seg || !len) + last_slice = 1; + } + memcpy(ctx->src_buf, p, nal_len); + p += nal_len; + } else { + memcpy(ctx->src_buf, p, len); + nal_len = len; + last_slice = 1; + } + + hal_h264e_dbg_amend("nal_len %d multi %d last %d prefix %p\n", + nal_len, slice->is_multi_slice, last_slice, prefix); + + if (prefix) { + /* add prefix for each slice */ + RK_S32 prefix_bit = h264e_slice_write_prefix_nal_unit_svc(prefix, dst_buf, buf_size); + + prefix_bit = (prefix_bit + 7) / 8; + + dst_buf += prefix_bit; + buf_size -= prefix_bit; + final_len += prefix_bit; + + mpp_packet_add_segment_info(pkt_tmp, H264_NALU_TYPE_PREFIX, offset, prefix_bit); + offset += prefix_bit; + } + + H264eSlice slice_rd; + + memcpy(&slice_rd, slice, sizeof(slice_rd)); + + /* update slice by hw_cfg */ + slice_rd.pic_order_cnt_type = hw_cfg->hw_poc_type; + slice_rd.log2_max_frame_num = hw_cfg->hw_log2_max_frame_num_minus4 + 4; + + if (ctx->reorder) { + slice_rd.reorder = ctx->reorder; + h264e_reorder_init(slice_rd.reorder); + } + if (ctx->marking) { + slice_rd.marking = ctx->marking; + h264e_marking_init(slice_rd.marking); + } + + hw_len_bit = h264e_slice_read(&slice_rd, ctx->src_buf, nal_len); + + // write new header to header buffer + slice->qp_delta = slice_rd.qp_delta; + slice->first_mb_in_slice = slice_rd.first_mb_in_slice; + + if (ctx->reorder) + slice->reorder = slice_rd.reorder; + if (ctx->marking) + slice->marking = slice_rd.marking; + + sw_len_bit = h264e_slice_write(slice, dst_buf, buf_size); + + hw_len_byte = (hw_len_bit + 7) / 8; + sw_len_byte = (sw_len_bit + 7) / 8; + + tail_byte = ctx->src_buf[nal_len - 1]; + tail_tmp = tail_byte; + + while (!(tail_tmp & 1) && tail_0bit < 8) { + tail_tmp >>= 1; + tail_0bit++; + } + + mpp_assert(tail_0bit < 8); + + // move the reset slice data from src buffer to dst buffer + diff_size = h264e_slice_move(dst_buf, ctx->src_buf, + sw_len_bit, hw_len_bit, nal_len); + + hal_h264e_dbg_amend("tail 0x%02x %d hw_hdr %d sw_hdr %d len %d hw_byte %d sw_byte %d diff %d\n", + tail_byte, tail_0bit, hw_len_bit, sw_len_bit, nal_len, hw_len_byte, sw_len_byte, diff_size); + + if (slice->entropy_coding_mode) { + memcpy(dst_buf + sw_len_byte, ctx->src_buf + hw_len_byte, + nal_len - hw_len_byte); + final_len += nal_len - hw_len_byte + sw_len_byte; + nal_len = nal_len - hw_len_byte + sw_len_byte; + } else { + RK_S32 hdr_diff_bit = sw_len_bit - hw_len_bit; + RK_S32 bit_len = nal_len * 8 - tail_0bit + hdr_diff_bit; + RK_S32 new_len = (bit_len + diff_size * 8 + 7) / 8; + + hal_h264e_dbg_amend("frm %4d %c len %d bit hw %d sw %d byte hw %d sw %d diff %d -> %d\n", + slice->frame_num, (slice->idr_flag ? 'I' : 'P'), + nal_len, hw_len_bit, sw_len_bit, + hw_len_byte, sw_len_byte, diff_size, new_len); + + hal_h264e_dbg_amend("%02x %02x %02x %02x -> %02x %02x %02x %02x\n", + ctx->src_buf[nal_len - 4], ctx->src_buf[nal_len - 3], + ctx->src_buf[nal_len - 2], ctx->src_buf[nal_len - 1], + dst_buf[new_len - 4], dst_buf[new_len - 3], + dst_buf[new_len - 2], dst_buf[new_len - 1]); + nal_len = new_len; + final_len += new_len; + } + + { + H264NaluType type = slice->idr_flag ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + + mpp_packet_add_segment_info(pkt_tmp, type, offset, nal_len); + offset += nal_len; + } + + if (last_slice) { + p = mpp_packet_get_pos(pkt); + p += base; + memcpy(p, ctx->dst_buf, final_len); + + if (slice->entropy_coding_mode) { + if (final_len < ctx->old_length) + memset(p + final_len, 0, ctx->old_length - final_len); + } else + p[final_len] = 0; + + break; + } + + dst_buf += nal_len; + buf_size -= nal_len; + } while (1); + + ctx->new_length = final_len; + + /* update segment */ + mpp_packet_copy_segment_info(pkt, pkt_tmp); + + mpp_packet_deinit(&pkt_tmp); + + return MPP_OK; +} + +MPP_RET h264e_vepu_stream_amend_sync_ref_idc(HalH264eVepuStreamAmend *ctx) +{ + H264eSlice *slice = ctx->slice; + MppPacket pkt = ctx->packet; + RK_S32 base = ctx->buf_base; + RK_S32 len = ctx->old_length; + RK_U8 *p = mpp_packet_get_pos(pkt) + base; + RK_U8 val = 0; + RK_S32 hw_nal_ref_idc = 0; + RK_S32 sw_nal_ref_idc = 0; + + { + MppBuffer buf = mpp_packet_get_buffer(pkt); + RK_S32 fd = mpp_buffer_get_fd(buf); + + mpp_dmabuf_sync_partial_begin(fd, 1, base, len, __FUNCTION__); + } + + val = p[4]; + hw_nal_ref_idc = (val >> 5) & 0x3; + sw_nal_ref_idc = slice->nal_reference_idc; + + if (hw_nal_ref_idc == sw_nal_ref_idc) + return MPP_OK; + + /* fix nal_ref_idc in all slice */ + if (!slice->is_multi_slice) { + /* single slice do NOT scan */ + val = val & (~0x60); + val |= (sw_nal_ref_idc << 5) & 0x60; + p[4] = val; + return MPP_OK; + } + + /* multi-slice fix each nal_ref_idc */ + do { + RK_U32 nal_len = get_next_nal(p, &len); + + val = p[4]; + val = val & (~0x60); + val |= (sw_nal_ref_idc << 5) & 0x60; + p[4] = val; + + if (len == 0) + break; + + p += nal_len; + } while (1); + + return MPP_OK; +} diff --git a/mpp/hal/common/h264/hal_h264e_stream_amend.h b/mpp/hal/common/h264/hal_h264e_stream_amend.h new file mode 100644 index 000000000..9c3f2cdbb --- /dev/null +++ b/mpp/hal/common/h264/hal_h264e_stream_amend.h @@ -0,0 +1,53 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_STREAM_AMEND_H +#define HAL_H264E_STREAM_AMEND_H + +#include "h264e_slice.h" + +typedef struct HalH264eVepuStreamAmend_t { + RK_S32 enable; + H264eSlice *slice; + H264ePrefixNal *prefix; + + /* async encode TSVC info */ + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + + RK_S32 slice_enabled; + + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + + MppPacket packet; + /* sw length */ + RK_S32 buf_base; + /* hw length */ + RK_S32 old_length; + RK_S32 new_length; +} HalH264eVepuStreamAmend; + +MPP_RET h264e_vepu_stream_amend_init(HalH264eVepuStreamAmend *ctx); +MPP_RET h264e_vepu_stream_amend_deinit(HalH264eVepuStreamAmend *ctx); +MPP_RET h264e_vepu_stream_amend_config(HalH264eVepuStreamAmend *ctx, + MppPacket packet, MppEncCfgSet *cfg, + H264eSlice *slice, H264ePrefixNal *prefix); +MPP_RET h264e_vepu_stream_amend_proc(HalH264eVepuStreamAmend *ctx, MppEncH264HwCfg *hw_cfg); +MPP_RET h264e_vepu_stream_amend_sync_ref_idc(HalH264eVepuStreamAmend *ctx); + +#endif /* HAL_H264E_STREAM_AMEND_H */ diff --git a/mpp/hal/common/h265/CMakeLists.txt b/mpp/hal/common/h265/CMakeLists.txt new file mode 100644 index 000000000..a218d2f17 --- /dev/null +++ b/mpp/hal/common/h265/CMakeLists.txt @@ -0,0 +1,9 @@ +# vim: syntax=cmake +include_directories(.) +include_directories(../../rkenc/h265e/) +include_directories(../../../codec/enc/h265/) + +# hal h265 encoder common +add_library(hal_h265e_com OBJECT + hal_h265e_stream_amend.c + ) diff --git a/mpp/hal/common/h265/hal_h265e_debug.h b/mpp/hal/common/h265/hal_h265e_debug.h new file mode 100644 index 000000000..24eaef351 --- /dev/null +++ b/mpp/hal/common/h265/hal_h265e_debug.h @@ -0,0 +1,64 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_DEBUG_H +#define HAL_H265E_DEBUG_H + +#include "mpp_debug.h" + +#define HAL_H265E_DBG_FUNCTION (0x00000001) +#define HAL_H265E_DBG_SIMPLE (0x00000002) +#define HAL_H265E_DBG_FLOW (0x00000004) +#define HAL_H265E_DBG_DETAIL (0x00000008) + +#define HAL_H265E_DBG_REGS (0x00000010) +#define HAL_H265E_DBG_CTL_REGS (0x00000020) +#define HAL_H265E_DBG_RCKUT_REGS (0x00000040) +#define HAL_H265E_DBG_WGT_REGS (0x00000080) +#define HAL_H265E_DBG_RDO_REGS (0x000000C0) +#define HAL_H265E_DBG_ST_REGS (0x00000100) /* status registers */ +#define HAL_H265E_DBG_SMART_V3 (0x00000200) + +#define HAL_H265E_DBG_INPUT (0x00020000) +#define HAL_H265E_DBG_OUTPUT (0x00040000) +#define HAL_H265E_DBG_WRITE_IN_STREAM (0x00080000) +#define HAL_H265E_DBG_WRITE_OUT_STREAM (0x00100000) + +#define hal_h265e_dbg(flag, fmt, ...) mpp_dbg(hal_h265e_debug, flag, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_f(flag, fmt, ...) mpp_dbg_f(hal_h265e_debug, flag, fmt, ## __VA_ARGS__) + +#define hal_h265e_dbg_func(fmt, ...) hal_h265e_dbg_f(HAL_H265E_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_simple(fmt, ...) hal_h265e_dbg_f(HAL_H265E_DBG_SIMPLE, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_flow(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_FLOW, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_detail(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_DETAIL, fmt, ## __VA_ARGS__) + +#define hal_h265e_dbg_regs(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_REGS, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_ctl(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_CTL_REGS, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_rckut(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_RCKUT_REGS, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_wgt(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_WGT_REGS, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_rdo(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_RDO_REGS, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_st(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_ST_REGS, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_smartv3(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_SMART_V3, fmt, ## __VA_ARGS__) + +#define hal_h265e_dbg_input(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_INPUT, fmt, ## __VA_ARGS__) +#define hal_h265e_dbg_output(fmt, ...) hal_h265e_dbg(HAL_H265E_DBG_OUTPUT, fmt, ## __VA_ARGS__) + +#define hal_h265e_enter() hal_h265e_dbg_flow("(%d) enter\n", __LINE__); +#define hal_h265e_leave() hal_h265e_dbg_flow("(%d) leave\n", __LINE__); + +extern RK_U32 hal_h265e_debug; + +#endif diff --git a/mpp/hal/common/h265/hal_h265e_stream_amend.c b/mpp/hal/common/h265/hal_h265e_stream_amend.c new file mode 100644 index 000000000..2ae0235ee --- /dev/null +++ b/mpp/hal/common/h265/hal_h265e_stream_amend.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#include "hal_h265e_stream_amend.h" + +#include "mpp_common.h" +#include "mpp_log.h" + +MPP_RET hal_h265e_amend_temporal_id(HalEncTask *enc_task, RK_U32 strm_size) +{ + MPP_RET ret = MPP_OK; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + RK_U8 *stream_ptr = (RK_U8 *)(mpp_buffer_get_ptr(enc_task->output) + offset); + + if (strm_size < 5) { + mpp_err("Stream size is too small, maybe there is hw encoder error!"); + return MPP_NOK; + } + + if (syn->sp.temporal_id) + stream_ptr[5] = (stream_ptr[5] & 0xf8) | ((syn->sp.temporal_id + 1) & 0x7); + + return ret; +} \ No newline at end of file diff --git a/mpp/hal/common/h265/hal_h265e_stream_amend.h b/mpp/hal/common/h265/hal_h265e_stream_amend.h new file mode 100644 index 000000000..e0191f66f --- /dev/null +++ b/mpp/hal/common/h265/hal_h265e_stream_amend.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265E_STREAM_AMEND_H +#define HAL_H265E_STREAM_AMEND_H + +#include "hal_enc_task.h" +#include "h265e_syntax_new.h" + +MPP_RET hal_h265e_amend_temporal_id(HalEncTask *enc_task, RK_U32 strm_size); + +#endif /* HAL_H265E_STREAM_AMEND_H */ \ No newline at end of file diff --git a/mpp/hal/common/hal_bufs.c b/mpp/hal/common/hal_bufs.c new file mode 100644 index 000000000..c417760d0 --- /dev/null +++ b/mpp/hal/common/hal_bufs.c @@ -0,0 +1,270 @@ +/* + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "hal_bufs" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "hal_bufs.h" + +#define HAL_BUFS_DBG_FUNCTION (0x00000001) + +#define hal_bufs_dbg(flag, fmt, ...) mpp_dbg(hal_bufs_debug, flag, fmt, ## __VA_ARGS__) +#define hal_bufs_dbg_f(flag, fmt, ...) mpp_dbg_f(hal_bufs_debug, flag, fmt, ## __VA_ARGS__) + +#define hal_bufs_dbg_func(fmt, ...) hal_bufs_dbg_f(HAL_BUFS_DBG_FUNCTION, fmt, ## __VA_ARGS__) + +#define hal_bufs_enter() hal_bufs_dbg_func("enter\n"); +#define hal_bufs_leave() hal_bufs_dbg_func("leave\n"); + +#define MAX_HAL_BUFS_CNT 40 +#define MAX_HAL_BUFS_SIZE_CNT 8 + +typedef struct HalBufsImpl_t { + MppBufferGroup group; + + RK_S32 max_cnt; + RK_S32 size_cnt; + RK_S32 size_sum; + RK_S32 slot_sum; + RK_S32 elem_size; + + RK_U32 valid; + size_t sizes[MAX_HAL_BUFS_SIZE_CNT]; + RK_U8 *bufs; +} HalBufsImpl; + +static RK_U32 hal_bufs_debug = 0; + +static HalBuf *hal_bufs_pos(HalBufsImpl *impl, RK_S32 idx) +{ + RK_S32 elem_size = impl->elem_size; + + return (HalBuf *)(impl->bufs + idx * elem_size); +} + +static MPP_RET hal_bufs_clear(HalBufsImpl *impl) +{ + MPP_RET ret = MPP_OK; + + if (impl->valid && impl->size_sum) { + RK_S32 i; + + for (i = 0; i < impl->max_cnt; i++) { + RK_U32 mask = 1 << i; + + if (impl->valid & mask) { + HalBuf *buf = hal_bufs_pos(impl, i); + RK_S32 j = 0; + + for (j = 0; j < impl->size_cnt; j++) { + if (buf->buf[j]) { + impl->size_sum -= impl->sizes[j]; + ret |= mpp_buffer_put(buf->buf[j]); + buf->buf[j] = NULL; + } + } + impl->valid &= ~mask; + } + } + + mpp_assert(impl->valid == 0); + mpp_assert(impl->size_sum == 0); + } + + impl->max_cnt = 0; + impl->size_cnt = 0; + impl->size_sum = 0; + impl->slot_sum = 0; + impl->valid = 0; + memset(impl->sizes, 0, sizeof(impl->sizes)); + MPP_FREE(impl->bufs); + + return ret; +} + +MPP_RET hal_bufs_init(HalBufs *bufs) +{ + MPP_RET ret = MPP_OK; + + if (NULL == bufs) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_env_get_u32("hal_bufs_debug", &hal_bufs_debug, 0); + + hal_bufs_enter(); + + HalBufsImpl *impl = mpp_calloc(HalBufsImpl, 1); + if (impl) { + ret = mpp_buffer_group_get_internal(&impl->group, MPP_BUFFER_TYPE_ION); + } else { + mpp_err_f("failed to malloc HalBufs\n"); + ret = MPP_ERR_MALLOC; + } + + *bufs = impl; + + hal_bufs_leave(); + + return ret; +} + +MPP_RET hal_bufs_deinit(HalBufs bufs) +{ + HalBufsImpl *impl = (HalBufsImpl *)bufs; + MPP_RET ret = MPP_OK; + + if (NULL == bufs) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + hal_bufs_enter(); + + ret = hal_bufs_clear(impl); + + if (impl->group) { + ret |= mpp_buffer_group_put(impl->group); + impl->group = NULL; + } + + memset(impl, 0, sizeof(*impl)); + MPP_FREE(impl); + + hal_bufs_leave(); + + return ret; +} + +MPP_RET hal_bufs_setup(HalBufs bufs, RK_S32 max_cnt, RK_S32 size_cnt, size_t sizes[]) +{ + HalBufsImpl *impl = (HalBufsImpl *)bufs; + MPP_RET ret = MPP_OK; + RK_S32 elem_size = 0; + RK_S32 impl_size = 0; + + if (NULL == bufs || NULL == sizes) { + mpp_err_f("invalid NULL input bufs %p sizes %p\n", bufs, sizes); + return MPP_ERR_NULL_PTR; + } + + if (max_cnt <= 0 || max_cnt > MAX_HAL_BUFS_CNT || + size_cnt <= 0 || size_cnt > MAX_HAL_BUFS_SIZE_CNT) { + mpp_err_f("invalid max cnt %d size cnt %d\n", max_cnt, size_cnt); + return MPP_ERR_VALUE; + } + + hal_bufs_enter(); + + hal_bufs_clear(impl); + + if (impl->group) + ret = mpp_buffer_group_clear(impl->group); + else + ret = mpp_buffer_group_get_internal(&impl->group, MPP_BUFFER_TYPE_ION); + + mpp_assert(impl->group); + + elem_size = sizeof(HalBuf) + sizeof(MppBuffer) * size_cnt; + impl_size = elem_size * max_cnt; + + impl->elem_size = elem_size; + impl->bufs = mpp_calloc_size(void, impl_size); + if (impl->bufs) { + RK_S32 slot_sum = 0; + RK_S32 i; + + for (i = 0; i < size_cnt; i++) { + slot_sum += sizes[i]; + impl->sizes[i] = sizes[i]; + } + + impl->slot_sum = slot_sum; + + for (i = 0; i < max_cnt; i++) { + HalBuf *buf = hal_bufs_pos(impl, i); + + buf->cnt = size_cnt; + buf->buf = (MppBuffer)(buf + 1); + } + + impl->max_cnt = max_cnt; + impl->size_cnt = size_cnt; + } else { + mpp_err_f("failed to malloc size %d for impl\n", impl_size); + ret = MPP_ERR_MALLOC; + } + + hal_bufs_leave(); + + return ret; +} + +HalBuf *hal_bufs_get_buf(HalBufs bufs, RK_S32 buf_idx) +{ + HalBufsImpl *impl = (HalBufsImpl *)bufs; + RK_S32 i; + + if (NULL == impl || buf_idx < 0 || buf_idx >= impl->max_cnt) { + mpp_err_f("invalid input impl %p buf_idx %d max_cnt %d\n", impl, buf_idx, impl->max_cnt); + return NULL; + } + + hal_bufs_enter(); + + HalBuf *hal_buf = hal_bufs_pos(impl, buf_idx); + RK_U32 mask = 1 << buf_idx; + + if (!(impl->valid & mask)) { + MppBufferGroup group = impl->group; + + for (i = 0; i < impl->size_cnt; i++) { + size_t size = impl->sizes[i]; + MppBuffer buf = hal_buf->buf[i]; + + if (size && NULL == buf) { + mpp_buffer_get(group, &buf, size); + if (!buf) + goto failed; + impl->size_sum += size; + } + + mpp_assert(buf); + hal_buf->buf[i] = buf; + } + + impl->valid |= mask; + } + + hal_bufs_leave(); + + return hal_buf; + +failed: + for (i = 0; i < impl->size_cnt; i++) { + if (hal_buf->buf[i]) { + mpp_buffer_put(hal_buf->buf[i]); + hal_buf->buf[i] = NULL; + } + } + return NULL; +} diff --git a/osal/os_allocator.h b/mpp/hal/common/hal_bufs.h similarity index 55% rename from osal/os_allocator.h rename to mpp/hal/common/hal_bufs.h index 0f3436b45..9d6374cf0 100644 --- a/osal/os_allocator.h +++ b/mpp/hal/common/hal_bufs.h @@ -1,41 +1,44 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OS_ALLOCATOR_H__ -#define __OS_ALLOCATOR_H__ - -#include "mpp_allocator.h" - -typedef struct os_allocator_t { - MPP_RET (*open)(void **ctx, size_t alignment); - MPP_RET (*alloc)(void *ctx, MppBufferInfo *info); - MPP_RET (*free)(void *ctx, MppBufferInfo *info); - MPP_RET (*close)(void *ctx); -} os_allocator; - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET os_allocator_get(os_allocator *api, MppBufferType type); - -#ifdef __cplusplus -} -#endif - -#endif /*__OS_ALLOCATOR_H__*/ - - +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_BUFS_H +#define HAL_BUFS_H + +#include "mpp_buffer.h" + +/* HalBuf buffer set allocater */ +typedef struct HalBuf_t { + RK_U32 cnt; + MppBuffer *buf; +} HalBuf; + +typedef void* HalBufs; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET hal_bufs_init(HalBufs *bufs); +MPP_RET hal_bufs_deinit(HalBufs bufs); + +MPP_RET hal_bufs_setup(HalBufs bufs, RK_S32 max_cnt, RK_S32 size_cnt, size_t sizes[]); +HalBuf *hal_bufs_get_buf(HalBufs bufs, RK_S32 buf_idx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/hal/common/hal_info.c b/mpp/hal/common/hal_info.c new file mode 100644 index 000000000..4ec836917 --- /dev/null +++ b/mpp/hal/common/hal_info.c @@ -0,0 +1,290 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "mpp_mem.h" +#include "mpp_2str.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "hal_info.h" + +typedef struct HalInfoImpl_t { + MppCtxType type; + MppCodingType coding; + + RK_U32 updated; + RK_U32 elem_nb; + /* info data for output */ + MppDevInfoCfg *elems; +} HalInfoImpl; + +MPP_RET hal_info_init(HalInfo *ctx, MppCtxType type, MppCodingType coding) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input ctx\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_NOK; + RK_U32 elem_nb = (type == MPP_CTX_DEC) ? (ENC_INFO_BUTT) : (DEC_INFO_BUTT); + HalInfoImpl *impl = mpp_calloc_size(HalInfoImpl, sizeof(HalInfoImpl) + + sizeof(MppDevInfoCfg) * elem_nb); + if (impl) { + impl->type = type; + impl->coding = coding; + impl->elem_nb = elem_nb; + impl->elems = (MppDevInfoCfg *)(impl + 1); + ret = MPP_OK; + } + + *ctx = impl; + + return ret; +} + +MPP_RET hal_info_deinit(HalInfo ctx) +{ + MPP_FREE(ctx); + return MPP_OK; +} + +MPP_RET hal_info_set(HalInfo ctx, RK_U32 type, RK_U32 flag, RK_U64 data) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input ctx\n"); + return MPP_ERR_NULL_PTR; + } + + if (flag <= CODEC_INFO_FLAG_NULL || flag >= CODEC_INFO_FLAG_BUTT) { + mpp_err_f("found invalid flag %d\n", flag); + return MPP_ERR_VALUE; + } + + HalInfoImpl *info = (HalInfoImpl *)ctx; + MppDevInfoCfg *elems = NULL; + + switch (info->type) { + case MPP_CTX_DEC : { + if (type <= DEC_INFO_BASE || type >= DEC_INFO_BUTT) { + mpp_err_f("found invalid dec info type %d [%d:%d]\n", + type, DEC_INFO_BASE, DEC_INFO_BUTT); + return MPP_ERR_VALUE; + } + + /* shift enum base */ + type -= DEC_INFO_BASE; + } break; + case MPP_CTX_ENC : { + if (type <= ENC_INFO_BASE || type >= ENC_INFO_BUTT) { + mpp_err_f("found invalid enc info type %d [%d:%d]\n", + type, ENC_INFO_BASE, ENC_INFO_BUTT); + return MPP_ERR_VALUE; + } + + /* shift enum base */ + type -= ENC_INFO_BASE; + } break; + default : { + mpp_err_f("found invalid ctx type %d\n", info->type); + return MPP_ERR_VALUE; + } break; + } + + elems = &info->elems[type]; + + if (elems->type != type || elems->flag != flag || elems->data != data) { + /* set enc info */ + elems->type = type; + elems->flag = flag; + elems->data = data; + info->updated |= (1 << type); + } + + return MPP_OK; +} + +MPP_RET hal_info_get(HalInfo ctx, MppDevInfoCfg *data, RK_S32 *size) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input ctx\n"); + return MPP_ERR_NULL_PTR; + } + + if (NULL == data || NULL == size || *size == 0) { + mpp_err_f("found invalid output cfg data %p size %p\n", data, size); + return MPP_ERR_NULL_PTR; + } + + HalInfoImpl *info = (HalInfoImpl *)ctx; + if (!info->updated) { + *size = 0; + return MPP_OK; + } + + RK_S32 max_size = *size; + RK_S32 elem_size = sizeof(info->elems[0]); + RK_S32 out_size = 0; + RK_S32 type_max = 0; + RK_S32 i; + + switch (info->type) { + case MPP_CTX_DEC : { + type_max = DEC_INFO_BUTT - DEC_INFO_BASE; + } break; + case MPP_CTX_ENC : { + type_max = ENC_INFO_BUTT - ENC_INFO_BASE; + } break; + default : { + mpp_err_f("found invalid ctx type %d\n", info->type); + return MPP_ERR_VALUE; + } break; + } + + for (i = 0; i < type_max; i++) { + if (!(info->updated & (1 << i))) + continue; + + if (out_size + elem_size > max_size) { + mpp_err_f("out data size %d is too small for %d\n", + max_size, out_size + elem_size); + break; + } + + memcpy(data, &info->elems[i], elem_size); + data++; + out_size += elem_size; + info->updated &= ~(1 << i); + } + + *size = out_size; + return MPP_OK; +} + +RK_U64 hal_info_to_string(HalInfo ctx, RK_U32 type, void *val) +{ + RK_U64 ret = 0; + + if (NULL == ctx || NULL == val) { + mpp_err_f("found NULL input ctx %p val %p\n", ctx, val); + return ret; + } + + HalInfoImpl *info = (HalInfoImpl *)ctx; + const char *str = NULL; + + switch (info->type) { + case MPP_CTX_DEC : { + switch (type) { + case DEC_INFO_FORMAT : { + MppCodingType coding = *((MppCodingType *)val); + + mpp_assert(coding == info->coding); + str = strof_coding_type(coding); + } break; + default : { + } break; + } + } break; + case MPP_CTX_ENC : { + switch (type) { + case ENC_INFO_FORMAT : { + MppCodingType coding = *((MppCodingType *)val); + + mpp_assert(coding == info->coding); + str = strof_coding_type(coding); + } break; + case ENC_INFO_RC_MODE : { + MppEncRcMode rc_mode = *((MppEncRcMode *)val); + + str = strof_rc_mode(rc_mode); + } break; + case ENC_INFO_PROFILE : { + RK_U32 profile = *((RK_U32 *)val); + + str = strof_profle(info->coding, profile); + } break; + default : { + } break; + } + } break; + default : { + mpp_err_f("found invalid ctx type %d\n", info->type); + return MPP_ERR_VALUE; + } break; + } + + if (str) + snprintf((void *)&ret, sizeof(ret) - 1, "%s", str); + + return ret; +} + +RK_U64 hal_info_to_float(RK_S32 num, RK_S32 denom) +{ + RK_U64 ret = 0; + + if (!denom) + snprintf((void *)&ret, sizeof(ret) - 1, "%d", num); + else + snprintf((void *)&ret, sizeof(ret) - 1, "%.2f", (float)num / denom); + + return ret; +} + +MPP_RET hal_info_from_enc_cfg(HalInfo ctx, MppEncCfgSet *cfg) +{ + MppEncRcCfg *rc = &cfg->rc; + MppEncPrepCfg *prep = &cfg->prep; + HalInfoImpl *info = (HalInfoImpl *)ctx; + RK_U32 profile = 0; + RK_U64 val = 0; + + hal_info_set(ctx, ENC_INFO_WIDTH, CODEC_INFO_FLAG_NUMBER, prep->width); + hal_info_set(ctx, ENC_INFO_HEIGHT, CODEC_INFO_FLAG_NUMBER, prep->height); + + val = hal_info_to_string(ctx, ENC_INFO_FORMAT, &info->coding); + + hal_info_set(ctx, ENC_INFO_FORMAT, CODEC_INFO_FLAG_STRING, val); + hal_info_set(ctx, ENC_INFO_FPS_IN, CODEC_INFO_FLAG_NUMBER, + rc->fps_in_num / rc->fps_in_denom); + hal_info_set(ctx, ENC_INFO_FPS_OUT, CODEC_INFO_FLAG_NUMBER, + rc->fps_out_num / rc->fps_out_denom); + + val = hal_info_to_string(ctx, ENC_INFO_RC_MODE, &rc->rc_mode); + hal_info_set(ctx, ENC_INFO_RC_MODE, CODEC_INFO_FLAG_STRING, val); + + hal_info_set(ctx, ENC_INFO_BITRATE, CODEC_INFO_FLAG_NUMBER, rc->bps_target); + hal_info_set(ctx, ENC_INFO_GOP_SIZE, CODEC_INFO_FLAG_NUMBER, rc->gop); + + switch (info->coding) { + case MPP_VIDEO_CodingAVC : { + profile = cfg->h264.profile; + } break; + case MPP_VIDEO_CodingHEVC : { + profile = cfg->h265.profile; + } break; + case MPP_VIDEO_CodingMJPEG : + case MPP_VIDEO_CodingVP8 : + default : { + } break; + } + val = hal_info_to_string(ctx, ENC_INFO_PROFILE, &profile); + hal_info_set(ctx, ENC_INFO_PROFILE, CODEC_INFO_FLAG_STRING, val); + + return MPP_OK; +} diff --git a/mpp/hal/common/hal_info.h b/mpp/hal/common/hal_info.h new file mode 100644 index 000000000..4a9e03b17 --- /dev/null +++ b/mpp/hal/common/hal_info.h @@ -0,0 +1,75 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_INFO_H +#define HAL_INFO_H + +#include "mpp_enc_cfg.h" +#include "mpp_device.h" + +typedef enum CodecInfoType_e { + /* ENC info */ + ENC_INFO_BASE = 0, + ENC_INFO_WIDTH = (ENC_INFO_BASE + 1), + ENC_INFO_HEIGHT = (ENC_INFO_BASE + 2), + ENC_INFO_FORMAT = (ENC_INFO_BASE + 3), + ENC_INFO_FPS_IN = (ENC_INFO_BASE + 4), + ENC_INFO_FPS_OUT = (ENC_INFO_BASE + 5), + ENC_INFO_RC_MODE = (ENC_INFO_BASE + 6), + ENC_INFO_BITRATE = (ENC_INFO_BASE + 7), + ENC_INFO_GOP_SIZE = (ENC_INFO_BASE + 8), + ENC_INFO_FPS_CALC = (ENC_INFO_BASE + 9), + ENC_INFO_PROFILE = (ENC_INFO_BASE + 10), + ENC_INFO_BUTT, + + /* DEC info */ + DEC_INFO_BASE = 16, + DEC_INFO_WIDTH = (DEC_INFO_BASE + 1), + DEC_INFO_HEIGHT = (DEC_INFO_BASE + 2), + DEC_INFO_FORMAT = (DEC_INFO_BASE + 3), + DEC_INFO_BITDEPTH = (DEC_INFO_BASE + 4), + DEC_INFO_FPS = (DEC_INFO_BASE + 5), + DEC_INFO_BUTT, +} CodecInfoType; + +enum CODEC_INFO_FLAGS { + CODEC_INFO_FLAG_NULL = 0, + CODEC_INFO_FLAG_NUMBER = 1, + CODEC_INFO_FLAG_STRING = 2, + CODEC_INFO_FLAG_BUTT, +}; + +typedef void* HalInfo; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET hal_info_init(HalInfo *ctx, MppCtxType type, MppCodingType coding); +MPP_RET hal_info_deinit(HalInfo ctx); +MPP_RET hal_info_set(HalInfo ctx, RK_U32 type, RK_U32 flag, RK_U64 data); +MPP_RET hal_info_get(HalInfo ctx, MppDevInfoCfg *data, RK_S32 *size); + +RK_U64 hal_info_to_string(HalInfo ctx, RK_U32 type, void *val); +RK_U64 hal_info_to_float(RK_S32 num, RK_S32 denom); + +MPP_RET hal_info_from_enc_cfg(HalInfo ctx, MppEncCfgSet *cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_INFO_H */ diff --git a/mpp/hal/common/jpeg/CMakeLists.txt b/mpp/hal/common/jpeg/CMakeLists.txt new file mode 100644 index 000000000..a1d537f59 --- /dev/null +++ b/mpp/hal/common/jpeg/CMakeLists.txt @@ -0,0 +1,10 @@ +# vim: syntax=cmake +include_directories(.) +include_directories(../../rkenc/common/) +include_directories(../../rkenc/jpege/) +include_directories(../../vpu/jpege/) + +# hal jpeg encoder common +add_library(hal_jpege_com OBJECT + hal_jpege_hdr.c + ) diff --git a/mpp/hal/common/jpeg/hal_jpege_debug.h b/mpp/hal/common/jpeg/hal_jpege_debug.h new file mode 100644 index 000000000..0a27659ad --- /dev/null +++ b/mpp/hal/common/jpeg/hal_jpege_debug.h @@ -0,0 +1,43 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGE_DEBUG_H +#define HAL_JPEGE_DEBUG_H + +#include "mpp_debug.h" + +#define HAL_JPEGE_DBG_FUNCTION (0x00000001) +#define HAL_JPEGE_DBG_SIMPLE (0x00000002) +#define HAL_JPEGE_DBG_DETAIL (0x00000004) +#define HAL_JPEGE_DBG_INPUT (0x00000010) +#define HAL_JPEGE_DBG_OUTPUT (0x00000020) + +#define hal_jpege_dbg(flag, fmt, ...) mpp_dbg(hal_jpege_debug, flag, fmt, ## __VA_ARGS__) +#define hal_jpege_dbg_f(flag, fmt, ...) mpp_dbg_f(hal_jpege_debug, flag, fmt, ## __VA_ARGS__) + +#define hal_jpege_dbg_func(fmt, ...) hal_jpege_dbg_f(HAL_JPEGE_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define hal_jpege_dbg_simple(fmt, ...) hal_jpege_dbg(HAL_JPEGE_DBG_SIMPLE, fmt, ## __VA_ARGS__) +#define hal_jpege_dbg_detail(fmt, ...) hal_jpege_dbg(HAL_JPEGE_DBG_DETAIL, fmt, ## __VA_ARGS__) +#define hal_jpege_dbg_input(fmt, ...) hal_jpege_dbg(HAL_JPEGE_DBG_INPUT, fmt, ## __VA_ARGS__) +#define hal_jpege_dbg_output(fmt, ...) hal_jpege_dbg(HAL_JPEGE_DBG_OUTPUT, fmt, ## __VA_ARGS__) + +#define hal_jpege_enter() hal_jpege_dbg_func("(%d) enter\n", __LINE__); +#define hal_jpege_leave() hal_jpege_dbg_func("(%d) leave\n", __LINE__); + + +extern RK_U32 hal_jpege_debug; + +#endif /* HAL_JPEGE_DEBUG_H */ diff --git a/mpp/hal/common/jpeg/hal_jpege_hdr.c b/mpp/hal/common/jpeg/hal_jpege_hdr.c new file mode 100644 index 000000000..7ca7c6ac7 --- /dev/null +++ b/mpp/hal/common/jpeg/hal_jpege_hdr.c @@ -0,0 +1,991 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "hal_jpege_hdr.h" + +/* JPEG markers, table B.1 */ +enum { + SOI = 0xFFD8, /* Start of Image */ + DQT = 0xFFDB, /* Define Quantization Table(s) */ + SOF0 = 0xFFC0, /* Start of Frame */ + DRI = 0xFFDD, /* Define Restart Interval */ + RST0 = 0xFFD0, /* Restart marker 0 */ + RST1 = 0xFFD1, /* Restart marker 1 */ + RST2 = 0xFFD2, /* Restart marker 2 */ + RST3 = 0xFFD3, /* Restart marker 3 */ + RST4 = 0xFFD4, /* Restart marker 4 */ + RST5 = 0xFFD5, /* Restart marker 5 */ + RST6 = 0xFFD6, /* Restart marker 6 */ + RST7 = 0xFFD7, /* Restart marker 7 */ + DHT = 0xFFC4, /* Define Huffman Table(s) */ + SOS = 0xFFDA, /* Start of Scan */ + EOI = 0xFFD9, /* End of Image */ + APP0 = 0xFFE0, /* APP0 Marker */ + APP7 = 0xFFE7, /* APP7 Marker */ + COM = 0xFFFE /* Comment marker */ +}; + +enum { + JPEGE_NO_UNITS = 0, + JPEGE_DOTS_PER_INCH = 1, + JPEGE_DOTS_PER_CM = 2 +}; + +enum { + JPEGE_SINGLE_MARKER, + JPEGE_MULTI_MARKER +}; + +static const RK_U8 zigzag[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +/* Mjpeg quantization tables levels 0-10 */ +static const RK_U8 qtable_y[11][64] = { + { + 80, 56, 50, 80, 120, 200, 248, 248, + 60, 60, 72, 96, 136, 248, 248, 248, + 72, 68, 80, 120, 200, 248, 248, 248, + 72, 88, 112, 152, 248, 248, 248, 248, + 92, 112, 192, 248, 248, 248, 248, 248, + 120, 176, 248, 248, 248, 248, 248, 248, + 152, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248 + }, + + { + 40, 28, 25, 40, 60, 100, 128, 160, + 30, 30, 36, 48, 68, 152, 152, 144, + 36, 34, 40, 60, 100, 144, 176, 144, + 36, 44, 56, 76, 128, 224, 200, 160, + 46, 56, 96, 144, 176, 248, 248, 200, + 60, 88, 144, 160, 208, 248, 248, 232, + 124, 160, 200, 224, 248, 248, 248, 248, + 184, 232, 240, 248, 248, 248, 248, 248 + }, + + { + 27, 18, 17, 27, 40, 68, 88, 104, + 20, 20, 23, 32, 44, 96, 100, 92, + 23, 22, 27, 40, 68, 96, 116, 96, + 23, 28, 38, 48, 88, 144, 136, 104, + 30, 38, 62, 96, 116, 184, 176, 128, + 40, 58, 92, 108, 136, 176, 192, 160, + 84, 108, 136, 144, 176, 208, 200, 168, + 120, 160, 160, 168, 192, 168, 176, 168 + }, + + { + 20, 14, 13, 20, 30, 50, 64, 76, + 15, 15, 18, 24, 34, 76, 76, 72, + 18, 16, 20, 30, 50, 72, 88, 72, + 18, 21, 28, 36, 64, 112, 100, 80, + 23, 28, 46, 72, 88, 136, 136, 96, + 30, 44, 72, 80, 104, 136, 144, 116, + 62, 80, 100, 112, 136, 152, 152, 128, + 92, 116, 120, 124, 144, 128, 136, 124 + }, + + { + 16, 11, 10, 16, 24, 40, 52, 62, + 12, 12, 14, 19, 26, 58, 60, 56, + 14, 13, 16, 24, 40, 58, 72, 56, + 14, 17, 22, 29, 52, 88, 80, 62, + 18, 22, 38, 56, 68, 112, 104, 80, + 24, 36, 56, 64, 84, 104, 116, 92, + 50, 64, 80, 88, 104, 124, 120, 104, + 72, 92, 96, 100, 124, 100, 104, 100 + }, + + { + 13, 9, 8, 13, 19, 32, 42, 50, + 10, 10, 11, 15, 21, 46, 48, 44, + 11, 10, 13, 19, 32, 46, 56, 46, + 11, 14, 18, 23, 42, 72, 64, 50, + 14, 18, 30, 46, 54, 88, 84, 62, + 19, 28, 44, 52, 68, 84, 92, 76, + 40, 52, 62, 72, 84, 100, 96, 84, + 58, 76, 76, 80, 100, 80, 84, 80 + }, + + { + 10, 7, 6, 10, 14, 24, 31, 38, + 7, 7, 8, 11, 16, 36, 36, 34, + 8, 8, 10, 14, 24, 34, 42, 34, + 8, 10, 13, 17, 32, 52, 48, 38, + 11, 13, 22, 34, 42, 68, 62, 46, + 14, 21, 34, 38, 50, 62, 68, 56, + 29, 38, 48, 52, 62, 76, 72, 62, + 44, 56, 58, 60, 68, 60, 62, 60 + }, + + { + 6, 4, 4, 6, 10, 16, 20, 24, + 5, 5, 6, 8, 10, 23, 24, 22, + 6, 5, 6, 10, 16, 23, 28, 22, + 6, 7, 9, 12, 20, 36, 32, 25, + 7, 9, 15, 22, 27, 44, 42, 31, + 10, 14, 22, 26, 32, 42, 46, 38, + 20, 26, 31, 36, 42, 48, 48, 40, + 29, 38, 38, 40, 46, 40, 42, 40 + }, + + { + 3, 2, 2, 3, 5, 8, 10, 12, + 2, 2, 3, 4, 5, 12, 12, 11, + 3, 3, 3, 5, 8, 11, 14, 11, + 3, 3, 4, 6, 10, 17, 16, 12, + 4, 4, 7, 11, 14, 22, 21, 15, + 5, 7, 11, 13, 16, 21, 23, 18, + 10, 13, 16, 17, 21, 24, 24, 20, + 14, 18, 19, 20, 22, 20, 21, 20 + }, + + { + 1, 1, 1, 1, 2, 3, 3, 4, + 1, 1, 1, 1, 2, 4, 4, 4, + 1, 1, 1, 2, 3, 4, 5, 4, + 1, 1, 1, 2, 3, 6, 5, 4, + 1, 1, 2, 4, 5, 7, 7, 5, + 2, 2, 4, 4, 5, 7, 8, 6, + 3, 4, 5, 6, 7, 8, 8, 7, + 5, 6, 6, 7, 7, 7, 7, 7 + }, + + { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 + } +}; + +static const RK_U8 qtable_c[11][64] = { + { + 88, 92, 120, 240, 248, 248, 248, 248, + 92, 108, 136, 248, 248, 248, 248, 248, + 120, 136, 248, 248, 248, 248, 248, 248, + 240, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248 + }, + + { + 44, 46, 60, 120, 248, 248, 248, 248, + 46, 54, 68, 168, 248, 248, 248, 248, + 60, 66, 144, 248, 248, 248, 248, 248, + 120, 168, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248 + }, + + { + 28, 30, 40, 80, 168, 168, 168, 168, + 30, 36, 44, 112, 168, 168, 168, 168, + 40, 44, 96, 168, 168, 168, 168, 168, + 80, 112, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168 + }, + + { + 21, 23, 30, 60, 124, 124, 124, 124, + 23, 26, 34, 84, 124, 124, 124, 124, + 30, 34, 72, 124, 124, 124, 124, 124, + 60, 84, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124 + }, + + { + 17, 18, 24, 48, 100, 100, 100, 100, + 18, 21, 26, 68, 100, 100, 100, 100, + 24, 26, 56, 100, 100, 100, 100, 100, + 48, 68, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100 + }, + + { + 14, 14, 19, 38, 80, 80, 80, 80, + 14, 17, 21, 54, 80, 80, 80, 80, + 19, 21, 46, 80, 80, 80, 80, 80, + 38, 54, 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 + }, + + { + 10, 11, 14, 28, 60, 60, 60, 60, + 11, 13, 16, 40, 60, 60, 60, 60, + 14, 16, 34, 60, 60, 60, 60, 60, + 28, 40, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60 + }, + + { + 7, 7, 10, 19, 40, 40, 40, 40, + 7, 8, 10, 26, 40, 40, 40, 40, + 10, 10, 22, 40, 40, 40, 40, 40, + 19, 26, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40 + }, + + { + 3, 4, 5, 9, 20, 20, 20, 20, + 4, 4, 5, 13, 20, 20, 20, 20, + 5, 5, 11, 20, 20, 20, 20, 20, + 9, 13, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20 + }, + + { + 1, 1, 2, 3, 7, 7, 7, 7, + 1, 1, 2, 4, 7, 7, 7, 7, + 2, 2, 4, 7, 7, 7, 7, 7, + 3, 4, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7 + }, + + { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 + } +}; + +/* + * from RFC435 spec. + */ +const RK_U8 jpege_luma_quantizer[QUANTIZE_TABLE_SIZE] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +const RK_U8 jpege_chroma_quantizer[QUANTIZE_TABLE_SIZE] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +typedef struct { + RK_U32 Ci[MAX_NUMBER_OF_COMPONENTS]; + RK_U32 Hi[MAX_NUMBER_OF_COMPONENTS]; + RK_U32 Vi[MAX_NUMBER_OF_COMPONENTS]; + RK_U32 Tqi[MAX_NUMBER_OF_COMPONENTS]; +} JpegeColorInfo; + +typedef struct { + RK_U32 val_y; + RK_U32 val_c; +} JpegeHuffmanTable; + +static const JpegeHuffmanTable dc_li[16] = { + {0x00, 0x00}, + {0x01, 0x03}, + {0x05, 0x01}, + {0x01, 0x01}, + {0x01, 0x01}, + {0x01, 0x01}, + {0x01, 0x01}, + {0x01, 0x01}, + {0x01, 0x01}, + {0x00, 0x01}, + {0x00, 0x01}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00}, + {0x00, 0x00} +}; + +static const JpegeHuffmanTable dc_vij[12] = { + {0x00, 0x00}, + {0x01, 0x01}, + {0x02, 0x02}, + {0x03, 0x03}, + {0x04, 0x04}, + {0x05, 0x05}, + {0x06, 0x06}, + {0x07, 0x07}, + {0x08, 0x08}, + {0x09, 0x09}, + {0x0A, 0x0A}, + {0x0B, 0x0B}, +}; + +static const JpegeHuffmanTable ac_li[16] = { + {0x00, 0x00}, + {0x02, 0x02}, + {0x01, 0x01}, + {0x03, 0x02}, + {0x03, 0x04}, + {0x02, 0x04}, + {0x04, 0x03}, + {0x03, 0x04}, + {0x05, 0x07}, + {0x05, 0x05}, + {0x04, 0x04}, + {0x04, 0x04}, + {0x00, 0x00}, + {0x00, 0x01}, + {0x01, 0x02}, + {0x7D, 0x77} +}; + +static const JpegeHuffmanTable ac_vij[162] = { + {0x01, 0x00}, + {0x02, 0x01}, + {0x03, 0x02}, + {0x00, 0x03}, + {0x04, 0x11}, + {0x11, 0x04}, + {0x05, 0x05}, + {0x12, 0x21}, + {0x21, 0x31}, + {0x31, 0x06}, + {0x41, 0x12}, + {0x06, 0x41}, + {0x13, 0x51}, + {0x51, 0x07}, + {0x61, 0x61}, + {0x07, 0x71}, + {0x22, 0x13}, + {0x71, 0x22}, + {0x14, 0x32}, + {0x32, 0x81}, + {0x81, 0x08}, + {0x91, 0x14}, + {0xA1, 0x42}, + {0x08, 0x91}, + {0x23, 0xA1}, + {0x42, 0xB1}, + {0xB1, 0xC1}, + {0xC1, 0x09}, + {0x15, 0x23}, + {0x52, 0x33}, + {0xD1, 0x52}, + {0xF0, 0xF0}, + {0x24, 0x15}, + {0x33, 0x62}, + {0x62, 0x72}, + {0x72, 0xD1}, + {0x82, 0x0A}, + {0x09, 0x16}, + {0x0A, 0x24}, + {0x16, 0x34}, + {0x17, 0xE1}, + {0x18, 0x25}, + {0x19, 0xF1}, + {0x1A, 0x17}, + {0x25, 0x18}, + {0x26, 0x19}, + {0x27, 0x1A}, + {0x28, 0x26}, + {0x29, 0x27}, + {0x2A, 0x28}, + {0x34, 0x29}, + {0x35, 0x2A}, + {0x36, 0x35}, + {0x37, 0x36}, + {0x38, 0x37}, + {0x39, 0x38}, + {0x3A, 0x39}, + {0x43, 0x3A}, + {0x44, 0x43}, + {0x45, 0x44}, + {0x46, 0x45}, + {0x47, 0x46}, + {0x48, 0x47}, + {0x49, 0x48}, + {0x4A, 0x49}, + {0x53, 0x4A}, + {0x54, 0x53}, + {0x55, 0x54}, + {0x56, 0x55}, + {0x57, 0x56}, + {0x58, 0x57}, + {0x59, 0x58}, + {0x5A, 0x59}, + {0x63, 0x5A}, + {0x64, 0x63}, + {0x65, 0x64}, + {0x66, 0x65}, + {0x67, 0x66}, + {0x68, 0x67}, + {0x69, 0x68}, + {0x6A, 0x69}, + {0x73, 0x6A}, + {0x74, 0x73}, + {0x75, 0x74}, + {0x76, 0x75}, + {0x77, 0x76}, + {0x78, 0x77}, + {0x79, 0x78}, + {0x7A, 0x79}, + {0x83, 0x7A}, + {0x84, 0x82}, + {0x85, 0x83}, + {0x86, 0x84}, + {0x87, 0x85}, + {0x88, 0x86}, + {0x89, 0x87}, + {0x8A, 0x88}, + {0x92, 0x89}, + {0x93, 0x8A}, + {0x94, 0x92}, + {0x95, 0x93}, + {0x96, 0x94}, + {0x97, 0x95}, + {0x98, 0x96}, + {0x99, 0x97}, + {0x9A, 0x98}, + {0xA2, 0x99}, + {0xA3, 0x9A}, + {0xA4, 0xA2}, + {0xA5, 0xA3}, + {0xA6, 0xA4}, + {0xA7, 0xA5}, + {0xA8, 0xA6}, + {0xA9, 0xA7}, + {0xAA, 0xA8}, + {0xB2, 0xA9}, + {0xB3, 0xAA}, + {0xB4, 0xB2}, + {0xB5, 0xB3}, + {0xB6, 0xB4}, + {0xB7, 0xB5}, + {0xB8, 0xB6}, + {0xB9, 0xB7}, + {0xBA, 0xB8}, + {0xC2, 0xB9}, + {0xC3, 0xBA}, + {0xC4, 0xC2}, + {0xC5, 0xC3}, + {0xC6, 0xC4}, + {0xC7, 0xC5}, + {0xC8, 0xC6}, + {0xC9, 0xC7}, + {0xCA, 0xC8}, + {0xD2, 0xC9}, + {0xD3, 0xCA}, + {0xD4, 0xD2}, + {0xD5, 0xD3}, + {0xD6, 0xD4}, + {0xD7, 0xD5}, + {0xD8, 0xD6}, + {0xD9, 0xD7}, + {0xDA, 0xD8}, + {0xE1, 0xD9}, + {0xE2, 0xDA}, + {0xE3, 0xE2}, + {0xE4, 0xE3}, + {0xE5, 0xE4}, + {0xE6, 0xE5}, + {0xE7, 0xE6}, + {0xE8, 0xE7}, + {0xE9, 0xE8}, + {0xEA, 0xE9}, + {0xF1, 0xEA}, + {0xF2, 0xF2}, + {0xF3, 0xF3}, + {0xF4, 0xF4}, + {0xF5, 0xF5}, + {0xF6, 0xF6}, + {0xF7, 0xF7}, + {0xF8, 0xF8}, + {0xF9, 0xF9}, + {0xFA, 0xFA} +}; + +typedef struct { + RK_U8 *buffer; /* Pointer to first byte of stream */ + RK_U8 *stream; /* Pointer to next byte of stream */ + RK_U32 size; /* Byte size of stream buffer */ + RK_U32 byteCnt; /* Byte counter */ + RK_U32 bitCnt; /* Bit counter */ + RK_U32 byteBuffer; /* Byte buffer */ + RK_U32 bufferedBits; /* Amount of bits in byte buffer, [0-7] */ +} JpegeBitsImpl; + +void jpege_bits_init(JpegeBits *ctx) +{ + JpegeBitsImpl *impl = mpp_malloc(JpegeBitsImpl, 1); + *ctx = impl; +} + +void jpege_bits_deinit(JpegeBits ctx) +{ + if (ctx) + mpp_free(ctx); +} + +void jpege_bits_setup(JpegeBits ctx, RK_U8 *buf, RK_S32 size) +{ + JpegeBitsImpl *impl = (JpegeBitsImpl *)ctx; + + impl->buffer = buf; + impl->stream = buf; + impl->size = size; + impl->byteCnt = 0; + impl->bitCnt = 0; + impl->byteBuffer = 0; + impl->bufferedBits = 0; +} + +void jpege_bits_put(JpegeBits ctx, RK_U32 value, RK_S32 number) +{ + JpegeBitsImpl *impl = (JpegeBitsImpl *)ctx; + + RK_U32 bits; + RK_U32 byteBuffer = impl->byteBuffer; + RK_U8 *stream = impl->stream; + + /* Debug: value is too big */ + mpp_assert(value < ((RK_U32) 1 << number)); + mpp_assert(number < 25); + + bits = number + impl->bufferedBits; + + value <<= (32 - bits); + byteBuffer = (((RK_U32) stream[0]) << 24) | value; + + while (bits > 7) { + *stream = (RK_U8) (byteBuffer >> 24); + bits -= 8; + byteBuffer <<= 8; + stream++; + impl->byteCnt++; + } + + stream[0] = (RK_U8) (byteBuffer >> 24); + impl->stream = stream; + impl->bitCnt += number; + impl->byteBuffer = byteBuffer; + impl->bufferedBits = (RK_U8) bits; +} + +void jpege_seek_bits(JpegeBits ctx, RK_S32 len) +{ + JpegeBitsImpl *impl = (JpegeBitsImpl*)ctx; + RK_U32 bits = len; + RK_U8 *stream = impl->stream; + + mpp_assert(bits < impl->size); + + while (bits > 7) { + stream++; + impl->byteCnt++; + bits -= 8; + } + + impl->stream = stream; + impl->bitCnt += len; + impl->byteBuffer = (RK_U32)stream[0]; + impl->bufferedBits = (RK_U8) bits; +} + +void jpege_bits_align_byte(JpegeBits ctx) +{ + JpegeBitsImpl *impl = (JpegeBitsImpl *)ctx; + + if (impl->bitCnt & 7) + jpege_bits_put(ctx, 0, 8 - (impl->bitCnt & 7)); +} + +RK_U8 *jpege_bits_get_buf(JpegeBits ctx) +{ + JpegeBitsImpl *impl = (JpegeBitsImpl *)ctx; + return impl->buffer; +} + +RK_S32 jpege_bits_get_bitpos(JpegeBits ctx) +{ + JpegeBitsImpl *impl = (JpegeBitsImpl *)ctx; + return impl->bitCnt; +} + +RK_S32 jpege_bits_get_bytepos(JpegeBits ctx) +{ + JpegeBitsImpl *impl = (JpegeBitsImpl *)ctx; + return impl->byteCnt; +} + +static void write_jpeg_comment_header(JpegeBits *bits, JpegeSyntax *syntax) +{ + RK_U32 i; + RK_U8 *data = syntax->comment_data; + RK_U32 length = syntax->comment_length; + + /* COM */ + jpege_bits_put(bits, COM, 16); + + /* Lc */ + jpege_bits_put(bits, 2 + length, 16); + + for (i = 0; i < length; i++) { + /* COM data */ + jpege_bits_put(bits, data[i], 8); + } +} + +static void write_jpeg_dqt_header(JpegeBits *bits, const RK_U8 *qtable, RK_U32 tbl_idx) +{ + RK_S32 i; + + /* DQT */ + jpege_bits_put(bits, DQT, 16); + /* Lq */ + jpege_bits_put(bits, 2 + 65, 16); + /* Pq */ + jpege_bits_put(bits, 0, 4); + /* Tq */ + jpege_bits_put(bits, tbl_idx, 4); + + for (i = 0; i < 64; i++) { + /* Qk table 0 */ + jpege_bits_put(bits, qtable[zigzag[i]], 8); + } +} + +static void write_jpeg_SOFO_header(JpegeBits *bits, JpegeSyntax *syntax) +{ + RK_U32 i; + RK_U32 width = syntax->width; + RK_U32 height = syntax->height; + + /* SOF0 */ + jpege_bits_put(bits, SOF0, 16); + + /* Lf */ + jpege_bits_put(bits, (8 + 3 * syntax->nb_components), 16); + /* P */ + jpege_bits_put(bits, 8, 8); + /* Y */ + jpege_bits_put(bits, height, 16); + /* X */ + jpege_bits_put(bits, width, 16); + /* Nf */ + jpege_bits_put(bits, syntax->nb_components, 8); + + for (i = 0; i < syntax->nb_components; i++) { + /* Ci */ + jpege_bits_put(bits, syntax->comp_info[i].component_id, 8); + /* Hi */ + jpege_bits_put(bits, syntax->comp_info[i].h_sample_factor, 4); + /* Vi */ + jpege_bits_put(bits, syntax->comp_info[i].v_sample_factor, 4); + /* Tqi */ + jpege_bits_put(bits, syntax->comp_info[i].tbl_selector, 8); + } +} + +static void write_jpeg_dht_header(JpegeBits *bits, JpegeSyntax *syntax) +{ + RK_S32 i; + + /* DHT */ + jpege_bits_put(bits, DHT, 16); + + /* Huffman table for luminance DC components */ + /* Lh */ + jpege_bits_put(bits, 2 + ((17 * 1) + ((1 * 12))), 16); + /* TC */ + jpege_bits_put(bits, TABLE_DC, 4); + /* TH */ + jpege_bits_put(bits, syntax->comp_info[0].tbl_selector, 4); + + for (i = 0; i < 16; i++) { + /* Dc_Li */ + jpege_bits_put(bits, dc_li[i].val_y, 8); + } + + for (i = 0; i < 12; i++) { + /* Dc_Vij */ + jpege_bits_put(bits, dc_vij[i].val_y, 8); + } + + /* DHT */ + jpege_bits_put(bits, DHT, 16); + + /* Huffman table for luminance AC components */ + /* Lh */ + jpege_bits_put(bits, 2 + ((17 * 1) + ((1 * 162))), 16); + /* TC */ + jpege_bits_put(bits, TABLE_AC, 4); + /* TH */ + jpege_bits_put(bits, syntax->comp_info[0].tbl_selector, 4); + + for (i = 0; i < 16; i++) { + /* Ac_Li */ + jpege_bits_put(bits, ac_li[i].val_y, 8); + } + + for (i = 0; i < 162; i++) { + /* Ac_Vij */ + jpege_bits_put(bits, ac_vij[i].val_y, 8); + } + + if (syntax->nb_components == 1) + return; + + /* Huffman table for chrominance DC components */ + /* DHT */ + jpege_bits_put(bits, DHT, 16); + /* Lh */ + jpege_bits_put(bits, 2 + ((17 * 1) + ((1 * 12))), 16); + /* TC */ + jpege_bits_put(bits, TABLE_DC, 4); + /* TH */ + jpege_bits_put(bits, syntax->comp_info[1].tbl_selector, 4); + + for (i = 0; i < 16; i++) { + /* Dc_Li */ + jpege_bits_put(bits, dc_li[i].val_c, 8); + } + + for (i = 0; i < 12; i++) { + /* Dc_Vij */ + jpege_bits_put(bits, dc_vij[i].val_c, 8); + } + + /* Huffman table for chrominance AC components */ + /* DHT */ + jpege_bits_put(bits, DHT, 16); + /* Lh */ + jpege_bits_put(bits, 2 + ((17 * 1) + ((1 * 162))), 16); + /* TC */ + jpege_bits_put(bits, TABLE_AC, 4); + /* TH */ + jpege_bits_put(bits, syntax->comp_info[1].tbl_selector, 4); + + for (i = 0; i < 16; i++) { + /* Ac_Li */ + jpege_bits_put(bits, ac_li[i].val_c, 8); + } + + for (i = 0; i < 162; i++) { + /* Ac_Vij */ + jpege_bits_put(bits, ac_vij[i].val_c, 8); + } +} + +static void write_jpeg_sos_header(JpegeBits *bits, JpegeSyntax *syntax) +{ + RK_U32 i; + RK_U32 Ns = syntax->nb_components; + RK_U32 Ls = (6 + (2 * Ns)); + + /* SOS */ + jpege_bits_put(bits, SOS, 16); + /* Ls */ + jpege_bits_put(bits, Ls, 16); + /* Ns */ + jpege_bits_put(bits, Ns, 8); + + for (i = 0; i < Ns; i++) { + /* Csj */ + jpege_bits_put(bits, syntax->comp_info[i].component_id, 8); + /* Tdj */ + jpege_bits_put(bits, syntax->comp_info[i].tbl_selector, 4); + /* Taj */ + jpege_bits_put(bits, syntax->comp_info[i].tbl_selector, 4); + } + + /* Ss */ + jpege_bits_put(bits, 0, 8); + /* Se */ + jpege_bits_put(bits, 63, 8); + /* Ah */ + jpege_bits_put(bits, 0, 4); + /* Al */ + jpege_bits_put(bits, 0, 4); +} + + +void write_jpeg_RestartInterval(JpegeBits *bits, JpegeSyntax *syntax) +{ + if (syntax->restart_ri) { + jpege_bits_put(bits, 0xFFDD, 16); + jpege_bits_put(bits, 4, 16); + jpege_bits_put(bits, syntax->restart_ri, 16); + } +} + +MPP_RET write_jpeg_header(JpegeBits *bits, JpegeSyntax *syntax, HalJpegeRc *hal_rc) +{ + RK_U32 i = 0; + RK_U32 qtable_number = syntax->nb_components == 1 ? 1 : 2; + + /* Com header */ + if (syntax->comment_length) + write_jpeg_comment_header(bits, syntax); + + for (i = 0; i < qtable_number; i++) + write_jpeg_dqt_header(bits, hal_rc->qtables[i], i); + + /* Frame header */ + write_jpeg_SOFO_header(bits, syntax); + + /* Do NOT have Restart interval */ + write_jpeg_RestartInterval(bits, syntax); + + /* Huffman header */ + write_jpeg_dht_header(bits, syntax); + + /* Scan header */ + write_jpeg_sos_header(bits, syntax); + + jpege_bits_align_byte(bits); + return MPP_OK; +} + +void hal_jpege_rc_init(HalJpegeRc *hal_rc) +{ + /* default best quality qtable 10 */ + hal_rc->q_mode = JPEG_QUANT; + hal_rc->quant = 10; + hal_rc->q_factor = -1; + memset(hal_rc->qtable_y, 1, QUANTIZE_TABLE_SIZE); + memset(hal_rc->qtable_u, 1, QUANTIZE_TABLE_SIZE); + memset(hal_rc->qtable_v, 1, QUANTIZE_TABLE_SIZE); + hal_rc->qtables[0] = qtable_y[hal_rc->quant]; + hal_rc->qtables[1] = qtable_c[hal_rc->quant]; + hal_rc->qtables[2] = qtable_c[hal_rc->quant]; +} + +static void qfactor_to_qf_table(RK_S32 qfactor, RK_U8 *hal_rc_qtable_y, RK_U8 *hal_rc_qtable_c) +{ + RK_U32 q; + RK_U32 i; + + if (qfactor < 50) + q = 5000 / qfactor; + else + q = 200 - (qfactor << 1); + + for (i = 0; i < QUANTIZE_TABLE_SIZE; i++) { + RK_S16 lq = (jpege_luma_quantizer[i] * q + 50) / 100; + RK_S16 cq = (jpege_chroma_quantizer[i] * q + 50) / 100; + + /* Limit the quantizers to 1 <= q <= 255 */ + hal_rc_qtable_y[i] = MPP_CLIP3(1, 255, lq); + hal_rc_qtable_c[i] = MPP_CLIP3(1, 255, cq); + } +} + +void hal_jpege_rc_update(HalJpegeRc *hal_rc, JpegeSyntax *syntax) +{ + switch (syntax->q_mode) { + case JPEG_QUANT : { + RK_S32 quant = syntax->quant; + + hal_rc->q_mode = JPEG_QUANT; + hal_rc->quant = quant; + hal_rc->qtables[0] = qtable_y[quant]; + hal_rc->qtables[1] = qtable_c[quant]; + hal_rc->qtables[2] = qtable_c[quant]; + hal_rc->q_factor = -1; + } break; + case JPEG_QFACTOR : { + if (hal_rc->q_mode != JPEG_QFACTOR || hal_rc->q_factor != syntax->q_factor) + qfactor_to_qf_table(syntax->q_factor, hal_rc->qtable_y, hal_rc->qtable_u); + + hal_rc->q_mode = JPEG_QFACTOR; + /* NOTE: qfactor mode uv use the same table */ + hal_rc->qtables[0] = hal_rc->qtable_y; + hal_rc->qtables[1] = hal_rc->qtable_u; + hal_rc->qtables[2] = hal_rc->qtable_u; + hal_rc->q_factor = syntax->q_factor; + } break; + case JPEG_QTABLE : { + hal_rc->q_mode = JPEG_QTABLE; + memcpy(hal_rc->qtable_y, syntax->qtable_y, QUANTIZE_TABLE_SIZE); + memcpy(hal_rc->qtable_u, syntax->qtable_u, QUANTIZE_TABLE_SIZE); + memcpy(hal_rc->qtable_v, syntax->qtable_v, QUANTIZE_TABLE_SIZE); + hal_rc->qtables[0] = hal_rc->qtable_y; + hal_rc->qtables[1] = hal_rc->qtable_u; + hal_rc->qtables[2] = hal_rc->qtable_v; + hal_rc->q_factor = -1; + } break; + default : { + mpp_err_f("invalid q_mode %d use default best quanlity qtable\n", syntax->q_mode); + hal_rc->q_mode = JPEG_QUANT; + hal_rc->quant = 10; + hal_rc->qtables[0] = qtable_y[10]; + hal_rc->qtables[1] = qtable_c[10]; + hal_rc->qtables[2] = qtable_c[10]; + hal_rc->q_factor = -1; + } break; + } +} diff --git a/mpp/hal/common/jpeg/hal_jpege_hdr.h b/mpp/hal/common/jpeg/hal_jpege_hdr.h new file mode 100644 index 000000000..e17e850c3 --- /dev/null +++ b/mpp/hal/common/jpeg/hal_jpege_hdr.h @@ -0,0 +1,60 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGE_HDR_H +#define HAL_JPEGE_HDR_H + +#include "jpege_syntax.h" + +typedef void *JpegeBits; + +#ifdef __cplusplus +extern "C" { +#endif + +#define QUANTIZE_TABLE_SIZE 64 +typedef struct HalJpegeRc_t { + RK_S32 q_mode; + RK_S32 quant; + RK_S32 q_factor; + RK_U8 qtable_y[QUANTIZE_TABLE_SIZE]; + RK_U8 qtable_u[QUANTIZE_TABLE_SIZE]; + RK_U8 qtable_v[QUANTIZE_TABLE_SIZE]; + const RK_U8 *qtables[3]; +} HalJpegeRc; + +void jpege_bits_init(JpegeBits *ctx); +void jpege_bits_deinit(JpegeBits ctx); + +void jpege_bits_setup(JpegeBits ctx, RK_U8 *buf, RK_S32 size); +void jpege_bits_put(JpegeBits ctx, RK_U32 val, RK_S32 len); +void jpege_bits_align_byte(JpegeBits ctx); +void jpege_seek_bits(JpegeBits ctx, RK_S32 len); +RK_U8 *jpege_bits_get_buf(JpegeBits ctx); +RK_S32 jpege_bits_get_bitpos(JpegeBits ctx); +RK_S32 jpege_bits_get_bytepos(JpegeBits ctx); + +MPP_RET write_jpeg_header(JpegeBits *bits, JpegeSyntax *syntax, HalJpegeRc *rc); + +void hal_jpege_rc_init(HalJpegeRc *hal_rc); +void hal_jpege_rc_update(HalJpegeRc *hal_rc, JpegeSyntax *syntax); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_JPEGE_HDR_H */ + diff --git a/mpp/hal/dummy/CMakeLists.txt b/mpp/hal/dummy/CMakeLists.txt deleted file mode 100644 index a581e1889..000000000 --- a/mpp/hal/dummy/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# vim: syntax=cmake - -# hal dummy decoder api -set(HAL_DUMMY_API - ../inc/hal_dummy_dec_api.h - ../inc/hal_dummy_enc_api.h - ) - - -# hal dummy header -set(HAL_DUMMY_HDR - - ) - -# hal dummy decoder sourse -set(HAL_DUMMY_SRC - hal_dummy_dec_api.c - hal_dummy_enc_api.c - ) - -add_library(hal_dummy STATIC - ${HAL_DUMMY_API} - ${HAL_DUMMY_HDR} - ${HAL_DUMMY_SRC} - ) - -set_target_properties(hal_dummy PROPERTIES FOLDER "mpp/hal") diff --git a/mpp/hal/dummy/hal_dummy_dec_api.c b/mpp/hal/dummy/hal_dummy_dec_api.c deleted file mode 100644 index f56f5b13e..000000000 --- a/mpp/hal/dummy/hal_dummy_dec_api.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#define MODULE_TAG "hal_dummy_dec" - -#include "hal_dummy_dec_api.h" - - -MPP_RET hal_dummy_dec_init(void *hal, MppHalCfg *cfg) -{ - (void)hal; - (void)cfg; - return MPP_OK; -} - -MPP_RET hal_dummy_dec_deinit(void *hal) -{ - (void)hal; - return MPP_OK; -} - -MPP_RET hal_dummy_dec_gen_regs(void *hal, HalTask *task) -{ - (void)hal; - (void)task; - return MPP_OK; -} -MPP_RET hal_dummy_dec_start(void *hal, HalTask *task) -{ - (void)hal; - (void)task; - return MPP_OK; -} - -MPP_RET hal_dummy_dec_wait(void *hal, HalTask *task) -{ - (void)hal; - (void)task; - return MPP_OK; -} - -MPP_RET hal_dummy_dec_reset(void *hal) -{ - (void)hal; - return MPP_OK; -} - -MPP_RET hal_dummy_dec_flush(void *hal) -{ - (void)hal; - return MPP_OK; -} - -MPP_RET hal_dummy_dec_control(void *hal, RK_S32 cmd_type, void *param) -{ - (void)hal; - (void)cmd_type; - (void)param; - return MPP_OK; -} - -const MppHalApi hal_api_dummy_dec = { - "dummy_hw_dec", - MPP_CTX_DEC, - MPP_VIDEO_CodingUnused, - 0, - 0, - hal_dummy_dec_init, - hal_dummy_dec_deinit, - hal_dummy_dec_gen_regs, - hal_dummy_dec_start, - hal_dummy_dec_wait, - hal_dummy_dec_reset, - hal_dummy_dec_flush, - hal_dummy_dec_control, -}; - diff --git a/mpp/hal/dummy/hal_dummy_enc_api.c b/mpp/hal/dummy/hal_dummy_enc_api.c deleted file mode 100644 index 12a423a0f..000000000 --- a/mpp/hal/dummy/hal_dummy_enc_api.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#define MODULE_TAG "hal_dummy_enc" - -#include "hal_dummy_enc_api.h" - - -MPP_RET hal_dummy_enc_init(void *hal, MppHalCfg *cfg) -{ - (void)hal; - (void)cfg; - return MPP_OK; -} - -MPP_RET hal_dummy_enc_deinit(void *hal) -{ - (void)hal; - return MPP_OK; -} - -MPP_RET hal_dummy_enc_gen_regs(void *hal, HalTask *task) -{ - (void)hal; - (void)task; - return MPP_OK; -} -MPP_RET hal_dummy_enc_start(void *hal, HalTask *task) -{ - (void)hal; - (void)task; - return MPP_OK; -} - -MPP_RET hal_dummy_enc_wait(void *hal, HalTask *task) -{ - (void)hal; - (void)task; - return MPP_OK; -} - -MPP_RET hal_dummy_enc_reset(void *hal) -{ - (void)hal; - return MPP_OK; -} - -MPP_RET hal_dummy_enc_flush(void *hal) -{ - (void)hal; - return MPP_OK; -} - -MPP_RET hal_dummy_enc_control(void *hal, RK_S32 cmd_type, void *param) -{ - (void)hal; - (void)cmd_type; - (void)param; - return MPP_OK; -} - -const MppHalApi hal_api_dummy_enc = { - "dummy_hw_enc", - MPP_CTX_ENC, - MPP_VIDEO_CodingUnused, - 0, - 0, - hal_dummy_enc_init, - hal_dummy_enc_deinit, - hal_dummy_enc_gen_regs, - hal_dummy_enc_start, - hal_dummy_enc_wait, - hal_dummy_enc_reset, - hal_dummy_enc_flush, - hal_dummy_enc_control, -}; - diff --git a/mpp/hal/hal_task.c b/mpp/hal/hal_task.c new file mode 100644 index 000000000..12f5f7366 --- /dev/null +++ b/mpp/hal/hal_task.c @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_task" + +#include + +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_lock.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "hal_task.h" + +typedef struct HalTaskImpl_t HalTaskImpl; +typedef struct HalTaskGroupImpl_t HalTaskGroupImpl; + +struct HalTaskImpl_t { + struct list_head list; + HalTaskGroupImpl *group; + RK_S32 index; + RK_S32 status; + void *data; +}; + +struct HalTaskGroupImpl_t { + RK_S32 stage_count; + RK_S32 task_count; + + spinlock_t lock; + + RK_S32 size; + RK_S32 aligned_size; + + struct list_head *list; + RK_U32 *count; + HalTaskImpl *tasks; +}; + +MPP_RET hal_task_group_init(HalTaskGroup *group, RK_S32 stage_cnt, RK_S32 task_cnt, RK_S32 task_size) +{ + if (NULL == group || stage_cnt < 0 || task_cnt < 0 || task_size < 0) { + mpp_err_f("found invalid input group %p stage %d task %d size %d\n", + group, stage_cnt, task_cnt, task_size); + return MPP_ERR_UNKNOW; + } + + HalTaskGroupImpl *p = NULL; + RK_S32 aligned_size = MPP_ALIGN(task_size, sizeof(void *)); + + do { + RK_U8 *buf = NULL; + RK_S32 i; + + p = mpp_calloc_size(HalTaskGroupImpl, sizeof(HalTaskGroupImpl) + + (sizeof(HalTaskImpl) + aligned_size) * task_cnt + + (sizeof(struct list_head)) * stage_cnt + + (sizeof(RK_U32)) * stage_cnt); + if (NULL == p) { + mpp_err_f("malloc group failed\n"); + break; + } + + p->stage_count = stage_cnt; + p->task_count = task_cnt; + p->size = task_size; + p->aligned_size = aligned_size; + p->list = (struct list_head *)((HalTaskImpl *)(p + 1)); + p->count = (RK_U32 *)(p->list + stage_cnt); + p->tasks = (HalTaskImpl *)(p->count + stage_cnt); + + mpp_spinlock_init(&p->lock); + + for (i = 0; i < stage_cnt; i++) + INIT_LIST_HEAD(&p->list[i]); + + buf = (RK_U8 *)(p->tasks + task_cnt); + + for (i = 0; i < task_cnt; i++) { + HalTaskImpl *task = &p->tasks[i]; + + INIT_LIST_HEAD(&task->list); + task->index = i; + task->group = p; + task->status = TASK_IDLE; + task->data = buf + i * aligned_size; + list_add_tail(&task->list, &p->list[TASK_IDLE]); + p->count[TASK_IDLE]++; + } + *group = p; + return MPP_OK; + } while (0); + + MPP_FREE(p); + + *group = NULL; + return MPP_NOK; +} + +MPP_RET hal_task_group_deinit(HalTaskGroup group) +{ + MPP_FREE(group); + return MPP_OK; +} + +MPP_RET hal_task_get_hnd(HalTaskGroup group, RK_S32 status, HalTaskHnd *hnd) +{ + if (NULL == group || status >= TASK_BUTT || NULL == hnd) { + mpp_err_f("found invaid input group %p status %d hnd %p\n", group, status, hnd); + return MPP_ERR_UNKNOW; + } + + *hnd = NULL; + HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; + struct list_head *list = &p->list[status]; + + mpp_spinlock_lock(&p->lock); + if (list_empty(list)) { + mpp_spinlock_unlock(&p->lock); + return MPP_NOK; + } + + HalTaskImpl *task = list_entry(list->next, HalTaskImpl, list); + mpp_assert(task->status == status); + *hnd = task; + mpp_spinlock_unlock(&p->lock); + return MPP_OK; +} + +MPP_RET hal_task_check_empty(HalTaskGroup group, RK_S32 status) +{ + if (NULL == group || status >= TASK_BUTT) { + mpp_err_f("found invaid input group %p status %d \n", group, status); + return MPP_ERR_UNKNOW; + } + + HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; + struct list_head *list = &p->list[status]; + MPP_RET ret; + + mpp_spinlock_lock(&p->lock); + ret = list_empty(list) ? MPP_OK : MPP_NOK; + mpp_spinlock_unlock(&p->lock); + + return ret; +} + +RK_S32 hal_task_get_count(HalTaskGroup group, RK_S32 status) +{ + if (NULL == group || status >= TASK_BUTT) { + mpp_err_f("found invaid input group %p status %d\n", group, status); + return -1; + } + + HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; + RK_S32 count; + + mpp_spinlock_lock(&p->lock); + count = p->count[status]; + mpp_spinlock_unlock(&p->lock); + + return count; +} + +MPP_RET hal_task_hnd_set_status(HalTaskHnd hnd, RK_S32 status) +{ + if (NULL == hnd || status >= TASK_BUTT) { + mpp_err_f("found invaid input hnd %p status %d\n", hnd, status); + return MPP_ERR_UNKNOW; + } + + HalTaskImpl *impl = (HalTaskImpl *)hnd; + HalTaskGroupImpl *group = impl->group; + + mpp_assert(group); + mpp_assert(impl->index < group->task_count); + + mpp_spinlock_lock(&group->lock); + list_del_init(&impl->list); + list_add_tail(&impl->list, &group->list[status]); + group->count[impl->status]--; + group->count[status]++; + impl->status = status; + mpp_spinlock_unlock(&group->lock); + + return MPP_OK; +} + +MPP_RET hal_task_hnd_set_info(HalTaskHnd hnd, void *info) +{ + if (NULL == hnd || NULL == info) { + mpp_err_f("found invaid input hnd %p info %p\n", hnd, info); + return MPP_ERR_UNKNOW; + } + + HalTaskImpl *impl = (HalTaskImpl *)hnd; + HalTaskGroupImpl *group = impl->group; + + mpp_assert(impl->index < group->task_count); + + mpp_spinlock_lock(&group->lock); + memcpy(impl->data, info, group->size); + mpp_spinlock_unlock(&group->lock); + + return MPP_OK; +} + +MPP_RET hal_task_hnd_get_info(HalTaskHnd hnd, void *info) +{ + if (NULL == hnd || NULL == info) { + mpp_err_f("found invaid input hnd %p info %p\n", hnd, info); + return MPP_ERR_UNKNOW; + } + + HalTaskImpl *impl = (HalTaskImpl *)hnd; + HalTaskGroupImpl *group = impl->group; + + mpp_assert(impl->index < group->task_count); + + mpp_spinlock_lock(&group->lock); + memcpy(info, impl->data, group->size); + mpp_spinlock_unlock(&group->lock); + + return MPP_OK; +} + +void *hal_task_hnd_get_data(HalTaskHnd hnd) +{ + if (NULL == hnd) { + mpp_err_f("found invaid input hnd %p\n", hnd); + return NULL; + } + + HalTaskImpl *impl = (HalTaskImpl *)hnd; + HalTaskGroupImpl *group = impl->group; + + mpp_assert(impl->index < group->task_count); + + return impl->data; +} diff --git a/mpp/hal/hal_task.cpp b/mpp/hal/hal_task.cpp deleted file mode 100644 index 489884ac6..000000000 --- a/mpp/hal/hal_task.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#define MODULE_TAG "hal_task" - -#include - -#include "mpp_mem.h" -#include "mpp_log.h" -#include "mpp_list.h" - -#include "hal_task.h" - -typedef struct HalTaskImpl_t HalTaskImpl; -typedef struct HalTaskGroupImpl_t HalTaskGroupImpl; - -struct HalTaskImpl_t { - RK_U32 index; - HalTask task; -}; - -struct HalTaskGroupImpl_t { - RK_U32 count_put; - RK_U32 count_get; - MppCtxType type; - RK_S32 count; - mpp_list *tasks; -}; - -MPP_RET hal_task_group_init(HalTaskGroup *group, MppCtxType type, RK_U32 count) -{ - if (NULL == group || 0 == count) { - mpp_err_f("found invalid input group %p count %d\n", group, count); - return MPP_ERR_UNKNOW; - } - - *group = NULL; - HalTaskGroupImpl *p = mpp_malloc(HalTaskGroupImpl, 1); - if (NULL == p) { - mpp_err_f("malloc group failed\n"); - return MPP_NOK; - } - p->tasks = new mpp_list(NULL); - if (NULL == p->tasks) { - mpp_err_f("malloc task list failed\n"); - mpp_free(p); - return MPP_NOK; - } - p->type = type; - p->count = count - 1; - p->count_put = p->count_get = 0; - *group = p; - return MPP_OK; -} - -MPP_RET hal_task_group_deinit(HalTaskGroup group) -{ - if (NULL == group) { - mpp_err_f("found NULL input group\n"); - return MPP_ERR_NULL_PTR; - } - - HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; - if (p->tasks) - delete p->tasks; - mpp_free(p); - return MPP_OK; -} - -MPP_RET hal_task_can_put(HalTaskGroup group) -{ - if (NULL == group) { - mpp_err_f("found NULL input group\n"); - return MPP_ERR_NULL_PTR; - } - - HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; - mpp_list *tasks = p->tasks; - Mutex::Autolock auto_lock(tasks->mutex()); - return (tasks->list_size() < p->count) ? (MPP_OK) : (MPP_NOK); -} - -MPP_RET hal_task_can_get(HalTaskGroup group) -{ - if (NULL == group) { - mpp_err_f("found NULL input group\n"); - return MPP_ERR_NULL_PTR; - } - - HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; - mpp_list *tasks = p->tasks; - Mutex::Autolock auto_lock(tasks->mutex()); - return (tasks->list_size()) ? (MPP_OK) : (MPP_NOK); -} - -MPP_RET hal_task_init(HalTask *task, MppCtxType type) -{ - if (NULL == task || type >= MPP_CTX_BUTT) { - mpp_err_f("found invalid input task %p type %d\n", task, type); - return MPP_ERR_UNKNOW; - } - if (MPP_CTX_DEC == type) { - task->dec.valid = 0; - task->dec.output = -1; - memset(&task->dec.syntax, 0, sizeof(task->dec.syntax)); - memset(task->dec.refer, -1, sizeof(task->dec.refer)); - } else { - memset(&task->enc, 0, sizeof(task->enc)); - } - return MPP_OK; -} - -MPP_RET hal_task_put(HalTaskGroup group, HalTask *task) -{ - MPP_RET ret = hal_task_can_put(group); - mpp_assert(ret == MPP_OK); - - HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; - mpp_list *tasks = p->tasks; - Mutex::Autolock auto_lock(tasks->mutex()); - tasks->add_at_tail(task, sizeof(*task)); - p->count_put++; - return MPP_OK; -} - -MPP_RET hal_task_get(HalTaskGroup group, HalTask *task) -{ - MPP_RET ret = hal_task_can_get(group); - mpp_assert(ret == MPP_OK); - - HalTaskGroupImpl *p = (HalTaskGroupImpl *)group; - mpp_list *tasks = p->tasks; - Mutex::Autolock auto_lock(tasks->mutex()); - tasks->del_at_head(task, sizeof(*task)); - p->count_get++; - return MPP_OK; -} - diff --git a/mpp/hal/inc/hal_dec_task.h b/mpp/hal/inc/hal_dec_task.h new file mode 100644 index 000000000..3d7d3b7f3 --- /dev/null +++ b/mpp/hal/inc/hal_dec_task.h @@ -0,0 +1,119 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef HAL_DEC_TASK_H +#define HAL_DEC_TASK_H + +#include "hal_task.h" +#include "mpp_callback.h" + +#define MAX_DEC_REF_NUM 17 + +/* + * modified by parser and encoder + * + * number : the number of the data pointer array element + * data : the address of the pointer array, parser will add its data here + */ +typedef struct MppSyntax_t { + RK_U32 number; + void *data; +} MppSyntax; + +typedef union HalDecTaskFlag_t { + RK_U64 val; + struct { + RK_U32 eos : 1; + RK_U32 info_change : 1; + + /* + * Different error flags for task + * + * parse_err : + * When set it means fatal error happened at parsing stage + * This task should not enable hardware just output a empty frame with + * error flag. + * + * ref_err : + * When set it means current task is ok but it contains reference frame + * with error which will introduce error pixels to this frame. + * + * used_for_ref : + * When set it means this output frame will be used as reference frame + * for further decoding. When there is error on decoding this frame + * if used_for_ref is set then the frame will set errinfo flag + * if used_for_ref is cleared then the frame will set discard flag. + */ + RK_U32 parse_err : 1; + RK_U32 ref_err : 1; + RK_U32 used_for_ref : 1; + + RK_U32 wait_done : 1; + RK_U32 reserved0 : 1; + RK_U32 ref_info_valid : 1; + RK_U32 ref_miss : 16; + RK_U32 ref_used : 16; + }; +} HalDecTaskFlag; + +typedef struct HalDecTask_t { + // set by parser to signal that it is valid + RK_U32 valid; + HalDecTaskFlag flags; + + // current tesk protocol syntax information + MppSyntax syntax; + + // packet need to be copied to hardware buffer + // parser will create this packet and mpp_dec will copy it to hardware bufffer + MppPacket input_packet; + RK_S32 input_no_copy; + + // current task input slot index + RK_S32 input; + + RK_S32 reg_index; + // for test purpose + // current tesk output slot index + RK_S32 output; + + // current task reference slot index, -1 for unused + RK_S32 refer[MAX_DEC_REF_NUM]; +} HalDecTask; + +typedef union HalDecVprocTaskFlag_t { + RK_U32 val; + + struct { + RK_U32 eos : 1; + RK_U32 info_change : 1; + }; +} HalDecVprocTaskFlag; + +typedef struct HalDecVprocTask_t { + // input slot index for post-process + HalDecVprocTaskFlag flags; + + RK_S32 input; +} HalDecVprocTask; + +typedef union HalTask_u { + HalDecTask dec; + HalDecVprocTask dec_vproc; +} HalTaskInfo; + +#endif /* HAL_DEC_TASK_H */ diff --git a/mpp/hal/inc/hal_dummy_enc_api.h b/mpp/hal/inc/hal_dummy_enc_api.h index 19be92e48..824e8e6a1 100644 --- a/mpp/hal/inc/hal_dummy_enc_api.h +++ b/mpp/hal/inc/hal_dummy_enc_api.h @@ -1,34 +1,34 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#ifndef __HAL_DUMMY_ENC_API_H__ -#define __HAL_DUMMY_ENC_API_H__ - -#include "mpp_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern const MppHalApi hal_api_dummy_enc; - -#ifdef __cplusplus -} -#endif - -#endif /*__HAL_DUMMY_ENC_API_H__*/ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef HAL_DUMMY_ENC_API_H +#define HAL_DUMMY_ENC_API_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_api_dummy_enc; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_DUMMY_ENC_API_H */ diff --git a/mpp/hal/inc/hal_enc_task.h b/mpp/hal/inc/hal_enc_task.h new file mode 100644 index 000000000..69c0658d0 --- /dev/null +++ b/mpp/hal/inc/hal_enc_task.h @@ -0,0 +1,156 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef HAL_ENC_TASK_H +#define HAL_ENC_TASK_H + +#include "mpp_time.h" + +#include "hal_task.h" +#include "mpp_rc_defs.h" +#include "mpp_enc_refs.h" + +#define HAL_ENC_TASK_ERR_INIT 0x00000001 +#define HAL_ENC_TASK_ERR_ALLOC 0x00000010 +#define HAL_ENC_TASK_ERR_EXTRAINFO 0x00000100 +#define HAL_ENC_TASK_ERR_GENREG 0x00001000 +#define HAL_ENC_TASK_ERR_START 0x00010000 +#define HAL_ENC_TASK_ERR_WAIT 0x00100000 + +typedef struct HalEncTaskFlag_t { + RK_U32 err; + RK_S32 drop_by_fps; + RK_S32 reg_idx; + /* hal buf index */ + RK_S32 curr_idx; + RK_S32 refr_idx; +} HalEncTaskFlag; + +typedef struct MppSyntax_t { + RK_U32 number; + void *data; +} MppSyntax; + +typedef struct HalEncTask_t { + RK_U32 valid; + + // rate control data channel + EncRcTask *rc_task; + + // cpb reference force config + MppEncRefFrmUsrCfg *frm_cfg; + + // current tesk protocol syntax information + MppSyntax syntax; + MppSyntax hal_ret; + + /* + * Current tesk output stream buffer + * + * Usage and flow of changing task length and packet length + * + * 1. length is runtime updated for each stage. + * header_length / sei_length / hw_length are for recording. + * + * 2. When writing vps/sps/pps encoder should update length. + * Then length will be kept before next stage is done. + * For example when vps/sps/pps were inserted and slice data need + * reencoding the hal should update length at the final loop. + * + * 3. length in task and length in packet should be updated at the same + * time. Encoder flow need to check these two length between stages. + */ + MppPacket packet; + MppBuffer output; + RK_S32 header_length; + RK_S32 sei_length; + RK_S32 hw_length; + RK_U32 length; + /* For reenc process and record segment number before hardware encoding */ + RK_U32 segment_nb; + + // current tesk input slot buffer + MppFrame frame; + MppBuffer input; + + // task stopwatch for timing + MppStopwatch stopwatch; + + // current md info output buffer + MppBuffer md_info; + + // low delay mode part output information + RK_U32 part_first; + RK_U32 part_last; + RK_U32 part_count; + RK_U8 *part_pos; + size_t part_length; + + HalEncTaskFlag flags; +} HalEncTask; + +/* encoder internal work flow */ +typedef union EncAsyncStatus_u { + RK_U32 val; + struct { + RK_U32 task_hnd_rdy : 1; + RK_U32 task_in_rdy : 1; + RK_U32 task_out_rdy : 1; + + RK_U32 frm_pkt_rdy : 1; + + RK_U32 hal_task_reset_rdy : 1; // reset hal task to start + RK_U32 rc_check_frm_drop : 1; // rc stage + RK_U32 check_frm_pskip : 1; // pskip frame check + RK_U32 pkt_buf_rdy : 1; // prepare pkt buf + + RK_U32 enc_start : 1; // enc stage + RK_U32 refs_force_update : 1; // enc stage + RK_U32 low_delay_again : 1; // enc stage low delay output again + + RK_U32 enc_backup : 1; // enc stage + RK_U32 enc_restore : 1; // reenc flow start point + RK_U32 enc_proc_dpb : 1; // enc stage + RK_U32 rc_frm_start : 1; // rc stage + RK_U32 check_type_reenc : 1; // flow checkpoint if reenc -> enc_restore + RK_U32 enc_proc_hal : 1; // enc stage + RK_U32 hal_get_task : 1; // hal stage + RK_U32 rc_hal_start : 1; // rc stage + RK_U32 hal_gen_reg : 1; // hal stage + RK_U32 hal_start : 1; // hal stage + RK_U32 hal_wait : 1; // hal stage NOTE: special in low delay mode + RK_U32 rc_hal_end : 1; // rc stage + RK_U32 hal_ret_task : 1; // hal stage + RK_U32 enc_update_hal : 1; // enc stage + RK_U32 rc_frm_end : 1; // rc stage + RK_U32 check_rc_reenc : 1; // flow checkpoint if reenc -> enc_restore + RK_U32 enc_done : 1; // done stage + RK_U32 slice_out_done : 1; + }; +} EncAsyncStatus; + +typedef struct EncAsyncTaskInfo_t { + RK_S32 seq_idx; + EncAsyncStatus status; + RK_S64 pts; + + HalEncTask task; + EncRcTask rc; + MppEncRefFrmUsrCfg usr; +} EncAsyncTaskInfo; + +#endif /* HAL_ENC_TASK_H */ diff --git a/mpp/hal/inc/hal_h264d_api.h b/mpp/hal/inc/hal_h264d_api.h deleted file mode 100644 index 6cde13b6b..000000000 --- a/mpp/hal/inc/hal_h264d_api.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#ifndef __HAL_H264D_API_H__ -#define __HAL_H264D_API_H__ - -#include "rk_type.h" -#include "mpp_err.h" -#include "mpp_hal.h" - - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const MppHalApi hal_api_h264d; - -MPP_RET hal_h264d_init (void *hal, MppHalCfg *cfg); -MPP_RET hal_h264d_deinit (void *hal); -MPP_RET hal_h264d_gen_regs(void *hal, HalTask *task); -MPP_RET hal_h264d_start (void *hal, HalTask *task); -MPP_RET hal_h264d_wait (void *hal, HalTask *task); -MPP_RET hal_h264d_reset (void *hal); -MPP_RET hal_h264d_flush (void *hal); -MPP_RET hal_h264d_control (void *hal, RK_S32 cmd_type, void *param); - -#ifdef __cplusplus -} -#endif - -#endif /*__HAL_H264D_API_H__*/ diff --git a/mpp/hal/inc/hal_hw_id.h b/mpp/hal/inc/hal_hw_id.h new file mode 100644 index 000000000..42823e488 --- /dev/null +++ b/mpp/hal/inc/hal_hw_id.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_HW_ID_H +#define HAL_HW_ID_H + +/* decoder */ +#define HWID_VDPU345 (0xdbdc0701) +#define HWID_VDPU34X (0x032a3f03) +#define HWID_VDPU38X (0x53813f05) +#define HWID_VDPU382_RK3528 (0x70393f05) +#define HWID_VDPU382_RK3562 (0x72bb0f01) +#define HWID_VDPU383 (0x38321746) +#define HWID_VDPU384A (0x38436021) +#define HWID_VDPU384B_RK3572 (0x384bbfb4) +#define HWID_VDPU384B_RK3538 (0x384bbfb3) + +/* encoder */ +#define HWID_VEPU58X (0x50603312) +#define HWID_VEPU540C (0x50603313) +#define HWID_VEPU510 (0x506f2314) +#define HWID_VEPU511 (0x50602715) +#define HWID_VEPU511A (0x506f3316) + +/* jpeg */ +#define HWID_JPEGE_VPU730 (0x73010000) + +#endif /* HAL_HW_ID_H */ \ No newline at end of file diff --git a/mpp/hal/inc/hal_task.h b/mpp/hal/inc/hal_task.h index 1abd7305e..f97d3e746 100644 --- a/mpp/hal/inc/hal_task.h +++ b/mpp/hal/inc/hal_task.h @@ -1,146 +1,81 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __HAL_TASK__ -#define __HAL_TASK__ - -#include "rk_mpi.h" - -#define MAX_DEC_REF_NUM 17 - -/* - * modified by parser - * - * number : the number of the data pointer array element - * data : the address of the pointer array, parser will add its data here - */ -typedef struct MppSyntax_t { - RK_U32 number; - void *data; -} MppSyntax; - -/* - * HalTask memory layout: - * - * +----^----+ +----------------------+ +----^----+ - * | | context type | | - * | +----------------------+ | - * + | coding type | | - * header +----------------------+ | - * + | size | | - * | +----------------------+ | - * | | pointer count | | - * +----v----+ +----------------------+ | - * | | | - * | pointers | | - * | | + - * +----------------------+ size - * | | + - * | data_0 | | - * | | | - * +----------------------+ | - * | | | - * | data_1 | | - * | | | - * +----------------------+ | - * | | | - * | | | - * | data_2 | | - * | | | - * | | | - * +----------------------+ +----v----+ - */ -typedef struct HalDecTask_t { - // set by parser to signal that it is valid - RK_U32 valid; - - // current tesk protocol syntax information - MppSyntax syntax; - - // for test purpose - // current tesk output slot index - RK_S32 output; - // current task reference slot index, -1 for unused - RK_S32 refer[MAX_DEC_REF_NUM]; -} HalDecTask; - -typedef struct HalEncTask_t { - RK_U32 valid; - - // current tesk protocol syntax information - MppSyntax syntax; - - // current tesk output stream buffer index - RK_S32 output; - - // current tesk input slot buffer index - RK_S32 input; - // current task reference index, -1 for unused - RK_S32 refer; - // current task recon index - RK_S32 recon; -} HalEncTask; - -typedef union HalTask_u { - HalDecTask dec; - HalEncTask enc; -} HalTask; - -typedef void* HalTaskHnd; -typedef void* HalTaskGroup; - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * group init / deinit will be called by hal - * - * NOTE: use mpp_list to implement - * the count means the max task waiting for process - */ -MPP_RET hal_task_group_init(HalTaskGroup *group, MppCtxType type, RK_U32 count); -MPP_RET hal_task_group_deinit(HalTaskGroup group); - -/* - * normal working flow: - * - * dec: - * - * hal_task_can_put(group) - dec test whether can send task to hal - * parser->parse(task) - parser write a local task - * hal_task_put(group, task) - dec send the task to hal - * - * hal: - * - * hal_task_can_get(group) - hal test whether there is task waiting for process - * hal_task_get(group, task) - hal get the task to process - * - */ -MPP_RET hal_task_can_put(HalTaskGroup group); -MPP_RET hal_task_can_get(HalTaskGroup group); - -MPP_RET hal_task_init(HalTask *task, MppCtxType type); -MPP_RET hal_task_put(HalTaskGroup group, HalTask *task); -MPP_RET hal_task_get(HalTaskGroup group, HalTask *task); - -#ifdef __cplusplus -} -#endif - -#endif /*__HAL_TASK__*/ - +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_TASK_H +#define HAL_TASK_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef enum HalTaskStatus_e { + TASK_IDLE, + TASK_PROCESSING, + TASK_PROC_DONE, + TASK_BUTT, +} HalTaskStatus; + +typedef void* HalTaskHnd; +typedef void* HalTaskGroup; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * group init / deinit will be called by hal + * HalTaskGroup is a group of task list with status + */ +MPP_RET hal_task_group_init(HalTaskGroup *group, RK_S32 stage_cnt, + RK_S32 task_cnt, RK_S32 task_size); +MPP_RET hal_task_group_deinit(HalTaskGroup group); + +/* + * normal working flow: + * + * dec: + * + * - codec + * hal_task_get_hnd(group, idle, hnd) - dec try get idle task to work + * hal_task_hnd_set_status(hnd, prepare) - dec prepare the task + * codec prepare task + * hal_task_hnd_set_status(hnd, wait_proc) - dec send the task to hardware queue + * + * - hal + * hal_task_get_hnd(group, wait_proc, hnd) - hal get task on wait_proc status + * hal start task + * hal_task_set_hnd(hnd, processing) - hal send task to hardware for process + * hal wait task done + * hal_task_set_hnd(hnd, proc_done) - hal mark task is finished + * + * - codec + * hal_task_get_hnd(group, task_done, hnd) - codec query the previous finished task + * codec do error process on task + * hal_task_set_hnd(hnd, idle) - codec mark task is idle + * + */ +MPP_RET hal_task_get_hnd(HalTaskGroup group, RK_S32 status, HalTaskHnd *hnd); +RK_S32 hal_task_get_count(HalTaskGroup group, RK_S32 status); +MPP_RET hal_task_hnd_set_status(HalTaskHnd hnd, RK_S32 status); +MPP_RET hal_task_hnd_set_info(HalTaskHnd hnd, void *task); +MPP_RET hal_task_hnd_get_info(HalTaskHnd hnd, void *task); +void *hal_task_hnd_get_data(HalTaskHnd hnd); +MPP_RET hal_task_check_empty(HalTaskGroup group, RK_S32 status); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_TASK_H */ diff --git a/mpp/hal/inc/mpp_enc_hal.h b/mpp/hal/inc/mpp_enc_hal.h new file mode 100644 index 000000000..b3a1a7a96 --- /dev/null +++ b/mpp/hal/inc/mpp_enc_hal.h @@ -0,0 +1,107 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_ENC_HAL_H +#define MPP_ENC_HAL_H + +#include "mpp_soc.h" +#include "mpp_device.h" +#include "hal_enc_task.h" +#include "mpp_enc_cfg.h" +#include "mpp_singleton.h" + +typedef struct MppEncHalCfg_t { + // input for encoder + MppCodingType coding; + MppEncCfgSet *cfg; + MppCbCtx *output_cb; + RK_S32 task_cnt; + + // output from enc_impl + MppClientType type; + MppDev dev; + RK_S32 cap_recn_out; + HalTaskGroup tasks; +} MppEncHalCfg; + +typedef struct MppEncHalApi_t { + char *name; + MppCodingType coding; + RK_U32 ctx_size; + RK_U32 flag; + + MPP_RET (*init)(void *ctx, MppEncHalCfg *cfg); + MPP_RET (*deinit)(void *ctx); + + // prepare function after encoder config is set + MPP_RET (*prepare)(void *ctx); + + // configure function + MPP_RET (*get_task)(void *ctx, HalEncTask *task); + MPP_RET (*gen_regs)(void *ctx, HalEncTask *task); + + // hw operation function + MPP_RET (*start)(void *ctx, HalEncTask *task); + MPP_RET (*wait)(void *ctx, HalEncTask *task); + MPP_RET (*part_start)(void *ctx, HalEncTask *task); + MPP_RET (*part_wait)(void *ctx, HalEncTask *task); + + // return function + MPP_RET (*ret_task)(void *ctx, HalEncTask *task); + + MppClientType client; + RockchipSocType soc_type[]; +} MppEncHalApi; + +typedef void* MppEncHal; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_enc_hal_api_register(const MppEncHalApi *api); + +MPP_RET mpp_enc_hal_init(MppEncHal *ctx, MppEncHalCfg *cfg); +MPP_RET mpp_enc_hal_deinit(MppEncHal ctx); + +/* prepare after cfg */ +MPP_RET mpp_enc_hal_prepare(MppEncHal ctx); + +MPP_RET mpp_enc_hal_get_task(MppEncHal ctx, HalEncTask *task); +MPP_RET mpp_enc_hal_gen_regs(MppEncHal ctx, HalEncTask *task); + +// start / wait hardware +MPP_RET mpp_enc_hal_start(MppEncHal ctx, HalEncTask *task); +MPP_RET mpp_enc_hal_wait(MppEncHal ctx, HalEncTask *task); +MPP_RET mpp_enc_hal_part_start(MppEncHal ctx, HalEncTask *task); +MPP_RET mpp_enc_hal_part_wait(MppEncHal ctx, HalEncTask *task); + +MPP_RET mpp_enc_hal_ret_task(MppEncHal ctx, HalEncTask *task); + +MPP_RET mpp_enc_hal_check_part_mode(MppEncHal ctx); + +#define MPP_ENC_HAL_API_REGISTER(api) \ + static void register_##api(void) \ + { \ + mpp_enc_hal_api_register(&api); \ + } \ + MPP_MODULE_ADD(api, register_##api, NULL); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENC_HAL_H */ diff --git a/mpp/hal/inc/mpp_hal.h b/mpp/hal/inc/mpp_hal.h index 0985a57c2..924531231 100644 --- a/mpp/hal/inc/mpp_hal.h +++ b/mpp/hal/inc/mpp_hal.h @@ -1,88 +1,113 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_HAL_H__ -#define __MPP_HAL_H__ - -#include "rk_mpi.h" -#include "hal_task.h" -#include "mpp_buf_slot.h" - -typedef enum MppHalType_e { - HAL_MODE_LIBVPU, - HAL_MODE_V4L2, - HAL_MODE_BUTT, -} HalWorkMode; - -typedef void* MppHalCtx; - -typedef struct MppHalCfg_t { - // input - MppCtxType type; - MppCodingType coding; - HalWorkMode mode; - MppBufSlots slots; - - // output - HalTaskGroup tasks; - RK_U32 task_count; -} MppHalCfg; - -typedef struct MppHalApi_t { - char *name; - MppCtxType type; - MppCodingType coding; - RK_U32 ctx_size; - RK_U32 flag; - - MPP_RET (*init)(void *ctx, MppHalCfg *cfg); - MPP_RET (*deinit)(void *ctx); - - // task preprocess function - MPP_RET (*reg_gen)(void *ctx, HalTask *syn); - - // hw operation function - MPP_RET (*start)(void *ctx, HalTask *task); - MPP_RET (*wait)(void *ctx, HalTask *task); - - MPP_RET (*reset)(void *ctx); - MPP_RET (*flush)(void *ctx); - MPP_RET (*control)(void *ctx, RK_S32 cmd, void *param); -} MppHalApi; - -typedef void* MppHal; - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET mpp_hal_init(MppHal *ctx, MppHalCfg *cfg); -MPP_RET mpp_hal_deinit(MppHal ctx); - -MPP_RET mpp_hal_reg_gen(MppHal ctx, HalTask *task); -MPP_RET mpp_hal_hw_start(MppHal ctx, HalTask *task); -MPP_RET mpp_hal_hw_wait(MppHal ctx, HalTask *task); - -MPP_RET mpp_hal_reset(MppHal ctx); -MPP_RET mpp_hal_flush(MppHal ctx); -MPP_RET mpp_hal_control(MppHal ctx, RK_S32 cmd, void *param); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_HAL_H__*/ - +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_HAL_H +#define MPP_HAL_H + +#include "rk_mpi_cmd.h" + +#include "mpp_buf_slot.h" +#include "mpp_platform.h" +#include "mpp_soc.h" +#include "mpp_singleton.h" + +#include "hal_dec_task.h" +#include "mpp_dec_cfg.h" +#include "mpp_device.h" + +typedef enum VpuHwMode_e { + MODE_NULL = 0, + RKVDEC_MODE = 0x01, + VDPU1_MODE = 0x02, + VDPU2_MODE = 0x04, + RKVENC_MODE = 0x05, + MODE_BUTT, +} VpuHwMode; + +typedef struct MppHalCfg_t { + // input + MppCtxType type; + MppCodingType coding; + MppBufSlots frame_slots; + MppBufSlots packet_slots; + MppDecCfgSet *cfg; + MppCbCtx *dec_cb; + + // output from hardware module + const MppDecHwCap *hw_info; + // codec dev + MppDev dev; + RK_S32 support_fast_mode; + SlotHalFbcAdjCfg *hal_fbc_adj_cfg; + MppBufferGroup buf_group; +} MppHalCfg; + +typedef struct MppHalApi_t { + char *name; + MppCtxType type; + MppCodingType coding; + RK_U32 ctx_size; + RK_U32 flag; + + MPP_RET (*init)(void *ctx, MppHalCfg *cfg); + MPP_RET (*deinit)(void *ctx); + + // task preprocess function + MPP_RET (*reg_gen)(void *ctx, HalTaskInfo *syn); + + // hw operation function + MPP_RET (*start)(void *ctx, HalTaskInfo *task); + MPP_RET (*wait)(void *ctx, HalTaskInfo *task); + + MPP_RET (*reset)(void *ctx); + MPP_RET (*flush)(void *ctx); + MPP_RET (*control)(void *ctx, MpiCmd cmd, void *param); + + MppClientType client; + RockchipSocType soc_type[]; +} MppHalApi; + +typedef void* MppHal; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_hal_init(MppHal *ctx, MppHalCfg *cfg); +MPP_RET mpp_hal_deinit(MppHal ctx); + +MPP_RET mpp_hal_reg_gen(MppHal ctx, HalTaskInfo *task); +MPP_RET mpp_hal_hw_start(MppHal ctx, HalTaskInfo *task); +MPP_RET mpp_hal_hw_wait(MppHal ctx, HalTaskInfo *task); + +MPP_RET mpp_hal_reset(MppHal ctx); +MPP_RET mpp_hal_flush(MppHal ctx); +MPP_RET mpp_hal_control(MppHal ctx, MpiCmd cmd, void *param); + +MPP_RET mpp_hal_api_register(const MppHalApi *api); + +#define MPP_DEC_HAL_API_REGISTER(api) \ + static void register_##api(void) \ + { \ + mpp_hal_api_register(&api); \ + } \ + MPP_MODULE_ADD(api, register_##api, NULL); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_HAL_H */ diff --git a/mpp/hal/mpp_enc_hal.c b/mpp/hal/mpp_enc_hal.c new file mode 100644 index 000000000..56e36f18b --- /dev/null +++ b/mpp/hal/mpp_enc_hal.c @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_enc_hal" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_common.h" + +#include "mpp.h" +#include "mpp_soc.h" +#include "mpp_platform.h" +#include "mpp_enc_hal.h" +#include "mpp_frame_impl.h" + +#define ENC_HAL_DBG_FLOW (0x00000001) +#define ENC_HAL_DBG_API (0x00000002) + +#define enc_hal_dbg(flag, fmt, ...) mpp_dbg(mpp_enc_hal_debug, flag, fmt, ## __VA_ARGS__) +#define enc_hal_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_enc_hal_debug, flag, fmt, ## __VA_ARGS__) + +#define enc_hal_dbg_flow(fmt, ...) enc_hal_dbg_f(ENC_HAL_DBG_FLOW, fmt, ## __VA_ARGS__) +#define enc_hal_dbg_api(fmt, ...) enc_hal_dbg(ENC_HAL_DBG_API, fmt, ## __VA_ARGS__) + +#define TRY_GET_ENC_HAL_API(client_type) \ + if (vcodec_type & (1 << client_type)) { \ + api = mpp_enc_hal_api_get(coding, (client_type)); \ + if (api) { \ + ret = hal_impl_init(p, api, cfg); \ + break; \ + } \ + } + +typedef struct MppEncHalImpl_t { + MppCodingType coding; + + void *ctx; + const MppEncHalApi *api; + + HalTaskGroup tasks; +} MppEncHalImpl; + +/* max 32 coding type and max 2 apis on each soc for each coding type hardware encoder */ +static const MppEncHalApi *venc_apis[32][2] = { 0 }; + +static RK_U32 mpp_enc_hal_debug = 0; +RK_U32 hal_h265e_debug = 0; +RK_U32 hal_h264e_debug = 0; +RK_U32 hal_jpege_debug = 0; +RK_U32 hal_vp8e_debug = 0; + +MPP_RET mpp_enc_hal_api_register(const MppEncHalApi *api) +{ + RockchipSocType soc_type = mpp_get_soc_type(); + const char *soc_name = mpp_get_soc_name(); + RK_S32 soc_match = 0; + RK_S32 index; + RK_S32 i; + + mpp_env_get_u32("mpp_enc_hal_debug", &mpp_enc_hal_debug, 0); + + enc_hal_dbg_api("api %s adding coding %d client %d\n", + api->name, api->coding, api->client); + + for (i = 0; api->soc_type[i] != ROCKCHIP_SOC_BUTT; i++) + if (api->soc_type[i] == soc_type) { + enc_hal_dbg_api("api %s match soc %d %s success\n", + api->name, soc_type, soc_name); + soc_match = 1; + break; + } + + if (!soc_match) { + enc_hal_dbg_api("api %s match soc %d %s failed\n", + api->name, soc_type, soc_name); + return MPP_NOK; + } + + index = mpp_coding_to_index(api->coding); + if (index < 0 || index >= MPP_ARRAY_ELEMS_S(venc_apis)) + return MPP_NOK; + + if (NULL == venc_apis[index][0]) + venc_apis[index][0] = api; + else if (NULL == venc_apis[index][1]) + venc_apis[index][1] = api; + else + return MPP_NOK; + + return MPP_OK; +} + +const MppEncHalApi *mpp_enc_hal_api_get(MppCodingType coding, MppClientType type) +{ + RK_S32 index = mpp_coding_to_index(coding); + const MppEncHalApi *api; + + if (index < 0 || index >= MPP_ARRAY_ELEMS_S(venc_apis)) + return NULL; + + api = venc_apis[index][0]; + if (!api) + return NULL; + + if (api->client == type) { + enc_hal_dbg_api("found api %s for coding %d client %d\n", + api->name, coding, type); + return api; + } + + api = venc_apis[index][1]; + if (api && api->client == type) { + enc_hal_dbg_api("found api %s for coding %d client %d\n", + api->name, coding, type); + return api; + } + + return NULL; +} + +static MPP_RET hal_impl_init(MppEncHalImpl *p, const MppEncHalApi *api, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + + p->coding = api->coding; + p->api = api; + p->ctx = mpp_calloc_size(void, p->api->ctx_size); + + ret = p->api->init(p->ctx, cfg); + if (!ret) { + ret = hal_task_group_init(&p->tasks, TASK_BUTT, cfg->task_cnt, + sizeof(EncAsyncTaskInfo)); + if (ret) { + mpp_err_f("hal_task_group_init failed ret %d\n", ret); + MPP_FREE(p->ctx); + } + cfg->tasks = p->tasks; + } else { + mpp_err_f("hal %s init failed ret %d\n", api->name, ret); + } + + return ret; +} + +MPP_RET mpp_enc_hal_init(MppEncHal *ctx, MppEncHalCfg *cfg) +{ + MppEncHalImpl *p; + const MppEncHalApi *api; + MppCodingType coding; + MPP_RET ret = MPP_NOK; + RK_U32 vcodec_type; + + if (NULL == ctx || NULL == cfg) { + mpp_err_f("found NULL input ctx %p cfg %p\n", ctx, cfg); + return MPP_ERR_NULL_PTR; + } + + *ctx = NULL; + + p = mpp_calloc(MppEncHalImpl, 1); + if (NULL == p) { + mpp_err_f("malloc failed\n"); + return MPP_ERR_MALLOC; + } + + enc_hal_dbg_flow("enter\n"); + + vcodec_type = mpp_get_vcodec_type(); + coding = cfg->coding; + + do { + TRY_GET_ENC_HAL_API(VPU_CLIENT_RKVENC); + if (coding == MPP_VIDEO_CodingMJPEG) + TRY_GET_ENC_HAL_API(VPU_CLIENT_JPEG_ENC); + TRY_GET_ENC_HAL_API(VPU_CLIENT_VEPU2); + TRY_GET_ENC_HAL_API(VPU_CLIENT_VEPU1); + TRY_GET_ENC_HAL_API(VPU_CLIENT_VEPU22); + } while (0); + + if (ret) { + mpp_err_f("could not found coding type %d\n", coding); + MPP_FREE(p); + } + + *ctx = p; + + enc_hal_dbg_flow("leave ret %d\n", ret); + + return ret; +} + +MPP_RET mpp_enc_hal_deinit(MppEncHal ctx) +{ + MppEncHalImpl *p; + + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + enc_hal_dbg_flow("enter\n"); + + p = (MppEncHalImpl*)ctx; + p->api->deinit(p->ctx); + mpp_free(p->ctx); + if (p->tasks) + hal_task_group_deinit(p->tasks); + mpp_free(p); + + enc_hal_dbg_flow("leave\n"); + + return MPP_OK; +} + +MPP_RET mpp_enc_hal_prepare(void *hal) +{ + if (NULL == hal) { + mpp_err_f("found NULL input ctx %p\n", hal); + return MPP_ERR_NULL_PTR; + } + + MppEncHalImpl *p = (MppEncHalImpl*)hal; + if (!p->api || !p->api->prepare) + return MPP_OK; + + return p->api->prepare(p->ctx); +} + +MPP_RET mpp_enc_hal_check_part_mode(MppEncHal ctx) +{ + MppEncHalImpl *p = (MppEncHalImpl*)ctx; + + if (p && p->api && p->api->part_start && p->api->part_wait) + return MPP_OK; + + return MPP_NOK; +} + +MPP_RET mpp_enc_hal_start(void *hal, HalEncTask *task) +{ + if (NULL == hal || NULL == task) { + mpp_err_f("found NULL input ctx %p task %p\n", hal, task); + return MPP_ERR_NULL_PTR; + } + + MppEncHalImpl *p = (MppEncHalImpl*)hal; + if (!p->api || !p->api->start) + return MPP_OK; + + /* Add buffer sync process */ + mpp_buffer_sync_partial_end(task->output, 0, task->length); + + return p->api->start(p->ctx, task); +} + +#define MPP_ENC_HAL_TASK_FUNC(func) \ + MPP_RET mpp_enc_hal_##func(void *hal, HalEncTask *task) \ + { \ + if (NULL == hal || NULL == task) { \ + mpp_err_f("found NULL input ctx %p task %p\n", hal, task); \ + return MPP_ERR_NULL_PTR; \ + } \ + \ + MppEncHalImpl *p = (MppEncHalImpl*)hal; \ + if (!p->api || !p->api->func) \ + return MPP_OK; \ + \ + return p->api->func(p->ctx, task); \ + } + +MPP_ENC_HAL_TASK_FUNC(get_task) +MPP_ENC_HAL_TASK_FUNC(gen_regs) +MPP_ENC_HAL_TASK_FUNC(wait) +MPP_ENC_HAL_TASK_FUNC(part_start) +MPP_ENC_HAL_TASK_FUNC(part_wait) +MPP_ENC_HAL_TASK_FUNC(ret_task) diff --git a/mpp/hal/mpp_hal.c b/mpp/hal/mpp_hal.c new file mode 100644 index 000000000..60234a4d3 --- /dev/null +++ b/mpp/hal/mpp_hal.c @@ -0,0 +1,453 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_hal" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_common.h" +#include "osal_2str.h" + +#include "mpp.h" +#include "mpp_soc.h" +#include "mpp_hal.h" +#include "mpp_frame_impl.h" + +#include "avsd_syntax.h" + +#define DEC_HAL_DBG_FLOW (0x00000001) +#define DEC_HAL_DBG_API (0x00000002) + +#define dec_hal_dbg(flag, fmt, ...) mpp_dbg(mpp_hal_debug, flag, fmt, ## __VA_ARGS__) +#define dec_hal_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_hal_debug, flag, fmt, ## __VA_ARGS__) + +#define dec_hal_dbg_flow(fmt, ...) dec_hal_dbg_f(DEC_HAL_DBG_FLOW, fmt, ## __VA_ARGS__) +#define dec_hal_dbg_api(fmt, ...) dec_hal_dbg(DEC_HAL_DBG_API, fmt, ## __VA_ARGS__) + +#define TRY_GET_DEC_HAL_API(cl_type) \ + do { \ + if (vcodec_type & (1 << cl_type)) { \ + api = mpp_dec_hal_api_get(coding, (cl_type)); \ + if (api) { \ + p->client_type = cl_type; \ + ret = hal_impl_init(p, api, cfg); \ + goto __DONE; \ + } \ + } \ + } while(0) + +#define CHECK_HAL_API_FUNC(p, func) \ + if (NULL == p->api || NULL == p->api->func) \ + return MPP_OK; + +typedef struct MppHalImpl_t { + MppCodingType coding; + void *ctx; + const MppHalApi *api; + MppHalCfg cfg; + RK_U32 client_type; + MppBufferGroup buf_group; + MppDev dev; + + HalTaskGroup tasks; +} MppHalImpl; + +/* max 32 coding type and max 2 apis on each soc for each coding type hardware decoder */ +static const MppHalApi *vdec_apis[32][2] = { 0 }; + +static RK_U32 mpp_hal_debug = 0; +RK_U32 hal_h265d_debug = 0; +RK_U32 hal_h264d_debug = 0; +RK_U32 hal_vp8d_debug = 0; +RK_U32 hal_jpegd_debug = 0; +RK_U32 hal_avsd_debug = 0; +RK_U32 hal_vp9d_debug = 0; +RK_U32 hal_mpg4d_debug = 0; +RK_U32 hal_avs2d_debug = 0; +RK_U32 hal_m2vd_debug = 0; +RK_U32 hal_h263d_debug = 0; +RK_U32 hal_av1d_debug = 0; + +MPP_RET mpp_hal_api_register(const MppHalApi *api) +{ + RockchipSocType soc_type = mpp_get_soc_type(); + const char *soc_name = mpp_get_soc_name(); + RK_S32 soc_match = 0; + RK_S32 index; + RK_S32 i; + + mpp_env_get_u32("mpp_hal_debug", &mpp_hal_debug, 0); + + dec_hal_dbg_api("api %s adding coding %d type %d client %d\n", + api->name, api->coding, api->type, api->client); + + for (i = 0; api->soc_type[i] != ROCKCHIP_SOC_BUTT; i++) + if (api->soc_type[i] == soc_type) { + dec_hal_dbg_api("api %s match soc %d %s success\n", + api->name, soc_type, soc_name); + soc_match = 1; + break; + } + + if (!soc_match) { + dec_hal_dbg_api("api %s match soc %d %s failed\n", + api->name, soc_type, soc_name); + return MPP_NOK; + } + + index = mpp_coding_to_index(api->coding); + if (index < 0 || index >= MPP_ARRAY_ELEMS_S(vdec_apis)) + return MPP_NOK; + + if (NULL == vdec_apis[index][0]) + vdec_apis[index][0] = api; + else if (NULL == vdec_apis[index][1]) + vdec_apis[index][1] = api; + else + return MPP_NOK; + + return MPP_OK; +} + +const MppHalApi *mpp_dec_hal_api_get(MppCodingType coding, MppClientType type) +{ + RK_S32 index = mpp_coding_to_index(coding); + const MppHalApi *api; + + if (index < 0 || index >= MPP_ARRAY_ELEMS_S(vdec_apis)) + return NULL; + + api = vdec_apis[index][0]; + if (!api) + return NULL; + + if (api->client == type) { + dec_hal_dbg_api("found api %s for coding %d client %d\n", + api->name, coding, type); + return api; + } + + api = vdec_apis[index][1]; + if (api && api->client == type) { + dec_hal_dbg_api("found api %s for coding %d client %d\n", + api->name, coding, type); + return api; + } + + return NULL; +} + +static MPP_RET hal_impl_init(MppHalImpl *p, const MppHalApi *api, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + + p->coding = api->coding; + p->api = api; + p->ctx = mpp_calloc_size(void, p->api->ctx_size); + if (NULL == p->ctx) { + mpp_err_f("malloc failed for hal %s size %d\n", + api->name, p->api->ctx_size); + + return MPP_ERR_MALLOC; + } + + ret = mpp_buffer_group_get_internal(&p->buf_group, MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err_f("mpp_buffer_group_get_internal failed. ret: %d\n", ret); + goto __FAILED; + } + + ret = mpp_dev_init(&p->dev, p->client_type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + mpp_buffer_group_put(p->buf_group); + goto __FAILED; + } + + p->cfg = *cfg; + p->cfg.hw_info = mpp_get_dec_hw_info_by_client_type(p->client_type); + p->cfg.buf_group = p->buf_group; + p->cfg.dev = p->dev; + + ret = p->api->init(p->ctx, &p->cfg); + if (ret) + mpp_err_f("hal %s init failed ret %d\n", api->name, ret); + + *cfg = p->cfg; + + return ret; + +__FAILED: + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + if (p->buf_group) { + mpp_buffer_group_put(p->buf_group); + p->buf_group = NULL; + } + if (p->ctx) { + mpp_free(p->ctx); + p->ctx = NULL; + } + return ret; +} + +MPP_RET mpp_hal_init(MppHal *ctx, MppHalCfg *cfg) +{ + MppHalImpl *p; + const MppHalApi *api = NULL; + MppCodingType coding; + MPP_RET ret = MPP_NOK; + RK_U32 vcodec_type; + MppDecBaseCfg *base; + + if (NULL == ctx || NULL == cfg) { + mpp_err_f("found NULL input ctx %p cfg %p\n", ctx, cfg); + return MPP_ERR_NULL_PTR; + } + + *ctx = NULL; + + p = mpp_calloc(MppHalImpl, 1); + if (NULL == p) { + mpp_err_f("malloc failed\n"); + return MPP_ERR_MALLOC; + } + + base = &cfg->cfg->base; + vcodec_type = mpp_get_vcodec_type(); + coding = cfg->coding; + + if (mpp_check_soc_cap(base->type, coding)) { + RK_S32 hw_type = base->hw_type; + + if (hw_type > 0) { + dec_hal_dbg_api("init with coding %d %s hw\n", coding, strof_client_type(hw_type)); + TRY_GET_DEC_HAL_API(hw_type); + if (!api) + mpp_err_f("coding %d invalid hw_type %d with vcodec_type %08x\n", + coding, hw_type, vcodec_type); + } + } + + switch (coding) { + case MPP_VIDEO_CodingAVC: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_RKVDEC); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2_PP); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1_PP); + } break; + case MPP_VIDEO_CodingHEVC: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_RKVDEC); + TRY_GET_DEC_HAL_API(VPU_CLIENT_HEVC_DEC); + } break; + case MPP_VIDEO_CodingVP8: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2_PP); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1_PP); + } break; + case MPP_VIDEO_CodingVP9: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_RKVDEC); + } break; + case MPP_VIDEO_CodingMJPEG: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_JPEG_DEC); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2_PP); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1_PP); + } break; + case MPP_VIDEO_CodingAVSPLUS: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_AVSPLUS_DEC); + } break; + case MPP_VIDEO_CodingAVS: + case MPP_VIDEO_CodingMPEG4: + case MPP_VIDEO_CodingMPEG2: + case MPP_VIDEO_CodingH263: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU2_PP); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1); + TRY_GET_DEC_HAL_API(VPU_CLIENT_VDPU1_PP); + } break; + case MPP_VIDEO_CodingAV1: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_RKVDEC); + TRY_GET_DEC_HAL_API(VPU_CLIENT_AV1DEC); + } break; + case MPP_VIDEO_CodingAVS2: { + TRY_GET_DEC_HAL_API(VPU_CLIENT_RKVDEC); + } break; + default: { + mpp_err_f("unsupported coding type %d soc %s\n", coding, mpp_get_soc_name()); + ret = MPP_NOK; + goto __DONE; + } break; + } + +__DONE: + if (ret) { + mpp_err_f("soc %s hal %s init failed ret %d\n", + mpp_get_soc_name(), p->api->name, ret); + mpp_free(p->ctx); + mpp_free(p); + return ret; + } + + *ctx = p; + + return MPP_OK; +} + +MPP_RET mpp_hal_deinit(MppHal ctx) +{ + MppHalImpl *p; + + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (MppHalImpl*)ctx; + + p->api->deinit(p->ctx); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + if (p->buf_group) { + mpp_buffer_group_put(p->buf_group); + p->buf_group = NULL; + } + + mpp_free(p->ctx); + mpp_free(p); + + return MPP_OK; +} + +MPP_RET mpp_hal_reg_gen(MppHal ctx, HalTaskInfo *task) +{ + MppHalImpl *p = (MppHalImpl*)ctx; + + if (NULL == ctx || NULL == task) { + mpp_err_f("found NULL input ctx %p task %p\n", ctx, task); + return MPP_ERR_NULL_PTR; + } + +#ifdef HAVE_AVSD + if (p->coding == MPP_VIDEO_CodingAVS) { + AvsdSyntax_t *syn = (AvsdSyntax_t *)task->dec.syntax.data; + + if (syn->pp.profileId == 0x48) { + const MppHalApi *api; + MppCodingType coding = MPP_VIDEO_CodingAVSPLUS; + MPP_RET ret; + + ret = p->api->deinit(p->ctx); + if (ret) { + mpp_err_f("deinit decoder failed, ret %d\n", ret); + return ret; + } + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + if (p->buf_group) { + mpp_buffer_group_put(p->buf_group); + p->buf_group = NULL; + } + MPP_FREE(p->ctx); + + api = mpp_dec_hal_api_get(coding, VPU_CLIENT_AVSPLUS_DEC); + if (!api) { + mpp_err_f("could not find avsplus hal api\n"); + return MPP_NOK; + } + ret = hal_impl_init(p, api, &p->cfg); + if (ret) { + mpp_err_f("hal_impl_init failed, ret %d\n", ret); + return ret; + } + } + } +#endif + + CHECK_HAL_API_FUNC(p, reg_gen); + + return p->api->reg_gen(p->ctx, task); +} + +MPP_RET mpp_hal_hw_start(MppHal ctx, HalTaskInfo *task) +{ + if (NULL == ctx || NULL == task) { + mpp_err_f("found NULL input ctx %p task %p\n", ctx, task); + return MPP_ERR_NULL_PTR; + } + + MppHalImpl *p = (MppHalImpl*)ctx; + + CHECK_HAL_API_FUNC(p, start); + + return p->api->start(p->ctx, task); +} + +MPP_RET mpp_hal_hw_wait(MppHal ctx, HalTaskInfo *task) +{ + if (NULL == ctx || NULL == task) { + mpp_err_f("found NULL input ctx %p task %p\n", ctx, task); + return MPP_ERR_NULL_PTR; + } + + MppHalImpl *p = (MppHalImpl*)ctx; + + CHECK_HAL_API_FUNC(p, wait); + + return p->api->wait(p->ctx, task); +} + +MPP_RET mpp_hal_reset(MppHal ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppHalImpl *p = (MppHalImpl*)ctx; + + CHECK_HAL_API_FUNC(p, reset); + + return p->api->reset(p->ctx); +} + +MPP_RET mpp_hal_flush(MppHal ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppHalImpl *p = (MppHalImpl*)ctx; + + CHECK_HAL_API_FUNC(p, flush); + + return p->api->flush(p->ctx); +} + +MPP_RET mpp_hal_control(MppHal ctx, MpiCmd cmd, void *param) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppHalImpl *p = (MppHalImpl*)ctx; + + CHECK_HAL_API_FUNC(p, control); + + return p->api->control(p->ctx, cmd, param); +} diff --git a/mpp/hal/mpp_hal.cpp b/mpp/hal/mpp_hal.cpp deleted file mode 100644 index 8eb3fe823..000000000 --- a/mpp/hal/mpp_hal.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_hal" - -#include "mpp_mem.h" -#include "mpp_log.h" -#include "mpp_common.h" - -#include "mpp.h" -#include "mpp_hal.h" -#include "mpp_frame_impl.h" - -#include "hal_h264d_api.h" - -// for test and demo -#include "hal_dummy_dec_api.h" -#include "hal_dummy_enc_api.h" - -/* - * all hardware api static register here - */ -static const MppHalApi *hw_apis[] = { - &hal_api_h264d, - &hal_api_dummy_dec, - &hal_api_dummy_enc, -}; - -typedef struct MppHalImpl_t { - MppCtxType type; - MppCodingType coding; - MppBufSlots slots; - - void *ctx; - const MppHalApi *api; - - HalTaskGroup tasks; - RK_U32 task_count; -} MppHalImpl; - - -MPP_RET mpp_hal_init(MppHal *ctx, MppHalCfg *cfg) -{ - if (NULL == ctx || NULL == cfg) { - mpp_err_f("found NULL input ctx %p cfg %p\n", ctx, cfg); - return MPP_ERR_NULL_PTR; - } - *ctx = NULL; - - MppHalImpl *p = mpp_calloc(MppHalImpl, 1); - if (NULL == p) { - mpp_err_f("malloc failed\n"); - return MPP_ERR_MALLOC; - } - - RK_U32 i; - for (i = 0; i < MPP_ARRAY_ELEMS(hw_apis); i++) { - if (cfg->type == hw_apis[i]->type && - cfg->coding == hw_apis[i]->coding) { - mpp_assert(cfg->task_count > 0); - p->type = cfg->type; - p->coding = cfg->coding; - p->slots = cfg->slots; - p->api = hw_apis[i]; - p->task_count = cfg->task_count; - p->ctx = mpp_calloc_size(void, p->api->ctx_size); - p->api->init(p->ctx, cfg); - - MPP_RET ret = hal_task_group_init(&p->tasks, p->type, p->task_count); - if (ret) { - mpp_err_f("hal_task_group_init failed ret %d\n", ret); - break; - } - - cfg->tasks = p->tasks; - *ctx = p; - return MPP_OK; - } - } - - mpp_err_f("could not found coding type %d\n", cfg->coding); - mpp_free(p->ctx); - mpp_free(p); - - return MPP_NOK; -} - -MPP_RET mpp_hal_deinit(MppHal ctx) -{ - if (NULL == ctx) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppHalImpl *p = (MppHalImpl*)ctx; - p->api->deinit(p->ctx); - mpp_free(p->ctx); - if (p->tasks) - hal_task_group_deinit(p->tasks); - mpp_free(p); - return MPP_OK; -} - -MPP_RET mpp_hal_reg_gen(MppHal ctx, HalTask *task) -{ - if (NULL == ctx || NULL == task) { - mpp_err_f("found NULL input ctx %p task %p\n", ctx, task); - return MPP_ERR_NULL_PTR; - } - - MppHalImpl *p = (MppHalImpl*)ctx; - return p->api->reg_gen(p->ctx, task); -} - -MPP_RET mpp_hal_hw_start(MppHal ctx, HalTask *task) -{ - if (NULL == ctx || NULL == task) { - mpp_err_f("found NULL input ctx %p task %p\n", ctx, task); - return MPP_ERR_NULL_PTR; - } - - MppHalImpl *p = (MppHalImpl*)ctx; - return p->api->start(p->ctx, task); -} - -MPP_RET mpp_hal_hw_wait(MppHal ctx, HalTask *task) -{ - if (NULL == ctx || NULL == task) { - mpp_err_f("found NULL input ctx %p task %p\n", ctx, task); - return MPP_ERR_NULL_PTR; - } - - MppHalImpl *p = (MppHalImpl*)ctx; - return p->api->wait(p->ctx, task); -} - -MPP_RET mpp_hal_reset(MppHal ctx) -{ - if (NULL == ctx) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppHalImpl *p = (MppHalImpl*)ctx; - return p->api->reset(p->ctx); -} - -MPP_RET mpp_hal_flush(MppHal ctx) -{ - if (NULL == ctx) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppHalImpl *p = (MppHalImpl*)ctx; - return p->api->flush(p->ctx); -} - -MPP_RET mpp_hal_control(MppHal ctx, RK_S32 cmd, void *param) -{ - if (NULL == ctx) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppHalImpl *p = (MppHalImpl*)ctx; - return p->api->control(p->ctx, cmd, param); -} - diff --git a/mpp/hal/rkdec/CMakeLists.txt b/mpp/hal/rkdec/CMakeLists.txt new file mode 100644 index 000000000..67021f33c --- /dev/null +++ b/mpp/hal/rkdec/CMakeLists.txt @@ -0,0 +1,28 @@ +# vim: syntax=cmake +include_directories(inc) + +add_subdirectory(common) + +if( HAVE_AVSD ) + add_subdirectory(avsd) +endif() + +if( HAVE_AVS2D ) + add_subdirectory(avs2d) +endif() + +if( HAVE_H264D ) + add_subdirectory(h264d) +endif() + +if( HAVE_H265D ) + add_subdirectory(h265d) +endif() + +if( HAVE_VP9D ) + add_subdirectory(vp9d) +endif() + +if( HAVE_AV1D ) + add_subdirectory(av1d) +endif() diff --git a/mpp/hal/rkdec/av1d/CMakeLists.txt b/mpp/hal/rkdec/av1d/CMakeLists.txt new file mode 100644 index 000000000..134da6ed8 --- /dev/null +++ b/mpp/hal/rkdec/av1d/CMakeLists.txt @@ -0,0 +1,12 @@ +# vim: syntax=cmake +include_directories(../../common/av1) + +set(HAL_AV1D_SRC) + +add_hal_source(HAL_AV1D_SRC HAVE_VDPU383 hal_av1d_vdpu383.c) +add_hal_source(HAL_AV1D_SRC HAVE_VDPU384B hal_av1d_vdpu384b.c) + +if (HAL_AV1D_SRC) + list(APPEND HAL_AV1D_SRC hal_av1d_com.c) + add_library(hal_av1d_rkv OBJECT ${HAL_AV1D_SRC}) +endif() diff --git a/mpp/hal/rkdec/av1d/hal_av1d_com.c b/mpp/hal/rkdec/av1d/hal_av1d_com.c new file mode 100644 index 000000000..6a75ef229 --- /dev/null +++ b/mpp/hal/rkdec/av1d/hal_av1d_com.c @@ -0,0 +1,1674 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_av1d_com" + +#include "mpp_bitput.h" + +#include "hal_av1d_ctx.h" +#include "hal_av1d_com.h" +#include "vdpu38x_com.h" + +const RK_U32 g_av1d_default_prob[7400] = { + 0x000052ce, 0x90000000, 0x000003e2, 0x3b000000, 0x0013e5db, 0x00000000, 0x00000000, 0x20000000, + 0x0e2d3544, 0x80000252, 0x11938c99, 0x16000042, 0x0ad1c0cf, 0x95800004, 0x6c0db50d, 0x20000000, + 0x571fc313, 0x02f5c801, 0x7c7b593f, 0x62112a31, 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0xea6ee10b, 0xd5074f9b, 0x94f16a25, 0x761fc65f, 0x0000000b, 0x00000000, 0x00000000, 0x00000000, + 0x6615eada, 0x85ff113e, 0xfd02628a, 0x8b324070, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0xb393759a, 0x35d09796, 0xf0f9b25f, 0x3d269662, 0x00000006, 0x00000000, 0x00000000, 0x00000000, + 0x172437e2, 0xd280296b, 0xc474391b, 0xc8143c32, 0x00000004, 0x00000000, 0x00000000, 0x00000000, + 0x2e4e61f7, 0x43cc143a, 0xe4cdd1bc, 0x8424ee5a, 0x0000000e, 0x00000000, 0x00000000, 0x00000000, + 0xae67e881, 0xf404162c, 0x04c279cb, 0xd128f459, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x3bb07a8e, 0xb2075d45, 0xc06730e7, 0x65142e2d, 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x95eab157, 0x31904976, 0x104e58b7, 0x140ea823, 0x00000004, 0x00000000, 0x00000000, 0x00000000, + 0xf15f65b4, 0x625b16b9, 0x5c84e91a, 0x6818843b, 0x0000000a, 0x00000000, 0x00000000, 0x00000000, + 0x3108e8c7, 0x31feb7d9, 0x405e58e4, 0x12134c2a, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x7da27c9a, 0xe0c45e8c, 0x04255055, 0xb406ee10, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0xc8e29305, 0x50238423, 0x0404a80e, 0x31000002, 0xed325966, 0x22505897, 0x06340d70, 0x10000000, + 0xb2f66acb, 0xd05cb90b, 0xe8076821, 0x39000002, 0xdb3e1d7d, 0x0e60281e, 0x01a004b8, 0x10000000, + 0xf095ea0a, 0xf718f048, 0xac895935, 0x3e000003, 0xf8dc6548, 0xae43d329, 0x06a03be8, 0x10000000, + 0x485c9479, 0x31e4c3f3, 0x6403c817, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x10000000, + 0x20004000, 0xd0893000, 0x4f7103f7, 0x415e3802, 0x00000060, 0x00000000, 0x00000000, 0x30000000, + 0xc1441200, 0x00000016, 0x6c144120, 0xbd000001, 0x00000008, 0x00000000, 0x00000000, 0x20000000, + 0xc1441200, 0x00000016, 0x6c144120, 0x00000001, 0x16c14412, 0x20000000, 0x016c1441, 0x20000000, + 0x9f757cda, 0xf30acc49, 0x41ed9ecd, 0x91f3da2f, 0x0004dcbe, 0x00000000, 0x00000000, 0x30000000, + 0x99a0ef74, 0xbbc6c189, 0xe01b49f3, 0x05a9f5f1, 0x447d2e17, 0x00013411, 0x00000000, 0x30000000, + 0x510e9734, 0xbace1440, 0xabda974a, 0xb5b865df, 0x00141ae2, 0x00000000, 0x00000000, 0x30000000, + 0x92c86b5c, 0x3e1ce0f8, 0x20ef048a, 0xaa88b5cf, 0x00000017, 0x00000000, 0x00000000, 0x30000000, + 0x5926ecae, 0x7b6081fd, 0x84356a85, 0x688991e8, 0x00000014, 0x00000000, 0x00000000, 0x30000000, + 0x9e717745, 0x9f4e221c, 0x00473c4b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x30000000, + 0x2500e1b0, 0xc762f090, 0xd57a3352, 0x1600005b, 0x59da0256, 0x2194e46b, 0x3f30eeaa, 0x10000000, + 0x1881d658, 0x94d0caeb, 0xb0e6aa11, 0x0e000043, 0x025ed44c, 0xe154314c, 0x6328dbc1, 0x10000000, + 0x9271b628, 0x629b0759, 0x688cf130, 0x1b00001f, 0x591de956, 0x17d4db8c, 0x6908ed82, 0x10000000, + 0x9097bd1b, 0xa29386ca, 0x007f011c, 0x0a000022, 0x11d2a94d, 0x4d535548, 0x35b88731, 0x10000000, + 0x5f85221d, 0x2be7d105, 0x076de504, 0x00f7c5de, 0x00000000, 0x00000000, 0x00000000, 0x30000000, + 0x10c2225a, 0x82064e92, 0x41916a10, 0xff402133, 0x00000035, 0x00000000, 0x00000000, 0x30000000, + 0xd21fa6ef, 0xf3e98846, 0x48cfa9bf, 0xd729cc60, 0x02c6ea12, 0x00012e63, 0x00000000, 0x00000000, + 0x593db70f, 0x249d49e6, 0x24fdba27, 0x082a3871, 0xb805fd92, 0x0000ef82, 0x00000000, 0x00000000, + 0x1706b2c6, 0xf44fa927, 0x40fd9214, 0x4a2c7e77, 0xf786a813, 0x000107a2, 0x00000000, 0x00000000, + 0x9665b145, 0x34aec9b2, 0xa5209a52, 0xf83e388d, 0x9e0c189c, 0x00024de5, 0x00000000, 0x00000000, + 0x9ebec31c, 0x6620cd1d, 0xfd6c52f3, 0x834a68aa, 0x96c8fda1, 0x00011fc3, 0x00000000, 0x00000000, + 0x1cb75110, 0x16162cf1, 0x0161e2f1, 0x8e4c10aa, 0x89080720, 0x0000a9e2, 0x00000000, 0x00000000, + 0x2af6d8bc, 0x14df8a3a, 0xed29ca5f, 0xd037d886, 0xc5c6b419, 0x00009622, 0x00000000, 0x00000000, + 0xa1e948f5, 0x06d10ff1, 0x899d3354, 0x565360c7, 0xc486379f, 0x00002641, 0x00000000, 0x00000000, + 0x6617d0a6, 0xf7f170c3, 0x258dfb74, 0xbb3822a2, 0xa7c4e598, 0x000024a1, 0x00000000, 0x00000000, + 0x19bfd8d9, 0x85880ba4, 0x3d38c2ab, 0xdb445297, 0x3b87551c, 0x0000a682, 0x00000000, 0x00000000, + 0x10eee8a1, 0x63d94804, 0x1cd9e9e1, 0x2631926b, 0x75059794, 0x000079c1, 0x00000000, 0x00000000, + 0xe709e2ec, 0xb5e10c4b, 0x995ccada, 0x6b4926a5, 0x97897aa0, 0x00011c83, 0x00000000, 0x00000000, + 0x234fdea7, 0x07a830ee, 0x61c823c0, 0xb7651ee0, 0xa2070f9f, 0x000045c1, 0x00000000, 0x00000000, + 0x2434e289, 0xf817b0de, 0x81789ba0, 0x6f4078a8, 0xbec60a9a, 0x000060c1, 0x00000000, 0x00000000, + 0x6574cebb, 0x85418b1e, 0x5d3e7a8d, 0x7f3c4292, 0x67c64f1b, 0x00005662, 0x00000000, 0x00000000, + 0xa5b15a29, 0xc69c4ded, 0xa58a6b36, 0x4d53a4bc, 0x7949d0a5, 0x0000e8a3, 0x00000000, 0x00000000, + 0x334be7d9, 0x232e8696, 0xd8c5f190, 0x75227c58, 0xed847e90, 0x00005541, 0x00000000, 0x00000000, + 0xa9155622, 0x37971165, 0xfdcfe3b6, 0xba57dadd, 0x6c4768a2, 0x00004082, 0x00000000, 0x00000000, + 0xecbf5c16, 0x87922fe2, 0x15a8eb80, 0x3f352eaf, 0xfbc54418, 0x00002621, 0x00000000, 0x00000000, + 0x23e0cec6, 0x670670e0, 0xd1a46b6a, 0x1c58aacb, 0xcec6001e, 0x00002ce1, 0x00000000, 0x00000000, + 0x2501dff5, 0x17a5f1d1, 0x71c96bbe, 0x7767e8e0, 0x9286699d, 0x00003541, 0x00000000, 0x00000000, + 0x2cfedefd, 0x4762b159, 0x09c03b9a, 0xe357bcd6, 0xa087211f, 0x00005dc2, 0x00000000, 0x00000000, + 0x2e5461de, 0xf7dcb6b5, 0xfdecf3e4, 0x896d62f3, 0x3404a597, 0x00001e01, 0x00000000, 0x00000000, + 0x2bec5d75, 0x488574c6, 0x71cf4bef, 0x574e84d5, 0xbe457f9b, 0x00002361, 0x00000000, 0x00000000, + 0x654ccede, 0xd7c7d065, 0xcd727b57, 0x95392e98, 0x9484fd19, 0x00002461, 0x00000000, 0x00000000, + 0x25635aa5, 0x483d9146, 0x05740baa, 0xdc42a8a5, 0x9646159c, 0x00003d61, 0x00000000, 0x00000000, + 0x2e9ddf5c, 0xa7160ecc, 0xe98bb346, 0x9e354a9e, 0x31459a18, 0x00003f62, 0x00000000, 0x00000000, + 0x28ecd5ad, 0x682ad32f, 0xf5cc4bd8, 0xd94e3ed7, 0xd746679f, 0x000023c1, 0x00000000, 0x00000000, + 0x6fd0623e, 0x6ade765f, 0x25b8fc3e, 0x041f309a, 0xf182c28e, 0x000015e0, 0x00000000, 0x00000000, + 0x762c777c, 0x34e1189c, 0x004fb969, 0x03000000, 0x67f50c77, 0x6a248837, 0x00004c31, 0x10000000, + 0x6a7b713c, 0x568cd29f, 0x002e525d, 0x1b000000, 0x356a136e, 0xab67a1d1, 0x0000889a, 0x10000000, + 0xeaa8f937, 0x766f91d4, 0x007b4a72, 0x98000000, 0xceec2075, 0xba0761d3, 0x0000470a, 0x10000000, + 0xea547740, 0xf61170e8, 0x00785a7d, 0xeb000000, 0xd56ba271, 0xd0475e93, 0x0000420a, 0x10000000, + 0x90d42799, 0xe3786737, 0x44c341a7, 0xac25da59, 0xc8c54a91, 0x000064e1, 0x00000000, 0x00000000, + 0xcb7fdad7, 0x22cb45a8, 0x949f8161, 0x3926a04e, 0xe6065f91, 0x00007982, 0x00000000, 0x00000000, + 0x6ca2d98b, 0xb1fc0402, 0xc87ca0fa, 0x62170437, 0xf7c3ea0b, 0x00005c60, 0x00000000, 0x00000000, + 0x64dbcab9, 0xa3a1b229, 0x7cdc09bf, 0x5f2be86a, 0x61443610, 0x00002261, 0x00000000, 0x00000000, + 0xaccad9dc, 0x6b23d64d, 0x28b299cd, 0xad24184b, 0x00034191, 0x000032a1, 0x00000000, 0x00000000, + 0xe575d1cf, 0x894d12a4, 0x2c6f1c53, 0xf119dc36, 0x4bc3238b, 0x00001b41, 0x00000000, 0x00000000, + 0x23e0c8a1, 0xa7c96fc8, 0xe5d48bac, 0xdb141041, 0x6a81d189, 0x00000ca0, 0x00000000, 0x00000000, + 0xa6894dab, 0x7863515f, 0x4213e42c, 0xad1c7103, 0xc9c4268d, 0x00002660, 0x00000000, 0x00000000, + 0xa551d106, 0xe886f273, 0x16149437, 0xe580df06, 0xf444a610, 0x00002c01, 0x00000000, 0x00000000, + 0x59403594, 0x25c98be7, 0x0d612ad6, 0x7a4e82aa, 0x5547a1a5, 0x00004a22, 0x00000000, 0x00000000, + 0x999fb73d, 0xc5a3ab84, 0x255642c0, 0x194b62a5, 0x56cb29a4, 0x00004d81, 0x00000000, 0x00000000, + 0xdae23d7e, 0x6611ac78, 0x6d6c8af9, 0x2e54dab2, 0x14cd6c28, 0x000076a6, 0x00000000, 0x00000000, + 0x6520d0a4, 0x18ae1164, 0x6a29ac56, 0x69898514, 0x56613bc4, 0x0007e450, 0x00000000, 0x00000000, + 0x2a1c5759, 0x19907367, 0x36450ca0, 0x8e85b117, 0x7f58c541, 0x16c5092b, 0x00000002, 0x00000000, + 0xd95e6e4c, 0x46212c69, 0xc56d8b03, 0xad586ab4, 0xe2d0ae29, 0xce02cd07, 0x00000000, 0x00000000, + 0xf57eeb67, 0xf61a4c4b, 0xad814b05, 0xf25682b8, 0x5012cf2a, 0x7c93f028, 0x00000001, 0x00000000, + 0xb200e5ac, 0x89171884, 0x1a31fc73, 0x3d7d3715, 0x5095f838, 0x18a4946a, 0x00000002, 0x00000000, + 0x35846c85, 0x6d099a36, 0x7d852b55, 0x755226aa, 0x370f58a8, 0x8f834aa7, 0x00000001, 0x00000000, + 0x728beb06, 0x6c63f8ec, 0x996c35ae, 0x23560eb1, 0x358f9a2a, 0x5d830d67, 0x00000001, 0x00000000, + 0x364fed30, 0x3c6c58f7, 0xdee8f5dc, 0xbd5e6cc4, 0xcb52b62e, 0xe9440f28, 0x00000001, 0x00000000, + 0xf2d66630, 0x7b94f7ab, 0xe6dba5bd, 0x8d6ceb67, 0x57146035, 0xf2744c89, 0x00000001, 0x00000000, + 0xf182e892, 0x9ba37866, 0x9ed59dbd, 0x2eae9f67, 0x67541136, 0xa7b3e889, 0x00000001, 0x00000000, + 0xa9ef565c, 0x69ac73be, 0xa25644bf, 0x528ac924, 0xb8d78b43, 0xee348daa, 0x00000001, 0x00000000, + 0x297b56e6, 0xe9abb3be, 0x6e516cbb, 0xe288fb21, 0xd618bd41, 0xb1246449, 0x00000001, 0x00000000, + 0x6b1ed88d, 0x69a0f3a8, 0x4e54fcbb, 0xec898b23, 0x01999242, 0xd884842c, 0x00000001, 0x00000000, + 0xb610f3b8, 0x7c5618ca, 0x1f0fb625, 0xd8c10186, 0x5b6df05f, 0xe88adcf6, 0x00000000, 0x00000000, + 0x3bdafa76, 0x470372f9, 0x688a496a, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x10000000, + 0xd788e22b, 0xf023e155, 0x30028006, 0x44009001, 0x0f002000, 0x03400700, 0x00b00180, 0x00000000, + 0x51e6c7e3, 0x90c80486, 0x640ba825, 0x94018604, 0x19003c80, 0x05c00c00, 0x015002c0, 0x00000000, + 0xd44a52f4, 0x30b00438, 0xe007a81a, 0x5f00ee02, 0x15c02d80, 0x04f00a60, 0x011c0258, 0x00000000, + 0x82ab1692, 0xc018a079, 0x10024004, 0x3c008001, 0x0d001c00, 0x02c00600, 0x00900140, 0x00000000, + 0x0d1b3ca0, 0x710e03c6, 0x081bd85b, 0x76037e0a, 0x3f009801, 0x0c001a00, 0x02480578, 0x00000000, + 0x55a9466e, 0x026066d3, 0xf04d10ea, 0x70073a1b, 0x3e00b182, 0x092015c0, 0x01b00380, 0x00000000, + 0xf2d4edf3, 0x9c28da3e, 0x22da74ef, 0x2c90473e, 0x00145cce, 0x00080010, 0x00000000, 0x30000000, + 0x20004000, 0xe8001000, 0xeebc04e1, 0x007296c3, 0x00200040, 0x00000000, 0x00000000, 0x30000000, + 0x670c5d0b, 0x01914f31, 0x02a00700, 0x000000d2, 0x00000040, 0x00000000, 0x00000004, 0x20000000, + 0x83801000, 0x903800e3, 0x7003800d, 0x06001600, 0x00000080, 0x00000000, 0x00000000, 0x00000000, + 0x83801000, 0x903800e3, 0x7003800d, 0x06001600, 0x00000080, 0x00000000, 0x00000000, 0x00000000, + 0x0a001400, 0x07400f00, 0x01800360, 0x004000a0, 0xc0058010, 0x00010002, 0x00000000, 0x30000000, + 0x1d003c00, 0x06000d80, 0x01000280, 0x00160040, 0x0004000b, 0x00000000, 0x00000000, 0x30000000, + 0x10004000, 0x00000600, 0x01680500, 0x00000087, 0x00100040, 0x00000006, 0x87016805, 0x20000000, + 0x18003000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x30000000, + 0x1e006000, 0x00000b40, 0x01e00600, 0x000000b4, 0x00000040, 0x00000000, 0x00000004, 0x20000000, + 0x2a007000, 0x00000d20, 0x00000400, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x20000000, + 0x83801000, 0x903800e3, 0x7003800d, 0x06001600, 0x00000080, 0x00000000, 0x00000000, 0x00000000, + 0x83801000, 0x903800e3, 0x7003800d, 0x06001600, 0x00000080, 0x00000000, 0x00000000, 0x00000000, + 0x0a001400, 0x07400f00, 0x01800360, 0x004000a0, 0xc0058010, 0x00010002, 0x00000000, 0x30000000, + 0x1d003c00, 0x06000d80, 0x01000280, 0x00160040, 0x0004000b, 0x00000000, 0x00000000, 0x30000000, + 0x10004000, 0x00000600, 0x01680500, 0x00000087, 0x00100040, 0x00000006, 0x87016805, 0x20000000, + 0x18003000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x30000000, + 0x1e006000, 0x00000b40, 0x01e00600, 0x000000b4, 0x00000040, 0x00000000, 0x00000004, 0x20000000, + 0x000016f9, 0x30000000, 0x00000143, 0xe3000000, 0x00000009, 0x00000000, 0x00000000, 0x20000000, + 0x2a5b78ad, 0x7000054f, 0xb2c7a765, 0x72000063, 0xaea977ef, 0x00000006, 0x00000000, 0x20000000, + 0x0f41b1bc, 0x428ec5ec, 0x2067e0c8, 0x0080005c, 0x00200040, 0x00080010, 0x00000000, 0x30000000, + 0x20004000, 0x08001000, 0x02000400, 0x65ae7700, 0xfa2dd5db, 0x0008f52e, 0x00000000, 0x30000000, + 0x4d93c4da, 0x0537a9b6, 0xe036d0a5, 0x00010412, 0xe4200040, 0x0005cb68, 0x00000000, 0x30000000, + 0x4b80a238, 0x2991a91e, 0xd2ceb533, 0xe4bfaf71, 0x00200067, 0x00080010, 0x00000000, 0x30000000, + 0x20004000, 0x08001000, 0xae8ea400, 0x00800187, 0x00000040, 0x00000000, 0x00000000, 0x30000000, + 0x0fa4621d, 0xe0000000, 0x00fa1ed7, 0xf1000000, 0x000e246a, 0x42500000, 0x0000ba33, 0x20000000, + 0x11e56bfd, 0xa0000000, 0x0108652a, 0x6c000000, 0x00072219, 0x07800000, 0x00009313, 0x20000000, + 0x0b992b51, 0x40000000, 0x004098cb, 0x1e000000, 0x0004a18f, 0x76200000, 0x00002cc8, 0x20000000, + 0x00690105, 0x50000000, 0x01555d55, 0x55000000, 0x001555d5, 0xf8100000, 0x00002b10, 0x20000000, + 0x03e518c1, 0x30000000, 0x0024b0ed, 0xd2000000, 0x00030e8b, 0x00000000, 0x00000000, 0x20000000, + 0x7754767a, 0x3bc5398e, 0xe66db550, 0x7972a509, 0x70545330, 0x39837348, 0x18f467b1, 0x00000000, + 0xf99f7cda, 0xecb5da22, 0x9719ce3c, 0x3d8e0986, 0xfb1e14c0, 0x6c96844d, 0x310ccf8a, 0x00000000, + 0x78b37525, 0x1c7a7b6d, 0xc7057e1a, 0xed8fd778, 0x0e165639, 0xcf029648, 0x116045f8, 0x00000000, + 0x78ebf96c, 0xac879a75, 0x8e9fb5ba, 0x257a111e, 0xa7170fb5, 0x7a140d29, 0x1d8c7eb1, 0x00000000, + 0xf92efb8a, 0x7c6dd9de, 0x06faee06, 0xf7959173, 0x4f9f5343, 0x807691ee, 0x3248d322, 0x00000000, + 0x77cef54a, 0xcc13ba68, 0x7adc45ce, 0x8a91a961, 0x1d97e5bc, 0x2d835189, 0x152063f1, 0x00000000, + 0xf84a7941, 0xfc319a0a, 0xaa7e4598, 0x626c0109, 0x9954f52f, 0x6943a428, 0x1b707d11, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0xfe12ff66, 0x8effbe1e, 0x67be0f7d, 0x694c0fde, 0x99d09223, 0x58537587, 0x1d047969, 0x00000000, + 0xfd6b7b91, 0x8eb6be8a, 0xbbaa7f57, 0x695bd1d4, 0x634f0fa6, 0xa771c165, 0x0d0c3880, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x38007800, 0x0c001a00, 0x02800580, 0x00800120, 0x00180038, 0x8004000a, 0x20008001, 0x00000000, + 0x134a9811, 0x23fdcd9a, 0xf13b7322, 0x739b7ee2, 0xe2a61ae4, 0x000dbb96, 0x00000000, 0x30000000, + 0x00180341, 0x00000000, 0x00018ea4, 0x5a000000, 0x003a437e, 0x1ac00000, 0x00000501, 0x20000000, + 0x0197861a, 0x20000000, 0x00143ed0, 0xfe000000, 0x003dc07c, 0xe6700000, 0x0000deda, 0x20000000, + 0x0016035a, 0x80000000, 0x0001c6fe, 0xcf000000, 0x003b9cfe, 0x4f500000, 0x00000421, 0x20000000, + 0x017b86d2, 0xd0000000, 0x00151f46, 0xa7000000, 0x003e28fd, 0x58700000, 0x00016354, 0x20000000, + 0x516d105b, 0xc420aba4, 0x6684db8e, 0x03aaf2da, 0x770aead5, 0x000a7dec, 0x00000000, 0x30000000, + 0x1a4a184b, 0x6252321c, 0xee3e02bd, 0x2850fe47, 0x80190041, 0x0004200c, 0x00000000, 0x30000000, + 0x05125010, 0x00000000, 0x00512501, 0x0b000000, 0x0003c037, 0x00000000, 0x00000000, 0x20000000, + 0x225a4d46, 0x60000000, 0x0225a4d4, 0x12000000, 0x000dff21, 0x00000000, 0x00000000, 0x20000000, + 0xf04efa01, 0x59c636c2, 0x009a7a45, 0xcc000000, 0x84f97cfd, 0x921ab156, 0x00009213, 0x10000000, + 0x2996e96a, 0xa0000000, 0x02996e96, 0x5d000000, 0x00138cbe, 0x00000000, 0x00000000, 0x20000000, + 0x39a8fd60, 0x9a265c69, 0x012d4b42, 0x61000000, 0xe064e1eb, 0x41973090, 0x00004ea2, 0x10000000, + 0xf9528444, 0x506b1ec4, 0xc7e1674d, 0xf3e5700e, 0x85c1717c, 0x000f8f1c, 0x00000000, 0x30000000, + 0xf4236eb9, 0x3aea1833, 0x006c71ba, 0x32000000, 0xc337b7fa, 0xfb8acb56, 0x00009e93, 0x10000000, + 0xb1ab81cb, 0x103efe92, 0xfbd07f05, 0x7fc1ec04, 0x040099ff, 0x0000000b, 0x00000000, 0x30000000, + 0xba757e49, 0x6cb5fc8f, 0x0119b397, 0x5a000000, 0x4277bbfb, 0x0c7a4d5b, 0x0001063b, 0x10000000, + 0xe69c60f0, 0x95834e46, 0x006e39c4, 0x1d000000, 0x2f69b1e4, 0x38e67510, 0x000092ba, 0x10000000, + 0x77947beb, 0xcb0a378e, 0x006b4b72, 0x36000000, 0x5d78b57f, 0xd19c6fdb, 0x00011183, 0x10000000, + 0xe71de194, 0x55fd8f14, 0x00847210, 0xb1000000, 0x2ea4885f, 0xe115788e, 0x00008459, 0x10000000, + 0x77947e41, 0x6ba99957, 0x01167417, 0xeb000000, 0xde7777fe, 0xfafba6fa, 0x0001480b, 0x10000000, + 0x5a8a4e4b, 0x13df2aa6, 0x0052c147, 0x11000000, 0x7962ec5a, 0xbc35b88f, 0x000098e9, 0x10000000, + 0x756272af, 0x986235a6, 0x0110c331, 0xb2000000, 0xcfa52978, 0x3267f1d1, 0x00009e72, 0x10000000, + 0x9761c5a4, 0x7430cad4, 0x0075c966, 0xf7000000, 0x8218fadd, 0x59d18ae5, 0x00000f80, 0x10000000, + 0x2ed27eba, 0x88a331b6, 0x00a5134b, 0x1c000000, 0x7831347e, 0x5298f2b8, 0x00013e0b, 0x10000000, + 0xe195e931, 0x82d7a8f8, 0x002160b6, 0xb6000000, 0x6c6a026e, 0xaf9582ae, 0x00006851, 0x10000000, + 0x620a7b9a, 0x07b0307a, 0x004dcae6, 0x71000000, 0xdff6857d, 0x9add1cfa, 0x0000aff2, 0x10000000, + 0xed847364, 0x572af15b, 0x00a72280, 0x48000000, 0x376ea571, 0x82174893, 0x0000adca, 0x10000000, + 0xf3637aed, 0xdb76d752, 0x00e33c5f, 0xc9000000, 0x9435a8fe, 0x115ca37a, 0x00013b84, 0x10000000, + 0xef7ef660, 0xb5701370, 0x0083a9c4, 0x0b000000, 0xcff562fb, 0xb3c6bdb5, 0x0000d7ba, 0x10000000, + 0xb042fc8d, 0x7a80d7ec, 0x015e9bc7, 0x1b000000, 0xe6b1327d, 0xed0af2f6, 0x00007453, 0x10000000, + 0xe0000fda, 0xd2cc95b1, 0x0072f848, 0xb7bbef00, 0x0002430d, 0x00000000, 0x00000000, 0x30000000, + 0x71897f92, 0x7b82b845, 0x0126fc15, 0x95000000, 0xdcf06d7e, 0x2f3ac9f6, 0x00010334, 0x10000000, + 0x0473131b, 0x40000000, 0x00dcfd2f, 0x70000000, 0x0004f366, 0x61600000, 0x000092c2, 0x20000000, + 0x3110ff67, 0x5b261814, 0x018f2443, 0x49000000, 0x18f3a272, 0x48588335, 0x00011eb3, 0x10000000, + 0x00bf8355, 0x70000000, 0x007139d5, 0x01000000, 0x000ab1d0, 0x48700000, 0x00009646, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0x0e61b14f, 0x00000000, 0x00234887, 0x1c000000, 0xa8c9391c, 0xafa00002, 0x56215d55, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0x0b95e3b0, 0x100002e0, 0x0d02d352, 0x58000045, 0x8181d785, 0x16e00000, 0x2cc4aeca, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0x94475960, 0x3000056c, 0x4cd1de8f, 0x72000036, 0x54d4bc38, 0x90500004, 0x0d283300, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0x0b5a9f35, 0x3136c418, 0xdd83a5e2, 0x61248687, 0x4fca29ef, 0x0000d4a3, 0x00000000, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0x11c33268, 0x2194c5e9, 0xb41b5846, 0x0002ac09, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0xce3ca63c, 0x315bc4de, 0x956305f2, 0x2f1e6c7b, 0x1f867bf7, 0x00009242, 0x00000000, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0x5697350b, 0xc20686b1, 0x9c16a039, 0x0001f407, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x663334cc, 0xcce666e6, 0x0003334c, 0x00000000, 0x20000000, + 0x8e60a5a4, 0x721da5a9, 0x000000a8, 0xed000000, 0xc4de5362, 0x2b23e8cb, 0x00000001, 0x10000000, + 0xe666e666, 0x63334ccc, 0xce666e66, 0x993334cc, 0xc326f97b, 0x000294a9, 0x00000000, 0x20000000, + 0x0f716764, 0x11f205b0, 0x00000083, 0x1c000000, 0x535348b6, 0xc2c29aa7, 0x00000000, 0x10000000, + 0x32cbff6f, 0x62fab44d, 0x8b480fe9, 0x7f7d5749, 0xd96249fe, 0x0001036d, 0x00000000, 0x20000000, + 0x026105da, 0xf058a0f0, 0x00000019, 0x37000000, 0xfcd004a9, 0x8ac1fea5, 0x00000000, 0x10000000, + 0xba4f7fe7, 0x42602968, 0x6f7457fc, 0xdb449348, 0xd4797e7f, 0x00058711, 0x00000000, 0x20000000, + 0x1ff56375, 0x83f90cd3, 0x0000010f, 0xa7000000, 0xc04f0c6e, 0x7391de45, 0x00000000, 0x10000000, + 0x33a87f63, 0x977c3345, 0x5b2e0ff8, 0xd11a5936, 0xb8352fff, 0x000580b3, 0x00000000, 0x20000000, + 0x57e83cc6, 0x22f0493a, 0x000000c7, 0x2e000000, 0x57038b88, 0x23108121, 0x00000000, 0x10000000, + 0xb4227ef3, 0xd4b6b501, 0x7f508ffa, 0x50796944, 0x42752678, 0x0006f1b4, 0x00000000, 0x20000000, + 0x0ec8a5bf, 0xd27b8628, 0x004c90ef, 0xda000000, 0x7e21d4e4, 0xc214eced, 0x00008369, 0x10000000, + 0x75246e96, 0xeb42787c, 0xfe31dcbe, 0x0061aced, 0xa093602c, 0x3b138fc8, 0x21647869, 0x00000000, + 0x92276278, 0x72b7a71b, 0x004060f0, 0x90000000, 0x1dd44db7, 0x229335a8, 0x00005519, 0x10000000, + 0xbaf9f993, 0x1d363b55, 0x9af29618, 0xf688075b, 0x02d8243a, 0x6143c9ca, 0x1f8c7a41, 0x00000000, + 0x82928622, 0x506ec112, 0x000bc828, 0x09000000, 0x8b12c02d, 0xfdf2d5c7, 0x000046b0, 0x10000000, + 0xfb45fcfe, 0x59b2bae5, 0x1db08c23, 0x1d43ceaf, 0x2fc84918, 0x00000002, 0x00000000, 0x00000000, + 0x22ae666f, 0x1558ee6b, 0x007f19c6, 0x88000000, 0x34cca4f2, 0xa521fc05, 0x00002970, 0x10000000, + 0x00004000, 0x90000000, 0x000006fb, 0x32000000, 0x00000078, 0xd1400000, 0x00000007, 0x20000000, + 0x1c36c1ef, 0x03f0cace, 0x0060316a, 0xf4000000, 0x42430e06, 0x31108141, 0x00000dd8, 0x10000000, + 0x3df8fcb8, 0xed9c3e11, 0x97eb0fe8, 0x00dd13e2, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0x515aab47, 0xe322076d, 0x347b2948, 0x14000028, 0x9421f3e5, 0x1215734e, 0x37b0bbfa, 0x10000000, + 0xfefc7e70, 0x2ef95f0b, 0x00000667, 0x2e000000, 0xb77f35ff, 0x28fe605e, 0x00000006, 0x10000000, + 0x92b969ed, 0x230d478b, 0x3069812b, 0x6b00001d, 0x2793e734, 0x47c34ec8, 0x244074c9, 0x10000000, + 0xff077eb7, 0xff211eec, 0x030d9733, 0xb1000000, 0x937e937e, 0xdcdd515e, 0x000269dd, 0x10000000, + 0x02ed06cc, 0x9084e13c, 0xe0133834, 0x3e000005, 0xd292842c, 0x3ff32f47, 0x22747661, 0x10000000, + 0x3f0f7f25, 0x0efabee3, 0x5b43a71a, 0x8d00013b, 0xc6bea2fe, 0xaf9da45e, 0xee9e7775, 0x10000000, + 0x22d5e919, 0xd5e88edc, 0x9cc6aa37, 0xa9000036, 0xc0cd9772, 0xdd925545, 0x11f84a30, 0x10000000, + 0x7edc7eca, 0x8e3f7e28, 0xa2f2ee7e, 0x1a85b94e, 0x12bc637c, 0xc43d439d, 0x9a359283, 0x10003822, + 0x18c639d3, 0xe44b4a4a, 0x28887195, 0x2a000025, 0x3902cf86, 0x3af08821, 0x06f81730, 0x10000000, + 0x7e14fd7f, 0x6d595c61, 0x722c9580, 0x334918da, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x7f2dfe77, 0x8f353f44, 0x7f39873a, 0xd573032f, 0x000d8d27, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x36557351, 0x08e3b68a, 0xb7973789, 0x008d9386, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0x347e0397, 0xf54a342c, 0x64a57b0b, 0xefc43404, 0x45c57033, 0x00013bd6, 0x00000000, 0x30000000, + 0x37a7f5b4, 0xfa3dd897, 0x00000304, 0x06000000, 0x42b9caf9, 0x592a7479, 0x00000003, 0x10000000, + 0xbcf984c4, 0x17de161b, 0x9cc9e376, 0x50d5ca03, 0x000566b9, 0x00080010, 0x00000000, 0x30000000, + 0xb5a4724f, 0xc9415626, 0x0125b3ae, 0xe5000000, 0x3d3aba79, 0x68eaac3b, 0x00014184, 0x10000000, + 0x75788afb, 0x147e4e62, 0xecd91286, 0x18e27c08, 0x000765c4, 0x00080010, 0x00000000, 0x30000000, + 0x31706b83, 0xf842936c, 0xa114231b, 0xfa000050, 0x44f93877, 0x8be90d1a, 0x5e017c93, 0x10000000, + 0xbc733a00, 0x53a8f8e3, 0x4025f555, 0xf4f55402, 0xdb848142, 0x000d7e9f, 0x00000000, 0x30000000, + 0x39ac7628, 0xfbab5a30, 0x39db54ed, 0x654330c8, 0xbd77ef77, 0xf54ac1b8, 0x6fdd1bfa, 0x10002b06, + 0xbfc5e75c, 0x0ef1fe66, 0x66aaac00, 0x00800027, 0x00200040, 0x00080010, 0x00000000, 0x30000000, + 0x33696c19, 0xf97ad63d, 0x25cdf416, 0x2c33deb9, 0x0000000e, 0x00000000, 0x00000000, 0x00000000, + 0x2000028b, 0x008af000, 0x020c0400, 0x806d0134, 0x2026c044, 0x0000000f, 0x00000000, 0x30000000, + 0xbc1e78b7, 0xbdeddd23, 0x59fb356d, 0x7e2b12b2, 0x0001ec10, 0x00000000, 0x00000000, 0x00000000, + 0xde5cbdbf, 0x0800188e, 0x02000400, 0x00800100, 0xc4a41340, 0x0004324b, 0x00000000, 0x40000000, + 0x82dd2787, 0x98c26090, 0x1c487960, 0xf875b57e, 0xe4fa1924, 0xa009c1d7, 0x8fc37627, 0x80000001, + 0x84a3b36b, 0x4965a128, 0x084ec197, 0x406e857c, 0xe6788b20, 0xa3783355, 0x95d37f5f, 0x80000001, + 0xc5e9b95e, 0x49d980de, 0x6847199f, 0x835b056c, 0x36f3ae16, 0x66159c31, 0x6727395f, 0x80000001, + 0x05d928ae, 0x08cfa15d, 0xbc6f11c8, 0x1a949f97, 0x5ebbf637, 0x000b72da, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x0740ba53, 0x40a54318, 0x881bd078, 0x3e1dd87a, 0x926e8f70, 0x00000013, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x0a2fc288, 0xea86c21d, 0x147c6a30, 0x0b939da3, 0xe577c4b3, 0x4ef937b6, 0x62d73617, 0x80000001, + 0xc4572f45, 0x59a1a0d1, 0xa452519f, 0x366d7780, 0x7675bc9f, 0x4fc6e713, 0x519f1ed7, 0x80000001, + 0x7985f960, 0x18f91b3e, 0x5938e321, 0x3e4a9d06, 0xfba83297, 0xc28455ec, 0xc3761745, 0x80000000, + 0xd9b7cf08, 0x5bbf08c4, 0x999e8c53, 0xb6a7839f, 0x48b6bd43, 0x1259e0d7, 0x5b3b1b5f, 0x80000001, + 0x1d95d5ac, 0x4be98a9d, 0x15b30c79, 0x80a3fb9a, 0x55b593c1, 0x42694816, 0x7bcb48e7, 0x80000001, + 0x2748e464, 0x6d3d0f5f, 0xb23bc573, 0xb4d901d7, 0x5fe84c63, 0xa28589ce, 0x817d787c, 0x80000000, + 0xdebfb04f, 0x29b6f374, 0x0200048f, 0x00800100, 0xa0a3dd40, 0x0004144b, 0x00000000, 0x40000000, + 0x40ba980e, 0xe6ec401b, 0xf014588d, 0x0236c93d, 0xb1b1148b, 0x4473ef4d, 0x3f170357, 0x80000001, + 0x41e5a121, 0x77d82052, 0xbc2180e2, 0xcb47fd56, 0xd2b35e0f, 0x6914bdef, 0x5f6b32f7, 0x80000001, + 0x82a41c8d, 0x07e4608c, 0x003cf127, 0xb94d6f54, 0x1d327e93, 0x5bf51ab0, 0x5b5f2b27, 0x80000001, + 0x01601e0c, 0x073cc02f, 0x201720a5, 0x3e3ccf44, 0x0ab1518d, 0x3554220e, 0x2fb6ed9f, 0x80000001, + 0xc246a740, 0x38b2005d, 0xf42cc922, 0xe8527d67, 0x8a33b012, 0x4a251f70, 0x41eb0bb7, 0x80000001, + 0x4c49e9ab, 0x20852239, 0xc013104c, 0x4809fa30, 0x53ec546e, 0x00000012, 0x00000000, 0x50000000, + 0x442eb069, 0xc936009f, 0xa03ac956, 0xf857956d, 0x62b46795, 0x5955b031, 0x4f271e3f, 0x80000001, + 0x8289225e, 0xa79d6061, 0x141770bd, 0xf3393f38, 0xc82e758a, 0xd8835b6c, 0xf7ea9ca6, 0x80000000, + 0x41ea213f, 0x27c20043, 0x281bc8cf, 0xae3c4545, 0xb8b08a0b, 0x2c93c08d, 0x2deaedbf, 0x80000001, + 0x39577938, 0x28f45b12, 0x5d34f31b, 0xab4d1b0c, 0x16285d17, 0xc9d45fad, 0xc36a1905, 0x80000000, + 0xdb12d1d0, 0x7bf7e96e, 0x71b46c7c, 0x46ac0ba4, 0xb6b742c6, 0x1eaa2617, 0x631726b7, 0x80000001, + 0xd414c582, 0x7a6c263a, 0x8528cb70, 0xd8881575, 0x733207b1, 0x18579053, 0x640b2427, 0x80000001, + 0x2762e4a9, 0xfd398f5a, 0xea393d6f, 0x4ad585d3, 0xebe12be1, 0x85541b2a, 0x4658eb9b, 0x80000000, + 0x9e6b229f, 0xe75c3035, 0xf211f49f, 0x00800143, 0x25eb5ec0, 0x000659b0, 0x00000000, 0x40000000, + 0x40388bf1, 0xe5a9e008, 0x440af855, 0x132b852d, 0xd36ec207, 0xf522844a, 0xf5ca9a2e, 0x80000000, + 0x00e21590, 0x76bea030, 0x4015a890, 0x85448747, 0x3b31a70f, 0x2b53f72e, 0x2386df0f, 0x80000001, + 0x88b8aba3, 0xfa9c620b, 0xb4c4a2a3, 0x5873ad80, 0x3ef5c326, 0x89f6f393, 0x802b5d47, 0x80000001, + 0x405f0fdc, 0x762d0009, 0x1008f05f, 0xa728c52a, 0x03ad9b05, 0xc7921d2a, 0xcfea60ee, 0x80000000, + 0x40dc1289, 0x26e4a02c, 0xf01970a5, 0x6b3b8d41, 0xe7b0d70c, 0x25c3e7ad, 0x2682e10f, 0x80000001, + 0x675e7906, 0xd08ee20e, 0x5009601a, 0x91074e19, 0x9d2b926a, 0x00000012, 0x00000000, 0x50000000, + 0x417c1439, 0xb7a06045, 0x8c2750f4, 0x44447b4c, 0x56b0f78f, 0x3fd42dce, 0x411b060f, 0x80000001, + 0x808f1194, 0x566a201c, 0x700b606b, 0xd42b0927, 0xe4ed3d86, 0xcf4286ca, 0xe83283f6, 0x80000000, + 0x813d976a, 0x4749802c, 0x581f48c8, 0x0d411549, 0x3671450e, 0x44f40eae, 0x3f870477, 0x80000001, + 0xbaee7ae1, 0xca825c42, 0x9598bbfe, 0x356c433f, 0x4e6b61a7, 0x03859aef, 0xe2de4a56, 0x80000000, + 0x20b559be, 0x7cb44ca9, 0x76138d15, 0x30b83db2, 0xbd787dce, 0x415acfb8, 0x75fb41df, 0x80000001, + 0x920641b0, 0x29f0e562, 0x81049322, 0x737d7d67, 0x1d305e2c, 0xfd66cfd2, 0x54bf0c76, 0x80000001, + 0xe9976734, 0x9d7690cc, 0x4e5d45a4, 0x45dca5db, 0xb5a5f3e6, 0x496577ed, 0x3cb8d14b, 0x80000000, + 0x601c94f9, 0xf6700e5a, 0x61c002f0, 0x9bb0b4ce, 0x6cbb72dd, 0x000d709c, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0xc75115ce, 0x8cbe82e8, 0x1215f4ee, 0x42cfb7de, 0xb37dcd5e, 0xe45dc9bc, 0xdccbd57f, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x01580c39, 0x083ce037, 0xd04d7146, 0xd9636379, 0xf976739c, 0x74069772, 0x5bfb294f, 0x80000001, + 0x3b0e7905, 0x008a41e4, 0xec02b03b, 0xeb018e09, 0xef32246b, 0x00000017, 0x00000000, 0x50000000, + 0xc11d91fb, 0x55e0203e, 0x2c258092, 0xd43f4320, 0xbdb60093, 0x8ee74e73, 0x7eef55ff, 0x80000001, + 0x00160614, 0xa4990005, 0xcc06f83e, 0xad289d1a, 0x98af6a06, 0x1c42af0b, 0x1272c177, 0x80000001, + 0x03279a1d, 0x596a4053, 0x5085e9fe, 0x3a8c119a, 0x68396332, 0xa0698357, 0x91cb78f7, 0x80000001, + 0x3db5fda8, 0xac411e4c, 0xe1de1cc1, 0xd7c321bd, 0xcefa4ed5, 0x6f2c637a, 0x9fe377e7, 0x80000001, + 0xf6aef4b5, 0x9dc159ff, 0x02cffe23, 0x11ca87c9, 0x067953dc, 0x5d7b729a, 0x8c9f56e7, 0x80000001, + 0xd714c9eb, 0x2a9a27ca, 0x394c7b9d, 0xa7878571, 0x29f17132, 0x2d677a13, 0x732f383f, 0x80000001, + 0xb83077b1, 0xaf18da93, 0xbf5b2f26, 0xe5f0e7f0, 0x2f5c4c74, 0x21425568, 0x66dd3b8c, 0x80000000, + 0x1555a492, 0x88000e00, 0x62777bd3, 0x86510af1, 0x0030002c, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x524936db, 0x0d556492, 0xeeaaae00, 0x4f89d9c4, 0x6bfaf2ac, 0xf96a1b18, 0xf35bf1b7, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00930a2d, 0x07100015, 0x34180090, 0x3130c54d, 0x1134448c, 0x746599b1, 0x745f2e8f, 0x80000001, + 0xb943f943, 0x706821a0, 0x9004d813, 0xa700ee05, 0xb87e14fd, 0x0000001e, 0x00000000, 0x50000000, + 0x41278716, 0x6785a031, 0xa834e0c8, 0xee508168, 0x00300014, 0x92558e50, 0x50030497, 0x80000001, + 0x00110640, 0xf5054005, 0x7c094852, 0xd637cb37, 0x07725e0b, 0x3d94b5cf, 0x2d66ea4f, 0x80000001, + 0x85f928f6, 0x2bd880da, 0xc8d402e4, 0x5d9cafc5, 0x0e3cd639, 0xd27aae79, 0xc967ba27, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc173a0d7, 0x76e1e02e, 0xb019c8a6, 0x48523960, 0xfcf54494, 0x58c607f1, 0x4c5b184f, 0x80000001, + 0xd401b583, 0x080012ef, 0x02000400, 0x00800100, 0xa1e0d0c0, 0x00032a49, 0x00000000, 0x40000000, + 0xc1951f9a, 0xe6e7602d, 0xb01d48b2, 0x355e196d, 0xf8b6ef99, 0x53a72a53, 0x4b17192f, 0x80000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x42672600, 0xc8948049, 0x7027c10d, 0x9e4cbd63, 0x88b33d90, 0x22e4866f, 0x1472cd47, 0x80000001, + 0xc1cf1ca7, 0x76d2a04a, 0x902a68d9, 0xd876a188, 0x32b95823, 0x0008a737, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x055b2c8b, 0x602b2234, 0x08049845, 0x6206ee31, 0xbfdfe267, 0x0000000a, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0xc3e73117, 0x98cbc08b, 0x182f3125, 0x6b624d7d, 0x0f747218, 0xf54544d1, 0xe84e960e, 0x80000000, + 0xc1bea084, 0x483ee03c, 0xf82368f0, 0xce4d4f64, 0x6eb34090, 0xfee46eaf, 0xf2f29ece, 0x80000000, + 0xb65d7636, 0x14c118f3, 0xb03940f7, 0xe92f60ce, 0x91e2650b, 0x3702c4e9, 0x8e79b27d, 0x80000000, + 0x57a94b22, 0x4b5c07ff, 0x057e4c12, 0xf99dd193, 0x2575863d, 0xefb92796, 0x46befa76, 0x80000001, + 0xd21ec2d4, 0x0a11a535, 0x0102c32c, 0x6f7cf568, 0x0ef088ab, 0xac06b0d2, 0x225ec236, 0x80000001, + 0xa1d45d4b, 0xbc878c39, 0xe5dfc4dc, 0x28c12fbd, 0x219948d3, 0x6361c386, 0x3bf0d5bb, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0a5182c, 0x75d18016, 0xb40d6060, 0xf137393d, 0xa9ef068a, 0xea22d40b, 0xf22e827e, 0x80000000, + 0x9791af37, 0x08aaf11b, 0x0200045b, 0x00800100, 0xd021ce40, 0x0003906a, 0x00000000, 0x40000000, + 0x00a9952a, 0xf5908012, 0xfc0f806f, 0x633a9539, 0x90ee040b, 0xc662fe0b, 0xdb525ece, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x82141f3a, 0x37c84055, 0x58358105, 0x904da95a, 0x90f2d993, 0x34e4bc2f, 0x2c32e977, 0x80000001, + 0xc0909529, 0x758d400d, 0xf80be861, 0x6e3c5341, 0xbf70940b, 0xdc23a32d, 0xd8fe6d76, 0x80000000, + 0x40cb1443, 0xd6baa020, 0x0418b0a7, 0x6442914f, 0xb271d00e, 0x0654390e, 0x035eaf87, 0x80000001, + 0x09aa4ec0, 0x7043e20a, 0xf40d887a, 0x6b02b216, 0x8edf3ee8, 0x0000000a, 0x00000000, 0x50000000, + 0x41d49adb, 0x57e7e046, 0xcc2b6905, 0xea4e4960, 0x4eb2a811, 0x18447f8f, 0x106ac417, 0x80000001, + 0x00f31ad0, 0x865ee01c, 0xb40f607b, 0x3532fb37, 0xdeaf4209, 0xb0c2deab, 0xc03648ae, 0x80000000, + 0x01121c12, 0xa6e3a019, 0xf8110897, 0xcd33b73b, 0x076f8e08, 0xde42e9ec, 0xe1627be6, 0x80000000, + 0xb732770d, 0x864e198e, 0xf45be16d, 0x883a6ee7, 0x8c241d0f, 0x562328ea, 0x9969c945, 0x80000000, + 0x5a67d076, 0xdbbda95a, 0x91a3e454, 0xfea4919b, 0xed366341, 0xfd59a096, 0x53fb0f8e, 0x80000001, + 0x515fc077, 0x69c544fc, 0x44f44306, 0x377a6d62, 0xb72fe32a, 0xbab680b1, 0x2b2acf7e, 0x80000001, + 0x6310df19, 0x5cb1acd5, 0x59f3d500, 0xb7c375c0, 0x89993a54, 0x45520006, 0x3b0cd013, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x01069b27, 0x96e8c00c, 0x4c0dd857, 0x7a22c525, 0x16a81083, 0xaa70ad26, 0x43795d65, 0x80000000, + 0xd760a269, 0x2816ad6c, 0x5a4603a2, 0x00800144, 0xb52ac540, 0x0005c56f, 0x00000000, 0x40000000, + 0x004291e4, 0x353a800b, 0x28014019, 0xf0103ce5, 0xd0244600, 0x01a06023, 0x1dbcda05, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x84099975, 0x99c240e9, 0x649b2a31, 0x305e9f71, 0x2c33901b, 0x65f58550, 0x56eb1fbf, 0x80000001, + 0x0149a190, 0xf7130023, 0x8c1928c0, 0x2046d360, 0x71f0978c, 0x85427c8c, 0x8979f4ce, 0x80000000, + 0x40e50c3b, 0x7711002b, 0x801df8b2, 0x0957eb61, 0x03b58917, 0x40560ad2, 0x2f7afab7, 0x80000001, + 0x1163b657, 0x002a814f, 0x840c5840, 0xd701e40f, 0xc0641169, 0x0000000c, 0x00000000, 0x50000000, + 0x00951014, 0xd76fc017, 0x7011787c, 0xe22dfd26, 0xb2eb8008, 0x3bc26469, 0xae2dffa6, 0x80000000, + 0x802887e9, 0x44c44005, 0x8808b844, 0x7026991d, 0xbbec2106, 0x79e22809, 0xb736227e, 0x80000000, + 0x40668af7, 0xd70e400c, 0x7c1998b3, 0x53407d4e, 0xdb70920d, 0x05e37f2c, 0x0d1ab517, 0x80000001, + 0x39907979, 0x9940bb2d, 0xc1307352, 0xb06ab944, 0x31ab1f25, 0x0d056c2f, 0xe18e45b6, 0x80000000, + 0x22415a40, 0x3ca34dc2, 0x9e1e850b, 0xefba79b4, 0x01b8e94f, 0x424af6d9, 0x6d57371f, 0x80000001, + 0x12fc425d, 0x39d44570, 0xf101631a, 0x3476ef58, 0x1b6dffa9, 0xc2a63551, 0x3b3adde6, 0x80000001, + 0x27fd652c, 0xed6cd041, 0x526de5cd, 0x18d2ebd1, 0xfa59745f, 0x60b1c565, 0x3b20d153, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x574f9e9c, 0x67dc5441, 0x0a27f323, 0xac9452ec, 0xfcf4970f, 0x000ab556, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x86301f53, 0x3b60c1bd, 0x01437b5a, 0xc0b781c8, 0x29fd0fc7, 0xd5bd58fc, 0xd543d127, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x807605bc, 0x38cb6036, 0x2c197096, 0x87a549bb, 0xf73ede37, 0x961c6cdb, 0x2352c23f, 0x80000001, + 0xd492ca49, 0x402ce0a9, 0x54978163, 0x63015c36, 0xd9724df6, 0x00000016, 0x00000000, 0x50000000, + 0x40f30ac8, 0x469a802c, 0x501fe0a6, 0x8d434551, 0x6134f70c, 0x7be69ef1, 0x7be3605f, 0x80000001, + 0x001a0390, 0x04c38005, 0x08062045, 0x542fc12a, 0xf3301908, 0xf633426c, 0xfab2a9ae, 0x80000000, + 0xc409224d, 0x5961c0a2, 0xf46d8a00, 0x5d8e499e, 0x4939e0ad, 0x67d85ef5, 0x4d77214f, 0x80000001, + 0x7b5f7bc2, 0xab41dcc7, 0x858123c9, 0x1d94fd7a, 0x3476653d, 0xfdfa2f57, 0x5b1f14a6, 0x80000001, + 0x392ef6f7, 0x8e895bd3, 0x3315c682, 0x74c5d3da, 0xb47a1359, 0x014aaab7, 0x5486e8bf, 0x80000001, + 0xda834d5e, 0x1afc0866, 0xd14c7ba4, 0x1288b579, 0xacef0b2f, 0xcfa67a91, 0x31aed2e6, 0x80000001, + 0xb531f6c4, 0x6f1ad821, 0xff522f22, 0xdbe949e8, 0x4de1e9ef, 0x2b537dab, 0x60fd5204, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20004000, 0x08001000, 0x02000400, 0x00800100, 0x00300040, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x5555d555, 0x55557555, 0x55555d55, 0x00555755, 0x00200060, 0x00000008, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0xfb04f7b3, 0xfba1daf4, 0xf7e81fdf, 0x00ce7be2, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0x515aab47, 0xe322076d, 0x347b2948, 0x14000028, 0x9421f3e5, 0x1215734e, 0x37b0bbfa, 0x10000000, + 0x7d8ffc23, 0xfdf93e07, 0x0000055d, 0xc7000000, 0xed7f23fe, 0xe8ee937e, 0x00000005, 0x10000000, + 0x92b969ed, 0x230d478b, 0x3069812b, 0x6b00001d, 0x2793e734, 0x47c34ec8, 0x244074c9, 0x10000000, + 0xfd2d7b14, 0x4e301dcc, 0x025e3e60, 0x6f000000, 0xfefed1fe, 0x92bebfbe, 0x00027576, 0x10000000, + 0x02ed06cc, 0x9084e13c, 0xe0133834, 0x3e000005, 0xd292842c, 0x3ff32f47, 0x22747661, 0x10000000, + 0x3e2dfd53, 0x2eacde8c, 0x2af476d6, 0x270000d3, 0x65bf507f, 0xb73ee03f, 0xef02c87e, 0x10000000, + 0x22d5e919, 0xd5e88edc, 0x9cc6aa37, 0xa9000036, 0xc0cd9772, 0xdd925545, 0x11f84a30, 0x10000000, + 0x7be1fa58, 0xfcf13bf2, 0xa261a5b8, 0x7149f8e7, 0x4afe02fe, 0x734e845e, 0x9cb61a35, 0x10002ac4, + 0x18c639d3, 0xe44b4a4a, 0x28887195, 0x2a000025, 0x3902cf86, 0x3af08821, 0x06f81730, 0x10000000, + 0x7b8d7b32, 0x1c341b15, 0xea20751a, 0xb33ff0cd, 0x0000000f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xfe267d48, 0x6d375ced, 0x1662fda1, 0xa45540e9, 0x00093f1b, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6d73622b, 0xf6ab9213, 0x7b800763, 0x007b3f75, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0x7137095d, 0x75de3327, 0xccb22ae1, 0xead5120b, 0x0008c439, 0x00080010, 0x00000000, 0x30000000, + 0x2bc85f36, 0x26cb3265, 0x000001a6, 0xee000000, 0x02f7f275, 0x15695358, 0x00000002, 0x10000000, + 0xfc6a03da, 0xa767958f, 0xc4a412b8, 0x5add7a05, 0x0008a3c0, 0x00080010, 0x00000000, 0x30000000, + 0x2b465e5f, 0xa6dcd1b8, 0x0075027a, 0x7d000000, 0x4579e4f8, 0x83bb433a, 0x0000b124, 0x10000000, + 0x6bdc8363, 0x83e34e60, 0x6097b250, 0x74df1207, 0x0008a5c2, 0x00080010, 0x00000000, 0x30000000, + 0xea206093, 0x466eb0dd, 0x98a78227, 0xfa00001c, 0xb477e076, 0x9f58ad78, 0x27817703, 0x10000000, + 0x7df5979a, 0x65f25492, 0xf8d47378, 0xbfd4620c, 0x5fc6992c, 0x000520ff, 0x00000000, 0x30000000, + 0x701666fe, 0x88a413ac, 0xc5360b6d, 0x761a7e62, 0x66b9a679, 0x883b0a3a, 0x7c2d1832, 0x10000e48, + 0x7fa21828, 0x6407375c, 0x80444a66, 0x00800002, 0x00200040, 0x00080010, 0x00000000, 0x30000000, + 0x6c82e39f, 0xc699d08d, 0x4916d2ae, 0xbd222862, 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x20004000, 0x00a49000, 0x020c0400, 0x806d0134, 0x2026c044, 0x0000000f, 0x00000000, 0x30000000, + 0xb8fcf590, 0xb7a896e3, 0x85092273, 0x27250a61, 0x0003b211, 0x00000000, 0x00000000, 0x00000000, + 0xd880bbc1, 0x080014e8, 0x02000400, 0x00800100, 0x28e2b6c0, 0x0003ea6b, 0x00000000, 0x40000000, + 0x816f9c6a, 0x57cf805a, 0xd440112c, 0x2472176c, 0xacfac5a5, 0xa14a3d78, 0x8ffb7847, 0x80000001, + 0x82b226a1, 0x789220a3, 0x2c38a92a, 0x6e68176d, 0x6af9471e, 0xaa888216, 0x99f38507, 0x80000001, + 0x43a3b09a, 0x19158081, 0x803fd973, 0x275eb367, 0x65f37818, 0x46a5a3b1, 0x55d7208f, 0x80000001, + 0xc2911844, 0x57a300a6, 0xf0532166, 0xe788217d, 0x703c48b0, 0x000b607a, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x45a03b68, 0x10986306, 0xa816406e, 0x67159455, 0x7268d968, 0x00000010, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x464bb958, 0xd99f4127, 0x505439b0, 0x157c8b74, 0x17310d29, 0x99b73973, 0x1e22bda6, 0x80000001, + 0x82b923f1, 0x88afc080, 0x9838f14e, 0x7261ff6c, 0xc8b2ff19, 0x0b45f931, 0x350ef0df, 0x80000001, + 0xb8eff8c9, 0x58ef1ac5, 0x6945cb33, 0x73433cf9, 0x1326ce14, 0xb3d3eeec, 0xbb0e0885, 0x80000000, + 0xd85fcc9a, 0x2ba267f9, 0x9d92e442, 0x41a5d79d, 0x2ef697c2, 0x16d9c317, 0x59f71cbf, 0x80000001, + 0x1a5dd0da, 0x2ba0e8ee, 0x358bb43d, 0xbc9c8d92, 0x57f480bc, 0x12f89b95, 0x5cc71c97, 0x80000001, + 0x2733e470, 0xdd4b0f41, 0xda3c2579, 0x81d371d1, 0x5a67a85f, 0x386592ce, 0x69394004, 0x80000000, + 0x57a53032, 0xf7b6d0fe, 0x0200046b, 0x00800100, 0x5020c0c0, 0x000392ea, 0x00000000, 0x40000000, + 0x80601272, 0xf5a8c012, 0x480ec05a, 0x5233712d, 0x8c72098b, 0x4ef46aae, 0x40770757, 0x80000001, + 0x80ee1b0c, 0x56adc02e, 0x1414f885, 0xf5403d45, 0x4a73db0e, 0x6dc515d0, 0x5d1b3187, 0x80000001, + 0xc1e59f1a, 0x9766004d, 0x242ba0e8, 0x9d4af353, 0x44b34392, 0x53451990, 0x49eb1587, 0x80000001, + 0x807813c2, 0xc5e7c014, 0x0c0fa069, 0xc53d0b3e, 0x7872f60d, 0x46a4b8ef, 0x3626fb9f, 0x80000001, + 0x81181a7c, 0x0810603d, 0x0426d0f1, 0x1458eb71, 0x6f74e415, 0x56358111, 0x447311af, 0x80000001, + 0x458a4479, 0xe054216b, 0xc00a7027, 0x8506081d, 0xbca528e5, 0x0000000e, 0x00000000, 0x50000000, + 0x41c8a598, 0x58274051, 0x082d190b, 0x6b601b78, 0x5f35c298, 0x5c360e32, 0x4b471acf, 0x80000001, + 0x80d617f4, 0x663d4022, 0x140d586b, 0x95340f31, 0xefef3a09, 0xd933584c, 0xf1a295fe, 0x80000000, + 0xc0c89d4e, 0x76b24020, 0x5412888a, 0x913b0942, 0x43b1b88b, 0x2bb3f00e, 0x241ae1a7, 0x80000001, + 0x38a2f894, 0x484a9a8e, 0x1d139aca, 0x9242aaf9, 0x13a6db93, 0xa8a3e2cc, 0xb66a00ad, 0x80000000, + 0x98f64d06, 0x0bcdc871, 0xbda2745f, 0x7aa973a1, 0x85771b44, 0x1a89f8b7, 0x5e7f20ef, 0x80000001, + 0xd2e54357, 0x3a4e45b3, 0x151d3b5d, 0x72866174, 0x33b1c7b0, 0xf6875a93, 0x4d43042e, 0x80000001, + 0xe633e348, 0x3d170eae, 0x82258551, 0xd1cf4dcd, 0xc52137dc, 0x48a4a90b, 0x3ea4d3db, 0x80000000, + 0x96f62877, 0x3781b0b7, 0x25889c39, 0x008000cf, 0xbd2589c0, 0x0004b14c, 0x00000000, 0x40000000, + 0x40288a4b, 0xa4bd2007, 0x1007e835, 0x6424db1c, 0xdbee4186, 0xf5b297ea, 0xf24293d6, 0x80000000, + 0x807811c8, 0x05d1e015, 0xb00e105e, 0xc9365338, 0xa3f1398b, 0x24b3d4ad, 0x1dced61f, 0x80000001, + 0x431b20a6, 0xe8f8c078, 0x8c4e9978, 0x95673d7c, 0x6136b11d, 0x8136d3f3, 0x70274a97, 0x80000001, + 0x00268cb2, 0x9509a005, 0xc004d832, 0x2c1f9d17, 0x932d1084, 0xcbc1fa89, 0xcf4a5e96, 0x80000000, + 0x005d0de8, 0x76338010, 0x74118077, 0x653c0744, 0xaab26e8c, 0x3534306e, 0x2526e38f, 0x80000001, + 0x8ec975ac, 0x1027a0b6, 0x68024808, 0x7d01f409, 0xeee2d162, 0x0000000d, 0x00000000, 0x50000000, + 0xc0979521, 0xa6846018, 0xd4129086, 0x753c9d45, 0xbd326d0c, 0x44143ece, 0x3362f73f, 0x80000001, + 0x402e0eb6, 0x75354008, 0xe0060039, 0x53252f1e, 0xd46e5e85, 0xdaa25caa, 0xdb1273d6, 0x80000000, + 0x40ca1768, 0x16da801a, 0x0c1a28af, 0x4c462d54, 0x7cf35f0f, 0x41c4854f, 0x2e56f217, 0x80000001, + 0xb9d479c2, 0xd889fb6f, 0x9518dae0, 0xa0533316, 0x0669ce9a, 0xe5f4dc8e, 0xd15a2fbd, 0x80000000, + 0x9c1951bc, 0xdc222a46, 0x49d49cac, 0x86b0c3aa, 0x3477dd49, 0x2dca7898, 0x6cb734b7, 0x80000001, + 0x9035be2a, 0xa9b80495, 0x58f2c2ff, 0xee7b5d64, 0xffb03b2a, 0xe726b311, 0x45faf70e, 0x80000001, + 0x283465af, 0x9d4fcfe8, 0x4a42557e, 0x44d2cdd1, 0x56d873df, 0xdb229ce7, 0x2b3ca412, 0x80000000, + 0x58531a79, 0x76644eaf, 0x69e32b72, 0xf276e6ab, 0x53b4dbc2, 0x00085275, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x580f49f3, 0x2d1cc818, 0x99a40487, 0x56afcbc3, 0xf63ae646, 0xbd5a9bd8, 0xb563a28f, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00e28d36, 0x779f0024, 0xf82c00eb, 0xfc553569, 0x99347294, 0x51e52f90, 0x43c70cef, 0x80000001, + 0x7b97fbec, 0x0069a1f7, 0x30025823, 0xfa013208, 0x57b2a4f3, 0x00000016, 0x00000000, 0x50000000, + 0x409f0dc2, 0x76df001a, 0xc81db0b1, 0x70496f5b, 0xe373d590, 0x5d04b56f, 0x491f1747, 0x80000001, + 0x001d07df, 0x156f4005, 0xdc084850, 0x6a2e3535, 0xe3300507, 0x1cb2d4cb, 0x0ddebf1f, 0x80000001, + 0xc2311b27, 0xe94e803b, 0x804a7991, 0xda6ecf8d, 0x3a36d69e, 0x8df69693, 0x7d835bdf, 0x80000001, + 0x3bd3fbdf, 0x5b1bdcdd, 0xb1606bd5, 0xbb9db58c, 0x68f4263f, 0xc168ffb5, 0x3bd6e096, 0x80000001, + 0x6711e0f6, 0x5cadf043, 0xaa04f50a, 0x88b0d3aa, 0x2d77d1c8, 0x389a61b8, 0x6d033d5f, 0x80000001, + 0x94ee468d, 0xca470695, 0xcd282365, 0xd383616d, 0x91f0bf2f, 0x0d971bd2, 0x5ea31adf, 0x80000001, + 0x705b6f28, 0xae319524, 0x8ece5e4c, 0xe9e605e5, 0xa79b5dec, 0xb1027047, 0x4d5cff63, 0x80000000, + 0xa9ec1813, 0xe7ea0faa, 0x6920e2e7, 0xd496c6c9, 0x00300025, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x5c934c96, 0x7eaf0b8d, 0x8eee6e61, 0x3bdf7fea, 0x51bddae5, 0xeacdb29d, 0xe707e01f, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x82a01204, 0x67bda0d0, 0x104ad939, 0xc15c0571, 0xd9746118, 0x6445ac90, 0x4beb1b0f, 0x80000001, + 0xfc6b7e22, 0x3061a1b8, 0xbc01601c, 0xf500f01d, 0xf13a84fb, 0x0000001b, 0x00000000, 0x50000000, + 0x80918876, 0xd638c018, 0xb02580af, 0x37476950, 0x61730212, 0x4084c86f, 0x3436f547, 0x80000001, + 0x001603e7, 0x95254005, 0xd80c5875, 0xdd3c1340, 0xa031b10b, 0x0a339eed, 0xfc62ab2f, 0x80000000, + 0x4496a6d6, 0xeaeca09e, 0x28b612af, 0x2f9f13b6, 0x163b38bc, 0xb35ad3f9, 0xa2178bdf, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x41b61d2e, 0xe74de045, 0xf02740d6, 0x2d595f68, 0x5936ad18, 0x6ee6bc13, 0x4bb32457, 0x80000001, + 0x95aeb091, 0x08001187, 0x02000400, 0x00800100, 0x4a2196c0, 0x00036d6a, 0x00000000, 0x40000000, + 0x41a81c80, 0x573b6038, 0x502380d3, 0xe05f1f70, 0x97f6dc18, 0x49b69fd3, 0x2e12f7c7, 0x80000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0175a3f5, 0xa8126029, 0x701a08cf, 0x52448358, 0xe232dd8d, 0x0a94140e, 0xf91eaa8f, 0x80000000, + 0x81629899, 0x96fcc030, 0xc01ad8ba, 0x9c67f17c, 0x48f88e1a, 0x00079955, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x030a181e, 0x50174186, 0xf404183a, 0xf9046421, 0x341ae2de, 0x00000008, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x423026da, 0xf7d58047, 0xac1a38c3, 0xcb4c0f5f, 0x9432458f, 0xcfd4060e, 0xb00a4e16, 0x80000000, + 0x80f01937, 0x177d4021, 0x501508a7, 0x113fc552, 0x0c31f28c, 0xd8a3a96e, 0xd2366e66, 0x80000000, + 0xb459744f, 0x9490176e, 0x643e30f1, 0xae27dcbb, 0x299fd309, 0xf4922ea8, 0x79958964, 0x80000000, + 0x95dcc756, 0xfb066738, 0xb15dfbd3, 0x0598178d, 0x5834b4ba, 0xd6889555, 0x3382e1ee, 0x80000001, + 0xce39ba65, 0xb93b83b5, 0x18c512a6, 0x176f8554, 0x71ee83a4, 0x6d05cbf0, 0xfeea8b96, 0x80000000, + 0x5fccdb3e, 0x2c520b10, 0x21bcfcad, 0x13b51db1, 0x5996cf4b, 0xec417885, 0x2ad8a7b2, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x808a1940, 0xc608e011, 0x380bf856, 0x582b552a, 0x432e7908, 0xf762f86b, 0xf76a937e, 0x80000000, + 0x94fa299b, 0x382acdc9, 0x0200041f, 0x00800100, 0x47e2e6c0, 0x0004092b, 0x00000000, 0x40000000, + 0x40cd995f, 0x65e8000e, 0x900a385f, 0x4a2b1522, 0x9dacb907, 0xbd42aeaa, 0xd2ea59f6, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc1d1a0ac, 0xf7b3603c, 0x2c1ec0d0, 0x2342ad50, 0x03b2d08e, 0x25e4448f, 0x12a6ccd7, 0x80000001, + 0x009a979b, 0xe5c0200a, 0xc4078852, 0xa5317d33, 0x61b00407, 0xd3d2f14c, 0xc92661ce, 0x80000000, + 0xc09b11cc, 0x46ebc018, 0xb414e099, 0xce415150, 0xc232978d, 0x1a24356e, 0x05eabc37, 0x80000001, + 0x83841959, 0xf0222196, 0x1c072041, 0x41015c0d, 0x24da3ade, 0x00000008, 0x00000000, 0x50000000, + 0x013c1b1f, 0x378be026, 0x0c1758b6, 0xe040d351, 0xa2f26e8c, 0x1484156e, 0x01eeb2e7, 0x80000001, + 0x80861528, 0x45d1c00f, 0xec095851, 0x63278b24, 0xc32e7e06, 0xac32684a, 0xb4f635be, 0x80000000, + 0x80949955, 0x066e200d, 0x980a3064, 0x532d6d32, 0xe52ff507, 0xda52decb, 0xd272673e, 0x80000000, + 0xf5867572, 0xc4e4f852, 0xd4485111, 0x1e2becc3, 0xd760f40b, 0x1c028168, 0x86f5a355, 0x80000000, + 0x5862cb31, 0x2b656884, 0x51839c1a, 0xf49f7b97, 0x8636103e, 0xf6d94d96, 0x48b70136, 0x80000001, + 0xce84ba8b, 0x494803e3, 0x84ca3ab3, 0xbb702354, 0x94ee55a4, 0x80e5e650, 0x0f06a20e, 0x80000001, + 0x20e25c5e, 0x3c580b9c, 0x19c234af, 0xc6b541b0, 0x11d749cb, 0xe0b1df86, 0x2d10a8a2, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0649afa, 0xe5d8c008, 0x9406482c, 0x0210bef2, 0x05260e82, 0xa3b0a1c5, 0x3c293fe5, 0x80000000, + 0xd4182164, 0xc6c38ead, 0x91c0a34b, 0x008000d9, 0xd7e4bc40, 0x0004da6c, 0x00000000, 0x40000000, + 0x002394d5, 0xa3d4c005, 0xdc01b017, 0xe809e0b0, 0xf7dffc00, 0x25407502, 0x39b0f665, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02731d91, 0x38c94066, 0x5c43895f, 0xa458856f, 0x2c74d296, 0x3b2550d1, 0x2976ea8f, 0x80000001, + 0x40ef217f, 0x06c46008, 0xd0066868, 0x552e4f40, 0xac300a85, 0x3c81ccca, 0x7515e406, 0x80000000, + 0x40858be0, 0xb77d2012, 0xfc1b08bf, 0x744dad64, 0xedb47c11, 0x29a53990, 0x196ed297, 0x80000001, + 0x89f63cdd, 0x501b4107, 0x1802d01e, 0xbf019a0d, 0xd21ee166, 0x0000000a, 0x00000000, 0x50000000, + 0xc080903a, 0x268b800f, 0xdc0fc885, 0x3e32e532, 0xff2ee709, 0xee63170b, 0xf4aa954e, 0x80000000, + 0x003089ac, 0xd55d8006, 0x58085848, 0xc5269720, 0x326d3a85, 0xce62332a, 0xd61e670e, 0x80000000, + 0x80fd1693, 0xf7818015, 0x141558b0, 0xa83d774e, 0x9ef1c38b, 0x16a3868d, 0x04aab57f, 0x80000001, + 0xb89c78a5, 0x46d81a72, 0xe07881bc, 0x823fecf6, 0x70659812, 0x72b3a3eb, 0xa3e1d935, 0x80000000, + 0x1e21d472, 0xcc824b45, 0xb5e6d4d5, 0xd5b1ddac, 0x7037dcc9, 0x268a99f8, 0x694b30df, 0x80000001, + 0xcfde3d4c, 0x2979c481, 0x58e91ae3, 0x5973a757, 0xb72e6527, 0x9b461430, 0x1d7eb786, 0x80000001, + 0x23abdf3e, 0xdcb54d55, 0x3dec84ec, 0x15c069bd, 0xd354cc53, 0xfad13ce4, 0x2ce4a912, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x16119827, 0x07572c0c, 0xde23eb4b, 0xbb5072c2, 0x11afd50e, 0x000839d3, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xcb8b2ffa, 0x3c3682fe, 0x111a4b87, 0xa6b7b1ca, 0xeabc0e4c, 0x8f7bfb7a, 0x848763ff, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x007c069c, 0xb7272016, 0xf01cb0aa, 0xb04c8f5f, 0x40f6d614, 0x192696f2, 0xedb2931f, 0x80000000, + 0xccd0acbb, 0x10ed838c, 0x9c3008d8, 0x840d2230, 0x7da8456b, 0x0000000f, 0x00000000, 0x50000000, + 0x005d8a94, 0x95bda00c, 0x9414407c, 0x973e1945, 0xc0b2188d, 0x10741b8e, 0x0142b177, 0x80000001, + 0x0012832e, 0x4452e005, 0x8008b841, 0xca24c90d, 0x88298185, 0x7cf20ca9, 0xbdae3aa6, 0x80000000, + 0x41c71655, 0x5831803b, 0x70432947, 0xa1582970, 0x37b3bf97, 0x3dc4610f, 0x1952dbaf, 0x80000001, + 0xb93f7968, 0xb9ad3adc, 0x10c392a9, 0xcc82a967, 0x0533adb0, 0xbc18bd55, 0x3baadbde, 0x80000001, + 0x6102d6cd, 0xeb8dcd86, 0x3d7bfc21, 0xbe9a6395, 0x84369abc, 0x06f933b6, 0x52231a47, 0x80000001, + 0xd0bbc019, 0x392ee4b3, 0xa0d78ab4, 0xe66e054b, 0xecadb224, 0x8065c50f, 0x0f8aa1b6, 0x80000001, + 0x2fedeedb, 0xfe39f4c7, 0xc2b4264d, 0x4dca83c7, 0x85d58659, 0x41413a24, 0x3220c15b, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20004000, 0x08001000, 0x02000400, 0x00800100, 0x00300040, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x5555d555, 0x55557555, 0x55555d55, 0x00555755, 0x00200060, 0x00000008, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0xf66ff050, 0x48b11753, 0xabdd7fd3, 0x00b171d6, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0x515aab47, 0xe322076d, 0x347b2948, 0x14000028, 0x9421f3e5, 0x1215734e, 0x37b0bbfa, 0x10000000, + 0x3a22f62d, 0x7c03dba7, 0x00000415, 0xc2000000, 0x353e65fd, 0xcb8d83fe, 0x00000004, 0x10000000, + 0x92b969ed, 0x230d478b, 0x3069812b, 0x6b00001d, 0x2793e734, 0x47c34ec8, 0x244074c9, 0x10000000, + 0x7a9676ba, 0x0c729b86, 0x01983500, 0x0f000000, 0xb77e6b7e, 0x4a4e891e, 0x0002173e, 0x10000000, + 0x02ed06cc, 0x9084e13c, 0xe0133834, 0x3e000005, 0xd292842c, 0x3ff32f47, 0x22747661, 0x10000000, + 0x7c9b7aaa, 0x5d8d1d88, 0xf6125db7, 0x9e00007e, 0x143ee97e, 0x389ea71f, 0xabb6495e, 0x10000000, + 0x22d5e919, 0xd5e88edc, 0x9cc6aa37, 0xa9000036, 0xc0cd9772, 0xdd925545, 0x11f84a30, 0x10000000, + 0xb85873ef, 0x6b619a1a, 0x6992bc84, 0xc41c106d, 0x983b657b, 0x325d7fdc, 0x6965ca4d, 0x10001732, + 0x18c639d3, 0xe44b4a4a, 0x28887195, 0x2a000025, 0x3902cf86, 0x3af08821, 0x06f81730, 0x10000000, + 0x385075c0, 0x5b4559ac, 0x75d61496, 0x9a220c94, 0x00000006, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xf884f520, 0x1adcf91f, 0x35b32460, 0xd32f8c96, 0x00035d8d, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xe615547d, 0x847e4e2f, 0x1f62c738, 0x0065ab5f, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0x2e4a0c52, 0x7675d361, 0x38feabab, 0x66dfd221, 0x000de3c1, 0x00080010, 0x00000000, 0x30000000, + 0xe028cb64, 0xf3bdec1d, 0x000000d9, 0x2a000000, 0xd4754172, 0xbd47d115, 0x00000001, 0x10000000, + 0xf9b1032b, 0x1726b51b, 0x38c2c315, 0xf5e82c0c, 0x000edec6, 0x00080010, 0x00000000, 0x30000000, + 0x9e8d4536, 0x43d94b17, 0x003fd120, 0x3e000000, 0x0173b770, 0xd228af56, 0x000085aa, 0x10000000, + 0xab1e0195, 0x641b6d5b, 0x5c8b4208, 0xb6e38009, 0x000ba0c2, 0x00080010, 0x00000000, 0x30000000, + 0xe0454ac5, 0x44126c4c, 0x2449892d, 0x7d00000e, 0x93ecafe7, 0x2ac4b091, 0x07c04719, 0x10000000, + 0x78840833, 0xa6c6f49c, 0x79277b2b, 0xe1d7f816, 0xfd886636, 0x0005c15c, 0x00000000, 0x30000000, + 0x250f5306, 0x75ddceee, 0x30a8720d, 0x550ba633, 0xd92d3b66, 0xe5c557d0, 0x0e783c98, 0x10000078, + 0xb9c89063, 0xb350ee9d, 0xf49a417c, 0x00800005, 0x00200040, 0x00080010, 0x00000000, 0x30000000, + 0x2327d111, 0x253b8cdf, 0x70d96216, 0x8e1bba55, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x20004000, 0x019fb000, 0x020c0400, 0x806d0134, 0x2026c044, 0x0000000f, 0x00000000, 0x30000000, + 0x67a75a97, 0x35de4ead, 0x9d2a8a9d, 0x0d38ea7f, 0x0001641b, 0x00000000, 0x00000000, 0x00000000, + 0xd7f035d9, 0x08001176, 0x02000400, 0x00800100, 0x4c607b40, 0x00038b6a, 0x00000000, 0x40000000, + 0x01001431, 0x57c4e04d, 0xc43e513f, 0x3c711d6a, 0x46fa0a23, 0x81b91d37, 0x67174757, 0x80000001, + 0x0189196c, 0xd87b6070, 0xc8342124, 0x0869df67, 0x98f9a19f, 0xa3887fd6, 0x8ad778f7, 0x80000001, + 0x41ed23b3, 0x5897603c, 0x482d3939, 0x0a5a1f61, 0x7df37615, 0x33b57951, 0x3a6b012f, 0x80000001, + 0x01788eb3, 0x275e605e, 0x303b893d, 0x4d786970, 0xa93b4ea5, 0x0009be58, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x43e53184, 0x505d8206, 0x1814c866, 0x400ed440, 0xdaa04edd, 0x0000000b, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0xc3e5aef7, 0xb89400a8, 0x603b995a, 0xbd5cef34, 0xc668019b, 0x2d54874d, 0xb03dddbd, 0x80000000, + 0x017b9efd, 0xb7f06044, 0xcc25290f, 0xe657ed54, 0x71b09b94, 0xaf453610, 0x074aa986, 0x80000001, + 0xb70af732, 0x48949945, 0xcd2bbb0c, 0xdd3906e1, 0xdb64d110, 0x8bc361ca, 0xa855e815, 0x80000000, + 0x1431440d, 0x0b4e4649, 0xe16563ea, 0xf5a01b98, 0xcc369abd, 0x15c962b6, 0x4d930bff, 0x80000001, + 0x14fec822, 0x5ab52643, 0xd52c1392, 0xba850177, 0xbe31482e, 0xadb6f212, 0x1d7abd0e, 0x80000001, + 0x656162b5, 0x7cfe4dd9, 0x4a0bed36, 0x0cc32fc1, 0x6d629c54, 0x8e64180b, 0x41dce7f3, 0x80000000, + 0x5608b53d, 0xf5ca4d7c, 0x02000356, 0x00800100, 0x25205540, 0x00036aca, 0x00000000, 0x40000000, + 0x404a8b4e, 0x15716011, 0x8411b86a, 0xc03eab3c, 0xfd73bb8e, 0x3524e48f, 0x1d7ede17, 0x80000001, + 0x40a00fa0, 0xf660e023, 0x30175889, 0xc447b74b, 0x51b53211, 0x66458751, 0x4d032097, 0x80000001, + 0xc0f51776, 0xc7064021, 0xd41da8c4, 0xcd489b55, 0xce73950f, 0x35049e6f, 0x230ee317, 0x80000001, + 0x00478bed, 0xd5c4400e, 0x7c0f286d, 0x7a471350, 0x4034420f, 0x29d4d590, 0x0f2acc2f, 0x80000001, + 0x410015aa, 0x18808034, 0x2c286911, 0x4f5ecb76, 0xef353c96, 0x4895a131, 0x3416ff17, 0x80000001, + 0x8473b97f, 0xd03c4109, 0x08093825, 0x18049013, 0x5d1e395a, 0x0000000b, 0x00000000, 0x50000000, + 0xc1441ed5, 0x788fe03b, 0x8c295919, 0xcc5f4d79, 0xecf56496, 0x44e5a691, 0x3166fb5f, 0x80000001, + 0x005211d7, 0xa5b9e011, 0x6c09c052, 0xf5333731, 0x11efe088, 0xcbe3496d, 0xd9ca76be, 0x80000000, + 0x406195bc, 0x8652c011, 0x100db879, 0xa73bc148, 0x63f2568a, 0x1583c62e, 0x047ab9b7, 0x80000001, + 0x7714f70b, 0xd841b95d, 0x7117a2cd, 0xca37fce0, 0x8924058f, 0x6533344a, 0x9d01cf7d, 0x80000000, + 0x5664487b, 0x1b80674c, 0x1580cc23, 0xf5a4259c, 0x0776aac0, 0x11399ed7, 0x54df159f, 0x80000001, + 0x50213ea8, 0xb9b8647c, 0x90e862f5, 0x6f785f62, 0x692f9aa8, 0x99d640b1, 0x1702b22e, 0x80000001, + 0x63675f97, 0xbcb4cd02, 0x71f01cf9, 0x06bf8bbc, 0xe05fb652, 0xf4540caa, 0x3070af92, 0x80000000, + 0xd6013287, 0xf61aaeec, 0x6926fb84, 0x008000b0, 0xb0a3cd40, 0x00043ceb, 0x00000000, 0x40000000, + 0x40268656, 0x44b7c007, 0xa40a2041, 0x192f1d28, 0xfd30aa09, 0x0ec3662c, 0xf8aea467, 0x80000000, + 0x40590ae3, 0xd601e012, 0xa412d070, 0xdd47cb4c, 0xb8347211, 0x429538f0, 0x2eaaf31f, 0x80000001, + 0x41b999d7, 0x48a8403c, 0xc8371133, 0x8a5f5977, 0x4135fc18, 0x5b45fbd2, 0x45af1397, 0x80000001, + 0x001606da, 0x34766005, 0x94046029, 0x55245b19, 0x41af4f85, 0xe222954b, 0xd616709e, 0x80000000, + 0xc0438ad9, 0x164aa00b, 0xec11b87e, 0x9b431151, 0x7533760d, 0x2c04644f, 0x13cacf3f, 0x80000001, + 0x072dcdca, 0x501a407c, 0x38013806, 0xb8016e07, 0x6bdd8ed9, 0x0000000b, 0x00000000, 0x50000000, + 0x004c10cf, 0x264ec00e, 0x64106081, 0xd9445154, 0x9fb3b50d, 0x35447c4f, 0x1d4eddef, 0x80000001, + 0x00198ab9, 0x04cc8005, 0xd804702e, 0x0f25d120, 0x2c6f4705, 0xd1225ecb, 0xc8c65d7e, 0x80000000, + 0xc0841461, 0xa70f4010, 0x7414e0a9, 0x66490960, 0x8533d90e, 0x27a4528f, 0x0ddac8f7, 0x80000001, + 0x3849783e, 0xd8161a46, 0x9cf4f29a, 0x3f444efd, 0x18e70a14, 0x9d93dbac, 0xb161f8e5, 0x80000000, + 0xda7eceb3, 0x3c01e971, 0x59c0f48d, 0x88adf7a7, 0xf477ba47, 0x289a4577, 0x66cb2d17, 0x80000001, + 0xce53bb04, 0x695f43c3, 0xecd372c1, 0x66738f59, 0x0faf2e26, 0xa1961af1, 0x1bf2b82e, 0x80000001, + 0xa52b61fa, 0x2ce86e08, 0x6e0d252a, 0xacc4dbc2, 0x38936ed5, 0x9301bdc5, 0x1ffc84f2, 0x80000000, + 0x95cca4f0, 0xe6be6fdc, 0x25b05398, 0x487bce85, 0x8fae583d, 0x00070911, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x0734ad1d, 0x2a8b6120, 0x38834a32, 0x3971178e, 0x06b67321, 0x89e6aab3, 0x78b753e7, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x80790afe, 0xa8204013, 0xe82378ec, 0x28591f72, 0x8df56e95, 0x48159d31, 0x3256f8d7, 0x80000001, + 0xda4df507, 0xe012408c, 0x5801301a, 0x9801300f, 0xd4e9fb6e, 0x00000010, 0x00000000, 0x50000000, + 0x80538c9d, 0xf7266009, 0x2811b894, 0xe443cd5d, 0xec735e0c, 0x4664114e, 0x2c96f19f, 0x80000001, + 0x001a8740, 0x35e8c005, 0x8c087857, 0x3b2fe13c, 0xdaf04307, 0xf792accb, 0xe5f288d6, 0x80000000, + 0x413c17e5, 0x28db401e, 0xd029091a, 0xfd59b377, 0x07750894, 0x58d54111, 0x422b0f67, 0x80000001, + 0x3938f93e, 0x3a3cbaee, 0x953a5b84, 0x2f72ed4d, 0x98ad9b29, 0x28d61db0, 0xec1e5f9e, 0x80000000, + 0x614d5905, 0x2c22ed0a, 0x75c3cc9a, 0xb0aaefa4, 0x86f707c4, 0x1149e457, 0x576718e7, 0x80000001, + 0x9160c0d7, 0x69bd84f5, 0x40f23301, 0x3a789960, 0x4e2f5929, 0xc5364a91, 0x330ad9f6, 0x80000001, + 0x29e5e7a7, 0x8d7df0fa, 0x7e58bda4, 0x63d2e5d1, 0x649694df, 0x3a518705, 0x331cc173, 0x80000000, + 0x9f4f968a, 0x56c2ce94, 0x2db9a33c, 0x7e84c0f1, 0x00300027, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x973f494e, 0x0ce72731, 0x1999b453, 0x6fa35dba, 0xe57a67bd, 0xac09e157, 0x9c27849f, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x01020b2c, 0xc77e602e, 0x7c2548e1, 0x7a52a965, 0xb8748513, 0x502532b0, 0x2fd6f13f, 0x80000001, + 0xf9657c59, 0xe06b61ee, 0xd0006012, 0xf101fe1d, 0x2ef1c7f5, 0x00000015, 0x00000000, 0x50000000, + 0xc0640a19, 0xd6f4000d, 0x681678a0, 0x273fc554, 0x42f2698c, 0x24c3ae2e, 0x0e52c3d7, 0x80000001, + 0x001003ef, 0x05b9e005, 0xa006f05a, 0x422f293b, 0xc4304606, 0xf102756b, 0xe0928306, 0x80000000, + 0x42fc9f70, 0x49dae04d, 0xcc5781cf, 0x8471758f, 0xa7762fa0, 0x62764a72, 0x4aaf1bc7, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x01a9961d, 0x372f0054, 0xa030e8f2, 0x74588d60, 0x63f6e617, 0x6c067a53, 0x3ca32777, 0x80000001, + 0x9a063186, 0x08000f1e, 0x02000400, 0x00800100, 0x12de0740, 0x00026128, 0x00000000, 0x40000000, + 0xc13116b0, 0xb6e78026, 0x1c1708ac, 0xb850ad60, 0xb6b55091, 0x35d57e91, 0xf4aeaf8f, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00e39b75, 0x578f0017, 0x841118a0, 0x383da54e, 0xa6726d8b, 0xf413d86e, 0xe5a68f66, 0x80000000, + 0x00a413d0, 0x16380013, 0x100a5064, 0xe6594778, 0x8474f110, 0x00055bb1, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x03449586, 0xd01220f1, 0xc807803e, 0xc8020c14, 0xbc14ec55, 0x00000005, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x40e09b72, 0x46736018, 0xec09d064, 0xdd31e72e, 0x09ac4587, 0xc072f3cb, 0x5cdd99f5, 0x80000000, + 0xc07b9318, 0x46b4400f, 0xb00b106e, 0xd0322f3b, 0x856fd987, 0x9d62ecac, 0xad5a35fe, 0x80000000, + 0x32a971ed, 0x856d1618, 0xd050413c, 0xd125eab2, 0x421e2888, 0xb971d767, 0x693d63dc, 0x80000000, + 0xd24241ef, 0x3a5ae573, 0x8d161354, 0x7c8c497e, 0x3d735032, 0xd5d7eb54, 0x2a4ed4d6, 0x80000001, + 0x0a11318b, 0x18844249, 0x68830a0f, 0x1667e147, 0xd36c099f, 0x1f73e82d, 0xc27e3916, 0x80000000, + 0x9df7d86c, 0x8bcf8a2f, 0x099a7c55, 0xe5a657a7, 0xeb10e63f, 0x2d30a4c2, 0x1264600a, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0869232, 0x75774018, 0xa4178872, 0xc93e1d38, 0xa1f3378f, 0x1bf4bfcf, 0xf8feb4df, 0x80000000, + 0xd7a42fc8, 0x26a9abdb, 0x0200045f, 0x00800100, 0x5763cfc0, 0x0003d2cb, 0x00000000, 0x40000000, + 0x006c11fd, 0x3535600a, 0x60098051, 0x41390132, 0xc131bc8a, 0xb873908d, 0xb8964b4e, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0cd9aa6, 0xc743c016, 0x88102090, 0x883b9549, 0xe0b2e00b, 0xf7a3ff0e, 0xe992937e, 0x80000000, + 0x00449110, 0xf5350006, 0x2c05283c, 0x82306b2c, 0x9af0dd87, 0xcf72f9ac, 0xb43a4996, 0x80000000, + 0xc06e8ecb, 0x16e0e00f, 0x6410888b, 0x9a43eb55, 0x3473708d, 0x11543e6f, 0xfc5ab907, 0x80000000, + 0x43c31614, 0x801540c7, 0xf406002a, 0xf800d00a, 0xd594d0d4, 0x00000005, 0x00000000, 0x50000000, + 0xc096970a, 0x16b3e012, 0xb80d2879, 0xc03b0b47, 0x67728c0a, 0xeee3cece, 0xd7427dae, 0x80000000, + 0x00310c76, 0x94b12006, 0xb404d82f, 0x44200710, 0xec6dd704, 0x8001f249, 0x99220ebe, 0x80000000, + 0x40489110, 0xc5aa8005, 0xf0060844, 0x322a092b, 0xbcafeb06, 0xc372a44b, 0xb97e48ce, 0x80000000, + 0xb382f339, 0x7527d698, 0xc8531934, 0x832a30bb, 0xc11f010b, 0xc4120c67, 0x6d8d6724, 0x80000000, + 0xd59646be, 0x8b27a70d, 0xe95e5be4, 0xc79a0992, 0xbe756aba, 0xd0c8a6d5, 0x34aae1b6, 0x80000001, + 0x0a99b252, 0xd860e270, 0x9c939233, 0x95633f44, 0x296d2d9e, 0x2374712e, 0xd4e250be, 0x80000000, + 0x5e47d8ca, 0xdbcea9f7, 0xcd84cc59, 0x6ca72ba7, 0x1e94fac4, 0x5c617dc5, 0x182c7132, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x803a117d, 0x564ee005, 0x38062829, 0xe22e7d18, 0xefabdf0d, 0x62920009, 0x92a1e0c6, 0x80000000, + 0xd23b29e7, 0x95f6cc77, 0xd98a7ae2, 0x0080010c, 0xaa257fc0, 0x0004ab4c, 0x00000000, 0x40000000, + 0xc0520eed, 0xf37ce005, 0xe803d01d, 0x552000da, 0x1eac6f85, 0x532212a9, 0xa63622de, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc1879a1f, 0x882e2024, 0x481ea8eb, 0xea46ed5b, 0x79f2da0d, 0x0b43f36e, 0xfabaa70f, 0x80000000, + 0x4081a283, 0x96452007, 0x0404484f, 0x6334b346, 0x60b24708, 0x8922b18c, 0x822dca36, 0x80000000, + 0x80578b13, 0x375f400c, 0xbc132898, 0x1347a15d, 0x2533ce8f, 0x07850f30, 0x05bebb5f, 0x80000001, + 0xc4b11c7c, 0x100a2095, 0x1c027812, 0x1f010c11, 0xe419895c, 0x00000007, 0x00000000, 0x50000000, + 0x80679127, 0x968b4007, 0xc408f063, 0x8a2bb32f, 0xb7efdf06, 0xda12bf2b, 0xcee66396, 0x80000000, + 0x001f0692, 0x24d76005, 0x6405c836, 0x4523cd19, 0x24adde05, 0xa2f2288a, 0xaa522546, 0x80000000, + 0x006511c0, 0xe6ac8006, 0x4008d865, 0x6130093c, 0x32f0e187, 0xe2a2df6c, 0xd74a6e9e, 0x80000000, + 0x360af5ef, 0x450cb8c3, 0x3c4438ff, 0x452734b9, 0x74e1100a, 0xfec268c8, 0x801d8e1c, 0x80000000, + 0xd9164cb8, 0x7beee8b0, 0x39a1ac60, 0x2faa41a0, 0x5e76db45, 0x1b89e357, 0x5a93187f, 0x80000001, + 0x4d0ab813, 0x688fe33f, 0xd4a9425b, 0x38601139, 0x2b6b191d, 0x043491ee, 0xd39a3c06, 0x80000000, + 0x9f37d818, 0x5bf16b0b, 0x95aabc88, 0x35a8c1a1, 0xc6d2c144, 0xa750dd43, 0x1f84885a, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0xcf59182d, 0xc6550dcc, 0x9acb0b05, 0x6f14150b, 0x13e7e69f, 0x00062a8f, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x02959538, 0x09ef8068, 0x8083c20c, 0xd0727b88, 0xfef4f122, 0x1e564851, 0x0f8abd47, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x402702ea, 0xb6edc005, 0x3c13708d, 0x29497150, 0x70b4f990, 0xc6f52e4f, 0xfc0e9a66, 0x80000000, + 0x8727a72f, 0x2032c1e9, 0x000468ac, 0x26018423, 0x1d17b3d8, 0x00000007, 0x00000000, 0x50000000, + 0x001d0583, 0xa57a0005, 0xf408404f, 0x9427c726, 0x6bae5285, 0xbba23e8a, 0xcf8a5dfe, 0x80000000, + 0x000e0194, 0xd3df2005, 0xe006c835, 0x301f2af3, 0x6de7ae04, 0x7eb18bc8, 0xa0ce1f1e, 0x80000000, + 0x004c071f, 0x76e0c008, 0x1c10188d, 0x053a114c, 0x0131738a, 0xe7e33b8d, 0xd8ea682e, 0x80000000, + 0x750274ca, 0x06347831, 0xf48491c6, 0xdf4d4511, 0x82a6a399, 0x9ca434ac, 0xb195f7fd, 0x80000000, + 0xd924cb3f, 0x0b312951, 0x415e23dd, 0x5498718e, 0x39f6cc38, 0xef78f156, 0x3d0f08b6, 0x80000001, + 0xcc64b61b, 0xf8378326, 0xf49cb239, 0x7d5f3737, 0xbe6a5b1d, 0x0fd4960d, 0xd70e3ede, 0x80000000, + 0x200c5b10, 0x4ca72bba, 0x8dbc1cd7, 0x66ad79a7, 0x1d8de445, 0x7d606d42, 0x1a30726a, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20004000, 0x08001000, 0x02000400, 0x00800100, 0x00300040, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x5555d555, 0x55557555, 0x55555d55, 0x00555755, 0x00200060, 0x00000008, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0xae8165cc, 0xa5317199, 0x47bf37b3, 0x00879db5, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0x515aab47, 0xe322076d, 0x347b2948, 0x14000028, 0x9421f3e5, 0x1215734e, 0x37b0bbfa, 0x10000000, + 0xb4d9edf7, 0x195e17c0, 0x0000025a, 0x7c000000, 0x697cad7b, 0xfc5b78dc, 0x00000002, 0x10000000, + 0x92b969ed, 0x230d478b, 0x3069812b, 0x6b00001d, 0x2793e734, 0x47c34ec8, 0x244074c9, 0x10000000, + 0x3145e75d, 0x78035439, 0x00993a7e, 0xf7000000, 0x1f7b787a, 0x8b7c215c, 0x000108ec, 0x10000000, + 0x02ed06cc, 0x9084e13c, 0xe0133834, 0x3e000005, 0xd292842c, 0x3ff32f47, 0x22747661, 0x10000000, + 0xf675f270, 0xb9e7f8af, 0xf501437a, 0x8a000030, 0xce7c9efc, 0x32fbdd7c, 0x44854c94, 0x10000000, + 0x22d5e919, 0xd5e88edc, 0x9cc6aa37, 0xa9000036, 0xc0cd9772, 0xdd925545, 0x11f84a30, 0x10000000, + 0x321beb1c, 0x68399475, 0x08bb3a9a, 0x6b07e626, 0xd7774376, 0xfa6bb6f9, 0x3ae1320b, 0x1000098a, + 0x18c639d3, 0xe44b4a4a, 0x28887195, 0x2a000025, 0x3902cf86, 0x3af08821, 0x06f81730, 0x10000000, + 0x70bfe8d9, 0x18df7555, 0x610dcb41, 0xc40cb443, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xefb965d6, 0x684dd451, 0x59165312, 0x961ae453, 0x00016706, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x157d3389, 0xf17e6691, 0xdeaf8e37, 0x0023bcd2, 0x00000000, 0x00000000, 0x00000000, 0x20000000, + 0xf2db96f9, 0xb77bd5e1, 0xc1419453, 0xabeace39, 0x00176dd1, 0x00080010, 0x00000000, 0x30000000, + 0x909329ba, 0x1176c59f, 0x00000040, 0xed000000, 0x996ab7e1, 0x4742da4b, 0x00000000, 0x10000000, + 0x3c020361, 0xa8dcd8a6, 0x0d0cc40c, 0x46ea3c1b, 0x0018a2d4, 0x00080010, 0x00000000, 0x30000000, + 0x0dca216c, 0x5155a465, 0x0016785b, 0xea000000, 0x0be7d35d, 0xaaa315cd, 0x00000990, 0x10000000, + 0xaf890102, 0x6434cf16, 0xd47c5a38, 0xc3e52009, 0x0013a94c, 0x00080010, 0x00000000, 0x30000000, + 0xcd192107, 0xf14ca447, 0x9c1b3060, 0x33000006, 0x58a60f5c, 0x36a1364b, 0x00e00628, 0x10000000, + 0xbbfc0449, 0x57c59487, 0x10fbab73, 0x36dba014, 0x3c8fc041, 0x0008d97e, 0x00000000, 0x30000000, + 0x0ff5a5ba, 0x91e4457f, 0x803988a2, 0xf2054415, 0x699d81d8, 0x5b4247e7, 0x05b416d0, 0x10000092, + 0x2f8784cd, 0x42600be8, 0x1c55b133, 0x00800005, 0x00200040, 0x00080010, 0x00000000, 0x30000000, + 0x92fead9b, 0x727ec6dc, 0x1c5f60e5, 0x2c0f382a, 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x20004000, 0x03a11000, 0x020c0400, 0x806d0134, 0x2026c044, 0x0000000f, 0x00000000, 0x30000000, + 0xd4332fa7, 0xb2e2a707, 0x48787926, 0x9117c833, 0x0000630b, 0x00000000, 0x00000000, 0x00000000, + 0x9765b12f, 0x08000c36, 0x02000400, 0x00800100, 0x47dc3ac0, 0x00028c28, 0x00000000, 0x40000000, + 0x00958cf1, 0xb7386025, 0x5c2b211a, 0x8062fd55, 0x72f8b099, 0x6ba6e3f4, 0x0a76d43f, 0x80000001, + 0xc116110f, 0xf88ac04d, 0xb037e134, 0xf472616d, 0xfffb8aa0, 0xb348a2d7, 0x84df83e7, 0x80000001, + 0x80fda026, 0x7952a017, 0xc81ee927, 0x115e7d79, 0xab74e594, 0x1b954071, 0x0a36cab7, 0x80000001, + 0x409706a4, 0xc613e021, 0xb418e8c7, 0x1161c357, 0xd5ba8a96, 0x000785f5, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x4311281f, 0xa0222107, 0x300d7848, 0x6a061425, 0x345fd464, 0x0000000a, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x81b122b0, 0x96e98038, 0x2c1868c0, 0xbf3dd902, 0xec21358d, 0x24928b29, 0x5228fc2b, 0x80000000, + 0x80af1883, 0x2801001b, 0x781530d6, 0xd64f0f5a, 0x3bb0080e, 0xa1b4222f, 0xd4f67356, 0x80000000, + 0xf4177515, 0x27a0f6f8, 0x0cbe824e, 0x9c27c0bc, 0x1ce0b009, 0x27b20fc8, 0x781d8c1d, 0x80000000, + 0x50fe3e2a, 0x9b0c84d1, 0xf92bdb9f, 0xa59a9596, 0x67b6e5b8, 0x1088d1d6, 0x3feb00df, 0x80000001, + 0x4bcab5ad, 0x58cda29e, 0x88818233, 0x595dad4e, 0x59ea869c, 0xc364304e, 0xbdde2b95, 0x80000000, + 0x9fe9dbb6, 0xac318a6e, 0x698f946f, 0xdf9f4d9a, 0xeb15a7bb, 0x88b13204, 0x178c7462, 0x80000000, + 0x56dfb0f2, 0x1517ed4a, 0x02000314, 0x00800100, 0xc4dc4f40, 0x000261c7, 0x00000000, 0x40000000, + 0x004d8734, 0x267bc00f, 0x8014a8a0, 0xa4448550, 0x7772c78d, 0xed23c6ae, 0xd3ca758e, 0x80000000, + 0x408f8a27, 0x17988024, 0x2425f0d8, 0xfe598365, 0xffb73c96, 0x5f660d92, 0x369f0d27, 0x80000001, + 0x40db1bba, 0x785a2013, 0xa81830dd, 0x1a4a1165, 0x5033768e, 0x0ed41e0f, 0xf5c6a82f, 0x80000000, + 0x8046886f, 0xa68ac00b, 0x9c0f0888, 0x1f477b5c, 0xc6f36a8d, 0xddb3dfce, 0xc5da6266, 0x80000000, + 0xc092111f, 0x3886c017, 0x5c19f0eb, 0x5e572374, 0xc3745111, 0x1dc4dfd0, 0x03e2bf2f, 0x80000001, + 0x435eac2f, 0x7023a0cc, 0x3c067026, 0xb6045214, 0x609ee661, 0x0000000a, 0x00000000, 0x50000000, + 0x40981570, 0x88612019, 0xf417e0e1, 0xbc531371, 0xc233d40f, 0x0314458f, 0xebe29c7f, 0x80000000, + 0x80450ddc, 0xc667c00c, 0x18099060, 0x95327134, 0x9eadfa07, 0x7fe2968b, 0xa8b6269e, 0x80000000, + 0xc0569456, 0x476b200a, 0xf40b8888, 0x9b3df556, 0xc0b21609, 0xe813588d, 0xd1d27386, 0x80000000, + 0xb48e74cd, 0xd7a3978c, 0x50d05a57, 0x3c2956c1, 0xf2dfa18a, 0xe3321687, 0x6ed97494, 0x80000000, + 0x52c9c34f, 0xcb62e5a1, 0x5155ebe9, 0x939e5d97, 0x5db6423c, 0xf7491156, 0x460b016e, 0x80000001, + 0xcac0b3e7, 0x1873c277, 0x0090ba3b, 0xa35f013e, 0x696bf59b, 0x0b04a46e, 0xccba360e, 0x80000000, + 0x9d155807, 0xcbd669b7, 0xd583ac41, 0x81a5219d, 0x1c580740, 0x5ed1b346, 0x18a47052, 0x80000000, + 0x97e8b21b, 0xa5052b08, 0x55457339, 0x008000c2, 0xd2de93c0, 0x0002c6e8, 0x00000000, 0x40000000, + 0x80290460, 0xa5c4c006, 0xf00d7868, 0x1d373d3d, 0x2231bc0a, 0xef232f0d, 0xd94280de, 0x80000000, + 0xc07207c1, 0x876f8014, 0x402260ca, 0x61584961, 0xebf6c617, 0x57263552, 0x334b0097, 0x80000001, + 0xc1b3223f, 0x98e7e023, 0xbc29292c, 0x865d5d7e, 0xabf5b115, 0x45957f51, 0x24a6ebaf, 0x80000001, + 0x001684a3, 0xe5906005, 0xe0079849, 0x5b2fff38, 0x27b17c87, 0xdac2d74c, 0xc5c65fae, 0x80000000, + 0x40430a12, 0x6774e007, 0x2c0f909b, 0x9e469f60, 0x31739c0c, 0x0f74110f, 0xf4b2a25f, 0x80000000, + 0x4440b1f4, 0xb0156089, 0x1401f00b, 0x3c03c20f, 0xc4defde1, 0x0000000a, 0x00000000, 0x50000000, + 0x805c9066, 0xf771e00a, 0x5c1090a2, 0x3e47e761, 0x10f3648d, 0x0bd410af, 0xf602a6f7, 0x80000000, + 0x001a881f, 0x057ac005, 0x5404f03a, 0x1d28872c, 0xc0ee9805, 0xa5422d6a, 0xa78a28c6, 0x80000000, + 0x00611290, 0xe7782009, 0x400e9899, 0xe0440360, 0x77b31b0b, 0x05e3c48e, 0xea8695ff, 0x80000000, + 0xb71bf731, 0x871a1960, 0x98b29a0c, 0x522f54d2, 0x8c62d40c, 0x41a2ba09, 0x8cb9afcd, 0x80000000, + 0x163148c5, 0x6bd30725, 0x45960456, 0xeea921a4, 0x96374cc3, 0x273a0477, 0x5dbb2817, 0x80000001, + 0x4bbb357d, 0x78ab42ce, 0x78a5fa5b, 0x5064df45, 0x202c951f, 0x40151ecf, 0xeaa26546, 0x80000000, + 0x217fddae, 0x4c6d6be5, 0x4dcd6cc5, 0x4bb5b1b0, 0x7093c8cb, 0x55013fc4, 0x16d46b6a, 0x80000000, + 0x54552c3e, 0x7617adee, 0x19669321, 0xc46870b5, 0xa7e83f56, 0x0004f10d, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x02fd27ac, 0x696e004e, 0xfc34895e, 0x78634582, 0x39f5e818, 0x5b85dc92, 0x3e7f0d2f, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x40638a4a, 0x285d4009, 0x0819b8d1, 0xc6552f71, 0xa674f891, 0x2b64ed90, 0x0e2ecea7, 0x80000001, + 0x04809fb9, 0xc0092059, 0x6c018012, 0x9801ea17, 0xb2e41068, 0x0000000c, 0x00000000, 0x50000000, + 0x405b108e, 0x67a1a008, 0xa00ee09a, 0x0b443360, 0xbdb3768c, 0x2283e5ce, 0x08c2c07f, 0x80000001, + 0x0015059b, 0x15eec005, 0x6c070050, 0x002b5f36, 0xc6af2806, 0xc1023eaa, 0xbbd2448e, 0x80000000, + 0xc0d41666, 0x9842c00e, 0xa81818d1, 0x574e116b, 0x90b3fc8f, 0x27b44bef, 0x0a5ac64f, 0x80000001, + 0xb703f74c, 0xb8083918, 0xb88c41f6, 0xe04a270a, 0x1c272515, 0x9483c52c, 0xa8a1ec4d, 0x80000000, + 0x9987ce33, 0xfbcf88c0, 0x9d843443, 0x61a4379f, 0xd4768e3f, 0x11396f16, 0x4a8f0f0f, 0x80000001, + 0xce823be0, 0xe922a3ba, 0xa0c29a9f, 0xa66c534f, 0x0aad9ea2, 0x77a58990, 0x06e295e6, 0x80000001, + 0x643a6130, 0x4cb0ed45, 0xd1ec3500, 0x24bce5b9, 0xc61297d0, 0xdc60e3a3, 0x234097e2, 0x80000000, + 0xd4d71a30, 0x55fa6cd8, 0xbdf8b3b4, 0x676ba6bf, 0x00300043, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x8b43ba60, 0x4b0482a5, 0x108bea6f, 0x938383a1, 0x51f87a29, 0x7347ca15, 0x61b73a67, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x8061087e, 0x07c7800c, 0xb01c68c9, 0x3c4fe56a, 0xaaf3af91, 0x2d04818f, 0x12c2cacf, 0x80000001, + 0x4f37cfba, 0x602fe167, 0xd4006008, 0xd701b824, 0xafaad0ef, 0x00000010, 0x00000000, 0x50000000, + 0xc04b8d39, 0x76c6a005, 0x600b787a, 0x21355549, 0xfcf16a08, 0x0bb2fcac, 0xf6329d17, 0x80000000, + 0x001004b4, 0x55cac005, 0xe4054048, 0xcf283731, 0x7ceee004, 0xc291ff8a, 0xb95a471e, 0x80000000, + 0x81781b10, 0x489f601a, 0x5c26a919, 0x4c52536d, 0xb8341f11, 0x30a4892f, 0x1a9ed96f, 0x80000001, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x015292b2, 0x46b3602e, 0x8c18e0b5, 0xe4520d5d, 0x9ff44d12, 0x90058092, 0x14032807, 0x80000001, + 0x9744ac58, 0x08000923, 0x02000400, 0x00800100, 0xb41627c0, 0x00012984, 0x00000000, 0x40000000, + 0x808591da, 0xf57c400c, 0x6c06384d, 0xbf3aff52, 0x3b34ec8a, 0xdb733b31, 0xdb6e492e, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0098164f, 0x4806a00b, 0xc40e589c, 0xe845035e, 0xf033e98b, 0x1fb43acf, 0xda22abe7, 0x80000000, + 0xc05e0ff0, 0x14fa0006, 0xf403582b, 0x4c530759, 0x496db711, 0x00024932, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x8250131b, 0x50050095, 0x94028026, 0x98008408, 0xd014d55b, 0x00000004, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00479268, 0x55122005, 0x1c03182b, 0xfb2c4d0f, 0x20dc9883, 0xaab2b946, 0xaaae0006, 0x80000000, + 0x00480e9e, 0xd69cc005, 0xb005a84e, 0x1d2daf39, 0xed323b86, 0x1d1281ac, 0x94b2165e, 0x80000000, + 0x72c471a1, 0x04a0545f, 0xcc2288a3, 0xa4167082, 0x821a6983, 0xc6e10fe5, 0x6371947c, 0x80000000, + 0x8d893972, 0x7a2983a5, 0x68f8c325, 0x0c8ad187, 0x02b4dd2e, 0xcde81e35, 0xf882e406, 0x80000000, + 0x486a25dd, 0x68f8016f, 0x0c497a39, 0x5b456d27, 0x99a33311, 0xaab26669, 0x55560006, 0x80000000, + 0xda4fd2c6, 0xfc0ee89a, 0xad6434c0, 0xdfaaabaa, 0x31ca8cb2, 0xeb806842, 0x0cf04189, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80fb8f5a, 0x26616026, 0xc81a80a0, 0xe350ed50, 0x27f59c12, 0xc474c0d2, 0xe9766d7e, 0x80000000, + 0x57d8b163, 0xb51d0acd, 0x020003c4, 0x00800100, 0xfd9d9840, 0x00024607, 0x00000000, 0x40000000, + 0x809494a4, 0xa5b58008, 0x7406784d, 0x15328339, 0xc9b00b86, 0x863238aa, 0x5979a196, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40b517ad, 0x77b3200e, 0x2c0f1098, 0xb23bbb4d, 0x9d337a89, 0x56f37fed, 0xc3a27ab6, 0x80000000, + 0xc0621397, 0xa5d40005, 0xf8039837, 0x462a4930, 0xff30ed04, 0x3d716bca, 0x70a5c296, 0x80000000, + 0x40578dbc, 0x47aa0009, 0x8c0ed090, 0x4b436359, 0xebb33c0d, 0xcbf44a2e, 0xc62e6476, 0x80000000, + 0x0328945a, 0xf01000bb, 0x38060829, 0x4e006208, 0x661868de, 0x00000006, 0x00000000, 0x50000000, + 0x407d1217, 0x0720a00d, 0x4c0b487c, 0x0539494d, 0xe6b1d609, 0xfe23380d, 0xb83a5ebe, 0x80000000, + 0x00150646, 0x24c2e005, 0xcc021822, 0xd21b9f0b, 0xe8edaa82, 0x4f619b09, 0x7939d986, 0x80000000, + 0x002b0b22, 0x55eae005, 0xc404b040, 0xa3270736, 0xc2709404, 0xb742358a, 0x8dba2f56, 0x80000000, + 0xb1727333, 0x94ca94bf, 0xf03fb107, 0x0f1dee9c, 0x4b1bee87, 0xc4e18e86, 0x6f3d78bc, 0x80000000, + 0x527ec23f, 0x6abe257b, 0x45187b63, 0x4f90a387, 0x5ab407b6, 0xe7e7c1d4, 0x17ced0c6, 0x80000001, + 0x4babae97, 0xc8d66317, 0xe880320d, 0xc547af4e, 0x95ae9311, 0xf934d4f1, 0xbf2658c5, 0x80000000, + 0xdda45453, 0xabf3aa0b, 0xc1000384, 0x78a32f89, 0xadcf4645, 0xbb60caa3, 0x09a44329, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0f59478, 0xd7b82015, 0x28150063, 0xc647af5c, 0x00300012, 0xd174aab0, 0xba31d17d, 0x80000000, + 0x4f292720, 0x45770a71, 0xd55a33ab, 0x008000d3, 0xcba11a40, 0x00031109, 0x00000000, 0x40000000, + 0x417f13bd, 0xd8a3e026, 0x002220cc, 0x00400150, 0xb6fb6d90, 0x38e4924d, 0x71c9c726, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80f797e6, 0x7801a010, 0x441208af, 0x4343dd53, 0xcb328a0c, 0xc723990d, 0xd36267fe, 0x80000000, + 0xc115907d, 0x35d9801b, 0x101088bb, 0xd4584796, 0x74745d08, 0x00045d31, 0x5555555c, 0x80000000, + 0x00760a63, 0xa7d2a00c, 0xa81020a2, 0x00481561, 0x3434b08e, 0xef647f90, 0xf1f2ba96, 0x80000000, + 0x446a9897, 0xc005a054, 0x7004e823, 0x6701e012, 0x785c1fe1, 0x00000008, 0x00000000, 0x50000000, + 0x00470ccc, 0x66494005, 0xc8079855, 0x6b2c8335, 0x482fb307, 0x65429e6b, 0x8b35ea0e, 0x80000000, + 0x001082dd, 0x24ca6005, 0xf004b03a, 0xe420c919, 0x906bc203, 0x4a4191e8, 0x6f25bffe, 0x80000000, + 0x00330b76, 0x9670e005, 0x8c063059, 0x6e30e740, 0xb7306486, 0x9d32782b, 0x97b60ed6, 0x80000000, + 0x72057290, 0x54293654, 0x683040e8, 0x5f24cca6, 0xd01fc709, 0xd8822367, 0x679d6a4c, 0x80000000, + 0x1735cb26, 0x6be6a760, 0x4980e435, 0x049fbf99, 0xd3758bc0, 0xdfb8e315, 0x3e8ef816, 0x80000001, + 0x486da860, 0x06b241de, 0x2063a1bb, 0x334c091f, 0x8b679892, 0xf662fccb, 0x666984d4, 0x80000000, + 0x1ba2d616, 0x9b06a73e, 0x8937cc06, 0x918db36e, 0x288f3b29, 0xf1f058e2, 0x10b85851, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x0f459fb8, 0xb453ebc7, 0xc6d552fe, 0xcb12c76c, 0x6764b1b4, 0x0004a8cc, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40f48fa9, 0x0914a018, 0xc425792d, 0x2b4d0b67, 0x88b2948e, 0xca03db8e, 0xd2366506, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x001f042f, 0xf7478005, 0x880d9883, 0xb33e293c, 0x5333ee0d, 0xc4f3edcd, 0xe76658a6, 0x80000000, + 0x027790be, 0xc008609a, 0xa4055040, 0x3a00700f, 0x0fd6cf54, 0x00000006, 0x00000000, 0x50000000, + 0x001a04c0, 0x754d8005, 0xe804883e, 0xb323af1d, 0x8ead7584, 0x53620809, 0x86dde546, 0x80000000, + 0x000800e1, 0xf4244003, 0xa8033029, 0xe81bbf06, 0x55ac1082, 0x4ef15f48, 0x6f31c3fe, 0x80000000, + 0x0035869b, 0x56870005, 0xc007e862, 0xc02e2d38, 0x6bafa706, 0xaaf20a2a, 0xa39a1f9e, 0x80000000, + 0x719af114, 0x35b4d61e, 0xc860a96d, 0x68205ab3, 0x2a9c1406, 0x5ea12366, 0x58a13414, 0x80000000, + 0x51f23de6, 0x1aa065d8, 0x8d02cb5a, 0xaa90ed8c, 0xc3f51132, 0x83679954, 0x0b56a19e, 0x80000001, + 0xc6d82b5c, 0x87112115, 0xc454316a, 0x7f4134ff, 0x83a3fa8d, 0xfae24709, 0x818d9514, 0x80000000, + 0x19f24eb4, 0x7b76c7ad, 0xd13773f5, 0xdc906197, 0xac49e431, 0xf7b06661, 0x0f505731, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20004000, 0x08001000, 0x02000400, 0x00800100, 0x00300040, 0x00040010, 0x00000000, 0x40000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x5555d555, 0x55557555, 0x55555d55, 0x00555755, 0x00200060, 0x00000008, 0x00000000, 0x50000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, 0x00300020, 0x00040010, 0x80020006, 0x80000000, +}; + +static void hal_av1d_release_res(void *hal) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + RK_U32 max_cnt = p_hal->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + RK_U32 i = 0; + + for (i = 0; i < max_cnt; i++) + MPP_FREE(reg_ctx->reg_buf[i].regs); + + BUF_PUT(reg_ctx->cdf_rd_def_base); + BUF_PUT(reg_ctx->bufs); + for (i = 0; i < max_cnt; i++) + BUF_PUT(reg_ctx->rcb_bufs[i]); + vdpu38x_rcb_calc_deinit(reg_ctx->rcb_ctx); + + BUF_PUT(reg_ctx->filter_mem); + + if (reg_ctx->cdf_segid_bufs) { + hal_bufs_deinit(reg_ctx->cdf_segid_bufs); + reg_ctx->cdf_segid_bufs = NULL; + } + if (reg_ctx->colmv_bufs) { + hal_bufs_deinit(reg_ctx->colmv_bufs); + reg_ctx->colmv_bufs = NULL; + } + if (reg_ctx->origin_bufs) { + hal_bufs_deinit(reg_ctx->origin_bufs); + reg_ctx->origin_bufs = NULL; + } + + MPP_FREE(p_hal->reg_ctx); +} + +MPP_RET vdpu38x_av1d_deinit(void *hal) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + if (p_hal) { + hal_av1d_release_res(p_hal); + } + + return MPP_OK; +} + +MPP_RET vdpu38x_av1d_reset(void *hal) +{ + (void)hal; + + return MPP_OK; +} + +MPP_RET vdpu38x_av1d_flush(void *hal) +{ + (void)hal; + + return MPP_OK; +} + +MPP_RET vdpu38x_av1d_control(void *hal, MpiCmd cmd_type, void *param) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, NULL == p_hal); + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO : { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + RK_U32 imgwidth = mpp_frame_get_width((MppFrame)param); + RK_U32 imgheight = mpp_frame_get_height((MppFrame)param); + + AV1D_DBG(AV1D_DBG_LOG, "control info: fmt %d, w %d, h %d\n", fmt, imgwidth, imgheight); + if ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV422SP) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, (MppFrame)param, 16); + } else if (imgwidth > 1920 || imgheight > 1088) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + } + break; + } + case MPP_DEC_GET_THUMBNAIL_FRAME_INFO: { + vdpu38x_update_thumbnail_frame_info((MppFrame)param); + } break; + case MPP_DEC_SET_OUTPUT_FORMAT : { + } break; + default : { + } break; + } + +__RETURN: + return ret = MPP_OK; +} + +static RK_S32 GetRelativeDist(DXVA_PicParams_AV1 *dxva, RK_S32 a, RK_S32 b) +{ + if (!dxva->order_hint_bits) return 0; + const RK_S32 bits = dxva->order_hint_bits - 1; + + RK_S32 diff = a - b; + RK_S32 m = 1 << bits; + diff = (diff & (m - 1)) - (diff & m); + return diff; +} + +MPP_RET vdpu38x_av1d_uncomp_hdr(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva, + RK_U64 *data, RK_U32 len) +{ + RockchipSocType soc_type; + BitputCtx_t bp; + RK_S32 i, j; + (void) p_hal; + + soc_type = mpp_get_soc_type(); + + mpp_set_bitput_ctx(&bp, data, len); + + /* sequence header */ + mpp_put_bits(&bp, dxva->coding.current_operating_point, 12); + mpp_put_bits(&bp, dxva->coding.use_128x128_superblock, 1); + mpp_put_bits(&bp, dxva->coding.filter_intra, 1); + mpp_put_bits(&bp, dxva->coding.intra_edge_filter, 1); + mpp_put_bits(&bp, dxva->coding.interintra_compound, 1); + mpp_put_bits(&bp, dxva->coding.masked_compound, 1); + mpp_put_bits(&bp, dxva->coding.dual_filter, 1); + mpp_put_bits(&bp, dxva->enable_order_hint, 1); + mpp_put_bits(&bp, dxva->coding.jnt_comp, 1); + mpp_put_bits(&bp, dxva->coding.enable_ref_frame_mvs, 1); + { + RK_S32 order_hint_bits_minus_1 = dxva->order_hint_bits ? (dxva->order_hint_bits - 1) : 0; + + mpp_put_bits(&bp, order_hint_bits_minus_1, 3); + } + { + RK_U32 skip_loop_filter = 0; // TODO: control by user + RK_U32 enable_cdef = !skip_loop_filter && !dxva->coded_lossless; + RK_U32 enable_cdef_y = dxva->cdef.y_strengths[0].primary || dxva->cdef.y_strengths[0].secondary; + RK_U32 enable_cdef_uv = dxva->cdef.uv_strengths[0].primary || dxva->cdef.uv_strengths[0].secondary; + + enable_cdef = enable_cdef && (dxva->cdef.bits || enable_cdef_y || enable_cdef_uv); + mpp_put_bits(&bp, enable_cdef, 1); + } + mpp_put_bits(&bp, (dxva->bitdepth > 8) ? (dxva->bitdepth - 8) : 0, 3); + { + RK_U32 yuv_format = 0; + + if (dxva->format.mono_chrome) + yuv_format = 0; // 400 + else if (dxva->format.subsampling_y == 1 && dxva->format.subsampling_y == 1) + yuv_format = 1; // 420 + else if (dxva->format.subsampling_x == 1) + yuv_format = 2; // 422 + else + yuv_format = 3; // 444 + + mpp_put_bits(&bp, yuv_format, 2); + } + + mpp_put_bits(&bp, dxva->film_grain.matrix_coefficients, 8); + mpp_put_bits(&bp, dxva->coding.film_grain_en, 1); + + /* frame uncompresss header */ + { + RK_U32 frame_is_intra = dxva->format.frame_type == AV1_KEY_FRAME || + dxva->format.frame_type == AV1_INTRA_ONLY_FRAME; + + mpp_put_bits(&bp, frame_is_intra, 1); + mpp_put_bits(&bp, dxva->coding.disable_cdf_update, 1); + mpp_put_bits(&bp, dxva->coding.screen_content_tools, 1); + mpp_put_bits(&bp, dxva->coding.integer_mv || frame_is_intra, 1); + mpp_put_bits(&bp, dxva->order_hint, 8); + if (soc_type == ROCKCHIP_SOC_RK3538 || + soc_type == ROCKCHIP_SOC_RK3572 || + soc_type == ROCKCHIP_SOC_RK3539) { + /* + * Hardware bugs in the vdpu384b need to be fixed; + * the hardened CDF (the default CDF) is temporarily disabled. + */ + mpp_put_bits(&bp, 0, 1); + } + mpp_put_bits(&bp, dxva->width, 16); + mpp_put_bits(&bp, dxva->height, 16); + mpp_put_bits(&bp, dxva->coding.superres, 1); + mpp_put_bits(&bp, dxva->superres_denom, 5); + mpp_put_bits(&bp, dxva->upscaled_width, 16); + mpp_put_bits(&bp, dxva->coding.high_precision_mv, 1); + mpp_put_bits(&bp, dxva->coding.intrabc, 1); + } + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) + mpp_put_bits(&bp, dxva->ref_frame_valued ? dxva->ref_frame_idx[i] : (RK_U32) - 1, 3); + + mpp_put_bits(&bp, dxva->interp_filter, 3); + mpp_put_bits(&bp, dxva->coding.switchable_motion_mode, 1); + mpp_put_bits(&bp, dxva->coding.use_ref_frame_mvs, 1); + + { + RK_U32 mapped_idx = 0; + + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + mpp_put_bits(&bp, dxva->frame_refs[i].order_hint, 8); + } + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + mapped_idx = dxva->ref_frame_idx[i]; + mpp_put_bits(&bp, dxva->ref_order_hint[mapped_idx], 8); + } + } + + for (i = 0; i < AV1_REFS_PER_FRAME; ++i) { + if (!dxva->order_hint_bits) { + dxva->ref_frame_sign_bias[i] = 0; + } else { + if (dxva->frame_refs[i].Index >= 0) { + RK_S32 ref_frame_offset = dxva->frame_refs[dxva->ref_frame_idx[i]].order_hint; + RK_S32 rel_off = GetRelativeDist(dxva, ref_frame_offset, dxva->order_hint); + + dxva->ref_frame_sign_bias[i] = (rel_off <= 0) ? 0 : 1; + } + } + mpp_put_bits(&bp, dxva->ref_frame_sign_bias[i], 1); + } + + mpp_put_bits(&bp, dxva->coding.disable_frame_end_update_cdf, 1); + + /* quantization params */ + mpp_put_bits(&bp, dxva->quantization.base_qindex, 8); + mpp_put_bits(&bp, dxva->quantization.y_dc_delta_q, 7); + mpp_put_bits(&bp, dxva->quantization.u_dc_delta_q, 7); + mpp_put_bits(&bp, dxva->quantization.u_ac_delta_q, 7); + mpp_put_bits(&bp, dxva->quantization.v_dc_delta_q, 7); + mpp_put_bits(&bp, dxva->quantization.v_ac_delta_q, 7); + mpp_put_bits(&bp, dxva->quantization.using_qmatrix, 1); + + /* segmentation params */ + mpp_put_bits(&bp, dxva->segmentation.enabled, 1); + mpp_put_bits(&bp, dxva->segmentation.update_map, 1); + mpp_put_bits(&bp, dxva->segmentation.temporal_update, 1); + + { + RK_U32 mi_rows = MPP_ALIGN(dxva->width, 8) >> AV1_MI_SIZE_LOG2; + RK_U32 mi_cols = MPP_ALIGN(dxva->height, 8) >> AV1_MI_SIZE_LOG2; + /* index 0: AV1_REF_FRAME_LAST - AV1_REF_FRAME_LAST */ + RK_U32 prev_mi_rows = MPP_ALIGN(dxva->frame_refs[0].width, 8) >> AV1_MI_SIZE_LOG2; + RK_U32 prev_mi_cols = MPP_ALIGN(dxva->frame_refs[0].height, 8) >> AV1_MI_SIZE_LOG2; + RK_U32 use_prev_segmentation_ids = dxva->segmentation.enabled && dxva->primary_ref_frame && + (mi_rows == prev_mi_rows) && + (mi_cols == prev_mi_cols); + + mpp_put_bits(&bp, use_prev_segmentation_ids, 1); + } + + /* Segmentation data update */ + for (i = 0; i < AV1_MAX_SEGMENTS; i++) + mpp_put_bits(&bp, dxva->segmentation.feature_mask[i], 8); + + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + mpp_put_bits(&bp, dxva->segmentation.feature_data[i][0], 9); + mpp_put_bits(&bp, dxva->segmentation.feature_data[i][1], 7); + mpp_put_bits(&bp, dxva->segmentation.feature_data[i][2], 7); + mpp_put_bits(&bp, dxva->segmentation.feature_data[i][3], 7); + mpp_put_bits(&bp, dxva->segmentation.feature_data[i][4], 7); + mpp_put_bits(&bp, dxva->segmentation.feature_data[i][5], 3); + } + mpp_put_bits(&bp, dxva->segmentation.last_active, 3); + mpp_put_bits(&bp, dxva->segmentation.preskip, 1); + mpp_put_bits(&bp, dxva->quantization.delta_q_present, 1); + if (dxva->quantization.delta_q_present) + mpp_put_bits(&bp, dxva->quantization.delta_q_res, 2); + else + mpp_put_bits(&bp, 1 << dxva->quantization.delta_q_res, 2); + + /* delta lf params */ + mpp_put_bits(&bp, dxva->loop_filter.delta_lf_present, 1); + mpp_put_bits(&bp, 1 << dxva->loop_filter.delta_lf_res, 2); + mpp_put_bits(&bp, dxva->loop_filter.delta_lf_multi, 1); + mpp_put_bits(&bp, dxva->coded_lossless, 1); + for (i = 0; i < AV1_MAX_SEGMENTS; ++i) { + RK_S32 qindex, lossless; + + if (dxva->segmentation.feature_mask[i] & 0x1) { + qindex = (dxva->quantization.base_qindex + dxva->segmentation.feature_data[i][AV1_SEG_LVL_ALT_Q]); + } else { + qindex = dxva->quantization.base_qindex; + } + qindex = mpp_clip_uint_pow2(qindex, 8); + lossless = qindex == 0 && dxva->quantization.y_dc_delta_q == 0 && + dxva->quantization.u_dc_delta_q == 0 && + dxva->quantization.v_dc_delta_q == 0 && + dxva->quantization.u_ac_delta_q == 0 && + dxva->quantization.v_ac_delta_q == 0; + + mpp_put_bits(&bp, lossless, 1); + } + mpp_put_bits(&bp, dxva->all_lossless, 1); + + /* segmentation dequant */ + mpp_put_bits(&bp, dxva->quantization.qm_y, 4); + mpp_put_bits(&bp, dxva->quantization.qm_u, 4); + mpp_put_bits(&bp, dxva->quantization.qm_v, 4); + mpp_put_bits(&bp, dxva->loop_filter.filter_level[0], 6); + mpp_put_bits(&bp, dxva->loop_filter.filter_level[1], 6); + mpp_put_bits(&bp, dxva->loop_filter.filter_level_u, 6); + mpp_put_bits(&bp, dxva->loop_filter.filter_level_v, 6); + mpp_put_bits(&bp, dxva->loop_filter.sharpness_level, 3); + mpp_put_bits(&bp, dxva->loop_filter.mode_ref_delta_enabled, 1); + + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + mpp_put_bits(&bp, dxva->loop_filter.ref_deltas[i], 7); + + for (i = 0; i < AV1_MAX_MODE_LF_DELTAS; i++) + mpp_put_bits(&bp, dxva->loop_filter.mode_deltas[i], 7); + + /* cdef params */ + mpp_put_bits(&bp, dxva->cdef.damping + 3, 3); + mpp_put_bits(&bp, dxva->cdef.bits, 2); + + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, dxva->cdef.y_strengths[i].primary, 4); + + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, dxva->cdef.uv_strengths[i].primary, 4); + + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, dxva->cdef.y_strengths[i].secondary, 2); + + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, dxva->cdef.uv_strengths[i].secondary, 2); + + { + RK_U32 uses_lr = 0; + + for (i = 0; i < (dxva->format.mono_chrome ? 1 : 3); i++) + uses_lr |= (dxva->loop_filter.frame_restoration_type[i] != AV1_RESTORE_NONE) ? 1 : 0; + mpp_put_bits(&bp, uses_lr, 1); + } + for (i = 0; i < 3; ++i) + mpp_put_bits(&bp, dxva->loop_filter.frame_restoration_type[i], 2); + for (i = 0; i < 2; ++i) // 0:32x32, 1:64x64, 2:128x128, 3:256x256 + mpp_put_bits(&bp, dxva->loop_filter.log2_restoration_unit_size[i], 2); + + mpp_put_bits(&bp, dxva->coding.tx_mode, 2); + mpp_put_bits(&bp, dxva->coding.reference_mode, 1); + mpp_put_bits(&bp, dxva->skip_ref0, 3); + mpp_put_bits(&bp, dxva->skip_ref1, 3); + mpp_put_bits(&bp, dxva->coding.skip_mode, 1); + mpp_put_bits(&bp, dxva->coding.warped_motion, 1); + mpp_put_bits(&bp, dxva->coding.reduced_tx_set, 1); + + /* gm_type and gm_params */ + for (i = 0; i < AV1_REFS_PER_FRAME; ++i) + mpp_put_bits(&bp, dxva->frame_refs[i].wmtype, 2); + + for (i = 0; i < AV1_REFS_PER_FRAME; ++i) + for (j = 0; j < 6; j++) + mpp_put_bits(&bp, dxva->frame_refs[i].wmmat_val[j], 17); + + /* film_grain_params */ + { + mpp_put_bits(&bp, dxva->film_grain.apply_grain, 1); + mpp_put_bits(&bp, dxva->film_grain.grain_seed, 16); + mpp_put_bits(&bp, dxva->film_grain.update_grain, 1); + mpp_put_bits(&bp, dxva->film_grain.num_y_points, 4); + + for (i = 0; i < 14; i++) + mpp_put_bits(&bp, dxva->film_grain.scaling_points_y[i][0], 8); + + for (i = 0; i < 14; i++) + mpp_put_bits(&bp, dxva->film_grain.scaling_points_y[i][1], 8); + + mpp_put_bits(&bp, dxva->film_grain.chroma_scaling_from_luma, 1); + mpp_put_bits(&bp, dxva->film_grain.num_cb_points, 4); + + for (i = 0; i < 10; ++i) + mpp_put_bits(&bp, dxva->film_grain.scaling_points_cb[i][0], 8); + + for (i = 0; i < 10; ++i) + mpp_put_bits(&bp, dxva->film_grain.scaling_points_cb[i][1], 8); + + mpp_put_bits(&bp, dxva->film_grain.num_cr_points, 4); + for (i = 0; i < 10; ++i) + mpp_put_bits(&bp, dxva->film_grain.scaling_points_cr[i][0], 8); + + for (i = 0; i < 10; ++i) + mpp_put_bits(&bp, dxva->film_grain.scaling_points_cr[i][1], 8); + + mpp_put_bits(&bp, dxva->film_grain.scaling_shift_minus8, 2); + mpp_put_bits(&bp, dxva->film_grain.ar_coeff_lag, 2); + for (i = 0; i < 24; ++i) + mpp_put_bits(&bp, dxva->film_grain.ar_coeffs_y[i], 8); + + for (i = 0; i < 25; ++i) + mpp_put_bits(&bp, dxva->film_grain.ar_coeffs_cb[i], 8); + + for (i = 0; i < 25; ++i) + mpp_put_bits(&bp, dxva->film_grain.ar_coeffs_cr[i], 8); + + mpp_put_bits(&bp, dxva->film_grain.ar_coeff_shift_minus6, 2); + mpp_put_bits(&bp, dxva->film_grain.grain_scale_shift, 2); + mpp_put_bits(&bp, dxva->film_grain.cb_mult, 8); + mpp_put_bits(&bp, dxva->film_grain.cb_luma_mult, 8); + mpp_put_bits(&bp, dxva->film_grain.cb_offset, 9); + mpp_put_bits(&bp, dxva->film_grain.cr_mult, 8); + mpp_put_bits(&bp, dxva->film_grain.cr_luma_mult, 8); + mpp_put_bits(&bp, dxva->film_grain.cr_offset, 9); + mpp_put_bits(&bp, dxva->film_grain.overlap_flag, 1); + mpp_put_bits(&bp, dxva->film_grain.clip_to_restricted_range, 1); + } + + /* ref frame info */ + for (i = 0; i < AV1_NUM_REF_FRAMES; ++i) + mpp_put_bits(&bp, dxva->frame_ref_state[i].upscaled_width, 16); + + for (i = 0; i < AV1_NUM_REF_FRAMES; ++i) + mpp_put_bits(&bp, dxva->frame_ref_state[i].frame_height, 16); + + for (i = 0; i < AV1_NUM_REF_FRAMES; ++i) + mpp_put_bits(&bp, dxva->frame_ref_state[i].frame_width, 16); + + for (i = 0; i < AV1_NUM_REF_FRAMES; ++i) + mpp_put_bits(&bp, dxva->frame_ref_state[i].frame_type, 2); + + for (i = 0; i < AV1_NUM_REF_FRAMES; ++i) { + mpp_put_bits(&bp, dxva->frame_refs[i].lst_frame_offset, 8); + mpp_put_bits(&bp, dxva->frame_refs[i].lst2_frame_offset, 8); + mpp_put_bits(&bp, dxva->frame_refs[i].lst3_frame_offset, 8); + mpp_put_bits(&bp, dxva->frame_refs[i].gld_frame_offset, 8); + mpp_put_bits(&bp, dxva->frame_refs[i].bwd_frame_offset, 8); + mpp_put_bits(&bp, dxva->frame_refs[i].alt2_frame_offset, 8); + mpp_put_bits(&bp, dxva->frame_refs[i].alt_frame_offset, 8); + } + + { + RK_U32 mapped_idx = 0; + RK_U32 mapped_frame_width[8] = {0}; + RK_U32 mapped_frame_height[8] = {0}; + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + mapped_idx = dxva->ref_frame_idx[i]; + mapped_frame_width[mapped_idx] = dxva->frame_ref_state[mapped_idx].frame_width; + mapped_frame_height[mapped_idx] = dxva->frame_ref_state[mapped_idx].frame_height; + } + for (i = 0; i <= AV1_REFS_PER_FRAME; ++i) { + RK_U32 hor_scale, ver_scale; + + if (dxva->coding.intrabc) { + hor_scale = dxva->width; + ver_scale = dxva->height; + } else { + hor_scale = mapped_frame_width[i]; + ver_scale = mapped_frame_height[i]; + } + hor_scale = ((hor_scale << AV1_REF_SCALE_SHIFT) + dxva->width / 2) / dxva->width; + ver_scale = ((ver_scale << AV1_REF_SCALE_SHIFT) + dxva->height / 2) / dxva->height; + + mpp_put_bits(&bp, hor_scale, 16); + mpp_put_bits(&bp, ver_scale, 16); + } + } + + mpp_put_bits(&bp, (dxva->frame_header_size + 7) >> 3, 10); + /* tile info */ + mpp_put_bits(&bp, dxva->tiles.cols, 7); + mpp_put_bits(&bp, dxva->tiles.rows, 7); + mpp_put_bits(&bp, dxva->tiles.context_update_id, 12); + mpp_put_bits(&bp, dxva->tiles.tile_sz_mag + 1, 3); + mpp_put_bits(&bp, dxva->tiles.cols * dxva->tiles.rows, 13); + mpp_put_bits(&bp, dxva->tile_cols_log2 + dxva->tile_rows_log2, 12); + + for (i = 0; i < 64; i++) + mpp_put_bits(&bp, dxva->tiles.widths[i], 7); + + for (i = 0; i < 64; i++) + mpp_put_bits(&bp, dxva->tiles.heights[i], 10); + + mpp_put_align(&bp, 128, 0); + + return MPP_OK; +} + +MPP_RET vdpu38x_av1d_cdf_setup(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + size_t segid_size = (MPP_ALIGN(dxva->width, 128) / 128) * \ + (MPP_ALIGN(dxva->height, 128) / 128) * \ + 32 * 16; + size_t size = ALL_CDF_SIZE + segid_size; + MPP_RET ret = MPP_ERR_UNKNOW; + + /* the worst case is the frame is error with whole frame */ + if (reg_ctx->cdf_segid_size < size) { + if (reg_ctx->cdf_segid_bufs) { + hal_bufs_deinit(reg_ctx->cdf_segid_bufs); + reg_ctx->cdf_segid_bufs = NULL; + } + + hal_bufs_init(®_ctx->cdf_segid_bufs); + if (reg_ctx->cdf_segid_bufs == NULL) { + mpp_err_f("cdf bufs init fail"); + goto __RETURN; + } + + reg_ctx->cdf_segid_size = size; + reg_ctx->cdf_segid_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(reg_ctx->cdf_segid_bufs, reg_ctx->cdf_segid_count, 1, &size); + } + +__RETURN: + return ret; +} + +/* + * cdf buf structure: + * + * base_addr0 +--------------------------+ + * 434x128bit | def_non_coeff_cdf | + * base_addr0+433 +--------------------------+ + * + * base_addr1 +--------------------------+ + * 354x128bit | def_coeff_cdf_0 | + * | (base_q_idx <= 20) | + * +--------------------------+ + * 354x128bit | def_coeff_cdf_1 | + * | (20 < base_q_idx <= 60) | + * +--------------------------+ + * 354x128bit | def_coeff_cdf_2 | + * | (60 < base_q_idx <= 120) | + * +--------------------------+ + * 354x128bit | def_coeff_cdf_3 | + * | (base_q_idx > 120) | + * base_addr1+1415 +--------------------------+ + */ +void vdpu38x_av1d_set_cdf_segid(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva, + RK_U32 *coef_rd_base, RK_U32 *coef_wr_base, + RK_U32 *segid_last_base, RK_U32 *segid_cur_base, + RK_U32 *noncoef_rd_base, RK_U32 *noncoef_wr_base) +{ + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + RK_U32 coeff_cdf_idx = 0; + RK_U32 mapped_idx = 0; + HalBuf *cdf_buf = NULL; + MppBuffer buf_tmp = NULL; + RK_U32 i = 0; + + /* use para in decoder */ +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "cabac_cdf_in.dat"; + + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + } +#endif + if (dxva->format.frame_type == AV1_FRAME_KEY) + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + reg_ctx->ref_info_tbl[i].cdf_valid = 0; + /* def coeff cdf idx */ + coeff_cdf_idx = dxva->quantization.base_qindex <= 20 ? 0 : + dxva->quantization.base_qindex <= 60 ? 1 : + dxva->quantization.base_qindex <= 120 ? 2 : 3; + + if (dxva->format.frame_type == AV1_FRAME_KEY || + dxva->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + *noncoef_rd_base = mpp_buffer_get_fd(reg_ctx->cdf_rd_def_base); + *coef_rd_base = mpp_buffer_get_fd(reg_ctx->cdf_rd_def_base); +#ifdef DUMP_VDPU38X_DATAS + { + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(reg_ctx->cdf_rd_def_base), + 8 * NON_COEF_CDF_SIZE, 128, 0, 0); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (RK_U8 *)mpp_buffer_get_ptr(reg_ctx->cdf_rd_def_base) + + NON_COEF_CDF_SIZE + COEF_CDF_SIZE * coeff_cdf_idx, + 8 * COEF_CDF_SIZE, 128, 0, 1); + } +#endif + } else { + mapped_idx = dxva->ref_frame_idx[dxva->primary_ref_frame]; + + coeff_cdf_idx = reg_ctx->ref_info_tbl[mapped_idx].coeff_idx; + if (!dxva->coding.disable_frame_end_update_cdf && + reg_ctx->ref_info_tbl[mapped_idx].cdf_valid && + dxva->frame_refs[mapped_idx].Index != (RK_S8)0xff && + dxva->frame_refs[mapped_idx].Index != 0x7f) { + cdf_buf = hal_bufs_get_buf(reg_ctx->cdf_segid_bufs, dxva->frame_refs[mapped_idx].Index); + buf_tmp = cdf_buf->buf[0]; + } else { + buf_tmp = reg_ctx->cdf_rd_def_base; + } + *noncoef_rd_base = mpp_buffer_get_fd(buf_tmp); + *coef_rd_base = mpp_buffer_get_fd(buf_tmp); + *segid_last_base = mpp_buffer_get_fd(buf_tmp); +#ifdef DUMP_VDPU38X_DATAS + { + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(buf_tmp), + 8 * NON_COEF_CDF_SIZE, 128, 0, 0); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (RK_U8 *)mpp_buffer_get_ptr(buf_tmp) + + NON_COEF_CDF_SIZE + COEF_CDF_SIZE * coeff_cdf_idx, + 8 * COEF_CDF_SIZE, 128, 0, 1); + } +#endif + } + cdf_buf = hal_bufs_get_buf(reg_ctx->cdf_segid_bufs, dxva->CurrPic.Index7Bits); + *noncoef_wr_base = mpp_buffer_get_fd(cdf_buf->buf[0]); + *coef_wr_base = mpp_buffer_get_fd(cdf_buf->buf[0]); + *segid_cur_base = mpp_buffer_get_fd(cdf_buf->buf[0]); + + /* byte, 434 x 128 bit = 434 x 16 byte */ + mpp_dev_set_reg_offset(p_hal->cfg->dev, 178, NON_COEF_CDF_SIZE + COEF_CDF_SIZE * coeff_cdf_idx); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 179, NON_COEF_CDF_SIZE); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 181, ALL_CDF_SIZE); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 182, ALL_CDF_SIZE); + + /* update params sync with "update buffer" */ + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (dxva->refresh_frame_flags & (1 << i)) { + if (dxva->coding.disable_frame_end_update_cdf) { + if (dxva->show_existing_frame && dxva->format.frame_type == AV1_FRAME_KEY) + reg_ctx->ref_info_tbl[i].coeff_idx + = reg_ctx->ref_info_tbl[dxva->frame_to_show_map_idx].coeff_idx; + else + reg_ctx->ref_info_tbl[i].coeff_idx = coeff_cdf_idx; + } else { + reg_ctx->ref_info_tbl[i].cdf_valid = 1; + reg_ctx->ref_info_tbl[i].coeff_idx = 0; + } + } + } + +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "cdf_rd_def.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(reg_ctx->cdf_rd_def_base), + (NON_COEF_CDF_SIZE + COEF_CDF_SIZE * 4) * 8, 128, 0, 0); + } +#endif + +} + +MPP_RET vdpu38x_av1d_colmv_setup(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + size_t mv_size; + MPP_RET ret = MPP_ERR_UNKNOW; + + /* the worst case is the frame is error with whole frame */ + mv_size = MPP_ALIGN(dxva->width, 64) / 64 * MPP_ALIGN(dxva->height, 64) / 64 * 1024; + if (reg_ctx->colmv_bufs == NULL || reg_ctx->colmv_size < mv_size) { + if (reg_ctx->colmv_bufs) { + hal_bufs_deinit(reg_ctx->colmv_bufs); + reg_ctx->colmv_bufs = NULL; + } + + hal_bufs_init(®_ctx->colmv_bufs); + if (reg_ctx->colmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + goto __RETURN; + } + reg_ctx->colmv_size = mv_size; + reg_ctx->colmv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(reg_ctx->colmv_bufs, reg_ctx->colmv_count, 1, &mv_size); + } + +__RETURN: + return ret; +} + +void vdpu38x_av1d_rcb_setup(Av1dHalCtx *p_hal, HalTaskInfo *task, + DXVA_PicParams_AV1 *dxva, Vdpu38xRcbRegSet *rcb_regs, + Vdpu38xRcbCalc_f func) +{ + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + RK_U32 max_cnt = p_hal->fast_mode ? VDPU_FAST_REG_SET_CNT : 1; + MppBuffer rcb_buf; + RK_U32 i; + + /* update rcb info */ + { + RcbTileInfo tl_info; + MppFrame mframe; + MppFrameFormat mpp_fmt; + Vdpu38xFmt rcb_fmt; + RK_U32 uses_lr = 0; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_fmt = mpp_frame_get_fmt(mframe); + rcb_fmt = vdpu38x_fmt_mpp2hal(mpp_fmt); + for (i = 0; i < (dxva->format.mono_chrome ? 1 : 3); i++) + uses_lr |= (dxva->loop_filter.frame_restoration_type[i] != AV1_RESTORE_NONE) ? 1 : 0; + + vdpu38x_rcb_reset(reg_ctx->rcb_ctx); + + /* update general info */ + vdpu38x_rcb_set_pic_w(reg_ctx->rcb_ctx, dxva->width); + vdpu38x_rcb_set_pic_h(reg_ctx->rcb_ctx, dxva->height); + vdpu38x_rcb_set_fmt(reg_ctx->rcb_ctx, rcb_fmt); + vdpu38x_rcb_set_bit_depth(reg_ctx->rcb_ctx, dxva->bitdepth); + + /* update cur spec info */ + vdpu38x_rcb_set_lr_en(reg_ctx->rcb_ctx, uses_lr ? 1 : 0); + vdpu38x_rcb_set_upsc_en(reg_ctx->rcb_ctx, dxva->use_superres); + + /* add tile info */ + /* Simplify the calculation. */ + tl_info.lt_x = 0; + tl_info.lt_y = 0; + tl_info.w = dxva->width; + tl_info.h = dxva->height; + vdpu38x_rcb_set_tile_dir(reg_ctx->rcb_ctx, 0); + vdpu38x_rcb_add_tile_info(reg_ctx->rcb_ctx, &tl_info); + vdpu38x_rcb_register_calc_handle(reg_ctx->rcb_ctx, func); + } + + vdpu38x_rcb_calc_exec(reg_ctx->rcb_ctx, ®_ctx->rcb_buf_size); + + for (i = 0; i < max_cnt; i++) { + rcb_buf = reg_ctx->rcb_bufs[i]; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + reg_ctx->rcb_bufs[i] = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, reg_ctx->rcb_buf_size); + reg_ctx->rcb_bufs[i] = rcb_buf; + } + + rcb_buf = p_hal->fast_mode ? reg_ctx->rcb_bufs[task->dec.reg_index] + : reg_ctx->rcb_bufs[0]; + vdpu38x_setup_rcb(reg_ctx->rcb_ctx, rcb_regs, p_hal->cfg->dev, rcb_buf); + + return; +} diff --git a/mpp/hal/rkdec/av1d/hal_av1d_com.h b/mpp/hal/rkdec/av1d/hal_av1d_com.h new file mode 100644 index 000000000..cac7dce59 --- /dev/null +++ b/mpp/hal/rkdec/av1d/hal_av1d_com.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AV1D_COM_H +#define HAL_AV1D_COM_H + +#include "rk_mpi_cmd.h" +#include "av1d_syntax.h" +#include "hal_av1d_common.h" +#include "vdpu38x_com.h" + +#define NON_COEF_CDF_SIZE (434 * 16) // byte +#define COEF_CDF_SIZE (354 * 16) // byte +#define ALL_CDF_SIZE (NON_COEF_CDF_SIZE + COEF_CDF_SIZE * 4) + +extern const RK_U32 g_av1d_default_prob[7400]; + +MPP_RET vdpu38x_av1d_deinit(void *hal); +MPP_RET vdpu38x_av1d_reset(void *hal); +MPP_RET vdpu38x_av1d_flush(void *hal); +MPP_RET vdpu38x_av1d_control(void *hal, MpiCmd cmd_type, void *param); +MPP_RET vdpu38x_av1d_uncomp_hdr(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva, + RK_U64 *data, RK_U32 len); +MPP_RET vdpu38x_av1d_cdf_setup(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva); +void vdpu38x_av1d_set_cdf_segid(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva, + RK_U32 *coef_rd_base, RK_U32 *coef_wr_base, + RK_U32 *segid_last_base, RK_U32 *segid_cur_base, + RK_U32 *noncoef_rd_base, RK_U32 *noncoef_wr_base); +MPP_RET vdpu38x_av1d_colmv_setup(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva); +void vdpu38x_av1d_rcb_setup(Av1dHalCtx *p_hal, HalTaskInfo *task, + DXVA_PicParams_AV1 *dxva, Vdpu38xRcbRegSet *rcb_regs, + Vdpu38xRcbCalc_f func); + +#endif /* HAL_AV1D_COM_H */ diff --git a/mpp/hal/rkdec/av1d/hal_av1d_ctx.h b/mpp/hal/rkdec/av1d/hal_av1d_ctx.h new file mode 100644 index 000000000..1c8399a27 --- /dev/null +++ b/mpp/hal/rkdec/av1d/hal_av1d_ctx.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AV1D_CTX_H +#define HAL_AV1D_CTX_H + +#include "av1d_common.h" +#include "vdpu_com.h" +#include "hal_bufs.h" + +typedef struct Av1dVdpu38xBuf_t { + RK_U32 valid; + void *regs; +} Av1dVdpu38xBuf; + +typedef struct Vdpu38xRefInfo_t { + RK_U32 dpb_idx; + RK_U32 seg_idx; + RK_U32 colmv_exist_flag; + RK_U32 cdf_valid; + RK_U32 coeff_idx; + RK_U32 mi_rows; + RK_U32 mi_cols; + RK_U32 seg_en; + RK_U32 seg_up_map; + RK_U32 cdf_update_flag; +} Vdpu38xRefInfo; + +typedef struct Vdpu38xAv1dRegCtx_t { + void *regs; + RK_U32 offset_uncomps; + + Av1dVdpu38xBuf reg_buf[VDPU_FAST_REG_SET_CNT]; + MppBuffer bufs; + RK_S32 bufs_fd; + void *bufs_ptr; + RK_U32 uncmps_offset[VDPU_FAST_REG_SET_CNT]; + + void *rcb_ctx; + VdpuRcbInfo rcb_buf_info[RCB_BUF_CNT]; + RK_U32 rcb_buf_size; + MppBuffer rcb_bufs[VDPU_FAST_REG_SET_CNT]; + + HalBufs colmv_bufs; + RK_U32 colmv_count; + RK_U32 colmv_size; + + Vdpu38xRefInfo ref_info_tbl[AV1_NUM_REF_FRAMES]; + + MppBuffer cdf_rd_def_base; + HalBufs cdf_segid_bufs; + RK_U32 cdf_segid_count; + RK_U32 cdf_segid_size; + RK_U32 cdf_coeff_cdf_idxs[AV1_NUM_REF_FRAMES]; + + MppBuffer tile_info; + MppBuffer film_grain_mem; + MppBuffer global_model; + MppBuffer filter_mem; + MppBuffer tile_buf; + + AV1CDFs *cdfs; + Av1MvCDFs *cdfs_ndvc; + AV1CDFs default_cdfs; + Av1MvCDFs default_cdfs_ndvc; + AV1CDFs cdfs_last[AV1_NUM_REF_FRAMES]; + Av1MvCDFs cdfs_last_ndvc[AV1_NUM_REF_FRAMES]; + RK_U32 refresh_frame_flags; + + RK_U32 width; + RK_U32 height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_U32 luma_size ; + RK_U32 chroma_size; + + AV1FilmGrainMemory fgsmem; + + RK_S8 prev_out_buffer_i; + RK_U8 fbc_en; + RK_U8 resolution_change; + RK_U8 tile_transpose; + RK_U32 ref_frame_sign_bias[AV1_REF_LIST_SIZE]; + + RK_U32 tile_out_count; + size_t tile_out_size; + + RK_U32 num_tile_cols; + /* uncompress header data */ + HalBufs origin_bufs; + RK_U8 header_data[0]; +} Vdpu38xAv1dRegCtx; + +#endif /* HAL_AV1D_CTX_H */ diff --git a/mpp/hal/rkdec/av1d/hal_av1d_vdpu383.c b/mpp/hal/rkdec/av1d/hal_av1d_vdpu383.c new file mode 100644 index 000000000..0f6b11bdc --- /dev/null +++ b/mpp/hal/rkdec/av1d/hal_av1d_vdpu383.c @@ -0,0 +1,642 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_av1d_vdpu383" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitput.h" +#include "mpp_buffer_impl.h" + +#include "vdpu_com.h" +#include "hal_av1d_common.h" +#include "hal_av1d_ctx.h" +#include "hal_av1d_com.h" +#include "vdpu38x_com.h" +#include "vdpu383_com.h" + +#include "av1d_syntax.h" +#include "film_grain_noise_table.h" +#include "av1d_syntax.h" + +#define VDPU383_UNCMPS_HEADER_SIZE (MPP_ALIGN(5160, 128) / 8 + 16) // byte, 5160 bit, reverse 128 bits +#define VDPU383_UNCMPS_HEADER_OFFSET_BASE (0) +#define VDPU383_INFO_ELEM_SIZE (VDPU383_UNCMPS_HEADER_SIZE) +#define VDPU383_UNCMPS_HEADER_OFFSET(idx) (VDPU383_INFO_ELEM_SIZE * idx + VDPU383_UNCMPS_HEADER_OFFSET_BASE) +#define VDPU383_INFO_BUF_SIZE(cnt) (VDPU383_INFO_ELEM_SIZE * cnt) + +static MPP_RET hal_av1d_alloc_res(void *hal) +{ + MPP_RET ret = MPP_OK; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + RK_U32 max_cnt = (p_hal->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + void *cdf_ptr; + INP_CHECK(ret, NULL == p_hal); + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Vdpu38xAv1dRegCtx) + + VDPU383_UNCMPS_HEADER_SIZE)); + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + + //!< malloc buffers + BUF_CHECK(ret, mpp_buffer_get(p_hal->cfg->buf_group, ®_ctx->bufs, VDPU383_INFO_BUF_SIZE(max_cnt))); + mpp_buffer_attach_dev(reg_ctx->bufs, p_hal->cfg->dev); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu383RegSet, 1); + memset(reg_ctx->reg_buf[i].regs, 0, sizeof(Vdpu383RegSet)); + reg_ctx->uncmps_offset[i] = VDPU383_UNCMPS_HEADER_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->offset_uncomps = reg_ctx->uncmps_offset[0]; + } + + BUF_CHECK(ret, mpp_buffer_get(p_hal->cfg->buf_group, ®_ctx->cdf_rd_def_base, + MPP_ALIGN(sizeof(g_av1d_default_prob), SZ_2K))); + mpp_buffer_attach_dev(reg_ctx->cdf_rd_def_base, p_hal->cfg->dev); + cdf_ptr = mpp_buffer_get_ptr(reg_ctx->cdf_rd_def_base); + memcpy(cdf_ptr, g_av1d_default_prob, sizeof(g_av1d_default_prob)); + mpp_buffer_sync_end(reg_ctx->cdf_rd_def_base); + +__RETURN: + return ret; +__FAILED: + return ret; +} + +MPP_RET vdpu383_av1d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + Vdpu38xAv1dRegCtx *reg_ctx = NULL; + + mpp_env_get_u32("hal_av1d_debug", &hal_av1d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + FUN_CHECK(hal_av1d_alloc_res(hal)); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu38x_av1d_deinit(hal); + + return ret; +} + +static MPP_RET vdpu383_av1d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + RK_U32 fltd_row_append = ctx->pic_w > 4096 ? 256 * 16 * 8 : 864 * 16 * 8; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, in_tl_row) * 100; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, in_tl_row) * 2752; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, on_tl_row) * 2752; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.6 * bit_depth + 0.5) + * (12.5 + 6 * cur_uv_para + 1.5 * ctx->lr_en); + cur_bit_size = cur_bit_size / 2 + fltd_row_append; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + // save space mode : half for RCB_FLTD_IN_ROW, half for RCB_FLTD_PROT_IN_ROW + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.6 * bit_depth + 0.5) + * (12.5 + 6 * cur_uv_para + 1.5 * ctx->lr_en); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_col_uv_coef_map[rcb_fmt]; + if (ctx->tile_dir == 0) + cur_bit_size = MPP_ROUNDUP(64, on_tl_col) * (1.6 * bit_depth + 0.5) * + (14 + 7 * cur_uv_para + (14 + 12.5 * cur_uv_para) * ctx->lr_en + + ((ctx->upsc_en != 0) ? (8.5 + 7 * cur_uv_para) : (5 + 1 * cur_uv_para))); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, on_tl_col) * bit_depth * 22; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +MPP_RET vdpu383_av1d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + Vdpu38xAv1dRegCtx *ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + Vdpu383RegSet *regs; + DXVA_PicParams_AV1 *dxva = (DXVA_PicParams_AV1*)task->dec.syntax.data; + RK_U32 i = 0; + HalBuf *origin_buf = NULL; + MppFrame mframe; + MppHalCfg *cfg = p_hal->cfg; + + INP_CHECK(ret, NULL == p_hal); + + ctx->refresh_frame_flags = dxva->refresh_frame_flags; + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + mpp_err_f("parse err %d ref err %d\n", + task->dec.flags.parse_err, task->dec.flags.ref_err); + goto __RETURN; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + MPP_MAX(dxva->width, dxva->height) > 4096 && ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, &ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + if (p_hal->fast_mode) { + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { + if (!ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + ctx->regs = ctx->reg_buf[i].regs; + ctx->reg_buf[i].valid = 1; + ctx->offset_uncomps = ctx->uncmps_offset[i]; + break; + } + } + } + regs = ctx->regs; + memset(regs, 0, sizeof(*regs)); + p_hal->strm_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + +#ifdef DUMP_VDPU38X_DATAS + { + memset(vdpu38x_dump_cur_dir, 0, sizeof(vdpu38x_dump_cur_dir)); + sprintf(vdpu38x_dump_cur_dir, "av1/Frame%04d", vdpu38x_dump_cur_frm); + if (access(vdpu38x_dump_cur_dir, 0)) { + if (mkdir(vdpu38x_dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", vdpu38x_dump_cur_dir); + } + vdpu38x_dump_cur_frm++; + } +#endif + + vdpu383_init_ctrl_regs(regs, MPP_VIDEO_CodingAV1); + vdpu383_setup_statistic(®s->ctrl_regs); + + /* set reg -> pkt data */ + { + MppBuffer mbuffer = NULL; + + /* uncompress header data */ + vdpu38x_av1d_uncomp_hdr(p_hal, dxva, (RK_U64 *)ctx->header_data, VDPU383_UNCMPS_HEADER_SIZE / 8); + memcpy((char *)ctx->bufs_ptr + ctx->offset_uncomps, (void *)ctx->header_data, VDPU383_UNCMPS_HEADER_SIZE); + regs->comm_paras.reg67_global_len = VDPU383_UNCMPS_HEADER_SIZE / 16; // 128 bit as unit + regs->comm_addrs.reg131_gbl_base = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 131, ctx->offset_uncomps); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "global_cfg.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, ctx->bufs_ptr, + 8 * regs->comm_paras.reg67_global_len * 16, 64, 0, 0); + } +#endif + // input strm + p_hal->strm_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + regs->comm_paras.reg66_stream_len = MPP_ALIGN(p_hal->strm_len + 15, 128); + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(mbuffer); + regs->comm_paras.reg65_strm_start_bit = 0; // bit start to decode + /* error */ + regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(mbuffer); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "stream_in.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * p_hal->strm_len, 128, 0, 0); + } + { + char *cur_fname = "stream_in_no_offset.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * p_hal->strm_len, 128, 0, 0); + } +#endif + } + + vdpu38x_av1d_rcb_setup(p_hal, task, dxva, ®s->comm_addrs.rcb_regs, + vdpu383_av1d_rcb_calc); + + /* set reg -> para (stride, len) */ + { + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + RK_U32 mapped_idx; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + if (mframe) { + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + uv_virstride = hor_virstride * ver_virstride / 2; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + RK_U32 fbd_offset; + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 h = MPP_ALIGN(mpp_frame_get_height(mframe), 64); + + regs->ctrl_regs.reg9.fbc_e = 1; + regs->comm_paras.reg68_hor_virstride = fbc_hdr_stride / 64; + fbd_offset = regs->comm_paras.reg68_hor_virstride * h * 4; + regs->comm_addrs.reg193_fbc_payload_offset = fbd_offset; + } else if (MPP_FRAME_FMT_IS_TILE(mpp_frame_get_fmt(mframe))) { + regs->ctrl_regs.reg9.tile_e = 1; + regs->comm_paras.reg68_hor_virstride = MPP_ALIGN(hor_virstride * 6, 16) >> 4; + regs->comm_paras.reg70_y_virstride = (y_virstride + uv_virstride) >> 4; + } else { + regs->ctrl_regs.reg9.fbc_e = 0; + regs->comm_paras.reg68_hor_virstride = hor_virstride >> 4; + regs->comm_paras.reg69_raster_uv_hor_virstride = hor_virstride >> 4; + regs->comm_paras.reg70_y_virstride = y_virstride >> 4; + } + /* error */ + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg68_hor_virstride; + regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = regs->comm_paras.reg69_raster_uv_hor_virstride; + regs->comm_paras.reg82_error_ref_virstride = regs->comm_paras.reg70_y_virstride; + } + + for (i = 0; i < AV1_REFS_PER_FRAME; ++i) { + mapped_idx = dxva->ref_frame_idx[i]; + if (dxva->frame_refs[mapped_idx].Index != (RK_S8)0xff && dxva->frame_refs[mapped_idx].Index != 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->frame_refs[mapped_idx].Index, SLOT_FRAME_PTR, &mframe); + if (mframe) { + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + hor_virstride = mpp_frame_get_fbc_hdr_stride(mframe) / 4; + } else if (MPP_FRAME_FMT_IS_TILE(mpp_frame_get_fmt(mframe))) { + hor_virstride = MPP_ALIGN(hor_virstride * 6, 16); + y_virstride += y_virstride / 2; + } + regs->comm_paras.ref_stride[mapped_idx].hor_y_stride = hor_virstride >> 4; + regs->comm_paras.ref_stride[mapped_idx].hor_uv_stride = hor_virstride >> 4; + regs->comm_paras.ref_stride[mapped_idx].y_stride = y_virstride >> 4; + } + } + } + } + + /* set reg -> para (ref, fbc, colmv) */ + { + MppBuffer mbuffer = NULL; + RK_U32 mapped_idx; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_BUFFER, &mbuffer); + regs->comm_addrs.reg168_decout_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg192_payload_st_cur_base = mpp_buffer_get_fd(mbuffer); + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + mapped_idx = dxva->ref_frame_idx[i]; + if (dxva->frame_refs[mapped_idx].Index != (RK_S8)0xff && dxva->frame_refs[mapped_idx].Index != 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->frame_refs[mapped_idx].Index, SLOT_BUFFER, &mbuffer); + if (ctx->origin_bufs && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, dxva->frame_refs[mapped_idx].Index); + mbuffer = origin_buf->buf[0]; + } + if (mbuffer) { + RK_U32 *reg_ref_base = NULL; + RK_U32 *reg_pld_base = NULL; + + reg_ref_base = regs->comm_addrs.reg170_185_ref_base; + reg_ref_base[mapped_idx] = mpp_buffer_get_fd(mbuffer); + reg_pld_base = regs->comm_addrs.reg195_210_payload_st_ref_base; + reg_pld_base[mapped_idx] = mpp_buffer_get_fd(mbuffer); + } + } + } + + HalBuf *mv_buf = NULL; + vdpu38x_av1d_colmv_setup(p_hal, dxva); + mv_buf = hal_bufs_get_buf(ctx->colmv_bufs, dxva->CurrPic.Index7Bits); + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); +#ifdef DUMP_VDPU38X_DATAS + memset(mpp_buffer_get_ptr(mv_buf->buf[0]), 0, mpp_buffer_get_size(mv_buf->buf[0])); +#endif + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (dxva->frame_refs[i].Index != (RK_S8)0xff && dxva->frame_refs[i].Index != 0x7f) { + mv_buf = hal_bufs_get_buf(ctx->colmv_bufs, dxva->frame_refs[i].Index); + regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "colmv_ref_frame"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s%d.dat", vdpu38x_dump_cur_dir, cur_fname, i); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mv_buf->buf[0]), + 8 * mpp_buffer_get_size(mv_buf->buf[0]), 64, 0, 0); + } +#endif + } + } + } + + vdpu38x_av1d_cdf_setup(p_hal, dxva); + vdpu38x_av1d_set_cdf_segid(p_hal, dxva, + ®s->comm_addrs.reg178_av1_coef_rd_base, + ®s->comm_addrs.reg179_av1_coef_wr_base, + ®s->comm_addrs.reg181_av1_rd_segid_base, + ®s->comm_addrs.reg182_av1_wr_segid_base, + ®s->comm_addrs.reg184_av1_noncoef_rd_base, + ®s->comm_addrs.reg185_av1_noncoef_wr_base); + mpp_buffer_sync_end(ctx->bufs); + + { + //scale down config + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + fd = mpp_buffer_get_fd(mbuffer); + + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + regs->comm_addrs.reg133_scale_down_base = fd; + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, dxva->CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + regs->comm_addrs.reg169_error_ref_base = fd; + vdpu383_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + regs->comm_addrs.reg133_scale_down_base = fd; + vdpu383_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu383_av1d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + INP_CHECK(ret, NULL == p_hal); + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + goto __RETURN; + } + + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + Vdpu383RegSet *regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + MppDev dev = p_hal->cfg->dev; + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->ctrl_regs; + wr_cfg.size = sizeof(regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_paras; + wr_cfg.size = sizeof(regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_addrs; + wr_cfg.size = sizeof(regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->ctrl_regs.reg15; + rd_cfg.size = sizeof(regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu383_av1d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + INP_CHECK(ret, NULL == p_hal); + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + Vdpu383RegSet *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "colmv_cur_frame.dat"; + DXVA_PicParams_AV1 *dxva = (DXVA_PicParams_AV1*)task->dec.syntax.data; + HalBuf *mv_buf = NULL; + mv_buf = hal_bufs_get_buf(reg_ctx->colmv_bufs, dxva->CurrPic.Index7Bits); + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mv_buf->buf[0]), + 8 * mpp_buffer_get_size(mv_buf->buf[0]), 64, 0, 0); + } + { + char *cur_fname = "decout.dat"; + MppBuffer mbuffer = NULL; + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_BUFFER, &mbuffer); + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * mpp_buffer_get_size(mbuffer), 128, 0, 0); + } +#endif + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "cabac_cdf_out.dat"; + HalBuf *cdf_buf = NULL; + DXVA_PicParams_AV1 *dxva = (DXVA_PicParams_AV1*)task->dec.syntax.data; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + cdf_buf = hal_bufs_get_buf(reg_ctx->cdf_segid_bufs, dxva->CurrPic.Index7Bits); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(cdf_buf->buf[0]), + (NON_COEF_CDF_SIZE + COEF_CDF_SIZE) * 8, 128, 0, 0); + } +#endif + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + (!p_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + p_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + p_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_frame_set_errinfo(mframe, 1); + } + +__SKIP_HARD: + if (p_hal->fast_mode) + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_av1d_vdpu383 = { + .name = "av1d_vdpu383", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAV1, + .ctx_size = sizeof(Av1dHalCtx), + .flag = 0, + .init = vdpu383_av1d_init, + .deinit = vdpu38x_av1d_deinit, + .reg_gen = vdpu383_av1d_gen_regs, + .start = vdpu383_av1d_start, + .wait = vdpu383_av1d_wait, + .reset = vdpu38x_av1d_reset, + .flush = vdpu38x_av1d_flush, + .control = vdpu38x_av1d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_av1d_vdpu383) diff --git a/mpp/hal/rkdec/av1d/hal_av1d_vdpu383.h b/mpp/hal/rkdec/av1d/hal_av1d_vdpu383.h new file mode 100644 index 000000000..964a8d8e4 --- /dev/null +++ b/mpp/hal/rkdec/av1d/hal_av1d_vdpu383.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AV1D_VDPU383_H +#define HAL_AV1D_VDPU383_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_av1d_vdpu383; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AV1D_VDPU383_H */ diff --git a/mpp/hal/rkdec/av1d/hal_av1d_vdpu384b.c b/mpp/hal/rkdec/av1d/hal_av1d_vdpu384b.c new file mode 100644 index 000000000..5fc312f1f --- /dev/null +++ b/mpp/hal/rkdec/av1d/hal_av1d_vdpu384b.c @@ -0,0 +1,892 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_av1d_vdpu384b" + +#include "mpp_buffer_impl.h" +#include "mpp_env.h" + +#include "hal_av1d_com.h" +#include "hal_av1d_ctx.h" +#include "vdpu38x_com.h" + +#define VDPU384B_UNCMPS_HEADER_SIZE (MPP_ALIGN(5160 + 64, 128) / 8) // byte, 5160 bit + Reserve 64 +#define VDPU384B_UNCMPS_HEADER_OFFSET_BASE (0) +#define VDPU384B_INFO_ELEM_SIZE (VDPU384B_UNCMPS_HEADER_SIZE) +#define VDPU384B_UNCMPS_HEADER_OFFSET(idx) (VDPU384B_INFO_ELEM_SIZE * idx + VDPU384B_UNCMPS_HEADER_OFFSET_BASE) +#define VDPU384B_INFO_BUF_SIZE(cnt) (VDPU384B_INFO_ELEM_SIZE * cnt) +#define VDPU384B_DEF_CDF_UPDATE_ARRAY_SIZE (20) + +static struct { + RK_U32 org_data_off; // char unit + RK_U32 new_data_sz; // char unit + RK_U32 data[16]; +} vdpu384b_def_prob_update_info[VDPU384B_DEF_CDF_UPDATE_ARRAY_SIZE] = { + { + .org_data_off = 314 * 8 * 4, + .new_data_sz = 64, + .data = { + 0xc173a0d7, 0x76e1e02e, 0xb019c8a6, 0x48523960, + 0xfcf54494, 0x58c607f1, 0x4c5b184f, 0x80000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 330 * 8 * 4, + .new_data_sz = 64, + .data = { + 0xc0a5182c, 0x75d18016, 0xb40d6060, 0xf137393d, + 0xa9ef068a, 0xea22d40b, 0xf22e827e, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 346 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x01069b27, 0x96e8c00c, 0x4c0dd857, 0x7a22c525, + 0x16a81083, 0xaa70ad26, 0x43795d65, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 362 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 378 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 491 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x41b61d2e, 0xe74de045, 0xf02740d6, 0x2d595f68, + 0x5936ad18, 0x6ee6bc13, 0x4bb32457, 0x80000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 507 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x808a1940, 0xc608e011, 0x380bf856, 0x582b552a, + 0x432e7908, 0xf762f86b, 0xf76a937e, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 523 * 8 * 4, + .new_data_sz = 64, + .data = { + 0xc0649afa, 0xe5d8c008, 0x9406482c, 0x0210bef2, + 0x05260e82, 0xa3b0a1c5, 0x3c293fe5, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 539 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 555 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 668 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x01a9961d, 0x372f0054, 0xa030e8f2, 0x74588d60, + 0x63f6e617, 0x6c067a53, 0x3ca32777, 0x80000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 684 * 8 * 4, + .new_data_sz = 64, + .data = { + 0xc0869232, 0x75774018, 0xa4178872, 0xc93e1d38, + 0xa1f3378f, 0x1bf4bfcf, 0xf8feb4df, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 700 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x803a117d, 0x564ee005, 0x38062829, 0xe22e7d18, + 0xefabdf0d, 0x62920009, 0x92a1e0c6, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 716 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 732 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 845 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x015292b2, 0x46b3602e, 0x8c18e0b5, 0xe4520d5d, + 0x9ff44d12, 0x90058092, 0x14032807, 0x80000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 861 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x80fb8f5a, 0x26616026, 0xc81a80a0, 0xe350ed50, + 0x27f59c12, 0xc474c0d2, 0xe9766d7e, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 877 * 8 * 4, + .new_data_sz = 64, + .data = { + 0xc0f59478, 0xd7b82015, 0x28150063, 0xc647af5c, + 0x00300012, 0xd174aab0, 0xba31d17d, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 893 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, + { + .org_data_off = 909 * 8 * 4, + .new_data_sz = 64, + .data = { + 0x20006000, 0x0c000800, 0x01000400, 0x00800180, + 0x00300020, 0x00040010, 0x80020006, 0x80000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, +}; + +static MPP_RET hal_av1d_alloc_res(void *hal) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + RK_U32 max_cnt = p_hal->fast_mode ? VDPU_FAST_REG_SET_CNT : 1; + void *cdf_ptr; + Vdpu38xAv1dRegCtx *reg_ctx = NULL; + RK_U32 i = 0; + MPP_RET ret = MPP_OK; + + INP_CHECK(ret, NULL == p_hal); + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Vdpu38xAv1dRegCtx) + + VDPU384B_UNCMPS_HEADER_SIZE)); + reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + + //!< malloc buffers + BUF_CHECK(ret, mpp_buffer_get(p_hal->cfg->buf_group, ®_ctx->bufs, VDPU384B_INFO_BUF_SIZE(max_cnt))); + mpp_buffer_attach_dev(reg_ctx->bufs, p_hal->cfg->dev); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + + + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu38xRegSet, 1); + memset(reg_ctx->reg_buf[i].regs, 0, sizeof(Vdpu38xRegSet)); + reg_ctx->uncmps_offset[i] = VDPU384B_UNCMPS_HEADER_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->offset_uncomps = reg_ctx->uncmps_offset[0]; + } + + BUF_CHECK(ret, mpp_buffer_get(p_hal->cfg->buf_group, ®_ctx->cdf_rd_def_base, MPP_ALIGN(sizeof(g_av1d_default_prob), 2048))); + mpp_buffer_attach_dev(reg_ctx->cdf_rd_def_base, p_hal->cfg->dev); + cdf_ptr = mpp_buffer_get_ptr(reg_ctx->cdf_rd_def_base); + memcpy(cdf_ptr, g_av1d_default_prob, sizeof(g_av1d_default_prob)); + /* update vdpu384b def cdf */ + { + RK_U8 *src, *dst; + + for (i = 0; i < VDPU384B_DEF_CDF_UPDATE_ARRAY_SIZE; i++) { + src = (RK_U8 *)vdpu384b_def_prob_update_info[i].data; + dst = (RK_U8 *)cdf_ptr; + dst += vdpu384b_def_prob_update_info[i].org_data_off; + memcpy(dst, src, vdpu384b_def_prob_update_info[i].new_data_sz); + } + } + mpp_buffer_sync_end(reg_ctx->cdf_rd_def_base); + +__RETURN: + return ret; +__FAILED: + return ret; +} + +MPP_RET vdpu384b_av1d_init(void *hal, MppHalCfg *cfg) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + Vdpu38xAv1dRegCtx *reg_ctx = NULL; + MPP_RET ret = MPP_OK; + + mpp_env_get_u32("hal_av1d_debug", &hal_av1d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + FUN_CHECK(hal_av1d_alloc_res(hal)); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu38x_av1d_deinit(hal); + + return ret; +} + +static MPP_RET vdpu384b_av1d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + /* + * For all spec, the hardware connects all in-tile rows of strmd to the on-tile. + * Therefore, only strmd on-tile needs to be configured, and there is no need to + * configure strmd in-tile. + * + * Versions with issues: swan1126b (384a), shark/robin (384b). + */ + cur_bit_size = MPP_DIVUP(8, in_tl_row) * 100; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, in_tl_row) * 2752; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, on_tl_row) * 2752; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.2 * bit_depth + 0.5) + * (12.5 + 6 * cur_uv_para + 1.5 * ctx->lr_en); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.2 * bit_depth + 0.5) + * (12.5 + 6 * cur_uv_para + 1.5 * ctx->lr_en); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_col_uv_coef_map[rcb_fmt]; + if (ctx->tile_dir == 0) + cur_bit_size = MPP_ROUNDUP(64, on_tl_col) * (1.6 * bit_depth + 0.5) * + (14 + 7 * cur_uv_para + (14 + 12.5 * cur_uv_para) * ctx->lr_en + + ( ctx->upsc_en ? (8.5 + 7 * cur_uv_para) : (5 + 1 * cur_uv_para))); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, on_tl_col) * bit_depth * 22; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +MPP_RET vdpu384b_av1d_gen_regs(void *hal, HalTaskInfo *task) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + Vdpu38xAv1dRegCtx *ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + Vdpu38xRegSet *regs; + DXVA_PicParams_AV1 *dxva = (DXVA_PicParams_AV1*)task->dec.syntax.data; + HalBuf *origin_buf = NULL; + MppFrame mframe; + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + MppHalCfg *cfg = p_hal->cfg; + + INP_CHECK(ret, NULL == p_hal); + + ctx->refresh_frame_flags = dxva->refresh_frame_flags; + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + mpp_err_f("parse err %d ref err %d\n", + task->dec.flags.parse_err, task->dec.flags.ref_err); + goto __RETURN; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + MPP_MAX(dxva->width, dxva->height) > 4096 && ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, &ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + if (p_hal->fast_mode) { + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { + if (!ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + ctx->regs = ctx->reg_buf[i].regs; + ctx->reg_buf[i].valid = 1; + ctx->offset_uncomps = ctx->uncmps_offset[i]; + break; + } + } + } + regs = ctx->regs; + memset(regs, 0, sizeof(*regs)); + p_hal->strm_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + +#ifdef DUMP_VDPU38X_DATAS + { + memset(vdpu38x_dump_cur_dir, 0, sizeof(vdpu38x_dump_cur_dir)); + sprintf(vdpu38x_dump_cur_dir, "av1/Frame%04d", vdpu38x_dump_cur_frm); + if (access(vdpu38x_dump_cur_dir, 0)) { + if (mkdir(vdpu38x_dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", vdpu38x_dump_cur_dir); + } + vdpu38x_dump_cur_frm++; + } +#endif + + vdpu384b_init_ctrl_regs(regs, MPP_VIDEO_CodingAV1); + vdpu38x_setup_statistic(®s->ctrl_regs); + + /* set reg -> pkt data */ + { + MppBuffer mbuffer = NULL; + + /* uncompress header data */ + vdpu38x_av1d_uncomp_hdr(p_hal, dxva, (RK_U64 *)ctx->header_data, VDPU384B_UNCMPS_HEADER_SIZE / 8); + memcpy((char *)ctx->bufs_ptr + ctx->offset_uncomps, (void *)ctx->header_data, VDPU384B_UNCMPS_HEADER_SIZE); + regs->comm_paras.reg67_global_len = VDPU384B_UNCMPS_HEADER_SIZE / 16; // 128 bit as unit + regs->comm_addrs.reg131_gbl_base = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 131, ctx->offset_uncomps); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "global_cfg.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, ctx->bufs_ptr, + 8 * regs->comm_paras.reg67_global_len * 16, 128, 0, 0); + } +#endif + // input strm + p_hal->strm_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + regs->comm_paras.reg66_stream_len = MPP_ALIGN(p_hal->strm_len + 15, 128); + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg129_stream_buf_st_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg130_stream_buf_end_base = mpp_buffer_get_fd(mbuffer); + mpp_dev_set_reg_offset(cfg->dev, 130, mpp_buffer_get_size(mbuffer)); + regs->comm_paras.reg65_strm_start_bit = 0; // bit start to decode + /* error */ + regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(mbuffer); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "stream_in.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * p_hal->strm_len, 128, 0, 0); + } + { + char *cur_fname = "stream_in_no_offset.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * p_hal->strm_len, 128, 0, 0); + } +#endif + } + + vdpu38x_av1d_rcb_setup(p_hal, task, dxva, ®s->comm_addrs.rcb_regs, + vdpu384b_av1d_rcb_calc); + + /* set reg -> para (stride, len) */ + { + MppFrameFormat fmt; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + RK_U32 mapped_idx = 0; + RK_U32 fbc_head_stride = 0; + RK_U32 fbc_pld_stride = 0; + RK_U32 fbc_offset = 0; + RK_U32 tile4x4_coeff = 0; + + fmt = mpp_frame_get_fmt(mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + uv_virstride = hor_virstride * ver_virstride / 2; + if (MPP_FRAME_FMT_IS_AFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 3; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_RKFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 2; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_TILE(fmt)) { + if (vdpu38x_get_tile4x4_h_stride_coeff(fmt, &tile4x4_coeff)) { + mpp_err("get tile 4x4 coeff failed\n"); + return MPP_NOK; + } + regs->ctrl_regs.reg9.pp_output_mode = 1; + regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride * tile4x4_coeff >> 4; + regs->comm_paras.reg70_pp_m_y_virstride = (y_virstride + uv_virstride) >> 4; + } else { + regs->ctrl_regs.reg9.pp_output_mode = 0; + regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride >> 4; + regs->comm_paras.reg69_pp_m_uv_hor_stride = hor_virstride >> 4; + regs->comm_paras.reg70_pp_m_y_virstride = y_virstride >> 4; + } + /* error */ + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg68_pp_m_hor_stride; + regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = regs->comm_paras.reg69_pp_m_uv_hor_stride; + regs->comm_paras.reg82_error_ref_virstride = regs->comm_paras.reg70_pp_m_y_virstride; + + for (i = 0; i < AV1_REFS_PER_FRAME; ++i) { + mapped_idx = dxva->ref_frame_idx[i]; + if (dxva->frame_refs[mapped_idx].Index != (RK_S8)0xff && dxva->frame_refs[mapped_idx].Index != 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->frame_refs[mapped_idx].Index, SLOT_FRAME_PTR, &mframe); + if (mframe) { + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + regs->comm_paras.ref_stride[mapped_idx].hor_y_stride = fbc_head_stride; + regs->comm_paras.ref_stride[mapped_idx].hor_uv_stride = fbc_pld_stride; + } else if (MPP_FRAME_FMT_IS_TILE(mpp_frame_get_fmt(mframe))) { + hor_virstride = MPP_ALIGN(hor_virstride * 6, 16); + y_virstride += y_virstride / 2; + regs->comm_paras.ref_stride[mapped_idx].hor_y_stride = hor_virstride >> 4; + regs->comm_paras.ref_stride[mapped_idx].hor_uv_stride = hor_virstride >> 4; + regs->comm_paras.ref_stride[mapped_idx].y_stride = y_virstride >> 4; + } else { + regs->comm_paras.ref_stride[mapped_idx].hor_y_stride = hor_virstride >> 4; + regs->comm_paras.ref_stride[mapped_idx].hor_uv_stride = hor_virstride >> 4; + regs->comm_paras.ref_stride[mapped_idx].y_stride = y_virstride >> 4; + } + } + } + } + } + + /* set reg -> para (ref, fbc, colmv) */ + { + MppBuffer mbuffer = NULL; + RK_U32 mapped_idx; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_BUFFER, &mbuffer); + regs->comm_addrs.reg168_decout_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg192_payload_st_cur_base = mpp_buffer_get_fd(mbuffer); + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + mapped_idx = dxva->ref_frame_idx[i]; + if (dxva->frame_refs[mapped_idx].Index != (RK_S8)0xff && dxva->frame_refs[mapped_idx].Index != 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->frame_refs[mapped_idx].Index, SLOT_BUFFER, &mbuffer); + if (ctx->origin_bufs && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, dxva->frame_refs[mapped_idx].Index); + mbuffer = origin_buf->buf[0]; + } + if (mbuffer) { + RK_U32 *reg_ref_base = NULL; + RK_U32 *reg_pld_base = NULL; + + reg_ref_base = regs->comm_addrs.reg170_185_ref_base; + reg_ref_base[mapped_idx] = mpp_buffer_get_fd(mbuffer); + reg_pld_base = regs->comm_addrs.reg195_210_payload_st_ref_base; + reg_pld_base[mapped_idx] = mpp_buffer_get_fd(mbuffer); + } + } + } + + HalBuf *mv_buf = NULL; + vdpu38x_av1d_colmv_setup(p_hal, dxva); + mv_buf = hal_bufs_get_buf(ctx->colmv_bufs, dxva->CurrPic.Index7Bits); + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); +#ifdef DUMP_VDPU38X_DATAS + memset(mpp_buffer_get_ptr(mv_buf->buf[0]), 0, mpp_buffer_get_size(mv_buf->buf[0])); +#endif + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (dxva->frame_refs[i].Index != (RK_S8)0xff && dxva->frame_refs[i].Index != 0x7f) { + mv_buf = hal_bufs_get_buf(ctx->colmv_bufs, dxva->frame_refs[i].Index); + regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "colmv_ref_frame"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s%d.dat", vdpu38x_dump_cur_dir, cur_fname, i); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mv_buf->buf[0]), + 8 * mpp_buffer_get_size(mv_buf->buf[0]), 64, 0, 0); + } +#endif + } + } + } + + vdpu38x_av1d_cdf_setup(p_hal, dxva); + vdpu38x_av1d_set_cdf_segid(p_hal, dxva, + ®s->comm_addrs.reg178_av1_coef_rd_base, + ®s->comm_addrs.reg179_av1_coef_wr_base, + ®s->comm_addrs.reg181_av1_segid_last_base, + ®s->comm_addrs.reg182_av1_segid_cur_base, + ®s->comm_addrs.reg184_av1_noncoef_rd_base, + ®s->comm_addrs.reg185_av1_noncoef_wr_base); + mpp_buffer_sync_end(ctx->bufs); + + { + //scale down config + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva->CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + fd = mpp_buffer_get_fd(mbuffer); + + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + regs->comm_addrs.reg133_scale_down_base = fd; + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, dxva->CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + regs->comm_addrs.reg169_error_ref_base = fd; + vdpu38x_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + regs->comm_addrs.reg133_scale_down_base = fd; + vdpu38x_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu384b_av1d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + MppDev dev; + + INP_CHECK(ret, NULL == p_hal); + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + goto __RETURN; + } + + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + Vdpu38xRegSet *regs = p_hal->fast_mode ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + dev = p_hal->cfg->dev; + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->ctrl_regs; + wr_cfg.size = sizeof(regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_paras; + wr_cfg.size = sizeof(regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_addrs; + wr_cfg.size = sizeof(regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->ctrl_regs.reg15; + rd_cfg.size = sizeof(regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + if (hal_av1d_debug & AV1D_DBG_REG) { + rd_cfg.reg = ®s->statistic_regs; + rd_cfg.size = sizeof(regs->statistic_regs); + rd_cfg.offset = VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu384b_av1d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + INP_CHECK(ret, NULL == p_hal); + Vdpu38xAv1dRegCtx *reg_ctx = (Vdpu38xAv1dRegCtx *)p_hal->reg_ctx; + Vdpu38xRegSet *p_regs = p_hal->fast_mode ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "colmv_cur_frame.dat"; + DXVA_PicParams_AV1 *dxva = (DXVA_PicParams_AV1*)task->dec.syntax.data; + HalBuf *mv_buf = NULL; + mv_buf = hal_bufs_get_buf(reg_ctx->colmv_bufs, dxva->CurrPic.Index7Bits); + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mv_buf->buf[0]), + 8 * mpp_buffer_get_size(mv_buf->buf[0]), 64, 0, 0); + } + { + char *cur_fname = "decout.dat"; + MppBuffer mbuffer = NULL; + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_BUFFER, &mbuffer); + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * mpp_buffer_get_size(mbuffer), 128, 0, 0); + } +#endif + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "cabac_cdf_out.dat"; + HalBuf *cdf_buf = NULL; + DXVA_PicParams_AV1 *dxva = (DXVA_PicParams_AV1*)task->dec.syntax.data; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + cdf_buf = hal_bufs_get_buf(reg_ctx->cdf_segid_bufs, dxva->CurrPic.Index7Bits); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(cdf_buf->buf[0]), + (NON_COEF_CDF_SIZE + COEF_CDF_SIZE) * 8, 128, 0, 0); + } +#endif + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + (!p_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + p_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + p_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_frame_set_errinfo(mframe, 1); + } + if (hal_av1d_debug & AV1D_DBG_REG) { + mpp_assert(p_regs->statistic_regs.reg312.rcb_rd_sum_chk == + p_regs->statistic_regs.reg312.rcb_wr_sum_chk); + } + +__SKIP_HARD: + if (p_hal->fast_mode) + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_av1d_vdpu384b = { + .name = "av1d_vdpu384b", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAV1, + .ctx_size = sizeof(Av1dHalCtx), + .flag = 0, + .init = vdpu384b_av1d_init, + .deinit = vdpu38x_av1d_deinit, + .reg_gen = vdpu384b_av1d_gen_regs, + .start = vdpu384b_av1d_start, + .wait = vdpu384b_av1d_wait, + .reset = vdpu38x_av1d_reset, + .flush = vdpu38x_av1d_flush, + .control = vdpu38x_av1d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_av1d_vdpu384b) diff --git a/mpp/hal/rkdec/av1d/hal_av1d_vdpu384b.h b/mpp/hal/rkdec/av1d/hal_av1d_vdpu384b.h new file mode 100644 index 000000000..ec9193ce7 --- /dev/null +++ b/mpp/hal/rkdec/av1d/hal_av1d_vdpu384b.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AV1D_VDPU384B_H +#define HAL_AV1D_VDPU384B_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_av1d_vdpu384b; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AV1D_VDPU384B_H */ diff --git a/mpp/hal/rkdec/avs2d/CMakeLists.txt b/mpp/hal/rkdec/avs2d/CMakeLists.txt new file mode 100644 index 000000000..1b0f5bf39 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/CMakeLists.txt @@ -0,0 +1,15 @@ +# vim: syntax=cmake + +# hal avs2 decoder sourse +set(HAL_AVS2D_SRC + hal_avs2d_com.c + ) + +add_hal_source(HAL_AVS2D_SRC HAVE_VDPU381 hal_avs2d_rkv.c) +add_hal_source(HAL_AVS2D_SRC HAVE_VDPU382 hal_avs2d_vdpu382.c) +add_hal_source(HAL_AVS2D_SRC HAVE_VDPU383 hal_avs2d_vdpu383.c) +add_hal_source(HAL_AVS2D_SRC HAVE_VDPU384B hal_avs2d_vdpu384b.c) + +if (HAL_AVS2D_SRC) + add_library(hal_avs2d_api OBJECT ${HAL_AVS2D_SRC}) +endif() diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_com.c b/mpp/hal/rkdec/avs2d/hal_avs2d_com.c new file mode 100644 index 000000000..89acaac4d --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_com.c @@ -0,0 +1,416 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_avs2d_com" + +#include +#include +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_platform.h" +#include "mpp_common.h" +#include "mpp_log.h" +#include "vdpu38x_com.h" +#include "hal_avs2d_global.h" +#include "hal_avs2d_ctx.h" +#include "hal_avs2d_com.h" +#include "mpp_bitput.h" + +MPP_RET hal_avs2d_vdpu_deinit(void *hal) +{ + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + RK_U32 i, loop; + MPP_RET ret = MPP_OK; + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == reg_ctx); + + //!< malloc buffers + loop = p_hal->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + + MPP_FREE(reg_ctx->reg_buf[i].regs); + } + vdpu38x_rcb_calc_deinit(reg_ctx->rcb_ctx); + + if (reg_ctx->bufs) { + mpp_buffer_put(reg_ctx->bufs); + reg_ctx->bufs = NULL; + } + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + MPP_FREE(reg_ctx->shph_dat); + MPP_FREE(reg_ctx->scalist_dat); + + MPP_FREE(p_hal->reg_ctx); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +MPP_RET hal_avs2d_vdpu38x_prepare_header(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + AlfParams_Avs2d *alfp = &syntax->alfp; + RefParams_Avs2d *refp = &syntax->refp; + WqmParams_Avs2d *wqmp = &syntax->wqmp; + RK_U64 *bit_buf = (RK_U64 *)data; + BitputCtx_t bp; + RK_U32 i, j; + + memset(data, 0, len); + + mpp_set_bitput_ctx(&bp, bit_buf, len); + + //!< sequence header syntax + mpp_put_bits(&bp, pp->chroma_format_idc, 2); + mpp_put_bits(&bp, pp->pic_width_in_luma_samples, 16); + mpp_put_bits(&bp, pp->pic_height_in_luma_samples, 16); + mpp_put_bits(&bp, pp->bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, pp->bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, pp->lcu_size, 3); + mpp_put_bits(&bp, pp->progressive_sequence, 1); + mpp_put_bits(&bp, pp->field_coded_sequence, 1); + + mpp_put_bits(&bp, pp->secondary_transform_enable_flag, 1); + mpp_put_bits(&bp, pp->sample_adaptive_offset_enable_flag, 1); + mpp_put_bits(&bp, pp->adaptive_loop_filter_enable_flag, 1); + mpp_put_bits(&bp, pp->pmvr_enable_flag, 1); + mpp_put_bits(&bp, pp->cross_slice_loopfilter_enable_flag, 1); + + //!< picture header syntax + mpp_put_bits(&bp, pp->picture_type, 3); + mpp_put_bits(&bp, refp->ref_pic_num, 3); + mpp_put_bits(&bp, pp->scene_reference_enable_flag, 1); + mpp_put_bits(&bp, pp->bottom_field_picture_flag, 1); + mpp_put_bits(&bp, pp->fixed_picture_qp, 1); + mpp_put_bits(&bp, pp->picture_qp, 7); + mpp_put_bits(&bp, pp->loop_filter_disable_flag, 1); + mpp_put_bits(&bp, pp->alpha_c_offset, 5); + mpp_put_bits(&bp, pp->beta_offset, 5); + + //!< weight quant param + mpp_put_bits(&bp, wqmp->chroma_quant_param_delta_cb, 6); + mpp_put_bits(&bp, wqmp->chroma_quant_param_delta_cr, 6); + mpp_put_bits(&bp, wqmp->pic_weight_quant_enable_flag, 1); + + //!< alf param + mpp_put_bits(&bp, alfp->enable_pic_alf_y, 1); + mpp_put_bits(&bp, alfp->enable_pic_alf_cb, 1); + mpp_put_bits(&bp, alfp->enable_pic_alf_cr, 1); + + mpp_put_bits(&bp, alfp->alf_filter_num_minus1, 4); + for (i = 0; i < 16; i++) + mpp_put_bits(&bp, alfp->alf_coeff_idx_tab[i], 4); + + for (i = 0; i < 16; i++) + for (j = 0; j < 9; j++) + mpp_put_bits(&bp, alfp->alf_coeff_y[i][j], 7); + + for (j = 0; j < 9; j++) + mpp_put_bits(&bp, alfp->alf_coeff_cb[j], 7); + + for (j = 0; j < 9; j++) + mpp_put_bits(&bp, alfp->alf_coeff_cr[j], 7); + + /* other flags */ + mpp_put_bits(&bp, pp->multi_hypothesis_skip_enable_flag, 1); + mpp_put_bits(&bp, pp->dual_hypothesis_prediction_enable_flag, 1); + mpp_put_bits(&bp, pp->weighted_skip_enable_flag, 1); + mpp_put_bits(&bp, pp->asymmetrc_motion_partitions_enable_flag, 1); + mpp_put_bits(&bp, pp->nonsquare_quadtree_transform_enable_flag, 1); + mpp_put_bits(&bp, pp->nonsquare_intra_prediction_enable_flag, 1); + + //!< picture reference params + mpp_put_bits(&bp, pp->cur_poc, 32); + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, (i < refp->ref_pic_num) ? refp->ref_poc_list[i] : 0, 32); + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, (i < refp->ref_pic_num) ? pp->field_coded_sequence : 0, 1); + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, (i < refp->ref_pic_num) ? pp->bottom_field_picture_flag : 0, 1); + for (i = 0; i < 8; i++) + mpp_put_bits(&bp, (i < refp->ref_pic_num), 1); + + mpp_put_align(&bp, 64, 0); + +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "global_cfg.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)bp.pbuf, + 64 * bp.index + bp.bitpos, 128, 0, 0); + } +#endif + + return MPP_OK; +} + +MPP_RET hal_avs2d_vdpu38x_prepare_scalist(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + Avs2dSyntax_t *syntax = &p_hal->syntax; + WqmParams_Avs2d *wqmp = &syntax->wqmp; + RK_U32 i = 0; + RK_U32 n = 0; + + if (!wqmp->pic_weight_quant_enable_flag) + return MPP_OK; + + memset(data, 0, len); + + /* dump by block4x4, vectial direction */ + for (i = 0; i < 4; i++) { + data[n++] = wqmp->wq_matrix[0][i + 0]; + data[n++] = wqmp->wq_matrix[0][i + 4]; + data[n++] = wqmp->wq_matrix[0][i + 8]; + data[n++] = wqmp->wq_matrix[0][i + 12]; + } + + /* block8x8 */ + { + RK_S32 blk4_x = 0, blk4_y = 0; + + /* dump by block4x4, vectial direction */ + for (blk4_x = 0; blk4_x < 8; blk4_x += 4) { + for (blk4_y = 0; blk4_y < 8; blk4_y += 4) { + RK_S32 pos = blk4_y * 8 + blk4_x; + + for (i = 0; i < 4; i++) { + data[n++] = wqmp->wq_matrix[1][pos + i + 0]; + data[n++] = wqmp->wq_matrix[1][pos + i + 8]; + data[n++] = wqmp->wq_matrix[1][pos + i + 16]; + data[n++] = wqmp->wq_matrix[1][pos + i + 24]; + } + } + } + } + + return MPP_OK; +} + +RK_S32 hal_avs2d_get_frame_fd(Avs2dHalCtx_t *p_hal, RK_S32 idx) +{ + RK_S32 ret_fd = 0; + MppBuffer mbuffer = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, idx, SLOT_BUFFER, &mbuffer); + ret_fd = mpp_buffer_get_fd(mbuffer); + + return ret_fd; +} + +RK_S32 hal_avs2d_get_packet_fd(Avs2dHalCtx_t *p_hal, RK_S32 idx) +{ + RK_S32 ret_fd = 0; + MppBuffer mbuffer = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, idx, SLOT_BUFFER, &mbuffer); + ret_fd = mpp_buffer_get_fd(mbuffer); + + return ret_fd; +} + +MPP_RET hal_avs2d_set_up_colmv_buf(void *hal) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + RK_U32 ctu_size = 1 << (p_hal->syntax.pp.lcu_size); + RK_S32 mv_size = hal_h265d_avs2d_calc_mv_size(pp->pic_width_in_luma_samples, + pp->pic_height_in_luma_samples * + (1 + pp->field_coded_sequence), + ctu_size); + + AVS2D_HAL_TRACE("mv_size %d", mv_size); + + if (p_hal->mv_size < (RK_U32)mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + ret = MPP_ERR_INIT; + goto __RETURN; + } + + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + +__RETURN: + return ret; +} + +RK_U8 hal_avs2d_fetch_data(RK_U32 fmt, RK_U8 *line, RK_U32 num) +{ + RK_U32 offset = 0; + RK_U32 value = 0; + + if (fmt == MPP_FMT_YUV420SP_10BIT) { + offset = (num * 2) & 7; + value = (line[num * 10 / 8] >> offset) | + (line[num * 10 / 8 + 1] << (8 - offset)); + + value = (value & 0x3ff) >> 2; + } else if (fmt == MPP_FMT_YUV420SP) { + value = line[num]; + } + + return value; +} + +MPP_RET hal_avs2d_vdpu_dump_yuv(void *hal, HalTaskInfo *task) +{ + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + MppFrameFormat fmt = MPP_FMT_YUV420SP; + RK_U32 vir_w = 0; + RK_U32 vir_h = 0; + FILE *fp_stream = NULL; + char name[50]; + MppBuffer buffer = NULL; + MppFrame frame; + void *base = NULL; + RK_U32 i, j; + MPP_RET ret = MPP_OK; + + ret = mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &frame); + + if (ret != MPP_OK || frame == NULL) + mpp_log_f("failed to get frame slot %d", task->dec.output); + + ret = mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_BUFFER, &buffer); + + if (ret != MPP_OK || buffer == NULL) + mpp_log_f("failed to get frame buffer slot %d", task->dec.output); + + AVS2D_HAL_TRACE("frame slot %d, fd %d\n", task->dec.output, mpp_buffer_get_fd(buffer)); + base = mpp_buffer_get_ptr(buffer); + vir_w = mpp_frame_get_hor_stride(frame); + vir_h = mpp_frame_get_ver_stride(frame); + fmt = mpp_frame_get_fmt(frame); + snprintf(name, sizeof(name), "/data/tmp/rkv_out_%dx%d_nv12_%03d.yuv", vir_w, vir_h, + p_hal->frame_no); + fp_stream = fopen(name, "wb"); + /* if format is fbc, write fbc header first */ + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + RK_U32 header_size = 0; + + header_size = vir_w * vir_h / 16; + fwrite(base, 1, header_size, fp_stream); + base += header_size; + } + + if (fmt != MPP_FMT_YUV420SP_10BIT) { + fwrite(base, 1, vir_w * vir_h * 3 / 2, fp_stream); + } else { + RK_U8 tmp = 0; + for (i = 0; i < vir_h; i++) { + for (j = 0; j < vir_w; j++) { + tmp = hal_avs2d_fetch_data(fmt, base, j); + fwrite(&tmp, 1, 1, fp_stream); + } + base += vir_w; + } + + for (i = 0; i < vir_h / 2; i++) { + for (j = 0; j < vir_w; j++) { + tmp = hal_avs2d_fetch_data(fmt, base, j); + fwrite(&tmp, 1, 1, fp_stream); + } + base += vir_w; + } + } + fclose(fp_stream); + + return ret; +} + +void vdpu38x_avs2d_rcb_setup(void *hal, HalTaskInfo *task, + Vdpu38xRcbRegSet *rcb_regs, Vdpu38xRcbCalc_f func) +{ + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + Avs2dRkvRegCtx *reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + RK_S32 loop = p_hal->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + MppBuffer rcb_buf = NULL; + MPP_RET ret = MPP_OK; + RK_S32 i = 0; + + /* update rcb info */ + { + RcbTileInfo tl_info; + MppFrame mframe; + MppFrameFormat mpp_fmt; + Vdpu38xFmt rcb_fmt; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_fmt = mpp_frame_get_fmt(mframe); + rcb_fmt = vdpu38x_fmt_mpp2hal(mpp_fmt); + + vdpu38x_rcb_reset(reg_ctx->rcb_ctx); + + /* update general info */ + vdpu38x_rcb_set_pic_w(reg_ctx->rcb_ctx, pp->pic_width_in_luma_samples); + vdpu38x_rcb_set_pic_h(reg_ctx->rcb_ctx, pp->pic_height_in_luma_samples); + vdpu38x_rcb_set_fmt(reg_ctx->rcb_ctx, rcb_fmt); + vdpu38x_rcb_set_bit_depth(reg_ctx->rcb_ctx, pp->bit_depth_luma_minus8 + 8); + + /* update cur spec info */ + vdpu38x_rcb_set_alf_en(reg_ctx->rcb_ctx, pp->adaptive_loop_filter_enable_flag); + + /* add tile info */ + /* Simplify the calculation. */ + tl_info.lt_x = 0; + tl_info.lt_y = 0; + tl_info.w = pp->pic_width_in_luma_samples; + tl_info.h = pp->pic_height_in_luma_samples; + vdpu38x_rcb_set_tile_dir(reg_ctx->rcb_ctx, 0); + vdpu38x_rcb_add_tile_info(reg_ctx->rcb_ctx, &tl_info); + vdpu38x_rcb_register_calc_handle(reg_ctx->rcb_ctx, func); + } + + vdpu38x_rcb_calc_exec(reg_ctx->rcb_ctx, ®_ctx->rcb_buf_size); + + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + + ret = mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, reg_ctx->rcb_buf_size); + if (ret) + mpp_err_f("AVS2D mpp_buffer_get failed\n"); + + reg_ctx->rcb_buf[i] = rcb_buf; + } + + rcb_buf = p_hal->fast_mode ? + reg_ctx->rcb_buf[task->dec.reg_index] : reg_ctx->rcb_buf[0]; + vdpu38x_setup_rcb(reg_ctx->rcb_ctx, rcb_regs, p_hal->cfg->dev, rcb_buf); +} diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_com.h b/mpp/hal/rkdec/avs2d/hal_avs2d_com.h new file mode 100644 index 000000000..be50f43bf --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_com.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AVS2D_COM_H +#define HAL_AVS2D_COM_H + +#include "mpp_env.h" +#include "vdpu38x_com.h" + +MPP_RET hal_avs2d_vdpu_deinit(void *hal); +MPP_RET hal_avs2d_vdpu38x_prepare_header(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len); +MPP_RET hal_avs2d_vdpu38x_prepare_scalist(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len); +RK_S32 hal_avs2d_get_frame_fd(Avs2dHalCtx_t *p_hal, RK_S32 idx); +RK_S32 hal_avs2d_get_packet_fd(Avs2dHalCtx_t *p_hal, RK_S32 idx); +MPP_RET hal_avs2d_set_up_colmv_buf(void *hal); +RK_U8 hal_avs2d_fetch_data(RK_U32 fmt, RK_U8 *line, RK_U32 num); +MPP_RET hal_avs2d_vdpu_dump_yuv(void *hal, HalTaskInfo *task); +void vdpu38x_avs2d_rcb_setup(void *hal, HalTaskInfo *task, + Vdpu38xRcbRegSet *rcb_regs, Vdpu38xRcbCalc_f func); + +#endif /* HAL_AVS2D_COM_H */ diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_ctx.h b/mpp/hal/rkdec/avs2d/hal_avs2d_ctx.h new file mode 100644 index 000000000..77e874bb1 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_ctx.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AVS2D_CTX_H +#define HAL_AVS2D_CTX_H + +#include "vdpu_com.h" + +#define VDPU_TOTAL_REG_CNT 320 + +typedef struct Avs2dRkvBuf_t { + RK_U32 valid; + RK_U32 offset_shph; + RK_U32 offset_sclst; + void *regs; +} Avs2dRkvBuf; + +typedef struct Avs2dRkvRegCtx { + Avs2dRkvBuf reg_buf[VDPU_FAST_REG_SET_CNT]; + + RK_U32 shph_offset; + RK_U32 sclst_offset; + + void *regs; + + RK_U8 *shph_dat; + RK_U8 *scalist_dat; + + MppBuffer bufs; + RK_S32 bufs_fd; + void *bufs_ptr; + + MppBuffer rcb_buf[VDPU_FAST_REG_SET_CNT]; + void *rcb_ctx; + RK_U32 rcb_buf_size; + VdpuRcbInfo rcb_info[RCB_BUF_CNT]; + RK_U32 reg_out[VDPU_TOTAL_REG_CNT]; +} Avs2dRkvRegCtx; + +#endif /* HAL_AVS2D_CTX_H */ + diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_global.h b/mpp/hal/rkdec/avs2d/hal_avs2d_global.h new file mode 100644 index 000000000..d9dee0eef --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_global.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AVS2D_GLOBAL_H +#define HAL_AVS2D_GLOBAL_H + +#include "mpp_device.h" +#include "hal_bufs.h" +#include "mpp_hal.h" + +#include "parser_api.h" +#include "avs2d_syntax.h" + +#define AVS2D_HAL_DBG_ERROR (0x00000001) +#define AVS2D_HAL_DBG_ASSERT (0x00000002) +#define AVS2D_HAL_DBG_WARNNING (0x00000004) +#define AVS2D_HAL_DBG_TRACE (0x00000100) +#define AVS2D_HAL_DBG_REG (0x00000200) +#define AVS2D_HAL_DBG_IN (0x00000400) +#define AVS2D_HAL_DBG_OUT (0x00000800) + +#define AVS2D_HAL_DBG_OFFSET (0x00010000) + +extern RK_U32 hal_avs2d_debug; + +#define AVS2D_HAL_DBG(level, fmt, ...)\ +do {\ + if (level & hal_avs2d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define AVS2D_HAL_TRACE(fmt, ...)\ +do {\ + if (AVS2D_HAL_DBG_TRACE & hal_avs2d_debug)\ + { mpp_log_f(fmt, ## __VA_ARGS__); }\ +} while (0) + + +#define INP_CHECK(ret, val, ...)\ +do{\ + if ((val)) { \ + ret = MPP_ERR_INIT; \ + AVS2D_HAL_DBG(AVS2D_HAL_DBG_WARNNING, "input empty(%d).\n", __LINE__); \ + goto __RETURN; \ + }\ +} while (0) + + +#define FUN_CHECK(val)\ +do{\ + if ((val) < 0) {\ + AVS2D_HAL_DBG(AVS2D_HAL_DBG_WARNNING, "Function error(%d).\n", __LINE__); \ + goto __FAILED; \ + }\ +} while (0) + + +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do{\ + if (!(val)) {\ + ret = MPP_ERR_MALLOC; \ + mpp_err_f("malloc buffer error(%d).\n", __LINE__); \ + goto __FAILED; \ + }\ +} while (0) + + +#define FIELDPICTURE 0 +#define FRAMEPICTURE 1 + +enum { + IFRAME = 0, + PFRAME = 1, + BFRAME = 2 +}; + +typedef struct avs2d_hal_ctx_t { + MppHalCfg *cfg; + HalBufs cmv_bufs; + RK_U32 mv_size; + RK_U32 mv_count; + Avs2dSyntax_t syntax; + RK_U32 fast_mode; + + void *reg_ctx; + MppBuffer shph_buf; + MppBuffer scalist_buf; + + RK_U32 frame_no; +} Avs2dHalCtx_t; + +#endif /* HAL_AVS2D_GLOBAL_H */ diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c b/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c new file mode 100644 index 000000000..13ebf22e3 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.c @@ -0,0 +1,987 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_avs2d_rkv" + +#include +#include + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_debug.h" +#include "mpp_bitput.h" + +#include "avs2d_syntax.h" +#include "hal_avs2d_rkv.h" +#include "mpp_dec_cb_param.h" +#include "vdpu34x_avs2d.h" +#include "hal_avs2d_ctx.h" +#include "hal_avs2d_com.h" + +#define MAX_REF_NUM (8) +#define AVS2_RKV_SHPH_SIZE (1408 / 8) /* bytes */ +#define AVS2_RKV_SCALIST_SIZE (80 + 128) /* bytes */ + +#define AVS2_RKV_SHPH_ALIGNED_SIZE (MPP_ALIGN(AVS2_RKV_SHPH_SIZE, SZ_4K)) +#define AVS2_RKV_SCALIST_ALIGNED_SIZE (MPP_ALIGN(AVS2_RKV_SCALIST_SIZE, SZ_4K)) +#define AVS2_RKV_STREAM_INFO_SET_SIZE (AVS2_RKV_SHPH_ALIGNED_SIZE + \ + AVS2_RKV_SCALIST_ALIGNED_SIZE) +#define AVS2_ALL_TBL_BUF_SIZE(cnt) (AVS2_RKV_STREAM_INFO_SET_SIZE * (cnt)) +#define AVS2_SHPH_OFFSET(pos) (AVS2_RKV_STREAM_INFO_SET_SIZE * (pos)) +#define AVS2_SCALIST_OFFSET(pos) (AVS2_SHPH_OFFSET(pos) + AVS2_RKV_SHPH_ALIGNED_SIZE) + +#define COLMV_COMPRESS_EN (1) +#define COLMV_BLOCK_SIZE (16) +#define COLMV_BYTES (16) + + +MPP_RET hal_avs2d_rkv_deinit(void *hal); + +static MPP_RET prepare_header(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + RK_U32 i, j; + BitputCtx_t bp; + RK_U64 *bit_buf = (RK_U64 *)data; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + AlfParams_Avs2d *alfp = &syntax->alfp; + RefParams_Avs2d *refp = &syntax->refp; + WqmParams_Avs2d *wqmp = &syntax->wqmp; + + memset(data, 0, len); + + mpp_set_bitput_ctx(&bp, bit_buf, len); + //!< sequence header syntax + mpp_put_bits(&bp, pp->chroma_format_idc, 2); + mpp_put_bits(&bp, pp->pic_width_in_luma_samples, 16); + mpp_put_bits(&bp, pp->pic_height_in_luma_samples, 16); + mpp_put_bits(&bp, pp->bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, pp->bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, pp->lcu_size, 3); + mpp_put_bits(&bp, pp->progressive_sequence, 1); + mpp_put_bits(&bp, pp->field_coded_sequence, 1); + mpp_put_bits(&bp, pp->multi_hypothesis_skip_enable_flag, 1); + mpp_put_bits(&bp, pp->dual_hypothesis_prediction_enable_flag, 1); + mpp_put_bits(&bp, pp->weighted_skip_enable_flag, 1); + mpp_put_bits(&bp, pp->asymmetrc_motion_partitions_enable_flag, 1); + mpp_put_bits(&bp, pp->nonsquare_quadtree_transform_enable_flag, 1); + mpp_put_bits(&bp, pp->nonsquare_intra_prediction_enable_flag, 1); + mpp_put_bits(&bp, pp->secondary_transform_enable_flag, 1); + mpp_put_bits(&bp, pp->sample_adaptive_offset_enable_flag, 1); + mpp_put_bits(&bp, pp->adaptive_loop_filter_enable_flag, 1); + mpp_put_bits(&bp, pp->pmvr_enable_flag, 1); + mpp_put_bits(&bp, pp->cross_slice_loopfilter_enable_flag, 1); + //!< picture header syntax + mpp_put_bits(&bp, pp->picture_type, 3); + mpp_put_bits(&bp, refp->ref_pic_num, 3); + mpp_put_bits(&bp, pp->scene_reference_enable_flag, 1); + mpp_put_bits(&bp, pp->bottom_field_picture_flag, 1); + mpp_put_bits(&bp, pp->fixed_picture_qp, 1); + mpp_put_bits(&bp, pp->picture_qp, 7); + mpp_put_bits(&bp, pp->loop_filter_disable_flag, 1); + mpp_put_bits(&bp, pp->alpha_c_offset, 5); + mpp_put_bits(&bp, pp->beta_offset, 5); + //!< weight quant param + mpp_put_bits(&bp, wqmp->chroma_quant_param_delta_cb, 6); + mpp_put_bits(&bp, wqmp->chroma_quant_param_delta_cr, 6); + mpp_put_bits(&bp, wqmp->pic_weight_quant_enable_flag, 1); + //!< alf param + mpp_put_bits(&bp, alfp->enable_pic_alf_y, 1); + mpp_put_bits(&bp, alfp->enable_pic_alf_cb, 1); + mpp_put_bits(&bp, alfp->enable_pic_alf_cr, 1); + + if (alfp->enable_pic_alf_y) { + RK_U32 alf_filter_num = alfp->alf_filter_num_minus1 + 1; + mpp_put_bits(&bp, alfp->alf_filter_num_minus1, 4); + + for (i = 0; i < 16; i++) + mpp_put_bits(&bp, alfp->alf_coeff_idx_tab[i], 4); + + for (i = 0; i < alf_filter_num; i++) { + for (j = 0; j < 9; j++) { + mpp_put_bits(&bp, alfp->alf_coeff_y[i][j], 7); + } + } + } + + if (alfp->enable_pic_alf_cb) { + for (j = 0; j < 9; j++) + mpp_put_bits(&bp, alfp->alf_coeff_cb[j], 7); + } + + if (alfp->enable_pic_alf_cr) { + for (j = 0; j < 9; j++) + mpp_put_bits(&bp, alfp->alf_coeff_cr[j], 7); + } + + mpp_put_align(&bp, 128, 0); + + return MPP_OK; +} + +static MPP_RET prepare_scalist(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + RK_U32 i, j; + RK_U32 size_id, block_size; + BitputCtx_t bp; + RK_U64 *bit_buf = (RK_U64 *)data; + Avs2dSyntax_t *syntax = &p_hal->syntax; + WqmParams_Avs2d *wqmp = &syntax->wqmp; + + if (!wqmp->pic_weight_quant_enable_flag) + return MPP_OK; + + memset(data, 0, len); + + mpp_set_bitput_ctx(&bp, bit_buf, len); + + for (size_id = 0; size_id < 2; size_id++) { + block_size = MPP_MIN(1 << (size_id + 2), 8); + for (i = 0; i < block_size; i++) { + for (j = 0 ; j < block_size; j++) + //!< row col reversed + mpp_put_bits(&bp, wqmp->wq_matrix[size_id][size_id * j + i], 8); + } + } + + return MPP_OK; +} + +static MPP_RET init_common_regs(Vdpu34xAvs2dRegSet *regs) +{ + Vdpu34xRegCommon *common = ®s->common; + + common->reg009.dec_mode = 3; // AVS2 + common->reg015.rlc_mode = 0; + + common->reg011.buf_empty_en = 1; + common->reg011.dec_timeout_e = 1; + + common->reg010.dec_e = 1; + + common->reg013.h26x_error_mode = 0; + common->reg013.colmv_error_mode = 0; + common->reg013.h26x_streamd_error_mode = 0; + common->reg021.inter_error_prc_mode = 0; + common->reg021.error_deb_en = 0; + common->reg021.error_intra_mode = 0; + + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) { + common->reg024.cabac_err_en_lowbits = 0; + common->reg025.cabac_err_en_highbits = 0; + common->reg026.swreg_block_gating_e = 0xfffef; + } else { + common->reg024.cabac_err_en_lowbits = 0xffffffdf; + common->reg025.cabac_err_en_highbits = 0x3dffffff; + common->reg026.swreg_block_gating_e = 0xfffff; + } + + common->reg026.reg_cfg_gating_en = 1; + common->reg032_timeout_threshold = 0x3fffff; + + common->reg011.dec_clkgate_e = 1; + common->reg011.dec_e_strmd_clkgate_dis = 0; + common->reg011.dec_timeout_e = 1; + + common->reg013.timeout_mode = 1; + common->reg013.stmerror_waitdecfifo_empty = 1; + common->reg012.colmv_compress_en = COLMV_COMPRESS_EN; + common->reg012.wr_ddr_align_en = 1; + common->reg012.info_collect_en = 1; + common->reg012.error_info_en = 0; + + return MPP_OK; +} + +//TODO calc rcb buffer size; +/* +static void avs2d_refine_rcb_size(VdpuRcbInfo *rcb_info, + Vdpu34xAvs2dRegSet *hw_regs, + RK_S32 width, RK_S32 height, void *dxva) +{ + (void) rcb_info; + (void) hw_regs; + (void) width; + (void) height; + (void) dxva; + return; +} +*/ + +static void hal_avs2d_rcb_info_update(void *hal, Vdpu34xAvs2dRegSet *hw_regs) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + RK_S32 width = p_hal->syntax.pp.pic_width_in_luma_samples; + RK_S32 height = p_hal->syntax.pp.pic_height_in_luma_samples; + RK_S32 i = 0; + RK_S32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + + (void) hw_regs; + + reg_ctx->rcb_buf_size = vdpu34x_get_rcb_buf_size(reg_ctx->rcb_info, width, height); + //avs2d_refine_rcb_size(reg_ctx->rcb_info, hw_regs, width, height, (void *)&p_hal->syntax); + + for (i = 0; i < loop; i++) { + MppBuffer rcb_buf = NULL; + + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + + ret = mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, reg_ctx->rcb_buf_size); + if (ret) + mpp_err_f("AVS2D mpp_buffer_get failed\n"); + + reg_ctx->rcb_buf[i] = rcb_buf; + } +} + +static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu34xAvs2dRegSet *p_regs, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + MppFrame mframe = NULL; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + RefParams_Avs2d *refp = &syntax->refp; + HalDecTask *task_dec = &task->dec; + Vdpu34xRegCommon *common = &p_regs->common; + RK_U32 is_fbc = 0; + HalBuf *mv_buf = NULL; + MppBufSlots frm_slots = p_hal->cfg->frame_slots; + + mpp_buf_slot_get_prop(frm_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + is_fbc = MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe)); + + //!< caculate the yuv_frame_size + { + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + AVS2D_HAL_TRACE("is_fbc %d y_virstride %d, hor_virstride %d, ver_virstride %d\n", is_fbc, y_virstride, hor_virstride, ver_virstride); + + if (is_fbc) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (ver_virstride + 16) / 16, SZ_4K); + + common->reg012.fbc_e = 1; + common->reg018.y_hor_virstride = fbc_hdr_stride / 16; + common->reg019.uv_hor_virstride = fbc_hdr_stride / 16; + common->reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + common->reg012.fbc_e = 0; + common->reg018.y_hor_virstride = hor_virstride / 16; + common->reg019.uv_hor_virstride = hor_virstride / 16; + common->reg020_y_virstride.y_virstride = y_virstride / 16; + } + common->reg013.cur_pic_is_idr = (pp->picture_type == 0 || pp->picture_type == 4 || pp->picture_type == 5); + } + + // set current + { + RK_S32 fd = -1; + p_regs->avs2d_param.reg65_cur_top_poc = mpp_frame_get_poc(mframe); + p_regs->avs2d_param.reg66_cur_bot_poc = 0; + fd = hal_avs2d_get_frame_fd(p_hal, task_dec->output); + mpp_assert(fd >= 0); + p_regs->common_addr.reg130_decout_base = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, task_dec->output); + p_regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + AVS2D_HAL_TRACE("cur frame index %d, fd %d, colmv fd %d", task_dec->output, fd, p_regs->common_addr.reg131_colmv_cur_base); + } + + // set reference + { + RK_U64 ref_flag = 0; + RK_S32 valid_slot = -1; + RK_U32 *ref_low = (RK_U32 *)&p_regs->avs2d_param.reg99; + RK_U32 *ref_hight = (RK_U32 *)&p_regs->avs2d_param.reg100; + RK_U32 err_ref_base = 0; + + AVS2D_HAL_TRACE("num of ref %d", refp->ref_pic_num); + + for (i = 0; i < refp->ref_pic_num; i++) { + if (task_dec->refer[i] < 0) + continue; + + valid_slot = i; + break; + } + + for (i = 0; i < refp->ref_pic_num; i++) { + MppFrame frame_ref = NULL; + + RK_S32 slot_idx = task_dec->refer[i] < 0 ? task_dec->refer[valid_slot] : task_dec->refer[i]; + + if (slot_idx < 0) { + AVS2D_HAL_DBG(AVS2D_HAL_DBG_ERROR, "missing ref, could not found valid ref"); + task->dec.flags.ref_err = 1; + return ret = MPP_ERR_UNKNOW; + } + + mpp_buf_slot_get_prop(frm_slots, slot_idx, SLOT_FRAME_PTR, &frame_ref); + + if (frame_ref) { + RK_U32 frm_flag = 1 << 3; + + if (pp->bottom_field_picture_flag) + frm_flag |= 1 << 2; + + if (pp->field_coded_sequence) + frm_flag |= 1; + + ref_flag |= frm_flag << (i * 8); + + p_regs->avs2d_addr.ref_base[i] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + p_regs->avs2d_addr.colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + + p_regs->avs2d_param.reg67_098_ref_poc[i] = mpp_frame_get_poc(frame_ref); + + if (!err_ref_base && !mpp_frame_get_errinfo(frame_ref)) + err_ref_base = p_regs->avs2d_addr.ref_base[i]; + + AVS2D_HAL_TRACE("ref_base[%d] index=%d, fd = %d, colmv %d, poc %d", + i, slot_idx, p_regs->avs2d_addr.ref_base[i], + p_regs->avs2d_addr.colmv_base[i], p_regs->avs2d_param.reg67_098_ref_poc[i]); + } + } + + if (p_hal->syntax.refp.scene_ref_enable && p_hal->syntax.refp.scene_ref_slot_idx >= 0) { + MppFrame scene_ref = NULL; + RK_S32 slot_idx = p_hal->syntax.refp.scene_ref_slot_idx; + RK_S32 replace_idx = p_hal->syntax.refp.scene_ref_replace_pos; + + mpp_buf_slot_get_prop(frm_slots, slot_idx, SLOT_FRAME_PTR, &scene_ref); + + if (scene_ref) { + p_regs->avs2d_addr.ref_base[replace_idx] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + p_regs->avs2d_addr.colmv_base[replace_idx] = mpp_buffer_get_fd(mv_buf->buf[0]); + p_regs->avs2d_param.reg67_098_ref_poc[replace_idx] = mpp_frame_get_poc(scene_ref); + } + } + + *ref_low = (RK_U32) (ref_flag & 0xffffffff); + *ref_hight = (RK_U32) ((ref_flag >> 32) & 0xffffffff); + + p_regs->common_addr.reg132_error_ref_base = err_ref_base; + } + + // set rlc + { + p_regs->common_addr.reg128_rlc_base = hal_avs2d_get_packet_fd(p_hal, task_dec->input); + AVS2D_HAL_TRACE("packet fd %d from slot %d", p_regs->common_addr.reg128_rlc_base, task_dec->input); + p_regs->common_addr.reg129_rlcwrite_base = p_regs->common_addr.reg128_rlc_base; + common->reg016_str_len = MPP_ALIGN(mpp_packet_get_length(task_dec->input_packet), 16) + 64; + } + + return ret; +} + +MPP_RET hal_avs2d_rkv_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + RK_U32 i, loop; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == reg_ctx); + + //!< malloc buffers + loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + + MPP_FREE(reg_ctx->reg_buf[i].regs); + } + + if (reg_ctx->bufs) { + mpp_buffer_put(reg_ctx->bufs); + reg_ctx->bufs = NULL; + } + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + MPP_FREE(reg_ctx->shph_dat); + MPP_FREE(reg_ctx->scalist_dat); + + MPP_FREE(p_hal->reg_ctx); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +MPP_RET hal_avs2d_rkv_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + RK_U32 i, loop; + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + + mpp_env_get_u32("hal_avs2d_debug", &hal_avs2d_debug, 0); + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Avs2dRkvRegCtx))); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + //!< malloc buffers + reg_ctx->shph_dat = mpp_calloc(RK_U8, AVS2_RKV_SHPH_SIZE); + reg_ctx->scalist_dat = mpp_calloc(RK_U8, AVS2_RKV_SCALIST_SIZE); + loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, AVS2_ALL_TBL_BUF_SIZE(loop))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + + for (i = 0; i < loop; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu34xAvs2dRegSet, 1); + init_common_regs(reg_ctx->reg_buf[i].regs); + reg_ctx->reg_buf[i].offset_shph = AVS2_SHPH_OFFSET(i); + reg_ctx->reg_buf[i].offset_sclst = AVS2_SCALIST_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[0].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[0].offset_sclst; + } + + if (MPP_FRAME_FMT_IS_FBC(cfg->cfg->base.out_fmt)) + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_64); + else + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + + return ret; +__FAILED: + hal_avs2d_rkv_deinit(p_hal); + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +static MPP_RET set_up_colmv_buf(void *hal) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + RK_U32 mv_size = 0; + RK_U32 ctu_size = 1 << (p_hal->syntax.pp.lcu_size); + RK_U32 width = p_hal->syntax.pp.pic_width_in_luma_samples; + RK_U32 height = p_hal->syntax.pp.pic_height_in_luma_samples; + + mv_size = vdpu34x_get_colmv_size(width, height, ctu_size, COLMV_BYTES, + COLMV_BLOCK_SIZE, COLMV_COMPRESS_EN); + if (pp->field_coded_sequence) + mv_size *= 2; + AVS2D_HAL_TRACE("mv_size %d", mv_size); + + if (p_hal->cmv_bufs == NULL || p_hal->mv_size < mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + ret = MPP_ERR_INIT; + goto __RETURN; + } + + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + +__RETURN: + return ret; +} + +MPP_RET hal_avs2d_rkv_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Vdpu34xAvs2dRegSet *regs = NULL; + MppHalCfg *cfg = p_hal->cfg; + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !cfg->cfg->base.disable_error) { + ret = MPP_NOK; + goto __RETURN; + } + + memcpy(&p_hal->syntax, task->dec.syntax.data, sizeof(Avs2dSyntax_t)); + ret = set_up_colmv_buf(p_hal); + if (ret) + goto __RETURN; + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + if (p_hal->fast_mode) { + RK_U32 i = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(reg_ctx->reg_buf); i++) { + if (!reg_ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = reg_ctx->reg_buf[i].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[i].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[i].offset_sclst; + reg_ctx->regs = reg_ctx->reg_buf[i].regs; + reg_ctx->reg_buf[i].valid = 1; + break; + } + } + + mpp_assert(regs); + } + + regs = reg_ctx->regs; + memset(regs, 0, sizeof(Vdpu34xAvs2dRegSet)); + init_common_regs(regs); + + prepare_header(p_hal, reg_ctx->shph_dat, AVS2_RKV_SHPH_SIZE / 8); + prepare_scalist(p_hal, reg_ctx->scalist_dat, AVS2_RKV_SCALIST_SIZE / 8); + + ret = fill_registers(p_hal, regs, task); + + if (ret) + goto __RETURN; + + { + memcpy(reg_ctx->bufs_ptr + reg_ctx->shph_offset, reg_ctx->shph_dat, AVS2_RKV_SHPH_SIZE); + memcpy(reg_ctx->bufs_ptr + reg_ctx->sclst_offset, reg_ctx->scalist_dat, AVS2_RKV_SCALIST_SIZE); + regs->common.reg012.scanlist_addr_valid_en = 1; + + regs->avs2d_addr.head_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 161, reg_ctx->shph_offset); + + regs->avs2d_param.reg105.head_len = AVS2_RKV_SHPH_SIZE / 16; + regs->avs2d_param.reg105.head_len -= (regs->avs2d_param.reg105.head_len > 0) ? 1 : 0; + + regs->avs2d_addr.scanlist_addr = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 180, reg_ctx->sclst_offset); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) { + FILE *fp_shph = NULL; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_shph_%03d.bin", p_hal->frame_no); + fp_shph = fopen(name, "wb"); + fwrite(reg_ctx->bufs_ptr + reg_ctx->shph_offset, 1, AVS2_RKV_SHPH_SIZE, fp_shph); + fclose(fp_shph); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) { + FILE *fp_scalist = NULL; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_scalist_%03d.bin", p_hal->frame_no); + fp_scalist = fopen(name, "wb"); + fwrite(reg_ctx->bufs_ptr + reg_ctx->sclst_offset, 1, AVS2_RKV_SCALIST_SIZE, fp_scalist); + fclose(fp_scalist); + } + + // set rcb + { + hal_avs2d_rcb_info_update(p_hal, regs); + vdpu34x_setup_rcb(®s->common_addr, cfg->dev, (p_hal->fast_mode != 0) ? + reg_ctx->rcb_buf[task->dec.reg_index] : reg_ctx->rcb_buf[0], + reg_ctx->rcb_info); + + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) { + FILE *fp_rcb = NULL; + char name[50]; + void *base = NULL; + snprintf(name, sizeof(name), "/data/tmp/rkv_rcb_%03d.bin", p_hal->frame_no); + fp_rcb = fopen(name, "wb"); + base = mpp_buffer_get_ptr(reg_ctx->rcb_buf[0]); + fwrite(base, 1, reg_ctx->rcb_buf_size, fp_rcb); + fclose(fp_rcb); + + } + + vdpu34x_setup_statistic(®s->common, ®s->statistic); + mpp_buffer_sync_end(reg_ctx->bufs); + + /* enable reference frame usage feedback */ + regs->statistic.reg265.perf_cnt0_sel = 42; + regs->statistic.reg266_perf_cnt0 = 0; + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +static MPP_RET hal_avs2d_rkv_dump_reg_write(void *hal, Vdpu34xAvs2dRegSet *regs) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + FILE *fp_reg = NULL; + RK_U32 i = 0; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_reg_write_%03d.txt", p_hal->frame_no); + fp_reg = fopen(name , "w+"); + + fprintf(fp_reg, "********Frame num %d\n", p_hal->frame_no); + for (i = 0; i < 8; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i, 0); + + for (i = 0; i < sizeof(Vdpu34xRegCommon) / sizeof(RK_U32); i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU34X_OFF_COMMON_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->common)[i]); + + for (i = 0; i < 63 - 32; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 33, 0); + + for (i = 0; i < sizeof(Vdpu34xRegAvs2dParam) / sizeof(RK_U32); i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU34X_OFF_CODEC_PARAMS_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->avs2d_param)[i]); + + for (i = 0; i < 127 - 112; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 113, 0); + + for (i = 0; i < sizeof(Vdpu34xRegCommonAddr) / sizeof(RK_U32); i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU34X_OFF_COMMON_ADDR_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->common_addr)[i]); + + for (i = 0; i < 159 - 142; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 143, 0); + + + for (i = 0; i < sizeof(Vdpu34xRegAvs2dAddr) / sizeof(RK_U32); i++ ) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU34X_OFF_CODEC_ADDR_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->avs2d_addr)[i]); + + for (i = 0; i < 223 - 197; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 198, 0); + + for (i = 0; i < sizeof(Vdpu34xRegIrqStatus) / sizeof(RK_U32); i++ ) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU34X_OFF_INTERRUPT_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->irq_status)[i]); + + for (i = 0; i < 255 - 237; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 238, 0); + + for (i = 0; i < sizeof(Vdpu34xRegStatistic) / sizeof(RK_U32); i++ ) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU34X_OFF_STATISTIC_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->statistic)[i]); + + fclose(fp_reg); + return ret; +} + +static MPP_RET hal_avs2d_rkv_dump_stream(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + + FILE *fp_stream = NULL; + char name[50]; + MppBuffer buffer = NULL; + void *base = NULL; + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &buffer); + base = mpp_buffer_get_ptr(buffer); + snprintf(name, sizeof(name), "/data/tmp/rkv_stream_in_%03d.bin", p_hal->frame_no); + fp_stream = fopen(name, "wb"); + fwrite(base, 1, mpp_packet_get_length(task->dec.input_packet), fp_stream); + fclose(fp_stream); + + return ret; +} + +MPP_RET hal_avs2d_rkv_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Vdpu34xAvs2dRegSet *regs = NULL; + Avs2dRkvRegCtx *reg_ctx; + MppDev dev = NULL; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + + AVS2D_HAL_TRACE("In."); + INP_CHECK(ret, NULL == p_hal); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + ret = MPP_NOK; + goto __RETURN; + } + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + regs = (p_hal->fast_mode != 0) ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + dev = p_hal->cfg->dev; + + p_hal->frame_no++; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->common; + wr_cfg.size = sizeof(regs->common); + wr_cfg.offset = VDPU34X_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->avs2d_param; + wr_cfg.size = sizeof(regs->avs2d_param); + wr_cfg.offset = VDPU34X_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->common_addr; + wr_cfg.size = sizeof(regs->common_addr); + wr_cfg.offset = VDPU34X_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->avs2d_addr; + wr_cfg.size = sizeof(regs->avs2d_addr); + wr_cfg.offset = VDPU34X_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->statistic; + wr_cfg.size = sizeof(regs->statistic); + wr_cfg.offset = VDPU34X_OFF_STATISTIC_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->irq_status; + rd_cfg.size = sizeof(regs->irq_status); + rd_cfg.offset = VDPU34X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->avs2d_param; + rd_cfg.size = sizeof(regs->avs2d_param); + rd_cfg.offset = VDPU34X_OFF_CODEC_PARAMS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->statistic; + rd_cfg.size = sizeof(regs->statistic); + rd_cfg.offset = VDPU34X_OFF_STATISTIC_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) { + memset(reg_ctx->reg_out, 0, sizeof(reg_ctx->reg_out)); + rd_cfg.reg = reg_ctx->reg_out; + rd_cfg.size = sizeof(reg_ctx->reg_out); + rd_cfg.offset = 0; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + // rcb info for sram + vdpu34x_set_rcbinfo(dev, reg_ctx->rcb_info); + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) + hal_avs2d_rkv_dump_stream(hal, task); + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) + hal_avs2d_rkv_dump_reg_write(hal, regs); + + // send request to hardware + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + + } while (0); + +__RETURN: + AVS2D_HAL_TRACE("Out."); + return ret; +} + +MPP_RET hal_avs2d_rkv_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx; + Vdpu34xAvs2dRegSet *p_regs; + + INP_CHECK(ret, NULL == p_hal); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + p_regs = (p_hal->fast_mode != 0) ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + AVS2D_HAL_DBG(AVS2D_HAL_DBG_ERROR, "found task error.\n"); + ret = MPP_NOK; + goto __RETURN; + } else { + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_OUT) + hal_avs2d_vdpu_dump_yuv(hal, task); + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) { + FILE *fp_reg = NULL; + RK_U32 i = 0; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_reg_read_%03d.txt", p_hal->frame_no); + fp_reg = fopen(name , "w+"); + + for (i = 0; i < 278; i++) + fprintf(fp_reg, "%08x\n", reg_ctx->reg_out[i]); + + fclose(fp_reg); + } + + AVS2D_HAL_TRACE("read reg[224] 0x%08x\n", p_regs->irq_status.reg224); + + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + + if (p_regs->irq_status.reg224.dec_error_sta || + (!p_regs->irq_status.reg224.dec_rdy_sta) || + p_regs->irq_status.reg224.buf_empty_sta || + p_regs->irq_status.reg226.strmd_error_status || + p_regs->irq_status.reg227.colmv_error_ref_picidx || + p_regs->irq_status.reg225.strmd_detect_error_flag) + param.hard_err = 1; + else + param.hard_err = 0; + + task->dec.flags.ref_used = p_regs->statistic.reg266_perf_cnt0; + task->dec.flags.ref_info_valid = 1; + + if (task->dec.flags.ref_miss) { + RK_U32 ref_hw_usage = p_regs->statistic.reg266_perf_cnt0; + + AVS2D_HAL_TRACE("hal frame %d ref miss %x hard_err %d hw_usage %x", p_hal->frame_no, + task->dec.flags.ref_miss, param.hard_err, ref_hw_usage); + } + + AVS2D_HAL_TRACE("hal frame %d hard_err= %d", p_hal->frame_no, param.hard_err); + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + + memset(&p_regs->irq_status.reg224, 0, sizeof(RK_U32)); + + if (p_hal->fast_mode) + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +const MppHalApi hal_avs2d_rkvdpu = { + .name = "avs2d_rkvdpu", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVS2, + .ctx_size = sizeof(Avs2dHalCtx_t), + .flag = 0, + .init = hal_avs2d_rkv_init, + .deinit = hal_avs2d_vdpu_deinit, + .reg_gen = hal_avs2d_rkv_gen_regs, + .start = hal_avs2d_rkv_start, + .wait = hal_avs2d_rkv_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_avs2d_rkvdpu) diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.h b/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.h new file mode 100644 index 000000000..1ff4e3522 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_rkv.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVS2D_RKV_H +#define HAL_AVS2D_RKV_H + +#include "mpp_device.h" + +#include "parser_api.h" +#include "hal_avs2d_global.h" +#include "avs2d_syntax.h" + +#define AVS2D_REGISTERS (278) + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_avs2d_rkvdpu; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVS2D_RKV_H */ diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu382.c b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu382.c new file mode 100644 index 000000000..8e4681c00 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu382.c @@ -0,0 +1,1012 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_avs2d_vdpu382" + +#include +#include + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_debug.h" +#include "mpp_bitput.h" + +#include "avs2d_syntax.h" +#include "hal_avs2d_vdpu382.h" +#include "mpp_dec_cb_param.h" +#include "vdpu382_avs2d.h" +#include "vdpu_com.h" +#include "hal_avs2d_ctx.h" +#include "hal_avs2d_com.h" + +#define MAX_REF_NUM (8) +#define AVS2_RKV_SHPH_SIZE (1408 / 8) /* bytes */ +#define AVS2_RKV_SCALIST_SIZE (80 + 128) /* bytes */ + +#define AVS2_RKV_SHPH_ALIGNED_SIZE (MPP_ALIGN(AVS2_RKV_SHPH_SIZE, SZ_4K)) +#define AVS2_RKV_SCALIST_ALIGNED_SIZE (MPP_ALIGN(AVS2_RKV_SCALIST_SIZE, SZ_4K)) +#define AVS2_RKV_STREAM_INFO_SET_SIZE (AVS2_RKV_SHPH_ALIGNED_SIZE + \ + AVS2_RKV_SCALIST_ALIGNED_SIZE) +#define AVS2_ALL_TBL_BUF_SIZE(cnt) (AVS2_RKV_STREAM_INFO_SET_SIZE * (cnt)) +#define AVS2_SHPH_OFFSET(pos) (AVS2_RKV_STREAM_INFO_SET_SIZE * (pos)) +#define AVS2_SCALIST_OFFSET(pos) (AVS2_SHPH_OFFSET(pos) + AVS2_RKV_SHPH_ALIGNED_SIZE) + +#define COLMV_COMPRESS_EN (1) +#define COLMV_BLOCK_SIZE (16) +#define COLMV_BYTES (16) + + +static MPP_RET prepare_header(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + RK_U32 i, j; + BitputCtx_t bp; + RK_U64 *bit_buf = (RK_U64 *)data; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + AlfParams_Avs2d *alfp = &syntax->alfp; + RefParams_Avs2d *refp = &syntax->refp; + WqmParams_Avs2d *wqmp = &syntax->wqmp; + + memset(data, 0, len); + + mpp_set_bitput_ctx(&bp, bit_buf, len); + //!< sequence header syntax + mpp_put_bits(&bp, pp->chroma_format_idc, 2); + mpp_put_bits(&bp, pp->pic_width_in_luma_samples, 16); + mpp_put_bits(&bp, pp->pic_height_in_luma_samples, 16); + mpp_put_bits(&bp, pp->bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, pp->bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, pp->lcu_size, 3); + mpp_put_bits(&bp, pp->progressive_sequence, 1); + mpp_put_bits(&bp, pp->field_coded_sequence, 1); + mpp_put_bits(&bp, pp->multi_hypothesis_skip_enable_flag, 1); + mpp_put_bits(&bp, pp->dual_hypothesis_prediction_enable_flag, 1); + mpp_put_bits(&bp, pp->weighted_skip_enable_flag, 1); + mpp_put_bits(&bp, pp->asymmetrc_motion_partitions_enable_flag, 1); + mpp_put_bits(&bp, pp->nonsquare_quadtree_transform_enable_flag, 1); + mpp_put_bits(&bp, pp->nonsquare_intra_prediction_enable_flag, 1); + mpp_put_bits(&bp, pp->secondary_transform_enable_flag, 1); + mpp_put_bits(&bp, pp->sample_adaptive_offset_enable_flag, 1); + mpp_put_bits(&bp, pp->adaptive_loop_filter_enable_flag, 1); + mpp_put_bits(&bp, pp->pmvr_enable_flag, 1); + mpp_put_bits(&bp, pp->cross_slice_loopfilter_enable_flag, 1); + //!< picture header syntax + mpp_put_bits(&bp, pp->picture_type, 3); + mpp_put_bits(&bp, refp->ref_pic_num, 3); + mpp_put_bits(&bp, pp->scene_reference_enable_flag, 1); + mpp_put_bits(&bp, pp->bottom_field_picture_flag, 1); + mpp_put_bits(&bp, pp->fixed_picture_qp, 1); + mpp_put_bits(&bp, pp->picture_qp, 7); + mpp_put_bits(&bp, pp->loop_filter_disable_flag, 1); + mpp_put_bits(&bp, pp->alpha_c_offset, 5); + mpp_put_bits(&bp, pp->beta_offset, 5); + //!< weight quant param + mpp_put_bits(&bp, wqmp->chroma_quant_param_delta_cb, 6); + mpp_put_bits(&bp, wqmp->chroma_quant_param_delta_cr, 6); + mpp_put_bits(&bp, wqmp->pic_weight_quant_enable_flag, 1); + //!< alf param + mpp_put_bits(&bp, alfp->enable_pic_alf_y, 1); + mpp_put_bits(&bp, alfp->enable_pic_alf_cb, 1); + mpp_put_bits(&bp, alfp->enable_pic_alf_cr, 1); + + if (alfp->enable_pic_alf_y) { + RK_U32 alf_filter_num = alfp->alf_filter_num_minus1 + 1; + mpp_put_bits(&bp, alfp->alf_filter_num_minus1, 4); + + for (i = 0; i < 16; i++) + mpp_put_bits(&bp, alfp->alf_coeff_idx_tab[i], 4); + + for (i = 0; i < alf_filter_num; i++) { + for (j = 0; j < 9; j++) { + mpp_put_bits(&bp, alfp->alf_coeff_y[i][j], 7); + } + } + } + + if (alfp->enable_pic_alf_cb) { + for (j = 0; j < 9; j++) + mpp_put_bits(&bp, alfp->alf_coeff_cb[j], 7); + } + + if (alfp->enable_pic_alf_cr) { + for (j = 0; j < 9; j++) + mpp_put_bits(&bp, alfp->alf_coeff_cr[j], 7); + } + + mpp_put_align(&bp, 128, 0); + + return MPP_OK; +} + +static MPP_RET prepare_scalist(Avs2dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + RK_U32 i, j; + RK_U32 size_id, block_size; + BitputCtx_t bp; + RK_U64 *bit_buf = (RK_U64 *)data; + Avs2dSyntax_t *syntax = &p_hal->syntax; + WqmParams_Avs2d *wqmp = &syntax->wqmp; + + if (!wqmp->pic_weight_quant_enable_flag) + return MPP_OK; + + memset(data, 0, len); + + mpp_set_bitput_ctx(&bp, bit_buf, len); + + for (size_id = 0; size_id < 2; size_id++) { + block_size = MPP_MIN(1 << (size_id + 2), 8); + for (i = 0; i < block_size; i++) { + for (j = 0 ; j < block_size; j++) + //!< row col reversed + mpp_put_bits(&bp, wqmp->wq_matrix[size_id][size_id * j + i], 8); + } + } + + return MPP_OK; +} + +static MPP_RET init_common_regs(Vdpu382Avs2dRegSet *regs) +{ + Vdpu382RegCommon *common = ®s->common; + + common->reg009.dec_mode = 3; // AVS2 + common->reg015.rlc_mode = 0; + + common->reg011.buf_empty_en = 1; + common->reg011.err_head_fill_e = 1; + common->reg011.err_colmv_fill_e = 1; + + common->reg010.dec_e = 1; + + common->reg013.h26x_error_mode = 0; + common->reg021.inter_error_prc_mode = 0; + common->reg021.error_deb_en = 0; + common->reg021.error_intra_mode = 0; + + common->reg024.cabac_err_en_lowbits = 0xffffffdf; + common->reg025.cabac_err_en_highbits = 0x3dffffff; + + common->reg026.inter_auto_gating_e = 1; + common->reg026.filterd_auto_gating_e = 1; + common->reg026.strmd_auto_gating_e = 1; + common->reg026.mcp_auto_gating_e = 1; + common->reg026.busifd_auto_gating_e = 1; + common->reg026.dec_ctrl_auto_gating_e = 1; + common->reg026.intra_auto_gating_e = 1; + common->reg026.mc_auto_gating_e = 1; + common->reg026.transd_auto_gating_e = 1; + common->reg026.sram_auto_gating_e = 1; + common->reg026.cru_auto_gating_e = 1; + common->reg026.reg_cfg_gating_en = 1; + + common->reg032_timeout_threshold = 0x3fffff; + + common->reg011.dec_clkgate_e = 1; + + common->reg013.stmerror_waitdecfifo_empty = 1; + common->reg012.colmv_compress_en = COLMV_COMPRESS_EN; + common->reg012.info_collect_en = 1; + common->reg012.error_info_en = 0; + + return MPP_OK; +} + +static void avs2d_refine_rcb_size(VdpuRcbInfo *rcb_info, + Vdpu382Avs2dRegSet *hw_regs, + RK_S32 width, RK_S32 height, void *dxva) +{ + (void) height; + Avs2dSyntax_t *syntax = dxva; + RK_U8 ctu_size = 1 << syntax->pp.lcu_size; + RK_U32 chroma_fmt_idc = syntax->pp.chroma_format_idc; + RK_U8 bit_depth = syntax->pp.bit_depth_chroma_minus8 + 8; + RK_U32 rcb_bits = 0; + + width = MPP_ALIGN(width, ctu_size); + + /* RCB_STRMD_ROW */ + if (width >= 8192) { + RK_U32 factor = 64 / ctu_size; + + rcb_bits = (MPP_ALIGN(width, ctu_size) + factor - 1) / factor * 24; + } else + rcb_bits = 0; + rcb_info[RCB_STRMD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_ROW */ + if (width >= 8192) + rcb_bits = (MPP_ALIGN(width - 8192, 4) << 1); + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_COL */ + rcb_info[RCB_TRANSD_COL].size = 0; + + /* RCB_INTER_ROW */ + rcb_bits = width * 21; + rcb_info[RCB_INTER_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_COL */ + rcb_info[RCB_INTER_COL].size = 0; + + /* RCB_INTRA_ROW */ + rcb_bits = width * (((chroma_fmt_idc != 0) ? 1 : 0) + 1) * 11; + rcb_info[RCB_INTRA_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_DBLK_ROW */ + if (chroma_fmt_idc == 1 ) { + if (ctu_size == 32) + rcb_bits = width * ( 4 + 8 * bit_depth); + else + rcb_bits = width * ( 2 + 8 * bit_depth); + } else + rcb_bits = 0; + rcb_info[RCB_DBLK_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_SAO_ROW */ + if (chroma_fmt_idc == 1 || chroma_fmt_idc == 2) { + rcb_bits = width * (128 / ctu_size + 2 * bit_depth); + } else { + rcb_bits = width * (128 / ctu_size + 3 * bit_depth); + } + rcb_info[RCB_SAO_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FBC_ROW */ + if (hw_regs->common.reg012.fbc_e) + rcb_bits = width * 4 * bit_depth; + else + rcb_bits = 0; + rcb_info[RCB_FBC_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FILT_COL */ + rcb_info[RCB_FILT_COL].size = 0; + return; +} + +static void hal_avs2d_rcb_info_update(void *hal, Vdpu382Avs2dRegSet *hw_regs) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + RK_S32 width = p_hal->syntax.pp.pic_width_in_luma_samples; + RK_S32 height = p_hal->syntax.pp.pic_height_in_luma_samples; + RK_S32 i = 0; + RK_S32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + + reg_ctx->rcb_buf_size = vdpu382_get_rcb_buf_size(reg_ctx->rcb_info, width, height); + avs2d_refine_rcb_size(reg_ctx->rcb_info, hw_regs, width, height, (void *)&p_hal->syntax); + + for (i = 0; i < loop; i++) { + MppBuffer rcb_buf = NULL; + + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + + ret = mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, reg_ctx->rcb_buf_size); + + if (ret) + mpp_err_f("AVS2D mpp_buffer_get failed\n"); + + reg_ctx->rcb_buf[i] = rcb_buf; + } +} + +static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu382Avs2dRegSet *p_regs, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + MppFrame mframe = NULL; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + RefParams_Avs2d *refp = &syntax->refp; + HalDecTask *task_dec = &task->dec; + Vdpu382RegCommon *common = &p_regs->common; + MppBufSlots frm_slots = p_hal->cfg->frame_slots; + RK_U32 is_fbc = 0; + HalBuf *mv_buf = NULL; + + mpp_buf_slot_get_prop(frm_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + is_fbc = MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe)); + + //!< caculate the yuv_frame_size + { + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + AVS2D_HAL_TRACE("is_fbc %d y_virstride %d, hor_virstride %d, ver_virstride %d\n", is_fbc, y_virstride, hor_virstride, ver_virstride); + + if (is_fbc) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (ver_virstride + 16) / 16, SZ_4K); + + common->reg012.fbc_e = 1; + common->reg018.y_hor_virstride = fbc_hdr_stride / 16; + common->reg019.uv_hor_virstride = fbc_hdr_stride / 16; + common->reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + common->reg012.fbc_e = 0; + common->reg018.y_hor_virstride = hor_virstride / 16; + common->reg019.uv_hor_virstride = hor_virstride / 16; + common->reg020_y_virstride.y_virstride = y_virstride / 16; + } + common->reg013.cur_pic_is_idr = (pp->picture_type == 0 || pp->picture_type == 4 || pp->picture_type == 5); + } + + // set current + { + RK_S32 fd = -1; + p_regs->avs2d_param.reg65_cur_top_poc = mpp_frame_get_poc(mframe); + p_regs->avs2d_param.reg66_cur_bot_poc = 0; + fd = hal_avs2d_get_frame_fd(p_hal, task_dec->output); + mpp_assert(fd >= 0); + p_regs->common_addr.reg130_decout_base = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, task_dec->output); + p_regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + AVS2D_HAL_TRACE("cur frame index %d, fd %d, colmv fd %d", task_dec->output, fd, p_regs->common_addr.reg131_colmv_cur_base); + } + + // set reference + { + RK_U64 ref_flag = 0; + RK_S32 valid_slot = -1; + RK_U32 *ref_low = (RK_U32 *)&p_regs->avs2d_param.reg99; + RK_U32 *ref_hight = (RK_U32 *)&p_regs->avs2d_param.reg100; + RK_U32 err_ref_base = 0; + + AVS2D_HAL_TRACE("num of ref %d", refp->ref_pic_num); + + for (i = 0; i < refp->ref_pic_num; i++) { + if (task_dec->refer[i] < 0) + continue; + + valid_slot = i; + break; + } + + for (i = 0; i < refp->ref_pic_num; i++) { + MppFrame frame_ref = NULL; + + RK_S32 slot_idx = task_dec->refer[i] < 0 ? task_dec->refer[valid_slot] : task_dec->refer[i]; + + if (slot_idx < 0) { + AVS2D_HAL_DBG(AVS2D_HAL_DBG_ERROR, "missing ref, could not found valid ref"); + task->dec.flags.ref_err = 1; + return ret = MPP_ERR_UNKNOW; + } + + mpp_buf_slot_get_prop(frm_slots, slot_idx, SLOT_FRAME_PTR, &frame_ref); + + if (frame_ref) { + RK_U32 frm_flag = 1 << 3; + + if (pp->bottom_field_picture_flag) + frm_flag |= 1 << 2; + + if (pp->field_coded_sequence) + frm_flag |= 1; + + ref_flag |= frm_flag << (i * 8); + + p_regs->avs2d_addr.ref_base[i] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + p_regs->avs2d_addr.colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + + p_regs->avs2d_param.reg67_098_ref_poc[i] = mpp_frame_get_poc(frame_ref); + if (!err_ref_base && !mpp_frame_get_errinfo(frame_ref)) + err_ref_base = p_regs->avs2d_addr.ref_base[i]; + + AVS2D_HAL_TRACE("ref_base[%d] index=%d, fd = %d, colmv %d, poc %d", + i, slot_idx, p_regs->avs2d_addr.ref_base[i], + p_regs->avs2d_addr.colmv_base[i], p_regs->avs2d_param.reg67_098_ref_poc[i]); + } + } + + if (p_hal->syntax.refp.scene_ref_enable && p_hal->syntax.refp.scene_ref_slot_idx >= 0) { + MppFrame scene_ref = NULL; + RK_S32 replace_idx = p_hal->syntax.refp.scene_ref_replace_pos; + RK_S32 slot_idx = p_hal->syntax.refp.scene_ref_slot_idx; + + mpp_buf_slot_get_prop(frm_slots, slot_idx, SLOT_FRAME_PTR, &scene_ref); + + if (scene_ref) { + p_regs->avs2d_addr.ref_base[replace_idx] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + p_regs->avs2d_addr.colmv_base[replace_idx] = mpp_buffer_get_fd(mv_buf->buf[0]); + p_regs->avs2d_param.reg67_098_ref_poc[replace_idx] = mpp_frame_get_poc(scene_ref); + } + } + + *ref_low = (RK_U32) (ref_flag & 0xffffffff); + *ref_hight = (RK_U32) ((ref_flag >> 32) & 0xffffffff); + + p_regs->common_addr.reg132_error_ref_base = err_ref_base; + } + + // set rlc + { + p_regs->common_addr.reg128_rlc_base = hal_avs2d_get_packet_fd(p_hal, task_dec->input); + AVS2D_HAL_TRACE("packet fd %d from slot %d", p_regs->common_addr.reg128_rlc_base, task_dec->input); + p_regs->common_addr.reg129_rlcwrite_base = p_regs->common_addr.reg128_rlc_base; + common->reg016_str_len = MPP_ALIGN(mpp_packet_get_length(task_dec->input_packet), 16) + 64; + } + + /* set scale down info */ + if (mpp_frame_get_thumbnail_en(mframe)) { + p_regs->avs2d_addr.scale_down_luma_base = p_regs->common_addr.reg130_decout_base; + p_regs->avs2d_addr.scale_down_chorme_base = p_regs->common_addr.reg130_decout_base; + vdpu382_setup_down_scale(mframe, p_hal->cfg->dev, &p_regs->common); + } else { + p_regs->avs2d_addr.scale_down_luma_base = 0; + p_regs->avs2d_addr.scale_down_chorme_base = 0; + p_regs->common.reg012.scale_down_en = 0; + } + + return ret; +} + +MPP_RET hal_avs2d_vdpu382_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + RK_U32 i, loop; + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + MppBufSlots frm_slots = cfg->frame_slots; + + mpp_env_get_u32("hal_avs2d_debug", &hal_avs2d_debug, 0); + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Avs2dRkvRegCtx))); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + //!< malloc buffers + reg_ctx->shph_dat = mpp_calloc(RK_U8, AVS2_RKV_SHPH_SIZE); + reg_ctx->scalist_dat = mpp_calloc(RK_U8, AVS2_RKV_SCALIST_SIZE); + loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + FUN_CHECK(ret = mpp_buffer_get(p_hal->cfg->buf_group, ®_ctx->bufs, AVS2_ALL_TBL_BUF_SIZE(loop))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + + for (i = 0; i < loop; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu382Avs2dRegSet, 1); + init_common_regs(reg_ctx->reg_buf[i].regs); + reg_ctx->reg_buf[i].offset_shph = AVS2_SHPH_OFFSET(i); + reg_ctx->reg_buf[i].offset_sclst = AVS2_SCALIST_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[0].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[0].offset_sclst; + } + + if (MPP_FRAME_FMT_IS_FBC(cfg->cfg->base.out_fmt)) + mpp_slots_set_prop(frm_slots, SLOTS_HOR_ALIGN, mpp_align_64); + else + mpp_slots_set_prop(frm_slots, SLOTS_HOR_ALIGN, mpp_align_16); + + mpp_slots_set_prop(frm_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(frm_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(frm_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + (void)cfg; + return ret; +__FAILED: + hal_avs2d_vdpu_deinit(p_hal); + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +static MPP_RET set_up_colmv_buf(void *hal) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dSyntax_t *syntax = &p_hal->syntax; + PicParams_Avs2d *pp = &syntax->pp; + RK_U32 mv_size = 0; + RK_U32 ctu_size = 1 << (p_hal->syntax.pp.lcu_size); + RK_U32 width = p_hal->syntax.pp.pic_width_in_luma_samples; + RK_U32 height = p_hal->syntax.pp.pic_height_in_luma_samples; + + mv_size = vdpu382_get_colmv_size(width, height, ctu_size, COLMV_BYTES, + COLMV_BLOCK_SIZE, COLMV_COMPRESS_EN); + if (pp->field_coded_sequence) + mv_size *= 2; + AVS2D_HAL_TRACE("mv_size %d", mv_size); + + if (p_hal->cmv_bufs == NULL || p_hal->mv_size < mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + ret = MPP_ERR_INIT; + goto __RETURN; + } + + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + +__RETURN: + return ret; +} + +MPP_RET hal_avs2d_vdpu382_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Vdpu382Avs2dRegSet *regs = NULL; + MppHalCfg *cfg = p_hal->cfg; + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !cfg->cfg->base.disable_error) { + ret = MPP_NOK; + goto __RETURN; + } + + memcpy(&p_hal->syntax, task->dec.syntax.data, sizeof(Avs2dSyntax_t)); + ret = set_up_colmv_buf(p_hal); + if (ret) + goto __RETURN; + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + if (p_hal->fast_mode) { + RK_U32 i = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(reg_ctx->reg_buf); i++) { + if (!reg_ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = reg_ctx->reg_buf[i].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[i].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[i].offset_sclst; + reg_ctx->regs = reg_ctx->reg_buf[i].regs; + reg_ctx->reg_buf[i].valid = 1; + break; + } + } + + mpp_assert(regs); + } + + regs = reg_ctx->regs; + memset(regs, 0, sizeof(Vdpu382Avs2dRegSet)); + init_common_regs(regs); + + prepare_header(p_hal, reg_ctx->shph_dat, AVS2_RKV_SHPH_SIZE / 8); + prepare_scalist(p_hal, reg_ctx->scalist_dat, AVS2_RKV_SCALIST_SIZE / 8); + + ret = fill_registers(p_hal, regs, task); + + if (ret) + goto __RETURN; + + { + memcpy(reg_ctx->bufs_ptr + reg_ctx->shph_offset, reg_ctx->shph_dat, AVS2_RKV_SHPH_SIZE); + memcpy(reg_ctx->bufs_ptr + reg_ctx->sclst_offset, reg_ctx->scalist_dat, AVS2_RKV_SCALIST_SIZE); + regs->common.reg012.scanlist_addr_valid_en = 1; + + regs->avs2d_addr.head_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 161, reg_ctx->shph_offset); + + regs->avs2d_param.reg105.head_len = AVS2_RKV_SHPH_SIZE / 16; + regs->avs2d_param.reg105.head_len -= (regs->avs2d_param.reg105.head_len > 0) ? 1 : 0; + + regs->avs2d_addr.scanlist_addr = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 180, reg_ctx->sclst_offset); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) { + FILE *fp_shph = NULL; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_shph_%03d.bin", p_hal->frame_no); + fp_shph = fopen(name, "wb"); + fwrite(reg_ctx->bufs_ptr + reg_ctx->shph_offset, 1, AVS2_RKV_SHPH_SIZE, fp_shph); + fclose(fp_shph); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) { + FILE *fp_scalist = NULL; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_scalist_%03d.bin", p_hal->frame_no); + fp_scalist = fopen(name, "wb"); + fwrite(reg_ctx->bufs_ptr + reg_ctx->sclst_offset, 1, AVS2_RKV_SCALIST_SIZE, fp_scalist); + fclose(fp_scalist); + } + + // set rcb + { + hal_avs2d_rcb_info_update(p_hal, regs); + vdpu382_setup_rcb(®s->common_addr, cfg->dev, (p_hal->fast_mode != 0) ? + reg_ctx->rcb_buf[task->dec.reg_index] : reg_ctx->rcb_buf[0], + reg_ctx->rcb_info); + + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) { + FILE *fp_rcb = NULL; + char name[50]; + void *base = NULL; + snprintf(name, sizeof(name), "/data/tmp/rkv_rcb_%03d.bin", p_hal->frame_no); + fp_rcb = fopen(name, "wb"); + base = mpp_buffer_get_ptr(reg_ctx->rcb_buf[0]); + fwrite(base, 1, reg_ctx->rcb_buf_size, fp_rcb); + fclose(fp_rcb); + + } + + vdpu382_setup_statistic(®s->common, ®s->statistic); + mpp_buffer_sync_end(reg_ctx->bufs); + + /* enable reference frame usage feedback */ + regs->statistic.reg265.perf_cnt0_sel = 42; + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +static MPP_RET hal_avs2d_vdpu382_dump_reg_write(void *hal, Vdpu382Avs2dRegSet *regs) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + FILE *fp_reg = NULL; + RK_U32 i = 0; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_reg_write_%03d.txt", p_hal->frame_no); + fp_reg = fopen(name , "w+"); + + fprintf(fp_reg, "********Frame num %d\n", p_hal->frame_no); + for (i = 0; i < 8; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i, 0); + + for (i = 0; i < sizeof(Vdpu382RegCommon) / sizeof(RK_U32); i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU382_OFF_COMMON_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->common)[i]); + + for (i = 0; i < 63 - 32; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 33, 0); + + for (i = 0; i < sizeof(Vdpu382RegAvs2dParam) / sizeof(RK_U32); i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU382_OFF_CODEC_PARAMS_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->avs2d_param)[i]); + + for (i = 0; i < 127 - 112; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 113, 0); + + for (i = 0; i < sizeof(Vdpu382RegCommonAddr) / sizeof(RK_U32); i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU382_OFF_COMMON_ADDR_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->common_addr)[i]); + + for (i = 0; i < 159 - 142; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 143, 0); + + + for (i = 0; i < sizeof(Vdpu382RegAvs2dAddr) / sizeof(RK_U32); i++ ) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU382_OFF_CODEC_ADDR_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->avs2d_addr)[i]); + + for (i = 0; i < 223 - 197; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 198, 0); + + for (i = 0; i < sizeof(Vdpu382RegIrqStatus) / sizeof(RK_U32); i++ ) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU382_OFF_INTERRUPT_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->irq_status)[i]); + + for (i = 0; i < 255 - 237; i++) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", i + 238, 0); + + for (i = 0; i < sizeof(Vdpu382RegStatistic) / sizeof(RK_U32); i++ ) + fprintf(fp_reg, "Write reg[%03d] : 0x%08x\n", (RK_U32)(i + VDPU382_OFF_STATISTIC_REGS / sizeof(RK_U32)), + ((RK_U32 *)®s->statistic)[i]); + + fclose(fp_reg); + return ret; +} + +static MPP_RET hal_avs2d_vdpu382_dump_stream(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + + FILE *fp_stream = NULL; + char name[50]; + MppBuffer buffer = NULL; + void *base = NULL; + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &buffer); + base = mpp_buffer_get_ptr(buffer); + snprintf(name, sizeof(name), "/data/tmp/rkv_stream_in_%03d.bin", p_hal->frame_no); + fp_stream = fopen(name, "wb"); + fwrite(base, 1, mpp_packet_get_length(task->dec.input_packet), fp_stream); + fclose(fp_stream); + + return ret; +} + +MPP_RET hal_avs2d_vdpu382_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Vdpu382Avs2dRegSet *regs = NULL; + Avs2dRkvRegCtx *reg_ctx; + MppDev dev = NULL; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + + AVS2D_HAL_TRACE("In."); + INP_CHECK(ret, NULL == p_hal); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + ret = MPP_NOK; + goto __RETURN; + } + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + regs = (p_hal->fast_mode != 0) ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + dev = p_hal->cfg->dev; + + p_hal->frame_no++; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->common; + wr_cfg.size = sizeof(regs->common); + wr_cfg.offset = VDPU382_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->avs2d_param; + wr_cfg.size = sizeof(regs->avs2d_param); + wr_cfg.offset = VDPU382_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->common_addr; + wr_cfg.size = sizeof(regs->common_addr); + wr_cfg.offset = VDPU382_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->avs2d_addr; + wr_cfg.size = sizeof(regs->avs2d_addr); + wr_cfg.offset = VDPU382_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->statistic; + wr_cfg.size = sizeof(regs->statistic); + wr_cfg.offset = VDPU382_OFF_STATISTIC_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->irq_status; + rd_cfg.size = sizeof(regs->irq_status); + rd_cfg.offset = VDPU382_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->avs2d_param; + rd_cfg.size = sizeof(regs->avs2d_param); + rd_cfg.offset = VDPU382_OFF_CODEC_PARAMS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->statistic; + rd_cfg.size = sizeof(regs->statistic); + rd_cfg.offset = VDPU382_OFF_STATISTIC_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) { + memset(reg_ctx->reg_out, 0, sizeof(reg_ctx->reg_out)); + rd_cfg.reg = reg_ctx->reg_out; + rd_cfg.size = sizeof(reg_ctx->reg_out); + rd_cfg.offset = 0; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + // rcb info for sram + vdpu382_set_rcbinfo(dev, reg_ctx->rcb_info); + + if (hal_avs2d_debug & AVS2D_HAL_DBG_IN) + hal_avs2d_vdpu382_dump_stream(hal, task); + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) + hal_avs2d_vdpu382_dump_reg_write(hal, regs); + + // send request to hardware + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + + } while (0); + +__RETURN: + AVS2D_HAL_TRACE("Out."); + return ret; +} + +MPP_RET hal_avs2d_vdpu382_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx; + Vdpu382Avs2dRegSet *p_regs; + + INP_CHECK(ret, NULL == p_hal); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + p_regs = (p_hal->fast_mode != 0) ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + AVS2D_HAL_DBG(AVS2D_HAL_DBG_ERROR, "found task error.\n"); + ret = MPP_NOK; + goto __RETURN; + } else { + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_OUT) + hal_avs2d_vdpu_dump_yuv(hal, task); + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) { + FILE *fp_reg = NULL; + RK_U32 i = 0; + char name[50]; + snprintf(name, sizeof(name), "/data/tmp/rkv_reg_read_%03d.txt", p_hal->frame_no); + fp_reg = fopen(name , "w+"); + + for (i = 0; i < 278; i++) + fprintf(fp_reg, "%08x\n", reg_ctx->reg_out[i]); + + fclose(fp_reg); + } + + AVS2D_HAL_TRACE("read reg[224] 0x%08x\n", p_regs->irq_status.reg224); + + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + + if (p_regs->irq_status.reg224.dec_error_sta || + (!p_regs->irq_status.reg224.dec_rdy_sta) || + p_regs->irq_status.reg224.buf_empty_sta || + p_regs->irq_status.reg226.strmd_error_status || + p_regs->irq_status.reg227.colmv_error_ref_picidx || + p_regs->irq_status.reg226.strmd_detect_error_flag) + param.hard_err = 1; + else + param.hard_err = 0; + + task->dec.flags.ref_used = p_regs->statistic.reg265.link_perf_cnt0; + task->dec.flags.ref_info_valid = 1; + + if (task->dec.flags.ref_miss) { + RK_U32 ref_hw_usage = p_regs->statistic.reg265.link_perf_cnt0; + + AVS2D_HAL_TRACE("hal frame %d ref miss %x hard_err %d hw_usage %x", p_hal->frame_no, + task->dec.flags.ref_miss, param.hard_err, ref_hw_usage); + } + + AVS2D_HAL_TRACE("hal frame %d hard_err= %d", p_hal->frame_no, param.hard_err); + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + + memset(&p_regs->irq_status.reg224, 0, sizeof(RK_U32)); + + if (p_hal->fast_mode) + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +const MppHalApi hal_avs2d_vdpu382 = { + .name = "avs2d_vdpu382", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVS2, + .ctx_size = sizeof(Avs2dHalCtx_t), + .flag = 0, + .init = hal_avs2d_vdpu382_init, + .deinit = hal_avs2d_vdpu_deinit, + .reg_gen = hal_avs2d_vdpu382_gen_regs, + .start = hal_avs2d_vdpu382_start, + .wait = hal_avs2d_vdpu382_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_avs2d_vdpu382) diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu382.h b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu382.h new file mode 100644 index 000000000..ca6b87cd8 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu382.h @@ -0,0 +1,38 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVS2D_VDPU382_H +#define HAL_AVS2D_VDPU382_H + +#include "mpp_device.h" + +#include "parser_api.h" +#include "hal_avs2d_global.h" +#include "avs2d_syntax.h" + +#define AVS2D_REGISTERS (278) + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_avs2d_vdpu382; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVS2D_VDPU382_H */ diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu383.c b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu383.c new file mode 100644 index 000000000..62f2ffb2a --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu383.c @@ -0,0 +1,591 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_avs2d_vdpu383" + +#include +#include + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_debug.h" +#include "mpp_bitput.h" +#include "mpp_buffer_impl.h" + +#include "avs2d_syntax.h" +#include "hal_avs2d_global.h" +#include "hal_avs2d_vdpu383.h" +#include "mpp_dec_cb_param.h" +#include "vdpu_com.h" +#include "vdpu38x_com.h" +#include "vdpu383_com.h" +#include "hal_avs2d_ctx.h" +#include "hal_avs2d_com.h" + +#define MAX_REF_NUM (8) +#define AVS2_383_SHPH_SIZE (208) /* bytes */ +#define AVS2_383_SCALIST_SIZE (80) /* bytes */ + +#define AVS2_383_SHPH_ALIGNED_SIZE (MPP_ALIGN(AVS2_383_SHPH_SIZE, SZ_4K)) +#define AVS2_383_SCALIST_ALIGNED_SIZE (MPP_ALIGN(AVS2_383_SCALIST_SIZE, SZ_4K)) +#define AVS2_383_STREAM_INFO_SET_SIZE (AVS2_383_SHPH_ALIGNED_SIZE + \ + AVS2_383_SCALIST_ALIGNED_SIZE) +#define AVS2_ALL_TBL_BUF_SIZE(cnt) (AVS2_383_STREAM_INFO_SET_SIZE * (cnt)) +#define AVS2_SHPH_OFFSET(pos) (AVS2_383_STREAM_INFO_SET_SIZE * (pos)) +#define AVS2_SCALIST_OFFSET(pos) (AVS2_SHPH_OFFSET(pos) + AVS2_383_SHPH_ALIGNED_SIZE) + +#define COLMV_COMPRESS_EN (1) +#define COLMV_BLOCK_SIZE (16) +#define COLMV_BYTES (16) + +static MPP_RET vdpu383_avs2d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + RK_U32 fltd_row_append = ctx->pic_w > 4096 ? 256 * 16 * 8 : 864 * 16 * 8; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + /* + * For all spec, the hardware connects all in-tile rows of strmd to the on-tile. + * Therefore, only strmd on-tile needs to be configured, and there is no need to + * configure strmd in-tile. + * + * Versions with issues: rk3576(383), swan1126b (384a), shark/robin (384b). + */ + if (ctx->pic_w > 8192) + cur_bit_size = MPP_DIVUP(64, in_tl_row) * 112; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, in_tl_row) * 166; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, on_tl_row) * 166; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.6 * bit_depth + 0.5) + * (12 + 5 * cur_uv_para + 1.5 * ctx->alf_en); + cur_bit_size = cur_bit_size / 2 + fltd_row_append; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + // save space mode : half for RCB_FLTD_IN_ROW, half for RCB_FLTD_PROT_IN_ROW + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.6 * bit_depth + 0.5) + * (12 + 5 * cur_uv_para + 1.5 * ctx->alf_en); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu383RegSet *regs, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 i; + MppFrame mframe = NULL; + Avs2dSyntax_t *syntax = &p_hal->syntax; + RefParams_Avs2d *refp = &syntax->refp; + HalDecTask *task_dec = &task->dec; + MppBufSlots frm_slots = p_hal->cfg->frame_slots; + + RK_U32 is_fbc = 0; + RK_U32 is_tile = 0; + HalBuf *mv_buf = NULL; + + mpp_buf_slot_get_prop(frm_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + is_fbc = MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe)); + is_tile = MPP_FRAME_FMT_IS_TILE(mpp_frame_get_fmt(mframe)); + + //!< caculate the yuv_frame_size + { + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + uv_virstride = hor_virstride * ver_virstride / 2; + AVS2D_HAL_TRACE("is_fbc %d y_virstride %d, hor_virstride %d, ver_virstride %d\n", + is_fbc, y_virstride, hor_virstride, ver_virstride); + + if (is_fbc) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset; + + regs->ctrl_regs.reg9.fbc_e = 1; + regs->comm_paras.reg68_hor_virstride = fbc_hdr_stride / 64; + fbd_offset = regs->comm_paras.reg68_hor_virstride * MPP_ALIGN(ver_virstride, 64) * 4; + regs->comm_addrs.reg193_fbc_payload_offset = fbd_offset; + } else if (is_tile) { + regs->ctrl_regs.reg9.tile_e = 1; + regs->comm_paras.reg68_hor_virstride = hor_virstride * 6 / 16; + regs->comm_paras.reg70_y_virstride = (y_virstride + uv_virstride) / 16; + } else { + regs->ctrl_regs.reg9.fbc_e = 0; + regs->ctrl_regs.reg9.tile_e = 0; + regs->comm_paras.reg68_hor_virstride = hor_virstride / 16; + regs->comm_paras.reg69_raster_uv_hor_virstride = hor_virstride / 16; + regs->comm_paras.reg70_y_virstride = y_virstride / 16; + } + } + + // set current + { + RK_S32 fd = hal_avs2d_get_frame_fd(p_hal, task_dec->output); + + mpp_assert(fd >= 0); + + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, task_dec->output); + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + AVS2D_HAL_TRACE("cur frame index %d, fd %d, colmv fd %d", task_dec->output, fd, regs->comm_addrs.reg216_colmv_cur_base); + + // TODO: set up error_ref_base + // regs->avs2d_addr.reg169_err_ref_base.base = regs->avs2d_addr.reg216_colmv_cur_base.base; + } + + // set reference + { + RK_S32 valid_slot = -1; + + AVS2D_HAL_TRACE("num of ref %d", refp->ref_pic_num); + + for (i = 0; i < refp->ref_pic_num; i++) { + if (task_dec->refer[i] < 0) + continue; + + valid_slot = i; + break; + } + + for (i = 0; i < MAX_REF_NUM; i++) { + if (i < refp->ref_pic_num) { + MppFrame frame_ref = NULL; + + RK_S32 slot_idx = task_dec->refer[i] < 0 ? task_dec->refer[valid_slot] : task_dec->refer[i]; + + if (slot_idx < 0) { + AVS2D_HAL_TRACE("missing ref, could not found valid ref"); + task->dec.flags.ref_err = 1; + return ret = MPP_ERR_UNKNOW; + } + + mpp_buf_slot_get_prop(frm_slots, slot_idx, SLOT_FRAME_PTR, &frame_ref); + + if (frame_ref) { + regs->comm_addrs.reg170_185_ref_base[i] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + } + + if (p_hal->syntax.refp.scene_ref_enable && p_hal->syntax.refp.scene_ref_slot_idx >= 0) { + MppFrame scene_ref = NULL; + RK_S32 slot_idx = p_hal->syntax.refp.scene_ref_slot_idx; + RK_S32 replace_idx = p_hal->syntax.refp.scene_ref_replace_pos; + + mpp_buf_slot_get_prop(frm_slots, slot_idx, SLOT_FRAME_PTR, &scene_ref); + + if (scene_ref) { + regs->comm_addrs.reg170_185_ref_base[replace_idx] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + regs->comm_addrs.reg195_210_payload_st_ref_base[replace_idx] = regs->comm_addrs.reg170_185_ref_base[replace_idx]; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + regs->comm_addrs.reg217_232_colmv_ref_base[replace_idx] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + regs->comm_addrs.reg169_error_ref_base = regs->comm_addrs.reg170_185_ref_base[0]; + regs->comm_addrs.reg194_payload_st_error_ref_base = regs->comm_addrs.reg195_210_payload_st_ref_base[0]; + } + + // set rlc + regs->comm_addrs.reg128_strm_base = hal_avs2d_get_packet_fd(p_hal, task_dec->input); + AVS2D_HAL_TRACE("packet fd %d from slot %d", regs->comm_addrs.reg128_strm_base, task_dec->input); + + regs->comm_paras.reg66_stream_len = MPP_ALIGN(mpp_packet_get_length(task_dec->input_packet), 16) + 64; + + { + //scale down config + mpp_buf_slot_get_prop(frm_slots, task_dec->output, + SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe)) { + regs->comm_addrs.reg133_scale_down_base = regs->comm_addrs.reg168_decout_base; + vdpu383_setup_down_scale(mframe, p_hal->cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + } else { + regs->ctrl_regs.reg9.scale_down_en = 0; + } + } + + return ret; +} + +MPP_RET hal_avs2d_vdpu383_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + RK_U32 i, loop; + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + + mpp_env_get_u32("hal_avs2d_debug", &hal_avs2d_debug, 0); + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Avs2dRkvRegCtx))); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + //!< malloc buffers + reg_ctx->shph_dat = mpp_calloc(RK_U8, AVS2_383_SHPH_SIZE); + reg_ctx->scalist_dat = mpp_calloc(RK_U8, AVS2_383_SCALIST_SIZE); + loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + FUN_CHECK(ret = mpp_buffer_get(p_hal->cfg->buf_group, ®_ctx->bufs, AVS2_ALL_TBL_BUF_SIZE(loop))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + mpp_buffer_attach_dev(reg_ctx->bufs, p_hal->cfg->dev); + + for (i = 0; i < loop; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu383RegSet, 1); + vdpu383_init_ctrl_regs(reg_ctx->reg_buf[i].regs, MPP_VIDEO_CodingAVS2); + reg_ctx->reg_buf[i].offset_shph = AVS2_SHPH_OFFSET(i); + reg_ctx->reg_buf[i].offset_sclst = AVS2_SCALIST_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[0].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[0].offset_sclst; + } + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + (void)cfg; + return ret; +__FAILED: + hal_avs2d_vdpu_deinit(p_hal); + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +MPP_RET hal_avs2d_vdpu383_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Vdpu383RegSet *regs = NULL; + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + ret = MPP_NOK; + goto __RETURN; + } + + memcpy(&p_hal->syntax, task->dec.syntax.data, sizeof(Avs2dSyntax_t)); + ret = hal_avs2d_set_up_colmv_buf(p_hal); + if (ret) + goto __RETURN; + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + if (p_hal->fast_mode) { + RK_U32 i = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(reg_ctx->reg_buf); i++) { + if (!reg_ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = reg_ctx->reg_buf[i].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[i].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[i].offset_sclst; + reg_ctx->regs = reg_ctx->reg_buf[i].regs; + reg_ctx->reg_buf[i].valid = 1; + break; + } + } + + mpp_assert(regs); + } + + regs = reg_ctx->regs; + memset(regs, 0, sizeof(Vdpu383RegSet)); + vdpu383_init_ctrl_regs(regs, MPP_VIDEO_CodingAVS2); + + hal_avs2d_vdpu38x_prepare_header(p_hal, reg_ctx->shph_dat, AVS2_383_SHPH_SIZE / 8); + hal_avs2d_vdpu38x_prepare_scalist(p_hal, reg_ctx->scalist_dat, AVS2_383_SCALIST_SIZE / 8); + + ret = fill_registers(p_hal, regs, task); + + if (ret) + goto __RETURN; + + { + memcpy(reg_ctx->bufs_ptr + reg_ctx->shph_offset, reg_ctx->shph_dat, AVS2_383_SHPH_SIZE); + memcpy(reg_ctx->bufs_ptr + reg_ctx->sclst_offset, reg_ctx->scalist_dat, AVS2_383_SCALIST_SIZE); + + regs->comm_addrs.reg131_gbl_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(p_hal->cfg->dev, 131, reg_ctx->shph_offset); + regs->comm_paras.reg67_global_len = AVS2_383_SHPH_SIZE; + + regs->comm_addrs.reg132_scanlist_addr = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(p_hal->cfg->dev, 132, reg_ctx->sclst_offset); + } + + vdpu38x_avs2d_rcb_setup(p_hal, task, ®s->comm_addrs.rcb_regs, + vdpu383_avs2d_rcb_calc); + vdpu383_setup_statistic(®s->ctrl_regs); + mpp_buffer_sync_end(reg_ctx->bufs); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +MPP_RET hal_avs2d_vdpu383_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Vdpu383RegSet *regs = NULL; + Avs2dRkvRegCtx *reg_ctx; + MppDev dev = NULL; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + + AVS2D_HAL_TRACE("In."); + INP_CHECK(ret, NULL == p_hal); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + regs = (p_hal->fast_mode != 0) ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + dev = p_hal->cfg->dev; + + p_hal->frame_no++; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->ctrl_regs; + wr_cfg.size = sizeof(regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_paras; + wr_cfg.size = sizeof(regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_addrs; + wr_cfg.size = sizeof(regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->ctrl_regs.reg15; + rd_cfg.size = sizeof(regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) { + memset(reg_ctx->reg_out, 0, sizeof(reg_ctx->reg_out)); + rd_cfg.reg = reg_ctx->reg_out; + rd_cfg.size = sizeof(reg_ctx->reg_out); + rd_cfg.offset = 0; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + // send request to hardware + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + + } while (0); + +__RETURN: + AVS2D_HAL_TRACE("Out."); + return ret; +} + +MPP_RET hal_avs2d_vdpu383_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx; + Vdpu383RegSet *regs; + + INP_CHECK(ret, NULL == p_hal); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + regs = (p_hal->fast_mode != 0) ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + AVS2D_HAL_DBG(AVS2D_HAL_DBG_ERROR, "found task error.\n"); + ret = MPP_NOK; + goto __RETURN; + } else { + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_OUT) + hal_avs2d_vdpu_dump_yuv(hal, task); + + AVS2D_HAL_TRACE("read irq_status 0x%08x\n", regs->ctrl_regs.reg15); + + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)regs; + + if ((!regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) + param.hard_err = 1; + else + param.hard_err = 0; + + task->dec.flags.ref_info_valid = 0; + + AVS2D_HAL_TRACE("hal frame %d hard_err= %d", p_hal->frame_no, param.hard_err); + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + + memset(®s->ctrl_regs.reg15, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +const MppHalApi hal_avs2d_vdpu383 = { + .name = "avs2d_vdpu383", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVS2, + .ctx_size = sizeof(Avs2dHalCtx_t), + .flag = 0, + .init = hal_avs2d_vdpu383_init, + .deinit = hal_avs2d_vdpu_deinit, + .reg_gen = hal_avs2d_vdpu383_gen_regs, + .start = hal_avs2d_vdpu383_start, + .wait = hal_avs2d_vdpu383_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_avs2d_vdpu383) diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu383.h b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu383.h new file mode 100644 index 000000000..bbfd170dd --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu383.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AVS2D_VDPU383_H +#define HAL_AVS2D_VDPU383_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_avs2d_vdpu383; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVS2D_RKV_H */ diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu384b.c b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu384b.c new file mode 100644 index 000000000..4cba4b435 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu384b.c @@ -0,0 +1,639 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_avs2d_vdpu384b" + +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_bitput.h" +#include "mpp_buffer_impl.h" + +#include "vdpu38x_com.h" +#include "hal_avs2d_global.h" +#include "hal_avs2d_vdpu384b.h" +#include "mpp_dec_cb_param.h" +#include "hal_avs2d_ctx.h" +#include "hal_avs2d_com.h" + +#define MAX_REF_NUM (8) +#define AVS2_384B_SHPH_SIZE (MPP_ALIGN(1614 + 64, 128) / 8) // byte, 1614 bit + Reserve 64 +#define AVS2_384B_SCALIST_SIZE (80) /* bytes */ + +#define AVS2_384B_SHPH_ALIGNED_SIZE (MPP_ALIGN(AVS2_384B_SHPH_SIZE, SZ_4K)) +#define AVS2_384B_SCALIST_ALIGNED_SIZE (MPP_ALIGN(AVS2_384B_SCALIST_SIZE, SZ_4K)) +#define AVS2_384B_STREAM_INFO_SET_SIZE (AVS2_384B_SHPH_ALIGNED_SIZE + \ + AVS2_384B_SCALIST_ALIGNED_SIZE) +#define AVS2_ALL_TBL_BUF_SIZE(cnt) (AVS2_384B_STREAM_INFO_SET_SIZE * (cnt)) +#define AVS2_SHPH_OFFSET(pos) (AVS2_384B_STREAM_INFO_SET_SIZE * (pos)) +#define AVS2_SCALIST_OFFSET(pos) (AVS2_SHPH_OFFSET(pos) + AVS2_384B_SHPH_ALIGNED_SIZE) + +#define COLMV_COMPRESS_EN (1) +#define COLMV_BLOCK_SIZE (16) +#define COLMV_BYTES (16) + +static MPP_RET vdpu384b_avs2d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + /* + * For all spec, the hardware connects all in-tile rows of strmd to the on-tile. + * Therefore, only strmd on-tile needs to be configured, and there is no need to + * configure strmd in-tile. + * + * Versions with issues: rk3576(383), swan1126b (384a), shark/robin (384b). + */ + if (ctx->pic_w > 8192) + cur_bit_size = MPP_DIVUP(64, in_tl_row) * 112; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, in_tl_row) * 166; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, on_tl_row) * 166; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.2 * bit_depth + 0.5) + * (12 + 5 * cur_uv_para + 1.5 * ctx->alf_en); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.2 * bit_depth + 0.5) + * (12 + 5 * cur_uv_para + 1.5 * ctx->alf_en); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +static MPP_RET fill_registers(Avs2dHalCtx_t *p_hal, Vdpu38xRegSet *regs, HalTaskInfo *task) +{ + MppFrame mframe = NULL; + Avs2dSyntax_t *syntax = &p_hal->syntax; + RefParams_Avs2d *refp = &syntax->refp; + HalDecTask *task_dec = &task->dec; + MppHalCfg *cfg = p_hal->cfg; + HalBuf *mv_buf = NULL; + RK_U32 i; + MPP_RET ret = MPP_OK; + + mpp_buf_slot_get_prop(cfg->frame_slots, task_dec->output, SLOT_FRAME_PTR, &mframe); + + //!< caculate the yuv_frame_size + { + MppFrameFormat fmt; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + RK_U32 fbc_head_stride = 0; + RK_U32 fbc_pld_stride = 0; + RK_U32 fbc_offset = 0; + RK_U32 tile4x4_coeff = 0; + + fmt = mpp_frame_get_fmt(mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + uv_virstride = hor_virstride * ver_virstride / 2; + if (MPP_FRAME_FMT_IS_AFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 3; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_RKFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 2; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_TILE(fmt)) { + if (vdpu38x_get_tile4x4_h_stride_coeff(fmt, &tile4x4_coeff)) { + mpp_err("get tile 4x4 coeff failed\n"); + return MPP_NOK; + } + regs->ctrl_regs.reg9.pp_output_mode = 1; + regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride * tile4x4_coeff / 16; + regs->comm_paras.reg70_pp_m_y_virstride = (y_virstride + uv_virstride) / 16; + } else { + regs->ctrl_regs.reg9.pp_output_mode = 0; + regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride / 16; + regs->comm_paras.reg69_pp_m_uv_hor_stride = hor_virstride / 16; + regs->comm_paras.reg70_pp_m_y_virstride = y_virstride / 16; + } + /* error stride */ + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg68_pp_m_hor_stride; + regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = regs->comm_paras.reg69_pp_m_uv_hor_stride; + regs->comm_paras.reg82_error_ref_virstride = regs->comm_paras.reg70_pp_m_y_virstride; + } + + // set current + { + RK_S32 fd = hal_avs2d_get_frame_fd(p_hal, task_dec->output); + + mpp_assert(fd >= 0); + + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, task_dec->output); + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + AVS2D_HAL_TRACE("cur frame index %d, fd %d, colmv fd %d", task_dec->output, fd, regs->comm_addrs.reg216_colmv_cur_base); + + // TODO: set up error_ref_base + // regs->avs2d_addr.reg169_err_ref_base.base = regs->avs2d_addr.reg216_colmv_cur_base.base; + } + + // set reference + { + RK_S32 valid_slot = -1; + + AVS2D_HAL_TRACE("num of ref %d", refp->ref_pic_num); + + for (i = 0; i < refp->ref_pic_num; i++) { + if (task_dec->refer[i] < 0) + continue; + + valid_slot = i; + break; + } + + for (i = 0; i < MAX_REF_NUM; i++) { + if (i < refp->ref_pic_num) { + MppFrame frame_ref = NULL; + + RK_S32 slot_idx = task_dec->refer[i] < 0 ? task_dec->refer[valid_slot] : task_dec->refer[i]; + + if (slot_idx < 0) { + AVS2D_HAL_TRACE("missing ref, could not found valid ref"); + task->dec.flags.ref_err = 1; + return ret = MPP_ERR_UNKNOW; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, slot_idx, SLOT_FRAME_PTR, &frame_ref); + + if (frame_ref) { + regs->comm_addrs.reg170_185_ref_base[i] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + } + + if (p_hal->syntax.refp.scene_ref_enable && p_hal->syntax.refp.scene_ref_slot_idx >= 0) { + MppFrame scene_ref = NULL; + RK_S32 slot_idx = p_hal->syntax.refp.scene_ref_slot_idx; + RK_S32 replace_idx = p_hal->syntax.refp.scene_ref_replace_pos; + + mpp_buf_slot_get_prop(cfg->frame_slots, slot_idx, SLOT_FRAME_PTR, &scene_ref); + + if (scene_ref) { + regs->comm_addrs.reg170_185_ref_base[replace_idx] = hal_avs2d_get_frame_fd(p_hal, slot_idx); + regs->comm_addrs.reg195_210_payload_st_ref_base[replace_idx] = regs->comm_addrs.reg170_185_ref_base[replace_idx]; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, slot_idx); + regs->comm_addrs.reg217_232_colmv_ref_base[replace_idx] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + regs->comm_addrs.reg169_error_ref_base = regs->comm_addrs.reg170_185_ref_base[0]; + regs->comm_addrs.reg194_payload_st_error_ref_base = regs->comm_addrs.reg195_210_payload_st_ref_base[0]; + } + + // set rlc + regs->comm_addrs.reg128_strm_base = hal_avs2d_get_packet_fd(p_hal, task_dec->input); + AVS2D_HAL_TRACE("packet fd %d from slot %d", regs->comm_addrs.reg128_strm_base, task_dec->input); + + regs->comm_paras.reg66_stream_len = MPP_ALIGN(mpp_packet_get_length(task_dec->input_packet), 16) + 64; + regs->comm_addrs.reg129_stream_buf_st_base = hal_avs2d_get_packet_fd(p_hal, task_dec->input); + regs->comm_addrs.reg130_stream_buf_end_base = hal_avs2d_get_packet_fd(p_hal, task_dec->input); + { + MppBuffer mbuffer = NULL; + + mpp_buf_slot_get_prop(cfg->packet_slots, task_dec->input, SLOT_BUFFER, &mbuffer); + mpp_dev_set_reg_offset(cfg->dev, 130, mpp_buffer_get_size(mbuffer)); + } +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "stream_in.dat"; + MppBuffer strm_in_buf = NULL; + + mpp_buf_slot_get_prop(cfg->packet_slots, task_dec->input, SLOT_BUFFER, &strm_in_buf); + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(strm_in_buf), + 8 * regs->comm_paras.reg66_stream_len, 128, 0, 0); + } +#endif + + { + //scale down config + mpp_buf_slot_get_prop(cfg->frame_slots, task_dec->output, + SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe)) { + regs->comm_addrs.reg133_scale_down_base = regs->comm_addrs.reg168_decout_base; + vdpu38x_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + } else { + regs->ctrl_regs.reg9.scale_down_en = 0; + } + } + + return ret; +} + +MPP_RET hal_avs2d_vdpu384b_init(void *hal, MppHalCfg *cfg) +{ + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + RK_U32 i, loop; + MPP_RET ret = MPP_OK; + + mpp_env_get_u32("hal_avs2d_debug", &hal_avs2d_debug, 0); + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Avs2dRkvRegCtx))); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + //!< malloc buffers + reg_ctx->shph_dat = mpp_calloc(RK_U8, AVS2_384B_SHPH_SIZE); + reg_ctx->scalist_dat = mpp_calloc(RK_U8, AVS2_384B_SCALIST_SIZE); + loop = p_hal->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + FUN_CHECK(ret = mpp_buffer_get(p_hal->cfg->buf_group, ®_ctx->bufs, AVS2_ALL_TBL_BUF_SIZE(loop))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + mpp_buffer_attach_dev(reg_ctx->bufs, p_hal->cfg->dev); + + for (i = 0; i < loop; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu38xRegSet, 1); + vdpu384b_init_ctrl_regs(reg_ctx->reg_buf[i].regs, MPP_VIDEO_CodingAVS2); + reg_ctx->reg_buf[i].offset_shph = AVS2_SHPH_OFFSET(i); + reg_ctx->reg_buf[i].offset_sclst = AVS2_SCALIST_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[0].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[0].offset_sclst; + } + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + + return ret; +__FAILED: + hal_avs2d_vdpu_deinit(p_hal); + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +MPP_RET hal_avs2d_vdpu384b_gen_regs(void *hal, HalTaskInfo *task) +{ + Avs2dRkvRegCtx *reg_ctx; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Vdpu38xRegSet *regs = NULL; + MPP_RET ret = MPP_OK; + + AVS2D_HAL_TRACE("In."); + + INP_CHECK(ret, NULL == p_hal); + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + ret = MPP_NOK; + goto __RETURN; + } + + memcpy(&p_hal->syntax, task->dec.syntax.data, sizeof(Avs2dSyntax_t)); + ret = hal_avs2d_set_up_colmv_buf(p_hal); + if (ret) + goto __RETURN; + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + + if (p_hal->fast_mode) { + RK_U32 i = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(reg_ctx->reg_buf); i++) { + if (!reg_ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = reg_ctx->reg_buf[i].regs; + reg_ctx->shph_offset = reg_ctx->reg_buf[i].offset_shph; + reg_ctx->sclst_offset = reg_ctx->reg_buf[i].offset_sclst; + reg_ctx->regs = reg_ctx->reg_buf[i].regs; + reg_ctx->reg_buf[i].valid = 1; + break; + } + } + + mpp_assert(regs); + } + + regs = reg_ctx->regs; + memset(regs, 0, sizeof(Vdpu38xRegSet)); + vdpu384b_init_ctrl_regs(regs, MPP_VIDEO_CodingAVS2); + +#ifdef DUMP_VDPU38X_DATAS + { + memset(vdpu38x_dump_cur_dir, 0, sizeof(vdpu38x_dump_cur_dir)); + sprintf(vdpu38x_dump_cur_dir, "avs2/Frame%04d", vdpu38x_dump_cur_frm); + if (access(vdpu38x_dump_cur_dir, 0)) { + if (mkdir(vdpu38x_dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", vdpu38x_dump_cur_dir); + } + vdpu38x_dump_cur_frm++; + } +#endif + + hal_avs2d_vdpu38x_prepare_header(p_hal, reg_ctx->shph_dat, AVS2_384B_SHPH_SIZE / 8); + hal_avs2d_vdpu38x_prepare_scalist(p_hal, reg_ctx->scalist_dat, AVS2_384B_SCALIST_SIZE / 8); + + ret = fill_registers(p_hal, regs, task); + + if (ret) + goto __RETURN; + + { + memcpy(reg_ctx->bufs_ptr + reg_ctx->shph_offset, reg_ctx->shph_dat, AVS2_384B_SHPH_SIZE); + memcpy(reg_ctx->bufs_ptr + reg_ctx->sclst_offset, reg_ctx->scalist_dat, AVS2_384B_SCALIST_SIZE); + + regs->comm_addrs.reg131_gbl_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(p_hal->cfg->dev, 131, reg_ctx->shph_offset); + regs->comm_paras.reg67_global_len = AVS2_384B_SHPH_SIZE; + + regs->comm_addrs.reg132_scanlist_addr = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(p_hal->cfg->dev, 132, reg_ctx->sclst_offset); + } + + vdpu38x_avs2d_rcb_setup(p_hal, task, ®s->comm_addrs.rcb_regs, vdpu384b_avs2d_rcb_calc); + vdpu38x_setup_statistic(®s->ctrl_regs); + mpp_buffer_sync_end(reg_ctx->bufs); + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +MPP_RET hal_avs2d_vdpu384b_start(void *hal, HalTaskInfo *task) +{ + Vdpu38xRegSet *regs = NULL; + Avs2dRkvRegCtx *reg_ctx; + MppDev dev = NULL; + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + MPP_RET ret = MPP_OK; + + AVS2D_HAL_TRACE("In."); + INP_CHECK(ret, NULL == p_hal); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + regs = p_hal->fast_mode ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + dev = p_hal->cfg->dev; + + p_hal->frame_no++; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->ctrl_regs; + wr_cfg.size = sizeof(regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_paras; + wr_cfg.size = sizeof(regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_addrs; + wr_cfg.size = sizeof(regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->ctrl_regs.reg15; + rd_cfg.size = sizeof(regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) { + rd_cfg.reg = ®s->statistic_regs; + rd_cfg.size = sizeof(regs->statistic_regs); + rd_cfg.offset = VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + // send request to hardware + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + + } while (0); + +__RETURN: + AVS2D_HAL_TRACE("Out."); + return ret; +} + +MPP_RET hal_avs2d_vdpu384b_wait(void *hal, HalTaskInfo *task) +{ + Avs2dHalCtx_t *p_hal = (Avs2dHalCtx_t *)hal; + Avs2dRkvRegCtx *reg_ctx; + Vdpu38xRegSet *regs; + MPP_RET ret = MPP_OK; + + INP_CHECK(ret, NULL == p_hal); + reg_ctx = (Avs2dRkvRegCtx *)p_hal->reg_ctx; + regs = p_hal->fast_mode ? reg_ctx->reg_buf[task->dec.reg_index].regs : reg_ctx->regs; + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + AVS2D_HAL_DBG(AVS2D_HAL_DBG_ERROR, "found task error.\n"); + ret = MPP_NOK; + goto __RETURN; + } else { + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + if (hal_avs2d_debug & AVS2D_HAL_DBG_OUT) + hal_avs2d_vdpu_dump_yuv(hal, task); + + if (hal_avs2d_debug & AVS2D_HAL_DBG_REG) { + RK_U32 *p = (RK_U32 *)regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(regs->ctrl_regs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_CTRL_REGS, *p++); + for (i = 0; i < sizeof(regs->comm_paras) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_CODEC_PARAS_REGS, *p++); + for (i = 0; i < sizeof(regs->comm_addrs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_COMMON_ADDR_REGS, *p++); + for (i = 0; i < sizeof(regs->statistic_regs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B, *p++); + + mpp_assert(regs->statistic_regs.reg312.rcb_rd_sum_chk == + regs->statistic_regs.reg312.rcb_wr_sum_chk); + } + + AVS2D_HAL_TRACE("read irq_status 0x%08x\n", regs->ctrl_regs.reg15); + + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)regs; + + if ((!regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) + param.hard_err = 1; + else + param.hard_err = 0; + + task->dec.flags.ref_info_valid = 0; + + AVS2D_HAL_TRACE("hal frame %d hard_err= %d", p_hal->frame_no, param.hard_err); + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + + memset(®s->ctrl_regs.reg15, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + +__RETURN: + AVS2D_HAL_TRACE("Out. ret %d", ret); + return ret; +} + +const MppHalApi hal_avs2d_vdpu384b = { + .name = "avs2d_vdpu384b", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVS2, + .ctx_size = sizeof(Avs2dHalCtx_t), + .flag = 0, + .init = hal_avs2d_vdpu384b_init, + .deinit = hal_avs2d_vdpu_deinit, + .reg_gen = hal_avs2d_vdpu384b_gen_regs, + .start = hal_avs2d_vdpu384b_start, + .wait = hal_avs2d_vdpu384b_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_avs2d_vdpu384b) diff --git a/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu384b.h b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu384b.h new file mode 100644 index 000000000..695d49d34 --- /dev/null +++ b/mpp/hal/rkdec/avs2d/hal_avs2d_vdpu384b.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_AVS2D_VDPU384B_H +#define HAL_AVS2D_VDPU384B_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_avs2d_vdpu384b; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVS2D_VDPU384B_H */ diff --git a/mpp/hal/rkdec/avsd/CMakeLists.txt b/mpp/hal/rkdec/avsd/CMakeLists.txt new file mode 100644 index 000000000..cef83d569 --- /dev/null +++ b/mpp/hal/rkdec/avsd/CMakeLists.txt @@ -0,0 +1,15 @@ +# vim: syntax=cmake + +# hal avs decoder sourse + +set(HAL_AVSD_SRC + hal_avsd_base.c + hal_avsd_plus.c + ) + +add_hal_source(HAL_AVSD_SRC HAVE_VDPU1 hal_avsd_vdpu1.c) +add_hal_source(HAL_AVSD_SRC HAVE_VDPU2 hal_avsd_vdpu2.c) + +if (HAL_AVSD_SRC) + add_library(hal_avsd_api OBJECT ${HAL_AVSD_SRC}) +endif() diff --git a/mpp/hal/rkdec/avsd/hal_avsd_base.c b/mpp/hal/rkdec/avsd/hal_avsd_base.c new file mode 100644 index 000000000..022ac05f2 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_base.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_avsd_base" + +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_platform.h" +#include "hal_avsd_base.h" + +RK_S32 get_queue_pic(AvsdHalCtx_t *p_hal) +{ + RK_U32 i = 0; + RK_S32 ret_idx = -1; + + for (i = 0; i < MPP_ARRAY_ELEMS(p_hal->pic); i++) { + if (!p_hal->pic[i].valid) { + ret_idx = i; + p_hal->pic[i].valid = 1; + break; + } + } + + return ret_idx; +} + +RK_S32 get_packet_fd(AvsdHalCtx_t *p_hal, RK_S32 idx) +{ + RK_S32 ret_fd = 0; + MppBuffer mbuffer = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, idx, SLOT_BUFFER, &mbuffer); + mpp_assert(mbuffer); + ret_fd = mpp_buffer_get_fd(mbuffer); + + return ret_fd; +} + +RK_S32 get_frame_fd(AvsdHalCtx_t *p_hal, RK_S32 idx) +{ + RK_S32 ret_fd = 0; + MppBuffer mbuffer = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, idx, SLOT_BUFFER, &mbuffer); + mpp_assert(mbuffer); + ret_fd = mpp_buffer_get_fd(mbuffer); + + return ret_fd; +} diff --git a/mpp/hal/rkdec/avsd/hal_avsd_base.h b/mpp/hal/rkdec/avsd/hal_avsd_base.h new file mode 100644 index 000000000..5735063a1 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_base.h @@ -0,0 +1,139 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVSD_BASE_H +#define HAL_AVSD_BASE_H + +#include "parser_api.h" +#include "avsd_syntax.h" +#include "mpp_hal.h" +#include "mpp_env.h" + +#include "mpp_device.h" + +#define AVSD_HAL_DBG_ERROR (0x00000001) +#define AVSD_HAL_DBG_ASSERT (0x00000002) +#define AVSD_HAL_DBG_WARNNING (0x00000004) +#define AVSD_HAL_DBG_TRACE (0x00000008) + +#define AVSD_HAL_DBG_OFFSET (0x00000010) +#define AVSD_HAL_DBG_WAIT (0x00000020) + +#define AVSD_DBG_HARD_MODE (0x00010000) +#define AVSD_DBG_PROFILE_ID (0x00020000) + +extern RK_U32 hal_avsd_debug; + +#define AVSD_HAL_DBG(level, fmt, ...)\ +do {\ + if (level & hal_avsd_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define AVSD_HAL_TRACE(fmt, ...)\ +do {\ + if (AVSD_HAL_DBG_TRACE & hal_avsd_debug)\ + { mpp_log_f(fmt, ## __VA_ARGS__); }\ +} while (0) + + +#define INP_CHECK(ret, val, ...)\ +do{\ + if ((val)) { \ + ret = MPP_ERR_INIT; \ + AVSD_HAL_DBG(AVSD_HAL_DBG_WARNNING, "input empty(%d).\n", __LINE__); \ + goto __RETURN; \ + }\ +} while (0) + + +#define FUN_CHECK(val)\ +do{\ + if ((val) < 0) {\ + AVSD_HAL_DBG(AVSD_HAL_DBG_WARNNING, "Function error(%d).\n", __LINE__); \ + goto __FAILED; \ + }\ +} while (0) + + +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do{\ + if (!(val)) {\ + ret = MPP_ERR_MALLOC; \ + mpp_err_f("malloc buffer error(%d).\n", __LINE__); \ + goto __FAILED; \ + }\ +} while (0) + + +#define FIELDPICTURE 0 +#define FRAMEPICTURE 1 + +enum { + IFRAME = 0, + PFRAME = 1, + BFRAME = 2 +}; + +typedef struct avsd_hal_picture_t { + RK_U32 valid; + RK_U32 pic_type; + RK_U32 pic_code_type; + RK_U32 picture_distance; + + RK_S32 slot_idx; +} AvsdHalPic_t; + + +typedef struct avsd_hal_ctx_t { + MppCodingType coding; + + MppHalCfg *cfg; + + AvsdSyntax_t syn; + RK_U32 *p_regs; + RK_U32 regs_num; + MppBuffer mv_buf; + + AvsdHalPic_t pic[3]; + //!< add for control + RK_U32 first_field; + RK_U32 prev_pic_structure; + RK_U32 prev_pic_code_type; + RK_S32 future2prev_past_dist; + RK_S32 work0; + RK_S32 work1; + RK_S32 work_out; + RK_U32 data_offset; + + RK_U32 frame_no; +} AvsdHalCtx_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 get_queue_pic(AvsdHalCtx_t *p_hal); +RK_S32 get_packet_fd(AvsdHalCtx_t *p_hal, RK_S32 idx); +RK_S32 get_frame_fd(AvsdHalCtx_t *p_hal, RK_S32 idx); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVSD_COMMON_H */ diff --git a/mpp/hal/rkdec/avsd/hal_avsd_plus.c b/mpp/hal/rkdec/avsd/hal_avsd_plus.c new file mode 100644 index 000000000..ee8834ff7 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_plus.c @@ -0,0 +1,902 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_avsd_plus" + +#include + +#include "mpp_common.h" +#include "mpp_mem.h" +#include "mpp_device.h" + +#include "mpp_hal.h" +#include "avsd_syntax.h" +#include "hal_avsd_plus_reg.h" +#include "hal_avsd_plus.h" +#include "mpp_dec_cb_param.h" +#include "hal_avsd_base.h" + +/*! + *********************************************************************** + * \brief + * init decoder parameters + *********************************************************************** + */ +//extern "C" +static MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal) +{ + AvsdPlusRegs_t *p_regs = (AvsdPlusRegs_t *)p_hal->p_regs; + + p_regs->sw02.dec_out_endian = 1; + p_regs->sw02.dec_in_endian = 0; + p_regs->sw02.dec_strendian_e = 1; + p_regs->sw02.dec_max_burst = 16; + p_regs->sw02.dec_scmd_dis = 0; + + p_regs->sw02.dec_adv_pre_dis = 0; + p_regs->sw55.apf_threshold = 8; + + p_regs->sw02.dec_latency = 0; + p_regs->sw02.dec_data_disc_e = 0; + p_regs->sw02.dec_outswap32_e = 1; + p_regs->sw02.dec_inswap32_e = 1; + p_regs->sw02.dec_strswap32_e = 1; + + p_regs->sw02.dec_timeout_e = 0; + p_regs->sw02.dec_clk_gate_e = 1; + p_regs->sw01.dec_irq_dis = 0; + + p_regs->sw58.serv_merge_dis = 0; + p_regs->sw02.dec_axi_rd_id = 0xFF; + p_regs->sw03.dec_axi_wr_id = 0; + + p_regs->sw49.pred_bc_tap_0_0 = -1; + p_regs->sw49.pred_bc_tap_0_1 = 5; + p_regs->sw49.pred_bc_tap_0_2 = 5; + p_regs->sw34.pred_bc_tap_0_3 = -1; + + p_regs->sw34.pred_bc_tap_1_0 = 1; + p_regs->sw34.pred_bc_tap_1_1 = 7; + p_regs->sw35.pred_bc_tap_1_2 = 7; + p_regs->sw35.pred_bc_tap_1_3 = 1; + + return MPP_OK; +} + +static MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AvsdSyntax_t *p_syn = &p_hal->syn; + AvsdPlusRegs_t *p_regs = (AvsdPlusRegs_t *)p_hal->p_regs; + MppHalCfg *cfg = p_hal->cfg; + + p_regs->sw02.dec_timeout_e = 1; + + //!< set wrok_out pic info + if (p_hal->work_out < 0) { + p_hal->work_out = get_queue_pic(p_hal); + if (p_hal->work_out < 0) { + ret = MPP_NOK; + mpp_err_f("cannot get a pic_info buffer.\n"); + goto __FAILED; + } + } + { + AvsdHalPic_t *p_work_out = &p_hal->pic[p_hal->work_out]; + + p_work_out->slot_idx = task->output; + p_work_out->pic_code_type = p_syn->pp.picCodingType; + p_work_out->picture_distance = p_syn->pp.pictureDistance; + } + //!< set register + set_defalut_parameters(p_hal); + p_regs->sw04.pic_mb_width = (p_syn->pp.horizontalSize + 15) >> 4; + p_regs->sw03.dec_mode = 11; //!< DEC_MODE_AVS + + if (p_syn->pp.pictureStructure == FRAMEPICTURE) { + p_regs->sw03.pic_interlace_e = 0; + p_regs->sw03.pic_fieldmode_e = 0; + p_regs->sw03.pic_topfiled_e = 0; + } else { + p_regs->sw03.pic_interlace_e = 1; + p_regs->sw03.pic_fieldmode_e = 1; + if (p_syn->pp.topFieldFirst) { + p_regs->sw03.pic_topfiled_e = p_hal->first_field; + } else { + p_regs->sw03.pic_topfiled_e = !p_hal->first_field; + } + } + + p_regs->sw04.pic_mb_height_p = (p_syn->pp.verticalSize + 15) >> 4; + p_regs->sw07.avs_h_ext = (p_syn->pp.verticalSize + 15) >> 12; + + if (p_syn->pp.picCodingType == BFRAME) { + p_regs->sw03.pic_b_e = 1; + } else { + p_regs->sw03.pic_b_e = 0; + } + p_regs->sw03.pic_inter_e = (p_syn->pp.picCodingType != IFRAME) ? 1 : 0; + + p_regs->sw05.strm_start_bit = 8 * (p_hal->data_offset & 0x7); + p_hal->data_offset = (p_hal->data_offset & ~0x7); + p_regs->sw12.rlc_vlc_base = get_packet_fd(p_hal, task->input); + mpp_dev_set_reg_offset(cfg->dev, 12, p_hal->data_offset); + p_regs->sw06.stream_len = p_syn->bitstream_size - p_hal->data_offset; + + p_regs->sw03.pic_fixed_quant = p_syn->pp.fixedPictureQp; + p_regs->sw06.init_qp = p_syn->pp.pictureQp; + //!< AVS Plus stuff + if (p_syn->pp.profileId == 0x48) { + p_regs->sw44.dec_avsp_ena = 1; + } else { + p_regs->sw44.dec_avsp_ena = 0; + } + if (p_regs->sw44.dec_avsp_ena) { + p_regs->sw44.weight_qp_e = p_syn->pp.weightingQuantFlag; + p_regs->sw44.avs_aec_e = p_syn->pp.aecEnable; + p_regs->sw44.no_fwd_ref_e = p_syn->pp.noForwardReferenceFlag; + p_regs->sw44.pb_field_enhance_e = p_syn->pp.pbFieldEnhancedFlag; + + if (p_syn->pp.weightingQuantFlag + && !p_syn->pp.chromaQuantParamDisable) { + p_regs->sw44.qp_delta_cb = p_syn->pp.chromaQuantParamDeltaCb; + p_regs->sw44.qp_delta_cr = p_syn->pp.chromaQuantParamDeltaCr; + } else { + p_regs->sw44.qp_delta_cb = 0; + p_regs->sw44.qp_delta_cr = 0; + } + if (p_syn->pp.weightingQuantFlag) { + p_regs->sw44.weight_qp_model = p_syn->pp.weightingQuantModel; + p_regs->sw44.weight_qp_0 = p_syn->pp.weightingQuantParam[0]; + p_regs->sw42.weight_qp_1 = p_syn->pp.weightingQuantParam[1]; + p_regs->sw43.weight_qp_2 = p_syn->pp.weightingQuantParam[2]; + p_regs->sw43.weight_qp_3 = p_syn->pp.weightingQuantParam[3]; + p_regs->sw43.weight_qp_4 = p_syn->pp.weightingQuantParam[4]; + p_regs->sw43.weight_qp_5 = p_syn->pp.weightingQuantParam[5]; + } + } + //!< AVS Plus end + if (p_syn->pp.pictureStructure == FRAMEPICTURE || p_hal->first_field) { + p_regs->sw13.dec_out_base = get_frame_fd(p_hal, task->output); + } else { + //!< start of bottom field line + RK_U32 stride = p_syn->pp.horizontalSize; + + p_regs->sw13.dec_out_base = get_frame_fd(p_hal, task->output); + mpp_dev_set_reg_offset(cfg->dev, 13, stride); + } + { + RK_S32 tmp_fwd = -1; + RK_S32 refer0 = -1; + RK_S32 refer1 = -1; + + tmp_fwd = (p_hal->work1 < 0) ? p_hal->work0 : p_hal->work1; + tmp_fwd = (tmp_fwd < 0) ? p_hal->work_out : tmp_fwd; + + refer0 = (task->refer[0] < 0) ? task->output : task->refer[0]; + refer1 = (task->refer[1] < 0) ? refer0 : task->refer[1]; + if (!p_hal->first_field + && p_syn->pp.pictureStructure == FIELDPICTURE + && p_syn->pp.picCodingType != BFRAME) { + p_regs->sw14.refer0_base = get_frame_fd(p_hal, task->output); + p_regs->sw15.refer1_base = get_frame_fd(p_hal, refer0); + p_regs->sw16.refer2_base = get_frame_fd(p_hal, refer0); + p_regs->sw17.refer3_base = get_frame_fd(p_hal, refer1); + } else { + p_regs->sw14.refer0_base = get_frame_fd(p_hal, refer0); + p_regs->sw15.refer1_base = get_frame_fd(p_hal, refer0); + p_regs->sw16.refer2_base = get_frame_fd(p_hal, refer1); + p_regs->sw17.refer3_base = get_frame_fd(p_hal, refer1); + } + } + //!< block distances + if (p_syn->pp.pictureStructure == FRAMEPICTURE) { + if (p_syn->pp.picCodingType == BFRAME) { + RK_S32 tmp = 0; + //!< current to future anchor + if (p_hal->work0 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_syn->pp.pictureDistance + 512) & 0x1FF; + } + //!< prevent division by zero + if (!tmp) tmp = 2; + p_regs->sw31.ref_dist_cur_2 = tmp; + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_2 = 512 / tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + + //!< current to past anchor + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + p_regs->sw30.ref_dist_cur_0 = tmp; + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_0 = 512 / tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + //!< future anchor to past anchor + if (p_hal->work0 >= 0 && p_hal->work1 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + tmp = 16384 / tmp; + p_regs->sw32.ref_invd_col_0 = tmp; + p_regs->sw32.ref_invd_col_1 = tmp; + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + tmp = 16384 / tmp; + p_regs->sw33.ref_invd_col_2 = tmp; + p_regs->sw33.ref_invd_col_3 = tmp; + } else { + RK_S32 tmp = 0; + //!< current to past anchor + if (p_hal->work0 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF; + } + if (!tmp) tmp = 2; + p_regs->sw30.ref_dist_cur_0 = tmp; + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_0 = 512 / tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + //!< current to previous past anchor + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + //!< this will become "future to previous past" for next B + p_hal->future2prev_past_dist = tmp; + + p_regs->sw31.ref_dist_cur_2 = tmp; + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_2 = 512 / tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + + p_regs->sw32.ref_invd_col_0 = 0; + p_regs->sw32.ref_invd_col_1 = 0; + p_regs->sw33.ref_invd_col_2 = 0; + p_regs->sw33.ref_invd_col_3 = 0; + } + } else { + //!< field interlaced + if (p_syn->pp.picCodingType == BFRAME) { + RK_S32 tmp = 0; + //!< block distances + if (p_hal->work0 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_syn->pp.pictureDistance + 512) & 0x1FF; + } + //!< prevent division by zero + if (!tmp) tmp = 2; + + if (p_hal->first_field) { + p_regs->sw31.ref_dist_cur_2 = tmp; + p_regs->sw31.ref_dist_cur_3 = tmp + 1; + p_regs->sw29.ref_invd_cur_2 = 512 / tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / (tmp + 1); + } else { + p_regs->sw31.ref_dist_cur_2 = tmp - 1; + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_2 = 512 / (tmp - 1); + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + } + + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + if (p_hal->first_field) { + p_regs->sw30.ref_dist_cur_0 = (tmp - 1); + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_0 = 512 / (tmp - 1); + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + } else { + p_regs->sw30.ref_dist_cur_0 = tmp; + p_regs->sw30.ref_dist_cur_1 = tmp + 1; + p_regs->sw28.ref_invd_cur_0 = 512 / tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / (tmp + 1); + } + + if (p_hal->work0 >= 0 && p_hal->work1 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + //!< AVS Plus stuff + if (p_syn->pp.pbFieldEnhancedFlag && !p_hal->first_field) { + //!< in this case, BlockDistanceRef is different with before, the mvRef points to top field + p_regs->sw32.ref_invd_col_0 = 16384 / (tmp - 1); + p_regs->sw32.ref_invd_col_1 = 16384 / tmp; + + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + + p_regs->sw33.ref_invd_col_2 = 16384 / (tmp - 1); + p_regs->sw33.ref_invd_col_3 = 16384 / tmp; + } else { + if (p_hal->first_field) { + p_regs->sw32.ref_invd_col_0 = 16384 / (tmp - 1); + p_regs->sw32.ref_invd_col_1 = 16384 / tmp; + } else { + p_regs->sw32.ref_invd_col_0 = 16384; + p_regs->sw32.ref_invd_col_1 = 16384 / tmp; + p_regs->sw33.ref_invd_col_2 = 16384 / (tmp + 1); + } + + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + + if (p_hal->first_field) { + p_regs->sw33.ref_invd_col_2 = 16384 / (tmp - 1); + p_regs->sw33.ref_invd_col_3 = 16384 / tmp; + } else { + p_regs->sw33.ref_invd_col_3 = 16384 / tmp; + } + } + } else { + RK_S32 tmp = 0; + if (p_hal->work0 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF; + } + if (!tmp) tmp = 2; + + if (!p_hal->first_field) { + p_regs->sw30.ref_dist_cur_0 = 1; + p_regs->sw31.ref_dist_cur_2 = tmp + 1; + + p_regs->sw28.ref_invd_cur_0 = 512; + p_regs->sw29.ref_invd_cur_2 = 512 / (tmp + 1); + } else { + p_regs->sw30.ref_dist_cur_0 = tmp - 1; + p_regs->sw28.ref_invd_cur_0 = 512 / (tmp - 1); + } + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + //!< this will become "future to previous past" for next B + p_hal->future2prev_past_dist = tmp; + if (p_hal->first_field) { + p_regs->sw31.ref_dist_cur_2 = tmp - 1; + p_regs->sw31.ref_dist_cur_3 = tmp; + + p_regs->sw29.ref_invd_cur_2 = 512 / (tmp - 1); + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + } else { + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + } + + p_regs->sw32.ref_invd_col_0 = 0; + p_regs->sw32.ref_invd_col_1 = 0; + p_regs->sw33.ref_invd_col_2 = 0; + p_regs->sw33.ref_invd_col_3 = 0; + } + } + //!< AVS Plus stuff + if (p_regs->sw44.dec_avsp_ena) { + p_regs->sw42.ref_delta_col_0 = 0; + p_regs->sw42.ref_delta_col_1 = 0; + p_regs->sw42.ref_delta_col_2 = 0; + p_regs->sw42.ref_delta_col_3 = 0; + p_regs->sw42.ref_delta_cur_0 = 0; + p_regs->sw42.ref_delta_cur_1 = 0; + p_regs->sw42.ref_delta_cur_2 = 0; + p_regs->sw42.ref_delta_cur_3 = 0; + if (p_syn->pp.pictureStructure == FIELDPICTURE + && p_syn->pp.picCodingType == BFRAME) { + //!< 1 means delta=2, 3 means delta=-2, 0 means delta=0 + //!< delta1 + p_regs->sw42.ref_delta_col_0 = 2; + p_regs->sw42.ref_delta_col_1 = 0; + p_regs->sw42.ref_delta_col_2 = 2; + p_regs->sw42.ref_delta_col_3 = 0; + if (p_hal->first_field) { + //!< deltaFw + p_regs->sw42.ref_delta_cur_0 = 2; + p_regs->sw42.ref_delta_cur_1 = 0; + //!< deltaBw + p_regs->sw42.ref_delta_cur_2 = 0; + p_regs->sw42.ref_delta_cur_3 = 0; + } else { + //!< deltaFw + p_regs->sw42.ref_delta_cur_0 = 0; + p_regs->sw42.ref_delta_cur_1 = 0; + //!< deltaBw + p_regs->sw42.ref_delta_cur_2 = 6; //!< (RK_U32)-2 + p_regs->sw42.ref_delta_cur_3 = 6; //!< (RK_U32)-2 + } + } + } + //!< AVS Plus end + + p_regs->sw48.startmb_x = 0; + p_regs->sw48.startmb_y = 0; + + p_regs->sw03.filtering_dis = p_syn->pp.loopFilterDisable; + p_regs->sw05.alpha_offset = p_syn->pp.alphaOffset; + p_regs->sw05.beta_offset = p_syn->pp.betaOffset; + p_regs->sw03.skip_mode = p_syn->pp.skipModeFlag; + p_regs->sw04.pic_refer_flag = p_syn->pp.pictureReferenceFlag; + + //!< AVS Plus change + p_regs->sw03.write_mvs_e = 0; + if (p_regs->sw44.dec_avsp_ena) { + if (p_syn->pp.picCodingType == PFRAME + || p_syn->pp.picCodingType == IFRAME) { + p_regs->sw03.write_mvs_e = 1; + } + } else { + if (p_syn->pp.picCodingType == PFRAME + || (p_syn->pp.picCodingType == IFRAME && !p_hal->first_field)) { + p_regs->sw03.write_mvs_e = 1; + } + } + //!< AVS Plus end + //!< set mv base + if (p_hal->first_field || + (p_syn->pp.picCodingType == BFRAME && p_hal->prev_pic_structure)) { + p_regs->sw41.dir_mv_base = mpp_buffer_get_fd(p_hal->mv_buf); + } else { + RK_U32 frame_width = 0, frame_height = 0, offset = 0; + frame_width = (p_syn->pp.horizontalSize + 15) >> 4; + if (p_syn->pp.progressiveFrame) + frame_height = (p_syn->pp.verticalSize + 15) >> 4; + else + frame_height = 2 * ((p_syn->pp.verticalSize + 31) >> 5); + offset = MPP_ALIGN(frame_width * frame_height / 2, 2) * 16; + p_regs->sw41.dir_mv_base = mpp_buffer_get_fd(p_hal->mv_buf); + mpp_dev_set_reg_offset(cfg->dev, 41, offset); + } + //!< AVS Plus stuff + if (p_regs->sw44.dec_avsp_ena) { + p_regs->sw45.dir_mv_base2 = mpp_buffer_get_fd(p_hal->mv_buf); + } + //!< AVS Plus end + { + RK_U32 pic_type = 0; + RK_U32 prev_anc_type = 0; + + if (p_hal->work0 >= 0) { + pic_type = p_hal->pic[p_hal->work0].pic_type; + } + prev_anc_type = !pic_type || (!p_hal->first_field && !p_hal->prev_pic_structure); + p_regs->sw18.prev_anc_type = prev_anc_type; + } + //!< b-picture needs to know if future reference is field or frame coded + // p_regs->sw16.refer2_field_e = (!p_hal->prev_pic_structure) ? 1 : 0; + // p_regs->sw17.refer3_field_e = (!p_hal->prev_pic_structure) ? 1 : 0; + if (!p_hal->prev_pic_structure) { + mpp_dev_set_reg_offset(cfg->dev, 16, 2); + mpp_dev_set_reg_offset(cfg->dev, 17, 3); + } + + p_regs->sw03.dec_out_dis = 0; + p_regs->sw01.dec_e = 1; + + return MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET update_parameters(AvsdHalCtx_t *p_hal) +{ + AvsdSyntax_t *p_syn = &p_hal->syn; + + if (p_syn->pp.pictureStructure == FRAMEPICTURE || !p_hal->first_field) { + p_hal->first_field = 1; + if (p_syn->pp.picCodingType != BFRAME) { + RK_S32 temp = p_hal->work1; + + p_hal->work1 = p_hal->work0; + p_hal->work0 = p_hal->work_out; + + if (p_hal->work_out >= 0) + p_hal->pic[p_hal->work_out].pic_type = p_syn->pp.picCodingType == IFRAME; + p_hal->work_out = temp; + p_hal->prev_pic_structure = p_syn->pp.pictureStructure; + } + p_hal->prev_pic_code_type = p_syn->pp.picCodingType; + } else { + p_hal->first_field = 0; + } + + return MPP_OK; +} + +static MPP_RET hal_avsd_plus_start(void *decoder, HalTaskInfo *task); +static MPP_RET hal_avsd_plus_wait(void *decoder, HalTaskInfo *task); +static MPP_RET repeat_other_field(AvsdHalCtx_t *p_hal, HalTaskInfo *task) +{ + RK_U32 i = 0; + RK_U8 *pdata = NULL; + MppBuffer mbuffer = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdPlusRegs_t *p_regs = (AvsdPlusRegs_t *)p_hal->p_regs; + RK_U32 stream_remain = 0; + RK_U8 *ptr = NULL; + + //!< re-find start code and calculate offset + p_hal->data_offset = p_regs->sw12.rlc_vlc_base >> 10; + p_hal->data_offset += p_hal->syn.bitstream_offset; + p_hal->data_offset -= MPP_MIN(p_hal->data_offset, 8); + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + pdata = (RK_U8 *)mpp_buffer_get_ptr(mbuffer) + p_hal->data_offset; + stream_remain = p_hal->syn.bitstream_size - p_hal->data_offset; + + AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no=%d, poc %d, stream %d, offset %d, remain %d\n", + p_hal->frame_no, p_hal->syn.pp.pictureDistance, p_hal->syn.bitstream_size, + p_hal->data_offset, stream_remain); + + while (stream_remain > 3) { + ptr = memchr(pdata, 1, stream_remain); + + if (!ptr) + break; + + stream_remain = stream_remain - (ptr - pdata + 1); + + if (!ptr[-1] && !ptr[-2]) { + p_hal->data_offset = p_hal->syn.bitstream_size - stream_remain - 3; + break; + } else { + pdata = ptr + 1; + ptr = NULL; + } + } + AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no=%d, i=%d, offset=%d\n", + p_hal->frame_no, i, p_hal->data_offset); + //!< re-generate register + p_hal->frame_no++; + FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec)); + hal_avsd_plus_start((void *)p_hal, task); + hal_avsd_plus_wait((void *)p_hal, task); + + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! + *********************************************************************** + * \brief + * init + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_init(void *decoder, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 buf_size = 0; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + mpp_env_get_u32("hal_avsd_debug", &hal_avsd_debug, 0); + + AVSD_HAL_TRACE("AVS_plus In."); + + p_hal->cfg = cfg; + + buf_size = (1920 * 1088) * 2; + FUN_CHECK(ret = mpp_buffer_get(p_hal->cfg->buf_group, &p_hal->mv_buf, buf_size)); + + p_hal->p_regs = mpp_calloc_size(RK_U32, sizeof(AvsdPlusRegs_t)); + MEM_CHECK(ret, p_hal->p_regs); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + p_hal->regs_num = 60; + //!< initial for control + p_hal->first_field = 1; + p_hal->prev_pic_structure = 0; //!< field + + memset(p_hal->pic, 0, sizeof(p_hal->pic)); + p_hal->work_out = -1; + p_hal->work0 = -1; + p_hal->work1 = -1; + p_hal->cfg = cfg; + + AVSD_HAL_TRACE("Out."); + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! + *********************************************************************** + * \brief + * deinit + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_deinit(void *decoder) +{ + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + if (p_hal->mv_buf) { + mpp_buffer_put(p_hal->mv_buf); + p_hal->mv_buf = NULL; + } + MPP_FREE(p_hal->p_regs); + + AVSD_HAL_TRACE("Out."); + return MPP_OK; +} +/*! + *********************************************************************** + * \brief + * generate register + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_gen_regs(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + p_hal->data_offset = p_hal->syn.bitstream_offset; + + memcpy(&p_hal->syn, task->dec.syntax.data, sizeof(AvsdSyntax_t)); + FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec)); +__RETURN: + AVSD_HAL_TRACE("Out."); + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! + *********************************************************************** + * \brief h + * start hard + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_start(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + INP_CHECK(ret, NULL == decoder); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = p_hal->cfg->dev; + + wr_cfg.reg = p_hal->p_regs; + wr_cfg.size = AVSD_REGISTERS * sizeof(RK_U32); + wr_cfg.offset = 0; + + if (hal_avsd_debug & AVSD_HAL_DBG_ERROR) { + static RK_U32 frame_no = 0; + static FILE *fp = NULL; + RK_U32 i; + + if (!fp) + fp = fopen("regs.txt", "w+b"); + + if (fp) { + fprintf(fp, "frame %d\n", frame_no); + + for (i = 0; i < AVSD_REGISTERS; i++) + fprintf(fp, "reg[%03d]: %08x\n", i, p_hal->p_regs[i]); + + frame_no++; + + fflush(fp); + } + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = p_hal->p_regs; + rd_cfg.size = AVSD_REGISTERS * sizeof(RK_U32); + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + AVSD_HAL_TRACE("Out."); + + return ret; +} +/*! + *********************************************************************** + * \brief + * wait hard + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_wait(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + INP_CHECK(ret, NULL == decoder); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_hal->p_regs; + param.hard_err = (!((AvsdPlusRegs_t *)p_hal->p_regs)->sw01.dec_rdy_int) || + ((AvsdPlusRegs_t *)p_hal->p_regs)->sw01.dec_error_int; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + + AVSD_HAL_DBG(AVSD_HAL_DBG_WAIT, "first_field %d, irq 0x%08x, parse err %d, ref err %d\n", + p_hal->first_field, p_hal->p_regs[1], task->dec.flags.parse_err, task->dec.flags.ref_err); + + update_parameters(p_hal); + if (!p_hal->first_field && p_hal->syn.pp.pictureStructure == FIELDPICTURE && + ((!task->dec.flags.parse_err && !task->dec.flags.ref_err) || + p_hal->cfg->cfg->base.disable_error)) { + if (((AvsdPlusRegs_t *)p_hal->p_regs)->sw01.dec_rdy_int && + !((AvsdPlusRegs_t *)p_hal->p_regs)->sw01.dec_error_int) { + memset(&p_hal->p_regs[1], 0, sizeof(RK_U32)); + repeat_other_field(p_hal, task); + } else { + AVSD_HAL_DBG(AVSD_HAL_DBG_WAIT, "last field error, skip decoding"); + } + } + memset(&p_hal->p_regs[1], 0, sizeof(RK_U32)); + +__RETURN: + AVSD_HAL_TRACE("Out."); + + return ret; +} +/*! + *********************************************************************** + * \brief + * reset + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_reset(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + p_hal->first_field = 1; + p_hal->prev_pic_structure = 0; //!< field + + memset(p_hal->pic, 0, sizeof(p_hal->pic)); + p_hal->work_out = -1; + p_hal->work0 = -1; + p_hal->work1 = -1; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} +/*! + *********************************************************************** + * \brief + * flush + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_flush(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AVSD_HAL_TRACE("In."); + + (void)decoder; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} +/*! + *********************************************************************** + * \brief + * control + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_plus_control(void *decoder, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AVSD_HAL_TRACE("In."); + + (void)decoder; + (void)cmd_type; + (void)param; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} + +const MppHalApi hal_avsd_plus = { + .name = "avsd_plus", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVSPLUS, + .ctx_size = sizeof(AvsdHalCtx_t), + .flag = 0, + .init = hal_avsd_plus_init, + .deinit = hal_avsd_plus_deinit, + .reg_gen = hal_avsd_plus_gen_regs, + .start = hal_avsd_plus_start, + .wait = hal_avsd_plus_wait, + .reset = hal_avsd_plus_reset, + .flush = hal_avsd_plus_flush, + .control = hal_avsd_plus_control, + .client = VPU_CLIENT_AVSPLUS_DEC, + .soc_type = { + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_avsd_plus) diff --git a/mpp/hal/rkdec/avsd/hal_avsd_plus.h b/mpp/hal/rkdec/avsd/hal_avsd_plus.h new file mode 100644 index 000000000..878ad742c --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_plus.h @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVSD_PLUS_H +#define HAL_AVSD_PLUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_avsd_plus; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVSD_PLUS_H */ diff --git a/mpp/hal/rkdec/avsd/hal_avsd_plus_reg.h b/mpp/hal/rkdec/avsd/hal_avsd_plus_reg.h new file mode 100644 index 000000000..1f70f4b28 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_plus_reg.h @@ -0,0 +1,280 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVSD_REG_H +#define HAL_AVSD_REG_H + +#include "mpp_debug.h" +#include "mpp_device.h" + +#include "parser_api.h" +#include "avsd_syntax.h" + +#define AVSD_REGISTERS 60 + +typedef struct { + RK_U32 sw00; + struct { + RK_U32 dec_e : 1; + RK_U32 reserve0 : 3; + RK_U32 dec_irq_dis : 1; + RK_U32 dec_abort_e : 1; + RK_U32 reserve1 : 2; + RK_U32 dec_irq : 1; + RK_U32 reserve2 : 2; + RK_U32 dec_abort_int : 1; + RK_U32 dec_rdy_int : 1; + RK_U32 dec_bus_int : 1; + RK_U32 dec_buffer_int : 1; + RK_U32 reserve3 : 1; + RK_U32 dec_error_int : 1; + RK_U32 reserve4 : 1; + RK_U32 dec_timeout : 1; + RK_U32 reserve5 : 5; + RK_U32 dec_pic_inf : 1; + RK_U32 reserve6 : 7; + } sw01; + struct { + RK_U32 dec_max_burst : 5; + RK_U32 dec_scmd_dis : 1; + RK_U32 dec_adv_pre_dis : 1; + RK_U32 tiled_mode_lsb : 1; + RK_U32 dec_out_endian : 1; + RK_U32 dec_in_endian : 1; + RK_U32 dec_clk_gate_e : 1; + RK_U32 dec_latency : 6; + RK_U32 dec_out_tiled_e : 1; + RK_U32 dec_data_disc_e : 1; + RK_U32 dec_outswap32_e : 1; + RK_U32 dec_inswap32_e : 1; + RK_U32 dec_strendian_e : 1; + RK_U32 dec_strswap32_e : 1; + RK_U32 dec_timeout_e : 1; + RK_U32 dec_axi_rd_id : 8; + } sw02; + struct { + RK_U32 dec_axi_wr_id : 8; + RK_U32 dec_ahb_hlock_e : 1; + RK_U32 picord_count_e : 1; + RK_U32 reserve0 : 1; + RK_U32 reftopfirst_e : 1; + RK_U32 write_mvs_e : 1; + RK_U32 pic_fixed_quant : 1; + RK_U32 filtering_dis : 1; + RK_U32 dec_out_dis : 1; + RK_U32 ref_topfield_e : 1; + RK_U32 reserve1 : 1; + RK_U32 fwd_interlace_e : 1; + RK_U32 pic_topfiled_e : 1; + RK_U32 pic_inter_e : 1; + RK_U32 pic_b_e : 1; + RK_U32 pic_fieldmode_e : 1; + RK_U32 pic_interlace_e : 1; + RK_U32 reserve2 : 2; + RK_U32 skip_mode : 1; + RK_U32 rlc_mode_e : 1; + RK_U32 dec_mode : 4; + } sw03; + struct { + RK_U32 pic_refer_flag : 1; + RK_U32 reverse0 : 10; + RK_U32 pic_mb_height_p : 8; + RK_U32 mb_width_off : 4; + RK_U32 pic_mb_width : 9; + } sw04; + struct { + RK_U32 beta_offset : 5; + RK_U32 alpha_offset : 5; + RK_U32 reserve1 : 16; + RK_U32 strm_start_bit : 6; + } sw05; + struct { + RK_U32 stream_len : 24; + RK_U32 stream_len_ext : 1; + RK_U32 init_qp : 6; + RK_U32 start_code_e : 1; + } sw06; + struct { + RK_U32 reserve0 : 25; + RK_U32 avs_h_ext : 1; + RK_U32 reserve1 : 6; + } sw07; + RK_U32 sw08; + RK_U32 sw09; + RK_U32 sw10; + RK_U32 sw11; + struct { + RK_U32 rlc_vlc_base; + } sw12; + struct { + RK_U32 dec_out_base; + } sw13; + union { + RK_U32 refer0_base; + struct { + RK_U32 refer0_topc_e : 1; + RK_U32 refer0_field_e : 1; + }; + } sw14; + union { + RK_U32 refer1_base; + struct { + RK_U32 refer1_topc_e : 1; + RK_U32 refer1_field_e : 1; + }; + } sw15; + union { + RK_U32 refer2_base; + struct { + RK_U32 refer2_topc_e : 1; + RK_U32 refer2_field_e : 1; + }; + } sw16; + union { + RK_U32 refer3_base; + struct { + RK_U32 refer3_topc_e : 1; + RK_U32 refer3_field_e : 1; + }; + } sw17; + struct { + RK_U32 prev_anc_type : 1; + RK_U32 reverse0 : 31; + } sw18; + RK_U32 sw19_27[9]; + struct { + RK_U32 ref_invd_cur_0 : 16; + RK_U32 ref_invd_cur_1 : 16; + } sw28; + struct { + RK_U32 ref_invd_cur_2 : 16; + RK_U32 ref_invd_cur_3 : 16; + } sw29; + struct { + RK_U32 ref_dist_cur_0 : 16; + RK_U32 ref_dist_cur_1 : 16; + } sw30; + struct { + RK_U32 ref_dist_cur_2 : 16; + RK_U32 ref_dist_cur_3 : 16; + } sw31; + struct { + RK_U32 ref_invd_col_0 : 16; + RK_U32 ref_invd_col_1 : 16; + } sw32; + struct { + RK_U32 ref_invd_col_2 : 16; + RK_U32 ref_invd_col_3 : 16; + } sw33; + struct { + RK_U32 reserve0 : 2; + RK_U32 pred_bc_tap_1_1 : 10; + RK_U32 pred_bc_tap_1_0 : 10; + RK_U32 pred_bc_tap_0_3 : 10; + } sw34; + struct { + RK_U32 reserve0 : 12; + RK_U32 pred_bc_tap_1_3 : 10; + RK_U32 pred_bc_tap_1_2 : 10; + } sw35; + RK_U32 sw36_40[5]; + struct { + RK_U32 dir_mv_base : 32; + } sw41; + struct { + RK_U32 ref_delta_cur_3 : 3; + RK_U32 ref_delta_cur_2 : 3; + RK_U32 ref_delta_cur_1 : 3; + RK_U32 ref_delta_cur_0 : 3; + RK_U32 ref_delta_col_3 : 3; + RK_U32 ref_delta_col_2 : 3; + RK_U32 ref_delta_col_1 : 3; + RK_U32 ref_delta_col_0 : 3; + RK_U32 weight_qp_1 : 8; + } sw42; + struct { + RK_U32 weight_qp_5 : 8; + RK_U32 weight_qp_4 : 8; + RK_U32 weight_qp_3 : 8; + RK_U32 weight_qp_2 : 8; + } sw43; + struct { + RK_U32 weight_qp_0 : 8; + RK_U32 qp_delta_cr : 6; + RK_U32 qp_delta_cb : 6; + RK_U32 pb_field_enhance_e : 1; + RK_U32 no_fwd_ref_e : 1; + RK_U32 avs_aec_e : 1; + RK_U32 weight_qp_model : 2; + RK_U32 weight_qp_e : 1; + RK_U32 dec_avsp_ena : 1; + RK_U32 reserve0 : 5; + } sw44; + struct { + RK_U32 dir_mv_base2 : 32; + } sw45; + RK_U32 sw46; + RK_U32 sw47; + struct { + RK_U32 reserve0 : 14; + RK_U32 startmb_y : 9; + RK_U32 startmb_x : 9; + } sw48; + struct { + RK_U32 reserve0 : 2; + RK_U32 pred_bc_tap_0_2 : 10; + RK_U32 pred_bc_tap_0_1 : 10; + RK_U32 pred_bc_tap_0_0 : 10; + } sw49; + RK_U32 sw50; + struct { + RK_U32 refbu_y_offset : 9; + RK_U32 reserve0 : 3; + RK_U32 refbu_fparmod_e : 1; + RK_U32 refbu_eval_e : 1; + RK_U32 refbu_picid : 5; + RK_U32 refbu_thr : 12; + RK_U32 refbu_e : 1; + } sw51; + struct { + RK_U32 refbu_intra_sum : 16; + RK_U32 refbu_hit_sum : 16; + } sw52; + struct { + RK_U32 refbu_y_mv_sum : 22; + RK_U32 reserve0 : 10; + } sw53; + RK_U32 sw54; + struct { + RK_U32 apf_threshold : 14; + RK_U32 refbu2_picid : 5; + RK_U32 refbu2_thr : 12; + RK_U32 refbu2_buf_e : 1; + } sw55; + + struct { + RK_U32 refbu_bot_sum : 16; + RK_U32 refbu_top_sum : 16; + } sw56; + RK_U32 sw57; + struct { + RK_U32 reserve0 : 31; + RK_U32 serv_merge_dis : 1; + } sw58; + RK_U32 sw59; +} AvsdPlusRegs_t; + +#endif /* HAL_AVSD_PLUS_REG_H */ diff --git a/mpp/hal/rkdec/avsd/hal_avsd_vdpu1.c b/mpp/hal/rkdec/avsd/hal_avsd_vdpu1.c new file mode 100644 index 000000000..7bfa7f010 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_vdpu1.c @@ -0,0 +1,770 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_avsd_vdpu1" + +#include + +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_mem.h" +#include "mpp_device.h" +#include "mpp_dec_cb_param.h" + +#include "hal_avsd_base.h" +#include "hal_avsd_vdpu1.h" +#include "hal_avsd_vdpu1_reg.h" + +static MPP_RET hal_avsd_vdpu1_start(void *decoder, HalTaskInfo *task); +static MPP_RET hal_avsd_vdpu1_wait(void *decoder, HalTaskInfo *task); +static MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal) +{ + AvsdVdpu1Regs_t *p_regs = (AvsdVdpu1Regs_t *)p_hal->p_regs; + + p_regs->sw02.dec_out_endian = 1; + p_regs->sw02.dec_in_endian = 0; + p_regs->sw02.dec_strendian_e = 1; + p_regs->sw02.dec_max_burst = 16; + p_regs->sw02.dec_scmd_dis = 0; + + p_regs->sw02.dec_adv_pre_dis = 0; + p_regs->sw55.apf_threshold = 8; + p_regs->sw02.dec_latency = 0; + + p_regs->sw02.dec_data_disc_e = 0; + p_regs->sw02.dec_outswap32_e = 1; + p_regs->sw02.dec_inswap32_e = 1; + p_regs->sw02.dec_strswap32_e = 1; + + p_regs->sw02.dec_timeout_e = 0; + p_regs->sw02.dec_clk_gate_e = 1; + p_regs->sw01.dec_irq_dis = 0; + + p_regs->sw02.dec_axi_rd_id = 0xFF; + p_regs->sw03.dec_axi_wr_id = 0; + + p_regs->sw49.pred_bc_tap_0_0 = 0x3FF; + p_regs->sw49.pred_bc_tap_0_1 = 5; + p_regs->sw49.pred_bc_tap_0_2 = 5; + p_regs->sw34.pred_bc_tap_0_3 = 0x3FF; + p_regs->sw34.pred_bc_tap_1_0 = 1; + p_regs->sw34.pred_bc_tap_1_1 = 7; + p_regs->sw35.pred_bc_tap_1_2 = 7; + p_regs->sw35.pred_bc_tap_1_3 = 1; + + p_regs->sw02.tiled_mode_lsb = 0; + + return MPP_OK; +} + +static MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AvsdSyntax_t *p_syn = &p_hal->syn; + AvsdVdpu1Regs_t *p_regs = (AvsdVdpu1Regs_t *)p_hal->p_regs; + MppDev dev = p_hal->cfg->dev; + + set_defalut_parameters(p_hal); + + p_regs->sw02.dec_timeout_e = 1; + p_regs->sw02.dec_clk_gate_e = 1; + p_regs->sw01.dec_irq_dis = 0; + p_regs->sw03.rlc_mode_e = 0; + + //!< set wrok_out pic info + if (p_hal->work_out < 0) { + p_hal->work_out = get_queue_pic(p_hal); + if (p_hal->work_out < 0) { + ret = MPP_NOK; + mpp_err_f("cannot get a pic_info buffer.\n"); + goto __FAILED; + } + } + { + AvsdHalPic_t *p_work_out = &p_hal->pic[p_hal->work_out]; + + p_work_out->slot_idx = task->output; + p_work_out->pic_code_type = p_syn->pp.picCodingType; + p_work_out->picture_distance = p_syn->pp.pictureDistance; + } + //!< set register + p_regs->sw04.pic_mb_width = (p_syn->pp.horizontalSize + 15) >> 4; + p_regs->sw03.dec_mode = 11; //!< DEC_MODE_AVS + + if (p_syn->pp.pictureStructure == FRAMEPICTURE) { + p_regs->sw03.pic_interlace_e = 0; + p_regs->sw03.pic_fieldmode_e = 0; + p_regs->sw03.pic_topfiled_e = 0; + } else { + p_regs->sw03.pic_interlace_e = 1; + p_regs->sw03.pic_fieldmode_e = 1; + p_regs->sw03.pic_topfiled_e = p_hal->first_field; + } + + p_regs->sw04.pic_mb_height_p = (p_syn->pp.verticalSize + 15) >> 4; + //p_regs->sw07.avs_h_ext = (p_syn->pp.verticalSize + 15) >> 12; + + if (p_syn->pp.picCodingType == BFRAME) { + p_regs->sw03.pic_b_e = 1; + } else { + p_regs->sw03.pic_b_e = 0; + } + p_regs->sw03.pic_inter_e = (p_syn->pp.picCodingType != IFRAME) ? 1 : 0; + + mpp_log("data_offset %x\n", p_hal->data_offset); + p_regs->sw05.strm_start_bit = 8 * (p_hal->data_offset & 0x7); + p_hal->data_offset = (p_hal->data_offset & ~0x7); + p_regs->sw12.rlc_vlc_base = get_packet_fd(p_hal, task->input); + mpp_dev_set_reg_offset(dev, 12, p_hal->data_offset); + p_regs->sw06.stream_len = p_syn->bitstream_size - p_hal->data_offset; + p_regs->sw03.pic_fixed_quant = p_syn->pp.fixedPictureQp; + p_regs->sw06.init_qp = p_syn->pp.pictureQp; + + p_regs->sw13.dec_out_base = get_frame_fd(p_hal, task->output); + if (p_syn->pp.pictureStructure == FIELDPICTURE && !p_hal->first_field) { + //!< start of bottom field line + mpp_dev_set_reg_offset(dev, 13, p_syn->pp.horizontalSize); + } + { + RK_S32 tmp_fwd = -1; + RK_S32 refer0 = -1; + RK_S32 refer1 = -1; + + tmp_fwd = (p_hal->work1 < 0) ? p_hal->work0 : p_hal->work1; + tmp_fwd = (tmp_fwd < 0) ? p_hal->work_out : tmp_fwd; + + refer0 = (task->refer[0] < 0) ? task->output : task->refer[0]; + refer1 = (task->refer[1] < 0) ? refer0 : task->refer[1]; + if (!p_hal->first_field + && p_syn->pp.pictureStructure == FIELDPICTURE + && p_syn->pp.picCodingType != BFRAME) { + p_regs->sw14.refer0_base = get_frame_fd(p_hal, task->output); + p_regs->sw15.refer1_base = get_frame_fd(p_hal, refer0); + p_regs->sw16.refer2_base = get_frame_fd(p_hal, refer0); + p_regs->sw17.refer3_base = get_frame_fd(p_hal, refer1); + } else { + p_regs->sw14.refer0_base = get_frame_fd(p_hal, refer0); + p_regs->sw15.refer1_base = get_frame_fd(p_hal, refer0); + p_regs->sw16.refer2_base = get_frame_fd(p_hal, refer1); + p_regs->sw17.refer3_base = get_frame_fd(p_hal, refer1); + } + } + //!< block distances + if (p_syn->pp.pictureStructure == FRAMEPICTURE) { + if (p_syn->pp.picCodingType == BFRAME) { + RK_S32 tmp = 0; + //!< current to future anchor + if (p_hal->work0 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_syn->pp.pictureDistance + 512) & 0x1FF; + } + //!< prevent division by zero + if (!tmp) tmp = 2; + p_regs->sw31.ref_dist_cur_2 = tmp; + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_2 = 512 / tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + + //!< current to past anchor + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + p_regs->sw30.ref_dist_cur_0 = tmp; + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_0 = 512 / tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + //!< future anchor to past anchor + if (p_hal->work0 >= 0 && p_hal->work1 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + tmp = 16384 / tmp; + p_regs->sw32.ref_invd_col_0 = tmp; + p_regs->sw32.ref_invd_col_1 = tmp; + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + tmp = 16384 / tmp; + p_regs->sw33.ref_invd_col_2 = tmp; + p_regs->sw33.ref_invd_col_3 = tmp; + } else { + RK_S32 tmp = 0; + //!< current to past anchor + if (p_hal->work0 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF; + } + if (!tmp) tmp = 2; + p_regs->sw30.ref_dist_cur_0 = tmp; + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_0 = 512 / tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + //!< current to previous past anchor + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + //!< this will become "future to previous past" for next B + p_hal->future2prev_past_dist = tmp; + + p_regs->sw31.ref_dist_cur_2 = tmp; + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_2 = 512 / tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + + p_regs->sw32.ref_invd_col_0 = 0; + p_regs->sw32.ref_invd_col_1 = 0; + p_regs->sw33.ref_invd_col_2 = 0; + p_regs->sw33.ref_invd_col_3 = 0; + } + } else { + //!< field interlaced + if (p_syn->pp.picCodingType == BFRAME) { + RK_S32 tmp = 0; + //!< block distances + if (p_hal->work0 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_syn->pp.pictureDistance + 512) & 0x1FF; + } + //!< prevent division by zero + if (!tmp) tmp = 2; + + if (p_hal->first_field) { + p_regs->sw31.ref_dist_cur_2 = tmp; + p_regs->sw31.ref_dist_cur_3 = tmp + 1; + p_regs->sw29.ref_invd_cur_2 = 512 / tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / (tmp + 1); + } else { + p_regs->sw31.ref_dist_cur_2 = tmp - 1; + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_2 = 512 / (tmp - 1); + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + } + + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + if (p_hal->first_field) { + p_regs->sw30.ref_dist_cur_0 = (tmp - 1); + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_0 = 512 / (tmp - 1); + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + } else { + p_regs->sw30.ref_dist_cur_0 = tmp; + p_regs->sw30.ref_dist_cur_1 = tmp + 1; + p_regs->sw28.ref_invd_cur_0 = 512 / tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / (tmp + 1); + } + + if (p_hal->work0 >= 0 && p_hal->work1 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + + if (p_syn->pp.pbFieldEnhancedFlag && !p_hal->first_field) { + //!< in this case, BlockDistanceRef is different with before, the mvRef points to top field + p_regs->sw32.ref_invd_col_0 = 16384 / (tmp - 1); + p_regs->sw32.ref_invd_col_1 = 16384 / tmp; + + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + + p_regs->sw33.ref_invd_col_2 = 16384 / (tmp - 1); + p_regs->sw33.ref_invd_col_3 = 16384 / tmp; + } else { + if (p_hal->first_field) { + p_regs->sw32.ref_invd_col_0 = 16384 / (tmp - 1); + p_regs->sw32.ref_invd_col_1 = 16384 / tmp; + } else { + p_regs->sw32.ref_invd_col_0 = 16384; + p_regs->sw32.ref_invd_col_1 = 16384 / tmp; + p_regs->sw33.ref_invd_col_2 = 16384 / (tmp + 1); + } + + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + + if (p_hal->first_field) { + p_regs->sw33.ref_invd_col_2 = 16384 / (tmp - 1); + p_regs->sw33.ref_invd_col_3 = 16384 / tmp; + } else { + p_regs->sw33.ref_invd_col_3 = 16384 / tmp; + } + } + } else { + RK_S32 tmp = 0; + if (p_hal->work0 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF; + } + if (!tmp) tmp = 2; + + if (!p_hal->first_field) { + p_regs->sw30.ref_dist_cur_0 = 1; + p_regs->sw31.ref_dist_cur_2 = tmp + 1; + + p_regs->sw28.ref_invd_cur_0 = 512; + p_regs->sw29.ref_invd_cur_2 = 512 / (tmp + 1); + } else { + p_regs->sw30.ref_dist_cur_0 = tmp - 1; + p_regs->sw28.ref_invd_cur_0 = 512 / (tmp - 1); + } + p_regs->sw30.ref_dist_cur_1 = tmp; + p_regs->sw28.ref_invd_cur_1 = 512 / tmp; + + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + //!< this will become "future to previous past" for next B + p_hal->future2prev_past_dist = tmp; + if (p_hal->first_field) { + p_regs->sw31.ref_dist_cur_2 = tmp - 1; + p_regs->sw31.ref_dist_cur_3 = tmp; + + p_regs->sw29.ref_invd_cur_2 = 512 / (tmp - 1); + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + } else { + p_regs->sw31.ref_dist_cur_3 = tmp; + p_regs->sw29.ref_invd_cur_3 = 512 / tmp; + } + + p_regs->sw32.ref_invd_col_0 = 0; + p_regs->sw32.ref_invd_col_1 = 0; + p_regs->sw33.ref_invd_col_2 = 0; + p_regs->sw33.ref_invd_col_3 = 0; + } + } + + p_regs->sw48.startmb_x = 0; + p_regs->sw48.startmb_y = 0; + + p_regs->sw03.filtering_dis = p_syn->pp.loopFilterDisable; + p_regs->sw05.alpha_offset = p_syn->pp.alphaOffset; + p_regs->sw05.beta_offset = p_syn->pp.betaOffset; + p_regs->sw03.skip_mode = p_syn->pp.skipModeFlag; + p_regs->sw04.pic_refer_flag = p_syn->pp.pictureReferenceFlag; + + if (p_syn->pp.picCodingType == PFRAME + || (p_syn->pp.picCodingType == IFRAME && !p_hal->first_field)) { + p_regs->sw03.write_mvs_e = 1; + } else { + p_regs->sw03.write_mvs_e = 0; + } + //!< set mv base + p_regs->sw41.dir_mv_base = mpp_buffer_get_fd(p_hal->mv_buf); + if (p_hal->first_field || + (p_syn->pp.picCodingType == BFRAME && p_hal->prev_pic_structure)) { + } else { + RK_U32 frame_width = 0, frame_height = 0, offset = 0; + frame_width = (p_syn->pp.horizontalSize + 15) >> 4; + if (p_syn->pp.progressiveFrame) + frame_height = (p_syn->pp.verticalSize + 15) >> 4; + else + frame_height = 2 * ((p_syn->pp.verticalSize + 31) >> 5); + offset = MPP_ALIGN(frame_width * frame_height / 2, 2) * 16; + mpp_dev_set_reg_offset(dev, 41, offset); + } + { + RK_U32 pic_type = 0; + RK_U32 prev_anc_type = 0; + if (p_hal->work0 >= 0) { + pic_type = p_hal->pic[p_hal->work0].pic_type; + } + prev_anc_type = !pic_type || (!p_hal->first_field && !p_hal->prev_pic_structure); + p_regs->sw18.prev_anc_type = prev_anc_type; + } + //!< b-picture needs to know if future reference is field or frame coded + // p_regs->sw16.refer2_field_e = (!p_hal->prev_pic_structure) ? 1 : 0; + // p_regs->sw17.refer3_field_e = (!p_hal->prev_pic_structure) ? 1 : 0; + if (!p_hal->prev_pic_structure) { + mpp_dev_set_reg_offset(dev, 16, 2); + mpp_dev_set_reg_offset(dev, 17, 3); + } + + p_regs->sw03.dec_out_dis = 0; + p_regs->sw01.dec_e = 1; + + return MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET update_parameters(AvsdHalCtx_t *p_hal) +{ + AvsdSyntax_t *p_syn = &p_hal->syn; + + if (p_syn->pp.pictureStructure == FRAMEPICTURE || !p_hal->first_field) { + p_hal->first_field = 1; + if (p_syn->pp.picCodingType != BFRAME) { + RK_S32 temp = p_hal->work1; + + p_hal->work1 = p_hal->work0; + p_hal->work0 = p_hal->work_out; + + if (p_hal->work_out >= 0) + p_hal->pic[p_hal->work_out].pic_type = p_syn->pp.picCodingType == IFRAME; + p_hal->work_out = temp; + p_hal->prev_pic_structure = p_syn->pp.pictureStructure; + } + p_hal->prev_pic_code_type = p_syn->pp.picCodingType; + } else { + p_hal->first_field = 0; + } + + return MPP_OK; +} + +static MPP_RET repeat_other_field(AvsdHalCtx_t *p_hal, HalTaskInfo *task) +{ + RK_U8 i = 0; + RK_U8 *pdata = NULL; + MppBuffer mbuffer = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdVdpu1Regs_t *p_regs = (AvsdVdpu1Regs_t *)p_hal->p_regs; + + //!< re-find start code and calculate offset + p_hal->data_offset = p_regs->sw12.rlc_vlc_base >> 10; + p_hal->data_offset += p_hal->syn.bitstream_offset; + p_hal->data_offset -= MPP_MIN(p_hal->data_offset, 8); + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + pdata = (RK_U8 *)mpp_buffer_get_ptr(mbuffer) + p_hal->data_offset; + + while (i < 16) { + if (pdata[i] == 0 && pdata[i + 1] == 0 && pdata[i + 2] == 1) { + p_hal->data_offset += i; + break; + } + i++; + } + AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no=%d, i=%d, offset=%d\n", + p_hal->frame_no, i, p_hal->data_offset); + //!< re-generate register + FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec)); + hal_avsd_vdpu1_start((void *)p_hal, task); + hal_avsd_vdpu1_wait((void *)p_hal, task); + + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief +* init +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_init(void *decoder, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 buf_size = 0; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + mpp_env_get_u32("hal_avsd_debug", &hal_avsd_debug, 0); + + AVSD_HAL_TRACE("AVS_vdpu1 In."); + + p_hal->cfg = cfg; + + buf_size = (1920 * 1088) * 2; + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, &p_hal->mv_buf, buf_size)); + + p_hal->p_regs = mpp_calloc_size(RK_U32, sizeof(AvsdVdpu1Regs_t)); + MEM_CHECK(ret, p_hal->p_regs); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + p_hal->regs_num = 60; + //!< initial for control + p_hal->first_field = 1; + p_hal->prev_pic_structure = 0; //!< field + + memset(p_hal->pic, 0, sizeof(p_hal->pic)); + p_hal->work_out = -1; + p_hal->work0 = -1; + p_hal->work1 = -1; + + AVSD_HAL_TRACE("Out."); + (void)cfg; + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief +* deinit +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_deinit(void *decoder) +{ + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + if (p_hal->mv_buf) { + mpp_buffer_put(p_hal->mv_buf); + p_hal->mv_buf = NULL; + } + MPP_FREE(p_hal->p_regs); + + AVSD_HAL_TRACE("Out."); + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* generate register +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_gen_regs(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + p_hal->data_offset = p_hal->syn.bitstream_offset; + + memcpy(&p_hal->syn, task->dec.syntax.data, sizeof(AvsdSyntax_t)); + FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec)); +__RETURN: + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief h +* start hard +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_start(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = 101 * sizeof(RK_U32); + MppDev dev = p_hal->cfg->dev; + + wr_cfg.reg = p_hal->p_regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = p_hal->p_regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + AVSD_HAL_TRACE("Out."); + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* wait hard +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_wait(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_hal->p_regs; + + if (!((AvsdVdpu1Regs_t *)p_hal->p_regs)->sw01.dec_rdy_int) { + param.hard_err = 1; + } else + param.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + AVSD_HAL_DBG(AVSD_HAL_DBG_WAIT, "reg[1]=%08x, ref=%d, dpberr=%d, harderr=%d\n", + p_hal->p_regs[1], task->dec.flags.used_for_ref, task->dec.flags.ref_err, param.hard_err); + } + update_parameters(p_hal); + memset(&p_hal->p_regs[1], 0, sizeof(RK_U32)); + if (!p_hal->first_field && p_hal->syn.pp.pictureStructure == FIELDPICTURE && + ((!task->dec.flags.parse_err && !task->dec.flags.ref_err) || + p_hal->cfg->cfg->base.disable_error)) { + repeat_other_field(p_hal, task); + } + p_hal->frame_no++; + + AVSD_HAL_TRACE("Out."); + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_reset(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + p_hal->first_field = 1; + p_hal->prev_pic_structure = 0; //!< field + + memset(p_hal->pic, 0, sizeof(p_hal->pic)); + p_hal->work_out = -1; + p_hal->work0 = -1; + p_hal->work1 = -1; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_flush(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AVSD_HAL_TRACE("In."); + + (void)decoder; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* control +*********************************************************************** +*/ +//extern "C" +static MPP_RET hal_avsd_vdpu1_control(void *decoder, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AVSD_HAL_TRACE("In."); + + (void)decoder; + (void)cmd_type; + (void)param; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} + +const MppHalApi hal_avsd_vdpu1 = { + .name = "avsd_vdpu1", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVS, + .ctx_size = sizeof(AvsdHalCtx_t), + .flag = 0, + .init = hal_avsd_vdpu1_init, + .deinit = hal_avsd_vdpu1_deinit, + .reg_gen = hal_avsd_vdpu1_gen_regs, + .start = hal_avsd_vdpu1_start, + .wait = hal_avsd_vdpu1_wait, + .reset = hal_avsd_vdpu1_reset, + .flush = hal_avsd_vdpu1_flush, + .control = hal_avsd_vdpu1_control, + .client = VPU_CLIENT_VDPU1, + .soc_type = { + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_avsd_vdpu1) diff --git a/mpp/hal/rkdec/avsd/hal_avsd_vdpu1.h b/mpp/hal/rkdec/avsd/hal_avsd_vdpu1.h new file mode 100644 index 000000000..91cf21c47 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_vdpu1.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVSD_VDPU1_H +#define HAL_AVSD_VDPU1_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_avsd_vdpu1; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVSD_VDPU1_H */ diff --git a/mpp/hal/rkdec/avsd/hal_avsd_vdpu1_reg.h b/mpp/hal/rkdec/avsd/hal_avsd_vdpu1_reg.h new file mode 100644 index 000000000..3c27584a5 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_vdpu1_reg.h @@ -0,0 +1,247 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVSD_VDPU1_REG_H +#define HAL_AVSD_VDPU1_REG_H + + +typedef struct { + RK_U32 sw00; + struct { + RK_U32 dec_e : 1; + RK_U32 reserve0 : 3; + RK_U32 dec_irq_dis : 1; + RK_U32 dec_abort_e : 1; + RK_U32 reserve1 : 2; + RK_U32 dec_irq : 1; + RK_U32 reserve2 : 2; + RK_U32 dec_abort_int : 1; + RK_U32 dec_rdy_int : 1; + RK_U32 dec_bus_int : 1; + RK_U32 dec_buffer_int : 1; + RK_U32 reserve3 : 1; + RK_U32 dec_error_int : 1; + RK_U32 reserve4 : 1; + RK_U32 dec_timeout : 1; + RK_U32 reserve5 : 5; + RK_U32 dec_pic_inf : 1; + RK_U32 reserve6 : 7; + } sw01; + union { + struct { + RK_U32 dec_max_burst : 5; + RK_U32 dec_scmd_dis : 1; + RK_U32 dec_adv_pre_dis : 1; + RK_U32 tiled_mode_lsb : 1; + RK_U32 dec_out_endian : 1; + RK_U32 dec_in_endian : 1; + RK_U32 dec_clk_gate_e : 1; + RK_U32 dec_latency : 6; + RK_U32 dec_out_tiled_e : 1; + RK_U32 dec_data_disc_e : 1; + RK_U32 dec_outswap32_e : 1; + RK_U32 dec_inswap32_e : 1; + RK_U32 dec_strendian_e : 1; + RK_U32 dec_strswap32_e : 1; + RK_U32 dec_timeout_e : 1; + RK_U32 dec_axi_rd_id : 8; + }; + struct { + RK_U32 reserve0 : 5; + RK_U32 priority_mode : 3; + RK_U32 reserve1 : 9; + RK_U32 tiled_mode_msb : 1; + RK_U32 dec_2chan_dis : 1; + RK_U32 reserve2 : 13; + }; + } sw02; + struct { + RK_U32 dec_axi_wr_id : 8; + RK_U32 dec_ahb_hlock_e : 1; + RK_U32 picord_count_e : 1; + RK_U32 reserve0 : 1; + RK_U32 reftopfirst_e : 1; + RK_U32 write_mvs_e : 1; + RK_U32 pic_fixed_quant : 1; + RK_U32 filtering_dis : 1; + RK_U32 dec_out_dis : 1; + RK_U32 ref_topfield_e : 1; + RK_U32 reserve1 : 1; + RK_U32 fwd_interlace_e : 1; + RK_U32 pic_topfiled_e : 1; + RK_U32 pic_inter_e : 1; + RK_U32 pic_b_e : 1; + RK_U32 pic_fieldmode_e : 1; + RK_U32 pic_interlace_e : 1; + RK_U32 reserve2 : 2; + RK_U32 skip_mode : 1; + RK_U32 rlc_mode_e : 1; + RK_U32 dec_mode : 4; + } sw03; + struct { + RK_U32 pic_refer_flag : 1; + RK_U32 reverse0 : 10; + RK_U32 pic_mb_height_p : 8; + RK_U32 mb_width_off : 4; + RK_U32 pic_mb_width : 9; + } sw04; + union { + struct { + RK_U32 fieldpic_flag_e : 1; + RK_S32 reserve0 : 31; + }; + struct { + RK_U32 beta_offset : 5; + RK_U32 alpha_offset : 5; + RK_U32 reserve1 : 16; + RK_U32 strm_start_bit : 6; + }; + } sw05; + struct { + RK_U32 stream_len : 24; + RK_U32 stream_len_ext : 1; + RK_U32 init_qp : 6; + RK_U32 start_code_e : 1; + } sw06; + RK_U32 sw07_11[5]; + struct { + RK_U32 rlc_vlc_base : 32; + } sw12; + struct { + RK_U32 dec_out_base : 32; + } sw13; + union { + RK_U32 refer0_base : 32; + struct { //!< left move 10bit + RK_U32 reserve0 : 10; + RK_U32 refer0_topc_e : 1; + RK_U32 refer0_field_e : 1; + RK_U32 reserve1 : 20; + }; + } sw14; + union { + struct { + RK_U32 refer1_base : 32; + }; + struct { //!< left move 10bit + RK_U32 reserve0 : 10; + RK_U32 refer1_topc_e : 1; + RK_U32 refer1_field_e : 1; + RK_U32 reserve1 : 20; + }; + } sw15; + union { + struct { + RK_U32 refer2_base : 32; + }; + struct { //!< left move 10bit + RK_U32 reserve0 : 10; + RK_U32 refer2_topc_e : 1; + RK_U32 refer2_field_e : 1; + RK_U32 reserve1 : 20; + }; + } sw16; + union { + struct { + RK_U32 refer3_base : 32; + }; + struct { //!< left move 10bit + RK_U32 reserve0 : 10; + RK_U32 refer3_topc_e : 1; + RK_U32 refer3_field_e : 1; + RK_U32 reserve1 : 20; + }; + } sw17; + struct { + RK_U32 prev_anc_type : 1; + RK_U32 reverse0 : 31; + } sw18; + RK_U32 sw19_27[9]; + struct { + RK_U32 ref_invd_cur_0 : 16; + RK_U32 ref_invd_cur_1 : 16; + } sw28; + struct { + RK_U32 ref_invd_cur_2 : 16; + RK_U32 ref_invd_cur_3 : 16; + } sw29; + struct { + RK_U32 ref_dist_cur_0 : 16; + RK_U32 ref_dist_cur_1 : 16; + } sw30; + struct { + RK_U32 ref_dist_cur_2 : 16; + RK_U32 ref_dist_cur_3 : 16; + } sw31; + struct { + RK_U32 ref_invd_col_0 : 16; + RK_U32 ref_invd_col_1 : 16; + } sw32; + struct { + RK_U32 ref_invd_col_2 : 16; + RK_U32 ref_invd_col_3 : 16; + } sw33; + struct { + RK_U32 reserve0 : 2; + RK_U32 pred_bc_tap_1_1 : 10; + RK_U32 pred_bc_tap_1_0 : 10; + RK_U32 pred_bc_tap_0_3 : 10; + } sw34; + struct { + RK_U32 reserve0 : 12; + RK_U32 pred_bc_tap_1_3 : 10; + RK_U32 pred_bc_tap_1_2 : 10; + } sw35; + RK_U32 sw36_40[5]; + struct { + RK_U32 dir_mv_base : 32; + } sw41; + RK_U32 sw42_47[6]; + struct { + RK_U32 reserve0 : 14; + RK_U32 startmb_y : 9; + RK_U32 startmb_x : 9; + } sw48; + struct { + RK_U32 reserve0 : 2; + RK_U32 pred_bc_tap_0_2 : 10; + RK_U32 pred_bc_tap_0_1 : 10; + RK_U32 pred_bc_tap_0_0 : 10; + } sw49; + RK_U32 sw50_54[5]; + struct { + RK_U32 apf_threshold : 14; + RK_U32 refbu2_picid : 5; + RK_U32 refbu2_thr : 12; + RK_U32 refbu2_buf_e : 1; + } sw55; + RK_U32 sw56; + struct { + RK_U32 stream_len_ext : 1; + RK_U32 inter_dblspeed : 1; + RK_U32 intra_dblspeed : 1; + RK_U32 intra_dbl3t : 1; + RK_U32 bus_pos_sel : 1; + RK_U32 axi_sel : 1; + RK_U32 pref_sigchan : 1; + RK_U32 cache_en : 1; + RK_U32 reserve : 24; + } sw57; + RK_U32 sw58_59[2]; + RK_U32 resever[40]; +} AvsdVdpu1Regs_t; + +#endif /* HAL_AVSD_VDPU1_REG_H */ diff --git a/mpp/hal/rkdec/avsd/hal_avsd_vdpu2.c b/mpp/hal/rkdec/avsd/hal_avsd_vdpu2.c new file mode 100644 index 000000000..20b4ec791 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_vdpu2.c @@ -0,0 +1,779 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_avsd_vdpu2" + +#include + +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_mem.h" +#include "mpp_device.h" +#include "mpp_dec_cb_param.h" + +#include "hal_avsd_base.h" +#include "hal_avsd_vdpu2.h" +#include "hal_avsd_vdpu2_reg.h" + +static MPP_RET hal_avsd_vdpu2_start(void *decoder, HalTaskInfo *task); +static MPP_RET hal_avsd_vdpu2_wait(void *decoder, HalTaskInfo *task); + +static MPP_RET set_defalut_parameters(AvsdHalCtx_t *p_hal) +{ + AvsdVdpu2Regs_t *p_regs = (AvsdVdpu2Regs_t *)p_hal->p_regs; + + p_regs->sw54.dec_out_endian = 1; + p_regs->sw54.dec_in_endian = 0; + p_regs->sw54.dec_strendian_e = 1; + p_regs->sw56.dec_max_burlen = 16; + p_regs->sw50.dec_ascmd0_dis = 0; + + p_regs->sw50.adv_pref_dis = 0; + p_regs->sw52.adv_pref_thrd = 8; + p_regs->sw50.adtion_latency = 0; + + p_regs->sw56.dec_data_discd_en = 0; + p_regs->sw54.dec_out_wordsp = 1; + p_regs->sw54.dec_in_wordsp = 1; + p_regs->sw54.dec_strm_wordsp = 1; + p_regs->sw55.timeout_det_sts = 0; + p_regs->sw57.dec_clkgate_en = 1; + p_regs->sw55.dec_irq_dis = 0; + + p_regs->sw56.dec_axi_id_rd = 0xFF; + p_regs->sw56.dec_axi_id_wr = 0; + + p_regs->sw59.pred_bc_tap_0_0 = 0x3FF; + p_regs->sw59.pred_bc_tap_0_1 = 5; + p_regs->sw59.pred_bc_tap_0_2 = 5; + p_regs->sw153.pred_bc_tap_0_3 = 0x3FF; + p_regs->sw153.pred_bc_tap_1_0 = 1; + p_regs->sw153.pred_bc_tap_1_1 = 7; + p_regs->sw154.pred_bc_tap_1_2 = 7; + p_regs->sw154.pred_bc_tap_1_3 = 1; + + p_regs->sw50.dec_tiled_lsb = 0; + + return MPP_OK; +} + +static MPP_RET set_regs_parameters(AvsdHalCtx_t *p_hal, HalDecTask *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AvsdSyntax_t *p_syn = &p_hal->syn; + AvsdVdpu2Regs_t *p_regs = (AvsdVdpu2Regs_t *)p_hal->p_regs; + MppDev dev = p_hal->cfg->dev; + + set_defalut_parameters(p_hal); + + p_regs->sw57.timeout_sts_en = 1; + p_regs->sw57.dec_clkgate_en = 1; + p_regs->sw55.dec_irq_dis = 0; + + //!< set wrok_out pic info + if (p_hal->work_out < 0) { + p_hal->work_out = get_queue_pic(p_hal); + if (p_hal->work_out < 0) { + ret = MPP_NOK; + mpp_err_f("cannot get a pic_info buffer.\n"); + goto __FAILED; + } + } + { + AvsdHalPic_t *p_work_out = &p_hal->pic[p_hal->work_out]; + + p_work_out->slot_idx = task->output; + p_work_out->pic_code_type = p_syn->pp.picCodingType; + p_work_out->picture_distance = p_syn->pp.pictureDistance; + } + //!< set register + p_regs->sw120.pic_mb_width = (p_syn->pp.horizontalSize + 15) >> 4; + p_regs->sw53.dec_fmt_sel = 11; //!< DEC_MODE_AVS + + if (p_syn->pp.pictureStructure == FRAMEPICTURE) { + p_regs->sw57.pic_interlace_e = 0; //!< interlace_e + p_regs->sw57.pic_fieldmode_e = 0; //!< fieldmode_e + p_regs->sw57.pic_topfield_e = 0; //!< topfield_e + } else { + p_regs->sw57.pic_interlace_e = 1; + p_regs->sw57.pic_fieldmode_e = 1; + p_regs->sw57.pic_topfield_e = p_hal->first_field; + } + + p_regs->sw120.pic_mb_height_p = (p_syn->pp.verticalSize + 15) >> 4; + p_regs->sw121.avs_h_ext = (p_syn->pp.verticalSize + 15) >> 12; + p_regs->sw57.pic_b_e = (p_syn->pp.picCodingType == BFRAME); + p_regs->sw57.pic_inter_e = (p_syn->pp.picCodingType != IFRAME) ? 1 : 0; + + p_regs->sw122.strm_start_bit = 8 * (p_hal->data_offset & 0x7); + p_hal->data_offset = (p_hal->data_offset & ~0x7); + p_regs->sw64.rlc_vlc_st_adr = get_packet_fd(p_hal, task->input); + mpp_dev_set_reg_offset(dev, 64, p_hal->data_offset); + p_regs->sw51.stream_len = p_syn->bitstream_size - p_hal->data_offset; + p_regs->sw50.dec_fixed_quant = p_syn->pp.fixedPictureQp; + p_regs->sw51.init_qp = p_syn->pp.pictureQp; + + p_regs->sw63.dec_out_st_adr = get_frame_fd(p_hal, task->output); + if (p_syn->pp.pictureStructure == FIELDPICTURE && !p_hal->first_field) { + //!< start of bottom field line + mpp_dev_set_reg_offset(dev, 63, p_syn->pp.horizontalSize); + } + { + RK_S32 tmp_fwd = -1; + RK_S32 refer0 = -1; + RK_S32 refer1 = -1; + + tmp_fwd = (p_hal->work1 < 0) ? p_hal->work0 : p_hal->work1; + tmp_fwd = (tmp_fwd < 0) ? p_hal->work_out : tmp_fwd; + + refer0 = (task->refer[0] < 0) ? task->output : task->refer[0]; + refer1 = (task->refer[1] < 0) ? refer0 : task->refer[1]; + if (!p_hal->first_field + && p_syn->pp.pictureStructure == FIELDPICTURE + && p_syn->pp.picCodingType != BFRAME) { + p_regs->sw131.refer0_base = get_frame_fd(p_hal, task->output); + p_regs->sw148.refer1_base = get_frame_fd(p_hal, refer0); + p_regs->sw134.refer2_base = get_frame_fd(p_hal, refer0); + p_regs->sw135.refer3_base = get_frame_fd(p_hal, refer1); + } else { + p_regs->sw131.refer0_base = get_frame_fd(p_hal, refer0); + p_regs->sw148.refer1_base = get_frame_fd(p_hal, refer0); + p_regs->sw134.refer2_base = get_frame_fd(p_hal, refer1); + p_regs->sw135.refer3_base = get_frame_fd(p_hal, refer1); + } + } + //!< block distances + if (p_syn->pp.pictureStructure == FRAMEPICTURE) { + if (p_syn->pp.picCodingType == BFRAME) { + RK_S32 tmp = 0; + //!< current to future anchor + if (p_hal->work0 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_syn->pp.pictureDistance + 512) & 0x1FF; + } + //!< prevent division by zero + if (!tmp) tmp = 2; + p_regs->sw133.ref_dist_cur_2 = tmp; + p_regs->sw133.ref_dist_cur_3 = tmp; + p_regs->sw147.ref_invd_cur_2 = 512 / tmp; + p_regs->sw147.ref_invd_cur_3 = 512 / tmp; + + //!< current to past anchor + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + p_regs->sw132.ref_dist_cur_0 = tmp; + p_regs->sw132.ref_dist_cur_1 = tmp; + p_regs->sw146.ref_invd_cur_0 = 512 / tmp; + p_regs->sw146.ref_invd_cur_1 = 512 / tmp; + //!< future anchor to past anchor + if (p_hal->work0 >= 0 && p_hal->work1 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + tmp = 16384 / tmp; + p_regs->sw129.ref_invd_col_0 = tmp; + p_regs->sw129.ref_invd_col_1 = tmp; + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + tmp = 16384 / tmp; + p_regs->sw130.ref_invd_col_2 = tmp; + p_regs->sw130.ref_invd_col_3 = tmp; + } else { + RK_S32 tmp = 0; + //!< current to past anchor + if (p_hal->work0 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF; + } + if (!tmp) tmp = 2; + p_regs->sw132.ref_dist_cur_0 = tmp; + p_regs->sw132.ref_dist_cur_1 = tmp; + p_regs->sw146.ref_invd_cur_0 = 512 / tmp; + p_regs->sw146.ref_invd_cur_1 = 512 / tmp; + //!< current to previous past anchor + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + //!< this will become "future to previous past" for next B + p_hal->future2prev_past_dist = tmp; + + p_regs->sw133.ref_dist_cur_2 = tmp; + p_regs->sw133.ref_dist_cur_3 = tmp; + p_regs->sw147.ref_invd_cur_2 = 512 / tmp; + p_regs->sw147.ref_invd_cur_3 = 512 / tmp; + + p_regs->sw129.ref_invd_col_0 = 0; + p_regs->sw129.ref_invd_col_1 = 0; + p_regs->sw130.ref_invd_col_2 = 0; + p_regs->sw130.ref_invd_col_3 = 0; + } + } else { + //!< field interlaced + if (p_syn->pp.picCodingType == BFRAME) { + RK_S32 tmp = 0; + //!< block distances + if (p_hal->work0 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_syn->pp.pictureDistance + 512) & 0x1FF; + } + //!< prevent division by zero + if (!tmp) tmp = 2; + + if (p_hal->first_field) { + p_regs->sw133.ref_dist_cur_2 = tmp; + p_regs->sw133.ref_dist_cur_3 = tmp + 1; + p_regs->sw147.ref_invd_cur_2 = 512 / tmp; + p_regs->sw147.ref_invd_cur_3 = 512 / (tmp + 1); + } else { + p_regs->sw133.ref_dist_cur_2 = tmp - 1; + p_regs->sw133.ref_dist_cur_3 = tmp; + p_regs->sw147.ref_invd_cur_2 = 512 / (tmp - 1); + p_regs->sw147.ref_invd_cur_3 = 512 / tmp; + } + + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + if (p_hal->first_field) { + p_regs->sw132.ref_dist_cur_0 = (tmp - 1); + p_regs->sw132.ref_dist_cur_1 = tmp; + p_regs->sw146.ref_invd_cur_0 = 512 / (tmp - 1); + p_regs->sw146.ref_invd_cur_1 = 512 / tmp; + } else { + p_regs->sw132.ref_dist_cur_0 = tmp; + p_regs->sw132.ref_dist_cur_1 = tmp + 1; + p_regs->sw146.ref_invd_cur_0 = 512 / tmp; + p_regs->sw146.ref_invd_cur_1 = 512 / (tmp + 1); + } + + if (p_hal->work0 >= 0 && p_hal->work1 >= 0) { + tmp = (2 * p_hal->pic[p_hal->work0].picture_distance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + + if (p_syn->pp.pbFieldEnhancedFlag && !p_hal->first_field) { + //!< in this case, BlockDistanceRef is different with before, the mvRef points to top field + p_regs->sw129.ref_invd_col_0 = 16384 / (tmp - 1); + p_regs->sw129.ref_invd_col_1 = 16384 / tmp; + + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + + p_regs->sw130.ref_invd_col_2 = 16384 / (tmp - 1); + p_regs->sw130.ref_invd_col_3 = 16384 / tmp; + } else { + if (p_hal->first_field) { + p_regs->sw129.ref_invd_col_0 = 16384 / (tmp - 1); + p_regs->sw129.ref_invd_col_1 = 16384 / tmp; + } else { + p_regs->sw129.ref_invd_col_0 = 16384; + p_regs->sw129.ref_invd_col_1 = 16384 / tmp; + p_regs->sw130.ref_invd_col_2 = 16384 / (tmp + 1); + } + + //!< future anchor to previous past anchor + tmp = p_hal->future2prev_past_dist; + + if (p_hal->first_field) { + p_regs->sw130.ref_invd_col_2 = 16384 / (tmp - 1); + p_regs->sw130.ref_invd_col_3 = 16384 / tmp; + } else { + p_regs->sw130.ref_invd_col_3 = 16384 / tmp; + } + } + } else { + RK_S32 tmp = 0; + if (p_hal->work0 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work0].picture_distance - 512) & 0x1FF; + } + if (!tmp) tmp = 2; + + if (!p_hal->first_field) { + p_regs->sw132.ref_dist_cur_0 = 1; + p_regs->sw133.ref_dist_cur_2 = tmp + 1; + + p_regs->sw146.ref_invd_cur_0 = 512; + p_regs->sw147.ref_invd_cur_2 = 512 / (tmp + 1); + } else { + p_regs->sw132.ref_dist_cur_0 = tmp - 1; + p_regs->sw146.ref_invd_cur_0 = 512 / (tmp - 1); + } + p_regs->sw132.ref_dist_cur_1 = tmp; + p_regs->sw146.ref_invd_cur_1 = 512 / tmp; + + if (p_hal->work1 >= 0) { + tmp = (2 * p_syn->pp.pictureDistance - + 2 * p_hal->pic[p_hal->work1].picture_distance - 512) & 0x1FF; + if (!tmp) tmp = 2; + } + //!< this will become "future to previous past" for next B + p_hal->future2prev_past_dist = tmp; + if (p_hal->first_field) { + p_regs->sw133.ref_dist_cur_2 = tmp - 1; + p_regs->sw133.ref_dist_cur_3 = tmp; + + p_regs->sw147.ref_invd_cur_2 = 512 / (tmp - 1); + p_regs->sw147.ref_invd_cur_3 = 512 / tmp; + } else { + p_regs->sw133.ref_dist_cur_3 = tmp; + p_regs->sw147.ref_invd_cur_3 = 512 / tmp; + } + + p_regs->sw129.ref_invd_col_0 = 0; + p_regs->sw129.ref_invd_col_1 = 0; + p_regs->sw130.ref_invd_col_2 = 0; + p_regs->sw130.ref_invd_col_3 = 0; + } + } + + p_regs->sw52.startmb_x = 0; + p_regs->sw52.startmb_y = 0; + + p_regs->sw50.filtering_dis = p_syn->pp.loopFilterDisable; + p_regs->sw122.alpha_offset = p_syn->pp.alphaOffset; + p_regs->sw122.beta_offset = p_syn->pp.betaOffset; + p_regs->sw50.skip_mode = p_syn->pp.skipModeFlag; + p_regs->sw120.pic_refer_flag = p_syn->pp.pictureReferenceFlag; + + if (p_syn->pp.picCodingType == PFRAME + || (p_syn->pp.picCodingType == IFRAME && !p_hal->first_field)) { + p_regs->sw57.dmmv_wr_en = 1; + } else { + p_regs->sw57.dmmv_wr_en = 0; + } + + //!< set mv base + p_regs->sw62.dmmv_st_adr = mpp_buffer_get_fd(p_hal->mv_buf); + if (p_hal->first_field || + (p_syn->pp.picCodingType == BFRAME && p_hal->prev_pic_structure)) { + } else { + RK_U32 frame_width = 0, frame_height = 0, offset = 0; + frame_width = (p_syn->pp.horizontalSize + 15) >> 4; + if (p_syn->pp.progressiveFrame) + frame_height = (p_syn->pp.verticalSize + 15) >> 4; + else + frame_height = 2 * ((p_syn->pp.verticalSize + 31) >> 5); + offset = MPP_ALIGN(frame_width * frame_height / 2, 2) * 16; + mpp_dev_set_reg_offset(dev, 62, offset); + } + { + RK_U32 pic_type = 0; + RK_U32 prev_anc_type = 0; + if (p_hal->work0 >= 0) { + pic_type = p_hal->pic[p_hal->work0].pic_type; + } + prev_anc_type = !pic_type || (!p_hal->first_field && !p_hal->prev_pic_structure); + p_regs->sw136.prev_anc_type = prev_anc_type; + } + //!< b-picture needs to know if future reference is field or frame coded + // p_regs->sw134.refer2_field_e = (!p_hal->prev_pic_structure) ? 1 : 0; + // p_regs->sw135.refer3_field_e = (!p_hal->prev_pic_structure) ? 1 : 0; + if (!p_hal->prev_pic_structure) { + mpp_dev_set_reg_offset(dev, 134, 2); + mpp_dev_set_reg_offset(dev, 135, 3); + } + + p_regs->sw57.dec_out_dis = 0; + p_regs->sw57.dec_e = 1; + + return MPP_OK; +__FAILED: + return ret; +} + +static MPP_RET update_parameters(AvsdHalCtx_t *p_hal) +{ + AvsdSyntax_t *p_syn = &p_hal->syn; + + if (p_syn->pp.pictureStructure == FRAMEPICTURE || !p_hal->first_field) { + p_hal->first_field = 1; + if (p_syn->pp.picCodingType != BFRAME) { + RK_S32 temp = p_hal->work1; + + p_hal->work1 = p_hal->work0; + p_hal->work0 = p_hal->work_out; + + if (p_hal->work_out >= 0) + p_hal->pic[p_hal->work_out].pic_type = p_syn->pp.picCodingType == IFRAME; + p_hal->work_out = temp; + p_hal->prev_pic_structure = p_syn->pp.pictureStructure; + } + p_hal->prev_pic_code_type = p_syn->pp.picCodingType; + } else { + p_hal->first_field = 0; + } + + return MPP_OK; +} + +static MPP_RET repeat_other_field(AvsdHalCtx_t *p_hal, HalTaskInfo *task) +{ + RK_U8 i = 0; + RK_U8 *pdata = NULL; + MppBuffer mbuffer = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdVdpu2Regs_t *p_regs = (AvsdVdpu2Regs_t *)p_hal->p_regs; + + //!< re-find start code and calculate offset + p_hal->data_offset = p_regs->sw64.rlc_vlc_st_adr >> 10; + p_hal->data_offset += p_hal->syn.bitstream_offset; + p_hal->data_offset -= MPP_MIN(p_hal->data_offset, 8); + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + pdata = (RK_U8 *)mpp_buffer_get_ptr(mbuffer) + p_hal->data_offset; + + while (i < 16) { + if (pdata[i] == 0 && pdata[i + 1] == 0 && pdata[i + 2] == 1) { + p_hal->data_offset += i; + break; + } + i++; + } + + AVSD_HAL_DBG(AVSD_HAL_DBG_OFFSET, "frame_no %d idx %d offset %x\n", + p_hal->frame_no, i, p_hal->data_offset); + + //!< re-generate register + FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec)); + hal_avsd_vdpu2_start((void *)p_hal, task); + hal_avsd_vdpu2_wait((void *)p_hal, task); + + return ret = MPP_OK; +__FAILED: + return ret; +} + + +/*! + *********************************************************************** + * \brief + * init + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_init(void *decoder, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 buf_size = 0; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + mpp_env_get_u32("hal_avsd_debug", &hal_avsd_debug, 0); + + AVSD_HAL_TRACE("AVS_vdpu2 In."); + + p_hal->cfg = cfg; + + buf_size = (1920 * 1088) * 2; + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, &p_hal->mv_buf, buf_size)); + + p_hal->p_regs = mpp_calloc_size(RK_U32, sizeof(AvsdVdpu2Regs_t)); + MEM_CHECK(ret, p_hal->p_regs); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + p_hal->regs_num = 159; + //!< initial for control + p_hal->first_field = 1; + p_hal->prev_pic_structure = 0; //!< field + + memset(p_hal->pic, 0, sizeof(p_hal->pic)); + p_hal->work_out = -1; + p_hal->work0 = -1; + p_hal->work1 = -1; + + AVSD_HAL_TRACE("Out."); + (void)cfg; + return ret = MPP_OK; +__FAILED: + return ret; + +} +/*! + *********************************************************************** + * \brief + * deinit + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_deinit(void *decoder) +{ + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + if (p_hal->mv_buf) { + mpp_buffer_put(p_hal->mv_buf); + p_hal->mv_buf = NULL; + } + MPP_FREE(p_hal->p_regs); + + AVSD_HAL_TRACE("Out."); + + return MPP_OK; +} +/*! + *********************************************************************** + * \brief + * generate register + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_gen_regs(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + p_hal->data_offset = p_hal->syn.bitstream_offset; + + memcpy(&p_hal->syn, task->dec.syntax.data, sizeof(AvsdSyntax_t)); + FUN_CHECK(ret = set_regs_parameters(p_hal, &task->dec)); +__RETURN: + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +__FAILED: + return ret; + +} +/*! + *********************************************************************** + * \brief h + * start hard + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_start(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __RETURN; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = 159 * sizeof(RK_U32); + MppDev dev = p_hal->cfg->dev; + + wr_cfg.reg = p_hal->p_regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = p_hal->p_regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + AVSD_HAL_TRACE("Out."); + return ret = MPP_OK; +} +/*! + *********************************************************************** + * \brief + * wait hard + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_wait(void *decoder, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + if ((task->dec.flags.parse_err || task->dec.flags.ref_err) && + !p_hal->cfg->cfg->base.disable_error) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_hal->p_regs; + + if (!((AvsdVdpu2Regs_t *)p_hal->p_regs)->sw55.dec_rdy_sts) { + param.hard_err = 1; + } else + param.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + AVSD_HAL_DBG(AVSD_HAL_DBG_WAIT, "reg[55]=%08x, ref=%d, dpberr=%d, harderr=%d\n", + p_hal->p_regs[55], task->dec.flags.used_for_ref, task->dec.flags.ref_err, param.hard_err); + } + + update_parameters(p_hal); + memset(&p_hal->p_regs[55], 0, sizeof(RK_U32)); + if (!p_hal->first_field && p_hal->syn.pp.pictureStructure == FIELDPICTURE && + ((!task->dec.flags.parse_err && !task->dec.flags.ref_err) || + p_hal->cfg->cfg->base.disable_error)) { + repeat_other_field(p_hal, task); + } + p_hal->frame_no++; + + AVSD_HAL_TRACE("Out."); + return ret = MPP_OK; +} +/*! + *********************************************************************** + * \brief + * reset + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_reset(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + AvsdHalCtx_t *p_hal = (AvsdHalCtx_t *)decoder; + + AVSD_HAL_TRACE("In."); + + p_hal->first_field = 1; + p_hal->prev_pic_structure = 0; //!< field + + memset(p_hal->pic, 0, sizeof(p_hal->pic)); + p_hal->work_out = -1; + p_hal->work0 = -1; + p_hal->work1 = -1; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} +/*! + *********************************************************************** + * \brief + * flush + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_flush(void *decoder) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AVSD_HAL_TRACE("In."); + + (void)decoder; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} +/*! + *********************************************************************** + * \brief + * control + *********************************************************************** + */ +//extern "C" +static MPP_RET hal_avsd_vdpu2_control(void *decoder, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + AVSD_HAL_TRACE("In."); + + (void)decoder; + (void)cmd_type; + (void)param; + + AVSD_HAL_TRACE("Out."); + + return ret = MPP_OK; +} + +const MppHalApi hal_avsd_vdpu2 = { + .name = "avsd_vdpu2", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVS, + .ctx_size = sizeof(AvsdHalCtx_t), + .flag = 0, + .init = hal_avsd_vdpu2_init, + .deinit = hal_avsd_vdpu2_deinit, + .reg_gen = hal_avsd_vdpu2_gen_regs, + .start = hal_avsd_vdpu2_start, + .wait = hal_avsd_vdpu2_wait, + .reset = hal_avsd_vdpu2_reset, + .flush = hal_avsd_vdpu2_flush, + .control = hal_avsd_vdpu2_control, + .client = VPU_CLIENT_VDPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_avsd_vdpu2) diff --git a/mpp/hal/rkdec/avsd/hal_avsd_vdpu2.h b/mpp/hal/rkdec/avsd/hal_avsd_vdpu2.h new file mode 100644 index 000000000..a2cb95a29 --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_vdpu2.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVSD_VDPU2_H +#define HAL_AVSD_VDPU2_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_avsd_vdpu2; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_AVSD_VDPU2_H */ diff --git a/mpp/hal/rkdec/avsd/hal_avsd_vdpu2_reg.h b/mpp/hal/rkdec/avsd/hal_avsd_vdpu2_reg.h new file mode 100644 index 000000000..04e1266ff --- /dev/null +++ b/mpp/hal/rkdec/avsd/hal_avsd_vdpu2_reg.h @@ -0,0 +1,230 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AVSD_VDPU2_REG_H +#define HAL_AVSD_VDPU2_REG_H + + +typedef struct { + RK_U32 sw00_49[50]; + struct { + RK_U32 dec_tiled_msb : 1; + RK_U32 adtion_latency : 6; + RK_U32 dec_fixed_quant : 1; + RK_U32 filtering_dis : 1; + RK_U32 skip_mode : 1; + RK_U32 dec_ascmd0_dis : 1; + RK_U32 adv_pref_dis : 1; + RK_U32 dec_tiled_lsb : 1; + RK_U32 refbuf_thrd : 12; + RK_U32 refbuf_pid : 5; + RK_U32 reverse0 : 2; + } sw50; + struct { + RK_U32 stream_len : 24; + RK_U32 stream_len_ext : 1; + RK_U32 init_qp : 6; + RK_U32 reverse0 : 1; + } sw51; + struct { + RK_U32 startmb_y : 8; + RK_U32 startmb_x : 9; + RK_U32 adv_pref_thrd : 14; + RK_U32 reverse0 : 1; + } sw52; + struct { + RK_U32 dec_fmt_sel : 4; + RK_U32 reverse0 : 28; + } sw53; + struct { + RK_U32 dec_in_endian : 1; + RK_U32 dec_out_endian : 1; + RK_U32 dec_in_wordsp : 1; + RK_U32 dec_out_wordsp : 1; + RK_U32 dec_strm_wordsp : 1; + RK_U32 dec_strendian_e : 1; + RK_U32 reverse0 : 26; + } sw54; + struct { + RK_U32 dec_irq : 1; + RK_U32 dec_irq_dis : 1; + RK_U32 reverse0 : 2; + RK_U32 dec_rdy_sts : 1; + RK_U32 pp_bus_sts : 1; + RK_U32 buf_emt_sts : 1; + RK_U32 reverse1 : 1; + RK_U32 aso_det_sts : 1; + RK_U32 slice_det_sts : 1; + RK_U32 bslice_det_sts : 1; + RK_U32 reverse2 : 1; + RK_U32 error_det_sts : 1; + RK_U32 timeout_det_sts : 1; + RK_U32 reverse3 : 18; + } sw55; + struct { + RK_U32 dec_axi_id_rd : 8; + RK_U32 dec_axi_id_wr : 8; + RK_U32 dec_max_burlen : 5; + RK_U32 bus_pos_sel : 1; + RK_U32 dec_data_discd_en : 1; + RK_U32 axi_sel : 1; + RK_U32 reverse0 : 8; + } sw56; + struct { + RK_U32 dec_e : 1; + RK_U32 refpic_buf2_en : 1; + RK_U32 dec_out_dis : 1; + RK_U32 reverse0 : 1; + RK_U32 dec_clkgate_en : 1; + RK_U32 timeout_sts_en : 1; + RK_U32 rd_cnt_tab_en : 1; + RK_U32 reverse1 : 1; + RK_U32 first_reftop_en : 1; + RK_U32 reftop_en : 1; + RK_U32 dmmv_wr_en : 1; + RK_U32 reverse2 : 1; + RK_U32 fwd_interlace_e : 1; + RK_U32 pic_topfield_e : 1; + RK_U32 pic_inter_e : 1; + RK_U32 pic_b_e : 1; + RK_U32 pic_fieldmode_e : 1; + RK_U32 pic_interlace_e : 1; + RK_U32 reverse3 : 2; + RK_U32 rlc_mode_en : 1; + RK_U32 addit_ch_fmt_wen : 1; + RK_U32 st_code_exit : 1; + RK_U32 reverse4 : 2; + RK_U32 inter_dblspeed : 1; + RK_U32 intra_dblspeed : 1; + RK_U32 intra_dbl3t : 1; + RK_U32 pref_sigchan : 1; + RK_U32 cache_en : 1; + RK_U32 reverse5 : 1; + RK_U32 dec_timeout_mode : 1; + } sw57; + RK_U32 sw58; + struct { + RK_U32 reserve : 2; + RK_U32 pred_bc_tap_0_2 : 10; + RK_U32 pred_bc_tap_0_1 : 10; + RK_U32 pred_bc_tap_0_0 : 10; + } sw59; + RK_U32 sw60; + RK_U32 sw61; + struct { + RK_U32 dmmv_st_adr : 32; + } sw62; + struct { + RK_U32 dec_out_st_adr : 32; + } sw63; + struct { + RK_U32 rlc_vlc_st_adr : 32; + } sw64; + RK_U32 sw65_119[55]; + struct { + RK_U32 pic_refer_flag : 1; + RK_U32 reserver0 : 6; + RK_U32 mb_height_off : 4; + RK_U32 pic_mb_height_p : 8; + RK_U32 mb_width_off : 4; + RK_U32 pic_mb_width : 9; + } sw120; + struct { + RK_U32 reserve0 : 25; + RK_U32 avs_h_ext : 1; + RK_U32 reserve1 : 6; + } sw121; + struct { + RK_U32 beta_offset : 5; + RK_U32 alpha_offset : 5; + RK_U32 reserver0 : 16; + RK_U32 strm_start_bit : 6; + } sw122; + RK_U32 sw123_128[6]; + struct { + RK_U32 ref_invd_col_0 : 16; + RK_U32 ref_invd_col_1 : 16; + } sw129; + struct { + RK_U32 ref_invd_col_2 : 16; + RK_U32 ref_invd_col_3 : 16; + } sw130; + union { + RK_U32 refer0_base : 32; + struct { //!< left move 10bit + RK_U32 refer0_topc_e : 1; + RK_U32 refer0_field_e : 1; + }; + } sw131; + struct { + RK_U32 ref_dist_cur_0 : 16; + RK_U32 ref_dist_cur_1 : 16; + } sw132; + struct { + RK_U32 ref_dist_cur_2 : 16; + RK_U32 ref_dist_cur_3 : 16; + } sw133; + union { + RK_U32 refer2_base : 32; + struct { //!< left move 10bit + RK_U32 refer2_topc_e : 1; + RK_U32 refer2_field_e : 1; + }; + } sw134; + union { + RK_U32 refer3_base : 32; + struct { //!< left move 10bit + RK_U32 refer3_topc_e : 1; + RK_U32 refer3_field_e : 1; + }; + } sw135; + struct { + RK_U32 prev_anc_type : 1; + RK_U32 reserver0 : 31; + } sw136; + RK_U32 sw137_145[9]; + struct { + RK_U32 ref_invd_cur_0 : 16; + RK_U32 ref_invd_cur_1 : 16; + } sw146; + struct { + RK_U32 ref_invd_cur_2 : 16; + RK_U32 ref_invd_cur_3 : 16; + } sw147; + union { + RK_U32 refer1_base : 32; + struct { //!< left move 10bit + RK_U32 refer1_topc_e : 1; + RK_U32 refer1_field_e : 1; + }; + } sw148; + RK_U32 sw149_152[4]; + struct { + RK_U32 reserve : 2; + RK_U32 pred_bc_tap_1_1 : 10; + RK_U32 pred_bc_tap_1_0 : 10; + RK_U32 pred_bc_tap_0_3 : 10; + } sw153; + struct { + RK_U32 reserve : 2; + RK_U32 pred_bc_tap_2_0 : 10; + RK_U32 pred_bc_tap_1_3 : 10; + RK_U32 pred_bc_tap_1_2 : 10; + } sw154; + RK_U32 sw155_158[4]; +} AvsdVdpu2Regs_t; + +#endif /* HAL_AVSD_VDPU2_REG_H */ diff --git a/mpp/hal/rkdec/common/CMakeLists.txt b/mpp/hal/rkdec/common/CMakeLists.txt new file mode 100644 index 000000000..b40b3c0b3 --- /dev/null +++ b/mpp/hal/rkdec/common/CMakeLists.txt @@ -0,0 +1,18 @@ +# vim: syntax=cmake +include_directories(.) +# ---------------------------------------------------------------------------- +# add rkvdec common file +# ---------------------------------------------------------------------------- +set(HAL_RKVDEC_SRC + vdpu_com.c + vdpu34x_com.c + vdpu382_com.c + vdpu383_com.c + vdpu384a_com.c + vdpu38x_com.c + ) + +add_library(hal_rkvdec_com OBJECT ${HAL_RKVDEC_SRC}) + +target_link_libraries(hal_rkvdec_com mpp_base) +set_target_properties(hal_rkvdec_com PROPERTIES FOLDER "mpp/hal") diff --git a/mpp/hal/rkdec/common/vdpu34x_com.c b/mpp/hal/rkdec/common/vdpu34x_com.c new file mode 100644 index 000000000..7b22ad789 --- /dev/null +++ b/mpp/hal/rkdec/common/vdpu34x_com.c @@ -0,0 +1,220 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vdpu34x_com" + +#include +#include + +#include "mpp_log.h" +#include "mpp_buffer.h" +#include "mpp_common.h" +#include "mpp_compat_impl.h" +#include "mpp_env.h" + +#include "vdpu_com.h" +#include "vdpu34x_com.h" + +static RK_U32 rcb_coeff[RCB_BUF_COUNT] = { + [RCB_INTRA_ROW] = 6, /* RCB_INTRA_ROW_COEF */ + [RCB_TRANSD_ROW] = 1, /* RCB_TRANSD_ROW_COEF */ + [RCB_TRANSD_COL] = 1, /* RCB_TRANSD_COL_COEF */ + [RCB_STRMD_ROW] = 3, /* RCB_STRMD_ROW_COEF */ + [RCB_INTER_ROW] = 6, /* RCB_INTER_ROW_COEF */ + [RCB_INTER_COL] = 3, /* RCB_INTER_COL_COEF */ + [RCB_DBLK_ROW] = 22, /* RCB_DBLK_ROW_COEF */ + [RCB_SAO_ROW] = 6, /* RCB_SAO_ROW_COEF */ + [RCB_FBC_ROW] = 11, /* RCB_FBC_ROW_COEF */ + [RCB_FILT_COL] = 67, /* RCB_FILT_COL_COEF */ +}; + +static RK_S32 update_size_offset(VdpuRcbInfo *info, RK_U32 reg, + RK_S32 offset, RK_S32 len, RK_S32 idx) +{ + RK_S32 buf_size = 0; + + buf_size = MPP_ALIGN(len * rcb_coeff[idx], RCB_ALLINE_SIZE); + info[idx].reg_idx = reg; + info[idx].offset = offset; + info[idx].size = buf_size; + + return buf_size; +} + +RK_S32 vdpu34x_get_rcb_buf_size(VdpuRcbInfo *info, RK_S32 width, RK_S32 height) +{ + RK_S32 offset = 0; + + offset += update_size_offset(info, 139, offset, width, RCB_DBLK_ROW); + offset += update_size_offset(info, 133, offset, width, RCB_INTRA_ROW); + offset += update_size_offset(info, 134, offset, width, RCB_TRANSD_ROW); + offset += update_size_offset(info, 136, offset, width, RCB_STRMD_ROW); + offset += update_size_offset(info, 137, offset, width, RCB_INTER_ROW); + offset += update_size_offset(info, 140, offset, width, RCB_SAO_ROW); + offset += update_size_offset(info, 141, offset, width, RCB_FBC_ROW); + /* col rcb */ + offset += update_size_offset(info, 135, offset, height, RCB_TRANSD_COL); + offset += update_size_offset(info, 138, offset, height, RCB_INTER_COL); + offset += update_size_offset(info, 142, offset, height, RCB_FILT_COL); + + return offset; +} + +void vdpu34x_setup_rcb(Vdpu34xRegCommonAddr *reg, MppDev dev, MppBuffer buf, VdpuRcbInfo *info) +{ + RK_S32 fd = mpp_buffer_get_fd(buf); + + reg->reg139_rcb_dblk_base = fd; + reg->reg133_rcb_intra_base = fd; + reg->reg134_rcb_transd_row_base = fd; + reg->reg136_rcb_streamd_row_base = fd; + reg->reg137_rcb_inter_row_base = fd; + reg->reg140_rcb_sao_base = fd; + reg->reg141_rcb_fbc_base = fd; + reg->reg135_rcb_transd_col_base = fd; + reg->reg138_rcb_inter_col_base = fd; + reg->reg142_rcb_filter_col_base = fd; + + if (info[RCB_DBLK_ROW].offset) + mpp_dev_set_reg_offset(dev, 139, info[RCB_DBLK_ROW].offset); + if (info[RCB_INTRA_ROW].offset) + mpp_dev_set_reg_offset(dev, 133, info[RCB_INTRA_ROW].offset); + if (info[RCB_TRANSD_ROW].offset) + mpp_dev_set_reg_offset(dev, 134, info[RCB_TRANSD_ROW].offset); + if (info[RCB_STRMD_ROW].offset) + mpp_dev_set_reg_offset(dev, 136, info[RCB_STRMD_ROW].offset); + if (info[RCB_INTER_ROW].offset) + mpp_dev_set_reg_offset(dev, 137, info[RCB_INTER_ROW].offset); + if (info[RCB_SAO_ROW].offset) + mpp_dev_set_reg_offset(dev, 140, info[RCB_SAO_ROW].offset); + if (info[RCB_FBC_ROW].offset) + mpp_dev_set_reg_offset(dev, 141, info[RCB_FBC_ROW].offset); + if (info[RCB_TRANSD_COL].offset) + mpp_dev_set_reg_offset(dev, 135, info[RCB_TRANSD_COL].offset); + if (info[RCB_INTER_COL].offset) + mpp_dev_set_reg_offset(dev, 138, info[RCB_INTER_COL].offset); + if (info[RCB_FILT_COL].offset) + mpp_dev_set_reg_offset(dev, 142, info[RCB_FILT_COL].offset); +} + +RK_S32 vdpu34x_set_rcbinfo(MppDev dev, VdpuRcbInfo *rcb_info) +{ + MppDevRcbInfoCfg rcb_cfg; + RK_U32 i; + VdpuRcbSetMode set_rcb_mode = RCB_SET_BY_PRIORITY_MODE; + static const RK_U32 rcb_priority[RCB_BUF_COUNT] = { + RCB_DBLK_ROW, + RCB_INTRA_ROW, + RCB_SAO_ROW, + RCB_INTER_ROW, + RCB_FBC_ROW, + RCB_TRANSD_ROW, + RCB_STRMD_ROW, + RCB_INTER_COL, + RCB_FILT_COL, + RCB_TRANSD_COL, + }; + + switch (set_rcb_mode) { + case RCB_SET_BY_SIZE_SORT_MODE : { + VdpuRcbInfo info[RCB_BUF_COUNT]; + + memcpy(info, rcb_info, sizeof(info)); + qsort(info, MPP_ARRAY_ELEMS(info), + sizeof(info[0]), vdpu_compare_rcb_size); + + for (i = 0; i < MPP_ARRAY_ELEMS(info); i++) { + rcb_cfg.reg_idx = info[i].reg_idx; + rcb_cfg.size = info[i].size; + if (rcb_cfg.size > 0) { + mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg); + } else + break; + } + } break; + case RCB_SET_BY_PRIORITY_MODE : { + VdpuRcbInfo *info = rcb_info; + RK_U32 index = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(rcb_priority); i ++) { + index = rcb_priority[i]; + /* + * If the inter row rcb buffer is placed in sram, + * may conflict with other buffer in ddr, + * will result in slower access to data and degraded decoding performance. + * The issue will be resolved in chips after rk3588. + */ + if (index == RCB_INTER_ROW) + continue; + + rcb_cfg.reg_idx = info[index].reg_idx; + rcb_cfg.size = info[index].size; + if (rcb_cfg.size > 0) { + mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg); + } + } + } break; + default: + break; + } + + return 0; +} + +void vdpu34x_setup_statistic(Vdpu34xRegCommon *com, Vdpu34xRegStatistic *sta) +{ + com->reg011.pix_range_detection_e = 1; + + memset(sta, 0, sizeof(*sta)); + + sta->reg256.axi_perf_work_e = 1; + sta->reg256.axi_perf_clr_e = 1; + sta->reg256.axi_cnt_type = 1; + + sta->reg257.addr_align_type = 1; + + /* set hurry */ + sta->reg270.axi_rd_hurry_level = 3; + sta->reg270.axi_wr_hurry_level = 1; + sta->reg270.axi_wr_qos = 1; + sta->reg270.axi_rd_qos = 3; + sta->reg270.bus2mc_buffer_qos_level = 255; + sta->reg271_wr_wait_cycle_qos = 0; +} + +RK_U32 vdpu34x_get_colmv_size(RK_U32 width, RK_U32 height, RK_U32 ctu_size, + RK_U32 colmv_bytes, RK_U32 colmv_size, RK_U32 compress) +{ + RK_U32 colmv_total_size; + + if (compress) { + RK_U32 segment_w = (64 * colmv_size * colmv_size) / ctu_size; + RK_U32 segment_h = ctu_size; + RK_U32 seg_cnt_w = MPP_ALIGN(width, segment_w) / segment_w; + RK_U32 seg_cnt_h = MPP_ALIGN(height, segment_h) / segment_h; + RK_U32 seg_head_size = MPP_ALIGN(seg_cnt_w, 16) * seg_cnt_h; + RK_U32 seg_payload_size = seg_cnt_w * seg_cnt_h * 64 * colmv_bytes; + + colmv_total_size = seg_head_size + seg_payload_size; + } else { + RK_U32 colmv_block_size_w = MPP_ALIGN(width, 64) / colmv_size; + RK_U32 colmv_block_size_h = MPP_ALIGN(height, 64) / colmv_size; + + colmv_total_size = colmv_block_size_w * colmv_block_size_h * colmv_bytes; + } + + return MPP_ALIGN(colmv_total_size, 128); +} diff --git a/mpp/hal/rkdec/common/vdpu382_com.c b/mpp/hal/rkdec/common/vdpu382_com.c new file mode 100644 index 000000000..e4d93cf48 --- /dev/null +++ b/mpp/hal/rkdec/common/vdpu382_com.c @@ -0,0 +1,245 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vdpu382_com" + +#include +#include +#include "mpp_log.h" +#include "mpp_buffer.h" +#include "mpp_common.h" +#include "mpp_compat_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_env.h" + +#include "vdpu_com.h" +#include "vdpu382_com.h" + +static RK_U32 rcb_coeff[RCB_BUF_COUNT] = { + [RCB_INTRA_ROW] = 6, /* RCB_INTRA_ROW_COEF */ + [RCB_TRANSD_ROW] = 1, /* RCB_TRANSD_ROW_COEF */ + [RCB_TRANSD_COL] = 1, /* RCB_TRANSD_COL_COEF */ + [RCB_STRMD_ROW] = 3, /* RCB_STRMD_ROW_COEF */ + [RCB_INTER_ROW] = 6, /* RCB_INTER_ROW_COEF */ + [RCB_INTER_COL] = 3, /* RCB_INTER_COL_COEF */ + [RCB_DBLK_ROW] = 22, /* RCB_DBLK_ROW_COEF */ + [RCB_SAO_ROW] = 6, /* RCB_SAO_ROW_COEF */ + [RCB_FBC_ROW] = 11, /* RCB_FBC_ROW_COEF */ + [RCB_FILT_COL] = 67, /* RCB_FILT_COL_COEF */ +}; + +static RK_S32 update_size_offset(VdpuRcbInfo *info, RK_U32 reg, + RK_S32 offset, RK_S32 len, RK_S32 idx) +{ + RK_S32 buf_size = 0; + + buf_size = MPP_ALIGN(len * rcb_coeff[idx], RCB_ALLINE_SIZE); + info[idx].reg_idx = reg; + info[idx].offset = offset; + info[idx].size = buf_size; + + return buf_size; +} + +RK_S32 vdpu382_get_rcb_buf_size(VdpuRcbInfo *info, RK_S32 width, RK_S32 height) +{ + RK_S32 offset = 0; + + offset += update_size_offset(info, 139, offset, width, RCB_DBLK_ROW); + offset += update_size_offset(info, 133, offset, width, RCB_INTRA_ROW); + offset += update_size_offset(info, 134, offset, width, RCB_TRANSD_ROW); + offset += update_size_offset(info, 136, offset, width, RCB_STRMD_ROW); + offset += update_size_offset(info, 137, offset, width, RCB_INTER_ROW); + offset += update_size_offset(info, 140, offset, width, RCB_SAO_ROW); + offset += update_size_offset(info, 141, offset, width, RCB_FBC_ROW); + /* col rcb */ + offset += update_size_offset(info, 135, offset, height, RCB_TRANSD_COL); + offset += update_size_offset(info, 138, offset, height, RCB_INTER_COL); + offset += update_size_offset(info, 142, offset, height, RCB_FILT_COL); + + return offset; +} + +void vdpu382_setup_rcb(Vdpu382RegCommonAddr *reg, MppDev dev, MppBuffer buf, VdpuRcbInfo *info) +{ + RK_S32 fd = mpp_buffer_get_fd(buf); + + reg->reg139_rcb_dblk_base = fd; + reg->reg133_rcb_intra_base = fd; + reg->reg134_rcb_transd_row_base = fd; + reg->reg136_rcb_streamd_row_base = fd; + reg->reg137_rcb_inter_row_base = fd; + reg->reg140_rcb_sao_base = fd; + reg->reg141_rcb_fbc_base = fd; + reg->reg135_rcb_transd_col_base = fd; + reg->reg138_rcb_inter_col_base = fd; + reg->reg142_rcb_filter_col_base = fd; + + if (info[RCB_DBLK_ROW].offset) + mpp_dev_set_reg_offset(dev, 139, info[RCB_DBLK_ROW].offset); + if (info[RCB_INTRA_ROW].offset) + mpp_dev_set_reg_offset(dev, 133, info[RCB_INTRA_ROW].offset); + if (info[RCB_TRANSD_ROW].offset) + mpp_dev_set_reg_offset(dev, 134, info[RCB_TRANSD_ROW].offset); + if (info[RCB_STRMD_ROW].offset) + mpp_dev_set_reg_offset(dev, 136, info[RCB_STRMD_ROW].offset); + if (info[RCB_INTER_ROW].offset) + mpp_dev_set_reg_offset(dev, 137, info[RCB_INTER_ROW].offset); + if (info[RCB_SAO_ROW].offset) + mpp_dev_set_reg_offset(dev, 140, info[RCB_SAO_ROW].offset); + if (info[RCB_FBC_ROW].offset) + mpp_dev_set_reg_offset(dev, 141, info[RCB_FBC_ROW].offset); + if (info[RCB_TRANSD_COL].offset) + mpp_dev_set_reg_offset(dev, 135, info[RCB_TRANSD_COL].offset); + if (info[RCB_INTER_COL].offset) + mpp_dev_set_reg_offset(dev, 138, info[RCB_INTER_COL].offset); + if (info[RCB_FILT_COL].offset) + mpp_dev_set_reg_offset(dev, 142, info[RCB_FILT_COL].offset); +} + +RK_S32 vdpu382_set_rcbinfo(MppDev dev, VdpuRcbInfo *rcb_info) +{ + MppDevRcbInfoCfg rcb_cfg; + RK_U32 i; + VdpuRcbSetMode set_rcb_mode = RCB_SET_BY_PRIORITY_MODE; + static const RK_U32 rcb_priority[RCB_BUF_COUNT] = { + RCB_DBLK_ROW, + RCB_INTRA_ROW, + RCB_SAO_ROW, + RCB_INTER_ROW, + RCB_FBC_ROW, + RCB_TRANSD_ROW, + RCB_STRMD_ROW, + RCB_INTER_COL, + RCB_FILT_COL, + RCB_TRANSD_COL, + }; + + switch (set_rcb_mode) { + case RCB_SET_BY_SIZE_SORT_MODE : { + VdpuRcbInfo info[RCB_BUF_COUNT]; + + memcpy(info, rcb_info, sizeof(info)); + qsort(info, MPP_ARRAY_ELEMS(info), + sizeof(info[0]), vdpu_compare_rcb_size); + + for (i = 0; i < MPP_ARRAY_ELEMS(info); i++) { + rcb_cfg.reg_idx = info[i].reg_idx; + rcb_cfg.size = info[i].size; + if (rcb_cfg.size > 0) { + mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg); + } else + break; + } + } break; + case RCB_SET_BY_PRIORITY_MODE : { + VdpuRcbInfo *info = rcb_info; + RK_U32 index = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(rcb_priority); i ++) { + index = rcb_priority[i]; + + rcb_cfg.reg_idx = info[index].reg_idx; + rcb_cfg.size = info[index].size; + if (rcb_cfg.size > 0) { + mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg); + } + } + } break; + default: + break; + } + + return 0; +} + +void vdpu382_setup_statistic(Vdpu382RegCommon *com, Vdpu382RegStatistic *sta) +{ + com->reg011.pix_range_detection_e = 1; + + memset(sta, 0, sizeof(*sta)); + + sta->reg256.axi_perf_work_e = 1; + sta->reg256.axi_perf_clr_e = 1; + sta->reg256.axi_cnt_type = 1; + + sta->reg257.addr_align_type = 1; + + /* set hurry */ + sta->reg270.axi_rd_hurry_level = 3; + sta->reg270.axi_wr_hurry_level = 1; + sta->reg270.axi_wr_qos = 1; + sta->reg270.axi_rd_qos = 3; + sta->reg270.bus2mc_buffer_qos_level = 255; + sta->reg271_wr_wait_cycle_qos = 0; +} + +void vdpu382_setup_down_scale(MppFrame frame, MppDev dev, Vdpu382RegCommon *com) +{ + RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); + RK_U32 hor_stride = mpp_frame_get_hor_stride(frame); + RK_U32 down_scale_ver = MPP_ALIGN(ver_stride >> 1, 16); + RK_U32 down_scale_hor = MPP_ALIGN(hor_stride >> 1, 16); + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + MppMeta meta = mpp_frame_get_meta(frame); + RK_U32 down_scale_y_offset = 0; + RK_U32 down_scale_uv_offset = 0; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) + down_scale_y_offset = mpp_frame_get_fbc_size(frame); + else + down_scale_y_offset = ver_stride * hor_stride * 3 / 2; + + com->reg012.scale_down_en = 1; + com->reg029.scale_down_y_wratio = 2; + com->reg029.scale_down_y_hratio = 2; + com->reg029.scale_down_c_wratio = 2; + com->reg029.scale_down_c_hratio = 2; + com->reg030.y_scale_down_hor_stride = MPP_ALIGN(down_scale_hor, 16) >> 4; + com->reg031.uv_scale_down_hor_stride = MPP_ALIGN(down_scale_hor, 16) >> 4; + + down_scale_y_offset = MPP_ALIGN(down_scale_y_offset, 16); + mpp_dev_set_reg_offset(dev, 198, down_scale_y_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_Y_OFFSET, down_scale_y_offset); + + down_scale_uv_offset = down_scale_y_offset + down_scale_hor * down_scale_ver; + mpp_dev_set_reg_offset(dev, 199, down_scale_uv_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_UV_OFFSET, down_scale_uv_offset); +} + +RK_U32 vdpu382_get_colmv_size(RK_U32 width, RK_U32 height, RK_U32 ctu_size, + RK_U32 colmv_bytes, RK_U32 colmv_size, RK_U32 compress) +{ + RK_U32 colmv_total_size; + + if (compress) { + RK_U32 segment_w = (64 * colmv_size * colmv_size) / ctu_size; + RK_U32 segment_h = ctu_size; + RK_U32 seg_cnt_w = MPP_ALIGN(width, segment_w) / segment_w; + RK_U32 seg_cnt_h = MPP_ALIGN(height, segment_h) / segment_h; + RK_U32 seg_head_size = MPP_ALIGN(seg_cnt_w, 16) * seg_cnt_h; + RK_U32 seg_payload_size = seg_cnt_w * seg_cnt_h * 64 * colmv_bytes; + + colmv_total_size = seg_head_size + seg_payload_size; + } else { + RK_U32 colmv_block_size_w = MPP_ALIGN(width, 64) / colmv_size; + RK_U32 colmv_block_size_h = MPP_ALIGN(height, 64) / colmv_size; + + colmv_total_size = colmv_block_size_w * colmv_block_size_h * colmv_bytes; + } + + return MPP_ALIGN(colmv_total_size, 128); +} diff --git a/mpp/hal/rkdec/common/vdpu383_com.c b/mpp/hal/rkdec/common/vdpu383_com.c new file mode 100644 index 000000000..857f4f524 --- /dev/null +++ b/mpp/hal/rkdec/common/vdpu383_com.c @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpu383_com" + +#include + +#include "mpp_log.h" +#include "mpp_buffer.h" +#include "mpp_common.h" +#include "mpp_compat_impl.h" +#include "mpp_frame_impl.h" + +#include "vdpu_com.h" +#include "vdpu383_com.h" + +void vdpu383_init_ctrl_regs(Vdpu383RegSet *regs, MppCodingType codec_t) +{ + Vdpu383CtrlReg *ctrl_regs = ®s->ctrl_regs; + + switch (codec_t) { + case MPP_VIDEO_CodingAVC : { + ctrl_regs->reg8_dec_mode = 1; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xfffedfff; + ctrl_regs->reg21_cabac_error_en_highbits = 0x0ffbf9ff; + } break; + case MPP_VIDEO_CodingHEVC : { + ctrl_regs->reg8_dec_mode = 0; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffff; + ctrl_regs->reg21_cabac_error_en_highbits = 0x3ff3f9ff; + } break; + case MPP_VIDEO_CodingAVS2 : { + ctrl_regs->reg8_dec_mode = 3; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffff; + ctrl_regs->reg21_cabac_error_en_highbits = 0x3fffffff; + } break; + case MPP_VIDEO_CodingVP9 : { + ctrl_regs->reg8_dec_mode = 2; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffdf; + ctrl_regs->reg21_cabac_error_en_highbits = 0x3fffffff; + } break; + case MPP_VIDEO_CodingAV1 : { + ctrl_regs->reg8_dec_mode = 4; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffdf; + ctrl_regs->reg21_cabac_error_en_highbits = 0x3fffffff; + } break; + default : { + mpp_err("not support codec type %d\n", codec_t); + } break; + } + + ctrl_regs->reg9.buf_empty_en = 0; + + ctrl_regs->reg10.strmd_auto_gating_e = 1; + ctrl_regs->reg10.inter_auto_gating_e = 1; + ctrl_regs->reg10.intra_auto_gating_e = 1; + ctrl_regs->reg10.transd_auto_gating_e = 1; + ctrl_regs->reg10.recon_auto_gating_e = 1; + ctrl_regs->reg10.filterd_auto_gating_e = 1; + ctrl_regs->reg10.bus_auto_gating_e = 1; + ctrl_regs->reg10.ctrl_auto_gating_e = 1; + ctrl_regs->reg10.rcb_auto_gating_e = 1; + ctrl_regs->reg10.err_prc_auto_gating_e = 1; + + ctrl_regs->reg13_core_timeout_threshold = 0xffffff; + + ctrl_regs->reg16.error_proc_disable = 1; + ctrl_regs->reg16.error_spread_disable = 0; + ctrl_regs->reg16.roi_error_ctu_cal_en = 0; + + return; +} + +void vdpu383_setup_statistic(Vdpu383CtrlReg *ctrl_regs) +{ + ctrl_regs->reg28.axi_perf_work_e = 1; + ctrl_regs->reg28.axi_cnt_type = 1; + ctrl_regs->reg28.rd_latency_id = 11; + + ctrl_regs->reg29.addr_align_type = 1; + ctrl_regs->reg29.ar_cnt_id_type = 0; + ctrl_regs->reg29.aw_cnt_id_type = 1; + ctrl_regs->reg29.ar_count_id = 17; + ctrl_regs->reg29.aw_count_id = 0; + ctrl_regs->reg29.rd_band_width_mode = 0; + + /* set hurry */ + ctrl_regs->reg30.axi_wr_qos = 0; + ctrl_regs->reg30.axi_rd_qos = 0; +} + +void vdpu383_update_thumbnail_frame_info(MppFrame frame) +{ + RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1; + RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1; + RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16); + RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16); + RK_U32 down_scale_buf_size = 0; + + if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) { + down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor); + down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1; + } + + down_scale_buf_size = down_scale_hor * down_scale_ver * 3 / 2; + /* + * no matter what format, scale down image will output as 8bit raster format; + */ + mpp_frame_set_fmt(frame, MPP_FMT_YUV420SP); + mpp_frame_set_width(frame, down_scale_width); + mpp_frame_set_height(frame, down_scale_height); + mpp_frame_set_hor_stride(frame, down_scale_hor); + mpp_frame_set_ver_stride(frame, down_scale_ver); + mpp_frame_set_buf_size(frame, down_scale_buf_size); +} + +void vdpu383_setup_down_scale(MppFrame frame, MppDev dev, Vdpu383CtrlReg *com, void* comParas) +{ + RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1; + RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1; + RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16); + RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16); + + Vdpu383RegCommParas* paras = (Vdpu383RegCommParas*)comParas; + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + MppMeta meta = mpp_frame_get_meta(frame); + RK_U32 down_scale_y_offset = 0; + RK_U32 down_scale_uv_offset = 0; + RK_U32 down_scale_y_virstride = down_scale_ver * down_scale_hor; + RK_U32 downscale_buf_size; + + if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) { + down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor); + down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1; + down_scale_y_virstride = down_scale_ver * down_scale_hor; + } + /* + * no matter what format, scale down image will output as 8bit raster format; + * down_scale image buffer size was already added to the buf_size of mpp_frame, + * which was calculated in mpp_buf_slot.cpp: (size = original_size + scaledown_size) + */ + switch ((fmt & MPP_FRAME_FMT_MASK)) { + case MPP_FMT_YUV400 : { + downscale_buf_size = down_scale_y_virstride; + } break; + case MPP_FMT_YUV420SP_10BIT : + case MPP_FMT_YUV420SP : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + case MPP_FMT_YUV422SP_10BIT : + case MPP_FMT_YUV422SP : { + downscale_buf_size = down_scale_y_virstride * 2; + } break; + case MPP_FMT_YUV444SP : { + downscale_buf_size = down_scale_y_virstride * 3; + } break; + default : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + } + downscale_buf_size = MPP_ALIGN(downscale_buf_size, 16); + + down_scale_y_offset = MPP_ALIGN((mpp_frame_get_buf_size(frame) - downscale_buf_size), 16); + down_scale_uv_offset = down_scale_y_offset + down_scale_y_virstride; + + com->reg9.scale_down_en = 1; + com->reg9.av1_fgs_en = 0; + paras->reg71_scl_ref_hor_virstride = down_scale_hor >> 4; + paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 4; + if ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP) + paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 3; + paras->reg73_scl_ref_virstride = down_scale_y_virstride >> 4; + if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_MIXED) { + mpp_dev_set_reg_offset(dev, 133, down_scale_y_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_Y_OFFSET, down_scale_y_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_UV_OFFSET, down_scale_uv_offset); + } +} + +#ifdef DUMP_VDPU383_DATAS +RK_U32 dump_cur_frame = 0; +char dump_cur_dir[128]; +char dump_cur_fname_path[512]; + +MPP_RET flip_string(char *str) +{ + RK_U32 len = strlen(str); + RK_U32 i, j; + + for (i = 0, j = len - 1; i <= j; i++, j--) { + // swapping characters + char c = str[i]; + str[i] = str[j]; + str[j] = c; + } + + return MPP_OK; +} + +MPP_RET dump_data_to_file(char *fname_path, void *data, RK_U32 data_bit_size, + RK_U32 line_bits, RK_U32 big_end) +{ + RK_U8 *buf_p = (RK_U8 *)data; + RK_U8 cur_data; + RK_U32 i; + RK_U32 loop_cnt; + FILE *dump_fp = NULL; + char line_tmp[256]; + RK_U32 str_idx = 0; + + dump_fp = fopen(fname_path, "w+"); + if (!dump_fp) { + mpp_err_f("open file: %s error!\n", fname_path); + return MPP_NOK; + } + + if ((data_bit_size % 4 != 0) || (line_bits % 8 != 0)) { + mpp_err_f("line bits not align to 4!\n"); + return MPP_NOK; + } + + loop_cnt = data_bit_size / 8; + for (i = 0; i < loop_cnt; i++) { + cur_data = buf_p[i]; + + sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf); + if ((i * 8 + 4) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + sprintf(&line_tmp[str_idx++], "%0x", (cur_data >> 4) & 0xf); + if ((i * 8 + 8) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + } + + // last line + if (data_bit_size % 4) { + cur_data = buf_p[i]; + sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf); + if ((i * 8 + 8) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + } + if (data_bit_size % line_bits) { + loop_cnt = (line_bits - (data_bit_size % line_bits)) / 4; + for (i = 0; i < loop_cnt; i++) + sprintf(&line_tmp[str_idx++], "%0x", 0); + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + + fclose(dump_fp); + + return MPP_OK; +} +#endif diff --git a/mpp/hal/rkdec/common/vdpu384a_com.c b/mpp/hal/rkdec/common/vdpu384a_com.c new file mode 100644 index 000000000..be72d7d13 --- /dev/null +++ b/mpp/hal/rkdec/common/vdpu384a_com.c @@ -0,0 +1,262 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpu384a_com" + +#include + +#include "mpp_log.h" +#include "mpp_buffer.h" +#include "mpp_common.h" +#include "mpp_compat_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_debug.h" + +#include "vdpu_com.h" +#include "vdpu384a_com.h" + +void vdpu384a_init_ctrl_regs(Vdpu384aRegSet *regs, MppCodingType codec_t) +{ + Vdpu384aCtrlReg *ctrl_regs = ®s->ctrl_regs; + + switch (codec_t) { + case MPP_VIDEO_CodingAVC : { + ctrl_regs->reg8_dec_mode = 1; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xfffedfff; + ctrl_regs->reg21_cabac_error_en_highbits = 0x0ffbf9ff; + } break; + case MPP_VIDEO_CodingHEVC : { + ctrl_regs->reg8_dec_mode = 0; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffff; + ctrl_regs->reg21_cabac_error_en_highbits = 0x3ff3f9ff; + } break; + default : { + mpp_err("not support codec type %d\n", codec_t); + } break; + } + + ctrl_regs->reg9.low_latency_en = 0; + + ctrl_regs->reg10.strmd_auto_gating_e = 1; + ctrl_regs->reg10.inter_auto_gating_e = 1; + ctrl_regs->reg10.intra_auto_gating_e = 1; + ctrl_regs->reg10.transd_auto_gating_e = 1; + ctrl_regs->reg10.recon_auto_gating_e = 1; + ctrl_regs->reg10.filterd_auto_gating_e = 1; + ctrl_regs->reg10.bus_auto_gating_e = 1; + ctrl_regs->reg10.ctrl_auto_gating_e = 1; + ctrl_regs->reg10.rcb_auto_gating_e = 1; + ctrl_regs->reg10.err_prc_auto_gating_e = 1; + + ctrl_regs->reg11.rd_outstanding = 32; + ctrl_regs->reg11.wr_outstanding = 250; + + ctrl_regs->reg13_core_timeout_threshold = 0xffffff; + + ctrl_regs->reg16.error_proc_disable = 1; + ctrl_regs->reg16.error_spread_disable = 0; + ctrl_regs->reg16.roi_error_ctu_cal_en = 0; + + return; +} + +void vdpu384a_setup_statistic(Vdpu384aCtrlReg *ctrl_regs) +{ + ctrl_regs->reg28.axi_perf_work_e = 1; + ctrl_regs->reg28.axi_cnt_type = 1; + ctrl_regs->reg28.rd_latency_id = 11; + + ctrl_regs->reg29.addr_align_type = 1; + ctrl_regs->reg29.ar_cnt_id_type = 0; + ctrl_regs->reg29.aw_cnt_id_type = 1; + ctrl_regs->reg29.ar_count_id = 17; + ctrl_regs->reg29.aw_count_id = 0; + ctrl_regs->reg29.rd_band_width_mode = 0; + + /* set hurry */ + ctrl_regs->reg30.axi_wr_qos = 0; + ctrl_regs->reg30.axi_rd_qos = 0; +} + +void vdpu384a_update_thumbnail_frame_info(MppFrame frame) +{ + RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1; + RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1; + RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16); + RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16); + RK_U32 down_scale_buf_size = 0; + + if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) { + down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor); + down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1; + } + + down_scale_buf_size = down_scale_hor * down_scale_ver * 3 / 2; + /* + * no matter what format, scale down image will output as 8bit raster format; + */ + mpp_frame_set_fmt(frame, MPP_FMT_YUV420SP); + mpp_frame_set_width(frame, down_scale_width); + mpp_frame_set_height(frame, down_scale_height); + mpp_frame_set_hor_stride(frame, down_scale_hor); + mpp_frame_set_ver_stride(frame, down_scale_ver); + mpp_frame_set_buf_size(frame, down_scale_buf_size); +} + +void vdpu384a_setup_down_scale(MppFrame frame, MppDev dev, Vdpu384aCtrlReg *com, void* comParas) +{ + RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1; + RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1; + RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16); + RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16); + + Vdpu384aRegCommParas* paras = (Vdpu384aRegCommParas*)comParas; + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + MppMeta meta = mpp_frame_get_meta(frame); + RK_U32 down_scale_y_offset = 0; + RK_U32 down_scale_uv_offset = 0; + RK_U32 down_scale_y_virstride = down_scale_ver * down_scale_hor; + RK_U32 downscale_buf_size; + + if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) { + down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor); + down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1; + down_scale_y_virstride = down_scale_ver * down_scale_hor; + } + /* + * no matter what format, scale down image will output as 8bit raster format; + * down_scale image buffer size was already added to the buf_size of mpp_frame, + * which was calculated in mpp_buf_slot.cpp: (size = original_size + scaledown_size) + */ + switch ((fmt & MPP_FRAME_FMT_MASK)) { + case MPP_FMT_YUV400 : { + downscale_buf_size = down_scale_y_virstride; + } break; + case MPP_FMT_YUV420SP_10BIT : + case MPP_FMT_YUV420SP : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + case MPP_FMT_YUV422SP_10BIT : + case MPP_FMT_YUV422SP : { + downscale_buf_size = down_scale_y_virstride * 2; + } break; + case MPP_FMT_YUV444SP : { + downscale_buf_size = down_scale_y_virstride * 3; + } break; + default : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + } + downscale_buf_size = MPP_ALIGN(downscale_buf_size, 16); + + down_scale_y_offset = MPP_ALIGN((mpp_frame_get_buf_size(frame) - downscale_buf_size), 16); + down_scale_uv_offset = down_scale_y_offset + down_scale_y_virstride; + + com->reg9.scale_down_en = 1; + com->reg9.av1_fgs_en = 0; + paras->reg71_scl_ref_hor_virstride = down_scale_hor >> 4; + paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 4; + if ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP) + paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 3; + paras->reg73_scl_ref_virstride = down_scale_y_virstride >> 4; + if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_MIXED) { + mpp_dev_set_reg_offset(dev, 133, down_scale_y_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_Y_OFFSET, down_scale_y_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_UV_OFFSET, down_scale_uv_offset); + } +} + +#ifdef DUMP_VDPU384A_DATAS +RK_U32 dump_cur_frame = 0; +char dump_cur_dir[128]; +char dump_cur_fname_path[512]; + +MPP_RET flip_string(char *str) +{ + RK_U32 len = strlen(str); + RK_U32 i, j; + + for (i = 0, j = len - 1; i <= j; i++, j--) { + // swapping characters + char c = str[i]; + str[i] = str[j]; + str[j] = c; + } + + return MPP_OK; +} + +MPP_RET dump_data_to_file(char *fname_path, void *data, RK_U32 data_bit_size, + RK_U32 line_bits, RK_U32 big_end) +{ + RK_U8 *buf_p = (RK_U8 *)data; + RK_U8 cur_data; + RK_U32 i; + RK_U32 loop_cnt; + FILE *dump_fp = NULL; + char line_tmp[256]; + RK_U32 str_idx = 0; + + dump_fp = fopen(fname_path, "w+"); + if (!dump_fp) { + mpp_err_f("open file: %s error!\n", fname_path); + return MPP_NOK; + } + + if ((data_bit_size % 4 != 0) || (line_bits % 8 != 0)) { + mpp_err_f("line bits not align to 4!\n"); + return MPP_NOK; + } + + loop_cnt = data_bit_size / 8; + for (i = 0; i < loop_cnt; i++) { + cur_data = buf_p[i]; + + sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf); + if ((i * 8 + 4) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + sprintf(&line_tmp[str_idx++], "%0x", (cur_data >> 4) & 0xf); + if ((i * 8 + 8) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + } + + // last line + if (data_bit_size % 4) { + cur_data = buf_p[i]; + sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf); + if ((i * 8 + 8) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + } + if (data_bit_size % line_bits) { + loop_cnt = (line_bits - (data_bit_size % line_bits)) / 4; + for (i = 0; i < loop_cnt; i++) + sprintf(&line_tmp[str_idx++], "%0x", 0); + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + + fclose(dump_fp); + + return MPP_OK; +} +#endif diff --git a/mpp/hal/rkdec/common/vdpu38x_com.c b/mpp/hal/rkdec/common/vdpu38x_com.c new file mode 100644 index 000000000..0c58b800e --- /dev/null +++ b/mpp/hal/rkdec/common/vdpu38x_com.c @@ -0,0 +1,810 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpu38x_com" + +#include + +#include "mpp_log.h" +#include "mpp_buffer.h" +#include "mpp_common.h" +#include "mpp_compat_impl.h" +#include "mpp_frame_impl.h" + +#include "vdpu_com.h" +#include "vdpu38x_com.h" + +const RK_U32 vdpu38x_rcb_type2loc_map[RCB_BUF_CNT] = { + [RCB_STRMD_IN_ROW] = VDPU38X_RCB_IN_TILE_ROW, + [RCB_STRMD_ON_ROW] = VDPU38X_RCB_ON_TILE_ROW, + [RCB_INTER_IN_ROW] = VDPU38X_RCB_IN_TILE_ROW, + [RCB_INTER_ON_ROW] = VDPU38X_RCB_ON_TILE_ROW, + [RCB_INTRA_IN_ROW] = VDPU38X_RCB_IN_TILE_ROW, + [RCB_INTRA_ON_ROW] = VDPU38X_RCB_ON_TILE_ROW, + [RCB_FLTD_IN_ROW] = VDPU38X_RCB_IN_TILE_ROW, + [RCB_FLTD_PROT_IN_ROW] = VDPU38X_RCB_IN_TILE_ROW, + [RCB_FLTD_ON_ROW] = VDPU38X_RCB_ON_TILE_ROW, + [RCB_FLTD_ON_COL] = VDPU38X_RCB_ON_TILE_COL, + [RCB_FLTD_UPSC_ON_COL] = VDPU38X_RCB_ON_TILE_COL, +}; + +const RK_U32 vdpu38x_intra_uv_coef_map[MPP_HAL_FMT_BUTT] = { + [MPP_HAL_FMT_YUV400] = 1, + [MPP_HAL_FMT_YUV420] = 2, + [MPP_HAL_FMT_YUV422] = 2, + [MPP_HAL_FMT_YUV444] = 3, +}; + +const RK_U32 vdpu38x_filter_row_uv_coef_map[MPP_HAL_FMT_BUTT] = { + [MPP_HAL_FMT_YUV400] = 0, + [MPP_HAL_FMT_YUV420] = 1, + [MPP_HAL_FMT_YUV422] = 1, + [MPP_HAL_FMT_YUV444] = 3, +}; + +const RK_U32 vdpu38x_filter_col_uv_coef_map[MPP_HAL_FMT_BUTT] = { + [MPP_HAL_FMT_YUV400] = 0, + [MPP_HAL_FMT_YUV420] = 1, + [MPP_HAL_FMT_YUV422] = 3, + [MPP_HAL_FMT_YUV444] = 3, +}; + +MPP_RET vdpu38x_rcb_calc_init(Vdpu38xRcbCtx **ctx) +{ + Vdpu38xRcbCtx *p = NULL; + + p = (Vdpu38xRcbCtx *)mpp_calloc(Vdpu38xRcbCtx, 1); + if (!p) { + mpp_loge_f("malloc rcb ctx failed\n"); + return MPP_ERR_MALLOC; + } + p->tile_infos = (RcbTileInfo *)mpp_calloc(RcbTileInfo, 1); + if (!p) { + mpp_loge_f("malloc tile infos failed\n"); + return MPP_ERR_MALLOC; + } + p->tile_info_cap = 1; + p->fmt = MPP_HAL_FMT_BUTT; + *ctx = p; + + return MPP_OK; +} + +MPP_RET vdpu38x_rcb_calc_deinit(Vdpu38xRcbCtx *ctx) +{ + if (NULL != ctx) { + MPP_FREE(ctx->tile_infos); + MPP_FREE(ctx); + } + + return MPP_OK; +} + +MPP_RET vdpu38x_rcb_reset(Vdpu38xRcbCtx *ctx) +{ + ctx->pic_w = 0; + ctx->pic_h = 0; + /* tile info */ + ctx->tile_num = 0; + ctx->tile_dir = 0; + /* general */ + ctx->fmt = MPP_HAL_FMT_BUTT; + ctx->bit_depth = 0; + ctx->buf_sz = 0; + /* h264 */ + ctx->mbaff_flag = 0; + /* avs2 */ + ctx->alf_en = 0; + /* av1 */ + ctx->lr_en = 0; + ctx->upsc_en = 0; + + memset(ctx->buf_info, 0, sizeof(VdpuRcbInfo) * RCB_BUF_CNT); + + return MPP_OK; +} + +MPP_RET vdpu38x_rcb_add_tile_info(Vdpu38xRcbCtx *ctx, RcbTileInfo *tile_info) +{ + RcbTileInfo *tl_infos = NULL; + RcbTileInfo *p = NULL; + + tl_infos = ctx->tile_infos; + if (ctx->tile_num >= ctx->tile_info_cap) { + ctx->tile_info_cap += 4; + tl_infos = (RcbTileInfo *)mpp_realloc(tl_infos, RcbTileInfo, ctx->tile_info_cap); + if (!tl_infos) { + mpp_loge_f("realloc failed\n"); + return MPP_ERR_NOMEM; + } + ctx->tile_infos = tl_infos; + } + p = &tl_infos[ctx->tile_num++]; + memcpy(p, tile_info, sizeof(RcbTileInfo)); + + return MPP_OK; +} + +MPP_RET vdpu38x_rcb_dump_tile_info(Vdpu38xRcbCtx *ctx) +{ + RcbTileInfo *p = ctx->tile_infos; + RK_U32 i; + + for (i = 0; i < ctx->tile_num; i++) { + mpp_logi("tile %d: idx %d lt(%d,%d) w %d h %d\n", + i, p[i].idx, p[i].lt_x, p[i].lt_y, p[i].w, p[i].h); + } + + return MPP_OK; +} + +Vdpu38xFmt vdpu38x_fmt_mpp2hal(MppFrameFormat mpp_fmt) +{ + switch (mpp_fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV400 : { + return MPP_HAL_FMT_YUV400; + } break; + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_10BIT : + case MPP_FMT_YUV420P : + case MPP_FMT_YUV420SP_VU : { + return MPP_HAL_FMT_YUV420; + } break; + case MPP_FMT_YUV422SP : + case MPP_FMT_YUV422SP_10BIT : + case MPP_FMT_YUV422P : + case MPP_FMT_YUV422SP_VU : + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_YVYU : + case MPP_FMT_YUV422_UYVY : + case MPP_FMT_YUV422_VYUY : { + return MPP_HAL_FMT_YUV422; + } break; + case MPP_FMT_YUV444SP : + case MPP_FMT_YUV444P : + case MPP_FMT_YUV444SP_10BIT : { + return MPP_HAL_FMT_YUV444; + } break; + default : { + mpp_loge_f("hal format not support %d\n", mpp_fmt); + } break; + } + + return MPP_HAL_FMT_BUTT; +} + +#define VDPU38X_RCB_ACCESSORS(type, field) \ + type vdpu38x_rcb_get_##field(Vdpu38xRcbCtx *ctx) \ + { \ + return ((Vdpu38xRcbCtx*)ctx)->field; \ + } \ + void vdpu38x_rcb_set_##field(Vdpu38xRcbCtx *ctx, type v) \ + { \ + ((Vdpu38xRcbCtx*)ctx)->field = v; \ + } + +VDPU38X_RCB_ACCESSORS(RK_U32, pic_w) +VDPU38X_RCB_ACCESSORS(RK_U32, pic_h) +VDPU38X_RCB_ACCESSORS(RK_U32, tile_dir) +VDPU38X_RCB_ACCESSORS(Vdpu38xFmt, fmt) +VDPU38X_RCB_ACCESSORS(RK_U32, bit_depth) +VDPU38X_RCB_ACCESSORS(RK_U32, mbaff_flag) +VDPU38X_RCB_ACCESSORS(RK_U32, alf_en) +VDPU38X_RCB_ACCESSORS(RK_U32, lr_en) +VDPU38X_RCB_ACCESSORS(RK_U32, upsc_en) + +MPP_RET vdpu38x_rcb_get_len(Vdpu38xRcbCtx *ctx, Vdpu38xTileLoc loc, RK_U32 *len) +{ + RcbTileInfo *tile_p = NULL; + RK_U32 i = 0; + RK_U32 res = 0; + RK_U32 ret = MPP_OK; + + tile_p = ctx->tile_infos; + + if (loc == VDPU38X_RCB_IN_TILE_ROW) { + for (i = 0, res = 0; i < ctx->tile_num; i++) + res = res < tile_p[i].w ? tile_p[i].w : res; + } else if (loc == VDPU38X_RCB_IN_TILE_COL) { + mpp_loge_f("invalid tile loc %d\n", loc); + ret = MPP_NOK; + } else if (loc == VDPU38X_RCB_ON_TILE_ROW) { + res = ctx->pic_w; + } else if (loc == VDPU38X_RCB_ON_TILE_COL) { + if (ctx->tile_dir == 0) { /* left to right */ + for (i = 0, res = 0; i < ctx->tile_num; i++) + res = res < tile_p[i].h ? tile_p[i].h : res; + } else { /* top to bottom */ + res = ctx->pic_h; + } + } else { + mpp_loge_f("invalid tile loc %d\n", loc); + ret = MPP_NOK; + } + *len = res; + + return ret; +} + +MPP_RET vdpu38x_rcb_get_extra_size(Vdpu38xRcbCtx *ctx, Vdpu38xTileLoc loc, RK_U32 *extra_sz) +{ + RK_U32 tl_row_num = 0; + RK_U32 tl_col_num = 0; + RK_U32 buf_size = 0; + RK_U32 i; + + for (i = 0; i < ctx->tile_num; i++) { + if (ctx->tile_infos[i].lt_y == 0) + tl_row_num++; + if (ctx->tile_infos[i].lt_x == 0) + tl_col_num++; + } + + if (loc == VDPU38X_RCB_ON_TILE_ROW) + buf_size = (tl_row_num - 1) * 64; + else if (loc == VDPU38X_RCB_ON_TILE_COL) + buf_size = (tl_col_num - 1) * 64; + else + buf_size = 0; + + *extra_sz = buf_size; + + return MPP_OK; +} + +RK_U32 vdpu38x_rcb_reg_info_update(Vdpu38xRcbCtx *ctx, Vdpu38xRcbType type, RK_U32 idx, + RK_FLOAT sz) +{ + RK_U32 extra_sz = 0; + RK_U32 result = 0; + Vdpu38xTileLoc loc = vdpu38x_rcb_type2loc_map[type]; + + vdpu38x_rcb_get_extra_size(ctx, loc, &extra_sz); + result = MPP_RCB_BYTES(sz) + extra_sz; + ctx->buf_info[type].reg_idx = idx; + ctx->buf_info[type].offset = ctx->buf_sz; + ctx->buf_info[type].size = result; + ctx->buf_sz += result; + + return result; +} + +RK_U32 vdpu38x_rcb_get_total_size(Vdpu38xRcbCtx *ctx) +{ + return ctx->buf_sz; +} + +MPP_RET vdpu38x_rcb_register_calc_handle(Vdpu38xRcbCtx *ctx, Vdpu38xRcbCalc_f func) +{ + ctx->calc_func = func; + + return MPP_OK; +} + +MPP_RET vdpu38x_rcb_calc_exec(Vdpu38xRcbCtx *ctx, RK_U32 *total_sz) +{ + if (NULL == ctx->calc_func) { + mpp_logi("error: The compute function is not registered\n"); + return MPP_NOK; + } + + return ctx->calc_func(ctx, total_sz); +} + +void vdpu38x_setup_rcb(Vdpu38xRcbCtx *ctx, Vdpu38xRcbRegSet *regs, MppDev dev, + MppBuffer buf) +{ + VdpuRcbInfo *info = ctx->buf_info; + RK_U32 i; + + regs->strmd_in_row_off = mpp_buffer_get_fd(buf); + regs->strmd_on_row_off = mpp_buffer_get_fd(buf); + regs->inter_in_row_off = mpp_buffer_get_fd(buf); + regs->inter_on_row_off = mpp_buffer_get_fd(buf); + regs->intra_in_row_off = mpp_buffer_get_fd(buf); + regs->intra_on_row_off = mpp_buffer_get_fd(buf); + regs->fltd_in_row_off = mpp_buffer_get_fd(buf); + regs->fltd_prot_in_row_off = mpp_buffer_get_fd(buf); + regs->fltd_on_row_off = mpp_buffer_get_fd(buf); + regs->fltd_on_col_off = mpp_buffer_get_fd(buf); + regs->fltd_upsc_on_col_off = mpp_buffer_get_fd(buf); + + regs->strmd_in_row_len = info[RCB_STRMD_IN_ROW].size; + regs->strmd_on_row_len = info[RCB_STRMD_ON_ROW].size; + regs->inter_in_row_len = info[RCB_INTER_IN_ROW].size; + regs->inter_on_row_len = info[RCB_INTER_ON_ROW].size; + regs->intra_in_row_len = info[RCB_INTRA_IN_ROW].size; + regs->intra_on_row_len = info[RCB_INTRA_ON_ROW].size; + regs->fltd_in_row_len = info[RCB_FLTD_IN_ROW].size; + regs->fltd_prot_in_row_len = info[RCB_FLTD_PROT_IN_ROW].size; + regs->fltd_on_row_len = info[RCB_FLTD_ON_ROW].size; + regs->fltd_on_col_len = info[RCB_FLTD_ON_COL].size; + regs->fltd_upsc_on_col_len = info[RCB_FLTD_UPSC_ON_COL].size; + + for (i = 0; i < RCB_BUF_CNT; i++) { + if (info[i].offset) + mpp_dev_set_reg_offset(dev, info[i].reg_idx, info[i].offset); + } +} + +RK_S32 vdpu38x_rcb_set_info(Vdpu38xRcbCtx *ctx, MppDev dev) +{ + MppDevRcbInfoCfg rcb_cfg; + VdpuRcbSetMode set_rcb_mode = RCB_SET_BY_PRIORITY_MODE; + static const RK_U32 rcb_priority[RCB_BUF_CNT] = { + RCB_FLTD_IN_ROW, + RCB_INTER_IN_ROW, + RCB_INTRA_IN_ROW, + RCB_STRMD_IN_ROW, + RCB_INTER_ON_ROW, + RCB_INTRA_ON_ROW, + RCB_STRMD_ON_ROW, + RCB_FLTD_ON_ROW, + RCB_FLTD_ON_COL, + RCB_FLTD_UPSC_ON_COL, + RCB_FLTD_PROT_IN_ROW, + }; + RK_U32 i; + /* + * RCB_SET_BY_SIZE_SORT_MODE: by size sort + * RCB_SET_BY_PRIORITY_MODE: by priority + */ + + switch (set_rcb_mode) { + case RCB_SET_BY_SIZE_SORT_MODE : { + VdpuRcbInfo info[RCB_BUF_CNT]; + + memcpy(info, ctx->buf_info, sizeof(info)); + qsort(info, MPP_ARRAY_ELEMS(info), + sizeof(info[0]), vdpu_compare_rcb_size); + + for (i = 0; i < MPP_ARRAY_ELEMS(info); i++) { + rcb_cfg.reg_idx = info[i].reg_idx; + rcb_cfg.size = info[i].size; + if (rcb_cfg.size > 0) { + mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg); + } else + break; + } + } break; + case RCB_SET_BY_PRIORITY_MODE : { + VdpuRcbInfo *info = ctx->buf_info; + RK_U32 index = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(rcb_priority); i ++) { + index = rcb_priority[i]; + + rcb_cfg.reg_idx = info[index].reg_idx; + rcb_cfg.size = info[index].size; + if (rcb_cfg.size > 0) { + mpp_dev_ioctl(dev, MPP_DEV_RCB_INFO, &rcb_cfg); + } + } + } break; + default: + break; + } + + return 0; +} + +MPP_RET vdpu38x_rcb_dump_rcb_result(Vdpu38xRcbCtx *ctx) +{ + VdpuRcbInfo *info = ctx->buf_info; + static const char rcb_descs[RCB_BUF_CNT][32] = { + "RCB_STRMD_IN_ROW", + "RCB_STRMD_ON_ROW", + "RCB_INTER_IN_ROW", + "RCB_INTER_ON_ROW", + "RCB_INTRA_IN_ROW", + "RCB_INTRA_ON_ROW", + "RCB_FLTD_IN_ROW", + "RCB_FLTD_PROT_IN_ROW", + "RCB_FLTD_ON_ROW", + "RCB_FLTD_ON_COL", + "RCB_FLTD_UPSC_ON_COL", + }; + RK_U32 i; + + for (i = 0; i < RCB_BUF_CNT; i++) { + mpp_logi("rcb buf %2d: desc %-24s reg_idx %3d size %-8d offset %-4d\n", + i, rcb_descs[i], info[i].reg_idx, info[i].size, info[i].offset); + } + + return MPP_OK; +} + +MPP_RET vdpu38x_get_fbc_off(MppFrame mframe, RK_U32 *head_stride, RK_U32 *pld_stride, RK_U32 *pld_offset) +{ + if (!mframe) { + mpp_loge("mframe is null\n"); + return MPP_ERR_NULL_PTR; + } + + MppFrameFormat fmt; + RK_U32 fbc_unit_w = 0; + RK_U32 fbc_unit_h = 0; + RK_U32 bit_depth; + Vdpu38xFmt fmt_type; + static const RK_FLOAT fmt_coeff[MPP_HAL_FMT_BUTT] = {1, 1.5, 2, 3}; + RK_U32 ver_virstride = 0; + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbc_unit_bit_sz; + RK_U32 head_vir_w; // byte + RK_U32 pld_real_w; // byte + RK_U32 pld_vir_w; // byte + + ver_virstride = mpp_frame_get_ver_stride(mframe); + fmt = mpp_frame_get_fmt(mframe); + + if (MPP_FRAME_FMT_IS_AFBC(fmt)) { + fbc_unit_w = 32; + fbc_unit_h = 8; + } else if (MPP_FRAME_FMT_IS_RKFBC(fmt)) { + fbc_unit_w = 64; + fbc_unit_h = 4; + } + + bit_depth = MPP_FRAME_FMT_IS_YUV_10BIT(fmt) ? 10 : 8; + fmt_type = vdpu38x_fmt_mpp2hal(fmt); + + /* head stride */ + head_vir_w = MPP_ALIGN(fbc_hdr_stride, fbc_unit_w) / fbc_unit_w * 16; + *head_stride = head_vir_w >> 4; + + /* pld stride */ + fbc_unit_bit_sz = MPP_ALIGN((int)ceilf(fbc_unit_w * fbc_unit_h * fmt_coeff[fmt_type] * bit_depth), 128); + pld_real_w = fbc_hdr_stride / fbc_unit_w * fbc_unit_bit_sz >> 3; + pld_vir_w = MPP_ALIGN(pld_real_w, 16); + *pld_stride = pld_vir_w >> 4; + + /* pld offset*/ + *pld_offset = head_vir_w * (MPP_ALIGN(ver_virstride, fbc_unit_h) / fbc_unit_h); + + return MPP_OK; +} + +MPP_RET vdpu38x_get_tile4x4_h_stride_coeff(MppFrameFormat fmt, RK_U32 *coeff) +{ + RK_U32 val = 0; + MPP_RET ret = MPP_OK; + + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV400 : { + val = 4; + } break; + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_10BIT : + case MPP_FMT_YUV420P : + case MPP_FMT_YUV420SP_VU : { + val = 6; + } break; + case MPP_FMT_YUV422SP: + case MPP_FMT_YUV422SP_10BIT: + case MPP_FMT_YUV422P : + case MPP_FMT_YUV422SP_VU : + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_YVYU : + case MPP_FMT_YUV422_UYVY : + case MPP_FMT_YUV422_VYUY : { + val = 8; + } break; + case MPP_FMT_YUV444SP : + case MPP_FMT_YUV444P : + case MPP_FMT_YUV444SP_10BIT : { + val = 12; + } break; + default : { + mpp_err_f("format not support %d\n", fmt); + ret = MPP_NOK; + } break; + } + + *coeff = val; + + return ret; +} + +void vdpu384b_init_ctrl_regs(Vdpu38xRegSet *regs, MppCodingType codec_t) +{ + Vdpu38xCtrlReg *ctrl_regs = ®s->ctrl_regs; + + switch (codec_t) { + case MPP_VIDEO_CodingAVC : { + ctrl_regs->reg8_dec_mode = 1; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffff; + ctrl_regs->reg21_cabac_error_en_highbits = 0xfff3ffff; + } break; + case MPP_VIDEO_CodingHEVC : { + ctrl_regs->reg8_dec_mode = 0; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffdfff; + ctrl_regs->reg21_cabac_error_en_highbits = 0xfffbf9ff; + } break; + case MPP_VIDEO_CodingAVS2 : { + ctrl_regs->reg8_dec_mode = 3; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffdf; + ctrl_regs->reg21_cabac_error_en_highbits = 0xffffffff; + } break; + case MPP_VIDEO_CodingVP9 : { + ctrl_regs->reg8_dec_mode = 2; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffff; + ctrl_regs->reg21_cabac_error_en_highbits = 0xffffffff; + } break; + case MPP_VIDEO_CodingAV1 : { + ctrl_regs->reg8_dec_mode = 4; + ctrl_regs->reg20_cabac_error_en_lowbits = 0xffffffff; + ctrl_regs->reg21_cabac_error_en_highbits = 0xffffffff; + } break; + default : { + mpp_err("not support codec type %d\n", codec_t); + } break; + } + + ctrl_regs->reg9.collect_info_dis = 1; + + ctrl_regs->reg10.strmd_auto_gating_dis = 0; + ctrl_regs->reg10.inter_auto_gating_dis = 0; + ctrl_regs->reg10.intra_auto_gating_dis = 0; + ctrl_regs->reg10.transd_auto_gating_dis = 0; + ctrl_regs->reg10.recon_auto_gating_dis = 0; + ctrl_regs->reg10.filterd_auto_gating_dis = 0; + ctrl_regs->reg10.bus_auto_gating_dis = 0; + ctrl_regs->reg10.ctrl_auto_gating_dis = 0; + ctrl_regs->reg10.rcb_auto_gating_dis = 0; + ctrl_regs->reg10.err_prc_auto_gating_dis = 0; + ctrl_regs->reg10.cache_auto_gating_dis = 0; + + ctrl_regs->reg11.rd_outstanding = 32; + ctrl_regs->reg11.wr_outstanding = 250; + + ctrl_regs->reg13_core_timeout_threshold = 0xffffff; + + ctrl_regs->reg16.error_proc_disable = 1; + ctrl_regs->reg16.error_spread_disable = 0; + ctrl_regs->reg16.roi_error_ctu_cal_en = 0; + + return; +} + +void vdpu38x_setup_statistic(Vdpu38xCtrlReg *ctrl_regs) +{ + ctrl_regs->reg28.axi_perf_work_e = 1; + ctrl_regs->reg28.axi_cnt_type = 1; + ctrl_regs->reg28.rd_latency_id = 11; + + ctrl_regs->reg29.addr_align_type = 1; + ctrl_regs->reg29.ar_cnt_id_type = 0; + ctrl_regs->reg29.aw_cnt_id_type = 1; + ctrl_regs->reg29.ar_count_id = 17; + ctrl_regs->reg29.aw_count_id = 0; + ctrl_regs->reg29.rd_band_width_mode = 0; + + /* set hurry */ + ctrl_regs->reg30.axi_wr_qos = 0; + ctrl_regs->reg30.axi_rd_qos = 0; +} + +void vdpu38x_update_thumbnail_frame_info(MppFrame frame) +{ + RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1; + RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1; + RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16); + RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16); + RK_U32 down_scale_buf_size = 0; + + if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) { + down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor); + down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1; + } + + down_scale_buf_size = down_scale_hor * down_scale_ver * 3 / 2; + /* + * no matter what format, scale down image will output as 8bit raster format; + */ + mpp_frame_set_fmt(frame, MPP_FMT_YUV420SP); + mpp_frame_set_width(frame, down_scale_width); + mpp_frame_set_height(frame, down_scale_height); + mpp_frame_set_hor_stride(frame, down_scale_hor); + mpp_frame_set_ver_stride(frame, down_scale_ver); + mpp_frame_set_buf_size(frame, down_scale_buf_size); +} + +void vdpu38x_setup_down_scale(MppFrame frame, MppDev dev, Vdpu38xCtrlReg *com, void* comParas) +{ + RK_U32 down_scale_height = mpp_frame_get_height(frame) >> 1; + RK_U32 down_scale_width = mpp_frame_get_width(frame) >> 1; + RK_U32 down_scale_ver = MPP_ALIGN(down_scale_height, 16); + RK_U32 down_scale_hor = MPP_ALIGN(down_scale_width, 16); + + Vdpu38xRegCommParas* paras = (Vdpu38xRegCommParas*)comParas; + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + MppMeta meta = mpp_frame_get_meta(frame); + RK_U32 down_scale_y_offset = 0; + RK_U32 down_scale_uv_offset = 0; + RK_U32 down_scale_y_virstride = down_scale_ver * down_scale_hor; + RK_U32 downscale_buf_size; + + if (!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(frame))) { + down_scale_hor = mpp_align_128_odd_plus_64(down_scale_hor); + down_scale_ver = mpp_frame_get_ver_stride(frame) >> 1; + down_scale_y_virstride = down_scale_ver * down_scale_hor; + } + /* + * no matter what format, scale down image will output as 8bit raster format; + * down_scale image buffer size was already added to the buf_size of mpp_frame, + * which was calculated in mpp_buf_slot.cpp: (size = original_size + scaledown_size) + */ + switch ((fmt & MPP_FRAME_FMT_MASK)) { + case MPP_FMT_YUV400 : { + downscale_buf_size = down_scale_y_virstride; + } break; + case MPP_FMT_YUV420SP_10BIT : + case MPP_FMT_YUV420SP : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + case MPP_FMT_YUV422SP_10BIT : + case MPP_FMT_YUV422SP : { + downscale_buf_size = down_scale_y_virstride * 2; + } break; + case MPP_FMT_YUV444SP : { + downscale_buf_size = down_scale_y_virstride * 3; + } break; + default : { + downscale_buf_size = down_scale_y_virstride * 3 / 2; + } break; + } + downscale_buf_size = MPP_ALIGN(downscale_buf_size, 16); + + down_scale_y_offset = MPP_ALIGN((mpp_frame_get_buf_size(frame) - downscale_buf_size), 16); + down_scale_uv_offset = down_scale_y_offset + down_scale_y_virstride; + + com->reg9.scale_down_en = 1; + com->reg9.av1_fgs_en = 0; + paras->reg71_scl_ref_hor_virstride = down_scale_hor >> 4; + paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 4; + if ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV444SP) + paras->reg72_scl_ref_raster_uv_hor_virstride = down_scale_hor >> 3; + paras->reg73_scl_ref_virstride = down_scale_y_virstride >> 4; + if (mpp_frame_get_thumbnail_en(frame) == MPP_FRAME_THUMBNAIL_MIXED) { + mpp_dev_set_reg_offset(dev, 133, down_scale_y_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_Y_OFFSET, down_scale_y_offset); + mpp_meta_set_s32(meta, KEY_DEC_TBN_UV_OFFSET, down_scale_uv_offset); + } +} + +MPP_RET vdpu38x_setup_scale_origin_bufs(MppFrame mframe, HalBufs *org_bufs, RK_S32 max_cnt) +{ + /* for 8K FrameBuf scale mode */ + size_t origin_buf_size = 0; + + origin_buf_size = mpp_frame_get_buf_size(mframe); + + if (!origin_buf_size) { + mpp_err_f("origin_bufs get buf size failed\n"); + return MPP_NOK; + } + if (*org_bufs) { + hal_bufs_deinit(*org_bufs); + *org_bufs = NULL; + } + hal_bufs_init(org_bufs); + if (!(*org_bufs)) { + mpp_err_f("org_bufs init fail\n"); + return MPP_ERR_NOMEM; + } + hal_bufs_setup(*org_bufs, max_cnt > 0 ? max_cnt : 16, 1, &origin_buf_size); + + return MPP_OK; +} + +RK_S32 hal_h265d_avs2d_calc_mv_size(RK_S32 pic_w, RK_S32 pic_h, RK_S32 ctu_w) +{ + RK_S32 seg_w = 64 * 16 * 16 / ctu_w; // colmv_block_size = 16, colmv_per_bytes = 16 + RK_S32 seg_cnt_w = MPP_ALIGN(pic_w, seg_w) / seg_w; + RK_S32 seg_cnt_h = MPP_ALIGN(pic_h, ctu_w) / ctu_w; + RK_S32 mv_size = seg_cnt_w * seg_cnt_h * 64 * 16; + + return mv_size; +} + +#ifdef DUMP_VDPU38X_DATAS +RK_U32 vdpu38x_dump_cur_frm = 0; +char vdpu38x_dump_cur_dir[128]; +char vdpu38x_dump_cur_fname_path[512]; + +MPP_RET vdpu38x_flip_string(char *str) +{ + RK_U32 len = strlen(str); + RK_U32 i, j; + + for (i = 0, j = len - 1; i <= j; i++, j--) { + // swapping characters + char c = str[i]; + str[i] = str[j]; + str[j] = c; + } + + return MPP_OK; +} + +MPP_RET vdpu38x_dump_data_to_file(char *fname_path, void *data, RK_U32 data_bit_size, + RK_U32 line_bits, RK_U32 big_end, RK_U32 append) +{ + RK_U8 *buf_p = (RK_U8 *)data; + RK_U8 cur_data; + RK_U32 i; + RK_U32 loop_cnt; + FILE *dump_fp = NULL; + char line_tmp[256]; + RK_U32 str_idx = 0; + + if (append) + dump_fp = fopen(fname_path, "aw+"); + else + dump_fp = fopen(fname_path, "w+"); + if (!dump_fp) { + mpp_err_f("open file: %s error!\n", fname_path); + return MPP_NOK; + } + if (append) + fseek(dump_fp, 0, SEEK_END); + + if ((data_bit_size % 4 != 0) || (line_bits % 8 != 0)) { + mpp_err_f("line bits not align to 4! data_bit_size: %d line_bits: %d\n", + data_bit_size, line_bits); + return MPP_NOK; + } + + loop_cnt = data_bit_size / 8; + for (i = 0; i < loop_cnt; i++) { + cur_data = buf_p[i]; + + sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf); + if ((i * 8 + 4) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + vdpu38x_flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + sprintf(&line_tmp[str_idx++], "%0x", (cur_data >> 4) & 0xf); + if ((i * 8 + 8) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + vdpu38x_flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + } + + // last line + if (data_bit_size % 4) { + cur_data = buf_p[i]; + sprintf(&line_tmp[str_idx++], "%0x", cur_data & 0xf); + if ((i * 8 + 8) % line_bits == 0) { + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + vdpu38x_flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + } + if (data_bit_size % line_bits) { + loop_cnt = (line_bits - (data_bit_size % line_bits)) / 4; + for (i = 0; i < loop_cnt; i++) + sprintf(&line_tmp[str_idx++], "%0x", 0); + line_tmp[str_idx++] = '\0'; + str_idx = 0; + if (!big_end) + vdpu38x_flip_string(line_tmp); + fprintf(dump_fp, "%s\n", line_tmp); + } + + fflush(dump_fp); + fclose(dump_fp); + + return MPP_OK; +} +#endif diff --git a/mpp/hal/rkdec/common/vdpu_com.c b/mpp/hal/rkdec/common/vdpu_com.c new file mode 100644 index 000000000..357d5f78e --- /dev/null +++ b/mpp/hal/rkdec/common/vdpu_com.c @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpu_comm" + +#include "mpp_common.h" +#include "mpp_compat_impl.h" +#include "vdpu_com.h" + +RK_S32 vdpu_compare_rcb_size(const void *a, const void *b) +{ + VdpuRcbInfo *p0 = (VdpuRcbInfo *)a; + VdpuRcbInfo *p1 = (VdpuRcbInfo *)b; + + return (p0->size > p1->size) ? -1 : 1; +} + +void vdpu_afbc_align_calc(MppBufSlots slots, MppFrame frame, RK_U32 expand) +{ + RK_U32 ver_stride = 0; + RK_U32 img_height = mpp_frame_get_height(frame); + RK_U32 img_width = mpp_frame_get_width(frame); + RK_U32 hdr_stride = (*compat_ext_fbc_hdr_256_odd) ? + (MPP_ALIGN(img_width, 256) | 256) : + (MPP_ALIGN(img_width, 64)); + + mpp_slots_set_prop(slots, SLOTS_HOR_ALIGN, mpp_align_64); + mpp_slots_set_prop(slots, SLOTS_VER_ALIGN, mpp_align_16); + + mpp_frame_set_fbc_hdr_stride(frame, hdr_stride); + + ver_stride = mpp_align_16(img_height); + if (*compat_ext_fbc_buf_size) { + ver_stride += expand; + } + mpp_frame_set_ver_stride(frame, ver_stride); +} diff --git a/mpp/hal/rkdec/h264d/CMakeLists.txt b/mpp/hal/rkdec/h264d/CMakeLists.txt index e3dd6eedd..6ca7bfad6 100644 --- a/mpp/hal/rkdec/h264d/CMakeLists.txt +++ b/mpp/hal/rkdec/h264d/CMakeLists.txt @@ -1,36 +1,20 @@ # vim: syntax=cmake -# hal h264 decoder api -set(HAL_H264D_API - ../../inc/hal_h264d_api.h - - ) - - -# hal h264 header -set(HAL_H264D_HDR - hal_h264d_global.h - hal_h264d_reg.h - hal_h264d_fifo.h - hal_h264d_packet.h - ) - # hal h264 decoder sourse set(HAL_H264D_SRC - hal_h264d_api.c - hal_h264d_reg.c - hal_h264d_fifo.c - hal_h264d_packet.c - - ) - -add_library(hal_h264d STATIC - ${HAL_H264D_API} - ${HAL_H264D_HDR} - ${HAL_H264D_SRC} - ) -target_link_libraries(hal_h264d - mpp - ) -set_target_properties(hal_h264d PROPERTIES FOLDER "mpp/hal") + hal_h264d_com.c + hal_h264d_vdpu_com.c + ) + +add_hal_source(HAL_H264D_SRC HAVE_VDPU2 hal_h264d_vdpu2.c) +add_hal_source(HAL_H264D_SRC HAVE_VDPU1 hal_h264d_vdpu1.c) +add_hal_source(HAL_H264D_SRC HAVE_VDPU341 hal_h264d_rkv_reg.c) +add_hal_source(HAL_H264D_SRC HAVE_VDPU34X hal_h264d_vdpu34x.c) +add_hal_source(HAL_H264D_SRC HAVE_VDPU382 hal_h264d_vdpu382.c) +add_hal_source(HAL_H264D_SRC HAVE_VDPU383 hal_h264d_vdpu383.c) +add_hal_source(HAL_H264D_SRC HAVE_VDPU384A hal_h264d_vdpu384a.c) +add_hal_source(HAL_H264D_SRC HAVE_VDPU384B hal_h264d_vdpu384b.c) +if (HAL_H264D_SRC) + add_library(hal_h264d_api OBJECT ${HAL_H264D_SRC}) +endif() diff --git a/mpp/hal/rkdec/h264d/hal_h264d_api.c b/mpp/hal/rkdec/h264d/hal_h264d_api.c deleted file mode 100644 index a3529f368..000000000 --- a/mpp/hal/rkdec/h264d/hal_h264d_api.c +++ /dev/null @@ -1,368 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#include -#include -#include - -#include "rk_type.h" -#include "mpp_log.h" -#include "mpp_err.h" -#include "mpp_mem.h" - -#include "dxva_syntax.h" -#include "h264d_syntax.h" -#include "h264d_log.h" - -#include "hal_h264d_global.h" -#include "hal_h264d_reg.h" -#include "hal_h264d_packet.h" -#include "hal_h264d_api.h" - - - -#define MODULE_TAG "hal_h264d_api" - - - -static void close_log_files(LogEnv_t *env) -{ - FCLOSE(env->fp_driver); - FCLOSE(env->fp_syn_hal); - FCLOSE(env->fp_run_hal); -} - -static MPP_RET open_log_files(LogEnv_t *env, LogFlag_t *pflag) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - char fname[128] = { 0 }; - - INP_CHECK(ret, ctx, !pflag->write_en); - set_log_outpath(env); - //!< runlog file - if (GetBitVal(env->ctrl, LOG_DEBUG)) { - sprintf(fname, "%s/h264d_hal_runlog.dat", env->outpath); - FLE_CHECK(ret, env->fp_run_hal = fopen(fname, "wb")); - } - //!< fpga drive file - if (GetBitVal(env->ctrl, LOG_FPGA)) { - sprintf(fname, "%s/h264d_driver_data.dat", env->outpath); - FLE_CHECK(ret, env->fp_driver = fopen(fname, "wb")); - } - //!< write syntax - if ( GetBitVal(env->ctrl, LOG_WRITE_SPSPPS ) - || GetBitVal(env->ctrl, LOG_WRITE_RPS ) - || GetBitVal(env->ctrl, LOG_WRITE_SCANLIST) - || GetBitVal(env->ctrl, LOG_WRITE_STEAM ) - || GetBitVal(env->ctrl, LOG_WRITE_REG ) ) { - sprintf(fname, "%s/h264d_write_syntax.dat", env->outpath); - FLE_CHECK(ret, env->fp_syn_hal = fopen(fname, "wb")); - } - -__RETURN: - return MPP_OK; - -__FAILED: - return ret; -} - -static MPP_RET logctx_deinit(H264dLogCtx_t *logctx) -{ - close_log_files(&logctx->env); - - return MPP_OK; -} - -static MPP_RET logctx_init(H264dLogCtx_t *logctx, LogCtx_t *logbuf) -{ - RK_U8 i = 0; - MPP_RET ret = MPP_ERR_UNKNOW; - LogCtx_t *pcur = NULL; - - FUN_CHECK(ret = get_logenv(&logctx->env)); - - FUN_CHECK(ret = explain_ctrl_flag(logctx->env.ctrl, &logctx->log_flag)); - if ( !logctx->log_flag.debug_en - && !logctx->log_flag.print_en && !logctx->log_flag.write_en ) { - logctx->log_flag.debug_en = 0; - goto __RETURN; - } - logctx->log_flag.level = (1 << logctx->env.level) - 1; - //!< open file - FUN_CHECK(ret = open_log_files(&logctx->env, &logctx->log_flag)); - //!< set logctx - while (i < LOG_MAX) { - if (GetBitVal(logctx->env.ctrl, i)) { - pcur = logctx->parr[i] = &logbuf[i]; - pcur->tag = logctrl_name[i]; - pcur->flag = &logctx->log_flag; - - switch (i) { - case LOG_FPGA: - pcur->fp = logctx->env.fp_driver; - break; - case RUN_HAL: - pcur->fp = logctx->env.fp_run_hal; - break; - case LOG_WRITE_SPSPPS: - case LOG_WRITE_RPS: - case LOG_WRITE_SCANLIST: - case LOG_WRITE_STEAM: - case LOG_WRITE_REG: - pcur->fp = logctx->env.fp_syn_hal; - default: - break; - } - } - i++; - } -__RETURN: - return ret = MPP_OK; -__FAILED: - logctx->log_flag.debug_en = 0; - logctx_deinit(logctx); - - return ret; -} - - -/*! -*********************************************************************** -* \brief -* init -*********************************************************************** -*/ -//extern "C" -MPP_RET hal_h264d_init(void *hal, MppHalCfg *cfg) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - memset(p_hal, 0, sizeof(H264dHalCtx_t)); - //!< init logctx - FUN_CHECK(ret = logctx_init(&p_hal->logctx, p_hal->logctxbuf)); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - p_hal->mem = mpp_calloc(H264dHalMem_t, 1); - MEM_CHECK(ret, p_hal->mem); - p_hal->regs = &p_hal->mem->regs; - p_hal->mmu_regs = &p_hal->mem->mmu_regs; - p_hal->cache_regs = &p_hal->mem->cache_regs; - p_hal->pkts = &p_hal->mem->pkts; - FUN_CHECK(ret = alloc_fifo_packet(&p_hal->logctx, p_hal->pkts)); - - FunctionOut(p_hal->logctx.parr[RUN_HAL]); - (void)cfg; -__RETURN: - return MPP_OK; -__FAILED: - hal_h264d_deinit(hal); - - return ret; -} -/*! -*********************************************************************** -* \brief -* deinit -*********************************************************************** -*/ -//extern "C" -MPP_RET hal_h264d_deinit(void *hal) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - - free_fifo_packet(p_hal->pkts); - mpp_free(p_hal->mem); - - FunctionOut(p_hal->logctx.parr[RUN_HAL]); - logctx_deinit(&p_hal->logctx); -__RETURN: - return ret = MPP_OK; -} -/*! -*********************************************************************** -* \brief -* generate register -*********************************************************************** -*/ -//extern "C" -MPP_RET hal_h264d_gen_regs(void *hal, HalTask *task) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - - explain_input_buffer(hal, &task->dec); - prepare_spspps_packet(hal, &p_hal->pkts->spspps); - prepare_framerps_packet(hal, &p_hal->pkts->rps); - prepare_scanlist_packet(hal, &p_hal->pkts->scanlist); - prepare_stream_packet(hal, &p_hal->pkts->strm); - generate_regs(p_hal, &p_hal->pkts->reg); - - mpp_log("++++++++++ hal_h264_decoder, g_framecnt=%d \n", p_hal->g_framecnt++); - ((HalDecTask*)&task->dec)->valid = 0; - FunctionOut(p_hal->logctx.parr[RUN_HAL]); - -__RETURN: - return ret = MPP_OK; -} -/*! -*********************************************************************** -* \brief h -* start hard -*********************************************************************** -*/ -//extern "C" - -MPP_RET hal_h264d_start(void *hal, HalTask *task) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - - - - - - FunctionOut(p_hal->logctx.parr[RUN_HAL]); - (void)task; -__RETURN: - return ret = MPP_OK; -} -/*! -*********************************************************************** -* \brief -* wait hard -*********************************************************************** -*/ -//extern "C" -MPP_RET hal_h264d_wait(void *hal, HalTask *task) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - - - - - - FunctionOut(p_hal->logctx.parr[RUN_HAL]); - (void)task; -__RETURN: - return ret = MPP_OK; -} -/*! -*********************************************************************** -* \brief -* reset -*********************************************************************** -*/ -//extern "C" -MPP_RET hal_h264d_reset(void *hal) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - - memset(&p_hal->regs, 0, sizeof(H264_REGS_t)); - memset(&p_hal->mmu_regs, 0, sizeof(H264_MMU_t)); - memset(&p_hal->cache_regs, 0, sizeof(H264_CACHE_t)); - reset_fifo_packet(p_hal->pkts); - - FunctionOut(p_hal->logctx.parr[RUN_HAL]); -__RETURN: - return ret = MPP_OK; -} -/*! -*********************************************************************** -* \brief -* flush -*********************************************************************** -*/ -//extern "C" -MPP_RET hal_h264d_flush(void *hal) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - - - - - - FunctionOut(p_hal->logctx.parr[RUN_HAL]); -__RETURN: - return ret = MPP_OK; -} -/*! -*********************************************************************** -* \brief -* control -*********************************************************************** -*/ -//extern "C" -MPP_RET hal_h264d_control(void *hal, RK_S32 cmd_type, void *param) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - INP_CHECK(ret, ctx, NULL == p_hal); - FunctionIn(p_hal->logctx.parr[RUN_HAL]); - - - - - - FunctionOut(p_hal->logctx.parr[RUN_HAL]); - (void)hal; - (void)cmd_type; - (void)param; -__RETURN: - return ret = MPP_OK; -} - -const MppHalApi hal_api_h264d = { - "h264d_rkdec", - MPP_CTX_DEC, - MPP_VIDEO_CodingAVC, - sizeof(H264dHalCtx_t), - 0, - hal_h264d_init, - hal_h264d_deinit, - hal_h264d_gen_regs, - hal_h264d_start, - hal_h264d_wait, - hal_h264d_reset, - hal_h264d_flush, - hal_h264d_control, -}; - diff --git a/mpp/hal/rkdec/h264d/hal_h264d_com.c b/mpp/hal/rkdec/h264d/hal_h264d_com.c new file mode 100644 index 000000000..3bb34d79e --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_com.c @@ -0,0 +1,590 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_264d_com" + +#include "mpp_platform.h" +#include "mpp_bitput.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_ctx.h" +#include "hal_h264d_com.h" +#include "vdpu38x_com.h" + +const RK_U32 rkv_cabac_table[928] = { + 0x3602f114, 0xf1144a03, 0x4a033602, 0x68e97fe4, 0x36ff35fa, 0x21173307, + 0x00150217, 0x31000901, 0x390576db, 0x41f54ef3, 0x310c3e01, 0x321149fc, + 0x2b094012, 0x431a001d, 0x68095a10, 0x68ec7fd2, 0x4ef34301, 0x3e0141f5, + 0x5fef56fa, 0x2d093dfa, 0x51fa45fd, 0x370660f5, 0x56fb4307, 0x3a005802, + 0x5ef64cfd, 0x45043605, 0x580051fd, 0x4afb43f9, 0x50fb4afc, 0x3a0148f9, + 0x3f002900, 0x3f003f00, 0x560453f7, 0x48f96100, 0x3e03290d, 0x4efc2d00, + 0x7ee560fd, 0x65e762e4, 0x52e443e9, 0x53f05eec, 0x5beb6eea, 0x5df366ee, + 0x5cf97fe3, 0x60f959fb, 0x2efd6cf3, 0x39ff41ff, 0x4afd5df7, 0x57f85cf7, + 0x36057ee9, 0x3b063c06, 0x30ff4506, 0x45fc4400, 0x55fe58f8, 0x4bff4efa, + 0x36024df9, 0x44fd3205, 0x2a063201, 0x3f0151fc, 0x430046fc, 0x4cfe3902, + 0x4004230b, 0x230b3d01, 0x180c1912, 0x240d1d0d, 0x49f95df6, 0x2e0d49fe, + 0x64f93109, 0x35023509, 0x3dfe3505, 0x38003800, 0x3cfb3ff3, 0x39043eff, + 0x390445fa, 0x3304270e, 0x4003440d, 0x3f093d01, 0x27103207, 0x34042c05, + 0x3cfb300b, 0x3b003bff, 0x2c052116, 0x4eff2b0e, 0x45093c00, 0x28021c0b, + 0x31002c03, 0x2c022e00, 0x2f003302, 0x3e022704, 0x36002e06, 0x3a023603, + 0x33063f04, 0x35073906, 0x37063406, 0x240e2d0b, 0x52ff3508, 0x4efd3707, + 0x1f162e0f, 0x071954ff, 0x031cf91e, 0x0020041c, 0x061eff22, 0x0920061e, + 0x1b1a131f, 0x14251e1a, 0x4611221c, 0x3b054301, 0x1e104309, 0x23122012, + 0x1f181d16, 0x2b122617, 0x3f0b2914, 0x40093b09, 0x59fe5eff, 0x4cfa6cf7, + 0x2d002cfe, 0x40fd3400, 0x46fc3bfe, 0x52f84bfc, 0x4df766ef, 0x2a001803, + 0x37003000, 0x47f93bfa, 0x57f553f4, 0x3a0177e2, 0x24ff1dfd, 0x2b022601, + 0x3a0037fa, 0x4afd4000, 0x46005af6, 0x1f051dfc, 0x3b012a07, 0x48fd3afe, + 0x61f551fd, 0x05083a00, 0x120e0e0a, 0x28021b0d, 0x46fd3a00, 0x55f84ffa, + 0x6af30000, 0x57f66af0, 0x6eee72eb, 0x6eea62f2, 0x67ee6aeb, 0x6ce96beb, + 0x60f670e6, 0x5bfb5ff4, 0x5eea5df7, 0x430956fb, 0x55f650fc, 0x3c0746ff, + 0x3d053a09, 0x320f320c, 0x36113112, 0x2e07290a, 0x310733ff, 0x29093408, + 0x37022f06, 0x2c0a290d, 0x35053206, 0x3f04310d, 0x45fe4006, 0x46063bfe, + 0x1f092c0a, 0x35032b0c, 0x260a220e, 0x280d34fd, 0x2c072011, 0x320d2607, + 0x2b1a390a, 0x0e0b0b0e, 0x0b120b09, 0xfe170915, 0xf120f120, 0xe927eb22, + 0xe129df2a, 0xf426e42e, 0xe82d1d15, 0xe630d335, 0xed2bd541, 0x091ef627, + 0x1b141a12, 0x52f23900, 0x61ed4bfb, 0x001b7ddd, 0xfc1f001c, 0x0822061b, + 0x16180a1e, 0x20161321, 0x29151f1a, 0x2f172c1a, 0x470e4110, 0x3f063c08, + 0x18154111, 0x171a1417, 0x171c201b, 0x2817181c, 0x1d1c2018, 0x39132a17, + 0x3d163516, 0x280c560b, 0x3b0e330b, 0x47f94ffc, 0x46f745fb, 0x44f642f8, + 0x45f449ed, 0x43f146f0, 0x46ed3eec, 0x41ea42f0, 0xfe093fec, 0xf721f71a, + 0xfe29f927, 0x0931032d, 0x3b241b2d, 0x23f942fa, 0x2df82af9, 0x38f430fb, + 0x3efb3cfa, 0x4cf842f8, 0x51fa55fb, 0x51f94df6, 0x49ee50ef, 0x53f64afc, + 0x43f747f7, 0x42f83dff, 0x3b0042f2, 0xf3153b02, 0xf927f221, 0x0233fe2e, + 0x113d063c, 0x3e2a2237, 0x00000000, 0x00000000, 0x3602f114, 0xf1144a03, + 0x4a033602, 0x68e97fe4, 0x36ff35fa, 0x19163307, 0x00100022, 0x290409fe, + 0x410276e3, 0x4ff347fa, 0x32093405, 0x360a46fd, 0x1613221a, 0x02390028, + 0x451a2429, 0x65f17fd3, 0x47fa4cfc, 0x34054ff3, 0x5af34506, 0x2b083400, + 0x52fb45fe, 0x3b0260f6, 0x57fd4b02, 0x380164fd, 0x55fa4afd, 0x51fd3b00, + 0x5ffb56f9, 0x4dff42ff, 0x56fe4601, 0x3d0048fb, 0x3f002900, 0x3f003f00, + 0x560453f7, 0x48f96100, 0x3e03290d, 0x33070f0d, 0x7fd95002, 0x60ef5bee, + 0x62dd51e6, 0x61e966e8, 0x63e877e5, 0x66ee6eeb, 0x50007fdc, 0x5ef959fb, + 0x27005cfc, 0x54f14100, 0x49fe7fdd, 0x5bf768f4, 0x37037fe1, 0x37073807, + 0x35fd3d08, 0x4af94400, 0x67f358f7, 0x59f75bf3, 0x4cf85cf2, 0x6ee957f4, + 0x4ef669e8, 0x63ef70ec, 0x7fba7fb2, 0x7fd27fce, 0x4efb42fc, 0x48f847fc, + 0x37ff3b02, 0x4bfa46f9, 0x77de59f8, 0x14204bfd, 0x7fd4161e, 0x3dfb3600, + 0x3cff3a00, 0x43f83dfd, 0x4af254e7, 0x340541fb, 0x3d003902, 0x46f545f7, + 0x47fc3712, 0x3d073a00, 0x19122909, 0x2b052009, 0x2c002f09, 0x2e023300, + 0x42fc2613, 0x2a0c260f, 0x59002209, 0x1c0a2d04, 0xf5211f0a, 0x0f12d534, + 0xea23001c, 0x0022e726, 0xf420ee27, 0x0000a266, 0xfc21f138, 0xfb250a1d, + 0xf727e333, 0xc645de34, 0xfb2cc143, 0xe3370720, 0x00000120, 0xe721241b, + 0xe424e222, 0xe526e426, 0xf023ee22, 0xf820f222, 0x0023fa25, 0x121c0a1e, + 0x291d191a, 0x48024b00, 0x230e4d08, 0x23111f12, 0x2d111e15, 0x2d122a14, + 0x36101a1b, 0x38104207, 0x430a490b, 0x70e974f6, 0x3df947f1, 0x42fb3500, + 0x50f74df5, 0x57f654f7, 0x65eb7fde, 0x35fb27fd, 0x4bf53df9, 0x5bef4df1, + 0x6fe76be7, 0x4cf57ae4, 0x34f62cf6, 0x3af739f6, 0x45f948f0, 0x4afb45fc, + 0x420256f7, 0x200122f7, 0x34051f0b, 0x43fe37fe, 0x59f84900, 0x04073403, + 0x0811080a, 0x25031310, 0x49fb3dff, 0x4efc46ff, 0x7eeb0000, 0x6eec7ce9, + 0x7ce77ee6, 0x79e569ef, 0x66ef75e5, 0x74e575e6, 0x5ff67adf, 0x5ff864f2, + 0x72e46fef, 0x50fe59fa, 0x55f752fc, 0x48ff51f8, 0x43014005, 0x45003809, + 0x45074501, 0x43fa45f9, 0x40fe4df0, 0x43fa3d02, 0x390240fd, 0x42fd41fd, + 0x33093e00, 0x47fe42ff, 0x46ff4bfe, 0x3c0e48f7, 0x2f002510, 0x250b2312, + 0x290a290c, 0x290c3002, 0x3b00290d, 0x28133203, 0x32124203, 0xfa12fa13, + 0xf41a000e, 0xe721f01f, 0xe425ea21, 0xe22ae227, 0xdc2dd62f, 0xef29de31, + 0xb9450920, 0xc042c13f, 0xd936b64d, 0xf629dd34, 0xff280024, 0x1a1c0e1e, + 0x370c2517, 0xdf25410b, 0xdb28dc27, 0xdf2ee226, 0xe828e22a, 0xf426e331, + 0xfd26f628, 0x141ffb2e, 0x2c191e1d, 0x310b300c, 0x16162d1a, 0x151b1617, + 0x1c1a1421, 0x221b181e, 0x27192a12, 0x460c3212, 0x470e3615, 0x2019530b, + 0x36153115, 0x51fa55fb, 0x51f94df6, 0x49ee50ef, 0x53f64afc, 0x43f747f7, + 0x42f83dff, 0x3b0042f2, 0xf6113b02, 0xf72af320, 0x0035fb31, 0x0a440340, + 0x392f1b42, 0x180047fb, 0x2afe24ff, 0x39f734fe, 0x41fc3ffa, 0x52f943fc, + 0x4cfd51fd, 0x4efa48f9, 0x44f248f4, 0x4cfa46fd, 0x3efb42fb, 0x3dfc3900, + 0x36013cf7, 0xf6113a02, 0xf72af320, 0x0035fb31, 0x0a440340, 0x392f1b42, + 0x00000000, 0x00000000, 0x3602f114, 0xf1144a03, 0x4a033602, 0x68e97fe4, + 0x36ff35fa, 0x101d3307, 0x000e0019, 0x3efd33f6, 0x101a63e5, 0x66e855fc, + 0x39063905, 0x390e49ef, 0x0a142814, 0x0036001d, 0x610c2a25, 0x75ea7fe0, + 0x55fc4afe, 0x390566e8, 0x58f25dfa, 0x37042cfa, 0x67f159f5, 0x391374eb, + 0x54043a14, 0x3f016006, 0x6af355fb, 0x4b063f05, 0x65ff5afd, 0x4ffc3703, + 0x61f44bfe, 0x3c0132f9, 0x3f002900, 0x3f003f00, 0x560453f7, 0x48f96100, + 0x3e03290d, 0x58f72207, 0x7fdc7fec, 0x5ff25bef, 0x56e754e7, 0x5bef59f4, + 0x4cf27fe1, 0x5af367ee, 0x500b7fdb, 0x54024c05, 0x37fa4e05, 0x53f23d04, + 0x4ffb7fdb, 0x5bf568f5, 0x41007fe2, 0x48004ffe, 0x38fa5cfc, 0x47f84403, + 0x56fc62f3, 0x52fb58f4, 0x43fc48fd, 0x59f048f8, 0x3bff45f7, 0x39044205, + 0x47fe47fc, 0x4aff3a02, 0x45ff2cfc, 0x33f93e00, 0x2afa2ffc, 0x35fa29fd, + 0x4ef74c08, 0x340953f5, 0x5afb4300, 0x48f14301, 0x50f84bfb, 0x40eb53eb, + 0x40e71ff3, 0x4b095ee3, 0x4af83f11, 0x1bfe23fb, 0x41035b0d, 0x4d0845f9, + 0x3e0342f6, 0x51ec44fd, 0x07011e00, 0x4aeb17fd, 0x7ce94210, 0xee2c2511, + 0x7feade32, 0x2a002704, 0x1d0b2207, 0x25061f08, 0x28032a07, 0x2b0d2108, + 0x2f04240d, 0x3a023703, 0x2c083c06, 0x2a0e2c0b, 0x38043007, 0x250d3404, + 0x3a133109, 0x2d0c300a, 0x21144500, 0xee233f08, 0xfd1ce721, 0x001b0a18, + 0xd434f222, 0x1113e827, 0x1d24191f, 0x0f222118, 0x4916141e, 0x1f132214, + 0x10132c1b, 0x240f240f, 0x15191c15, 0x0c1f141e, 0x2a18101b, 0x380e5d00, + 0x261a390f, 0x73e87fe8, 0x3ef752ea, 0x3b003500, 0x59f355f2, 0x5cf55ef3, + 0x64eb7fe3, 0x43f439f2, 0x4df647f5, 0x58f055eb, 0x62f168e9, 0x52f67fdb, + 0x3df830f8, 0x46f942f8, 0x4ff64bf2, 0x5cf453f7, 0x4ffc6cee, 0x4bf045ea, + 0x3a013afe, 0x53f74ef3, 0x63f351fc, 0x26fa51f3, 0x3afa3ef3, 0x49f03bfe, + 0x56f34cf6, 0x57f653f7, 0x7fea0000, 0x78e77fe7, 0x72ed7fe5, 0x76e775e9, + 0x71e875e6, 0x78e176e4, 0x5ef67cdb, 0x63f666f1, 0x7fce6af3, 0x39115cfb, + 0x5ef356fb, 0x4dfe5bf4, 0x49ff4700, 0x51f94004, 0x390f4005, 0x44004301, + 0x440143f6, 0x40024d00, 0x4efb4400, 0x3b053707, 0x360e4102, 0x3c052c0f, + 0x4cfe4602, 0x460c56ee, 0x46f44005, 0x3805370b, 0x41024500, 0x36054afa, + 0x4cfa3607, 0x4dfe52f5, 0x2a194dfe, 0xf710f311, 0xeb1bf411, 0xd829e225, + 0xd130d72a, 0xd82ee027, 0xd72ecd34, 0xed2bd934, 0xc93d0b20, 0xce3ed238, + 0xec2dbd51, 0x0f1cfe23, 0x01270122, 0x2614111e, 0x360f2d12, 0xf0244f00, + 0xef25f225, 0x0f220120, 0x19180f1d, 0x101f1622, 0x1c1f1223, 0x1c242921, + 0x3e152f1b, 0x1a131f12, 0x17181824, 0x1e18101b, 0x29161d1f, 0x3c102a16, + 0x3c0e340f, 0x7bf04e03, 0x38163515, 0x21153d19, 0x3d113213, 0x4af84efd, + 0x48f648f7, 0x47f44bee, 0x46fb3ff5, 0x48f24bef, 0x35f843f0, 0x34f73bf2, + 0xfe0944f5, 0xfc1ff61e, 0x0721ff21, 0x17250c1f, 0x4014261f, 0x25f947f7, + 0x31f52cf8, 0x3bf438f6, 0x43f73ff8, 0x4ff644fa, 0x4af84efd, 0x48f648f7, + 0x47f44bee, 0x46fb3ff5, 0x48f24bef, 0x35f843f0, 0x34f73bf2, 0xfe0944f5, + 0xfc1ff61e, 0x0721ff21, 0x17250c1f, 0x4014261f, 0x00000000, 0x00000000, + 0x3602f114, 0xf1144a03, 0x4a033602, 0x68e97fe4, 0x36ff35fa, 0x00003307, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3f002900, 0x3f003f00, 0x560453f7, 0x48f96100, 0x3e03290d, 0x37010b00, + 0x7fef4500, 0x520066f3, 0x6beb4af9, 0x7fe17fe5, 0x5fee7fe8, 0x72eb7fe5, + 0x7bef7fe2, 0x7af073f4, 0x3ff473f5, 0x54f144fe, 0x46fd68f3, 0x5af65df8, + 0x4aff7fe2, 0x5bf961fa, 0x38fc7fec, 0x4cf952fb, 0x5df97dea, 0x4dfd57f5, + 0x3ffc47fb, 0x54f444fc, 0x41f93ef9, 0x38053d08, 0x400142fe, 0x4efe3d00, + 0x34073201, 0x2c00230a, 0x2d01260b, 0x2c052e00, 0x3301111f, 0x131c3207, + 0x3e0e2110, 0x64f16cf3, 0x5bf365f3, 0x58f65ef4, 0x56f654f0, 0x57f353f9, + 0x46015eed, 0x4afb4800, 0x66f83b12, 0x5f0064f1, 0x48024bfc, 0x47fd4bf5, + 0x45f32e0f, 0x41003e00, 0x48f12515, 0x36103909, 0x480c3e00, 0x090f0018, + 0x120d1908, 0x130d090f, 0x120c250a, 0x21141d06, 0x2d041e0f, 0x3e003a01, + 0x260c3d07, 0x270f2d0b, 0x2c0d2a0b, 0x290c2d10, 0x221e310a, 0x370a2a12, + 0x2e113311, 0xed1a5900, 0xef1aef16, 0xec1ce71e, 0xe525e921, 0xe428e921, + 0xf521ef26, 0xfa29f128, 0x11290126, 0x031bfa1e, 0xf025161a, 0xf826fc23, + 0x0325fd26, 0x002a0526, 0x16271023, 0x251b300e, 0x440c3c15, 0x47fd6102, + 0x32fb2afa, 0x3efe36fd, 0x3f013a00, 0x4aff48fe, 0x43fb5bf7, 0x27fd1bfb, + 0x2e002cfe, 0x44f840f0, 0x4dfa4ef6, 0x5cf456f6, 0x3cf637f1, 0x41fc3efa, + 0x4cf849f4, 0x58f750f9, 0x61f56eef, 0x4ff554ec, 0x4afc49fa, 0x60f356f3, + 0x75ed61f5, 0x21fb4ef8, 0x35fe30fc, 0x47f33efd, 0x56f44ff6, 0x61f25af3, + 0x5dfa0000, 0x4ff854fa, 0x47ff4200, 0x3cfe3e00, 0x4bfb3bfe, 0x3afc3efd, + 0x4fff42f7, 0x44034700, 0x3ef92c0a, 0x280e240f, 0x1d0c1b10, 0x24142c01, + 0x2a052012, 0x3e0a3001, 0x40092e11, 0x61f568f4, 0x58f960f0, 0x55f955f8, + 0x58f355f7, 0x4dfd4204, 0x4cfa4cfd, 0x4cff3a0a, 0x63f953ff, 0x5f025ff2, + 0x4afb4c00, 0x4bf54600, 0x41004401, 0x3e0349f2, 0x44ff3e04, 0x370b4bf3, + 0x460c4005, 0x1306060f, 0x0e0c1007, 0x0b0d0d12, 0x100f0f0d, 0x170d170c, + 0x1a0e140f, 0x28112c0e, 0x11182f11, 0x16191515, 0x1d161b1f, 0x320e2313, + 0x3f07390a, 0x52fc4dfe, 0x45095efd, 0xdd246df4, 0xe620de24, 0xe02ce225, + 0xf122ee22, 0xf921f128, 0x0021fb23, 0x0d210226, 0x3a0d2317, 0x001afd1d, + 0xf91f1e16, 0xfd22f123, 0xff240322, 0x0b200522, 0x0c220523, 0x1d1e0b27, + 0x271d1a22, 0x151f4213, 0x32191f1f, 0x70ec78ef, 0x55f572ee, 0x59f25cf1, + 0x51f147e6, 0x440050f2, 0x38e846f2, 0x32e844e9, 0xf3174af5, 0xf128f31a, + 0x032cf231, 0x222c062d, 0x52133621, 0x17ff4bfd, 0x2b012201, 0x37fe3600, + 0x40013d00, 0x5cf74400, 0x61f36af2, 0x5af45af1, 0x49f658ee, 0x56f24ff7, + 0x46f649f6, 0x42fb45f6, 0x3afb40f7, 0xf6153b02, 0xf81cf518, 0x031dff1c, + 0x1423091d, 0x430e241d, 0x00000000, 0x00000000 +}; + +MPP_RET vdpu3xx_h264d_deinit(void *hal) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_U32 loop = p_hal->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + RK_U32 i = 0; + + vdpu38x_rcb_calc_deinit(reg_ctx->rcb_ctx); + + if (reg_ctx->bufs) { + mpp_buffer_put(reg_ctx->bufs); + reg_ctx->bufs = NULL; + } + + if (reg_ctx->vdpu382_is_used == 1) { + for (i = 0; i < loop; i++) + MPP_FREE(reg_ctx->reg_382_buf[i].regs); + } else { + for (i = 0; i < loop; i++) + MPP_FREE(reg_ctx->reg_buf[i].regs); + } + + loop = p_hal->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->rcb_buf) : 1; + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + } + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + if (reg_ctx->origin_bufs) { + hal_bufs_deinit(reg_ctx->origin_bufs); + reg_ctx->origin_bufs = NULL; + } + + MPP_FREE(reg_ctx->spspps); + MPP_FREE(reg_ctx->rps); + MPP_FREE(reg_ctx->sclst); + + MPP_FREE(p_hal->reg_ctx); + + return MPP_OK; +} + +MPP_RET vdpu_h264d_reset(void *hal) +{ + (void)hal; + + return MPP_OK; +} + +MPP_RET vdpu_h264d_flush(void *hal) +{ + (void)hal; + + return MPP_OK; +} + +MPP_RET vdpu38x_h264d_control(void *hal, MpiCmd cmd_type, void *param) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, NULL == p_hal); + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + RK_U32 imgwidth = mpp_frame_get_width((MppFrame)param); + RK_U32 imgheight = mpp_frame_get_height((MppFrame)param); + + mpp_log("control info: fmt %d, w %d, h %d\n", fmt, imgwidth, imgheight); + if (fmt == MPP_FMT_YUV422SP) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, (MppFrame)param, 16); + } else if (imgwidth > 1920 || imgheight > 1088) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + } + } break; + case MPP_DEC_GET_THUMBNAIL_FRAME_INFO: { + vdpu38x_update_thumbnail_frame_info((MppFrame)param); + } break; + case MPP_DEC_SET_OUTPUT_FORMAT: { + } break; + default : { + } break; + } + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu38x_h264d_prepare_spspps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RockchipSocType soc_type = mpp_get_soc_type(); + RK_S32 is_long_term = 0, voidx = 0; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + BitputCtx_t bp; + RK_U32 tmp = 0; + RK_S32 i = 0, j = 0; + + mpp_set_bitput_ctx(&bp, data, len); + + if (!p_hal->fast_mode && !pp->spspps_update) { + bp.index = 2; + bp.bitpos = 24; + bp.bvalue = bp.pbuf[bp.index] & 0xFFFFFF; + } else { + RK_U32 pic_width, pic_height; + + //!< sps syntax + pic_width = 16 * (pp->wFrameWidthInMbsMinus1 + 1); + pic_height = 16 * (pp->wFrameHeightInMbsMinus1 + 1); + pic_height *= (2 - pp->frame_mbs_only_flag); + pic_height /= (1 + pp->field_pic_flag); + mpp_put_bits(&bp, pp->seq_parameter_set_id, 4); + mpp_put_bits(&bp, pp->profile_idc, 8); + mpp_put_bits(&bp, pp->constraint_set3_flag, 1); + mpp_put_bits(&bp, pp->chroma_format_idc, 2); + mpp_put_bits(&bp, pp->bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, pp->bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, 0, 1); // set 0 + mpp_put_bits(&bp, pp->log2_max_frame_num_minus4, 4); + mpp_put_bits(&bp, pp->num_ref_frames, 5); + mpp_put_bits(&bp, pp->pic_order_cnt_type, 2); + mpp_put_bits(&bp, pp->log2_max_pic_order_cnt_lsb_minus4, 4); + mpp_put_bits(&bp, pp->delta_pic_order_always_zero_flag, 1); + mpp_put_bits(&bp, pic_width, 16); + mpp_put_bits(&bp, pic_height, 16); + mpp_put_bits(&bp, pp->frame_mbs_only_flag, 1); + mpp_put_bits(&bp, pp->MbaffFrameFlag, 1); + mpp_put_bits(&bp, pp->direct_8x8_inference_flag, 1); + /* multi-view */ + mpp_put_bits(&bp, pp->mvc_extension_enable, 1); + if (pp->mvc_extension_enable) { + mpp_put_bits(&bp, (pp->num_views_minus1 + 1), 2); + mpp_put_bits(&bp, pp->view_id[0], 10); + mpp_put_bits(&bp, pp->view_id[1], 10); + } else { + mpp_put_bits(&bp, 0, 22); + } + // hw_fifo_align_bits(&bp, 128); + //!< pps syntax + mpp_put_bits(&bp, pp->pps_pic_parameter_set_id, 8); + mpp_put_bits(&bp, pp->pps_seq_parameter_set_id, 5); + mpp_put_bits(&bp, pp->entropy_coding_mode_flag, 1); + mpp_put_bits(&bp, pp->pic_order_present_flag, 1); + + mpp_put_bits(&bp, pp->num_ref_idx_l0_active_minus1, 5); + mpp_put_bits(&bp, pp->num_ref_idx_l1_active_minus1, 5); + mpp_put_bits(&bp, pp->weighted_pred_flag, 1); + mpp_put_bits(&bp, pp->weighted_bipred_idc, 2); + mpp_put_bits(&bp, pp->pic_init_qp_minus26, 7); + mpp_put_bits(&bp, pp->pic_init_qs_minus26, 6); + mpp_put_bits(&bp, pp->chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->deblocking_filter_control_present_flag, 1); + mpp_put_bits(&bp, pp->constrained_intra_pred_flag, 1); + mpp_put_bits(&bp, pp->redundant_pic_cnt_present_flag, 1); + mpp_put_bits(&bp, pp->transform_8x8_mode_flag, 1); + mpp_put_bits(&bp, pp->second_chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->scaleing_list_enable_flag, 1); + } + + //!< set dpb + for (i = 0; i < 16; i++) { + is_long_term = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefFrameList[i].AssociatedFlag : 0; + tmp |= (RK_U32)(is_long_term & 0x1) << i; + } + for (i = 0; i < 16; i++) { + voidx = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefPicLayerIdList[i] : 0; + tmp |= (RK_U32)(voidx & 0x1) << (i + 16); + } + mpp_put_bits(&bp, tmp, 32); + /* set current frame */ + mpp_put_bits(&bp, pp->field_pic_flag, 1); + mpp_put_bits(&bp, (pp->field_pic_flag && pp->CurrPic.AssociatedFlag), 1); + + mpp_put_bits(&bp, pp->CurrFieldOrderCnt[0], 32); + mpp_put_bits(&bp, pp->CurrFieldOrderCnt[1], 32); + + /* refer poc */ + for (i = 0; i < 16; i++) { + mpp_put_bits(&bp, pp->FieldOrderCntList[i][0], 32); + mpp_put_bits(&bp, pp->FieldOrderCntList[i][1], 32); + } + + tmp = 0; + for (i = 0; i < 16; i++) + tmp |= ((pp->RefPicFiledFlags >> i) & 0x01) << i; + for (i = 0; i < 16; i++) + tmp |= ((pp->UsedForReferenceFlags >> (2 * i + 0)) & 0x01) << (i + 16); + mpp_put_bits(&bp, tmp, 32); + + tmp = 0; + for (i = 0; i < 16; i++) + tmp |= ((pp->UsedForReferenceFlags >> (2 * i + 1)) & 0x01) << i; + for (i = 0; i < 16; i++) + tmp |= ((pp->RefPicColmvUsedFlags >> i) & 0x01) << (i + 16); + mpp_put_bits(&bp, tmp, 32); + + if (soc_type >= ROCKCHIP_SOC_RV1126B) { + /* rps */ + RK_S32 dpb_idx = 0; + RK_S32 dpb_valid = 0, bottom_flag = 0; + RK_U32 max_frame_num = 0; + RK_U16 frame_num_wrap = 0; + + max_frame_num = 1 << (pp->log2_max_frame_num_minus4 + 4); + for (i = 0; i < 16; i++) { + if ((pp->NonExistingFrameFlags >> i) & 0x01) { + frame_num_wrap = 0; + } else { + if (pp->RefFrameList[i].AssociatedFlag) { + frame_num_wrap = pp->FrameNumList[i]; + } else { + frame_num_wrap = (pp->FrameNumList[i] > pp->frame_num) ? + (pp->FrameNumList[i] - max_frame_num) : pp->FrameNumList[i]; + } + } + mpp_put_bits(&bp, frame_num_wrap, 16); + } + + /* dbp_idx_p_l0_32x7bit + dbp_idx_b_l0_32x7bit + dbp_idx_b_l1_32x7bit */ + for (j = 0; j < 3; j++) { + for (i = 0; i < 32; i++) { + tmp = 0; + dpb_valid = (p_hal->slice_long[0].RefPicList[j][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = dpb_valid ? p_hal->slice_long[0].RefPicList[j][i].Index7Bits : 0; + bottom_flag = dpb_valid ? p_hal->slice_long[0].RefPicList[j][i].AssociatedFlag : 0; + voidx = dpb_valid ? pp->RefPicLayerIdList[dpb_idx] : 0; + tmp |= (RK_U32)(dpb_idx | (dpb_valid << 4)) & 0x1f; + tmp |= (RK_U32)(bottom_flag & 0x1) << 5; + if (dpb_valid) + tmp |= (RK_U32)(voidx & 0x1) << 6; + mpp_put_bits(&bp, tmp, 7); + } + } + } + mpp_put_align(&bp, 64, 0);//128 + +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "global_cfg.dat"; + + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)bp.pbuf, + 64 * bp.index + bp.bitpos, 128, 0, 0); + } +#endif + + return MPP_OK; +} + +MPP_RET vdpu38x_h264d_prepare_scanlist(H264dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + RK_U32 i = 0, j = 0, n = 0; + + if (!p_hal->pp->scaleing_list_enable_flag) + return MPP_OK; + + for (i = 0; i < 6; i++) { //4x4, 6 lists + /* dump by block4x4, vectial direction */ + for (j = 0; j < 4; j++) { + data[n++] = p_hal->qm->bScalingLists4x4[i][j * 4 + 0]; + data[n++] = p_hal->qm->bScalingLists4x4[i][j * 4 + 1]; + data[n++] = p_hal->qm->bScalingLists4x4[i][j * 4 + 2]; + data[n++] = p_hal->qm->bScalingLists4x4[i][j * 4 + 3]; + } + } + + for (i = 0; i < 2; i++) { //8x8, 2 lists + RK_U32 blk4_x = 0, blk4_y = 0; + + /* dump by block4x4, vectial direction */ + for (blk4_y = 0; blk4_y < 8; blk4_y += 4) { + for (blk4_x = 0; blk4_x < 8; blk4_x += 4) { + RK_U32 pos = blk4_y * 8 + blk4_x; + + for (j = 0; j < 4; j++) { + data[n++] = p_hal->qm->bScalingLists8x8[i][pos + j * 8 + 0]; + data[n++] = p_hal->qm->bScalingLists8x8[i][pos + j * 8 + 1]; + data[n++] = p_hal->qm->bScalingLists8x8[i][pos + j * 8 + 2]; + data[n++] = p_hal->qm->bScalingLists8x8[i][pos + j * 8 + 3]; + } + } + } + } + + mpp_assert(n <= len); + +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "scanlist.dat"; + + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)data, 8 * n, 128, 0, 0); + } +#endif + + return MPP_OK; +} + +void vdpu38x_h264d_rcb_setup(void *hal, HalTaskInfo *task, + Vdpu38xRcbRegSet *rcb_regs, Vdpu38xRcbCalc_f func) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t*)hal; + RK_U32 mbaff = p_hal->pp->MbaffFrameFlag; + RK_U32 bit_depth = p_hal->pp->bit_depth_luma_minus8 + 8; + RK_U32 chroma_format_idc = p_hal->pp->chroma_format_idc; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_S32 width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + RK_S32 height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + MppBuffer rcb_buf; + + if ( ctx->bit_depth != bit_depth || + ctx->chroma_format_idc != chroma_format_idc || + ctx->mbaff != mbaff || + ctx->width != width || + ctx->height != height) { + RK_U32 i; + RK_U32 loop = p_hal->fast_mode ? MPP_ARRAY_ELEMS(ctx->reg_buf) : 1; + + /* update rcb info */ + { + RcbTileInfo tl_info; + MppFrame mframe; + MppFrameFormat mpp_fmt; + Vdpu38xFmt rcb_fmt; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, p_hal->pp->CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + mpp_fmt = mpp_frame_get_fmt(mframe); + rcb_fmt = vdpu38x_fmt_mpp2hal(mpp_fmt); + + vdpu38x_rcb_reset(ctx->rcb_ctx); + + /* update general info */ + vdpu38x_rcb_set_pic_w(ctx->rcb_ctx, width); + vdpu38x_rcb_set_pic_h(ctx->rcb_ctx, height); + vdpu38x_rcb_set_fmt(ctx->rcb_ctx, rcb_fmt); + vdpu38x_rcb_set_bit_depth(ctx->rcb_ctx, bit_depth); + + /* update cur spec info */ + vdpu38x_rcb_set_mbaff_flag(ctx->rcb_ctx, mbaff); + + /* add tile info */ + /* Simplify the calculation. */ + tl_info.lt_x = 0; + tl_info.lt_y = 0; + tl_info.w = width; + tl_info.h = height; + vdpu38x_rcb_set_tile_dir(ctx->rcb_ctx, 0); + vdpu38x_rcb_add_tile_info(ctx->rcb_ctx, &tl_info); + vdpu38x_rcb_register_calc_handle(ctx->rcb_ctx, func); + } + + vdpu38x_rcb_calc_exec(ctx->rcb_ctx, &ctx->rcb_buf_size); + /* vdpu384b_check_rcb_buf_size(ctx->rcb_info, width, height); */ + for (i = 0; i < loop; i++) { + rcb_buf = ctx->rcb_buf[i]; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + ctx->rcb_buf[i] = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, ctx->rcb_buf_size); + ctx->rcb_buf[i] = rcb_buf; + } + ctx->bit_depth = bit_depth; + ctx->width = width; + ctx->height = height; + ctx->mbaff = mbaff; + ctx->chroma_format_idc = chroma_format_idc; + } + + rcb_buf = p_hal->fast_mode ? ctx->rcb_buf[task->dec.reg_index] + : ctx->rcb_buf[0]; + vdpu38x_setup_rcb(ctx->rcb_ctx, rcb_regs, p_hal->cfg->dev, rcb_buf); +} + + +void hal_h264d_explain_input_buffer(void *hal, HalDecTask *task) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + DXVA2_DecodeBufferDesc *pdes = (DXVA2_DecodeBufferDesc *)task->syntax.data; + RK_U32 i = 0; + + for (i = 0; i < task->syntax.number; i++) { + switch (pdes[i].CompressedBufferType) { + case DXVA2_PictureParametersBufferType: + p_hal->pp = (DXVA_PicParams_H264_MVC *)pdes[i].pvPVPState; + break; + case DXVA2_InverseQuantizationMatrixBufferType: + p_hal->qm = (DXVA_Qmatrix_H264 *)pdes[i].pvPVPState; + break; + case DXVA2_SliceControlBufferType: + p_hal->slice_num = pdes[i].DataSize / sizeof(DXVA_Slice_H264_Long); + p_hal->slice_long = (DXVA_Slice_H264_Long *)pdes[i].pvPVPState; + break; + case DXVA2_BitStreamDateBufferType: + p_hal->bitstream = (RK_U8 *)pdes[i].pvPVPState; + p_hal->strm_len = pdes[i].DataSize; + break; + default: + break; + } + } +} diff --git a/mpp/hal/rkdec/h264d/hal_h264d_com.h b/mpp/hal/rkdec/h264d/hal_h264d_com.h new file mode 100644 index 000000000..2fe6ddd3f --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_com.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264D_COM_H +#define HAL_H264D_COM_H + +#include "rk_mpi_cmd.h" +#include "vdpu38x_com.h" + +#define H264_CTU_SIZE 16 + +extern const RK_U32 rkv_cabac_table[928]; + +MPP_RET vdpu3xx_h264d_deinit(void *hal); +MPP_RET vdpu_h264d_reset(void *hal); +MPP_RET vdpu_h264d_flush(void *hal); +MPP_RET vdpu38x_h264d_control(void *hal, MpiCmd cmd_type, void *param); +MPP_RET vdpu38x_h264d_prepare_spspps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len); +MPP_RET vdpu38x_h264d_prepare_scanlist(H264dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len); +void vdpu38x_h264d_rcb_setup(void *hal, HalTaskInfo *task, + Vdpu38xRcbRegSet *rcb_regs, Vdpu38xRcbCalc_f func); +void hal_h264d_explain_input_buffer(void *hal, HalDecTask *task); + +#endif /* HAL_H264D_COM_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_ctx.h b/mpp/hal/rkdec/h264d/hal_h264d_ctx.h new file mode 100644 index 000000000..5fc3a9f78 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_ctx.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264D_CTX_H +#define HAL_H264D_CTX_H + +#include "mpp_common.h" +#include "vdpu_com.h" + +typedef struct H264dVdpu3xxBuf_t { + RK_U32 valid; + void *regs; +} H264dVdpu3xxBuf; + +typedef struct H264dVdpu382Buf_t { + RK_U32 valid; + void *regs; + DXVA_PicEntry_H264 RefFrameList[16]; + DXVA_PicEntry_H264 RefPicList[3][32]; +} H264dVdpu382Buf; + +typedef struct Vdpu3xxH264dRegCtx_t { + RK_U8 *spspps; + RK_U8 *rps; + RK_U8 *sclst; + + MppBuffer bufs; + RK_S32 bufs_fd; + void *bufs_ptr; + RK_U32 offset_cabac; + RK_U32 offset_errinfo; + RK_U32 offset_spspps[VDPU_FAST_REG_SET_CNT]; + RK_U32 offset_rps[VDPU_FAST_REG_SET_CNT]; + RK_U32 offset_sclst[VDPU_FAST_REG_SET_CNT]; + + RK_U8 vdpu382_is_used; + union { + H264dVdpu3xxBuf reg_buf[VDPU_FAST_REG_SET_CNT]; + H264dVdpu382Buf reg_382_buf[VDPU_FAST_REG_SET_CNT]; + }; + + RK_U32 spspps_offset; + RK_U32 rps_offset; + RK_U32 sclst_offset; + + RK_S32 width; + RK_S32 height; + /* rcb buffers info */ + RK_U32 bit_depth; + RK_U32 mbaff; + RK_U32 chroma_format_idc; + + void *rcb_ctx; + RK_U32 rcb_buf_size; + VdpuRcbInfo rcb_info[RCB_BUF_CNT]; + MppBuffer rcb_buf[VDPU_FAST_REG_SET_CNT]; + + void *regs; + HalBufs origin_bufs; + + RK_U32 err_ref_hack; +} Vdpu3xxH264dRegCtx; + +#endif /* HAL_H264D_CTX_H */ + diff --git a/mpp/hal/rkdec/h264d/hal_h264d_fifo.c b/mpp/hal/rkdec/h264d/hal_h264d_fifo.c deleted file mode 100644 index fdb3b6d22..000000000 --- a/mpp/hal/rkdec/h264d/hal_h264d_fifo.c +++ /dev/null @@ -1,199 +0,0 @@ - -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "mpp_log.h" -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "hal_h264d_fifo.h" - -#define MODULE_TAG "hal_h264d_fifo" - -/*! -*********************************************************************** -* \brief -* write fifo data to file -*********************************************************************** -*/ -//extern "C" -void fifo_fwrite(FILE *fp, void *psrc, RK_U32 size) -{ - fwrite(psrc, 1, size, fp); - fflush(fp); -} - -/*! -*********************************************************************** -* \brief -* flush left bytes to fifo -*********************************************************************** -*/ -//extern "C" -void fifo_flush_bits(FifoCtx_t *pkt) -{ - if (pkt->bitpos) { - fifo_write_bits(pkt, 0, (64 - pkt->bitpos), "flush"); - pkt->index++; - pkt->bitpos = 0; - } -} - -//void fifo_fwrite_header(FifoCtx_t *pkt, RK_S32 pkt_size) -//{ -// if (pkt->fp_data) -// { -// pkt->size = pkt_size; -// fifo_fwrite(pkt->fp_data, &pkt->header, sizeof(RK_U32)); -// fifo_fwrite(pkt->fp_data, &pkt->size, sizeof(RK_U32)); -// } -//} - -/*! -*********************************************************************** -* \brief -* fwrite header and data -*********************************************************************** -*/ -//extern "C" -void fifo_fwrite_data(FifoCtx_t *pkt) -{ - RK_U32 pkt_size = 0; - - if (pkt->fp_data) { - pkt_size = pkt->index * sizeof(RK_U64); - fifo_fwrite(pkt->fp_data, &pkt->header, sizeof(RK_U32)); - fifo_fwrite(pkt->fp_data, &pkt_size, sizeof(RK_U32)); - fifo_fwrite(pkt->fp_data, pkt->pbuf, pkt->index * sizeof(RK_U64)); - } -} - -/*! -*********************************************************************** -* \brief -* write bits to fifo -*********************************************************************** -*/ -//extern "C" -void fifo_write_bits(FifoCtx_t *pkt, RK_U64 invalue, RK_U8 lbits, const char *name) -{ - RK_U8 hbits = 0; - - if (!lbits) return; - - hbits = 64 - lbits; - invalue = (invalue << hbits) >> hbits; - LogInfo(pkt->logctx, "%48s = %10d (bits=%d)", name, invalue, lbits); - pkt->bvalue |= invalue << pkt->bitpos; // high bits value - if ((pkt->bitpos + lbits) >= 64) { - pkt->pbuf[pkt->index] = pkt->bvalue; - pkt->bvalue = invalue >> (64 - pkt->bitpos); // low bits value - pkt->index++; - ASSERT(pkt->index <= pkt->buflen); - } - pkt->pbuf[pkt->index] = pkt->bvalue; - pkt->bitpos = (pkt->bitpos + lbits) & 63; -} -/*! -*********************************************************************** -* \brief -* align fifo bits -*********************************************************************** -*/ -//extern "C" -void fifo_align_bits(FifoCtx_t *pkt, RK_U8 align_bits) -{ - RK_U32 word_offset = 0, bits_offset = 0, bitlen = 0; - - word_offset = (align_bits >= 64) ? ((pkt->index & (((align_bits & 0xfe0) >> 6) - 1)) << 6) : 0; - bits_offset = (align_bits - (word_offset + (pkt->bitpos % align_bits))) % align_bits; - while (bits_offset > 0) { - bitlen = (bits_offset >= 8) ? 8 : bits_offset; - fifo_write_bits(pkt, 0, bitlen, "align"); - bits_offset -= bitlen; - } -} -/*! -*********************************************************************** -* \brief -* write bytes to fifo -*********************************************************************** -*/ -//extern "C" -void fifo_write_bytes(FifoCtx_t *pkt, void *psrc, RK_U32 size) -{ - RK_U8 hbits = 0; - RK_U32 bitslen = 0; - RK_U8 *pdst = NULL; - - hbits = 64 - pkt->bitpos; - pkt->pbuf[pkt->index] = pkt->bitpos ? ((pkt->bvalue << hbits) >> hbits) : 0; - if (size) { - pdst = (RK_U8 *)&pkt->pbuf[pkt->index]; - pdst += pkt->bitpos / 8; - - memcpy(pdst, psrc, size); - bitslen = size * 8 + pkt->bitpos; - - pkt->index += bitslen / 64; - pkt->bitpos = bitslen & 63; - - hbits = 64 - pkt->bitpos; - pkt->bvalue = pkt->bitpos ? ((pkt->pbuf[pkt->index] << hbits) >> hbits) : 0; - } -} - -void fifo_packet_reset(FifoCtx_t *pkt) -{ - pkt->index = 0; - pkt->bitpos = 0; - pkt->bvalue = 0; - pkt->size = 0; -} - -/*! -*********************************************************************** -* \brief -* init fifo packet -*********************************************************************** -*/ -//extern "C" -MPP_RET fifo_packet_init(FifoCtx_t *pkt, RK_S32 header, RK_S32 size) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - pkt->header = header; - pkt->index = 0; - pkt->bitpos = 0; - pkt->bvalue = 0; - pkt->size = 0; - pkt->buflen = (size + 7) / 8; // align 64bit - pkt->pbuf = NULL; - if (pkt->buflen) { - pkt->pbuf = mpp_malloc(RK_U64, pkt->buflen); - MEM_CHECK(ret, pkt->pbuf); - } - - return MPP_OK; - -__FAILED: - return ret; -} - - diff --git a/mpp/hal/rkdec/h264d/hal_h264d_fifo.h b/mpp/hal/rkdec/h264d/hal_h264d_fifo.h deleted file mode 100644 index 20e1cfc04..000000000 --- a/mpp/hal/rkdec/h264d/hal_h264d_fifo.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __HAL_H264D_FIFO_H__ -#define __HAL_H264D_FIFO_H__ - -#include "rk_type.h" -#include "mpp_err.h" -#include "h264d_log.h" - - -typedef struct { - RK_U32 header; - RK_U32 buflen; //!< max buf length, 64bit uint - RK_U32 index; //!< current uint position - RK_U64 *pbuf; //!< outpacket data - RK_U64 bvalue; //!< buffer value, 64 bit - RK_U8 bitpos; //!< bit pos in 64bit - RK_U32 size; //!< data size,except header - LogCtx_t *logctx; //!< for debug - FILE *fp_data; //!< for fpga -} FifoCtx_t; - - -#ifdef __cplusplus -extern "C" { -#endif - -void fifo_packet_reset (FifoCtx_t *pkt); -void fifo_fwrite_header(FifoCtx_t *pkt, RK_S32 pkt_size); -void fifo_fwrite_data (FifoCtx_t *pkt); -void fifo_write_bits (FifoCtx_t *pkt, RK_U64 invalue, RK_U8 lbits, const char *name); -void fifo_flush_bits (FifoCtx_t *pkt); -void fifo_align_bits (FifoCtx_t *pkt, RK_U8 align_bits); -void fifo_write_bytes (FifoCtx_t *pkt, void *psrc, RK_U32 size); -void fifo_fwrite (FILE *fp, void *psrc, RK_U32 size); -MPP_RET fifo_packet_init (FifoCtx_t *pkt, RK_S32 header, RK_S32 size); -#ifdef __cplusplus -} -#endif - - - -//!<============================ -#endif //!<__HAL_H264D_FIFO_H__ - - - diff --git a/mpp/hal/rkdec/h264d/hal_h264d_global.h b/mpp/hal/rkdec/h264d/hal_h264d_global.h index ed9dc3816..1b8f1a4ad 100644 --- a/mpp/hal/rkdec/h264d/hal_h264d_global.h +++ b/mpp/hal/rkdec/h264d/hal_h264d_global.h @@ -1,63 +1,119 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#ifndef __HAL_H264D_GLOBAL_H__ -#define __HAL_H264D_GLOBAL_H__ - -#include "mpp_hal.h" -#include "dxva_syntax.h" -#include "h264d_syntax.h" - -#include "h264d_log.h" -#include "hal_h264d_reg.h" -#include "hal_h264d_fifo.h" -#include "hal_h264d_packet.h" - - -typedef struct h264d_hal_mem_t { - H264_REGS_t regs; //!< for register - H264_MMU_t mmu_regs; - H264_CACHE_t cache_regs; - H264_FifoPkt_t pkts; -} H264dHalMem_t; - -typedef struct h264d_hal_ctx_t { - H264dHalMem_t *mem; - H264_REGS_t *regs; - H264_MMU_t *mmu_regs; - H264_CACHE_t *cache_regs; - H264_FifoPkt_t *pkts; - RK_U8 spt_BitstrmRaw; - RK_U8 set_BitstrmRaw; - - DXVA_PicParams_H264_MVC *pp; - DXVA_Qmatrix_H264 *qm; - RK_U32 slice_num; - DXVA_Slice_H264_Short *slice_short; //!< MAX_SLICES - DXVA_Slice_H264_Long *slice_long; //!< MAX_SLICES - RK_U8 *bitstream; - RK_U32 strm_len; - RK_U32 g_framecnt; - H264dLogCtx_t logctx; //!< debug log file - LogCtx_t logctxbuf[LOG_MAX]; - -} H264dHalCtx_t; - - - -#endif /*__HAL_H264D_REG_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264D_GLOBAL_H +#define HAL_H264D_GLOBAL_H + +#include "mpp_hal.h" +#include "mpp_debug.h" +#include "mpp_device.h" +#include "mpp_env.h" +#include "hal_bufs.h" + +#include "dxva_syntax.h" +#include "h264d_syntax.h" + +#define H264D_DBG_ERROR (0x00000001) +#define H264D_DBG_ASSERT (0x00000002) +#define H264D_DBG_WARNNING (0x00000004) +#define H264D_DBG_LOG (0x00000008) + +#define H264D_DBG_HARD_MODE (0x00000010) +#define H264D_DBG_REG (0x00000020) + +extern RK_U32 hal_h264d_debug; + + +#define H264D_DBG(level, fmt, ...)\ +do {\ + if (level & hal_h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + + +#define H264D_ERR(fmt, ...)\ +do {\ + if (H264D_DBG_ERROR & hal_h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define ASSERT(val)\ +do {\ + if (H264D_DBG_ASSERT & hal_h264d_debug)\ + { mpp_assert(val); }\ +} while (0) + +#define H264D_WARNNING(fmt, ...)\ +do {\ + if (H264D_DBG_WARNNING & hal_h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + +#define H264D_LOG(fmt, ...)\ +do {\ + if (H264D_DBG_LOG & hal_h264d_debug)\ + { mpp_log(fmt, ## __VA_ARGS__); }\ +} while (0) + + +//!< vaule check +#define VAL_CHECK(ret, val, ...)\ +do{\ + if (!(val)){\ + ret = MPP_ERR_VALUE; \ + H264D_WARNNING("value error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do{\ + if (!(val)) {\ + ret = MPP_ERR_MALLOC; \ + H264D_ERR("malloc buffer error(%d).\n", __LINE__); \ + ASSERT(0); goto __FAILED; \ +}} while (0) + + +//!< input check +#define INP_CHECK(ret, val, ...)\ +do{\ + if ((val)) {\ + ret = MPP_ERR_INIT; \ + H264D_WARNNING("input empty(%d).\n", __LINE__); \ + goto __RETURN; \ +}} while (0) +//!< function return check +#define FUN_CHECK(val)\ +do{\ + if ((val) < 0) {\ + H264D_WARNNING("Function error(%d).\n", __LINE__); \ + goto __FAILED; \ +}} while (0) + + +typedef struct h264d_hal_ctx_t { + DXVA_PicParams_H264_MVC *pp; + DXVA_Qmatrix_H264 *qm; + RK_U32 slice_num; + DXVA_Slice_H264_Short *slice_short; //!< MAX_SLICES + DXVA_Slice_H264_Long *slice_long; //!< MAX_SLICES + RK_U8 *bitstream; + RK_U32 strm_len; + + void *priv; //!< resert data for extent + //!< add + HalDecTask *in_task; + MppHalCfg *cfg; + HalBufs cmv_bufs; + RK_S32 mv_size; + RK_S32 mv_count; + + void *reg_ctx; + RK_U32 fast_mode; +} H264dHalCtx_t; + +extern const RK_U32 h264_cabac_table[928]; + +#endif /* HAL_H264D_GLOBAL_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_packet.c b/mpp/hal/rkdec/h264d/hal_h264d_packet.c deleted file mode 100644 index 28cb4621b..000000000 --- a/mpp/hal/rkdec/h264d/hal_h264d_packet.c +++ /dev/null @@ -1,468 +0,0 @@ - -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "mpp_mem.h" -#include "hal_task.h" - -#include "dxva_syntax.h" -#include "h264d_log.h" -#include "h264d_syntax.h" -#include "hal_h264d_fifo.h" -#include "hal_h264d_api.h" -#include "hal_h264d_packet.h" -#include "hal_h264d_global.h" - -#define MODULE_TAG "hal_h264d_packet" - -//!< Header -#define H264dREG_HEADER 0x48474552 -#define H264dPPS_HEADER 0x48535050 -#define H264dSCL_HEADER 0x534c4353 -#define H264dRPS_HEADER 0x48535052 -#define H264dCRC_HEADER 0x48435243 -#define H264dSTM_HEADER 0x4d525453 -#define H264dERR_HEADER 0x524f5245 - - -enum { - H264ScalingList4x4Length = 16, - H264ScalingList8x8Length = 64, -} ScalingListLength; - - -static void write_sps_to_fifo(H264dHalCtx_t *p_hal, FifoCtx_t *pkt) -{ - fifo_write_bits(pkt, -1, 4, "seq_parameter_set_id"); //!< not used in hard - fifo_write_bits(pkt, -1, 8, "profile_idc"); //!< not used in hard - fifo_write_bits(pkt, -1, 1, "constraint_set3_flag"); //!< not used in hard - fifo_write_bits(pkt, p_hal->pp->chroma_format_idc, 2, "chroma_format_idc"); - fifo_write_bits(pkt, (p_hal->pp->bit_depth_luma_minus8 + 8), 3, "bit_depth_luma"); - fifo_write_bits(pkt, (p_hal->pp->bit_depth_chroma_minus8 + 8), 3, "bit_depth_chroma"); - fifo_write_bits(pkt, 0, 1, "qpprime_y_zero_transform_bypass_flag"); //!< not supported in hard - fifo_write_bits(pkt, p_hal->pp->log2_max_frame_num_minus4, 4, "log2_max_frame_num_minus4"); - fifo_write_bits(pkt, p_hal->pp->num_ref_frames, 5, "max_num_ref_frames"); - fifo_write_bits(pkt, p_hal->pp->pic_order_cnt_type, 2, "pic_order_cnt_type"); - fifo_write_bits(pkt, p_hal->pp->log2_max_pic_order_cnt_lsb_minus4, 4, "log2_max_pic_order_cnt_lsb_minus4"); - fifo_write_bits(pkt, p_hal->pp->delta_pic_order_always_zero_flag, 1, "delta_pic_order_always_zero_flag"); - fifo_write_bits(pkt, (p_hal->pp->wFrameWidthInMbsMinus1 + 1), 9, "pic_width_in_mbs"); - fifo_write_bits(pkt, (p_hal->pp->wFrameHeightInMbsMinus1 + 1), 9, "pic_height_in_mbs"); - fifo_write_bits(pkt, p_hal->pp->frame_mbs_only_flag, 1, "frame_mbs_only_flag"); - fifo_write_bits(pkt, p_hal->pp->MbaffFrameFlag, 1, "mb_adaptive_frame_field_flag"); - fifo_write_bits(pkt, p_hal->pp->direct_8x8_inference_flag, 1, "direct_8x8_inference_flag"); - - fifo_write_bits(pkt, 1, 1, "mvc_extension_enable"); - fifo_write_bits(pkt, (p_hal->pp->num_views_minus1 + 1), 2, "num_views"); - fifo_write_bits(pkt, p_hal->pp->view_id[0], 10, "view_id[2]"); - fifo_write_bits(pkt, p_hal->pp->view_id[1], 10, "view_id[2]"); - fifo_write_bits(pkt, p_hal->pp->num_anchor_refs_l0[0], 1, "num_anchor_refs_l0"); - if (p_hal->pp->num_anchor_refs_l0[0]) { - fifo_write_bits(pkt, p_hal->pp->anchor_ref_l0[0][0], 10, "anchor_ref_l0"); - } else { - fifo_write_bits(pkt, 0, 10, "anchor_ref_l0"); - } - fifo_write_bits(pkt, p_hal->pp->num_anchor_refs_l1[0], 1, "num_anchor_refs_l1"); - if (p_hal->pp->num_anchor_refs_l1[0]) { - fifo_write_bits(pkt, p_hal->pp->anchor_ref_l1[0][0], 10, "anchor_ref_l1"); - } else { - fifo_write_bits(pkt, 0, 10, "anchor_ref_l1"); - } - fifo_write_bits(pkt, p_hal->pp->num_non_anchor_refs_l0[0], 1, "num_non_anchor_refs_l0"); - if (p_hal->pp->num_non_anchor_refs_l0[0]) { - fifo_write_bits(pkt, p_hal->pp->non_anchor_ref_l0[0][0], 10, "non_anchor_ref_l0"); - } else { - fifo_write_bits(pkt, 0, 10, "non_anchor_ref_l0"); - } - fifo_write_bits(pkt, p_hal->pp->num_non_anchor_refs_l1[0], 1, "num_non_anchor_refs_l1"); - if (p_hal->pp->num_non_anchor_refs_l1[0]) { - fifo_write_bits(pkt, p_hal->pp->non_anchor_ref_l1[0][0], 10, "non_anchor_ref_l1"); - } else { - fifo_write_bits(pkt, 0, 10, "non_anchor_ref_l1"); - } - fifo_align_bits(pkt, 32); -} - -static void write_pps_to_fifo(H264dHalCtx_t *p_hal, FifoCtx_t *pkt) -{ - fifo_write_bits(pkt, -1, 8, "pps_pic_parameter_set_id"); - fifo_write_bits(pkt, -1, 5, "pps_seq_parameter_set_id"); - fifo_write_bits(pkt, p_hal->pp->entropy_coding_mode_flag, 1, "entropy_coding_mode_flag"); - fifo_write_bits(pkt, p_hal->pp->pic_order_present_flag, 1, "bottom_field_pic_order_in_frame_present_flag"); - fifo_write_bits(pkt, p_hal->pp->num_ref_idx_l0_active_minus1, 5, "num_ref_idx_l0_default_active_minus1"); - fifo_write_bits(pkt, p_hal->pp->num_ref_idx_l1_active_minus1, 5, "num_ref_idx_l1_default_active_minus1"); - fifo_write_bits(pkt, p_hal->pp->weighted_pred_flag, 1, "weighted_pred_flag"); - fifo_write_bits(pkt, p_hal->pp->weighted_bipred_idc, 2, "weighted_bipred_idc"); - fifo_write_bits(pkt, p_hal->pp->pic_init_qp_minus26, 7, "pic_init_qp_minus26"); - fifo_write_bits(pkt, p_hal->pp->pic_init_qs_minus26, 6, "pic_init_qs_minus26"); - fifo_write_bits(pkt, p_hal->pp->chroma_qp_index_offset, 5, "chroma_qp_index_offset"); - fifo_write_bits(pkt, p_hal->pp->deblocking_filter_control_present_flag, 1, "deblocking_filter_control_present_flag"); - fifo_write_bits(pkt, p_hal->pp->constrained_intra_pred_flag, 1, "constrained_intra_pred_flag"); - fifo_write_bits(pkt, p_hal->pp->redundant_pic_cnt_present_flag, 1, "redundant_pic_cnt_present_flag"); - fifo_write_bits(pkt, p_hal->pp->transform_8x8_mode_flag, 1, "transform_8x8_mode_flag"); - fifo_write_bits(pkt, p_hal->pp->second_chroma_qp_index_offset, 5, "second_chroma_qp_index_offset"); - fifo_write_bits(pkt, p_hal->pp->scaleing_list_enable_flag, 1, "scaleing_list_enable_flag"); - fifo_write_bits(pkt, 0/*(RK_U32)p_hal->pkts.scanlist.pbuf*/, 32, "Scaleing_list_address"); - -} - - -/*! -*********************************************************************** -* \brief -* reset fifo packet -*********************************************************************** -*/ -//extern "C" -void reset_fifo_packet(H264_FifoPkt_t *pkt) -{ - if (pkt) { - fifo_packet_reset(&pkt->spspps); - fifo_packet_reset(&pkt->rps); - fifo_packet_reset(&pkt->strm); - fifo_packet_reset(&pkt->scanlist); - fifo_packet_reset(&pkt->reg); - } -} - -/*! -*********************************************************************** -* \brief -* free fifo pakcket -*********************************************************************** -*/ -//extern "C" -void free_fifo_packet(H264_FifoPkt_t *pkt) -{ - if (pkt) { - mpp_free(pkt->spspps.pbuf); - mpp_free(pkt->rps.pbuf); - mpp_free(pkt->scanlist.pbuf); - mpp_free(pkt->reg.pbuf); - } -} -/*! -*********************************************************************** -* \brief -* alloc fifo packet -*********************************************************************** -*/ -//extern "C" -MPP_RET alloc_fifo_packet(H264dLogCtx_t *logctx, H264_FifoPkt_t *pkts) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - LogCtx_t *log_driver = NULL; - RK_U32 pps_size = 256 * 32 + 16; - RK_U32 rps_size = 128 + 16; - RK_U32 strm_size = 0; - RK_U32 sclst_size = 256; - RK_U32 regs_size = 512; - - //!< initial packages header and malloc buffer - FUN_CHECK(ret = fifo_packet_init(&pkts->spspps, H264dPPS_HEADER, pps_size)); - FUN_CHECK(ret = fifo_packet_init(&pkts->rps, H264dRPS_HEADER, rps_size)); - FUN_CHECK(ret = fifo_packet_init(&pkts->strm, H264dSTM_HEADER, strm_size)); - FUN_CHECK(ret = fifo_packet_init(&pkts->scanlist, H264dSCL_HEADER, sclst_size)); - FUN_CHECK(ret = fifo_packet_init(&pkts->reg, H264dREG_HEADER, regs_size)); - - //!< set logctx - pkts->spspps.logctx = logctx->parr[LOG_WRITE_SPSPPS]; - pkts->rps.logctx = logctx->parr[LOG_WRITE_RPS]; - pkts->scanlist.logctx = logctx->parr[LOG_WRITE_SCANLIST]; - pkts->reg.logctx = logctx->parr[LOG_WRITE_REG]; - - //!< set bitstream file output - log_driver = logctx->parr[LOG_FPGA]; - if (log_driver && log_driver->flag->write_en) { - pkts->spspps.fp_data = log_driver->fp; - pkts->rps.fp_data = log_driver->fp; - pkts->scanlist.fp_data = log_driver->fp; - pkts->reg.fp_data = log_driver->fp; - pkts->strm.fp_data = log_driver->fp; - } else { - pkts->spspps.fp_data = NULL; - pkts->rps.fp_data = NULL; - pkts->scanlist.fp_data = NULL; - pkts->reg.fp_data = NULL; - pkts->strm.fp_data = NULL; - } - return ret = MPP_OK; -__FAILED: - free_fifo_packet(pkts); - - return ret; -} - -/*! -*********************************************************************** -* \brief -* expalin decoder buffer dest -*********************************************************************** -*/ -//extern "C" -void explain_input_buffer(void *hal, HalDecTask *task) -{ - RK_U32 i = 0; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - DXVA2_DecodeBufferDesc *pdes = (DXVA2_DecodeBufferDesc *)task->syntax.data; - for (i = 0; i < task->syntax.number; i++) { - switch (pdes[i].CompressedBufferType) { - case DXVA2_PictureParametersBufferType: - p_hal->pp = (DXVA_PicParams_H264_MVC *)pdes[i].pvPVPState; - break; - case DXVA2_InverseQuantizationMatrixBufferType: - p_hal->qm = (DXVA_Qmatrix_H264 *)pdes[i].pvPVPState; - break; - case DXVA2_SliceControlBufferType: - p_hal->slice_num = pdes[i].DataSize / sizeof(DXVA_Slice_H264_Long); - p_hal->slice_long = (DXVA_Slice_H264_Long *)pdes[i].pvPVPState; - break; - case DXVA2_BitStreamDateBufferType: - p_hal->bitstream = (RK_U8 *)pdes[i].pvPVPState; - p_hal->strm_len = pdes[i].DataSize; - break; - default: - break; - } - } -} -/*! -*********************************************************************** -* \brief -* prepare sps_sps packet -*********************************************************************** -*/ -//extern "C" -void prepare_spspps_packet(void *hal, FifoCtx_t *pkt) -{ - RK_S32 i = 0; - RK_S32 is_long_term = 0, voidx = 0; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - fifo_packet_reset(pkt); - LogInfo(pkt->logctx, "------------------ Frame SPS_PPS begin ------------------------"); - write_sps_to_fifo(p_hal, pkt); - write_pps_to_fifo(p_hal, pkt); - - for (i = 0; i < 16; i++) { - is_long_term = (p_hal->pp->RefFrameList[i].bPicEntry != 0xff) ? p_hal->pp->RefFrameList[i].AssociatedFlag : 0; - fifo_write_bits(pkt, is_long_term, 1, "is_long_term"); - } - for (i = 0; i < 16; i++) { - voidx = (p_hal->pp->RefFrameList[i].bPicEntry != 0xff) ? p_hal->pp->RefPicLayerIdList[i] : 0; - fifo_write_bits(pkt, voidx, 1, "voidx"); - } - fifo_align_bits(pkt, 64); - fifo_fwrite_data(pkt); //!< "PPSH" header 32 bit -} -/*! -*********************************************************************** -* \brief -* prepare frame rps packet -*********************************************************************** -*/ -//extern "C" -void prepare_framerps_packet(void *hal, FifoCtx_t *pkt) -{ - RK_S32 i = 0, j = 0; - RK_S32 dpb_idx = 0, voidx = 0; - RK_S32 dpb_valid = 0, bottom_flag = 0; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - fifo_packet_reset(pkt); - LogInfo(pkt->logctx, "------------------ Frame RPS begin ------------------------"); - for (i = 0; i < 16; i++) { - fifo_write_bits(pkt, p_hal->pp->FrameNumList[i], 16, "frame_num_wrap"); - } - for (i = 0; i < 16; i++) { - fifo_write_bits(pkt, 0, 1, "NULL"); - } - for (i = 0; i < 16; i++) { - fifo_write_bits(pkt, p_hal->pp->RefPicLayerIdList[i], 1, "voidx"); - } - for (i = 0; i < 32; i++) { - dpb_valid = (p_hal->slice_long[0].RefPicList[0][i].bPicEntry == 0xff) ? 0 : 1; - dpb_idx = dpb_valid ? p_hal->slice_long[0].RefPicList[0][i].Index7Bits : 0; - bottom_flag = dpb_valid ? p_hal->slice_long[0].RefPicList[0][i].AssociatedFlag : 0; - voidx = dpb_valid ? p_hal->pp->RefPicLayerIdList[dpb_idx] : 0; - fifo_write_bits(pkt, dpb_idx | (dpb_valid << 4), 5, "dpb_idx"); - fifo_write_bits(pkt, bottom_flag, 1, "bottom_flag"); - fifo_write_bits(pkt, voidx, 1, "voidx"); - } - for (j = 1; j < 3; j++) { - for (i = 0; i < 32; i++) { - dpb_valid = (p_hal->slice_long[0].RefPicList[j][i].bPicEntry == 0xff) ? 0 : 1; - dpb_idx = dpb_valid ? p_hal->slice_long[0].RefPicList[j][i].Index7Bits : 0; - bottom_flag = dpb_valid ? p_hal->slice_long[0].RefPicList[j][i].AssociatedFlag : 0; - voidx = dpb_valid ? p_hal->pp->RefPicLayerIdList[dpb_idx] : 0; - fifo_write_bits(pkt, dpb_idx | (dpb_valid << 4), 5, "dpb_idx"); - fifo_write_bits(pkt, bottom_flag, 1, "bottom_flag"); - fifo_write_bits(pkt, voidx, 1, "voidx"); - } - } - fifo_align_bits(pkt, 128); - fifo_flush_bits(pkt); - fifo_fwrite_data(pkt); //!< "RPSH" header 32 bit -} -/*! -*********************************************************************** -* \brief -* prepare scanlist packet -*********************************************************************** -*/ -//extern "C" -void prepare_scanlist_packet(void *hal, FifoCtx_t *pkt) -{ - RK_S32 i = 0; - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - if (p_hal->pp->scaleing_list_enable_flag) { - fifo_packet_reset(pkt); - LogInfo(pkt->logctx, "------------------ Scanlist begin ------------------------"); - for (i = 0; i < 6; ++i) { //!< 4x4, 6 lists - fifo_write_bytes(pkt, p_hal->qm->bScalingLists4x4[i], H264ScalingList4x4Length); - } - for (i = 0; i < 2; ++i) { - fifo_write_bytes(pkt, p_hal->qm->bScalingLists8x8[i], H264ScalingList8x8Length); - } - fifo_fwrite_data(pkt); //!< "SCLS" header 32 bit - } -} -/*! -*********************************************************************** -* \brief -* prepare stream packet -*********************************************************************** -*/ -//extern "C" -void prepare_stream_packet(void *hal, FifoCtx_t *pkt) -{ - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - - fifo_packet_reset(pkt); - pkt->pbuf = (RK_U64 *)p_hal->bitstream; - pkt->index = p_hal->strm_len / 8; - fifo_fwrite_data(pkt); // "STRM" header 32 bit -} -/*! -*********************************************************************** -* \brief -* generate register packet -*********************************************************************** -*/ -//extern "C" -void generate_regs(void *hal, FifoCtx_t *pkt) -{ - RK_S32 i = 0; - RK_U8 bit_depth[3] = { 0 }; - RK_U32 sw_y_hor_virstride = 0; - RK_U32 sw_uv_hor_virstride = 0; - RK_U32 sw_y_virstride = 0; - RK_U32 yuv_virstride = 0; - RK_U32 pic_h[3] = { 0 }, pic_w[3] = { 0 }; - RK_U32 mb_width = 0, mb_height = 0, mv_size = 0; - - H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; - H264_REGS_t *p_regs = p_hal->regs; - memset(p_regs, 0, sizeof(H264_REGS_t)); - - if (p_regs->swreg2_sysctrl.sw_rlc_mode == 1) { - p_regs->swreg5_stream_rlc_len.sw_stream_len = 0; - } else { - p_regs->swreg5_stream_rlc_len.sw_stream_len = p_hal->strm_len; - } - //!< caculate the yuv_frame_size and mv_size - mb_width = p_hal->pp->wFrameWidthInMbsMinus1 + 1; - mb_height = (2 - p_hal->pp->frame_mbs_only_flag) * (p_hal->pp->wFrameHeightInMbsMinus1 + 1); - mv_size = mb_width * mb_height * 8; // 64bit per 4x4 - bit_depth[0] = p_hal->pp->bit_depth_luma_minus8 + 8; - if (p_hal->pp->chroma_format_idc) { // Y420 Y422 - bit_depth[1] = p_hal->pp->bit_depth_chroma_minus8 + 8; - } else { //!< Y400 - bit_depth[1] = 0; - } - pic_h[0] = mb_height * 16; - if (p_hal->pp->chroma_format_idc == 2) { // Y422 - pic_h[1] = mb_height * 16; - } else { //!< Y420 - pic_h[1] = mb_height * 8; - } - pic_w[0] = mb_width * 16; - pic_w[1] = mb_width * 16; - sw_y_hor_virstride = ((pic_w[0] * bit_depth[0] + 127) & (~127)) / 128; - sw_uv_hor_virstride = ((pic_w[1] * bit_depth[1] + 127) & (~127)) / 128; - - if (sw_y_hor_virstride > p_regs->swreg3_picpar.sw_y_hor_virstride) { - p_regs->swreg3_picpar.sw_y_hor_virstride = sw_y_hor_virstride; - } - if (sw_uv_hor_virstride > p_regs->swreg3_picpar.sw_uv_hor_virstride) { - p_regs->swreg3_picpar.sw_uv_hor_virstride = sw_uv_hor_virstride; - } - sw_y_virstride = pic_h[0] * p_regs->swreg3_picpar.sw_y_hor_virstride; - if (sw_y_virstride > p_regs->swreg8_y_virstride.sw_y_virstride) { - p_regs->swreg8_y_virstride.sw_y_virstride = sw_y_virstride; - } - if (p_hal->pp->chroma_format_idc == 0) { // YUV400 - yuv_virstride = p_regs->swreg8_y_virstride.sw_y_virstride; - } else { - yuv_virstride = pic_h[0] * p_regs->swreg3_picpar.sw_y_hor_virstride + - pic_h[1] * p_regs->swreg3_picpar.sw_uv_hor_virstride; - } - if (yuv_virstride > p_regs->swreg9_yuv_virstride.sw_yuv_virstride) { - p_regs->swreg9_yuv_virstride.sw_yuv_virstride = yuv_virstride; - } - p_regs->compare_len = (p_regs->swreg9_yuv_virstride.sw_yuv_virstride + mv_size) * 2; - if (p_regs->swreg2_sysctrl.sw_h264_rps_mode) { // rps_mode == 1 - p_regs->swreg43_rps_base.sw_rps_base += 0x8; - } - p_regs->swreg3_picpar.sw_slice_num_lowbits = 0x7ff; // p_Vid->iNumOfSlicesDecoded & 0x7ff - p_regs->swreg3_picpar.sw_slice_num_highbit = 1; // (p_Vid->iNumOfSlicesDecoded >> 11) & 1 - //!< set current - p_regs->swreg40_cur_poc.sw_cur_poc = p_hal->pp->CurrFieldOrderCnt[0]; - p_regs->swreg74_h264_cur_poc1.sw_h264_cur_poc1 = p_hal->pp->CurrFieldOrderCnt[1]; - p_regs->swreg7_decout_base.sw_decout_base = p_hal->pp->CurrPic.Index7Bits; - //!< set reference - for (i = 0; i < 15; i++) { - p_regs->swreg25_39_refer0_14_poc[i] = (i & 1) ? p_hal->pp->FieldOrderCntList[i / 2][1] : p_hal->pp->FieldOrderCntList[i / 2][0]; - p_regs->swreg49_63_refer15_29_poc[i] = (i & 1) ? p_hal->pp->FieldOrderCntList[(i + 15) / 2][0] : p_hal->pp->FieldOrderCntList[(i + 15) / 2][1]; - p_regs->swreg10_24_refer0_14_base[i].sw_ref_field = (p_hal->pp->RefPicFiledFlags >> i) & 0x01; - p_regs->swreg10_24_refer0_14_base[i].sw_ref_topfield_used = (p_hal->pp->UsedForReferenceFlags >> (2 * i + 0)) & 0x01; - p_regs->swreg10_24_refer0_14_base[i].sw_ref_botfield_used = (p_hal->pp->UsedForReferenceFlags >> (2 * i + 1)) & 0x01; - p_regs->swreg10_24_refer0_14_base[i].sw_ref_colmv_use_flag = (p_hal->pp->RefPicColmvUsedFlags >> i) & 0x01; - if (p_hal->pp->RefFrameList[i].bPicEntry != 0xff) { - p_regs->swreg10_24_refer0_14_base[i].sw_refer_base = p_hal->pp->RefFrameList[i].Index7Bits; - } - } - p_regs->swreg72_refer30_poc = p_hal->pp->FieldOrderCntList[i][0]; - p_regs->swreg73_refer31_poc = p_hal->pp->FieldOrderCntList[i][1]; - p_regs->swreg48_refer15_base.sw_ref_field = (p_hal->pp->RefPicFiledFlags >> 15) & 0x01; - p_regs->swreg48_refer15_base.sw_ref_topfield_used = (p_hal->pp->UsedForReferenceFlags >> 30) & 0x01; - p_regs->swreg48_refer15_base.sw_ref_botfield_used = (p_hal->pp->UsedForReferenceFlags >> 31) & 0x01; - p_regs->swreg48_refer15_base.sw_ref_colmv_use_flag = (p_hal->pp->RefPicColmvUsedFlags >> 15) & 0x01; - if (p_hal->pp->RefFrameList[15].bPicEntry != 0xff) { - p_regs->swreg48_refer15_base.sw_refer_base = p_hal->pp->RefFrameList[15].Index7Bits; - } - - fifo_packet_reset(pkt); - fifo_write_bytes(pkt, (void *)p_hal->regs, sizeof(H264_REGS_t)); - fifo_write_bytes(pkt, (void *)p_hal->mmu_regs, sizeof(H264_MMU_t)); - fifo_write_bytes(pkt, (void *)p_hal->cache_regs, sizeof(H264_CACHE_t)); - fifo_align_bits(pkt, 64); - fifo_flush_bits(pkt); - fifo_fwrite_data(pkt); //!< "REGH" header 32 bit -} - diff --git a/mpp/hal/rkdec/h264d/hal_h264d_packet.h b/mpp/hal/rkdec/h264d/hal_h264d_packet.h deleted file mode 100644 index af30dbbe7..000000000 --- a/mpp/hal/rkdec/h264d/hal_h264d_packet.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __HAL_H264D_PACKET_H__ -#define __HAL_H264D_PACKET_H__ - -#include "rk_type.h" -#include "mpp_err.h" -#include "hal_task.h" - -#include "h264d_log.h" -#include "hal_h264d_fifo.h" - -typedef struct h264_fifo_packet_t { - FifoCtx_t spspps; - FifoCtx_t rps; - FifoCtx_t strm; - FifoCtx_t scanlist; - FifoCtx_t reg; -} H264_FifoPkt_t; - - -#ifdef __cplusplus -extern "C" { -#endif -void reset_fifo_packet(H264_FifoPkt_t *pkt); -void free_fifo_packet (H264_FifoPkt_t *pkt); -MPP_RET alloc_fifo_packet(H264dLogCtx_t *logctx, H264_FifoPkt_t *pkts); - -void explain_input_buffer (void *hal, HalDecTask *task); -void prepare_spspps_packet (void *hal, FifoCtx_t *pkt); -void prepare_framerps_packet(void *hal, FifoCtx_t *pkt); -void prepare_scanlist_packet(void *hal, FifoCtx_t *pkt); -void prepare_stream_packet (void *hal, FifoCtx_t *pkt); -void generate_regs (void *hal, FifoCtx_t *pkt); - -#ifdef __cplusplus -} -#endif - - - -//!<============================ -#endif // __HAL_H264D_PACKET_H__ - - - diff --git a/mpp/hal/rkdec/h264d/hal_h264d_reg.c b/mpp/hal/rkdec/h264d/hal_h264d_reg.c deleted file mode 100644 index 295d8a02a..000000000 --- a/mpp/hal/rkdec/h264d/hal_h264d_reg.c +++ /dev/null @@ -1,269 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#include -#include -#include - -#include "rk_type.h" -#include "mpp_err.h" -#include "mpp_mem.h" - -#include "h264d_log.h" -#include "hal_h264d_reg.h" - - - -#define MODULE_TAG "hal_h264d_reg" - - - -const RK_U8 H264_Cabac_table[] = { - 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, - 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x17, 0x21, 0x17, 0x02, 0x15, 0x00, 0x01, 0x09, 0x00, 0x31, - 0xdb, 0x76, 0x05, 0x39, 0xf3, 0x4e, 0xf5, 0x41, 0x01, 0x3e, 0x0c, 0x31, 0xfc, 0x49, 0x11, 0x32, - 0x12, 0x40, 0x09, 0x2b, 0x1d, 0x00, 0x1a, 0x43, 0x10, 0x5a, 0x09, 0x68, 0xd2, 0x7f, 0xec, 0x68, - 0x01, 0x43, 0xf3, 0x4e, 0xf5, 0x41, 0x01, 0x3e, 0xfa, 0x56, 0xef, 0x5f, 0xfa, 0x3d, 0x09, 0x2d, - 0xfd, 0x45, 0xfa, 0x51, 0xf5, 0x60, 0x06, 0x37, 0x07, 0x43, 0xfb, 0x56, 0x02, 0x58, 0x00, 0x3a, - 0xfd, 0x4c, 0xf6, 0x5e, 0x05, 0x36, 0x04, 0x45, 0xfd, 0x51, 0x00, 0x58, 0xf9, 0x43, 0xfb, 0x4a, - 0xfc, 0x4a, 0xfb, 0x50, 0xf9, 0x48, 0x01, 0x3a, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, - 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x00, 0x2d, 0xfc, 0x4e, - 0xfd, 0x60, 0xe5, 0x7e, 0xe4, 0x62, 0xe7, 0x65, 0xe9, 0x43, 0xe4, 0x52, 0xec, 0x5e, 0xf0, 0x53, - 0xea, 0x6e, 0xeb, 0x5b, 0xee, 0x66, 0xf3, 0x5d, 0xe3, 0x7f, 0xf9, 0x5c, 0xfb, 0x59, 0xf9, 0x60, - 0xf3, 0x6c, 0xfd, 0x2e, 0xff, 0x41, 0xff, 0x39, 0xf7, 0x5d, 0xfd, 0x4a, 0xf7, 0x5c, 0xf8, 0x57, - 0xe9, 0x7e, 0x05, 0x36, 0x06, 0x3c, 0x06, 0x3b, 0x06, 0x45, 0xff, 0x30, 0x00, 0x44, 0xfc, 0x45, - 0xf8, 0x58, 0xfe, 0x55, 0xfa, 0x4e, 0xff, 0x4b, 0xf9, 0x4d, 0x02, 0x36, 0x05, 0x32, 0xfd, 0x44, - 0x01, 0x32, 0x06, 0x2a, 0xfc, 0x51, 0x01, 0x3f, 0xfc, 0x46, 0x00, 0x43, 0x02, 0x39, 0xfe, 0x4c, - 0x0b, 0x23, 0x04, 0x40, 0x01, 0x3d, 0x0b, 0x23, 0x12, 0x19, 0x0c, 0x18, 0x0d, 0x1d, 0x0d, 0x24, - 0xf6, 0x5d, 0xf9, 0x49, 0xfe, 0x49, 0x0d, 0x2e, 0x09, 0x31, 0xf9, 0x64, 0x09, 0x35, 0x02, 0x35, - 0x05, 0x35, 0xfe, 0x3d, 0x00, 0x38, 0x00, 0x38, 0xf3, 0x3f, 0xfb, 0x3c, 0xff, 0x3e, 0x04, 0x39, - 0xfa, 0x45, 0x04, 0x39, 0x0e, 0x27, 0x04, 0x33, 0x0d, 0x44, 0x03, 0x40, 0x01, 0x3d, 0x09, 0x3f, - 0x07, 0x32, 0x10, 0x27, 0x05, 0x2c, 0x04, 0x34, 0x0b, 0x30, 0xfb, 0x3c, 0xff, 0x3b, 0x00, 0x3b, - 0x16, 0x21, 0x05, 0x2c, 0x0e, 0x2b, 0xff, 0x4e, 0x00, 0x3c, 0x09, 0x45, 0x0b, 0x1c, 0x02, 0x28, - 0x03, 0x2c, 0x00, 0x31, 0x00, 0x2e, 0x02, 0x2c, 0x02, 0x33, 0x00, 0x2f, 0x04, 0x27, 0x02, 0x3e, - 0x06, 0x2e, 0x00, 0x36, 0x03, 0x36, 0x02, 0x3a, 0x04, 0x3f, 0x06, 0x33, 0x06, 0x39, 0x07, 0x35, - 0x06, 0x34, 0x06, 0x37, 0x0b, 0x2d, 0x0e, 0x24, 0x08, 0x35, 0xff, 0x52, 0x07, 0x37, 0xfd, 0x4e, - 0x0f, 0x2e, 0x16, 0x1f, 0xff, 0x54, 0x19, 0x07, 0x1e, 0xf9, 0x1c, 0x03, 0x1c, 0x04, 0x20, 0x00, - 0x22, 0xff, 0x1e, 0x06, 0x1e, 0x06, 0x20, 0x09, 0x1f, 0x13, 0x1a, 0x1b, 0x1a, 0x1e, 0x25, 0x14, - 0x1c, 0x22, 0x11, 0x46, 0x01, 0x43, 0x05, 0x3b, 0x09, 0x43, 0x10, 0x1e, 0x12, 0x20, 0x12, 0x23, - 0x16, 0x1d, 0x18, 0x1f, 0x17, 0x26, 0x12, 0x2b, 0x14, 0x29, 0x0b, 0x3f, 0x09, 0x3b, 0x09, 0x40, - 0xff, 0x5e, 0xfe, 0x59, 0xf7, 0x6c, 0xfa, 0x4c, 0xfe, 0x2c, 0x00, 0x2d, 0x00, 0x34, 0xfd, 0x40, - 0xfe, 0x3b, 0xfc, 0x46, 0xfc, 0x4b, 0xf8, 0x52, 0xef, 0x66, 0xf7, 0x4d, 0x03, 0x18, 0x00, 0x2a, - 0x00, 0x30, 0x00, 0x37, 0xfa, 0x3b, 0xf9, 0x47, 0xf4, 0x53, 0xf5, 0x57, 0xe2, 0x77, 0x01, 0x3a, - 0xfd, 0x1d, 0xff, 0x24, 0x01, 0x26, 0x02, 0x2b, 0xfa, 0x37, 0x00, 0x3a, 0x00, 0x40, 0xfd, 0x4a, - 0xf6, 0x5a, 0x00, 0x46, 0xfc, 0x1d, 0x05, 0x1f, 0x07, 0x2a, 0x01, 0x3b, 0xfe, 0x3a, 0xfd, 0x48, - 0xfd, 0x51, 0xf5, 0x61, 0x00, 0x3a, 0x08, 0x05, 0x0a, 0x0e, 0x0e, 0x12, 0x0d, 0x1b, 0x02, 0x28, - 0x00, 0x3a, 0xfd, 0x46, 0xfa, 0x4f, 0xf8, 0x55, 0x00, 0x00, 0xf3, 0x6a, 0xf0, 0x6a, 0xf6, 0x57, - 0xeb, 0x72, 0xee, 0x6e, 0xf2, 0x62, 0xea, 0x6e, 0xeb, 0x6a, 0xee, 0x67, 0xeb, 0x6b, 0xe9, 0x6c, - 0xe6, 0x70, 0xf6, 0x60, 0xf4, 0x5f, 0xfb, 0x5b, 0xf7, 0x5d, 0xea, 0x5e, 0xfb, 0x56, 0x09, 0x43, - 0xfc, 0x50, 0xf6, 0x55, 0xff, 0x46, 0x07, 0x3c, 0x09, 0x3a, 0x05, 0x3d, 0x0c, 0x32, 0x0f, 0x32, - 0x12, 0x31, 0x11, 0x36, 0x0a, 0x29, 0x07, 0x2e, 0xff, 0x33, 0x07, 0x31, 0x08, 0x34, 0x09, 0x29, - 0x06, 0x2f, 0x02, 0x37, 0x0d, 0x29, 0x0a, 0x2c, 0x06, 0x32, 0x05, 0x35, 0x0d, 0x31, 0x04, 0x3f, - 0x06, 0x40, 0xfe, 0x45, 0xfe, 0x3b, 0x06, 0x46, 0x0a, 0x2c, 0x09, 0x1f, 0x0c, 0x2b, 0x03, 0x35, - 0x0e, 0x22, 0x0a, 0x26, 0xfd, 0x34, 0x0d, 0x28, 0x11, 0x20, 0x07, 0x2c, 0x07, 0x26, 0x0d, 0x32, - 0x0a, 0x39, 0x1a, 0x2b, 0x0e, 0x0b, 0x0b, 0x0e, 0x09, 0x0b, 0x12, 0x0b, 0x15, 0x09, 0x17, 0xfe, - 0x20, 0xf1, 0x20, 0xf1, 0x22, 0xeb, 0x27, 0xe9, 0x2a, 0xdf, 0x29, 0xe1, 0x2e, 0xe4, 0x26, 0xf4, - 0x15, 0x1d, 0x2d, 0xe8, 0x35, 0xd3, 0x30, 0xe6, 0x41, 0xd5, 0x2b, 0xed, 0x27, 0xf6, 0x1e, 0x09, - 0x12, 0x1a, 0x14, 0x1b, 0x00, 0x39, 0xf2, 0x52, 0xfb, 0x4b, 0xed, 0x61, 0xdd, 0x7d, 0x1b, 0x00, - 0x1c, 0x00, 0x1f, 0xfc, 0x1b, 0x06, 0x22, 0x08, 0x1e, 0x0a, 0x18, 0x16, 0x21, 0x13, 0x16, 0x20, - 0x1a, 0x1f, 0x15, 0x29, 0x1a, 0x2c, 0x17, 0x2f, 0x10, 0x41, 0x0e, 0x47, 0x08, 0x3c, 0x06, 0x3f, - 0x11, 0x41, 0x15, 0x18, 0x17, 0x14, 0x1a, 0x17, 0x1b, 0x20, 0x1c, 0x17, 0x1c, 0x18, 0x17, 0x28, - 0x18, 0x20, 0x1c, 0x1d, 0x17, 0x2a, 0x13, 0x39, 0x16, 0x35, 0x16, 0x3d, 0x0b, 0x56, 0x0c, 0x28, - 0x0b, 0x33, 0x0e, 0x3b, 0xfc, 0x4f, 0xf9, 0x47, 0xfb, 0x45, 0xf7, 0x46, 0xf8, 0x42, 0xf6, 0x44, - 0xed, 0x49, 0xf4, 0x45, 0xf0, 0x46, 0xf1, 0x43, 0xec, 0x3e, 0xed, 0x46, 0xf0, 0x42, 0xea, 0x41, - 0xec, 0x3f, 0x09, 0xfe, 0x1a, 0xf7, 0x21, 0xf7, 0x27, 0xf9, 0x29, 0xfe, 0x2d, 0x03, 0x31, 0x09, - 0x2d, 0x1b, 0x24, 0x3b, 0xfa, 0x42, 0xf9, 0x23, 0xf9, 0x2a, 0xf8, 0x2d, 0xfb, 0x30, 0xf4, 0x38, - 0xfa, 0x3c, 0xfb, 0x3e, 0xf8, 0x42, 0xf8, 0x4c, 0xfb, 0x55, 0xfa, 0x51, 0xf6, 0x4d, 0xf9, 0x51, - 0xef, 0x50, 0xee, 0x49, 0xfc, 0x4a, 0xf6, 0x53, 0xf7, 0x47, 0xf7, 0x43, 0xff, 0x3d, 0xf8, 0x42, - 0xf2, 0x42, 0x00, 0x3b, 0x02, 0x3b, 0x15, 0xf3, 0x21, 0xf2, 0x27, 0xf9, 0x2e, 0xfe, 0x33, 0x02, - 0x3c, 0x06, 0x3d, 0x11, 0x37, 0x22, 0x2a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, - 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x16, 0x19, 0x22, 0x00, 0x10, 0x00, 0xfe, 0x09, 0x04, 0x29, - 0xe3, 0x76, 0x02, 0x41, 0xfa, 0x47, 0xf3, 0x4f, 0x05, 0x34, 0x09, 0x32, 0xfd, 0x46, 0x0a, 0x36, - 0x1a, 0x22, 0x13, 0x16, 0x28, 0x00, 0x39, 0x02, 0x29, 0x24, 0x1a, 0x45, 0xd3, 0x7f, 0xf1, 0x65, - 0xfc, 0x4c, 0xfa, 0x47, 0xf3, 0x4f, 0x05, 0x34, 0x06, 0x45, 0xf3, 0x5a, 0x00, 0x34, 0x08, 0x2b, - 0xfe, 0x45, 0xfb, 0x52, 0xf6, 0x60, 0x02, 0x3b, 0x02, 0x4b, 0xfd, 0x57, 0xfd, 0x64, 0x01, 0x38, - 0xfd, 0x4a, 0xfa, 0x55, 0x00, 0x3b, 0xfd, 0x51, 0xf9, 0x56, 0xfb, 0x5f, 0xff, 0x42, 0xff, 0x4d, - 0x01, 0x46, 0xfe, 0x56, 0xfb, 0x48, 0x00, 0x3d, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, - 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x0d, 0x0f, 0x07, 0x33, - 0x02, 0x50, 0xd9, 0x7f, 0xee, 0x5b, 0xef, 0x60, 0xe6, 0x51, 0xdd, 0x62, 0xe8, 0x66, 0xe9, 0x61, - 0xe5, 0x77, 0xe8, 0x63, 0xeb, 0x6e, 0xee, 0x66, 0xdc, 0x7f, 0x00, 0x50, 0xfb, 0x59, 0xf9, 0x5e, - 0xfc, 0x5c, 0x00, 0x27, 0x00, 0x41, 0xf1, 0x54, 0xdd, 0x7f, 0xfe, 0x49, 0xf4, 0x68, 0xf7, 0x5b, - 0xe1, 0x7f, 0x03, 0x37, 0x07, 0x38, 0x07, 0x37, 0x08, 0x3d, 0xfd, 0x35, 0x00, 0x44, 0xf9, 0x4a, - 0xf7, 0x58, 0xf3, 0x67, 0xf3, 0x5b, 0xf7, 0x59, 0xf2, 0x5c, 0xf8, 0x4c, 0xf4, 0x57, 0xe9, 0x6e, - 0xe8, 0x69, 0xf6, 0x4e, 0xec, 0x70, 0xef, 0x63, 0xb2, 0x7f, 0xba, 0x7f, 0xce, 0x7f, 0xd2, 0x7f, - 0xfc, 0x42, 0xfb, 0x4e, 0xfc, 0x47, 0xf8, 0x48, 0x02, 0x3b, 0xff, 0x37, 0xf9, 0x46, 0xfa, 0x4b, - 0xf8, 0x59, 0xde, 0x77, 0xfd, 0x4b, 0x20, 0x14, 0x1e, 0x16, 0xd4, 0x7f, 0x00, 0x36, 0xfb, 0x3d, - 0x00, 0x3a, 0xff, 0x3c, 0xfd, 0x3d, 0xf8, 0x43, 0xe7, 0x54, 0xf2, 0x4a, 0xfb, 0x41, 0x05, 0x34, - 0x02, 0x39, 0x00, 0x3d, 0xf7, 0x45, 0xf5, 0x46, 0x12, 0x37, 0xfc, 0x47, 0x00, 0x3a, 0x07, 0x3d, - 0x09, 0x29, 0x12, 0x19, 0x09, 0x20, 0x05, 0x2b, 0x09, 0x2f, 0x00, 0x2c, 0x00, 0x33, 0x02, 0x2e, - 0x13, 0x26, 0xfc, 0x42, 0x0f, 0x26, 0x0c, 0x2a, 0x09, 0x22, 0x00, 0x59, 0x04, 0x2d, 0x0a, 0x1c, - 0x0a, 0x1f, 0x21, 0xf5, 0x34, 0xd5, 0x12, 0x0f, 0x1c, 0x00, 0x23, 0xea, 0x26, 0xe7, 0x22, 0x00, - 0x27, 0xee, 0x20, 0xf4, 0x66, 0xa2, 0x00, 0x00, 0x38, 0xf1, 0x21, 0xfc, 0x1d, 0x0a, 0x25, 0xfb, - 0x33, 0xe3, 0x27, 0xf7, 0x34, 0xde, 0x45, 0xc6, 0x43, 0xc1, 0x2c, 0xfb, 0x20, 0x07, 0x37, 0xe3, - 0x20, 0x01, 0x00, 0x00, 0x1b, 0x24, 0x21, 0xe7, 0x22, 0xe2, 0x24, 0xe4, 0x26, 0xe4, 0x26, 0xe5, - 0x22, 0xee, 0x23, 0xf0, 0x22, 0xf2, 0x20, 0xf8, 0x25, 0xfa, 0x23, 0x00, 0x1e, 0x0a, 0x1c, 0x12, - 0x1a, 0x19, 0x1d, 0x29, 0x00, 0x4b, 0x02, 0x48, 0x08, 0x4d, 0x0e, 0x23, 0x12, 0x1f, 0x11, 0x23, - 0x15, 0x1e, 0x11, 0x2d, 0x14, 0x2a, 0x12, 0x2d, 0x1b, 0x1a, 0x10, 0x36, 0x07, 0x42, 0x10, 0x38, - 0x0b, 0x49, 0x0a, 0x43, 0xf6, 0x74, 0xe9, 0x70, 0xf1, 0x47, 0xf9, 0x3d, 0x00, 0x35, 0xfb, 0x42, - 0xf5, 0x4d, 0xf7, 0x50, 0xf7, 0x54, 0xf6, 0x57, 0xde, 0x7f, 0xeb, 0x65, 0xfd, 0x27, 0xfb, 0x35, - 0xf9, 0x3d, 0xf5, 0x4b, 0xf1, 0x4d, 0xef, 0x5b, 0xe7, 0x6b, 0xe7, 0x6f, 0xe4, 0x7a, 0xf5, 0x4c, - 0xf6, 0x2c, 0xf6, 0x34, 0xf6, 0x39, 0xf7, 0x3a, 0xf0, 0x48, 0xf9, 0x45, 0xfc, 0x45, 0xfb, 0x4a, - 0xf7, 0x56, 0x02, 0x42, 0xf7, 0x22, 0x01, 0x20, 0x0b, 0x1f, 0x05, 0x34, 0xfe, 0x37, 0xfe, 0x43, - 0x00, 0x49, 0xf8, 0x59, 0x03, 0x34, 0x07, 0x04, 0x0a, 0x08, 0x11, 0x08, 0x10, 0x13, 0x03, 0x25, - 0xff, 0x3d, 0xfb, 0x49, 0xff, 0x46, 0xfc, 0x4e, 0x00, 0x00, 0xeb, 0x7e, 0xe9, 0x7c, 0xec, 0x6e, - 0xe6, 0x7e, 0xe7, 0x7c, 0xef, 0x69, 0xe5, 0x79, 0xe5, 0x75, 0xef, 0x66, 0xe6, 0x75, 0xe5, 0x74, - 0xdf, 0x7a, 0xf6, 0x5f, 0xf2, 0x64, 0xf8, 0x5f, 0xef, 0x6f, 0xe4, 0x72, 0xfa, 0x59, 0xfe, 0x50, - 0xfc, 0x52, 0xf7, 0x55, 0xf8, 0x51, 0xff, 0x48, 0x05, 0x40, 0x01, 0x43, 0x09, 0x38, 0x00, 0x45, - 0x01, 0x45, 0x07, 0x45, 0xf9, 0x45, 0xfa, 0x43, 0xf0, 0x4d, 0xfe, 0x40, 0x02, 0x3d, 0xfa, 0x43, - 0xfd, 0x40, 0x02, 0x39, 0xfd, 0x41, 0xfd, 0x42, 0x00, 0x3e, 0x09, 0x33, 0xff, 0x42, 0xfe, 0x47, - 0xfe, 0x4b, 0xff, 0x46, 0xf7, 0x48, 0x0e, 0x3c, 0x10, 0x25, 0x00, 0x2f, 0x12, 0x23, 0x0b, 0x25, - 0x0c, 0x29, 0x0a, 0x29, 0x02, 0x30, 0x0c, 0x29, 0x0d, 0x29, 0x00, 0x3b, 0x03, 0x32, 0x13, 0x28, - 0x03, 0x42, 0x12, 0x32, 0x13, 0xfa, 0x12, 0xfa, 0x0e, 0x00, 0x1a, 0xf4, 0x1f, 0xf0, 0x21, 0xe7, - 0x21, 0xea, 0x25, 0xe4, 0x27, 0xe2, 0x2a, 0xe2, 0x2f, 0xd6, 0x2d, 0xdc, 0x31, 0xde, 0x29, 0xef, - 0x20, 0x09, 0x45, 0xb9, 0x3f, 0xc1, 0x42, 0xc0, 0x4d, 0xb6, 0x36, 0xd9, 0x34, 0xdd, 0x29, 0xf6, - 0x24, 0x00, 0x28, 0xff, 0x1e, 0x0e, 0x1c, 0x1a, 0x17, 0x25, 0x0c, 0x37, 0x0b, 0x41, 0x25, 0xdf, - 0x27, 0xdc, 0x28, 0xdb, 0x26, 0xe2, 0x2e, 0xdf, 0x2a, 0xe2, 0x28, 0xe8, 0x31, 0xe3, 0x26, 0xf4, - 0x28, 0xf6, 0x26, 0xfd, 0x2e, 0xfb, 0x1f, 0x14, 0x1d, 0x1e, 0x19, 0x2c, 0x0c, 0x30, 0x0b, 0x31, - 0x1a, 0x2d, 0x16, 0x16, 0x17, 0x16, 0x1b, 0x15, 0x21, 0x14, 0x1a, 0x1c, 0x1e, 0x18, 0x1b, 0x22, - 0x12, 0x2a, 0x19, 0x27, 0x12, 0x32, 0x0c, 0x46, 0x15, 0x36, 0x0e, 0x47, 0x0b, 0x53, 0x19, 0x20, - 0x15, 0x31, 0x15, 0x36, 0xfb, 0x55, 0xfa, 0x51, 0xf6, 0x4d, 0xf9, 0x51, 0xef, 0x50, 0xee, 0x49, - 0xfc, 0x4a, 0xf6, 0x53, 0xf7, 0x47, 0xf7, 0x43, 0xff, 0x3d, 0xf8, 0x42, 0xf2, 0x42, 0x00, 0x3b, - 0x02, 0x3b, 0x11, 0xf6, 0x20, 0xf3, 0x2a, 0xf7, 0x31, 0xfb, 0x35, 0x00, 0x40, 0x03, 0x44, 0x0a, - 0x42, 0x1b, 0x2f, 0x39, 0xfb, 0x47, 0x00, 0x18, 0xff, 0x24, 0xfe, 0x2a, 0xfe, 0x34, 0xf7, 0x39, - 0xfa, 0x3f, 0xfc, 0x41, 0xfc, 0x43, 0xf9, 0x52, 0xfd, 0x51, 0xfd, 0x4c, 0xf9, 0x48, 0xfa, 0x4e, - 0xf4, 0x48, 0xf2, 0x44, 0xfd, 0x46, 0xfa, 0x4c, 0xfb, 0x42, 0xfb, 0x3e, 0x00, 0x39, 0xfc, 0x3d, - 0xf7, 0x3c, 0x01, 0x36, 0x02, 0x3a, 0x11, 0xf6, 0x20, 0xf3, 0x2a, 0xf7, 0x31, 0xfb, 0x35, 0x00, - 0x40, 0x03, 0x44, 0x0a, 0x42, 0x1b, 0x2f, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, - 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x1d, 0x10, 0x19, 0x00, 0x0e, 0x00, 0xf6, 0x33, 0xfd, 0x3e, - 0xe5, 0x63, 0x1a, 0x10, 0xfc, 0x55, 0xe8, 0x66, 0x05, 0x39, 0x06, 0x39, 0xef, 0x49, 0x0e, 0x39, - 0x14, 0x28, 0x14, 0x0a, 0x1d, 0x00, 0x36, 0x00, 0x25, 0x2a, 0x0c, 0x61, 0xe0, 0x7f, 0xea, 0x75, - 0xfe, 0x4a, 0xfc, 0x55, 0xe8, 0x66, 0x05, 0x39, 0xfa, 0x5d, 0xf2, 0x58, 0xfa, 0x2c, 0x04, 0x37, - 0xf5, 0x59, 0xf1, 0x67, 0xeb, 0x74, 0x13, 0x39, 0x14, 0x3a, 0x04, 0x54, 0x06, 0x60, 0x01, 0x3f, - 0xfb, 0x55, 0xf3, 0x6a, 0x05, 0x3f, 0x06, 0x4b, 0xfd, 0x5a, 0xff, 0x65, 0x03, 0x37, 0xfc, 0x4f, - 0xfe, 0x4b, 0xf4, 0x61, 0xf9, 0x32, 0x01, 0x3c, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, - 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x07, 0x22, 0xf7, 0x58, - 0xec, 0x7f, 0xdc, 0x7f, 0xef, 0x5b, 0xf2, 0x5f, 0xe7, 0x54, 0xe7, 0x56, 0xf4, 0x59, 0xef, 0x5b, - 0xe1, 0x7f, 0xf2, 0x4c, 0xee, 0x67, 0xf3, 0x5a, 0xdb, 0x7f, 0x0b, 0x50, 0x05, 0x4c, 0x02, 0x54, - 0x05, 0x4e, 0xfa, 0x37, 0x04, 0x3d, 0xf2, 0x53, 0xdb, 0x7f, 0xfb, 0x4f, 0xf5, 0x68, 0xf5, 0x5b, - 0xe2, 0x7f, 0x00, 0x41, 0xfe, 0x4f, 0x00, 0x48, 0xfc, 0x5c, 0xfa, 0x38, 0x03, 0x44, 0xf8, 0x47, - 0xf3, 0x62, 0xfc, 0x56, 0xf4, 0x58, 0xfb, 0x52, 0xfd, 0x48, 0xfc, 0x43, 0xf8, 0x48, 0xf0, 0x59, - 0xf7, 0x45, 0xff, 0x3b, 0x05, 0x42, 0x04, 0x39, 0xfc, 0x47, 0xfe, 0x47, 0x02, 0x3a, 0xff, 0x4a, - 0xfc, 0x2c, 0xff, 0x45, 0x00, 0x3e, 0xf9, 0x33, 0xfc, 0x2f, 0xfa, 0x2a, 0xfd, 0x29, 0xfa, 0x35, - 0x08, 0x4c, 0xf7, 0x4e, 0xf5, 0x53, 0x09, 0x34, 0x00, 0x43, 0xfb, 0x5a, 0x01, 0x43, 0xf1, 0x48, - 0xfb, 0x4b, 0xf8, 0x50, 0xeb, 0x53, 0xeb, 0x40, 0xf3, 0x1f, 0xe7, 0x40, 0xe3, 0x5e, 0x09, 0x4b, - 0x11, 0x3f, 0xf8, 0x4a, 0xfb, 0x23, 0xfe, 0x1b, 0x0d, 0x5b, 0x03, 0x41, 0xf9, 0x45, 0x08, 0x4d, - 0xf6, 0x42, 0x03, 0x3e, 0xfd, 0x44, 0xec, 0x51, 0x00, 0x1e, 0x01, 0x07, 0xfd, 0x17, 0xeb, 0x4a, - 0x10, 0x42, 0xe9, 0x7c, 0x11, 0x25, 0x2c, 0xee, 0x32, 0xde, 0xea, 0x7f, 0x04, 0x27, 0x00, 0x2a, - 0x07, 0x22, 0x0b, 0x1d, 0x08, 0x1f, 0x06, 0x25, 0x07, 0x2a, 0x03, 0x28, 0x08, 0x21, 0x0d, 0x2b, - 0x0d, 0x24, 0x04, 0x2f, 0x03, 0x37, 0x02, 0x3a, 0x06, 0x3c, 0x08, 0x2c, 0x0b, 0x2c, 0x0e, 0x2a, - 0x07, 0x30, 0x04, 0x38, 0x04, 0x34, 0x0d, 0x25, 0x09, 0x31, 0x13, 0x3a, 0x0a, 0x30, 0x0c, 0x2d, - 0x00, 0x45, 0x14, 0x21, 0x08, 0x3f, 0x23, 0xee, 0x21, 0xe7, 0x1c, 0xfd, 0x18, 0x0a, 0x1b, 0x00, - 0x22, 0xf2, 0x34, 0xd4, 0x27, 0xe8, 0x13, 0x11, 0x1f, 0x19, 0x24, 0x1d, 0x18, 0x21, 0x22, 0x0f, - 0x1e, 0x14, 0x16, 0x49, 0x14, 0x22, 0x13, 0x1f, 0x1b, 0x2c, 0x13, 0x10, 0x0f, 0x24, 0x0f, 0x24, - 0x15, 0x1c, 0x19, 0x15, 0x1e, 0x14, 0x1f, 0x0c, 0x1b, 0x10, 0x18, 0x2a, 0x00, 0x5d, 0x0e, 0x38, - 0x0f, 0x39, 0x1a, 0x26, 0xe8, 0x7f, 0xe8, 0x73, 0xea, 0x52, 0xf7, 0x3e, 0x00, 0x35, 0x00, 0x3b, - 0xf2, 0x55, 0xf3, 0x59, 0xf3, 0x5e, 0xf5, 0x5c, 0xe3, 0x7f, 0xeb, 0x64, 0xf2, 0x39, 0xf4, 0x43, - 0xf5, 0x47, 0xf6, 0x4d, 0xeb, 0x55, 0xf0, 0x58, 0xe9, 0x68, 0xf1, 0x62, 0xdb, 0x7f, 0xf6, 0x52, - 0xf8, 0x30, 0xf8, 0x3d, 0xf8, 0x42, 0xf9, 0x46, 0xf2, 0x4b, 0xf6, 0x4f, 0xf7, 0x53, 0xf4, 0x5c, - 0xee, 0x6c, 0xfc, 0x4f, 0xea, 0x45, 0xf0, 0x4b, 0xfe, 0x3a, 0x01, 0x3a, 0xf3, 0x4e, 0xf7, 0x53, - 0xfc, 0x51, 0xf3, 0x63, 0xf3, 0x51, 0xfa, 0x26, 0xf3, 0x3e, 0xfa, 0x3a, 0xfe, 0x3b, 0xf0, 0x49, - 0xf6, 0x4c, 0xf3, 0x56, 0xf7, 0x53, 0xf6, 0x57, 0x00, 0x00, 0xea, 0x7f, 0xe7, 0x7f, 0xe7, 0x78, - 0xe5, 0x7f, 0xed, 0x72, 0xe9, 0x75, 0xe7, 0x76, 0xe6, 0x75, 0xe8, 0x71, 0xe4, 0x76, 0xe1, 0x78, - 0xdb, 0x7c, 0xf6, 0x5e, 0xf1, 0x66, 0xf6, 0x63, 0xf3, 0x6a, 0xce, 0x7f, 0xfb, 0x5c, 0x11, 0x39, - 0xfb, 0x56, 0xf3, 0x5e, 0xf4, 0x5b, 0xfe, 0x4d, 0x00, 0x47, 0xff, 0x49, 0x04, 0x40, 0xf9, 0x51, - 0x05, 0x40, 0x0f, 0x39, 0x01, 0x43, 0x00, 0x44, 0xf6, 0x43, 0x01, 0x44, 0x00, 0x4d, 0x02, 0x40, - 0x00, 0x44, 0xfb, 0x4e, 0x07, 0x37, 0x05, 0x3b, 0x02, 0x41, 0x0e, 0x36, 0x0f, 0x2c, 0x05, 0x3c, - 0x02, 0x46, 0xfe, 0x4c, 0xee, 0x56, 0x0c, 0x46, 0x05, 0x40, 0xf4, 0x46, 0x0b, 0x37, 0x05, 0x38, - 0x00, 0x45, 0x02, 0x41, 0xfa, 0x4a, 0x05, 0x36, 0x07, 0x36, 0xfa, 0x4c, 0xf5, 0x52, 0xfe, 0x4d, - 0xfe, 0x4d, 0x19, 0x2a, 0x11, 0xf3, 0x10, 0xf7, 0x11, 0xf4, 0x1b, 0xeb, 0x25, 0xe2, 0x29, 0xd8, - 0x2a, 0xd7, 0x30, 0xd1, 0x27, 0xe0, 0x2e, 0xd8, 0x34, 0xcd, 0x2e, 0xd7, 0x34, 0xd9, 0x2b, 0xed, - 0x20, 0x0b, 0x3d, 0xc9, 0x38, 0xd2, 0x3e, 0xce, 0x51, 0xbd, 0x2d, 0xec, 0x23, 0xfe, 0x1c, 0x0f, - 0x22, 0x01, 0x27, 0x01, 0x1e, 0x11, 0x14, 0x26, 0x12, 0x2d, 0x0f, 0x36, 0x00, 0x4f, 0x24, 0xf0, - 0x25, 0xf2, 0x25, 0xef, 0x20, 0x01, 0x22, 0x0f, 0x1d, 0x0f, 0x18, 0x19, 0x22, 0x16, 0x1f, 0x10, - 0x23, 0x12, 0x1f, 0x1c, 0x21, 0x29, 0x24, 0x1c, 0x1b, 0x2f, 0x15, 0x3e, 0x12, 0x1f, 0x13, 0x1a, - 0x24, 0x18, 0x18, 0x17, 0x1b, 0x10, 0x18, 0x1e, 0x1f, 0x1d, 0x16, 0x29, 0x16, 0x2a, 0x10, 0x3c, - 0x0f, 0x34, 0x0e, 0x3c, 0x03, 0x4e, 0xf0, 0x7b, 0x15, 0x35, 0x16, 0x38, 0x19, 0x3d, 0x15, 0x21, - 0x13, 0x32, 0x11, 0x3d, 0xfd, 0x4e, 0xf8, 0x4a, 0xf7, 0x48, 0xf6, 0x48, 0xee, 0x4b, 0xf4, 0x47, - 0xf5, 0x3f, 0xfb, 0x46, 0xef, 0x4b, 0xf2, 0x48, 0xf0, 0x43, 0xf8, 0x35, 0xf2, 0x3b, 0xf7, 0x34, - 0xf5, 0x44, 0x09, 0xfe, 0x1e, 0xf6, 0x1f, 0xfc, 0x21, 0xff, 0x21, 0x07, 0x1f, 0x0c, 0x25, 0x17, - 0x1f, 0x26, 0x14, 0x40, 0xf7, 0x47, 0xf9, 0x25, 0xf8, 0x2c, 0xf5, 0x31, 0xf6, 0x38, 0xf4, 0x3b, - 0xf8, 0x3f, 0xf7, 0x43, 0xfa, 0x44, 0xf6, 0x4f, 0xfd, 0x4e, 0xf8, 0x4a, 0xf7, 0x48, 0xf6, 0x48, - 0xee, 0x4b, 0xf4, 0x47, 0xf5, 0x3f, 0xfb, 0x46, 0xef, 0x4b, 0xf2, 0x48, 0xf0, 0x43, 0xf8, 0x35, - 0xf2, 0x3b, 0xf7, 0x34, 0xf5, 0x44, 0x09, 0xfe, 0x1e, 0xf6, 0x1f, 0xfc, 0x21, 0xff, 0x21, 0x07, - 0x1f, 0x0c, 0x25, 0x17, 0x1f, 0x26, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0x14, 0xf1, 0x02, 0x36, 0x03, 0x4a, 0xe4, 0x7f, 0xe9, 0x68, - 0xfa, 0x35, 0xff, 0x36, 0x07, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, - 0xf7, 0x53, 0x04, 0x56, 0x00, 0x61, 0xf9, 0x48, 0x0d, 0x29, 0x03, 0x3e, 0x00, 0x0b, 0x01, 0x37, - 0x00, 0x45, 0xef, 0x7f, 0xf3, 0x66, 0x00, 0x52, 0xf9, 0x4a, 0xeb, 0x6b, 0xe5, 0x7f, 0xe1, 0x7f, - 0xe8, 0x7f, 0xee, 0x5f, 0xe5, 0x7f, 0xeb, 0x72, 0xe2, 0x7f, 0xef, 0x7b, 0xf4, 0x73, 0xf0, 0x7a, - 0xf5, 0x73, 0xf4, 0x3f, 0xfe, 0x44, 0xf1, 0x54, 0xf3, 0x68, 0xfd, 0x46, 0xf8, 0x5d, 0xf6, 0x5a, - 0xe2, 0x7f, 0xff, 0x4a, 0xfa, 0x61, 0xf9, 0x5b, 0xec, 0x7f, 0xfc, 0x38, 0xfb, 0x52, 0xf9, 0x4c, - 0xea, 0x7d, 0xf9, 0x5d, 0xf5, 0x57, 0xfd, 0x4d, 0xfb, 0x47, 0xfc, 0x3f, 0xfc, 0x44, 0xf4, 0x54, - 0xf9, 0x3e, 0xf9, 0x41, 0x08, 0x3d, 0x05, 0x38, 0xfe, 0x42, 0x01, 0x40, 0x00, 0x3d, 0xfe, 0x4e, - 0x01, 0x32, 0x07, 0x34, 0x0a, 0x23, 0x00, 0x2c, 0x0b, 0x26, 0x01, 0x2d, 0x00, 0x2e, 0x05, 0x2c, - 0x1f, 0x11, 0x01, 0x33, 0x07, 0x32, 0x1c, 0x13, 0x10, 0x21, 0x0e, 0x3e, 0xf3, 0x6c, 0xf1, 0x64, - 0xf3, 0x65, 0xf3, 0x5b, 0xf4, 0x5e, 0xf6, 0x58, 0xf0, 0x54, 0xf6, 0x56, 0xf9, 0x53, 0xf3, 0x57, - 0xed, 0x5e, 0x01, 0x46, 0x00, 0x48, 0xfb, 0x4a, 0x12, 0x3b, 0xf8, 0x66, 0xf1, 0x64, 0x00, 0x5f, - 0xfc, 0x4b, 0x02, 0x48, 0xf5, 0x4b, 0xfd, 0x47, 0x0f, 0x2e, 0xf3, 0x45, 0x00, 0x3e, 0x00, 0x41, - 0x15, 0x25, 0xf1, 0x48, 0x09, 0x39, 0x10, 0x36, 0x00, 0x3e, 0x0c, 0x48, 0x18, 0x00, 0x0f, 0x09, - 0x08, 0x19, 0x0d, 0x12, 0x0f, 0x09, 0x0d, 0x13, 0x0a, 0x25, 0x0c, 0x12, 0x06, 0x1d, 0x14, 0x21, - 0x0f, 0x1e, 0x04, 0x2d, 0x01, 0x3a, 0x00, 0x3e, 0x07, 0x3d, 0x0c, 0x26, 0x0b, 0x2d, 0x0f, 0x27, - 0x0b, 0x2a, 0x0d, 0x2c, 0x10, 0x2d, 0x0c, 0x29, 0x0a, 0x31, 0x1e, 0x22, 0x12, 0x2a, 0x0a, 0x37, - 0x11, 0x33, 0x11, 0x2e, 0x00, 0x59, 0x1a, 0xed, 0x16, 0xef, 0x1a, 0xef, 0x1e, 0xe7, 0x1c, 0xec, - 0x21, 0xe9, 0x25, 0xe5, 0x21, 0xe9, 0x28, 0xe4, 0x26, 0xef, 0x21, 0xf5, 0x28, 0xf1, 0x29, 0xfa, - 0x26, 0x01, 0x29, 0x11, 0x1e, 0xfa, 0x1b, 0x03, 0x1a, 0x16, 0x25, 0xf0, 0x23, 0xfc, 0x26, 0xf8, - 0x26, 0xfd, 0x25, 0x03, 0x26, 0x05, 0x2a, 0x00, 0x23, 0x10, 0x27, 0x16, 0x0e, 0x30, 0x1b, 0x25, - 0x15, 0x3c, 0x0c, 0x44, 0x02, 0x61, 0xfd, 0x47, 0xfa, 0x2a, 0xfb, 0x32, 0xfd, 0x36, 0xfe, 0x3e, - 0x00, 0x3a, 0x01, 0x3f, 0xfe, 0x48, 0xff, 0x4a, 0xf7, 0x5b, 0xfb, 0x43, 0xfb, 0x1b, 0xfd, 0x27, - 0xfe, 0x2c, 0x00, 0x2e, 0xf0, 0x40, 0xf8, 0x44, 0xf6, 0x4e, 0xfa, 0x4d, 0xf6, 0x56, 0xf4, 0x5c, - 0xf1, 0x37, 0xf6, 0x3c, 0xfa, 0x3e, 0xfc, 0x41, 0xf4, 0x49, 0xf8, 0x4c, 0xf9, 0x50, 0xf7, 0x58, - 0xef, 0x6e, 0xf5, 0x61, 0xec, 0x54, 0xf5, 0x4f, 0xfa, 0x49, 0xfc, 0x4a, 0xf3, 0x56, 0xf3, 0x60, - 0xf5, 0x61, 0xed, 0x75, 0xf8, 0x4e, 0xfb, 0x21, 0xfc, 0x30, 0xfe, 0x35, 0xfd, 0x3e, 0xf3, 0x47, - 0xf6, 0x4f, 0xf4, 0x56, 0xf3, 0x5a, 0xf2, 0x61, 0x00, 0x00, 0xfa, 0x5d, 0xfa, 0x54, 0xf8, 0x4f, - 0x00, 0x42, 0xff, 0x47, 0x00, 0x3e, 0xfe, 0x3c, 0xfe, 0x3b, 0xfb, 0x4b, 0xfd, 0x3e, 0xfc, 0x3a, - 0xf7, 0x42, 0xff, 0x4f, 0x00, 0x47, 0x03, 0x44, 0x0a, 0x2c, 0xf9, 0x3e, 0x0f, 0x24, 0x0e, 0x28, - 0x10, 0x1b, 0x0c, 0x1d, 0x01, 0x2c, 0x14, 0x24, 0x12, 0x20, 0x05, 0x2a, 0x01, 0x30, 0x0a, 0x3e, - 0x11, 0x2e, 0x09, 0x40, 0xf4, 0x68, 0xf5, 0x61, 0xf0, 0x60, 0xf9, 0x58, 0xf8, 0x55, 0xf9, 0x55, - 0xf7, 0x55, 0xf3, 0x58, 0x04, 0x42, 0xfd, 0x4d, 0xfd, 0x4c, 0xfa, 0x4c, 0x0a, 0x3a, 0xff, 0x4c, - 0xff, 0x53, 0xf9, 0x63, 0xf2, 0x5f, 0x02, 0x5f, 0x00, 0x4c, 0xfb, 0x4a, 0x00, 0x46, 0xf5, 0x4b, - 0x01, 0x44, 0x00, 0x41, 0xf2, 0x49, 0x03, 0x3e, 0x04, 0x3e, 0xff, 0x44, 0xf3, 0x4b, 0x0b, 0x37, - 0x05, 0x40, 0x0c, 0x46, 0x0f, 0x06, 0x06, 0x13, 0x07, 0x10, 0x0c, 0x0e, 0x12, 0x0d, 0x0d, 0x0b, - 0x0d, 0x0f, 0x0f, 0x10, 0x0c, 0x17, 0x0d, 0x17, 0x0f, 0x14, 0x0e, 0x1a, 0x0e, 0x2c, 0x11, 0x28, - 0x11, 0x2f, 0x18, 0x11, 0x15, 0x15, 0x19, 0x16, 0x1f, 0x1b, 0x16, 0x1d, 0x13, 0x23, 0x0e, 0x32, - 0x0a, 0x39, 0x07, 0x3f, 0xfe, 0x4d, 0xfc, 0x52, 0xfd, 0x5e, 0x09, 0x45, 0xf4, 0x6d, 0x24, 0xdd, - 0x24, 0xde, 0x20, 0xe6, 0x25, 0xe2, 0x2c, 0xe0, 0x22, 0xee, 0x22, 0xf1, 0x28, 0xf1, 0x21, 0xf9, - 0x23, 0xfb, 0x21, 0x00, 0x26, 0x02, 0x21, 0x0d, 0x17, 0x23, 0x0d, 0x3a, 0x1d, 0xfd, 0x1a, 0x00, - 0x16, 0x1e, 0x1f, 0xf9, 0x23, 0xf1, 0x22, 0xfd, 0x22, 0x03, 0x24, 0xff, 0x22, 0x05, 0x20, 0x0b, - 0x23, 0x05, 0x22, 0x0c, 0x27, 0x0b, 0x1e, 0x1d, 0x22, 0x1a, 0x1d, 0x27, 0x13, 0x42, 0x1f, 0x15, - 0x1f, 0x1f, 0x19, 0x32, 0xef, 0x78, 0xec, 0x70, 0xee, 0x72, 0xf5, 0x55, 0xf1, 0x5c, 0xf2, 0x59, - 0xe6, 0x47, 0xf1, 0x51, 0xf2, 0x50, 0x00, 0x44, 0xf2, 0x46, 0xe8, 0x38, 0xe9, 0x44, 0xe8, 0x32, - 0xf5, 0x4a, 0x17, 0xf3, 0x1a, 0xf3, 0x28, 0xf1, 0x31, 0xf2, 0x2c, 0x03, 0x2d, 0x06, 0x2c, 0x22, - 0x21, 0x36, 0x13, 0x52, 0xfd, 0x4b, 0xff, 0x17, 0x01, 0x22, 0x01, 0x2b, 0x00, 0x36, 0xfe, 0x37, - 0x00, 0x3d, 0x01, 0x40, 0x00, 0x44, 0xf7, 0x5c, 0xf2, 0x6a, 0xf3, 0x61, 0xf1, 0x5a, 0xf4, 0x5a, - 0xee, 0x58, 0xf6, 0x49, 0xf7, 0x4f, 0xf2, 0x56, 0xf6, 0x49, 0xf6, 0x46, 0xf6, 0x45, 0xfb, 0x42, - 0xf7, 0x40, 0xfb, 0x3a, 0x02, 0x3b, 0x15, 0xf6, 0x18, 0xf5, 0x1c, 0xf8, 0x1c, 0xff, 0x1d, 0x03, - 0x1d, 0x09, 0x23, 0x14, 0x1d, 0x24, 0x0e, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff --git a/mpp/hal/rkdec/h264d/hal_h264d_reg.h b/mpp/hal/rkdec/h264d/hal_h264d_reg.h deleted file mode 100644 index aaa270b91..000000000 --- a/mpp/hal/rkdec/h264d/hal_h264d_reg.h +++ /dev/null @@ -1,307 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#ifndef __HAL_H264D_REG_H__ -#define __HAL_H264D_REG_H__ - -#include "mpp_hal.h" - -typedef struct h264_mmu_t { - RK_U32 mmu_dte_addr; - struct { - RK_U32 pageing_enabled : 1; - RK_U32 page_fault_active : 1; - RK_U32 stail_active : 1; - RK_U32 mmu_idle : 1; - RK_U32 replay_buffer_empty1 : 1; - RK_U32 page_fault_is_write : 1; - RK_U32 page_fault_bus_id : 5; - RK_U32 reserve : 8; - //RK_U32 field0000 : 1; - } mmu_status; - struct { - RK_U32 mmu_cmd : 3; - RK_U32 field0000 : 1; - } mmu_cmd; - - RK_U32 page_fault_addr; - RK_U32 mmu_zap_one_line; - struct int_rawstat { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } raw_stat; - struct int_clear { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } clear; - struct int_mask { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } mask; - struct int_status { - RK_U32 page_fault : 1; - RK_U32 read_bus_error : 1; - } status; - RK_U32 mmu_auto_gating : 1; -} H264_MMU_t; - -typedef struct h264_cache_t { - struct st_version { - RK_U32 version_minor : 8; - RK_U32 version_major : 8; - RK_U32 product_id : 16; - } version; - struct st_size { - RK_U32 line_size : 8; - RK_U32 associativity : 8; - RK_U32 cache_size : 8; - RK_U32 external_bus_width : 8; - } size; - struct st_status { - RK_U32 cmd_busy : 1; - RK_U32 data_busy : 1; - } status; - struct st_command { - RK_U32 command : 4; - RK_U32 sw_addrb_sel : 2; - } command; - RK_U32 clear_page; - RK_U32 max_reads : 5; - struct st_enable { - RK_U32 permit_cacheable_access : 1; - RK_U32 permit_cach_read_allocate : 1; - RK_U32 sw_readbuffer_counter_reject_en : 1; - RK_U32 sw_cache_clk_disgate : 1; - RK_U32 sw_cache_linsize : 1; - } enable; - RK_U32 perfcnt_src0; - RK_U32 perfcnt_val0; - RK_U32 perfcnt_src1; - RK_U32 perfcnt_val1; -} H264_CACHE_t; - -typedef struct h264_regs_t { - struct { - RK_U32 minor_ver : 8; - RK_U32 level : 1; - RK_U32 dec_support : 3; - RK_U32 profile : 1; - RK_U32 reserve0 : 1; - RK_U32 codec_flag : 1; - RK_U32 reserve1 : 1; - RK_U32 prod_num : 16; - } swreg0_id; - struct { - RK_U32 sw_dec_e : 1;//0 - RK_U32 sw_dec_clkgate_e : 1; // 1 - RK_U32 reserve0 : 1;// 2 - RK_U32 sw_timeout_mode : 1; // 3 - RK_U32 sw_dec_irq_dis : 1;//4 // 4 - RK_U32 sw_dec_timeout_e : 1; //5 - RK_U32 sw_buf_empty_en : 1; // 6 - RK_U32 sw_stmerror_waitdecfifo_empty : 1; // 7 - RK_U32 sw_dec_irq : 1; // 8 - RK_U32 sw_dec_irq_raw : 1; // 9 - RK_U32 reserve2 : 2; - RK_U32 sw_dec_rdy_sta : 1; //12 - RK_U32 sw_dec_bus_sta : 1; //13 - RK_U32 sw_dec_error_sta : 1; // 14 - RK_U32 sw_dec_timeout_sta : 1; //15 - RK_U32 sw_dec_empty_sta : 1; // 16 - RK_U32 sw_colmv_ref_error_sta : 1; // 17 - RK_U32 sw_cabu_end_sta : 1; // 18 - RK_U32 sw_h264orvp9_error_mode : 1; //19 - RK_U32 sw_softrst_en_p : 1; //20 - RK_U32 sw_force_softreset_valid : 1; //21 - RK_U32 sw_softreset_rdy : 1; // 22 - } swreg1_int; - struct { - RK_U32 sw_in_endian : 1; - RK_U32 sw_in_swap32_e : 1; - RK_U32 sw_in_swap64_e : 1; - RK_U32 sw_str_endian : 1; - RK_U32 sw_str_swap32_e : 1; - RK_U32 sw_str_swap64_e : 1; - RK_U32 sw_out_endian : 1; - RK_U32 sw_out_swap32_e : 1; - RK_U32 sw_out_cbcr_swap : 1; - RK_U32 reserve0 : 1; - RK_U32 sw_rlc_mode_direct_write : 1; - RK_U32 sw_rlc_mode : 1; - RK_U32 sw_strm_start_bit : 7; - RK_U32 reserve1 : 1; - RK_U32 sw_dec_mode : 2; - RK_U32 reserve2 : 2; - RK_U32 sw_h264_rps_mode : 1; - RK_U32 sw_h264_stream_mode : 1; - RK_U32 sw_h264_stream_lastpacket : 1; - RK_U32 sw_h264_firstslice_flag : 1; - RK_U32 sw_h264_frame_orslice : 1; - RK_U32 sw_buspr_slot_disable : 1; - } swreg2_sysctrl; - struct { - RK_U32 sw_y_hor_virstride : 9; - RK_U32 reserve : 2; - RK_U32 sw_slice_num_highbit : 1; - RK_U32 sw_uv_hor_virstride : 9; - RK_U32 sw_slice_num_lowbits : 11; - } swreg3_picpar; - struct { - RK_U32 reverse0 : 4; - RK_U32 sw_strm_rlc_base : 28; - } swreg4_strm_rlc_base; - struct { - RK_U32 sw_stream_len : 27; - } swreg5_stream_rlc_len; - struct { - RK_U32 reverse0 : 4; - RK_U32 sw_cabactbl_base : 28; - } swreg6_cabactbl_prob_base; - struct { - RK_U32 reverse0 : 4; - RK_U32 sw_decout_base : 28; - } swreg7_decout_base; - struct { - RK_U32 sw_y_virstride : 20; - } swreg8_y_virstride; - struct { - RK_U32 sw_yuv_virstride : 21; - } swreg9_yuv_virstride; - struct { - RK_U32 sw_ref_field : 1; - RK_U32 sw_ref_topfield_used : 1; - RK_U32 sw_ref_botfield_used : 1; - RK_U32 sw_ref_colmv_use_flag : 1; - RK_U32 sw_refer_base : 28; - } swreg10_24_refer0_14_base[15]; - RK_U32 swreg25_39_refer0_14_poc[15]; - struct { - RK_U32 sw_cur_poc : 32; - } swreg40_cur_poc; - struct { - RK_U32 reserve : 3; - RK_U32 sw_rlcwrite_base : 29; - } swreg41_rlcwrite_base; - struct { - RK_U32 reserve : 4; - RK_U32 sw_pps_base : 28; - } swreg42_pps_base; - struct swreg_sw_rps_base { - RK_U32 reserve : 4; - RK_U32 sw_rps_base : 28; - } swreg43_rps_base; - struct swreg_strmd_error_e { - RK_U32 sw_strmd_error_e : 28; - RK_U32 reserve : 4; - } swreg44_strmd_error_en; - struct { - RK_U32 sw_strmd_error_status : 28; - RK_U32 sw_colmv_error_ref_picidx : 4; - } swreg45_strmd_error_status; - struct { - RK_U32 sw_strmd_error_ctu_xoffset : 8; - RK_U32 sw_strmd_error_ctu_yoffset : 8; - RK_U32 sw_streamfifo_space2full : 7; - RK_U32 reserve : 1; - RK_U32 sw_vp9_error_ctu0_en : 1; - } swreg46_strmd_error_ctu; - struct { - RK_U32 sw_saowr_xoffet : 9; - RK_U32 reserve : 7; - RK_U32 sw_saowr_yoffset : 10; - } swreg47_sao_ctu_position; - struct { - RK_U32 sw_ref_field : 1; - RK_U32 sw_ref_topfield_used : 1; - RK_U32 sw_ref_botfield_used : 1; - RK_U32 sw_ref_colmv_use_flag : 1; - RK_U32 sw_refer_base : 28; - } swreg48_refer15_base; - RK_U32 swreg49_63_refer15_29_poc[15]; - struct { - RK_U32 sw_performance_cycle : 32; - } swreg64_performance_cycle; - struct { - RK_U32 sw_axi_ddr_rdata : 32; - } swreg65_axi_ddr_rdata; - struct { - RK_U32 sw_axi_ddr_rdata : 32; - } swreg66_axi_ddr_wdata; - struct { - RK_U32 sw_busifd_resetn : 1; - RK_U32 sw_cabac_resetn : 1; - RK_U32 sw_dec_ctrl_resetn : 1; - RK_U32 sw_transd_resetn : 1; - RK_U32 sw_intra_resetn : 1; - RK_U32 sw_inter_resetn : 1; - RK_U32 sw_recon_resetn : 1; - RK_U32 sw_filer_resetn : 1; - } swreg67_fpgadebug_reset; - struct { - RK_U32 perf_cnt0_sel : 6; - RK_U32 reserve0 : 2; - RK_U32 perf_cnt1_sel : 6; - RK_U32 reserve1 : 2; - RK_U32 perf_cnt2_sel : 6; - } swreg68_performance_sel; - struct { - RK_U32 perf_cnt0 : 32; - } swreg69_performance_cnt0; - struct { - RK_U32 perf_cnt1 : 32; - } swreg70_performance_cnt1; - struct { - RK_U32 perf_cnt2 : 32; - } swreg71_performance_cnt2; - RK_U32 swreg72_refer30_poc; - RK_U32 swreg73_refer31_poc; - struct { - RK_U32 sw_h264_cur_poc1 : 32; - } swreg74_h264_cur_poc1; - struct { - RK_U32 reserve : 4; - RK_U32 sw_errorinfo_base : 28; - } swreg75_h264_errorinfo_base; - struct { - RK_U32 sw_slicedec_num : 14; - RK_U32 reserve : 1; - RK_U32 sw_strmd_detect_error_flag : 1; - RK_U32 sw_error_packet_num : 14; - } swreg76_h264_errorinfo_num; - struct { - RK_U32 sw_h264_error_en_highbits : 30; - RK_U32 reserve : 2; - } swreg77_h264_error_e; - RK_U32 compare_len; -} H264_REGS_t; - - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const RK_U8 H264_Cabac_table[]; - - - -#ifdef __cplusplus -} -#endif - -#endif /*__HAL_H264D_REG_H__*/ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_rkv_reg.c b/mpp/hal/rkdec/h264d/hal_h264d_rkv_reg.c new file mode 100644 index 000000000..839c00a0e --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_rkv_reg.c @@ -0,0 +1,694 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define MODULE_TAG "hal_h264d_rkv_reg" + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_bitput.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_rkv_reg.h" +#include "mpp_dec_cb_param.h" +#include "hal_h264d_com.h" + +/* Number registers for the decoder */ +#define DEC_RKV_REGISTERS 78 + +#define RKV_CABAC_TAB_SIZE (928*4 + 128) /* bytes */ +#define RKV_SPSPPS_SIZE (256*32 + 128) /* bytes */ +#define RKV_RPS_SIZE (128 + 128) /* bytes */ +#define RKV_SCALING_LIST_SIZE (6*16+2*64 + 128) /* bytes */ +#define RKV_ERROR_INFO_SIZE (256*144*4) /* bytes */ + +typedef struct h264d_rkv_buf_t { + RK_U32 valid; + MppBuffer spspps; + MppBuffer rps; + MppBuffer sclst; + H264dRkvRegs_t *regs; +} H264dRkvBuf_t; + +typedef struct h264d_rkv_reg_ctx_t { + RK_U8 spspps[32]; + RK_U8 rps[RKV_RPS_SIZE]; + RK_U8 sclst[RKV_SCALING_LIST_SIZE]; + + MppBuffer cabac_buf; + MppBuffer errinfo_buf; + H264dRkvBuf_t reg_buf[3]; + + MppBuffer spspps_buf; + MppBuffer rps_buf; + MppBuffer sclst_buf; + H264dRkvRegs_t *regs; +} H264dRkvRegCtx_t; + +MPP_RET rkv_h264d_deinit(void *hal); + +static MPP_RET prepare_spspps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0; + RK_S32 is_long_term = 0, voidx = 0; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + + BitputCtx_t bp; + + mpp_set_bitput_ctx(&bp, data, len); + //!< sps syntax + { + mpp_put_bits(&bp, -1, 4); //!< seq_parameter_set_id + mpp_put_bits(&bp, -1, 8); //!< profile_idc + mpp_put_bits(&bp, -1, 1); //!< constraint_set3_flag + mpp_put_bits(&bp, pp->chroma_format_idc, 2); + mpp_put_bits(&bp, pp->bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, pp->bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, 0, 1); //!< qpprime_y_zero_transform_bypass_flag + mpp_put_bits(&bp, pp->log2_max_frame_num_minus4, 4); + mpp_put_bits(&bp, pp->num_ref_frames, 5); + mpp_put_bits(&bp, pp->pic_order_cnt_type, 2); + mpp_put_bits(&bp, pp->log2_max_pic_order_cnt_lsb_minus4, 4); + mpp_put_bits(&bp, pp->delta_pic_order_always_zero_flag, 1); + mpp_put_bits(&bp, (pp->wFrameWidthInMbsMinus1 + 1), 9); + mpp_put_bits(&bp, (pp->wFrameHeightInMbsMinus1 + 1), 9); + mpp_put_bits(&bp, pp->frame_mbs_only_flag, 1); + mpp_put_bits(&bp, pp->MbaffFrameFlag, 1); + mpp_put_bits(&bp, pp->direct_8x8_inference_flag, 1); + + mpp_put_bits(&bp, 1, 1); //!< mvc_extension_enable + mpp_put_bits(&bp, (pp->num_views_minus1 + 1), 2); + mpp_put_bits(&bp, pp->view_id[0], 10); + mpp_put_bits(&bp, pp->view_id[1], 10); + mpp_put_bits(&bp, pp->num_anchor_refs_l0[0], 1); + if (pp->num_anchor_refs_l0[0]) { + mpp_put_bits(&bp, pp->anchor_ref_l0[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); + } + mpp_put_bits(&bp, pp->num_anchor_refs_l1[0], 1); + if (pp->num_anchor_refs_l1[0]) { + mpp_put_bits(&bp, pp->anchor_ref_l1[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); //!< anchor_ref_l1 + } + mpp_put_bits(&bp, pp->num_non_anchor_refs_l0[0], 1); + if (pp->num_non_anchor_refs_l0[0]) { + mpp_put_bits(&bp, pp->non_anchor_ref_l0[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); //!< non_anchor_ref_l0 + } + mpp_put_bits(&bp, pp->num_non_anchor_refs_l1[0], 1); + if (pp->num_non_anchor_refs_l1[0]) { + mpp_put_bits(&bp, pp->non_anchor_ref_l1[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10);//!< non_anchor_ref_l1 + } + mpp_put_align(&bp, 32, 0); + } + //!< pps syntax + { + H264dRkvRegCtx_t *reg_ctx = (H264dRkvRegCtx_t *)p_hal->reg_ctx; + + mpp_put_bits(&bp, -1, 8); //!< pps_pic_parameter_set_id + mpp_put_bits(&bp, -1, 5); //!< pps_seq_parameter_set_id + mpp_put_bits(&bp, pp->entropy_coding_mode_flag, 1); + mpp_put_bits(&bp, pp->pic_order_present_flag, 1); + mpp_put_bits(&bp, pp->num_ref_idx_l0_active_minus1, 5); + mpp_put_bits(&bp, pp->num_ref_idx_l1_active_minus1, 5); + mpp_put_bits(&bp, pp->weighted_pred_flag, 1); + mpp_put_bits(&bp, pp->weighted_bipred_idc, 2); + mpp_put_bits(&bp, pp->pic_init_qp_minus26, 7); + mpp_put_bits(&bp, pp->pic_init_qs_minus26, 6); + mpp_put_bits(&bp, pp->chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->deblocking_filter_control_present_flag, 1); + mpp_put_bits(&bp, pp->constrained_intra_pred_flag, 1); + mpp_put_bits(&bp, pp->redundant_pic_cnt_present_flag, 1); + mpp_put_bits(&bp, pp->transform_8x8_mode_flag, 1); + mpp_put_bits(&bp, pp->second_chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->scaleing_list_enable_flag, 1); + mpp_put_bits(&bp, mpp_buffer_get_fd(reg_ctx->sclst_buf), 32); + } + //!< set dpb + for (i = 0; i < 16; i++) { + is_long_term = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefFrameList[i].AssociatedFlag : 0; + mpp_put_bits(&bp, is_long_term, 1); + } + for (i = 0; i < 16; i++) { + voidx = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefPicLayerIdList[i] : 0; + mpp_put_bits(&bp, voidx, 1); + } + mpp_put_align(&bp, 64, 0); + + return MPP_OK; +} + +static MPP_RET prepare_framerps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0, j = 0; + RK_S32 dpb_idx = 0, voidx = 0; + RK_S32 dpb_valid = 0, bottom_flag = 0; + RK_U32 max_frame_num = 0; + RK_U16 frame_num_wrap = 0; + + BitputCtx_t bp; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + + mpp_set_bitput_ctx(&bp, data, len); + + max_frame_num = 1 << (pp->log2_max_frame_num_minus4 + 4); + for (i = 0; i < 16; i++) { + if ((pp->NonExistingFrameFlags >> i) & 0x01) { + frame_num_wrap = 0; + } else { + if (pp->RefFrameList[i].AssociatedFlag) { + frame_num_wrap = pp->FrameNumList[i]; + } else { + frame_num_wrap = (pp->FrameNumList[i] > pp->frame_num) ? + (pp->FrameNumList[i] - max_frame_num) : pp->FrameNumList[i]; + } + } + + mpp_put_bits(&bp, frame_num_wrap, 16); + } + for (i = 0; i < 16; i++) { + mpp_put_bits(&bp, 0, 1);//!< NULL + } + for (i = 0; i < 16; i++) { + mpp_put_bits(&bp, pp->RefPicLayerIdList[i], 1); //!< voidx + } + for (i = 0; i < 32; i++) { + dpb_valid = (p_hal->slice_long[0].RefPicList[0][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + mpp_put_bits(&bp, dpb_idx | (dpb_valid << 4), 5); //!< dpb_idx + mpp_put_bits(&bp, bottom_flag, 1); + mpp_put_bits(&bp, voidx, 1); + } + for (j = 1; j < 3; j++) { + for (i = 0; i < 32; i++) { + dpb_valid = (p_hal->slice_long[0].RefPicList[j][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + mpp_put_bits(&bp, dpb_idx | (dpb_valid << 4), 5); //!< dpb_idx + mpp_put_bits(&bp, bottom_flag, 1); + mpp_put_bits(&bp, voidx, 1); + } + } + mpp_put_align(&bp, 128, 0); + + return MPP_OK; +} + +static MPP_RET prepare_scanlist(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0, j = 0; + + if (p_hal->pp->scaleing_list_enable_flag) { + BitputCtx_t bp; + mpp_set_bitput_ctx(&bp, data, len); + + for (i = 0; i < 6; i++) { //!< 4x4, 6 lists + for (j = 0; j < 16; j++) { + mpp_put_bits(&bp, p_hal->qm->bScalingLists4x4[i][j], 8); + } + + } + for (i = 0; i < 2; i++) { //!< 8x8, 2 lists + for (j = 0; j < 64; j++) { + mpp_put_bits(&bp, p_hal->qm->bScalingLists8x8[i][j], 8); + } + } + } + return MPP_OK; +} + +static MPP_RET set_registers(H264dHalCtx_t *p_hal, H264dRkvRegs_t *p_regs, HalTaskInfo *task) +{ + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + MppHalCfg *cfg = p_hal->cfg; + + memset(p_regs, 0, sizeof(H264dRkvRegs_t)); + //!< set dec_mode && rlc_mode && rps_mode && slice_num + { + p_regs->sw02.dec_mode = 1; //!< h264 + if (p_regs->sw02.rlc_mode == 1) { + p_regs->sw05.stream_len = 0; + } else { + p_regs->sw05.stream_len = p_hal->strm_len; + } + if (p_regs->sw02.rps_mode) { // rps_mode == 1 + p_regs->sw43.rps_base += 0x8; + } + p_regs->sw03.slice_num_lowbits = 0x7ff; + p_regs->sw03.slice_num_highbit = 1; + } + //!< caculate the yuv_frame_size + { + MppFrame mframe = NULL; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 yuv_virstride = 0; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + + if (pp->chroma_format_idc == 0) { //!< Y400 + yuv_virstride = y_virstride; + } else if (pp->chroma_format_idc == 1) { //!< Y420 + yuv_virstride = y_virstride + y_virstride / 2; + } else if (pp->chroma_format_idc == 2) { //!< Y422 + yuv_virstride = 2 * y_virstride; + } + p_regs->sw03.y_hor_virstride = hor_virstride / 16; + p_regs->sw03.uv_hor_virstride = hor_virstride / 16; + p_regs->sw08.y_virstride = y_virstride / 16; + p_regs->sw09.yuv_virstride = yuv_virstride / 16; + } + //!< set current + { + MppBuffer mbuffer = NULL; + p_regs->sw40.cur_poc = pp->CurrFieldOrderCnt[0]; + p_regs->sw74.cur_poc1 = pp->CurrFieldOrderCnt[1]; + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + p_regs->sw07.decout_base = mpp_buffer_get_fd(mbuffer); + } + //!< set reference + { + RK_S32 i = 0; + RK_S32 ref_index = -1; + RK_S32 near_index = -1; + RK_U32 sw10_24_offset = 0; + RK_U32 sw48_offset = 0; + MppBuffer mbuffer = NULL; + + for (i = 0; i < 15; i++) { + p_regs->sw25_39[i].ref0_14_poc = ((i & 1) != 0) + ? pp->FieldOrderCntList[i / 2][1] : pp->FieldOrderCntList[i / 2][0]; + p_regs->sw49_63[i].ref15_29_poc = ((i & 1) != 0) + ? pp->FieldOrderCntList[(i + 15) / 2][0] : pp->FieldOrderCntList[(i + 15) / 2][1]; + sw10_24_offset = ((pp->RefPicFiledFlags >> i) & 0x01) | + ((pp->UsedForReferenceFlags >> (2 * i + 0)) & 0x01) << 0x01 | + ((pp->UsedForReferenceFlags >> (2 * i + 1)) & 0x01) << 0x02 | + ((pp->RefPicColmvUsedFlags >> i) & 0x01) << 0x03; + mpp_dev_set_reg_offset(cfg->dev, 10 + i, sw10_24_offset); + + if (pp->RefFrameList[i].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[i].Index7Bits; + near_index = pp->RefFrameList[i].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_BUFFER, &mbuffer); + p_regs->sw10_24[i].ref0_14_base = mpp_buffer_get_fd(mbuffer); + } + p_regs->sw72.ref30_poc = pp->FieldOrderCntList[15][0]; + p_regs->sw73.ref31_poc = pp->FieldOrderCntList[15][1]; + sw48_offset = ((pp->RefPicFiledFlags >> 15) & 0x01) | + ((pp->UsedForReferenceFlags >> 30) & 0x01) << 0x01 | + ((pp->UsedForReferenceFlags >> 31) & 0x01) << 0x02 | + ((pp->RefPicColmvUsedFlags >> 15) & 0x01) << 0x03; + mpp_dev_set_reg_offset(cfg->dev, 48, sw48_offset); + + if (pp->RefFrameList[15].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[15].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_BUFFER, &mbuffer); + p_regs->sw48.ref15_base = mpp_buffer_get_fd(mbuffer); + } + { + MppBuffer mbuffer = NULL; + H264dRkvRegCtx_t *reg_ctx = (H264dRkvRegCtx_t *)p_hal->reg_ctx; + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + p_regs->sw04.strm_rlc_base = mpp_buffer_get_fd(mbuffer); + p_regs->sw06.cabactbl_base = mpp_buffer_get_fd(reg_ctx->cabac_buf); + p_regs->sw41.rlcwrite_base = p_regs->sw04.strm_rlc_base; + } + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* init +*********************************************************************** +*/ +//extern "C" +MPP_RET rkv_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + MppBufferGroup group = cfg->buf_group; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + p_hal->cfg = cfg; + + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(H264dRkvRegCtx_t))); + H264dRkvRegCtx_t *reg_ctx = (H264dRkvRegCtx_t *)p_hal->reg_ctx; + //!< malloc buffers + FUN_CHECK(ret = mpp_buffer_get(group, ®_ctx->cabac_buf, RKV_CABAC_TAB_SIZE)); + FUN_CHECK(ret = mpp_buffer_get(group, ®_ctx->errinfo_buf, RKV_ERROR_INFO_SIZE)); + // malloc buffers + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + for (i = 0; i < loop; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(H264dRkvRegs_t, 1); + FUN_CHECK(ret = mpp_buffer_get(group, ®_ctx->reg_buf[i].spspps, RKV_SPSPPS_SIZE)); + FUN_CHECK(ret = mpp_buffer_get(group, ®_ctx->reg_buf[i].rps, RKV_RPS_SIZE)); + FUN_CHECK(ret = mpp_buffer_get(group, ®_ctx->reg_buf[i].sclst, RKV_SCALING_LIST_SIZE)); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->spspps_buf = reg_ctx->reg_buf[0].spspps; + reg_ctx->rps_buf = reg_ctx->reg_buf[0].rps; + reg_ctx->sclst_buf = reg_ctx->reg_buf[0].sclst; + } + + //!< copy cabac table bytes + FUN_CHECK(ret = mpp_buffer_write(reg_ctx->cabac_buf, 0, + (void *)rkv_cabac_table, sizeof(rkv_cabac_table))); + mpp_buffer_sync_end(reg_ctx->cabac_buf); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + +__RETURN: + return MPP_OK; +__FAILED: + rkv_h264d_deinit(hal); + + return ret; +} +/*! +*********************************************************************** +* \brief +* deinit +*********************************************************************** +*/ +//extern "C" +MPP_RET rkv_h264d_deinit(void *hal) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264dRkvRegCtx_t *reg_ctx = (H264dRkvRegCtx_t *)p_hal->reg_ctx; + + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + for (i = 0; i < loop; i++) { + MPP_FREE(reg_ctx->reg_buf[i].regs); + mpp_buffer_put(reg_ctx->reg_buf[i].spspps); + mpp_buffer_put(reg_ctx->reg_buf[i].rps); + mpp_buffer_put(reg_ctx->reg_buf[i].sclst); + } + mpp_buffer_put(reg_ctx->cabac_buf); + mpp_buffer_put(reg_ctx->errinfo_buf); + MPP_FREE(p_hal->reg_ctx); + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* generate register +*********************************************************************** +*/ +//extern "C" +MPP_RET rkv_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + H264dRkvRegCtx_t *reg_ctx = (H264dRkvRegCtx_t *)p_hal->reg_ctx; + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(reg_ctx->reg_buf); i++) { + if (!reg_ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + reg_ctx->spspps_buf = reg_ctx->reg_buf[i].spspps; + reg_ctx->rps_buf = reg_ctx->reg_buf[i].rps; + reg_ctx->sclst_buf = reg_ctx->reg_buf[i].sclst; + reg_ctx->regs = reg_ctx->reg_buf[i].regs; + reg_ctx->reg_buf[i].valid = 1; + break; + } + } + } + + prepare_spspps(p_hal, (RK_U64 *)reg_ctx->spspps, sizeof(reg_ctx->spspps)); + prepare_framerps(p_hal, (RK_U64 *)reg_ctx->rps, sizeof(reg_ctx->rps)); + prepare_scanlist(p_hal, (RK_U64 *)reg_ctx->sclst, sizeof(reg_ctx->sclst)); + set_registers(p_hal, reg_ctx->regs, task); + + //!< copy datas + RK_U32 i = 0; + for (i = 0; i < 256; i++) { + mpp_buffer_write(reg_ctx->spspps_buf, + (sizeof(reg_ctx->spspps) * i), (void *)reg_ctx->spspps, + sizeof(reg_ctx->spspps)); + } + reg_ctx->regs->sw42.pps_base = mpp_buffer_get_fd(reg_ctx->spspps_buf); + + mpp_buffer_write(reg_ctx->rps_buf, 0, + (void *)reg_ctx->rps, sizeof(reg_ctx->rps)); + reg_ctx->regs->sw43.rps_base = mpp_buffer_get_fd(reg_ctx->rps_buf); + + mpp_buffer_write(reg_ctx->sclst_buf, 0, + (void *)reg_ctx->sclst, sizeof(reg_ctx->sclst)); + reg_ctx->regs->sw75.errorinfo_base = mpp_buffer_get_fd(reg_ctx->errinfo_buf); + mpp_buffer_sync_end(reg_ctx->spspps_buf); + mpp_buffer_sync_end(reg_ctx->rps_buf); + mpp_buffer_sync_end(reg_ctx->sclst_buf); + +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief h +* start hard +*********************************************************************** +*/ +//extern "C" +MPP_RET rkv_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + H264dRkvRegCtx_t *reg_ctx = (H264dRkvRegCtx_t *)p_hal->reg_ctx; + RK_U32 *p_regs = (p_hal->fast_mode != 0) ? + (RK_U32 *)reg_ctx->reg_buf[task->dec.reg_index].regs : + (RK_U32 *)reg_ctx->regs; + + p_regs[64] = 0; + p_regs[65] = 0; + p_regs[66] = 0; + p_regs[67] = 0x000000ff; // disable fpga reset + p_regs[44] = 0xfffffff7; // 0xffff_ffff, debug enable + p_regs[77] = 0xffffffff; // 0xffff_dfff, debug enable + + p_regs[1] |= 0x00000061; // run hardware, enable buf_empty_en + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = DEC_RKV_REGISTERS * sizeof(RK_U32); + MppDev dev = p_hal->cfg->dev; + + wr_cfg.reg = p_regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = p_regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* wait hard +*********************************************************************** +*/ +//extern "C" +MPP_RET rkv_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + H264dRkvRegCtx_t *reg_ctx = (H264dRkvRegCtx_t *)p_hal->reg_ctx; + H264dRkvRegs_t *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + + if (p_regs->sw01.dec_error_sta + || (!p_regs->sw01.dec_rdy_sta) + || p_regs->sw01.dec_empty_sta + || p_regs->sw45.strmd_error_status + || p_regs->sw45.colmv_error_ref_picidx + || p_regs->sw76.strmd_detect_error_flag) + param.hard_err = 1; + else + param.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + memset(&p_regs->sw01, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) { + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + } + + (void)task; +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* control +*********************************************************************** +*/ +//extern "C" +MPP_RET rkv_h264d_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + RK_U32 imgwidth = mpp_frame_get_width((MppFrame)param); + RK_U32 imgheight = mpp_frame_get_height((MppFrame)param); + + mpp_log("control info: fmt %d, w %d, h %d\n", fmt, imgwidth, imgheight); + if (fmt == MPP_FMT_YUV422SP) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } + if (imgwidth > 1920 || imgheight > 1088) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + } + break; + } + + default: + break; + } + +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_rkvdpu = { + .name = "h264d_rkvdpu", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = rkv_h264d_init, + .deinit = rkv_h264d_deinit, + .reg_gen = rkv_h264d_gen_regs, + .start = rkv_h264d_start, + .wait = rkv_h264d_wait, + .reset = vdpu_h264d_reset, + .flush = vdpu_h264d_flush, + .control = rkv_h264d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RV1108, + ROCKCHIP_SOC_RV1109, + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_rkvdpu) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_rkv_reg.h b/mpp/hal/rkdec/h264d/hal_h264d_rkv_reg.h new file mode 100644 index 000000000..0c449c8bf --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_rkv_reg.h @@ -0,0 +1,243 @@ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef HAL_H264D_RKV_REG_H +#define HAL_H264D_RKV_REG_H + +#include "mpp_hal.h" + +typedef struct h264d_rkv_regs_t { + struct { + RK_U32 minor_ver : 8; + RK_U32 level : 1; + RK_U32 dec_support : 3; + RK_U32 profile : 1; + RK_U32 reserve0 : 1; + RK_U32 codec_flag : 1; + RK_U32 reserve1 : 1; + RK_U32 prod_num : 16; + } sw00; + struct { + RK_U32 dec_e : 1;//0 + RK_U32 dec_clkgate_e : 1; // 1 + RK_U32 reserve0 : 1;// 2 + RK_U32 timeout_mode : 1; // 3 + RK_U32 dec_irq_dis : 1;//4 // 4 + RK_U32 dec_timeout_e : 1; //5 + RK_U32 buf_empty_en : 1; // 6 + RK_U32 stmerror_waitdecfifo_empty : 1; // 7 + RK_U32 dec_irq : 1; // 8 + RK_U32 dec_irq_raw : 1; // 9 + RK_U32 reserve2 : 2; + RK_U32 dec_rdy_sta : 1; //12 + RK_U32 dec_bus_sta : 1; //13 + RK_U32 dec_error_sta : 1; // 14 + RK_U32 dec_timeout_sta : 1; //15 + RK_U32 dec_empty_sta : 1; // 16 + RK_U32 colmv_ref_error_sta : 1; // 17 + RK_U32 cabu_end_sta : 1; // 18 + RK_U32 h264orvp9_error_mode : 1; //19 + RK_U32 softrst_en_p : 1; //20 + RK_U32 force_softreset_valid : 1; //21 + RK_U32 softreset_rdy : 1; // 22 + RK_U32 reserve1 : 9; + } sw01; + struct { + RK_U32 in_endian : 1; + RK_U32 in_swap32_e : 1; + RK_U32 in_swap64_e : 1; + RK_U32 str_endian : 1; + RK_U32 str_swap32_e : 1; + RK_U32 str_swap64_e : 1; + RK_U32 out_endian : 1; + RK_U32 out_swap32_e : 1; + RK_U32 out_cbcr_swap : 1; + RK_U32 reserve0 : 1; + RK_U32 rlc_mode_direct_write : 1; + RK_U32 rlc_mode : 1; + RK_U32 strm_start_bit : 7; + RK_U32 reserve1 : 1; + RK_U32 dec_mode : 2; + RK_U32 reserve2 : 2; + RK_U32 rps_mode : 1; + RK_U32 stream_mode : 1; + RK_U32 stream_lastpacket : 1; + RK_U32 firstslice_flag : 1; + RK_U32 frame_orslice : 1; + RK_U32 buspr_slot_disable : 1; + RK_U32 reverse3 : 2; + } sw02; + struct { + RK_U32 y_hor_virstride : 9; + RK_U32 reserve : 2; + RK_U32 slice_num_highbit : 1; + RK_U32 uv_hor_virstride : 9; + RK_U32 slice_num_lowbits : 11; + } sw03; + struct { + RK_U32 strm_rlc_base : 32; + } sw04; + struct { + RK_U32 stream_len : 27; + RK_U32 reverse0 : 5; + } sw05; + struct { + RK_U32 cabactbl_base : 32; + } sw06; + struct { + RK_U32 decout_base : 32; + } sw07; + struct { + RK_U32 y_virstride : 20; + RK_U32 reverse0 : 12; + } sw08; + struct { + RK_U32 yuv_virstride : 21; + RK_U32 reverse0 : 11; + } sw09; + struct { + /* bit0: ref0_14_field + * bit1: ref0_14_topfield_used + * bit2: ref0_14_botfield_used + * bit3: ref0_14_colmv_use_flag + */ + RK_U32 ref0_14_base; /* bit4-bit31 */ + } sw10_24[15]; + struct { + RK_U32 ref0_14_poc : 32; + } sw25_39[15]; + struct { + RK_U32 cur_poc : 32; + } sw40; + struct { + RK_U32 rlcwrite_base; + } sw41; + struct { + RK_U32 pps_base; + } sw42; + struct { + RK_U32 rps_base; + } sw43; + struct { + RK_U32 strmd_error_e : 28; + RK_U32 reserve : 4; + } sw44; + struct { + RK_U32 strmd_error_status : 28; + RK_U32 colmv_error_ref_picidx : 4; + } sw45; + struct { + RK_U32 strmd_error_ctu_xoffset : 8; + RK_U32 strmd_error_ctu_yoffset : 8; + RK_U32 streamfifo_space2full : 7; + RK_U32 reserve0 : 1; + RK_U32 vp9_error_ctu0_en : 1; + RK_U32 reverse1 : 7; + } sw46; + struct { + RK_U32 saowr_xoffet : 9; + RK_U32 reserve0 : 7; + RK_U32 saowr_yoffset : 10; + RK_U32 reverse1 : 6; + } sw47; + struct { + /* bit0: ref15_field + * bit1: ref15_topfield_used + * bit2: ref15_botfield_used + * bit3: ref15_colmv_use_flag + */ + RK_U32 ref15_base; /* bit4-bit31 */ + } sw48; + struct { + RK_U32 ref15_29_poc : 32; + } sw49_63[15]; + struct { + RK_U32 performance_cycle : 32; + } sw64; + struct { + RK_U32 axi_ddr_rdata : 32; + } sw65; + struct { + RK_U32 axi_ddr_rdata : 32; + } sw66; + struct { + RK_U32 busifd_resetn : 1; + RK_U32 cabac_resetn : 1; + RK_U32 dec_ctrl_resetn : 1; + RK_U32 transd_resetn : 1; + RK_U32 intra_resetn : 1; + RK_U32 inter_resetn : 1; + RK_U32 recon_resetn : 1; + RK_U32 filer_resetn : 1; + RK_U32 reverse0 : 24; + } sw67; + struct { + RK_U32 perf_cnt0_sel : 6; + RK_U32 reserve0 : 2; + RK_U32 perf_cnt1_sel : 6; + RK_U32 reserve1 : 2; + RK_U32 perf_cnt2_sel : 6; + RK_U32 reverse1 : 10; + } sw68; + struct { + RK_U32 perf_cnt0 : 32; + } sw69; + struct { + RK_U32 perf_cnt1 : 32; + } sw70; + struct { + RK_U32 perf_cnt2 : 32; + } sw71; + struct { + RK_U32 ref30_poc; + } sw72; + struct { + RK_U32 ref31_poc; + } sw73; + struct { + RK_U32 cur_poc1 : 32; + } sw74; + struct { + RK_U32 errorinfo_base : 32; + } sw75; + struct { + RK_U32 slicedec_num : 14; + RK_U32 reserve0 : 1; + RK_U32 strmd_detect_error_flag : 1; + RK_U32 error_packet_num : 14; + RK_U32 reverse1 : 2; + } sw76; + struct { + RK_U32 error_en_highbits : 30; + RK_U32 reserve : 2; + } sw77; + RK_U32 reverse[2]; +} H264dRkvRegs_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_rkvdpu; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_RKV_REG_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu1.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu1.c new file mode 100644 index 000000000..8207406f7 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu1.c @@ -0,0 +1,1069 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264d_vdpu1_reg" + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_vdpu_com.h" +#include "hal_h264d_vdpu1.h" +#include "hal_h264d_vdpu1_reg.h" +#include "hal_h264d_com.h" +#include "mpp_dec_cb_param.h" + +const RK_U32 vdpu1_ref_idx[16] = { + 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29 +}; + +MPP_RET vdpu1_h264d_deinit(void *hal); +static MPP_RET vdpu1_set_refer_pic_idx(H264dVdpu1Regs_t *p_regs, RK_U32 i, + RK_U16 val) +{ + switch (i) { + case 0: + p_regs->SwReg30.sw_refer0_nbr = val; + break; + case 1: + p_regs->SwReg30.sw_refer1_nbr = val; + break; + case 2: + p_regs->SwReg31.sw_refer2_nbr = val; + break; + case 3: + p_regs->SwReg31.sw_refer3_nbr = val; + break; + case 4: + p_regs->SwReg32.sw_refer4_nbr = val; + break; + case 5: + p_regs->SwReg32.sw_refer5_nbr = val; + break; + case 6: + p_regs->SwReg33.sw_refer6_nbr = val; + break; + case 7: + p_regs->SwReg33.sw_refer7_nbr = val; + break; + case 8: + p_regs->SwReg34.sw_refer8_nbr = val; + break; + case 9: + p_regs->SwReg34.sw_refer9_nbr = val; + break; + case 10: + p_regs->SwReg35.sw_refer10_nbr = val; + break; + case 11: + p_regs->SwReg35.sw_refer11_nbr = val; + break; + case 12: + p_regs->SwReg36.sw_refer12_nbr = val; + break; + case 13: + p_regs->SwReg36.sw_refer13_nbr = val; + break; + case 14: + p_regs->SwReg37.sw_refer14_nbr = val; + break; + case 15: + p_regs->SwReg37.sw_refer15_nbr = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET vdpu1_set_refer_pic_list_p(H264dVdpu1Regs_t *p_regs, RK_U32 i, + RK_U16 val) +{ + switch (i) { + case 0: + p_regs->SwReg47.sw_pinit_rlist_f0 = val; + break; + case 1: + p_regs->SwReg47.sw_pinit_rlist_f1 = val; + break; + case 2: + p_regs->SwReg47.sw_pinit_rlist_f2 = val; + break; + case 3: + p_regs->SwReg47.sw_pinit_rlist_f3 = val; + break; + case 4: + p_regs->SwReg10.sw_pinit_rlist_f4 = val; + break; + case 5: + p_regs->SwReg10.sw_pinit_rlist_f5 = val; + break; + case 6: + p_regs->SwReg10.sw_pinit_rlist_f6 = val; + break; + case 7: + p_regs->SwReg10.sw_pinit_rlist_f7 = val; + break; + case 8: + p_regs->SwReg10.sw_pinit_rlist_f8 = val; + break; + case 9: + p_regs->SwReg10.sw_pinit_rlist_f9 = val; + break; + case 10: + p_regs->SwReg11.sw_pinit_rlist_f10 = val; + break; + case 11: + p_regs->SwReg11.sw_pinit_rlist_f11 = val; + break; + case 12: + p_regs->SwReg11.sw_pinit_rlist_f12 = val; + break; + case 13: + p_regs->SwReg11.sw_pinit_rlist_f13 = val; + break; + case 14: + p_regs->SwReg11.sw_pinit_rlist_f14 = val; + break; + case 15: + p_regs->SwReg11.sw_pinit_rlist_f15 = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET vdpu1_set_refer_pic_list_b0(H264dVdpu1Regs_t *p_regs, RK_U32 i, + RK_U16 val) +{ + switch (i) { + case 0: + p_regs->SwReg42.sw_binit_rlist_f0 = val; + break; + case 1: + p_regs->SwReg42.sw_binit_rlist_f1 = val; + break; + case 2: + p_regs->SwReg42.sw_binit_rlist_f2 = val; + break; + case 3: + p_regs->SwReg43.sw_binit_rlist_f3 = val; + break; + case 4: + p_regs->SwReg43.sw_binit_rlist_f4 = val; + break; + case 5: + p_regs->SwReg43.sw_binit_rlist_f5 = val; + break; + case 6: + p_regs->SwReg44.sw_binit_rlist_f6 = val; + break; + case 7: + p_regs->SwReg44.sw_binit_rlist_f7 = val; + break; + case 8: + p_regs->SwReg44.sw_binit_rlist_f8 = val; + break; + case 9: + p_regs->SwReg45.sw_binit_rlist_f9 = val; + break; + case 10: + p_regs->SwReg45.sw_binit_rlist_f10 = val; + break; + case 11: + p_regs->SwReg45.sw_binit_rlist_f11 = val; + break; + case 12: + p_regs->SwReg46.sw_binit_rlist_f12 = val; + break; + case 13: + p_regs->SwReg46.sw_binit_rlist_f13 = val; + break; + case 14: + p_regs->SwReg46.sw_binit_rlist_f14 = val; + break; + case 15: + p_regs->SwReg47.sw_binit_rlist_f15 = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET vdpu1_set_refer_pic_list_b1(H264dVdpu1Regs_t *p_regs, RK_U32 i, + RK_U16 val) +{ + switch (i) { + case 0: + p_regs->SwReg42.sw_binit_rlist_b0 = val; + break; + case 1: + p_regs->SwReg42.sw_binit_rlist_b1 = val; + break; + case 2: + p_regs->SwReg42.sw_binit_rlist_b2 = val; + break; + case 3: + p_regs->SwReg43.sw_binit_rlist_b3 = val; + break; + case 4: + p_regs->SwReg43.sw_binit_rlist_b4 = val; + break; + case 5: + p_regs->SwReg43.sw_binit_rlist_b5 = val; + break; + case 6: + p_regs->SwReg44.sw_binit_rlist_b6 = val; + break; + case 7: + p_regs->SwReg44.sw_binit_rlist_b7 = val; + break; + case 8: + p_regs->SwReg44.sw_binit_rlist_b8 = val; + break; + case 9: + p_regs->SwReg45.sw_binit_rlist_b9 = val; + break; + case 10: + p_regs->SwReg45.sw_binit_rlist_b10 = val; + break; + case 11: + p_regs->SwReg45.sw_binit_rlist_b11 = val; + break; + case 12: + p_regs->SwReg46.sw_binit_rlist_b12 = val; + break; + case 13: + p_regs->SwReg46.sw_binit_rlist_b13 = val; + break; + case 14: + p_regs->SwReg46.sw_binit_rlist_b14 = val; + break; + case 15: + p_regs->SwReg47.sw_binit_rlist_b15 = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET vdpu1_set_refer_pic_base_addr(H264dVdpu1Regs_t *p_regs, RK_U32 i, + RK_U32 val) +{ + switch (i) { + case 0: + p_regs->SwReg14.sw_refer0_base = val; + break; + case 1: + p_regs->SwReg15.sw_refer1_base = val; + break; + case 2: + p_regs->SwReg16.sw_refer2_base = val; + break; + case 3: + p_regs->SwReg17.sw_refer3_base = val; + break; + case 4: + p_regs->SwReg18.sw_refer4_base = val; + break; + case 5: + p_regs->SwReg19.sw_refer5_base = val; + break; + case 6: + p_regs->SwReg20.sw_refer6_base = val; + break; + case 7: + p_regs->SwReg21.sw_refer7_base = val; + break; + case 8: + p_regs->SwReg22.sw_refer8_base = val; + break; + case 9: + p_regs->SwReg23.sw_refer9_base = val; + break; + case 10: + p_regs->SwReg24.sw_refer10_base = val; + break; + case 11: + p_regs->SwReg25.sw_refer11_base = val; + break; + case 12: + p_regs->SwReg26.sw_refer12_base = val; + break; + case 13: + p_regs->SwReg27.sw_refer13_base = val; + break; + case 14: + p_regs->SwReg28.sw_refer14_base = val; + break; + case 15: + p_regs->SwReg29.sw_refer15_base = val; + break; + default: + break; + } + return MPP_OK; +} + +static MPP_RET vdpu1_set_pic_regs(H264dHalCtx_t *p_hal, + H264dVdpu1Regs_t *p_regs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + p_regs->SwReg04.sw_pic_mb_width = p_hal->pp->wFrameWidthInMbsMinus1 + 1; + p_regs->SwReg04.sw_pic_mb_height_p = (2 - p_hal->pp->frame_mbs_only_flag) + * (p_hal->pp->wFrameHeightInMbsMinus1 + 1); + + return ret = MPP_OK; +} + +static MPP_RET vdpu1_set_vlc_regs(H264dHalCtx_t *p_hal, + H264dVdpu1Regs_t *p_regs) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + + p_regs->SwReg03.sw_dec_out_dis = 0; + p_regs->SwReg03.sw_rlc_mode_e = 0; + p_regs->SwReg06.sw_init_qp = pp->pic_init_qp_minus26 + 26; + p_regs->SwReg09.sw_refidx0_active = pp->num_ref_idx_l0_active_minus1 + 1; + p_regs->SwReg04.sw_ref_frames = pp->num_ref_frames; + + p_regs->SwReg07.sw_framenum_len = pp->log2_max_frame_num_minus4 + 4; + p_regs->SwReg07.sw_framenum = pp->frame_num; + + p_regs->SwReg08.sw_const_intra_e = pp->constrained_intra_pred_flag; + p_regs->SwReg08.sw_filt_ctrl_pres = + pp->deblocking_filter_control_present_flag; + p_regs->SwReg08.sw_rdpic_cnt_pres = pp->redundant_pic_cnt_present_flag; + p_regs->SwReg08.sw_refpic_mk_len = p_hal->slice_long[0].drpm_used_bitlen; + p_regs->SwReg08.sw_idr_pic_e = p_hal->slice_long[0].idr_flag; + p_regs->SwReg08.sw_idr_pic_id = p_hal->slice_long[0].idr_pic_id; + + p_regs->SwReg09.sw_pps_id = p_hal->slice_long[0].active_pps_id; + p_regs->SwReg09.sw_poc_length = p_hal->slice_long[0].poc_used_bitlen; + + /* reference picture flags, TODO separate fields */ + if (pp->field_pic_flag) { + RK_U32 validTmp = 0, validFlags = 0; + RK_U32 longTermTmp = 0, longTermflags = 0; + for (i = 0; i < 32; i++) { + if (pp->RefFrameList[i / 2].bPicEntry == 0xff) { //!< invalid + longTermflags <<= 1; + validFlags <<= 1; + } else { + longTermTmp = pp->RefFrameList[i / 2].AssociatedFlag; //!< get long term flag + longTermflags = (longTermflags << 1) | longTermTmp; + + validTmp = ((pp->UsedForReferenceFlags >> i) & 0x01); + validFlags = (validFlags << 1) | validTmp; + } + } + p_regs->SwReg38.refpic_term_flag = longTermflags; + p_regs->SwReg39.refpic_valid_flag = validFlags; + } else { + RK_U32 validTmp = 0, validFlags = 0; + RK_U32 longTermTmp = 0, longTermflags = 0; + for (i = 0; i < 16; i++) { + if (pp->RefFrameList[i].bPicEntry == 0xff) { //!< invalid + longTermflags <<= 1; + validFlags <<= 1; + } else { + longTermTmp = pp->RefFrameList[i].AssociatedFlag; + longTermflags = (longTermflags << 1) | longTermTmp; + validTmp = ((pp->UsedForReferenceFlags >> (2 * i)) & 0x03) > 0; + validFlags = (validFlags << 1) | validTmp; + } + } + p_regs->SwReg38.refpic_term_flag = (longTermflags << 16); + p_regs->SwReg39.refpic_valid_flag = (validFlags << 16); + } + + for (i = 0; i < 16; i++) { + if (pp->RefFrameList[i].bPicEntry != 0xff) { //!< valid + if (pp->RefFrameList[i].AssociatedFlag) { //!< longterm flag + vdpu1_set_refer_pic_idx(p_regs, i, pp->LongTermPicNumList[i]); //!< pic_num + } else { + vdpu1_set_refer_pic_idx(p_regs, i, pp->FrameNumList[i]); //< frame_num + } + } + } + p_regs->SwReg03.sw_picord_count_e = 1; + //!< set poc to buffer + { + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + RK_U32 *pocBase = (RK_U32 *)reg_ctx->poc_ptr; + + //!< set reference reorder poc + for (i = 0; i < 32; i++) { + if (pp->RefFrameList[i / 2].bPicEntry != 0xff) { + *pocBase++ = pp->FieldOrderCntList[i / 2][i & 0x1]; + } else { + *pocBase++ = 0; + } + } + + //!< set current poc + if (pp->field_pic_flag || !pp->MbaffFrameFlag) { + if (pp->field_pic_flag) + *pocBase++ = pp->CurrFieldOrderCnt[(pp->CurrPic.AssociatedFlag != 0) ? 1 : 0]; + else + *pocBase++ = MPP_MIN(pp->CurrFieldOrderCnt[0], pp->CurrFieldOrderCnt[1]); + } else { + *pocBase++ = pp->CurrFieldOrderCnt[0]; + *pocBase++ = pp->CurrFieldOrderCnt[1]; + } + } + + p_regs->SwReg07.sw_cabac_e = pp->entropy_coding_mode_flag; + + //!< stream position update + { + MppBuffer bitstream_buf = NULL; + p_regs->SwReg06.sw_start_code_e = 1; + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, p_hal->in_task->input, + SLOT_BUFFER, &bitstream_buf); + + p_regs->SwReg05.sw_strm_start_bit = 0; /* sodb stream start bit */ + p_regs->SwReg12.rlc_vlc_st_adr = mpp_buffer_get_fd(bitstream_buf); + + p_regs->SwReg06.sw_stream_len = p_hal->strm_len; + } + + return ret = MPP_OK; +} + +static MPP_RET vdpu1_set_ref_regs(H264dHalCtx_t *p_hal, + H264dVdpu1Regs_t *p_regs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 i = 0; + RK_U32 num_refs = 0; + RK_U32 num_reorder = 0; + H264dRefsList_t m_lists[3][16]; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + RK_U32 max_frame_num = 1 << (pp->log2_max_frame_num_minus4 + 4); + + // init list + memset(m_lists, 0, sizeof(m_lists)); + for (i = 0; i < 16; i++) { + RK_U32 ref_flag = pp->UsedForReferenceFlags >> (2 * i) & 0x3; + + m_lists[0][i].idx = i; + if (ref_flag) { + num_refs++; + m_lists[0][i].cur_poc = (pp->CurrPic.AssociatedFlag != 0) + ? pp->CurrFieldOrderCnt[1] : pp->CurrFieldOrderCnt[0]; + m_lists[0][i].ref_flag = ref_flag; + m_lists[0][i].lt_flag = pp->RefFrameList[i].AssociatedFlag; + if (m_lists[0][i].lt_flag) { + m_lists[0][i].ref_picnum = pp->LongTermPicNumList[i]; + } else { + m_lists[0][i].ref_picnum = pp->FrameNumList[i] > pp->frame_num ? + (pp->FrameNumList[i] - max_frame_num) : + pp->FrameNumList[i]; + } + + if (ref_flag == 3) { + m_lists[0][i].ref_poc = MPP_MIN(pp->FieldOrderCntList[i][0], pp->FieldOrderCntList[i][1]); + } else if (ref_flag & 0x1) { + m_lists[0][i].ref_poc = pp->FieldOrderCntList[i][0]; + } else if (ref_flag & 0x2) { + m_lists[0][i].ref_poc = pp->FieldOrderCntList[i][1]; + } + num_reorder = i + 1; + } + } + /* + * the value of num_reorder may be greater than num_refs, + * e.g. v: valid x: invalid + * num_refs = 3, num_reorder = 4 + * the index 1 will be reorder to the end + * ┌─┬─┬─┬─┬─┬─┬─┐ + * │0│1│2│3│.│.│F│ + * ├─┼─┼─┼─┼─┼─┼─┤ + * │v│x│v│v│x│x│x│ + * └─┴─┴─┴─┴─┴─┴─┘ + */ + memcpy(m_lists[1], m_lists[0], sizeof(m_lists[0])); + memcpy(m_lists[2], m_lists[0], sizeof(m_lists[0])); + qsort(m_lists[0], num_reorder, sizeof(m_lists[0][0]), compare_p); + qsort(m_lists[1], num_reorder, sizeof(m_lists[1][0]), compare_b0); + qsort(m_lists[2], num_reorder, sizeof(m_lists[2][0]), compare_b1); + if (num_refs > 1 && !p_hal->pp->field_pic_flag) { + if (!memcmp(m_lists[1], m_lists[2], sizeof(m_lists[1]))) { + MPP_SWAP(H264dRefsList_t, m_lists[2][0], m_lists[2][1]); + } + } + //!< list0 list1 listP + for (i = 0; i < 16; i++) { + vdpu1_set_refer_pic_list_p(p_regs, i, m_lists[0][i].idx); + vdpu1_set_refer_pic_list_b0(p_regs, i, m_lists[1][i].idx); + vdpu1_set_refer_pic_list_b1(p_regs, i, m_lists[2][i].idx); + } + + return ret = MPP_OK; +} + +static MPP_RET vdpu1_set_asic_regs(H264dHalCtx_t *p_hal, + H264dVdpu1Regs_t *p_regs) +{ + RK_U32 i = 0, j = 0; + RK_U32 outPhyAddr = 0; + MppBuffer frame_buf = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + DXVA_Slice_H264_Long *p_long = &p_hal->slice_long[0]; + MppHalCfg *cfg = p_hal->cfg; + + /* reference picture physic address */ + for (i = 0, j = 0xff; i < MPP_ARRAY_ELEMS(pp->RefFrameList); i++) { + RK_U32 val = 0; + RK_U32 top_closer = 0; + RK_U32 field_flag = 0; + RK_S32 cur_poc = 0; + RK_U32 used_flag = 0; + + if (pp->RefFrameList[i].bPicEntry != 0xff) { + mpp_buf_slot_get_prop(cfg->frame_slots, + pp->RefFrameList[i].Index7Bits, + SLOT_BUFFER, &frame_buf); //!< reference phy addr + j = i; + } else { + mpp_buf_slot_get_prop(cfg->frame_slots, + pp->CurrPic.Index7Bits, + SLOT_BUFFER, &frame_buf); //!< current out phy addr + } + + field_flag = (((pp->RefPicFiledFlags >> i) & 0x1) != 0) ? 0x2 : 0; + cur_poc = (pp->CurrPic.AssociatedFlag != 0) + ? pp->CurrFieldOrderCnt[1] : pp->CurrFieldOrderCnt[0]; + used_flag = ((pp->UsedForReferenceFlags >> (2 * i)) & 0x3); + if (used_flag & 0x3) { + top_closer = MPP_ABS(pp->FieldOrderCntList[i][0] - cur_poc) < + MPP_ABS(pp->FieldOrderCntList[i][1] - cur_poc) ? 0x1 : 0; + } else if (used_flag & 0x2) { + top_closer = 0; + } else if (used_flag & 0x1) { + top_closer = 1; + } + val = top_closer | field_flag; + if (val) + mpp_dev_set_reg_offset(cfg->dev, vdpu1_ref_idx[i], val); + vdpu1_set_refer_pic_base_addr(p_regs, i, mpp_buffer_get_fd(frame_buf)); + } + + /* inter-view reference picture */ + { + H264dVdpuPriv_t *priv = (H264dVdpuPriv_t *)p_hal->priv; + if (pp->curr_layer_id && priv->ilt_dpb && priv->ilt_dpb->valid /*pp->inter_view_flag*/) { + mpp_buf_slot_get_prop(cfg->frame_slots, + priv->ilt_dpb->slot_index, + SLOT_BUFFER, &frame_buf); + p_regs->SwReg29.sw_refer15_base = mpp_buffer_get_fd(frame_buf); //!< inter-view base, ref15 + p_regs->SwReg39.refpic_valid_flag |= + ((pp->field_pic_flag != 0) ? 0x3 : 0x10000); + } + } + + p_regs->SwReg03.sw_pic_fixed_quant = pp->curr_layer_id; //!< VDPU_MVC_E + p_regs->SwReg03.sw_filtering_dis = 0; + + mpp_buf_slot_get_prop(cfg->frame_slots, + pp->CurrPic.Index7Bits, + SLOT_BUFFER, &frame_buf); //!< current out phy addr + outPhyAddr = mpp_buffer_get_fd(frame_buf); + if (pp->field_pic_flag && pp->CurrPic.AssociatedFlag) { + mpp_dev_set_reg_offset(cfg->dev, 13, ((pp->wFrameWidthInMbsMinus1 + 1) * 16)); + } + p_regs->SwReg13.dec_out_st_adr = outPhyAddr; //!< outPhyAddr, pp->CurrPic.Index7Bits + + p_regs->SwReg05.sw_ch_qp_offset = pp->chroma_qp_index_offset; + p_regs->SwReg05.sw_ch_qp_offset2 = pp->second_chroma_qp_index_offset; + + /* set default value for register[41] to avoid illegal translation fd */ + { + RK_U32 dirMvOffset = 0; + RK_U32 picSizeInMbs = 0; + + picSizeInMbs = p_hal->pp->wFrameWidthInMbsMinus1 + 1; + picSizeInMbs = picSizeInMbs * (2 - pp->frame_mbs_only_flag) + * (pp->wFrameHeightInMbsMinus1 + 1); + dirMvOffset = picSizeInMbs + * ((p_hal->pp->chroma_format_idc == 0) ? 256 : 384); + dirMvOffset += (pp->field_pic_flag && pp->CurrPic.AssociatedFlag) + ? (picSizeInMbs * 32) : 0; + if (dirMvOffset) { + RK_U32 offset = mpp_get_ioctl_version() ? dirMvOffset : dirMvOffset >> 4; + mpp_dev_set_reg_offset(cfg->dev, 41, offset); + } + p_regs->SwReg41.dmmv_st_adr = mpp_buffer_get_fd(frame_buf); + } + + p_regs->SwReg03.sw_write_mvs_e = (p_long->nal_ref_idc != 0) ? 1 : 0; /* defalut set 1 */ + p_regs->SwReg07.sw_dir_8x8_infer_e = pp->direct_8x8_inference_flag; + p_regs->SwReg07.sw_weight_pred_e = pp->weighted_pred_flag; + p_regs->SwReg07.sw_weight_bipr_idc = pp->weighted_bipred_idc; + p_regs->SwReg09.sw_refidx1_active = (pp->num_ref_idx_l1_active_minus1 + 1); + p_regs->SwReg05.sw_fieldpic_flag_e = (pp->frame_mbs_only_flag == 0) ? 1 : 0; + + p_regs->SwReg03.sw_pic_interlace_e = + (!pp->frame_mbs_only_flag + && (pp->MbaffFrameFlag || pp->field_pic_flag)) ? 1 : 0; + p_regs->SwReg03.sw_pic_fieldmode_e = pp->field_pic_flag; + p_regs->SwReg03.sw_pic_topfield_e = (pp->CurrPic.AssociatedFlag == 0) ? 1 : 0; /* bottomFieldFlag */ + p_regs->SwReg03.sw_seq_mbaff_e = pp->MbaffFrameFlag; + p_regs->SwReg08.sw_8x8trans_flag_e = pp->transform_8x8_mode_flag; + p_regs->SwReg07.sw_blackwhite_e = (p_long->profileIdc >= 100 + && pp->chroma_format_idc == 0) ? 1 : 0; + p_regs->SwReg05.sw_type1_quant_e = pp->scaleing_list_enable_flag; + + { + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + if (p_hal->pp->scaleing_list_enable_flag) { + RK_U32 temp = 0; + RK_U32 *ptr = (RK_U32 *)reg_ctx->sclst_ptr; + + for (i = 0; i < 6; i++) { + for (j = 0; j < 4; j++) { + temp = (p_hal->qm->bScalingLists4x4[i][4 * j + 0] << 24) | + (p_hal->qm->bScalingLists4x4[i][4 * j + 1] << 16) | + (p_hal->qm->bScalingLists4x4[i][4 * j + 2] << 8) | + (p_hal->qm->bScalingLists4x4[i][4 * j + 3]); + *ptr++ = temp; + } + } + + for (i = 0; i < 2; i++) { + for (j = 0; j < 16; j++) { + temp = (p_hal->qm->bScalingLists8x8[i][4 * j + 0] << 24) | + (p_hal->qm->bScalingLists8x8[i][4 * j + 1] << 16) | + (p_hal->qm->bScalingLists8x8[i][4 * j + 2] << 8) | + (p_hal->qm->bScalingLists8x8[i][4 * j + 3]); + *ptr++ = temp; + } + } + } + p_regs->SwReg40.qtable_st_adr = mpp_buffer_get_fd(reg_ctx->buf); + } + + p_regs->SwReg03.sw_dec_out_dis = 0; /* set defalut 0 */ + p_regs->SwReg06.sw_ch_8pix_ileav_e = 0; + p_regs->SwReg01.sw_dec_en = 1; + + return ret = MPP_OK; +} + +static MPP_RET vdpu1_set_device_regs(H264dHalCtx_t *p_hal, + H264dVdpu1Regs_t *p_reg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + p_reg->SwReg03.sw_dec_mode = 0; /* set H264 mode */ + p_reg->SwReg02.sw_dec_out_endian = 1; /* little endian */ + p_reg->SwReg02.sw_dec_in_endian = 0; /* big endian */ + p_reg->SwReg02.sw_dec_strendian_e = 1; //!< little endian + p_reg->SwReg02.sw_tiled_mode_msb = 0; /* 0: raster scan 1: tiled */ + + /* bus_burst_length = 16, bus burst */ + p_reg->SwReg02.sw_dec_max_burst = 16; /* (0, 4, 8, 16) choice one */ + p_reg->SwReg02.sw_dec_scmd_dis = 0; /* disable */ + p_reg->SwReg02.sw_dec_adv_pre_dis = 0; /* disable */ + p_reg->SwReg55.sw_apf_threshold = 8; + p_reg->SwReg02.sw_dec_latency = 0; /* compensation for bus latency; values up to 63 */ + p_reg->SwReg02.sw_dec_data_disc_e = 0; + p_reg->SwReg02.sw_dec_out_endian = 1; /* little endian */ + p_reg->SwReg02.sw_dec_inswap32_e = 1; /* little endian */ + p_reg->SwReg02.sw_dec_outswap32_e = 1; + p_reg->SwReg02.sw_dec_strswap32_e = 1; + p_reg->SwReg02.sw_dec_strendian_e = 1; /* little endian */ + p_reg->SwReg02.sw_dec_timeout_e = 1; + + /* clock_gating 0:clock always on, 1: clock gating module control the key(turn off when decoder free) */ + p_reg->SwReg02.sw_dec_clk_gate_e = 1; + p_reg->SwReg01.sw_dec_irq_dis_cfg = 0; + + //!< set AXI RW IDs + p_reg->SwReg02.sw_dec_axi_rd_id = (0xFF & 0xFFU); /* 0-255 */ + p_reg->SwReg03.sw_dec_axi_wr_id = (0x00 & 0xFFU); /* 0-255 */ + + ///!< Set prediction filter taps + { + RK_U32 val = 0; + p_reg->SwReg49.sw_pred_bc_tap_0_0 = 1; + + val = (RK_U32)(-5); + p_reg->SwReg49.sw_pred_bc_tap_0_1 = val; + p_reg->SwReg49.sw_pred_bc_tap_0_2 = 20; + } + + (void)p_hal; + + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* init VDPU granite decoder +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + + INP_CHECK(ret, NULL == hal); + + //!< malloc init registers + MEM_CHECK(ret, p_hal->priv = mpp_calloc_size(void, sizeof(H264dVdpuPriv_t))); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 0; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(H264dVdpuRegCtx_t))); + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + //!< malloc buffers + { + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + + RK_U32 buf_size = VDPU_CABAC_TAB_SIZE + VDPU_POC_BUF_SIZE + VDPU_SCALING_LIST_SIZE; + for (i = 0; i < loop; i++) { + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->reg_buf[i].buf, buf_size)); + reg_ctx->reg_buf[i].cabac_ptr = mpp_buffer_get_ptr(reg_ctx->reg_buf[i].buf); + reg_ctx->reg_buf[i].poc_ptr = reg_ctx->reg_buf[i].cabac_ptr + VDPU_CABAC_TAB_SIZE; + reg_ctx->reg_buf[i].sclst_ptr = reg_ctx->reg_buf[i].poc_ptr + VDPU_POC_BUF_SIZE; + reg_ctx->reg_buf[i].regs = mpp_calloc_size(void, sizeof(H264dVdpu1Regs_t)); + //!< copy cabac table bytes + memcpy(reg_ctx->reg_buf[i].cabac_ptr, (void *)vdpu_cabac_table, sizeof(vdpu_cabac_table)); + } + } + if (!p_hal->fast_mode) { + reg_ctx->buf = reg_ctx->reg_buf[0].buf; + reg_ctx->cabac_ptr = reg_ctx->reg_buf[0].cabac_ptr; + reg_ctx->poc_ptr = reg_ctx->reg_buf[0].poc_ptr; + reg_ctx->sclst_ptr = reg_ctx->reg_buf[0].sclst_ptr; + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + } + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu1_h264d_deinit(hal); + + return ret; +} + +/*! +*********************************************************************** +* \brief +* deinit +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_deinit(void *hal) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + for (i = 0; i < loop; i++) { + MPP_FREE(reg_ctx->reg_buf[i].regs); + mpp_buffer_put(reg_ctx->reg_buf[i].buf); + } + MPP_FREE(p_hal->reg_ctx); + MPP_FREE(p_hal->priv); + + return MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* generate register +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dVdpuPriv_t *priv = NULL; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, NULL == p_hal); + p_hal->in_task = &task->dec; + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + priv = p_hal->priv; + priv->layed_id = p_hal->pp->curr_layer_id; + + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(reg_ctx->reg_buf); i++) { + if (!reg_ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + reg_ctx->buf = reg_ctx->reg_buf[i].buf; + reg_ctx->cabac_ptr = reg_ctx->reg_buf[i].cabac_ptr; + reg_ctx->poc_ptr = reg_ctx->reg_buf[i].poc_ptr; + reg_ctx->sclst_ptr = reg_ctx->reg_buf[i].sclst_ptr; + reg_ctx->regs = reg_ctx->reg_buf[i].regs; + reg_ctx->reg_buf[i].valid = 1; + break; + } + } + } + + hal_h264d_explain_input_buffer(hal, &task->dec); + FUN_CHECK(ret = adjust_input(priv, &p_hal->slice_long[0], p_hal->pp)); + FUN_CHECK(ret = vdpu1_set_device_regs(p_hal, (H264dVdpu1Regs_t *)reg_ctx->regs)); + FUN_CHECK(ret = vdpu1_set_pic_regs(p_hal, (H264dVdpu1Regs_t *)reg_ctx->regs)); + FUN_CHECK(ret = vdpu1_set_vlc_regs(p_hal, (H264dVdpu1Regs_t *)reg_ctx->regs)); + FUN_CHECK(ret = vdpu1_set_ref_regs(p_hal, (H264dVdpu1Regs_t *)reg_ctx->regs)); + FUN_CHECK(ret = vdpu1_set_asic_regs(p_hal, (H264dVdpu1Regs_t *)reg_ctx->regs)); + mpp_buffer_sync_end(reg_ctx->buf); + +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} + +/*! +*********************************************************************** +* \brief h +* start hard +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + H264dVdpu1Regs_t *p_regs = (H264dVdpu1Regs_t *)((p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + p_regs->SwReg57.sw_cache_en = 1; + p_regs->SwReg57.sw_pref_sigchan = 1; + p_regs->SwReg57.sw_intra_dbl3t = 1; + p_regs->SwReg57.sw_inter_dblspeed = 1; + p_regs->SwReg57.sw_intra_dblspeed = 1; + p_regs->SwReg57.sw_paral_bus = 1; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = DEC_VDPU1_REGISTERS * sizeof(RK_U32); + MppDev dev = p_hal->cfg->dev; + + wr_cfg.reg = reg_ctx->regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = reg_ctx->regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + (void)task; + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* wait hard +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + H264dVdpu1Regs_t *p_regs = (H264dVdpu1Regs_t *)((p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)reg_ctx->regs; + param.hard_err = !p_regs->SwReg01.sw_dec_rdy_int; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + memset(&p_regs->SwReg01, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) { + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + } + (void)task; + + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_reset(void *hal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + memset(p_hal->priv, 0, sizeof(H264dVdpuPriv_t)); + +__RETURN: + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_flush(void *hal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + + +__RETURN: + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* control +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu1_h264d_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + (void)hal; + (void)cmd_type; + (void)param; +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_vdpu1 = { + .name = "h264d_vdpu1", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = vdpu1_h264d_init, + .deinit = vdpu1_h264d_deinit, + .reg_gen = vdpu1_h264d_gen_regs, + .start = vdpu1_h264d_start, + .wait = vdpu1_h264d_wait, + .reset = vdpu1_h264d_reset, + .flush = vdpu1_h264d_flush, + .control = vdpu1_h264d_control, + .client = VPU_CLIENT_VDPU1, + .soc_type = { + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_vdpu1) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu1.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu1.h new file mode 100644 index 000000000..d3be4940d --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu1.h @@ -0,0 +1,33 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264D_VDPU1_REG_H +#define HAL_H264D_VDPU1_REG_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_vdpu1; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU1_REG_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu1_reg.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu1_reg.h new file mode 100644 index 000000000..b6a1dfaa9 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu1_reg.h @@ -0,0 +1,430 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264D_VDPU1_REG_TBL_H +#define HAL_H264D_VDPU1_REG_TBL_H + +#include "rk_type.h" + +/* Number registers for the decoder */ +#define DEC_VDPU1_REGISTERS (101) + +typedef struct { + RK_U32 SwReg00; + + struct { + RK_U32 sw_dec_en : 1; + RK_U32 reserve0 : 3; + RK_U32 sw_dec_irq_dis_cfg : 1; + RK_U32 reserve1 : 3; + RK_U32 sw_dec_irq_config : 1; + RK_U32 reserve2 : 3; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserve3 : 5; + RK_U32 sw_dec_pic_inf : 1; + RK_U32 reserve4 : 7; + } SwReg01; + + struct { + RK_U32 sw_dec_max_burst : 5; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_tiled_mode_lsb : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_tiled_mode_msb : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_dec_axi_rd_id : 8; + } SwReg02; + + struct { + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 sw_dec_ahb_hlock_e : 1; + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; + RK_U32 sw_skip_mode : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_dec_mode : 4; + } SwReg03; + + struct { + RK_U32 sw_ref_frames : 5; + RK_U32 reserve0 : 6; + RK_U32 sw_pic_mb_height_p : 8; + RK_U32 reserve1 : 4; + RK_U32 sw_pic_mb_width : 9; + } SwReg04; + + struct { + RK_U32 sw_fieldpic_flag_e : 1; + RK_U32 reserve0 : 13; + RK_U32 sw_ch_qp_offset2 : 5; /* Cr */ + RK_U32 sw_ch_qp_offset : 5; /* Cb */ + RK_U32 sw_type1_quant_e : 1; + RK_U32 sw_sync_marker_e : 1; + RK_U32 sw_strm_start_bit : 6; + } SwReg05; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_init_qp : 6; + RK_U32 sw_start_code_e : 1; + } SwReg06; + + struct { + RK_U32 sw_framenum : 16; + RK_U32 sw_framenum_len : 5; + RK_U32 reserve0 : 5; + RK_U32 sw_weight_bipr_idc : 2; + RK_U32 sw_weight_pred_e : 1; + RK_U32 sw_dir_8x8_infer_e : 1; + RK_U32 sw_blackwhite_e : 1; + RK_U32 sw_cabac_e : 1; + } SwReg07; + + struct { + RK_U32 sw_idr_pic_id : 16; + RK_U32 sw_idr_pic_e : 1; + RK_U32 sw_refpic_mk_len : 11; + RK_U32 sw_8x8trans_flag_e : 1; + RK_U32 sw_rdpic_cnt_pres : 1; + RK_U32 sw_filt_ctrl_pres : 1; + RK_U32 sw_const_intra_e : 1; + } SwReg08; + + struct { + RK_U32 sw_poc_length : 8; + RK_U32 reserve0 : 6; + RK_U32 sw_refidx0_active : 5; + RK_U32 sw_refidx1_active : 5; + RK_U32 sw_pps_id : 8; + } SwReg09; + + struct { + RK_U32 sw_pinit_rlist_f4 : 5; + RK_U32 sw_pinit_rlist_f5 : 5; + RK_U32 sw_pinit_rlist_f6 : 5; + RK_U32 sw_pinit_rlist_f7 : 5; + RK_U32 sw_pinit_rlist_f8 : 5; + RK_U32 sw_pinit_rlist_f9 : 5; + RK_U32 reserve0 : 2; + } SwReg10; + + struct { + RK_U32 sw_pinit_rlist_f10 : 5; + RK_U32 sw_pinit_rlist_f11 : 5; + RK_U32 sw_pinit_rlist_f12 : 5; + RK_U32 sw_pinit_rlist_f13 : 5; + RK_U32 sw_pinit_rlist_f14 : 5; + RK_U32 sw_pinit_rlist_f15 : 5; + RK_U32 sw_i4x4_or_dc_base : 2; + } SwReg11; + + struct { + RK_U32 rlc_vlc_st_adr : 32; + } SwReg12; + + struct { + RK_U32 dec_out_st_adr : 32; + } SwReg13; + + /* MPP passes fd of reference frame to kernel + * with the whole register rather than higher 30-bit. + * At the same time, the lower 2-bit will be assigned + * by kernel. + * */ + struct { + //RK_U32 sw_refer0_topc_e : 1; + //RK_U32 sw_refer0_field_e : 1; + RK_U32 sw_refer0_base : 32; + } SwReg14; + + struct { + //RK_U32 sw_refer1_topc_e : 1; + //RK_U32 sw_refer1_field_e : 1; + RK_U32 sw_refer1_base : 32; + } SwReg15; + + struct { + //RK_U32 sw_refer2_topc_e : 1; + //RK_U32 sw_refer2_field_e : 1; + RK_U32 sw_refer2_base : 32; + } SwReg16; + + struct { + //RK_U32 sw_refer3_topc_e : 1; + //RK_U32 sw_refer3_field_e : 1; + RK_U32 sw_refer3_base : 32; + } SwReg17; + + struct { + //RK_U32 sw_refer4_topc_e : 1; + //RK_U32 sw_refer4_field_e : 1; + RK_U32 sw_refer4_base : 32; + } SwReg18; + + struct { + //RK_U32 sw_refer5_topc_e : 1; + //RK_U32 sw_refer5_field_e : 1; + RK_U32 sw_refer5_base : 32; + } SwReg19; + + struct { + //RK_U32 sw_refer6_topc_e : 1; + //RK_U32 sw_refer6_field_e : 1; + RK_U32 sw_refer6_base : 32; + } SwReg20; + + struct { + //RK_U32 sw_refer7_topc_e : 1; + //RK_U32 sw_refer7_field_e : 1; + RK_U32 sw_refer7_base : 32; + } SwReg21; + + struct { + //RK_U32 sw_refer8_topc_e : 1; + //RK_U32 sw_refer8_field_e : 1; + RK_U32 sw_refer8_base : 32; + } SwReg22; + + struct { + //RK_U32 sw_refer9_topc_e : 1; + //RK_U32 sw_refer9_field_e : 1; + RK_U32 sw_refer9_base : 32; + } SwReg23; + + struct { + //RK_U32 sw_refer10_topc_e : 1; + //RK_U32 sw_refer10_field_e : 1; + RK_U32 sw_refer10_base : 32; + } SwReg24; + + struct { + //RK_U32 sw_refer11_topc_e : 1; + //RK_U32 sw_refer11_field_e : 1; + RK_U32 sw_refer11_base : 32; + } SwReg25; + + struct { + //RK_U32 sw_refer12_topc_e : 1; + //RK_U32 sw_refer12_field_e : 1; + RK_U32 sw_refer12_base : 32; + } SwReg26; + + struct { + //RK_U32 sw_refer13_topc_e : 1; + //RK_U32 sw_refer13_field_e : 1; + RK_U32 sw_refer13_base : 32; + } SwReg27; + + struct { + //RK_U32 sw_refer14_topc_e : 1; + //RK_U32 sw_refer14_field_e : 1; + RK_U32 sw_refer14_base : 32; + } SwReg28; + + struct { + //RK_U32 sw_refer15_topc_e : 1; + //RK_U32 sw_refer15_field_e : 1; + RK_U32 sw_refer15_base : 32; + } SwReg29; + + struct { + RK_U32 sw_refer0_nbr : 16; + RK_U32 sw_refer1_nbr : 16; + } SwReg30; + + struct { + RK_U32 sw_refer2_nbr : 16; + RK_U32 sw_refer3_nbr : 16; + } SwReg31; + + struct { + RK_U32 sw_refer4_nbr : 16; + RK_U32 sw_refer5_nbr : 16; + } SwReg32; + + struct { + RK_U32 sw_refer6_nbr : 16; + RK_U32 sw_refer7_nbr : 16; + } SwReg33; + + struct { + RK_U32 sw_refer8_nbr : 16; + RK_U32 sw_refer9_nbr : 16; + } SwReg34; + + struct { + RK_U32 sw_refer10_nbr : 16; + RK_U32 sw_refer11_nbr : 16; + } SwReg35; + + struct { + RK_U32 sw_refer12_nbr : 16; + RK_U32 sw_refer13_nbr : 16; + } SwReg36; + + struct { + RK_U32 sw_refer14_nbr : 16; + RK_U32 sw_refer15_nbr : 16; + } SwReg37; + + struct { + RK_U32 refpic_term_flag : 32; + } SwReg38; + + struct { + RK_U32 refpic_valid_flag : 32; + } SwReg39; + + struct { + RK_U32 qtable_st_adr : 32; + } SwReg40; + + struct { + RK_U32 dmmv_st_adr : 32; + } SwReg41; + + struct { + RK_U32 sw_binit_rlist_f0 : 5; + RK_U32 sw_binit_rlist_b0 : 5; + RK_U32 sw_binit_rlist_f1 : 5; + RK_U32 sw_binit_rlist_b1 : 5; + RK_U32 sw_binit_rlist_f2 : 5; + RK_U32 sw_binit_rlist_b2 : 5; + RK_U32 reserve0 : 2; + } SwReg42; + + struct { + RK_U32 sw_binit_rlist_f3 : 5; + RK_U32 sw_binit_rlist_b3 : 5; + RK_U32 sw_binit_rlist_f4 : 5; + RK_U32 sw_binit_rlist_b4 : 5; + RK_U32 sw_binit_rlist_f5 : 5; + RK_U32 sw_binit_rlist_b5 : 5; + RK_U32 reserve0 : 2; + } SwReg43; + + struct { + RK_U32 sw_binit_rlist_f6 : 5; + RK_U32 sw_binit_rlist_b6 : 5; + RK_U32 sw_binit_rlist_f7 : 5; + RK_U32 sw_binit_rlist_b7 : 5; + RK_U32 sw_binit_rlist_f8 : 5; + RK_U32 sw_binit_rlist_b8 : 5; + RK_U32 reserve0 : 2; + } SwReg44; + + struct { + RK_U32 sw_binit_rlist_f9 : 5; + RK_U32 sw_binit_rlist_b9 : 5; + RK_U32 sw_binit_rlist_f10 : 5; + RK_U32 sw_binit_rlist_b10 : 5; + RK_U32 sw_binit_rlist_f11 : 5; + RK_U32 sw_binit_rlist_b11 : 5; + RK_U32 reserve0 : 2; + } SwReg45; + + struct { + RK_U32 sw_binit_rlist_f12 : 5; + RK_U32 sw_binit_rlist_b12 : 5; + RK_U32 sw_binit_rlist_f13 : 5; + RK_U32 sw_binit_rlist_b13 : 5; + RK_U32 sw_binit_rlist_f14 : 5; + RK_U32 sw_binit_rlist_b14 : 5; + RK_U32 reserve0 : 2; + } SwReg46; + + struct { + RK_U32 sw_binit_rlist_f15 : 5; + RK_U32 sw_binit_rlist_b15 : 5; + RK_U32 sw_pinit_rlist_f0 : 5; + RK_U32 sw_pinit_rlist_f1 : 5; + RK_U32 sw_pinit_rlist_f2 : 5; + RK_U32 sw_pinit_rlist_f3 : 5; + RK_U32 reserve0 : 2; + } SwReg47; + + struct { + RK_U32 reserve0 : 15; + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + } SwReg48; + + struct { + RK_U32 reserve0 : 2; + RK_U32 sw_pred_bc_tap_0_2 : 10; + RK_U32 sw_pred_bc_tap_0_1 : 10; + RK_U32 sw_pred_bc_tap_0_0 : 10; + } SwReg49; + + RK_U32 SwReg50_54[5]; + + struct { + RK_U32 sw_apf_threshold : 14; + RK_U32 sw_refbu2_picid : 5; + RK_U32 sw_refbu2_thr : 12; + RK_U32 sw_refbu2_buf_e : 1; + } SwReg55; + + RK_U32 SwReg56; + + struct { + RK_U32 sw_stream_len_hi : 1; + RK_U32 sw_inter_dblspeed : 1; + RK_U32 sw_intra_dblspeed : 1; + RK_U32 sw_intra_dbl3t : 1; + RK_U32 sw_paral_bus : 1; + RK_U32 sw_axiwr_sel : 1; + RK_U32 sw_pref_sigchan : 1; + RK_U32 sw_cache_en : 1; + RK_U32 reserve0 : 24; + } SwReg57; + + RK_U32 SwReg58_100[43]; +} H264dVdpu1Regs_t; + +#endif /* HAL_H264D_VDPU1_REG_TBL_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu2.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu2.c new file mode 100644 index 000000000..0369be4de --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu2.c @@ -0,0 +1,1164 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264d_vdpu_reg" + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_common.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_vdpu_com.h" +#include "hal_h264d_vdpu2.h" +#include "hal_h264d_vdpu2_reg.h" +#include "hal_h264d_com.h" +#include "mpp_dec_cb_param.h" + +const RK_U32 vdpu2_ref_idx[16] = { + 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99 +}; + +MPP_RET vdpu2_h264d_deinit(void *hal); +static MPP_RET set_device_regs(H264dHalCtx_t *p_hal, H264dVdpuRegs_t *p_reg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + p_reg->sw53.dec_fmt_sel = 0; //!< set H264 mode + p_reg->sw54.dec_out_endian = 1; //!< little endian + p_reg->sw54.dec_in_endian = 0; //!< big endian + p_reg->sw54.dec_strendian_e = 1; //!< little endian + p_reg->sw50.dec_tiled_msb = 0; //!< 0: raster scan 1: tiled + p_reg->sw56.dec_max_burlen = 16; //!< (0, 4, 8, 16) choice one + p_reg->sw50.dec_ascmd0_dis = 0; //!< disable + p_reg->sw50.adv_pref_dis = 0; //!< disable + p_reg->sw52.adv_pref_thrd = 8; + p_reg->sw50.adtion_latency = 0; //!< compensation for bus latency; values up to 63 + p_reg->sw56.dec_data_discd_en = 0; + p_reg->sw54.dec_out_wordsp = 1;//!< little endian + p_reg->sw54.dec_in_wordsp = 1;//!< little endian + p_reg->sw54.dec_strm_wordsp = 1;//!< little endian + p_reg->sw57.timeout_sts_en = 1; + p_reg->sw57.dec_clkgate_en = 1; + p_reg->sw55.dec_irq_dis = 0; + //!< set AXI RW IDs + p_reg->sw56.dec_axi_id_rd = (0xFF & 0xFFU); //!< 0-255 + p_reg->sw56.dec_axi_id_wr = (0x0 & 0xFFU); //!< 0-255 + ///!< Set prediction filter taps + { + RK_U32 val = 0; + p_reg->sw59.pflt_set0_tap0 = 1; + val = (RK_U32)(-5); + p_reg->sw59.pflt_set0_tap1 = val; + p_reg->sw59.pflt_set0_tap2 = 20; + } + p_reg->sw50.adtion_latency = 0; + //!< clock_gating 0:clock always on, 1: clock gating module control the key(turn off when decoder free) + p_reg->sw57.dec_clkgate_en = 1; + p_reg->sw50.dec_tiled_msb = 0; //!< 0: raster scan 1: tiled + //!< bus_burst_length = 16, bus burst + p_reg->sw56.dec_max_burlen = 16; + p_reg->sw56.dec_data_discd_en = 0; + (void)p_hal; + + return ret = MPP_OK; +} + +static MPP_RET set_refer_pic_idx(H264dVdpuRegs_t *p_regs, RK_U32 i, RK_U16 val) +{ + switch (i) { + case 0: + p_regs->sw76.num_ref_idx0 = val; + break; + case 1: + p_regs->sw76.num_ref_idx1 = val; + break; + case 2: + p_regs->sw77.num_ref_idx2 = val; + break; + case 3: + p_regs->sw77.num_ref_idx3 = val; + break; + case 4: + p_regs->sw78.num_ref_idx4 = val; + break; + case 5: + p_regs->sw78.num_ref_idx5 = val; + break; + case 6: + p_regs->sw79.num_ref_idx6 = val; + break; + case 7: + p_regs->sw79.num_ref_idx7 = val; + break; + case 8: + p_regs->sw80.num_ref_idx8 = val; + break; + case 9: + p_regs->sw80.num_ref_idx9 = val; + break; + case 10: + p_regs->sw81.num_ref_idx10 = val; + break; + case 11: + p_regs->sw81.num_ref_idx11 = val; + break; + case 12: + p_regs->sw82.num_ref_idx12 = val; + break; + case 13: + p_regs->sw82.num_ref_idx13 = val; + break; + case 14: + p_regs->sw83.num_ref_idx14 = val; + break; + case 15: + p_regs->sw83.num_ref_idx15 = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET set_refer_pic_list_p(H264dVdpuRegs_t *p_regs, RK_U32 i, + RK_U16 val) +{ + switch (i) { + case 0: + p_regs->sw106.init_reflist_pf0 = val; + break; + case 1: + p_regs->sw106.init_reflist_pf1 = val; + break; + case 2: + p_regs->sw106.init_reflist_pf2 = val; + break; + case 3: + p_regs->sw106.init_reflist_pf3 = val; + break; + case 4: + p_regs->sw74.init_reflist_pf4 = val; + break; + case 5: + p_regs->sw74.init_reflist_pf5 = val; + break; + case 6: + p_regs->sw74.init_reflist_pf6 = val; + break; + case 7: + p_regs->sw74.init_reflist_pf7 = val; + break; + case 8: + p_regs->sw74.init_reflist_pf8 = val; + break; + case 9: + p_regs->sw74.init_reflist_pf9 = val; + break; + case 10: + p_regs->sw75.init_reflist_pf10 = val; + break; + case 11: + p_regs->sw75.init_reflist_pf11 = val; + break; + case 12: + p_regs->sw75.init_reflist_pf12 = val; + break; + case 13: + p_regs->sw75.init_reflist_pf13 = val; + break; + case 14: + p_regs->sw75.init_reflist_pf14 = val; + break; + case 15: + p_regs->sw75.init_reflist_pf15 = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET set_refer_pic_list_b0(H264dVdpuRegs_t *p_regs, RK_U32 i, + RK_U16 val) +{ + switch (i) { + case 0: + p_regs->sw100.init_reflist_df0 = val; + break; + case 1: + p_regs->sw100.init_reflist_df1 = val; + break; + case 2: + p_regs->sw100.init_reflist_df2 = val; + break; + case 3: + p_regs->sw100.init_reflist_df3 = val; + break; + case 4: + p_regs->sw100.init_reflist_df4 = val; + break; + case 5: + p_regs->sw100.init_reflist_df5 = val; + break; + case 6: + p_regs->sw101.init_reflist_df6 = val; + break; + case 7: + p_regs->sw101.init_reflist_df7 = val; + break; + case 8: + p_regs->sw101.init_reflist_df8 = val; + break; + case 9: + p_regs->sw101.init_reflist_df9 = val; + break; + case 10: + p_regs->sw101.init_reflist_df10 = val; + break; + case 11: + p_regs->sw101.init_reflist_df11 = val; + break; + case 12: + p_regs->sw102.init_reflist_df12 = val; + break; + case 13: + p_regs->sw102.init_reflist_df13 = val; + break; + case 14: + p_regs->sw102.init_reflist_df14 = val; + break; + case 15: + p_regs->sw102.init_reflist_df15 = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET set_refer_pic_list_b1(H264dVdpuRegs_t *p_regs, RK_U32 i, + RK_U16 val) +{ + switch (i) { + case 0: + p_regs->sw103.init_reflist_db0 = val; + break; + case 1: + p_regs->sw103.init_reflist_db1 = val; + break; + case 2: + p_regs->sw103.init_reflist_db2 = val; + break; + case 3: + p_regs->sw103.init_reflist_db3 = val; + break; + case 4: + p_regs->sw103.init_reflist_db4 = val; + break; + case 5: + p_regs->sw103.init_reflist_db5 = val; + break; + case 6: + p_regs->sw104.init_reflist_db6 = val; + break; + case 7: + p_regs->sw104.init_reflist_db7 = val; + break; + case 8: + p_regs->sw104.init_reflist_db8 = val; + break; + case 9: + p_regs->sw104.init_reflist_db9 = val; + break; + case 10: + p_regs->sw104.init_reflist_db10 = val; + break; + case 11: + p_regs->sw104.init_reflist_db11 = val; + break; + case 12: + p_regs->sw105.init_reflist_db12 = val; + break; + case 13: + p_regs->sw105.init_reflist_db13 = val; + break; + case 14: + p_regs->sw105.init_reflist_db14 = val; + break; + case 15: + p_regs->sw105.init_reflist_db15 = val; + break; + default: + break; + } + + return MPP_OK; +} + +static MPP_RET set_refer_pic_base_addr(H264dVdpuRegs_t *p_regs, RK_U32 i, + RK_U32 val) +{ + switch (i) { + case 0: + p_regs->sw84.ref0_st_addr = val; + break; + case 1: + p_regs->sw85.ref1_st_addr = val; + break; + case 2: + p_regs->sw86.ref2_st_addr = val; + break; + case 3: + p_regs->sw87.ref3_st_addr = val; + break; + case 4: + p_regs->sw88.ref4_st_addr = val; + break; + case 5: + p_regs->sw89.ref5_st_addr = val; + break; + case 6: + p_regs->sw90.ref6_st_addr = val; + break; + case 7: + p_regs->sw91.ref7_st_addr = val; + break; + case 8: + p_regs->sw92.ref8_st_addr = val; + break; + case 9: + p_regs->sw93.ref9_st_addr = val; + break; + case 10: + p_regs->sw94.ref10_st_addr = val; + break; + case 11: + p_regs->sw95.ref11_st_addr = val; + break; + case 12: + p_regs->sw96.ref12_st_addr = val; + break; + case 13: + p_regs->sw97.ref13_st_addr = val; + break; + case 14: + p_regs->sw98.ref14_st_addr = val; + break; + case 15: + p_regs->sw99.ref15_st_addr = val; + break; + default: + break; + } + return MPP_OK; +} + +static MPP_RET set_pic_regs(H264dHalCtx_t *p_hal, H264dVdpuRegs_t *p_regs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + p_regs->sw110.pic_mb_w = p_hal->pp->wFrameWidthInMbsMinus1 + 1; + p_regs->sw110.pic_mb_h = (2 - p_hal->pp->frame_mbs_only_flag) + * (p_hal->pp->wFrameHeightInMbsMinus1 + 1); + + return ret = MPP_OK; +} + +static MPP_RET set_vlc_regs(H264dHalCtx_t *p_hal, H264dVdpuRegs_t *p_regs) +{ + RK_U32 i = 0; + MPP_RET ret = MPP_ERR_UNKNOW; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + RK_U32 validFlags = 0; + RK_U32 longTermTmp = 0, longTermflags = 0; + + p_regs->sw57.dec_wr_extmen_dis = 0; + p_regs->sw57.rlc_mode_en = 0; + p_regs->sw51.qp_init_val = pp->pic_init_qp_minus26 + 26; + p_regs->sw114.max_refidx0 = pp->num_ref_idx_l0_active_minus1 + 1; + p_regs->sw111.max_refnum = pp->num_ref_frames; + p_regs->sw112.cur_frm_len = pp->log2_max_frame_num_minus4 + 4; + p_regs->sw112.curfrm_num = pp->frame_num; + p_regs->sw115.const_intra_en = pp->constrained_intra_pred_flag; + p_regs->sw112.dblk_ctrl_flag = pp->deblocking_filter_control_present_flag; + p_regs->sw112.rpcp_flag = pp->redundant_pic_cnt_present_flag; + p_regs->sw113.refpic_mk_len = p_hal->slice_long[0].drpm_used_bitlen; + p_regs->sw115.idr_pic_flag = p_hal->slice_long[0].idr_flag; + p_regs->sw113.idr_pic_id = p_hal->slice_long[0].idr_pic_id; + p_regs->sw114.pps_id = p_hal->slice_long[0].active_pps_id; + p_regs->sw114.poc_field_len = p_hal->slice_long[0].poc_used_bitlen; + /* reference picture flags, TODO separate fields */ + if (pp->field_pic_flag) { + for (i = 0; i < 32; i++) { + if (pp->RefFrameList[i / 2].bPicEntry == 0xff) { //!< invalid + longTermflags <<= 1; + validFlags <<= 1; + } else { + longTermTmp = pp->RefFrameList[i / 2].AssociatedFlag; //!< get long term flag + longTermflags = (longTermflags << 1) | longTermTmp; + + validFlags = (validFlags << 1) + | ((pp->UsedForReferenceFlags >> i) & 0x01); + } + } + p_regs->sw107.refpic_term_flag = longTermflags; + p_regs->sw108.refpic_valid_flag = validFlags; + } else { + for (i = 0; i < 16; i++) { + if (pp->RefFrameList[i].bPicEntry == 0xff) { //!< invalid + longTermflags <<= 1; + validFlags <<= 1; + } else { + RK_U32 use_flag = (pp->UsedForReferenceFlags >> (2 * i)) & 0x03; + + longTermTmp = pp->RefFrameList[i].AssociatedFlag; + longTermflags = (longTermflags << 1) | longTermTmp; + validFlags = (validFlags << 1) | (use_flag > 0); + } + } + p_regs->sw107.refpic_term_flag = (longTermflags << 16); + p_regs->sw108.refpic_valid_flag = (validFlags << 16); + } + + for (i = 0; i < 16; i++) { + if (pp->RefFrameList[i].bPicEntry != 0xff) { //!< valid + if (pp->RefFrameList[i].AssociatedFlag) { //!< longterm flag + set_refer_pic_idx(p_regs, i, pp->LongTermPicNumList[i]); //!< pic_num + } else { + set_refer_pic_idx(p_regs, i, pp->FrameNumList[i]); //< frame_num + } + } + } + p_regs->sw57.rd_cnt_tab_en = 1; + //!< set poc to buffer + { + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + RK_U32 *ptr = (RK_U32 *)reg_ctx->poc_ptr; + + //!< set reference reorder poc + for (i = 0; i < 32; i++) { + if (pp->RefFrameList[i / 2].bPicEntry != 0xff) { + *ptr++ = pp->FieldOrderCntList[i / 2][i & 0x1]; + } else { + *ptr++ = 0; + } + } + //!< set current poc + if (pp->field_pic_flag || !pp->MbaffFrameFlag) { + if (pp->field_pic_flag) + *ptr++ = pp->CurrFieldOrderCnt[(pp->CurrPic.AssociatedFlag != 0) ? 1 : 0]; + else + *ptr++ = MPP_MIN(pp->CurrFieldOrderCnt[0], pp->CurrFieldOrderCnt[1]); + } else { + *ptr++ = pp->CurrFieldOrderCnt[0]; + *ptr++ = pp->CurrFieldOrderCnt[1]; + } + +#if DEBUG_REF_LIST + { + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + RK_U32 *ptr_tmp = (RK_U32 *)reg_ctx->poc_ptr; + RK_U32 *ref_reg = &p_regs->sw76; + char file_name[128]; + sprintf(file_name, "/sdcard/test/mpp_pocbase_log.txt"); + FILE *fp = fopen(file_name, "ab"); + char buf[1024]; + RK_S32 buf_len = 0, buf_size = sizeof(buf) - 1; + + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "=== poc_base filed %d fram_num %d ===\n", + pp->field_pic_flag || !pp->MbaffFrameFlag, pp->frame_num); + for (; ptr_tmp < ptr; ptr_tmp++) + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "poc 0x%08x\n", *ptr_tmp); + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "term_flag 0x%08x refpic_valid_flag 0x%08x \n", + longTermflags, validFlags); + for (i = 0; i < 8; i++) + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "ref[%d] 0x%08x\n", i, ref_reg[i]); + fprintf(fp, "%s", buf); + + fflush(fp); + fclose(fp); + } +#endif + } + p_regs->sw115.cabac_en = pp->entropy_coding_mode_flag; + //!< stream position update + { + MppBuffer bitstream_buf = NULL; + p_regs->sw57.st_code_exit = 1; + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, + p_hal->in_task->input, + SLOT_BUFFER, &bitstream_buf); + p_regs->sw109.strm_start_bit = 0; //!< sodb stream start bit + p_regs->sw64.rlc_vlc_st_adr = mpp_buffer_get_fd(bitstream_buf); + p_regs->sw51.stream_len = p_hal->strm_len; + } + + return ret = MPP_OK; +} + +static MPP_RET set_ref_regs(H264dHalCtx_t *p_hal, H264dVdpuRegs_t *p_regs) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_U32 i = 0; + RK_U32 num_refs = 0; + RK_U32 num_reorder = 0; + H264dRefsList_t m_lists[3][16]; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + RK_U32 max_frame_num = 1 << (pp->log2_max_frame_num_minus4 + 4); + + // init list + memset(m_lists, 0, sizeof(m_lists)); + for (i = 0; i < 16; i++) { + RK_U32 ref_flag = pp->UsedForReferenceFlags >> (2 * i) & 0x3; + + m_lists[0][i].idx = i; + if (ref_flag) { + num_refs++; + m_lists[0][i].cur_poc = (pp->CurrPic.AssociatedFlag != 0) + ? pp->CurrFieldOrderCnt[1] : pp->CurrFieldOrderCnt[0]; + m_lists[0][i].ref_flag = ref_flag; + m_lists[0][i].lt_flag = pp->RefFrameList[i].AssociatedFlag; + if (m_lists[0][i].lt_flag) { + m_lists[0][i].ref_picnum = pp->LongTermPicNumList[i]; + } else { + m_lists[0][i].ref_picnum = pp->FrameNumList[i] > pp->frame_num ? + (pp->FrameNumList[i] - max_frame_num) : + pp->FrameNumList[i]; + } + + if (ref_flag == 3) { + m_lists[0][i].ref_poc = MPP_MIN(pp->FieldOrderCntList[i][0], pp->FieldOrderCntList[i][1]); + } else if (ref_flag & 0x1) { + m_lists[0][i].ref_poc = pp->FieldOrderCntList[i][0]; + } else if (ref_flag & 0x2) { + m_lists[0][i].ref_poc = pp->FieldOrderCntList[i][1]; + } +#if DEBUG_REF_LIST + mpp_log("i %d ref_pic_num %d lt_flag %d ref_flag %d ref_poc %d cur_poc %d\n", + i, m_lists[0][i].ref_picnum, m_lists[0][i].lt_flag, ref_flag, + m_lists[0][i].ref_poc, m_lists[0][i].cur_poc); +#endif + num_reorder = i + 1; + } + } + /* + * the value of num_reorder may be greater than num_refs, + * e.g. v: valid x: invalid + * num_refs = 3, num_reorder = 4 + * the index 1 will be reorder to the end + * ┌─┬─┬─┬─┬─┬─┬─┐ + * │0│1│2│3│.│.│F│ + * ├─┼─┼─┼─┼─┼─┼─┤ + * │v│x│v│v│x│x│x│ + * └─┴─┴─┴─┴─┴─┴─┘ + */ + memcpy(m_lists[1], m_lists[0], sizeof(m_lists[0])); + memcpy(m_lists[2], m_lists[0], sizeof(m_lists[0])); + qsort(m_lists[0], num_reorder, sizeof(m_lists[0][0]), compare_p); + qsort(m_lists[1], num_reorder, sizeof(m_lists[1][0]), compare_b0); + qsort(m_lists[2], num_reorder, sizeof(m_lists[2][0]), compare_b1); + if (num_refs > 1 && !p_hal->pp->field_pic_flag) { + if (!memcmp(m_lists[1], m_lists[2], sizeof(m_lists[1]))) { + MPP_SWAP(H264dRefsList_t, m_lists[2][0], m_lists[2][1]); + } + } + + //!< list0 list1 listP + for (i = 0; i < 16; i++) { + set_refer_pic_list_p(p_regs, i, m_lists[0][i].idx); + set_refer_pic_list_b0(p_regs, i, m_lists[1][i].idx); + set_refer_pic_list_b1(p_regs, i, m_lists[2][i].idx); + } +#if DEBUG_REF_LIST + { + char file_name[128]; \ + sprintf(file_name, "/sdcard/test/mpp2_RefPicList_log.txt"); \ + FILE *fp = fopen(file_name, "ab"); \ + char buf[1024]; + RK_S32 buf_len = 0, buf_size = sizeof(buf) - 1; + // fwrite(buf, 1, size, fp); + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "frame_num %d field %d bottom %d\n", + pp->frame_num, pp->field_pic_flag, pp->CurrPic.AssociatedFlag); + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "list0 : "); + for (i = 0; i < 16; i++) + buf_len += snprintf(buf + buf_len, buf_size - buf_len, " %04d", m_lists[1][i]); + fprintf(fp, "%s\n", buf); + + buf_len = 0; + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "list1 : "); + for (i = 0; i < 16; i++) + buf_len += snprintf(buf + buf_len, buf_size - buf_len, " %04d", m_lists[2][i]); + fprintf(fp, "%s\n", buf); + + buf_len = 0; + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "listP : "); + for (i = 0; i < 16; i++) + buf_len += snprintf(buf + buf_len, buf_size - buf_len, " %04d", m_lists[0][i]); + fprintf(fp, "%s\n", buf); + + fflush(fp); \ + fclose(fp); \ + } +#endif + + return ret = MPP_OK; +} + +static MPP_RET set_asic_regs(H264dHalCtx_t *p_hal, H264dVdpuRegs_t *p_regs) +{ + RK_U32 i = 0, j = 0; + RK_U32 outPhyAddr = 0; + MppBuffer frame_buf = NULL; + MPP_RET ret = MPP_ERR_UNKNOW; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + DXVA_Slice_H264_Long *p_long = &p_hal->slice_long[0]; + MppBufSlots frm_slots = p_hal->cfg->frame_slots; + + { +#if DEBUG_REF_LIST + char file_name[128]; \ + sprintf(file_name, "/sdcard/test/mpp2_dpb_log.txt"); \ + FILE *fp = fopen(file_name, "ab"); \ + char buf[2048]; + static RK_U32 num = 0; + RK_S32 buf_len = 0, buf_size = sizeof(buf) - 1; + + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "cnt %d frame_num %d field %d bottom %d\n", + num++, pp->frame_num, pp->field_pic_flag, pp->CurrPic.AssociatedFlag); +#endif + for (i = 0, j = 0xff; i < MPP_ARRAY_ELEMS(pp->RefFrameList); i++) { + RK_U32 val = 0; + RK_U32 top_closer = 0; + RK_U32 field_flag = 0; + RK_S32 cur_poc = 0; + RK_U32 used_flag = 0; + + if (pp->RefFrameList[i].bPicEntry != 0xff) { + mpp_buf_slot_get_prop(frm_slots, + pp->RefFrameList[i].Index7Bits, + SLOT_BUFFER, &frame_buf); //!< reference phy addr + j = i; +#if DEBUG_REF_LIST + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "refPicList[%d], frame_num=%d, poc0=%d, poc1=%d\n", + i, pp->FrameNumList[i], pp->FieldOrderCntList[i][0], pp->FieldOrderCntList[i][1]); +#endif + } else { + mpp_buf_slot_get_prop(frm_slots, + pp->CurrPic.Index7Bits, + SLOT_BUFFER, &frame_buf); //!< current out phy addr + } + + field_flag = ((pp->RefPicFiledFlags >> i) & 0x1) ? 0x2 : 0; + cur_poc = (pp->CurrPic.AssociatedFlag != 0) + ? pp->CurrFieldOrderCnt[1] : pp->CurrFieldOrderCnt[0]; + used_flag = ((pp->UsedForReferenceFlags >> (2 * i)) & 0x3); + if (used_flag & 0x3) { + top_closer = MPP_ABS(pp->FieldOrderCntList[i][0] - cur_poc) < + MPP_ABS(pp->FieldOrderCntList[i][1] - cur_poc) ? 0x1 : 0; + } else if (used_flag & 0x2) { + top_closer = 0; + } else if (used_flag & 0x1) { + top_closer = 1; + } + val = top_closer | field_flag; + if (val) { + mpp_dev_set_reg_offset(p_hal->cfg->dev, vdpu2_ref_idx[i], val); +#if DEBUG_REF_LIST + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "ref_offset[%d] %d\n", + i, val); +#endif + } + set_refer_pic_base_addr(p_regs, i, mpp_buffer_get_fd(frame_buf)); + } +#if DEBUG_REF_LIST + fprintf(fp, "%s\n", buf); + fflush(fp); + fclose(fp); +#endif + } + /* inter-view reference picture */ + { + H264dVdpuPriv_t *priv = (H264dVdpuPriv_t *)p_hal->priv; + if (pp->curr_layer_id && priv->ilt_dpb && priv->ilt_dpb->valid) { + mpp_buf_slot_get_prop(frm_slots, + priv->ilt_dpb->slot_index, + SLOT_BUFFER, &frame_buf); + p_regs->sw99.ref15_st_addr = mpp_buffer_get_fd(frame_buf); //!< inter-view base, ref15 + p_regs->sw108.refpic_valid_flag |= ((pp->field_pic_flag != 0) + ? 0x3 : 0x10000); + } + } + p_regs->sw50.dec_fixed_quant = pp->curr_layer_id; //!< VDPU_MVC_E + p_regs->sw50.dblk_flt_dis = 0; //!< filterDisable = 0; + mpp_buf_slot_get_prop(frm_slots, + pp->CurrPic.Index7Bits, + SLOT_BUFFER, &frame_buf); //!< current out phy addr + outPhyAddr = mpp_buffer_get_fd(frame_buf); + if (pp->field_pic_flag && pp->CurrPic.AssociatedFlag) { + mpp_dev_set_reg_offset(p_hal->cfg->dev, 63, ((pp->wFrameWidthInMbsMinus1 + 1) * 16)); + } + p_regs->sw63.dec_out_st_adr = outPhyAddr; //!< outPhyAddr, pp->CurrPic.Index7Bits + p_regs->sw110.flt_offset_cb_qp = pp->chroma_qp_index_offset; + p_regs->sw110.flt_offset_cr_qp = pp->second_chroma_qp_index_offset; + /* set default value for register[41] to avoid illegal translation fd */ + { + RK_U32 dirMvOffset = 0; + RK_U32 picSizeInMbs = 0; + + picSizeInMbs = p_hal->pp->wFrameWidthInMbsMinus1 + 1; + picSizeInMbs = picSizeInMbs + * (2 - pp->frame_mbs_only_flag) * (pp->wFrameHeightInMbsMinus1 + 1); + dirMvOffset = picSizeInMbs + * ((p_hal->pp->chroma_format_idc == 0) ? 256 : 384); + dirMvOffset += (pp->field_pic_flag && pp->CurrPic.AssociatedFlag) + ? (picSizeInMbs * 32) : 0; + if (dirMvOffset) { + RK_U32 offset = mpp_get_ioctl_version() ? dirMvOffset : dirMvOffset >> 4; + mpp_dev_set_reg_offset(p_hal->cfg->dev, 62, offset); + } + p_regs->sw62.dmmv_st_adr = mpp_buffer_get_fd(frame_buf); + } + p_regs->sw57.dmmv_wr_en = (p_long->nal_ref_idc != 0) ? 1 : 0; //!< defalut set 1 + p_regs->sw115.dlmv_method_en = pp->direct_8x8_inference_flag; + p_regs->sw115.weight_pred_en = pp->weighted_pred_flag; + p_regs->sw111.wp_bslice_sel = pp->weighted_bipred_idc; + p_regs->sw114.max_refidx1 = (pp->num_ref_idx_l1_active_minus1 + 1); + p_regs->sw115.fieldpic_flag_exist = (pp->frame_mbs_only_flag == 0) ? 1 : 0; + p_regs->sw57.curpic_code_sel = (!pp->frame_mbs_only_flag + && (pp->MbaffFrameFlag || pp->field_pic_flag)) ? 1 : 0; + p_regs->sw57.curpic_stru_sel = pp->field_pic_flag; + p_regs->sw57.pic_decfield_sel = (pp->CurrPic.AssociatedFlag == 0) ? 1 : 0; //!< bottomFieldFlag + p_regs->sw57.sequ_mbaff_en = pp->MbaffFrameFlag; + p_regs->sw115.tranf_8x8_flag_en = pp->transform_8x8_mode_flag; + p_regs->sw115.monochr_en = (p_long->profileIdc >= 100 + && pp->chroma_format_idc == 0) ? 1 : 0; + p_regs->sw115.scl_matrix_en = pp->scaleing_list_enable_flag; + { + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + if (p_hal->pp->scaleing_list_enable_flag) { + RK_U32 temp = 0; + RK_U32 *ptr = (RK_U32 *)reg_ctx->sclst_ptr; + + for (i = 0; i < 6; i++) { + for (j = 0; j < 4; j++) { + temp = (p_hal->qm->bScalingLists4x4[i][4 * j + 0] << 24) | + (p_hal->qm->bScalingLists4x4[i][4 * j + 1] << 16) | + (p_hal->qm->bScalingLists4x4[i][4 * j + 2] << 8) | + (p_hal->qm->bScalingLists4x4[i][4 * j + 3]); + *ptr++ = temp; + } + } + for (i = 0; i < 2; i++) { + for (j = 0; j < 16; j++) { + temp = (p_hal->qm->bScalingLists8x8[i][4 * j + 0] << 24) | + (p_hal->qm->bScalingLists8x8[i][4 * j + 1] << 16) | + (p_hal->qm->bScalingLists8x8[i][4 * j + 2] << 8) | + (p_hal->qm->bScalingLists8x8[i][4 * j + 3]); + *ptr++ = temp; + } + } + } + p_regs->sw61.qtable_st_adr = mpp_buffer_get_fd(reg_ctx->buf); + } + p_regs->sw57.dec_wr_extmen_dis = 0; //!< set defalut 0 + p_regs->sw57.addit_ch_fmt_wen = 0; + p_regs->sw57.dec_st_work = 1; + + return ret = MPP_OK; +} + +/*! +*********************************************************************** +* \brief +* init VDPU granite decoder +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + + INP_CHECK(ret, NULL == hal); + + MEM_CHECK(ret, p_hal->priv = mpp_calloc_size(void, sizeof(H264dVdpuPriv_t))); + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(H264dVdpuRegCtx_t))); + p_hal->cfg = cfg; + + cfg->support_fast_mode = 0; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + //!< malloc buffers + { + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + + RK_U32 buf_size = VDPU_CABAC_TAB_SIZE + VDPU_POC_BUF_SIZE + VDPU_SCALING_LIST_SIZE; + for (i = 0; i < loop; i++) { + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->reg_buf[i].buf, buf_size)); + reg_ctx->reg_buf[i].cabac_ptr = mpp_buffer_get_ptr(reg_ctx->reg_buf[i].buf); + reg_ctx->reg_buf[i].poc_ptr = reg_ctx->reg_buf[i].cabac_ptr + VDPU_CABAC_TAB_SIZE; + reg_ctx->reg_buf[i].sclst_ptr = reg_ctx->reg_buf[i].poc_ptr + VDPU_POC_BUF_SIZE; + reg_ctx->reg_buf[i].regs = mpp_calloc_size(void, sizeof(H264dVdpuRegs_t)); + //!< copy cabac table bytes + memcpy(reg_ctx->reg_buf[i].cabac_ptr, (void *)vdpu_cabac_table, sizeof(vdpu_cabac_table)); + } + } + + if (!p_hal->fast_mode) { + reg_ctx->buf = reg_ctx->reg_buf[0].buf; + reg_ctx->cabac_ptr = reg_ctx->reg_buf[0].cabac_ptr; + reg_ctx->poc_ptr = reg_ctx->reg_buf[0].poc_ptr; + reg_ctx->sclst_ptr = reg_ctx->reg_buf[0].sclst_ptr; + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + } + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu2_h264d_deinit(hal); + + return ret; +} + + +/*! +*********************************************************************** +* \brief +* deinit +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_deinit(void *hal) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + for (i = 0; i < loop; i++) { + MPP_FREE(reg_ctx->reg_buf[i].regs); + mpp_buffer_put(reg_ctx->reg_buf[i].buf); + } + + MPP_FREE(p_hal->reg_ctx); + MPP_FREE(p_hal->priv); + + return MPP_OK; +} +/*! +*********************************************************************** +* \brief +* generate register +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + H264dVdpuPriv_t *priv = NULL; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, NULL == p_hal); + p_hal->in_task = &task->dec; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + hal_h264d_explain_input_buffer(hal, &task->dec); + priv = p_hal->priv; + priv->layed_id = p_hal->pp->curr_layer_id; + + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(reg_ctx->reg_buf); i++) { + if (!reg_ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + reg_ctx->buf = reg_ctx->reg_buf[i].buf; + reg_ctx->cabac_ptr = reg_ctx->reg_buf[i].cabac_ptr; + reg_ctx->poc_ptr = reg_ctx->reg_buf[i].poc_ptr; + reg_ctx->sclst_ptr = reg_ctx->reg_buf[i].sclst_ptr; + reg_ctx->regs = reg_ctx->reg_buf[i].regs; + reg_ctx->reg_buf[i].valid = 1; + break; + } + } + } + + FUN_CHECK(ret = adjust_input(priv, &p_hal->slice_long[0], p_hal->pp)); + FUN_CHECK(ret = set_device_regs(p_hal, (H264dVdpuRegs_t *)reg_ctx->regs)); + FUN_CHECK(ret = set_pic_regs(p_hal, (H264dVdpuRegs_t *)reg_ctx->regs)); + FUN_CHECK(ret = set_vlc_regs(p_hal, (H264dVdpuRegs_t *)reg_ctx->regs)); + FUN_CHECK(ret = set_ref_regs(p_hal, (H264dVdpuRegs_t *)reg_ctx->regs)); + FUN_CHECK(ret = set_asic_regs(p_hal, (H264dVdpuRegs_t *)reg_ctx->regs)); + mpp_buffer_sync_end(reg_ctx->buf); + +__RETURN: + return ret = MPP_OK; +__FAILED: + return ret; +} +/*! +*********************************************************************** +* \brief h +* start hard +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + H264dVdpuRegs_t *p_regs = (p_hal->fast_mode != 0) ? + (H264dVdpuRegs_t *)reg_ctx->reg_buf[task->dec.reg_index].regs : + (H264dVdpuRegs_t *)reg_ctx->regs; + RK_U32 w = p_regs->sw110.pic_mb_w * 16; + RK_U32 h = p_regs->sw110.pic_mb_h * 16; + RK_U32 cache_en = 1; + RockchipSocType soc_type = mpp_get_soc_type(); + MppDev dev = p_hal->cfg->dev; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + if (soc_type == ROCKCHIP_SOC_RK3326 || + soc_type == ROCKCHIP_SOC_PX30 || + soc_type == ROCKCHIP_SOC_RK3228H) + cache_en = ((w * h) >= (1280 * 720)) ? 1 : 0; + + p_regs->sw57.cache_en = cache_en; + p_regs->sw57.pref_sigchan = 1; + p_regs->sw56.bus_pos_sel = 1; + p_regs->sw57.intra_dbl3t = 1; + p_regs->sw57.inter_dblspeed = 1; + p_regs->sw57.intra_dblspeed = 1; + +#if DEBUG_REF_LIST + { + char file_name[128]; + sprintf(file_name, "/sdcard/test/mpp2_reg_dump_log.txt"); + FILE *fp = fopen(file_name, "ab"); + char buf[2048]; + RK_S32 buf_len = 0, buf_size = sizeof(buf) - 1; + RK_U32 *reg_tmp = (RK_U32*)reg_ctx->regs; + RK_U32 i; + + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "=== reg dump fram_num %d ===\n", + p_hal->pp->frame_num); + for (i = 50; i < 116; i++) { + buf_len += snprintf(buf + buf_len, buf_size - buf_len, "Regs[%d] = 0x%08x\n", i, reg_tmp[i]); + } + fprintf(fp, "%s", buf); + + fflush(fp); + fclose(fp); + } +#endif + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = DEC_VDPU_REGISTERS * sizeof(RK_U32); + + wr_cfg.reg = reg_ctx->regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = reg_ctx->regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + (void)task; + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* wait hard +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + H264dVdpuRegCtx_t *reg_ctx = (H264dVdpuRegCtx_t *)p_hal->reg_ctx; + H264dVdpuRegs_t *p_regs = (H264dVdpuRegs_t *)((p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)reg_ctx->regs; + param.hard_err = !p_regs->sw55.dec_rdy_sts; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + memset(&p_regs->sw55, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) { + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + } + + (void)task; + + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* reset +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_reset(void *hal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + memset(p_hal->priv, 0, sizeof(H264dVdpuPriv_t)); + +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* flush +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_flush(void *hal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + +__RETURN: + return ret = MPP_OK; +} +/*! +*********************************************************************** +* \brief +* control +*********************************************************************** +*/ +//extern "C" +MPP_RET vdpu2_h264d_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + (void)hal; + (void)cmd_type; + (void)param; +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_vdpu2 = { + .name = "h264d_vdpu2", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = vdpu2_h264d_init, + .deinit = vdpu2_h264d_deinit, + .reg_gen = vdpu2_h264d_gen_regs, + .start = vdpu2_h264d_start, + .wait = vdpu2_h264d_wait, + .reset = vdpu2_h264d_reset, + .flush = vdpu2_h264d_flush, + .control = vdpu2_h264d_control, + .client = VPU_CLIENT_VDPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_vdpu2) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu2.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu2.h new file mode 100644 index 000000000..95251730f --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu2.h @@ -0,0 +1,33 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264D_VDPU2_REG_H +#define HAL_H264D_VDPU2_REG_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_vdpu2; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU2_REG_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu2_reg.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu2_reg.h new file mode 100644 index 000000000..5ebd1f19b --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu2_reg.h @@ -0,0 +1,466 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264D_VDPU2_REG_TBL_H +#define HAL_H264D_VDPU2_REG_TBL_H + +#include "rk_type.h" + +/* Number registers for the decoder */ +#define DEC_VDPU_REGISTERS 159 + +typedef struct { + RK_U32 sw00_49[50]; + struct { + RK_U32 dec_tiled_msb : 1; + RK_U32 adtion_latency : 6; + RK_U32 dec_fixed_quant : 1; + RK_U32 dblk_flt_dis : 1; + RK_U32 skip_sel : 1; + RK_U32 dec_ascmd0_dis : 1; + RK_U32 adv_pref_dis : 1; + RK_U32 dec_tiled_lsb : 1; + RK_U32 refbuf_thrd : 12; + RK_U32 refbuf_pid : 5; + RK_U32 reverse0 : 2; + } sw50; + struct { + RK_U32 stream_len : 24; + RK_U32 stream_len_ext : 1; + RK_U32 qp_init_val : 6; + RK_U32 reverse0 : 1; + } sw51; + struct { + RK_U32 ydim_mbst : 8; + RK_U32 xdim_mbst : 9; + RK_U32 adv_pref_thrd : 14; + RK_U32 reverse0 : 1; + } sw52; + struct { + RK_U32 dec_fmt_sel : 4; + RK_U32 reverse0 : 28; + } sw53; + struct { + RK_U32 dec_in_endian : 1; + RK_U32 dec_out_endian : 1; + RK_U32 dec_in_wordsp : 1; + RK_U32 dec_out_wordsp : 1; + RK_U32 dec_strm_wordsp : 1; + RK_U32 dec_strendian_e : 1; + RK_U32 reverse0 : 26; + } sw54; + struct { + RK_U32 dec_irq : 1; + RK_U32 dec_irq_dis : 1; + RK_U32 reverse0 : 2; + RK_U32 dec_rdy_sts : 1; + RK_U32 pp_bus_sts : 1; + RK_U32 buf_emt_sts : 1; + RK_U32 reverse1 : 1; + RK_U32 aso_det_sts : 1; + RK_U32 slice_det_sts : 1; + RK_U32 bslice_det_sts : 1; + RK_U32 reverse2 : 1; + RK_U32 error_det_sts : 1; + RK_U32 timeout_det_sts : 1; + RK_U32 reverse3 : 18; + } sw55; + struct { + RK_U32 dec_axi_id_rd : 8; + RK_U32 dec_axi_id_wr : 8; + RK_U32 dec_max_burlen : 5; + RK_U32 bus_pos_sel : 1; + RK_U32 dec_data_discd_en : 1; + RK_U32 axi_sel : 1; + RK_U32 reverse0 : 8; + } sw56; + struct { + RK_U32 dec_st_work : 1; + RK_U32 refpic_buf2_en : 1; + RK_U32 dec_wr_extmen_dis : 1; + RK_U32 reverse0 : 1; + RK_U32 dec_clkgate_en : 1; + RK_U32 timeout_sts_en : 1; + RK_U32 rd_cnt_tab_en : 1; + RK_U32 sequ_mbaff_en : 1; + RK_U32 first_reftop_en : 1; + RK_U32 reftop_en : 1; + RK_U32 dmmv_wr_en : 1; + RK_U32 sorspa_en : 1; + RK_U32 fwd_refpic_mode_sel : 1; + RK_U32 pic_decfield_sel : 1; + RK_U32 pic_type_sel0 : 1; + RK_U32 pic_type_sel1 : 1; + RK_U32 curpic_stru_sel : 1; + RK_U32 curpic_code_sel : 1; + RK_U32 prog_jpeg_en : 1; + RK_U32 divx3_en : 1; + RK_U32 rlc_mode_en : 1; + RK_U32 addit_ch_fmt_wen : 1; + RK_U32 st_code_exit : 1; + RK_U32 reverse1 : 2; + RK_U32 inter_dblspeed : 1; + RK_U32 intra_dblspeed : 1; + RK_U32 intra_dbl3t : 1; + RK_U32 pref_sigchan : 1; + RK_U32 cache_en : 1; + RK_U32 reverse2 : 1; + RK_U32 dec_timeout_mode : 1; + } sw57; + struct { + RK_U32 soft_rst : 1; + RK_U32 reverse0 : 31; + } sw58; + struct { + RK_U32 reverse0 : 2; + RK_U32 pflt_set0_tap2 : 10; + RK_U32 pflt_set0_tap1 : 10; + RK_U32 pflt_set0_tap0 : 10; + } sw59; + struct { + RK_U32 addit_ch_st_adr : 32; + } sw60; + struct { + RK_U32 qtable_st_adr : 32; + } sw61; + struct { + RK_U32 dmmv_st_adr : 32; + } sw62; + struct { + RK_U32 dec_out_st_adr : 32; + } sw63; + struct { + RK_U32 rlc_vlc_st_adr : 32; + } sw64; + struct { + RK_U32 refbuf_y_offset : 9; + RK_U32 reserve0 : 3; + RK_U32 refbuf_fildpar_mode_e : 1; + RK_U32 refbuf_idcal_e : 1; + RK_U32 refbuf_picid : 5; + RK_U32 refbuf_thr_level : 12; + RK_U32 refbuf_e : 1; + } sw65; + RK_U32 sw66; + RK_U32 sw67; + struct { + RK_U32 refbuf_sum_bot : 16; + RK_U32 refbuf_sum_top : 16; + } sw68; + struct { + RK_U32 luma_sum_intra : 16; + RK_U32 refbuf_sum_hit : 16; + } sw69; + struct { + RK_U32 ycomp_mv_sum : 22; + RK_U32 reserve0 : 10; + } sw70; + RK_U32 sw71; + RK_U32 sw72; + RK_U32 sw73; + struct { + RK_U32 init_reflist_pf4 : 5; + RK_U32 init_reflist_pf5 : 5; + RK_U32 init_reflist_pf6 : 5; + RK_U32 init_reflist_pf7 : 5; + RK_U32 init_reflist_pf8 : 5; + RK_U32 init_reflist_pf9 : 5; + RK_U32 reverse0 : 2; + } sw74; + struct { + RK_U32 init_reflist_pf10 : 5; + RK_U32 init_reflist_pf11 : 5; + RK_U32 init_reflist_pf12 : 5; + RK_U32 init_reflist_pf13 : 5; + RK_U32 init_reflist_pf14 : 5; + RK_U32 init_reflist_pf15 : 5; + RK_U32 reverse0 : 2; + } sw75; + struct { + RK_U32 num_ref_idx0 : 16; + RK_U32 num_ref_idx1 : 16; + } sw76; + struct { + RK_U32 num_ref_idx2 : 16; + RK_U32 num_ref_idx3 : 16; + } sw77; + struct { + RK_U32 num_ref_idx4 : 16; + RK_U32 num_ref_idx5 : 16; + } sw78; + struct { + RK_U32 num_ref_idx6 : 16; + RK_U32 num_ref_idx7 : 16; + } sw79; + struct { + RK_U32 num_ref_idx8 : 16; + RK_U32 num_ref_idx9 : 16; + } sw80; + struct { + RK_U32 num_ref_idx10 : 16; + RK_U32 num_ref_idx11 : 16; + } sw81; + struct { + RK_U32 num_ref_idx12 : 16; + RK_U32 num_ref_idx13 : 16; + } sw82; + struct { + RK_U32 num_ref_idx14 : 16; + RK_U32 num_ref_idx15 : 16; + } sw83; + union { + RK_U32 ref0_st_addr; + struct { + RK_U32 ref0_closer_sel : 1; + RK_U32 ref0_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw84; + union { + RK_U32 ref1_st_addr; + struct { + RK_U32 ref1_closer_sel : 1; + RK_U32 ref1_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw85; + union { + RK_U32 ref2_st_addr; + struct { + RK_U32 ref2_closer_sel : 1; + RK_U32 ref2_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw86; + union { + RK_U32 ref3_st_addr; + struct { + RK_U32 ref3_closer_sel : 1; + RK_U32 ref3_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw87; + union { + RK_U32 ref4_st_addr; + struct { + RK_U32 ref4_closer_sel : 1; + RK_U32 ref4_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw88; + union { + RK_U32 ref5_st_addr; + struct { + RK_U32 ref5_closer_sel : 1; + RK_U32 ref5_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw89; + union { + RK_U32 ref6_st_addr; + struct { + RK_U32 ref6_closer_sel : 1; + RK_U32 ref6_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw90; + union { + RK_U32 ref7_st_addr; + struct { + RK_U32 ref7_closer_sel : 1; + RK_U32 ref7_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw91; + union { + RK_U32 ref8_st_addr; + struct { + RK_U32 ref8_closer_sel : 1; + RK_U32 ref8_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw92; + union { + RK_U32 ref9_st_addr; + struct { + RK_U32 ref9_closer_sel : 1; + RK_U32 ref9_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw93; + union { + RK_U32 ref10_st_addr; + struct { + RK_U32 ref10_closer_sel : 1; + RK_U32 ref10_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw94; + union { + RK_U32 ref11_st_addr; + struct { + RK_U32 ref11_closer_sel : 1; + RK_U32 ref11_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw95; + union { + RK_U32 ref12_st_addr; + struct { + RK_U32 ref12_closer_sel : 1; + RK_U32 ref12_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw96; + union { + RK_U32 ref13_st_addr; + struct { + RK_U32 ref13_closer_sel : 1; + RK_U32 ref13_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw97; + union { + RK_U32 ref14_st_addr; + struct { + RK_U32 ref14_closer_sel : 1; + RK_U32 ref14_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw98; + union { + RK_U32 ref15_st_addr; + struct { + RK_U32 ref15_closer_sel : 1; + RK_U32 ref15_field_en : 1; + RK_U32 reverse0 : 30; + }; + } sw99; + struct { + RK_U32 init_reflist_df0 : 5; + RK_U32 init_reflist_df1 : 5; + RK_U32 init_reflist_df2 : 5; + RK_U32 init_reflist_df3 : 5; + RK_U32 init_reflist_df4 : 5; + RK_U32 init_reflist_df5 : 5; + RK_U32 reverse0 : 2; + } sw100; + struct { + RK_U32 init_reflist_df6 : 5; + RK_U32 init_reflist_df7 : 5; + RK_U32 init_reflist_df8 : 5; + RK_U32 init_reflist_df9 : 5; + RK_U32 init_reflist_df10 : 5; + RK_U32 init_reflist_df11 : 5; + RK_U32 reverse0 : 2; + } sw101; + struct { + RK_U32 init_reflist_df12 : 5; + RK_U32 init_reflist_df13 : 5; + RK_U32 init_reflist_df14 : 5; + RK_U32 init_reflist_df15 : 5; + RK_U32 reverse0 : 12; + } sw102; + struct { + RK_U32 init_reflist_db0 : 5; + RK_U32 init_reflist_db1 : 5; + RK_U32 init_reflist_db2 : 5; + RK_U32 init_reflist_db3 : 5; + RK_U32 init_reflist_db4 : 5; + RK_U32 init_reflist_db5 : 5; + RK_U32 reverse0 : 2; + } sw103; + struct { + RK_U32 init_reflist_db6 : 5; + RK_U32 init_reflist_db7 : 5; + RK_U32 init_reflist_db8 : 5; + RK_U32 init_reflist_db9 : 5; + RK_U32 init_reflist_db10 : 5; + RK_U32 init_reflist_db11 : 5; + RK_U32 reverse0 : 2; + } sw104; + struct { + RK_U32 init_reflist_db12 : 5; + RK_U32 init_reflist_db13 : 5; + RK_U32 init_reflist_db14 : 5; + RK_U32 init_reflist_db15 : 5; + RK_U32 reverse0 : 12; + } sw105; + struct { + RK_U32 init_reflist_pf0 : 5; + RK_U32 init_reflist_pf1 : 5; + RK_U32 init_reflist_pf2 : 5; + RK_U32 init_reflist_pf3 : 5; + RK_U32 reverse0 : 12; + } sw106; + struct { + RK_U32 refpic_term_flag : 32; + } sw107; + struct { + RK_U32 refpic_valid_flag : 32; + } sw108; + struct { + RK_U32 strm_start_bit : 6; + RK_U32 reverse0 : 26; + } sw109; + struct { + RK_U32 pic_mb_w : 9; + RK_U32 pic_mb_h : 8; + RK_U32 flt_offset_cb_qp : 5; + RK_U32 flt_offset_cr_qp : 5; + RK_U32 reverse0 : 5; + } sw110; + struct { + RK_U32 max_refnum : 5; + RK_U32 reverse0 : 11; + RK_U32 wp_bslice_sel : 2; + RK_U32 reverse1 : 14; + } sw111; + struct { + RK_U32 curfrm_num : 16; + RK_U32 cur_frm_len : 5; + RK_U32 reverse0 : 9; + RK_U32 rpcp_flag : 1; + RK_U32 dblk_ctrl_flag : 1; + } sw112; + struct { + RK_U32 idr_pic_id : 16; + RK_U32 refpic_mk_len : 11; + RK_U32 reverse0 : 5; + } sw113; + struct { + RK_U32 poc_field_len : 8; + RK_U32 reverse0 : 6; + RK_U32 max_refidx0 : 5; + RK_U32 max_refidx1 : 5; + RK_U32 pps_id : 8; + } sw114; + struct { + RK_U32 fieldpic_flag_exist : 1; + RK_U32 scl_matrix_en : 1; + RK_U32 tranf_8x8_flag_en : 1; + RK_U32 const_intra_en : 1; + RK_U32 weight_pred_en : 1; + RK_U32 cabac_en : 1; + RK_U32 monochr_en : 1; + RK_U32 dlmv_method_en : 1; + RK_U32 idr_pic_flag : 1; + RK_U32 reverse0 : 23; + } sw115; + RK_U32 sw116_158[43]; +} H264dVdpuRegs_t; + +#endif /* HAL_H264D_VDPU_REG_TBL_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu34x.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu34x.c new file mode 100644 index 000000000..5f67350d0 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu34x.c @@ -0,0 +1,1019 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264d_vdpu34x" + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_bitput.h" + +#include "mpp_device.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_vdpu34x.h" +#include "vdpu34x_h264d.h" +#include "mpp_dec_cb_param.h" +#include "vdpu_com.h" +#include "hal_h264d_ctx.h" +#include "hal_h264d_com.h" + +/* Number registers for the decoder */ +#define DEC_VDPU34X_REGISTERS 276 + +#define VDPU34X_CABAC_TAB_SIZE (928*4 + 128) /* bytes */ +#define VDPU34X_SPSPPS_UNIT_SIZE (48) /* bytes */ +#define VDPU34X_SPSPPS_SIZE (256*48 + 128) /* bytes */ +#define VDPU34X_RPS_SIZE (128 + 128 + 128) /* bytes */ +#define VDPU34X_SCALING_LIST_SIZE (6*16+2*64 + 128) /* bytes */ +#define VDPU34X_ERROR_INFO_SIZE (256*144*4) /* bytes */ + +#define VDPU34X_CABAC_TAB_ALIGNED_SIZE (MPP_ALIGN(VDPU34X_CABAC_TAB_SIZE, SZ_4K)) +#define VDPU34X_ERROR_INFO_ALIGNED_SIZE (0) +#define VDPU34X_SPSPPS_ALIGNED_SIZE (MPP_ALIGN(VDPU34X_SPSPPS_SIZE, SZ_4K)) +#define VDPU34X_RPS_ALIGNED_SIZE (MPP_ALIGN(VDPU34X_RPS_SIZE, SZ_4K)) +#define VDPU34X_SCALING_LIST_ALIGNED_SIZE (MPP_ALIGN(VDPU34X_SCALING_LIST_SIZE, SZ_4K)) +#define VDPU34X_STREAM_INFO_SET_SIZE (VDPU34X_SPSPPS_ALIGNED_SIZE + \ + VDPU34X_RPS_ALIGNED_SIZE + \ + VDPU34X_SCALING_LIST_ALIGNED_SIZE) + +#define VDPU34X_CABAC_TAB_OFFSET (0) +#define VDPU34X_ERROR_INFO_OFFSET (VDPU34X_CABAC_TAB_OFFSET + VDPU34X_CABAC_TAB_ALIGNED_SIZE) +#define VDPU34X_STREAM_INFO_OFFSET_BASE (VDPU34X_ERROR_INFO_OFFSET + VDPU34X_ERROR_INFO_ALIGNED_SIZE) +#define VDPU34X_SPSPPS_OFFSET(pos) (VDPU34X_STREAM_INFO_OFFSET_BASE + (VDPU34X_STREAM_INFO_SET_SIZE * pos)) +#define VDPU34X_RPS_OFFSET(pos) (VDPU34X_SPSPPS_OFFSET(pos) + VDPU34X_SPSPPS_ALIGNED_SIZE) +#define VDPU34X_SCALING_LIST_OFFSET(pos) (VDPU34X_RPS_OFFSET(pos) + VDPU34X_RPS_ALIGNED_SIZE) +#define VDPU34X_INFO_BUFFER_SIZE(cnt) (VDPU34X_STREAM_INFO_OFFSET_BASE + (VDPU34X_STREAM_INFO_SET_SIZE * cnt)) + +#define VDPU34X_SPS_PPS_LEN (43) + +#define SET_REF_INFO(regs, index, field, value)\ + do{ \ + switch(index){\ + case 0: regs.reg99.ref0_##field = value; break;\ + case 1: regs.reg99.ref1_##field = value; break;\ + case 2: regs.reg99.ref2_##field = value; break;\ + case 3: regs.reg99.ref3_##field = value; break;\ + case 4: regs.reg100.ref4_##field = value; break;\ + case 5: regs.reg100.ref5_##field = value; break;\ + case 6: regs.reg100.ref6_##field = value; break;\ + case 7: regs.reg100.ref7_##field = value; break;\ + case 8: regs.reg101.ref8_##field = value; break;\ + case 9: regs.reg101.ref9_##field = value; break;\ + case 10: regs.reg101.ref10_##field = value; break;\ + case 11: regs.reg101.ref11_##field = value; break;\ + case 12: regs.reg102.ref12_##field = value; break;\ + case 13: regs.reg102.ref13_##field = value; break;\ + case 14: regs.reg102.ref14_##field = value; break;\ + case 15: regs.reg102.ref15_##field = value; break;\ + default: break;}\ + }while(0) + +#define SET_POC_HIGNBIT_INFO(regs, index, field, value)\ + do{ \ + switch(index){\ + case 0: regs.reg200.ref0_##field = value; break;\ + case 1: regs.reg200.ref1_##field = value; break;\ + case 2: regs.reg200.ref2_##field = value; break;\ + case 3: regs.reg200.ref3_##field = value; break;\ + case 4: regs.reg200.ref4_##field = value; break;\ + case 5: regs.reg200.ref5_##field = value; break;\ + case 6: regs.reg200.ref6_##field = value; break;\ + case 7: regs.reg200.ref7_##field = value; break;\ + case 8: regs.reg201.ref8_##field = value; break;\ + case 9: regs.reg201.ref9_##field = value; break;\ + case 10: regs.reg201.ref10_##field = value; break;\ + case 11: regs.reg201.ref11_##field = value; break;\ + case 12: regs.reg201.ref12_##field = value; break;\ + case 13: regs.reg201.ref13_##field = value; break;\ + case 14: regs.reg201.ref14_##field = value; break;\ + case 15: regs.reg201.ref15_##field = value; break;\ + case 16: regs.reg202.ref16_##field = value; break;\ + case 17: regs.reg202.ref17_##field = value; break;\ + case 18: regs.reg202.ref18_##field = value; break;\ + case 19: regs.reg202.ref19_##field = value; break;\ + case 20: regs.reg202.ref20_##field = value; break;\ + case 21: regs.reg202.ref21_##field = value; break;\ + case 22: regs.reg202.ref22_##field = value; break;\ + case 23: regs.reg202.ref23_##field = value; break;\ + case 24: regs.reg203.ref24_##field = value; break;\ + case 25: regs.reg203.ref25_##field = value; break;\ + case 26: regs.reg203.ref26_##field = value; break;\ + case 27: regs.reg203.ref27_##field = value; break;\ + case 28: regs.reg203.ref28_##field = value; break;\ + case 29: regs.reg203.ref29_##field = value; break;\ + case 30: regs.reg203.ref30_##field = value; break;\ + case 31: regs.reg203.ref31_##field = value; break;\ + default: break;}\ + }while(0) + +MPP_RET vdpu34x_h264d_deinit(void *hal); + +static MPP_RET prepare_spspps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0; + RK_S32 is_long_term = 0, voidx = 0; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + RK_U32 tmp = 0; + BitputCtx_t bp; + + mpp_set_bitput_ctx(&bp, data, len); + + if (!p_hal->fast_mode && !pp->spspps_update) { + bp.index = VDPU34X_SPS_PPS_LEN >> 3; + bp.bitpos = (VDPU34X_SPS_PPS_LEN & 0x7) << 3; + } else { + //!< sps syntax + mpp_put_bits(&bp, -1, 13); //!< sps_id 4bit && profile_idc 8bit && constraint_set3_flag 1bit + mpp_put_bits(&bp, pp->chroma_format_idc, 2); + mpp_put_bits(&bp, pp->bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, pp->bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, 0, 1); //!< qpprime_y_zero_transform_bypass_flag + mpp_put_bits(&bp, pp->log2_max_frame_num_minus4, 4); + mpp_put_bits(&bp, pp->num_ref_frames, 5); + mpp_put_bits(&bp, pp->pic_order_cnt_type, 2); + mpp_put_bits(&bp, pp->log2_max_pic_order_cnt_lsb_minus4, 4); + mpp_put_bits(&bp, pp->delta_pic_order_always_zero_flag, 1); + mpp_put_bits(&bp, (pp->wFrameWidthInMbsMinus1 + 1), 12); + mpp_put_bits(&bp, (pp->wFrameHeightInMbsMinus1 + 1), 12); + mpp_put_bits(&bp, pp->frame_mbs_only_flag, 1); + mpp_put_bits(&bp, pp->MbaffFrameFlag, 1); + mpp_put_bits(&bp, pp->direct_8x8_inference_flag, 1); + + mpp_put_bits(&bp, 1, 1); //!< mvc_extension_enable + mpp_put_bits(&bp, (pp->num_views_minus1 + 1), 2); + mpp_put_bits(&bp, pp->view_id[0], 10); + mpp_put_bits(&bp, pp->view_id[1], 10); + mpp_put_bits(&bp, pp->num_anchor_refs_l0[0], 1); + if (pp->num_anchor_refs_l0[0]) { + mpp_put_bits(&bp, pp->anchor_ref_l0[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); + } + mpp_put_bits(&bp, pp->num_anchor_refs_l1[0], 1); + if (pp->num_anchor_refs_l1[0]) { + mpp_put_bits(&bp, pp->anchor_ref_l1[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); //!< anchor_ref_l1 + } + mpp_put_bits(&bp, pp->num_non_anchor_refs_l0[0], 1); + if (pp->num_non_anchor_refs_l0[0]) { + mpp_put_bits(&bp, pp->non_anchor_ref_l0[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); //!< non_anchor_ref_l0 + } + mpp_put_bits(&bp, pp->num_non_anchor_refs_l1[0], 1); + if (pp->num_non_anchor_refs_l1[0]) { + mpp_put_bits(&bp, pp->non_anchor_ref_l1[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10);//!< non_anchor_ref_l1 + } + mpp_put_align(&bp, 128, 0); + //!< pps syntax + mpp_put_bits(&bp, -1, 13); //!< pps_id 8bit && sps_id 5bit + mpp_put_bits(&bp, pp->entropy_coding_mode_flag, 1); + mpp_put_bits(&bp, pp->pic_order_present_flag, 1); + mpp_put_bits(&bp, pp->num_ref_idx_l0_active_minus1, 5); + mpp_put_bits(&bp, pp->num_ref_idx_l1_active_minus1, 5); + mpp_put_bits(&bp, pp->weighted_pred_flag, 1); + mpp_put_bits(&bp, pp->weighted_bipred_idc, 2); + mpp_put_bits(&bp, pp->pic_init_qp_minus26, 7); + mpp_put_bits(&bp, pp->pic_init_qs_minus26, 6); + mpp_put_bits(&bp, pp->chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->deblocking_filter_control_present_flag, 1); + mpp_put_bits(&bp, pp->constrained_intra_pred_flag, 1); + mpp_put_bits(&bp, pp->redundant_pic_cnt_present_flag, 1); + mpp_put_bits(&bp, pp->transform_8x8_mode_flag, 1); + mpp_put_bits(&bp, pp->second_chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->scaleing_list_enable_flag, 1); + mpp_put_bits(&bp, 0, 32);// scanlist buffer has another addr + } + + //!< set dpb + for (i = 0; i < 16; i++) { + is_long_term = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefFrameList[i].AssociatedFlag : 0; + tmp |= (RK_U32)(is_long_term & 0x1) << i; + } + for (i = 0; i < 16; i++) { + voidx = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefPicLayerIdList[i] : 0; + tmp |= (RK_U32)(voidx & 0x1) << (i + 16); + } + mpp_put_bits(&bp, tmp, 32); + mpp_put_align(&bp, 64, 0); + + return MPP_OK; +} + +static MPP_RET prepare_framerps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0, j = 0; + RK_S32 dpb_idx = 0, voidx = 0; + RK_S32 dpb_valid = 0, bottom_flag = 0; + RK_U32 max_frame_num = 0; + RK_U16 frame_num_wrap = 0; + RK_U32 tmp = 0; + + BitputCtx_t bp; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + + mpp_set_bitput_ctx(&bp, data, len); + mpp_put_align(&bp, 128, 0); + max_frame_num = 1 << (pp->log2_max_frame_num_minus4 + 4); + for (i = 0; i < 16; i++) { + if ((pp->NonExistingFrameFlags >> i) & 0x01) { + frame_num_wrap = 0; + } else { + if (pp->RefFrameList[i].AssociatedFlag) { + frame_num_wrap = pp->FrameNumList[i]; + } else { + frame_num_wrap = (pp->FrameNumList[i] > pp->frame_num) ? + (pp->FrameNumList[i] - max_frame_num) : pp->FrameNumList[i]; + } + } + + mpp_put_bits(&bp, frame_num_wrap, 16); + } + + mpp_put_bits(&bp, 0, 16);//!< NULL + tmp = 0; + for (i = 0; i < 16; i++) { + tmp |= (RK_U32)pp->RefPicLayerIdList[i] << i; + } + mpp_put_bits(&bp, tmp, 16); + + for (i = 0; i < 32; i++) { + tmp = 0; + dpb_valid = (p_hal->slice_long[0].RefPicList[0][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + tmp |= (RK_U32)(dpb_idx | (dpb_valid << 4)) & 0x1f; + tmp |= (RK_U32)(bottom_flag & 0x1) << 5; + tmp |= (RK_U32)(voidx & 0x1) << 6; + mpp_put_bits(&bp, tmp, 7); + } + for (j = 1; j < 3; j++) { + for (i = 0; i < 32; i++) { + tmp = 0; + dpb_valid = (p_hal->slice_long[0].RefPicList[j][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + tmp |= (RK_U32)(dpb_idx | (dpb_valid << 4)) & 0x1f; + tmp |= (RK_U32)(bottom_flag & 0x1) << 5; + tmp |= (RK_U32)(voidx & 0x1) << 6; + mpp_put_bits(&bp, tmp, 7); + } + } + mpp_put_align(&bp, 128, 0); + + return MPP_OK; +} + +static MPP_RET prepare_scanlist(H264dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + RK_U32 i = 0, j = 0, n = 0; + + if (p_hal->pp->scaleing_list_enable_flag) { + for (i = 0; i < 6; i++) { //!< 4x4, 6 lists + for (j = 0; j < 16; j++) { + data[n++] = p_hal->qm->bScalingLists4x4[i][j]; + } + } + for (i = 0; i < 2; i++) { //!< 8x8, 2 lists + for (j = 0; j < 64; j++) { + data[n++] = p_hal->qm->bScalingLists8x8[i][j]; + } + } + } + mpp_assert(n <= len); + + return MPP_OK; +} + +static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu34xH264dRegSet *regs, HalTaskInfo *task) +{ + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + Vdpu34xRegCommon *common = ®s->common; + MppBufSlots frm_slots = p_hal->cfg->frame_slots; + HalBuf *mv_buf = NULL; + + // memset(regs, 0, sizeof(Vdpu34xH264dRegSet)); + memset(®s->h264d_highpoc, 0, sizeof(regs->h264d_highpoc)); + common->reg016_str_len = p_hal->strm_len; + common->reg013.cur_pic_is_idr = p_hal->slice_long->idr_flag; + common->reg012.colmv_compress_en = (pp->frame_mbs_only_flag != 0) ? 1 : 0; + common->reg028.sw_poc_arb_flag = 0; + + /* caculate the yuv_frame_size */ + { + MppFrame mframe = NULL; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + + mpp_buf_slot_get_prop(frm_slots, pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (ver_virstride + 16) / 16, SZ_4K); + + common->reg012.fbc_e = 1; + common->reg018.y_hor_virstride = fbc_hdr_stride / 16; + common->reg019.uv_hor_virstride = fbc_hdr_stride / 16; + common->reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + common->reg012.fbc_e = 0; + common->reg018.y_hor_virstride = hor_virstride / 16; + common->reg019.uv_hor_virstride = hor_virstride / 16; + common->reg020_y_virstride.y_virstride = y_virstride / 16; + } + } + /* set current frame info */ + { + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + + regs->h264d_param.reg65.cur_top_poc = pp->CurrFieldOrderCnt[0]; + regs->h264d_param.reg66.cur_bot_poc = pp->CurrFieldOrderCnt[1]; + mpp_buf_slot_get_prop(frm_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + regs->common_addr.reg130_decout_base = fd; + + //colmv_cur_base + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, pp->CurrPic.Index7Bits); + regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + regs->common_addr.reg132_error_ref_base = fd; + /* + * poc_hight bit[0] : + * 0 -> top field or frame + * 1 -> bot field + */ + if (pp->field_pic_flag) + regs->h264d_highpoc.reg204.cur_poc_highbit = pp->CurrPic.AssociatedFlag; + else + regs->h264d_highpoc.reg204.cur_poc_highbit = 0; + } + /* set reference info */ + { + RK_S32 i = 0; + RK_S32 ref_index = -1; + RK_S32 near_index = -1; + MppBuffer mbuffer = NULL; + RK_U32 min_frame_num = 0; + MppFrame mframe = NULL; + + for (i = 0; i <= 15; i++) { + RK_U32 field_flag = (pp->RefPicFiledFlags >> i) & 0x01; + RK_U32 top_used = (pp->UsedForReferenceFlags >> (2 * i + 0)) & 0x01; + RK_U32 bot_used = (pp->UsedForReferenceFlags >> (2 * i + 1)) & 0x01; + + regs->h264d_param.reg67_98_ref_poc[2 * i] = pp->FieldOrderCntList[i][0]; + regs->h264d_param.reg67_98_ref_poc[2 * i + 1] = pp->FieldOrderCntList[i][1]; + SET_REF_INFO(regs->h264d_param, i, field, field_flag); + SET_REF_INFO(regs->h264d_param, i, topfield_used, top_used); + SET_REF_INFO(regs->h264d_param, i, botfield_used, bot_used); + SET_REF_INFO(regs->h264d_param, i, colmv_use_flag, (pp->RefPicColmvUsedFlags >> i) & 0x01); + + if (pp->RefFrameList[i].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[i].Index7Bits; + near_index = pp->RefFrameList[i].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + + if (pp->field_pic_flag) { + SET_POC_HIGNBIT_INFO(regs->h264d_highpoc, 2 * i, poc_highbit, 0); + SET_POC_HIGNBIT_INFO(regs->h264d_highpoc, 2 * i + 1, poc_highbit, 1); + } else if (ref_index == pp->CurrPic.Index7Bits) { + SET_POC_HIGNBIT_INFO(regs->h264d_highpoc, 2 * i, poc_highbit, 3); + SET_POC_HIGNBIT_INFO(regs->h264d_highpoc, 2 * i + 1, poc_highbit, 3); + } + + mpp_buf_slot_get_prop(frm_slots, ref_index, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(frm_slots, ref_index, SLOT_FRAME_PTR, &mframe); + + if (pp->FrameNumList[i] < pp->frame_num && + pp->FrameNumList[i] > min_frame_num && + (!mpp_frame_get_errinfo(mframe))) { + min_frame_num = pp->FrameNumList[i]; + regs->common_addr.reg132_error_ref_base = mpp_buffer_get_fd(mbuffer); + if (!pp->weighted_pred_flag) + common->reg021.error_intra_mode = 0; + } + + regs->h264d_addr.ref_base[i] = mpp_buffer_get_fd(mbuffer); + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->h264d_addr.colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + /* set input */ + { + MppBuffer mbuffer = NULL; + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + regs->common_addr.reg128_rlc_base = mpp_buffer_get_fd(mbuffer); + regs->common_addr.reg129_rlcwrite_base = regs->common_addr.reg128_rlc_base; + + regs->h264d_addr.cabactbl_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(p_hal->cfg->dev, 197, reg_ctx->offset_cabac); + } + + return MPP_OK; +} + +static MPP_RET init_common_regs(Vdpu34xH264dRegSet *regs) +{ + Vdpu34xRegCommon *common = ®s->common; + + common->reg009.dec_mode = 1; //!< h264 + common->reg015.rlc_mode = 0; + + common->reg011.buf_empty_en = 1; + common->reg011.dec_timeout_e = 1; + + common->reg010.dec_e = 1; + common->reg017.slice_num = 0x3fff; + + common->reg012.wait_reset_en = 1; + common->reg013.h26x_error_mode = 1; + common->reg013.colmv_error_mode = 1; + common->reg013.h26x_streamd_error_mode = 1; + common->reg021.error_deb_en = 1; + common->reg021.inter_error_prc_mode = 0; + common->reg021.error_intra_mode = 1; + + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) { + common->reg024.cabac_err_en_lowbits = 0; + common->reg025.cabac_err_en_highbits = 0; + common->reg026.swreg_block_gating_e = 0xfffef; + } else { + common->reg024.cabac_err_en_lowbits = 0xffffffff; + common->reg025.cabac_err_en_highbits = 0x3ff3ffff; + common->reg026.swreg_block_gating_e = 0xfffff; + } + common->reg026.reg_cfg_gating_en = 1; + common->reg032_timeout_threshold = 0x3ffff; + + common->reg011.dec_clkgate_e = 1; + common->reg011.dec_e_strmd_clkgate_dis = 0; + common->reg011.dec_timeout_e = 1; + + common->reg013.timeout_mode = 1; + + return MPP_OK; +} + +MPP_RET vdpu34x_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Vdpu3xxH264dRegCtx))); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_U32 max_cnt = (p_hal->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + + //!< malloc buffers + reg_ctx->spspps = mpp_calloc(RK_U8, VDPU34X_SPSPPS_UNIT_SIZE); + reg_ctx->rps = mpp_calloc(RK_U8, VDPU34X_RPS_SIZE); + reg_ctx->sclst = mpp_calloc(RK_U8, VDPU34X_SCALING_LIST_SIZE); + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, + VDPU34X_INFO_BUFFER_SIZE(max_cnt))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + reg_ctx->offset_cabac = VDPU34X_CABAC_TAB_OFFSET; + reg_ctx->offset_errinfo = VDPU34X_ERROR_INFO_OFFSET; + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu34xH264dRegSet, 1); + init_common_regs(reg_ctx->reg_buf[i].regs); + reg_ctx->offset_spspps[i] = VDPU34X_SPSPPS_OFFSET(i); + reg_ctx->offset_rps[i] = VDPU34X_RPS_OFFSET(i); + reg_ctx->offset_sclst[i] = VDPU34X_SCALING_LIST_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->rps_offset = reg_ctx->offset_rps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + //!< copy cabac table bytes + memcpy((char *)reg_ctx->bufs_ptr + reg_ctx->offset_cabac, + (void *)rkv_cabac_table, sizeof(rkv_cabac_table)); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + +__RETURN: + return MPP_OK; +__FAILED: + vdpu34x_h264d_deinit(hal); + + return ret; +} + +MPP_RET vdpu34x_h264d_deinit(void *hal) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + + mpp_buffer_put(reg_ctx->bufs); + + for (i = 0; i < loop; i++) + MPP_FREE(reg_ctx->reg_buf[i].regs); + + loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->rcb_buf) : 1; + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + } + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + MPP_FREE(reg_ctx->spspps); + MPP_FREE(reg_ctx->rps); + MPP_FREE(reg_ctx->sclst); + + MPP_FREE(p_hal->reg_ctx); + + return MPP_OK; +} + +static void h264d_refine_rcb_size(H264dHalCtx_t *p_hal, VdpuRcbInfo *rcb_info, + Vdpu34xH264dRegSet *regs, + RK_S32 width, RK_S32 height) +{ + RK_U32 rcb_bits = 0; + RK_U32 mbaff = p_hal->pp->MbaffFrameFlag; + RK_U32 bit_depth = p_hal->pp->bit_depth_luma_minus8 + 8; + RK_U32 chroma_format_idc = p_hal->pp->chroma_format_idc; + + width = MPP_ALIGN(width, H264_CTU_SIZE); + height = MPP_ALIGN(height, H264_CTU_SIZE); + /* RCB_STRMD_ROW */ + if (width > 4096) + rcb_bits = ((width + 15) / 16) * 154 * ((mbaff != 0) ? 2 : 1); + else + rcb_bits = 0; + rcb_info[RCB_STRMD_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_TRANSD_ROW */ + if (width > 8192) + rcb_bits = ((width - 8192 + 3) / 4) * 2; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_TRANSD_COL */ + if (height > 8192) + rcb_bits = ((height - 8192 + 3) / 4) * 2; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_COL].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_INTER_ROW */ + rcb_bits = width * 42; + rcb_info[RCB_INTER_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_INTER_COL */ + rcb_info[RCB_INTER_COL].size = 0; + /* RCB_INTRA_ROW */ + rcb_bits = width * 44; + rcb_info[RCB_INTRA_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_DBLK_ROW */ + rcb_bits = width * (2 + ((mbaff != 0) ? 12 : 6) * bit_depth); + rcb_info[RCB_DBLK_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_SAO_ROW */ + rcb_info[RCB_SAO_ROW].size = 0; + /* RCB_FBC_ROW */ + if (regs->common.reg012.fbc_e) { + rcb_bits = (chroma_format_idc > 1) ? (2 * width * bit_depth) : 0; + } else + rcb_bits = 0; + rcb_info[RCB_FBC_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_FILT_COL */ + rcb_info[RCB_FILT_COL].size = 0; +} + +static void hal_h264d_rcb_info_update(void *hal, Vdpu34xH264dRegSet *regs) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t*)hal; + RK_U32 mbaff = p_hal->pp->MbaffFrameFlag; + RK_U32 bit_depth = p_hal->pp->bit_depth_luma_minus8 + 8; + RK_U32 chroma_format_idc = p_hal->pp->chroma_format_idc; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_S32 width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + RK_S32 height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + + if ( ctx->bit_depth != bit_depth || + ctx->chroma_format_idc != chroma_format_idc || + ctx->mbaff != mbaff || + ctx->width != width || + ctx->height != height) { + RK_U32 i; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(ctx->reg_buf) : 1; + + ctx->rcb_buf_size = vdpu34x_get_rcb_buf_size(ctx->rcb_info, width, height); + h264d_refine_rcb_size(hal, ctx->rcb_info, regs, width, height); + for (i = 0; i < loop; i++) { + MppBuffer rcb_buf = ctx->rcb_buf[i]; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + ctx->rcb_buf[i] = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, ctx->rcb_buf_size); + ctx->rcb_buf[i] = rcb_buf; + } + + if (mbaff && 2 == chroma_format_idc) + mpp_err("Warning: rkv do not support H.264 4:2:2 MBAFF decoding."); + + ctx->bit_depth = bit_depth; + ctx->width = width; + ctx->height = height; + ctx->mbaff = mbaff; + ctx->chroma_format_idc = chroma_format_idc; + } +} + +static MPP_RET vdpu34x_h264d_setup_colmv_buf(void *hal, RK_U32 width, RK_U32 height) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + RK_U32 ctu_size = 16, colmv_size = 4, colmv_byte = 16; + RK_U32 colmv_compress = (p_hal->pp->frame_mbs_only_flag != 0) ? 1 : 0; + RK_S32 mv_size; + + mv_size = vdpu34x_get_colmv_size(width, height, ctu_size, colmv_byte, colmv_size, colmv_compress); + + /* if is field mode is enabled enlarge colmv buffer and disable colmv compression */ + if (!p_hal->pp->frame_mbs_only_flag) + mv_size *= 2; + + if (p_hal->cmv_bufs == NULL || p_hal->mv_size < mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_NOK; + } + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + + return MPP_OK; +} + +MPP_RET vdpu34x_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + RK_S32 width; + RK_S32 height; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu34xH264dRegSet *regs = ctx->regs; + MppHalCfg *cfg = p_hal->cfg; + + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { + if (!ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = ctx->reg_buf[i].regs; + + ctx->spspps_offset = ctx->offset_spspps[i]; + ctx->rps_offset = ctx->offset_rps[i]; + ctx->sclst_offset = ctx->offset_sclst[i]; + ctx->reg_buf[i].valid = 1; + break; + } + } + } + + hal_h264d_explain_input_buffer(hal, &task->dec); + width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + + if (vdpu34x_h264d_setup_colmv_buf(hal, width, height)) + goto __RETURN; + prepare_spspps(p_hal, (RK_U64 *)ctx->spspps, VDPU34X_SPSPPS_UNIT_SIZE / 8); + prepare_framerps(p_hal, (RK_U64 *)ctx->rps, VDPU34X_RPS_SIZE / 8); + prepare_scanlist(p_hal, ctx->sclst, VDPU34X_SCALING_LIST_SIZE); + set_registers(p_hal, regs, task); + + //!< copy datas + RK_U32 i = 0; + if (!p_hal->fast_mode && !p_hal->pp->spspps_update) { + RK_U32 offset = 0; + RK_U32 len = VDPU34X_SPS_PPS_LEN; //!< sps+pps data length + for (i = 0; i < 256; i++) { + offset = ctx->spspps_offset + (VDPU34X_SPSPPS_UNIT_SIZE * i) + len; + memcpy((char *)ctx->bufs_ptr + offset, (char *)ctx->spspps + len, VDPU34X_SPSPPS_UNIT_SIZE - len); + } + } else { + RK_U32 offset = 0; + for (i = 0; i < 256; i++) { + offset = ctx->spspps_offset + (VDPU34X_SPSPPS_UNIT_SIZE * i); + memcpy((char *)ctx->bufs_ptr + offset, (void *)ctx->spspps, VDPU34X_SPSPPS_UNIT_SIZE); + } + } + + regs->h264d_addr.pps_base = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 161, ctx->spspps_offset); + + memcpy((char *)ctx->bufs_ptr + ctx->rps_offset, (void *)ctx->rps, VDPU34X_RPS_SIZE); + regs->h264d_addr.rps_base = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 163, ctx->rps_offset); + + regs->common.reg012.scanlist_addr_valid_en = 1; + if (p_hal->pp->scaleing_list_enable_flag) { + memcpy((char *)ctx->bufs_ptr + ctx->sclst_offset, (void *)ctx->sclst, VDPU34X_SCALING_LIST_SIZE); + regs->h264d_addr.scanlist_addr = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 180, ctx->sclst_offset); + } else { + regs->h264d_addr.scanlist_addr = 0; + } + + hal_h264d_rcb_info_update(p_hal, regs); + vdpu34x_setup_rcb(®s->common_addr, cfg->dev, (p_hal->fast_mode != 0) ? + ctx->rcb_buf[task->dec.reg_index] : ctx->rcb_buf[0], + ctx->rcb_info); + vdpu34x_setup_statistic(®s->common, ®s->statistic); + mpp_buffer_sync_end(ctx->bufs); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu34x_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu34xH264dRegSet *regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + MppDev dev = p_hal->cfg->dev; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->common; + wr_cfg.size = sizeof(regs->common); + wr_cfg.offset = VDPU34X_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->h264d_param; + wr_cfg.size = sizeof(regs->h264d_param); + wr_cfg.offset = VDPU34X_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->common_addr; + wr_cfg.size = sizeof(regs->common_addr); + wr_cfg.offset = VDPU34X_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->h264d_addr; + wr_cfg.size = sizeof(regs->h264d_addr); + wr_cfg.offset = VDPU34X_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) { + wr_cfg.reg = ®s->h264d_highpoc; + wr_cfg.size = sizeof(regs->h264d_highpoc); + wr_cfg.offset = VDPU34X_OFF_POC_HIGHBIT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + } + + wr_cfg.reg = ®s->statistic; + wr_cfg.size = sizeof(regs->statistic); + wr_cfg.offset = VDPU34X_OFF_STATISTIC_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->irq_status; + rd_cfg.size = sizeof(regs->irq_status); + rd_cfg.offset = VDPU34X_OFF_INTERRUPT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu34x_set_rcbinfo(dev, reg_ctx->rcb_info); + + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu34x_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu34xH264dRegSet *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + + if (p_regs->irq_status.reg224.dec_error_sta || + (!p_regs->irq_status.reg224.dec_rdy_sta) || + p_regs->irq_status.reg224.buf_empty_sta || + p_regs->irq_status.reg226.strmd_error_status || + p_regs->irq_status.reg227.colmv_error_ref_picidx || + p_regs->irq_status.reg225.strmd_detect_error_flag) + param.hard_err = 1; + else + param.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + memset(&p_regs->irq_status.reg224, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) { + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + } + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu34x_h264d_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + RK_U32 imgwidth = mpp_frame_get_width((MppFrame)param); + RK_U32 imgheight = mpp_frame_get_height((MppFrame)param); + + mpp_log("control info: fmt %d, w %d, h %d\n", fmt, imgwidth, imgheight); + if (fmt == MPP_FMT_YUV422SP) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, (MppFrame)param, 16); + } else if (imgwidth > 1920 || imgheight > 1088) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + } + break; + } + case MPP_DEC_SET_OUTPUT_FORMAT: { + + } break; + default: + break; + } + +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_vdpu34x = { + .name = "h264d_vdpu34x", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = vdpu34x_h264d_init, + .deinit = vdpu3xx_h264d_deinit, + .reg_gen = vdpu34x_h264d_gen_regs, + .start = vdpu34x_h264d_start, + .wait = vdpu34x_h264d_wait, + .reset = vdpu_h264d_reset, + .flush = vdpu_h264d_flush, + .control = vdpu34x_h264d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_vdpu34x) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu34x.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu34x.h new file mode 100644 index 000000000..93a787f63 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu34x.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264D_VDPU34X_H +#define HAL_H264D_VDPU34X_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_vdpu34x; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU34X_H */ \ No newline at end of file diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c new file mode 100644 index 000000000..141f10728 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.c @@ -0,0 +1,1092 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264d_vdpu382" + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_bitput.h" +#include "mpp_service.h" + +#include "mpp_device.h" +#include "mpp_frame_impl.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_vdpu382.h" +#include "vdpu382_h264d.h" +#include "mpp_dec_cb_param.h" +#include "vdpu_com.h" +#include "hal_h264d_ctx.h" +#include "hal_h264d_com.h" + +/* Number registers for the decoder */ +#define DEC_VDPU382_REGISTERS 276 + +#define VDPU382_CABAC_TAB_SIZE (928*4 + 128) /* bytes */ +#define VDPU382_SPSPPS_UNIT_SIZE (48) /* bytes */ +#define VDPU382_SPSPPS_SIZE (256*48 + 128) /* bytes */ +#define VDPU382_RPS_SIZE (128 + 128 + 128) /* bytes */ +#define VDPU382_SCALING_LIST_SIZE (6*16+2*64 + 128) /* bytes */ +#define VDPU382_ERROR_INFO_SIZE (256*144*4) /* bytes */ + +#define VDPU382_CABAC_TAB_ALIGNED_SIZE (MPP_ALIGN(VDPU382_CABAC_TAB_SIZE, SZ_4K)) +#define VDPU382_ERROR_INFO_ALIGNED_SIZE (0) +#define VDPU382_SPSPPS_ALIGNED_SIZE (MPP_ALIGN(VDPU382_SPSPPS_SIZE, SZ_4K)) +#define VDPU382_RPS_ALIGNED_SIZE (MPP_ALIGN(VDPU382_RPS_SIZE, SZ_4K)) +#define VDPU382_SCALING_LIST_ALIGNED_SIZE (MPP_ALIGN(VDPU382_SCALING_LIST_SIZE, SZ_4K)) +#define VDPU382_STREAM_INFO_SET_SIZE (VDPU382_SPSPPS_ALIGNED_SIZE + \ + VDPU382_RPS_ALIGNED_SIZE + \ + VDPU382_SCALING_LIST_ALIGNED_SIZE) + +#define VDPU382_CABAC_TAB_OFFSET (0) +#define VDPU382_ERROR_INFO_OFFSET (VDPU382_CABAC_TAB_OFFSET + VDPU382_CABAC_TAB_ALIGNED_SIZE) +#define VDPU382_STREAM_INFO_OFFSET_BASE (VDPU382_ERROR_INFO_OFFSET + VDPU382_ERROR_INFO_ALIGNED_SIZE) +#define VDPU382_SPSPPS_OFFSET(pos) (VDPU382_STREAM_INFO_OFFSET_BASE + (VDPU382_STREAM_INFO_SET_SIZE * pos)) +#define VDPU382_RPS_OFFSET(pos) (VDPU382_SPSPPS_OFFSET(pos) + VDPU382_SPSPPS_ALIGNED_SIZE) +#define VDPU382_SCALING_LIST_OFFSET(pos) (VDPU382_RPS_OFFSET(pos) + VDPU382_RPS_ALIGNED_SIZE) +#define VDPU382_INFO_BUFFER_SIZE(cnt) (VDPU382_STREAM_INFO_OFFSET_BASE + (VDPU382_STREAM_INFO_SET_SIZE * cnt)) + +#define VDPU382_SPS_PPS_LEN (43) + +#define SET_REF_INFO(regs, index, field, value)\ + do{ \ + switch(index){\ + case 0: regs.reg99.ref0_##field = value; break;\ + case 1: regs.reg99.ref1_##field = value; break;\ + case 2: regs.reg99.ref2_##field = value; break;\ + case 3: regs.reg99.ref3_##field = value; break;\ + case 4: regs.reg100.ref4_##field = value; break;\ + case 5: regs.reg100.ref5_##field = value; break;\ + case 6: regs.reg100.ref6_##field = value; break;\ + case 7: regs.reg100.ref7_##field = value; break;\ + case 8: regs.reg101.ref8_##field = value; break;\ + case 9: regs.reg101.ref9_##field = value; break;\ + case 10: regs.reg101.ref10_##field = value; break;\ + case 11: regs.reg101.ref11_##field = value; break;\ + case 12: regs.reg102.ref12_##field = value; break;\ + case 13: regs.reg102.ref13_##field = value; break;\ + case 14: regs.reg102.ref14_##field = value; break;\ + case 15: regs.reg102.ref15_##field = value; break;\ + default: break;}\ + }while(0) + +#define SET_POC_HIGNBIT_INFO(regs, index, field, value)\ + do{ \ + switch(index){\ + case 0: regs.reg200.ref0_##field = value; break;\ + case 1: regs.reg200.ref1_##field = value; break;\ + case 2: regs.reg200.ref2_##field = value; break;\ + case 3: regs.reg200.ref3_##field = value; break;\ + case 4: regs.reg200.ref4_##field = value; break;\ + case 5: regs.reg200.ref5_##field = value; break;\ + case 6: regs.reg200.ref6_##field = value; break;\ + case 7: regs.reg200.ref7_##field = value; break;\ + case 8: regs.reg201.ref8_##field = value; break;\ + case 9: regs.reg201.ref9_##field = value; break;\ + case 10: regs.reg201.ref10_##field = value; break;\ + case 11: regs.reg201.ref11_##field = value; break;\ + case 12: regs.reg201.ref12_##field = value; break;\ + case 13: regs.reg201.ref13_##field = value; break;\ + case 14: regs.reg201.ref14_##field = value; break;\ + case 15: regs.reg201.ref15_##field = value; break;\ + case 16: regs.reg202.ref16_##field = value; break;\ + case 17: regs.reg202.ref17_##field = value; break;\ + case 18: regs.reg202.ref18_##field = value; break;\ + case 19: regs.reg202.ref19_##field = value; break;\ + case 20: regs.reg202.ref20_##field = value; break;\ + case 21: regs.reg202.ref21_##field = value; break;\ + case 22: regs.reg202.ref22_##field = value; break;\ + case 23: regs.reg202.ref23_##field = value; break;\ + case 24: regs.reg203.ref24_##field = value; break;\ + case 25: regs.reg203.ref25_##field = value; break;\ + case 26: regs.reg203.ref26_##field = value; break;\ + case 27: regs.reg203.ref27_##field = value; break;\ + case 28: regs.reg203.ref28_##field = value; break;\ + case 29: regs.reg203.ref29_##field = value; break;\ + case 30: regs.reg203.ref30_##field = value; break;\ + case 31: regs.reg203.ref31_##field = value; break;\ + default: break;}\ + }while(0) + +static MPP_RET prepare_spspps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0; + RK_S32 is_long_term = 0, voidx = 0; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + RK_U32 tmp = 0; + BitputCtx_t bp; + + mpp_set_bitput_ctx(&bp, data, len); + + if (!p_hal->fast_mode && !pp->spspps_update) { + bp.index = VDPU382_SPS_PPS_LEN >> 3; + bp.bitpos = (VDPU382_SPS_PPS_LEN & 0x7) << 3; + } else { + //!< sps syntax + mpp_put_bits(&bp, -1, 13); //!< sps_id 4bit && profile_idc 8bit && constraint_set3_flag 1bit + mpp_put_bits(&bp, pp->chroma_format_idc, 2); + mpp_put_bits(&bp, pp->bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, pp->bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, 0, 1); //!< qpprime_y_zero_transform_bypass_flag + mpp_put_bits(&bp, pp->log2_max_frame_num_minus4, 4); + mpp_put_bits(&bp, pp->num_ref_frames, 5); + mpp_put_bits(&bp, pp->pic_order_cnt_type, 2); + mpp_put_bits(&bp, pp->log2_max_pic_order_cnt_lsb_minus4, 4); + mpp_put_bits(&bp, pp->delta_pic_order_always_zero_flag, 1); + mpp_put_bits(&bp, (pp->wFrameWidthInMbsMinus1 + 1), 12); + mpp_put_bits(&bp, (pp->wFrameHeightInMbsMinus1 + 1), 12); + mpp_put_bits(&bp, pp->frame_mbs_only_flag, 1); + mpp_put_bits(&bp, pp->MbaffFrameFlag, 1); + mpp_put_bits(&bp, pp->direct_8x8_inference_flag, 1); + + mpp_put_bits(&bp, 1, 1); //!< mvc_extension_enable + mpp_put_bits(&bp, (pp->num_views_minus1 + 1), 2); + mpp_put_bits(&bp, pp->view_id[0], 10); + mpp_put_bits(&bp, pp->view_id[1], 10); + mpp_put_bits(&bp, pp->num_anchor_refs_l0[0], 1); + if (pp->num_anchor_refs_l0[0]) { + mpp_put_bits(&bp, pp->anchor_ref_l0[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); + } + mpp_put_bits(&bp, pp->num_anchor_refs_l1[0], 1); + if (pp->num_anchor_refs_l1[0]) { + mpp_put_bits(&bp, pp->anchor_ref_l1[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); //!< anchor_ref_l1 + } + mpp_put_bits(&bp, pp->num_non_anchor_refs_l0[0], 1); + if (pp->num_non_anchor_refs_l0[0]) { + mpp_put_bits(&bp, pp->non_anchor_ref_l0[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10); //!< non_anchor_ref_l0 + } + mpp_put_bits(&bp, pp->num_non_anchor_refs_l1[0], 1); + if (pp->num_non_anchor_refs_l1[0]) { + mpp_put_bits(&bp, pp->non_anchor_ref_l1[0][0], 10); + } else { + mpp_put_bits(&bp, 0, 10);//!< non_anchor_ref_l1 + } + mpp_put_align(&bp, 128, 0); + //!< pps syntax + mpp_put_bits(&bp, -1, 13); //!< pps_id 8bit && sps_id 5bit + mpp_put_bits(&bp, pp->entropy_coding_mode_flag, 1); + mpp_put_bits(&bp, pp->pic_order_present_flag, 1); + mpp_put_bits(&bp, pp->num_ref_idx_l0_active_minus1, 5); + mpp_put_bits(&bp, pp->num_ref_idx_l1_active_minus1, 5); + mpp_put_bits(&bp, pp->weighted_pred_flag, 1); + mpp_put_bits(&bp, pp->weighted_bipred_idc, 2); + mpp_put_bits(&bp, pp->pic_init_qp_minus26, 7); + mpp_put_bits(&bp, pp->pic_init_qs_minus26, 6); + mpp_put_bits(&bp, pp->chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->deblocking_filter_control_present_flag, 1); + mpp_put_bits(&bp, pp->constrained_intra_pred_flag, 1); + mpp_put_bits(&bp, pp->redundant_pic_cnt_present_flag, 1); + mpp_put_bits(&bp, pp->transform_8x8_mode_flag, 1); + mpp_put_bits(&bp, pp->second_chroma_qp_index_offset, 5); + mpp_put_bits(&bp, pp->scaleing_list_enable_flag, 1); + mpp_put_bits(&bp, 0, 32);// scanlist buffer has another addr + } + + //!< set dpb + for (i = 0; i < 16; i++) { + is_long_term = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefFrameList[i].AssociatedFlag : 0; + tmp |= (RK_U32)(is_long_term & 0x1) << i; + } + for (i = 0; i < 16; i++) { + voidx = (pp->RefFrameList[i].bPicEntry != 0xff) ? pp->RefPicLayerIdList[i] : 0; + tmp |= (RK_U32)(voidx & 0x1) << (i + 16); + } + mpp_put_bits(&bp, tmp, 32); + mpp_put_align(&bp, 64, 0); + + return MPP_OK; +} + +static MPP_RET prepare_framerps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0, j = 0; + RK_S32 dpb_idx = 0, voidx = 0; + RK_S32 dpb_valid = 0, bottom_flag = 0; + RK_U32 max_frame_num = 0; + RK_U16 frame_num_wrap = 0; + RK_U32 tmp = 0; + + BitputCtx_t bp; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + + mpp_set_bitput_ctx(&bp, data, len); + mpp_put_align(&bp, 128, 0); + max_frame_num = 1 << (pp->log2_max_frame_num_minus4 + 4); + for (i = 0; i < 16; i++) { + if ((pp->NonExistingFrameFlags >> i) & 0x01) { + frame_num_wrap = 0; + } else { + if (pp->RefFrameList[i].AssociatedFlag) { + frame_num_wrap = pp->FrameNumList[i]; + } else { + frame_num_wrap = (pp->FrameNumList[i] > pp->frame_num) ? + (pp->FrameNumList[i] - max_frame_num) : pp->FrameNumList[i]; + } + } + + mpp_put_bits(&bp, frame_num_wrap, 16); + } + + mpp_put_bits(&bp, 0, 16);//!< NULL + tmp = 0; + for (i = 0; i < 16; i++) { + tmp |= (RK_U32)pp->RefPicLayerIdList[i] << i; + } + mpp_put_bits(&bp, tmp, 16); + + for (i = 0; i < 32; i++) { + tmp = 0; + dpb_valid = (p_hal->slice_long[0].RefPicList[0][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + tmp |= (RK_U32)(dpb_idx | (dpb_valid << 4)) & 0x1f; + tmp |= (RK_U32)(bottom_flag & 0x1) << 5; + tmp |= (RK_U32)(voidx & 0x1) << 6; + mpp_put_bits(&bp, tmp, 7); + } + for (j = 1; j < 3; j++) { + for (i = 0; i < 32; i++) { + tmp = 0; + dpb_valid = (p_hal->slice_long[0].RefPicList[j][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + tmp |= (RK_U32)(dpb_idx | (dpb_valid << 4)) & 0x1f; + tmp |= (RK_U32)(bottom_flag & 0x1) << 5; + tmp |= (RK_U32)(voidx & 0x1) << 6; + mpp_put_bits(&bp, tmp, 7); + } + } + mpp_put_align(&bp, 128, 0); + + return MPP_OK; +} + +static MPP_RET prepare_scanlist(H264dHalCtx_t *p_hal, RK_U8 *data, RK_U32 len) +{ + RK_U32 i = 0, j = 0, n = 0; + + if (p_hal->pp->scaleing_list_enable_flag) { + for (i = 0; i < 6; i++) { //!< 4x4, 6 lists + for (j = 0; j < 16; j++) { + data[n++] = p_hal->qm->bScalingLists4x4[i][j]; + } + } + for (i = 0; i < 2; i++) { //!< 8x8, 2 lists + for (j = 0; j < 64; j++) { + data[n++] = p_hal->qm->bScalingLists8x8[i][j]; + } + } + } + mpp_assert(n <= len); + + return MPP_OK; +} + +static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu382H264dRegSet *regs, HalTaskInfo *task) +{ + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + MppHalCfg *cfg = p_hal->cfg; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + Vdpu382RegCommon *common = ®s->common; + HalBuf *mv_buf = NULL; + + // memset(regs, 0, sizeof(Vdpu382H264dRegSet)); + memset(®s->h264d_highpoc, 0, sizeof(regs->h264d_highpoc)); + common->reg016_str_len = p_hal->strm_len; + common->reg013.cur_pic_is_idr = p_hal->slice_long->idr_flag; + common->reg012.colmv_compress_en = + (cfg->hw_info && cfg->hw_info->cap_colmv_compress && pp->frame_mbs_only_flag) ? 1 : 0; + common->reg012.info_collect_en = 1; + common->reg013.h26x_error_mode = (ctx->err_ref_hack != 0) ? 0 : 1; + + //!< caculate the yuv_frame_size + { + MppFrame mframe = NULL; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (ver_virstride + 16) / 16, SZ_4K); + + common->reg012.fbc_e = 1; + common->reg018.y_hor_virstride = fbc_hdr_stride / 16; + common->reg019.uv_hor_virstride = fbc_hdr_stride / 16; + common->reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + common->reg012.fbc_e = 0; + common->reg018.y_hor_virstride = hor_virstride / 16; + common->reg019.uv_hor_virstride = hor_virstride / 16; + common->reg020_y_virstride.y_virstride = y_virstride / 16; + } + } + //!< set current + { + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + + regs->h264d_param.reg65.cur_top_poc = pp->CurrFieldOrderCnt[0]; + regs->h264d_param.reg66.cur_bot_poc = pp->CurrFieldOrderCnt[1]; + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + regs->common_addr.reg130_decout_base = fd; + + //colmv_cur_base + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, pp->CurrPic.Index7Bits); + regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + regs->common_addr.reg132_error_ref_base = fd; + if (pp->field_pic_flag) + regs->h264d_highpoc.reg204.cur_poc_highbit = 1 << pp->CurrPic.AssociatedFlag; // top:1 bot:2 + else + regs->h264d_highpoc.reg204.cur_poc_highbit = 0; // frame + } + //!< set reference + { + RK_S32 i = 0; + RK_S32 ref_index = -1; + RK_S32 near_index = -1; + MppBuffer mbuffer = NULL; + RK_U32 min_frame_num = 0; + MppFrame mframe = NULL; + + task->dec.flags.ref_miss = 0; + + for (i = 0; i <= 15; i++) { + RK_U32 field_flag = (pp->RefPicFiledFlags >> i) & 0x01; + RK_U32 top_used = (pp->UsedForReferenceFlags >> (2 * i + 0)) & 0x01; + RK_U32 bot_used = (pp->UsedForReferenceFlags >> (2 * i + 1)) & 0x01; + + regs->h264d_param.reg67_98_ref_poc[2 * i] = pp->FieldOrderCntList[i][0]; + regs->h264d_param.reg67_98_ref_poc[2 * i + 1] = pp->FieldOrderCntList[i][1]; + SET_REF_INFO(regs->h264d_param, i, field, field_flag); + SET_REF_INFO(regs->h264d_param, i, topfield_used, top_used); + SET_REF_INFO(regs->h264d_param, i, botfield_used, bot_used); + SET_REF_INFO(regs->h264d_param, i, colmv_use_flag, (pp->RefPicColmvUsedFlags >> i) & 0x01); + + if (pp->RefFrameList[i].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[i].Index7Bits; + near_index = pp->RefFrameList[i].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + task->dec.flags.ref_miss |= (1 << i); + } + /* mark 3 to differ from current frame */ + if (ref_index == pp->CurrPic.Index7Bits) { + SET_POC_HIGNBIT_INFO(regs->h264d_highpoc, 2 * i, poc_highbit, 3); + SET_POC_HIGNBIT_INFO(regs->h264d_highpoc, 2 * i + 1, poc_highbit, 3); + } + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_FRAME_PTR, &mframe); + + if (pp->FrameNumList[i] < pp->frame_num && + pp->FrameNumList[i] > min_frame_num && + (!mpp_frame_get_errinfo(mframe))) { + min_frame_num = pp->FrameNumList[i]; + regs->common_addr.reg132_error_ref_base = mpp_buffer_get_fd(mbuffer); + common->reg021.error_intra_mode = 0; + } + + RK_S32 fd = mpp_buffer_get_fd(mbuffer); + /* + * if ref is err frame, set fd = 0, + * in order for trigger pagefault if the cur frame use the err ref. + * This makes it possible to accurately identify whether an err ref + * frame is being used. + */ + if (ctx->err_ref_hack && mpp_frame_get_errinfo(mframe)) { + regs->h264d_param.reg67_98_ref_poc[2 * i] = 0; + regs->h264d_param.reg67_98_ref_poc[2 * i + 1] = 0; + fd = 0; + } + regs->h264d_addr.ref_base[i] = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->h264d_addr.colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + + } + } + { + MppBuffer mbuffer = NULL; + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + regs->common_addr.reg128_rlc_base = mpp_buffer_get_fd(mbuffer); + regs->common_addr.reg129_rlcwrite_base = regs->common_addr.reg128_rlc_base; + + regs->h264d_addr.cabactbl_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 197, reg_ctx->offset_cabac); + } + + return MPP_OK; +} + +static MPP_RET init_common_regs(Vdpu382H264dRegSet *regs) +{ + Vdpu382RegCommon *common = ®s->common; + Vdpu382H264dHighPoc_t *highpoc = ®s->h264d_highpoc; + + common->reg009.dec_mode = 1; //!< h264 + common->reg015.rlc_mode = 0; + + common->reg011.buf_empty_en = 1; + common->reg011.err_head_fill_e = 1; + common->reg011.err_colmv_fill_e = 1; + + common->reg010.dec_e = 1; + common->reg017.slice_num = 0x3fff; + + common->reg013.h26x_error_mode = 1; + common->reg013.strmd_zero_rm_en = 1; + + common->reg021.error_deb_en = 1; + common->reg021.inter_error_prc_mode = 0; + common->reg021.error_intra_mode = 1; + + common->reg024.cabac_err_en_lowbits = 0xffffffff; + common->reg025.cabac_err_en_highbits = 0x3ff3ffff; + + common->reg026.inter_auto_gating_e = 1; + common->reg026.filterd_auto_gating_e = 1; + common->reg026.strmd_auto_gating_e = 1; + common->reg026.mcp_auto_gating_e = 1; + common->reg026.busifd_auto_gating_e = 1; + common->reg026.dec_ctrl_auto_gating_e = 1; + common->reg026.intra_auto_gating_e = 1; + common->reg026.mc_auto_gating_e = 1; + common->reg026.transd_auto_gating_e = 1; + common->reg026.sram_auto_gating_e = 1; + common->reg026.cru_auto_gating_e = 1; + common->reg026.reg_cfg_gating_en = 1; + + common->reg032_timeout_threshold = 0x3ffff; + + common->reg011.dec_clkgate_e = 1; + + //highpoc_t205 + memset(&highpoc->reg205, 0, sizeof(RK_U32)); + + + return MPP_OK; +} + +MPP_RET vdpu382_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Vdpu3xxH264dRegCtx))); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_U32 max_cnt = (p_hal->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + + //!< malloc buffers + reg_ctx->spspps = mpp_calloc(RK_U8, VDPU382_SPSPPS_SIZE); + reg_ctx->rps = mpp_calloc(RK_U8, VDPU382_RPS_SIZE); + reg_ctx->sclst = mpp_calloc(RK_U8, VDPU382_SCALING_LIST_SIZE); + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, + VDPU382_INFO_BUFFER_SIZE(max_cnt))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + reg_ctx->offset_cabac = VDPU382_CABAC_TAB_OFFSET; + reg_ctx->offset_errinfo = VDPU382_ERROR_INFO_OFFSET; + reg_ctx->vdpu382_is_used = 1; + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_382_buf[i].regs = mpp_calloc(Vdpu382H264dRegSet, 1); + init_common_regs(reg_ctx->reg_382_buf[i].regs); + reg_ctx->offset_spspps[i] = VDPU382_SPSPPS_OFFSET(i); + reg_ctx->offset_rps[i] = VDPU382_RPS_OFFSET(i); + reg_ctx->offset_sclst[i] = VDPU382_SCALING_LIST_OFFSET(i); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_382_buf[0].regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->rps_offset = reg_ctx->offset_rps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + //!< copy cabac table bytes + memcpy((char *)reg_ctx->bufs_ptr + reg_ctx->offset_cabac, + (void *)rkv_cabac_table, sizeof(rkv_cabac_table)); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + { + /* check kernel support err ref hack process */ + const MppServiceCmdCap *cap = mpp_get_mpp_service_cmd_cap(); + + reg_ctx->err_ref_hack = cap->ctrl_cmd > MPP_CMD_SET_ERR_REF_HACK; + if (reg_ctx->err_ref_hack) + mpp_dev_ioctl(cfg->dev, MPP_DEV_SET_ERR_REF_HACK, ®_ctx->err_ref_hack); + } + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + +__RETURN: + return MPP_OK; +__FAILED: + vdpu3xx_h264d_deinit(hal); + + return ret; +} + +static void h264d_refine_rcb_size(H264dHalCtx_t *p_hal, VdpuRcbInfo *rcb_info, + Vdpu382H264dRegSet *regs, + RK_S32 width, RK_S32 height) +{ + RK_U32 rcb_bits = 0; + RK_U32 mbaff = p_hal->pp->MbaffFrameFlag; + RK_U32 bit_depth = p_hal->pp->bit_depth_luma_minus8 + 8; + RK_U32 chroma_format_idc = p_hal->pp->chroma_format_idc; + + width = MPP_ALIGN(width, H264_CTU_SIZE); + height = MPP_ALIGN(height, H264_CTU_SIZE); + + /* RCB_STRMD_ROW */ + if (width >= 4096) + rcb_bits = ((width + 15) / 16) * 154 * ((mbaff != 0) ? 2 : 1); + else + rcb_bits = 0; + rcb_info[RCB_STRMD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_ROW */ + if (width >= 8192) + rcb_bits = ((width - 8192 + 3) / 4) * 2; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_COL */ + rcb_info[RCB_TRANSD_COL].size = 0; + + /* RCB_INTER_ROW */ + rcb_bits = width * 42; + rcb_info[RCB_INTER_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_COL */ + rcb_info[RCB_INTER_COL].size = 0; + + /* RCB_INTRA_ROW */ + if (mbaff) + rcb_bits = width * 44; + else + rcb_bits = width * (((chroma_format_idc != 0) ? 1 : 0) + 1) * 11; + rcb_info[RCB_INTRA_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_DBLK_ROW */ + rcb_bits = width * (2 + ((mbaff != 0) ? 12 : 6) * bit_depth); + rcb_info[RCB_DBLK_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_SAO_ROW */ + rcb_info[RCB_SAO_ROW].size = 0; + + /* RCB_FBC_ROW */ + if (regs->common.reg012.fbc_e) { + rcb_bits = (chroma_format_idc > 1) ? (2 * width * bit_depth) : 0; + } else + rcb_bits = 0; + rcb_info[RCB_FBC_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FILT_COL */ + rcb_info[RCB_FILT_COL].size = 0; +} + +static void hal_h264d_rcb_info_update(void *hal, Vdpu382H264dRegSet *regs) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t*)hal; + RK_U32 mbaff = p_hal->pp->MbaffFrameFlag; + RK_U32 bit_depth = p_hal->pp->bit_depth_luma_minus8 + 8; + RK_U32 chroma_format_idc = p_hal->pp->chroma_format_idc; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_S32 width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + RK_S32 height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + + if ( ctx->bit_depth != bit_depth || + ctx->chroma_format_idc != chroma_format_idc || + ctx->mbaff != mbaff || + ctx->width != width || + ctx->height != height) { + RK_U32 i; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(ctx->reg_382_buf) : 1; + + ctx->rcb_buf_size = vdpu382_get_rcb_buf_size(ctx->rcb_info, width, height); + h264d_refine_rcb_size(hal, ctx->rcb_info, regs, width, height); + for (i = 0; i < loop; i++) { + MppBuffer rcb_buf = ctx->rcb_buf[i]; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + ctx->rcb_buf[i] = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, ctx->rcb_buf_size); + ctx->rcb_buf[i] = rcb_buf; + } + ctx->bit_depth = bit_depth; + ctx->width = width; + ctx->height = height; + ctx->mbaff = mbaff; + ctx->chroma_format_idc = chroma_format_idc; + } +} + +static MPP_RET vdpu382_h264d_setup_colmv_buf(void *hal) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + RK_S32 width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + RK_S32 height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + RK_U32 ctu_size = 16, colmv_size = 4, colmv_byte = 16; + RK_S32 mv_size; + + mv_size = vdpu382_get_colmv_size(width, height, ctu_size, colmv_byte, colmv_size, 1); + if (p_hal->cmv_bufs == NULL || p_hal->mv_size < mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_OK; + } + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + + return MPP_OK; +} + +MPP_RET vdpu382_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu382H264dRegSet *regs = ctx->regs; + MppHalCfg *cfg = p_hal->cfg; + + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + task->dec.reg_index = 0; + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_382_buf); i++) { + if (!ctx->reg_382_buf[i].valid) { + task->dec.reg_index = i; + regs = ctx->reg_382_buf[i].regs; + + ctx->spspps_offset = ctx->offset_spspps[i]; + ctx->rps_offset = ctx->offset_rps[i]; + ctx->sclst_offset = ctx->offset_sclst[i]; + ctx->reg_382_buf[i].valid = 1; + break; + } + } + } + + hal_h264d_explain_input_buffer(hal, &task->dec); + if (vdpu382_h264d_setup_colmv_buf(hal)) + goto __RETURN; + prepare_spspps(p_hal, (RK_U64 *)ctx->spspps, VDPU382_SPSPPS_UNIT_SIZE / 8); + prepare_framerps(p_hal, (RK_U64 *)ctx->rps, VDPU382_RPS_SIZE / 8); + prepare_scanlist(p_hal, ctx->sclst, VDPU382_SCALING_LIST_SIZE); + set_registers(p_hal, regs, task); + + //!< copy datas + RK_U32 i = 0; + if (!p_hal->fast_mode && !p_hal->pp->spspps_update) { + RK_U32 offset = 0; + RK_U32 len = VDPU382_SPS_PPS_LEN; //!< sps+pps data length + for (i = 0; i < 256; i++) { + offset = ctx->spspps_offset + (VDPU382_SPSPPS_UNIT_SIZE * i) + len; + memcpy((char *)ctx->bufs_ptr + offset, (char *)ctx->spspps + len, VDPU382_SPSPPS_UNIT_SIZE - len); + } + } else { + RK_U32 offset = 0; + for (i = 0; i < 256; i++) { + offset = ctx->spspps_offset + (VDPU382_SPSPPS_UNIT_SIZE * i); + memcpy((char *)ctx->bufs_ptr + offset, (void *)ctx->spspps, VDPU382_SPSPPS_UNIT_SIZE); + } + } + + regs->h264d_addr.pps_base = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 161, ctx->spspps_offset); + + memcpy((char *)ctx->bufs_ptr + ctx->rps_offset, (void *)ctx->rps, VDPU382_RPS_SIZE); + regs->h264d_addr.rps_base = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 163, ctx->rps_offset); + + regs->common.reg012.scanlist_addr_valid_en = 1; + if (p_hal->pp->scaleing_list_enable_flag) { + memcpy((char *)ctx->bufs_ptr + ctx->sclst_offset, (void *)ctx->sclst, VDPU382_SCALING_LIST_SIZE); + regs->h264d_addr.scanlist_addr = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 180, ctx->sclst_offset); + } else { + regs->h264d_addr.scanlist_addr = 0; + } + + hal_h264d_rcb_info_update(p_hal, regs); + vdpu382_setup_rcb(®s->common_addr, cfg->dev, (p_hal->fast_mode != 0) ? + ctx->rcb_buf[task->dec.reg_index] : ctx->rcb_buf[0], + ctx->rcb_info); + { + MppFrame mframe = NULL; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + + if (mpp_frame_get_thumbnail_en(mframe)) { + regs->h264d_addr.reg198_scale_down_luma_base = + regs->common_addr.reg130_decout_base; + regs->h264d_addr.reg199_scale_down_chorme_base = + regs->common_addr.reg130_decout_base; + vdpu382_setup_down_scale(mframe, cfg->dev, ®s->common); + } else { + regs->h264d_addr.reg198_scale_down_luma_base = 0; + regs->h264d_addr.reg199_scale_down_chorme_base = 0; + regs->common.reg012.scale_down_en = 0; + } + } + /* back up ref infos */ + { + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + RK_S32 index = task->dec.reg_index; + + memcpy(ctx->reg_382_buf[index].RefFrameList, pp->RefFrameList, sizeof(pp->RefFrameList)); + memcpy(ctx->reg_382_buf[index].RefPicList, p_hal->slice_long->RefPicList, + sizeof(p_hal->slice_long->RefPicList)); + } + vdpu382_setup_statistic(®s->common, ®s->statistic); + mpp_buffer_sync_end(ctx->bufs); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu382_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu382H264dRegSet *regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_382_buf[task->dec.reg_index].regs : + reg_ctx->regs; + MppDev dev = p_hal->cfg->dev; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->common; + wr_cfg.size = sizeof(regs->common); + wr_cfg.offset = VDPU382_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->h264d_param; + wr_cfg.size = sizeof(regs->h264d_param); + wr_cfg.offset = VDPU382_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->common_addr; + wr_cfg.size = sizeof(regs->common_addr); + wr_cfg.offset = VDPU382_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->h264d_addr; + wr_cfg.size = sizeof(regs->h264d_addr); + wr_cfg.offset = VDPU382_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->h264d_highpoc; + wr_cfg.size = sizeof(regs->h264d_highpoc); + wr_cfg.offset = VDPU382_OFF_POC_HIGHBIT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->statistic; + wr_cfg.size = sizeof(regs->statistic); + wr_cfg.offset = VDPU382_OFF_STATISTIC_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->irq_status; + rd_cfg.size = sizeof(regs->irq_status); + rd_cfg.offset = VDPU382_OFF_INTERRUPT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->statistic; + rd_cfg.size = sizeof(regs->statistic); + rd_cfg.offset = VDPU382_OFF_STATISTIC_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu382_set_rcbinfo(dev, reg_ctx->rcb_info); + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +RK_U32 vdpu382_h264_get_ref_used(void *hal, HalTaskInfo *task) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu382H264dRegSet *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_382_buf[task->dec.reg_index].regs : + reg_ctx->regs; + RK_U32 hw_ref_used; + RK_U32 ref_used = 0;; + + memcpy(&hw_ref_used, &p_regs->statistic.reg265, sizeof(RK_U32)); + + { + H264dVdpu382Buf *cur_buf = ®_ctx->reg_382_buf[task->dec.reg_index]; + RK_U32 i, j; + MppFrame cur_frame = NULL; + MppFrameStatus *status; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &cur_frame); + status = mpp_frame_get_status(cur_frame); + + if (status->is_intra) + return ref_used; + + for (i = 0; i < 32; i++) { + RK_U32 mask = 1 << i; + RK_U32 dpb_idx; + + if (!(hw_ref_used & mask)) + continue; + + if (status->is_b_frame) { + for (j = 1; j < 3; j++) { + dpb_idx = cur_buf->RefPicList[j][i].Index7Bits; + if (cur_buf->RefPicList[j][i].bPicEntry != 0xff && dpb_idx < 16) + ref_used |= (1 << dpb_idx); + } + } else { + j = 1; + dpb_idx = cur_buf->RefPicList[j][i].Index7Bits; + if (cur_buf->RefPicList[j][i].bPicEntry != 0xff && dpb_idx < 16) + ref_used |= (1 << dpb_idx); + } + } + } + H264D_LOG("hw_ref_used 0x%08x ref_used %08x\n", hw_ref_used, ref_used); + + return ref_used; +} + +MPP_RET vdpu382_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + RK_S32 index = task->dec.reg_index; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + RK_U32 hw_err = 0; + RK_U32 ref_used = 0; + + INP_CHECK(ret, NULL == p_hal); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu382H264dRegSet *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_382_buf[index].regs : + reg_ctx->regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + hw_err = p_regs->irq_status.reg224.dec_error_sta || + (!p_regs->irq_status.reg224.dec_rdy_sta) || + p_regs->irq_status.reg224.buf_empty_sta || + p_regs->irq_status.reg226.strmd_error_status || + p_regs->irq_status.reg227.colmv_error_ref_picidx || + p_regs->irq_status.reg226.strmd_detect_error_flag; + + /* the hw ref may not correct*/ + ref_used = (reg_ctx->err_ref_hack != 0) ? 0 : vdpu382_h264_get_ref_used(hal, task); + task->dec.flags.ref_info_valid = 1; + task->dec.flags.ref_used = ref_used; + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + param.hard_err = hw_err; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + + if (p_hal->fast_mode) + reg_ctx->reg_382_buf[index].valid = 0; + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu382_h264d_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + RK_U32 imgwidth = mpp_frame_get_width((MppFrame)param); + RK_U32 imgheight = mpp_frame_get_height((MppFrame)param); + + mpp_log("control info: fmt %d, w %d, h %d\n", fmt, imgwidth, imgheight); + if (fmt == MPP_FMT_YUV422SP) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, (MppFrame)param, 16); + } else if (imgwidth > 1920 || imgheight > 1088) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + } + break; + } + case MPP_DEC_SET_OUTPUT_FORMAT: { + + } break; + default: + break; + } + +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_vdpu382 = { + .name = "h264d_vdpu382", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = vdpu382_h264d_init, + .deinit = vdpu3xx_h264d_deinit, + .reg_gen = vdpu382_h264d_gen_regs, + .start = vdpu382_h264d_start, + .wait = vdpu382_h264d_wait, + .reset = vdpu_h264d_reset, + .flush = vdpu_h264d_flush, + .control = vdpu382_h264d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3562, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_vdpu382) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.h new file mode 100644 index 000000000..182f07227 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu382.h @@ -0,0 +1,32 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264D_VDPU382_H +#define HAL_H264D_VDPU382_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_vdpu382; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU382_H */ \ No newline at end of file diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu383.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu383.c new file mode 100644 index 000000000..0b8db1b00 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu383.c @@ -0,0 +1,723 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h264d_vdpu383" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_bitput.h" +#include "mpp_buffer_impl.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_vdpu383.h" +#include "mpp_dec_cb_param.h" +#include "vdpu_com.h" +#include "vdpu38x_com.h" +#include "vdpu383_com.h" +#include "hal_h264d_ctx.h" +#include "hal_h264d_com.h" + +/* Number registers for the decoder */ +#define DEC_VDPU383_REGISTERS 276 + +#define VDPU383_CABAC_TAB_SIZE (928*4 + 128) /* bytes */ +#define VDPU383_SPSPPS_SIZE (168 + 128) /* bytes */ +#define VDPU383_RPS_SIZE (128 + 128 + 128) /* bytes */ +#define VDPU383_SCALING_LIST_SIZE (6*16+2*64 + 128) /* bytes */ +#define VDPU383_ERROR_INFO_SIZE (256*144*4) /* bytes */ + +#define VDPU383_CABAC_TAB_ALIGNED_SIZE (MPP_ALIGN(VDPU383_CABAC_TAB_SIZE, SZ_4K)) +#define VDPU383_ERROR_INFO_ALIGNED_SIZE (0) +#define VDPU383_SPSPPS_ALIGNED_SIZE (MPP_ALIGN(VDPU383_SPSPPS_SIZE, SZ_4K)) +#define VDPU383_RPS_ALIGNED_SIZE (MPP_ALIGN(VDPU383_RPS_SIZE, SZ_4K)) +#define VDPU383_SCALING_LIST_ALIGNED_SIZE (MPP_ALIGN(VDPU383_SCALING_LIST_SIZE, SZ_4K)) +#define VDPU383_STREAM_INFO_SET_SIZE (VDPU383_SPSPPS_ALIGNED_SIZE + \ + VDPU383_RPS_ALIGNED_SIZE + \ + VDPU383_SCALING_LIST_ALIGNED_SIZE) + +#define VDPU383_CABAC_TAB_OFFSET (0) +#define VDPU383_ERROR_INFO_OFFSET (VDPU383_CABAC_TAB_OFFSET + VDPU383_CABAC_TAB_ALIGNED_SIZE) +#define VDPU383_STREAM_INFO_OFFSET_BASE (VDPU383_ERROR_INFO_OFFSET + VDPU383_ERROR_INFO_ALIGNED_SIZE) +#define VDPU383_SPSPPS_OFFSET(pos) (VDPU383_STREAM_INFO_OFFSET_BASE + (VDPU383_STREAM_INFO_SET_SIZE * pos)) +#define VDPU383_RPS_OFFSET(pos) (VDPU383_SPSPPS_OFFSET(pos) + VDPU383_SPSPPS_ALIGNED_SIZE) +#define VDPU383_SCALING_LIST_OFFSET(pos) (VDPU383_RPS_OFFSET(pos) + VDPU383_RPS_ALIGNED_SIZE) +#define VDPU383_INFO_BUFFER_SIZE(cnt) (VDPU383_STREAM_INFO_OFFSET_BASE + (VDPU383_STREAM_INFO_SET_SIZE * cnt)) + +#define VDPU383_SPS_PPS_LEN (MPP_ALIGN(1338, 128) / 8) // byte, 1338 bit + +static MPP_RET prepare_framerps(H264dHalCtx_t *p_hal, RK_U64 *data, RK_U32 len) +{ + RK_S32 i = 0, j = 0; + RK_S32 dpb_idx = 0, voidx = 0; + RK_S32 dpb_valid = 0, bottom_flag = 0; + RK_U32 max_frame_num = 0; + RK_U16 frame_num_wrap = 0; + RK_U32 tmp = 0; + + BitputCtx_t bp; + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + + mpp_set_bitput_ctx(&bp, data, len); + + max_frame_num = 1 << (pp->log2_max_frame_num_minus4 + 4); + for (i = 0; i < 16; i++) { + if ((pp->NonExistingFrameFlags >> i) & 0x01) { + frame_num_wrap = 0; + } else { + if (pp->RefFrameList[i].AssociatedFlag) { + frame_num_wrap = pp->FrameNumList[i]; + } else { + frame_num_wrap = (pp->FrameNumList[i] > pp->frame_num) ? + (pp->FrameNumList[i] - max_frame_num) : pp->FrameNumList[i]; + } + } + mpp_put_bits(&bp, frame_num_wrap, 16); + } + + tmp = 0; + for (i = 0; i < 16; i++) { + tmp |= (RK_U32)pp->RefPicLayerIdList[i] << (i + 16); + } + mpp_put_bits(&bp, tmp, 32); + + for (i = 0; i < 32; i++) { + tmp = 0; + dpb_valid = (p_hal->slice_long[0].RefPicList[0][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[0][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + + tmp |= (RK_U32)(dpb_idx | (dpb_valid << 4)) & 0x1f; + tmp |= (RK_U32)(bottom_flag & 0x1) << 5; + if (dpb_valid) + tmp |= (RK_U32)(voidx & 0x1) << 6; + mpp_put_bits(&bp, tmp, 7); + } + + for (j = 1; j < 3; j++) { + for (i = 0; i < 32; i++) { + tmp = 0; + dpb_valid = (p_hal->slice_long[0].RefPicList[j][i].bPicEntry == 0xff) ? 0 : 1; + dpb_idx = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].Index7Bits : 0; + bottom_flag = (dpb_valid != 0) ? p_hal->slice_long[0].RefPicList[j][i].AssociatedFlag : 0; + voidx = (dpb_valid != 0) ? pp->RefPicLayerIdList[dpb_idx] : 0; + tmp |= (RK_U32)(dpb_idx | (dpb_valid << 4)) & 0x1f; + tmp |= (RK_U32)(bottom_flag & 0x1) << 5; + if (dpb_valid) + tmp |= (RK_U32)(voidx & 0x1) << 6; + mpp_put_bits(&bp, tmp, 7); + } + } + + mpp_put_align(&bp, 128, 0); + +#ifdef DUMP_VDPU383_DATAS + { + char *cur_fname = "rps.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)bp.pbuf, 64 * bp.index + bp.bitpos, 64, 0); + } +#endif + + return MPP_OK; +} + +static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu383RegSet *regs, HalTaskInfo *task) +{ + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + HalBuf *mv_buf = NULL; + HalBuf *origin_buf = NULL; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + MppHalCfg *cfg = p_hal->cfg; + + // memset(regs, 0, sizeof(Vdpu383RegSet)); + regs->comm_paras.reg66_stream_len = p_hal->strm_len; + + //!< caculate the yuv_frame_size + { + MppFrame mframe = NULL; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + uv_virstride = hor_virstride * ver_virstride / 2; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset; + + fbd_offset = fbc_hdr_stride * MPP_ALIGN(ver_virstride, 64) / 16; + + regs->ctrl_regs.reg9.fbc_e = 1; + regs->comm_paras.reg68_hor_virstride = fbc_hdr_stride / 64; + regs->comm_addrs.reg193_fbc_payload_offset = fbd_offset; + } else if (MPP_FRAME_FMT_IS_TILE(mpp_frame_get_fmt(mframe))) { + regs->ctrl_regs.reg9.tile_e = 1; + regs->comm_paras.reg68_hor_virstride = hor_virstride * 6 / 16; + regs->comm_paras.reg70_y_virstride = (y_virstride + uv_virstride) / 16; + } else { + regs->ctrl_regs.reg9.fbc_e = 0; + regs->comm_paras.reg68_hor_virstride = hor_virstride / 16; + regs->comm_paras.reg69_raster_uv_hor_virstride = hor_virstride / 16; + regs->comm_paras.reg70_y_virstride = y_virstride / 16; + } + } + //!< set current + { + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + + //colmv_cur_base + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, pp->CurrPic.Index7Bits); + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + regs->comm_addrs.reg169_error_ref_base = fd; + } + //!< set reference + { + RK_S32 i = 0; + RK_S32 fd = -1; + RK_S32 ref_index = -1; + RK_S32 near_index = -1; + MppBuffer mbuffer = NULL; + RK_U32 min_frame_num = 0; + MppFrame mframe = NULL; + + for (i = 0; i < 15; i++) { + if (pp->RefFrameList[i].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[i].Index7Bits; + near_index = pp->RefFrameList[i].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + /* mark 3 to differ from current frame */ + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_FRAME_PTR, &mframe); + if (ctx->origin_bufs && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, ref_index); + mbuffer = origin_buf->buf[0]; + } + + if (pp->FrameNumList[i] < pp->frame_num && + pp->FrameNumList[i] > min_frame_num && + (!mpp_frame_get_errinfo(mframe))) { + min_frame_num = pp->FrameNumList[i]; + regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(mbuffer); + } + + fd = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg170_185_ref_base[i] = fd; + regs->comm_addrs.reg195_210_payload_st_ref_base[i] = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + + if (pp->RefFrameList[15].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[15].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + if (mpp_frame_get_thumbnail_en(mframe) == 2) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, ref_index); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + } + regs->comm_addrs.reg170_185_ref_base[15] = fd; + regs->comm_addrs.reg195_210_payload_st_ref_base[15] = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->comm_addrs.reg217_232_colmv_ref_base[15] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + { + MppBuffer mbuffer = NULL; + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(mbuffer); + // regs->comm_paras.reg65_strm_start_bit = 2 * 8; +#ifdef DUMP_VDPU383_DATAS + { + char *cur_fname = "stream_in.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * p_hal->strm_len, 128, 0); + } +#endif + + regs->comm_addrs.reg130_cabactbl_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 130, reg_ctx->offset_cabac); + } + + { + //scale down config + MppFrame mframe = NULL; + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + fd = mpp_buffer_get_fd(mbuffer); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + regs->comm_addrs.reg133_scale_down_base = fd; + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, pp->CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + regs->comm_addrs.reg169_error_ref_base = fd; + vdpu383_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, (void*)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + regs->comm_addrs.reg133_scale_down_base = fd; + vdpu383_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, (void*)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return MPP_OK; +} + +MPP_RET vdpu383_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Vdpu3xxH264dRegCtx))); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_U32 max_cnt = (p_hal->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + + //!< malloc buffers + reg_ctx->spspps = mpp_calloc(RK_U8, VDPU383_SPS_PPS_LEN); + reg_ctx->rps = mpp_calloc(RK_U8, VDPU383_RPS_SIZE); + reg_ctx->sclst = mpp_calloc(RK_U8, VDPU383_SCALING_LIST_SIZE); + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, + VDPU383_INFO_BUFFER_SIZE(max_cnt))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + reg_ctx->offset_cabac = VDPU383_CABAC_TAB_OFFSET; + reg_ctx->offset_errinfo = VDPU383_ERROR_INFO_OFFSET; + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu383RegSet, 1); + vdpu383_init_ctrl_regs(reg_ctx->reg_buf[i].regs, MPP_VIDEO_CodingAVC); + reg_ctx->offset_spspps[i] = VDPU383_SPSPPS_OFFSET(i); + reg_ctx->offset_rps[i] = VDPU383_RPS_OFFSET(i); + reg_ctx->offset_sclst[i] = VDPU383_SCALING_LIST_OFFSET(i); + } + + mpp_buffer_attach_dev(reg_ctx->bufs, cfg->dev); + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->rps_offset = reg_ctx->offset_rps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + //!< copy cabac table bytes + memcpy((char *)reg_ctx->bufs_ptr + reg_ctx->offset_cabac, + (void *)rkv_cabac_table, sizeof(rkv_cabac_table)); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu3xx_h264d_deinit(hal); + + return ret; +} + +static MPP_RET vdpu383_h264d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + RK_U32 fltd_row_append = ctx->pic_w > 4096 ? 256 * 16 * 8 : 864 * 16 * 8; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + /* + * For all spec, the hardware connects all in-tile rows of strmd to the on-tile. + * Therefore, only strmd on-tile needs to be configured, and there is no need to + * configure strmd in-tile. + * + * Versions with issues: rk3576(383), swan1126b (384a), shark/robin (384b). + */ + if (ctx->pic_w > 4096) + cur_bit_size = MPP_DIVUP(16, in_tl_row) * 154 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(4, in_tl_row) * 92 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(4, on_tl_row) * 92 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(16, in_tl_row) * (1.6 * bit_depth + 0.5) + * (( 6 + 3 * cur_uv_para) * (1 + ctx->mbaff_flag) + + 2 * cur_uv_para + 1.5); + cur_bit_size = cur_bit_size / 2 + fltd_row_append; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + // save space mode : half for RCB_FLTD_IN_ROW, half for RCB_FLTD_PROT_IN_ROW + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(16, on_tl_row) * (1.6 * bit_depth + 0.5) + * (( 6 + 3 * cur_uv_para) * (1 + ctx->mbaff_flag) + + 2 * cur_uv_para + 1.5); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +MPP_RET vdpu383_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu383RegSet *regs = ctx->regs; + MppHalCfg *cfg = p_hal->cfg; + RK_S32 width, height, mv_size; + MppFrame mframe; + + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + hal_h264d_explain_input_buffer(hal, &task->dec); + + width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + mv_size = MPP_ALIGN(width, 64) * MPP_ALIGN(height, 16); // 16 byte unit + + /* if is field mode is enabled enlarge colmv buffer and disable colmv compression */ + if (!p_hal->pp->frame_mbs_only_flag) + mv_size *= 2; + + if (p_hal->cmv_bufs == NULL || p_hal->mv_size < mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + goto __RETURN; + } + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + + mpp_buf_slot_get_prop(cfg->frame_slots, p_hal->pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, &ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { + if (!ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = ctx->reg_buf[i].regs; + + ctx->spspps_offset = ctx->offset_spspps[i]; + ctx->rps_offset = ctx->offset_rps[i]; + ctx->sclst_offset = ctx->offset_sclst[i]; + ctx->reg_buf[i].valid = 1; + break; + } + } + } + +#ifdef DUMP_VDPU383_DATAS + { + memset(dump_cur_dir, 0, sizeof(dump_cur_dir)); + sprintf(dump_cur_dir, "avc/Frame%04d", dump_cur_frame); + if (access(dump_cur_dir, 0)) { + if (mkdir(dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", dump_cur_dir); + } + dump_cur_frame++; + } +#endif + + vdpu38x_h264d_prepare_spspps(p_hal, (RK_U64 *)ctx->spspps, VDPU383_SPS_PPS_LEN / 8); + prepare_framerps(p_hal, (RK_U64 *)ctx->rps, VDPU383_RPS_SIZE / 8); + vdpu38x_h264d_prepare_scanlist(p_hal, ctx->sclst, VDPU383_SCALING_LIST_SIZE); + set_registers(p_hal, regs, task); + + //!< copy spspps datas + memcpy((char *)ctx->bufs_ptr + ctx->spspps_offset, (char *)ctx->spspps, VDPU383_SPS_PPS_LEN); + + regs->comm_addrs.reg131_gbl_base = ctx->bufs_fd; + regs->comm_paras.reg67_global_len = VDPU383_SPS_PPS_LEN / 16; // 128 bit as unit + mpp_dev_set_reg_offset(cfg->dev, 131, ctx->spspps_offset); + + memcpy((char *)ctx->bufs_ptr + ctx->rps_offset, (void *)ctx->rps, VDPU383_RPS_SIZE); + regs->comm_addrs.reg129_rps_base = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 129, ctx->rps_offset); + + if (p_hal->pp->scaleing_list_enable_flag) { + memcpy((char *)ctx->bufs_ptr + ctx->sclst_offset, (void *)ctx->sclst, VDPU383_SCALING_LIST_SIZE); + regs->comm_addrs.reg132_scanlist_addr = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 132, ctx->sclst_offset); + } else { + regs->comm_addrs.reg132_scanlist_addr = 0; + } + + vdpu38x_h264d_rcb_setup(p_hal, task, ®s->comm_addrs.rcb_regs, + vdpu383_h264d_rcb_calc); + vdpu383_setup_statistic(®s->ctrl_regs); + mpp_buffer_sync_end(ctx->bufs); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu383_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu383RegSet *regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + MppDev dev = p_hal->cfg->dev; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->ctrl_regs; + wr_cfg.size = sizeof(regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_paras; + wr_cfg.size = sizeof(regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_addrs; + wr_cfg.size = sizeof(regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->ctrl_regs.reg15; + rd_cfg.size = sizeof(regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu383_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu383RegSet *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + + if ((!p_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + p_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + p_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) + param.hard_err = 1; + else + param.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + memset(&p_regs->ctrl_regs.reg19, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) { + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + } + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_vdpu383 = { + .name = "h264d_vdpu383", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = vdpu383_h264d_init, + .deinit = vdpu3xx_h264d_deinit, + .reg_gen = vdpu383_h264d_gen_regs, + .start = vdpu383_h264d_start, + .wait = vdpu383_h264d_wait, + .reset = vdpu_h264d_reset, + .flush = vdpu_h264d_flush, + .control = vdpu38x_h264d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_vdpu383) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu383.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu383.h new file mode 100644 index 000000000..d636eea8c --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu383.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264D_VDPU383_H +#define HAL_H264D_VDPU383_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_vdpu383; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU34X_H */ \ No newline at end of file diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu384a.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384a.c new file mode 100644 index 000000000..b2259958e --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384a.c @@ -0,0 +1,638 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h264d_vdpu384a" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_bitput.h" +#include "mpp_buffer_impl.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_vdpu384a.h" +#include "mpp_dec_cb_param.h" +#include "vdpu_com.h" +#include "vdpu38x_com.h" +#include "vdpu384a_com.h" +#include "hal_h264d_ctx.h" +#include "hal_h264d_com.h" + +/* Number registers for the decoder */ +#define DEC_VDPU384A_REGISTERS 276 + +#define VDPU384A_SPSPPS_SIZE (MPP_ALIGN(2266 + 64, 128) / 8) /* byte, 2266 bit + Reserve 64 */ +#define VDPU384A_SCALING_LIST_SIZE (6*16+2*64 + 128) /* bytes */ +#define VDPU384A_ERROR_INFO_SIZE (256*144*4) /* bytes */ + +#define VDPU384A_ERROR_INFO_ALIGNED_SIZE (0) +#define VDPU384A_SPSPPS_ALIGNED_SIZE (MPP_ALIGN(VDPU384A_SPSPPS_SIZE, SZ_4K)) +#define VDPU384A_SCALING_LIST_ALIGNED_SIZE (MPP_ALIGN(VDPU384A_SCALING_LIST_SIZE, SZ_4K)) +#define VDPU384A_STREAM_INFO_SET_SIZE (VDPU384A_SPSPPS_ALIGNED_SIZE + \ + VDPU384A_SCALING_LIST_ALIGNED_SIZE) + +#define VDPU384A_ERROR_INFO_OFFSET (0) +#define VDPU384A_STREAM_INFO_OFFSET_BASE (VDPU384A_ERROR_INFO_OFFSET + VDPU384A_ERROR_INFO_ALIGNED_SIZE) +#define VDPU384A_SPSPPS_OFFSET(pos) (VDPU384A_STREAM_INFO_OFFSET_BASE + (VDPU384A_STREAM_INFO_SET_SIZE * pos)) +#define VDPU384A_SCALING_LIST_OFFSET(pos) (VDPU384A_SPSPPS_OFFSET(pos) + VDPU384A_SPSPPS_ALIGNED_SIZE) +#define VDPU384A_INFO_BUFFER_SIZE(cnt) (VDPU384A_STREAM_INFO_OFFSET_BASE + (VDPU384A_STREAM_INFO_SET_SIZE * cnt)) + +static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu384aRegSet *regs, HalTaskInfo *task) +{ + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + HalBuf *mv_buf = NULL; + HalBuf *origin_buf = NULL; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + MppHalCfg *cfg = p_hal->cfg; + + // memset(regs, 0, sizeof(Vdpu384aRegSet)); + regs->comm_paras.reg66_stream_len = p_hal->strm_len; + + //!< caculate the yuv_frame_size + { + MppFrame mframe = NULL; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + uv_virstride = hor_virstride * ver_virstride / 2; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset; + + fbd_offset = fbc_hdr_stride * MPP_ALIGN(ver_virstride, 64) / 16; + + regs->ctrl_regs.reg9.dpb_data_sel = 0; + regs->ctrl_regs.reg9.dpb_output_dis = 0; + regs->ctrl_regs.reg9.pp_m_output_mode = 0; + + regs->comm_paras.reg68_dpb_hor_virstride = fbc_hdr_stride / 64; + regs->comm_addrs.reg193_dpb_fbc64x4_payload_offset = fbd_offset; + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg68_dpb_hor_virstride; + } else if (MPP_FRAME_FMT_IS_TILE(mpp_frame_get_fmt(mframe))) { + regs->ctrl_regs.reg9.dpb_data_sel = 1; + regs->ctrl_regs.reg9.dpb_output_dis = 1; + regs->ctrl_regs.reg9.pp_m_output_mode = 2; + + regs->comm_paras.reg77_pp_m_hor_stride = hor_virstride * 6 / 16; + regs->comm_paras.reg79_pp_m_y_virstride = (y_virstride + uv_virstride) / 16; + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg77_pp_m_hor_stride; + } else { + regs->ctrl_regs.reg9.dpb_data_sel = 1; + regs->ctrl_regs.reg9.dpb_output_dis = 1; + regs->ctrl_regs.reg9.pp_m_output_mode = 1; + + regs->comm_paras.reg77_pp_m_hor_stride = hor_virstride / 16; + regs->comm_paras.reg78_pp_m_uv_hor_stride = hor_virstride / 16; + regs->comm_paras.reg79_pp_m_y_virstride = y_virstride / 16; + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg77_pp_m_hor_stride; + } + regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = regs->comm_paras.reg78_pp_m_uv_hor_stride; + regs->comm_paras.reg82_error_ref_virstride = regs->comm_paras.reg79_pp_m_y_virstride; + } + //!< set current + { + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + /* output rkfbc64 */ + // regs->comm_addrs.reg168_dpb_decout_base = fd; + /* output raster/tile4x4 */ + regs->comm_addrs.reg135_pp_m_decout_base = fd; + regs->comm_addrs.reg192_dpb_payload64x4_st_cur_base = fd; + + //colmv_cur_base + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, pp->CurrPic.Index7Bits); + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + regs->comm_addrs.reg169_error_ref_base = fd; + } + //!< set reference + { + RK_S32 i = 0; + RK_S32 fd = -1; + RK_S32 ref_index = -1; + RK_S32 near_index = -1; + MppBuffer mbuffer = NULL; + RK_U32 min_frame_num = 0; + MppFrame mframe = NULL; + + for (i = 0; i < 15; i++) { + if (pp->RefFrameList[i].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[i].Index7Bits; + near_index = pp->RefFrameList[i].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + /* mark 3 to differ from current frame */ + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_FRAME_PTR, &mframe); + if (ctx->origin_bufs && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, ref_index); + mbuffer = origin_buf->buf[0]; + } + + if (pp->FrameNumList[i] < pp->frame_num && + pp->FrameNumList[i] > min_frame_num && + (!mpp_frame_get_errinfo(mframe))) { + min_frame_num = pp->FrameNumList[i]; + regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(mbuffer); + } + + fd = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg170_185_ref_base[i] = fd; + regs->comm_addrs.reg195_210_payload_st_ref_base[i] = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + + if (pp->RefFrameList[15].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[15].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, ref_index, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + if (mpp_frame_get_thumbnail_en(mframe) == 2) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, ref_index); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + } + regs->comm_addrs.reg170_185_ref_base[15] = fd; + regs->comm_addrs.reg195_210_payload_st_ref_base[15] = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->comm_addrs.reg217_232_colmv_ref_base[15] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + { + MppBuffer mbuffer = NULL; + + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg129_stream_buf_st_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg130_stream_buf_end_base = mpp_buffer_get_fd(mbuffer); + mpp_dev_set_reg_offset(cfg->dev, 130, mpp_buffer_get_size(mbuffer)); + // regs->comm_paras.reg65_strm_start_bit = 2 * 8; +#ifdef DUMP_VDPU384A_DATAS + { + char *cur_fname = "stream_in.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * p_hal->strm_len, 128, 0); + } +#endif + } + + { + //scale down config + MppFrame mframe = NULL; + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, pp->CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + fd = mpp_buffer_get_fd(mbuffer); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + regs->comm_addrs.reg133_scale_down_base = fd; + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, pp->CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + /* output rkfbc64 */ + // regs->comm_addrs.reg168_dpb_decout_base = fd; + /* output raster/tile4x4 */ + regs->comm_addrs.reg135_pp_m_decout_base = fd; + regs->comm_addrs.reg192_dpb_payload64x4_st_cur_base = fd; + regs->comm_addrs.reg169_error_ref_base = fd; + vdpu384a_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, (void*)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + regs->comm_addrs.reg133_scale_down_base = fd; + vdpu384a_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, (void*)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return MPP_OK; +} + +MPP_RET vdpu384a_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Vdpu3xxH264dRegCtx))); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_U32 max_cnt = (p_hal->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + + //!< malloc buffers + reg_ctx->spspps = mpp_calloc(RK_U8, VDPU384A_SPSPPS_SIZE); + reg_ctx->sclst = mpp_calloc(RK_U8, VDPU384A_SCALING_LIST_SIZE); + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, + VDPU384A_INFO_BUFFER_SIZE(max_cnt))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + reg_ctx->offset_errinfo = VDPU384A_ERROR_INFO_OFFSET; + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu384aRegSet, 1); + vdpu384a_init_ctrl_regs(reg_ctx->reg_buf[i].regs, MPP_VIDEO_CodingAVC); + reg_ctx->offset_spspps[i] = VDPU384A_SPSPPS_OFFSET(i); + reg_ctx->offset_sclst[i] = VDPU384A_SCALING_LIST_OFFSET(i); + } + + mpp_buffer_attach_dev(reg_ctx->bufs, cfg->dev); + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv420); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu3xx_h264d_deinit(hal); + + return ret; +} + +static MPP_RET vdpu384a_h264d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + /* + * For all spec, the hardware connects all in-tile rows of strmd to the on-tile. + * Therefore, only strmd on-tile needs to be configured, and there is no need to + * configure strmd in-tile. + * + * Versions with issues: rk3576(383), swan1126b (384a), shark/robin (384b). + */ + if (ctx->pic_w > 4096) + cur_bit_size = MPP_DIVUP(16, in_tl_row) * 158 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(4, in_tl_row) * 92 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(4, on_tl_row) * 92 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(16, in_tl_row) * (1.2 * bit_depth + 0.5) + * (( 6 + 3 * cur_uv_para) * (1 + ctx->mbaff_flag) + + 2 * cur_uv_para + 1.5); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(16, on_tl_row) * (1.2 * bit_depth + 0.5) + * (( 6 + 3 * cur_uv_para) * (1 + ctx->mbaff_flag) + + 2 * cur_uv_para + 1.5); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +MPP_RET vdpu384a_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu384aRegSet *regs = ctx->regs; + MppHalCfg *cfg = p_hal->cfg; + RK_S32 width, height, mv_size; + MppFrame mframe; + + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + goto __RETURN; + } + hal_h264d_explain_input_buffer(hal, &task->dec); + + width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + mv_size = MPP_ALIGN(width, 64) * MPP_ALIGN(height, 16); // 16 byte unit + + /* if is field mode is enabled enlarge colmv buffer and disable colmv compression */ + if (!p_hal->pp->frame_mbs_only_flag) + mv_size *= 2; + + if (p_hal->cmv_bufs == NULL || p_hal->mv_size < mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + goto __RETURN; + } + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + + mpp_buf_slot_get_prop(cfg->frame_slots, p_hal->pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, &ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { + if (!ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = ctx->reg_buf[i].regs; + + ctx->spspps_offset = ctx->offset_spspps[i]; + ctx->sclst_offset = ctx->offset_sclst[i]; + ctx->reg_buf[i].valid = 1; + break; + } + } + } + +#ifdef DUMP_VDPU384A_DATAS + { + memset(dump_cur_dir, 0, sizeof(dump_cur_dir)); + sprintf(dump_cur_dir, "avc/Frame%04d", dump_cur_frame); + if (access(dump_cur_dir, 0)) { + if (mkdir(dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", dump_cur_dir); + } + dump_cur_frame++; + } +#endif + + vdpu38x_h264d_prepare_spspps(p_hal, (RK_U64 *)ctx->spspps, VDPU384A_SPSPPS_SIZE / 8); + vdpu38x_h264d_prepare_scanlist(p_hal, ctx->sclst, VDPU384A_SCALING_LIST_SIZE); + set_registers(p_hal, regs, task); + + //!< copy spspps datas + memcpy((char *)ctx->bufs_ptr + ctx->spspps_offset, (char *)ctx->spspps, VDPU384A_SPSPPS_SIZE); + + regs->comm_addrs.reg131_gbl_base = ctx->bufs_fd; + regs->comm_paras.reg67_global_len = VDPU384A_SPSPPS_SIZE / 16; // 128 bit as unit + mpp_dev_set_reg_offset(cfg->dev, 131, ctx->spspps_offset); + + if (p_hal->pp->scaleing_list_enable_flag) { + memcpy((char *)ctx->bufs_ptr + ctx->sclst_offset, (void *)ctx->sclst, VDPU384A_SCALING_LIST_SIZE); + regs->comm_addrs.reg132_scanlist_addr = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 132, ctx->sclst_offset); + } else { + regs->comm_addrs.reg132_scanlist_addr = 0; + } + + vdpu38x_h264d_rcb_setup(p_hal, task, ®s->comm_addrs.rcb_regs, + vdpu384a_h264d_rcb_calc); + vdpu384a_setup_statistic(®s->ctrl_regs); + mpp_buffer_sync_end(ctx->bufs); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu384a_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu384aRegSet *regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + MppDev dev = p_hal->cfg->dev; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->ctrl_regs; + wr_cfg.size = sizeof(regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_paras; + wr_cfg.size = sizeof(regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_addrs; + wr_cfg.size = sizeof(regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->ctrl_regs.reg15; + rd_cfg.size = sizeof(regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu384a_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu384aRegSet *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + + if ((!p_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + p_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + p_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) + param.hard_err = 1; + else + param.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + memset(&p_regs->ctrl_regs.reg19, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) { + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + } + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_vdpu384a = { + .name = "h264d_vdpu384a", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = vdpu384a_h264d_init, + .deinit = vdpu3xx_h264d_deinit, + .reg_gen = vdpu384a_h264d_gen_regs, + .start = vdpu384a_h264d_start, + .wait = vdpu384a_h264d_wait, + .reset = vdpu_h264d_reset, + .flush = vdpu_h264d_flush, + .control = vdpu38x_h264d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RV1126B, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_vdpu384a) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu384a.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384a.h new file mode 100644 index 000000000..2c879d298 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384a.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264D_VDPU384A_H +#define HAL_H264D_VDPU384A_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_vdpu384a; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU384A_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu384b.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384b.c new file mode 100644 index 000000000..7a6aa26ed --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384b.c @@ -0,0 +1,642 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h264d_vdpu384b" + +#include + +#include "mpp_buffer_impl.h" +#include "mpp_dec_cb_param.h" + +#include "hal_h264d_global.h" +#include "hal_h264d_ctx.h" +#include "hal_h264d_com.h" +#include "vdpu38x_com.h" + +/* Number registers for the decoder */ +#define DEC_VDPU384B_REGISTERS 276 + +#define VDPU384B_SPSPPS_SIZE (MPP_ALIGN(2266 + 64, 128) / 8) /* byte, 2266 bit + Reserve 64 */ +#define VDPU384B_SCALING_LIST_SIZE (6*16+2*64 + 128) /* bytes */ +#define VDPU384B_ERROR_INFO_SIZE (256*144*4) /* bytes */ + +#define VDPU384B_ERROR_INFO_ALIGNED_SIZE (0) +#define VDPU384B_SPSPPS_ALIGNED_SIZE (MPP_ALIGN(VDPU384B_SPSPPS_SIZE, SZ_4K)) +#define VDPU384B_SCALING_LIST_ALIGNED_SIZE (MPP_ALIGN(VDPU384B_SCALING_LIST_SIZE, SZ_4K)) +#define VDPU384B_STREAM_INFO_SET_SIZE (VDPU384B_SPSPPS_ALIGNED_SIZE + \ + VDPU384B_SCALING_LIST_ALIGNED_SIZE) + +#define VDPU384B_ERROR_INFO_OFFSET (0) +#define VDPU384B_STREAM_INFO_OFFSET_BASE (VDPU384B_ERROR_INFO_OFFSET + VDPU384B_ERROR_INFO_ALIGNED_SIZE) +#define VDPU384B_SPSPPS_OFFSET(pos) (VDPU384B_STREAM_INFO_OFFSET_BASE + (VDPU384B_STREAM_INFO_SET_SIZE * pos)) +#define VDPU384B_SCALING_LIST_OFFSET(pos) (VDPU384B_SPSPPS_OFFSET(pos) + VDPU384B_SPSPPS_ALIGNED_SIZE) +#define VDPU384B_INFO_BUFFER_SIZE(cnt) (VDPU384B_STREAM_INFO_OFFSET_BASE + (VDPU384B_STREAM_INFO_SET_SIZE * cnt)) + +static MPP_RET set_registers(H264dHalCtx_t *p_hal, Vdpu38xRegSet *regs, HalTaskInfo *task) +{ + DXVA_PicParams_H264_MVC *pp = p_hal->pp; + HalBuf *mv_buf = NULL; + HalBuf *origin_buf = NULL; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + MppBufSlots frm_slots = p_hal->cfg->frame_slots; + + // memset(regs, 0, sizeof(Vdpu38xRegSet)); + regs->comm_paras.reg66_stream_len = p_hal->strm_len; + + //!< caculate the yuv_frame_size + { + MppFrame mframe = NULL; + MppFrameFormat fmt; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + RK_U32 fbc_head_stride = 0; + RK_U32 fbc_pld_stride = 0; + RK_U32 fbc_offset = 0; + RK_U32 tile4x4_coeff = 0; + + mpp_buf_slot_get_prop(frm_slots, pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + fmt = mpp_frame_get_fmt(mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + y_virstride = hor_virstride * ver_virstride; + uv_virstride = hor_virstride * ver_virstride / 2; + + if (MPP_FRAME_FMT_IS_AFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 3; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_RKFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 2; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_TILE(fmt)) { + if (vdpu38x_get_tile4x4_h_stride_coeff(fmt, &tile4x4_coeff)) { + mpp_err("get tile 4x4 coeff failed\n"); + return MPP_NOK; + } + regs->ctrl_regs.reg9.pp_output_mode = 1; + regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride * tile4x4_coeff / 16; + regs->comm_paras.reg70_pp_m_y_virstride = (y_virstride + uv_virstride) / 16; + } else { + regs->ctrl_regs.reg9.pp_output_mode = 0; + regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride / 16; + regs->comm_paras.reg69_pp_m_uv_hor_stride = hor_virstride / 16; + regs->comm_paras.reg70_pp_m_y_virstride = y_virstride / 16; + } + /* error */ + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg68_pp_m_hor_stride; + regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = regs->comm_paras.reg69_pp_m_uv_hor_stride; + regs->comm_paras.reg82_error_ref_virstride = regs->comm_paras.reg70_pp_m_y_virstride; + } + //!< set current + { + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + + mpp_buf_slot_get_prop(frm_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + + //colmv_cur_base + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, pp->CurrPic.Index7Bits); + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + regs->comm_addrs.reg169_error_ref_base = fd; + } + //!< set reference + { + RK_S32 i = 0; + RK_S32 fd = -1; + RK_S32 ref_index = -1; + RK_S32 near_index = -1; + MppBuffer mbuffer = NULL; + RK_U32 min_frame_num = 0; + MppFrame mframe = NULL; + + for (i = 0; i < 15; i++) { + if (pp->RefFrameList[i].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[i].Index7Bits; + near_index = pp->RefFrameList[i].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + /* mark 3 to differ from current frame */ + mpp_buf_slot_get_prop(frm_slots, ref_index, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(frm_slots, ref_index, SLOT_FRAME_PTR, &mframe); + if (ctx->origin_bufs && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, ref_index); + mbuffer = origin_buf->buf[0]; + } + + if (pp->FrameNumList[i] < pp->frame_num && + pp->FrameNumList[i] > min_frame_num && + (!mpp_frame_get_errinfo(mframe))) { + min_frame_num = pp->FrameNumList[i]; + regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(mbuffer); + } + + fd = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg170_185_ref_base[i] = fd; + regs->comm_addrs.reg195_210_payload_st_ref_base[i] = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + + if (pp->RefFrameList[15].bPicEntry != 0xff) { + ref_index = pp->RefFrameList[15].Index7Bits; + } else { + ref_index = (near_index < 0) ? pp->CurrPic.Index7Bits : near_index; + } + + mpp_buf_slot_get_prop(frm_slots, ref_index, SLOT_BUFFER, &mbuffer); + fd = mpp_buffer_get_fd(mbuffer); + if (mpp_frame_get_thumbnail_en(mframe) == 2) { + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, ref_index); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + } + regs->comm_addrs.reg170_185_ref_base[15] = fd; + regs->comm_addrs.reg195_210_payload_st_ref_base[15] = fd; + mv_buf = hal_bufs_get_buf(p_hal->cmv_bufs, ref_index); + regs->comm_addrs.reg217_232_colmv_ref_base[15] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + { + MppBuffer mbuffer = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &mbuffer); + regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg129_stream_buf_st_base = mpp_buffer_get_fd(mbuffer); + regs->comm_addrs.reg130_stream_buf_end_base = mpp_buffer_get_fd(mbuffer); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 130, mpp_buffer_get_size(mbuffer)); + // regs->comm_paras.reg65_strm_start_bit = 2 * 8; +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "stream_in.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mbuffer), + 8 * p_hal->strm_len, 128, 0, 0); + } +#endif + } + + { + //scale down config + MppFrame mframe = NULL; + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(frm_slots, pp->CurrPic.Index7Bits, SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(frm_slots, pp->CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + fd = mpp_buffer_get_fd(mbuffer); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + regs->comm_addrs.reg133_scale_down_base = fd; + origin_buf = hal_bufs_get_buf(ctx->origin_bufs, pp->CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + regs->comm_addrs.reg169_error_ref_base = fd; + vdpu38x_setup_down_scale(mframe, p_hal->cfg->dev, ®s->ctrl_regs, (void*)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + regs->comm_addrs.reg133_scale_down_base = fd; + vdpu38x_setup_down_scale(mframe, p_hal->cfg->dev, ®s->ctrl_regs, (void*)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return MPP_OK; +} + +MPP_RET vdpu384b_h264d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + mpp_env_get_u32("hal_h264d_debug", &hal_h264d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + cfg->support_fast_mode = 1; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(Vdpu3xxH264dRegCtx))); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + RK_U32 max_cnt = p_hal->fast_mode ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + + //!< malloc buffers + reg_ctx->spspps = mpp_calloc(RK_U8, VDPU384B_SPSPPS_SIZE); + reg_ctx->sclst = mpp_calloc(RK_U8, VDPU384B_SCALING_LIST_SIZE); + FUN_CHECK(ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, + VDPU384B_INFO_BUFFER_SIZE(max_cnt))); + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->bufs_ptr = mpp_buffer_get_ptr(reg_ctx->bufs); + reg_ctx->offset_errinfo = VDPU384B_ERROR_INFO_OFFSET; + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(Vdpu38xRegSet, 1); + vdpu384b_init_ctrl_regs(reg_ctx->reg_buf[i].regs, MPP_VIDEO_CodingAVC); + reg_ctx->offset_spspps[i] = VDPU384B_SPSPPS_OFFSET(i); + reg_ctx->offset_sclst[i] = VDPU384B_SCALING_LIST_OFFSET(i); + } + + mpp_buffer_attach_dev(reg_ctx->bufs, cfg->dev); + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv420); + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu3xx_h264d_deinit(hal); + + return ret; +} + +static MPP_RET vdpu384b_h264d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + /* + * For all spec, the hardware connects all in-tile rows of strmd to the on-tile. + * Therefore, only strmd on-tile needs to be configured, and there is no need to + * configure strmd in-tile. + * + * Versions with issues: rk3576(383), swan1126b (384a), shark/robin (384b). + */ + if (ctx->pic_w > 4096) + cur_bit_size = MPP_DIVUP(16, in_tl_row) * 158 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(4, in_tl_row) * 92 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(4, on_tl_row) * 92 * (1 + ctx->mbaff_flag); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(16, in_tl_row) * (1.2 * bit_depth + 0.5) + * (( 6 + 3 * cur_uv_para) * (1 + ctx->mbaff_flag) + + 2 * cur_uv_para + 1.5); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(16, on_tl_row) * (1.2 * bit_depth + 0.5) + * (( 6 + 3 * cur_uv_para) * (1 + ctx->mbaff_flag) + + 2 * cur_uv_para + 1.5); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +MPP_RET vdpu384b_h264d_gen_regs(void *hal, HalTaskInfo *task) +{ + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + Vdpu3xxH264dRegCtx *ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu38xRegSet *regs = ctx->regs; + MppHalCfg *cfg = p_hal->cfg; + MppFrame mframe; + RK_S32 width, height, mv_size; + MPP_RET ret = MPP_ERR_UNKNOW; + + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + goto __RETURN; + } + hal_h264d_explain_input_buffer(hal, &task->dec); + + width = MPP_ALIGN((p_hal->pp->wFrameWidthInMbsMinus1 + 1) << 4, 64); + height = MPP_ALIGN((p_hal->pp->wFrameHeightInMbsMinus1 + 1) << 4, 64); + mv_size = MPP_ALIGN(width, 64) * MPP_ALIGN(height, 16); // 16 byte unit + + /* if is field mode is enabled enlarge colmv buffer and disable colmv compression */ + if (!p_hal->pp->frame_mbs_only_flag) + mv_size *= 2; + + if (p_hal->cmv_bufs == NULL || p_hal->mv_size < mv_size) { + size_t size = mv_size; + + if (p_hal->cmv_bufs) { + hal_bufs_deinit(p_hal->cmv_bufs); + p_hal->cmv_bufs = NULL; + } + + hal_bufs_init(&p_hal->cmv_bufs); + if (p_hal->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + goto __RETURN; + } + p_hal->mv_size = mv_size; + p_hal->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(p_hal->cmv_bufs, p_hal->mv_count, 1, &size); + } + + mpp_buf_slot_get_prop(cfg->frame_slots, p_hal->pp->CurrPic.Index7Bits, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, &ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + if (p_hal->fast_mode) { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { + if (!ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + regs = ctx->reg_buf[i].regs; + + ctx->spspps_offset = ctx->offset_spspps[i]; + ctx->sclst_offset = ctx->offset_sclst[i]; + ctx->reg_buf[i].valid = 1; + break; + } + } + } + +#ifdef DUMP_VDPU38X_DATAS + { + memset(vdpu38x_dump_cur_dir, 0, sizeof(vdpu38x_dump_cur_dir)); + sprintf(vdpu38x_dump_cur_dir, "avc/Frame%04d", vdpu38x_dump_cur_frm); + if (access(vdpu38x_dump_cur_dir, 0)) { + if (mkdir(vdpu38x_dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", vdpu38x_dump_cur_dir); + } + vdpu38x_dump_cur_frm++; + } +#endif + + vdpu38x_h264d_prepare_spspps(p_hal, (RK_U64 *)ctx->spspps, VDPU384B_SPSPPS_SIZE / 8); + vdpu38x_h264d_prepare_scanlist(p_hal, ctx->sclst, VDPU384B_SCALING_LIST_SIZE); + set_registers(p_hal, regs, task); + + //!< copy spspps datas + memcpy((char *)ctx->bufs_ptr + ctx->spspps_offset, (char *)ctx->spspps, VDPU384B_SPSPPS_SIZE); + + regs->comm_addrs.reg131_gbl_base = ctx->bufs_fd; + regs->comm_paras.reg67_global_len = VDPU384B_SPSPPS_SIZE / 16; // 128 bit as unit + mpp_dev_set_reg_offset(cfg->dev, 131, ctx->spspps_offset); + + if (p_hal->pp->scaleing_list_enable_flag) { + memcpy((char *)ctx->bufs_ptr + ctx->sclst_offset, (void *)ctx->sclst, VDPU384B_SCALING_LIST_SIZE); + regs->comm_addrs.reg132_scanlist_addr = ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 132, ctx->sclst_offset); + } else { + regs->comm_addrs.reg132_scanlist_addr = 0; + } + + vdpu38x_h264d_rcb_setup(p_hal, task, ®s->comm_addrs.rcb_regs, vdpu384b_h264d_rcb_calc); + vdpu38x_setup_statistic(®s->ctrl_regs); + mpp_buffer_sync_end(ctx->bufs); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu384b_h264d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + INP_CHECK(ret, NULL == p_hal); + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __RETURN; + } + + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu38xRegSet *regs = p_hal->fast_mode ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + MppDev dev = p_hal->cfg->dev; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->ctrl_regs; + wr_cfg.size = sizeof(regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_paras; + wr_cfg.size = sizeof(regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->comm_addrs; + wr_cfg.size = sizeof(regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->ctrl_regs.reg15; + rd_cfg.size = sizeof(regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + if (hal_h264d_debug & H264D_DBG_REG) { + rd_cfg.reg = ®s->statistic_regs; + rd_cfg.size = sizeof(regs->statistic_regs); + rd_cfg.offset = VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu384b_h264d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + H264dHalCtx_t *p_hal = (H264dHalCtx_t *)hal; + + INP_CHECK(ret, NULL == p_hal); + Vdpu3xxH264dRegCtx *reg_ctx = (Vdpu3xxH264dRegCtx *)p_hal->reg_ctx; + Vdpu38xRegSet *p_regs = p_hal->fast_mode ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !p_hal->cfg->cfg->base.disable_error)) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)p_regs; + + if ((!p_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + p_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + p_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + p_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + p_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) + param.hard_err = 1; + else + param.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, ¶m); + } + if (hal_h264d_debug & H264D_DBG_REG) { + mpp_assert(p_regs->statistic_regs.reg312.rcb_rd_sum_chk == + p_regs->statistic_regs.reg312.rcb_wr_sum_chk); + } + memset(&p_regs->ctrl_regs.reg19, 0, sizeof(RK_U32)); + if (p_hal->fast_mode) { + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + } + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_h264d_vdpu384b = { + .name = "h264d_vdpu384b", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(H264dHalCtx_t), + .flag = 0, + .init = vdpu384b_h264d_init, + .deinit = vdpu3xx_h264d_deinit, + .reg_gen = vdpu384b_h264d_gen_regs, + .start = vdpu384b_h264d_start, + .wait = vdpu384b_h264d_wait, + .reset = vdpu_h264d_reset, + .flush = vdpu_h264d_flush, + .control = vdpu38x_h264d_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h264d_vdpu384b) diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu384b.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384b.h new file mode 100644 index 000000000..e2dcc5d28 --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu384b.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264D_VDPU384B_H +#define HAL_H264D_VDPU384B_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h264d_vdpu384b; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU384B_H */ diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu_com.c b/mpp/hal/rkdec/h264d/hal_h264d_vdpu_com.c new file mode 100644 index 000000000..0ac2e826e --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu_com.c @@ -0,0 +1,513 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODEUL_TAG "hal_h264d_vdpu_com" + +#include + +#include "mpp_common.h" +#include "hal_h264d_vdpu_com.h" + +const RK_U32 vdpu_cabac_table[VDPU_CABAC_TAB_SIZE / 4] = { + 0x14f10236, 0x034a14f1, 0x0236034a, 0xe47fe968, 0xfa35ff36, 0x07330000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0029003f, 0x003f003f, 0xf7530456, 0x0061f948, 0x0d29033e, 0x000b0137, + 0x0045ef7f, 0xf3660052, 0xf94aeb6b, 0xe57fe17f, 0xe87fee5f, 0xe57feb72, + 0xe27fef7b, 0xf473f07a, 0xf573f43f, 0xfe44f154, 0xf368fd46, 0xf85df65a, + 0xe27fff4a, 0xfa61f95b, 0xec7ffc38, 0xfb52f94c, 0xea7df95d, 0xf557fd4d, + 0xfb47fc3f, 0xfc44f454, 0xf93ef941, 0x083d0538, 0xfe420140, 0x003dfe4e, + 0x01320734, 0x0a23002c, 0x0b26012d, 0x002e052c, 0x1f110133, 0x07321c13, + 0x10210e3e, 0xf36cf164, 0xf365f35b, 0xf45ef658, 0xf054f656, 0xf953f357, + 0xed5e0146, 0x0048fb4a, 0x123bf866, 0xf164005f, 0xfc4b0248, 0xf54bfd47, + 0x0f2ef345, 0x003e0041, 0x1525f148, 0x09391036, 0x003e0c48, 0x18000f09, + 0x08190d12, 0x0f090d13, 0x0a250c12, 0x061d1421, 0x0f1e042d, 0x013a003e, + 0x073d0c26, 0x0b2d0f27, 0x0b2a0d2c, 0x102d0c29, 0x0a311e22, 0x122a0a37, + 0x1133112e, 0x00591aed, 0x16ef1aef, 0x1ee71cec, 0x21e925e5, 0x21e928e4, + 0x26ef21f5, 0x28f129fa, 0x26012911, 0x1efa1b03, 0x1a1625f0, 0x23fc26f8, + 0x26fd2503, 0x26052a00, 0x23102716, 0x0e301b25, 0x153c0c44, 0x0261fd47, + 0xfa2afb32, 0xfd36fe3e, 0x003a013f, 0xfe48ff4a, 0xf75bfb43, 0xfb1bfd27, + 0xfe2c002e, 0xf040f844, 0xf64efa4d, 0xf656f45c, 0xf137f63c, 0xfa3efc41, + 0xf449f84c, 0xf950f758, 0xef6ef561, 0xec54f54f, 0xfa49fc4a, 0xf356f360, + 0xf561ed75, 0xf84efb21, 0xfc30fe35, 0xfd3ef347, 0xf64ff456, 0xf35af261, + 0x0000fa5d, 0xfa54f84f, 0x0042ff47, 0x003efe3c, 0xfe3bfb4b, 0xfd3efc3a, + 0xf742ff4f, 0x00470344, 0x0a2cf93e, 0x0f240e28, 0x101b0c1d, 0x012c1424, + 0x1220052a, 0x01300a3e, 0x112e0940, 0xf468f561, 0xf060f958, 0xf855f955, + 0xf755f358, 0x0442fd4d, 0xfd4cfa4c, 0x0a3aff4c, 0xff53f963, 0xf25f025f, + 0x004cfb4a, 0x0046f54b, 0x01440041, 0xf249033e, 0x043eff44, 0xf34b0b37, + 0x05400c46, 0x0f060613, 0x07100c0e, 0x120d0d0b, 0x0d0f0f10, 0x0c170d17, + 0x0f140e1a, 0x0e2c1128, 0x112f1811, 0x15151916, 0x1f1b161d, 0x13230e32, + 0x0a39073f, 0xfe4dfc52, 0xfd5e0945, 0xf46d24dd, 0x24de20e6, 0x25e22ce0, + 0x22ee22f1, 0x28f121f9, 0x23fb2100, 0x2602210d, 0x17230d3a, 0x1dfd1a00, + 0x161e1ff9, 0x23f122fd, 0x220324ff, 0x2205200b, 0x2305220c, 0x270b1e1d, + 0x221a1d27, 0x13421f15, 0x1f1f1932, 0xef78ec70, 0xee72f555, 0xf15cf259, + 0xe647f151, 0xf2500044, 0xf246e838, 0xe944e832, 0xf54a17f3, 0x1af328f1, + 0x31f22c03, 0x2d062c22, 0x21361352, 0xfd4bff17, 0x0122012b, 0x0036fe37, + 0x003d0140, 0x0044f75c, 0xf26af361, 0xf15af45a, 0xee58f649, 0xf74ff256, + 0xf649f646, 0xf645fb42, 0xf740fb3a, 0x023b15f6, 0x18f51cf8, 0x1cff1d03, + 0x1d092314, 0x1d240e43, 0x14f10236, 0x034a14f1, 0x0236034a, 0xe47fe968, + 0xfa35ff36, 0x07331721, 0x17021500, 0x01090031, 0xdb760539, 0xf34ef541, + 0x013e0c31, 0xfc491132, 0x1240092b, 0x1d001a43, 0x105a0968, 0xd27fec68, + 0x0143f34e, 0xf541013e, 0xfa56ef5f, 0xfa3d092d, 0xfd45fa51, 0xf5600637, + 0x0743fb56, 0x0258003a, 0xfd4cf65e, 0x05360445, 0xfd510058, 0xf943fb4a, + 0xfc4afb50, 0xf948013a, 0x0029003f, 0x003f003f, 0xf7530456, 0x0061f948, + 0x0d29033e, 0x002dfc4e, 0xfd60e57e, 0xe462e765, 0xe943e452, 0xec5ef053, + 0xea6eeb5b, 0xee66f35d, 0xe37ff95c, 0xfb59f960, 0xf36cfd2e, 0xff41ff39, + 0xf75dfd4a, 0xf75cf857, 0xe97e0536, 0x063c063b, 0x0645ff30, 0x0044fc45, + 0xf858fe55, 0xfa4eff4b, 0xf94d0236, 0x0532fd44, 0x0132062a, 0xfc51013f, + 0xfc460043, 0x0239fe4c, 0x0b230440, 0x013d0b23, 0x12190c18, 0x0d1d0d24, + 0xf65df949, 0xfe490d2e, 0x0931f964, 0x09350235, 0x0535fe3d, 0x00380038, + 0xf33ffb3c, 0xff3e0439, 0xfa450439, 0x0e270433, 0x0d440340, 0x013d093f, + 0x07321027, 0x052c0434, 0x0b30fb3c, 0xff3b003b, 0x1621052c, 0x0e2bff4e, + 0x003c0945, 0x0b1c0228, 0x032c0031, 0x002e022c, 0x0233002f, 0x0427023e, + 0x062e0036, 0x0336023a, 0x043f0633, 0x06390735, 0x06340637, 0x0b2d0e24, + 0x0835ff52, 0x0737fd4e, 0x0f2e161f, 0xff541907, 0x1ef91c03, 0x1c042000, + 0x22ff1e06, 0x1e062009, 0x1f131a1b, 0x1a1e2514, 0x1c221146, 0x0143053b, + 0x0943101e, 0x12201223, 0x161d181f, 0x1726122b, 0x14290b3f, 0x093b0940, + 0xff5efe59, 0xf76cfa4c, 0xfe2c002d, 0x0034fd40, 0xfe3bfc46, 0xfc4bf852, + 0xef66f74d, 0x0318002a, 0x00300037, 0xfa3bf947, 0xf453f557, 0xe277013a, + 0xfd1dff24, 0x0126022b, 0xfa37003a, 0x0040fd4a, 0xf65a0046, 0xfc1d051f, + 0x072a013b, 0xfe3afd48, 0xfd51f561, 0x003a0805, 0x0a0e0e12, 0x0d1b0228, + 0x003afd46, 0xfa4ff855, 0x0000f36a, 0xf06af657, 0xeb72ee6e, 0xf262ea6e, + 0xeb6aee67, 0xeb6be96c, 0xe670f660, 0xf45ffb5b, 0xf75dea5e, 0xfb560943, + 0xfc50f655, 0xff46073c, 0x093a053d, 0x0c320f32, 0x12311136, 0x0a29072e, + 0xff330731, 0x08340929, 0x062f0237, 0x0d290a2c, 0x06320535, 0x0d31043f, + 0x0640fe45, 0xfe3b0646, 0x0a2c091f, 0x0c2b0335, 0x0e220a26, 0xfd340d28, + 0x1120072c, 0x07260d32, 0x0a391a2b, 0x0e0b0b0e, 0x090b120b, 0x150917fe, + 0x20f120f1, 0x22eb27e9, 0x2adf29e1, 0x2ee426f4, 0x151d2de8, 0x35d330e6, + 0x41d52bed, 0x27f61e09, 0x121a141b, 0x0039f252, 0xfb4bed61, 0xdd7d1b00, + 0x1c001ffc, 0x1b062208, 0x1e0a1816, 0x21131620, 0x1a1f1529, 0x1a2c172f, + 0x10410e47, 0x083c063f, 0x11411518, 0x17141a17, 0x1b201c17, 0x1c181728, + 0x18201c1d, 0x172a1339, 0x1635163d, 0x0b560c28, 0x0b330e3b, 0xfc4ff947, + 0xfb45f746, 0xf842f644, 0xed49f445, 0xf046f143, 0xec3eed46, 0xf042ea41, + 0xec3f09fe, 0x1af721f7, 0x27f929fe, 0x2d033109, 0x2d1b243b, 0xfa42f923, + 0xf92af82d, 0xfb30f438, 0xfa3cfb3e, 0xf842f84c, 0xfb55fa51, 0xf64df951, + 0xef50ee49, 0xfc4af653, 0xf747f743, 0xff3df842, 0xf242003b, 0x023b15f3, + 0x21f227f9, 0x2efe3302, 0x3c063d11, 0x37222a3e, 0x14f10236, 0x034a14f1, + 0x0236034a, 0xe47fe968, 0xfa35ff36, 0x07331619, 0x22001000, 0xfe090429, + 0xe3760241, 0xfa47f34f, 0x05340932, 0xfd460a36, 0x1a221316, 0x28003902, + 0x29241a45, 0xd37ff165, 0xfc4cfa47, 0xf34f0534, 0x0645f35a, 0x0034082b, + 0xfe45fb52, 0xf660023b, 0x024bfd57, 0xfd640138, 0xfd4afa55, 0x003bfd51, + 0xf956fb5f, 0xff42ff4d, 0x0146fe56, 0xfb48003d, 0x0029003f, 0x003f003f, + 0xf7530456, 0x0061f948, 0x0d29033e, 0x0d0f0733, 0x0250d97f, 0xee5bef60, + 0xe651dd62, 0xe866e961, 0xe577e863, 0xeb6eee66, 0xdc7f0050, 0xfb59f95e, + 0xfc5c0027, 0x0041f154, 0xdd7ffe49, 0xf468f75b, 0xe17f0337, 0x07380737, + 0x083dfd35, 0x0044f94a, 0xf758f367, 0xf35bf759, 0xf25cf84c, 0xf457e96e, + 0xe869f64e, 0xec70ef63, 0xb27fba7f, 0xce7fd27f, 0xfc42fb4e, 0xfc47f848, + 0x023bff37, 0xf946fa4b, 0xf859de77, 0xfd4b2014, 0x1e16d47f, 0x0036fb3d, + 0x003aff3c, 0xfd3df843, 0xe754f24a, 0xfb410534, 0x0239003d, 0xf745f546, + 0x1237fc47, 0x003a073d, 0x09291219, 0x0920052b, 0x092f002c, 0x0033022e, + 0x1326fc42, 0x0f260c2a, 0x09220059, 0x042d0a1c, 0x0a1f21f5, 0x34d5120f, + 0x1c0023ea, 0x26e72200, 0x27ee20f4, 0x66a20000, 0x38f121fc, 0x1d0a25fb, + 0x33e327f7, 0x34de45c6, 0x43c12cfb, 0x200737e3, 0x20010000, 0x1b2421e7, + 0x22e224e4, 0x26e426e5, 0x22ee23f0, 0x22f220f8, 0x25fa2300, 0x1e0a1c12, + 0x1a191d29, 0x004b0248, 0x084d0e23, 0x121f1123, 0x151e112d, 0x142a122d, + 0x1b1a1036, 0x07421038, 0x0b490a43, 0xf674e970, 0xf147f93d, 0x0035fb42, + 0xf54df750, 0xf754f657, 0xde7feb65, 0xfd27fb35, 0xf93df54b, 0xf14def5b, + 0xe76be76f, 0xe47af54c, 0xf62cf634, 0xf639f73a, 0xf048f945, 0xfc45fb4a, + 0xf7560242, 0xf7220120, 0x0b1f0534, 0xfe37fe43, 0x0049f859, 0x03340704, + 0x0a081108, 0x10130325, 0xff3dfb49, 0xff46fc4e, 0x0000eb7e, 0xe97cec6e, + 0xe67ee77c, 0xef69e579, 0xe575ef66, 0xe675e574, 0xdf7af65f, 0xf264f85f, + 0xef6fe472, 0xfa59fe50, 0xfc52f755, 0xf851ff48, 0x05400143, 0x09380045, + 0x01450745, 0xf945fa43, 0xf04dfe40, 0x023dfa43, 0xfd400239, 0xfd41fd42, + 0x003e0933, 0xff42fe47, 0xfe4bff46, 0xf7480e3c, 0x1025002f, 0x12230b25, + 0x0c290a29, 0x02300c29, 0x0d29003b, 0x03321328, 0x03421232, 0x13fa12fa, + 0x0e001af4, 0x1ff021e7, 0x21ea25e4, 0x27e22ae2, 0x2fd62ddc, 0x31de29ef, + 0x200945b9, 0x3fc142c0, 0x4db636d9, 0x34dd29f6, 0x240028ff, 0x1e0e1c1a, + 0x17250c37, 0x0b4125df, 0x27dc28db, 0x26e22edf, 0x2ae228e8, 0x31e326f4, + 0x28f626fd, 0x2efb1f14, 0x1d1e192c, 0x0c300b31, 0x1a2d1616, 0x17161b15, + 0x21141a1c, 0x1e181b22, 0x122a1927, 0x12320c46, 0x15360e47, 0x0b531920, + 0x15311536, 0xfb55fa51, 0xf64df951, 0xef50ee49, 0xfc4af653, 0xf747f743, + 0xff3df842, 0xf242003b, 0x023b11f6, 0x20f32af7, 0x31fb3500, 0x4003440a, + 0x421b2f39, 0xfb470018, 0xff24fe2a, 0xfe34f739, 0xfa3ffc41, 0xfc43f952, + 0xfd51fd4c, 0xf948fa4e, 0xf448f244, 0xfd46fa4c, 0xfb42fb3e, 0x0039fc3d, + 0xf73c0136, 0x023a11f6, 0x20f32af7, 0x31fb3500, 0x4003440a, 0x421b2f39, + 0x14f10236, 0x034a14f1, 0x0236034a, 0xe47fe968, 0xfa35ff36, 0x07331d10, + 0x19000e00, 0xf633fd3e, 0xe5631a10, 0xfc55e866, 0x05390639, 0xef490e39, + 0x1428140a, 0x1d003600, 0x252a0c61, 0xe07fea75, 0xfe4afc55, 0xe8660539, + 0xfa5df258, 0xfa2c0437, 0xf559f167, 0xeb741339, 0x143a0454, 0x0660013f, + 0xfb55f36a, 0x053f064b, 0xfd5aff65, 0x0337fc4f, 0xfe4bf461, 0xf932013c, + 0x0029003f, 0x003f003f, 0xf7530456, 0x0061f948, 0x0d29033e, 0x0722f758, + 0xec7fdc7f, 0xef5bf25f, 0xe754e756, 0xf459ef5b, 0xe17ff24c, 0xee67f35a, + 0xdb7f0b50, 0x054c0254, 0x054efa37, 0x043df253, 0xdb7ffb4f, 0xf568f55b, + 0xe27f0041, 0xfe4f0048, 0xfc5cfa38, 0x0344f847, 0xf362fc56, 0xf458fb52, + 0xfd48fc43, 0xf848f059, 0xf745ff3b, 0x05420439, 0xfc47fe47, 0x023aff4a, + 0xfc2cff45, 0x003ef933, 0xfc2ffa2a, 0xfd29fa35, 0x084cf74e, 0xf5530934, + 0x0043fb5a, 0x0143f148, 0xfb4bf850, 0xeb53eb40, 0xf31fe740, 0xe35e094b, + 0x113ff84a, 0xfb23fe1b, 0x0d5b0341, 0xf945084d, 0xf642033e, 0xfd44ec51, + 0x001e0107, 0xfd17eb4a, 0x1042e97c, 0x11252cee, 0x32deea7f, 0x0427002a, + 0x07220b1d, 0x081f0625, 0x072a0328, 0x08210d2b, 0x0d24042f, 0x0337023a, + 0x063c082c, 0x0b2c0e2a, 0x07300438, 0x04340d25, 0x0931133a, 0x0a300c2d, + 0x00451421, 0x083f23ee, 0x21e71cfd, 0x180a1b00, 0x22f234d4, 0x27e81311, + 0x1f19241d, 0x1821220f, 0x1e141649, 0x1422131f, 0x1b2c1310, 0x0f240f24, + 0x151c1915, 0x1e141f0c, 0x1b10182a, 0x005d0e38, 0x0f391a26, 0xe87fe873, + 0xea52f73e, 0x0035003b, 0xf255f359, 0xf35ef55c, 0xe37feb64, 0xf239f443, + 0xf547f64d, 0xeb55f058, 0xe968f162, 0xdb7ff652, 0xf830f83d, 0xf842f946, + 0xf24bf64f, 0xf753f45c, 0xee6cfc4f, 0xea45f04b, 0xfe3a013a, 0xf34ef753, + 0xfc51f363, 0xf351fa26, 0xf33efa3a, 0xfe3bf049, 0xf64cf356, 0xf753f657, + 0x0000ea7f, 0xe77fe778, 0xe57fed72, 0xe975e776, 0xe675e871, 0xe476e178, + 0xdb7cf65e, 0xf166f663, 0xf36ace7f, 0xfb5c1139, 0xfb56f35e, 0xf45bfe4d, + 0x0047ff49, 0x0440f951, 0x05400f39, 0x01430044, 0xf6430144, 0x004d0240, + 0x0044fb4e, 0x0737053b, 0x02410e36, 0x0f2c053c, 0x0246fe4c, 0xee560c46, + 0x0540f446, 0x0b370538, 0x00450241, 0xfa4a0536, 0x0736fa4c, 0xf552fe4d, + 0xfe4d192a, 0x11f310f7, 0x11f41beb, 0x25e229d8, 0x2ad730d1, 0x27e02ed8, + 0x34cd2ed7, 0x34d92bed, 0x200b3dc9, 0x38d23ece, 0x51bd2dec, 0x23fe1c0f, + 0x22012701, 0x1e111426, 0x122d0f36, 0x004f24f0, 0x25f225ef, 0x2001220f, + 0x1d0f1819, 0x22161f10, 0x23121f1c, 0x2129241c, 0x1b2f153e, 0x121f131a, + 0x24181817, 0x1b10181e, 0x1f1d1629, 0x162a103c, 0x0f340e3c, 0x034ef07b, + 0x15351638, 0x193d1521, 0x1332113d, 0xfd4ef84a, 0xf748f648, 0xee4bf447, + 0xf53ffb46, 0xef4bf248, 0xf043f835, 0xf23bf734, 0xf54409fe, 0x1ef61ffc, + 0x21ff2107, 0x1f0c2517, 0x1f261440, 0xf747f925, 0xf82cf531, 0xf638f43b, + 0xf83ff743, 0xfa44f64f, 0xfd4ef84a, 0xf748f648, 0xee4bf447, 0xf53ffb46, + 0xef4bf248, 0xf043f835, 0xf23bf734, 0xf54409fe, 0x1ef61ffc, 0x21ff2107, + 0x1f0c2517, 0x1f261440, +}; + +const RK_U32 vdpu_value_list[34] = { + 0, 1, 2, 3, 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 +}; + +static MPP_RET get_info_input(H264dVdpuPriv_t *priv, + DXVA_Slice_H264_Long *p_long, + DXVA_PicParams_H264_MVC *pp) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + memset(priv->new_dpb, 0, sizeof(priv->new_dpb)); + memset(priv->refinfo, 0, sizeof(priv->refinfo)); + //!< change dpb_info syntax + { + RK_U32 i = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefFrameList); i++) { + if (pp->RefFrameList[i].bPicEntry != 0xff) { + priv->new_dpb[i].valid = 1; + priv->new_dpb[i].is_long_term = pp->RefFrameList[i].AssociatedFlag; + priv->new_dpb[i].slot_index = pp->RefFrameList[i].Index7Bits; + priv->new_dpb[i].top_poc = pp->FieldOrderCntList[i][0]; + priv->new_dpb[i].bot_poc = pp->FieldOrderCntList[i][1]; + if (priv->new_dpb[i].is_long_term) { + priv->new_dpb[i].long_term_frame_idx = pp->FrameNumList[i]; + } else { + priv->new_dpb[i].frame_num = pp->FrameNumList[i]; + } + priv->new_dpb[i].long_term_pic_num = pp->LongTermPicNumList[i]; + priv->new_dpb[i].top_used = (((pp->UsedForReferenceFlags + >> (2 * i + 0)) & 0x1) != 0) ? 1 : 0; + priv->new_dpb[i].bot_used = (((pp->UsedForReferenceFlags + >> (2 * i + 1)) & 0x1) != 0) ? 1 : 0; + priv->new_dpb[i].colmv_is_used = (((pp->RefPicColmvUsedFlags >> i) & 0x1) != 0) ? 1 : 0; + priv->new_dpb[i].field_flag = (((pp->RefPicFiledFlags >> i) & 0x1) != 0) ? 1 : 0; + priv->new_dpb[i].is_ilt_flag = (((pp->UsedForInTerviewflags >> i) & 0x1) != 0) ? 1 : 0; + } + } + for (i = 0; i < MPP_ARRAY_ELEMS(pp->ViewIDList); i++) { + priv->new_dpb[i].view_id = pp->ViewIDList[i]; + } + + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefPicLayerIdList); i++) { + priv->new_dpb[i].voidx = pp->RefPicLayerIdList[i]; + } + } + //!< change ref_pic_info syntax + { + RK_U32 i = 0, j = 0; + //!< list P B0 B1 + for (j = 0; j < 3; j++) { + for (i = 0; i < MPP_ARRAY_ELEMS(p_long->RefPicList[j]); i++) { + if (p_long->RefPicList[j][i].bPicEntry != 0xff) { + priv->refinfo[j][i].valid = 1; + priv->refinfo[j][i].dpb_idx = p_long->RefPicList[j][i].Index7Bits; + priv->refinfo[j][i].bottom_flag = p_long->RefPicList[j][i].AssociatedFlag; + } + } + } + } + return ret = MPP_OK; +} + +static MPP_RET fill_picture_entry(DXVA_PicEntry_H264 *pic, RK_U32 index, + RK_U32 flag) +{ + ASSERT((index & 0x7f) == index && (flag & 0x01) == flag); + pic->bPicEntry = index | (flag << 7); + + return MPP_OK; +} + +static MPP_RET refill_info_input(H264dVdpuPriv_t *priv, + DXVA_Slice_H264_Long *p_long, + DXVA_PicParams_H264_MVC *pp) + +{ + MPP_RET ret = MPP_ERR_UNKNOW; + { + RK_U32 i = 0; + H264dVdpuDpbInfo_t *old_dpb = priv->old_dpb[priv->layed_id]; + //!< re-fill dpb_info + pp->UsedForReferenceFlags = 0; + pp->RefPicColmvUsedFlags = 0; + pp->RefPicFiledFlags = 0; + pp->UsedForInTerviewflags = 0; + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefFrameList); i++) { + if (old_dpb[i].valid) { + fill_picture_entry(&pp->RefFrameList[i], old_dpb[i].slot_index, + old_dpb[i].is_long_term); + pp->FieldOrderCntList[i][0] = old_dpb[i].top_poc; + pp->FieldOrderCntList[i][1] = old_dpb[i].bot_poc; + pp->FrameNumList[i] = (old_dpb[i].is_long_term != 0) ? + old_dpb[i].long_term_frame_idx : old_dpb[i].frame_num; + pp->LongTermPicNumList[i] = old_dpb[i].long_term_pic_num; + if (old_dpb[i].top_used) { //!< top_field + pp->UsedForReferenceFlags |= 1 << (2 * i + 0); + } + if (old_dpb[i].bot_used) { //!< bot_field + pp->UsedForReferenceFlags |= 1 << (2 * i + 1); + } + if (old_dpb[i].colmv_is_used) { + pp->RefPicColmvUsedFlags |= 1 << i; + } + if (old_dpb[i].field_flag) { + pp->RefPicFiledFlags |= 1 << i; + } + if (old_dpb[i].is_ilt_flag) { + pp->UsedForInTerviewflags |= 1 << i; + } + } else { + pp->RefFrameList[i].bPicEntry = 0xff; + pp->FieldOrderCntList[i][0] = 0; + pp->FieldOrderCntList[i][1] = 0; + pp->FrameNumList[i] = 0; + pp->LongTermPicNumList[i] = 0; + } + } + for (i = 0; i < MPP_ARRAY_ELEMS(pp->ViewIDList); i++) { + pp->ViewIDList[i] = old_dpb[i].view_id; + } + + for (i = 0; i < MPP_ARRAY_ELEMS(pp->RefPicLayerIdList); i++) { + pp->RefPicLayerIdList[i] = old_dpb[i].voidx; + } + } + //!< re-fill ref_info + { + RK_U32 i = 0, j = 0; + for (j = 0; j < 3; j++) { + H264dVdpuRefPicInfo_t *p = priv->refinfo[j]; + for (i = 0; i < MPP_ARRAY_ELEMS(p_long->RefPicList[j]); i++) { + if (p[i].valid) { + fill_picture_entry(&p_long->RefPicList[j][i], + p[i].dpb_idx, p[i].bottom_flag); + } else { + p_long->RefPicList[j][i].bPicEntry = 0xff; + } + } + } + } + return ret = MPP_OK; +} + +MPP_RET adjust_input(H264dVdpuPriv_t *priv, + DXVA_Slice_H264_Long *p_long, + DXVA_PicParams_H264_MVC *pp) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + + get_info_input(priv, p_long, pp); + //!< dpb mapping to new order + { + RK_U32 i = 0, j = 0; + RK_U32 find_flag = 0; + H264dVdpuDpbInfo_t *new_dpb = priv->new_dpb; + H264dVdpuDpbInfo_t *old_dpb = priv->old_dpb[priv->layed_id]; + +#if DEBUG_REF_LIST + { + mpp_log("=== frame_num %d ===\n", pp->frame_num); + for (i = 0; i < MPP_ARRAY_ELEMS(priv->old_dpb[priv->layed_id]); i++) { + mpp_log("old_dpb[%d] frame_num=%d field=%d poc0=%d poc1=%d\n", + i, old_dpb[i].frame_num, old_dpb[i].field_flag, old_dpb[i].top_poc, old_dpb[i].bot_poc); + } + for (i = 0; i < MPP_ARRAY_ELEMS(priv->old_dpb[priv->layed_id]); i++) { + mpp_log("new_dpb[%d] frame_num=%d field=%d poc0=%d poc1=%d\n", + i, new_dpb[i].frame_num, new_dpb[i].field_flag, new_dpb[i].top_poc, new_dpb[i].bot_poc); + } + } +#endif + //!< delete old dpb + for (i = 0; i < MPP_ARRAY_ELEMS(priv->old_dpb[priv->layed_id]); i++) { + find_flag = 0; + if (old_dpb[i].valid) { + for (j = 0; j < MPP_ARRAY_ELEMS(priv->new_dpb); j++) { + if (new_dpb[j].valid) { + find_flag = + ((old_dpb[i].frame_num == new_dpb[j].frame_num) + ? 1 : 0); + find_flag = ((old_dpb[i].slot_index + == new_dpb[j].slot_index) + ? find_flag : 0); + if (new_dpb[j].top_used && old_dpb[i].top_used) { + find_flag = + ((old_dpb[i].top_poc == new_dpb[j].top_poc) + ? find_flag : 0); + } + if (new_dpb[j].bot_used && old_dpb[i].bot_used) { + find_flag = + ((old_dpb[i].bot_poc == new_dpb[j].bot_poc) + ? find_flag : 0); + } + if (find_flag) { //!< found + new_dpb[j].have_same = 1; + new_dpb[j].new_dpb_idx = i; + old_dpb[i] = new_dpb[j]; + break; + } + } + } + } + //!< not found + if (find_flag == 0) { + memset(&old_dpb[i], 0, sizeof(old_dpb[i])); + } + } + //!< add new dpb + for (j = 0; j < MPP_ARRAY_ELEMS(priv->new_dpb); j++) { + if ((new_dpb[j].valid == 0) || new_dpb[j].have_same) { + continue; + } + for (i = 0; i < MPP_ARRAY_ELEMS(priv->old_dpb[priv->layed_id]); i++) { + if (old_dpb[i].valid == 0) { + old_dpb[i] = new_dpb[j]; + new_dpb[j].new_dpb_idx = i; + break; + } + } + } + //!< inter-layer reference + priv->ilt_dpb = NULL; + if (priv->layed_id) { + for (i = 0; i < MPP_ARRAY_ELEMS(priv->old_dpb[1]); i++) { + if ((old_dpb[i].valid == 0) && old_dpb[i].is_ilt_flag) { + priv->ilt_dpb = &old_dpb[i]; + break; + } + } + } + } + //!< addjust ref_dpb + { + RK_U32 i = 0, j = 0; + H264dVdpuDpbInfo_t *new_dpb = priv->new_dpb; + + for (j = 0; j < 3; j++) { + H264dVdpuRefPicInfo_t *p = priv->refinfo[j]; + for (i = 0; i < MPP_ARRAY_ELEMS(priv->refinfo[j]); i++) { + if (p[i].valid) { + p[i].dpb_idx = new_dpb[p[i].dpb_idx].new_dpb_idx; + } + } + } + } + refill_info_input(priv, p_long, pp); + + return ret = MPP_OK; +} + +RK_S32 compare_p(const void *a, const void *b) +{ + RK_S32 val = 0; + H264dRefsList_t *p0 = (H264dRefsList_t *)a; + H264dRefsList_t *p1 = (H264dRefsList_t *)b; + + if (!p0->ref_flag) + return 1; + if (!p1->ref_flag) + return -1; + + if (p0->lt_flag && p1->lt_flag) { // inc + val = (p0->ref_picnum > p1->ref_picnum) ? 1 : -1; + } else if (!p0->lt_flag && p1->lt_flag) { // dec + val = -1; + } else if (p0->lt_flag && !p1->lt_flag) { // inc + val = 1; + } else if (!p0->lt_flag && !p1->lt_flag) { // dec + val = (p0->ref_picnum < p1->ref_picnum) ? 1 : -1; + } + + return val; +} + +RK_S32 compare_b0(const void *a, const void *b) +{ + RK_S32 val = 0; + H264dRefsList_t *p0 = (H264dRefsList_t *)a; + H264dRefsList_t *p1 = (H264dRefsList_t *)b; + + if (!p0->ref_flag) + return 1; + if (!p1->ref_flag) + return -1; + + if (p0->lt_flag && p1->lt_flag) { // inc + val = (p0->ref_picnum > p1->ref_picnum) ? 1 : -1; + } else if (!p0->lt_flag && p1->lt_flag) { // dec + val = 1; + } else if (p0->lt_flag && !p1->lt_flag) { // inc + val = -1; + } else if (!p0->lt_flag && !p1->lt_flag) { + if (MPP_MAX(p0->ref_poc, p1->ref_poc) < p0->cur_poc) { // dec + val = (p0->ref_poc < p1->ref_poc) ? 1 : -1; + } else if (MPP_MIN(p0->ref_poc, p1->ref_poc) > p0->cur_poc) { // inc + val = (p0->ref_poc > p1->ref_poc) ? 1 : -1; + } else { + val = (p0->ref_poc > p1->ref_poc) ? 1 : -1; // inc + } + } + + return val; +} + +RK_S32 compare_b1(const void *a, const void *b) +{ + RK_S32 val = 0; + H264dRefsList_t *p0 = (H264dRefsList_t *)a; + H264dRefsList_t *p1 = (H264dRefsList_t *)b; + + if (!p0->ref_flag) + return 1; + if (!p1->ref_flag) + return -1; + + if (p0->lt_flag && p1->lt_flag) { // inc + val = (p0->ref_picnum > p1->ref_picnum) ? 1 : -1; + } else if (!p0->lt_flag && p1->lt_flag) { + val = -1; + } else if (p0->lt_flag && !p1->lt_flag) { + val = 1; + } else if (!p0->lt_flag && !p1->lt_flag) { + if (MPP_MIN(p0->ref_poc, p1->ref_poc) > p0->cur_poc) { // inc + val = (p0->ref_poc > p1->ref_poc) ? 1 : -1; + } else if (MPP_MAX(p0->ref_poc, p1->ref_poc) < p0->cur_poc) { // dec + val = (p0->ref_poc < p1->ref_poc) ? 1 : -1; + } else { + val = (p0->ref_poc < p1->ref_poc) ? 1 : -1; // dec + } + } + + return val; +} diff --git a/mpp/hal/rkdec/h264d/hal_h264d_vdpu_com.h b/mpp/hal/rkdec/h264d/hal_h264d_vdpu_com.h new file mode 100644 index 000000000..d369d5c5b --- /dev/null +++ b/mpp/hal/rkdec/h264d/hal_h264d_vdpu_com.h @@ -0,0 +1,117 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264D_VDPU_COM_H +#define HAL_H264D_VDPU_COM_H + +#include "rk_type.h" + +#include "hal_h264d_global.h" + +#define VDPU_CABAC_TAB_SIZE (3680) /* bytes */ +#define VDPU_POC_BUF_SIZE (34*4) /* bytes */ +#define VDPU_SCALING_LIST_SIZE (6*16+2*64) /* bytes */ + +#define DEBUG_REF_LIST 0 + +extern const RK_U32 vdpu_cabac_table[VDPU_CABAC_TAB_SIZE / 4]; +extern const RK_U32 vdpu_value_list[34]; + +typedef struct h264d_vdpu_dpb_info_t { + RK_U8 valid; + + RK_S32 slot_index; + RK_U32 is_long_term; + RK_S32 top_poc; + RK_S32 bot_poc; + RK_U16 frame_num; + RK_U32 long_term_frame_idx; + RK_U32 long_term_pic_num; + RK_U32 top_used; + RK_U32 bot_used; + RK_U32 view_id; + RK_U32 colmv_is_used; + RK_U32 field_flag; + RK_U32 is_ilt_flag; + RK_U32 voidx; + + RK_U8 have_same; + RK_U32 new_dpb_idx; +} H264dVdpuDpbInfo_t; + +typedef struct h264d_vdpu_ref_pic_info_t { + RK_U32 valid; + + RK_S32 dpb_idx; + RK_S32 bottom_flag; +} H264dVdpuRefPicInfo_t; + +typedef struct h264d_vdpu_priv_t { + RK_U32 layed_id; + + H264dVdpuDpbInfo_t old_dpb[2][16]; + H264dVdpuDpbInfo_t new_dpb[16]; + H264dVdpuDpbInfo_t *ilt_dpb; + H264dVdpuRefPicInfo_t refinfo[3][32]; //!< listP listB0 list1 +} H264dVdpuPriv_t; + +typedef struct h264d_vdpu_buf_t { + RK_U32 valid; + + MppBuffer buf; + void *cabac_ptr; + void *poc_ptr; + void *sclst_ptr; + void *regs; +} H264dVdpuBuf_t; + +typedef struct h264d_refs_list_t { + RK_S32 idx; + RK_S32 cur_poc; + + RK_S32 lt_flag; + RK_S32 ref_poc; + RK_S32 ref_picnum; + RK_S32 ref_flag; +} H264dRefsList_t; + +typedef struct h264d_vdpu_reg_ctx_t { + H264dVdpuBuf_t reg_buf[3]; + + MppBuffer buf; + void *cabac_ptr; + void *poc_ptr; + void *sclst_ptr; + void *regs; +} H264dVdpuRegCtx_t; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET adjust_input(H264dVdpuPriv_t *priv, + DXVA_Slice_H264_Long *p_long, + DXVA_PicParams_H264_MVC *pp); + +RK_S32 compare_p(const void *a, const void *b); +RK_S32 compare_b0(const void *a, const void *b); +RK_S32 compare_b1(const void *a, const void *b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/hal/rkdec/h265d/CMakeLists.txt b/mpp/hal/rkdec/h265d/CMakeLists.txt index b66fe4acf..59468f32c 100644 --- a/mpp/hal/rkdec/h265d/CMakeLists.txt +++ b/mpp/hal/rkdec/h265d/CMakeLists.txt @@ -1 +1,17 @@ # vim: syntax=cmake +# hal h265 reg + +set(HAL_H265D_SRC + hal_h265d_com.c + ) + +add_hal_source(HAL_H265D_SRC HAVE_VDPU341 hal_h265d_rkv.c) +add_hal_source(HAL_H265D_SRC HAVE_VDPU34X hal_h265d_vdpu34x.c) +add_hal_source(HAL_H265D_SRC HAVE_VDPU382 hal_h265d_vdpu382.c) +add_hal_source(HAL_H265D_SRC HAVE_VDPU383 hal_h265d_vdpu383.c) +add_hal_source(HAL_H265D_SRC HAVE_VDPU384A hal_h265d_vdpu384a.c) +add_hal_source(HAL_H265D_SRC HAVE_VDPU384B hal_h265d_vdpu384b.c) + +if (HAL_H265D_SRC) + add_library(hal_h265d_api OBJECT ${HAL_H265D_SRC}) +endif() diff --git a/mpp/hal/rkdec/h265d/hal_h265d_com.c b/mpp/hal/rkdec/h265d/hal_h265d_com.c new file mode 100644 index 000000000..4fcbf9442 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_com.c @@ -0,0 +1,3058 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265d_com" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_bitread.h" +#include "mpp_bitput.h" + +#include "hal_h265d_debug.h" +#include "hal_h265d_ctx.h" +#include "hal_h265d_com.h" +#include "h265d_syntax.h" +#include "vdpu38x_com.h" + +RK_U8 hal_hevc_diag_scan4x4_x[16] = { + 0, 0, 1, 0, + 1, 2, 0, 1, + 2, 3, 1, 2, + 3, 2, 3, 3, +}; + +RK_U8 hal_hevc_diag_scan4x4_y[16] = { + 0, 1, 0, 2, + 1, 0, 3, 2, + 1, 0, 3, 2, + 1, 3, 2, 3, +}; + +RK_U8 hal_hevc_diag_scan8x8_x[64] = { + 0, 0, 1, 0, + 1, 2, 0, 1, + 2, 3, 0, 1, + 2, 3, 4, 0, + 1, 2, 3, 4, + 5, 0, 1, 2, + 3, 4, 5, 6, + 0, 1, 2, 3, + 4, 5, 6, 7, + 1, 2, 3, 4, + 5, 6, 7, 2, + 3, 4, 5, 6, + 7, 3, 4, 5, + 6, 7, 4, 5, + 6, 7, 5, 6, + 7, 6, 7, 7, +}; + +RK_U8 hal_hevc_diag_scan8x8_y[64] = { + 0, 1, 0, 2, + 1, 0, 3, 2, + 1, 0, 4, 3, + 2, 1, 0, 5, + 4, 3, 2, 1, + 0, 6, 5, 4, + 3, 2, 1, 0, + 7, 6, 5, 4, + 3, 2, 1, 0, + 7, 6, 5, 4, + 3, 2, 1, 7, + 6, 5, 4, 3, + 2, 7, 6, 5, + 4, 3, 7, 6, + 5, 4, 7, 6, + 5, 7, 6, 7, +}; + +void hal_record_scaling_list(scalingFactor_t *pScalingFactor_out, scalingList_t *pScalingList) +{ + RK_U32 g_scalingListNum_model[SCALING_LIST_SIZE_NUM] = {6, 6, 6, 2}; // from C Model + RK_U32 nIndex = 0; + RK_U32 sizeId, matrixId, listId; + RK_U8 *p = pScalingFactor_out->scalingfactor0; + RK_U8 tmpBuf[8 * 8]; + RK_S32 i; + + //output non-default scalingFactor Table (1248 BYTES) + for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) { + for (listId = 0; listId < g_scalingListNum_model[sizeId]; listId++) { + if (sizeId < 3) { + for (i = 0; i < (sizeId == 0 ? 16 : 64); i++) { + pScalingFactor_out->scalingfactor0[nIndex++] = (RK_U8)pScalingList->sl[sizeId][listId][i]; + } + } else { + for (i = 0; i < 64; i ++) { + pScalingFactor_out->scalingfactor0[nIndex++] = (RK_U8)pScalingList->sl[sizeId][listId][i]; + } + for (i = 0; i < 128; i ++) { + pScalingFactor_out->scalingfactor0[nIndex++] = 0; + } + } + } + } + //output non-default scalingFactor Table Rotation(96 Bytes) + nIndex = 0; + for (listId = 0; listId < g_scalingListNum_model[0]; listId++) { + RK_U8 temp16[16] = {0}; + for (i = 0; i < 16; i ++) { + temp16[i] = (RK_U8)pScalingList->sl[0][listId][i]; + } + for (i = 0; i < 4; i ++) { + pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i]; + pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 4]; + pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 8]; + pScalingFactor_out->scalingfactor1[nIndex++] = temp16[i + 12]; + } + } + //output non-default ScalingList_DC_Coeff (12 BYTES) + nIndex = 0; + for (listId = 0; listId < g_scalingListNum_model[2]; listId++) { //sizeId = 2 + pScalingFactor_out->scalingdc[nIndex++] = (RK_U8)pScalingList->sl_dc[0][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC + } + for (listId = 0; listId < g_scalingListNum_model[3]; listId++) { //sizeId = 3 + pScalingFactor_out->scalingdc[nIndex++] = (RK_U8)pScalingList->sl_dc[1][listId];// zrh warning: sl_dc differed from scalingList->getScalingListDC + pScalingFactor_out->scalingdc[nIndex++] = 0; + pScalingFactor_out->scalingdc[nIndex++] = 0; + } + + //align 16X address + nIndex = 0; + for (i = 0; i < 4; i ++) { + pScalingFactor_out->reserverd[nIndex++] = 0; + } + + //----------------------All above code show the normal store way in HM-------------------------- + //--------from now on, the scalingfactor0 is rotated 90', the scalingfactor1 is also rotated 90' + + //sizeId == 0 + for (matrixId = 0; matrixId < 6; matrixId++) { + p = pScalingFactor_out->scalingfactor0 + matrixId * 16; + + for (i = 0; i < 4; i++) { + tmpBuf[4 * 0 + i] = p[i * 4 + 0]; + tmpBuf[4 * 1 + i] = p[i * 4 + 1]; + tmpBuf[4 * 2 + i] = p[i * 4 + 2]; + tmpBuf[4 * 3 + i] = p[i * 4 + 3]; + } + memcpy(p, tmpBuf, 4 * 4 * sizeof(RK_U8)); + } + //sizeId == 1 + for (matrixId = 0; matrixId < 6; matrixId++) { + p = pScalingFactor_out->scalingfactor0 + 6 * 16 + matrixId * 64; + + for (i = 0; i < 8; i++) { + tmpBuf[8 * 0 + i] = p[i * 8 + 0]; + tmpBuf[8 * 1 + i] = p[i * 8 + 1]; + tmpBuf[8 * 2 + i] = p[i * 8 + 2]; + tmpBuf[8 * 3 + i] = p[i * 8 + 3]; + tmpBuf[8 * 4 + i] = p[i * 8 + 4]; + tmpBuf[8 * 5 + i] = p[i * 8 + 5]; + tmpBuf[8 * 6 + i] = p[i * 8 + 6]; + tmpBuf[8 * 7 + i] = p[i * 8 + 7]; + } + memcpy(p, tmpBuf, 8 * 8 * sizeof(RK_U8)); + } + //sizeId == 2 + for (matrixId = 0; matrixId < 6; matrixId++) { + p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + matrixId * 64; + + for (i = 0; i < 8; i++) { + tmpBuf[8 * 0 + i] = p[i * 8 + 0]; + tmpBuf[8 * 1 + i] = p[i * 8 + 1]; + tmpBuf[8 * 2 + i] = p[i * 8 + 2]; + tmpBuf[8 * 3 + i] = p[i * 8 + 3]; + tmpBuf[8 * 4 + i] = p[i * 8 + 4]; + tmpBuf[8 * 5 + i] = p[i * 8 + 5]; + tmpBuf[8 * 6 + i] = p[i * 8 + 6]; + tmpBuf[8 * 7 + i] = p[i * 8 + 7]; + } + memcpy(p, tmpBuf, 8 * 8 * sizeof(RK_U8)); + } + //sizeId == 3 + for (matrixId = 0; matrixId < 6; matrixId++) { + p = pScalingFactor_out->scalingfactor0 + 6 * 16 + 6 * 64 + 6 * 64 + matrixId * 64; + + for (i = 0; i < 8; i++) { + tmpBuf[8 * 0 + i] = p[i * 8 + 0]; + tmpBuf[8 * 1 + i] = p[i * 8 + 1]; + tmpBuf[8 * 2 + i] = p[i * 8 + 2]; + tmpBuf[8 * 3 + i] = p[i * 8 + 3]; + tmpBuf[8 * 4 + i] = p[i * 8 + 4]; + tmpBuf[8 * 5 + i] = p[i * 8 + 5]; + tmpBuf[8 * 6 + i] = p[i * 8 + 6]; + tmpBuf[8 * 7 + i] = p[i * 8 + 7]; + } + memcpy(p, tmpBuf, 8 * 8 * sizeof(RK_U8)); + } + + //sizeId == 0 + for (matrixId = 0; matrixId < 6; matrixId++) { + p = pScalingFactor_out->scalingfactor1 + matrixId * 16; + + for (i = 0; i < 4; i++) { + tmpBuf[4 * 0 + i] = p[i * 4 + 0]; + tmpBuf[4 * 1 + i] = p[i * 4 + 1]; + tmpBuf[4 * 2 + i] = p[i * 4 + 2]; + tmpBuf[4 * 3 + i] = p[i * 4 + 3]; + } + memcpy(p, tmpBuf, 4 * 4 * sizeof(RK_U8)); + } +} + +int hal_h265d_slice_rpl(void *dxva, SliceHeader_t *sh, RefPicListTab_t *ref) +{ + RK_U8 nb_list = sh->slice_type == B_SLICE ? 2 : 1; + RK_U8 list_idx; + RK_U8 bef_nb_refs = 0, aft_nb_refs = 0, lt_cur_nb_refs = 0; + h265d_dxva2_picture_context_t *dxva_cxt = NULL; + RK_S32 cand_lists[3]; + RK_U32 i, j; + + memset(ref, 0, sizeof(RefPicListTab_t)); + dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + + for (i = 0; i < 8; i++ ) { + if (dxva_cxt->pp.RefPicSetStCurrBefore[i] != 0xff) { + bef_nb_refs ++; + } + + if (dxva_cxt->pp.RefPicSetStCurrAfter[i] != 0xff) { + aft_nb_refs ++; + } + + if (dxva_cxt->pp.RefPicSetLtCurr[i] != 0xff) { + lt_cur_nb_refs ++; + } + } + + if (!(bef_nb_refs + aft_nb_refs + + lt_cur_nb_refs)) { + mpp_loge("rps: zero refs in frame\n"); + return MPP_ERR_STREAM; + } + + for (list_idx = 0; list_idx < nb_list; list_idx++) { + RefPicList_t rpl_tmp; + RefPicList_t *rpl = &ref->refPicList[list_idx]; + memset(&rpl_tmp, 0, sizeof(RefPicList_t)); + + /* The order of the elements is + * ST_CURR_BEF - ST_CURR_AFT - LT_CURR for the L0 and + * ST_CURR_AFT - ST_CURR_BEF - LT_CURR for the L1 */ + + cand_lists[0] = (list_idx != 0) ? ST_CURR_AFT : ST_CURR_BEF; + cand_lists[1] = (list_idx != 0) ? ST_CURR_BEF : ST_CURR_AFT; + cand_lists[2] = LT_CURR; + /* concatenate the candidate lists for the current frame */ + while ((RK_U32)rpl_tmp.nb_refs < sh->nb_refs[list_idx]) { + for (i = 0; i < MPP_ARRAY_ELEMS(cand_lists); i++) { + RK_U8 *rps = NULL; + RK_U32 nb_refs = 0; + if (cand_lists[i] == ST_CURR_BEF) { + rps = &dxva_cxt->pp.RefPicSetStCurrBefore[0]; + nb_refs = bef_nb_refs; + } else if (cand_lists[i] == ST_CURR_AFT) { + rps = &dxva_cxt->pp.RefPicSetStCurrAfter[0]; + nb_refs = aft_nb_refs; + } else { + rps = &dxva_cxt->pp.RefPicSetLtCurr[0]; + nb_refs = lt_cur_nb_refs; + } + for (j = 0; j < nb_refs && rpl_tmp.nb_refs < MAX_REFS; j++) { + rpl_tmp.dpb_index[rpl_tmp.nb_refs] = rps[j]; + rpl_tmp.nb_refs++; + } + } + } + + /* reorder the references if necessary */ + if (sh->rpl_modification_flag[list_idx]) { + for (i = 0; i < sh->nb_refs[list_idx]; i++) { + int idx = sh->list_entry_lx[list_idx][i]; + rpl->dpb_index[i] = rpl_tmp.dpb_index[idx]; + rpl->nb_refs++; + } + } else { + memcpy(rpl, &rpl_tmp, sizeof(*rpl)); + rpl->nb_refs = MPP_MIN((RK_U32)rpl->nb_refs, sh->nb_refs[list_idx]); + } + } + return 0; +} + +RK_S32 hal_h265d_slice_hw_rps(void *dxva, void *rps_buf, void* sw_rps_buf, RK_U32 fast_mode) +{ + BitputCtx_t bp; + RK_S32 fifo_len = 400; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + RK_S32 i = 0, j = 0; + + if (!dxva_cxt->pp.rps_update_flag) { + if (fast_mode) { + memcpy(rps_buf, sw_rps_buf, fifo_len * sizeof(RK_U64)); + } + return 0; + } + mpp_set_bitput_ctx(&bp, (RK_U64*)sw_rps_buf, fifo_len); + for (i = 0; i < 32; i ++) { + mpp_put_bits(&bp, dxva_cxt->pp.sps_lt_rps[i].lt_ref_pic_poc_lsb, 16); + mpp_put_bits(&bp, dxva_cxt->pp.sps_lt_rps[i].used_by_curr_pic_lt_flag, 1); + mpp_put_bits(&bp, 0, 15); + } + + for (i = 0; i < 64; i++) { + if (i < dxva_cxt->pp.num_short_term_ref_pic_sets) { + + mpp_put_bits(&bp, dxva_cxt->pp.sps_st_rps[i].num_negative_pics, 4); + mpp_put_bits(&bp, dxva_cxt->pp.sps_st_rps[i].num_positive_pics, 4); + for ( j = 0; j < dxva_cxt->pp.sps_st_rps[i].num_negative_pics; j++) { + + mpp_put_bits(&bp, dxva_cxt->pp.sps_st_rps[i].delta_poc_s0[j], 16); + mpp_put_bits(&bp, dxva_cxt->pp.sps_st_rps[i].s0_used_flag[j], 1); + } + + for (j = 0; j < dxva_cxt->pp.sps_st_rps[i].num_positive_pics; j++) { + mpp_put_bits(&bp, dxva_cxt->pp.sps_st_rps[i].delta_poc_s1[j], 16); + mpp_put_bits(&bp, dxva_cxt->pp.sps_st_rps[i].s1_used_flag[j], 1); + + } + + for ( j = dxva_cxt->pp.sps_st_rps[i].num_negative_pics + dxva_cxt->pp.sps_st_rps[i].num_positive_pics; j < 15; j++) { + mpp_put_bits(&bp, 0, 16); + mpp_put_bits(&bp, 0, 1); + } + + } else { + mpp_put_bits(&bp, 0, 4); + mpp_put_bits(&bp, 0, 4); + for ( j = 0; j < 15; j++) { + mpp_put_bits(&bp, 0, 16); + mpp_put_bits(&bp, 0, 1); + } + } + mpp_put_align(&bp, 64, 0); + mpp_put_bits(&bp, 0, 64); + } + RK_U32 *tmp = (RK_U32 *)sw_rps_buf; + memcpy(rps_buf, sw_rps_buf, fifo_len * sizeof(RK_U64)); + for (i = 0; i < 400 * 8 / 4; i++) { + h265h_dbg(H265H_DBG_RPS, "rps[%3d] = 0x%08x\n", i, tmp[i]); + } + return 0; +} + +RK_S32 hal_h265d_slice_output_rps(void *dxva, void *rps_buf) +{ + RK_S32 value; + RK_U32 nal_type; + RK_S32 slice_idx = 0; + BitReadCtx_t gb_cxt, *gb; + SliceHeader_t sh; + H265dSliceRpsData_t *rps_data = NULL; + RK_U32 nb_refs = 0; + RK_S32 bit_begin; + h265d_dxva2_picture_context_t *dxva_cxt = NULL; + RK_U32 i, j, k; + + // Allocate RPS data buffer (600 slices) + rps_data = mpp_calloc(H265dSliceRpsData_t, 600); + if (rps_data == NULL) { + mpp_err("hal: failed to allocate rps_data\n"); + return MPP_ERR_NOMEM; + } + + dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + for (k = 0; k < dxva_cxt->slice_count; k++) { + RefPicListTab_t ref; + memset(&sh, 0, sizeof(SliceHeader_t)); + // mpp_err("data[%d]= 0x%x,size[%d] = %d \n", + // k,dxva_cxt->slice_short[k].BSNALunitDataLocation, k,dxva_cxt->slice_short[k].SliceBytesInBuffer); + mpp_set_bitread_ctx(&gb_cxt, (RK_U8*)(dxva_cxt->bitstream + dxva_cxt->slice_short[k].BSNALunitDataLocation), + dxva_cxt->slice_short[k].SliceBytesInBuffer); + + mpp_set_bitread_pseudo_code_type(&gb_cxt, PSEUDO_CODE_H264_H265); + gb = &gb_cxt; + + READ_ONEBIT(gb, &value); + + if ( value != 0) { + mpp_free(rps_data); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, 6, &nal_type); + + if (nal_type > 23) { + continue; + } + + SKIP_BITS(gb, 9); + + READ_ONEBIT(gb, &sh.first_slice_in_pic_flag); + + if (nal_type >= 16 && nal_type <= 23) + READ_ONEBIT(gb, &sh.no_output_of_prior_pics_flag); + + READ_UE(gb, &sh.pps_id); + + if (sh.pps_id >= 64 ) { + mpp_loge("pps: invalid pps id %d\n", sh.pps_id); + mpp_free(rps_data); + return MPP_ERR_STREAM; + } + + sh.dependent_slice_segment_flag = 0; + if (!sh.first_slice_in_pic_flag) { + RK_S32 slice_address_length; + RK_S32 width, height, ctb_width, ctb_height; + RK_S32 log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + RK_S32 log2_ctb_size = log2_min_cb_size + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size; + + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + + ctb_width = (width + (1 << log2_ctb_size) - 1) >> log2_ctb_size; + ctb_height = (height + (1 << log2_ctb_size) - 1) >> log2_ctb_size; + + if (dxva_cxt->pp.dependent_slice_segments_enabled_flag) + READ_ONEBIT(gb, &sh.dependent_slice_segment_flag); + + slice_address_length = mpp_ceil_log2(ctb_width * ctb_height); + + READ_BITS(gb, slice_address_length, &sh.slice_segment_addr); + + if (sh.slice_segment_addr >= (RK_U32)(ctb_width * ctb_height)) { + mpp_err("slice: invalid segment address %u\n", + sh.slice_segment_addr); + mpp_free(rps_data); + return MPP_ERR_STREAM; + } + + if (!sh.dependent_slice_segment_flag) { + sh.slice_addr = sh.slice_segment_addr; + slice_idx++; + } + } else { + sh.slice_segment_addr = sh.slice_addr = 0; + slice_idx = 0; + } + + if (!sh.dependent_slice_segment_flag) { + for (i = 0; i < dxva_cxt->pp.num_extra_slice_header_bits; i++) + SKIP_BITS(gb, 1); + + READ_UE(gb, &sh.slice_type); + if (!(sh.slice_type == I_SLICE || + sh.slice_type == P_SLICE || + sh.slice_type == B_SLICE)) { + mpp_loge("slice: unknown type %d\n", + sh.slice_type); + mpp_free(rps_data); + return MPP_ERR_STREAM; + } + + if (dxva_cxt->pp.output_flag_present_flag) + READ_ONEBIT(gb, &sh.pic_output_flag); + + if (dxva_cxt->pp.separate_colour_plane_flag) + READ_BITS(gb, 2, &sh.colour_plane_id ); + + if (!IS_IDR(nal_type)) { + int short_term_ref_pic_set_sps_flag; + + READ_BITS(gb, (dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4), &sh.pic_order_cnt_lsb); + + READ_ONEBIT(gb, &short_term_ref_pic_set_sps_flag); + + bit_begin = gb->used_bits; + + if (!short_term_ref_pic_set_sps_flag) { + SKIP_BITS(gb, dxva_cxt->pp.wNumBitsForShortTermRPSInSlice); + } else { + RK_S32 numbits, rps_idx; + if (!dxva_cxt->pp.num_short_term_ref_pic_sets) { + mpp_loge("sps: missing ref lists\n"); + mpp_free(rps_data); + return MPP_ERR_STREAM; + } + numbits = mpp_ceil_log2(dxva_cxt->pp.num_short_term_ref_pic_sets); + rps_idx = 0; + if (numbits > 0) + READ_BITS(gb, numbits, &rps_idx); + } + + rps_data[slice_idx].rps_bit_offset_st = gb->used_bits - bit_begin; + rps_data[slice_idx].rps_bit_offset = rps_data[slice_idx].rps_bit_offset_st; + if (dxva_cxt->pp.long_term_ref_pics_present_flag) { + +// RK_S32 max_poc_lsb = 1 << (dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4); + RK_U32 nb_sps = 0, nb_sh; + + bit_begin = gb->used_bits; + if (dxva_cxt->pp.num_long_term_ref_pics_sps > 0) + READ_UE(gb, &nb_sps); + + READ_UE(gb, &nb_sh); + + nb_refs = nb_sh + nb_sps; + + for (i = 0; i < nb_refs; i++) { + RK_U8 delta_poc_msb_present; + + if ((RK_U32)i < nb_sps) { + RK_U8 lt_idx_sps = 0; + + if (dxva_cxt->pp.num_long_term_ref_pics_sps > 1) + READ_BITS(gb, mpp_ceil_log2(dxva_cxt->pp.num_long_term_ref_pics_sps), <_idx_sps); + } else { + SKIP_BITS(gb, (dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4)); + SKIP_BITS(gb, 1); + } + + READ_ONEBIT(gb, &delta_poc_msb_present); + if (delta_poc_msb_present) { + RK_S32 delta = 0; + READ_UE(gb, &delta); + } + } + rps_data[slice_idx].rps_bit_offset += (gb->used_bits - bit_begin); + + } + + if (dxva_cxt->pp.sps_temporal_mvp_enabled_flag) + READ_ONEBIT(gb, &sh.slice_temporal_mvp_enabled_flag); + else + sh.slice_temporal_mvp_enabled_flag = 0; + } else { + sh.st_rps_using = NULL; + } + + if (dxva_cxt->pp.sample_adaptive_offset_enabled_flag) { + READ_ONEBIT(gb, &sh.slice_sample_adaptive_offset_flag[0]); + READ_ONEBIT(gb, &sh.slice_sample_adaptive_offset_flag[1]); + sh.slice_sample_adaptive_offset_flag[2] = + sh.slice_sample_adaptive_offset_flag[1]; + } else { + sh.slice_sample_adaptive_offset_flag[0] = 0; + sh.slice_sample_adaptive_offset_flag[1] = 0; + sh.slice_sample_adaptive_offset_flag[2] = 0; + } + + sh.nb_refs[L0] = sh.nb_refs[L1] = 0; + if (sh.slice_type == P_SLICE || sh.slice_type == B_SLICE) { + + sh.nb_refs[L0] = dxva_cxt->pp.num_ref_idx_l0_default_active_minus1 + 1; + if (sh.slice_type == B_SLICE) + sh.nb_refs[L1] = dxva_cxt->pp.num_ref_idx_l1_default_active_minus1 + 1; + + READ_ONEBIT(gb, &value); + + if (value) { // num_ref_idx_active_override_flag + READ_UE(gb, &sh.nb_refs[L0]); + sh.nb_refs[L0] += 1; + if (sh.slice_type == B_SLICE) { + READ_UE(gb, &sh.nb_refs[L1]); + sh.nb_refs[L1] += 1; + } + } + if (sh.nb_refs[L0] > MAX_REFS || sh.nb_refs[L1] > MAX_REFS) { + mpp_loge("slice: reference count exceeds limit %d %d\n", + sh.nb_refs[L0], sh.nb_refs[L1]); + return MPP_ERR_STREAM; + } + + sh.rpl_modification_flag[0] = 0; + sh.rpl_modification_flag[1] = 0; + nb_refs = 0; + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_cxt->pp.RefPicList); i++) { + if (dxva_cxt->pp.RefPicList[i].bPicEntry != 0xff) { + h265h_dbg(H265H_DBG_RPS, "dxva_cxt->pp.RefPicList[i].bPicEntry = %d", dxva_cxt->pp.RefPicList[i].bPicEntry); + nb_refs++; + } + } + + if (!nb_refs) { + mpp_loge("refs: zero refs for p or b frame\n"); + mpp_free(rps_data); + return MPP_ERR_STREAM; + } + + if (dxva_cxt->pp.lists_modification_present_flag && nb_refs > 1) { + READ_ONEBIT(gb, &sh.rpl_modification_flag[0]); + if (sh.rpl_modification_flag[0]) { + for (i = 0; (RK_U32)i < sh.nb_refs[L0]; i++) + READ_BITS(gb, mpp_ceil_log2(nb_refs), &sh.list_entry_lx[0][i]); + } + + if (sh.slice_type == B_SLICE) { + READ_ONEBIT(gb, &sh.rpl_modification_flag[1]); + if (sh.rpl_modification_flag[1] == 1) + for (i = 0; (RK_U32)i < sh.nb_refs[L1]; i++) + READ_BITS(gb, mpp_ceil_log2(nb_refs), &sh.list_entry_lx[1][i]); + } + } + } + } + + if (!sh.dependent_slice_segment_flag && + sh.slice_type != I_SLICE) { + RK_U32 nb_list = I_SLICE - sh.slice_type; + + hal_h265d_slice_rpl(dxva, &sh, &ref); + rps_data[slice_idx].lowdelay_flag = 1; + + for (j = 0; j < nb_list; j++) { + for (i = 0; i < ref.refPicList[j].nb_refs; i++) { + RK_U8 index = 0; + index = ref.refPicList[j].dpb_index[i]; + // mpp_err("slice_idx = %d index = %d,j = %d i = %d",slice_idx,index,j,i); + if (index != 0xff) { + rps_data[slice_idx].rps_pic_info[j][i].dpb_index = index; + rps_data[slice_idx].rps_pic_info[j][i].is_long_term + = dxva_cxt->pp.RefPicList[index].AssociatedFlag; + if (dxva_cxt->pp.PicOrderCntValList[index] > dxva_cxt->pp.CurrPicOrderCntVal) + rps_data[slice_idx].lowdelay_flag = 0; + } + } + } + + if (sh.slice_type == I_SLICE) + rps_data[slice_idx].slice_nb_rps_poc = 0; + else + rps_data[slice_idx].slice_nb_rps_poc = nb_refs; + + } + } +//out put for rk format + { + RK_S32 nb_slice = slice_idx + 1; + RK_S32 fifo_len = nb_slice * 4 + 1;//size of rps_packet alloc more 1 64 bit invoid buffer no enought + RK_U64 *rps_packet = mpp_malloc(RK_U64, fifo_len); + BitputCtx_t bp; + + mpp_set_bitput_ctx(&bp, rps_packet, fifo_len); + for (k = 0; k < (RK_U32)nb_slice; k++) { + for (j = 0; j < 2; j++) { + for (i = 0; i < 15; i++) { + mpp_put_bits(&bp, rps_data[k].rps_pic_info[j][i].is_long_term, 1); + if (j == 1 && i == 4) { + mpp_put_align (&bp, 64, 0); + } + mpp_put_bits(&bp, rps_data[k].rps_pic_info[j][i].dpb_index, 4); + } + } + mpp_put_bits(&bp, rps_data[k].lowdelay_flag, 1); + h265h_dbg(H265H_DBG_RPS, "lowdelay_flag = %d \n", rps_data[k].lowdelay_flag); + mpp_put_bits(&bp, rps_data[k].rps_bit_offset, 10); + + h265h_dbg(H265H_DBG_RPS, "rps_bit_offset = %d \n", rps_data[k].rps_bit_offset); + mpp_put_bits(&bp, rps_data[k].rps_bit_offset_st, 9); + + h265h_dbg(H265H_DBG_RPS, "rps_bit_offset_st = %d \n", rps_data[k].rps_bit_offset_st); + mpp_put_bits(&bp, rps_data[k].slice_nb_rps_poc, 4); + + h265h_dbg(H265H_DBG_RPS, "slice_nb_rps_poc = %d \n", rps_data[k].slice_nb_rps_poc); + mpp_put_align (&bp, 64, 0); + } + if (rps_buf != NULL) { + memcpy(rps_buf, rps_packet, nb_slice * 32); + } + mpp_free(rps_packet); + } + + mpp_free(rps_data); + return 0; +__BITREAD_ERR: + mpp_free(rps_data); + return MPP_ERR_STREAM; +} + +void hal_h265d_output_scalinglist_packet(void *hal, void *ptr, void *dxva) +{ + scalingList_t sl; + RK_U32 i, j, pos; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + if (!dxva_cxt->pp.scaling_list_enabled_flag) { + return; + } + if (memcmp((void*)&dxva_cxt->qm, reg_ctx->scaling_qm, sizeof(DXVA_Qmatrix_HEVC))) { + memset(&sl, 0, sizeof(scalingList_t)); + for (i = 0; i < 6; i++) { + for (j = 0; j < 16; j++) { + pos = 4 * hal_hevc_diag_scan4x4_y[j] + hal_hevc_diag_scan4x4_x[j]; + sl.sl[0][i][pos] = dxva_cxt->qm.ucScalingLists0[i][j]; + } + + for (j = 0; j < 64; j++) { + pos = 8 * hal_hevc_diag_scan8x8_y[j] + hal_hevc_diag_scan8x8_x[j]; + sl.sl[1][i][pos] = dxva_cxt->qm.ucScalingLists1[i][j]; + sl.sl[2][i][pos] = dxva_cxt->qm.ucScalingLists2[i][j]; + + if (i < 2) + sl.sl[3][i][pos] = dxva_cxt->qm.ucScalingLists3[i][j]; + } + + sl.sl_dc[0][i] = dxva_cxt->qm.ucScalingListDCCoefSizeID2[i]; + if (i < 2) + sl.sl_dc[1][i] = dxva_cxt->qm.ucScalingListDCCoefSizeID3[i]; + } + hal_record_scaling_list((scalingFactor_t *)reg_ctx->scaling_rk, &sl); + } + memcpy(ptr, reg_ctx->scaling_rk, sizeof(scalingFactor_t)); +} + +RK_U8 cabac_table[27456] = { + 0x07, 0x0f, 0x48, 0x58, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x68, + 0x48, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x68, + 0x58, 0x60, 0x40, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x60, 0x60, 0x50, 0x58, + 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, 0x60, 0x60, + 0x50, 0x58, 0x50, 0x07, 0x58, 0x68, 0x50, 0x58, 0x68, 0x68, 0x68, 0x68, 0x68, 0x50, 0x48, 0x68, + 0x48, 0x48, 0x1f, 0x58, 0x68, 0x68, 0x58, 0x60, 0x60, 0x60, 0x50, 0x50, 0x50, 0x48, 0x58, 0x58, + 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x48, 0x58, 0x58, 0x37, 0x07, 0x58, 0x50, + 0x48, 0x1f, 0x1f, 0x0f, 0x0f, 0x0f, 0x0f, 0x07, 0x0f, 0x48, 0x68, 0x0f, 0x48, 0x68, 0x40, 0x40, + 0x50, 0x50, 0x07, 0x40, 0x50, 0x0f, 0x40, 0x48, 0x07, 0x40, 0x27, 0x50, 0x48, 0x48, 0x40, 0x0f, + 0x50, 0x37, 0x1f, 0x1f, 0x50, 0x37, 0x40, 0x27, 0x40, 0x07, 0x0f, 0x17, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x0f, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, 0x40, 0x40, 0x40, 0x0f, 0x66, + 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x67, + 0x57, 0x5e, 0x00, 0x1f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5f, 0x5f, 0x4f, 0x57, + 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, 0x5f, 0x5f, + 0x4f, 0x57, 0x4f, 0x07, 0x57, 0x67, 0x4f, 0x57, 0x67, 0x67, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x66, + 0x46, 0x48, 0x20, 0x57, 0x67, 0x67, 0x57, 0x5f, 0x5f, 0x5e, 0x4f, 0x4f, 0x4f, 0x47, 0x57, 0x57, + 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x47, 0x57, 0x57, 0x37, 0x07, 0x57, 0x4f, + 0x47, 0x1f, 0x1f, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x67, 0x10, 0x47, 0x67, 0x40, 0x40, + 0x4f, 0x4e, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x01, 0x27, 0x4e, 0x47, 0x47, 0x00, 0x0f, + 0x4f, 0x37, 0x1f, 0x1f, 0x4f, 0x36, 0x00, 0x27, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x0e, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x64, + 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x66, + 0x57, 0x5d, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5e, 0x5e, 0x4e, 0x56, + 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, 0x5e, 0x5e, + 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x56, 0x66, 0x67, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x64, + 0x45, 0x48, 0x20, 0x57, 0x66, 0x66, 0x56, 0x5e, 0x5e, 0x5d, 0x4e, 0x4e, 0x4e, 0x46, 0x56, 0x57, + 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x46, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, + 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x66, 0x10, 0x47, 0x66, 0x40, 0x40, + 0x4f, 0x4d, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x03, 0x27, 0x4d, 0x47, 0x46, 0x01, 0x0f, + 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x34, 0x01, 0x26, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x0d, 0x47, 0x57, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0e, 0x40, 0x40, 0x40, 0x0e, 0x62, + 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x00, 0x00, 0x65, + 0x57, 0x5c, 0x00, 0x1e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x47, 0x5d, 0x5d, 0x4e, 0x56, + 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, 0x5d, 0x5d, + 0x4e, 0x56, 0x4f, 0x07, 0x56, 0x66, 0x4f, 0x55, 0x65, 0x67, 0x66, 0x65, 0x63, 0x4d, 0x46, 0x62, + 0x44, 0x48, 0x20, 0x57, 0x65, 0x65, 0x56, 0x5d, 0x5d, 0x5c, 0x4e, 0x4d, 0x4e, 0x45, 0x56, 0x57, + 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x45, 0x56, 0x57, 0x36, 0x07, 0x56, 0x4f, + 0x47, 0x1e, 0x1e, 0x0f, 0x10, 0x0f, 0x10, 0x07, 0x10, 0x47, 0x65, 0x10, 0x47, 0x65, 0x40, 0x40, + 0x4f, 0x4c, 0x08, 0x00, 0x4f, 0x0f, 0x00, 0x47, 0x07, 0x04, 0x27, 0x4c, 0x47, 0x45, 0x01, 0x0f, + 0x4f, 0x36, 0x1f, 0x1e, 0x4f, 0x33, 0x01, 0x25, 0x00, 0x07, 0x10, 0x17, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x0c, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0d, 0x40, 0x40, 0x40, 0x0d, 0x60, + 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x64, + 0x56, 0x5b, 0x01, 0x1d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5c, 0x5c, 0x4d, 0x55, + 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, 0x5c, 0x5c, + 0x4d, 0x55, 0x4e, 0x07, 0x55, 0x65, 0x4e, 0x54, 0x64, 0x66, 0x65, 0x64, 0x61, 0x4c, 0x45, 0x60, + 0x43, 0x49, 0x21, 0x56, 0x64, 0x64, 0x55, 0x5c, 0x5c, 0x5b, 0x4d, 0x4c, 0x4d, 0x44, 0x55, 0x56, + 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x44, 0x55, 0x56, 0x35, 0x07, 0x55, 0x4e, + 0x46, 0x1d, 0x1d, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x64, 0x11, 0x46, 0x64, 0x40, 0x40, + 0x4e, 0x4b, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x06, 0x27, 0x4b, 0x46, 0x44, 0x02, 0x0f, + 0x4e, 0x35, 0x1e, 0x1d, 0x4e, 0x31, 0x02, 0x24, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x0b, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5e, + 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x63, + 0x56, 0x59, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5b, 0x5b, 0x4c, 0x54, + 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, 0x5b, 0x5b, + 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x53, 0x63, 0x66, 0x64, 0x63, 0x60, 0x4b, 0x44, 0x5e, + 0x41, 0x49, 0x21, 0x56, 0x63, 0x63, 0x54, 0x5b, 0x5b, 0x59, 0x4c, 0x4b, 0x4c, 0x43, 0x54, 0x56, + 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x43, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, + 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x63, 0x11, 0x46, 0x63, 0x40, 0x40, + 0x4e, 0x49, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x07, 0x27, 0x49, 0x46, 0x43, 0x03, 0x0f, + 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x30, 0x03, 0x23, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x0a, 0x46, 0x56, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0c, 0x40, 0x40, 0x40, 0x0c, 0x5c, + 0x46, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x01, 0x01, 0x62, + 0x56, 0x58, 0x01, 0x1c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x46, 0x5a, 0x5a, 0x4c, 0x54, + 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, 0x5a, 0x5a, + 0x4c, 0x54, 0x4e, 0x07, 0x54, 0x64, 0x4e, 0x52, 0x62, 0x66, 0x64, 0x62, 0x5e, 0x4a, 0x44, 0x5c, + 0x40, 0x49, 0x21, 0x56, 0x62, 0x62, 0x54, 0x5a, 0x5a, 0x58, 0x4c, 0x4a, 0x4c, 0x42, 0x54, 0x56, + 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x42, 0x54, 0x56, 0x34, 0x07, 0x54, 0x4e, + 0x46, 0x1c, 0x1c, 0x0f, 0x11, 0x0f, 0x11, 0x07, 0x11, 0x46, 0x62, 0x11, 0x46, 0x62, 0x40, 0x40, + 0x4e, 0x48, 0x09, 0x01, 0x4e, 0x0f, 0x01, 0x46, 0x07, 0x09, 0x27, 0x48, 0x46, 0x42, 0x03, 0x0f, + 0x4e, 0x34, 0x1e, 0x1c, 0x4e, 0x2e, 0x03, 0x22, 0x01, 0x07, 0x11, 0x16, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x09, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0b, 0x40, 0x40, 0x40, 0x0b, 0x5a, + 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x61, + 0x55, 0x57, 0x02, 0x1b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x59, 0x59, 0x4b, 0x53, + 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, 0x59, 0x59, + 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x51, 0x61, 0x65, 0x63, 0x61, 0x5d, 0x49, 0x43, 0x5a, + 0x00, 0x4a, 0x22, 0x55, 0x61, 0x61, 0x53, 0x59, 0x59, 0x57, 0x4b, 0x49, 0x4b, 0x41, 0x53, 0x55, + 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x41, 0x53, 0x55, 0x33, 0x07, 0x53, 0x4d, + 0x45, 0x1b, 0x1b, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x61, 0x12, 0x45, 0x61, 0x40, 0x40, + 0x4d, 0x47, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0a, 0x27, 0x47, 0x45, 0x41, 0x04, 0x0f, + 0x4d, 0x33, 0x1d, 0x1b, 0x4d, 0x2d, 0x04, 0x21, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x08, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x59, + 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x60, + 0x55, 0x56, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x58, 0x58, 0x4b, 0x53, + 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, 0x58, 0x58, + 0x4b, 0x53, 0x4d, 0x07, 0x53, 0x63, 0x4d, 0x50, 0x60, 0x65, 0x63, 0x60, 0x5b, 0x48, 0x43, 0x59, + 0x01, 0x4a, 0x22, 0x55, 0x60, 0x60, 0x53, 0x58, 0x58, 0x56, 0x4b, 0x48, 0x4b, 0x40, 0x53, 0x55, + 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x40, 0x53, 0x55, 0x32, 0x07, 0x53, 0x4d, + 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x60, 0x12, 0x45, 0x60, 0x40, 0x40, + 0x4d, 0x46, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0c, 0x27, 0x46, 0x45, 0x40, 0x04, 0x0f, + 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x2b, 0x04, 0x20, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x07, 0x45, 0x55, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, 0x40, 0x40, 0x40, 0x0a, 0x57, + 0x45, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x02, 0x02, 0x5f, + 0x55, 0x54, 0x02, 0x1a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x45, 0x57, 0x57, 0x4a, 0x52, + 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, 0x57, 0x57, + 0x4a, 0x52, 0x4d, 0x07, 0x52, 0x62, 0x4d, 0x4f, 0x5f, 0x65, 0x62, 0x5f, 0x59, 0x47, 0x42, 0x57, + 0x03, 0x4a, 0x22, 0x55, 0x5f, 0x5f, 0x52, 0x57, 0x57, 0x54, 0x4a, 0x47, 0x4a, 0x00, 0x52, 0x55, + 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x00, 0x52, 0x55, 0x32, 0x07, 0x52, 0x4d, + 0x45, 0x1a, 0x1a, 0x0f, 0x12, 0x0f, 0x12, 0x07, 0x12, 0x45, 0x5f, 0x12, 0x45, 0x5f, 0x40, 0x40, + 0x4d, 0x44, 0x0a, 0x02, 0x4d, 0x0f, 0x02, 0x45, 0x07, 0x0e, 0x27, 0x44, 0x45, 0x00, 0x05, 0x0f, + 0x4d, 0x32, 0x1d, 0x1a, 0x4d, 0x29, 0x05, 0x1f, 0x02, 0x07, 0x12, 0x15, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x55, + 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5e, + 0x54, 0x53, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x56, 0x56, 0x49, 0x51, + 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, 0x56, 0x56, + 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4e, 0x5e, 0x64, 0x61, 0x5e, 0x58, 0x46, 0x41, 0x55, + 0x04, 0x4b, 0x23, 0x54, 0x5e, 0x5e, 0x51, 0x56, 0x56, 0x53, 0x49, 0x46, 0x49, 0x01, 0x51, 0x54, + 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x01, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, + 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5e, 0x13, 0x44, 0x5e, 0x40, 0x40, + 0x4c, 0x43, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x0f, 0x27, 0x43, 0x44, 0x01, 0x06, 0x0f, + 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x28, 0x06, 0x1e, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x05, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x09, 0x40, 0x40, 0x40, 0x09, 0x53, + 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5d, + 0x54, 0x52, 0x03, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x55, 0x55, 0x49, 0x51, + 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, 0x55, 0x55, + 0x49, 0x51, 0x4c, 0x07, 0x51, 0x61, 0x4c, 0x4d, 0x5d, 0x64, 0x61, 0x5d, 0x56, 0x45, 0x41, 0x53, + 0x05, 0x4b, 0x23, 0x54, 0x5d, 0x5d, 0x51, 0x55, 0x55, 0x52, 0x49, 0x45, 0x49, 0x02, 0x51, 0x54, + 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x02, 0x51, 0x54, 0x31, 0x07, 0x51, 0x4c, + 0x44, 0x19, 0x19, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5d, 0x13, 0x44, 0x5d, 0x40, 0x40, + 0x4c, 0x42, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x11, 0x27, 0x42, 0x44, 0x02, 0x06, 0x0f, + 0x4c, 0x31, 0x1c, 0x19, 0x4c, 0x26, 0x06, 0x1d, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x04, 0x44, 0x54, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, 0x40, 0x40, 0x40, 0x08, 0x51, + 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x03, 0x03, 0x5c, + 0x54, 0x51, 0x03, 0x18, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x54, 0x54, 0x48, 0x50, + 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, 0x54, 0x54, + 0x48, 0x50, 0x4c, 0x07, 0x50, 0x60, 0x4c, 0x4c, 0x5c, 0x64, 0x60, 0x5c, 0x55, 0x44, 0x40, 0x51, + 0x06, 0x4b, 0x23, 0x54, 0x5c, 0x5c, 0x50, 0x54, 0x54, 0x51, 0x48, 0x44, 0x48, 0x03, 0x50, 0x54, + 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x03, 0x50, 0x54, 0x30, 0x07, 0x50, 0x4c, + 0x44, 0x18, 0x18, 0x0f, 0x13, 0x0f, 0x13, 0x07, 0x13, 0x44, 0x5c, 0x13, 0x44, 0x5c, 0x40, 0x40, + 0x4c, 0x41, 0x0b, 0x03, 0x4c, 0x0f, 0x03, 0x44, 0x07, 0x12, 0x27, 0x41, 0x44, 0x03, 0x07, 0x0f, + 0x4c, 0x30, 0x1c, 0x18, 0x4c, 0x25, 0x07, 0x1c, 0x03, 0x07, 0x13, 0x14, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x03, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4f, + 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5b, + 0x53, 0x4f, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x53, 0x53, 0x47, 0x4f, + 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, 0x53, 0x53, + 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4b, 0x5b, 0x63, 0x5f, 0x5b, 0x53, 0x43, 0x00, 0x4f, + 0x08, 0x4c, 0x24, 0x53, 0x5b, 0x5b, 0x4f, 0x53, 0x53, 0x4f, 0x47, 0x43, 0x47, 0x04, 0x4f, 0x53, + 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x04, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, + 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5b, 0x14, 0x43, 0x5b, 0x40, 0x40, + 0x4b, 0x00, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x14, 0x27, 0x00, 0x43, 0x04, 0x08, 0x0f, + 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x23, 0x08, 0x1b, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x02, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x07, 0x4d, + 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x5a, + 0x53, 0x4e, 0x04, 0x17, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x52, 0x52, 0x47, 0x4f, + 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, 0x52, 0x52, + 0x47, 0x4f, 0x4b, 0x07, 0x4f, 0x5f, 0x4b, 0x4a, 0x5a, 0x63, 0x5f, 0x5a, 0x52, 0x42, 0x00, 0x4d, + 0x09, 0x4c, 0x24, 0x53, 0x5a, 0x5a, 0x4f, 0x52, 0x52, 0x4e, 0x47, 0x42, 0x47, 0x05, 0x4f, 0x53, + 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x05, 0x4f, 0x53, 0x2f, 0x07, 0x4f, 0x4b, + 0x43, 0x17, 0x17, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x5a, 0x14, 0x43, 0x5a, 0x40, 0x40, + 0x4b, 0x01, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x15, 0x27, 0x01, 0x43, 0x05, 0x08, 0x0f, + 0x4b, 0x2f, 0x1b, 0x17, 0x4b, 0x22, 0x08, 0x1a, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x01, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x06, 0x4b, + 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, + 0x53, 0x4d, 0x04, 0x16, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, + 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, 0x51, 0x51, + 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x50, 0x41, 0x01, 0x4b, + 0x0a, 0x4c, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4d, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, + 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2e, 0x07, 0x4e, 0x4b, + 0x43, 0x16, 0x16, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, + 0x4b, 0x02, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x17, 0x27, 0x02, 0x43, 0x06, 0x09, 0x0f, + 0x4b, 0x2e, 0x1b, 0x16, 0x4b, 0x20, 0x09, 0x19, 0x04, 0x07, 0x14, 0x13, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x43, 0x53, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x4a, + 0x43, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x04, 0x04, 0x59, + 0x53, 0x4c, 0x04, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x43, 0x51, 0x51, 0x46, 0x4e, + 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, 0x51, 0x51, + 0x46, 0x4e, 0x4b, 0x07, 0x4e, 0x5e, 0x4b, 0x49, 0x59, 0x63, 0x5e, 0x59, 0x4f, 0x41, 0x01, 0x4a, + 0x0b, 0x4d, 0x24, 0x53, 0x59, 0x59, 0x4e, 0x51, 0x51, 0x4c, 0x46, 0x41, 0x46, 0x06, 0x4e, 0x53, + 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x06, 0x4e, 0x53, 0x2d, 0x07, 0x4e, 0x4b, + 0x43, 0x15, 0x15, 0x0f, 0x14, 0x0f, 0x14, 0x07, 0x14, 0x43, 0x59, 0x14, 0x43, 0x59, 0x40, 0x40, + 0x4b, 0x03, 0x0c, 0x04, 0x4b, 0x0f, 0x04, 0x43, 0x07, 0x18, 0x27, 0x03, 0x43, 0x06, 0x09, 0x0f, + 0x4b, 0x2d, 0x1a, 0x15, 0x4b, 0x1e, 0x09, 0x18, 0x04, 0x07, 0x14, 0x12, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x05, 0x48, + 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x58, + 0x52, 0x4a, 0x05, 0x15, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x50, 0x50, 0x45, 0x4d, + 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, 0x50, 0x50, + 0x45, 0x4d, 0x4a, 0x07, 0x4d, 0x5d, 0x4a, 0x48, 0x58, 0x62, 0x5d, 0x58, 0x4d, 0x40, 0x02, 0x48, + 0x0d, 0x4d, 0x25, 0x52, 0x58, 0x58, 0x4d, 0x50, 0x50, 0x4a, 0x45, 0x40, 0x45, 0x07, 0x4d, 0x52, + 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x07, 0x4d, 0x52, 0x2d, 0x07, 0x4d, 0x4a, + 0x42, 0x15, 0x15, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x58, 0x15, 0x42, 0x58, 0x40, 0x40, + 0x4a, 0x05, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1a, 0x27, 0x05, 0x42, 0x07, 0x0a, 0x0f, + 0x4a, 0x2d, 0x1a, 0x15, 0x4a, 0x1d, 0x0a, 0x18, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x40, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x46, + 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x57, + 0x52, 0x49, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4f, 0x4f, 0x44, 0x4c, + 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, 0x4f, 0x4f, + 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x47, 0x57, 0x62, 0x5c, 0x57, 0x4b, 0x00, 0x03, 0x46, + 0x0e, 0x4d, 0x25, 0x52, 0x57, 0x57, 0x4c, 0x4f, 0x4f, 0x49, 0x44, 0x00, 0x44, 0x08, 0x4c, 0x52, + 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x08, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, + 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x57, 0x15, 0x42, 0x57, 0x40, 0x40, + 0x4a, 0x06, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1c, 0x27, 0x06, 0x42, 0x08, 0x0b, 0x0f, + 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1b, 0x0b, 0x17, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x41, 0x42, 0x52, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x04, 0x44, + 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x05, 0x05, 0x56, + 0x52, 0x48, 0x05, 0x14, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4e, 0x4e, 0x44, 0x4c, + 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, 0x4e, 0x4e, + 0x44, 0x4c, 0x4a, 0x07, 0x4c, 0x5c, 0x4a, 0x46, 0x56, 0x62, 0x5c, 0x56, 0x4a, 0x01, 0x03, 0x44, + 0x0f, 0x4d, 0x25, 0x52, 0x56, 0x56, 0x4c, 0x4e, 0x4e, 0x48, 0x44, 0x01, 0x44, 0x09, 0x4c, 0x52, + 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x09, 0x4c, 0x52, 0x2c, 0x07, 0x4c, 0x4a, + 0x42, 0x14, 0x14, 0x0f, 0x15, 0x0f, 0x15, 0x07, 0x15, 0x42, 0x56, 0x15, 0x42, 0x56, 0x40, 0x40, + 0x4a, 0x07, 0x0d, 0x05, 0x4a, 0x0f, 0x05, 0x42, 0x07, 0x1d, 0x27, 0x07, 0x42, 0x09, 0x0b, 0x0f, + 0x4a, 0x2c, 0x1a, 0x14, 0x4a, 0x1a, 0x0b, 0x16, 0x05, 0x07, 0x15, 0x12, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x42, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x40, 0x40, 0x40, 0x03, 0x42, + 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x55, + 0x51, 0x47, 0x06, 0x13, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4d, 0x4d, 0x43, 0x4b, + 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, 0x4d, 0x4d, + 0x43, 0x4b, 0x49, 0x07, 0x4b, 0x5b, 0x49, 0x45, 0x55, 0x61, 0x5b, 0x55, 0x48, 0x02, 0x04, 0x42, + 0x10, 0x4e, 0x26, 0x51, 0x55, 0x55, 0x4b, 0x4d, 0x4d, 0x47, 0x43, 0x02, 0x43, 0x0a, 0x4b, 0x51, + 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x0a, 0x4b, 0x51, 0x2b, 0x07, 0x4b, 0x49, + 0x41, 0x13, 0x13, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x55, 0x16, 0x41, 0x55, 0x40, 0x40, + 0x49, 0x08, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x1f, 0x27, 0x08, 0x41, 0x0a, 0x0c, 0x0f, + 0x49, 0x2b, 0x19, 0x13, 0x49, 0x18, 0x0c, 0x15, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x43, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x40, + 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x54, + 0x51, 0x45, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4c, 0x4c, 0x42, 0x4a, + 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, 0x4c, 0x4c, + 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x44, 0x54, 0x61, 0x5a, 0x54, 0x47, 0x03, 0x05, 0x40, + 0x12, 0x4e, 0x26, 0x51, 0x54, 0x54, 0x4a, 0x4c, 0x4c, 0x45, 0x42, 0x03, 0x42, 0x0b, 0x4a, 0x51, + 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0b, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, + 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x54, 0x16, 0x41, 0x54, 0x40, 0x40, + 0x49, 0x0a, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x20, 0x27, 0x0a, 0x41, 0x0b, 0x0d, 0x0f, + 0x49, 0x2a, 0x19, 0x12, 0x49, 0x17, 0x0d, 0x14, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x44, 0x41, 0x51, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x02, 0x01, + 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x06, 0x06, 0x53, + 0x51, 0x44, 0x06, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4b, 0x42, 0x4a, + 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, 0x4b, 0x4b, + 0x42, 0x4a, 0x49, 0x07, 0x4a, 0x5a, 0x49, 0x43, 0x53, 0x61, 0x5a, 0x53, 0x45, 0x04, 0x05, 0x01, + 0x13, 0x4e, 0x26, 0x51, 0x53, 0x53, 0x4a, 0x4b, 0x4b, 0x44, 0x42, 0x04, 0x42, 0x0c, 0x4a, 0x51, + 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x0c, 0x4a, 0x51, 0x2a, 0x07, 0x4a, 0x49, + 0x41, 0x12, 0x12, 0x0f, 0x16, 0x0f, 0x16, 0x07, 0x16, 0x41, 0x53, 0x16, 0x41, 0x53, 0x40, 0x40, + 0x49, 0x0b, 0x0e, 0x06, 0x49, 0x0f, 0x06, 0x41, 0x07, 0x22, 0x27, 0x0b, 0x41, 0x0c, 0x0d, 0x0f, + 0x49, 0x2a, 0x19, 0x12, 0x49, 0x15, 0x0d, 0x13, 0x06, 0x07, 0x16, 0x11, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x45, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x40, 0x40, 0x40, 0x01, 0x03, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x52, + 0x50, 0x43, 0x07, 0x11, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x4a, 0x41, 0x49, + 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, 0x4a, 0x4a, + 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x42, 0x52, 0x60, 0x59, 0x52, 0x44, 0x05, 0x06, 0x03, + 0x14, 0x4f, 0x27, 0x50, 0x52, 0x52, 0x49, 0x4a, 0x4a, 0x43, 0x41, 0x05, 0x41, 0x0d, 0x49, 0x50, + 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x0d, 0x49, 0x50, 0x29, 0x07, 0x49, 0x48, + 0x40, 0x11, 0x11, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x52, 0x17, 0x40, 0x52, 0x40, 0x40, + 0x48, 0x0c, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x23, 0x27, 0x0c, 0x40, 0x0d, 0x0e, 0x0f, + 0x48, 0x29, 0x18, 0x11, 0x48, 0x14, 0x0e, 0x12, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x46, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x51, + 0x50, 0x42, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, + 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, 0x49, 0x49, + 0x41, 0x49, 0x48, 0x07, 0x49, 0x59, 0x48, 0x41, 0x51, 0x60, 0x59, 0x51, 0x42, 0x06, 0x06, 0x04, + 0x15, 0x4f, 0x27, 0x50, 0x51, 0x51, 0x49, 0x49, 0x49, 0x42, 0x41, 0x06, 0x41, 0x0e, 0x49, 0x50, + 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x0e, 0x49, 0x50, 0x28, 0x07, 0x49, 0x48, + 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x51, 0x17, 0x40, 0x51, 0x40, 0x40, + 0x48, 0x0d, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x25, 0x27, 0x0d, 0x40, 0x0e, 0x0e, 0x0f, + 0x48, 0x28, 0x18, 0x10, 0x48, 0x12, 0x0e, 0x11, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x47, 0x40, 0x50, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x40, 0x40, 0x00, 0x06, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x50, + 0x50, 0x40, 0x07, 0x10, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, + 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, 0x48, 0x48, + 0x40, 0x48, 0x48, 0x07, 0x48, 0x58, 0x48, 0x40, 0x50, 0x60, 0x58, 0x50, 0x40, 0x07, 0x07, 0x06, + 0x17, 0x4f, 0x27, 0x50, 0x50, 0x50, 0x48, 0x48, 0x48, 0x40, 0x40, 0x07, 0x40, 0x0f, 0x48, 0x50, + 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x0f, 0x48, 0x50, 0x28, 0x07, 0x48, 0x48, + 0x40, 0x10, 0x10, 0x0f, 0x17, 0x0f, 0x17, 0x07, 0x17, 0x40, 0x50, 0x17, 0x40, 0x50, 0x40, 0x40, + 0x48, 0x0f, 0x0f, 0x07, 0x48, 0x0f, 0x07, 0x40, 0x07, 0x27, 0x27, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, + 0x48, 0x28, 0x18, 0x10, 0x48, 0x10, 0x0f, 0x10, 0x07, 0x07, 0x17, 0x10, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x48, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x08, + 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4f, + 0x4f, 0x00, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, + 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, + 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x00, 0x4f, 0x5f, 0x57, 0x4f, 0x00, 0x08, 0x08, 0x08, + 0x18, 0x50, 0x28, 0x4f, 0x4f, 0x4f, 0x47, 0x47, 0x47, 0x00, 0x00, 0x08, 0x00, 0x10, 0x47, 0x4f, + 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x10, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, + 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4f, 0x18, 0x00, 0x4f, 0x40, 0x40, + 0x47, 0x10, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x28, 0x27, 0x10, 0x00, 0x10, 0x10, 0x0f, + 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0f, 0x10, 0x0f, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x49, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0a, + 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4e, + 0x4f, 0x01, 0x08, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x46, 0x00, 0x47, + 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, 0x46, 0x46, + 0x00, 0x47, 0x47, 0x07, 0x47, 0x57, 0x47, 0x01, 0x4e, 0x5f, 0x57, 0x4e, 0x02, 0x09, 0x08, 0x0a, + 0x19, 0x50, 0x28, 0x4f, 0x4e, 0x4e, 0x47, 0x46, 0x46, 0x01, 0x00, 0x09, 0x00, 0x11, 0x47, 0x4f, + 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x11, 0x47, 0x4f, 0x27, 0x07, 0x47, 0x47, + 0x00, 0x0f, 0x0f, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4e, 0x18, 0x00, 0x4e, 0x40, 0x40, + 0x47, 0x11, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2a, 0x27, 0x11, 0x00, 0x11, 0x10, 0x0f, + 0x47, 0x27, 0x17, 0x0f, 0x47, 0x0d, 0x10, 0x0e, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4a, 0x00, 0x4f, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x40, 0x40, 0x40, 0x41, 0x0c, + 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x08, 0x08, 0x4d, + 0x4f, 0x02, 0x08, 0x0e, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x45, 0x45, 0x01, 0x46, + 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, 0x45, 0x45, + 0x01, 0x46, 0x47, 0x07, 0x46, 0x56, 0x47, 0x02, 0x4d, 0x5f, 0x56, 0x4d, 0x03, 0x0a, 0x09, 0x0c, + 0x1a, 0x50, 0x28, 0x4f, 0x4d, 0x4d, 0x46, 0x45, 0x45, 0x02, 0x01, 0x0a, 0x01, 0x12, 0x46, 0x4f, + 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x12, 0x46, 0x4f, 0x26, 0x07, 0x46, 0x47, + 0x00, 0x0e, 0x0e, 0x0f, 0x18, 0x0f, 0x18, 0x07, 0x18, 0x00, 0x4d, 0x18, 0x00, 0x4d, 0x40, 0x40, + 0x47, 0x12, 0x10, 0x08, 0x47, 0x0f, 0x08, 0x00, 0x07, 0x2b, 0x27, 0x12, 0x00, 0x12, 0x11, 0x0f, + 0x47, 0x26, 0x17, 0x0e, 0x47, 0x0c, 0x11, 0x0d, 0x08, 0x07, 0x18, 0x0f, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4b, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x0e, + 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4c, + 0x4e, 0x04, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x44, 0x02, 0x45, + 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, 0x44, 0x44, + 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x03, 0x4c, 0x5e, 0x55, 0x4c, 0x05, 0x0b, 0x0a, 0x0e, + 0x1c, 0x51, 0x29, 0x4e, 0x4c, 0x4c, 0x45, 0x44, 0x44, 0x04, 0x02, 0x0b, 0x02, 0x13, 0x45, 0x4e, + 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x13, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, + 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4c, 0x19, 0x01, 0x4c, 0x40, 0x40, + 0x46, 0x14, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2d, 0x27, 0x14, 0x01, 0x13, 0x12, 0x0f, + 0x46, 0x25, 0x16, 0x0d, 0x46, 0x0a, 0x12, 0x0c, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4c, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x42, 0x10, + 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4b, + 0x4e, 0x05, 0x09, 0x0d, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x43, 0x43, 0x02, 0x45, + 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, 0x43, 0x43, + 0x02, 0x45, 0x46, 0x07, 0x45, 0x55, 0x46, 0x04, 0x4b, 0x5e, 0x55, 0x4b, 0x06, 0x0c, 0x0a, 0x10, + 0x1d, 0x51, 0x29, 0x4e, 0x4b, 0x4b, 0x45, 0x43, 0x43, 0x05, 0x02, 0x0c, 0x02, 0x14, 0x45, 0x4e, + 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x14, 0x45, 0x4e, 0x25, 0x07, 0x45, 0x46, + 0x01, 0x0d, 0x0d, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4b, 0x19, 0x01, 0x4b, 0x40, 0x40, + 0x46, 0x15, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x2e, 0x27, 0x15, 0x01, 0x14, 0x12, 0x0f, + 0x46, 0x25, 0x16, 0x0d, 0x46, 0x09, 0x12, 0x0b, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4d, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x43, 0x40, 0x40, 0x40, 0x43, 0x12, + 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, + 0x4e, 0x06, 0x09, 0x0c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, + 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, 0x42, 0x42, + 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x08, 0x0d, 0x0b, 0x12, + 0x1e, 0x51, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x06, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, + 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x24, 0x07, 0x44, 0x46, + 0x01, 0x0c, 0x0c, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, + 0x46, 0x16, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x30, 0x27, 0x16, 0x01, 0x15, 0x13, 0x0f, + 0x46, 0x24, 0x16, 0x0c, 0x46, 0x07, 0x13, 0x0a, 0x09, 0x07, 0x19, 0x0e, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4e, 0x01, 0x4e, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x13, + 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x09, 0x09, 0x4a, + 0x4e, 0x07, 0x09, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01, 0x42, 0x42, 0x03, 0x44, + 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, 0x42, 0x42, + 0x03, 0x44, 0x46, 0x07, 0x44, 0x54, 0x46, 0x05, 0x4a, 0x5e, 0x54, 0x4a, 0x09, 0x0d, 0x0b, 0x13, + 0x1f, 0x52, 0x29, 0x4e, 0x4a, 0x4a, 0x44, 0x42, 0x42, 0x07, 0x03, 0x0d, 0x03, 0x15, 0x44, 0x4e, + 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x15, 0x44, 0x4e, 0x23, 0x07, 0x44, 0x46, + 0x01, 0x0b, 0x0b, 0x0f, 0x19, 0x0f, 0x19, 0x07, 0x19, 0x01, 0x4a, 0x19, 0x01, 0x4a, 0x40, 0x40, + 0x46, 0x17, 0x11, 0x09, 0x46, 0x0f, 0x09, 0x01, 0x07, 0x31, 0x27, 0x17, 0x01, 0x15, 0x13, 0x0f, + 0x46, 0x23, 0x15, 0x0b, 0x46, 0x05, 0x13, 0x09, 0x09, 0x07, 0x19, 0x0d, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4e, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x40, 0x40, 0x40, 0x44, 0x15, + 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x49, + 0x4d, 0x09, 0x0a, 0x0b, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x41, 0x41, 0x04, 0x43, + 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, 0x41, 0x41, + 0x04, 0x43, 0x45, 0x07, 0x43, 0x53, 0x45, 0x06, 0x49, 0x5d, 0x53, 0x49, 0x0b, 0x0e, 0x0c, 0x15, + 0x21, 0x52, 0x2a, 0x4d, 0x49, 0x49, 0x43, 0x41, 0x41, 0x09, 0x04, 0x0e, 0x04, 0x16, 0x43, 0x4d, + 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x16, 0x43, 0x4d, 0x23, 0x07, 0x43, 0x45, + 0x02, 0x0b, 0x0b, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x49, 0x1a, 0x02, 0x49, 0x40, 0x40, + 0x45, 0x19, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x33, 0x27, 0x19, 0x02, 0x16, 0x14, 0x0f, + 0x45, 0x23, 0x15, 0x0b, 0x45, 0x04, 0x14, 0x09, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4f, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x17, + 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x48, + 0x4d, 0x0a, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x40, 0x40, 0x05, 0x42, + 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, 0x40, 0x40, + 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x07, 0x48, 0x5d, 0x52, 0x48, 0x0d, 0x0f, 0x0d, 0x17, + 0x22, 0x52, 0x2a, 0x4d, 0x48, 0x48, 0x42, 0x40, 0x40, 0x0a, 0x05, 0x0f, 0x05, 0x17, 0x42, 0x4d, + 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x17, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, + 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x48, 0x1a, 0x02, 0x48, 0x40, 0x40, + 0x45, 0x1a, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x35, 0x27, 0x1a, 0x02, 0x17, 0x15, 0x0f, + 0x45, 0x22, 0x15, 0x0a, 0x45, 0x02, 0x15, 0x08, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x50, 0x02, 0x4d, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x45, 0x40, 0x40, 0x40, 0x45, 0x19, + 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0a, 0x0a, 0x47, + 0x4d, 0x0b, 0x0a, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x00, 0x00, 0x05, 0x42, + 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, 0x00, 0x00, + 0x05, 0x42, 0x45, 0x07, 0x42, 0x52, 0x45, 0x08, 0x47, 0x5d, 0x52, 0x47, 0x0e, 0x10, 0x0d, 0x19, + 0x23, 0x52, 0x2a, 0x4d, 0x47, 0x47, 0x42, 0x00, 0x00, 0x0b, 0x05, 0x10, 0x05, 0x18, 0x42, 0x4d, + 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x18, 0x42, 0x4d, 0x22, 0x07, 0x42, 0x45, + 0x02, 0x0a, 0x0a, 0x0f, 0x1a, 0x0f, 0x1a, 0x07, 0x1a, 0x02, 0x47, 0x1a, 0x02, 0x47, 0x40, 0x40, + 0x45, 0x1b, 0x12, 0x0a, 0x45, 0x0f, 0x0a, 0x02, 0x07, 0x36, 0x27, 0x1b, 0x02, 0x18, 0x15, 0x0f, + 0x45, 0x22, 0x15, 0x0a, 0x45, 0x01, 0x15, 0x07, 0x0a, 0x07, 0x1a, 0x0d, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x51, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x40, 0x40, 0x40, 0x46, 0x1b, + 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x46, + 0x4c, 0x0c, 0x0b, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x01, 0x01, 0x06, 0x41, + 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, 0x01, 0x01, + 0x06, 0x41, 0x44, 0x07, 0x41, 0x51, 0x44, 0x09, 0x46, 0x5c, 0x51, 0x46, 0x10, 0x11, 0x0e, 0x1b, + 0x24, 0x53, 0x2b, 0x4c, 0x46, 0x46, 0x41, 0x01, 0x01, 0x0c, 0x06, 0x11, 0x06, 0x19, 0x41, 0x4c, + 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x19, 0x41, 0x4c, 0x21, 0x07, 0x41, 0x44, + 0x03, 0x09, 0x09, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x46, 0x1b, 0x03, 0x46, 0x40, 0x40, + 0x44, 0x1c, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x38, 0x27, 0x1c, 0x03, 0x19, 0x16, 0x0f, + 0x44, 0x21, 0x14, 0x09, 0x44, 0x40, 0x16, 0x06, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x52, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1d, + 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x45, + 0x4c, 0x0e, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x02, 0x02, 0x07, 0x40, + 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, 0x02, 0x02, + 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0a, 0x45, 0x5c, 0x50, 0x45, 0x11, 0x12, 0x0f, 0x1d, + 0x26, 0x53, 0x2b, 0x4c, 0x45, 0x45, 0x40, 0x02, 0x02, 0x0e, 0x07, 0x12, 0x07, 0x1a, 0x40, 0x4c, + 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1a, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, + 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x45, 0x1b, 0x03, 0x45, 0x40, 0x40, + 0x44, 0x1e, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x39, 0x27, 0x1e, 0x03, 0x1a, 0x17, 0x0f, + 0x44, 0x20, 0x14, 0x08, 0x44, 0x41, 0x17, 0x05, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x53, 0x03, 0x4c, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x47, 0x40, 0x40, 0x40, 0x47, 0x1f, + 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0b, 0x0b, 0x44, + 0x4c, 0x0f, 0x0b, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x03, 0x03, 0x03, 0x03, 0x07, 0x40, + 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, 0x03, 0x03, + 0x07, 0x40, 0x44, 0x07, 0x40, 0x50, 0x44, 0x0b, 0x44, 0x5c, 0x50, 0x44, 0x13, 0x13, 0x0f, 0x1f, + 0x27, 0x53, 0x2b, 0x4c, 0x44, 0x44, 0x40, 0x03, 0x03, 0x0f, 0x07, 0x13, 0x07, 0x1b, 0x40, 0x4c, + 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x1b, 0x40, 0x4c, 0x20, 0x07, 0x40, 0x44, + 0x03, 0x08, 0x08, 0x0f, 0x1b, 0x0f, 0x1b, 0x07, 0x1b, 0x03, 0x44, 0x1b, 0x03, 0x44, 0x40, 0x40, + 0x44, 0x1f, 0x13, 0x0b, 0x44, 0x0f, 0x0b, 0x03, 0x07, 0x3b, 0x27, 0x1f, 0x03, 0x1b, 0x17, 0x0f, + 0x44, 0x20, 0x14, 0x08, 0x44, 0x43, 0x17, 0x04, 0x0b, 0x07, 0x1b, 0x0c, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x54, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x40, 0x40, 0x40, 0x48, 0x21, + 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x43, + 0x4b, 0x10, 0x0c, 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x04, 0x04, 0x08, 0x00, + 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, 0x04, 0x04, + 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0c, 0x43, 0x5b, 0x4f, 0x43, 0x14, 0x14, 0x10, 0x21, + 0x28, 0x54, 0x2c, 0x4b, 0x43, 0x43, 0x00, 0x04, 0x04, 0x10, 0x08, 0x14, 0x08, 0x1c, 0x00, 0x4b, + 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x1c, 0x00, 0x4b, 0x1f, 0x07, 0x00, 0x43, + 0x04, 0x07, 0x07, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x43, 0x1c, 0x04, 0x43, 0x40, 0x40, + 0x43, 0x20, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3c, 0x27, 0x20, 0x04, 0x1c, 0x18, 0x0f, + 0x43, 0x1f, 0x13, 0x07, 0x43, 0x44, 0x18, 0x03, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x55, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x22, + 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x42, + 0x4b, 0x11, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x05, 0x05, 0x08, 0x00, + 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, 0x05, 0x05, + 0x08, 0x00, 0x43, 0x07, 0x00, 0x4f, 0x43, 0x0d, 0x42, 0x5b, 0x4f, 0x42, 0x16, 0x15, 0x10, 0x22, + 0x29, 0x54, 0x2c, 0x4b, 0x42, 0x42, 0x00, 0x05, 0x05, 0x11, 0x08, 0x15, 0x08, 0x1d, 0x00, 0x4b, + 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x1d, 0x00, 0x4b, 0x1e, 0x07, 0x00, 0x43, + 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x42, 0x1c, 0x04, 0x42, 0x40, 0x40, + 0x43, 0x21, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x21, 0x04, 0x1d, 0x18, 0x0f, + 0x43, 0x1e, 0x13, 0x06, 0x43, 0x46, 0x18, 0x02, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x56, 0x04, 0x4b, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x40, 0x40, 0x40, 0x49, 0x24, + 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0c, 0x0c, 0x41, + 0x4b, 0x13, 0x0c, 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x04, 0x04, 0x06, 0x06, 0x09, 0x01, + 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, 0x06, 0x06, + 0x09, 0x01, 0x43, 0x07, 0x01, 0x4e, 0x43, 0x0e, 0x41, 0x5b, 0x4e, 0x41, 0x18, 0x16, 0x11, 0x24, + 0x2b, 0x54, 0x2c, 0x4b, 0x41, 0x41, 0x01, 0x06, 0x06, 0x13, 0x09, 0x16, 0x09, 0x1e, 0x01, 0x4b, + 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x1e, 0x01, 0x4b, 0x1e, 0x07, 0x01, 0x43, + 0x04, 0x06, 0x06, 0x0f, 0x1c, 0x0f, 0x1c, 0x07, 0x1c, 0x04, 0x41, 0x1c, 0x04, 0x41, 0x40, 0x40, + 0x43, 0x23, 0x14, 0x0c, 0x43, 0x0f, 0x0c, 0x04, 0x07, 0x3e, 0x27, 0x23, 0x04, 0x1e, 0x19, 0x0f, + 0x43, 0x1e, 0x13, 0x06, 0x43, 0x48, 0x19, 0x01, 0x0c, 0x07, 0x1c, 0x0b, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x57, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x26, + 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x40, + 0x4a, 0x14, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x07, 0x07, 0x0a, 0x02, + 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, 0x07, 0x07, + 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x0f, 0x40, 0x5a, 0x4d, 0x40, 0x19, 0x17, 0x12, 0x26, + 0x2c, 0x55, 0x2d, 0x4a, 0x40, 0x40, 0x02, 0x07, 0x07, 0x14, 0x0a, 0x17, 0x0a, 0x1f, 0x02, 0x4a, + 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x1f, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, + 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x40, 0x1d, 0x05, 0x40, 0x40, 0x40, + 0x42, 0x24, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x24, 0x05, 0x1f, 0x1a, 0x0f, + 0x42, 0x1d, 0x12, 0x05, 0x42, 0x49, 0x1a, 0x00, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x58, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4a, 0x40, 0x40, 0x40, 0x4a, 0x28, + 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x00, + 0x4a, 0x15, 0x0d, 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x08, 0x08, 0x0a, 0x02, + 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, 0x08, 0x08, + 0x0a, 0x02, 0x42, 0x07, 0x02, 0x4d, 0x42, 0x10, 0x00, 0x5a, 0x4d, 0x00, 0x1b, 0x18, 0x12, 0x28, + 0x2d, 0x55, 0x2d, 0x4a, 0x00, 0x00, 0x02, 0x08, 0x08, 0x15, 0x0a, 0x18, 0x0a, 0x20, 0x02, 0x4a, + 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x20, 0x02, 0x4a, 0x1d, 0x07, 0x02, 0x42, + 0x05, 0x05, 0x05, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x00, 0x1d, 0x05, 0x00, 0x40, 0x40, + 0x42, 0x25, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x25, 0x05, 0x20, 0x1a, 0x0f, + 0x42, 0x1d, 0x12, 0x05, 0x42, 0x4b, 0x1a, 0x40, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x59, 0x05, 0x4a, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x40, 0x40, 0x40, 0x4b, 0x2a, + 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0d, 0x0d, 0x01, + 0x4a, 0x16, 0x0d, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x05, 0x05, 0x09, 0x09, 0x0b, 0x03, + 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, 0x09, 0x09, + 0x0b, 0x03, 0x42, 0x07, 0x03, 0x4c, 0x42, 0x11, 0x01, 0x5a, 0x4c, 0x01, 0x1c, 0x19, 0x13, 0x2a, + 0x2e, 0x55, 0x2d, 0x4a, 0x01, 0x01, 0x03, 0x09, 0x09, 0x16, 0x0b, 0x19, 0x0b, 0x21, 0x03, 0x4a, + 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x21, 0x03, 0x4a, 0x1c, 0x07, 0x03, 0x42, + 0x05, 0x04, 0x04, 0x0f, 0x1d, 0x0f, 0x1d, 0x07, 0x1d, 0x05, 0x01, 0x1d, 0x05, 0x01, 0x40, 0x40, + 0x42, 0x26, 0x15, 0x0d, 0x42, 0x0f, 0x0d, 0x05, 0x07, 0x3e, 0x27, 0x26, 0x05, 0x21, 0x1b, 0x0f, + 0x42, 0x1c, 0x12, 0x04, 0x42, 0x4c, 0x1b, 0x41, 0x0d, 0x07, 0x1d, 0x0a, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5a, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2c, + 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x02, + 0x49, 0x18, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0a, 0x0a, 0x0c, 0x04, + 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, 0x0a, 0x0a, + 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x12, 0x02, 0x59, 0x4b, 0x02, 0x1e, 0x1a, 0x14, 0x2c, + 0x30, 0x56, 0x2e, 0x49, 0x02, 0x02, 0x04, 0x0a, 0x0a, 0x18, 0x0c, 0x1a, 0x0c, 0x22, 0x04, 0x49, + 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x22, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, + 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x02, 0x1e, 0x06, 0x02, 0x40, 0x40, + 0x41, 0x28, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x28, 0x06, 0x22, 0x1c, 0x0f, + 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4e, 0x1c, 0x42, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5b, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x40, 0x4c, 0x2e, + 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x03, + 0x49, 0x19, 0x0e, 0x03, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0b, 0x0b, 0x0c, 0x04, + 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, 0x0b, 0x0b, + 0x0c, 0x04, 0x41, 0x07, 0x04, 0x4b, 0x41, 0x13, 0x03, 0x59, 0x4b, 0x03, 0x1f, 0x1b, 0x14, 0x2e, + 0x31, 0x56, 0x2e, 0x49, 0x03, 0x03, 0x04, 0x0b, 0x0b, 0x19, 0x0c, 0x1b, 0x0c, 0x23, 0x04, 0x49, + 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x23, 0x04, 0x49, 0x1b, 0x07, 0x04, 0x41, + 0x06, 0x03, 0x03, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x03, 0x1e, 0x06, 0x03, 0x40, 0x40, + 0x41, 0x29, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x29, 0x06, 0x23, 0x1c, 0x0f, + 0x41, 0x1b, 0x11, 0x03, 0x41, 0x4f, 0x1c, 0x43, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5c, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x4d, 0x30, + 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, + 0x49, 0x1a, 0x0e, 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, + 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, 0x0c, 0x0c, + 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x21, 0x1c, 0x15, 0x30, + 0x32, 0x56, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1a, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, + 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x24, 0x05, 0x49, 0x1a, 0x07, 0x05, 0x41, + 0x06, 0x02, 0x02, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, + 0x41, 0x2a, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2a, 0x06, 0x24, 0x1d, 0x0f, + 0x41, 0x1a, 0x11, 0x02, 0x41, 0x51, 0x1d, 0x44, 0x0e, 0x07, 0x1e, 0x09, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5d, 0x06, 0x49, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x31, + 0x06, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0e, 0x0e, 0x04, + 0x49, 0x1b, 0x0e, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x06, 0x06, 0x0c, 0x0c, 0x0d, 0x05, + 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, 0x0c, 0x0c, + 0x0d, 0x05, 0x41, 0x07, 0x05, 0x4a, 0x41, 0x14, 0x04, 0x59, 0x4a, 0x04, 0x22, 0x1c, 0x15, 0x31, + 0x33, 0x57, 0x2e, 0x49, 0x04, 0x04, 0x05, 0x0c, 0x0c, 0x1b, 0x0d, 0x1c, 0x0d, 0x24, 0x05, 0x49, + 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x24, 0x05, 0x49, 0x19, 0x07, 0x05, 0x41, + 0x06, 0x01, 0x01, 0x0f, 0x1e, 0x0f, 0x1e, 0x07, 0x1e, 0x06, 0x04, 0x1e, 0x06, 0x04, 0x40, 0x40, + 0x41, 0x2b, 0x16, 0x0e, 0x41, 0x0f, 0x0e, 0x06, 0x07, 0x3e, 0x27, 0x2b, 0x06, 0x24, 0x1d, 0x0f, + 0x41, 0x19, 0x10, 0x01, 0x41, 0x53, 0x1d, 0x45, 0x0e, 0x07, 0x1e, 0x08, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5d, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x4e, 0x33, + 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x05, + 0x48, 0x1d, 0x0f, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0d, 0x0d, 0x0e, 0x06, + 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, 0x0d, 0x0d, + 0x0e, 0x06, 0x40, 0x07, 0x06, 0x49, 0x40, 0x15, 0x05, 0x58, 0x49, 0x05, 0x24, 0x1d, 0x16, 0x33, + 0x35, 0x57, 0x2f, 0x48, 0x05, 0x05, 0x06, 0x0d, 0x0d, 0x1d, 0x0e, 0x1d, 0x0e, 0x25, 0x06, 0x48, + 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x25, 0x06, 0x48, 0x19, 0x07, 0x06, 0x40, + 0x07, 0x01, 0x01, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x05, 0x1f, 0x07, 0x05, 0x40, 0x40, + 0x40, 0x2d, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2d, 0x07, 0x25, 0x1e, 0x0f, + 0x40, 0x19, 0x10, 0x01, 0x40, 0x54, 0x1e, 0x45, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5e, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x35, + 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x06, + 0x48, 0x1e, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0e, 0x0e, 0x0f, 0x07, + 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, 0x0e, 0x0e, + 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x16, 0x06, 0x58, 0x48, 0x06, 0x26, 0x1e, 0x17, 0x35, + 0x36, 0x57, 0x2f, 0x48, 0x06, 0x06, 0x07, 0x0e, 0x0e, 0x1e, 0x0f, 0x1e, 0x0f, 0x26, 0x07, 0x48, + 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x26, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, + 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x06, 0x1f, 0x07, 0x06, 0x40, 0x40, + 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2e, 0x07, 0x26, 0x1f, 0x0f, + 0x40, 0x18, 0x10, 0x00, 0x40, 0x56, 0x1f, 0x46, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5f, 0x07, 0x48, 0x58, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x4f, 0x37, + 0x07, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x0f, 0x0f, 0x07, + 0x48, 0x1f, 0x0f, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x07, + 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, 0x0f, 0x0f, + 0x0f, 0x07, 0x40, 0x07, 0x07, 0x48, 0x40, 0x17, 0x07, 0x58, 0x48, 0x07, 0x27, 0x1f, 0x17, 0x37, + 0x37, 0x57, 0x2f, 0x48, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x1f, 0x0f, 0x1f, 0x0f, 0x27, 0x07, 0x48, + 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x27, 0x07, 0x48, 0x18, 0x07, 0x07, 0x40, + 0x07, 0x00, 0x00, 0x0f, 0x1f, 0x0f, 0x1f, 0x07, 0x1f, 0x07, 0x07, 0x1f, 0x07, 0x07, 0x40, 0x40, + 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x07, 0x07, 0x3e, 0x27, 0x2f, 0x07, 0x27, 0x1f, 0x0f, + 0x40, 0x18, 0x10, 0x00, 0x40, 0x57, 0x1f, 0x47, 0x0f, 0x07, 0x1f, 0x08, 0x0f, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x07, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x48, 0x40, 0x40, 0x40, 0x0f, + 0x48, 0x68, 0x60, 0x40, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x50, 0x40, 0x60, 0x07, + 0x68, 0x27, 0x48, 0x17, 0x40, 0x50, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x60, 0x60, + 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, 0x58, 0x60, + 0x60, 0x60, 0x68, 0x68, 0x58, 0x68, 0x60, 0x60, 0x60, 0x68, 0x68, 0x68, 0x60, 0x50, 0x48, 0x50, + 0x07, 0x50, 0x58, 0x40, 0x48, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x07, 0x1f, 0x17, 0x50, + 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, + 0x07, 0x48, 0x48, 0x48, 0x07, 0x48, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, + 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x07, + 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x07, 0x1f, 0x48, 0x17, 0x48, 0x40, 0x48, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x07, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, + 0x47, 0x66, 0x5f, 0x00, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x4f, 0x00, 0x5e, 0x07, + 0x67, 0x27, 0x47, 0x17, 0x40, 0x4f, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x5e, 0x5f, + 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, 0x57, 0x5f, + 0x5e, 0x5f, 0x66, 0x66, 0x57, 0x67, 0x5f, 0x5e, 0x5f, 0x67, 0x67, 0x66, 0x5e, 0x4f, 0x47, 0x4f, + 0x08, 0x4f, 0x56, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x07, 0x1f, 0x17, 0x4f, + 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, + 0x07, 0x47, 0x47, 0x47, 0x08, 0x47, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, + 0x40, 0x2f, 0x2f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x08, + 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1f, 0x47, 0x17, 0x46, 0x00, 0x47, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, + 0x47, 0x64, 0x5e, 0x01, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5d, 0x07, + 0x66, 0x27, 0x46, 0x17, 0x40, 0x4f, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x5d, 0x5e, + 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, 0x56, 0x5e, + 0x5d, 0x5e, 0x65, 0x64, 0x56, 0x66, 0x5e, 0x5c, 0x5e, 0x66, 0x66, 0x65, 0x5d, 0x4e, 0x46, 0x4e, + 0x09, 0x4f, 0x54, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x07, 0x1f, 0x16, 0x4f, + 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, + 0x07, 0x46, 0x46, 0x46, 0x09, 0x46, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, + 0x40, 0x2e, 0x2e, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, + 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x46, 0x17, 0x45, 0x01, 0x46, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x27, 0x40, 0x47, 0x40, 0x40, 0x40, 0x0f, + 0x47, 0x63, 0x5d, 0x01, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x4e, 0x00, 0x5c, 0x07, + 0x65, 0x27, 0x45, 0x17, 0x40, 0x4f, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x5c, 0x5d, + 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, 0x56, 0x5d, + 0x5c, 0x5d, 0x64, 0x63, 0x56, 0x65, 0x5d, 0x5b, 0x5d, 0x65, 0x65, 0x64, 0x5c, 0x4d, 0x46, 0x4d, + 0x09, 0x4f, 0x52, 0x40, 0x48, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x07, 0x1f, 0x16, 0x4f, + 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, + 0x07, 0x46, 0x46, 0x45, 0x09, 0x45, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, + 0x40, 0x2d, 0x2d, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x08, + 0x07, 0x3d, 0x1f, 0x17, 0x40, 0x17, 0x08, 0x1e, 0x45, 0x17, 0x44, 0x01, 0x45, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x05, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, + 0x46, 0x61, 0x5c, 0x02, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x4d, 0x01, 0x5b, 0x07, + 0x64, 0x27, 0x44, 0x16, 0x40, 0x4e, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x5b, 0x5c, + 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, 0x55, 0x5c, + 0x5b, 0x5c, 0x63, 0x61, 0x55, 0x64, 0x5c, 0x59, 0x5c, 0x64, 0x64, 0x63, 0x5b, 0x4c, 0x45, 0x4c, + 0x0a, 0x4e, 0x50, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x07, 0x1e, 0x15, 0x4e, + 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, + 0x07, 0x45, 0x45, 0x44, 0x0a, 0x44, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, + 0x40, 0x2c, 0x2c, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x09, + 0x06, 0x3c, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1d, 0x44, 0x16, 0x43, 0x02, 0x44, 0x16, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x04, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, + 0x46, 0x60, 0x5b, 0x03, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x59, 0x07, + 0x63, 0x27, 0x43, 0x16, 0x40, 0x4e, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x59, 0x5b, + 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, 0x54, 0x5b, + 0x59, 0x5b, 0x61, 0x60, 0x54, 0x63, 0x5b, 0x58, 0x5b, 0x63, 0x63, 0x61, 0x59, 0x4b, 0x44, 0x4b, + 0x0b, 0x4e, 0x4e, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x07, 0x1e, 0x14, 0x4e, + 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, + 0x07, 0x44, 0x44, 0x43, 0x0b, 0x43, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, + 0x40, 0x2b, 0x2b, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, + 0x06, 0x3b, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x43, 0x16, 0x41, 0x03, 0x43, 0x16, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x04, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x27, 0x40, 0x46, 0x40, 0x40, 0x40, 0x0f, + 0x46, 0x5e, 0x5a, 0x03, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x4c, 0x01, 0x58, 0x07, + 0x62, 0x27, 0x42, 0x16, 0x40, 0x4e, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x58, 0x5a, + 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, 0x54, 0x5a, + 0x58, 0x5a, 0x60, 0x5e, 0x54, 0x62, 0x5a, 0x56, 0x5a, 0x62, 0x62, 0x60, 0x58, 0x4a, 0x44, 0x4a, + 0x0b, 0x4e, 0x4c, 0x40, 0x48, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x07, 0x1e, 0x14, 0x4e, + 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, + 0x07, 0x44, 0x44, 0x42, 0x0b, 0x42, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, + 0x40, 0x2a, 0x2a, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x09, + 0x06, 0x3a, 0x1e, 0x16, 0x40, 0x16, 0x09, 0x1c, 0x42, 0x16, 0x40, 0x03, 0x42, 0x16, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x03, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, + 0x45, 0x5d, 0x59, 0x04, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x57, 0x07, + 0x61, 0x27, 0x41, 0x15, 0x40, 0x4d, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x57, 0x59, + 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, 0x53, 0x59, + 0x57, 0x59, 0x5f, 0x5d, 0x53, 0x61, 0x59, 0x55, 0x59, 0x61, 0x61, 0x5f, 0x57, 0x49, 0x43, 0x49, + 0x0c, 0x4d, 0x4a, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x07, 0x1d, 0x13, 0x4d, + 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, + 0x07, 0x43, 0x43, 0x41, 0x0c, 0x41, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, + 0x40, 0x29, 0x29, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, + 0x05, 0x39, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1b, 0x41, 0x15, 0x00, 0x04, 0x41, 0x15, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x02, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, + 0x45, 0x5b, 0x58, 0x04, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x4b, 0x02, 0x56, 0x07, + 0x60, 0x27, 0x40, 0x15, 0x40, 0x4d, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x56, 0x58, + 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, 0x53, 0x58, + 0x56, 0x58, 0x5e, 0x5b, 0x53, 0x60, 0x58, 0x53, 0x58, 0x60, 0x60, 0x5e, 0x56, 0x48, 0x43, 0x48, + 0x0c, 0x4d, 0x49, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x07, 0x1d, 0x12, 0x4d, + 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, + 0x07, 0x43, 0x43, 0x40, 0x0c, 0x40, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, + 0x40, 0x28, 0x28, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x0a, + 0x05, 0x38, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x40, 0x15, 0x01, 0x04, 0x40, 0x15, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x02, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x27, 0x40, 0x45, 0x40, 0x40, 0x40, 0x0f, + 0x45, 0x59, 0x57, 0x05, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x4a, 0x02, 0x54, 0x07, + 0x5f, 0x27, 0x00, 0x15, 0x40, 0x4d, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x54, 0x57, + 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, 0x52, 0x57, + 0x54, 0x57, 0x5c, 0x59, 0x52, 0x5f, 0x57, 0x51, 0x57, 0x5f, 0x5f, 0x5c, 0x54, 0x47, 0x42, 0x47, + 0x0d, 0x4d, 0x47, 0x40, 0x48, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x07, 0x1d, 0x12, 0x4d, + 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, + 0x07, 0x42, 0x42, 0x00, 0x0d, 0x00, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, + 0x40, 0x27, 0x27, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x0a, + 0x05, 0x37, 0x1d, 0x15, 0x40, 0x15, 0x0a, 0x1a, 0x00, 0x15, 0x03, 0x05, 0x00, 0x15, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x01, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, + 0x44, 0x58, 0x56, 0x06, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x53, 0x07, + 0x5e, 0x27, 0x01, 0x14, 0x40, 0x4c, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x53, 0x56, + 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, 0x51, 0x56, + 0x53, 0x56, 0x5b, 0x58, 0x51, 0x5e, 0x56, 0x50, 0x56, 0x5e, 0x5e, 0x5b, 0x53, 0x46, 0x41, 0x46, + 0x0e, 0x4c, 0x45, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x07, 0x1c, 0x11, 0x4c, + 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, + 0x07, 0x41, 0x41, 0x01, 0x0e, 0x01, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, + 0x40, 0x26, 0x26, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, + 0x04, 0x36, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x01, 0x14, 0x04, 0x06, 0x01, 0x14, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x01, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, + 0x44, 0x56, 0x55, 0x06, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x49, 0x03, 0x52, 0x07, + 0x5d, 0x27, 0x02, 0x14, 0x40, 0x4c, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x52, 0x55, + 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, 0x51, 0x55, + 0x52, 0x55, 0x5a, 0x56, 0x51, 0x5d, 0x55, 0x4e, 0x55, 0x5d, 0x5d, 0x5a, 0x52, 0x45, 0x41, 0x45, + 0x0e, 0x4c, 0x43, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x07, 0x1c, 0x11, 0x4c, + 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, + 0x07, 0x41, 0x41, 0x02, 0x0e, 0x02, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, + 0x40, 0x25, 0x25, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x0b, + 0x04, 0x35, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x19, 0x02, 0x14, 0x05, 0x06, 0x02, 0x14, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x27, 0x40, 0x44, 0x40, 0x40, 0x40, 0x0f, + 0x44, 0x55, 0x54, 0x07, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x48, 0x03, 0x51, 0x07, + 0x5c, 0x27, 0x03, 0x14, 0x40, 0x4c, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x51, 0x54, + 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, 0x50, 0x54, + 0x51, 0x54, 0x59, 0x55, 0x50, 0x5c, 0x54, 0x4d, 0x54, 0x5c, 0x5c, 0x59, 0x51, 0x44, 0x40, 0x44, + 0x0f, 0x4c, 0x41, 0x40, 0x48, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x07, 0x1c, 0x10, 0x4c, + 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, + 0x07, 0x40, 0x40, 0x03, 0x0f, 0x03, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, + 0x40, 0x24, 0x24, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x0b, + 0x04, 0x34, 0x1c, 0x14, 0x40, 0x14, 0x0b, 0x18, 0x03, 0x14, 0x06, 0x07, 0x03, 0x14, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x40, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, + 0x43, 0x53, 0x53, 0x08, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4f, 0x07, + 0x5b, 0x27, 0x04, 0x13, 0x40, 0x4b, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x4f, 0x53, + 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, 0x4f, 0x53, + 0x4f, 0x53, 0x57, 0x53, 0x4f, 0x5b, 0x53, 0x4b, 0x53, 0x5b, 0x5b, 0x57, 0x4f, 0x43, 0x00, 0x43, + 0x10, 0x4b, 0x00, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x07, 0x1b, 0x0f, 0x4b, + 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, + 0x07, 0x00, 0x00, 0x04, 0x10, 0x04, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, + 0x40, 0x23, 0x23, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, + 0x03, 0x33, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x04, 0x13, 0x08, 0x08, 0x04, 0x13, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x40, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, + 0x43, 0x52, 0x52, 0x08, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x47, 0x04, 0x4e, 0x07, + 0x5a, 0x27, 0x05, 0x13, 0x40, 0x4b, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x4e, 0x52, + 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, 0x4f, 0x52, + 0x4e, 0x52, 0x56, 0x52, 0x4f, 0x5a, 0x52, 0x4a, 0x52, 0x5a, 0x5a, 0x56, 0x4e, 0x42, 0x00, 0x42, + 0x10, 0x4b, 0x02, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x07, 0x1b, 0x0f, 0x4b, + 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, + 0x07, 0x00, 0x00, 0x05, 0x10, 0x05, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, + 0x40, 0x22, 0x22, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x0c, + 0x03, 0x32, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x17, 0x05, 0x13, 0x09, 0x08, 0x05, 0x13, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x41, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, + 0x43, 0x50, 0x51, 0x09, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x46, 0x04, 0x4d, 0x07, + 0x59, 0x27, 0x06, 0x13, 0x40, 0x4b, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4d, 0x51, + 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, 0x4e, 0x51, + 0x4d, 0x51, 0x55, 0x50, 0x4e, 0x59, 0x51, 0x48, 0x51, 0x59, 0x59, 0x55, 0x4d, 0x41, 0x01, 0x41, + 0x11, 0x4b, 0x04, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x07, 0x1b, 0x0e, 0x4b, + 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, + 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, + 0x40, 0x21, 0x21, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, + 0x03, 0x31, 0x1b, 0x13, 0x40, 0x13, 0x0c, 0x16, 0x06, 0x13, 0x0a, 0x09, 0x06, 0x13, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x42, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x43, 0x40, 0x40, 0x40, 0x0f, + 0x43, 0x4f, 0x51, 0x09, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x46, 0x04, 0x4c, 0x07, + 0x59, 0x27, 0x06, 0x12, 0x40, 0x4b, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x4c, 0x51, + 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, 0x4e, 0x51, + 0x4c, 0x51, 0x54, 0x4f, 0x4e, 0x59, 0x51, 0x47, 0x51, 0x59, 0x59, 0x54, 0x4c, 0x41, 0x01, 0x41, + 0x11, 0x4b, 0x05, 0x40, 0x48, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x07, 0x1a, 0x0d, 0x4b, + 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, + 0x07, 0x01, 0x01, 0x06, 0x11, 0x06, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, + 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x0c, + 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0c, 0x15, 0x06, 0x12, 0x0b, 0x09, 0x06, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x42, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, + 0x42, 0x4d, 0x50, 0x0a, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x45, 0x05, 0x4a, 0x07, + 0x58, 0x27, 0x07, 0x12, 0x40, 0x4a, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x4a, 0x50, + 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, 0x4d, 0x50, + 0x4a, 0x50, 0x52, 0x4d, 0x4d, 0x58, 0x50, 0x45, 0x50, 0x58, 0x58, 0x52, 0x4a, 0x40, 0x02, 0x40, + 0x12, 0x4a, 0x07, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x07, 0x1a, 0x0d, 0x4a, + 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, + 0x07, 0x02, 0x02, 0x07, 0x12, 0x07, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, + 0x40, 0x20, 0x20, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0d, + 0x02, 0x30, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x15, 0x07, 0x12, 0x0d, 0x0a, 0x07, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x43, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, + 0x42, 0x4b, 0x4f, 0x0b, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x49, 0x07, + 0x57, 0x27, 0x08, 0x12, 0x40, 0x4a, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x49, 0x4f, + 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, 0x4c, 0x4f, + 0x49, 0x4f, 0x51, 0x4b, 0x4c, 0x57, 0x4f, 0x43, 0x4f, 0x57, 0x57, 0x51, 0x49, 0x00, 0x03, 0x00, + 0x13, 0x4a, 0x09, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x07, 0x1a, 0x0c, 0x4a, + 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, + 0x07, 0x03, 0x03, 0x08, 0x13, 0x08, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, + 0x40, 0x1f, 0x1f, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, + 0x02, 0x2f, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x08, 0x12, 0x0e, 0x0b, 0x08, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x43, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x27, 0x40, 0x42, 0x40, 0x40, 0x40, 0x0f, + 0x42, 0x4a, 0x4e, 0x0b, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x44, 0x05, 0x48, 0x07, + 0x56, 0x27, 0x09, 0x12, 0x40, 0x4a, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x48, 0x4e, + 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, 0x4c, 0x4e, + 0x48, 0x4e, 0x50, 0x4a, 0x4c, 0x56, 0x4e, 0x42, 0x4e, 0x56, 0x56, 0x50, 0x48, 0x01, 0x03, 0x01, + 0x13, 0x4a, 0x0b, 0x40, 0x48, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x07, 0x1a, 0x0c, 0x4a, + 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, + 0x07, 0x03, 0x03, 0x09, 0x13, 0x09, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, + 0x40, 0x1e, 0x1e, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0d, + 0x02, 0x2e, 0x1a, 0x12, 0x40, 0x12, 0x0d, 0x14, 0x09, 0x12, 0x0f, 0x0b, 0x09, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x44, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, + 0x41, 0x48, 0x4d, 0x0c, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x43, 0x06, 0x47, 0x07, + 0x55, 0x27, 0x0a, 0x11, 0x40, 0x49, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x47, 0x4d, + 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, 0x4b, 0x4d, + 0x47, 0x4d, 0x4f, 0x48, 0x4b, 0x55, 0x4d, 0x40, 0x4d, 0x55, 0x55, 0x4f, 0x47, 0x02, 0x04, 0x02, + 0x14, 0x49, 0x0d, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x07, 0x19, 0x0b, 0x49, + 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, + 0x07, 0x04, 0x04, 0x0a, 0x14, 0x0a, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, + 0x40, 0x1d, 0x1d, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0e, + 0x01, 0x2d, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x13, 0x0a, 0x11, 0x10, 0x0c, 0x0a, 0x11, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x45, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, + 0x41, 0x47, 0x4c, 0x0d, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x42, 0x06, 0x45, 0x07, + 0x54, 0x27, 0x0b, 0x11, 0x40, 0x49, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x45, 0x4c, + 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, 0x4a, 0x4c, + 0x45, 0x4c, 0x4d, 0x47, 0x4a, 0x54, 0x4c, 0x00, 0x4c, 0x54, 0x54, 0x4d, 0x45, 0x03, 0x05, 0x03, + 0x15, 0x49, 0x0f, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x07, 0x19, 0x0a, 0x49, + 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, + 0x07, 0x05, 0x05, 0x0b, 0x15, 0x0b, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, + 0x40, 0x1c, 0x1c, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, + 0x01, 0x2c, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0b, 0x11, 0x12, 0x0d, 0x0b, 0x11, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x45, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x27, 0x40, 0x41, 0x40, 0x40, 0x40, 0x0f, + 0x41, 0x45, 0x4b, 0x0d, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x42, 0x06, 0x44, 0x07, + 0x53, 0x27, 0x0c, 0x11, 0x40, 0x49, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x44, 0x4b, + 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, 0x4a, 0x4b, + 0x44, 0x4b, 0x4c, 0x45, 0x4a, 0x53, 0x4b, 0x02, 0x4b, 0x53, 0x53, 0x4c, 0x44, 0x04, 0x05, 0x04, + 0x15, 0x49, 0x11, 0x40, 0x48, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x07, 0x19, 0x0a, 0x49, + 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, + 0x07, 0x05, 0x05, 0x0c, 0x15, 0x0c, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, + 0x40, 0x1b, 0x1b, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0e, + 0x01, 0x2b, 0x19, 0x11, 0x40, 0x11, 0x0e, 0x12, 0x0c, 0x11, 0x13, 0x0d, 0x0c, 0x11, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x46, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, + 0x40, 0x44, 0x4a, 0x0e, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x41, 0x07, 0x43, 0x07, + 0x52, 0x27, 0x0d, 0x10, 0x40, 0x48, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x43, 0x4a, + 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, 0x49, 0x4a, + 0x43, 0x4a, 0x4b, 0x44, 0x49, 0x52, 0x4a, 0x03, 0x4a, 0x52, 0x52, 0x4b, 0x43, 0x05, 0x06, 0x05, + 0x16, 0x48, 0x13, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x07, 0x18, 0x09, 0x48, + 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, + 0x07, 0x06, 0x06, 0x0d, 0x16, 0x0d, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, + 0x40, 0x1a, 0x1a, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, + 0x00, 0x2a, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x11, 0x0d, 0x10, 0x14, 0x0e, 0x0d, 0x10, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x47, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, + 0x40, 0x42, 0x49, 0x0e, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x41, 0x07, 0x42, 0x07, + 0x51, 0x27, 0x0e, 0x10, 0x40, 0x48, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x42, 0x49, + 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, 0x49, 0x49, + 0x42, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x49, 0x05, 0x49, 0x51, 0x51, 0x4a, 0x42, 0x06, 0x06, 0x06, + 0x16, 0x48, 0x14, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x07, 0x18, 0x08, 0x48, + 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, + 0x07, 0x06, 0x06, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, + 0x40, 0x19, 0x19, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0f, + 0x00, 0x29, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x47, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x40, 0x0f, + 0x40, 0x40, 0x48, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x40, 0x07, 0x40, 0x07, + 0x50, 0x27, 0x0f, 0x10, 0x40, 0x48, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, + 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, + 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x48, 0x07, 0x48, 0x50, 0x50, 0x48, 0x40, 0x07, 0x07, 0x07, + 0x17, 0x48, 0x16, 0x40, 0x48, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x07, 0x18, 0x08, 0x48, + 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, + 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, + 0x40, 0x18, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, + 0x00, 0x28, 0x18, 0x10, 0x40, 0x10, 0x0f, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x48, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, + 0x00, 0x00, 0x47, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x00, 0x08, 0x00, 0x07, + 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x47, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, + 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, + 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x47, 0x08, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0x08, 0x08, 0x08, + 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x07, 0x17, 0x07, 0x47, + 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, + 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, + 0x40, 0x17, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, + 0x40, 0x27, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x48, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, + 0x00, 0x02, 0x46, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x00, 0x08, 0x01, 0x07, + 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x47, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x01, 0x46, + 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, 0x47, 0x46, + 0x01, 0x46, 0x46, 0x02, 0x47, 0x4e, 0x46, 0x0a, 0x46, 0x4e, 0x4e, 0x46, 0x01, 0x09, 0x08, 0x09, + 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x07, 0x17, 0x07, 0x47, + 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, + 0x07, 0x08, 0x08, 0x11, 0x18, 0x11, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, + 0x40, 0x16, 0x16, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, + 0x40, 0x26, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0f, 0x11, 0x0f, 0x19, 0x10, 0x11, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x49, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x27, 0x40, 0x00, 0x40, 0x40, 0x40, 0x0f, + 0x00, 0x03, 0x45, 0x11, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x01, 0x08, 0x02, 0x07, + 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x47, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x02, 0x45, + 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, 0x46, 0x45, + 0x02, 0x45, 0x45, 0x03, 0x46, 0x4d, 0x45, 0x0b, 0x45, 0x4d, 0x4d, 0x45, 0x02, 0x0a, 0x09, 0x0a, + 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x07, 0x17, 0x06, 0x47, + 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, + 0x07, 0x09, 0x09, 0x12, 0x19, 0x12, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, + 0x40, 0x15, 0x15, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x10, + 0x40, 0x25, 0x17, 0x0f, 0x40, 0x0f, 0x10, 0x0e, 0x12, 0x0f, 0x1a, 0x11, 0x12, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4a, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, + 0x01, 0x05, 0x44, 0x12, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x02, 0x09, 0x04, 0x07, + 0x4c, 0x27, 0x13, 0x0e, 0x40, 0x46, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x04, 0x44, + 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, 0x45, 0x44, + 0x04, 0x44, 0x43, 0x05, 0x45, 0x4c, 0x44, 0x0d, 0x44, 0x4c, 0x4c, 0x43, 0x04, 0x0b, 0x0a, 0x0b, + 0x1a, 0x46, 0x1e, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x07, 0x16, 0x05, 0x46, + 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, + 0x07, 0x0a, 0x0a, 0x13, 0x1a, 0x13, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, + 0x40, 0x14, 0x14, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, + 0x41, 0x24, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x13, 0x0e, 0x1c, 0x12, 0x13, 0x0e, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4a, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, + 0x01, 0x06, 0x43, 0x12, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x02, 0x09, 0x05, 0x07, + 0x4b, 0x27, 0x14, 0x0e, 0x40, 0x46, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x05, 0x43, + 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, 0x45, 0x43, + 0x05, 0x43, 0x42, 0x06, 0x45, 0x4b, 0x43, 0x0e, 0x43, 0x4b, 0x4b, 0x42, 0x05, 0x0c, 0x0a, 0x0c, + 0x1a, 0x46, 0x20, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x07, 0x16, 0x05, 0x46, + 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, + 0x07, 0x0a, 0x0a, 0x14, 0x1a, 0x14, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, + 0x40, 0x13, 0x13, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x11, + 0x41, 0x23, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0d, 0x14, 0x0e, 0x1d, 0x12, 0x14, 0x0e, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4b, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, + 0x01, 0x08, 0x42, 0x13, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x03, 0x09, 0x06, 0x07, + 0x4a, 0x27, 0x15, 0x0e, 0x40, 0x46, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x06, 0x42, + 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, 0x44, 0x42, + 0x06, 0x42, 0x41, 0x08, 0x44, 0x4a, 0x42, 0x10, 0x42, 0x4a, 0x4a, 0x41, 0x06, 0x0d, 0x0b, 0x0d, + 0x1b, 0x46, 0x22, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x07, 0x16, 0x04, 0x46, + 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, + 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, + 0x40, 0x12, 0x12, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, + 0x41, 0x22, 0x16, 0x0e, 0x40, 0x0e, 0x11, 0x0c, 0x15, 0x0e, 0x1e, 0x13, 0x15, 0x0e, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4c, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x01, 0x40, 0x40, 0x40, 0x0f, + 0x01, 0x09, 0x42, 0x13, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x03, 0x09, 0x07, 0x07, + 0x4a, 0x27, 0x15, 0x0d, 0x40, 0x46, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x07, 0x42, + 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, 0x44, 0x42, + 0x07, 0x42, 0x40, 0x09, 0x44, 0x4a, 0x42, 0x11, 0x42, 0x4a, 0x4a, 0x40, 0x07, 0x0d, 0x0b, 0x0d, + 0x1b, 0x46, 0x23, 0x40, 0x48, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x07, 0x15, 0x03, 0x46, + 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, + 0x07, 0x0b, 0x0b, 0x15, 0x1b, 0x15, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, + 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x11, + 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x11, 0x0b, 0x15, 0x0d, 0x1f, 0x13, 0x15, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4c, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, + 0x02, 0x0b, 0x41, 0x14, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x04, 0x0a, 0x09, 0x07, + 0x49, 0x27, 0x16, 0x0d, 0x40, 0x45, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x09, 0x41, + 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, 0x43, 0x41, + 0x09, 0x41, 0x01, 0x0b, 0x43, 0x49, 0x41, 0x13, 0x41, 0x49, 0x49, 0x01, 0x09, 0x0e, 0x0c, 0x0e, + 0x1c, 0x45, 0x25, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x07, 0x15, 0x03, 0x45, + 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, + 0x07, 0x0c, 0x0c, 0x16, 0x1c, 0x16, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, + 0x40, 0x11, 0x11, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x12, + 0x42, 0x21, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0b, 0x16, 0x0d, 0x21, 0x14, 0x16, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4d, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, + 0x02, 0x0d, 0x40, 0x15, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0a, 0x07, + 0x48, 0x27, 0x17, 0x0d, 0x40, 0x45, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x0a, 0x40, + 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, 0x42, 0x40, + 0x0a, 0x40, 0x02, 0x0d, 0x42, 0x48, 0x40, 0x15, 0x40, 0x48, 0x48, 0x02, 0x0a, 0x0f, 0x0d, 0x0f, + 0x1d, 0x45, 0x27, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x07, 0x15, 0x02, 0x45, + 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, + 0x07, 0x0d, 0x0d, 0x17, 0x1d, 0x17, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, + 0x40, 0x10, 0x10, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, + 0x42, 0x20, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x17, 0x0d, 0x22, 0x15, 0x17, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4d, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x27, 0x40, 0x02, 0x40, 0x40, 0x40, 0x0f, + 0x02, 0x0e, 0x00, 0x15, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x05, 0x0a, 0x0b, 0x07, + 0x47, 0x27, 0x18, 0x0d, 0x40, 0x45, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x0b, 0x00, + 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, 0x42, 0x00, + 0x0b, 0x00, 0x03, 0x0e, 0x42, 0x47, 0x00, 0x16, 0x00, 0x47, 0x47, 0x03, 0x0b, 0x10, 0x0d, 0x10, + 0x1d, 0x45, 0x29, 0x40, 0x48, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x07, 0x15, 0x02, 0x45, + 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, + 0x07, 0x0d, 0x0d, 0x18, 0x1d, 0x18, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, + 0x40, 0x0f, 0x0f, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x12, + 0x42, 0x1f, 0x15, 0x0d, 0x40, 0x0d, 0x12, 0x0a, 0x18, 0x0d, 0x23, 0x15, 0x18, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, + 0x03, 0x10, 0x01, 0x16, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x06, 0x0b, 0x0c, 0x07, + 0x46, 0x27, 0x19, 0x0c, 0x40, 0x44, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x0c, 0x01, + 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, 0x41, 0x01, + 0x0c, 0x01, 0x04, 0x10, 0x41, 0x46, 0x01, 0x18, 0x01, 0x46, 0x46, 0x04, 0x0c, 0x11, 0x0e, 0x11, + 0x1e, 0x44, 0x2b, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x07, 0x14, 0x01, 0x44, + 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, + 0x07, 0x0e, 0x0e, 0x19, 0x1e, 0x19, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, + 0x40, 0x0e, 0x0e, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x13, + 0x43, 0x1e, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x09, 0x19, 0x0c, 0x24, 0x16, 0x19, 0x0c, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4f, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, + 0x03, 0x11, 0x02, 0x17, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0e, 0x07, + 0x45, 0x27, 0x1a, 0x0c, 0x40, 0x44, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x0e, 0x02, + 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, 0x40, 0x02, + 0x0e, 0x02, 0x06, 0x11, 0x40, 0x45, 0x02, 0x19, 0x02, 0x45, 0x45, 0x06, 0x0e, 0x12, 0x0f, 0x12, + 0x1f, 0x44, 0x2d, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, + 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, + 0x07, 0x0f, 0x0f, 0x1a, 0x1f, 0x1a, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, + 0x40, 0x0d, 0x0d, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, + 0x43, 0x1d, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1a, 0x0c, 0x26, 0x17, 0x1a, 0x0c, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x4f, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x27, 0x40, 0x03, 0x40, 0x40, 0x40, 0x0f, + 0x03, 0x13, 0x03, 0x17, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x07, 0x0b, 0x0f, 0x07, + 0x44, 0x27, 0x1b, 0x0c, 0x40, 0x44, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x0f, 0x03, + 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, 0x40, 0x03, + 0x0f, 0x03, 0x07, 0x13, 0x40, 0x44, 0x03, 0x1b, 0x03, 0x44, 0x44, 0x07, 0x0f, 0x13, 0x0f, 0x13, + 0x1f, 0x44, 0x2f, 0x40, 0x48, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, + 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, + 0x07, 0x0f, 0x0f, 0x1b, 0x1f, 0x1b, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, + 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x13, + 0x43, 0x1c, 0x14, 0x0c, 0x40, 0x0c, 0x13, 0x08, 0x1b, 0x0c, 0x27, 0x17, 0x1b, 0x0c, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x50, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, + 0x04, 0x14, 0x04, 0x18, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x10, 0x07, + 0x43, 0x27, 0x1c, 0x0b, 0x40, 0x43, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x10, 0x04, + 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, 0x00, 0x04, + 0x10, 0x04, 0x08, 0x14, 0x00, 0x43, 0x04, 0x1c, 0x04, 0x43, 0x43, 0x08, 0x10, 0x14, 0x10, 0x14, + 0x20, 0x43, 0x31, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x07, 0x13, 0x40, 0x43, + 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, + 0x07, 0x10, 0x10, 0x1c, 0x20, 0x1c, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, + 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, + 0x44, 0x1b, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x07, 0x1c, 0x0b, 0x28, 0x18, 0x1c, 0x0b, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x51, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, + 0x04, 0x16, 0x05, 0x18, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x08, 0x0c, 0x11, 0x07, + 0x42, 0x27, 0x1d, 0x0b, 0x40, 0x43, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x11, 0x05, + 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, 0x00, 0x05, + 0x11, 0x05, 0x09, 0x16, 0x00, 0x42, 0x05, 0x1e, 0x05, 0x42, 0x42, 0x09, 0x11, 0x15, 0x10, 0x15, + 0x20, 0x43, 0x32, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x07, 0x13, 0x41, 0x43, + 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, + 0x07, 0x10, 0x10, 0x1d, 0x20, 0x1d, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, + 0x40, 0x0a, 0x0a, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x14, + 0x44, 0x1a, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1d, 0x0b, 0x29, 0x18, 0x1d, 0x0b, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x51, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x27, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, + 0x04, 0x18, 0x06, 0x19, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x09, 0x0c, 0x13, 0x07, + 0x41, 0x27, 0x1e, 0x0b, 0x40, 0x43, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x13, 0x06, + 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, 0x01, 0x06, + 0x13, 0x06, 0x0b, 0x18, 0x01, 0x41, 0x06, 0x20, 0x06, 0x41, 0x41, 0x0b, 0x13, 0x16, 0x11, 0x16, + 0x21, 0x43, 0x34, 0x40, 0x48, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x07, 0x13, 0x41, 0x43, + 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, + 0x07, 0x11, 0x11, 0x1e, 0x21, 0x1e, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, + 0x40, 0x09, 0x09, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x14, + 0x44, 0x19, 0x13, 0x0b, 0x40, 0x0b, 0x14, 0x06, 0x1e, 0x0b, 0x2b, 0x19, 0x1e, 0x0b, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x52, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, + 0x05, 0x19, 0x07, 0x1a, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x14, 0x07, + 0x40, 0x27, 0x1f, 0x0a, 0x40, 0x42, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x14, 0x07, + 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, 0x02, 0x07, + 0x14, 0x07, 0x0c, 0x19, 0x02, 0x40, 0x07, 0x21, 0x07, 0x40, 0x40, 0x0c, 0x14, 0x17, 0x12, 0x17, + 0x22, 0x42, 0x36, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x07, 0x12, 0x42, 0x42, + 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, + 0x07, 0x12, 0x12, 0x1f, 0x22, 0x1f, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, + 0x40, 0x08, 0x08, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, + 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x1f, 0x0a, 0x2c, 0x1a, 0x1f, 0x0a, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x52, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, + 0x05, 0x1b, 0x08, 0x1a, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0a, 0x0d, 0x15, 0x07, + 0x00, 0x27, 0x20, 0x0a, 0x40, 0x42, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x15, 0x08, + 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, 0x02, 0x08, + 0x15, 0x08, 0x0d, 0x1b, 0x02, 0x00, 0x08, 0x23, 0x08, 0x00, 0x00, 0x0d, 0x15, 0x18, 0x12, 0x18, + 0x22, 0x42, 0x38, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x07, 0x12, 0x42, 0x42, + 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, + 0x07, 0x12, 0x12, 0x20, 0x22, 0x20, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, + 0x40, 0x07, 0x07, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x15, + 0x45, 0x17, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x05, 0x20, 0x0a, 0x2d, 0x1a, 0x20, 0x0a, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x53, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x27, 0x40, 0x05, 0x40, 0x40, 0x40, 0x0f, + 0x05, 0x1c, 0x09, 0x1b, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0d, 0x16, 0x07, + 0x01, 0x27, 0x21, 0x0a, 0x40, 0x42, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x16, 0x09, + 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, 0x03, 0x09, + 0x16, 0x09, 0x0e, 0x1c, 0x03, 0x01, 0x09, 0x24, 0x09, 0x01, 0x01, 0x0e, 0x16, 0x19, 0x13, 0x19, + 0x23, 0x42, 0x3a, 0x40, 0x48, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x07, 0x12, 0x43, 0x42, + 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, + 0x07, 0x13, 0x13, 0x21, 0x23, 0x21, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, + 0x40, 0x06, 0x06, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x15, + 0x45, 0x16, 0x12, 0x0a, 0x40, 0x0a, 0x15, 0x04, 0x21, 0x0a, 0x2e, 0x1b, 0x21, 0x0a, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x54, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, + 0x06, 0x1e, 0x0a, 0x1c, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x18, 0x07, + 0x02, 0x27, 0x22, 0x09, 0x40, 0x41, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x18, 0x0a, + 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, 0x04, 0x0a, + 0x18, 0x0a, 0x10, 0x1e, 0x04, 0x02, 0x0a, 0x26, 0x0a, 0x02, 0x02, 0x10, 0x18, 0x1a, 0x14, 0x1a, + 0x24, 0x41, 0x3c, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x07, 0x11, 0x44, 0x41, + 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, + 0x07, 0x14, 0x14, 0x22, 0x24, 0x22, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, + 0x40, 0x05, 0x05, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, + 0x46, 0x15, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x22, 0x09, 0x30, 0x1c, 0x22, 0x09, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x54, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, + 0x06, 0x1f, 0x0b, 0x1c, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0c, 0x0e, 0x19, 0x07, + 0x03, 0x27, 0x23, 0x09, 0x40, 0x41, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x19, 0x0b, + 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, 0x04, 0x0b, + 0x19, 0x0b, 0x11, 0x1f, 0x04, 0x03, 0x0b, 0x27, 0x0b, 0x03, 0x03, 0x11, 0x19, 0x1b, 0x14, 0x1b, + 0x24, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x07, 0x11, 0x44, 0x41, + 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, + 0x07, 0x14, 0x14, 0x23, 0x24, 0x23, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, + 0x40, 0x04, 0x04, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x16, + 0x46, 0x14, 0x11, 0x09, 0x40, 0x09, 0x16, 0x03, 0x23, 0x09, 0x31, 0x1c, 0x23, 0x09, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x55, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, + 0x06, 0x21, 0x0c, 0x1d, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x0d, 0x0e, 0x1a, 0x07, + 0x04, 0x27, 0x24, 0x09, 0x40, 0x41, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1a, 0x0c, + 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, 0x05, 0x0c, + 0x1a, 0x0c, 0x12, 0x21, 0x05, 0x04, 0x0c, 0x29, 0x0c, 0x04, 0x04, 0x12, 0x1a, 0x1c, 0x15, 0x1c, + 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x07, 0x11, 0x45, 0x41, + 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, + 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, + 0x40, 0x03, 0x03, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, + 0x46, 0x13, 0x11, 0x09, 0x40, 0x09, 0x16, 0x02, 0x24, 0x09, 0x32, 0x1d, 0x24, 0x09, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x56, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x06, 0x40, 0x40, 0x40, 0x0f, + 0x06, 0x22, 0x0c, 0x1d, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0d, 0x0e, 0x1b, 0x07, + 0x04, 0x27, 0x24, 0x08, 0x40, 0x41, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x1b, 0x0c, + 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, 0x05, 0x0c, + 0x1b, 0x0c, 0x13, 0x22, 0x05, 0x04, 0x0c, 0x2a, 0x0c, 0x04, 0x04, 0x13, 0x1b, 0x1c, 0x15, 0x1c, + 0x25, 0x41, 0x3e, 0x40, 0x48, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x07, 0x10, 0x46, 0x41, + 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, + 0x07, 0x15, 0x15, 0x24, 0x25, 0x24, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, + 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x16, + 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x16, 0x01, 0x24, 0x08, 0x33, 0x1d, 0x24, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x56, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, + 0x07, 0x24, 0x0d, 0x1e, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0e, 0x0f, 0x1d, 0x07, + 0x05, 0x27, 0x25, 0x08, 0x40, 0x40, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x1d, 0x0d, + 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, 0x06, 0x0d, + 0x1d, 0x0d, 0x15, 0x24, 0x06, 0x05, 0x0d, 0x2c, 0x0d, 0x05, 0x05, 0x15, 0x1d, 0x1d, 0x16, 0x1d, + 0x26, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x07, 0x10, 0x46, 0x40, + 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, + 0x07, 0x16, 0x16, 0x25, 0x26, 0x25, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, + 0x40, 0x02, 0x02, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x17, + 0x47, 0x12, 0x10, 0x08, 0x40, 0x08, 0x17, 0x01, 0x25, 0x08, 0x35, 0x1e, 0x25, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x57, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, + 0x07, 0x26, 0x0e, 0x1f, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1e, 0x07, + 0x06, 0x27, 0x26, 0x08, 0x40, 0x40, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x1e, 0x0e, + 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, 0x07, 0x0e, + 0x1e, 0x0e, 0x16, 0x26, 0x07, 0x06, 0x0e, 0x2e, 0x0e, 0x06, 0x06, 0x16, 0x1e, 0x1e, 0x17, 0x1e, + 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x07, 0x10, 0x47, 0x40, + 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, + 0x07, 0x17, 0x17, 0x26, 0x27, 0x26, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, + 0x40, 0x01, 0x01, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, + 0x47, 0x11, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x26, 0x08, 0x36, 0x1f, 0x26, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x57, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x27, 0x40, 0x07, 0x40, 0x40, 0x40, 0x0f, + 0x07, 0x27, 0x0f, 0x1f, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x0f, 0x0f, 0x1f, 0x07, + 0x07, 0x27, 0x27, 0x08, 0x40, 0x40, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x1f, 0x0f, + 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, 0x07, 0x0f, + 0x1f, 0x0f, 0x17, 0x27, 0x07, 0x07, 0x0f, 0x2f, 0x0f, 0x07, 0x07, 0x17, 0x1f, 0x1f, 0x17, 0x1f, + 0x27, 0x40, 0x3e, 0x40, 0x48, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x07, 0x10, 0x47, 0x40, + 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, + 0x07, 0x17, 0x17, 0x27, 0x27, 0x27, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, + 0x40, 0x00, 0x00, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x17, + 0x47, 0x10, 0x10, 0x08, 0x40, 0x08, 0x17, 0x00, 0x27, 0x08, 0x37, 0x1f, 0x27, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x48, 0x48, 0x60, 0x40, 0x27, 0x07, 0x07, 0x1f, 0x40, 0x48, 0x40, 0x40, 0x17, 0x0f, + 0x48, 0x68, 0x40, 0x07, 0x68, 0x68, 0x68, 0x68, 0x68, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x40, 0x07, + 0x68, 0x27, 0x50, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x48, 0x48, 0x58, 0x60, 0x50, 0x60, + 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, 0x58, 0x60, + 0x50, 0x60, 0x68, 0x60, 0x58, 0x68, 0x68, 0x68, 0x58, 0x60, 0x68, 0x68, 0x68, 0x50, 0x48, 0x58, + 0x07, 0x50, 0x58, 0x40, 0x40, 0x40, 0x48, 0x07, 0x48, 0x48, 0x48, 0x68, 0x50, 0x1f, 0x17, 0x50, + 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x1f, 0x17, 0x50, 0x0f, 0x07, 0x40, 0x40, + 0x07, 0x40, 0x40, 0x40, 0x07, 0x40, 0x07, 0x17, 0x17, 0x17, 0x50, 0x17, 0x17, 0x50, 0x40, 0x40, + 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x1f, 0x27, 0x0f, 0x07, 0x07, 0x0f, 0x40, + 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x48, 0x17, 0x48, 0x48, 0x48, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x47, 0x47, 0x5f, 0x40, 0x27, 0x07, 0x07, 0x20, 0x40, 0x47, 0x40, 0x40, 0x17, 0x0f, + 0x47, 0x66, 0x40, 0x08, 0x66, 0x66, 0x66, 0x65, 0x65, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x00, 0x07, + 0x67, 0x27, 0x4e, 0x17, 0x40, 0x07, 0x1f, 0x40, 0x40, 0x40, 0x47, 0x47, 0x57, 0x5f, 0x4f, 0x5f, + 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, 0x57, 0x5f, + 0x4f, 0x5f, 0x66, 0x5e, 0x57, 0x67, 0x67, 0x66, 0x57, 0x5f, 0x67, 0x67, 0x66, 0x4f, 0x47, 0x56, + 0x08, 0x4f, 0x56, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x47, 0x47, 0x66, 0x4f, 0x1f, 0x17, 0x4f, + 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x17, 0x4f, 0x10, 0x07, 0x40, 0x40, + 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x17, 0x17, 0x17, 0x4f, 0x17, 0x17, 0x4f, 0x40, 0x40, + 0x40, 0x2f, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x1f, 0x20, 0x27, 0x10, 0x07, 0x08, 0x10, 0x00, + 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1f, 0x47, 0x17, 0x46, 0x47, 0x47, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x46, 0x47, 0x5e, 0x40, 0x26, 0x06, 0x06, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, + 0x47, 0x64, 0x40, 0x08, 0x65, 0x64, 0x64, 0x63, 0x63, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, + 0x66, 0x27, 0x4d, 0x17, 0x40, 0x07, 0x1e, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5e, 0x4e, 0x5e, + 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, 0x56, 0x5e, + 0x4e, 0x5e, 0x65, 0x5d, 0x56, 0x66, 0x66, 0x64, 0x56, 0x5e, 0x66, 0x66, 0x64, 0x4e, 0x46, 0x55, + 0x09, 0x4f, 0x54, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x64, 0x4e, 0x1f, 0x16, 0x4f, + 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, + 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, + 0x40, 0x2e, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, + 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x46, 0x17, 0x45, 0x46, 0x46, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x45, 0x47, 0x5e, 0x40, 0x25, 0x06, 0x05, 0x20, 0x40, 0x47, 0x40, 0x40, 0x16, 0x0f, + 0x47, 0x63, 0x40, 0x08, 0x64, 0x63, 0x62, 0x60, 0x60, 0x07, 0x07, 0x0f, 0x3e, 0x17, 0x01, 0x07, + 0x65, 0x27, 0x4c, 0x17, 0x40, 0x07, 0x1d, 0x40, 0x40, 0x40, 0x47, 0x47, 0x56, 0x5d, 0x4e, 0x5d, + 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, 0x56, 0x5d, + 0x4e, 0x5d, 0x64, 0x5c, 0x56, 0x65, 0x65, 0x63, 0x56, 0x5e, 0x65, 0x65, 0x63, 0x4d, 0x46, 0x54, + 0x09, 0x4f, 0x52, 0x40, 0x40, 0x40, 0x47, 0x07, 0x47, 0x46, 0x46, 0x62, 0x4e, 0x1f, 0x16, 0x4f, + 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x1f, 0x16, 0x4f, 0x10, 0x07, 0x40, 0x40, + 0x07, 0x00, 0x00, 0x01, 0x09, 0x01, 0x09, 0x17, 0x17, 0x16, 0x4f, 0x17, 0x16, 0x4f, 0x40, 0x40, + 0x40, 0x2d, 0x17, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x1e, 0x20, 0x27, 0x10, 0x07, 0x09, 0x10, 0x01, + 0x07, 0x3e, 0x1f, 0x17, 0x40, 0x0f, 0x17, 0x1e, 0x45, 0x17, 0x44, 0x45, 0x45, 0x17, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x44, 0x46, 0x5d, 0x40, 0x24, 0x05, 0x04, 0x21, 0x40, 0x46, 0x40, 0x40, 0x15, 0x0f, + 0x46, 0x61, 0x40, 0x09, 0x63, 0x61, 0x60, 0x5e, 0x5e, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x02, 0x07, + 0x64, 0x27, 0x4b, 0x16, 0x40, 0x06, 0x1c, 0x40, 0x40, 0x40, 0x46, 0x46, 0x55, 0x5c, 0x4d, 0x5c, + 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, 0x55, 0x5c, + 0x4d, 0x5c, 0x63, 0x5b, 0x55, 0x64, 0x64, 0x61, 0x55, 0x5d, 0x64, 0x64, 0x61, 0x4c, 0x45, 0x53, + 0x0a, 0x4e, 0x50, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x45, 0x45, 0x60, 0x4d, 0x1e, 0x15, 0x4e, + 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x15, 0x4e, 0x11, 0x07, 0x40, 0x41, + 0x07, 0x01, 0x01, 0x02, 0x0a, 0x02, 0x0a, 0x16, 0x17, 0x15, 0x4e, 0x17, 0x15, 0x4e, 0x40, 0x40, + 0x40, 0x2c, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x1d, 0x21, 0x27, 0x11, 0x07, 0x0a, 0x11, 0x02, + 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1d, 0x44, 0x16, 0x43, 0x44, 0x44, 0x16, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x43, 0x46, 0x5c, 0x40, 0x23, 0x04, 0x03, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, + 0x46, 0x60, 0x40, 0x09, 0x61, 0x60, 0x5e, 0x5b, 0x5b, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, + 0x63, 0x27, 0x49, 0x16, 0x40, 0x06, 0x1b, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5b, 0x4c, 0x5b, + 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, 0x54, 0x5b, + 0x4c, 0x5b, 0x61, 0x59, 0x54, 0x63, 0x63, 0x60, 0x54, 0x5c, 0x63, 0x63, 0x60, 0x4b, 0x44, 0x51, + 0x0b, 0x4e, 0x4e, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5e, 0x4c, 0x1e, 0x14, 0x4e, + 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, + 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, + 0x40, 0x2b, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, + 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x43, 0x16, 0x41, 0x43, 0x43, 0x16, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x42, 0x46, 0x5c, 0x40, 0x22, 0x04, 0x02, 0x21, 0x40, 0x46, 0x40, 0x40, 0x14, 0x0f, + 0x46, 0x5e, 0x40, 0x09, 0x60, 0x5e, 0x5c, 0x59, 0x59, 0x07, 0x07, 0x0e, 0x3e, 0x16, 0x03, 0x07, + 0x62, 0x27, 0x48, 0x16, 0x40, 0x06, 0x1a, 0x40, 0x40, 0x40, 0x46, 0x46, 0x54, 0x5a, 0x4c, 0x5a, + 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, 0x54, 0x5a, + 0x4c, 0x5a, 0x60, 0x58, 0x54, 0x62, 0x62, 0x5e, 0x54, 0x5c, 0x62, 0x62, 0x5e, 0x4a, 0x44, 0x50, + 0x0b, 0x4e, 0x4c, 0x40, 0x41, 0x40, 0x46, 0x07, 0x46, 0x44, 0x44, 0x5c, 0x4c, 0x1e, 0x14, 0x4e, + 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x1e, 0x14, 0x4e, 0x11, 0x07, 0x40, 0x41, + 0x07, 0x01, 0x01, 0x03, 0x0b, 0x03, 0x0b, 0x16, 0x17, 0x14, 0x4e, 0x17, 0x14, 0x4e, 0x40, 0x40, + 0x40, 0x2a, 0x16, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x1c, 0x21, 0x27, 0x11, 0x07, 0x0b, 0x11, 0x03, + 0x06, 0x3e, 0x1e, 0x16, 0x40, 0x0f, 0x16, 0x1c, 0x42, 0x16, 0x40, 0x42, 0x42, 0x16, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x41, 0x45, 0x5b, 0x40, 0x21, 0x03, 0x01, 0x22, 0x40, 0x45, 0x40, 0x40, 0x13, 0x0f, + 0x45, 0x5d, 0x40, 0x0a, 0x5f, 0x5d, 0x5a, 0x56, 0x56, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, + 0x61, 0x27, 0x47, 0x15, 0x40, 0x05, 0x19, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x59, 0x4b, 0x59, + 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, 0x53, 0x59, + 0x4b, 0x59, 0x5f, 0x57, 0x53, 0x61, 0x61, 0x5d, 0x53, 0x5b, 0x61, 0x61, 0x5d, 0x49, 0x43, 0x4f, + 0x0c, 0x4d, 0x4a, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x5a, 0x4b, 0x1d, 0x13, 0x4d, + 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x13, 0x4d, 0x12, 0x07, 0x40, 0x42, + 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x13, 0x4d, 0x17, 0x13, 0x4d, 0x40, 0x40, + 0x40, 0x29, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x1b, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, + 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1b, 0x41, 0x15, 0x00, 0x41, 0x41, 0x15, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x40, 0x45, 0x5b, 0x40, 0x20, 0x02, 0x00, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, + 0x45, 0x5b, 0x40, 0x0a, 0x5e, 0x5b, 0x59, 0x54, 0x54, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x04, 0x07, + 0x60, 0x27, 0x46, 0x15, 0x40, 0x05, 0x18, 0x40, 0x40, 0x40, 0x45, 0x45, 0x53, 0x58, 0x4b, 0x58, + 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, 0x53, 0x58, + 0x4b, 0x58, 0x5e, 0x56, 0x53, 0x60, 0x60, 0x5b, 0x53, 0x5b, 0x60, 0x60, 0x5b, 0x48, 0x43, 0x4e, + 0x0c, 0x4d, 0x49, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x43, 0x43, 0x59, 0x4b, 0x1d, 0x12, 0x4d, + 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, + 0x07, 0x02, 0x02, 0x04, 0x0c, 0x04, 0x0c, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, + 0x40, 0x28, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0c, 0x12, 0x04, + 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x40, 0x15, 0x01, 0x40, 0x40, 0x15, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x00, 0x45, 0x5a, 0x40, 0x1f, 0x02, 0x40, 0x22, 0x40, 0x45, 0x40, 0x40, 0x12, 0x0f, + 0x45, 0x59, 0x40, 0x0a, 0x5c, 0x59, 0x57, 0x51, 0x51, 0x07, 0x07, 0x0d, 0x3e, 0x15, 0x05, 0x07, + 0x5f, 0x27, 0x44, 0x15, 0x40, 0x05, 0x17, 0x40, 0x40, 0x40, 0x45, 0x45, 0x52, 0x57, 0x4a, 0x57, + 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, 0x52, 0x57, + 0x4a, 0x57, 0x5c, 0x54, 0x52, 0x5f, 0x5f, 0x59, 0x52, 0x5a, 0x5f, 0x5f, 0x59, 0x47, 0x42, 0x4c, + 0x0d, 0x4d, 0x47, 0x40, 0x42, 0x40, 0x45, 0x07, 0x45, 0x42, 0x42, 0x57, 0x4a, 0x1d, 0x12, 0x4d, + 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x1d, 0x12, 0x4d, 0x12, 0x07, 0x40, 0x42, + 0x07, 0x02, 0x02, 0x05, 0x0d, 0x05, 0x0d, 0x15, 0x17, 0x12, 0x4d, 0x17, 0x12, 0x4d, 0x40, 0x40, + 0x40, 0x27, 0x15, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x1a, 0x22, 0x27, 0x12, 0x07, 0x0d, 0x12, 0x05, + 0x05, 0x3e, 0x1d, 0x15, 0x40, 0x0f, 0x15, 0x1a, 0x00, 0x15, 0x03, 0x00, 0x00, 0x15, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x01, 0x44, 0x59, 0x40, 0x1e, 0x01, 0x41, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, + 0x44, 0x58, 0x40, 0x0b, 0x5b, 0x58, 0x55, 0x4f, 0x4f, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, + 0x5e, 0x27, 0x43, 0x14, 0x40, 0x04, 0x16, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x56, 0x49, 0x56, + 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, 0x51, 0x56, + 0x49, 0x56, 0x5b, 0x53, 0x51, 0x5e, 0x5e, 0x58, 0x51, 0x59, 0x5e, 0x5e, 0x58, 0x46, 0x41, 0x4b, + 0x0e, 0x4c, 0x45, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x55, 0x49, 0x1c, 0x11, 0x4c, + 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, + 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, + 0x40, 0x26, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, + 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x01, 0x14, 0x04, 0x01, 0x01, 0x14, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x02, 0x44, 0x59, 0x40, 0x1d, 0x01, 0x42, 0x23, 0x40, 0x44, 0x40, 0x40, 0x11, 0x0f, + 0x44, 0x56, 0x40, 0x0b, 0x5a, 0x56, 0x53, 0x4c, 0x4c, 0x07, 0x07, 0x0c, 0x3e, 0x14, 0x06, 0x07, + 0x5d, 0x27, 0x42, 0x14, 0x40, 0x04, 0x15, 0x40, 0x40, 0x40, 0x44, 0x44, 0x51, 0x55, 0x49, 0x55, + 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, 0x51, 0x55, + 0x49, 0x55, 0x5a, 0x52, 0x51, 0x5d, 0x5d, 0x56, 0x51, 0x59, 0x5d, 0x5d, 0x56, 0x45, 0x41, 0x4a, + 0x0e, 0x4c, 0x43, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x41, 0x41, 0x53, 0x49, 0x1c, 0x11, 0x4c, + 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x11, 0x4c, 0x13, 0x07, 0x40, 0x43, + 0x07, 0x03, 0x03, 0x06, 0x0e, 0x06, 0x0e, 0x14, 0x17, 0x11, 0x4c, 0x17, 0x11, 0x4c, 0x40, 0x40, + 0x40, 0x25, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x19, 0x23, 0x27, 0x13, 0x07, 0x0e, 0x13, 0x06, + 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x19, 0x02, 0x14, 0x05, 0x02, 0x02, 0x14, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x03, 0x44, 0x58, 0x40, 0x1c, 0x00, 0x43, 0x23, 0x40, 0x44, 0x40, 0x40, 0x10, 0x0f, + 0x44, 0x55, 0x40, 0x0b, 0x59, 0x55, 0x51, 0x4a, 0x4a, 0x07, 0x07, 0x0c, 0x3d, 0x14, 0x07, 0x07, + 0x5c, 0x27, 0x41, 0x14, 0x40, 0x04, 0x14, 0x40, 0x40, 0x40, 0x44, 0x44, 0x50, 0x54, 0x48, 0x54, + 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, 0x50, 0x54, + 0x48, 0x54, 0x59, 0x51, 0x50, 0x5c, 0x5c, 0x55, 0x50, 0x58, 0x5c, 0x5c, 0x55, 0x44, 0x40, 0x49, + 0x0f, 0x4c, 0x41, 0x40, 0x43, 0x40, 0x44, 0x07, 0x44, 0x40, 0x40, 0x51, 0x48, 0x1c, 0x10, 0x4c, + 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x1c, 0x10, 0x4c, 0x13, 0x07, 0x40, 0x43, + 0x07, 0x03, 0x03, 0x07, 0x0f, 0x07, 0x0f, 0x14, 0x17, 0x10, 0x4c, 0x17, 0x10, 0x4c, 0x40, 0x40, + 0x40, 0x24, 0x14, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x18, 0x23, 0x27, 0x13, 0x07, 0x0f, 0x13, 0x07, + 0x04, 0x3e, 0x1c, 0x14, 0x40, 0x0f, 0x14, 0x18, 0x03, 0x14, 0x06, 0x03, 0x03, 0x14, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x04, 0x43, 0x57, 0x40, 0x1b, 0x40, 0x44, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, + 0x43, 0x53, 0x40, 0x0c, 0x57, 0x53, 0x4f, 0x47, 0x47, 0x07, 0x07, 0x0b, 0x3b, 0x13, 0x08, 0x07, + 0x5b, 0x27, 0x00, 0x13, 0x40, 0x03, 0x13, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x53, 0x47, 0x53, + 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, 0x4f, 0x53, + 0x47, 0x53, 0x57, 0x4f, 0x4f, 0x5b, 0x5b, 0x53, 0x4f, 0x57, 0x5b, 0x5b, 0x53, 0x43, 0x00, 0x47, + 0x10, 0x4b, 0x00, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4f, 0x47, 0x1b, 0x0f, 0x4b, + 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, + 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, + 0x40, 0x23, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, + 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x04, 0x13, 0x08, 0x04, 0x04, 0x13, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x05, 0x43, 0x57, 0x40, 0x1a, 0x40, 0x45, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0f, 0x0f, + 0x43, 0x52, 0x40, 0x0c, 0x56, 0x52, 0x4d, 0x45, 0x45, 0x07, 0x07, 0x0b, 0x3a, 0x13, 0x08, 0x07, + 0x5a, 0x27, 0x01, 0x13, 0x40, 0x03, 0x12, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4f, 0x52, 0x47, 0x52, + 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, 0x4f, 0x52, + 0x47, 0x52, 0x56, 0x4e, 0x4f, 0x5a, 0x5a, 0x52, 0x4f, 0x57, 0x5a, 0x5a, 0x52, 0x42, 0x00, 0x46, + 0x10, 0x4b, 0x02, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x00, 0x00, 0x4d, 0x47, 0x1b, 0x0f, 0x4b, + 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0f, 0x4b, 0x14, 0x07, 0x40, 0x44, + 0x07, 0x04, 0x04, 0x08, 0x10, 0x08, 0x10, 0x13, 0x17, 0x0f, 0x4b, 0x17, 0x0f, 0x4b, 0x40, 0x40, + 0x40, 0x22, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x17, 0x24, 0x27, 0x14, 0x07, 0x10, 0x14, 0x08, + 0x03, 0x3e, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x17, 0x05, 0x13, 0x09, 0x05, 0x05, 0x13, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x19, 0x41, 0x46, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0e, 0x0f, + 0x43, 0x50, 0x40, 0x0c, 0x55, 0x50, 0x4b, 0x42, 0x42, 0x07, 0x07, 0x0b, 0x38, 0x13, 0x09, 0x07, + 0x59, 0x27, 0x02, 0x13, 0x40, 0x03, 0x11, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, + 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, 0x4e, 0x51, + 0x46, 0x51, 0x55, 0x4d, 0x4e, 0x59, 0x59, 0x50, 0x4e, 0x56, 0x59, 0x59, 0x50, 0x41, 0x01, 0x45, + 0x11, 0x4b, 0x04, 0x40, 0x44, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4b, 0x46, 0x1b, 0x0e, 0x4b, + 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x1b, 0x0e, 0x4b, 0x14, 0x07, 0x40, 0x44, + 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x13, 0x17, 0x0e, 0x4b, 0x17, 0x0e, 0x4b, 0x40, 0x40, + 0x40, 0x21, 0x13, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x16, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, + 0x03, 0x3d, 0x1b, 0x13, 0x40, 0x0f, 0x13, 0x16, 0x06, 0x13, 0x0a, 0x06, 0x06, 0x13, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x06, 0x43, 0x56, 0x40, 0x18, 0x42, 0x47, 0x24, 0x40, 0x43, 0x40, 0x40, 0x0d, 0x0f, + 0x43, 0x4f, 0x40, 0x0c, 0x54, 0x4f, 0x4a, 0x40, 0x40, 0x07, 0x07, 0x0a, 0x36, 0x12, 0x09, 0x07, + 0x59, 0x27, 0x03, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x43, 0x43, 0x4e, 0x51, 0x46, 0x51, + 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, 0x4e, 0x51, + 0x46, 0x51, 0x54, 0x4c, 0x4e, 0x59, 0x59, 0x4f, 0x4e, 0x56, 0x59, 0x59, 0x4f, 0x41, 0x01, 0x44, + 0x11, 0x4b, 0x05, 0x40, 0x45, 0x40, 0x43, 0x07, 0x43, 0x01, 0x01, 0x4a, 0x46, 0x1a, 0x0d, 0x4b, + 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x1a, 0x0d, 0x4b, 0x14, 0x07, 0x40, 0x45, + 0x07, 0x04, 0x04, 0x09, 0x11, 0x09, 0x11, 0x12, 0x17, 0x0d, 0x4b, 0x17, 0x0d, 0x4b, 0x40, 0x40, + 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x24, 0x27, 0x14, 0x07, 0x11, 0x14, 0x09, + 0x02, 0x3b, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x06, 0x12, 0x0b, 0x06, 0x06, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x07, 0x42, 0x55, 0x40, 0x18, 0x42, 0x47, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0d, 0x0f, + 0x42, 0x4d, 0x40, 0x0d, 0x52, 0x4d, 0x48, 0x02, 0x02, 0x07, 0x07, 0x0a, 0x35, 0x12, 0x0a, 0x07, + 0x58, 0x27, 0x05, 0x12, 0x40, 0x02, 0x10, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4d, 0x50, 0x45, 0x50, + 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, 0x4d, 0x50, + 0x45, 0x50, 0x52, 0x4a, 0x4d, 0x58, 0x58, 0x4d, 0x4d, 0x55, 0x58, 0x58, 0x4d, 0x40, 0x02, 0x42, + 0x12, 0x4a, 0x07, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x02, 0x02, 0x48, 0x45, 0x1a, 0x0d, 0x4a, + 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0d, 0x4a, 0x15, 0x07, 0x40, 0x45, + 0x07, 0x05, 0x05, 0x0a, 0x12, 0x0a, 0x12, 0x12, 0x17, 0x0d, 0x4a, 0x17, 0x0d, 0x4a, 0x40, 0x40, + 0x40, 0x20, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x15, 0x25, 0x27, 0x15, 0x07, 0x12, 0x15, 0x0a, + 0x02, 0x3a, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x15, 0x07, 0x12, 0x0d, 0x07, 0x07, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x08, 0x42, 0x54, 0x40, 0x17, 0x43, 0x48, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, + 0x42, 0x4b, 0x40, 0x0d, 0x51, 0x4b, 0x46, 0x04, 0x04, 0x07, 0x07, 0x0a, 0x33, 0x12, 0x0b, 0x07, + 0x57, 0x27, 0x06, 0x12, 0x40, 0x02, 0x0f, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4f, 0x44, 0x4f, + 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, 0x4c, 0x4f, + 0x44, 0x4f, 0x51, 0x49, 0x4c, 0x57, 0x57, 0x4b, 0x4c, 0x54, 0x57, 0x57, 0x4b, 0x00, 0x03, 0x41, + 0x13, 0x4a, 0x09, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x46, 0x44, 0x1a, 0x0c, 0x4a, + 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, + 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, + 0x40, 0x1f, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, + 0x02, 0x39, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x08, 0x12, 0x0e, 0x08, 0x08, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x09, 0x42, 0x54, 0x40, 0x16, 0x43, 0x49, 0x25, 0x40, 0x42, 0x40, 0x40, 0x0c, 0x0f, + 0x42, 0x4a, 0x40, 0x0d, 0x50, 0x4a, 0x44, 0x07, 0x07, 0x07, 0x07, 0x0a, 0x32, 0x12, 0x0b, 0x07, + 0x56, 0x27, 0x07, 0x12, 0x40, 0x02, 0x0e, 0x40, 0x40, 0x40, 0x42, 0x42, 0x4c, 0x4e, 0x44, 0x4e, + 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, 0x4c, 0x4e, + 0x44, 0x4e, 0x50, 0x48, 0x4c, 0x56, 0x56, 0x4a, 0x4c, 0x54, 0x56, 0x56, 0x4a, 0x01, 0x03, 0x40, + 0x13, 0x4a, 0x0b, 0x40, 0x45, 0x40, 0x42, 0x07, 0x42, 0x03, 0x03, 0x44, 0x44, 0x1a, 0x0c, 0x4a, + 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x1a, 0x0c, 0x4a, 0x15, 0x07, 0x40, 0x45, + 0x07, 0x05, 0x05, 0x0b, 0x13, 0x0b, 0x13, 0x12, 0x17, 0x0c, 0x4a, 0x17, 0x0c, 0x4a, 0x40, 0x40, + 0x40, 0x1e, 0x12, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x14, 0x25, 0x27, 0x15, 0x07, 0x13, 0x15, 0x0b, + 0x02, 0x38, 0x1a, 0x12, 0x40, 0x0f, 0x12, 0x14, 0x09, 0x12, 0x0f, 0x09, 0x09, 0x12, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x0a, 0x41, 0x53, 0x40, 0x15, 0x44, 0x4a, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0b, 0x0f, + 0x41, 0x48, 0x40, 0x0e, 0x4f, 0x48, 0x42, 0x09, 0x09, 0x07, 0x07, 0x09, 0x30, 0x11, 0x0c, 0x07, + 0x55, 0x27, 0x08, 0x11, 0x40, 0x01, 0x0d, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4b, 0x4d, 0x43, 0x4d, + 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, 0x4b, 0x4d, + 0x43, 0x4d, 0x4f, 0x47, 0x4b, 0x55, 0x55, 0x48, 0x4b, 0x53, 0x55, 0x55, 0x48, 0x02, 0x04, 0x00, + 0x14, 0x49, 0x0d, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x04, 0x04, 0x42, 0x43, 0x19, 0x0b, 0x49, + 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0b, 0x49, 0x16, 0x07, 0x40, 0x46, + 0x07, 0x06, 0x06, 0x0c, 0x14, 0x0c, 0x14, 0x11, 0x17, 0x0b, 0x49, 0x17, 0x0b, 0x49, 0x40, 0x40, + 0x40, 0x1d, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x13, 0x26, 0x27, 0x16, 0x07, 0x14, 0x16, 0x0c, + 0x01, 0x36, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x13, 0x0a, 0x11, 0x10, 0x0a, 0x0a, 0x11, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x0b, 0x41, 0x52, 0x40, 0x14, 0x45, 0x4b, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, + 0x41, 0x47, 0x40, 0x0e, 0x4d, 0x47, 0x40, 0x0c, 0x0c, 0x07, 0x07, 0x09, 0x2f, 0x11, 0x0d, 0x07, + 0x54, 0x27, 0x0a, 0x11, 0x40, 0x01, 0x0c, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4c, 0x42, 0x4c, + 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, 0x4a, 0x4c, + 0x42, 0x4c, 0x4d, 0x45, 0x4a, 0x54, 0x54, 0x47, 0x4a, 0x52, 0x54, 0x54, 0x47, 0x03, 0x05, 0x02, + 0x15, 0x49, 0x0f, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x40, 0x42, 0x19, 0x0a, 0x49, + 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, + 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, + 0x40, 0x1c, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, + 0x01, 0x35, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0b, 0x11, 0x12, 0x0b, 0x0b, 0x11, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x0c, 0x41, 0x52, 0x40, 0x13, 0x45, 0x4c, 0x26, 0x40, 0x41, 0x40, 0x40, 0x0a, 0x0f, + 0x41, 0x45, 0x40, 0x0e, 0x4c, 0x45, 0x01, 0x0e, 0x0e, 0x07, 0x07, 0x09, 0x2d, 0x11, 0x0d, 0x07, + 0x53, 0x27, 0x0b, 0x11, 0x40, 0x01, 0x0b, 0x40, 0x40, 0x40, 0x41, 0x41, 0x4a, 0x4b, 0x42, 0x4b, + 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, 0x4a, 0x4b, + 0x42, 0x4b, 0x4c, 0x44, 0x4a, 0x53, 0x53, 0x45, 0x4a, 0x52, 0x53, 0x53, 0x45, 0x04, 0x05, 0x03, + 0x15, 0x49, 0x11, 0x40, 0x46, 0x40, 0x41, 0x07, 0x41, 0x05, 0x05, 0x01, 0x42, 0x19, 0x0a, 0x49, + 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x19, 0x0a, 0x49, 0x16, 0x07, 0x40, 0x46, + 0x07, 0x06, 0x06, 0x0d, 0x15, 0x0d, 0x15, 0x11, 0x17, 0x0a, 0x49, 0x17, 0x0a, 0x49, 0x40, 0x40, + 0x40, 0x1b, 0x11, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x12, 0x26, 0x27, 0x16, 0x07, 0x15, 0x16, 0x0d, + 0x01, 0x34, 0x19, 0x11, 0x40, 0x0f, 0x11, 0x12, 0x0c, 0x11, 0x13, 0x0c, 0x0c, 0x11, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x0d, 0x40, 0x51, 0x40, 0x12, 0x46, 0x4d, 0x27, 0x40, 0x40, 0x40, 0x40, 0x09, 0x0f, + 0x40, 0x44, 0x40, 0x0f, 0x4b, 0x44, 0x03, 0x11, 0x11, 0x07, 0x07, 0x08, 0x2c, 0x10, 0x0e, 0x07, + 0x52, 0x27, 0x0c, 0x10, 0x40, 0x00, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x4a, 0x41, 0x4a, + 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, 0x49, 0x4a, + 0x41, 0x4a, 0x4b, 0x43, 0x49, 0x52, 0x52, 0x44, 0x49, 0x51, 0x52, 0x52, 0x44, 0x05, 0x06, 0x04, + 0x16, 0x48, 0x13, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x03, 0x41, 0x18, 0x09, 0x48, + 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x18, 0x09, 0x48, 0x17, 0x07, 0x40, 0x47, + 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x09, 0x48, 0x17, 0x09, 0x48, 0x40, 0x40, + 0x40, 0x1a, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x11, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, + 0x00, 0x33, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x11, 0x0d, 0x10, 0x14, 0x0d, 0x0d, 0x10, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x0e, 0x40, 0x51, 0x40, 0x11, 0x47, 0x4e, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, + 0x40, 0x42, 0x40, 0x0f, 0x4a, 0x42, 0x04, 0x13, 0x13, 0x07, 0x07, 0x08, 0x2a, 0x10, 0x0e, 0x07, + 0x51, 0x27, 0x0d, 0x10, 0x40, 0x00, 0x09, 0x40, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, 0x41, 0x49, + 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, 0x49, 0x49, + 0x41, 0x49, 0x4a, 0x42, 0x49, 0x51, 0x51, 0x42, 0x49, 0x51, 0x51, 0x51, 0x42, 0x06, 0x06, 0x05, + 0x16, 0x48, 0x14, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x06, 0x06, 0x04, 0x41, 0x18, 0x08, 0x48, + 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, + 0x07, 0x07, 0x07, 0x0e, 0x16, 0x0e, 0x16, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, + 0x40, 0x19, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x16, 0x17, 0x0e, + 0x00, 0x31, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0e, 0x10, 0x15, 0x0e, 0x0e, 0x10, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x0f, 0x40, 0x50, 0x40, 0x10, 0x47, 0x4f, 0x27, 0x40, 0x40, 0x40, 0x40, 0x08, 0x0f, + 0x40, 0x40, 0x40, 0x0f, 0x48, 0x40, 0x06, 0x16, 0x16, 0x07, 0x07, 0x08, 0x28, 0x10, 0x0f, 0x07, + 0x50, 0x27, 0x0f, 0x10, 0x40, 0x00, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x48, 0x48, 0x40, 0x48, + 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, 0x48, 0x48, + 0x40, 0x48, 0x48, 0x40, 0x48, 0x50, 0x50, 0x40, 0x48, 0x50, 0x50, 0x50, 0x40, 0x07, 0x07, 0x07, + 0x17, 0x48, 0x16, 0x40, 0x47, 0x40, 0x40, 0x07, 0x40, 0x07, 0x07, 0x06, 0x40, 0x18, 0x08, 0x48, + 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x18, 0x08, 0x48, 0x17, 0x07, 0x40, 0x47, + 0x07, 0x07, 0x07, 0x0f, 0x17, 0x0f, 0x17, 0x10, 0x17, 0x08, 0x48, 0x17, 0x08, 0x48, 0x40, 0x40, + 0x40, 0x18, 0x10, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x10, 0x27, 0x27, 0x17, 0x07, 0x17, 0x17, 0x0f, + 0x00, 0x30, 0x18, 0x10, 0x40, 0x0f, 0x10, 0x10, 0x0f, 0x10, 0x17, 0x0f, 0x0f, 0x10, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x10, 0x00, 0x4f, 0x40, 0x0f, 0x48, 0x50, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, + 0x00, 0x00, 0x40, 0x10, 0x47, 0x00, 0x08, 0x18, 0x18, 0x07, 0x07, 0x07, 0x27, 0x0f, 0x10, 0x07, + 0x4f, 0x27, 0x10, 0x0f, 0x40, 0x40, 0x07, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x47, 0x00, 0x47, + 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, 0x47, 0x47, + 0x00, 0x47, 0x47, 0x00, 0x47, 0x4f, 0x4f, 0x00, 0x47, 0x4f, 0x4f, 0x4f, 0x00, 0x08, 0x08, 0x08, + 0x18, 0x47, 0x18, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x08, 0x00, 0x17, 0x07, 0x47, + 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, + 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, + 0x40, 0x17, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, + 0x40, 0x2f, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x10, 0x0f, 0x18, 0x10, 0x10, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x11, 0x00, 0x4f, 0x40, 0x0e, 0x48, 0x51, 0x28, 0x40, 0x00, 0x40, 0x40, 0x07, 0x0f, + 0x00, 0x02, 0x40, 0x10, 0x46, 0x02, 0x0a, 0x1b, 0x1b, 0x07, 0x07, 0x07, 0x25, 0x0f, 0x10, 0x07, + 0x4e, 0x27, 0x11, 0x0f, 0x40, 0x40, 0x06, 0x40, 0x40, 0x40, 0x00, 0x00, 0x47, 0x46, 0x00, 0x46, + 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, 0x47, 0x46, + 0x00, 0x46, 0x46, 0x01, 0x47, 0x4e, 0x4e, 0x02, 0x47, 0x4f, 0x4e, 0x4e, 0x02, 0x09, 0x08, 0x09, + 0x18, 0x47, 0x1a, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x08, 0x08, 0x0a, 0x00, 0x17, 0x07, 0x47, + 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x17, 0x07, 0x47, 0x18, 0x07, 0x40, 0x48, + 0x07, 0x08, 0x08, 0x10, 0x18, 0x10, 0x18, 0x0f, 0x17, 0x07, 0x47, 0x17, 0x07, 0x47, 0x40, 0x40, + 0x40, 0x16, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x0f, 0x28, 0x27, 0x18, 0x07, 0x18, 0x18, 0x10, + 0x40, 0x2e, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0f, 0x11, 0x0f, 0x19, 0x11, 0x11, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x12, 0x00, 0x4e, 0x40, 0x0d, 0x49, 0x52, 0x28, 0x40, 0x00, 0x40, 0x40, 0x06, 0x0f, + 0x00, 0x03, 0x40, 0x10, 0x45, 0x03, 0x0c, 0x1d, 0x1d, 0x07, 0x07, 0x07, 0x24, 0x0f, 0x11, 0x07, + 0x4d, 0x27, 0x12, 0x0f, 0x40, 0x40, 0x05, 0x40, 0x40, 0x40, 0x00, 0x00, 0x46, 0x45, 0x01, 0x45, + 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, 0x46, 0x45, + 0x01, 0x45, 0x45, 0x02, 0x46, 0x4d, 0x4d, 0x03, 0x46, 0x4e, 0x4d, 0x4d, 0x03, 0x0a, 0x09, 0x0a, + 0x19, 0x47, 0x1c, 0x40, 0x48, 0x40, 0x00, 0x07, 0x00, 0x09, 0x09, 0x0c, 0x01, 0x17, 0x06, 0x47, + 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x17, 0x06, 0x47, 0x18, 0x07, 0x40, 0x48, + 0x07, 0x08, 0x08, 0x11, 0x19, 0x11, 0x19, 0x0f, 0x17, 0x06, 0x47, 0x17, 0x06, 0x47, 0x40, 0x40, + 0x40, 0x15, 0x0f, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x0e, 0x28, 0x27, 0x18, 0x07, 0x19, 0x18, 0x11, + 0x40, 0x2c, 0x17, 0x0f, 0x40, 0x0f, 0x0f, 0x0e, 0x12, 0x0f, 0x1a, 0x12, 0x12, 0x0f, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x13, 0x01, 0x4d, 0x40, 0x0c, 0x4a, 0x53, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, + 0x01, 0x05, 0x40, 0x11, 0x43, 0x05, 0x0e, 0x20, 0x20, 0x07, 0x07, 0x06, 0x22, 0x0e, 0x12, 0x07, + 0x4c, 0x27, 0x14, 0x0e, 0x40, 0x41, 0x04, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x44, 0x02, 0x44, + 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, 0x45, 0x44, + 0x02, 0x44, 0x43, 0x04, 0x45, 0x4c, 0x4c, 0x05, 0x45, 0x4d, 0x4c, 0x4c, 0x05, 0x0b, 0x0a, 0x0c, + 0x1a, 0x46, 0x1e, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x0e, 0x02, 0x16, 0x05, 0x46, + 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, + 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, + 0x40, 0x14, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, + 0x41, 0x2b, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x13, 0x0e, 0x1c, 0x13, 0x13, 0x0e, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x14, 0x01, 0x4d, 0x40, 0x0b, 0x4a, 0x54, 0x29, 0x40, 0x01, 0x40, 0x40, 0x05, 0x0f, + 0x01, 0x06, 0x40, 0x11, 0x42, 0x06, 0x10, 0x22, 0x22, 0x07, 0x07, 0x06, 0x21, 0x0e, 0x12, 0x07, + 0x4b, 0x27, 0x15, 0x0e, 0x40, 0x41, 0x03, 0x40, 0x40, 0x40, 0x01, 0x01, 0x45, 0x43, 0x02, 0x43, + 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, 0x45, 0x43, + 0x02, 0x43, 0x42, 0x05, 0x45, 0x4b, 0x4b, 0x06, 0x45, 0x4d, 0x4b, 0x4b, 0x06, 0x0c, 0x0a, 0x0d, + 0x1a, 0x46, 0x20, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0a, 0x0a, 0x10, 0x02, 0x16, 0x05, 0x46, + 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x16, 0x05, 0x46, 0x19, 0x07, 0x40, 0x49, + 0x07, 0x09, 0x09, 0x12, 0x1a, 0x12, 0x1a, 0x0e, 0x17, 0x05, 0x46, 0x17, 0x05, 0x46, 0x40, 0x40, + 0x40, 0x13, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x0d, 0x29, 0x27, 0x19, 0x07, 0x1a, 0x19, 0x12, + 0x41, 0x2a, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0d, 0x14, 0x0e, 0x1d, 0x14, 0x14, 0x0e, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x0a, 0x4b, 0x55, 0x29, 0x40, 0x01, 0x40, 0x40, 0x04, 0x0f, + 0x01, 0x08, 0x40, 0x11, 0x41, 0x08, 0x12, 0x25, 0x25, 0x07, 0x07, 0x06, 0x1f, 0x0e, 0x13, 0x07, + 0x4a, 0x27, 0x16, 0x0e, 0x40, 0x41, 0x02, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, + 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, 0x44, 0x42, + 0x03, 0x42, 0x41, 0x06, 0x44, 0x4a, 0x4a, 0x08, 0x44, 0x4c, 0x4a, 0x4a, 0x08, 0x0d, 0x0b, 0x0e, + 0x1b, 0x46, 0x22, 0x40, 0x49, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x12, 0x03, 0x16, 0x04, 0x46, + 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x16, 0x04, 0x46, 0x19, 0x07, 0x40, 0x49, + 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0e, 0x17, 0x04, 0x46, 0x17, 0x04, 0x46, 0x40, 0x40, + 0x40, 0x12, 0x0e, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x0c, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, + 0x41, 0x29, 0x16, 0x0e, 0x40, 0x0f, 0x0e, 0x0c, 0x15, 0x0e, 0x1e, 0x15, 0x15, 0x0e, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x15, 0x01, 0x4c, 0x40, 0x09, 0x4c, 0x56, 0x29, 0x40, 0x01, 0x40, 0x40, 0x03, 0x0f, + 0x01, 0x09, 0x40, 0x11, 0x40, 0x09, 0x13, 0x27, 0x27, 0x07, 0x07, 0x05, 0x1d, 0x0d, 0x13, 0x07, + 0x4a, 0x27, 0x17, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x01, 0x01, 0x44, 0x42, 0x03, 0x42, + 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, 0x44, 0x42, + 0x03, 0x42, 0x40, 0x07, 0x44, 0x4a, 0x4a, 0x09, 0x44, 0x4c, 0x4a, 0x4a, 0x09, 0x0d, 0x0b, 0x0f, + 0x1b, 0x46, 0x23, 0x40, 0x4a, 0x40, 0x01, 0x07, 0x01, 0x0b, 0x0b, 0x13, 0x03, 0x15, 0x03, 0x46, + 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x15, 0x03, 0x46, 0x19, 0x07, 0x40, 0x4a, + 0x07, 0x09, 0x09, 0x13, 0x1b, 0x13, 0x1b, 0x0d, 0x17, 0x03, 0x46, 0x17, 0x03, 0x46, 0x40, 0x40, + 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x29, 0x27, 0x19, 0x07, 0x1b, 0x19, 0x13, + 0x42, 0x27, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x15, 0x0d, 0x1f, 0x15, 0x15, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x16, 0x02, 0x4b, 0x40, 0x09, 0x4c, 0x56, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x03, 0x0f, + 0x02, 0x0b, 0x40, 0x12, 0x01, 0x0b, 0x15, 0x2a, 0x2a, 0x07, 0x07, 0x05, 0x1c, 0x0d, 0x14, 0x07, + 0x49, 0x27, 0x19, 0x0d, 0x40, 0x42, 0x01, 0x40, 0x40, 0x40, 0x02, 0x02, 0x43, 0x41, 0x04, 0x41, + 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, 0x43, 0x41, + 0x04, 0x41, 0x01, 0x09, 0x43, 0x49, 0x49, 0x0b, 0x43, 0x4b, 0x49, 0x49, 0x0b, 0x0e, 0x0c, 0x11, + 0x1c, 0x45, 0x25, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0c, 0x0c, 0x15, 0x04, 0x15, 0x03, 0x45, + 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x03, 0x45, 0x1a, 0x07, 0x40, 0x4a, + 0x07, 0x0a, 0x0a, 0x14, 0x1c, 0x14, 0x1c, 0x0d, 0x17, 0x03, 0x45, 0x17, 0x03, 0x45, 0x40, 0x40, + 0x40, 0x11, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x0b, 0x2a, 0x27, 0x1a, 0x07, 0x1c, 0x1a, 0x14, + 0x42, 0x26, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0b, 0x16, 0x0d, 0x21, 0x16, 0x16, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x17, 0x02, 0x4a, 0x40, 0x08, 0x4d, 0x57, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, + 0x02, 0x0d, 0x40, 0x12, 0x02, 0x0d, 0x17, 0x2c, 0x2c, 0x07, 0x07, 0x05, 0x1a, 0x0d, 0x15, 0x07, + 0x48, 0x27, 0x1a, 0x0d, 0x40, 0x42, 0x00, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x05, 0x40, + 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, 0x42, 0x40, + 0x05, 0x40, 0x02, 0x0a, 0x42, 0x48, 0x48, 0x0d, 0x42, 0x4a, 0x48, 0x48, 0x0d, 0x0f, 0x0d, 0x12, + 0x1d, 0x45, 0x27, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x17, 0x05, 0x15, 0x02, 0x45, + 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, + 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, + 0x40, 0x10, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, + 0x42, 0x25, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x17, 0x0d, 0x22, 0x17, 0x17, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x18, 0x02, 0x4a, 0x40, 0x07, 0x4d, 0x58, 0x2a, 0x40, 0x02, 0x40, 0x40, 0x02, 0x0f, + 0x02, 0x0e, 0x40, 0x12, 0x03, 0x0e, 0x19, 0x2f, 0x2f, 0x07, 0x07, 0x05, 0x19, 0x0d, 0x15, 0x07, + 0x47, 0x27, 0x1b, 0x0d, 0x40, 0x42, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x00, 0x05, 0x00, + 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, 0x42, 0x00, + 0x05, 0x00, 0x03, 0x0b, 0x42, 0x47, 0x47, 0x0e, 0x42, 0x4a, 0x47, 0x47, 0x0e, 0x10, 0x0d, 0x13, + 0x1d, 0x45, 0x29, 0x40, 0x4a, 0x40, 0x02, 0x07, 0x02, 0x0d, 0x0d, 0x19, 0x05, 0x15, 0x02, 0x45, + 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x15, 0x02, 0x45, 0x1a, 0x07, 0x40, 0x4a, + 0x07, 0x0a, 0x0a, 0x15, 0x1d, 0x15, 0x1d, 0x0d, 0x17, 0x02, 0x45, 0x17, 0x02, 0x45, 0x40, 0x40, + 0x40, 0x0f, 0x0d, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x0a, 0x2a, 0x27, 0x1a, 0x07, 0x1d, 0x1a, 0x15, + 0x42, 0x24, 0x15, 0x0d, 0x40, 0x0f, 0x0d, 0x0a, 0x18, 0x0d, 0x23, 0x18, 0x18, 0x0d, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x19, 0x03, 0x49, 0x40, 0x06, 0x4e, 0x59, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x01, 0x0f, + 0x03, 0x10, 0x40, 0x13, 0x04, 0x10, 0x1b, 0x31, 0x31, 0x07, 0x07, 0x04, 0x17, 0x0c, 0x16, 0x07, + 0x46, 0x27, 0x1c, 0x0c, 0x40, 0x43, 0x41, 0x40, 0x40, 0x40, 0x03, 0x03, 0x41, 0x01, 0x06, 0x01, + 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, 0x41, 0x01, + 0x06, 0x01, 0x04, 0x0c, 0x41, 0x46, 0x46, 0x10, 0x41, 0x49, 0x46, 0x46, 0x10, 0x11, 0x0e, 0x14, + 0x1e, 0x44, 0x2b, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0e, 0x0e, 0x1b, 0x06, 0x14, 0x01, 0x44, + 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x01, 0x44, 0x1b, 0x07, 0x40, 0x4b, + 0x07, 0x0b, 0x0b, 0x16, 0x1e, 0x16, 0x1e, 0x0c, 0x17, 0x01, 0x44, 0x17, 0x01, 0x44, 0x40, 0x40, + 0x40, 0x0e, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x09, 0x2b, 0x27, 0x1b, 0x07, 0x1e, 0x1b, 0x16, + 0x43, 0x22, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x09, 0x19, 0x0c, 0x24, 0x19, 0x19, 0x0c, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x1a, 0x03, 0x48, 0x40, 0x05, 0x4f, 0x5a, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, + 0x03, 0x11, 0x40, 0x13, 0x06, 0x11, 0x1d, 0x34, 0x34, 0x07, 0x07, 0x04, 0x16, 0x0c, 0x17, 0x07, + 0x45, 0x27, 0x1e, 0x0c, 0x40, 0x43, 0x42, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x02, 0x07, 0x02, + 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, 0x40, 0x02, + 0x07, 0x02, 0x06, 0x0e, 0x40, 0x45, 0x45, 0x11, 0x40, 0x48, 0x45, 0x45, 0x11, 0x12, 0x0f, 0x16, + 0x1f, 0x44, 0x2d, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1d, 0x07, 0x14, 0x00, 0x44, + 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, + 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, + 0x40, 0x0d, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, + 0x43, 0x21, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1a, 0x0c, 0x26, 0x1a, 0x1a, 0x0c, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x1b, 0x03, 0x48, 0x40, 0x04, 0x4f, 0x5b, 0x2b, 0x40, 0x03, 0x40, 0x40, 0x00, 0x0f, + 0x03, 0x13, 0x40, 0x13, 0x07, 0x13, 0x1f, 0x36, 0x36, 0x07, 0x07, 0x04, 0x14, 0x0c, 0x17, 0x07, + 0x44, 0x27, 0x1f, 0x0c, 0x40, 0x43, 0x43, 0x40, 0x40, 0x40, 0x03, 0x03, 0x40, 0x03, 0x07, 0x03, + 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, 0x40, 0x03, + 0x07, 0x03, 0x07, 0x0f, 0x40, 0x44, 0x44, 0x13, 0x40, 0x48, 0x44, 0x44, 0x13, 0x13, 0x0f, 0x17, + 0x1f, 0x44, 0x2f, 0x40, 0x4b, 0x40, 0x03, 0x07, 0x03, 0x0f, 0x0f, 0x1f, 0x07, 0x14, 0x00, 0x44, + 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x14, 0x00, 0x44, 0x1b, 0x07, 0x40, 0x4b, + 0x07, 0x0b, 0x0b, 0x17, 0x1f, 0x17, 0x1f, 0x0c, 0x17, 0x00, 0x44, 0x17, 0x00, 0x44, 0x40, 0x40, + 0x40, 0x0c, 0x0c, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x08, 0x2b, 0x27, 0x1b, 0x07, 0x1f, 0x1b, 0x17, + 0x43, 0x20, 0x14, 0x0c, 0x40, 0x0f, 0x0c, 0x08, 0x1b, 0x0c, 0x27, 0x1b, 0x1b, 0x0c, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x1c, 0x04, 0x47, 0x40, 0x03, 0x50, 0x5c, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x40, 0x0f, + 0x04, 0x14, 0x40, 0x14, 0x08, 0x14, 0x21, 0x39, 0x39, 0x07, 0x07, 0x03, 0x13, 0x0b, 0x18, 0x07, + 0x43, 0x27, 0x20, 0x0b, 0x40, 0x44, 0x44, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x04, 0x08, 0x04, + 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, 0x00, 0x04, + 0x08, 0x04, 0x08, 0x10, 0x00, 0x43, 0x43, 0x14, 0x00, 0x47, 0x43, 0x43, 0x14, 0x14, 0x10, 0x18, + 0x20, 0x43, 0x31, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x21, 0x08, 0x13, 0x40, 0x43, + 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x40, 0x43, 0x1c, 0x07, 0x40, 0x4c, + 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x40, 0x43, 0x17, 0x40, 0x43, 0x40, 0x40, + 0x40, 0x0b, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x07, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, + 0x44, 0x1f, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x07, 0x1c, 0x0b, 0x28, 0x1c, 0x1c, 0x0b, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x1d, 0x04, 0x47, 0x40, 0x02, 0x51, 0x5d, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, + 0x04, 0x16, 0x40, 0x14, 0x09, 0x16, 0x22, 0x3b, 0x3b, 0x07, 0x07, 0x03, 0x11, 0x0b, 0x18, 0x07, + 0x42, 0x27, 0x21, 0x0b, 0x40, 0x44, 0x45, 0x40, 0x40, 0x40, 0x04, 0x04, 0x00, 0x05, 0x08, 0x05, + 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, 0x00, 0x05, + 0x08, 0x05, 0x09, 0x11, 0x00, 0x42, 0x42, 0x16, 0x00, 0x47, 0x42, 0x42, 0x16, 0x15, 0x10, 0x19, + 0x20, 0x43, 0x32, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x10, 0x10, 0x22, 0x08, 0x13, 0x41, 0x43, + 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, + 0x07, 0x0c, 0x0c, 0x18, 0x20, 0x18, 0x20, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, + 0x40, 0x0a, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x20, 0x1c, 0x18, + 0x44, 0x1d, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1d, 0x0b, 0x29, 0x1d, 0x1d, 0x0b, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x1e, 0x04, 0x46, 0x40, 0x01, 0x51, 0x5e, 0x2c, 0x40, 0x04, 0x40, 0x40, 0x41, 0x0f, + 0x04, 0x18, 0x40, 0x14, 0x0b, 0x18, 0x24, 0x3e, 0x3e, 0x07, 0x07, 0x03, 0x0f, 0x0b, 0x19, 0x07, + 0x41, 0x27, 0x23, 0x0b, 0x40, 0x44, 0x46, 0x40, 0x40, 0x40, 0x04, 0x04, 0x01, 0x06, 0x09, 0x06, + 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, 0x01, 0x06, + 0x09, 0x06, 0x0b, 0x13, 0x01, 0x41, 0x41, 0x18, 0x01, 0x46, 0x41, 0x41, 0x18, 0x16, 0x11, 0x1b, + 0x21, 0x43, 0x34, 0x40, 0x4c, 0x40, 0x04, 0x07, 0x04, 0x11, 0x11, 0x24, 0x09, 0x13, 0x41, 0x43, + 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x13, 0x41, 0x43, 0x1c, 0x07, 0x40, 0x4c, + 0x07, 0x0c, 0x0c, 0x19, 0x21, 0x19, 0x21, 0x0b, 0x17, 0x41, 0x43, 0x17, 0x41, 0x43, 0x40, 0x40, + 0x40, 0x09, 0x0b, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x06, 0x2c, 0x27, 0x1c, 0x07, 0x21, 0x1c, 0x19, + 0x44, 0x1c, 0x13, 0x0b, 0x40, 0x0f, 0x0b, 0x06, 0x1e, 0x0b, 0x2b, 0x1e, 0x1e, 0x0b, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x1f, 0x05, 0x45, 0x40, 0x00, 0x52, 0x5f, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, + 0x05, 0x19, 0x40, 0x15, 0x0c, 0x19, 0x26, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0e, 0x0a, 0x1a, 0x07, + 0x40, 0x27, 0x24, 0x0a, 0x40, 0x45, 0x47, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x07, 0x0a, 0x07, + 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, 0x02, 0x07, + 0x0a, 0x07, 0x0c, 0x14, 0x02, 0x40, 0x40, 0x19, 0x02, 0x45, 0x40, 0x40, 0x19, 0x17, 0x12, 0x1c, + 0x22, 0x42, 0x36, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x26, 0x0a, 0x12, 0x42, 0x42, + 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, + 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, + 0x40, 0x08, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, + 0x45, 0x1b, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x1f, 0x0a, 0x2c, 0x1f, 0x1f, 0x0a, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x20, 0x05, 0x45, 0x40, 0x40, 0x52, 0x60, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x42, 0x0f, + 0x05, 0x1b, 0x40, 0x15, 0x0d, 0x1b, 0x28, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0c, 0x0a, 0x1a, 0x07, + 0x00, 0x27, 0x25, 0x0a, 0x40, 0x45, 0x48, 0x40, 0x40, 0x40, 0x05, 0x05, 0x02, 0x08, 0x0a, 0x08, + 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, 0x02, 0x08, + 0x0a, 0x08, 0x0d, 0x15, 0x02, 0x00, 0x00, 0x1b, 0x02, 0x45, 0x00, 0x00, 0x1b, 0x18, 0x12, 0x1d, + 0x22, 0x42, 0x38, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x12, 0x12, 0x28, 0x0a, 0x12, 0x42, 0x42, + 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x42, 0x42, 0x1d, 0x07, 0x40, 0x4d, + 0x07, 0x0d, 0x0d, 0x1a, 0x22, 0x1a, 0x22, 0x0a, 0x17, 0x42, 0x42, 0x17, 0x42, 0x42, 0x40, 0x40, + 0x40, 0x07, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x05, 0x2d, 0x27, 0x1d, 0x07, 0x22, 0x1d, 0x1a, + 0x45, 0x1a, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x05, 0x20, 0x0a, 0x2d, 0x20, 0x20, 0x0a, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x21, 0x05, 0x44, 0x40, 0x41, 0x53, 0x61, 0x2d, 0x40, 0x05, 0x40, 0x40, 0x43, 0x0f, + 0x05, 0x1c, 0x40, 0x15, 0x0e, 0x1c, 0x2a, 0x3e, 0x3e, 0x07, 0x07, 0x02, 0x0b, 0x0a, 0x1b, 0x07, + 0x01, 0x27, 0x26, 0x0a, 0x40, 0x45, 0x49, 0x40, 0x40, 0x40, 0x05, 0x05, 0x03, 0x09, 0x0b, 0x09, + 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, 0x03, 0x09, + 0x0b, 0x09, 0x0e, 0x16, 0x03, 0x01, 0x01, 0x1c, 0x03, 0x44, 0x01, 0x01, 0x1c, 0x19, 0x13, 0x1e, + 0x23, 0x42, 0x3a, 0x40, 0x4d, 0x40, 0x05, 0x07, 0x05, 0x13, 0x13, 0x2a, 0x0b, 0x12, 0x43, 0x42, + 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x12, 0x43, 0x42, 0x1d, 0x07, 0x40, 0x4d, + 0x07, 0x0d, 0x0d, 0x1b, 0x23, 0x1b, 0x23, 0x0a, 0x17, 0x43, 0x42, 0x17, 0x43, 0x42, 0x40, 0x40, + 0x40, 0x06, 0x0a, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x04, 0x2d, 0x27, 0x1d, 0x07, 0x23, 0x1d, 0x1b, + 0x45, 0x18, 0x12, 0x0a, 0x40, 0x0f, 0x0a, 0x04, 0x21, 0x0a, 0x2e, 0x21, 0x21, 0x0a, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x22, 0x06, 0x43, 0x40, 0x42, 0x54, 0x62, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, + 0x06, 0x1e, 0x40, 0x16, 0x10, 0x1e, 0x2c, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x09, 0x09, 0x1c, 0x07, + 0x02, 0x27, 0x28, 0x09, 0x40, 0x46, 0x4a, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0a, 0x0c, 0x0a, + 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, 0x04, 0x0a, + 0x0c, 0x0a, 0x10, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x04, 0x43, 0x02, 0x02, 0x1e, 0x1a, 0x14, 0x20, + 0x24, 0x41, 0x3c, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2c, 0x0c, 0x11, 0x44, 0x41, + 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, + 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, + 0x40, 0x05, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, + 0x46, 0x17, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x22, 0x09, 0x30, 0x22, 0x22, 0x09, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x23, 0x06, 0x43, 0x40, 0x43, 0x54, 0x63, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x44, 0x0f, + 0x06, 0x1f, 0x40, 0x16, 0x11, 0x1f, 0x2e, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x08, 0x09, 0x1c, 0x07, + 0x03, 0x27, 0x29, 0x09, 0x40, 0x46, 0x4b, 0x40, 0x40, 0x40, 0x06, 0x06, 0x04, 0x0b, 0x0c, 0x0b, + 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, 0x04, 0x0b, + 0x0c, 0x0b, 0x11, 0x19, 0x04, 0x03, 0x03, 0x1f, 0x04, 0x43, 0x03, 0x03, 0x1f, 0x1b, 0x14, 0x21, + 0x24, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x14, 0x14, 0x2e, 0x0c, 0x11, 0x44, 0x41, + 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x44, 0x41, 0x1e, 0x07, 0x40, 0x4e, + 0x07, 0x0e, 0x0e, 0x1c, 0x24, 0x1c, 0x24, 0x09, 0x17, 0x44, 0x41, 0x17, 0x44, 0x41, 0x40, 0x40, + 0x40, 0x04, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x03, 0x2e, 0x27, 0x1e, 0x07, 0x24, 0x1e, 0x1c, + 0x46, 0x16, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x03, 0x23, 0x09, 0x31, 0x23, 0x23, 0x09, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x44, 0x55, 0x64, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x45, 0x0f, + 0x06, 0x21, 0x40, 0x16, 0x12, 0x21, 0x30, 0x3e, 0x3e, 0x07, 0x07, 0x01, 0x06, 0x09, 0x1d, 0x07, + 0x04, 0x27, 0x2a, 0x09, 0x40, 0x46, 0x4c, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, + 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, 0x05, 0x0c, + 0x0d, 0x0c, 0x12, 0x1a, 0x05, 0x04, 0x04, 0x21, 0x05, 0x42, 0x04, 0x04, 0x21, 0x1c, 0x15, 0x22, + 0x25, 0x41, 0x3e, 0x40, 0x4e, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x30, 0x0d, 0x11, 0x45, 0x41, + 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x11, 0x45, 0x41, 0x1e, 0x07, 0x40, 0x4e, + 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x09, 0x17, 0x45, 0x41, 0x17, 0x45, 0x41, 0x40, 0x40, + 0x40, 0x03, 0x09, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x02, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, + 0x46, 0x15, 0x11, 0x09, 0x40, 0x0f, 0x09, 0x02, 0x24, 0x09, 0x32, 0x24, 0x24, 0x09, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x24, 0x06, 0x42, 0x40, 0x45, 0x56, 0x65, 0x2e, 0x40, 0x06, 0x40, 0x40, 0x46, 0x0f, + 0x06, 0x22, 0x40, 0x16, 0x13, 0x22, 0x31, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x04, 0x08, 0x1d, 0x07, + 0x04, 0x27, 0x2b, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x06, 0x06, 0x05, 0x0c, 0x0d, 0x0c, + 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, 0x05, 0x0c, + 0x0d, 0x0c, 0x13, 0x1b, 0x05, 0x04, 0x04, 0x22, 0x05, 0x42, 0x04, 0x04, 0x22, 0x1c, 0x15, 0x23, + 0x25, 0x41, 0x3e, 0x40, 0x4f, 0x40, 0x06, 0x07, 0x06, 0x15, 0x15, 0x31, 0x0d, 0x10, 0x46, 0x41, + 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x10, 0x46, 0x41, 0x1e, 0x07, 0x40, 0x4f, + 0x07, 0x0e, 0x0e, 0x1d, 0x25, 0x1d, 0x25, 0x08, 0x17, 0x46, 0x41, 0x17, 0x46, 0x41, 0x40, 0x40, + 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2e, 0x27, 0x1e, 0x07, 0x25, 0x1e, 0x1d, + 0x47, 0x13, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x24, 0x08, 0x33, 0x24, 0x24, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x25, 0x07, 0x41, 0x40, 0x45, 0x56, 0x65, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x46, 0x0f, + 0x07, 0x24, 0x40, 0x17, 0x15, 0x24, 0x33, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x03, 0x08, 0x1e, 0x07, + 0x05, 0x27, 0x2d, 0x08, 0x40, 0x47, 0x4d, 0x40, 0x40, 0x40, 0x07, 0x07, 0x06, 0x0d, 0x0e, 0x0d, + 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, 0x06, 0x0d, + 0x0e, 0x0d, 0x15, 0x1d, 0x06, 0x05, 0x05, 0x24, 0x06, 0x41, 0x05, 0x05, 0x24, 0x1d, 0x16, 0x25, + 0x26, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x16, 0x16, 0x33, 0x0e, 0x10, 0x46, 0x40, + 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x46, 0x40, 0x1f, 0x07, 0x40, 0x4f, + 0x07, 0x0f, 0x0f, 0x1e, 0x26, 0x1e, 0x26, 0x08, 0x17, 0x46, 0x40, 0x17, 0x46, 0x40, 0x40, 0x40, + 0x40, 0x02, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x01, 0x2f, 0x27, 0x1f, 0x07, 0x26, 0x1f, 0x1e, + 0x47, 0x12, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x01, 0x25, 0x08, 0x35, 0x25, 0x25, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x26, 0x07, 0x40, 0x40, 0x46, 0x57, 0x66, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, + 0x07, 0x26, 0x40, 0x17, 0x16, 0x26, 0x35, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x01, 0x08, 0x1f, 0x07, + 0x06, 0x27, 0x2e, 0x08, 0x40, 0x47, 0x4e, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0e, 0x0f, 0x0e, + 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, 0x07, 0x0e, + 0x0f, 0x0e, 0x16, 0x1e, 0x07, 0x06, 0x06, 0x26, 0x07, 0x40, 0x06, 0x06, 0x26, 0x1e, 0x17, 0x26, + 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x35, 0x0f, 0x10, 0x47, 0x40, + 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, + 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, + 0x40, 0x01, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, + 0x47, 0x11, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x26, 0x08, 0x36, 0x26, 0x26, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x3e, 0x27, 0x07, 0x40, 0x40, 0x47, 0x57, 0x67, 0x2f, 0x40, 0x07, 0x40, 0x40, 0x47, 0x0f, + 0x07, 0x27, 0x40, 0x17, 0x17, 0x27, 0x37, 0x3e, 0x3e, 0x07, 0x07, 0x00, 0x00, 0x08, 0x1f, 0x07, + 0x07, 0x27, 0x2f, 0x08, 0x40, 0x47, 0x4f, 0x40, 0x40, 0x40, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x0f, + 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, 0x07, 0x0f, + 0x0f, 0x0f, 0x17, 0x1f, 0x07, 0x07, 0x07, 0x27, 0x07, 0x40, 0x07, 0x07, 0x27, 0x1f, 0x17, 0x27, + 0x27, 0x40, 0x3e, 0x40, 0x4f, 0x40, 0x07, 0x07, 0x07, 0x17, 0x17, 0x37, 0x0f, 0x10, 0x47, 0x40, + 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x10, 0x47, 0x40, 0x1f, 0x07, 0x40, 0x4f, + 0x07, 0x0f, 0x0f, 0x1f, 0x27, 0x1f, 0x27, 0x08, 0x17, 0x47, 0x40, 0x17, 0x47, 0x40, 0x40, 0x40, + 0x40, 0x00, 0x08, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x00, 0x2f, 0x27, 0x1f, 0x07, 0x27, 0x1f, 0x1f, + 0x47, 0x10, 0x10, 0x08, 0x40, 0x0f, 0x08, 0x00, 0x27, 0x08, 0x37, 0x27, 0x27, 0x08, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +MPP_RET hal_h265d_vdpu38x_deinit(void *hal) +{ + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_U32 loop = reg_ctx->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->g_buf) : 1; + RK_U32 i; + + if (reg_ctx->bufs) { + mpp_buffer_put(reg_ctx->bufs); + reg_ctx->bufs = NULL; + } + + loop = reg_ctx->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->rcb_buf) : 1; + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + } + vdpu38x_rcb_calc_deinit((Vdpu38xRcbCtx *)reg_ctx->rcb_ctx); + + for (i = 0; i < loop; i++) + MPP_FREE(reg_ctx->g_buf[i].hw_regs); + + MPP_FREE(reg_ctx->scaling_qm); + MPP_FREE(reg_ctx->scaling_rk); + MPP_FREE(reg_ctx->pps_buf); + MPP_FREE(reg_ctx->sw_rps_buf); + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + if (reg_ctx->origin_bufs) { + hal_bufs_deinit(reg_ctx->origin_bufs); + reg_ctx->origin_bufs = NULL; + } + + return MPP_OK; +} + +MPP_RET hal_h265d_vdpu_reset(void *hal) +{ + HalH265dCtx *p_hal = (HalH265dCtx *)hal; + MPP_RET ret = MPP_OK; + + p_hal->fast_mode_err_found = 0; + + return ret; +} + +MPP_RET hal_h265d_vdpu_flush(void *hal) +{ + (void)hal; + + return MPP_OK; +} + +MPP_RET hal_h265d_vdpu38x_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_OK; + HalH265dCtx *p_hal = (HalH265dCtx *)hal; + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrame frame = (MppFrame)param; + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + RK_U32 imgwidth = mpp_frame_get_width((MppFrame)param); + RK_U32 imgheight = mpp_frame_get_height((MppFrame)param); + + if (fmt == MPP_FMT_YUV422SP) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } else if (fmt == MPP_FMT_YUV444SP || fmt == MPP_FMT_YUV444SP_10BIT) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv444); + } + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, frame, 16); + } else if (imgwidth > 1920 || imgheight > 1088) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + } + break; + } + case MPP_DEC_GET_THUMBNAIL_FRAME_INFO: { + vdpu38x_update_thumbnail_frame_info((MppFrame)param); + } break; + case MPP_DEC_SET_OUTPUT_FORMAT: { + } break; + default: { + } break; + } + return ret; +} + +#define SCALING_LIST_NUM 6 +void hal_vdpu38x_record_scaling_list(scalingFactor_t *pScalingFactor_out, scalingList_t *pScalingList) +{ + BitputCtx_t bp; + RK_U32 listId; + RK_S32 i; + + mpp_set_bitput_ctx(&bp, (RK_U64 *)pScalingFactor_out, 170); // 170*64bits + + //-------- following make it by hardware needed -------- + //sizeId == 0, block4x4 + for (listId = 0; listId < SCALING_LIST_NUM; listId++) { + RK_U8 *p_data = pScalingList->sl[0][listId]; + /* dump by block4x4, vectial direction */ + for (i = 0; i < 4; i++) { + mpp_put_bits(&bp, p_data[i + 0], 8); + mpp_put_bits(&bp, p_data[i + 4], 8); + mpp_put_bits(&bp, p_data[i + 8], 8); + mpp_put_bits(&bp, p_data[i + 12], 8); + } + } + //sizeId == 1, block8x8 + for (listId = 0; listId < SCALING_LIST_NUM; listId++) { + RK_S32 blk4_x = 0, blk4_y = 0; + RK_U8 *p_data = pScalingList->sl[1][listId]; + + /* dump by block4x4, vectial direction */ + for (blk4_x = 0; blk4_x < 8; blk4_x += 4) { + for (blk4_y = 0; blk4_y < 8; blk4_y += 4) { + RK_S32 pos = blk4_y * 8 + blk4_x; + + for (i = 0; i < 4; i++) { + mpp_put_bits(&bp, p_data[pos + i + 0], 8); + mpp_put_bits(&bp, p_data[pos + i + 8], 8); + mpp_put_bits(&bp, p_data[pos + i + 16], 8); + mpp_put_bits(&bp, p_data[pos + i + 24], 8); + } + } + } + } + //sizeId == 2, block16x16 + for (listId = 0; listId < SCALING_LIST_NUM; listId++) { + RK_S32 blk4_x = 0, blk4_y = 0; + RK_U8 *p_data = pScalingList->sl[2][listId]; + + /* dump by block4x4, vectial direction */ + for (blk4_x = 0; blk4_x < 8; blk4_x += 4) { + for (blk4_y = 0; blk4_y < 8; blk4_y += 4) { + RK_S32 pos = blk4_y * 8 + blk4_x; + + for (i = 0; i < 4; i++) { + mpp_put_bits(&bp, p_data[pos + i + 0], 8); + mpp_put_bits(&bp, p_data[pos + i + 8], 8); + mpp_put_bits(&bp, p_data[pos + i + 16], 8); + mpp_put_bits(&bp, p_data[pos + i + 24], 8); + } + } + } + } + //sizeId == 3, blcok32x32 + for (listId = 0; listId < 6; listId++) { + RK_S32 blk4_x = 0, blk4_y = 0; + RK_U8 *p_data = pScalingList->sl[3][listId]; + + /* dump by block4x4, vectial direction */ + for (blk4_x = 0; blk4_x < 8; blk4_x += 4) { + for (blk4_y = 0; blk4_y < 8; blk4_y += 4) { + RK_S32 pos = blk4_y * 8 + blk4_x; + + for (i = 0; i < 4; i++) { + mpp_put_bits(&bp, p_data[pos + i + 0], 8); + mpp_put_bits(&bp, p_data[pos + i + 8], 8); + mpp_put_bits(&bp, p_data[pos + i + 16], 8); + mpp_put_bits(&bp, p_data[pos + i + 24], 8); + } + } + } + } + //sizeId == 0, block4x4, horiztion direction */ + for (listId = 0; listId < SCALING_LIST_NUM; listId++) { + RK_U8 *p_data = pScalingList->sl[0][listId]; + + for (i = 0; i < 16; i++) + mpp_put_bits(&bp, p_data[i], 8); + } + + // dump dc value + for (i = 0; i < SCALING_LIST_NUM; i++)//sizeId = 2, 16x16 + mpp_put_bits(&bp, pScalingList->sl_dc[0][i], 8); + for (i = 0; i < SCALING_LIST_NUM; i++) //sizeId = 3, 32x32 + mpp_put_bits(&bp, pScalingList->sl_dc[1][i], 8); + + mpp_put_align(&bp, 128, 0); +} + +MPP_RET hal_h265d_vdpu38x_scalinglist_packet(void *hal, void *ptr, void *dxva) +{ + scalingList_t sl; + h265d_dxva2_picture_context_t *dxva_ctx = (h265d_dxva2_picture_context_t*)dxva; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + RK_U32 i, j, pos; + + if (!dxva_ctx->pp.scaling_list_enabled_flag) { + return MPP_OK; + } + + if (memcmp((void*)&dxva_ctx->qm, reg_ctx->scaling_qm, sizeof(DXVA_Qmatrix_HEVC))) { + memset(&sl, 0, sizeof(scalingList_t)); + + for (i = 0; i < 6; i++) { + for (j = 0; j < 16; j++) { + pos = 4 * hal_hevc_diag_scan4x4_y[j] + hal_hevc_diag_scan4x4_x[j]; + sl.sl[0][i][pos] = dxva_ctx->qm.ucScalingLists0[i][j]; + } + + for (j = 0; j < 64; j++) { + pos = 8 * hal_hevc_diag_scan8x8_y[j] + hal_hevc_diag_scan8x8_x[j]; + sl.sl[1][i][pos] = dxva_ctx->qm.ucScalingLists1[i][j]; + sl.sl[2][i][pos] = dxva_ctx->qm.ucScalingLists2[i][j]; + + if (i == 0) + sl.sl[3][i][pos] = dxva_ctx->qm.ucScalingLists3[0][j]; + else if (i == 3) + sl.sl[3][i][pos] = dxva_ctx->qm.ucScalingLists3[1][j]; + else + sl.sl[3][i][pos] = dxva_ctx->qm.ucScalingLists2[i][j]; + } + + sl.sl_dc[0][i] = dxva_ctx->qm.ucScalingListDCCoefSizeID2[i]; + if (i == 0) + sl.sl_dc[1][i] = dxva_ctx->qm.ucScalingListDCCoefSizeID3[0]; + else if (i == 3) + sl.sl_dc[1][i] = dxva_ctx->qm.ucScalingListDCCoefSizeID3[1]; + else + sl.sl_dc[1][i] = dxva_ctx->qm.ucScalingListDCCoefSizeID2[i]; + } + hal_vdpu38x_record_scaling_list((scalingFactor_t *)reg_ctx->scaling_rk, &sl); + } + + memcpy(ptr, reg_ctx->scaling_rk, sizeof(scalingFactor_t)); + + return MPP_OK; +} + +RK_S32 hal_h265d_vdpu38x_output_pps_packet(void *hal, void *dxva, RK_U32 *scanlist_addr) +{ + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_ctx = (h265d_dxva2_picture_context_t*)dxva; + RK_U32 log2_min_cb_size; + RK_S32 width, height; + BitputCtx_t bp; + RockchipSocType soc_type = mpp_get_soc_type(); + RK_S32 i; + + if (NULL == reg_ctx || NULL == dxva_ctx) { + mpp_err("hal: reg_ctx or dxva_ctx is NULL at %s:%d\n", + __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + + // SPS + { + void *pps_ptr = mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->spspps_offset; + RK_U64 *pps_packet = reg_ctx->pps_buf; + + if (NULL == pps_ptr) { + mpp_err("hal: pps_data get ptr failed\n"); + return MPP_ERR_NOMEM; + } + + log2_min_cb_size = dxva_ctx->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_ctx->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_ctx->pp.PicHeightInMinCbsY << log2_min_cb_size); + + mpp_set_bitput_ctx(&bp, pps_packet, reg_ctx->pps_buf_sz / 8); + + if (dxva_ctx->pp.ps_update_flag) { + mpp_put_bits(&bp, dxva_ctx->pp.vps_id, 4); + mpp_put_bits(&bp, dxva_ctx->pp.sps_id, 4); + mpp_put_bits(&bp, dxva_ctx->pp.chroma_format_idc, 2); + + mpp_put_bits(&bp, width, 16); + mpp_put_bits(&bp, height, 16); + mpp_put_bits(&bp, dxva_ctx->pp.bit_depth_luma_minus8, 3); + mpp_put_bits(&bp, dxva_ctx->pp.bit_depth_chroma_minus8, 3); + mpp_put_bits(&bp, dxva_ctx->pp.log2_max_pic_order_cnt_lsb_minus4 + 4, 5); + mpp_put_bits(&bp, dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size, 2); + mpp_put_bits(&bp, dxva_ctx->pp.log2_min_luma_coding_block_size_minus3 + 3, 3); + mpp_put_bits(&bp, dxva_ctx->pp.log2_min_transform_block_size_minus2 + 2, 3); + + mpp_put_bits(&bp, dxva_ctx->pp.log2_diff_max_min_transform_block_size, 2); + mpp_put_bits(&bp, dxva_ctx->pp.max_transform_hierarchy_depth_inter, 3); + mpp_put_bits(&bp, dxva_ctx->pp.max_transform_hierarchy_depth_intra, 3); + mpp_put_bits(&bp, dxva_ctx->pp.scaling_list_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.amp_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.sample_adaptive_offset_enabled_flag, 1); + ///<-zrh comment ^ 68 bit above + mpp_put_bits(&bp, dxva_ctx->pp.pcm_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.pcm_enabled_flag ? (dxva_ctx->pp.pcm_sample_bit_depth_luma_minus1 + 1) : 0, 4); + mpp_put_bits(&bp, dxva_ctx->pp.pcm_enabled_flag ? (dxva_ctx->pp.pcm_sample_bit_depth_chroma_minus1 + 1) : 0, 4); + mpp_put_bits(&bp, dxva_ctx->pp.pcm_loop_filter_disabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.log2_diff_max_min_pcm_luma_coding_block_size, 3); + mpp_put_bits(&bp, dxva_ctx->pp.pcm_enabled_flag ? (dxva_ctx->pp.log2_min_pcm_luma_coding_block_size_minus3 + 3) : 0, 3); + + mpp_put_bits(&bp, dxva_ctx->pp.num_short_term_ref_pic_sets, 7); + mpp_put_bits(&bp, dxva_ctx->pp.long_term_ref_pics_present_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.num_long_term_ref_pics_sps, 6); + mpp_put_bits(&bp, dxva_ctx->pp.sps_temporal_mvp_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.strong_intra_smoothing_enabled_flag, 1); + // SPS extenstion + mpp_put_bits(&bp, dxva_ctx->pp.transform_skip_rotation_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.transform_skip_context_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.strong_intra_smoothing_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.implicit_rdpcm_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.explicit_rdpcm_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.extended_precision_processing_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.intra_smoothing_disabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.sps_max_dec_pic_buffering_minus1, 4); + mpp_put_bits(&bp, dxva_ctx->pp.separate_colour_plane_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.high_precision_offsets_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.persistent_rice_adaptation_enabled_flag, 1); + + /* PPS */ + mpp_put_bits(&bp, dxva_ctx->pp.pps_id, 6); + mpp_put_bits(&bp, dxva_ctx->pp.sps_id, 4); + mpp_put_bits(&bp, dxva_ctx->pp.dependent_slice_segments_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.output_flag_present_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.num_extra_slice_header_bits, 13); + + mpp_put_bits(&bp, dxva_ctx->pp.sign_data_hiding_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.cabac_init_present_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.num_ref_idx_l0_default_active_minus1 + 1, 4); + mpp_put_bits(&bp, dxva_ctx->pp.num_ref_idx_l1_default_active_minus1 + 1, 4); + mpp_put_bits(&bp, dxva_ctx->pp.init_qp_minus26, 7); + mpp_put_bits(&bp, dxva_ctx->pp.constrained_intra_pred_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.transform_skip_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.cu_qp_delta_enabled_flag, 1); + mpp_put_bits(&bp, log2_min_cb_size + dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size - dxva_ctx->pp.diff_cu_qp_delta_depth, 3); + + mpp_put_bits(&bp, dxva_ctx->pp.pps_cb_qp_offset, 5); + mpp_put_bits(&bp, dxva_ctx->pp.pps_cr_qp_offset, 5); + mpp_put_bits(&bp, dxva_ctx->pp.pps_slice_chroma_qp_offsets_present_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.weighted_pred_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.weighted_bipred_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.transquant_bypass_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.tiles_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.entropy_coding_sync_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.pps_loop_filter_across_slices_enabled_flag, 1); + + mpp_put_bits(&bp, dxva_ctx->pp.loop_filter_across_tiles_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.deblocking_filter_override_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.pps_deblocking_filter_disabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.pps_beta_offset_div2, 4); + mpp_put_bits(&bp, dxva_ctx->pp.pps_tc_offset_div2, 4); + mpp_put_bits(&bp, dxva_ctx->pp.lists_modification_present_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.log2_parallel_merge_level_minus2 + 2, 3); + mpp_put_bits(&bp, dxva_ctx->pp.slice_segment_header_extension_present_flag, 1); + mpp_put_bits(&bp, 0, 3); + + // PPS externsion + if (dxva_ctx->pp.log2_max_transform_skip_block_size > 2) { + mpp_put_bits(&bp, dxva_ctx->pp.log2_max_transform_skip_block_size - 2, 2); + } else { + mpp_put_bits(&bp, 0, 2); + } + mpp_put_bits(&bp, dxva_ctx->pp.cross_component_prediction_enabled_flag, 1); + mpp_put_bits(&bp, dxva_ctx->pp.chroma_qp_offset_list_enabled_flag, 1); + + RK_S32 log2_min_cu_chroma_qp_delta_size = log2_min_cb_size + + dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size - + dxva_ctx->pp.diff_cu_chroma_qp_offset_depth; + mpp_put_bits(&bp, log2_min_cu_chroma_qp_delta_size, 3); + for (i = 0; i < 6; i++) + mpp_put_bits(&bp, dxva_ctx->pp.cb_qp_offset_list[i], 5); + for (i = 0; i < 6; i++) + mpp_put_bits(&bp, dxva_ctx->pp.cr_qp_offset_list[i], 5); + mpp_put_bits(&bp, dxva_ctx->pp.chroma_qp_offset_list_len_minus1, 3); + + /* mvc0 && mvc1 */ + mpp_put_bits(&bp, 0xffff, 16); + mpp_put_bits(&bp, 0, 1); + mpp_put_bits(&bp, 0, 6); + mpp_put_bits(&bp, 0, 1); + mpp_put_bits(&bp, 0, 1); + } else { + bp.index = 4; + bp.bitpos = 41; + bp.bvalue = bp.pbuf[bp.index] & MPP_GENMASK(bp.bitpos - 1, 0); + } + /* poc info */ + { + RK_S32 dpb_valid[15] = {0}, refpic_poc[15] = {0}; + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_ctx->pp.RefPicList); i++) { + if (dxva_ctx->pp.RefPicList[i].bPicEntry != 0xff && + dxva_ctx->pp.RefPicList[i].bPicEntry != 0x7f) { + dpb_valid[i] = 1; + refpic_poc[i] = dxva_ctx->pp.PicOrderCntValList[i]; + } + } + + mpp_put_bits(&bp, 0, 1); + mpp_put_bits(&bp, 0, 1); + mpp_put_bits(&bp, 0, 1); + mpp_put_bits(&bp, dxva_ctx->pp.current_poc, 32); + + for (i = 0; i < 15; i++) + mpp_put_bits(&bp, refpic_poc[i], 32); + mpp_put_bits(&bp, 0, 32); + for (i = 0; i < 15; i++) + mpp_put_bits(&bp, dpb_valid[i], 1); + mpp_put_bits(&bp, 0, 1); + } + + /* tile info */ + mpp_put_bits(&bp, dxva_ctx->pp.tiles_enabled_flag ? (dxva_ctx->pp.num_tile_columns_minus1 + 1) : 1, 5); + mpp_put_bits(&bp, dxva_ctx->pp.tiles_enabled_flag ? (dxva_ctx->pp.num_tile_rows_minus1 + 1) : 1, 5); + { + /// tiles info begin + RK_U16 column_width[20]; + RK_U16 row_height[22]; + + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + if (dxva_ctx->pp.tiles_enabled_flag) { + if (dxva_ctx->pp.uniform_spacing_flag == 0) { + RK_S32 maxcuwidth = dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size; + RK_S32 ctu_width_in_pic = (width + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 ctu_height_in_pic = (height + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 sum = 0; + for (i = 0; i < dxva_ctx->pp.num_tile_columns_minus1; i++) { + column_width[i] = dxva_ctx->pp.column_width_minus1[i] + 1; + sum += column_width[i] ; + } + column_width[i] = ctu_width_in_pic - sum; + + sum = 0; + for (i = 0; i < dxva_ctx->pp.num_tile_rows_minus1; i++) { + row_height[i] = dxva_ctx->pp.row_height_minus1[i] + 1; + sum += row_height[i]; + } + row_height[i] = ctu_height_in_pic - sum; + } else { + RK_S32 pic_in_cts_width = (width + (1 << (log2_min_cb_size + + dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size)); + RK_S32 pic_in_cts_height = (height + (1 << (log2_min_cb_size + + dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size)); + + for (i = 0; i < dxva_ctx->pp.num_tile_columns_minus1 + 1; i++) + column_width[i] = ((i + 1) * pic_in_cts_width) / (dxva_ctx->pp.num_tile_columns_minus1 + 1) - + (i * pic_in_cts_width) / (dxva_ctx->pp.num_tile_columns_minus1 + 1); + + for (i = 0; i < dxva_ctx->pp.num_tile_rows_minus1 + 1; i++) + row_height[i] = ((i + 1) * pic_in_cts_height) / (dxva_ctx->pp.num_tile_rows_minus1 + 1) - + (i * pic_in_cts_height) / (dxva_ctx->pp.num_tile_rows_minus1 + 1); + } + } else { + RK_S32 MaxCUWidth = (1 << (dxva_ctx->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size)); + column_width[0] = (width + MaxCUWidth - 1) / MaxCUWidth; + row_height[0] = (height + MaxCUWidth - 1) / MaxCUWidth; + } + + for (i = 0; i < 20; i++) + mpp_put_bits(&bp, column_width[i], 12); + + for (i = 0; i < 22; i++) + mpp_put_bits(&bp, row_height[i], 12); + } + /* update rps */ + if ((soc_type == ROCKCHIP_SOC_RK3538 || + soc_type == ROCKCHIP_SOC_RK3572 || + soc_type == ROCKCHIP_SOC_RK3539) && + dxva_ctx->pp.rps_update_flag) { + Short_SPS_RPS_HEVC *cur_st_rps_ptr = &dxva_ctx->pp.cur_st_rps; + + for (i = 0; i < 32; i ++) { + mpp_put_bits(&bp, dxva_ctx->pp.sps_lt_rps[i].lt_ref_pic_poc_lsb, 16); + mpp_put_bits(&bp, dxva_ctx->pp.sps_lt_rps[i].used_by_curr_pic_lt_flag, 1); + } + + mpp_put_bits(&bp, cur_st_rps_ptr->num_negative_pics, 4); + mpp_put_bits(&bp, cur_st_rps_ptr->num_positive_pics, 4); + + for (i = 0; i < cur_st_rps_ptr->num_negative_pics; i++) { + mpp_put_bits(&bp, cur_st_rps_ptr->delta_poc_s0[i], 16); + mpp_put_bits(&bp, cur_st_rps_ptr->s0_used_flag[i], 1); + } + + for (i = 0; i < cur_st_rps_ptr->num_positive_pics; i++) { + mpp_put_bits(&bp, cur_st_rps_ptr->delta_poc_s1[i], 16); + mpp_put_bits(&bp, cur_st_rps_ptr->s1_used_flag[i], 1); + } + + for ( i = cur_st_rps_ptr->num_negative_pics + cur_st_rps_ptr->num_positive_pics; i < 15; i++) { + mpp_put_bits(&bp, 0, 16); + mpp_put_bits(&bp, 0, 1); + } + } + mpp_put_align(&bp, 64, 0);//128 + memcpy(pps_ptr, reg_ctx->pps_buf, reg_ctx->pps_buf_sz); + } /* --- end spspps data ------*/ + + if (dxva_ctx->pp.scaling_list_enabled_flag) { + RK_U32 addr; + RK_U8 *ptr_scaling = (RK_U8 *)mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->sclst_offset; + + if (dxva_ctx->pp.scaling_list_data_present_flag) { + addr = (dxva_ctx->pp.pps_id + 16) * 1360; + } else if (dxva_ctx->pp.scaling_list_enabled_flag) { + addr = dxva_ctx->pp.sps_id * 1360; + } else { + addr = 80 * 1360; + } + + hal_h265d_vdpu38x_scalinglist_packet(hal, ptr_scaling + addr, dxva); + + *scanlist_addr = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(reg_ctx->cfg->dev, 132, addr + reg_ctx->sclst_offset); + } + +#ifdef dump + fwrite(pps_ptr, 1, 80 * 64, fp); + RK_U32 *tmp = (RK_U32 *)pps_ptr; + for (i = 0; i < 112 / 4; i++) { + mpp_log("pps[%3d] = 0x%08x\n", i, tmp[i]); + } +#endif +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "global_cfg.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)bp.pbuf, + 64 * bp.index + bp.bitpos, 128, 0, 0); + } +#endif + + return 0; +} + +void vdpu38x_h265d_rcb_setup(void *hal, h265d_dxva2_picture_context_t *dxva, + HalTaskInfo *task, RK_S32 width, RK_S32 height, + Vdpu38xRcbRegSet *rcb_regs, Vdpu38xRcbCalc_f func) +{ + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_ctx = (h265d_dxva2_picture_context_t*)dxva; + DXVA_PicParams_HEVC *pp = &dxva_ctx->pp; + RK_U32 chroma_fmt_idc = pp->chroma_format_idc;//0 400,1 4202 ,422,3 444 + RK_U8 bit_depth = MPP_MAX(pp->bit_depth_luma_minus8, pp->bit_depth_chroma_minus8) + 8; + RK_U8 ctu_size = 1 << (pp->log2_diff_max_min_luma_coding_block_size + + pp->log2_min_luma_coding_block_size_minus3 + 3); + RK_U32 num_tiles = pp->num_tile_rows_minus1 + 1; + MppBuffer rcb_buf; + + if (reg_ctx->num_row_tiles != num_tiles || + reg_ctx->bit_depth != bit_depth || + reg_ctx->chroma_fmt_idc != chroma_fmt_idc || + reg_ctx->ctu_size != ctu_size || + reg_ctx->width != width || + reg_ctx->height != height) { + RK_U32 loop = reg_ctx->fast_mode ? MPP_ARRAY_ELEMS(reg_ctx->g_buf) : 1; + RK_U32 i = 0; + + /* update rcb info */ + { + RcbTileInfo tl_info; + MppFrame mframe; + MppFrameFormat mpp_fmt; + Vdpu38xFmt rcb_fmt; + + mpp_buf_slot_get_prop(reg_ctx->cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + mpp_fmt = mpp_frame_get_fmt(mframe); + rcb_fmt = vdpu38x_fmt_mpp2hal(mpp_fmt); + + vdpu38x_rcb_reset(reg_ctx->rcb_ctx); + + /* update general info */ + vdpu38x_rcb_set_pic_w(reg_ctx->rcb_ctx, width); + vdpu38x_rcb_set_pic_h(reg_ctx->rcb_ctx, height); + vdpu38x_rcb_set_fmt(reg_ctx->rcb_ctx, rcb_fmt); + vdpu38x_rcb_set_bit_depth(reg_ctx->rcb_ctx, bit_depth); + + /* add tile info */ + /* Simplify the calculation. */ + tl_info.lt_x = 0; + tl_info.lt_y = 0; + tl_info.w = width; + tl_info.h = height; + vdpu38x_rcb_set_tile_dir(reg_ctx->rcb_ctx, 0); + vdpu38x_rcb_add_tile_info(reg_ctx->rcb_ctx, &tl_info); + vdpu38x_rcb_register_calc_handle(reg_ctx->rcb_ctx, func); + } + + vdpu38x_rcb_calc_exec(reg_ctx->rcb_ctx, ®_ctx->rcb_buf_size); + /* vdpu384b_check_rcb_buf_size((VdpuRcbInfo *)reg_ctx->rcb_info, width, height); */ + + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + mpp_buffer_get(reg_ctx->cfg->buf_group, &rcb_buf, reg_ctx->rcb_buf_size); + reg_ctx->rcb_buf[i] = rcb_buf; + } + + reg_ctx->num_row_tiles = num_tiles; + reg_ctx->bit_depth = bit_depth; + reg_ctx->chroma_fmt_idc = chroma_fmt_idc; + reg_ctx->ctu_size = ctu_size; + reg_ctx->width = width; + reg_ctx->height = height; + } + + rcb_buf = reg_ctx->fast_mode ? reg_ctx->rcb_buf[task->dec.reg_index] + : reg_ctx->rcb_buf[0]; + vdpu38x_setup_rcb(reg_ctx->rcb_ctx, rcb_regs, reg_ctx->cfg->dev, rcb_buf); +} diff --git a/mpp/hal/rkdec/h265d/hal_h265d_com.h b/mpp/hal/rkdec/h265d/hal_h265d_com.h new file mode 100644 index 000000000..97ac149a8 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_com.h @@ -0,0 +1,169 @@ +/* + * + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265D_COM_H +#define HAL_H265D_COM_H + +#include + +#include "h265d_syntax.h" + +#include "hal_h265d_ctx.h" +#include "vdpu38x_com.h" + +#define SCALING_LIST_SIZE (81 * 1360) +#define RPS_SIZE (600 * 32) +#define SCALING_LIST_SIZE_NUM 4 + +#define L0 0 +#define L1 1 +#define MAX_REFS 16 + +#define IS_IDR(nal_type) (nal_type == 19 || nal_type == 20) +#define IS_BLA(nal_type) (nal_type == 17 || nal_type == 16 || nal_type == 18) +#define IS_IRAP(nal_type) (nal_type >= 16 && nal_type <= 23) + +enum RPSType { + ST_CURR_BEF = 0, + ST_CURR_AFT, + ST_FOLL, + LT_CURR, + LT_FOLL, + NB_RPS_TYPE, +}; + +enum SliceType { + B_SLICE = 0, + P_SLICE = 1, + I_SLICE = 2, +}; + +typedef struct slice_ref_map { + RK_U8 dpb_index; + RK_U8 is_long_term; +} slice_ref_map_t; + +// Per-slice RPS data structure +typedef struct H265dSliceRpsData { + RK_U8 rps_bit_offset; + RK_U8 rps_bit_offset_st; + RK_U8 slice_nb_rps_poc; + RK_U8 lowdelay_flag; + slice_ref_map_t rps_pic_info[2][15]; +} H265dSliceRpsData_t; + +typedef struct RefPicList { + RK_U32 dpb_index[MAX_REFS]; + RK_U32 nb_refs; +} RefPicList_t; + +typedef struct RefPicListTab { + RefPicList_t refPicList[2]; +} RefPicListTab_t; + +typedef struct SliceHeader { + RK_U32 pps_id; + + ///< address (in raster order) of the first block in the current slice segment + RK_U32 slice_segment_addr; + ///< address (in raster order) of the first block in the current slice + RK_U32 slice_addr; + + enum SliceType slice_type; + + RK_S32 pic_order_cnt_lsb; + + RK_U8 first_slice_in_pic_flag; + RK_U8 dependent_slice_segment_flag; + RK_U8 pic_output_flag; + RK_U8 colour_plane_id; + + ///< RPS coded in the slice header itself is stored here + H265dStRps st_rps_slice; + const H265dStRps *st_rps_using; + H265dLtRps lt_rps; + RK_U32 list_entry_lx[2][32]; + + RK_U8 rpl_modification_flag[2]; + RK_U8 no_output_of_prior_pics_flag; + RK_U8 slice_temporal_mvp_enabled_flag; + + RK_U32 nb_refs[2]; + + RK_U8 slice_sample_adaptive_offset_flag[3]; + RK_U8 mvd_l1_zero_flag; + + RK_U8 cabac_init_flag; + RK_U8 disable_deblocking_filter_flag; ///< slice_header_disable_deblocking_filter_flag + RK_U8 slice_loop_filter_across_slices_enabled_flag; + RK_U8 collocated_list; + + RK_U32 collocated_ref_idx; + + RK_S32 slice_qp_delta; + RK_S32 slice_cb_qp_offset; + RK_S32 slice_cr_qp_offset; + + RK_S32 beta_offset; ///< beta_offset_div2 * 2 + RK_S32 tc_offset; ///< tc_offset_div2 * 2 + + RK_U32 max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand + + RK_S32 *entry_point_offset; + RK_S32 * offset; + RK_S32 * size; + RK_S32 num_entry_point_offsets; + + RK_S8 slice_qp; + + RK_U8 luma_log2_weight_denom; + RK_S16 chroma_log2_weight_denom; + + RK_S32 slice_ctb_addr_rs; +} SliceHeader_t; + +extern RK_U8 hal_hevc_diag_scan4x4_x[16]; +extern RK_U8 hal_hevc_diag_scan4x4_y[16]; +extern RK_U8 hal_hevc_diag_scan8x8_x[64]; +extern RK_U8 hal_hevc_diag_scan8x8_y[64]; +extern RK_U8 cabac_table[27456]; + +#ifdef __cplusplus +extern "C" { +#endif + +void hal_record_scaling_list(scalingFactor_t *pScalingFactor_out, scalingList_t *pScalingList); +RK_S32 hal_h265d_slice_hw_rps(void *dxva, void *rps_buf, void* sw_rps_buf, RK_U32 fast_mode); +RK_S32 hal_h265d_slice_output_rps(void *dxva, void *rps_buf); +void hal_h265d_output_scalinglist_packet(void *hal, void *ptr, void *dxva); +void hal_vdpu38x_record_scaling_list(scalingFactor_t *pScalingFactor_out, scalingList_t *pScalingList); +MPP_RET hal_h265d_vdpu38x_scalinglist_packet(void *hal, void *ptr, void *dxva); +RK_S32 hal_h265d_vdpu38x_output_pps_packet(void *hal, void *dxva, RK_U32 *scanlist_addr); +void vdpu38x_h265d_rcb_setup(void *hal, h265d_dxva2_picture_context_t *dxva, + HalTaskInfo *task, RK_S32 width, RK_S32 height, + Vdpu38xRcbRegSet *rcb_regs, Vdpu38xRcbCalc_f func); + +MPP_RET hal_h265d_vdpu38x_deinit(void *hal); +MPP_RET hal_h265d_vdpu_reset(void *hal); +MPP_RET hal_h265d_vdpu_flush(void *hal); +MPP_RET hal_h265d_vdpu38x_control(void *hal, MpiCmd cmd_type, void *param); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_COM_H */ diff --git a/mpp/hal/rkdec/h265d/hal_h265d_ctx.h b/mpp/hal/rkdec/h265d/hal_h265d_ctx.h new file mode 100644 index 000000000..2bc488ba2 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_ctx.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265D_CTX_H +#define HAL_H265D_CTX_H + +#include "mpp_device.h" +#include "mpp_hal.h" +#include "mpp_env.h" +#include "hal_bufs.h" +#include "vdpu_com.h" + +/* before vdpu383 10 buf */ +#define H265D_RCB_BUF_COUNT 11 + +typedef struct H265dRegBuf_t { + RK_S32 use_flag; + MppBuffer scaling_list_data; + MppBuffer pps_data; + MppBuffer rps_data; + void *hw_regs; +} H265dRegBuf; + +typedef struct H265dRcbInfo_t { + RK_S32 reg; + RK_S32 size; + RK_S32 offset; +} H265dRcbInfo; + +typedef struct HalH265dCtx_t { + /* for hardware info */ + MppClientType client_type; + RK_U32 hw_id; + + MppHalCfg *cfg; + + MppBuffer cabac_table_data; + MppBuffer scaling_list_data; + MppBuffer pps_data; + MppBuffer rps_data; + + RK_S32 width; + RK_S32 height; + void *rcb_ctx; + RK_U32 rcb_buf_size; + H265dRcbInfo rcb_info[H265D_RCB_BUF_COUNT]; + MppBuffer rcb_buf[VDPU_FAST_REG_SET_CNT]; + + void *hw_regs; + H265dRegBuf g_buf[VDPU_FAST_REG_SET_CNT]; + RK_U32 fast_mode; + RK_U32 fast_mode_err_found; + void *scaling_rk; + void *scaling_qm; + HalBufs cmv_bufs; + RK_U32 mv_size; + RK_S32 mv_count; + + struct { + RK_U32 is_v341 : 1; + RK_U32 is_v345 : 1; + RK_U32 is_v34x : 1; + }; + /* rcb info */ + RK_U32 chroma_fmt_idc; + RK_U8 ctu_size; + RK_U8 num_row_tiles; + RK_U8 bit_depth; + RK_U8 error_index[VDPU_FAST_REG_SET_CNT]; + /* for vdpu34x */ + MppBuffer bufs; + RK_S32 bufs_fd; + RK_U32 offset_cabac; + RK_U32 offset_spspps[VDPU_FAST_REG_SET_CNT]; + RK_U32 offset_rps[VDPU_FAST_REG_SET_CNT]; + RK_U32 offset_sclst[VDPU_FAST_REG_SET_CNT]; + RK_U32 spspps_offset; + RK_U32 rps_offset; + RK_U32 sclst_offset; + void *pps_buf; + RK_U32 pps_buf_sz; + void *sw_rps_buf; + HalBufs origin_bufs; + MppBuffer missing_ref_buf; + RK_U32 missing_ref_buf_size; +} HalH265dCtx; + +typedef struct ScalingList_t { + /* This is a little wasteful, since sizeID 0 only needs 8 coeffs, + * and size ID 3 only has 2 arrays, not 6. */ + RK_U8 sl[4][6][64]; + RK_U8 sl_dc[2][6]; +} scalingList_t; + +typedef struct ScalingFactor_Model { + RK_U8 scalingfactor0[1248]; + RK_U8 scalingfactor1[96]; /*4X4 TU Rotate, total 16X4*/ + RK_U8 scalingdc[12]; /*N1005 Vienna Meeting*/ + RK_U8 reserverd[4]; /*16Bytes align*/ +} scalingFactor_t; + +#endif diff --git a/mpp/hal/inc/hal_dummy_dec_api.h b/mpp/hal/rkdec/h265d/hal_h265d_debug.h similarity index 56% rename from mpp/hal/inc/hal_dummy_dec_api.h rename to mpp/hal/rkdec/h265d/hal_h265d_debug.h index 4f9c6cfa5..e7753faa5 100644 --- a/mpp/hal/inc/hal_dummy_dec_api.h +++ b/mpp/hal/rkdec/h265d/hal_h265d_debug.h @@ -1,34 +1,42 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - - -#ifndef __HAL_DUMMY_DEC_API_H__ -#define __HAL_DUMMY_DEC_API_H__ - -#include "mpp_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern const MppHalApi hal_api_dummy_dec; - -#ifdef __cplusplus -} -#endif - -#endif /*__HAL_DUMMY_DEC_API_H__*/ +/* +* +* Copyright 2015 Rockchip Electronics Co. LTD +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef HAL_H265D_DEBUG_H +#define HAL_H265D_DEBUG_H + +#include "mpp_debug.h" + +#define H265H_DBG_FUNCTION (0x00000001) +#define H265H_DBG_RPS (0x00000002) +#define H265H_DBG_PPS (0x00000004) +#define H265H_DBG_REG (0x00000008) +#define H265H_DBG_FAST_ERR (0x00000010) +#define H265H_DBG_TASK_ERR (0x00000020) + +#define h265h_dbg(flag, fmt, ...) mpp_dbg(hal_h265d_debug, flag, fmt, ## __VA_ARGS__) + +#ifdef __cplusplus +extern "C" { +#endif + +extern RK_U32 hal_h265d_debug; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_DEBUG_H */ diff --git a/mpp/hal/rkdec/h265d/hal_h265d_rkv.c b/mpp/hal/rkdec/h265d/hal_h265d_rkv.c new file mode 100644 index 000000000..34c8c341f --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_rkv.c @@ -0,0 +1,1121 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265d_rkv" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bitput.h" + +#include "hal_hw_id.h" +#include "hal_h265d_debug.h" +#include "hal_h265d_ctx.h" +#include "hal_h265d_com.h" +#include "hal_h265d_rkv.h" +#include "hal_h265d_rkv_reg.h" +#include "h265d_syntax.h" + +/* #define dump */ +#ifdef dump +static FILE *fp = NULL; +#endif +#define HW_RPS + +#define PPS_SIZE (96 * 64) + +static MPP_RET hal_h265d_alloc_res(void *hal) +{ + RK_S32 i = 0; + RK_S32 ret = 0; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppBufferGroup group = reg_ctx->cfg->buf_group; + + if (reg_ctx->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + reg_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(H265d_REGS_t)); + ret = mpp_buffer_get(group, ®_ctx->g_buf[i].scaling_list_data, SCALING_LIST_SIZE); + if (ret) { + mpp_err("h265d scaling_list_data get buffer failed\n"); + return ret; + } + + ret = mpp_buffer_get(group, ®_ctx->g_buf[i].pps_data, + PPS_SIZE); + if (ret) { + mpp_err("h265d pps_data get buffer failed\n"); + return ret; + } + + ret = mpp_buffer_get(group, ®_ctx->g_buf[i].rps_data, + RPS_SIZE); + if (ret) { + mpp_err("h265d rps_data get buffer failed\n"); + return ret; + } + } + } else { + reg_ctx->hw_regs = mpp_calloc_size(void, sizeof(H265d_REGS_t)); + ret = mpp_buffer_get(group, ®_ctx->scaling_list_data, + SCALING_LIST_SIZE); + if (ret) { + mpp_err("h265d scaling_list_data get buffer failed\n"); + return ret; + } + + ret = mpp_buffer_get(group, ®_ctx->pps_data, PPS_SIZE); + if (ret) { + mpp_err("h265d pps_data get buffer failed\n"); + return ret; + } + + ret = mpp_buffer_get(group, ®_ctx->rps_data, RPS_SIZE); + if (ret) { + mpp_err("h265d rps_data get buffer failed\n"); + return ret; + } + + } + return MPP_OK; +} + +static MPP_RET hal_h265d_release_res(void *hal) +{ + RK_S32 ret = 0; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + RK_S32 i = 0; + if (reg_ctx->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (reg_ctx->g_buf[i].scaling_list_data) { + ret = mpp_buffer_put(reg_ctx->g_buf[i].scaling_list_data); + if (ret) { + mpp_err("h265d scaling_list_data free buffer failed\n"); + return ret; + } + } + if (reg_ctx->g_buf[i].pps_data) { + ret = mpp_buffer_put(reg_ctx->g_buf[i].pps_data); + if (ret) { + mpp_err("h265d pps_data free buffer failed\n"); + return ret; + } + } + + if (reg_ctx->g_buf[i].rps_data) { + ret = mpp_buffer_put(reg_ctx->g_buf[i].rps_data); + if (ret) { + mpp_err("h265d rps_data free buffer failed\n"); + return ret; + } + } + + if (reg_ctx->g_buf[i].hw_regs) { + mpp_free(reg_ctx->g_buf[i].hw_regs); + reg_ctx->g_buf[i].hw_regs = NULL; + } + } + } else { + if (reg_ctx->scaling_list_data) { + ret = mpp_buffer_put(reg_ctx->scaling_list_data); + if (ret) { + mpp_err("h265d scaling_list_data free buffer failed\n"); + return ret; + } + } + if (reg_ctx->pps_data) { + ret = mpp_buffer_put(reg_ctx->pps_data); + if (ret) { + mpp_err("h265d pps_data free buffer failed\n"); + return ret; + } + } + + if (reg_ctx->rps_data) { + ret = mpp_buffer_put(reg_ctx->rps_data); + if (ret) { + mpp_err("h265d rps_data free buffer failed\n"); + return ret; + } + } + + if (reg_ctx->hw_regs) { + mpp_free(reg_ctx->hw_regs); + reg_ctx->hw_regs = NULL; + } + } + return MPP_OK; +} + +MPP_RET hal_h265d_rkv_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_NOK; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RockchipSocType soc = mpp_get_soc_type(); + RK_U32 vcodec_type = mpp_get_vcodec_type(); + RK_U32 client_type; + RK_U32 hw_id = 0; + + mpp_env_get_u32("hal_h265d_debug", &hal_h265d_debug, 0); + + reg_ctx->cfg = cfg; + cfg->support_fast_mode = 1; + reg_ctx->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + client_type = (vcodec_type & HAVE_HEVC_DEC) ? VPU_CLIENT_HEVC_DEC : VPU_CLIENT_RKVDEC; + hw_id = mpp_get_client_hw_id(client_type); + reg_ctx->client_type = client_type; + reg_ctx->is_v341 = (soc == ROCKCHIP_SOC_RK3228H || (soc == ROCKCHIP_SOC_RK3328)); + reg_ctx->is_v345 = (hw_id == HWID_VDPU345); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + + reg_ctx->scaling_qm = mpp_calloc(DXVA_Qmatrix_HEVC, 1); + reg_ctx->sw_rps_buf = mpp_calloc(RK_U64, 400); + + if (reg_ctx->scaling_qm == NULL) { + mpp_err("scaling_org alloc fail"); + return MPP_ERR_MALLOC; + } + + reg_ctx->scaling_rk = mpp_calloc(scalingFactor_t, 1); + if (reg_ctx->scaling_rk == NULL) { + mpp_err("scaling_rk alloc fail"); + return MPP_ERR_MALLOC; + } + + ret = mpp_buffer_get(cfg->buf_group, ®_ctx->cabac_table_data, sizeof(cabac_table)); + if (ret) { + mpp_err("h265d cabac_table get buffer failed\n"); + return ret; + } + + ret = mpp_buffer_write(reg_ctx->cabac_table_data, 0, (void*)cabac_table, sizeof(cabac_table)); + if (ret) { + mpp_err("h265d write cabac_table data failed\n"); + return ret; + } + mpp_buffer_sync_end(reg_ctx->cabac_table_data); + + ret = hal_h265d_alloc_res(hal); + if (ret) { + mpp_err("hal_h265d_alloc_res failed\n"); + return ret; + } + +#ifdef dump + fp = fopen("/data/hal.bin", "wb"); +#endif + return MPP_OK; +} + +MPP_RET hal_h265d_rkv_deinit(void *hal) +{ + RK_S32 ret = 0; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + + ret = mpp_buffer_put(reg_ctx->cabac_table_data); + if (ret) { + mpp_err("h265d cabac_table free buffer failed\n"); + return ret; + } + + if (reg_ctx->scaling_qm) { + mpp_free(reg_ctx->scaling_qm); + } + + if (reg_ctx->sw_rps_buf) { + mpp_free(reg_ctx->sw_rps_buf); + } + + if (reg_ctx->scaling_rk) { + mpp_free(reg_ctx->scaling_rk); + } + + hal_h265d_release_res(hal); + + return MPP_OK; +} + +static RK_S32 hal_h265d_v345_output_pps_packet(void *hal, void *dxva) +{ + RK_S32 fifo_len = 12; + RK_S32 i, j; + RK_U32 log2_min_cb_size; + RK_S32 width, height; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + BitputCtx_t bp; + RK_U64 *pps_packet = mpp_calloc(RK_U64, fifo_len + 1); + + if (NULL == reg_ctx || dxva_cxt == NULL) { + mpp_err("%s:%s:%d reg_ctx or dxva_cxt is NULL", + __FILE__, __FUNCTION__, __LINE__); + MPP_FREE(pps_packet); + return MPP_ERR_NULL_PTR; + } + + void *pps_ptr = mpp_buffer_get_ptr(reg_ctx->pps_data); + if (NULL == pps_ptr) { + mpp_err("pps_data get ptr error"); + return MPP_ERR_NOMEM; + } + memset(pps_ptr, 0, 96 * 64); + // pps_packet = (RK_U64 *)(pps_ptr + dxva_cxt->pp.pps_id * 80); + + for (i = 0; i < 12; i++) pps_packet[i] = 0; + + mpp_set_bitput_ctx(&bp, pps_packet, fifo_len); + + // SPS + mpp_put_bits(&bp, dxva_cxt->pp.vps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.chroma_format_idc , 2); + + log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + + mpp_put_bits(&bp, width , 13); + mpp_put_bits(&bp, height , 13); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_luma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_chroma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4 , 5); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size , 2); //log2_maxa_coding_block_depth + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_transform_block_size_minus2 + 2 , 3); + ///<-zrh comment ^ 57 bit above + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_transform_block_size , 2); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_inter , 3); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_intra , 3); + mpp_put_bits(&bp, dxva_cxt->pp.scaling_list_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.amp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.sample_adaptive_offset_enabled_flag , 1); + ///<-zrh comment ^ 68 bit above + mpp_put_bits(&bp, dxva_cxt->pp.pcm_enabled_flag , 1); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_luma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_chroma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pcm_loop_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_pcm_luma_coding_block_size , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.log2_min_pcm_luma_coding_block_size_minus3 + 3) : 0, 3); + + mpp_put_bits(&bp, dxva_cxt->pp.num_short_term_ref_pic_sets , 7); + mpp_put_bits(&bp, dxva_cxt->pp.long_term_ref_pics_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_long_term_ref_pics_sps , 6); + mpp_put_bits(&bp, dxva_cxt->pp.sps_temporal_mvp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.strong_intra_smoothing_enabled_flag , 1); + ///<-zrh comment ^ 100 bit above + + mpp_put_bits(&bp, 0 , 7 ); + + mpp_put_bits(&bp, dxva_cxt->pp.sps_max_dec_pic_buffering_minus1, 4); + mpp_put_bits(&bp, 0, 3); + mpp_put_align(&bp , 32, 0xf); //128 + + // PPS + mpp_put_bits(&bp, dxva_cxt->pp.pps_id , 6 ); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4 ); + mpp_put_bits(&bp, dxva_cxt->pp.dependent_slice_segments_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.output_flag_present_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.num_extra_slice_header_bits , 13); + mpp_put_bits(&bp, dxva_cxt->pp.sign_data_hiding_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cabac_init_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l0_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l1_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.init_qp_minus26 , 7); + mpp_put_bits(&bp, dxva_cxt->pp.constrained_intra_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transform_skip_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cu_qp_delta_enabled_flag , 1); //164 + + mpp_put_bits(&bp, log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size - + dxva_cxt->pp.diff_cu_qp_delta_depth , 3); + + h265h_dbg(H265H_DBG_PPS, "log2_min_cb_size %d %d %d \n", log2_min_cb_size, + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size, dxva_cxt->pp.diff_cu_qp_delta_depth ); + + mpp_put_bits(&bp, dxva_cxt->pp.pps_cb_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_cr_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_slice_chroma_qp_offsets_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_bipred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transquant_bypass_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.tiles_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.entropy_coding_sync_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_loop_filter_across_slices_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.loop_filter_across_tiles_enabled_flag , 1); //185 + mpp_put_bits(&bp, dxva_cxt->pp.deblocking_filter_override_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_deblocking_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_beta_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pps_tc_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.lists_modification_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_parallel_merge_level_minus2 + 2 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.slice_segment_header_extension_present_flag , 1); + mpp_put_bits(&bp, 0 , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.tiles_enabled_flag != 0) ? dxva_cxt->pp.num_tile_columns_minus1 + 1 : 0, 5); + mpp_put_bits(&bp, (dxva_cxt->pp.tiles_enabled_flag != 0) ? dxva_cxt->pp.num_tile_rows_minus1 + 1 : 0 , 5 ); + mpp_put_bits(&bp, 0, 4); //mSps_Pps[i]->mMode + mpp_put_align(&bp, 64, 0xf); + { + /// tiles info begin + RK_U16 column_width[20]; + RK_U16 row_height[22]; + + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + if (dxva_cxt->pp.tiles_enabled_flag) { + + if (dxva_cxt->pp.uniform_spacing_flag == 0) { + RK_S32 maxcuwidth = dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size; + RK_S32 ctu_width_in_pic = (width + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 ctu_height_in_pic = (height + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1; i++) { + column_width[i] = dxva_cxt->pp.column_width_minus1[i] + 1; + sum += column_width[i] ; + } + column_width[i] = ctu_width_in_pic - sum; + + sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1; i++) { + row_height[i] = dxva_cxt->pp.row_height_minus1[i] + 1; + sum += row_height[i]; + } + row_height[i] = ctu_height_in_pic - sum; + } // end of (pps->uniform_spacing_flag == 0) + else { + + RK_S32 pic_in_cts_width = (width + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + RK_S32 pic_in_cts_height = (height + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1 + 1; i++) + column_width[i] = ((i + 1) * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1) - + (i * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1); + + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1 + 1; i++) + row_height[i] = ((i + 1) * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1) - + (i * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1); + } + } // pps->tiles_enabled_flag + else { + RK_S32 MaxCUWidth = (1 << (dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size)); + column_width[0] = (width + MaxCUWidth - 1) / MaxCUWidth; + row_height[0] = (height + MaxCUWidth - 1) / MaxCUWidth; + } + + for (j = 0; j < 20; j++) { + if (column_width[j] > 0) + column_width[j]--; + mpp_put_bits(&bp, column_width[j], 8); + } + + for (j = 0; j < 22; j++) { + if (row_height[j] > 0) + row_height[j]--; + mpp_put_bits(&bp, row_height[j], 8); + } + } + + { + RK_U8 *ptr_scaling = (RK_U8 *)mpp_buffer_get_ptr(reg_ctx->scaling_list_data); + RK_U32 fd = mpp_buffer_get_fd(reg_ctx->scaling_list_data); + + hal_h265d_output_scalinglist_packet(hal, ptr_scaling, dxva); + mpp_put_bits(&bp, fd, 32); + mpp_put_bits(&bp, 0, 60); + mpp_put_align(&bp, 128, 0xf); + } + + for (i = 0; i < 64; i++) + memcpy(pps_ptr + i * 96, pps_packet, 96); + +#ifdef dump + fwrite(pps_ptr, 1, 80 * 64, fp); + RK_U32 *tmp = (RK_U32 *)pps_ptr; + for (i = 0; i < 96 / 4; i++) { + h265h_dbg(H265H_DBG_PPS, "pps[%3d] = 0x%08x\n", i, tmp[i]); + } +#endif + MPP_FREE(pps_packet); + return 0; +} + +static RK_S32 hal_h265d_output_pps_packet(void *hal, void *dxva) +{ + RK_S32 fifo_len = 10; + RK_S32 i, j; + RK_U32 log2_min_cb_size; + RK_S32 width, height; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + BitputCtx_t bp; + RK_U64 *pps_packet = mpp_calloc(RK_U64, fifo_len + 1); + + if (NULL == reg_ctx || dxva_cxt == NULL) { + mpp_err("%s:%s:%d reg_ctx or dxva_cxt is NULL", + __FILE__, __FUNCTION__, __LINE__); + MPP_FREE(pps_packet); + return MPP_ERR_NULL_PTR; + } + + void *pps_ptr = mpp_buffer_get_ptr(reg_ctx->pps_data); + if (NULL == pps_ptr) { + mpp_err("pps_data get ptr error"); + return MPP_ERR_NOMEM; + } + memset(pps_ptr, 0, 80 * 64); + // pps_packet = (RK_U64 *)(pps_ptr + dxva_cxt->pp.pps_id * 80); + + for (i = 0; i < 10; i++) pps_packet[i] = 0; + + mpp_set_bitput_ctx(&bp, pps_packet, fifo_len); + + // SPS + mpp_put_bits(&bp, dxva_cxt->pp.vps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.chroma_format_idc , 2); + + log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + + mpp_put_bits(&bp, width , 13); + mpp_put_bits(&bp, height , 13); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_luma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_chroma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4 , 5); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size , 2); //log2_maxa_coding_block_depth + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_transform_block_size_minus2 + 2 , 3); + ///<-zrh comment ^ 57 bit above + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_transform_block_size , 2); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_inter , 3); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_intra , 3); + mpp_put_bits(&bp, dxva_cxt->pp.scaling_list_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.amp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.sample_adaptive_offset_enabled_flag , 1); + ///<-zrh comment ^ 68 bit above + mpp_put_bits(&bp, dxva_cxt->pp.pcm_enabled_flag , 1); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_luma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_chroma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pcm_loop_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_pcm_luma_coding_block_size , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.log2_min_pcm_luma_coding_block_size_minus3 + 3) : 0, 3); + + mpp_put_bits(&bp, dxva_cxt->pp.num_short_term_ref_pic_sets , 7); + mpp_put_bits(&bp, dxva_cxt->pp.long_term_ref_pics_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_long_term_ref_pics_sps , 6); + mpp_put_bits(&bp, dxva_cxt->pp.sps_temporal_mvp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.strong_intra_smoothing_enabled_flag , 1); + ///<-zrh comment ^ 100 bit above + + mpp_put_bits(&bp, 0 , 7 ); + mpp_put_align(&bp , 32, 0xf); + + // PPS + mpp_put_bits(&bp, dxva_cxt->pp.pps_id , 6 ); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4 ); + mpp_put_bits(&bp, dxva_cxt->pp.dependent_slice_segments_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.output_flag_present_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.num_extra_slice_header_bits , 13); + mpp_put_bits(&bp, dxva_cxt->pp.sign_data_hiding_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cabac_init_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l0_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l1_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.init_qp_minus26 , 7); + mpp_put_bits(&bp, dxva_cxt->pp.constrained_intra_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transform_skip_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cu_qp_delta_enabled_flag , 1); + + mpp_put_bits(&bp, log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size - + dxva_cxt->pp.diff_cu_qp_delta_depth , 3); + + h265h_dbg(H265H_DBG_PPS, "log2_min_cb_size %d %d %d \n", log2_min_cb_size, + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size, dxva_cxt->pp.diff_cu_qp_delta_depth ); + + mpp_put_bits(&bp, dxva_cxt->pp.pps_cb_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_cr_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_slice_chroma_qp_offsets_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_bipred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transquant_bypass_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.tiles_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.entropy_coding_sync_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_loop_filter_across_slices_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.loop_filter_across_tiles_enabled_flag , 1); + + mpp_put_bits(&bp, dxva_cxt->pp.deblocking_filter_override_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_deblocking_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_beta_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pps_tc_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.lists_modification_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_parallel_merge_level_minus2 + 2 , 3); + /*slice_segment_header_extension_present_flag need set 0 */ + mpp_put_bits(&bp, 0 , 1); + mpp_put_bits(&bp, 0 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.num_tile_columns_minus1 + 1, 5); + mpp_put_bits(&bp, dxva_cxt->pp.num_tile_rows_minus1 + 1 , 5 ); + mpp_put_bits(&bp, 3, 2); //mSps_Pps[i]->mMode + mpp_put_align(&bp, 64, 0xf); + + { + /// tiles info begin + RK_U16 column_width[20]; + RK_U16 row_height[22]; + + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + if (dxva_cxt->pp.tiles_enabled_flag) { + if (dxva_cxt->pp.uniform_spacing_flag == 0) { + RK_S32 maxcuwidth = dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size; + RK_S32 ctu_width_in_pic = (width + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 ctu_height_in_pic = (height + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1; i++) { + column_width[i] = dxva_cxt->pp.column_width_minus1[i] + 1; + sum += column_width[i] ; + } + column_width[i] = ctu_width_in_pic - sum; + + sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1; i++) { + row_height[i] = dxva_cxt->pp.row_height_minus1[i] + 1; + sum += row_height[i]; + } + row_height[i] = ctu_height_in_pic - sum; + } // end of (pps->uniform_spacing_flag == 0) + else { + + RK_S32 pic_in_cts_width = (width + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + RK_S32 pic_in_cts_height = (height + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1 + 1; i++) + column_width[i] = ((i + 1) * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1) - + (i * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1); + + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1 + 1; i++) + row_height[i] = ((i + 1) * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1) - + (i * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1); + } + } // pps->tiles_enabled_flag + else { + RK_S32 MaxCUWidth = (1 << (dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size)); + column_width[0] = (width + MaxCUWidth - 1) / MaxCUWidth; + row_height[0] = (height + MaxCUWidth - 1) / MaxCUWidth; + } + + for (j = 0; j < 20; j++) { + if (column_width[j] > 0) + column_width[j]--; + mpp_put_bits(&bp, column_width[j], 8); + } + + for (j = 0; j < 22; j++) { + if (row_height[j] > 0) + row_height[j]--; + mpp_put_bits(&bp, row_height[j], 8); + } + } + + { + RK_U8 *ptr_scaling = (RK_U8 *)mpp_buffer_get_ptr(reg_ctx->scaling_list_data); + RK_U32 fd = mpp_buffer_get_fd(reg_ctx->scaling_list_data); + + hal_h265d_output_scalinglist_packet(hal, ptr_scaling, dxva); + mpp_put_bits(&bp, fd, 32); + mpp_put_align(&bp, 64, 0xf); + } + + for (i = 0; i < 64; i++) + memcpy(pps_ptr + i * 80, pps_packet, 80); + +#ifdef dump + fwrite(pps_ptr, 1, 80 * 64, fp); + fflush(fp); +#endif + + MPP_FREE(pps_packet); + return 0; +} + +static void update_stream_buffer(MppBuffer streambuf, HalTaskInfo *syn) +{ + h265d_dxva2_picture_context_t *dxva_cxt = + (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + RK_U8 *ptr = (RK_U8*)mpp_buffer_get_ptr(streambuf); + RK_U8 bit_left = 0; + RK_U16 start_byte, end_byte, i = 0; + RK_U32 stream_size = dxva_cxt->bitstream_size; + RK_U8 *buf = NULL; + RK_U8 *temp = NULL; + RK_U32 cut_byte = 0, cut_byte_acc = 0; + + for (i = 0; i < dxva_cxt->slice_count; i++) { + if (dxva_cxt->slice_cut_param[i].is_enable) { + + bit_left = 8 - (dxva_cxt->slice_cut_param[i].start_bit & 0x7); + start_byte = dxva_cxt->slice_cut_param[i].start_bit >> 3; + end_byte = (dxva_cxt->slice_cut_param[i].end_bit + 7) >> 3; + buf = ptr + (dxva_cxt->slice_short[i].BSNALunitDataLocation - cut_byte_acc); + temp = buf + start_byte; + + h265h_dbg(H265H_DBG_FUNCTION, "start bit %d start byte[%d] 0x%x end bit %d end byte[%d] 0x%x\n", + dxva_cxt->slice_cut_param[i].start_bit, start_byte, buf[start_byte], + dxva_cxt->slice_cut_param[i].end_bit, end_byte, buf[end_byte]); + if (bit_left < 8) { + *temp = (*temp >> bit_left) << bit_left; + *temp |= 1 << (bit_left - 1); + } else { + *temp = 0x80; + } + if ((dxva_cxt->slice_cut_param[i].end_bit & 0x7) == 0 && buf[end_byte] == 0x80) + end_byte += 1; + + h265h_dbg(H265H_DBG_FUNCTION, "i %d location %d count %d SliceBytesInBuffer %d bitstream_size %d\n", + i, dxva_cxt->slice_short[i].BSNALunitDataLocation, dxva_cxt->slice_count, + dxva_cxt->slice_short[i].SliceBytesInBuffer, dxva_cxt->bitstream_size); + + memmove(buf + start_byte + 1, buf + end_byte, + stream_size - dxva_cxt->slice_short[i].BSNALunitDataLocation - end_byte); + + cut_byte = end_byte - start_byte - 1; + dxva_cxt->slice_short[i].SliceBytesInBuffer -= cut_byte; + dxva_cxt->bitstream_size -= cut_byte; + cut_byte_acc += cut_byte; + } + } +} + +MPP_RET hal_h265d_rkv_gen_regs(void *hal, HalTaskInfo *syn) +{ + RK_S32 i = 0; + RK_S32 stride_y, stride_uv, virstrid_y, virstrid_yuv; + H265d_REGS_t *hw_regs; + RK_S32 ret = MPP_SUCCESS; + MppBuffer streambuf = NULL; + RK_S32 aglin_offset = 0; + RK_S32 valid_ref = -1; + MppBuffer framebuf = NULL; + RK_U32 sw_ref_valid = 0; + RK_U32 stream_buf_size = 0; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + MppFrame mframe; + MppHalCfg *cfg = reg_ctx->cfg; + + if (syn->dec.flags.parse_err || + (syn->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + h265d_dxva2_picture_context_t *dxva_cxt = + (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + + void *rps_ptr = NULL; + if (reg_ctx ->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!reg_ctx->g_buf[i].use_flag) { + syn->dec.reg_index = i; + reg_ctx->rps_data = reg_ctx->g_buf[i].rps_data; + reg_ctx->scaling_list_data = + reg_ctx->g_buf[i].scaling_list_data; + reg_ctx->pps_data = reg_ctx->g_buf[i].pps_data; + reg_ctx->hw_regs = reg_ctx->g_buf[i].hw_regs; + reg_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("hevc rps buf all used"); + return MPP_ERR_NOMEM; + } + } else { + syn->dec.reg_index = 0; + } + rps_ptr = mpp_buffer_get_ptr(reg_ctx->rps_data); + if (NULL == rps_ptr) { + + mpp_err("rps_data get ptr error"); + return MPP_ERR_NOMEM; + } + + + if (syn->dec.syntax.data == NULL) { + mpp_err("%s:%s:%d dxva is NULL", __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + + /* output pps */ + if (reg_ctx->is_v345) { + hal_h265d_v345_output_pps_packet(hal, syn->dec.syntax.data); + } else { + hal_h265d_output_pps_packet(hal, syn->dec.syntax.data); + } + + if (NULL == reg_ctx->hw_regs) { + return MPP_ERR_NULL_PTR; + } + + hw_regs = (H265d_REGS_t*)reg_ctx->hw_regs; + memset(hw_regs, 0, sizeof(H265d_REGS_t)); + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + stride_y = mpp_frame_get_hor_stride(mframe); + stride_uv = mpp_frame_get_hor_stride(mframe); + virstrid_y = mpp_frame_get_ver_stride(mframe) * stride_y; + virstrid_yuv = virstrid_y + stride_uv * mpp_frame_get_ver_stride(mframe) / 2; + + hw_regs->sw_picparameter.sw_slice_num = dxva_cxt->slice_count; + hw_regs->sw_picparameter.sw_y_hor_virstride = stride_y >> 4; + hw_regs->sw_picparameter.sw_uv_hor_virstride = stride_uv >> 4; + hw_regs->sw_y_virstride = virstrid_y >> 4; + hw_regs->sw_yuv_virstride = virstrid_yuv >> 4; + hw_regs->sw_sysctrl.sw_h26x_rps_mode = 0; + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &framebuf); + hw_regs->sw_decout_base = mpp_buffer_get_fd(framebuf); //just index need map + + /*if out_base is equal to zero it means this frame may error + we return directly add by csy*/ + + if (hw_regs->sw_decout_base == 0) { + return 0; + } + + hw_regs->sw_cur_poc = dxva_cxt->pp.CurrPicOrderCntVal; + + mpp_buf_slot_get_prop(cfg->packet_slots, syn->dec.input, SLOT_BUFFER, + &streambuf); + + if ( dxva_cxt->bitstream == NULL) { + dxva_cxt->bitstream = mpp_buffer_get_ptr(streambuf); + } + if (reg_ctx->is_v345) { +#ifdef HW_RPS + hw_regs->sw_sysctrl.sw_wait_reset_en = 1; + hw_regs->v345_reg_ends.reg064_mvc0.refp_layer_same_with_cur = 0xffff; + hal_h265d_slice_hw_rps(syn->dec.syntax.data, rps_ptr, reg_ctx->sw_rps_buf, reg_ctx->fast_mode); +#else + hw_regs->sw_sysctrl.sw_h26x_rps_mode = 1; + hal_h265d_slice_output_rps(syn->dec.syntax.data, rps_ptr); +#endif + } else { + hal_h265d_slice_output_rps(syn->dec.syntax.data, rps_ptr); + } + + if (dxva_cxt->pp.slice_segment_header_extension_present_flag && !reg_ctx->is_v345) { + update_stream_buffer(streambuf, syn); + mpp_buffer_sync_end(streambuf); + } + + hw_regs->sw_cabactbl_base = mpp_buffer_get_fd(reg_ctx->cabac_table_data); + hw_regs->sw_pps_base = mpp_buffer_get_fd(reg_ctx->pps_data); + hw_regs->sw_rps_base = mpp_buffer_get_fd(reg_ctx->rps_data); + hw_regs->sw_strm_rlc_base = mpp_buffer_get_fd(streambuf); + stream_buf_size = mpp_buffer_get_size(streambuf); + + hw_regs->sw_stream_len = ((dxva_cxt->bitstream_size + 15) + & (~15)) + 64; + hw_regs->sw_stream_len = stream_buf_size > hw_regs->sw_stream_len ? + hw_regs->sw_stream_len : stream_buf_size; + + aglin_offset = hw_regs->sw_stream_len - dxva_cxt->bitstream_size; + if (aglin_offset > 0) { + memset((void *)(dxva_cxt->bitstream + dxva_cxt->bitstream_size), 0, + aglin_offset); + } + hw_regs->sw_interrupt.sw_dec_e = 1; + hw_regs->sw_interrupt.sw_dec_timeout_e = 1; + hw_regs->sw_interrupt.sw_wr_ddr_align_en = (dxva_cxt->pp.tiles_enabled_flag != 0) + ? 0 : 1; + + ///find s->rps_model[i] position, and set register + hw_regs->cabac_error_en = 0xfdfffffd; + hw_regs->rkv_reg_ends.extern_error_en = 0x30000000; + + valid_ref = hw_regs->sw_decout_base; + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(hw_regs->sw_refer_base); i++) { + if (dxva_cxt->pp.RefPicList[i].bPicEntry != 0xff && + dxva_cxt->pp.RefPicList[i].bPicEntry != 0x7f) { + hw_regs->sw_refer_poc[i] = dxva_cxt->pp.PicOrderCntValList[i]; + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_cxt->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + if (framebuf != NULL) { + hw_regs->sw_refer_base[i] = mpp_buffer_get_fd(framebuf); + valid_ref = hw_regs->sw_refer_base[i]; + } else { + hw_regs->sw_refer_base[i] = valid_ref; + } + sw_ref_valid |= (1 << i); + } else { + hw_regs->sw_refer_base[i] = hw_regs->sw_decout_base; + } + } + + if (sw_ref_valid) { + mpp_dev_set_reg_offset(cfg->dev, 10, sw_ref_valid & 0xf); + mpp_dev_set_reg_offset(cfg->dev, 11, ((sw_ref_valid >> 4) & 0xf)); + mpp_dev_set_reg_offset(cfg->dev, 12, ((sw_ref_valid >> 8) & 0xf)); + mpp_dev_set_reg_offset(cfg->dev, 13, ((sw_ref_valid >> 12) & 0xf)); + } + mpp_buffer_sync_end(reg_ctx->scaling_list_data); + mpp_buffer_sync_end(reg_ctx->pps_data); + mpp_buffer_sync_end(reg_ctx->rps_data); + + return ret; +} + +MPP_RET hal_h265d_rkv_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + H265d_REGS_t *hw_regs = NULL; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_S32 index = task->dec.reg_index; + + RK_U32 i; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !reg_ctx->cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx->fast_mode) { + hw_regs = ( H265d_REGS_t *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( H265d_REGS_t *)reg_ctx->hw_regs; + } + + if (hw_regs == NULL) { + mpp_err("hal_h265d_start hw_regs is NULL"); + return MPP_ERR_NULL_PTR; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = reg_ctx->cfg->dev; + + RK_U32 reg_size = (reg_ctx->is_v341 || reg_ctx->is_v345) ? V345_HEVC_REGISTERS : + (reg_ctx->client_type == VPU_CLIENT_RKVDEC) ? + RKVDEC_V1_REGISTERS : RKVDEC_HEVC_REGISTERS; + + reg_size *= sizeof(RK_U32); + + wr_cfg.reg = hw_regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + if (hal_h265d_debug & H265H_DBG_REG) { + for (i = 0; i < reg_size / sizeof(RK_U32); i++) + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", i, ((RK_U32 *)hw_regs)[i]); + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = hw_regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + +MPP_RET hal_h265d_rkv_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_S32 index = task->dec.reg_index; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + H265d_REGS_t *hw_regs = NULL; + RK_S32 i; + + if (reg_ctx->fast_mode) { + hw_regs = ( H265d_REGS_t *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( H265d_REGS_t *)reg_ctx->hw_regs; + } + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + goto ERR_PROC; + } + + ret = mpp_dev_ioctl(cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +ERR_PROC: + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + hw_regs->sw_interrupt.sw_dec_error_sta || + hw_regs->sw_interrupt.sw_dec_timeout_sta || + hw_regs->sw_interrupt.sw_dec_empty_sta) { + if (!reg_ctx->fast_mode) { + if (cfg->dec_cb) + mpp_callback(cfg->dec_cb, &task->dec); + } else { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + if (mframe) { + reg_ctx->fast_mode_err_found = 1; + mpp_frame_set_errinfo(mframe, 1); + } + } + } else { + if (reg_ctx->fast_mode && reg_ctx->fast_mode_err_found) { + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(task->dec.refer); i++) { + if (task->dec.refer[i] >= 0) { + MppFrame frame_ref = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.refer[i], + SLOT_FRAME_PTR, &frame_ref); + h265h_dbg(H265H_DBG_FAST_ERR, "refer[%d] %d frame %p\n", + i, task->dec.refer[i], frame_ref); + if (frame_ref && mpp_frame_get_errinfo(frame_ref)) { + MppFrame frame_out = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &frame_out); + mpp_frame_set_errinfo(frame_out, 1); + break; + } + } + } + } + } + + if (hal_h265d_debug & H265H_DBG_REG) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[1]=0x%08X, regs[45]=0x%08x\n", ((RK_U32 *)hw_regs)[1], ((RK_U32 *)hw_regs)[45]); + } + + if (reg_ctx->fast_mode) { + reg_ctx->g_buf[index].use_flag = 0; + } + + return ret; +} + +MPP_RET hal_h265d_rkv_reset(void *hal) +{ + MPP_RET ret = MPP_OK; + HalH265dCtx *p_hal = (HalH265dCtx *)hal; + + p_hal->fast_mode_err_found = 0; + + return ret; +} + +const MppHalApi hal_h265d_rkv_hevc_dec = { + .name = "h265d_rkdec", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(HalH265dCtx), + .flag = 0, + .init = hal_h265d_rkv_init, + .deinit = hal_h265d_rkv_deinit, + .reg_gen = hal_h265d_rkv_gen_regs, + .start = hal_h265d_rkv_start, + .wait = hal_h265d_rkv_wait, + .reset = hal_h265d_rkv_reset, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_HEVC_DEC, + .soc_type = { + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_PX30, + ROCKCHIP_SOC_BUTT + }, +}; +MPP_DEC_HAL_API_REGISTER(hal_h265d_rkv_hevc_dec) + +const MppHalApi hal_h265d_rkv = { + .name = "h265d_rkdec", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(HalH265dCtx), + .flag = 0, + .init = hal_h265d_rkv_init, + .deinit = hal_h265d_rkv_deinit, + .reg_gen = hal_h265d_rkv_gen_regs, + .start = hal_h265d_rkv_start, + .wait = hal_h265d_rkv_wait, + .reset = hal_h265d_rkv_reset, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RV1109, + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h265d_rkv) diff --git a/mpp/hal/rkdec/h265d/hal_h265d_rkv.h b/mpp/hal/rkdec/h265d/hal_h265d_rkv.h new file mode 100644 index 000000000..4ad68a345 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_rkv.h @@ -0,0 +1,33 @@ +/* + * + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265D_RKV_H +#define HAL_H265D_RKV_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h265d_rkv; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_RKV_H */ diff --git a/mpp/hal/rkdec/h265d/hal_h265d_rkv_reg.h b/mpp/hal/rkdec/h265d/hal_h265d_rkv_reg.h new file mode 100644 index 000000000..0dec75d18 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_rkv_reg.h @@ -0,0 +1,156 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file hal_h265d_reg.h + * @brief + * @author csy(csy@rock-chips.com) + + * @version 1.0.0 + * @history + * 2015.7.15 : Create + */ + +#ifndef HAL_H265D_REG_H +#define HAL_H265D_REG_H + +#include "rk_type.h" + +#define HEVC_DECODER_REG_NUM (48) +#define RKVDEC_REG_PERF_CYCLE_INDEX (64) + +#define RKVDEC_HEVC_REGISTERS (68) +#define RKVDEC_V1_REGISTERS (78) +#define V345_HEVC_REGISTERS (108) + +typedef struct RKV_HEVC_REG_END { + RK_U32 performance_cycle; //65 + RK_U32 axi_ddr_rdata; + RK_U32 axi_ddr_wdata; + RK_U32 fpgadebug_reset; + RK_U32 reserve[9]; + RK_U32 extern_error_en; +} rkv_reg_end; + +typedef struct V345_HEVC_REG_END { + struct hevc_mvc0 { + RK_U32 refp_layer_same_with_cur : 16 ; + RK_U32 reserve : 16 ; + } reg064_mvc0; + RK_U32 reserve[55]; +} v345_reg_end; + +typedef struct { + struct swreg_id { + RK_U32 minor_ver : 8 ; + RK_U32 major_ver : 8 ; + RK_U32 prod_num : 16 ; + } sw_id; + + struct swreg_int { + RK_U32 sw_dec_e : 1 ; + RK_U32 sw_dec_clkgate_e : 1 ; + RK_U32 reserve0 : 2 ; + RK_U32 sw_dec_irq_dis : 1 ; + RK_U32 sw_dec_timeout_e : 1 ; + RK_U32 sw_buf_empty_en : 1 ; + RK_U32 reserve1 : 1 ; + RK_U32 sw_dec_irq : 1 ; + RK_U32 sw_dec_irq_raw : 1 ; + RK_U32 reserve2 : 2 ; + RK_U32 sw_dec_rdy_sta : 1 ; + RK_U32 sw_dec_bus_sta : 1 ; + RK_U32 sw_dec_error_sta : 1 ; + RK_U32 sw_dec_timeout_sta : 1 ; + RK_U32 sw_dec_empty_sta : 1 ; + RK_U32 reserve4 : 3 ; + RK_U32 sw_softrst_en_p : 1 ; + RK_U32 sw_force_softreset_valid: 1 ; + RK_U32 sw_softreset_rdy : 1 ; + RK_U32 sw_wr_ddr_align_en : 1; + RK_U32 sw_scl_down_en : 1; + RK_U32 sw_allow_not_wr_unref_bframe : 1; + } sw_interrupt; ///<- zrh: do nothing in C Model + + struct swreg_sysctrl { + RK_U32 sw_in_endian : 1 ; + RK_U32 sw_in_swap32_e : 1 ; + RK_U32 sw_in_swap64_e : 1 ; + RK_U32 sw_str_endian : 1 ; + RK_U32 sw_str_swap32_e : 1 ; + RK_U32 sw_str_swap64_e : 1 ; + RK_U32 sw_out_endian : 1 ; + RK_U32 sw_out_swap32_e : 1 ; + RK_U32 sw_out_cbcr_swap : 1 ; + RK_U32 sw_error_info_en : 1 ; + RK_U32 sw_rlc_mode_direct_write : 1; + RK_U32 sw_rlc_mode : 1 ; + RK_U32 sw_strm_start_bit : 7 ; + RK_U32 sw_inter_error_prc_mode : 1; + RK_U32 sw_dec_mode : 2 ; + RK_U32 sw_info_collect_en : 1 ; + RK_U32 sw_wait_reset_en : 1 ; + RK_U32 sw_h26x_rps_mode : 1 ; + RK_U32 reserve2 : 5 ; + RK_U32 sw_colmv_mode : 1 ; + RK_U32 sw_head_prior_high_en : 1; + } sw_sysctrl; + + struct swreg_pic { + RK_U32 sw_y_hor_virstride : 9 ; + RK_U32 reserve : 3 ; + RK_U32 sw_uv_hor_virstride : 9 ; + RK_U32 sw_slice_num : 8 ; + } sw_picparameter; + + RK_U32 sw_strm_rlc_base ;///<- zrh: do nothing in C Model + RK_U32 sw_stream_len ;///<- zrh: do nothing in C Model + RK_U32 sw_cabactbl_base ;///<- zrh: do nothing in C Model + RK_U32 sw_decout_base ; + RK_U32 sw_y_virstride ; + RK_U32 sw_yuv_virstride ; + RK_U32 sw_refer_base[15] ; + RK_S32 sw_refer_poc[15] ; + RK_S32 sw_cur_poc ; + RK_U32 sw_rlcwrite_base ;///<- zrh: do nothing in C Model + RK_U32 sw_pps_base ;///<- zrh: do nothing in C Model + RK_U32 sw_rps_base ;///<- zrh: do nothing in C Model + RK_U32 cabac_error_en ;///<- zrh add + RK_U32 cabac_error_status ;///<- zrh add + + struct cabac_error_ctu { + RK_U32 sw_cabac_error_ctu_xoffset : 8; + RK_U32 sw_cabac_error_ctu_yoffset : 8; + RK_U32 sw_streamfifo_space2full : 7; + RK_U32 reversed0 : 9; + } cabac_error_ctu; + + struct sao_ctu_position { + RK_U32 sw_saowr_xoffset : 9; + RK_U32 reversed0 : 7; + RK_U32 sw_saowr_yoffset : 10; + RK_U32 reversed1 : 6; + } sao_ctu_position; + + RK_U32 reg_not_use0[RKVDEC_REG_PERF_CYCLE_INDEX - HEVC_DECODER_REG_NUM]; + union { + rkv_reg_end rkv_reg_ends; + v345_reg_end v345_reg_ends; + }; +} H265d_REGS_t; + +#endif diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu34x.c b/mpp/hal/rkdec/h265d/hal_h265d_vdpu34x.c new file mode 100644 index 000000000..19ffeaa37 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu34x.c @@ -0,0 +1,1432 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265d_vdpu34x" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bitput.h" + +#include "hal_hw_id.h" +#include "h265d_syntax.h" +#include "hal_h265d_debug.h" +#include "hal_h265d_ctx.h" +#include "hal_h265d_com.h" +#include "hal_h265d_vdpu34x.h" +#include "vdpu34x_h265d.h" +#include "vdpu_com.h" + +/* #define dump */ +#ifdef dump +static FILE *fp = NULL; +#endif + +#define HW_RPS +#define PPS_SIZE (112 * 64)//(96x64) + +#define COLMV_COMPRESS_EN 1 + +#define SET_REF_VALID(regs, index, value)\ + do{ \ + switch(index){\ + case 0: regs.reg99.hevc_ref_valid_0 = value; break;\ + case 1: regs.reg99.hevc_ref_valid_1 = value; break;\ + case 2: regs.reg99.hevc_ref_valid_2 = value; break;\ + case 3: regs.reg99.hevc_ref_valid_3 = value; break;\ + case 4: regs.reg99.hevc_ref_valid_4 = value; break;\ + case 5: regs.reg99.hevc_ref_valid_5 = value; break;\ + case 6: regs.reg99.hevc_ref_valid_6 = value; break;\ + case 7: regs.reg99.hevc_ref_valid_7 = value; break;\ + case 8: regs.reg99.hevc_ref_valid_8 = value; break;\ + case 9: regs.reg99.hevc_ref_valid_9 = value; break;\ + case 10: regs.reg99.hevc_ref_valid_10 = value; break;\ + case 11: regs.reg99.hevc_ref_valid_11 = value; break;\ + case 12: regs.reg99.hevc_ref_valid_12 = value; break;\ + case 13: regs.reg99.hevc_ref_valid_13 = value; break;\ + case 14: regs.reg99.hevc_ref_valid_14 = value; break;\ + default: break;}\ + }while(0) + +#define FMT 4 +#define CTU 3 + +typedef struct { + RK_U32 a; + RK_U32 b; +} FilterdColBufRatio; + +static const FilterdColBufRatio filterd_fbc_on[CTU][FMT] = { + /* 400 420 422 444 */ + {{0, 0}, {27, 15}, {36, 15}, {52, 15}}, //ctu 16 + {{0, 0}, {27, 8}, {36, 8}, {52, 8}}, //ctu 32 + {{0, 0}, {27, 5}, {36, 5}, {52, 5}} //ctu 64 +}; + +static const FilterdColBufRatio filterd_fbc_off[CTU][FMT] = { + /* 400 420 422 444 */ + {{0, 0}, {9, 31}, {12, 39}, {12, 39}}, //ctu 16 + {{0, 0}, {9, 25}, {12, 33}, {12, 33}}, //ctu 32 + {{0, 0}, {9, 21}, {12, 29}, {12, 29}} //ctu 64 +}; + +#define CABAC_TAB_ALIGEND_SIZE (MPP_ALIGN(27456, SZ_4K)) +#define SPSPPS_ALIGNED_SIZE (MPP_ALIGN(112 * 64, SZ_4K)) +#define RPS_ALIGEND_SIZE (MPP_ALIGN(400 * 8, SZ_4K)) +#define SCALIST_ALIGNED_SIZE (MPP_ALIGN(81 * 1360, SZ_4K)) +#define INFO_BUFFER_SIZE (SPSPPS_ALIGNED_SIZE + RPS_ALIGEND_SIZE + SCALIST_ALIGNED_SIZE) +#define ALL_BUFFER_SIZE(cnt) (CABAC_TAB_ALIGEND_SIZE + INFO_BUFFER_SIZE *cnt) + +#define CABAC_TAB_OFFSET (0) +#define SPSPPS_OFFSET(pos) (CABAC_TAB_OFFSET + CABAC_TAB_ALIGEND_SIZE + (INFO_BUFFER_SIZE * pos)) +#define RPS_OFFSET(pos) (SPSPPS_OFFSET(pos) + SPSPPS_ALIGNED_SIZE) +#define SCALIST_OFFSET(pos) (RPS_OFFSET(pos) + RPS_ALIGEND_SIZE) + +static MPP_RET hal_h265d_vdpu34x_init(void *hal, MppHalCfg *cfg) +{ + RK_S32 ret = 0; + RK_U32 hw_id = 0; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + + mpp_env_get_u32("hal_h265d_debug", &hal_h265d_debug, 0); + + reg_ctx->cfg = cfg; + cfg->support_fast_mode = 1; + reg_ctx->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + hw_id = mpp_get_client_hw_id(VPU_CLIENT_RKVDEC); + reg_ctx->is_v34x = (hw_id == HWID_VDPU34X || hw_id == HWID_VDPU38X); + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + + reg_ctx->scaling_qm = mpp_calloc(DXVA_Qmatrix_HEVC, 1); + if (reg_ctx->scaling_qm == NULL) { + mpp_err("scaling_org alloc fail"); + return MPP_ERR_MALLOC; + } + + reg_ctx->scaling_rk = mpp_calloc(scalingFactor_t, 1); + reg_ctx->pps_buf = mpp_calloc(RK_U64, 15); + reg_ctx->sw_rps_buf = mpp_calloc(RK_U64, 400); + + if (reg_ctx->scaling_rk == NULL) { + mpp_err("scaling_rk alloc fail"); + return MPP_ERR_MALLOC; + } + + { + RK_U32 i = 0; + RK_U32 max_cnt = (reg_ctx->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + + //!< malloc buffers + ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, ALL_BUFFER_SIZE(max_cnt)); + if (ret) { + mpp_err("h265d mpp_buffer_get failed\n"); + return ret; + } + + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->offset_cabac = CABAC_TAB_OFFSET; + for (i = 0; i < max_cnt; i++) { + reg_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu34xH265dRegSet)); + reg_ctx->offset_spspps[i] = SPSPPS_OFFSET(i); + reg_ctx->offset_rps[i] = RPS_OFFSET(i); + reg_ctx->offset_sclst[i] = SCALIST_OFFSET(i); + } + } + + if (!reg_ctx->fast_mode) { + reg_ctx->hw_regs = reg_ctx->g_buf[0].hw_regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->rps_offset = reg_ctx->offset_rps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + ret = mpp_buffer_write(reg_ctx->bufs, 0, (void*)cabac_table, sizeof(cabac_table)); + if (ret) { + mpp_err("h265d write cabac_table data failed\n"); + return ret; + } + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + +#ifdef dump + fp = fopen("/data/hal.bin", "wb"); +#endif + return MPP_OK; +} + +static MPP_RET hal_h265d_vdpu34x_deinit(void *hal) +{ + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_U32 loop = (reg_ctx->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->g_buf) : 1; + RK_U32 i; + + if (reg_ctx->bufs) { + mpp_buffer_put(reg_ctx->bufs); + reg_ctx->bufs = NULL; + } + + loop = (reg_ctx->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->rcb_buf) : 1; + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + } + + if (reg_ctx->missing_ref_buf) { + mpp_buffer_put(reg_ctx->missing_ref_buf); + reg_ctx->missing_ref_buf = NULL; + } + + for (i = 0; i < loop; i++) + MPP_FREE(reg_ctx->g_buf[i].hw_regs); + + MPP_FREE(reg_ctx->scaling_qm); + MPP_FREE(reg_ctx->scaling_rk); + MPP_FREE(reg_ctx->pps_buf); + MPP_FREE(reg_ctx->sw_rps_buf); + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + return MPP_OK; +} + +static RK_S32 hal_h265d_v345_output_pps_packet(void *hal, void *dxva) +{ + RK_S32 fifo_len = 14;//12 + RK_S32 i, j; + RK_U32 addr; + RK_U32 log2_min_cb_size; + RK_S32 width, height; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + Vdpu34xH265dRegSet *hw_reg = (Vdpu34xH265dRegSet*)(reg_ctx->hw_regs); + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + BitputCtx_t bp; + + if (NULL == reg_ctx || dxva_cxt == NULL) { + mpp_err("%s:%s:%d reg_ctx or dxva_cxt is NULL", + __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + void *pps_ptr = mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->spspps_offset; + if (dxva_cxt->pp.ps_update_flag) { + RK_U64 *pps_packet = reg_ctx->pps_buf; + if (NULL == pps_ptr) { + mpp_err("pps_data get ptr error"); + return MPP_ERR_NOMEM; + } + + for (i = 0; i < 14; i++) pps_packet[i] = 0; + + mpp_set_bitput_ctx(&bp, pps_packet, fifo_len); + + // SPS + mpp_put_bits(&bp, dxva_cxt->pp.vps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.chroma_format_idc , 2); + + log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + + mpp_put_bits(&bp, width , 16); + mpp_put_bits(&bp, height , 16); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_luma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_chroma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4 , 5); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size , 2); //log2_maxa_coding_block_depth + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_transform_block_size_minus2 + 2 , 3); + ///<-zrh comment ^ 63 bit above + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_transform_block_size , 2); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_inter , 3); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_intra , 3); + mpp_put_bits(&bp, dxva_cxt->pp.scaling_list_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.amp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.sample_adaptive_offset_enabled_flag , 1); + ///<-zrh comment ^ 68 bit above + mpp_put_bits(&bp, dxva_cxt->pp.pcm_enabled_flag , 1); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_luma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_chroma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pcm_loop_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_pcm_luma_coding_block_size , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.log2_min_pcm_luma_coding_block_size_minus3 + 3) : 0, 3); + + mpp_put_bits(&bp, dxva_cxt->pp.num_short_term_ref_pic_sets , 7); + mpp_put_bits(&bp, dxva_cxt->pp.long_term_ref_pics_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_long_term_ref_pics_sps , 6); + mpp_put_bits(&bp, dxva_cxt->pp.sps_temporal_mvp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.strong_intra_smoothing_enabled_flag , 1); + ///<-zrh comment ^ 100 bit above + + mpp_put_bits(&bp, 0 , 7 ); //49bits + //yandong change + mpp_put_bits(&bp, dxva_cxt->pp.sps_max_dec_pic_buffering_minus1, 4); + mpp_put_bits(&bp, 0, 3); + mpp_put_align(&bp , 32, 0xf); //128 + // PPS + mpp_put_bits(&bp, dxva_cxt->pp.pps_id , 6 ); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4 ); + mpp_put_bits(&bp, dxva_cxt->pp.dependent_slice_segments_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.output_flag_present_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.num_extra_slice_header_bits , 13); + mpp_put_bits(&bp, dxva_cxt->pp.sign_data_hiding_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cabac_init_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l0_default_active_minus1 + 1 , 4);//31 bits + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l1_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.init_qp_minus26 , 7); + mpp_put_bits(&bp, dxva_cxt->pp.constrained_intra_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transform_skip_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cu_qp_delta_enabled_flag , 1); //164 + mpp_put_bits(&bp, log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size - + dxva_cxt->pp.diff_cu_qp_delta_depth , 3); + + h265h_dbg(H265H_DBG_PPS, "log2_min_cb_size %d %d %d \n", log2_min_cb_size, + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size, dxva_cxt->pp.diff_cu_qp_delta_depth ); + + mpp_put_bits(&bp, dxva_cxt->pp.pps_cb_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_cr_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_slice_chroma_qp_offsets_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_bipred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transquant_bypass_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.tiles_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.entropy_coding_sync_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_loop_filter_across_slices_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.loop_filter_across_tiles_enabled_flag , 1); //185 + mpp_put_bits(&bp, dxva_cxt->pp.deblocking_filter_override_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_deblocking_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_beta_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pps_tc_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.lists_modification_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_parallel_merge_level_minus2 + 2 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.slice_segment_header_extension_present_flag , 1); + mpp_put_bits(&bp, 0 , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.tiles_enabled_flag != 0) ? dxva_cxt->pp.num_tile_columns_minus1 + 1 : 0, 5); + mpp_put_bits(&bp, (dxva_cxt->pp.tiles_enabled_flag != 0) ? dxva_cxt->pp.num_tile_rows_minus1 + 1 : 0 , 5 ); + mpp_put_bits(&bp, 0, 4);//2 //mSps_Pps[i]->mMode + mpp_put_align(&bp, 64, 0xf); + { + /// tiles info begin + RK_U16 column_width[20]; + RK_U16 row_height[22]; + + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + if (dxva_cxt->pp.tiles_enabled_flag) { + + if (dxva_cxt->pp.uniform_spacing_flag == 0) { + RK_S32 maxcuwidth = dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size; + RK_S32 ctu_width_in_pic = (width + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 ctu_height_in_pic = (height + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1; i++) { + column_width[i] = dxva_cxt->pp.column_width_minus1[i] + 1; + sum += column_width[i] ; + } + column_width[i] = ctu_width_in_pic - sum; + + sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1; i++) { + row_height[i] = dxva_cxt->pp.row_height_minus1[i] + 1; + sum += row_height[i]; + } + row_height[i] = ctu_height_in_pic - sum; + } // end of (pps->uniform_spacing_flag == 0) + else { + + RK_S32 pic_in_cts_width = (width + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + RK_S32 pic_in_cts_height = (height + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1 + 1; i++) + column_width[i] = ((i + 1) * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1) - + (i * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1); + + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1 + 1; i++) + row_height[i] = ((i + 1) * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1) - + (i * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1); + } + } // pps->tiles_enabled_flag + else { + RK_S32 MaxCUWidth = (1 << (dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size)); + column_width[0] = (width + MaxCUWidth - 1) / MaxCUWidth; + row_height[0] = (height + MaxCUWidth - 1) / MaxCUWidth; + } + + for (j = 0; j < 20; j++) { + if (column_width[j] > 0) + column_width[j]--; + mpp_put_bits(&bp, column_width[j], 12); + } + + for (j = 0; j < 22; j++) { + if (row_height[j] > 0) + row_height[j]--; + mpp_put_bits(&bp, row_height[j], 12); + } + } + + mpp_put_bits(&bp, 0, 32); + mpp_put_bits(&bp, 0, 70); + mpp_put_align(&bp, 64, 0xf);//128 + } + + if (dxva_cxt->pp.scaling_list_enabled_flag) { + RK_U8 *ptr_scaling = (RK_U8 *)mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->sclst_offset; + + if (dxva_cxt->pp.scaling_list_data_present_flag) { + addr = (dxva_cxt->pp.pps_id + 16) * 1360; + } else if (dxva_cxt->pp.scaling_list_enabled_flag) { + addr = dxva_cxt->pp.sps_id * 1360; + } else { + addr = 80 * 1360; + } + + hal_h265d_output_scalinglist_packet(hal, ptr_scaling + addr, dxva); + + hw_reg->h265d_addr.reg180_scanlist_addr = reg_ctx->bufs_fd; + hw_reg->common.reg012.scanlist_addr_valid_en = 1; + + /* need to config addr */ + mpp_dev_set_reg_offset(reg_ctx->cfg->dev, 180, addr + reg_ctx->sclst_offset); + } + + for (i = 0; i < 64; i++) + memcpy(pps_ptr + i * 112, reg_ctx->pps_buf, 112); +#ifdef dump + fwrite(pps_ptr, 1, 80 * 64, fp); + RK_U32 *tmp = (RK_U32 *)pps_ptr; + for (i = 0; i < 112 / 4; i++) { + mpp_log("pps[%3d] = 0x%08x\n", i, tmp[i]); + } +#endif + return 0; +} + +static RK_S32 hal_h265d_output_pps_packet(void *hal, void *dxva) +{ + RK_S32 fifo_len = 10; + RK_S32 i, j; + RK_U32 addr; + RK_U32 log2_min_cb_size; + RK_S32 width, height; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + BitputCtx_t bp; + + if (NULL == reg_ctx || dxva_cxt == NULL) { + mpp_err("%s:%s:%d reg_ctx or dxva_cxt is NULL", + __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + + void *pps_ptr = mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->spspps_offset; + + if (dxva_cxt->pp.ps_update_flag || dxva_cxt->pp.scaling_list_enabled_flag) { + RK_U64 *pps_packet = reg_ctx->pps_buf; + + if (NULL == pps_ptr) { + mpp_err("pps_data get ptr error"); + return MPP_ERR_NOMEM; + } + + for (i = 0; i < 10; i++) pps_packet[i] = 0; + + mpp_set_bitput_ctx(&bp, pps_packet, fifo_len); + + // SPS + mpp_put_bits(&bp, dxva_cxt->pp.vps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.chroma_format_idc , 2); + + log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + + mpp_put_bits(&bp, width , 16);//yandong + mpp_put_bits(&bp, height , 16);//yandong + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_luma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_chroma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4 , 5); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size , 2); //log2_maxa_coding_block_depth + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_transform_block_size_minus2 + 2 , 3); + ///<-zrh comment ^ 57 bit above + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_transform_block_size , 2); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_inter , 3); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_intra , 3); + mpp_put_bits(&bp, dxva_cxt->pp.scaling_list_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.amp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.sample_adaptive_offset_enabled_flag , 1); + ///<-zrh comment ^ 68 bit above + mpp_put_bits(&bp, dxva_cxt->pp.pcm_enabled_flag , 1); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_luma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_chroma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pcm_loop_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_pcm_luma_coding_block_size , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.log2_min_pcm_luma_coding_block_size_minus3 + 3) : 0, 3); + + mpp_put_bits(&bp, dxva_cxt->pp.num_short_term_ref_pic_sets , 7); + mpp_put_bits(&bp, dxva_cxt->pp.long_term_ref_pics_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_long_term_ref_pics_sps , 6); + mpp_put_bits(&bp, dxva_cxt->pp.sps_temporal_mvp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.strong_intra_smoothing_enabled_flag , 1); + ///<-zrh comment ^ 100 bit above + + mpp_put_bits(&bp, 0 , 7 ); + mpp_put_align(&bp , 32, 0xf); + + // PPS + mpp_put_bits(&bp, dxva_cxt->pp.pps_id , 6 ); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4 ); + mpp_put_bits(&bp, dxva_cxt->pp.dependent_slice_segments_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.output_flag_present_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.num_extra_slice_header_bits , 13); + mpp_put_bits(&bp, dxva_cxt->pp.sign_data_hiding_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cabac_init_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l0_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l1_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.init_qp_minus26 , 7); + mpp_put_bits(&bp, dxva_cxt->pp.constrained_intra_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transform_skip_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cu_qp_delta_enabled_flag , 1); + + mpp_put_bits(&bp, log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size - + dxva_cxt->pp.diff_cu_qp_delta_depth , 3); + + h265h_dbg(H265H_DBG_PPS, "log2_min_cb_size %d %d %d \n", log2_min_cb_size, + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size, dxva_cxt->pp.diff_cu_qp_delta_depth ); + + mpp_put_bits(&bp, dxva_cxt->pp.pps_cb_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_cr_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_slice_chroma_qp_offsets_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_bipred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transquant_bypass_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.tiles_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.entropy_coding_sync_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_loop_filter_across_slices_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.loop_filter_across_tiles_enabled_flag , 1); + + mpp_put_bits(&bp, dxva_cxt->pp.deblocking_filter_override_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_deblocking_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_beta_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pps_tc_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.lists_modification_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_parallel_merge_level_minus2 + 2 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.slice_segment_header_extension_present_flag , 1); + mpp_put_bits(&bp, 0 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.num_tile_columns_minus1 + 1, 5); + mpp_put_bits(&bp, dxva_cxt->pp.num_tile_rows_minus1 + 1 , 5 ); + mpp_put_bits(&bp, 3, 2); //mSps_Pps[i]->mMode + mpp_put_align(&bp, 64, 0xf); + + { + /// tiles info begin + RK_U16 column_width[20]; + RK_U16 row_height[22]; + + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + if (dxva_cxt->pp.tiles_enabled_flag) { + if (dxva_cxt->pp.uniform_spacing_flag == 0) { + RK_S32 maxcuwidth = dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size; + RK_S32 ctu_width_in_pic = (width + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 ctu_height_in_pic = (height + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1; i++) { + column_width[i] = dxva_cxt->pp.column_width_minus1[i] + 1; + sum += column_width[i] ; + } + column_width[i] = ctu_width_in_pic - sum; + + sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1; i++) { + row_height[i] = dxva_cxt->pp.row_height_minus1[i] + 1; + sum += row_height[i]; + } + row_height[i] = ctu_height_in_pic - sum; + } // end of (pps->uniform_spacing_flag == 0) + else { + + RK_S32 pic_in_cts_width = (width + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + RK_S32 pic_in_cts_height = (height + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1 + 1; i++) + column_width[i] = ((i + 1) * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1) - + (i * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1); + + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1 + 1; i++) + row_height[i] = ((i + 1) * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1) - + (i * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1); + } + } // pps->tiles_enabled_flag + else { + RK_S32 MaxCUWidth = (1 << (dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size)); + column_width[0] = (width + MaxCUWidth - 1) / MaxCUWidth; + row_height[0] = (height + MaxCUWidth - 1) / MaxCUWidth; + } + + for (j = 0; j < 20; j++) { + if (column_width[j] > 0) + column_width[j]--; + mpp_put_bits(&bp, column_width[j], 12);// yandong 8bit -> 12bit + } + + for (j = 0; j < 22; j++) { + if (row_height[j] > 0) + row_height[j]--; + mpp_put_bits(&bp, row_height[j], 12);// yandong 8bit -> 12bit + } + } + + { + RK_U8 *ptr_scaling = (RK_U8 *)mpp_buffer_get_ptr(reg_ctx->scaling_list_data); + if (dxva_cxt->pp.scaling_list_data_present_flag) { + addr = (dxva_cxt->pp.pps_id + 16) * 1360; + } else if (dxva_cxt->pp.scaling_list_enabled_flag) { + addr = dxva_cxt->pp.sps_id * 1360; + } else { + addr = 80 * 1360; + } + + hal_h265d_output_scalinglist_packet(hal, ptr_scaling + addr, dxva); + + RK_U32 fd = mpp_buffer_get_fd(reg_ctx->scaling_list_data); + /* need to config addr */ + addr = fd | (addr << 10); + + mpp_put_bits(&bp, addr, 32); + mpp_put_align(&bp, 64, 0xf); + } + for (i = 0; i < 64; i++) + memcpy(pps_ptr + i * 80, reg_ctx->pps_buf, 80); + } else if (reg_ctx->fast_mode) { + for (i = 0; i < 64; i++) + memcpy(pps_ptr + i * 80, reg_ctx->pps_buf, 80); + } + +#ifdef dump + fwrite(pps_ptr, 1, 80 * 64, fp); + fflush(fp); +#endif + return 0; +} + +static void h265d_refine_rcb_size(VdpuRcbInfo *rcb_info, + Vdpu34xH265dRegSet *hw_regs, + RK_S32 width, RK_S32 height, void *dxva) +{ + RK_U32 rcb_bits = 0; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + DXVA_PicParams_HEVC *pp = &dxva_cxt->pp; + RK_U32 chroma_fmt_idc = pp->chroma_format_idc;//0 400,1 4202 ,422,3 444 + RK_U8 bit_depth = MPP_MAX(pp->bit_depth_luma_minus8, pp->bit_depth_chroma_minus8) + 8; + RK_U8 ctu_size = 1 << (pp->log2_diff_max_min_luma_coding_block_size + pp->log2_min_luma_coding_block_size_minus3 + 3); + RK_U32 tile_col_cut_num = pp->num_tile_columns_minus1; + RK_U32 ext_align_size = tile_col_cut_num * 64 * 8; + + width = MPP_ALIGN(width, ctu_size); + height = MPP_ALIGN(height, ctu_size); + + /* RCB_STRMD_ROW */ + if (width > 8192) { + RK_U32 factor = ctu_size / 16; + rcb_bits = (MPP_ALIGN(width, ctu_size) + factor - 1) * factor * 24 + ext_align_size; + } else + rcb_bits = 0; + rcb_info[RCB_STRMD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_ROW */ + if (width > 8192) + rcb_bits = (MPP_ALIGN(width - 8192, 4) << 1) + ext_align_size; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_COL */ + if (height > 8192 && tile_col_cut_num) + rcb_bits = (MPP_ALIGN(height - 8192, 4) << 1); + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_COL].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_ROW */ + rcb_bits = width * 22 + ext_align_size; + rcb_info[RCB_INTER_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_COL */ + rcb_bits = (tile_col_cut_num != 0) ? height * 22 : 0; + rcb_info[RCB_INTER_COL].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTRA_ROW */ + rcb_bits = width * 48 + ext_align_size; + rcb_info[RCB_INTRA_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_DBLK_ROW */ + if (chroma_fmt_idc == 1 || chroma_fmt_idc == 2) { + if (ctu_size == 32) + rcb_bits = width * ( 4 + 6 * bit_depth); + else + rcb_bits = width * ( 2 + 6 * bit_depth); + } else { + if (ctu_size == 32) + rcb_bits = width * ( 4 + 8 * bit_depth); + else + rcb_bits = width * ( 2 + 8 * bit_depth); + } + rcb_bits += (tile_col_cut_num * (bit_depth == 8 ? 256 : 192)) + ext_align_size; + rcb_info[RCB_DBLK_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_SAO_ROW */ + if (chroma_fmt_idc == 1 || chroma_fmt_idc == 2) { + rcb_bits = width * (128 / ctu_size + 2 * bit_depth); + } else { + rcb_bits = width * (128 / ctu_size + 3 * bit_depth); + } + rcb_bits += (tile_col_cut_num * (bit_depth == 8 ? 160 : 128)) + ext_align_size; + rcb_info[RCB_SAO_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FBC_ROW */ + if (hw_regs->common.reg012.fbc_e) { + rcb_bits = width * (chroma_fmt_idc - 1) * 2 * bit_depth; + rcb_bits += (tile_col_cut_num * (bit_depth == 8 ? 128 : 64)) + ext_align_size; + } else + rcb_bits = 0; + rcb_info[RCB_FBC_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FILT_COL */ + if (tile_col_cut_num) { + if (hw_regs->common.reg012.fbc_e) { + RK_U32 ctu_idx = ctu_size >> 5; + RK_U32 a = filterd_fbc_on[ctu_idx][chroma_fmt_idc].a; + RK_U32 b = filterd_fbc_on[ctu_idx][chroma_fmt_idc].b; + + rcb_bits = height * (a * bit_depth + b); + } else { + RK_U32 ctu_idx = ctu_size >> 5; + RK_U32 a = filterd_fbc_off[ctu_idx][chroma_fmt_idc].a; + RK_U32 b = filterd_fbc_off[ctu_idx][chroma_fmt_idc].b; + + rcb_bits = height * (a * bit_depth + b + (bit_depth == 10 ? 16 : 0)); + } + } else + rcb_bits = 0; + + rcb_info[RCB_FILT_COL].size = MPP_RCB_BYTES(rcb_bits); +} + +static void hal_h265d_rcb_info_update(void *hal, void *dxva, + Vdpu34xH265dRegSet *hw_regs, + RK_S32 width, RK_S32 height) +{ + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + DXVA_PicParams_HEVC *pp = &dxva_cxt->pp; + RK_U32 chroma_fmt_idc = pp->chroma_format_idc;//0 400,1 4202 ,422,3 444 + RK_U8 bit_depth = MPP_MAX(pp->bit_depth_luma_minus8, pp->bit_depth_chroma_minus8) + 8; + RK_U8 ctu_size = 1 << (pp->log2_diff_max_min_luma_coding_block_size + pp->log2_min_luma_coding_block_size_minus3 + 3); + RK_U32 num_tiles = pp->num_tile_rows_minus1 + 1; + + if (reg_ctx->num_row_tiles != num_tiles || + reg_ctx->bit_depth != bit_depth || + reg_ctx->chroma_fmt_idc != chroma_fmt_idc || + reg_ctx->ctu_size != ctu_size || + reg_ctx->width != width || + reg_ctx->height != height) { + RK_U32 i = 0; + RK_U32 loop = (reg_ctx->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->g_buf) : 1; + + reg_ctx->rcb_buf_size = vdpu34x_get_rcb_buf_size((VdpuRcbInfo*)reg_ctx->rcb_info, width, height); + h265d_refine_rcb_size((VdpuRcbInfo*)reg_ctx->rcb_info, hw_regs, width, height, dxva_cxt); + + for (i = 0; i < loop; i++) { + MppBuffer rcb_buf; + + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + mpp_buffer_get(reg_ctx->cfg->buf_group, &rcb_buf, reg_ctx->rcb_buf_size); + reg_ctx->rcb_buf[i] = rcb_buf; + } + + reg_ctx->num_row_tiles = num_tiles; + reg_ctx->bit_depth = bit_depth; + reg_ctx->chroma_fmt_idc = chroma_fmt_idc; + reg_ctx->ctu_size = ctu_size; + reg_ctx->width = width; + reg_ctx->height = height; + } +} + +#define SET_POC_HIGNBIT_INFO(regs, index, field, value)\ + do{ \ + switch(index){\ + case 0: regs.reg200.ref0_##field = value; break;\ + case 1: regs.reg200.ref1_##field = value; break;\ + case 2: regs.reg200.ref2_##field = value; break;\ + case 3: regs.reg200.ref3_##field = value; break;\ + case 4: regs.reg200.ref4_##field = value; break;\ + case 5: regs.reg200.ref5_##field = value; break;\ + case 6: regs.reg200.ref6_##field = value; break;\ + case 7: regs.reg200.ref7_##field = value; break;\ + case 8: regs.reg201.ref8_##field = value; break;\ + case 9: regs.reg201.ref9_##field = value; break;\ + case 10: regs.reg201.ref10_##field = value; break;\ + case 11: regs.reg201.ref11_##field = value; break;\ + case 12: regs.reg201.ref12_##field = value; break;\ + case 13: regs.reg201.ref13_##field = value; break;\ + case 14: regs.reg201.ref14_##field = value; break;\ + case 15: regs.reg201.ref15_##field = value; break;\ + default: break;}\ + }while(0) + +#define pocdistance(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) + +static MPP_RET hal_h265d_vdpu34x_gen_regs(void *hal, HalTaskInfo *syn) +{ + RK_S32 i = 0; + RK_S32 log2_min_cb_size; + RK_S32 width, height; + RK_S32 stride_y, stride_uv, virstrid_y; + Vdpu34xH265dRegSet *hw_regs; + RK_S32 ret = MPP_SUCCESS; + MppBuffer streambuf = NULL; + RK_S32 aglin_offset = 0; + RK_S32 valid_ref = -1; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_S32 fd = -1; + RK_U32 mv_size = 0; + RK_S32 distance = INT_MAX; + h265d_dxva2_picture_context_t *dxva_cxt = + (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + void *rps_ptr = NULL; + RK_U32 stream_buf_size = 0; + DXVA_PicParams_HEVC *pp = &dxva_cxt->pp; + RK_U8 ctu_size = 1 << (pp->log2_diff_max_min_luma_coding_block_size + + pp->log2_min_luma_coding_block_size_minus3 + 3); + + if (syn->dec.flags.parse_err || + (syn->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx ->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!reg_ctx->g_buf[i].use_flag) { + syn->dec.reg_index = i; + + reg_ctx->spspps_offset = reg_ctx->offset_spspps[i]; + reg_ctx->rps_offset = reg_ctx->offset_rps[i]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[i]; + + reg_ctx->hw_regs = reg_ctx->g_buf[i].hw_regs; + reg_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("hevc rps buf all used"); + return MPP_ERR_NOMEM; + } + } else { + syn->dec.reg_index = 0; + } + rps_ptr = mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->rps_offset; + if (NULL == rps_ptr) { + + mpp_err("rps_data get ptr error"); + return MPP_ERR_NOMEM; + } + + + if (syn->dec.syntax.data == NULL) { + mpp_err("%s:%s:%d dxva is NULL", __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + + /* output pps */ + hw_regs = (Vdpu34xH265dRegSet*)reg_ctx->hw_regs; + memset(hw_regs, 0, sizeof(Vdpu34xH265dRegSet)); + + if (NULL == reg_ctx->hw_regs) { + return MPP_ERR_NULL_PTR; + } + + log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + mv_size = vdpu34x_get_colmv_size(width, height, ctu_size, 16, 16, COLMV_COMPRESS_EN); + if (reg_ctx->cmv_bufs == NULL || reg_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(®_ctx->cmv_bufs); + if (reg_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_ERR_NULL_PTR; + } + + reg_ctx->mv_size = mv_size; + reg_ctx->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(reg_ctx->cmv_bufs, reg_ctx->mv_count, 1, &size); + } + + { + MppFrame mframe = NULL; + RK_U32 ver_virstride; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + stride_y = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + stride_uv = stride_y; + virstrid_y = ver_virstride * stride_y; + hw_regs->common.reg013.h26x_error_mode = 1; + hw_regs->common.reg013.h26x_streamd_error_mode = 1; + hw_regs->common.reg013.colmv_error_mode = 1; + hw_regs->common.reg021.error_deb_en = 1; + hw_regs->common.reg021.inter_error_prc_mode = 0; + hw_regs->common.reg021.error_intra_mode = 1; + + hw_regs->common.reg017.slice_num = dxva_cxt->slice_count; + hw_regs->h265d_param.reg64.h26x_rps_mode = 0; + hw_regs->h265d_param.reg64.h26x_frame_orslice = 0; + hw_regs->h265d_param.reg64.h26x_stream_mode = 0; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (ver_virstride + 64) / 16, SZ_4K); + + hw_regs->common.reg012.fbc_e = 1; + hw_regs->common.reg018.y_hor_virstride = fbc_hdr_stride >> 4; + hw_regs->common.reg019.uv_hor_virstride = fbc_hdr_stride >> 4; + hw_regs->common.reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + hw_regs->common.reg012.fbc_e = 0; + hw_regs->common.reg018.y_hor_virstride = stride_y >> 4; + hw_regs->common.reg019.uv_hor_virstride = stride_uv >> 4; + hw_regs->common.reg020_y_virstride.y_virstride = virstrid_y >> 4; + } + } + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &framebuf); + hw_regs->common_addr.reg130_decout_base = mpp_buffer_get_fd(framebuf); //just index need map + /*if out_base is equal to zero it means this frame may error + we return directly add by csy*/ + + if (hw_regs->common_addr.reg130_decout_base == 0) { + return 0; + } + fd = mpp_buffer_get_fd(framebuf); + hw_regs->common_addr.reg130_decout_base = fd; + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_cxt->pp.CurrPic.Index7Bits); + hw_regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + + hw_regs->h265d_param.reg65.cur_top_poc = dxva_cxt->pp.CurrPicOrderCntVal; + + mpp_buf_slot_get_prop(cfg->packet_slots, syn->dec.input, SLOT_BUFFER, + &streambuf); + if ( dxva_cxt->bitstream == NULL) { + dxva_cxt->bitstream = mpp_buffer_get_ptr(streambuf); + } + if (reg_ctx->is_v34x) { +#ifdef HW_RPS + hw_regs->common.reg012.wait_reset_en = 1; + hw_regs->h265d_param.reg103.ref_pic_layer_same_with_cur = 0xffff; + hal_h265d_slice_hw_rps(syn->dec.syntax.data, rps_ptr, reg_ctx->sw_rps_buf, reg_ctx->fast_mode); +#else + hw_regs->sw_sysctrl.sw_h26x_rps_mode = 1; + hal_h265d_slice_output_rps(syn->dec.syntax.data, rps_ptr); +#endif + } else { + hal_h265d_slice_output_rps(syn->dec.syntax.data, rps_ptr); + } + + /* cabac table */ + hw_regs->h265d_addr.reg197_cabactbl_base = reg_ctx->bufs_fd; + /* pps */ + hw_regs->h265d_addr.reg161_pps_base = reg_ctx->bufs_fd; + hw_regs->h265d_addr.reg163_rps_base = reg_ctx->bufs_fd; + + hw_regs->common_addr.reg128_rlc_base = mpp_buffer_get_fd(streambuf); + hw_regs->common_addr.reg129_rlcwrite_base = mpp_buffer_get_fd(streambuf); + stream_buf_size = mpp_buffer_get_size(streambuf); + hw_regs->common.reg016_str_len = ((dxva_cxt->bitstream_size + 15) + & (~15)) + 64; + hw_regs->common.reg016_str_len = stream_buf_size > hw_regs->common.reg016_str_len ? + hw_regs->common.reg016_str_len : stream_buf_size; + + aglin_offset = hw_regs->common.reg016_str_len - dxva_cxt->bitstream_size; + if (aglin_offset > 0) { + memset((void *)(dxva_cxt->bitstream + dxva_cxt->bitstream_size), 0, + aglin_offset); + } + hw_regs->common.reg010.dec_e = 1; + hw_regs->common.reg011.dec_timeout_e = 1; + hw_regs->common.reg012.wr_ddr_align_en = (dxva_cxt->pp.tiles_enabled_flag != 0) + ? 0 : 1; + hw_regs->common.reg012.colmv_compress_en = COLMV_COMPRESS_EN; + + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) { + hw_regs->common.reg026.swreg_block_gating_e = 0xfffef; + hw_regs->common.reg024.cabac_err_en_lowbits = 0; + hw_regs->common.reg025.cabac_err_en_highbits = 0; + } else { + hw_regs->common.reg024.cabac_err_en_lowbits = 0xffffdfff; + hw_regs->common.reg025.cabac_err_en_highbits = 0x3ffbf9ff; + hw_regs->common.reg026.swreg_block_gating_e = 0xfffff; + } + + hw_regs->common.reg011.dec_clkgate_e = 1; + hw_regs->common.reg011.dec_e_strmd_clkgate_dis = 0; + hw_regs->common.reg026.reg_cfg_gating_en = 1; + hw_regs->common.reg032_timeout_threshold = 0x3ffff; + + valid_ref = hw_regs->common_addr.reg130_decout_base; + reg_ctx->error_index[syn->dec.reg_index] = dxva_cxt->pp.CurrPic.Index7Bits; + hw_regs->common_addr.reg132_error_ref_base = valid_ref; + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_cxt->pp.RefPicList); i++) { + if (dxva_cxt->pp.RefPicList[i].bPicEntry != 0xff && + dxva_cxt->pp.RefPicList[i].bPicEntry != 0x7f) { + + MppFrame mframe = NULL; + MppBuffer ref_buf = NULL; + hw_regs->h265d_param.reg67_82_ref_poc[i] = dxva_cxt->pp.PicOrderCntValList[i]; + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_cxt->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &ref_buf); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + if (!ref_buf && mpp_get_soc_type() == ROCKCHIP_SOC_RK3588 && + cfg->cfg->base.disable_error) { + if (reg_ctx->missing_ref_buf && reg_ctx->missing_ref_buf_size < mpp_buffer_get_size(framebuf)) { + mpp_buffer_put(reg_ctx->missing_ref_buf); + reg_ctx->missing_ref_buf = NULL; + } + + if (!reg_ctx->missing_ref_buf) { + reg_ctx->missing_ref_buf_size = mpp_buffer_get_size(framebuf); + mpp_buffer_get(cfg->buf_group, ®_ctx->missing_ref_buf, reg_ctx->missing_ref_buf_size); + if (!reg_ctx->missing_ref_buf) { + syn->dec.flags.ref_err = 1; + h265h_dbg(H265H_DBG_TASK_ERR, "Failed to generate missing ref buf\n"); + return MPP_ERR_NOMEM; + } + } + ref_buf = reg_ctx->missing_ref_buf; + } + if (ref_buf) { + hw_regs->h265d_addr.reg164_179_ref_base[i] = mpp_buffer_get_fd(ref_buf); + valid_ref = hw_regs->h265d_addr.reg164_179_ref_base[i]; + h265h_dbg(H265H_DBG_TASK_ERR, "cur poc %d, ref poc %d", dxva_cxt->pp.current_poc, dxva_cxt->pp.PicOrderCntValList[i]); + if ((pocdistance(dxva_cxt->pp.PicOrderCntValList[i], dxva_cxt->pp.current_poc) < distance) + && (!mpp_frame_get_errinfo(mframe))) { + distance = pocdistance(dxva_cxt->pp.PicOrderCntValList[i], dxva_cxt->pp.current_poc); + hw_regs->common_addr.reg132_error_ref_base = hw_regs->h265d_addr.reg164_179_ref_base[i]; + reg_ctx->error_index[syn->dec.reg_index] = dxva_cxt->pp.RefPicList[i].Index7Bits; + hw_regs->common.reg021.error_intra_mode = 0; + h265h_dbg(H265H_DBG_TASK_ERR, "update error ref to ref[%d] to poc %d, slot_idx %d, fd %d\n", + i, dxva_cxt->pp.PicOrderCntValList[i], + dxva_cxt->pp.RefPicList[i].Index7Bits, + hw_regs->common_addr.reg132_error_ref_base); + } + } else { + h265h_dbg(H265H_DBG_TASK_ERR, "ref[%d] buffer is empty, replace with fd %d\n", i, valid_ref); + hw_regs->h265d_addr.reg164_179_ref_base[i] = valid_ref; + } + + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_cxt->pp.RefPicList[i].Index7Bits); + + SET_REF_VALID(hw_regs->h265d_param, i, 1); + + if (hw_regs->common.reg013.h26x_error_mode && + !hw_regs->common.reg021.error_intra_mode && + (!ref_buf || mpp_frame_get_errinfo(mframe))) { + + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->h265d_addr.reg164_179_ref_base[i] = hw_regs->common_addr.reg132_error_ref_base; + } + } else { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->h265d_addr.reg164_179_ref_base[i] = hw_regs->common_addr.reg132_error_ref_base; + /* mark 3 to differ from current frame */ + if (reg_ctx->error_index[syn->dec.reg_index] == dxva_cxt->pp.CurrPic.Index7Bits) + SET_POC_HIGNBIT_INFO(hw_regs->highpoc, i, poc_highbit, 3); + } + hw_regs->h265d_addr.reg181_196_colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + + if ((reg_ctx->error_index[syn->dec.reg_index] == dxva_cxt->pp.CurrPic.Index7Bits) && + !dxva_cxt->pp.IntraPicFlag && !cfg->cfg->base.disable_error) { + h265h_dbg(H265H_DBG_TASK_ERR, "current frm may be err, should skip process"); + syn->dec.flags.ref_err = 1; + return MPP_OK; + } + + if (reg_ctx->is_v34x) { + hal_h265d_v345_output_pps_packet(hal, syn->dec.syntax.data); + } else { + hal_h265d_output_pps_packet(hal, syn->dec.syntax.data); + } + + mpp_dev_set_reg_offset(cfg->dev, 161, reg_ctx->spspps_offset); + /* rps */ + mpp_dev_set_reg_offset(cfg->dev, 163, reg_ctx->rps_offset); + + hw_regs->common.reg013.timeout_mode = 1; + hw_regs->common.reg013.cur_pic_is_idr = dxva_cxt->pp.IdrPicFlag;//p_hal->slice_long->idr_flag; + + hw_regs->common.reg011.buf_empty_en = 1; + + hal_h265d_rcb_info_update(hal, dxva_cxt, hw_regs, width, height); + vdpu34x_setup_rcb(&hw_regs->common_addr, cfg->dev, (reg_ctx->fast_mode != 0) ? + reg_ctx->rcb_buf[syn->dec.reg_index] : reg_ctx->rcb_buf[0], + (VdpuRcbInfo*)reg_ctx->rcb_info); + vdpu34x_setup_statistic(&hw_regs->common, &hw_regs->statistic); + mpp_buffer_sync_end(reg_ctx->bufs); + + return ret; +} + +static MPP_RET hal_h265d_vdpu34x_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U8* p = NULL; + Vdpu34xH265dRegSet *hw_regs = NULL; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_S32 index = task->dec.reg_index; + + RK_U32 i; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !reg_ctx->cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx->fast_mode) { + p = (RK_U8*)reg_ctx->g_buf[index].hw_regs; + hw_regs = ( Vdpu34xH265dRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + p = (RK_U8*)reg_ctx->hw_regs; + hw_regs = ( Vdpu34xH265dRegSet *)reg_ctx->hw_regs; + } + + if (hw_regs == NULL) { + mpp_err("hal_h265d_start hw_regs is NULL"); + return MPP_ERR_NULL_PTR; + } + for (i = 0; i < 68; i++) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + //mpp_log("RK_HEVC_DEC: regs[%02d]=%08X\n", i, *((RK_U32*)p)); + p += 4; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = reg_ctx->cfg->dev; + + wr_cfg.reg = &hw_regs->common; + wr_cfg.size = sizeof(hw_regs->common); + wr_cfg.offset = VDPU34X_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->h265d_param; + wr_cfg.size = sizeof(hw_regs->h265d_param); + wr_cfg.offset = VDPU34X_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->common_addr; + wr_cfg.size = sizeof(hw_regs->common_addr); + wr_cfg.offset = VDPU34X_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->h265d_addr; + wr_cfg.size = sizeof(hw_regs->h265d_addr); + wr_cfg.offset = VDPU34X_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->statistic; + wr_cfg.size = sizeof(hw_regs->statistic); + wr_cfg.offset = VDPU34X_OFF_STATISTIC_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) { + wr_cfg.reg = &hw_regs->highpoc; + wr_cfg.size = sizeof(hw_regs->highpoc); + wr_cfg.offset = VDPU34X_OFF_POC_HIGHBIT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + } + + rd_cfg.reg = &hw_regs->irq_status; + rd_cfg.size = sizeof(hw_regs->irq_status); + rd_cfg.offset = VDPU34X_OFF_INTERRUPT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu34x_set_rcbinfo(dev, (VdpuRcbInfo*)reg_ctx->rcb_info); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + + +static MPP_RET hal_h265d_vdpu34x_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_S32 index = task->dec.reg_index; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + RK_U8* p = NULL; + Vdpu34xH265dRegSet *hw_regs = NULL; + RK_S32 i; + + if (reg_ctx->fast_mode) { + hw_regs = ( Vdpu34xH265dRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( Vdpu34xH265dRegSet *)reg_ctx->hw_regs; + } + + p = (RK_U8*)hw_regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + goto ERR_PROC; + } + + ret = mpp_dev_ioctl(cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +ERR_PROC: + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + hw_regs->irq_status.reg224.dec_error_sta || + hw_regs->irq_status.reg224.buf_empty_sta || + hw_regs->irq_status.reg224.dec_bus_sta || + !hw_regs->irq_status.reg224.dec_rdy_sta) { + if (!reg_ctx->fast_mode) { + if (cfg->dec_cb) + mpp_callback(cfg->dec_cb, &task->dec); + } else { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + if (mframe) { + reg_ctx->fast_mode_err_found = 1; + mpp_frame_set_errinfo(mframe, 1); + } + } + } else { + if (reg_ctx->fast_mode && reg_ctx->fast_mode_err_found) { + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(task->dec.refer); i++) { + if (task->dec.refer[i] >= 0) { + MppFrame frame_ref = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.refer[i], + SLOT_FRAME_PTR, &frame_ref); + h265h_dbg(H265H_DBG_FAST_ERR, "refer[%d] %d frame %p\n", + i, task->dec.refer[i], frame_ref); + if (frame_ref && mpp_frame_get_errinfo(frame_ref)) { + MppFrame frame_out = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &frame_out); + mpp_frame_set_errinfo(frame_out, 1); + break; + } + } + } + } + } + + for (i = 0; i < 68; i++) { + if (i == 1) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + + if (i == 45) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + p += 4; + } + + if (reg_ctx->fast_mode) { + reg_ctx->g_buf[index].use_flag = 0; + } + + return ret; +} + +static MPP_RET hal_h265d_vdpu34x_reset(void *hal) +{ + MPP_RET ret = MPP_OK; + HalH265dCtx *p_hal = (HalH265dCtx *)hal; + p_hal->fast_mode_err_found = 0; + (void)hal; + return ret; +} + +static MPP_RET hal_h265d_vdpu34x_flush(void *hal) +{ + MPP_RET ret = MPP_OK; + + (void)hal; + return ret; +} + +static MPP_RET hal_h265d_vdpu34x_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_OK; + HalH265dCtx *p_hal = (HalH265dCtx *)hal; + + (void)hal; + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrame frame = (MppFrame)param; + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, frame, 16); + } + break; + } + case MPP_DEC_SET_OUTPUT_FORMAT: { + } break; + default: + break; + } + return ret; +} + +const MppHalApi hal_h265d_vdpu34x = { + .name = "h265d_vdpu34x", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(HalH265dCtx), + .flag = 0, + .init = hal_h265d_vdpu34x_init, + .deinit = hal_h265d_vdpu34x_deinit, + .reg_gen = hal_h265d_vdpu34x_gen_regs, + .start = hal_h265d_vdpu34x_start, + .wait = hal_h265d_vdpu34x_wait, + .reset = hal_h265d_vdpu34x_reset, + .flush = hal_h265d_vdpu34x_flush, + .control = hal_h265d_vdpu34x_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h265d_vdpu34x) diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu34x.h b/mpp/hal/rkdec/h265d/hal_h265d_vdpu34x.h new file mode 100644 index 000000000..4eeba6e3f --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu34x.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265D_VDPU34X_H +#define HAL_H265D_VDPU34X_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h265d_vdpu34x; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_VDPU34X_H */ diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu382.c b/mpp/hal/rkdec/h265d/hal_h265d_vdpu382.c new file mode 100644 index 000000000..fd7aca13d --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu382.c @@ -0,0 +1,1215 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265d_vdpu382" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bitput.h" + +#include "h265d_syntax.h" +#include "hal_h265d_debug.h" +#include "hal_h265d_ctx.h" +#include "hal_h265d_com.h" +#include "hal_h265d_vdpu382.h" +#include "vdpu382_h265d.h" +#include "vdpu_com.h" + +/* #define dump */ +#ifdef dump +static FILE *fp = NULL; +#endif + +#define HW_RPS +#define PPS_SIZE (112 * 64)//(96x64) + +#define SET_REF_VALID(regs, index, value)\ + do{ \ + switch(index){\ + case 0: regs.reg99.hevc_ref_valid_0 = value; break;\ + case 1: regs.reg99.hevc_ref_valid_1 = value; break;\ + case 2: regs.reg99.hevc_ref_valid_2 = value; break;\ + case 3: regs.reg99.hevc_ref_valid_3 = value; break;\ + case 4: regs.reg99.hevc_ref_valid_4 = value; break;\ + case 5: regs.reg99.hevc_ref_valid_5 = value; break;\ + case 6: regs.reg99.hevc_ref_valid_6 = value; break;\ + case 7: regs.reg99.hevc_ref_valid_7 = value; break;\ + case 8: regs.reg99.hevc_ref_valid_8 = value; break;\ + case 9: regs.reg99.hevc_ref_valid_9 = value; break;\ + case 10: regs.reg99.hevc_ref_valid_10 = value; break;\ + case 11: regs.reg99.hevc_ref_valid_11 = value; break;\ + case 12: regs.reg99.hevc_ref_valid_12 = value; break;\ + case 13: regs.reg99.hevc_ref_valid_13 = value; break;\ + case 14: regs.reg99.hevc_ref_valid_14 = value; break;\ + default: break;}\ + }while(0) + +#define FMT 4 +#define CTU 3 + +typedef struct { + RK_U32 a; + RK_U32 b; +} FilterdColBufRatio; + +static const FilterdColBufRatio filterd_fbc_on[CTU][FMT] = { + /* 400 420 422 444 */ + {{0, 0}, {27, 15}, {36, 15}, {52, 15}}, //ctu 16 + {{0, 0}, {27, 8}, {36, 8}, {52, 8}}, //ctu 32 + {{0, 0}, {27, 5}, {36, 5}, {52, 5}} //ctu 64 +}; + +static const FilterdColBufRatio filterd_fbc_off[CTU][FMT] = { + /* 400 420 422 444 */ + {{0, 0}, {15, 5}, {20, 5}, {20, 5}}, //ctu 16 + {{0, 0}, {15, 9}, {20, 9}, {20, 9}}, //ctu 32 + {{0, 0}, {15, 16}, {20, 16}, {20, 16}} //ctu 64 +}; + +#define CABAC_TAB_ALIGEND_SIZE (MPP_ALIGN(27456, SZ_4K)) +#define SPSPPS_ALIGNED_SIZE (MPP_ALIGN(112 * 64, SZ_4K)) +#define RPS_ALIGEND_SIZE (MPP_ALIGN(400 * 8, SZ_4K)) +#define SCALIST_ALIGNED_SIZE (MPP_ALIGN(81 * 1360, SZ_4K)) +#define INFO_BUFFER_SIZE (SPSPPS_ALIGNED_SIZE + RPS_ALIGEND_SIZE + SCALIST_ALIGNED_SIZE) +#define ALL_BUFFER_SIZE(cnt) (CABAC_TAB_ALIGEND_SIZE + INFO_BUFFER_SIZE *cnt) + +#define CABAC_TAB_OFFSET (0) +#define SPSPPS_OFFSET(pos) (CABAC_TAB_OFFSET + CABAC_TAB_ALIGEND_SIZE + (INFO_BUFFER_SIZE * pos)) +#define RPS_OFFSET(pos) (SPSPPS_OFFSET(pos) + SPSPPS_ALIGNED_SIZE) +#define SCALIST_OFFSET(pos) (RPS_OFFSET(pos) + RPS_ALIGEND_SIZE) + +static MPP_RET hal_h265d_vdpu382_init(void *hal, MppHalCfg *cfg) +{ + RK_S32 ret = 0; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + + mpp_env_get_u32("hal_h265d_debug", &hal_h265d_debug, 0); + + reg_ctx->cfg = cfg; + cfg->support_fast_mode = 1; + reg_ctx->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + + reg_ctx->scaling_qm = mpp_calloc(DXVA_Qmatrix_HEVC, 1); + if (reg_ctx->scaling_qm == NULL) { + mpp_err("scaling_org alloc fail"); + return MPP_ERR_MALLOC; + } + + reg_ctx->scaling_rk = mpp_calloc(scalingFactor_t, 1); + reg_ctx->pps_buf = mpp_calloc(RK_U64, 15); + reg_ctx->sw_rps_buf = mpp_calloc(RK_U64, 400); + + if (reg_ctx->scaling_rk == NULL) { + mpp_err("scaling_rk alloc fail"); + return MPP_ERR_MALLOC; + } + + { + RK_U32 i = 0; + RK_U32 max_cnt = (reg_ctx->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + + //!< malloc buffers + ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, ALL_BUFFER_SIZE(max_cnt)); + if (ret) { + mpp_err("h265d mpp_buffer_get failed\n"); + return ret; + } + + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->offset_cabac = CABAC_TAB_OFFSET; + for (i = 0; i < max_cnt; i++) { + reg_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu382H265dRegSet)); + reg_ctx->offset_spspps[i] = SPSPPS_OFFSET(i); + reg_ctx->offset_rps[i] = RPS_OFFSET(i); + reg_ctx->offset_sclst[i] = SCALIST_OFFSET(i); + } + } + + if (!reg_ctx->fast_mode) { + reg_ctx->hw_regs = reg_ctx->g_buf[0].hw_regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->rps_offset = reg_ctx->offset_rps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + ret = mpp_buffer_write(reg_ctx->bufs, 0, (void*)cabac_table, sizeof(cabac_table)); + if (ret) { + mpp_err("h265d write cabac_table data failed\n"); + return ret; + } + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + +#ifdef dump + fp = fopen("/data/hal.bin", "wb"); +#endif + return MPP_OK; +} + +static MPP_RET hal_h265d_vdpu382_deinit(void *hal) +{ + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_U32 loop = (reg_ctx->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->g_buf) : 1; + RK_U32 i; + + if (reg_ctx->bufs) { + mpp_buffer_put(reg_ctx->bufs); + reg_ctx->bufs = NULL; + } + + loop = (reg_ctx->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->rcb_buf) : 1; + for (i = 0; i < loop; i++) { + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + } + + for (i = 0; i < loop; i++) + MPP_FREE(reg_ctx->g_buf[i].hw_regs); + + MPP_FREE(reg_ctx->scaling_qm); + MPP_FREE(reg_ctx->scaling_rk); + MPP_FREE(reg_ctx->pps_buf); + MPP_FREE(reg_ctx->sw_rps_buf); + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + return MPP_OK; +} + +static RK_S32 hal_h265d_v382_output_pps_packet(void *hal, void *dxva) +{ + RK_S32 fifo_len = 14;//12 + RK_S32 i, j; + RK_U32 addr; + RK_U32 log2_min_cb_size; + RK_S32 width, height; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + Vdpu382H265dRegSet *hw_reg = (Vdpu382H265dRegSet*)(reg_ctx->hw_regs); + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + BitputCtx_t bp; + + if (NULL == reg_ctx || dxva_cxt == NULL) { + mpp_err("%s:%s:%d reg_ctx or dxva_cxt is NULL", + __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + void *pps_ptr = mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->spspps_offset; + if (dxva_cxt->pp.ps_update_flag) { + RK_U64 *pps_packet = reg_ctx->pps_buf; + if (NULL == pps_ptr) { + mpp_err("pps_data get ptr error"); + return MPP_ERR_NOMEM; + } + + for (i = 0; i < 14; i++) pps_packet[i] = 0; + + mpp_set_bitput_ctx(&bp, pps_packet, fifo_len); + + // SPS + mpp_put_bits(&bp, dxva_cxt->pp.vps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4); + mpp_put_bits(&bp, dxva_cxt->pp.chroma_format_idc , 2); + + log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + + mpp_put_bits(&bp, width , 16); + mpp_put_bits(&bp, height , 16); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_luma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.bit_depth_chroma_minus8 + 8 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.log2_max_pic_order_cnt_lsb_minus4 + 4 , 5); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size , 2); //log2_maxa_coding_block_depth + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.log2_min_transform_block_size_minus2 + 2 , 3); + ///<-zrh comment ^ 63 bit above + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_transform_block_size , 2); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_inter , 3); + mpp_put_bits(&bp, dxva_cxt->pp.max_transform_hierarchy_depth_intra , 3); + mpp_put_bits(&bp, dxva_cxt->pp.scaling_list_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.amp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.sample_adaptive_offset_enabled_flag , 1); + ///<-zrh comment ^ 68 bit above + mpp_put_bits(&bp, dxva_cxt->pp.pcm_enabled_flag , 1); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_luma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.pcm_sample_bit_depth_chroma_minus1 + 1) : 0 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pcm_loop_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_diff_max_min_pcm_luma_coding_block_size , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.pcm_enabled_flag != 0) ? (dxva_cxt->pp.log2_min_pcm_luma_coding_block_size_minus3 + 3) : 0, 3); + + mpp_put_bits(&bp, dxva_cxt->pp.num_short_term_ref_pic_sets , 7); + mpp_put_bits(&bp, dxva_cxt->pp.long_term_ref_pics_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_long_term_ref_pics_sps , 6); + mpp_put_bits(&bp, dxva_cxt->pp.sps_temporal_mvp_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.strong_intra_smoothing_enabled_flag , 1); + ///<-zrh comment ^ 100 bit above + + mpp_put_bits(&bp, 0 , 7 ); //49bits + //yandong change + mpp_put_bits(&bp, dxva_cxt->pp.sps_max_dec_pic_buffering_minus1, 4); + mpp_put_bits(&bp, 0, 3); + mpp_put_align(&bp , 32, 0xf); //128 + // PPS + mpp_put_bits(&bp, dxva_cxt->pp.pps_id , 6 ); + mpp_put_bits(&bp, dxva_cxt->pp.sps_id , 4 ); + mpp_put_bits(&bp, dxva_cxt->pp.dependent_slice_segments_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.output_flag_present_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.num_extra_slice_header_bits , 13); + mpp_put_bits(&bp, dxva_cxt->pp.sign_data_hiding_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cabac_init_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l0_default_active_minus1 + 1 , 4);//31 bits + mpp_put_bits(&bp, dxva_cxt->pp.num_ref_idx_l1_default_active_minus1 + 1 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.init_qp_minus26 , 7); + mpp_put_bits(&bp, dxva_cxt->pp.constrained_intra_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transform_skip_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.cu_qp_delta_enabled_flag , 1); //164 + mpp_put_bits(&bp, log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size - + dxva_cxt->pp.diff_cu_qp_delta_depth , 3); + + h265h_dbg(H265H_DBG_PPS, "log2_min_cb_size %d %d %d \n", log2_min_cb_size, + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size, dxva_cxt->pp.diff_cu_qp_delta_depth ); + + mpp_put_bits(&bp, dxva_cxt->pp.pps_cb_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_cr_qp_offset , 5); + mpp_put_bits(&bp, dxva_cxt->pp.pps_slice_chroma_qp_offsets_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_pred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.weighted_bipred_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.transquant_bypass_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.tiles_enabled_flag , 1 ); + mpp_put_bits(&bp, dxva_cxt->pp.entropy_coding_sync_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_loop_filter_across_slices_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.loop_filter_across_tiles_enabled_flag , 1); //185 + mpp_put_bits(&bp, dxva_cxt->pp.deblocking_filter_override_enabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_deblocking_filter_disabled_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.pps_beta_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.pps_tc_offset_div2 , 4); + mpp_put_bits(&bp, dxva_cxt->pp.lists_modification_present_flag , 1); + mpp_put_bits(&bp, dxva_cxt->pp.log2_parallel_merge_level_minus2 + 2 , 3); + mpp_put_bits(&bp, dxva_cxt->pp.slice_segment_header_extension_present_flag , 1); + mpp_put_bits(&bp, 0 , 3); + mpp_put_bits(&bp, (dxva_cxt->pp.tiles_enabled_flag != 0) ? dxva_cxt->pp.num_tile_columns_minus1 + 1 : 0, 5); + mpp_put_bits(&bp, (dxva_cxt->pp.tiles_enabled_flag != 0) ? dxva_cxt->pp.num_tile_rows_minus1 + 1 : 0 , 5 ); + mpp_put_bits(&bp, 0, 4);//2 //mSps_Pps[i]->mMode + mpp_put_align(&bp, 64, 0xf); + { + /// tiles info begin + RK_U16 column_width[20]; + RK_U16 row_height[22]; + + memset(column_width, 0, sizeof(column_width)); + memset(row_height, 0, sizeof(row_height)); + + if (dxva_cxt->pp.tiles_enabled_flag) { + + if (dxva_cxt->pp.uniform_spacing_flag == 0) { + RK_S32 maxcuwidth = dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size; + RK_S32 ctu_width_in_pic = (width + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 ctu_height_in_pic = (height + + (1 << maxcuwidth) - 1) / (1 << maxcuwidth) ; + RK_S32 sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1; i++) { + column_width[i] = dxva_cxt->pp.column_width_minus1[i] + 1; + sum += column_width[i] ; + } + column_width[i] = ctu_width_in_pic - sum; + + sum = 0; + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1; i++) { + row_height[i] = dxva_cxt->pp.row_height_minus1[i] + 1; + sum += row_height[i]; + } + row_height[i] = ctu_height_in_pic - sum; + } // end of (pps->uniform_spacing_flag == 0) + else { + + RK_S32 pic_in_cts_width = (width + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + RK_S32 pic_in_cts_height = (height + + (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)) - 1) + / (1 << (log2_min_cb_size + + dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size)); + + for (i = 0; i < dxva_cxt->pp.num_tile_columns_minus1 + 1; i++) + column_width[i] = ((i + 1) * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1) - + (i * pic_in_cts_width) / (dxva_cxt->pp.num_tile_columns_minus1 + 1); + + for (i = 0; i < dxva_cxt->pp.num_tile_rows_minus1 + 1; i++) + row_height[i] = ((i + 1) * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1) - + (i * pic_in_cts_height) / (dxva_cxt->pp.num_tile_rows_minus1 + 1); + } + } // pps->tiles_enabled_flag + else { + RK_S32 MaxCUWidth = (1 << (dxva_cxt->pp.log2_diff_max_min_luma_coding_block_size + log2_min_cb_size)); + column_width[0] = (width + MaxCUWidth - 1) / MaxCUWidth; + row_height[0] = (height + MaxCUWidth - 1) / MaxCUWidth; + } + + for (j = 0; j < 20; j++) { + if (column_width[j] > 0) + column_width[j]--; + mpp_put_bits(&bp, column_width[j], 12); + } + + for (j = 0; j < 22; j++) { + if (row_height[j] > 0) + row_height[j]--; + mpp_put_bits(&bp, row_height[j], 12); + } + } + + mpp_put_bits(&bp, 0, 32); + mpp_put_bits(&bp, 0, 70); + mpp_put_align(&bp, 64, 0xf);//128 + } + + if (dxva_cxt->pp.scaling_list_enabled_flag) { + RK_U8 *ptr_scaling = (RK_U8 *)mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->sclst_offset; + + if (dxva_cxt->pp.scaling_list_data_present_flag) { + addr = (dxva_cxt->pp.pps_id + 16) * 1360; + } else if (dxva_cxt->pp.scaling_list_enabled_flag) { + addr = dxva_cxt->pp.sps_id * 1360; + } else { + addr = 80 * 1360; + } + + hal_h265d_output_scalinglist_packet(hal, ptr_scaling + addr, dxva); + + hw_reg->h265d_addr.reg180_scanlist_addr = reg_ctx->bufs_fd; + hw_reg->common.reg012.scanlist_addr_valid_en = 1; + + /* need to config addr */ + mpp_dev_set_reg_offset(reg_ctx->cfg->dev, 180, addr + reg_ctx->sclst_offset); + } + + for (i = 0; i < 64; i++) + memcpy(pps_ptr + i * 112, reg_ctx->pps_buf, 112); +#ifdef dump + fwrite(pps_ptr, 1, 80 * 64, fp); + RK_U32 *tmp = (RK_U32 *)pps_ptr; + for (i = 0; i < 112 / 4; i++) { + mpp_log("pps[%3d] = 0x%08x\n", i, tmp[i]); + } +#endif + return 0; +} + +static void h265d_refine_rcb_size(VdpuRcbInfo *rcb_info, + Vdpu382H265dRegSet *hw_regs, + RK_S32 width, RK_S32 height, void *dxva) +{ + RK_U32 rcb_bits = 0; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + DXVA_PicParams_HEVC *pp = &dxva_cxt->pp; + RK_U32 chroma_fmt_idc = pp->chroma_format_idc;//0 400,1 420 ,2 422,3 444 + RK_U8 bit_depth = MPP_MAX(pp->bit_depth_luma_minus8, pp->bit_depth_chroma_minus8) + 8; + RK_U8 ctu_size = 1 << (pp->log2_diff_max_min_luma_coding_block_size + pp->log2_min_luma_coding_block_size_minus3 + 3); + RK_U32 tile_col_cut_num = pp->num_tile_columns_minus1; + RK_U32 ext_align_size = tile_col_cut_num * 64 * 8; + + width = MPP_ALIGN(width, ctu_size); + height = MPP_ALIGN(height, ctu_size); + + /* RCB_STRMD_ROW */ + if (width >= 8192) { + RK_U32 factor = 64 / ctu_size; + + rcb_bits = (MPP_ALIGN(width, ctu_size) + factor - 1) / factor * 24 + ext_align_size; + } else + rcb_bits = 0; + rcb_info[RCB_STRMD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_ROW */ + if (width >= 8192) + rcb_bits = (MPP_ALIGN(width - 8192, 4) << 1) + ext_align_size; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_COL */ + if (height >= 8192 && tile_col_cut_num) + rcb_bits = (tile_col_cut_num != 0) ? (MPP_ALIGN(height - 8192, 4) << 1) : 0; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_COL].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_ROW */ + rcb_bits = width * 22 + ext_align_size; + rcb_info[RCB_INTER_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_COL */ + rcb_bits = (tile_col_cut_num != 0) ? (height * 22) : 0; + rcb_info[RCB_INTER_COL].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTRA_ROW */ + rcb_bits = width * (((chroma_fmt_idc != 0) ? 1 : 0) + 1) * 11 + ext_align_size; + rcb_info[RCB_INTRA_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_DBLK_ROW */ + if (chroma_fmt_idc == 1 || chroma_fmt_idc == 2) { + if (ctu_size == 32) + rcb_bits = width * ( 4 + 6 * bit_depth); + else + rcb_bits = width * ( 2 + 6 * bit_depth); + } else { + if (ctu_size == 32) + rcb_bits = width * ( 4 + 8 * bit_depth); + else + rcb_bits = width * ( 2 + 8 * bit_depth); + } + rcb_bits += (tile_col_cut_num * (bit_depth == 8 ? 256 : 192)) + ext_align_size; + rcb_info[RCB_DBLK_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_SAO_ROW */ + if (chroma_fmt_idc == 1 || chroma_fmt_idc == 2) { + rcb_bits = width * (128 / ctu_size + 2 * bit_depth); + } else { + rcb_bits = width * (128 / ctu_size + 3 * bit_depth); + } + rcb_bits += (tile_col_cut_num * (bit_depth == 8 ? 160 : 128)) + ext_align_size; + rcb_info[RCB_SAO_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FBC_ROW */ + if (hw_regs->common.reg012.fbc_e) { + rcb_bits = width * (chroma_fmt_idc - 1) * 2 * bit_depth; + rcb_bits += (tile_col_cut_num * (bit_depth == 8 ? 128 : 64)) + ext_align_size; + } else + rcb_bits = 0; + rcb_info[RCB_FBC_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FILT_COL */ + if (tile_col_cut_num) { + if (hw_regs->common.reg012.fbc_e) { + RK_U32 ctu_idx = ctu_size >> 5; + RK_U32 a = filterd_fbc_on[ctu_idx][chroma_fmt_idc].a; + RK_U32 b = filterd_fbc_on[ctu_idx][chroma_fmt_idc].b; + + rcb_bits = height * (a * bit_depth + b); + } else { + RK_U32 ctu_idx = ctu_size >> 5; + RK_U32 a = filterd_fbc_off[ctu_idx][chroma_fmt_idc].a; + RK_U32 b = filterd_fbc_off[ctu_idx][chroma_fmt_idc].b; + + rcb_bits = height * (a * bit_depth + b); + } + } else + rcb_bits = 0; + rcb_info[RCB_FILT_COL].size = MPP_RCB_BYTES(rcb_bits); +} + +static void hal_h265d_rcb_info_update(void *hal, void *dxva, + Vdpu382H265dRegSet *hw_regs, + RK_S32 width, RK_S32 height) +{ + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t*)dxva; + DXVA_PicParams_HEVC *pp = &dxva_cxt->pp; + RK_U32 chroma_fmt_idc = pp->chroma_format_idc;//0 400,1 4202 ,422,3 444 + RK_U8 bit_depth = MPP_MAX(pp->bit_depth_luma_minus8, pp->bit_depth_chroma_minus8) + 8; + RK_U8 ctu_size = 1 << (pp->log2_diff_max_min_luma_coding_block_size + pp->log2_min_luma_coding_block_size_minus3 + 3); + RK_U32 num_tiles = pp->num_tile_rows_minus1 + 1; + + if (reg_ctx->num_row_tiles != num_tiles || + reg_ctx->bit_depth != bit_depth || + reg_ctx->chroma_fmt_idc != chroma_fmt_idc || + reg_ctx->ctu_size != ctu_size || + reg_ctx->width != width || + reg_ctx->height != height) { + RK_U32 i = 0; + RK_U32 loop = (reg_ctx->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->g_buf) : 1; + + reg_ctx->rcb_buf_size = vdpu382_get_rcb_buf_size((VdpuRcbInfo*)reg_ctx->rcb_info, width, height); + h265d_refine_rcb_size((VdpuRcbInfo*)reg_ctx->rcb_info, hw_regs, width, height, dxva_cxt); + + for (i = 0; i < loop; i++) { + MppBuffer rcb_buf; + + if (reg_ctx->rcb_buf[i]) { + mpp_buffer_put(reg_ctx->rcb_buf[i]); + reg_ctx->rcb_buf[i] = NULL; + } + mpp_buffer_get(reg_ctx->cfg->buf_group, &rcb_buf, reg_ctx->rcb_buf_size); + reg_ctx->rcb_buf[i] = rcb_buf; + } + + reg_ctx->num_row_tiles = num_tiles; + reg_ctx->bit_depth = bit_depth; + reg_ctx->chroma_fmt_idc = chroma_fmt_idc; + reg_ctx->ctu_size = ctu_size; + reg_ctx->width = width; + reg_ctx->height = height; + } +} + +#define SET_POC_HIGNBIT_INFO(regs, index, field, value)\ + do{ \ + switch(index){\ + case 0: regs.reg200.ref0_##field = value; break;\ + case 1: regs.reg200.ref1_##field = value; break;\ + case 2: regs.reg200.ref2_##field = value; break;\ + case 3: regs.reg200.ref3_##field = value; break;\ + case 4: regs.reg200.ref4_##field = value; break;\ + case 5: regs.reg200.ref5_##field = value; break;\ + case 6: regs.reg200.ref6_##field = value; break;\ + case 7: regs.reg200.ref7_##field = value; break;\ + case 8: regs.reg201.ref8_##field = value; break;\ + case 9: regs.reg201.ref9_##field = value; break;\ + case 10: regs.reg201.ref10_##field = value; break;\ + case 11: regs.reg201.ref11_##field = value; break;\ + case 12: regs.reg201.ref12_##field = value; break;\ + case 13: regs.reg201.ref13_##field = value; break;\ + case 14: regs.reg201.ref14_##field = value; break;\ + case 15: regs.reg201.ref15_##field = value; break;\ + default: break;}\ + }while(0) + +#define pocdistance(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) + +static MPP_RET hal_h265d_vdpu382_setup_colmv_buf(void *hal, HalTaskInfo *syn) +{ + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + h265d_dxva2_picture_context_t *dxva_cxt = (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + DXVA_PicParams_HEVC *pp = &dxva_cxt->pp; + RK_U8 ctu_size = 1 << (pp->log2_diff_max_min_luma_coding_block_size + + pp->log2_min_luma_coding_block_size_minus3 + 3); + RK_U32 log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + + RK_U32 width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + RK_U32 height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + RK_U32 mv_size = 0, colmv_size = 16, colmv_byte = 16; + RK_U32 compress = reg_ctx->cfg->hw_info ? reg_ctx->cfg->hw_info->cap_colmv_compress : 1; + + + mv_size = vdpu382_get_colmv_size(width, height, ctu_size, colmv_byte, colmv_size, compress); + + if (reg_ctx->cmv_bufs == NULL || reg_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(®_ctx->cmv_bufs); + if (reg_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_ERR_NOMEM;; + } + + reg_ctx->mv_size = mv_size; + reg_ctx->mv_count = mpp_buf_slot_get_count(reg_ctx->cfg->frame_slots); + hal_bufs_setup(reg_ctx->cmv_bufs, reg_ctx->mv_count, 1, &size); + } + + return MPP_OK; +} + +static MPP_RET hal_h265d_vdpu382_gen_regs(void *hal, HalTaskInfo *syn) +{ + RK_S32 i = 0; + RK_S32 log2_min_cb_size; + RK_S32 width, height; + RK_S32 stride_y, stride_uv, virstrid_y; + Vdpu382H265dRegSet *hw_regs; + RK_S32 ret = MPP_SUCCESS; + MppBuffer streambuf = NULL; + RK_S32 aglin_offset = 0; + RK_S32 valid_ref = -1; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_S32 fd = -1; + RK_S32 distance = INT_MAX; + h265d_dxva2_picture_context_t *dxva_cxt = + (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + HalH265dCtx *reg_ctx = ( HalH265dCtx *)hal; + void *rps_ptr = NULL; + RK_U32 stream_buf_size = 0; + MppHalCfg *cfg = reg_ctx->cfg; + + if (syn->dec.flags.parse_err || + (syn->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx ->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!reg_ctx->g_buf[i].use_flag) { + syn->dec.reg_index = i; + + reg_ctx->spspps_offset = reg_ctx->offset_spspps[i]; + reg_ctx->rps_offset = reg_ctx->offset_rps[i]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[i]; + + reg_ctx->hw_regs = reg_ctx->g_buf[i].hw_regs; + reg_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("hevc rps buf all used"); + return MPP_ERR_NOMEM; + } + } else { + syn->dec.reg_index = 0; + } + rps_ptr = mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->rps_offset; + if (NULL == rps_ptr) { + + mpp_err("rps_data get ptr error"); + return MPP_ERR_NOMEM; + } + + + if (syn->dec.syntax.data == NULL) { + mpp_err("%s:%s:%d dxva is NULL", __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + + /* output pps */ + hw_regs = (Vdpu382H265dRegSet*)reg_ctx->hw_regs; + memset(hw_regs, 0, sizeof(Vdpu382H265dRegSet)); + + if (NULL == reg_ctx->hw_regs) { + return MPP_ERR_NULL_PTR; + } + + + log2_min_cb_size = dxva_cxt->pp.log2_min_luma_coding_block_size_minus3 + 3; + + width = (dxva_cxt->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_cxt->pp.PicHeightInMinCbsY << log2_min_cb_size); + ret = hal_h265d_vdpu382_setup_colmv_buf(hal, syn); + if (ret) + return MPP_ERR_NOMEM; + + { + MppFrame mframe = NULL; + RK_U32 ver_virstride; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + stride_y = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + stride_uv = stride_y; + virstrid_y = ver_virstride * stride_y; + hw_regs->common.reg013.h26x_error_mode = 1; + hw_regs->common.reg021.error_deb_en = 1; + hw_regs->common.reg021.inter_error_prc_mode = 0; + hw_regs->common.reg021.error_intra_mode = 1; + + hw_regs->common.reg017.slice_num = dxva_cxt->slice_count; + hw_regs->h265d_param.reg64.h26x_rps_mode = 0; + hw_regs->h265d_param.reg64.h26x_frame_orslice = 0; + hw_regs->h265d_param.reg64.h26x_stream_mode = 0; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (ver_virstride + 64) / 16, SZ_4K); + + hw_regs->common.reg012.fbc_e = 1; + hw_regs->common.reg018.y_hor_virstride = fbc_hdr_stride >> 4; + hw_regs->common.reg019.uv_hor_virstride = fbc_hdr_stride >> 4; + hw_regs->common.reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + hw_regs->common.reg012.fbc_e = 0; + hw_regs->common.reg018.y_hor_virstride = stride_y >> 4; + hw_regs->common.reg019.uv_hor_virstride = stride_uv >> 4; + hw_regs->common.reg020_y_virstride.y_virstride = virstrid_y >> 4; + } + } + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &framebuf); + hw_regs->common_addr.reg130_decout_base = mpp_buffer_get_fd(framebuf); //just index need map + /*if out_base is equal to zero it means this frame may error + we return directly add by csy*/ + + if (hw_regs->common_addr.reg130_decout_base == 0) { + return 0; + } + fd = mpp_buffer_get_fd(framebuf); + hw_regs->common_addr.reg130_decout_base = fd; + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_cxt->pp.CurrPic.Index7Bits); + hw_regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + + hw_regs->h265d_param.reg65.cur_top_poc = dxva_cxt->pp.CurrPicOrderCntVal; + + mpp_buf_slot_get_prop(cfg->packet_slots, syn->dec.input, SLOT_BUFFER, + &streambuf); + if ( dxva_cxt->bitstream == NULL) { + dxva_cxt->bitstream = mpp_buffer_get_ptr(streambuf); + } +#ifdef HW_RPS + hw_regs->h265d_param.reg103.ref_pic_layer_same_with_cur = 0xffff; + hal_h265d_slice_hw_rps(syn->dec.syntax.data, rps_ptr, reg_ctx->sw_rps_buf, reg_ctx->fast_mode); +#else + hw_regs->sw_sysctrl.sw_h26x_rps_mode = 1; + hal_h265d_slice_output_rps(syn->dec.syntax.data, rps_ptr); +#endif + + /* cabac table */ + hw_regs->h265d_addr.reg197_cabactbl_base = reg_ctx->bufs_fd; + /* pps */ + hw_regs->h265d_addr.reg161_pps_base = reg_ctx->bufs_fd; + hw_regs->h265d_addr.reg163_rps_base = reg_ctx->bufs_fd; + + hw_regs->common_addr.reg128_rlc_base = mpp_buffer_get_fd(streambuf); + hw_regs->common_addr.reg129_rlcwrite_base = mpp_buffer_get_fd(streambuf); + stream_buf_size = mpp_buffer_get_size(streambuf); + hw_regs->common.reg016_str_len = ((dxva_cxt->bitstream_size + 15) + & (~15)) + 64; + hw_regs->common.reg016_str_len = stream_buf_size > hw_regs->common.reg016_str_len ? + hw_regs->common.reg016_str_len : stream_buf_size; + + aglin_offset = hw_regs->common.reg016_str_len - dxva_cxt->bitstream_size; + if (aglin_offset > 0) { + memset((void *)(dxva_cxt->bitstream + dxva_cxt->bitstream_size), 0, + aglin_offset); + } + hw_regs->common.reg010.dec_e = 1; + hw_regs->common.reg012.colmv_compress_en = cfg->hw_info ? + cfg->hw_info->cap_colmv_compress : 0; + + hw_regs->common.reg024.cabac_err_en_lowbits = 0xffffdfff; + hw_regs->common.reg025.cabac_err_en_highbits = 0x3ffbf9ff; + + hw_regs->common.reg011.dec_clkgate_e = 1; + hw_regs->common.reg011.err_head_fill_e = 1; + hw_regs->common.reg011.err_colmv_fill_e = 1; + + hw_regs->common.reg026.inter_auto_gating_e = 1; + hw_regs->common.reg026.filterd_auto_gating_e = 1; + hw_regs->common.reg026.strmd_auto_gating_e = 1; + hw_regs->common.reg026.mcp_auto_gating_e = 1; + hw_regs->common.reg026.busifd_auto_gating_e = 1; + hw_regs->common.reg026.dec_ctrl_auto_gating_e = 1; + hw_regs->common.reg026.intra_auto_gating_e = 1; + hw_regs->common.reg026.mc_auto_gating_e = 1; + hw_regs->common.reg026.transd_auto_gating_e = 1; + hw_regs->common.reg026.sram_auto_gating_e = 1; + hw_regs->common.reg026.cru_auto_gating_e = 1; + hw_regs->common.reg026.reg_cfg_gating_en = 1; + hw_regs->common.reg032_timeout_threshold = 0x3ffff; + + valid_ref = hw_regs->common_addr.reg130_decout_base; + reg_ctx->error_index[syn->dec.reg_index] = dxva_cxt->pp.CurrPic.Index7Bits; + hw_regs->common_addr.reg132_error_ref_base = valid_ref; + + memset(&hw_regs->highpoc.reg205, 0, sizeof(RK_U32)); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_cxt->pp.RefPicList); i++) { + if (dxva_cxt->pp.RefPicList[i].bPicEntry != 0xff && + dxva_cxt->pp.RefPicList[i].bPicEntry != 0x7f) { + + MppFrame mframe = NULL; + hw_regs->h265d_param.reg67_82_ref_poc[i] = dxva_cxt->pp.PicOrderCntValList[i]; + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_cxt->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + if (framebuf != NULL) { + hw_regs->h265d_addr.reg164_179_ref_base[i] = mpp_buffer_get_fd(framebuf); + valid_ref = hw_regs->h265d_addr.reg164_179_ref_base[i]; + // mpp_log("cur poc %d, ref poc %d", dxva_cxt->pp.current_poc, dxva_cxt->pp.PicOrderCntValList[i]); + if ((pocdistance(dxva_cxt->pp.PicOrderCntValList[i], dxva_cxt->pp.current_poc) < distance) + && (!mpp_frame_get_errinfo(mframe))) { + distance = pocdistance(dxva_cxt->pp.PicOrderCntValList[i], dxva_cxt->pp.current_poc); + hw_regs->common_addr.reg132_error_ref_base = hw_regs->h265d_addr.reg164_179_ref_base[i]; + reg_ctx->error_index[syn->dec.reg_index] = dxva_cxt->pp.RefPicList[i].Index7Bits; + hw_regs->common.reg021.error_intra_mode = 0; + + } + } else { + hw_regs->h265d_addr.reg164_179_ref_base[i] = valid_ref; + } + + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_cxt->pp.RefPicList[i].Index7Bits); + hw_regs->h265d_addr.reg181_196_colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + + SET_REF_VALID(hw_regs->h265d_param, i, 1); + } + } + + if ((reg_ctx->error_index[syn->dec.reg_index] == dxva_cxt->pp.CurrPic.Index7Bits) && + !dxva_cxt->pp.IntraPicFlag && !cfg->cfg->base.disable_error) { + h265h_dbg(H265H_DBG_TASK_ERR, "current frm may be err, should skip process"); + syn->dec.flags.ref_err = 1; + return MPP_OK; + } + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_cxt->pp.RefPicList); i++) { + + if (dxva_cxt->pp.RefPicList[i].bPicEntry != 0xff && + dxva_cxt->pp.RefPicList[i].bPicEntry != 0x7f) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_cxt->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + + if (framebuf == NULL || mpp_frame_get_errinfo(mframe)) { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->h265d_addr.reg164_179_ref_base[i] = hw_regs->common_addr.reg132_error_ref_base; + hw_regs->h265d_addr.reg181_196_colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } else { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->h265d_addr.reg164_179_ref_base[i] = hw_regs->common_addr.reg132_error_ref_base; + hw_regs->h265d_addr.reg181_196_colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + /* mark 3 to differ from current frame */ + if (reg_ctx->error_index[syn->dec.reg_index] == dxva_cxt->pp.CurrPic.Index7Bits) + SET_POC_HIGNBIT_INFO(hw_regs->highpoc, i, poc_highbit, 3); + } + } + hal_h265d_v382_output_pps_packet(hal, syn->dec.syntax.data); + + mpp_dev_set_reg_offset(cfg->dev, 161, reg_ctx->spspps_offset); + /* rps */ + mpp_dev_set_reg_offset(cfg->dev, 163, reg_ctx->rps_offset); + + hw_regs->common.reg013.cur_pic_is_idr = dxva_cxt->pp.IdrPicFlag;//p_hal->slice_long->idr_flag; + + hw_regs->common.reg011.buf_empty_en = 1; + + hal_h265d_rcb_info_update(hal, dxva_cxt, hw_regs, width, height); + vdpu382_setup_rcb(&hw_regs->common_addr, cfg->dev, (reg_ctx->fast_mode != 0) ? + reg_ctx->rcb_buf[syn->dec.reg_index] : reg_ctx->rcb_buf[0], + (VdpuRcbInfo*)reg_ctx->rcb_info); + { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_cxt->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + + if (mpp_frame_get_thumbnail_en(mframe)) { + hw_regs->h265d_addr.reg198_scale_down_luma_base = + hw_regs->common_addr.reg130_decout_base; + hw_regs->h265d_addr.reg199_scale_down_chorme_base = + hw_regs->common_addr.reg130_decout_base; + vdpu382_setup_down_scale(mframe, cfg->dev, &hw_regs->common); + } else { + hw_regs->h265d_addr.reg198_scale_down_luma_base = 0; + hw_regs->h265d_addr.reg199_scale_down_chorme_base = 0; + hw_regs->common.reg012.scale_down_en = 0; + } + } + vdpu382_setup_statistic(&hw_regs->common, &hw_regs->statistic); + mpp_buffer_sync_end(reg_ctx->bufs); + + return ret; +} + +static MPP_RET hal_h265d_vdpu382_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U8* p = NULL; + Vdpu382H265dRegSet *hw_regs = NULL; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_S32 index = task->dec.reg_index; + + RK_U32 i; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !reg_ctx->cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx->fast_mode) { + p = (RK_U8*)reg_ctx->g_buf[index].hw_regs; + hw_regs = ( Vdpu382H265dRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + p = (RK_U8*)reg_ctx->hw_regs; + hw_regs = ( Vdpu382H265dRegSet *)reg_ctx->hw_regs; + } + + if (hw_regs == NULL) { + mpp_err("hal_h265d_start hw_regs is NULL"); + return MPP_ERR_NULL_PTR; + } + for (i = 0; i < 68; i++) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + //mpp_log("RK_HEVC_DEC: regs[%02d]=%08X\n", i, *((RK_U32*)p)); + p += 4; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = reg_ctx->cfg->dev; + + wr_cfg.reg = &hw_regs->common; + wr_cfg.size = sizeof(hw_regs->common); + wr_cfg.offset = VDPU382_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->h265d_param; + wr_cfg.size = sizeof(hw_regs->h265d_param); + wr_cfg.offset = VDPU382_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->common_addr; + wr_cfg.size = sizeof(hw_regs->common_addr); + wr_cfg.offset = VDPU382_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->h265d_addr; + wr_cfg.size = sizeof(hw_regs->h265d_addr); + wr_cfg.offset = VDPU382_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->statistic; + wr_cfg.size = sizeof(hw_regs->statistic); + wr_cfg.offset = VDPU382_OFF_STATISTIC_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->highpoc; + wr_cfg.size = sizeof(hw_regs->highpoc); + wr_cfg.offset = VDPU382_OFF_POC_HIGHBIT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->irq_status; + rd_cfg.size = sizeof(hw_regs->irq_status); + rd_cfg.offset = VDPU382_OFF_INTERRUPT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + /* rcb info for sram */ + vdpu382_set_rcbinfo(dev, (VdpuRcbInfo*)reg_ctx->rcb_info); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + + +static MPP_RET hal_h265d_vdpu382_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_S32 index = task->dec.reg_index; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + RK_U8* p = NULL; + Vdpu382H265dRegSet *hw_regs = NULL; + RK_S32 i; + + if (reg_ctx->fast_mode) { + hw_regs = ( Vdpu382H265dRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( Vdpu382H265dRegSet *)reg_ctx->hw_regs; + } + + p = (RK_U8*)hw_regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + goto ERR_PROC; + } + + ret = mpp_dev_ioctl(cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +ERR_PROC: + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + hw_regs->irq_status.reg224.dec_error_sta || + hw_regs->irq_status.reg224.buf_empty_sta || + hw_regs->irq_status.reg224.dec_bus_sta || + !hw_regs->irq_status.reg224.dec_rdy_sta) { + if (!reg_ctx->fast_mode) { + if (cfg->dec_cb) + mpp_callback(cfg->dec_cb, &task->dec); + } else { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + if (mframe) { + reg_ctx->fast_mode_err_found = 1; + mpp_frame_set_errinfo(mframe, 1); + } + } + } else { + if (reg_ctx->fast_mode && reg_ctx->fast_mode_err_found) { + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(task->dec.refer); i++) { + if (task->dec.refer[i] >= 0) { + MppFrame frame_ref = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.refer[i], + SLOT_FRAME_PTR, &frame_ref); + h265h_dbg(H265H_DBG_FAST_ERR, "refer[%d] %d frame %p\n", + i, task->dec.refer[i], frame_ref); + if (frame_ref && mpp_frame_get_errinfo(frame_ref)) { + MppFrame frame_out = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &frame_out); + mpp_frame_set_errinfo(frame_out, 1); + break; + } + } + } + } + } + + for (i = 0; i < 68; i++) { + if (i == 1) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + + if (i == 45) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + p += 4; + } + + if (reg_ctx->fast_mode) { + reg_ctx->g_buf[index].use_flag = 0; + } + + return ret; +} + +static MPP_RET hal_h265d_vdpu382_reset(void *hal) +{ + MPP_RET ret = MPP_OK; + HalH265dCtx *p_hal = (HalH265dCtx *)hal; + p_hal->fast_mode_err_found = 0; + (void)hal; + return ret; +} + +static MPP_RET hal_h265d_vdpu382_flush(void *hal) +{ + MPP_RET ret = MPP_OK; + + (void)hal; + return ret; +} + +static MPP_RET hal_h265d_vdpu382_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_OK; + HalH265dCtx *p_hal = (HalH265dCtx *)hal; + + (void)hal; + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrame frame = (MppFrame)param; + MppFrameFormat fmt = mpp_frame_get_fmt(frame); + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, frame, 16); + } + break; + } + case MPP_DEC_SET_OUTPUT_FORMAT: { + } break; + default: + break; + } + return ret; +} + +const MppHalApi hal_h265d_vdpu382 = { + .name = "h265d_vdpu382", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(HalH265dCtx), + .flag = 0, + .init = hal_h265d_vdpu382_init, + .deinit = hal_h265d_vdpu382_deinit, + .reg_gen = hal_h265d_vdpu382_gen_regs, + .start = hal_h265d_vdpu382_start, + .wait = hal_h265d_vdpu382_wait, + .reset = hal_h265d_vdpu382_reset, + .flush = hal_h265d_vdpu382_flush, + .control = hal_h265d_vdpu382_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3562, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h265d_vdpu382) diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu382.h b/mpp/hal/rkdec/h265d/hal_h265d_vdpu382.h new file mode 100644 index 000000000..a444cb754 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu382.h @@ -0,0 +1,32 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265D_VDPU382_H +#define HAL_H265D_VDPU382_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h265d_vdpu382; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_VDPU382_H */ diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu383.c b/mpp/hal/rkdec/h265d/hal_h265d_vdpu383.c new file mode 100644 index 000000000..dcac075d1 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu383.c @@ -0,0 +1,843 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h265d_vdpu383" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bitput.h" +#include "mpp_buffer_impl.h" + +#include "h265d_syntax.h" +#include "hal_h265d_debug.h" +#include "hal_h265d_ctx.h" +#include "hal_h265d_com.h" +#include "hal_h265d_vdpu383.h" +#include "vdpu38x_com.h" +#include "vdpu383_com.h" +#include "vdpu_com.h" +#include "vdpu38x_com.h" + +#define PPS_SIZE (112 * 64)//(96x64) + +#define CABAC_TAB_ALIGEND_SIZE (MPP_ALIGN(27456, SZ_4K)) +#define SPSPPS_ALIGNED_SIZE (MPP_ALIGN(176, SZ_4K)) +#define RPS_ALIGEND_SIZE (MPP_ALIGN(400 * 8, SZ_4K)) +#define SCALIST_ALIGNED_SIZE (MPP_ALIGN(81 * 1360, SZ_4K)) +#define INFO_BUFFER_SIZE (SPSPPS_ALIGNED_SIZE + RPS_ALIGEND_SIZE + SCALIST_ALIGNED_SIZE) +#define ALL_BUFFER_SIZE(cnt) (CABAC_TAB_ALIGEND_SIZE + INFO_BUFFER_SIZE *cnt) + +#define CABAC_TAB_OFFSET (0) +#define SPSPPS_OFFSET(pos) (CABAC_TAB_OFFSET + CABAC_TAB_ALIGEND_SIZE + (INFO_BUFFER_SIZE * pos)) +#define RPS_OFFSET(pos) (SPSPPS_OFFSET(pos) + SPSPPS_ALIGNED_SIZE) +#define SCALIST_OFFSET(pos) (RPS_OFFSET(pos) + RPS_ALIGEND_SIZE) + +#define pocdistance(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) + +static MPP_RET hal_h265d_vdpu383_init(void *hal, MppHalCfg *cfg) +{ + RK_S32 ret = 0; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + + mpp_env_get_u32("hal_h265d_debug", &hal_h265d_debug, 0); + + reg_ctx->cfg = cfg; + cfg->support_fast_mode = 1; + reg_ctx->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + + reg_ctx->scaling_qm = mpp_calloc(DXVA_Qmatrix_HEVC, 1); + if (reg_ctx->scaling_qm == NULL) { + mpp_err("scaling_org alloc fail"); + return MPP_ERR_MALLOC; + } + + reg_ctx->scaling_rk = mpp_calloc(scalingFactor_t, 1); + reg_ctx->pps_buf = mpp_calloc(RK_U64, 24); + reg_ctx->pps_buf_sz = 22 * sizeof(RK_U64); // 22 * 64 bits + reg_ctx->sw_rps_buf = mpp_calloc(RK_U64, 400); + + if (reg_ctx->scaling_rk == NULL) { + mpp_err("scaling_rk alloc fail"); + return MPP_ERR_MALLOC; + } + + { + RK_U32 i = 0; + RK_U32 max_cnt = (reg_ctx->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + + //!< malloc buffers + ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, ALL_BUFFER_SIZE(max_cnt)); + if (ret) { + mpp_err("h265d mpp_buffer_get failed\n"); + return ret; + } + + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + reg_ctx->offset_cabac = CABAC_TAB_OFFSET; + for (i = 0; i < max_cnt; i++) { + reg_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu383RegSet)); + reg_ctx->offset_spspps[i] = SPSPPS_OFFSET(i); + reg_ctx->offset_rps[i] = RPS_OFFSET(i); + reg_ctx->offset_sclst[i] = SCALIST_OFFSET(i); + } + + mpp_buffer_attach_dev(reg_ctx->bufs, cfg->dev); + } + + if (!reg_ctx->fast_mode) { + reg_ctx->hw_regs = reg_ctx->g_buf[0].hw_regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->rps_offset = reg_ctx->offset_rps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + ret = mpp_buffer_write(reg_ctx->bufs, 0, (void*)cabac_table, sizeof(cabac_table)); + if (ret) { + mpp_err("h265d write cabac_table data failed\n"); + return ret; + } + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + + return MPP_OK; +} + +static RK_S32 hal_h265d_vdpu383_rps(void *dxva, void *rps_buf, void* sw_rps_buf, RK_U32 fast_mode) +{ + BitputCtx_t bp; + RK_S32 fifo_len = 400; + RK_S32 i = 0, j = 0; + h265d_dxva2_picture_context_t *dxva_ctx = (h265d_dxva2_picture_context_t*)dxva; + + if (!dxva_ctx->pp.rps_update_flag) { + if (fast_mode) { + memcpy(rps_buf, sw_rps_buf, fifo_len * sizeof(RK_U64)); + } + return 0; + } + + mpp_set_bitput_ctx(&bp, (RK_U64*)sw_rps_buf, fifo_len); + + for (i = 0; i < 32; i ++) { + mpp_put_bits(&bp, dxva_ctx->pp.sps_lt_rps[i].lt_ref_pic_poc_lsb, 16); + mpp_put_bits(&bp, dxva_ctx->pp.sps_lt_rps[i].used_by_curr_pic_lt_flag, 1); + mpp_put_bits(&bp, 0, 15); + } + + for (i = 0; i < 64; i++) { + if (i < dxva_ctx->pp.num_short_term_ref_pic_sets) { + + mpp_put_bits(&bp, dxva_ctx->pp.sps_st_rps[i].num_negative_pics, 4); + mpp_put_bits(&bp, dxva_ctx->pp.sps_st_rps[i].num_positive_pics, 4); + for ( j = 0; j < dxva_ctx->pp.sps_st_rps[i].num_negative_pics; j++) { + + mpp_put_bits(&bp, dxva_ctx->pp.sps_st_rps[i].delta_poc_s0[j], 16); + mpp_put_bits(&bp, dxva_ctx->pp.sps_st_rps[i].s0_used_flag[j], 1); + } + + for (j = 0; j < dxva_ctx->pp.sps_st_rps[i].num_positive_pics; j++) { + mpp_put_bits(&bp, dxva_ctx->pp.sps_st_rps[i].delta_poc_s1[j], 16); + mpp_put_bits(&bp, dxva_ctx->pp.sps_st_rps[i].s1_used_flag[j], 1); + + } + + for ( j = dxva_ctx->pp.sps_st_rps[i].num_negative_pics + dxva_ctx->pp.sps_st_rps[i].num_positive_pics; j < 15; j++) { + mpp_put_bits(&bp, 0, 16); + mpp_put_bits(&bp, 0, 1); + } + + } else { + mpp_put_bits(&bp, 0, 4); + mpp_put_bits(&bp, 0, 4); + for ( j = 0; j < 15; j++) { + mpp_put_bits(&bp, 0, 16); + mpp_put_bits(&bp, 0, 1); + } + } + mpp_put_align(&bp, 64, 0); + mpp_put_bits(&bp, 0, 128); + } + +#ifdef DUMP_VDPU383_DATAS + { + char *cur_fname = "rps_128bit.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)bp.pbuf, 64 * bp.index + bp.bitpos, 128, 0); + } +#endif + + RK_U32 *tmp = (RK_U32 *)sw_rps_buf; + memcpy(rps_buf, sw_rps_buf, fifo_len * sizeof(RK_U64)); + + if (hal_h265d_debug & H265H_DBG_RPS) { + for (i = 0; i < 400 * 8 / 4; i++) { + mpp_log("rps[%3d] = 0x%08x\n", i, tmp[i]); + } + } + return 0; +} + +static MPP_RET vdpu383_h265d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + RK_U32 fltd_row_append = ctx->pic_w > 4096 ? 256 * 16 * 8 : 864 * 16 * 8; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, in_tl_row) * 174; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, on_tl_row) * 174; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.6 * bit_depth + 0.5 ) + * (7.5 + 5 * cur_uv_para); + cur_bit_size = cur_bit_size / 2 + fltd_row_append; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + // save space mode : half for RCB_FLTD_IN_ROW, half for RCB_FLTD_PROT_IN_ROW + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.6 * bit_depth + 0.5) + * (7.5 + 5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_col_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.6 * bit_depth + 0.5) + * (16.5 + 5.5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +static MPP_RET hal_h265d_vdpu383_gen_regs(void *hal, HalTaskInfo *syn) +{ + RK_S32 i = 0; + RK_S32 log2_min_cb_size; + RK_S32 width, height; + RK_S32 stride_y, stride_uv, virstrid_y; + Vdpu383RegSet *hw_regs; + RK_S32 ret = MPP_SUCCESS; + MppBuffer streambuf = NULL; + RK_S32 aglin_offset = 0; + RK_S32 valid_ref = -1; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_S32 fd = -1; + RK_U32 mv_size = 0; + RK_S32 distance = INT_MAX; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + + if (syn->dec.flags.parse_err || + (syn->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + h265d_dxva2_picture_context_t *dxva_ctx = (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + HalBuf *origin_buf = NULL; + + void *rps_ptr = NULL; + if (reg_ctx ->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!reg_ctx->g_buf[i].use_flag) { + syn->dec.reg_index = i; + + reg_ctx->spspps_offset = reg_ctx->offset_spspps[i]; + reg_ctx->rps_offset = reg_ctx->offset_rps[i]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[i]; + + reg_ctx->hw_regs = reg_ctx->g_buf[i].hw_regs; + reg_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("hevc rps buf all used"); + return MPP_ERR_NOMEM; + } + } + rps_ptr = mpp_buffer_get_ptr(reg_ctx->bufs) + reg_ctx->rps_offset; + if (NULL == rps_ptr) { + + mpp_err("rps_data get ptr error"); + return MPP_ERR_NOMEM; + } + + + if (syn->dec.syntax.data == NULL) { + mpp_err("%s:%s:%d dxva is NULL", __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + +#ifdef DUMP_VDPU383_DATAS + { + memset(dump_cur_dir, 0, sizeof(dump_cur_dir)); + sprintf(dump_cur_dir, "hevc/Frame%04d", dump_cur_frame); + if (access(dump_cur_dir, 0)) { + if (mkdir(dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", dump_cur_dir); + } + dump_cur_frame++; + } +#endif + + /* output pps */ + hw_regs = (Vdpu383RegSet*)reg_ctx->hw_regs; + memset(hw_regs, 0, sizeof(Vdpu383RegSet)); + + if (NULL == reg_ctx->hw_regs) { + return MPP_ERR_NULL_PTR; + } + + + log2_min_cb_size = dxva_ctx->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_ctx->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_ctx->pp.PicHeightInMinCbsY << log2_min_cb_size); + mv_size = hal_h265d_avs2d_calc_mv_size(width, height, 1 << log2_min_cb_size) * 2; + + if (reg_ctx->cmv_bufs == NULL || reg_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(®_ctx->cmv_bufs); + if (reg_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_ERR_NULL_PTR; + } + + reg_ctx->mv_size = mv_size; + reg_ctx->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(reg_ctx->cmv_bufs, reg_ctx->mv_count, 1, &size); + } + + { + MppFrame mframe = NULL; + RK_U32 ver_virstride; + RK_U32 virstrid_uv; + MppFrameFormat fmt; + RK_U32 chroma_fmt_idc = dxva_ctx->pp.chroma_format_idc; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + /* for 8K downscale mode*/ + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + reg_ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, ®_ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + fmt = mpp_frame_get_fmt(mframe); + + stride_y = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + stride_uv = stride_y; + virstrid_y = ver_virstride * stride_y; + if (chroma_fmt_idc == 3) + stride_uv *= 2; + if (chroma_fmt_idc == 3 || chroma_fmt_idc == 2) { + virstrid_uv = stride_uv * ver_virstride; + } else { + virstrid_uv = stride_uv * ver_virstride / 2; + } + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset; + + hw_regs->ctrl_regs.reg9.fbc_e = 1; + hw_regs->comm_paras.reg68_hor_virstride = fbc_hdr_stride / 64; + fbd_offset = fbc_hdr_stride * MPP_ALIGN(ver_virstride, 64) / 16; + hw_regs->comm_addrs.reg193_fbc_payload_offset = fbd_offset; + } else if (MPP_FRAME_FMT_IS_TILE(fmt)) { + hw_regs->ctrl_regs.reg9.tile_e = 1; + if (chroma_fmt_idc == 0) { //yuv400 + hw_regs->comm_paras.reg68_hor_virstride = stride_y * 4 / 16; + } else if (chroma_fmt_idc == 2) { //yuv422 + hw_regs->comm_paras.reg68_hor_virstride = stride_y * 8 / 16; + } else if (chroma_fmt_idc == 3) { //yuv444 + hw_regs->comm_paras.reg68_hor_virstride = stride_y * 12 / 16; + } else { //yuv420 + hw_regs->comm_paras.reg68_hor_virstride = stride_y * 6 / 16; + } + hw_regs->comm_paras.reg70_y_virstride = (virstrid_y + virstrid_uv) / 16; + } else { + hw_regs->ctrl_regs.reg9.fbc_e = 0; + hw_regs->comm_paras.reg68_hor_virstride = stride_y >> 4; + hw_regs->comm_paras.reg69_raster_uv_hor_virstride = stride_uv >> 4; + hw_regs->comm_paras.reg70_y_virstride = virstrid_y >> 4; + } + hw_regs->comm_paras.reg80_error_ref_hor_virstride = hw_regs->comm_paras.reg68_hor_virstride; + hw_regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = hw_regs->comm_paras.reg69_raster_uv_hor_virstride; + hw_regs->comm_paras.reg82_error_ref_virstride = hw_regs->comm_paras.reg70_y_virstride; + } + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &framebuf); + + if (reg_ctx->origin_bufs) { + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, + dxva_ctx->pp.CurrPic.Index7Bits); + framebuf = origin_buf->buf[0]; + } + + hw_regs->comm_addrs.reg168_decout_base = mpp_buffer_get_fd(framebuf); //just index need map + hw_regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(framebuf); + /*if out_base is equal to zero it means this frame may error + we return directly add by csy*/ + + if (hw_regs->comm_addrs.reg168_decout_base == 0) { + return 0; + } + + fd = mpp_buffer_get_fd(framebuf); + hw_regs->comm_addrs.reg168_decout_base = fd; + hw_regs->comm_addrs.reg192_payload_st_cur_base = fd; + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_ctx->pp.CurrPic.Index7Bits); + + hw_regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); +#ifdef DUMP_VDPU383_DATAS + { + char *cur_fname = "colmv_cur_frame.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mv_buf->buf[0]), + mpp_buffer_get_size(mv_buf->buf[0]), 64, 0); + } +#endif + + mpp_buf_slot_get_prop(cfg->packet_slots, syn->dec.input, SLOT_BUFFER, + &streambuf); + if ( dxva_ctx->bitstream == NULL) { + dxva_ctx->bitstream = mpp_buffer_get_ptr(streambuf); + } + +#ifdef DUMP_VDPU383_DATAS + { + char *cur_fname = "stream_in_128bit.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(streambuf), + mpp_buffer_get_size(streambuf), 128, 0); + } +#endif + + hal_h265d_vdpu383_rps(syn->dec.syntax.data, rps_ptr, reg_ctx->sw_rps_buf, reg_ctx->fast_mode); + + hw_regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(streambuf); + hw_regs->comm_paras.reg66_stream_len = ((dxva_ctx->bitstream_size + 15) & (~15)) + 64; + aglin_offset = hw_regs->comm_paras.reg66_stream_len - dxva_ctx->bitstream_size; + if (aglin_offset > 0) + memset((void *)(dxva_ctx->bitstream + dxva_ctx->bitstream_size), 0, aglin_offset); + + vdpu383_init_ctrl_regs(hw_regs, MPP_VIDEO_CodingHEVC); + + valid_ref = hw_regs->comm_addrs.reg168_decout_base; + reg_ctx->error_index[syn->dec.reg_index] = dxva_ctx->pp.CurrPic.Index7Bits; + + hw_regs->comm_addrs.reg169_error_ref_base = valid_ref; + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_ctx->pp.RefPicList); i++) { + if (dxva_ctx->pp.RefPicList[i].bPicEntry != 0xff && + dxva_ctx->pp.RefPicList[i].bPicEntry != 0x7f) { + + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, + dxva_ctx->pp.RefPicList[i].Index7Bits); + framebuf = origin_buf->buf[0]; + } + if (framebuf != NULL) { + hw_regs->comm_addrs.reg170_185_ref_base[i] = mpp_buffer_get_fd(framebuf); + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = mpp_buffer_get_fd(framebuf); + valid_ref = hw_regs->comm_addrs.reg170_185_ref_base[i]; + if ((pocdistance(dxva_ctx->pp.PicOrderCntValList[i], dxva_ctx->pp.current_poc) < distance) + && (!mpp_frame_get_errinfo(mframe))) { + + distance = pocdistance(dxva_ctx->pp.PicOrderCntValList[i], dxva_ctx->pp.current_poc); + hw_regs->comm_addrs.reg169_error_ref_base = hw_regs->comm_addrs.reg170_185_ref_base[i]; + reg_ctx->error_index[syn->dec.reg_index] = dxva_ctx->pp.RefPicList[i].Index7Bits; + hw_regs->ctrl_regs.reg16.error_proc_disable = 1; + } + } else { + hw_regs->comm_addrs.reg170_185_ref_base[i] = valid_ref; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = valid_ref; + } + + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_ctx->pp.RefPicList[i].Index7Bits); + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + if ((reg_ctx->error_index[syn->dec.reg_index] == dxva_ctx->pp.CurrPic.Index7Bits) && + !dxva_ctx->pp.IntraPicFlag && !cfg->cfg->base.disable_error) { + h265h_dbg(H265H_DBG_TASK_ERR, "current frm may be err, should skip process"); + syn->dec.flags.ref_err = 1; + return MPP_OK; + } + + /* pps */ + hw_regs->comm_addrs.reg131_gbl_base = reg_ctx->bufs_fd; + hw_regs->comm_paras.reg67_global_len = 0xc; //22 * 8; + mpp_dev_set_reg_offset(cfg->dev, 131, reg_ctx->spspps_offset); + + /* rps */ + hw_regs->comm_addrs.reg129_rps_base = reg_ctx->bufs_fd; + mpp_dev_set_reg_offset(cfg->dev, 129, reg_ctx->rps_offset); + + hal_h265d_vdpu38x_output_pps_packet(hal, syn->dec.syntax.data, + &hw_regs->comm_addrs.reg132_scanlist_addr); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_ctx->pp.RefPicList); i++) { + + if (dxva_ctx->pp.RefPicList[i].bPicEntry != 0xff && + dxva_ctx->pp.RefPicList[i].bPicEntry != 0x7f) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + + if (framebuf == NULL || mpp_frame_get_errinfo(mframe)) { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->comm_addrs.reg170_185_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } else { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->comm_addrs.reg170_185_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + vdpu38x_h265d_rcb_setup(hal, dxva_ctx, syn, width, height, + &hw_regs->comm_addrs.rcb_regs, vdpu383_h265d_rcb_calc); + vdpu383_setup_statistic(&hw_regs->ctrl_regs); + mpp_buffer_sync_end(reg_ctx->bufs); + + { + //scale down config + MppFrame mframe = NULL; + MppBuffer mbuffer = NULL; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + hw_regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, dxva_ctx->pp.CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + hw_regs->comm_addrs.reg168_decout_base = fd; + hw_regs->comm_addrs.reg192_payload_st_cur_base = fd; + hw_regs->comm_addrs.reg169_error_ref_base = fd; + vdpu383_setup_down_scale(mframe, cfg->dev, &hw_regs->ctrl_regs, (void*)&hw_regs->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + hw_regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + vdpu383_setup_down_scale(mframe, cfg->dev, &hw_regs->ctrl_regs, (void*)&hw_regs->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + hw_regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return ret; +} + +static MPP_RET hal_h265d_vdpu383_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U8* p = NULL; + Vdpu383RegSet *hw_regs = NULL; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_S32 index = task->dec.reg_index; + + RK_U32 i; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !reg_ctx->cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx->fast_mode) { + p = (RK_U8*)reg_ctx->g_buf[index].hw_regs; + hw_regs = ( Vdpu383RegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + p = (RK_U8*)reg_ctx->hw_regs; + hw_regs = ( Vdpu383RegSet *)reg_ctx->hw_regs; + } + + if (hw_regs == NULL) { + mpp_err("hal_h265d_start hw_regs is NULL"); + return MPP_ERR_NULL_PTR; + } + for (i = 0; i < 68; i++) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + //mpp_log("RK_HEVC_DEC: regs[%02d]=%08X\n", i, *((RK_U32*)p)); + p += 4; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = reg_ctx->cfg->dev; + + wr_cfg.reg = &hw_regs->ctrl_regs; + wr_cfg.size = sizeof(hw_regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_paras; + wr_cfg.size = sizeof(hw_regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_addrs; + wr_cfg.size = sizeof(hw_regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->ctrl_regs.reg15; + rd_cfg.size = sizeof(hw_regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + + +static MPP_RET hal_h265d_vdpu383_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_S32 index = task->dec.reg_index; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + RK_U8* p = NULL; + Vdpu383RegSet *hw_regs = NULL; + RK_S32 i; + + if (reg_ctx->fast_mode) { + hw_regs = ( Vdpu383RegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( Vdpu383RegSet *)reg_ctx->hw_regs; + } + + p = (RK_U8*)hw_regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + goto ERR_PROC; + } + + ret = mpp_dev_ioctl(cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +ERR_PROC: + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + (!hw_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + hw_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + hw_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) { + if (!reg_ctx->fast_mode) { + if (cfg->dec_cb) + mpp_callback(cfg->dec_cb, &task->dec); + } else { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + if (mframe) { + reg_ctx->fast_mode_err_found = 1; + mpp_frame_set_errinfo(mframe, 1); + } + } + } else { + if (reg_ctx->fast_mode && reg_ctx->fast_mode_err_found) { + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(task->dec.refer); i++) { + if (task->dec.refer[i] >= 0) { + MppFrame frame_ref = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.refer[i], + SLOT_FRAME_PTR, &frame_ref); + h265h_dbg(H265H_DBG_FAST_ERR, "refer[%d] %d frame %p\n", + i, task->dec.refer[i], frame_ref); + if (frame_ref && mpp_frame_get_errinfo(frame_ref)) { + MppFrame frame_out = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &frame_out); + mpp_frame_set_errinfo(frame_out, 1); + break; + } + } + } + } + } + + for (i = 0; i < 68; i++) { + if (i == 1) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + + if (i == 45) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + p += 4; + } + + if (reg_ctx->fast_mode) { + reg_ctx->g_buf[index].use_flag = 0; + } + + return ret; +} + +const MppHalApi hal_h265d_vdpu383 = { + .name = "h265d_vdpu383", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(HalH265dCtx), + .flag = 0, + .init = hal_h265d_vdpu383_init, + .deinit = hal_h265d_vdpu38x_deinit, + .reg_gen = hal_h265d_vdpu383_gen_regs, + .start = hal_h265d_vdpu383_start, + .wait = hal_h265d_vdpu383_wait, + .reset = hal_h265d_vdpu_reset, + .flush = hal_h265d_vdpu_flush, + .control = hal_h265d_vdpu38x_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h265d_vdpu383) diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu383.h b/mpp/hal/rkdec/h265d/hal_h265d_vdpu383.h new file mode 100644 index 000000000..a878ce1d8 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu383.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265D_VDPU383_H +#define HAL_H265D_VDPU383_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h265d_vdpu383; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_VDPU383_H */ diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu384a.c b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384a.c new file mode 100644 index 000000000..fad6d84e0 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384a.c @@ -0,0 +1,768 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h265d_vdpu384a" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_bitread.h" +#include "mpp_bitput.h" +#include "mpp_buffer_impl.h" + +#include "h265d_syntax.h" +#include "hal_h265d_debug.h" +#include "hal_h265d_ctx.h" +#include "hal_h265d_com.h" +#include "hal_h265d_vdpu384a.h" +#include "vdpu38x_com.h" +#include "vdpu384a_com.h" +#include "vdpu_com.h" +#include "vdpu38x_com.h" + +#define PPS_SIZE (112 * 64)//(96x64) + +#define SPSPPS_ALIGNED_SIZE (MPP_ALIGN(2181 + 64, 128) / 8) // byte, 2181 bit + Reserve 64 +#define SCALIST_ALIGNED_SIZE (MPP_ALIGN(81 * 1360, SZ_4K)) +#define INFO_BUFFER_SIZE (SPSPPS_ALIGNED_SIZE + SCALIST_ALIGNED_SIZE) +#define ALL_BUFFER_SIZE(cnt) (INFO_BUFFER_SIZE *cnt) + +#define SPSPPS_OFFSET(pos) (INFO_BUFFER_SIZE * pos) +#define SCALIST_OFFSET(pos) (SPSPPS_OFFSET(pos) + SPSPPS_ALIGNED_SIZE) + +#define pocdistance(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) + +static MPP_RET hal_h265d_vdpu384a_init(void *hal, MppHalCfg *cfg) +{ + RK_S32 ret = 0; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + + mpp_env_get_u32("hal_h265d_debug", &hal_h265d_debug, 0); + + reg_ctx->cfg = cfg; + cfg->support_fast_mode = 1; + reg_ctx->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + + reg_ctx->scaling_qm = mpp_calloc(DXVA_Qmatrix_HEVC, 1); + if (reg_ctx->scaling_qm == NULL) { + mpp_err("scaling_org alloc fail"); + return MPP_ERR_MALLOC; + } + + reg_ctx->scaling_rk = mpp_calloc(scalingFactor_t, 1); + reg_ctx->pps_buf = mpp_calloc(RK_U8, SPSPPS_ALIGNED_SIZE); + reg_ctx->pps_buf_sz = SPSPPS_ALIGNED_SIZE; + + if (reg_ctx->scaling_rk == NULL) { + mpp_err("scaling_rk alloc fail"); + return MPP_ERR_MALLOC; + } + + { + RK_U32 i = 0; + RK_U32 max_cnt = (reg_ctx->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + + //!< malloc buffers + ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, ALL_BUFFER_SIZE(max_cnt)); + if (ret) { + mpp_err("h265d mpp_buffer_get failed\n"); + return ret; + } + + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + for (i = 0; i < max_cnt; i++) { + reg_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu384aRegSet)); + reg_ctx->offset_spspps[i] = SPSPPS_OFFSET(i); + reg_ctx->offset_sclst[i] = SCALIST_OFFSET(i); + } + + mpp_buffer_attach_dev(reg_ctx->bufs, cfg->dev); + } + + if (!reg_ctx->fast_mode) { + reg_ctx->hw_regs = reg_ctx->g_buf[0].hw_regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + + return MPP_OK; +} + +static MPP_RET vdpu384a_h265d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, in_tl_row) * 174; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, on_tl_row) * 174; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.2 * bit_depth + 0.5 ) + * (7.5 + 5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.2 * bit_depth + 0.5) + * (7.5 + 5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_col_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.6 * bit_depth + 0.5) + * (16.5 + 5.5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +static MPP_RET hal_h265d_vdpu384a_gen_regs(void *hal, HalTaskInfo *syn) +{ + RK_S32 i = 0; + RK_S32 log2_min_cb_size; + RK_S32 width, height; + RK_S32 stride_y, stride_uv, virstrid_y; + Vdpu384aRegSet *hw_regs; + RK_S32 ret = MPP_SUCCESS; + MppBuffer streambuf = NULL; + RK_S32 aglin_offset = 0; + RK_S32 valid_ref = -1; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_S32 fd = -1; + RK_U32 mv_size = 0; + RK_S32 distance = INT_MAX; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + + if (syn->dec.flags.parse_err || + (syn->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + h265d_dxva2_picture_context_t *dxva_ctx = (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + HalBuf *origin_buf = NULL; + + if (reg_ctx ->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!reg_ctx->g_buf[i].use_flag) { + syn->dec.reg_index = i; + + reg_ctx->spspps_offset = reg_ctx->offset_spspps[i]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[i]; + + reg_ctx->hw_regs = reg_ctx->g_buf[i].hw_regs; + reg_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("hevc rps buf all used"); + return MPP_ERR_NOMEM; + } + } + + if (syn->dec.syntax.data == NULL) { + mpp_err("%s:%s:%d dxva is NULL", __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + +#ifdef DUMP_VDPU384A_DATAS + { + memset(dump_cur_dir, 0, sizeof(dump_cur_dir)); + sprintf(dump_cur_dir, "/data/hevc/Frame%04d", dump_cur_frame); + if (access(dump_cur_dir, 0)) { + if (mkdir(dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", dump_cur_dir); + } + dump_cur_frame++; + } +#endif + + /* output pps */ + hw_regs = (Vdpu384aRegSet*)reg_ctx->hw_regs; + memset(hw_regs, 0, sizeof(Vdpu384aRegSet)); + + if (NULL == reg_ctx->hw_regs) { + return MPP_ERR_NULL_PTR; + } + + + log2_min_cb_size = dxva_ctx->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_ctx->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_ctx->pp.PicHeightInMinCbsY << log2_min_cb_size); + mv_size = hal_h265d_avs2d_calc_mv_size(width, height, 1 << log2_min_cb_size) * 2; + + if (reg_ctx->cmv_bufs == NULL || reg_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(®_ctx->cmv_bufs); + if (reg_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_ERR_NULL_PTR; + } + + reg_ctx->mv_size = mv_size; + reg_ctx->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(reg_ctx->cmv_bufs, reg_ctx->mv_count, 1, &size); + } + + { + MppFrame mframe = NULL; + RK_U32 ver_virstride; + RK_U32 virstrid_uv; + MppFrameFormat fmt; + RK_U32 chroma_fmt_idc = dxva_ctx->pp.chroma_format_idc; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + /* for 8K downscale mode*/ + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + reg_ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, ®_ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + fmt = mpp_frame_get_fmt(mframe); + + stride_y = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + stride_uv = stride_y; + virstrid_y = ver_virstride * stride_y; + if (chroma_fmt_idc == 3) + stride_uv *= 2; + if (chroma_fmt_idc == 3 || chroma_fmt_idc == 2) { + virstrid_uv = stride_uv * ver_virstride; + } else { + virstrid_uv = stride_uv * ver_virstride / 2; + } + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 fbd_offset; + + hw_regs->ctrl_regs.reg9.dpb_data_sel = 0; + hw_regs->ctrl_regs.reg9.dpb_output_dis = 0; + hw_regs->ctrl_regs.reg9.pp_m_output_mode = 0; + + hw_regs->comm_paras.reg68_dpb_hor_virstride = fbc_hdr_stride / 64; + fbd_offset = fbc_hdr_stride * MPP_ALIGN(ver_virstride, 64) / 16; + hw_regs->comm_addrs.reg193_dpb_fbc64x4_payload_offset = fbd_offset; + hw_regs->comm_paras.reg80_error_ref_hor_virstride = hw_regs->comm_paras.reg68_dpb_hor_virstride; + } else if (MPP_FRAME_FMT_IS_TILE(fmt)) { + hw_regs->ctrl_regs.reg9.dpb_data_sel = 1; + hw_regs->ctrl_regs.reg9.dpb_output_dis = 1; + hw_regs->ctrl_regs.reg9.pp_m_output_mode = 2; + + if (chroma_fmt_idc == 0) { //yuv400 + hw_regs->comm_paras.reg77_pp_m_hor_stride = stride_y * 4 / 16; + } else if (chroma_fmt_idc == 2) { //yuv422 + hw_regs->comm_paras.reg77_pp_m_hor_stride = stride_y * 8 / 16; + } else if (chroma_fmt_idc == 3) { //yuv444 + hw_regs->comm_paras.reg77_pp_m_hor_stride = stride_y * 12 / 16; + } else { //yuv420 + hw_regs->comm_paras.reg77_pp_m_hor_stride = stride_y * 6 / 16; + } + hw_regs->comm_paras.reg79_pp_m_y_virstride = (virstrid_y + virstrid_uv) / 16; + hw_regs->comm_paras.reg80_error_ref_hor_virstride = hw_regs->comm_paras.reg77_pp_m_hor_stride; + } else { + hw_regs->ctrl_regs.reg9.dpb_data_sel = 1; + hw_regs->ctrl_regs.reg9.dpb_output_dis = 1; + hw_regs->ctrl_regs.reg9.pp_m_output_mode = 1; + + hw_regs->comm_paras.reg77_pp_m_hor_stride = stride_y >> 4; + hw_regs->comm_paras.reg78_pp_m_uv_hor_stride = stride_uv >> 4; + hw_regs->comm_paras.reg79_pp_m_y_virstride = virstrid_y >> 4; + hw_regs->comm_paras.reg80_error_ref_hor_virstride = hw_regs->comm_paras.reg77_pp_m_hor_stride; + } + hw_regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = hw_regs->comm_paras.reg78_pp_m_uv_hor_stride; + hw_regs->comm_paras.reg82_error_ref_virstride = hw_regs->comm_paras.reg79_pp_m_y_virstride; + } + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &framebuf); + + if (reg_ctx->origin_bufs) { + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, + dxva_ctx->pp.CurrPic.Index7Bits); + framebuf = origin_buf->buf[0]; + } + + /* output rkfbc64 */ + // hw_regs->comm_addrs.reg168_dpb_decout_base = mpp_buffer_get_fd(framebuf); //just index need map + /* output raster/tile4x4 */ + hw_regs->comm_addrs.reg135_pp_m_decout_base = mpp_buffer_get_fd(framebuf); //just index need map + hw_regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(framebuf); + /*if out_base is equal to zero it means this frame may error + we return directly add by csy*/ + + /* output rkfbc64 */ + // if (!hw_regs->comm_addrs.reg168_dpb_decout_base) + // return 0; + /* output raster/tile4x4 */ + if (!hw_regs->comm_addrs.reg135_pp_m_decout_base) + return 0; + + fd = mpp_buffer_get_fd(framebuf); + /* output rkfbc64 */ + // hw_regs->comm_addrs.reg168_dpb_decout_base = fd; + /* output raster/tile4x4 */ + hw_regs->comm_addrs.reg135_pp_m_decout_base = fd; + hw_regs->comm_addrs.reg192_dpb_payload64x4_st_cur_base = fd; + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_ctx->pp.CurrPic.Index7Bits); + + hw_regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); +#ifdef DUMP_VDPU384A_DATAS + { + char *cur_fname = "colmv_cur_frame.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(mv_buf->buf[0]), + mpp_buffer_get_size(mv_buf->buf[0]), 64, 0); + } +#endif + + mpp_buf_slot_get_prop(cfg->packet_slots, syn->dec.input, SLOT_BUFFER, + &streambuf); + if ( dxva_ctx->bitstream == NULL) { + dxva_ctx->bitstream = mpp_buffer_get_ptr(streambuf); + } + +#ifdef DUMP_VDPU384A_DATAS + { + char *cur_fname = "stream_in_128bit.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(streambuf), + mpp_buffer_get_size(streambuf), 128, 0); + } +#endif + + hw_regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(streambuf); + hw_regs->comm_paras.reg66_stream_len = ((dxva_ctx->bitstream_size + 15) & (~15)) + 64; + hw_regs->comm_addrs.reg129_stream_buf_st_base = mpp_buffer_get_fd(streambuf); + hw_regs->comm_addrs.reg130_stream_buf_end_base = mpp_buffer_get_fd(streambuf); + mpp_dev_set_reg_offset(cfg->dev, 130, mpp_buffer_get_size(streambuf)); + aglin_offset = hw_regs->comm_paras.reg66_stream_len - dxva_ctx->bitstream_size; + if (aglin_offset > 0) + memset((void *)(dxva_ctx->bitstream + dxva_ctx->bitstream_size), 0, aglin_offset); + + /* common setting */ + vdpu384a_init_ctrl_regs(hw_regs, MPP_VIDEO_CodingHEVC); + + /* output rkfbc64 */ + // valid_ref = hw_regs->comm_addrs.reg168_dpb_decout_base; + /* output raster/tile4x4 */ + valid_ref = hw_regs->comm_addrs.reg135_pp_m_decout_base; + reg_ctx->error_index[syn->dec.reg_index] = dxva_ctx->pp.CurrPic.Index7Bits; + + hw_regs->comm_addrs.reg169_error_ref_base = valid_ref; + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_ctx->pp.RefPicList); i++) { + if (dxva_ctx->pp.RefPicList[i].bPicEntry != 0xff && + dxva_ctx->pp.RefPicList[i].bPicEntry != 0x7f) { + + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, + dxva_ctx->pp.RefPicList[i].Index7Bits); + framebuf = origin_buf->buf[0]; + } + if (framebuf != NULL) { + hw_regs->comm_addrs.reg170_185_ref_base[i] = mpp_buffer_get_fd(framebuf); + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = mpp_buffer_get_fd(framebuf); + valid_ref = hw_regs->comm_addrs.reg170_185_ref_base[i]; + if ((pocdistance(dxva_ctx->pp.PicOrderCntValList[i], dxva_ctx->pp.current_poc) < distance) + && (!mpp_frame_get_errinfo(mframe))) { + + distance = pocdistance(dxva_ctx->pp.PicOrderCntValList[i], dxva_ctx->pp.current_poc); + hw_regs->comm_addrs.reg169_error_ref_base = hw_regs->comm_addrs.reg170_185_ref_base[i]; + reg_ctx->error_index[syn->dec.reg_index] = dxva_ctx->pp.RefPicList[i].Index7Bits; + hw_regs->ctrl_regs.reg16.error_proc_disable = 1; + } + } else { + hw_regs->comm_addrs.reg170_185_ref_base[i] = valid_ref; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = valid_ref; + } + + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_ctx->pp.RefPicList[i].Index7Bits); + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + if ((reg_ctx->error_index[syn->dec.reg_index] == dxva_ctx->pp.CurrPic.Index7Bits) && + !dxva_ctx->pp.IntraPicFlag && !cfg->cfg->base.disable_error) { + h265h_dbg(H265H_DBG_TASK_ERR, "current frm may be err, should skip process"); + syn->dec.flags.ref_err = 1; + return MPP_OK; + } + + /* pps */ + hw_regs->comm_addrs.reg131_gbl_base = reg_ctx->bufs_fd; + hw_regs->comm_paras.reg67_global_len = SPSPPS_ALIGNED_SIZE / 16; + + mpp_dev_set_reg_offset(cfg->dev, 131, reg_ctx->spspps_offset); + + hal_h265d_vdpu38x_output_pps_packet(hal, syn->dec.syntax.data, + &hw_regs->comm_addrs.reg132_scanlist_addr); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_ctx->pp.RefPicList); i++) { + + if (dxva_ctx->pp.RefPicList[i].bPicEntry != 0xff && + dxva_ctx->pp.RefPicList[i].bPicEntry != 0x7f) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + + if (framebuf == NULL || mpp_frame_get_errinfo(mframe)) { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->comm_addrs.reg170_185_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } else { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->comm_addrs.reg170_185_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + vdpu38x_h265d_rcb_setup(hal, dxva_ctx, syn, width, height, + &hw_regs->comm_addrs.rcb_regs, + vdpu384a_h265d_rcb_calc); + vdpu384a_setup_statistic(&hw_regs->ctrl_regs); + mpp_buffer_sync_end(reg_ctx->bufs); + + { + //scale down config + MppFrame mframe = NULL; + MppBuffer mbuffer = NULL; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + hw_regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, dxva_ctx->pp.CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + /* output rkfbc64 */ + // hw_regs->comm_addrs.reg168_dpb_decout_base = fd; + /* output raster/tile4x4 */ + hw_regs->comm_addrs.reg135_pp_m_decout_base = fd; + hw_regs->comm_addrs.reg192_dpb_payload64x4_st_cur_base = fd; + hw_regs->comm_addrs.reg169_error_ref_base = fd; + vdpu384a_setup_down_scale(mframe, cfg->dev, &hw_regs->ctrl_regs, (void*)&hw_regs->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + hw_regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + vdpu384a_setup_down_scale(mframe, cfg->dev, &hw_regs->ctrl_regs, (void*)&hw_regs->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + hw_regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return ret; +} + +static MPP_RET hal_h265d_vdpu384a_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U8* p = NULL; + Vdpu384aRegSet *hw_regs = NULL; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_S32 index = task->dec.reg_index; + + RK_U32 i; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !reg_ctx->cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx->fast_mode) { + p = (RK_U8*)reg_ctx->g_buf[index].hw_regs; + hw_regs = ( Vdpu384aRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + p = (RK_U8*)reg_ctx->hw_regs; + hw_regs = ( Vdpu384aRegSet *)reg_ctx->hw_regs; + } + + if (hw_regs == NULL) { + mpp_err("hal_h265d_start hw_regs is NULL"); + return MPP_ERR_NULL_PTR; + } + for (i = 0; i < 68; i++) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + //mpp_log("RK_HEVC_DEC: regs[%02d]=%08X\n", i, *((RK_U32*)p)); + p += 4; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = reg_ctx->cfg->dev; + + wr_cfg.reg = &hw_regs->ctrl_regs; + wr_cfg.size = sizeof(hw_regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_paras; + wr_cfg.size = sizeof(hw_regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_addrs; + wr_cfg.size = sizeof(hw_regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->ctrl_regs.reg15; + rd_cfg.size = sizeof(hw_regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + + +static MPP_RET hal_h265d_vdpu384a_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_S32 index = task->dec.reg_index; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + RK_U8* p = NULL; + Vdpu384aRegSet *hw_regs = NULL; + RK_S32 i; + + if (reg_ctx->fast_mode) { + hw_regs = ( Vdpu384aRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( Vdpu384aRegSet *)reg_ctx->hw_regs; + } + + p = (RK_U8*)hw_regs; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + goto ERR_PROC; + } + + ret = mpp_dev_ioctl(cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +ERR_PROC: + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + (!hw_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + hw_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + hw_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) { + if (!reg_ctx->fast_mode) { + if (cfg->dec_cb) + mpp_callback(cfg->dec_cb, &task->dec); + } else { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + if (mframe) { + reg_ctx->fast_mode_err_found = 1; + mpp_frame_set_errinfo(mframe, 1); + } + } + } else { + if (reg_ctx->fast_mode && reg_ctx->fast_mode_err_found) { + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(task->dec.refer); i++) { + if (task->dec.refer[i] >= 0) { + MppFrame frame_ref = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.refer[i], + SLOT_FRAME_PTR, &frame_ref); + h265h_dbg(H265H_DBG_FAST_ERR, "refer[%d] %d frame %p\n", + i, task->dec.refer[i], frame_ref); + if (frame_ref && mpp_frame_get_errinfo(frame_ref)) { + MppFrame frame_out = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &frame_out); + mpp_frame_set_errinfo(frame_out, 1); + break; + } + } + } + } + } + + for (i = 0; i < 68; i++) { + if (i == 1) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + + if (i == 45) { + h265h_dbg(H265H_DBG_REG, "RK_HEVC_DEC: regs[%02d]=%08X\n", + i, *((RK_U32*)p)); + } + p += 4; + } + + if (reg_ctx->fast_mode) { + reg_ctx->g_buf[index].use_flag = 0; + } + + return ret; +} + +const MppHalApi hal_h265d_vdpu384a = { + .name = "h265d_vdpu384a", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(HalH265dCtx), + .flag = 0, + .init = hal_h265d_vdpu384a_init, + .deinit = hal_h265d_vdpu38x_deinit, + .reg_gen = hal_h265d_vdpu384a_gen_regs, + .start = hal_h265d_vdpu384a_start, + .wait = hal_h265d_vdpu384a_wait, + .reset = hal_h265d_vdpu_reset, + .flush = hal_h265d_vdpu_flush, + .control = hal_h265d_vdpu38x_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RV1126B, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h265d_vdpu384a) diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu384a.h b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384a.h new file mode 100644 index 000000000..4ca9aeba5 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384a.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265D_VDPU384A_H +#define HAL_H265D_VDPU384A_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h265d_vdpu384a; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_VDPU384A_H */ diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu384b.c b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384b.c new file mode 100644 index 000000000..a8fde0168 --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384b.c @@ -0,0 +1,729 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h265d_vdpu384b" + +#include "mpp_buffer_impl.h" + +#include "vdpu38x_com.h" +#include "h265d_syntax.h" +#include "hal_h265d_debug.h" +#include "hal_h265d_ctx.h" +#include "hal_h265d_com.h" +#include "hal_h265d_vdpu384b.h" + +#define PPS_SIZE (112 * 64) //(96x64) + +#define SPSPPS_ALIGNED_SIZE (MPP_ALIGN(2182 + 64, 128) / 8) // byte, 2182 bit + Reserve 64 +#define SCALIST_ALIGNED_SIZE (MPP_ALIGN(81 * 1360, SZ_4K)) +#define INFO_BUFFER_SIZE (SPSPPS_ALIGNED_SIZE + SCALIST_ALIGNED_SIZE) +#define ALL_BUFFER_SIZE(cnt) (INFO_BUFFER_SIZE *cnt) + +#define SPSPPS_OFFSET(pos) (INFO_BUFFER_SIZE * pos) +#define SCALIST_OFFSET(pos) (SPSPPS_OFFSET(pos) + SPSPPS_ALIGNED_SIZE) + +#define pocdistance(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) + +static MPP_RET hal_h265d_vdpu384b_init(void *hal, MppHalCfg *cfg) +{ + RK_S32 ret = 0; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + + mpp_env_get_u32("hal_h265d_debug", &hal_h265d_debug, 0); + + reg_ctx->cfg = cfg; + cfg->support_fast_mode = 1; + reg_ctx->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + + reg_ctx->scaling_qm = mpp_calloc(DXVA_Qmatrix_HEVC, 1); + if (reg_ctx->scaling_qm == NULL) { + mpp_err("scaling_org alloc fail"); + return MPP_ERR_MALLOC; + } + + reg_ctx->scaling_rk = mpp_calloc(scalingFactor_t, 1); + reg_ctx->pps_buf = mpp_calloc(RK_U8, SPSPPS_ALIGNED_SIZE); + reg_ctx->pps_buf_sz = SPSPPS_ALIGNED_SIZE; + + if (reg_ctx->scaling_rk == NULL) { + mpp_err("scaling_rk alloc fail"); + return MPP_ERR_MALLOC; + } + + { + RK_U32 max_cnt = reg_ctx->fast_mode ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + + //!< malloc buffers + ret = mpp_buffer_get(cfg->buf_group, ®_ctx->bufs, ALL_BUFFER_SIZE(max_cnt)); + if (ret) { + mpp_err("h265d mpp_buffer_get failed\n"); + return ret; + } + + reg_ctx->bufs_fd = mpp_buffer_get_fd(reg_ctx->bufs); + for (i = 0; i < max_cnt; i++) { + reg_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu38xRegSet)); + reg_ctx->offset_spspps[i] = SPSPPS_OFFSET(i); + reg_ctx->offset_sclst[i] = SCALIST_OFFSET(i); + } + + mpp_buffer_attach_dev(reg_ctx->bufs, cfg->dev); + } + + if (!reg_ctx->fast_mode) { + reg_ctx->hw_regs = reg_ctx->g_buf[0].hw_regs; + reg_ctx->spspps_offset = reg_ctx->offset_spspps[0]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[0]; + } + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 16; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)®_ctx->rcb_ctx); + + return MPP_OK; +} + +static MPP_RET vdpu384b_h265d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, in_tl_row) * 174; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(8, on_tl_row) * 174; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.2 * bit_depth + 0.5 ) + * (7.5 + 5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.2 * bit_depth + 0.5) + * (7.5 + 5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_col_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.6 * bit_depth + 0.5) + * (16.5 + 5.5 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +static MPP_RET hal_h265d_vdpu384b_gen_regs(void *hal, HalTaskInfo *syn) +{ + RK_S32 i = 0; + RK_S32 log2_min_cb_size; + RK_S32 width, height; + Vdpu38xRegSet *hw_regs; + RK_S32 ret = MPP_SUCCESS; + MppBuffer streambuf = NULL; + RK_S32 aglin_offset = 0; + RK_S32 valid_ref = -1; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_S32 fd = -1; + RK_U32 mv_size = 0; + RK_S32 distance = INT_MAX; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + + if (syn->dec.flags.parse_err || + (syn->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + h265d_dxva2_picture_context_t *dxva_ctx = (h265d_dxva2_picture_context_t *)syn->dec.syntax.data; + HalBuf *origin_buf = NULL; + + if (reg_ctx->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!reg_ctx->g_buf[i].use_flag) { + syn->dec.reg_index = i; + + reg_ctx->spspps_offset = reg_ctx->offset_spspps[i]; + reg_ctx->sclst_offset = reg_ctx->offset_sclst[i]; + + reg_ctx->hw_regs = reg_ctx->g_buf[i].hw_regs; + reg_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("hevc rps buf all used"); + return MPP_ERR_NOMEM; + } + } + + if (syn->dec.syntax.data == NULL) { + mpp_err("%s:%s:%d dxva is NULL", __FILE__, __FUNCTION__, __LINE__); + return MPP_ERR_NULL_PTR; + } + +#ifdef DUMP_VDPU38X_DATAS + { + memset(vdpu38x_dump_cur_dir, 0, sizeof(vdpu38x_dump_cur_dir)); + sprintf(vdpu38x_dump_cur_dir, "hevc/Frame%04d", vdpu38x_dump_cur_frm); + if (access(vdpu38x_dump_cur_dir, 0)) { + if (mkdir(vdpu38x_dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", vdpu38x_dump_cur_dir); + } + vdpu38x_dump_cur_frm++; + } +#endif + + /* output pps */ + hw_regs = (Vdpu38xRegSet*)reg_ctx->hw_regs; + memset(hw_regs, 0, sizeof(Vdpu38xRegSet)); + + if (NULL == reg_ctx->hw_regs) { + return MPP_ERR_NULL_PTR; + } + + + log2_min_cb_size = dxva_ctx->pp.log2_min_luma_coding_block_size_minus3 + 3; + width = (dxva_ctx->pp.PicWidthInMinCbsY << log2_min_cb_size); + height = (dxva_ctx->pp.PicHeightInMinCbsY << log2_min_cb_size); + mv_size = hal_h265d_avs2d_calc_mv_size(width, height, 1 << log2_min_cb_size) * 2; + + if (reg_ctx->cmv_bufs == NULL || reg_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (reg_ctx->cmv_bufs) { + hal_bufs_deinit(reg_ctx->cmv_bufs); + reg_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(®_ctx->cmv_bufs); + if (reg_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_ERR_NULL_PTR; + } + + reg_ctx->mv_size = mv_size; + reg_ctx->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(reg_ctx->cmv_bufs, reg_ctx->mv_count, 1, &size); + } + + { + MppFrame mframe = NULL; + MppFrameFormat fmt = 0; + RK_U32 hor_virstride = 0; + RK_U32 ver_virstride = 0; + RK_U32 y_virstride = 0; + RK_U32 uv_virstride = 0; + RK_U32 uv_virstride_tile = 0; + RK_U32 chroma_fmt_idc = dxva_ctx->pp.chroma_format_idc; + RK_U32 fbc_head_stride = 0; + RK_U32 fbc_pld_stride = 0; + RK_U32 fbc_offset = 0; + RK_U32 tile4x4_coeff = 0; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + /* for 8K downscale mode*/ + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + reg_ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, ®_ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + fmt = mpp_frame_get_fmt(mframe); + hor_virstride = mpp_frame_get_hor_stride(mframe); + ver_virstride = mpp_frame_get_ver_stride(mframe); + uv_virstride = hor_virstride; + y_virstride = ver_virstride * hor_virstride; + + if (chroma_fmt_idc == 3) + uv_virstride *= 2; + if (chroma_fmt_idc == 3 || chroma_fmt_idc == 2) + uv_virstride_tile = uv_virstride * ver_virstride; + else + uv_virstride_tile = uv_virstride * ver_virstride / 2; + if (MPP_FRAME_FMT_IS_AFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + hw_regs->ctrl_regs.reg9.pp_output_mode = 3; + hw_regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + hw_regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + hw_regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_RKFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + hw_regs->ctrl_regs.reg9.pp_output_mode = 2; + hw_regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + hw_regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + hw_regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + } else if (MPP_FRAME_FMT_IS_TILE(fmt)) { + if (vdpu38x_get_tile4x4_h_stride_coeff(fmt, &tile4x4_coeff)) { + mpp_err("get tile 4x4 coeff failed\n"); + return MPP_NOK; + } + hw_regs->ctrl_regs.reg9.pp_output_mode = 1; + hw_regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride * tile4x4_coeff / 16; + hw_regs->comm_paras.reg70_pp_m_y_virstride = (y_virstride + uv_virstride_tile) / 16; + } else { + hw_regs->ctrl_regs.reg9.pp_output_mode = 0; + hw_regs->comm_paras.reg68_pp_m_hor_stride = hor_virstride >> 4; + hw_regs->comm_paras.reg69_pp_m_uv_hor_stride = uv_virstride >> 4; + hw_regs->comm_paras.reg70_pp_m_y_virstride = y_virstride >> 4; + } + /* error */ + hw_regs->comm_paras.reg80_error_ref_hor_virstride = hw_regs->comm_paras.reg68_pp_m_hor_stride; + hw_regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = hw_regs->comm_paras.reg69_pp_m_uv_hor_stride; + hw_regs->comm_paras.reg82_error_ref_virstride = hw_regs->comm_paras.reg70_pp_m_y_virstride; + } + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &framebuf); + + if (reg_ctx->origin_bufs) { + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, + dxva_ctx->pp.CurrPic.Index7Bits); + framebuf = origin_buf->buf[0]; + } + + hw_regs->comm_addrs.reg168_decout_base = mpp_buffer_get_fd(framebuf); //just index need map + hw_regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(framebuf); + /*if out_base is equal to zero it means this frame may error + we return directly add by csy*/ + if (!hw_regs->comm_addrs.reg168_decout_base) + return 0; + + fd = mpp_buffer_get_fd(framebuf); + hw_regs->comm_addrs.reg168_decout_base = fd; + hw_regs->comm_addrs.reg192_payload_st_cur_base = fd; + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_ctx->pp.CurrPic.Index7Bits); + + hw_regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "colmv_cur_frame.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(mv_buf->buf[0]), + mpp_buffer_get_size(mv_buf->buf[0]), 64, 0, 0); + } +#endif + + mpp_buf_slot_get_prop(cfg->packet_slots, syn->dec.input, SLOT_BUFFER, + &streambuf); + if ( dxva_ctx->bitstream == NULL) { + dxva_ctx->bitstream = mpp_buffer_get_ptr(streambuf); + } + +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "stream_in_128bit.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(streambuf), + mpp_buffer_get_size(streambuf), 128, 0, 0); + } +#endif + + hw_regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(streambuf); + hw_regs->comm_paras.reg66_stream_len = ((dxva_ctx->bitstream_size + 15) & (~15)) + 64; + hw_regs->comm_addrs.reg129_stream_buf_st_base = mpp_buffer_get_fd(streambuf); + hw_regs->comm_addrs.reg130_stream_buf_end_base = mpp_buffer_get_fd(streambuf); + mpp_dev_set_reg_offset(cfg->dev, 130, mpp_buffer_get_size(streambuf)); + aglin_offset = hw_regs->comm_paras.reg66_stream_len - dxva_ctx->bitstream_size; + if (aglin_offset > 0) + memset((void *)(dxva_ctx->bitstream + dxva_ctx->bitstream_size), 0, aglin_offset); + + vdpu384b_init_ctrl_regs(hw_regs, MPP_VIDEO_CodingHEVC); + + valid_ref = hw_regs->comm_addrs.reg168_decout_base; + reg_ctx->error_index[syn->dec.reg_index] = dxva_ctx->pp.CurrPic.Index7Bits; + + hw_regs->comm_addrs.reg169_error_ref_base = valid_ref; + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_ctx->pp.RefPicList); i++) { + if (dxva_ctx->pp.RefPicList[i].bPicEntry != 0xff && + dxva_ctx->pp.RefPicList[i].bPicEntry != 0x7f) { + + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, + dxva_ctx->pp.RefPicList[i].Index7Bits); + framebuf = origin_buf->buf[0]; + } + if (framebuf != NULL) { + hw_regs->comm_addrs.reg170_185_ref_base[i] = mpp_buffer_get_fd(framebuf); + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = mpp_buffer_get_fd(framebuf); + valid_ref = hw_regs->comm_addrs.reg170_185_ref_base[i]; + if ((pocdistance(dxva_ctx->pp.PicOrderCntValList[i], dxva_ctx->pp.current_poc) < distance) + && (!mpp_frame_get_errinfo(mframe))) { + + distance = pocdistance(dxva_ctx->pp.PicOrderCntValList[i], dxva_ctx->pp.current_poc); + hw_regs->comm_addrs.reg169_error_ref_base = hw_regs->comm_addrs.reg170_185_ref_base[i]; + reg_ctx->error_index[syn->dec.reg_index] = dxva_ctx->pp.RefPicList[i].Index7Bits; + hw_regs->ctrl_regs.reg16.error_proc_disable = 1; + } + } else { + hw_regs->comm_addrs.reg170_185_ref_base[i] = valid_ref; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = valid_ref; + } + + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, dxva_ctx->pp.RefPicList[i].Index7Bits); + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + if ((reg_ctx->error_index[syn->dec.reg_index] == dxva_ctx->pp.CurrPic.Index7Bits) && + !dxva_ctx->pp.IntraPicFlag && !cfg->cfg->base.disable_error) { + h265h_dbg(H265H_DBG_TASK_ERR, "current frm may be err, should skip process"); + syn->dec.flags.ref_err = 1; + return MPP_OK; + } + + /* pps */ + hw_regs->comm_addrs.reg131_gbl_base = reg_ctx->bufs_fd; + hw_regs->comm_paras.reg67_global_len = SPSPPS_ALIGNED_SIZE / 16; + mpp_dev_set_reg_offset(cfg->dev, 131, reg_ctx->spspps_offset); + + hal_h265d_vdpu38x_output_pps_packet(hal, syn->dec.syntax.data, + &hw_regs->comm_addrs.reg132_scanlist_addr); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dxva_ctx->pp.RefPicList); i++) { + + if (dxva_ctx->pp.RefPicList[i].bPicEntry != 0xff && + dxva_ctx->pp.RefPicList[i].bPicEntry != 0x7f) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, + dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_BUFFER, &framebuf); + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.RefPicList[i].Index7Bits, + SLOT_FRAME_PTR, &mframe); + + if (framebuf == NULL || mpp_frame_get_errinfo(mframe)) { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->comm_addrs.reg170_185_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } else { + mv_buf = hal_bufs_get_buf(reg_ctx->cmv_bufs, reg_ctx->error_index[syn->dec.reg_index]); + hw_regs->comm_addrs.reg170_185_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg195_210_payload_st_ref_base[i] = hw_regs->comm_addrs.reg169_error_ref_base; + hw_regs->comm_addrs.reg217_232_colmv_ref_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } + } + + vdpu38x_h265d_rcb_setup(hal, dxva_ctx, syn, width, height, + &hw_regs->comm_addrs.rcb_regs, + vdpu384b_h265d_rcb_calc); + vdpu38x_setup_statistic(&hw_regs->ctrl_regs); + mpp_buffer_sync_end(reg_ctx->bufs); + + { + //scale down config + MppFrame mframe = NULL; + MppBuffer mbuffer = NULL; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, dxva_ctx->pp.CurrPic.Index7Bits, + SLOT_FRAME_PTR, &mframe); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + hw_regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + origin_buf = hal_bufs_get_buf(reg_ctx->origin_bufs, dxva_ctx->pp.CurrPic.Index7Bits); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + hw_regs->comm_addrs.reg168_decout_base = fd; + hw_regs->comm_addrs.reg192_payload_st_cur_base = fd; + hw_regs->comm_addrs.reg169_error_ref_base = fd; + vdpu38x_setup_down_scale(mframe, cfg->dev, &hw_regs->ctrl_regs, (void*)&hw_regs->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + hw_regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + vdpu38x_setup_down_scale(mframe, cfg->dev, &hw_regs->ctrl_regs, (void*)&hw_regs->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + hw_regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return ret; +} + +static MPP_RET hal_h265d_vdpu384b_start(void *hal, HalTaskInfo *task) +{ + Vdpu38xRegSet *hw_regs = NULL; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + RK_S32 index = task->dec.reg_index; + MPP_RET ret = MPP_OK; + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !reg_ctx->cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + return MPP_OK; + } + + if (reg_ctx->fast_mode) { + hw_regs = ( Vdpu38xRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( Vdpu38xRegSet *)reg_ctx->hw_regs; + } + + if (hw_regs == NULL) { + mpp_err("hal_h265d_start hw_regs is NULL"); + return MPP_ERR_NULL_PTR; + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = reg_ctx->cfg->dev; + + wr_cfg.reg = &hw_regs->ctrl_regs; + wr_cfg.size = sizeof(hw_regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_paras; + wr_cfg.size = sizeof(hw_regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_addrs; + wr_cfg.size = sizeof(hw_regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->ctrl_regs.reg15; + rd_cfg.size = sizeof(hw_regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + if (hal_h265d_debug & H265H_DBG_REG) { + rd_cfg.reg = &hw_regs->statistic_regs; + rd_cfg.size = sizeof(hw_regs->statistic_regs); + rd_cfg.offset = VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + /* rcb info for sram */ + vdpu38x_rcb_set_info(reg_ctx->rcb_ctx, dev); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + + +static MPP_RET hal_h265d_vdpu384b_wait(void *hal, HalTaskInfo *task) +{ + RK_S32 index = task->dec.reg_index; + HalH265dCtx *reg_ctx = (HalH265dCtx *)hal; + MppHalCfg *cfg = reg_ctx->cfg; + Vdpu38xRegSet *hw_regs = NULL; + RK_U32 i; + MPP_RET ret = MPP_OK; + + if (reg_ctx->fast_mode) { + hw_regs = ( Vdpu38xRegSet *)reg_ctx->g_buf[index].hw_regs; + } else { + hw_regs = ( Vdpu38xRegSet *)reg_ctx->hw_regs; + } + + if (task->dec.flags.parse_err || + (task->dec.flags.ref_err && !cfg->cfg->base.disable_error)) { + h265h_dbg(H265H_DBG_TASK_ERR, "%s found task error\n", __FUNCTION__); + goto ERR_PROC; + } + + ret = mpp_dev_ioctl(cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + +ERR_PROC: + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + (!hw_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + hw_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + hw_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) { + if (!reg_ctx->fast_mode) { + if (cfg->dec_cb) + mpp_callback(cfg->dec_cb, &task->dec); + } else { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + if (mframe) { + reg_ctx->fast_mode_err_found = 1; + mpp_frame_set_errinfo(mframe, 1); + } + } + } else { + if (reg_ctx->fast_mode && reg_ctx->fast_mode_err_found) { + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(task->dec.refer); i++) { + if (task->dec.refer[i] >= 0) { + MppFrame frame_ref = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.refer[i], + SLOT_FRAME_PTR, &frame_ref); + h265h_dbg(H265H_DBG_FAST_ERR, "refer[%d] %d frame %p\n", + i, task->dec.refer[i], frame_ref); + if (frame_ref && mpp_frame_get_errinfo(frame_ref)) { + MppFrame frame_out = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &frame_out); + mpp_frame_set_errinfo(frame_out, 1); + break; + } + } + } + } + } + if (hal_h265d_debug & H265H_DBG_REG) { + RK_U32 *p = (RK_U32 *)hw_regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(hw_regs->ctrl_regs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_CTRL_REGS, *p++); + for (i = 0; i < sizeof(hw_regs->comm_paras) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_CODEC_PARAS_REGS, *p++); + for (i = 0; i < sizeof(hw_regs->comm_addrs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_COMMON_ADDR_REGS, *p++); + for (i = 0; i < sizeof(hw_regs->statistic_regs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B, *p++); + + mpp_assert(hw_regs->statistic_regs.reg312.rcb_rd_sum_chk == + hw_regs->statistic_regs.reg312.rcb_wr_sum_chk); + } + + if (reg_ctx->fast_mode) { + reg_ctx->g_buf[index].use_flag = 0; + } + + return ret; +} + +const MppHalApi hal_h265d_vdpu384b = { + .name = "h265d_vdpu384b", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(HalH265dCtx), + .flag = 0, + .init = hal_h265d_vdpu384b_init, + .deinit = hal_h265d_vdpu38x_deinit, + .reg_gen = hal_h265d_vdpu384b_gen_regs, + .start = hal_h265d_vdpu384b_start, + .wait = hal_h265d_vdpu384b_wait, + .reset = hal_h265d_vdpu_reset, + .flush = hal_h265d_vdpu_flush, + .control = hal_h265d_vdpu38x_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h265d_vdpu384b) diff --git a/mpp/hal/rkdec/h265d/hal_h265d_vdpu384b.h b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384b.h new file mode 100644 index 000000000..d2ce4afcf --- /dev/null +++ b/mpp/hal/rkdec/h265d/hal_h265d_vdpu384b.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265D_VDPU384B_H +#define HAL_H265D_VDPU384B_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_h265d_vdpu384b; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H265D_VDPU384B_H */ diff --git a/mpp/hal/rkdec/inc/vdpu34x_avs2d.h b/mpp/hal/rkdec/inc/vdpu34x_avs2d.h new file mode 100644 index 000000000..05b617a34 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu34x_avs2d.h @@ -0,0 +1,152 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU34X_AVS2D_H +#define VDPU34X_AVS2D_H + +#include "vdpu34x_com.h" + +typedef struct Vdpu34xRegAvs2dParam_t { + struct SWREG64_H26X_SET { + RK_U32 h26x_frame_orslice : 1; + RK_U32 h26x_rps_mode : 1; + RK_U32 h26x_stream_mode : 1; + RK_U32 h26x_stream_lastpacket : 1; + RK_U32 h264_firstslice_flag : 1; + RK_U32 reserve : 27; + } reg64; + + RK_U32 reg65_cur_top_poc; + RK_U32 reg66_cur_bot_poc; + + RK_U32 reg67_098_ref_poc[32]; + + struct SWREG99_AVS2_REF0_3_INFO { + RK_U32 ref0_field : 1; + RK_U32 : 1; + RK_U32 ref0_botfield_used : 1; + RK_U32 ref0_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref1_field : 1; + RK_U32 : 1; + RK_U32 ref1_botfield_used : 1; + RK_U32 ref1_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref2_field : 1; + RK_U32 : 1; + RK_U32 ref2_botfield_used : 1; + RK_U32 ref2_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref3_field : 1; + RK_U32 : 1; + RK_U32 ref3_botfield_used : 1; + RK_U32 ref3_valid_flag : 1; + RK_U32 : 4; + } reg99; + + struct SWREG100_AVS2_REF4_7_INFO { + RK_U32 ref4_field : 1; + RK_U32 : 1; + RK_U32 ref4_botfield_used : 1; + RK_U32 ref4_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref5_field : 1; + RK_U32 : 1; + RK_U32 ref5_botfield_used : 1; + RK_U32 ref5_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref6_field : 1; + RK_U32 : 1; + RK_U32 ref6_botfield_used : 1; + RK_U32 ref6_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref7_field : 1; + RK_U32 : 1; + RK_U32 ref7_botfield_used : 1; + RK_U32 ref7_valid_flag : 1; + RK_U32 : 4; + } reg100; + + RK_U32 reg101_102[2]; + + struct SW103_CTRL_EXTRA { + // 0 : use default 255, 1 : use fixed 256 + RK_U32 slice_hor_pos_ctrl : 1; + RK_U32 : 31; + } reg103; + + RK_U32 reg104; + struct SW105_HEAD_LEN { + RK_U32 head_len : 4; + RK_U32 count_update_en : 1; + RK_U32 : 27; + } reg105; + + RK_U32 reg106_111[6]; + struct SW112_ERROR_REF_INFO { + // 0 : Frame, 1 : field + RK_U32 ref_error_field : 1; + /** + * @brief Refer error is top field flag. + * 0 : Bottom field flag, + * 1 : Top field flag. + */ + RK_U32 ref_error_topfield : 1; + // For inter, 0 : top field is no used, 1 : top field is used. + RK_U32 ref_error_topfield_used : 1; + // For inter, 0 : bottom field is no used, 1 : bottom field is used. + RK_U32 ref_error_botfield_used : 1; + RK_U32 : 28; + } reg112; + +} Vdpu34xRegAvs2dParam; + +typedef struct Vdpu34xRegAvs2dAddr_t { + /* SWREG160 */ + RK_U32 reg160_no_use; + + /* SWREG161 */ + RK_U32 head_base; + + /* SWREG162 */ + RK_U32 reg162_no_use; + + /* SWREG163 */ + RK_U32 rps_base; + + /* SWREG164~179 */ + RK_U32 ref_base[16]; + + /* SWREG180 */ + RK_U32 scanlist_addr; + + /* SWREG181~196 */ + RK_U32 colmv_base[16]; + + /* SWREG197 */ + RK_U32 cabactbl_base; +} Vdpu34xRegAvs2dAddr; + +typedef struct Vdpu34xAvs2dRegSet_t { + Vdpu34xRegCommon common; + Vdpu34xRegAvs2dParam avs2d_param; + Vdpu34xRegCommonAddr common_addr; + Vdpu34xRegAvs2dAddr avs2d_addr; + Vdpu34xRegIrqStatus irq_status; + Vdpu34xRegStatistic statistic; +} Vdpu34xAvs2dRegSet; + +#endif /* VDPU34X_AVS2D_H */ diff --git a/mpp/hal/rkdec/inc/vdpu34x_com.h b/mpp/hal/rkdec/inc/vdpu34x_com.h new file mode 100644 index 000000000..7e8ce7ae1 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu34x_com.h @@ -0,0 +1,495 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU34X_COM_H +#define VDPU34X_COM_H + +#include "mpp_device.h" +#include "mpp_buf_slot.h" +#include "vdpu_com.h" + +#define VDPU34X_OFF_COMMON_REGS (8 * sizeof(RK_U32)) +#define VDPU34X_OFF_CODEC_PARAMS_REGS (64 * sizeof(RK_U32)) +#define VDPU34X_OFF_COMMON_ADDR_REGS (128 * sizeof(RK_U32)) +#define VDPU34X_OFF_CODEC_ADDR_REGS (160 * sizeof(RK_U32)) +#define VDPU34X_OFF_POC_HIGHBIT_REGS (200 * sizeof(RK_U32)) +#define VDPU34X_OFF_INTERRUPT_REGS (224 * sizeof(RK_U32)) +#define VDPU34X_OFF_STATISTIC_REGS (256 * sizeof(RK_U32)) + +typedef enum Vdpu34x_RCB_TYPE_E { + RCB_DBLK_ROW, + RCB_INTRA_ROW, + RCB_TRANSD_ROW, + RCB_STRMD_ROW, + RCB_INTER_ROW, + RCB_SAO_ROW, + RCB_FBC_ROW, + RCB_TRANSD_COL, + RCB_INTER_COL, + RCB_FILT_COL, + + RCB_BUF_COUNT, +} Vdpu34xRcbType_e; + +/* base: OFFSET_COMMON_REGS */ +typedef struct Vdpu34xRegCommon_t { + struct SWREG8_IN_OUT { + RK_U32 in_endian : 1; + RK_U32 in_swap32_e : 1; + RK_U32 in_swap64_e : 1; + RK_U32 str_endian : 1; + RK_U32 str_swap32_e : 1; + RK_U32 str_swap64_e : 1; + RK_U32 out_endian : 1; + RK_U32 out_swap32_e : 1; + RK_U32 out_cbcr_swap : 1; + RK_U32 out_swap64_e : 1; + RK_U32 reserve : 22; + } reg008; + + struct SWREG9_DEC_MODE { + RK_U32 dec_mode : 10; + RK_U32 reserve : 22; + } reg009; + + struct SWREG10_DEC_E { + RK_U32 dec_e : 1; + RK_U32 reserve : 31; + } reg010; + + struct SWREG11_IMPORTANT_EN { + RK_U32 reserver : 1; + RK_U32 dec_clkgate_e : 1; + RK_U32 dec_e_strmd_clkgate_dis : 1; + RK_U32 reserve0 : 1; + + RK_U32 dec_irq_dis : 1; + RK_U32 dec_timeout_e : 1; + RK_U32 buf_empty_en : 1; + RK_U32 reserve1 : 3; + + RK_U32 dec_e_rewrite_valid : 1; + RK_U32 reserve2 : 9; + RK_U32 softrst_en_p : 1; + RK_U32 force_softreset_valid : 1; + RK_U32 reserve3 : 2; + RK_U32 pix_range_detection_e : 1; + RK_U32 reserve4 : 7; + } reg011; + + struct SWREG12_SENCODARY_EN { + RK_U32 wr_ddr_align_en : 1; + RK_U32 colmv_compress_en : 1; + RK_U32 fbc_e : 1; + RK_U32 reserve0 : 1; + + RK_U32 buspr_slot_disable : 1; + RK_U32 error_info_en : 1; + RK_U32 info_collect_en : 1; + RK_U32 wait_reset_en : 1; + + RK_U32 scanlist_addr_valid_en : 1; + RK_U32 scale_down_en : 1; + RK_U32 error_cfg_wr_disable : 1; + RK_U32 reserve1 : 21; + } reg012; + + struct SWREG13_EN_MODE_SET { + RK_U32 timeout_mode : 1; + RK_U32 req_timeout_rst_sel : 1; + RK_U32 reserve0 : 1; + RK_U32 dec_commonirq_mode : 1; + RK_U32 reserve1 : 2; + RK_U32 stmerror_waitdecfifo_empty : 1; + RK_U32 reserve2 : 2; + RK_U32 h26x_streamd_error_mode : 1; + RK_U32 reserve3 : 2; + RK_U32 allow_not_wr_unref_bframe : 1; + RK_U32 fbc_output_wr_disable : 1; + RK_U32 reserve4 : 1; + RK_U32 colmv_error_mode : 1; + + RK_U32 reserve5 : 2; + RK_U32 h26x_error_mode : 1; + RK_U32 reserve6 : 2; + RK_U32 ycacherd_prior : 1; + RK_U32 reserve7 : 2; + RK_U32 cur_pic_is_idr : 1; + RK_U32 reserve8 : 1; + RK_U32 right_auto_rst_disable : 1; + RK_U32 frame_end_err_rst_flag : 1; + RK_U32 rd_prior_mode : 1; + RK_U32 rd_ctrl_prior_mode : 1; + RK_U32 reserved9 : 1; + RK_U32 filter_outbuf_mode : 1; + } reg013; + + struct SWREG14_FBC_PARAM_SET { + RK_U32 fbc_force_uncompress : 1; + + RK_U32 reserve0 : 2; + RK_U32 allow_16x8_cp_flag : 1; + RK_U32 reserve1 : 2; + + RK_U32 fbc_h264_exten_4or8_flag: 1; + RK_U32 reserve2 : 25; + } reg014; + + struct SWREG15_STREAM_PARAM_SET { + RK_U32 rlc_mode_direct_write : 1; + RK_U32 rlc_mode : 1; + RK_U32 reserve0 : 3; + + RK_U32 strm_start_bit : 7; + RK_U32 reserve1 : 20; + } reg015; + + RK_U32 reg016_str_len; + + struct SWREG17_SLICE_NUMBER { + RK_U32 slice_num : 25; + RK_U32 reserve : 7; + } reg017; + + struct SWREG18_Y_HOR_STRIDE { + RK_U32 y_hor_virstride : 16; + RK_U32 reserve : 16; + } reg018; + + struct SWREG19_UV_HOR_STRIDE { + RK_U32 uv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg019; + + union { + struct SWREG20_Y_STRIDE { + RK_U32 y_virstride : 28; + RK_U32 reserve : 4; + } reg020_y_virstride; + + struct SWREG20_FBC_PAYLOAD_OFFSET { + RK_U32 reserve : 4; + RK_U32 payload_st_offset : 28; + } reg020_fbc_payload_off; + }; + + + struct SWREG21_ERROR_CTRL_SET { + RK_U32 inter_error_prc_mode : 1; + RK_U32 error_intra_mode : 1; + RK_U32 error_deb_en : 1; + RK_U32 picidx_replace : 5; + RK_U32 error_spread_e : 1; + RK_U32 : 3; + RK_U32 error_inter_pred_cross_slice : 1; + RK_U32 reserve0 : 11; + + RK_U32 roi_error_ctu_cal_en : 1; + RK_U32 reserve1 : 7; + } reg021; + + struct SWREG22_ERR_ROI_CTU_OFFSET_START { + RK_U32 roi_x_ctu_offset_st : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_st : 12; + RK_U32 reserve1 : 4; + } reg022; + + struct SWREG23_ERR_ROI_CTU_OFFSET_END { + RK_U32 roi_x_ctu_offset_end : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_end : 12; + RK_U32 reserve1 : 4; + } reg023; + + struct SWREG24_CABAC_ERROR_EN_LOWBITS { + RK_U32 cabac_err_en_lowbits : 32; + } reg024; + + struct SWREG25_CABAC_ERROR_EN_HIGHBITS { + RK_U32 cabac_err_en_highbits : 30; + RK_U32 reserve : 2; + } reg025; + + struct SWREG26_BLOCK_GATING_EN { + RK_U32 swreg_block_gating_e : 20; + RK_U32 reserve : 11; + RK_U32 reg_cfg_gating_en : 1; + } reg026; + + /* NOTE: reg027 ~ reg032 are added in vdpu38x at rk3588 */ + struct SW027_CORE_SAFE_PIXELS { + // colmv and recon report coord x safe pixels + RK_U32 core_safe_x_pixels : 16; + // colmv and recon report coord y safe pixels + RK_U32 core_safe_y_pixels : 16; + } reg027; + + struct SWREG28_MULTIPLY_CORE_CTRL { + RK_U32 swreg_vp9_wr_prob_idx : 3; + RK_U32 reserve0 : 1; + RK_U32 swreg_vp9_rd_prob_idx : 3; + RK_U32 reserve1 : 1; + + RK_U32 swreg_ref_req_advance_flag : 1; + RK_U32 sw_colmv_req_advance_flag : 1; + RK_U32 sw_poc_only_highbit_flag : 1; + RK_U32 sw_poc_arb_flag : 1; + + RK_U32 reserve2 : 4; + RK_U32 sw_film_idx : 10; + RK_U32 reserve3 : 2; + RK_U32 sw_pu_req_mismatch_dis : 1; + RK_U32 sw_colmv_req_mismatch_dis : 1; + RK_U32 reserve4 : 2; + } reg028; + + struct SW029_SCALE_DOWN_CTRL { + RK_U32 scale_down_hor_ratio : 2; + RK_U32 : 6; + RK_U32 scale_down_vrz_ratio : 2; + RK_U32 : 22; + } reg029; + + struct SW032_Y_SCALE_DOWN_TILE8x8_HOR_STRIDE { + RK_U32 y_scale_down_hor_stride : 20; + RK_U32 : 12; + } reg030; + + struct SW031_UV_SCALE_DOWN_TILE8x8_HOR_STRIDE { + RK_U32 uv_scale_down_hor_stride : 20; + RK_U32 : 12; + } reg031; + + /* NOTE: timeout must be config in vdpu38x */ + RK_U32 reg032_timeout_threshold; +} Vdpu34xRegCommon; + +/* base: OFFSET_COMMON_ADDR_REGS */ +typedef struct Vdpu34xRegCommonAddr_t { + /* offset 128 */ + RK_U32 reg128_rlc_base; + + RK_U32 reg129_rlcwrite_base; + + RK_U32 reg130_decout_base; + + RK_U32 reg131_colmv_cur_base; + + RK_U32 reg132_error_ref_base; + + RK_U32 reg133_rcb_intra_base; + + RK_U32 reg134_rcb_transd_row_base; + + RK_U32 reg135_rcb_transd_col_base; + + RK_U32 reg136_rcb_streamd_row_base; + + RK_U32 reg137_rcb_inter_row_base; + + RK_U32 reg138_rcb_inter_col_base; + + RK_U32 reg139_rcb_dblk_base; + + RK_U32 reg140_rcb_sao_base; + + RK_U32 reg141_rcb_fbc_base; + + RK_U32 reg142_rcb_filter_col_base; +} Vdpu34xRegCommonAddr; + +/* base: OFFSET_COMMON_ADDR_REGS */ +typedef struct Vdpu34xRegIrqStatus_t { + struct SWREG224_STA_INT { + RK_U32 dec_irq : 1; + RK_U32 dec_irq_raw : 1; + + RK_U32 dec_rdy_sta : 1; + RK_U32 dec_bus_sta : 1; + RK_U32 dec_error_sta : 1; + RK_U32 dec_timeout_sta : 1; + RK_U32 buf_empty_sta : 1; + RK_U32 colmv_ref_error_sta : 1; + RK_U32 cabu_end_sta : 1; + + RK_U32 softreset_rdy : 1; + + RK_U32 reserve : 22; + } reg224; + + struct SWREG225_STA_ERR_INFO { + RK_U32 all_frame_error_flag : 1; + RK_U32 strmd_detect_error_flag : 1; + RK_U32 reserve : 30; + } reg225; + + struct SWREG226_STA_CABAC_ERROR_STATUS { + RK_U32 strmd_error_status : 28; + RK_U32 reserve : 4; + } reg226; + + struct SWREG227_STA_COLMV_ERROR_REF_PICIDX { + RK_U32 colmv_error_ref_picidx : 4; + RK_U32 reserve : 28; + } reg227; + + struct SWREG228_STA_CABAC_ERROR_CTU_OFFSET { + RK_U32 cabac_error_ctu_offset_x : 12; + RK_U32 : 4; + RK_U32 cabac_error_ctu_offset_y : 12; + RK_U32 : 4; + } reg228; + + struct SWREG229_STA_SAOWR_CTU_OFFSET { + RK_U32 saowr_xoffset : 16; + RK_U32 saowr_yoffset : 16; + } reg229; + + struct SWREG230_STA_SLICE_DEC_NUM { + RK_U32 slicedec_num : 25; + RK_U32 reserve : 7; + } reg230; + + struct SWREG231_STA_FRAME_ERROR_CTU_NUM { + RK_U32 frame_ctu_err_num : 32; + } reg231; + + struct SWREG232_STA_ERROR_PACKET_NUM { + RK_U32 packet_err_num : 16; + RK_U32 reserve : 16; + } reg232; + + struct SWREG233_STA_ERR_CTU_NUM_IN_RO { + RK_U32 error_ctu_num_in_roi : 24; + RK_U32 reserve : 8; + } reg233; + + RK_U32 reserve_reg234_237[4]; +} Vdpu34xRegIrqStatus; + +typedef struct Vdpu34xRegStatistic_t { + struct SWREG256_DEBUG_PERF_LATENCY_CTRL0 { + RK_U32 axi_perf_work_e : 1; + RK_U32 axi_perf_clr_e : 1; + RK_U32 reserve0 : 1; + RK_U32 axi_cnt_type : 1; + RK_U32 rd_latency_id : 4; + RK_U32 rd_latency_thr : 12; + RK_U32 reserve1 : 12; + } reg256; + + struct SWREG257_DEBUG_PERF_LATENCY_CTRL1 { + RK_U32 addr_align_type : 2; + RK_U32 ar_cnt_id_type : 1; + RK_U32 aw_cnt_id_type : 1; + RK_U32 ar_count_id : 4; + RK_U32 aw_count_id : 4; + RK_U32 rd_band_width_mode : 1; + RK_U32 reserve : 19; + } reg257; + + struct SWREG258_DEBUG_PERF_RD_MAX_LATENCY_NUM { + RK_U32 rd_max_latency_num : 16; + RK_U32 reserve : 16; + } reg258; + + RK_U32 reg259_rd_latency_thr_num_ch0; + RK_U32 reg260_rd_latency_acc_sum; + RK_U32 reg261_perf_rd_axi_total_byte; + RK_U32 reg262_perf_wr_axi_total_byte; + RK_U32 reg263_perf_working_cnt; + + RK_U32 reserve_reg264; + + struct SWREG265_DEBUG_PERF_SEL { + RK_U32 perf_cnt0_sel : 6; + RK_U32 reserve0 : 2; + RK_U32 perf_cnt1_sel : 6; + RK_U32 reserve1 : 2; + RK_U32 perf_cnt2_sel : 6; + RK_U32 reserve2 : 10; + } reg265; + + RK_U32 reg266_perf_cnt0; + RK_U32 reg267_perf_cnt1; + RK_U32 reg268_perf_cnt2; + + RK_U32 reserve_reg269; + + struct SWREG270_DEBUG_QOS_CTRL { + RK_U32 bus2mc_buffer_qos_level : 8; + RK_U32 reserve0 : 8; + RK_U32 axi_rd_hurry_level : 2; + RK_U32 reserve1 : 2; + RK_U32 axi_wr_qos : 2; + RK_U32 reserve2 : 2; + RK_U32 axi_wr_hurry_level : 2; + RK_U32 reserve3 : 2; + RK_U32 axi_rd_qos : 2; + RK_U32 reserve4 : 2; + } reg270; + + RK_U32 reg271_wr_wait_cycle_qos; + + struct SWREG272_DEBUG_INT { + RK_U32 bu_rw_clean : 1; + RK_U32 saowr_frame_rdy : 1; + RK_U32 saobu_frame_rdy_valid : 1; + RK_U32 colmvwr_frame_rdy_real : 1; + RK_U32 cabu_rlcend_valid_real : 1; + RK_U32 stream_rdburst_cnteq0_towr : 1; + RK_U32 wr_tansfer_cnt : 6; + RK_U32 reserve0 : 4; + RK_U32 streamfifo_space2full : 7; + RK_U32 reserve1 : 9; + } reg272; + + struct SWREG273 { + RK_U32 bus_status_flag : 19; + RK_U32 reserve0 : 12; + RK_U32 pps_no_ref_bframe_dec_r : 1; + } reg273; + + RK_U16 reg274_y_min_value; + RK_U16 reg274_y_max_value; + RK_U16 reg275_u_min_value; + RK_U16 reg275_u_max_value; + RK_U16 reg276_v_min_value; + RK_U16 reg276_v_max_value; + + struct SWREG277_ERROR_SPREAD_NUM { + RK_U32 err_spread_cnt_sum : 24; + RK_U32 : 8; + } reg277; +} Vdpu34xRegStatistic; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 vdpu34x_get_rcb_buf_size(VdpuRcbInfo *info, RK_S32 width, RK_S32 height); +void vdpu34x_setup_rcb(Vdpu34xRegCommonAddr *reg, MppDev dev, MppBuffer buf, VdpuRcbInfo *info); +void vdpu34x_setup_statistic(Vdpu34xRegCommon *com, Vdpu34xRegStatistic *sta); +RK_S32 vdpu34x_set_rcbinfo(MppDev dev, VdpuRcbInfo *rcb_info); +RK_U32 vdpu34x_get_colmv_size(RK_U32 width, RK_U32 height, RK_U32 ctu_size, + RK_U32 colmv_bytes, RK_U32 colmv_size, RK_U32 compress); + +#ifdef __cplusplus +} +#endif + +#endif /* VDPU34X_COM_H */ diff --git a/mpp/hal/rkdec/inc/vdpu34x_h264d.h b/mpp/hal/rkdec/inc/vdpu34x_h264d.h new file mode 100644 index 000000000..f96f908e7 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu34x_h264d.h @@ -0,0 +1,249 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU34X_H264D_H +#define VDPU34X_H264D_H + +#include "vdpu34x_com.h" + +/* base: OFFSET_CODEC_PARAMS_REGS */ +typedef struct Vdpu34xRegH264dParam_t { + struct { + RK_U32 h26x_frame_orslice : 1; + RK_U32 h26x_rps_mode : 1; + RK_U32 h26x_stream_mode : 1; + RK_U32 h26x_stream_lastpacket : 1; + RK_U32 h264_firstslice_flag : 1; + RK_U32 reserve : 27; + } reg64; + + struct { + RK_U32 cur_top_poc : 32; + } reg65; + + struct { + RK_U32 cur_bot_poc : 32; + } reg66; + + RK_U32 reg67_98_ref_poc[32]; + + struct { + + RK_U32 ref0_field : 1; + RK_U32 ref0_topfield_used : 1; + RK_U32 ref0_botfield_used : 1; + RK_U32 ref0_colmv_use_flag : 1; + RK_U32 ref0_reserve : 4; + + RK_U32 ref1_field : 1; + RK_U32 ref1_topfield_used : 1; + RK_U32 ref1_botfield_used : 1; + RK_U32 ref1_colmv_use_flag : 1; + RK_U32 ref1_reserve : 4; + + RK_U32 ref2_field : 1; + RK_U32 ref2_topfield_used : 1; + RK_U32 ref2_botfield_used : 1; + RK_U32 ref2_colmv_use_flag : 1; + RK_U32 ref2_reserve : 4; + + RK_U32 ref3_field : 1; + RK_U32 ref3_topfield_used : 1; + RK_U32 ref3_botfield_used : 1; + RK_U32 ref3_colmv_use_flag : 1; + RK_U32 ref3_reserve : 4; + } reg99; + + struct { + + RK_U32 ref4_field : 1; + RK_U32 ref4_topfield_used : 1; + RK_U32 ref4_botfield_used : 1; + RK_U32 ref4_colmv_use_flag : 1; + RK_U32 ref4_reserve : 4; + + RK_U32 ref5_field : 1; + RK_U32 ref5_topfield_used : 1; + RK_U32 ref5_botfield_used : 1; + RK_U32 ref5_colmv_use_flag : 1; + RK_U32 ref5_reserve : 4; + + RK_U32 ref6_field : 1; + RK_U32 ref6_topfield_used : 1; + RK_U32 ref6_botfield_used : 1; + RK_U32 ref6_colmv_use_flag : 1; + RK_U32 ref6_reserve : 4; + + RK_U32 ref7_field : 1; + RK_U32 ref7_topfield_used : 1; + RK_U32 ref7_botfield_used : 1; + RK_U32 ref7_colmv_use_flag : 1; + RK_U32 ref7_reserve : 4; + } reg100; + + struct { + + RK_U32 ref8_field : 1; + RK_U32 ref8_topfield_used : 1; + RK_U32 ref8_botfield_used : 1; + RK_U32 ref8_colmv_use_flag : 1; + RK_U32 ref8_reserve : 4; + + RK_U32 ref9_field : 1; + RK_U32 ref9_topfield_used : 1; + RK_U32 ref9_botfield_used : 1; + RK_U32 ref9_colmv_use_flag : 1; + RK_U32 ref9_reserve : 4; + + RK_U32 ref10_field : 1; + RK_U32 ref10_topfield_used : 1; + RK_U32 ref10_botfield_used : 1; + RK_U32 ref10_colmv_use_flag : 1; + RK_U32 ref10_reserve : 4; + + RK_U32 ref11_field : 1; + RK_U32 ref11_topfield_used : 1; + RK_U32 ref11_botfield_used : 1; + RK_U32 ref11_colmv_use_flag : 1; + RK_U32 ref11_reserve : 4; + } reg101; + + struct { + + RK_U32 ref12_field : 1; + RK_U32 ref12_topfield_used : 1; + RK_U32 ref12_botfield_used : 1; + RK_U32 ref12_colmv_use_flag : 1; + RK_U32 ref12_reserve : 4; + + RK_U32 ref13_field : 1; + RK_U32 ref13_topfield_used : 1; + RK_U32 ref13_botfield_used : 1; + RK_U32 ref13_colmv_use_flag : 1; + RK_U32 ref13_reserve : 4; + + RK_U32 ref14_field : 1; + RK_U32 ref14_topfield_used : 1; + RK_U32 ref14_botfield_used : 1; + RK_U32 ref14_colmv_use_flag : 1; + RK_U32 ref14_reserve : 4; + + RK_U32 ref15_field : 1; + RK_U32 ref15_topfield_used : 1; + RK_U32 ref15_botfield_used : 1; + RK_U32 ref15_colmv_use_flag : 1; + RK_U32 ref15_reserve : 4; + } reg102; + + struct { + RK_U32 reserve; + } no_use_regs[9]; + + struct { + RK_U32 avs2_ref_error_field : 1; + RK_U32 avs2_ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve : 28; + } reg112; +} Vdpu34xRegH264dParam; + +/* base: OFFSET_CODEC_ADDR_REGS */ +typedef struct Vdpu34xRegH264dAddr_t { + /* SWREG160 */ + RK_U32 reg160_no_use; + + /* SWREG161 */ + RK_U32 pps_base; + + /* SWREG162 */ + RK_U32 reg162_no_use; + + /* SWREG163 */ + RK_U32 rps_base; + + /* SWREG164~179 */ + RK_U32 ref_base[16]; + + /* SWREG180 */ + RK_U32 scanlist_addr; + + /* SWREG181~196 */ + RK_U32 colmv_base[16]; + + /* SWREG197 */ + RK_U32 cabactbl_base; +} Vdpu34xRegH264dAddr; + +typedef struct Vdpu34xH264dHighPoc_t { + /* SWREG200 */ + struct { + RK_U32 ref0_poc_highbit : 4; + RK_U32 ref1_poc_highbit : 4; + RK_U32 ref2_poc_highbit : 4; + RK_U32 ref3_poc_highbit : 4; + RK_U32 ref4_poc_highbit : 4; + RK_U32 ref5_poc_highbit : 4; + RK_U32 ref6_poc_highbit : 4; + RK_U32 ref7_poc_highbit : 4; + } reg200; + struct { + RK_U32 ref8_poc_highbit : 4; + RK_U32 ref9_poc_highbit : 4; + RK_U32 ref10_poc_highbit : 4; + RK_U32 ref11_poc_highbit : 4; + RK_U32 ref12_poc_highbit : 4; + RK_U32 ref13_poc_highbit : 4; + RK_U32 ref14_poc_highbit : 4; + RK_U32 ref15_poc_highbit : 4; + } reg201; + struct { + RK_U32 ref16_poc_highbit : 4; + RK_U32 ref17_poc_highbit : 4; + RK_U32 ref18_poc_highbit : 4; + RK_U32 ref19_poc_highbit : 4; + RK_U32 ref20_poc_highbit : 4; + RK_U32 ref21_poc_highbit : 4; + RK_U32 ref22_poc_highbit : 4; + RK_U32 ref23_poc_highbit : 4; + } reg202; + struct { + RK_U32 ref24_poc_highbit : 4; + RK_U32 ref25_poc_highbit : 4; + RK_U32 ref26_poc_highbit : 4; + RK_U32 ref27_poc_highbit : 4; + RK_U32 ref28_poc_highbit : 4; + RK_U32 ref29_poc_highbit : 4; + RK_U32 ref30_poc_highbit : 4; + RK_U32 ref31_poc_highbit : 4; + } reg203; + struct { + RK_U32 cur_poc_highbit : 4; + RK_U32 reserver : 28; + } reg204; +} Vdpu34xH264dHighPoc_t; + +typedef struct Vdpu34xH264dRegSet_t { + Vdpu34xRegCommon common; + Vdpu34xRegH264dParam h264d_param; + Vdpu34xRegCommonAddr common_addr; + Vdpu34xRegH264dAddr h264d_addr; + Vdpu34xH264dHighPoc_t h264d_highpoc; + Vdpu34xRegIrqStatus irq_status; + Vdpu34xRegStatistic statistic; +} Vdpu34xH264dRegSet; + +#endif /* VDPU34X_H264D_H */ diff --git a/mpp/hal/rkdec/inc/vdpu34x_h265d.h b/mpp/hal/rkdec/inc/vdpu34x_h265d.h new file mode 100644 index 000000000..9610f4370 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu34x_h265d.h @@ -0,0 +1,188 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU34X_H265D_H +#define VDPU34X_H265D_H + +#include "vdpu34x_com.h" + +typedef struct Vdpu34xRegH265d_t { + struct { + RK_U32 h26x_frame_orslice : 1; + RK_U32 h26x_rps_mode : 1; + RK_U32 h26x_stream_mode : 1; + RK_U32 h26x_stream_lastpacket : 1; + RK_U32 h264_firstslice_flag : 1; + RK_U32 reserve : 27; + } reg64; + + struct { + RK_U32 cur_top_poc : 32; + } reg65; + + struct { + RK_U32 cur_bot_poc : 32; + } reg66; + + RK_U32 reg67_82_ref_poc[16]; + + + struct { + RK_U32 ref_poc : 32; + } ref_poc_no_use[16]; + + /* struct SWREG99_HEVC_REF_VALID{ + RK_U32 hevc_ref_valid : 15; + RK_U32 reserve : 17; + }hevc_ref_valid; */ + + struct { + RK_U32 hevc_ref_valid_0 : 1; + RK_U32 hevc_ref_valid_1 : 1; + RK_U32 hevc_ref_valid_2 : 1; + RK_U32 hevc_ref_valid_3 : 1; + RK_U32 reserve0 : 4; + RK_U32 hevc_ref_valid_4 : 1; + RK_U32 hevc_ref_valid_5 : 1; + RK_U32 hevc_ref_valid_6 : 1; + RK_U32 hevc_ref_valid_7 : 1; + RK_U32 reserve1 : 4; + RK_U32 hevc_ref_valid_8 : 1; + RK_U32 hevc_ref_valid_9 : 1; + RK_U32 hevc_ref_valid_10 : 1; + RK_U32 hevc_ref_valid_11 : 1; + RK_U32 reserve2 : 4; + RK_U32 hevc_ref_valid_12 : 1; + RK_U32 hevc_ref_valid_13 : 1; + RK_U32 hevc_ref_valid_14 : 1; + RK_U32 reserve3 : 5; + } reg99; + + RK_U32 reg100_102_no_use[3]; + + struct { + RK_U32 ref_pic_layer_same_with_cur : 16; + RK_U32 reserve : 16; + } reg103; + + struct { + RK_U32 poc_lsb_not_present_flag : 1; + RK_U32 num_direct_ref_layers : 6; + RK_U32 reserve0 : 1; + + RK_U32 num_reflayer_pics : 6; + RK_U32 default_ref_layers_active_flag : 1; + RK_U32 max_one_active_ref_layer_flag : 1; + + RK_U32 poc_reset_info_present_flag : 1; + RK_U32 vps_poc_lsb_aligned_flag : 1; + RK_U32 mvc_poc15_valid_flag : 1; + RK_U32 reserve1 : 13; + } reg104; + + struct { + RK_U32 no_use_regs[7]; + } no_use_regs; + + struct { + RK_U32 avs2_ref_error_field : 1; + RK_U32 avs2_ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve : 28; + } reg112; + +} Vdpu34xRegH265d; + +typedef struct Vdpu34xRegH265dAddr_t { + struct { + RK_U32 vp9_delta_prob_base : 32; + } reg160_no_use; + + RK_U32 reg161_pps_base; + + RK_U32 reg162_no_use; + + RK_U32 reg163_rps_base; + + RK_U32 reg164_179_ref_base[16]; + + RK_U32 reg180_scanlist_addr; + + RK_U32 reg181_196_colmv_base[16]; + + RK_U32 reg197_cabactbl_base; +} Vdpu34xRegH265dAddr; + +typedef struct Vdpu34xH265dHighPoc_t { + /* SWREG200 */ + struct { + RK_U32 ref0_poc_highbit : 4; + RK_U32 ref1_poc_highbit : 4; + RK_U32 ref2_poc_highbit : 4; + RK_U32 ref3_poc_highbit : 4; + RK_U32 ref4_poc_highbit : 4; + RK_U32 ref5_poc_highbit : 4; + RK_U32 ref6_poc_highbit : 4; + RK_U32 ref7_poc_highbit : 4; + } reg200; + struct { + RK_U32 ref8_poc_highbit : 4; + RK_U32 ref9_poc_highbit : 4; + RK_U32 ref10_poc_highbit : 4; + RK_U32 ref11_poc_highbit : 4; + RK_U32 ref12_poc_highbit : 4; + RK_U32 ref13_poc_highbit : 4; + RK_U32 ref14_poc_highbit : 4; + RK_U32 ref15_poc_highbit : 4; + } reg201; + struct { + RK_U32 ref16_poc_highbit : 4; + RK_U32 ref17_poc_highbit : 4; + RK_U32 ref18_poc_highbit : 4; + RK_U32 ref19_poc_highbit : 4; + RK_U32 ref20_poc_highbit : 4; + RK_U32 ref21_poc_highbit : 4; + RK_U32 ref22_poc_highbit : 4; + RK_U32 ref23_poc_highbit : 4; + } reg202; + struct { + RK_U32 ref24_poc_highbit : 4; + RK_U32 ref25_poc_highbit : 4; + RK_U32 ref26_poc_highbit : 4; + RK_U32 ref27_poc_highbit : 4; + RK_U32 ref28_poc_highbit : 4; + RK_U32 ref29_poc_highbit : 4; + RK_U32 ref30_poc_highbit : 4; + RK_U32 ref31_poc_highbit : 4; + } reg203; + struct { + RK_U32 cur_poc_highbit : 4; + RK_U32 reserver : 28; + } reg204; +} Vdpu34xH2645HighPoc_t; + +typedef struct Vdpu34xH265dRegSet_t { + Vdpu34xRegCommon common; + Vdpu34xRegH265d h265d_param; + Vdpu34xRegCommonAddr common_addr; + Vdpu34xRegH265dAddr h265d_addr; + Vdpu34xH2645HighPoc_t highpoc; + Vdpu34xRegIrqStatus irq_status; + Vdpu34xRegStatistic statistic; +} Vdpu34xH265dRegSet; + +#endif /* VDPU34X_H265D_H */ diff --git a/mpp/hal/rkdec/inc/vdpu34x_vp9d.h b/mpp/hal/rkdec/inc/vdpu34x_vp9d.h new file mode 100644 index 000000000..0e241b559 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu34x_vp9d.h @@ -0,0 +1,294 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VDPU34X_VP9D_H +#define HAL_VDPU34X_VP9D_H + +#include "rk_type.h" +#include "vdpu34x_com.h" + + +typedef struct Vdpu34xRegVp9dParam_t { + struct { + RK_U32 cprheader_offset : 16; + RK_U32 reserve : 16; + } reg64; + + struct { + RK_U32 cur_poc : 32; + } reg65; + + RK_U32 reg66; + + struct { + RK_U32 segid_abs_delta : 1; + RK_U32 segid_frame_qp_delta_en : 1; + RK_U32 segid_frame_qp_delta : 9; + RK_U32 segid_frame_loopfitler_value_en : 1; + RK_U32 segid_frame_loopfilter_value : 7; + RK_U32 segid_referinfo_en : 1; + RK_U32 segid_referinfo : 2; + RK_U32 segid_frame_skip_en : 1; + RK_U32 reserve : 9; + } reg67_74[8]; + + struct { + RK_U32 mode_deltas_lastframe : 14; + RK_U32 vp9_segment_id_clear : 1; + RK_U32 vp9_segment_id_update : 1; + RK_U32 segmentation_enable_lstframe : 1; + RK_U32 last_show_frame : 1; + RK_U32 last_intra_only : 1; + RK_U32 last_widthheight_eqcur : 1; + RK_U32 color_space_lastkeyframe : 3; + RK_U32 reserve1 : 9; + } reg75; + + struct { + RK_U32 tx_mode : 3; + RK_U32 frame_reference_mode : 2; + RK_U32 reserve : 27; + } reg76; + + struct { + RK_U32 intercmd_num : 24; + RK_U32 reserve : 8; + } reg77; + + struct { + RK_U32 lasttile_size : 24; + RK_U32 reserve : 8; + } reg78; + + struct { + RK_U32 lastfy_hor_virstride : 16; + RK_U32 reserve : 16; + } reg79; + + struct { + RK_U32 lastfuv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg80; + + struct { + RK_U32 goldenfy_hor_virstride : 16; + RK_U32 reserve : 16; + } reg81; + + struct { + RK_U32 goldenfuv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg82; + + struct { + RK_U32 altreffy_hor_virstride : 16; + RK_U32 reserve : 16; + } reg83; + + struct { + RK_U32 altreffuv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg84; + + struct { + RK_U32 lastfy_virstride : 28; + RK_U32 reserve : 4; + } reg85; + + struct { + RK_U32 goldeny_virstride : 28; + RK_U32 reserve : 4; + } reg86; + + struct { + RK_U32 altrefy_virstride : 28; + RK_U32 reserve : 4; + } reg87; + + struct { + RK_U32 lref_hor_scale : 16; + RK_U32 reserve : 16; + } reg88; + + struct { + RK_U32 lref_ver_scale : 16; + RK_U32 reserve : 16; + } reg89; + + struct { + RK_U32 gref_hor_scale : 16; + RK_U32 reserve : 16; + } reg90; + + struct { + RK_U32 gref_ver_scale : 16; + RK_U32 reserve : 16; + } reg91; + + struct { + RK_U32 aref_hor_scale : 16; + RK_U32 reserve : 16; + } reg92; + + struct { + RK_U32 aref_ver_scale : 16; + RK_U32 reserve : 16; + } reg93; + + struct { + RK_U32 ref_deltas_lastframe : 28; + RK_U32 reserve : 4; + } reg94; + + struct { + RK_U32 last_poc : 32; + } reg95; + + struct { + RK_U32 golden_poc : 32; + } reg96; + + struct { + RK_U32 altref_poc : 32; + } reg97; + + struct { + RK_U32 col_ref_poc : 32; + } reg98; + + struct { + RK_U32 prob_ref_poc : 32; + } reg99; + + struct { + RK_U32 segid_ref_poc : 32; + } reg100; + + RK_U32 reg101_102_no_use[2]; + + struct { + RK_U32 reserve : 20; + RK_U32 prob_update_en : 1; + RK_U32 refresh_en : 1; + RK_U32 prob_save_en : 1; + RK_U32 intra_only_flag : 1; + + RK_U32 txfmmode_rfsh_en : 1; + RK_U32 ref_mode_rfsh_en : 1; + RK_U32 single_ref_rfsh_en : 1; + RK_U32 comp_ref_rfsh_en : 1; + + RK_U32 interp_filter_switch_en : 1; + RK_U32 allow_high_precision_mv : 1; + RK_U32 last_key_frame_flag : 1; + RK_U32 inter_coef_rfsh_flag : 1; + } reg103; + + RK_U32 reg104_no_use; + + struct { + RK_U32 avs2_head_len : 4; + RK_U32 count_update_en : 1; + RK_U32 reserve : 27; + } reg105; + + struct { + RK_U32 framewidth_last : 16; + RK_U32 reserve : 16; + } reg106; + + struct { + RK_U32 frameheight_last : 16; + RK_U32 reserve : 16; + } reg107; + + struct { + RK_U32 framewidth_golden : 16; + RK_U32 reserve : 16; + } reg108; + + struct { + RK_U32 frameheight_golden : 16; + RK_U32 reserve : 16; + } reg109; + + struct { + RK_U32 framewidth_alfter : 16; + RK_U32 reserve : 16; + } reg110; + + struct { + RK_U32 frameheight_alfter : 16; + RK_U32 reserve : 16; + } reg111; + + struct { + RK_U32 ref_error_field : 1; + RK_U32 ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve : 28; + } reg112; + +} Vdpu34xRegVp9dParam; + +typedef struct Vdpu34xRegVp9dAddr_t { + + RK_U32 reg160_delta_prob_base; + + RK_U32 reg161_pps_base; + + RK_U32 reg162_last_prob_base; + + RK_U32 reg163_rps_base; + + RK_U32 reg164_ref_last_base; + + RK_U32 reg165_ref_golden_base; + + RK_U32 reg166_ref_alfter_base; + + RK_U32 reg167_count_prob_base; + + RK_U32 reg168_segidlast_base; + + RK_U32 reg169_segidcur_base; + + RK_U32 reg170_ref_colmv_base; + + RK_U32 reg171_intercmd_base; + + RK_U32 reg172_update_prob_wr_base; + + RK_U32 reg173_179_no_use[7]; + + RK_U32 reg180_scanlist_base; + + RK_U32 reg181_196_ref_colmv_base[16]; + + RK_U32 reg197_cabactbl_base; +} Vdpu34xRegVp9dAddr; + +typedef struct Vdpu34xVp9dRegSet_t { + Vdpu34xRegCommon common; + Vdpu34xRegVp9dParam vp9d_param; + Vdpu34xRegCommonAddr common_addr; + Vdpu34xRegVp9dAddr vp9d_addr; + Vdpu34xRegIrqStatus irq_status; + Vdpu34xRegStatistic statistic; +} Vdpu34xVp9dRegSet; + +#endif /* HAL_VDPU34X_VP9D_H */ \ No newline at end of file diff --git a/mpp/hal/rkdec/inc/vdpu382_avs2d.h b/mpp/hal/rkdec/inc/vdpu382_avs2d.h new file mode 100644 index 000000000..dc87b79a5 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu382_avs2d.h @@ -0,0 +1,156 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU382_AVS2D_H +#define VDPU382_AVS2D_H + +#include "vdpu382_com.h" + +typedef struct Vdpu382RegAvs2dParam_t { + struct { + RK_U32 h26x_frame_orslice : 1; + RK_U32 h26x_rps_mode : 1; + RK_U32 h26x_stream_mode : 1; + RK_U32 h26x_stream_lastpacket : 1; + RK_U32 h264_firstslice_flag : 1; + RK_U32 reserve : 27; + } reg64; + + RK_U32 reg65_cur_top_poc; + RK_U32 reg66_cur_bot_poc; + + RK_U32 reg67_098_ref_poc[32]; + + struct { + RK_U32 ref0_field : 1; + RK_U32 : 1; + RK_U32 ref0_botfield_used : 1; + RK_U32 ref0_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref1_field : 1; + RK_U32 : 1; + RK_U32 ref1_botfield_used : 1; + RK_U32 ref1_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref2_field : 1; + RK_U32 : 1; + RK_U32 ref2_botfield_used : 1; + RK_U32 ref2_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref3_field : 1; + RK_U32 : 1; + RK_U32 ref3_botfield_used : 1; + RK_U32 ref3_valid_flag : 1; + RK_U32 : 4; + } reg99; + + struct { + RK_U32 ref4_field : 1; + RK_U32 : 1; + RK_U32 ref4_botfield_used : 1; + RK_U32 ref4_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref5_field : 1; + RK_U32 : 1; + RK_U32 ref5_botfield_used : 1; + RK_U32 ref5_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref6_field : 1; + RK_U32 : 1; + RK_U32 ref6_botfield_used : 1; + RK_U32 ref6_valid_flag : 1; + RK_U32 : 4; + RK_U32 ref7_field : 1; + RK_U32 : 1; + RK_U32 ref7_botfield_used : 1; + RK_U32 ref7_valid_flag : 1; + RK_U32 : 4; + } reg100; + + RK_U32 reg101_102[2]; + + struct { + // 0 : use default 255, 1 : use fixed 256 + RK_U32 slice_hor_pos_ctrl : 1; + RK_U32 : 31; + } reg103; + + RK_U32 reg104; + struct { + RK_U32 head_len : 4; + RK_U32 count_update_en : 1; + RK_U32 : 27; + } reg105; + + RK_U32 reg106_111[6]; + struct { + // 0 : Frame, 1 : field + RK_U32 ref_error_field : 1; + /** + * @brief Refer error is top field flag. + * 0 : Bottom field flag, + * 1 : Top field flag. + */ + RK_U32 ref_error_topfield : 1; + // For inter, 0 : top field is no used, 1 : top field is used. + RK_U32 ref_error_topfield_used : 1; + // For inter, 0 : bottom field is no used, 1 : bottom field is used. + RK_U32 ref_error_botfield_used : 1; + RK_U32 : 28; + } reg112; + +} Vdpu382RegAvs2dParam; + +typedef struct Vdpu382RegAvs2dAddr_t { + /* SWREG160 */ + RK_U32 reg160_no_use; + + /* SWREG161 */ + RK_U32 head_base; + + /* SWREG162 */ + RK_U32 reg162_no_use; + + /* SWREG163 */ + RK_U32 rps_base; + + /* SWREG164~179 */ + RK_U32 ref_base[16]; + + /* SWREG180 */ + RK_U32 scanlist_addr; + + /* SWREG181~196 */ + RK_U32 colmv_base[16]; + + /* SWREG197 */ + RK_U32 cabactbl_base; + + RK_U32 scale_down_luma_base; + + RK_U32 scale_down_chorme_base; +} Vdpu382RegAvs2dAddr; + +typedef struct Vdpu382Avs2dRegSet_t { + Vdpu382RegCommon common; + Vdpu382RegAvs2dParam avs2d_param; + Vdpu382RegCommonAddr common_addr; + Vdpu382RegAvs2dAddr avs2d_addr; + Vdpu382RegIrqStatus irq_status; + Vdpu382RegStatistic statistic; +} Vdpu382Avs2dRegSet; + +#endif /* VDPU382_AVS2D_H */ diff --git a/mpp/hal/rkdec/inc/vdpu382_com.h b/mpp/hal/rkdec/inc/vdpu382_com.h new file mode 100644 index 000000000..f9e13dbcf --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu382_com.h @@ -0,0 +1,561 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU382_COM_H +#define VDPU382_COM_H + +#include "mpp_device.h" +#include "mpp_buf_slot.h" +#include "vdpu_com.h" + +#define VDPU382_OFF_COMMON_REGS (8 * sizeof(RK_U32)) +#define VDPU382_OFF_CODEC_PARAMS_REGS (64 * sizeof(RK_U32)) +#define VDPU382_OFF_COMMON_ADDR_REGS (128 * sizeof(RK_U32)) +#define VDPU382_OFF_CODEC_ADDR_REGS (160 * sizeof(RK_U32)) +#define VDPU382_OFF_POC_HIGHBIT_REGS (200 * sizeof(RK_U32)) +#define VDPU382_OFF_INTERRUPT_REGS (224 * sizeof(RK_U32)) +#define VDPU382_OFF_STATISTIC_REGS (256 * sizeof(RK_U32)) + +typedef enum Vdpu382_RCB_TYPE_E { + RCB_DBLK_ROW, + RCB_INTRA_ROW, + RCB_TRANSD_ROW, + RCB_STRMD_ROW, + RCB_INTER_ROW, + RCB_SAO_ROW, + RCB_FBC_ROW, + RCB_TRANSD_COL, + RCB_INTER_COL, + RCB_FILT_COL, + + RCB_BUF_COUNT, +} Vdpu382RcbType_e; + +/* base: OFFSET_COMMON_REGS */ +typedef struct Vdpu382RegCommon_t { + struct { + RK_U32 in_endian : 1; + RK_U32 in_swap32_e : 1; + RK_U32 in_swap64_e : 1; + RK_U32 str_endian : 1; + RK_U32 str_swap32_e : 1; + RK_U32 str_swap64_e : 1; + RK_U32 out_endian : 1; + RK_U32 out_swap32_e : 1; + RK_U32 out_cbcr_swap : 1; + RK_U32 out_swap64_e : 1; + RK_U32 reserve : 22; + } reg008; + + struct { + RK_U32 dec_mode : 10; + RK_U32 reserve : 22; + } reg009; + + struct { + RK_U32 dec_e : 1; + RK_U32 reserve : 31; + } reg010; + + struct { + RK_U32 reserver : 1; + RK_U32 dec_clkgate_e : 1; + RK_U32 reserve1 : 2; + + RK_U32 dec_irq_dis : 1; + RK_U32 dec_line_irq_dis : 1; //change to reg205[9] + RK_U32 buf_empty_en : 1; + RK_U32 reserve2 : 1; + + RK_U32 dec_line_irq_en : 1; + RK_U32 reserve3 : 1; + RK_U32 dec_e_rewrite_valid : 1; + RK_U32 reserve4 : 9; + + RK_U32 softrst_en_p : 1; + RK_U32 reserve5 : 1; //change to reg205[0] + RK_U32 err_head_fill_e : 1; + RK_U32 err_colmv_fill_e : 1; + RK_U32 pix_range_detection_e : 1; + RK_U32 reserve6 : 3; + RK_U32 wlast_match_fail : 1; + RK_U32 mmu_wlast_match_fail : 1; + RK_U32 reserve7 : 2; + } reg011; + + struct { + RK_U32 reserve0 : 1; + RK_U32 colmv_compress_en : 1; + RK_U32 fbc_e : 1; + RK_U32 tile_e : 1; + + RK_U32 reserve1 : 1; + RK_U32 error_info_en : 1; + RK_U32 info_collect_en : 1; + RK_U32 reserve2 : 1; //change to reg205[4] + + RK_U32 scanlist_addr_valid_en : 1; + RK_U32 scale_down_en : 1; + RK_U32 reserve3 : 22; + } reg012; + + struct { + RK_U32 reserve0 : 1; + RK_U32 req_timeout_rst_sel : 1; + RK_U32 reserve1 : 1; + RK_U32 dec_commonirq_mode : 1; + RK_U32 reserve2 : 2; + RK_U32 stmerror_waitdecfifo_empty : 1; + RK_U32 reserve3 : 1; + RK_U32 strmd_zero_rm_en : 1; + RK_U32 reserve4 : 3; + RK_U32 allow_not_wr_unref_bframe : 1; + RK_U32 fbc_output_wr_disable : 1; + + RK_U32 reserve5 : 4; + RK_U32 h26x_error_mode : 1; + RK_U32 reserve6 : 5; + RK_U32 cur_pic_is_idr : 1; + RK_U32 reserve8 : 6; //change to reg205[5] + RK_U32 filter_outbuf_mode : 1; + + } reg013; + + struct { + RK_U32 fbc_force_uncompress : 1; + + RK_U32 reserve0 : 2; + RK_U32 allow_16x8_cp_flag : 1; + RK_U32 reserve1 : 2; + + RK_U32 fbc_h264_exten_4or8_flag: 1; + RK_U32 reserve2 : 25; + } reg014; + + struct { + RK_U32 rlc_mode_direct_write : 1; + RK_U32 rlc_mode : 1; + RK_U32 strmd_ofifo_perf_opt_en : 1; + RK_U32 reserve0 : 2; + + RK_U32 strm_start_bit : 7; + RK_U32 reserve1 : 20; + } reg015; + + RK_U32 reg016_str_len; + + struct { + RK_U32 slice_num : 25; + RK_U32 reserve : 7; + } reg017; + + struct { + RK_U32 y_hor_virstride : 16; + RK_U32 reserve : 16; + } reg018; + + struct { + RK_U32 uv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg019; + + union { + struct { + RK_U32 y_virstride : 28; + RK_U32 reserve : 4; + } reg020_y_virstride; + + struct { + RK_U32 reserve : 4; + RK_U32 payload_st_offset : 28; + } reg020_fbc_payload_off; + }; + + + struct { + RK_U32 inter_error_prc_mode : 1; + RK_U32 error_intra_mode : 1; + RK_U32 error_deb_en : 1; + RK_U32 picidx_replace : 5; + RK_U32 error_spread_e : 1; + RK_U32 : 3; + RK_U32 error_inter_pred_cross_slice : 1; + RK_U32 reserve0 : 11; + + RK_U32 roi_error_ctu_cal_en : 1; + RK_U32 reserve1 : 7; + } reg021; + + struct { + RK_U32 roi_x_ctu_offset_st : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_st : 12; + RK_U32 reserve1 : 4; + } reg022; + + struct { + RK_U32 roi_x_ctu_offset_end : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_end : 12; + RK_U32 reserve1 : 4; + } reg023; + + struct { + RK_U32 cabac_err_en_lowbits : 32; + } reg024; + + struct { + RK_U32 cabac_err_en_highbits : 30; + RK_U32 reserve : 2; + } reg025; + + struct { + RK_U32 inter_auto_gating_e : 1; + RK_U32 filterd_auto_gating_e : 1; + RK_U32 strmd_auto_gating_e : 1; + RK_U32 mcp_auto_gating_e : 1; + RK_U32 busifd_auto_gating_e : 1; + RK_U32 reserved : 3; + RK_U32 dec_ctrl_auto_gating_e : 1; + RK_U32 intra_auto_gating_e : 1; + RK_U32 mc_auto_gating_e : 1; + RK_U32 transd_auto_gating_e : 1; + RK_U32 reserved1 : 4; + RK_U32 sram_auto_gating_e : 1; + RK_U32 cru_auto_gating_e : 1; + RK_U32 reserved2 : 13; + RK_U32 reg_cfg_gating_en : 1; + } reg026; + + /* NOTE: reg027 ~ reg032 are added in vdpu38x at rk3588 */ + struct { + // colmv and recon report coord x safe pixels + RK_U32 core_safe_x_pixels : 16; + // colmv and recon report coord y safe pixels + RK_U32 core_safe_y_pixels : 16; + } reg027; + + struct { + RK_U32 swreg_vp9_wr_prob_idx : 3; + RK_U32 reserve0 : 1; + RK_U32 swreg_vp9_rd_prob_idx : 3; + RK_U32 reserve1 : 1; + + RK_U32 swreg_ref_req_advance_flag : 1; + RK_U32 sw_colmv_req_advance_flag : 1; + RK_U32 sw_poc_only_highbit_flag : 1; + RK_U32 sw_poc_arb_flag : 1; + + RK_U32 reserve2 : 4; + RK_U32 sw_film_idx : 10; + RK_U32 reserve3 : 2; + RK_U32 sw_pu_req_mismatch_dis : 1; + RK_U32 sw_colmv_req_mismatch_dis : 1; + RK_U32 reserve4 : 2; + } reg028; + + struct { + RK_U32 scale_down_y_wratio : 5; + RK_U32 reserve0 : 3; + RK_U32 scale_down_y_hratio : 5; + RK_U32 reserve1 : 3; + RK_U32 scale_down_c_wratio : 5; + RK_U32 reserve2 : 3; + RK_U32 scale_down_c_hratio : 5; + RK_U32 reserve3 : 1; + RK_U32 scale_down_roi_mode : 1; + RK_U32 scale_down_tile_mode : 1; + } reg029; + + struct { + RK_U32 y_scale_down_hor_stride : 20; + RK_U32 : 12; + } reg030; + + struct { + RK_U32 uv_scale_down_hor_stride : 20; + RK_U32 : 12; + } reg031; + + /* NOTE: reg027 ~ reg032 are added in vdpu38x at rk3588 */ + /* NOTE: timeout must be config in vdpu38x */ + RK_U32 reg032_timeout_threshold; + + struct { + RK_U32 dec_line_irq_step : 12; + RK_U32 dec_line_offset_y_st : 12; + RK_U32 buf_empty_timeout_threshold : 8; + } reg033; + + /* 0x00000088 reg34 */ + struct { + RK_U32 scale_down_roi_st_offsetx : 16; + RK_U32 scale_down_roi_st_offsety : 16; + } reg034; + + /* 0x0000008c reg35 */ + struct { + RK_U32 scale_down_roi_out_width : 16; + RK_U32 scale_down_roi_out_height : 16; + } reg035; + +} Vdpu382RegCommon; + +/* base: OFFSET_COMMON_ADDR_REGS */ +typedef struct Vdpu382RegCommonAddr_t { + /* offset 128 */ + RK_U32 reg128_rlc_base; + + RK_U32 reg129_rlcwrite_base; + + RK_U32 reg130_decout_base; + + RK_U32 reg131_colmv_cur_base; + + RK_U32 reg132_error_ref_base; + + RK_U32 reg133_rcb_intra_base; + + RK_U32 reg134_rcb_transd_row_base; + + RK_U32 reg135_rcb_transd_col_base; + + RK_U32 reg136_rcb_streamd_row_base; + + RK_U32 reg137_rcb_inter_row_base; + + RK_U32 reg138_rcb_inter_col_base; + + RK_U32 reg139_rcb_dblk_base; + + RK_U32 reg140_rcb_sao_base; + + RK_U32 reg141_rcb_fbc_base; + + RK_U32 reg142_rcb_filter_col_base; + + RK_U32 reg143_rcb_base; +} Vdpu382RegCommonAddr; + +/* base: OFFSET_COMMON_ADDR_REGS */ +typedef struct Vdpu382RegIrqStatus_t { + struct { + RK_U32 dec_irq : 1; + RK_U32 dec_irq_raw : 1; + + RK_U32 dec_rdy_sta : 1; + RK_U32 dec_bus_sta : 1; + RK_U32 dec_error_sta : 1; + RK_U32 dec_timeout_sta : 1; + RK_U32 buf_empty_sta : 1; + RK_U32 colmv_ref_error_sta : 1; + RK_U32 cabu_end_sta : 1; + + RK_U32 softreset_rdy : 1; + + RK_U32 dec_line_irq : 1; + RK_U32 dec_line_irq_raw : 1; + RK_U32 ltb_pause_sta : 1; + RK_U32 mmureset_rdy : 1; + RK_U32 ltb_end_sta : 1; + + RK_U32 reserve : 17; + } reg224; + + struct { + RK_U32 strmd_slice_byte_offset : 32; + } reg225; + + struct { + RK_U32 all_frame_error_flag : 1; + RK_U32 strmd_detect_error_flag : 3; + RK_U32 strmd_error_status : 28; + } reg226; + + struct { + RK_U32 colmv_error_ref_picidx : 4; + RK_U32 reserve : 28; + } reg227; + + struct { + RK_U32 cabac_error_ctu_offset_x : 12; + RK_U32 : 4; + RK_U32 cabac_error_ctu_offset_y : 12; + RK_U32 : 4; + } reg228; + + struct { + RK_U32 axi_wch_finish_flag : 17; + RK_U32 reserved : 15; + } reg229; + + struct { + RK_U32 slicedec_num : 25; + RK_U32 reserve : 7; + } reg230; + + struct { + RK_U32 frame_ctu_err_num : 32; + } reg231; + + struct { + RK_U32 packet_err_num : 16; + RK_U32 reserve : 16; + } reg232; + + struct { + RK_U32 error_ctu_num_in_roi : 24; + RK_U32 reserve : 8; + } reg233; + + struct { + RK_U32 coord_report_offset_x : 16; + RK_U32 coord_report_offset_y : 16; + } reg234; + + struct { + RK_U32 coord_report_output_height : 16; + RK_U32 reserve : 16; + } reg235; + + RK_U32 reserve_reg236_237[2]; +} Vdpu382RegIrqStatus; + +typedef struct Vdpu382RegStatistic_t { + struct { + RK_U32 axi_perf_work_e : 1; + RK_U32 axi_perf_clr_e : 1; + RK_U32 reserve0 : 1; + RK_U32 axi_cnt_type : 1; + RK_U32 rd_latency_id : 4; + RK_U32 rd_latency_thr : 12; + RK_U32 reserve1 : 12; + } reg256; + + struct { + RK_U32 addr_align_type : 2; + RK_U32 ar_cnt_id_type : 1; + RK_U32 aw_cnt_id_type : 1; + RK_U32 ar_count_id : 4; + RK_U32 aw_count_id : 4; + RK_U32 rd_band_width_mode : 1; + RK_U32 reserve : 19; + } reg257; + + struct { + RK_U32 rd_max_latency_num : 16; + RK_U32 reserve : 16; + } reg258; + + RK_U32 reg259_rd_latency_thr_num_ch0; + RK_U32 reg260_rd_latency_acc_sum; + RK_U32 reg261_perf_rd_axi_total_byte; + RK_U32 reg262_perf_wr_axi_total_byte; + RK_U32 reg263_perf_working_cnt; + + struct { + RK_U32 bus_state_flag : 25; + RK_U32 reserve : 7; + } reg264; + + union { + struct { + RK_U32 perf_cnt0_sel : 6; + RK_U32 reserve0 : 2; + RK_U32 perf_cnt1_sel : 6; + RK_U32 reserve1 : 2; + RK_U32 perf_cnt2_sel : 6; + RK_U32 reserve2 : 10; + }; + + RK_U32 link_perf_cnt0; + } reg265; + + RK_U32 reg266_perf_cnt0; + RK_U32 reg267_perf_cnt1; + RK_U32 reg268_perf_cnt2; + + RK_U32 reserve_reg269; + + struct { + RK_U32 bus2mc_buffer_qos_level : 8; + RK_U32 reserve0 : 8; + RK_U32 axi_wr_hurry_level : 3; + RK_U32 reserve1 : 1; + RK_U32 axi_wr_qos : 3; + RK_U32 reserve2 : 1; + RK_U32 axi_rd_hurry_level : 3; + RK_U32 reserve3 : 1; + RK_U32 axi_rd_qos : 3; + RK_U32 reserve4 : 1; + } reg270; + + RK_U32 reg271_wr_wait_cycle_qos; + + struct { + RK_U32 busidle_flag : 1; + RK_U32 reserved : 4; + RK_U32 mmu_busidle_flag : 1; + RK_U32 wr_tansfer_cnt : 8; + RK_U32 reserved1 : 2; + RK_U32 Sw_streamfifo_space2full : 7; + RK_U32 reserved2 : 1; + RK_U32 mmu_wr_transer_cnt : 8; + } reg272; + + struct { + RK_U32 bus_status_flag : 25; + RK_U32 reserve0 : 6; + RK_U32 pps_no_ref_bframe_dec_r : 1; + } reg273; + + RK_U16 reg274_y_min_value; + RK_U16 reg274_y_max_value; + RK_U16 reg275_u_min_value; + RK_U16 reg275_u_max_value; + RK_U16 reg276_v_min_value; + RK_U16 reg276_v_max_value; + + struct { + RK_U32 err_spread_cnt_sum : 24; + RK_U32 : 8; + } reg277; + + // RK_U32 reg277_err_spread_num; + // struct SWREG278_DEC_LINE_OFFSET_Y { + // RK_U32 dec_line_offset_y : 16; + // RK_U32 reserve : 16; + // } reg278; + +} Vdpu382RegStatistic; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 vdpu382_get_rcb_buf_size(VdpuRcbInfo *info, RK_S32 width, RK_S32 height); +void vdpu382_setup_rcb(Vdpu382RegCommonAddr *reg, MppDev dev, MppBuffer buf, VdpuRcbInfo *info); +RK_S32 vdpu382_set_rcbinfo(MppDev dev, VdpuRcbInfo *rcb_info); +void vdpu382_setup_statistic(Vdpu382RegCommon *com, Vdpu382RegStatistic *sta); +void vdpu382_setup_down_scale(MppFrame frame, MppDev dev, Vdpu382RegCommon *com); +RK_U32 vdpu382_get_colmv_size(RK_U32 width, RK_U32 height, RK_U32 ctu_size, + RK_U32 colmv_bytes, RK_U32 colmv_size, RK_U32 compress); + +#ifdef __cplusplus +} +#endif + +#endif /* VDPU382_COM_H */ diff --git a/mpp/hal/rkdec/inc/vdpu382_h264d.h b/mpp/hal/rkdec/inc/vdpu382_h264d.h new file mode 100644 index 000000000..485b042b4 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu382_h264d.h @@ -0,0 +1,276 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU382_H264D_H +#define VDPU382_H264D_H + +#include "vdpu382_com.h" + +/* base: OFFSET_CODEC_PARAMS_REGS */ +typedef struct Vdpu382RegH264dParam_t { + struct { + RK_U32 h26x_frame_orslice : 1; + RK_U32 h26x_rps_mode : 1; + RK_U32 h26x_stream_mode : 1; + RK_U32 h26x_stream_lastpacket : 1; + RK_U32 h264_firstslice_flag : 1; + RK_U32 reserve : 27; + } reg64; + + struct { + RK_U32 cur_top_poc : 32; + } reg65; + + struct { + RK_U32 cur_bot_poc : 32; + } reg66; + + RK_U32 reg67_98_ref_poc[32]; + + struct { + + RK_U32 ref0_field : 1; + RK_U32 ref0_topfield_used : 1; + RK_U32 ref0_botfield_used : 1; + RK_U32 ref0_colmv_use_flag : 1; + RK_U32 ref0_reserve : 4; + + RK_U32 ref1_field : 1; + RK_U32 ref1_topfield_used : 1; + RK_U32 ref1_botfield_used : 1; + RK_U32 ref1_colmv_use_flag : 1; + RK_U32 ref1_reserve : 4; + + RK_U32 ref2_field : 1; + RK_U32 ref2_topfield_used : 1; + RK_U32 ref2_botfield_used : 1; + RK_U32 ref2_colmv_use_flag : 1; + RK_U32 ref2_reserve : 4; + + RK_U32 ref3_field : 1; + RK_U32 ref3_topfield_used : 1; + RK_U32 ref3_botfield_used : 1; + RK_U32 ref3_colmv_use_flag : 1; + RK_U32 ref3_reserve : 4; + } reg99; + + struct { + + RK_U32 ref4_field : 1; + RK_U32 ref4_topfield_used : 1; + RK_U32 ref4_botfield_used : 1; + RK_U32 ref4_colmv_use_flag : 1; + RK_U32 ref4_reserve : 4; + + RK_U32 ref5_field : 1; + RK_U32 ref5_topfield_used : 1; + RK_U32 ref5_botfield_used : 1; + RK_U32 ref5_colmv_use_flag : 1; + RK_U32 ref5_reserve : 4; + + RK_U32 ref6_field : 1; + RK_U32 ref6_topfield_used : 1; + RK_U32 ref6_botfield_used : 1; + RK_U32 ref6_colmv_use_flag : 1; + RK_U32 ref6_reserve : 4; + + RK_U32 ref7_field : 1; + RK_U32 ref7_topfield_used : 1; + RK_U32 ref7_botfield_used : 1; + RK_U32 ref7_colmv_use_flag : 1; + RK_U32 ref7_reserve : 4; + } reg100; + + struct { + + RK_U32 ref8_field : 1; + RK_U32 ref8_topfield_used : 1; + RK_U32 ref8_botfield_used : 1; + RK_U32 ref8_colmv_use_flag : 1; + RK_U32 ref8_reserve : 4; + + RK_U32 ref9_field : 1; + RK_U32 ref9_topfield_used : 1; + RK_U32 ref9_botfield_used : 1; + RK_U32 ref9_colmv_use_flag : 1; + RK_U32 ref9_reserve : 4; + + RK_U32 ref10_field : 1; + RK_U32 ref10_topfield_used : 1; + RK_U32 ref10_botfield_used : 1; + RK_U32 ref10_colmv_use_flag : 1; + RK_U32 ref10_reserve : 4; + + RK_U32 ref11_field : 1; + RK_U32 ref11_topfield_used : 1; + RK_U32 ref11_botfield_used : 1; + RK_U32 ref11_colmv_use_flag : 1; + RK_U32 ref11_reserve : 4; + } reg101; + + struct { + + RK_U32 ref12_field : 1; + RK_U32 ref12_topfield_used : 1; + RK_U32 ref12_botfield_used : 1; + RK_U32 ref12_colmv_use_flag : 1; + RK_U32 ref12_reserve : 4; + + RK_U32 ref13_field : 1; + RK_U32 ref13_topfield_used : 1; + RK_U32 ref13_botfield_used : 1; + RK_U32 ref13_colmv_use_flag : 1; + RK_U32 ref13_reserve : 4; + + RK_U32 ref14_field : 1; + RK_U32 ref14_topfield_used : 1; + RK_U32 ref14_botfield_used : 1; + RK_U32 ref14_colmv_use_flag : 1; + RK_U32 ref14_reserve : 4; + + RK_U32 ref15_field : 1; + RK_U32 ref15_topfield_used : 1; + RK_U32 ref15_botfield_used : 1; + RK_U32 ref15_colmv_use_flag : 1; + RK_U32 ref15_reserve : 4; + } reg102; + + struct { + RK_U32 reserve; + } no_use_regs[9]; + + struct { + RK_U32 avs2_ref_error_field : 1; + RK_U32 avs2_ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve : 28; + } reg112; +} Vdpu382RegH264dParam; + +/* base: OFFSET_CODEC_ADDR_REGS */ +typedef struct Vdpu382RegH264dAddr_t { + /* SWREG160 */ + RK_U32 reg160_no_use; + + /* SWREG161 */ + RK_U32 pps_base; + + /* SWREG162 */ + RK_U32 reg162_no_use; + + /* SWREG163 */ + RK_U32 rps_base; + + /* SWREG164~179 */ + RK_U32 ref_base[16]; + + /* SWREG180 */ + RK_U32 scanlist_addr; + + /* SWREG181~196 */ + RK_U32 colmv_base[16]; + + /* SWREG197 */ + RK_U32 cabactbl_base; + + /* SWREG198*/ + RK_U32 reg198_scale_down_luma_base; + + /* SWREG199*/ + RK_U32 reg199_scale_down_chorme_base; + +} Vdpu382RegH264dAddr; + +typedef struct Vdpu382H264dHighPoc_t { + /* SWREG200 */ + struct { + RK_U32 ref0_poc_highbit : 4; + RK_U32 ref1_poc_highbit : 4; + RK_U32 ref2_poc_highbit : 4; + RK_U32 ref3_poc_highbit : 4; + RK_U32 ref4_poc_highbit : 4; + RK_U32 ref5_poc_highbit : 4; + RK_U32 ref6_poc_highbit : 4; + RK_U32 ref7_poc_highbit : 4; + } reg200; + struct { + RK_U32 ref8_poc_highbit : 4; + RK_U32 ref9_poc_highbit : 4; + RK_U32 ref10_poc_highbit : 4; + RK_U32 ref11_poc_highbit : 4; + RK_U32 ref12_poc_highbit : 4; + RK_U32 ref13_poc_highbit : 4; + RK_U32 ref14_poc_highbit : 4; + RK_U32 ref15_poc_highbit : 4; + } reg201; + struct { + RK_U32 ref16_poc_highbit : 4; + RK_U32 ref17_poc_highbit : 4; + RK_U32 ref18_poc_highbit : 4; + RK_U32 ref19_poc_highbit : 4; + RK_U32 ref20_poc_highbit : 4; + RK_U32 ref21_poc_highbit : 4; + RK_U32 ref22_poc_highbit : 4; + RK_U32 ref23_poc_highbit : 4; + } reg202; + struct { + RK_U32 ref24_poc_highbit : 4; + RK_U32 ref25_poc_highbit : 4; + RK_U32 ref26_poc_highbit : 4; + RK_U32 ref27_poc_highbit : 4; + RK_U32 ref28_poc_highbit : 4; + RK_U32 ref29_poc_highbit : 4; + RK_U32 ref30_poc_highbit : 4; + RK_U32 ref31_poc_highbit : 4; + } reg203; + struct { + RK_U32 cur_poc_highbit : 4; + RK_U32 reserver : 28; + } reg204; + + struct { + RK_U32 force_softreset_valid : 1; + RK_U32 force_mmureset_valid : 1; + RK_U32 reserve0 : 2; + RK_U32 error_auto_rst_disable : 1; + RK_U32 right_auto_rst_disable : 1; + RK_U32 buf_empty_security_en : 1; + RK_U32 coord_realtime_report_en : 1; + + RK_U32 fetchcmd_merge_dis : 1; + RK_U32 dec_timeout_dis : 1; + RK_U32 reg_cfg_wr_dis : 1; + RK_U32 reserve1 : 1; + RK_U32 force_busidle_req : 1; + RK_U32 mmu_force_busidle_req : 1; + RK_U32 mmu_sel : 1; + RK_U32 reserve2 : 17; + + } reg205; +} Vdpu382H264dHighPoc_t; + +typedef struct Vdpu382H264dRegSet_t { + Vdpu382RegCommon common; + Vdpu382RegH264dParam h264d_param; + Vdpu382RegCommonAddr common_addr; + Vdpu382RegH264dAddr h264d_addr; + Vdpu382H264dHighPoc_t h264d_highpoc; + Vdpu382RegIrqStatus irq_status; + Vdpu382RegStatistic statistic; +} Vdpu382H264dRegSet; + +#endif /* VDPU382_H264D_H */ diff --git a/mpp/hal/rkdec/inc/vdpu382_h265d.h b/mpp/hal/rkdec/inc/vdpu382_h265d.h new file mode 100644 index 000000000..c41dda271 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu382_h265d.h @@ -0,0 +1,212 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VDPU382_H265D_H +#define VDPU382_H265D_H + +#include "vdpu382_com.h" + +typedef struct Vdpu382RegH265d_t { + struct { + RK_U32 h26x_frame_orslice : 1; + RK_U32 h26x_rps_mode : 1; + RK_U32 h26x_stream_mode : 1; + RK_U32 h26x_stream_lastpacket : 1; + RK_U32 h264_firstslice_flag : 1; + RK_U32 reserve : 27; + } reg64; + + struct { + RK_U32 cur_top_poc : 32; + } reg65; + + struct { + RK_U32 cur_bot_poc : 32; + } reg66; + + RK_U32 reg67_82_ref_poc[16]; + + + struct { + RK_U32 ref_poc : 32; + } ref_poc_no_use[16]; + + /* struct SWREG99_HEVC_REF_VALID{ + RK_U32 hevc_ref_valid : 15; + RK_U32 reserve : 17; + }hevc_ref_valid; */ + + struct { + RK_U32 hevc_ref_valid_0 : 1; + RK_U32 hevc_ref_valid_1 : 1; + RK_U32 hevc_ref_valid_2 : 1; + RK_U32 hevc_ref_valid_3 : 1; + RK_U32 reserve0 : 4; + RK_U32 hevc_ref_valid_4 : 1; + RK_U32 hevc_ref_valid_5 : 1; + RK_U32 hevc_ref_valid_6 : 1; + RK_U32 hevc_ref_valid_7 : 1; + RK_U32 reserve1 : 4; + RK_U32 hevc_ref_valid_8 : 1; + RK_U32 hevc_ref_valid_9 : 1; + RK_U32 hevc_ref_valid_10 : 1; + RK_U32 hevc_ref_valid_11 : 1; + RK_U32 reserve2 : 4; + RK_U32 hevc_ref_valid_12 : 1; + RK_U32 hevc_ref_valid_13 : 1; + RK_U32 hevc_ref_valid_14 : 1; + RK_U32 reserve3 : 5; + } reg99; + + RK_U32 reg100_102_no_use[3]; + + struct { + RK_U32 ref_pic_layer_same_with_cur : 16; + RK_U32 reserve : 16; + } reg103; + + struct { + RK_U32 poc_lsb_not_present_flag : 1; + RK_U32 num_direct_ref_layers : 6; + RK_U32 reserve0 : 1; + + RK_U32 num_reflayer_pics : 6; + RK_U32 default_ref_layers_active_flag : 1; + RK_U32 max_one_active_ref_layer_flag : 1; + + RK_U32 poc_reset_info_present_flag : 1; + RK_U32 vps_poc_lsb_aligned_flag : 1; + RK_U32 mvc_poc15_valid_flag : 1; + RK_U32 reserve1 : 13; + } reg104; + + struct { + RK_U32 no_use_regs[7]; + } no_use_regs; + + struct { + RK_U32 avs2_ref_error_field : 1; + RK_U32 avs2_ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve : 28; + } reg112; + +} Vdpu382RegH265d; + +typedef struct Vdpu382RegH265dAddr_t { + struct { + RK_U32 vp9_delta_prob_base : 32; + } reg160_no_use; + + RK_U32 reg161_pps_base; + + RK_U32 reg162_no_use; + + RK_U32 reg163_rps_base; + + RK_U32 reg164_179_ref_base[16]; + + RK_U32 reg180_scanlist_addr; + + RK_U32 reg181_196_colmv_base[16]; + + RK_U32 reg197_cabactbl_base; + + RK_U32 reg198_scale_down_luma_base; + + RK_U32 reg199_scale_down_chorme_base; +} Vdpu382RegH265dAddr; + +typedef struct Vdpu382H265dHighPoc_t { + /* SWREG200 */ + struct { + RK_U32 ref0_poc_highbit : 4; + RK_U32 ref1_poc_highbit : 4; + RK_U32 ref2_poc_highbit : 4; + RK_U32 ref3_poc_highbit : 4; + RK_U32 ref4_poc_highbit : 4; + RK_U32 ref5_poc_highbit : 4; + RK_U32 ref6_poc_highbit : 4; + RK_U32 ref7_poc_highbit : 4; + } reg200; + struct { + RK_U32 ref8_poc_highbit : 4; + RK_U32 ref9_poc_highbit : 4; + RK_U32 ref10_poc_highbit : 4; + RK_U32 ref11_poc_highbit : 4; + RK_U32 ref12_poc_highbit : 4; + RK_U32 ref13_poc_highbit : 4; + RK_U32 ref14_poc_highbit : 4; + RK_U32 ref15_poc_highbit : 4; + } reg201; + struct { + RK_U32 ref16_poc_highbit : 4; + RK_U32 ref17_poc_highbit : 4; + RK_U32 ref18_poc_highbit : 4; + RK_U32 ref19_poc_highbit : 4; + RK_U32 ref20_poc_highbit : 4; + RK_U32 ref21_poc_highbit : 4; + RK_U32 ref22_poc_highbit : 4; + RK_U32 ref23_poc_highbit : 4; + } reg202; + struct { + RK_U32 ref24_poc_highbit : 4; + RK_U32 ref25_poc_highbit : 4; + RK_U32 ref26_poc_highbit : 4; + RK_U32 ref27_poc_highbit : 4; + RK_U32 ref28_poc_highbit : 4; + RK_U32 ref29_poc_highbit : 4; + RK_U32 ref30_poc_highbit : 4; + RK_U32 ref31_poc_highbit : 4; + } reg203; + struct { + RK_U32 cur_poc_highbit : 4; + RK_U32 reserver : 28; + } reg204; + + struct { + RK_U32 force_softreset_valid : 1; + RK_U32 force_mmureset_valid : 1; + RK_U32 reserve0 : 2; + RK_U32 error_auto_rst_disable : 1; + RK_U32 right_auto_rst_disable : 1; + RK_U32 buf_empty_security_en : 1; + RK_U32 coord_realtime_report_en : 1; + + RK_U32 fetchcmd_merge_dis : 1; + RK_U32 dec_timeout_dis : 1; + RK_U32 reg_cfg_wr_dis : 1; + RK_U32 reserve1 : 1; + RK_U32 force_busidle_req : 1; + RK_U32 mmu_force_busidle_req : 1; + RK_U32 mmu_sel : 1; + RK_U32 reserve2 : 17; + + } reg205; +} Vdpu382H2645HighPoc_t; + +typedef struct Vdpu382H265dRegSet_t { + Vdpu382RegCommon common; + Vdpu382RegH265d h265d_param; + Vdpu382RegCommonAddr common_addr; + Vdpu382RegH265dAddr h265d_addr; + Vdpu382H2645HighPoc_t highpoc; + Vdpu382RegIrqStatus irq_status; + Vdpu382RegStatistic statistic; +} Vdpu382H265dRegSet; + +#endif /* VDPU382_H265D_H */ diff --git a/mpp/hal/rkdec/inc/vdpu382_vp9d.h b/mpp/hal/rkdec/inc/vdpu382_vp9d.h new file mode 100644 index 000000000..c463296c7 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu382_vp9d.h @@ -0,0 +1,319 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VDPU382_VP9D_H +#define HAL_VDPU382_VP9D_H + +#include "rk_type.h" +#include "vdpu382_com.h" + + +typedef struct Vdpu382RegVp9dParam_t { + struct { + RK_U32 cprheader_offset : 16; + RK_U32 reserve : 16; + } reg64; + + struct { + RK_U32 cur_poc : 32; + } reg65; + + RK_U32 reg66; + + struct { + RK_U32 segid_abs_delta : 1; + RK_U32 segid_frame_qp_delta_en : 1; + RK_U32 segid_frame_qp_delta : 9; + RK_U32 segid_frame_loopfitler_value_en : 1; + RK_U32 segid_frame_loopfilter_value : 7; + RK_U32 segid_referinfo_en : 1; + RK_U32 segid_referinfo : 2; + RK_U32 segid_frame_skip_en : 1; + RK_U32 reserve : 9; + } reg67_74[8]; + + struct { + RK_U32 mode_deltas_lastframe : 14; + RK_U32 vp9_segment_id_clear : 1; + RK_U32 vp9_segment_id_update : 1; + RK_U32 segmentation_enable_lstframe : 1; + RK_U32 last_show_frame : 1; + RK_U32 last_intra_only : 1; + RK_U32 last_widthheight_eqcur : 1; + RK_U32 color_space_lastkeyframe : 3; + RK_U32 reserve1 : 9; + } reg75; + + struct { + RK_U32 tx_mode : 3; + RK_U32 frame_reference_mode : 2; + RK_U32 reserve : 27; + } reg76; + + struct { + RK_U32 intercmd_num : 24; + RK_U32 reserve : 8; + } reg77; + + struct { + RK_U32 lasttile_size : 24; + RK_U32 reserve : 8; + } reg78; + + struct { + RK_U32 lastfy_hor_virstride : 16; + RK_U32 reserve : 16; + } reg79; + + struct { + RK_U32 lastfuv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg80; + + struct { + RK_U32 goldenfy_hor_virstride : 16; + RK_U32 reserve : 16; + } reg81; + + struct { + RK_U32 goldenfuv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg82; + + struct { + RK_U32 altreffy_hor_virstride : 16; + RK_U32 reserve : 16; + } reg83; + + struct { + RK_U32 altreffuv_hor_virstride : 16; + RK_U32 reserve : 16; + } reg84; + + struct { + RK_U32 lastfy_virstride : 28; + RK_U32 reserve : 4; + } reg85; + + struct { + RK_U32 goldeny_virstride : 28; + RK_U32 reserve : 4; + } reg86; + + struct { + RK_U32 altrefy_virstride : 28; + RK_U32 reserve : 4; + } reg87; + + struct { + RK_U32 lref_hor_scale : 16; + RK_U32 reserve : 16; + } reg88; + + struct { + RK_U32 lref_ver_scale : 16; + RK_U32 reserve : 16; + } reg89; + + struct { + RK_U32 gref_hor_scale : 16; + RK_U32 reserve : 16; + } reg90; + + struct { + RK_U32 gref_ver_scale : 16; + RK_U32 reserve : 16; + } reg91; + + struct { + RK_U32 aref_hor_scale : 16; + RK_U32 reserve : 16; + } reg92; + + struct { + RK_U32 aref_ver_scale : 16; + RK_U32 reserve : 16; + } reg93; + + struct { + RK_U32 ref_deltas_lastframe : 28; + RK_U32 reserve : 4; + } reg94; + + struct { + RK_U32 last_poc : 32; + } reg95; + + struct { + RK_U32 golden_poc : 32; + } reg96; + + struct { + RK_U32 altref_poc : 32; + } reg97; + + struct { + RK_U32 col_ref_poc : 32; + } reg98; + + struct { + RK_U32 prob_ref_poc : 32; + } reg99; + + struct { + RK_U32 segid_ref_poc : 32; + } reg100; + + RK_U32 reg101_102_no_use[2]; + + struct { + RK_U32 reserve : 20; + RK_U32 prob_update_en : 1; + RK_U32 refresh_en : 1; + RK_U32 prob_save_en : 1; + RK_U32 intra_only_flag : 1; + + RK_U32 txfmmode_rfsh_en : 1; + RK_U32 ref_mode_rfsh_en : 1; + RK_U32 single_ref_rfsh_en : 1; + RK_U32 comp_ref_rfsh_en : 1; + + RK_U32 interp_filter_switch_en : 1; + RK_U32 allow_high_precision_mv : 1; + RK_U32 last_key_frame_flag : 1; + RK_U32 inter_coef_rfsh_flag : 1; + } reg103; + + RK_U32 reg104_no_use; + + struct { + RK_U32 avs2_head_len : 4; + RK_U32 count_update_en : 1; + RK_U32 reserve : 27; + } reg105; + + struct { + RK_U32 framewidth_last : 16; + RK_U32 reserve : 16; + } reg106; + + struct { + RK_U32 frameheight_last : 16; + RK_U32 reserve : 16; + } reg107; + + struct { + RK_U32 framewidth_golden : 16; + RK_U32 reserve : 16; + } reg108; + + struct { + RK_U32 frameheight_golden : 16; + RK_U32 reserve : 16; + } reg109; + + struct { + RK_U32 framewidth_alfter : 16; + RK_U32 reserve : 16; + } reg110; + + struct { + RK_U32 frameheight_alfter : 16; + RK_U32 reserve : 16; + } reg111; + + struct { + RK_U32 ref_error_field : 1; + RK_U32 ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve : 28; + } reg112; + +} Vdpu382RegVp9dParam; + +typedef struct Vdpu382RegVp9dAddr_t { + + RK_U32 reg160_delta_prob_base; + + RK_U32 reg161_pps_base; + + RK_U32 reg162_last_prob_base; + + RK_U32 reg163_rps_base; + + RK_U32 reg164_ref_last_base; + + RK_U32 reg165_ref_golden_base; + + RK_U32 reg166_ref_alfter_base; + + RK_U32 reg167_count_prob_base; + + RK_U32 reg168_segidlast_base; + + RK_U32 reg169_segidcur_base; + + RK_U32 reg170_ref_colmv_base; + + RK_U32 reg171_intercmd_base; + + RK_U32 reg172_update_prob_wr_base; + + RK_U32 reg173_179_no_use[7]; + + RK_U32 reg180_scanlist_base; + + RK_U32 reg181_196_ref_colmv_base[16]; + + RK_U32 reg197_cabactbl_base; + + RK_U32 reg198_scale_down_luma_base; + + RK_U32 reg199_scale_down_chorme_base; + + RK_U32 reg200_204reserve[5]; + + struct { + RK_U32 force_softreset_valid : 1; + RK_U32 force_mmureset_valid : 1; + RK_U32 reserve0 : 2; + RK_U32 error_auto_rst_disable : 1; + RK_U32 right_auto_rst_disable : 1; + RK_U32 buf_empty_security_en : 1; + RK_U32 coord_realtime_report_en : 1; + + RK_U32 fetchcmd_merge_dis : 1; + RK_U32 dec_timeout_dis : 1; + RK_U32 reserve1 : 2; + RK_U32 force_busidle_req : 1; + RK_U32 mmu_force_busidle_req : 1; + RK_U32 mmu_sel : 1; + RK_U32 reserve2 : 17; + + } reg205; +} Vdpu382RegVp9dAddr; + +typedef struct Vdpu382Vp9dRegSet_t { + Vdpu382RegCommon common; + Vdpu382RegVp9dParam vp9d_param; + Vdpu382RegCommonAddr common_addr; + Vdpu382RegVp9dAddr vp9d_addr; + Vdpu382RegIrqStatus irq_status; + Vdpu382RegStatistic statistic; +} Vdpu382Vp9dRegSet; + +#endif /* HAL_VDPU382_VP9D_H */ \ No newline at end of file diff --git a/mpp/hal/rkdec/inc/vdpu383_com.h b/mpp/hal/rkdec/inc/vdpu383_com.h new file mode 100644 index 000000000..c2d19942c --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu383_com.h @@ -0,0 +1,621 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPU383_COM_H +#define VDPU383_COM_H + +#include "mpp_device.h" +#include "mpp_buf_slot.h" +#include "vdpu_com.h" + +// #define DUMP_VDPU383_DATAS + +typedef struct Vdpu383RegVersion_t { + struct { + RK_U32 minor_ver : 8; + RK_U32 major_ver : 8; + RK_U32 prod_num : 16; + } reg0; + +} Vdpu383RegVersion; + +typedef struct Vdpu383CtrlReg_t { + /* SWREG8_DEC_MODE */ + RK_U32 reg8_dec_mode; + + struct { + RK_U32 fbc_e : 1; + RK_U32 tile_e : 1; + RK_U32 reserve0 : 2; + RK_U32 buf_empty_en : 1; + RK_U32 scale_down_en : 1; + RK_U32 reserve1 : 1; + RK_U32 pix_range_det_e : 1; + RK_U32 av1_fgs_en : 1; + RK_U32 reserve2 : 7; + RK_U32 line_irq_en : 1; + RK_U32 out_cbcr_swap : 1; + RK_U32 fbc_force_uncompress : 1; + RK_U32 fbc_sparse_mode : 1; + RK_U32 reserve3 : 12; + } reg9; + + struct { + RK_U32 strmd_auto_gating_e : 1; + RK_U32 inter_auto_gating_e : 1; + RK_U32 intra_auto_gating_e : 1; + RK_U32 transd_auto_gating_e : 1; + RK_U32 recon_auto_gating_e : 1; + RK_U32 filterd_auto_gating_e : 1; + RK_U32 bus_auto_gating_e : 1; + RK_U32 ctrl_auto_gating_e : 1; + RK_U32 rcb_auto_gating_e : 1; + RK_U32 err_prc_auto_gating_e : 1; + RK_U32 reserve0 : 22; + } reg10; + + struct { + RK_U32 reserve0 : 9; + RK_U32 dec_timeout_dis : 1; + RK_U32 reserve1 : 22; + } reg11; + + struct { + RK_U32 reserve0 : 7; + RK_U32 cache_hash_mask : 25; + } reg12; + + /* SWREG13_CORE_TIMEOUT_THRESHOLD */ + RK_U32 reg13_core_timeout_threshold; + + struct { + RK_U32 dec_line_irq_step : 16; + RK_U32 dec_line_offset_y_st : 16; + } reg14; + + /* copy from llp, media group add */ + struct { + RK_U32 rkvdec_frame_rdy_sta : 1; + RK_U32 rkvdec_strm_error_sta : 1; + RK_U32 rkvdec_core_timeout_sta : 1; + RK_U32 rkvdec_ip_timeout_sta : 1; + RK_U32 rkvdec_bus_error_sta : 1; + RK_U32 rkvdec_buffer_empty_sta : 1; + RK_U32 rkvdec_colmv_ref_error_sta : 1; + RK_U32 rkvdec_error_spread_sta : 1; + RK_U32 create_core_timeout_sta : 1; + RK_U32 wlast_miss_match_sta : 1; + RK_U32 rkvdec_core_rst_rdy_sta : 1; + RK_U32 rkvdec_ip_rst_rdy_sta : 1; + RK_U32 force_busidle_rdy_sta : 1; + RK_U32 ltb_pause_rdy_sta : 1; + RK_U32 ltb_end_flag : 1; + RK_U32 unsupport_decmode_error_sta : 1; + RK_U32 wmask_bits : 15; + RK_U32 reserve0 : 1; + } reg15; + + struct { + RK_U32 error_proc_disable : 1; + RK_U32 reserve0 : 7; + RK_U32 error_spread_disable : 1; + RK_U32 reserve1 : 15; + RK_U32 roi_error_ctu_cal_en : 1; + RK_U32 reserve2 : 7; + } reg16; + + struct { + RK_U32 roi_x_ctu_offset_st : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_st : 12; + RK_U32 reserve1 : 4; + } reg17; + + struct { + RK_U32 roi_x_ctu_offset_end : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_end : 12; + RK_U32 reserve1 : 4; + } reg18; + + struct { + RK_U32 avs2_ref_error_field : 1; + RK_U32 avs2_ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve0 : 28; + } reg19; + + /* SWREG20_CABAC_ERROR_EN_LOWBITS */ + RK_U32 reg20_cabac_error_en_lowbits; + + /* SWREG21_CABAC_ERROR_EN_HIGHBITS */ + RK_U32 reg21_cabac_error_en_highbits; + + RK_U32 reserve_reg22; + + struct { + RK_U32 fill_y : 10; + RK_U32 fill_u : 10; + RK_U32 fill_v : 10; + RK_U32 reserve0 : 2; + } reg23; + + RK_U32 reserve_reg24_26[3]; + + struct { + RK_U32 reserve0 : 4; + RK_U32 ctu_align_wr_en : 1; + RK_U32 reserve1 : 27; + } reg27; + + struct { + RK_U32 axi_perf_work_e : 1; + RK_U32 reserve0 : 2; + RK_U32 axi_cnt_type : 1; + RK_U32 rd_latency_id : 8; + RK_U32 reserve1 : 4; + RK_U32 rd_latency_thr : 12; + RK_U32 reserve2 : 4; + } reg28; + + struct { + RK_U32 addr_align_type : 2; + RK_U32 ar_cnt_id_type : 1; + RK_U32 aw_cnt_id_type : 1; + RK_U32 ar_count_id : 8; + RK_U32 reserve0 : 4; + RK_U32 aw_count_id : 8; + RK_U32 rd_band_width_mode : 1; + RK_U32 reserve1 : 7; + } reg29; + + struct { + RK_U32 axi_wr_qos_level : 4; + RK_U32 reserve0 : 4; + RK_U32 axi_wr_qos : 4; + RK_U32 reserve1 : 4; + RK_U32 axi_rd_qos_level : 4; + RK_U32 reserve2 : 4; + RK_U32 axi_rd_qos : 4; + RK_U32 reserve3 : 4; + } reg30; +} Vdpu383CtrlReg; + +typedef struct Vdpu383RegCommParas_t { + /* SWREG64_H26X_PARA */ + RK_U32 reg64_unused_bits; + + /* SWREG65_STREAM_PARAM_SET */ + RK_U32 reg65_strm_start_bit; + + /* SWREG66_STREAM_LEN */ + RK_U32 reg66_stream_len; + + /* SWREG67_GLOBAL_LEN */ + RK_U32 reg67_global_len; + + /* SWREG68_HOR_STRIDE */ + RK_U32 reg68_hor_virstride; + + /* SWREG69_RASTER_UV_HOR_STRIDE */ + RK_U32 reg69_raster_uv_hor_virstride; + + /* SWREG70_Y_STRIDE */ + RK_U32 reg70_y_virstride; + + /* SWREG71_SCL_Y_HOR_VIRSTRIDE */ + RK_U32 reg71_scl_ref_hor_virstride; + + /* SWREG72_SCL_UV_HOR_VIRSTRIDE */ + RK_U32 reg72_scl_ref_raster_uv_hor_virstride; + + /* SWREG73_SCL_Y_VIRSTRIDE */ + RK_U32 reg73_scl_ref_virstride; + + /* SWREG74_FGS_Y_HOR_VIRSTRIDE */ + RK_U32 reg74_fgs_ref_hor_virstride; + + RK_U32 reserve_reg75_79[5]; + + /* SWREG80_ERROR_REF_Y_HOR_VIRSTRIDE */ + RK_U32 reg80_error_ref_hor_virstride; + + /* SWREG81_ERROR_REF_UV_HOR_VIRSTRIDE */ + RK_U32 reg81_error_ref_raster_uv_hor_virstride; + + /* SWREG82_ERROR_REF_Y_VIRSTRIDE */ + RK_U32 reg82_error_ref_virstride; + + union { + struct { + RK_U32 hor_y_stride; + RK_U32 hor_uv_stride; + RK_U32 y_stride; + } ref_stride[VDPU38X_REG_MAX_REF_CNT]; + struct { + RK_U32 reg83_ref0_hor_virstride; + RK_U32 reg84_ref0_raster_uv_hor_virstride; + RK_U32 reg85_ref0_virstride; + RK_U32 reg86_ref1_hor_virstride; + RK_U32 reg87_ref1_raster_uv_hor_virstride; + RK_U32 reg88_ref1_virstride; + RK_U32 reg89_ref2_hor_virstride; + RK_U32 reg90_ref2_raster_uv_hor_virstride; + RK_U32 reg91_ref2_virstride; + RK_U32 reg92_ref3_hor_virstride; + RK_U32 reg93_ref3_raster_uv_hor_virstride; + RK_U32 reg94_ref3_virstride; + RK_U32 reg95_ref4_hor_virstride; + RK_U32 reg96_ref4_raster_uv_hor_virstride; + RK_U32 reg97_ref4_virstride; + RK_U32 reg98_ref5_hor_virstride; + RK_U32 reg99_ref5_raster_uv_hor_virstride; + RK_U32 reg100_ref5_virstride; + RK_U32 reg101_ref6_hor_virstride; + RK_U32 reg102_ref6_raster_uv_hor_virstride; + RK_U32 reg103_ref6_virstride; + RK_U32 reg104_ref7_hor_virstride; + RK_U32 reg105_ref7_raster_uv_hor_virstride; + RK_U32 reg106_ref7_virstride; + }; + }; +} Vdpu383RegCommParas; + +typedef struct Vdpu383RegCommonAddr_t { + /* SWREG128_STRM_BASE */ + RK_U32 reg128_strm_base; + + /* SWREG129_RPS_BASE */ + RK_U32 reg129_rps_base; + + /* SWREG130_CABACTBL_BASE */ + RK_U32 reg130_cabactbl_base; + + /* SWREG131_GBL_BASE */ + RK_U32 reg131_gbl_base; + + /* SWREG132_SCANLIST_ADDR */ + RK_U32 reg132_scanlist_addr; + + /* SWREG133_SCL_BASE */ + RK_U32 reg133_scale_down_base; + + /* SWREG134_FGS_BASE */ + RK_U32 reg134_fgs_base; + + RK_U32 reserve_reg135_139[5]; + + union { + Vdpu38xRcbRegSet rcb_regs; + struct { + RK_U32 reg140_rcb_strmd_row_offset; + RK_U32 reg141_rcb_strmd_row_len; + RK_U32 reg142_rcb_strmd_tile_row_offset; + RK_U32 reg143_rcb_strmd_tile_row_len; + RK_U32 reg144_rcb_inter_row_offset; + RK_U32 reg145_rcb_inter_row_len; + RK_U32 reg146_rcb_inter_tile_row_offset; + RK_U32 reg147_rcb_inter_tile_row_len; + RK_U32 reg148_rcb_intra_row_offset; + RK_U32 reg149_rcb_intra_row_len; + RK_U32 reg150_rcb_intra_tile_row_offset; + RK_U32 reg151_rcb_intra_tile_row_len; + RK_U32 reg152_rcb_filterd_row_offset; + RK_U32 reg153_rcb_filterd_row_len; + RK_U32 reg154_rcb_filterd_protect_row_offset; + RK_U32 reg155_rcb_filterd_protect_row_len; + RK_U32 reg156_rcb_filterd_tile_row_offset; + RK_U32 reg157_rcb_filterd_tile_row_len; + RK_U32 reg158_rcb_filterd_tile_col_offset; + RK_U32 reg159_rcb_filterd_tile_col_len; + RK_U32 reg160_rcb_filterd_av1_upscale_tile_col_offset; + RK_U32 reg161_rcb_filterd_av1_upscale_tile_col_len; + }; + }; + + RK_U32 reserve_reg162_167[6]; + + /* SWREG168_DECOUT_BASE */ + RK_U32 reg168_decout_base; + + /* SWREG169_ERROR_REF_BASE */ + RK_U32 reg169_error_ref_base; + + /* SWREG170_185_REF_BASE */ + union { + RK_U32 reg170_185_ref_base[16]; + /* vp9 */ + struct { + RK_U32 reg170_180[11]; + RK_U32 reg181_segidlast_base; + RK_U32 reg182_segidcur_base; + RK_U32 reg183_kfprob_base; + RK_U32 reg184_lastprob_base; + RK_U32 reg185_updateprob_base; + }; + /* av1 */ + struct { + RK_U32 reg170_av1_last_base; + RK_U32 reg171_av1golden_base; + RK_U32 reg172_av1alfter_base; + RK_U32 reg173_refer3_base; + RK_U32 reg174_refer4_base; + RK_U32 reg175_refer5_base; + RK_U32 reg176_refer6_base; + RK_U32 reg177_refer7_base; + RK_U32 reg178_av1_coef_rd_base; + RK_U32 reg179_av1_coef_wr_base; + RK_U32 reg180_refer10_base; + RK_U32 reg181_av1_rd_segid_base; + RK_U32 reg182_av1_wr_segid_base; + RK_U32 reg183_kf_prob_base; + RK_U32 reg184_av1_noncoef_rd_base; + RK_U32 reg185_av1_noncoef_wr_base; + }; + }; + + RK_U32 reserve_reg186_191[6]; + + /* SWREG192_PAYLOAD_ST_CUR_BASE */ + RK_U32 reg192_payload_st_cur_base; + + /* SWREG193_FBC_PAYLOAD_OFFSET */ + RK_U32 reg193_fbc_payload_offset; + + /* SWREG194_PAYLOAD_ST_ERROR_REF_BASE */ + RK_U32 reg194_payload_st_error_ref_base; + + /* SWREG195_210_PAYLOAD_ST_REF0_BASE */ + RK_U32 reg195_210_payload_st_ref_base[16]; + + RK_U32 reserve_reg211_215[5]; + + /* SWREG216_COLMV_CUR_BASE */ + RK_U32 reg216_colmv_cur_base; + + /* SWREG217_232_COLMV_REF0_BASE */ + RK_U32 reg217_232_colmv_ref_base[16]; +} Vdpu383RegCommonAddr; + +typedef struct Vdpu383RegStatistic_t { + struct { + RK_U32 reserve0 : 24; + RK_U32 rkvdec_bus_idle_flag : 1; + RK_U32 reserve1 : 7; + } reg320; + + RK_U32 reserve_reg321; + + /* SWREG322_PERF_MONITOR */ + RK_U32 reg322_perf_rd_max_latency_num; + + /* SWREG323_PERF_MONITOR */ + RK_U32 reg323_perf_rd_latency_samp_num; + + /* SWREG324_PERF_MONITOR */ + RK_U32 reg324_perf_rd_latency_acc_sum; + + /* SWREG325_PERF_MONITOR */ + RK_U32 reg325_perf_rd_axi_total_byte; + + /* SWREG326_PERF_MONITOR */ + RK_U32 reg326_perf_wr_axi_total_bytes; + + /* SWREG327_PERF_MONITOR */ + RK_U32 reg327_perf_working_cnt; + + RK_U32 reserve_reg328_336[9]; + + /* SWREG337_REFLIST_IDX_USED */ + RK_U32 reg337_inter_sw_reflst_idx_use; + + RK_U32 reserve_reg338_348[11]; + + /* SWREG349_PAYLOAD_CNT */ + RK_U32 reg349_filterd_payload_total_cnt; + + struct { + RK_U32 filterd_report_offsety : 16; + RK_U32 filterd_report_offsetx : 16; + } reg350; + + struct { + RK_U32 filterd_max_y : 10; + RK_U32 filterd_max_u : 10; + RK_U32 filterd_max_v : 10; + RK_U32 reserve0 : 2; + } reg351; + + struct { + RK_U32 filterd_min_y : 10; + RK_U32 filterd_min_u : 10; + RK_U32 filterd_min_v : 10; + RK_U32 reserve0 : 2; + } reg352; + + /* SWREG353_WR_LINE_NUM */ + RK_U32 reg353_filterd_line_irq_offsety; + + RK_U32 reserve_reg354_355[2]; + + struct { + RK_U32 rcb_rd_sum_chk : 8; + RK_U32 rcb_wr_sum_chk : 8; + RK_U32 reserve0 : 16; + } reg356; + + RK_U32 reserve_reg357; + + struct { + RK_U32 error_ctu_num : 24; + RK_U32 roi_error_ctu_num_lowbit : 8; + } reg358; + + /* SWREG359_ERR_CTU_NUM1 */ + RK_U32 reg359_roi_error_ctu_num_highbit; + +} Vdpu383RegStatistic; + +typedef struct Vdpu383RegLlp_t { + struct { + RK_U32 llp_mmu_zap_cache_dis : 1; + RK_U32 reserve0 : 15; + RK_U32 core_work_mode : 1; + RK_U32 ccu_core_work_mode : 1; + RK_U32 reserve1 : 3; + RK_U32 ltb_pause_flag : 1; + RK_U32 reserve2 : 10; + } reg0; + + struct { + RK_U32 reserve0 : 4; + RK_U32 reg_cfg_addr : 28; + } reg1; + + struct { + RK_U32 pre_frame_num : 30; + RK_U32 reserve0 : 1; + RK_U32 link_mode : 1; + } reg2; + + /* SWREG3_CONFIG_DONE */ + RK_U32 reg3_done; + + /* SWREG4_DECODERED_NUM */ + RK_U32 reg4_num; + + /* SWREG5_DEC_TOTAL_NUM */ + RK_U32 reg5_total_num; + + /* SWREG6_LINK_MODE_EN */ + RK_U32 reg6_mode_en; + + /* SWREG7_SKIP_NUM */ + RK_U32 reg7_num; + + /* SWREG8_CUR_LTB_IDX */ + RK_U32 reg8_ltb_idx; + + RK_U32 reserve_reg9_15[7]; + + /* SWREG16_DEC_E */ + RK_U32 reg16_dec_e; + + /* SWREG17_SOFT_RST */ + RK_U32 reg17_rkvdec_ip_rst_p; + + struct { + RK_U32 rkvdec_irq : 1; + RK_U32 rkvdec_line_irq : 1; + RK_U32 reserve0 : 14; + RK_U32 wmask : 2; + RK_U32 reserve1 : 14; + } reg18; + + struct { + RK_U32 rkvdec_frame_rdy_sta : 1; + RK_U32 rkvdec_strm_error_sta : 1; + RK_U32 rkvdec_core_timeout_sta : 1; + RK_U32 rkvdec_ip_timeout_sta : 1; + RK_U32 rkvdec_bus_error_sta : 1; + RK_U32 rkvdec_buffer_empty_sta : 1; + RK_U32 rkvdec_colmv_ref_error_sta : 1; + RK_U32 rkvdec_error_spread_sta : 1; + RK_U32 create_core_timeout_sta : 1; + RK_U32 wlast_miss_match_sta : 1; + RK_U32 rkvdec_core_rst_rdy_sta : 1; + RK_U32 rkvdec_ip_rst_rdy_sta : 1; + RK_U32 force_busidle_rdy_sta : 1; + RK_U32 ltb_pause_rdy_sta : 1; + RK_U32 ltb_end_flag : 1; + RK_U32 unsupport_decmode_error_sta : 1; + RK_U32 wmask_bits : 15; + RK_U32 reserve0 : 1; + } reg19; + + RK_U32 reserve_reg20; + + /* SWREG21_IP_TIMEOUT_THRESHOD */ + RK_U32 reg21_ip_timeout_threshold; + + struct { + RK_U32 ip_timeout_pause_flag : 1; + RK_U32 reserve0 : 3; + RK_U32 auto_reset_dis : 1; + RK_U32 reserve1 : 3; + RK_U32 force_busidle_req_flag : 1; + RK_U32 reserve2 : 3; + RK_U32 bus_clkgate_dis : 1; + RK_U32 ctrl_clkgate_dis : 1; + RK_U32 reserve3 : 1; + RK_U32 irq_dis : 1; + RK_U32 wid_reorder_dis : 1; + RK_U32 reserve4 : 7; + RK_U32 clk_cru_mode : 2; + RK_U32 reserve5 : 5; + RK_U32 mmu_sel : 1; + } reg22; + + struct { + RK_U32 endian : 1; + RK_U32 swap32_e : 1; + RK_U32 swap64_e : 1; + RK_U32 str_endian : 1; + RK_U32 str_swap32_e : 1; + RK_U32 str_swap64_e : 1; + RK_U32 reserve0 : 26; + } reg23; + + /* SWREG24_EXTRA_STRM_BASE */ + RK_U32 reg24_extra_stream_base; + + /* SWREG25_EXTRA_STRM_LEN */ + RK_U32 reg25_extra_stream_len; + + /* SWREG26_EXTRA_STRM_PARA_SET */ + RK_U32 reg26_extra_strm_start_bit; + + /* SWREG27_BUF_EMPTY_RESTART */ + RK_U32 reg27_buf_emtpy_restart_p; + + /* SWREG28_RCB_BASE */ + RK_U32 reg28_rcb_base; + +} Vdpu383RegLlp; + +typedef struct Vdpu383RegSet_t { + Vdpu383RegVersion reg_version; /* 0 */ + Vdpu383CtrlReg ctrl_regs; /* 8-30 */ + Vdpu383RegCommParas comm_paras; /* 64-74, 80-106 */ + Vdpu383RegCommonAddr comm_addrs; /* 128-134, 140-161, 168-185, 192-210, 216-232 */ + Vdpu383RegStatistic statistic_regs; /* 320-359 */ +} Vdpu383RegSet; + + +#ifdef __cplusplus +extern "C" { +#endif + +void vdpu383_init_ctrl_regs(Vdpu383RegSet *regs, MppCodingType codec_t); +void vdpu383_setup_statistic(Vdpu383CtrlReg *com); +void vdpu383_setup_down_scale(MppFrame frame, MppDev dev, Vdpu383CtrlReg *com, void* comParas); +void vdpu383_update_thumbnail_frame_info(MppFrame frame); + +#ifdef DUMP_VDPU383_DATAS +extern RK_U32 dump_cur_frame; +extern char dump_cur_dir[128]; +extern char dump_cur_fname_path[512]; + +MPP_RET flip_string(char *str); +MPP_RET dump_data_to_file(char *fname_path, void *data, RK_U32 data_bit_size, + RK_U32 line_bits, RK_U32 big_end); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* VDPU383_COM_H */ diff --git a/mpp/hal/rkdec/inc/vdpu384a_com.h b/mpp/hal/rkdec/inc/vdpu384a_com.h new file mode 100644 index 000000000..5e27a99ff --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu384a_com.h @@ -0,0 +1,687 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPU384A_COM_H +#define VDPU384A_COM_H + +#include "mpp_device.h" +#include "mpp_buf_slot.h" +#include "vdpu_com.h" + +// #define DUMP_VDPU384A_DATAS + +typedef struct Vdpu384aRegVersion_t { + /* SWREG0_ID */ + struct { + RK_U32 minor_ver : 8; + RK_U32 major_ver : 8; + RK_U32 prod_num : 16; + } reg0; + +} Vdpu384aRegVersion; + +typedef struct Vdpu384aCtrlReg_t { + /* SWREG8_DEC_MODE */ + RK_U32 reg8_dec_mode; + + /* SWREG9_IMPORTANT_EN */ + struct { + RK_U32 dpb_output_dis : 1; + /* + * 0: dpb data use rkfbc64x4 channel + * 1: dpb data user main pp channel + * 2: dpb data use scl down channel + */ + RK_U32 dpb_data_sel : 2; + RK_U32 reserve0 : 1; + RK_U32 low_latency_en : 1; + RK_U32 scale_down_en : 1; + RK_U32 reserve1 : 1; + RK_U32 pix_range_det_e : 1; + RK_U32 av1_fgs_en : 1; + RK_U32 reserve2 : 3; + RK_U32 scale_down_ratio : 1; + RK_U32 scale_down_10bitto8bit_en : 1; + RK_U32 line_irq_en : 3; + RK_U32 out_cbcr_swap : 1; + RK_U32 dpb_rkfbc_force_uncompress : 1; + RK_U32 dpb_rkfbc_sparse_mode : 1; + RK_U32 reserve3 : 1; + RK_U32 pp_m_fbc32x8_force_uncompress : 1; + RK_U32 pp_m_fbc32x8_sparse_mode : 1; + RK_U32 inter_max_mv_detect_en : 1; + /* + * 0:disable pp main channel output + * 1:pp main channel output raster picture to ddr. + * 2:pp main channel output tile4x4 picture to ddr. + * 3:pp main channel output afbc32x8 picture to ddr. + */ + RK_U32 pp_m_output_mode : 2; + RK_U32 reserve4 : 6; + } reg9; + + /* SWREG10_BLOCK_GATING_EN */ + struct { + RK_U32 strmd_auto_gating_e : 1; + RK_U32 inter_auto_gating_e : 1; + RK_U32 intra_auto_gating_e : 1; + RK_U32 transd_auto_gating_e : 1; + RK_U32 recon_auto_gating_e : 1; + RK_U32 filterd_auto_gating_e : 1; + RK_U32 bus_auto_gating_e : 1; + RK_U32 ctrl_auto_gating_e : 1; + RK_U32 rcb_auto_gating_e : 1; + RK_U32 err_prc_auto_gating_e : 1; + RK_U32 reserve0 : 22; + } reg10; + + /* SWREG11_CFG_PARA */ + struct { + RK_U32 frame_irq_dis : 1; + RK_U32 reserve0 : 8; + RK_U32 dec_timeout_dis : 1; + RK_U32 reserve1 : 6; + RK_U32 rd_outstanding : 8; + RK_U32 wr_outstanding : 8; + } reg11; + + /* SWREG12_CACHE_HASH_MASK */ + struct { + RK_U32 reserve0 : 7; + RK_U32 cache_hash_mask : 25; + } reg12; + + /* SWREG13_CORE_TIMEOUT_THRESHOLD */ + RK_U32 reg13_core_timeout_threshold; + + /* SWREG14_LINE_IRQ_CTRL */ + struct { + RK_U32 dec_line_irq_step : 16; + RK_U32 dec_line_offset_y_st : 16; + } reg14; + + /* copy from llp, media group add */ + /* SWREG15_IRQ_STA */ + struct { + RK_U32 rkvdec_frame_rdy_sta : 1; + RK_U32 rkvdec_strm_error_sta : 1; + RK_U32 rkvdec_core_timeout_sta : 1; + RK_U32 rkvdec_ip_timeout_sta : 1; + RK_U32 rkvdec_bus_error_sta : 1; + RK_U32 rkvdec_buffer_empty_sta : 1; + RK_U32 rkvdec_colmv_ref_error_sta : 1; + RK_U32 rkvdec_error_spread_sta : 1; + RK_U32 create_core_timeout_sta : 1; + RK_U32 wlast_miss_match_sta : 1; + RK_U32 rkvdec_core_rst_rdy_sta : 1; + RK_U32 rkvdec_ip_rst_rdy_sta : 1; + RK_U32 force_busidle_rdy_sta : 1; + RK_U32 ltb_pause_rdy_sta : 1; + RK_U32 ltb_end_flag : 1; + RK_U32 unsupport_decmode_error_sta : 1; + RK_U32 wmask_bits : 15; + RK_U32 reserve0 : 1; + } reg15; + + /* SWREG16_ERROR_CTRL_SET */ + struct { + RK_U32 error_proc_disable : 1; + RK_U32 reserve0 : 3; + RK_U32 error_proc_mode : 1; + RK_U32 reserve1 : 3; + RK_U32 error_spread_disable : 1; + RK_U32 error_fill_mode : 1; + RK_U32 reserve2 : 14; + RK_U32 roi_error_ctu_cal_en : 1; + RK_U32 reserve3 : 7; + } reg16; + + /* SWREG17_ERR_ROI_CTU_OFFSET_START */ + struct { + RK_U32 roi_x_ctu_offset_st : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_st : 12; + RK_U32 reserve1 : 4; + } reg17; + + /* SWREG18_ERR_ROI_CTU_OFFSET_END */ + struct { + RK_U32 roi_x_ctu_offset_end : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_end : 12; + RK_U32 reserve1 : 4; + } reg18; + + /* SWREG19_ERROR_REF_INFO */ + struct { + RK_U32 avs2_ref_error_field : 1; + RK_U32 avs2_ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve0 : 28; + } reg19; + + /* SWREG20_CABAC_ERROR_EN_LOWBITS */ + RK_U32 reg20_cabac_error_en_lowbits; + + /* SWREG21_CABAC_ERROR_EN_HIGHBITS */ + RK_U32 reg21_cabac_error_en_highbits; + + RK_U32 reserve_reg22; + + /* SWREG23_INVALID_PIXEL_FILL */ + struct { + RK_U32 fill_y : 10; + RK_U32 fill_u : 10; + RK_U32 fill_v : 10; + RK_U32 reserve0 : 2; + } reg23; + + RK_U32 reserve_reg24_27[4]; + + /* SWREG28_DEBUG_PERF_LATENCY_CTRL0 */ + struct { + RK_U32 axi_perf_work_e : 1; + RK_U32 reserve0 : 2; + RK_U32 axi_cnt_type : 1; + RK_U32 rd_latency_id : 8; + RK_U32 reserve1 : 4; + RK_U32 rd_latency_thr : 12; + RK_U32 reserve2 : 4; + } reg28; + + /* SWREG29_DEBUG_PERF_LATENCY_CTRL1 */ + struct { + RK_U32 addr_align_type : 2; + RK_U32 ar_cnt_id_type : 1; + RK_U32 aw_cnt_id_type : 1; + RK_U32 ar_count_id : 8; + RK_U32 reserve0 : 4; + RK_U32 aw_count_id : 8; + RK_U32 rd_band_width_mode : 1; + RK_U32 reserve1 : 7; + } reg29; + + /* SWREG30_QOS_CTRL */ + struct { + RK_U32 axi_wr_qos_level : 4; + RK_U32 reserve0 : 4; + RK_U32 axi_wr_qos : 4; + RK_U32 reserve1 : 4; + RK_U32 axi_rd_qos_level : 4; + RK_U32 reserve2 : 4; + RK_U32 axi_rd_qos : 4; + RK_U32 reserve3 : 4; + } reg30; + +} Vdpu384aCtrlReg; + +typedef struct Vdpu384aRegCommParas_t { + /* SWREG64_H26X_PARA */ + RK_U32 reg64_unused_bits; + + /* SWREG65_STREAM_PARAM_SET */ + RK_U32 reg65_strm_start_bit; + + /* SWREG66_STREAM_LEN */ + RK_U32 reg66_stream_len; + + /* SWREG67_GLOBAL_LEN */ + RK_U32 reg67_global_len; + + /* SWREG68_DPB_HOR_STRIDE */ + RK_U32 reg68_dpb_hor_virstride; + + RK_U32 reserve_reg69_70[2]; + + /* SWREG71_SCL_Y_HOR_VIRSTRIDE */ + RK_U32 reg71_scl_ref_hor_virstride; + + /* SWREG72_SCL_UV_HOR_VIRSTRIDE */ + RK_U32 reg72_scl_ref_raster_uv_hor_virstride; + + /* SWREG73_SCL_Y_VIRSTRIDE */ + RK_U32 reg73_scl_ref_virstride; + + /* SWREG74_FGS_Y_HOR_VIRSTRIDE */ + RK_U32 reg74_fgs_ref_hor_virstride; + + RK_U32 reserve_reg75_76[2]; + + /* SWREG77_HEAD_HOR_STRIDE */ + RK_U32 reg77_pp_m_hor_stride; + + /* SWREG78_PP_M_RASTER_UV_HOR_STRIDE */ + RK_U32 reg78_pp_m_uv_hor_stride; + + /* SWREG79_PP_M_Y_STRIDE */ + RK_U32 reg79_pp_m_y_virstride; + + /* SWREG80_ERROR_REF_Y_HOR_VIRSTRIDE */ + RK_U32 reg80_error_ref_hor_virstride; + + /* SWREG81_ERROR_REF_UV_HOR_VIRSTRIDE */ + RK_U32 reg81_error_ref_raster_uv_hor_virstride; + + /* SWREG82_ERROR_REF_Y_VIRSTRIDE */ + RK_U32 reg82_error_ref_virstride; + + /* SWREG83_REF0_Y_HOR_VIRSTRIDE */ + RK_U32 reg83_ref0_hor_virstride; + + /* SWREG84_REF0_UV_HOR_VIRSTRIDE */ + RK_U32 reg84_ref0_raster_uv_hor_virstride; + + /* SWREG85_REF0_Y_VIRSTRIDE */ + RK_U32 reg85_ref0_virstride; + + /* SWREG86_REF1_Y_HOR_VIRSTRIDE */ + RK_U32 reg86_ref1_hor_virstride; + + /* SWREG87_REF1_UV_HOR_VIRSTRIDE */ + RK_U32 reg87_ref1_raster_uv_hor_virstride; + + /* SWREG88_REF1_Y_VIRSTRIDE */ + RK_U32 reg88_ref1_virstride; + + /* SWREG89_REF2_Y_HOR_VIRSTRIDE */ + RK_U32 reg89_ref2_hor_virstride; + + /* SWREG90_REF2_UV_HOR_VIRSTRIDE */ + RK_U32 reg90_ref2_raster_uv_hor_virstride; + + /* SWREG91_REF2_Y_VIRSTRIDE */ + RK_U32 reg91_ref2_virstride; + + /* SWREG92_REF3_Y_HOR_VIRSTRIDE */ + RK_U32 reg92_ref3_hor_virstride; + + /* SWREG93_REF3_UV_HOR_VIRSTRIDE */ + RK_U32 reg93_ref3_raster_uv_hor_virstride; + + /* SWREG94_REF3_Y_VIRSTRIDE */ + RK_U32 reg94_ref3_virstride; + + /* SWREG95_REF4_Y_HOR_VIRSTRIDE */ + RK_U32 reg95_ref4_hor_virstride; + + /* SWREG96_REF4_UV_HOR_VIRSTRIDE */ + RK_U32 reg96_ref4_raster_uv_hor_virstride; + + /* SWREG97_REF4_Y_VIRSTRIDE */ + RK_U32 reg97_ref4_virstride; + + /* SWREG98_REF5_Y_HOR_VIRSTRIDE */ + RK_U32 reg98_ref5_hor_virstride; + + /* SWREG99_REF5_UV_HOR_VIRSTRIDE */ + RK_U32 reg99_ref5_raster_uv_hor_virstride; + + /* SWREG100_REF5_Y_VIRSTRIDE */ + RK_U32 reg100_ref5_virstride; + + /* SWREG101_REF6_Y_HOR_VIRSTRIDE */ + RK_U32 reg101_ref6_hor_virstride; + + /* SWREG102_REF6_UV_HOR_VIRSTRIDE */ + RK_U32 reg102_ref6_raster_uv_hor_virstride; + + /* SWREG103_REF6_Y_VIRSTRIDE */ + RK_U32 reg103_ref6_virstride; + + /* SWREG104_REF7_Y_HOR_VIRSTRIDE */ + RK_U32 reg104_ref7_hor_virstride; + + /* SWREG105_REF7_UV_HOR_VIRSTRIDE */ + RK_U32 reg105_ref7_raster_uv_hor_virstride; + + /* SWREG106_REF7_Y_VIRSTRIDE */ + RK_U32 reg106_ref7_virstride; + +} Vdpu384aRegCommParas; + +typedef struct Vdpu384aRegCommonAddr_t { + /* SWREG128_STRM_BASE */ + RK_U32 reg128_strm_base; + + /* SWREG129_STREAM_BUF_ST_BASE */ + RK_U32 reg129_stream_buf_st_base; + + /* SWREG130_STREAM_BUF_END_BASE */ + RK_U32 reg130_stream_buf_end_base; + + /* SWREG131_GBL_BASE */ + RK_U32 reg131_gbl_base; + + /* SWREG132_SCANLIST_ADDR */ + RK_U32 reg132_scanlist_addr; + + /* SWREG133_SCL_BASE */ + RK_U32 reg133_scale_down_base; + + /* SWREG134_FGS_BASE */ + RK_U32 reg134_fgs_base; + + /* SWREG135_PP_M_DECOUT_BASE */ + RK_U32 reg135_pp_m_decout_base; + + /* SWREG136_PP_M_FBC32x8_PAYLOAD_OFFSET */ + RK_U32 reg136_pp_m_fbc32x8_payload_offset; + + RK_U32 reserve_reg137_139[3]; + + union { + Vdpu38xRcbRegSet rcb_regs; + struct { + RK_U32 reg140_rcb_strmd_row_offset; + RK_U32 reg141_rcb_strmd_row_len; + RK_U32 reg142_rcb_strmd_tile_row_offset; + RK_U32 reg143_rcb_strmd_tile_row_len; + RK_U32 reg144_rcb_inter_row_offset; + RK_U32 reg145_rcb_inter_row_len; + RK_U32 reg146_rcb_inter_tile_row_offset; + RK_U32 reg147_rcb_inter_tile_row_len; + RK_U32 reg148_rcb_intra_row_offset; + RK_U32 reg149_rcb_intra_row_len; + RK_U32 reg150_rcb_intra_tile_row_offset; + RK_U32 reg151_rcb_intra_tile_row_len; + RK_U32 reg152_rcb_filterd_row_offset; + RK_U32 reg153_rcb_filterd_row_len; + RK_U32 reg154_rcb_filterd_protect_row_offset; // deleted in vdpu384a + RK_U32 reg155_rcb_filterd_protect_row_len; // deleted in vdpu384a + RK_U32 reg156_rcb_filterd_tile_row_offset; + RK_U32 reg157_rcb_filterd_tile_row_len; + RK_U32 reg158_rcb_filterd_tile_col_offset; + RK_U32 reg159_rcb_filterd_tile_col_len; + RK_U32 reg160_rcb_filterd_av1_upscale_tile_col_offset; + RK_U32 reg161_rcb_filterd_av1_upscale_tile_col_len; + }; + }; + + RK_U32 reserve_reg162_167[6]; + + /* SWREG168_DECOUT_BASE */ + RK_U32 reg168_dpb_decout_base; + + /* SWREG169_ERROR_REF_BASE */ + RK_U32 reg169_error_ref_base; + + /* SWREG170_185_REF0_15_BASE */ + RK_U32 reg170_185_ref_base[16]; + + RK_U32 reserve_reg186_191[6]; + + /* SWREG192_PAYLOAD_ST_CUR_BASE */ + RK_U32 reg192_dpb_payload64x4_st_cur_base; + + /* SWREG193_FBC_PAYLOAD_OFFSET */ + RK_U32 reg193_dpb_fbc64x4_payload_offset; + + /* SWREG194_PAYLOAD_ST_ERROR_REF_BASE */ + RK_U32 reg194_payload_st_error_ref_base; + + /* SWREG195_210_PAYLOAD_ST_REF0_15_BASE */ + RK_U32 reg195_210_payload_st_ref_base[16]; + + RK_U32 reserve_reg211_215[5]; + + /* SWREG216_COLMV_CUR_BASE */ + RK_U32 reg216_colmv_cur_base; + + /* SWREG217_232_COLMV_REF0_15_BASE */ + RK_U32 reg217_232_colmv_ref_base[16]; +} Vdpu384aRegCommonAddr; + +typedef struct Vdpu384aRegStatistic_t { + /* SWREG256_IDLE_FLAG */ + struct { + RK_U32 reserve0 : 24; + RK_U32 rkvdec_bus_idle_flag : 1; + RK_U32 reserve1 : 7; + } reg256; + + RK_U32 reserve_reg257; + + /* SWREG258_PERF_MONITOR */ + RK_U32 reg258_perf_rd_max_latency_num; + + /* SWREG259_PERF_MONITOR */ + RK_U32 reg259_perf_rd_latency_samp_num; + + /* SWREG260_PERF_MONITOR */ + RK_U32 reg260_perf_rd_latency_acc_sum; + + /* SWREG261_PERF_MONITOR */ + RK_U32 reg261_perf_rd_axi_total_byte; + + /* SWREG262_PERF_MONITOR */ + RK_U32 reg262_perf_wr_axi_total_bytes; + + /* SWREG263_PERF_MONITOR */ + RK_U32 reg263_perf_working_cnt; + + RK_U32 reserve_reg264_272[9]; + + /* SWREG273_REFLIST_IDX_USED */ + RK_U32 reg273_inter_sw_reflst_idx_use; + + RK_U32 reserve_reg274_284[11]; + + /* SWREG285_PAYLOAD_CNT */ + RK_U32 reg285_filterd_payload_total_cnt; + + /* SWREG286_WR_OFFSET */ + struct { + RK_U32 filterd_report_offsety : 16; + RK_U32 filterd_report_offsetx : 16; + } reg286; + + /* SWREG287_MAX_PIX */ + struct { + RK_U32 filterd_max_y : 10; + RK_U32 filterd_max_u : 10; + RK_U32 filterd_max_v : 10; + RK_U32 reserve0 : 2; + } reg287; + + /* SWREG288_MIN_PIX */ + struct { + RK_U32 filterd_min_y : 10; + RK_U32 filterd_min_u : 10; + RK_U32 filterd_min_v : 10; + RK_U32 reserve0 : 2; + } reg288; + + /* SWREG289_WR_LINE_NUM */ + RK_U32 reg289_filterd_line_irq_offsety; + + RK_U32 reserve_reg290_291[2]; + + /* SWREG292_RCB_RW_SUM */ + struct { + RK_U32 rcb_rd_sum_chk : 8; + RK_U32 rcb_wr_sum_chk : 8; + RK_U32 reserve0 : 16; + } reg292; + + RK_U32 reserve_reg293; + + /* SWREG294_ERR_CTU_NUM0 */ + struct { + RK_U32 error_ctu_num : 24; + RK_U32 roi_error_ctu_num_lowbit : 8; + } reg294; + + /* SWREG295_ERR_CTU_NUM1 */ + RK_U32 reg295_roi_error_ctu_num_highbit; + +} Vdpu384aRegStatistic; + +typedef struct Vdpu384aRegLlp_t { + /* SWREG0_LINK_MODE */ + struct { + RK_U32 llp_mmu_zap_cache_dis : 1; + RK_U32 reserve0 : 15; + RK_U32 core_work_mode : 1; + RK_U32 ccu_core_work_mode : 1; + RK_U32 reserve1 : 3; + RK_U32 ltb_pause_flag : 1; + RK_U32 reserve2 : 10; + } reg0; + + /* SWREG1_CFG_START_ADDR */ + struct { + RK_U32 reserve0 : 4; + RK_U32 reg_cfg_addr : 28; + } reg1; + + /* SWREG2_LINK_MODE */ + struct { + RK_U32 pre_frame_num : 30; + RK_U32 reserve0 : 1; + RK_U32 link_mode : 1; + } reg2; + + /* SWREG3_CONFIG_DONE */ + RK_U32 reg3_done; + + /* SWREG4_DECODERED_NUM */ + RK_U32 reg4_num; + + /* SWREG5_DEC_TOTAL_NUM */ + RK_U32 reg5_total_num; + + /* SWREG6_LINK_MODE_EN */ + RK_U32 reg6_mode_en; + + /* SWREG7_SKIP_NUM */ + RK_U32 reg7_num; + + /* SWREG8_CUR_LTB_IDX */ + RK_U32 reg8_ltb_idx; + + RK_U32 reserve_reg9_15[7]; + + /* SWREG16_DEC_E */ + RK_U32 reg16_dec_e; + + /* SWREG17_SOFT_RST */ + RK_U32 reg17_rkvdec_ip_rst_p; + + /* SWREG18_IRQ */ + struct { + RK_U32 rkvdec_irq : 1; + RK_U32 rkvdec_line_irq : 1; + RK_U32 reserve0 : 14; + RK_U32 wmask : 2; + RK_U32 reserve1 : 14; + } reg18; + + /* SWREG19_STA */ + struct { + RK_U32 rkvdec_frame_rdy_sta : 1; + RK_U32 rkvdec_strm_error_sta : 1; + RK_U32 rkvdec_core_timeout_sta : 1; + RK_U32 rkvdec_ip_timeout_sta : 1; + RK_U32 rkvdec_bus_error_sta : 1; + RK_U32 rkvdec_buffer_empty_sta : 1; + RK_U32 rkvdec_colmv_ref_error_sta : 1; + RK_U32 rkvdec_error_spread_sta : 1; + RK_U32 create_core_timeout_sta : 1; + RK_U32 wlast_miss_match_sta : 1; + RK_U32 rkvdec_core_rst_rdy_sta : 1; + RK_U32 rkvdec_ip_rst_rdy_sta : 1; + RK_U32 force_busidle_rdy_sta : 1; + RK_U32 ltb_pause_rdy_sta : 1; + RK_U32 ltb_end_flag : 1; + RK_U32 unsupport_decmode_error_sta : 1; + RK_U32 wmask_bits : 15; + RK_U32 reserve0 : 1; + } reg19; + + RK_U32 reserve_reg20; + + /* SWREG21_IP_TIMEOUT_THRESHOD */ + RK_U32 reg21_ip_timeout_threshold; + + /* SWREG22_IP_EN */ + struct { + RK_U32 ip_timeout_pause_flag : 1; + RK_U32 reserve0 : 3; + RK_U32 abnormal_auto_reset_dis : 1; + RK_U32 reserve1 : 3; + RK_U32 force_busidle_req_flag : 1; + RK_U32 reserve2 : 3; + RK_U32 bus_clkgate_dis : 1; + RK_U32 ctrl_clkgate_dis : 1; + RK_U32 reserve3 : 1; + RK_U32 irq_dis : 1; + RK_U32 wid_reorder_dis : 1; + RK_U32 reserve4 : 7; + RK_U32 clk_cru_mode : 2; + RK_U32 reserve5 : 5; + RK_U32 mmu_sel : 1; + } reg22; + + /* SWREG23_IN_OUT */ + struct { + RK_U32 endian : 1; + RK_U32 swap32_e : 1; + RK_U32 swap64_e : 1; + RK_U32 str_endian : 1; + RK_U32 str_swap32_e : 1; + RK_U32 str_swap64_e : 1; + RK_U32 reserve0 : 26; + } reg23; + + /* SWREG24_EXTRA_STRM_BASE */ + RK_U32 reg24_extra_stream_base; + + /* SWREG25_EXTRA_STRM_LEN */ + RK_U32 reg25_extra_stream_len; + + /* SWREG26_EXTRA_STRM_PARA_SET */ + RK_U32 reg26_extra_strm_start_bit; + + /* SWREG27_BUF_EMPTY_RESTART */ + RK_U32 reg27_buf_emtpy_restart_p; + + /* SWREG28_RCB_BASE */ + RK_U32 reg28_rcb_base; + +} Vdpu384aRegLlp; + +typedef struct Vdpu384aRegSet_t { + Vdpu384aRegVersion reg_version; /* 0 */ + Vdpu384aCtrlReg ctrl_regs; /* 8-30 */ + Vdpu384aRegCommParas comm_paras; /* 64-74, 80-106 */ + Vdpu384aRegCommonAddr comm_addrs; /* 128-134, 140-161, 168-185, 192-210, 216-232 */ + Vdpu384aRegStatistic statistic_regs; /* 256-295 */ +} Vdpu384aRegSet; + +#ifdef __cplusplus +extern "C" { +#endif + +void vdpu384a_init_ctrl_regs(Vdpu384aRegSet *regs, MppCodingType codec_t); +void vdpu384a_setup_statistic(Vdpu384aCtrlReg *com); +void vdpu384a_setup_down_scale(MppFrame frame, MppDev dev, Vdpu384aCtrlReg *com, void* comParas); +void vdpu384a_update_thumbnail_frame_info(MppFrame frame); + +#ifdef DUMP_VDPU384A_DATAS +extern RK_U32 dump_cur_frame; +extern char dump_cur_dir[128]; +extern char dump_cur_fname_path[512]; + +MPP_RET flip_string(char *str); +MPP_RET dump_data_to_file(char *fname_path, void *data, RK_U32 data_bit_size, + RK_U32 line_bits, RK_U32 big_end); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* VDPU384A_COM_H */ diff --git a/mpp/hal/rkdec/inc/vdpu38x_com.h b/mpp/hal/rkdec/inc/vdpu38x_com.h new file mode 100644 index 000000000..385534ac4 --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu38x_com.h @@ -0,0 +1,843 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPU38X_COM_H +#define VDPU38X_COM_H + +#include + +#include "mpp_device.h" +#include "mpp_buf_slot.h" + +#include "vdpu_com.h" +#include "hal_bufs.h" + +// #define DUMP_VDPU38X_DATAS + +#define VDPU38X_OFF_CTRL_REGS (8 * sizeof(RK_U32)) +#define VDPU38X_OFF_INTERRUPT_REGS (15 * sizeof(RK_U32)) +#define VDPU38X_OFF_CODEC_PARAS_REGS (64 * sizeof(RK_U32)) +#define VDPU38X_OFF_COMMON_ADDR_REGS (128 * sizeof(RK_U32)) +#define VDPU38X_OFF_CODEC_ADDR_REGS (168 * sizeof(RK_U32)) +#define VDPU38X_OFF_COM_STATISTIC_REGS_VDPU383 (320 * sizeof(RK_U32)) +#define VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384A (320 * sizeof(RK_U32)) +#define VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B (256 * sizeof(RK_U32)) + +typedef enum Vdpu38xFmt_e { + MPP_HAL_FMT_YUV400 = 0, + MPP_HAL_FMT_YUV420, + MPP_HAL_FMT_YUV422, + MPP_HAL_FMT_YUV444, + MPP_HAL_FMT_BUTT, +} Vdpu38xFmt; + +extern const RK_U32 vdpu38x_rcb_type2loc_map[RCB_BUF_CNT]; +extern const RK_U32 vdpu38x_intra_uv_coef_map[MPP_HAL_FMT_BUTT]; +extern const RK_U32 vdpu38x_filter_row_uv_coef_map[MPP_HAL_FMT_BUTT]; +extern const RK_U32 vdpu38x_filter_col_uv_coef_map[MPP_HAL_FMT_BUTT]; + +typedef struct RcbTileInfo_t { + RK_U32 idx; + RK_U32 lt_x; + RK_U32 lt_y; + RK_U32 w; + RK_U32 h; +} RcbTileInfo; + +typedef MPP_RET (*Vdpu38xRcbCalc_f)(void *ctx, RK_U32 *total_sz); + +typedef struct Vdpu38xRcbCtx_t { + RK_U32 pic_w; + RK_U32 pic_h; + + /* tile info */ + RcbTileInfo *tile_infos; + RK_U32 tile_num; + RK_U32 tile_info_cap; + RK_U32 tile_dir; /* 0: left to right, 1: top to bottom */ + + /* general */ + Vdpu38xFmt fmt; + RK_U32 bit_depth; + RK_U32 buf_sz; + /* h264 */ + RK_U32 mbaff_flag; + /* avs2 */ + RK_U32 alf_en; + /* av1 */ + RK_U32 lr_en; + RK_U32 upsc_en; + + VdpuRcbInfo buf_info[RCB_BUF_CNT]; + Vdpu38xRcbCalc_f calc_func; +} Vdpu38xRcbCtx; + +typedef struct Vdpu38xRegVersion_t { + struct SWREG0_ID { + RK_U32 minor_ver : 8; + RK_U32 major_ver : 8; + RK_U32 prod_num : 16; + } reg0; +} Vdpu38xRegVersion; + +typedef struct Vdpu38xCtrlReg_t { + /* SWREG8_DEC_MODE */ + RK_U32 reg8_dec_mode; + + struct SWREG9_IMPORTANT_EN { + RK_U32 secure_access : 1; + RK_U32 reserve0 : 3; + RK_U32 low_latency_en : 1; + RK_U32 scale_down_en : 1; + RK_U32 collect_info_dis : 1; + RK_U32 pix_range_det_e : 1; + RK_U32 av1_fgs_en : 1; + RK_U32 reserve2 : 3; + RK_U32 scale_down_ratio : 1; + RK_U32 scale_down_10bitto8bit_en : 1; + RK_U32 line_irq_en : 2; + RK_U32 reserve3 : 1; + RK_U32 out_cbcr_swap : 1; + RK_U32 fbc_force_uncompress : 1; + RK_U32 fbc_sparse_mode : 1; + RK_U32 reserve4 : 3; + /* + * vdpu384b is unused + * refer to collect_info_dis for its + * original functionality. + */ + RK_U32 inter_max_mv_detect_en : 1; + /* + * 0:pp output raster. + * 1:pp output tile4x4. + * 2:pp output rkfbc64x4. + * 3:pp output afbc32x8. + */ + RK_U32 pp_output_mode : 2; + RK_U32 reserve5 : 6; + } reg9; + + struct SWREG10_BLOCK_GATING_DIS { + RK_U32 strmd_auto_gating_dis : 1; + RK_U32 inter_auto_gating_dis : 1; + RK_U32 intra_auto_gating_dis : 1; + RK_U32 transd_auto_gating_dis : 1; + RK_U32 recon_auto_gating_dis : 1; + RK_U32 filterd_auto_gating_dis : 1; + RK_U32 bus_auto_gating_dis : 1; + RK_U32 ctrl_auto_gating_dis : 1; + RK_U32 rcb_auto_gating_dis : 1; + RK_U32 err_prc_auto_gating_dis : 1; + RK_U32 cache_auto_gating_dis : 1; + RK_U32 reserve0 : 21; + } reg10; + + struct SWREG11_CFG_PARA { + RK_U32 frame_irq_dis : 1; + RK_U32 recon_ahead_release_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 cache_perf_opt_disable : 1; + RK_U32 cache_dis : 1; + RK_U32 cache_pu_parse_opt_dis : 1; + RK_U32 cache_multi_id_dis : 1; + RK_U32 cache_grp_dis : 1; + RK_U32 dec_timeout_dis : 1; + RK_U32 reserve1 : 3; + RK_U32 coord_rpt_mode : 1; + RK_U32 reserve2 : 2; + RK_U32 rd_outstanding : 8; + RK_U32 wr_outstanding : 8; + } reg11; + + RK_U32 reserve_reg12; + + /* SWREG13_CORE_TIMEOUT_THRESHOLD */ + RK_U32 reg13_core_timeout_threshold; + + struct SWREG14_LINE_IRQ_CTRL { + RK_U32 dec_line_irq_step : 16; + RK_U32 dec_line_offset_y_st : 16; + } reg14; + + struct SWREG15_STA { + RK_U32 rkvdec_frame_rdy_sta : 1; + RK_U32 rkvdec_strm_error_sta : 1; + RK_U32 rkvdec_core_timeout_sta : 1; + RK_U32 rkvdec_ip_timeout_sta : 1; + RK_U32 rkvdec_bus_error_sta : 1; + RK_U32 rkvdec_buffer_empty_sta : 1; + RK_U32 rkvdec_colmv_ref_error_sta : 1; + RK_U32 rkvdec_error_spread_sta : 1; + RK_U32 create_core_timeout_sta : 1; + RK_U32 wlast_miss_match_sta : 1; + RK_U32 rkvdec_core_rst_rdy_sta : 1; + RK_U32 rkvdec_ip_rst_rdy_sta : 1; + RK_U32 force_busidle_rdy_sta : 1; + RK_U32 ltb_pause_rdy_sta : 1; + RK_U32 ltb_end_flag : 1; + RK_U32 unsupport_decmode_error_sta : 1; + RK_U32 wmask_bits : 15; + RK_U32 reserve0 : 1; + } reg15; + + struct SWREG16_ERROR_CTRL_SET { + RK_U32 error_proc_disable : 1; + RK_U32 error_proc_restart_mode : 1; + RK_U32 error_flush_dis : 1; + RK_U32 roi_error_ctu_cal_en : 1; + RK_U32 nxt_slice_retrieval_dis : 1; + RK_U32 filterd_err_wr_prot_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 error_spread_disable : 1; + RK_U32 error_fill_mode : 1; + RK_U32 error_intra_creat_mode : 1; + RK_U32 reserve1 : 13; + RK_U32 inter_error_gbl_mv_x : 4; + RK_U32 inter_error_gbl_mv_y : 4; + } reg16; + + struct SWREG17_ERR_ROI_CTU_OFFSET_START { + RK_U32 roi_x_ctu_offset_st : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_st : 12; + RK_U32 reserve1 : 4; + } reg17; + + struct SWREG18_ERR_ROI_CTU_OFFSET_END { + RK_U32 roi_x_ctu_offset_end : 12; + RK_U32 reserve0 : 4; + RK_U32 roi_y_ctu_offset_end : 12; + RK_U32 reserve1 : 4; + } reg18; + + struct SWREG19_ERROR_REF_INFO { + RK_U32 avs2_ref_error_field : 1; + RK_U32 avs2_ref_error_topfield : 1; + RK_U32 ref_error_topfield_used : 1; + RK_U32 ref_error_botfield_used : 1; + RK_U32 reserve0 : 28; + } reg19; + + /* SWREG20_CABAC_ERROR_EN_LOWBITS */ + RK_U32 reg20_cabac_error_en_lowbits; + + /* SWREG21_CABAC_ERROR_EN_HIGHBITS */ + RK_U32 reg21_cabac_error_en_highbits; + + RK_U32 reserve_reg22; + + struct SWREG23_INVALID_PIXEL_FILL { + RK_U32 fill_y : 10; + RK_U32 fill_u : 10; + RK_U32 fill_v : 10; + RK_U32 reserve0 : 2; + } reg23; + + RK_U32 reserve_reg24_27[4]; + + struct SWREG28_DEBUG_PERF_LATENCY_CTRL0 { + RK_U32 axi_perf_work_e : 1; + RK_U32 reserve0 : 2; + RK_U32 axi_cnt_type : 1; + RK_U32 rd_latency_id : 8; + RK_U32 reserve1 : 4; + RK_U32 rd_latency_thr : 12; + RK_U32 reserve2 : 4; + } reg28; + + struct SWREG29_DEBUG_PERF_LATENCY_CTRL1 { + RK_U32 addr_align_type : 2; + RK_U32 ar_cnt_id_type : 1; + RK_U32 aw_cnt_id_type : 1; + RK_U32 ar_count_id : 8; + RK_U32 reserve0 : 4; + RK_U32 aw_count_id : 8; + RK_U32 rd_band_width_mode : 1; + RK_U32 reserve1 : 7; + } reg29; + + struct SWREG30_QOS_CTRL { + RK_U32 axi_wr_qos_level : 4; + RK_U32 reserve0 : 4; + RK_U32 axi_wr_qos : 4; + RK_U32 reserve1 : 4; + RK_U32 axi_rd_qos_level : 4; + RK_U32 reserve2 : 4; + RK_U32 axi_rd_qos : 4; + RK_U32 axi_mmu_rd_qos : 4; + } reg30; + +} Vdpu38xCtrlReg; + +typedef struct Vdpu38xRegCommParas_t { + /* SWREG64_H26X_PARA */ + RK_U32 reg64_unused_bits; + + /* SWREG65_STREAM_PARAM_SET */ + RK_U32 reg65_strm_start_bit; + + /* SWREG66_STREAM_LEN */ + RK_U32 reg66_stream_len; + + /* SWREG67_GLOBAL_LEN */ + RK_U32 reg67_global_len; + + /* SWREG68_HEAD_HOR_STRIDE */ + RK_U32 reg68_pp_m_hor_stride; + + /* SWREG69_PP_M_UV_HOR_STRIDE */ + RK_U32 reg69_pp_m_uv_hor_stride; + + /* SWREG70_PP_M_Y_STRIDE */ + RK_U32 reg70_pp_m_y_virstride; + + /* SWREG71_SCL_Y_HOR_VIRSTRIDE */ + RK_U32 reg71_scl_ref_hor_virstride; + + /* SWREG72_SCL_UV_HOR_VIRSTRIDE */ + RK_U32 reg72_scl_ref_raster_uv_hor_virstride; + + /* SWREG73_SCL_Y_VIRSTRIDE */ + RK_U32 reg73_scl_ref_virstride; + + /* SWREG74_FGS_Y_HOR_VIRSTRIDE */ + RK_U32 reg74_fgs_ref_hor_virstride; + + /* SWREG75_FGS_UV_HOR_VIRSTRIDE */ + RK_U32 reg75_fgs_ref_uv_hor_virstride; + + /* SWREG76_FGS_Y_VIRSTRIDE */ + RK_U32 reg76_fgs_ref_virstride; + + RK_U32 reserve_reg77; + + struct SWREG78_ERROR_REF_PIC { + RK_U32 error_ref_pic_width : 16; + RK_U32 error_ref_pic_height : 16; + } reg78; + + struct SWREG79_ERROR_REF_SCALE { + RK_U32 error_ref_scale_step_x : 16; + RK_U32 error_ref_scale_step_y : 16; + } reg79; + + /* SWREG80_ERROR_REF_Y_HOR_VIRSTRIDE */ + RK_U32 reg80_error_ref_hor_virstride; + + /* SWREG81_ERROR_REF_UV_HOR_VIRSTRIDE */ + RK_U32 reg81_error_ref_raster_uv_hor_virstride; + + /* SWREG82_ERROR_REF_Y_VIRSTRIDE */ + RK_U32 reg82_error_ref_virstride; + + union { + struct { + RK_U32 hor_y_stride; + RK_U32 hor_uv_stride; + RK_U32 y_stride; + } ref_stride[VDPU38X_REG_MAX_REF_CNT]; + struct { + RK_U32 reg83_ref0_hor_virstride; + RK_U32 reg84_ref0_raster_uv_hor_virstride; + RK_U32 reg85_ref0_virstride; + RK_U32 reg86_ref1_hor_virstride; + RK_U32 reg87_ref1_raster_uv_hor_virstride; + RK_U32 reg88_ref1_virstride; + RK_U32 reg89_ref2_hor_virstride; + RK_U32 reg90_ref2_raster_uv_hor_virstride; + RK_U32 reg91_ref2_virstride; + RK_U32 reg92_ref3_hor_virstride; + RK_U32 reg93_ref3_raster_uv_hor_virstride; + RK_U32 reg94_ref3_virstride; + RK_U32 reg95_ref4_hor_virstride; + RK_U32 reg96_ref4_raster_uv_hor_virstride; + RK_U32 reg97_ref4_virstride; + RK_U32 reg98_ref5_hor_virstride; + RK_U32 reg99_ref5_raster_uv_hor_virstride; + RK_U32 reg100_ref5_virstride; + RK_U32 reg101_ref6_hor_virstride; + RK_U32 reg102_ref6_raster_uv_hor_virstride; + RK_U32 reg103_ref6_virstride; + RK_U32 reg104_ref7_hor_virstride; + RK_U32 reg105_ref7_raster_uv_hor_virstride; + RK_U32 reg106_ref7_virstride; + }; + }; +} Vdpu38xRegCommParas; + +typedef struct Vdpu38xRegCommonAddr_t { + /* SWREG128_STRM_BASE */ + RK_U32 reg128_strm_base; + + /* SWREG129_STREAM_BUF_ST_BASE */ + RK_U32 reg129_stream_buf_st_base; + + /* SWREG130_STREAM_BUF_END_BASE */ + RK_U32 reg130_stream_buf_end_base; + + /* SWREG131_GBL_BASE */ + RK_U32 reg131_gbl_base; + + /* SWREG132_SCANLIST_ADDR */ + RK_U32 reg132_scanlist_addr; + + /* SWREG133_SCL_BASE */ + RK_U32 reg133_scale_down_base; + + /* SWREG134_FGS_BASE */ + RK_U32 reg134_fgs_base; + + RK_U32 reserve_reg135_139[5]; + + union { + Vdpu38xRcbRegSet rcb_regs; + struct { + RK_U32 reg140_rcb_strmd_row_offset; + RK_U32 reg141_rcb_strmd_row_len; + RK_U32 reg142_rcb_strmd_tile_row_offset; + RK_U32 reg143_rcb_strmd_tile_row_len; + RK_U32 reg144_rcb_inter_row_offset; + RK_U32 reg145_rcb_inter_row_len; + RK_U32 reg146_rcb_inter_tile_row_offset; + RK_U32 reg147_rcb_inter_tile_row_len; + RK_U32 reg148_rcb_intra_row_offset; + RK_U32 reg149_rcb_intra_row_len; + RK_U32 reg150_rcb_intra_tile_row_offset; + RK_U32 reg151_rcb_intra_tile_row_len; + RK_U32 reg152_rcb_filterd_row_offset; + RK_U32 reg153_rcb_filterd_row_len; + RK_U32 reg154_rcb_filterd_protect_row_offset; // deleted in vdpu384b + RK_U32 reg155_rcb_filterd_protect_row_len; // deleted in vdpu384b + RK_U32 reg156_rcb_filterd_tile_row_offset; + RK_U32 reg157_rcb_filterd_tile_row_len; + RK_U32 reg158_rcb_filterd_tile_col_offset; + RK_U32 reg159_rcb_filterd_tile_col_len; + RK_U32 reg160_rcb_filterd_av1_upscale_tile_col_offset; + RK_U32 reg161_rcb_filterd_av1_upscale_tile_col_len; + }; + }; + + RK_U32 reserve_reg162_167[6]; + + /* SWREG168_DECOUT_BASE */ + RK_U32 reg168_decout_base; + + /* SWREG169_ERROR_REF_BASE */ + RK_U32 reg169_error_ref_base; + + union { + /* h264 / h265 / avs2 */ + RK_U32 reg170_185_ref_base[16]; + /* vp9 */ + struct { + RK_U32 reg170_180[11]; + RK_U32 reg181_segidlast_base; + RK_U32 reg182_segidcur_base; + RK_U32 reg183_reserve; + RK_U32 reg184_lastprob_base; + RK_U32 reg185_updateprob_base; + }; + /* av1 */ + struct { + RK_U32 reg170_av1_last_base; + RK_U32 reg171_av1golden_base; + RK_U32 reg172_av1alfter_base; + RK_U32 reserve_reg173_177[5]; + RK_U32 reg178_av1_coef_rd_base; + RK_U32 reg179_av1_coef_wr_base; + RK_U32 reserve_reg180; + RK_U32 reg181_av1_segid_last_base; + RK_U32 reg182_av1_segid_cur_base; + RK_U32 reserve_reg183; + RK_U32 reg184_av1_noncoef_rd_base; + RK_U32 reg185_av1_noncoef_wr_base; + }; + }; + + + RK_U32 reserve_reg186_190[5]; + + /* SWREG191_FGS_FBC_PAYLOAD_ST */ + RK_U32 reg191_fgs_fbc_payload_st_base; + + /* SWREG192_PAYLOAD_ST_CUR_BASE */ + RK_U32 reg192_payload_st_cur_base; + + /* SWREG193_FBC_PAYLOAD_OFFSET */ + RK_U32 reg193_fbc_payload_offset; + + /* SWREG194_PAYLOAD_ST_ERROR_REF_BASE */ + RK_U32 reg194_payload_st_error_ref_base; + + /* SWREG195_PAYLOAD_ST_REF0_BASE */ + RK_U32 reg195_210_payload_st_ref_base[16]; + + RK_U32 reserve_reg211_215[5]; + + /* SWREG216_COLMV_CUR_BASE */ + RK_U32 reg216_colmv_cur_base; + + /* SWREG217_232_COLMV_REF0_BASE */ + RK_U32 reg217_232_colmv_ref_base[16]; + +} Vdpu38xRegCommonAddr; + + +typedef struct Vdpu38xRegStatistic_t { + struct SWREG256_CTRL_RESP { + RK_U32 reserve0 : 24; + RK_U32 rkvdec_bus_idle_flag : 1; + RK_U32 reserve1 : 7; + } reg256; + + RK_U32 reserve_reg257; + + /* SWREG258_BUS_RESP */ + RK_U32 reg258_perf_rd_max_latency_num; + + /* SWREG259_BUS_RESP */ + RK_U32 reg259_perf_rd_latency_samp_num; + + /* SWREG260_BUS_RESP */ + RK_U32 reg260_perf_rd_latency_acc_sum; + + /* SWREG261_BUS_RESP */ + RK_U32 reg261_perf_rd_axi_total_byte; + + /* SWREG262_BUS_RESP */ + RK_U32 reg262_perf_wr_axi_total_bytes; + + /* SWREG263_BUS_RESP */ + RK_U32 reg263_perf_working_cnt; + + RK_U32 reserve_reg264_272[9]; + + struct SWREG273_CABAC_RESP { + RK_U32 qp_max : 9; + RK_U32 reserve0 : 3; + RK_U32 qp_min : 9; + RK_U32 reserve1 : 3; + RK_U32 qp_sum_low8bit : 8; + } reg273; + + /* SWREG274_CABAC_RESP */ + RK_U32 reg274_qp_sum_high; + + /* SWREG275_CABAC_RESP */ + RK_U32 reg275_tu_need_iq_sum; + + /* SWREG276_INTER_RESP */ + RK_U32 reg276_inter_sw_reflst_idx_use; + + /* SWREG277_INTER_RESP */ + RK_U32 reg277_sw_mv_x_out_sum_31_0; + + struct SWREG278_INTER_RESP { + RK_U32 inter_sw_mv_x_out_sum_43_32 : 12; + RK_U32 inter_sw_mv_y_out_sum_19_0 : 20; + } reg278; + + struct SWREG279_INTER_RESP { + RK_U32 inter_sw_mv_y_out_sum_43_20 : 24; + RK_U32 dbg_inter_min_mv_x : 4; + RK_U32 dbg_inter_min_mv_y : 4; + } reg279; + + struct SWREG280_INTER_RESP { + RK_U32 inter_sw_mv_x_max_out : 16; + RK_U32 inter_sw_mv_y_max_out : 16; + } reg280; + + struct SWREG281_INTER_RESP { + RK_U32 inter_sw_mv_x_min_out : 16; + RK_U32 inter_sw_mv_y_min_out : 16; + } reg281; + + struct SWREG282_INTER_RESP { + RK_U32 inter_sw_skip_pu_cnt_sum : 28; + RK_U32 inter_sw_pu_cnt_sum_3_0 : 4; + } reg282; + + struct SWREG283_INTER_RESP { + RK_U32 inter_sw_pu_cnt_sum_27_4 : 24; + RK_U32 inter_sw_min_pu_cnt_sum_7_0 : 8; + } reg283; + + /* SWREG284_INTER_RESP */ + RK_U32 reg284_sw_min_pu_cnt_sum_27_8; + + RK_U32 reserve_reg285_286[2]; + + /* SWREG287_INTER_RESP */ + RK_U32 reg287_inter_cache_info_reserve0; + + /* SWREG288_INTER_RESP */ + RK_U32 reg288_inter_cache_info_reserve1; + + /* SWREG289_INTER_RESP */ + RK_U32 reg289_inter_cache_info_reserve2; + + /* SWREG290_INTER_RESP */ + RK_U32 reg290_inter_dbg_info_reserve; + + RK_U32 reserve_reg291_298[8]; + + /* SWREG299_FILTERD_RESP */ + RK_U32 reg299_filterd_payload_total_cnt; + + struct SWREG300_FILTERD_RESP { + RK_U32 fdbg_filterd_report_offsety : 16; + RK_U32 fdbg_filterd_report_offsetx : 16; + } reg300; + + struct SWREG301_FILTERD_RESP { + RK_U32 fdbg_filterd_max_y : 10; + RK_U32 fdbg_filterd_max_u : 10; + RK_U32 fdbg_filterd_max_v : 10; + RK_U32 reserve0 : 2; + } reg301; + + struct SWREG302_FILTERD_RESP { + RK_U32 fdbg_filterd_min_y : 10; + RK_U32 fdbg_filterd_min_u : 10; + RK_U32 fdbg_filterd_min_v : 10; + RK_U32 reserve0 : 2; + } reg302; + + struct SWREG303_FILTERD_RESP { + RK_U32 fdbg_filterd_ppm_line_irq_offsety : 16; + RK_U32 fdbg_filterd_scl_line_irq_offsety : 16; + } reg303; + + /* SWREG304_FILTERD_RESP */ + RK_U32 reg304_filterd_err_ctu_num; + + RK_U32 reserve_reg305_311[7]; + + struct SWREG312_RCB_RESP { + RK_U32 rcb_rd_sum_chk : 8; + RK_U32 rcb_wr_sum_chk : 8; + RK_U32 reserve0 : 16; + } reg312; + +} Vdpu38xRegStatistic; + +typedef struct Vdpu38xRegLlp_t { + struct SWREG0_LINK_MODE { + RK_U32 llp_mmu_zap_cache_dis : 1; + RK_U32 reserve0 : 15; + RK_U32 core_work_mode : 1; + RK_U32 ccu_core_work_mode : 1; + RK_U32 reserve1 : 3; + RK_U32 ltb_pause_flag : 1; + RK_U32 reserve2 : 10; + } reg0; + + struct SWREG1_CFG_START_ADDR { + RK_U32 reserve0 : 4; + RK_U32 reg_cfg_addr : 28; + } reg1; + + struct SWREG2_LINK_MODE { + RK_U32 pre_frame_num : 30; + RK_U32 reserve0 : 1; + RK_U32 link_mode : 1; + } reg2; + + /* SWREG3_CONFIG_DONE */ + RK_U32 reg3_done; + + /* SWREG4_DECODERED_NUM */ + RK_U32 reg4_num; + + /* SWREG5_DEC_TOTAL_NUM */ + RK_U32 reg5_total_num; + + /* SWREG6_LINK_MODE_EN */ + RK_U32 reg6_mode_en; + + /* SWREG7_SKIP_NUM */ + RK_U32 reg7_num; + + struct SWREG8_CUR_LTB_IDX { + RK_U32 reserve0 : 4; + RK_U32 ltb_idx : 28; + } reg8; + + RK_U32 reserve_reg9_15[7]; + + /* SWREG16_DEC_E */ + RK_U32 reg16_dec_e; + + /* SWREG17_SOFT_RST */ + RK_U32 reg17_rkvdec_ip_rst_p; + + struct SWREG18_IRQ { + RK_U32 rkvdec_irq : 1; + RK_U32 rkvdec_line_irq : 1; + RK_U32 reserve0 : 14; + RK_U32 wmask : 2; + RK_U32 reserve1 : 14; + } reg18; + + struct SWREG19_STA { + RK_U32 rkvdec_frame_rdy_sta : 1; + RK_U32 rkvdec_strm_error_sta : 1; + RK_U32 rkvdec_core_timeout_sta : 1; + RK_U32 rkvdec_ip_timeout_sta : 1; + RK_U32 rkvdec_bus_error_sta : 1; + RK_U32 rkvdec_buffer_empty_sta : 1; + RK_U32 rkvdec_colmv_ref_error_sta : 1; + RK_U32 rkvdec_error_spread_sta : 1; + RK_U32 create_core_timeout_sta : 1; + RK_U32 wlast_miss_match_sta : 1; + RK_U32 rkvdec_core_rst_rdy_sta : 1; + RK_U32 rkvdec_ip_rst_rdy_sta : 1; + RK_U32 force_busidle_rdy_sta : 1; + RK_U32 ltb_pause_rdy_sta : 1; + RK_U32 ltb_end_flag : 1; + RK_U32 unsupport_decmode_error_sta : 1; + RK_U32 wmask_bits : 15; + RK_U32 reserve0 : 1; + } reg19; + + RK_U32 reserve_reg20; + + /* SWREG21_IP_TIMEOUT_THRESHOD */ + RK_U32 reg21_ip_timeout_threshold; + + struct SWREG22_IP_EN { + RK_U32 ip_timeout_pause_flag : 1; + RK_U32 reserve0 : 3; + RK_U32 abnormal_auto_reset_dis : 1; + RK_U32 reserve1 : 3; + RK_U32 force_busidle_req_flag : 1; + RK_U32 reserve2 : 3; + RK_U32 bus_clkgate_dis : 1; + RK_U32 ctrl_clkgate_dis : 1; + RK_U32 reserve3 : 1; + RK_U32 irq_dis : 1; + RK_U32 wid_reorder_dis : 1; + RK_U32 reserve4 : 7; + RK_U32 clk_cru_mode : 2; + RK_U32 reserve5 : 4; + RK_U32 rkmmu_rd_mode : 1; + RK_U32 mmu_sel : 1; + } reg22; + + struct SWREG23_IN_OUT { + RK_U32 endian : 1; + RK_U32 swap32_e : 1; + RK_U32 swap64_e : 1; + RK_U32 str_endian : 1; + RK_U32 str_swap32_e : 1; + RK_U32 str_swap64_e : 1; + RK_U32 reserve0 : 26; + } reg23; + + struct SWREG24_EXTRA_STRM_BASE { + RK_U32 reserve0 : 4; + RK_U32 extra_stream_base : 28; + } reg24; + + /* SWREG25_EXTRA_STRM_LEN */ + RK_U32 reg25_extra_stream_len; + + /* SWREG26_EXTRA_STRM_PARA_SET */ + RK_U32 reg26_extra_strm_start_bit; + + struct SWREG27_BUF_EMPTY_RESTART { + RK_U32 buf_emtpy_restart_p : 1; + RK_U32 extra_strm_last_packet_flag : 1; + RK_U32 reserve0 : 30; + } reg27; + + struct SWREG28_RCB_BASE { + RK_U32 reserve0 : 4; + RK_U32 rcb_base : 28; + } reg28; + + /* SWREG29_STRMD_LEN_USED */ + RK_U32 reg29_strm_len_used_bytes; + +} Vdpu38xRegLlp; + +typedef struct Vdpu38xdRegSet_t { + Vdpu38xRegVersion reg_version; + Vdpu38xCtrlReg ctrl_regs; /* 8-30 */ + Vdpu38xRegCommParas comm_paras; /* 64-106 */ + Vdpu38xRegCommonAddr comm_addrs; /* 128-134, 140-161, 168-185, 192-210, 216-232 */ + Vdpu38xRegStatistic statistic_regs; /* 256-312 */ +} Vdpu38xRegSet; + +typedef enum Vdpu38xTileLoc_e { + VDPU38X_RCB_IN_TILE_ROW = 0, + VDPU38X_RCB_IN_TILE_COL, + VDPU38X_RCB_ON_TILE_ROW, + VDPU38X_RCB_ON_TILE_COL, +} Vdpu38xTileLoc ; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vdpu38x_rcb_calc_init(Vdpu38xRcbCtx **ctx); +MPP_RET vdpu38x_rcb_calc_deinit(Vdpu38xRcbCtx *ctx); +MPP_RET vdpu38x_rcb_reset(Vdpu38xRcbCtx *ctx); +MPP_RET vdpu38x_rcb_add_tile_info(Vdpu38xRcbCtx *ctx, RcbTileInfo *tile_info); +MPP_RET vdpu38x_rcb_dump_tile_info(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_pic_w(Vdpu38xRcbCtx *ctx, RK_U32 pic_w); +Vdpu38xFmt vdpu38x_fmt_mpp2hal(MppFrameFormat mpp_fmt); +RK_U32 vdpu38x_rcb_get_pic_w(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_pic_h(Vdpu38xRcbCtx *ctx, RK_U32 pic_h); +RK_U32 vdpu38x_rcb_get_pic_h(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_tile_dir(Vdpu38xRcbCtx *ctx, RK_U32 tile_dir); +RK_U32 vdpu38x_rcb_get_tile_dir(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_fmt(Vdpu38xRcbCtx *ctx, RK_U32 fmt); +Vdpu38xFmt vdpu38x_rcb_get_fmt(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_bit_depth(Vdpu38xRcbCtx *ctx, RK_U32 bit_depth); +RK_U32 vdpu38x_rcb_get_bit_depth(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_mbaff_flag(Vdpu38xRcbCtx *ctx, RK_U32 mbaff_flag); +RK_U32 vdpu38x_rcb_get_mbaff_flag(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_alf_en(Vdpu38xRcbCtx *ctx, RK_U32 alf_en); +RK_U32 vdpu38x_rcb_get_alf_en(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_lr_en(Vdpu38xRcbCtx *ctx, RK_U32 lr_en); +RK_U32 vdpu38x_rcb_get_lr_en(Vdpu38xRcbCtx *ctx); +void vdpu38x_rcb_set_upsc_en(Vdpu38xRcbCtx *ctx, RK_U32 upsc_en); +RK_U32 vdpu38x_rcb_get_upsc_en(Vdpu38xRcbCtx *ctx); +MPP_RET vdpu38x_rcb_get_len(Vdpu38xRcbCtx *ctx, Vdpu38xTileLoc loc, RK_U32 *len); +MPP_RET vdpu38x_rcb_get_extra_size(Vdpu38xRcbCtx *ctx, Vdpu38xTileLoc loc, RK_U32 *extra_sz); +RK_U32 vdpu38x_rcb_reg_info_update(Vdpu38xRcbCtx *ctx, Vdpu38xRcbType type, RK_U32 idx, + RK_FLOAT sz); +RK_U32 vdpu38x_rcb_get_total_size(Vdpu38xRcbCtx *ctx); +MPP_RET vdpu38x_rcb_register_calc_handle(Vdpu38xRcbCtx *ctx, Vdpu38xRcbCalc_f func); +MPP_RET vdpu38x_rcb_calc_exec(Vdpu38xRcbCtx *ctx, RK_U32 *total_sz); +RK_S32 vdpu38x_rcb_set_info(Vdpu38xRcbCtx *ctx, MppDev dev); +MPP_RET vdpu38x_rcb_dump_rcb_result(Vdpu38xRcbCtx *ctx); +MPP_RET vdpu38x_get_fbc_off(MppFrame mframe, RK_U32 *head_stride, RK_U32 *pld_stride, RK_U32 *pld_offset); +MPP_RET vdpu38x_get_tile4x4_h_stride_coeff(MppFrameFormat fmt, RK_U32 *coeff); +void vdpu38x_setup_rcb(Vdpu38xRcbCtx *ctx, Vdpu38xRcbRegSet *regs, MppDev dev, MppBuffer buf); +void vdpu384b_init_ctrl_regs(Vdpu38xRegSet *regs, MppCodingType codec_t); +void vdpu38x_setup_statistic(Vdpu38xCtrlReg *com); +void vdpu38x_setup_down_scale(MppFrame frame, MppDev dev, Vdpu38xCtrlReg *com, void* comParas); +void vdpu38x_update_thumbnail_frame_info(MppFrame frame); +MPP_RET vdpu38x_setup_scale_origin_bufs(MppFrame mframe, HalBufs *org_bufs, RK_S32 max_cnt); +RK_S32 hal_h265d_avs2d_calc_mv_size(RK_S32 pic_w, RK_S32 pic_h, RK_S32 ctu_w); + +#ifdef DUMP_VDPU38X_DATAS +extern RK_U32 vdpu38x_dump_cur_frm; +extern char vdpu38x_dump_cur_dir[128]; +extern char vdpu38x_dump_cur_fname_path[512]; + +MPP_RET vdpu38x_flip_string(char *str); +MPP_RET vdpu38x_dump_data_to_file(char *fname_path, void *data, RK_U32 data_bit_size, + RK_U32 line_bits, RK_U32 big_end, RK_U32 append); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* VDPU38X_COM_H */ diff --git a/mpp/hal/rkdec/inc/vdpu_com.h b/mpp/hal/rkdec/inc/vdpu_com.h new file mode 100644 index 000000000..dabcb03ea --- /dev/null +++ b/mpp/hal/rkdec/inc/vdpu_com.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPU_COM_H +#define VDPU_COM_H + +#include + +#include "mpp_buf_slot.h" + +#define VDPU_FAST_REG_SET_CNT 3 + +#define RCB_ALLINE_SIZE (64) +#define MPP_RCB_BYTES(bits) ((RK_U32)(MPP_ALIGN(((RK_U32)ceilf(bits) + 7) / 8, RCB_ALLINE_SIZE))) + +#define VDPU38X_REG_MAX_REF_CNT 8 + +typedef enum VdpuRcbSetMode_e { + RCB_SET_BY_SIZE_SORT_MODE, + RCB_SET_BY_PRIORITY_MODE, +} VdpuRcbSetMode; + +/* IN/ON_TILE */ +typedef enum Vdpu38xRcbType_e { + RCB_STRMD_IN_ROW, + RCB_STRMD_ON_ROW, + RCB_INTER_IN_ROW, + RCB_INTER_ON_ROW, + RCB_INTRA_IN_ROW, + RCB_INTRA_ON_ROW, + RCB_FLTD_IN_ROW, + RCB_FLTD_PROT_IN_ROW, + RCB_FLTD_ON_ROW, + RCB_FLTD_ON_COL, + RCB_FLTD_UPSC_ON_COL, + RCB_BUF_CNT, +} Vdpu38xRcbType; + +typedef struct VdpuRcbInfo_t { + RK_U32 reg_idx; + RK_S32 size; + RK_S32 offset; +} VdpuRcbInfo; + +typedef struct Vdpu38xRcbRegSet_t { + RK_U32 strmd_in_row_off; + RK_U32 strmd_in_row_len; + RK_U32 strmd_on_row_off; + RK_U32 strmd_on_row_len; + RK_U32 inter_in_row_off; + RK_U32 inter_in_row_len; + RK_U32 inter_on_row_off; + RK_U32 inter_on_row_len; + RK_U32 intra_in_row_off; + RK_U32 intra_in_row_len; + RK_U32 intra_on_row_off; + RK_U32 intra_on_row_len; + RK_U32 fltd_in_row_off; + RK_U32 fltd_in_row_len; + RK_U32 fltd_prot_in_row_off; + RK_U32 fltd_prot_in_row_len; + RK_U32 fltd_on_row_off; + RK_U32 fltd_on_row_len; + RK_U32 fltd_on_col_off; + RK_U32 fltd_on_col_len; + RK_U32 fltd_upsc_on_col_off; + RK_U32 fltd_upsc_on_col_len; +} Vdpu38xRcbRegSet; + +RK_S32 vdpu_compare_rcb_size(const void *a, const void *b); +void vdpu_afbc_align_calc(MppBufSlots slots, MppFrame frame, RK_U32 expand); + +#endif /* VDPU_COM_H */ diff --git a/mpp/hal/rkdec/vp9d/CMakeLists.txt b/mpp/hal/rkdec/vp9d/CMakeLists.txt index b66fe4acf..e70cb3a71 100644 --- a/mpp/hal/rkdec/vp9d/CMakeLists.txt +++ b/mpp/hal/rkdec/vp9d/CMakeLists.txt @@ -1 +1,16 @@ # vim: syntax=cmake + +# hal vp9 decoder sourse +set(HAL_VP9D_SRC + hal_vp9d_com.c + ) + +add_hal_source(HAL_VP9D_SRC HAVE_VDPU341 hal_vp9d_rkv.c) +add_hal_source(HAL_VP9D_SRC HAVE_VDPU34X hal_vp9d_vdpu34x.c) +add_hal_source(HAL_VP9D_SRC HAVE_VDPU382 hal_vp9d_vdpu382.c) +add_hal_source(HAL_VP9D_SRC HAVE_VDPU383 hal_vp9d_vdpu383.c) +add_hal_source(HAL_VP9D_SRC HAVE_VDPU384B hal_vp9d_vdpu384b.c) + +if (HAL_VP9D_SRC) + add_library(hal_vp9d_api OBJECT ${HAL_VP9D_SRC}) +endif() diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_com.c b/mpp/hal/rkdec/vp9d/hal_vp9d_com.c new file mode 100644 index 000000000..4a1beab07 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_com.c @@ -0,0 +1,2493 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mpp_bitput.h" + +#include "hal_vp9d_com.h" +#include "vdpu38x_com.h" +#include "hal_vp9d_debug.h" + +typedef struct { + RK_U8 y_mode[4][9]; + RK_U8 uv_mode[10][9]; + RK_U8 filter[4][2]; + RK_U8 mv_mode[7][3]; + RK_U8 intra[4]; + RK_U8 comp[5]; + RK_U8 single_ref[5][2]; + RK_U8 comp_ref[5]; + RK_U8 tx32p[2][3]; + RK_U8 tx16p[2][2]; + RK_U8 tx8p[2]; + RK_U8 skip[3]; + RK_U8 mv_joint[3]; + struct { + RK_U8 sign; + RK_U8 classes[10]; + RK_U8 class0; + RK_U8 bits[10]; + RK_U8 class0_fp[2][3]; + RK_U8 fp[3]; + RK_U8 class0_hp; + RK_U8 hp; + } mv_comp[2]; + RK_U8 partition[4][4][3]; +} prob_context; + +static const prob_context vp9_default_probs = { + { /* y_mode */ + { 65, 32, 18, 144, 162, 194, 41, 51, 98 } /* bsize < 8x8 */, + { 132, 68, 18, 165, 217, 196, 45, 40, 78 } /* bsize < 16x16 */, + { 173, 80, 19, 176, 240, 193, 64, 35, 46 } /* bsize < 32x32 */, + { 221, 135, 38, 194, 248, 121, 96, 85, 29 } /* bsize >= 32x32 */ + }, { /* uv_mode */ + { 48, 12, 154, 155, 139, 90, 34, 117, 119 } /* y = v */, + { 67, 6, 25, 204, 243, 158, 13, 21, 96 } /* y = h */, + { 120, 7, 76, 176, 208, 126, 28, 54, 103 } /* y = dc */, + { 97, 5, 44, 131, 176, 139, 48, 68, 97 } /* y = d45 */, + { 83, 5, 42, 156, 111, 152, 26, 49, 152 } /* y = d135 */, + { 80, 5, 58, 178, 74, 83, 33, 62, 145 } /* y = d117 */, + { 86, 5, 32, 154, 192, 168, 14, 22, 163 } /* y = d153 */, + { 77, 7, 64, 116, 132, 122, 37, 126, 120 } /* y = d63 */, + { 85, 5, 32, 156, 216, 148, 19, 29, 73 } /* y = d207 */, + { 101, 21, 107, 181, 192, 103, 19, 67, 125 } /* y = tm */ + }, { /* filter */ + { 235, 162, }, + { 36, 255, }, + { 34, 3, }, + { 149, 144, }, + }, { /* mv_mode */ + { 2, 173, 34}, // 0 = both zero mv + { 7, 145, 85}, // 1 = one zero mv + one a predicted mv + { 7, 166, 63}, // 2 = two predicted mvs + { 7, 94, 66}, // 3 = one predicted/zero and one new mv + { 8, 64, 46}, // 4 = two new mvs + { 17, 81, 31}, // 5 = one intra neighbour + x + { 25, 29, 30}, // 6 = two intra neighbours + }, { /* intra */ + 9, 102, 187, 225 + }, { /* comp */ + 239, 183, 119, 96, 41 + }, { /* single_ref */ + { 33, 16 }, + { 77, 74 }, + { 142, 142 }, + { 172, 170 }, + { 238, 247 } + }, { /* comp_ref */ + 50, 126, 123, 221, 226 + }, { /* tx32p */ + { 3, 136, 37, }, + { 5, 52, 13, }, + }, { /* tx16p */ + { 20, 152, }, + { 15, 101, }, + }, { /* tx8p */ + 100, 66 + }, { /* skip */ + 192, 128, 64 + }, { /* mv_joint */ + 32, 64, 96 + }, { + { /* mv vertical component */ + 128, /* sign */ + { 224, 144, 192, 168, 192, 176, 192, 198, 198, 245 }, /* class */ + 216, /* class0 */ + { 136, 140, 148, 160, 176, 192, 224, 234, 234, 240}, /* bits */ + { /* class0_fp */ + { 128, 128, 64 }, + { 96, 112, 64 } + }, + { 64, 96, 64 }, /* fp */ + 160, /* class0_hp bit */ + 128, /* hp */ + }, { /* mv horizontal component */ + 128, /* sign */ + { 216, 128, 176, 160, 176, 176, 192, 198, 198, 208 }, /* class */ + 208, /* class0 */ + { 136, 140, 148, 160, 176, 192, 224, 234, 234, 240 }, /* bits */ + { /* class0_fp */ + { 128, 128, 64 }, + { 96, 112, 64 } + }, + { 64, 96, 64 }, /* fp */ + 160, /* class0_hp bit */ + 128, /* hp */ + } + }, { /* partition */ + { /* 64x64 -> 32x32 */ + { 222, 34, 30 } /* a/l both not split */, + { 72, 16, 44 } /* a split, l not split */, + { 58, 32, 12 } /* l split, a not split */, + { 10, 7, 6 } /* a/l both split */, + }, { /* 32x32 -> 16x16 */ + { 177, 58, 59 } /* a/l both not split */, + { 68, 26, 63 } /* a split, l not split */, + { 52, 79, 25 } /* l split, a not split */, + { 17, 14, 12 } /* a/l both split */, + }, { /* 16x16 -> 8x8 */ + { 174, 73, 87 } /* a/l both not split */, + { 92, 41, 83 } /* a split, l not split */, + { 82, 99, 50 } /* l split, a not split */, + { 53, 39, 39 } /* a/l both split */, + }, { /* 8x8 -> 4x4 */ + { 199, 122, 141 } /* a/l both not split */, + { 147, 63, 159 } /* a split, l not split */, + { 148, 133, 118 } /* l split, a not split */, + { 121, 104, 114 } /* a/l both split */, + } + }, +}; + +static const RK_U8 vp9_default_coef_probs[4][2][2][6][6][3] = { + { /* tx = 4x4 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 195, 29, 183 }, + { 84, 49, 136 }, + { 8, 42, 71 } + }, { /* Coeff Band 1 */ + { 31, 107, 169 }, + { 35, 99, 159 }, + { 17, 82, 140 }, + { 8, 66, 114 }, + { 2, 44, 76 }, + { 1, 19, 32 } + }, { /* Coeff Band 2 */ + { 40, 132, 201 }, + { 29, 114, 187 }, + { 13, 91, 157 }, + { 7, 75, 127 }, + { 3, 58, 95 }, + { 1, 28, 47 } + }, { /* Coeff Band 3 */ + { 69, 142, 221 }, + { 42, 122, 201 }, + { 15, 91, 159 }, + { 6, 67, 121 }, + { 1, 42, 77 }, + { 1, 17, 31 } + }, { /* Coeff Band 4 */ + { 102, 148, 228 }, + { 67, 117, 204 }, + { 17, 82, 154 }, + { 6, 59, 114 }, + { 2, 39, 75 }, + { 1, 15, 29 } + }, { /* Coeff Band 5 */ + { 156, 57, 233 }, + { 119, 57, 212 }, + { 58, 48, 163 }, + { 29, 40, 124 }, + { 12, 30, 81 }, + { 3, 12, 31 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 191, 107, 226 }, + { 124, 117, 204 }, + { 25, 99, 155 } + }, { /* Coeff Band 1 */ + { 29, 148, 210 }, + { 37, 126, 194 }, + { 8, 93, 157 }, + { 2, 68, 118 }, + { 1, 39, 69 }, + { 1, 17, 33 } + }, { /* Coeff Band 2 */ + { 41, 151, 213 }, + { 27, 123, 193 }, + { 3, 82, 144 }, + { 1, 58, 105 }, + { 1, 32, 60 }, + { 1, 13, 26 } + }, { /* Coeff Band 3 */ + { 59, 159, 220 }, + { 23, 126, 198 }, + { 4, 88, 151 }, + { 1, 66, 114 }, + { 1, 38, 71 }, + { 1, 18, 34 } + }, { /* Coeff Band 4 */ + { 114, 136, 232 }, + { 51, 114, 207 }, + { 11, 83, 155 }, + { 3, 56, 105 }, + { 1, 33, 65 }, + { 1, 17, 34 } + }, { /* Coeff Band 5 */ + { 149, 65, 234 }, + { 121, 57, 215 }, + { 61, 49, 166 }, + { 28, 36, 114 }, + { 12, 25, 76 }, + { 3, 16, 42 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 214, 49, 220 }, + { 132, 63, 188 }, + { 42, 65, 137 } + }, { /* Coeff Band 1 */ + { 85, 137, 221 }, + { 104, 131, 216 }, + { 49, 111, 192 }, + { 21, 87, 155 }, + { 2, 49, 87 }, + { 1, 16, 28 } + }, { /* Coeff Band 2 */ + { 89, 163, 230 }, + { 90, 137, 220 }, + { 29, 100, 183 }, + { 10, 70, 135 }, + { 2, 42, 81 }, + { 1, 17, 33 } + }, { /* Coeff Band 3 */ + { 108, 167, 237 }, + { 55, 133, 222 }, + { 15, 97, 179 }, + { 4, 72, 135 }, + { 1, 45, 85 }, + { 1, 19, 38 } + }, { /* Coeff Band 4 */ + { 124, 146, 240 }, + { 66, 124, 224 }, + { 17, 88, 175 }, + { 4, 58, 122 }, + { 1, 36, 75 }, + { 1, 18, 37 } + }, { /* Coeff Band 5 */ + { 141, 79, 241 }, + { 126, 70, 227 }, + { 66, 58, 182 }, + { 30, 44, 136 }, + { 12, 34, 96 }, + { 2, 20, 47 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 229, 99, 249 }, + { 143, 111, 235 }, + { 46, 109, 192 } + }, { /* Coeff Band 1 */ + { 82, 158, 236 }, + { 94, 146, 224 }, + { 25, 117, 191 }, + { 9, 87, 149 }, + { 3, 56, 99 }, + { 1, 33, 57 } + }, { /* Coeff Band 2 */ + { 83, 167, 237 }, + { 68, 145, 222 }, + { 10, 103, 177 }, + { 2, 72, 131 }, + { 1, 41, 79 }, + { 1, 20, 39 } + }, { /* Coeff Band 3 */ + { 99, 167, 239 }, + { 47, 141, 224 }, + { 10, 104, 178 }, + { 2, 73, 133 }, + { 1, 44, 85 }, + { 1, 22, 47 } + }, { /* Coeff Band 4 */ + { 127, 145, 243 }, + { 71, 129, 228 }, + { 17, 93, 177 }, + { 3, 61, 124 }, + { 1, 41, 84 }, + { 1, 21, 52 } + }, { /* Coeff Band 5 */ + { 157, 78, 244 }, + { 140, 72, 231 }, + { 69, 58, 184 }, + { 31, 44, 137 }, + { 14, 38, 105 }, + { 8, 23, 61 } + } + } + } + }, { /* tx = 8x8 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 125, 34, 187 }, + { 52, 41, 133 }, + { 6, 31, 56 } + }, { /* Coeff Band 1 */ + { 37, 109, 153 }, + { 51, 102, 147 }, + { 23, 87, 128 }, + { 8, 67, 101 }, + { 1, 41, 63 }, + { 1, 19, 29 } + }, { /* Coeff Band 2 */ + { 31, 154, 185 }, + { 17, 127, 175 }, + { 6, 96, 145 }, + { 2, 73, 114 }, + { 1, 51, 82 }, + { 1, 28, 45 } + }, { /* Coeff Band 3 */ + { 23, 163, 200 }, + { 10, 131, 185 }, + { 2, 93, 148 }, + { 1, 67, 111 }, + { 1, 41, 69 }, + { 1, 14, 24 } + }, { /* Coeff Band 4 */ + { 29, 176, 217 }, + { 12, 145, 201 }, + { 3, 101, 156 }, + { 1, 69, 111 }, + { 1, 39, 63 }, + { 1, 14, 23 } + }, { /* Coeff Band 5 */ + { 57, 192, 233 }, + { 25, 154, 215 }, + { 6, 109, 167 }, + { 3, 78, 118 }, + { 1, 48, 69 }, + { 1, 21, 29 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 202, 105, 245 }, + { 108, 106, 216 }, + { 18, 90, 144 } + }, { /* Coeff Band 1 */ + { 33, 172, 219 }, + { 64, 149, 206 }, + { 14, 117, 177 }, + { 5, 90, 141 }, + { 2, 61, 95 }, + { 1, 37, 57 } + }, { /* Coeff Band 2 */ + { 33, 179, 220 }, + { 11, 140, 198 }, + { 1, 89, 148 }, + { 1, 60, 104 }, + { 1, 33, 57 }, + { 1, 12, 21 } + }, { /* Coeff Band 3 */ + { 30, 181, 221 }, + { 8, 141, 198 }, + { 1, 87, 145 }, + { 1, 58, 100 }, + { 1, 31, 55 }, + { 1, 12, 20 } + }, { /* Coeff Band 4 */ + { 32, 186, 224 }, + { 7, 142, 198 }, + { 1, 86, 143 }, + { 1, 58, 100 }, + { 1, 31, 55 }, + { 1, 12, 22 } + }, { /* Coeff Band 5 */ + { 57, 192, 227 }, + { 20, 143, 204 }, + { 3, 96, 154 }, + { 1, 68, 112 }, + { 1, 42, 69 }, + { 1, 19, 32 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 212, 35, 215 }, + { 113, 47, 169 }, + { 29, 48, 105 } + }, { /* Coeff Band 1 */ + { 74, 129, 203 }, + { 106, 120, 203 }, + { 49, 107, 178 }, + { 19, 84, 144 }, + { 4, 50, 84 }, + { 1, 15, 25 } + }, { /* Coeff Band 2 */ + { 71, 172, 217 }, + { 44, 141, 209 }, + { 15, 102, 173 }, + { 6, 76, 133 }, + { 2, 51, 89 }, + { 1, 24, 42 } + }, { /* Coeff Band 3 */ + { 64, 185, 231 }, + { 31, 148, 216 }, + { 8, 103, 175 }, + { 3, 74, 131 }, + { 1, 46, 81 }, + { 1, 18, 30 } + }, { /* Coeff Band 4 */ + { 65, 196, 235 }, + { 25, 157, 221 }, + { 5, 105, 174 }, + { 1, 67, 120 }, + { 1, 38, 69 }, + { 1, 15, 30 } + }, { /* Coeff Band 5 */ + { 65, 204, 238 }, + { 30, 156, 224 }, + { 7, 107, 177 }, + { 2, 70, 124 }, + { 1, 42, 73 }, + { 1, 18, 34 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 225, 86, 251 }, + { 144, 104, 235 }, + { 42, 99, 181 } + }, { /* Coeff Band 1 */ + { 85, 175, 239 }, + { 112, 165, 229 }, + { 29, 136, 200 }, + { 12, 103, 162 }, + { 6, 77, 123 }, + { 2, 53, 84 } + }, { /* Coeff Band 2 */ + { 75, 183, 239 }, + { 30, 155, 221 }, + { 3, 106, 171 }, + { 1, 74, 128 }, + { 1, 44, 76 }, + { 1, 17, 28 } + }, { /* Coeff Band 3 */ + { 73, 185, 240 }, + { 27, 159, 222 }, + { 2, 107, 172 }, + { 1, 75, 127 }, + { 1, 42, 73 }, + { 1, 17, 29 } + }, { /* Coeff Band 4 */ + { 62, 190, 238 }, + { 21, 159, 222 }, + { 2, 107, 172 }, + { 1, 72, 122 }, + { 1, 40, 71 }, + { 1, 18, 32 } + }, { /* Coeff Band 5 */ + { 61, 199, 240 }, + { 27, 161, 226 }, + { 4, 113, 180 }, + { 1, 76, 129 }, + { 1, 46, 80 }, + { 1, 23, 41 } + } + } + } + }, { /* tx = 16x16 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 7, 27, 153 }, + { 5, 30, 95 }, + { 1, 16, 30 } + }, { /* Coeff Band 1 */ + { 50, 75, 127 }, + { 57, 75, 124 }, + { 27, 67, 108 }, + { 10, 54, 86 }, + { 1, 33, 52 }, + { 1, 12, 18 } + }, { /* Coeff Band 2 */ + { 43, 125, 151 }, + { 26, 108, 148 }, + { 7, 83, 122 }, + { 2, 59, 89 }, + { 1, 38, 60 }, + { 1, 17, 27 } + }, { /* Coeff Band 3 */ + { 23, 144, 163 }, + { 13, 112, 154 }, + { 2, 75, 117 }, + { 1, 50, 81 }, + { 1, 31, 51 }, + { 1, 14, 23 } + }, { /* Coeff Band 4 */ + { 18, 162, 185 }, + { 6, 123, 171 }, + { 1, 78, 125 }, + { 1, 51, 86 }, + { 1, 31, 54 }, + { 1, 14, 23 } + }, { /* Coeff Band 5 */ + { 15, 199, 227 }, + { 3, 150, 204 }, + { 1, 91, 146 }, + { 1, 55, 95 }, + { 1, 30, 53 }, + { 1, 11, 20 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 19, 55, 240 }, + { 19, 59, 196 }, + { 3, 52, 105 } + }, { /* Coeff Band 1 */ + { 41, 166, 207 }, + { 104, 153, 199 }, + { 31, 123, 181 }, + { 14, 101, 152 }, + { 5, 72, 106 }, + { 1, 36, 52 } + }, { /* Coeff Band 2 */ + { 35, 176, 211 }, + { 12, 131, 190 }, + { 2, 88, 144 }, + { 1, 60, 101 }, + { 1, 36, 60 }, + { 1, 16, 28 } + }, { /* Coeff Band 3 */ + { 28, 183, 213 }, + { 8, 134, 191 }, + { 1, 86, 142 }, + { 1, 56, 96 }, + { 1, 30, 53 }, + { 1, 12, 20 } + }, { /* Coeff Band 4 */ + { 20, 190, 215 }, + { 4, 135, 192 }, + { 1, 84, 139 }, + { 1, 53, 91 }, + { 1, 28, 49 }, + { 1, 11, 20 } + }, { /* Coeff Band 5 */ + { 13, 196, 216 }, + { 2, 137, 192 }, + { 1, 86, 143 }, + { 1, 57, 99 }, + { 1, 32, 56 }, + { 1, 13, 24 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 211, 29, 217 }, + { 96, 47, 156 }, + { 22, 43, 87 } + }, { /* Coeff Band 1 */ + { 78, 120, 193 }, + { 111, 116, 186 }, + { 46, 102, 164 }, + { 15, 80, 128 }, + { 2, 49, 76 }, + { 1, 18, 28 } + }, { /* Coeff Band 2 */ + { 71, 161, 203 }, + { 42, 132, 192 }, + { 10, 98, 150 }, + { 3, 69, 109 }, + { 1, 44, 70 }, + { 1, 18, 29 } + }, { /* Coeff Band 3 */ + { 57, 186, 211 }, + { 30, 140, 196 }, + { 4, 93, 146 }, + { 1, 62, 102 }, + { 1, 38, 65 }, + { 1, 16, 27 } + }, { /* Coeff Band 4 */ + { 47, 199, 217 }, + { 14, 145, 196 }, + { 1, 88, 142 }, + { 1, 57, 98 }, + { 1, 36, 62 }, + { 1, 15, 26 } + }, { /* Coeff Band 5 */ + { 26, 219, 229 }, + { 5, 155, 207 }, + { 1, 94, 151 }, + { 1, 60, 104 }, + { 1, 36, 62 }, + { 1, 16, 28 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 233, 29, 248 }, + { 146, 47, 220 }, + { 43, 52, 140 } + }, { /* Coeff Band 1 */ + { 100, 163, 232 }, + { 179, 161, 222 }, + { 63, 142, 204 }, + { 37, 113, 174 }, + { 26, 89, 137 }, + { 18, 68, 97 } + }, { /* Coeff Band 2 */ + { 85, 181, 230 }, + { 32, 146, 209 }, + { 7, 100, 164 }, + { 3, 71, 121 }, + { 1, 45, 77 }, + { 1, 18, 30 } + }, { /* Coeff Band 3 */ + { 65, 187, 230 }, + { 20, 148, 207 }, + { 2, 97, 159 }, + { 1, 68, 116 }, + { 1, 40, 70 }, + { 1, 14, 29 } + }, { /* Coeff Band 4 */ + { 40, 194, 227 }, + { 8, 147, 204 }, + { 1, 94, 155 }, + { 1, 65, 112 }, + { 1, 39, 66 }, + { 1, 14, 26 } + }, { /* Coeff Band 5 */ + { 16, 208, 228 }, + { 3, 151, 207 }, + { 1, 98, 160 }, + { 1, 67, 117 }, + { 1, 41, 74 }, + { 1, 17, 31 } + } + } + } + }, { /* tx = 32x32 */ + { /* block Type 0 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 17, 38, 140 }, + { 7, 34, 80 }, + { 1, 17, 29 } + }, { /* Coeff Band 1 */ + { 37, 75, 128 }, + { 41, 76, 128 }, + { 26, 66, 116 }, + { 12, 52, 94 }, + { 2, 32, 55 }, + { 1, 10, 16 } + }, { /* Coeff Band 2 */ + { 50, 127, 154 }, + { 37, 109, 152 }, + { 16, 82, 121 }, + { 5, 59, 85 }, + { 1, 35, 54 }, + { 1, 13, 20 } + }, { /* Coeff Band 3 */ + { 40, 142, 167 }, + { 17, 110, 157 }, + { 2, 71, 112 }, + { 1, 44, 72 }, + { 1, 27, 45 }, + { 1, 11, 17 } + }, { /* Coeff Band 4 */ + { 30, 175, 188 }, + { 9, 124, 169 }, + { 1, 74, 116 }, + { 1, 48, 78 }, + { 1, 30, 49 }, + { 1, 11, 18 } + }, { /* Coeff Band 5 */ + { 10, 222, 223 }, + { 2, 150, 194 }, + { 1, 83, 128 }, + { 1, 48, 79 }, + { 1, 27, 45 }, + { 1, 11, 17 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 36, 41, 235 }, + { 29, 36, 193 }, + { 10, 27, 111 } + }, { /* Coeff Band 1 */ + { 85, 165, 222 }, + { 177, 162, 215 }, + { 110, 135, 195 }, + { 57, 113, 168 }, + { 23, 83, 120 }, + { 10, 49, 61 } + }, { /* Coeff Band 2 */ + { 85, 190, 223 }, + { 36, 139, 200 }, + { 5, 90, 146 }, + { 1, 60, 103 }, + { 1, 38, 65 }, + { 1, 18, 30 } + }, { /* Coeff Band 3 */ + { 72, 202, 223 }, + { 23, 141, 199 }, + { 2, 86, 140 }, + { 1, 56, 97 }, + { 1, 36, 61 }, + { 1, 16, 27 } + }, { /* Coeff Band 4 */ + { 55, 218, 225 }, + { 13, 145, 200 }, + { 1, 86, 141 }, + { 1, 57, 99 }, + { 1, 35, 61 }, + { 1, 13, 22 } + }, { /* Coeff Band 5 */ + { 15, 235, 212 }, + { 1, 132, 184 }, + { 1, 84, 139 }, + { 1, 57, 97 }, + { 1, 34, 56 }, + { 1, 14, 23 } + } + } + }, { /* block Type 1 */ + { /* Intra */ + { /* Coeff Band 0 */ + { 181, 21, 201 }, + { 61, 37, 123 }, + { 10, 38, 71 } + }, { /* Coeff Band 1 */ + { 47, 106, 172 }, + { 95, 104, 173 }, + { 42, 93, 159 }, + { 18, 77, 131 }, + { 4, 50, 81 }, + { 1, 17, 23 } + }, { /* Coeff Band 2 */ + { 62, 147, 199 }, + { 44, 130, 189 }, + { 28, 102, 154 }, + { 18, 75, 115 }, + { 2, 44, 65 }, + { 1, 12, 19 } + }, { /* Coeff Band 3 */ + { 55, 153, 210 }, + { 24, 130, 194 }, + { 3, 93, 146 }, + { 1, 61, 97 }, + { 1, 31, 50 }, + { 1, 10, 16 } + }, { /* Coeff Band 4 */ + { 49, 186, 223 }, + { 17, 148, 204 }, + { 1, 96, 142 }, + { 1, 53, 83 }, + { 1, 26, 44 }, + { 1, 11, 17 } + }, { /* Coeff Band 5 */ + { 13, 217, 212 }, + { 2, 136, 180 }, + { 1, 78, 124 }, + { 1, 50, 83 }, + { 1, 29, 49 }, + { 1, 14, 23 } + } + }, { /* Inter */ + { /* Coeff Band 0 */ + { 197, 13, 247 }, + { 82, 17, 222 }, + { 25, 17, 162 } + }, { /* Coeff Band 1 */ + { 126, 186, 247 }, + { 234, 191, 243 }, + { 176, 177, 234 }, + { 104, 158, 220 }, + { 66, 128, 186 }, + { 55, 90, 137 } + }, { /* Coeff Band 2 */ + { 111, 197, 242 }, + { 46, 158, 219 }, + { 9, 104, 171 }, + { 2, 65, 125 }, + { 1, 44, 80 }, + { 1, 17, 91 } + }, { /* Coeff Band 3 */ + { 104, 208, 245 }, + { 39, 168, 224 }, + { 3, 109, 162 }, + { 1, 79, 124 }, + { 1, 50, 102 }, + { 1, 43, 102 } + }, { /* Coeff Band 4 */ + { 84, 220, 246 }, + { 31, 177, 231 }, + { 2, 115, 180 }, + { 1, 79, 134 }, + { 1, 55, 77 }, + { 1, 60, 79 } + }, { /* Coeff Band 5 */ + { 43, 243, 240 }, + { 8, 180, 217 }, + { 1, 115, 166 }, + { 1, 84, 121 }, + { 1, 51, 67 }, + { 1, 16, 6 } + } + } + } + } +}; + +const vp9_prob vp9_kf_y_mode_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1] = { + { + // above = dc + { 137, 30, 42, 148, 151, 207, 70, 52, 91 }, // left = dc + { 92, 45, 102, 136, 116, 180, 74, 90, 100 }, // left = v + { 73, 32, 19, 187, 222, 215, 46, 34, 100 }, // left = h + { 91, 30, 32, 116, 121, 186, 93, 86, 94 }, // left = d45 + { 72, 35, 36, 149, 68, 206, 68, 63, 105 }, // left = d135 + { 73, 31, 28, 138, 57, 124, 55, 122, 151 }, // left = d117 + { 67, 23, 21, 140, 126, 197, 40, 37, 171 }, // left = d153 + { 86, 27, 28, 128, 154, 212, 45, 43, 53 }, // left = d207 + { 74, 32, 27, 107, 86, 160, 63, 134, 102 }, // left = d63 + { 59, 67, 44, 140, 161, 202, 78, 67, 119 } // left = tm + }, { // above = v + { 63, 36, 126, 146, 123, 158, 60, 90, 96 }, // left = dc + { 43, 46, 168, 134, 107, 128, 69, 142, 92 }, // left = v + { 44, 29, 68, 159, 201, 177, 50, 57, 77 }, // left = h + { 58, 38, 76, 114, 97, 172, 78, 133, 92 }, // left = d45 + { 46, 41, 76, 140, 63, 184, 69, 112, 57 }, // left = d135 + { 38, 32, 85, 140, 46, 112, 54, 151, 133 }, // left = d117 + { 39, 27, 61, 131, 110, 175, 44, 75, 136 }, // left = d153 + { 52, 30, 74, 113, 130, 175, 51, 64, 58 }, // left = d207 + { 47, 35, 80, 100, 74, 143, 64, 163, 74 }, // left = d63 + { 36, 61, 116, 114, 128, 162, 80, 125, 82 } // left = tm + }, { // above = h + { 82, 26, 26, 171, 208, 204, 44, 32, 105 }, // left = dc + { 55, 44, 68, 166, 179, 192, 57, 57, 108 }, // left = v + { 42, 26, 11, 199, 241, 228, 23, 15, 85 }, // left = h + { 68, 42, 19, 131, 160, 199, 55, 52, 83 }, // left = d45 + { 58, 50, 25, 139, 115, 232, 39, 52, 118 }, // left = d135 + { 50, 35, 33, 153, 104, 162, 64, 59, 131 }, // left = d117 + { 44, 24, 16, 150, 177, 202, 33, 19, 156 }, // left = d153 + { 55, 27, 12, 153, 203, 218, 26, 27, 49 }, // left = d207 + { 53, 49, 21, 110, 116, 168, 59, 80, 76 }, // left = d63 + { 38, 72, 19, 168, 203, 212, 50, 50, 107 } // left = tm + }, { // above = d45 + { 103, 26, 36, 129, 132, 201, 83, 80, 93 }, // left = dc + { 59, 38, 83, 112, 103, 162, 98, 136, 90 }, // left = v + { 62, 30, 23, 158, 200, 207, 59, 57, 50 }, // left = h + { 67, 30, 29, 84, 86, 191, 102, 91, 59 }, // left = d45 + { 60, 32, 33, 112, 71, 220, 64, 89, 104 }, // left = d135 + { 53, 26, 34, 130, 56, 149, 84, 120, 103 }, // left = d117 + { 53, 21, 23, 133, 109, 210, 56, 77, 172 }, // left = d153 + { 77, 19, 29, 112, 142, 228, 55, 66, 36 }, // left = d207 + { 61, 29, 29, 93, 97, 165, 83, 175, 162 }, // left = d63 + { 47, 47, 43, 114, 137, 181, 100, 99, 95 } // left = tm + }, { // above = d135 + { 69, 23, 29, 128, 83, 199, 46, 44, 101 }, // left = dc + { 53, 40, 55, 139, 69, 183, 61, 80, 110 }, // left = v + { 40, 29, 19, 161, 180, 207, 43, 24, 91 }, // left = h + { 60, 34, 19, 105, 61, 198, 53, 64, 89 }, // left = d45 + { 52, 31, 22, 158, 40, 209, 58, 62, 89 }, // left = d135 + { 44, 31, 29, 147, 46, 158, 56, 102, 198 }, // left = d117 + { 35, 19, 12, 135, 87, 209, 41, 45, 167 }, // left = d153 + { 55, 25, 21, 118, 95, 215, 38, 39, 66 }, // left = d207 + { 51, 38, 25, 113, 58, 164, 70, 93, 97 }, // left = d63 + { 47, 54, 34, 146, 108, 203, 72, 103, 151 } // left = tm + }, { // above = d117 + { 64, 19, 37, 156, 66, 138, 49, 95, 133 }, // left = dc + { 46, 27, 80, 150, 55, 124, 55, 121, 135 }, // left = v + { 36, 23, 27, 165, 149, 166, 54, 64, 118 }, // left = h + { 53, 21, 36, 131, 63, 163, 60, 109, 81 }, // left = d45 + { 40, 26, 35, 154, 40, 185, 51, 97, 123 }, // left = d135 + { 35, 19, 34, 179, 19, 97, 48, 129, 124 }, // left = d117 + { 36, 20, 26, 136, 62, 164, 33, 77, 154 }, // left = d153 + { 45, 18, 32, 130, 90, 157, 40, 79, 91 }, // left = d207 + { 45, 26, 28, 129, 45, 129, 49, 147, 123 }, // left = d63 + { 38, 44, 51, 136, 74, 162, 57, 97, 121 } // left = tm + }, { // above = d153 + { 75, 17, 22, 136, 138, 185, 32, 34, 166 }, // left = dc + { 56, 39, 58, 133, 117, 173, 48, 53, 187 }, // left = v + { 35, 21, 12, 161, 212, 207, 20, 23, 145 }, // left = h + { 56, 29, 19, 117, 109, 181, 55, 68, 112 }, // left = d45 + { 47, 29, 17, 153, 64, 220, 59, 51, 114 }, // left = d135 + { 46, 16, 24, 136, 76, 147, 41, 64, 172 }, // left = d117 + { 34, 17, 11, 108, 152, 187, 13, 15, 209 }, // left = d153 + { 51, 24, 14, 115, 133, 209, 32, 26, 104 }, // left = d207 + { 55, 30, 18, 122, 79, 179, 44, 88, 116 }, // left = d63 + { 37, 49, 25, 129, 168, 164, 41, 54, 148 } // left = tm + }, { // above = d207 + { 82, 22, 32, 127, 143, 213, 39, 41, 70 }, // left = dc + { 62, 44, 61, 123, 105, 189, 48, 57, 64 }, // left = v + { 47, 25, 17, 175, 222, 220, 24, 30, 86 }, // left = h + { 68, 36, 17, 106, 102, 206, 59, 74, 74 }, // left = d45 + { 57, 39, 23, 151, 68, 216, 55, 63, 58 }, // left = d135 + { 49, 30, 35, 141, 70, 168, 82, 40, 115 }, // left = d117 + { 51, 25, 15, 136, 129, 202, 38, 35, 139 }, // left = d153 + { 68, 26, 16, 111, 141, 215, 29, 28, 28 }, // left = d207 + { 59, 39, 19, 114, 75, 180, 77, 104, 42 }, // left = d63 + { 40, 61, 26, 126, 152, 206, 61, 59, 93 } // left = tm + }, { // above = d63 + { 78, 23, 39, 111, 117, 170, 74, 124, 94 }, // left = dc + { 48, 34, 86, 101, 92, 146, 78, 179, 134 }, // left = v + { 47, 22, 24, 138, 187, 178, 68, 69, 59 }, // left = h + { 56, 25, 33, 105, 112, 187, 95, 177, 129 }, // left = d45 + { 48, 31, 27, 114, 63, 183, 82, 116, 56 }, // left = d135 + { 43, 28, 37, 121, 63, 123, 61, 192, 169 }, // left = d117 + { 42, 17, 24, 109, 97, 177, 56, 76, 122 }, // left = d153 + { 58, 18, 28, 105, 139, 182, 70, 92, 63 }, // left = d207 + { 46, 23, 32, 74, 86, 150, 67, 183, 88 }, // left = d63 + { 36, 38, 48, 92, 122, 165, 88, 137, 91 } // left = tm + }, { // above = tm + { 65, 70, 60, 155, 159, 199, 61, 60, 81 }, // left = dc + { 44, 78, 115, 132, 119, 173, 71, 112, 93 }, // left = v + { 39, 38, 21, 184, 227, 206, 42, 32, 64 }, // left = h + { 58, 47, 36, 124, 137, 193, 80, 82, 78 }, // left = d45 + { 49, 50, 35, 144, 95, 205, 63, 78, 59 }, // left = d135 + { 41, 53, 52, 148, 71, 142, 65, 128, 51 }, // left = d117 + { 40, 36, 28, 143, 143, 202, 40, 55, 137 }, // left = d153 + { 52, 34, 29, 129, 183, 227, 42, 35, 43 }, // left = d207 + { 42, 44, 44, 104, 105, 164, 64, 130, 80 }, // left = d63 + { 43, 81, 53, 140, 169, 204, 68, 84, 72 } // left = tm + } +}; + +const vp9_prob vp9_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1] = { + { 144, 11, 54, 157, 195, 130, 46, 58, 108 }, // y = dc + { 118, 15, 123, 148, 131, 101, 44, 93, 131 }, // y = v + { 113, 12, 23, 188, 226, 142, 26, 32, 125 }, // y = h + { 120, 11, 50, 123, 163, 135, 64, 77, 103 }, // y = d45 + { 113, 9, 36, 155, 111, 157, 32, 44, 161 }, // y = d135 + { 116, 9, 55, 176, 76, 96, 37, 61, 149 }, // y = d117 + { 115, 9, 28, 141, 161, 167, 21, 25, 193 }, // y = d153 + { 120, 12, 32, 145, 195, 142, 32, 38, 86 }, // y = d207 + { 116, 12, 64, 120, 140, 125, 49, 115, 121 }, // y = d63 + { 102, 19, 66, 162, 182, 122, 35, 59, 128 } // y = tm +}; + +const vp9_prob vp9_kf_partition_probs[PARTITION_CONTEXTS][PARTITION_TYPES - 1] = { + // 8x8 -> 4x4 + { 158, 97, 94 }, // a/l both not split + { 93, 24, 99 }, // a split, l not split + { 85, 119, 44 }, // l split, a not split + { 62, 59, 67 }, // a/l both split + // 16x16 -> 8x8 + { 149, 53, 53 }, // a/l both not split + { 94, 20, 48 }, // a split, l not split + { 83, 53, 24 }, // l split, a not split + { 52, 18, 18 }, // a/l both split + // 32x32 -> 16x16 + { 150, 40, 39 }, // a/l both not split + { 78, 12, 26 }, // a split, l not split + { 67, 33, 11 }, // l split, a not split + { 24, 7, 5 }, // a/l both split + // 64x64 -> 32x32 + { 174, 35, 49 }, // a/l both not split + { 68, 11, 27 }, // a split, l not split + { 57, 15, 9 }, // l split, a not split + { 12, 3, 3 }, // a/l both split +}; + +#define EIGHTTAP 0 +#define EIGHTTAP_SMOOTH 1 +#define EIGHTTAP_SHARP 2 +#define BILINEAR 3 + +const RK_U8 literal_to_filter[] = {EIGHTTAP_SMOOTH, EIGHTTAP, + EIGHTTAP_SHARP, BILINEAR + }; + +MPP_RET hal_vp9d_output_probe(void *buf, void *dxva) +{ + RK_S32 i, j, k, m, n; + RK_S32 fifo_len = 304; + RK_U64 *probe_packet = NULL; + BitputCtx_t bp; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)dxva; + RK_S32 intraFlag = (!pic_param->frame_type || pic_param->intra_only); + vp9_prob partition_probs[PARTITION_CONTEXTS][PARTITION_TYPES - 1]; + vp9_prob uv_mode_prob[INTRA_MODES][INTRA_MODES - 1]; + + memset(buf, 0, 304 * 8); + + if (intraFlag) { + memcpy(partition_probs, vp9_kf_partition_probs, sizeof(partition_probs)); + memcpy(uv_mode_prob, vp9_kf_uv_mode_prob, sizeof(uv_mode_prob)); + } else { + memcpy(partition_probs, pic_param->prob.partition, sizeof(partition_probs)); + memcpy(uv_mode_prob, pic_param->prob.uv_mode, sizeof(uv_mode_prob)); + } + + probe_packet = mpp_calloc(RK_U64, fifo_len + 1); + mpp_set_bitput_ctx(&bp, probe_packet, fifo_len); + //sb info 5 x 128 bit + for (i = 0; i < PARTITION_CONTEXTS; i++) //kf_partition_prob + for (j = 0; j < PARTITION_TYPES - 1; j++) + mpp_put_bits(&bp, partition_probs[i][j], 8); //48 + + for (i = 0; i < PREDICTION_PROBS; i++) //Segment_id_pred_prob //3 + mpp_put_bits(&bp, pic_param->stVP9Segments.pred_probs[i], 8); + + for (i = 0; i < SEG_TREE_PROBS; i++) //Segment_id_probs + mpp_put_bits(&bp, pic_param->stVP9Segments.tree_probs[i], 8); //7 + + for (i = 0; i < SKIP_CONTEXTS; i++) //Skip_flag_probs //3 + mpp_put_bits(&bp, pic_param->prob.skip[i], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //6 + for (j = 0; j < TX_SIZES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.tx32p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //4 + for (j = 0; j < TX_SIZES - 2; j++) + mpp_put_bits(&bp, pic_param->prob.tx16p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //2 + mpp_put_bits(&bp, pic_param->prob.tx8p[i], 8); + + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) //Tx_size_probs //4 + mpp_put_bits(&bp, pic_param->prob.intra[i], 8); + + mpp_put_align(&bp, 128, 0); + if (intraFlag) { //intra probs + //intra only //149 x 128 bit ,aligned to 152 x 128 bit + //coeff releated prob 64 x 128 bit + for (i = 0; i < TX_SIZES; i++) + for (j = 0; j < PLANE_TYPES; j++) { + RK_S32 byte_count = 0; + for (k = 0; k < COEF_BANDS; k++) { + for (m = 0; m < COEFF_CONTEXTS; m++) + for (n = 0; n < UNCONSTRAINED_NODES; n++) { + mpp_put_bits(&bp, pic_param->prob.coef[i][j][0][k][m][n], 8); + + byte_count++; + if (byte_count == 27) { + mpp_put_align(&bp, 128, 0); + byte_count = 0; + } + } + } + mpp_put_align(&bp, 128, 0); + } + + //intra mode prob 80 x 128 bit + for (i = 0; i < INTRA_MODES; i++) { //vp9_kf_y_mode_prob + RK_S32 byte_count = 0; + for (j = 0; j < INTRA_MODES; j++) + for (k = 0; k < INTRA_MODES - 1; k++) { + mpp_put_bits(&bp, vp9_kf_y_mode_prob[i][j][k], 8); + byte_count++; + if (byte_count == 27) { + byte_count = 0; + mpp_put_align(&bp, 128, 0); + } + + } + if (i < 4) { + for (m = 0; m < (i < 3 ? 23 : 21); m++) + mpp_put_bits(&bp, ((vp9_prob *)(&vp9_kf_uv_mode_prob[0][0]))[i * 23 + m], 8); + for (; m < 23; m++) + mpp_put_bits(&bp, 0, 8); + } else { + for (m = 0; m < 23; m++) + mpp_put_bits(&bp, 0, 8); + } + mpp_put_align(&bp, 128, 0); + } + //align to 152 x 128 bit + for (i = 0; i < INTER_PROB_SIZE_ALIGN_TO_128 - INTRA_PROB_SIZE_ALIGN_TO_128; i++) { //aligned to 153 x 256 bit + mpp_put_bits(&bp, 0, 8); + mpp_put_align(&bp, 128, 0); + } + } else { + //inter probs + //151 x 128 bit ,aligned to 152 x 128 bit + //inter only + + //intra_y_mode & inter_block info 6 x 128 bit + for (i = 0; i < BLOCK_SIZE_GROUPS; i++) //intra_y_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.y_mode[i][j], 8); + + for (i = 0; i < COMP_INTER_CONTEXTS; i++) //reference_mode prob + mpp_put_bits(&bp, pic_param->prob.comp[i], 8); + + for (i = 0; i < REF_CONTEXTS; i++) //comp ref bit + mpp_put_bits(&bp, pic_param->prob.comp_ref[i], 8); + + for (i = 0; i < REF_CONTEXTS; i++) //single ref bit + for (j = 0; j < 2; j++) + mpp_put_bits(&bp, pic_param->prob.single_ref[i][j], 8); + + for (i = 0; i < INTER_MODE_CONTEXTS; i++) //mv mode bit + for (j = 0; j < INTER_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.mv_mode[i][j], 8); + + + for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) //comp ref bit + for (j = 0; j < SWITCHABLE_FILTERS - 1; j++) + mpp_put_bits(&bp, pic_param->prob.filter[i][j], 8); + + mpp_put_align(&bp, 128, 0); + + //128 x 128bit + //coeff releated + for (i = 0; i < TX_SIZES; i++) + for (j = 0; j < PLANE_TYPES; j++) { + RK_S32 byte_count = 0; + for (k = 0; k < COEF_BANDS; k++) { + for (m = 0; m < COEFF_CONTEXTS; m++) + for (n = 0; n < UNCONSTRAINED_NODES; n++) { + mpp_put_bits(&bp, pic_param->prob.coef[i][j][0][k][m][n], 8); + byte_count++; + if (byte_count == 27) { + mpp_put_align(&bp, 128, 0); + byte_count = 0; + } + } + } + mpp_put_align(&bp, 128, 0); + } + for (i = 0; i < TX_SIZES; i++) + for (j = 0; j < PLANE_TYPES; j++) { + RK_S32 byte_count = 0; + for (k = 0; k < COEF_BANDS; k++) { + for (m = 0; m < COEFF_CONTEXTS; m++) { + for (n = 0; n < UNCONSTRAINED_NODES; n++) { + mpp_put_bits(&bp, pic_param->prob.coef[i][j][1][k][m][n], 8); + byte_count++; + if (byte_count == 27) { + mpp_put_align(&bp, 128, 0); + byte_count = 0; + } + } + + } + } + mpp_put_align(&bp, 128, 0); + } + + //intra uv mode 6 x 128 + for (i = 0; i < 3; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, uv_mode_prob[i][j], 8); + mpp_put_align(&bp, 128, 0); + + for (; i < 6; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, uv_mode_prob[i][j], 8); + mpp_put_align(&bp, 128, 0); + + for (; i < 9; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, uv_mode_prob[i][j], 8); + mpp_put_align(&bp, 128, 0); + for (; i < INTRA_MODES; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, uv_mode_prob[i][j], 8); + + mpp_put_align(&bp, 128, 0); + mpp_put_bits(&bp, 0, 8); + mpp_put_align(&bp, 128, 0); + + //mv releated 6 x 128 + for (i = 0; i < MV_JOINTS - 1; i++) //mv_joint_type + mpp_put_bits(&bp, pic_param->prob.mv_joint[i], 8); + + for (i = 0; i < 2; i++) { //sign bit + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].sign, 8); + } + for (i = 0; i < 2; i++) { //classes bit + for (j = 0; j < MV_CLASSES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].classes[j], 8); + } + for (i = 0; i < 2; i++) { //classe0 bit + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].class0, 8); + } + for (i = 0; i < 2; i++) { // bits + for (j = 0; j < MV_OFFSET_BITS; j++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].bits[j], 8); + } + for (i = 0; i < 2; i++) { //class0_fp bit + for (j = 0; j < CLASS0_SIZE; j++) + for (k = 0; k < MV_FP_SIZE - 1; k++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].class0_fp[j][k], 8); + } + for (i = 0; i < 2; i++) { //comp ref bit + for (j = 0; j < MV_FP_SIZE - 1; j++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].fp[j], 8); + } + for (i = 0; i < 2; i++) { //class0_hp bit + + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].class0_hp, 8); + } + for (i = 0; i < 2; i++) { //hp bit + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].hp, 8); + } + mpp_put_align(&bp, 128, 0); + } + + memcpy(buf, probe_packet, 304 * 8); + +#ifdef dump + if (intraFlag) { + fwrite(probe_packet, 1, 302 * 8, vp9_fp); + } else { + fwrite(probe_packet, 1, 304 * 8, vp9_fp); + } + fflush(vp9_fp); +#endif + MPP_FREE(probe_packet); + + return 0; +} + +MPP_RET hal_vp9d_prob_default(void *buf, void *dxva) +{ + RK_S32 i, j, k, m, n; + RK_S32 fifo_len = PROB_SIZE >> 3; + RK_U64 *probe_packet = NULL; + BitputCtx_t bp; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)dxva; + RK_S32 intraFlag = (!pic_param->frame_type || pic_param->intra_only); + vp9_prob partition_probs[PARTITION_CONTEXTS][PARTITION_TYPES - 1]; + memset(buf, 0, PROB_SIZE); + + if (intraFlag) { + memcpy(&pic_param->prob.tx32p, &vp9_default_probs.tx32p, sizeof(vp9_default_probs.tx32p)); + memcpy(&pic_param->prob.tx16p, &vp9_default_probs.tx16p, sizeof(vp9_default_probs.tx16p)); + memcpy(&pic_param->prob.tx8p, &vp9_default_probs.tx8p, sizeof(vp9_default_probs.tx8p)); + memcpy(&pic_param->prob.skip, &vp9_default_probs.skip, sizeof(vp9_default_probs.skip)); + memcpy(&pic_param->prob.coef, &vp9_default_coef_probs, sizeof(vp9_default_coef_probs)); + } + memcpy(partition_probs, pic_param->prob.partition, sizeof(partition_probs)); + + probe_packet = mpp_calloc(RK_U64, fifo_len); + memset(probe_packet, 0, fifo_len); + mpp_set_bitput_ctx(&bp, probe_packet, fifo_len); + + //sb info 5 x 128 bit + for (i = 0; i < 16; i++) //kf_partition_prob + for (j = 0; j < 3; j++) + mpp_put_bits(&bp, partition_probs[i][j], 8); //48 + + for (i = 0; i < PREDICTION_PROBS; i++) //Segment_id_pred_prob //3 + mpp_put_bits(&bp, 0, 8); + + for (i = 0; i < SEG_TREE_PROBS; i++) //Segment_id_probs + mpp_put_bits(&bp, 0, 8); //7 + + for (i = 0; i < SKIP_CONTEXTS; i++) //Skip_flag_probs //3 + mpp_put_bits(&bp, pic_param->prob.skip[i], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //6 + for (j = 0; j < TX_SIZES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.tx32p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //4 + for (j = 0; j < TX_SIZES - 2; j++) + mpp_put_bits(&bp, pic_param->prob.tx16p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //2 + mpp_put_bits(&bp, pic_param->prob.tx8p[i], 8); + + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) //Tx_size_probs //4 + mpp_put_bits(&bp, pic_param->prob.intra[i], 8); + + mpp_put_align(&bp, 128, 0); + + //intra_y_mode & inter_block info 6 x 128 bit + for (i = 0; i < BLOCK_SIZE_GROUPS; i++) //intra_y_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.y_mode[i][j], 8); + + for (i = 0; i < COMP_INTER_CONTEXTS; i++) //reference_mode prob + mpp_put_bits(&bp, pic_param->prob.comp[i], 8); + + for (i = 0; i < REF_CONTEXTS; i++) //comp ref bit + mpp_put_bits(&bp, pic_param->prob.comp_ref[i], 8); + + for (i = 0; i < REF_CONTEXTS; i++) //single ref bit + for (j = 0; j < 2; j++) + mpp_put_bits(&bp, pic_param->prob.single_ref[i][j], 8); + + for (i = 0; i < INTER_MODE_CONTEXTS; i++) //mv mode bit + for (j = 0; j < INTER_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.mv_mode[i][j], 8); + + + for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) //comp ref bit + for (j = 0; j < SWITCHABLE_FILTERS - 1; j++) + mpp_put_bits(&bp, pic_param->prob.filter[i][j], 8); + + mpp_put_align(&bp, 128, 0); + + //128 x 128bit + //coeff releated + for (i = 0; i < TX_SIZES; i++) + for (j = 0; j < PLANE_TYPES; j++) { + RK_S32 byte_count = 0; + for (k = 0; k < COEF_BANDS; k++) { + for (m = 0; m < COEFF_CONTEXTS; m++) + for (n = 0; n < UNCONSTRAINED_NODES; n++) { + mpp_put_bits(&bp, pic_param->prob.coef[i][j][0][k][m][n], 8); + byte_count++; + if (byte_count == 27) { + mpp_put_align(&bp, 128, 0); + byte_count = 0; + } + } + } + mpp_put_align(&bp, 128, 0); + } + for (i = 0; i < TX_SIZES; i++) + for (j = 0; j < PLANE_TYPES; j++) { + RK_S32 byte_count = 0; + for (k = 0; k < COEF_BANDS; k++) { + for (m = 0; m < COEFF_CONTEXTS; m++) { + for (n = 0; n < UNCONSTRAINED_NODES; n++) { + mpp_put_bits(&bp, pic_param->prob.coef[i][j][1][k][m][n], 8); + byte_count++; + if (byte_count == 27) { + mpp_put_align(&bp, 128, 0); + byte_count = 0; + } + } + + } + } + mpp_put_align(&bp, 128, 0); + } + + //intra uv mode 6 x 128 + for (i = 0; i < 3; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.uv_mode[i][j], 8); + mpp_put_align(&bp, 128, 0); + + for (; i < 6; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.uv_mode[i][j], 8); + mpp_put_align(&bp, 128, 0); + + for (; i < 9; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.uv_mode[i][j], 8); + mpp_put_align(&bp, 128, 0); + for (; i < INTRA_MODES; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.uv_mode[i][j], 8); + + mpp_put_align(&bp, 128, 0); + mpp_put_bits(&bp, 0, 8); + mpp_put_align(&bp, 128, 0); + + //mv releated 6 x 128 + for (i = 0; i < MV_JOINTS - 1; i++) //mv_joint_type + mpp_put_bits(&bp, pic_param->prob.mv_joint[i], 8); + + for (i = 0; i < 2; i++) { //sign bit + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].sign, 8); + } + for (i = 0; i < 2; i++) { //classes bit + for (j = 0; j < MV_CLASSES - 1; j++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].classes[j], 8); + } + for (i = 0; i < 2; i++) { //classe0 bit + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].class0, 8); + } + for (i = 0; i < 2; i++) { // bits + for (j = 0; j < MV_OFFSET_BITS; j++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].bits[j], 8); + } + for (i = 0; i < 2; i++) { //class0_fp bit + for (j = 0; j < CLASS0_SIZE; j++) + for (k = 0; k < MV_FP_SIZE - 1; k++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].class0_fp[j][k], 8); + } + for (i = 0; i < 2; i++) { //comp ref bit + for (j = 0; j < MV_FP_SIZE - 1; j++) + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].fp[j], 8); + } + for (i = 0; i < 2; i++) { //class0_hp bit + + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].class0_hp, 8); + } + for (i = 0; i < 2; i++) { //hp bit + mpp_put_bits(&bp, pic_param->prob.mv_comp[i].hp, 8); + } + mpp_put_align(&bp, 128, 0); + mpp_put_bits(&bp, 0, 8); + mpp_put_align(&bp, 128, 0); + + memcpy(buf, probe_packet, fifo_len << 3); + +#if VP9_DUMP + { + static RK_U32 file_cnt = 0; + char file_name[128]; + sprintf(file_name, "/data/vp9/prob_default_%d.txt", file_cnt); + FILE *vp9_fp = fopen(file_name, "wb"); + RK_U32 *tmp = (RK_U32 *)buf; + for (i = 0; i < bp.index * 2; i += 2) { + fprintf(vp9_fp, "%08x%08x\n", tmp[i + 1], tmp[i]); + } + file_cnt++; + fflush(vp9_fp); + fclose(vp9_fp); + } +#endif + MPP_FREE(probe_packet); + + return 0; +} + + +MPP_RET hal_vp9d_prob_flag_delta(void *buf, void *dxva) +{ + RK_S32 i, j, k, m, n; + RK_S32 fifo_len = PROB_SIZE >> 3; + BitputCtx_t bp; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)dxva; + RK_S32 intraFlag = (!pic_param->frame_type || pic_param->intra_only); + vp9_prob partition_flag[PARTITION_CONTEXTS][PARTITION_TYPES - 1]; + vp9_prob partition_delta[PARTITION_CONTEXTS][PARTITION_TYPES - 1]; + vp9_prob partition_probs[PARTITION_CONTEXTS][PARTITION_TYPES - 1]; + DXVA_prob_vp9 *prob_flag = &pic_param->prob_flag_delta.p_flag; + DXVA_prob_vp9 *prob_delta = &pic_param->prob_flag_delta.p_delta; + + memset(buf, 0, PROB_SIZE); + + if (intraFlag) { + memcpy(partition_probs, vp9_kf_partition_probs, sizeof(partition_probs)); + } else { + memcpy(partition_flag, prob_flag->partition, sizeof(partition_flag)); + memcpy(partition_delta, prob_delta->partition, sizeof(partition_delta)); + } + + mpp_set_bitput_ctx(&bp, buf, fifo_len); + + if (intraFlag) { //intra probs + //sb info 5 x 128 bit + for (i = 0; i < PARTITION_CONTEXTS; i++) //kf_partition_prob + for (j = 0; j < PARTITION_TYPES - 1; j++) + mpp_put_bits(&bp, 0, 1); //48 + + for (i = 0; i < PREDICTION_PROBS; i++) //Segment_id_pred_prob //3 + mpp_put_bits(&bp, 0, 1); + + for (i = 0; i < SEG_TREE_PROBS; i++) //Segment_id_probs + mpp_put_bits(&bp, 0, 1); //7 + + for (i = 0; i < SKIP_CONTEXTS; i++) //Skip_flag_probs //3 + mpp_put_bits(&bp, prob_flag->skip[i], 1); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //6 + for (j = 0; j < TX_SIZES - 1; j++) + mpp_put_bits(&bp, prob_flag->tx32p[i][j], 1); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //4 + for (j = 0; j < TX_SIZES - 2; j++) + mpp_put_bits(&bp, prob_flag->tx16p[i][j], 1); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //2 + mpp_put_bits(&bp, prob_flag->tx8p[i], 1); + + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) //Tx_size_probs //4 + mpp_put_bits(&bp, 0, 1); + + mpp_put_bits(&bp, 0, 3); //reserve + //intra coeff related prob 64 x 128 bit + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + RK_U8 *pp = &pic_param->prob_flag_delta.coef_flag[i][j][0][0][0][0]; + for (k = 0; k < 4; k++) { + for (m = 0; m < 27; m++) { + mpp_put_bits(&bp, pp[m + 27 * k], 1);// "coeff_intra_prob" + } + mpp_put_bits(&bp, 0, 5);//"reserve" + } + } + //inter coeff related prob 64 x 128 bit + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + RK_U8 *pp = &pic_param->prob_flag_delta.coef_flag[i][j][1][0][0][0]; + for (k = 0; k < 4; k++) { + for (m = 0; m < 27; m++) { + mpp_put_bits(&bp, pp[m + 27 * k], 1);// "coeff_intra_prob" + } + mpp_put_bits(&bp, 0, 5);//"reserve" + } + } + mpp_put_align(&bp, 128, 0); + /* ---------------- intra flag prob end ----------------- */ + /* ---------------- intra delat prob start ----------------- */ + for (i = 0; i < PARTITION_CONTEXTS; i++) //kf_partition_prob + for (j = 0; j < PARTITION_TYPES - 1; j++) + mpp_put_bits(&bp, partition_probs[i][j], 8); //48 + + for (i = 0; i < PREDICTION_PROBS; i++) //Segment_id_pred_prob //3 + mpp_put_bits(&bp, pic_param->stVP9Segments.pred_probs[i], 8); + + for (i = 0; i < SEG_TREE_PROBS; i++) //Segment_id_probs + mpp_put_bits(&bp, pic_param->stVP9Segments.tree_probs[i], 8); //7 + + for (i = 0; i < SKIP_CONTEXTS; i++) //Skip_flag_probs //3 + mpp_put_bits(&bp, prob_delta->skip[i], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //6 + for (j = 0; j < TX_SIZES - 1; j++) + mpp_put_bits(&bp, prob_delta->tx32p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //4 + for (j = 0; j < TX_SIZES - 2; j++) + mpp_put_bits(&bp, prob_delta->tx16p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //2 + mpp_put_bits(&bp, prob_delta->tx8p[i], 8); + + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) //Tx_size_probs //4 + mpp_put_bits(&bp, prob_delta->intra[i], 8); + + mpp_put_align(&bp, 128, 0); + //coeff releated prob 64 x 128 bit + for (i = 0; i < TX_SIZES; i++) + for (j = 0; j < PLANE_TYPES; j++) { + RK_S32 byte_count = 0; + for (k = 0; k < COEF_BANDS; k++) { + for (m = 0; m < COEFF_CONTEXTS; m++) + for (n = 0; n < UNCONSTRAINED_NODES; n++) { + mpp_put_bits(&bp, pic_param->prob_flag_delta.coef_delta[i][j][0][k][m][n], 8); + + byte_count++; + if (byte_count == 27) { + mpp_put_align(&bp, 128, 0); + byte_count = 0; + } + } + } + mpp_put_align(&bp, 128, 0); + } + + //intra mode prob 80 x 128 bit + for (i = 0; i < INTRA_MODES; i++) { //vp9_kf_y_mode_prob + RK_S32 byte_count = 0; + for (j = 0; j < INTRA_MODES; j++) + for (k = 0; k < INTRA_MODES - 1; k++) { + mpp_put_bits(&bp, vp9_kf_y_mode_prob[i][j][k], 8); + byte_count++; + if (byte_count == 27) { + byte_count = 0; + mpp_put_align(&bp, 128, 0); + } + + } + if (i < 4) { + for (m = 0; m < (i < 3 ? 23 : 21); m++) + mpp_put_bits(&bp, ((vp9_prob *)(&vp9_kf_uv_mode_prob[0][0]))[i * 23 + m], 8); + for (; m < 23; m++) + mpp_put_bits(&bp, 0, 8); + } else { + for (m = 0; m < 23; m++) + mpp_put_bits(&bp, 0, 8); + } + mpp_put_align(&bp, 128, 0); + } + + //inter coeff releated prob 64 x 128 bit + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + int32_t byte_count = 0; // 8 x128bit + for (k = 0; k < 6; k++) + for (m = 0; m < 6; m++) + for (n = 0; n < 3; n++) { + mpp_put_bits(&bp, pic_param->prob_flag_delta.coef_delta[i][j][1][k][m][n], 8); + byte_count++; + if (byte_count == 27) { + mpp_put_align(&bp, 128, 0); + byte_count = 0; + } + } + mpp_put_align(&bp, 128, 0); + } + } else { + //inter probs + //151 x 128 bit ,aligned to 152 x 128 bit + //inter only + //sb info 5 x 128 bit + for (i = 0; i < PARTITION_CONTEXTS; i++) //kf_partition_prob + for (j = 0; j < PARTITION_TYPES - 1; j++) + mpp_put_bits(&bp, partition_flag[i][j], 1); //48 + + for (i = 0; i < PREDICTION_PROBS; i++) //Segment_id_pred_prob //3 + mpp_put_bits(&bp, 0, 1); + + for (i = 0; i < SEG_TREE_PROBS; i++) //Segment_id_probs + mpp_put_bits(&bp, 0, 1); //7 + + for (i = 0; i < SKIP_CONTEXTS; i++) //Skip_flag_probs //3 + mpp_put_bits(&bp, prob_flag->skip[i], 1); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //6 + for (j = 0; j < TX_SIZES - 1; j++) + mpp_put_bits(&bp, prob_flag->tx32p[i][j], 1); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //4 + for (j = 0; j < TX_SIZES - 2; j++) + mpp_put_bits(&bp, prob_flag->tx16p[i][j], 1); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //2 + mpp_put_bits(&bp, prob_flag->tx8p[i], 1); + + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) //Tx_size_probs //4 + mpp_put_bits(&bp, prob_flag->intra[i], 1); + + mpp_put_bits(&bp, 0, 3); //reserve + + //intra_y_mode & inter_block info 6 x 128 bit + for (i = 0; i < BLOCK_SIZE_GROUPS; i++) //intra_y_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_flag->y_mode[i][j], 1); + + for (i = 0; i < COMP_INTER_CONTEXTS; i++) //reference_mode prob + mpp_put_bits(&bp, prob_flag->comp[i], 1); + + for (i = 0; i < REF_CONTEXTS; i++) //comp ref bit + mpp_put_bits(&bp, prob_flag->comp_ref[i], 1); + + for (i = 0; i < REF_CONTEXTS; i++) //single ref bit + for (j = 0; j < 2; j++) + mpp_put_bits(&bp, prob_flag->single_ref[i][j], 1); + + for (i = 0; i < INTER_MODE_CONTEXTS; i++) //mv mode bit + for (j = 0; j < INTER_MODES - 1; j++) + mpp_put_bits(&bp, prob_flag->mv_mode[i][j], 1); + + + for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) //comp ref bit + for (j = 0; j < SWITCHABLE_FILTERS - 1; j++) + mpp_put_bits(&bp, prob_flag->filter[i][j], 1); + + mpp_put_bits(&bp, 0, 11);//reserve + + //intra coeff related prob 64 x 128 bit + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + RK_U8 *pp = &pic_param->prob_flag_delta.coef_flag[i][j][0][0][0][0]; + for (k = 0; k < 4; k++) { + for (m = 0; m < 27; m++) { + mpp_put_bits(&bp, pp[m + 27 * k], 1);// "coeff_intra_prob" + } + mpp_put_bits(&bp, 0, 5);//"reserve" + } + } + //inter coeff related prob 64 x 128 bit + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + RK_U8 *pp = &pic_param->prob_flag_delta.coef_flag[i][j][1][0][0][0]; + for (k = 0; k < 4; k++) { + for (m = 0; m < 27; m++) { + mpp_put_bits(&bp, pp[m + 27 * k], 1);// "coeff_intra_prob" + } + mpp_put_bits(&bp, 0, 5);//"reserve" + } + } + + //intra uv mode 6 x 128 + for (i = 0; i < 3; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_flag->uv_mode[i][j], 1); + mpp_put_bits(&bp, 0, 5);//reserve + for (; i < 6; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_flag->uv_mode[i][j], 1); + mpp_put_bits(&bp, 0, 5);//reserve + + for (; i < 9; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_flag->uv_mode[i][j], 1); + mpp_put_bits(&bp, 0, 5);//reserve + for (; i < INTRA_MODES; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_flag->uv_mode[i][j], 1); + mpp_put_bits(&bp, 0, 23);//reserve + + //mv releated 6 x 128 + for (i = 0; i < MV_JOINTS - 1; i++) //mv_joint_type + mpp_put_bits(&bp, prob_flag->mv_joint[i], 1); + + for (i = 0; i < 2; i++) { //sign bit + mpp_put_bits(&bp, prob_flag->mv_comp[i].sign, 1); + } + for (i = 0; i < 2; i++) { //classes bit + for (j = 0; j < MV_CLASSES - 1; j++) + mpp_put_bits(&bp, prob_flag->mv_comp[i].classes[j], 1); + } + for (i = 0; i < 2; i++) { //classe0 bit + mpp_put_bits(&bp, prob_flag->mv_comp[i].class0, 1); + } + for (i = 0; i < 2; i++) { // bits + for (j = 0; j < MV_OFFSET_BITS; j++) + mpp_put_bits(&bp, prob_flag->mv_comp[i].bits[j], 1); + } + for (i = 0; i < 2; i++) { //class0_fp bit + for (j = 0; j < CLASS0_SIZE; j++) + for (k = 0; k < MV_FP_SIZE - 1; k++) + mpp_put_bits(&bp, prob_flag->mv_comp[i].class0_fp[j][k], 1); + } + for (i = 0; i < 2; i++) { //comp ref bit + for (j = 0; j < MV_FP_SIZE - 1; j++) + mpp_put_bits(&bp, prob_flag->mv_comp[i].fp[j], 1); + } + for (i = 0; i < 2; i++) { //class0_hp bit + mpp_put_bits(&bp, prob_flag->mv_comp[i].class0_hp, 1); + } + for (i = 0; i < 2; i++) { //hp bit + mpp_put_bits(&bp, prob_flag->mv_comp[i].hp, 1); + } + mpp_put_bits(&bp, 0, 11);//reserve + + for (i = 0; i < 8; i++) { + mpp_put_bits(&bp, 0, 16);//reserve + } + //sb info 5 x 128 bit + for (i = 0; i < PARTITION_CONTEXTS; i++) //kf_partition_prob + for (j = 0; j < PARTITION_TYPES - 1; j++) + mpp_put_bits(&bp, partition_delta[i][j], 8); //48 + + for (i = 0; i < PREDICTION_PROBS; i++) //Segment_id_pred_prob //3 + mpp_put_bits(&bp, pic_param->stVP9Segments.pred_probs[i], 8); + + for (i = 0; i < SEG_TREE_PROBS; i++) //Segment_id_probs + mpp_put_bits(&bp, pic_param->stVP9Segments.tree_probs[i], 8); //7 + + for (i = 0; i < SKIP_CONTEXTS; i++) //Skip_flag_probs //3 + mpp_put_bits(&bp, prob_delta->skip[i], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //6 + for (j = 0; j < TX_SIZES - 1; j++) + mpp_put_bits(&bp, prob_delta->tx32p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //4 + for (j = 0; j < TX_SIZES - 2; j++) + mpp_put_bits(&bp, prob_delta->tx16p[i][j], 8); + + for (i = 0; i < TX_SIZE_CONTEXTS; i++) //Tx_size_probs //2 + mpp_put_bits(&bp, prob_delta->tx8p[i], 8); + + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) //Tx_size_probs //4 + mpp_put_bits(&bp, prob_delta->intra[i], 8); + + mpp_put_bits(&bp, 0, 24); //reserve + + //intra_y_mode & inter_block info 6 x 128 bit + for (i = 0; i < BLOCK_SIZE_GROUPS; i++) //intra_y_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_delta->y_mode[i][j], 8); + + for (i = 0; i < COMP_INTER_CONTEXTS; i++) //reference_mode prob + mpp_put_bits(&bp, prob_delta->comp[i], 8); + + for (i = 0; i < REF_CONTEXTS; i++) //comp ref bit + mpp_put_bits(&bp, prob_delta->comp_ref[i], 8); + + for (i = 0; i < REF_CONTEXTS; i++) //single ref bit + for (j = 0; j < 2; j++) + mpp_put_bits(&bp, prob_delta->single_ref[i][j], 8); + + for (i = 0; i < INTER_MODE_CONTEXTS; i++) //mv mode bit + for (j = 0; j < INTER_MODES - 1; j++) + mpp_put_bits(&bp, prob_delta->mv_mode[i][j], 8); + + + for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++) //comp ref bit + for (j = 0; j < SWITCHABLE_FILTERS - 1; j++) + mpp_put_bits(&bp, prob_delta->filter[i][j], 8); + for (i = 0; i < 11; i++) + mpp_put_bits(&bp, 0, 8);//reserve + + //intra coeff related prob 64 x 128 bit + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + RK_U32 byte_count = 0; + for (k = 0; k < 6; k++) { + for (m = 0; m < 6; m++) + for (n = 0; n < 3; n++) { + mpp_put_bits(&bp, pic_param->prob_flag_delta.coef_delta[i][j][0][k][m][n], 8); + byte_count++; + if (byte_count == 27) { + mpp_put_bits(&bp, 0, 40);//aline + byte_count = 0; + } + } + } + } + for (i = 0; i < 4; i++) + for (j = 0; j < 2; j++) { + int32_t byte_count = 0; + for (k = 0; k < 6; k++) { + for (m = 0; m < 6; m++) + for (n = 0; n < 3; n++) { + mpp_put_bits(&bp, pic_param->prob_flag_delta.coef_delta[i][j][1][k][m][n], 8);//"coeff_inter_prob" + byte_count++; + if (byte_count == 27) { + mpp_put_bits(&bp, 0, 40);//aline + byte_count = 0; + } + } + } + } + + //intra uv mode 6 x 128 + for (i = 0; i < 3; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_delta->uv_mode[i][j], 8); + mpp_put_bits(&bp, 0, 40);//reserve + for (; i < 6; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_delta->uv_mode[i][j], 8); + mpp_put_bits(&bp, 0, 40);//reserve + + for (; i < 9; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_delta->uv_mode[i][j], 8); + mpp_put_bits(&bp, 0, 40);//reserve + for (; i < INTRA_MODES; i++) //intra_uv_mode + for (j = 0; j < INTRA_MODES - 1; j++) + mpp_put_bits(&bp, prob_delta->uv_mode[i][j], 8); + for (i = 0; i < 23; i++) + mpp_put_bits(&bp, 0xff, 8);//reserve + + //mv releated 6 x 128 + for (i = 0; i < MV_JOINTS - 1; i++) //mv_joint_type + mpp_put_bits(&bp, prob_delta->mv_joint[i], 8); + + for (i = 0; i < 2; i++) { //sign bit + mpp_put_bits(&bp, prob_delta->mv_comp[i].sign, 8); + } + for (i = 0; i < 2; i++) { //classes bit + for (j = 0; j < MV_CLASSES - 1; j++) + mpp_put_bits(&bp, prob_delta->mv_comp[i].classes[j], 8); + } + for (i = 0; i < 2; i++) { //classe0 bit + mpp_put_bits(&bp, prob_delta->mv_comp[i].class0, 8); + } + for (i = 0; i < 2; i++) { // bits + for (j = 0; j < MV_OFFSET_BITS; j++) + mpp_put_bits(&bp, prob_delta->mv_comp[i].bits[j], 8); + } + for (i = 0; i < 2; i++) { //class0_fp bit + for (j = 0; j < CLASS0_SIZE; j++) + for (k = 0; k < MV_FP_SIZE - 1; k++) + mpp_put_bits(&bp, prob_delta->mv_comp[i].class0_fp[j][k], 8); + } + for (i = 0; i < 2; i++) { //comp ref bit + for (j = 0; j < MV_FP_SIZE - 1; j++) + mpp_put_bits(&bp, prob_delta->mv_comp[i].fp[j], 8); + } + for (i = 0; i < 2; i++) { //class0_hp bit + mpp_put_bits(&bp, prob_delta->mv_comp[i].class0_hp, 8); + } + for (i = 0; i < 2; i++) { //hp bit + mpp_put_bits(&bp, prob_delta->mv_comp[i].hp, 8); + } + for (i = 0; i < 27; i++) + mpp_put_bits(&bp, 0, 8);//reserve + + } + mpp_put_align(&bp, 128, 0); + +#if VP9_DUMP + static RK_U32 file_cnt = 0; + char file_name[128]; + sprintf(file_name, "/data/vp9/prob_%d.txt", file_cnt); + FILE *vp9_fp = fopen(file_name, "wb"); + RK_U32 *tmp = (RK_U32 *)buf; + for (i = 0; i < bp.index * 2; i += 2) { + fprintf(vp9_fp, "%08x%08x\n", tmp[i + 1], tmp[i]); + } + file_cnt++; + fflush(vp9_fp); + fclose(vp9_fp); +#endif + + return 0; +} + +MPP_RET hal_vp9d_prob_kf(void *buf) +{ + RK_S32 i, j, k, m; + RK_S32 fifo_len = PROB_KF_SIZE >> 3; + BitputCtx_t bp; + + memset(buf, 0, PROB_KF_SIZE); + mpp_set_bitput_ctx(&bp, buf, fifo_len); + + for (i = 0; i < 16; i++)//kf_partition_prob + for (j = 0; j < 3; j++) + mpp_put_bits(&bp, vp9_kf_partition_probs[i][j], 8); + + //intra mode prob 80 x 128 bit, 10x 8x 128bit + for (i = 0; i < 10; i++) { + RK_S32 byte_count = 0;// 4x128 bit + RK_U8 val = 0; + for (j = 0; j < 10; j++) + for (k = 0; k < 9; k++) { + mpp_put_bits(&bp, vp9_kf_y_mode_prob[i][j][k], 8); + byte_count++; + if (byte_count == 27) { + byte_count = 0; + mpp_put_align(&bp, 128, 0); + } + } + // 6x128 bit, 23x4 bytes + if (i < 4) { + for (m = 0; m < (i < 3 ? 23 : 21); m++) { + val = ((RK_U8 *)(&vp9_kf_uv_mode_prob[0][0]))[i * 23 + m]; + mpp_put_bits(&bp, val, 8); + } + for (; m < 23; m++) + mpp_put_bits(&bp, 0, 8); + } else { + for (m = 0; m < 23; m++) + mpp_put_bits(&bp, 0, 8); + } + mpp_put_align(&bp, 128, 0); + } + + mpp_put_align(&bp, 128, 0); + + return MPP_OK; +} + +void hal_vp9d_update_counts(void *buf, void *dxva) +{ + DXVA_PicParams_VP9 *s = (DXVA_PicParams_VP9*)dxva; + RK_S32 i, j, m, n, k; + RK_U32 *eob_coef; + RK_S32 ref_type; +#ifdef dump + RK_U32 count_length; +#endif + RK_U32 com_len = 0; + +#ifdef dump + if (!(s->frame_type == 0 || s->intra_only)) //inter + count_length = (213 * 64 + 576 * 5 * 32) / 8; + else //intra + count_length = (49 * 64 + 288 * 5 * 32) / 8; + + fwrite(buf, 1, count_length, vp9_fp1); + fflush(vp9_fp1); +#endif + if ((s->frame_type == 0 || s->intra_only)) { + com_len = sizeof(s->counts.partition) + sizeof(s->counts.skip) + sizeof(s->counts.intra) + + sizeof(s->counts.tx32p) + sizeof(s->counts.tx16p) + sizeof(s->counts.tx8p); + } else { + com_len = sizeof(s->counts) - sizeof(s->counts.coef) - sizeof(s->counts.eob); + } + eob_coef = (RK_U32 *)(buf + com_len); + memcpy(&s->counts, buf, com_len); + ref_type = (!(s->frame_type == 0 || s->intra_only)) ? 2 : 1; + if (ref_type == 1) { + memset(s->counts.eob, 0, sizeof(s->counts.eob)); + memset(s->counts.coef, 0, sizeof(s->counts.coef)); + } + for (i = 0; i < ref_type; i++) { + for (j = 0; j < 4; j++) { + for (m = 0; m < 2; m++) { + for (n = 0; n < 6; n++) { + for (k = 0; k < 6; k++) { + s->counts.eob[j][m][i][n][k][0] = eob_coef[1]; + // ff need do branch_ct[UNCONSTRAINED_NODES][2] = { neob, eob_counts[i][j][k][l] - neob }, + s->counts.eob[j][m][i][n][k][1] = eob_coef[0] - eob_coef[1]; + s->counts.coef[j][m][i][n][k][0] = eob_coef[2]; + s->counts.coef[j][m][i][n][k][1] = eob_coef[3]; + s->counts.coef[j][m][i][n][k][2] = eob_coef[4]; + eob_coef += 5; + } + } + } + } + } +} + +static MPP_RET hal_vp9d_release_res(HalVp9dCtx *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + RK_S32 ret = 0; + RK_S32 i = 0; + + if (hw_ctx->prob_default_base) { + ret = mpp_buffer_put(hw_ctx->prob_default_base); + if (ret) { + mpp_err("vp9 probe_wr_base get buffer failed\n"); + return ret; + } + } + if (hw_ctx->segid_cur_base) { + ret = mpp_buffer_put(hw_ctx->segid_cur_base); + if (ret) { + mpp_err("vp9 segid_cur_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->segid_last_base) { + ret = mpp_buffer_put(hw_ctx->segid_last_base); + if (ret) { + mpp_err("vp9 segid_last_base put buffer failed\n"); + return ret; + } + } + for (i = 0; i < VP9_CONTEXT; i++) { + if (hw_ctx->prob_loop_base[i]) { + ret = mpp_buffer_put(hw_ctx->prob_loop_base[i]); + if (ret) { + mpp_err("vp9 prob_loop_base put buffer failed\n"); + return ret; + } + } + } + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (hw_ctx->g_buf[i].global_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].global_base); + if (ret) { + mpp_err("vp9 global_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].probe_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].probe_base); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].count_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].count_base); + if (ret) { + mpp_err("vp9 count_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].hw_regs) { + mpp_free(hw_ctx->g_buf[i].hw_regs); + hw_ctx->g_buf[i].hw_regs = NULL; + } + if (hw_ctx->g_buf[i].rcb_buf) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].rcb_buf); + if (ret) { + mpp_err("vp9 rcb_buf[%d] put buffer failed\n", i); + return ret; + } + } + } + } else { + if (hw_ctx->global_base) { + ret = mpp_buffer_put(hw_ctx->global_base); + if (ret) { + mpp_err("vp9 global_base get buffer failed\n"); + return ret; + } + } + if (hw_ctx->probe_base) { + ret = mpp_buffer_put(hw_ctx->probe_base); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + } + if (hw_ctx->count_base) { + ret = mpp_buffer_put(hw_ctx->count_base); + if (ret) { + mpp_err("vp9 count_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->hw_regs) { + mpp_free(hw_ctx->hw_regs); + hw_ctx->hw_regs = NULL; + } + if (hw_ctx->rcb_buf) { + ret = mpp_buffer_put(hw_ctx->rcb_buf); + if (ret) { + mpp_err("vp9 rcb_buf put buffer failed\n"); + return ret; + } + } + } + + if (hw_ctx->cmv_bufs) { + ret = hal_bufs_deinit(hw_ctx->cmv_bufs); + if (ret) { + mpp_err("vp9 cmv bufs deinit buffer failed\n"); + return ret; + } + } + if (hw_ctx->origin_bufs) { + ret = hal_bufs_deinit(hw_ctx->origin_bufs); + if (ret) { + mpp_err("thumb vp9 origin_bufs deinit buffer failed\n"); + return ret; + } + hw_ctx->origin_bufs = NULL; + } + + return MPP_OK; +} + +MPP_RET hal_vp9d_vdpu38x_deinit(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + MPP_RET ret = MPP_OK; + + hal_vp9d_release_res(p_hal); + vdpu38x_rcb_calc_deinit(hw_ctx->rcb_ctx); + + MPP_FREE(p_hal->hw_ctx); + + return ret; +} + +MPP_RET hal_vp9d_vdpu38x_reset(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + + hal_vp9d_enter(); + + memset(&hw_ctx->ls_info, 0, sizeof(hw_ctx->ls_info)); + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + hw_ctx->last_segid_flag = 1; + + hal_vp9d_leave(); + + return MPP_OK; +} + +MPP_RET hal_vp9d_vdpu38x_flush(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + + hal_vp9d_enter(); + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + + hal_vp9d_leave(); + + return MPP_OK; +} + +MPP_RET hal_vp9d_vdpu38x_control(void *hal, MpiCmd cmd_type, void *param) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO : { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, (MppFrame)param, 0); + } else { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + } + } break; + case MPP_DEC_GET_THUMBNAIL_FRAME_INFO: { + vdpu38x_update_thumbnail_frame_info((MppFrame)param); + } break; + default : { + } break; + } + + return MPP_OK; +} + +void set_tile_offset(RK_S32 *start, RK_S32 *end, RK_S32 idx, RK_S32 log2_n, RK_S32 n) +{ + RK_S32 sb_start = ( idx * n) >> log2_n; + RK_S32 sb_end = ((idx + 1) * n) >> log2_n; + + *start = MPP_MIN(sb_start, n) << 3; + *end = MPP_MIN(sb_end, n) << 3; +} + +MPP_RET vdpu38x_vp9d_uncomp_hdr(HalVp9dCtx *p_hal, DXVA_PicParams_VP9 *pp, + RK_U64 *data, RK_U32 len) +{ + RockchipSocType soc_type; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx *)p_hal->hw_ctx; + BitputCtx_t bp; + RK_S32 i, j; + + soc_type = mpp_get_soc_type(); + + mpp_set_bitput_ctx(&bp, data, len); + + mpp_put_bits(&bp, pp->frame_type, 1); + mpp_put_bits(&bp, pp->error_resilient_mode, 1); + mpp_put_bits(&bp, pp->BitDepthMinus8Luma, 3); + mpp_put_bits(&bp, 1, 2); // yuv420 + mpp_put_bits(&bp, pp->width, 16); + mpp_put_bits(&bp, pp->height, 16); + + mpp_put_bits(&bp, (!pp->frame_type || pp->intra_only), 1); + mpp_put_bits(&bp, pp->ref_frame_sign_bias[1], 1); + mpp_put_bits(&bp, pp->ref_frame_sign_bias[2], 1); + mpp_put_bits(&bp, pp->ref_frame_sign_bias[3], 1); + + mpp_put_bits(&bp, pp->allow_high_precision_mv, 1); + /* sync with cmodel */ + if (!pp->frame_type || pp->intra_only) + mpp_put_bits(&bp, 0, 3); + else { + if (pp->interp_filter == 4) /* FILTER_SWITCHABLE */ + mpp_put_bits(&bp, pp->interp_filter, 3); + else + mpp_put_bits(&bp, literal_to_filter[pp->interp_filter], 3); + } + mpp_put_bits(&bp, pp->parallelmode, 1); + mpp_put_bits(&bp, pp->refresh_frame_context, 1); + if (soc_type == ROCKCHIP_SOC_RK3538 || + soc_type == ROCKCHIP_SOC_RK3572 || + soc_type == ROCKCHIP_SOC_RK3539) { + if ((!pp->frame_type || pp->intra_only) || pp->error_resilient_mode || + pp->reset_frame_context == 3 || pp->reset_frame_context == 2) + mpp_put_bits(&bp, 1, 1); + else + mpp_put_bits(&bp, 0, 1); + } + + /* loop filter */ + mpp_put_bits(&bp, pp->filter_level, 6); + mpp_put_bits(&bp, pp->sharpness_level, 3); + mpp_put_bits(&bp, pp->mode_ref_delta_enabled, 1); + mpp_put_bits(&bp, pp->mode_ref_delta_update, 1); + + mpp_put_bits(&bp, pp->ref_deltas[0], 7); + mpp_put_bits(&bp, pp->ref_deltas[1], 7); + mpp_put_bits(&bp, pp->ref_deltas[2], 7); + mpp_put_bits(&bp, pp->ref_deltas[3], 7); + mpp_put_bits(&bp, pp->mode_deltas[0], 7); + mpp_put_bits(&bp, pp->mode_deltas[1], 7); + + mpp_put_bits(&bp, pp->base_qindex, 8); + mpp_put_bits(&bp, pp->y_dc_delta_q, 5); + mpp_put_bits(&bp, pp->uv_dc_delta_q, 5); + mpp_put_bits(&bp, pp->uv_ac_delta_q, 5); + mpp_put_bits(&bp, (!pp->base_qindex && !pp->y_dc_delta_q && !pp->uv_dc_delta_q && !pp->uv_ac_delta_q), 1); + + for (i = 0; i < 3; i++) { + mpp_put_bits(&bp, pp->stVP9Segments.pred_probs[i], 8); + } + for (i = 0; i < 7; i++) { + mpp_put_bits(&bp, pp->stVP9Segments.tree_probs[i], 8); + } + mpp_put_bits(&bp, pp->stVP9Segments.enabled, 1); + mpp_put_bits(&bp, pp->stVP9Segments.update_map, 1); + mpp_put_bits(&bp, pp->stVP9Segments.temporal_update, 1); + mpp_put_bits(&bp, pp->stVP9Segments.abs_delta, 1); + + { + RK_U32 use_prev_frame_mvs = !pp->error_resilient_mode && + pp->width == hw_ctx->ls_info.last_width && + pp->height == hw_ctx->ls_info.last_height && + !hw_ctx->ls_info.last_intra_only && + hw_ctx->ls_info.last_show_frame; + mpp_put_bits(&bp, use_prev_frame_mvs, 1); + } + + for (i = 0; i < 8; i++) + for (j = 0; j < 4; j++) + mpp_put_bits(&bp, (pp->stVP9Segments.feature_mask[i] >> j) & 0x1, 1); + + for (i = 0; i < 8; i++) { + mpp_put_bits(&bp, pp->stVP9Segments.feature_data[i][0], 9); + mpp_put_bits(&bp, pp->stVP9Segments.feature_data[i][1], 7); + mpp_put_bits(&bp, pp->stVP9Segments.feature_data[i][2], 2); + } + + mpp_put_bits(&bp, pp->first_partition_size, 16); + + /* refer frame width and height */ + { + RK_S32 ref_idx = pp->frame_refs[0].Index7Bits; + mpp_put_bits(&bp, pp->ref_frame_coded_width[ref_idx], 16); + mpp_put_bits(&bp, pp->ref_frame_coded_height[ref_idx], 16); + ref_idx = pp->frame_refs[1].Index7Bits; + mpp_put_bits(&bp, pp->ref_frame_coded_width[ref_idx], 16); + mpp_put_bits(&bp, pp->ref_frame_coded_height[ref_idx], 16); + ref_idx = pp->frame_refs[2].Index7Bits; + mpp_put_bits(&bp, pp->ref_frame_coded_width[ref_idx], 16); + mpp_put_bits(&bp, pp->ref_frame_coded_height[ref_idx], 16); + } + + /* last frame info */ + mpp_put_bits(&bp, hw_ctx->ls_info.last_mode_deltas[0], 7); + mpp_put_bits(&bp, hw_ctx->ls_info.last_mode_deltas[1], 7); + mpp_put_bits(&bp, hw_ctx->ls_info.last_ref_deltas[0], 7); + mpp_put_bits(&bp, hw_ctx->ls_info.last_ref_deltas[1], 7); + mpp_put_bits(&bp, hw_ctx->ls_info.last_ref_deltas[2], 7); + mpp_put_bits(&bp, hw_ctx->ls_info.last_ref_deltas[3], 7); + mpp_put_bits(&bp, hw_ctx->ls_info.segmentation_enable_flag_last, 1); + + mpp_put_bits(&bp, hw_ctx->ls_info.last_show_frame, 1); + mpp_put_bits(&bp, pp->intra_only, 1); + { + RK_U32 last_widthheight_eqcur = pp->width == hw_ctx->ls_info.last_width && + pp->height == hw_ctx->ls_info.last_height; + + mpp_put_bits(&bp, last_widthheight_eqcur, 1); + } + mpp_put_bits(&bp, hw_ctx->ls_info.color_space_last, 3); + + mpp_put_bits(&bp, !hw_ctx->ls_info.last_frame_type, 1); + mpp_put_bits(&bp, 0, 1); + mpp_put_bits(&bp, 1, 1); + mpp_put_bits(&bp, 1, 1); + mpp_put_bits(&bp, 1, 1); + + mpp_put_bits(&bp, pp->mvscale[0][0], 16); + mpp_put_bits(&bp, pp->mvscale[0][1], 16); + mpp_put_bits(&bp, pp->mvscale[1][0], 16); + mpp_put_bits(&bp, pp->mvscale[1][1], 16); + mpp_put_bits(&bp, pp->mvscale[2][0], 16); + mpp_put_bits(&bp, pp->mvscale[2][1], 16); + + /* tile cols and rows */ + { + RK_S32 tile_width[64] = {0}; + RK_S32 tile_height[4] = {0}; + RK_S32 tile_cols = 1 << pp->log2_tile_cols; + RK_S32 tile_rows = 1 << pp->log2_tile_rows; + + mpp_put_bits(&bp, tile_cols, 7); + mpp_put_bits(&bp, tile_rows, 3); + + for (i = 0; i < tile_cols; ++i) { // tile_col + RK_S32 tile_col_start = 0; + RK_S32 tile_col_end = 0; + + set_tile_offset(&tile_col_start, &tile_col_end, + i, pp->log2_tile_cols, MPP_ALIGN(pp->width, 64) / 64); + tile_width[i] = (tile_col_end - tile_col_start + 7) / 8; + } + + for (j = 0; j < tile_rows; ++j) { // tile_row + RK_S32 tile_row_start = 0; + RK_S32 tile_row_end = 0; + + set_tile_offset(&tile_row_start, &tile_row_end, + j, pp->log2_tile_rows, MPP_ALIGN(pp->height, 64) / 64); + tile_height[j] = (tile_row_end - tile_row_start + 7) / 8; + } + + for (i = 0; i < 64; i++) + mpp_put_bits(&bp, tile_width[i], 10); + + for (j = 0; j < 4; j++) + mpp_put_bits(&bp, tile_height[j], 10); + } + + mpp_put_align(&bp, 64, 0); // 128 + +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "global_cfg.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)bp.pbuf, + 64 * bp.index + bp.bitpos, 128, 0, 0); + } +#endif + + return MPP_OK; +} + +void vdpu38x_vp9d_rcb_setup(void *hal, DXVA_PicParams_VP9 *pic_param, + HalTaskInfo *task, Vdpu38xRcbRegSet *rcb_regs, + Vdpu38xRcbCalc_f func) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + RK_U32 num_tiles = pic_param->log2_tile_rows; + RK_U32 bit_depth = pic_param->BitDepthMinus8Luma + 8; + RK_S32 height = mpp_align_64(pic_param->height); + RK_S32 width = mpp_align_64(pic_param->width); + MppBuffer rcb_buf; + + if (hw_ctx->num_row_tiles != num_tiles || + hw_ctx->bit_depth != bit_depth || + hw_ctx->width != width || + hw_ctx->height != height) { + + /* update rcb info */ + { + RcbTileInfo tl_info; + MppFrame mframe; + MppFrameFormat mpp_fmt; + Vdpu38xFmt rcb_fmt; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_fmt = mpp_frame_get_fmt(mframe); + rcb_fmt = vdpu38x_fmt_mpp2hal(mpp_fmt); + + vdpu38x_rcb_reset(hw_ctx->rcb_ctx); + + /* update general info */ + vdpu38x_rcb_set_pic_w(hw_ctx->rcb_ctx, width); + vdpu38x_rcb_set_pic_h(hw_ctx->rcb_ctx, height); + vdpu38x_rcb_set_fmt(hw_ctx->rcb_ctx, rcb_fmt); + vdpu38x_rcb_set_bit_depth(hw_ctx->rcb_ctx, bit_depth); + + /* add tile info */ + /* Simplify the calculation. */ + tl_info.lt_x = 0; + tl_info.lt_y = 0; + tl_info.w = width; + tl_info.h = height; + vdpu38x_rcb_set_tile_dir(hw_ctx->rcb_ctx, 0); + vdpu38x_rcb_add_tile_info(hw_ctx->rcb_ctx, &tl_info); + vdpu38x_rcb_register_calc_handle(hw_ctx->rcb_ctx, func); + } + + vdpu38x_rcb_calc_exec(hw_ctx->rcb_ctx, &hw_ctx->rcb_buf_size); + // TODO: refine rcb buffer size + + if (p_hal->fast_mode) { + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(hw_ctx->g_buf); i++) { + rcb_buf = hw_ctx->g_buf[i].rcb_buf; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + hw_ctx->g_buf[i].rcb_buf = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, hw_ctx->rcb_buf_size); + hw_ctx->g_buf[i].rcb_buf = rcb_buf; + } + } else { + rcb_buf = hw_ctx->rcb_buf; + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + rcb_buf = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, hw_ctx->rcb_buf_size); + hw_ctx->rcb_buf = rcb_buf; + } + + hw_ctx->num_row_tiles = num_tiles; + hw_ctx->bit_depth = bit_depth; + hw_ctx->width = width; + hw_ctx->height = height; + } + + rcb_buf = p_hal->fast_mode ? hw_ctx->g_buf[task->dec.reg_index].rcb_buf : + hw_ctx->rcb_buf; + vdpu38x_setup_rcb(hw_ctx->rcb_ctx, rcb_regs, p_hal->cfg->dev, rcb_buf); +} diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_com.h b/mpp/hal/rkdec/vp9d/hal_vp9d_com.h new file mode 100644 index 000000000..ec76aa4d8 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_com.h @@ -0,0 +1,116 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP9D_COM_H +#define HAL_VP9D_COM_H + +#include "mpp_env.h" + +#include "rk_mpi_cmd.h" +#include "hal_vp9d_ctx.h" +#include "vp9d_syntax.h" +#include "vdpu38x_com.h" + +typedef RK_U8 vp9_prob; + +#define PARTITION_CONTEXTS 16 +#define PARTITION_TYPES 4 +#define MAX_SEGMENTS 8 +#define SEG_TREE_PROBS (MAX_SEGMENTS-1) +#define PREDICTION_PROBS 3 +#define SKIP_CONTEXTS 3 +#define TX_SIZE_CONTEXTS 2 +#define TX_SIZES 4 +#define INTRA_INTER_CONTEXTS 4 +#define PLANE_TYPES 2 +#define COEF_BANDS 6 +#define COEFF_CONTEXTS 6 +#define UNCONSTRAINED_NODES 3 +#define INTRA_MODES 10 +#define INTER_PROB_SIZE_ALIGN_TO_128 151 +#define INTRA_PROB_SIZE_ALIGN_TO_128 149 +#define BLOCK_SIZE_GROUPS 4 +#define COMP_INTER_CONTEXTS 5 +#define REF_CONTEXTS 5 +#define INTER_MODE_CONTEXTS 7 +#define SWITCHABLE_FILTERS 3 // number of switchable filters +#define SWITCHABLE_FILTER_CONTEXTS (SWITCHABLE_FILTERS + 1) +#define INTER_MODES 4 +#define MV_JOINTS 4 +#define MV_CLASSES 11 +#define CLASS0_BITS 1 /* bits at integer precision for class 0 */ +#define CLASS0_SIZE (1 << CLASS0_BITS) +#define MV_OFFSET_BITS (MV_CLASSES + CLASS0_BITS - 2) +#define MV_FP_SIZE 4 + +#define PROB_SIZE 4864 +#define PROB_KF_SIZE (82 * 16) +#define COUNT_SIZE 13208 + +#define VP9_CTU_SIZE 64 + +/* + * MAX_SEGMAP_SIZE calculate(e.g. 4096x2304): + * nCtuX*nCtuY*8*8/2 + * MaxnCtuX = 4096/64 + * MaxnCtuY = 2304/64 + * for support 8k resolusion, segmap_size(8k) = segmap_size(4k) * 4 + */ +#define MAX_SEGMAP_SIZE (73728 * 4) + +#define VP9_DUMP 0 + +//!< memory malloc check +#define MEM_CHECK(ret, val, ...)\ +do{\ + if (!(val)) {\ + ret = MPP_ERR_MALLOC; \ + mpp_err("malloc buffer error(%d).\n", __LINE__); \ + mpp_assert(0); goto __FAILED; \ +}} while (0) + + +extern const vp9_prob vp9_kf_y_mode_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1]; +extern const vp9_prob vp9_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1]; +extern const vp9_prob vp9_kf_partition_probs[PARTITION_CONTEXTS][PARTITION_TYPES - 1]; +extern const RK_U8 literal_to_filter[]; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET hal_vp9d_output_probe(void *buf, void *dxva); +MPP_RET hal_vp9d_prob_flag_delta(void *buf, void *dxva); +void hal_vp9d_update_counts(void *buf, void *dxva); +MPP_RET hal_vp9d_prob_default(void *buf, void *dxva); +MPP_RET hal_vp9d_prob_kf(void *buf); +void set_tile_offset(RK_S32 *start, RK_S32 *end, RK_S32 idx, RK_S32 log2_n, RK_S32 n); +MPP_RET vdpu38x_vp9d_uncomp_hdr(HalVp9dCtx *p_hal, DXVA_PicParams_VP9 *pp, + RK_U64 *data, RK_U32 len); +void vdpu38x_vp9d_rcb_setup(void *hal, DXVA_PicParams_VP9 *pic_param, + HalTaskInfo *task, Vdpu38xRcbRegSet *rcb_regs, + Vdpu38xRcbCalc_f func); + +MPP_RET hal_vp9d_vdpu38x_deinit(void *hal); +MPP_RET hal_vp9d_vdpu38x_reset(void *hal); +MPP_RET hal_vp9d_vdpu38x_flush(void *hal); +MPP_RET hal_vp9d_vdpu38x_control(void *hal, MpiCmd cmd_type, void *param); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_ctx.h b/mpp/hal/rkdec/vp9d/hal_vp9d_ctx.h new file mode 100644 index 000000000..469410776 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_ctx.h @@ -0,0 +1,102 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP9D_CTX_H +#define HAL_VP9D_CTX_H + +#include "mpp_device.h" +#include "mpp_hal.h" +#include "hal_bufs.h" +#include "vdpu_com.h" + +#define VP9_CONTEXT 4 + +typedef struct Vp9dLastInfo_t { + RK_S32 abs_delta_last; + RK_S8 last_ref_deltas[4]; + RK_S8 last_mode_deltas[2]; + RK_U8 segmentation_enable_flag_last; + RK_U8 last_show_frame; + RK_U8 last_intra_only; + RK_U32 last_width; + RK_U32 last_height; + RK_S16 feature_data[8][4]; + RK_U8 feature_mask[8]; + RK_U8 color_space_last; + RK_U8 last_frame_type; +} Vp9dLastInfo; + +typedef struct Vp9dRegBuf_t { + RK_S32 use_flag; + MppBuffer global_base; + MppBuffer probe_base; + MppBuffer count_base; + MppBuffer segid_cur_base; + MppBuffer segid_last_base; + void *hw_regs; + MppBuffer rcb_buf; +} Vp9dRegBuf; + +typedef struct HalVp9dCtx_t { + /* for hardware info */ + MppClientType client_type; + + MppHalCfg *cfg; + + RK_U32 fast_mode; + void *hw_ctx; +} HalVp9dCtx; + +typedef struct Vdpu38xVp9dCtx_t { + Vp9dRegBuf g_buf[VDPU_FAST_REG_SET_CNT]; + MppBuffer global_base; + MppBuffer probe_base; + MppBuffer count_base; + MppBuffer segid_cur_base; + MppBuffer segid_last_base; + MppBuffer prob_default_base; + void *hw_regs; + RK_S32 mv_base_addr; + RK_S32 pre_mv_base_addr; + Vp9dLastInfo ls_info; + /* + * swap between segid_cur_base & segid_last_base + * 0 used segid_cur_base as last + * 1 used segid_last_base as + */ + RK_U32 last_segid_flag; + RK_S32 width; + RK_S32 height; + /* rcb buffers info */ + void *rcb_ctx; + RK_U32 rcb_buf_size; + VdpuRcbInfo rcb_info[RCB_BUF_CNT]; + MppBuffer rcb_buf; + RK_U32 num_row_tiles; + RK_U32 bit_depth; + /* colmv buffers info */ + HalBufs cmv_bufs; + RK_S32 mv_size; + RK_S32 mv_count; + HalBufs origin_bufs; + RK_U32 prob_ctx_valid[VP9_CONTEXT]; + MppBuffer prob_loop_base[VP9_CONTEXT]; + /* uncompress header data */ + RK_U8 header_data[0]; +} Vdpu38xVp9dCtx; + +#endif /* HAL_VP9D_CTX_H */ + diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_debug.h b/mpp/hal/rkdec/vp9d/hal_vp9d_debug.h new file mode 100644 index 000000000..849de4a2f --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_debug.h @@ -0,0 +1,38 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP9D_DEBUG_H +#define HAL_VP9D_DEBUG_H + +#include "mpp_debug.h" + +#define HAL_VP9D_DBG_FUNC (0x00000001) +#define HAL_VP9D_DBG_PAR (0x00000002) +#define HAL_VP9D_DBG_REG (0x00000004) + +#define hal_vp9d_dbg(flag, fmt, ...) mpp_dbg(hal_vp9d_debug, flag, fmt, ## __VA_ARGS__) +#define hal_vp9d_dbg_f(flag, fmt, ...) mpp_dbg_f(hal_vp9d_debug, flag, fmt, ## __VA_ARGS__) + +#define hal_vp9d_dbg_func(fmt, ...) hal_vp9d_dbg_f(HAL_VP9D_DBG_FUNC, fmt, ## __VA_ARGS__) +#define hal_vp9d_dbg_par(fmt, ...) hal_vp9d_dbg(HAL_VP9D_DBG_PAR, fmt, ## __VA_ARGS__) +#define hal_vp9d_dbg_reg(fmt, ...) hal_vp9d_dbg(HAL_VP9D_DBG_REG, fmt, ## __VA_ARGS__) + +#define hal_vp9d_enter() hal_vp9d_dbg_func("(%d) enter\n", __LINE__); +#define hal_vp9d_leave() hal_vp9d_dbg_func("(%d) leave\n", __LINE__); + +extern RK_U32 hal_vp9d_debug; + +#endif /* HAL_VP9D_DEBUG_H */ diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_rkv.c b/mpp/hal/rkdec/vp9d/hal_vp9d_rkv.c new file mode 100644 index 000000000..7f22d6cf8 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_rkv.c @@ -0,0 +1,696 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp9d_rkv" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "hal_vp9d_debug.h" +#include "hal_vp9d_ctx.h" +#include "hal_vp9d_com.h" +#include "hal_vp9d_rkv.h" +#include "hal_vp9d_rkv_reg.h" +#include "vp9d_syntax.h" + + +typedef struct Vp9dRkvCtx_t { + Vp9dRegBuf g_buf[VDPU_FAST_REG_SET_CNT]; + MppBuffer probe_base; + MppBuffer count_base; + MppBuffer segid_cur_base; + MppBuffer segid_last_base; + void *hw_regs; + RK_S32 mv_base_addr; + RK_U32 mv_base_offset; + RK_S32 pre_mv_base_addr; + RK_U32 pre_mv_base_offset; + Vp9dLastInfo ls_info; + /* + * swap between segid_cur_base & segid_last_base + * 0 used segid_cur_base as last + * 1 used segid_last_base as + */ + RK_U32 last_segid_flag; +} Vp9dRkvCtx; + +static MPP_RET hal_vp9d_alloc_res(HalVp9dCtx *hal) +{ + RK_S32 i = 0; + RK_S32 ret = 0; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vp9dRkvCtx *hw_ctx = (Vp9dRkvCtx*)p_hal->hw_ctx; + MppBufferGroup group = p_hal->cfg->buf_group; + + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + hw_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(VP9_REGS)); + ret = mpp_buffer_get(group, &hw_ctx->g_buf[i].probe_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + ret = mpp_buffer_get(group, &hw_ctx->g_buf[i].count_base, COUNT_SIZE); + if (ret) { + mpp_err("vp9 count_base get buffer failed\n"); + return ret; + } + ret = mpp_buffer_get(group, &hw_ctx->g_buf[i].segid_cur_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_cur_base get buffer failed\n"); + return ret; + } + ret = mpp_buffer_get(group, &hw_ctx->g_buf[i].segid_last_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_last_base get buffer failed\n"); + return ret; + } + } + } else { + hw_ctx->hw_regs = mpp_calloc_size(void, sizeof(VP9_REGS)); + ret = mpp_buffer_get(group, &hw_ctx->probe_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + ret = mpp_buffer_get(group, &hw_ctx->count_base, COUNT_SIZE); + if (ret) { + mpp_err("vp9 count_base get buffer failed\n"); + return ret; + } + ret = mpp_buffer_get(group, &hw_ctx->segid_cur_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_cur_base get buffer failed\n"); + return ret; + } + ret = mpp_buffer_get(group, &hw_ctx->segid_last_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_last_base get buffer failed\n"); + return ret; + } + } + return MPP_OK; +} + +static MPP_RET hal_vp9d_release_res(HalVp9dCtx *hal) +{ + RK_S32 i = 0; + RK_S32 ret = 0; + HalVp9dCtx *p_hal = hal; + Vp9dRkvCtx *hw_ctx = (Vp9dRkvCtx*)p_hal->hw_ctx; + + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (hw_ctx->g_buf[i].probe_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].probe_base); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].count_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].count_base); + if (ret) { + mpp_err("vp9 count_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].segid_cur_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].segid_cur_base); + if (ret) { + mpp_err("vp9 segid_cur_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].segid_last_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].segid_last_base); + if (ret) { + mpp_err("vp9 segid_last_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].hw_regs) { + mpp_free(hw_ctx->g_buf[i].hw_regs); + hw_ctx->g_buf[i].hw_regs = NULL; + } + } + } else { + if (hw_ctx->probe_base) { + ret = mpp_buffer_put(hw_ctx->probe_base); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + } + if (hw_ctx->count_base) { + ret = mpp_buffer_put(hw_ctx->count_base); + if (ret) { + mpp_err("vp9 count_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->segid_cur_base) { + ret = mpp_buffer_put(hw_ctx->segid_cur_base); + if (ret) { + mpp_err("vp9 segid_cur_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->segid_last_base) { + ret = mpp_buffer_put(hw_ctx->segid_last_base); + if (ret) { + mpp_err("vp9 segid_last_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->hw_regs) { + mpp_free(hw_ctx->hw_regs); + hw_ctx->hw_regs = NULL; + } + } + return MPP_OK; +} + +MPP_RET hal_vp9d_rkv_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + + mpp_env_get_u32("hal_vp9d_debug", &hal_vp9d_debug, 0); + + p_hal->cfg = cfg; + p_hal->client_type = VPU_CLIENT_RKVDEC; + cfg->support_fast_mode = 0; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + MEM_CHECK(ret, p_hal->hw_ctx = mpp_calloc_size(void, sizeof(Vp9dRkvCtx))); + Vp9dRkvCtx *ctx = (Vp9dRkvCtx *)p_hal->hw_ctx; + + mpp_log("hal_vp9d_rkv_init in"); + ctx->mv_base_addr = -1; + ctx->pre_mv_base_addr = -1; + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_64); + + ret = hal_vp9d_alloc_res(p_hal); + if (ret) { + mpp_err("hal_vp9d_alloc_res failed\n"); + return ret; + } + + ctx->last_segid_flag = 1; + + return ret = MPP_OK; +__FAILED: + return ret = MPP_NOK; +} + +MPP_RET hal_vp9d_rkv_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + + hal_vp9d_release_res(p_hal); + + MPP_FREE(p_hal->hw_ctx); + + return ret = MPP_OK; +} + +MPP_RET hal_vp9d_rkv_gen_regs(void *hal, HalTaskInfo *task) +{ + RK_S32 i; + RK_U8 bit_depth = 0; + RK_U32 ref_frame_width_y; + RK_U32 ref_frame_height_y; + RK_S32 stream_len = 0, aglin_offset = 0; + RK_U32 y_hor_virstride, uv_hor_virstride, y_virstride, uv_virstride, yuv_virstride; + RK_U8 *bitstream = NULL; + MppBuffer streambuf = NULL; + RK_U32 sw_y_hor_virstride; + RK_U32 sw_uv_hor_virstride; + RK_U32 sw_y_virstride; + RK_U32 sw_uv_virstride; + RK_U32 sw_yuv_virstride ; + RK_U8 ref_idx = 0; + RK_U8 ref_frame_idx = 0; + RK_U32 *reg_ref_base = 0; + RK_S32 intraFlag = 0; + MppBuffer framebuf = NULL; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vp9dRkvCtx *hw_ctx = (Vp9dRkvCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + MppBufSlots frm_slots = p_hal->cfg->frame_slots; + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(frm_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!hw_ctx->g_buf[i].use_flag) { + task->dec.reg_index = i; + hw_ctx->probe_base = hw_ctx->g_buf[i].probe_base; + hw_ctx->count_base = hw_ctx->g_buf[i].count_base; + hw_ctx->segid_cur_base = hw_ctx->g_buf[i].segid_cur_base; + hw_ctx->segid_last_base = hw_ctx->g_buf[i].segid_last_base; + hw_ctx->hw_regs = hw_ctx->g_buf[i].hw_regs; + hw_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("vp9 fast mode buf all used\n"); + return MPP_ERR_NOMEM; + } + } + VP9_REGS *vp9_hw_regs = (VP9_REGS*)hw_ctx->hw_regs; + intraFlag = (!pic_param->frame_type || pic_param->intra_only); + hal_vp9d_output_probe(mpp_buffer_get_ptr(hw_ctx->probe_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->count_base); + stream_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + memset(hw_ctx->hw_regs, 0, sizeof(VP9_REGS)); + vp9_hw_regs->swreg2_sysctrl.sw_dec_mode = 2; //set as vp9 dec + vp9_hw_regs->swreg5_stream_len = ((stream_len + 15) & (~15)) + 0x80; + + mpp_buf_slot_get_prop(p_hal->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + bitstream = mpp_buffer_get_ptr(streambuf); + aglin_offset = vp9_hw_regs->swreg5_stream_len - stream_len; + if (aglin_offset > 0) { + memset((void *)(bitstream + stream_len), 0, aglin_offset); + } + + //--- caculate the yuv_frame_size and mv_size + bit_depth = pic_param->BitDepthMinus8Luma + 8; + + sw_y_hor_virstride = mpp_frame_get_hor_stride(mframe) >> 4; + sw_uv_hor_virstride = mpp_frame_get_hor_stride(mframe) >> 4; + sw_y_virstride = sw_y_hor_virstride * mpp_frame_get_ver_stride(mframe); + + sw_uv_virstride = sw_uv_hor_virstride * mpp_frame_get_ver_stride(mframe) / 2; + sw_yuv_virstride = sw_y_virstride + sw_uv_virstride; + + vp9_hw_regs->swreg3_picpar.sw_y_hor_virstride = sw_y_hor_virstride; + vp9_hw_regs->swreg3_picpar.sw_uv_hor_virstride = sw_uv_hor_virstride; + vp9_hw_regs->swreg8_y_virstride.sw_y_virstride = sw_y_virstride; + vp9_hw_regs->swreg9_yuv_virstride.sw_yuv_virstride = sw_yuv_virstride; + + if (!pic_param->intra_only && pic_param->frame_type && + !pic_param->error_resilient_mode && hw_ctx->ls_info.last_show_frame) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + hw_ctx->pre_mv_base_offset = hw_ctx->mv_base_offset; + } + + + mpp_buf_slot_get_prop(frm_slots, task->dec.output, SLOT_BUFFER, &framebuf); + vp9_hw_regs->swreg7_decout_base = mpp_buffer_get_fd(framebuf); + vp9_hw_regs->swreg4_strm_rlc_base = mpp_buffer_get_fd(streambuf); + + vp9_hw_regs->swreg6_cabactbl_prob_base = mpp_buffer_get_fd(hw_ctx->probe_base); + vp9_hw_regs->swreg14_vp9_count_base = mpp_buffer_get_fd(hw_ctx->count_base); + + if (hw_ctx->last_segid_flag) { + vp9_hw_regs->swreg15_vp9_segidlast_base = mpp_buffer_get_fd(hw_ctx->segid_last_base); + vp9_hw_regs->swreg16_vp9_segidcur_base = mpp_buffer_get_fd(hw_ctx->segid_cur_base); + } else { + vp9_hw_regs->swreg15_vp9_segidlast_base = mpp_buffer_get_fd(hw_ctx->segid_cur_base); + vp9_hw_regs->swreg16_vp9_segidcur_base = mpp_buffer_get_fd(hw_ctx->segid_last_base); + } + + if (pic_param->stVP9Segments.enabled && pic_param->stVP9Segments.update_map) { + hw_ctx->last_segid_flag = !hw_ctx->last_segid_flag; + } + + hw_ctx->mv_base_addr = vp9_hw_regs->swreg7_decout_base; + hw_ctx->mv_base_offset = mpp_get_ioctl_version() ? sw_yuv_virstride << 4 : sw_yuv_virstride; + if (hw_ctx->pre_mv_base_addr < 0) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + hw_ctx->pre_mv_base_offset = hw_ctx->mv_base_offset; + } + vp9_hw_regs->swreg52_vp9_refcolmv_base = hw_ctx->pre_mv_base_addr; + mpp_dev_set_reg_offset(p_hal->cfg->dev, 52, hw_ctx->pre_mv_base_offset); + + vp9_hw_regs->swreg10_vp9_cprheader_offset.sw_vp9_cprheader_offset = 0; //no use now. + reg_ref_base = &vp9_hw_regs->swreg11_vp9_referlast_base; + for (i = 0; i < 3; i++) { + ref_idx = pic_param->frame_refs[i].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + ref_frame_width_y = pic_param->ref_frame_coded_width[ref_idx]; + ref_frame_height_y = pic_param->ref_frame_coded_height[ref_idx]; + if (ref_frame_idx < 0x7f) { + mpp_buf_slot_get_prop(frm_slots, ref_frame_idx, SLOT_FRAME_PTR, &mframe); + y_hor_virstride = mpp_frame_get_hor_stride(mframe) >> 4; + uv_hor_virstride = mpp_frame_get_hor_stride(mframe) >> 4; + y_virstride = y_hor_virstride * mpp_frame_get_ver_stride(mframe); + uv_virstride = uv_hor_virstride * mpp_frame_get_ver_stride(mframe) / 2; + } else { + y_hor_virstride = (mpp_align_256_odd((ref_frame_width_y * bit_depth) >> 3) >> 4); + uv_hor_virstride = (mpp_align_256_odd((ref_frame_width_y * bit_depth) >> 3) >> 4); + y_virstride = y_hor_virstride * mpp_align_64(ref_frame_height_y); + uv_virstride = uv_hor_virstride * mpp_align_64(ref_frame_height_y) / 2; + } + yuv_virstride = y_virstride + uv_virstride; + + if (ref_frame_idx < 0x7f) + mpp_buf_slot_get_prop(frm_slots, ref_frame_idx, SLOT_BUFFER, &framebuf); + + if (ref_frame_idx < 0x7f) { + switch (i) { + case 0: { + vp9_hw_regs->swreg17_vp9_frame_size_last.sw_framewidth_last = ref_frame_width_y; + vp9_hw_regs->swreg17_vp9_frame_size_last.sw_frameheight_last = ref_frame_height_y; + vp9_hw_regs->swreg37_vp9_lastf_hor_virstride.sw_vp9_lastfy_hor_virstride = y_hor_virstride; + vp9_hw_regs->swreg37_vp9_lastf_hor_virstride.sw_vp9_lastfuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->swreg48_vp9_last_ystride.sw_vp9_lastfy_virstride = y_virstride; + vp9_hw_regs->swreg51_vp9_lastref_yuvstride.sw_vp9_lastref_yuv_virstride = yuv_virstride; + break; + } + case 1: { + vp9_hw_regs->swreg18_vp9_frame_size_golden.sw_framewidth_golden = ref_frame_width_y; + vp9_hw_regs->swreg18_vp9_frame_size_golden.sw_frameheight_golden = ref_frame_height_y; + vp9_hw_regs->swreg38_vp9_goldenf_hor_virstride.sw_vp9_goldenfy_hor_virstride = y_hor_virstride; + vp9_hw_regs->swreg38_vp9_goldenf_hor_virstride.sw_vp9_goldenuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->swreg49_vp9_golden_ystride.sw_vp9_goldeny_virstride = y_virstride; + break; + } + case 2: { + vp9_hw_regs->swreg19_vp9_frame_size_altref.sw_framewidth_alfter = ref_frame_width_y; + vp9_hw_regs->swreg19_vp9_frame_size_altref.sw_frameheight_alfter = ref_frame_height_y; + vp9_hw_regs->swreg39_vp9_altreff_hor_virstride.sw_vp9_altreffy_hor_virstride = y_hor_virstride; + vp9_hw_regs->swreg39_vp9_altreff_hor_virstride.sw_vp9_altreffuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->swreg50_vp9_altrefy_ystride.sw_vp9_altrefy_virstride = y_virstride; + break; + } + default: + break; + } + + /*0 map to 11*/ + /*1 map to 12*/ + /*2 map to 13*/ + if (framebuf != NULL) { + reg_ref_base[i] = mpp_buffer_get_fd(framebuf); + } else { + mpp_log("ref buff address is no valid used out as base slot index 0x%x", ref_frame_idx); + reg_ref_base[i] = vp9_hw_regs->swreg7_decout_base; //set + } + } else { + reg_ref_base[i] = vp9_hw_regs->swreg7_decout_base; //set + } + } + + for (i = 0; i < 8; i++) { + vp9_hw_regs->swreg20_27_vp9_segid_grp[i].sw_vp9segid_frame_qp_delta_en = (hw_ctx->ls_info.feature_mask[i]) & 0x1; + vp9_hw_regs->swreg20_27_vp9_segid_grp[i].sw_vp9segid_frame_qp_delta = hw_ctx->ls_info.feature_data[i][0]; + vp9_hw_regs->swreg20_27_vp9_segid_grp[i].sw_vp9segid_frame_loopfitler_value_en = (hw_ctx->ls_info.feature_mask[i] >> 1) & 0x1; + vp9_hw_regs->swreg20_27_vp9_segid_grp[i].sw_vp9segid_frame_loopfilter_value = hw_ctx->ls_info.feature_data[i][1]; + vp9_hw_regs->swreg20_27_vp9_segid_grp[i].sw_vp9segid_referinfo_en = (hw_ctx->ls_info.feature_mask[i] >> 2) & 0x1; + vp9_hw_regs->swreg20_27_vp9_segid_grp[i].sw_vp9segid_referinfo = hw_ctx->ls_info.feature_data[i][2]; + vp9_hw_regs->swreg20_27_vp9_segid_grp[i].sw_vp9segid_frame_skip_en = (hw_ctx->ls_info.feature_mask[i] >> 3) & 0x1; + } + + + vp9_hw_regs->swreg20_27_vp9_segid_grp[0].sw_vp9segid_abs_delta = hw_ctx->ls_info.abs_delta_last; + + vp9_hw_regs->swreg28_vp9_cprheader_config.sw_vp9_tx_mode = pic_param->txmode; + + vp9_hw_regs->swreg28_vp9_cprheader_config.sw_vp9_frame_reference_mode = pic_param->refmode; + + vp9_hw_regs->swreg32_vp9_ref_deltas_lastframe.sw_vp9_ref_deltas_lastframe = 0; + + if (!intraFlag) { + for (i = 0; i < 4; i++) + vp9_hw_regs->swreg32_vp9_ref_deltas_lastframe.sw_vp9_ref_deltas_lastframe |= (hw_ctx->ls_info.last_ref_deltas[i] & 0x7f) << (7 * i); + + for (i = 0; i < 2; i++) + vp9_hw_regs->swreg33_vp9_info_lastframe.sw_vp9_mode_deltas_lastframe |= (hw_ctx->ls_info.last_mode_deltas[i] & 0x7f) << (7 * i); + + + } else { + hw_ctx->ls_info.segmentation_enable_flag_last = 0; + hw_ctx->ls_info.last_intra_only = 1; + } + + vp9_hw_regs->swreg33_vp9_info_lastframe.sw_vp9_mode_deltas_lastframe = 0; + + vp9_hw_regs->swreg33_vp9_info_lastframe.sw_segmentation_enable_lstframe = hw_ctx->ls_info.segmentation_enable_flag_last; + vp9_hw_regs->swreg33_vp9_info_lastframe.sw_vp9_last_show_frame = hw_ctx->ls_info.last_show_frame; + vp9_hw_regs->swreg33_vp9_info_lastframe.sw_vp9_last_intra_only = hw_ctx->ls_info.last_intra_only; + vp9_hw_regs->swreg33_vp9_info_lastframe.sw_vp9_last_widthheight_eqcur = (pic_param->width == hw_ctx->ls_info.last_width) && (pic_param->height == hw_ctx->ls_info.last_height); + + vp9_hw_regs->swreg36_vp9_lasttile_size.sw_vp9_lasttile_size = stream_len - pic_param->first_partition_size; + + + if (!intraFlag) { + vp9_hw_regs->swreg29_vp9_lref_scale.sw_vp9_lref_hor_scale = pic_param->mvscale[0][0]; + vp9_hw_regs->swreg29_vp9_lref_scale.sw_vp9_lref_ver_scale = pic_param->mvscale[0][1]; + vp9_hw_regs->swreg30_vp9_gref_scale.sw_vp9_gref_hor_scale = pic_param->mvscale[1][0]; + vp9_hw_regs->swreg30_vp9_gref_scale.sw_vp9_gref_ver_scale = pic_param->mvscale[1][1]; + vp9_hw_regs->swreg31_vp9_aref_scale.sw_vp9_aref_hor_scale = pic_param->mvscale[2][0]; + vp9_hw_regs->swreg31_vp9_aref_scale.sw_vp9_aref_ver_scale = pic_param->mvscale[2][1]; + // vp9_hw_regs.swreg33_vp9_info_lastframe.sw_vp9_color_space_lastkeyframe = p_cm->color_space_last; + } + + + //reuse reg64, and it will be written by hardware to show performance. + vp9_hw_regs->swreg64_performance_cycle.sw_performance_cycle = 0; + vp9_hw_regs->swreg64_performance_cycle.sw_performance_cycle |= pic_param->width; + vp9_hw_regs->swreg64_performance_cycle.sw_performance_cycle |= pic_param->height << 16; + + vp9_hw_regs->swreg1_int.sw_dec_e = 1; + vp9_hw_regs->swreg1_int.sw_dec_timeout_e = 1; + + //last info update + hw_ctx->ls_info.abs_delta_last = pic_param->stVP9Segments.abs_delta; + for (i = 0 ; i < 4; i ++) { + hw_ctx->ls_info.last_ref_deltas[i] = pic_param->ref_deltas[i]; + } + + for (i = 0 ; i < 2; i ++) { + hw_ctx->ls_info.last_mode_deltas[i] = pic_param->mode_deltas[i]; + } + + for (i = 0; i < 8; i++) { + hw_ctx->ls_info.feature_data[i][0] = pic_param->stVP9Segments.feature_data[i][0]; + hw_ctx->ls_info.feature_data[i][1] = pic_param->stVP9Segments.feature_data[i][1]; + hw_ctx->ls_info.feature_data[i][2] = pic_param->stVP9Segments.feature_data[i][2]; + hw_ctx->ls_info.feature_data[i][3] = pic_param->stVP9Segments.feature_data[i][3]; + hw_ctx->ls_info.feature_mask[i] = pic_param->stVP9Segments.feature_mask[i]; + } + if (!hw_ctx->ls_info.segmentation_enable_flag_last) + hw_ctx->ls_info.segmentation_enable_flag_last = pic_param->stVP9Segments.enabled; + + hw_ctx->ls_info.last_show_frame = pic_param->show_frame; + hw_ctx->ls_info.last_width = pic_param->width; + hw_ctx->ls_info.last_height = pic_param->height; + hw_ctx->ls_info.last_intra_only = (!pic_param->frame_type || pic_param->intra_only); + hal_vp9d_dbg_par("stVP9Segments.enabled %d show_frame %d width %d height %d last_intra_only %d", + pic_param->stVP9Segments.enabled, pic_param->show_frame, + pic_param->width, pic_param->height, + hw_ctx->ls_info.last_intra_only); + + // whether need update counts + if (pic_param->refresh_frame_context && !pic_param->parallelmode) { + task->dec.flags.wait_done = 1; + } + + return MPP_OK; +} + +MPP_RET hal_vp9d_rkv_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + Vp9dRkvCtx *hw_ctx = (Vp9dRkvCtx*)p_hal->hw_ctx; + VP9_REGS *hw_regs = (VP9_REGS *)hw_ctx->hw_regs; + MppDev dev = p_hal->cfg->dev; + + if (p_hal->fast_mode) { + RK_S32 index = task->dec.reg_index; + hw_regs = (VP9_REGS *)hw_ctx->g_buf[index].hw_regs; + } + + mpp_assert(hw_regs); + + if (hal_vp9d_debug & HAL_VP9D_DBG_REG) { + RK_U32 *p = (RK_U32 *)hw_regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(VP9_REGS) / 4; i++) + mpp_log("set regs[%02d]: %08X\n", i, *p++); + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = sizeof(VP9_REGS); + + wr_cfg.reg = hw_ctx->hw_regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = hw_ctx->hw_regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +MPP_RET hal_vp9d_rkv_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + Vp9dRkvCtx *hw_ctx = (Vp9dRkvCtx*)p_hal->hw_ctx; + VP9_REGS *hw_regs = (VP9_REGS *)hw_ctx->hw_regs; + + if (p_hal->fast_mode) + hw_regs = (VP9_REGS *)hw_ctx->g_buf[task->dec.reg_index].hw_regs; + + mpp_assert(hw_regs); + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (hal_vp9d_debug & HAL_VP9D_DBG_REG) { + RK_U32 *p = (RK_U32 *)hw_regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(VP9_REGS) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i, *p++); + } + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + !hw_regs->swreg1_int.sw_dec_rdy_sta) { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_frame_set_errinfo(mframe, 1); + } + + if (p_hal->cfg->dec_cb && task->dec.flags.wait_done) { + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + + mpp_buffer_sync_ro_begin(hw_ctx->count_base); + hal_vp9d_update_counts(mpp_buffer_get_ptr(hw_ctx->count_base), task->dec.syntax.data); + + mpp_callback(p_hal->cfg->dec_cb, &pic_param->counts); + } + if (p_hal->fast_mode) { + hw_ctx->g_buf[task->dec.reg_index].use_flag = 0; + } + + (void)task; + return ret; +} + +MPP_RET hal_vp9d_rkv_reset(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + Vp9dRkvCtx *hw_ctx = (Vp9dRkvCtx*)p_hal->hw_ctx; + + hal_vp9d_enter(); + + memset(&hw_ctx->ls_info, 0, sizeof(hw_ctx->ls_info)); + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + hw_ctx->last_segid_flag = 1; + + hal_vp9d_leave(); + + return MPP_OK; +} + +MPP_RET hal_vp9d_rkv_flush(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + Vp9dRkvCtx *hw_ctx = p_hal->hw_ctx; + + hal_vp9d_enter(); + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + + hal_vp9d_leave(); + + return MPP_OK; +} + +MPP_RET hal_vp9d_rkv_control(void *hal, MpiCmd cmd_type, void *param) +{ + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + /* commit buffer stride */ + RK_U32 width = mpp_frame_get_width((MppFrame)param); + RK_U32 height = mpp_frame_get_height((MppFrame)param); + + mpp_frame_set_hor_stride((MppFrame)param, mpp_align_256_odd(width)); + mpp_frame_set_ver_stride((MppFrame)param, mpp_align_64(height)); + } break; + default: { + } break; + } + (void)hal; + + return MPP_OK; +} + +const MppHalApi hal_vp9d_rkv = { + .name = "vp9d_rkdec", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingVP9, + .ctx_size = sizeof(HalVp9dCtx), + .flag = 0, + .init = hal_vp9d_rkv_init, + .deinit = hal_vp9d_rkv_deinit, + .reg_gen = hal_vp9d_rkv_gen_regs, + .start = hal_vp9d_rkv_start, + .wait = hal_vp9d_rkv_wait, + .reset = hal_vp9d_rkv_reset, + .flush = hal_vp9d_rkv_flush, + .control = hal_vp9d_rkv_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_vp9d_rkv) diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_rkv.h b/mpp/hal/rkdec/vp9d/hal_vp9d_rkv.h new file mode 100644 index 000000000..4fdd0a2ba --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_rkv.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP9D_RKV_H +#define HAL_VP9D_RKV_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_vp9d_rkv; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_VP9D_RKV_H */ diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_rkv_reg.h b/mpp/hal/rkdec/vp9d/hal_vp9d_rkv_reg.h new file mode 100644 index 000000000..1ae357578 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_rkv_reg.h @@ -0,0 +1,355 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP9D_REG_H +#define HAL_VP9D_REG_H + +#include "rk_type.h" + +typedef struct { + struct { + RK_U32 minor_ver : 8; + RK_U32 level : 1; + RK_U32 dec_support : 3; + RK_U32 profile : 1; + RK_U32 reserve0 : 1; + RK_U32 codec_flag : 1; + RK_U32 reserve1 : 1; + RK_U32 prod_num : 16; + } swreg0_id; + + struct { + RK_U32 sw_dec_e : 1;//0 + RK_U32 sw_dec_clkgate_e : 1; // 1 + RK_U32 reserve0 : 1;// 2 + RK_U32 sw_timeout_mode : 1; // 3 + RK_U32 sw_dec_irq_dis : 1;//4 // 4 + RK_U32 sw_dec_timeout_e : 1; //5 + RK_U32 sw_buf_empty_en : 1; // 6 + RK_U32 sw_stmerror_waitdecfifo_empty : 1; // 7 + RK_U32 sw_dec_irq : 1; // 8 + RK_U32 sw_dec_irq_raw : 1; // 9 + RK_U32 reserve2 : 2; + RK_U32 sw_dec_rdy_sta : 1; //12 + RK_U32 sw_dec_bus_sta : 1; //13 + RK_U32 sw_dec_error_sta : 1; // 14 + RK_U32 sw_dec_timeout_sta : 1; //15 + RK_U32 sw_dec_empty_sta : 1; // 16 + RK_U32 sw_colmv_ref_error_sta : 1; // 17 + RK_U32 sw_cabu_end_sta : 1; // 18 + RK_U32 sw_h264orvp9_error_mode : 1; //19 + RK_U32 sw_softrst_en_p : 1; //20 + RK_U32 sw_force_softreset_valid : 1; //21 + RK_U32 sw_softreset_rdy : 1; // 22 + } swreg1_int; + + struct { + RK_U32 sw_in_endian : 1; + RK_U32 sw_in_swap32_e : 1; + RK_U32 sw_in_swap64_e : 1; + RK_U32 sw_str_endian : 1; + RK_U32 sw_str_swap32_e : 1; + RK_U32 sw_str_swap64_e : 1; + RK_U32 sw_out_endian : 1; + RK_U32 sw_out_swap32_e : 1; + RK_U32 sw_out_cbcr_swap : 1; + RK_U32 reserve0 : 1; + RK_U32 sw_rlc_mode_direct_write : 1; + RK_U32 sw_rlc_mode : 1; + RK_U32 sw_strm_start_bit : 7; + RK_U32 reserve1 : 1; + RK_U32 sw_dec_mode : 2; + RK_U32 reserve2 : 2; + RK_U32 sw_h264_rps_mode : 1; + RK_U32 sw_h264_stream_mode : 1; + RK_U32 sw_h264_stream_lastpacket : 1; + RK_U32 sw_h264_firstslice_flag : 1; + RK_U32 sw_h264_frame_orslice : 1; + RK_U32 sw_buspr_slot_disable : 1; + RK_U32 reserve3 : 2; + } swreg2_sysctrl; + + struct { + RK_U32 sw_y_hor_virstride : 9; + RK_U32 reserve : 2; + RK_U32 sw_slice_num_highbit : 1; + RK_U32 sw_uv_hor_virstride : 9; + RK_U32 sw_slice_num_lowbits : 11; + } swreg3_picpar; + + RK_U32 swreg4_strm_rlc_base; + RK_U32 swreg5_stream_len; + RK_U32 swreg6_cabactbl_prob_base; + RK_U32 swreg7_decout_base; + + struct { + RK_U32 sw_y_virstride : 20; + RK_U32 reverse0 : 12; + } swreg8_y_virstride; + + struct { + RK_U32 sw_yuv_virstride : 21; + RK_U32 reverse : 11; + } swreg9_yuv_virstride; + + + //only for vp9 + struct { + RK_U32 sw_vp9_cprheader_offset : 16; + RK_U32 reverse : 16; + } swreg10_vp9_cprheader_offset; + + RK_U32 swreg11_vp9_referlast_base; + RK_U32 swreg12_vp9_refergolden_base; + RK_U32 swreg13_vp9_referalfter_base; + RK_U32 swreg14_vp9_count_base; + RK_U32 swreg15_vp9_segidlast_base; + RK_U32 swreg16_vp9_segidcur_base; + + struct { + RK_U32 sw_framewidth_last : 16; + RK_U32 sw_frameheight_last : 16; + } swreg17_vp9_frame_size_last; + + struct { + RK_U32 sw_framewidth_golden : 16; + RK_U32 sw_frameheight_golden : 16; + } swreg18_vp9_frame_size_golden; + + + struct { + RK_U32 sw_framewidth_alfter : 16; + RK_U32 sw_frameheight_alfter : 16; + } swreg19_vp9_frame_size_altref; + + + struct { + RK_U32 sw_vp9segid_abs_delta : 1; //NOTE: only in reg#20, this bit is valid. + RK_U32 sw_vp9segid_frame_qp_delta_en : 1; + RK_U32 sw_vp9segid_frame_qp_delta : 9; + RK_U32 sw_vp9segid_frame_loopfitler_value_en : 1; + RK_U32 sw_vp9segid_frame_loopfilter_value : 7; + RK_U32 sw_vp9segid_referinfo_en : 1; + RK_U32 sw_vp9segid_referinfo : 2; + RK_U32 sw_vp9segid_frame_skip_en : 1; + RK_U32 reverse : 9; + } swreg20_27_vp9_segid_grp[8]; + + + struct { + RK_U32 sw_vp9_tx_mode : 3; + RK_U32 sw_vp9_frame_reference_mode : 2; + RK_U32 reserved : 27; + } swreg28_vp9_cprheader_config; + + + struct { + RK_U32 sw_vp9_lref_hor_scale : 16; + RK_U32 sw_vp9_lref_ver_scale : 16; + } swreg29_vp9_lref_scale; + + struct { + RK_U32 sw_vp9_gref_hor_scale : 16; + RK_U32 sw_vp9_gref_ver_scale : 16; + } swreg30_vp9_gref_scale; + + struct { + RK_U32 sw_vp9_aref_hor_scale : 16; + RK_U32 sw_vp9_aref_ver_scale : 16; + } swreg31_vp9_aref_scale; + + struct { + RK_U32 sw_vp9_ref_deltas_lastframe : 28; + RK_U32 reserve : 4; + } swreg32_vp9_ref_deltas_lastframe; + + struct { + RK_U32 sw_vp9_mode_deltas_lastframe : 14; + RK_U32 reserve0 : 2; + RK_U32 sw_segmentation_enable_lstframe : 1; + RK_U32 sw_vp9_last_show_frame : 1; + RK_U32 sw_vp9_last_intra_only : 1; + RK_U32 sw_vp9_last_widthheight_eqcur : 1; + RK_U32 sw_vp9_color_space_lastkeyframe : 3; + RK_U32 reserve1 : 9; + } swreg33_vp9_info_lastframe; + + RK_U32 swreg34_vp9_intercmd_base; + + struct { + RK_U32 sw_vp9_intercmd_num : 24; + RK_U32 reserve : 8; + } swreg35_vp9_intercmd_num; + + struct { + RK_U32 sw_vp9_lasttile_size : 24; + RK_U32 reserve : 8; + } swreg36_vp9_lasttile_size; + + struct { + RK_U32 sw_vp9_lastfy_hor_virstride : 9; + RK_U32 reserve0 : 7; + RK_U32 sw_vp9_lastfuv_hor_virstride : 9; + RK_U32 reserve1 : 7; + } swreg37_vp9_lastf_hor_virstride; + + struct { + RK_U32 sw_vp9_goldenfy_hor_virstride : 9; + RK_U32 reserve0 : 7; + RK_U32 sw_vp9_goldenuv_hor_virstride : 9; + RK_U32 reserve1 : 7; + } swreg38_vp9_goldenf_hor_virstride; + + struct { + RK_U32 sw_vp9_altreffy_hor_virstride : 9; + RK_U32 reserve0 : 7; + RK_U32 sw_vp9_altreffuv_hor_virstride : 9; + RK_U32 reserve1 : 7; + } swreg39_vp9_altreff_hor_virstride; + + struct { + RK_U32 sw_cur_poc : 32; + } swreg40_cur_poc; + + struct { + RK_U32 reserve : 3; + RK_U32 sw_rlcwrite_base : 29; + } swreg41_rlcwrite_base; + + struct { + RK_U32 reserve : 4; + RK_U32 sw_pps_base : 28; + } swreg42_pps_base; + + struct { + RK_U32 reserve : 4; + RK_U32 sw_rps_base : 28; + } swreg43_rps_base; + + struct { + RK_U32 sw_strmd_error_e : 28; + RK_U32 reserve : 4; + } swreg44_strmd_error_en; + + struct { + RK_U32 vp9_error_info0 : 32; + } swreg45_vp9_error_info0; + + struct { + RK_U32 sw_strmd_error_ctu_xoffset : 8; + RK_U32 sw_strmd_error_ctu_yoffset : 8; + RK_U32 sw_streamfifo_space2full : 7; + RK_U32 reserve : 1; + RK_U32 sw_vp9_error_ctu0_en : 1; + } swreg46_strmd_error_ctu; + + struct { + RK_U32 sw_saowr_xoffet : 9; + RK_U32 reserve : 7; + RK_U32 sw_saowr_yoffset : 10; + } swreg47_sao_ctu_position; + + struct { + RK_U32 sw_vp9_lastfy_virstride : 20; + RK_U32 reserve : 12; + } swreg48_vp9_last_ystride; + + struct { + RK_U32 sw_vp9_goldeny_virstride : 20; + RK_U32 reserve : 12; + } swreg49_vp9_golden_ystride; + + struct { + RK_U32 sw_vp9_altrefy_virstride : 20; + RK_U32 reserve : 12; + } swreg50_vp9_altrefy_ystride; + + struct { + RK_U32 sw_vp9_lastref_yuv_virstride : 21; + RK_U32 reserve : 11; + } swreg51_vp9_lastref_yuvstride; + + + RK_U32 swreg52_vp9_refcolmv_base; + + RK_U32 reg_not_use0[64 - 52 - 1]; + + struct { + RK_U32 sw_performance_cycle : 32; + } swreg64_performance_cycle; + + struct { + RK_U32 sw_axi_ddr_rdata : 32; + } swreg65_axi_ddr_rdata; + + struct { + RK_U32 sw_axi_ddr_wdata : 32; + } swreg66_axi_ddr_wdata; + + struct { + RK_U32 sw_busifd_resetn : 1; + RK_U32 sw_cabac_resetn : 1; + RK_U32 sw_dec_ctrl_resetn : 1; + RK_U32 sw_transd_resetn : 1; + RK_U32 sw_intra_resetn : 1; + RK_U32 sw_inter_resetn : 1; + RK_U32 sw_recon_resetn : 1; + RK_U32 sw_filer_resetn : 1; + } swreg67_fpgadebug_reset; + + struct { + RK_U32 perf_cnt0_sel : 6; + RK_U32 reserve0 : 2; + RK_U32 perf_cnt1_sel : 6; + RK_U32 reserve1 : 2; + RK_U32 perf_cnt2_sel : 6; + } swreg68_performance_sel; + + struct { + RK_U32 perf_cnt0 : 32; + } swreg69_performance_cnt0; + + struct { + RK_U32 perf_cnt1 : 32; + } swreg70_performance_cnt1; + + struct { + RK_U32 perf_cnt2 : 32; + } swreg71_performance_cnt2; + + RK_U32 reg_not_use1[74 - 71 - 1]; + + struct { + RK_U32 sw_h264_cur_poc1 : 32; + } swreg74_h264_cur_poc1; + + struct { + RK_U32 vp9_error_info1 : 32; + } swreg75_vp9_error_info1; + + struct { + RK_U32 vp9_error_ctu1_x : 6; + RK_U32 reserve0 : 2; + RK_U32 vp9_error_ctu1_y : 6; + RK_U32 reserve1 : 1; + RK_U32 vp9_error_ctu1_en : 1; + RK_U32 reserve2 : 16; + } swreg76_vp9_error_ctu1; + + RK_U32 reg_not_use2; +} VP9_REGS; + +#endif diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu34x.c b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu34x.c new file mode 100644 index 000000000..8a70c3677 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu34x.c @@ -0,0 +1,1106 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp9d_vdpu34x" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_hal.h" + +#include "hal_bufs.h" +#include "hal_vp9d_debug.h" +#include "hal_vp9d_com.h" +#include "hal_vp9d_vdpu34x.h" +#include "hal_vp9d_ctx.h" +#include "vdpu34x_vp9d.h" +#include "vp9d_syntax.h" +#include "vdpu_com.h" + +#define HW_PROB 1 +#define PROB_SIZE_ALIGN_TO_4K MPP_ALIGN(PROB_SIZE, SZ_4K) +#define COUNT_SIZE_ALIGN_TO_4K MPP_ALIGN(COUNT_SIZE, SZ_4K) +#define MAX_SEGMAP_SIZE_ALIGN_TO_4K MPP_ALIGN(MAX_SEGMAP_SIZE, SZ_4K) + +#define VDPU34X_OFFSET_COUNT (PROB_SIZE_ALIGN_TO_4K) +#define VDPU34X_PROBE_BUFFER_SIZE (PROB_SIZE_ALIGN_TO_4K + COUNT_SIZE_ALIGN_TO_4K) + +typedef struct Vdpu34xVp9dCtx_t { + Vp9dRegBuf g_buf[VDPU_FAST_REG_SET_CNT]; + MppBuffer probe_base; + MppBuffer seg_base; + RK_U32 offset_count; + RK_U32 offset_segid_cur; + RK_U32 offset_segid_last; + MppBuffer prob_default_base; + void *hw_regs; + RK_S32 mv_base_addr; + RK_S32 pre_mv_base_addr; + Vp9dLastInfo ls_info; + /* + * swap between segid_cur_base & segid_last_base + * 0 used segid_cur_base as last + * 1 used segid_last_base as + */ + RK_U32 last_segid_flag; + RK_S32 width; + RK_S32 height; + /* rcb buffers info */ + RK_S32 rcb_buf_size; + VdpuRcbInfo rcb_info[RCB_BUF_COUNT]; + MppBuffer rcb_buf; + RK_U32 num_row_tiles; + RK_U32 bit_depth; + /* colmv buffers info */ + HalBufs cmv_bufs; + RK_S32 mv_size; + RK_S32 mv_count; + RK_U32 prob_ctx_valid[VP9_CONTEXT]; + MppBuffer prob_loop_base[VP9_CONTEXT]; + RK_U32 prob_ref_poc[VP9_CONTEXT]; + RK_U32 col_ref_poc; + RK_U32 segid_ref_poc; +} Vdpu34xVp9dCtx; + +static MPP_RET hal_vp9d_alloc_res(HalVp9dCtx *hal) +{ + RK_S32 i = 0; + RK_S32 ret = 0; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + MppBufferGroup group = p_hal->cfg->buf_group; + + hw_ctx->offset_count = VDPU34X_OFFSET_COUNT; + hw_ctx->offset_segid_cur = 0; + hw_ctx->offset_segid_last = MAX_SEGMAP_SIZE_ALIGN_TO_4K; + /* alloc common buffer */ + for (i = 0; i < VP9_CONTEXT; i++) { + ret = mpp_buffer_get(group, &hw_ctx->prob_loop_base[i], PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_loop_base get buffer failed\n"); + return ret; + } + } + ret = mpp_buffer_get(group, &hw_ctx->prob_default_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_default_base get buffer failed\n"); + return ret; + } + /* alloc buffer for fast mode or normal */ + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + hw_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu34xVp9dRegSet)); + ret = mpp_buffer_get(group, &hw_ctx->g_buf[i].probe_base, VDPU34X_PROBE_BUFFER_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + } + } else { + hw_ctx->hw_regs = mpp_calloc_size(void, sizeof(Vdpu34xVp9dRegSet)); + ret = mpp_buffer_get(group, &hw_ctx->probe_base, VDPU34X_PROBE_BUFFER_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + } + ret = mpp_buffer_get(group, &hw_ctx->seg_base, MAX_SEGMAP_SIZE_ALIGN_TO_4K * 2); + if (ret) { + mpp_err("vp9 segid_base get buffer failed\n"); + return ret; + } + return MPP_OK; +} + +static MPP_RET hal_vp9d_release_res(HalVp9dCtx *hal) +{ + RK_S32 i = 0; + RK_S32 ret = 0; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + + if (hw_ctx->prob_default_base) { + ret = mpp_buffer_put(hw_ctx->prob_default_base); + if (ret) { + mpp_err("vp9 probe_wr_base put buffer failed\n"); + return ret; + } + } + for (i = 0; i < VP9_CONTEXT; i++) { + if (hw_ctx->prob_loop_base[i]) { + ret = mpp_buffer_put(hw_ctx->prob_loop_base[i]); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + } + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (hw_ctx->g_buf[i].probe_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].probe_base); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].hw_regs) { + mpp_free(hw_ctx->g_buf[i].hw_regs); + hw_ctx->g_buf[i].hw_regs = NULL; + } + if (hw_ctx->g_buf[i].rcb_buf) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].rcb_buf); + if (ret) { + mpp_err("vp9 rcb_buf[%d] put buffer failed\n", i); + return ret; + } + } + } + } else { + if (hw_ctx->probe_base) { + ret = mpp_buffer_put(hw_ctx->probe_base); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + + if (hw_ctx->hw_regs) { + mpp_free(hw_ctx->hw_regs); + hw_ctx->hw_regs = NULL; + } + if (hw_ctx->rcb_buf) { + ret = mpp_buffer_put(hw_ctx->rcb_buf); + if (ret) { + mpp_err("vp9 rcb_buf put buffer failed\n"); + return ret; + } + } + } + + if (hw_ctx->cmv_bufs) { + ret = hal_bufs_deinit(hw_ctx->cmv_bufs); + if (ret) { + mpp_err("vp9 cmv bufs deinit buffer failed\n"); + return ret; + } + } + + if (hw_ctx->seg_base) { + ret = mpp_buffer_put(hw_ctx->seg_base); + if (ret) { + mpp_err("vp9 seg_base put buffer failed\n"); + return ret; + } + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu34x_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + + hal_vp9d_release_res(p_hal); + + MPP_FREE(p_hal->hw_ctx); + + return ret = MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu34x_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + + mpp_env_get_u32("hal_vp9d_debug", &hal_vp9d_debug, 0); + + cfg->support_fast_mode = 1; + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) + cfg->support_fast_mode = 0; + + p_hal->cfg = cfg; + p_hal->client_type = VPU_CLIENT_RKVDEC; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->hw_ctx = mpp_calloc_size(void, sizeof(Vdpu34xVp9dCtx))); + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_64); + + ret = hal_vp9d_alloc_res(p_hal); + if (ret) { + mpp_err("hal_vp9d_alloc_res failed\n"); + goto __FAILED; + } + + hw_ctx->last_segid_flag = 1; + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + return ret; +__FAILED: + hal_vp9d_vdpu34x_deinit(hal); + return ret; +} + +static void vp9d_refine_rcb_size(VdpuRcbInfo *rcb_info, + Vdpu34xVp9dRegSet *vp9_hw_regs, + RK_S32 width, RK_S32 height, void* data) +{ + RK_U32 rcb_bits = 0; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)data; + RK_U32 num_tiles = pic_param->log2_tile_rows; + RK_U32 bit_depth = pic_param->BitDepthMinus8Luma + 8; + RK_U32 ext_align_size = num_tiles * 64 * 8; + + width = MPP_ALIGN(width, VP9_CTU_SIZE); + height = MPP_ALIGN(height, VP9_CTU_SIZE); + /* RCB_STRMD_ROW */ + if (width > 4096) + rcb_bits = MPP_ALIGN(width, 64) * 232 + ext_align_size; + else + rcb_bits = 0; + rcb_info[RCB_STRMD_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_TRANSD_ROW */ + if (width > 8192) + rcb_bits = (MPP_ALIGN(width - 8192, 4) << 1) + ext_align_size; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_TRANSD_COL */ + if (height > 8192) + rcb_bits = (MPP_ALIGN(height - 8192, 4) << 1) + ext_align_size; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_COL].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_INTER_ROW */ + rcb_bits = width * 36 + ext_align_size; + rcb_info[RCB_INTER_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_INTER_COL */ + rcb_info[RCB_INTER_COL].size = 0; + /* RCB_INTRA_ROW */ + rcb_bits = width * 48 + ext_align_size; + rcb_info[RCB_INTRA_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_DBLK_ROW */ + rcb_bits = width * (1 + 16 * bit_depth) + num_tiles * 192 * bit_depth + ext_align_size; + rcb_info[RCB_DBLK_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_SAO_ROW */ + rcb_info[RCB_SAO_ROW].size = 0; + /* RCB_FBC_ROW */ + if (vp9_hw_regs->common.reg012.fbc_e) { + rcb_bits = 8 * width * bit_depth + ext_align_size; + } else + rcb_bits = 0; + rcb_info[RCB_FBC_ROW].size = MPP_RCB_BYTES(rcb_bits); + /* RCB_FILT_COL */ + if (vp9_hw_regs->common.reg012.fbc_e) { + rcb_bits = height * (4 + 24 * bit_depth); + } else + rcb_bits = height * (4 + 16 * bit_depth); + rcb_bits += ext_align_size; + rcb_info[RCB_FILT_COL].size = MPP_RCB_BYTES(rcb_bits); +} + +static void hal_vp9d_rcb_info_update(void *hal, Vdpu34xVp9dRegSet *hw_regs, void *data) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)data; + RK_U32 num_tiles = pic_param->log2_tile_rows; + RK_U32 bit_depth = pic_param->BitDepthMinus8Luma + 8; + RK_S32 height = mpp_align_64(pic_param->height); + RK_S32 width = mpp_align_64(pic_param->width); + + if (hw_ctx->num_row_tiles != num_tiles || + hw_ctx->bit_depth != bit_depth || + hw_ctx->width != width || + hw_ctx->height != height) { + + hw_ctx->rcb_buf_size = vdpu34x_get_rcb_buf_size(hw_ctx->rcb_info, width, height); + vp9d_refine_rcb_size(hw_ctx->rcb_info, hw_regs, width, height, pic_param); + + if (p_hal->fast_mode) { + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(hw_ctx->g_buf); i++) { + MppBuffer rcb_buf = hw_ctx->g_buf[i].rcb_buf; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + hw_ctx->g_buf[i].rcb_buf = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, hw_ctx->rcb_buf_size); + hw_ctx->g_buf[i].rcb_buf = rcb_buf; + } + } else { + MppBuffer rcb_buf = hw_ctx->rcb_buf; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + rcb_buf = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, hw_ctx->rcb_buf_size); + hw_ctx->rcb_buf = rcb_buf; + } + + hw_ctx->num_row_tiles = num_tiles; + hw_ctx->bit_depth = bit_depth; + hw_ctx->width = width; + hw_ctx->height = height; + } +} + +static MPP_RET hal_vp9d_vdpu34x_setup_colmv_buf(void *hal, HalTaskInfo *task) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + RK_U32 width = pic_param->width; + RK_U32 height = pic_param->height; + RK_S32 mv_size = 0, colmv_size = 8, colmv_byte = 16; + RK_U32 compress = p_hal->cfg->hw_info ? p_hal->cfg->hw_info->cap_colmv_compress : 1; + + mv_size = vdpu34x_get_colmv_size(width, height, VP9_CTU_SIZE, colmv_byte, colmv_size, compress); + if (hw_ctx->cmv_bufs == NULL || hw_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (hw_ctx->cmv_bufs) { + hal_bufs_deinit(hw_ctx->cmv_bufs); + hw_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(&hw_ctx->cmv_bufs); + if (hw_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_ERR_NOMEM; + } + hw_ctx->mv_size = mv_size; + hw_ctx->mv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(hw_ctx->cmv_bufs, hw_ctx->mv_count, 1, &size); + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu34x_gen_regs(void *hal, HalTaskInfo *task) +{ + RK_S32 i; + RK_U8 bit_depth = 0; + RK_U32 ref_frame_width_y; + RK_U32 ref_frame_height_y; + RK_S32 stream_len = 0, aglin_offset = 0; + RK_U32 y_hor_virstride, uv_hor_virstride, y_virstride; + RK_U8 *bitstream = NULL; + MppBuffer streambuf = NULL; + RK_U32 sw_y_hor_virstride; + RK_U32 sw_uv_hor_virstride; + RK_U32 sw_y_virstride; + RK_U8 ref_idx = 0; + RK_U8 ref_frame_idx = 0; + RK_U32 *reg_ref_base = 0; + RK_S32 intraFlag = 0; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_U32 fbc_en = 0; + + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + RK_U32 frame_ctx_id = pic_param->frame_context_idx; + MppHalCfg *cfg = p_hal->cfg; + + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!hw_ctx->g_buf[i].use_flag) { + task->dec.reg_index = i; + hw_ctx->probe_base = hw_ctx->g_buf[i].probe_base; + + hw_ctx->hw_regs = hw_ctx->g_buf[i].hw_regs; + hw_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("vp9 fast mode buf all used\n"); + return MPP_ERR_NOMEM; + } + } + + if (hal_vp9d_vdpu34x_setup_colmv_buf(hal, task)) + return MPP_ERR_NOMEM; + + Vdpu34xVp9dRegSet *vp9_hw_regs = (Vdpu34xVp9dRegSet*)hw_ctx->hw_regs; + intraFlag = (!pic_param->frame_type || pic_param->intra_only); + stream_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + memset(hw_ctx->hw_regs, 0, sizeof(Vdpu34xVp9dRegSet)); +#if HW_PROB + hal_vp9d_prob_flag_delta(mpp_buffer_get_ptr(hw_ctx->probe_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->probe_base); + if (intraFlag) { + hal_vp9d_prob_default(mpp_buffer_get_ptr(hw_ctx->prob_default_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->prob_default_base); + } + + /* config reg103 */ + vp9_hw_regs->vp9d_param.reg103.prob_update_en = 1; + vp9_hw_regs->vp9d_param.reg103.intra_only_flag = intraFlag; + if (!intraFlag) { + vp9_hw_regs->vp9d_param.reg103.txfmmode_rfsh_en = (pic_param->txmode == 4) ? 1 : 0; + vp9_hw_regs->vp9d_param.reg103.interp_filter_switch_en = pic_param->interp_filter == 4 ? 1 : 0; + } + vp9_hw_regs->vp9d_param.reg103.ref_mode_rfsh_en = 1; + vp9_hw_regs->vp9d_param.reg103.single_ref_rfsh_en = 1; + vp9_hw_regs->vp9d_param.reg103.comp_ref_rfsh_en = 1; + vp9_hw_regs->vp9d_param.reg103.inter_coef_rfsh_flag = 0; + vp9_hw_regs->vp9d_param.reg103.refresh_en = + !pic_param->error_resilient_mode && !pic_param->parallelmode; + vp9_hw_regs->vp9d_param.reg103.prob_save_en = pic_param->refresh_frame_context; + vp9_hw_regs->vp9d_param.reg103.allow_high_precision_mv = pic_param->allow_high_precision_mv; + vp9_hw_regs->vp9d_param.reg103.last_key_frame_flag = hw_ctx->ls_info.last_intra_only; + + /* set info for multi core */ + { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg65.cur_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + // last poc + ref_idx = pic_param->frame_refs[0].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + if (ref_frame_idx < 0x7f) { + mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg95.last_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + } + // golden poc + ref_idx = pic_param->frame_refs[1].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + if (ref_frame_idx < 0x7f) { + mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg96.golden_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + } + // altref poc + ref_idx = pic_param->frame_refs[2].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + if (ref_frame_idx < 0x7f) { + mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg97.altref_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + } + // colref poc + vp9_hw_regs->vp9d_param.reg98.col_ref_poc = + (hw_ctx->col_ref_poc != 0) ? hw_ctx->col_ref_poc : vp9_hw_regs->vp9d_param.reg65.cur_poc; + if (pic_param->show_frame && !pic_param->show_existing_frame) + hw_ctx->col_ref_poc = vp9_hw_regs->vp9d_param.reg65.cur_poc; + // segment id ref poc + vp9_hw_regs->vp9d_param.reg100.segid_ref_poc = hw_ctx->segid_ref_poc; + + vp9_hw_regs->vp9d_addr.reg169_segidcur_base = mpp_buffer_get_fd(hw_ctx->seg_base); + vp9_hw_regs->vp9d_addr.reg168_segidlast_base = mpp_buffer_get_fd(hw_ctx->seg_base); + if (hw_ctx->last_segid_flag) { + mpp_dev_set_reg_offset(cfg->dev, 168, hw_ctx->offset_segid_last); + mpp_dev_set_reg_offset(cfg->dev, 169, hw_ctx->offset_segid_cur); + } else { + mpp_dev_set_reg_offset(cfg->dev, 168, hw_ctx->offset_segid_cur); + mpp_dev_set_reg_offset(cfg->dev, 169, hw_ctx->offset_segid_last); + } + + if ((pic_param->stVP9Segments.enabled && pic_param->stVP9Segments.update_map) || + (hw_ctx->ls_info.last_width != pic_param->width) || + (hw_ctx->ls_info.last_height != pic_param->height) || + intraFlag || pic_param->error_resilient_mode) { + hw_ctx->segid_ref_poc = vp9_hw_regs->vp9d_param.reg65.cur_poc; + hw_ctx->last_segid_flag = !hw_ctx->last_segid_flag; + vp9_hw_regs->vp9d_param.reg100.segid_ref_poc = 0; + vp9_hw_regs->vp9d_param.reg75.vp9_segment_id_update = 1; + } else + vp9_hw_regs->vp9d_param.reg75.vp9_segment_id_update = 0; + } + + /* config last prob base and update write base */ + { + + if (intraFlag || pic_param->error_resilient_mode) { + if (intraFlag + || pic_param->error_resilient_mode + || (pic_param->reset_frame_context == 3)) { + memset(hw_ctx->prob_ctx_valid, 0, sizeof(hw_ctx->prob_ctx_valid)); + } else if (pic_param->reset_frame_context == 2) { + hw_ctx->prob_ctx_valid[frame_ctx_id] = 0; + } + } + +#if VP9_DUMP + { + static RK_U32 file_cnt = 0; + char file_name[128]; + RK_U32 i = 0; + sprintf(file_name, "/data/vp9/prob_last_%d.txt", file_cnt); + FILE *fp = fopen(file_name, "wb"); + RK_U32 *tmp = NULL; + if (hw_ctx->prob_ctx_valid[frame_ctx_id]) { + tmp = (RK_U32 *)mpp_buffer_get_ptr(hw_ctx->prob_loop_base[pic_param->frame_context_idx]); + } else { + tmp = (RK_U32 *)mpp_buffer_get_ptr(hw_ctx->prob_default_base); + } + for (i = 0; i < PROB_SIZE / 4; i += 2) { + fprintf(fp, "%08x%08x\n", tmp[i + 1], tmp[i]); + } + file_cnt++; + fflush(fp); + fclose(fp); + } +#endif + + if (hw_ctx->prob_ctx_valid[frame_ctx_id]) { + vp9_hw_regs->vp9d_addr.reg162_last_prob_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); + vp9_hw_regs->common.reg028.swreg_vp9_rd_prob_idx = frame_ctx_id + 1; + vp9_hw_regs->vp9d_param.reg99.prob_ref_poc = hw_ctx->prob_ref_poc[frame_ctx_id]; + } else { + vp9_hw_regs->vp9d_addr.reg162_last_prob_base = mpp_buffer_get_fd(hw_ctx->prob_default_base); + hw_ctx->prob_ctx_valid[frame_ctx_id] |= pic_param->refresh_frame_context; + vp9_hw_regs->common.reg028.swreg_vp9_rd_prob_idx = 0; + vp9_hw_regs->vp9d_param.reg99.prob_ref_poc = 0; + hw_ctx->prob_ref_poc[frame_ctx_id] = vp9_hw_regs->vp9d_param.reg65.cur_poc; + } + hal_vp9d_dbg_par("vp9d intra %d parallelmode %d frame_ctx_id %d refresh %d err %d\n", + intraFlag, pic_param->parallelmode, frame_ctx_id, + pic_param->refresh_frame_context, pic_param->error_resilient_mode); + if (!pic_param->parallelmode) + hw_ctx->prob_ref_poc[frame_ctx_id] = vp9_hw_regs->vp9d_param.reg65.cur_poc; + vp9_hw_regs->vp9d_addr.reg172_update_prob_wr_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); + vp9_hw_regs->common.reg028.swreg_vp9_wr_prob_idx = frame_ctx_id + 1; + + } + vp9_hw_regs->vp9d_addr.reg160_delta_prob_base = mpp_buffer_get_fd(hw_ctx->probe_base); +#else + hal_vp9d_output_probe(mpp_buffer_get_ptr(hw_ctx->probe_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->probe_base); +#endif + vp9_hw_regs->common.reg012.colmv_compress_en = cfg->hw_info ? cfg->hw_info->cap_colmv_compress : 1; + vp9_hw_regs->common.reg013.cur_pic_is_idr = !pic_param->frame_type; + vp9_hw_regs->common.reg009.dec_mode = 2; //set as vp9 dec + vp9_hw_regs->common.reg016_str_len = ((stream_len + 15) & (~15)) + 0x80; + + mpp_buf_slot_get_prop(p_hal ->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + bitstream = mpp_buffer_get_ptr(streambuf); + aglin_offset = vp9_hw_regs->common.reg016_str_len - stream_len; + if (aglin_offset > 0) { + memset((void *)(bitstream + stream_len), 0, aglin_offset); + } + + //--- caculate the yuv_frame_size and mv_size + bit_depth = pic_param->BitDepthMinus8Luma + 8; + + { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + fbc_en = MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe)); + + if (fbc_en) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 h = MPP_ALIGN(mpp_frame_get_height(mframe), 64); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (h + 16) / 16, SZ_4K); + + vp9_hw_regs->common.reg012.fbc_e = 1; + vp9_hw_regs->common.reg018.y_hor_virstride = fbc_hdr_stride >> 4; + vp9_hw_regs->common.reg019.uv_hor_virstride = fbc_hdr_stride >> 4; + vp9_hw_regs->common.reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + sw_y_hor_virstride = mpp_frame_get_hor_stride(mframe) >> 4; + sw_uv_hor_virstride = sw_y_hor_virstride; + sw_y_virstride = mpp_frame_get_ver_stride(mframe) * sw_y_hor_virstride; + + vp9_hw_regs->common.reg012.fbc_e = 0; + vp9_hw_regs->common.reg018.y_hor_virstride = sw_y_hor_virstride; + vp9_hw_regs->common.reg019.uv_hor_virstride = sw_uv_hor_virstride; + vp9_hw_regs->common.reg020_y_virstride.y_virstride = sw_y_virstride; + } + } + if (!pic_param->intra_only && pic_param->frame_type && + !pic_param->error_resilient_mode && hw_ctx->ls_info.last_show_frame) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + } + + mpp_buf_slot_get_prop(p_hal ->cfg->frame_slots, task->dec.output, SLOT_BUFFER, &framebuf); + vp9_hw_regs->common_addr.reg130_decout_base = mpp_buffer_get_fd(framebuf); + vp9_hw_regs->common_addr.reg128_rlc_base = mpp_buffer_get_fd(streambuf); + vp9_hw_regs->common_addr.reg129_rlcwrite_base = mpp_buffer_get_fd(streambuf); + + vp9_hw_regs->vp9d_addr.reg167_count_prob_base = mpp_buffer_get_fd(hw_ctx->probe_base); + mpp_dev_set_reg_offset(cfg->dev, 167, hw_ctx->offset_count); + + //set cur colmv base + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, task->dec.output); + vp9_hw_regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + hw_ctx->mv_base_addr = vp9_hw_regs->common_addr.reg131_colmv_cur_base; + if (hw_ctx->pre_mv_base_addr < 0) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + } + vp9_hw_regs->vp9d_addr.reg170_ref_colmv_base = hw_ctx->pre_mv_base_addr; + + vp9_hw_regs->vp9d_param.reg64.cprheader_offset = 0; + reg_ref_base = (RK_U32*)&vp9_hw_regs->vp9d_addr.reg164_ref_last_base; + for (i = 0; i < 3; i++) { + MppFrame frame = NULL; + + ref_idx = pic_param->frame_refs[i].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + ref_frame_width_y = pic_param->ref_frame_coded_width[ref_idx]; + ref_frame_height_y = pic_param->ref_frame_coded_height[ref_idx]; + + if (ref_frame_idx < 0x7f) + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &frame); + + if (fbc_en && frame) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(frame); + RK_U32 h = MPP_ALIGN(mpp_frame_get_height(frame), 64); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (h + 16) / 16, SZ_4K); + + y_hor_virstride = uv_hor_virstride = fbc_hdr_stride >> 4; + y_virstride = fbd_offset; + } else { + if (frame) { + y_hor_virstride = uv_hor_virstride = mpp_frame_get_hor_stride(frame) >> 4; + y_virstride = y_hor_virstride * mpp_frame_get_ver_stride(frame); + } else { + y_hor_virstride = uv_hor_virstride = (mpp_align_256_odd((ref_frame_width_y * bit_depth) >> 3) >> 4); + y_virstride = y_hor_virstride * mpp_align_64(ref_frame_height_y); + } + } + + if (pic_param->ref_frame_map[ref_idx].Index7Bits < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->ref_frame_map[ref_idx].Index7Bits, SLOT_BUFFER, &framebuf); + } + + if (pic_param->ref_frame_map[ref_idx].Index7Bits < 0x7f) { + switch (i) { + case 0: { + vp9_hw_regs->vp9d_param.reg106.framewidth_last = ref_frame_width_y; + vp9_hw_regs->vp9d_param.reg107.frameheight_last = ref_frame_height_y; + vp9_hw_regs->vp9d_param.reg79.lastfy_hor_virstride = y_hor_virstride; + vp9_hw_regs->vp9d_param.reg80.lastfuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->vp9d_param.reg85.lastfy_virstride = y_virstride; + } break; + case 1: { + vp9_hw_regs->vp9d_param.reg108.framewidth_golden = ref_frame_width_y; + vp9_hw_regs->vp9d_param.reg109.frameheight_golden = ref_frame_height_y; + vp9_hw_regs->vp9d_param.reg81.goldenfy_hor_virstride = y_hor_virstride; + vp9_hw_regs->vp9d_param.reg82.goldenfuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->vp9d_param.reg86.goldeny_virstride = y_virstride; + } break; + case 2: { + vp9_hw_regs->vp9d_param.reg110.framewidth_alfter = ref_frame_width_y; + vp9_hw_regs->vp9d_param.reg111.frameheight_alfter = ref_frame_height_y; + vp9_hw_regs->vp9d_param.reg83.altreffy_hor_virstride = y_hor_virstride; + vp9_hw_regs->vp9d_param.reg84.altreffuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->vp9d_param.reg87.altrefy_virstride = y_virstride; + } break; + default: + break; + } + + /*0 map to 11*/ + /*1 map to 12*/ + /*2 map to 13*/ + if (framebuf != NULL) { + reg_ref_base[i] = mpp_buffer_get_fd(framebuf); + } else { + mpp_log("ref buff address is no valid used out as base slot index 0x%x", pic_param->ref_frame_map[ref_idx].Index7Bits); + reg_ref_base[i] = vp9_hw_regs->common_addr.reg130_decout_base; + } + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, pic_param->ref_frame_map[ref_idx].Index7Bits); + vp9_hw_regs->vp9d_addr.reg181_196_ref_colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } else { + reg_ref_base[i] = vp9_hw_regs->common_addr.reg130_decout_base; + vp9_hw_regs->vp9d_addr.reg181_196_ref_colmv_base[i] = vp9_hw_regs->common_addr.reg131_colmv_cur_base; + } + } + + for (i = 0; i < 8; i++) { + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_qp_delta_en = (hw_ctx->ls_info.feature_mask[i]) & 0x1; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_qp_delta = hw_ctx->ls_info.feature_data[i][0]; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_loopfitler_value_en = (hw_ctx->ls_info.feature_mask[i] >> 1) & 0x1; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_loopfilter_value = hw_ctx->ls_info.feature_data[i][1]; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_referinfo_en = (hw_ctx->ls_info.feature_mask[i] >> 2) & 0x1; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_referinfo = hw_ctx->ls_info.feature_data[i][2]; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_skip_en = (hw_ctx->ls_info.feature_mask[i] >> 3) & 0x1; + } + + vp9_hw_regs->vp9d_param.reg67_74[0].segid_abs_delta = hw_ctx->ls_info.abs_delta_last; + vp9_hw_regs->vp9d_param.reg76.tx_mode = pic_param->txmode; + vp9_hw_regs->vp9d_param.reg76.frame_reference_mode = pic_param->refmode; + vp9_hw_regs->vp9d_param.reg94.ref_deltas_lastframe = 0; + + if (!intraFlag) { + for (i = 0; i < 4; i++) + vp9_hw_regs->vp9d_param.reg94.ref_deltas_lastframe |= (hw_ctx->ls_info.last_ref_deltas[i] & 0x7f) << (7 * i); + + for (i = 0; i < 2; i++) + vp9_hw_regs->vp9d_param.reg75.mode_deltas_lastframe |= (hw_ctx->ls_info.last_mode_deltas[i] & 0x7f) << (7 * i); + } else { + hw_ctx->ls_info.segmentation_enable_flag_last = 0; + hw_ctx->ls_info.last_intra_only = 1; + } + + vp9_hw_regs->vp9d_param.reg75.segmentation_enable_lstframe = hw_ctx->ls_info.segmentation_enable_flag_last; + vp9_hw_regs->vp9d_param.reg75.last_show_frame = hw_ctx->ls_info.last_show_frame; + vp9_hw_regs->vp9d_param.reg75.last_intra_only = hw_ctx->ls_info.last_intra_only; + vp9_hw_regs->vp9d_param.reg75.last_widthheight_eqcur = (pic_param->width == hw_ctx->ls_info.last_width) && (pic_param->height == hw_ctx->ls_info.last_height); + vp9_hw_regs->vp9d_param.reg78.lasttile_size = stream_len - pic_param->first_partition_size; + + + if (!intraFlag) { + vp9_hw_regs->vp9d_param.reg88.lref_hor_scale = pic_param->mvscale[0][0]; + vp9_hw_regs->vp9d_param.reg89.lref_ver_scale = pic_param->mvscale[0][1]; + vp9_hw_regs->vp9d_param.reg90.gref_hor_scale = pic_param->mvscale[1][0]; + vp9_hw_regs->vp9d_param.reg91.gref_ver_scale = pic_param->mvscale[1][1]; + vp9_hw_regs->vp9d_param.reg92.aref_hor_scale = pic_param->mvscale[2][0]; + vp9_hw_regs->vp9d_param.reg93.aref_ver_scale = pic_param->mvscale[2][1]; + } + + vp9_hw_regs->common.reg010.dec_e = 1; + vp9_hw_regs->common.reg011.dec_timeout_e = 1; + vp9_hw_regs->common.reg011.buf_empty_en = 1; + vp9_hw_regs->common.reg011.dec_clkgate_e = 1; + vp9_hw_regs->common.reg011.dec_e_strmd_clkgate_dis = 0; + + vp9_hw_regs->common.reg012.wait_reset_en = 1; + vp9_hw_regs->common.reg013.timeout_mode = 1; + + vp9_hw_regs->common.reg026.swreg_block_gating_e = + (mpp_get_soc_type() == ROCKCHIP_SOC_RK3588) ? 0xfffef : 0xfffff; + vp9_hw_regs->common.reg026.reg_cfg_gating_en = 1; + vp9_hw_regs->common.reg032_timeout_threshold = 0x3ffff; + + //last info update + hw_ctx->ls_info.abs_delta_last = pic_param->stVP9Segments.abs_delta; + for (i = 0 ; i < 4; i ++) { + hw_ctx->ls_info.last_ref_deltas[i] = pic_param->ref_deltas[i]; + } + + for (i = 0 ; i < 2; i ++) { + hw_ctx->ls_info.last_mode_deltas[i] = pic_param->mode_deltas[i]; + } + + for (i = 0; i < 8; i++) { + hw_ctx->ls_info.feature_data[i][0] = pic_param->stVP9Segments.feature_data[i][0]; + hw_ctx->ls_info.feature_data[i][1] = pic_param->stVP9Segments.feature_data[i][1]; + hw_ctx->ls_info.feature_data[i][2] = pic_param->stVP9Segments.feature_data[i][2]; + hw_ctx->ls_info.feature_data[i][3] = pic_param->stVP9Segments.feature_data[i][3]; + hw_ctx->ls_info.feature_mask[i] = pic_param->stVP9Segments.feature_mask[i]; + } + if (!hw_ctx->ls_info.segmentation_enable_flag_last) + hw_ctx->ls_info.segmentation_enable_flag_last = pic_param->stVP9Segments.enabled; + + hw_ctx->ls_info.last_show_frame = pic_param->show_frame; + hw_ctx->ls_info.last_width = pic_param->width; + hw_ctx->ls_info.last_height = pic_param->height; + hw_ctx->ls_info.last_intra_only = (!pic_param->frame_type || pic_param->intra_only); + hal_vp9d_dbg_par("stVP9Segments.enabled %d show_frame %d width %d height %d last_intra_only %d", + pic_param->stVP9Segments.enabled, pic_param->show_frame, + pic_param->width, pic_param->height, + hw_ctx->ls_info.last_intra_only); + + hal_vp9d_rcb_info_update(hal, vp9_hw_regs, pic_param); + { + MppBuffer rcb_buf = NULL; + + rcb_buf = (p_hal->fast_mode != 0) ? hw_ctx->g_buf[task->dec.reg_index].rcb_buf : hw_ctx->rcb_buf; + vdpu34x_setup_rcb(&vp9_hw_regs->common_addr, cfg->dev, rcb_buf, hw_ctx->rcb_info); + } + vdpu34x_setup_statistic(&vp9_hw_regs->common, &vp9_hw_regs->statistic); + + // whether need update counts + if (pic_param->refresh_frame_context && !pic_param->parallelmode) { + task->dec.flags.wait_done = 1; + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu34x_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + Vdpu34xVp9dRegSet *hw_regs = (Vdpu34xVp9dRegSet *)hw_ctx->hw_regs; + MppDev dev = p_hal->cfg->dev; + + if (p_hal->fast_mode) { + RK_S32 index = task->dec.reg_index; + hw_regs = (Vdpu34xVp9dRegSet *)hw_ctx->g_buf[index].hw_regs; + } + + mpp_assert(hw_regs); + + +#if VP9_DUMP + { + static RK_U32 file_cnt = 0; + char file_name[128]; + sprintf(file_name, "/data/vp9_regs/reg_%d.txt", file_cnt); + FILE *fp = fopen(file_name, "wb"); + RK_U32 i = 0; + RK_U32 *tmp = NULL; + tmp = (RK_U32 *)&hw_regs->common; + for (i = 0; i < sizeof(hw_regs->common) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 8, tmp[i]); + } + fprintf(fp, "\n"); + tmp = (RK_U32 *)&hw_regs->vp9d_param; + for (i = 0; i < sizeof(hw_regs->vp9d_param) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 64, tmp[i]); + } + fprintf(fp, "\n"); + tmp = (RK_U32 *)&hw_regs->common_addr; + for (i = 0; i < sizeof(hw_regs->common_addr) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 128, tmp[i]); + } + fprintf(fp, "\n"); + tmp = (RK_U32 *)&hw_regs->vp9d_addr; + for (i = 0; i < sizeof(hw_regs->vp9d_addr) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 160, tmp[i]); + } + file_cnt++; + fflush(fp); + fclose(fp); + } +#endif + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = &hw_regs->common; + wr_cfg.size = sizeof(hw_regs->common); + wr_cfg.offset = VDPU34X_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->vp9d_param; + wr_cfg.size = sizeof(hw_regs->vp9d_param); + wr_cfg.offset = VDPU34X_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->common_addr; + wr_cfg.size = sizeof(hw_regs->common_addr); + wr_cfg.offset = VDPU34X_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->vp9d_addr; + wr_cfg.size = sizeof(hw_regs->vp9d_addr); + wr_cfg.offset = VDPU34X_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->statistic; + wr_cfg.size = sizeof(hw_regs->statistic); + wr_cfg.offset = VDPU34X_OFF_STATISTIC_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->irq_status; + rd_cfg.size = sizeof(hw_regs->irq_status); + rd_cfg.offset = VDPU34X_OFF_INTERRUPT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* rcb info for sram */ + vdpu34x_set_rcbinfo(dev, hw_ctx->rcb_info); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +static MPP_RET hal_vp9d_vdpu34x_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + Vdpu34xVp9dRegSet *hw_regs = (Vdpu34xVp9dRegSet *)hw_ctx->hw_regs; + + if (p_hal->fast_mode) + hw_regs = (Vdpu34xVp9dRegSet *)hw_ctx->g_buf[task->dec.reg_index].hw_regs; + + mpp_assert(hw_regs); + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (hal_vp9d_debug & HAL_VP9D_DBG_REG) { + RK_U32 *p = (RK_U32 *)hw_regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(Vdpu34xVp9dRegSet) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i, *p++); + } + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + !hw_regs->irq_status.reg224.dec_rdy_sta) { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_frame_set_errinfo(mframe, 1); + } +#if !HW_PROB + if (p_hal->dec_cb && task->dec.flags.wait_done) { + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + + mpp_buffer_sync_end(hw_ctx->count_base); + hal_vp9d_update_counts(mpp_buffer_get_ptr(hw_ctx->count_base), task->dec.syntax.data); + mpp_callback(p_hal->dec_cb, &pic_param->counts); + } +#endif + if (p_hal->fast_mode) { + hw_ctx->g_buf[task->dec.reg_index].use_flag = 0; + } + + (void)task; + return ret; +} + +static MPP_RET hal_vp9d_vdpu34x_reset(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + + hal_vp9d_enter(); + + memset(&hw_ctx->ls_info, 0, sizeof(hw_ctx->ls_info)); + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + hw_ctx->last_segid_flag = 1; + memset(&hw_ctx->prob_ref_poc, 0, sizeof(hw_ctx->prob_ref_poc)); + hw_ctx->col_ref_poc = 0; + hw_ctx->segid_ref_poc = 0; + + hal_vp9d_leave(); + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu34x_flush(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu34xVp9dCtx *hw_ctx = (Vdpu34xVp9dCtx*)p_hal->hw_ctx; + + hal_vp9d_enter(); + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + + hal_vp9d_leave(); + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu34x_control(void *hal, MpiCmd cmd_type, void *param) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO : { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, (MppFrame)param, 0); + } else { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + } + } break; + default : { + } break; + } + + return MPP_OK; +} + +const MppHalApi hal_vp9d_vdpu34x = { + .name = "vp9d_vdpu34x", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingVP9, + .ctx_size = sizeof(HalVp9dCtx), + .flag = 0, + .init = hal_vp9d_vdpu34x_init, + .deinit = hal_vp9d_vdpu34x_deinit, + .reg_gen = hal_vp9d_vdpu34x_gen_regs, + .start = hal_vp9d_vdpu34x_start, + .wait = hal_vp9d_vdpu34x_wait, + .reset = hal_vp9d_vdpu34x_reset, + .flush = hal_vp9d_vdpu34x_flush, + .control = hal_vp9d_vdpu34x_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_vp9d_vdpu34x) diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu34x.h b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu34x.h new file mode 100644 index 000000000..63305b543 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu34x.h @@ -0,0 +1,31 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP9D_VDPU34X_H +#define HAL_VP9D_VDPU34X_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_vp9d_vdpu34x; + +#ifdef __cplusplus +} +#endif +#endif /* HAL_VP9D_VDPU34X_H */ diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu382.c b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu382.c new file mode 100644 index 000000000..7851106b5 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu382.c @@ -0,0 +1,1133 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp9d_vdpu382" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_hal.h" + +#include "hal_bufs.h" +#include "hal_vp9d_debug.h" +#include "hal_vp9d_com.h" +#include "hal_vp9d_vdpu382.h" +#include "hal_vp9d_ctx.h" +#include "vdpu382_vp9d.h" +#include "vp9d_syntax.h" +#include "vdpu_com.h" + +#define HW_PROB 1 +#define PROB_SIZE_ALIGN_TO_4K MPP_ALIGN(PROB_SIZE, SZ_4K) +#define COUNT_SIZE_ALIGN_TO_4K MPP_ALIGN(COUNT_SIZE, SZ_4K) +#define MAX_SEGMAP_SIZE_ALIGN_TO_4K MPP_ALIGN(MAX_SEGMAP_SIZE, SZ_4K) + +#define VDPU382_OFFSET_COUNT (PROB_SIZE_ALIGN_TO_4K) +#define VDPU382_PROBE_BUFFER_SIZE (PROB_SIZE_ALIGN_TO_4K + COUNT_SIZE_ALIGN_TO_4K) + +typedef struct Vdpu382Vp9dCtx_t { + Vp9dRegBuf g_buf[VDPU_FAST_REG_SET_CNT]; + MppBuffer probe_base; + MppBuffer seg_base; + RK_U32 offset_count; + RK_U32 offset_segid_cur; + RK_U32 offset_segid_last; + MppBuffer prob_default_base; + void *hw_regs; + RK_S32 mv_base_addr; + RK_S32 pre_mv_base_addr; + Vp9dLastInfo ls_info; + /* + * swap between segid_cur_base & segid_last_base + * 0 used segid_cur_base as last + * 1 used segid_last_base as + */ + RK_U32 last_segid_flag; + RK_S32 width; + RK_S32 height; + /* rcb buffers info */ + RK_S32 rcb_buf_size; + VdpuRcbInfo rcb_info[RCB_BUF_COUNT]; + MppBuffer rcb_buf; + RK_U32 num_row_tiles; + RK_U32 bit_depth; + /* colmv buffers info */ + HalBufs cmv_bufs; + RK_S32 mv_size; + RK_S32 mv_count; + RK_U32 prob_ctx_valid[VP9_CONTEXT]; + MppBuffer prob_loop_base[VP9_CONTEXT]; + RK_U32 prob_ref_poc[VP9_CONTEXT]; + RK_U32 col_ref_poc; + RK_U32 segid_ref_poc; +} Vdpu382Vp9dCtx; + +static MPP_RET hal_vp9d_alloc_res(HalVp9dCtx *hal) +{ + RK_S32 i = 0; + RK_S32 ret = 0; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + MppBufferGroup group = p_hal->cfg->buf_group; + + hw_ctx->offset_count = VDPU382_OFFSET_COUNT; + hw_ctx->offset_segid_cur = 0; + hw_ctx->offset_segid_last = MAX_SEGMAP_SIZE_ALIGN_TO_4K; + /* alloc common buffer */ + for (i = 0; i < VP9_CONTEXT; i++) { + ret = mpp_buffer_get(group, &hw_ctx->prob_loop_base[i], PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_loop_base get buffer failed\n"); + return ret; + } + } + ret = mpp_buffer_get(group, &hw_ctx->prob_default_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_default_base get buffer failed\n"); + return ret; + } + /* alloc buffer for fast mode or normal */ + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + hw_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu382Vp9dRegSet)); + ret = mpp_buffer_get(group, &hw_ctx->g_buf[i].probe_base, VDPU382_PROBE_BUFFER_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + } + } else { + hw_ctx->hw_regs = mpp_calloc_size(void, sizeof(Vdpu382Vp9dRegSet)); + ret = mpp_buffer_get(group, &hw_ctx->probe_base, VDPU382_PROBE_BUFFER_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + } + + ret = mpp_buffer_get(group, &hw_ctx->seg_base, MAX_SEGMAP_SIZE_ALIGN_TO_4K * 2); + if (ret) { + mpp_err("vp9 segid_base get buffer failed\n"); + return ret; + } + return MPP_OK; +} + +static MPP_RET hal_vp9d_release_res(HalVp9dCtx *hal) +{ + RK_S32 i = 0; + RK_S32 ret = 0; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + + if (hw_ctx->prob_default_base) { + ret = mpp_buffer_put(hw_ctx->prob_default_base); + if (ret) { + mpp_err("vp9 probe_wr_base put buffer failed\n"); + return ret; + } + } + for (i = 0; i < VP9_CONTEXT; i++) { + if (hw_ctx->prob_loop_base[i]) { + ret = mpp_buffer_put(hw_ctx->prob_loop_base[i]); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + } + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (hw_ctx->g_buf[i].probe_base) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].probe_base); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + if (hw_ctx->g_buf[i].hw_regs) { + mpp_free(hw_ctx->g_buf[i].hw_regs); + hw_ctx->g_buf[i].hw_regs = NULL; + } + if (hw_ctx->g_buf[i].rcb_buf) { + ret = mpp_buffer_put(hw_ctx->g_buf[i].rcb_buf); + if (ret) { + mpp_err("vp9 rcb_buf[%d] put buffer failed\n", i); + return ret; + } + } + } + } else { + if (hw_ctx->probe_base) { + ret = mpp_buffer_put(hw_ctx->probe_base); + if (ret) { + mpp_err("vp9 probe_base put buffer failed\n"); + return ret; + } + } + + if (hw_ctx->hw_regs) { + mpp_free(hw_ctx->hw_regs); + hw_ctx->hw_regs = NULL; + } + if (hw_ctx->rcb_buf) { + ret = mpp_buffer_put(hw_ctx->rcb_buf); + if (ret) { + mpp_err("vp9 rcb_buf put buffer failed\n"); + return ret; + } + } + } + + if (hw_ctx->cmv_bufs) { + ret = hal_bufs_deinit(hw_ctx->cmv_bufs); + if (ret) { + mpp_err("vp9 cmv bufs deinit buffer failed\n"); + return ret; + } + } + + if (hw_ctx->seg_base) { + ret = mpp_buffer_put(hw_ctx->seg_base); + if (ret) { + mpp_err("vp9 seg_base put buffer failed\n"); + return ret; + } + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu382_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx *)hal; + + hal_vp9d_release_res(p_hal); + + MPP_FREE(p_hal->hw_ctx); + + return ret = MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu382_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + + mpp_env_get_u32("hal_vp9d_debug", &hal_vp9d_debug, 0); + + cfg->support_fast_mode = 1; + p_hal->cfg = cfg; + p_hal->client_type = VPU_CLIENT_RKVDEC; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->hw_ctx = mpp_calloc_size(void, sizeof(Vdpu382Vp9dCtx))); + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_64); + + ret = hal_vp9d_alloc_res(p_hal); + if (ret) { + mpp_err("hal_vp9d_alloc_res failed\n"); + goto __FAILED; + } + + hw_ctx->last_segid_flag = 1; + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + return ret; +__FAILED: + hal_vp9d_vdpu382_deinit(hal); + return ret; +} + +static void vp9d_refine_rcb_size(VdpuRcbInfo *rcb_info, + Vdpu382Vp9dRegSet *vp9_hw_regs, + RK_S32 width, RK_S32 height, void* data) +{ + RK_U32 rcb_bits = 0; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)data; + RK_U32 num_tiles_col = 1 << pic_param->log2_tile_cols; + RK_U32 bit_depth = pic_param->BitDepthMinus8Luma + 8; + RK_U32 ext_align_size = num_tiles_col * 64 * 8; + + width = MPP_ALIGN(width, VP9_CTU_SIZE); + height = MPP_ALIGN(height, VP9_CTU_SIZE); + /* RCB_STRMD_ROW */ + if (width >= 4096) + rcb_bits = MPP_ALIGN(width, 64) * 232 + ext_align_size; + else + rcb_bits = 0; + rcb_info[RCB_STRMD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_ROW */ + if (width >= 8192) + rcb_bits = (MPP_ALIGN(width - 8192, 4) << 1) + ext_align_size; + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_TRANSD_COL */ + if ((height >= 8192) && (num_tiles_col > 1)) + rcb_bits = (MPP_ALIGN(height - 8192, 4) << 1); + else + rcb_bits = 0; + rcb_info[RCB_TRANSD_COL].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_ROW */ + rcb_bits = width * 36 + ext_align_size; + rcb_info[RCB_INTER_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_INTER_COL */ + rcb_info[RCB_INTER_COL].size = 0; + + /* RCB_INTRA_ROW */ + rcb_bits = width * 2 * 11 + ext_align_size; + rcb_info[RCB_INTRA_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_DBLK_ROW */ + rcb_bits = width * (0.5 + 16 * bit_depth) + num_tiles_col * 192 * bit_depth + ext_align_size; + rcb_info[RCB_DBLK_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_SAO_ROW */ + rcb_info[RCB_SAO_ROW].size = 0; + + /* RCB_FBC_ROW */ + if (vp9_hw_regs->common.reg012.fbc_e) { + rcb_bits = 8 * width * bit_depth + ext_align_size; + } else + rcb_bits = 0; + rcb_info[RCB_FBC_ROW].size = MPP_RCB_BYTES(rcb_bits); + + /* RCB_FILT_COL */ + if (num_tiles_col > 1) { + if (vp9_hw_regs->common.reg012.fbc_e) { + rcb_bits = height * (4 + 24 * bit_depth); + } else + rcb_bits = height * (4 + 16 * bit_depth); + } else + rcb_bits = 0; + rcb_info[RCB_FILT_COL].size = MPP_RCB_BYTES(rcb_bits); +} + +static void hal_vp9d_rcb_info_update(void *hal, Vdpu382Vp9dRegSet *hw_regs, void *data) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)data; + RK_U32 num_tiles = pic_param->log2_tile_rows; + RK_U32 bit_depth = pic_param->BitDepthMinus8Luma + 8; + RK_S32 height = mpp_align_64(pic_param->height); + RK_S32 width = mpp_align_64(pic_param->width); + + if (hw_ctx->num_row_tiles != num_tiles || + hw_ctx->bit_depth != bit_depth || + hw_ctx->width != width || + hw_ctx->height != height) { + + hw_ctx->rcb_buf_size = vdpu382_get_rcb_buf_size(hw_ctx->rcb_info, width, height); + vp9d_refine_rcb_size(hw_ctx->rcb_info, hw_regs, width, height, pic_param); + + if (p_hal->fast_mode) { + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(hw_ctx->g_buf); i++) { + MppBuffer rcb_buf = hw_ctx->g_buf[i].rcb_buf; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + hw_ctx->g_buf[i].rcb_buf = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, hw_ctx->rcb_buf_size); + hw_ctx->g_buf[i].rcb_buf = rcb_buf; + } + } else { + MppBuffer rcb_buf = hw_ctx->rcb_buf; + + if (rcb_buf) { + mpp_buffer_put(rcb_buf); + rcb_buf = NULL; + } + mpp_buffer_get(p_hal->cfg->buf_group, &rcb_buf, hw_ctx->rcb_buf_size); + hw_ctx->rcb_buf = rcb_buf; + } + + hw_ctx->num_row_tiles = num_tiles; + hw_ctx->bit_depth = bit_depth; + hw_ctx->width = width; + hw_ctx->height = height; + } +} + + +static MPP_RET hal_vp9d_vdpu382_setup_colmv_buf(void *hal, HalTaskInfo *task) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + RK_U32 width = pic_param->width; + RK_U32 height = pic_param->height; + RK_S32 mv_size = 0, colmv_size = 8, colmv_byte = 16; + RK_U32 compress = p_hal->cfg->hw_info ? p_hal->cfg->hw_info->cap_colmv_compress : 1; + + mv_size = vdpu382_get_colmv_size(width, height, VP9_CTU_SIZE, colmv_byte, colmv_size, compress); + if (hw_ctx->cmv_bufs == NULL || hw_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (hw_ctx->cmv_bufs) { + hal_bufs_deinit(hw_ctx->cmv_bufs); + hw_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(&hw_ctx->cmv_bufs); + if (hw_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_ERR_NOMEM; + } + hw_ctx->mv_size = mv_size; + hw_ctx->mv_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(hw_ctx->cmv_bufs, hw_ctx->mv_count, 1, &size); + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu382_gen_regs(void *hal, HalTaskInfo *task) +{ + RK_S32 i; + RK_U8 bit_depth = 0; + RK_U32 ref_frame_width_y; + RK_U32 ref_frame_height_y; + RK_S32 stream_len = 0, aglin_offset = 0; + RK_U32 y_hor_virstride, uv_hor_virstride, y_virstride; + RK_U8 *bitstream = NULL; + MppBuffer streambuf = NULL; + RK_U32 sw_y_hor_virstride; + RK_U32 sw_uv_hor_virstride; + RK_U32 sw_y_virstride; + RK_U8 ref_idx = 0; + RK_U8 ref_frame_idx = 0; + RK_U32 *reg_ref_base = 0; + RK_S32 intraFlag = 0; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_U32 fbc_en = 0; + + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + RK_U32 frame_ctx_id = pic_param->frame_context_idx; + MppHalCfg *cfg = p_hal->cfg; + + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!hw_ctx->g_buf[i].use_flag) { + task->dec.reg_index = i; + hw_ctx->probe_base = hw_ctx->g_buf[i].probe_base; + + hw_ctx->hw_regs = hw_ctx->g_buf[i].hw_regs; + hw_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("vp9 fast mode buf all used\n"); + return MPP_ERR_NOMEM; + } + } + + if (hal_vp9d_vdpu382_setup_colmv_buf(hal, task)) + return MPP_ERR_NOMEM; + + Vdpu382Vp9dRegSet *vp9_hw_regs = (Vdpu382Vp9dRegSet*)hw_ctx->hw_regs; + intraFlag = (!pic_param->frame_type || pic_param->intra_only); + stream_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + memset(hw_ctx->hw_regs, 0, sizeof(Vdpu382Vp9dRegSet)); +#if HW_PROB + hal_vp9d_prob_flag_delta(mpp_buffer_get_ptr(hw_ctx->probe_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->probe_base); + if (intraFlag) { + hal_vp9d_prob_default(mpp_buffer_get_ptr(hw_ctx->prob_default_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->prob_default_base); + } + + /* config reg103 */ + vp9_hw_regs->vp9d_param.reg103.prob_update_en = 1; + vp9_hw_regs->vp9d_param.reg103.intra_only_flag = intraFlag; + if (!intraFlag) { + vp9_hw_regs->vp9d_param.reg103.txfmmode_rfsh_en = (pic_param->txmode == 4) ? 1 : 0; + vp9_hw_regs->vp9d_param.reg103.interp_filter_switch_en = pic_param->interp_filter == 4 ? 1 : 0; + } + vp9_hw_regs->vp9d_param.reg103.ref_mode_rfsh_en = 1; + vp9_hw_regs->vp9d_param.reg103.single_ref_rfsh_en = 1; + vp9_hw_regs->vp9d_param.reg103.comp_ref_rfsh_en = 1; + vp9_hw_regs->vp9d_param.reg103.inter_coef_rfsh_flag = 0; + vp9_hw_regs->vp9d_param.reg103.refresh_en = + !pic_param->error_resilient_mode && !pic_param->parallelmode; + vp9_hw_regs->vp9d_param.reg103.prob_save_en = pic_param->refresh_frame_context; + vp9_hw_regs->vp9d_param.reg103.allow_high_precision_mv = pic_param->allow_high_precision_mv; + vp9_hw_regs->vp9d_param.reg103.last_key_frame_flag = hw_ctx->ls_info.last_intra_only; + + /* set info for multi core */ + { + MppFrame mframe = NULL; + + vp9_hw_regs->common.reg028.sw_poc_arb_flag = 1; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg65.cur_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + // last poc + ref_idx = pic_param->frame_refs[0].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + if (ref_frame_idx < 0x7f) { + mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg95.last_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + } + // golden poc + ref_idx = pic_param->frame_refs[1].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + if (ref_frame_idx < 0x7f) { + mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg96.golden_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + } + // altref poc + ref_idx = pic_param->frame_refs[2].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + if (ref_frame_idx < 0x7f) { + mframe = NULL; + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &mframe); + vp9_hw_regs->vp9d_param.reg97.altref_poc = mframe ? mpp_frame_get_poc(mframe) : 0; + } + // colref poc + vp9_hw_regs->vp9d_param.reg98.col_ref_poc = + (hw_ctx->col_ref_poc != 0) ? hw_ctx->col_ref_poc : vp9_hw_regs->vp9d_param.reg65.cur_poc; + if (pic_param->show_frame && !pic_param->show_existing_frame) + hw_ctx->col_ref_poc = vp9_hw_regs->vp9d_param.reg65.cur_poc; + // segment id ref poc + vp9_hw_regs->vp9d_param.reg100.segid_ref_poc = hw_ctx->segid_ref_poc; + + vp9_hw_regs->vp9d_addr.reg169_segidcur_base = mpp_buffer_get_fd(hw_ctx->seg_base); + vp9_hw_regs->vp9d_addr.reg168_segidlast_base = mpp_buffer_get_fd(hw_ctx->seg_base); + if (hw_ctx->last_segid_flag) { + mpp_dev_set_reg_offset(cfg->dev, 168, hw_ctx->offset_segid_last); + mpp_dev_set_reg_offset(cfg->dev, 169, hw_ctx->offset_segid_cur); + } else { + mpp_dev_set_reg_offset(cfg->dev, 168, hw_ctx->offset_segid_cur); + mpp_dev_set_reg_offset(cfg->dev, 169, hw_ctx->offset_segid_last); + } + + if ((pic_param->stVP9Segments.enabled && pic_param->stVP9Segments.update_map) || + (hw_ctx->ls_info.last_width != pic_param->width) || + (hw_ctx->ls_info.last_height != pic_param->height) || + intraFlag || pic_param->error_resilient_mode) { + hw_ctx->segid_ref_poc = vp9_hw_regs->vp9d_param.reg65.cur_poc; + hw_ctx->last_segid_flag = !hw_ctx->last_segid_flag; + vp9_hw_regs->vp9d_param.reg100.segid_ref_poc = 0; + vp9_hw_regs->vp9d_param.reg75.vp9_segment_id_update = 1; + } else + vp9_hw_regs->vp9d_param.reg75.vp9_segment_id_update = 0; + } + + /* config last prob base and update write base */ + { + + if (intraFlag || pic_param->error_resilient_mode) { + if (intraFlag + || pic_param->error_resilient_mode + || (pic_param->reset_frame_context == 3)) { + memset(hw_ctx->prob_ctx_valid, 0, sizeof(hw_ctx->prob_ctx_valid)); + } else if (pic_param->reset_frame_context == 2) { + hw_ctx->prob_ctx_valid[frame_ctx_id] = 0; + } + } + +#if VP9_DUMP + { + static RK_U32 file_cnt = 0; + char file_name[128]; + RK_U32 i = 0; + sprintf(file_name, "/data/vp9/prob_last_%d.txt", file_cnt); + FILE *fp = fopen(file_name, "wb"); + RK_U32 *tmp = NULL; + if (hw_ctx->prob_ctx_valid[frame_ctx_id]) { + tmp = (RK_U32 *)mpp_buffer_get_ptr(hw_ctx->prob_loop_base[pic_param->frame_context_idx]); + } else { + tmp = (RK_U32 *)mpp_buffer_get_ptr(hw_ctx->prob_default_base); + } + for (i = 0; i < PROB_SIZE / 4; i += 2) { + fprintf(fp, "%08x%08x\n", tmp[i + 1], tmp[i]); + } + file_cnt++; + fflush(fp); + fclose(fp); + } +#endif + + if (hw_ctx->prob_ctx_valid[frame_ctx_id]) { + vp9_hw_regs->vp9d_addr.reg162_last_prob_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); + vp9_hw_regs->common.reg028.swreg_vp9_rd_prob_idx = frame_ctx_id + 1; + vp9_hw_regs->vp9d_param.reg99.prob_ref_poc = hw_ctx->prob_ref_poc[frame_ctx_id]; + } else { + vp9_hw_regs->vp9d_addr.reg162_last_prob_base = mpp_buffer_get_fd(hw_ctx->prob_default_base); + hw_ctx->prob_ctx_valid[frame_ctx_id] |= pic_param->refresh_frame_context; + vp9_hw_regs->common.reg028.swreg_vp9_rd_prob_idx = 0; + vp9_hw_regs->vp9d_param.reg99.prob_ref_poc = 0; + if (pic_param->refresh_frame_context) + hw_ctx->prob_ref_poc[frame_ctx_id] = vp9_hw_regs->vp9d_param.reg65.cur_poc; + } + vp9_hw_regs->vp9d_addr.reg172_update_prob_wr_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); + vp9_hw_regs->common.reg028.swreg_vp9_wr_prob_idx = frame_ctx_id + 1; + + } + vp9_hw_regs->vp9d_addr.reg160_delta_prob_base = mpp_buffer_get_fd(hw_ctx->probe_base); +#else + hal_vp9d_output_probe(mpp_buffer_get_ptr(hw_ctx->probe_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->probe_base); +#endif + vp9_hw_regs->common.reg012.colmv_compress_en = cfg->hw_info ? cfg->hw_info->cap_colmv_compress : 1; + vp9_hw_regs->common.reg013.cur_pic_is_idr = !pic_param->frame_type; + vp9_hw_regs->common.reg009.dec_mode = 2; //set as vp9 dec + vp9_hw_regs->common.reg016_str_len = ((stream_len + 15) & (~15)) + 0x80; + + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + bitstream = mpp_buffer_get_ptr(streambuf); + aglin_offset = vp9_hw_regs->common.reg016_str_len - stream_len; + if (aglin_offset > 0) { + memset((void *)(bitstream + stream_len), 0, aglin_offset); + } + + //--- caculate the yuv_frame_size and mv_size + bit_depth = pic_param->BitDepthMinus8Luma + 8; + + { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + fbc_en = MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe)); + + if (fbc_en) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 h = MPP_ALIGN(mpp_frame_get_height(mframe), 64); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (h + 16) / 16, SZ_4K); + + vp9_hw_regs->common.reg012.fbc_e = 1; + vp9_hw_regs->common.reg018.y_hor_virstride = fbc_hdr_stride >> 4; + vp9_hw_regs->common.reg019.uv_hor_virstride = fbc_hdr_stride >> 4; + vp9_hw_regs->common.reg020_fbc_payload_off.payload_st_offset = fbd_offset >> 4; + } else { + sw_y_hor_virstride = mpp_frame_get_hor_stride(mframe) >> 4; + sw_uv_hor_virstride = sw_y_hor_virstride; + sw_y_virstride = mpp_frame_get_ver_stride(mframe) * sw_y_hor_virstride; + + vp9_hw_regs->common.reg012.fbc_e = 0; + vp9_hw_regs->common.reg018.y_hor_virstride = sw_y_hor_virstride; + vp9_hw_regs->common.reg019.uv_hor_virstride = sw_uv_hor_virstride; + vp9_hw_regs->common.reg020_y_virstride.y_virstride = sw_y_virstride; + } + } + if (!pic_param->intra_only && pic_param->frame_type && + !pic_param->error_resilient_mode && hw_ctx->ls_info.last_show_frame) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_BUFFER, &framebuf); + vp9_hw_regs->common_addr.reg130_decout_base = mpp_buffer_get_fd(framebuf); + vp9_hw_regs->common_addr.reg128_rlc_base = mpp_buffer_get_fd(streambuf); + vp9_hw_regs->common_addr.reg129_rlcwrite_base = mpp_buffer_get_fd(streambuf); + + vp9_hw_regs->vp9d_addr.reg167_count_prob_base = mpp_buffer_get_fd(hw_ctx->probe_base); + mpp_dev_set_reg_offset(cfg->dev, 167, hw_ctx->offset_count); + + //set cur colmv base + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, task->dec.output); + vp9_hw_regs->common_addr.reg131_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + hw_ctx->mv_base_addr = vp9_hw_regs->common_addr.reg131_colmv_cur_base; + if (hw_ctx->pre_mv_base_addr < 0) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + } + vp9_hw_regs->vp9d_addr.reg170_ref_colmv_base = hw_ctx->pre_mv_base_addr; + + vp9_hw_regs->vp9d_param.reg64.cprheader_offset = 0; + reg_ref_base = (RK_U32*)&vp9_hw_regs->vp9d_addr.reg164_ref_last_base; + for (i = 0; i < 3; i++) { + MppFrame frame = NULL; + + ref_idx = pic_param->frame_refs[i].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + ref_frame_width_y = pic_param->ref_frame_coded_width[ref_idx]; + ref_frame_height_y = pic_param->ref_frame_coded_height[ref_idx]; + + if (ref_frame_idx < 0x7f) + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &frame); + + if (fbc_en && frame) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(frame); + RK_U32 h = MPP_ALIGN(mpp_frame_get_height(frame), 64); + RK_U32 fbd_offset = MPP_ALIGN(fbc_hdr_stride * (h + 16) / 16, SZ_4K); + + y_hor_virstride = uv_hor_virstride = fbc_hdr_stride >> 4; + y_virstride = fbd_offset; + } else { + if (frame) { + y_hor_virstride = uv_hor_virstride = mpp_frame_get_hor_stride(frame) >> 4; + y_virstride = y_hor_virstride * mpp_frame_get_ver_stride(frame); + } else { + y_hor_virstride = uv_hor_virstride = (mpp_align_256_odd((ref_frame_width_y * bit_depth) >> 3) >> 4); + y_virstride = y_hor_virstride * mpp_align_64(ref_frame_height_y); + } + } + + if (pic_param->ref_frame_map[ref_idx].Index7Bits < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->ref_frame_map[ref_idx].Index7Bits, SLOT_BUFFER, &framebuf); + } + + if (pic_param->ref_frame_map[ref_idx].Index7Bits < 0x7f) { + switch (i) { + case 0: { + vp9_hw_regs->vp9d_param.reg106.framewidth_last = ref_frame_width_y; + vp9_hw_regs->vp9d_param.reg107.frameheight_last = ref_frame_height_y; + vp9_hw_regs->vp9d_param.reg79.lastfy_hor_virstride = y_hor_virstride; + vp9_hw_regs->vp9d_param.reg80.lastfuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->vp9d_param.reg85.lastfy_virstride = y_virstride; + } break; + case 1: { + vp9_hw_regs->vp9d_param.reg108.framewidth_golden = ref_frame_width_y; + vp9_hw_regs->vp9d_param.reg109.frameheight_golden = ref_frame_height_y; + vp9_hw_regs->vp9d_param.reg81.goldenfy_hor_virstride = y_hor_virstride; + vp9_hw_regs->vp9d_param.reg82.goldenfuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->vp9d_param.reg86.goldeny_virstride = y_virstride; + } break; + case 2: { + vp9_hw_regs->vp9d_param.reg110.framewidth_alfter = ref_frame_width_y; + vp9_hw_regs->vp9d_param.reg111.frameheight_alfter = ref_frame_height_y; + vp9_hw_regs->vp9d_param.reg83.altreffy_hor_virstride = y_hor_virstride; + vp9_hw_regs->vp9d_param.reg84.altreffuv_hor_virstride = uv_hor_virstride; + vp9_hw_regs->vp9d_param.reg87.altrefy_virstride = y_virstride; + } break; + default: + break; + } + + /*0 map to 11*/ + /*1 map to 12*/ + /*2 map to 13*/ + if (framebuf != NULL) { + reg_ref_base[i] = mpp_buffer_get_fd(framebuf); + } else { + mpp_log("ref buff address is no valid used out as base slot index 0x%x", pic_param->ref_frame_map[ref_idx].Index7Bits); + reg_ref_base[i] = vp9_hw_regs->common_addr.reg130_decout_base; + } + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, pic_param->ref_frame_map[ref_idx].Index7Bits); + vp9_hw_regs->vp9d_addr.reg181_196_ref_colmv_base[i] = mpp_buffer_get_fd(mv_buf->buf[0]); + } else { + reg_ref_base[i] = vp9_hw_regs->common_addr.reg130_decout_base; + vp9_hw_regs->vp9d_addr.reg181_196_ref_colmv_base[i] = vp9_hw_regs->common_addr.reg131_colmv_cur_base; + } + } + + for (i = 0; i < 8; i++) { + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_qp_delta_en = (hw_ctx->ls_info.feature_mask[i]) & 0x1; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_qp_delta = hw_ctx->ls_info.feature_data[i][0]; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_loopfitler_value_en = (hw_ctx->ls_info.feature_mask[i] >> 1) & 0x1; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_loopfilter_value = hw_ctx->ls_info.feature_data[i][1]; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_referinfo_en = (hw_ctx->ls_info.feature_mask[i] >> 2) & 0x1; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_referinfo = hw_ctx->ls_info.feature_data[i][2]; + vp9_hw_regs->vp9d_param.reg67_74[i].segid_frame_skip_en = (hw_ctx->ls_info.feature_mask[i] >> 3) & 0x1; + } + + vp9_hw_regs->vp9d_param.reg67_74[0].segid_abs_delta = hw_ctx->ls_info.abs_delta_last; + vp9_hw_regs->vp9d_param.reg76.tx_mode = pic_param->txmode; + vp9_hw_regs->vp9d_param.reg76.frame_reference_mode = pic_param->refmode; + vp9_hw_regs->vp9d_param.reg94.ref_deltas_lastframe = 0; + + if (!intraFlag) { + for (i = 0; i < 4; i++) + vp9_hw_regs->vp9d_param.reg94.ref_deltas_lastframe |= (hw_ctx->ls_info.last_ref_deltas[i] & 0x7f) << (7 * i); + + for (i = 0; i < 2; i++) + vp9_hw_regs->vp9d_param.reg75.mode_deltas_lastframe |= (hw_ctx->ls_info.last_mode_deltas[i] & 0x7f) << (7 * i); + } else { + hw_ctx->ls_info.segmentation_enable_flag_last = 0; + hw_ctx->ls_info.last_intra_only = 1; + } + + vp9_hw_regs->vp9d_param.reg75.segmentation_enable_lstframe = hw_ctx->ls_info.segmentation_enable_flag_last; + vp9_hw_regs->vp9d_param.reg75.last_show_frame = hw_ctx->ls_info.last_show_frame; + vp9_hw_regs->vp9d_param.reg75.last_intra_only = hw_ctx->ls_info.last_intra_only; + vp9_hw_regs->vp9d_param.reg75.last_widthheight_eqcur = (pic_param->width == hw_ctx->ls_info.last_width) && (pic_param->height == hw_ctx->ls_info.last_height); + vp9_hw_regs->vp9d_param.reg78.lasttile_size = stream_len - pic_param->first_partition_size; + + + if (!intraFlag) { + vp9_hw_regs->vp9d_param.reg88.lref_hor_scale = pic_param->mvscale[0][0]; + vp9_hw_regs->vp9d_param.reg89.lref_ver_scale = pic_param->mvscale[0][1]; + vp9_hw_regs->vp9d_param.reg90.gref_hor_scale = pic_param->mvscale[1][0]; + vp9_hw_regs->vp9d_param.reg91.gref_ver_scale = pic_param->mvscale[1][1]; + vp9_hw_regs->vp9d_param.reg92.aref_hor_scale = pic_param->mvscale[2][0]; + vp9_hw_regs->vp9d_param.reg93.aref_ver_scale = pic_param->mvscale[2][1]; + } + + vp9_hw_regs->common.reg010.dec_e = 1; + vp9_hw_regs->common.reg011.buf_empty_en = 1; + vp9_hw_regs->common.reg011.dec_clkgate_e = 1; + vp9_hw_regs->common.reg011.err_head_fill_e = 1; + vp9_hw_regs->common.reg011.err_colmv_fill_e = 1; + + vp9_hw_regs->common.reg026.inter_auto_gating_e = 1; + vp9_hw_regs->common.reg026.filterd_auto_gating_e = 1; + vp9_hw_regs->common.reg026.strmd_auto_gating_e = 1; + vp9_hw_regs->common.reg026.mcp_auto_gating_e = 1; + vp9_hw_regs->common.reg026.busifd_auto_gating_e = 1; + vp9_hw_regs->common.reg026.dec_ctrl_auto_gating_e = 1; + vp9_hw_regs->common.reg026.intra_auto_gating_e = 1; + vp9_hw_regs->common.reg026.mc_auto_gating_e = 1; + vp9_hw_regs->common.reg026.transd_auto_gating_e = 1; + vp9_hw_regs->common.reg026.sram_auto_gating_e = 1; + vp9_hw_regs->common.reg026.cru_auto_gating_e = 1; + vp9_hw_regs->common.reg026.reg_cfg_gating_en = 1; + + vp9_hw_regs->common.reg032_timeout_threshold = 0x3ffff; + + //last info update + hw_ctx->ls_info.abs_delta_last = pic_param->stVP9Segments.abs_delta; + for (i = 0 ; i < 4; i ++) { + hw_ctx->ls_info.last_ref_deltas[i] = pic_param->ref_deltas[i]; + } + + for (i = 0 ; i < 2; i ++) { + hw_ctx->ls_info.last_mode_deltas[i] = pic_param->mode_deltas[i]; + } + + for (i = 0; i < 8; i++) { + hw_ctx->ls_info.feature_data[i][0] = pic_param->stVP9Segments.feature_data[i][0]; + hw_ctx->ls_info.feature_data[i][1] = pic_param->stVP9Segments.feature_data[i][1]; + hw_ctx->ls_info.feature_data[i][2] = pic_param->stVP9Segments.feature_data[i][2]; + hw_ctx->ls_info.feature_data[i][3] = pic_param->stVP9Segments.feature_data[i][3]; + hw_ctx->ls_info.feature_mask[i] = pic_param->stVP9Segments.feature_mask[i]; + } + if (!hw_ctx->ls_info.segmentation_enable_flag_last) + hw_ctx->ls_info.segmentation_enable_flag_last = pic_param->stVP9Segments.enabled; + + hw_ctx->ls_info.last_show_frame = pic_param->show_frame; + hw_ctx->ls_info.last_width = pic_param->width; + hw_ctx->ls_info.last_height = pic_param->height; + hw_ctx->ls_info.last_intra_only = (!pic_param->frame_type || pic_param->intra_only); + hal_vp9d_dbg_par("stVP9Segments.enabled %d show_frame %d width %d height %d last_intra_only %d", + pic_param->stVP9Segments.enabled, pic_param->show_frame, + pic_param->width, pic_param->height, + hw_ctx->ls_info.last_intra_only); + + hal_vp9d_rcb_info_update(hal, vp9_hw_regs, pic_param); + { + MppBuffer rcb_buf = NULL; + + rcb_buf = (p_hal->fast_mode != 0) ? hw_ctx->g_buf[task->dec.reg_index].rcb_buf : hw_ctx->rcb_buf; + vdpu382_setup_rcb(&vp9_hw_regs->common_addr, cfg->dev, rcb_buf, hw_ctx->rcb_info); + } + + { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe)) { + vp9_hw_regs->vp9d_addr.reg198_scale_down_luma_base = + vp9_hw_regs->common_addr.reg130_decout_base; + vp9_hw_regs->vp9d_addr.reg199_scale_down_chorme_base = + vp9_hw_regs->common_addr.reg130_decout_base; + vdpu382_setup_down_scale(mframe, cfg->dev, &vp9_hw_regs->common); + } else { + vp9_hw_regs->vp9d_addr.reg198_scale_down_luma_base = 0; + vp9_hw_regs->vp9d_addr.reg199_scale_down_chorme_base = 0; + vp9_hw_regs->common.reg012.scale_down_en = 0; + } + } + vdpu382_setup_statistic(&vp9_hw_regs->common, &vp9_hw_regs->statistic); + + // whether need update counts + if (pic_param->refresh_frame_context && !pic_param->parallelmode) { + task->dec.flags.wait_done = 1; + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu382_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + Vdpu382Vp9dRegSet *hw_regs = (Vdpu382Vp9dRegSet *)hw_ctx->hw_regs; + MppDev dev = p_hal->cfg->dev; + + if (p_hal->fast_mode) { + RK_S32 index = task->dec.reg_index; + hw_regs = (Vdpu382Vp9dRegSet *)hw_ctx->g_buf[index].hw_regs; + } + + mpp_assert(hw_regs); + + +#if VP9_DUMP + { + static RK_U32 file_cnt = 0; + char file_name[128]; + sprintf(file_name, "/data/vp9_regs/reg_%d.txt", file_cnt); + FILE *fp = fopen(file_name, "wb"); + RK_U32 i = 0; + RK_U32 *tmp = NULL; + tmp = (RK_U32 *)&hw_regs->common; + for (i = 0; i < sizeof(hw_regs->common) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 8, tmp[i]); + } + fprintf(fp, "\n"); + tmp = (RK_U32 *)&hw_regs->vp9d_param; + for (i = 0; i < sizeof(hw_regs->vp9d_param) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 64, tmp[i]); + } + fprintf(fp, "\n"); + tmp = (RK_U32 *)&hw_regs->common_addr; + for (i = 0; i < sizeof(hw_regs->common_addr) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 128, tmp[i]); + } + fprintf(fp, "\n"); + tmp = (RK_U32 *)&hw_regs->vp9d_addr; + for (i = 0; i < sizeof(hw_regs->vp9d_addr) / 4; i++) { + fprintf(fp, "reg[%d] 0x%08x\n", i + 160, tmp[i]); + } + file_cnt++; + fflush(fp); + fclose(fp); + } +#endif + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = &hw_regs->common; + wr_cfg.size = sizeof(hw_regs->common); + wr_cfg.offset = VDPU382_OFF_COMMON_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->vp9d_param; + wr_cfg.size = sizeof(hw_regs->vp9d_param); + wr_cfg.offset = VDPU382_OFF_CODEC_PARAMS_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->common_addr; + wr_cfg.size = sizeof(hw_regs->common_addr); + wr_cfg.offset = VDPU382_OFF_COMMON_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->vp9d_addr; + wr_cfg.size = sizeof(hw_regs->vp9d_addr); + wr_cfg.offset = VDPU382_OFF_CODEC_ADDR_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->statistic; + wr_cfg.size = sizeof(hw_regs->statistic); + wr_cfg.offset = VDPU382_OFF_STATISTIC_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->irq_status; + rd_cfg.size = sizeof(hw_regs->irq_status); + rd_cfg.offset = VDPU382_OFF_INTERRUPT_REGS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + /* rcb info for sram */ + vdpu382_set_rcbinfo(dev, hw_ctx->rcb_info); + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +static MPP_RET hal_vp9d_vdpu382_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + Vdpu382Vp9dRegSet *hw_regs = (Vdpu382Vp9dRegSet *)hw_ctx->hw_regs; + + if (p_hal->fast_mode) + hw_regs = (Vdpu382Vp9dRegSet *)hw_ctx->g_buf[task->dec.reg_index].hw_regs; + + mpp_assert(hw_regs); + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (hal_vp9d_debug & HAL_VP9D_DBG_REG) { + RK_U32 *p = (RK_U32 *)hw_regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(Vdpu382Vp9dRegSet) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i, *p++); + } + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + !hw_regs->irq_status.reg224.dec_rdy_sta) { + MppFrame mframe = NULL; + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_frame_set_errinfo(mframe, 1); + } +#if !HW_PROB + if (p_hal->dec_cb && task->dec.flags.wait_done) { + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + + mpp_buffer_sync_end(hw_ctx->count_base); + hal_vp9d_update_counts(mpp_buffer_get_ptr(hw_ctx->count_base), task->dec.syntax.data); + mpp_callback(p_hal->dec_cb, &pic_param->counts); + } +#endif + if (p_hal->fast_mode) { + hw_ctx->g_buf[task->dec.reg_index].use_flag = 0; + } + + (void)task; + return ret; +} + +static MPP_RET hal_vp9d_vdpu382_reset(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + + hal_vp9d_enter(); + + memset(&hw_ctx->ls_info, 0, sizeof(hw_ctx->ls_info)); + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + hw_ctx->last_segid_flag = 1; + memset(&hw_ctx->prob_ref_poc, 0, sizeof(hw_ctx->prob_ref_poc)); + hw_ctx->col_ref_poc = 0; + hw_ctx->segid_ref_poc = 0; + + hal_vp9d_leave(); + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu382_flush(void *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu382Vp9dCtx *hw_ctx = (Vdpu382Vp9dCtx*)p_hal->hw_ctx; + + hal_vp9d_enter(); + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + + hal_vp9d_leave(); + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu382_control(void *hal, MpiCmd cmd_type, void *param) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO : { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + vdpu_afbc_align_calc(p_hal->cfg->frame_slots, (MppFrame)param, 0); + } else { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_256_odd); + } + } break; + default : { + } break; + } + + return MPP_OK; +} + +const MppHalApi hal_vp9d_vdpu382 = { + .name = "vp9d_vdpu382", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingVP9, + .ctx_size = sizeof(HalVp9dCtx), + .flag = 0, + .init = hal_vp9d_vdpu382_init, + .deinit = hal_vp9d_vdpu382_deinit, + .reg_gen = hal_vp9d_vdpu382_gen_regs, + .start = hal_vp9d_vdpu382_start, + .wait = hal_vp9d_vdpu382_wait, + .reset = hal_vp9d_vdpu382_reset, + .flush = hal_vp9d_vdpu382_flush, + .control = hal_vp9d_vdpu382_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3562, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_vp9d_vdpu382) diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu382.h b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu382.h new file mode 100644 index 000000000..f9a5f5a67 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu382.h @@ -0,0 +1,31 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP9D_VDPU382_H +#define HAL_VP9D_VDPU382_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_vp9d_vdpu382; + +#ifdef __cplusplus +} +#endif +#endif /* HAL_VP9D_VDPU382_H */ diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu383.c b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu383.c new file mode 100644 index 000000000..ac88d031b --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu383.c @@ -0,0 +1,860 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_vp9d_vdpu383" + +#include + +#include "mpp_debug.h" +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_buffer_impl.h" +#include "mpp_bitput.h" +#include "mpp_compat_impl.h" + +#include "hal_vp9d_debug.h" +#include "hal_vp9d_com.h" +#include "hal_vp9d_vdpu383.h" +#include "hal_vp9d_ctx.h" +#include "vdpu38x_com.h" +#include "vdpu383_com.h" +#include "vp9d_syntax.h" +#include "vdpu_com.h" +#include "vdpu38x_com.h" + +#define HW_PROB 1 +#define GBL_SIZE 2 * (MPP_ALIGN(1299, 128) / 8) + +#ifdef DUMP_VDPU383_DATAS +static RK_U32 cur_last_segid_flag; +static MppBuffer cur_last_prob_base; +#endif + +static MPP_RET hal_vp9d_alloc_res(HalVp9dCtx *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + MppHalCfg *cfg = p_hal->cfg; + MppBufferGroup group = cfg->buf_group; + RK_S32 ret = 0; + RK_S32 i = 0; + + /* alloc common buffer */ + for (i = 0; i < VP9_CONTEXT; i++) { + ret = mpp_buffer_get(group, &hw_ctx->prob_loop_base[i], PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_loop_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->prob_loop_base[i], cfg->dev); + } + ret = mpp_buffer_get(group, &hw_ctx->prob_default_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_default_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->prob_default_base, cfg->dev); + + ret = mpp_buffer_get(group, &hw_ctx->segid_cur_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_cur_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->segid_cur_base, cfg->dev); + ret = mpp_buffer_get(group, &hw_ctx->segid_last_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_last_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->segid_last_base, cfg->dev); + + /* alloc buffer for fast mode or normal */ + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + hw_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu383RegSet)); + ret = mpp_buffer_get(group, + &hw_ctx->g_buf[i].global_base, GBL_SIZE); + mpp_buffer_attach_dev(hw_ctx->g_buf[i].global_base, cfg->dev); + if (ret) { + mpp_err("vp9 global_base get buffer failed\n"); + return ret; + } + ret = mpp_buffer_get(group, + &hw_ctx->g_buf[i].probe_base, PROB_KF_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->g_buf[i].probe_base, cfg->dev); + ret = mpp_buffer_get(group, + &hw_ctx->g_buf[i].count_base, COUNT_SIZE); + if (ret) { + mpp_err("vp9 count_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->g_buf[i].count_base, cfg->dev); + } + } else { + hw_ctx->hw_regs = mpp_calloc_size(void, sizeof(Vdpu383RegSet)); + ret = mpp_buffer_get(group, &hw_ctx->global_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 global_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->global_base, cfg->dev); + + ret = mpp_buffer_get(group, &hw_ctx->probe_base, PROB_KF_SIZE); + if (ret) { + mpp_err("vp9 probe_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->probe_base, cfg->dev); + + ret = mpp_buffer_get(group, &hw_ctx->count_base, COUNT_SIZE); + if (ret) { + mpp_err("vp9 count_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->count_base, cfg->dev); + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu383_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + + mpp_env_get_u32("hal_vp9d_debug", &hal_vp9d_debug, 0); + + cfg->support_fast_mode = 1; + p_hal->cfg = cfg; + p_hal->client_type = VPU_CLIENT_RKVDEC; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->hw_ctx = mpp_calloc_size(void, sizeof(Vdpu38xVp9dCtx) + GBL_SIZE)); + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_64); + + ret = hal_vp9d_alloc_res(p_hal); + if (ret) { + mpp_err("hal_vp9d_alloc_res failed\n"); + goto __FAILED; + } + + hw_ctx->last_segid_flag = 1; + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)&hw_ctx->rcb_ctx); + + return ret; +__FAILED: + hal_vp9d_vdpu38x_deinit(hal); + return ret; +} + +static MPP_RET vdpu383_vp9d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + RK_U32 fltd_row_append = ctx->pic_w > 4096 ? 256 * 16 * 8 : 864 * 16 * 8; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + if (ctx->pic_w > 4096) + cur_bit_size = MPP_DIVUP(64, on_tl_row) * 250; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, in_tl_row) * 2368; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, on_tl_row) * 2368; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.6 * bit_depth + 0.5) + * (17.5 + 8 * cur_uv_para); + cur_bit_size = cur_bit_size / 2 + fltd_row_append; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + // save space mode : half for RCB_FLTD_IN_ROW, half for RCB_FLTD_PROT_IN_ROW + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.6 * bit_depth + 0.5) + * (17.5 + 8 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_col_uv_coef_map[rcb_fmt]; + if (ctx->tile_dir == 0) + cur_bit_size = MPP_ROUNDUP(64, on_tl_col) * (1.6 * bit_depth + 0.5) + * (17.75 + 8 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu383_gen_regs(void *hal, HalTaskInfo *task) +{ + RK_S32 i; + RK_U8 bit_depth = 0; + RK_U32 ref_frame_width_y; + RK_U32 ref_frame_height_y; + RK_S32 stream_len = 0, aglin_offset = 0; + RK_U32 y_hor_virstride, uv_hor_virstride, y_virstride; + RK_U8 *bitstream = NULL; + MppBuffer streambuf = NULL; + RK_U32 sw_y_hor_virstride; + RK_U32 sw_uv_hor_virstride; + RK_U32 sw_y_virstride; + RK_U32 sw_uv_virstride; + RK_U8 ref_idx = 0; + RK_U8 ref_frame_idx = 0; + RK_U32 *reg_ref_base = NULL; + RK_U32 *reg_payload_ref_base = NULL; + RK_S32 intraFlag = 0; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + RK_U32 fbc_en = 0; + HalBuf *origin_buf = NULL; + + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + MppHalCfg *cfg = p_hal->cfg; + Vdpu383RegSet *regs = NULL; + RK_S32 mv_size = pic_param->width * pic_param->height / 2; + RK_U32 frame_ctx_id = pic_param->frame_context_idx; + MppFrame mframe; + MppFrame ref_frame = NULL; + + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!hw_ctx->g_buf[i].use_flag) { + task->dec.reg_index = i; + hw_ctx->global_base = hw_ctx->g_buf[i].global_base; + hw_ctx->probe_base = hw_ctx->g_buf[i].probe_base; + hw_ctx->count_base = hw_ctx->g_buf[i].count_base; + hw_ctx->hw_regs = hw_ctx->g_buf[i].hw_regs; + hw_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("vp9 fast mode buf all used\n"); + return MPP_ERR_NOMEM; + } + } + regs = (Vdpu383RegSet*)hw_ctx->hw_regs; + memset(regs, 0, sizeof(Vdpu383RegSet)); + +#ifdef DUMP_VDPU383_DATAS + { + memset(dump_cur_dir, 0, sizeof(dump_cur_dir)); + sprintf(dump_cur_dir, "vp9/Frame%04d", dump_cur_frame); + if (access(dump_cur_dir, 0)) { + if (mkdir(dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", dump_cur_dir); + } + dump_cur_frame++; + } +#endif + + /* uncompress header data */ + vdpu38x_vp9d_uncomp_hdr(p_hal, pic_param, (RK_U64 *)hw_ctx->header_data, GBL_SIZE / 8); + memcpy(mpp_buffer_get_ptr(hw_ctx->global_base), hw_ctx->header_data, GBL_SIZE); + mpp_buffer_sync_end(hw_ctx->global_base); + regs->comm_paras.reg67_global_len = GBL_SIZE / 16; + regs->comm_addrs.reg131_gbl_base = mpp_buffer_get_fd(hw_ctx->global_base); + + if (hw_ctx->cmv_bufs == NULL || hw_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (hw_ctx->cmv_bufs) { + hal_bufs_deinit(hw_ctx->cmv_bufs); + hw_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(&hw_ctx->cmv_bufs); + if (hw_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_NOK; + } + hw_ctx->mv_size = mv_size; + hw_ctx->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(hw_ctx->cmv_bufs, hw_ctx->mv_count, 1, &size); + } + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + hw_ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, &hw_ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + stream_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + + intraFlag = (!pic_param->frame_type || pic_param->intra_only); +#if HW_PROB + // hal_vp9d_prob_flag_delta(mpp_buffer_get_ptr(hw_ctx->probe_base), task->dec.syntax.data); + /* init kf_probe */ + hal_vp9d_prob_kf(mpp_buffer_get_ptr(hw_ctx->probe_base)); + mpp_buffer_sync_end(hw_ctx->probe_base); + if (intraFlag) { + hal_vp9d_prob_default(mpp_buffer_get_ptr(hw_ctx->prob_default_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->prob_default_base); + } + + /* config last prob base and update write base */ + { + if (intraFlag || pic_param->error_resilient_mode) { + if (intraFlag + || pic_param->error_resilient_mode + || (pic_param->reset_frame_context == 3)) { + memset(hw_ctx->prob_ctx_valid, 0, sizeof(hw_ctx->prob_ctx_valid)); + } else if (pic_param->reset_frame_context == 2) { + hw_ctx->prob_ctx_valid[frame_ctx_id] = 0; + } + } + + if (hw_ctx->prob_ctx_valid[frame_ctx_id]) { + regs->comm_addrs.reg184_lastprob_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); +#ifdef DUMP_VDPU383_DATAS + { cur_last_prob_base = hw_ctx->prob_loop_base[frame_ctx_id]; } +#endif + } else { + regs->comm_addrs.reg184_lastprob_base = mpp_buffer_get_fd(hw_ctx->prob_default_base); + hw_ctx->prob_ctx_valid[frame_ctx_id] |= pic_param->refresh_frame_context; +#ifdef DUMP_VDPU383_DATAS + { cur_last_prob_base = hw_ctx->prob_default_base; } +#endif + } + regs->comm_addrs.reg185_updateprob_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); + } + regs->comm_addrs.reg183_kfprob_base = mpp_buffer_get_fd(hw_ctx->probe_base); +#ifdef DUMP_VDPU383_DATAS + { + char *cur_fname = "cabac_last_probe.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(cur_last_prob_base), + 8 * 152 * 16, 128, 0); + } + { + char *cur_fname = "cabac_kf_probe.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(hw_ctx->probe_base), + 8 * PROB_KF_SIZE, 128, 0); + } +#endif +#else +#endif + + regs->comm_paras.reg66_stream_len = ((stream_len + 15) & (~15)) + 0x80; + + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + bitstream = mpp_buffer_get_ptr(streambuf); + aglin_offset = regs->comm_paras.reg66_stream_len - stream_len; + if (aglin_offset > 0) { + memset((void *)(bitstream + stream_len), 0, aglin_offset); + } + + //--- caculate the yuv_frame_size and mv_size + bit_depth = pic_param->BitDepthMinus8Luma + 8; + + { + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + fbc_en = MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe)); + + if (fbc_en) { + RK_U32 fbc_hdr_stride = mpp_frame_get_fbc_hdr_stride(mframe); + RK_U32 h = MPP_ALIGN(mpp_frame_get_height(mframe), 64); + RK_U32 fbd_offset; + + regs->ctrl_regs.reg9.fbc_e = 1; + regs->comm_paras.reg68_hor_virstride = fbc_hdr_stride / 64; + fbd_offset = regs->comm_paras.reg68_hor_virstride * h * 4; + regs->comm_addrs.reg193_fbc_payload_offset = fbd_offset; + /* error stride */ + regs->comm_paras.reg80_error_ref_hor_virstride = fbc_hdr_stride / 64; + } else { + sw_y_hor_virstride = mpp_frame_get_hor_stride(mframe) >> 4; + sw_uv_hor_virstride = sw_y_hor_virstride; + sw_y_virstride = mpp_frame_get_ver_stride(mframe) * sw_y_hor_virstride; + sw_uv_virstride = sw_y_virstride / 2; + + regs->ctrl_regs.reg9.fbc_e = 0; + if (MPP_FRAME_FMT_IS_TILE(mpp_frame_get_fmt(mframe))) { + regs->ctrl_regs.reg9.tile_e = 1; + regs->comm_paras.reg68_hor_virstride = sw_y_hor_virstride * 6; + regs->comm_paras.reg70_y_virstride = sw_y_virstride + sw_uv_virstride; + } else { + regs->ctrl_regs.reg9.tile_e = 0; + regs->comm_paras.reg68_hor_virstride = sw_y_hor_virstride; + regs->comm_paras.reg69_raster_uv_hor_virstride = sw_uv_hor_virstride; + regs->comm_paras.reg70_y_virstride = sw_y_virstride; + } + /* error stride */ + regs->comm_paras.reg80_error_ref_hor_virstride = sw_y_hor_virstride; + regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = sw_uv_hor_virstride; + regs->comm_paras.reg82_error_ref_virstride = sw_y_virstride; + } + } + if (!pic_param->intra_only && pic_param->frame_type && + !pic_param->error_resilient_mode && hw_ctx->ls_info.last_show_frame) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_BUFFER, &framebuf); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(hw_ctx->origin_bufs, task->dec.output); + framebuf = origin_buf->buf[0]; + } + regs->comm_addrs.reg168_decout_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg192_payload_st_cur_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg194_payload_st_error_ref_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(streambuf); + + { + RK_U32 strm_offset = pic_param->uncompressed_header_size_byte_aligned; + + regs->comm_paras.reg65_strm_start_bit = 8 * (strm_offset & 0xf); + mpp_dev_set_reg_offset(cfg->dev, 128, strm_offset & 0xfffffff0); + } + + if (hw_ctx->last_segid_flag) { + regs->comm_addrs.reg181_segidlast_base = mpp_buffer_get_fd(hw_ctx->segid_last_base); + regs->comm_addrs.reg182_segidcur_base = mpp_buffer_get_fd(hw_ctx->segid_cur_base); + } else { + regs->comm_addrs.reg181_segidlast_base = mpp_buffer_get_fd(hw_ctx->segid_cur_base); + regs->comm_addrs.reg182_segidcur_base = mpp_buffer_get_fd(hw_ctx->segid_last_base); + } +#ifdef DUMP_VDPU383_DATAS + cur_last_segid_flag = hw_ctx->last_segid_flag; + { + char *cur_fname = "stream_in.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, (void *)mpp_buffer_get_ptr(streambuf) + + pic_param->uncompressed_header_size_byte_aligned, + 8 * (((stream_len + 15) & (~15)) + 0x80), 128, 0); + } +#endif + /* set last segid flag */ + if ((pic_param->stVP9Segments.enabled && pic_param->stVP9Segments.update_map) || + (pic_param->width != hw_ctx->ls_info.last_width || pic_param->height != hw_ctx->ls_info.last_height) || + intraFlag || pic_param->error_resilient_mode) { + hw_ctx->last_segid_flag = !hw_ctx->last_segid_flag; + } + //set cur colmv base + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, task->dec.output); + + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + + hw_ctx->mv_base_addr = regs->comm_addrs.reg216_colmv_cur_base; + if (hw_ctx->pre_mv_base_addr < 0) + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + + // vp9 only one colmv + regs->comm_addrs.reg217_232_colmv_ref_base[0] = hw_ctx->pre_mv_base_addr; + + reg_ref_base = regs->comm_addrs.reg170_185_ref_base; + reg_payload_ref_base = regs->comm_addrs.reg195_210_payload_st_ref_base; + for (i = 0; i < 3; i++) { + ref_idx = pic_param->frame_refs[i].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + ref_frame_width_y = pic_param->ref_frame_coded_width[ref_idx]; + ref_frame_height_y = pic_param->ref_frame_coded_height[ref_idx]; + if (ref_frame_idx < 0x7f) + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &ref_frame); + if (fbc_en) { + y_hor_virstride = uv_hor_virstride = MPP_ALIGN(ref_frame_width_y, 64) / 64; + if (*compat_ext_fbc_hdr_256_odd) + y_hor_virstride = uv_hor_virstride = (MPP_ALIGN(ref_frame_width_y, 256) | 256) / 64; + } else { + if (ref_frame) + y_hor_virstride = uv_hor_virstride = (mpp_frame_get_hor_stride(ref_frame) >> 4); + else + y_hor_virstride = uv_hor_virstride = (mpp_align_128_odd_plus_64((ref_frame_width_y * bit_depth) >> 3) >> 4); + } + if (ref_frame) + y_virstride = y_hor_virstride * mpp_frame_get_ver_stride(ref_frame); + else + y_virstride = y_hor_virstride * mpp_align_64(ref_frame_height_y); + + if (ref_frame_idx < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_BUFFER, &framebuf); + if (hw_ctx->origin_bufs && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(hw_ctx->origin_bufs, ref_frame_idx); + framebuf = origin_buf->buf[0]; + } + + switch (i) { + case 0: { + regs->comm_paras.reg83_ref0_hor_virstride = y_hor_virstride; + regs->comm_paras.reg84_ref0_raster_uv_hor_virstride = uv_hor_virstride; + regs->comm_paras.reg85_ref0_virstride = y_virstride; + } break; + case 1: { + regs->comm_paras.reg86_ref1_hor_virstride = y_hor_virstride; + regs->comm_paras.reg87_ref1_raster_uv_hor_virstride = uv_hor_virstride; + regs->comm_paras.reg88_ref1_virstride = y_virstride; + } break; + case 2: { + regs->comm_paras.reg89_ref2_hor_virstride = y_hor_virstride; + regs->comm_paras.reg90_ref2_raster_uv_hor_virstride = uv_hor_virstride; + regs->comm_paras.reg91_ref2_virstride = y_virstride; + } break; + default: + break; + } + + /*0 map to 11*/ + /*1 map to 12*/ + /*2 map to 13*/ + if (framebuf != NULL) { + reg_ref_base[i] = mpp_buffer_get_fd(framebuf); + reg_payload_ref_base[i] = mpp_buffer_get_fd(framebuf); + } else { + mpp_log("ref buff address is no valid used out as base slot index 0x%x", ref_frame_idx); + reg_ref_base[i] = regs->comm_addrs.reg168_decout_base; + reg_payload_ref_base[i] = regs->comm_addrs.reg168_decout_base; + } + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, ref_frame_idx); + } else { + reg_ref_base[i] = regs->comm_addrs.reg168_decout_base; + reg_payload_ref_base[i] = regs->comm_addrs.reg168_decout_base; + } + } + + vdpu383_init_ctrl_regs(regs, MPP_VIDEO_CodingVP9); + + //last info update + hw_ctx->ls_info.abs_delta_last = pic_param->stVP9Segments.abs_delta; + for (i = 0 ; i < 4; i ++) { + hw_ctx->ls_info.last_ref_deltas[i] = pic_param->ref_deltas[i]; + } + + for (i = 0 ; i < 2; i ++) { + hw_ctx->ls_info.last_mode_deltas[i] = pic_param->mode_deltas[i]; + } + + for (i = 0; i < 8; i++) { + hw_ctx->ls_info.feature_data[i][0] = pic_param->stVP9Segments.feature_data[i][0]; + hw_ctx->ls_info.feature_data[i][1] = pic_param->stVP9Segments.feature_data[i][1]; + hw_ctx->ls_info.feature_data[i][2] = pic_param->stVP9Segments.feature_data[i][2]; + hw_ctx->ls_info.feature_data[i][3] = pic_param->stVP9Segments.feature_data[i][3]; + hw_ctx->ls_info.feature_mask[i] = pic_param->stVP9Segments.feature_mask[i]; + } + if (!hw_ctx->ls_info.segmentation_enable_flag_last) + hw_ctx->ls_info.segmentation_enable_flag_last = pic_param->stVP9Segments.enabled; + + hw_ctx->ls_info.last_show_frame = pic_param->show_frame; + hw_ctx->ls_info.last_width = pic_param->width; + hw_ctx->ls_info.last_height = pic_param->height; + hw_ctx->ls_info.last_frame_type = pic_param->frame_type; + + if (intraFlag) + hw_ctx->ls_info.last_intra_only = 1; + + hw_ctx->ls_info.last_intra_only = (!pic_param->frame_type || pic_param->intra_only); + hal_vp9d_dbg_par("stVP9Segments.enabled %d show_frame %d width %d height %d last_intra_only %d", + pic_param->stVP9Segments.enabled, pic_param->show_frame, + pic_param->width, pic_param->height, + hw_ctx->ls_info.last_intra_only); + + vdpu38x_vp9d_rcb_setup(hal, pic_param, task, ®s->comm_addrs.rcb_regs, + vdpu383_vp9d_rcb_calc); + vdpu383_setup_statistic(®s->ctrl_regs); + // whether need update counts + if (pic_param->refresh_frame_context && !pic_param->parallelmode) { + task->dec.flags.wait_done = 1; + } + + { + //scale down config + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + origin_buf = hal_bufs_get_buf(hw_ctx->origin_bufs, task->dec.output); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg169_error_ref_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + regs->comm_addrs.reg194_payload_st_error_ref_base = fd; + vdpu383_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + vdpu383_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu383_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + Vdpu383RegSet *hw_regs = (Vdpu383RegSet *)hw_ctx->hw_regs; + MppDev dev = p_hal->cfg->dev; + + if (p_hal->fast_mode) { + RK_S32 index = task->dec.reg_index; + + hw_regs = (Vdpu383RegSet *)hw_ctx->g_buf[index].hw_regs; + } + + mpp_assert(hw_regs); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = &hw_regs->ctrl_regs; + wr_cfg.size = sizeof(hw_regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_paras; + wr_cfg.size = sizeof(hw_regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_addrs; + wr_cfg.size = sizeof(hw_regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->ctrl_regs.reg15; + rd_cfg.size = sizeof(hw_regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + // rcb info for sram + vdpu38x_rcb_set_info(hw_ctx->rcb_ctx, dev); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + +static MPP_RET hal_vp9d_vdpu383_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + Vdpu383RegSet *hw_regs = (Vdpu383RegSet *)hw_ctx->hw_regs; + + if (p_hal->fast_mode) + hw_regs = (Vdpu383RegSet *)hw_ctx->g_buf[task->dec.reg_index].hw_regs; + + mpp_assert(hw_regs); + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); +#ifdef DUMP_VDPU383_DATAS + { + char *cur_fname = "cabac_update_probe.dat"; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + RK_U32 frame_ctx_id = pic_param->frame_context_idx; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + dump_data_to_file(dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->prob_loop_base[frame_ctx_id]), + 8 * 152 * 16, 128, 0); + } + { + char *cur_fname = "segid_last.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + if (!cur_last_segid_flag) + dump_data_to_file(dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_cur_base), + 8 * 1559 * 8, 64, 0); + else + dump_data_to_file(dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_last_base), + 8 * 1559 * 8, 64, 0); + } + { + char *cur_fname = "segid_cur.dat"; + memset(dump_cur_fname_path, 0, sizeof(dump_cur_fname_path)); + sprintf(dump_cur_fname_path, "%s/%s", dump_cur_dir, cur_fname); + if (cur_last_segid_flag) + dump_data_to_file(dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_cur_base), + 8 * 1559 * 8, 64, 0); + else + dump_data_to_file(dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_last_base), + 8 * 1559 * 8, 64, 0); + } +#endif + + if (hal_vp9d_debug & HAL_VP9D_DBG_REG) { + RK_U32 *p = (RK_U32 *)hw_regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(Vdpu383RegSet) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i, *p++); + } + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + (!hw_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + hw_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + hw_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_frame_set_errinfo(mframe, 1); + } + +#if !HW_PROB + if (p_hal->dec_cb && task->dec.flags.wait_done) { + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + hal_vp9d_update_counts(mpp_buffer_get_ptr(hw_ctx->count_base), task->dec.syntax.data); + mpp_callback(p_hal->dec_cb, &pic_param->counts); + } +#endif + if (p_hal->fast_mode) { + hw_ctx->g_buf[task->dec.reg_index].use_flag = 0; + } + + (void)task; + return ret; +} + +const MppHalApi hal_vp9d_vdpu383 = { + .name = "vp9d_vdpu383", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingVP9, + .ctx_size = sizeof(HalVp9dCtx), + .flag = 0, + .init = hal_vp9d_vdpu383_init, + .deinit = hal_vp9d_vdpu38x_deinit, + .reg_gen = hal_vp9d_vdpu383_gen_regs, + .start = hal_vp9d_vdpu383_start, + .wait = hal_vp9d_vdpu383_wait, + .reset = hal_vp9d_vdpu38x_reset, + .flush = hal_vp9d_vdpu38x_flush, + .control = hal_vp9d_vdpu38x_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_vp9d_vdpu383) diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu383.h b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu383.h new file mode 100644 index 000000000..0a78af294 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu383.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_VP9D_VDPU383_H +#define HAL_VP9D_VDPU383_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_vp9d_vdpu383; + +#ifdef __cplusplus +} +#endif +#endif /* HAL_VP9D_VDPU34X_H */ diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu384b.c b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu384b.c new file mode 100644 index 000000000..9ba52497a --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu384b.c @@ -0,0 +1,826 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_vp9d_vdpu384b" + +#include "mpp_buffer_impl.h" + +#include "vp9d_syntax.h" +#include "hal_vp9d_debug.h" +#include "vdpu38x_com.h" +#include "hal_vp9d_com.h" +#include "hal_vp9d_ctx.h" +#include "hal_vp9d_vdpu384b.h" + +#define GBL_SIZE (MPP_ALIGN(1340 + 64, 128) / 8) // byte, 1340 bit + Reserve 64 + +#ifdef DUMP_VDPU38X_DATAS +static RK_U32 cur_last_segid_flag; +static MppBuffer cur_last_prob_base; +#endif + +static MPP_RET hal_vp9d_alloc_res(HalVp9dCtx *hal) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + MppBufferGroup group = p_hal->cfg->buf_group; + RK_S32 ret = 0; + RK_S32 i = 0; + + /* alloc common buffer */ + for (i = 0; i < VP9_CONTEXT; i++) { + ret = mpp_buffer_get(group, &hw_ctx->prob_loop_base[i], PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_loop_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->prob_loop_base[i], p_hal->cfg->dev); + } + ret = mpp_buffer_get(group, &hw_ctx->prob_default_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 probe_default_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->prob_default_base, p_hal->cfg->dev); + + ret = mpp_buffer_get(group, &hw_ctx->segid_cur_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_cur_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->segid_cur_base, p_hal->cfg->dev); + ret = mpp_buffer_get(group, &hw_ctx->segid_last_base, MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("vp9 segid_last_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->segid_last_base, p_hal->cfg->dev); + + /* alloc buffer for fast mode or normal */ + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + hw_ctx->g_buf[i].hw_regs = mpp_calloc_size(void, sizeof(Vdpu38xRegSet)); + ret = mpp_buffer_get(group, + &hw_ctx->g_buf[i].global_base, GBL_SIZE); + mpp_buffer_attach_dev(hw_ctx->g_buf[i].global_base, p_hal->cfg->dev); + if (ret) { + mpp_err("vp9 global_base get buffer failed\n"); + return ret; + } + } + } else { + hw_ctx->hw_regs = mpp_calloc_size(void, sizeof(Vdpu38xRegSet)); + ret = mpp_buffer_get(group, &hw_ctx->global_base, PROB_SIZE); + if (ret) { + mpp_err("vp9 global_base get buffer failed\n"); + return ret; + } + mpp_buffer_attach_dev(hw_ctx->global_base, p_hal->cfg->dev); + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu384b_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + + mpp_env_get_u32("hal_vp9d_debug", &hal_vp9d_debug, 0); + + cfg->support_fast_mode = 1; + p_hal->cfg = cfg; + p_hal->client_type = VPU_CLIENT_RKVDEC; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + MEM_CHECK(ret, p_hal->hw_ctx = mpp_calloc_size(void, sizeof(Vdpu38xVp9dCtx) + GBL_SIZE)); + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + + hw_ctx->mv_base_addr = -1; + hw_ctx->pre_mv_base_addr = -1; + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_128_odd_plus_64); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_64); + + ret = hal_vp9d_alloc_res(p_hal); + if (ret) { + mpp_err("hal_vp9d_alloc_res failed\n"); + goto __FAILED; + } + + hw_ctx->last_segid_flag = 1; + + if (cfg->hal_fbc_adj_cfg) { + cfg->hal_fbc_adj_cfg->func = vdpu_afbc_align_calc; + cfg->hal_fbc_adj_cfg->expand = 0; + } + + vdpu38x_rcb_calc_init((Vdpu38xRcbCtx **)&hw_ctx->rcb_ctx); + + return ret; +__FAILED: + hal_vp9d_vdpu38x_deinit(hal); + return ret; +} + +static MPP_RET vdpu384b_vp9d_rcb_calc(void *context, RK_U32 *total_size) +{ + Vdpu38xRcbCtx *ctx = (Vdpu38xRcbCtx *)context; + RK_FLOAT cur_bit_size = 0; + RK_U32 cur_uv_para = 0; + RK_U32 bit_depth = ctx->bit_depth; + RK_U32 in_tl_row = 0; + RK_U32 on_tl_row = 0; + RK_U32 on_tl_col = 0; + Vdpu38xFmt rcb_fmt; + + /* vdpu383/vdpu384a/vdpu384b fix 10bit */ + bit_depth = 10; + + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_IN_TILE_ROW, &in_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_ROW, &on_tl_row); + vdpu38x_rcb_get_len(ctx, VDPU38X_RCB_ON_TILE_COL, &on_tl_col); + rcb_fmt = vdpu38x_rcb_get_fmt(ctx); + + /* RCB_STRMD_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_IN_ROW, 140, cur_bit_size); + + /* RCB_STRMD_ON_ROW */ + cur_bit_size = 0; + if (ctx->pic_w > 4096) + cur_bit_size = MPP_DIVUP(64, on_tl_row) * 250; + vdpu38x_rcb_reg_info_update(ctx, RCB_STRMD_ON_ROW, 142, cur_bit_size); + + /* RCB_INTER_IN_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, in_tl_row) * 2368; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_IN_ROW, 144, cur_bit_size); + + /* RCB_INTER_ON_ROW */ + cur_bit_size = 0; + cur_bit_size = MPP_DIVUP(64, on_tl_row) * 2368; + vdpu38x_rcb_reg_info_update(ctx, RCB_INTER_ON_ROW, 146, cur_bit_size); + + /* RCB_INTRA_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (in_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_IN_ROW, 148, cur_bit_size); + + /* RCB_INTRA_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_intra_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(512, (on_tl_row * (bit_depth + 2) + * (1 + ctx->mbaff_flag) * cur_uv_para)); + vdpu38x_rcb_reg_info_update(ctx, RCB_INTRA_ON_ROW, 150, cur_bit_size); + + /* RCB_FLTD_IN_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, in_tl_row) * (1.2 * bit_depth + 0.5) + * (17.5 + 8 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_IN_ROW, 152, cur_bit_size); + + /* RCB_FLTD_PROT_IN_ROW */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_PROT_IN_ROW, 154, cur_bit_size); + + /* RCB_FLTD_ON_ROW */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_row_uv_coef_map[rcb_fmt]; + cur_bit_size = MPP_ROUNDUP(64, on_tl_row) * (1.2 * bit_depth + 0.5) + * (17.5 + 8 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_ROW, 156, cur_bit_size); + + /* RCB_FLTD_ON_COL */ + cur_bit_size = 0; + cur_uv_para = vdpu38x_filter_col_uv_coef_map[rcb_fmt]; + if (ctx->tile_dir == 0) + cur_bit_size = MPP_ROUNDUP(64, on_tl_col) * (1.6 * bit_depth + 0.5) + * (17.75 + 8 * cur_uv_para); + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_ON_COL, 158, cur_bit_size); + + /* RCB_FLTD_UPSC_ON_COL */ + cur_bit_size = 0; + vdpu38x_rcb_reg_info_update(ctx, RCB_FLTD_UPSC_ON_COL, 160, cur_bit_size); + + *total_size = vdpu38x_rcb_get_total_size(ctx); + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu384b_gen_regs(void *hal, HalTaskInfo *task) +{ + RK_S32 i; + RK_U8 bit_depth = 0; + RK_U32 ref_frame_width_y; + RK_U32 ref_frame_height_y; + RK_S32 stream_len = 0, aglin_offset = 0; + RK_U32 y_hor_virstride, uv_hor_virstride, y_virstride; + RK_U8 *bitstream = NULL; + MppBuffer streambuf = NULL; + RK_U8 ref_idx = 0; + RK_U8 ref_frame_idx = 0; + RK_U32 *reg_ref_base = NULL; + RK_U32 *reg_payload_ref_base = NULL; + RK_S32 intraFlag = 0; + MppBuffer framebuf = NULL; + HalBuf *mv_buf = NULL; + HalBuf *origin_buf = NULL; + + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + MppHalCfg *cfg = p_hal->cfg; + Vdpu38xRegSet *regs = NULL; + RK_S32 mv_size = pic_param->width * pic_param->height / 2; + RK_U32 frame_ctx_id = pic_param->frame_context_idx; + MppFrame mframe; + MppFrame ref_frame = NULL; + + if (p_hal->fast_mode) { + for (i = 0; i < VDPU_FAST_REG_SET_CNT; i++) { + if (!hw_ctx->g_buf[i].use_flag) { + task->dec.reg_index = i; + hw_ctx->global_base = hw_ctx->g_buf[i].global_base; + hw_ctx->hw_regs = hw_ctx->g_buf[i].hw_regs; + hw_ctx->g_buf[i].use_flag = 1; + break; + } + } + if (i == VDPU_FAST_REG_SET_CNT) { + mpp_err("vp9 fast mode buf all used\n"); + return MPP_ERR_NOMEM; + } + } + regs = (Vdpu38xRegSet*)hw_ctx->hw_regs; + memset(regs, 0, sizeof(Vdpu38xRegSet)); + +#ifdef DUMP_VDPU38X_DATAS + { + memset(vdpu38x_dump_cur_dir, 0, sizeof(vdpu38x_dump_cur_dir)); + sprintf(vdpu38x_dump_cur_dir, "vp9/Frame%04d", vdpu38x_dump_cur_frm); + if (access(vdpu38x_dump_cur_dir, 0)) { + if (mkdir(vdpu38x_dump_cur_dir)) + mpp_err_f("error: mkdir %s\n", vdpu38x_dump_cur_dir); + } + vdpu38x_dump_cur_frm++; + } +#endif + + /* uncompress header data */ + vdpu38x_vp9d_uncomp_hdr(p_hal, pic_param, (RK_U64 *)hw_ctx->header_data, GBL_SIZE / 8); + memcpy(mpp_buffer_get_ptr(hw_ctx->global_base), hw_ctx->header_data, GBL_SIZE); + mpp_buffer_sync_end(hw_ctx->global_base); + regs->comm_paras.reg67_global_len = GBL_SIZE / 16; + regs->comm_addrs.reg131_gbl_base = mpp_buffer_get_fd(hw_ctx->global_base); + + if (hw_ctx->cmv_bufs == NULL || hw_ctx->mv_size < mv_size) { + size_t size = mv_size; + + if (hw_ctx->cmv_bufs) { + hal_bufs_deinit(hw_ctx->cmv_bufs); + hw_ctx->cmv_bufs = NULL; + } + + hal_bufs_init(&hw_ctx->cmv_bufs); + if (hw_ctx->cmv_bufs == NULL) { + mpp_err_f("colmv bufs init fail"); + return MPP_NOK; + } + hw_ctx->mv_size = mv_size; + hw_ctx->mv_count = mpp_buf_slot_get_count(cfg->frame_slots); + hal_bufs_setup(hw_ctx->cmv_bufs, hw_ctx->mv_count, 1, &size); + } + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY && + hw_ctx->origin_bufs == NULL) { + vdpu38x_setup_scale_origin_bufs(mframe, &hw_ctx->origin_bufs, + mpp_buf_slot_get_count(cfg->frame_slots)); + } + + stream_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + + intraFlag = (!pic_param->frame_type || pic_param->intra_only); + /* init kf_probe */ + if (intraFlag) { + hal_vp9d_prob_default(mpp_buffer_get_ptr(hw_ctx->prob_default_base), task->dec.syntax.data); + mpp_buffer_sync_end(hw_ctx->prob_default_base); + } + + /* config last prob base and update write base */ + { + if (intraFlag || pic_param->error_resilient_mode) { + if (intraFlag + || pic_param->error_resilient_mode + || (pic_param->reset_frame_context == 3)) { + memset(hw_ctx->prob_ctx_valid, 0, sizeof(hw_ctx->prob_ctx_valid)); + } else if (pic_param->reset_frame_context == 2) { + hw_ctx->prob_ctx_valid[frame_ctx_id] = 0; + } + } + + if (hw_ctx->prob_ctx_valid[frame_ctx_id]) { + regs->comm_addrs.reg184_lastprob_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); +#ifdef DUMP_VDPU38X_DATAS + cur_last_prob_base = hw_ctx->prob_loop_base[frame_ctx_id]; +#endif + } else { + /* + * When configuring the default prob, the hardware actually uses + * the internal buffer of the hardware. + */ + regs->comm_addrs.reg184_lastprob_base = mpp_buffer_get_fd(hw_ctx->prob_default_base); + hw_ctx->prob_ctx_valid[frame_ctx_id] |= pic_param->refresh_frame_context; +#ifdef DUMP_VDPU38X_DATAS + cur_last_prob_base = hw_ctx->prob_default_base; +#endif + } + regs->comm_addrs.reg185_updateprob_base = + mpp_buffer_get_fd(hw_ctx->prob_loop_base[frame_ctx_id]); + } +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "cabac_last_probe.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(cur_last_prob_base), + 8 * 152 * 16, 128, 0, 0); + } +#endif + + regs->comm_paras.reg66_stream_len = ((stream_len + 15) & (~15)) + 0x80; + + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + bitstream = mpp_buffer_get_ptr(streambuf); + aglin_offset = regs->comm_paras.reg66_stream_len - stream_len; + if (aglin_offset > 0) { + memset((void *)(bitstream + stream_len), 0, aglin_offset); + } + + //--- caculate the yuv_frame_size and mv_size + bit_depth = pic_param->BitDepthMinus8Luma + 8; + + { + MppFrameFormat fmt; + RK_U32 sw_hor_virstride = 0; + RK_U32 sw_ver_virstride = 0; + RK_U32 sw_y_virstride = 0; + RK_U32 sw_uv_virstride = 0; + RK_U32 fbc_head_stride = 0; + RK_U32 fbc_pld_stride = 0; + RK_U32 fbc_offset = 0; + RK_U32 tile4x4_coeff = 0; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + fmt = mpp_frame_get_fmt(mframe); + sw_hor_virstride = mpp_frame_get_hor_stride(mframe); + sw_ver_virstride = mpp_frame_get_ver_stride(mframe); + sw_y_virstride = sw_ver_virstride * sw_hor_virstride; + sw_uv_virstride = sw_ver_virstride * sw_hor_virstride / 2; + if (MPP_FRAME_FMT_IS_AFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 3; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + regs->comm_paras.reg80_error_ref_hor_virstride = fbc_head_stride; + } else if (MPP_FRAME_FMT_IS_RKFBC(fmt)) { + vdpu38x_get_fbc_off(mframe, &fbc_head_stride, &fbc_pld_stride, &fbc_offset); + + regs->ctrl_regs.reg9.pp_output_mode = 2; + regs->comm_paras.reg68_pp_m_hor_stride = fbc_head_stride; + regs->comm_paras.reg69_pp_m_uv_hor_stride = fbc_pld_stride; + regs->comm_addrs.reg193_fbc_payload_offset = fbc_offset; + regs->comm_paras.reg80_error_ref_hor_virstride = fbc_head_stride; + } else if (MPP_FRAME_FMT_IS_TILE(fmt)) { + if (vdpu38x_get_tile4x4_h_stride_coeff(fmt, &tile4x4_coeff)) { + mpp_err("get tile 4x4 coeff failed\n"); + return MPP_NOK; + } + regs->ctrl_regs.reg9.pp_output_mode = 1; + regs->comm_paras.reg68_pp_m_hor_stride = sw_hor_virstride * tile4x4_coeff >> 4; + regs->comm_paras.reg70_pp_m_y_virstride = (sw_y_virstride + sw_uv_virstride) >> 4; + } else { + regs->ctrl_regs.reg9.pp_output_mode = 0; + regs->comm_paras.reg68_pp_m_hor_stride = sw_hor_virstride >> 4; + regs->comm_paras.reg69_pp_m_uv_hor_stride = sw_hor_virstride >> 4; + regs->comm_paras.reg70_pp_m_y_virstride = sw_y_virstride >> 4; + } + /* error stride */ + regs->comm_paras.reg80_error_ref_hor_virstride = regs->comm_paras.reg68_pp_m_hor_stride; + regs->comm_paras.reg81_error_ref_raster_uv_hor_virstride = regs->comm_paras.reg69_pp_m_uv_hor_stride; + regs->comm_paras.reg82_error_ref_virstride = regs->comm_paras.reg70_pp_m_y_virstride; + } + if (!pic_param->intra_only && pic_param->frame_type && + !pic_param->error_resilient_mode && hw_ctx->ls_info.last_show_frame) { + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + } + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_BUFFER, &framebuf); + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(hw_ctx->origin_bufs, task->dec.output); + framebuf = origin_buf->buf[0]; + } + regs->comm_addrs.reg168_decout_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg169_error_ref_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg192_payload_st_cur_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg194_payload_st_error_ref_base = mpp_buffer_get_fd(framebuf); + regs->comm_addrs.reg128_strm_base = mpp_buffer_get_fd(streambuf); + regs->comm_addrs.reg129_stream_buf_st_base = mpp_buffer_get_fd(streambuf); + regs->comm_addrs.reg130_stream_buf_end_base = mpp_buffer_get_fd(streambuf); + mpp_dev_set_reg_offset(cfg->dev, 130, mpp_buffer_get_size(streambuf)); + + { + RK_U32 strm_offset = pic_param->uncompressed_header_size_byte_aligned; + + regs->comm_paras.reg65_strm_start_bit = 8 * (strm_offset & 0xf); + mpp_dev_set_reg_offset(cfg->dev, 128, strm_offset & 0xfffffff0); + } + + if (hw_ctx->last_segid_flag) { + regs->comm_addrs.reg181_segidlast_base = mpp_buffer_get_fd(hw_ctx->segid_last_base); + regs->comm_addrs.reg182_segidcur_base = mpp_buffer_get_fd(hw_ctx->segid_cur_base); + } else { + regs->comm_addrs.reg181_segidlast_base = mpp_buffer_get_fd(hw_ctx->segid_cur_base); + regs->comm_addrs.reg182_segidcur_base = mpp_buffer_get_fd(hw_ctx->segid_last_base); + } +#ifdef DUMP_VDPU38X_DATAS + cur_last_segid_flag = hw_ctx->last_segid_flag; + { + char *cur_fname = "stream_in.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, (void *)mpp_buffer_get_ptr(streambuf) + + pic_param->uncompressed_header_size_byte_aligned, + 8 * (((stream_len + 15) & (~15)) + 0x80), 128, 0, 0); + } +#endif + /* set last segid flag */ + if ((pic_param->stVP9Segments.enabled && pic_param->stVP9Segments.update_map) || + (pic_param->width != hw_ctx->ls_info.last_width || pic_param->height != hw_ctx->ls_info.last_height) || + intraFlag || pic_param->error_resilient_mode) { + hw_ctx->last_segid_flag = !hw_ctx->last_segid_flag; + } + //set cur colmv base + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, task->dec.output); + + regs->comm_addrs.reg216_colmv_cur_base = mpp_buffer_get_fd(mv_buf->buf[0]); + + hw_ctx->mv_base_addr = regs->comm_addrs.reg216_colmv_cur_base; + if (hw_ctx->pre_mv_base_addr < 0) + hw_ctx->pre_mv_base_addr = hw_ctx->mv_base_addr; + + // vp9 only one colmv + regs->comm_addrs.reg217_232_colmv_ref_base[0] = hw_ctx->pre_mv_base_addr; + + reg_ref_base = regs->comm_addrs.reg170_185_ref_base; + reg_payload_ref_base = regs->comm_addrs.reg195_210_payload_st_ref_base; + for (i = 0; i < 3; i++) { + ref_idx = pic_param->frame_refs[i].Index7Bits; + ref_frame_idx = pic_param->ref_frame_map[ref_idx].Index7Bits; + ref_frame_width_y = pic_param->ref_frame_coded_width[ref_idx]; + ref_frame_height_y = pic_param->ref_frame_coded_height[ref_idx]; + if (ref_frame_idx < 0x7f) + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_FRAME_PTR, &ref_frame); + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe))) { + vdpu38x_get_fbc_off(ref_frame, &y_hor_virstride, &uv_hor_virstride, &y_virstride); + } else { + if (ref_frame) + y_hor_virstride = uv_hor_virstride = (mpp_frame_get_hor_stride(ref_frame) >> 4); + else + y_hor_virstride = uv_hor_virstride = (mpp_align_128_odd_plus_64((ref_frame_width_y * bit_depth) >> 3) >> 4); + } + if (ref_frame) + y_virstride = y_hor_virstride * mpp_frame_get_ver_stride(ref_frame); + else + y_virstride = y_hor_virstride * mpp_align_64(ref_frame_height_y); + + if (ref_frame_idx < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, ref_frame_idx, SLOT_BUFFER, &framebuf); + if (hw_ctx->origin_bufs && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) { + origin_buf = hal_bufs_get_buf(hw_ctx->origin_bufs, ref_frame_idx); + framebuf = origin_buf->buf[0]; + } + + switch (i) { + case 0: { + regs->comm_paras.reg83_ref0_hor_virstride = y_hor_virstride; + regs->comm_paras.reg84_ref0_raster_uv_hor_virstride = uv_hor_virstride; + regs->comm_paras.reg85_ref0_virstride = y_virstride; + } break; + case 1: { + regs->comm_paras.reg86_ref1_hor_virstride = y_hor_virstride; + regs->comm_paras.reg87_ref1_raster_uv_hor_virstride = uv_hor_virstride; + regs->comm_paras.reg88_ref1_virstride = y_virstride; + } break; + case 2: { + regs->comm_paras.reg89_ref2_hor_virstride = y_hor_virstride; + regs->comm_paras.reg90_ref2_raster_uv_hor_virstride = uv_hor_virstride; + regs->comm_paras.reg91_ref2_virstride = y_virstride; + } break; + default: + break; + } + + /*0 map to 11*/ + /*1 map to 12*/ + /*2 map to 13*/ + if (framebuf != NULL) { + reg_ref_base[i] = mpp_buffer_get_fd(framebuf); + reg_payload_ref_base[i] = mpp_buffer_get_fd(framebuf); + } else { + mpp_log("ref buff address is no valid used out as base slot index 0x%x", ref_frame_idx); + reg_ref_base[i] = regs->comm_addrs.reg168_decout_base; + reg_payload_ref_base[i] = regs->comm_addrs.reg168_decout_base; + } + mv_buf = hal_bufs_get_buf(hw_ctx->cmv_bufs, ref_frame_idx); + } else { + reg_ref_base[i] = regs->comm_addrs.reg168_decout_base; + reg_payload_ref_base[i] = regs->comm_addrs.reg168_decout_base; + } + } + + vdpu384b_init_ctrl_regs(regs, MPP_VIDEO_CodingVP9); + + //last info update + hw_ctx->ls_info.abs_delta_last = pic_param->stVP9Segments.abs_delta; + for (i = 0 ; i < 4; i ++) { + hw_ctx->ls_info.last_ref_deltas[i] = pic_param->ref_deltas[i]; + } + + for (i = 0 ; i < 2; i ++) { + hw_ctx->ls_info.last_mode_deltas[i] = pic_param->mode_deltas[i]; + } + + for (i = 0; i < 8; i++) { + hw_ctx->ls_info.feature_data[i][0] = pic_param->stVP9Segments.feature_data[i][0]; + hw_ctx->ls_info.feature_data[i][1] = pic_param->stVP9Segments.feature_data[i][1]; + hw_ctx->ls_info.feature_data[i][2] = pic_param->stVP9Segments.feature_data[i][2]; + hw_ctx->ls_info.feature_data[i][3] = pic_param->stVP9Segments.feature_data[i][3]; + hw_ctx->ls_info.feature_mask[i] = pic_param->stVP9Segments.feature_mask[i]; + } + if (!hw_ctx->ls_info.segmentation_enable_flag_last) + hw_ctx->ls_info.segmentation_enable_flag_last = pic_param->stVP9Segments.enabled; + + hw_ctx->ls_info.last_show_frame = pic_param->show_frame; + hw_ctx->ls_info.last_width = pic_param->width; + hw_ctx->ls_info.last_height = pic_param->height; + hw_ctx->ls_info.last_frame_type = pic_param->frame_type; + + if (intraFlag) + hw_ctx->ls_info.last_intra_only = 1; + + hw_ctx->ls_info.last_intra_only = (!pic_param->frame_type || pic_param->intra_only); + hal_vp9d_dbg_par("stVP9Segments.enabled %d show_frame %d width %d height %d last_intra_only %d", + pic_param->stVP9Segments.enabled, pic_param->show_frame, + pic_param->width, pic_param->height, + hw_ctx->ls_info.last_intra_only); + + vdpu38x_vp9d_rcb_setup(hal, pic_param, task, ®s->comm_addrs.rcb_regs, + vdpu384b_vp9d_rcb_calc); + vdpu38x_setup_statistic(®s->ctrl_regs); + // whether need update counts + if (pic_param->refresh_frame_context && !pic_param->parallelmode) { + task->dec.flags.wait_done = 1; + } + + { + //scale down config + MppBuffer mbuffer = NULL; + RK_S32 fd = -1; + MppFrameThumbnailMode thumbnail_mode; + + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_BUFFER, &mbuffer); + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, + SLOT_FRAME_PTR, &mframe); + thumbnail_mode = mpp_frame_get_thumbnail_en(mframe); + switch (thumbnail_mode) { + case MPP_FRAME_THUMBNAIL_ONLY: + regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + origin_buf = hal_bufs_get_buf(hw_ctx->origin_bufs, task->dec.output); + fd = mpp_buffer_get_fd(origin_buf->buf[0]); + regs->comm_addrs.reg168_decout_base = fd; + regs->comm_addrs.reg169_error_ref_base = fd; + regs->comm_addrs.reg192_payload_st_cur_base = fd; + regs->comm_addrs.reg194_payload_st_error_ref_base = fd; + vdpu38x_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_MIXED: + regs->comm_addrs.reg133_scale_down_base = mpp_buffer_get_fd(mbuffer); + vdpu38x_setup_down_scale(mframe, cfg->dev, ®s->ctrl_regs, + (void *)®s->comm_paras); + break; + case MPP_FRAME_THUMBNAIL_NONE: + default: + regs->ctrl_regs.reg9.scale_down_en = 0; + break; + } + } + + return MPP_OK; +} + +static MPP_RET hal_vp9d_vdpu384b_start(void *hal, HalTaskInfo *task) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + Vdpu38xRegSet *hw_regs = (Vdpu38xRegSet *)hw_ctx->hw_regs; + MppDev dev = p_hal->cfg->dev; + MPP_RET ret = MPP_OK; + + if (p_hal->fast_mode) { + RK_S32 index = task->dec.reg_index; + + hw_regs = (Vdpu38xRegSet *)hw_ctx->g_buf[index].hw_regs; + } + + mpp_assert(hw_regs); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = &hw_regs->ctrl_regs; + wr_cfg.size = sizeof(hw_regs->ctrl_regs); + wr_cfg.offset = VDPU38X_OFF_CTRL_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_paras; + wr_cfg.size = sizeof(hw_regs->comm_paras); + wr_cfg.offset = VDPU38X_OFF_CODEC_PARAS_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &hw_regs->comm_addrs; + wr_cfg.size = sizeof(hw_regs->comm_addrs); + wr_cfg.offset = VDPU38X_OFF_COMMON_ADDR_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &hw_regs->ctrl_regs.reg15; + rd_cfg.size = sizeof(hw_regs->ctrl_regs.reg15); + rd_cfg.offset = VDPU38X_OFF_INTERRUPT_REGS; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + if (hal_vp9d_debug & HAL_VP9D_DBG_REG) { + rd_cfg.reg = &hw_regs->statistic_regs; + rd_cfg.size = sizeof(hw_regs->statistic_regs); + rd_cfg.offset = VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + } + + // rcb info for sram + vdpu38x_rcb_set_info(hw_ctx->rcb_ctx, dev); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + return ret; +} + +static MPP_RET hal_vp9d_vdpu384b_wait(void *hal, HalTaskInfo *task) +{ + HalVp9dCtx *p_hal = (HalVp9dCtx*)hal; + Vdpu38xVp9dCtx *hw_ctx = (Vdpu38xVp9dCtx*)p_hal->hw_ctx; + Vdpu38xRegSet *hw_regs = (Vdpu38xRegSet *)hw_ctx->hw_regs; + MPP_RET ret = MPP_OK; + + if (p_hal->fast_mode) + hw_regs = (Vdpu38xRegSet *)hw_ctx->g_buf[task->dec.reg_index].hw_regs; + + mpp_assert(hw_regs); + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); +#ifdef DUMP_VDPU38X_DATAS + { + char *cur_fname = "cabac_update_probe.dat"; + DXVA_PicParams_VP9 *pic_param = (DXVA_PicParams_VP9*)task->dec.syntax.data; + RK_U32 frame_ctx_id = pic_param->frame_context_idx; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->prob_loop_base[frame_ctx_id]), + 8 * 152 * 16, 128, 0, 0); + } + { + char *cur_fname = "segid_last.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + if (!cur_last_segid_flag) + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_cur_base), + 8 * 1559 * 8, 64, 0, 0); + else + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_last_base), + 8 * 1559 * 8, 64, 0, 0); + } + { + char *cur_fname = "segid_cur.dat"; + memset(vdpu38x_dump_cur_fname_path, 0, sizeof(vdpu38x_dump_cur_fname_path)); + sprintf(vdpu38x_dump_cur_fname_path, "%s/%s", vdpu38x_dump_cur_dir, cur_fname); + if (cur_last_segid_flag) + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_cur_base), + 8 * 1559 * 8, 64, 0, 0); + else + vdpu38x_dump_data_to_file(vdpu38x_dump_cur_fname_path, + (void *)mpp_buffer_get_ptr(hw_ctx->segid_last_base), + 8 * 1559 * 8, 64, 0, 0); + } +#endif + + if (hal_vp9d_debug & HAL_VP9D_DBG_REG) { + RK_U32 *p = (RK_U32 *)hw_regs; + RK_U32 i = 0; + + for (i = 0; i < sizeof(hw_regs->ctrl_regs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_CTRL_REGS, *p++); + for (i = 0; i < sizeof(hw_regs->comm_paras) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_CODEC_PARAS_REGS, *p++); + for (i = 0; i < sizeof(hw_regs->comm_addrs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_COMMON_ADDR_REGS, *p++); + for (i = 0; i < sizeof(hw_regs->statistic_regs) / 4; i++) + mpp_log("get regs[%02d]: %08X\n", i + VDPU38X_OFF_COM_STATISTIC_REGS_VDPU384B, *p++); + + mpp_assert(hw_regs->statistic_regs.reg312.rcb_rd_sum_chk == + hw_regs->statistic_regs.reg312.rcb_wr_sum_chk); + } + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err || + (!hw_regs->ctrl_regs.reg15.rkvdec_frame_rdy_sta) || + hw_regs->ctrl_regs.reg15.rkvdec_strm_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_core_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_ip_timeout_sta || + hw_regs->ctrl_regs.reg15.rkvdec_bus_error_sta || + hw_regs->ctrl_regs.reg15.rkvdec_buffer_empty_sta || + hw_regs->ctrl_regs.reg15.rkvdec_colmv_ref_error_sta) { + MppFrame mframe = NULL; + + mpp_buf_slot_get_prop(p_hal->cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_frame_set_errinfo(mframe, 1); + } + + if (p_hal->fast_mode) { + hw_ctx->g_buf[task->dec.reg_index].use_flag = 0; + } + + (void)task; + return ret; +} + +const MppHalApi hal_vp9d_vdpu384b = { + .name = "vp9d_vdpu384b", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingVP9, + .ctx_size = sizeof(HalVp9dCtx), + .flag = 0, + .init = hal_vp9d_vdpu384b_init, + .deinit = hal_vp9d_vdpu38x_deinit, + .reg_gen = hal_vp9d_vdpu384b_gen_regs, + .start = hal_vp9d_vdpu384b_start, + .wait = hal_vp9d_vdpu384b_wait, + .reset = hal_vp9d_vdpu38x_reset, + .flush = hal_vp9d_vdpu38x_flush, + .control = hal_vp9d_vdpu38x_control, + .client = VPU_CLIENT_RKVDEC, + .soc_type = { + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_vp9d_vdpu384b) diff --git a/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu384b.h b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu384b.h new file mode 100644 index 000000000..05d91cd57 --- /dev/null +++ b/mpp/hal/rkdec/vp9d/hal_vp9d_vdpu384b.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_VP9D_VDPU384B_H +#define HAL_VP9D_VDPU384B_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_vp9d_vdpu384b; + +#ifdef __cplusplus +} +#endif +#endif /* HAL_VP9D_VDPU384B_H */ diff --git a/mpp/hal/rkenc/CMakeLists.txt b/mpp/hal/rkenc/CMakeLists.txt new file mode 100644 index 000000000..2ab5f8e06 --- /dev/null +++ b/mpp/hal/rkenc/CMakeLists.txt @@ -0,0 +1,14 @@ +# vim: syntax=cmake +add_subdirectory(common) + +if( HAVE_H264E ) + add_subdirectory(h264e) +endif() + +if( HAVE_H265E ) + add_subdirectory(h265e) +endif() + +if( HAVE_JPEGE ) + add_subdirectory(jpege) +endif() diff --git a/mpp/hal/rkenc/common/CMakeLists.txt b/mpp/hal/rkenc/common/CMakeLists.txt new file mode 100644 index 000000000..f362e01b9 --- /dev/null +++ b/mpp/hal/rkenc/common/CMakeLists.txt @@ -0,0 +1,14 @@ +# vim: syntax=cmake +include_directories(.) + +# hal vepu541 common module +add_library(hal_vepu5xx_common OBJECT + vepu541_common.c + vepu5xx_common.c + vepu540c_common.c + vepu580_tune.c + vepu580_common.c + vepu510_common.c + vepu511_common.c + vepu511a_common.c + ) diff --git a/mpp/hal/rkenc/common/rkv_enc_def.h b/mpp/hal/rkenc/common/rkv_enc_def.h new file mode 100644 index 000000000..efb8e7363 --- /dev/null +++ b/mpp/hal/rkenc/common/rkv_enc_def.h @@ -0,0 +1,130 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RKV_ENC_DEF_H +#define RKV_ENC_DEF_H + +#define RKV_ENC_INT_ONE_FRAME_FINISH 0x00000001 +#define RKV_ENC_INT_LINKTABLE_FINISH 0x00000002 +#define RKV_ENC_INT_SAFE_CLEAR_FINISH 0x00000004 +#define RKV_ENC_INT_ONE_SLICE_FINISH 0x00000008 +#define RKV_ENC_INT_BIT_STREAM_OVERFLOW 0x00000010 +#define RKV_ENC_INT_BUS_WRITE_FULL 0x00000020 +#define RKV_ENC_INT_BUS_WRITE_ERROR 0x00000040 +#define RKV_ENC_INT_BUS_READ_ERROR 0x00000080 +#define RKV_ENC_INT_TIMEOUT_ERROR 0x00000100 + +#define RKVENC_CODING_TYPE_AUTO 0x0000 /* Let enc choose the right type */ +#define RKVENC_CODING_TYPE_IDR 0x0001 +#define RKVENC_CODING_TYPE_I 0x0002 +#define RKVENC_CODING_TYPE_P 0x0003 +#define RKVENC_CODING_TYPE_BREF 0x0004 /* Non-disposable B-frame */ +#define RKVENC_CODING_TYPE_B 0x0005 +#define RKVENC_CODING_TYPE_KEYFRAME 0x0006 /* IDR or I depending on b_open_gop option */ + +#define RKVE_IOC_CUSTOM_BASE 0x1000 +#define RKVE_IOC_SET_OSD_PLT (RKVE_IOC_CUSTOM_BASE + 1) +#define RKVE_IOC_SET_L2_REG (RKVE_IOC_CUSTOM_BASE + 2) + + +#define RKVE_CSP2_MASK 0x00ff /* */ +#define RKVE_CSP2_NONE 0x0000 /* Invalid mode */ +#define RKVE_CSP2_I420 0x0001 /* yuv 4:2:0 planar */ +#define RKVE_CSP2_YV12 0x0002 /* yvu 4:2:0 planar */ +#define RKVE_CSP2_NV12 0x0003 /* yuv 4:2:0, with one y plane and one packed u+v */ +#define RKVE_CSP2_I422 0x0004 /* yuv 4:2:2 planar */ +#define RKVE_CSP2_YV16 0x0005 /* yvu 4:2:2 planar */ +#define RKVE_CSP2_NV16 0x0006 /* yuv 4:2:2, with one y plane and one packed u+v */ +#define RKVE_CSP2_V210 0x0007 /* 10-bit yuv 4:2:2 packed in 32 */ +#define RKVE_CSP2_I444 0x0008 /* yuv 4:4:4 planar */ +#define RKVE_CSP2_YV24 0x0009 /* yvu 4:4:4 planar */ +#define RKVE_CSP2_BGR 0x000a /* packed bgr 24bits */ +#define RKVE_CSP2_BGRA 0x000b /* packed bgr 32bits */ +#define RKVE_CSP2_RGB 0x000c /* packed rgb 24bits */ +#define RKVE_CSP2_MAX 0x000d /* end of list */ +#define RKVE_CSP2_VFLIP 0x1000 /* the csp is vertically flipped */ +#define RKVE_CSP2_HIGH_DEPTH 0x2000 /* the csp has a depth of 16 bits per pixel component */ + +#define RKVE_MB_RC_ONLY_QUALITY 0 +#define RKVE_MB_RC_MORE_QUALITY 1 +#define RKVE_MB_RC_BALANCE 2 +#define RKVE_MB_RC_MORE_BITRATE 3 +#define RKVE_MB_RC_ONLY_BITRATE 4 +#define RKVE_MB_RC_WIDE_RANGE 5 +#define RKVE_MB_RC_ONLY_AQ 6 +#define RKVE_MB_RC_M_NUM 7 + +typedef enum RkveCsp_e { + RKVE_CSP_BGRA8888, // 0 + RKVE_CSP_BGR888, // 1 + RKVE_CSP_BGR565, // 2 + RKVE_CSP_NONE, // 3 + RKVE_CSP_YUV422SP, // 4 + RKVE_CSP_YUV422P, // 5 + RKVE_CSP_YUV420SP, // 6 + RKVE_CSP_YUV420P, // 7 + RKVE_CSP_YUYV422, // 8 + RKVE_CSP_UYVY422, // 9 + RKVE_CSP_BUTT, // 10 +} RkveCsp; + +typedef enum enc_hal_rkv_buf_grp_t { + ENC_HAL_RKV_BUF_GRP_PP, + ENC_HAL_RKV_BUF_GRP_DSP, + ENC_HAL_RKV_BUF_GRP_MEI, + ENC_HAL_RKV_BUF_GRP_CMV, + ENC_HAL_RKV_BUF_GRP_ROI, + ENC_HAL_RKV_BUF_GRP_REC, + ENC_HAL_RKV_BUF_GRP_BUTT +} enc_hal_rkv_buf_grp; + +typedef enum enc_rkv_lnktable_t { + RKVENC_LINKTABLE_DISABLE = 1, + RKVENC_LINKTABLE_START, + RKVENC_LINKTABLE_UPDATE +} enc_rkv_lnk_table; + +typedef struct { + RK_U8 qp_y : 6; + RK_U8 set_qp_y_en : 1; + RK_U8 forbid_inter : 1; +} RkvRoiCfg; + +typedef struct { + RK_U16 forbid_inter : 1; /* intra flag for cu 16x16 */ + RK_U16 reserved : 3; /* reserved */ + RK_U16 qp_area_idx : 3; /* roi range index */ + RK_U16 area_map : 1; /* roi en */ + RK_S16 qp_y : 7; /* qp_value, absolute qp or relative qp*/ + RK_U16 set_qp_y : 1; +} RkvRoiCfg_v2; + +typedef enum ReOsdPltType_e { + RKVE_OSD_PLT_TYPE_NONE = -1, + RKVE_OSD_PLT_TYPE_USERDEF = 0, + RKVE_OSD_PLT_TYPE_DEFAULT = 1, +} RkveOsdPltType; + + +#define RKV_ENC_MODE RKVENC_LINKTABLE_DISABLE //2 +#define RKVE_LINKTABLE_FRAME_NUM 1 //2 + +#define RKVE_LINKTABLE_EACH_NUM RKVE_LINKTABLE_FRAME_NUM + +#define RKVE_LINKTABLE_MAX_SIZE 256 + +#define RKVE_RC_TEXTURE_THR_SIZE 16 + +#endif diff --git a/mpp/hal/rkenc/common/vepu510_common.c b/mpp/hal/rkenc/common/vepu510_common.c new file mode 100644 index 000000000..942ba7699 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu510_common.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vepu510_common" + +#include +#include "mpp_log.h" +#include "mpp_common.h" +#include "vepu510_common.h" + +MPP_RET vepu510_set_roi(void *roi_reg_base, MppEncROICfg * roi, + RK_S32 w, RK_S32 h) +{ + MppEncROIRegion *region = roi->regions; + Vepu510RoiCfg *roi_cfg = (Vepu510RoiCfg *)roi_reg_base; + Vepu510RoiRegion *reg_regions = &roi_cfg->regions[0]; + MPP_RET ret = MPP_NOK; + RK_S32 i = 0; + + if (NULL == reg_regions) { + mpp_err_f("invalid reg_regions %p\n", reg_regions); + goto DONE; + } + memset(reg_regions, 0, sizeof(Vepu510RoiRegion) * 8); + + if (NULL == roi_cfg || NULL == roi) { + mpp_err_f("invalid buf %p roi %p\n", roi_cfg, roi); + goto DONE; + } + + if (roi->number > VEPU510_MAX_ROI_NUM) { + mpp_err_f("invalid region number %d\n", roi->number); + goto DONE; + } + + /* check region config */ + ret = MPP_OK; + for (i = 0; i < (RK_S32) roi->number; i++, region++) { + if (region->x + region->w > w || region->y + region->h > h) + ret = MPP_NOK; + + if (region->intra > 1 + || region->qp_area_idx >= VEPU510_MAX_ROI_NUM + || region->area_map_en > 1 || region->abs_qp_en > 1) + ret = MPP_NOK; + + if ((region->abs_qp_en && region->quality > 51) || + (!region->abs_qp_en + && (region->quality > 51 || region->quality < -51))) + ret = MPP_NOK; + + if (ret) { + mpp_err_f("region %d invalid param:\n", i); + mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n", + region->x, region->y, region->w, region->h, w, + h); + mpp_err_f("force intra %d qp area index %d\n", + region->intra, region->qp_area_idx); + mpp_err_f("abs qp mode %d value %d\n", + region->abs_qp_en, region->quality); + goto DONE; + } + reg_regions->roi_pos_lt.roi_lt_x = MPP_ALIGN(region->x, 16) >> 4; + reg_regions->roi_pos_lt.roi_lt_y = MPP_ALIGN(region->y, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_x = MPP_ALIGN(region->x + region->w, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_y = MPP_ALIGN(region->y + region->h, 16) >> 4; + reg_regions->roi_base.roi_qp_value = region->quality; + reg_regions->roi_base.roi_qp_adj_mode = region->abs_qp_en; + reg_regions->roi_base.roi_en = 1; + reg_regions->roi_base.roi_pri = 0x1f; + if (region->intra) { + reg_regions->roi_mdc.roi_mdc_intra16 = 1; + reg_regions->roi_mdc.roi0_mdc_intra32_hevc = 1; + } + reg_regions++; + } + +DONE: + return ret; +} + diff --git a/mpp/hal/rkenc/common/vepu510_common.h b/mpp/hal/rkenc/common/vepu510_common.h new file mode 100644 index 000000000..0160aa7ee --- /dev/null +++ b/mpp/hal/rkenc/common/vepu510_common.h @@ -0,0 +1,2225 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VEPU510_COMMON_H +#define VEPU510_COMMON_H + +#include "rk_venc_cmd.h" + +#define VEPU510_CTL_OFFSET (0 * sizeof(RK_U32)) /* 0x00000000 reg0 - 0x00000120 reg72 */ +#define VEPU510_FRAME_OFFSET (156 * sizeof(RK_U32)) /* 0x00000270 reg156 - 0x000003f4 reg253 */ +#define VEPU510_RC_ROI_OFFSET (1024 * sizeof(RK_U32)) /* 0x00001000 reg1024 - 0x0000110c reg1091 */ +#define VEPU510_PARAM_OFFSET (1472 * sizeof(RK_U32)) /* 0x00001700 reg1472 - 0x000019cc reg1651 */ +#define VEPU510_SQI_OFFSET (2048 * sizeof(RK_U32)) /* 0x00002000 reg2048 - 0x0000212c reg2123 */ +#define VEPU510_SCL_OFFSET (2176 * sizeof(RK_U32)) /* 0x00002200 reg2176 - 0x00002584 reg2401 */ +#define VEPU510_STATUS_OFFSET (4096 * sizeof(RK_U32)) /* 0x00004000 reg4096 - 0x0000424c reg4243 */ +#define VEPU510_DBG_OFFSET (5120 * sizeof(RK_U32)) /* 0x00005000 reg5120 - 0x00005230 reg5260 */ +#define VEPU510_REG_BASE_HW_STATUS (0x2c) +#define VEPU510_MAX_ROI_NUM 8 +#define VEPU510_SLICE_FIFO_LEN 8 + +typedef struct Vepu510Online_t { + /* 0x00000270 reg156 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsy_t : 28; + } adr_vsy_t; + + /* 0x00000274 reg157 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsc_t : 28; + } adr_vsc_t; + + /* 0x00000278 reg158 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsy_b : 28; + } adr_vsy_b; + + /* 0x0000027c reg159 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsc_b : 28; + } adr_vsc_b; +} vepu510_online; + +typedef struct Vepu510RdoSkipPar_t { + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } atf_thd0; + + /* 0x00002064 reg2073 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd3 : 12; + RK_U32 reserved1 : 4; + } atf_thd1; + + /* 0x00002068 reg2074 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt0; + + /* 0x0000206c reg2075 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 reserved : 24; + } atf_wgt1; +} rdo_skip_par; + +typedef struct Vepu510RdoNoSkipPar_t { + /* 0x00002080 reg2080 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } ratf_thd0; + + /* 0x00002084 reg2081 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 atf_bypass_pri_flag : 1; + RK_U32 reserved1 : 15; + } ratf_thd1; + + /* 0x00002088 reg2082 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt; +} rdo_noskip_par; + +typedef struct Vepu510RoiRegion_t { + struct { + RK_U32 roi_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_lt_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_lt; + + struct { + RK_U32 roi_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_rb_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_rb; + + struct { + RK_U32 roi_qp_value : 7; + RK_U32 roi_qp_adj_mode : 1; + RK_U32 roi_pri : 5; + RK_U32 roi_en : 1; + RK_U32 reserved : 18; + } roi_base; + + struct { + RK_U32 roi_mdc_inter16 : 4; + RK_U32 roi_mdc_skip16 : 4; + RK_U32 roi_mdc_intra16 : 4; + RK_U32 roi0_mdc_inter32_hevc : 4; + RK_U32 roi0_mdc_skip32_hevc : 4; + RK_U32 roi0_mdc_intra32_hevc : 4; + RK_U32 roi0_mdc_dpth_hevc : 1; + RK_U32 reserved : 7; + } roi_mdc; +} Vepu510RoiRegion; + +typedef struct Vepu510RoiCfg_t { + /* 0x00001080 reg1056 */ + struct { + RK_U32 fmdc_adju_inter16 : 4; + RK_U32 fmdc_adju_skip16 : 4; + RK_U32 fmdc_adju_intra16 : 4; + RK_U32 fmdc_adju_inter32 : 4; + RK_U32 fmdc_adju_skip32 : 4; + RK_U32 fmdc_adju_intra32 : 4; + RK_U32 fmdc_adj_pri : 5; + RK_U32 reserved : 3; + } fmdc_adj0; + + /* 0x00001084 reg1057 */ + struct { + RK_U32 fmdc_adju_inter8 : 4; + RK_U32 fmdc_adju_skip8 : 4; + RK_U32 fmdc_adju_intra8 : 4; + RK_U32 reserved : 20; + } fmdc_adj1; + + RK_U32 reserved_1058; + + /* 0x0000108c reg1059 */ + struct { + RK_U32 bmap_en : 1; + RK_U32 bmap_pri : 5; + RK_U32 bmap_qpmin : 6; + RK_U32 bmap_qpmax : 6; + RK_U32 bmap_mdc_dpth : 1; + RK_U32 reserved : 13; + } bmap_cfg; + + /* 0x00001090 reg1060 - 0x0000110c reg1091 */ + Vepu510RoiRegion regions[8]; +} Vepu510RoiCfg; + +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct Vepu510ControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 h264_cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 reserved : 2; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } version; + + /* 0x00000004 - 0x0000000c */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 3; + RK_U32 reserved : 21; + } enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } enc_clr; + + /* 0x00000018 reg6 */ + struct { + RK_U32 vswm_lcnt_soft : 14; + RK_U32 vswm_fcnt_soft : 8; + RK_U32 reserved : 2; + RK_U32 dvbm_ack_soft : 1; + RK_U32 dvbm_ack_sel : 1; + RK_U32 dvbm_inf_sel : 1; + RK_U32 reserved1 : 5; + } vs_ldly; + + /* 0x0000001c */ + RK_U32 reserved_7; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 vslc_done_en : 1; + RK_U32 vbsf_oflw_en : 1; + RK_U32 vbuf_lens_en : 1; + RK_U32 enc_err_en : 1; + RK_U32 vsrc_err_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 lkt_err_stop_en : 1; + RK_U32 lkt_force_stop_en : 1; + RK_U32 jslc_done_en : 1; + RK_U32 jbsf_oflw_en : 1; + RK_U32 jbuf_lens_en : 1; + RK_U32 dvbm_err_en : 1; + RK_U32 reserved : 16; + } int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 vslc_done_msk : 1; + RK_U32 vbsf_oflw_msk : 1; + RK_U32 vbuf_lens_msk : 1; + RK_U32 enc_err_msk : 1; + RK_U32 vsrc_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_int_msk : 1; + RK_U32 lkt_err_stop_msk : 1; + RK_U32 lkt_force_stop_msk : 1; + RK_U32 jslc_done_msk : 1; + RK_U32 jbsf_oflw_msk : 1; + RK_U32 jbuf_lens_msk : 1; + RK_U32 dvbm_err_msk : 1; + RK_U32 reserved : 16; + } int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 vslc_done_clr : 1; + RK_U32 vbsf_oflw_clr : 1; + RK_U32 vbuf_lens_clr : 1; + RK_U32 enc_err_clr : 1; + RK_U32 vsrc_err_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_int_clr : 1; + RK_U32 lkt_err_stop_clr : 1; + RK_U32 lkt_force_stop_clr : 1; + RK_U32 jslc_done_clr : 1; + RK_U32 jbsf_oflw_clr : 1; + RK_U32 jbuf_lens_clr : 1; + RK_U32 dvbm_err_clr : 1; + RK_U32 reserved : 16; + } int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 vslc_done_sta : 1; + RK_U32 vbsf_oflw_sta : 1; + RK_U32 vbuf_lens_sta : 1; + RK_U32 enc_err_sta : 1; + RK_U32 vsrc_err_sta : 1; + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_int_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + RK_U32 jslc_done_sta : 1; + RK_U32 jbsf_oflw_sta : 1; + RK_U32 jbuf_lens_sta : 1; + RK_U32 dvbm_err_sta : 1; + RK_U32 reserved : 16; + } int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 jpeg_bus_edin : 4; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 4; + RK_U32 reserved : 8; + RK_U32 lktw_bus_edin : 4; + RK_U32 rec_nfbc_bus_edin : 4; + } dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 reserved : 16; + RK_U32 axi_brsp_cke : 10; + RK_U32 reserved1 : 6; + } dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 reserved : 8; + } enc_wdg; + + /* 0x0000003c - 0x0000004c */ + RK_U32 reserved15_19[5]; + + /* 0x00000050 reg20 */ + struct { + RK_U32 idle_en_core : 1; + RK_U32 idle_en_axi : 1; + RK_U32 idle_en_ahb : 1; + RK_U32 reserved : 29; + } enc_idle_en; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 rfpr_err_e : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 link_err_stop : 1; + RK_U32 reserved : 27; + } opt_strg; + + /* 0x00000058 reg22 */ + union { + struct { + RK_U32 tq8_ckg : 1; + RK_U32 tq4_ckg : 1; + RK_U32 bits_ckg_8x8 : 1; + RK_U32 bits_ckg_4x4_1 : 1; + RK_U32 bits_ckg_4x4_0 : 1; + RK_U32 inter_mode_ckg : 1; + RK_U32 inter_ctrl_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 reserved : 22; + } h264; + struct { + RK_U32 recon32_ckg : 1; + RK_U32 iqit32_ckg : 1; + RK_U32 q32_ckg : 1; + RK_U32 t32_ckg : 1; + RK_U32 cabac32_ckg : 1; + RK_U32 recon16_ckg : 1; + RK_U32 iqit16_ckg : 1; + RK_U32 q16_ckg : 1; + RK_U32 t16_ckg : 1; + RK_U32 cabac16_ckg : 1; + RK_U32 recon8_ckg : 1; + RK_U32 iqit8_ckg : 1; + RK_U32 q8_ckg : 1; + RK_U32 t8_ckg : 1; + RK_U32 cabac8_ckg : 1; + RK_U32 recon4_ckg : 1; + RK_U32 iqit4_ckg : 1; + RK_U32 q4_ckg : 1; + RK_U32 t4_ckg : 1; + RK_U32 cabac4_ckg : 1; + RK_U32 intra32_ckg : 1; + RK_U32 intra16_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 reserved : 7; + } hevc; + } rdo_ckg; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } core_id; +} Vepu510ControlCfg; + +/* 0x00000270 reg156 - 0x0000039c reg231 */ +typedef struct Vepu510FrmCommon_t { + /* 0x00000270 reg156 - 0x0000027c reg159 */ + vepu510_online online_addr; + + /* 0x00000280 reg160 */ + RK_U32 adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 colmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 colmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 adr_bsbs; + + /* 0x000002bc reg175 */ + RK_U32 bsbr_addr; + + /* 0x000002c0 reg176 */ + RK_U32 lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 ebuft_addr; + + /* 0x000002cc reg179 */ + RK_U32 ebufb_addr; + + /* 0x000002d0 reg180 */ + RK_U32 rfpt_h_addr; + + /* 0x000002d4 reg181 */ + RK_U32 rfpb_h_addr; + + /* 0x000002d8 reg182 */ + RK_U32 rfpt_b_addr; + + /* 0x000002dc reg183 */ + RK_U32 adr_rfpb_b; + + /* 0x000002e0 reg184 */ + RK_U32 adr_smear_rd; + + /* 0x000002e4 reg185 */ + RK_U32 adr_smear_wr; + + /* 0x000002e8 reg186 */ + RK_U32 adr_roir; + + /* 0x2ec - 0x2fc */ + RK_U32 reserved187_191[5]; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 reserved : 3; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur_hevc : 5; + RK_U32 log2_ctu_num_hevc : 5; + RK_U32 reserved1 : 6; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } enc_pic; + + /* 0x00000304 reg193 */ + struct { + RK_U32 dchs_txid : 2; + RK_U32 dchs_rxid : 2; + RK_U32 dchs_txe : 1; + RK_U32 dchs_rxe : 1; + RK_U32 reserved : 2; + RK_U32 dchs_dly : 8; + RK_U32 dchs_ofst : 10; + RK_U32 reserved1 : 6; + } dual_core; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 frm_id_match : 1; + RK_U32 reserved : 7; + RK_U32 ch_id : 2; + RK_U32 vrsp_rtn_en : 1; + RK_U32 vinf_req_en : 1; + RK_U32 reserved1 : 12; + } enc_id; + + /* 0x0000030c reg195 */ + RK_U32 bsp_size; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_rcne : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved : 21; + } src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 cr_force_value : 8; + RK_U32 cb_force_value : 8; + RK_U32 chroma_force_en : 1; + RK_U32 reserved : 9; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 tile4x4_en : 1; + RK_U32 reserved1 : 2; + } src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 21; + RK_U32 reserved : 11; + } src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } src_strd1; + + /* 0x33c - 0x34c */ + RK_U32 reserved207_211[5]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 reserved : 10; + RK_U32 rc_ctu_num : 20; + } rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } rc_tgt; + + /* 0x35c */ + RK_U32 reserved_215; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } sli_cnum; + + /* 0x0000036c reg219 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } vbs_pad; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cime_srch_dwnh : 4; + RK_U32 cime_srch_uph : 4; + RK_U32 cime_srch_rgtw : 4; + RK_U32 cime_srch_lftw : 4; + RK_U32 dlt_frm_num : 16; + } me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 srgn_max_num : 7; + RK_U32 cime_dist_thre : 13; + RK_U32 rme_srch_h : 2; + RK_U32 rme_srch_v : 2; + RK_U32 rme_dis : 3; + RK_U32 reserved : 1; + RK_U32 fme_dis : 3; + RK_U32 reserved1 : 1; + } me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cime_zero_thre : 13; + RK_U32 reserved : 15; + RK_U32 fme_prefsu_en : 2; + RK_U32 colmv_stor_hevc : 1; + RK_U32 colmv_load_hevc : 1; + } me_cach; + + /* 0x37c - 0x39c */ + RK_U32 reserved223_231[9]; +} Vepu510FrmCommon; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x0000110c reg1091 */ +typedef struct Vepu510RcRoi_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 24; + RK_U32 qpmap_mode : 2; + } roi_qthd3; + + /* 0x00001040 reg1040 */ + RK_U32 reserved_1040; + + /* 0x00001044 reg1041 - 0x00001050 reg1044 */ + RK_U8 aq_tthd[16]; + + /* 0x00001054 reg1045 */ + struct { + RK_S32 aq_stp_s0 : 5; + RK_S32 aq_stp_0t1 : 5; + RK_S32 aq_stp_1t2 : 5; + RK_S32 aq_stp_2t3 : 5; + RK_S32 aq_stp_3t4 : 5; + RK_S32 aq_stp_4t5 : 5; + RK_S32 reserved : 2; + } aq_stp0; + + /* 0x00001058 reg1046 */ + struct { + RK_S32 aq_stp_5t6 : 5; + RK_S32 aq_stp_6t7 : 5; + RK_S32 aq_stp_7t8 : 5; + RK_S32 aq_stp_8t9 : 5; + RK_S32 aq_stp_9t10 : 5; + RK_S32 aq_stp_10t11 : 5; + RK_S32 reserved : 2; + } aq_stp1; + + /* 0x0000105c reg1047 */ + struct { + RK_S32 aq_stp_11t12 : 5; + RK_S32 aq_stp_12t13 : 5; + RK_S32 aq_stp_13t14 : 5; + RK_S32 aq_stp_14t15 : 5; + RK_S32 aq_stp_b15 : 5; + RK_U32 reserved : 7; + } aq_stp2; + + /* 0x00001060 reg1048 */ + struct { + RK_U32 aq16_rnge : 4; + RK_U32 aq32_rnge : 4; + RK_U32 aq8_rnge : 5; + RK_U32 aq16_dif0 : 5; + RK_U32 aq16_dif1 : 5; + RK_U32 reserved : 1; + RK_U32 aq_cme_en : 1; + RK_U32 aq_subj_cme_en : 1; + RK_U32 aq_rme_en : 1; + RK_U32 aq_subj_rme_en : 1; + RK_U32 reserved1 : 4; + } aq_clip; + + /* 0x00001064 reg1049 */ + struct { + RK_U32 madi_th0 : 8; + RK_U32 madi_th1 : 8; + RK_U32 madi_th2 : 8; + RK_U32 reserved : 8; + } madi_st_thd; + + /* 0x00001068 reg1050 */ + struct { + RK_U32 madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_th1 : 12; + RK_U32 reserved1 : 4; + } madp_st_thd0; + + /* 0x0000106c reg1051 */ + struct { + RK_U32 madp_th2 : 12; + RK_U32 reserved : 20; + } madp_st_thd1; + + /* 0x1070 - 0x1078 */ + RK_U32 reserved1052_1054[3]; + + /* 0x0000107c reg1055 */ + struct { + RK_U32 chrm_klut_ofst : 4; + RK_U32 reserved : 4; + RK_U32 inter_chrm_dist_multi : 6; + RK_U32 reserved1 : 18; + } klut_ofst; + + /*0x00001080 reg1056 - 0x0000110c reg1091 */ + Vepu510RoiCfg roi_cfg; +} Vepu510RcRoi; + +/* class: scaling list */ +/* 0x00002200 reg2176- 0x00002584 reg2401*/ +typedef struct Vepu510SclCfg_t { + /* 0x2200 - 0x221F, valid for h.264/h.h265, jpeg no use */ + RK_U32 tu8_intra_y[16]; + RK_U32 tu8_intra_u[16]; /* tu8_inter_y[16] for h.264 */ + + /* 0x2220 - 0x2584, valid for h.265 only */ + RK_U32 tu8_intra_v[16]; + RK_U32 tu8_inter_y[16]; + RK_U32 tu8_inter_u[16]; + RK_U32 tu8_inter_v[16]; + RK_U32 tu16_intra_y_ac[16]; + RK_U32 tu16_intra_u_ac[16]; + RK_U32 tu16_intra_v_ac[16]; + RK_U32 tu16_inter_y_ac[16]; + RK_U32 tu16_inter_u_ac[16]; + RK_U32 tu16_inter_v_ac[16]; + RK_U32 tu32_intra_y_ac[16]; + RK_U32 tu32_inter_y_ac[16]; + + /* 0x2580 */ + struct { + RK_U32 tu16_intra_y_dc : 8; + RK_U32 tu16_intra_u_dc : 8; + RK_U32 tu16_intra_v_dc : 8; + RK_U32 tu16_inter_y_dc : 8; + } tu_dc0; + + /* 0x2584 */ + struct { + RK_U32 tu16_inter_u_dc : 8; + RK_U32 tu16_inter_v_dc : 8; + RK_U32 tu32_intra_y_dc : 8; + RK_U32 tu32_inter_y_dc : 8; + } tu_dc1; +} Vepu510SclCfg; + +/* class: st */ +/* 0x00004000 reg4096 - 0x0000424c reg4243*/ +typedef struct Vepu510Status_t { + /* 0x00004000 reg4096 */ + RK_U32 bs_lgth_l32; + + /* 0x00004004 reg4097 */ + struct { + RK_U32 bs_lgth_h8 : 8; + RK_U32 reserved : 8; + RK_U32 sse_l16 : 16; + } st_sse_bsl; + + /* 0x00004008 reg4098 */ + RK_U32 sse_h32; + + /* 0x0000400c reg4099 */ + RK_U32 qp_sum; + + /* 0x00004010 reg4100 */ + struct { + RK_U32 sao_cnum : 16; + RK_U32 sao_ynum : 16; + } st_sao; + + /* 0x00004014 reg4101 */ + RK_U32 rdo_head_bits; + + /* 0x00004018 reg4102 */ + struct { + RK_U32 rdo_head_bits_h8 : 8; + RK_U32 reserved : 8; + RK_U32 rdo_res_bits_l16 : 16; + } st_head_res_bl; + + /* 0x0000401c reg4103 */ + RK_U32 rdo_res_bits_h24; + + /* 0x00004020 reg4104 */ + struct { + RK_U32 st_enc : 2; + RK_U32 st_sclr : 1; + RK_U32 isp_src_oflw : 1; + RK_U32 vepu_src_oflw : 1; + RK_U32 vepu_fcnt_nmch : 1; + RK_U32 vepu_fbd_err : 5; + RK_U32 reserved : 5; + RK_U32 dvbm_finf_wful : 1; + RK_U32 dvbm_linf_wful : 1; + RK_U32 dvbm_fcnt_late : 1; + RK_U32 dvbm_fcnt_early : 1; + RK_U32 dvbm_isp_oflw : 1; + RK_U32 dvbm_vepu_oflw : 1; + RK_U32 isp_time_out : 1; + RK_U32 dvbm_vsrc_fcnt : 1; + RK_U32 reserved1 : 8; + } st_enc; + + /* 0x00004024 reg4105 */ + struct { + RK_U32 fnum_cfg_done : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 fnum_enc_done : 8; + } st_lkt; + + /* 0x00004028 reg4106 */ + struct { + RK_U32 reserved : 4; + RK_U32 node_addr : 28; + } st_nadr; + + /* 0x0000402c reg4107 */ + struct { + RK_U32 bsbw_ovfl : 1; + RK_U32 reserved : 2; + RK_U32 bsbw_addr : 28; + RK_U32 reserved1 : 1; + } st_bsb; + + /* 0x00004030 reg4108 */ + struct { + RK_U32 axib_idl : 8; + RK_U32 axib_ovfl : 8; + RK_U32 axib_err : 8; + RK_U32 axir_err : 8; + } st_bus; + + /* 0x00004034 reg4109 */ + struct { + RK_U32 sli_num_video : 6; + RK_U32 sli_num_jpeg : 6; + RK_U32 reserved : 4; + RK_U32 bpkt_num_video : 7; + RK_U32 bpkt_lst_video : 1; + RK_U32 bpkt_num_jpeg : 7; + RK_U32 bpkt_lst_jpeg : 1; + } st_snum; + + /* 0x00004038 reg4110 */ + struct { + RK_U32 sli_len : 31; + RK_U32 sli_lst : 1; + } st_slen; + + /* 0x403c - reg4111 */ + struct { + RK_U32 task_id_proc : 12; + RK_U32 task_id_done : 12; + RK_U32 task_done : 1; + RK_U32 task_lkt_err : 3; + RK_U32 reserved : 4; + } st_link_task; + + /* 0x4040 - 0x405c */ + RK_U32 reserved4111_4119[8]; + + /* 0x00004060 reg4120 */ + struct { + RK_U32 sli_len_jpeg : 31; + RK_U32 sli_lst_jpeg : 1; + } st_slen_jpeg; + + /* 0x00004064 reg4121 */ + RK_U32 jpeg_head_bits_l32; + + /* 0x00004068 reg4122 */ + struct { + RK_U32 jpeg_head_bits_h8 : 1; + RK_U32 reserved : 31; + } st_bsl_h8_jpeg; + + /* 0x0000406c reg4123 */ + struct { + RK_U32 jbsbw_ovfl : 1; + RK_U32 reserved : 2; + RK_U32 jbsbw_addr : 28; + RK_U32 reserved1 : 1; + } st_jbsb; + + /* 0x4070 - 0x407c */ + RK_U32 reserved4124_4127[4]; + + /* 0x00004080 reg4128 */ + struct { + RK_U32 pnum_p64 : 17; + RK_U32 reserved : 15; + } st_pnum_p64; + + /* 0x00004084 reg4129 */ + struct { + RK_U32 pnum_p32 : 19; + RK_U32 reserved : 13; + } st_pnum_p32; + + /* 0x00004088 reg4130 */ + struct { + RK_U32 pnum_p16 : 21; + RK_U32 reserved : 11; + } st_pnum_p16; + + /* 0x0000408c reg4131 */ + struct { + RK_U32 pnum_p8 : 23; + RK_U32 reserved : 9; + } st_pnum_p8; + + /* 0x00004090 reg4132 */ + struct { + RK_U32 pnum_i32 : 19; + RK_U32 reserved : 13; + } st_pnum_i32; + + /* 0x00004094 reg4133 */ + struct { + RK_U32 pnum_i16 : 21; + RK_U32 reserved : 11; + } st_pnum_i16; + + /* 0x00004098 reg4134 */ + struct { + RK_U32 pnum_i8 : 23; + RK_U32 reserved : 9; + } st_pnum_i8; + + /* 0x0000409c reg4135 */ + struct { + RK_U32 pnum_i4 : 23; + RK_U32 reserved : 9; + } st_pnum_i4; + + /* 0x000040a0 reg4136 */ + struct { + RK_U32 num_b16 : 23; + RK_U32 reserved : 9; + } st_bnum_b16; + + /* 0x000040a4 reg4137 */ + struct { + RK_U32 rdo_smear_cnt0 : 8; + RK_U32 rdo_smear_cnt1 : 8; + RK_U32 rdo_smear_cnt2 : 8; + RK_U32 rdo_smear_cnt3 : 8; + } st_smear_cnt; + + /* 0x000040a8 reg4138 */ + RK_U32 madi16_sum; + + /* 0x000040ac reg4139 */ + RK_U32 madi32_sum; + + /* 0x000040b0 reg4140 */ + RK_U32 madp16_sum; + + /* 0x40b4 - 0x40bc */ + RK_U32 reserved4141_4143[3]; + + /* 0x000040c0 reg4144 */ + struct { + RK_U32 madi_th_lt_cnt0 : 16; + RK_U32 madi_th_lt_cnt1 : 16; + } st_madi_lt_num0; + + /* 0x000040c4 reg4145 */ + struct { + RK_U32 madi_th_lt_cnt2 : 16; + RK_U32 madi_th_lt_cnt3 : 16; + } st_madi_lt_num1; + + /* 0x000040c8 reg4146 */ + struct { + RK_U32 madi_th_rt_cnt0 : 16; + RK_U32 madi_th_rt_cnt1 : 16; + } st_madi_rt_num0; + + /* 0x000040cc reg4147 */ + struct { + RK_U32 madi_th_rt_cnt2 : 16; + RK_U32 madi_th_rt_cnt3 : 16; + } st_madi_rt_num1; + + /* 0x000040d0 reg4148 */ + struct { + RK_U32 madi_th_lb_cnt0 : 16; + RK_U32 madi_th_lb_cnt1 : 16; + } st_madi_lb_num0; + + /* 0x000040d4 reg4149 */ + struct { + RK_U32 madi_th_lb_cnt2 : 16; + RK_U32 madi_th_lb_cnt3 : 16; + } st_madi_lb_num1; + + /* 0x000040d8 reg4150 */ + struct { + RK_U32 madi_th_rb_cnt0 : 16; + RK_U32 madi_th_rb_cnt1 : 16; + } st_madi_rb_num0; + + /* 0x000040dc reg4151 */ + struct { + RK_U32 madi_th_rb_cnt2 : 16; + RK_U32 madi_th_rb_cnt3 : 16; + } st_madi_rb_num1; + + /* 0x000040e0 reg4152 */ + struct { + RK_U32 madp_th_lt_cnt0 : 16; + RK_U32 madp_th_lt_cnt1 : 16; + } st_madp_lt_num0; + + /* 0x000040e4 reg4153 */ + struct { + RK_U32 madp_th_lt_cnt2 : 16; + RK_U32 madp_th_lt_cnt3 : 16; + } st_madp_lt_num1; + + /* 0x000040e8 reg4154 */ + struct { + RK_U32 madp_th_rt_cnt0 : 16; + RK_U32 madp_th_rt_cnt1 : 16; + } st_madp_rt_num0; + + /* 0x000040ec reg4155 */ + struct { + RK_U32 madp_th_rt_cnt2 : 16; + RK_U32 madp_th_rt_cnt3 : 16; + } st_madp_rt_num1; + + /* 0x000040f0 reg4156 */ + struct { + RK_U32 madp_th_lb_cnt0 : 16; + RK_U32 madp_th_lb_cnt1 : 16; + } st_madp_lb_num0; + + /* 0x000040f4 reg4157 */ + struct { + RK_U32 madp_th_lb_cnt2 : 16; + RK_U32 madp_th_lb_cnt3 : 16; + } st_madp_lb_num1; + + /* 0x000040f8 reg4158 */ + struct { + RK_U32 madp_th_rb_cnt0 : 16; + RK_U32 madp_th_rb_cnt1 : 16; + } st_madp_rb_num0; + + /* 0x000040fc reg4159 */ + struct { + RK_U32 madp_th_rb_cnt2 : 16; + RK_U32 madp_th_rb_cnt3 : 16; + } st_madp_rb_num1; + + /* 0x00004100 reg4160 */ + struct { + RK_U32 cmv_th_lt_cnt0 : 16; + RK_U32 cmv_th_lt_cnt1 : 16; + } st_cmv_lt_num0; + + /* 0x00004104 reg4161 */ + struct { + RK_U32 cmv_th_lt_cnt2 : 16; + RK_U32 cmv_th_lt_cnt3 : 16; + } st_cmv_lt_num1; + + /* 0x00004108 reg4162 */ + struct { + RK_U32 cmv_th_rt_cnt0 : 16; + RK_U32 cmv_th_rt_cnt1 : 16; + } st_cmv_rt_num0; + + /* 0x0000410c reg4163 */ + struct { + RK_U32 cmv_th_rt_cnt2 : 16; + RK_U32 cmv_th_rt_cnt3 : 16; + } st_cmv_rt_num1; + + /* 0x00004110 reg4164 */ + struct { + RK_U32 cmv_th_lb_cnt0 : 16; + RK_U32 cmv_th_lb_cnt1 : 16; + } st_cmv_lb_num0; + + /* 0x00004114 reg4165 */ + struct { + RK_U32 cmv_th_lb_cnt2 : 16; + RK_U32 cmv_th_lb_cnt3 : 16; + } st_cmv_lb_num1; + + /* 0x00004118 reg4166 */ + struct { + RK_U32 cmv_th_rb_cnt0 : 16; + RK_U32 cmv_th_rb_cnt1 : 16; + } st_cmv_rb_num0; + + /* 0x0000411c reg4167 */ + struct { + RK_U32 cmv_th_rb_cnt2 : 16; + RK_U32 cmv_th_rb_cnt3 : 16; + } st_cmv_rb_num1; + + /* 0x00004120 reg4168 */ + struct { + RK_U32 org_y_r_max_value : 8; + RK_U32 org_y_r_min_value : 8; + RK_U32 org_u_g_max_value : 8; + RK_U32 org_u_g_min_value : 8; + } st_vsp_org_value0; + + /* 0x00004124 reg4169 */ + struct { + RK_U32 org_v_b_max_value : 8; + RK_U32 org_v_b_min_value : 8; + RK_U32 reserved : 16; + } st_vsp_org_value1; + + /* 0x4128 - 0x412c */ + RK_U32 reserved4170_4171[2]; + + /* 0x00004130 reg4172 */ + RK_U32 dsp_y_sum; + + /* 0x00004134 reg4173 */ + RK_U32 acc_zero_mv; + + /* 0x00004138 reg4174 */ + RK_U32 acc_dist0; + + /* 0x0000413c reg4175 */ + RK_U32 acc_block_num; + + /* 0x00004140 reg4176 */ + struct { + RK_U32 num0_point_skin : 15; + RK_U32 acc_cmplx_num : 17; + } st_skin_sum0; + + /* 0x00004144 reg4177 */ + struct { + RK_U32 num1_point_skin : 15; + RK_U32 acc_cover16_num : 17; + } st_skin_sum1; + + /* 0x00004148 reg4178 */ + struct { + RK_U32 num2_point_skin : 15; + RK_U32 acc_bndry16_num : 17; + } st_skin_sum2; + + /* 0x0000414c reg4179 */ + RK_U32 num0_grdnt_point_dep0; + + /* 0x00004150 reg4180 */ + RK_U32 num1_grdnt_point_dep0; + + /* 0x00004154 reg4181 */ + RK_U32 num2_grdnt_point_dep0; + + /* 0x4158 - 0x417c */ + RK_U32 reserved4182_4191[10]; + + /* 0x00004180 reg4192 - 0x0000424c reg4243*/ + RK_U32 st_b8_qp[52]; +} Vepu510Status; + +/* class: dbg/st/axipn */ +/* 0x00005000 reg5120 - 0x0000230 reg5260*/ +//TODO: +typedef struct Vepu510Dbg_t { + /* 0x00005000 reg5120 */ + struct { + RK_U32 vsp0_pos_x : 16; + RK_U32 vsp0_pos_y : 16; + } st_ppl_pos_vsp0; + + /* 0x00005004 reg5121 */ + struct { + RK_U32 vsp1_pos_x : 16; + RK_U32 vsp1_pos_y : 16; + } st_ppl_pos_vsp1; + + /* 0x00005008 reg5122 */ + struct { + RK_U32 cme_pos_x : 16; + RK_U32 cme_pos_y : 16; + } st_ppl_pos_cme; + + /* 0x0000500c reg5123 */ + struct { + RK_U32 swin_cmd_x : 16; + RK_U32 swin_cmd_y : 16; + } st_ppl_cmd_swin; + + /* 0x00005010 reg5124 */ + struct { + RK_U32 swin_pos_x : 16; + RK_U32 swin_pos_y : 16; + } st_ppl_pos_swin; + + /* 0x00005014 reg5125 */ + struct { + RK_U32 pren_pos_x : 16; + RK_U32 pren_pos_y : 16; + } st_ppl_pos_pren; + + /* 0x00005018 reg5126 */ + struct { + RK_U32 rfme_pos_x : 16; + RK_U32 rfme_pos_y : 16; + } st_ppl_pos_rfme; + + /* 0x0000501c reg5127 */ + struct { + RK_U32 rdo_pos_x : 16; + RK_U32 rdo_pos_y : 16; + } st_ppl_pos_rdo; + + /* 0x00005020 reg5128 */ + struct { + RK_U32 lpf_pos_x : 16; + RK_U32 lpf_pos_y : 16; + } st_ppl_pos_lpf; + + /* 0x00005024 reg5129 */ + struct { + RK_U32 etpy_pos_x : 16; + RK_U32 etpy_pos_y : 16; + } st_ppl_pos_etpy; + + /* 0x00005028 reg5130 */ + struct { + RK_U32 vsp0_pos_x : 16; + RK_U32 vsp0_pos_y : 16; + } st_ppl_pos_jsp0; + + /* 0x0000502c reg5131 */ + struct { + RK_U32 vsp1_pos_x : 16; + RK_U32 vsp1_pos_y : 16; + } st_ppl_pos_jsp1; + + /* 0x00005030 reg5132 */ + struct { + RK_U32 jpeg_pos_x : 16; + RK_U32 jpeg_pos_y : 16; + } st_ppl_pos_jpeg; + + /* 0x5034 - 0x503c */ + RK_U32 reserved5133_5135[3]; + /* 0x00005040 reg5136 */ + struct { + RK_U32 vsp0_org_err : 1; + RK_U32 vsp0_vsld_err : 1; + RK_U32 pp0_pp1_err : 1; + RK_U32 vsp0_cmd_err : 1; + RK_U32 reserved : 24; + RK_U32 vsp0_wrk : 1; + RK_U32 vsp0_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_vsp0; + + /* 0x00005044 reg5137 */ + struct { + RK_U32 vsp1_org_err : 1; + RK_U32 vsp1_rdo_err : 1; + RK_U32 reserved : 26; + RK_U32 vsp1_wrk : 1; + RK_U32 vsp1_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_vsp1; + + /* 0x00005048 reg5138 */ + struct { + RK_U32 cme_org_err : 1; + RK_U32 cme_roi_err : 1; + RK_U32 cme_win_err : 1; + RK_U32 cme_cmmv_err : 1; + RK_U32 cme_smvp_err : 1; + RK_U32 cme_meiw_err : 1; + RK_U32 cme_dist_err : 1; + RK_U32 cme_rdo_err : 1; + RK_U32 cme_madp_err : 1; + RK_U32 cme_mv_err : 1; + RK_U32 reserved : 18; + RK_U32 cme_wrk : 1; + RK_U32 cme_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_cme; + + /* 0x0000504c reg5139 */ + struct { + RK_U32 swin_org_err : 1; + RK_U32 swin_ref_err : 1; + RK_U32 swin_cmd_err : 1; + RK_U32 reserved : 25; + RK_U32 swin_wrk : 1; + RK_U32 swin_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_swin; + + /* 0x00005050 reg5140 */ + struct { + RK_U32 swin_buff_ptr : 2; + RK_U32 swin_buff_num0 : 2; + RK_U32 swin_buff_num1 : 2; + RK_U32 swin_buff_num2 : 2; + RK_U32 reserved : 24; + } dbg_ppl_swin; + + /* 0x00005054 reg5141 */ + struct { + RK_U32 pnra_org_err : 1; + RK_U32 pnra_dist_err : 1; + RK_U32 pnra_olm_err : 1; + RK_U32 reserved : 25; + RK_U32 pnra_wrk : 1; + RK_U32 pnra_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_pren; + + /* 0x00005058 reg5142 */ + struct { + RK_U32 rfme_org_err : 1; + RK_U32 rfme_ref_err : 1; + RK_U32 rfme_cmmv_err : 1; + RK_U32 rfme_rfmv_err : 1; + RK_U32 rfme_tmvp_err : 1; + RK_U32 reserved : 23; + RK_U32 rfme_wrk : 1; + RK_U32 rfme_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_rfme; + + /* 0x0000505c reg5143 */ + struct { + RK_U32 rdo_org_err : 1; + RK_U32 rdo_ref_err : 1; + RK_U32 rdo_inf_err : 1; + RK_U32 rdo_roi_err : 1; + RK_U32 rdo_rfmv_err : 1; + RK_U32 rdo_lbfr_err : 1; + RK_U32 rdo_lbfw_err : 1; + RK_U32 rdo_tmvp_rd_err : 1; + RK_U32 rdo_tmvp_wr_err : 1; + RK_U32 rdo_st_err : 1; + RK_U32 rdo_pnra_err : 1; + RK_U32 rdo_lpf_err : 1; + RK_U32 rdo_ent_err : 1; + RK_U32 reserved : 15; + RK_U32 rdo_wrk : 1; + RK_U32 rdo_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_rdo; + + /* 0x00005060 reg5144 */ + struct { + RK_U32 lpf_org_err : 1; + RK_U32 lpf_lbfr_err : 1; + RK_U32 lpf_lbfw_err : 1; + RK_U32 lpf_rcol_err : 1; + RK_U32 reserved : 24; + RK_U32 lpf_wrk : 1; + RK_U32 lpf_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_lpf; + + /* 0x00005064 reg5145 */ + struct { + RK_U32 etpy_bsw_err : 1; + RK_U32 reserved : 27; + RK_U32 etpy_wrk : 1; + RK_U32 etpy_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_etpy; + + /* 0x00005068 reg5146 */ + struct { + RK_U32 jsp0_org_err : 1; + RK_U32 jsp0_vsld_err : 1; + RK_U32 pp0_pp1_err : 1; + RK_U32 jsp0_cmd_err : 1; + RK_U32 reserved : 24; + RK_U32 jsp0_wrk : 1; + RK_U32 jsp0_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_jsp0; + + /* 0x0000506c reg5147 */ + struct { + RK_U32 jsp1_org_err : 1; + RK_U32 jsp1_madi_err : 1; + RK_U32 reserved : 26; + RK_U32 jsp1_wrk : 1; + RK_U32 jsp1_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_jsp1; + + /* 0x00005070 reg5148 */ + struct { + RK_U32 jpeg_org_err : 1; + RK_U32 reserved : 27; + RK_U32 jpeg_wrk : 1; + RK_U32 jpeg_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_jpeg; + + /* 0x00005074 reg5149 */ + struct { + RK_U32 dma_brsp_idle : 1; + RK_U32 jpeg_frm_done : 1; + RK_U32 rdo_frm_done : 1; + RK_U32 lpf_frm_done : 1; + RK_U32 ent_frm_done : 1; + RK_U32 ppl_ctrl_done : 1; + RK_U32 criw_frm_done : 1; + RK_U32 meiw_frm_done : 1; + RK_U32 smiw_frm_done : 1; + RK_U32 strg_rsrc_done : 1; + RK_U32 reserved : 18; + RK_U32 frm_wrk : 1; + RK_U32 frm_tout : 1; + RK_U32 reserved1 : 2; + } dbg_tctrl0; + + /* 0x00005078 reg5150 */ + struct { + RK_U32 pp0_cmd_vld : 1; + RK_U32 pp0_cmd_rdy : 1; + RK_U32 pp0_cmd_eid : 1; + RK_U32 cme_madp_vld : 1; + RK_U32 cme_madp_rdy0 : 1; + RK_U32 cmd_madp_rdy1 : 1; + RK_U32 cme_mv16_vld : 1; + RK_U32 cmd_mv16_rdy : 1; + RK_U32 swin_cmd_vld : 1; + RK_U32 swin_cmd_rdy : 1; + RK_U32 pnra_olm_vld : 1; + RK_U32 pnra_olm_rdy : 1; + RK_U32 lpf_rcol_vld : 1; + RK_U32 lpf_rcol_rdy : 1; + RK_U32 bsw_dat_vld : 1; + RK_U32 bsw_dat_rdy : 1; + RK_U32 slc_fifo_full : 1; + RK_U32 reserved : 15; + } dbg_tctrl1; + + /* 0x507c */ + RK_U32 reserved_5151; + + /* 0x00005080 reg5152 */ + struct { + RK_U32 sli_num : 15; + RK_U32 reserved : 17; + } st_sli_num; + + /* 0x5084 - 0x50fc */ + RK_U32 reserved5153_5183[31]; + + /* 0x00005100 reg5184 */ + struct { + RK_U32 empty_oafifo : 1; + RK_U32 full_cmd_oafifo : 1; + RK_U32 full_data_oafifo : 1; + RK_U32 empty_iafifo : 1; + + RK_U32 full_cmd_iafifo : 1; + RK_U32 full_info_iafifo : 1; + RK_U32 fbd_brq_st : 4; + RK_U32 fbd_hdr_vld : 1; + RK_U32 fbd_bmng_end : 1; + + RK_U32 nfbd_req_st : 4; + RK_U32 acc_axi_cmd : 8; + RK_U32 reserved : 8; + } dbg_pp_st; + + /* 0x00005104 reg5185 */ + struct { + RK_U32 r_ena_lambd : 1; + RK_U32 r_fst_swinw_end : 1; + RK_U32 r_swinw_end : 1; + RK_U32 r_cnt_swinw : 1; + + RK_U32 r_dspw_end : 1; + RK_U32 r_dspw_cnt : 1; + RK_U32 i_sjgen_work : 1; + RK_U32 r_end_rspgen : 1; + + RK_U32 r_cost_gate : 1; + RK_U32 r_ds_gate : 1; + RK_U32 r_mvp_gate : 1; + RK_U32 i_smvp_arrdy : 1; + + RK_U32 i_smvp_arvld : 1; + RK_U32 i_stptr_wrdy : 1; + RK_U32 i_stptr_wvld : 1; + RK_U32 i_rdy_atf : 1; + + RK_U32 i_vld_atf : 1; + RK_U32 i_rdy_bmv16 : 1; + RK_U32 i_vld_bmv16 : 1; + RK_U32 i_wr_dsp : 1; + + RK_U32 i_rdy_dsp : 1; + RK_U32 i_vld_dsp : 1; + RK_U32 r_rdy_org : 1; + RK_U32 i_vld_org : 1; + + RK_U32 i_rdy_state : 1; + RK_U32 i_vld_state : 1; + RK_U32 i_rdy_madp : 1; + RK_U32 i_vld_madp : 1; + + RK_U32 i_rdy_diff : 1; + RK_U32 i_vld_diff : 1; + RK_U32 reserved : 2; + } dbg_cime_st; + + /* 0x00005108 reg5186 */ + RK_U32 swin_dbg_inf; + + /* 0x0000510c reg5187 */ + struct { + RK_U32 bbrq_cmps_left_len2 : 1; + RK_U32 bbrq_cmps_left_len1 : 1; + RK_U32 cmps_left_len0 : 1; + RK_U32 bbrq_rdy2 : 1; + RK_U32 dcps_vld2 : 1; + RK_U32 bbrq_rdy1 : 1; + RK_U32 dcps_vld1 : 1; + RK_U32 bbrq_rdy0 : 1; + RK_U32 dcps_vld0 : 1; + RK_U32 hb_rdy2 : 1; + RK_U32 bbrq_vld2 : 1; + RK_U32 hb_rdy1 : 1; + RK_U32 bbrq_vld1 : 1; + RK_U32 hb_rdy0 : 1; + RK_U32 bbrq_vld0 : 1; + RK_U32 idle_msb2 : 1; + RK_U32 idle_msb1 : 1; + RK_U32 idle_msb0 : 1; + RK_U32 cur_state_dcps : 1; + RK_U32 cur_state_bbrq : 1; + RK_U32 cur_state_hb : 1; + RK_U32 cke_bbrq_dcps : 1; + RK_U32 cke_dcps : 1; + RK_U32 cke_bbrq : 1; + RK_U32 rdy_lwcd_rsp : 1; + RK_U32 vld_lwcd_rsp : 1; + RK_U32 rdy_lwcd_req : 1; + RK_U32 vld_lwcd_req : 1; + RK_U32 rdy_lwrsp : 1; + RK_U32 vld_lwrsp : 1; + RK_U32 rdy_lwreq : 1; + RK_U32 vld_lwreq : 1; + } dbg_fbd_hhit0; + + /* 0x00005110 reg5188 */ + RK_U32 rfme_dbg_inf; + + /* 0x00005114 reg5189 */ + struct { + RK_U32 mscnt_clr : 1; + RK_U32 reserved : 31; + } dbg_cach_clr; + + /* 0x00005118 reg5190 */ + RK_U32 l1_mis; + + /* 0x0000511c reg5191 */ + RK_U32 l2_mis; + + /* 0x00005120 reg5192 */ + RK_U32 rdo_dbg0; + + /* 0x00005124 reg5193 */ + RK_U32 rdo_dbg1; + + /* 0x00005128 reg5194 */ + struct { + RK_U32 h264_sh_st_cs : 4; + RK_U32 rsd_st_cs : 4; + RK_U32 h264_sd_st_cs : 5; + RK_U32 etpy_rdy : 1; + RK_U32 reserved : 18; + } dbg_etpy; + + /* 0x0000512c reg5195 */ + struct { + RK_U32 chl_aw_vld : 10; + RK_U32 chl_aw_rdy : 10; + RK_U32 aw_vld_arb : 1; + RK_U32 aw_rdy_arb : 1; + RK_U32 aw_vld_crosclk : 1; + RK_U32 aw_rdy_crosclk : 1; + RK_U32 aw_rdy_mmu : 1; + RK_U32 aw_vld_mmu : 1; + RK_U32 aw_rdy_axi : 1; + RK_U32 aw_vld_axi : 1; + RK_U32 reserved : 4; + } dbg_dma_aw; + + /* 0x00005130 reg5196 */ + struct { + RK_U32 chl_w_vld : 10; + RK_U32 chl_w_rdy : 10; + RK_U32 w_vld_arb : 1; + RK_U32 w_rdy_arb : 1; + RK_U32 w_vld_crosclk : 1; + RK_U32 w_rdy_crosclk : 1; + RK_U32 w_rdy_mmu : 1; + RK_U32 w_vld_mmu : 1; + RK_U32 w_rdy_axi : 1; + RK_U32 w_vld_axi : 1; + RK_U32 reserved : 4; + } dbg_dma_w; + + /* 0x00005134 reg5197 */ + struct { + RK_U32 chl_ar_vld : 9; + RK_U32 chl_ar_rdy : 9; + RK_U32 reserved : 2; + RK_U32 ar_vld_arb : 1; + RK_U32 ar_rdy_arb : 1; + RK_U32 ar_vld_crosclk : 1; + RK_U32 ar_rdy_crosclk : 1; + RK_U32 ar_rdy_mmu : 1; + RK_U32 ar_vld_mmu : 1; + RK_U32 ar_rdy_axi : 1; + RK_U32 ar_vld_axi : 1; + RK_U32 reserved1 : 4; + } dbg_dma_ar; + + /* 0x00005138 reg5198 */ + struct { + RK_U32 chl_r_vld : 9; + RK_U32 chl_r_rdy : 9; + RK_U32 reserved : 2; + RK_U32 r_vld_arb : 1; + RK_U32 r_rdy_arb : 1; + RK_U32 r_vld_crosclk : 1; + RK_U32 r_rdy_crosclk : 1; + RK_U32 r_rdy_mmu : 1; + RK_U32 r_vld_mmu : 1; + RK_U32 r_rdy_axi : 1; + RK_U32 r_vld_axi : 1; + RK_U32 b_rdy_mmu : 1; + RK_U32 b_vld_mmu : 1; + RK_U32 b_rdy_axi : 1; + RK_U32 b_vld_axi : 1; + } dbg_dma_r; + + /* 0x513c */ + RK_U32 reserved_5199; + + /* 0x00005140 reg5200 */ + struct { + RK_U32 bsw_fsm_stus : 4; + RK_U32 bsw_aw_full : 1; + RK_U32 bsw_rdy_ent : 1; + RK_U32 bsw_vld_ent : 1; + RK_U32 jpg_bsw_stus : 4; + RK_U32 jpg_aw_full : 1; + RK_U32 jpg_bsw_rdy : 1; + RK_U32 jpg_bsw_vld : 1; + RK_U32 crpw_fsm_stus : 3; + RK_U32 hdwr_rdy : 1; + RK_U32 hdwr_vld : 1; + RK_U32 bdwr_rdy : 1; + RK_U32 bdwr_vld : 1; + RK_U32 nfbc_rdy : 1; + RK_U32 nfbc_vld : 1; + RK_U32 dsp_fsm_stus : 2; + RK_U32 dsp_wr_flg : 1; + RK_U32 dsp_rsy : 1; + RK_U32 dsp_vld : 1; + RK_U32 lpfw_fsm_stus : 3; + RK_U32 reserved : 1; + } dbg_dma_dbg1; + + /* 0x5144 */ + RK_U32 reserved_5201; + + /* 0x00005148 reg5202 */ + struct { + RK_U32 rdo_st : 20; + RK_U32 reserved : 12; + } dbg_rdo_st; + + /* 0x0000514c reg5203 */ + struct { + RK_U32 lpf_work : 1; + RK_U32 rdo_par_nrdy : 1; + RK_U32 rdo_rcn_nrdy : 1; + RK_U32 lpf_rcn_rdy : 1; + RK_U32 dblk_work : 1; + RK_U32 sao_work : 1; + RK_U32 reserved : 18; + RK_U32 tile_bdry_read : 1; + RK_U32 tile_bdry_write : 1; + RK_U32 tile_bdry_rrdy : 1; + RK_U32 rdo_read_tile_bdry : 1; + RK_U32 rdo_write_tile_bdry : 1; + RK_U32 reserved1 : 3; + } dbg_lpf; + + /* 0x5150 */ + RK_U32 reserved_5204; + + /* 0x00005154 reg5205 */ + RK_U32 dbg0_cache; + + /* 0x00005158 reg5206 */ + RK_U32 dbg1_cache; + + /* 0x0000515c reg5207 */ + RK_U32 dbg2_cache; + + /* 0x00005160 reg5208 */ + struct { + RK_U32 ebuf_diff_cmd : 8; + RK_U32 lbuf_lpf_ncnt : 7; + RK_U32 lbuf_lpf_cien : 1; + RK_U32 lbuf_rdo_ncnt : 7; + RK_U32 lbuf_rdo_cien : 1; + RK_U32 reserved : 8; + } dbg_lbuf0; + + /* 0x00005164 reg5209 */ + struct { + RK_U32 rvld_ebfr : 1; + RK_U32 rrdy_ebfr : 1; + RK_U32 arvld_ebfr : 1; + RK_U32 arrdy_ebfr : 1; + RK_U32 wvld_ebfw : 1; + RK_U32 wrdy_ebfw : 1; + RK_U32 awvld_ebfw : 1; + RK_U32 awrdy_ebfw : 1; + RK_U32 lpf_lbuf_rvld : 1; + RK_U32 lpf_lbuf_rrdy : 1; + RK_U32 lpf_lbuf_wvld : 1; + RK_U32 lpf_lbuf_wrdy : 1; + RK_U32 rdo_lbuf_rvld : 1; + RK_U32 rdo_lbuf_rrdy : 1; + RK_U32 rdo_lbuf_wvld : 1; + RK_U32 rdo_lbuf_wrdy : 1; + RK_U32 fme_lbuf_rvld : 1; + RK_U32 fme_lbuf_rrdy : 1; + RK_U32 cme_lbuf_rvld : 1; + RK_U32 cme_lbuf_rrdy : 1; + RK_U32 smear_lbuf_rvld : 1; + RK_U32 smear_lbuf_rrdy : 1; + RK_U32 smear_lbuf_wvld : 1; + RK_U32 smear_lbuf_wrdy : 1; + RK_U32 rdo_lbufw_flag : 1; + RK_U32 rdo_lbufr_flag : 1; + RK_U32 cme_lbufr_flag : 1; + RK_U32 reserved : 5; + } dbg_lbuf1; + + /* 0x00005168 reg5210 */ + struct { + RK_U32 dbg_isp_fcnt : 8; + RK_U32 dbg_isp_fcyc : 24; + } dbg_dvbm_isp0; + + /* 0x0000516c reg5211 */ + struct { + RK_U32 dbg_isp_lcnt : 14; + RK_U32 reserved : 1; + RK_U32 dbg_isp_ltgl : 1; + RK_U32 dbg_isp_fcnt : 8; + RK_U32 dbg_isp_oflw : 1; + RK_U32 dbg_isp_ftgl : 1; + RK_U32 dbg_isp_full : 1; + RK_U32 dbg_isp_work : 1; + RK_U32 dbg_isp_lvld : 1; + RK_U32 dbg_isp_lrdy : 1; + RK_U32 dbg_isp_fvld : 1; + RK_U32 dbg_isp_frdy : 1; + } dbg_dvbm_isp1; + + /* 0x00005170 reg5212 */ + struct { + RK_U32 dbg_bf0_isp_lcnt : 14; + RK_U32 dbg_bf0_isp_llst : 1; + RK_U32 dbg_bf0_isp_sofw : 1; + RK_U32 dbg_bf0_isp_fcnt : 8; + RK_U32 dbg_bf0_isp_pnt : 1; + RK_U32 reserved : 3; + RK_U32 dbg_bf0_vpu_pnt : 1; + RK_U32 reserved1 : 3; + } dbg_dvbm_buf0_inf0; + + /* 0x00005174 reg5213 */ + struct { + RK_U32 dbg_bf0_src_lcnt : 14; + RK_U32 dbg_bf0_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf0_vpu_lcnt : 14; + RK_U32 dbg_bf0_vpu_llst : 1; + RK_U32 dbg_bf0_vpu_vofw : 1; + } dbg_dvbm_buf0_inf1; + + /* 0x00005178 reg5214 */ + struct { + RK_U32 dbg_bf1_isp_lcnt : 14; + RK_U32 dbg_bf1_isp_llst : 1; + RK_U32 dbg_bf1_isp_sofw : 1; + RK_U32 dbg_bf1_isp_fcnt : 1; + RK_U32 reserved : 7; + RK_U32 dbg_bf1_isp_pnt : 1; + RK_U32 reserved1 : 3; + RK_U32 dbg_bf1_vpu_pnt : 1; + RK_U32 reserved2 : 3; + } dbg_dvbm_buf1_inf0; + + /* 0x0000517c reg5215 */ + struct { + RK_U32 dbg_bf1_src_lcnt : 14; + RK_U32 dbg_bf1_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf1_vpu_lcnt : 14; + RK_U32 dbg_bf1_vpu_llst : 1; + RK_U32 dbg_bf1_vpu_vofw : 1; + } dbg_dvbm_buf1_inf1; + + /* 0x00005180 reg5216 */ + struct { + RK_U32 dbg_bf2_isp_lcnt : 14; + RK_U32 dbg_bf2_isp_llst : 1; + RK_U32 dbg_bf2_isp_sofw : 1; + RK_U32 dbg_bf2_isp_fcnt : 1; + RK_U32 reserved : 7; + RK_U32 dbg_bf2_isp_pnt : 1; + RK_U32 reserved1 : 3; + RK_U32 dbg_bf2_vpu_pnt : 1; + RK_U32 reserved2 : 3; + } dbg_dvbm_buf2_inf0; + + /* 0x00005184 reg5217 */ + struct { + RK_U32 dbg_bf2_src_lcnt : 14; + RK_U32 dbg_bf2_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf2_vpu_lcnt : 14; + RK_U32 dbg_bf2_vpu_llst : 1; + RK_U32 dbg_bf2_vpu_vofw : 1; + } dbg_dvbm_buf2_inf1; + + /* 0x00005188 reg5218 */ + struct { + RK_U32 dbg_bf3_isp_lcnt : 14; + RK_U32 dbg_bf3_isp_llst : 1; + RK_U32 dbg_bf3_isp_sofw : 1; + RK_U32 dbg_bf3_isp_fcnt : 1; + RK_U32 reserved : 7; + RK_U32 dbg_bf3_isp_pnt : 1; + RK_U32 reserved1 : 3; + RK_U32 dbg_bf3_vpu_pnt : 1; + RK_U32 reserved2 : 3; + } dbg_dvbm_buf3_inf0; + + /* 0x0000518c reg5219 */ + struct { + RK_U32 dbg_bf3_src_lcnt : 14; + RK_U32 dbg_bf3_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf3_vpu_lcnt : 14; + RK_U32 dbg_bf3_vpu_llst : 1; + RK_U32 dbg_bf3_vpu_vofw : 1; + } dbg_dvbm_buf3_inf1; + + /* 0x00005190 reg5220 */ + struct { + RK_U32 dbg_isp_fptr : 3; + RK_U32 dbg_isp_full : 1; + RK_U32 dbg_src_fptr : 3; + RK_U32 reserved : 1; + RK_U32 dbg_vpu_fptr : 3; + RK_U32 dbg_vpu_empt : 1; + RK_U32 dbg_vpu_lvld : 1; + RK_U32 dbg_vpu_lrdy : 1; + RK_U32 dbg_vpu_fvld : 1; + RK_U32 dbg_vpu_frdy : 1; + RK_U32 dbg_fcnt_misp : 4; + RK_U32 dbg_fcnt_mvpu : 4; + RK_U32 dbg_fcnt_sofw : 4; + RK_U32 dbg_fcnt_vofw : 4; + } dbg_dvbm_ctrl; + + /* 0x5194 - 0x519c */ + RK_U32 reserved5221_5223[3]; + + /* 0x000051a0 reg5224 */ + RK_U32 dbg_dvbm_buf0_yadr; + + /* 0x000051a4 reg5225 */ + RK_U32 dbg_dvbm_buf0_cadr; + + /* 0x000051a8 reg5226 */ + RK_U32 dbg_dvbm_buf1_yadr; + + /* 0x000051ac reg5227 */ + RK_U32 dbg_dvbm_buf1_cadr; + + /* 0x000051b0 reg5228 */ + RK_U32 dbg_dvbm_buf2_yadr; + + /* 0x000051b4 reg5229 */ + RK_U32 dbg_dvbm_buf2_cadr; + + /* 0x000051b8 reg5230 */ + RK_U32 dbg_dvbm_buf3_yadr; + + /* 0x000051bc reg5231 */ + RK_U32 dbg_dvbm_buf3_cadr; + + /* 0x000051c0 reg5232 */ + struct { + RK_U32 dchs_rx_cnt : 11; + RK_U32 dchs_rx_id : 2; + RK_U32 dchs_rx_en : 1; + RK_U32 dchs_rx_ack : 1; + RK_U32 dchs_rx_req : 1; + RK_U32 dchs_tx_cnt : 11; + RK_U32 dchs_tx_id : 2; + RK_U32 dchs_tx_en : 1; + RK_U32 dchs_tx_ack : 1; + RK_U32 dchs_tx_req : 1; + } dbg_dchs_intfc; + + /* 0x000051c4 reg5233 */ + struct { + RK_U32 lpfw_tx_cnt : 11; + RK_U32 lpfw_tx_en : 1; + RK_U32 crpw_tx_cnt : 11; + RK_U32 crpw_tx_en : 1; + RK_U32 dual_err_updt : 1; + RK_U32 dlyc_fifo_oflw : 1; + RK_U32 dlyc_tx_vld : 1; + RK_U32 dlyc_tx_rdy : 1; + RK_U32 dlyc_tx_empty : 1; + RK_U32 dchs_tx_idle : 1; + RK_U32 dchs_tx_asy : 1; + RK_U32 dchs_tx_syn : 1; + } dbg_dchs_tx_inf0; + + /* 0x000051c8 reg5234 */ + struct { + RK_U32 criw_tx_cnt : 11; + RK_U32 criw_tx_en : 1; + RK_U32 smrw_tx_cnt : 11; + RK_U32 smrw_tx_en : 1; + RK_U32 reserved : 8; + } dbg_dchs_tx_inf1; + + /* 0x000051cc reg5235 */ + struct { + RK_U32 dual_rx_cnt : 11; + RK_U32 dual_rx_id : 2; + RK_U32 dual_rx_en : 1; + RK_U32 dual_rx_syn : 1; + RK_U32 dual_rx_lock : 1; + RK_U32 dual_lpfr_dule : 1; + RK_U32 dual_cime_dule : 1; + RK_U32 dual_clomv_dule : 1; + RK_U32 dual_smear_dule : 1; + RK_U32 reserved : 12; + } dbg_dchs_rx_inf0; + + /* 0x51d0 - 0x51fc */ + RK_U32 reserved5236_5247[12]; + + /* 0x00005200 reg5248 */ + RK_U32 frame_cyc; + + /* 0x00005204 reg5249 */ + RK_U32 vsp0_fcyc; + + /* 0x00005208 reg5250 */ + RK_U32 vsp1_fcyc; + + /* 0x0000520c reg5251 */ + RK_U32 cme_fcyc; + + /* 0x00005210 reg5252 */ + RK_U32 ldr_fcyc; + + /* 0x00005214 reg5253 */ + RK_U32 rfme_fcyc; + + /* 0x00005218 reg5254 */ + RK_U32 fme_fcyc; + + /* 0x0000521c reg5255 */ + RK_U32 rdo_fcyc; + + /* 0x00005220 reg5256 */ + RK_U32 lpf_fcyc; + + /* 0x00005224 reg5257 */ + RK_U32 etpy_fcyc; + + /* 0x00005228 reg5258 */ + RK_U32 jsp0_fcyc; + + /* 0x0000522c reg5259 */ + RK_U32 jsp1_fcyc; + + /* 0x00005230 reg5260 */ + RK_U32 jpeg_fcyc; +} Vepu510Dbg; + +/* ROI block configuration */ +typedef struct Vepu510H264RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_skip : 4; + RK_U32 mdc_adju_intra : 4; + RK_U32 reserved : 12; +} Vepu510H264RoiBlkCfg; + +typedef struct Vepu510H265RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 reserved : 12; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_skip : 4; + RK_U32 mdc_adju_intra : 4; +} Vepu510H265RoiBlkCfg; + +typedef struct Vepu510NpuOut_t { + RK_S32 found_objects; + /* npu object flag: one byte for each block16x16 */ + RK_U8 *object_seg_map; +} Vepu510NpuOut; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vepu510_set_roi(void *roi_reg_base, MppEncROICfg * roi, RK_S32 w, + RK_S32 h); + +#ifdef __cplusplus +} +#endif + +#endif /* VEPU510_COMMON_H */ diff --git a/mpp/hal/rkenc/common/vepu511_common.c b/mpp/hal/rkenc/common/vepu511_common.c new file mode 100644 index 000000000..cb10791e1 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu511_common.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vepu511_common" + +#include + +#include "kmpp_obj.h" +#include "kmpp_buffer.h" + +#include "mpp_log.h" +#include "mpp_common.h" +#include "vepu511_common.h" +#include "jpege_syntax.h" +#include "vepu5xx_common.h" +#include "hal_enc_task.h" +#include "mpp_frame_impl.h" +#include "mpp_packet.h" +#include "mpp_debug.h" +#include "mpp_mem.h" + +MPP_RET vepu511_set_osd(Vepu511OsdCfg * cfg) +{ + Vepu511Osd *regs = (Vepu511Osd *) (cfg->reg_base); + MppEncOSDData3 *osd_ptr = cfg->osd_data3; + Vepu511OsdRegion *osd_regions = ®s->osd_regions[0]; + MppEncOSDRegion3 *region = osd_ptr->region; + RK_U32 i = 0; + + if (NULL == osd_regions) { + mpp_err_f("invalid reg_regions %p\n", osd_regions); + } + + memset(osd_regions, 0, sizeof(Vepu511OsdRegion) * 8); + if (osd_ptr->num_region > 8) { + mpp_err_f("do NOT support more than 8 regions invalid num %d\n", + osd_ptr->num_region); + mpp_assert(osd_ptr->num_region <= 8); + return MPP_NOK; + } + + for (i = 0; i < osd_ptr->num_region; i++, region++) { + Vepu511OsdRegion *reg = ®s->osd_regions[i]; + VepuFmtCfg fmt_cfg; + MppFrameFormat fmt = region->fmt; + KmppBuffer buffer = NULL; + KmppBufCfg buf_cfg = NULL; + + vepu5xx_set_fmt(&fmt_cfg, fmt); + reg->cfg0.osd_en = region->enable; + reg->cfg0.osd_range_trns_en = region->range_trns_en; + reg->cfg0.osd_range_trns_sel = region->range_trns_sel; + reg->cfg0.osd_fmt = fmt_cfg.format; + reg->cfg0.osd_rbuv_swap = region->rbuv_swap; + reg->cfg1.osd_lt_xcrd = region->lt_x; + reg->cfg1.osd_lt_ycrd = region->lt_y; + reg->cfg2.osd_rb_xcrd = region->rb_x; + reg->cfg2.osd_rb_ycrd = region->rb_y; + + reg->cfg1.osd_endn = region->osd_endn; + reg->cfg5.osd_stride = region->stride; + reg->cfg5.osd_ch_ds_mode = region->ch_ds_mode; + reg->cfg0.osd_alpha_swap = region->alpha_cfg.alpha_swap; + reg->cfg0.osd_fg_alpha = region->alpha_cfg.fg_alpha; + reg->cfg0.osd_fg_alpha_sel = region->alpha_cfg.fg_alpha_sel; + reg->cfg0.osd_qp_adj_en = region->qp_cfg.qp_adj_en; + reg->cfg8.osd_qp_adj_sel = region->qp_cfg.qp_adj_sel; + reg->cfg8.osd_qp = region->qp_cfg.qp; + reg->cfg8.osd_qp_max = region->qp_cfg.qp_max; + reg->cfg8.osd_qp_min = region->qp_cfg.qp_min; + reg->cfg8.osd_qp_prj = region->qp_cfg.qp_prj; + + kmpp_obj_get_by_sptr_f(&buffer, ®ion->osd_buf); + if (buffer) { + buf_cfg = kmpp_buffer_to_cfg(buffer); + kmpp_buf_cfg_get_fd(buf_cfg, (RK_S32 *)®->osd_st_addr); + } + memcpy(reg->lut, region->lut, sizeof(region->lut)); + } + + regs->osd_whi_cfg0.osd_csc_yr = 77; + regs->osd_whi_cfg0.osd_csc_yg = 150; + regs->osd_whi_cfg0.osd_csc_yb = 29; + + regs->osd_whi_cfg1.osd_csc_ur = -43; + regs->osd_whi_cfg1.osd_csc_ug = -85; + regs->osd_whi_cfg1.osd_csc_ub = 128; + + regs->osd_whi_cfg2.osd_csc_vr = 128; + regs->osd_whi_cfg2.osd_csc_vg = -107; + regs->osd_whi_cfg2.osd_csc_vb = -21; + + regs->osd_whi_cfg3.osd_csc_ofst_y = 0; + regs->osd_whi_cfg3.osd_csc_ofst_u = 128; + regs->osd_whi_cfg3.osd_csc_ofst_v = 128; + + return MPP_OK; +} + +MPP_RET vepu511_set_roi(Vepu511RoiCfg *roi_reg_base, MppEncROICfg * roi, RK_S32 w, RK_S32 h) +{ + MppEncROIRegion *region = roi->regions; + Vepu511RoiCfg *roi_cfg = (Vepu511RoiCfg *)roi_reg_base; + Vepu511RoiRegion *reg_regions = &roi_cfg->regions[0]; + MPP_RET ret = MPP_NOK; + RK_S32 i = 0; + + memset(reg_regions, 0, sizeof(Vepu511RoiRegion) * 8); + if (NULL == roi_cfg || NULL == roi) { + mpp_err_f("invalid buf %p roi %p\n", roi_cfg, roi); + goto DONE; + } + + if (roi->number > VEPU511_MAX_ROI_NUM) { + mpp_err_f("invalid region number %d\n", roi->number); + goto DONE; + } + + /* check region config */ + ret = MPP_OK; + for (i = 0; i < (RK_S32) roi->number; i++, region++) { + if (region->x + region->w > w || region->y + region->h > h) + ret = MPP_NOK; + + if (region->intra > 1 || region->qp_area_idx >= VEPU511_MAX_ROI_NUM || + region->area_map_en > 1 || region->abs_qp_en > 1) + ret = MPP_NOK; + + if ((region->abs_qp_en && region->quality > 51) || + (!region->abs_qp_en && (region->quality > 51 || region->quality < -51))) + ret = MPP_NOK; + + if (ret) { + mpp_err_f("region %d invalid param:\n", i); + mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n", + region->x, region->y, region->w, region->h, w, h); + mpp_err_f("force intra %d qp area index %d\n", + region->intra, region->qp_area_idx); + mpp_err_f("abs qp mode %d value %d\n", + region->abs_qp_en, region->quality); + goto DONE; + } + + reg_regions->roi_pos_lt.roi_lt_x = MPP_ALIGN(region->x, 16) >> 4; + reg_regions->roi_pos_lt.roi_lt_y = MPP_ALIGN(region->y, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_x = MPP_ALIGN(region->x + region->w, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_y = MPP_ALIGN(region->y + region->h, 16) >> 4; + reg_regions->roi_base.roi_qp_value = region->quality; + reg_regions->roi_base.roi_qp_adj_mode = region->abs_qp_en; + reg_regions->roi_base.roi_en = 1; + reg_regions->roi_base.roi_pri = 0x1f; + if (region->intra) { + reg_regions->roi_mdc0.h265.roi_mdc_intra16 = 1; + reg_regions->roi_mdc1.roi_mdc_intra32 = 1; + } + reg_regions++; + } + +DONE: + return ret; +} + + diff --git a/mpp/hal/rkenc/common/vepu511_common.h b/mpp/hal/rkenc/common/vepu511_common.h new file mode 100644 index 000000000..74a4646b2 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu511_common.h @@ -0,0 +1,2262 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef VEPU511_COMMON_H +#define VEPU511_COMMON_H + +#include "rk_venc_cmd.h" +#include "mpp_device.h" + +#define VEPU511_CTL_OFFSET (0 * sizeof(RK_U32)) /* 0x00000000 reg0000 - 0x00000060 reg0024 */ +#define VEPU511_FRAME_OFFSET (156 * sizeof(RK_U32)) /* 0x00000270 reg0156 - 0x000003fc reg0255 */ +#define VEPU511_RC_ROI_OFFSET (1024 * sizeof(RK_U32)) /* 0x00001000 reg1024 - 0x00001160 reg1112 */ +#define VEPU511_PARAM_OFFSET (1472 * sizeof(RK_U32)) /* 0x00001700 reg1472 - 0x000019cc reg1651 */ +#define VEPU511_SQI_OFFSET (2048 * sizeof(RK_U32)) /* 0x00002000 reg2048 - 0x0000216c reg2139 */ +#define VEPU511_SCL_JPGTBL_OFFSET (2176 * sizeof(RK_U32)) /* 0x00002200 reg2176 - 0x00002e1c reg2951 */ +#define VEPU511_OSD_OFFSET (3072 * sizeof(RK_U32)) /* 0x00003000 reg3072 - 0x00003264 reg3225 */ +#define VEPU511_STATUS_OFFSET (4096 * sizeof(RK_U32)) /* 0x00004000 reg4096 - 0x0000424c reg4243 */ +#define VEPU511_DBG_OFFSET (5120 * sizeof(RK_U32)) /* 0x00005000 reg5120 - 0x00005230 reg5260 */ +#define VEPU511_REG_BASE_HW_STATUS (0x2c) + +#define VEPU511_MAX_ROI_NUM 8 +#define VEPU511_SLICE_FIFO_LEN 8 + +#define REF_BODY_SIZE(w, h) MPP_ALIGN((((w) * (h) * 3 / 2) + 48 * MPP_MAX(w, h)), SZ_4K) +#define REF_WRAP_BODY_EXT_SIZE(w, h) MPP_ALIGN((240 * MPP_MAX(w, h)), SZ_4K) +#define REF_HEADER_SIZE(w, h) MPP_ALIGN((((w) * (h) / 64) + MPP_MAX(w, h) / 2), SZ_4K) +#define REF_WRAP_HEADER_EXT_SIZE(w, h) MPP_ALIGN((3 * MPP_MAX(w, h)), SZ_4K) + +typedef enum ref_type_e { + ST_REF_TO_ST, + ST_REF_TO_LT, + LT_REF_TO_ST, + LT_REF_TO_LT, +} RefType; + +typedef enum qbias_ofst_e { + IFRAME_THD0 = 0, + IFRAME_THD1, + IFRAME_THD2, + IFRAME_BIAS0, + IFRAME_BIAS1, + IFRAME_BIAS2, + IFRAME_BIAS3, + PFRAME_THD0, + PFRAME_THD1, + PFRAME_THD2, + PFRAME_IBLK_BIAS0, + PFRAME_IBLK_BIAS1, + PFRAME_IBLK_BIAS2, + PFRAME_IBLK_BIAS3, + PFRAME_PBLK_BIAS0, + PFRAME_PBLK_BIAS1, + PFRAME_PBLK_BIAS2, + PFRAME_PBLK_BIAS3 +} QbiasOfst; + +typedef enum aq_rnge_ofst_e { + AQ16_RNGE = 0, + AQ32_RNGE, + AQ8_RNGE, + AQ16_DIFF0, + AQ16_DIFF1 +} AqRngeOfst; + +typedef struct wrap_info { + RK_U32 bottom; + RK_U32 top; + RK_U32 cur_off; + RK_U32 pre_off; + RK_U32 size; + RK_U32 total_size; +} WrapInfo; + +typedef struct wrap_buf_info { + WrapInfo hdr_lt; + WrapInfo hdr; + WrapInfo body_lt; + WrapInfo body; +} WrapBufInfo; + +typedef struct Vepu511Online_t { + /* 0x00000270 reg156 */ + RK_U32 reg0156_adr_vsy_t; + /* 0x00000274 reg157 */ + RK_U32 reg0157_adr_vsc_t; + /* 0x00000278 reg158 */ + RK_U32 reg0158_adr_vsy_b; + /* 0x0000027c reg159 */ + RK_U32 reg0159_adr_vsc_b; +} vepu511_online; + +typedef struct Vepu511RoiRegion_t { + struct { + RK_U32 roi_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_lt_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_lt; + + struct { + RK_U32 roi_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_rb_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_rb; + + struct { + RK_U32 roi_qp_value : 7; + RK_U32 roi_qp_adj_mode : 1; + RK_U32 roi_pri : 5; + RK_U32 roi_en : 1; + RK_U32 reserved : 18; + } roi_base; + + union { + struct { + RK_U32 roi_mdc_intra16 : 4; + RK_U32 roi_mdc_inter16 : 4; + RK_U32 roi_mdc_split16 : 4; + RK_U32 roi_mdc_res_intra16 : 4; + RK_U32 roi_mdc_res_inter16 : 4; + RK_U32 roi_mdc_res_zeromv16 : 4; + RK_U32 roi_mdc_dpth_hevc : 1; + RK_U32 reserved : 7; + } h265; + + struct { + RK_U32 roi_mdc_intra16 : 4; + RK_U32 roi_mdc_inter16 : 4; + RK_U32 roi_mdc_skip16 : 4; + RK_U32 reserved : 20; + } h264; + } roi_mdc0; + + /* h265 used */ + struct { + RK_U32 roi_mdc_intra32 : 4; + RK_U32 roi_mdc_inter32 : 4; + RK_U32 roi_mdc_split32 : 4; + RK_U32 roi_mdc_res_intra32 : 4; + RK_U32 roi_mdc_res_inter32 : 4; + RK_U32 roi_mdc_res_zeromv32 : 4; + RK_U32 reserved : 8; + } roi_mdc1; +} Vepu511RoiRegion; + +/* + * Vepu511RoiCfg + */ +typedef struct Vepu511RoiCfg_t { + /* 0x00001090 reg1060 - 0x0000112c reg1099 */ + Vepu511RoiRegion regions[8]; +} Vepu511RoiCfg; + +/* class: scaling list */ +/* 0x00002200 reg2176- 0x00002584 reg2401: scale_iq */ +typedef struct Vepu511SclCfg_t { + /* 0x2200 - 0x221F, valid for h.264/h.h265, jpeg no use */ + RK_U32 tu8_intra_y[16]; + RK_U32 tu8_intra_u[16]; /* tu8_inter_y[16] for h.264 */ + + /* 0x2220 - 0x2584, valid for h.265 only */ + RK_U32 tu8_intra_v[16]; + RK_U32 tu8_inter_y[16]; + RK_U32 tu8_inter_u[16]; + RK_U32 tu8_inter_v[16]; + RK_U32 tu16_intra_y_ac[16]; + RK_U32 tu16_intra_u_ac[16]; + RK_U32 tu16_intra_v_ac[16]; + RK_U32 tu16_inter_y_ac[16]; + RK_U32 tu16_inter_u_ac[16]; + RK_U32 tu16_inter_v_ac[16]; + RK_U32 tu32_intra_y_ac[16]; + RK_U32 tu32_inter_y_ac[16]; + + /* 0x2580 */ + struct { + RK_U32 tu16_intra_y_dc : 8; + RK_U32 tu16_intra_u_dc : 8; + RK_U32 tu16_intra_v_dc : 8; + RK_U32 tu16_inter_y_dc : 8; + } tu_dc0; + + /* 0x2584 */ + struct { + RK_U32 tu16_inter_u_dc : 8; + RK_U32 tu16_inter_v_dc : 8; + RK_U32 tu32_intra_y_dc : 8; + RK_U32 tu32_inter_y_dc : 8; + } tu_dc1; +} Vepu511SclCfg; + +/* 0x00002590 - 0x00002c9c : scale_q */ +typedef struct Vepu511SclCfgExt_t { + /* 0x2590 - 0x268C, valid for h.264/h.h265, jpeg no use */ + RK_U32 tu8_intra_y[32]; + RK_U32 tu8_intra_u[32]; + + /* 0x2690 - 0x2C8C, valid for h.265 only */ + RK_U32 tu8_intra_v[32]; + RK_U32 tu8_inter_y[32]; + RK_U32 tu8_inter_u[32]; + RK_U32 tu8_inter_v[32]; + RK_U32 tu16_intra_y_ac[32]; + RK_U32 tu16_intra_u_ac[32]; + RK_U32 tu16_intra_v_ac[32]; + RK_U32 tu16_inter_y_ac[32]; + RK_U32 tu16_inter_u_ac[32]; + RK_U32 tu16_inter_v_ac[32]; + RK_U32 tu32_intra_y_ac[32]; + RK_U32 tu32_inter_y_ac[32]; + + /* 0x2C90 */ + struct { + RK_U32 tu16_intra_y_dc : 16; + RK_U32 tu16_intra_u_dc : 16; + } tu_dc0; + + /* 0x2C94 */ + struct { + RK_U32 tu16_intra_v_dc : 16; + RK_U32 tu16_inter_y_dc : 16; + } tu_dc1; + + /* 0x2C98 */ + struct { + RK_U32 tu16_inter_u_dc : 16; + RK_U32 tu16_inter_v_dc : 16; + } tu_dc2; + + /* 0x2C9C */ + struct { + RK_U32 tu32_intra_y_dc : 16; + RK_U32 tu32_inter_y_dc : 16; + } tu_dc3; +} Vepu511SclCfgExt; + +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct Vepu511ControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 h264_cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 jpeg_cap : 1; + RK_U32 reserved : 1; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } version; + + /* 0x00000004 - 0x0000000c */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 3; + RK_U32 reserved : 21; + } enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 dvbm_clr : 1; + RK_U32 reserved : 29; + } enc_clr; + + /* 0x00000018 reg6 */ + struct { + RK_U32 vswm_lcnt_soft : 14; + RK_U32 vswm_fcnt_soft : 8; + RK_U32 vswm_fsid_soft : 1; + RK_U32 reserved : 1; + RK_U32 dvbm_ack_soft : 1; + RK_U32 dvbm_ack_sel : 1; + RK_U32 dvbm_inf_sel : 1; + RK_U32 reserved1 : 5; + } vs_ldly; + + /* 0x0000001c */ + RK_U32 reserved_7; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 vslc_done_en : 1; + RK_U32 vbsf_oflw_en : 1; + RK_U32 vbuf_lens_en : 1; + RK_U32 enc_err_en : 1; + RK_U32 vsrc_err_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 lkt_err_stop_en : 1; + RK_U32 lkt_force_stop_en : 1; + RK_U32 jslc_done_en : 1; + RK_U32 jbsf_oflw_en : 1; + RK_U32 jbuf_lens_en : 1; + RK_U32 dvbm_err_en : 1; + RK_U32 reserved : 16; + } int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 vslc_done_msk : 1; + RK_U32 vbsf_oflw_msk : 1; + RK_U32 vbuf_lens_msk : 1; + RK_U32 enc_err_msk : 1; + RK_U32 vsrc_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_int_msk : 1; + RK_U32 lkt_err_stop_msk : 1; + RK_U32 lkt_force_stop_msk : 1; + RK_U32 jslc_done_msk : 1; + RK_U32 jbsf_oflw_msk : 1; + RK_U32 jbuf_lens_msk : 1; + RK_U32 dvbm_err_msk : 1; + RK_U32 reserved : 16; + } int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 vslc_done_clr : 1; + RK_U32 vbsf_oflw_clr : 1; + RK_U32 vbuf_lens_clr : 1; + RK_U32 enc_err_clr : 1; + RK_U32 vsrc_err_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_int_clr : 1; + RK_U32 lkt_err_stop_clr : 1; + RK_U32 lkt_force_stop_clr : 1; + RK_U32 jslc_done_clr : 1; + RK_U32 jbsf_oflw_clr : 1; + RK_U32 jbuf_lens_clr : 1; + RK_U32 dvbm_err_clr : 1; + RK_U32 reserved : 16; + } int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 vslc_done_sta : 1; + RK_U32 vbsf_oflw_sta : 1; + RK_U32 vbuf_lens_sta : 1; + RK_U32 enc_err_sta : 1; + RK_U32 vsrc_err_sta : 1; + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_int_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + RK_U32 jslc_done_sta : 1; + RK_U32 jbsf_oflw_sta : 1; + RK_U32 jbuf_lens_sta : 1; + RK_U32 dvbm_err_sta : 1; + RK_U32 reserved : 16; + } int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 jpeg_bus_edin : 4; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 4; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 rec_nfbc_bus_edin : 4; + } dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 jsrc_bus_edin : 4; + RK_U32 reserved : 12; + RK_U32 axi_brsp_cke : 13; + RK_U32 reserved1 : 3; + } dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 reserved : 8; + } enc_wdg; + + /* 0x0000003c reg15 */ + struct { + RK_U32 hurry_en : 1; + RK_U32 hurry_low : 3; + RK_U32 hurry_mid : 3; + RK_U32 hurry_high : 3; + RK_U32 qos_sub_e : 1; + RK_U32 reserved1 : 5; + RK_U32 qos_period : 16; + } qos_cfg; + + /* 0x00000040 reg16 */ + struct { + RK_U32 qos_ar_dprt : 4; + RK_U32 qos_ar_lprt : 4; + RK_U32 qos_ar_mprt : 4; + RK_U32 qos_ar_hprt : 4; + RK_U32 qos_aw_dprt : 4; + RK_U32 qos_aw_lprt : 4; + RK_U32 qos_aw_mprt : 4; + RK_U32 qos_aw_hprt : 4; + } qos_prty; + + /* 0x00000044 reg17 */ + RK_U32 hurry_thd_low; + + /* 0x00000048 reg18 */ + RK_U32 hurry_thd_mid; + + /* 0x0000004c reg19 */ + RK_U32 hurry_thd_high; + + /* 0x50 QOS_CHID */ + struct { + RK_U32 qos_prt_mmu : 4; + RK_U32 qos_prt_rfpr : 4; + RK_U32 reserved1 : 24; + } qos_chid; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 rfpr_err_e : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 link_err_stop : 1; + RK_U32 reserved : 27; + } opt_strg; + + /* 0x00000058 reg22 */ + union { + struct { + RK_U32 tq8_ckg : 1; + RK_U32 tq4_ckg : 1; + RK_U32 bits_ckg_8x8 : 1; + RK_U32 bits_ckg_4x4_1 : 1; + RK_U32 bits_ckg_4x4_0 : 1; + RK_U32 inter_mode_ckg : 1; + RK_U32 inter_ctrl_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 reserved : 22; + } rdo_ckg_h264; + + struct { + RK_U32 recon32_ckg : 1; + RK_U32 iqit32_ckg : 1; + RK_U32 q32_ckg : 1; + RK_U32 t32_ckg : 1; + RK_U32 cabac32_ckg : 1; + RK_U32 recon16_ckg : 1; + RK_U32 iqit16_ckg : 1; + RK_U32 q16_ckg : 1; + RK_U32 t16_ckg : 1; + RK_U32 cabac16_ckg : 1; + RK_U32 recon8_ckg : 1; + RK_U32 iqit8_ckg : 1; + RK_U32 q8_ckg : 1; + RK_U32 t8_ckg : 1; + RK_U32 cabac8_ckg : 1; + RK_U32 recon4_ckg : 1; + RK_U32 iqit4_ckg : 1; + RK_U32 q4_ckg : 1; + RK_U32 t4_ckg : 1; + RK_U32 cabac4_ckg : 1; + RK_U32 intra32_ckg : 1; + RK_U32 intra16_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 reserved : 7; + } rdo_ckg_hevc; + }; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } core_id; + + /* 0x00000060 reg24 */ + struct { + RK_U32 dvbm_en : 1; + RK_U32 src_badr_sel : 1; + RK_U32 dvbm_vpu_fskp : 1; + RK_U32 src_oflw_drop : 1; + RK_U32 dvbm_isp_cnct : 1; + RK_U32 dvbm_vepu_cnct : 1; + RK_U32 vepu_expt_type : 2; + RK_U32 vinf_dly_cycle : 8; + RK_U32 ybuf_full_mgn : 8; + RK_U32 ybuf_oflw_mgn : 8; + } dvbm_cfg; +} Vepu511ControlCfg; + +typedef struct Vepu511JpegRoi_t { + struct { + RK_U32 roi0_rdoq_start_x : 11; + RK_U32 roi0_rdoq_start_y : 11; + RK_U32 reserved : 3; + RK_U32 roi0_rdoq_level : 6; + RK_U32 roi0_rdoq_en : 1; + } roi_cfg0; + + struct { + RK_U32 roi0_rdoq_width_m1 : 11; + RK_U32 roi0_rdoq_height_m1 : 11; + /* the below 10 bits only for roi0 */ + RK_U32 reserved : 3; + RK_U32 frm_rdoq_level : 6; + RK_U32 frm_rdoq_en : 1; + } roi_cfg1; +} Vepu511JpegRoi; + +typedef struct Vepu511JpegTable_t { + /* 0x2ca0 - 0x2e1c */ + RK_U16 qua_tab0[64]; + RK_U16 qua_tab1[64]; + RK_U16 qua_tab2[64]; +} Vepu511JpegTable; + +/* class osd */ +typedef struct Vepu511OsdRegion_t { + struct { + RK_U32 osd_en : 1; + RK_U32 reserved : 4; + RK_U32 osd_qp_adj_en : 1; + RK_U32 osd_range_trns_en : 1; + RK_U32 osd_range_trns_sel : 1; + RK_U32 osd_fmt : 4; + RK_U32 osd_alpha_swap : 1; + RK_U32 osd_rbuv_swap : 1; + RK_U32 reserved1 : 8; + RK_U32 osd_fg_alpha : 8; + RK_U32 osd_fg_alpha_sel : 2; + } cfg0; + + struct { + RK_U32 osd_lt_xcrd : 14; + RK_U32 osd_lt_ycrd : 14; + RK_U32 osd_endn : 4; + } cfg1; + + struct { + RK_U32 osd_rb_xcrd : 14; + RK_U32 osd_rb_ycrd : 14; + RK_U32 reserved : 4; + } cfg2; + + RK_U32 osd_st_addr; + + RK_U32 reserved; + + struct { + RK_U32 osd_stride : 17; + RK_U32 reserved : 8; + RK_U32 osd_ch_ds_mode : 1; + RK_U32 reserved1 : 6; + } cfg5; + + RK_U8 lut[8]; + + /* only for h.264/h.h265, jpeg no use */ + struct { + RK_U32 osd_qp_adj_sel : 1; + RK_U32 osd_qp : 7; + RK_U32 osd_qp_max : 6; + RK_U32 osd_qp_min : 6; + RK_U32 osd_qp_prj : 5; + RK_U32 reserved : 7; + } cfg8; +} Vepu511OsdRegion; + +/* class: osd */ +/* 0x00003000 reg3072 - 0x00003134 reg3149 */ +typedef struct Vepu511Osd_t { + /* 0x00003000 reg3072 - 0x0000311c reg3143*/ + Vepu511OsdRegion osd_regions[8]; + + /* 0x00003120 reg3144 */ + struct { + RK_U32 osd_csc_yr : 9; + RK_U32 osd_csc_yg : 9; + RK_U32 osd_csc_yb : 9; + RK_U32 reserved : 5; + } osd_whi_cfg0; + + /* 0x00003124 reg3145 */ + struct { + RK_U32 osd_csc_ur : 9; + RK_U32 osd_csc_ug : 9; + RK_U32 osd_csc_ub : 9; + RK_U32 reserved : 5; + } osd_whi_cfg1; + + /* 0x00003128 reg3146 */ + struct { + RK_U32 osd_csc_vr : 9; + RK_U32 osd_csc_vg : 9; + RK_U32 osd_csc_vb : 9; + RK_U32 reserved : 5; + } osd_whi_cfg2; + + /* 0x0000312c reg3147 */ + struct { + RK_U32 osd_csc_ofst_y : 8; + RK_U32 osd_csc_ofst_u : 8; + RK_U32 osd_csc_ofst_v : 8; + RK_U32 reserved : 8; + } osd_whi_cfg3; +} Vepu511Osd; + +/* class: osd */ +/*0x00003000 reg3072 - 0x00003264 reg3225 */ +typedef struct Vepu511OsdComb_t { + /*0x00003000 reg3072 - 0x0000312c reg3147 */ + Vepu511Osd osd; + + /* 0x00003130 reg3148 - 0x00003134 reg3149 */ + RK_U32 reserve[2]; + + /*0x00003138 reg3150 - 0x00003264 reg3225 */ + Vepu511Osd jpeg_osd; +} Vepu511OsdComb; + +/* class: st */ +/* 0x00004000 reg4096 - 0x0000424c reg4243*/ +typedef struct Vepu511Status_t { + /* 0x00004000 reg4096 */ + RK_U32 bs_lgth_l32; + + /* 0x00004004 reg4097 */ + struct { + RK_U32 bs_lgth_h8 : 8; + RK_U32 st_rc_lst_dqp : 6; + RK_U32 reserved : 2; + RK_U32 sse_l16 : 16; + } st_sse_bsl; + + /* 0x00004008 reg4098 */ + RK_U32 sse_h32; + + /* 0x0000400c reg4099 */ + RK_U32 qp_sum; + + /* 0x00004010 reg4100 */ + struct { + RK_U32 sao_cnum : 16; + RK_U32 sao_ynum : 16; + } st_sao; + + /* 0x00004014 reg4101 */ + RK_U32 rdo_head_bits_l32; + + /* 0x00004018 reg4102 */ + struct { + RK_U32 rdo_head_bits_h8 : 8; + RK_U32 reserved : 8; + RK_U32 rdo_res_bits_l16 : 16; + } st_head_res_bl; + + /* 0x0000401c reg4103 */ + RK_U32 rdo_res_bits_h24; + + /* 0x00004020 reg4104 */ + struct { + RK_U32 st_enc : 2; + RK_U32 st_sclr : 1; + RK_U32 vepu_fbd_err : 1; + RK_U32 vepu_vsp_err : 1; + RK_U32 reserved : 3; + RK_U32 isp_src_oflw : 1; + RK_U32 vepu_src_oflw : 1; + RK_U32 vepu_sid_nmch : 1; + RK_U32 vepu_fcnt_nmch : 1; + RK_U32 reserved1 : 4; + RK_U32 dvbm_finf_wful : 1; + RK_U32 dvbm_linf_wful : 1; + RK_U32 dvbm_fsid_nmch : 1; + RK_U32 dvbm_fcnt_early : 1; + RK_U32 dvbm_fcnt_late : 1; + RK_U32 dvbm_isp_oflw : 1; + RK_U32 dvbm_vepu_oflw : 1; + RK_U32 isp_time_out : 1; + RK_U32 anti_info_oflw : 1; + RK_U32 anti_vsrc_oflw : 1; + RK_U32 reserved2 : 1; + RK_U32 dvbm_vsrc_sid : 1; + RK_U32 dvbm_vsrc_fcnt : 4; + } st_enc; + + /* 0x00004024 reg4105 */ + struct { + RK_U32 fnum_cfg_done : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 fnum_enc_done : 8; + } st_lkt; + + /* 0x00004028 reg4106 */ + RK_U32 node_addr; + + /* 0x0000402c reg4107 */ + RK_U32 vbsbw_addr; + + /* 0x00004030 reg4108 */ + struct { + RK_U32 axib_idl : 8; + RK_U32 axib_ovfl : 8; + RK_U32 axib_err : 8; + RK_U32 axir_err : 8; + } st_bus; + + /* 0x00004034 reg4109 */ + struct { + RK_U32 sli_num_video : 8; + RK_U32 sli_num_jpeg : 8; + RK_U32 bpkt_num_video : 7; + RK_U32 bpkt_lst_video : 1; + RK_U32 bpkt_num_jpeg : 7; + RK_U32 bpkt_lst_jpeg : 1; + } st_snum; + + /* 0x00004038 reg4110 */ + struct { + RK_U32 sli_len : 30; + RK_U32 sli_lst : 1; + RK_U32 sli_sid : 1; + } st_slen; + + /* 0x0000403c reg4111 */ + struct { + RK_U32 task_id_proc : 12; + RK_U32 task_id_done : 12; + RK_U32 task_done : 1; + RK_U32 task_lkt_err : 3; + RK_U32 reserved : 4; + } st_link_task; + + /* 0x00004040 reg4112 */ + struct { + RK_U32 eslf_nptr : 10; + RK_U32 eslf_empty : 1; + RK_U32 eslf_full : 1; + RK_U32 eslf_sid : 1; + RK_U32 reserved : 19; + } st_eslf_nptr; + + /* 0x00004044 reg4113 */ + struct { + RK_U32 vsrd_posy : 10; + RK_U32 reserved : 5; + RK_U32 vsrd_fend : 1; + RK_U32 vsrd_posy_jpeg : 10; + RK_U32 reserved1 : 5; + RK_U32 vsrd_fend_jpeg : 1; + } st_vlsd_rlvl; + + /* 0x00004048 reg4114 */ + struct { + RK_U32 eslf_nptr_jpeg : 10; + RK_U32 eslf_empty_jpeg : 1; + RK_U32 eslf_full_jpeg : 1; + RK_U32 eslf_sid_jpeg : 1; + RK_U32 reserved : 19; + } st_eslf_nptr_jpeg; + + /* 0x404c - 0x405c */ + RK_U32 reserved4115_4119[5]; + + /* 0x00004060 reg4120 */ + struct { + RK_U32 sli_len_jpeg : 30; + RK_U32 sli_lst_jpeg : 1; + RK_U32 sli_sid_jpeg : 1; + } st_slen_jpeg; + + /* 0x00004064 reg4121 */ + RK_U32 jpeg_head_bits_l32; + + /* 0x00004068 reg4122 */ + struct { + RK_U32 jpeg_head_bits_h8 : 1; + RK_U32 reserved : 31; + } st_bsl_h8_jpeg; + + /* 0x0000406c reg4123 */ + RK_U32 jbsbw_addr; + + /* 0x00004070 reg4124 */ + RK_U32 luma_pix_sum_od; + + /* 0x4074 - 0x407c */ + RK_U32 reserved4125_4127[3]; + + /* 0x00004080 reg4128 */ + struct { + RK_U32 pnum_p64 : 17; + RK_U32 reserved : 15; + } st_pnum_p64; + + /* 0x00004084 reg4129 */ + struct { + RK_U32 pnum_p32 : 19; + RK_U32 reserved : 13; + } st_pnum_p32; + + /* 0x00004088 reg4130 */ + struct { + RK_U32 pnum_p16 : 21; + RK_U32 reserved : 11; + } st_pnum_p16; + + /* 0x0000408c reg4131 */ + struct { + RK_U32 pnum_p8 : 23; + RK_U32 reserved : 9; + } st_pnum_p8; + + /* 0x00004090 reg4132 */ + struct { + RK_U32 pnum_i32 : 19; + RK_U32 reserved : 13; + } st_pnum_i32; + + /* 0x00004094 reg4133 */ + struct { + RK_U32 pnum_i16 : 21; + RK_U32 reserved : 11; + } st_pnum_i16; + + /* 0x00004098 reg4134 */ + struct { + RK_U32 pnum_i8 : 23; + RK_U32 reserved : 9; + } st_pnum_i8; + + /* 0x0000409c reg4135 */ + struct { + RK_U32 pnum_i4 : 23; + RK_U32 reserved : 9; + } st_pnum_i4; + + /* 0x000040a0 reg4136 */ + struct { + RK_U32 num_b16 : 23; + RK_U32 reserved : 9; + } st_bnum_b16; + + /* 0x40a4 */ + RK_U32 reserved_4137; + + /* 0x000040a8 reg4138 */ + RK_U32 madi16_sum; + + /* 0x000040ac reg4139 */ + RK_U32 madi32_sum; + + /* 0x000040b0 reg4140 */ + RK_U32 madp16_sum; + + /* 0x000040b4 reg4141 */ + struct { + RK_U32 rdo_smear_cnt0 : 10; + RK_U32 reserved : 6; + RK_U32 rdo_smear_cnt1 : 10; + RK_U32 reserved1 : 6; + } st_smear_cnt0; + + /* 0x000040b8 reg4142 */ + struct { + RK_U32 rdo_smear_cnt2 : 10; + RK_U32 reserved : 6; + RK_U32 rdo_smear_cnt3 : 10; + RK_U32 reserved1 : 6; + } st_smear_cnt1; + + /* 0x40bc */ + RK_U32 reserved_4143; + + /* 0x000040c0 reg4144 */ + struct { + RK_U32 madi_th_lt_cnt0 : 16; + RK_U32 madi_th_lt_cnt1 : 16; + } st_madi_lt_num0; + + /* 0x000040c4 reg4145 */ + struct { + RK_U32 madi_th_lt_cnt2 : 16; + RK_U32 madi_th_lt_cnt3 : 16; + } st_madi_lt_num1; + + /* 0x000040c8 reg4146 */ + struct { + RK_U32 madi_th_rt_cnt0 : 16; + RK_U32 madi_th_rt_cnt1 : 16; + } st_madi_rt_num0; + + /* 0x000040cc reg4147 */ + struct { + RK_U32 madi_th_rt_cnt2 : 16; + RK_U32 madi_th_rt_cnt3 : 16; + } st_madi_rt_num1; + + /* 0x000040d0 reg4148 */ + struct { + RK_U32 madi_th_lb_cnt0 : 16; + RK_U32 madi_th_lb_cnt1 : 16; + } st_madi_lb_num0; + + /* 0x000040d4 reg4149 */ + struct { + RK_U32 madi_th_lb_cnt2 : 16; + RK_U32 madi_th_lb_cnt3 : 16; + } st_madi_lb_num1; + + /* 0x000040d8 reg4150 */ + struct { + RK_U32 madi_th_rb_cnt0 : 16; + RK_U32 madi_th_rb_cnt1 : 16; + } st_madi_rb_num0; + + /* 0x000040dc reg4151 */ + struct { + RK_U32 madi_th_rb_cnt2 : 16; + RK_U32 madi_th_rb_cnt3 : 16; + } st_madi_rb_num1; + + /* 0x000040e0 reg4152 */ + struct { + RK_U32 madp_th_lt_cnt0 : 16; + RK_U32 madp_th_lt_cnt1 : 16; + } st_madp_lt_num0; + + /* 0x000040e4 reg4153 */ + struct { + RK_U32 madp_th_lt_cnt2 : 16; + RK_U32 madp_th_lt_cnt3 : 16; + } st_madp_lt_num1; + + /* 0x000040e8 reg4154 */ + struct { + RK_U32 madp_th_rt_cnt0 : 16; + RK_U32 madp_th_rt_cnt1 : 16; + } st_madp_rt_num0; + + /* 0x000040ec reg4155 */ + struct { + RK_U32 madp_th_rt_cnt2 : 16; + RK_U32 madp_th_rt_cnt3 : 16; + } st_madp_rt_num1; + + /* 0x000040f0 reg4156 */ + struct { + RK_U32 madp_th_lb_cnt0 : 16; + RK_U32 madp_th_lb_cnt1 : 16; + } st_madp_lb_num0; + + /* 0x000040f4 reg4157 */ + struct { + RK_U32 madp_th_lb_cnt2 : 16; + RK_U32 madp_th_lb_cnt3 : 16; + } st_madp_lb_num1; + + /* 0x000040f8 reg4158 */ + struct { + RK_U32 madp_th_rb_cnt0 : 16; + RK_U32 madp_th_rb_cnt1 : 16; + } st_madp_rb_num0; + + /* 0x000040fc reg4159 */ + struct { + RK_U32 madp_th_rb_cnt2 : 16; + RK_U32 madp_th_rb_cnt3 : 16; + } st_madp_rb_num1; + + /* 0x00004100 reg4160 */ + struct { + RK_U32 cmv_th_lt_cnt0 : 16; + RK_U32 cmv_th_lt_cnt1 : 16; + } st_cmv_lt_num0; + + /* 0x00004104 reg4161 */ + struct { + RK_U32 cmv_th_lt_cnt2 : 16; + RK_U32 cmv_th_lt_cnt3 : 16; + } st_cmv_lt_num1; + + /* 0x00004108 reg4162 */ + struct { + RK_U32 cmv_th_rt_cnt0 : 16; + RK_U32 cmv_th_rt_cnt1 : 16; + } st_cmv_rt_num0; + + /* 0x0000410c reg4163 */ + struct { + RK_U32 cmv_th_rt_cnt2 : 16; + RK_U32 cmv_th_rt_cnt3 : 16; + } st_cmv_rt_num1; + + /* 0x00004110 reg4164 */ + struct { + RK_U32 cmv_th_lb_cnt0 : 16; + RK_U32 cmv_th_lb_cnt1 : 16; + } st_cmv_lb_num0; + + /* 0x00004114 reg4165 */ + struct { + RK_U32 cmv_th_lb_cnt2 : 16; + RK_U32 cmv_th_lb_cnt3 : 16; + } st_cmv_lb_num1; + + /* 0x00004118 reg4166 */ + struct { + RK_U32 cmv_th_rb_cnt0 : 16; + RK_U32 cmv_th_rb_cnt1 : 16; + } st_cmv_rb_num0; + + /* 0x0000411c reg4167 */ + struct { + RK_U32 cmv_th_rb_cnt2 : 16; + RK_U32 cmv_th_rb_cnt3 : 16; + } st_cmv_rb_num1; + + /* 0x00004120 reg4168 */ + struct { + RK_U32 org_y_r_max_value : 8; + RK_U32 org_y_r_min_value : 8; + RK_U32 org_u_g_max_value : 8; + RK_U32 org_u_g_min_value : 8; + } st_vsp_org_value0; + + /* 0x00004124 reg4169 */ + struct { + RK_U32 org_v_b_max_value : 8; + RK_U32 org_v_b_min_value : 8; + RK_U32 reserved : 16; + } st_vsp_org_value1; + + /* 0x00004128 reg4170 */ + struct { + RK_U32 jpeg_y_r_max_value : 8; + RK_U32 jpeg_y_r_min_value : 8; + RK_U32 jpeg_u_g_max_value : 8; + RK_U32 jpeg_u_g_min_value : 8; + } st_vsp_jpeg_value0; + + /* 0x0000412c reg4171 */ + struct { + RK_U32 jpeg_v_b_max_value : 8; + RK_U32 jpeg_v_b_min_value : 8; + RK_U32 reserved : 16; + } st_vsp_jpeg_value1; + + /* 0x00004130 reg4172 */ + RK_U32 dsp_y_sum; + + /* 0x00004134 reg4173 */ + RK_U32 acc_zero_mv; + + /* 0x00004138 reg4174 */ + struct { + RK_U32 ref1_inter8_num : 23; + RK_U32 reserved1 : 9; + } st_ref1_inter8; + + /* 0x0000413c reg4175 */ + struct { + RK_U32 acc_block_num : 18; + RK_U32 reserved : 14; + } st_blk_avb_sum; + + /* 0x00004140 reg4176 */ + struct { + RK_U32 reserved1 : 15; + RK_U32 acc_cmplx_num : 17; + } st_cmplx_sum; + + /* 0x00004144 reg4177 */ + struct { + RK_U32 reserved1 : 15; + RK_U32 acc_cover16_num : 17; + } st_cover_sum; + + /* 0x00004148 reg4178 */ + struct { + RK_U32 reserved1 : 15; + RK_U32 acc_bndry16_num : 17; + } st_bndry16_sum; + + /* 0x0000414c reg4179 */ + RK_U32 num0_grdnt_point_dep0; + + /* 0x00004150 reg4180 */ + RK_U32 num1_grdnt_point_dep0; + + /* 0x00004154 reg4181 */ + RK_U32 num2_grdnt_point_dep0; + + /* 0x00004158 reg4182 */ + struct { + RK_U32 num : 19; + RK_U32 reserved : 13; + } st_ref1_inter32; + + /* 0x0000415c reg4183 */ + struct { + RK_U32 num : 21; + RK_U32 reserved : 11; + } st_ref1_inter16; + + /* 0x00004160 reg4184 */ + struct { + RK_U32 num0_point_skin : 21; + RK_U32 reserved1 : 11; + } st_skin_sum0; + + /* 0x00004164 reg4185 */ + struct { + RK_U32 num1_point_skin : 21; + RK_U32 reserved1 : 11; + } st_skin_sum1; + + /* 0x00004168 reg4186 */ + struct { + RK_U32 num2_point_skin : 21; + RK_U32 reserved1 : 11; + } st_skin_sum2; + + /* 0x416c - 0x417c */ + RK_U32 reserved4185_4191[5]; + + /* 0x00004180 reg4192 -0x0000424c reg4243 */ + RK_U32 st_b8_qp[52]; +} Vepu511Status; + +/* class: dbg/st/axipn */ +/* 0x00005000 reg5120 - 0x00005230 reg5260*/ +typedef struct Vepu511Dbg_t { + /* 0x00005000 reg5120 */ + struct { + RK_U32 vsp0_pos_x : 16; + RK_U32 vsp0_pos_y : 16; + } st_ppl_pos_vsp0; + + /* 0x00005004 reg5121 */ + struct { + RK_U32 vsp1_pos_x : 16; + RK_U32 vsp1_pos_y : 16; + } st_ppl_pos_vsp1; + + /* 0x00005008 reg5122 */ + struct { + RK_U32 vsp2_pos_x : 16; + RK_U32 vsp2_pos_y : 16; + } st_ppl_pos_vsp2; + + /* 0x0000500c reg5123 */ + struct { + RK_U32 cme_pos_x : 16; + RK_U32 cme_pos_y : 16; + } st_ppl_pos_cme; + + /* 0x00005010 reg5124 */ + struct { + RK_U32 swin_cmd_x : 16; + RK_U32 swin_cmd_y : 16; + } st_ppl_cmd_swin; + + /* 0x00005014 reg5125 */ + struct { + RK_U32 swin_pos_x : 16; + RK_U32 swin_pos_y : 16; + } st_ppl_pos_swin; + + /* 0x00005018 reg5126 */ + struct { + RK_U32 pren_pos_x : 16; + RK_U32 pren_pos_y : 16; + } st_ppl_pos_pren; + + /* 0x0000501c reg5127 */ + struct { + RK_U32 rfme_pos_x : 16; + RK_U32 rfme_pos_y : 16; + } st_ppl_pos_rfme; + + /* 0x00005020 reg5128 */ + struct { + RK_U32 rdo_pos_x : 16; + RK_U32 rdo_pos_y : 16; + } st_ppl_pos_rdo; + + /* 0x00005024 reg5129 */ + struct { + RK_U32 lpf_pos_x : 16; + RK_U32 lpf_pos_y : 16; + } st_ppl_pos_lpf; + + /* 0x00005028 reg5130 */ + struct { + RK_U32 etpy_pos_x : 16; + RK_U32 etpy_pos_y : 16; + } st_ppl_pos_etpy; + + /* 0x0000502c reg5131 */ + struct { + RK_U32 jsp0_pos_x : 16; + RK_U32 jsp0_pos_y : 16; + } st_ppl_pos_jsp0; + + /* 0x00005030 reg5132 */ + struct { + RK_U32 jsp1_pos_x : 16; + RK_U32 jsp1_pos_y : 16; + } st_ppl_pos_jsp1; + + /* 0x00005034 reg5133 */ + struct { + RK_U32 jsp2_pos_x : 16; + RK_U32 jsp2_pos_y : 16; + } st_ppl_pos_jsp2; + + /* 0x00005038 reg5134 */ + struct { + RK_U32 jpeg_pos_x : 16; + RK_U32 jpeg_pos_y : 16; + } st_ppl_pos_jpeg; + + /* 0x0000503c reg5135 */ + struct { + RK_U32 vhdr_pos_y : 16; + RK_U32 jhdr_pos_y : 16; + } dbg_pos_pp_hdr; + + /* 0x00005040 reg5136 */ + struct { + RK_U32 vhdr_src_err : 1; + RK_U32 vhdr_cmd_flst : 1; + RK_U32 reserved1 : 2; + RK_U32 vsp0_org_err : 1; + RK_U32 vsp0_pp2_err : 1; + RK_U32 vsp0_paral_err : 1; + RK_U32 vsp0_cmd_flst : 1; + RK_U32 vhdr_vld : 1; + RK_U32 vhdr_rdy : 1; + RK_U32 vsp0_cmd_vld : 1; + RK_U32 vsp0_cmd_rdy : 1; + RK_U32 reserved2 : 12; + RK_U32 vsp0_wrk_ena : 1; + RK_U32 reserved3 : 3; + RK_U32 vsp0_wrk : 1; + RK_U32 vsp0_tout : 1; + RK_U32 reserved4 : 2; + } dbg_ctrl_vsp0; + + /* 0x00005044 reg5137 */ + struct { + RK_U32 vsp2_org_err : 1; + RK_U32 vsp2_meiw_err : 1; + RK_U32 vsp2_olm_err : 1; + RK_U32 reserved1 : 9; + RK_U32 vsp2_madi_vld : 1; + RK_U32 vsp2_madi_rdy : 1; + RK_U32 vsp2_aq_vld : 1; + RK_U32 vsp2_aq_rdy : 1; + RK_U32 reserved2 : 8; + RK_U32 vsp2_wrk_ena : 1; + RK_U32 reserved3 : 3; + RK_U32 vsp2_wrk : 1; + RK_U32 vsp2_tout : 1; + RK_U32 reserved4 : 2; + } dbg_ctrl_vsp2; + + /* 0x00005048 reg5138 */ + struct { + RK_U32 cme_org_err : 1; + RK_U32 cme_roi_err : 1; + RK_U32 cme_win_err : 1; + RK_U32 cme_cmmv_err : 1; + RK_U32 cme_smvp_err : 1; + RK_U32 cme_meiw_err : 1; + RK_U32 cme_olm_err : 1; + RK_U32 cme_smr_err : 1; + RK_U32 cme_scqp_err : 1; + RK_U32 cme_dual_err : 1; + RK_U32 reserved : 2; + RK_U32 cme_qp_err : 1; + RK_U32 reserved1 : 11; + RK_U32 cme_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 cme_wrk : 1; + RK_U32 cme_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_cme; + + /* 0x0000504c reg5139 */ + struct { + RK_U32 cme_madp_vld : 1; + RK_U32 cme_madp_rdy0 : 1; + RK_U32 cme_madp_rdy1 : 1; + RK_U32 reserved : 1; + RK_U32 cme_mv16_vld : 1; + RK_U32 cme_mv16_rdy : 1; + RK_U32 cme_st_vld : 1; + RK_U32 cme_st_rdy : 1; + RK_U32 cme_stat_vld : 1; + RK_U32 cme_stat_rdy : 1; + RK_U32 cme_diff_vld : 1; + RK_U32 cme_diff_rdy : 1; + RK_U32 cme_cmmv_vld : 1; + RK_U32 cme_cmmv_rdy : 1; + RK_U32 cme_smvp_vld : 1; + RK_U32 cme_smvp_rdy : 1; + RK_U32 rdo_tmvp_rvld : 1; + RK_U32 rdo_tmvp_rrdy : 1; + RK_U32 rdo_tmvp_wvld : 1; + RK_U32 rdo_tmvp_wrdy : 1; + RK_U32 rdo_lbf_wvld : 1; + RK_U32 rdo_lbf_wrdy : 1; + RK_U32 rdo_lbf_rvld : 1; + RK_U32 rdo_lbf_rrdy : 1; + RK_U32 rdo_rfmv_rvld : 1; + RK_U32 rdo_rfmv_rrdy : 1; + RK_U32 rdo_hevc_qp_vld : 1; + RK_U32 rdo_hevc_qp_rdy : 1; + RK_U32 reserved1 : 4; + } dbg_hs_ppl; + + /* 0x00005050 reg5140 */ + struct { + RK_U32 swin_org_err : 1; + RK_U32 swin_ref_err : 1; + RK_U32 reserved : 10; + RK_U32 swin_cmd_vld : 1; + RK_U32 swin_cmd_rdy : 1; + RK_U32 reserved1 : 2; + RK_U32 swin_buff_ptr : 2; + RK_U32 swin_buff_num0 : 2; + RK_U32 swin_buff_num1 : 2; + RK_U32 swin_buff_num2 : 2; + RK_U32 reserved2 : 4; + RK_U32 swin_wrk : 1; + RK_U32 swin_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_swin; + + /* 0x00005054 reg5141 */ + struct { + RK_U32 pnra_org_err : 1; + RK_U32 pnra_qp_err : 1; + RK_U32 pnra_rfme_err : 1; + RK_U32 reserved : 9; + RK_U32 pnra_olm_vld : 1; + RK_U32 pnra_olm_rdy : 1; + RK_U32 pnra_subj_vld : 1; + RK_U32 pnra_subj_rdy : 1; + RK_U32 reserved1 : 8; + RK_U32 pnra_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 pnra_wrk : 1; + RK_U32 pnra_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_pren; + + /* 0x00005058 reg5142 */ + struct { + RK_U32 rfme_org_err : 1; + RK_U32 rfme_ref_err : 1; + RK_U32 rfme_cmmv_err : 1; + RK_U32 rfme_rfmv_err : 1; + RK_U32 rfme_tmvp_err : 1; + RK_U32 rfme_qp_err : 1; + RK_U32 rfme_pnra_err : 1; + RK_U32 reserved : 5; + RK_U32 rfme_tmvp_vld : 1; + RK_U32 rfme_tmvp_rdy : 1; + RK_U32 rfme_smvp_vld : 1; + RK_U32 rfme_smvp_rdy : 1; + RK_U32 rfme_cmmv_vld : 1; + RK_U32 rfme_cmmv_rdy : 1; + RK_U32 rfme_rfmv_vld : 1; + RK_U32 rfme_rfmv_rdy : 1; + RK_U32 reserved1 : 8; + RK_U32 rfme_wrk : 1; + RK_U32 rfme_tout : 1; + RK_U32 reserved2 : 2; + } dbg_ctrl_rfme; + + /* 0x0000505c reg5143 */ + struct { + RK_U32 rdo_org_err : 1; + RK_U32 rdo_ref_err : 1; + RK_U32 rdo_inf_err : 1; + RK_U32 rdo_coef_err : 1; + RK_U32 rdo_lbfr_err : 1; + RK_U32 rdo_lbfw_err : 1; + RK_U32 rdo_madi_lbf_err : 1; + RK_U32 rdo_tmvp_wr_err : 1; + RK_U32 rdo_smear_err : 1; + RK_U32 rdo_mbqp_err : 1; + RK_U32 rdo_rc_err : 1; + RK_U32 rdo_ent_err : 1; + RK_U32 rdo_lpf_err : 1; + RK_U32 rdo_st_err : 1; + RK_U32 rdo_tmvp_rd_err : 1; + RK_U32 rdo_rfmv_err : 1; + RK_U32 reserved : 12; + RK_U32 rdo_wrk : 1; + RK_U32 rdo_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_rdo; + + /* 0x00005060 reg5144 */ + struct { + RK_U32 lpf_org_err : 1; + RK_U32 lpf_rdo_err : 1; + RK_U32 reserved : 10; + RK_U32 lpf_rcol_vld : 1; + RK_U32 lpf_rcol_rdy : 1; + RK_U32 lpf_lbf_wvld : 1; + RK_U32 lpf_lbf_wrdy : 1; + RK_U32 lpf_lbf_rvld : 1; + RK_U32 lpf_lbf_rrdy : 1; + RK_U32 reserved1 : 6; + RK_U32 lpf_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 lpf_wrk : 1; + RK_U32 lpf_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_lpf; + + /* 0x00005064 reg5145 */ + struct { + RK_U32 reserved : 12; + RK_U32 etpy_slf_full : 1; + RK_U32 etpy_bsw_vld : 1; + RK_U32 etpy_bsw_rdy : 1; + RK_U32 reserved1 : 9; + RK_U32 etpy_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 etpy_wrk : 1; + RK_U32 etpy_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_etpy; + + /* 0x00005068 reg5146 */ + struct { + RK_U32 jhdr_src_err : 1; + RK_U32 jhdr_cmd_flst : 1; + RK_U32 reserved1 : 2; + RK_U32 jsp0_org_err : 1; + RK_U32 jsp0_pp2_err : 1; + RK_U32 jsp0_paral_err : 1; + RK_U32 jsp0_cmd_flst : 1; + RK_U32 jhdr_vld : 1; + RK_U32 jhdr_rdy : 1; + RK_U32 jsp0_cmd_vld : 1; + RK_U32 jsp0_cmd_rdy : 1; + RK_U32 reserved2 : 12; + RK_U32 jsp0_wrk_ena : 1; + RK_U32 reserved3 : 3; + RK_U32 jsp0_wrk : 1; + RK_U32 jsp0_tout : 1; + RK_U32 reserved4 : 2; + } dbg_ctrl_jsp0; + + /* 0x0000506c reg5147 */ + struct { + RK_U32 jsp2_org_err : 1; + RK_U32 reserved1 : 11; + RK_U32 jsp2_madi_vld : 1; + RK_U32 jsp2_madi_rdy : 1; + RK_U32 reserved2 : 10; + RK_U32 jsp2_wrk_ena : 1; + RK_U32 reserved3 : 3; + RK_U32 jsp2_wrk : 1; + RK_U32 jsp2_tout : 1; + RK_U32 reserved4 : 2; + } dbg_ctrl_jsp2; + + /* 0x00005070 reg5148 */ + struct { + RK_U32 jpeg_org_err : 1; + RK_U32 jpeg_st_err : 1; + RK_U32 reserved : 10; + RK_U32 jpg_slf_full : 1; + RK_U32 jpg_bsw_vld : 1; + RK_U32 jpg_bsw_rdy : 1; + RK_U32 reserved1 : 9; + RK_U32 jpeg_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 jpeg_wrk : 1; + RK_U32 jpeg_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_jpeg; + + /* 0x00005074 reg5149 */ + struct { + RK_U32 vsp1_org_err : 1; + RK_U32 reserved : 7; + RK_U32 vsp1_wrk_ena : 1; + RK_U32 reserved1 : 3; + RK_U32 vsp1_wrk : 1; + RK_U32 vsp1_tout : 1; + RK_U32 reserved2 : 2; + RK_U32 jsp1_org_err : 1; + RK_U32 reserved3 : 7; + RK_U32 jsp1_wrk_ena : 1; + RK_U32 reserved4 : 3; + RK_U32 jsp1_wrk : 1; + RK_U32 jsp1_tout : 1; + RK_U32 reserved5 : 2; + } dbg_ctrl_pp1; + + /* 0x00005078 reg5150 */ + struct { + RK_U32 pp2_frm_done : 1; + RK_U32 cime_frm_done : 1; + RK_U32 jpeg_frm_done : 1; + RK_U32 rdo_frm_done : 1; + RK_U32 lpf_frm_done : 1; + RK_U32 ent_frm_done : 1; + RK_U32 reserved : 2; + RK_U32 criw_frm_done : 1; + RK_U32 meiw_frm_done : 1; + RK_U32 smiw_frm_done : 1; + RK_U32 dma_frm_idle : 1; + RK_U32 reserved1 : 12; + RK_U32 video_ena : 1; + RK_U32 jpeg_ena : 1; + RK_U32 vepu_pp_ena : 1; + RK_U32 reserved2 : 1; + RK_U32 frm_wrk : 1; + RK_U32 frm_tout : 1; + RK_U32 reserved3 : 2; + } dbg_tctrl; + + /* 0x0000507c reg5151 */ + struct { + RK_U32 enc_frm_cur : 3; + RK_U32 lkt_src_paus : 1; + RK_U32 lkt_cfg_paus : 1; + RK_U32 reserved : 27; + } dbg_frm_task; + + /* 0x00005080 reg5152 */ + struct { + RK_U32 sli_num : 15; + RK_U32 reserved : 17; + } st_sli_num; + + /* 0x5084 - 0x50fc */ + RK_U32 reserved5153_5183[31]; + + /* 0x00005100 reg5184 */ + struct { + RK_U32 empty_oafifo : 1; + RK_U32 full_cmd_oafifo : 1; + RK_U32 full_data_oafifo : 1; + RK_U32 empty_iafifo : 1; + + RK_U32 full_cmd_iafifo : 1; + RK_U32 full_info_iafifo : 1; + RK_U32 fbd_brq_st : 4; + RK_U32 fbd_hdr_vld : 1; + RK_U32 fbd_bmng_end : 1; + + RK_U32 nfbd_req_st : 4; + RK_U32 acc_axi_cmd : 8; + RK_U32 reserved : 8; + } dbg_pp_st; + + /* 0x00005104 reg5185 */ + struct { + RK_U32 r_ena_lambd : 1; + RK_U32 r_fst_swinw_end : 1; + RK_U32 r_swinw_end : 1; + RK_U32 r_cnt_swinw : 1; + + RK_U32 r_dspw_end : 1; + RK_U32 r_dspw_cnt : 1; + RK_U32 i_sjgen_work : 1; + RK_U32 r_end_rspgen : 1; + + RK_U32 r_cost_gate : 1; + RK_U32 r_ds_gate : 1; + RK_U32 r_mvp_gate : 1; + RK_U32 i_smvp_arrdy : 1; + + RK_U32 i_smvp_arvld : 1; + RK_U32 i_stptr_wrdy : 1; + RK_U32 i_stptr_wvld : 1; + RK_U32 i_rdy_atf : 1; + + RK_U32 i_vld_atf : 1; + RK_U32 i_rdy_bmv16 : 1; + RK_U32 i_vld_bmv16 : 1; + RK_U32 i_wr_dsp : 1; + + RK_U32 i_rdy_dsp : 1; + RK_U32 i_vld_dsp : 1; + RK_U32 r_rdy_org : 1; + RK_U32 i_vld_org : 1; + + RK_U32 i_rdy_state : 1; + RK_U32 i_vld_state : 1; + RK_U32 i_rdy_madp : 1; + RK_U32 i_vld_madp : 1; + + RK_U32 i_rdy_diff : 1; + RK_U32 i_vld_diff : 1; + RK_U32 reserved : 2; + } dbg_cime_st; + + /* 0x00005108 reg5186 */ + RK_U32 swin_dbg_inf; + + /* 0x0000510c reg5187 */ + struct { + RK_U32 bbrq_cmps_left_len2 : 1; + RK_U32 bbrq_cmps_left_len1 : 1; + RK_U32 cmps_left_len0 : 1; + RK_U32 bbrq_rdy2 : 1; + RK_U32 dcps_vld2 : 1; + RK_U32 bbrq_rdy1 : 1; + RK_U32 dcps_vld1 : 1; + RK_U32 bbrq_rdy0 : 1; + RK_U32 dcps_vld0 : 1; + RK_U32 hb_rdy2 : 1; + RK_U32 bbrq_vld2 : 1; + RK_U32 hb_rdy1 : 1; + RK_U32 bbrq_vld1 : 1; + RK_U32 hb_rdy0 : 1; + RK_U32 bbrq_vld0 : 1; + RK_U32 idle_msb2 : 1; + RK_U32 idle_msb1 : 1; + RK_U32 idle_msb0 : 1; + RK_U32 cur_state_dcps : 1; + RK_U32 cur_state_bbrq : 1; + RK_U32 cur_state_hb : 1; + RK_U32 cke_bbrq_dcps : 1; + RK_U32 cke_dcps : 1; + RK_U32 cke_bbrq : 1; + RK_U32 rdy_lwcd_rsp : 1; + RK_U32 vld_lwcd_rsp : 1; + RK_U32 rdy_lwcd_req : 1; + RK_U32 vld_lwcd_req : 1; + RK_U32 rdy_lwrsp : 1; + RK_U32 vld_lwrsp : 1; + RK_U32 rdy_lwreq : 1; + RK_U32 vld_lwreq : 1; + } dbg_fbd_hhit0; + + /* 0x00005110 reg5188 */ + RK_U32 rfme_dbg_inf; + + /* 0x5114 */ + RK_U32 reserved_5189; + + /* 0x00005118 reg5190 */ + RK_U32 dbg0_fbd; + + /* 0x0000511c reg5191 */ + RK_U32 dbg1_fbd; + + /* 0x00005120 reg5192 */ + RK_U32 rdo_dbg0; + + /* 0x00005124 reg5193 */ + RK_U32 rdo_dbg1; + + /* 0x00005128 reg5194 */ + struct { + RK_U32 h264_sh_st_cs : 4; + RK_U32 rsd_st_cs : 4; + RK_U32 h264_sd_st_cs : 5; + RK_U32 etpy_rdy : 1; + RK_U32 reserved : 18; + } dbg_etpy; + + /* 0x0000512c reg5195 */ + struct { + RK_U32 chl_aw_vld : 10; + RK_U32 chl_aw_rdy : 10; + RK_U32 aw_vld_arb : 1; + RK_U32 aw_rdy_arb : 1; + RK_U32 aw_vld_crosclk : 1; + RK_U32 aw_rdy_crosclk : 1; + RK_U32 aw_rdy_mmu : 1; + RK_U32 aw_vld_mmu : 1; + RK_U32 aw_rdy_axi : 1; + RK_U32 aw_vld_axi : 1; + RK_U32 reserved : 4; + } dbg_dma_aw; + + /* 0x00005130 reg5196 */ + struct { + RK_U32 chl_w_vld : 10; + RK_U32 chl_w_rdy : 10; + RK_U32 w_vld_arb : 1; + RK_U32 w_rdy_arb : 1; + RK_U32 w_vld_crosclk : 1; + RK_U32 w_rdy_crosclk : 1; + RK_U32 w_rdy_mmu : 1; + RK_U32 w_vld_mmu : 1; + RK_U32 w_rdy_axi : 1; + RK_U32 w_vld_axi : 1; + RK_U32 reserved : 4; + } dbg_dma_w; + + /* 0x00005134 reg5197 */ + struct { + RK_U32 chl_ar_vld : 9; + RK_U32 chl_ar_rdy : 9; + RK_U32 reserved : 2; + RK_U32 ar_vld_arb : 1; + RK_U32 ar_rdy_arb : 1; + RK_U32 ar_vld_crosclk : 1; + RK_U32 ar_rdy_crosclk : 1; + RK_U32 ar_rdy_mmu : 1; + RK_U32 ar_vld_mmu : 1; + RK_U32 ar_rdy_axi : 1; + RK_U32 ar_vld_axi : 1; + RK_U32 reserved1 : 4; + } dbg_dma_ar; + + /* 0x00005138 reg5198 */ + struct { + RK_U32 chl_r_vld : 9; + RK_U32 chl_r_rdy : 9; + RK_U32 reserved : 2; + RK_U32 r_vld_arb : 1; + RK_U32 r_rdy_arb : 1; + RK_U32 r_vld_crosclk : 1; + RK_U32 r_rdy_crosclk : 1; + RK_U32 r_rdy_mmu : 1; + RK_U32 r_vld_mmu : 1; + RK_U32 r_rdy_axi : 1; + RK_U32 r_vld_axi : 1; + RK_U32 b_rdy_mmu : 1; + RK_U32 b_vld_mmu : 1; + RK_U32 b_rdy_axi : 1; + RK_U32 b_vld_axi : 1; + } dbg_dma_r; + + /* 0x0000513c reg5199 */ + struct { + RK_U32 dbg_sclr : 20; + RK_U32 dbg_arb : 12; + } dbg_dma_dbg0; + + /* 0x00005140 reg5200 */ + struct { + RK_U32 bsw_fsm_stus : 4; + RK_U32 bsw_aw_full : 1; + RK_U32 bsw_rdy_ent : 1; + RK_U32 bsw_vld_ent : 1; + RK_U32 jpg_bsw_stus : 4; + RK_U32 jpg_aw_full : 1; + RK_U32 jpg_bsw_rdy : 1; + RK_U32 jpg_bsw_vld : 1; + RK_U32 crpw_fsm_stus : 3; + RK_U32 hdwr_rdy : 1; + RK_U32 hdwr_vld : 1; + RK_U32 bdwr_rdy : 1; + RK_U32 bdwr_vld : 1; + RK_U32 nfbc_rdy : 1; + RK_U32 nfbc_vld : 1; + RK_U32 dsp_fsm_stus : 2; + RK_U32 dsp_wr_flg : 1; + RK_U32 dsp_rsy : 1; + RK_U32 dsp_vld : 1; + RK_U32 lpfw_fsm_stus : 3; + RK_U32 reserved : 1; + } dbg_dma_dbg1; + + /* 0x00005144 reg5201 */ + struct { + RK_U32 awvld_mdo : 1; + RK_U32 awrdy_mdo : 1; + RK_U32 wvld_mdo : 1; + RK_U32 wrdy_mdo : 1; + RK_U32 awvld_odo : 1; + RK_U32 awrdy_odo : 1; + RK_U32 wvld_odo : 1; + RK_U32 wrdy_odo : 1; + RK_U32 awvld_rfmw : 1; + RK_U32 awrdy_rfmw : 1; + RK_U32 wvld_rfmw : 1; + RK_U32 wrdy_rfmw : 1; + RK_U32 arvld_rfmr : 1; + RK_U32 arrdy_rfmr : 1; + RK_U32 rvld_rfmr : 1; + RK_U32 rrdy_rfmr : 1; + RK_U32 reserved : 16; + } dbg_dma_vpp; + + /* 0x00005148 reg5202 */ + struct { + RK_U32 rdo_st : 20; + RK_U32 reserved : 12; + } dbg_rdo_st; + + /* 0x0000514c reg5203 */ + struct { + RK_U32 lpf_work : 1; + RK_U32 rdo_par_nrdy : 1; + RK_U32 rdo_rcn_nrdy : 1; + RK_U32 lpf_rcn_rdy : 1; + RK_U32 dblk_work : 1; + RK_U32 sao_work : 1; + RK_U32 reserved : 18; + RK_U32 tile_bdry_read : 1; + RK_U32 tile_bdry_write : 1; + RK_U32 tile_bdry_rrdy : 1; + RK_U32 rdo_read_tile_bdry : 1; + RK_U32 rdo_write_tile_bdry : 1; + RK_U32 reserved1 : 3; + } dbg_lpf; + + /* 0x5150 */ + RK_U32 reserved_5204; + + /* 0x00005154 reg5205 */ + RK_U32 dbg0_cache; + + /* 0x00005158 reg5206 */ + RK_U32 dbg2_fbd; + + /* 0x515c */ + RK_U32 reserved_5207; + + /* 0x00005160 reg5208 */ + struct { + RK_U32 ebuf_diff_cmd : 8; + RK_U32 lbuf_lpf_ncnt : 7; + RK_U32 lbuf_lpf_cien : 1; + RK_U32 lbuf_rdo_ncnt : 7; + RK_U32 lbuf_rdo_cien : 1; + RK_U32 lbuf_tctrl_ncnt : 7; + RK_U32 lbuf_tctrl_cien : 1; + } dbg_lbuf0; + + /* 0x00005164 reg5209 */ + struct { + RK_U32 rvld_ebfr : 1; + RK_U32 rrdy_ebfr : 1; + RK_U32 arvld_ebfr : 1; + RK_U32 arrdy_ebfr : 1; + RK_U32 wvld_ebfw : 1; + RK_U32 wrdy_ebfw : 1; + RK_U32 awvld_ebfw : 1; + RK_U32 awrdy_ebfw : 1; + RK_U32 lpf_lbuf_rvld : 1; + RK_U32 lpf_lbuf_rrdy : 1; + RK_U32 lpf_lbuf_wvld : 1; + RK_U32 lpf_lbuf_wrdy : 1; + RK_U32 rdo_lbuf_rvld : 1; + RK_U32 rdo_lbuf_rrdy : 1; + RK_U32 rdo_lbuf_wvld : 1; + RK_U32 rdo_lbuf_wrdy : 1; + RK_U32 fme_lbuf_rvld : 1; + RK_U32 fme_lbuf_rrdy : 1; + RK_U32 cme_lbuf_rvld : 1; + RK_U32 cme_lbuf_rrdy : 1; + RK_U32 smear_lbuf_rvld : 1; + RK_U32 smear_lbuf_rrdy : 1; + RK_U32 smear_lbuf_wvld : 1; + RK_U32 smear_lbuf_wrdy : 1; + RK_U32 depth_lbuf_wvld : 1; + RK_U32 depth_lbuf_wrdy : 1; + RK_U32 rdo_lbufw_flag : 1; + RK_U32 rdo_lbufr_flag : 1; + RK_U32 cme_lbufr_flag : 1; + RK_U32 reserved : 3; + } dbg_lbuf1; + + /* 0x00005168 reg5210 */ + struct { + RK_U32 dbg_isp_fcnt : 8; + RK_U32 dbg_isp_fcyc : 24; + } dbg_dvbm_isp0; + + /* 0x0000516c reg5211 */ + struct { + RK_U32 dbg_isp_lcnt : 14; + RK_U32 dbg_isp_ltgl : 1; + RK_U32 dvbm_isp_fsid : 1; + RK_U32 dbg_isp_fcnt : 8; + RK_U32 dbg_isp_oflw : 1; + RK_U32 dbg_isp_ftgl : 1; + RK_U32 dbg_isp_full : 1; + RK_U32 dbg_isp_work : 1; + RK_U32 dbg_isp_lvld : 1; + RK_U32 dbg_isp_lrdy : 1; + RK_U32 dbg_isp_fvld : 1; + RK_U32 dbg_isp_frdy : 1; + } dbg_dvbm_isp1; + + /* 0x00005170 reg5212 */ + struct { + RK_U32 dbg_bf0_isp_lcnt : 14; + RK_U32 dbg_bf0_isp_llst : 1; + RK_U32 dbg_bf0_isp_sofw : 1; + RK_U32 dbg_bf0_isp_fcnt : 8; + RK_U32 dbg_bf0_isp_fsid : 1; + RK_U32 reserved : 5; + RK_U32 dbg_bf0_isp_pnt : 1; + RK_U32 dbg_bf0_vpu_pnt : 1; + } dbg_dvbm_buf0_inf0; + + /* 0x00005174 reg5213 */ + struct { + RK_U32 dbg_bf0_src_lcnt : 14; + RK_U32 dbg_bf0_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf0_vpu_lcnt : 14; + RK_U32 dbg_bf0_vpu_llst : 1; + RK_U32 dbg_bf0_vpu_vofw : 1; + } dbg_dvbm_buf0_inf1; + + /* 0x00005178 reg5214 */ + struct { + RK_U32 dbg_bf1_isp_lcnt : 14; + RK_U32 dbg_bf1_isp_llst : 1; + RK_U32 dbg_bf1_isp_sofw : 1; + RK_U32 dbg_bf1_isp_fcnt : 8; + RK_U32 dbg_bf1_isp_fsid : 1; + RK_U32 reserved : 5; + RK_U32 dbg_bf1_isp_pnt : 1; + RK_U32 dbg_bf1_vpu_pnt : 1; + } dbg_dvbm_buf1_inf0; + + /* 0x0000517c reg5215 */ + struct { + RK_U32 dbg_bf1_src_lcnt : 14; + RK_U32 dbg_bf1_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf1_vpu_lcnt : 14; + RK_U32 dbg_bf1_vpu_llst : 1; + RK_U32 dbg_bf1_vpu_vofw : 1; + } dbg_dvbm_buf1_inf1; + + /* 0x00005180 reg5216 */ + struct { + RK_U32 dbg_bf2_isp_lcnt : 14; + RK_U32 dbg_bf2_isp_llst : 1; + RK_U32 dbg_bf2_isp_sofw : 1; + RK_U32 dbg_bf2_isp_fcnt : 8; + RK_U32 dbg_bf2_isp_fsid : 1; + RK_U32 reserved : 5; + RK_U32 dbg_bf2_isp_pnt : 1; + RK_U32 dbg_bf2_vpu_pnt : 1; + } dbg_dvbm_buf2_inf0; + + /* 0x00005184 reg5217 */ + struct { + RK_U32 dbg_bf2_src_lcnt : 14; + RK_U32 dbg_bf2_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf2_vpu_lcnt : 14; + RK_U32 dbg_bf2_vpu_llst : 1; + RK_U32 dbg_bf2_vpu_vofw : 1; + } dbg_dvbm_buf2_inf1; + + /* 0x00005188 reg5218 */ + struct { + RK_U32 dbg_bf3_isp_lcnt : 14; + RK_U32 dbg_bf3_isp_llst : 1; + RK_U32 dbg_bf3_isp_sofw : 1; + RK_U32 dbg_bf3_isp_fcnt : 1; + RK_U32 dbg_bf3_isp_fsid : 1; + RK_U32 reserved : 12; + RK_U32 dbg_bf3_isp_pnt : 1; + RK_U32 dbg_bf3_vpu_pnt : 1; + } dbg_dvbm_buf3_inf0; + + /* 0x0000518c reg5219 */ + struct { + RK_U32 dbg_bf3_src_lcnt : 14; + RK_U32 dbg_bf3_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf3_vpu_lcnt : 14; + RK_U32 dbg_bf3_vpu_llst : 1; + RK_U32 dbg_bf3_vpu_vofw : 1; + } dbg_dvbm_buf3_inf1; + + /* 0x00005190 reg5220 */ + struct { + RK_U32 dbg_isp_fptr : 3; + RK_U32 dbg_isp_full : 1; + RK_U32 dbg_src_fptr : 3; + RK_U32 dbg_dvbm_ctrl : 1; + RK_U32 dbg_vpu_fptr : 3; + RK_U32 dbg_vpu_empt : 1; + RK_U32 dbg_vpu_lvld : 1; + RK_U32 dbg_vpu_lrdy : 1; + RK_U32 dbg_vpu_fvld : 1; + RK_U32 dbg_vpu_frdy : 1; + RK_U32 dbg_fcnt_misp : 4; + RK_U32 dbg_fcnt_mvpu : 4; + RK_U32 dbg_fcnt_sofw : 4; + RK_U32 dbg_fcnt_vofw : 4; + } dbg_dvbm_ctrl; + + /* 0x5194 - 0x519c */ + RK_U32 reserved5221_5223[3]; + + /* 0x000051a0 reg5224 */ + RK_U32 dbg_dvbm_buf0_yadr; + + /* 0x000051a4 reg5225 */ + RK_U32 dbg_dvbm_buf0_cadr; + + /* 0x000051a8 reg5226 */ + RK_U32 dbg_dvbm_buf1_yadr; + + /* 0x000051ac reg5227 */ + RK_U32 dbg_dvbm_buf1_cadr; + + /* 0x000051b0 reg5228 */ + RK_U32 dbg_dvbm_buf2_yadr; + + /* 0x000051b4 reg5229 */ + RK_U32 dbg_dvbm_buf2_cadr; + + /* 0x000051b8 reg5230 */ + RK_U32 dbg_dvbm_buf3_yadr; + + /* 0x000051bc reg5231 */ + RK_U32 dbg_dvbm_buf3_cadr; + + /* 0x000051c0 reg5232 */ + struct { + RK_U32 dchs_rx_cnt : 11; + RK_U32 dchs_rx_id : 2; + RK_U32 dchs_rx_en : 1; + RK_U32 dchs_rx_ack : 1; + RK_U32 dchs_rx_req : 1; + RK_U32 dchs_tx_cnt : 11; + RK_U32 dchs_tx_id : 2; + RK_U32 dchs_tx_en : 1; + RK_U32 dchs_tx_ack : 1; + RK_U32 dchs_tx_req : 1; + } dbg_dchs_intfc; + + /* 0x000051c4 reg5233 */ + struct { + RK_U32 lpfw_tx_cnt : 11; + RK_U32 lpfw_tx_en : 1; + RK_U32 crpw_tx_cnt : 11; + RK_U32 crpw_tx_en : 1; + RK_U32 dual_err_updt : 1; + RK_U32 dlyc_fifo_oflw : 1; + RK_U32 dlyc_tx_vld : 1; + RK_U32 dlyc_tx_rdy : 1; + RK_U32 dlyc_tx_empty : 1; + RK_U32 dchs_tx_idle : 1; + RK_U32 dchs_tx_asy : 1; + RK_U32 dchs_tx_syn : 1; + } dbg_dchs_tx_inf0; + + /* 0x000051c8 reg5234 */ + struct { + RK_U32 criw_tx_cnt : 11; + RK_U32 criw_tx_en : 1; + RK_U32 smrw_tx_cnt : 11; + RK_U32 smrw_tx_en : 1; + RK_U32 reserved : 8; + } dbg_dchs_tx_inf1; + + /* 0x000051cc reg5235 */ + struct { + RK_U32 dual_rx_cnt : 11; + RK_U32 dual_rx_id : 2; + RK_U32 dual_rx_en : 1; + RK_U32 dual_rx_syn : 1; + RK_U32 dual_rx_lock : 1; + RK_U32 dual_lpfr_dule : 1; + RK_U32 dual_cime_dule : 1; + RK_U32 dual_clomv_dule : 1; + RK_U32 dual_smear_dule : 1; + RK_U32 reserved : 12; + } dbg_dchs_rx_inf0; + + /* 0x51d0 - 0x51fc */ + RK_U32 reserved5236_5247[12]; + + /* 0x00005200 reg5248 */ + RK_U32 frame_cyc; + + /* 0x00005204 reg5249 */ + RK_U32 vsp0_fcyc; + + /* 0x00005208 reg5250 */ + RK_U32 vsp1_fcyc; + + /* 0x0000520c reg5251 */ + RK_U32 vsp2_fcyc; + + /* 0x00005210 reg5252 */ + RK_U32 cme_fcyc; + + /* 0x00005214 reg5253 */ + RK_U32 ldr_fcyc; + + /* 0x00005218 reg5254 */ + RK_U32 rfme_fcyc; + + /* 0x0000521c reg5255 */ + RK_U32 fme_fcyc; + + /* 0x00005220 reg5256 */ + RK_U32 rdo_fcyc; + + /* 0x00005224 reg5257 */ + RK_U32 lpf_fcyc; + + /* 0x00005228 reg5258 */ + RK_U32 etpy_fcyc; + + /* 0x0000522c reg5259 */ + RK_U32 reserved_5259; + + /* 0x00005230 reg5260 */ + RK_U32 jsp0_fcyc; + + /* 0x00005234 reg5261 */ + RK_U32 jsp1_fcyc; + + /* 0x00005238 reg5262 */ + RK_U32 jsp2_fcyc; + + /* 0x0000523c reg5263 */ + RK_U32 jpeg_fcyc; +} Vepu511Dbg; + +typedef struct Vepu511OsdCfg_t { + void *reg_base; + MppDev dev; + MppEncOSDData3 *osd_data3; +} Vepu511OsdCfg; + +/* ROI block configuration */ +typedef struct Vepu511H264RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_skip : 4; + RK_U32 mdc_adju_intra : 4; + RK_U32 reserved : 12; +} Vepu511H264RoiBlkCfg; + +typedef struct Vepu511H265RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 mdc_adju_intra : 4; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_split : 4; + RK_U32 mdc_adju_res_intra : 4; + RK_U32 mdc_adju_res_inter : 4; + RK_U32 mdc_adju_res_mv0 : 4; +} Vepu511H265RoiBlkCfg; + +typedef struct Vepu511H265RoiDpt1BlkCfg { + //W0 + RK_U32 cu32_qp_adju : 8; + RK_U32 cu32_mdc_adju_intra : 4; + RK_U32 cu32_mdc_adju_inter : 4; + RK_U32 cu32_mdc_adju_split : 4; + RK_U32 cu32_mdc_adju_res_intra : 4; + RK_U32 cu32_mdc_adju_res_inter : 4; + RK_U32 cu32_mdc_adju_res_mv0 : 4; + //W1 + RK_U32 cu16_0_qp_adju : 8; + RK_U32 cu16_0_mdc_adju_intra : 4; + RK_U32 cu16_0_mdc_adju_inter : 4; + RK_U32 cu16_0_mdc_adju_split : 4; + RK_U32 cu16_0_mdc_adju_res_intra : 4; + RK_U32 cu16_0_mdc_adju_res_inter : 4; + RK_U32 cu16_0_mdc_adju_res_mv0 : 4; + //W2 + RK_U32 cu16_1_qp_adju : 8; + RK_U32 cu16_1_mdc_adju_intra : 4; + RK_U32 cu16_1_mdc_adju_inter : 4; + RK_U32 cu16_1_mdc_adju_split : 4; + RK_U32 cu16_1_mdc_adju_res_intra : 4; + RK_U32 cu16_1_mdc_adju_res_inter : 4; + RK_U32 cu16_1_mdc_adju_res_mv0 : 4; + //W3 + RK_U32 cu16_2_qp_adju : 8; + RK_U32 cu16_2_mdc_adju_intra : 4; + RK_U32 cu16_2_mdc_adju_inter : 4; + RK_U32 cu16_2_mdc_adju_split : 4; + RK_U32 cu16_2_mdc_adju_res_intra : 4; + RK_U32 cu16_2_mdc_adju_res_inter : 4; + RK_U32 cu16_2_mdc_adju_res_mv0 : 4; + //W4 + RK_U32 cu16_3_qp_adju : 8; + RK_U32 cu16_3_mdc_adju_intra : 4; + RK_U32 cu16_3_mdc_adju_inter : 4; + RK_U32 cu16_3_mdc_adju_split : 4; + RK_U32 cu16_3_mdc_adju_res_intra : 4; + RK_U32 cu16_3_mdc_adju_res_inter : 4; + RK_U32 cu16_3_mdc_adju_res_mv0 : 4; +} Vepu511H265RoiDpt1BlkCfg; + +typedef struct Vepu511JpegCfg_t { + MppDev dev; + void *jpeg_reg_base; + void *reg_tab; + void *enc_task; + void *input_fmt; + RK_U32 online; + RK_U32 rst_marker; +} Vepu511JpegCfg; + +typedef struct Vepu511SclJpgTbl_t { + /* 0x2200 reg2176 - 0x2584 reg2401*/ + Vepu511SclCfg scl; + /* 0x2588 - 0x258f */ + RK_U32 reserve[2]; + /* 0x2590 - 0x2c9c*/ + Vepu511SclCfgExt scl_ext; + /* 0x2ca0 - 0x2e1c */ + Vepu511JpegTable jpg_tbl; +} Vepu511SclJpgTbl; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vepu511_set_osd(Vepu511OsdCfg * cfg); +MPP_RET vepu511_set_roi(Vepu511RoiCfg *roi_reg_base, MppEncROICfg * roi, RK_S32 w, RK_S32 h); +MPP_RET vepu511_set_jpeg_reg(Vepu511JpegCfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* VEPU511_COMMON_H */ diff --git a/mpp/hal/rkenc/common/vepu511a_common.c b/mpp/hal/rkenc/common/vepu511a_common.c new file mode 100644 index 000000000..c18442310 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu511a_common.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vepu511a_common" + +#include + +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_packet.h" +#include "mpp_frame_impl.h" + +#include "kmpp_obj.h" +#include "kmpp_buffer.h" + +#include "hal_enc_task.h" +#include "vepu5xx_common.h" +#include "vepu511a_common.h" + +MPP_RET vepu511a_set_roi(Vepu511aRoiCfg *roi_reg_base, MppEncROICfg * roi, RK_S32 w, RK_S32 h) +{ + MppEncROIRegion *region = NULL; + Vepu511aRoiCfg *roi_cfg = NULL; + Vepu511aRoiRegion *reg_regions = NULL; + MPP_RET ret = MPP_NOK; + RK_U32 i = 0; + + if (NULL == roi_reg_base || NULL == roi) { + mpp_loge_f("invalid buf %p roi %p\n", roi_reg_base, roi); + goto DONE; + } + + roi_cfg = (Vepu511aRoiCfg *)roi_reg_base; + reg_regions = &roi_cfg->regions[0]; + region = roi->regions; + + memset(reg_regions, 0, sizeof(Vepu511aRoiRegion) * 8); + + if (roi->number > VEPU511A_MAX_ROI_NUM) { + mpp_loge_f("invalid region number %d\n", roi->number); + goto DONE; + } + + /* check region config */ + ret = MPP_OK; + for (i = 0; i < roi->number; i++, region++) { + if (region->x + region->w > w || region->y + region->h > h) + ret = MPP_NOK; + + if (region->intra > 1 || region->qp_area_idx >= VEPU511A_MAX_ROI_NUM || + region->area_map_en > 1 || region->abs_qp_en > 1) + ret = MPP_NOK; + + if ((region->abs_qp_en && region->quality > 51) || + (!region->abs_qp_en && (region->quality > 51 || region->quality < -51))) + ret = MPP_NOK; + + if (ret) { + mpp_loge_f("region %d invalid param:\n", i); + mpp_loge_f("position [%d:%d:%d:%d] vs [%d:%d]\n", + region->x, region->y, region->w, region->h, w, h); + mpp_loge_f("force intra %d qp area index %d\n", + region->intra, region->qp_area_idx); + mpp_loge_f("abs qp mode %d value %d\n", + region->abs_qp_en, region->quality); + goto DONE; + } + + reg_regions->roi_pos_lt.roi_lt_x = MPP_ALIGN(region->x, 16) >> 4; + reg_regions->roi_pos_lt.roi_lt_y = MPP_ALIGN(region->y, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_x = MPP_ALIGN(region->x + region->w, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_y = MPP_ALIGN(region->y + region->h, 16) >> 4; + reg_regions->roi_base.roi_qp_value = region->quality; + reg_regions->roi_base.roi_qp_adj_mode = region->abs_qp_en; + reg_regions->roi_base.roi_en = 1; + reg_regions->roi_base.roi_pri = 0x1f; + if (region->intra) { + reg_regions->reg1063.roi0_mdc0_hevc.mdc_intra16 = 1; + reg_regions->roi_mdc_hevc.mdc_intra32 = 1; + } + reg_regions++; + } + +DONE: + return ret; +} diff --git a/mpp/hal/rkenc/common/vepu511a_common.h b/mpp/hal/rkenc/common/vepu511a_common.h new file mode 100644 index 000000000..ee79b8127 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu511a_common.h @@ -0,0 +1,3003 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef VEPU511A_COMMON_H +#define VEPU511A_COMMON_H + +#include "rk_venc_cmd.h" +#include "mpp_device.h" + +#define VEPU511A_CTL_OFFSET (0 * sizeof(RK_U32)) /* 0x00000000 reg0 - 0x00000120 reg72 */ +#define VEPU511A_FRAME_OFFSET (156 * sizeof(RK_U32)) /* 0x00000270 reg156 - 0x00000538 reg334 */ +#define VEPU511A_RC_ROI_OFFSET (1024 * sizeof(RK_U32)) /* 0x00001000 reg1024 - 0x00001160 reg1112 */ +#define VEPU511A_PARAM_OFFSET (1472 * sizeof(RK_U32)) /* 0x00001700 reg1472 - 0x000019cc reg1651 */ +#define VEPU511A_SQI_OFFSET (2048 * sizeof(RK_U32)) /* 0x00002000 reg2048 - 0x0000216c reg2139 */ +#define VEPU511A_SCL_OFFSET (2176 * sizeof(RK_U32)) /* 0x00002200 reg2176 - 0x00002c9c reg2855 */ +#define VEPU511A_SLI_OFFSET (2951 * sizeof(RK_U32)) /* 0x00002e20 reg2951 - 0x00002e40 reg2959 */ +#define VEPU511A_STATUS_OFFSET (4096 * sizeof(RK_U32)) /* 0x00004000 reg4096 - 0x0000424c reg4243 */ +#define VEPU511A_DBG_OFFSET (5120 * sizeof(RK_U32)) /* 0x00005000 reg5120 - 0x0000523c reg5263 */ +#define VEPU511A_REG_BASE_HW_STATUS (0x2c) + +#define VEPU511A_MAX_ROI_NUM 8 +#define VEPU511A_SLICE_FIFO_LEN 8 + +typedef enum qbias_ofst_e { + IFRAME_THD0 = 0, + IFRAME_THD1, + IFRAME_THD2, + IFRAME_BIAS0, + IFRAME_BIAS1, + IFRAME_BIAS2, + IFRAME_BIAS3, + PFRAME_THD0, + PFRAME_THD1, + PFRAME_THD2, + PFRAME_IBLK_BIAS0, + PFRAME_IBLK_BIAS1, + PFRAME_IBLK_BIAS2, + PFRAME_IBLK_BIAS3, + PFRAME_PBLK_BIAS0, + PFRAME_PBLK_BIAS1, + PFRAME_PBLK_BIAS2, + PFRAME_PBLK_BIAS3 +} QbiasOfst; + +typedef struct Vepu511aOnline_t { + /* 0x00000270 reg156 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsy_t : 28; + } adr_vsy_t; + + /* 0x00000274 reg157 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsc_t : 28; + } adr_vsc_t; + + /* 0x00000278 reg158 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsy_b : 28; + } adr_vsy_b; + + /* 0x0000027c reg159 */ + struct { + RK_U32 reserved : 4; + RK_U32 adr_vsc_b : 28; + } adr_vsc_b; +} vepu511a_online; + +typedef struct RdoB32SkipPar_t { + /* 0x00002060 reg2072 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 1; + RK_U32 flckr_frame_qp_en : 1; + RK_U32 flckr_lgt_chng_en : 1; + RK_U32 flckr_en : 1; + } atf_thd0; + + /* 0x00002064 reg2073 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd3 : 12; + RK_U32 reserved1 : 4; + } atf_thd1; + + /* 0x00002068 reg2074 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt0; + + /* 0x206c */ + RK_U32 reserved_2075; +} rdo_b32_skip_par; + +typedef struct RdoSkipPar_t { + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } atf_thd0; + + /* 0x00002064 reg2073 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd3 : 12; + RK_U32 reserved1 : 4; + } atf_thd1; + + /* 0x00002068 reg2074 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt0; + + /* 0x0000206c reg2075 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 reserved : 24; + } atf_wgt1; +} rdo_skip_par; + +typedef struct RdoB32NoSkipPar_t { + /* 0x00002080 reg2080 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } atf_thd0; + + /* 0x00002084 reg2081 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved1 : 4; + RK_U32 atf_bypass_pri_flag : 1; + RK_U32 flckr_zero_mv_j_coef : 5; + RK_U32 reserved2 : 10; + } atf_thd1; + + + /* 0x00002088 reg2082 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 reserved : 8; + } atf_wgt; +} rdo_b32_noskip_par; + +typedef struct RdoNoSkipPar_t { + /* 0x00002080 reg2080 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } ratf_thd0; + + /* 0x00002084 reg2081 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 20; + } ratf_thd1; + + /* 0x00002088 reg2082 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt; +} rdo_noskip_par; + +typedef struct Vepu511aRoiRegion_t { + struct { + RK_U32 roi_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_lt_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_lt; + + struct { + RK_U32 roi_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_rb_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_rb; + + struct { + RK_U32 roi_qp_value : 7; + RK_U32 roi_qp_adj_mode : 1; + RK_U32 roi_pri : 5; + RK_U32 roi_en : 1; + RK_U32 reserved : 18; + } roi_base; + + /* 0x0000109c reg1063 */ + union { + struct { + RK_U32 mdc_intra16 : 4; + RK_U32 mdc_inter16 : 4; + RK_U32 mdc_split16 : 4; + RK_U32 mdc_res_intra16 : 4; + RK_U32 mdc_res_inter16 : 4; + RK_U32 mdc_res_zeromv16 : 4; + RK_U32 mdc_dpth_hevc : 1; + RK_U32 reserved : 7; + } roi0_mdc0_hevc; + + struct { + RK_U32 roi0_mdc_intra16 : 4; + RK_U32 roi0_mdc_inter16 : 4; + RK_U32 roi0_mdc_skip16 : 4; + RK_U32 reserved : 20; + } roi0_mdc0_h264; + } reg1063; + + /* 0x000010a0 reg1064 */ + struct { + RK_U32 mdc_intra32 : 4; + RK_U32 mdc_inter32 : 4; + RK_U32 mdc_split32 : 4; + RK_U32 mdc_res_intra32 : 4; + RK_U32 mdc_res_inter32 : 4; + RK_U32 mdc_res_zeromv32 : 4; + RK_U32 reserved : 8; + } roi_mdc_hevc; +} Vepu511aRoiRegion; + +typedef struct Vepu511aRoiCfg_t { + /* 0x00001080 reg1056 */ + union { + struct { + RK_U32 fmdc_adju_intra16 : 4; + RK_U32 fmdc_adju_inter16 : 4; + RK_U32 fmdc_adju_split16 : 4; + RK_U32 fmdc_adju_res_intra16 : 4; + RK_U32 fmdc_adju_res_inter16 : 4; + RK_U32 fmdc_adju_res_zeromv16 : 4; + RK_U32 fmdc_adju_pri : 5; + RK_U32 reserved : 3; + } fmdc_adj0_hevc; + + struct { + RK_U32 fmdc_adju_intra16 : 4; + RK_U32 fmdc_adju_inter16 : 4; + RK_U32 fmdc_adju_skip16 : 4; + RK_U32 reserved : 12; + RK_U32 fmdc_adj_pri : 5; + RK_U32 reserved1 : 3; + } fmdc_adj0_h264; + } reg1056; + + /* 0x00001084 reg1057 */ + struct { + RK_U32 fmdc_adju_intra32 : 4; + RK_U32 fmdc_adju_inter32 : 4; + RK_U32 fmdc_adju_split32 : 4; + RK_U32 fmdc_adju_res_intra32 : 4; + RK_U32 fmdc_adju_res_inter32 : 4; + RK_U32 fmdc_adju_res_zeromv32 : 4; + RK_U32 fmdc_adju_split8 : 4; + RK_U32 fmdc_adju_lt_ref32 : 4; + } fmdc_adj1_hevc; + + RK_U32 reserved_1058; + + /* 0x0000108c reg1059 */ + struct { + RK_U32 bmap_en : 1; + RK_U32 bmap_pri : 5; + RK_U32 bmap_qpmin : 6; + RK_U32 bmap_qpmax : 6; + RK_U32 bmap_mdc_dpth : 1; + RK_U32 reserved : 13; + } bmap_cfg; + + /* 0x00001090 reg1060 - 0x0000112c reg1099 */ + Vepu511aRoiRegion regions[8]; +} Vepu511aRoiCfg; + +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct Vepu511aControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 h264_cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 reserved : 2; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } version; + + /* 0x00000004 - 0x0000000c */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 3; + RK_U32 reserved : 21; + } enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } enc_clr; + + /* 0x00000018 reg6 */ + struct { + RK_U32 vswm_lcnt_soft : 14; + RK_U32 vswm_fcnt_soft : 8; + RK_U32 reserved : 2; + RK_U32 dvbm_ack_soft : 1; + RK_U32 dvbm_ack_sel : 1; + RK_U32 dvbm_inf_sel : 1; + RK_U32 reserved1 : 5; + } vs_ldly; + + /* 0x0000001c */ + RK_U32 reserved_7; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 vslc_done_en : 1; + RK_U32 vbsf_oflw_en : 1; + RK_U32 vbuf_lens_en : 1; + RK_U32 enc_err_en : 1; + RK_U32 vsrc_err_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 lkt_err_stop_en : 1; + RK_U32 lkt_force_stop_en : 1; + RK_U32 jslc_done_en : 1; + RK_U32 jbsf_oflw_en : 1; + RK_U32 jbuf_lens_en : 1; + RK_U32 dvbm_err_en : 1; + RK_U32 reserved : 16; + } int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 vslc_done_msk : 1; + RK_U32 vbsf_oflw_msk : 1; + RK_U32 vbuf_lens_msk : 1; + RK_U32 enc_err_msk : 1; + RK_U32 vsrc_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_int_msk : 1; + RK_U32 lkt_err_stop_msk : 1; + RK_U32 lkt_force_stop_msk : 1; + RK_U32 jslc_done_msk : 1; + RK_U32 jbsf_oflw_msk : 1; + RK_U32 jbuf_lens_msk : 1; + RK_U32 dvbm_err_msk : 1; + RK_U32 reserved : 16; + } int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 vslc_done_clr : 1; + RK_U32 vbsf_oflw_clr : 1; + RK_U32 vbuf_lens_clr : 1; + RK_U32 enc_err_clr : 1; + RK_U32 vsrc_err_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_int_clr : 1; + RK_U32 lkt_err_stop_clr : 1; + RK_U32 lkt_force_stop_clr : 1; + RK_U32 jslc_done_clr : 1; + RK_U32 jbsf_oflw_clr : 1; + RK_U32 jbuf_lens_clr : 1; + RK_U32 dvbm_err_clr : 1; + RK_U32 reserved : 16; + } int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 vslc_done_sta : 1; + RK_U32 vbsf_oflw_sta : 1; + RK_U32 vbuf_lens_sta : 1; + RK_U32 enc_err_sta : 1; + RK_U32 vsrc_err_sta : 1; + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_int_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + RK_U32 jslc_done_sta : 1; + RK_U32 jbsf_oflw_sta : 1; + RK_U32 jbuf_lens_sta : 1; + RK_U32 dvbm_err_sta : 1; + RK_U32 reserved : 16; + } int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 jpeg_bus_edin : 4; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 4; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 rec_nfbc_bus_edin : 4; + } dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 jsrc_bus_edin : 4; + RK_U32 reserved : 12; + RK_U32 axi_brsp_cke : 10; + RK_U32 reserved1 : 6; + } dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 reserved : 8; + } enc_wdg; + + /* 0x0000003c reg15 */ + struct { + RK_U32 hurry_en : 1; + RK_U32 hurry_low : 3; + RK_U32 hurry_mid : 3; + RK_U32 hurry_high : 3; + RK_U32 qos_sub_e : 1; + RK_U32 reserved1 : 5; + RK_U32 qos_prt_mmu : 4; + RK_U32 qos_prt_rfpr : 4; + RK_U32 reserved2 : 8; + } qos_cfg; + + /* 0x00000040 reg16 */ + struct { + RK_U32 qos_ar_dprt : 4; + RK_U32 qos_ar_lprt : 4; + RK_U32 qos_ar_mprt : 4; + RK_U32 qos_ar_hprt : 4; + RK_U32 qos_aw_dprt : 4; + RK_U32 qos_aw_lprt : 4; + RK_U32 qos_aw_mprt : 4; + RK_U32 qos_aw_hprt : 4; + } qos_prty; + + /* 0x00000044 reg17 */ + RK_U32 hurry_thd_low; + + /* 0x00000048 reg18 */ + RK_U32 hurry_thd_mid; + + /* 0x0000004c reg19 */ + RK_U32 hurry_thd_high; + + /* 0x00000050 reg20 */ + struct { + RK_U32 qos_prt_mmu : 4; + RK_U32 qos_prt_rfpr : 4; + RK_U32 reserved1 : 24; + } qos_chid; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 rfpr_err_e : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 link_err_stop : 1; + RK_U32 reserved : 27; + } opt_strg; + + /* 0x00000058 reg22 */ + union { + struct { + RK_U32 tq8_ckg : 1; + RK_U32 tq4_ckg : 1; + RK_U32 bits_ckg_8x8 : 1; + RK_U32 bits_ckg_4x4_1 : 1; + RK_U32 bits_ckg_4x4_0 : 1; + RK_U32 inter_mode_ckg : 1; + RK_U32 inter_ctrl_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 reserved : 22; + } rdo_ckg_h264; + + struct { + RK_U32 recon32_ckg : 1; + RK_U32 iqit32_ckg : 1; + RK_U32 q32_ckg : 1; + RK_U32 t32_ckg : 1; + RK_U32 cabac32_ckg : 1; + RK_U32 recon16_ckg : 1; + RK_U32 iqit16_ckg : 1; + RK_U32 q16_ckg : 1; + RK_U32 t16_ckg : 1; + RK_U32 cabac16_ckg : 1; + RK_U32 recon8_ckg : 1; + RK_U32 iqit8_ckg : 1; + RK_U32 q8_ckg : 1; + RK_U32 t8_ckg : 1; + RK_U32 cabac8_ckg : 1; + RK_U32 recon4_ckg : 1; + RK_U32 iqit4_ckg : 1; + RK_U32 q4_ckg : 1; + RK_U32 t4_ckg : 1; + RK_U32 cabac4_ckg : 1; + RK_U32 intra32_ckg : 1; + RK_U32 intra16_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 reserved : 7; + } rdo_ckg_hevc; + } reg0022; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } core_id; + + /* 0x00000060 reg24 */ + struct { + RK_U32 dvbm_en : 1; + RK_U32 src_badr_sel : 1; + RK_U32 ptr_gbck : 1; + RK_U32 dvbm_vpu_fskp : 1; + RK_U32 dvbm_isp_cnct : 1; + RK_U32 dvbm_vepu_cnct : 1; + RK_U32 vepu_expt_type : 2; + RK_U32 vinf_dly_cycle : 8; + RK_U32 ybuf_full_mgn : 8; + RK_U32 ybuf_oflw_mgn : 8; + } dvbm_cfg; + + /* 0x64 */ + RK_U32 reserved_25; + + /* 0x00000068 reg26 */ + struct { + RK_U32 reserved : 4; + RK_U32 src_y_adr_str : 28; + } dvbm_y_sadr; + + /* 0x0000006c reg27 */ + struct { + RK_U32 reserved : 4; + RK_U32 src_c_adr_str : 28; + } dvbm_c_sadr; + + /* 0x00000070 reg28 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_y_top : 28; + } dvbm_y_top; + + /* 0x00000074 reg29 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_c_top : 28; + } dvbm_c_top; + + /* 0x00000078 reg30 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_y_botm : 28; + } dvbm_y_botm; + + /* 0x0000007c reg31 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_c_botm : 28; + } dvbm_c_botm; + + /* 0x00000080 reg32 */ + struct { + RK_U32 dvbm_y_line_strd0 : 17; + RK_U32 reserved : 15; + } dvbm_y_lstd0; + + /* 0x84 */ + RK_U32 reserved_33; + + /* 0x00000088 reg34 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_y_frm_strd0 : 28; + } dvbm_y_fstd0; + + /* 0x0000008c reg35 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_c_frm_strd0 : 28; + } dvbm_c_fstd0; + + /* 0x00000090 reg36 */ + struct { + RK_U32 dvbm_y_line_strd1 : 17; + RK_U32 reserved : 15; + } dvbm_y_lstd1; + + /* 0x94 */ + RK_U32 reserved_37; + + /* 0x00000098 reg38 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_y_frm_strd1 : 28; + } dvbm_y_fstd1; + + /* 0x0000009c reg39 */ + struct { + RK_U32 reserved : 4; + RK_U32 dvbm_c_frm_strd1 : 28; + } dvbm_c_fstd1; + + /* 0xa0 - 0xfc */ + RK_U32 reserved40_63[24]; + + /* 0x00000100 reg64 */ + struct { + RK_U32 node_core_id : 2; + RK_U32 node_int : 1; + RK_U32 reserved : 1; + RK_U32 task_id : 12; + RK_U32 bsw_cntd : 1; + RK_U32 bsw_cntd_jpeg : 1; + RK_U32 reserved1 : 14; + } lkt_node_cfg; + + /* 0x00000104 reg65 */ + struct { + RK_U32 pcfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_pcfg : 28; + } lkt_addr_pcfg; + + /* 0x00000108 reg66 */ + struct { + RK_U32 rc_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_rc_cfg : 28; + } lkt_addr_rc_cfg; + + /* 0x0000010c reg67 */ + struct { + RK_U32 par_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_par_cfg : 28; + } lkt_addr_par_cfg; + + /* 0x00000110 reg68 */ + struct { + RK_U32 sqi_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_sqi_cfg : 28; + } lkt_addr_sqi_cfg; + + /* 0x00000114 reg69 */ + struct { + RK_U32 scal_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_scal_cfg : 28; + } lkt_addr_scal_cfg; + + /* 0x00000118 reg70 */ + struct { + RK_U32 pp_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_pp_cfg : 28; + } lkt_addr_osd_cfg; + + /* 0x0000011c reg71 */ + struct { + RK_U32 st_rd_en : 1; + RK_U32 st_wr_en : 1; + RK_U32 reserved : 2; + RK_U32 lkt_addr_st : 28; + } lkt_addr_st; + + /* 0x00000120 reg72 */ + struct { + RK_U32 nxt_node_vld : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_nxt : 28; + } lkt_addr_nxt; +} Vepu511aControlCfg; + +/* 0x00000270 reg156 - 0x0000039c reg231 */ +typedef struct Vepu511aFrmCommon_t { + /* 0x00000270 reg156 - 0x0000027c reg159 */ + vepu511a_online online_addr; + + /* 0x00000280 reg160 */ + RK_U32 adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 colmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 colmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 adr_bsbs; + + /* 0x000002bc reg175 */ + RK_U32 bsbr_addr; + + /* 0x000002c0 reg176 */ + RK_U32 lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 ebuft_addr; + + /* 0x000002cc reg179 */ + RK_U32 ebufb_addr; + + /* 0x000002d0 reg180 */ + RK_U32 rfpt_h_addr; + + /* 0x000002d4 reg181 */ + RK_U32 rfpb_h_addr; + + /* 0x000002d8 reg182 */ + RK_U32 rfpt_b_addr; + + /* 0x000002dc reg183 */ + RK_U32 adr_rfpb_b; + + /* 0x000002e0 reg184 */ + RK_U32 adr_smear_rd; + + /* 0x000002e4 reg185 */ + RK_U32 adr_smear_wr; + + /* 0x000002e8 reg186 */ + RK_U32 adr_roir; + + /* 0x000002ec reg187 */ + RK_U32 eslf_badr; + + /* 0x000002f0 reg188 */ + RK_U32 rfp1r_h_addr; + + /* 0x000002f4 reg189 */ + RK_U32 rfp1r_b_addr; + + /* 0x000002f8 reg190 */ + RK_U32 dsp1r_addr; + + /* 0x2fc */ + RK_U32 reserved_191; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 meiw_mode : 1; + RK_U32 reserved : 2; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur_hevc : 5; + RK_U32 log2_ctu_num_hevc : 5; + RK_U32 rfpr_compress_mode : 1; + RK_U32 reserved1 : 2; + RK_U32 eslf_out_e_jpeg : 1; + RK_U32 jpeg_slen_fifo : 1; + RK_U32 eslf_out_e : 1; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } enc_pic; + + /* 0x00000304 reg193 */ + struct { + RK_U32 dchs_txid : 2; + RK_U32 dchs_rxid : 2; + RK_U32 dchs_txe : 1; + RK_U32 dchs_rxe : 1; + RK_U32 reserved : 2; + RK_U32 dchs_dly : 8; + RK_U32 dchs_ofst : 10; + RK_U32 reserved1 : 6; + } dual_core; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 frm_id_match : 1; + RK_U32 reserved : 3; + RK_U32 source_id : 1; + RK_U32 src_id_match : 1; + RK_U32 reserved1 : 2; + RK_U32 ch_id : 2; + RK_U32 vrsp_rtn_en : 1; + RK_U32 vinf_req_en : 1; + RK_U32 reserved2 : 12; + } enc_id; + + /* 0x0000030c reg195 */ + RK_U32 bsp_size; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 reserved1 : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved2 : 21; + } src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 cr_force_value : 8; + RK_U32 cb_force_value : 8; + RK_U32 chroma_force_en : 1; + RK_U32 reserved : 9; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 tile4x4_en : 1; + RK_U32 rkfbcd_en : 1; + RK_U32 reserved1 : 1; + } src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 21; + RK_U32 reserved : 11; + } src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } src_strd1; + + /* 0x33c - 0x34c */ + RK_U32 reserved207_211[5]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 reserved : 10; + RK_U32 rc_ctu_num : 20; + } rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } rc_tgt; + + /* 0x0000035c reg215 */ + struct { + RK_U32 eslf_rptr : 10; + RK_U32 eslf_wptr : 10; + RK_U32 eslf_blen : 10; + RK_U32 eslf_updt : 2; + } eslf_buf; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } sli_cnum; + + /* 0x0000036c reg219 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } vbs_pad; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cime_srch_dwnh : 4; + RK_U32 cime_srch_uph : 4; + RK_U32 cime_srch_rgtw : 4; + RK_U32 cime_srch_lftw : 4; + RK_U32 dlt_frm_num : 16; + } me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 srgn_max_num : 7; + RK_U32 cime_dist_thre : 13; + RK_U32 rme_srch_h : 2; + RK_U32 rme_srch_v : 2; + RK_U32 rme_dis : 3; + RK_U32 reserved : 1; + RK_U32 fme_dis : 3; + RK_U32 reserved1 : 1; + } me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cime_zero_thre : 13; + RK_U32 reserved : 15; + RK_U32 fme_prefsu_en : 2; + RK_U32 colmv_stor_hevc : 1; + RK_U32 colmv_load_hevc : 1; + } me_cach; + + /* 0x0000037c reg223 */ + struct { + RK_U32 ref_num : 1; + RK_U32 thre_zero_sad_dep0_cme : 6; + RK_U32 thre_zero_sad_dep1_cme : 6; + RK_U32 thre_zero_diff_dep1_cme : 3; + RK_U32 thre_zero_num_dep1_cme : 3; + RK_U32 thre_num_hit_dep1_cme : 2; + RK_U32 reserved : 7; + RK_U32 rfpw_mode : 1; + RK_U32 rfpr_mode : 1; + RK_U32 rfp1r_mode : 1; + RK_U32 reserved1 : 1; + } me_ref_comb; + + /* 0x380 - 0x39c */ + RK_U32 reserved224_231[8]; + +} Vepu511aFrmCommon; + +/* 0x520 reg328 - 0x538 reg334 */ +typedef struct Vepu511aPpFrameCfg_t { + /* 0x00000520 reg328 */ + RK_U32 adr_md_vpp; + + /* 0x00000524 reg329 */ + RK_U32 adr_od_vpp; + + /* 0x00000528 reg330 */ + RK_U32 adr_ref_mdw; + + /* 0x0000052c reg331 */ + RK_U32 adr_ref_mdr; + + /* 0x00000530 reg332 */ + struct { + RK_U32 sto_stride_md : 8; + RK_U32 sto_stride_od : 8; + RK_U32 cur_frm_en_md : 1; + RK_U32 ref_frm_en_md : 1; + RK_U32 switch_sad_md : 2; + RK_U32 night_mode_en_md : 1; + RK_U32 flycatkin_flt_en_md : 1; + RK_U32 en_od : 1; + RK_U32 background_en_od : 1; + RK_U32 sad_comp_en_od : 1; + RK_U32 reserved : 6; + RK_U32 vepu_pp_en : 1; + } vpp_base_cfg; + + /* 0x00000534 reg333 */ + struct { + RK_U32 thres_sad_md : 12; + RK_U32 thres_move_md : 3; + RK_U32 reserved : 1; + RK_U32 thres_dust_move_md : 4; + RK_U32 thres_dust_blk_md : 3; + RK_U32 reserved1 : 1; + RK_U32 thres_dust_chng_md : 8; + } thd_md_vpp; + + /* 0x00000538 reg334 */ + struct { + RK_U32 thres_complex_od : 12; + RK_U32 thres_complex_cnt_od : 3; + RK_U32 thres_sad_od : 14; + RK_U32 reserved : 3; + } thd_od_vpp; +} Vepu511aPpFrameCfg; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x00001160 reg1112 */ +typedef struct Vepu511aRcRoi_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 26; + } roi_qthd3; + + /* 0x00001040 reg1040 */ + RK_U32 reserved_1040; + + /* 0x00001044 reg1041 - 0x00001050 reg1044 */ + RK_U8 aq_tthd[16]; + + /* 0x00001054 reg1045 */ + struct { + RK_S32 aq_stp_s0 : 5; + RK_S32 aq_stp_0t1 : 5; + RK_S32 aq_stp_1t2 : 5; + RK_S32 aq_stp_2t3 : 5; + RK_S32 aq_stp_3t4 : 5; + RK_S32 aq_stp_4t5 : 5; + RK_S32 reserved : 2; + } aq_stp0; + + /* 0x00001058 reg1046 */ + struct { + RK_S32 aq_stp_5t6 : 5; + RK_S32 aq_stp_6t7 : 5; + RK_S32 aq_stp_7t8 : 5; + RK_S32 aq_stp_8t9 : 5; + RK_S32 aq_stp_9t10 : 5; + RK_S32 aq_stp_10t11 : 5; + RK_S32 reserved : 2; + } aq_stp1; + + /* 0x0000105c reg1047 */ + struct { + RK_S32 aq_stp_11t12 : 5; + RK_S32 aq_stp_12t13 : 5; + RK_S32 aq_stp_13t14 : 5; + RK_S32 aq_stp_14t15 : 5; + RK_S32 aq_stp_b15 : 5; + RK_U32 reserved : 7; + } aq_stp2; + + /* 0x00001060 reg1048 */ + struct { + RK_U32 aq16_rnge : 4; + RK_U32 aq32_rnge : 4; + RK_U32 aq8_rnge : 5; + RK_U32 aq16_dif0 : 5; + RK_U32 aq16_dif1 : 5; + RK_U32 reserved : 1; + RK_U32 aq_cme_en : 1; + RK_U32 aq_subj_cme_en : 1; + RK_U32 aq_rme_en : 1; + RK_U32 aq_subj_rme_en : 1; + RK_U32 reserved1 : 4; + } aq_clip; + + /* 0x00001064 reg1049 */ + struct { + RK_U32 madi_th0 : 8; + RK_U32 madi_th1 : 8; + RK_U32 madi_th2 : 8; + RK_U32 reserved : 8; + } madi_st_thd; + + /* 0x00001068 reg1050 */ + struct { + RK_U32 madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_th1 : 12; + RK_U32 reserved1 : 4; + } madp_st_thd0; + + /* 0x0000106c reg1051 */ + struct { + RK_U32 madp_th2 : 12; + RK_U32 reserved : 20; + } madp_st_thd1; + + /* 0x1070 - 0x1078 */ + RK_U32 reserved1052_1054[3]; + + /* 0x0000107c reg1055 */ + struct { + RK_U32 chrm_klut_ofst : 4; + RK_U32 reserved : 28; + } klut_ofst; + + /*0x00001080 reg1056 - 0x0000112c reg1099 */ + Vepu511aRoiCfg roi_cfg; + + /* 0x00001130 reg1100 */ + struct { + RK_U32 base_thre_rough_mad32_intra : 4; + RK_U32 delta0_thre_rough_mad32_intra : 4; + RK_U32 delta1_thre_rough_mad32_intra : 6; + RK_U32 delta2_thre_rough_mad32_intra : 6; + RK_U32 delta3_thre_rough_mad32_intra : 7; + RK_U32 delta4_thre_rough_mad32_intra_low5 : 5; + } cudecis_thd0; + + /* 0x00001134 reg1101 */ + struct { + RK_U32 delta4_thre_rough_mad32_intra_high2 : 2; + RK_U32 delta5_thre_rough_mad32_intra : 7; + RK_U32 delta6_thre_rough_mad32_intra : 7; + RK_U32 base_thre_fine_mad32_intra : 4; + RK_U32 delta0_thre_fine_mad32_intra : 4; + RK_U32 delta1_thre_fine_mad32_intra : 5; + RK_U32 delta2_thre_fine_mad32_intra_low3 : 3; + } cudecis_thd1; + + /* 0x00001138 reg1102 */ + struct { + RK_U32 delta2_thre_fine_mad32_intra_high2 : 2; + RK_U32 delta3_thre_fine_mad32_intra : 5; + RK_U32 delta4_thre_fine_mad32_intra : 5; + RK_U32 delta5_thre_fine_mad32_intra : 6; + RK_U32 delta6_thre_fine_mad32_intra : 6; + RK_U32 base_thre_str_edge_mad32_intra : 3; + RK_U32 delta0_thre_str_edge_mad32_intra : 2; + RK_U32 delta1_thre_str_edge_mad32_intra : 3; + } cudecis_thd2; + + /* 0x0000113c reg1103 */ + struct { + RK_U32 delta2_thre_str_edge_mad32_intra : 3; + RK_U32 delta3_thre_str_edge_mad32_intra : 4; + RK_U32 base_thre_str_edge_bgrad32_intra : 5; + RK_U32 delta0_thre_str_edge_bgrad32_intra : 2; + RK_U32 delta1_thre_str_edge_bgrad32_intra : 3; + RK_U32 delta2_thre_str_edge_bgrad32_intra : 4; + RK_U32 delta3_thre_str_edge_bgrad32_intra : 5; + RK_U32 base_thre_mad16_intra : 3; + RK_U32 delta0_thre_mad16_intra : 3; + } cudecis_thd3; + + /* 0x00001140 reg1104 */ + struct { + RK_U32 delta1_thre_mad16_intra : 3; + RK_U32 delta2_thre_mad16_intra : 4; + RK_U32 delta3_thre_mad16_intra : 5; + RK_U32 delta4_thre_mad16_intra : 5; + RK_U32 delta5_thre_mad16_intra : 6; + RK_U32 delta6_thre_mad16_intra : 6; + RK_U32 delta0_thre_mad16_ratio_intra : 3; + } cudecis_thd4; + + /* 0x00001144 reg1105 */ + struct { + RK_U32 delta1_thre_mad16_ratio_intra : 3; + RK_U32 delta2_thre_mad16_ratio_intra : 3; + RK_U32 delta3_thre_mad16_ratio_intra : 3; + RK_U32 delta4_thre_mad16_ratio_intra : 3; + RK_U32 delta5_thre_mad16_ratio_intra : 3; + RK_U32 delta6_thre_mad16_ratio_intra : 3; + RK_U32 delta7_thre_mad16_ratio_intra : 3; + RK_U32 delta0_thre_rough_bgrad32_intra : 3; + RK_U32 delta1_thre_rough_bgrad32_intra : 4; + RK_U32 delta2_thre_rough_bgrad32_intra_low4 : 4; + } cudecis_thd5; + + /* 0x00001148 reg1106 */ + struct { + RK_U32 delta2_thre_rough_bgrad32_intra_high2 : 2; + RK_U32 delta3_thre_rough_bgrad32_intra : 10; + RK_U32 delta4_thre_rough_bgrad32_intra : 10; + RK_U32 delta5_thre_rough_bgrad32_intra_low10 : 10; + } cudecis_thd6; + + /* 0x0000114c reg1107 */ + struct { + RK_U32 delta5_thre_rough_bgrad32_intra_high1 : 1; + RK_U32 delta6_thre_rough_bgrad32_intra : 12; + RK_U32 delta7_thre_rough_bgrad32_intra : 13; + RK_U32 delta0_thre_bgrad16_ratio_intra : 4; + RK_U32 delta1_thre_bgrad16_ratio_intra_low2 : 2; + } cudecis_thd7; + + /* 0x00001150 reg1108 */ + struct { + RK_U32 delta1_thre_bgrad16_ratio_intra_high2 : 2; + RK_U32 delta2_thre_bgrad16_ratio_intra : 4; + RK_U32 delta3_thre_bgrad16_ratio_intra : 4; + RK_U32 delta4_thre_bgrad16_ratio_intra : 4; + RK_U32 delta5_thre_bgrad16_ratio_intra : 4; + RK_U32 delta6_thre_bgrad16_ratio_intra : 4; + RK_U32 delta7_thre_bgrad16_ratio_intra : 4; + RK_U32 delta0_thre_fme_ratio_inter : 3; + RK_U32 delta1_thre_fme_ratio_inter : 3; + } cudecis_thd8; + + /* 0x00001154 reg1109 */ + struct { + RK_U32 delta2_thre_fme_ratio_inter : 3; + RK_U32 delta3_thre_fme_ratio_inter : 3; + RK_U32 delta4_thre_fme_ratio_inter : 3; + RK_U32 delta5_thre_fme_ratio_inter : 3; + RK_U32 delta6_thre_fme_ratio_inter : 3; + RK_U32 delta7_thre_fme_ratio_inter : 3; + RK_U32 base_thre_fme32_inter : 3; + RK_U32 delta0_thre_fme32_inter : 3; + RK_U32 delta1_thre_fme32_inter : 4; + RK_U32 delta2_thre_fme32_inter : 4; + } cudecis_thd9; + + /* 0x00001158 reg1110 */ + struct { + RK_U32 delta3_thre_fme32_inter : 5; + RK_U32 delta4_thre_fme32_inter : 6; + RK_U32 delta5_thre_fme32_inter : 7; + RK_U32 delta6_thre_fme32_inter : 8; + RK_U32 thre_cme32_inter : 6; + } cudecis_thd10; + + /* 0x0000115c reg1111 */ + struct { + RK_U32 delta0_thre_mad_fme_ratio_inter : 4; + RK_U32 delta1_thre_mad_fme_ratio_inter : 4; + RK_U32 delta2_thre_mad_fme_ratio_inter : 4; + RK_U32 delta3_thre_mad_fme_ratio_inter : 4; + RK_U32 delta4_thre_mad_fme_ratio_inter : 4; + RK_U32 delta5_thre_mad_fme_ratio_inter : 4; + RK_U32 delta6_thre_mad_fme_ratio_inter : 4; + RK_U32 delta7_thre_mad_fme_ratio_inter : 4; + } cudecis_thd11; + + /* 0x00001160 reg1112 */ + struct { + RK_U32 delta0_thre_mad_fme_ratio_inter : 4; + RK_U32 delta1_thre_mad_fme_ratio_inter : 4; + RK_U32 delta2_thre_mad_fme_ratio_inter : 4; + RK_U32 delta3_thre_mad_fme_ratio_inter : 4; + RK_U32 delta4_thre_mad_fme_ratio_inter : 4; + RK_U32 delta5_thre_mad_fme_ratio_inter : 4; + RK_U32 delta6_thre_mad_fme_ratio_inter : 4; + RK_U32 delta7_thre_mad_fme_ratio_inter : 4; + } cudecis_thd12; +} Vepu511aRcRoi; + +/* class: sli */ +/* 0x00002E20 reg2951 - 0x00002E40 reg2959 */ +typedef struct Vepu511aSli_t { + /* 0x2E20 ENT_SLI_ADD_DAT0 */ + struct { + RK_U32 before_every_slice_add_data0 : 32; + } ent_sli_add_dat0; + + /* 0x2E24 ENT_SLI_ADD_DAT1 */ + struct { + RK_U32 before_every_slice_add_data1 : 32; + } ent_sli_add_dat1; + + /* 0x2E28 ENT_SLI_ADD_DAT2 */ + struct { + RK_U32 before_every_slice_add_data2 : 32; + } ent_sli_add_dat2; + + /* 0x2E2C ENT_SLI_ADD_DAT3 */ + struct { + RK_U32 before_every_slice_add_data3 : 32; + } ent_sli_add_dat3; + + /* 0x2E30 ENT_SLI_ADD_DAT4 */ + struct { + RK_U32 after_frame_add_data0 : 32; + } ent_sli_add_dat4; + + /* 0x2E34 ENT_SLI_ADD_DAT5 */ + struct { + RK_U32 after_frame_add_data1 : 32; + } ent_sli_add_dat5; + + /* 0x2E38 ENT_SLI_ADD_DAT6 */ + struct { + RK_U32 after_frame_add_data2 : 32; + } ent_sli_add_dat6; + + /* 0x2E3C ENT_SLI_ADD_DAT7 */ + struct { + RK_U32 after_frame_add_data3 : 32; + } ent_sli_add_dat7; + + /* 0x2E40 ENT_SLI_ADD_BYTE */ + struct { + RK_U32 before_every_slice_add_byte_len : 5; + RK_U32 after_frame_add_byte_len : 5; + RK_U32 reserved1 : 22; + } ent_sli_add_byte; +} Vepu511aSli; + +/* class: st */ +/* 0x00004000 reg4096 - 0x0000424c reg4243*/ +typedef struct Vepu511aStatus_t { + /* 0x00004000 reg4096 */ + RK_U32 bs_lgth_l32; + + /* 0x00004004 reg4097 */ + struct { + RK_U32 bs_lgth_h8 : 8; + RK_U32 st_rc_lst_dqp : 6; + RK_U32 reserved : 2; + RK_U32 sse_l16 : 16; + } st_sse_bsl; + + /* 0x00004008 reg4098 */ + RK_U32 sse_h32; + + /* 0x0000400c reg4099 */ + RK_U32 qp_sum; + + /* 0x00004010 reg4100 */ + struct { + RK_U32 sao_cnum : 16; + RK_U32 sao_ynum : 16; + } st_sao; + + /* 0x00004014 reg4101 */ + RK_U32 rdo_head_bits; + + /* 0x00004018 reg4102 */ + struct { + RK_U32 rdo_head_bits_h8 : 8; + RK_U32 reserved : 8; + RK_U32 rdo_res_bits_l16 : 16; + } st_head_res_bl; + + /* 0x0000401c reg4103 */ + RK_U32 rdo_res_bits_h24; + + /* 0x00004020 reg4104 */ + struct { + RK_U32 st_enc : 2; + RK_U32 st_sclr : 1; + RK_U32 vepu_fbd_err : 5; + RK_U32 isp_src_oflw : 1; + RK_U32 vepu_src_oflw : 1; + RK_U32 vepu_sid_nmch : 1; + RK_U32 vepu_fcnt_nmch : 1; + RK_U32 reserved : 4; + RK_U32 dvbm_finf_wful : 1; + RK_U32 dvbm_linf_wful : 1; + RK_U32 dvbm_fsid_nmch : 1; + RK_U32 dvbm_fcnt_early : 1; + RK_U32 dvbm_fcnt_late : 1; + RK_U32 dvbm_isp_oflw : 1; + RK_U32 dvbm_vepu_oflw : 1; + RK_U32 isp_time_out : 1; + RK_U32 dvbm_vsrc_fcnt : 8; + } st_enc; + + /* 0x00004024 reg4105 */ + struct { + RK_U32 fnum_cfg_done : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 fnum_enc_done : 8; + } st_lkt; + + /* 0x00004028 reg4106 */ + struct { + RK_U32 reserved : 4; + RK_U32 node_addr : 28; + } st_nadr; + + /* 0x0000402c reg4107 */ + RK_U32 vbsbw_addr; + + /* 0x00004030 reg4108 */ + struct { + RK_U32 axib_idl : 8; + RK_U32 axib_ovfl : 8; + RK_U32 axib_err : 8; + RK_U32 axir_err : 8; + } st_bus; + + /* 0x00004034 reg4109 */ + struct { + RK_U32 sli_num_video : 8; + RK_U32 sli_num_jpeg : 8; + RK_U32 bpkt_num_video : 7; + RK_U32 bpkt_lst_video : 1; + RK_U32 bpkt_num_jpeg : 7; + RK_U32 bpkt_lst_jpeg : 1; + } st_snum; + + /* 0x00004038 reg4110 */ + struct { + RK_U32 sli_len : 30; + RK_U32 sli_lst : 1; + RK_U32 sli_sid : 1; + } st_slen; + + /* 0x0000403c reg4111 */ + struct { + RK_U32 task_id_proc : 12; + RK_U32 task_id_done : 12; + RK_U32 task_done : 1; + RK_U32 task_lkt_err : 3; + RK_U32 reserved : 4; + } st_link_task; + + /* 0x00004040 reg4112 */ + struct { + RK_U32 eslf_nptr : 10; + RK_U32 eslf_empty : 1; + RK_U32 eslf_full : 1; + RK_U32 eslf_sid : 1; + RK_U32 reserved : 19; + } st_eslf_nptr; + + /* 0x00004044 reg4113 */ + struct { + RK_U32 vsrd_posy : 10; + RK_U32 reserved : 5; + RK_U32 vsrd_fend : 1; + RK_U32 vsrd_posy_jpeg : 10; + RK_U32 reserved1 : 5; + RK_U32 vsrd_fend_jpeg : 1; + } st_vlsd_rlvl; + + /* 0x00004048 reg4114 */ + struct { + RK_U32 eslf_nptr_jpeg : 10; + RK_U32 eslf_empty_jpeg : 1; + RK_U32 eslf_full_jpeg : 1; + RK_U32 eslf_sid_jpeg : 1; + RK_U32 reserved : 19; + } st_eslf_nptr_jpeg; + + /* 0x404c - 0x405c */ + RK_U32 reserved4115_4119[5]; + + /* 0x00004060 reg4120 */ + struct { + RK_U32 sli_len_jpeg : 30; + RK_U32 sli_lst_jpeg : 1; + RK_U32 sli_sid_jpeg : 1; + } st_slen_jpeg; + + /* 0x00004064 reg4121 */ + RK_U32 jpeg_head_bits_l32; + + /* 0x00004068 reg4122 */ + struct { + RK_U32 jpeg_head_bits_h8 : 1; + RK_U32 reserved : 31; + } st_bsl_h8_jpeg; + + /* 0x0000406c reg4123 */ + RK_U32 jbsbw_addr; + + /* 0x00004070 reg4124 */ + RK_U32 luma_pix_sum_od; + + /* 0x4074 - 0x407c */ + RK_U32 reserved4125_4127[3]; + + /* 0x00004080 reg4128 */ + struct { + RK_U32 pnum_p64 : 17; + RK_U32 reserved : 15; + } st_pnum_p64; + + /* 0x00004084 reg4129 */ + struct { + RK_U32 pnum_p32 : 19; + RK_U32 reserved : 13; + } st_pnum_p32; + + /* 0x00004088 reg4130 */ + struct { + RK_U32 pnum_p16 : 21; + RK_U32 reserved : 11; + } st_pnum_p16; + + /* 0x0000408c reg4131 */ + struct { + RK_U32 pnum_p8 : 23; + RK_U32 reserved : 9; + } st_pnum_p8; + + /* 0x00004090 reg4132 */ + struct { + RK_U32 pnum_i32 : 19; + RK_U32 reserved : 13; + } st_pnum_i32; + + /* 0x00004094 reg4133 */ + struct { + RK_U32 pnum_i16 : 21; + RK_U32 reserved : 11; + } st_pnum_i16; + + /* 0x00004098 reg4134 */ + struct { + RK_U32 pnum_i8 : 23; + RK_U32 reserved : 9; + } st_pnum_i8; + + /* 0x0000409c reg4135 */ + struct { + RK_U32 pnum_i4 : 23; + RK_U32 reserved : 9; + } st_pnum_i4; + + /* 0x000040a0 reg4136 */ + struct { + RK_U32 num_b16 : 23; + RK_U32 reserved : 9; + } st_bnum_b16; + + /* 0x40a4 */ + RK_U32 reserved_4137; + + /* 0x000040a8 reg4138 */ + RK_U32 madi16_sum; + + /* 0x000040ac reg4139 */ + RK_U32 madi32_sum; + + /* 0x000040b0 reg4140 */ + RK_U32 madp16_sum; + + /* 0x000040b4 reg4141 */ + struct { + RK_U32 rdo_smear_cnt0 : 10; + RK_U32 reserved : 6; + RK_U32 rdo_smear_cnt1 : 10; + RK_U32 reserved1 : 6; + } st_smear_cnt0; + + /* 0x000040b8 reg4142 */ + struct { + RK_U32 rdo_smear_cnt2 : 10; + RK_U32 reserved : 6; + RK_U32 rdo_smear_cnt3 : 10; + RK_U32 reserved1 : 6; + } st_smear_cnt1; + + /* 0x40bc */ + RK_U32 reserved_4143; + + /* 0x000040c0 reg4144 */ + struct { + RK_U32 madi_th_lt_cnt0 : 16; + RK_U32 madi_th_lt_cnt1 : 16; + } st_madi_lt_num0; + + /* 0x000040c4 reg4145 */ + struct { + RK_U32 madi_th_lt_cnt2 : 16; + RK_U32 madi_th_lt_cnt3 : 16; + } st_madi_lt_num1; + + /* 0x000040c8 reg4146 */ + struct { + RK_U32 madi_th_rt_cnt0 : 16; + RK_U32 madi_th_rt_cnt1 : 16; + } st_madi_rt_num0; + + /* 0x000040cc reg4147 */ + struct { + RK_U32 madi_th_rt_cnt2 : 16; + RK_U32 madi_th_rt_cnt3 : 16; + } st_madi_rt_num1; + + /* 0x000040d0 reg4148 */ + struct { + RK_U32 madi_th_lb_cnt0 : 16; + RK_U32 madi_th_lb_cnt1 : 16; + } st_madi_lb_num0; + + /* 0x000040d4 reg4149 */ + struct { + RK_U32 madi_th_lb_cnt2 : 16; + RK_U32 madi_th_lb_cnt3 : 16; + } st_madi_lb_num1; + + /* 0x000040d8 reg4150 */ + struct { + RK_U32 madi_th_rb_cnt0 : 16; + RK_U32 madi_th_rb_cnt1 : 16; + } st_madi_rb_num0; + + /* 0x000040dc reg4151 */ + struct { + RK_U32 madi_th_rb_cnt2 : 16; + RK_U32 madi_th_rb_cnt3 : 16; + } st_madi_rb_num1; + + /* 0x000040e0 reg4152 */ + struct { + RK_U32 madp_th_lt_cnt0 : 16; + RK_U32 madp_th_lt_cnt1 : 16; + } st_madp_lt_num0; + + /* 0x000040e4 reg4153 */ + struct { + RK_U32 madp_th_lt_cnt2 : 16; + RK_U32 madp_th_lt_cnt3 : 16; + } st_madp_lt_num1; + + /* 0x000040e8 reg4154 */ + struct { + RK_U32 madp_th_rt_cnt0 : 16; + RK_U32 madp_th_rt_cnt1 : 16; + } st_madp_rt_num0; + + /* 0x000040ec reg4155 */ + struct { + RK_U32 madp_th_rt_cnt2 : 16; + RK_U32 madp_th_rt_cnt3 : 16; + } st_madp_rt_num1; + + /* 0x000040f0 reg4156 */ + struct { + RK_U32 madp_th_lb_cnt0 : 16; + RK_U32 madp_th_lb_cnt1 : 16; + } st_madp_lb_num0; + + /* 0x000040f4 reg4157 */ + struct { + RK_U32 madp_th_lb_cnt2 : 16; + RK_U32 madp_th_lb_cnt3 : 16; + } st_madp_lb_num1; + + /* 0x000040f8 reg4158 */ + struct { + RK_U32 madp_th_rb_cnt0 : 16; + RK_U32 madp_th_rb_cnt1 : 16; + } st_madp_rb_num0; + + /* 0x000040fc reg4159 */ + struct { + RK_U32 madp_th_rb_cnt2 : 16; + RK_U32 madp_th_rb_cnt3 : 16; + } st_madp_rb_num1; + + /* 0x00004100 reg4160 */ + struct { + RK_U32 cmv_th_lt_cnt0 : 16; + RK_U32 cmv_th_lt_cnt1 : 16; + } st_cmv_lt_num0; + + /* 0x00004104 reg4161 */ + struct { + RK_U32 cmv_th_lt_cnt2 : 16; + RK_U32 cmv_th_lt_cnt3 : 16; + } st_cmv_lt_num1; + + /* 0x00004108 reg4162 */ + struct { + RK_U32 cmv_th_rt_cnt0 : 16; + RK_U32 cmv_th_rt_cnt1 : 16; + } st_cmv_rt_num0; + + /* 0x0000410c reg4163 */ + struct { + RK_U32 cmv_th_rt_cnt2 : 16; + RK_U32 cmv_th_rt_cnt3 : 16; + } st_cmv_rt_num1; + + /* 0x00004110 reg4164 */ + struct { + RK_U32 cmv_th_lb_cnt0 : 16; + RK_U32 cmv_th_lb_cnt1 : 16; + } st_cmv_lb_num0; + + /* 0x00004114 reg4165 */ + struct { + RK_U32 cmv_th_lb_cnt2 : 16; + RK_U32 cmv_th_lb_cnt3 : 16; + } st_cmv_lb_num1; + + /* 0x00004118 reg4166 */ + struct { + RK_U32 cmv_th_rb_cnt0 : 16; + RK_U32 cmv_th_rb_cnt1 : 16; + } st_cmv_rb_num0; + + /* 0x0000411c reg4167 */ + struct { + RK_U32 cmv_th_rb_cnt2 : 16; + RK_U32 cmv_th_rb_cnt3 : 16; + } st_cmv_rb_num1; + + /* 0x00004120 reg4168 */ + struct { + RK_U32 org_y_r_max_value : 8; + RK_U32 org_y_r_min_value : 8; + RK_U32 org_u_g_max_value : 8; + RK_U32 org_u_g_min_value : 8; + } st_vsp_org_value0; + + /* 0x00004124 reg4169 */ + struct { + RK_U32 org_v_b_max_value : 8; + RK_U32 org_v_b_min_value : 8; + RK_U32 reserved : 16; + } st_vsp_org_value1; + + /* 0x00004128 reg4170 */ + struct { + RK_U32 jpeg_y_r_max_value : 8; + RK_U32 jpeg_y_r_min_value : 8; + RK_U32 jpeg_u_g_max_value : 8; + RK_U32 jpeg_u_g_min_value : 8; + } st_vsp_jpeg_value0; + + /* 0x0000412c reg4171 */ + struct { + RK_U32 jpeg_v_b_max_value : 8; + RK_U32 jpeg_v_b_min_value : 8; + RK_U32 reserved : 16; + } st_vsp_jpeg_value1; + + /* 0x00004130 reg4172 */ + RK_U32 dsp_y_sum; + + /* 0x00004134 reg4173 */ + struct { + RK_U32 acc_zero_mv : 18; + RK_U32 reserved1 : 14; + } st_mv_zero_sum; + + /* 0x00004138 reg4174 */ + struct { + RK_U32 ref1_inter8_num : 23; + RK_U32 reserved : 9; + } st_ref1_inter8; + + /* 0x0000413c reg4175 */ + struct { + RK_U32 acc_block_num : 18; + RK_U32 reserved : 14; + } st_blk_avb_sum; + + /* 0x00004140 reg4176 */ + struct { + RK_U32 num0_point_skin : 15; + RK_U32 acc_cmplx_num : 17; + } st_skin_sum0; + + /* 0x00004144 reg4177 */ + struct { + RK_U32 num1_point_skin : 15; + RK_U32 acc_cover16_num : 17; + } st_skin_sum1; + + /* 0x00004148 reg4178 */ + struct { + RK_U32 num2_point_skin : 15; + RK_U32 acc_bndry16_num : 17; + } st_skin_sum2; + + /* 0x0000414c reg4179 */ + RK_U32 num0_grdnt_point_dep0; + + /* 0x00004150 reg4180 */ + RK_U32 num1_grdnt_point_dep0; + + /* 0x00004154 reg4181 */ + RK_U32 num2_grdnt_point_dep0; + + /* 0x00004158 reg4182 */ + struct { + RK_U32 ref1_inter32_num : 19; + RK_U32 reserved : 13; + } st_ref1_inter32; + + /* 0x0000415c reg4183 */ + struct { + RK_U32 ref1_inter16_num : 21; + RK_U32 reserved : 11; + } st_ref1_inter16; + + /* 0x4160 - 0x417c */ + RK_U32 reserved4184_4191[8]; + + /* 0x00004180 reg4192 - 0x0000424c reg4243*/ + RK_U32 st_b8_qp[52]; +} Vepu511aStatus; + +/* class: dbg/st/axipn */ +/* 0x00005000 reg5120 - 0x0000523c reg5263 */ +typedef struct Vepu511aDbg_t { + /* 0x00005000 reg5120 */ + struct { + RK_U32 vsp0_pos_x : 16; + RK_U32 vsp0_pos_y : 16; + } st_ppl_pos_vsp0; + + /* 0x00005004 reg5121 */ + struct { + RK_U32 vsp1_pos_x : 16; + RK_U32 vsp1_pos_y : 16; + } st_ppl_pos_vsp1; + + /* 0x00005008 reg5122 */ + struct { + RK_U32 vsp2_pos_x : 16; + RK_U32 vsp2_pos_y : 16; + } st_ppl_pos_vsp2; + + /* 0x0000500c reg5123 */ + struct { + RK_U32 cme_pos_x : 16; + RK_U32 cme_pos_y : 16; + } st_ppl_pos_cme; + + /* 0x00005010 reg5124 */ + struct { + RK_U32 swin_cmd_x : 16; + RK_U32 swin_cmd_y : 16; + } st_ppl_cmd_swin; + + /* 0x00005014 reg5125 */ + struct { + RK_U32 swin_pos_x : 16; + RK_U32 swin_pos_y : 16; + } st_ppl_pos_swin; + /* 0x00005018 reg5126 */ + struct { + RK_U32 pren_pos_x : 16; + RK_U32 pren_pos_y : 16; + } st_ppl_pos_pren; + + /* 0x0000501c reg5127 */ + struct { + RK_U32 rfme_pos_x : 16; + RK_U32 rfme_pos_y : 16; + } st_ppl_pos_rfme; + + /* 0x00005020 reg5128 */ + struct { + RK_U32 rdo_pos_x : 16; + RK_U32 rdo_pos_y : 16; + } st_ppl_pos_rdo; + + /* 0x00005024 reg5129 */ + struct { + RK_U32 lpf_pos_x : 16; + RK_U32 lpf_pos_y : 16; + } st_ppl_pos_lpf; + + /* 0x00005028 reg5130 */ + struct { + RK_U32 etpy_pos_x : 16; + RK_U32 etpy_pos_y : 16; + } st_ppl_pos_etpy; + + /* 0x0000502c reg5131 */ + struct { + RK_U32 jsp0_pos_x : 16; + RK_U32 jsp0_pos_y : 16; + } st_ppl_pos_jsp0; + + /* 0x00005030 reg5132 */ + struct { + RK_U32 jsp1_pos_x : 16; + RK_U32 jsp1_pos_y : 16; + } st_ppl_pos_jsp1; + + /* 0x00005034 reg5133 */ + struct { + RK_U32 jsp2_pos_x : 16; + RK_U32 jsp2_pos_y : 16; + } st_ppl_pos_jsp2; + + /* 0x00005038 reg5134 */ + struct { + RK_U32 jpeg_pos_x : 16; + RK_U32 jpeg_pos_y : 16; + } st_ppl_pos_jpeg; + + /* 0x0000503c reg5135 */ + struct { + RK_U32 vhdr_pos_y : 16; + RK_U32 jhdr_pos_y : 16; + } dbg_pos_pp_hdr; + + /* 0x00005040 reg5136 */ + struct { + RK_U32 reserved : 7; + RK_U32 vsp0_cmd_flst : 1; + RK_U32 reserved1 : 24; + } dbg_ctrl_vsp0; + + /* 0x00005044 reg5137 - 0x00005048 reg5138*/ + RK_U32 reserved[2]; + + /* 0x0000504c reg5139 */ + struct { + RK_U32 cme_madp_vld : 1; + RK_U32 cme_madp_rdy0 : 1; + RK_U32 cme_madp_rdy1 : 1; + RK_U32 reserved : 1; + RK_U32 cme_mv16_vld : 1; + RK_U32 cme_mv16_rdy : 1; + RK_U32 cme_st_vld : 1; + RK_U32 cme_st_rdy : 1; + RK_U32 cme_stat_vld : 1; + RK_U32 cme_stat_rdy : 1; + RK_U32 cme_diff_vld : 1; + RK_U32 cme_diff_rdy : 1; + RK_U32 cme_cmmv_vld : 1; + RK_U32 cme_cmmv_rdy : 1; + RK_U32 cme_smvp_vld : 1; + RK_U32 cme_smvp_rdy : 1; + RK_U32 rdo_tmvp_rvld : 1; + RK_U32 rdo_tmvp_rrdy : 1; + RK_U32 rdo_tmvp_wvld : 1; + RK_U32 rdo_tmvp_wrdy : 1; + RK_U32 rdo_lbf_wvld : 1; + RK_U32 rdo_lbf_wrdy : 1; + RK_U32 rdo_lbf_rvld : 1; + RK_U32 rdo_lbf_rrdy : 1; + RK_U32 rdo_rfmv_rvld : 1; + RK_U32 rdo_rfmv_rrdy : 1; + RK_U32 rdo_hevc_qp_vld : 1; + RK_U32 rdo_hevc_qp_rdy : 1; + RK_U32 reserved1 : 4; + } dbg_hs_ppl; + + /* 0x00005050 reg5140 */ + struct { + RK_U32 swin_org_err : 1; + RK_U32 swin_ref_err : 1; + RK_U32 reserved1 : 10; + RK_U32 swin_cmd_vld : 1; + RK_U32 swin_cmd_rdy : 1; + RK_U32 reserved2 : 2; + RK_U32 swin_buff_ptr : 2; + RK_U32 swin_buff_num0 : 2; + RK_U32 swin_buff_num1 : 2; + RK_U32 swin_buff_num2 : 2; + RK_U32 swin_wrk_ena : 1; + RK_U32 reserved3 : 3; + RK_U32 swin_wrk : 1; + RK_U32 swin_tout : 1; + RK_U32 reserved4 : 2; + } dbg_ctrl_swin; + + /* 0x00005054 reg5141 */ + struct { + RK_U32 pnra_org_err : 1; + RK_U32 pnra_qp_err : 1; + RK_U32 pnra_rfme_err : 1; + RK_U32 reserved : 9; + RK_U32 pnra_olm_vld : 1; + RK_U32 pnra_olm_rdy : 1; + RK_U32 pnra_subj_vld : 1; + RK_U32 pnra_subj_rdy : 1; + RK_U32 reserved1 : 8; + RK_U32 pnra_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 pnra_wrk : 1; + RK_U32 pnra_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_pren; + + /* 0x00005058 reg5142 */ + struct { + RK_U32 rfme_org_err : 1; + RK_U32 rfme_ref_err : 1; + RK_U32 rfme_cmmv_err : 1; + RK_U32 rfme_rfmv_err : 1; + RK_U32 rfme_tmvp_err : 1; + RK_U32 rfme_qp_err : 1; + RK_U32 rfme_pnra_err : 1; + RK_U32 reserved1 : 5; + RK_U32 rfme_tmvp_vld : 1; + RK_U32 rfme_tmvp_rdy : 1; + RK_U32 rfme_smvp_vld : 1; + RK_U32 rfme_smvp_rdy : 1; + RK_U32 rfme_cmmv_vld : 1; + RK_U32 rfme_cmmv_rdy : 1; + RK_U32 rfme_rfmv_vld : 1; + RK_U32 rfme_rfmv_rdy : 1; + RK_U32 reserved2 : 4; + RK_U32 rfme_wrk_ena : 1; + RK_U32 reserved3 : 3; + RK_U32 rfme_wrk : 1; + RK_U32 rfme_tout : 1; + RK_U32 reserved4 : 2; + } dbg_ctrl_rfme; + + /* 0x0000505c reg5143 */ + struct { + RK_U32 rdo_org_err : 1; + RK_U32 rdo_ref_err : 1; + RK_U32 rdo_inf_err : 1; + RK_U32 rdo_coef_err : 1; + RK_U32 rdo_lbfr_err : 1; + RK_U32 rdo_lbfw_err : 1; + RK_U32 rdo_madi_lbf_err : 1; + RK_U32 rdo_tmvp_wr_err : 1; + RK_U32 rdo_smear_err : 1; + RK_U32 rdo_mbqp_err : 1; + RK_U32 rdo_rc_err : 1; + RK_U32 rdo_ent_err : 1; + RK_U32 rdo_lpf_err : 1; + RK_U32 rdo_st_err : 1; + RK_U32 rdo_tmvp_rd_err : 1; + RK_U32 rdo_rfmv_err : 1; + RK_U32 reserved : 12; + RK_U32 rdo_wrk : 1; + RK_U32 rdo_tout : 1; + RK_U32 reserved1 : 2; + } dbg_ctrl_rdo; + + /* 0x00005060 reg5144 */ + struct { + RK_U32 lpf_org_err : 1; + RK_U32 lpf_rdo_err : 1; + RK_U32 reserved : 10; + RK_U32 lpf_rcol_vld : 1; + RK_U32 lpf_rcol_rdy : 1; + RK_U32 lpf_lbf_wvld : 1; + RK_U32 lpf_lbf_wrdy : 1; + RK_U32 lpf_lbf_rvld : 1; + RK_U32 lpf_lbf_rrdy : 1; + RK_U32 reserved1 : 6; + RK_U32 lpf_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 lpf_wrk : 1; + RK_U32 lpf_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_lpf; + + /* 0x00005064 reg5145 */ + struct { + RK_U32 reserved : 12; + RK_U32 etpy_slf_full : 1; + RK_U32 etpy_bsw_vld : 1; + RK_U32 etpy_bsw_rdy : 1; + RK_U32 reserved1 : 9; + RK_U32 etpy_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 etpy_wrk : 1; + RK_U32 etpy_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_etpy; + + /* 0x00005068 reg5146 */ + struct { + RK_U32 jhdr_src_err : 1; + RK_U32 jhdr_cmd_flst : 1; + RK_U32 reserved : 2; + RK_U32 jsp0_org_err : 1; + RK_U32 jsp0_pp2_err : 1; + RK_U32 jsp0_paral_err : 1; + RK_U32 jsp0_cmd_flst : 1; + RK_U32 jhdr_vld : 1; + RK_U32 jhdr_rdy : 1; + RK_U32 jsp0_cmd_vld : 1; + RK_U32 jsp0_cmd_rdy : 1; + RK_U32 reserved1 : 12; + RK_U32 jsp0_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 jsp0_wrk : 1; + RK_U32 jsp0_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_jsp0; + + /* 0x0000506c reg5147 */ + struct { + RK_U32 jsp2_org_err : 1; + RK_U32 reserved : 11; + RK_U32 jsp2_madi_vld : 1; + RK_U32 jsp2_madi_rdy : 1; + RK_U32 reserved1 : 10; + RK_U32 jsp2_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 jsp2_wrk : 1; + RK_U32 jsp2_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_jsp2; + + /* 0x00005070 reg5148 */ + struct { + RK_U32 jpeg_org_err : 1; + RK_U32 jpeg_st_err : 1; + RK_U32 reserved : 10; + RK_U32 jpg_slf_full : 1; + RK_U32 jpg_bsw_vld : 1; + RK_U32 jpg_bsw_rdy : 1; + RK_U32 reserved1 : 9; + RK_U32 jpeg_wrk_ena : 1; + RK_U32 reserved2 : 3; + RK_U32 jpeg_wrk : 1; + RK_U32 jpeg_tout : 1; + RK_U32 reserved3 : 2; + } dbg_ctrl_jpeg; + + /* 0x00005074 reg5149 */ + struct { + RK_U32 vsp1_org_err : 1; + RK_U32 reserved : 7; + RK_U32 vsp1_wrk_ena : 1; + RK_U32 reserved1 : 3; + RK_U32 vsp1_wrk : 1; + RK_U32 vsp1_tout : 1; + RK_U32 reserved2 : 2; + RK_U32 jsp1_org_err : 1; + RK_U32 reserved3 : 7; + RK_U32 jsp1_wrk_ena : 1; + RK_U32 reserved4 : 3; + RK_U32 jsp1_wrk : 1; + RK_U32 jsp1_tout : 1; + RK_U32 reserved5 : 2; + } dbg_ctrl_pp1; + + /* 0x00005078 reg5150 */ + struct { + RK_U32 pp2_frm_done : 1; + RK_U32 cime_frm_done : 1; + RK_U32 jpeg_frm_done : 1; + RK_U32 rdo_frm_done : 1; + RK_U32 lpf_frm_done : 1; + RK_U32 ent_frm_done : 1; + RK_U32 reserved : 2; + RK_U32 criw_frm_done : 1; + RK_U32 meiw_frm_done : 1; + RK_U32 smiw_frm_done : 1; + RK_U32 dma_frm_idle : 1; + RK_U32 reserved1 : 12; + RK_U32 video_ena : 1; + RK_U32 jpeg_ena : 1; + RK_U32 vepu_pp_ena : 1; + RK_U32 reserved2 : 1; + RK_U32 frm_wrk : 1; + RK_U32 frm_tout : 1; + RK_U32 reserved3 : 2; + } dbg_tctrl; + + /* 0x0000507c reg5151 */ + struct { + RK_U32 enc_frm_cur : 3; + RK_U32 lkt_src_paus : 1; + RK_U32 lkt_cfg_paus : 1; + RK_U32 reserved : 27; + } dbg_frm_task; + + /* 0x00005080 reg5152 */ + struct { + RK_U32 sli_num : 15; + RK_U32 reserved : 17; + } st_sli_num; + + /* 0x5084 - 0x50fc */ + RK_U32 reserved5153_5183[31]; + + /* 0x00005100 reg5184 */ + struct { + RK_U32 empty_oafifo : 1; + RK_U32 full_cmd_oafifo : 1; + RK_U32 full_data_oafifo : 1; + RK_U32 empty_iafifo : 1; + + RK_U32 full_cmd_iafifo : 1; + RK_U32 full_info_iafifo : 1; + RK_U32 fbd_brq_st : 4; + RK_U32 fbd_hdr_vld : 1; + RK_U32 fbd_bmng_end : 1; + + RK_U32 nfbd_req_st : 4; + RK_U32 acc_axi_cmd : 8; + RK_U32 reserved : 8; + } dbg_pp_st; + + /* 0x00005104 reg5185 */ + struct { + RK_U32 r_ena_lambd : 1; + RK_U32 r_fst_swinw_end : 1; + RK_U32 r_swinw_end : 1; + RK_U32 r_cnt_swinw : 1; + + RK_U32 r_dspw_end : 1; + RK_U32 r_dspw_cnt : 1; + RK_U32 i_sjgen_work : 1; + RK_U32 r_end_rspgen : 1; + + RK_U32 r_cost_gate : 1; + RK_U32 r_ds_gate : 1; + RK_U32 r_mvp_gate : 1; + RK_U32 i_smvp_arrdy : 1; + + RK_U32 i_smvp_arvld : 1; + RK_U32 i_stptr_wrdy : 1; + RK_U32 i_stptr_wvld : 1; + RK_U32 i_rdy_atf : 1; + + RK_U32 i_vld_atf : 1; + RK_U32 i_rdy_bmv16 : 1; + RK_U32 i_vld_bmv16 : 1; + RK_U32 i_wr_dsp : 1; + + RK_U32 i_rdy_dsp : 1; + RK_U32 i_vld_dsp : 1; + RK_U32 r_rdy_org : 1; + RK_U32 i_vld_org : 1; + + RK_U32 i_rdy_state : 1; + RK_U32 i_vld_state : 1; + RK_U32 i_rdy_madp : 1; + RK_U32 i_vld_madp : 1; + + RK_U32 i_rdy_diff : 1; + RK_U32 i_vld_diff : 1; + RK_U32 reserved : 2; + } dbg_cime_st; + + /* 0x00005108 reg5186 */ + RK_U32 swin_dbg_inf; + + /* 0x0000510c reg5187 */ + struct { + RK_U32 bbrq_cmps_left_len2 : 1; + RK_U32 bbrq_cmps_left_len1 : 1; + RK_U32 cmps_left_len0 : 1; + RK_U32 bbrq_rdy2 : 1; + RK_U32 dcps_vld2 : 1; + RK_U32 bbrq_rdy1 : 1; + RK_U32 dcps_vld1 : 1; + RK_U32 bbrq_rdy0 : 1; + RK_U32 dcps_vld0 : 1; + RK_U32 hb_rdy2 : 1; + RK_U32 bbrq_vld2 : 1; + RK_U32 hb_rdy1 : 1; + RK_U32 bbrq_vld1 : 1; + RK_U32 hb_rdy0 : 1; + RK_U32 bbrq_vld0 : 1; + RK_U32 idle_msb2 : 1; + RK_U32 idle_msb1 : 1; + RK_U32 idle_msb0 : 1; + RK_U32 cur_state_dcps : 1; + RK_U32 cur_state_bbrq : 1; + RK_U32 cur_state_hb : 1; + RK_U32 cke_bbrq_dcps : 1; + RK_U32 cke_dcps : 1; + RK_U32 cke_bbrq : 1; + RK_U32 rdy_lwcd_rsp : 1; + RK_U32 vld_lwcd_rsp : 1; + RK_U32 rdy_lwcd_req : 1; + RK_U32 vld_lwcd_req : 1; + RK_U32 rdy_lwrsp : 1; + RK_U32 vld_lwrsp : 1; + RK_U32 rdy_lwreq : 1; + RK_U32 vld_lwreq : 1; + } dbg_fbd_hhit0; + + /* 0x00005110 reg5188 */ + RK_U32 rfme_dbg_inf; + + /* 0x5114 */ + RK_U32 reserved_5189; + + /* 0x00005118 reg5190 */ + RK_U32 dbg0_fbd; + + /* 0x0000511c reg5191 */ + RK_U32 dbg1_fbd; + + /* 0x00005120 reg5192 */ + RK_U32 rdo_dbg0; + + /* 0x00005124 reg5193 */ + RK_U32 rdo_dbg1; + + /* 0x00005128 reg5194 */ + struct { + RK_U32 h264_sh_st_cs : 4; + RK_U32 rsd_st_cs : 4; + RK_U32 h264_sd_st_cs : 5; + RK_U32 etpy_rdy : 1; + RK_U32 reserved : 18; + } dbg_etpy; + + /* 0x0000512c reg5195 */ + struct { + RK_U32 chl_aw_vld : 10; + RK_U32 chl_aw_rdy : 10; + RK_U32 aw_vld_arb : 1; + RK_U32 aw_rdy_arb : 1; + RK_U32 aw_vld_crosclk : 1; + RK_U32 aw_rdy_crosclk : 1; + RK_U32 aw_rdy_mmu : 1; + RK_U32 aw_vld_mmu : 1; + RK_U32 aw_rdy_axi : 1; + RK_U32 aw_vld_axi : 1; + RK_U32 reserved : 4; + } dbg_dma_aw; + + /* 0x00005130 reg5196 */ + struct { + RK_U32 chl_w_vld : 10; + RK_U32 chl_w_rdy : 10; + RK_U32 w_vld_arb : 1; + RK_U32 w_rdy_arb : 1; + RK_U32 w_vld_crosclk : 1; + RK_U32 w_rdy_crosclk : 1; + RK_U32 w_rdy_mmu : 1; + RK_U32 w_vld_mmu : 1; + RK_U32 w_rdy_axi : 1; + RK_U32 w_vld_axi : 1; + RK_U32 reserved : 4; + } dbg_dma_w; + + /* 0x00005134 reg5197 */ + struct { + RK_U32 chl_ar_vld : 9; + RK_U32 chl_ar_rdy : 9; + RK_U32 reserved : 2; + RK_U32 ar_vld_arb : 1; + RK_U32 ar_rdy_arb : 1; + RK_U32 ar_vld_crosclk : 1; + RK_U32 ar_rdy_crosclk : 1; + RK_U32 ar_rdy_mmu : 1; + RK_U32 ar_vld_mmu : 1; + RK_U32 ar_rdy_axi : 1; + RK_U32 ar_vld_axi : 1; + RK_U32 reserved1 : 4; + } dbg_dma_ar; + + /* 0x00005138 reg5198 */ + struct { + RK_U32 chl_r_vld : 9; + RK_U32 chl_r_rdy : 9; + RK_U32 reserved : 2; + RK_U32 r_vld_arb : 1; + RK_U32 r_rdy_arb : 1; + RK_U32 r_vld_crosclk : 1; + RK_U32 r_rdy_crosclk : 1; + RK_U32 r_rdy_mmu : 1; + RK_U32 r_vld_mmu : 1; + RK_U32 r_rdy_axi : 1; + RK_U32 r_vld_axi : 1; + RK_U32 b_rdy_mmu : 1; + RK_U32 b_vld_mmu : 1; + RK_U32 b_rdy_axi : 1; + RK_U32 b_vld_axi : 1; + } dbg_dma_r; + + /* 0x0000513c reg5199 */ + struct { + RK_U32 dbg_sclr : 20; + RK_U32 dbg_arb : 12; + } dbg_dma_dbg0; + + /* 0x00005140 reg5200 */ + struct { + RK_U32 bsw_fsm_stus : 4; + RK_U32 bsw_aw_full : 1; + RK_U32 bsw_rdy_ent : 1; + RK_U32 bsw_vld_ent : 1; + RK_U32 jpg_bsw_stus : 4; + RK_U32 jpg_aw_full : 1; + RK_U32 jpg_bsw_rdy : 1; + RK_U32 jpg_bsw_vld : 1; + RK_U32 crpw_fsm_stus : 3; + RK_U32 hdwr_rdy : 1; + RK_U32 hdwr_vld : 1; + RK_U32 bdwr_rdy : 1; + RK_U32 bdwr_vld : 1; + RK_U32 nfbc_rdy : 1; + RK_U32 nfbc_vld : 1; + RK_U32 dsp_fsm_stus : 2; + RK_U32 dsp_wr_flg : 1; + RK_U32 dsp_rsy : 1; + RK_U32 dsp_vld : 1; + RK_U32 lpfw_fsm_stus : 3; + RK_U32 reserved : 1; + } dbg_dma_dbg1; + + /* 0x00005144 reg5201 */ + struct { + RK_U32 awvld_mdo : 1; + RK_U32 awrdy_mdo : 1; + RK_U32 wvld_mdo : 1; + RK_U32 wrdy_mdo : 1; + RK_U32 awvld_odo : 1; + RK_U32 awrdy_odo : 1; + RK_U32 wvld_odo : 1; + RK_U32 wrdy_odo : 1; + RK_U32 awvld_rfmw : 1; + RK_U32 awrdy_rfmw : 1; + RK_U32 wvld_rfmw : 1; + RK_U32 wrdy_rfmw : 1; + RK_U32 arvld_rfmr : 1; + RK_U32 arrdy_rfmr : 1; + RK_U32 rvld_rfmr : 1; + RK_U32 rrdy_rfmr : 1; + RK_U32 reserved : 16; + } dbg_dma_vpp; + + /* 0x00005148 reg5202 */ + struct { + RK_U32 rdo_st : 20; + RK_U32 reserved : 12; + } dbg_rdo_st; + + /* 0x0000514c reg5203 */ + struct { + RK_U32 lpf_work : 1; + RK_U32 rdo_par_nrdy : 1; + RK_U32 rdo_rcn_nrdy : 1; + RK_U32 lpf_rcn_rdy : 1; + RK_U32 dblk_work : 1; + RK_U32 sao_work : 1; + RK_U32 reserved : 18; + RK_U32 tile_bdry_read : 1; + RK_U32 tile_bdry_write : 1; + RK_U32 tile_bdry_rrdy : 1; + RK_U32 rdo_read_tile_bdry : 1; + RK_U32 rdo_write_tile_bdry : 1; + RK_U32 reserved1 : 3; + } dbg_lpf; + + /* 0x5150 */ + RK_U32 reserved_5204; + + /* 0x00005154 reg5205 */ + RK_U32 dbg0_cache; + + /* 0x00005158 reg5206 */ + RK_U32 dbg2_fbd; + + /* 0x515c */ + RK_U32 reserved_5207; + + /* 0x00005160 reg5208 */ + struct { + RK_U32 ebuf_diff_cmd : 8; + RK_U32 lbuf_lpf_ncnt : 7; + RK_U32 lbuf_lpf_cien : 1; + RK_U32 lbuf_rdo_ncnt : 7; + RK_U32 lbuf_rdo_cien : 1; + RK_U32 lbuf_tctrl_ncnt : 7; + RK_U32 lbuf_tctrl_cien : 1; + } dbg_lbuf0; + + /* 0x00005164 reg5209 */ + struct { + RK_U32 rvld_ebfr : 1; + RK_U32 rrdy_ebfr : 1; + RK_U32 arvld_ebfr : 1; + RK_U32 arrdy_ebfr : 1; + RK_U32 wvld_ebfw : 1; + RK_U32 wrdy_ebfw : 1; + RK_U32 awvld_ebfw : 1; + RK_U32 awrdy_ebfw : 1; + RK_U32 lpf_lbuf_rvld : 1; + RK_U32 lpf_lbuf_rrdy : 1; + RK_U32 lpf_lbuf_wvld : 1; + RK_U32 lpf_lbuf_wrdy : 1; + RK_U32 rdo_lbuf_rvld : 1; + RK_U32 rdo_lbuf_rrdy : 1; + RK_U32 rdo_lbuf_wvld : 1; + RK_U32 rdo_lbuf_wrdy : 1; + RK_U32 fme_lbuf_rvld : 1; + RK_U32 fme_lbuf_rrdy : 1; + RK_U32 cme_lbuf_rvld : 1; + RK_U32 cme_lbuf_rrdy : 1; + RK_U32 smear_lbuf_rvld : 1; + RK_U32 smear_lbuf_rrdy : 1; + RK_U32 smear_lbuf_wvld : 1; + RK_U32 smear_lbuf_wrdy : 1; + RK_U32 depth_lbuf_wvld : 1; + RK_U32 depth_lbuf_wrdy : 1; + RK_U32 rdo_lbufw_flag : 1; + RK_U32 rdo_lbufr_flag : 1; + RK_U32 cme_lbufr_flag : 1; + RK_U32 reserved : 3; + } dbg_lbuf1; + + /* 0x00005168 reg5210 */ + struct { + RK_U32 dbg_isp_fcnt : 8; + RK_U32 dbg_isp_fcyc : 24; + } dbg_dvbm_isp0; + + /* 0x0000516c reg5211 */ + struct { + RK_U32 dbg_isp_lcnt : 14; + RK_U32 reserved : 1; + RK_U32 dbg_isp_ltgl : 1; + RK_U32 dbg_isp_fcnt : 8; + RK_U32 dbg_isp_oflw : 1; + RK_U32 dbg_isp_ftgl : 1; + RK_U32 dbg_isp_full : 1; + RK_U32 dbg_isp_work : 1; + RK_U32 dbg_isp_lvld : 1; + RK_U32 dbg_isp_lrdy : 1; + RK_U32 dbg_isp_fvld : 1; + RK_U32 dbg_isp_frdy : 1; + } dbg_dvbm_isp1; + + /* 0x00005170 reg5212 */ + struct { + RK_U32 dbg_bf0_isp_lcnt : 14; + RK_U32 dbg_bf0_isp_llst : 1; + RK_U32 dbg_bf0_isp_sofw : 1; + RK_U32 dbg_bf0_isp_fcnt : 8; + RK_U32 dbg_bf0_isp_fsid : 1; + RK_U32 reserved : 5; + RK_U32 dbg_bf0_isp_pnt : 1; + RK_U32 dbg_bf0_vpu_pnt : 1; + } dbg_dvbm_buf0_inf0; + + /* 0x00005174 reg5213 */ + struct { + RK_U32 dbg_bf0_src_lcnt : 14; + RK_U32 dbg_bf0_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf0_vpu_lcnt : 14; + RK_U32 dbg_bf0_vpu_llst : 1; + RK_U32 dbg_bf0_vpu_vofw : 1; + } dbg_dvbm_buf0_inf1; + + /* 0x00005178 reg5214 */ + struct { + RK_U32 dbg_bf1_isp_lcnt : 14; + RK_U32 dbg_bf1_isp_llst : 1; + RK_U32 dbg_bf1_isp_sofw : 1; + RK_U32 dbg_bf1_isp_fcnt : 8; + RK_U32 dbg_bf1_isp_fsid : 1; + RK_U32 reserved : 5; + RK_U32 dbg_bf1_isp_pnt : 1; + RK_U32 dbg_bf1_vpu_pnt : 1; + } dbg_dvbm_buf1_inf0; + + /* 0x0000517c reg5215 */ + struct { + RK_U32 dbg_bf1_src_lcnt : 14; + RK_U32 dbg_bf1_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf1_vpu_lcnt : 14; + RK_U32 dbg_bf1_vpu_llst : 1; + RK_U32 dbg_bf1_vpu_vofw : 1; + } dbg_dvbm_buf1_inf1; + + /* 0x00005180 reg5216 */ + struct { + RK_U32 dbg_bf2_isp_lcnt : 14; + RK_U32 dbg_bf2_isp_llst : 1; + RK_U32 dbg_bf2_isp_sofw : 1; + RK_U32 dbg_bf2_isp_fcnt : 1; + RK_U32 dbg_bf2_isp_fsid : 1; + RK_U32 reserved : 12; + RK_U32 dbg_bf2_isp_pnt : 1; + RK_U32 dbg_bf2_vpu_pnt : 1; + } dbg_dvbm_buf2_inf0; + + /* 0x00005184 reg5217 */ + struct { + RK_U32 dbg_bf2_src_lcnt : 14; + RK_U32 dbg_bf2_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf2_vpu_lcnt : 14; + RK_U32 dbg_bf2_vpu_llst : 1; + RK_U32 dbg_bf2_vpu_vofw : 1; + } dbg_dvbm_buf2_inf1; + + /* 0x00005188 reg5218 */ + struct { + RK_U32 dbg_bf3_isp_lcnt : 14; + RK_U32 dbg_bf3_isp_llst : 1; + RK_U32 dbg_bf3_isp_sofw : 1; + RK_U32 dbg_bf3_isp_fcnt : 1; + RK_U32 dbg_bf3_isp_fsid : 1; + RK_U32 reserved : 12; + RK_U32 dbg_bf3_isp_pnt : 1; + RK_U32 dbg_bf3_vpu_pnt : 1; + } dbg_dvbm_buf3_inf0; + + /* 0x0000518c reg5219 */ + struct { + RK_U32 dbg_bf3_src_lcnt : 14; + RK_U32 dbg_bf3_src_llst : 1; + RK_U32 reserved : 1; + RK_U32 dbg_bf3_vpu_lcnt : 14; + RK_U32 dbg_bf3_vpu_llst : 1; + RK_U32 dbg_bf3_vpu_vofw : 1; + } dbg_dvbm_buf3_inf1; + + /* 0x00005190 reg5220 */ + struct { + RK_U32 dbg_isp_fptr : 3; + RK_U32 dbg_isp_full : 1; + RK_U32 dbg_src_fptr : 3; + RK_U32 reserved : 1; + RK_U32 dbg_vpu_fptr : 3; + RK_U32 dbg_vpu_empt : 1; + RK_U32 dbg_vpu_lvld : 1; + RK_U32 dbg_vpu_lrdy : 1; + RK_U32 dbg_vpu_fvld : 1; + RK_U32 dbg_vpu_frdy : 1; + RK_U32 dbg_fcnt_misp : 4; + RK_U32 dbg_fcnt_mvpu : 4; + RK_U32 dbg_fcnt_sofw : 4; + RK_U32 dbg_fcnt_vofw : 4; + } dbg_dvbm_ctrl; + + /* 0x5194 - 0x519c */ + RK_U32 reserved5221_5223[3]; + + /* 0x000051a0 reg5224 */ + RK_U32 dbg_dvbm_buf0_yadr; + + /* 0x000051a4 reg5225 */ + RK_U32 dbg_dvbm_buf0_cadr; + + /* 0x000051a8 reg5226 */ + RK_U32 dbg_dvbm_buf1_yadr; + + /* 0x000051ac reg5227 */ + RK_U32 dbg_dvbm_buf1_cadr; + + /* 0x000051b0 reg5228 */ + RK_U32 dbg_dvbm_buf2_yadr; + + /* 0x000051b4 reg5229 */ + RK_U32 dbg_dvbm_buf2_cadr; + + /* 0x000051b8 reg5230 */ + RK_U32 dbg_dvbm_buf3_yadr; + + /* 0x000051bc reg5231 */ + RK_U32 dbg_dvbm_buf3_cadr; + + /* 0x000051c0 reg5232 */ + struct { + RK_U32 dchs_rx_cnt : 11; + RK_U32 dchs_rx_id : 2; + RK_U32 dchs_rx_en : 1; + RK_U32 dchs_rx_ack : 1; + RK_U32 dchs_rx_req : 1; + RK_U32 dchs_tx_cnt : 11; + RK_U32 dchs_tx_id : 2; + RK_U32 dchs_tx_en : 1; + RK_U32 dchs_tx_ack : 1; + RK_U32 dchs_tx_req : 1; + } dbg_dchs_intfc; + + /* 0x000051c4 reg5233 */ + struct { + RK_U32 lpfw_tx_cnt : 11; + RK_U32 lpfw_tx_en : 1; + RK_U32 crpw_tx_cnt : 11; + RK_U32 crpw_tx_en : 1; + RK_U32 dual_err_updt : 1; + RK_U32 dlyc_fifo_oflw : 1; + RK_U32 dlyc_tx_vld : 1; + RK_U32 dlyc_tx_rdy : 1; + RK_U32 dlyc_tx_empty : 1; + RK_U32 dchs_tx_idle : 1; + RK_U32 dchs_tx_asy : 1; + RK_U32 dchs_tx_syn : 1; + } dbg_dchs_tx_inf0; + + /* 0x000051c8 reg5234 */ + struct { + RK_U32 criw_tx_cnt : 11; + RK_U32 criw_tx_en : 1; + RK_U32 smrw_tx_cnt : 11; + RK_U32 smrw_tx_en : 1; + RK_U32 reserved : 8; + } dbg_dchs_tx_inf1; + + /* 0x000051cc reg5235 */ + struct { + RK_U32 dual_rx_cnt : 11; + RK_U32 dual_rx_id : 2; + RK_U32 dual_rx_en : 1; + RK_U32 dual_rx_syn : 1; + RK_U32 dual_rx_lock : 1; + RK_U32 dual_lpfr_dule : 1; + RK_U32 dual_cime_dule : 1; + RK_U32 dual_clomv_dule : 1; + RK_U32 dual_smear_dule : 1; + RK_U32 reserved : 12; + } dbg_dchs_rx_inf0; + + /* 0x51d0 - 0x51fc */ + RK_U32 reserved5236_5247[12]; + + /* 0x00005200 reg5248 */ + RK_U32 frame_cyc; + + /* 0x00005204 reg5249 */ + RK_U32 vsp0_fcyc; + + /* 0x00005208 reg5250 */ + RK_U32 vsp1_fcyc; + + /* 0x0000520c reg5251 */ + RK_U32 vsp2_fcyc; + + /* 0x00005210 reg5252 */ + RK_U32 cme_fcyc; + + /* 0x00005214 reg5253 */ + RK_U32 ldr_fcyc; + + /* 0x00005218 reg5254 */ + RK_U32 rfme_fcyc; + + /* 0x0000521c reg5255 */ + RK_U32 pnra_fcyc; + + /* 0x00005220 reg5256 */ + RK_U32 rdo_fcyc; + + /* 0x00005224 reg5257 */ + RK_U32 lpf_fcyc; + + /* 0x00005228 reg5258 */ + RK_U32 etpy_fcyc; + + /* 0x522c */ + RK_U32 reserved_5259; + + /* 0x00005230 reg5260 */ + RK_U32 jsp0_fcyc; + + /* 0x00005234 reg5261 */ + RK_U32 jsp1_fcyc; + + /* 0x00005238 reg5262 */ + RK_U32 jsp2_fcyc; + + /* 0x0000523c reg5263 */ + RK_U32 jpeg_fcyc; + +} Vepu511aDbg; + +/* ROI block configuration */ +typedef struct Vepu511aH264RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_skip : 4; + RK_U32 mdc_adju_intra : 4; + RK_U32 reserved : 12; +} Vepu511aH264RoiBlkCfg; + +typedef struct Vepu511aH265RoiBlkCfg { + RK_U32 qp_adju : 8; + RK_U32 mdc_adju_intra : 4; + RK_U32 mdc_adju_inter : 4; + RK_U32 mdc_adju_split : 4; + RK_U32 mdc_adju_res_intra : 4; + RK_U32 mdc_adju_res_inter : 4; + RK_U32 mdc_adju_res_mv0 : 4; +} Vepu511aH265RoiBlkCfg; + +typedef struct Vepu511aH265RoiDpt1BlkCfg { + //W0 + RK_U32 cu32_qp_adju : 8; + RK_U32 cu32_mdc_adju_intra : 4; + RK_U32 cu32_mdc_adju_inter : 4; + RK_U32 cu32_mdc_adju_split : 4; + RK_U32 cu32_mdc_adju_res_intra : 4; + RK_U32 cu32_mdc_adju_res_inter : 4; + RK_U32 cu32_mdc_adju_res_mv0 : 4; + //W1 + RK_U32 cu16_0_qp_adju : 8; + RK_U32 cu16_0_mdc_adju_intra : 4; + RK_U32 cu16_0_mdc_adju_inter : 4; + RK_U32 cu16_0_mdc_adju_split : 4; + RK_U32 cu16_0_mdc_adju_res_intra : 4; + RK_U32 cu16_0_mdc_adju_res_inter : 4; + RK_U32 cu16_0_mdc_adju_res_mv0 : 4; + //W2 + RK_U32 cu16_1_qp_adju : 8; + RK_U32 cu16_1_mdc_adju_intra : 4; + RK_U32 cu16_1_mdc_adju_inter : 4; + RK_U32 cu16_1_mdc_adju_split : 4; + RK_U32 cu16_1_mdc_adju_res_intra : 4; + RK_U32 cu16_1_mdc_adju_res_inter : 4; + RK_U32 cu16_1_mdc_adju_res_mv0 : 4; + //W3 + RK_U32 cu16_2_qp_adju : 8; + RK_U32 cu16_2_mdc_adju_intra : 4; + RK_U32 cu16_2_mdc_adju_inter : 4; + RK_U32 cu16_2_mdc_adju_split : 4; + RK_U32 cu16_2_mdc_adju_res_intra : 4; + RK_U32 cu16_2_mdc_adju_res_inter : 4; + RK_U32 cu16_2_mdc_adju_res_mv0 : 4; + //W4 + RK_U32 cu16_3_qp_adju : 8; + RK_U32 cu16_3_mdc_adju_intra : 4; + RK_U32 cu16_3_mdc_adju_inter : 4; + RK_U32 cu16_3_mdc_adju_split : 4; + RK_U32 cu16_3_mdc_adju_res_intra : 4; + RK_U32 cu16_3_mdc_adju_res_inter : 4; + RK_U32 cu16_3_mdc_adju_res_mv0 : 4; +} Vepu511aH265RoiDpt1BlkCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vepu511a_set_roi(Vepu511aRoiCfg *roi_reg_base, MppEncROICfg * roi, RK_S32 w, RK_S32 h); + +#ifdef __cplusplus +} +#endif + +#endif /* VEPU511A_COMMON_H */ diff --git a/mpp/hal/rkenc/common/vepu540c_common.c b/mpp/hal/rkenc/common/vepu540c_common.c new file mode 100644 index 000000000..ce1dfa969 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu540c_common.c @@ -0,0 +1,262 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vepu540c_common" + +#include + +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "jpege_syntax.h" +#include "vepu5xx_common.h" +#include "vepu540c_common.h" +#include "hal_enc_task.h" +#include "mpp_frame_impl.h" +#include "mpp_packet.h" + +MPP_RET vepu540c_set_roi(void *roi_reg_base, MppEncROICfg * roi, + RK_S32 w, RK_S32 h) +{ + MppEncROIRegion *region = roi->regions; + Vepu540cRoiCfg *roi_cfg = (Vepu540cRoiCfg *)roi_reg_base; + Vepu540cRoiRegion *reg_regions = &roi_cfg->regions[0]; + MPP_RET ret = MPP_NOK; + RK_S32 i = 0; + memset(reg_regions, 0, sizeof(Vepu540cRoiRegion) * 8); + if (NULL == roi_cfg || NULL == roi) { + mpp_err_f("invalid buf %p roi %p\n", roi_cfg, roi); + goto DONE; + } + + if (roi->number > VEPU540C_MAX_ROI_NUM) { + mpp_err_f("invalid region number %d\n", roi->number); + goto DONE; + } + + /* check region config */ + ret = MPP_OK; + for (i = 0; i < (RK_S32) roi->number; i++, region++) { + if (region->x + region->w > w || region->y + region->h > h) + ret = MPP_NOK; + + if (region->intra > 1 + || region->qp_area_idx >= VEPU540C_MAX_ROI_NUM + || region->area_map_en > 1 || region->abs_qp_en > 1) + ret = MPP_NOK; + + if ((region->abs_qp_en && region->quality > 51) || + (!region->abs_qp_en + && (region->quality > 51 || region->quality < -51))) + ret = MPP_NOK; + + if (ret) { + mpp_err_f("region %d invalid param:\n", i); + mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n", + region->x, region->y, region->w, region->h, w, + h); + mpp_err_f("force intra %d qp area index %d\n", + region->intra, region->qp_area_idx); + mpp_err_f("abs qp mode %d value %d\n", + region->abs_qp_en, region->quality); + goto DONE; + } + reg_regions->roi_pos_lt.roi_lt_x = MPP_ALIGN(region->x, 16) >> 4; + reg_regions->roi_pos_lt.roi_lt_y = MPP_ALIGN(region->y, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_x = MPP_ALIGN(region->x + region->w, 16) >> 4; + reg_regions->roi_pos_rb.roi_rb_y = MPP_ALIGN(region->y + region->h, 16) >> 4; + reg_regions->roi_base.roi_qp_value = region->quality; + reg_regions->roi_base.roi_qp_adj_mode = region->abs_qp_en; + reg_regions->roi_base.roi_en = 1; + reg_regions->roi_base.roi_pri = 0x1f; + if (region->intra) { + reg_regions->roi_mdc.roi_mdc_intra16 = 1; + reg_regions->roi_mdc.roi0_mdc_intra32_hevc = 1; + } + reg_regions++; + } + +DONE: + return ret; +} + +static MPP_RET vepu540c_jpeg_set_patch_info(MppDev dev, JpegeSyntax *syn, + VepuFmt input_fmt, + HalEncTask *task) +{ + RK_U32 hor_stride = syn->hor_stride; + RK_U32 ver_stride = (syn->ver_stride != 0) ? syn->ver_stride : syn->height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + u_offset = mpp_frame_get_fbc_offset(task->frame); + v_offset = 0; + mpp_log("fbc case u_offset = %d", u_offset); + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + default: { + mpp_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + + /* input cb addr */ + if (u_offset) + mpp_dev_set_reg_offset(dev, 265, u_offset); + + /* input cr addr */ + if (v_offset) + mpp_dev_set_reg_offset(dev, 266, v_offset); + + return ret; +} + + +MPP_RET vepu540c_set_jpeg_reg(Vepu540cJpegCfg *cfg) +{ + HalEncTask *task = ( HalEncTask *)cfg->enc_task; + JpegeSyntax *syn = (JpegeSyntax *)task->syntax.data; + Vepu540cJpegReg *regs = (Vepu540cJpegReg *)cfg->jpeg_reg_base; + VepuFmtCfg *fmt = (VepuFmtCfg *)cfg->input_fmt; + RK_U32 pic_width_align8, pic_height_align8; + RK_S32 stridey = 0; + RK_S32 stridec = 0; + + pic_width_align8 = (syn->width + 7) & (~7); + pic_height_align8 = (syn->height + 7) & (~7); + + regs->reg0264_adr_src0 = mpp_buffer_get_fd(task->input); + regs->reg0265_adr_src1 = regs->reg0264_adr_src0; + regs->reg0266_adr_src2 = regs->reg0264_adr_src0; + + vepu540c_jpeg_set_patch_info(cfg->dev, syn, (VepuFmt)fmt->format, task); + + regs->reg0256_adr_bsbt = mpp_buffer_get_fd(task->output); + regs->reg0257_adr_bsbb = regs->reg0256_adr_bsbt; + regs->reg0258_adr_bsbs = regs->reg0256_adr_bsbt; + regs->reg0259_adr_bsbr = regs->reg0256_adr_bsbt; + + mpp_dev_set_reg_offset(cfg->dev, 258, task->length + task->hw_length); + mpp_dev_set_reg_offset(cfg->dev, 256, mpp_buffer_get_size(task->output)); + + regs->reg0272_enc_rsl.pic_wd8_m1 = pic_width_align8 / 8 - 1; + regs->reg0273_src_fill.pic_wfill = ((syn->width & 0x7) != 0) + ? (8 - (syn->width & 0x7)) : 0; + regs->reg0272_enc_rsl.pic_hd8_m1 = pic_height_align8 / 8 - 1; + regs->reg0273_src_fill.pic_hfill = ((syn->height & 0x7) != 0) + ? (8 - (syn->height & 0x7)) : 0; + + regs->reg0274_src_fmt.src_cfmt = fmt->format; + regs->reg0274_src_fmt.alpha_swap = fmt->alpha_swap; + regs->reg0274_src_fmt.rbuv_swap = fmt->rbuv_swap; + regs->reg0274_src_fmt.src_range_trns_en = 0; + regs->reg0274_src_fmt.src_range_trns_sel = 0; + regs->reg0274_src_fmt.chroma_ds_mode = 0; + regs->reg0274_src_fmt.out_fmt = 1; + + regs->reg0279_src_proc.src_mirr = 0 ;//prep_cfg->mirroring > 0; + regs->reg0279_src_proc.src_rot = syn->rotation; + + if (syn->hor_stride) { + stridey = syn->hor_stride; + } else { + if (regs->reg0274_src_fmt.src_cfmt == VEPU5xx_FMT_BGRA8888) + stridey = syn->width * 4; + else if (regs->reg0274_src_fmt.src_cfmt == VEPU5xx_FMT_BGR888) + stridey = syn->width * 3; + else if (regs->reg0274_src_fmt.src_cfmt == VEPU5xx_FMT_BGR565 || + regs->reg0274_src_fmt.src_cfmt == VEPU5xx_FMT_YUYV422 || + regs->reg0274_src_fmt.src_cfmt == VEPU5xx_FMT_UYVY422) + stridey = syn->width * 2; + } + + stridec = (regs->reg0274_src_fmt.src_cfmt == VEPU5xx_FMT_YUV422SP || + regs->reg0274_src_fmt.src_cfmt == VEPU5xx_FMT_YUV420SP) ? + stridey : stridey / 2; + + if (regs->reg0274_src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + regs->reg0275_src_udfy.csc_wgt_r2y = 66; + regs->reg0275_src_udfy.csc_wgt_g2y = 129; + regs->reg0275_src_udfy.csc_wgt_b2y = 25; + + regs->reg0276_src_udfu.csc_wgt_r2u = -38; + regs->reg0276_src_udfu.csc_wgt_g2u = -74; + regs->reg0276_src_udfu.csc_wgt_b2u = 112; + + regs->reg0277_src_udfv.csc_wgt_r2v = 112; + regs->reg0277_src_udfv.csc_wgt_g2v = -94; + regs->reg0277_src_udfv.csc_wgt_b2v = -18; + + regs->reg0278_src_udfo.csc_ofst_y = 16; + regs->reg0278_src_udfo.csc_ofst_u = 128; + regs->reg0278_src_udfo.csc_ofst_v = 128; + } + regs->reg0281_src_strd0.src_strd0 = stridey; + regs->reg0282_src_strd1.src_strd1 = stridec; + regs->reg0280_pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg0280_pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + //to be done + + // no 0283 ? + // regs->reg0283_src_flt.pp_corner_filter_strength = 0; + // regs->reg0283_src_flt.pp_edge_filter_strength = 0; + // regs->reg0283_src_flt.pp_internal_filter_strength = 0; + + regs->reg0284_y_cfg.bias_y = 0; + regs->reg0285_u_cfg.bias_u = 0; + regs->reg0286_v_cfg.bias_v = 0; + + regs->reg0287_base_cfg.jpeg_ri = 0; + regs->reg0287_base_cfg.jpeg_out_mode = 0; + regs->reg0287_base_cfg.jpeg_start_rst_m = 0; + regs->reg0287_base_cfg.jpeg_pic_last_ecs = 1; + regs->reg0287_base_cfg.jpeg_slen_fifo = 0; + regs->reg0287_base_cfg.jpeg_stnd = 1; //enable + + regs->reg0288_uvc_cfg.uvc_partition0_len = 0; + regs->reg0288_uvc_cfg.uvc_partition_len = 0; + regs->reg0288_uvc_cfg.uvc_skip_len = 0; + return MPP_OK; +} diff --git a/mpp/hal/rkenc/common/vepu540c_common.h b/mpp/hal/rkenc/common/vepu540c_common.h new file mode 100644 index 000000000..c53382641 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu540c_common.h @@ -0,0 +1,1781 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VEPU540C_COMMON_H +#define VEPU540C_COMMON_H + +#include "rk_venc_cmd.h" +#include "mpp_device.h" + +#define VEPU540C_CTL_OFFSET (0 * sizeof(RK_U32)) +#define VEPU540C_BASE_OFFSET (156 * sizeof(RK_U32)) +#define VEPU540C_RCROI_OFFSET (1024 * sizeof(RK_U32)) +#define VEPU540C_WEG_OFFSET (1472 * sizeof(RK_U32)) +#define VEPU540C_RDOCFG_OFFSET (2048 * sizeof(RK_U32)) +#define VEPU540C_SCLCFG_OFFSET (2168 * sizeof(RK_U32)) +#define VEPU540C_JPEGTAB_OFFSET (2848 * sizeof(RK_U32)) + +#define VEPU540C_OSD_OFFSET (3072 * sizeof(RK_U32)) +#define VEPU540C_STATUS_OFFSET (4096 * sizeof(RK_U32)) +#define VEPU540C_DEBUG_OFFSET (5120 * sizeof(RK_U32)) +#define VEPU540C_REG_BASE_HW_STATUS 0x2c + +#define VEPU540C_MAX_ROI_NUM 8 +#define VEPU540C_SLICE_FIFO_LEN 8 + +typedef union { + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 vslc_done_sta : 1; + RK_U32 vbsf_oflw_sta : 1; + RK_U32 vbuf_lens_sta : 1; + RK_U32 enc_err_sta : 1; + RK_U32 dvbm_fcfg_sta : 1; + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_int_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + RK_U32 jslc_done_sta : 1; + RK_U32 jbsf_oflw_sta : 1; + RK_U32 jbuf_lens_sta : 1; + RK_U32 dvbm_dcnt_sta : 1; + RK_U32 reserved : 16; + } int_sta; + + RK_U32 val; +} vepu540c_hw_status; + +typedef struct Vepu540cOnline_t { + /* 0x00000270 reg156 */ + RK_U32 reg0156_adr_vsy_t; + /* 0x00000274 reg157 */ + RK_U32 reg0157_adr_vsc_t; + /* 0x00000278 reg158 */ + RK_U32 reg0158_adr_vsy_b; + /* 0x0000027c reg159 */ + RK_U32 reg0159_adr_vsc_b; +} vepu540c_online; + +typedef struct IpRaw8_t { + RK_U8 intra_val[8]; + RK_U8 inter_val[8]; +} ip_raw8; + +typedef struct IpRaw32_16_t { + RK_U16 q_intra16[4]; + RK_U16 q_intra32[2]; + RK_U8 iq_intra16[4]; +} ip_raw32_16; + +/* 0x000021e0 reg2168 - 0x00002c7c reg2847*/ +typedef struct Vepu540cSclCfg_t { + /* 0x000021e0 reg2168 */ + RK_U32 q_dc_y16; + RK_U32 q_dc_u16; + RK_U32 q_dc_v16; + RK_U32 q_dc_y32; + RK_U32 iq_dc_0; + RK_U32 iq_dc_1; + + /* 0x000021f8 reg2174 */ + struct { + RK_U32 scal_clk_sel : 1; + RK_U32 reserved : 31; + } scal_cfg; + /* 0x21fc */ + RK_U32 reserved_2175; + /* 0x00002200 reg2176 - 0x0000227c reg2207*/ + RK_U16 q_intra_y8[64]; + /* 0x00002280 reg2208 - 0x000022fc reg2239*/ + RK_U16 q_intra_u8[64]; + /* 0x00002300 reg2240 - 0x0000237c reg2271*/ + RK_U16 q_intra_v8[64]; + + /* 0x00002380 reg2272 - 0x000023fc reg2303*/ + RK_U16 q_inter_y8[64]; + /* 0x00002400 reg2304 - 0x0000247c reg2335*/ + RK_U16 q_inter_u8[64]; + /* 0x00002480 reg2336 - 0x000024fc reg2367*/ + RK_U16 q_inter_v8[64]; + + /* 0x00002500 reg2368 - 0x000025fc reg2431*/ + ip_raw32_16 q_intra_y[16]; + /* 0x00002600 reg2432 - 0x000026fc reg2495*/ + ip_raw32_16 q_intra_u[16]; + /* 0x00002700 reg2496 - 0x000027fc reg2559 */ + ip_raw32_16 q_intra_v[16]; + + /*0x00002800 reg2560 - 0x000028fc reg2623*/ + ip_raw32_16 q_inter_y[16]; + /*0x00002900 reg2624 - 0x000029fc reg2687*/ + ip_raw32_16 q_inter_u[16]; + /*0x00002a00 reg2688 - 0x00002afc reg2751 */ + ip_raw32_16 q_inter_v[16]; + + /* 0x00002b00 reg2752 - 0x00002b7c reg2783 */ + ip_raw8 ip_y8[8]; + /* 0x00002b80 reg2784 - 0x00002bfc reg2815 */ + ip_raw8 ip_u8[8]; + /* 0x00002c00 reg2816 - 0x00002c7c reg2847 */ + ip_raw8 ip_v8[8]; +} vepu540c_scl_cfg; + +typedef struct Vepu540cPreCstPar_t { + struct { + RK_U32 madi_thd0 : 8; + RK_U32 madi_thd1 : 8; + RK_U32 madi_thd2 : 8; + RK_U32 madi_thd3 : 8; + } cst_madi_thd0; + + /* 0x000020c4 reg2097 */ + struct { + RK_U32 madi_thd4 : 8; + RK_U32 madi_thd5 : 8; + RK_U32 reserved : 16; + } cst_madi_thd1; + + /* 0x000020c8 reg2098 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } cst_wgt0; + + /* 0x000020cc reg2099 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 wgt5 : 8; + RK_U32 wgt6 : 8; + RK_U32 wgt7 : 8; + } cst_wgt1; + + /* 0x000020d0 reg2100 */ + struct { + RK_U32 wgt8 : 8; + RK_U32 wgt9 : 8; + RK_U32 mode_th : 3; + RK_U32 reserved : 13; + } cst_wgt2; +} pre_cst_par; + +typedef struct Vepu540cRdoSkipPar_t { + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } atf_thd0; + + /* 0x00002064 reg2073 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd3 : 12; + RK_U32 reserved1 : 4; + } atf_thd1; + + /* 0x00002068 reg2074 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt0; + + /* 0x0000206c reg2075 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 reserved : 24; + } atf_wgt1; +} rdo_skip_par; + +typedef struct Vepu540cRdoNoSkipPar_t { + /* 0x00002080 reg2080 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } ratf_thd0; + + /* 0x00002084 reg2081 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 20; + } ratf_thd1; + + /* 0x00002088 reg2082 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt; +} rdo_noskip_par; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x00002c7c reg2847*/ +typedef struct Vepu540cRdoCfg_t { + + /* 0x2000 - 0x200c */ + RK_U32 reserved2048_2051[4]; + + /* 0x00002010 reg2052 */ + struct { + RK_U32 rdo_segment_multi : 8; + RK_U32 rdo_segment_en : 1; + RK_U32 reserved : 7; + RK_U32 rdo_smear_lvl4_multi : 8; + RK_U32 rdo_smear_lvl8_multi : 8; + } rdo_segment_cfg; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 rdo_smear_lvl16_multi : 8; + RK_U32 rdo_smear_dlt_qp : 4; + RK_U32 rdo_smear_order_state : 1; + RK_U32 stated_mode : 2; + RK_U32 rdo_smear_en : 1; + RK_U32 online_en : 1; + RK_U32 reserved : 3; + RK_U32 smear_stride : 12; + } rdo_smear_cfg_comb; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 rdo_smear_madp_cur_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_madp_cur_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_smear_madp_thd0_comb; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 rdo_smear_madp_cur_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_madp_cur_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_smear_madp_thd1_comb; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 rdo_smear_madp_around_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_madp_around_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_smear_madp_thd2_comb; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 rdo_smear_madp_around_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_madp_around_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_smear_madp_thd3_comb; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 rdo_smear_madp_around_thd4 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_madp_around_thd5 : 12; + RK_U32 reserved1 : 4; + } rdo_smear_madp_thd4_comb; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 rdo_smear_madp_ref_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_madp_ref_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_smear_madp_thd5_comb; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 rdo_smear_cnt_cur_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cnt_cur_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 rdo_smear_cnt_cur_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 rdo_smear_cnt_cur_thd3 : 4; + RK_U32 reserved3 : 4; + } rdo_smear_cnt_thd0_comb; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 rdo_smear_cnt_around_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cnt_around_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 rdo_smear_cnt_around_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 rdo_smear_cnt_around_thd3 : 4; + RK_U32 reserved3 : 4; + } rdo_smear_cnt_thd1_comb; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 rdo_smear_cnt_around_thd4 : 4; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cnt_around_thd5 : 4; + RK_U32 reserved1 : 4; + RK_U32 rdo_smear_cnt_around_thd6 : 4; + RK_U32 reserved2 : 4; + RK_U32 rdo_smear_cnt_around_thd7 : 4; + RK_U32 reserved3 : 4; + } rdo_smear_cnt_thd2_comb; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 rdo_smear_cnt_ref_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cnt_ref_thd1 : 4; + RK_U32 reserved1 : 20; + } rdo_smear_cnt_thd3_comb; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 rdo_smear_resi_small_cur_th0 : 6; + RK_U32 reserved : 2; + RK_U32 rdo_smear_resi_big_cur_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 rdo_smear_resi_small_cur_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 rdo_smear_resi_big_cur_th1 : 6; + RK_U32 reserved3 : 2; + } rdo_smear_resi_thd0_comb; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 rdo_smear_resi_small_around_th0 : 6; + RK_U32 reserved : 2; + RK_U32 rdo_smear_resi_big_around_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 rdo_smear_resi_small_around_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 rdo_smear_resi_big_around_th1 : 6; + RK_U32 reserved3 : 2; + } rdo_smear_resi_thd1_comb; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 rdo_smear_resi_small_around_th2 : 6; + RK_U32 reserved : 2; + RK_U32 rdo_smear_resi_big_around_th2 : 6; + RK_U32 reserved1 : 2; + RK_U32 rdo_smear_resi_small_around_th3 : 6; + RK_U32 reserved2 : 2; + RK_U32 rdo_smear_resi_big_around_th3 : 6; + RK_U32 reserved3 : 2; + } rdo_smear_resi_thd2_comb; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 rdo_smear_resi_small_ref_th0 : 6; + RK_U32 reserved : 2; + RK_U32 rdo_smear_resi_big_ref_th0 : 6; + RK_U32 reserved1 : 18; + } rdo_smear_resi_thd3_comb; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 rdo_smear_resi_th0 : 8; + RK_U32 reserved : 8; + RK_U32 rdo_smear_resi_th1 : 8; + RK_U32 reserved1 : 8; + } rdo_smear_st_thd0_comb; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 rdo_smear_madp_cnt_th0 : 4; + RK_U32 rdo_smear_madp_cnt_th1 : 4; + RK_U32 rdo_smear_madp_cnt_th2 : 4; + RK_U32 rdo_smear_madp_cnt_th3 : 4; + RK_U32 rdo_smear_madp_cnt_th4 : 4; + RK_U32 rdo_smear_madp_cnt_th5 : 4; + RK_U32 reserved : 8; + } rdo_smear_st_thd1_comb; + + /* 0x2058 - 0x205c */ + RK_U32 reserved2070_2071[2]; + /* 0x00002060 reg2072 - 0x0000206c reg2075 */ + rdo_skip_par rdo_b32_skip; + /* 0x00002070 reg2076 - 0x0000207c reg2079*/ + rdo_skip_par rdo_b16_skip; + + /* 0x00002080 reg2080 - 0x00002088 reg2082 */ + rdo_noskip_par rdo_b32_inter; + + /* 0x0000208c reg2083 - 0x00002094 reg2085 */ + rdo_noskip_par rdo_b16_inter; + + /* 0x00002098 reg2086 - 0x000020a4 reg2089 */ + rdo_noskip_par rdo_b32_intra; + + /* 0x000020a8 reg2090 - 0x000020ac reg2091 */ + rdo_noskip_par rdo_b16_intra; + + /* 0x000020b0 reg2092 */ + struct { + RK_U32 thd0 : 6; + RK_U32 reserved : 2; + RK_U32 thd1 : 6; + RK_U32 reserved1 : 2; + RK_U32 thd2 : 6; + RK_U32 reserved2 : 2; + RK_U32 thd3 : 6; + RK_U32 reserved3 : 2; + } rdo_b32_intra_atf_cnt_thd; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 thd0 : 4; + RK_U32 reserved : 4; + RK_U32 thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 thd3 : 4; + RK_U32 reserved3 : 4; + } rdo_b16_intra_atf_cnt_thd_comb; + + /* 0x000020b8 reg2094 */ + struct { + RK_U32 big_th0 : 6; + RK_U32 reserved : 2; + RK_U32 big_th1 : 6; + RK_U32 reserved1 : 2; + RK_U32 small_th0 : 6; + RK_U32 reserved2 : 2; + RK_U32 small_th1 : 6; + RK_U32 reserved3 : 2; + } rdo_atf_resi_thd_comb; + + /* 0x20bc */ + RK_U32 reserved_2095; + + /* 0x000020c0 reg2096 - 0x000020d0 reg2100 */ + pre_cst_par preintra32_cst; + /* 0x000020d4 reg2101 - 0x000020e4 reg2105 */ + pre_cst_par preintra16_cst; + + /* 0x20e8 - 0x20ec */ + RK_U32 reserved2106_2107[2]; + + /* 0x000020f0 reg2108 */ + struct { + RK_U32 pre_intra_qp_thd : 6; + RK_U32 reserved : 2; + RK_U32 pre_intra4_lambda_mv_bit : 3; + RK_U32 reserved1 : 1; + RK_U32 pre_intra8_lambda_mv_bit : 3; + RK_U32 reserved2 : 1; + RK_U32 pre_intra16_lambda_mv_bit : 3; + RK_U32 reserved3 : 1; + RK_U32 pre_intra32_lambda_mv_bit : 3; + RK_U32 reserved4 : 9; + } preintra_sqi_cfg; + + /* 0x000020f4 reg2109 */ + struct { + RK_U32 i_cu32_madi_thd0 : 8; + RK_U32 i_cu32_madi_thd1 : 8; + RK_U32 i_cu32_madi_thd2 : 8; + RK_U32 reserved : 8; + } rdo_atr_i_cu32_madi_cfg0; + + /* 0x000020f8 reg2110 */ + struct { + RK_U32 i_cu32_madi_cnt_thd3 : 5; + RK_U32 reserved : 3; + RK_U32 i_cu32_madi_thd4 : 8; + RK_U32 i_cu32_madi_cost_multi : 8; + RK_U32 reserved1 : 8; + } rdo_atr_i_cu32_madi_cfg1; + + /* 0x000020fc reg2111 */ + struct { + RK_U32 i_cu16_madi_thd0 : 8; + RK_U32 i_cu16_madi_thd1 : 8; + RK_U32 i_cu16_madi_cost_multi : 8; + RK_U32 reserved : 8; + } rdo_atr_i_cu16_madi_cfg0; +} vepu540c_rdo_cfg; + +typedef struct Vepu540cJpegReg_t { + + RK_U32 reg0256_adr_bsbt; + + /* 0x00000404 reg257 */ + RK_U32 reg0257_adr_bsbb; + + /* 0x00000408 reg258 */ + RK_U32 reg0258_adr_bsbs; + + /* 0x0000040c reg259 */ + RK_U32 reg0259_adr_bsbr; + + /* 0x00000410 reg260 */ + RK_U32 reg0260_adr_vsy_b; + + /* 0x00000414 reg261 */ + RK_U32 reg0261_adr_vsc_b; + + /* 0x00000418 reg262 */ + RK_U32 reg0262_adr_vsy_t; + + /* 0x0000041c reg263 */ + RK_U32 reg0263_adr_vsc_t; + + /* 0x00000420 reg264 */ + RK_U32 reg0264_adr_src0; + + /* 0x00000424 reg265 */ + RK_U32 reg0265_adr_src1; + + /* 0x00000428 reg266 */ + RK_U32 reg0266_adr_src2; + + /* 0x0000042c reg267 */ + struct { + RK_U32 bsp_size_jpeg : 1; + RK_U32 reserved : 31; + } bsp_size_jpeg; + + /* 0x430 - 0x43c */ + RK_U32 reserved268_271[4]; + + /* 0x00000440 reg272 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } reg0272_enc_rsl; + + /* 0x00000444 reg273 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } reg0273_src_fill; + + /* 0x00000448 reg274 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 reserved : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved1 : 21; + } reg0274_src_fmt; + + /* 0x0000044c reg275 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } reg0275_src_udfy; + + /* 0x00000450 reg276 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } reg0276_src_udfu; + + /* 0x00000454 reg277 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } reg0277_src_udfv; + + /* 0x00000458 reg278 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } reg0278_src_udfo; + + /* 0x0000045c reg279 */ + struct { + RK_U32 reserved : 26; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 reserved1 : 3; + } reg0279_src_proc; + + /* 0x00000460 reg280 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } reg0280_pic_ofst; + + /* 0x00000464 reg281 */ + struct { + RK_U32 src_strd0 : 17; + RK_U32 reserved : 15; + } reg0281_src_strd0; + + /* 0x00000468 reg282 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } reg0282_src_strd1; + + /* 0x0000046c reg283 */ + struct { + RK_U32 pp_corner_filter_strength : 2; + RK_U32 reserved : 2; + RK_U32 pp_edge_filter_strength : 2; + RK_U32 reserved1 : 2; + RK_U32 pp_internal_filter_strength : 2; + RK_U32 reserved2 : 22; + } reg0283_src_flt; + + /* 0x00000470 reg284 */ + struct { + RK_U32 bias_y : 15; + RK_U32 reserved : 17; + } reg0284_y_cfg; + + /* 0x00000474 reg285 */ + struct { + RK_U32 bias_u : 15; + RK_U32 reserved : 17; + } reg0285_u_cfg; + + /* 0x00000478 reg286 */ + struct { + RK_U32 bias_v : 15; + RK_U32 reserved : 17; + } reg0286_v_cfg; + + /* 0x0000047c reg287 */ + struct { + RK_U32 jpeg_ri : 25; + RK_U32 jpeg_out_mode : 1; + RK_U32 jpeg_start_rst_m : 3; + RK_U32 jpeg_pic_last_ecs : 1; + RK_U32 jpeg_slen_fifo : 1; + RK_U32 jpeg_stnd : 1; + } reg0287_base_cfg; + + /* 0x00000480 reg288 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } reg0288_uvc_cfg; +} Vepu540cJpegReg; + +/* 0x00002c80 reg2848 - - 0x00002dfc reg2943*/ +typedef struct Vepu540cJpegTab_t { + /* 0x00002c80 reg2848 - 0x00002cfc reg2879 */ + RK_U16 qua_tab0[64]; + /* 0x00002d00 reg2880 - 0x00002d7c reg2911 */ + RK_U16 qua_tab1[64]; + /* 0x00002d80 reg2912 - 0x00002dfc reg2943 */ + RK_U16 qua_tab2[64]; +} vepu540c_jpeg_tab; + +typedef struct Vepu540cRoiRegion_t { + + struct { + RK_U32 roi_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_lt_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_lt; + + struct { + RK_U32 roi_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 roi_rb_y : 10; + RK_U32 reserved1 : 6; + } roi_pos_rb; + + struct { + RK_U32 roi_qp_value : 7; + RK_U32 roi_qp_adj_mode : 1; + RK_U32 roi_pri : 5; + RK_U32 roi_en : 1; + RK_U32 reserved : 18; + } roi_base; + struct { + RK_U32 roi_mdc_inter16 : 4; + RK_U32 roi_mdc_skip16 : 4; + RK_U32 roi_mdc_intra16 : 4; + RK_U32 roi0_mdc_inter32_hevc : 4; + RK_U32 roi0_mdc_skip32_hevc : 4; + RK_U32 roi0_mdc_intra32_hevc : 4; + RK_U32 roi0_mdc_dpth_hevc : 1; + RK_U32 reserved : 7; + } roi_mdc; +} Vepu540cRoiRegion; + +/* + * Vepu540cRoiCfg + * + */ +typedef struct Vepu540cRoiCfg_t { + struct { + RK_U32 fmdc_adju_inter16 : 4; + RK_U32 fmdc_adju_skip16 : 4; + RK_U32 fmdc_adju_intra16 : 4; + RK_U32 fmdc_adju_inter32 : 4; + RK_U32 fmdc_adju_skip32 : 4; + RK_U32 fmdc_adju_intra32 : 4; + RK_U32 fmdc_adj_pri : 5; + RK_U32 reserved : 3; + } fmdc_adj0; + + /* 0x00001084 reg1057 */ + struct { + RK_U32 fmdc_adju_inter8 : 4; + RK_U32 fmdc_adju_skip8 : 4; + RK_U32 fmdc_adju_intra8 : 4; + RK_U32 reserved : 20; + } fmdc_adj1; + + RK_U32 reserved_1058; + + /* 0x0000108c reg1059 */ + struct { + RK_U32 bmap_en : 1; + RK_U32 bmap_pri : 5; + RK_U32 bmap_qpmin : 6; + RK_U32 bmap_qpmax : 6; + RK_U32 bmap_mdc_dpth : 1; + RK_U32 reserved : 13; + } bmap_cfg; + + Vepu540cRoiRegion regions[8]; +} Vepu540cRoiCfg; + +/* class: st */ +/* 0x00004000 reg4096 - 0x000042cc reg4275 */ +typedef struct Vepu540cStatus_t { + /* 0x00004000 reg4096 */ + RK_U32 bs_lgth_l32; + + /* 0x00004004 reg4097 */ + struct { + RK_U32 bs_lgth_h8 : 8; + RK_U32 reserved : 8; + RK_U32 sse_l16 : 16; + } st_sse_bsl; + + /* 0x00004008 reg4098 */ + RK_U32 sse_h32; + + /* 0x0000400c reg4099 */ + RK_U32 qp_sum; + + /* 0x00004010 reg4100 */ + struct { + RK_U32 sao_cnum : 16; + RK_U32 sao_ynum : 16; + } st_sao; + + /* 0x00004014 reg4101 */ + RK_U32 rdo_head_bits; + + /* 0x00004018 reg4102 */ + struct { + RK_U32 rdo_head_bits_h8 : 8; + RK_U32 reserved : 8; + RK_U32 rdo_res_bits_l16 : 16; + } st_head_res_bl; + + /* 0x0000401c reg4103 */ + RK_U32 rdo_res_bits_h24; + + /* 0x00004020 reg4104 */ + struct { + RK_U32 st_enc : 2; + RK_U32 st_sclr : 1; + RK_U32 reserved : 29; + } st_enc; + + /* 0x00004024 reg4105 */ + struct { + RK_U32 fnum_cfg_done : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 fnum_enc_done : 8; + } st_lkt; + + /* 0x00004028 reg4106 */ + RK_U32 node_addr; + + /* 0x0000402c reg4107 */ + struct { + RK_U32 bsbw_ovfl : 1; + RK_U32 reserved : 2; + RK_U32 bsbw_addr : 28; + RK_U32 reserved1 : 1; + } st_bsb; + + /* 0x00004030 reg4108 */ + struct { + RK_U32 axib_idl : 8; + RK_U32 axib_ovfl : 8; + RK_U32 axib_err : 8; + RK_U32 axir_err : 7; + RK_U32 reserved : 1; + } st_bus; + + /* 0x00004034 reg4109 */ + struct { + RK_U32 sli_num_video : 6; + RK_U32 sli_num_jpeg : 6; + RK_U32 reserved : 4; + RK_U32 bpkt_num_video : 7; + RK_U32 bpkt_lst_video : 1; + RK_U32 bpkt_num_jpeg : 7; + RK_U32 bpkt_lst_jpeg : 1; + } st_snum; + + /* 0x00004038 reg4110 */ + RK_U32 sli_len; + + /* 0x403c - 0x40fc */ + struct { + RK_U32 task_id_proc : 12; + RK_U32 task_id_done : 12; + RK_U32 task_done : 1; + RK_U32 task_lkt_err : 3; + RK_U32 dvbm_enc_err : 1; + RK_U32 dvbm_fmch_err : 1; + RK_U32 reserved : 1; + RK_U32 rfpr_ovrb_err : 1; + } st_link_task; + + /* 0x4040 - 0x405c */ + RK_U32 reserved4111_4119[8]; + + RK_U32 sli_len_jpeg; + + /* 0x00004064 reg4121 */ + RK_U32 jpeg_head_bits_l32; + + /* 0x00004068 reg4122 */ + struct { + RK_U32 jpeg_head_bits_h8 : 1; + RK_U32 reserved : 31; + } st_bsl_h8_jpeg; + + /* 0x0000406c reg4123 */ + struct { + RK_U32 jbsbw_ovfl : 1; + RK_U32 reserved : 2; + RK_U32 jbsbw_addr : 28; + RK_U32 reserved1 : 1; + } st_jbsb; + + /* 0x4070 - 0x407c */ + RK_U32 reserved4124_4127[4]; + + /* 0x00004080 reg4128 */ + struct { + RK_U32 pnum_p64 : 17; + RK_U32 reserved : 15; + } st_pnum_p64; + + /* 0x00004084 reg4129 */ + struct { + RK_U32 pnum_p32 : 19; + RK_U32 reserved : 13; + } st_pnum_p32; + + /* 0x00004088 reg4130 */ + struct { + RK_U32 pnum_p16 : 21; + RK_U32 reserved : 11; + } st_pnum_p16; + + /* 0x0000408c reg4131 */ + struct { + RK_U32 pnum_p8 : 23; + RK_U32 reserved : 9; + } st_pnum_p8; + + /* 0x00004090 reg4132 */ + struct { + RK_U32 pnum_i32 : 19; + RK_U32 reserved : 13; + } st_pnum_i32; + + /* 0x00004094 reg4133 */ + struct { + RK_U32 pnum_i16 : 21; + RK_U32 reserved : 11; + } st_pnum_i16; + + /* 0x00004098 reg4134 */ + struct { + RK_U32 pnum_i8 : 23; + RK_U32 reserved : 9; + } st_pnum_i8; + + /* 0x0000409c reg4135 */ + struct { + RK_U32 pnum_i4 : 23; + RK_U32 reserved : 9; + } st_pnum_i4; + + /* 0x000040a0 reg4136 */ + struct { + RK_U32 num_b16 : 23; + RK_U32 reserved : 9; + } st_bnum_b16; + + /* 0x000040a4 reg4137 */ + struct { + RK_U32 rdo_smear_cnt0 : 8; + RK_U32 rdo_smear_cnt1 : 8; + RK_U32 rdo_smear_cnt2 : 8; + RK_U32 rdo_smear_cnt3 : 8; + } st_smear_cnt; + + /* 0x000040a8 reg4138 */ + RK_U32 madi_sum; + + /* 0x40ac - 0x40bc */ + RK_U32 reserved4139_4143[5]; + + /* 0x000040c0 reg4144 */ + struct { + RK_U32 madi_th_lt_cnt0 : 16; + RK_U32 madi_th_lt_cnt1 : 16; + } st_madi_lt_num0; + + /* 0x000040c4 reg4145 */ + struct { + RK_U32 madi_th_lt_cnt2 : 16; + RK_U32 madi_th_lt_cnt3 : 16; + } st_madi_lt_num1; + + /* 0x000040c8 reg4146 */ + struct { + RK_U32 madi_th_rt_cnt0 : 16; + RK_U32 madi_th_rt_cnt1 : 16; + } st_madi_rt_num0; + + /* 0x000040cc reg4147 */ + struct { + RK_U32 madi_th_rt_cnt2 : 16; + RK_U32 madi_th_rt_cnt3 : 16; + } st_madi_rt_num1; + + /* 0x000040d0 reg4148 */ + struct { + RK_U32 madi_th_lb_cnt0 : 16; + RK_U32 madi_th_lb_cnt1 : 16; + } st_madi_lb_num0; + + /* 0x000040d4 reg4149 */ + struct { + RK_U32 madi_th_lb_cnt2 : 16; + RK_U32 madi_th_lb_cnt3 : 16; + } st_madi_lb_num1; + + /* 0x000040d8 reg4150 */ + struct { + RK_U32 madi_th_rb_cnt0 : 16; + RK_U32 madi_th_rb_cnt1 : 16; + } st_madi_rb_num0; + + /* 0x000040dc reg4151 */ + struct { + RK_U32 madi_th_rb_cnt2 : 16; + RK_U32 madi_th_rb_cnt3 : 16; + } st_madi_rb_num1; + + /* 0x000040e0 reg4152 */ + struct { + RK_U32 madp_th_lt_cnt0 : 16; + RK_U32 madp_th_lt_cnt1 : 16; + } st_madp_lt_num0; + + /* 0x000040e4 reg4153 */ + struct { + RK_U32 madp_th_lt_cnt2 : 16; + RK_U32 madp_th_lt_cnt3 : 16; + } st_madp_lt_num1; + + /* 0x000040e8 reg4154 */ + struct { + RK_U32 madp_th_rt_cnt0 : 16; + RK_U32 madp_th_rt_cnt1 : 16; + } st_madp_rt_num0; + + /* 0x000040ec reg4155 */ + struct { + RK_U32 madp_th_rt_cnt2 : 16; + RK_U32 madp_th_rt_cnt3 : 16; + } st_madp_rt_num1; + + /* 0x000040f0 reg4156 */ + struct { + RK_U32 madp_th_lb_cnt0 : 16; + RK_U32 madp_th_lb_cnt1 : 16; + } st_madp_lb_num0; + + /* 0x000040f4 reg4157 */ + struct { + RK_U32 madp_th_lb_cnt2 : 16; + RK_U32 madp_th_lb_cnt3 : 16; + } st_madp_lb_num1; + + /* 0x000040f8 reg4158 */ + struct { + RK_U32 madp_th_rb_cnt0 : 16; + RK_U32 madp_th_rb_cnt1 : 16; + } st_madp_rb_num0; + + /* 0x000040fc reg4159 */ + struct { + RK_U32 madp_th_rb_cnt2 : 16; + RK_U32 madp_th_rb_cnt3 : 16; + } st_madp_rb_num1; + + /* 0x00004100 reg4160 */ + struct { + RK_U32 cmv_th_lt_cnt0 : 16; + RK_U32 cmv_th_lt_cnt1 : 16; + } st_cmv_lt_num0; + + /* 0x00004104 reg4161 */ + struct { + RK_U32 cmv_th_lt_cnt2 : 16; + RK_U32 cmv_th_lt_cnt3 : 16; + } st_cmv_lt_num1; + + /* 0x00004108 reg4162 */ + struct { + RK_U32 cmv_th_rt_cnt0 : 16; + RK_U32 cmv_th_rt_cnt1 : 16; + } st_cmv_rt_num0; + + /* 0x0000410c reg4163 */ + struct { + RK_U32 cmv_th_rt_cnt2 : 16; + RK_U32 cmv_th_rt_cnt3 : 16; + } st_cmv_rt_num1; + + /* 0x00004110 reg4164 */ + struct { + RK_U32 cmv_th_lb_cnt0 : 16; + RK_U32 cmv_th_lb_cnt1 : 16; + } st_cmv_lb_num0; + + /* 0x00004114 reg4165 */ + struct { + RK_U32 cmv_th_lb_cnt2 : 16; + RK_U32 cmv_th_lb_cnt3 : 16; + } st_cmv_lb_num1; + + /* 0x00004118 reg4166 */ + struct { + RK_U32 cmv_th_rb_cnt0 : 16; + RK_U32 cmv_th_rb_cnt1 : 16; + } st_cmv_rb_num0; + + /* 0x0000411c reg4167 */ + struct { + RK_U32 cmv_th_rb_cnt2 : 16; + RK_U32 cmv_th_rb_cnt3 : 16; + } st_cmv_rb_num1; + + /* 0x00004120 reg4168 */ + struct { + RK_U32 org_y_r_max_value : 8; + RK_U32 org_y_r_min_value : 8; + RK_U32 org_u_g_max_value : 8; + RK_U32 org_u_g_min_value : 8; + } st_vsp_org_value0; + + /* 0x00004124 reg4169 */ + struct { + RK_U32 org_v_b_max_value : 8; + RK_U32 org_v_b_min_value : 8; + RK_U32 reserved : 16; + } st_vsp_org_value1; + + /* 0x00004128 reg4170 */ + struct { + RK_U32 jpeg_y_r_max_value : 8; + RK_U32 jpeg_y_r_min_value : 8; + RK_U32 jpeg_u_g_max_value : 8; + RK_U32 jpeg_u_g_min_value : 8; + } st_vsp_jpeg_value0; + + /* 0x0000412c reg4171 */ + struct { + RK_U32 jpeg_v_b_max_value : 8; + RK_U32 jpeg_v_b_min_value : 8; + RK_U32 reserved : 16; + } st_vsp_jpeg_value1; + + /* 0x4130 - 0x417c */ + RK_U32 reserved4172_4191[20]; + + /* 0x00004180 reg4192 - 0x0000424c reg4243*/ + RK_U32 st_b8_qp[52]; + +} vepu540c_status; + +/* class: dbg/st/axipn */ +/* 0x00005000 reg5120 - 0x00005354 reg5333*/ +typedef struct Vepu540cDbg_t { + struct { + RK_U32 pp0_tout : 1; + RK_U32 pp1_out : 1; + RK_U32 cme_tout : 1; + RK_U32 swn_tout : 1; + RK_U32 rfme_tout : 1; + RK_U32 pren_tout : 1; + RK_U32 rdo_tout : 1; + RK_U32 lpf_tout : 1; + RK_U32 etpy_tout : 1; + RK_U32 jpeg_tout : 1; + RK_U32 frm_tout : 1; + RK_U32 reserved : 21; + } st_wdg; + + /* 0x00005004 reg5121 */ + struct { + RK_U32 pp0_wrk : 1; + RK_U32 pp1_wrk : 1; + RK_U32 cme_wrk : 1; + RK_U32 swn_wrk : 1; + RK_U32 rfme_wrk : 1; + RK_U32 pren_wrk : 1; + RK_U32 rdo_wrk : 1; + RK_U32 lpf_wrk : 1; + RK_U32 etpy_wrk : 1; + RK_U32 jpeg_wrk : 1; + RK_U32 frm_wrk : 1; + RK_U32 reserved : 21; + } st_ppl; + + /* 0x00005008 reg5122 */ + struct { + RK_U32 vsp0_pos_x : 16; + RK_U32 vsp0_pos_y : 16; + } st_ppl_pos_vsp0; + + /* 0x0000500c reg5123 */ + struct { + RK_U32 vsp1_pos_x : 16; + RK_U32 vsp1_pos_y : 16; + } st_ppl_pos_vsp1; + + /* 0x00005010 reg5124 */ + struct { + RK_U32 cme_pos_x : 16; + RK_U32 cme_pos_y : 16; + } st_ppl_pos_cme; + + /* 0x00005014 reg5125 */ + struct { + RK_U32 swin_pos_x : 16; + RK_U32 swin_pos_y : 16; + } st_ppl_pos_swin; + + /* 0x00005018 reg5126 */ + struct { + RK_U32 rfme_pos_x : 16; + RK_U32 rfme_pos_y : 16; + } st_ppl_pos_rfme; + + /* 0x0000501c reg5127 */ + struct { + RK_U32 pren_pos_x : 16; + RK_U32 pren_pos_y : 16; + } st_ppl_pos_pren; + + /* 0x00005020 reg5128 */ + struct { + RK_U32 rdo_pos_x : 16; + RK_U32 rdo_pos_y : 16; + } st_ppl_pos_rdo; + + /* 0x00005024 reg5129 */ + struct { + RK_U32 lpf_pos_x : 16; + RK_U32 lpf_pos_y : 16; + } st_ppl_pos_lpf; + + /* 0x00005028 reg5130 */ + struct { + RK_U32 etpy_pos_x : 16; + RK_U32 etpy_pos_y : 16; + } st_ppl_pos_etpy; + + /* 0x0000502c reg5131 */ + struct { + RK_U32 vsp0_pos_x : 16; + RK_U32 vsp0_pos_y : 16; + } st_ppl_pos_jsp0; + + /* 0x00005030 reg5132 */ + struct { + RK_U32 vsp1_pos_x : 16; + RK_U32 vsp1_pos_y : 16; + } st_ppl_pos_jsp1; + + /* 0x00005034 reg5133 */ + struct { + RK_U32 jpeg_pos_x : 16; + RK_U32 jpeg_pos_y : 16; + } st_ppl_pos_jpeg; + + /* 0x5038 - 0x503c */ + RK_U32 reserved5134_5135[2]; + + /* 0x00005040 reg5136 */ + struct { + RK_U32 sli_num : 15; + RK_U32 reserved : 17; + } st_sli_num; + + /* 0x5044 - 0x50fc */ + RK_U32 reserved5137_5183[47]; + + /* 0x00005100 reg5184 */ + struct { + RK_U32 empty_oafifo : 1; + RK_U32 full_cmd_oafifo : 1; + RK_U32 full_data_oafifo : 1; + RK_U32 empty_iafifo : 1; + + RK_U32 full_cmd_iafifo : 1; + RK_U32 full_info_iafifo : 1; + RK_U32 fbd_brq_st : 4; + RK_U32 fbd_hdr_vld : 1; + RK_U32 fbd_bmng_end : 1; + + RK_U32 nfbd_req_st : 4; + RK_U32 acc_axi_cmd : 8; + RK_U32 reserved : 8; + } dbg_pp_st; + + /* 0x00005104 reg5185 */ + struct { + RK_U32 r_ena_lambd : 1; + RK_U32 r_fst_swinw_end : 1; + RK_U32 r_swinw_end : 1; + RK_U32 r_cnt_swinw : 1; + + RK_U32 r_dspw_end : 1; + RK_U32 r_dspw_cnt : 1; + RK_U32 i_sjgen_work : 1; + RK_U32 r_end_rspgen : 1; + + RK_U32 r_cost_gate : 1; + RK_U32 r_ds_gate : 1; + RK_U32 r_mvp_gate : 1; + RK_U32 i_smvp_arrdy : 1; + + RK_U32 i_smvp_arvld : 1; + RK_U32 i_stptr_wrdy : 1; + RK_U32 i_stptr_wvld : 1; + RK_U32 i_rdy_atf : 1; + + RK_U32 i_vld_atf : 1; + RK_U32 i_rdy_bmv16 : 1; + RK_U32 i_vld_bmv16 : 1; + RK_U32 i_wr_dsp : 1; + + RK_U32 i_rdy_dsp : 1; + RK_U32 i_vld_dsp : 1; + RK_U32 r_rdy_org : 1; + RK_U32 i_vld_org : 1; + + RK_U32 i_rdy_state : 1; + RK_U32 i_vld_state : 1; + RK_U32 i_rdy_madp : 1; + RK_U32 i_vld_madp : 1; + + RK_U32 i_rdy_diff : 1; + RK_U32 i_vld_diff : 1; + RK_U32 reserved : 2; + } dbg_cime_st; + + /* 0x00005108 reg5186 */ + RK_U32 swin_dbg_inf; + + /* 0x0000510c reg5187 */ + struct { + RK_U32 bbrq_cmps_left_len2 : 1; + RK_U32 bbrq_cmps_left_len1 : 1; + RK_U32 cmps_left_len0 : 1; + RK_U32 bbrq_rdy2 : 1; + RK_U32 dcps_vld2 : 1; + RK_U32 bbrq_rdy1 : 1; + RK_U32 dcps_vld1 : 1; + RK_U32 bbrq_rdy0 : 1; + RK_U32 dcps_vld0 : 1; + RK_U32 hb_rdy2 : 1; + RK_U32 bbrq_vld2 : 1; + RK_U32 hb_rdy1 : 1; + RK_U32 bbrq_vld1 : 1; + RK_U32 hb_rdy0 : 1; + RK_U32 bbrq_vld0 : 1; + RK_U32 idle_msb2 : 1; + RK_U32 idle_msb1 : 1; + RK_U32 idle_msb0 : 1; + RK_U32 cur_state_dcps : 1; + RK_U32 cur_state_bbrq : 1; + RK_U32 cur_state_hb : 1; + RK_U32 cke_bbrq_dcps : 1; + RK_U32 cke_dcps : 1; + RK_U32 cke_bbrq : 1; + RK_U32 rdy_lwcd_rsp : 1; + RK_U32 vld_lwcd_rsp : 1; + RK_U32 rdy_lwcd_req : 1; + RK_U32 vld_lwcd_req : 1; + RK_U32 rdy_lwrsp : 1; + RK_U32 vld_lwrsp : 1; + RK_U32 rdy_lwreq : 1; + RK_U32 vld_lwreq : 1; + } dbg_fbd_hhit0; + + /* 0x5110 */ + RK_U32 reserved_5188; + + /* 0x00005114 reg5189 */ + struct { + RK_U32 mscnt_clr : 1; + RK_U32 reserved : 31; + } dbg_cach_clr; + + /* 0x00005118 reg5190 */ + RK_U32 l1_mis; + + /* 0x0000511c reg5191 */ + RK_U32 l2_mis; + + /* 0x00005120 reg5192 */ + RK_U32 rdo_st; + + /* 0x00005124 reg5193 */ + RK_U32 rdo_if; + + /* 0x00005128 reg5194 */ + struct { + RK_U32 h264_sh_st_cs : 4; + RK_U32 rsd_st_cs : 4; + RK_U32 h264_sd_st_cs : 5; + RK_U32 etpy_rdy : 1; + RK_U32 reserved : 18; + } dbg_etpy; + + /* 0x0000512c reg5195 */ + struct { + RK_U32 crdy_ppr : 1; + RK_U32 cvld_ppr : 1; + RK_U32 drdy_ppw : 1; + RK_U32 dvld_ppw : 1; + RK_U32 crdy_ppw : 1; + RK_U32 cvld_ppw : 1; + RK_U32 reserved : 26; + } dbg_dma_pp; + + /* 0x00005130 reg5196 */ + struct { + RK_U32 axi_wrdy : 8; + RK_U32 axi_wvld : 8; + RK_U32 axi_awrdy : 8; + RK_U32 axi_awvld : 8; + } dbg_dma_w; + + /* 0x00005134 reg5197 */ + struct { + RK_U32 axi_otsd_read : 16; + RK_U32 axi_arrdy : 7; + RK_U32 reserved : 1; + RK_U32 axi_arvld : 7; + RK_U32 reserved1 : 1; + } dbg_dma_ar; + + /* 0x00005138 reg5198 */ + struct { + RK_U32 dfifo0_lvl : 4; + RK_U32 dfifo1_lvl : 4; + RK_U32 dfifo2_lvl : 4; + RK_U32 dfifo3_lvl : 4; + RK_U32 dfifo4_lvl : 4; + RK_U32 dfifo5_lvl : 4; + RK_U32 reserved : 6; + RK_U32 cmd_vld : 1; + RK_U32 reserved1 : 1; + } dbg_dma_r; + + /* 0x0000513c reg5199 */ + struct { + RK_U32 meiw_busy : 1; + RK_U32 dspw_busy : 1; + RK_U32 bsw_rdy : 1; + RK_U32 bsw_flsh : 1; + RK_U32 bsw_busy : 1; + RK_U32 crpw_busy : 1; + RK_U32 lktw_busy : 1; + RK_U32 lpfw_busy : 1; + RK_U32 roir_busy : 1; + RK_U32 dspr_crdy : 1; + RK_U32 dspr_cvld : 1; + RK_U32 lktr_busy : 1; + RK_U32 lpfr_otsd : 4; + RK_U32 rfpr_otsd : 12; + RK_U32 dspr_otsd : 4; + } dbg_dma_dbg0; + + /* 0x00005140 reg5200 */ + struct { + RK_U32 cpip_st : 2; + RK_U32 mvp_st : 3; + RK_U32 qpd6_st : 2; + RK_U32 cmd_st : 2; + RK_U32 reserved : 23; + } dbg_dma_dbg1; + + /* 0x00005144 reg5201 */ + struct { + RK_U32 cme_byps : 3; + RK_U32 reserved : 29; + } dbg_tctrl; + + /* 0x5148 */ + RK_U32 reserved_5202; + + /* 0x0000514c reg5203 */ + struct { + RK_U32 lpf_work : 1; + RK_U32 rdo_par_nrdy : 1; + RK_U32 rdo_rcn_nrdy : 1; + RK_U32 lpf_rcn_rdy : 1; + RK_U32 dblk_work : 1; + RK_U32 sao_work : 1; + RK_U32 reserved : 18; + RK_U32 tile_bdry_read : 1; + RK_U32 tile_bdry_write : 1; + RK_U32 tile_bdry_rrdy : 1; + RK_U32 rdo_read_tile_bdry : 1; + RK_U32 rdo_write_tile_bdry : 1; + RK_U32 reserved1 : 3; + } dbg_lpf; + + /* 0x00005150 reg5204 */ + RK_U32 dbg_topc_lpfr; + + /* 0x00005154 reg5205 */ + RK_U32 dbg0_cache; + + /* 0x00005158 reg5206 */ + RK_U32 dbg1_cache; + + /* 0x0000515c reg5207 */ + RK_U32 dbg2_cache; + + /* 0x00005160 reg5208 */ + struct { + RK_U32 ebuf_diff_cmd : 8; + RK_U32 lbuf_lpf_ncnt : 7; + RK_U32 lbuf_lpf_cien : 1; + RK_U32 lbuf_rdo_ncnt : 7; + RK_U32 lbuf_rdo_cien : 1; + RK_U32 reserved : 8; + } dbg_lbuf0; + + /* 0x00005164 reg5209 */ + struct { + RK_U32 rvld_ebfr : 1; + RK_U32 rrdy_ebfr : 1; + RK_U32 arvld_ebfr : 1; + RK_U32 arrdy_ebfr : 1; + RK_U32 wvld_ebfw : 1; + RK_U32 wrdy_ebfw : 1; + RK_U32 awvld_ebfw : 1; + RK_U32 awrdy_ebfw : 1; + RK_U32 lpf_lbuf_rvld : 1; + RK_U32 lpf_lbuf_rrdy : 1; + RK_U32 lpf_lbuf_wvld : 1; + RK_U32 lpf_lbuf_wrdy : 1; + RK_U32 rdo_lbuf_rvld : 1; + RK_U32 rdo_lbuf_rrdy : 1; + RK_U32 rdo_lbuf_wvld : 1; + RK_U32 rdo_lbuf_wrdy : 1; + RK_U32 fme_lbuf_rvld : 1; + RK_U32 fme_lbuf_rrdy : 1; + RK_U32 cme_lbuf_rvld : 1; + RK_U32 cme_lbuf_rrdy : 1; + RK_U32 smear_lbuf_rvld : 1; + RK_U32 smear_lbuf_rrdy : 1; + RK_U32 smear_lbuf_wvld : 1; + RK_U32 smear_lbuf_wrdy : 1; + RK_U32 rdo_lbufw_flag : 1; + RK_U32 rdo_lbufr_flag : 1; + RK_U32 cme_lbufr_flag : 1; + RK_U32 reserved : 5; + } dbg_lbuf1; + + /* 0x00005168 reg5210 */ + struct { + RK_U32 vinf_lcnt_dvbm : 14; + RK_U32 vinf_fcnt_dvbm : 8; + RK_U32 vinf_rdy_dvbm : 1; + RK_U32 vinf_vld_dvbm : 1; + RK_U32 st_cur_vinf : 3; + RK_U32 st_cur_vrsp : 2; + RK_U32 vcnt_req_sync : 1; + RK_U32 vcnt_ack_dvbm : 1; + RK_U32 vcnt_req_dvbm : 1; + } dbg_dvbm0; + + /* 0x0000516c reg5211 */ + struct { + RK_U32 vrsp_lcnt_dvbm : 14; + RK_U32 vrsp_fcnt_dvbm : 8; + RK_U32 vrsp_tgl_dvbm : 1; + RK_U32 reserved : 9; + } dbg_dvbm1; + + /* 0x00005170 reg5212 */ + struct { + RK_U32 dvbm_src_lcnt : 12; + RK_U32 jbuf_dvbm_rdy : 1; + RK_U32 vbuf_dvbm_rdy : 1; + RK_U32 work_dvbm_rdy : 1; + RK_U32 fmch_dvbm_rdy : 1; + RK_U32 vrsp_lcnt_vsld : 14; + RK_U32 vrsp_rdy_vsld : 1; + RK_U32 vrsp_vld_vsld : 1; + } dbg_dvbm2; + + /* 0x00005174 reg5213 */ + struct { + RK_U32 vsp_ctu_flag : 4; + RK_U32 reserved : 4; + RK_U32 cime_ctu_flag : 8; + RK_U32 swin_ctu_flag : 2; + RK_U32 rfme_ctu_flag : 6; + RK_U32 pnra_ctu_flag : 1; + RK_U32 rdo_ctu_flg0 : 7; + } dbg_tctrl0; + + /* 0x00005178 reg5214 */ + struct { + RK_U32 rdo_ctu_flg1 : 8; + RK_U32 jpeg_ctu_flag : 3; + RK_U32 lpf_ctu_flag : 1; + RK_U32 reserved : 4; + RK_U32 dma_brsp_idle : 1; + RK_U32 jpeg_frm_done : 1; + RK_U32 rdo_frm_done : 1; + RK_U32 lpf_frm_done : 1; + RK_U32 ent_frm_done : 1; + RK_U32 ppl_ctrl_done : 1; + RK_U32 reserved1 : 10; + } dbg_tctrl1; + + /* 0x0000517c reg5215 */ + struct { + RK_U32 criw_frm_done : 1; + RK_U32 meiw_frm_done : 1; + RK_U32 smiw_frm_done : 1; + RK_U32 strg_rsrc_done : 1; + RK_U32 reserved : 28; + } dbg_tctrl2; + + /* 0x5180 - 0x51fc */ + RK_U32 reserved5216_5247[32]; + + /* 0x00005200 reg5248 */ + RK_U32 frame_cyc; + + /* 0x00005204 reg5249 */ + RK_U32 pp0_fcyc; + + /* 0x00005208 reg5250 */ + RK_U32 pp1_fcyc; + + /* 0x0000520c reg5251 */ + RK_U32 cme_fcyc; + + /* 0x00005210 reg5252 */ + RK_U32 ldr_fcyc; + + /* 0x00005214 reg5253 */ + RK_U32 rfme_fcyc; + + /* 0x00005218 reg5254 */ + RK_U32 fme_fcyc; + + /* 0x0000521c reg5255 */ + RK_U32 rdo_fcyc; + + /* 0x00005220 reg5256 */ + RK_U32 lpf_fcyc; + + /* 0x00005224 reg5257 */ + RK_U32 etpy_fcyc; + + /* 0x00005228 reg5258 */ + RK_U32 jpeg_fcyc; + + /* 0x522c - 0x52fc */ + RK_U32 reserved5259_5311[53]; + + /* 0x00005300 reg5312 */ + struct { + RK_U32 axip_e : 1; + RK_U32 axip_clr : 1; + RK_U32 axip_mod : 1; + RK_U32 reserved : 29; + } axip0_cmd; + + /* 0x00005304 reg5313 */ + struct { + RK_U32 axip_ltcy_id : 4; + RK_U32 axip_ltcy_thd : 12; + RK_U32 reserved : 16; + } axip0_ltcy; + + /* 0x00005308 reg5314 */ + struct { + RK_U32 axip_cnt_typ : 1; + RK_U32 axip_cnt_ddr : 2; + RK_U32 axip_cnt_rid : 5; + RK_U32 axip_cnt_wid : 5; + RK_U32 reserved : 19; + } axip0_cnt; + + /* 0x530c */ + RK_U32 reserved_5315; + + /* 0x00005310 reg5316 */ + struct { + RK_U32 axip_e : 1; + RK_U32 axip_clr : 1; + RK_U32 axip_mod : 1; + RK_U32 reserved : 29; + } axip1_cmd; + + /* 0x00005314 reg5317 */ + struct { + RK_U32 axip_ltcy_id : 4; + RK_U32 axip_ltcy_thd : 12; + RK_U32 reserved : 16; + } axip1_ltcy; + + /* 0x00005318 reg5318 */ + struct { + RK_U32 axip_cnt_typ : 1; + RK_U32 axip_cnt_ddr : 2; + RK_U32 axip_cnt_rid : 5; + RK_U32 axip_cnt_wid : 5; + RK_U32 reserved : 19; + } axip1_cnt; + + /* 0x531c */ + RK_U32 reserved_5319; + + /* 0x00005320 reg5320 */ + struct { + RK_U32 axip_max_ltcy : 16; + RK_U32 reserved : 16; + } st_axip0_maxl; + + /* 0x00005324 reg5321 */ + RK_U32 axip_num_ltcy; + + /* 0x00005328 reg5322 */ + RK_U32 axip_sum_ltcy; + + /* 0x0000532c reg5323 */ + RK_U32 axip_rbyt; + + /* 0x00005330 reg5324 */ + RK_U32 axip_wbyt; + + /* 0x00005334 reg5325 */ + RK_U32 axip_wrk_cyc; + + /* 0x5338 - 0x533c */ + RK_U32 reserved5326_5327[2]; + + /* 0x00005340 reg5328 */ + struct { + RK_U32 axip_max_ltcy : 16; + RK_U32 reserved : 16; + } st_axip1_maxl; + + /* 0x00005344 reg5329 */ + RK_U32 axip1_num_ltcy; + + /* 0x00005348 reg5330 */ + RK_U32 axip1_sum_ltcy; + + /* 0x0000534c reg5331 */ + RK_U32 axip1_rbyt; + + /* 0x00005350 reg5332 */ + RK_U32 axip1_wbyt; + + /* 0x00005354 reg5333 */ + RK_U32 axip1_wrk_cyc; +} vepu540c_dbg; + +typedef struct Vepu540cJpegCfg_t { + MppDev dev; + void *jpeg_reg_base; + void *reg_tab; + void *enc_task; + void *input_fmt; +} Vepu540cJpegCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vepu540c_set_jpeg_reg(Vepu540cJpegCfg *cfg); +MPP_RET vepu540c_set_roi(void *roi_reg_base, MppEncROICfg * roi, RK_S32 w, + RK_S32 h); + +#ifdef __cplusplus +} +#endif +#endif /* VEPU540C_COMMON_H */ diff --git a/mpp/hal/rkenc/common/vepu541_common.c b/mpp/hal/rkenc/common/vepu541_common.c new file mode 100644 index 000000000..b2267960e --- /dev/null +++ b/mpp/hal/rkenc/common/vepu541_common.c @@ -0,0 +1,537 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vepu541_common" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "vepu5xx_common.h" +#include "vepu541_common.h" + +RK_S32 vepu541_get_roi_buf_size(RK_S32 w, RK_S32 h) +{ + RK_S32 stride_h = MPP_ALIGN(w, 64) / 16; + RK_S32 stride_v = MPP_ALIGN(h, 64) / 16; + RK_S32 buf_size = stride_h * stride_v * sizeof(Vepu541RoiCfg); + + /* extra 32 byte for hardware access padding */ + return buf_size + 32; +} + +MPP_RET vepu541_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h) +{ + Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf; + RK_S32 mb_w = MPP_ALIGN(w, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(h, 16) / 16; + RK_S32 stride_h = MPP_ALIGN(mb_w, 4); + Vepu541RoiCfg cfg; + MPP_RET ret = MPP_NOK; + + if (NULL == buf || NULL == region) { + mpp_err_f("invalid buf %p roi %p\n", buf, region); + goto DONE; + } + + RK_S32 roi_width = (region->w + 15) / 16; + RK_S32 roi_height = (region->h + 15) / 16; + RK_S32 pos_x_init = region->x / 16; + RK_S32 pos_y_init = region->y / 16; + RK_S32 pos_x_end = pos_x_init + roi_width; + RK_S32 pos_y_end = pos_y_init + roi_height; + RK_S32 x, y; + + pos_x_end = MPP_MIN(pos_x_end, mb_w); + pos_y_end = MPP_MIN(pos_y_end, mb_h); + pos_x_init = MPP_MAX(pos_x_init, 0); + pos_y_init = MPP_MAX(pos_y_init, 0); + + mpp_assert(pos_x_end > pos_x_init); + mpp_assert(pos_y_end > pos_y_init); + + cfg.force_intra = region->intra; + cfg.reserved = 0; + cfg.qp_area_idx = region->qp_area_idx; + // NOTE: When roi is enabled the qp_area_en should be one. + cfg.qp_area_en = 1; // region->area_map_en; + cfg.qp_adj = region->quality; + cfg.qp_adj_mode = region->abs_qp_en; + + ptr += pos_y_init * stride_h + pos_x_init; + roi_width = pos_x_end - pos_x_init; + roi_height = pos_y_end - pos_y_init; + + for (y = 0; y < roi_height; y++) { + Vepu541RoiCfg *dst = ptr; + + for (x = 0; x < roi_width; x++, dst++) + memcpy(dst, &cfg, sizeof(cfg)); + + ptr += stride_h; + } +DONE: + return ret; +} + +MPP_RET vepu541_set_roi(void *buf, MppEncROICfg *roi, RK_S32 w, RK_S32 h) +{ + MppEncROIRegion *region = roi->regions; + Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf; + RK_S32 mb_w = MPP_ALIGN(w, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(h, 16) / 16; + RK_S32 stride_h = MPP_ALIGN(mb_w, 4); + RK_S32 stride_v = MPP_ALIGN(mb_h, 4); + Vepu541RoiCfg cfg; + MPP_RET ret = MPP_NOK; + RK_S32 i; + + if (NULL == buf || NULL == roi) { + mpp_err_f("invalid buf %p roi %p\n", buf, roi); + goto DONE; + } + + cfg.force_intra = 0; + cfg.reserved = 0; + cfg.qp_area_idx = 0; + cfg.qp_area_en = 1; + cfg.qp_adj = 0; + cfg.qp_adj_mode = 0; + + /* step 1. reset all the config */ + for (i = 0; i < stride_h * stride_v; i++, ptr++) + memcpy(ptr, &cfg, sizeof(cfg)); + + if (w <= 0 || h <= 0) { + mpp_err_f("invalid size [%d:%d]\n", w, h); + goto DONE; + } + + if (roi->number > VEPU541_MAX_ROI_NUM) { + mpp_err_f("invalid region number %d\n", roi->number); + goto DONE; + } + + /* check region config */ + ret = MPP_OK; + for (i = 0; i < (RK_S32)roi->number; i++, region++) { + if (region->x + region->w > w || region->y + region->h > h) + ret = MPP_NOK; + + if (region->intra > 1 || region->qp_area_idx >= VEPU541_MAX_ROI_NUM || + region->area_map_en > 1 || region->abs_qp_en > 1) + ret = MPP_NOK; + + if ((region->abs_qp_en && region->quality > 51) || + (!region->abs_qp_en && (region->quality > 51 || region->quality < -51))) + ret = MPP_NOK; + + if (ret) { + mpp_err_f("region %d invalid param:\n", i); + mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n", + region->x, region->y, region->w, region->h, w, h); + mpp_err_f("force intra %d qp area index %d\n", + region->intra, region->qp_area_idx); + mpp_err_f("abs qp mode %d value %d\n", + region->abs_qp_en, region->quality); + goto DONE; + } + } + + region = roi->regions; + /* step 2. setup region for top to bottom */ + for (i = 0; i < (RK_S32)roi->number; i++, region++) { + vepu541_set_one_roi(buf, region, w, h); + } + +DONE: + return ret; +} + +/* + * Invert color threshold is for the absolute difference between background + * and foregroud color. + * If background color and foregroud color are close enough then trigger the + * invert color process. + */ +#define ENC_DEFAULT_OSD_INV_THR 15 + +#define VEPU541_OSD_ADDR_IDX_BASE 124 + +#define VEPU541_OSD_CFG_OFFSET 0x01C0 +#define VEPU541_OSD_PLT_OFFSET 0x0400 + +typedef struct Vepu541OsdReg_t { + /* + * OSD_CFG + * Address offset: 0x01C0 Access type: read and write + * OSD configuration + */ + struct { + /* OSD region enable, each bit controls corresponding OSD region. */ + RK_U32 osd_e : 8; + /* OSD inverse color enable, each bit controls corresponding region. */ + RK_U32 osd_inv_e : 8; + /* + * OSD palette clock selection. + * 1'h0: Configure bus clock domain. + * 1'h1: Core clock domain. + */ + RK_U32 osd_plt_cks : 1; + /* + * OSD palette type. + * 1'h1: Default type. + * 1'h0: User defined type. + */ + RK_U32 osd_plt_typ : 1; + RK_U32 reserved : 14; + } reg112; + + /* + * OSD_INV + * Address offset: 0x01C4 Access type: read and write + * OSD color inverse configuration + */ + struct { + /* Color inverse theshold for OSD region0. */ + RK_U32 osd_ithd_r0 : 4; + /* Color inverse theshold for OSD region1. */ + RK_U32 osd_ithd_r1 : 4; + /* Color inverse theshold for OSD region2. */ + RK_U32 osd_ithd_r2 : 4; + /* Color inverse theshold for OSD region3. */ + RK_U32 osd_ithd_r3 : 4; + /* Color inverse theshold for OSD region4. */ + RK_U32 osd_ithd_r4 : 4; + /* Color inverse theshold for OSD region5. */ + RK_U32 osd_ithd_r5 : 4; + /* Color inverse theshold for OSD region6. */ + RK_U32 osd_ithd_r6 : 4; + /* Color inverse theshold for OSD region7. */ + RK_U32 osd_ithd_r7 : 4; + } reg113; + + RK_U32 reg114; + RK_U32 reg115; + + /* + * OSD_POS reg116_123 + * Address offset: 0x01D0~0x01EC Access type: read and write + * OSD region position + */ + Vepu541OsdPos osd_pos[8]; + + /* + * ADR_OSD reg124_131 + * Address offset: 0x01F0~0x20C Access type: read and write + * Base address for OSD region, 16B aligned + */ + RK_U32 osd_addr[8]; +} Vepu541OsdReg; + +MPP_RET vepu541_set_osd(Vepu5xxOsdCfg *cfg) +{ + Vepu541OsdReg *regs = (Vepu541OsdReg *)(cfg->reg_base + (size_t)VEPU541_OSD_CFG_OFFSET); + MppDev dev = cfg->dev; + MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg; + MppEncOSDData2 osd; + + if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2)) + return MPP_NOK; + + if (osd.num_region == 0) + return MPP_OK; + + if (osd.num_region > 8) { + mpp_err_f("do NOT support more than 8 regions invalid num %d\n", + osd.num_region); + mpp_assert(osd.num_region <= 8); + return MPP_NOK; + } + + if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) { + MppDevRegWrCfg wr_cfg; + + wr_cfg.reg = plt_cfg->plt; + wr_cfg.size = sizeof(MppEncOSDPlt); + wr_cfg.offset = VEPU541_REG_BASE_OSD_PLT; + + mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + regs->reg112.osd_plt_cks = 1; + regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_USERDEF; + } else { + regs->reg112.osd_plt_cks = 0; + regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_DEFAULT; + } + + regs->reg112.osd_e = 0; + regs->reg112.osd_inv_e = 0; + + RK_U32 i = 0; + MppEncOSDRegion2 *region = osd.region; + MppEncOSDRegion2 *tmp = region; + RK_U32 num = osd.num_region; + + for (i = 0; i < num; i++, tmp++) { + regs->reg112.osd_e |= tmp->enable << i; + regs->reg112.osd_inv_e |= tmp->inverse << i; + + if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) { + Vepu541OsdPos *pos = ®s->osd_pos[i]; + size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256; + RK_S32 fd = 0; + RK_U32 buf_size = 0; + + pos->osd_lt_x = tmp->start_mb_x; + pos->osd_lt_y = tmp->start_mb_y; + pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1; + pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1; + + buf_size = mpp_buffer_get_size(tmp->buf); + fd = mpp_buffer_get_fd(tmp->buf); + if (fd < 0) { + mpp_err_f("invalid osd buffer fd %d\n", fd); + return MPP_NOK; + } + regs->osd_addr[i] = fd; + + if (tmp->buf_offset) + mpp_dev_set_reg_offset(dev, VEPU541_OSD_ADDR_IDX_BASE + i, tmp->buf_offset); + + /* There should be enough buffer and offset should be 16B aligned */ + if (buf_size < tmp->buf_offset + blk_len || + (tmp->buf_offset & 0xf)) { + mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x\n", + i, tmp->start_mb_x, tmp->start_mb_y, + tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset); + } + } + } + + SET_OSD_INV_THR(0, regs->reg113, region); + SET_OSD_INV_THR(1, regs->reg113, region); + SET_OSD_INV_THR(2, regs->reg113, region); + SET_OSD_INV_THR(3, regs->reg113, region); + SET_OSD_INV_THR(4, regs->reg113, region); + SET_OSD_INV_THR(5, regs->reg113, region); + SET_OSD_INV_THR(6, regs->reg113, region); + SET_OSD_INV_THR(7, regs->reg113, region); + + return MPP_OK; +} + +#define VEPU540_OSD_CFG_OFFSET 0x0178 + +typedef struct Vepu540OsdReg_t { + /* + * OSD_INV_CFG + * Address offset: 0x0178 Access type: read and write + * OSD color inverse configuration + */ + struct { + /* + * OSD color inverse enable of chroma component, + * each bit controls corresponding region. + */ + RK_U32 osd_ch_inv_en : 8; + /* + * OSD color inverse expression type + * each bit controls corresponding region. + * 1'h0: AND; + * 1'h1: OR + */ + RK_U32 osd_itype : 8; + /* + * OSD color inverse expression switch for luma component + * each bit controls corresponding region. + * 1'h0: Expression need to determine the condition; + * 1'h1: Expression don't need to determine the condition; + */ + RK_U32 osd_lu_inv_msk : 8; + /* + * OSD color inverse expression switch for chroma component + * each bit controls corresponding region. + * 1'h0: Expression need to determine the condition; + * 1'h1: Expression don't need to determine the condition; + */ + RK_U32 osd_ch_inv_msk : 8; + } reg094; + + /* reg gap 095~111 */ + RK_U32 reg_095_111[17]; + + /* + * OSD_CFG + * Address offset: 0x01C0 Access type: read and write + * OSD configuration + */ + struct { + /* OSD region enable, each bit controls corresponding OSD region. */ + RK_U32 osd_e : 8; + /* OSD inverse color enable, each bit controls corresponding region. */ + RK_U32 osd_lu_inv_en : 8; + /* + * OSD palette clock selection. + * 1'h0: Configure bus clock domain. + * 1'h1: Core clock domain. + */ + RK_U32 osd_plt_cks : 1; + /* + * OSD palette type. + * 1'h1: Default type. + * 1'h0: User defined type. + */ + RK_U32 osd_plt_typ : 1; + RK_U32 reserved : 14; + } reg112; + + /* + * OSD_INV + * Address offset: 0x01C4 Access type: read and write + * OSD color inverse configuration + */ + struct { + /* Color inverse theshold for OSD region0. */ + RK_U32 osd_ithd_r0 : 4; + /* Color inverse theshold for OSD region1. */ + RK_U32 osd_ithd_r1 : 4; + /* Color inverse theshold for OSD region2. */ + RK_U32 osd_ithd_r2 : 4; + /* Color inverse theshold for OSD region3. */ + RK_U32 osd_ithd_r3 : 4; + /* Color inverse theshold for OSD region4. */ + RK_U32 osd_ithd_r4 : 4; + /* Color inverse theshold for OSD region5. */ + RK_U32 osd_ithd_r5 : 4; + /* Color inverse theshold for OSD region6. */ + RK_U32 osd_ithd_r6 : 4; + /* Color inverse theshold for OSD region7. */ + RK_U32 osd_ithd_r7 : 4; + } reg113; + + RK_U32 reg114; + RK_U32 reg115; + + /* + * OSD_POS reg116_123 + * Address offset: 0x01D0~0x01EC Access type: read and write + * OSD region position + */ + Vepu541OsdPos osd_pos[8]; + + /* + * ADR_OSD reg124_131 + * Address offset: 0x01F0~0x20C Access type: read and write + * Base address for OSD region, 16B aligned + */ + RK_U32 osd_addr[8]; +} Vepu540OsdReg; + +MPP_RET vepu540_set_osd(Vepu5xxOsdCfg *cfg) +{ + Vepu540OsdReg *regs = (Vepu540OsdReg *)(cfg->reg_base + (size_t)VEPU540_OSD_CFG_OFFSET); + MppDev dev = cfg->dev; + MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg; + MppEncOSDData2 osd; + + if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2)) + return MPP_NOK; + + if (osd.num_region == 0) + return MPP_OK; + + if (osd.num_region > 8) { + mpp_err_f("do NOT support more than 8 regions invalid num %d\n", + osd.num_region); + mpp_assert(osd.num_region <= 8); + return MPP_NOK; + } + + if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) { + MppDevRegWrCfg wr_cfg; + + wr_cfg.reg = plt_cfg->plt; + wr_cfg.size = sizeof(MppEncOSDPlt); + wr_cfg.offset = VEPU541_REG_BASE_OSD_PLT; + mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + regs->reg112.osd_plt_cks = 1; + regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_USERDEF; + } else { + regs->reg112.osd_plt_cks = 0; + regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_DEFAULT; + } + + regs->reg112.osd_e = 0; + regs->reg112.osd_lu_inv_en = 0; + regs->reg094.osd_ch_inv_en = 0; + regs->reg094.osd_lu_inv_msk = 0; + + RK_U32 num = osd.num_region; + RK_U32 k = 0; + MppEncOSDRegion2 *region = osd.region; + MppEncOSDRegion2 *tmp = region; + + for (k = 0; k < num; k++, tmp++) { + regs->reg112.osd_e |= tmp->enable << k; + regs->reg112.osd_lu_inv_en |= (tmp->inverse != 0) ? (1 << k) : 0; + regs->reg094.osd_ch_inv_en |= (tmp->inverse != 0) ? (1 << k) : 0; + + if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) { + Vepu541OsdPos *pos = ®s->osd_pos[k]; + size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256; + RK_S32 fd = -1; + size_t buf_size = 0; + + pos->osd_lt_x = tmp->start_mb_x; + pos->osd_lt_y = tmp->start_mb_y; + pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1; + pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1; + + buf_size = mpp_buffer_get_size(tmp->buf); + fd = mpp_buffer_get_fd(tmp->buf); + if (fd < 0) { + mpp_err_f("invalid osd buffer fd %d\n", fd); + return MPP_NOK; + } + regs->osd_addr[k] = fd; + + if (tmp->buf_offset) + mpp_dev_set_reg_offset(dev, VEPU541_OSD_ADDR_IDX_BASE + k, tmp->buf_offset); + + /* There should be enough buffer and offset should be 16B aligned */ + if (buf_size < tmp->buf_offset + blk_len || + (tmp->buf_offset & 0xf)) { + mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x size %x\n", + k, tmp->start_mb_x, tmp->start_mb_y, + tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset, buf_size); + } + } + } + + SET_OSD_INV_THR(0, regs->reg113, region); + SET_OSD_INV_THR(1, regs->reg113, region); + SET_OSD_INV_THR(2, regs->reg113, region); + SET_OSD_INV_THR(3, regs->reg113, region); + SET_OSD_INV_THR(4, regs->reg113, region); + SET_OSD_INV_THR(5, regs->reg113, region); + SET_OSD_INV_THR(6, regs->reg113, region); + SET_OSD_INV_THR(7, regs->reg113, region); + + return MPP_OK; +} diff --git a/mpp/hal/rkenc/common/vepu541_common.h b/mpp/hal/rkenc/common/vepu541_common.h new file mode 100644 index 000000000..0d6aa1a31 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu541_common.h @@ -0,0 +1,116 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef VEPU541_COMMON_H +#define VEPU541_COMMON_H + +#include "rk_venc_cmd.h" +#include "mpp_device.h" +#include "vepu5xx_common.h" + +#define VEPU541_REG_BASE_HW_STATUS 0x0000001C +#define VEPU541_REG_BASE_STATISTICS 0x00000210 +#define VEPU541_REG_BASE_OSD_PLT 0x00000400 +#define VEPU541_REG_BASE_L2 0x00010004 + +#define VEPU541_MAX_ROI_NUM 8 + +/* + * Vepu541RoiCfg + * + * Each Vepu541RoiCfg in roi buffer indicates a 16x16 cu encoding config at + * corresponding position. + * + * NOTE: roi buffer should be aligned to 64x64 each is 4 16x16 in horizontal + * and 4 16x16 in vertical. So the buffer need to be enlarged to avoid hardware + * access error. + */ +typedef struct Vepu541RoiCfg_t { + /* + * Force_intra + * 1 - The corresponding 16x16cu is forced to be intra + * 0 - Not force to intra + */ + RK_U16 force_intra : 1; + RK_U16 reserved : 3; + /* + * Qp area index + * The choosed qp area index. + */ + RK_U16 qp_area_idx : 3; + /* + * Area qp limit function enable flag + * Force to be true in vepu541 + */ + RK_U16 qp_area_en : 1; + /* + * Qp_adj + * Qp_adj + * in absolute qp mode qp_adj is the final qp used by encoder + * in relative qp mode qp_adj is a adjustment to final qp + */ + RK_S16 qp_adj : 7; + /* + * Qp_adj_mode + * Qp adjustment mode + * 1 - absolute qp mode: + * the 16x16 MB qp is set to the qp_adj value + * 0 - relative qp mode + * the 16x16 MB qp is adjusted by qp_adj value + */ + RK_U16 qp_adj_mode : 1; +} Vepu541RoiCfg; + +typedef struct Vepu541OsdPos_t { + /* X coordinate/16 of OSD region's left-top point. */ + RK_U32 osd_lt_x : 8; + /* Y coordinate/16 of OSD region's left-top point. */ + RK_U32 osd_lt_y : 8; + /* X coordinate/16 of OSD region's right-bottom point. */ + RK_U32 osd_rb_x : 8; + /* Y coordinate/16 of OSD region's right-bottom point. */ + RK_U32 osd_rb_y : 8; +} Vepu541OsdPos; + +typedef struct Vepu541B8NumQp_t { + RK_U32 b8num_qp : 18; + RK_U32 reserved : 14; +} Vepu541B8NumQp; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * roi function + * + * vepu541_get_roi_buf_size + * Calculate roi buffer size for image with size w * h + * + * vepu541_set_roi + * Setup roi config buffeer for image with mb count mb_w * mb_h + */ +RK_S32 vepu541_get_roi_buf_size(RK_S32 w, RK_S32 h); +MPP_RET vepu541_set_roi(void *buf, MppEncROICfg *roi, RK_S32 w, RK_S32 h); +MPP_RET vepu541_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h); + +MPP_RET vepu541_set_osd(Vepu5xxOsdCfg *cfg); +MPP_RET vepu540_set_osd(Vepu5xxOsdCfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif /* VEPU541_COMMON_H */ diff --git a/mpp/hal/rkenc/common/vepu580_common.c b/mpp/hal/rkenc/common/vepu580_common.c new file mode 100644 index 000000000..ce26deab8 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu580_common.c @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vepu580_common" + +#include "mpp_debug.h" +#include "vepu580_common.h" + +MPP_RET vepu580_set_osd(Vepu5xxOsdCfg *cfg) +{ + Vepu580OsdReg *regs = (Vepu580OsdReg *)cfg->reg_base; + MppDev dev = cfg->dev; + MppDevRegOffCfgs *reg_cfg = cfg->reg_cfg; + MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg; + MppEncOSDData2 osd; + + if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2)) + return MPP_NOK; + + if (osd.num_region == 0) + return MPP_OK; + + if (osd.num_region > 8) { + mpp_err_f("do NOT support more than 8 regions invalid num %d\n", + osd.num_region); + mpp_assert(osd.num_region <= 8); + return MPP_NOK; + } + + if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) { + memcpy(regs->plt_data, plt_cfg->plt, sizeof(MppEncOSDPlt)); + regs->reg3074.osd_plt_cks = 1; + regs->reg3074.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_USERDEF; + } else { + regs->reg3074.osd_plt_cks = 0; + regs->reg3074.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_DEFAULT; + } + + regs->reg3074.osd_e = 0; + regs->reg3072.osd_lu_inv_en = 0; + regs->reg3072.osd_ch_inv_en = 0; + regs->reg3072.osd_lu_inv_msk = 0; + regs->reg3072.osd_ch_inv_msk = 0; + + RK_U32 num = osd.num_region; + RK_U32 k = 0; + MppEncOSDRegion2 *region = osd.region; + MppEncOSDRegion2 *tmp = region; + + for (k = 0; k < num; k++, tmp++) { + regs->reg3074.osd_e |= tmp->enable << k; + regs->reg3072.osd_lu_inv_en |= (tmp->inverse != 0) ? (1 << k) : 0; + regs->reg3072.osd_ch_inv_en |= (tmp->inverse != 0) ? (1 << k) : 0; + + if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) { + Vepu580OsdPos *pos = ®s->osd_pos[k]; + size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256; + RK_S32 fd = -1; + size_t buf_size = 0; + + pos->osd_lt_x = tmp->start_mb_x; + pos->osd_lt_y = tmp->start_mb_y; + pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1; + pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1; + + buf_size = mpp_buffer_get_size(tmp->buf); + fd = mpp_buffer_get_fd(tmp->buf); + if (fd < 0) { + mpp_err_f("invalid osd buffer fd %d\n", fd); + return MPP_NOK; + } + regs->osd_addr[k] = fd; + + if (tmp->buf_offset) { + if (reg_cfg) + mpp_dev_multi_offset_update(reg_cfg, VEPU580_OSD_ADDR_IDX_BASE + k, tmp->buf_offset); + else + mpp_dev_set_reg_offset(dev, VEPU580_OSD_ADDR_IDX_BASE + k, tmp->buf_offset); + } + + /* There should be enough buffer and offset should be 16B aligned */ + if (buf_size < tmp->buf_offset + blk_len || + (tmp->buf_offset & 0xf)) { + mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x size %x\n", + k, tmp->start_mb_x, tmp->start_mb_y, + tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset, buf_size); + } + } + } + + SET_OSD_INV_THR(0, regs->reg3073, region); + SET_OSD_INV_THR(1, regs->reg3073, region); + SET_OSD_INV_THR(2, regs->reg3073, region); + SET_OSD_INV_THR(3, regs->reg3073, region); + SET_OSD_INV_THR(4, regs->reg3073, region); + SET_OSD_INV_THR(5, regs->reg3073, region); + SET_OSD_INV_THR(6, regs->reg3073, region); + SET_OSD_INV_THR(7, regs->reg3073, region); + + return MPP_OK; +} diff --git a/mpp/hal/rkenc/common/vepu580_common.h b/mpp/hal/rkenc/common/vepu580_common.h new file mode 100644 index 000000000..9c1f74638 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu580_common.h @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef VEPU580_COMMON_H +#define VEPU580_COMMON_H + +#include "vepu5xx_common.h" + +#define VEPU580_SLICE_FIFO_LEN 32 +#define VEPU580_OSD_ADDR_IDX_BASE 3092 + +typedef struct Vepu580OsdPltColor_t { + /* V component */ + RK_U32 v : 8; + /* U component */ + RK_U32 u : 8; + /* Y component */ + RK_U32 y : 8; + /* Alpha */ + RK_U32 alpha : 8; +} Vepu580OsdPltColor; + +typedef struct Vepu580OsdPos_t { + /* X coordinate/16 of OSD region's left-top point. */ + RK_U32 osd_lt_x : 10; + RK_U32 reserved0 : 6; + /* Y coordinate/16 of OSD region's left-top point. */ + RK_U32 osd_lt_y : 10; + RK_U32 reserved1 : 6; + /* X coordinate/16 of OSD region's right-bottom point. */ + RK_U32 osd_rb_x : 10; + RK_U32 reserved2 : 6; + /* Y coordinate/16 of OSD region's right-bottom point. */ + RK_U32 osd_rb_y : 10; + RK_U32 reserved3 : 6; +} Vepu580OsdPos; + +typedef struct Vepu580OsdReg_t { + /* + * OSD_INV_CFG + * Address offset: 0x00003000 Access type: read and write + * OSD color inverse configuration + */ + struct { + /* + * OSD color inverse enable of luma component, + * each bit controls corresponding region. + */ + RK_U32 osd_lu_inv_en : 8; + + /* OSD color inverse enable of chroma component, + * each bit controls corresponding region. + */ + RK_U32 osd_ch_inv_en : 8; + /* + * OSD color inverse expression switch for luma component + * each bit controls corresponding region. + * 1'h0: Expression need to determine the condition; + * 1'h1: Expression don't need to determine the condition; + */ + RK_U32 osd_lu_inv_msk : 8; + /* + * OSD color inverse expression switch for chroma component + * each bit controls corresponding region. + * 1'h0: Expression need to determine the condition; + * 1'h1: Expression don't need to determine the condition; + */ + RK_U32 osd_ch_inv_msk : 8; + } reg3072; + + /* + * OSD_INV + * Address offset: 0x3004 Access type: read and write + * OSD color inverse configuration + */ + struct { + /* Color inverse theshold for OSD region0. */ + RK_U32 osd_ithd_r0 : 4; + /* Color inverse theshold for OSD region1. */ + RK_U32 osd_ithd_r1 : 4; + /* Color inverse theshold for OSD region2. */ + RK_U32 osd_ithd_r2 : 4; + /* Color inverse theshold for OSD region3. */ + RK_U32 osd_ithd_r3 : 4; + /* Color inverse theshold for OSD region4. */ + RK_U32 osd_ithd_r4 : 4; + /* Color inverse theshold for OSD region5. */ + RK_U32 osd_ithd_r5 : 4; + /* Color inverse theshold for OSD region6. */ + RK_U32 osd_ithd_r6 : 4; + /* Color inverse theshold for OSD region7. */ + RK_U32 osd_ithd_r7 : 4; + } reg3073; + + /* + * OSD_CFG + * Address offset: 0x3008 Access type: read and write + * OSD configuration + */ + struct { + /* OSD region enable, each bit controls corresponding OSD region. */ + RK_U32 osd_e : 8; + /* + * OSD color inverse expression type + * each bit controls corresponding region. + * 1'h0: AND; + * 1'h1: OR + */ + RK_U32 osd_itype : 8; + /* + * OSD palette clock selection. + * 1'h0: Configure bus clock domain. + * 1'h1: Core clock domain. + */ + RK_U32 osd_plt_cks : 1; + /* + * OSD palette type. + * 1'h1: Default type. + * 1'h0: User defined type. + */ + RK_U32 osd_plt_typ : 1; + RK_U32 reserved : 14; + } reg3074; + + RK_U32 reserved_3075; + /* + * OSD_POS reg3076_reg3091 + * Address offset: 0x3010~0x304c Access type: read and write + * OSD region position + */ + Vepu580OsdPos osd_pos[8]; + + /* + * ADR_OSD reg3092_reg3099 + * Address offset: 0x00003050~reg306c Access type: read and write + * Base address for OSD region, 16B aligned + */ + RK_U32 osd_addr[8]; + + RK_U32 reserved3100_3103[4]; + Vepu580OsdPltColor plt_data[256]; +} Vepu580OsdReg; + +MPP_RET vepu580_set_osd(Vepu5xxOsdCfg *cfg); + +#endif /* VEPU580_COMMON_H */ diff --git a/mpp/hal/rkenc/common/vepu580_tune.c b/mpp/hal/rkenc/common/vepu580_tune.c new file mode 100644 index 000000000..d948904e7 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu580_tune.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vepu580_tune" + +#include "rk_type.h" +#include "vepu580_tune.h" + +RK_S32 ctu_madp_cnt_thd[6][8] = { + {50, 100, 130, 50, 100, 550, 500, 550}, + {100, 150, 200, 80, 120, 500, 450, 550}, + {150, 200, 250, 100, 150, 450, 400, 450}, + {50, 100, 130, 50, 100, 550, 500, 550}, + {100, 150, 200, 80, 120, 500, 450, 550}, + {150, 200, 250, 100, 150, 450, 400, 450} +}; + +RK_S32 madp_num_map[5][4] = { + {0, 0, 0, 1}, + {0, 0, 1, 0}, + {0, 0, 1, 1}, + {1, 0, 0, 0}, + {1, 1, 1, 1}, +}; diff --git a/mpp/hal/rkenc/common/vepu580_tune.h b/mpp/hal/rkenc/common/vepu580_tune.h new file mode 100644 index 000000000..bb6360ed6 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu580_tune.h @@ -0,0 +1,35 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VEPU580_TUNE_H +#define VEPU580_TUNE_H + +#define FRAME_CONTENT_ANALYSIS_NUM 5 +#define FRAME_MOTION_ANALYSIS_NUM 5 +#define MD_WIN_LEN 5 +#define MD_SHOW_LEN 4 + +typedef enum MotionLevel_e { + MOTION_LEVEL_STILL = 0, + MOTION_LEVEL_MOTION = 1, + MOTION_LEVEL_BIG_MOTION = 2, + MOTION_LEVEL_UNKNOW_SCENE = 3, +} MotionLevel; + +extern RK_S32 ctu_madp_cnt_thd[6][8]; +extern RK_S32 madp_num_map[5][4]; + +#endif diff --git a/mpp/hal/rkenc/common/vepu5xx_common.c b/mpp/hal/rkenc/common/vepu5xx_common.c new file mode 100644 index 000000000..f802517e2 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu5xx_common.c @@ -0,0 +1,594 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vepu5xx_common" + +#include + +#include "mpp_debug.h" +#include "mpp_common.h" +#include "vepu5xx_common.h" + +const VepuRgb2YuvCfg vepu_rgb2limit_yuv_cfg_set[] = { + /* MPP_BT601_FULL_RGB_TO_LIMIT_YUV */ + { + .color = MPP_FRAME_SPC_RGB, .dst_range = MPP_FRAME_RANGE_UNSPECIFIED, + ._2y = {.r_coeff = 66, .g_coeff = 129, .b_coeff = 25, .offset = 16}, + ._2u = {.r_coeff = -38, .g_coeff = -74, .b_coeff = 112, .offset = 128}, + ._2v = {.r_coeff = 112, .g_coeff = -94, .b_coeff = -18, .offset = 128}, + }, + /* MPP_BT709_FULL_RGB_TO_LIMIT_YUV */ + { + .color = MPP_FRAME_SPC_BT709, .dst_range = MPP_FRAME_RANGE_UNSPECIFIED, + ._2y = {.r_coeff = 47, .g_coeff = 157, .b_coeff = 16, .offset = 16}, + ._2u = {.r_coeff = -26, .g_coeff = -87, .b_coeff = 112, .offset = 128}, + ._2v = {.r_coeff = 112, .g_coeff = -102, .b_coeff = -10, .offset = 128}, + }, +}; + +const VepuRgb2YuvCfg vepu_rgb2full_yuv_cfg_set[] = { + /* MPP_BT601_FULL_RGB_TO_FULL_YUV */ + { + .color = MPP_FRAME_SPC_RGB, .dst_range = MPP_FRAME_RANGE_JPEG, + ._2y = {.r_coeff = 77, .g_coeff = 150, .b_coeff = 29, .offset = 0}, + ._2u = {.r_coeff = -43, .g_coeff = -85, .b_coeff = 128, .offset = 128}, + ._2v = {.r_coeff = 128, .g_coeff = -107, .b_coeff = -21, .offset = 128}, + }, + /* MPP_BT709_FULL_RGB_TO_FULL_YUV */ + { + .color = MPP_FRAME_SPC_BT709, .dst_range = MPP_FRAME_RANGE_JPEG, + ._2y = {.r_coeff = 54, .g_coeff = 183, .b_coeff = 18, .offset = 0}, + ._2u = {.r_coeff = -29, .g_coeff = -99, .b_coeff = 128, .offset = 128}, + ._2v = {.r_coeff = 128, .g_coeff = -116, .b_coeff = -12, .offset = 128}, + }, +}; + +const VepuRgb2YuvCfg *get_rgb2yuv_cfg(MppFrameColorRange range, MppFrameColorSpace color) +{ + const VepuRgb2YuvCfg *cfg; + RK_U32 size; + RK_U32 i; + + /* only jpeg full range, others limit range */ + if (range == MPP_FRAME_RANGE_JPEG) { + /* set default cfg BT.601 */ + cfg = &vepu_rgb2full_yuv_cfg_set[0]; + size = MPP_ARRAY_ELEMS(vepu_rgb2full_yuv_cfg_set); + } else { + /* set default cfg BT.601 */ + cfg = &vepu_rgb2limit_yuv_cfg_set[0]; + size = MPP_ARRAY_ELEMS(vepu_rgb2limit_yuv_cfg_set); + } + + for (i = 0; i < size; i++) + if (cfg[i].color == color) + return &cfg[i]; + + return cfg; +} + +const RK_U32 vepu580_540_h264_flat_scl_tab[576] = { + /* 0x2200 */ + 0x2fbe3333, 0x2fbe4189, 0x2fbe3333, 0x2fbe4189, 0x2ca42fbe, 0x2ca43c79, 0x2ca42fbe, 0x2ca43c79, + 0x3c794189, 0x3c7951ec, 0x3c794189, 0x3c7951ec, 0x2ca42fbe, 0x2ca43c79, 0x2ca42fbe, 0x2ca43c79, + 0x2fbe3333, 0x2fbe4189, 0x2fbe3333, 0x2fbe4189, 0x2ca42fbe, 0x2ca43c79, 0x2ca42fbe, 0x2ca43c79, + 0x3c794189, 0x3c7951ec, 0x3c794189, 0x3c7951ec, 0x2ca42fbe, 0x2ca43c79, 0x2ca42fbe, 0x2ca43c79, + 0x2b322e8c, 0x2b323a84, 0x2b322e8c, 0x2b323a84, 0x2a4a2b32, 0x2a4a37d2, 0x2a4a2b32, 0x2a4a37d2, + 0x37d23a84, 0x37d24ae6, 0x37d23a84, 0x37d24ae6, 0x2a4a2b32, 0x2a4a37d2, 0x2a4a2b32, 0x2a4a37d2, + 0x2b322e8c, 0x2b323a84, 0x2b322e8c, 0x2b323a84, 0x2a4a2b32, 0x2a4a37d2, 0x2a4a2b32, 0x2a4a37d2, + 0x37d23a84, 0x37d24ae6, 0x37d23a84, 0x37d24ae6, 0x2a4a2b32, 0x2a4a37d2, 0x2a4a2b32, 0x2a4a37d2, + 0x25cb2762, 0x25cb31a6, 0x25cb2762, 0x25cb31a6, 0x22ef25cb, 0x22ef2ed1, 0x22ef25cb, 0x22ef2ed1, + 0x2ed131a6, 0x2ed13e6a, 0x2ed131a6, 0x2ed13e6a, 0x22ef25cb, 0x22ef2ed1, 0x22ef25cb, 0x22ef2ed1, + 0x25cb2762, 0x25cb31a6, 0x25cb2762, 0x25cb31a6, 0x22ef25cb, 0x22ef2ed1, 0x22ef25cb, 0x22ef2ed1, + 0x2ed131a6, 0x2ed13e6a, 0x2ed131a6, 0x2ed13e6a, 0x22ef25cb, 0x22ef2ed1, 0x22ef25cb, 0x22ef2ed1, + 0x22e32492, 0x22e32ed0, 0x22e32492, 0x22e32ed0, 0x202422e3, 0x20242bfb, 0x202422e3, 0x20242bfb, + 0x2bfb2ed0, 0x2bfb3a41, 0x2bfb2ed0, 0x2bfb3a41, 0x202422e3, 0x20242bfb, 0x202422e3, 0x20242bfb, + 0x22e32492, 0x22e32ed0, 0x22e32492, 0x22e32ed0, 0x202422e3, 0x20242bfb, 0x202422e3, 0x20242bfb, + 0x2bfb2ed0, 0x2bfb3a41, 0x2bfb2ed0, 0x2bfb3a41, 0x202422e3, 0x20242bfb, 0x202422e3, 0x20242bfb, + 0x1e3c2000, 0x1e3c28f6, 0x1e3c2000, 0x1e3c28f6, 0x1cb21e3c, 0x1cb22631, 0x1cb21e3c, 0x1cb22631, + 0x263128f6, 0x26313367, 0x263128f6, 0x26313367, 0x1cb21e3c, 0x1cb22631, 0x1cb21e3c, 0x1cb22631, + 0x1e3c2000, 0x1e3c28f6, 0x1e3c2000, 0x1e3c28f6, 0x1cb21e3c, 0x1cb22631, 0x1cb21e3c, 0x1cb22631, + 0x263128f6, 0x26313367, 0x263128f6, 0x26313367, 0x1cb21e3c, 0x1cb22631, 0x1cb21e3c, 0x1cb22631, + 0x1aae1c72, 0x1aae239e, 0x1aae1c72, 0x1aae239e, 0x191c1aae, 0x191c21c0, 0x191c1aae, 0x191c21c0, + 0x21c0239e, 0x21c02d32, 0x21c0239e, 0x21c02d32, 0x191c1aae, 0x191c21c0, 0x191c1aae, 0x191c21c0, + 0x1aae1c72, 0x1aae239e, 0x1aae1c72, 0x1aae239e, 0x191c1aae, 0x191c21c0, 0x191c1aae, 0x191c21c0, + 0x21c0239e, 0x21c02d32, 0x21c0239e, 0x21c02d32, 0x191c1aae, 0x191c21c0, 0x191c1aae, 0x191c21c0, + 0x00be0033, 0x00be0089, 0x00be0033, 0x00be0089, 0x00a400be, 0x00a40079, 0x00a400be, 0x00a40079, + 0x00790089, 0x007900ec, 0x00790089, 0x007900ec, 0x00a400be, 0x00a40079, 0x00a400be, 0x00a40079, + 0x00be0033, 0x00be0089, 0x00be0033, 0x00be0089, 0x00a400be, 0x00a40079, 0x00a400be, 0x00a40079, + 0x00790089, 0x007900ec, 0x00790089, 0x007900ec, 0x00a400be, 0x00a40079, 0x00a400be, 0x00a40079, + 0x0032008c, 0x00320084, 0x0032008c, 0x00320084, 0x004a0032, 0x004a00d2, 0x004a0032, 0x004a00d2, + 0x00d20084, 0x00d200e6, 0x00d20084, 0x00d200e6, 0x004a0032, 0x004a00d2, 0x004a0032, 0x004a00d2, + 0x0032008c, 0x00320084, 0x0032008c, 0x00320084, 0x004a0032, 0x004a00d2, 0x004a0032, 0x004a00d2, + 0x00d20084, 0x00d200e6, 0x00d20084, 0x00d200e6, 0x004a0032, 0x004a00d2, 0x004a0032, 0x004a00d2, + 0x00cb0062, 0x00cb00a6, 0x00cb0062, 0x00cb00a6, 0x00ef00cb, 0x00ef00d1, 0x00ef00cb, 0x00ef00d1, + 0x00d100a6, 0x00d1006a, 0x00d100a6, 0x00d1006a, 0x00ef00cb, 0x00ef00d1, 0x00ef00cb, 0x00ef00d1, + 0x00cb0062, 0x00cb00a6, 0x00cb0062, 0x00cb00a6, 0x00ef00cb, 0x00ef00d1, 0x00ef00cb, 0x00ef00d1, + 0x00d100a6, 0x00d1006a, 0x00d100a6, 0x00d1006a, 0x00ef00cb, 0x00ef00d1, 0x00ef00cb, 0x00ef00d1, + 0x00e30092, 0x00e300d0, 0x00e30092, 0x00e300d0, 0x002400e3, 0x002400fb, 0x002400e3, 0x002400fb, + 0x00fb00d0, 0x00fb0041, 0x00fb00d0, 0x00fb0041, 0x002400e3, 0x002400fb, 0x002400e3, 0x002400fb, + 0x00e30092, 0x00e300d0, 0x00e30092, 0x00e300d0, 0x002400e3, 0x002400fb, 0x002400e3, 0x002400fb, + 0x00fb00d0, 0x00fb0041, 0x00fb00d0, 0x00fb0041, 0x002400e3, 0x002400fb, 0x002400e3, 0x002400fb, + 0x003c0000, 0x003c00f6, 0x003c0000, 0x003c00f6, 0x00b2003c, 0x00b20031, 0x00b2003c, 0x00b20031, + 0x003100f6, 0x00310067, 0x003100f6, 0x00310067, 0x00b2003c, 0x00b20031, 0x00b2003c, 0x00b20031, + 0x003c0000, 0x003c00f6, 0x003c0000, 0x003c00f6, 0x00b2003c, 0x00b20031, 0x00b2003c, 0x00b20031, + 0x003100f6, 0x00310067, 0x003100f6, 0x00310067, 0x00b2003c, 0x00b20031, 0x00b2003c, 0x00b20031, + 0x00ae0072, 0x00ae009e, 0x00ae0072, 0x00ae009e, 0x001c00ae, 0x001c00c0, 0x001c00ae, 0x001c00c0, + 0x00c0009e, 0x00c00032, 0x00c0009e, 0x00c00032, 0x001c00ae, 0x001c00c0, 0x001c00ae, 0x001c00c0, + 0x00ae0072, 0x00ae009e, 0x00ae0072, 0x00ae009e, 0x001c00ae, 0x001c00c0, 0x001c00ae, 0x001c00c0, + 0x00c0009e, 0x00c00032, 0x00c0009e, 0x00c00032, 0x001c00ae, 0x001c00c0, 0x001c00ae, 0x001c00c0, + 0x002f0033, 0x002f0041, 0x002f0033, 0x002f0041, 0x002c002f, 0x002c003c, 0x002c002f, 0x002c003c, + 0x003c0041, 0x003c0051, 0x003c0041, 0x003c0051, 0x002c002f, 0x002c003c, 0x002c002f, 0x002c003c, + 0x002f0033, 0x002f0041, 0x002f0033, 0x002f0041, 0x002c002f, 0x002c003c, 0x002c002f, 0x002c003c, + 0x003c0041, 0x003c0051, 0x003c0041, 0x003c0051, 0x002c002f, 0x002c003c, 0x002c002f, 0x002c003c, + 0x002b002e, 0x002b003a, 0x002b002e, 0x002b003a, 0x002a002b, 0x002a0037, 0x002a002b, 0x002a0037, + 0x0037003a, 0x0037004a, 0x0037003a, 0x0037004a, 0x002a002b, 0x002a0037, 0x002a002b, 0x002a0037, + 0x002b002e, 0x002b003a, 0x002b002e, 0x002b003a, 0x002a002b, 0x002a0037, 0x002a002b, 0x002a0037, + 0x0037003a, 0x0037004a, 0x0037003a, 0x0037004a, 0x002a002b, 0x002a0037, 0x002a002b, 0x002a0037, + 0x01250127, 0x01250131, 0x01250127, 0x01250131, 0x01220125, 0x0122012e, 0x01220125, 0x0122012e, + 0x012e0131, 0x012e013e, 0x012e0131, 0x012e013e, 0x01220125, 0x0122012e, 0x01220125, 0x0122012e, + 0x01250127, 0x01250131, 0x01250127, 0x01250131, 0x01220125, 0x0122012e, 0x01220125, 0x0122012e, + 0x012e0131, 0x012e013e, 0x012e0131, 0x012e013e, 0x01220125, 0x0122012e, 0x01220125, 0x0122012e, + 0x01220124, 0x0122012e, 0x01220124, 0x0122012e, 0x01200122, 0x0120012b, 0x01200122, 0x0120012b, + 0x012b012e, 0x012b013a, 0x012b012e, 0x012b013a, 0x01200122, 0x0120012b, 0x01200122, 0x0120012b, + 0x01220124, 0x0122012e, 0x01220124, 0x0122012e, 0x01200122, 0x0120012b, 0x01200122, 0x0120012b, + 0x012b012e, 0x012b013a, 0x012b012e, 0x012b013a, 0x01200122, 0x0120012b, 0x01200122, 0x0120012b, + 0x001e0020, 0x001e0028, 0x001e0020, 0x001e0028, 0x001c001e, 0x001c0026, 0x001c001e, 0x001c0026, + 0x00260028, 0x00260033, 0x00260028, 0x00260033, 0x001c001e, 0x001c0026, 0x001c001e, 0x001c0026, + 0x001e0020, 0x001e0028, 0x001e0020, 0x001e0028, 0x001c001e, 0x001c0026, 0x001c001e, 0x001c0026, + 0x00260028, 0x00260033, 0x00260028, 0x00260033, 0x001c001e, 0x001c0026, 0x001c001e, 0x001c0026, + 0x001a001c, 0x001a0023, 0x001a001c, 0x001a0023, 0x0019001a, 0x00190021, 0x0019001a, 0x00190021, + 0x00210023, 0x0021002d, 0x00210023, 0x0021002d, 0x0019001a, 0x00190021, 0x0019001a, 0x00190021, + 0x001a001c, 0x001a0023, 0x001a001c, 0x001a0023, 0x0019001a, 0x00190021, 0x0019001a, 0x00190021, + 0x00210023, 0x0021002d, 0x00210023, 0x0021002d, 0x0019001a, 0x00190021, 0x0019001a, 0x00190021, +}; + +const RK_U32 klut_weight[24] = { + 0x50800080, 0x00330000, 0xA1000100, 0x00660000, 0x42000200, 0x00CC0001, + 0x84000400, 0x01980002, 0x08000800, 0x03300005, 0x10001000, 0x0660000A, + 0x20002000, 0x0CC00014, 0x40004000, 0x19800028, 0x80008000, 0x33000050, + 0x00010000, 0x660000A1, 0x00020000, 0xCC000142, 0xFF83FFFF, 0x000001FF +}; + +const RK_U32 lamd_satd_qp[52] = { + 0x00000183, 0x000001b2, 0x000001e7, 0x00000223, 0x00000266, 0x000002b1, 0x00000305, 0x00000364, + 0x000003ce, 0x00000445, 0x000004cb, 0x00000562, 0x0000060a, 0x000006c8, 0x0000079c, 0x0000088b, + 0x00000996, 0x00000ac3, 0x00000c14, 0x00000d8f, 0x00000f38, 0x00001115, 0x0000132d, 0x00001586, + 0x00001829, 0x00001b1e, 0x00001e70, 0x0000222b, 0x0000265a, 0x00002b0c, 0x00003052, 0x0000363c, + 0x00003ce1, 0x00004455, 0x00004cb4, 0x00005618, 0x000060a3, 0x00006c79, 0x000079c2, 0x000088ab, + 0x00009967, 0x0000ac30, 0x0000c147, 0x0000d8f2, 0x0000f383, 0x00011155, 0x000132ce, 0x00015861, + 0x0001828d, 0x0001b1e4, 0x0001e706, 0x000222ab +}; + +const RK_U32 lamd_moda_qp[52] = { + 0x00000049, 0x0000005c, 0x00000074, 0x00000092, 0x000000b8, 0x000000e8, 0x00000124, 0x00000170, + 0x000001cf, 0x00000248, 0x000002df, 0x0000039f, 0x0000048f, 0x000005bf, 0x0000073d, 0x0000091f, + 0x00000b7e, 0x00000e7a, 0x0000123d, 0x000016fb, 0x00001cf4, 0x0000247b, 0x00002df6, 0x000039e9, + 0x000048f6, 0x00005bed, 0x000073d1, 0x000091ec, 0x0000b7d9, 0x0000e7a2, 0x000123d7, 0x00016fb2, + 0x0001cf44, 0x000247ae, 0x0002df64, 0x00039e89, 0x00048f5c, 0x0005bec8, 0x00073d12, 0x00091eb8, + 0x000b7d90, 0x000e7a23, 0x00123d71, 0x0016fb20, 0x001cf446, 0x00247ae1, 0x002df640, 0x0039e88c, + 0x0048f5c3, 0x005bec81, 0x0073d119, 0x0091eb85 +}; + +const RK_U32 lamd_modb_qp[52] = { + 0x00000070, 0x00000089, 0x000000b0, 0x000000e0, 0x00000112, 0x00000160, 0x000001c0, 0x00000224, + 0x000002c0, 0x00000380, 0x00000448, 0x00000580, 0x00000700, 0x00000890, 0x00000b00, 0x00000e00, + 0x00001120, 0x00001600, 0x00001c00, 0x00002240, 0x00002c00, 0x00003800, 0x00004480, 0x00005800, + 0x00007000, 0x00008900, 0x0000b000, 0x0000e000, 0x00011200, 0x00016000, 0x0001c000, 0x00022400, + 0x0002c000, 0x00038000, 0x00044800, 0x00058000, 0x00070000, 0x00089000, 0x000b0000, 0x000e0000, + 0x00112000, 0x00160000, 0x001c0000, 0x00224000, 0x002c0000, 0x00380000, 0x00448000, 0x00580000, + 0x00700000, 0x00890000, 0x00b00000, 0x00e00000 +}; + +const RK_U32 lamd_satd_qp_510[52] = { + 0x00000243, 0x00000289, 0x000002DA, 0x00000333, 0x00000397, 0x00000408, 0x00000487, 0x00000514, + 0x000005B5, 0x00000667, 0x000007C9, 0x000008BD, 0x00000B52, 0x00000CB5, 0x00000E44, 0x00001002, + 0x000011F9, 0x0000142D, 0x00001523, 0x000017BA, 0x00001AA2, 0x0000199F, 0x00001CC2, 0x00002049, + 0x0000243C, 0x000032D8, 0x00002DA8, 0x0000333F, 0x00003985, 0x00004092, 0x00004879, 0x000065B0, + 0x000062EC, 0x000088AA, 0x00007CA2, 0x0000AC30, 0x00009D08, 0x0000B043, 0x0000C5D9, 0x0000EF29, + 0x00010C74, 0x00012D54, 0x000121E9, 0x00014569, 0x00018BB4, 0x0001BC2A, 0x0001F28E, 0x00020490, + 0x000243D3, 0x00028AD4, 0x0002DA89, 0x000333FF, +}; + +static const RK_S32 zeros[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +static VepuFmtCfg vepu5xx_yuv_cfg[MPP_FMT_YUV_BUTT] = { + { /* MPP_FMT_YUV420SP */ + .format = VEPU5xx_FMT_YUV420SP, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV420SP_10BIT */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422SP */ + .format = VEPU5xx_FMT_YUV422SP, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422SP_10BIT */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV420P */ + .format = VEPU5xx_FMT_YUV420P, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV420SP_VU */ + .format = VEPU5xx_FMT_YUV420SP, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422P */ + .format = VEPU5xx_FMT_YUV422P, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422SP_VU */ + .format = VEPU5xx_FMT_YUV422SP, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422_YUYV */ + .format = VEPU5xx_FMT_YUYV422, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422_YVYU */ + .format = VEPU5xx_FMT_YUYV422, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422_UYVY */ + .format = VEPU5xx_FMT_UYVY422, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV422_VYUY */ + .format = VEPU5xx_FMT_UYVY422, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV400 */ + .format = VEPU5xx_FMT_YUV400, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV440SP */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV411SP */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_YUV444SP */ + .format = VEPU5xx_FMT_YUV444SP, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + + { /* MPP_FMT_YUV444P */ + .format = VEPU5xx_FMT_YUV444P, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + + { /* MPP_FMT_YUV444SP_10BIT */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + + { /* MPP_FMT_AYUV2BPP */ + .format = VEPU5xx_FMT_AYUV2BPP, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + + { /* MPP_FMT_AYUV1BPP */ + .format = VEPU5xx_FMT_AYUV1BPP, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, +}; + +static VepuFmtCfg vepu5xx_rgb_cfg[MPP_FMT_RGB_BUTT - MPP_FRAME_FMT_RGB] = { + { /* MPP_FMT_RGB565 */ + .format = VEPU5xx_FMT_BGR565, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_range = 0, + .src_endian = 1, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_BGR565 */ + .format = VEPU5xx_FMT_BGR565, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 1, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_RGB555 */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_BGR555 */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_RGB444 */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_BGR444 */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_RGB888 */ + .format = VEPU5xx_FMT_BGR888, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_BGR888 */ + .format = VEPU5xx_FMT_BGR888, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_RGB101010 */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_BGR101010 */ + .format = VEPU5xx_FMT_BUTT, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_ARGB8888 */ + .format = VEPU5xx_FMT_BGRA8888, + .alpha_swap = 1, + .rbuv_swap = 1, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_ABGR8888 */ + .format = VEPU5xx_FMT_BGRA8888, + .alpha_swap = 1, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_BGRA8888 */ + .format = VEPU5xx_FMT_BGRA8888, + .alpha_swap = 0, + .rbuv_swap = 0, + .src_range = 0, + .src_endian = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_RGBA8888 */ + .format = VEPU5xx_FMT_BGRA8888, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_endian = 0, + .src_range = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_ARGB4444 */ + .format = VEPU5xx_FMT_ARGB4444, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_endian = 0, + .src_range = 0, + .weight = zeros, + .offset = zeros, + }, + { /* MPP_FMT_ARGB1555 */ + .format = VEPU5xx_FMT_ARGB1555, + .alpha_swap = 0, + .rbuv_swap = 1, + .src_endian = 0, + .src_range = 0, + .weight = zeros, + .offset = zeros, + }, +}; + +MPP_RET copy2osd2(MppEncOSDData2* dst, MppEncOSDData *src1, MppEncOSDData2 *src2) +{ + MPP_RET ret = MPP_OK; + RK_U32 i = 0; + + if (src1) { + dst->num_region = src1->num_region; + for (i = 0; i < src1->num_region; i++) { + dst->region[i].enable = src1->region[i].enable; + dst->region[i].inverse = src1->region[i].inverse; + dst->region[i].start_mb_x = src1->region[i].start_mb_x; + dst->region[i].start_mb_y = src1->region[i].start_mb_y; + dst->region[i].num_mb_x = src1->region[i].num_mb_x; + dst->region[i].num_mb_y = src1->region[i].num_mb_y; + dst->region[i].buf_offset = src1->region[i].buf_offset; + dst->region[i].buf = src1->buf; + } + ret = MPP_OK; + } else if (src2) { + memcpy(dst, src2, sizeof(MppEncOSDData2)); + ret = MPP_OK; + } else { + ret = MPP_NOK; + } + return ret; +} + +MPP_RET vepu5xx_set_fmt(VepuFmtCfg * cfg, MppFrameFormat format) +{ + VepuFmtCfg *fmt = NULL; + MPP_RET ret = MPP_OK; + + format &= MPP_FRAME_FMT_MASK; + + if (MPP_FRAME_FMT_IS_YUV(format)) + fmt = &vepu5xx_yuv_cfg[format - MPP_FRAME_FMT_YUV]; + else if (MPP_FRAME_FMT_IS_RGB(format)) + fmt = &vepu5xx_rgb_cfg[format - MPP_FRAME_FMT_RGB]; + else { + memset(cfg, 0, sizeof(*cfg)); + cfg->format = VEPU5xx_FMT_BUTT; + } + + if (fmt && fmt->format != VEPU5xx_FMT_BUTT) + memcpy(cfg, fmt, sizeof(*cfg)); + else { + mpp_err_f("unsupport frame format %x\n", format); + cfg->format = VEPU5xx_FMT_BUTT; + ret = MPP_NOK; + } + + return ret; +} \ No newline at end of file diff --git a/mpp/hal/rkenc/common/vepu5xx_common.h b/mpp/hal/rkenc/common/vepu5xx_common.h new file mode 100644 index 000000000..e50e15b65 --- /dev/null +++ b/mpp/hal/rkenc/common/vepu5xx_common.h @@ -0,0 +1,116 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VEPU5XX_COMMON_H +#define VEPU5XX_COMMON_H + +#include "rk_venc_cmd.h" +#include "mpp_device.h" + +/* + * Invert color threshold is for the absolute difference between background + * and foregroud color. + * If background color and foregroud color are close enough then trigger the + * invert color process. + */ +#define ENC_DEFAULT_OSD_INV_THR 15 +#define SET_OSD_INV_THR(index, reg, region)\ + if(region[index].inverse) \ + reg.osd_ithd_r##index = ENC_DEFAULT_OSD_INV_THR; + +typedef enum Vepu5xxOsdPltType_e { + VEPU5xx_OSD_PLT_TYPE_USERDEF = 0, + VEPU5xx_OSD_PLT_TYPE_DEFAULT = 1, +} Vepu5xxOsdPltType; + +typedef enum VepuFmt_e { + VEPU5xx_FMT_BGRA8888, // 0 + VEPU5xx_FMT_BGR888, // 1 + VEPU5xx_FMT_BGR565, // 2 + VEPU5xx_FMT_ARGB1555, // 3 + VEPU5xx_FMT_YUV422SP, // 4 + VEPU5xx_FMT_YUV422P, // 5 + VEPU5xx_FMT_YUV420SP, // 6 + VEPU5xx_FMT_YUV420P, // 7 + VEPU5xx_FMT_YUYV422, // 8 + VEPU5xx_FMT_UYVY422, // 9 + VEPU5xx_FMT_YUV400, // 10 + VEPU5xx_FMT_AYUV2BPP, // 11 + VEPU5xx_FMT_YUV444SP, // 12 + VEPU5xx_FMT_YUV444P, // 13 + VEPU5xx_FMT_ARGB4444, // 14 + VEPU5xx_FMT_AYUV1BPP, // 15 + VEPU5xx_FMT_BUTT, // 16 +} VepuFmt; + +typedef struct VepuFmtCfg_t { + VepuFmt format; + RK_U32 alpha_swap; + RK_U32 rbuv_swap; + RK_U32 src_range; + RK_U32 src_endian; + const RK_S32 *weight; + const RK_S32 *offset; +} VepuFmtCfg; + +typedef struct Vepu5xxOsdCfg_t { + void *reg_base; + MppDev dev; + MppDevRegOffCfgs *reg_cfg; + MppEncOSDPltCfg *plt_cfg; + MppEncOSDData *osd_data; + MppEncOSDData2 *osd_data2; +} Vepu5xxOsdCfg; + +typedef struct VepuRgb2YuvCoeffs_t { + RK_S16 r_coeff; + RK_S16 g_coeff; + RK_S16 b_coeff; + RK_S16 offset; +} VepuRgb2YuvCoeffs; + +/* formula: y(r, g, b) = (r_coeff x r + g_coeff x g + b_coeff x b + 128) >> 8 + offset */ +typedef struct VepuRgb2YuvCfg_t { + /* YUV colorspace type */ + MppFrameColorSpace color; + /* MPEG vs JPEG YUV range */ + MppFrameColorRange dst_range; + /* coeffs of rgb 2 yuv */ + VepuRgb2YuvCoeffs _2y; + VepuRgb2YuvCoeffs _2u; + VepuRgb2YuvCoeffs _2v; +} VepuRgb2YuvCfg; + +/** + * @brief Get rgb2yuv cfg by color range and color space. If not found, return default cfg. + * default cfg's yuv range - limit. + * default cfg's color space - BT.601. + */ +const VepuRgb2YuvCfg* get_rgb2yuv_cfg(MppFrameColorRange range, MppFrameColorSpace color); + +MPP_RET copy2osd2(MppEncOSDData2* dst, MppEncOSDData *src1, MppEncOSDData2 *src2); + +MPP_RET vepu5xx_set_fmt(VepuFmtCfg *cfg, MppFrameFormat format); + +extern const RK_U32 vepu580_540_h264_flat_scl_tab[576]; + +extern const RK_U32 klut_weight[24]; +extern const RK_U32 lamd_satd_qp[52]; +extern const RK_U32 lamd_moda_qp[52]; +extern const RK_U32 lamd_modb_qp[52]; +extern const RK_U32 lamd_satd_qp_510[52]; + +#endif /* VEPU5XX_COMMON_H */ \ No newline at end of file diff --git a/mpp/hal/rkenc/h264e/CMakeLists.txt b/mpp/hal/rkenc/h264e/CMakeLists.txt new file mode 100644 index 000000000..cc1d13e8e --- /dev/null +++ b/mpp/hal/rkenc/h264e/CMakeLists.txt @@ -0,0 +1,21 @@ +# vim: syntax=cmake +include_directories(.) +# hal/common for hal_bufs module +include_directories(../common/) +include_directories(../../common/h264/) +# mpp/codec/enc/h264 for h264 syntax +include_directories(../../../codec/enc/h264/) + +# hal h264 encoder sourse +set(HAL_H264E_SRC) + +add_hal_source(HAL_H264E_SRC HAVE_VEPU541 hal_h264e_vepu541.c) +add_hal_source(HAL_H264E_SRC HAVE_VEPU580 hal_h264e_vepu580.c) +add_hal_source(HAL_H264E_SRC HAVE_VEPU540C hal_h264e_vepu540c.c) +add_hal_source(HAL_H264E_SRC HAVE_VEPU510 hal_h264e_vepu510.c) +add_hal_source(HAL_H264E_SRC HAVE_VEPU511 hal_h264e_vepu511.c) +add_hal_source(HAL_H264E_SRC HAVE_VEPU511A hal_h264e_vepu511a.c) + +if (HAL_H264E_SRC) + add_library(hal_h264e_vepu5xx OBJECT ${HAL_H264E_SRC}) +endif() diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c new file mode 100644 index 000000000..51c03ff29 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.c @@ -0,0 +1,2586 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h264e_vepu510" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" +#include "mpp_enc_cb_param.h" + +#include "rkv_enc_def.h" +#include "hal_h264e_debug.h" +#include "hal_bufs.h" +#include "hal_h264e_vepu510_reg.h" +#include "hal_h264e_vepu510.h" +#include "hal_h264e_stream_amend.h" +#include "h264e_dpb.h" + +#include "vepu5xx_common.h" +#include "vepu510_common.h" + +#define DUMP_REG 0 +#define MAX_TASK_CNT 2 +#define VEPU540C_MAX_ROI_NUM 8 + +/* Custom Quant Matrices: Joint Video Team */ +static RK_U8 vepu510_h264_cqm_jvt8i[64] = { + 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static RK_U8 vepu510_h264_cqm_jvt8p[64] = { + 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 +}; + +typedef struct Vepu510RoiH264BsCfg_t { + RK_U64 force_inter : 42; + RK_U64 mode_mask : 9; + RK_U64 reserved : 10; + RK_U64 force_intra : 1; + RK_U64 qp_adj_en : 1; + RK_U64 amv_en : 1; +} Vepu510RoiH264BsCfg; + +typedef struct Vepu510H264Fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 frame_type; + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; + RK_U32 st_smear_cnt[5]; +} Vepu510H264Fbk; + +typedef struct HalH264eVepu510Ctx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_S32 frame_cnt; + RK_U32 task_cnt; + + /* buffers management */ + HalBufs hw_recn; + RK_S32 pixel_buf_fbc_hdr_size; + RK_S32 pixel_buf_fbc_bdy_size; + RK_S32 pixel_buf_size; + RK_S32 thumb_buf_size; + RK_S32 max_buf_cnt; + MppDevRegOffCfgs *offsets; + + /* external line buffer over 4K */ + MppBufferGroup ext_line_buf_grp; + MppBuffer ext_line_bufs[MAX_TASK_CNT]; + RK_S32 ext_line_buf_size; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eDpb *dpb; + H264eFrmInfo *frms; + + /* async encode TSVC info */ + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + + /* syntax for output to enc_impl */ + EncRcTaskInfo hal_rc_cfg; + + /* roi */ + void *roi_data; + MppBufferGroup roi_grp; + MppBuffer roir_buf; + RK_S32 roir_buf_size; + + /* two-pass deflicker */ + MppBuffer buf_pass1; + + /* register */ + HalVepu510RegSet *regs_sets; + HalH264eVepuStreamAmend *amend_sets; + + H264ePrefixNal *prefix_sets; + H264eSlice *slice_sets; + + /* frame parallel info */ + RK_S32 task_idx; + RK_S32 curr_idx; + RK_S32 prev_idx; + RK_S32 slot_to_dchs_txid[H264E_MAX_REFS_CNT]; + + HalVepu510RegSet *regs_set; + HalH264eVepuStreamAmend *amend; + H264ePrefixNal *prefix; + H264eSlice *slice; + + MppBuffer ext_line_buf; + + /* slice low delay output callback */ + MppCbCtx *output_cb; + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + MppDevPollCfg *poll_cfgs; + + Vepu510H264Fbk feedback; + Vepu510H264Fbk last_frame_fb; + + void *tune; + RK_S32 smart_en; + RK_S32 qpmap_en; + RK_S32 sp_enc_en; +} HalH264eVepu510Ctx; + +#include "hal_h264e_vepu510_tune.c" + +static RK_S32 h264_aq_tthd_default[16] = { + 0, 0, 0, 0, 3, 3, 5, 5, + 8, 8, 8, 15, 15, 20, 25, 25 +}; + +static RK_S32 h264_P_aq_step_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 7, 8 +}; + +static RK_S32 h264_I_aq_step_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 7, 8 +}; + +static void setup_ext_line_bufs(HalH264eVepu510Ctx *ctx) +{ + RK_U32 i; + + for (i = 0; i < ctx->task_cnt; i++) { + if (ctx->ext_line_bufs[i]) + continue; + + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_bufs[i], + ctx->ext_line_buf_size); + } +} + +static void clear_ext_line_bufs(HalH264eVepu510Ctx *ctx) +{ + RK_U32 i; + + for (i = 0; i < ctx->task_cnt; i++) { + if (ctx->ext_line_bufs[i]) { + mpp_buffer_put(ctx->ext_line_bufs[i]); + ctx->ext_line_bufs[i] = NULL; + } + } +} + +static MPP_RET hal_h264e_vepu510_deinit(void *hal) +{ + HalH264eVepu510Ctx *p = (HalH264eVepu510Ctx *)hal; + RK_U32 i; + + hal_h264e_dbg_func("enter %p\n", p); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + clear_ext_line_bufs(p); + + if (p->amend_sets) { + for (i = 0; i < p->task_cnt; i++) + h264e_vepu_stream_amend_deinit(&p->amend_sets[i]); + } + + MPP_FREE(p->regs_sets); + MPP_FREE(p->amend_sets); + MPP_FREE(p->prefix_sets); + MPP_FREE(p->slice_sets); + MPP_FREE(p->reorder); + MPP_FREE(p->marking); + MPP_FREE(p->poll_cfgs); + + if (p->ext_line_buf_grp) { + mpp_buffer_group_put(p->ext_line_buf_grp); + p->ext_line_buf_grp = NULL; + } + + if (p->hw_recn) { + hal_bufs_deinit(p->hw_recn); + p->hw_recn = NULL; + } + + if (p->roir_buf) { + mpp_buffer_put(p->roir_buf); + p->roir_buf = NULL; + p->roir_buf_size = 0; + } + + if (p->roi_grp) { + mpp_buffer_group_put(p->roi_grp); + p->roi_grp = NULL; + } + + if (p->offsets) { + mpp_dev_multi_offset_deinit(p->offsets); + p->offsets = NULL; + } + + if (p->buf_pass1) { + mpp_buffer_put(p->buf_pass1); + p->buf_pass1 = NULL; + } + + if (p->tune) { + vepu510_h264e_tune_deinit(p->tune); + p->tune = NULL; + } + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu510_init(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu510Ctx *p = (HalH264eVepu510Ctx *)hal; + MPP_RET ret = MPP_OK; + RK_U32 i; + + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + p->task_cnt = cfg->task_cnt; + mpp_assert(p->task_cnt && p->task_cnt <= MAX_TASK_CNT); + + ret = hal_bufs_init(&p->hw_recn); + if (ret) { + mpp_err_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + p->regs_sets = mpp_malloc(HalVepu510RegSet, p->task_cnt); + if (NULL == p->regs_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init register buffer failed\n"); + goto DONE; + } + + p->amend_sets = mpp_malloc(HalH264eVepuStreamAmend, p->task_cnt); + if (NULL == p->amend_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + if (p->task_cnt > 1) { + p->prefix_sets = mpp_malloc(H264ePrefixNal, p->task_cnt); + if (NULL == p->prefix_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + p->slice_sets = mpp_malloc(H264eSlice, p->task_cnt); + if (NULL == p->slice_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + p->reorder = mpp_malloc(H264eReorderInfo, 1); + if (NULL == p->reorder) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + p->marking = mpp_malloc(H264eMarkingInfo, 1); + if (NULL == p->marking) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + } + + p->poll_slice_max = 8; + p->poll_cfg_size = (sizeof(p->poll_cfgs) + sizeof(RK_S32) * p->poll_slice_max); + p->poll_cfgs = mpp_malloc_size(MppDevPollCfg, p->poll_cfg_size * p->task_cnt); + if (NULL == p->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init poll cfg buffer failed\n"); + goto DONE; + } + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 1; + hw->qp_delta_row = 2; + hw->extra_buf = 1; + hw->qbias_i = 683; + hw->qbias_p = 341; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, h264_aq_tthd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, h264_aq_tthd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, h264_I_aq_step_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, h264_P_aq_step_default, sizeof(hw->aq_step_p)); + + for (i = 0; i < MPP_ARRAY_ELEMS(hw->mode_bias); i++) + hw->mode_bias[i] = 8; + + hw->skip_sad = 8; + hw->skip_bias = 8; + } + + mpp_dev_multi_offset_init(&p->offsets, 24); + p->output_cb = cfg->output_cb; + cfg->cap_recn_out = 1; + for (i = 0; i < p->task_cnt; i++) + h264e_vepu_stream_amend_init(&p->amend_sets[i]); + + p->tune = vepu510_h264e_tune_init(p); + memset(p->slot_to_dchs_txid, 0, sizeof(p->slot_to_dchs_txid)); + +DONE: + if (ret) + hal_h264e_vepu510_deinit(hal); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +/* + * NOTE: recon / refer buffer is FBC data buffer. + * And FBC data require extra 16 lines space for hardware io. + */ +static void setup_hal_bufs(HalH264eVepu510Ctx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + RK_S32 alignment_w = 64; + RK_S32 alignment_h = 16; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment_w); + RK_S32 aligned_h = MPP_ALIGN(prep->height, alignment_h) + 16; + RK_S32 pixel_buf_fbc_hdr_size = MPP_ALIGN(aligned_w * aligned_h / 64, SZ_8K); + RK_S32 pixel_buf_fbc_bdy_size = aligned_w * aligned_h * 3 / 2; + RK_S32 pixel_buf_size = pixel_buf_fbc_hdr_size + pixel_buf_fbc_bdy_size; + RK_S32 thumb_buf_size = MPP_ALIGN(aligned_w / 64 * aligned_h / 64 * 256, SZ_8K); + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + MppEncRefCfg ref_cfg = cfg->ref_cfg; + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + if (new_max_cnt < MPP_MAX(new_max_cnt, info->dpb_size + 1)) + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > SZ_4K) { + RK_S32 ctu_w = (aligned_w + 63) / 64; + RK_S32 ext_line_buf_size = ((ctu_w - 53) * 53 + 15) / 16 * 16 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + clear_ext_line_bufs(ctx); + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + + ctx->ext_line_buf_size = ext_line_buf_size; + setup_ext_line_bufs(ctx); + } else { + clear_ext_line_bufs(ctx); + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + if ((ctx->pixel_buf_fbc_hdr_size != pixel_buf_fbc_hdr_size) || + (ctx->pixel_buf_fbc_bdy_size != pixel_buf_fbc_bdy_size) || + (ctx->pixel_buf_size != pixel_buf_size) || + (ctx->thumb_buf_size != thumb_buf_size) || + (new_max_cnt > old_max_cnt)) { + size_t sizes[3]; + + hal_h264e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->pixel_buf_size, pixel_buf_size, + old_max_cnt, new_max_cnt); + + /* pixel buffer */ + sizes[0] = pixel_buf_size; + /* thumb buffer */ + sizes[1] = thumb_buf_size; + /* smear buffer */ + sizes[2] = MPP_ALIGN(aligned_w / 64, 16) * MPP_ALIGN(aligned_h / 16, 16); + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_bufs_setup(ctx->hw_recn, new_max_cnt, MPP_ARRAY_ELEMS(sizes), sizes); + + ctx->pixel_buf_fbc_hdr_size = pixel_buf_fbc_hdr_size; + ctx->pixel_buf_fbc_bdy_size = pixel_buf_fbc_bdy_size; + ctx->pixel_buf_size = pixel_buf_size; + ctx->thumb_buf_size = thumb_buf_size; + ctx->max_buf_cnt = new_max_cnt; + } +} + +static MPP_RET hal_h264e_vepu510_prepare(void *hal) +{ + HalH264eVepu510Ctx *ctx = (HalH264eVepu510Ctx *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->hw_recn, i); + + prep->change_res = 0; + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_U32 update_vepu510_syntax(HalH264eVepu510Ctx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + ctx->dpb = desc->p; + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu510_get_task(void *hal, HalEncTask *task) +{ + HalH264eVepu510Ctx *ctx = (HalH264eVepu510Ctx *)hal; + MppEncCfgSet *cfg_set = ctx->cfg; + MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg_set->ref_cfg; + MppEncH264HwCfg *hw_cfg = &cfg_set->h264.hw_cfg; + RK_U32 updated = update_vepu510_syntax(ctx, &task->syntax); + EncFrmStatus *frm_status = &task->rc_task->frm; + H264eFrmInfo *frms = ctx->frms; + + hal_h264e_dbg_func("enter %p\n", hal); + + ctx->smart_en = (ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC); + ctx->qpmap_en = ctx->cfg->tune.deblur_en; + ctx->sp_enc_en = ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SE; + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) + setup_hal_bufs(ctx); + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(task->frame); + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + } + + if (!frm_status->reencode) + ctx->last_frame_fb = ctx->feedback; + + if (ctx->dpb) { + h264e_dpb_hal_start(ctx->dpb, frms->curr_idx); + h264e_dpb_hal_start(ctx->dpb, frms->refr_idx); + } + + task->flags.reg_idx = ctx->task_idx; + task->flags.curr_idx = frms->curr_idx; + task->flags.refr_idx = frms->refr_idx; + task->part_first = 1; + task->part_last = 0; + + ctx->ext_line_buf = ctx->ext_line_bufs[ctx->task_idx]; + ctx->regs_set = &ctx->regs_sets[ctx->task_idx]; + ctx->amend = &ctx->amend_sets[ctx->task_idx]; + + /* if not VEPU1/2, update log2_max_frame_num_minus4 in hw_cfg */ + hw_cfg->hw_log2_max_frame_num_minus4 = ctx->sps->log2_max_frame_num_minus4; + hw_cfg->hw_poc_type = ctx->sps->pic_order_cnt_type; + + if (ctx->task_cnt > 1 && (ref->lt_cfg_cnt || ref->st_cfg_cnt > 1)) { + H264ePrefixNal *prefix = &ctx->prefix_sets[ctx->task_idx]; + H264eSlice *slice = &ctx->slice_sets[ctx->task_idx]; + + //store async encode TSVC info + if (ctx->prefix) + memcpy(prefix, ctx->prefix, sizeof(H264ePrefixNal)); + else + prefix = NULL; + + if (ctx->slice) { + memcpy(slice, ctx->slice, sizeof(H264eSlice)); + + /* + * Generally, reorder and marking are shared by dpb and slice. + * However, async encoding TSVC will change reorder and marking in each task. + * Therefore, malloc a special space for async encoding TSVC. + */ + ctx->amend->reorder = ctx->reorder; + ctx->amend->marking = ctx->marking; + } + + h264e_vepu_stream_amend_config(ctx->amend, task->packet, ctx->cfg, + slice, prefix); + } else { + h264e_vepu_stream_amend_config(ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + } + + if (ctx->task_cnt > 1) + ctx->task_idx = !ctx->task_idx; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static void setup_vepu510_normal(HalVepu510RegSet *regs) +{ + hal_h264e_dbg_func("enter\n"); + /* reg000 VERSION is read only */ + + /* reg001 ENC_STRT */ + regs->reg_ctl.enc_strt.lkt_num = 0; + regs->reg_ctl.enc_strt.vepu_cmd = 1; + + regs->reg_ctl.opt_strg.cke = 1; + regs->reg_ctl.opt_strg.resetn_hw_en = 1; + + /* reg002 ENC_CLR */ + regs->reg_ctl.enc_clr.safe_clr = 0; + regs->reg_ctl.enc_clr.force_clr = 0; + + /* reg004 INT_EN */ + regs->reg_ctl.int_en.enc_done_en = 1; + regs->reg_ctl.int_en.lkt_node_done_en = 1; + regs->reg_ctl.int_en.sclr_done_en = 1; + regs->reg_ctl.int_en.vslc_done_en = 0; + regs->reg_ctl.int_en.vbsf_oflw_en = 1; + regs->reg_ctl.int_en.vbuf_lens_en = 1; + regs->reg_ctl.int_en.enc_err_en = 1; + + regs->reg_ctl.int_en.wdg_en = 1; + regs->reg_ctl.int_en.vsrc_err_en = 1; + regs->reg_ctl.int_en.wdg_en = 1; + regs->reg_ctl.int_en.lkt_err_int_en = 1; + regs->reg_ctl.int_en.lkt_err_stop_en = 1; + regs->reg_ctl.int_en.lkt_force_stop_en = 1; + regs->reg_ctl.int_en.jslc_done_en = 1; + regs->reg_ctl.int_en.jbsf_oflw_en = 1; + regs->reg_ctl.int_en.jbuf_lens_en = 1; + regs->reg_ctl.int_en.dvbm_err_en = 0; + + /* reg005 INT_MSK */ + regs->reg_ctl.int_msk.enc_done_msk = 0; + regs->reg_ctl.int_msk.lkt_node_done_msk = 0; + regs->reg_ctl.int_msk.sclr_done_msk = 0; + regs->reg_ctl.int_msk.vslc_done_msk = 0; + regs->reg_ctl.int_msk.vbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.vbuf_lens_msk = 0; + regs->reg_ctl.int_msk.enc_err_msk = 0; + regs->reg_ctl.int_msk.vsrc_err_msk = 0; + regs->reg_ctl.int_msk.wdg_msk = 0; + regs->reg_ctl.int_msk.lkt_err_int_msk = 0; + regs->reg_ctl.int_msk.lkt_err_stop_msk = 0; + regs->reg_ctl.int_msk.lkt_force_stop_msk = 0; + regs->reg_ctl.int_msk.jslc_done_msk = 0; + regs->reg_ctl.int_msk.jbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.jbuf_lens_msk = 0; + regs->reg_ctl.int_msk.dvbm_err_msk = 0; + + /* reg006 INT_CLR is not set */ + /* reg007 INT_STA is read only */ + /* reg008 ~ reg0011 gap */ + regs->reg_ctl.enc_wdg.vs_load_thd = 0; + + /* reg015 DTRNS_MAP */ + regs->reg_ctl.dtrns_map.jpeg_bus_edin = 0; + regs->reg_ctl.dtrns_map.src_bus_edin = 0; + regs->reg_ctl.dtrns_map.meiw_bus_edin = 0; + regs->reg_ctl.dtrns_map.bsw_bus_edin = 7; + regs->reg_ctl.dtrns_map.lktw_bus_edin = 0; + regs->reg_ctl.dtrns_map.rec_nfbc_bus_edin = 0; + + regs->reg_ctl.dtrns_cfg.axi_brsp_cke = 0; + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET setup_vepu510_prep(HalVepu510RegSet *regs, MppEncPrepCfg *prep) +{ + H264eVepu510Frame *reg_frm = ®s->reg_frm; + VepuFmtCfg cfg; + MppFrameFormat fmt = prep->format; + MPP_RET ret = vepu5xx_set_fmt(&cfg, fmt); + RK_U32 hw_fmt = cfg.format; + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + /* do nothing when color format is not supported */ + if (ret) + return ret; + + reg_frm->common.enc_rsl.pic_wd8_m1 = MPP_ALIGN(prep->width, 16) / 8 - 1; + reg_frm->common.src_fill.pic_wfill = MPP_ALIGN(prep->width, 16) - prep->width; + reg_frm->common.enc_rsl.pic_hd8_m1 = MPP_ALIGN(prep->height, 16) / 8 - 1; + reg_frm->common.src_fill.pic_hfill = MPP_ALIGN(prep->height, 16) - prep->height; + + regs->reg_ctl.dtrns_map.src_bus_edin = cfg.src_endian; + + reg_frm->common.src_fmt.src_cfmt = hw_fmt; + reg_frm->common.src_fmt.alpha_swap = cfg.alpha_swap; + reg_frm->common.src_fmt.rbuv_swap = cfg.rbuv_swap; + reg_frm->common.src_fmt.out_fmt = (hw_fmt == VEPU5xx_FMT_YUV400) ? 0 : 1; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + mpp_err("Unsupported FBC format input.\n"); + + return MPP_ERR_VALUE; + } else if (prep->hor_stride) { + if (MPP_FRAME_FMT_IS_TILE(fmt)) { + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV400: + y_stride = prep->hor_stride * 4; + break; + case MPP_FMT_YUV420P: + case MPP_FMT_YUV420SP: + y_stride = prep->hor_stride * 4 * 3 / 2; + break; + case MPP_FMT_YUV422P: + case MPP_FMT_YUV422SP: + y_stride = prep->hor_stride * 4 * 2; + break; + case MPP_FMT_YUV444P: + case MPP_FMT_YUV444SP: + y_stride = prep->hor_stride * 4 * 3; + break; + default: + mpp_err("Unsupported input format 0x%08x, with TILE mask.\n", fmt); + return MPP_ERR_VALUE; + break; + } + } else { + y_stride = prep->hor_stride; + } + } else { + if (hw_fmt == VEPU5xx_FMT_BGRA8888 ) + y_stride = prep->width * 4; + else if (hw_fmt == VEPU5xx_FMT_BGR888 ) + y_stride = prep->width * 3; + else if (hw_fmt == VEPU5xx_FMT_BGR565 || + hw_fmt == VEPU5xx_FMT_YUYV422 || + hw_fmt == VEPU5xx_FMT_UYVY422) + y_stride = prep->width * 2; + else + y_stride = prep->width; + } + + switch (hw_fmt) { + case VEPU5xx_FMT_YUV444SP : { + c_stride = y_stride * 2; + } break; + case VEPU5xx_FMT_YUV422SP : + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV444P : { + c_stride = y_stride; + } break; + default : { + c_stride = y_stride / 2; + } break; + } + + if (hw_fmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = get_rgb2yuv_cfg(prep->range, prep->color); + + hal_h264e_dbg_flow("input color range %d colorspace %d", prep->range, prep->color); + + reg_frm->common.src_udfy.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + reg_frm->common.src_udfy.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + reg_frm->common.src_udfy.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + + reg_frm->common.src_udfu.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + reg_frm->common.src_udfu.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + reg_frm->common.src_udfu.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + + reg_frm->common.src_udfv.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + reg_frm->common.src_udfv.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + reg_frm->common.src_udfv.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + + reg_frm->common.src_udfo.csc_ofst_y = cfg_coeffs->_2y.offset; + reg_frm->common.src_udfo.csc_ofst_u = cfg_coeffs->_2u.offset; + reg_frm->common.src_udfo.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h264e_dbg_flow("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } else { + reg_frm->common.src_udfy.csc_wgt_b2y = cfg.weight[0]; + reg_frm->common.src_udfy.csc_wgt_g2y = cfg.weight[1]; + reg_frm->common.src_udfy.csc_wgt_r2y = cfg.weight[2]; + + reg_frm->common.src_udfu.csc_wgt_b2u = cfg.weight[3]; + reg_frm->common.src_udfu.csc_wgt_g2u = cfg.weight[4]; + reg_frm->common.src_udfu.csc_wgt_r2u = cfg.weight[5]; + + reg_frm->common.src_udfv.csc_wgt_b2v = cfg.weight[6]; + reg_frm->common.src_udfv.csc_wgt_g2v = cfg.weight[7]; + reg_frm->common.src_udfv.csc_wgt_r2v = cfg.weight[8]; + + reg_frm->common.src_udfo.csc_ofst_y = cfg.offset[0]; + reg_frm->common.src_udfo.csc_ofst_u = cfg.offset[1]; + reg_frm->common.src_udfo.csc_ofst_v = cfg.offset[2]; + } + + reg_frm->common.src_strd0.src_strd0 = y_stride; + reg_frm->common.src_strd1.src_strd1 = c_stride; + + reg_frm->common.src_proc.src_mirr = prep->mirroring > 0; + reg_frm->common.src_proc.src_rot = prep->rotation; + + if (MPP_FRAME_FMT_IS_TILE(fmt)) + reg_frm->common.src_proc.tile4x4_en = 1; + else + reg_frm->common.src_proc.tile4x4_en = 0; + + reg_frm->sli_cfg.mv_v_lmt_thd = 0; + reg_frm->sli_cfg.mv_v_lmt_en = 0; + + reg_frm->common.pic_ofst.pic_ofst_y = 0; + reg_frm->common.pic_ofst.pic_ofst_x = 0; + + hal_h264e_dbg_func("leave\n"); + + return ret; +} + +static MPP_RET vepu510_h264e_save_pass1_patch(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ctx) +{ + H264eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + reg_frm->common.enc_pic.cur_frm_ref = 1; + reg_frm->common.rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + reg_frm->common.rfpw_b_addr = reg_frm->common.rfpw_h_addr; + reg_frm->common.enc_pic.rec_fbc_dis = 1; + + mpp_dev_multi_offset_update(ctx->offsets, 164, 0); + + /* NOTE: disable split to avoid lowdelay slice output */ + reg_frm->common.sli_splt.sli_splt = 0; + reg_frm->common.enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu510_h264e_use_pass1_patch(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ctx) +{ + MppEncPrepCfg *prep = &ctx->cfg->prep; + H264eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 fd_in = mpp_buffer_get_fd(ctx->buf_pass1); + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + reg_frm->common.src_fmt.alpha_swap = 0; + reg_frm->common.src_fmt.rbuv_swap = 0; + reg_frm->common.src_fmt.out_fmt = 1; + reg_frm->common.src_fmt.src_rcne = 1; + y_stride = MPP_ALIGN(prep->width, 16); + c_stride = y_stride; + + reg_frm->common.src_strd0.src_strd0 = y_stride; + reg_frm->common.src_strd1.src_strd1 = 3 * c_stride; + + reg_frm->common.src_proc.src_mirr = 0; + reg_frm->common.src_proc.src_rot = 0; + + reg_frm->common.pic_ofst.pic_ofst_y = 0; + reg_frm->common.pic_ofst.pic_ofst_x = 0; + + + reg_frm->common.adr_src0 = fd_in; + reg_frm->common.adr_src1 = fd_in; + reg_frm->common.adr_src2 = fd_in; + + mpp_dev_multi_offset_update(ctx->offsets, 161, 2 * y_stride); + + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + +static void setup_vepu510_codec(HalVepu510RegSet *regs, H264eSps *sps, + H264ePps *pps, H264eSlice *slice) +{ + H264eVepu510Frame *reg_frm = ®s->reg_frm; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.enc_pic.enc_stnd = 0; + reg_frm->common.enc_pic.cur_frm_ref = slice->nal_reference_idc > 0; + reg_frm->common.enc_pic.bs_scp = 1; + + reg_frm->synt_nal.nal_ref_idc = slice->nal_reference_idc; + reg_frm->synt_nal.nal_unit_type = slice->nalu_type; + + reg_frm->synt_sps.max_fnum = sps->log2_max_frame_num_minus4; + reg_frm->synt_sps.drct_8x8 = sps->direct8x8_inference; + reg_frm->synt_sps.mpoc_lm4 = sps->log2_max_poc_lsb_minus4; + reg_frm->synt_sps.poc_type = sps->pic_order_cnt_type; + + reg_frm->synt_pps.etpy_mode = pps->entropy_coding_mode; + reg_frm->synt_pps.trns_8x8 = pps->transform_8x8_mode; + reg_frm->synt_pps.csip_flag = pps->constrained_intra_pred; + reg_frm->synt_pps.num_ref0_idx = pps->num_ref_idx_l0_default_active - 1; + reg_frm->synt_pps.num_ref1_idx = pps->num_ref_idx_l1_default_active - 1; + reg_frm->synt_pps.pic_init_qp = pps->pic_init_qp; + reg_frm->synt_pps.cb_ofst = pps->chroma_qp_index_offset; + reg_frm->synt_pps.cr_ofst = pps->second_chroma_qp_index_offset; + reg_frm->synt_pps.dbf_cp_flg = pps->deblocking_filter_control; + + reg_frm->synt_sli0.sli_type = (slice->slice_type == H264_I_SLICE) ? (2) : (0); + reg_frm->synt_sli0.pps_id = slice->pic_parameter_set_id; + reg_frm->synt_sli0.drct_smvp = 0; + reg_frm->synt_sli0.num_ref_ovrd = slice->num_ref_idx_override; + reg_frm->synt_sli0.cbc_init_idc = slice->cabac_init_idc; + reg_frm->synt_sli0.frm_num = slice->frame_num; + + reg_frm->synt_sli1.idr_pid = (slice->slice_type == H264_I_SLICE) ? slice->idr_pic_id : (RK_U32)(-1); + reg_frm->synt_sli1.poc_lsb = slice->pic_order_cnt_lsb; + + + reg_frm->synt_sli2.dis_dblk_idc = slice->disable_deblocking_filter_idc; + reg_frm->synt_sli2.sli_alph_ofst = slice->slice_alpha_c0_offset_div2; + + h264e_reorder_rd_rewind(slice->reorder); + { /* reorder process */ + H264eRplmo rplmo; + MPP_RET ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + if (MPP_OK == ret) { + reg_frm->synt_sli2.ref_list0_rodr = 1; + reg_frm->synt_sli2.rodr_pic_idx = rplmo.modification_of_pic_nums_idc; + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + reg_frm->synt_sli2.rodr_pic_num = rplmo.abs_diff_pic_num_minus1; + } break; + case 2 : { + reg_frm->synt_sli2.rodr_pic_num = rplmo.long_term_pic_idx; + } break; + default : { + mpp_err_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + } else { + // slice->ref_pic_list_modification_flag; + reg_frm->synt_sli2.ref_list0_rodr = 0; + reg_frm->synt_sli2.rodr_pic_idx = 0; + reg_frm->synt_sli2.rodr_pic_num = 0; + } + } + + /* clear all mmco arg first */ + reg_frm->synt_refm0.nopp_flg = 0; + reg_frm->synt_refm0.ltrf_flg = 0; + reg_frm->synt_refm0.arpm_flg = 0; + reg_frm->synt_refm0.mmco4_pre = 0; + reg_frm->synt_refm0.mmco_type0 = 0; + reg_frm->synt_refm0.mmco_parm0 = 0; + reg_frm->synt_refm0.mmco_type1 = 0; + reg_frm->synt_refm1.mmco_parm1 = 0; + reg_frm->synt_refm0.mmco_type2 = 0; + reg_frm->synt_refm1.mmco_parm2 = 0; + reg_frm->synt_refm2.long_term_frame_idx0 = 0; + reg_frm->synt_refm2.long_term_frame_idx1 = 0; + reg_frm->synt_refm2.long_term_frame_idx2 = 0; + + h264e_marking_rd_rewind(slice->marking); + + /* only update used parameter */ + if (slice->slice_type == H264_I_SLICE) { + reg_frm->synt_refm0.nopp_flg = slice->no_output_of_prior_pics; + reg_frm->synt_refm0.ltrf_flg = slice->long_term_reference_flag; + } else { + if (!h264e_marking_is_empty(slice->marking)) { + H264eMmco mmco; + + reg_frm->synt_refm0.arpm_flg = 1; + + /* max 3 mmco */ + do { + RK_S32 type = 0; + RK_S32 param_0 = 0; + RK_S32 param_1 = 0; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + reg_frm->synt_refm0.mmco_type0 = type; + reg_frm->synt_refm0.mmco_parm0 = param_0; + reg_frm->synt_refm2.long_term_frame_idx0 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + reg_frm->synt_refm0.mmco_type1 = type; + reg_frm->synt_refm1.mmco_parm1 = param_0; + reg_frm->synt_refm2.long_term_frame_idx1 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + reg_frm->synt_refm0.mmco_type2 = type; + reg_frm->synt_refm1.mmco_parm2 = param_0; + reg_frm->synt_refm2.long_term_frame_idx2 = param_1; + } while (0); + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu510_rdo_pred(HalH264eVepu510Ctx *ctx, H264eSps *sps, + H264ePps *pps, H264eSlice *slice) +{ + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Frame *reg_frm = ®s->reg_frm; + RK_U32 is_ipc_scene = (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC); + + hal_h264e_dbg_func("enter\n"); + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = (is_ipc_scene != 0) ? 9 : 6; + } + + reg_frm->rdo_cfg.rect_size = (sps->profile_idc == H264_PROFILE_BASELINE && + sps->level_idc <= H264_LEVEL_3_0) ? 1 : 0; + reg_frm->rdo_cfg.vlc_lmt = (sps->profile_idc < H264_PROFILE_MAIN) && + !pps->entropy_coding_mode; + reg_frm->rdo_cfg.chrm_spcl = 1; + reg_frm->rdo_cfg.ccwa_e = 1; + reg_frm->rdo_cfg.scl_lst_sel = pps->pic_scaling_matrix_present; + reg_frm->rdo_cfg.atf_e = ctx->cfg->tune.anti_flicker_str > 0; + reg_frm->rdo_cfg.atr_e = ctx->cfg->tune.atr_str_i > 0; + reg_frm->rdo_cfg.atr_mult_sel_e = 1; + reg_frm->iprd_csts.rdo_mark_mode = 0; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu510_rc_base(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ctx, EncRcTask *rc_task) +{ + H264eSps *sps = ctx->sps; + H264eSlice *slice = ctx->slice; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + EncRcTaskInfo *rc_info = &rc_task->info; + H264eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 mb_w = sps->pic_width_in_mbs; + RK_S32 mb_h = sps->pic_height_in_mbs; + RK_U32 qp_target = rc_info->quality_target; + RK_U32 qp_min = rc_info->quality_min; + RK_U32 qp_max = rc_info->quality_max; + RK_U32 qpmap_mode = 1; + RK_S32 mb_target_bits_mul_16 = (rc_info->bit_target << 4) / (mb_w * mb_h); + RK_S32 mb_target_bits; + RK_S32 negative_bits_thd; + RK_S32 positive_bits_thd; + + hal_h264e_dbg_rc("bittarget %d qp [%d %d %d]\n", rc_info->bit_target, + qp_min, qp_target, qp_max); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_rc_roi.roi_qthd0.qpmin_area0 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area0 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area1 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area1 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area2 = qp_min; + + regs->reg_rc_roi.roi_qthd1.qpmax_area2 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area3 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area3 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area4 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area4 = qp_max; + + regs->reg_rc_roi.roi_qthd2.qpmin_area5 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area5 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area6 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area6 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area7 = qp_min; + + regs->reg_rc_roi.roi_qthd3.qpmax_area7 = qp_max; + regs->reg_rc_roi.roi_qthd3.qpmap_mode = qpmap_mode; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + reg_frm->common.enc_pic.pic_qp = rc_info->quality_target; + reg_frm->common.rc_qp.rc_max_qp = rc_info->quality_target; + reg_frm->common.rc_qp.rc_min_qp = rc_info->quality_target; + + return; + } + + if (mb_target_bits_mul_16 >= 0x100000) + mb_target_bits_mul_16 = 0x50000; + + mb_target_bits = (mb_target_bits_mul_16 * mb_w) >> 4; + negative_bits_thd = 0 - 5 * mb_target_bits / 16; + positive_bits_thd = 5 * mb_target_bits / 16; + + reg_frm->common.enc_pic.pic_qp = qp_target; + + reg_frm->common.rc_cfg.rc_en = 1; + reg_frm->common.rc_cfg.aq_en = 1; + reg_frm->common.rc_cfg.rc_ctu_num = mb_w; + + reg_frm->common.rc_qp.rc_max_qp = qp_max; + reg_frm->common.rc_qp.rc_min_qp = qp_min; + reg_frm->common.rc_tgt.ctu_ebit = mb_target_bits_mul_16; + + if (rc->rc_mode == MPP_ENC_RC_MODE_SMTRC || rc->rc_mode == MPP_ENC_RC_MODE_SE) { + reg_frm->common.rc_qp.rc_qp_range = 0; + } else { + reg_frm->common.rc_qp.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? + hw->qp_delta_row_i : hw->qp_delta_row; + } + + { + /* fixed frame level QP */ + RK_S32 fqp_min, fqp_max; + + if (slice->slice_type == H264_I_SLICE) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 1) && (fqp_max <= 51)) { + reg_frm->common.enc_pic.pic_qp = fqp_min; + reg_frm->common.rc_qp.rc_qp_range = 0; + } + } + + regs->reg_rc_roi.rc_adj0.qp_adj0 = -2; + regs->reg_rc_roi.rc_adj0.qp_adj1 = -1; + regs->reg_rc_roi.rc_adj0.qp_adj2 = 0; + regs->reg_rc_roi.rc_adj0.qp_adj3 = 1; + regs->reg_rc_roi.rc_adj0.qp_adj4 = 2; + regs->reg_rc_roi.rc_adj1.qp_adj5 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj6 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj7 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj8 = 0; + + regs->reg_rc_roi.rc_dthd_0_8[0] = 4 * negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[1] = negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[2] = positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[3] = 4 * positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[4] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[5] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[6] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[7] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[8] = 0x7FFFFFFF; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu510_io_buf(HalVepu510RegSet *regs, MppDevRegOffCfgs *offsets, + HalEncTask *task) +{ + MppFrame frm = task->frame; + MppPacket pkt = task->packet; + MppBuffer buf_in = mpp_frame_get_buffer(frm); + MppBuffer buf_out = task->output; + MppFrameFormat fmt = mpp_frame_get_fmt(frm); + H264eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 hor_stride = mpp_frame_get_hor_stride(frm); + RK_S32 ver_stride = mpp_frame_get_ver_stride(frm); + RK_S32 fd_in = mpp_buffer_get_fd(buf_in); + RK_U32 off_in[2] = {0}; + RK_U32 off_out = mpp_packet_get_length(pkt); + size_t siz_out = mpp_buffer_get_size(buf_out); + RK_S32 fd_out = mpp_buffer_get_fd(buf_out); + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.adr_src0 = fd_in; + reg_frm->common.adr_src1 = fd_in; + reg_frm->common.adr_src2 = fd_in; + + reg_frm->common.bsbt_addr = fd_out; + reg_frm->common.bsbb_addr = fd_out; + reg_frm->common.adr_bsbs = fd_out; + reg_frm->common.bsbr_addr = fd_out; + + reg_frm->common.rfpt_h_addr = 0xffffffff; + reg_frm->common.rfpb_h_addr = 0; + reg_frm->common.rfpt_b_addr = 0xffffffff; + reg_frm->common.adr_rfpb_b = 0; + + if (MPP_FRAME_FMT_IS_YUV(fmt)) { + VepuFmtCfg cfg; + + vepu5xx_set_fmt(&cfg, fmt); + switch (cfg.format) { + case VEPU5xx_FMT_BGRA8888 : + case VEPU5xx_FMT_BGR888 : + case VEPU5xx_FMT_BGR565 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV422SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV422P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 3 / 2; + } break; + case VEPU5xx_FMT_YUV420P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 5 / 4; + } break; + case VEPU5xx_FMT_YUV400 : + case VEPU5xx_FMT_YUYV422 : + case VEPU5xx_FMT_UYVY422 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 2; + } break; + default : { + off_in[0] = 0; + off_in[1] = 0; + } break; + } + } + + mpp_dev_multi_offset_update(offsets, 161, off_in[0]); + mpp_dev_multi_offset_update(offsets, 162, off_in[1]); + mpp_dev_multi_offset_update(offsets, 172, siz_out); + mpp_dev_multi_offset_update(offsets, 174, off_out); + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET vepu510_h264_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h) +{ + Vepu510RoiH264BsCfg *ptr = (Vepu510RoiH264BsCfg *)buf; + RK_S32 mb_w = MPP_ALIGN(w, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(h, 16) / 16; + RK_S32 stride_h = MPP_ALIGN(mb_w, 4); + Vepu510RoiH264BsCfg cfg; + MPP_RET ret = MPP_NOK; + + if (NULL == buf || NULL == region) { + mpp_err_f("invalid buf %p roi %p\n", buf, region); + goto DONE; + } + + RK_S32 roi_width = (region->w + 15) / 16; + RK_S32 roi_height = (region->h + 15) / 16; + RK_S32 pos_x_init = region->x / 16; + RK_S32 pos_y_init = region->y / 16; + RK_S32 pos_x_end = pos_x_init + roi_width; + RK_S32 pos_y_end = pos_y_init + roi_height; + RK_S32 x, y; + + pos_x_end = MPP_MIN(pos_x_end, mb_w); + pos_y_end = MPP_MIN(pos_y_end, mb_h); + pos_x_init = MPP_MAX(pos_x_init, 0); + pos_y_init = MPP_MAX(pos_y_init, 0); + + mpp_assert(pos_x_end > pos_x_init); + mpp_assert(pos_y_end > pos_y_init); + + cfg.force_intra = 1; + + ptr += pos_y_init * stride_h + pos_x_init; + roi_width = pos_x_end - pos_x_init; + roi_height = pos_y_end - pos_y_init; + + for (y = 0; y < roi_height; y++) { + Vepu510RoiH264BsCfg *dst = ptr; + + for (x = 0; x < roi_width; x++, dst++) + memcpy(dst, &cfg, sizeof(cfg)); + + ptr += stride_h; + } +DONE: + return ret; +} + +static MPP_RET setup_vepu510_intra_refresh(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ctx, RK_U32 refresh_idx) +{ + MPP_RET ret = MPP_OK; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 w = mb_w * 16; + RK_U32 h = mb_h * 16; + MppEncROIRegion *region = NULL; + H264eVepu510Frame *reg_frm = ®s->reg_frm; + RK_U32 refresh_num = ctx->cfg->rc.refresh_num; + RK_U32 stride_h = MPP_ALIGN(mb_w, 4); + RK_U32 stride_v = MPP_ALIGN(mb_h, 4); + RK_U32 roir_buf_size = stride_h * stride_v * 8; + RK_U32 i = 0; + + hal_h264e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en) { + ret = MPP_ERR_VALUE; + goto RET; + } + + if (NULL == ctx->roir_buf) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + mpp_buffer_get(ctx->roi_grp, &ctx->roir_buf, roir_buf_size); + ctx->roir_buf_size = roir_buf_size; + } + + mpp_assert(ctx->roir_buf); + void *base_cfg_buf = mpp_buffer_get_ptr(ctx->roir_buf); + Vepu510RoiH264BsCfg base_cfg; + Vepu510RoiH264BsCfg *base_cfg_ptr = (Vepu510RoiH264BsCfg *)base_cfg_buf; + + base_cfg.force_intra = 0; + base_cfg.qp_adj_en = 1; + + for (i = 0; i < stride_h * stride_v; i++, base_cfg_ptr++) + memcpy(base_cfg_ptr, &base_cfg, sizeof(base_cfg)); + + region = mpp_calloc(MppEncROIRegion, 1); + + if (NULL == region) { + mpp_err_f("Failed to calloc for MppEncROIRegion !\n"); + ret = MPP_ERR_MALLOC; + } + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + region->x = 0; + region->w = w; + if (refresh_idx > 0) { + region->y = refresh_idx * 16 * refresh_num - 32; + region->h = 16 * refresh_num + 32; + } else { + region->y = refresh_idx * 16 * refresh_num; + region->h = 16 * refresh_num; + } + reg_frm->common.me_rnge.cime_srch_uph = 1; + } else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) { + region->y = 0; + region->h = h; + if (refresh_idx > 0) { + region->x = refresh_idx * 16 * refresh_num - 32; + region->w = 16 * refresh_num + 32; + } else { + region->x = refresh_idx * 16 * refresh_num; + region->w = 16 * refresh_num; + } + reg_frm->common.me_rnge.cime_srch_dwnh = 1; + } + + region->intra = 1; + region->quality = -ctx->cfg->rc.qp_delta_ip; + + region->area_map_en = 1; + region->qp_area_idx = 1; + region->abs_qp_en = 0; + + vepu510_h264_set_one_roi(base_cfg_buf, region, w, h); + mpp_free(region); +RET: + hal_h264e_dbg_func("leave, ret %d\n", ret); + return ret; +} + +static void setup_vepu510_recn_refr(HalH264eVepu510Ctx *ctx, HalVepu510RegSet *regs) +{ + + H264eVepu510Frame *reg_frm = ®s->reg_frm; + H264eFrmInfo *frms = ctx->frms; + HalBufs bufs = ctx->hw_recn; + RK_S32 fbc_hdr_size = ctx->pixel_buf_fbc_hdr_size; + + HalBuf *curr = hal_bufs_get_buf(bufs, frms->curr_idx); + HalBuf *refr = hal_bufs_get_buf(bufs, frms->refr_idx); + + hal_h264e_dbg_func("enter\n"); + + if (curr && curr->cnt) { + MppBuffer buf_pixel = curr->buf[0]; + MppBuffer buf_thumb = curr->buf[1]; + MppBuffer buf_smear = curr->buf[2]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + reg_frm->common.rfpw_h_addr = fd; + reg_frm->common.rfpw_b_addr = fd; + reg_frm->common.dspw_addr = mpp_buffer_get_fd(buf_thumb); + reg_frm->common.adr_smear_wr = mpp_buffer_get_fd(buf_smear); + } + + if (refr && refr->cnt) { + MppBuffer buf_pixel = refr->buf[0]; + MppBuffer buf_thumb = refr->buf[1]; + MppBuffer buf_smear = refr->buf[2]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + reg_frm->common.rfpr_h_addr = fd; + reg_frm->common.rfpr_b_addr = fd; + reg_frm->common.dspr_addr = mpp_buffer_get_fd(buf_thumb); + reg_frm->common.adr_smear_rd = mpp_buffer_get_fd(buf_smear); + } + mpp_dev_multi_offset_update(ctx->offsets, 164, fbc_hdr_size); + mpp_dev_multi_offset_update(ctx->offsets, 166, fbc_hdr_size); + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu510_split(HalVepu510RegSet *regs, MppEncCfgSet *enc_cfg) +{ + H264eVepu510Frame *reg_frm = ®s->reg_frm; + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h264e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + reg_frm->common.sli_splt.sli_splt = 0; + reg_frm->common.sli_splt.sli_splt_mode = 0; + reg_frm->common.sli_splt.sli_splt_cpst = 0; + reg_frm->common.sli_splt.sli_max_num_m1 = 0; + reg_frm->common.sli_splt.sli_flsh = 0; + reg_frm->common.sli_cnum.sli_splt_cnum_m1 = 0; + + reg_frm->common.sli_byte.sli_splt_byte = 0; + reg_frm->common.enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + reg_frm->common.sli_splt.sli_splt = 1; + reg_frm->common.sli_splt.sli_splt_mode = 0; + reg_frm->common.sli_splt.sli_splt_cpst = 0; + reg_frm->common.sli_splt.sli_max_num_m1 = 500; + reg_frm->common.sli_splt.sli_flsh = 1; + reg_frm->common.sli_cnum.sli_splt_cnum_m1 = 0; + + reg_frm->common.sli_byte.sli_splt_byte = cfg->split_arg; + reg_frm->common.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = reg_frm->common.enc_pic.slen_fifo; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + RK_U32 mb_w = MPP_ALIGN(enc_cfg->prep.width, 16) / 16; + RK_U32 mb_h = MPP_ALIGN(enc_cfg->prep.height, 16) / 16; + RK_U32 slice_num = (mb_w * mb_h + cfg->split_arg - 1) / cfg->split_arg; + + reg_frm->common.sli_splt.sli_splt = 1; + reg_frm->common.sli_splt.sli_splt_mode = 1; + reg_frm->common.sli_splt.sli_splt_cpst = 0; + reg_frm->common.sli_splt.sli_max_num_m1 = 500; + reg_frm->common.sli_splt.sli_flsh = 1; + reg_frm->common.sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + reg_frm->common.sli_byte.sli_splt_byte = 0; + reg_frm->common.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + if ((cfg->split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) || + (regs->reg_frm.common.enc_pic.slen_fifo && (slice_num > VEPU510_SLICE_FIFO_LEN))) + regs->reg_ctl.int_en.vslc_done_en = 1; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu510_me(HalH264eVepu510Ctx *ctx) +{ + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Frame *reg_frm = ®s->reg_frm; + H264eVepu510Param *reg_param = ®s->reg_param; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.me_rnge.cime_srch_dwnh = 15; + reg_frm->common.me_rnge.cime_srch_uph = 15; + reg_frm->common.me_rnge.cime_srch_rgtw = 12; + reg_frm->common.me_rnge.cime_srch_lftw = 12; + reg_frm->common.me_cfg.rme_srch_h = 3; + reg_frm->common.me_cfg.rme_srch_v = 3; + + reg_frm->common.me_cfg.srgn_max_num = 54; + reg_frm->common.me_cfg.cime_dist_thre = 1024; + reg_frm->common.me_cfg.rme_dis = 0; + reg_frm->common.me_cfg.fme_dis = 0; + reg_frm->common.me_rnge.dlt_frm_num = 0x0; + reg_frm->common.me_cach.cime_zero_thre = 64; + + /* CIME: 0x1760 - 0x176C */ + reg_param->me_sqi_comb.cime_pmv_num = 1; + reg_param->me_sqi_comb.cime_fuse = 1; + reg_param->me_sqi_comb.itp_mode = 0; + reg_param->me_sqi_comb.move_lambda = 0; + reg_param->me_sqi_comb.rime_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prelvl_en = 0; + reg_param->me_sqi_comb.rime_prersu_en = 0; + reg_param->cime_mvd_th_comb.cime_mvd_th0 = 16; + reg_param->cime_mvd_th_comb.cime_mvd_th1 = 48; + reg_param->cime_mvd_th_comb.cime_mvd_th2 = 80; + reg_param->cime_madp_th_comb.cime_madp_th = 16; + reg_param->cime_multi_comb.cime_multi0 = 8; + reg_param->cime_multi_comb.cime_multi1 = 12; + reg_param->cime_multi_comb.cime_multi2 = 16; + reg_param->cime_multi_comb.cime_multi3 = 20; + + /* RFME: 0x1770 - 0x1778 */ + reg_param->rime_mvd_th_comb.rime_mvd_th0 = 1; + reg_param->rime_mvd_th_comb.rime_mvd_th1 = 2; + reg_param->rime_mvd_th_comb.fme_madp_th = 0; + reg_param->rime_madp_th_comb.rime_madp_th0 = 8; + reg_param->rime_madp_th_comb.rime_madp_th1 = 16; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 8; + reg_param->rime_multi_comb.rime_multi2 = 12; + reg_param->cmv_st_th_comb.cmv_th0 = 64; + reg_param->cmv_st_th_comb.cmv_th1 = 96; + reg_param->cmv_st_th_comb.cmv_th2 = 128; + + if (sm != MPP_ENC_SCENE_MODE_IPC) { + /* disable subjective optimization */ + reg_param->cime_madp_th_comb.cime_madp_th = 0; + reg_param->rime_madp_th_comb.rime_madp_th0 = 0; + reg_param->rime_madp_th_comb.rime_madp_th1 = 0; + reg_param->cime_multi_comb.cime_multi0 = 4; + reg_param->cime_multi_comb.cime_multi1 = 4; + reg_param->cime_multi_comb.cime_multi2 = 4; + reg_param->cime_multi_comb.cime_multi3 = 4; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 4; + reg_param->rime_multi_comb.rime_multi2 = 4; + } + + /* 0x1064 */ + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + /* 0x1068 */ + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + /* 0x106C */ + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; + + hal_h264e_dbg_func("leave\n"); +} + +#define H264E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) + +static RK_U32 h264e_lambda_default[60] = { + 0x00000005, 0x00000006, 0x00000007, 0x00000009, + 0x0000000b, 0x0000000e, 0x00000012, 0x00000016, + 0x0000001c, 0x00000024, 0x0000002d, 0x00000039, + 0x00000048, 0x0000005b, 0x00000073, 0x00000091, + 0x000000b6, 0x000000e6, 0x00000122, 0x0000016d, + 0x000001cc, 0x00000244, 0x000002db, 0x00000399, + 0x00000489, 0x000005b6, 0x00000733, 0x00000912, + 0x00000b6d, 0x00000e66, 0x00001224, 0x000016db, + 0x00001ccc, 0x00002449, 0x00002db7, 0x00003999, + 0x00004892, 0x00005b6f, 0x00007333, 0x00009124, + 0x0000b6de, 0x0000e666, 0x00012249, 0x00016dbc, + 0x0001cccc, 0x00024492, 0x0002db79, 0x00039999, + 0x00048924, 0x0005b6f2, 0x00073333, 0x00091249, + 0x000b6de5, 0x000e6666, 0x00122492, 0x0016dbcb, + 0x001ccccc, 0x00244924, 0x002db796, 0x00399998, +}; + +static RK_U32 h264e_lambda_cvr[60] = { + 0x00000009, 0x0000000b, 0x0000000e, 0x00000011, + 0x00000016, 0x0000001b, 0x00000022, 0x0000002b, + 0x00000036, 0x00000045, 0x00000056, 0x0000006d, + 0x00000089, 0x000000ad, 0x000000da, 0x00000112, + 0x00000159, 0x000001b3, 0x00000224, 0x000002b3, + 0x00000366, 0x00000449, 0x00000566, 0x000006cd, + 0x00000891, 0x00000acb, 0x00000d9a, 0x000013c1, + 0x000018e4, 0x00001f5c, 0x00002783, 0x000031c8, + 0x00003eb8, 0x00004f06, 0x00006390, 0x00008e14, + 0x0000b302, 0x0000e18a, 0x00011c29, 0x00016605, + 0x0001c313, 0x00027ae1, 0x00031fe6, 0x0003efcf, + 0x0004f5c3, 0x0006e785, 0x0008b2ef, 0x000af5c3, + 0x000f1e7a, 0x00130c7f, 0x00180000, 0x001e3cf4, + 0x002618fe, 0x00300000, 0x003c79e8, 0x004c31fc, + 0x00600000, 0x0078f3d0, 0x009863f8, 0x0c000000, +}; + +static void +setup_vepu510_l2(HalH264eVepu510Ctx *ctx, MppEncHwCfg *hw) +{ + HalVepu510RegSet *regs = ctx->regs_set; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + RK_S32 lambda_idx = ctx->cfg->tune.lambda_idx_i; //TODO: lambda_idx_p + + hal_h264e_dbg_func("enter\n"); + + if (sm == MPP_ENC_SCENE_MODE_IPC) { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_default[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } else { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_cvr[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } + + if (hw->qbias_en) { + regs->reg_param.qnt_bias_comb.qnt_f_bias_i = hw->qbias_i; + regs->reg_param.qnt_bias_comb.qnt_f_bias_p = hw->qbias_p; + } else { + regs->reg_param.qnt_bias_comb.qnt_f_bias_i = 683; + regs->reg_param.qnt_bias_comb.qnt_f_bias_p = 341; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu510_ext_line_buf(HalVepu510RegSet *regs, HalH264eVepu510Ctx *ctx) +{ + H264eVepu510Frame *reg_frm = ®s->reg_frm; + MppDevRcbInfoCfg rcb_cfg; + RK_S32 offset = 0; + RK_S32 fd; + + if (!ctx->ext_line_buf) { + reg_frm->common.ebufb_addr = 0; + reg_frm->common.ebufb_addr = 0; + return; + } + + fd = mpp_buffer_get_fd(ctx->ext_line_buf); + offset = ctx->ext_line_buf_size; + + reg_frm->common.ebuft_addr = fd; + reg_frm->common.ebufb_addr = fd; + + mpp_dev_multi_offset_update(ctx->offsets, 178, offset); + + /* rcb info for sram */ + rcb_cfg.reg_idx = 179; + rcb_cfg.size = offset; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); + + rcb_cfg.reg_idx = 178; + rcb_cfg.size = 0; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); +} + +static MPP_RET setup_vepu510_dual_core(HalH264eVepu510Ctx *ctx, H264SliceType slice_type, + RK_S32 curr_slot, RK_S32 refr_slot) +{ + H264eVepu510Frame *reg_frm = &ctx->regs_set->reg_frm; + RK_U32 dchs_ofst = 9; + RK_U32 dchs_rxe = 1; + RK_U32 dchs_dly = 0; + RK_U32 dchs_txe = 1; + RK_U32 rxid = 0; + + if (ctx->task_cnt == 1) + return MPP_OK; + + if (curr_slot < 0 || curr_slot >= H264E_MAX_REFS_CNT || refr_slot < 0 || refr_slot >= H264E_MAX_REFS_CNT) { + mpp_loge_f("dual core setup failed! invalid frame slot index. curr_slot:%d, refr_slot:%d", + curr_slot, refr_slot); + return MPP_ERR_UNKNOW; + } + + if (slice_type == H264_I_SLICE) { + ctx->curr_idx = 0; + ctx->prev_idx = 0; + dchs_rxe = 0; + rxid = 0; + } else { + rxid = ctx->slot_to_dchs_txid[refr_slot]; + } + + if (!reg_frm->common.enc_pic.cur_frm_ref) + dchs_txe = 0; + + ctx->slot_to_dchs_txid[curr_slot] = ctx->curr_idx; + + reg_frm->common.dual_core.dchs_txid = ctx->curr_idx; + reg_frm->common.dual_core.dchs_rxid = rxid; + reg_frm->common.dual_core.dchs_txe = dchs_txe; + reg_frm->common.dual_core.dchs_rxe = dchs_rxe; + reg_frm->common.dual_core.dchs_ofst = dchs_ofst; + reg_frm->common.dual_core.dchs_dly = dchs_dly; + + ctx->prev_idx = ctx->curr_idx++; + if (ctx->curr_idx > 3) + ctx->curr_idx = 0; + + return MPP_OK; +} + +static void setup_vepu510_aq(HalH264eVepu510Ctx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncHwCfg *hw = &cfg->hw; + Vepu510RcRoi *s = &ctx->regs_set->reg_rc_roi; + RK_S32 *aq_step, *aq_thd; + RK_U8 i; + + if (ctx->slice->slice_type == H264_I_SLICE) { + aq_thd = (RK_S32 *)&hw->aq_thrd_i[0]; + aq_step = &hw->aq_step_i[0]; + } else { + aq_thd = (RK_S32 *)&hw->aq_thrd_p[0]; + aq_step = &hw->aq_step_p[0]; + } + + for (i = 0; i < 16; i++) + s->aq_tthd[i] = aq_thd[i] & 0xff; + + s->aq_stp0.aq_stp_s0 = aq_step[0] & 0x1f; + s->aq_stp0.aq_stp_0t1 = aq_step[1] & 0x1f; + s->aq_stp0.aq_stp_1t2 = aq_step[2] & 0x1f; + s->aq_stp0.aq_stp_2t3 = aq_step[3] & 0x1f; + s->aq_stp0.aq_stp_3t4 = aq_step[4] & 0x1f; + s->aq_stp0.aq_stp_4t5 = aq_step[5] & 0x1f; + s->aq_stp1.aq_stp_5t6 = aq_step[6] & 0x1f; + s->aq_stp1.aq_stp_6t7 = aq_step[7] & 0x1f; + s->aq_stp1.aq_stp_7t8 = 0; + s->aq_stp1.aq_stp_8t9 = aq_step[8] & 0x1f; + s->aq_stp1.aq_stp_9t10 = aq_step[9] & 0x1f; + s->aq_stp1.aq_stp_10t11 = aq_step[10] & 0x1f; + s->aq_stp2.aq_stp_11t12 = aq_step[11] & 0x1f; + s->aq_stp2.aq_stp_12t13 = aq_step[12] & 0x1f; + s->aq_stp2.aq_stp_13t14 = aq_step[13] & 0x1f; + s->aq_stp2.aq_stp_14t15 = aq_step[14] & 0x1f; + s->aq_stp2.aq_stp_b15 = aq_step[15] & 0x1f; +} + +static void setup_vepu510_anti_stripe(HalH264eVepu510Ctx *ctx) +{ + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Param *s = ®s->reg_param; + RK_S32 str = ctx->cfg->tune.atl_str; + + s->iprd_tthdy4_0.iprd_tthdy4_0 = 1; + s->iprd_tthdy4_0.iprd_tthdy4_1 = 3; + s->iprd_tthdy4_1.iprd_tthdy4_2 = 6; + s->iprd_tthdy4_1.iprd_tthdy4_3 = 8; + s->iprd_tthdc8_0.iprd_tthdc8_0 = 1; + s->iprd_tthdc8_0.iprd_tthdc8_1 = 3; + s->iprd_tthdc8_1.iprd_tthdc8_2 = 6; + s->iprd_tthdc8_1.iprd_tthdc8_3 = 8; + s->iprd_tthdy8_0.iprd_tthdy8_0 = 1; + s->iprd_tthdy8_0.iprd_tthdy8_1 = 3; + s->iprd_tthdy8_1.iprd_tthdy8_2 = 6; + s->iprd_tthdy8_1.iprd_tthdy8_3 = 8; + + if (ctx->cfg->tune.scene_mode != MPP_ENC_SCENE_MODE_IPC) + s->iprd_tthd_ul.iprd_tthd_ul = 4095; /* disable anti-stripe */ + else + s->iprd_tthd_ul.iprd_tthd_ul = (str != 0) ? 4 : 255; + + s->iprd_wgty8.iprd_wgty8_0 = (str != 0) ? 22 : 16; + s->iprd_wgty8.iprd_wgty8_1 = (str != 0) ? 23 : 16; + s->iprd_wgty8.iprd_wgty8_2 = (str != 0) ? 20 : 16; + s->iprd_wgty8.iprd_wgty8_3 = (str != 0) ? 22 : 16; + s->iprd_wgty4.iprd_wgty4_0 = (str != 0) ? 22 : 16; + s->iprd_wgty4.iprd_wgty4_1 = (str != 0) ? 26 : 16; + s->iprd_wgty4.iprd_wgty4_2 = (str != 0) ? 20 : 16; + s->iprd_wgty4.iprd_wgty4_3 = (str != 0) ? 22 : 16; + s->iprd_wgty16.iprd_wgty16_0 = 22; + s->iprd_wgty16.iprd_wgty16_1 = 26; + s->iprd_wgty16.iprd_wgty16_2 = 20; + s->iprd_wgty16.iprd_wgty16_3 = 22; + s->iprd_wgtc8.iprd_wgtc8_0 = 18; + s->iprd_wgtc8.iprd_wgtc8_1 = 21; + s->iprd_wgtc8.iprd_wgtc8_2 = 20; + s->iprd_wgtc8.iprd_wgtc8_3 = 19; +} + +static void setup_vepu510_anti_ringing(HalH264eVepu510Ctx *ctx) +{ + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Param *s = ®s->reg_param; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + + s->atr_thd1.thdqp = (sm == MPP_ENC_SCENE_MODE_IPC) ? 32 : 45; + if (ctx->slice->slice_type == H264_I_SLICE) { + s->atr_thd0.thd0 = 1; + s->atr_thd0.thd1 = 2; + s->atr_thd1.thd2 = 6; + s->atr_wgt16.atr_lv16_wgt0 = 16; + s->atr_wgt16.atr_lv16_wgt1 = 16; + s->atr_wgt16.atr_lv16_wgt2 = 16; + + if (sm == MPP_ENC_SCENE_MODE_IPC) { + s->atr_wgt8.atr_lv8_wgt0 = 22; + s->atr_wgt8.atr_lv8_wgt1 = 21; + s->atr_wgt8.atr_lv8_wgt2 = 20; + s->atr_wgt4.atr_lv4_wgt0 = 20; + s->atr_wgt4.atr_lv4_wgt1 = 18; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } else { + s->atr_wgt8.atr_lv8_wgt0 = 18; + s->atr_wgt8.atr_lv8_wgt1 = 17; + s->atr_wgt8.atr_lv8_wgt2 = 18; + s->atr_wgt4.atr_lv4_wgt0 = 16; + s->atr_wgt4.atr_lv4_wgt1 = 16; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } + } else { + if (sm == MPP_ENC_SCENE_MODE_IPC) { + s->atr_thd0.thd0 = 2; + s->atr_thd0.thd1 = 4; + s->atr_thd1.thd2 = 9; + s->atr_wgt16.atr_lv16_wgt0 = 25; + s->atr_wgt16.atr_lv16_wgt1 = 20; + s->atr_wgt16.atr_lv16_wgt2 = 16; + s->atr_wgt8.atr_lv8_wgt0 = 25; + s->atr_wgt8.atr_lv8_wgt1 = 20; + s->atr_wgt8.atr_lv8_wgt2 = 18; + s->atr_wgt4.atr_lv4_wgt0 = 25; + s->atr_wgt4.atr_lv4_wgt1 = 20; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } else { + s->atr_thd0.thd0 = 1; + s->atr_thd0.thd1 = 2; + s->atr_thd1.thd2 = 7; + s->atr_wgt16.atr_lv16_wgt0 = 23; + s->atr_wgt16.atr_lv16_wgt1 = 22; + s->atr_wgt16.atr_lv16_wgt2 = 20; + s->atr_wgt8.atr_lv8_wgt0 = 24; + s->atr_wgt8.atr_lv8_wgt1 = 24; + s->atr_wgt8.atr_lv8_wgt2 = 24; + s->atr_wgt4.atr_lv4_wgt0 = 23; + s->atr_wgt4.atr_lv4_wgt1 = 22; + s->atr_wgt4.atr_lv4_wgt2 = 20; + } + } +} + +static void setup_vepu510_anti_flicker(HalH264eVepu510Ctx *ctx) +{ + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Sqi *reg = ®s->reg_sqi; + RK_U32 str = ctx->cfg->tune.anti_flicker_str; + rdo_skip_par *p_skip = NULL; + rdo_noskip_par *p_no_skip = NULL; + + static RK_U8 pskip_atf_th0[4] = { 0, 0, 0, 1 }; + static RK_U8 pskip_atf_th1[4] = { 7, 7, 7, 10 }; + static RK_U8 pskip_atf_wgt0[4] = { 16, 16, 16, 20 }; + static RK_U8 pskip_atf_wgt1[4] = { 16, 16, 14, 16 }; + static RK_U8 intra_atf_th0[4] = { 8, 16, 20, 20 }; + static RK_U8 intra_atf_th1[4] = { 16, 32, 40, 40 }; + static RK_U8 intra_atf_th2[4] = { 32, 56, 72, 72 }; + static RK_U8 intra_atf_wgt0[4] = { 16, 24, 27, 27 }; + static RK_U8 intra_atf_wgt1[4] = { 16, 22, 25, 25 }; + static RK_U8 intra_atf_wgt2[4] = { 16, 19, 20, 20 }; + + p_skip = ®->rdo_b16_skip; + p_skip->atf_thd0.madp_thd0 = pskip_atf_th0[str]; + p_skip->atf_thd0.madp_thd1 = pskip_atf_th1[str]; + p_skip->atf_thd1.madp_thd2 = 15; + p_skip->atf_thd1.madp_thd3 = 25; + p_skip->atf_wgt0.wgt0 = pskip_atf_wgt0[str]; + p_skip->atf_wgt0.wgt1 = pskip_atf_wgt1[str]; + p_skip->atf_wgt0.wgt2 = 16; + p_skip->atf_wgt0.wgt3 = 16; + p_skip->atf_wgt1.wgt4 = 16; + + p_no_skip = ®->rdo_b16_inter; + p_no_skip->ratf_thd0.madp_thd0 = 20; + p_no_skip->ratf_thd0.madp_thd1 = 40; + p_no_skip->ratf_thd1.madp_thd2 = 72; + p_no_skip->atf_wgt.wgt0 = 16; + p_no_skip->atf_wgt.wgt1 = 16; + p_no_skip->atf_wgt.wgt2 = 16; + p_no_skip->atf_wgt.wgt3 = 16; + + p_no_skip = ®->rdo_b16_intra; + p_no_skip->ratf_thd0.madp_thd0 = intra_atf_th0[str]; + p_no_skip->ratf_thd0.madp_thd1 = intra_atf_th1[str]; + p_no_skip->ratf_thd1.madp_thd2 = intra_atf_th2[str]; + p_no_skip->atf_wgt.wgt0 = intra_atf_wgt0[str]; + p_no_skip->atf_wgt.wgt1 = intra_atf_wgt1[str]; + p_no_skip->atf_wgt.wgt2 = intra_atf_wgt2[str]; + p_no_skip->atf_wgt.wgt3 = 16; + + reg->rdo_b16_intra_atf_cnt_thd.thd0 = 1; + reg->rdo_b16_intra_atf_cnt_thd.thd1 = 4; + reg->rdo_b16_intra_atf_cnt_thd.thd2 = 1; + reg->rdo_b16_intra_atf_cnt_thd.thd3 = 4; + + reg->rdo_atf_resi_thd.big_th0 = 16; + reg->rdo_atf_resi_thd.big_th1 = 16; + reg->rdo_atf_resi_thd.small_th0 = 8; + reg->rdo_atf_resi_thd.small_th1 = 8; +} + +static void setup_vepu510_anti_smear(HalH264eVepu510Ctx *ctx) +{ + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Sqi *reg = ®s->reg_sqi; + H264eSlice *slice = ctx->slice; + Vepu510H264Fbk *last_fb = &ctx->last_frame_fb; + RK_U32 mb_cnt = last_fb->st_mb_num; + RK_U32 *smear_cnt = last_fb->st_smear_cnt; + RK_S32 deblur_str = ctx->cfg->tune.deblur_str; + RK_S32 delta_qp = 0; + RK_S32 flg0 = smear_cnt[4] < (mb_cnt >> 6); + RK_S32 flg1 = 1, flg2 = 0, flg3 = 0; + RK_S32 smear_multi[4] = { 9, 12, 16, 16 }; + + hal_h264e_dbg_func("enter\n"); + + if ((smear_cnt[3] < ((5 * mb_cnt) >> 10)) || + (smear_cnt[3] < ((1126 * MPP_MAX3(smear_cnt[0], smear_cnt[1], smear_cnt[2])) >> 10)) || + (deblur_str == 6) || (deblur_str == 7)) + flg1 = 0; + + flg3 = flg1 ? 3 : (smear_cnt[4] > ((102 * mb_cnt) >> 10)) ? 2 : + (smear_cnt[4] > ((66 * mb_cnt) >> 10)) ? 1 : 0; + + if (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + reg->smear_opt_cfg.rdo_smear_en = ctx->qpmap_en; + if (ctx->qpmap_en && deblur_str > 3) + reg->smear_opt_cfg.rdo_smear_lvl16_multi = smear_multi[flg3]; + else + reg->smear_opt_cfg.rdo_smear_lvl16_multi = (flg0 != 0) ? 9 : 12; + } else { + reg->smear_opt_cfg.rdo_smear_en = 0; + reg->smear_opt_cfg.rdo_smear_lvl16_multi = 16; + } + + if (ctx->qpmap_en && deblur_str > 3) { + flg2 = 1; + if (smear_cnt[2] + smear_cnt[3] > (3 * smear_cnt[4] / 4)) + delta_qp = 1; + if (smear_cnt[4] < (mb_cnt >> 4)) + delta_qp -= 8; + else if (smear_cnt[4] < ((3 * mb_cnt) >> 5)) + delta_qp -= 7; + else + delta_qp -= 6; + + if (flg3 == 2) + delta_qp = 0; + else if (flg3 == 1) + delta_qp = -2; + } else { + if (smear_cnt[2] + smear_cnt[3] > smear_cnt[4] / 2) + delta_qp = 1; + if (smear_cnt[4] < (mb_cnt >> 8)) + delta_qp -= (deblur_str < 2) ? 6 : 8; + else if (smear_cnt[4] < (mb_cnt >> 7)) + delta_qp -= (deblur_str < 2) ? 5 : 6; + else if (smear_cnt[4] < (mb_cnt >> 6)) + delta_qp -= (deblur_str < 2) ? 3 : 4; + else + delta_qp -= 1; + } + reg->smear_opt_cfg.rdo_smear_dlt_qp = delta_qp; + + if ((H264_I_SLICE == slice->slice_type) || + (H264_I_SLICE == last_fb->frame_type)) + reg->smear_opt_cfg.stated_mode = 1; + else + reg->smear_opt_cfg.stated_mode = 2; + + reg->smear_madp_thd0.madp_cur_thd0 = 0; + reg->smear_madp_thd0.madp_cur_thd1 = (flg2 != 0) ? 48 : 24; + reg->smear_madp_thd1.madp_cur_thd2 = (flg2 != 0) ? 64 : 48; + reg->smear_madp_thd1.madp_cur_thd3 = (flg2 != 0) ? 72 : 64; + reg->smear_madp_thd2.madp_around_thd0 = (flg2 != 0) ? 4095 : 16; + reg->smear_madp_thd2.madp_around_thd1 = 32; + reg->smear_madp_thd3.madp_around_thd2 = 48; + reg->smear_madp_thd3.madp_around_thd3 = (flg2 != 0) ? 0 : 96; + reg->smear_madp_thd4.madp_around_thd4 = 48; + reg->smear_madp_thd4.madp_around_thd5 = 24; + reg->smear_madp_thd5.madp_ref_thd0 = (flg2 != 0) ? 64 : 96; + reg->smear_madp_thd5.madp_ref_thd1 = 48; + + reg->smear_cnt_thd0.cnt_cur_thd0 = (flg2 != 0) ? 2 : 1; + reg->smear_cnt_thd0.cnt_cur_thd1 = (flg2 != 0) ? 5 : 3; + reg->smear_cnt_thd0.cnt_cur_thd2 = 1; + reg->smear_cnt_thd0.cnt_cur_thd3 = 3; + reg->smear_cnt_thd1.cnt_around_thd0 = 1; + reg->smear_cnt_thd1.cnt_around_thd1 = 4; + reg->smear_cnt_thd1.cnt_around_thd2 = 1; + reg->smear_cnt_thd1.cnt_around_thd3 = 4; + reg->smear_cnt_thd2.cnt_around_thd4 = 0; + reg->smear_cnt_thd2.cnt_around_thd5 = 3; + reg->smear_cnt_thd2.cnt_around_thd6 = 0; + reg->smear_cnt_thd2.cnt_around_thd7 = 3; + reg->smear_cnt_thd3.cnt_ref_thd0 = 1; + reg->smear_cnt_thd3.cnt_ref_thd1 = 3; + + reg->smear_resi_thd0.resi_small_cur_th0 = 6; + reg->smear_resi_thd0.resi_big_cur_th0 = 9; + reg->smear_resi_thd0.resi_small_cur_th1 = 6; + reg->smear_resi_thd0.resi_big_cur_th1 = 9; + reg->smear_resi_thd1.resi_small_around_th0 = 6; + reg->smear_resi_thd1.resi_big_around_th0 = 11; + reg->smear_resi_thd1.resi_small_around_th1 = 6; + reg->smear_resi_thd1.resi_big_around_th1 = 8; + reg->smear_resi_thd2.resi_small_around_th2 = 9; + reg->smear_resi_thd2.resi_big_around_th2 = 20; + reg->smear_resi_thd2.resi_small_around_th3 = 6; + reg->smear_resi_thd2.resi_big_around_th3 = 20; + reg->smear_resi_thd3.resi_small_ref_th0 = 7; + reg->smear_resi_thd3.resi_big_ref_th0 = 16; + reg->smear_resi_thd4.resi_th0 = (flg2 != 0) ? 0 : 10; + reg->smear_resi_thd4.resi_th1 = (flg2 != 0) ? 0 : 6; + + reg->smear_st_thd.madp_cnt_th0 = (flg2 != 0) ? 0 : 1; + reg->smear_st_thd.madp_cnt_th1 = (flg2 != 0) ? 0 : 5; + reg->smear_st_thd.madp_cnt_th2 = (flg2 != 0) ? 0 : 1; + reg->smear_st_thd.madp_cnt_th3 = (flg2 != 0) ? 0 : 3; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu510_scaling_list(HalH264eVepu510Ctx *ctx) +{ + HalVepu510RegSet *regs = ctx->regs_set; + Vepu510SclCfg *s = ®s->reg_scl; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U8 idx; + + hal_h264e_dbg_func("enter\n"); + + /* intra4x4 and inter4x4 is not supported on VEPU500. + * valid range: 0x2200 ~ 0x221F + */ + if (ctx->pps->pic_scaling_matrix_present == 1) { + for (idx = 0; idx < 64; idx++) { + p[idx] = vepu510_h264_cqm_jvt8i[63 - idx]; /* intra8x8 */ + p[idx + 64] = vepu510_h264_cqm_jvt8p[63 - idx]; /* inter8x8 */ + } + } else if (ctx->pps->pic_scaling_matrix_present == 2) { + //TODO: Update scaling list for (scaling_list_mode == 2) + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET hal_h264e_vepu510_gen_regs(void *hal, HalEncTask *task) +{ + HalH264eVepu510Ctx *ctx = (HalH264eVepu510Ctx *)hal; + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Frame *reg_frm = ®s->reg_frm; + MppEncCfgSet *cfg = ctx->cfg; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + EncRcTask *rc_task = task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + MPP_RET ret = MPP_OK; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h264e_dbg_func("enter %p\n", hal); + hal_h264e_dbg_detail("frame %d generate regs now", ctx->frms->seq_idx); + + /* register setup */ + memset(regs, 0, sizeof(*regs)); + + setup_vepu510_normal(regs); + ret = setup_vepu510_prep(regs, &ctx->cfg->prep); + if (ret) + return ret; + + setup_vepu510_codec(regs, sps, pps, slice); + setup_vepu510_dual_core(ctx, slice->slice_type, task->flags.curr_idx, task->flags.refr_idx); + setup_vepu510_rdo_pred(ctx, sps, pps, slice); + setup_vepu510_aq(ctx); + setup_vepu510_anti_stripe(ctx); + setup_vepu510_anti_ringing(ctx); + setup_vepu510_anti_flicker(ctx); + setup_vepu510_anti_smear(ctx); + setup_vepu510_scaling_list(ctx); + + setup_vepu510_rc_base(regs, ctx, rc_task); + setup_vepu510_io_buf(regs, ctx->offsets, task); + setup_vepu510_recn_refr(ctx, regs); + + reg_frm->common.meiw_addr = task->md_info ? mpp_buffer_get_fd(task->md_info) : 0; + reg_frm->common.enc_pic.mei_stor = task->md_info ? 1 : 0; + + reg_frm->common.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + reg_frm->common.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + setup_vepu510_split(regs, cfg); + setup_vepu510_me(ctx); + + if (frm_status->is_i_refresh) + setup_vepu510_intra_refresh(regs, ctx, frm_status->seq_idx % cfg->rc.gop); + + setup_vepu510_l2(ctx, &cfg->hw); + setup_vepu510_ext_line_buf(regs, ctx); + if (ctx->roi_data) + vepu510_set_roi(&ctx->regs_set->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + + vepu510_h264e_tune_reg_patch(ctx->tune, task); + + /* two pass register patch */ + if (frm->save_pass1) + vepu510_h264e_save_pass1_patch(regs, ctx); + + if (frm->use_pass1) + vepu510_h264e_use_pass1_patch(regs, ctx); + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu510_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu510Ctx *ctx = (HalH264eVepu510Ctx *)hal; + HalVepu510RegSet *regs = ctx->regs_set; + + (void) task; + + hal_h264e_dbg_func("enter %p\n", hal); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->reg_ctl; + wr_cfg.size = sizeof(regs->reg_ctl); + wr_cfg.offset = VEPU510_CTL_OFFSET; +#if DUMP_REG + { + RK_U32 i; + RK_U32 *reg = (RK_U32)wr_cfg.reg; + for ( i = 0; i < sizeof(regs->reg_ctl) / sizeof(RK_U32); i++) { + mpp_log("reg[%d] = 0x%08x\n", i, reg[i]); + } + + } +#endif + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_frm; + wr_cfg.size = sizeof(regs->reg_frm); + wr_cfg.offset = VEPU510_FRAME_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_rc_roi; + wr_cfg.size = sizeof(regs->reg_rc_roi); + wr_cfg.offset = VEPU510_RC_ROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_param; + wr_cfg.size = sizeof(regs->reg_param); + wr_cfg.offset = VEPU510_PARAM_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_sqi; + wr_cfg.size = sizeof(regs->reg_sqi); + wr_cfg.offset = VEPU510_SQI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_scl; + wr_cfg.size = sizeof(regs->reg_scl); + wr_cfg.offset = VEPU510_SCL_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->offsets); + if (ret) { + mpp_err_f("set register offsets failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_ctl.int_sta; + rd_cfg.size = sizeof(RK_U32); + rd_cfg.offset = VEPU510_REG_BASE_HW_STATUS; + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_st; + rd_cfg.size = sizeof(regs->reg_st); + rd_cfg.offset = VEPU510_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* send request to hardware */ + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu510_status_check(HalVepu510RegSet *regs) +{ + MPP_RET ret = MPP_OK; + + if (regs->reg_ctl.int_sta.lkt_node_done_sta) + hal_h264e_dbg_detail("lkt_done finish"); + + if (regs->reg_ctl.int_sta.enc_done_sta) + hal_h264e_dbg_detail("enc_done finish"); + + if (regs->reg_ctl.int_sta.vslc_done_sta) + hal_h264e_dbg_detail("enc_slice finsh"); + + if (regs->reg_ctl.int_sta.sclr_done_sta) + hal_h264e_dbg_detail("safe clear finsh"); + + if (regs->reg_ctl.int_sta.vbsf_oflw_sta) { + mpp_err_f("bit stream overflow"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.vbuf_lens_sta) { + mpp_err_f("bus write full"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.enc_err_sta) { + mpp_err_f("bus error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wdg_sta) { + mpp_err_f("wdg timeout"); + ret = MPP_NOK; + } + + return ret; +} + +static MPP_RET hal_h264e_vepu510_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu510Ctx *ctx = (HalH264eVepu510Ctx *)hal; + HalVepu510RegSet *regs = &ctx->regs_sets[task->flags.reg_idx]; + RK_U32 split_out = ctx->cfg->split.split_out; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + H264NaluType type = (task->rc_task->frm.is_idr != 0) ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppEncH264HwCfg *hw_cfg = &ctx->cfg->h264.hw_cfg; + RK_S32 i; + + hal_h264e_dbg_func("enter %p\n", hal); + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (task->rc_task->frm.save_pass1) + split_out = 0; + + /* update split_out in hw_cfg */ + hw_cfg->hw_split_out = split_out; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len; + RK_U32 slice_last; + MppDevPollCfg *poll_cfg = (MppDevPollCfg *)((char *)ctx->poll_cfgs + + task->flags.reg_idx * ctx->poll_cfg_size); + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = split_out & MPP_ENC_SPLIT_OUT_LOWDELAY ? 1 : ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].vepu510.sli_lst; + slice_len = poll_cfg->slice_info[i].vepu510.sli_len; + + mpp_packet_add_segment_info(pkt, type, offset, slice_len); + offset += slice_len; + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) { + param.length = slice_len; + + if (slice_last) + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + else + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + + mpp_callback(ctx->output_cb, ¶m); + } + } + } while (!slice_last); + + ret = hal_h264e_vepu510_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + ret = hal_h264e_vepu510_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } + + mpp_packet_add_segment_info(pkt, type, offset, regs->reg_st.bs_lgth_l32); + } + + if (!(split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) && !ret) { + HalH264eVepuStreamAmend *amend = &ctx->amend_sets[task->flags.reg_idx]; + + if (amend->enable) { + amend->old_length = task->hw_length; + amend->slice->is_multi_slice = (ctx->cfg->split.split_mode > 0); + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + task->hw_length = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = task->hw_length; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + + hal_h264e_dbg_func("leave %p ret %d\n", hal, ret); + + return ret; +} + +static MPP_RET hal_h264e_vepu510_ret_task(void * hal, HalEncTask * task) +{ + HalH264eVepu510Ctx *ctx = (HalH264eVepu510Ctx *)hal; + HalVepu510RegSet *regs = &ctx->regs_sets[task->flags.reg_idx]; + EncRcTaskInfo *rc_info = &task->rc_task->info; + Vepu510H264Fbk *fb = &ctx->feedback; + Vepu510Status *reg_st = ®s->reg_st; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + + hal_h264e_dbg_func("enter %p\n", hal); + + fb->st_mb_num = mbs; + fb->st_smear_cnt[0] = reg_st->st_smear_cnt.rdo_smear_cnt0 * 4; + fb->st_smear_cnt[1] = reg_st->st_smear_cnt.rdo_smear_cnt1 * 4; + fb->st_smear_cnt[2] = reg_st->st_smear_cnt.rdo_smear_cnt2 * 4; + fb->st_smear_cnt[3] = reg_st->st_smear_cnt.rdo_smear_cnt3 * 4; + fb->st_smear_cnt[4] = fb->st_smear_cnt[0] + fb->st_smear_cnt[1] + + fb->st_smear_cnt[2] + fb->st_smear_cnt[3]; + fb->frame_type = ctx->slice->slice_type; + + // update total hardware length + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = regs->reg_st.qp_sum / mbs; + rc_info->iblk4_prop = (regs->reg_st.st_pnum_i4.pnum_i4 + + regs->reg_st.st_pnum_i8.pnum_i8 + + regs->reg_st.st_pnum_i16.pnum_i16) * 256 / mbs; + + rc_info->sse = ((RK_S64)regs->reg_st.sse_h32 << 16) + + (regs->reg_st.st_sse_bsl.sse_l16 & 0xffff); + rc_info->lvl16_inter_num = regs->reg_st.st_pnum_p16.pnum_p16; + rc_info->lvl8_inter_num = regs->reg_st.st_pnum_p8.pnum_p8; + rc_info->lvl16_intra_num = regs->reg_st.st_pnum_i16.pnum_i16; + rc_info->lvl8_intra_num = regs->reg_st.st_pnum_i8.pnum_i8; + rc_info->lvl4_intra_num = regs->reg_st.st_pnum_i4.pnum_i4; + + ctx->hal_rc_cfg.bit_real = rc_info->bit_real; + ctx->hal_rc_cfg.quality_real = rc_info->quality_real; + ctx->hal_rc_cfg.iblk4_prop = rc_info->iblk4_prop; + + task->hal_ret.data = &ctx->hal_rc_cfg; + task->hal_ret.number = 1; + + mpp_dev_multi_offset_reset(ctx->offsets); + + if (ctx->dpb) { + h264e_dpb_hal_end(ctx->dpb, task->flags.curr_idx); + h264e_dpb_hal_end(ctx->dpb, task->flags.refr_idx); + } + + vepu510_h264e_tune_stat_update(ctx->tune, task); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu510 = { + .name = "hal_h264e_vepu510", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu510Ctx), + .flag = 0, + .init = hal_h264e_vepu510_init, + .deinit = hal_h264e_vepu510_deinit, + .prepare = hal_h264e_vepu510_prepare, + .get_task = hal_h264e_vepu510_get_task, + .gen_regs = hal_h264e_vepu510_gen_regs, + .start = hal_h264e_vepu510_start, + .wait = hal_h264e_vepu510_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu510_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu510) diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.h new file mode 100644 index 000000000..7f54d8b3f --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264E_VEPU510_H +#define HAL_H264E_VEPU510_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h264e_vepu510; + +#endif /* HAL_H264E_VEPU510_H */ diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510_reg.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_reg.h new file mode 100644 index 000000000..a0ffc4459 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_reg.h @@ -0,0 +1,641 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264E_VEPU510_REG_H +#define HAL_H264E_VEPU510_REG_H + +#include "rk_type.h" +#include "vepu510_common.h" + +/* class: buffer/video syntax */ +/* 0x00000270 reg156 - 0x000003f4 reg253*/ +typedef struct H264eVepu510Frame_t { + + Vepu510FrmCommon common; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 rect_size : 1; + RK_U32 reserved : 2; + RK_U32 vlc_lmt : 1; + RK_U32 chrm_spcl : 1; + RK_U32 reserved1 : 8; + RK_U32 ccwa_e : 1; + RK_U32 reserved2 : 1; + RK_U32 atr_e : 1; + RK_U32 reserved3 : 4; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved4 : 6; + RK_U32 atf_e : 1; + RK_U32 atr_mult_sel_e : 1; + RK_U32 reserved5 : 2; + } rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 rdo_mark_mode : 9; + RK_U32 reserved : 23; + } iprd_csts; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_ref_idc : 2; + RK_U32 nal_unit_type : 5; + RK_U32 reserved : 25; + } synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 max_fnum : 4; + RK_U32 drct_8x8 : 1; + RK_U32 mpoc_lm4 : 4; + RK_U32 poc_type : 2; + RK_U32 reserved : 21; + } synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 etpy_mode : 1; + RK_U32 trns_8x8 : 1; + RK_U32 csip_flag : 1; + RK_U32 num_ref0_idx : 2; + RK_U32 num_ref1_idx : 2; + RK_U32 pic_init_qp : 6; + RK_U32 cb_ofst : 5; + RK_U32 cr_ofst : 5; + RK_U32 reserved : 1; + RK_U32 dbf_cp_flg : 1; + RK_U32 reserved1 : 7; + } synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 sli_type : 2; + RK_U32 pps_id : 8; + RK_U32 drct_smvp : 1; + RK_U32 num_ref_ovrd : 1; + RK_U32 cbc_init_idc : 2; + RK_U32 reserved : 2; + RK_U32 frm_num : 16; + } synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 idr_pid : 16; + RK_U32 poc_lsb : 16; + } synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 rodr_pic_idx : 2; + RK_U32 ref_list0_rodr : 1; + RK_U32 sli_beta_ofst : 4; + RK_U32 sli_alph_ofst : 4; + RK_U32 dis_dblk_idc : 2; + RK_U32 reserved : 3; + RK_U32 rodr_pic_num : 16; + } synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 nopp_flg : 1; + RK_U32 ltrf_flg : 1; + RK_U32 arpm_flg : 1; + RK_U32 mmco4_pre : 1; + RK_U32 mmco_type0 : 3; + RK_U32 mmco_parm0 : 16; + RK_U32 mmco_type1 : 3; + RK_U32 mmco_type2 : 3; + RK_U32 reserved : 3; + } synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 mmco_parm1 : 16; + RK_U32 mmco_parm2 : 16; + } synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 long_term_frame_idx0 : 4; + RK_U32 long_term_frame_idx1 : 4; + RK_U32 long_term_frame_idx2 : 4; + RK_U32 reserved : 20; + } synt_refm2; + + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } synt_refm3_hevc; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } synt_long_refm0_hevc; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } synt_long_refm1_hevc; + + /* 0x000003e0 reg248 */ + struct { + RK_U32 sao_lambda_multi : 3; + RK_U32 reserved : 29; + } sao_cfg_hevc; + + /* 0x3e4 - 0x3ec */ + RK_U32 reserved249_251[3]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 mv_v_lmt_thd : 14; + RK_U32 reserved : 1; + RK_U32 mv_v_lmt_en : 1; + RK_U32 reserved1 : 16; + } sli_cfg; + + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 9; + RK_U32 reserved : 7; + RK_U32 tile_y : 9; + RK_U32 reserved1 : 7; + } tile_pos_hevc; +} H264eVepu510Frame; + +/* class: param */ +/* 0x00001700 reg1472 - 0x000019cc reg1651 */ +typedef struct H264eVepu510Param_t { + /* 0x00001700 reg1472 */ + struct { + RK_U32 iprd_tthdy4_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_0; + + /* 0x00001704 reg1473 */ + struct { + RK_U32 iprd_tthdy4_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_1; + + /* 0x00001708 reg1474 */ + struct { + RK_U32 iprd_tthdc8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_0; + + /* 0x0000170c reg1475 */ + struct { + RK_U32 iprd_tthdc8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_1; + + /* 0x00001710 reg1476 */ + struct { + RK_U32 iprd_tthdy8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_0; + + /* 0x00001714 reg1477 */ + struct { + RK_U32 iprd_tthdy8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_1; + + /* 0x00001718 reg1478 */ + struct { + RK_U32 iprd_tthd_ul : 12; + RK_U32 reserved : 20; + } iprd_tthd_ul; + + /* 0x0000171c reg1479 */ + struct { + RK_U32 iprd_wgty8_0 : 8; + RK_U32 iprd_wgty8_1 : 8; + RK_U32 iprd_wgty8_2 : 8; + RK_U32 iprd_wgty8_3 : 8; + } iprd_wgty8; + + /* 0x00001720 reg1480 */ + struct { + RK_U32 iprd_wgty4_0 : 8; + RK_U32 iprd_wgty4_1 : 8; + RK_U32 iprd_wgty4_2 : 8; + RK_U32 iprd_wgty4_3 : 8; + } iprd_wgty4; + + /* 0x00001724 reg1481 */ + struct { + RK_U32 iprd_wgty16_0 : 8; + RK_U32 iprd_wgty16_1 : 8; + RK_U32 iprd_wgty16_2 : 8; + RK_U32 iprd_wgty16_3 : 8; + } iprd_wgty16; + + /* 0x00001728 reg1482 */ + struct { + RK_U32 iprd_wgtc8_0 : 8; + RK_U32 iprd_wgtc8_1 : 8; + RK_U32 iprd_wgtc8_2 : 8; + RK_U32 iprd_wgtc8_3 : 8; + } iprd_wgtc8; + + /* 0x172c */ + RK_U32 reserved_1483; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 qnt_f_bias_i : 10; + RK_U32 qnt_f_bias_p : 10; + RK_U32 reserve : 12; + } qnt_bias_comb; + + /* 0x1734 - 0x173c */ + RK_U32 reserved1485_1487[3]; + + /* 0x00001740 reg1488 */ + struct { + RK_U32 thd0 : 8; + RK_U32 reserve0 : 8; + RK_U32 thd1 : 8; + RK_U32 reserve1 : 8; + } atr_thd0; + + /* 0x00001744 reg1489 */ + struct { + RK_U32 thd2 : 8; + RK_U32 reserve0 : 8; + RK_U32 thdqp : 6; + RK_U32 reserve1 : 10; + } atr_thd1; + + /* 0x1748 - 0x174c */ + RK_U32 reserved1490_1491[2]; + + /* 0x00001750 reg1492 */ + struct { + RK_U32 atr_lv16_wgt0 : 8; + RK_U32 atr_lv16_wgt1 : 8; + RK_U32 atr_lv16_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt16; + + /* 0x00001754 reg1493*/ + struct { + RK_U32 atr_lv8_wgt0 : 8; + RK_U32 atr_lv8_wgt1 : 8; + RK_U32 atr_lv8_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt8; + + /* 0x00001758 reg1494 */ + struct { + RK_U32 atr_lv4_wgt0 : 8; + RK_U32 atr_lv4_wgt1 : 8; + RK_U32 atr_lv4_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt4; + + /* 0x175c */ + RK_U32 reserved_1495; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 itp_mode : 1; + RK_U32 reserved : 1; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 reserved1 : 17; + } me_sqi_comb; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th_comb; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 reserved : 20; + } cime_madp_th_comb; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi_comb; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th_comb; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th_comb; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi_comb; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th_comb; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 reg1536 - 0x000018cc reg1587*/ + RK_U32 pprd_lamb_satd_0_51[52]; + + /* 0x000018d0 reg1588 */ + struct { + RK_U32 lambda_satd_offset : 5; + RK_U32 reserved : 27; + } iprd_lamb_satd_ofst; + + /* 0x18d4 - 0x18fc */ + RK_U32 reserved1589_1599[11]; + + /* 0x00001900 reg1600 - 0x000019cc reg1651*/ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} H264eVepu510Param; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x000020fc reg2111 */ +typedef struct H264eVepu510SqiCfg_t { + /* 0x00002000 reg2048 - 0x00002010 reg2052*/ + RK_U32 reserved_2048_2052[5]; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 rdo_smear_lvl16_multi : 8; + RK_U32 rdo_smear_dlt_qp : 4; + RK_U32 reserved : 1; + RK_U32 stated_mode : 2; + RK_U32 rdo_smear_en : 1; + RK_U32 reserved1 : 16; + } smear_opt_cfg; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 madp_cur_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_cur_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd0; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 madp_cur_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_cur_thd3 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd1; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 madp_around_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd2; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 madp_around_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd3 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd3; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 madp_around_thd4 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd5 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd4; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 madp_ref_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_ref_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd5; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 cnt_cur_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_cur_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_cur_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_cur_thd3 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd0; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 cnt_around_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_around_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_around_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_around_thd3 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd1; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 cnt_around_thd4 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_around_thd5 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_around_thd6 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_around_thd7 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd2; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 cnt_ref_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_ref_thd1 : 4; + RK_U32 reserved1 : 20; + } smear_cnt_thd3; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 resi_small_cur_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_cur_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_cur_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_cur_th1 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd0; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 resi_small_around_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_around_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_around_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_around_th1 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd1; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 resi_small_around_th2 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_around_th2 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_around_th3 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_around_th3 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd2; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 resi_small_ref_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_ref_th0 : 6; + RK_U32 reserved1 : 18; + } smear_resi_thd3; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 resi_th0 : 8; + RK_U32 reserved : 8; + RK_U32 resi_th1 : 8; + RK_U32 reserved1 : 8; + } smear_resi_thd4; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 madp_cnt_th0 : 4; + RK_U32 madp_cnt_th1 : 4; + RK_U32 madp_cnt_th2 : 4; + RK_U32 madp_cnt_th3 : 4; + RK_U32 reserved : 16; + } smear_st_thd; + + /* 0x2058 - 0x206c */ + RK_U32 reserved2070_2075[6]; + + /* 0x00002070 reg2076 - 0x0000207c reg2079*/ + rdo_skip_par rdo_b16_skip; + + /* 0x00002080 reg2080 - 0x00002088 reg2082 */ + RK_U32 reserved2080_2082[3]; + + /* 0x0000208c reg2083 - 0x00002094 reg2085 */ + rdo_noskip_par rdo_b16_inter; + + /* 0x00002098 reg2086 - 0x000020a4 reg2088 */ + RK_U32 reserved2086_2088[3]; + + /* 0x000020a8 reg2089 - 0x000020ac reg2091 */ + rdo_noskip_par rdo_b16_intra; + + /* 0x000020b0 reg2092 */ + RK_U32 reserved2092; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 thd0 : 4; + RK_U32 reserved : 4; + RK_U32 thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 thd3 : 4; + RK_U32 reserved3 : 4; + } rdo_b16_intra_atf_cnt_thd; + + /* 0x000020b8 reg2094 */ + struct { + RK_U32 big_th0 : 6; + RK_U32 reserved : 2; + RK_U32 big_th1 : 6; + RK_U32 reserved1 : 2; + RK_U32 small_th0 : 6; + RK_U32 reserved2 : 2; + RK_U32 small_th1 : 6; + RK_U32 reserved3 : 2; + } rdo_atf_resi_thd; +} H264eVepu510Sqi; + +/* class: mmu */ +/* 0x0000f000 reg15360 - 0x0000f024 reg15369 */ +typedef struct HalVepu510Reg_t { + Vepu510ControlCfg reg_ctl; + H264eVepu510Frame reg_frm; + Vepu510RcRoi reg_rc_roi; + H264eVepu510Param reg_param; + H264eVepu510Sqi reg_sqi; + Vepu510SclCfg reg_scl; + Vepu510Status reg_st; + Vepu510Dbg reg_dbg; +} HalVepu510RegSet; + +#endif \ No newline at end of file diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu510_tune.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_tune.c new file mode 100644 index 000000000..77d6e1f72 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu510_tune.c @@ -0,0 +1,206 @@ +/* + * Copyright 2024 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hal_enc_task.h" +#include "hal_h264e_vepu510_reg.h" + +#define HAL_H264E_DBG_CONTENT (0x00000200) +#define hal_h264e_dbg_content(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_CONTENT, fmt, ## __VA_ARGS__) + +typedef struct HalH264eVepu510Tune_t { + HalH264eVepu510Ctx *ctx; + + RK_U8 *qm_mv_buf; /* qpmap mv buffer */ + RK_U32 qm_mv_buf_size; + Vepu510NpuOut *obj_out; /* object map from npu */ + + RK_S32 pre_madp[2]; + RK_S32 pre_madi[2]; +} HalH264eVepu510Tune; + +static HalH264eVepu510Tune *vepu510_h264e_tune_init(HalH264eVepu510Ctx *ctx) +{ + HalH264eVepu510Tune *tune = mpp_calloc(HalH264eVepu510Tune, 1); + + if (NULL == tune) + return tune; + + tune->ctx = ctx; + tune->pre_madi[0] = tune->pre_madi[1] = -1; + tune->pre_madp[0] = tune->pre_madp[1] = -1; + + return tune; +} + +static void vepu510_h264e_tune_deinit(void *tune) +{ + HalH264eVepu510Tune * t = (HalH264eVepu510Tune *)tune; + MPP_FREE(t->qm_mv_buf); + MPP_FREE(tune); +} + +static MPP_RET vepu510_h264e_tune_qpmap_init(HalH264eVepu510Tune *tune) +{ + HalH264eVepu510Ctx *ctx = tune->ctx; + HalVepu510RegSet *regs = ctx->regs_set; + H264eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 w64 = MPP_ALIGN(ctx->cfg->prep.width, 64); + RK_S32 h16 = MPP_ALIGN(ctx->cfg->prep.height, 16); + RK_S32 roir_buf_fd = -1; + + if (ctx->roi_data) { + //TODO: external qpmap buffer + } else { + if (NULL == ctx->roir_buf) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + + //TODO: bmap_mdc_dpth = 1 ??? + ctx->roir_buf_size = w64 * h16 / 256 * 4; + mpp_buffer_get(ctx->roi_grp, &ctx->roir_buf, ctx->roir_buf_size); + } + + roir_buf_fd = mpp_buffer_get_fd(ctx->roir_buf); + } + + if (ctx->roir_buf == NULL) { + mpp_err("failed to get roir_buf\n"); + return MPP_ERR_MALLOC; + } + reg_frm->common.adr_roir = roir_buf_fd; + + if (tune->qm_mv_buf == NULL) { + tune->qm_mv_buf_size = w64 * h16 / 256; + tune->qm_mv_buf = mpp_calloc(RK_U8, tune->qm_mv_buf_size); + if (NULL == tune->qm_mv_buf) { + mpp_err("failed to get qm_mv_buf\n"); + return MPP_ERR_MALLOC; + } + } + + hal_h264e_dbg_detail("roir_buf_fd %d, size %d qm_mv_buf %p size %d\n", + roir_buf_fd, ctx->roir_buf_size, tune->qm_mv_buf, + tune->qm_mv_buf_size); + return MPP_OK; +} + +static void vepu510_h264e_tune_qpmap(void *p, HalEncTask *task) +{ + HalH264eVepu510Tune *tune = (HalH264eVepu510Tune *)p; + MPP_RET ret = MPP_OK; + + (void)task; + hal_h264e_dbg_func("enter\n"); + + ret = vepu510_h264e_tune_qpmap_init(tune); + if (ret != MPP_OK) { + mpp_err("failed to init qpmap\n"); + return; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void vepu510_h264e_tune_reg_patch(void *p, HalEncTask *task) +{ + HalH264eVepu510Tune *tune = (HalH264eVepu510Tune *)p; + + if (NULL == tune) + return; + + HalH264eVepu510Ctx *ctx = tune->ctx; + + if (ctx->qpmap_en && (task->md_info != NULL)) + vepu510_h264e_tune_qpmap(tune, task); +} + +static void vepu510_h264e_tune_stat_update(void *p, HalEncTask *task) +{ + HalH264eVepu510Tune *tune = (HalH264eVepu510Tune *)p; + + if (NULL == tune) + return; + + EncRcTaskInfo *rc_info = &task->rc_task->info; + HalH264eVepu510Ctx *ctx = tune->ctx; + HalVepu510RegSet *regs = &ctx->regs_sets[task->flags.reg_idx]; + Vepu510Status *st = ®s->reg_st; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 b16_num = mb_w * mb_h; + RK_U32 madi_cnt = 0; + + RK_U32 madi_th_cnt0 = st->st_madi_lt_num0.madi_th_lt_cnt0 + + st->st_madi_rt_num0.madi_th_rt_cnt0 + + st->st_madi_lb_num0.madi_th_lb_cnt0 + + st->st_madi_rb_num0.madi_th_rb_cnt0; + RK_U32 madi_th_cnt1 = st->st_madi_lt_num0.madi_th_lt_cnt1 + + st->st_madi_rt_num0.madi_th_rt_cnt1 + + st->st_madi_lb_num0.madi_th_lb_cnt1 + + st->st_madi_rb_num0.madi_th_rb_cnt1; + RK_U32 madi_th_cnt2 = st->st_madi_lt_num1.madi_th_lt_cnt2 + + st->st_madi_rt_num1.madi_th_rt_cnt2 + + st->st_madi_lb_num1.madi_th_lb_cnt2 + + st->st_madi_rb_num1.madi_th_rb_cnt2; + RK_U32 madi_th_cnt3 = st->st_madi_lt_num1.madi_th_lt_cnt3 + + st->st_madi_rt_num1.madi_th_rt_cnt3 + + st->st_madi_lb_num1.madi_th_lb_cnt3 + + st->st_madi_rb_num1.madi_th_rb_cnt3; + RK_U32 madp_th_cnt0 = st->st_madp_lt_num0.madp_th_lt_cnt0 + + st->st_madp_rt_num0.madp_th_rt_cnt0 + + st->st_madp_lb_num0.madp_th_lb_cnt0 + + st->st_madp_rb_num0.madp_th_rb_cnt0; + RK_U32 madp_th_cnt1 = st->st_madp_lt_num0.madp_th_lt_cnt1 + + st->st_madp_rt_num0.madp_th_rt_cnt1 + + st->st_madp_lb_num0.madp_th_lb_cnt1 + + st->st_madp_rb_num0.madp_th_rb_cnt1; + RK_U32 madp_th_cnt2 = st->st_madp_lt_num1.madp_th_lt_cnt2 + + st->st_madp_rt_num1.madp_th_rt_cnt2 + + st->st_madp_lb_num1.madp_th_lb_cnt2 + + st->st_madp_rb_num1.madp_th_rb_cnt2; + RK_U32 madp_th_cnt3 = st->st_madp_lt_num1.madp_th_lt_cnt3 + + st->st_madp_rt_num1.madp_th_rt_cnt3 + + st->st_madp_lb_num1.madp_th_lb_cnt3 + + st->st_madp_rb_num1.madp_th_rb_cnt3; + + madi_cnt = (6 * madi_th_cnt3 + 5 * madi_th_cnt2 + 4 * madi_th_cnt1) >> 2; + rc_info->complex_level = (madi_cnt * 100 > 30 * b16_num) ? 2 : + (madi_cnt * 100 > 13 * b16_num) ? 1 : 0; + + { + RK_U32 md_cnt = 0, motion_level = 0; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt3 + 11 * madp_th_cnt2 + 8 * madp_th_cnt1) >> 2; + else + md_cnt = (24 * madp_th_cnt3 + 22 * madp_th_cnt2 + 17 * madp_th_cnt1) >> 2; + + if (md_cnt * 100 > 15 * b16_num) + motion_level = 200; + else if (md_cnt * 100 > 5 * b16_num) + motion_level = 100; + else if (md_cnt * 100 > (b16_num >> 2)) + motion_level = 1; + else + motion_level = 0; + rc_info->motion_level = motion_level; + } + hal_h264e_dbg_rc("complex_level %d motion_level %d\n", + rc_info->complex_level, rc_info->motion_level); + + (void)madi_th_cnt0; + (void)madp_th_cnt0; +} diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu511.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu511.c new file mode 100644 index 000000000..0d0b6b74b --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu511.c @@ -0,0 +1,2629 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h264e_vepu511" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" +#include "mpp_enc_cb_param.h" + +#include "rkv_enc_def.h" +#include "hal_h264e_debug.h" +#include "hal_bufs.h" +#include "hal_h264e_vepu511_reg.h" +#include "hal_h264e_vepu511.h" +#include "hal_h264e_stream_amend.h" +#include "h264e_dpb.h" + +#include "vepu5xx_common.h" +#include "vepu511_common.h" + +#define DUMP_REG 0 +#define VEPU540C_MAX_ROI_NUM 8 + +/* Custom Quant Matrices: Joint Video Team */ +static RK_U8 vepu511_h264_cqm_jvt8i[64] = { + 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static RK_U8 vepu511_h264_cqm_jvt8p[64] = { + 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 +}; + +/* scale_q = (65536 + scale_iq / 2) / scale_iq */ +static RK_U16 vepu511_h264_cqm_jvt8i_q[64] = { + 10923, 6554, 5041, 4096, 3641, 2849, 2621, 2427, + 6554, 5958, 4096, 3641, 2849, 2621, 2427, 2260, + 5041, 4096, 3641, 2849, 2621, 2427, 2260, 2114, + 4096, 3641, 2849, 2621, 2427, 2260, 2114, 1986, + 3641, 2849, 2621, 2427, 2260, 2114, 1986, 1820, + 2849, 2621, 2427, 2260, 2114, 1986, 1820, 1725, + 2621, 2427, 2260, 2114, 1986, 1820, 1725, 1638, + 2427, 2260, 2114, 1986, 1820, 1725, 1638, 1560 +}; + +/* scale_q = (65536 + scale_iq / 2) / scale_iq */ +static RK_U16 vepu511_h264_cqm_jvt8p_q[64] = { + 7282, 5041, 4369, 3855, 3449, 3121, 2979, 2731, + 5041, 5041, 3855, 3449, 3121, 2979, 2731, 2621, + 4369, 3855, 3449, 3121, 2979, 2731, 2621, 2427, + 3855, 3449, 3121, 2979, 2731, 2621, 2427, 2341, + 3449, 3121, 2979, 2731, 2621, 2427, 2341, 2185, + 3121, 2979, 2731, 2621, 2427, 2341, 2185, 2048, + 2979, 2731, 2621, 2427, 2341, 2185, 2048, 1986, + 2731, 2621, 2427, 2341, 2185, 2048, 1986, 1872 +}; + +typedef struct Vepu511RoiH264BsCfg_t { + RK_U64 force_inter : 42; + RK_U64 mode_mask : 9; + RK_U64 reserved : 10; + RK_U64 force_intra : 1; + RK_U64 qp_adj_en : 1; + RK_U64 amv_en : 1; +} Vepu511RoiH264BsCfg; + +typedef struct Vepu511H264Fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 frame_type; + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; + RK_U32 st_smear_cnt[5]; +} Vepu511H264Fbk; + +typedef struct HalH264eVepu511Ctx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_S32 frame_cnt; + + /* buffers management */ + HalBufs hw_recn; + RK_S32 pixel_buf_fbc_hdr_size; + RK_S32 pixel_buf_fbc_bdy_size; + RK_S32 pixel_buf_size; + RK_S32 thumb_buf_size; + RK_S32 smear_size; + RK_S32 max_buf_cnt; + MppDevRegOffCfgs *offsets; + + /* external line buffer over 4K */ + MppBufferGroup ext_line_buf_grp; + MppBuffer ext_line_buf; + RK_S32 ext_line_buf_size; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eDpb *dpb; + H264eFrmInfo *frms; + + /* async encode TSVC info */ + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + + /* syntax for output to enc_impl */ + EncRcTaskInfo hal_rc_cfg; + + /* osd */ + Vepu511OsdCfg osd_cfg; + + /* roi */ + void *roi_data; + MppBufferGroup roi_grp; + MppBuffer roi_base_cfg_buf; + RK_S32 roi_base_buf_size; + + /* two-pass deflicker */ + MppBuffer buf_pass1; + + /* single register set for single core */ + HalVepu511RegSet *regs_set; + HalH264eVepuStreamAmend amend; + H264ePrefixNal *prefix; + H264eSlice *slice; + + RK_S32 curr_idx; + RK_S32 prev_idx; + + /* slice low delay output callback */ + MppCbCtx *output_cb; + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + MppDevPollCfg *poll_cfgs; + + Vepu511H264Fbk feedback; + Vepu511H264Fbk last_frame_fb; + + void *tune; + RK_S32 smart_en; + RK_S32 qpmap_en; +} HalH264eVepu511Ctx; + +static RK_S32 h264_aq_tthd_default[16] = { + 0, 0, 0, 0, 3, 3, 5, 5, + 8, 8, 8, 15, 15, 20, 25, 25 +}; + +static RK_S32 h264_P_aq_step_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 7, 8 +}; + +static RK_S32 h264_I_aq_step_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 7, 8 +}; + +#define H264E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) + +static RK_U32 h264e_lambda_default[60] = { + 0x00000005, 0x00000006, 0x00000007, 0x00000009, + 0x0000000b, 0x0000000e, 0x00000012, 0x00000016, + 0x0000001c, 0x00000024, 0x0000002d, 0x00000039, + 0x00000048, 0x0000005b, 0x00000073, 0x00000091, + 0x000000b6, 0x000000e6, 0x00000122, 0x0000016d, + 0x000001cc, 0x00000244, 0x000002db, 0x00000399, + 0x00000489, 0x000005b6, 0x00000733, 0x00000912, + 0x00000b6d, 0x00000e66, 0x00001224, 0x000016db, + 0x00001ccc, 0x00002449, 0x00002db7, 0x00003999, + 0x00004892, 0x00005b6f, 0x00007333, 0x00009124, + 0x0000b6de, 0x0000e666, 0x00012249, 0x00016dbc, + 0x0001cccc, 0x00024492, 0x0002db79, 0x00039999, + 0x00048924, 0x0005b6f2, 0x00073333, 0x00091249, + 0x000b6de5, 0x000e6666, 0x00122492, 0x0016dbcb, + 0x001ccccc, 0x00244924, 0x002db796, 0x00399998, +}; + +static RK_U32 h264e_lambda_cvr[60] = { + 0x00000009, 0x0000000b, 0x0000000e, 0x00000011, + 0x00000016, 0x0000001b, 0x00000022, 0x0000002b, + 0x00000036, 0x00000045, 0x00000056, 0x0000006d, + 0x00000089, 0x000000ad, 0x000000da, 0x00000112, + 0x00000159, 0x000001b3, 0x00000224, 0x000002b3, + 0x00000366, 0x00000449, 0x00000566, 0x000006cd, + 0x00000891, 0x00000acb, 0x00000d9a, 0x000013c1, + 0x000018e4, 0x00001f5c, 0x00002783, 0x000031c8, + 0x00003eb8, 0x00004f06, 0x00006390, 0x00008e14, + 0x0000b302, 0x0000e18a, 0x00011c29, 0x00016605, + 0x0001c313, 0x00027ae1, 0x00031fe6, 0x0003efcf, + 0x0004f5c3, 0x0006e785, 0x0008b2ef, 0x000af5c3, + 0x000f1e7a, 0x00130c7f, 0x00180000, 0x001e3cf4, + 0x002618fe, 0x00300000, 0x003c79e8, 0x004c31fc, + 0x00600000, 0x0078f3d0, 0x009863f8, 0x0c000000, +}; + +static void setup_ext_line_bufs(HalH264eVepu511Ctx *ctx) +{ + if (ctx->ext_line_buf) + return; + + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_buf, + ctx->ext_line_buf_size); +} + +static void clear_ext_line_bufs(HalH264eVepu511Ctx *ctx) +{ + if (ctx->ext_line_buf) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + } +} + +static MPP_RET hal_h264e_vepu511_deinit(void *hal) +{ + HalH264eVepu511Ctx *p = (HalH264eVepu511Ctx *)hal; + + hal_h264e_dbg_func("enter %p\n", p); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + clear_ext_line_bufs(p); + + h264e_vepu_stream_amend_deinit(&p->amend); + + MPP_FREE(p->regs_set); + MPP_FREE(p->reorder); + MPP_FREE(p->marking); + MPP_FREE(p->poll_cfgs); + + if (p->ext_line_buf_grp) { + mpp_buffer_group_put(p->ext_line_buf_grp); + p->ext_line_buf_grp = NULL; + } + + if (p->hw_recn) { + hal_bufs_deinit(p->hw_recn); + p->hw_recn = NULL; + } + + if (p->roi_base_cfg_buf) { + mpp_buffer_put(p->roi_base_cfg_buf); + p->roi_base_cfg_buf = NULL; + p->roi_base_buf_size = 0; + } + + if (p->roi_grp) { + mpp_buffer_group_put(p->roi_grp); + p->roi_grp = NULL; + } + + if (p->offsets) { + mpp_dev_multi_offset_deinit(p->offsets); + p->offsets = NULL; + } + + if (p->buf_pass1) { + mpp_buffer_put(p->buf_pass1); + p->buf_pass1 = NULL; + } + + if (p->tune) { + // vepu511_h264e_tune_deinit(p->tune); + p->tune = NULL; + } + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu511_init(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu511Ctx *p = (HalH264eVepu511Ctx *)hal; + MPP_RET ret = MPP_OK; + RK_U32 i; + + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + + ret = hal_bufs_init(&p->hw_recn); + if (ret) { + mpp_err_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + p->regs_set = mpp_malloc(HalVepu511RegSet, 1); + if (NULL == p->regs_set) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init register buffer failed\n"); + goto DONE; + } + + p->reorder = mpp_malloc(H264eReorderInfo, 1); + if (NULL == p->reorder) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init reorder data failed\n"); + goto DONE; + } + + p->marking = mpp_malloc(H264eMarkingInfo, 1); + if (NULL == p->marking) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init marking data failed\n"); + goto DONE; + } + + p->poll_slice_max = 8; + p->poll_cfg_size = (sizeof(p->poll_cfgs) + sizeof(RK_S32) * p->poll_slice_max); + p->poll_cfgs = mpp_malloc_size(MppDevPollCfg, p->poll_cfg_size); + if (NULL == p->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init poll cfg buffer failed\n"); + goto DONE; + } + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 1; + hw->qp_delta_row = 2; + hw->extra_buf = 1; + hw->qbias_i = 683; + hw->qbias_p = 341; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, h264_aq_tthd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, h264_aq_tthd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, h264_I_aq_step_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, h264_P_aq_step_default, sizeof(hw->aq_step_p)); + + for (i = 0; i < MPP_ARRAY_ELEMS(hw->mode_bias); i++) + hw->mode_bias[i] = 8; + + hw->skip_sad = 8; + hw->skip_bias = 8; + } + + mpp_dev_multi_offset_init(&p->offsets, 24); + p->output_cb = cfg->output_cb; + cfg->cap_recn_out = 1; + h264e_vepu_stream_amend_init(&p->amend); + + // p->tune = vepu511_h264e_tune_init(p); + +DONE: + if (ret) + hal_h264e_vepu511_deinit(hal); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +/* + * NOTE: recon / refer buffer is FBC data buffer. + * And FBC data require extra 16 lines space for hardware io. + */ +static void setup_hal_bufs(HalH264eVepu511Ctx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + RK_S32 alignment_w = 64; + RK_S32 alignment_h = 16; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment_w); + RK_S32 aligned_h = MPP_ALIGN(prep->height, alignment_h) + 16; + RK_S32 pixel_buf_fbc_hdr_size = MPP_ALIGN(aligned_w * aligned_h / 64, SZ_8K); + RK_S32 pixel_buf_fbc_bdy_size = aligned_w * aligned_h * 3 / 2; + RK_S32 pixel_buf_size = pixel_buf_fbc_hdr_size + pixel_buf_fbc_bdy_size; + RK_S32 thumb_buf_size = MPP_ALIGN(aligned_w / 64 * aligned_h / 64 * 256, SZ_8K); + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + RK_S32 smear_size = 0; + RK_S32 smear_r_size = 0; + MppEncRefCfg ref_cfg = cfg->ref_cfg; + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + if (new_max_cnt < MPP_MAX(new_max_cnt, info->dpb_size + 1)) + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > SZ_4K) { + RK_S32 ctu_w = (aligned_w + 63) / 64; + RK_S32 ext_line_buf_size = ((ctu_w - 53) * 53 + 15) / 16 * 16 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + clear_ext_line_bufs(ctx); + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + + ctx->ext_line_buf_size = ext_line_buf_size; + setup_ext_line_bufs(ctx); + } else { + clear_ext_line_bufs(ctx); + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + smear_size = MPP_ALIGN(aligned_w, 1024) / 1024 * MPP_ALIGN(aligned_h, 16) / 16 * 16; + smear_r_size = MPP_ALIGN(aligned_h, 1024) / 1024 * MPP_ALIGN(aligned_w, 16) / 16 * 16; + smear_size = MPP_MAX(smear_size, smear_r_size); + + if ((ctx->pixel_buf_fbc_hdr_size != pixel_buf_fbc_hdr_size) || + (ctx->pixel_buf_fbc_bdy_size != pixel_buf_fbc_bdy_size) || + (ctx->pixel_buf_size != pixel_buf_size) || + (ctx->thumb_buf_size != thumb_buf_size) || + (ctx->smear_size != smear_size) || + (new_max_cnt > old_max_cnt)) { + size_t sizes[3]; + + hal_h264e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->pixel_buf_size, pixel_buf_size, + old_max_cnt, new_max_cnt); + + /* pixel buffer */ + sizes[0] = pixel_buf_size; + /* thumb buffer */ + sizes[1] = thumb_buf_size; + /* smear buffer */ + sizes[2] = smear_size; + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_bufs_setup(ctx->hw_recn, new_max_cnt, MPP_ARRAY_ELEMS(sizes), sizes); + + ctx->pixel_buf_fbc_hdr_size = pixel_buf_fbc_hdr_size; + ctx->pixel_buf_fbc_bdy_size = pixel_buf_fbc_bdy_size; + ctx->pixel_buf_size = pixel_buf_size; + ctx->thumb_buf_size = thumb_buf_size; + ctx->smear_size = smear_size; + ctx->max_buf_cnt = new_max_cnt; + } +} + +static MPP_RET hal_h264e_vepu511_prepare(void *hal) +{ + HalH264eVepu511Ctx *ctx = (HalH264eVepu511Ctx *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->hw_recn, i); + + prep->change_res = 0; + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_U32 update_vepu511_syntax(HalH264eVepu511Ctx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + ctx->dpb = desc->p; + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu511_get_task(void *hal, HalEncTask *task) +{ + HalH264eVepu511Ctx *ctx = (HalH264eVepu511Ctx *)hal; + MppEncCfgSet *cfg_set = ctx->cfg; + MppEncH264HwCfg *hw_cfg = &cfg_set->h264.hw_cfg; + RK_U32 updated = update_vepu511_syntax(ctx, &task->syntax); + EncFrmStatus *frm_status = &task->rc_task->frm; + H264eFrmInfo *frms = ctx->frms; + + hal_h264e_dbg_func("enter %p\n", hal); + + ctx->smart_en = (ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC); + ctx->qpmap_en = ctx->cfg->tune.deblur_en; + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) + setup_hal_bufs(ctx); + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(task->frame); + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA3, (void **)&ctx->osd_cfg.osd_data3, NULL); + } + + if (!frm_status->reencode) + ctx->last_frame_fb = ctx->feedback; + + if (ctx->dpb) { + h264e_dpb_hal_start(ctx->dpb, frms->curr_idx); + h264e_dpb_hal_start(ctx->dpb, frms->refr_idx); + } + + task->flags.curr_idx = frms->curr_idx; + task->flags.refr_idx = frms->refr_idx; + task->part_first = 1; + task->part_last = 0; + + /* if not VEPU1/2, update log2_max_frame_num_minus4 in hw_cfg */ + hw_cfg->hw_log2_max_frame_num_minus4 = ctx->sps->log2_max_frame_num_minus4; + hw_cfg->hw_poc_type = ctx->sps->pic_order_cnt_type; + + h264e_vepu_stream_amend_config(&ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static void setup_vepu511_normal(HalVepu511RegSet *regs) +{ + hal_h264e_dbg_func("enter\n"); + /* reg000 VERSION is read only */ + + /* reg001 ENC_STRT */ + regs->reg_ctl.enc_strt.lkt_num = 0; + regs->reg_ctl.enc_strt.vepu_cmd = 1; + + regs->reg_ctl.opt_strg.cke = 1; + regs->reg_ctl.opt_strg.resetn_hw_en = 1; + + /* reg002 ENC_CLR */ + regs->reg_ctl.enc_clr.safe_clr = 0; + regs->reg_ctl.enc_clr.force_clr = 0; + + /* reg004 INT_EN */ + regs->reg_ctl.int_en.enc_done_en = 1; + regs->reg_ctl.int_en.lkt_node_done_en = 1; + regs->reg_ctl.int_en.sclr_done_en = 1; + regs->reg_ctl.int_en.vslc_done_en = 0; + regs->reg_ctl.int_en.vbsf_oflw_en = 1; + regs->reg_ctl.int_en.vbuf_lens_en = 1; + regs->reg_ctl.int_en.enc_err_en = 1; + + regs->reg_ctl.int_en.wdg_en = 1; + regs->reg_ctl.int_en.vsrc_err_en = 1; + regs->reg_ctl.int_en.wdg_en = 1; + regs->reg_ctl.int_en.lkt_err_int_en = 1; + regs->reg_ctl.int_en.lkt_err_stop_en = 1; + regs->reg_ctl.int_en.lkt_force_stop_en = 1; + regs->reg_ctl.int_en.jslc_done_en = 1; + regs->reg_ctl.int_en.jbsf_oflw_en = 1; + regs->reg_ctl.int_en.jbuf_lens_en = 1; + regs->reg_ctl.int_en.dvbm_err_en = 0; + + /* reg005 INT_MSK */ + regs->reg_ctl.int_msk.enc_done_msk = 0; + regs->reg_ctl.int_msk.lkt_node_done_msk = 0; + regs->reg_ctl.int_msk.sclr_done_msk = 0; + regs->reg_ctl.int_msk.vslc_done_msk = 0; + regs->reg_ctl.int_msk.vbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.vbuf_lens_msk = 0; + regs->reg_ctl.int_msk.enc_err_msk = 0; + regs->reg_ctl.int_msk.vsrc_err_msk = 0; + regs->reg_ctl.int_msk.wdg_msk = 0; + regs->reg_ctl.int_msk.lkt_err_int_msk = 0; + regs->reg_ctl.int_msk.lkt_err_stop_msk = 0; + regs->reg_ctl.int_msk.lkt_force_stop_msk = 0; + regs->reg_ctl.int_msk.jslc_done_msk = 0; + regs->reg_ctl.int_msk.jbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.jbuf_lens_msk = 0; + regs->reg_ctl.int_msk.dvbm_err_msk = 0; + + /* reg006 INT_CLR is not set */ + /* reg007 INT_STA is read only */ + /* reg008 ~ reg0011 gap */ + regs->reg_ctl.enc_wdg.vs_load_thd = 0; + + /* reg015 DTRNS_MAP */ + regs->reg_ctl.dtrns_map.jpeg_bus_edin = 0; + regs->reg_ctl.dtrns_map.src_bus_edin = 0; + regs->reg_ctl.dtrns_map.meiw_bus_edin = 0; + regs->reg_ctl.dtrns_map.bsw_bus_edin = 7; + regs->reg_ctl.dtrns_map.lktw_bus_edin = 0; + regs->reg_ctl.dtrns_map.rec_nfbc_bus_edin = 0; + + regs->reg_ctl.dtrns_cfg.axi_brsp_cke = 0; + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET setup_vepu511_prep(HalVepu511RegSet *regs, MppEncPrepCfg *prep, HalEncTask *task) +{ + VepuFmtCfg cfg; + MppFrameFormat fmt = prep->format; + MPP_RET ret = vepu5xx_set_fmt(&cfg, fmt); + RK_U32 hw_fmt = cfg.format; + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + /* do nothing when color format is not supported */ + if (ret) + return ret; + + regs->reg_frm.enc_rsl.pic_wd8_m1 = MPP_ALIGN(prep->width, 16) / 8 - 1; + regs->reg_frm.src_fill.pic_wfill = MPP_ALIGN(prep->width, 16) - prep->width; + regs->reg_frm.enc_rsl.pic_hd8_m1 = MPP_ALIGN(prep->height, 16) / 8 - 1; + regs->reg_frm.src_fill.pic_hfill = MPP_ALIGN(prep->height, 16) - prep->height; + + regs->reg_ctl.dtrns_map.src_bus_edin = cfg.src_endian; + + regs->reg_frm.src_fmt.src_cfmt = hw_fmt; + regs->reg_frm.src_fmt.alpha_swap = cfg.alpha_swap; + regs->reg_frm.src_fmt.rbuv_swap = cfg.rbuv_swap; + regs->reg_frm.src_fmt.out_fmt = (hw_fmt == VEPU5xx_FMT_YUV400) ? 0 : 1; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + regs->reg_frm.src_proc.rkfbcd_en = 1; + + y_stride = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!y_stride) + y_stride = MPP_ALIGN(prep->hor_stride, 64) >> 2; + } else if (prep->hor_stride) { + y_stride = prep->hor_stride; + } else { + if (hw_fmt == VEPU5xx_FMT_BGRA8888 ) + y_stride = prep->width * 4; + else if (hw_fmt == VEPU5xx_FMT_BGR888 ) + y_stride = prep->width * 3; + else if (hw_fmt == VEPU5xx_FMT_BGR565 || + hw_fmt == VEPU5xx_FMT_YUYV422 || + hw_fmt == VEPU5xx_FMT_UYVY422) + y_stride = prep->width * 2; + else + y_stride = prep->width; + } + + switch (hw_fmt) { + case VEPU5xx_FMT_YUV444SP : { + c_stride = y_stride * 2; + } break; + case VEPU5xx_FMT_YUV422SP : + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV444P : { + c_stride = y_stride; + } break; + default : { + c_stride = y_stride / 2; + } break; + } + + if (hw_fmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = get_rgb2yuv_cfg(prep->range, prep->color); + + hal_h264e_dbg_flow("input color range %d colorspace %d", prep->range, prep->color); + + regs->reg_frm.src_udfy.csc_wgt_b2y = 29; + regs->reg_frm.src_udfy.csc_wgt_g2y = 150; + regs->reg_frm.src_udfy.csc_wgt_r2y = 77; + + regs->reg_frm.src_udfu.csc_wgt_b2u = 128; + regs->reg_frm.src_udfu.csc_wgt_g2u = -85; + regs->reg_frm.src_udfu.csc_wgt_r2u = -43; + + regs->reg_frm.src_udfv.csc_wgt_b2v = -21; + regs->reg_frm.src_udfv.csc_wgt_g2v = -107; + regs->reg_frm.src_udfv.csc_wgt_r2v = 128; + + regs->reg_frm.src_udfo.csc_ofst_y = 0; + regs->reg_frm.src_udfo.csc_ofst_u = 128; + regs->reg_frm.src_udfo.csc_ofst_v = 128; + + hal_h264e_dbg_flow("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } else { + regs->reg_frm.src_udfy.csc_wgt_b2y = cfg.weight[0]; + regs->reg_frm.src_udfy.csc_wgt_g2y = cfg.weight[1]; + regs->reg_frm.src_udfy.csc_wgt_r2y = cfg.weight[2]; + + regs->reg_frm.src_udfu.csc_wgt_b2u = cfg.weight[3]; + regs->reg_frm.src_udfu.csc_wgt_g2u = cfg.weight[4]; + regs->reg_frm.src_udfu.csc_wgt_r2u = cfg.weight[5]; + + regs->reg_frm.src_udfv.csc_wgt_b2v = cfg.weight[6]; + regs->reg_frm.src_udfv.csc_wgt_g2v = cfg.weight[7]; + regs->reg_frm.src_udfv.csc_wgt_r2v = cfg.weight[8]; + + regs->reg_frm.src_udfo.csc_ofst_y = cfg.offset[0]; + regs->reg_frm.src_udfo.csc_ofst_u = cfg.offset[1]; + regs->reg_frm.src_udfo.csc_ofst_v = cfg.offset[2]; + } + + regs->reg_frm.src_strd0.src_strd0 = y_stride; + regs->reg_frm.src_strd1.src_strd1 = c_stride; + + regs->reg_frm.src_proc.src_mirr = prep->mirroring > 0; + regs->reg_frm.src_proc.src_rot = prep->rotation; + + regs->reg_frm.src_proc.tile4x4_en = 0; + regs->reg_frm.sli_cfg.mv_v_lmt_thd = 0; + regs->reg_frm.sli_cfg.mv_v_lmt_en = 0; + + regs->reg_frm.pic_ofst.pic_ofst_y = 0; + regs->reg_frm.pic_ofst.pic_ofst_x = 0; + + hal_h264e_dbg_func("leave\n"); + + return ret; +} + +static MPP_RET vepu511_h264e_save_pass1_patch(HalVepu511RegSet *regs, HalH264eVepu511Ctx *ctx) +{ + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + regs->reg_frm.enc_pic.cur_frm_ref = 1; + regs->reg_frm.rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + regs->reg_frm.rfpw_b_addr = regs->reg_frm.rfpw_h_addr; + regs->reg_frm.enc_pic.rec_fbc_dis = 1; + regs->reg_frm.me_ref_comb.rfpw_mode = 0; + + mpp_dev_multi_offset_update(ctx->offsets, 164, width_align * height_align); + + /* NOTE: disable split to avoid lowdelay slice output */ + regs->reg_frm.sli_splt.sli_splt = 0; + regs->reg_frm.enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu511_h264e_use_pass1_patch(HalVepu511RegSet *regs, HalH264eVepu511Ctx *ctx) +{ + RK_S32 fd_in = mpp_buffer_get_fd(ctx->buf_pass1); + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + RK_S32 y_stride = width_align; + + hal_h264e_dbg_func("enter\n"); + + regs->reg_frm.enc_pic.rfpr_compress_mode = 1; + regs->reg_frm.src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + regs->reg_frm.src_fmt.alpha_swap = 0; + regs->reg_frm.src_fmt.rbuv_swap = 0; + regs->reg_frm.src_fmt.out_fmt = 1; + + regs->reg_frm.src_strd0.src_strd0 = y_stride; + regs->reg_frm.src_strd1.src_strd1 = y_stride; + + regs->reg_frm.src_proc.src_mirr = 0; + regs->reg_frm.src_proc.src_rot = 0; + regs->reg_frm.src_proc.rkfbcd_en = 0; + + regs->reg_frm.pic_ofst.pic_ofst_y = 0; + regs->reg_frm.pic_ofst.pic_ofst_x = 0; + + regs->reg_frm.adr_src0 = fd_in; + regs->reg_frm.adr_src1 = fd_in; + regs->reg_frm.adr_src2 = 0; + + mpp_dev_multi_offset_update(ctx->offsets, 161, width_align * height_align); + + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + +static void setup_vepu511_codec(HalVepu511RegSet *regs, HalH264eVepu511Ctx *ctx) +{ + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + + hal_h264e_dbg_func("enter\n"); + + regs->reg_frm.enc_pic.enc_stnd = 0; + regs->reg_frm.enc_pic.cur_frm_ref = slice->nal_reference_idc > 0; + regs->reg_frm.enc_pic.bs_scp = 1; + + regs->reg_frm.synt_nal.nal_ref_idc = slice->nal_reference_idc; + regs->reg_frm.synt_nal.nal_unit_type = slice->nalu_type; + + regs->reg_frm.synt_sps.max_fnum = sps->log2_max_frame_num_minus4; + regs->reg_frm.synt_sps.drct_8x8 = sps->direct8x8_inference; + regs->reg_frm.synt_sps.mpoc_lm4 = sps->log2_max_poc_lsb_minus4; + regs->reg_frm.synt_sps.poc_type = sps->pic_order_cnt_type; + regs->reg_frm.synt_pps.etpy_mode = pps->entropy_coding_mode; + regs->reg_frm.synt_pps.trns_8x8 = pps->transform_8x8_mode; + regs->reg_frm.synt_pps.csip_flag = pps->constrained_intra_pred; + regs->reg_frm.synt_pps.num_ref0_idx = pps->num_ref_idx_l0_default_active - 1; + regs->reg_frm.synt_pps.num_ref1_idx = pps->num_ref_idx_l1_default_active - 1; + regs->reg_frm.synt_pps.pic_init_qp = pps->pic_init_qp; + regs->reg_frm.synt_pps.cb_ofst = pps->chroma_qp_index_offset; + regs->reg_frm.synt_pps.cr_ofst = pps->second_chroma_qp_index_offset; + regs->reg_frm.synt_pps.dbf_cp_flg = pps->deblocking_filter_control; + + regs->reg_frm.synt_sli0.sli_type = (slice->slice_type == H264_I_SLICE) ? (2) : (0); + regs->reg_frm.synt_sli0.pps_id = slice->pic_parameter_set_id; + regs->reg_frm.synt_sli0.drct_smvp = 0; + regs->reg_frm.synt_sli0.num_ref_ovrd = slice->num_ref_idx_override; + regs->reg_frm.synt_sli0.cbc_init_idc = slice->cabac_init_idc; + regs->reg_frm.synt_sli0.frm_num = slice->frame_num; + + regs->reg_frm.synt_sli1.idr_pid = (slice->slice_type == H264_I_SLICE) ? slice->idr_pic_id : (RK_U32)(-1); + regs->reg_frm.synt_sli1.poc_lsb = slice->pic_order_cnt_lsb; + + regs->reg_frm.synt_sli2.dis_dblk_idc = slice->disable_deblocking_filter_idc; + regs->reg_frm.synt_sli2.sli_alph_ofst = slice->slice_alpha_c0_offset_div2; + + h264e_reorder_rd_rewind(slice->reorder); + { /* reorder process */ + H264eRplmo rplmo; + MPP_RET ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + if (MPP_OK == ret) { + regs->reg_frm.synt_sli2.ref_list0_rodr = 1; + regs->reg_frm.synt_sli2.rodr_pic_idx = rplmo.modification_of_pic_nums_idc; + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + regs->reg_frm.synt_sli2.rodr_pic_num = rplmo.abs_diff_pic_num_minus1; + } break; + case 2 : { + regs->reg_frm.synt_sli2.rodr_pic_num = rplmo.long_term_pic_idx; + } break; + default : { + mpp_loge_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + } else { + // slice->ref_pic_list_modification_flag; + regs->reg_frm.synt_sli2.ref_list0_rodr = 0; + regs->reg_frm.synt_sli2.rodr_pic_idx = 0; + regs->reg_frm.synt_sli2.rodr_pic_num = 0; + } + } + + /* clear all mmco arg first */ + regs->reg_frm.synt_refm0.nopp_flg = 0; + regs->reg_frm.synt_refm0.ltrf_flg = 0; + regs->reg_frm.synt_refm0.arpm_flg = 0; + regs->reg_frm.synt_refm0.mmco4_pre = 0; + regs->reg_frm.synt_refm0.mmco_type0 = 0; + regs->reg_frm.synt_refm0.mmco_parm0 = 0; + regs->reg_frm.synt_refm0.mmco_type1 = 0; + regs->reg_frm.synt_refm1.mmco_parm1 = 0; + regs->reg_frm.synt_refm0.mmco_type2 = 0; + regs->reg_frm.synt_refm1.mmco_parm2 = 0; + regs->reg_frm.synt_refm2.long_term_frame_idx0 = 0; + regs->reg_frm.synt_refm2.long_term_frame_idx1 = 0; + regs->reg_frm.synt_refm2.long_term_frame_idx2 = 0; + + h264e_marking_rd_rewind(slice->marking); + + /* only update used parameter */ + if (slice->slice_type == H264_I_SLICE) { + regs->reg_frm.synt_refm0.nopp_flg = slice->no_output_of_prior_pics; + regs->reg_frm.synt_refm0.ltrf_flg = slice->long_term_reference_flag; + } else { + if (!h264e_marking_is_empty(slice->marking)) { + H264eMmco mmco; + + regs->reg_frm.synt_refm0.arpm_flg = 1; + + /* max 3 mmco */ + do { + RK_S32 type = 0; + RK_S32 param_0 = 0; + RK_S32 param_1 = 0; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_loge_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_frm.synt_refm0.mmco_type0 = type; + regs->reg_frm.synt_refm0.mmco_parm0 = param_0; + regs->reg_frm.synt_refm2.long_term_frame_idx0 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_loge_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_frm.synt_refm0.mmco_type1 = type; + regs->reg_frm.synt_refm1.mmco_parm1 = param_0; + regs->reg_frm.synt_refm2.long_term_frame_idx1 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_loge_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_frm.synt_refm0.mmco_type2 = type; + regs->reg_frm.synt_refm1.mmco_parm2 = param_0; + regs->reg_frm.synt_refm2.long_term_frame_idx2 = param_1; + } while (0); + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511_rdo_pred(HalH264eVepu511Ctx *ctx) +{ + HalVepu511RegSet *regs = ctx->regs_set; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + RK_S32 lambda_idx = 0; + + hal_h264e_dbg_func("enter\n"); + + /* + * H264 Mode Mask of Mode Decision. + * More prediction modes lead to better compression performance but increase computational cycles. + * + * Default speed preset configuration to 0.67 PPC, ~40 FPS for 4K resolution at 500MHz: + * - Set i4/i16 partition RDO numbers to 1 for P-frames and all other CU RDO numbers to 2. + * - Set cime_fuse = 0, enable dual-window search for higher compression performance. + * - Set fme_lvl_mrg = 1, enable FME's depth1 and depth2 joint search, + * improves real-time performance but will reduce the compression ratio. + * - Set cime_srch_lftw/rgtw/uph/dwnh = 12/12/15/15, expand CIME search range degraded real-time performance. + * - Set rime_prelvl_en = 0, disable RIME pre-level to improve real-time performance. + */ + switch (ctx->cfg->tune.speed) { + default : + case 0 : { + // FULL RDO MODE, 0.63ppc + regs->reg_frm.rdo_mark_mode.p16_interp_num = 3; + regs->reg_frm.rdo_mark_mode.p16t8_rdo_num = 3; + regs->reg_frm.rdo_mark_mode.p16t4_rmd_num = 2; + regs->reg_frm.rdo_mark_mode.p8_interp_num = 3; + regs->reg_frm.rdo_mark_mode.p8t8_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.p8t4_rmd_num = 2; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 2; + if (slice->slice_type == H264_I_SLICE) { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 2; + } else { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + } + } break; + case 1 : { + // 0.69ppc + regs->reg_frm.rdo_mark_mode.p16_interp_num = 2; + regs->reg_frm.rdo_mark_mode.p16t8_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.p16t4_rmd_num = 2; + regs->reg_frm.rdo_mark_mode.p8_interp_num = 2; + regs->reg_frm.rdo_mark_mode.p8t8_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.p8t4_rmd_num = 2; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + if (slice->slice_type == H264_I_SLICE) { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 2; + } else { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + } + } break; + case 2 : { + // 0.71 + regs->reg_frm.rdo_mark_mode.p16_interp_num = 2; + regs->reg_frm.rdo_mark_mode.p16t8_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.p16t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.p8_interp_num = 2; + regs->reg_frm.rdo_mark_mode.p8t8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.p8t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + if (slice->slice_type == H264_I_SLICE) { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 2; + } else { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 1; + } + } break; + case 3 : { + // 0.73ppc + regs->reg_frm.rdo_mark_mode.p16_interp_num = 2; + regs->reg_frm.rdo_mark_mode.p16t8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.p16t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.p8_interp_num = 2; + regs->reg_frm.rdo_mark_mode.p8t8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.p8t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + if (slice->slice_type == H264_I_SLICE) { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 2; + } else { + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 1; + } + } break; + } + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + lambda_idx = ctx->cfg->tune.lambda_idx_i; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = (sm == MPP_ENC_SCENE_MODE_IPC) ? 9 : 6; + lambda_idx = ctx->cfg->tune.lambda_idx_p; + } + + if (sm == MPP_ENC_SCENE_MODE_IPC || sm == MPP_ENC_SCENE_MODE_IPC_PTZ) + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, &h264e_lambda_default[lambda_idx], + H264E_LAMBDA_TAB_SIZE); + else + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, &h264e_lambda_cvr[lambda_idx], + H264E_LAMBDA_TAB_SIZE); + + regs->reg_frm.rdo_cfg.rect_size = (sps->profile_idc == H264_PROFILE_BASELINE && + sps->level_idc <= H264_LEVEL_3_0) ? 1 : 0; + regs->reg_frm.rdo_cfg.vlc_lmt = (sps->profile_idc < H264_PROFILE_MAIN) && + !pps->entropy_coding_mode; + regs->reg_frm.rdo_cfg.ccwa_e = 1; + regs->reg_frm.rdo_cfg.scl_lst_sel = pps->pic_scaling_matrix_present; + regs->reg_frm.rdo_cfg.atf_e = ctx->cfg->tune.atf_str > 0; + regs->reg_frm.rdo_cfg.atr_e = ctx->cfg->tune.atr_str_i > 0; + regs->reg_frm.rdo_cfg.atr_mult_sel_e = 1; + regs->reg_frm.rdo_mark_mode.rdo_mark_mode = 0; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511_rc_base(HalVepu511RegSet *regs, HalH264eVepu511Ctx *ctx, EncRcTask *rc_task) +{ + H264eSps *sps = ctx->sps; + H264eSlice *slice = ctx->slice; + MppEncCfgSet *cfg = ctx->cfg; + MppEncHwCfg *hw = &cfg->hw; + EncRcTaskInfo *rc_info = &rc_task->info; + RK_S32 mb_w = sps->pic_width_in_mbs; + RK_S32 mb_h = sps->pic_height_in_mbs; + RK_U32 qp_target = rc_info->quality_target; + RK_U32 qp_min = rc_info->quality_min; + RK_U32 qp_max = rc_info->quality_max; + RK_S32 mb_target_bits_mul_16 = (rc_info->bit_target << 4) / (mb_w * mb_h); + RK_S32 mb_target_bits; + RK_S32 negative_bits_thd; + RK_S32 positive_bits_thd; + + hal_h264e_dbg_rc("bittarget %d qp [%d %d %d]\n", rc_info->bit_target, + qp_min, qp_target, qp_max); + + hal_h264e_dbg_func("enter\n"); + + if (mb_target_bits_mul_16 >= 0x100000) + mb_target_bits_mul_16 = 0x50000; + + mb_target_bits = (mb_target_bits_mul_16 * mb_w) >> 4; + negative_bits_thd = 0 - 5 * mb_target_bits / 16; + positive_bits_thd = 5 * mb_target_bits / 16; + + regs->reg_frm.enc_pic.pic_qp = qp_target; + regs->reg_frm.rc_cfg.rc_en = 1; + regs->reg_frm.rc_cfg.aq_en = 1; + regs->reg_frm.rc_cfg.rc_ctu_num = mb_w; + regs->reg_frm.rc_qp.rc_max_qp = qp_max; + regs->reg_frm.rc_qp.rc_min_qp = qp_min; + regs->reg_frm.rc_tgt.ctu_ebit = mb_target_bits_mul_16; + + if (ctx->smart_en) + regs->reg_frm.rc_qp.rc_qp_range = 0; + else + regs->reg_frm.rc_qp.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? + hw->qp_delta_row_i : hw->qp_delta_row; + + { + MppEncRcCfg *rc = &ctx->cfg->rc; + RK_S32 fqp_min, fqp_max; + + if (slice->slice_type == H264_I_SLICE) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 1) && (fqp_max <= 51)) { + regs->reg_frm.enc_pic.pic_qp = fqp_min; + regs->reg_frm.rc_qp.rc_qp_range = 0; + } + } + + regs->reg_rc_roi.rc_adj0.qp_adj0 = -2; + regs->reg_rc_roi.rc_adj0.qp_adj1 = -1; + regs->reg_rc_roi.rc_adj0.qp_adj2 = 0; + regs->reg_rc_roi.rc_adj0.qp_adj3 = 1; + regs->reg_rc_roi.rc_adj0.qp_adj4 = 2; + regs->reg_rc_roi.rc_adj1.qp_adj5 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj6 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj7 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj8 = 0; + + regs->reg_rc_roi.rc_dthd_0_8[0] = 4 * negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[1] = negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[2] = positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[3] = 4 * positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[4] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[5] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[6] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[7] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[8] = 0x7FFFFFFF; + + regs->reg_rc_roi.roi_qthd0.qpmin_area0 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area0 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area1 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area1 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area2 = qp_min; + + regs->reg_rc_roi.roi_qthd1.qpmax_area2 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area3 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area3 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area4 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area4 = qp_max; + + regs->reg_rc_roi.roi_qthd2.qpmin_area5 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area5 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area6 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area6 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area7 = qp_min; + + regs->reg_rc_roi.roi_qthd3.qpmax_area7 = qp_max; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511_io_buf(HalVepu511RegSet *regs, MppDevRegOffCfgs *offsets, + HalEncTask *task) +{ + MppFrame frm = task->frame; + MppPacket pkt = task->packet; + MppBuffer buf_in = mpp_frame_get_buffer(frm); + MppBuffer buf_out = task->output; + MppFrameFormat fmt = mpp_frame_get_fmt(frm); + RK_S32 hor_stride = mpp_frame_get_hor_stride(frm); + RK_S32 ver_stride = mpp_frame_get_ver_stride(frm); + RK_S32 fd_in = mpp_buffer_get_fd(buf_in); + RK_U32 off_in[2] = {0}; + RK_U32 off_out = mpp_packet_get_length(pkt); + size_t siz_out = mpp_buffer_get_size(buf_out); + RK_S32 fd_out = mpp_buffer_get_fd(buf_out); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_frm.adr_src0 = fd_in; + regs->reg_frm.adr_src1 = fd_in; + regs->reg_frm.adr_src2 = fd_in; + + regs->reg_frm.bsbt_addr = fd_out; + regs->reg_frm.bsbb_addr = fd_out; + regs->reg_frm.bsbs_addr = fd_out; + regs->reg_frm.bsbr_addr = fd_out; + + regs->reg_frm.rfpt_h_addr = 0xffffffff; + regs->reg_frm.rfpb_h_addr = 0; + regs->reg_frm.rfpt_b_addr = 0xffffffff; + regs->reg_frm.rfpb_b_addr = 0; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + off_in[0] = mpp_frame_get_fbc_offset(task->frame);; + off_in[1] = off_in[0]; + } else if (MPP_FRAME_FMT_IS_YUV(fmt)) { + VepuFmtCfg cfg; + + vepu5xx_set_fmt(&cfg, fmt); + switch (cfg.format) { + case VEPU5xx_FMT_BGRA8888 : + case VEPU5xx_FMT_BGR888 : + case VEPU5xx_FMT_BGR565 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV422SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV422P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 3 / 2; + } break; + case VEPU5xx_FMT_YUV420P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 5 / 4; + } break; + case VEPU5xx_FMT_YUV400 : + case VEPU5xx_FMT_YUYV422 : + case VEPU5xx_FMT_UYVY422 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 2; + } break; + default : { + off_in[0] = 0; + off_in[1] = 0; + } break; + } + } + + mpp_dev_multi_offset_update(offsets, 161, off_in[0]); + mpp_dev_multi_offset_update(offsets, 162, off_in[1]); + mpp_dev_multi_offset_update(offsets, 172, siz_out); + mpp_dev_multi_offset_update(offsets, 174, off_out); + + regs->reg_frm.meiw_addr = task->md_info ? mpp_buffer_get_fd(task->md_info) : 0; + regs->reg_frm.enc_pic.mei_stor = 0; + regs->reg_frm.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg_frm.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET vepu511_h264_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h) +{ + Vepu511RoiH264BsCfg *ptr = (Vepu511RoiH264BsCfg *)buf; + RK_S32 mb_w = MPP_ALIGN(w, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(h, 16) / 16; + RK_S32 stride_h = MPP_ALIGN(mb_w, 4); + Vepu511RoiH264BsCfg cfg; + MPP_RET ret = MPP_NOK; + + if (NULL == buf || NULL == region) { + mpp_err_f("invalid buf %p roi %p\n", buf, region); + goto DONE; + } + + RK_S32 roi_width = (region->w + 15) / 16; + RK_S32 roi_height = (region->h + 15) / 16; + RK_S32 pos_x_init = region->x / 16; + RK_S32 pos_y_init = region->y / 16; + RK_S32 pos_x_end = pos_x_init + roi_width; + RK_S32 pos_y_end = pos_y_init + roi_height; + RK_S32 x, y; + + pos_x_end = MPP_MIN(pos_x_end, mb_w); + pos_y_end = MPP_MIN(pos_y_end, mb_h); + pos_x_init = MPP_MAX(pos_x_init, 0); + pos_y_init = MPP_MAX(pos_y_init, 0); + + mpp_assert(pos_x_end > pos_x_init); + mpp_assert(pos_y_end > pos_y_init); + + cfg.force_intra = 1; + + ptr += pos_y_init * stride_h + pos_x_init; + roi_width = pos_x_end - pos_x_init; + roi_height = pos_y_end - pos_y_init; + + for (y = 0; y < roi_height; y++) { + Vepu511RoiH264BsCfg *dst = ptr; + + for (x = 0; x < roi_width; x++, dst++) + memcpy(dst, &cfg, sizeof(cfg)); + + ptr += stride_h; + } +DONE: + return ret; +} + +static MPP_RET setup_vepu511_intra_refresh(HalVepu511RegSet *regs, HalH264eVepu511Ctx *ctx, RK_U32 refresh_idx) +{ + MPP_RET ret = MPP_OK; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 w = mb_w * 16; + RK_U32 h = mb_h * 16; + MppEncROIRegion *region = NULL; + RK_U32 refresh_num = ctx->cfg->rc.refresh_num; + RK_U32 stride_h = MPP_ALIGN(mb_w, 4); + RK_U32 stride_v = MPP_ALIGN(mb_h, 4); + RK_U32 roi_base_buf_size = stride_h * stride_v * 8; + RK_U32 i = 0; + + hal_h264e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en) { + ret = MPP_ERR_VALUE; + goto RET; + } + + if (NULL == ctx->roi_base_cfg_buf) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + mpp_buffer_get(ctx->roi_grp, &ctx->roi_base_cfg_buf, roi_base_buf_size); + ctx->roi_base_buf_size = roi_base_buf_size; + } + + mpp_assert(ctx->roi_base_cfg_buf); + void *base_cfg_buf = mpp_buffer_get_ptr(ctx->roi_base_cfg_buf); + Vepu511RoiH264BsCfg base_cfg; + Vepu511RoiH264BsCfg *base_cfg_ptr = (Vepu511RoiH264BsCfg *)base_cfg_buf; + + base_cfg.force_intra = 0; + base_cfg.qp_adj_en = 1; + + for (i = 0; i < stride_h * stride_v; i++, base_cfg_ptr++) + memcpy(base_cfg_ptr, &base_cfg, sizeof(base_cfg)); + + region = mpp_calloc(MppEncROIRegion, 1); + + if (NULL == region) { + mpp_err_f("Failed to calloc for MppEncROIRegion !\n"); + ret = MPP_ERR_MALLOC; + } + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + region->x = 0; + region->w = w; + if (refresh_idx > 0) { + region->y = refresh_idx * 16 * refresh_num - 32; + region->h = 16 * refresh_num + 32; + } else { + region->y = refresh_idx * 16 * refresh_num; + region->h = 16 * refresh_num; + } + regs->reg_frm.me_rnge.cime_srch_uph = 1; + } else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) { + region->y = 0; + region->h = h; + if (refresh_idx > 0) { + region->x = refresh_idx * 16 * refresh_num - 32; + region->w = 16 * refresh_num + 32; + } else { + region->x = refresh_idx * 16 * refresh_num; + region->w = 16 * refresh_num; + } + regs->reg_frm.me_rnge.cime_srch_dwnh = 1; + } + + region->intra = 1; + region->quality = -ctx->cfg->rc.qp_delta_ip; + + region->area_map_en = 1; + region->qp_area_idx = 1; + region->abs_qp_en = 0; + + vepu511_h264_set_one_roi(base_cfg_buf, region, w, h); + mpp_free(region); +RET: + hal_h264e_dbg_func("leave, ret %d\n", ret); + return ret; +} + +static void setup_vepu511_recn_refr(HalH264eVepu511Ctx *ctx, HalVepu511RegSet *regs) +{ + + H264eFrmInfo *frms = ctx->frms; + HalBufs bufs = ctx->hw_recn; + RK_S32 fbc_hdr_size = ctx->pixel_buf_fbc_hdr_size; + + HalBuf *curr = hal_bufs_get_buf(bufs, frms->curr_idx); + HalBuf *refr = hal_bufs_get_buf(bufs, frms->refr_idx); + + hal_h264e_dbg_func("enter\n"); + + if (curr && curr->cnt) { + MppBuffer buf_pixel = curr->buf[0]; + MppBuffer buf_thumb = curr->buf[1]; + MppBuffer buf_smear = curr->buf[2]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg_frm.rfpw_h_addr = fd; + regs->reg_frm.rfpw_b_addr = fd; + regs->reg_frm.dspw_addr = mpp_buffer_get_fd(buf_thumb); + regs->reg_frm.adr_smear_wr = mpp_buffer_get_fd(buf_smear); + } + + if (refr && refr->cnt) { + MppBuffer buf_pixel = refr->buf[0]; + MppBuffer buf_thumb = refr->buf[1]; + MppBuffer buf_smear = refr->buf[2]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg_frm.rfpr_h_addr = fd; + regs->reg_frm.rfpr_b_addr = fd; + regs->reg_frm.dspr_addr = mpp_buffer_get_fd(buf_thumb); + regs->reg_frm.adr_smear_rd = mpp_buffer_get_fd(buf_smear); + } + mpp_dev_multi_offset_update(ctx->offsets, 164, fbc_hdr_size); + mpp_dev_multi_offset_update(ctx->offsets, 166, fbc_hdr_size); + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511_split(HalVepu511RegSet *regs, MppEncCfgSet *enc_cfg) +{ + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h264e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_frm.sli_splt.sli_splt = 0; + regs->reg_frm.sli_splt.sli_splt_mode = 0; + regs->reg_frm.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.sli_splt.sli_max_num_m1 = 0; + regs->reg_frm.sli_splt.sli_flsh = 0; + regs->reg_frm.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.sli_byte.sli_splt_byte = 0; + regs->reg_frm.enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_frm.sli_splt.sli_splt = 1; + regs->reg_frm.sli_splt.sli_splt_mode = 0; + regs->reg_frm.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.sli_splt.sli_flsh = 1; + regs->reg_frm.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.sli_byte.sli_splt_byte = cfg->split_arg; + regs->reg_frm.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = (cfg->split_out != 0) ? 1 : 0; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + regs->reg_frm.sli_splt.sli_splt = 1; + regs->reg_frm.sli_splt.sli_splt_mode = 1; + regs->reg_frm.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.sli_splt.sli_flsh = 1; + regs->reg_frm.sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg_frm.sli_byte.sli_splt_byte = 0; + regs->reg_frm.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + if (cfg->split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) + regs->reg_ctl.int_en.vslc_done_en = 1; + } break; + default : { + mpp_logi_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511_me(HalH264eVepu511Ctx *ctx) +{ + HalVepu511RegSet *regs = ctx->regs_set; + Vepu511FrameCfg *reg_frm = ®s->reg_frm; + Vepu511Param *reg_param = ®s->reg_param; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->me_rnge.cime_srch_dwnh = 15; + reg_frm->me_rnge.cime_srch_uph = 15; + reg_frm->me_rnge.cime_srch_rgtw = 12; + reg_frm->me_rnge.cime_srch_lftw = 12; + reg_frm->me_cfg.rme_srch_h = 3; + reg_frm->me_cfg.rme_srch_v = 3; + + reg_frm->me_cfg.srgn_max_num = 72; + reg_frm->me_cfg.cime_dist_thre = 1024; + reg_frm->me_cfg.rme_dis = 0; + reg_frm->me_cfg.fme_dis = 0; + reg_frm->me_rnge.dlt_frm_num = 0x0; + reg_frm->me_cach.cime_zero_thre = 64; + + /* CIME: 0x1760 - 0x176C */ + reg_param->me_sqi_cfg.cime_pmv_num = 1; + reg_param->me_sqi_cfg.cime_fuse = 0; + reg_param->me_sqi_cfg.move_lambda = 0; + reg_param->me_sqi_cfg.rime_lvl_mrg = 1; + reg_param->me_sqi_cfg.rime_prelvl_en = 3; + reg_param->me_sqi_cfg.rime_prersu_en = 0; + reg_param->me_sqi_cfg.fme_lvl_mrg = 0; + reg_param->cime_mvd_th.cime_mvd_th0 = 16; + reg_param->cime_mvd_th.cime_mvd_th1 = 48; + reg_param->cime_mvd_th.cime_mvd_th2 = 80; + reg_param->cime_madp_th.cime_madp_th = 16; + reg_param->cime_madp_th.ratio_consi_cfg = 13; + reg_param->cime_madp_th.ratio_bmv_dist = 9; + reg_param->cime_multi.cime_multi0 = 8; + reg_param->cime_multi.cime_multi1 = 12; + reg_param->cime_multi.cime_multi2 = 16; + reg_param->cime_multi.cime_multi3 = 20; + + /* RFME: 0x1770 - 0x1778 */ + reg_param->rime_mvd_th.rime_mvd_th0 = 1; + reg_param->rime_mvd_th.rime_mvd_th1 = 2; + reg_param->rime_mvd_th.fme_madp_th = 0; + reg_param->rime_madp_th.rime_madp_th0 = 8; + reg_param->rime_madp_th.rime_madp_th1 = 16; + reg_param->rime_multi.rime_multi0 = 4; + reg_param->rime_multi.rime_multi1 = 8; + reg_param->rime_multi.rime_multi2 = 12; + + if (sm != MPP_ENC_SCENE_MODE_IPC) { + /* disable subjective optimization */ + reg_param->cime_madp_th.cime_madp_th = 0; + reg_param->rime_madp_th.rime_madp_th0 = 0; + reg_param->rime_madp_th.rime_madp_th1 = 0; + reg_param->cime_multi.cime_multi0 = 4; + reg_param->cime_multi.cime_multi1 = 4; + reg_param->cime_multi.cime_multi2 = 4; + reg_param->cime_multi.cime_multi3 = 4; + reg_param->rime_multi.rime_multi0 = 4; + reg_param->rime_multi.rime_multi1 = 4; + reg_param->rime_multi.rime_multi2 = 4; + } + + /* 0x177C */ + reg_param->cmv_st_th.cmv_th0 = 64; + reg_param->cmv_st_th.cmv_th1 = 96; + reg_param->cmv_st_th.cmv_th2 = 128; + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; + + hal_h264e_dbg_func("leave\n"); +} + +static void +setup_vepu511_l2(HalH264eVepu511Ctx *ctx) +{ + HalVepu511RegSet *regs = ctx->regs_set; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + RK_S32 lambda_idx = ctx->cfg->tune.lambda_idx_i; //TODO: lambda_idx_p + + hal_h264e_dbg_func("enter\n"); + + if (sm == MPP_ENC_SCENE_MODE_IPC) { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_default[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } else { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_cvr[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511_ext_line_buf(HalVepu511RegSet *regs, HalH264eVepu511Ctx *ctx) +{ + MppDevRcbInfoCfg rcb_cfg; + RK_S32 offset = 0; + RK_S32 fd; + + if (!ctx->ext_line_buf) { + regs->reg_frm.ebufb_addr = 0; + regs->reg_frm.ebuft_addr = 0; + return; + } + + fd = mpp_buffer_get_fd(ctx->ext_line_buf); + offset = ctx->ext_line_buf_size; + + regs->reg_frm.ebufb_addr = fd; + regs->reg_frm.ebuft_addr = fd; + + mpp_dev_multi_offset_update(ctx->offsets, 178, offset); + + /* rcb info for sram */ + rcb_cfg.reg_idx = 179; + rcb_cfg.size = offset; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); + + rcb_cfg.reg_idx = 178; + rcb_cfg.size = 0; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); +} + +static void setup_vepu511_aq(HalH264eVepu511Ctx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncHwCfg *hw = &cfg->hw; + Vepu511RcRoiCfg *s = &ctx->regs_set->reg_rc_roi; + RK_S32 *aq_step, *aq_thd; + + if (ctx->slice->slice_type == H264_I_SLICE) { + aq_thd = (RK_S32 *)&hw->aq_thrd_i[0]; + aq_step = &hw->aq_step_i[0]; + } else { + aq_thd = (RK_S32 *)&hw->aq_thrd_p[0]; + aq_step = &hw->aq_step_p[0]; + } + + s->aq_tthd0.aq_tthd0 = (RK_U8)aq_thd[0] & 0xff; + s->aq_tthd0.aq_tthd1 = (RK_U8)aq_thd[1] & 0xff; + s->aq_tthd0.aq_tthd2 = (RK_U8)aq_thd[2] & 0xff; + s->aq_tthd0.aq_tthd3 = (RK_U8)aq_thd[3] & 0xff; + s->aq_tthd1.aq_tthd4 = (RK_U8)aq_thd[4] & 0xff; + s->aq_tthd1.aq_tthd5 = (RK_U8)aq_thd[5] & 0xff; + s->aq_tthd1.aq_tthd6 = (RK_U8)aq_thd[6] & 0xff; + s->aq_tthd1.aq_tthd7 = (RK_U8)aq_thd[7] & 0xff; + s->aq_tthd2.aq_tthd8 = (RK_U8)aq_thd[8] & 0xff; + s->aq_tthd2.aq_tthd9 = (RK_U8)aq_thd[9] & 0xff; + s->aq_tthd2.aq_tthd10 = (RK_U8)aq_thd[10] & 0xff; + s->aq_tthd2.aq_tthd11 = (RK_U8)aq_thd[11] & 0xff; + s->aq_tthd3.aq_tthd12 = (RK_U8)aq_thd[12] & 0xff; + s->aq_tthd3.aq_tthd13 = (RK_U8)aq_thd[13] & 0xff; + s->aq_tthd3.aq_tthd14 = (RK_U8)aq_thd[14] & 0xff; + s->aq_tthd3.aq_tthd15 = (RK_U8)aq_thd[15] & 0xff; + + s->aq_stp0.aq_stp_s0 = aq_step[0] & 0x1f; + s->aq_stp0.aq_stp_0t1 = aq_step[1] & 0x1f; + s->aq_stp0.aq_stp_1t2 = aq_step[2] & 0x1f; + s->aq_stp0.aq_stp_2t3 = aq_step[3] & 0x1f; + s->aq_stp0.aq_stp_3t4 = aq_step[4] & 0x1f; + s->aq_stp0.aq_stp_4t5 = aq_step[5] & 0x1f; + s->aq_stp1.aq_stp_5t6 = aq_step[6] & 0x1f; + s->aq_stp1.aq_stp_6t7 = aq_step[7] & 0x1f; + s->aq_stp1.aq_stp_7t8 = 0; + s->aq_stp1.aq_stp_8t9 = aq_step[8] & 0x1f; + s->aq_stp1.aq_stp_9t10 = aq_step[9] & 0x1f; + s->aq_stp1.aq_stp_10t11 = aq_step[10] & 0x1f; + s->aq_stp2.aq_stp_11t12 = aq_step[11] & 0x1f; + s->aq_stp2.aq_stp_12t13 = aq_step[12] & 0x1f; + s->aq_stp2.aq_stp_13t14 = aq_step[13] & 0x1f; + s->aq_stp2.aq_stp_14t15 = aq_step[14] & 0x1f; + s->aq_stp2.aq_stp_b15 = aq_step[15] & 0x1f; + s->aq_clip.aq16_rnge = 15; +} + +static void setup_vepu511_anti_stripe(HalH264eVepu511Ctx *ctx) +{ + HalVepu511RegSet *regs = ctx->regs_set; + Vepu511Param *s = ®s->reg_param; + RK_S32 str = ctx->cfg->tune.atl_str; + + s->iprd_tthdy4_0.iprd_tthdy4_0 = 1; + s->iprd_tthdy4_0.iprd_tthdy4_1 = 3; + s->iprd_tthdy4_1.iprd_tthdy4_2 = 6; + s->iprd_tthdy4_1.iprd_tthdy4_3 = 8; + s->iprd_tthdc8_0.iprd_tthdc8_0 = 1; + s->iprd_tthdc8_0.iprd_tthdc8_1 = 3; + s->iprd_tthdc8_1.iprd_tthdc8_2 = 6; + s->iprd_tthdc8_1.iprd_tthdc8_3 = 8; + s->iprd_tthdy8_0.iprd_tthdy8_0 = 1; + s->iprd_tthdy8_0.iprd_tthdy8_1 = 3; + s->iprd_tthdy8_1.iprd_tthdy8_2 = 6; + s->iprd_tthdy8_1.iprd_tthdy8_3 = 8; + + if (ctx->cfg->tune.scene_mode != MPP_ENC_SCENE_MODE_IPC) + s->iprd_tthd_ul.iprd_tthd_ul = 4095; /* disable anti-stripe */ + else + s->iprd_tthd_ul.iprd_tthd_ul = (str != 0) ? 4 : 255; + + s->iprd_wgty8.iprd_wgty8_0 = (str != 0) ? 22 : 16; + s->iprd_wgty8.iprd_wgty8_1 = (str != 0) ? 23 : 16; + s->iprd_wgty8.iprd_wgty8_2 = (str != 0) ? 20 : 16; + s->iprd_wgty8.iprd_wgty8_3 = (str != 0) ? 22 : 16; + s->iprd_wgty4.iprd_wgty4_0 = (str != 0) ? 22 : 16; + s->iprd_wgty4.iprd_wgty4_1 = (str != 0) ? 26 : 16; + s->iprd_wgty4.iprd_wgty4_2 = (str != 0) ? 20 : 16; + s->iprd_wgty4.iprd_wgty4_3 = (str != 0) ? 22 : 16; + s->iprd_wgty16.iprd_wgty16_0 = 22; + s->iprd_wgty16.iprd_wgty16_1 = 26; + s->iprd_wgty16.iprd_wgty16_2 = 20; + s->iprd_wgty16.iprd_wgty16_3 = 22; + s->iprd_wgtc8.iprd_wgtc8_0 = 18; + s->iprd_wgtc8.iprd_wgtc8_1 = 21; + s->iprd_wgtc8.iprd_wgtc8_2 = 20; + s->iprd_wgtc8.iprd_wgtc8_3 = 19; +} + +static void setup_vepu511_anti_ringing(HalH264eVepu511Ctx *ctx) +{ + HalVepu511RegSet *regs = ctx->regs_set; + Vepu511SqiCfg *s = ®s->reg_sqi; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + + s->atr_thd.atr_qp = (sm == MPP_ENC_SCENE_MODE_IPC) ? 32 : 45; + if (ctx->slice->slice_type == H264_I_SLICE) { + s->atr_thd.atr_thd0 = 1; + s->atr_thd.atr_thd1 = 2; + s->atr_thd.atr_thd2 = 6; + s->atr_wgt16.atr_lv16_wgt0 = 16; + s->atr_wgt16.atr_lv16_wgt1 = 16; + s->atr_wgt16.atr_lv16_wgt2 = 16; + + if (sm == MPP_ENC_SCENE_MODE_IPC) { + s->atr_wgt8.atr_lv8_wgt0 = 22; + s->atr_wgt8.atr_lv8_wgt1 = 21; + s->atr_wgt8.atr_lv8_wgt2 = 20; + s->atr_wgt4.atr_lv4_wgt0 = 20; + s->atr_wgt4.atr_lv4_wgt1 = 18; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } else { + s->atr_wgt8.atr_lv8_wgt0 = 18; + s->atr_wgt8.atr_lv8_wgt1 = 17; + s->atr_wgt8.atr_lv8_wgt2 = 18; + s->atr_wgt4.atr_lv4_wgt0 = 16; + s->atr_wgt4.atr_lv4_wgt1 = 16; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } + } else { + if (sm == MPP_ENC_SCENE_MODE_IPC) { + s->atr_thd.atr_thd0 = 2; + s->atr_thd.atr_thd1 = 4; + s->atr_thd.atr_thd2 = 9; + s->atr_wgt16.atr_lv16_wgt0 = 25; + s->atr_wgt16.atr_lv16_wgt1 = 20; + s->atr_wgt16.atr_lv16_wgt2 = 16; + s->atr_wgt8.atr_lv8_wgt0 = 25; + s->atr_wgt8.atr_lv8_wgt1 = 20; + s->atr_wgt8.atr_lv8_wgt2 = 18; + s->atr_wgt4.atr_lv4_wgt0 = 25; + s->atr_wgt4.atr_lv4_wgt1 = 20; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } else { + s->atr_thd.atr_thd0 = 1; + s->atr_thd.atr_thd1 = 2; + s->atr_thd.atr_thd2 = 7; + s->atr_wgt16.atr_lv16_wgt0 = 23; + s->atr_wgt16.atr_lv16_wgt1 = 22; + s->atr_wgt16.atr_lv16_wgt2 = 20; + s->atr_wgt8.atr_lv8_wgt0 = 24; + s->atr_wgt8.atr_lv8_wgt1 = 24; + s->atr_wgt8.atr_lv8_wgt2 = 24; + s->atr_wgt4.atr_lv4_wgt0 = 23; + s->atr_wgt4.atr_lv4_wgt1 = 22; + s->atr_wgt4.atr_lv4_wgt2 = 20; + } + } +} + +static void setup_vepu511_anti_flicker(HalH264eVepu511Ctx *ctx) +{ + HalVepu511RegSet *regs = ctx->regs_set; + Vepu511SqiCfg *reg = ®s->reg_sqi; + RK_U32 str = ctx->cfg->tune.anti_flicker_str; + + static RK_U8 pskip_atf_th0[4] = { 0, 0, 1, 1 }; + static RK_U8 pskip_atf_th1[4] = { 7, 7, 10, 10 }; + static RK_U8 pskip_atf_th2[4] = { 15, 15, 15, 15 }; + static RK_U8 pskip_atf_th3[4] = { 25, 25, 25, 25 }; + static RK_U8 pskip_atf_wgt0[4] = { 16, 16, 20, 20 }; + static RK_U8 pskip_atf_wgt1[4] = { 16, 16, 15, 14 }; + static RK_U8 pskip_atf_wgt2[4] = { 16, 16, 16, 15 }; + static RK_U8 pskip_atf_wgt3[4] = { 16, 16, 16, 15 }; + static RK_U8 pskip_atf_wgt4[4] = { 16, 16, 16, 16 }; + static RK_U8 intra_atf_th0[4] = { 8, 16, 20, 20 }; + static RK_U8 intra_atf_th1[4] = { 16, 32, 40, 40 }; + static RK_U8 intra_atf_th2[4] = { 32, 56, 72, 72 }; + static RK_U8 intra_atf_wgt0[4] = { 16, 24, 28, 28 }; + static RK_U8 intra_atf_wgt1[4] = { 16, 22, 26, 26 }; + static RK_U8 intra_atf_wgt2[4] = { 16, 20, 22, 22 }; + static RK_U8 intra_atf_wgt3[4] = { 16, 16, 16, 18 }; + + reg->rdo_b16_skip_atf_thd0.madp_thd0 = pskip_atf_th0[str]; + reg->rdo_b16_skip_atf_thd0.madp_thd1 = pskip_atf_th1[str]; + reg->rdo_b16_skip_atf_thd1.madp_thd2 = pskip_atf_th2[str]; + reg->rdo_b16_skip_atf_thd1.madp_thd3 = pskip_atf_th3[str]; + reg->rdo_b16_skip_atf_wgt0.wgt0 = pskip_atf_wgt0[str]; + reg->rdo_b16_skip_atf_wgt0.wgt1 = pskip_atf_wgt1[str]; + reg->rdo_b16_skip_atf_wgt0.wgt2 = pskip_atf_wgt2[str]; + reg->rdo_b16_skip_atf_wgt0.wgt3 = pskip_atf_wgt3[str]; + reg->rdo_b16_skip_atf_wgt1.wgt4 = pskip_atf_wgt4[str]; + + reg->rdo_b16_inter_atf_thd0.madp_thd0 = 20; + reg->rdo_b16_inter_atf_thd0.madp_thd1 = 40; + reg->rdo_b16_inter_atf_thd1.madp_thd2 = 72; + reg->rdo_b16_inter_atf_wgt.wgt0 = 16; + reg->rdo_b16_inter_atf_wgt.wgt1 = 16; + reg->rdo_b16_inter_atf_wgt.wgt2 = 16; + reg->rdo_b16_inter_atf_wgt.wgt3 = 16; + + reg->rdo_b16_intra_atf_thd0.madp_thd0 = intra_atf_th0[str]; + reg->rdo_b16_intra_atf_thd0.madp_thd1 = intra_atf_th1[str]; + reg->rdo_b16_intra_atf_thd1.madp_thd2 = intra_atf_th2[str]; + reg->rdo_b16_intra_atf_wgt.wgt0 = intra_atf_wgt0[str]; + reg->rdo_b16_intra_atf_wgt.wgt1 = intra_atf_wgt1[str]; + reg->rdo_b16_intra_atf_wgt.wgt2 = intra_atf_wgt2[str]; + reg->rdo_b16_intra_atf_wgt.wgt3 = intra_atf_wgt3[str]; + + reg->rdo_b16_intra_atf_cnt_thd.cnt_thd0 = 1; + reg->rdo_b16_intra_atf_cnt_thd.cnt_thd1 = 4; + reg->rdo_b16_intra_atf_cnt_thd.cnt_thd2 = 1; + reg->rdo_b16_intra_atf_cnt_thd.cnt_thd3 = 4; + + reg->rdo_atf_resi_thd.big_th0 = 16; + reg->rdo_atf_resi_thd.big_th1 = 16; + reg->rdo_atf_resi_thd.small_th0 = 8; + reg->rdo_atf_resi_thd.small_th1 = 8; +} + +static void setup_vepu511_anti_smear(HalH264eVepu511Ctx *ctx) +{ + HalVepu511RegSet *regs = ctx->regs_set; + Vepu511SqiCfg *reg = ®s->reg_sqi; + H264eSlice *slice = ctx->slice; + Vepu511H264Fbk *last_fb = &ctx->last_frame_fb; + RK_U32 mb_cnt = last_fb->st_mb_num; + RK_U32 *smear_cnt = last_fb->st_smear_cnt; + RK_S32 deblur_str = ctx->cfg->tune.deblur_str; + RK_S32 delta_qp = 0; + RK_S32 flg0 = smear_cnt[4] < (mb_cnt >> 6); + RK_S32 flg1 = 1, flg2 = 0, flg3 = 0; + RK_S32 smear_multi[4] = { 9, 12, 16, 16 }; + + hal_h264e_dbg_func("enter\n"); + + if ((smear_cnt[3] < ((5 * mb_cnt) >> 10)) || + (smear_cnt[3] < ((1126 * MPP_MAX3(smear_cnt[0], smear_cnt[1], smear_cnt[2])) >> 10)) || + (deblur_str == 6) || (deblur_str == 7)) + flg1 = 0; + + flg3 = (flg1 != 0) ? 3 : (smear_cnt[4] > ((102 * mb_cnt) >> 10)) ? 2 : + (smear_cnt[4] > ((66 * mb_cnt) >> 10)) ? 1 : 0; + + if (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + reg->smear_opt_cfg.rdo_smear_en = ctx->qpmap_en; + if (ctx->qpmap_en && deblur_str > 3) + reg->smear_opt_cfg.rdo_smear_lvl16_multi = smear_multi[flg3]; + else + reg->smear_opt_cfg.rdo_smear_lvl16_multi = (flg0 != 0) ? 9 : 12; + } else { + reg->smear_opt_cfg.rdo_smear_en = 0; + reg->smear_opt_cfg.rdo_smear_lvl16_multi = 16; + } + + if (ctx->qpmap_en && deblur_str > 3) { + flg2 = 1; + if (smear_cnt[2] + smear_cnt[3] > (3 * smear_cnt[4] / 4)) + delta_qp = 1; + if (smear_cnt[4] < (mb_cnt >> 4)) + delta_qp -= 8; + else if (smear_cnt[4] < ((3 * mb_cnt) >> 5)) + delta_qp -= 7; + else + delta_qp -= 6; + + if (flg3 == 2) + delta_qp = 0; + else if (flg3 == 1) + delta_qp = -2; + } else { + if (smear_cnt[2] + smear_cnt[3] > smear_cnt[4] / 2) + delta_qp = 1; + if (smear_cnt[4] < (mb_cnt >> 8)) + delta_qp -= (deblur_str < 2) ? 6 : 8; + else if (smear_cnt[4] < (mb_cnt >> 7)) + delta_qp -= (deblur_str < 2) ? 5 : 6; + else if (smear_cnt[4] < (mb_cnt >> 6)) + delta_qp -= (deblur_str < 2) ? 3 : 4; + else + delta_qp -= 1; + } + reg->smear_opt_cfg.rdo_smear_dlt_qp = delta_qp; + + if ((H264_I_SLICE == slice->slice_type) || + (H264_I_SLICE == last_fb->frame_type)) + reg->smear_opt_cfg.stated_mode = 1; + else + reg->smear_opt_cfg.stated_mode = 2; + + reg->smear_madp_thd0.madp_cur_thd0 = 0; + reg->smear_madp_thd0.madp_cur_thd1 = (flg2 != 0) ? 48 : 24; + reg->smear_madp_thd1.madp_cur_thd2 = (flg2 != 0) ? 64 : 48; + reg->smear_madp_thd1.madp_cur_thd3 = (flg2 != 0) ? 72 : 64; + reg->smear_madp_thd2.madp_around_thd0 = (flg2 != 0) ? 4095 : 16; + reg->smear_madp_thd2.madp_around_thd1 = 32; + reg->smear_madp_thd3.madp_around_thd2 = 48; + reg->smear_madp_thd3.madp_around_thd3 = (flg2 != 0) ? 0 : 96; + reg->smear_madp_thd4.madp_around_thd4 = 48; + reg->smear_madp_thd4.madp_around_thd5 = 24; + reg->smear_madp_thd5.madp_ref_thd0 = (flg2 != 0) ? 64 : 96; + reg->smear_madp_thd5.madp_ref_thd1 = 48; + + reg->smear_cnt_thd0.cnt_cur_thd0 = (flg2 != 0) ? 2 : 1; + reg->smear_cnt_thd0.cnt_cur_thd1 = (flg2 != 0) ? 5 : 3; + reg->smear_cnt_thd0.cnt_cur_thd2 = 1; + reg->smear_cnt_thd0.cnt_cur_thd3 = 3; + reg->smear_cnt_thd1.cnt_around_thd0 = 1; + reg->smear_cnt_thd1.cnt_around_thd1 = 4; + reg->smear_cnt_thd1.cnt_around_thd2 = 1; + reg->smear_cnt_thd1.cnt_around_thd3 = 4; + reg->smear_cnt_thd2.cnt_around_thd4 = 0; + reg->smear_cnt_thd2.cnt_around_thd5 = 3; + reg->smear_cnt_thd2.cnt_around_thd6 = 0; + reg->smear_cnt_thd2.cnt_around_thd7 = 3; + reg->smear_cnt_thd3.cnt_ref_thd0 = 1; + reg->smear_cnt_thd3.cnt_ref_thd1 = 3; + + reg->smear_resi_thd0.resi_small_cur_th0 = 6; + reg->smear_resi_thd0.resi_big_cur_th0 = 9; + reg->smear_resi_thd0.resi_small_cur_th1 = 6; + reg->smear_resi_thd0.resi_big_cur_th1 = 9; + reg->smear_resi_thd1.resi_small_around_th0 = 6; + reg->smear_resi_thd1.resi_big_around_th0 = 11; + reg->smear_resi_thd1.resi_small_around_th1 = 6; + reg->smear_resi_thd1.resi_big_around_th1 = 8; + reg->smear_resi_thd2.resi_small_around_th2 = 9; + reg->smear_resi_thd2.resi_big_around_th2 = 20; + reg->smear_resi_thd2.resi_small_around_th3 = 6; + reg->smear_resi_thd2.resi_big_around_th3 = 20; + reg->smear_resi_thd3.resi_small_ref_th0 = 7; + reg->smear_resi_thd3.resi_big_ref_th0 = 16; + reg->smear_resi_thd4.resi_th0 = (flg2 != 0) ? 0 : 10; + reg->smear_resi_thd4.resi_th1 = (flg2 != 0) ? 0 : 6; + + reg->rdo_smear_st_thd.madp_cnt_th0 = (flg2 != 0) ? 0 : 1; + reg->rdo_smear_st_thd.madp_cnt_th1 = (flg2 != 0) ? 0 : 5; + reg->rdo_smear_st_thd.madp_cnt_th2 = (flg2 != 0) ? 0 : 1; + reg->rdo_smear_st_thd.madp_cnt_th3 = (flg2 != 0) ? 0 : 3; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511_scaling_list(HalH264eVepu511Ctx *ctx) +{ + Vepu511SclCfg *s = &ctx->regs_set->reg_scl_jpgtbl.scl; + Vepu511SclCfgExt *s_ext = &ctx->regs_set->reg_scl_jpgtbl.scl_ext; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U16 *q = (RK_U16 *)&s_ext->tu8_intra_y[0]; + RK_U8 idx; + + hal_h264e_dbg_func("enter\n"); + + /* intra4x4 and inter4x4 is not supported on VEPU500. + * valid range: 0x2200 ~ 0x221F + */ + if (ctx->pps->pic_scaling_matrix_present == 1) { + for (idx = 0; idx < 64; idx++) { + p[idx] = vepu511_h264_cqm_jvt8i[63 - idx]; /* intra8x8 */ + p[idx + 64] = vepu511_h264_cqm_jvt8p[63 - idx]; /* inter8x8 */ + + q[idx] = vepu511_h264_cqm_jvt8i_q[63 - idx]; /* intra8x8 */ + q[idx + 64] = vepu511_h264_cqm_jvt8p_q[63 - idx]; /* inter8x8 */ + } + } else if (ctx->pps->pic_scaling_matrix_present == 2) { + //TODO: Update scaling list for (scaling_list_mode == 2) + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET hal_h264e_vepu511_gen_regs(void *hal, HalEncTask *task) +{ + HalH264eVepu511Ctx *ctx = (HalH264eVepu511Ctx *)hal; + HalVepu511RegSet *regs = ctx->regs_set; + MppEncCfgSet *cfg = ctx->cfg; + EncRcTask *rc_task = task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + MPP_RET ret = MPP_OK; + + hal_h264e_dbg_func("enter %p\n", hal); + hal_h264e_dbg_detail("frame %d generate regs now", ctx->frms->seq_idx); + + /* register setup */ + memset(regs, 0, sizeof(*regs)); + + setup_vepu511_normal(regs); + ret = setup_vepu511_prep(regs, &ctx->cfg->prep, task); + if (ret) + return ret; + + setup_vepu511_codec(regs, ctx); + setup_vepu511_rdo_pred(ctx); + setup_vepu511_aq(ctx); + setup_vepu511_anti_stripe(ctx); + setup_vepu511_anti_ringing(ctx); + setup_vepu511_anti_flicker(ctx); + setup_vepu511_anti_smear(ctx); + setup_vepu511_scaling_list(ctx); + + setup_vepu511_rc_base(regs, ctx, rc_task); + setup_vepu511_io_buf(regs, ctx->offsets, task); + setup_vepu511_recn_refr(ctx, regs); + setup_vepu511_split(regs, cfg); + setup_vepu511_me(ctx); + + if (frm->is_i_refresh) + setup_vepu511_intra_refresh(regs, ctx, frm->seq_idx % cfg->rc.gop); + + setup_vepu511_l2(ctx); + setup_vepu511_ext_line_buf(regs, ctx); + + if (ctx->osd_cfg.osd_data3) + vepu511_set_osd(&ctx->osd_cfg); + + if (ctx->roi_data) + vepu511_set_roi(&ctx->regs_set->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + + /* two pass register patch */ + if (frm->save_pass1) + vepu511_h264e_save_pass1_patch(regs, ctx); + + if (frm->use_pass1) + vepu511_h264e_use_pass1_patch(regs, ctx); + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu511_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu511Ctx *ctx = (HalH264eVepu511Ctx *)hal; + HalVepu511RegSet *regs = ctx->regs_set; + + (void) task; + + hal_h264e_dbg_func("enter %p\n", hal); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->reg_ctl; + wr_cfg.size = sizeof(regs->reg_ctl); + wr_cfg.offset = VEPU511_CTL_OFFSET; +#if DUMP_REG + { + RK_U32 i; + RK_U32 *reg = (RK_U32)wr_cfg.reg; + for ( i = 0; i < sizeof(regs->reg_ctl) / sizeof(RK_U32); i++) { + mpp_log("reg[%d] = 0x%08x\n", i, reg[i]); + } + + } +#endif + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_frm; + wr_cfg.size = sizeof(regs->reg_frm); + wr_cfg.offset = VEPU511_FRAME_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_rc_roi; + wr_cfg.size = sizeof(regs->reg_rc_roi); + wr_cfg.offset = VEPU511_RC_ROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_param; + wr_cfg.size = sizeof(regs->reg_param); + wr_cfg.offset = VEPU511_PARAM_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_sqi; + wr_cfg.size = sizeof(regs->reg_sqi); + wr_cfg.offset = VEPU511_SQI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_scl_jpgtbl; + wr_cfg.size = sizeof(regs->reg_scl_jpgtbl); + wr_cfg.offset = VEPU511_SCL_JPGTBL_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_osd; + wr_cfg.size = sizeof(regs->reg_osd); + wr_cfg.offset = VEPU511_OSD_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->offsets); + if (ret) { + mpp_err_f("set register offsets failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_ctl.int_sta; + rd_cfg.size = sizeof(RK_U32); + rd_cfg.offset = VEPU511_REG_BASE_HW_STATUS; + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_st; + rd_cfg.size = sizeof(regs->reg_st); + rd_cfg.offset = VEPU511_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* send request to hardware */ + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu511_status_check(HalVepu511RegSet *regs) +{ + MPP_RET ret = MPP_OK; + + if (regs->reg_ctl.int_sta.lkt_node_done_sta) + hal_h264e_dbg_detail("lkt_done finish"); + + if (regs->reg_ctl.int_sta.enc_done_sta) + hal_h264e_dbg_detail("enc_done finish"); + + if (regs->reg_ctl.int_sta.vslc_done_sta) + hal_h264e_dbg_detail("enc_slice finsh"); + + if (regs->reg_ctl.int_sta.sclr_done_sta) + hal_h264e_dbg_detail("safe clear finsh"); + + if (regs->reg_ctl.int_sta.vbsf_oflw_sta) { + mpp_err_f("bit stream overflow"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.vbuf_lens_sta) { + mpp_err_f("bus write full"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.enc_err_sta) { + mpp_err_f("bus error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wdg_sta) { + mpp_err_f("wdg timeout"); + ret = MPP_NOK; + } + + return ret; +} + +static MPP_RET hal_h264e_vepu511_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu511Ctx *ctx = (HalH264eVepu511Ctx *)hal; + HalVepu511RegSet *regs = ctx->regs_set; + RK_U32 split_out = ctx->cfg->split.split_out; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + H264NaluType type = (task->rc_task->frm.is_idr != 0) ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppEncH264HwCfg *hw_cfg = &ctx->cfg->h264.hw_cfg; + RK_S32 i; + + hal_h264e_dbg_func("enter %p\n", hal); + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (task->rc_task->frm.save_pass1) + split_out = 0; + + /* update split_out in hw_cfg */ + hw_cfg->hw_split_out = split_out; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len; + RK_U32 slice_last; + MppDevPollCfg *poll_cfg = ctx->poll_cfgs; + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = split_out & MPP_ENC_SPLIT_OUT_LOWDELAY ? 1 : ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].vepu511.sli_lst; + slice_len = poll_cfg->slice_info[i].vepu511.sli_len; + + mpp_packet_add_segment_info(pkt, type, offset, slice_len); + offset += slice_len; + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) { + param.length = slice_len; + + if (slice_last) + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + else + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + + mpp_callback(ctx->output_cb, ¶m); + } + } + } while (!slice_last); + + ret = hal_h264e_vepu511_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + ret = hal_h264e_vepu511_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } + + mpp_packet_add_segment_info(pkt, type, offset, regs->reg_st.bs_lgth_l32); + } + + if (!(split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) && !ret) { + HalH264eVepuStreamAmend *amend = &ctx->amend; + + if (amend->enable) { + amend->old_length = task->hw_length; + amend->slice->is_multi_slice = (ctx->cfg->split.split_mode > 0); + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + task->hw_length = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = task->hw_length; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + + hal_h264e_dbg_func("leave %p ret %d\n", hal, ret); + + return ret; +} + +static void vepu511_h264e_update_tune_stat(HalH264eVepu511Ctx *ctx, HalEncTask *task) +{ + HalVepu511RegSet *regs = ctx->regs_set; + Vepu511Status *reg_st = ®s->reg_st; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + RK_U32 madi_th_cnt[4], madp_th_cnt[4]; + RK_U32 madi_cnt = 0, madp_cnt = 0; + RK_U32 md_cnt; + + madi_th_cnt[0] = reg_st->st_madi_lt_num0.madi_th_lt_cnt0 + + reg_st->st_madi_rt_num0.madi_th_rt_cnt0 + + reg_st->st_madi_lb_num0.madi_th_lb_cnt0 + + reg_st->st_madi_rb_num0.madi_th_rb_cnt0; + madi_th_cnt[1] = reg_st->st_madi_lt_num0.madi_th_lt_cnt1 + + reg_st->st_madi_rt_num0.madi_th_rt_cnt1 + + reg_st->st_madi_lb_num0.madi_th_lb_cnt1 + + reg_st->st_madi_rb_num0.madi_th_rb_cnt1; + madi_th_cnt[2] = reg_st->st_madi_lt_num1.madi_th_lt_cnt2 + + reg_st->st_madi_rt_num1.madi_th_rt_cnt2 + + reg_st->st_madi_lb_num1.madi_th_lb_cnt2 + + reg_st->st_madi_rb_num1.madi_th_rb_cnt2; + madi_th_cnt[3] = reg_st->st_madi_lt_num1.madi_th_lt_cnt3 + + reg_st->st_madi_rt_num1.madi_th_rt_cnt3 + + reg_st->st_madi_lb_num1.madi_th_lb_cnt3 + + reg_st->st_madi_rb_num1.madi_th_rb_cnt3; + madp_th_cnt[0] = reg_st->st_madp_lt_num0.madp_th_lt_cnt0 + + reg_st->st_madp_rt_num0.madp_th_rt_cnt0 + + reg_st->st_madp_lb_num0.madp_th_lb_cnt0 + + reg_st->st_madp_rb_num0.madp_th_rb_cnt0; + madp_th_cnt[1] = reg_st->st_madp_lt_num0.madp_th_lt_cnt1 + + reg_st->st_madp_rt_num0.madp_th_rt_cnt1 + + reg_st->st_madp_lb_num0.madp_th_lb_cnt1 + + reg_st->st_madp_rb_num0.madp_th_rb_cnt1; + madp_th_cnt[2] = reg_st->st_madp_lt_num1.madp_th_lt_cnt2 + + reg_st->st_madp_rt_num1.madp_th_rt_cnt2 + + reg_st->st_madp_lb_num1.madp_th_lb_cnt2 + + reg_st->st_madp_rb_num1.madp_th_rb_cnt2; + madp_th_cnt[3] = reg_st->st_madp_lt_num1.madp_th_lt_cnt3 + + reg_st->st_madp_rt_num1.madp_th_rt_cnt3 + + reg_st->st_madp_lb_num1.madp_th_lb_cnt3 + + reg_st->st_madp_rb_num1.madp_th_rb_cnt3; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt[3] + 11 * madp_th_cnt[2] + 8 * madp_th_cnt[1]) >> 2; + else + md_cnt = (24 * madp_th_cnt[3] + 22 * madp_th_cnt[2] + 17 * madp_th_cnt[1]) >> 2; + madi_cnt = (6 * madi_th_cnt[3] + 5 * madi_th_cnt[2] + 4 * madi_th_cnt[1]) >> 2; + + /* fill rc info */ + if (md_cnt * 100 > 15 * mbs) + rc_info->motion_level = 200; + else if (md_cnt * 100 > 5 * mbs) + rc_info->motion_level = 100; + else if (md_cnt * 100 > (mbs >> 2)) + rc_info->motion_level = 1; + else + rc_info->motion_level = 0; + + if (madi_cnt * 100 > 30 * mbs) + rc_info->complex_level = 2; + else if (madi_cnt * 100 > 13 * mbs) + rc_info->complex_level = 1; + else + rc_info->complex_level = 0; + + rc_info->madi = madi_th_cnt[0] * regs->reg_rc_roi.madi_st_thd.madi_th0 + + madi_th_cnt[1] * (regs->reg_rc_roi.madi_st_thd.madi_th0 + + regs->reg_rc_roi.madi_st_thd.madi_th1) / 2 + + madi_th_cnt[2] * (regs->reg_rc_roi.madi_st_thd.madi_th1 + + regs->reg_rc_roi.madi_st_thd.madi_th2) / 2 + + madi_th_cnt[3] * regs->reg_rc_roi.madi_st_thd.madi_th2; + + madi_cnt = madi_th_cnt[0] + madi_th_cnt[1] + madi_th_cnt[2] + madi_th_cnt[3]; + if (madi_cnt) + rc_info->madi = rc_info->madi / madi_cnt; + + rc_info->madp = madp_th_cnt[0] * regs->reg_rc_roi.madp_st_thd0.madp_th0 + + madp_th_cnt[1] * (regs->reg_rc_roi.madp_st_thd0.madp_th0 + + regs->reg_rc_roi.madp_st_thd0.madp_th1) / 2 + + madp_th_cnt[2] * (regs->reg_rc_roi.madp_st_thd0.madp_th1 + + regs->reg_rc_roi.madp_st_thd1.madp_th2) / 2 + + madp_th_cnt[3] * regs->reg_rc_roi.madp_st_thd1.madp_th2; + + madp_cnt = madp_th_cnt[0] + madp_th_cnt[1] + madp_th_cnt[2] + madp_th_cnt[3]; + + if (madp_cnt) + rc_info->madp = rc_info->madp / madp_cnt; + + hal_h264e_dbg_rc("complex_level %d motion_level %d\n", + rc_info->complex_level, rc_info->motion_level); +} + +static MPP_RET hal_h264e_vepu511_ret_task(void * hal, HalEncTask * task) +{ + HalH264eVepu511Ctx *ctx = (HalH264eVepu511Ctx *)hal; + HalVepu511RegSet *regs = ctx->regs_set; + EncRcTaskInfo *rc_info = &task->rc_task->info; + Vepu511H264Fbk *fb = &ctx->feedback; + Vepu511Status *reg_st = ®s->reg_st; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + + hal_h264e_dbg_func("enter %p\n", hal); + + fb->st_mb_num = mbs; + fb->st_smear_cnt[0] = reg_st->st_smear_cnt0.rdo_smear_cnt0 * 4; + fb->st_smear_cnt[1] = reg_st->st_smear_cnt0.rdo_smear_cnt1 * 4; + fb->st_smear_cnt[2] = reg_st->st_smear_cnt1.rdo_smear_cnt2 * 4; + fb->st_smear_cnt[3] = reg_st->st_smear_cnt1.rdo_smear_cnt3 * 4; + fb->st_smear_cnt[4] = fb->st_smear_cnt[0] + fb->st_smear_cnt[1] + + fb->st_smear_cnt[2] + fb->st_smear_cnt[3]; + fb->frame_type = ctx->slice->slice_type; + + // update total hardware length + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = regs->reg_st.qp_sum / mbs; + rc_info->iblk4_prop = (regs->reg_st.st_pnum_i4.pnum_i4 + + regs->reg_st.st_pnum_i8.pnum_i8 + + regs->reg_st.st_pnum_i16.pnum_i16) * 256 / mbs; + + rc_info->sse = ((RK_S64)regs->reg_st.sse_h32 << 16) + + (regs->reg_st.st_sse_bsl.sse_l16 & 0xffff); + rc_info->lvl16_inter_num = regs->reg_st.st_pnum_p16.pnum_p16; + rc_info->lvl8_inter_num = regs->reg_st.st_pnum_p8.pnum_p8; + rc_info->lvl16_intra_num = regs->reg_st.st_pnum_i16.pnum_i16; + rc_info->lvl8_intra_num = regs->reg_st.st_pnum_i8.pnum_i8; + rc_info->lvl4_intra_num = regs->reg_st.st_pnum_i4.pnum_i4; + + ctx->hal_rc_cfg.bit_real = rc_info->bit_real; + ctx->hal_rc_cfg.quality_real = rc_info->quality_real; + ctx->hal_rc_cfg.iblk4_prop = rc_info->iblk4_prop; + + task->hal_ret.data = &ctx->hal_rc_cfg; + task->hal_ret.number = 1; + + mpp_dev_multi_offset_reset(ctx->offsets); + + if (ctx->dpb) { + h264e_dpb_hal_end(ctx->dpb, task->flags.curr_idx); + h264e_dpb_hal_end(ctx->dpb, task->flags.refr_idx); + } + + vepu511_h264e_update_tune_stat(ctx, task); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu511 = { + .name = "hal_h264e_vepu511", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu511Ctx), + .flag = 0, + .init = hal_h264e_vepu511_init, + .deinit = hal_h264e_vepu511_deinit, + .prepare = hal_h264e_vepu511_prepare, + .get_task = hal_h264e_vepu511_get_task, + .gen_regs = hal_h264e_vepu511_gen_regs, + .start = hal_h264e_vepu511_start, + .wait = hal_h264e_vepu511_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu511_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RV1126B, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu511) diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu511.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu511.h new file mode 100644 index 000000000..126034acd --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu511.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264E_VEPU511_H +#define HAL_H264E_VEPU511_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h264e_vepu511; + +#endif /* HAL_H264E_VEPU511_H */ diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu511_reg.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu511_reg.h new file mode 100644 index 000000000..3ce3970a1 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu511_reg.h @@ -0,0 +1,1329 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264E_VEPU511_REG_H +#define HAL_H264E_VEPU511_REG_H + +#include "rk_type.h" +#include "vepu511_common.h" + +/* class: buffer/video syntax */ +/* 0x00000270 reg156 - 0x000003fc reg255*/ +typedef struct Vepu511FrameCfg_t { + /* 0x00000270 reg156 - 0x0000027c reg159 */ + vepu511_online online_addr; + + /* 0x00000280 reg160 4*/ + RK_U32 adr_src0; + + /* 0x00000284 reg161 5*/ + RK_U32 adr_src1; + + /* 0x00000288 reg162 6*/ + RK_U32 adr_src2; + + /* 0x0000028c reg163 7*/ + RK_U32 rfpw_h_addr; + + /* 0x00000290 reg164 8*/ + RK_U32 rfpw_b_addr; + + /* 0x00000294 reg165 9*/ + RK_U32 rfpr_h_addr; + + /* 0x00000298 reg166 10*/ + RK_U32 rfpr_b_addr; + + /* 0x0000029c reg167 11*/ + RK_U32 colmvw_addr; + + /* 0x000002a0 reg168 12*/ + RK_U32 colmvr_addr; + + /* 0x000002a4 reg169 13*/ + RK_U32 dspw_addr; + + /* 0x000002a8 reg170 14*/ + RK_U32 dspr_addr; + + /* 0x000002ac reg171 15*/ + RK_U32 meiw_addr; + + /* 0x000002b0 reg172 16*/ + RK_U32 bsbt_addr; + + /* 0x000002b4 reg173 17*/ + RK_U32 bsbb_addr; + + /* 0x000002b8 reg174 18*/ + RK_U32 bsbs_addr; + + /* 0x000002bc reg175 19*/ + RK_U32 bsbr_addr; + + /* 0x000002c0 reg176 20*/ + RK_U32 lpfw_addr; + + /* 0x000002c4 reg177 21*/ + RK_U32 lpfr_addr; + + /* 0x000002c8 reg178 22*/ + RK_U32 ebuft_addr; + + /* 0x000002cc reg179 23*/ + RK_U32 ebufb_addr; + + /* 0x000002d0 reg180 */ + RK_U32 rfpt_h_addr; + + /* 0x000002d4 reg181 */ + RK_U32 rfpb_h_addr; + + /* 0x000002d8 reg182 */ + RK_U32 rfpt_b_addr; + + /* 0x000002dc reg183 */ + RK_U32 rfpb_b_addr; + + /* 0x000002e0 reg184 */ + RK_U32 adr_smear_rd; + + /* 0x000002e4 reg185 */ + RK_U32 adr_smear_wr; + + /* 0x000002e8 reg186 */ + RK_U32 adr_roir; + + /* 0x000002ec reg187 */ + RK_U32 adr_eslf; + + /* 0x000002f0 reg188 */ + RK_U32 rfp1r_h_addr; + + /* 0x000002f4 reg189 */ + RK_U32 rfp1r_b_addr; + + /* 0x000002f8 reg190 */ + RK_U32 dsp1r_addr; + + /* 0x000002fc reg191 */ + RK_U32 reserved191; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 meiw_mode : 1; + RK_U32 reserved : 2; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur_hevc : 5; + RK_U32 log2_ctu_num_hevc : 5; + RK_U32 rfpr_compress_mode : 1; + RK_U32 reserved1 : 2; + RK_U32 eslf_out_e_jpeg : 1; + RK_U32 jpeg_slen_fifo : 1; + RK_U32 eslf_out_e : 1; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } enc_pic; + + /* 0x00000304 reg193 */ + struct { + RK_U32 dchs_txid : 2; + RK_U32 dchs_rxid : 2; + RK_U32 dchs_txe : 1; + RK_U32 dchs_rxe : 1; + RK_U32 reserved : 2; + RK_U32 dchs_dly : 8; + RK_U32 dchs_ofst : 10; + RK_U32 reserved1 : 6; + } dual_core; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 frm_id_match : 1; + RK_U32 reserved : 3; + RK_U32 source_id : 1; + RK_U32 src_id_match : 1; + RK_U32 reserved1 : 2; + RK_U32 ch_id : 2; + RK_U32 vrsp_rtn_en : 1; + RK_U32 vinf_req_en : 1; + RK_U32 reserved2 : 12; + } enc_id; + + /* 0x0000030c reg195 */ + RK_U32 bsp_size; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_rcne : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved : 21; + } src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 cr_force_value : 8; + RK_U32 cb_force_value : 8; + RK_U32 chroma_force_en : 1; + RK_U32 reserved : 9; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 tile4x4_en : 1; + RK_U32 rkfbcd_en : 1; + RK_U32 reserved1 : 1; + } src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 21; + RK_U32 reserved : 11; + } src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } src_strd1; + + /* 0x0000033c reg207 */ + struct { + RK_U32 pp_corner_filter_strength : 2; + RK_U32 reserved : 2; + RK_U32 pp_edge_filter_strength : 2; + RK_U32 reserved1 : 2; + RK_U32 pp_internal_filter_strength : 2; + RK_U32 reserved2 : 22; + } src_flt_cfg; + + /* 0x340 - 0x34c */ + RK_U32 reserved208_211[4]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 reserved : 10; + RK_U32 rc_ctu_num : 20; + } rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } rc_tgt; + + /* 0x0000035c reg215 */ + struct { + RK_U32 eslf_rptr : 10; + RK_U32 eslf_wptr : 10; + RK_U32 eslf_blen : 10; + RK_U32 eslf_updt : 2; + } eslf_buf; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } sli_cnum; + + /* 0x0000036c reg219 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } vbs_pad; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cime_srch_dwnh : 4; + RK_U32 cime_srch_uph : 4; + RK_U32 cime_srch_rgtw : 4; + RK_U32 cime_srch_lftw : 4; + RK_U32 dlt_frm_num : 16; + } me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 srgn_max_num : 7; + RK_U32 cime_dist_thre : 13; + RK_U32 rme_srch_h : 2; + RK_U32 rme_srch_v : 2; + RK_U32 rme_dis : 3; + RK_U32 reserved : 1; + RK_U32 fme_dis : 3; + RK_U32 reserved1 : 1; + } me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cime_zero_thre : 13; + RK_U32 reserved : 15; + RK_U32 fme_prefsu_en : 2; + RK_U32 colmv_stor_hevc : 1; + RK_U32 colmv_load_hevc : 1; + } me_cach; + + /* 0x0000037c reg223 */ + struct { + RK_U32 ref_num : 1; + RK_U32 thre_zero_sad_dep0_cme : 6; + RK_U32 thre_zero_sad_dep1_cme : 6; + RK_U32 thre_zero_diff_dep1_cme : 3; + RK_U32 thre_zero_num_dep1_cme : 3; + RK_U32 thre_num_hit_dep1_cme : 2; + RK_U32 reserved : 7; + RK_U32 rfpw_mode : 1; + RK_U32 rfpr_mode : 1; + RK_U32 rfp1r_mode : 1; + RK_U32 reserved1 : 1; + } me_ref_comb; + + /* 0x380 - 0x39c */ + RK_U32 reserved224_231[8]; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 rect_size : 1; + RK_U32 reserved : 2; + RK_U32 vlc_lmt : 1; + RK_U32 reserved1 : 9; + RK_U32 ccwa_e : 1; + RK_U32 reserved2 : 1; + RK_U32 atr_e : 1; + RK_U32 reserved3 : 4; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved4 : 6; + RK_U32 atf_e : 1; + RK_U32 atr_mult_sel_e : 1; + RK_U32 reserved5 : 2; + } rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 rdo_mark_mode : 9; + RK_U32 reserved : 5; + RK_U32 p16_interp_num : 2; + RK_U32 p16t8_rdo_num : 2; + RK_U32 p16t4_rmd_num : 2; + RK_U32 p8_interp_num : 2; + RK_U32 p8t8_rdo_num : 2; + RK_U32 p8t4_rmd_num : 2; + RK_U32 iframe_i16_rdo_num : 2; + RK_U32 i8_rdo_num : 2; + RK_U32 iframe_i4_rdo_num : 2; + } rdo_mark_mode; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_ref_idc : 2; + RK_U32 nal_unit_type : 5; + RK_U32 reserved : 25; + } synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 max_fnum : 4; + RK_U32 drct_8x8 : 1; + RK_U32 mpoc_lm4 : 4; + RK_U32 poc_type : 2; + RK_U32 reserved : 21; + } synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 etpy_mode : 1; + RK_U32 trns_8x8 : 1; + RK_U32 csip_flag : 1; + RK_U32 num_ref0_idx : 2; + RK_U32 num_ref1_idx : 2; + RK_U32 pic_init_qp : 6; + RK_U32 cb_ofst : 5; + RK_U32 cr_ofst : 5; + RK_U32 reserved : 1; + RK_U32 dbf_cp_flg : 1; + RK_U32 reserved1 : 7; + } synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 sli_type : 2; + RK_U32 pps_id : 8; + RK_U32 drct_smvp : 1; + RK_U32 num_ref_ovrd : 1; + RK_U32 cbc_init_idc : 2; + RK_U32 reserved : 2; + RK_U32 frm_num : 16; + } synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 idr_pid : 16; + RK_U32 poc_lsb : 16; + } synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 rodr_pic_idx : 2; + RK_U32 ref_list0_rodr : 1; + RK_U32 sli_beta_ofst : 4; + RK_U32 sli_alph_ofst : 4; + RK_U32 dis_dblk_idc : 2; + RK_U32 reserved : 3; + RK_U32 rodr_pic_num : 16; + } synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 nopp_flg : 1; + RK_U32 ltrf_flg : 1; + RK_U32 arpm_flg : 1; + RK_U32 mmco4_pre : 1; + RK_U32 mmco_type0 : 3; + RK_U32 mmco_parm0 : 16; + RK_U32 mmco_type1 : 3; + RK_U32 mmco_type2 : 3; + RK_U32 reserved : 3; + } synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 mmco_parm1 : 16; + RK_U32 mmco_parm2 : 16; + } synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 long_term_frame_idx0 : 4; + RK_U32 long_term_frame_idx1 : 4; + RK_U32 long_term_frame_idx2 : 4; + RK_U32 reserved : 20; + } synt_refm2; + + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } synt_refm3_hevc; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } synt_long_refm0_hevc; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } synt_long_refm1_hevc; + + /* 0x000003e0 reg248 */ + struct { + RK_U32 sao_lambda_multi : 3; + RK_U32 reserved : 29; + } sao_cfg_hevc; + + /* 0x3e4 - 0x3ec */ + RK_U32 reserved249_251[3]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 mv_v_lmt_thd : 14; + RK_U32 reserved : 1; + RK_U32 mv_v_lmt_en : 1; + RK_U32 reserved1 : 16; + } sli_cfg; + + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 9; + RK_U32 reserved : 7; + RK_U32 tile_y : 9; + RK_U32 reserved1 : 7; + } tile_pos_hevc; + + /* 0x000003f8 reg254 */ + struct { + RK_U32 slice_sta_x : 9; + RK_U32 reserved1 : 7; + RK_U32 slice_sta_y : 10; + RK_U32 reserved2 : 5; + RK_U32 slice_enc_ena : 1; + } slice_enc_cfg0; + + /* 0x000003fc reg255 */ + struct { + RK_U32 slice_end_x : 9; + RK_U32 reserved : 7; + RK_U32 slice_end_y : 10; + RK_U32 reserved1 : 6; + } slice_enc_cfg1; +} Vepu511FrameCfg; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x0000110c reg1091 */ +typedef struct Vepu511RcRoiCfg_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 26; + } roi_qthd3; + + /* 0x1040 */ + RK_U32 reserved_1040; + + /* 0x00001044 reg1041 */ + struct { + RK_U32 aq_tthd0 : 8; + RK_U32 aq_tthd1 : 8; + RK_U32 aq_tthd2 : 8; + RK_U32 aq_tthd3 : 8; + } aq_tthd0; + + /* 0x00001048 reg1042 */ + struct { + RK_U32 aq_tthd4 : 8; + RK_U32 aq_tthd5 : 8; + RK_U32 aq_tthd6 : 8; + RK_U32 aq_tthd7 : 8; + } aq_tthd1; + + /* 0x0000104c reg1043 */ + struct { + RK_U32 aq_tthd8 : 8; + RK_U32 aq_tthd9 : 8; + RK_U32 aq_tthd10 : 8; + RK_U32 aq_tthd11 : 8; + } aq_tthd2; + + /* 0x00001050 reg1044 */ + struct { + RK_U32 aq_tthd12 : 8; + RK_U32 aq_tthd13 : 8; + RK_U32 aq_tthd14 : 8; + RK_U32 aq_tthd15 : 8; + } aq_tthd3; + + /* 0x00001054 reg1045 */ + struct { + RK_U32 aq_stp_s0 : 5; + RK_U32 aq_stp_0t1 : 5; + RK_U32 aq_stp_1t2 : 5; + RK_U32 aq_stp_2t3 : 5; + RK_U32 aq_stp_3t4 : 5; + RK_U32 aq_stp_4t5 : 5; + RK_U32 reserved : 2; + } aq_stp0; + + /* 0x00001058 reg1046 */ + struct { + RK_U32 aq_stp_5t6 : 5; + RK_U32 aq_stp_6t7 : 5; + RK_U32 aq_stp_7t8 : 5; + RK_U32 aq_stp_8t9 : 5; + RK_U32 aq_stp_9t10 : 5; + RK_U32 aq_stp_10t11 : 5; + RK_U32 reserved : 2; + } aq_stp1; + + /* 0x0000105c reg1047 */ + struct { + RK_U32 aq_stp_11t12 : 5; + RK_U32 aq_stp_12t13 : 5; + RK_U32 aq_stp_13t14 : 5; + RK_U32 aq_stp_14t15 : 5; + RK_U32 aq_stp_b15 : 5; + RK_U32 reserved : 7; + } aq_stp2; + + /* 0x00001060 reg1048 */ + struct { + RK_U32 aq16_rnge : 4; + RK_U32 aq32_rnge : 4; + RK_U32 aq8_rnge : 5; + RK_U32 aq16_dif0 : 5; + RK_U32 aq16_dif1 : 5; + RK_U32 reserved : 1; + RK_U32 aq_cme_en : 1; + RK_U32 aq_subj_cme_en : 1; + RK_U32 aq_rme_en : 1; + RK_U32 aq_subj_rme_en : 1; + RK_U32 reserved1 : 4; + } aq_clip; + + /* 0x00001064 reg1049 */ + struct { + RK_U32 madi_th0 : 8; + RK_U32 madi_th1 : 8; + RK_U32 madi_th2 : 8; + RK_U32 reserved : 8; + } madi_st_thd; + + /* 0x00001068 reg1050 */ + struct { + RK_U32 madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_th1 : 12; + RK_U32 reserved1 : 4; + } madp_st_thd0; + + /* 0x0000106c reg1051 */ + struct { + RK_U32 madp_th2 : 12; + RK_U32 reserved : 20; + } madp_st_thd1; + + /* 0x1070 - 0x1078 */ + RK_U32 reserved1052_1054[3]; + + /* 0x0000107c reg1055 */ + struct { + RK_U32 chrm_klut_ofst : 4; + RK_U32 reserved : 28; + } klut_ofst; + + /* 0x00001080 reg1056 */ + struct { + RK_U32 fmdc_adju_intra16 : 4; + RK_U32 fmdc_adju_inter16 : 4; + RK_U32 fmdc_adju_skip16 : 4; + RK_U32 reserved : 12; + RK_U32 fmdc_adj_pri : 5; + RK_U32 reserved1 : 3; + } fmdc_adj0; + + /* 0x00001084 reg1057 - 0x00001088 reg1058 */ + RK_U32 reserved_1057_1058[2]; + + /* 0x0000108c reg1059 */ + struct { + RK_U32 bmap_en : 1; + RK_U32 bmap_pri : 5; + RK_U32 bmap_qpmin : 6; + RK_U32 bmap_qpmax : 6; + RK_U32 bmap_mdc_dpth : 1; + RK_U32 reserved : 13; + } bmap_cfg; + + /* 0x00001090 reg1060 - 0x0000112c reg1099 */ + Vepu511RoiCfg roi_cfg; +} Vepu511RcRoiCfg; + +/* class: iprd/iprd_wgt/rdo_wgta/prei_dif/sobel */ +/* 0x00001700 reg1472 -0x000019cc reg1651 */ +typedef struct Vepu511Param_t { + /* 0x00001700 reg1472 */ + struct { + RK_U32 iprd_tthdy4_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_0; + + /* 0x00001704 reg1473 */ + struct { + RK_U32 iprd_tthdy4_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_1; + + /* 0x00001708 reg1474 */ + struct { + RK_U32 iprd_tthdc8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_0; + + /* 0x0000170c reg1475 */ + struct { + RK_U32 iprd_tthdc8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_1; + + /* 0x00001710 reg1476 */ + struct { + RK_U32 iprd_tthdy8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_0; + + /* 0x00001714 reg1477 */ + struct { + RK_U32 iprd_tthdy8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_1; + + /* 0x00001718 reg1478 */ + struct { + RK_U32 iprd_tthd_ul : 12; + RK_U32 reserved : 20; + } iprd_tthd_ul; + + /* 0x0000171c reg1479 */ + struct { + RK_U32 iprd_wgty8_0 : 8; + RK_U32 iprd_wgty8_1 : 8; + RK_U32 iprd_wgty8_2 : 8; + RK_U32 iprd_wgty8_3 : 8; + } iprd_wgty8; + + /* 0x00001720 reg1480 */ + struct { + RK_U32 iprd_wgty4_0 : 8; + RK_U32 iprd_wgty4_1 : 8; + RK_U32 iprd_wgty4_2 : 8; + RK_U32 iprd_wgty4_3 : 8; + } iprd_wgty4; + + /* 0x00001724 reg1481 */ + struct { + RK_U32 iprd_wgty16_0 : 8; + RK_U32 iprd_wgty16_1 : 8; + RK_U32 iprd_wgty16_2 : 8; + RK_U32 iprd_wgty16_3 : 8; + } iprd_wgty16; + + /* 0x00001728 reg1482 */ + struct { + RK_U32 iprd_wgtc8_0 : 8; + RK_U32 iprd_wgtc8_1 : 8; + RK_U32 iprd_wgtc8_2 : 8; + RK_U32 iprd_wgtc8_3 : 8; + } iprd_wgtc8; + + /* 0x172c */ + RK_U32 reserved_1483; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 bias_madi_th0 : 8; + RK_U32 bias_madi_th1 : 8; + RK_U32 bias_madi_th2 : 8; + RK_U32 reserved : 8; + } bias_madi_thd_comb; + + /* 0x00001734 reg1485 */ + struct { + RK_U32 bias_i_val0 : 10; + RK_U32 bias_i_val1 : 10; + RK_U32 bias_i_val2 : 10; + RK_U32 reserved : 2; + } qnt0_i_bias_comb; + + /* 0x00001738 reg1486 */ + struct { + RK_U32 bias_i_val3 : 10; + RK_U32 reserved : 22; + } qnt1_i_bias_comb; + + /* 0x0000173c reg1487 */ + struct { + RK_U32 bias_p_val0 : 10; + RK_U32 bias_p_val1 : 10; + RK_U32 bias_p_val2 : 10; + RK_U32 reserved : 2; + } qnt0_p_bias_comb; + + /* 0x00001740 reg1488 */ + struct { + RK_U32 bias_p_val3 : 10; + RK_U32 reserved : 22; + } qnt1_p_bias_comb; + + /* 0x00001744 reg1489 */ + struct { + RK_U32 light_change_en : 1; + RK_U32 light_ratio_mult1 : 5; + RK_U32 light_ratio_mult2 : 4; + RK_U32 light_thre_csu1_cnt : 2; + RK_U32 srch_rgn_en : 1; + RK_U32 reserved : 3; + RK_U32 light_thre_madp : 8; + RK_U32 light_thre_lightmadp : 8; + } light_cfg; + + /* 0x1748 - 0x175c */ + RK_U32 reserved1490_1495[6]; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 reserved : 2; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 fme_lvl_mrg : 1; + RK_U32 reserved1 : 16; + } me_sqi_cfg; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 ratio_consi_cfg : 4; + RK_U32 ratio_bmv_dist : 4; + RK_U32 reserved : 12; + } cime_madp_th; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th; + + /* 0x1780 - 0x18fc */ + RK_U32 reserved1504_1599[96]; + + /* 0x00001900 reg1600 - 0x000019cc reg1651*/ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} Vepu511Param; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x0000216c reg2139 */ +typedef struct Vepu511SqiCfg_t { + /* 0x00002000 reg2048 - 0x00002010 reg2052*/ + RK_U32 reserved_2048_2052[5]; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 rdo_smear_lvl16_multi : 8; + RK_S32 rdo_smear_dlt_qp : 4; + RK_U32 reserved : 1; + RK_U32 stated_mode : 2; + RK_U32 rdo_smear_en : 1; + RK_U32 reserved1 : 16; + } smear_opt_cfg; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 madp_cur_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_cur_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd0; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 madp_cur_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_cur_thd3 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd1; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 madp_around_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd2; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 madp_around_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd3 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd3; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 madp_around_thd4 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd5 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd4; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 madp_ref_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_ref_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd5; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 cnt_cur_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_cur_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_cur_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_cur_thd3 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd0; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 cnt_around_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_around_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_around_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_around_thd3 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd1; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 cnt_around_thd4 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_around_thd5 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_around_thd6 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_around_thd7 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd2; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 cnt_ref_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_ref_thd1 : 4; + RK_U32 reserved1 : 20; + } smear_cnt_thd3; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 resi_small_cur_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_cur_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_cur_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_cur_th1 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd0; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 resi_small_around_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_around_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_around_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_around_th1 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd1; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 resi_small_around_th2 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_around_th2 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_around_th3 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_around_th3 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd2; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 resi_small_ref_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_ref_th0 : 6; + RK_U32 reserved1 : 18; + } smear_resi_thd3; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 resi_th0 : 8; + RK_U32 reserved : 8; + RK_U32 resi_th1 : 8; + RK_U32 reserved1 : 8; + } smear_resi_thd4; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 madp_cnt_th0 : 4; + RK_U32 madp_cnt_th1 : 4; + RK_U32 madp_cnt_th2 : 4; + RK_U32 madp_cnt_th3 : 4; + RK_U32 reserved : 16; + } rdo_smear_st_thd; + + /* 0x00002058 reg2070 */ + RK_U32 reserved_2070; + + /* 0x0000205c reg2071 */ + struct { + RK_U32 lid_grdn_blk_cu16_th : 8; + RK_U32 lid_rmd_intra_jcoef_ang : 5; + RK_U32 lid_rdo_intra_rcoef_ang : 5; + RK_U32 lid_rmd_intra_jcoef_dp : 6; + RK_U32 lid_rdo_intra_rcoef_dp : 6; + RK_U32 lid_en : 1; + RK_U32 reserved : 1; + } line_intra_dir_cfg; + + RK_U32 reserved2072_2075[4]; + + /* 0x00002070 reg2076 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_skip_atf_thd0; + + /* 0x00002074 reg2077 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_skip_atf_thd1; + + /* 0x00002078 reg2078 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } rdo_b16_skip_atf_wgt0; + + /* 0x0000207c reg2079 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 reserved : 24; + } rdo_b16_skip_atf_wgt1; + + /* 0x00002080 reg2080 - 0x00002088 reg2082 */ + RK_U32 reserved2080_2082[3]; + + /* 0x0000208c reg2083 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_inter_atf_thd0; + + /* 0x00002090 reg2084 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b16_inter_atf_thd1; + + /* 0x00002094 reg2085 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } rdo_b16_inter_atf_wgt; + + /* 0x00002098 reg2086 - 0x000020a0 reg2088 */ + RK_U32 reserved2086_2088[3]; + + /* 0x000020a4 reg2089 */ + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_intra_atf_thd0; + + /* 0x000020a8 reg2090 */ + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b16_intra_atf_thd1; + + /* 0x000020ac reg2091 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } rdo_b16_intra_atf_wgt; + + /* 0x20b0 */ + RK_U32 reserved_2092; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 cnt_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_thd3 : 4; + RK_U32 reserved3 : 4; + } rdo_b16_intra_atf_cnt_thd; + + /* 0x000020b8 reg2094 */ + struct { + RK_U32 big_th0 : 6; + RK_U32 reserved : 2; + RK_U32 big_th1 : 6; + RK_U32 reserved1 : 2; + RK_U32 small_th0 : 6; + RK_U32 reserved2 : 2; + RK_U32 small_th1 : 6; + RK_U32 reserved3 : 2; + } rdo_atf_resi_thd; + + /* 0x20bc reg2095 - 0x0000215c reg2135*/ + RK_U32 reserved_2095_2135[41]; + + /* 0x00002160 reg2136 */ + struct { + RK_U32 atr_thd0 : 8; + RK_U32 atr_thd1 : 8; + RK_U32 atr_thd2 : 8; + RK_U32 atr_qp : 6; + RK_U32 reserved : 2; + } atr_thd; + + /* 0x00002164 reg2137 */ + struct { + RK_U32 atr_lv16_wgt0 : 8; + RK_U32 atr_lv16_wgt1 : 8; + RK_U32 atr_lv16_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt16; + + /* 0x00002168 reg2138 */ + struct { + RK_U32 atr_lv8_wgt0 : 8; + RK_U32 atr_lv8_wgt1 : 8; + RK_U32 atr_lv8_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt8; + + /* 0x0000216c reg2139 */ + struct { + RK_U32 atr_lv4_wgt0 : 8; + RK_U32 atr_lv4_wgt1 : 8; + RK_U32 atr_lv4_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt4; +} Vepu511SqiCfg; + +typedef struct HalVepu511Reg_t { + Vepu511ControlCfg reg_ctl; + Vepu511FrameCfg reg_frm; + Vepu511RcRoiCfg reg_rc_roi; + Vepu511Param reg_param; + Vepu511SqiCfg reg_sqi; + Vepu511SclJpgTbl reg_scl_jpgtbl; + Vepu511OsdComb reg_osd; + Vepu511Status reg_st; + Vepu511Dbg reg_dbg; +} HalVepu511RegSet; + +#endif \ No newline at end of file diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu511a.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu511a.c new file mode 100644 index 000000000..ed5f7a6de --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu511a.c @@ -0,0 +1,2757 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h264e_vepu511a" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_packet_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_enc_hal.h" +#include "mpp_enc_cb_param.h" + +#include "rkv_enc_def.h" +#include "hal_bufs.h" +#include "h264e_dpb.h" +#include "hal_h264e_debug.h" +#include "vepu5xx_common.h" +#include "vepu511a_common.h" +#include "hal_h264e_stream_amend.h" +#include "hal_h264e_vepu511a_reg.h" + +#define DUMP_REG 0 +#define MAX_TASK_CNT 2 +#define VEPU540C_MAX_ROI_NUM 8 + +typedef struct Vepu511aRoiH264BsCfg_t { + RK_U64 force_inter : 42; + RK_U64 mode_mask : 9; + RK_U64 reserved : 10; + RK_U64 force_intra : 1; + RK_U64 qp_adj_en : 1; + RK_U64 amv_en : 1; +} Vepu511aRoiH264BsCfg; + +typedef struct VEPU511AH264Fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 frame_type; + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; + RK_U32 st_smear_cnt[5]; +} Vepu511aH264Fbk; + +typedef struct HalH264eVepu511aCtx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_S32 frame_cnt; + + /* buffers management */ + HalBufs hw_recn; + RK_S32 pixel_buf_fbc_hdr_size; + RK_S32 pixel_buf_fbc_bdy_size; + RK_S32 pixel_buf_size; + RK_S32 thumb_buf_size; + RK_S32 max_buf_cnt; + MppDevRegOffCfgs *offsets; + + /* external line buffer over 4K */ + MppBufferGroup ext_line_buf_grp; + MppBuffer ext_line_buf; + RK_S32 ext_line_buf_size; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eDpb *dpb; + H264eFrmInfo *frms; + + /* async encode TSVC info */ + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + + /* syntax for output to enc_impl */ + EncRcTaskInfo hal_rc_cfg; + + /* osd */ + // Vepu511aOsdCfg osd_cfg; + + /* roi */ + void *roi_data; + MppBufferGroup roi_grp; + MppBuffer roi_base_cfg_buf; + RK_S32 roi_base_buf_size; + + /* two-pass deflicker */ + MppBuffer buf_pass1; + + /* single register set for single core */ + HalVepu511aRegSet *regs_set; + HalH264eVepuStreamAmend amend; + H264ePrefixNal *prefix; + H264eSlice *slice; + + RK_S32 curr_idx; + RK_S32 prev_idx; + + /* slice low delay output callback */ + MppCbCtx *output_cb; + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + MppDevPollCfg *poll_cfgs; + + Vepu511aH264Fbk feedback; + Vepu511aH264Fbk last_frame_fb; + + void *tune; + RK_S32 smart_en; + RK_S32 qpmap_en; +} HalH264eVepu511aCtx; + +/* Custom Quant Matrices: Joint Video Team */ +static RK_U8 vepu511a_h264_cqm_jvt8i[64] = { + 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static RK_U8 vepu511a_h264_cqm_jvt8p[64] = { + 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 +}; + +static RK_S32 h264_aq_tthd_default[16] = { + 0, 0, 0, 0, 3, 3, 5, 5, + 8, 8, 8, 15, 15, 20, 25, 25 +}; + +static RK_S32 h264_P_aq_step_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 7, 8 +}; + +static RK_S32 h264_I_aq_step_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 7, 8 +}; + +static void setup_ext_line_bufs(HalH264eVepu511aCtx *ctx) +{ + if (ctx->ext_line_buf) + return; + + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_buf, + ctx->ext_line_buf_size); +} + +static void clear_ext_line_bufs(HalH264eVepu511aCtx *ctx) +{ + if (ctx->ext_line_buf) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + } +} + +static MPP_RET hal_h264e_vepu511a_deinit(void *hal) +{ + HalH264eVepu511aCtx *p = (HalH264eVepu511aCtx *)hal; + + hal_h264e_dbg_func("enter %p\n", p); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + clear_ext_line_bufs(p); + + h264e_vepu_stream_amend_deinit(&p->amend); + + MPP_FREE(p->regs_set); + MPP_FREE(p->reorder); + MPP_FREE(p->marking); + MPP_FREE(p->poll_cfgs); + + if (p->ext_line_buf_grp) { + mpp_buffer_group_put(p->ext_line_buf_grp); + p->ext_line_buf_grp = NULL; + } + + if (p->hw_recn) { + hal_bufs_deinit(p->hw_recn); + p->hw_recn = NULL; + } + + if (p->roi_base_cfg_buf) { + mpp_buffer_put(p->roi_base_cfg_buf); + p->roi_base_cfg_buf = NULL; + p->roi_base_buf_size = 0; + } + + if (p->roi_grp) { + mpp_buffer_group_put(p->roi_grp); + p->roi_grp = NULL; + } + + if (p->offsets) { + mpp_dev_multi_offset_deinit(p->offsets); + p->offsets = NULL; + } + + if (p->buf_pass1) { + mpp_buffer_put(p->buf_pass1); + p->buf_pass1 = NULL; + } + + if (p->tune) { + // vepu511a_h264e_tune_deinit(p->tune); + p->tune = NULL; + } + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu511a_init(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu511aCtx *p = (HalH264eVepu511aCtx *)hal; + MPP_RET ret = MPP_OK; + RK_U32 i; + + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_loge_f("mpp_dev_init failed. ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + + ret = hal_bufs_init(&p->hw_recn); + if (ret) { + mpp_loge_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + /* single core uses single set of buffers */ + p->regs_set = mpp_malloc(HalVepu511aRegSet, 1); + if (NULL == p->regs_set) { + ret = MPP_ERR_MALLOC; + mpp_loge_f("init register buffer failed\n"); + goto DONE; + } + + p->reorder = mpp_malloc(H264eReorderInfo, 1); + if (NULL == p->reorder) { + ret = MPP_ERR_MALLOC; + mpp_loge_f("init reorder data failed\n"); + goto DONE; + } + + p->marking = mpp_malloc(H264eMarkingInfo, 1); + if (NULL == p->marking) { + ret = MPP_ERR_MALLOC; + mpp_loge_f("init marking data failed\n"); + goto DONE; + } + + p->poll_slice_max = 8; + p->poll_cfg_size = (sizeof(p->poll_cfgs) + sizeof(RK_S32) * p->poll_slice_max); + p->poll_cfgs = mpp_malloc_size(MppDevPollCfg, p->poll_cfg_size); + if (NULL == p->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_loge_f("init poll cfg buffer failed\n"); + goto DONE; + } + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 1; + hw->qp_delta_row = 2; + hw->extra_buf = 1; + hw->qbias_i = 683; + hw->qbias_p = 341; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, h264_aq_tthd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, h264_aq_tthd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, h264_I_aq_step_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, h264_P_aq_step_default, sizeof(hw->aq_step_p)); + + for (i = 0; i < MPP_ARRAY_ELEMS(hw->mode_bias); i++) + hw->mode_bias[i] = 8; + + hw->skip_sad = 8; + hw->skip_bias = 8; + } + + mpp_dev_multi_offset_init(&p->offsets, 24); + p->output_cb = cfg->output_cb; + cfg->cap_recn_out = 1; + h264e_vepu_stream_amend_init(&p->amend); + + // p->tune = vepu511a_h264e_tune_init(p); + +DONE: + if (ret) + hal_h264e_vepu511a_deinit(hal); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +/* + * NOTE: recon / refer buffer is FBC data buffer. + * And FBC data require extra 16 lines space for hardware io. + */ +static void setup_hal_bufs(HalH264eVepu511aCtx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + RK_S32 alignment_w = 64; + RK_S32 alignment_h = 16; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment_w); + RK_S32 aligned_h = MPP_ALIGN(prep->height, alignment_h) + 16; + RK_S32 pixel_buf_fbc_hdr_size = MPP_ALIGN(aligned_w * aligned_h / 64, SZ_8K); + RK_S32 pixel_buf_fbc_bdy_size = aligned_w * aligned_h * 3 / 2; + RK_S32 pixel_buf_size = pixel_buf_fbc_hdr_size + pixel_buf_fbc_bdy_size; + RK_S32 thumb_buf_size = MPP_ALIGN(aligned_w / 64 * aligned_h / 64 * 256, SZ_8K); + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + MppEncRefCfg ref_cfg = cfg->ref_cfg; + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + if (new_max_cnt < MPP_MAX(new_max_cnt, info->dpb_size + 1)) + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > SZ_4K) { + RK_S32 ctu_w = (aligned_w + 63) / 64; + RK_S32 ext_line_buf_size = ((ctu_w - 53) * 53 + 15) / 16 * 16 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + clear_ext_line_bufs(ctx); + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + + ctx->ext_line_buf_size = ext_line_buf_size; + setup_ext_line_bufs(ctx); + } else { + clear_ext_line_bufs(ctx); + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + if ((ctx->pixel_buf_fbc_hdr_size != pixel_buf_fbc_hdr_size) || + (ctx->pixel_buf_fbc_bdy_size != pixel_buf_fbc_bdy_size) || + (ctx->pixel_buf_size != pixel_buf_size) || + (ctx->thumb_buf_size != thumb_buf_size) || + (new_max_cnt > old_max_cnt)) { + size_t sizes[3]; + + hal_h264e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->pixel_buf_size, pixel_buf_size, + old_max_cnt, new_max_cnt); + + /* pixel buffer */ + sizes[0] = pixel_buf_size; + /* thumb buffer */ + sizes[1] = thumb_buf_size; + /* smear buffer */ + sizes[2] = MPP_ALIGN(aligned_w / 64, 16) * MPP_ALIGN(aligned_h / 16, 16); + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_bufs_setup(ctx->hw_recn, new_max_cnt, MPP_ARRAY_ELEMS(sizes), sizes); + + ctx->pixel_buf_fbc_hdr_size = pixel_buf_fbc_hdr_size; + ctx->pixel_buf_fbc_bdy_size = pixel_buf_fbc_bdy_size; + ctx->pixel_buf_size = pixel_buf_size; + ctx->thumb_buf_size = thumb_buf_size; + ctx->max_buf_cnt = new_max_cnt; + } +} + +static MPP_RET hal_h264e_vepu511a_prepare(void *hal) +{ + HalH264eVepu511aCtx *ctx = (HalH264eVepu511aCtx *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->hw_recn, i); + + prep->change_res = 0; + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_U32 update_vepu511a_syntax(HalH264eVepu511aCtx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + ctx->dpb = desc->p; + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu511a_get_task(void *hal, HalEncTask *task) +{ + HalH264eVepu511aCtx *ctx = (HalH264eVepu511aCtx *)hal; + MppEncCfgSet *cfg_set = ctx->cfg; + MppEncH264HwCfg *hw_cfg = &cfg_set->h264.hw_cfg; + RK_U32 updated = update_vepu511a_syntax(ctx, &task->syntax); + EncFrmStatus *frm_status = &task->rc_task->frm; + H264eFrmInfo *frms = ctx->frms; + + hal_h264e_dbg_func("enter %p\n", hal); + + ctx->smart_en = (ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC); + ctx->qpmap_en = ctx->cfg->tune.deblur_en; + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) + setup_hal_bufs(ctx); + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(task->frame); + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + } + + if (!frm_status->reencode) + ctx->last_frame_fb = ctx->feedback; + + if (ctx->dpb) { + h264e_dpb_hal_start(ctx->dpb, frms->curr_idx); + h264e_dpb_hal_start(ctx->dpb, frms->refr_idx); + } + + task->flags.curr_idx = frms->curr_idx; + task->flags.refr_idx = frms->refr_idx; + task->part_first = 1; + task->part_last = 0; + + /* if not VEPU1/2, update log2_max_frame_num_minus4 in hw_cfg */ + hw_cfg->hw_log2_max_frame_num_minus4 = ctx->sps->log2_max_frame_num_minus4; + hw_cfg->hw_poc_type = ctx->sps->pic_order_cnt_type; + + h264e_vepu_stream_amend_config(&ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static void setup_vepu511a_normal(HalVepu511aRegSet *regs) +{ + hal_h264e_dbg_func("enter\n"); + /* reg000 VERSION is read only */ + + /* reg001 ENC_STRT */ + regs->reg_ctl.enc_strt.lkt_num = 0; + regs->reg_ctl.enc_strt.vepu_cmd = 1; + + regs->reg_ctl.opt_strg.cke = 1; + regs->reg_ctl.opt_strg.resetn_hw_en = 1; + + /* reg002 ENC_CLR */ + regs->reg_ctl.enc_clr.safe_clr = 0; + regs->reg_ctl.enc_clr.force_clr = 0; + + /* reg004 INT_EN */ + regs->reg_ctl.int_en.enc_done_en = 1; + regs->reg_ctl.int_en.lkt_node_done_en = 1; + regs->reg_ctl.int_en.sclr_done_en = 1; + regs->reg_ctl.int_en.vslc_done_en = 0; + regs->reg_ctl.int_en.vbsf_oflw_en = 1; + regs->reg_ctl.int_en.vbuf_lens_en = 1; + regs->reg_ctl.int_en.enc_err_en = 1; + + regs->reg_ctl.int_en.wdg_en = 1; + regs->reg_ctl.int_en.vsrc_err_en = 1; + regs->reg_ctl.int_en.wdg_en = 1; + regs->reg_ctl.int_en.lkt_err_int_en = 1; + regs->reg_ctl.int_en.lkt_err_stop_en = 1; + regs->reg_ctl.int_en.lkt_force_stop_en = 1; + regs->reg_ctl.int_en.jslc_done_en = 1; + regs->reg_ctl.int_en.jbsf_oflw_en = 1; + regs->reg_ctl.int_en.jbuf_lens_en = 1; + regs->reg_ctl.int_en.dvbm_err_en = 0; + + /* reg005 INT_MSK */ + regs->reg_ctl.int_msk.enc_done_msk = 0; + regs->reg_ctl.int_msk.lkt_node_done_msk = 0; + regs->reg_ctl.int_msk.sclr_done_msk = 0; + regs->reg_ctl.int_msk.vslc_done_msk = 0; + regs->reg_ctl.int_msk.vbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.vbuf_lens_msk = 0; + regs->reg_ctl.int_msk.enc_err_msk = 0; + regs->reg_ctl.int_msk.vsrc_err_msk = 0; + regs->reg_ctl.int_msk.wdg_msk = 0; + regs->reg_ctl.int_msk.lkt_err_int_msk = 0; + regs->reg_ctl.int_msk.lkt_err_stop_msk = 0; + regs->reg_ctl.int_msk.lkt_force_stop_msk = 0; + regs->reg_ctl.int_msk.jslc_done_msk = 0; + regs->reg_ctl.int_msk.jbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.jbuf_lens_msk = 0; + regs->reg_ctl.int_msk.dvbm_err_msk = 0; + + /* reg006 INT_CLR is not set */ + /* reg007 INT_STA is read only */ + /* reg008 ~ reg0011 gap */ + regs->reg_ctl.enc_wdg.vs_load_thd = 0; + + /* reg015 DTRNS_MAP */ + regs->reg_ctl.dtrns_map.jpeg_bus_edin = 0; + regs->reg_ctl.dtrns_map.src_bus_edin = 0; + regs->reg_ctl.dtrns_map.meiw_bus_edin = 0; + regs->reg_ctl.dtrns_map.bsw_bus_edin = 7; + regs->reg_ctl.dtrns_map.lktw_bus_edin = 0; + regs->reg_ctl.dtrns_map.rec_nfbc_bus_edin = 0; + + regs->reg_ctl.dtrns_cfg.axi_brsp_cke = 0; + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET setup_vepu511a_prep(HalVepu511aRegSet *regs, MppEncPrepCfg *prep, HalEncTask *task) +{ + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + VepuFmtCfg cfg; + MppFrameFormat fmt = prep->format; + MPP_RET ret = vepu5xx_set_fmt(&cfg, fmt); + RK_U32 hw_fmt = cfg.format; + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + /* do nothing when color format is not supported */ + if (ret) + return ret; + + reg_frm->common.enc_rsl.pic_wd8_m1 = MPP_ALIGN(prep->width, 16) / 8 - 1; + reg_frm->common.src_fill.pic_wfill = MPP_ALIGN(prep->width, 16) - prep->width; + reg_frm->common.enc_rsl.pic_hd8_m1 = MPP_ALIGN(prep->height, 16) / 8 - 1; + reg_frm->common.src_fill.pic_hfill = MPP_ALIGN(prep->height, 16) - prep->height; + + regs->reg_ctl.dtrns_map.src_bus_edin = cfg.src_endian; + + reg_frm->common.src_fmt.src_cfmt = hw_fmt; + reg_frm->common.src_fmt.alpha_swap = cfg.alpha_swap; + reg_frm->common.src_fmt.rbuv_swap = cfg.rbuv_swap; + reg_frm->common.src_fmt.out_fmt = (hw_fmt == VEPU5xx_FMT_YUV400) ? 0 : 1; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + reg_frm->common.src_proc.rkfbcd_en = 1; + + y_stride = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!y_stride) + y_stride = MPP_ALIGN(prep->hor_stride, 64) >> 2; + } else if (prep->hor_stride) { + if (MPP_FRAME_FMT_IS_TILE(fmt)) { + reg_frm->common.src_proc.tile4x4_en = 1; + + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV400: + y_stride = prep->hor_stride * 4; + break; + case MPP_FMT_YUV420P: + case MPP_FMT_YUV420SP: + y_stride = prep->hor_stride * 4 * 3 / 2; + break; + case MPP_FMT_YUV422P: + case MPP_FMT_YUV422SP: + y_stride = prep->hor_stride * 4 * 2; + break; + case MPP_FMT_YUV444P: + case MPP_FMT_YUV444SP: + y_stride = prep->hor_stride * 4 * 3; + break; + default: + mpp_err("Unsupported input format 0x%08x, with TILE mask.\n", fmt); + return MPP_ERR_VALUE; + break; + } + } else { + y_stride = prep->hor_stride; + } + } else { + if (hw_fmt == VEPU5xx_FMT_BGRA8888 ) + y_stride = prep->width * 4; + else if (hw_fmt == VEPU5xx_FMT_BGR888 ) + y_stride = prep->width * 3; + else if (hw_fmt == VEPU5xx_FMT_BGR565 || + hw_fmt == VEPU5xx_FMT_YUYV422 || + hw_fmt == VEPU5xx_FMT_UYVY422) + y_stride = prep->width * 2; + else + y_stride = prep->width; + } + + switch (hw_fmt) { + case VEPU5xx_FMT_YUV444SP : { + c_stride = y_stride * 2; + } break; + case VEPU5xx_FMT_YUV422SP : + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV444P : { + c_stride = y_stride; + } break; + default : { + c_stride = y_stride / 2; + } break; + } + + if (hw_fmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = get_rgb2yuv_cfg(prep->range, prep->color); + + hal_h264e_dbg_flow("input color range %d colorspace %d", + prep->range, prep->color); + + reg_frm->common.src_udfy.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + reg_frm->common.src_udfy.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + reg_frm->common.src_udfy.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + + reg_frm->common.src_udfu.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + reg_frm->common.src_udfu.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + reg_frm->common.src_udfu.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + + reg_frm->common.src_udfv.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + reg_frm->common.src_udfv.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + reg_frm->common.src_udfv.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + + reg_frm->common.src_udfo.csc_ofst_y = cfg_coeffs->_2y.offset; + reg_frm->common.src_udfo.csc_ofst_u = cfg_coeffs->_2u.offset; + reg_frm->common.src_udfo.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h264e_dbg_flow("use color range %d colorspace %d", + cfg_coeffs->dst_range, cfg_coeffs->color); + } else { + reg_frm->common.src_udfy.csc_wgt_b2y = cfg.weight[0]; + reg_frm->common.src_udfy.csc_wgt_g2y = cfg.weight[1]; + reg_frm->common.src_udfy.csc_wgt_r2y = cfg.weight[2]; + + reg_frm->common.src_udfu.csc_wgt_b2u = cfg.weight[3]; + reg_frm->common.src_udfu.csc_wgt_g2u = cfg.weight[4]; + reg_frm->common.src_udfu.csc_wgt_r2u = cfg.weight[5]; + + reg_frm->common.src_udfv.csc_wgt_b2v = cfg.weight[6]; + reg_frm->common.src_udfv.csc_wgt_g2v = cfg.weight[7]; + reg_frm->common.src_udfv.csc_wgt_r2v = cfg.weight[8]; + + reg_frm->common.src_udfo.csc_ofst_y = cfg.offset[0]; + reg_frm->common.src_udfo.csc_ofst_u = cfg.offset[1]; + reg_frm->common.src_udfo.csc_ofst_v = cfg.offset[2]; + } + + reg_frm->common.src_strd0.src_strd0 = y_stride; + reg_frm->common.src_strd1.src_strd1 = c_stride; + + reg_frm->common.src_proc.src_mirr = prep->mirroring > 0; + reg_frm->common.src_proc.src_rot = prep->rotation; + + reg_frm->sli_cfg.mv_v_lmt_thd = 0; + reg_frm->sli_cfg.mv_v_lmt_en = 0; + + reg_frm->common.pic_ofst.pic_ofst_y = 0; + reg_frm->common.pic_ofst.pic_ofst_x = 0; + + hal_h264e_dbg_func("leave\n"); + + return ret; +} + +static MPP_RET vepu511a_h264e_save_pass1_patch(HalVepu511aRegSet *regs, HalH264eVepu511aCtx *ctx) +{ + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + reg_frm->common.enc_pic.cur_frm_ref = 1; + reg_frm->common.rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + reg_frm->common.rfpw_b_addr = reg_frm->common.rfpw_h_addr; + reg_frm->common.enc_pic.rec_fbc_dis = 1; + + mpp_dev_multi_offset_update(ctx->offsets, 164, width_align * height_align); + + /* NOTE: disable split to avoid lowdelay slice output */ + reg_frm->common.sli_splt.sli_splt = 0; + reg_frm->common.enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu511a_h264e_use_pass1_patch(HalVepu511aRegSet *regs, HalH264eVepu511aCtx *ctx) +{ + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 fd_in = mpp_buffer_get_fd(ctx->buf_pass1); + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + RK_S32 y_stride = width_align; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.enc_pic.rfpr_compress_mode = 1; + reg_frm->common.src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + reg_frm->common.src_fmt.alpha_swap = 0; + reg_frm->common.src_fmt.rbuv_swap = 0; + reg_frm->common.src_fmt.out_fmt = 1; + + reg_frm->common.src_strd0.src_strd0 = y_stride; + reg_frm->common.src_strd1.src_strd1 = y_stride; + + reg_frm->common.src_proc.src_mirr = 0; + reg_frm->common.src_proc.src_rot = 0; + + reg_frm->common.pic_ofst.pic_ofst_y = 0; + reg_frm->common.pic_ofst.pic_ofst_x = 0; + + reg_frm->common.adr_src0 = fd_in; + reg_frm->common.adr_src1 = fd_in; + + mpp_dev_multi_offset_update(ctx->offsets, 161, width_align * height_align); + + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + +static void setup_vepu511a_codec(HalVepu511aRegSet *regs, HalH264eVepu511aCtx *ctx) +{ + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.enc_pic.enc_stnd = 0; + reg_frm->common.enc_pic.cur_frm_ref = slice->nal_reference_idc > 0; + reg_frm->common.enc_pic.bs_scp = 1; + + reg_frm->synt_nal.nal_ref_idc = slice->nal_reference_idc; + reg_frm->synt_nal.nal_unit_type = slice->nalu_type; + + reg_frm->synt_sps.max_fnum = sps->log2_max_frame_num_minus4; + reg_frm->synt_sps.drct_8x8 = sps->direct8x8_inference; + reg_frm->synt_sps.mpoc_lm4 = sps->log2_max_poc_lsb_minus4; + reg_frm->synt_sps.poc_type = sps->pic_order_cnt_type; + + reg_frm->synt_pps.etpy_mode = pps->entropy_coding_mode; + reg_frm->synt_pps.trns_8x8 = pps->transform_8x8_mode; + reg_frm->synt_pps.csip_flag = pps->constrained_intra_pred; + reg_frm->synt_pps.num_ref0_idx = pps->num_ref_idx_l0_default_active - 1; + reg_frm->synt_pps.num_ref1_idx = pps->num_ref_idx_l1_default_active - 1; + reg_frm->synt_pps.pic_init_qp = pps->pic_init_qp; + reg_frm->synt_pps.cb_ofst = pps->chroma_qp_index_offset; + reg_frm->synt_pps.cr_ofst = pps->second_chroma_qp_index_offset; + reg_frm->synt_pps.dbf_cp_flg = pps->deblocking_filter_control; + + reg_frm->synt_sli0.sli_type = (slice->slice_type == H264_I_SLICE) ? (2) : (0); + reg_frm->synt_sli0.pps_id = slice->pic_parameter_set_id; + reg_frm->synt_sli0.drct_smvp = 0; + reg_frm->synt_sli0.num_ref_ovrd = slice->num_ref_idx_override; + reg_frm->synt_sli0.cbc_init_idc = slice->cabac_init_idc; + reg_frm->synt_sli0.frm_num = slice->frame_num; + + reg_frm->synt_sli1.idr_pid = (slice->slice_type == H264_I_SLICE) ? + slice->idr_pic_id : (RK_U32)(-1); + reg_frm->synt_sli1.poc_lsb = slice->pic_order_cnt_lsb; + + reg_frm->synt_sli2.dis_dblk_idc = slice->disable_deblocking_filter_idc; + reg_frm->synt_sli2.sli_alph_ofst = slice->slice_alpha_c0_offset_div2; + + h264e_reorder_rd_rewind(slice->reorder); + { /* reorder process */ + H264eRplmo rplmo; + MPP_RET ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + if (MPP_OK == ret) { + reg_frm->synt_sli2.ref_list0_rodr = 1; + reg_frm->synt_sli2.rodr_pic_idx = rplmo.modification_of_pic_nums_idc; + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + reg_frm->synt_sli2.rodr_pic_num = rplmo.abs_diff_pic_num_minus1; + } break; + case 2 : { + reg_frm->synt_sli2.rodr_pic_num = rplmo.long_term_pic_idx; + } break; + default : { + mpp_loge_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + } else { + // slice->ref_pic_list_modification_flag; + reg_frm->synt_sli2.ref_list0_rodr = 0; + reg_frm->synt_sli2.rodr_pic_idx = 0; + reg_frm->synt_sli2.rodr_pic_num = 0; + } + } + + /* clear all mmco arg first */ + reg_frm->synt_refm0.nopp_flg = 0; + reg_frm->synt_refm0.ltrf_flg = 0; + reg_frm->synt_refm0.arpm_flg = 0; + reg_frm->synt_refm0.mmco4_pre = 0; + reg_frm->synt_refm0.mmco_type0 = 0; + reg_frm->synt_refm0.mmco_parm0 = 0; + reg_frm->synt_refm0.mmco_type1 = 0; + reg_frm->synt_refm1.mmco_parm1 = 0; + reg_frm->synt_refm0.mmco_type2 = 0; + reg_frm->synt_refm1.mmco_parm2 = 0; + reg_frm->synt_refm2.long_term_frame_idx0 = 0; + reg_frm->synt_refm2.long_term_frame_idx1 = 0; + reg_frm->synt_refm2.long_term_frame_idx2 = 0; + + h264e_marking_rd_rewind(slice->marking); + + /* only update used parameter */ + if (slice->slice_type == H264_I_SLICE) { + reg_frm->synt_refm0.nopp_flg = slice->no_output_of_prior_pics; + reg_frm->synt_refm0.ltrf_flg = slice->long_term_reference_flag; + } else { + if (!h264e_marking_is_empty(slice->marking)) { + H264eMmco mmco; + + reg_frm->synt_refm0.arpm_flg = 1; + + /* max 3 mmco */ + do { + RK_S32 type = 0; + RK_S32 param_0 = 0; + RK_S32 param_1 = 0; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_loge_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + reg_frm->synt_refm0.mmco_type0 = type; + reg_frm->synt_refm0.mmco_parm0 = param_0; + reg_frm->synt_refm2.long_term_frame_idx0 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_loge_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + reg_frm->synt_refm0.mmco_type1 = type; + reg_frm->synt_refm1.mmco_parm1 = param_0; + reg_frm->synt_refm2.long_term_frame_idx1 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_loge_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + reg_frm->synt_refm0.mmco_type2 = type; + reg_frm->synt_refm1.mmco_parm2 = param_0; + reg_frm->synt_refm2.long_term_frame_idx2 = param_1; + } while (0); + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_rdo_pred(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->rdo_cfg.rect_size = (sps->profile_idc == H264_PROFILE_BASELINE && + sps->level_idc <= H264_LEVEL_3_0) ? 1 : 0; + reg_frm->rdo_cfg.vlc_lmt = (sps->profile_idc < H264_PROFILE_MAIN) && + !pps->entropy_coding_mode; + reg_frm->rdo_cfg.ccwa_e = 1; + reg_frm->rdo_cfg.scl_lst_sel = pps->pic_scaling_matrix_present; + reg_frm->rdo_cfg.atf_e = ctx->cfg->tune.anti_flicker_str > 0; + reg_frm->rdo_cfg.atr_e = ctx->cfg->tune.atr_str_i > 0; + reg_frm->rdo_cfg.atr_mult_sel_e = 1; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_rc_base(HalVepu511aRegSet *regs, HalH264eVepu511aCtx *ctx, EncRcTask *rc_task) +{ + H264eSps *sps = ctx->sps; + H264eSlice *slice = ctx->slice; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + EncRcTaskInfo *rc_info = &rc_task->info; + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 mb_w = sps->pic_width_in_mbs; + RK_S32 mb_h = sps->pic_height_in_mbs; + RK_U32 qp_target = rc_info->quality_target; + RK_U32 qp_min = rc_info->quality_min; + RK_U32 qp_max = rc_info->quality_max; + RK_S32 mb_target_bits_mul_16 = (rc_info->bit_target << 4) / (mb_w * mb_h); + RK_S32 mb_target_bits; + RK_S32 negative_bits_thd; + RK_S32 positive_bits_thd; + + hal_h264e_dbg_rc("bittarget %d qp [%d %d %d]\n", rc_info->bit_target, + qp_min, qp_target, qp_max); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_rc_roi.roi_qthd0.qpmin_area0 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area0 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area1 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area1 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area2 = qp_min; + + regs->reg_rc_roi.roi_qthd1.qpmax_area2 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area3 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area3 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area4 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area4 = qp_max; + + regs->reg_rc_roi.roi_qthd2.qpmin_area5 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area5 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area6 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area6 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area7 = qp_min; + regs->reg_rc_roi.roi_qthd3.qpmax_area7 = qp_max; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + reg_frm->common.enc_pic.pic_qp = rc_info->quality_target; + reg_frm->common.rc_qp.rc_max_qp = rc_info->quality_target; + reg_frm->common.rc_qp.rc_min_qp = rc_info->quality_target; + + return; + } + + if (mb_target_bits_mul_16 >= 0x100000) + mb_target_bits_mul_16 = 0x50000; + + mb_target_bits = (mb_target_bits_mul_16 * mb_w) >> 4; + negative_bits_thd = 0 - 5 * mb_target_bits / 16; + positive_bits_thd = 5 * mb_target_bits / 16; + + reg_frm->common.enc_pic.pic_qp = qp_target; + + reg_frm->common.rc_cfg.rc_en = 1; + reg_frm->common.rc_cfg.aq_en = 1; + reg_frm->common.rc_cfg.rc_ctu_num = mb_w; + + reg_frm->common.rc_qp.rc_max_qp = qp_max; + reg_frm->common.rc_qp.rc_min_qp = qp_min; + reg_frm->common.rc_tgt.ctu_ebit = mb_target_bits_mul_16; + + if (rc->rc_mode == MPP_ENC_RC_MODE_SMTRC) { + reg_frm->common.rc_qp.rc_qp_range = 0; + } else { + reg_frm->common.rc_qp.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? + hw->qp_delta_row_i : hw->qp_delta_row; + } + + { + /* fixed frame level QP */ + RK_S32 fqp_min, fqp_max; + + if (slice->slice_type == H264_I_SLICE) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 1) && (fqp_max <= 51)) { + reg_frm->common.enc_pic.pic_qp = fqp_min; + reg_frm->common.rc_qp.rc_qp_range = 0; + } + } + + regs->reg_rc_roi.rc_adj0.qp_adj0 = -2; + regs->reg_rc_roi.rc_adj0.qp_adj1 = -1; + regs->reg_rc_roi.rc_adj0.qp_adj2 = 0; + regs->reg_rc_roi.rc_adj0.qp_adj3 = 1; + regs->reg_rc_roi.rc_adj0.qp_adj4 = 2; + regs->reg_rc_roi.rc_adj1.qp_adj5 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj6 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj7 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj8 = 0; + + regs->reg_rc_roi.rc_dthd_0_8[0] = 4 * negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[1] = negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[2] = positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[3] = 4 * positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[4] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[5] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[6] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[7] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[8] = 0x7FFFFFFF; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_io_buf(HalVepu511aRegSet *regs, MppDevRegOffCfgs *offsets, + HalEncTask *task) +{ + MppFrame frm = task->frame; + MppPacket pkt = task->packet; + MppBuffer buf_in = mpp_frame_get_buffer(frm); + MppBuffer buf_out = task->output; + MppFrameFormat fmt = mpp_frame_get_fmt(frm); + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 hor_stride = mpp_frame_get_hor_stride(frm); + RK_S32 ver_stride = mpp_frame_get_ver_stride(frm); + RK_S32 fd_in = mpp_buffer_get_fd(buf_in); + RK_U32 off_in[2] = {0}; + RK_U32 off_out = mpp_packet_get_length(pkt); + size_t siz_out = mpp_buffer_get_size(buf_out); + RK_S32 fd_out = mpp_buffer_get_fd(buf_out); + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.adr_src0 = fd_in; + reg_frm->common.adr_src1 = fd_in; + reg_frm->common.adr_src2 = fd_in; + + reg_frm->common.bsbt_addr = fd_out; + reg_frm->common.bsbb_addr = fd_out; + reg_frm->common.adr_bsbs = fd_out; + reg_frm->common.bsbr_addr = fd_out; + + reg_frm->common.rfpt_h_addr = 0xffffffff; + reg_frm->common.rfpb_h_addr = 0; + reg_frm->common.rfpt_b_addr = 0xffffffff; + reg_frm->common.adr_rfpb_b = 0; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + off_in[0] = mpp_frame_get_fbc_offset(task->frame);; + off_in[1] = off_in[0]; + } else if (MPP_FRAME_FMT_IS_YUV(fmt)) { + VepuFmtCfg cfg; + + vepu5xx_set_fmt(&cfg, fmt); + switch (cfg.format) { + case VEPU5xx_FMT_BGRA8888 : + case VEPU5xx_FMT_BGR888 : + case VEPU5xx_FMT_BGR565 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV422SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV422P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 3 / 2; + } break; + case VEPU5xx_FMT_YUV420P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 5 / 4; + } break; + case VEPU5xx_FMT_YUV400 : + case VEPU5xx_FMT_YUYV422 : + case VEPU5xx_FMT_UYVY422 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 2; + } break; + default : { + off_in[0] = 0; + off_in[1] = 0; + } break; + } + } + + mpp_dev_multi_offset_update(offsets, 161, off_in[0]); + mpp_dev_multi_offset_update(offsets, 162, off_in[1]); + mpp_dev_multi_offset_update(offsets, 172, siz_out); + mpp_dev_multi_offset_update(offsets, 174, off_out); + + reg_frm->common.meiw_addr = task->md_info ? mpp_buffer_get_fd(task->md_info) : 0; + reg_frm->common.enc_pic.mei_stor = 0; + reg_frm->common.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + reg_frm->common.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET vepu511a_h264_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h) +{ + Vepu511aRoiH264BsCfg *ptr = (Vepu511aRoiH264BsCfg *)buf; + RK_S32 mb_w = MPP_ALIGN(w, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(h, 16) / 16; + RK_S32 stride_h = MPP_ALIGN(mb_w, 4); + Vepu511aRoiH264BsCfg cfg; + MPP_RET ret = MPP_NOK; + + if (NULL == buf || NULL == region) { + mpp_loge_f("invalid buf %p roi %p\n", buf, region); + goto DONE; + } + + RK_S32 roi_width = (region->w + 15) / 16; + RK_S32 roi_height = (region->h + 15) / 16; + RK_S32 pos_x_init = region->x / 16; + RK_S32 pos_y_init = region->y / 16; + RK_S32 pos_x_end = pos_x_init + roi_width; + RK_S32 pos_y_end = pos_y_init + roi_height; + RK_S32 x, y; + + pos_x_end = MPP_MIN(pos_x_end, mb_w); + pos_y_end = MPP_MIN(pos_y_end, mb_h); + pos_x_init = MPP_MAX(pos_x_init, 0); + pos_y_init = MPP_MAX(pos_y_init, 0); + + mpp_assert(pos_x_end > pos_x_init); + mpp_assert(pos_y_end > pos_y_init); + + cfg.force_intra = 1; + + ptr += pos_y_init * stride_h + pos_x_init; + roi_width = pos_x_end - pos_x_init; + roi_height = pos_y_end - pos_y_init; + + for (y = 0; y < roi_height; y++) { + Vepu511aRoiH264BsCfg *dst = ptr; + + for (x = 0; x < roi_width; x++, dst++) + memcpy(dst, &cfg, sizeof(cfg)); + + ptr += stride_h; + } +DONE: + return ret; +} + +static MPP_RET setup_vepu511a_intra_refresh(HalVepu511aRegSet *regs, HalH264eVepu511aCtx *ctx, RK_U32 refresh_idx) +{ + MPP_RET ret = MPP_OK; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 w = mb_w * 16; + RK_U32 h = mb_h * 16; + MppEncROIRegion *region = NULL; + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_U32 refresh_num = ctx->cfg->rc.refresh_num; + RK_U32 stride_h = MPP_ALIGN(mb_w, 4); + RK_U32 stride_v = MPP_ALIGN(mb_h, 4); + RK_U32 roi_base_buf_size = stride_h * stride_v * 8; + RK_U32 i = 0; + + hal_h264e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en) { + ret = MPP_ERR_VALUE; + goto RET; + } + + if (NULL == ctx->roi_base_cfg_buf) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + mpp_buffer_get(ctx->roi_grp, &ctx->roi_base_cfg_buf, roi_base_buf_size); + ctx->roi_base_buf_size = roi_base_buf_size; + } + + mpp_assert(ctx->roi_base_cfg_buf); + void *base_cfg_buf = mpp_buffer_get_ptr(ctx->roi_base_cfg_buf); + Vepu511aRoiH264BsCfg base_cfg; + Vepu511aRoiH264BsCfg *base_cfg_ptr = (Vepu511aRoiH264BsCfg *)base_cfg_buf; + + base_cfg.force_intra = 0; + base_cfg.qp_adj_en = 1; + + for (i = 0; i < stride_h * stride_v; i++, base_cfg_ptr++) + memcpy(base_cfg_ptr, &base_cfg, sizeof(base_cfg)); + + region = mpp_calloc(MppEncROIRegion, 1); + + if (NULL == region) { + mpp_loge_f("Failed to calloc for MppEncROIRegion !\n"); + ret = MPP_ERR_MALLOC; + } + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + region->x = 0; + region->w = w; + if (refresh_idx > 0) { + region->y = refresh_idx * 16 * refresh_num - 32; + region->h = 16 * refresh_num + 32; + } else { + region->y = refresh_idx * 16 * refresh_num; + region->h = 16 * refresh_num; + } + reg_frm->common.me_rnge.cime_srch_uph = 1; + } else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) { + region->y = 0; + region->h = h; + if (refresh_idx > 0) { + region->x = refresh_idx * 16 * refresh_num - 32; + region->w = 16 * refresh_num + 32; + } else { + region->x = refresh_idx * 16 * refresh_num; + region->w = 16 * refresh_num; + } + reg_frm->common.me_rnge.cime_srch_dwnh = 1; + } + + region->intra = 1; + region->quality = -ctx->cfg->rc.qp_delta_ip; + + region->area_map_en = 1; + region->qp_area_idx = 1; + region->abs_qp_en = 0; + + vepu511a_h264_set_one_roi(base_cfg_buf, region, w, h); + mpp_free(region); +RET: + hal_h264e_dbg_func("leave, ret %d\n", ret); + return ret; +} + +static void setup_vepu511a_recn_refr(HalH264eVepu511aCtx *ctx, HalVepu511aRegSet *regs) +{ + + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + H264eFrmInfo *frms = ctx->frms; + HalBufs bufs = ctx->hw_recn; + RK_S32 fbc_hdr_size = ctx->pixel_buf_fbc_hdr_size; + + HalBuf *curr = hal_bufs_get_buf(bufs, frms->curr_idx); + HalBuf *refr = hal_bufs_get_buf(bufs, frms->refr_idx); + + hal_h264e_dbg_func("enter\n"); + + if (curr && curr->cnt) { + MppBuffer buf_pixel = curr->buf[0]; + MppBuffer buf_thumb = curr->buf[1]; + MppBuffer buf_smear = curr->buf[2]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + reg_frm->common.rfpw_h_addr = fd; + reg_frm->common.rfpw_b_addr = fd; + reg_frm->common.dspw_addr = mpp_buffer_get_fd(buf_thumb); + reg_frm->common.adr_smear_wr = mpp_buffer_get_fd(buf_smear); + } + + if (refr && refr->cnt) { + MppBuffer buf_pixel = refr->buf[0]; + MppBuffer buf_thumb = refr->buf[1]; + MppBuffer buf_smear = curr->buf[2]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + reg_frm->common.rfpr_h_addr = fd; + reg_frm->common.rfpr_b_addr = fd; + reg_frm->common.dspr_addr = mpp_buffer_get_fd(buf_thumb); + reg_frm->common.adr_smear_rd = mpp_buffer_get_fd(buf_smear); + } + mpp_dev_multi_offset_update(ctx->offsets, 164, fbc_hdr_size); + mpp_dev_multi_offset_update(ctx->offsets, 166, fbc_hdr_size); + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_split(HalVepu511aRegSet *regs, MppEncCfgSet *enc_cfg) +{ + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h264e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + reg_frm->common.sli_splt.sli_splt = 0; + reg_frm->common.sli_splt.sli_splt_mode = 0; + reg_frm->common.sli_splt.sli_splt_cpst = 0; + reg_frm->common.sli_splt.sli_max_num_m1 = 0; + reg_frm->common.sli_splt.sli_flsh = 0; + reg_frm->common.sli_cnum.sli_splt_cnum_m1 = 0; + + reg_frm->common.sli_byte.sli_splt_byte = 0; + reg_frm->common.enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + reg_frm->common.sli_splt.sli_splt = 1; + reg_frm->common.sli_splt.sli_splt_mode = 0; + reg_frm->common.sli_splt.sli_splt_cpst = 0; + reg_frm->common.sli_splt.sli_max_num_m1 = 500; + reg_frm->common.sli_splt.sli_flsh = 1; + reg_frm->common.sli_cnum.sli_splt_cnum_m1 = 0; + + reg_frm->common.sli_byte.sli_splt_byte = cfg->split_arg; + reg_frm->common.enc_pic.slen_fifo = cfg->split_out ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = reg_frm->common.enc_pic.slen_fifo; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + RK_U32 mb_w = MPP_ALIGN(enc_cfg->prep.width, 16) / 16; + RK_U32 mb_h = MPP_ALIGN(enc_cfg->prep.height, 16) / 16; + RK_U32 slice_num = (mb_w * mb_h + cfg->split_arg - 1) / cfg->split_arg; + + reg_frm->common.sli_splt.sli_splt = 1; + reg_frm->common.sli_splt.sli_splt_mode = 1; + reg_frm->common.sli_splt.sli_splt_cpst = 0; + reg_frm->common.sli_splt.sli_max_num_m1 = 500; + reg_frm->common.sli_splt.sli_flsh = 1; + reg_frm->common.sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + reg_frm->common.sli_byte.sli_splt_byte = 0; + reg_frm->common.enc_pic.slen_fifo = cfg->split_out ? 1 : 0; + if ((cfg->split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) || + (regs->reg_frm.common.enc_pic.slen_fifo && (slice_num > VEPU511A_SLICE_FIFO_LEN))) + regs->reg_ctl.int_en.vslc_done_en = 1; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_me(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + H264eVepu511aParam *reg_param = ®s->reg_param; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + + hal_h264e_dbg_func("enter\n"); + + reg_frm->common.me_rnge.cime_srch_dwnh = 15; + reg_frm->common.me_rnge.cime_srch_uph = 15; + reg_frm->common.me_rnge.cime_srch_rgtw = 12; + reg_frm->common.me_rnge.cime_srch_lftw = 12; + reg_frm->common.me_cfg.rme_srch_h = 3; + reg_frm->common.me_cfg.rme_srch_v = 3; + + reg_frm->common.me_cfg.srgn_max_num = 54; + reg_frm->common.me_cfg.cime_dist_thre = 1024; + reg_frm->common.me_cfg.rme_dis = 0; + reg_frm->common.me_cfg.fme_dis = 0; + reg_frm->common.me_rnge.dlt_frm_num = 0x0; + reg_frm->common.me_cach.cime_zero_thre = 64; + + /* CIME: 0x1760 - 0x176C */ + reg_param->me_sqi_comb.cime_pmv_num = 1; + reg_param->me_sqi_comb.cime_fuse = 1; + reg_param->me_sqi_comb.move_lambda = 0; + reg_param->me_sqi_comb.rime_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prersu_en = 0; + reg_param->cime_mvd_th_comb.cime_mvd_th0 = 16; + reg_param->cime_mvd_th_comb.cime_mvd_th1 = 48; + reg_param->cime_mvd_th_comb.cime_mvd_th2 = 80; + reg_param->cime_madp_th_comb.cime_madp_th = 16; + reg_param->cime_madp_th_comb.ratio_consi_cfg = 13; + reg_param->cime_madp_th_comb.ratio_bmv_dist = 9; + reg_param->cime_multi_comb.cime_multi0 = 8; + reg_param->cime_multi_comb.cime_multi1 = 12; + reg_param->cime_multi_comb.cime_multi2 = 16; + reg_param->cime_multi_comb.cime_multi3 = 20; + + /* RFME: 0x1770 - 0x1778 */ + reg_param->rime_mvd_th_comb.rime_mvd_th0 = 1; + reg_param->rime_mvd_th_comb.rime_mvd_th1 = 2; + reg_param->rime_mvd_th_comb.fme_madp_th = 0; + reg_param->rime_madp_th_comb.rime_madp_th0 = 8; + reg_param->rime_madp_th_comb.rime_madp_th1 = 16; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 8; + reg_param->rime_multi_comb.rime_multi2 = 12; + reg_param->cmv_st_th_comb.cmv_th0 = 64; + reg_param->cmv_st_th_comb.cmv_th1 = 96; + reg_param->cmv_st_th_comb.cmv_th2 = 128; + + if (sm != MPP_ENC_SCENE_MODE_IPC) { + /* disable subjective optimization */ + reg_param->cime_madp_th_comb.cime_madp_th = 0; + reg_param->rime_madp_th_comb.rime_madp_th0 = 0; + reg_param->rime_madp_th_comb.rime_madp_th1 = 0; + reg_param->cime_multi_comb.cime_multi0 = 4; + reg_param->cime_multi_comb.cime_multi1 = 4; + reg_param->cime_multi_comb.cime_multi2 = 4; + reg_param->cime_multi_comb.cime_multi3 = 4; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 4; + reg_param->rime_multi_comb.rime_multi2 = 4; + } + + /* 0x1064 */ + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + /* 0x1068 */ + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + /* 0x106C */ + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; + + hal_h264e_dbg_func("leave\n"); +} + +static void vepu511a_set_speed(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + H264eVepu511aParam *reg_param = ®s->reg_param; + H264eSlice *slice = ctx->slice; + RK_S32 is_ipc_scene = ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC; + RK_S32 ppc_level = ctx->cfg->tune.speed; + + /* Speed mode 0-5 (ppc = pixels per cycle): + * 0 - slowest (ppc 0.35, best quality) + * 1 - slow (ppc 0.4) + * 2 - medium (ppc 0.5) + * 3 - fast (ppc 0.6) + * 4 - faster (ppc 0.6_1) + * 5 - fastest (ppc 0.6_2, worst quality) + */ + hal_h264e_dbg_func("enter\n"); + hal_h264e_dbg_detail("vepu511a_set_speed ppc_level %d\n", ppc_level); + + switch (ppc_level) { + case 0: + default: { // speed mode 0: slowest (ppc 0.35, best quality) + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + reg_frm->rdo_mark_mode.iframe_i16_rdo_num = 2; + reg_frm->rdo_mark_mode.i8_rdo_num = 2; + reg_frm->rdo_mark_mode.iframe_i4_rdo_num = 2; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = is_ipc_scene ? 9 : 6; + reg_frm->rdo_mark_mode.p16_interp_num = 3; + reg_frm->rdo_mark_mode.p16t8_rdo_num = 3; + reg_frm->rdo_mark_mode.p16t4_rmd_num = 2; + reg_frm->rdo_mark_mode.p8_interp_num = 3; + reg_frm->rdo_mark_mode.p8t8_rdo_num = 2; + reg_frm->rdo_mark_mode.p8t4_rmd_num = 2; + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 2; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + } + + reg_frm->rdo_mark_mode.rdo_mark_mode = 0; + reg_param->me_sqi_comb.fme_lvl_mrg = 0; + reg_param->me_sqi_comb.rime_prelvl_en = 3; + break; + } + + case 1: { // speed mode 1: slow (ppc 0.4) + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + reg_frm->rdo_mark_mode.iframe_i16_rdo_num = 2; + reg_frm->rdo_mark_mode.i8_rdo_num = 1; + reg_frm->rdo_mark_mode.iframe_i4_rdo_num = 2; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = is_ipc_scene ? 9 : 6; + reg_frm->rdo_mark_mode.p16_interp_num = 2; + reg_frm->rdo_mark_mode.p16t8_rdo_num = 2; + reg_frm->rdo_mark_mode.p16t4_rmd_num = 2; + reg_frm->rdo_mark_mode.p8_interp_num = 2; + reg_frm->rdo_mark_mode.p8t8_rdo_num = 2; + reg_frm->rdo_mark_mode.p8t4_rmd_num = 2; + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + } + + reg_frm->rdo_mark_mode.rdo_mark_mode = 0; + reg_param->me_sqi_comb.fme_lvl_mrg = 0; + reg_param->me_sqi_comb.rime_prelvl_en = 3; + break; + } + + case 2: { // speed mode 2: medium (ppc 0.5) + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + reg_frm->rdo_mark_mode.iframe_i16_rdo_num = 2; + reg_frm->rdo_mark_mode.i8_rdo_num = 1; + reg_frm->rdo_mark_mode.iframe_i4_rdo_num = 1; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = is_ipc_scene ? 9 : 6; + reg_frm->rdo_mark_mode.p16_interp_num = 2; + reg_frm->rdo_mark_mode.p16t8_rdo_num = 2; + reg_frm->rdo_mark_mode.p16t4_rmd_num = 2; + reg_frm->rdo_mark_mode.p8_interp_num = 1; + reg_frm->rdo_mark_mode.p8t8_rdo_num = 1; + reg_frm->rdo_mark_mode.p8t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + } + + reg_frm->rdo_mark_mode.rdo_mark_mode = 256; + reg_param->me_sqi_comb.fme_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prelvl_en = 3; + break; + } + + case 3: { // speed mode 3: fastest (ppc 0.6, lowest quality) + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + reg_frm->rdo_mark_mode.iframe_i16_rdo_num = 2; + reg_frm->rdo_mark_mode.i8_rdo_num = 1; + reg_frm->rdo_mark_mode.iframe_i4_rdo_num = 1; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = is_ipc_scene ? 9 : 6; + reg_frm->rdo_mark_mode.p16_interp_num = 1; + reg_frm->rdo_mark_mode.p16t8_rdo_num = 1; + reg_frm->rdo_mark_mode.p16t4_rmd_num = 1; + reg_frm->rdo_mark_mode.p8_interp_num = 1; + reg_frm->rdo_mark_mode.p8t8_rdo_num = 1; + reg_frm->rdo_mark_mode.p8t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + } + + reg_frm->rdo_mark_mode.rdo_mark_mode = 257; + reg_param->me_sqi_comb.fme_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prelvl_en = 0; + break; + } + + case 4: { // ppc 0.6_1 + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + reg_frm->rdo_mark_mode.iframe_i16_rdo_num = 2; + reg_frm->rdo_mark_mode.i8_rdo_num = 1; + reg_frm->rdo_mark_mode.iframe_i4_rdo_num = 1; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = is_ipc_scene ? 9 : 6; + reg_frm->rdo_mark_mode.p16_interp_num = 2; + reg_frm->rdo_mark_mode.p16t8_rdo_num = 2; + reg_frm->rdo_mark_mode.p16t4_rmd_num = 1; + reg_frm->rdo_mark_mode.p8_interp_num = 1; + reg_frm->rdo_mark_mode.p8t8_rdo_num = 1; + reg_frm->rdo_mark_mode.p8t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + } + + reg_frm->rdo_mark_mode.rdo_mark_mode = 256; + reg_param->me_sqi_comb.fme_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prelvl_en = 0; + break; + } + + case 5: { // ppc 0.6_2 + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + reg_frm->rdo_mark_mode.iframe_i16_rdo_num = 2; + reg_frm->rdo_mark_mode.i8_rdo_num = 1; + reg_frm->rdo_mark_mode.iframe_i4_rdo_num = 1; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = is_ipc_scene ? 9 : 6; + reg_frm->rdo_mark_mode.p16_interp_num = 2; + reg_frm->rdo_mark_mode.p16t8_rdo_num = 2; + reg_frm->rdo_mark_mode.p16t4_rmd_num = 0; + reg_frm->rdo_mark_mode.p8_interp_num = 1; + reg_frm->rdo_mark_mode.p8t8_rdo_num = 1; + reg_frm->rdo_mark_mode.p8t4_rmd_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i16_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.i8_rdo_num = 1; + regs->reg_frm.rdo_mark_mode.iframe_i4_rdo_num = 1; + } + + reg_frm->rdo_mark_mode.rdo_mark_mode = 260; + reg_param->me_sqi_comb.fme_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prelvl_en = 0; + break; + } + } + hal_h264e_dbg_func("leave\n"); +} + + +#define H264E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) + +static RK_U32 h264e_lambda_default[60] = { + 0x00000005, 0x00000006, 0x00000007, 0x00000009, + 0x0000000b, 0x0000000e, 0x00000012, 0x00000016, + 0x0000001c, 0x00000024, 0x0000002d, 0x00000039, + 0x00000048, 0x0000005b, 0x00000073, 0x00000091, + 0x000000b6, 0x000000e6, 0x00000122, 0x0000016d, + 0x000001cc, 0x00000244, 0x000002db, 0x00000399, + 0x00000489, 0x000005b6, 0x00000733, 0x00000912, + 0x00000b6d, 0x00000e66, 0x00001224, 0x000016db, + 0x00001ccc, 0x00002449, 0x00002db7, 0x00003999, + 0x00004892, 0x00005b6f, 0x00007333, 0x00009124, + 0x0000b6de, 0x0000e666, 0x00012249, 0x00016dbc, + 0x0001cccc, 0x00024492, 0x0002db79, 0x00039999, + 0x00048924, 0x0005b6f2, 0x00073333, 0x00091249, + 0x000b6de5, 0x000e6666, 0x00122492, 0x0016dbcb, + 0x001ccccc, 0x00244924, 0x002db796, 0x00399998, +}; + +static RK_U32 h264e_lambda_cvr[60] = { + 0x00000009, 0x0000000b, 0x0000000e, 0x00000011, + 0x00000016, 0x0000001b, 0x00000022, 0x0000002b, + 0x00000036, 0x00000045, 0x00000056, 0x0000006d, + 0x00000089, 0x000000ad, 0x000000da, 0x00000112, + 0x00000159, 0x000001b3, 0x00000224, 0x000002b3, + 0x00000366, 0x00000449, 0x00000566, 0x000006cd, + 0x00000891, 0x00000acb, 0x00000d9a, 0x000013c1, + 0x000018e4, 0x00001f5c, 0x00002783, 0x000031c8, + 0x00003eb8, 0x00004f06, 0x00006390, 0x00008e14, + 0x0000b302, 0x0000e18a, 0x00011c29, 0x00016605, + 0x0001c313, 0x00027ae1, 0x00031fe6, 0x0003efcf, + 0x0004f5c3, 0x0006e785, 0x0008b2ef, 0x000af5c3, + 0x000f1e7a, 0x00130c7f, 0x00180000, 0x001e3cf4, + 0x002618fe, 0x00300000, 0x003c79e8, 0x004c31fc, + 0x00600000, 0x0078f3d0, 0x009863f8, 0x0c000000, +}; + +static void +setup_vepu511a_l2(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + RK_S32 lambda_idx = ctx->cfg->tune.lambda_idx_i; //TODO: lambda_idx_p + + hal_h264e_dbg_func("enter\n"); + + if (sm == MPP_ENC_SCENE_MODE_IPC) { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_default[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } else { + memcpy(regs->reg_param.rdo_wgta_qp_grpa_0_51, + &h264e_lambda_cvr[lambda_idx], H264E_LAMBDA_TAB_SIZE); + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_ext_line_buf(HalVepu511aRegSet *regs, HalH264eVepu511aCtx *ctx) +{ + H264eVepu511aFrame *reg_frm = ®s->reg_frm; + MppDevRcbInfoCfg rcb_cfg; + RK_S32 offset = 0; + RK_S32 fd; + + if (!ctx->ext_line_buf) { + reg_frm->common.ebufb_addr = 0; + reg_frm->common.ebufb_addr = 0; + return; + } + + fd = mpp_buffer_get_fd(ctx->ext_line_buf); + offset = ctx->ext_line_buf_size; + + reg_frm->common.ebuft_addr = fd; + reg_frm->common.ebufb_addr = fd; + + mpp_dev_multi_offset_update(ctx->offsets, 178, offset); + + /* rcb info for sram */ + rcb_cfg.reg_idx = 179; + rcb_cfg.size = offset; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); + + rcb_cfg.reg_idx = 178; + rcb_cfg.size = 0; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); +} + +static void setup_vepu511a_aq(HalH264eVepu511aCtx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncHwCfg *hw = &cfg->hw; + Vepu511aRcRoi *s = &ctx->regs_set->reg_rc_roi; + RK_S32 *aq_step, *aq_thd; + RK_U8 i; + + if (ctx->slice->slice_type == H264_I_SLICE) { + aq_thd = (RK_S32 *)&hw->aq_thrd_i[0]; + aq_step = &hw->aq_step_i[0]; + } else { + aq_thd = (RK_S32 *)&hw->aq_thrd_p[0]; + aq_step = &hw->aq_step_p[0]; + } + + for (i = 0; i < 16; i++) + s->aq_tthd[i] = aq_thd[i] & 0xff; + + s->aq_stp0.aq_stp_s0 = aq_step[0] & 0x1f; + s->aq_stp0.aq_stp_0t1 = aq_step[1] & 0x1f; + s->aq_stp0.aq_stp_1t2 = aq_step[2] & 0x1f; + s->aq_stp0.aq_stp_2t3 = aq_step[3] & 0x1f; + s->aq_stp0.aq_stp_3t4 = aq_step[4] & 0x1f; + s->aq_stp0.aq_stp_4t5 = aq_step[5] & 0x1f; + s->aq_stp1.aq_stp_5t6 = aq_step[6] & 0x1f; + s->aq_stp1.aq_stp_6t7 = aq_step[7] & 0x1f; + s->aq_stp1.aq_stp_7t8 = 0; + s->aq_stp1.aq_stp_8t9 = aq_step[8] & 0x1f; + s->aq_stp1.aq_stp_9t10 = aq_step[9] & 0x1f; + s->aq_stp1.aq_stp_10t11 = aq_step[10] & 0x1f; + s->aq_stp2.aq_stp_11t12 = aq_step[11] & 0x1f; + s->aq_stp2.aq_stp_12t13 = aq_step[12] & 0x1f; + s->aq_stp2.aq_stp_13t14 = aq_step[13] & 0x1f; + s->aq_stp2.aq_stp_14t15 = aq_step[14] & 0x1f; + s->aq_stp2.aq_stp_b15 = aq_step[15] & 0x1f; +} + +static void setup_vepu511a_anti_stripe(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aParam *s = ®s->reg_param; + RK_S32 str = ctx->cfg->tune.atl_str; + + s->iprd_tthdy4_0.iprd_tthdy4_0 = 1; + s->iprd_tthdy4_0.iprd_tthdy4_1 = 3; + s->iprd_tthdy4_1.iprd_tthdy4_2 = 6; + s->iprd_tthdy4_1.iprd_tthdy4_3 = 8; + s->iprd_tthdc8_0.iprd_tthdc8_0 = 1; + s->iprd_tthdc8_0.iprd_tthdc8_1 = 3; + s->iprd_tthdc8_1.iprd_tthdc8_2 = 6; + s->iprd_tthdc8_1.iprd_tthdc8_3 = 8; + s->iprd_tthdy8_0.iprd_tthdy8_0 = 1; + s->iprd_tthdy8_0.iprd_tthdy8_1 = 3; + s->iprd_tthdy8_1.iprd_tthdy8_2 = 6; + s->iprd_tthdy8_1.iprd_tthdy8_3 = 8; + + if (ctx->cfg->tune.scene_mode != MPP_ENC_SCENE_MODE_IPC) + s->iprd_tthd_ul.iprd_tthd_ul = 4095; /* disable anti-stripe */ + else + s->iprd_tthd_ul.iprd_tthd_ul = str ? 4 : 255; + + s->iprd_wgty8.iprd_wgty8_0 = str ? 22 : 16; + s->iprd_wgty8.iprd_wgty8_1 = str ? 23 : 16; + s->iprd_wgty8.iprd_wgty8_2 = str ? 20 : 16; + s->iprd_wgty8.iprd_wgty8_3 = str ? 22 : 16; + s->iprd_wgty4.iprd_wgty4_0 = str ? 22 : 16; + s->iprd_wgty4.iprd_wgty4_1 = str ? 26 : 16; + s->iprd_wgty4.iprd_wgty4_2 = str ? 20 : 16; + s->iprd_wgty4.iprd_wgty4_3 = str ? 22 : 16; + s->iprd_wgty16.iprd_wgty16_0 = 22; + s->iprd_wgty16.iprd_wgty16_1 = 26; + s->iprd_wgty16.iprd_wgty16_2 = 20; + s->iprd_wgty16.iprd_wgty16_3 = 22; + s->iprd_wgtc8.iprd_wgtc8_0 = 18; + s->iprd_wgtc8.iprd_wgtc8_1 = 21; + s->iprd_wgtc8.iprd_wgtc8_2 = 20; + s->iprd_wgtc8.iprd_wgtc8_3 = 19; +} + +static void setup_vepu511a_anti_ringing(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aSqi *s = ®s->reg_sqi; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + + s->atr_thd.atr_qp = (sm == MPP_ENC_SCENE_MODE_IPC) ? 32 : 45; + if (ctx->slice->slice_type == H264_I_SLICE) { + s->atr_thd.atr_thd0 = 1; + s->atr_thd.atr_thd1 = 2; + s->atr_thd.atr_thd2 = 6; + s->atr_wgt16.atr_lv16_wgt0 = 16; + s->atr_wgt16.atr_lv16_wgt1 = 16; + s->atr_wgt16.atr_lv16_wgt2 = 16; + + if (sm == MPP_ENC_SCENE_MODE_IPC) { + s->atr_wgt8.atr_lv8_wgt0 = 22; + s->atr_wgt8.atr_lv8_wgt1 = 21; + s->atr_wgt8.atr_lv8_wgt2 = 20; + s->atr_wgt4.atr_lv4_wgt0 = 20; + s->atr_wgt4.atr_lv4_wgt1 = 18; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } else { + s->atr_wgt8.atr_lv8_wgt0 = 18; + s->atr_wgt8.atr_lv8_wgt1 = 17; + s->atr_wgt8.atr_lv8_wgt2 = 18; + s->atr_wgt4.atr_lv4_wgt0 = 16; + s->atr_wgt4.atr_lv4_wgt1 = 16; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } + } else { + if (sm == MPP_ENC_SCENE_MODE_IPC) { + s->atr_thd.atr_thd0 = 2; + s->atr_thd.atr_thd1 = 4; + s->atr_thd.atr_thd2 = 9; + s->atr_wgt16.atr_lv16_wgt0 = 25; + s->atr_wgt16.atr_lv16_wgt1 = 20; + s->atr_wgt16.atr_lv16_wgt2 = 16; + s->atr_wgt8.atr_lv8_wgt0 = 25; + s->atr_wgt8.atr_lv8_wgt1 = 20; + s->atr_wgt8.atr_lv8_wgt2 = 18; + s->atr_wgt4.atr_lv4_wgt0 = 25; + s->atr_wgt4.atr_lv4_wgt1 = 20; + s->atr_wgt4.atr_lv4_wgt2 = 16; + } else { + s->atr_thd.atr_thd0 = 1; + s->atr_thd.atr_thd1 = 2; + s->atr_thd.atr_thd2 = 7; + s->atr_wgt16.atr_lv16_wgt0 = 23; + s->atr_wgt16.atr_lv16_wgt1 = 22; + s->atr_wgt16.atr_lv16_wgt2 = 20; + s->atr_wgt8.atr_lv8_wgt0 = 24; + s->atr_wgt8.atr_lv8_wgt1 = 24; + s->atr_wgt8.atr_lv8_wgt2 = 24; + s->atr_wgt4.atr_lv4_wgt0 = 23; + s->atr_wgt4.atr_lv4_wgt1 = 22; + s->atr_wgt4.atr_lv4_wgt2 = 20; + } + } +} + +static void setup_vepu511a_anti_flicker(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aSqi *reg = ®s->reg_sqi; + RK_U32 str = ctx->cfg->tune.anti_flicker_str; + rdo_skip_par *p_skip = NULL; + rdo_noskip_par *p_no_skip = NULL; + + static RK_U8 pskip_atf_th0[4] = { 0, 0, 0, 1 }; + static RK_U8 pskip_atf_th1[4] = { 7, 7, 7, 10 }; + static RK_U8 pskip_atf_wgt0[4] = { 16, 16, 16, 20 }; + static RK_U8 pskip_atf_wgt1[4] = { 16, 16, 14, 16 }; + static RK_U8 intra_atf_th0[4] = { 8, 16, 20, 20 }; + static RK_U8 intra_atf_th1[4] = { 16, 32, 40, 40 }; + static RK_U8 intra_atf_th2[4] = { 32, 56, 72, 72 }; + static RK_U8 intra_atf_wgt0[4] = { 16, 24, 27, 27 }; + static RK_U8 intra_atf_wgt1[4] = { 16, 22, 25, 25 }; + static RK_U8 intra_atf_wgt2[4] = { 16, 19, 20, 20 }; + + p_skip = ®->rdo_b16_skip; + p_skip->atf_thd0.madp_thd0 = pskip_atf_th0[str]; + p_skip->atf_thd0.madp_thd1 = pskip_atf_th1[str]; + p_skip->atf_thd1.madp_thd2 = 15; + p_skip->atf_thd1.madp_thd3 = 25; + p_skip->atf_wgt0.wgt0 = pskip_atf_wgt0[str]; + p_skip->atf_wgt0.wgt1 = pskip_atf_wgt1[str]; + p_skip->atf_wgt0.wgt2 = 16; + p_skip->atf_wgt0.wgt3 = 16; + p_skip->atf_wgt1.wgt4 = 16; + + p_no_skip = ®->rdo_b16_inter; + p_no_skip->ratf_thd0.madp_thd0 = 20; + p_no_skip->ratf_thd0.madp_thd1 = 40; + p_no_skip->ratf_thd1.madp_thd2 = 72; + p_no_skip->atf_wgt.wgt0 = 16; + p_no_skip->atf_wgt.wgt1 = 16; + p_no_skip->atf_wgt.wgt2 = 16; + p_no_skip->atf_wgt.wgt3 = 16; + + p_no_skip = ®->rdo_b16_intra; + p_no_skip->ratf_thd0.madp_thd0 = intra_atf_th0[str]; + p_no_skip->ratf_thd0.madp_thd1 = intra_atf_th1[str]; + p_no_skip->ratf_thd1.madp_thd2 = intra_atf_th2[str]; + p_no_skip->atf_wgt.wgt0 = intra_atf_wgt0[str]; + p_no_skip->atf_wgt.wgt1 = intra_atf_wgt1[str]; + p_no_skip->atf_wgt.wgt2 = intra_atf_wgt2[str]; + p_no_skip->atf_wgt.wgt3 = 16; + + reg->rdo_b16_intra_atf_cnt_thd.thd0 = 1; + reg->rdo_b16_intra_atf_cnt_thd.thd1 = 4; + reg->rdo_b16_intra_atf_cnt_thd.thd2 = 1; + reg->rdo_b16_intra_atf_cnt_thd.thd3 = 4; + + reg->rdo_atf_resi_thd.big_th0 = 16; + reg->rdo_atf_resi_thd.big_th1 = 16; + reg->rdo_atf_resi_thd.small_th0 = 8; + reg->rdo_atf_resi_thd.small_th1 = 8; +} + +static void setup_vepu511a_anti_smear(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aSqi *reg = ®s->reg_sqi; + H264eSlice *slice = ctx->slice; + Vepu511aH264Fbk *last_fb = &ctx->last_frame_fb; + RK_U32 mb_cnt = last_fb->st_mb_num; + RK_U32 *smear_cnt = last_fb->st_smear_cnt; + RK_S32 deblur_str = ctx->cfg->tune.deblur_str; + RK_S32 delta_qp = 0; + RK_S32 flg0 = smear_cnt[4] < (mb_cnt >> 6); + RK_S32 flg1 = 1, flg2 = 0, flg3 = 0; + RK_S32 smear_multi[4] = { 9, 12, 16, 16 }; + + hal_h264e_dbg_func("enter\n"); + + if ((smear_cnt[3] < ((5 * mb_cnt) >> 10)) || + (smear_cnt[3] < ((1126 * MPP_MAX3(smear_cnt[0], smear_cnt[1], smear_cnt[2])) >> 10)) || + (deblur_str == 6) || (deblur_str == 7)) + flg1 = 0; + + flg3 = flg1 ? 3 : (smear_cnt[4] > ((102 * mb_cnt) >> 10)) ? 2 : + (smear_cnt[4] > ((66 * mb_cnt) >> 10)) ? 1 : 0; + + if (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + reg->smear_opt_cfg.rdo_smear_en = ctx->qpmap_en; + if (ctx->qpmap_en && deblur_str > 3) + reg->smear_opt_cfg.rdo_smear_lvl16_multi = smear_multi[flg3]; + else + reg->smear_opt_cfg.rdo_smear_lvl16_multi = flg0 ? 9 : 12; + } else { + reg->smear_opt_cfg.rdo_smear_en = 0; + reg->smear_opt_cfg.rdo_smear_lvl16_multi = 16; + } + + if (ctx->qpmap_en && deblur_str > 3) { + flg2 = 1; + if (smear_cnt[2] + smear_cnt[3] > (3 * smear_cnt[4] / 4)) + delta_qp = 1; + if (smear_cnt[4] < (mb_cnt >> 4)) + delta_qp -= 8; + else if (smear_cnt[4] < ((3 * mb_cnt) >> 5)) + delta_qp -= 7; + else + delta_qp -= 6; + + if (flg3 == 2) + delta_qp = 0; + else if (flg3 == 1) + delta_qp = -2; + } else { + if (smear_cnt[2] + smear_cnt[3] > smear_cnt[4] / 2) + delta_qp = 1; + if (smear_cnt[4] < (mb_cnt >> 8)) + delta_qp -= (deblur_str < 2) ? 6 : 8; + else if (smear_cnt[4] < (mb_cnt >> 7)) + delta_qp -= (deblur_str < 2) ? 5 : 6; + else if (smear_cnt[4] < (mb_cnt >> 6)) + delta_qp -= (deblur_str < 2) ? 3 : 4; + else + delta_qp -= 1; + } + reg->smear_opt_cfg.rdo_smear_dlt_qp = delta_qp; + + if ((H264_I_SLICE == slice->slice_type) || + (H264_I_SLICE == last_fb->frame_type)) + reg->smear_opt_cfg.stated_mode = 1; + else + reg->smear_opt_cfg.stated_mode = 2; + + reg->smear_madp_thd0.madp_cur_thd0 = 0; + reg->smear_madp_thd0.madp_cur_thd1 = flg2 ? 48 : 24; + reg->smear_madp_thd1.madp_cur_thd2 = flg2 ? 64 : 48; + reg->smear_madp_thd1.madp_cur_thd3 = flg2 ? 72 : 64; + reg->smear_madp_thd2.madp_around_thd0 = flg2 ? 4095 : 16; + reg->smear_madp_thd2.madp_around_thd1 = 32; + reg->smear_madp_thd3.madp_around_thd2 = 48; + reg->smear_madp_thd3.madp_around_thd3 = flg2 ? 0 : 96; + reg->smear_madp_thd4.madp_around_thd4 = 48; + reg->smear_madp_thd4.madp_around_thd5 = 24; + reg->smear_madp_thd5.madp_ref_thd0 = flg2 ? 64 : 96; + reg->smear_madp_thd5.madp_ref_thd1 = 48; + + reg->smear_cnt_thd0.cnt_cur_thd0 = flg2 ? 2 : 1; + reg->smear_cnt_thd0.cnt_cur_thd1 = flg2 ? 5 : 3; + reg->smear_cnt_thd0.cnt_cur_thd2 = 1; + reg->smear_cnt_thd0.cnt_cur_thd3 = 3; + reg->smear_cnt_thd1.cnt_around_thd0 = 1; + reg->smear_cnt_thd1.cnt_around_thd1 = 4; + reg->smear_cnt_thd1.cnt_around_thd2 = 1; + reg->smear_cnt_thd1.cnt_around_thd3 = 4; + reg->smear_cnt_thd2.cnt_around_thd4 = 0; + reg->smear_cnt_thd2.cnt_around_thd5 = 3; + reg->smear_cnt_thd2.cnt_around_thd6 = 0; + reg->smear_cnt_thd2.cnt_around_thd7 = 3; + reg->smear_cnt_thd3.cnt_ref_thd0 = 1; + reg->smear_cnt_thd3.cnt_ref_thd1 = 3; + + reg->smear_resi_thd0.resi_small_cur_th0 = 6; + reg->smear_resi_thd0.resi_big_cur_th0 = 9; + reg->smear_resi_thd0.resi_small_cur_th1 = 6; + reg->smear_resi_thd0.resi_big_cur_th1 = 9; + reg->smear_resi_thd1.resi_small_around_th0 = 6; + reg->smear_resi_thd1.resi_big_around_th0 = 11; + reg->smear_resi_thd1.resi_small_around_th1 = 6; + reg->smear_resi_thd1.resi_big_around_th1 = 8; + reg->smear_resi_thd2.resi_small_around_th2 = 9; + reg->smear_resi_thd2.resi_big_around_th2 = 20; + reg->smear_resi_thd2.resi_small_around_th3 = 6; + reg->smear_resi_thd2.resi_big_around_th3 = 20; + reg->smear_resi_thd3.resi_small_ref_th0 = 7; + reg->smear_resi_thd3.resi_big_ref_th0 = 16; + reg->smear_resi_thd4.resi_th0 = flg2 ? 0 : 10; + reg->smear_resi_thd4.resi_th1 = flg2 ? 0 : 6; + + reg->smear_st_thd.madp_cnt_th0 = flg2 ? 0 : 1; + reg->smear_st_thd.madp_cnt_th1 = flg2 ? 0 : 5; + reg->smear_st_thd.madp_cnt_th2 = flg2 ? 0 : 1; + reg->smear_st_thd.madp_cnt_th3 = flg2 ? 0 : 3; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_scaling_list(HalH264eVepu511aCtx *ctx) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aSclCfg *s = ®s->reg_scl; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U8 idx; + + hal_h264e_dbg_func("enter\n"); + + /* intra4x4 and inter4x4 is not supported on VEPU500. + * valid range: 0x2200 ~ 0x221F + */ + if (ctx->pps->pic_scaling_matrix_present == 1) { + for (idx = 0; idx < 64; idx++) { + p[idx] = vepu511a_h264_cqm_jvt8i[63 - idx]; /* intra8x8 */ + p[idx + 64] = vepu511a_h264_cqm_jvt8p[63 - idx]; /* inter8x8 */ + } + } else if (ctx->pps->pic_scaling_matrix_present == 2) { + //TODO: Update scaling list for (scaling_list_mode == 2) + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu511a_quant(HalH264eVepu511aCtx *ctx) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + HalVepu511aRegSet *regs = ctx->regs_set; + H264eVepu511aParam *s = ®s->reg_param; + RK_U8 th0 = 0, th1 = 0, th2 = 0; /* 5, 13, 27 */ + RK_U16 bias_i0 = 0, bias_i1 = 0, bias_i2 = 0, bias_i3 = 683; /* 171, 150, 120, 100 */ + RK_U16 bias_p0 = 0, bias_p1 = 0, bias_p2 = 0, bias_p3 = 341; /* 85, 80, 70, 65 */ + RK_U32 sli_type = ctx->slice->slice_type; + + if (!hw->qbias_en) { + /* used for venc_info log */ + hw->qbias_arr[IFRAME_THD0] = hw->qbias_arr[PFRAME_THD0] = th0; + hw->qbias_arr[IFRAME_THD1] = hw->qbias_arr[PFRAME_THD1] = th1; + hw->qbias_arr[IFRAME_THD2] = hw->qbias_arr[PFRAME_THD2] = th2; + hw->qbias_arr[IFRAME_BIAS0] = hw->qbias_arr[PFRAME_IBLK_BIAS0] = bias_i0; + hw->qbias_arr[IFRAME_BIAS1] = hw->qbias_arr[PFRAME_IBLK_BIAS1] = bias_i1; + hw->qbias_arr[IFRAME_BIAS2] = hw->qbias_arr[PFRAME_IBLK_BIAS2] = bias_i2; + hw->qbias_arr[IFRAME_BIAS3] = hw->qbias_arr[PFRAME_IBLK_BIAS3] = bias_i3; + hw->qbias_arr[PFRAME_PBLK_BIAS0] = bias_p0; + hw->qbias_arr[PFRAME_PBLK_BIAS1] = bias_p1; + hw->qbias_arr[PFRAME_PBLK_BIAS2] = bias_p2; + hw->qbias_arr[PFRAME_PBLK_BIAS3] = bias_p3; + } else { + if (sli_type == H264_I_SLICE) { + th0 = hw->qbias_arr[IFRAME_THD0]; + th1 = hw->qbias_arr[IFRAME_THD1]; + th2 = hw->qbias_arr[IFRAME_THD2]; + bias_i0 = hw->qbias_arr[IFRAME_BIAS0]; + bias_i1 = hw->qbias_arr[IFRAME_BIAS1]; + bias_i2 = hw->qbias_arr[IFRAME_BIAS2]; + bias_i3 = hw->qbias_arr[IFRAME_BIAS3]; + } else { + th0 = hw->qbias_arr[PFRAME_THD0]; + th1 = hw->qbias_arr[PFRAME_THD1]; + th2 = hw->qbias_arr[PFRAME_THD2]; + bias_i0 = hw->qbias_arr[PFRAME_IBLK_BIAS0]; + bias_i1 = hw->qbias_arr[PFRAME_IBLK_BIAS1]; + bias_i2 = hw->qbias_arr[PFRAME_IBLK_BIAS2]; + bias_i3 = hw->qbias_arr[PFRAME_IBLK_BIAS3]; + bias_p0 = hw->qbias_arr[PFRAME_PBLK_BIAS0]; + bias_p1 = hw->qbias_arr[PFRAME_PBLK_BIAS1]; + bias_p2 = hw->qbias_arr[PFRAME_PBLK_BIAS2]; + bias_p3 = hw->qbias_arr[PFRAME_PBLK_BIAS3]; + } + } + + s->bias_madi_thd_comb.bias_madi_th0 = th0; + s->bias_madi_thd_comb.bias_madi_th1 = th1; + s->bias_madi_thd_comb.bias_madi_th2 = th2; + s->qnt0_i_bias_comb.bias_i_val0 = bias_i0; + s->qnt0_i_bias_comb.bias_i_val1 = bias_i1; + s->qnt0_i_bias_comb.bias_i_val2 = bias_i2; + s->qnt1_i_bias_comb.bias_i_val3 = bias_i3; + s->qnt0_p_bias_comb.bias_p_val0 = bias_p0; + s->qnt0_p_bias_comb.bias_p_val1 = bias_p1; + s->qnt0_p_bias_comb.bias_p_val2 = bias_p2; + s->qnt1_p_bias_comb.bias_p_val3 = bias_p3; +} + +static MPP_RET hal_h264e_vepu511a_gen_regs(void *hal, HalEncTask *task) +{ + HalH264eVepu511aCtx *ctx = (HalH264eVepu511aCtx *)hal; + HalVepu511aRegSet *regs = ctx->regs_set; + MppEncCfgSet *cfg = ctx->cfg; + EncRcTask *rc_task = task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + MPP_RET ret = MPP_OK; + + hal_h264e_dbg_func("enter %p\n", hal); + hal_h264e_dbg_detail("frame %d generate regs now", ctx->frms->seq_idx); + + /* register setup */ + memset(regs, 0, sizeof(*regs)); + + setup_vepu511a_normal(regs); + ret = setup_vepu511a_prep(regs, &ctx->cfg->prep, task); + if (ret) + return ret; + + setup_vepu511a_codec(regs, ctx); + setup_vepu511a_rdo_pred(ctx); + setup_vepu511a_aq(ctx); + setup_vepu511a_anti_stripe(ctx); + setup_vepu511a_anti_ringing(ctx); + setup_vepu511a_anti_flicker(ctx); + setup_vepu511a_anti_smear(ctx); + setup_vepu511a_scaling_list(ctx); + setup_vepu511a_quant(ctx); + + setup_vepu511a_rc_base(regs, ctx, rc_task); + setup_vepu511a_io_buf(regs, ctx->offsets, task); + setup_vepu511a_recn_refr(ctx, regs); + setup_vepu511a_split(regs, cfg); + setup_vepu511a_me(ctx); + vepu511a_set_speed(ctx); + + if (frm->is_i_refresh) + setup_vepu511a_intra_refresh(regs, ctx, frm->seq_idx % cfg->rc.gop); + + setup_vepu511a_l2(ctx); + setup_vepu511a_ext_line_buf(regs, ctx); + + if (ctx->roi_data) + vepu511a_set_roi(&ctx->regs_set->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + + /* two pass register patch */ + if (frm->save_pass1) + vepu511a_h264e_save_pass1_patch(regs, ctx); + + if (frm->use_pass1) + vepu511a_h264e_use_pass1_patch(regs, ctx); + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu511a_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu511aCtx *ctx = (HalH264eVepu511aCtx *)hal; + HalVepu511aRegSet *regs = ctx->regs_set; + + (void) task; + + hal_h264e_dbg_func("enter %p\n", hal); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->reg_ctl; + wr_cfg.size = sizeof(regs->reg_ctl); + wr_cfg.offset = VEPU511A_CTL_OFFSET; +#if DUMP_REG + { + RK_U32 i; + RK_U32 *reg = (RK_U32)wr_cfg.reg; + for ( i = 0; i < sizeof(regs->reg_ctl) / sizeof(RK_U32); i++) { + mpp_log("reg[%d] = 0x%08x\n", i, reg[i]); + } + + } +#endif + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_frm; + wr_cfg.size = sizeof(regs->reg_frm); + wr_cfg.offset = VEPU511A_FRAME_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_rc_roi; + wr_cfg.size = sizeof(regs->reg_rc_roi); + wr_cfg.offset = VEPU511A_RC_ROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_param; + wr_cfg.size = sizeof(regs->reg_param); + wr_cfg.offset = VEPU511A_PARAM_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_sqi; + wr_cfg.size = sizeof(regs->reg_sqi); + wr_cfg.offset = VEPU511A_SQI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_scl; + wr_cfg.size = sizeof(regs->reg_scl); + wr_cfg.offset = VEPU511A_SCL_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->offsets); + if (ret) { + mpp_loge_f("set register offsets failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_ctl.int_sta; + rd_cfg.size = sizeof(RK_U32); + rd_cfg.offset = VEPU511A_REG_BASE_HW_STATUS; + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_loge_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_st; + rd_cfg.size = sizeof(regs->reg_st); + rd_cfg.offset = VEPU511A_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_loge_f("set register read failed %d\n", ret); + break; + } + + /* send request to hardware */ + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_loge_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu511a_status_check(HalVepu511aRegSet *regs) +{ + MPP_RET ret = MPP_OK; + + if (regs->reg_ctl.int_sta.lkt_node_done_sta) + hal_h264e_dbg_detail("lkt_done finish"); + + if (regs->reg_ctl.int_sta.enc_done_sta) + hal_h264e_dbg_detail("enc_done finish"); + + if (regs->reg_ctl.int_sta.vslc_done_sta) + hal_h264e_dbg_detail("enc_slice finsh"); + + if (regs->reg_ctl.int_sta.sclr_done_sta) + hal_h264e_dbg_detail("safe clear finsh"); + + if (regs->reg_ctl.int_sta.vbsf_oflw_sta) { + mpp_loge_f("bit stream overflow"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.vbuf_lens_sta) { + mpp_loge_f("bus write full"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.enc_err_sta) { + mpp_loge_f("bus error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wdg_sta) { + mpp_loge_f("wdg timeout"); + ret = MPP_NOK; + } + + return ret; +} + +static MPP_RET hal_h264e_vepu511a_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu511aCtx *ctx = (HalH264eVepu511aCtx *)hal; + HalVepu511aRegSet *regs = ctx->regs_set; + RK_U32 split_out = ctx->cfg->split.split_out; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + H264NaluType type = task->rc_task->frm.is_idr ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppEncH264HwCfg *hw_cfg = &ctx->cfg->h264.hw_cfg; + RK_S32 i; + + hal_h264e_dbg_func("enter %p\n", hal); + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (task->rc_task->frm.save_pass1) + split_out = 0; + + /* update split_out in hw_cfg */ + hw_cfg->hw_split_out = split_out; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len; + RK_U32 slice_last; + MppDevPollCfg *poll_cfg = (MppDevPollCfg *)((char *)ctx->poll_cfgs + + task->flags.reg_idx * ctx->poll_cfg_size); + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].last; + slice_len = poll_cfg->slice_info[i].length; + + mpp_packet_add_segment_info(pkt, type, offset, slice_len); + offset += slice_len; + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) { + param.length = slice_len; + + if (slice_last) + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + else + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + + mpp_callback(ctx->output_cb, ¶m); + } + } + } while (!slice_last); + + ret = hal_h264e_vepu511a_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_loge_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + ret = hal_h264e_vepu511a_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } + + mpp_packet_add_segment_info(pkt, type, offset, regs->reg_st.bs_lgth_l32); + } + + if (!(split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) && !ret) { + HalH264eVepuStreamAmend *amend = &ctx->amend; + + if (amend->enable) { + amend->old_length = task->hw_length; + amend->slice->is_multi_slice = (ctx->cfg->split.split_mode > 0); + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + task->hw_length = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = task->hw_length; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + + hal_h264e_dbg_func("leave %p ret %d\n", hal, ret); + + return ret; +} + +static void vepu511a_h264e_update_tune_stat(HalH264eVepu511aCtx *ctx, HalEncTask *task) +{ + HalVepu511aRegSet *regs = ctx->regs_set; + Vepu511aStatus *reg_st = ®s->reg_st; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + RK_U32 madi_th_cnt[4], madp_th_cnt[4]; + RK_U32 madi_cnt = 0, madp_cnt = 0; + RK_U32 md_cnt; + + madi_th_cnt[0] = reg_st->st_madi_lt_num0.madi_th_lt_cnt0 + + reg_st->st_madi_rt_num0.madi_th_rt_cnt0 + + reg_st->st_madi_lb_num0.madi_th_lb_cnt0 + + reg_st->st_madi_rb_num0.madi_th_rb_cnt0; + madi_th_cnt[1] = reg_st->st_madi_lt_num0.madi_th_lt_cnt1 + + reg_st->st_madi_rt_num0.madi_th_rt_cnt1 + + reg_st->st_madi_lb_num0.madi_th_lb_cnt1 + + reg_st->st_madi_rb_num0.madi_th_rb_cnt1; + madi_th_cnt[2] = reg_st->st_madi_lt_num1.madi_th_lt_cnt2 + + reg_st->st_madi_rt_num1.madi_th_rt_cnt2 + + reg_st->st_madi_lb_num1.madi_th_lb_cnt2 + + reg_st->st_madi_rb_num1.madi_th_rb_cnt2; + madi_th_cnt[3] = reg_st->st_madi_lt_num1.madi_th_lt_cnt3 + + reg_st->st_madi_rt_num1.madi_th_rt_cnt3 + + reg_st->st_madi_lb_num1.madi_th_lb_cnt3 + + reg_st->st_madi_rb_num1.madi_th_rb_cnt3; + madp_th_cnt[0] = reg_st->st_madp_lt_num0.madp_th_lt_cnt0 + + reg_st->st_madp_rt_num0.madp_th_rt_cnt0 + + reg_st->st_madp_lb_num0.madp_th_lb_cnt0 + + reg_st->st_madp_rb_num0.madp_th_rb_cnt0; + madp_th_cnt[1] = reg_st->st_madp_lt_num0.madp_th_lt_cnt1 + + reg_st->st_madp_rt_num0.madp_th_rt_cnt1 + + reg_st->st_madp_lb_num0.madp_th_lb_cnt1 + + reg_st->st_madp_rb_num0.madp_th_rb_cnt1; + madp_th_cnt[2] = reg_st->st_madp_lt_num1.madp_th_lt_cnt2 + + reg_st->st_madp_rt_num1.madp_th_rt_cnt2 + + reg_st->st_madp_lb_num1.madp_th_lb_cnt2 + + reg_st->st_madp_rb_num1.madp_th_rb_cnt2; + madp_th_cnt[3] = reg_st->st_madp_lt_num1.madp_th_lt_cnt3 + + reg_st->st_madp_rt_num1.madp_th_rt_cnt3 + + reg_st->st_madp_lb_num1.madp_th_lb_cnt3 + + reg_st->st_madp_rb_num1.madp_th_rb_cnt3; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt[3] + 11 * madp_th_cnt[2] + 8 * madp_th_cnt[1]) >> 2; + else + md_cnt = (24 * madp_th_cnt[3] + 22 * madp_th_cnt[2] + 17 * madp_th_cnt[1]) >> 2; + madi_cnt = (6 * madi_th_cnt[3] + 5 * madi_th_cnt[2] + 4 * madi_th_cnt[1]) >> 2; + + /* fill rc info */ + if (md_cnt * 100 > 15 * mbs) + rc_info->motion_level = 200; + else if (md_cnt * 100 > 5 * mbs) + rc_info->motion_level = 100; + else if (md_cnt * 100 > (mbs >> 2)) + rc_info->motion_level = 1; + else + rc_info->motion_level = 0; + + if (madi_cnt * 100 > 30 * mbs) + rc_info->complex_level = 2; + else if (madi_cnt * 100 > 13 * mbs) + rc_info->complex_level = 1; + else + rc_info->complex_level = 0; + + rc_info->madi = madi_th_cnt[0] * regs->reg_rc_roi.madi_st_thd.madi_th0 + + madi_th_cnt[1] * (regs->reg_rc_roi.madi_st_thd.madi_th0 + + regs->reg_rc_roi.madi_st_thd.madi_th1) / 2 + + madi_th_cnt[2] * (regs->reg_rc_roi.madi_st_thd.madi_th1 + + regs->reg_rc_roi.madi_st_thd.madi_th2) / 2 + + madi_th_cnt[3] * regs->reg_rc_roi.madi_st_thd.madi_th2; + + madi_cnt = madi_th_cnt[0] + madi_th_cnt[1] + madi_th_cnt[2] + madi_th_cnt[3]; + if (madi_cnt) + rc_info->madi = rc_info->madi / madi_cnt; + + rc_info->madp = madp_th_cnt[0] * regs->reg_rc_roi.madp_st_thd0.madp_th0 + + madp_th_cnt[1] * (regs->reg_rc_roi.madp_st_thd0.madp_th0 + + regs->reg_rc_roi.madp_st_thd0.madp_th1) / 2 + + madp_th_cnt[2] * (regs->reg_rc_roi.madp_st_thd0.madp_th1 + + regs->reg_rc_roi.madp_st_thd1.madp_th2) / 2 + + madp_th_cnt[3] * regs->reg_rc_roi.madp_st_thd1.madp_th2; + + madp_cnt = madp_th_cnt[0] + madp_th_cnt[1] + madp_th_cnt[2] + madp_th_cnt[3]; + + if (madp_cnt) + rc_info->madp = rc_info->madp / madp_cnt; + + hal_h264e_dbg_rc("complex_level %d motion_level %d\n", + rc_info->complex_level, rc_info->motion_level); +} + +static MPP_RET hal_h264e_vepu511a_ret_task(void * hal, HalEncTask * task) +{ + HalH264eVepu511aCtx *ctx = (HalH264eVepu511aCtx *)hal; + HalVepu511aRegSet *regs = ctx->regs_set; + EncRcTaskInfo *rc_info = &task->rc_task->info; + Vepu511aH264Fbk *fb = &ctx->feedback; + Vepu511aStatus *reg_st = ®s->reg_st; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + + hal_h264e_dbg_func("enter %p\n", hal); + + fb->st_mb_num = mbs; + fb->st_smear_cnt[0] = reg_st->st_smear_cnt0.rdo_smear_cnt0 * 4; + fb->st_smear_cnt[1] = reg_st->st_smear_cnt0.rdo_smear_cnt1 * 4; + fb->st_smear_cnt[2] = reg_st->st_smear_cnt1.rdo_smear_cnt2 * 4; + fb->st_smear_cnt[3] = reg_st->st_smear_cnt1.rdo_smear_cnt3 * 4; + fb->st_smear_cnt[4] = fb->st_smear_cnt[0] + fb->st_smear_cnt[1] + + fb->st_smear_cnt[2] + fb->st_smear_cnt[3]; + fb->frame_type = ctx->slice->slice_type; + + // update total hardware length + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = regs->reg_st.qp_sum / mbs; + rc_info->iblk4_prop = (regs->reg_st.st_pnum_i4.pnum_i4 + + regs->reg_st.st_pnum_i8.pnum_i8 + + regs->reg_st.st_pnum_i16.pnum_i16) * 256 / mbs; + + rc_info->sse = ((RK_S64)regs->reg_st.sse_h32 << 16) + + (regs->reg_st.st_sse_bsl.sse_l16 & 0xffff); + rc_info->lvl16_inter_num = regs->reg_st.st_pnum_p16.pnum_p16; + rc_info->lvl8_inter_num = regs->reg_st.st_pnum_p8.pnum_p8; + rc_info->lvl16_intra_num = regs->reg_st.st_pnum_i16.pnum_i16; + rc_info->lvl8_intra_num = regs->reg_st.st_pnum_i8.pnum_i8; + rc_info->lvl4_intra_num = regs->reg_st.st_pnum_i4.pnum_i4; + + ctx->hal_rc_cfg.bit_real = rc_info->bit_real; + ctx->hal_rc_cfg.quality_real = rc_info->quality_real; + ctx->hal_rc_cfg.iblk4_prop = rc_info->iblk4_prop; + + task->hal_ret.data = &ctx->hal_rc_cfg; + task->hal_ret.number = 1; + + mpp_dev_multi_offset_reset(ctx->offsets); + + if (ctx->dpb) { + h264e_dpb_hal_end(ctx->dpb, task->flags.curr_idx); + h264e_dpb_hal_end(ctx->dpb, task->flags.refr_idx); + } + + vepu511a_h264e_update_tune_stat(ctx, task); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu511a = { + .name = "hal_h264e_vepu511a", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu511aCtx), + .flag = 0, + .init = hal_h264e_vepu511a_init, + .deinit = hal_h264e_vepu511a_deinit, + .prepare = hal_h264e_vepu511a_prepare, + .get_task = hal_h264e_vepu511a_get_task, + .gen_regs = hal_h264e_vepu511a_gen_regs, + .start = hal_h264e_vepu511a_start, + .wait = hal_h264e_vepu511a_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu511a_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu511a) diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu511a_reg.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu511a_reg.h new file mode 100644 index 000000000..e2ac6646e --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu511a_reg.h @@ -0,0 +1,794 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H264E_VEPU511A_REG_H +#define HAL_H264E_VEPU511A_REG_H + +#include "rk_type.h" +#include "vepu511a_common.h" + +/* class: buffer/video syntax */ +/* 0x00000270 reg156 - 0x00000538 reg334 */ +typedef struct H264eVepu511aFrame_t { + /* 0x00000270 reg156 - 0x0000039c reg231 */ + Vepu511aFrmCommon common; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 rect_size : 1; + RK_U32 reserved1 : 2; + RK_U32 vlc_lmt : 1; + RK_U32 reserved2 : 9; + RK_U32 ccwa_e : 1; + RK_U32 reserved3 : 1; + RK_U32 atr_e : 1; + RK_U32 reserved4 : 4; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved5 : 6; + RK_U32 atf_e : 1; + RK_U32 atr_mult_sel_e : 1; + RK_U32 h264_it_debug_e : 2; + } rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 rdo_mark_mode : 9; + RK_U32 reserved : 5; + RK_U32 p16_interp_num : 2; + RK_U32 p16t8_rdo_num : 2; + RK_U32 p16t4_rmd_num : 2; + RK_U32 p8_interp_num : 2; + RK_U32 p8t8_rdo_num : 2; + RK_U32 p8t4_rmd_num : 2; + RK_U32 iframe_i16_rdo_num : 2; + RK_U32 i8_rdo_num : 2; + RK_U32 iframe_i4_rdo_num : 2; + } rdo_mark_mode; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_ref_idc : 2; + RK_U32 nal_unit_type : 5; + RK_U32 reserved : 25; + } synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 max_fnum : 4; + RK_U32 drct_8x8 : 1; + RK_U32 mpoc_lm4 : 4; + RK_U32 poc_type : 2; + RK_U32 reserved : 21; + } synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 etpy_mode : 1; + RK_U32 trns_8x8 : 1; + RK_U32 csip_flag : 1; + RK_U32 num_ref0_idx : 2; + RK_U32 num_ref1_idx : 2; + RK_U32 pic_init_qp : 6; + RK_U32 cb_ofst : 5; + RK_U32 cr_ofst : 5; + RK_U32 reserved : 1; + RK_U32 dbf_cp_flg : 1; + RK_U32 reserved1 : 7; + } synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 sli_type : 2; + RK_U32 pps_id : 8; + RK_U32 drct_smvp : 1; + RK_U32 num_ref_ovrd : 1; + RK_U32 cbc_init_idc : 2; + RK_U32 reserved : 2; + RK_U32 frm_num : 16; + } synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 idr_pid : 16; + RK_U32 poc_lsb : 16; + } synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 rodr_pic_idx : 2; + RK_U32 ref_list0_rodr : 1; + RK_U32 sli_beta_ofst : 4; + RK_U32 sli_alph_ofst : 4; + RK_U32 dis_dblk_idc : 2; + RK_U32 reserved : 3; + RK_U32 rodr_pic_num : 16; + } synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 nopp_flg : 1; + RK_U32 ltrf_flg : 1; + RK_U32 arpm_flg : 1; + RK_U32 mmco4_pre : 1; + RK_U32 mmco_type0 : 3; + RK_U32 mmco_parm0 : 16; + RK_U32 mmco_type1 : 3; + RK_U32 mmco_type2 : 3; + RK_U32 reserved : 3; + } synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 mmco_parm1 : 16; + RK_U32 mmco_parm2 : 16; + } synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 long_term_frame_idx0 : 4; + RK_U32 long_term_frame_idx1 : 4; + RK_U32 long_term_frame_idx2 : 4; + RK_U32 reserved : 20; + } synt_refm2; + + /* 0x000003d4 reg245 - 0x0x00000 reg251 */ + RK_U32 reserved245_251[7]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 mv_v_lmt_thd : 14; + RK_U32 reserved : 1; + RK_U32 mv_v_lmt_en : 1; + RK_U32 reserved1 : 16; + } sli_cfg; + + /* 0x000003f4 reg253 */ + RK_U32 reserved253; + + /* 0x000003f8 reg254 */ + struct { + RK_U32 slice_sta_x : 9; + RK_U32 reserved1 : 7; + RK_U32 slice_sta_y : 10; + RK_U32 reserved2 : 5; + RK_U32 slice_enc_ena : 1; + } slice_enc_cfg0; + + /* 0x000003fc reg255 */ + struct { + RK_U32 slice_end_x : 9; + RK_U32 reserved : 7; + RK_U32 slice_end_y : 10; + RK_U32 reserved1 : 6; + } slice_enc_cfg1; + + /* 0x400 reg256 - 0x51c reg327*/ + RK_U32 reserved256_327[72]; + + /* 0x00000520 reg328 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_md : 28; + } adr_md_vpp; + + /* 0x00000524 reg329 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_od : 28; + } adr_od_vpp; + + /* 0x00000528 reg330 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_ref_mdw : 28; + } adr_ref_mdw; + + /* 0x0000052c reg331 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_ref_mdr : 28; + } adr_ref_mdr; + + /* 0x00000530 reg332 */ + struct { + RK_U32 sto_stride_md : 8; + RK_U32 sto_stride_od : 8; + RK_U32 cur_frm_en_md : 1; + RK_U32 ref_frm_en_md : 1; + RK_U32 switch_sad_md : 2; + RK_U32 night_mode_en_md : 1; + RK_U32 flycatkin_flt_en_md : 1; + RK_U32 en_od : 1; + RK_U32 background_en_od : 1; + RK_U32 sad_comp_en_od : 1; + RK_U32 reserved : 6; + RK_U32 vepu_pp_en : 1; + } vpp_base_cfg; + + /* 0x00000534 reg333 */ + struct { + RK_U32 thres_sad_md : 12; + RK_U32 thres_move_md : 3; + RK_U32 reserved : 1; + RK_U32 thres_dust_move_md : 4; + RK_U32 thres_dust_blk_md : 3; + RK_U32 reserved1 : 1; + RK_U32 thres_dust_chng_md : 8; + } thd_md_vpp; + + /* 0x00000538 reg334 */ + struct { + RK_U32 thres_complex_od : 12; + RK_U32 thres_complex_cnt_od : 3; + RK_U32 thres_sad_od : 14; + RK_U32 reserved : 3; + } thd_od_vpp; +} H264eVepu511aFrame; + +/* class: param */ +/* 0x00001700 reg1472 - 0x000019cc reg1651 */ +typedef struct H264eVepu511aParam_t { + /* 0x00001700 reg1472 */ + struct { + RK_U32 iprd_tthdy4_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_0; + + /* 0x00001704 reg1473 */ + struct { + RK_U32 iprd_tthdy4_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_1; + + /* 0x00001708 reg1474 */ + struct { + RK_U32 iprd_tthdc8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_0; + + /* 0x0000170c reg1475 */ + struct { + RK_U32 iprd_tthdc8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_1; + + /* 0x00001710 reg1476 */ + struct { + RK_U32 iprd_tthdy8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_0; + + /* 0x00001714 reg1477 */ + struct { + RK_U32 iprd_tthdy8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_1; + + /* 0x00001718 reg1478 */ + struct { + RK_U32 iprd_tthd_ul : 12; + RK_U32 reserved : 20; + } iprd_tthd_ul; + + /* 0x0000171c reg1479 */ + struct { + RK_U32 iprd_wgty8_0 : 8; + RK_U32 iprd_wgty8_1 : 8; + RK_U32 iprd_wgty8_2 : 8; + RK_U32 iprd_wgty8_3 : 8; + } iprd_wgty8; + + /* 0x00001720 reg1480 */ + struct { + RK_U32 iprd_wgty4_0 : 8; + RK_U32 iprd_wgty4_1 : 8; + RK_U32 iprd_wgty4_2 : 8; + RK_U32 iprd_wgty4_3 : 8; + } iprd_wgty4; + + /* 0x00001724 reg1481 */ + struct { + RK_U32 iprd_wgty16_0 : 8; + RK_U32 iprd_wgty16_1 : 8; + RK_U32 iprd_wgty16_2 : 8; + RK_U32 iprd_wgty16_3 : 8; + } iprd_wgty16; + + /* 0x00001728 reg1482 */ + struct { + RK_U32 iprd_wgtc8_0 : 8; + RK_U32 iprd_wgtc8_1 : 8; + RK_U32 iprd_wgtc8_2 : 8; + RK_U32 iprd_wgtc8_3 : 8; + } iprd_wgtc8; + + /* 0x172c */ + RK_U32 reserved_1483; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 bias_madi_th0 : 8; + RK_U32 bias_madi_th1 : 8; + RK_U32 bias_madi_th2 : 8; + RK_U32 reserved : 8; + } bias_madi_thd_comb; + + /* 0x00001734 reg1485 */ + struct { + RK_U32 bias_i_val0 : 10; + RK_U32 bias_i_val1 : 10; + RK_U32 bias_i_val2 : 10; + RK_U32 reserved : 2; + } qnt0_i_bias_comb; + + /* 0x00001738 reg1486 */ + struct { + RK_U32 bias_i_val3 : 10; + RK_U32 reserved : 22; + } qnt1_i_bias_comb; + + /* 0x0000173c reg1487 */ + struct { + RK_U32 bias_p_val0 : 10; + RK_U32 bias_p_val1 : 10; + RK_U32 bias_p_val2 : 10; + RK_U32 reserved : 2; + } qnt0_p_bias_comb; + + /* 0x00001740 reg1488 */ + struct { + RK_U32 bias_p_val3 : 10; + RK_U32 reserved : 22; + } qnt1_p_bias_comb; + + /* 0x1744 - 0x175c */ + RK_U32 reserved1489_1495[7]; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 reserved : 2; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 fme_lvl_mrg : 1; + RK_U32 reserved1 : 16; + } me_sqi_comb; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th_comb; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 ratio_consi_cfg : 4; + RK_U32 ratio_bmv_dist : 4; + RK_U32 reserved : 12; + } cime_madp_th_comb; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi_comb; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th_comb; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th_comb; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi_comb; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th_comb; + + /* 0x1780 - 0x18fc */ + RK_U32 reserved1504_1599[96]; + + /* 0x00001900 reg1600 - 0x000019cc reg1651*/ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} H264eVepu511aParam; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x000020b8 reg2094 */ +typedef struct H264eVepu511aSqiCfg_t { + /* 0x00002000 reg2048 */ + struct { + RK_U32 reserved1 : 12; + RK_U32 thre_sum_grdn_point : 20; + } subj_opt_cfg; + + /* 0x00002004 reg2049 - 0x00002010 reg2052*/ + RK_U32 reserved_2049_2052[4]; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 rdo_smear_lvl16_multi : 8; + RK_U32 rdo_smear_dlt_qp : 4; + RK_U32 reserved : 1; + RK_U32 stated_mode : 2; + RK_U32 rdo_smear_en : 1; + RK_U32 reserved1 : 16; + } smear_opt_cfg; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 madp_cur_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_cur_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd0; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 madp_cur_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_cur_thd3 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd1; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 madp_around_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd2; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 madp_around_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd3 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd3; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 madp_around_thd4 : 12; + RK_U32 reserved : 4; + RK_U32 madp_around_thd5 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd4; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 madp_ref_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_ref_thd1 : 12; + RK_U32 reserved1 : 4; + } smear_madp_thd5; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 cnt_cur_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_cur_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_cur_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_cur_thd3 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd0; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 cnt_around_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_around_thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_around_thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_around_thd3 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd1; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 cnt_around_thd4 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_around_thd5 : 4; + RK_U32 reserved1 : 4; + RK_U32 cnt_around_thd6 : 4; + RK_U32 reserved2 : 4; + RK_U32 cnt_around_thd7 : 4; + RK_U32 reserved3 : 4; + } smear_cnt_thd2; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 cnt_ref_thd0 : 4; + RK_U32 reserved : 4; + RK_U32 cnt_ref_thd1 : 4; + RK_U32 reserved1 : 20; + } smear_cnt_thd3; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 resi_small_cur_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_cur_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_cur_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_cur_th1 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd0; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 resi_small_around_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_around_th0 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_around_th1 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_around_th1 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd1; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 resi_small_around_th2 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_around_th2 : 6; + RK_U32 reserved1 : 2; + RK_U32 resi_small_around_th3 : 6; + RK_U32 reserved2 : 2; + RK_U32 resi_big_around_th3 : 6; + RK_U32 reserved3 : 2; + } smear_resi_thd2; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 resi_small_ref_th0 : 6; + RK_U32 reserved : 2; + RK_U32 resi_big_ref_th0 : 6; + RK_U32 reserved1 : 18; + } smear_resi_thd3; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 resi_th0 : 8; + RK_U32 reserved : 8; + RK_U32 resi_th1 : 8; + RK_U32 reserved1 : 8; + } smear_resi_thd4; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 madp_cnt_th0 : 4; + RK_U32 madp_cnt_th1 : 4; + RK_U32 madp_cnt_th2 : 4; + RK_U32 madp_cnt_th3 : 4; + RK_U32 reserved : 16; + } smear_st_thd; + + /* 0x2058 - 0x206c */ + RK_U32 reserved_2070; + + /* 0x0000205c reg2071 */ + struct { + RK_U32 lid_grdn_blk_cu16_th : 8; + RK_U32 lid_rmd_intra_jcoef_ang : 5; + RK_U32 lid_rdo_intra_rcoef_ang : 5; + RK_U32 lid_rmd_intra_jcoef_dp : 6; + RK_U32 lid_rdo_intra_rcoef_dp : 6; + RK_U32 lid_en : 1; + RK_U32 reserved : 1; + } line_intra_dir_cfg; + + RK_U32 reserved2072_2075[4]; + + /* 0x00002070 reg2076 - 0x0000207c reg2079*/ + rdo_skip_par rdo_b16_skip; + + /* 0x00002080 reg2080 - 0x00002088 reg2082 */ + RK_U32 reserved2080_2082[3]; + + /* 0x0000208c reg2083 - 0x00002094 reg2085 */ + rdo_noskip_par rdo_b16_inter; + + /* 0x00002098 reg2086 - 0x000020a4 reg2088 */ + RK_U32 reserved2086_2088[3]; + + /* 0x000020a8 reg2089 - 0x000020ac reg2091 */ + rdo_noskip_par rdo_b16_intra; + + /* 0x000020b0 reg2092 */ + RK_U32 reserved2092; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 thd0 : 4; + RK_U32 reserved : 4; + RK_U32 thd1 : 4; + RK_U32 reserved1 : 4; + RK_U32 thd2 : 4; + RK_U32 reserved2 : 4; + RK_U32 thd3 : 4; + RK_U32 reserved3 : 4; + } rdo_b16_intra_atf_cnt_thd; + + /* 0x000020b8 reg2094 */ + struct { + RK_U32 big_th0 : 6; + RK_U32 reserved : 2; + RK_U32 big_th1 : 6; + RK_U32 reserved1 : 2; + RK_U32 small_th0 : 6; + RK_U32 reserved2 : 2; + RK_U32 small_th1 : 6; + RK_U32 reserved3 : 2; + } rdo_atf_resi_thd; + + /* 0x000020bc reg2095 - 0x000020cc reg2099*/ + RK_U32 reserved_2095_2099[5]; + + /* 0x20D0 CMPLX_STATC_CFG_COMB */ + struct { + RK_U32 cmplx_static_en : 1; + RK_U32 cmplx_static_lgt_chng_en : 1; + RK_U32 thre_qp_cmplx_static : 6; + RK_U32 madp_th0_dep0_cmplx_static : 6; + RK_U32 madp_th1_dep0_cmplx_static : 8; + RK_U32 madp_th2_dep0_cmplx_static : 10; + } cmplx_statc_cfg; + + /* 0x000020d4 reg2101*/ + RK_U32 reserved_2101; + + /* 0x20D8 CMPLX_STATC_THD1_COMB reg2102*/ + struct { + RK_U32 madp_th0_dep1_cmplx_static : 6; + RK_U32 madp_th1_dep1_cmplx_static : 8; + RK_U32 madp_th2_dep1_cmplx_static : 10; + RK_U32 static_num_thre_dep1_cmplx_static : 2; + RK_U32 srch_rgn_mv_th_cmplx_static : 5; + RK_U32 reserved1 : 1; + } cmplx_statc_thd1_comb; + + /* 0x20DC CMPLX_STATC_THD2_COMB reg2103*/ + struct { + RK_U32 num_grdn_point_th1_dep1_cmplx_static : 6; + RK_U32 num_grdn_point_th2_dep1_cmplx_static : 6; + RK_U32 madi_th1_dep1_cmplx_static : 6; + RK_U32 madi_th2_dep1_cmplx_static : 6; + RK_U32 cmplx_static_num_cu16_th : 3; + RK_U32 cmplx_static_frame_qp_en : 1; + RK_U32 cmplx_static_ratio_light_madp_th : 2; + RK_U32 reserved1 : 2; + } cmplx_statc_thd2_comb; + + /* 0x20E0 CMPLX_STATC_WGT0_COMB reg2104*/ + struct { + RK_U32 cmplx_static_inter_res_j_coef_wgt1_dep0 : 8; + RK_U32 cmplx_static_inter_res_j_coef_wgt2_dep0 : 8; + RK_U32 cmplx_static_inter_res_j_coef_wgt1_dep1 : 8; + RK_U32 cmplx_static_inter_res_j_coef_wgt2_dep1 : 8; + } cmplx_statc_wgt0_comb; + + /* 0x20E4 CMPLX_STATC_WGT1_COMB reg2105*/ + struct { + RK_U32 cmplx_static_intra_j_coef_wgt1_dep0 : 8; + RK_U32 cmplx_static_intra_j_coef_wgt2_dep0 : 8; + RK_U32 cmplx_static_intra_j_coef_wgt1_dep1 : 8; + RK_U32 cmplx_static_intra_j_coef_wgt2_dep1 : 8; + } cmplx_statc_wgt1_comb; + + /* 0x000020e8 reg2106 - 0x0000215c reg2135*/ + RK_U32 reserved_2106_2135[29]; + + /* 0x00002160 reg2136 */ + struct { + RK_U32 atr_thd0 : 8; + RK_U32 atr_thd1 : 8; + RK_U32 atr_thd2 : 8; + RK_U32 atr_qp : 6; + RK_U32 reserved : 2; + } atr_thd; + + /* 0x00002164 reg2137 */ + struct { + RK_U32 atr_lv16_wgt0 : 8; + RK_U32 atr_lv16_wgt1 : 8; + RK_U32 atr_lv16_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt16; + + /* 0x00002168 reg2138 */ + struct { + RK_U32 atr_lv8_wgt0 : 8; + RK_U32 atr_lv8_wgt1 : 8; + RK_U32 atr_lv8_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt8; + + /* 0x0000216c reg2139 */ + struct { + RK_U32 atr_lv4_wgt0 : 8; + RK_U32 atr_lv4_wgt1 : 8; + RK_U32 atr_lv4_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt4; +} H264eVepu511aSqi; + +/* class: scaling list */ +/* 0x00002200 reg2176- 0x0000268c reg2467*/ +typedef struct H264eVepu511aSclCfg_t { + /* 0x2200 - 0x227c, valid for h.264 iq_scal_t8_intra0~15 iq_scal_t8_inter0~15*/ + RK_U32 tu8_intra_y[16]; + RK_U32 tu8_intra_u[16]; + + /* 0x2280 - 0x258c*/ + RK_U32 reserved_2208_2215[196]; + + /* 0x2590 - 0x268c, valid for h.264 q_scal_t8_intra0~31 q_scal_t8_inter0~31*/ + RK_U32 q_t8_intra[32]; + RK_U32 q_t8_inter[32]; +} H264eVepu511aSclCfg; + +typedef struct HalVepu511aReg_t { + Vepu511aControlCfg reg_ctl; + H264eVepu511aFrame reg_frm; + Vepu511aRcRoi reg_rc_roi; + H264eVepu511aParam reg_param; + H264eVepu511aSqi reg_sqi; + H264eVepu511aSclCfg reg_scl; + Vepu511aStatus reg_st; + Vepu511aDbg reg_dbg; +} HalVepu511aRegSet; + +#endif \ No newline at end of file diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu540c.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu540c.c new file mode 100644 index 000000000..b592e20a4 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu540c.c @@ -0,0 +1,1755 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264e_vepu540c" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" +#include "mpp_rc.h" +#include "mpp_packet_impl.h" + +#include "h264e_sps.h" +#include "h264e_pps.h" +#include "h264e_slice.h" + +#include "hal_h264e_debug.h" +#include "hal_bufs.h" +#include "mpp_enc_hal.h" +#include "vepu5xx_common.h" +#include "vepu540c_common.h" + +#include "hal_h264e_vepu540c_reg.h" +#include "hal_h264e_stream_amend.h" + +#define DUMP_REG 0 +#define MAX_CORE_NUM 2 + +typedef struct vepu540c_h264e_reg_ctx_t { + void *reg; + RK_U32 used; +} Vepu540cH264eRegCtx; + +typedef struct HalH264eVepu540cCtx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_S32 frame_cnt; + + /* buffers management */ + HalBufs hw_recn; + RK_S32 pixel_buf_fbc_hdr_size; + RK_S32 pixel_buf_fbc_bdy_size; + RK_S32 pixel_buf_size; + RK_S32 thumb_buf_size; + RK_S32 max_buf_cnt; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eSlice *slice; + H264eFrmInfo *frms; + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + H264ePrefixNal *prefix; + HalH264eVepuStreamAmend amend; + + /* syntax for output to enc_impl */ + EncRcTaskInfo hal_rc_cfg; + + /* roi */ + void *roi_data; + + /* register */ + HalVepu540cRegSet *regs_set; + + /* external line buffer over 3K */ + MppBufferGroup ext_line_buf_grp; + RK_S32 ext_line_buf_size; + MppBuffer ext_line_buf; +} HalH264eVepu540cCtx; + +static RK_S32 h264_aq_tthd_default[16] = { + 0, 0, 0, 0, + 3, 3, 5, 5, + 8, 8, 8, 15, + 15, 20, 25, 25, +}; + +static RK_S32 h264_P_aq_step_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 7, 8, +}; + +static RK_S32 h264_I_aq_step_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 8, 8, +}; + +static MPP_RET hal_h264e_vepu540c_deinit(void *hal) +{ + HalH264eVepu540cCtx *p = (HalH264eVepu540cCtx *)hal; + hal_h264e_dbg_func("enter %p\n", p); + + h264e_vepu_stream_amend_deinit(&p->amend); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + if (p->ext_line_buf) { + mpp_buffer_put(p->ext_line_buf); + p->ext_line_buf = NULL; + } + + if (p->ext_line_buf_grp) { + mpp_buffer_group_put(p->ext_line_buf_grp); + p->ext_line_buf_grp = NULL; + } + + if (p->hw_recn) { + hal_bufs_deinit(p->hw_recn); + p->hw_recn = NULL; + } + + MPP_FREE(p->regs_set); + + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu540c_init(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu540cCtx *p = (HalH264eVepu540cCtx *)hal; + MPP_RET ret = MPP_OK; + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + + ret = hal_bufs_init(&p->hw_recn); + if (ret) { + mpp_err_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 1; + hw->qp_delta_row = 2; + hw->qbias_i = 683; + hw->qbias_p = 341; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, h264_aq_tthd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, h264_aq_tthd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, h264_I_aq_step_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, h264_P_aq_step_default, sizeof(hw->aq_step_p)); + } + + p->regs_set = mpp_calloc(HalVepu540cRegSet, 1); + + if (!p->regs_set) { + mpp_err("HalVepu540cRegSet alloc fail"); + return MPP_ERR_MALLOC; + } + +DONE: + if (ret) + hal_h264e_vepu540c_deinit(hal); + + h264e_vepu_stream_amend_init(&p->amend); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +static void setup_hal_bufs(HalH264eVepu540cCtx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + RK_S32 alignment = 64; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment); + RK_S32 aligned_h = MPP_ALIGN(prep->height, alignment); + RK_S32 pixel_buf_fbc_hdr_size = MPP_ALIGN(aligned_w * aligned_h / 64, SZ_8K); + RK_S32 pixel_buf_fbc_bdy_size = aligned_w * aligned_h * 3 / 2; + RK_S32 pixel_buf_size = pixel_buf_fbc_hdr_size + pixel_buf_fbc_bdy_size; + RK_S32 thumb_buf_size = MPP_ALIGN(aligned_w / 64 * aligned_h / 64 * 256, SZ_8K); + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 2; + MppEncRefCfg ref_cfg = cfg->ref_cfg; + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + if (new_max_cnt < MPP_MAX(new_max_cnt, info->dpb_size + 1)) + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > (3 * SZ_1K)) { + RK_S32 ext_line_buf_size = (aligned_w / 64 - 36) * 56 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + + if (NULL == ctx->ext_line_buf) + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_buf, ext_line_buf_size); + + ctx->ext_line_buf_size = ext_line_buf_size; + } else { + if (ctx->ext_line_buf) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + } + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + if ((ctx->pixel_buf_fbc_hdr_size != pixel_buf_fbc_hdr_size) || + (ctx->pixel_buf_fbc_bdy_size != pixel_buf_fbc_bdy_size) || + (ctx->pixel_buf_size != pixel_buf_size) || + (ctx->thumb_buf_size != thumb_buf_size) || + (new_max_cnt > old_max_cnt)) { + size_t sizes[2]; + + hal_h264e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->pixel_buf_size, pixel_buf_size, + old_max_cnt, new_max_cnt); + + /* pixel buffer */ + sizes[0] = pixel_buf_size; + /* thumb buffer */ + sizes[1] = thumb_buf_size; + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_bufs_setup(ctx->hw_recn, new_max_cnt, 2, sizes); + + ctx->pixel_buf_fbc_hdr_size = pixel_buf_fbc_hdr_size; + ctx->pixel_buf_fbc_bdy_size = pixel_buf_fbc_bdy_size; + ctx->pixel_buf_size = pixel_buf_size; + ctx->thumb_buf_size = thumb_buf_size; + ctx->max_buf_cnt = new_max_cnt; + } +} + +static MPP_RET hal_h264e_vepu540c_prepare(void *hal) +{ + HalH264eVepu540cCtx *ctx = (HalH264eVepu540cCtx *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->hw_recn, i); + + prep->change_res = 0; + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_U32 update_vepu540c_syntax(HalH264eVepu540cCtx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu540c_get_task(void *hal, HalEncTask *task) +{ + HalH264eVepu540cCtx *ctx = (HalH264eVepu540cCtx *)hal; + MppEncH264HwCfg *hw_cfg = &ctx->cfg->h264.hw_cfg; + RK_U32 updated = update_vepu540c_syntax(ctx, &task->syntax); + EncFrmStatus *frm_status = &task->rc_task->frm; + hal_h264e_dbg_func("enter %p\n", hal); + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) + setup_hal_bufs(ctx); + + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(task->frame); + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + } + + /* if not VEPU1/2, update log2_max_frame_num_minus4 in hw_cfg */ + hw_cfg->hw_log2_max_frame_num_minus4 = ctx->sps->log2_max_frame_num_minus4; + + h264e_vepu_stream_amend_config(&ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static void setup_vepu540c_normal(HalVepu540cRegSet *regs) +{ + hal_h264e_dbg_func("enter\n"); + /* reg000 VERSION is read only */ + + /* reg001 ENC_STRT */ + regs->reg_ctl.enc_strt.lkt_num = 0; + regs->reg_ctl.enc_strt.vepu_cmd = 1; + + regs->reg_ctl.func_en.cke = 1; + regs->reg_ctl.func_en.resetn_hw_en = 1; + regs->reg_ctl.func_en.enc_done_tmvp_en = 1; + + /* reg002 ENC_CLR */ + regs->reg_ctl.enc_clr.safe_clr = 0; + regs->reg_ctl.enc_clr.force_clr = 0; + + /* reg003 LKT_ADDR */ + // regs->reg_ctl.lkt_addr = 0; + + /* reg004 INT_EN */ + regs->reg_ctl.int_en.enc_done_en = 1; + regs->reg_ctl.int_en.lkt_node_done_en = 1; + regs->reg_ctl.int_en.sclr_done_en = 1; + regs->reg_ctl.int_en.vslc_done_en = 0; + regs->reg_ctl.int_en.vbsf_oflw_en = 1; + regs->reg_ctl.int_en.vbuf_lens_en = 1; + regs->reg_ctl.int_en.enc_err_en = 1; + regs->reg_ctl.int_en.dvbm_fcfg_en = 1; + regs->reg_ctl.int_en.wdg_en = 1; + regs->reg_ctl.int_en.lkt_err_int_en = 1; + regs->reg_ctl.int_en.lkt_err_stop_en = 1; + regs->reg_ctl.int_en.lkt_force_stop_en = 1; + regs->reg_ctl.int_en.jslc_done_en = 1; + regs->reg_ctl.int_en.jbsf_oflw_en = 1; + regs->reg_ctl.int_en.jbuf_lens_en = 1; + regs->reg_ctl.int_en.dvbm_dcnt_en = 1; + + /* reg005 INT_MSK */ + regs->reg_ctl.int_msk.enc_done_msk = 0; + regs->reg_ctl.int_msk.lkt_node_done_msk = 0; + regs->reg_ctl.int_msk.sclr_done_msk = 0; + regs->reg_ctl.int_msk.vslc_done_msk = 0; + regs->reg_ctl.int_msk.vbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.vbuf_lens_msk = 0; + regs->reg_ctl.int_msk.enc_err_msk = 0; + regs->reg_ctl.int_msk.dvbm_fcfg_msk = 0; + regs->reg_ctl.int_msk.wdg_msk = 0; + regs->reg_ctl.int_msk.lkt_err_int_msk = 0; + regs->reg_ctl.int_msk.lkt_err_stop_msk = 0; + regs->reg_ctl.int_msk.lkt_force_stop_msk = 0; + regs->reg_ctl.int_msk.jslc_done_msk = 0; + regs->reg_ctl.int_msk.jbsf_oflw_msk = 0; + regs->reg_ctl.int_msk.jbuf_lens_msk = 0; + regs->reg_ctl.int_msk.dvbm_dcnt_msk = 0; + + /* reg006 INT_CLR is not set */ + /* reg007 INT_STA is read only */ + /* reg008 ~ reg0011 gap */ + regs->reg_ctl.enc_wdg.vs_load_thd = 0x5ffff; + regs->reg_ctl.enc_wdg.rfp_load_thd = 0;//xff; + + /* reg015 DTRNS_MAP */ + regs->reg_ctl.dtrns_map.jpeg_bus_edin = 0; + regs->reg_ctl.dtrns_map.src_bus_edin = 0; + regs->reg_ctl.dtrns_map.meiw_bus_edin = 0; + regs->reg_ctl.dtrns_map.bsw_bus_edin = 7; + regs->reg_ctl.dtrns_map.lktr_bus_edin = 0; + regs->reg_ctl.dtrns_map.roir_bus_edin = 0; + regs->reg_ctl.dtrns_map.lktw_bus_edin = 0; + regs->reg_ctl.dtrns_map.rec_nfbc_bus_edin = 0; + + regs->reg_ctl.dtrns_cfg.axi_brsp_cke = 0; + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET setup_vepu540c_prep(HalVepu540cRegSet *regs, MppEncPrepCfg *prep) +{ + VepuFmtCfg cfg; + MppFrameFormat fmt = prep->format; + MPP_RET ret = vepu5xx_set_fmt(&cfg, fmt); + RK_U32 hw_fmt = cfg.format; + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + /* do nothing when color format is not supported */ + if (ret) + return ret; + + regs->reg_base.enc_rsl.pic_wd8_m1 = MPP_ALIGN(prep->width, 16) / 8 - 1; + regs->reg_base.src_fill.pic_wfill = MPP_ALIGN(prep->width, 16) - prep->width; + regs->reg_base.enc_rsl.pic_hd8_m1 = MPP_ALIGN(prep->height, 16) / 8 - 1; + regs->reg_base.src_fill.pic_hfill = MPP_ALIGN(prep->height, 16) - prep->height; + + regs->reg_ctl.dtrns_map.src_bus_edin = cfg.src_endian; + + regs->reg_base.src_fmt.src_cfmt = hw_fmt; + regs->reg_base.src_fmt.alpha_swap = cfg.alpha_swap; + regs->reg_base.src_fmt.rbuv_swap = cfg.rbuv_swap; + regs->reg_base.src_fmt.out_fmt = (hw_fmt == VEPU5xx_FMT_YUV400) ? 0 : 1; + + y_stride = (MPP_FRAME_FMT_IS_FBC(fmt) != 0) ? (MPP_ALIGN(prep->width, 16)) : + (prep->hor_stride != 0) ? (prep->hor_stride) : (prep->width); + + c_stride = (hw_fmt == VEPU5xx_FMT_YUV422SP || hw_fmt == VEPU5xx_FMT_YUV420SP) ? + y_stride : y_stride / 2; + + if (hw_fmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = get_rgb2yuv_cfg(prep->range, prep->color); + + hal_h264e_dbg_flow("input color range %d colorspace %d", prep->range, prep->color); + + regs->reg_base.src_udfy.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + regs->reg_base.src_udfy.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + regs->reg_base.src_udfy.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + + regs->reg_base.src_udfu.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + regs->reg_base.src_udfu.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + regs->reg_base.src_udfu.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + + regs->reg_base.src_udfv.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + regs->reg_base.src_udfv.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + regs->reg_base.src_udfv.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + + regs->reg_base.src_udfo.csc_ofst_y = cfg_coeffs->_2y.offset; + regs->reg_base.src_udfo.csc_ofst_u = cfg_coeffs->_2u.offset; + regs->reg_base.src_udfo.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h264e_dbg_flow("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } else { + regs->reg_base.src_udfy.csc_wgt_b2y = cfg.weight[0]; + regs->reg_base.src_udfy.csc_wgt_g2y = cfg.weight[1]; + regs->reg_base.src_udfy.csc_wgt_r2y = cfg.weight[2]; + + regs->reg_base.src_udfu.csc_wgt_b2u = cfg.weight[3]; + regs->reg_base.src_udfu.csc_wgt_g2u = cfg.weight[4]; + regs->reg_base.src_udfu.csc_wgt_r2u = cfg.weight[5]; + + regs->reg_base.src_udfv.csc_wgt_b2v = cfg.weight[6]; + regs->reg_base.src_udfv.csc_wgt_g2v = cfg.weight[7]; + regs->reg_base.src_udfv.csc_wgt_r2v = cfg.weight[8]; + + regs->reg_base.src_udfo.csc_ofst_y = cfg.offset[0]; + regs->reg_base.src_udfo.csc_ofst_u = cfg.offset[1]; + regs->reg_base.src_udfo.csc_ofst_v = cfg.offset[2]; + } + + regs->reg_base.src_strd0.src_strd0 = y_stride; + regs->reg_base.src_strd1.src_strd1 = c_stride; + + regs->reg_base.src_proc.src_mirr = prep->mirroring > 0; + regs->reg_base.src_proc.src_rot = prep->rotation; + // regs->reg_base.src_proc.txa_en = 0; + + regs->reg_base.sli_cfg.mv_v_lmt_thd = 0; + regs->reg_base.sli_cfg.mv_v_lmt_en = 0; + + regs->reg_base.pic_ofst.pic_ofst_y = 0; + regs->reg_base.pic_ofst.pic_ofst_x = 0; + + hal_h264e_dbg_func("leave\n"); + + return ret; +} + +static void setup_vepu540c_codec(HalVepu540cRegSet *regs, H264eSps *sps, + H264ePps *pps, H264eSlice *slice) +{ + hal_h264e_dbg_func("enter\n"); + + regs->reg_base.enc_pic.enc_stnd = 0; + regs->reg_base.enc_pic.cur_frm_ref = slice->nal_reference_idc > 0; + regs->reg_base.enc_pic.bs_scp = 1; + + regs->reg_base.synt_nal.nal_ref_idc = slice->nal_reference_idc; + regs->reg_base.synt_nal.nal_unit_type = slice->nalu_type; + + regs->reg_base.synt_sps.max_fnum = sps->log2_max_frame_num_minus4; + regs->reg_base.synt_sps.drct_8x8 = sps->direct8x8_inference; + regs->reg_base.synt_sps.mpoc_lm4 = sps->log2_max_poc_lsb_minus4; + + regs->reg_base.synt_pps.etpy_mode = pps->entropy_coding_mode; + regs->reg_base.synt_pps.trns_8x8 = pps->transform_8x8_mode; + regs->reg_base.synt_pps.csip_flag = pps->constrained_intra_pred; + regs->reg_base.synt_pps.num_ref0_idx = pps->num_ref_idx_l0_default_active - 1; + regs->reg_base.synt_pps.num_ref1_idx = pps->num_ref_idx_l1_default_active - 1; + regs->reg_base.synt_pps.pic_init_qp = pps->pic_init_qp; + regs->reg_base.synt_pps.cb_ofst = pps->chroma_qp_index_offset; + regs->reg_base.synt_pps.cr_ofst = pps->second_chroma_qp_index_offset; + regs->reg_base.synt_pps.dbf_cp_flg = pps->deblocking_filter_control; + + regs->reg_base.synt_sli0.sli_type = (slice->slice_type == H264_I_SLICE) ? (2) : (0); + regs->reg_base.synt_sli0.pps_id = slice->pic_parameter_set_id; + regs->reg_base.synt_sli0.drct_smvp = 0; + regs->reg_base.synt_sli0.num_ref_ovrd = slice->num_ref_idx_override; + regs->reg_base.synt_sli0.cbc_init_idc = slice->cabac_init_idc; + regs->reg_base.synt_sli0.frm_num = slice->frame_num; + + regs->reg_base.synt_sli1.idr_pid = (slice->slice_type == H264_I_SLICE) ? slice->idr_pic_id : (RK_U32)(-1); + regs->reg_base.synt_sli1.poc_lsb = slice->pic_order_cnt_lsb; + + + regs->reg_base.synt_sli2.dis_dblk_idc = slice->disable_deblocking_filter_idc; + regs->reg_base.synt_sli2.sli_alph_ofst = slice->slice_alpha_c0_offset_div2; + + h264e_reorder_rd_rewind(slice->reorder); + { /* reorder process */ + H264eRplmo rplmo; + MPP_RET ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + if (MPP_OK == ret) { + regs->reg_base.synt_sli2.ref_list0_rodr = 1; + regs->reg_base.synt_sli2.rodr_pic_idx = rplmo.modification_of_pic_nums_idc; + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + regs->reg_base.synt_sli2.rodr_pic_num = rplmo.abs_diff_pic_num_minus1; + } break; + case 2 : { + regs->reg_base.synt_sli2.rodr_pic_num = rplmo.long_term_pic_idx; + } break; + default : { + mpp_err_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + } else { + // slice->ref_pic_list_modification_flag; + regs->reg_base.synt_sli2.ref_list0_rodr = 0; + regs->reg_base.synt_sli2.rodr_pic_idx = 0; + regs->reg_base.synt_sli2.rodr_pic_num = 0; + } + } + + /* clear all mmco arg first */ + regs->reg_base.synt_refm0.nopp_flg = 0; + regs->reg_base.synt_refm0.ltrf_flg = 0; + regs->reg_base.synt_refm0.arpm_flg = 0; + regs->reg_base.synt_refm0.mmco4_pre = 0; + regs->reg_base.synt_refm0.mmco_type0 = 0; + regs->reg_base.synt_refm0.mmco_parm0 = 0; + regs->reg_base.synt_refm0.mmco_type1 = 0; + regs->reg_base.synt_refm1.mmco_parm1 = 0; + regs->reg_base.synt_refm0.mmco_type2 = 0; + regs->reg_base.synt_refm1.mmco_parm2 = 0; + regs->reg_base.synt_refm2.long_term_frame_idx0 = 0; + regs->reg_base.synt_refm2.long_term_frame_idx1 = 0; + regs->reg_base.synt_refm2.long_term_frame_idx2 = 0; + + h264e_marking_rd_rewind(slice->marking); + + /* only update used parameter */ + if (slice->slice_type == H264_I_SLICE) { + regs->reg_base.synt_refm0.nopp_flg = slice->no_output_of_prior_pics; + regs->reg_base.synt_refm0.ltrf_flg = slice->long_term_reference_flag; + } else { + if (!h264e_marking_is_empty(slice->marking)) { + H264eMmco mmco; + + regs->reg_base.synt_refm0.arpm_flg = 1; + + /* max 3 mmco */ + do { + RK_S32 type = 0; + RK_S32 param_0 = 0; + RK_S32 param_1 = 0; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_base.synt_refm0.mmco_type0 = type; + regs->reg_base.synt_refm0.mmco_parm0 = param_0; + regs->reg_base.synt_refm2.long_term_frame_idx0 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_base.synt_refm0.mmco_type1 = type; + regs->reg_base.synt_refm1.mmco_parm1 = param_0; + regs->reg_base.synt_refm2.long_term_frame_idx1 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_base.synt_refm0.mmco_type2 = type; + regs->reg_base.synt_refm1.mmco_parm2 = param_0; + regs->reg_base.synt_refm2.long_term_frame_idx2 = param_1; + } while (0); + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540c_rdo_pred(HalVepu540cRegSet *regs, H264eSps *sps, + H264ePps *pps, H264eSlice *slice) +{ + hal_h264e_dbg_func("enter\n"); + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 6; + } else { + regs->reg_rc_roi.klut_ofst.chrm_klut_ofst = 9; + } + + regs->reg_base.rdo_cfg.rect_size = (sps->profile_idc == H264_PROFILE_BASELINE && + sps->level_idc <= H264_LEVEL_3_0) ? 1 : 0; + regs->reg_base.rdo_cfg.vlc_lmt = (sps->profile_idc < H264_PROFILE_MAIN) && + !pps->entropy_coding_mode; + regs->reg_base.rdo_cfg.chrm_spcl = 1; + regs->reg_base.rdo_cfg.ccwa_e = 1; + regs->reg_base.rdo_cfg.scl_lst_sel = pps->pic_scaling_matrix_present; + regs->reg_base.rdo_cfg.atf_e = 1; + regs->reg_base.rdo_cfg.atr_e = 1; + regs->reg_base.rdo_cfg.intra_cost_e = 1; + regs->reg_base.iprd_csts.rdo_mark_mode = 0x100; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540c_rdo_cfg(vepu540c_rdo_cfg *reg) +{ + hal_h264e_dbg_func("enter\n"); + rdo_skip_par *p_rdo_skip = NULL; + rdo_noskip_par *p_rdo_noskip = NULL; + + reg->rdo_smear_cfg_comb.rdo_smear_en = 0; + reg->rdo_smear_cfg_comb.rdo_smear_lvl16_multi = 9; + reg->rdo_smear_cfg_comb.rdo_smear_dlt_qp = 0 ; + reg->rdo_smear_cfg_comb.rdo_smear_order_state = 0; + reg->rdo_smear_cfg_comb.stated_mode = 0; + reg->rdo_smear_cfg_comb.online_en = 0; + reg->rdo_smear_cfg_comb.smear_stride = 0; + reg->rdo_smear_madp_thd0_comb.rdo_smear_madp_cur_thd0 = 0; + reg->rdo_smear_madp_thd0_comb.rdo_smear_madp_cur_thd1 = 24; + reg->rdo_smear_madp_thd1_comb.rdo_smear_madp_cur_thd2 = 48; + reg->rdo_smear_madp_thd1_comb.rdo_smear_madp_cur_thd3 = 64; + reg->rdo_smear_madp_thd2_comb.rdo_smear_madp_around_thd0 = 16; + reg->rdo_smear_madp_thd2_comb.rdo_smear_madp_around_thd1 = 32; + reg->rdo_smear_madp_thd3_comb.rdo_smear_madp_around_thd2 = 48; + reg->rdo_smear_madp_thd3_comb.rdo_smear_madp_around_thd3 = 96; + reg->rdo_smear_madp_thd4_comb.rdo_smear_madp_around_thd4 = 48; + reg->rdo_smear_madp_thd4_comb.rdo_smear_madp_around_thd5 = 24; + reg->rdo_smear_madp_thd5_comb.rdo_smear_madp_ref_thd0 = 96; + reg->rdo_smear_madp_thd5_comb.rdo_smear_madp_ref_thd1 = 48; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd0 = 1; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd1 = 3; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd2 = 1; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd3 = 3; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd0 = 1; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd1 = 4; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd2 = 1; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd3 = 4; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd4 = 0; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd5 = 3; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd6 = 0; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd7 = 3; + reg->rdo_smear_cnt_thd3_comb.rdo_smear_cnt_ref_thd0 = 1 ; + reg->rdo_smear_cnt_thd3_comb.rdo_smear_cnt_ref_thd1 = 3; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_small_cur_th0 = 6; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_big_cur_th0 = 9; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_small_cur_th1 = 6; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_big_cur_th1 = 9; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_small_around_th0 = 6; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_big_around_th0 = 11; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_small_around_th1 = 6; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_big_around_th1 = 8; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_small_around_th2 = 9; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_big_around_th2 = 20; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_small_around_th3 = 6; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_big_around_th3 = 20; + reg->rdo_smear_resi_thd3_comb.rdo_smear_resi_small_ref_th0 = 7; + reg->rdo_smear_resi_thd3_comb.rdo_smear_resi_big_ref_th0 = 16; + reg->rdo_smear_st_thd0_comb.rdo_smear_resi_th0 = 10; + reg->rdo_smear_st_thd0_comb.rdo_smear_resi_th1 = 6; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th0 = 1; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th1 = 5; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th2 = 1; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th3 = 3; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th4 = 9; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th5 = 10; + + p_rdo_skip = ®->rdo_b16_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 1; + p_rdo_skip->atf_thd0.madp_thd1 = 10; + p_rdo_skip->atf_thd1.madp_thd2 = 15; + p_rdo_skip->atf_thd1.madp_thd3 = 25; + p_rdo_skip->atf_wgt0.wgt0 = 20; + p_rdo_skip->atf_wgt0.wgt1 = 16; + p_rdo_skip->atf_wgt0.wgt2 = 16; + p_rdo_skip->atf_wgt0.wgt3 = 16; + p_rdo_skip->atf_wgt1.wgt4 = 16; + + p_rdo_noskip = ®->rdo_b16_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 16; + p_rdo_noskip->atf_wgt.wgt1 = 16; + p_rdo_noskip->atf_wgt.wgt2 = 16; + p_rdo_noskip->atf_wgt.wgt3 = 16; + + p_rdo_noskip = ®->rdo_b16_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 27; + p_rdo_noskip->atf_wgt.wgt1 = 25; + p_rdo_noskip->atf_wgt.wgt2 = 20; + p_rdo_noskip->atf_wgt.wgt3 = 16; + + reg->rdo_b16_intra_atf_cnt_thd_comb.thd0 = 1; + reg->rdo_b16_intra_atf_cnt_thd_comb.thd1 = 4; + reg->rdo_b16_intra_atf_cnt_thd_comb.thd2 = 1; + reg->rdo_b16_intra_atf_cnt_thd_comb.thd3 = 4; + reg->rdo_atf_resi_thd_comb.big_th0 = 16; + reg->rdo_atf_resi_thd_comb.big_th1 = 16; + reg->rdo_atf_resi_thd_comb.small_th0 = 8; + reg->rdo_atf_resi_thd_comb.small_th1 = 8; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540c_rc_base(HalVepu540cRegSet *regs, HalH264eVepu540cCtx *ctx, EncRcTask *rc_task) +{ + H264eSps *sps = ctx->sps; + H264eSlice *slice = ctx->slice; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + EncRcTaskInfo *rc_info = &rc_task->info; + RK_S32 mb_w = sps->pic_width_in_mbs; + RK_S32 mb_h = sps->pic_height_in_mbs; + RK_U32 qp_target = rc_info->quality_target; + RK_U32 qp_min = rc_info->quality_min; + RK_U32 qp_max = rc_info->quality_max; + RK_U32 qpmap_mode = 1; + RK_S32 mb_target_bits_mul_16 = (rc_info->bit_target << 4) / (mb_w * mb_h); + RK_S32 mb_target_bits; + RK_S32 negative_bits_thd; + RK_S32 positive_bits_thd; + + hal_h264e_dbg_rc("bittarget %d qp [%d %d %d]\n", rc_info->bit_target, + qp_min, qp_target, qp_max); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_rc_roi.roi_qthd0.qpmin_area0 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area0 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area1 = qp_min; + regs->reg_rc_roi.roi_qthd0.qpmax_area1 = qp_max; + regs->reg_rc_roi.roi_qthd0.qpmin_area2 = qp_min; + + regs->reg_rc_roi.roi_qthd1.qpmax_area2 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area3 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area3 = qp_max; + regs->reg_rc_roi.roi_qthd1.qpmin_area4 = qp_min; + regs->reg_rc_roi.roi_qthd1.qpmax_area4 = qp_max; + + regs->reg_rc_roi.roi_qthd2.qpmin_area5 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area5 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area6 = qp_min; + regs->reg_rc_roi.roi_qthd2.qpmax_area6 = qp_max; + regs->reg_rc_roi.roi_qthd2.qpmin_area7 = qp_min; + + regs->reg_rc_roi.roi_qthd3.qpmax_area7 = qp_max; + regs->reg_rc_roi.roi_qthd3.qpmap_mode = qpmap_mode; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + regs->reg_base.enc_pic.pic_qp = rc_info->quality_target; + regs->reg_base.rc_qp.rc_max_qp = rc_info->quality_target; + regs->reg_base.rc_qp.rc_min_qp = rc_info->quality_target; + + return; + } + + if (mb_target_bits_mul_16 >= 0x100000) + mb_target_bits_mul_16 = 0x50000; + + mb_target_bits = (mb_target_bits_mul_16 * mb_w) >> 4; + negative_bits_thd = 0 - 5 * mb_target_bits / 16; + positive_bits_thd = 5 * mb_target_bits / 16; + + regs->reg_base.enc_pic.pic_qp = qp_target; + + regs->reg_base.rc_cfg.rc_en = 1; + regs->reg_base.rc_cfg.aq_en = 1; + regs->reg_base.rc_cfg.aq_mode = 0; + regs->reg_base.rc_cfg.rc_ctu_num = mb_w; + + regs->reg_base.rc_qp.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? + hw->qp_delta_row_i : hw->qp_delta_row; + regs->reg_base.rc_qp.rc_max_qp = qp_max; + regs->reg_base.rc_qp.rc_min_qp = qp_min; + + regs->reg_base.rc_tgt.ctu_ebit = mb_target_bits_mul_16; + + regs->reg_rc_roi.rc_adj0.qp_adj0 = -2; + regs->reg_rc_roi.rc_adj0.qp_adj1 = -1; + regs->reg_rc_roi.rc_adj0.qp_adj2 = 0; + regs->reg_rc_roi.rc_adj0.qp_adj3 = 1; + regs->reg_rc_roi.rc_adj0.qp_adj4 = 2; + regs->reg_rc_roi.rc_adj1.qp_adj5 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj6 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj7 = 0; + regs->reg_rc_roi.rc_adj1.qp_adj8 = 0; + + regs->reg_rc_roi.rc_dthd_0_8[0] = 4 * negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[1] = negative_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[2] = positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[3] = 4 * positive_bits_thd; + regs->reg_rc_roi.rc_dthd_0_8[4] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[5] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[6] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[7] = 0x7FFFFFFF; + regs->reg_rc_roi.rc_dthd_0_8[8] = 0x7FFFFFFF; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540c_io_buf(HalVepu540cRegSet *regs, MppDev dev, + HalEncTask *task) +{ + MppFrame frm = task->frame; + MppPacket pkt = task->packet; + MppBuffer buf_in = mpp_frame_get_buffer(frm); + MppBuffer buf_out = task->output; + MppFrameFormat fmt = mpp_frame_get_fmt(frm); + RK_S32 hor_stride = mpp_frame_get_hor_stride(frm); + RK_S32 ver_stride = mpp_frame_get_ver_stride(frm); + RK_S32 fd_in = mpp_buffer_get_fd(buf_in); + RK_U32 off_in[2] = {0}; + RK_U32 off_out = mpp_packet_get_length(pkt); + size_t siz_out = mpp_buffer_get_size(buf_out); + RK_S32 fd_out = mpp_buffer_get_fd(buf_out); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_base.adr_src0 = fd_in; + regs->reg_base.adr_src1 = fd_in; + regs->reg_base.adr_src2 = fd_in; + + regs->reg_base.bsbt_addr = fd_out; + regs->reg_base.bsbb_addr = fd_out; + regs->reg_base.adr_bsbs = fd_out; + regs->reg_base.bsbr_addr = fd_out; + mpp_dev_set_reg_offset(dev, 172, siz_out); + mpp_dev_set_reg_offset(dev, 174, off_out); + + regs->reg_base.rfpt_h_addr = 0xffffffff; + regs->reg_base.rfpb_h_addr = 0; + regs->reg_base.rfpt_b_addr = 0xffffffff; + regs->reg_base.adr_rfpb_b = 0; + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + off_in[0] = mpp_frame_get_fbc_offset(frm);; + off_in[1] = 0; + } else if (MPP_FRAME_FMT_IS_YUV(fmt)) { + VepuFmtCfg cfg; + + vepu5xx_set_fmt(&cfg, fmt); + switch (cfg.format) { + case VEPU5xx_FMT_BGRA8888 : + case VEPU5xx_FMT_BGR888 : + case VEPU5xx_FMT_BGR565 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV422SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV422P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 3 / 2; + } break; + case VEPU5xx_FMT_YUV420P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 5 / 4; + } break; + case VEPU5xx_FMT_YUV400 : + case VEPU5xx_FMT_YUYV422 : + case VEPU5xx_FMT_UYVY422 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + default : { + off_in[0] = 0; + off_in[1] = 0; + } break; + } + } + + mpp_dev_set_reg_offset(dev, 161, off_in[0]); + mpp_dev_set_reg_offset(dev, 162, off_in[1]); + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540c_recn_refr(HalH264eVepu540cCtx *ctx, HalVepu540cRegSet *regs) +{ + + MppDev dev = ctx->dev; + H264eFrmInfo *frms = ctx->frms; + HalBufs bufs = ctx->hw_recn; + RK_S32 fbc_hdr_size = ctx->pixel_buf_fbc_hdr_size; + + HalBuf *curr = hal_bufs_get_buf(bufs, frms->curr_idx); + HalBuf *refr = hal_bufs_get_buf(bufs, frms->refr_idx); + + hal_h264e_dbg_func("enter\n"); + + if (curr && curr->cnt) { + MppBuffer buf_pixel = curr->buf[0]; + MppBuffer buf_thumb = curr->buf[1]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg_base.rfpw_h_addr = fd; + regs->reg_base.rfpw_b_addr = fd; + regs->reg_base.dspw_addr = mpp_buffer_get_fd(buf_thumb); + mpp_dev_set_reg_offset(dev, 164, fbc_hdr_size); + } + + if (refr && refr->cnt) { + MppBuffer buf_pixel = refr->buf[0]; + MppBuffer buf_thumb = refr->buf[1]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg_base.rfpr_h_addr = fd; + regs->reg_base.rfpr_b_addr = fd; + regs->reg_base.dspr_addr = mpp_buffer_get_fd(buf_thumb); + mpp_dev_set_reg_offset(dev, 166, fbc_hdr_size); + } + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540c_split(HalVepu540cRegSet *regs, MppEncCfgSet *cfg) +{ + hal_h264e_dbg_func("enter\n"); + + switch (cfg->split.split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_base.sli_splt.sli_splt = 0; + regs->reg_base.sli_splt.sli_splt_mode = 0; + regs->reg_base.sli_splt.sli_splt_cpst = 0; + regs->reg_base.sli_splt.sli_max_num_m1 = 0; + regs->reg_base.sli_splt.sli_flsh = 0; + regs->reg_base.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.sli_byte.sli_splt_byte = 0; + regs->reg_base.enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_base.sli_splt.sli_splt = 1; + regs->reg_base.sli_splt.sli_splt_mode = 0; + regs->reg_base.sli_splt.sli_splt_cpst = 0; + regs->reg_base.sli_splt.sli_max_num_m1 = 500; + regs->reg_base.sli_splt.sli_flsh = 1; + regs->reg_base.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.sli_byte.sli_splt_byte = cfg->split.split_arg; + regs->reg_base.enc_pic.slen_fifo = 0; + regs->reg_base.enc_pic.slen_fifo = (cfg->split.split_out != 0) ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = regs->reg_base.enc_pic.slen_fifo; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + RK_U32 mb_w = MPP_ALIGN(cfg->prep.width, 16) / 16; + RK_U32 mb_h = MPP_ALIGN(cfg->prep.height, 16) / 16; + RK_U32 slice_num = (mb_w * mb_h + cfg->split.split_arg - 1) / cfg->split.split_arg; + + regs->reg_base.sli_splt.sli_splt = 1; + regs->reg_base.sli_splt.sli_splt_mode = 1; + regs->reg_base.sli_splt.sli_splt_cpst = 0; + regs->reg_base.sli_splt.sli_max_num_m1 = 500; + regs->reg_base.sli_splt.sli_flsh = 1; + regs->reg_base.sli_cnum.sli_splt_cnum_m1 = cfg->split.split_arg - 1; + + regs->reg_base.sli_byte.sli_splt_byte = 0; + regs->reg_base.enc_pic.slen_fifo = (cfg->split.split_out != 0) ? 1 : 0; + if ((cfg->split.split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) || + (regs->reg_base.enc_pic.slen_fifo && (slice_num > VEPU540C_SLICE_FIFO_LEN))) + regs->reg_ctl.int_en.vslc_done_en = 1; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split.split_mode); + } break; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void calc_cime_parameter(HalVepu540cRegSet *regs) +{ + Vepu540cBaseCfg *base_regs = ®s->reg_base; + RK_S32 x_gmv = 0; + RK_S32 y_gmv = 0; + RK_S32 srch_lftw , srch_rgtw, srch_uph, srch_dwnh; + RK_S32 frm_sta = 0, frm_end = 0, pic_w = 0; + RK_S32 pic_wdt_align = ((base_regs->enc_rsl.pic_wd8_m1 + 1) * 8 + 63) / 64 * 2; + + + srch_lftw = base_regs->me_rnge.cime_srch_lftw * 4; + srch_rgtw = base_regs->me_rnge.cime_srch_rgtw * 4; + srch_uph = base_regs->me_rnge.cime_srch_uph * 2; + srch_dwnh = base_regs->me_rnge.cime_srch_dwnh * 2; + + // calc cime_linebuf_w + { + { + if (x_gmv - srch_lftw < 0) { + frm_sta = 0; + } else { + frm_sta = (x_gmv - srch_lftw) / 16; + } + if (x_gmv + srch_rgtw < 0) { + frm_end = pic_wdt_align - 1 + (x_gmv + srch_rgtw) / 16; + } else { + frm_end = pic_wdt_align - 1 + (x_gmv + srch_rgtw + 15) / 16; + } + } + if (frm_sta < 0) { + frm_sta = 0; + } else if (frm_sta > pic_wdt_align - 1) { + frm_sta = pic_wdt_align - 1; + } + frm_end = mpp_clip(frm_end, 0, pic_wdt_align - 1); + pic_w = (frm_end - frm_sta + 1) * 32; + base_regs->me_cach.cme_linebuf_w = pic_w / 32; + } + + // calc cime_rama_h and cime_rama_max + { + RK_U32 rama_size = 1796; + RK_U32 ramb_h; + RK_U32 ctu_2_h = 2; + RK_U32 cur_srch_8_w, cur_srch_2_h, cur_srch_h; + + + if ((y_gmv % 4 - srch_uph % 4) < 0) { + cur_srch_2_h = (4 + (y_gmv % 4 - srch_uph % 4) % 4 + srch_uph + srch_dwnh) / 2 + ctu_2_h; + } else { + cur_srch_2_h = ((y_gmv % 4 - srch_uph % 4) % 4 + srch_uph + srch_dwnh) / 2 + ctu_2_h; + } + base_regs->me_cach.cime_size_rama = (cur_srch_2_h + 1) / 2 * 2; + + if ((x_gmv % 16 - srch_lftw % 16) < 0) { + cur_srch_8_w = ((16 + (x_gmv % 16 - srch_lftw % 16) % 16 + srch_lftw + srch_rgtw + 15) / 16 + 1) * 2; + } else { + cur_srch_8_w = (((x_gmv % 16 - srch_lftw % 16) % 16 + srch_lftw + srch_rgtw + 15) / 16 + 1) * 2; + } + + cur_srch_h = ctu_2_h; + ramb_h = cur_srch_2_h; + while ((rama_size > ((cur_srch_h - ctu_2_h) * base_regs->me_cach.cme_linebuf_w + (ramb_h * cur_srch_8_w))) + && (cur_srch_h < base_regs->me_cach.cime_size_rama)) { + cur_srch_h = cur_srch_h + ctu_2_h; + if (ramb_h > ctu_2_h * 2) { + ramb_h = ramb_h - ctu_2_h; + } else { + ramb_h = ctu_2_h; + } + } + + if (cur_srch_2_h == ctu_2_h * 2) { + cur_srch_h = cur_srch_h + ctu_2_h; + ramb_h = ctu_2_h; + } + if (rama_size < ((cur_srch_h - ctu_2_h) * base_regs->me_cach.cme_linebuf_w + (ramb_h * cur_srch_8_w))) { + cur_srch_h = cur_srch_h - ctu_2_h; + } + base_regs->me_cach.cime_size_rama = ((cur_srch_h - ctu_2_h) * base_regs->me_cach.cme_linebuf_w + ctu_2_h * cur_srch_8_w) / 2; + base_regs->me_cach.cime_hgt_rama = cur_srch_h / 2; + } + +} + +static void setup_vepu540c_me(HalVepu540cRegSet *regs, H264eSps *sps, + H264eSlice *slice) +{ + (void)sps; + (void)slice; + regs->reg_base.me_rnge.cime_srch_dwnh = 15; + regs->reg_base.me_rnge.cime_srch_uph = 14; + regs->reg_base.me_rnge.cime_srch_rgtw = 12; + regs->reg_base.me_rnge.cime_srch_lftw = 12; + regs->reg_base.me_cfg.rme_srch_h = 3; + regs->reg_base.me_cfg.rme_srch_v = 3; + + regs->reg_base.me_cfg.srgn_max_num = 72; + regs->reg_base.me_cfg.cime_dist_thre = 1024; + regs->reg_base.me_cfg.rme_dis = 0; + regs->reg_base.me_cfg.fme_dis = 0; + regs->reg_base.me_rnge.dlt_frm_num = 0x0; + calc_cime_parameter(regs); + hal_h264e_dbg_func("leave\n"); +} + +#define H264E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) + +static RK_U32 h264e_lambda_default[58] = { + 0x00000003, 0x00000005, 0x00000006, 0x00000007, + 0x00000009, 0x0000000b, 0x0000000e, 0x00000012, + 0x00000016, 0x0000001c, 0x00000024, 0x0000002d, + 0x00000039, 0x00000048, 0x0000005b, 0x00000073, + 0x00000091, 0x000000b6, 0x000000e6, 0x00000122, + 0x0000016d, 0x000001cc, 0x00000244, 0x000002db, + 0x00000399, 0x00000489, 0x000005b6, 0x00000733, + 0x00000912, 0x00000b6d, 0x00000e66, 0x00001224, + 0x000016db, 0x00001ccc, 0x00002449, 0x00002db7, + 0x00003999, 0x00004892, 0x00005b6f, 0x00007333, + 0x00009124, 0x0000b6de, 0x0000e666, 0x00012249, + 0x00016dbc, 0x0001cccc, 0x00024492, 0x0002db79, + 0x00039999, 0x00048924, 0x0005b6f2, 0x00073333, + 0x00091249, 0x000b6de5, 0x000e6666, 0x00122492, + 0x0016dbcb, 0x001ccccc, +}; + +static void setup_vepu540c_l2(HalVepu540cRegSet *regs, H264eSlice *slice, MppEncHwCfg *hw) +{ + RK_U32 i; + + hal_h264e_dbg_func("enter\n"); + + memcpy(regs->reg_s3.rdo_wgta_qp_grpa_0_51, &h264e_lambda_default[6], H264E_LAMBDA_TAB_SIZE); + + if (hw->qbias_en) { + regs->reg_s3.RDO_QUANT.quant_f_bias_I = hw->qbias_i; + regs->reg_s3.RDO_QUANT.quant_f_bias_P = hw->qbias_p; + } else { + regs->reg_s3.RDO_QUANT.quant_f_bias_I = 683; + regs->reg_s3.RDO_QUANT.quant_f_bias_P = 341; + } + regs->reg_s3.iprd_tthdy4_0.iprd_tthdy4_0 = 1; + regs->reg_s3.iprd_tthdy4_0.iprd_tthdy4_1 = 3; + regs->reg_s3.iprd_tthdy4_1.iprd_tthdy4_2 = 6; + regs->reg_s3.iprd_tthdy4_1.iprd_tthdy4_3 = 8; + regs->reg_s3.iprd_tthdc8_0.iprd_tthdc8_0 = 1; + regs->reg_s3.iprd_tthdc8_0.iprd_tthdc8_1 = 3; + regs->reg_s3.iprd_tthdc8_1.iprd_tthdc8_2 = 6; + regs->reg_s3.iprd_tthdc8_1.iprd_tthdc8_3 = 8; + regs->reg_s3.iprd_tthdy8_0.iprd_tthdy8_0 = 1; + regs->reg_s3.iprd_tthdy8_0.iprd_tthdy8_1 = 3; + regs->reg_s3.iprd_tthdy8_1.iprd_tthdy8_2 = 6; + regs->reg_s3.iprd_tthdy8_1.iprd_tthdy8_3 = 8; + regs->reg_s3.iprd_tthd_ul.iprd_tthd_ul = 4; + regs->reg_s3.iprd_wgty8.iprd_wgty8_0 = 22; + regs->reg_s3.iprd_wgty8.iprd_wgty8_1 = 23; + regs->reg_s3.iprd_wgty8.iprd_wgty8_2 = 20; + regs->reg_s3.iprd_wgty8.iprd_wgty8_3 = 22; + regs->reg_s3.iprd_wgty4.iprd_wgty4_0 = 22; + regs->reg_s3.iprd_wgty4.iprd_wgty4_1 = 26; + regs->reg_s3.iprd_wgty4.iprd_wgty4_2 = 20; + regs->reg_s3.iprd_wgty4.iprd_wgty4_3 = 22; + regs->reg_s3.iprd_wgty16.iprd_wgty16_0 = 22; + regs->reg_s3.iprd_wgty16.iprd_wgty16_1 = 26; + regs->reg_s3.iprd_wgty16.iprd_wgty16_2 = 20; + regs->reg_s3.iprd_wgty16.iprd_wgty16_3 = 22; + regs->reg_s3.iprd_wgtc8.iprd_wgtc8_0 = 18; + regs->reg_s3.iprd_wgtc8.iprd_wgtc8_1 = 21; + regs->reg_s3.iprd_wgtc8.iprd_wgtc8_2 = 20; + regs->reg_s3.iprd_wgtc8.iprd_wgtc8_3 = 19; + + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_s3.ATR_THD0.atr_thd0 = 1; + regs->reg_s3.ATR_THD0.atr_thd1 = 2; + regs->reg_s3.ATR_THD1.atr_thd2 = 6; + } else { + regs->reg_s3.ATR_THD0.atr_thd0 = 2; + regs->reg_s3.ATR_THD0.atr_thd1 = 4; + regs->reg_s3.ATR_THD1.atr_thd2 = 9; + } + regs->reg_s3.ATR_THD1.atr_thdqp = 32; + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt0 = 16; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt1 = 16; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt2 = 16; + + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt0 = 22; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt1 = 21; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt2 = 20; + + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt0 = 20; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt1 = 18; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt2 = 16; + } else { + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt0 = 25; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt1 = 20; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt2 = 16; + + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt0 = 25; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt1 = 20; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt2 = 18; + + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt0 = 25; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt1 = 20; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt2 = 16; + } + /* CIME */ + { + /* 0x1760 */ + regs->reg_s3.cime_sqi_cfg.cime_pmv_num = 1; + regs->reg_s3.cime_sqi_cfg.cime_fuse = 1; + regs->reg_s3.cime_sqi_cfg.itp_mode = 0; + regs->reg_s3.cime_sqi_cfg.move_lambda = 0; + regs->reg_s3.cime_sqi_cfg.rime_lvl_mrg = 0; + regs->reg_s3.cime_sqi_cfg.rime_prelvl_en = 0; + regs->reg_s3.cime_sqi_cfg.rime_prersu_en = 0; + + /* 0x1764 */ + regs->reg_s3.cime_mvd_th.cime_mvd_th0 = 16; + regs->reg_s3.cime_mvd_th.cime_mvd_th1 = 48; + regs->reg_s3.cime_mvd_th.cime_mvd_th2 = 80; + + /* 0x1768 */ + regs->reg_s3.cime_madp_th.cime_madp_th = 16; + + /* 0x176c */ + regs->reg_s3.cime_multi.cime_multi0 = 8; + regs->reg_s3.cime_multi.cime_multi1 = 12; + regs->reg_s3.cime_multi.cime_multi2 = 16; + regs->reg_s3.cime_multi.cime_multi3 = 20; + } + + /* RIME && FME */ + { + /* 0x1770 */ + regs->reg_s3.rime_mvd_th.rime_mvd_th0 = 1; + regs->reg_s3.rime_mvd_th.rime_mvd_th1 = 2; + regs->reg_s3.rime_mvd_th.fme_madp_th = 0; + + /* 0x1774 */ + regs->reg_s3.rime_madp_th.rime_madp_th0 = 8; + regs->reg_s3.rime_madp_th.rime_madp_th1 = 16; + + /* 0x1778 */ + regs->reg_s3.rime_multi.rime_multi0 = 4; + regs->reg_s3.rime_multi.rime_multi1 = 8; + regs->reg_s3.rime_multi.rime_multi2 = 12; + + /* 0x177C */ + regs->reg_s3.cmv_st_th.cmv_th0 = 64; + regs->reg_s3.cmv_st_th.cmv_th1 = 96; + regs->reg_s3.cmv_st_th.cmv_th2 = 128; + } + /* madi and madp */ + { + /* 0x1064 */ + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + /* 0x1068 */ + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + /* 0x106C */ + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; + } + + if (slice->slice_type == H264_I_SLICE) { + for (i = 0; i < MPP_ARRAY_ELEMS(h264_aq_tthd_default); i++) { + regs->reg_rc_roi.aq_tthd[i] = hw->aq_thrd_i[i]; + regs->reg_rc_roi.aq_step[i] = hw->aq_step_i[i] & 0x3f; + } + } else { + for (i = 0; i < MPP_ARRAY_ELEMS(h264_P_aq_step_default); i++) { + regs->reg_rc_roi.aq_tthd[i] = hw->aq_thrd_p[i]; + regs->reg_rc_roi.aq_step[i] = hw->aq_step_p[i] & 0x3f; + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540c_ext_line_buf(HalVepu540cRegSet *regs, HalH264eVepu540cCtx *ctx) +{ + if (ctx->ext_line_buf) { + RK_S32 fd = mpp_buffer_get_fd(ctx->ext_line_buf); + + regs->reg_base.ebuft_addr = fd; + regs->reg_base.ebufb_addr = fd; + + mpp_dev_set_reg_offset(ctx->dev, 178, ctx->ext_line_buf_size); + } else { + regs->reg_base.ebuft_addr = 0; + regs->reg_base.ebufb_addr = 0; + } +} + +static MPP_RET hal_h264e_vepu540c_gen_regs(void *hal, HalEncTask *task) +{ + HalH264eVepu540cCtx *ctx = (HalH264eVepu540cCtx *)hal; + HalVepu540cRegSet *regs = ctx->regs_set; + MppEncCfgSet *cfg = ctx->cfg; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + MPP_RET ret = MPP_OK; + + hal_h264e_dbg_func("enter %p\n", hal); + hal_h264e_dbg_detail("frame %d generate regs now", ctx->frms->seq_idx); + + /* register setup */ + memset(regs, 0, sizeof(*regs)); + + setup_vepu540c_normal(regs); + ret = setup_vepu540c_prep(regs, &ctx->cfg->prep); + if (ret) + return ret; + + setup_vepu540c_codec(regs, sps, pps, slice); + setup_vepu540c_rdo_pred(regs, sps, pps, slice); + setup_vepu540c_rdo_cfg(®s->reg_rdo); + + // scl cfg + memcpy(®s->reg_scl.q_intra_y8, vepu580_540_h264_flat_scl_tab, sizeof(vepu580_540_h264_flat_scl_tab)); + + setup_vepu540c_rc_base(regs, ctx, task->rc_task); + setup_vepu540c_io_buf(regs, ctx->dev, task); + setup_vepu540c_recn_refr(ctx, regs); + + regs->reg_base.meiw_addr = task->md_info ? mpp_buffer_get_fd(task->md_info) : 0; + + regs->reg_base.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg_base.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + setup_vepu540c_split(regs, cfg); + setup_vepu540c_me(regs, sps, slice); + + setup_vepu540c_l2(ctx->regs_set, slice, &cfg->hw); + setup_vepu540c_ext_line_buf(regs, ctx); + + if (ctx->roi_data) + vepu540c_set_roi(&ctx->regs_set->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu540c_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu540cCtx *ctx = (HalH264eVepu540cCtx *)hal; + + (void) task; + + hal_h264e_dbg_func("enter %p\n", hal); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = &ctx->regs_set->reg_ctl; + wr_cfg.size = sizeof(ctx->regs_set->reg_ctl); + wr_cfg.offset = VEPU540C_CTL_OFFSET; +#if DUMP_REG + { + RK_U32 i; + RK_U32 *reg = (RK_U32)wr_cfg.reg; + for ( i = 0; i < sizeof(ctx->regs_set->reg_ctl) / sizeof(RK_U32); i++) { + /* code */ + mpp_log("reg[%d] = 0x%08x\n", i, reg[i]); + } + + } +#endif + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = &ctx->regs_set->reg_base; + wr_cfg.size = sizeof(ctx->regs_set->reg_base); + wr_cfg.offset = VEPU540C_BASE_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = &ctx->regs_set->reg_rc_roi; + wr_cfg.size = sizeof(ctx->regs_set->reg_rc_roi); + wr_cfg.offset = VEPU540C_RCROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = &ctx->regs_set->reg_s3; + wr_cfg.size = sizeof(ctx->regs_set->reg_s3); + wr_cfg.offset = VEPU540C_WEG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = &ctx->regs_set->reg_rdo; + wr_cfg.size = sizeof(ctx->regs_set->reg_rdo); + wr_cfg.offset = VEPU540C_RDOCFG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = &ctx->regs_set->reg_scl; + wr_cfg.size = sizeof(ctx->regs_set->reg_scl); + wr_cfg.offset = VEPU540C_SCLCFG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &ctx->regs_set->reg_st; + rd_cfg.size = sizeof(ctx->regs_set->reg_st); + rd_cfg.offset = VEPU540C_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + /* send request to hardware */ + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu540c_status_check(void *hal) +{ + HalH264eVepu540cCtx *ctx = (HalH264eVepu540cCtx *)hal; + HalVepu540cRegSet *regs_set = ctx->regs_set; + + if (regs_set->reg_ctl.int_sta.lkt_node_done_sta) + hal_h264e_dbg_detail("lkt_done finish"); + + if (regs_set->reg_ctl.int_sta.enc_done_sta) + hal_h264e_dbg_detail("enc_done finish"); + + if (regs_set->reg_ctl.int_sta.vslc_done_sta) + hal_h264e_dbg_detail("enc_slice finsh"); + + if (regs_set->reg_ctl.int_sta.sclr_done_sta) + hal_h264e_dbg_detail("safe clear finsh"); + + if (regs_set->reg_ctl.int_sta.vbsf_oflw_sta) + mpp_err_f("bit stream overflow"); + + if (regs_set->reg_ctl.int_sta.vbuf_lens_sta) + mpp_err_f("bus write full"); + + if (regs_set->reg_ctl.int_sta.enc_err_sta) + mpp_err_f("bus error"); + + if (regs_set->reg_ctl.int_sta.wdg_sta) + mpp_err_f("wdg timeout"); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu540c_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu540cCtx *ctx = (HalH264eVepu540cCtx *)hal; + HalVepu540cRegSet *regs_set = ctx->regs_set; + H264NaluType type = (task->rc_task->frm.is_idr != 0) ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + + hal_h264e_dbg_func("enter %p\n", hal); + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + hal_h264e_vepu540c_status_check(hal); + task->hw_length += regs_set->reg_st.bs_lgth_l32; + } + + mpp_packet_add_segment_info(pkt, type, offset, regs_set->reg_st.bs_lgth_l32); + + { + HalH264eVepuStreamAmend *amend = &ctx->amend; + + if (amend->enable) { + amend->old_length = task->hw_length; + amend->slice->is_multi_slice = (ctx->cfg->split.split_mode > 0); + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + task->hw_length = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = task->hw_length; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu540c_ret_task(void *hal, HalEncTask *task) +{ + HalH264eVepu540cCtx *ctx = (HalH264eVepu540cCtx *)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + HalVepu540cRegSet *regs_set = (HalVepu540cRegSet *)ctx->regs_set; + hal_h264e_dbg_func("enter %p\n", hal); + + // update total hardware length + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = regs_set->reg_st.qp_sum / mbs; + /* + rc_info->madi = (!regs_set->reg_st.st_bnum_b16.num_b16) ? 0 : + regs_set->reg_st.madi / regs_set->reg_st.st_bnum_b16.num_b16; + rc_info->madp = (!regs_set->reg_st.st_bnum_cme.num_ctu) ? 0 : + regs_set->reg_st.madi / regs_set->reg_st.st_bnum_cme.num_ctu;*/ + + rc_info->iblk4_prop = (regs_set->reg_st.st_pnum_i4.pnum_i4 + + regs_set->reg_st.st_pnum_i8.pnum_i8 + + regs_set->reg_st.st_pnum_i16.pnum_i16) * 256 / mbs; + + rc_info->sse = ((RK_S64)regs_set->reg_st.sse_h32 << 16) + + (regs_set->reg_st.st_sse_bsl.sse_l16 & 0xffff); + rc_info->lvl16_inter_num = regs_set->reg_st.st_pnum_p16.pnum_p16; + rc_info->lvl8_inter_num = regs_set->reg_st.st_pnum_p8.pnum_p8; + rc_info->lvl16_intra_num = regs_set->reg_st.st_pnum_i16.pnum_i16; + rc_info->lvl8_intra_num = regs_set->reg_st.st_pnum_i8.pnum_i8; + rc_info->lvl4_intra_num = regs_set->reg_st.st_pnum_i4.pnum_i4; + + ctx->hal_rc_cfg.bit_real = rc_info->bit_real; + ctx->hal_rc_cfg.quality_real = rc_info->quality_real; + ctx->hal_rc_cfg.iblk4_prop = rc_info->iblk4_prop; + + task->hal_ret.data = &ctx->hal_rc_cfg; + task->hal_ret.number = 1; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu540c = { + .name = "hal_h264e_vepu540c", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu540cCtx), + .flag = 0, + .init = hal_h264e_vepu540c_init, + .deinit = hal_h264e_vepu540c_deinit, + .prepare = hal_h264e_vepu540c_prepare, + .get_task = hal_h264e_vepu540c_get_task, + .gen_regs = hal_h264e_vepu540c_gen_regs, + .start = hal_h264e_vepu540c_start, + .wait = hal_h264e_vepu540c_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu540c_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3562, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu540c) diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu540c.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu540c.h new file mode 100644 index 000000000..afe73e7c3 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu540c.h @@ -0,0 +1,24 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU540C_H +#define HAL_H264E_VEPU540C_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h264e_vepu540c; + +#endif /* HAL_H264E_VEPU540C_H */ diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu540c_reg.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu540c_reg.h new file mode 100644 index 000000000..3371a5195 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu540c_reg.h @@ -0,0 +1,1073 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU540C_REG_H +#define HAL_H264E_VEPU540C_REG_H + +#include "rk_type.h" +#include "vepu540c_common.h" + +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct Vepu540cControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 reserved : 2; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } version; + + /* 0x4 - 0xc */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 2; + RK_U32 reserved : 22; + } enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } enc_clr; + + /* 0x00000018 reg6 */ + struct { + RK_U32 vswm_lcnt_soft : 14; + RK_U32 vswm_fcnt_soft : 8; + RK_U32 reserved : 2; + RK_U32 dvbm_ack_soft : 1; + RK_U32 dvbm_ack_sel : 1; + RK_U32 dvbm_inf_sel : 1; + RK_U32 reserved1 : 5; + } vs_ldly; + + /* 0x1c */ + RK_U32 reserved_7; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 vslc_done_en : 1; + RK_U32 vbsf_oflw_en : 1; + RK_U32 vbuf_lens_en : 1; + RK_U32 enc_err_en : 1; + RK_U32 dvbm_fcfg_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 lkt_err_stop_en : 1; + RK_U32 lkt_force_stop_en : 1; + RK_U32 jslc_done_en : 1; + RK_U32 jbsf_oflw_en : 1; + RK_U32 jbuf_lens_en : 1; + RK_U32 dvbm_dcnt_en : 1; + RK_U32 reserved : 16; + } int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 vslc_done_msk : 1; + RK_U32 vbsf_oflw_msk : 1; + RK_U32 vbuf_lens_msk : 1; + RK_U32 enc_err_msk : 1; + RK_U32 dvbm_fcfg_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_int_msk : 1; + RK_U32 lkt_err_stop_msk : 1; + RK_U32 lkt_force_stop_msk : 1; + RK_U32 jslc_done_msk : 1; + RK_U32 jbsf_oflw_msk : 1; + RK_U32 jbuf_lens_msk : 1; + RK_U32 dvbm_dcnt_msk : 1; + RK_U32 reserved : 16; + } int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 vslc_done_clr : 1; + RK_U32 vbsf_oflw_clr : 1; + RK_U32 vbuf_lens_clr : 1; + RK_U32 enc_err_clr : 1; + RK_U32 dvbm_fcfg_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_int_clr : 1; + RK_U32 lkt_err_stop_clr : 1; + RK_U32 lkt_force_stop_clr : 1; + RK_U32 jslc_done_clr : 1; + RK_U32 jbsf_oflw_clr : 1; + RK_U32 jbuf_lens_clr : 1; + RK_U32 dvbm_dcnt_clr : 1; + RK_U32 reserved : 16; + } int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 vslc_done_sta : 1; + + RK_U32 vbsf_oflw_sta : 1; + RK_U32 vbuf_lens_sta : 1; + RK_U32 enc_err_sta : 1; + RK_U32 dvbm_fcfg_sta : 1; + + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_int_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + + RK_U32 jslc_done_sta : 1; + RK_U32 jbsf_oflw_sta : 1; + RK_U32 jbuf_lens_sta : 1; + RK_U32 dvbm_dcnt_sta : 1; + + RK_U32 reserved : 16; + } int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 jpeg_bus_edin : 4; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 4; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 rec_nfbc_bus_edin : 4; + } dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 reserved : 16; + RK_U32 axi_brsp_cke : 10; + RK_U32 reserved1 : 6; + } dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 rfp_load_thd : 8; + } enc_wdg; + + /* 0x0000003c reg15 */ + struct { + RK_U32 hurry_en : 1; + RK_U32 hurry_low : 3; + RK_U32 hurry_mid : 3; + RK_U32 hurry_high : 3; + RK_U32 reserved : 22; + } qos_cfg; + + /* 0x00000040 reg16 */ + struct { + RK_U32 qos_period : 16; + RK_U32 reserved : 16; + } qos_perd; + + /* 0x00000044 reg17 */ + RK_U32 hurry_thd_low; + + /* 0x00000048 reg18 */ + RK_U32 hurry_thd_mid; + + /* 0x0000004c reg19 */ + RK_U32 hurry_thd_high; + + /* 0x00000050 reg20 */ + struct { + RK_U32 idle_en_core : 1; + RK_U32 idle_en_axi : 1; + RK_U32 idle_en_ahb : 1; + RK_U32 reserved : 29; + } enc_idle_en; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 enc_done_tmvp_en : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 link_err_stop : 1; + RK_U32 reserved : 27; + } func_en; + + /* 0x00000058 reg22 */ + struct { + RK_U32 tq8_ckg : 1; + RK_U32 tq4_ckg : 1; + RK_U32 bits_ckg_8x8 : 1; + RK_U32 bits_ckg_4x4_1 : 1; + RK_U32 bits_ckg_4x4_0 : 1; + RK_U32 inter_mode_ckg : 1; + RK_U32 inter_ctrl_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 reserved : 22; + } rdo_ckg; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } enc_id; + /* 0x00000060 reg24 */ + struct { + RK_U32 dvbm_en : 1; + RK_U32 src_badr_sel : 1; + RK_U32 vinf_frm_match : 1; + RK_U32 reserved : 1; + RK_U32 vrsp_half_cycle : 4; + RK_U32 reserved1 : 24; + } dvbm_cfg; +} Vepu540cControlCfg; + +/* class: buffer/video syntax */ +/* 0x00000280 reg160 - 0x000003f4 reg253*/ +typedef struct Vepu540cBaseCfg_t { + vepu540c_online online_addr; + /* 0x00000280 reg160 */ + RK_U32 adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 cmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 cmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 adr_bsbs; + + /* 0x000002bc reg175 */ + RK_U32 bsbr_addr; + + /* 0x000002c0 reg176 */ + RK_U32 lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 ebuft_addr ; + + /* 0x000002cc reg179 */ + RK_U32 ebufb_addr; + + /* 0x000002d0 reg180 */ + RK_U32 rfpt_h_addr; + + /* 0x000002d4 reg180 */ + RK_U32 rfpb_h_addr; + + /* 0x000002d8 reg182 */ + RK_U32 rfpt_b_addr; + + /* 0x000002dc reg183 */ + RK_U32 adr_rfpb_b; + + /* 0x000002e0 reg184 */ + RK_U32 adr_smear_rd; + + /* 0x000002e4 reg185 */ + RK_U32 adr_smear_wr; + + /* 0x000002e8 reg186 */ + RK_U32 adr_roir ; + + /* 0x2ec - 0x2fc */ + RK_U32 reserved187_191[5]; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + + RK_U32 bs_scp : 1; + RK_U32 reserved : 3; + + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur : 5; + RK_U32 log2_ctu_num : 5; + RK_U32 reserved1 : 6; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } enc_pic; + + /* 0x304 */ + RK_U32 reserved_193; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 reserved : 8; + RK_U32 ch_id : 2; + RK_U32 vrsp_rtn_en : 1; + RK_U32 reserved1 : 13; + } dvbm_id; + + /* 0x0000030c reg195 */ + RK_U32 bsp_size; + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_rcne : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved : 21; + } src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 reserved : 26; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 reserved1 : 3; + } src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 17; + RK_U32 reserved : 15; + } src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } src_strd1; + + /* 0x0000033c reg207 */ + struct { + RK_U32 pp_corner_filter_strength : 2; + RK_U32 reserved : 2; + RK_U32 pp_edge_filter_strength : 2; + RK_U32 reserved1 : 2; + RK_U32 pp_internal_filter_strength : 2; + RK_U32 reserved2 : 22; + } src_flt_cfg; + + /* 0x340 - 0x34c */ + RK_U32 reserved208_211[4]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 aq_mode : 1; + RK_U32 reserved : 9; + RK_U32 rc_ctu_num : 20; + } rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } rc_tgt; + + /* 0x35c */ + RK_U32 reserved_215; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } sli_cnum; + + /* 0x36c */ + /* 0x0000036c reg219 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } uvc_cfg; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cime_srch_dwnh : 4; + RK_U32 cime_srch_uph : 4; + RK_U32 cime_srch_rgtw : 4; + RK_U32 cime_srch_lftw : 4; + RK_U32 dlt_frm_num : 16; + } me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 srgn_max_num : 7; + RK_U32 cime_dist_thre : 13; + RK_U32 rme_srch_h : 2; + RK_U32 rme_srch_v : 2; + RK_U32 rme_dis : 3; + RK_U32 reserved1 : 1; + RK_U32 fme_dis : 3; + RK_U32 reserved2 : 1; + } me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cime_size_rama : 10; + RK_U32 reserved : 1; + RK_U32 cime_hgt_rama : 5; + RK_U32 reserved1 : 2; + RK_U32 cme_linebuf_w : 10; + RK_U32 fme_prefsu_en : 2; + RK_U32 colmv_stor_hevc : 1; + RK_U32 colmv_load_hevc : 1; + } me_cach; + + /* 0x37c - 0x39c */ + RK_U32 reserved223_231[9]; + /* 0x000003a0 reg232 */ + struct { + RK_U32 rect_size : 1; + RK_U32 reserved : 2; + RK_U32 vlc_lmt : 1; + RK_U32 chrm_spcl : 1; + RK_U32 reserved1 : 8; + RK_U32 ccwa_e : 1; + RK_U32 reserved2 : 1; + RK_U32 intra_cost_e : 1; + RK_U32 reserved3 : 4; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved4 : 6; + RK_U32 atf_e : 1; + RK_U32 atr_e : 1; + RK_U32 reserved5 : 2; + } rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 rdo_mark_mode : 9; + RK_U32 reserved : 23; + } iprd_csts; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_ref_idc : 2; + RK_U32 nal_unit_type : 5; + RK_U32 reserved : 25; + } synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 max_fnum : 4; + RK_U32 drct_8x8 : 1; + RK_U32 mpoc_lm4 : 4; + RK_U32 reserved : 23; + } synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 etpy_mode : 1; + RK_U32 trns_8x8 : 1; + RK_U32 csip_flag : 1; + RK_U32 num_ref0_idx : 2; + RK_U32 num_ref1_idx : 2; + RK_U32 pic_init_qp : 6; + RK_U32 cb_ofst : 5; + RK_U32 cr_ofst : 5; + RK_U32 reserved : 1; + RK_U32 dbf_cp_flg : 1; + RK_U32 reserved1 : 7; + } synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 sli_type : 2; + RK_U32 pps_id : 8; + RK_U32 drct_smvp : 1; + RK_U32 num_ref_ovrd : 1; + RK_U32 cbc_init_idc : 2; + RK_U32 reserved : 2; + RK_U32 frm_num : 16; + } synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 idr_pid : 16; + RK_U32 poc_lsb : 16; + } synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 rodr_pic_idx : 2; + RK_U32 ref_list0_rodr : 1; + RK_U32 sli_beta_ofst : 4; + RK_U32 sli_alph_ofst : 4; + RK_U32 dis_dblk_idc : 2; + RK_U32 reserved : 3; + RK_U32 rodr_pic_num : 16; + } synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 nopp_flg : 1; + RK_U32 ltrf_flg : 1; + RK_U32 arpm_flg : 1; + RK_U32 mmco4_pre : 1; + RK_U32 mmco_type0 : 3; + RK_U32 mmco_parm0 : 16; + RK_U32 mmco_type1 : 3; + RK_U32 mmco_type2 : 3; + RK_U32 reserved : 3; + } synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 mmco_parm1 : 16; + RK_U32 mmco_parm2 : 16; + } synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 long_term_frame_idx0 : 4; + RK_U32 long_term_frame_idx1 : 4; + RK_U32 long_term_frame_idx2 : 4; + RK_U32 reserved : 20; + } synt_refm2; + + /* 0x3d4 - 0x3ec */ + RK_U32 reserved248_251[7]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 mv_v_lmt_thd : 14; + RK_U32 reserved : 1; + RK_U32 mv_v_lmt_en : 1; + RK_U32 reserved1 : 16; + } sli_cfg; + + /* 0x3f4 - 0x3fc */ + RK_U32 reserved253_255[3]; + + /* 0x00000400 reg256 - 0x00000480 reg288 */ + Vepu540cJpegReg jpegReg; + +} Vepu540cBaseCfg; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x000010e0 reg1080 */ +typedef struct Vepu540cRcROiCfg_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 24; + RK_U32 qpmap_mode : 2; + } roi_qthd3; + + /* 0x1040 */ + RK_U32 reserved_1040; + + /* 0x00001044 reg1041 - 0x00001050 reg1044 */ + RK_U8 aq_tthd[16]; + + /* + * 0x00001054 reg1045 - 0x00001060 reg1048 + * only low 6 bits is valid for per step. + */ + RK_U8 aq_step[16]; + + /* 0x00001064 reg1049 */ + struct { + RK_U32 madi_th0 : 8; + RK_U32 madi_th1 : 8; + RK_U32 madi_th2 : 8; + RK_U32 reserved : 8; + } madi_st_thd; + + /* 0x00001068 reg1050 */ + struct { + RK_U32 madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_th1 : 12; + RK_U32 reserved1 : 4; + } madp_st_thd0; + + /* 0x0000106c reg1051 */ + struct { + RK_U32 madp_th2 : 12; + RK_U32 reserved : 20; + } madp_st_thd1; + + /* 0x1070 - 0x1078 */ + RK_U32 reserved1052_1054[3]; + + /* 0x0000107c reg1055 */ + struct { + RK_U32 chrm_klut_ofst : 4; + RK_U32 reserved : 4; + RK_U32 inter_chrm_dist_multi_hevc : 6; + RK_U32 reserved1 : 18; + } klut_ofst; + /*0x00001080 reg1056 - 0x0000110c reg1091 */ + Vepu540cRoiCfg roi_cfg; +} Vepu540cRcRoiCfg; + +/* class: iprd/iprd_wgt/rdo_wgta/prei_dif/sobel */ +/* 0x00001700 reg1472 - 0x00001cd4 reg1845 */ +typedef struct Vepu540cSection3_t { + /* 0x1700 */ + /* 0x00001700 reg1472 */ + struct { + RK_U32 iprd_tthdy4_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_0; + + /* 0x00001704 reg1473 */ + struct { + RK_U32 iprd_tthdy4_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy4_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy4_1; + + /* 0x00001708 reg1474 */ + struct { + RK_U32 iprd_tthdc8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_0; + + /* 0x0000170c reg1475 */ + struct { + RK_U32 iprd_tthdc8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdc8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdc8_1; + + /* 0x00001710 reg1476 */ + struct { + RK_U32 iprd_tthdy8_0 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_1 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_0; + + /* 0x00001714 reg1477 */ + struct { + RK_U32 iprd_tthdy8_2 : 12; + RK_U32 reserved : 4; + RK_U32 iprd_tthdy8_3 : 12; + RK_U32 reserved1 : 4; + } iprd_tthdy8_1; + + /* 0x00001718 reg1478 */ + struct { + RK_U32 iprd_tthd_ul : 12; + RK_U32 reserved : 20; + } iprd_tthd_ul; + + /* 0x0000171c reg1479 */ + struct { + RK_U32 iprd_wgty8_0 : 8; + RK_U32 iprd_wgty8_1 : 8; + RK_U32 iprd_wgty8_2 : 8; + RK_U32 iprd_wgty8_3 : 8; + } iprd_wgty8; + + /* 0x00001720 reg1480 */ + struct { + RK_U32 iprd_wgty4_0 : 8; + RK_U32 iprd_wgty4_1 : 8; + RK_U32 iprd_wgty4_2 : 8; + RK_U32 iprd_wgty4_3 : 8; + } iprd_wgty4; + + /* 0x00001724 reg1481 */ + struct { + RK_U32 iprd_wgty16_0 : 8; + RK_U32 iprd_wgty16_1 : 8; + RK_U32 iprd_wgty16_2 : 8; + RK_U32 iprd_wgty16_3 : 8; + } iprd_wgty16; + + /* 0x00001728 reg1482 */ + struct { + RK_U32 iprd_wgtc8_0 : 8; + RK_U32 iprd_wgtc8_1 : 8; + RK_U32 iprd_wgtc8_2 : 8; + RK_U32 iprd_wgtc8_3 : 8; + } iprd_wgtc8; + + /* 0x172c */ + RK_U32 reserved_1483; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 quant_f_bias_I : 10; + RK_U32 quant_f_bias_P : 10; + RK_U32 reserve : 12; + } RDO_QUANT; + + /* 0x1734 - 0x173c */ + RK_U32 reserved1485_1487[3]; + + /* 0x00001740 reg1488 */ + // atr + struct { + RK_U32 atr_thd0 : 12; + RK_U32 reserve0 : 4; + RK_U32 atr_thd1 : 12; + RK_U32 reserve1 : 4; + } ATR_THD0; // only 264 + + /* 0x1744 */ + struct { + RK_U32 atr_thd2 : 12; + RK_U32 reserve0 : 4; + RK_U32 atr_thdqp : 6; + RK_U32 reserve1 : 10; + } ATR_THD1; // only 264 + + /* 0x1748 */ + struct { + RK_U32 atr1_thd0 : 12; + RK_U32 reserve0 : 4; + RK_U32 atr1_thd1 : 12; + RK_U32 reserve1 : 4; + } ATR_THD10; // only 264 + + /* 0x174c */ + struct { + RK_U32 atr1_thd2 : 12; + RK_U32 reserve1 : 20; + } ATR_THD11; // only 264 + + /* 0x00001750 reg1492 */ + struct { + RK_U32 lvl16_atr_wgt0 : 8; + RK_U32 lvl16_atr_wgt1 : 8; + RK_U32 lvl16_atr_wgt2 : 8; + RK_U32 reserved : 8; + } Lvl16_ATR_WGT; // only 264 + + /* 0x1754 */ + struct { + RK_U32 lvl8_atr_wgt0 : 8; + RK_U32 lvl8_atr_wgt1 : 8; + RK_U32 lvl8_atr_wgt2 : 8; + RK_U32 reserved : 8; + } Lvl8_ATR_WGT; // only 264 + + /* 0x1758 */ + struct { + RK_U32 lvl4_atr_wgt0 : 8; + RK_U32 lvl4_atr_wgt1 : 8; + RK_U32 lvl4_atr_wgt2 : 8; + RK_U32 reserved : 8; + } Lvl4_ATR_WGT; // only 264 + + /* 0x175c */ + RK_U32 reserved_1495; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 itp_mode : 1; + RK_U32 reserved : 1; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 reserved1 : 17; + } cime_sqi_cfg; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 reserved : 20; + } cime_madp_th; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 - 0x18fc */ + RK_U32 reserved1537_1599[64]; + + /* wgt_qp48_grpa */ + /* 0x00001900 reg1600 - 0x19cc */ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} Vepu540cSection3; + +/* class: mmu */ +/* 0x0000f000 reg15360 - 0x0000f064 reg15385 */ + +typedef struct HalVepu540cReg_t { + Vepu540cControlCfg reg_ctl; + Vepu540cBaseCfg reg_base; + Vepu540cRcRoiCfg reg_rc_roi; + Vepu540cSection3 reg_s3; + vepu540c_rdo_cfg reg_rdo; + vepu540c_scl_cfg reg_scl; + vepu540c_jpeg_tab jpeg_table; + vepu540c_status reg_st; +} HalVepu540cRegSet; + +#endif diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu541.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu541.c new file mode 100644 index 000000000..065385a2d --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu541.c @@ -0,0 +1,1872 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264e_vepu541" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_frame.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_frame_impl.h" +#include "mpp_rc.h" +#include "mpp_packet_impl.h" + +#include "hal_h264e_debug.h" +#include "h264e_sps.h" +#include "h264e_pps.h" +#include "h264e_slice.h" + +#include "hal_bufs.h" +#include "hal_h264e_vepu541.h" +#include "hal_h264e_vepu541_reg.h" +#include "hal_h264e_vepu541_reg_l2.h" +#include "hal_h264e_stream_amend.h" +#include "vepu541_common.h" +#include "vepu5xx_common.h" + +typedef struct HalH264eVepu541Ctx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_U32 is_vepu540; + RK_S32 frame_cnt; + + /* buffers management */ + HalBufs hw_recn; + RK_S32 pixel_buf_fbc_hdr_size; + RK_S32 pixel_buf_fbc_bdy_size; + RK_S32 pixel_buf_size; + RK_S32 thumb_buf_size; + RK_S32 max_buf_cnt; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eSlice *slice; + H264eFrmInfo *frms; + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + H264ePrefixNal *prefix; + HalH264eVepuStreamAmend amend; + + /* syntax for output to enc_impl */ + EncRcTaskInfo hal_rc_cfg; + + /* roi */ + MppEncROICfg *roi_data; + MppEncROICfg2 *roi_data2; + MppBufferGroup roi_grp; + MppBuffer roi_buf; + RK_S32 roi_buf_size; + MppBuffer qpmap; + + /* osd */ + Vepu5xxOsdCfg osd_cfg; + + /* register */ + Vepu541H264eRegSet regs_set; + Vepu541H264eRegL2Set regs_l2_set; + Vepu541H264eRegRet regs_ret; +} HalH264eVepu541Ctx; + +#define CHROMA_KLUT_TAB_SIZE (24 * sizeof(RK_U32)) + +static RK_U32 h264e_klut_weight[30] = { + 0x0a000010, 0x00064000, 0x14000020, 0x000c8000, + 0x28000040, 0x00194000, 0x50800080, 0x0032c000, + 0xa1000100, 0x00658000, 0x42800200, 0x00cb0001, + 0x85000400, 0x01964002, 0x0a000800, 0x032c8005, + 0x14001000, 0x0659400a, 0x28802000, 0x0cb2c014, + 0x51004000, 0x1965c028, 0xa2808000, 0x32cbc050, + 0x4500ffff, 0x659780a1, 0x8a81fffe, 0xCC000142, + 0xFF83FFFF, 0x000001FF, +}; + +static RK_U32 dump_l1_reg = 0; +static RK_U32 dump_l2_reg = 0; + +static RK_S32 h264_aq_tthd_default[16] = { + 0, 0, 0, 0, + 3, 3, 5, 5, + 8, 8, 8, 15, + 15, 20, 25, 25, +}; + +static RK_S32 h264_P_aq_step_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 7, 8, +}; + +static RK_S32 h264_I_aq_step_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 3, 3, + 4, 5, 8, 8, +}; + +static MPP_RET hal_h264e_vepu541_deinit(void *hal) +{ + HalH264eVepu541Ctx *p = (HalH264eVepu541Ctx *)hal; + + hal_h264e_dbg_func("enter %p\n", p); + + h264e_vepu_stream_amend_deinit(&p->amend); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + if (p->roi_buf) { + mpp_buffer_put(p->roi_buf); + p->roi_buf = NULL; + } + + if (p->roi_grp) { + mpp_buffer_group_put(p->roi_grp); + p->roi_grp = NULL; + } + + if (p->hw_recn) { + hal_bufs_deinit(p->hw_recn); + p->hw_recn = NULL; + } + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu541_init(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu541Ctx *p = (HalH264eVepu541Ctx *)hal; + MPP_RET ret = MPP_OK; + + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + + { + RockchipSocType soc_type = mpp_get_soc_type(); + + if (soc_type == ROCKCHIP_SOC_RK3566 || soc_type == ROCKCHIP_SOC_RK3568) + p->is_vepu540 = 1; + else + p->is_vepu540 = 0; + } + + ret = hal_bufs_init(&p->hw_recn); + if (ret) { + mpp_err_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + p->osd_cfg.reg_base = &p->regs_set; + p->osd_cfg.dev = p->dev; + p->osd_cfg.reg_cfg = NULL; + p->osd_cfg.plt_cfg = &p->cfg->plt_cfg; + p->osd_cfg.osd_data = NULL; + p->osd_cfg.osd_data2 = NULL; + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 0; + hw->qp_delta_row = 2; + hw->qbias_i = 683; + hw->qbias_p = 341; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, h264_aq_tthd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, h264_aq_tthd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, h264_I_aq_step_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, h264_P_aq_step_default, sizeof(hw->aq_step_p)); + } + +DONE: + if (ret) + hal_h264e_vepu541_deinit(hal); + + h264e_vepu_stream_amend_init(&p->amend); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +static void setup_hal_bufs(HalH264eVepu541Ctx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + RK_S32 alignment = 64; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment); + RK_S32 aligned_h = MPP_ALIGN(prep->height, alignment) + 16; + RK_S32 pixel_buf_fbc_hdr_size = MPP_ALIGN(aligned_w * aligned_h / 64, SZ_8K); + RK_S32 pixel_buf_fbc_bdy_size = aligned_w * aligned_h * 3 / 2; + RK_S32 pixel_buf_size = pixel_buf_fbc_hdr_size + pixel_buf_fbc_bdy_size; + RK_S32 thumb_buf_size = MPP_ALIGN(aligned_w / 64 * aligned_h / 64 * 256, SZ_8K); + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 2; + MppEncRefCfg ref_cfg = cfg->ref_cfg; + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + if (new_max_cnt < MPP_MAX(new_max_cnt, info->dpb_size + 1)) + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if ((ctx->pixel_buf_fbc_hdr_size != pixel_buf_fbc_hdr_size) || + (ctx->pixel_buf_fbc_bdy_size != pixel_buf_fbc_bdy_size) || + (ctx->pixel_buf_size != pixel_buf_size) || + (ctx->thumb_buf_size != thumb_buf_size) || + (new_max_cnt > old_max_cnt)) { + size_t sizes[2]; + + hal_h264e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->pixel_buf_size, pixel_buf_size, + old_max_cnt, new_max_cnt); + + /* pixel buffer */ + sizes[0] = pixel_buf_size; + /* thumb buffer */ + sizes[1] = thumb_buf_size; + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_bufs_setup(ctx->hw_recn, new_max_cnt, 2, sizes); + + ctx->pixel_buf_fbc_hdr_size = pixel_buf_fbc_hdr_size; + ctx->pixel_buf_fbc_bdy_size = pixel_buf_fbc_bdy_size; + ctx->pixel_buf_size = pixel_buf_size; + ctx->thumb_buf_size = thumb_buf_size; + ctx->max_buf_cnt = new_max_cnt; + } +} + +static MPP_RET hal_h264e_vepu541_prepare(void *hal) +{ + HalH264eVepu541Ctx *ctx = (HalH264eVepu541Ctx *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->hw_recn, i); + + prep->change_res = 0; + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_U32 update_vepu541_syntax(HalH264eVepu541Ctx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu541_get_task(void *hal, HalEncTask *task) +{ + HalH264eVepu541Ctx *ctx = (HalH264eVepu541Ctx *)hal; + MppEncH264HwCfg *hw_cfg = &ctx->cfg->h264.hw_cfg; + RK_U32 updated = update_vepu541_syntax(ctx, &task->syntax); + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) + setup_hal_bufs(ctx); + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(task->frame); + + mpp_meta_get_ptr_d(meta, KEY_ROI_DATA, (void **)&ctx->roi_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_ROI_DATA2, (void **)&ctx->roi_data2, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA, (void **)&ctx->osd_cfg.osd_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA2, (void **)&ctx->osd_cfg.osd_data2, NULL); + mpp_meta_get_buffer_d(meta, KEY_QPMAP0, &ctx->qpmap, NULL); + } + + /* if not VEPU1/2, update log2_max_frame_num_minus4 in hw_cfg */ + hw_cfg->hw_log2_max_frame_num_minus4 = ctx->sps->log2_max_frame_num_minus4; + + h264e_vepu_stream_amend_config(&ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static void setup_vepu541_normal(Vepu541H264eRegSet *regs, RK_U32 is_vepu540) +{ + hal_h264e_dbg_func("enter\n"); + /* reg000 VERSION is read only */ + + /* reg001 ENC_STRT */ + regs->reg001.lkt_num = 0; + regs->reg001.rkvenc_cmd = 1; + regs->reg001.clk_gate_en = 1; + regs->reg001.resetn_hw_en = 0; + regs->reg001.enc_done_tmvp_en = 1; + + /* reg002 ENC_CLR */ + regs->reg002.safe_clr = 0; + regs->reg002.force_clr = 0; + + /* reg003 LKT_ADDR */ + regs->reg003.lkt_addr = 0; + + /* reg004 INT_EN */ + regs->reg004.enc_done_en = 1; + regs->reg004.lkt_done_en = 1; + regs->reg004.sclr_done_en = 1; + regs->reg004.enc_slice_done_en = 1; + regs->reg004.oflw_done_en = 1; + regs->reg004.brsp_done_en = 1; + regs->reg004.berr_done_en = 1; + regs->reg004.rerr_done_en = 1; + regs->reg004.wdg_done_en = 0; + + /* reg005 INT_MSK */ + regs->reg005.enc_done_msk = 0; + regs->reg005.lkt_done_msk = 0; + regs->reg005.sclr_done_msk = 0; + regs->reg005.enc_slice_done_msk = 0; + regs->reg005.oflw_done_msk = 0; + regs->reg005.brsp_done_msk = 0; + regs->reg005.berr_done_msk = 0; + regs->reg005.rerr_done_msk = 0; + regs->reg005.wdg_done_msk = 0; + + /* reg006 INT_CLR is not set */ + /* reg007 INT_STA is read only */ + /* reg008 ~ reg0011 gap */ + regs->reg014.vs_load_thd = 0; + regs->reg014.rfp_load_thrd = 0; + + /* reg015 DTRNS_MAP */ + regs->reg015.cmvw_bus_ordr = 0; + regs->reg015.dspw_bus_ordr = 0; + regs->reg015.rfpw_bus_ordr = 0; + regs->reg015.src_bus_edin = 0; + regs->reg015.meiw_bus_edin = 0; + regs->reg015.bsw_bus_edin = 7; + regs->reg015.lktr_bus_edin = 0; + regs->reg015.roir_bus_edin = 0; + regs->reg015.lktw_bus_edin = 0; + regs->reg015.afbc_bsize = 1; + + /* reg016 DTRNS_CFG */ + if (is_vepu540) { + /* vepu540 */ + regs->reg016.vepu540.axi_brsp_cke = 0; + regs->reg016.vepu540.dspr_otsd = 1; + } else { + /* vepu541 */ + regs->reg016.vepu541.axi_brsp_cke = 0; + regs->reg016.vepu541.dspr_otsd = 1; + } + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET setup_vepu541_prep(Vepu541H264eRegSet *regs, HalH264eVepu541Ctx *ctx, + HalEncTask *task) +{ + VepuFmtCfg cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + MppFrameFormat fmt = prep->format; + MPP_RET ret = vepu5xx_set_fmt(&cfg, fmt); + RK_U32 hw_fmt = cfg.format; + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + /* do nothing when color format is not supported */ + if (ret) + return ret; + + /* reg012 ENC_RSL */ + regs->reg012.pic_wd8_m1 = MPP_ALIGN(prep->width, 16) / 8 - 1; + regs->reg012.pic_wfill = MPP_ALIGN(prep->width, 16) - prep->width; + regs->reg012.pic_hd8_m1 = MPP_ALIGN(prep->height, 16) / 8 - 1; + regs->reg012.pic_hfill = MPP_ALIGN(prep->height, 16) - prep->height; + + /* reg015 DTRNS_MAP */ + regs->reg015.src_bus_edin = cfg.src_endian; + + /* reg022 SRC_PROC */ + regs->reg017.src_cfmt = hw_fmt; + regs->reg017.alpha_swap = cfg.alpha_swap; + regs->reg017.rbuv_swap = cfg.rbuv_swap; + regs->reg017.src_range = cfg.src_range; + regs->reg017.out_fmt_cfg = (hw_fmt == VEPU5xx_FMT_YUV400) ? 1 : 0; + + if (!ctx->frame_cnt && (fmt == MPP_FMT_YUV420SP_VU || fmt == MPP_FMT_YUV422SP_VU)) + mpp_logw("Warning: nv21/nv42 fmt not supported, will encode as nv12/nv24.\n"); + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + y_stride = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!y_stride) + y_stride = MPP_ALIGN(prep->hor_stride, 16); + } else + y_stride = (prep->hor_stride != 0) ? (prep->hor_stride) : (prep->width); + + + c_stride = (hw_fmt == VEPU5xx_FMT_YUV422SP || hw_fmt == VEPU5xx_FMT_YUV420SP) ? + y_stride : y_stride / 2; + + if (hw_fmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = get_rgb2yuv_cfg(prep->range, prep->color); + + hal_h264e_dbg_flow("input color range %d colorspace %d", prep->range, prep->color); + + regs->reg018.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + regs->reg018.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + regs->reg018.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + + regs->reg019.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + regs->reg019.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + regs->reg019.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + + regs->reg020.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + regs->reg020.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + regs->reg020.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + + regs->reg021.csc_ofst_y = cfg_coeffs->_2y.offset; + regs->reg021.csc_ofst_u = cfg_coeffs->_2u.offset; + regs->reg021.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h264e_dbg_flow("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } else { + regs->reg018.csc_wgt_b2y = cfg.weight[0]; + regs->reg018.csc_wgt_g2y = cfg.weight[1]; + regs->reg018.csc_wgt_r2y = cfg.weight[2]; + + regs->reg019.csc_wgt_b2u = cfg.weight[3]; + regs->reg019.csc_wgt_g2u = cfg.weight[4]; + regs->reg019.csc_wgt_r2u = cfg.weight[5]; + + regs->reg020.csc_wgt_b2v = cfg.weight[6]; + regs->reg020.csc_wgt_g2v = cfg.weight[7]; + regs->reg020.csc_wgt_r2v = cfg.weight[8]; + + regs->reg021.csc_ofst_y = cfg.offset[0]; + regs->reg021.csc_ofst_u = cfg.offset[1]; + regs->reg021.csc_ofst_v = cfg.offset[2]; + } + + regs->reg022.afbcd_en = (MPP_FRAME_FMT_IS_FBC(fmt) != 0) ? 1 : 0; + regs->reg069.src_strd0 = y_stride; + regs->reg069.src_strd1 = c_stride; + + regs->reg022.src_mirr = prep->mirroring > 0; + regs->reg022.src_rot = prep->rotation; + regs->reg022.txa_en = 1; + + regs->reg023.sli_crs_en = 1; + + regs->reg068.pic_ofst_y = 0; + regs->reg068.pic_ofst_x = 0; + + hal_h264e_dbg_func("leave\n"); + + return ret; +} + +static void setup_vepu541_codec(Vepu541H264eRegSet *regs, H264eSps *sps, + H264ePps *pps, H264eSlice *slice) +{ + hal_h264e_dbg_func("enter\n"); + + regs->reg013.enc_stnd = 0; + regs->reg013.cur_frm_ref = slice->nal_reference_idc > 0; + regs->reg013.bs_scp = 1; + regs->reg013.lamb_mod_sel = (slice->slice_type == H264_I_SLICE) ? 0 : 1; + regs->reg013.atr_thd_sel = 0; + regs->reg013.node_int = 0; + + regs->reg103.nal_ref_idc = slice->nal_reference_idc; + regs->reg103.nal_unit_type = slice->nalu_type; + + regs->reg104.max_fnum = sps->log2_max_frame_num_minus4; + regs->reg104.drct_8x8 = sps->direct8x8_inference; + regs->reg104.mpoc_lm4 = sps->log2_max_poc_lsb_minus4; + + regs->reg105.etpy_mode = pps->entropy_coding_mode; + regs->reg105.trns_8x8 = pps->transform_8x8_mode; + regs->reg105.csip_flag = pps->constrained_intra_pred; + regs->reg105.num_ref0_idx = pps->num_ref_idx_l0_default_active - 1; + regs->reg105.num_ref1_idx = pps->num_ref_idx_l1_default_active - 1; + regs->reg105.pic_init_qp = pps->pic_init_qp; + regs->reg105.cb_ofst = pps->chroma_qp_index_offset; + regs->reg105.cr_ofst = pps->second_chroma_qp_index_offset; + regs->reg105.wght_pred = pps->weighted_pred; + regs->reg105.dbf_cp_flg = pps->deblocking_filter_control; + + regs->reg106.sli_type = (slice->slice_type == H264_I_SLICE) ? (2) : (0); + regs->reg106.pps_id = slice->pic_parameter_set_id; + regs->reg106.drct_smvp = 0; + regs->reg106.num_ref_ovrd = slice->num_ref_idx_override; + regs->reg106.cbc_init_idc = slice->cabac_init_idc; + regs->reg106.frm_num = slice->frame_num; + + regs->reg107.idr_pic_id = (slice->slice_type == H264_I_SLICE) ? slice->idr_pic_id : (RK_U32)(-1); + regs->reg107.poc_lsb = slice->pic_order_cnt_lsb; + + + regs->reg108.dis_dblk_idc = slice->disable_deblocking_filter_idc; + regs->reg108.sli_alph_ofst = slice->slice_alpha_c0_offset_div2; + + h264e_reorder_rd_rewind(slice->reorder); + { /* reorder process */ + H264eRplmo rplmo; + MPP_RET ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + if (MPP_OK == ret) { + regs->reg108.ref_list0_rodr = 1; + regs->reg108.rodr_pic_idx = rplmo.modification_of_pic_nums_idc; + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + regs->reg108.rodr_pic_num = rplmo.abs_diff_pic_num_minus1; + } break; + case 2 : { + regs->reg108.rodr_pic_num = rplmo.long_term_pic_idx; + } break; + default : { + mpp_err_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + } else { + // slice->ref_pic_list_modification_flag; + regs->reg108.ref_list0_rodr = 0; + regs->reg108.rodr_pic_idx = 0; + regs->reg108.rodr_pic_num = 0; + } + } + + /* clear all mmco arg first */ + regs->reg109.nopp_flg = 0; + regs->reg109.ltrf_flg = 0; + regs->reg109.arpm_flg = 0; + regs->reg109.mmco4_pre = 0; + regs->reg109.mmco_type0 = 0; + regs->reg109.mmco_parm0 = 0; + regs->reg109.mmco_type1 = 0; + regs->reg110.mmco_parm1 = 0; + regs->reg109.mmco_type2 = 0; + regs->reg110.mmco_parm2 = 0; + regs->reg114.long_term_frame_idx0 = 0; + regs->reg114.long_term_frame_idx1 = 0; + regs->reg114.long_term_frame_idx2 = 0; + + h264e_marking_rd_rewind(slice->marking); + + /* only update used parameter */ + if (slice->slice_type == H264_I_SLICE) { + regs->reg109.nopp_flg = slice->no_output_of_prior_pics; + regs->reg109.ltrf_flg = slice->long_term_reference_flag; + } else { + if (!h264e_marking_is_empty(slice->marking)) { + H264eMmco mmco; + + regs->reg109.arpm_flg = 1; + + /* max 3 mmco */ + do { + RK_S32 type = 0; + RK_S32 param_0 = 0; + RK_S32 param_1 = 0; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg109.mmco_type0 = type; + regs->reg109.mmco_parm0 = param_0; + regs->reg114.long_term_frame_idx0 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg109.mmco_type1 = type; + regs->reg110.mmco_parm1 = param_0; + regs->reg114.long_term_frame_idx1 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg109.mmco_type2 = type; + regs->reg110.mmco_parm2 = param_0; + regs->reg114.long_term_frame_idx2 = param_1; + } while (0); + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu541_rdo_pred(Vepu541H264eRegSet *regs, H264eSps *sps, + H264ePps *pps, H264eSlice *slice, MppEncCfgSet *cfg) +{ + hal_h264e_dbg_func("enter\n"); + + if (slice->slice_type == H264_I_SLICE) { + regs->reg025.chrm_klut_ofst = 0; + memcpy(®s->reg026, &h264e_klut_weight[0], CHROMA_KLUT_TAB_SIZE); + } else { + regs->reg025.chrm_klut_ofst = 3; + if (cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) + memcpy(®s->reg026, &h264e_klut_weight[3], CHROMA_KLUT_TAB_SIZE); + else + memcpy(®s->reg026, &h264e_klut_weight[0], CHROMA_KLUT_TAB_SIZE); + } + + if (cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + regs->reg101.vthd_y = 9; + regs->reg101.vthd_c = 63; + regs->reg102.inter_4x4 = 0; + regs->reg102.rdo_mask = 24; + regs->reg102.atf_intra_e = 1; + } else { + regs->reg101.vthd_y = 2501; + regs->reg101.vthd_c = 2501; + regs->reg102.inter_4x4 = 1; + regs->reg102.rdo_mask = 0; + regs->reg102.atf_intra_e = 0; + } + + regs->reg102.rect_size = (sps->profile_idc == H264_PROFILE_BASELINE && + sps->level_idc <= H264_LEVEL_3_0) ? 1 : 0; + + regs->reg102.vlc_lmt = (sps->profile_idc < H264_PROFILE_MAIN) && + !pps->entropy_coding_mode; + regs->reg102.chrm_spcl = 1; + regs->reg102.ccwa_e = 1; + regs->reg102.scl_lst_sel = pps->pic_scaling_matrix_present; + regs->reg102.scl_lst_sel_ = pps->pic_scaling_matrix_present; + regs->reg102.atr_e = 1; + regs->reg102.atf_edg = 0; + regs->reg102.atf_lvl_e = 0; + regs->reg102.satd_byps_flg = 0; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu541_rc_base(Vepu541H264eRegSet *regs, H264eSps *sps, + H264eSlice *slice, MppEncHwCfg *hw, + EncRcTask *rc_task) +{ + EncRcTaskInfo *rc_info = &rc_task->info; + RK_S32 mb_w = sps->pic_width_in_mbs; + RK_S32 mb_h = sps->pic_height_in_mbs; + RK_U32 qp_target = rc_info->quality_target; + RK_U32 qp_min = rc_info->quality_min; + RK_U32 qp_max = rc_info->quality_max; + RK_U32 qpmap_mode = 1; + RK_S32 mb_target_bits_mul_16 = (rc_info->bit_target << 4) / (mb_w * mb_h); + RK_S32 mb_target_bits; + RK_S32 negative_bits_thd; + RK_S32 positive_bits_thd; + + hal_h264e_dbg_rc("bittarget %d qp [%d %d %d]\n", rc_info->bit_target, + qp_min, qp_target, qp_max); + + if (mb_target_bits_mul_16 >= 0x100000) { + mb_target_bits_mul_16 = 0x50000; + } + + mb_target_bits = (mb_target_bits_mul_16 * mb_w) >> 4; + negative_bits_thd = 0 - mb_target_bits * 5 / 16; + positive_bits_thd = mb_target_bits * 5 / 16; + + hal_h264e_dbg_func("enter\n"); + + regs->reg013.pic_qp = qp_target; + + regs->reg050.rc_en = 1; + regs->reg050.aq_en = 1; + regs->reg050.aq_mode = 0; + regs->reg050.rc_ctu_num = mb_w; + + regs->reg051.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? + hw->qp_delta_row_i : hw->qp_delta_row; + regs->reg051.rc_max_qp = qp_max; + regs->reg051.rc_min_qp = qp_min; + + regs->reg052.ctu_ebit = mb_target_bits_mul_16; + + regs->reg053.qp_adj0 = -2; + regs->reg053.qp_adj1 = -1; + regs->reg053.qp_adj2 = 0; + regs->reg053.qp_adj3 = 1; + regs->reg053.qp_adj4 = 2; + regs->reg054.qp_adj5 = 0; + regs->reg054.qp_adj6 = 0; + regs->reg054.qp_adj7 = 0; + regs->reg054.qp_adj8 = 0; + + regs->reg055_063.rc_dthd[0] = 2 * negative_bits_thd; + regs->reg055_063.rc_dthd[1] = negative_bits_thd; + regs->reg055_063.rc_dthd[2] = positive_bits_thd; + regs->reg055_063.rc_dthd[3] = 2 * positive_bits_thd; + regs->reg055_063.rc_dthd[4] = 0x7fffffff; + regs->reg055_063.rc_dthd[5] = 0x7fffffff; + regs->reg055_063.rc_dthd[6] = 0x7fffffff; + regs->reg055_063.rc_dthd[7] = 0x7fffffff; + regs->reg055_063.rc_dthd[8] = 0x7fffffff; + + regs->reg064.qpmin_area0 = qp_min; + regs->reg064.qpmax_area0 = qp_max; + regs->reg064.qpmin_area1 = qp_min; + regs->reg064.qpmax_area1 = qp_max; + regs->reg064.qpmin_area2 = qp_min; + + regs->reg065.qpmax_area2 = qp_max; + regs->reg065.qpmin_area3 = qp_min; + regs->reg065.qpmax_area3 = qp_max; + regs->reg065.qpmin_area4 = qp_min; + regs->reg065.qpmax_area4 = qp_max; + + regs->reg066.qpmin_area5 = qp_min; + regs->reg066.qpmax_area5 = qp_max; + regs->reg066.qpmin_area6 = qp_min; + regs->reg066.qpmax_area6 = qp_max; + regs->reg066.qpmin_area7 = qp_min; + + regs->reg067.qpmax_area7 = qp_max; + regs->reg067.qpmap_mode = qpmap_mode; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu541_io_buf(Vepu541H264eRegSet *regs, MppDev dev, + HalEncTask *task) +{ + MppFrame frm = task->frame; + MppPacket pkt = task->packet; + MppBuffer buf_in = mpp_frame_get_buffer(frm); + MppBuffer buf_out = task->output; + MppFrameFormat fmt = mpp_frame_get_fmt(frm); + RK_S32 hor_stride = mpp_frame_get_hor_stride(frm); + RK_S32 ver_stride = mpp_frame_get_ver_stride(frm); + RK_S32 fd_in = mpp_buffer_get_fd(buf_in); + RK_U32 off_in[2] = {0}; + RK_U32 off_out = mpp_packet_get_length(pkt); + size_t siz_out = mpp_buffer_get_size(buf_out); + RK_S32 fd_out = mpp_buffer_get_fd(buf_out); + + hal_h264e_dbg_func("enter\n"); + + regs->reg070.adr_src0 = fd_in; + regs->reg071.adr_src1 = fd_in; + regs->reg072.adr_src2 = fd_in; + + regs->reg084.bsbb_addr = fd_out; + regs->reg085.bsbr_addr = fd_out; + regs->reg086.adr_bsbs = fd_out; + regs->reg083.bsbt_addr = fd_out; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + off_in[0] = mpp_frame_get_fbc_offset(frm);; + off_in[1] = 0; + } else if (MPP_FRAME_FMT_IS_YUV(fmt)) { + VepuFmtCfg cfg; + + vepu5xx_set_fmt(&cfg, fmt); + switch (cfg.format) { + case VEPU5xx_FMT_BGRA8888 : + case VEPU5xx_FMT_BGR888 : + case VEPU5xx_FMT_BGR565 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV422SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV422P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 3 / 2; + } break; + case VEPU5xx_FMT_YUV420P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 5 / 4; + } break; + case VEPU5xx_FMT_YUV400 : + case VEPU5xx_FMT_YUYV422 : + case VEPU5xx_FMT_UYVY422 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + default : { + off_in[0] = 0; + off_in[1] = 0; + } break; + } + } + + mpp_dev_set_reg_offset(dev, 71, off_in[0]); + mpp_dev_set_reg_offset(dev, 72, off_in[1]); + mpp_dev_set_reg_offset(dev, 83, siz_out); + mpp_dev_set_reg_offset(dev, 86, off_out); + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET setup_vepu541_intra_refresh(Vepu541H264eRegSet *regs, HalH264eVepu541Ctx *ctx, RK_U32 refresh_idx) +{ + MPP_RET ret = MPP_OK; + RK_U32 w = ctx->sps->pic_width_in_mbs * 16; + RK_U32 h = ctx->sps->pic_height_in_mbs * 16; + MppEncROIRegion *region = NULL; + RK_U32 refresh_num = ctx->cfg->rc.refresh_num; + RK_U32 stride_h = MPP_ALIGN(w / 16, 4); + RK_U32 stride_v = MPP_ALIGN(h / 16, 4); + RK_U32 i = 0; + RK_S32 roi_buf_size; + + hal_h264e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en) { + ret = MPP_ERR_VALUE; + goto RET; + } + + roi_buf_size = vepu541_get_roi_buf_size(w, h); + if (ctx->roi_buf_size < roi_buf_size) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + if (ctx->roi_buf) + mpp_buffer_put(ctx->roi_buf); + + mpp_buffer_get(ctx->roi_grp, &ctx->roi_buf, roi_buf_size); + ctx->roi_buf_size = roi_buf_size; + } + + mpp_assert(ctx->roi_buf); + RK_S32 fd = mpp_buffer_get_fd(ctx->roi_buf); + void *buf = mpp_buffer_get_ptr(ctx->roi_buf); + Vepu541RoiCfg cfg; + Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf; + cfg.force_intra = 0; + cfg.reserved = 0; + cfg.qp_area_idx = 0; + cfg.qp_area_en = 1; + cfg.qp_adj = 0; + cfg.qp_adj_mode = 0; + + for (i = 0; i < stride_h * stride_v; i++, ptr++) + memcpy(ptr, &cfg, sizeof(cfg)); + + region = mpp_calloc(MppEncROIRegion, 1); + + if (NULL == region) { + mpp_err_f("Failed to calloc for MppEncROIRegion !\n"); + ret = MPP_ERR_MALLOC; + } + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + region->x = 0; + region->w = w; + if (refresh_idx > 0) { + region->y = refresh_idx * 16 * refresh_num - 32; + region->h = 16 * refresh_num + 32; + } else { + region->y = refresh_idx * 16 * refresh_num; + region->h = 16 * refresh_num; + } + regs->reg089.cme_srch_v = 1; + } else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) { + region->y = 0; + region->h = h; + if (refresh_idx > 0) { + region->x = refresh_idx * 16 * refresh_num - 32; + region->w = 16 * refresh_num + 32; + } else { + region->x = refresh_idx * 16 * refresh_num; + region->w = 16 * refresh_num; + } + regs->reg089.cme_srch_h = 1; + } + + region->intra = 1; + region->quality = -ctx->cfg->rc.qp_delta_ip; + + region->area_map_en = 1; + region->qp_area_idx = 1; + region->abs_qp_en = 0; + + regs->reg013.roi_enc = 1; + regs->reg073.roi_addr = fd; + vepu541_set_one_roi(buf, region, w, h); + mpp_free(region); + mpp_buffer_sync_end(ctx->roi_buf); + +RET: + hal_h264e_dbg_func("leave, ret %d\n", ret); + return ret; +} + +static void setup_vepu541_roi(Vepu541H264eRegSet *regs, HalH264eVepu541Ctx *ctx) +{ + + hal_h264e_dbg_func("enter\n"); + + if (ctx->roi_data2) { + MppEncROICfg2 *cfg = ( MppEncROICfg2 *)ctx->roi_data2; + + regs->reg013.roi_enc = 1; + regs->reg073.roi_addr = mpp_buffer_get_fd(cfg->base_cfg_buf); + } else if (ctx->qpmap) { + regs->reg013.roi_enc = 1; + regs->reg073.roi_addr = mpp_buffer_get_fd(ctx->qpmap); + } else { + MppEncROICfg *roi = ctx->roi_data; + RK_U32 w = ctx->sps->pic_width_in_mbs * 16; + RK_U32 h = ctx->sps->pic_height_in_mbs * 16; + + /* roi setup */ + if (roi && roi->number && roi->regions) { + RK_S32 roi_buf_size = vepu541_get_roi_buf_size(w, h); + + if (!ctx->roi_buf || roi_buf_size != ctx->roi_buf_size) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + else if (roi_buf_size != ctx->roi_buf_size) { + if (ctx->roi_buf) { + mpp_buffer_put(ctx->roi_buf); + ctx->roi_buf = NULL; + } + mpp_buffer_group_clear(ctx->roi_grp); + } + + mpp_assert(ctx->roi_grp); + + if (NULL == ctx->roi_buf) + mpp_buffer_get(ctx->roi_grp, &ctx->roi_buf, roi_buf_size); + + ctx->roi_buf_size = roi_buf_size; + } + + mpp_assert(ctx->roi_buf); + RK_S32 fd = mpp_buffer_get_fd(ctx->roi_buf); + void *buf = mpp_buffer_get_ptr(ctx->roi_buf); + + regs->reg013.roi_enc = 1; + regs->reg073.roi_addr = fd; + + vepu541_set_roi(buf, roi, w, h); + mpp_buffer_sync_end(ctx->roi_buf); + } else { + regs->reg013.roi_enc = 0; + regs->reg073.roi_addr = 0; + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu541_recn_refr(Vepu541H264eRegSet *regs, MppDev dev, + H264eFrmInfo *frms, HalBufs bufs, + RK_S32 fbc_hdr_size) +{ + HalBuf *curr = hal_bufs_get_buf(bufs, frms->curr_idx); + HalBuf *refr = hal_bufs_get_buf(bufs, frms->refr_idx); + + hal_h264e_dbg_func("enter\n"); + + if (curr && curr->cnt) { + MppBuffer buf_pixel = curr->buf[0]; + MppBuffer buf_thumb = curr->buf[1]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg074.rfpw_h_addr = fd; + regs->reg075.rfpw_b_addr = fd; + regs->reg080.dspw_addr = mpp_buffer_get_fd(buf_thumb); + + mpp_dev_set_reg_offset(dev, 75, fbc_hdr_size); + } + + if (refr && refr->cnt) { + MppBuffer buf_pixel = refr->buf[0]; + MppBuffer buf_thumb = refr->buf[1]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg076.rfpr_h_addr = fd; + regs->reg077.rfpr_b_addr = fd; + regs->reg081.dspr_addr = mpp_buffer_get_fd(buf_thumb); + + mpp_dev_set_reg_offset(dev, 77, fbc_hdr_size); + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu541_split(Vepu541H264eRegSet *regs, MppEncSliceSplit *cfg) +{ + hal_h264e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg087.sli_splt = 0; + regs->reg087.sli_splt_mode = 0; + regs->reg087.sli_splt_cpst = 0; + regs->reg087.sli_max_num_m1 = 0; + regs->reg087.sli_flsh = 0; + regs->reg087.sli_splt_cnum_m1 = 0; + + regs->reg088.sli_splt_byte = 0; + regs->reg013.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg087.sli_splt = 1; + regs->reg087.sli_splt_mode = 0; + regs->reg087.sli_splt_cpst = 0; + regs->reg087.sli_max_num_m1 = 500; + regs->reg087.sli_flsh = 1; + regs->reg087.sli_splt_cnum_m1 = 0; + + regs->reg088.sli_splt_byte = cfg->split_arg; + regs->reg013.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + regs->reg087.sli_splt = 1; + regs->reg087.sli_splt_mode = 1; + regs->reg087.sli_splt_cpst = 0; + regs->reg087.sli_max_num_m1 = 500; + regs->reg087.sli_flsh = 1; + regs->reg087.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg088.sli_splt_byte = 0; + regs->reg013.slen_fifo = 0; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu540_force_slice_split(Vepu541H264eRegSet *regs, RK_S32 width) +{ + RK_S32 mb_w = MPP_ALIGN(width, 16) >> 4; + + hal_h264e_dbg_func("enter\n"); + + regs->reg087.sli_splt = 1; + regs->reg087.sli_splt_mode = 1; + regs->reg087.sli_splt_cpst = 0; + regs->reg087.sli_max_num_m1 = 500; + regs->reg087.sli_flsh = 1; + regs->reg087.sli_splt_cnum_m1 = mb_w - 1; + + regs->reg088.sli_splt_byte = 0; + regs->reg013.slen_fifo = 0; + regs->reg023.sli_crs_en = 0; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu541_me(Vepu541H264eRegSet *regs, H264eSps *sps, + H264eSlice *slice, RK_U32 is_vepu540) +{ + RK_S32 level_idc = sps->level_idc; + RK_S32 pic_w = sps->pic_width_in_mbs * 16; + RK_S32 pic_wd64 = (pic_w + 63) / 64; + RK_S32 cime_w = 176; + RK_S32 cime_h = 112; + RK_S32 cime_blk_w_max = 44; + RK_S32 cime_blk_h_max = 28; + + hal_h264e_dbg_func("enter\n"); + /* + * Step 1. limit the mv range by level_idc + * For level 1 and level 1b the vertical MV range is [-64,+63.75] + * For level 1.1, 1.2, 1.3 and 2 the vertical MV range is [-128,+127.75] + */ + switch (level_idc) { + case H264_LEVEL_1_0 : + case H264_LEVEL_1_b : { + cime_blk_h_max = 12; + } break; + case H264_LEVEL_1_1 : + case H264_LEVEL_1_2 : + case H264_LEVEL_1_3 : + case H264_LEVEL_2_0 : { + cime_blk_h_max = 28; + } break; + default : { + cime_blk_h_max = 28; + } break; + } + + if (cime_w < cime_blk_w_max * 4) + cime_blk_w_max = cime_w / 4; + + if (cime_h < cime_blk_h_max * 4) + cime_blk_h_max = cime_h / 4; + + /* + * Step 2. limit the mv range by image size + */ + if (cime_blk_w_max / 4 * 2 > (sps->pic_width_in_mbs * 2 + 1) / 2) + cime_blk_w_max = (sps->pic_width_in_mbs * 2 + 1) / 2 / 2 * 4; + + if (cime_blk_h_max / 4 > MPP_ALIGN(sps->pic_height_in_mbs * 16, 64) / 128 * 4) + cime_blk_h_max = MPP_ALIGN(sps->pic_height_in_mbs * 16, 64) / 128 * 16; + + regs->reg089.cme_srch_h = cime_blk_w_max / 4; + regs->reg089.cme_srch_v = cime_blk_h_max / 4; + regs->reg089.rme_srch_h = 7; + regs->reg089.rme_srch_v = 5; + regs->reg089.dlt_frm_num = 0; + + if (slice->slice_type == H264_I_SLICE) { + regs->reg090.pmv_mdst_h = 0; + regs->reg090.pmv_mdst_v = 0; + } else { + regs->reg090.pmv_mdst_h = 5; + regs->reg090.pmv_mdst_v = 5; + } + regs->reg090.mv_limit = 2; + regs->reg090.pmv_num = 2; + + if (is_vepu540) { + RK_S32 w_temp = 1296; + RK_S32 h_temp = 1; + RK_S32 h_val_0 = 1; + RK_S32 h_val_1 = 18; + RK_S32 temp0, temp1; + RK_U32 pic_temp = ((regs->reg012.pic_wd8_m1 + 1) * 8 + 63) / 64 * 64; + RK_S32 cime_linebuf_w = pic_temp / 64; + + regs->reg091.cme_linebuf_w = cime_linebuf_w; + + while ((w_temp > ((h_temp - h_val_0)*cime_linebuf_w * 4 + ((h_val_1 - h_temp) * 4 * 7))) + && (h_temp < 17)) { + h_temp = h_temp + h_val_0; + } + if (w_temp < ((h_temp - h_val_0)*cime_linebuf_w * 4 + ((h_val_1 - h_temp) * 4 * 7))) + h_temp = h_temp - h_val_0; + + regs->reg091.cme_rama_h = h_temp; + + RK_S32 swin_scope_wd16 = (regs->reg089.cme_srch_h + 3) / 4 * 2 + 1; + + temp0 = 2 * regs->reg089.cme_srch_v + 1; + if (temp0 > regs->reg091.cme_rama_h) + temp0 = regs->reg091.cme_rama_h; + + temp1 = 0; + if (pic_wd64 >= swin_scope_wd16) + temp1 = swin_scope_wd16; + else + temp1 = pic_wd64 * 2; + regs->reg091.cme_rama_max = pic_wd64 * (temp0 - 1) + temp1; + } else { + if (pic_w > 3584) { + regs->reg091.cme_rama_h = 8; + } else if (pic_w > 3136) { + regs->reg091.cme_rama_h = 9; + } else if (pic_w > 2816) { + regs->reg091.cme_rama_h = 10; + } else if (pic_w > 2560) { + regs->reg091.cme_rama_h = 11; + } else if (pic_w > 2368) { + regs->reg091.cme_rama_h = 12; + } else if (pic_w > 2176) { + regs->reg091.cme_rama_h = 13; + } else if (pic_w > 2048) { + regs->reg091.cme_rama_h = 14; + } else if (pic_w > 1856) { + regs->reg091.cme_rama_h = 15; + } else if (pic_w > 1792) { + regs->reg091.cme_rama_h = 16; + } else { + regs->reg091.cme_rama_h = 17; + } + + { + RK_S32 swin_all_4_ver = 2 * regs->reg089.cme_srch_v + 1; + RK_S32 swin_all_16_hor = (regs->reg089.cme_srch_h * 4 + 15) / 16 * 2 + 1; + + if (swin_all_4_ver < regs->reg091.cme_rama_h) + regs->reg091.cme_rama_max = (swin_all_4_ver - 1) * pic_wd64 + swin_all_16_hor; + else + regs->reg091.cme_rama_max = (regs->reg091.cme_rama_h - 1) * pic_wd64 + swin_all_16_hor; + } + } + hal_h264e_dbg_func("leave\n"); +} + +#define H264E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) + +static RK_U32 h264e_lambda_default[58] = { + 0x00000003, 0x00000005, 0x00000006, 0x00000007, + 0x00000009, 0x0000000b, 0x0000000e, 0x00000012, + 0x00000016, 0x0000001c, 0x00000024, 0x0000002d, + 0x00000039, 0x00000048, 0x0000005b, 0x00000073, + 0x00000091, 0x000000b6, 0x000000e6, 0x00000122, + 0x0000016d, 0x000001cc, 0x00000244, 0x000002db, + 0x00000399, 0x00000489, 0x000005b6, 0x00000733, + 0x00000912, 0x00000b6d, 0x00000e66, 0x00001224, + 0x000016db, 0x00001ccc, 0x00002449, 0x00002db7, + 0x00003999, 0x00004892, 0x00005b6f, 0x00007333, + 0x00009124, 0x0000b6de, 0x0000e666, 0x00012249, + 0x00016dbc, 0x0001cccc, 0x00024492, 0x0002db79, + 0x00039999, 0x00048924, 0x0005b6f2, 0x00073333, + 0x00091249, 0x000b6de5, 0x000e6666, 0x00122492, + 0x0016dbcb, 0x001ccccc, +}; + +static void setup_vepu541_l2(Vepu541H264eRegL2Set *regs, H264eSlice *slice, MppEncHwCfg *hw, MppEncCfgSet *cfg) +{ + RK_U32 i; + + hal_h264e_dbg_func("enter\n"); + + memset(regs, 0, sizeof(*regs)); + + regs->iprd_tthdy4[0] = 1; + regs->iprd_tthdy4[1] = 4; + regs->iprd_tthdy4[2] = 9; + regs->iprd_tthdy4[3] = 36; + + regs->iprd_tthdc8[0] = 1; + regs->iprd_tthdc8[1] = 4; + regs->iprd_tthdc8[2] = 9; + regs->iprd_tthdc8[3] = 36; + + regs->iprd_tthdy8[0] = 1; + regs->iprd_tthdy8[1] = 4; + regs->iprd_tthdy8[2] = 9; + regs->iprd_tthdy8[3] = 36; + + regs->iprd_wgty8[0] = 0x30; + regs->iprd_wgty8[1] = 0x3c; + regs->iprd_wgty8[2] = 0x28; + regs->iprd_wgty8[3] = 0x30; + + regs->iprd_wgty4[0] = 0x30; + regs->iprd_wgty4[1] = 0x3c; + regs->iprd_wgty4[2] = 0x28; + regs->iprd_wgty4[3] = 0x30; + + regs->iprd_wgty16[0] = 0x30; + regs->iprd_wgty16[1] = 0x3c; + regs->iprd_wgty16[2] = 0x28; + regs->iprd_wgty16[3] = 0x30; + + regs->iprd_wgtc8[0] = 0x24; + regs->iprd_wgtc8[1] = 0x2a; + regs->iprd_wgtc8[2] = 0x1c; + regs->iprd_wgtc8[3] = 0x20; + + if (cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + regs->iprd_tthd_ul = 0x0; + regs->rme_mvd_penalty.mvd_pnlt_e = 1; + regs->rme_mvd_penalty.mvd_pnlt_coef = 1; + if (slice->slice_type == H264_I_SLICE) { + regs->qnt_bias_comb.qnt_bias_i = 683; + regs->atr_thd1_h264.atr_thd2 = 36; + regs->atr_wgt16_h264.atr_lv16_wgt0 = 16; + regs->atr_wgt16_h264.atr_lv16_wgt1 = 16; + regs->atr_wgt16_h264.atr_lv16_wgt2 = 16; + + regs->atr_wgt8_h264.atr_lv8_wgt0 = 32; + regs->atr_wgt8_h264.atr_lv8_wgt1 = 32; + regs->atr_wgt8_h264.atr_lv8_wgt2 = 32; + + regs->atr_wgt4_h264.atr_lv4_wgt0 = 20; + regs->atr_wgt4_h264.atr_lv4_wgt1 = 18; + regs->atr_wgt4_h264.atr_lv4_wgt2 = 16; + } else { + regs->qnt_bias_comb.qnt_bias_i = 583; + regs->atr_thd1_h264.atr_thd2 = 81; + regs->atr_wgt16_h264.atr_lv16_wgt0 = 28; + regs->atr_wgt16_h264.atr_lv16_wgt1 = 27; + regs->atr_wgt16_h264.atr_lv16_wgt2 = 23; + + regs->atr_wgt8_h264.atr_lv8_wgt0 = 32; + regs->atr_wgt8_h264.atr_lv8_wgt1 = 32; + regs->atr_wgt8_h264.atr_lv8_wgt2 = 32; + + regs->atr_wgt4_h264.atr_lv4_wgt0 = 28; + regs->atr_wgt4_h264.atr_lv4_wgt1 = 27; + regs->atr_wgt4_h264.atr_lv4_wgt2 = 23; + } + } else { + regs->iprd_tthd_ul = 0x9c5; + regs->rme_mvd_penalty.mvd_pnlt_e = 0; + regs->rme_mvd_penalty.mvd_pnlt_coef = 0; + if (slice->slice_type == H264_I_SLICE) { + regs->qnt_bias_comb.qnt_bias_i = 683; + regs->atr_thd1_h264.atr_thd2 = 36; + regs->atr_wgt16_h264.atr_lv16_wgt0 = 16; + regs->atr_wgt16_h264.atr_lv16_wgt1 = 16; + regs->atr_wgt16_h264.atr_lv16_wgt2 = 16; + + regs->atr_wgt8_h264.atr_lv8_wgt0 = 20; + regs->atr_wgt8_h264.atr_lv8_wgt1 = 20; + regs->atr_wgt8_h264.atr_lv8_wgt2 = 20; + + regs->atr_wgt4_h264.atr_lv4_wgt0 = 20; + regs->atr_wgt4_h264.atr_lv4_wgt1 = 18; + regs->atr_wgt4_h264.atr_lv4_wgt2 = 16; + } else { + regs->qnt_bias_comb.qnt_bias_i = 583; + regs->atr_thd1_h264.atr_thd2 = 81; + regs->atr_wgt16_h264.atr_lv16_wgt0 = 18; + regs->atr_wgt16_h264.atr_lv16_wgt1 = 17; + regs->atr_wgt16_h264.atr_lv16_wgt2 = 16; + + regs->atr_wgt8_h264.atr_lv8_wgt0 = 20; + regs->atr_wgt8_h264.atr_lv8_wgt1 = 20; + regs->atr_wgt8_h264.atr_lv8_wgt2 = 20; + + regs->atr_wgt4_h264.atr_lv4_wgt0 = 18; + regs->atr_wgt4_h264.atr_lv4_wgt1 = 17; + regs->atr_wgt4_h264.atr_lv4_wgt2 = 16; + } + } + + /* 000556ab */ + regs->qnt_bias_comb.qnt_bias_p = 171; + if (hw->qbias_en) { + regs->qnt_bias_comb.qnt_bias_i = hw->qbias_i; + regs->qnt_bias_comb.qnt_bias_p = hw->qbias_p; + } + + regs->atr_thd0_h264.atr_thd0 = 1; + regs->atr_thd0_h264.atr_thd1 = 4; + regs->atr_thd1_h264.atr_qp = 45; + regs->atf_tthd[0] = 0; + regs->atf_tthd[1] = 64; + regs->atf_tthd[2] = 144; + regs->atf_tthd[3] = 2500; + + regs->atf_sthd0_h264.atf_sthd_10 = 80; + regs->atf_sthd0_h264.atf_sthd_max = 280; + + regs->atf_sthd1_h264.atf_sthd_11 = 144; + regs->atf_sthd1_h264.atf_sthd_20 = 192; + + regs->atf_wgt0_h264.atf_wgt10 = 26; + regs->atf_wgt0_h264.atf_wgt11 = 24; + + regs->atf_wgt1_h264.atf_wgt12 = 19; + regs->atf_wgt1_h264.atf_wgt20 = 22; + + regs->atf_wgt2_h264.atf_wgt21 = 19; + regs->atf_wgt2_h264.atf_wgt30 = 19; + + regs->atf_ofst0_h264.atf_ofst10 = 3500; + regs->atf_ofst0_h264.atf_ofst11 = 3500; + + regs->atf_ofst1_h264.atf_ofst12 = 0; + regs->atf_ofst1_h264.atf_ofst20 = 3500; + + regs->atf_ofst2_h264.atf_ofst21 = 1000; + regs->atf_ofst2_h264.atf_ofst30 = 0; + + regs->iprd_wgt_qp[0] = 0; + /* ~ */ + regs->iprd_wgt_qp[51] = 0; + + memcpy(regs->wgt_qp_grpa, &h264e_lambda_default[6], H264E_LAMBDA_TAB_SIZE); + memcpy(regs->wgt_qp_grpb, &h264e_lambda_default[5], H264E_LAMBDA_TAB_SIZE); + + regs->madi_mode = 0; + + memcpy(regs->aq_tthd, h264_aq_tthd_default, sizeof(regs->aq_tthd)); + + if (slice->slice_type == H264_I_SLICE) { + for (i = 0; i < MPP_ARRAY_ELEMS(regs->aq_step); i++) { + regs->aq_tthd[i] = hw->aq_thrd_i[i]; + regs->aq_step[i] = hw->aq_step_i[i] & 0x3f; + } + } else { + for (i = 0; i < MPP_ARRAY_ELEMS(regs->aq_step); i++) { + regs->aq_tthd[i] = hw->aq_thrd_p[i]; + regs->aq_step[i] = hw->aq_step_p[i] & 0x3f; + } + } + + regs->rme_mvd_penalty.mvd_pnlt_cnst = 16000; + regs->rme_mvd_penalty.mvd_pnlt_lthd = 0; + regs->rme_mvd_penalty.mvd_pnlt_hthd = 0; + + regs->atr1_thd0_h264.atr1_thd0 = 1; + regs->atr1_thd0_h264.atr1_thd1 = 4; + regs->atr1_thd1_h264.atr1_thd2 = 49; + + mpp_env_get_u32("dump_l2_reg", &dump_l2_reg, 0); + + if (dump_l2_reg) { + mpp_log("L2 reg dump start:\n"); + RK_U32 *p = (RK_U32 *)regs; + + for (i = 0; i < (sizeof(*regs) / sizeof(RK_U32)); i++) + mpp_log("%04x %08x\n", 4 + i * 4, p[i]); + + mpp_log("L2 reg done\n"); + } + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET hal_h264e_vepu541_gen_regs(void *hal, HalEncTask *task) +{ + HalH264eVepu541Ctx *ctx = (HalH264eVepu541Ctx *)hal; + Vepu541H264eRegSet *regs = &ctx->regs_set; + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + MPP_RET ret = MPP_OK; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h264e_dbg_func("enter %p\n", hal); + hal_h264e_dbg_detail("frame %d generate regs now", ctx->frms->seq_idx); + + /* register setup */ + memset(regs, 0, sizeof(*regs)); + + setup_vepu541_normal(regs, ctx->is_vepu540); + ret = setup_vepu541_prep(regs, ctx, task); + if (ret) + return ret; + + setup_vepu541_codec(regs, sps, pps, slice); + setup_vepu541_rdo_pred(regs, sps, pps, slice, cfg); + setup_vepu541_rc_base(regs, sps, slice, &cfg->hw, task->rc_task); + setup_vepu541_io_buf(regs, ctx->dev, task); + setup_vepu541_roi(regs, ctx); + setup_vepu541_recn_refr(regs, ctx->dev, ctx->frms, ctx->hw_recn, + ctx->pixel_buf_fbc_hdr_size); + + regs->reg082.meiw_addr = task->md_info ? mpp_buffer_get_fd(task->md_info) : 0; + + regs->reg068.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg068.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + setup_vepu541_split(regs, &cfg->split); + if (ctx->is_vepu540 && prep->width > 1920) + setup_vepu540_force_slice_split(regs, prep->width); + + setup_vepu541_me(regs, sps, slice, ctx->is_vepu540); + + if (frm_status->is_i_refresh) + setup_vepu541_intra_refresh(regs, ctx, frm_status->seq_idx % cfg->rc.gop); + + if (ctx->is_vepu540) + vepu540_set_osd(&ctx->osd_cfg); + else + vepu541_set_osd(&ctx->osd_cfg); + + setup_vepu541_l2(&ctx->regs_l2_set, slice, &cfg->hw, cfg); + + mpp_env_get_u32("dump_l1_reg", &dump_l1_reg, 0); + + if (dump_l1_reg) { + mpp_log("L1 reg dump start:\n"); + RK_U32 *p = (RK_U32 *)regs; + RK_S32 n = 0x1D0 / sizeof(RK_U32); + RK_S32 i; + + for (i = 0; i < n; i++) + mpp_log("%04x %08x\n", i * 4, p[i]); + + mpp_log("L1 reg done\n"); + } + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu541_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu541Ctx *ctx = (HalH264eVepu541Ctx *)hal; + + (void) task; + + hal_h264e_dbg_func("enter %p\n", hal); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + /* write L2 registers */ + wr_cfg.reg = &ctx->regs_l2_set; + wr_cfg.size = sizeof(Vepu541H264eRegL2Set); + wr_cfg.offset = VEPU541_REG_BASE_L2; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + /* write L1 registers */ + wr_cfg.reg = &ctx->regs_set; + wr_cfg.size = sizeof(Vepu541H264eRegSet); + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + /* set output request */ + rd_cfg.reg = &ctx->regs_ret.hw_status; + rd_cfg.size = sizeof(RK_U32); + rd_cfg.offset = VEPU541_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = &ctx->regs_ret.st_bsl; + rd_cfg.size = sizeof(ctx->regs_ret) - 4; + rd_cfg.offset = VEPU541_REG_BASE_STATISTICS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* send request to hardware */ + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu541_status_check(void *hal) +{ + HalH264eVepu541Ctx *ctx = (HalH264eVepu541Ctx *)hal; + Vepu541H264eRegRet *regs_ret = &ctx->regs_ret; + + if (regs_ret->hw_status.lkt_done_sta) + hal_h264e_dbg_detail("lkt_done finish"); + + if (regs_ret->hw_status.enc_done_sta) + hal_h264e_dbg_detail("enc_done finish"); + + if (regs_ret->hw_status.enc_slice_done_sta) + hal_h264e_dbg_detail("enc_slice finsh"); + + if (regs_ret->hw_status.sclr_done_sta) + hal_h264e_dbg_detail("safe clear finsh"); + + if (regs_ret->hw_status.oflw_done_sta) + mpp_err_f("bit stream overflow"); + + if (regs_ret->hw_status.brsp_done_sta) + mpp_err_f("bus write full"); + + if (regs_ret->hw_status.berr_done_sta) + mpp_err_f("bus write error"); + + if (regs_ret->hw_status.rerr_done_sta) + mpp_err_f("bus read error"); + + if (regs_ret->hw_status.wdg_done_sta) + mpp_err_f("wdg timeout"); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu541_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu541Ctx *ctx = (HalH264eVepu541Ctx *)hal; + H264NaluType type = (task->rc_task->frm.is_idr != 0) ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + + hal_h264e_dbg_func("enter %p\n", hal); + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + hal_h264e_vepu541_status_check(hal); + task->hw_length += ctx->regs_ret.st_bsl.bs_lgth; + } + + mpp_packet_add_segment_info(pkt, type, offset, ctx->regs_ret.st_bsl.bs_lgth); + + { + HalH264eVepuStreamAmend *amend = &ctx->amend; + + if (amend->enable) { + amend->old_length = task->hw_length; + amend->slice->is_multi_slice = (ctx->cfg->split.split_mode > 0); + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + task->hw_length = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = task->hw_length; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu541_ret_task(void *hal, HalEncTask *task) +{ + HalH264eVepu541Ctx *ctx = (HalH264eVepu541Ctx *)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + + hal_h264e_dbg_func("enter %p\n", hal); + + // update total hardware length + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = ctx->regs_ret.st_sse_qp.qp_sum / mbs; + rc_info->madi = (ctx->regs_ret.st_mb_num == 0) ? 0 : + ctx->regs_ret.st_madi / ctx->regs_ret.st_mb_num; + rc_info->madp = (ctx->regs_ret.st_ctu_num == 0) ? 0 : + ctx->regs_ret.st_madp / ctx->regs_ret.st_ctu_num; + rc_info->iblk4_prop = (ctx->regs_ret.st_lvl4_intra_num + + ctx->regs_ret.st_lvl8_intra_num + + ctx->regs_ret.st_lvl16_intra_num) * 256 / mbs; + + rc_info->sse = ((RK_S64)(ctx->regs_ret.st_sse_qp.sse_h8 & 0xff) << 32) + + ctx->regs_ret.st_sse_l32.sse_l32; + rc_info->lvl16_inter_num = ctx->regs_ret.st_lvl16_inter_num; + rc_info->lvl8_inter_num = ctx->regs_ret.st_lvl8_inter_num; + rc_info->lvl16_intra_num = ctx->regs_ret.st_lvl16_intra_num; + rc_info->lvl8_intra_num = ctx->regs_ret.st_lvl8_intra_num; + rc_info->lvl4_intra_num = ctx->regs_ret.st_lvl4_intra_num; + + ctx->hal_rc_cfg.bit_real = rc_info->bit_real; + ctx->hal_rc_cfg.quality_real = rc_info->quality_real; + ctx->hal_rc_cfg.iblk4_prop = rc_info->iblk4_prop; + + task->hal_ret.data = &ctx->hal_rc_cfg; + task->hal_ret.number = 1; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu541 = { + .name = "hal_h264e_vepu541", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu541Ctx), + .flag = 0, + .init = hal_h264e_vepu541_init, + .deinit = hal_h264e_vepu541_deinit, + .prepare = hal_h264e_vepu541_prepare, + .get_task = hal_h264e_vepu541_get_task, + .gen_regs = hal_h264e_vepu541_gen_regs, + .start = hal_h264e_vepu541_start, + .wait = hal_h264e_vepu541_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu541_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu541) diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu541.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu541.h new file mode 100644 index 000000000..8bbf5edc9 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu541.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU541_H +#define HAL_H264E_VEPU541_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h264e_vepu541; + +#endif /* HAL_H264E_VEPU541_H */ \ No newline at end of file diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu541_reg.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu541_reg.h new file mode 100644 index 000000000..2e37c281e --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu541_reg.h @@ -0,0 +1,2487 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU541_REG_H +#define HAL_H264E_VEPU541_REG_H + +#include "vepu541_common.h" + +typedef struct Vepu541H264eRegSet_t { + /* + * VERSION + * Address: 0x0000 Access type: read only + * VEPU version. It contains IP function summary and sub-version informations. + */ + struct { + /* Sub-version(version 1.1) */ + RK_U32 sub_ver : 8; + /* Support H.264 encoding */ + RK_U32 h264_enc : 1; + /* Support HEVC encoding */ + RK_U32 h265_enc : 1; + RK_U32 reserved0 : 2; + /* + * The maximum resolution supported + * 4'd0: 4096x2304 pixels; + * 4'd1: 1920x1088 pixels; + * others: reserved + */ + RK_U32 pic_size : 4; + /* + * OSD capability. + * 2'd0: 8-area OSD, with 256-color palette + * 2'd3: no OSD + * others: reserved + */ + RK_U32 osd_cap : 2; + /* + * pre-process filter capability + * 2'd0: basic pre-process filter + * 2'd3: no pre-process filter + * others: reserved + */ + RK_U32 filtr_cap : 2; + /* B frame encoding capability */ + RK_U32 bfrm_cap : 1; + /* frame buffer compress capability */ + RK_U32 fbc_cap : 1; + RK_U32 reserved1 : 2; + /* IP indentifier for RKVENC default: 0x50 */ + RK_U32 rkvenc_ver : 8; + } reg000; + + /* + * ENC_STRT + * Address: 0x0004 Access type: read and write/write only + * Start cmd register.(auto clock gating enable, auto reset enable and + * tmvp adjust enable when frame done are also allocated here.) + */ + struct { + /* + * Number of new nodes in link table. + * It's valid only when rkvenc_cmd is 2 or 3. + */ + RK_U32 lkt_num : 8; + /* + * Rockchip video encoder command: + * 2'd0: N/A + * 2'd1: one frame encode by register configuration + * 2'd2: multi-frame encode start with link table + * 2'd3: multi_frame_encode link table update + */ + RK_U32 rkvenc_cmd : 2; + RK_U32 reserved0 : 6; + /* RKVENC encoder clock gating enable */ + RK_U32 clk_gate_en : 1; + /* auto reset core clock domain when frame finished */ + RK_U32 resetn_hw_en : 1; + /* wait tmvp write done by dma */ + RK_U32 enc_done_tmvp_en : 1; + RK_U32 reserved1 : 13; + } reg001; + + /* + * ENC_CLR + * Address offset: 0x0008 Access type: read and write + * ENC_CLR.safe_clr only clears RKVENC DMA and confirms the integrity of + * AXI transactions. To execute the global reset of RKVENC, user needs to + * configure SOC CRU register which controls RKVENC's asynchronous reset + */ + struct { + /* + * Safe clear. This filed only clears DMA module to confirm the + * integrity of AXI transactions + */ + RK_U32 safe_clr : 1; + /* + * Force clear. Clear all the sub modules besides regfile and AHB data + * path. + */ + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } reg002; + + /* + * LKT_ADDR + * Address offset: 0x000c Access type: read and write + * Link table + */ + struct { + /* + * High 28 bits of the address for the first node in current link table + * (16bytes aligned) + */ + RK_U32 lkt_addr : 32; + } reg003; + + /* + * INT_EN + * Address offset: 0x0010 Access type: read and write + * VEPU interrupt enable + */ + struct { + /* One frame encode finish interrupt enable */ + RK_U32 enc_done_en : 1; + /* Link table finish interrupt enable */ + RK_U32 lkt_done_en : 1; + /* Safe clear finish interrupt enable */ + RK_U32 sclr_done_en : 1; + /* Safe clear finish interrupt enable */ + RK_U32 enc_slice_done_en : 1; + /* Bit stream overflow interrupt enable */ + RK_U32 oflw_done_en : 1; + /* AXI write response fifo full interrupt enable */ + RK_U32 brsp_done_en : 1; + /* AXI write response channel error interrupt enable */ + RK_U32 berr_done_en : 1; + /* AXI read channel error interrupt enable */ + RK_U32 rerr_done_en : 1; + /* timeout error interrupt enable */ + RK_U32 wdg_done_en : 1; + RK_U32 reserved : 23; + } reg004; + + /* + * INT_MSK + * Address offset: 0x0014 Access type: read and write + * VEPU interrupt mask + */ + struct { + /* One frame encode finish interrupt mask */ + RK_U32 enc_done_msk : 1; + /* Link table finish interrupt mask */ + RK_U32 lkt_done_msk : 1; + /* Safe clear finish interrupt mask */ + RK_U32 sclr_done_msk : 1; + /* Safe clear finish interrupt mask */ + RK_U32 enc_slice_done_msk : 1; + /* Bit stream overflow interrupt mask */ + RK_U32 oflw_done_msk : 1; + /* AXI write response fifo full interrupt mask */ + RK_U32 brsp_done_msk : 1; + /* AXI write response channel error interrupt mask */ + RK_U32 berr_done_msk : 1; + /* AXI read channel error interrupt mask */ + RK_U32 rerr_done_msk : 1; + /* timeout error interrupt mask */ + RK_U32 wdg_done_msk : 1; + RK_U32 reserved : 23; + } reg005; + + /* + * INT_CLR + * Address offset: 0x0018 Access type: read and write, write one to clear + * VEPU interrupt clear + */ + struct { + /* One frame encode finish interrupt clear */ + RK_U32 enc_done_clr : 1; + /* Link table finish interrupt clear */ + RK_U32 lkt_done_clr : 1; + /* Safe clear finish interrupt clear */ + RK_U32 sclr_done_clr : 1; + /* One slice encode finish interrupt clear */ + RK_U32 enc_slice_done_clr : 1; + /* Bit stream overflow interrupt clear */ + RK_U32 oflw_done_clr : 1; + /* AXI write response fifo full interrupt clear */ + RK_U32 brsp_done_clr : 1; + /* AXI write response channel error interrupt clear */ + RK_U32 berr_done_clr : 1; + /* AXI read channel error interrupt clear */ + RK_U32 rerr_done_clr : 1; + /* timeout error interrupt clear */ + RK_U32 wdg_done_clr : 1; + RK_U32 reserved : 23; + } reg006; + + /* + * INT_STA + * Address offset: 0x001c Access type: read and write, write one to clear + * VEPU interrupt status + */ + struct { + /* One frame encode finish interrupt status */ + RK_U32 enc_done_sta : 1; + /* Link table finish interrupt status */ + RK_U32 lkt_done_sta : 1; + /* Safe clear finish interrupt status */ + RK_U32 sclr_done_sta : 1; + /* One slice encode finish interrupt status */ + RK_U32 enc_slice_done_sta : 1; + /* Bit stream overflow interrupt status */ + RK_U32 oflw_done_sta : 1; + /* AXI write response fifo full interrupt status */ + RK_U32 brsp_done_sta : 1; + /* AXI write response channel error interrupt status */ + RK_U32 berr_done_sta : 1; + /* AXI read channel error interrupt status */ + RK_U32 rerr_done_sta : 1; + /* timeout error interrupt status */ + RK_U32 wdg_done_sta : 1; + RK_U32 reserved : 23; + } reg007; + + /* reg gap 008~011 */ + RK_U32 reg_008_011[4]; + + /* + * ENC_RSL + * Address offset: 0x0030 Access type: read and write + * Resolution + */ + struct { + /* ceil(picture width/8) - 1 */ + RK_U32 pic_wd8_m1 : 9; + RK_U32 reserved0 : 1; + /* filling pixels to maintain picture width 8 pixels aligned */ + RK_U32 pic_wfill : 6; + /* Ceil(picture_height/8)-1 */ + RK_U32 pic_hd8_m1 : 9; + RK_U32 reserved1 : 1; + /* Filling pixels to maintain picture height 8 pixels aligned */ + RK_U32 pic_hfill : 6; + } reg012; + + /* + * ENC_PIC + * Address offset: 0x0034 Access type: read and write + * VEPU common configuration + */ + struct { + /* Video standard: 0->H.264; 1->HEVC */ + RK_U32 enc_stnd : 1; + /* ROI encode enable */ + RK_U32 roi_enc : 1; + /* Current frame should be refered in future */ + RK_U32 cur_frm_ref : 1; + /* Output ME information */ + RK_U32 mei_stor : 1; + /* Output start code prefix */ + RK_U32 bs_scp : 1; + /* 0: select table A, 1: select table B */ + RK_U32 lamb_mod_sel : 1; + RK_U32 reserved0 : 2; + /* QP value for current frame encoding */ + RK_U32 pic_qp : 6; + /* sum of reference pictures (indexed by difference POCs), HEVC only */ + RK_U32 tot_poc_num : 5; + /* bit width to express the maximum ctu number in current picure, HEVC only */ + RK_U32 log2_ctu_num : 4; + /* 1'h0: Select atr_thd group 1'h1: Select atr_thd group1 */ + RK_U32 atr_thd_sel : 1; + /* Dual-core handshake Rx ID. */ + RK_U32 dchs_rxid : 2; + /* Dual-core handshake tx ID. */ + RK_U32 dchs_txid : 2; + /* Dual-core handshake rx enable. */ + RK_U32 dchs_rxe : 1; + /* RDO intra-prediction satd path bypass enable. */ + RK_U32 satd_byps_en : 1; + /* Slice length fifo enable. */ + RK_U32 slen_fifo : 1; + /* Node interrupt enable (only for link table node configuration). */ + RK_U32 node_int : 1; + } reg013; + + /* + * ENC_WDG + * Address offset: 0x0038 Access type: read and write + * VEPU watch dog configure register + */ + struct { + /* + * Video source loading timeout threshold. + * 24'h0: No time limit + * 24'hx: x*256 core clock cycles + */ + RK_U32 vs_load_thd : 24; + /* + * Reference picture loading timeout threshold. + * 8'h0: No time limit + * 8'hx: x*256 core clock cycles + */ + RK_U32 rfp_load_thrd : 8; + } reg014; + + /* + * DTRNS_MAP + * Address offset: 0x003c Access type: read and write + * Data transaction mapping (endian and order) + */ + struct { + /* swap the position of 64bits in 128bits for lpf write data between tiles */ + RK_U32 lpfw_bus_ordr : 1; + /* Swap the position of 64 bits in 128 bits for co-located Mv(HEVC only). */ + RK_U32 cmvw_bus_ordr : 1; + /* Swap the position of 64 bits in 128 bits for down-sampled picture. */ + RK_U32 dspw_bus_ordr : 1; + /* Swap the position of 64 bits in 128 bits for reference picture. */ + RK_U32 rfpw_bus_ordr : 1; + /* + * Data swap for video source loading channel. + * [3]: Swap 64 bits in 128 bits + * [2]: Swap 32 bits in 64 bits + * [1]: Swap 16 bits in 32 bits + * [0]: Swap 8 bits in 16 bits + */ + RK_U32 src_bus_edin : 4; + /* + * Data swap for ME information write channel. + * [3]: Swap 64 bits in 128 bits + * [2]: Swap 32 bits in 64 bits + * [1]: Swap 16 bits in 32 bits + * [0]: Swap 8 bits in 16 bits + */ + RK_U32 meiw_bus_edin : 4; + /* + * Data swap for bis stream write channel. + * [2]: Swap 32 bits in 64 bits + * [1]: Swap 16 bits in 32 bits + * [0]: Swap 8 bits in 16 bits + */ + RK_U32 bsw_bus_edin : 3; + /* + * Data swap for link table read channel. + * [3]: Swap 64 bits in 128 bits + * [2]: Swap 32 bits in 64 bits + * [1]: Swap 16 bits in 32 bits + * [0]: Swap 8 bits in 16 bits + */ + RK_U32 lktr_bus_edin : 4; + /* + * Data swap for ROI configuration read channel. + * [3]: Swap 64 bits in 128 bits + * [2]: Swap 32 bits in 64 bits + * [1]: Swap 16 bits in 32 bits + * [0]: Swap 8 bits in 16 bits + */ + RK_U32 roir_bus_edin : 4; + /* + * Data swap for link table write channel. + * [3]: Swap 64 bits in 128 bits + * [2]: Swap 32 bits in 64 bits + * [1]: Swap 16 bits in 32 bits + * [0]: Swap 8 bits in 16 bits + */ + RK_U32 lktw_bus_edin : 4; + /* + * AFBC video source loading burst size. + * 1'h0: 32 bytes + * 1'h1: 64 bytes + */ + RK_U32 afbc_bsize : 1; + RK_U32 reserved1 : 4; + } reg015; + + /* + * DTRNS_CFG + * Address offset: 0x0040 Access type: read and write + * (AXI bus) Data transaction configuration + */ + union { + struct vepu541_t { + /* + * AXI write response channel check enable. + * [6]: Reconstructed picture write response check enable. + * [5]: ME information write response check enable. + * [4]: CTU information write response check enable. + * [3]: Down-sampled picture write response check enable. + * [2]: Bit stream write response check enable. + * [1]: Link table mode write reponse check enable. + * [0]: Reserved for video preprocess. + */ + RK_U32 axi_brsp_cke : 7; + /* + * Down sampled reference picture read outstanding enable. + * 1'h0: No outstanding + * 1'h1: Outstanding read, which improves data transaction efficiency, + * but core clock frequency should not lower than bus clock frequency. + */ + RK_U32 dspr_otsd : 1; + RK_U32 reserved : 24; + } vepu541; + + struct vepu540_t { + RK_U32 reserved0 : 7; + /* + * Down sampled reference picture read outstanding enable. + * 1'h0: No outstanding + * 1'h1: Outstanding read, which improves data transaction efficiency, + * but core clock frequency should not lower than bus clock frequency. + */ + RK_U32 dspr_otsd : 1; + RK_U32 reserved1 : 8; + /* + * AXI write response channel check enable. + * [7]: lpf write response check enable + * [6]: Reconstructed picture write response check enable. + * [5]: ME information write response check enable. + * [4]: CTU information write response check enable. + * [3]: Down-sampled picture write response check enable. + * [2]: Bit stream write response check enable. + * [1]: Link table mode write reponse check enable. + * [0]: Reserved for video preprocess. + */ + RK_U32 axi_brsp_cke : 8; + RK_U32 reserved2 : 8; + } vepu540; + } reg016; + + /* + * SRC_FMT + * Address offset: 0x0044 Access type: read and write + * Video source format + */ + struct { + /* + * Swap the position of alpha and RGB for ARBG8888. + * 1'h0: BGRA8888 or RGBA8888. + * 1'h1: ABGR8888 or ARGB8888. + */ + RK_U32 alpha_swap : 1; + /* + * Swap the position of R and B for BGRA8888, RGB888, RGB 656 format; + * Swap the position of U and V for YUV422-SP, YUV420-SP, YUYV422 and UYUV422 format. + * 1'h0: RGB or YUYV or UYVY. + * 1'h1: BGR or YVYU or VYUY. + */ + RK_U32 rbuv_swap : 1; + /* + * Video source color format. + * 4'h0: BGRA8888 + * 4'h1: RGB888 + * 4'h2: RGB565 + * 4'h4: YUV422 SP + * 4'h5: YUV422 P + * 4'h6: YUV420 SP + * 4'h7: YUV420 P + * 4'h8: YUYV422 + * 4'h9: UYVY422 + * Others: Reserved + */ + RK_U32 src_cfmt : 4; + /* + * Video source clip (low active). + * 1'h0: [16:235] for luma and [16:240] for chroma. + * 1'h1: [0:255] for both luma and chroma. + */ + RK_U32 src_range : 1; + /* + * Ourput reconstructed frame format + * 1'h0: yuv420 + * 1'h1: yuv400 + */ + RK_U32 out_fmt_cfg : 1; + RK_U32 reserved : 24; + } reg017; + + /* + * SRC_UDFY + * Address offset: 0x0048 Access type: read and write + * Weight of user defined formula for RBG to Y conversion + */ + struct { + /* Weight of BLUE in RBG to Y conversion formula. */ + RK_U32 csc_wgt_b2y : 9; + /* Weight of GREEN in RBG to Y conversion formula. */ + RK_U32 csc_wgt_g2y : 9; + /* Weight of RED in RBG to Y conversion formula. */ + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } reg018; + + /* + * SRC_UDFU + * Address offset: 0x004c Access type: read and write + * Weight of user defined formula for RBG to U conversion + */ + struct { + /* Weight of BLUE in RBG to U conversion formula. */ + RK_U32 csc_wgt_b2u : 9; + /* Weight of GREEN in RBG to U conversion formula. */ + RK_U32 csc_wgt_g2u : 9; + /* Weight of RED in RBG to U conversion formula. */ + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } reg019; + + /* + * SRC_UDFV + * Address offset: 0x0050 Access type: read and write + * Weight of user defined formula for RBG to V conversion + */ + struct { + /* Weight of BLUE in RBG to V conversion formula. */ + RK_U32 csc_wgt_b2v : 9; + /* Weight of GREEN in RBG to V conversion formula. */ + RK_U32 csc_wgt_g2v : 9; + /* Weight of RED in RBG to V conversion formula. */ + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } reg020; + + /* + * SRC_UDFO + * Address offset: 0x0054 Access type: read and write + * Offset of user defined formula for RBG to YUV conversion + */ + struct { + /* Offset of RBG to V conversion formula. */ + RK_U32 csc_ofst_v : 8; + /* Offset of RBG to U conversion formula. */ + RK_U32 csc_ofst_u : 8; + /* Offset of RBG to Y conversion formula. */ + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } reg021; + + /* + * SRC_PROC + * Address offset: 0x0058 Access type: read and write + * Video source process + */ + struct { + RK_U32 reserved0 : 26; + /* Video source mirror mode enable. */ + RK_U32 src_mirr : 1; + /* + * Video source rotation mode. + * 2'h0: 0 degree + * 2'h1: Clockwise 90 degree + * 2'h2: Clockwise 180 degree + * 2'h3: Clockwise 280 degree + */ + RK_U32 src_rot : 2; + /* Video source texture analysis enable. */ + RK_U32 txa_en : 1; + /* AFBC decompress enable (for AFBC format video source). */ + RK_U32 afbcd_en : 1; + RK_U32 reserved1 : 1; + } reg022; + + /* + * SLI_CFG_H264 + * Address offset: 0x005C Access type: read and write + * Slice cross lines configuration, h264 only. + */ + struct { + RK_U32 reserved0 : 31; + /* + * Slice cut cross lines enable, + * using for breaking the resolution limit, h264 only. + */ + RK_U32 sli_crs_en : 1; + } reg023; + + /* reg gap 024 */ + RK_U32 reg_024; + + /* + * KLUT_OFST + * Address offset: 0x0064 Access type: read and write + * Offset of (RDO) chroma cost weight table + */ + struct { + /* Offset of (RDO) chroma cost weight table, values from 0 to 6. */ + RK_U32 chrm_klut_ofst : 3; + RK_U32 reserved : 1; + } reg025; + + /* + * KLUT_WGT0 + * Address offset: 0x0068 Access type: read and write + * (RDO) Chroma weight table configure register0 + */ + struct { + /* Data0 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt0 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data1 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt1_l9 : 9; + } reg026; + + /* + * KLUT_WGT1 + * Address offset: 0x006C Access type: read and write + * (RDO) Chroma weight table configure register1 + */ + struct { + /* High 9 bits of data1 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt1_h9 : 9; + RK_U32 reserved : 5; + /* Data2 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt2 : 18; + } reg027; + + /* + * KLUT_WGT2 + * Address offset: 0x0070 Access type: read and write + * (RDO) Chroma weight table configure register2 + */ + struct { + /* Data3 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt3 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data4 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt4_l9 : 9; + } reg028; + + /* + * KLUT_WGT3 + * Address offset: 0x0074 Access type: read and write + * (RDO) Chroma weight table configure register3 + */ + struct { + /* High 9 bits of data4 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt4_h9 : 9; + RK_U32 reserved : 5; + /* Data5 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt5 : 18; + } reg029; + + /* + * KLUT_WGT4 + * Address offset: 0x0078 Access type: read and write + * (RDO) Chroma weight table configure register4 + */ + struct { + /* Data6 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt6 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data7 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt7_l9 : 9; + } reg030; + + /* + * KLUT_WGT5 + * Address offset: 0x007C Access type: read and write + * (RDO) Chroma weight table configure register5 + */ + struct { + /* High 9 bits of data7 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt7_h9 : 9; + RK_U32 reserved : 5; + /* Data8 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt8 : 18; + } reg031; + + /* + * KLUT_WGT6 + * Address offset: 0x0080 Access type: read and write + * (RDO) Chroma weight table configure register6 + */ + struct { + /* Data9 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt9 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data10 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt10_l9 : 9; + } reg032; + + /* + * KLUT_WGT7 + * Address offset: 0x0084 Access type: read and write + * (RDO) Chroma weight table configure register7 + */ + struct { + /* High 9 bits of data10 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt10_h9 : 9; + RK_U32 reserved : 5; + /* Data11 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt11 : 18; + } reg033; + + /* + * KLUT_WGT8 + * Address offset: 0x0088 Access type: read and write + * (RDO) Chroma weight table configure register8 + */ + struct { + /* Data12 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt12 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data13 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt13_l9 : 9; + } reg034; + + /* + * KLUT_WGT9 + * Address offset: 0x008C Access type: read and write + * (RDO) Chroma weight table configure register9 + */ + struct { + /* High 9 bits of data13 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt13_h9 : 9; + RK_U32 reserved : 5; + /* Data14 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt14 : 18; + } reg035; + + /* + * KLUT_WGT10 + * Address offset: 0x0090 Access type: read and write + * (RDO) Chroma weight table configure register10 + */ + struct { + /* Data15 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt15 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data16 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt16_l9 : 9; + } reg036; + + /* + * KLUT_WGT11 + * Address offset: 0x0094 Access type: read and write + * (RDO) Chroma weight table configure register11 + */ + struct { + /* High 9 bits of data16 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt16_h9 : 9; + RK_U32 reserved : 5; + /* Data17 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt17 : 18; + } reg037; + + /* + * KLUT_WGT12 + * Address offset: 0x0098 Access type: read and write + * (RDO) Chroma weight table configure register12 + */ + struct { + /* Data18 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt18 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data19 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt19_l9 : 9; + } reg038; + + /* + * KLUT_WGT13 + * Address offset: 0x009C Access type: read and write + * (RDO) Chroma weight table configure register13 + */ + struct { + /* High 9 bits of data19 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt19_h9 : 9; + RK_U32 reserved : 5; + /* Data14 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt20 : 18; + } reg039; + + /* + * KLUT_WGT14 + * Address offset: 0x00A0 Access type: read and write + * (RDO) Chroma weight table configure register14 + */ + struct { + /* Data21 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt21 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data22 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt22_l9 : 9; + } reg040; + + /* + * KLUT_WGT15 + * Address offset: 0x00A4 Access type: read and write + * (RDO) Chroma weight table configure register15 + */ + struct { + /* High 9 bits of data22 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt22_h9 : 9; + RK_U32 reserved : 5; + /* Data23 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt23 : 18; + } reg041; + + /* + * KLUT_WGT16 + * Address offset: 0x00A8 Access type: read and write + * (RDO) Chroma weight table configure register16 + */ + struct { + /* Data24 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt24 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data25 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt25_l9 : 9; + } reg042; + + /* + * KLUT_WGT17 + * Address offset: 0x00AC Access type: read and write + * (RDO) Chroma weight table configure register17 + */ + struct { + /* High 9 bits of data25 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt25_h9 : 9; + RK_U32 reserved : 5; + /* Data26 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt26 : 18; + } reg043; + + /* + * KLUT_WGT18 + * Address offset: 0x00B0 Access type: read and write + * (RDO) Chroma weight table configure register18 + */ + struct { + /* Data27 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt27 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data28 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt28_l9 : 9; + } reg044; + + /* + * KLUT_WGT19 + * Address offset: 0x00B4 Access type: read and write + * (RDO) Chroma weight table configure register19 + */ + struct { + /* High 9 bits of data28 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt28_h9 : 9; + RK_U32 reserved : 5; + /* Data29 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt29 : 18; + } reg045; + + /* + * KLUT_WGT20 + * Address offset: 0x00B8 Access type: read and write + * (RDO) Chroma weight table configure register20 + */ + struct { + /* Data30 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt30 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data31 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt31_l9 : 9; + } reg046; + + /* + * KLUT_WGT21 + * Address offset: 0x00BC Access type: read and write + * (RDO) Chroma weight table configure register21 + */ + struct { + /* High 9 bits of data31 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt31_h9 : 9; + RK_U32 reserved : 5; + /* Data32 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt32 : 18; + } reg047; + + /* + * KLUT_WGT22 + * Address offset: 0x00C0 Access type: read and write + * (RDO) Chroma weight table configure register22 + */ + struct { + /* Data33 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt33 : 18; + RK_U32 reserved : 5; + /* Low 9 bits of data34 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt34_l9 : 9; + } reg048; + + /* + * KLUT_WGT23 + * Address offset: 0x00C4 Access type: read and write + * (RDO) Chroma weight table configure register23 + */ + struct { + /* High 9 bits of data34 in chroma cost weight table. */ + RK_U32 chrm_klut_wgt34_h9 : 9; + RK_U32 reserved : 23; + } reg049; + + /* + * RC_CFG + * Address offset: 0x00C8 Access type: read and write + * Rate control configuration + */ + struct { + /* Rate control enable. */ + RK_U32 rc_en : 1; + /* Adaptive quantization enable. */ + RK_U32 aq_en : 1; + /* + * Mode of aq_delta calculation for CU32 and CU64. + * 1'b0: aq_delta of CU32/CU64 is calculated by corresponding MADI32/64; + * 1'b1: aq_delta of CU32/CU64 is calculated by corresponding 4/16 CU16 qp_deltas. + */ + RK_U32 aq_mode : 1; + RK_U32 reserved : 13; + /* RC adjustment intervals, base on CTU number. */ + RK_U32 rc_ctu_num : 16; + } reg050; + + /* + * RC_QP + * Address offset: 0x00CC Access type: read and write + * QP configuration for rate control + */ + struct { + RK_U32 reserved : 16; + /* + * QP adjust range(delta_qp) in rate control. + * Delta_qp is constrained between -rc_qp_range to rc_qp_range. + */ + RK_S32 rc_qp_range : 4; + /* Max QP for rate control and AQ mode. */ + RK_U32 rc_max_qp : 6; + /* Min QP for rate control and AQ mode. */ + RK_U32 rc_min_qp : 6; + } reg051; + + /* + * RC_TGT + * Address offset: 0x00D0 Access type: read and write + * The target bit rate for rate control + */ + struct { + /* + * Target bit num for one 64x64 CTU(for HEVC) + * or one 16x16 MB(for H.264), with 1/16 precision. + */ + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } reg052; + + /* + * RC_ADJ0 + * Address offset: 0x00D4 Access type: read and write + * QP adjust configuration for rate control + */ + struct { + /* QP adjust step0 for rate control. */ + RK_S32 qp_adj0 : 5; + /* QP adjust step1 for rate control. */ + RK_S32 qp_adj1 : 5; + /* QP adjust step2 for rate control. */ + RK_S32 qp_adj2 : 5; + /* QP adjust step3 for rate control. */ + RK_S32 qp_adj3 : 5; + /* QP adjust step4 for rate control. */ + RK_S32 qp_adj4 : 5; + RK_U32 reserved : 7; + } reg053; + + /* + * RC_ADJ1 + * Address offset: 0x00D8 Access type: read and write + * QP adjust configuration for rate control + */ + struct { + /* QP adjust step5 for rate control. */ + RK_S32 qp_adj5 : 5; + /* QP adjust step6 for rate control. */ + RK_S32 qp_adj6 : 5; + /* QP adjust step7 for rate control. */ + RK_S32 qp_adj7 : 5; + /* QP adjust step8 for rate control. */ + RK_S32 qp_adj8 : 5; + RK_U32 reserved : 12; + } reg054; + + /* + * RC_DTHD0~8 + * Address offset: 0x00DC~0x00FC Access type: read and write + * Bits rate deviation threshold0~8 + */ + struct { + /* Bits rate deviation threshold0~8. */ + RK_U32 rc_dthd[9]; + } reg055_063; + + /* + * ROI_QTHD0 + * Address offset: 0x0100 Access type: read and write + * ROI QP threshold configuration0 + */ + struct { + /* Min QP for 16x16 CU inside ROI area0. */ + RK_U32 qpmin_area0 : 6; + /* Max QP for 16x16 CU inside ROI area0. */ + RK_U32 qpmax_area0 : 6; + /* Min QP for 16x16 CU inside ROI area1. */ + RK_U32 qpmin_area1 : 6; + /* Max QP for 16x16 CU inside ROI area1. */ + RK_U32 qpmax_area1 : 6; + /* Min QP for 16x16 CU inside ROI area2. */ + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } reg064; + + /* + * ROI_QTHD1 + * Address offset: 0x0104 Access type: read and write + * ROI QP threshold configuration1 + */ + struct { + /* Max QP for 16x16 CU inside ROI area2. */ + RK_U32 qpmax_area2 : 6; + /* Min QP for 16x16 CU inside ROI area3. */ + RK_U32 qpmin_area3 : 6; + /* Max QP for 16x16 CU inside ROI area3. */ + RK_U32 qpmax_area3 : 6; + /* Min QP for 16x16 CU inside ROI area4. */ + RK_U32 qpmin_area4 : 6; + /* Min QP for 16x16 CU inside ROI area4. */ + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } reg065; + + /* + * ROI_QTHD2 + * Address offset: 0x0108 Access type: read and write + * ROI QP threshold configuration2 + */ + struct { + /* Min QP for 16x16 CU inside ROI area5. */ + RK_U32 qpmin_area5 : 6; + /* Max QP for 16x16 CU inside ROI area5. */ + RK_U32 qpmax_area5 : 6; + /* Min QP for 16x16 CU inside ROI area6. */ + RK_U32 qpmin_area6 : 6; + /* Max QP for 16x16 CU inside ROI area6. */ + RK_U32 qpmax_area6 : 6; + /* Min QP for 16x16 CU inside ROI area7. */ + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } reg066; + + /* + * ROI_QTHD3 + * Address offset: 0x010C Access type: read and write + * ROI QP threshold configuration3 + */ + struct { + /* Max QP for 16x16 CU inside ROI area7. */ + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 24; + /* + * QP theshold generation for the CUs whose size is bigger than 16x16. + * 2'h0: Mean value of 16x16 CU QP thesholds + * 2'h1: Max value of 16x16 CU QP thesholds + * 2'h2: Min value of 16x16 CU QP thesholds + * 2'h3: Reserved + */ + RK_U32 qpmap_mode : 2; + } reg067; + + /* + * PIC_OFST + * Address offset: 0x0110 Access type: read and write + * Encoding picture offset + */ + struct { + /* Vertical offset for encoding picture. */ + RK_U32 pic_ofst_y : 13; + RK_U32 reserved0 : 3; + /* Horizontal offset for encoding picture. */ + RK_U32 pic_ofst_x : 13; + RK_U32 reserved1 : 3; + } reg068; + + /* + * SRC_STRID + * Address offset: 0x0114 Access type: read and write + * Video source stride + */ + struct { + /* + * Video source stride0, based on pixel (byte). + * Note that if the video format is YUV, src_strd is the LUMA component + * stride while src_strid1 is the CHROMA component stride. + */ + RK_U32 src_strd0 : 16; + /* + * CHROMA stride of video source, only for YUV format. + * Note that U and V stride must be the same when color format is YUV + * planar. + */ + RK_U32 src_strd1 : 16; + } reg069; + + /* + * ADR_SRC0 + * Address offset: 0x0118 Access type: read and write + * Base address of the 1st storage area for video source + */ + struct { + /* + * Base address of the 1st storage area for video source. + * ARGB8888, BGR888, RGB565, YUYV422 and UYUV422 have only one storage + * area, while adr_src0 is configured as the base address of video + * source frame buffer. + * YUV422/420 semi-planar have 2 storage area, while adr_src0 is + * configured as the base address of Y frame buffer. + * YUV422/420 planar have 3 storage area, while adr_src0 is configured + * as the base address of Y frame buffer. + * Note that if the video source is compressed by AFBC, adr_src0 is + * configured as the base address of compressed frame buffer. + */ + RK_U32 adr_src0; + } reg070; + + /* + * ADR_SRC1 + * Address offset: 0x011C Access type: read and write + * Base address of the 2nd storage area for video source + */ + struct { + /* + * Base address of V frame buffer when video source is uncompress and + * color format is YUV422/420 planar. + */ + RK_U32 adr_src1; + } reg071; + + /* + * ADR_SRC2 + * Address offset: 0x0120 Access type: read and write + * Base address of the 3rd storage area for video source + */ + struct { + /* + * Base address of V frame buffer when video source is uncompress and + * color format is YUV422/420 planar. + */ + RK_U32 adr_src2; + } reg072; + + /* + * ADR_ROI + * Address offset: 0x0124 Access type: read and write + * Base address for ROI configuration, 16 bytes aligned + */ + struct { + /* High 28 bits of base address for ROI configuration. */ + RK_U32 roi_addr; + } reg073; + + /* + * ADR_RFPW_H + * Address offset: 0x0128 Access type: read and write + * Base address of header_block for compressed reference frame write, + * 4K bytes aligned + */ + struct { + /* + * High 20 bits of the header_block base address for compressed + * reference frame write. + */ + RK_U32 rfpw_h_addr; + } reg074; + + /* + * ADR_RFPW_B + * Address offset: 0x012C Access type: read and write + * Base address of body_block for compressed reference frame write, + * 4K bytes aligned + */ + struct { + /* + * High 20 bits of the body_block base address for compressed + * reference frame write. + */ + RK_U32 rfpw_b_addr; + } reg075; + + /* + * ADR_RFPR_H + * Address offset: 0x0130 Access type: read and write + * Base address of header_block for compressed reference frame read, + * 4K bytes aligned + */ + struct { + /* + * High 20 bits of the header_block base address for compressed + * reference frame read. + */ + RK_U32 rfpr_h_addr; + } reg076; + + /* + * ADR_RFPR_B + * Address offset: 0x0134 Access type: read and write + * Base address of body_block for compressed reference frame read, + * 4K bytes aligned + */ + struct { + /* + * High 20 bits of the body_block base address for compressed + * reference frame read. + */ + RK_U32 rfpr_b_addr; + } reg077; + + /* + * ADR_CMVW + * Address offset: 0x0138 Access type: read and write + * Base address for col-located Mv write, 1KB aligned, HEVC only + */ + struct { + /* High 22 bits of base address for col-located Mv write, HEVC only. */ + RK_U32 cmvw_addr; + } reg078; + + /* + * ADR_CMVR + * Address offset: 0x013C Access type: read and write + * Base address for col-located Mv read, 1KB aligned, HEVC only + */ + struct { + /* High 22 bits of base address for col-located Mv read, HEVC only. */ + RK_U32 cmvr_addr; + } reg079; + + /* + * ADR_DSPW + * Address offset: 0x0140 Access type: read and write + * Base address for down-sampled reference frame write, 1KB aligned + */ + struct { + /* High 22 bits of base address for down-sampled reference frame write. */ + RK_U32 dspw_addr; + } reg080; + + /* + * ADR_DSPR + * Address offset: 0x0144 Access type: read and write + * Base address for down-sampled reference frame read, 1KB aligned + */ + struct { + /* High 22 bits of base address for down-sampled reference frame read. */ + RK_U32 dspr_addr; + } reg081; + + /* + * ADR_MEIW + * Address offset: 0x0148 Access type: read and write + * Base address for ME information write, 1KB aligned + */ + struct { + /* High 22 bits of base address for ME information write. */ + RK_U32 meiw_addr; + } reg082; + + /* + * ADR_BSBT + * Address offset: 0x014C Access type: read and write + * Top address of bit stream buffer, 128B aligned + */ + struct { + /* High 25 bits of the top address of bit stream buffer. */ + RK_U32 bsbt_addr; + } reg083; + + /* + * ADR_BSBB + * Address offset: 0x0150 Access type: read and write + * Bottom address of bit stream buffer, 128B aligned + */ + struct { + /* High 25 bits of the bottom address of bit stream buffer. */ + RK_U32 bsbb_addr; + } reg084; + + /* + * ADR_BSBR + * Address offset: 0x0154 Access type: read and write + * Read address of bit stream buffer, 128B aligned + */ + struct { + /* + * Read address of bit stream buffer, 128B aligned. + * VEPU will pause when write address meets read address and then send + * an interrupt. SW should move some data out from bit stream buffer + * and change this register accordingly. + * After that VEPU will continue processing automatically. + */ + RK_U32 bsbr_addr; + } reg085; + + /* + * ADR_BSBS + * Address offset: 0x0158 Access type: read and write + * Start address of bit stream buffer + */ + struct { + /* + * Start address of bit stream buffer. + * VEPU begins to write bit stream from this address and increase + * address automatically. + * Note that the VEPU's real-time write address is marked in BSB_STUS. + */ + RK_U32 adr_bsbs; + } reg086; + + /* + * SLI_SPLT + * Address offset: 0x015C Access type: read and write + * Slice split configuration + */ + struct { + /* Slice split enable. */ + RK_U32 sli_splt : 1; + /* + * Slice split mode. + * 1'h0: Slice splited by byte. + * 1'h1: Slice splited by number of MB(H.264)/CTU(HEVC). + */ + RK_U32 sli_splt_mode : 1; + /* + * Slice split compensation when slice is splited by byte. + * Byte distortion of current slice will be compensated in the next slice. + */ + RK_U32 sli_splt_cpst : 1; + /* Max slice num in one frame. */ + RK_U32 sli_max_num_m1 : 10; + /* Slice flush. Flush all the bit stream after each slice finished. */ + RK_U32 sli_flsh : 1; + RK_U32 reserved : 2; + /* Number of CTU/MB for slice split. Valid when slice is splited by CTU/MB. */ + RK_U32 sli_splt_cnum_m1 : 16; + } reg087; + + /* + * SLI_BYTE + * Address offset: 0x0160 Access type: read and write + * Number of bytes for slice split + */ + struct { + /* Byte number for each slice when slice is splited by byte. */ + RK_U32 sli_splt_byte : 18; + RK_U32 reserved : 14; + } reg088; + + /* + * ME_RNGE + * Address offset: 0x0164 Access type: read and write + * Motion estimation range + */ + struct { + /* CME horizontal search range, base on 16 pixels. */ + RK_U32 cme_srch_h : 4; + /* CME vertical search range, base on 16 pixel. */ + RK_U32 cme_srch_v : 4; + /* RME horizontal search range, values from 3 to 7. */ + RK_U32 rme_srch_h : 3; + /* RME vertical search range, values from 4 to 5. */ + RK_U32 rme_srch_v : 3; + RK_U32 reserved : 2; + /* Frame number difference value between current and reference frame, HEVC only. */ + RK_U32 dlt_frm_num : 16; + } reg089; + + /* + * ME_CNST + * Address offset: 0x0168 Access type: read and write + * Motion estimation configuration + */ + struct { + /* Min horizontal distance for PMV selection. */ + RK_U32 pmv_mdst_h : 8; + /* Min vertical distance for PMV selection. */ + RK_U32 pmv_mdst_v : 8; + /* + * Motion vector limit ( by level), H.264 only. + * 2'h0: Mvy is limited to [-64,63]. + * Others: Mvy is limited to [-128,127]. + */ + RK_U32 mv_limit : 2; + /* PMV number (should be constant2). */ + RK_U32 pmv_num : 2; + /* Store col-Mv information to external memory, HEVC only. */ + RK_U32 colmv_stor : 1; + /* Load co-located Mvs as predicated Mv candidates, HEVC only. */ + RK_U32 colmv_load : 1; + /* + * [4]: Disable 64x64 block RME. + * [3]: Disable 32x32 block RME. + * [2]: Disable 16x16 block RME. + * [1]: Disable 8x8 block RME. + * [0]: Disable 4x4 block RME. + */ + RK_U32 rme_dis : 5; + /* + * [4]: Disable 64x64 block FME. + * [3]: Disable 32x32 block FME. + * [2]: Disable 16x16 block FME. + * [1]: Disable 8x8 block FME. + * [0]: Disable 4x4 block FME. + */ + RK_U32 fme_dis : 5; + } reg090; + + /* + * ME_RAM + * Address offset: 0x016C Access type: read and write + * ME cache configuration + */ + struct { + /* CME's max RAM address. */ + RK_U32 cme_rama_max : 11; + /* Height of CME RAMA district, base on 4 pixels. */ + RK_U32 cme_rama_h : 5; + /* + * L2 cach mapping, base on pixels. + * 2'h0: 32x512 + * 2'h1: 16x1024 + * 2'h2: 8x2048 + * 2'h3: 4x4096 + */ + RK_U32 cach_l2_map : 2; + /* The width of CIME down-sample recon data linebuf, based on 64 pixel. */ + RK_U32 cme_linebuf_w : 8; + RK_U32 reserved : 6; + } reg091; + + /* + * SYNT_LONG_REFM0 + * Address offset: 0x0170 Access type: read and write + * Long term reference frame mark0 for HEVC + */ + struct { + /* Poc_lsb_lt[1] */ + RK_U32 poc_lsb_lt1 : 16; + /* Poc_lsb_lt[2] */ + RK_U32 poc_lsb_lt2 : 16; + } reg092; + + /* + * SYNT_LONG_REFM1 + * Address offset: 0x0174 Access type: read and write + * Long term reference frame mark1 for HEVC + */ + struct { + /* Delta_poc_msb_cycle_lt[1] */ + RK_U32 dlt_poc_msb_cycl1 : 16; + /* Delta_poc_msb_cycle_lt[2] */ + RK_U32 dlt_poc_msb_cycl2 : 16; + } reg093; + + /* + * OSD_INV_CFG + * Address offset: 0x0178 Access type: read and write + * OSD color inverse configuration + * + * Added in vepu540 + */ + struct { + /* + * OSD color inverse enable of chroma component, + * each bit controls corresponding region. + */ + RK_U32 osd_ch_inv_en : 8; + /* + * OSD color inverse expression type + * each bit controls corresponding region. + * 1'h0: AND; + * 1'h1: OR + */ + RK_U32 osd_itype : 8; + /* + * OSD color inverse expression switch for luma component + * each bit controls corresponding region. + * 1'h0: Expression need to determine the condition; + * 1'h1: Expression don't need to determine the condition; + */ + RK_U32 osd_lu_inv_msk : 8; + /* + * OSD color inverse expression switch for chroma component + * each bit controls corresponding region. + * 1'h0: Expression need to determine the condition; + * 1'h1: Expression don't need to determine the condition; + */ + RK_U32 osd_ch_inv_msk : 8; + } reg094; + + /* reg gap 095~100 */ + RK_U32 reg_095_100[6]; + + /* + * IPRD_CSTS + * Address offset: 0x0194 Access type: read and write + * Cost function configuration for intra prediction + */ + struct { + /* LUMA variance threshold to select intra prediction cost function. */ + RK_U32 vthd_y : 12; + RK_U32 reserved0 : 4; + /* CHROMA variance threshold to select intra prediction cost function. */ + RK_U32 vthd_c : 12; + RK_U32 reserved1 : 4; + } reg101; + + /* + * RDO_CFG_H264 + * Address offset: 0x0198 Access type: read and write + * H.264 RDO configuration + */ + struct { + /* Limit sub_mb_rect_size for low level. */ + RK_U32 rect_size : 1; + /* 4x4 sub MB enable. */ + RK_U32 inter_4x4 : 1; + /* Reserved */ + RK_U32 arb_sel : 1; + /* CAVLC syntax limit. */ + RK_U32 vlc_lmt : 1; + /* Chroma special candidates enable. */ + RK_U32 chrm_spcl : 1; + /* + * [7]: Disable intra4x4. + * [6]: Disable intra8x8. + * [5]: Disable intra16x16. + * [4]: Disable inter8x8 with T4. + * [3]: Disable inter8x8 with T8. + * [2]: Disable inter16x16 with T4. + * [1]: Disable inter16x16 with T8. + * [0]: Disable skip mode. + */ + RK_U32 rdo_mask : 8; + /* Chroma cost weight adjustment(KLUT) enable. */ + RK_U32 ccwa_e : 1; + /* + * Scale list selection. + * 1'h0: Flat scale list. + * 1'h1: Default scale list. + */ + RK_U32 scl_lst_sel : 1; + /* Anti-ring enable. */ + RK_U32 atr_e : 1; + /* Edge of anti-flicker, base on MB. the MBs inside edge should not influenced. */ + RK_U32 atf_edg : 2; + /* Block level anti-flicker enable. */ + RK_U32 atf_lvl_e : 1; + /* Intra mode anti-flicker enable. */ + RK_U32 atf_intra_e : 1; + /* + * Scale list selection. (for vepu540) + * 2'h0: Flat scale list. + * 2'h1: Default scale list. + * 2'h2: User defined. + * 2'h3: Reserved. + */ + RK_U32 scl_lst_sel_ : 2; + RK_U32 reserved : 9; + /* + * Rdo cost caculation expression for intra by using sad or satd. + * 1'h0: SATD; + * 1'h1: SAD; + */ + RK_U32 satd_byps_flg : 1; + } reg102; + + /* + * SYNT_NAL_H264 + * Address offset: 0x019C Access type: read and write + * NAL configuration for H.264 + */ + struct { + /* nal_ref_idc */ + RK_U32 nal_ref_idc : 2; + RK_U32 nal_unit_type : 5; + /* nal_unit_type */ + RK_U32 reserved : 25; + } reg103; + + /* + * SYNT_SPS_H264 + * Address offset: 0x01A0 Access type: read and write + * Sequence parameter set syntax configuration for H.264 + */ + struct { + /* log2_max_frame_num_minus4 */ + RK_U32 max_fnum : 4; + /* direct_8x8_inference_flag */ + RK_U32 drct_8x8 : 1; + /* log2_max_pic_order_cnt_lsb_minus4 */ + RK_U32 mpoc_lm4 : 4; + RK_U32 reserved : 23; + } reg104; + + /* + * SYNT_PPS_H264 + * Address offset: 0x01A4 Access type: read and write + * Picture parameter set configuration for H.264 + */ + struct { + /* entropy_coding_mode_flag */ + RK_U32 etpy_mode : 1; + /* transform_8x8_mode_flag */ + RK_U32 trns_8x8 : 1; + /* constrained_intra_pred_flag */ + RK_U32 csip_flag : 1; + /* num_ref_idx_l0_active_minus1 */ + RK_U32 num_ref0_idx : 2; + /* num_ref_idx_l1_active_minus1 */ + RK_U32 num_ref1_idx : 2; + /* pic_init_qp_minus26 + 26 */ + RK_U32 pic_init_qp : 6; + /* chroma_qp_index_offset */ + RK_U32 cb_ofst : 5; + /* second_chroma_qp_index_offset */ + RK_U32 cr_ofst : 5; + /* weight_pred_flag */ + RK_U32 wght_pred : 1; + /* deblocking_filter_control_present_flag */ + RK_U32 dbf_cp_flg : 1; + RK_U32 reserved : 7; + } reg105; + + /* + * SYNT_SLI0_H264 + * Address offset: 0x01A8 Access type: read and write + * Slice header configuration0 for H.264 + */ + struct { + /* slice_type: 0->P, 1->B, 2->I. */ + RK_U32 sli_type : 2; + /* pic_parameter_set_id */ + RK_U32 pps_id : 8; + /* direct_spatial_mv_pred_flag */ + RK_U32 drct_smvp : 1; + /* num_ref_idx_active_override_flag */ + RK_U32 num_ref_ovrd : 1; + /* cabac_init_idc */ + RK_U32 cbc_init_idc : 2; + RK_U32 reserved : 2; + /* frame_num */ + RK_U32 frm_num : 16; + } reg106; + + /* + * SYNT_SLI1_H264 + * Address offset: 0x01AC Access type: read and write + * Slice header configuration1 for H.264 + */ + struct { + /* idr_pid */ + RK_U32 idr_pic_id : 16; + /* pic_order_cnt_lsb */ + RK_U32 poc_lsb : 16; + } reg107; + + /* + * SYNT_SLI2_H264 + * Address offset: 0x01B0 Access type: read and write + * Slice header configuration2 for H.264 + */ + struct { + /* reordering_of_pic_nums_idc */ + RK_U32 rodr_pic_idx : 2; + /* ref_pic_list_reordering_flag_l0 */ + RK_U32 ref_list0_rodr : 1; + /* slice_beta_offset_div2 */ + RK_U32 sli_beta_ofst : 4; + /* slice_alpha_c0_offset_div2 */ + RK_U32 sli_alph_ofst : 4; + /* disable_deblocking_filter_idc */ + RK_U32 dis_dblk_idc : 2; + RK_U32 reserved : 3; + /* abs_diff_pic_num_minus1/long_term_pic_num */ + RK_U32 rodr_pic_num : 16; + } reg108; + + /* + * SYNT_REFM0_H264 + * Address offset: 0x01B4 Access type: read and write + * Reference frame mark0 for H.264 + */ + struct { + /* no_output_of_prior_pics_flag */ + RK_U32 nopp_flg : 1; + /* long_term_reference_flag */ + RK_U32 ltrf_flg : 1; + /* adaptive_ref_pic_marking_mode_flag */ + RK_U32 arpm_flg : 1; + /* A No.4 MMCO should be executed firstly if mmo4_pre is 1 */ + RK_U32 mmco4_pre : 1; + /* memory_management_control_operation */ + RK_U32 mmco_type0 : 3; + /* + * MMCO parameters which have different meanings according to different mmco_parm0 valus. + * difference_of_pic_nums_minus1 for mmco_parm0 equals 0 or 3. + * long_term_pic_num for mmco_parm0 equals 2. + * long_term_frame_idx for mmco_parm0 equals 6. + * max_long_term_frame_idx_plus1 for mmco_parm0 equals 4. + */ + RK_U32 mmco_parm0 : 16; + /* memory_management_control_operation[1] */ + RK_U32 mmco_type1 : 3; + /* memory_management_control_operation[2] */ + RK_U32 mmco_type2 : 3; + RK_U32 reserved : 3; + } reg109; + + /* + * SYNT_REFM1_H264 + * Address offset: 0x01B8 Access type: read and write + * Reference frame mark1 for H.264 + */ + struct { + /* + * MMCO parameters which have different meanings according to different mmco_parm1 valus. + * difference_of_pic_nums_minus1 for mmco_parm1 equals 0 or 3. + * long_term_pic_num for mmco_parm1 equals 2. + * long_term_frame_idx for mmco_parm1 equals 6. + * max_long_term_frame_idx_plus1 for mmco_parm1 equals 4. + */ + RK_U32 mmco_parm1 : 16; + /* + * MMCO parameters which have different meanings according to different mmco_parm2 valus. + * difference_of_pic_nums_minus1 for mmco_parm2 equals 0 or 3. + * long_term_pic_num for mmco_parm2 equals 2. + * long_term_frame_idx for mmco_parm2 equals 6. + * max_long_term_frame_idx_plus1 for mmco_parm2 equals 4. + */ + RK_U32 mmco_parm2 : 16; + } reg110; + + /* reg gap 111 */ + RK_U32 reg_111; + + /* + * OSD_CFG + * Address offset: 0x01C0 Access type: read and write + * OSD configuration + */ + struct { + /* OSD region enable, each bit controls corresponding OSD region. */ + RK_U32 osd_e : 8; + /* OSD inverse color enable, each bit controls corresponding region. */ + RK_U32 osd_inv_e : 8; + /* + * OSD palette clock selection. + * 1'h0: Configure bus clock domain. + * 1'h1: Core clock domain. + */ + RK_U32 osd_plt_cks : 1; + /* + * OSD palette type. + * 1'h1: Default type. + * 1'h0: User defined type. + */ + RK_U32 osd_plt_typ : 1; + RK_U32 reserved : 14; + } reg112; + + /* + * OSD_INV + * Address offset: 0x01C4 Access type: read and write + * OSD color inverse configuration + */ + struct { + /* Color inverse theshold for OSD region0. */ + RK_U32 osd_ithd_r0 : 4; + /* Color inverse theshold for OSD region1. */ + RK_U32 osd_ithd_r1 : 4; + /* Color inverse theshold for OSD region2. */ + RK_U32 osd_ithd_r2 : 4; + /* Color inverse theshold for OSD region3. */ + RK_U32 osd_ithd_r3 : 4; + /* Color inverse theshold for OSD region4. */ + RK_U32 osd_ithd_r4 : 4; + /* Color inverse theshold for OSD region5. */ + RK_U32 osd_ithd_r5 : 4; + /* Color inverse theshold for OSD region6. */ + RK_U32 osd_ithd_r6 : 4; + /* Color inverse theshold for OSD region7. */ + RK_U32 osd_ithd_r7 : 4; + } reg113; + + /* + * SYNT_REFM2_H264 + * Address offset: 0x01C8 Access type: read and write + * Reference frame mark2 for H.264 + */ + struct { + /* long_term_frame_idx[0] (when mmco equal 3) */ + RK_U32 long_term_frame_idx0 : 4; + /* long_term_frame_idx[1] (when mmco equal 3) */ + RK_U32 long_term_frame_idx1 : 4; + /* long_term_frame_idx[2] (when mmco equal 3) */ + RK_U32 long_term_frame_idx2 : 4; + RK_U32 reserved : 20; + } reg114; + + /* + * SYNT_REFM3 + * Address offset: 0x01CC Access type: read and write + * Reference frame mark3 for HEVC + */ + RK_U32 reg115; + + /* + * OSD_POS + * Address offset: 0x01D0~0x01EC Access type: read and write + * OSD region position + */ + struct { + Vepu541OsdPos osd_pos[8]; + } reg116_123; + + /* + * ADR_OSD + * Address offset: 0x01F0~0x20C Access type: read and write + * Base address for OSD region, 16B aligned + */ + struct { + RK_U32 osd_addr[8]; + } reg124_131; + + /* + * ST_BSL + * Address offset: 0x210 Access type: read only + * Bit stream length for current frame + */ + struct { + /* Bit stream length for current frame. */ + RK_U32 bs_lgth : 27; + RK_U32 reserved : 5; + } reg132; + + /* + * ST_SSE_L32 + * Address offset: 0x214 Access type: read only + * Low 32 bits of encoding distortion (SSE) + */ + struct { + RK_U32 sse_l32; + } reg133; + + /* + * ST_SSE_QP + * Address offset: 0x218 Access type: read only + * High 8 bits of encoding distortion (SSE) and sum of QP for the encoded frame + */ + struct { + /* Sum of QP for the encoded frame. */ + RK_U32 qp_sum : 22; + RK_U32 reserved : 2; + /* High bits of encoding distortion(SSE). */ + RK_U32 sse_h8 : 8; + } reg134; + + /* + * ST_SAO + * Address offset: 0x21C Access type: read only + * Number of CTUs which adjusted by SAO + */ + struct { + /* Number of CTUs whose CHROMA component are adjusted by SAO. */ + RK_U32 sao_cnum : 12; + /* Number of CTUs whose LUMA component are adjusted by SAO. */ + RK_U32 sao_ynum : 12; + RK_U32 reserved : 8; + } reg135; + + /* reg gap 136~137 */ + RK_U32 reg_136_137[2]; + + /* + * ST_ENC + * Address offset: 0x228 Access type: read only + * VEPU working status + */ + struct { + /* + * VEPU working status. + * 2'h0: Idle. + * 2'h1: Working in register conifguration mode. + * 2'h2: Working in link table configuration mode. + */ + RK_U32 st_enc : 2; + /* + * Status of safe clear. + * 1'h0: Safe clear is finished or not started. + * 1'h1: VEPU is performing safe clear. + */ + RK_U32 st_sclr : 1; + RK_U32 reserved : 29; + } reg138; + + /* + * ST_LKT + * Address offset: 0x22C Access type: read only + * Status of link table mode encoding + */ + struct { + /* Number of frames has been encoded since link table mode started. */ + RK_U32 fnum_enc : 8; + /* Number of frames has been configured since link table mode started. */ + RK_U32 fnum_cfg : 8; + /* + * Number of frames has been encoded since link table mode started, + * updated only when corresponding link table node send interrupt + * (VEPU_ENC_PIC_node_int==1). + */ + RK_U32 fnum_int : 8; + RK_U32 reserved : 8; + } reg139; + + /* + * ST_NADR + * Address offset: 0x230 Access type: read only + * Address of the processing link table node + */ + struct { + /* High 28 bits of the address for the processing linke table node. */ + RK_U32 node_addr; + } reg140; + + /* + * ST_BSB + * Address offset: 0x234 Access type: read only + * Status of bit stream buffer + */ + struct { + /* High 28 bits of bit stream buffer write address. */ + RK_U32 bsbw_addr; + } reg141; + + /* + * ST_BUS + * Address offset: 0x238 Access type: read only + * VEPU bus status + */ + struct { + /* + * AXI write response idle. + * [6]: Reconstructed picture channel (AXI0_WID==5) + * [5]: ME information channel (AXI0_WID==4) + * [4]: Co-located Mv channel (AXI0_WID==3) + * [3]: Down-sampled picture channel (AXI0_WID==2) + * [2]: Bit stream channel (AXI0_WID==1) + * [1]: Link table node channel (AXI0_WID==0) + * [0]: Reserved + */ + RK_U32 axib_idl : 7; + /* + * AXI write response outstanding overflow. + * [6]: Reconstructed picture channel (AXI0_WID==5) + * [5]: ME information channel (AXI0_WID==4) + * [4]: Co-located Mv channel (AXI0_WID==3) + * [3]: Down-sampled picture channel (AXI0_WID==2) + * [2]: Bit stream channel (AXI0_WID==1) + * [1]: Link table node channel (AXI0_WID==0) + * [0]: Reserved. + */ + RK_U32 axib_ovfl : 7; + /* + * AXI write response error. + * [6]: Reconstructed picture channel (AXI0_WID==5) + * [5]: ME information channel (AXI0_WID==4) + * [4]: Co-located Mv channel (AXI0_WID==3) + * [3]: Down-sampled picture channel (AXI0_WID==2) + * [2]: Bit stream channel (AXI0_WID==1) + * [1]: Link table node channel (AXI0_WID==0) + * [0]: Reserved. + */ + RK_U32 axib_err : 7; + /* + * AXI read error. + * [5]: ROI configuration (AXI0_ARID==7) + * [4]: Down-sampled picture (AXI0_ARID==6) + * [3]: Co-located Mv (AXI0_ARID==5) + * [2]: Link table (AXI0_ARID==4) + * [1]: Reference picture (AXI0_ARID==1,2,3,8) + * [0]: Video source load (AXI1) + */ + RK_U32 axir_err : 6; + RK_U32 reserved : 5; + } reg142; + + /* + * ST_SNUM + * Address offset: 0x23C Access type: read only + * Slice number status + */ + struct { + /* Number for slices has been encoded and not read out (by reading ST_SLEN). */ + RK_U32 sli_num : 6; + RK_U32 reserved : 30; + } reg143; + + /* + * ST_SLEN + * Address offset: 0x240 Access type: read only + * Status of slice length + */ + struct { + /* Byte length for the earlist encoded slice which has not been read out( by reading VEPU_ST_SLEN). */ + RK_U32 sli_len : 25; + RK_U32 reserved : 7; + } reg144; + + /* + * ST_PNUM_P64 + * Address offset: 0x244 Access type: read only + * Number of 64x64 inter predicted blocks + */ + struct { + /* Number of 64x64 inter predicted blocks. */ + RK_U32 pnum_p64 : 12; + RK_U32 reserved : 20; + } reg145; + + /* + * ST_PNUM_P32 + * Address offset: 0x248 Access type: read only + * Number of 32x32 inter predicted blocks + */ + struct { + /* Number of 32x32 inter predicted blocks. */ + RK_U32 pnum_p32 : 14; + RK_U32 reserved : 18; + } reg146; + + /* + * ST_PNUM_P16 + * Address offset: 0x24C Access type: read only + * Number of 16x16 inter predicted blocks + */ + struct { + /* Number of 16x16 inter predicted blocks. */ + RK_U32 pnum_p16 : 16; + RK_U32 reserved : 16; + } reg147; + + /* + * ST_PNUM_P8 + * Address offset: 0x250 Access type: read only + * Number of 8x8 inter predicted blocks + */ + struct { + /* Number of 8x8 inter predicted blocks. */ + RK_U32 pnum_p8 : 18; + RK_U32 reserved : 14; + } reg148; + + /* + * ST_PNUM_I32 + * Address offset: 0x254 Access type: read only + * Number of 32x32 intra predicted blocks + */ + struct { + /* Number of 32x32 intra predicted blocks. */ + RK_U32 pnum_i32 : 14; + RK_U32 reserved : 18; + } reg149; + + /* + * ST_PNUM_I16 + * Address offset: 0x258 Access type: read only + * Number of 16x16 intra predicted blocks + */ + struct { + /* Number of 16x16 intra predicted blocks. */ + RK_U32 pnum_i16 : 16; + RK_U32 reserved : 16; + } reg150; + + /* + * ST_PNUM_I8 + * Address offset: 0x25C Access type: read only + * Number of 8x8 intra predicted blocks + */ + struct { + /* Number of 8x8 intra predicted blocks. */ + RK_U32 pnum_i8 : 18; + RK_U32 reserved : 14; + } reg151; + + /* + * ST_PNUM_I4 + * Address offset: 0x260 Access type: read only + * Number of 4x4 intra predicted blocks + */ + struct { + /* Number of 4x4 intra predicted blocks. */ + RK_U32 pnum_i4 : 20; + RK_U32 reserved : 12; + } reg152; + + /* + * ST_B8_QP0~51 + * Address offset: 0x264~0x330 Access type: read only + * Number of block8x8s with QP=0~51 + */ + struct { + /* + * Number of block8x8s with QP value. + * HEVC CUs of which size are bigger that 8x8 are considered as + * (CU_size/8)*(CU_size/8) clock8x8s; + * while H.264 MB is considered as 4 block8x8s. + */ + Vepu541B8NumQp num_qp[52]; + } reg153_204; + + /* + * ST_CPLX_TMP + * Address offset: 0x334 Access type: read only + * Temporal complexity(MADP) for current encoding and reference frame + */ + struct { + /* Mean absolute differences between current encoding and reference frame. */ + RK_U32 madp; + } reg205; + + /* + * ST_BNUM_CME + * Address offset: 0x338 Access type: read only + * Number of CME blocks in frame. + * H.264: number CME blocks (4 MBs) in 16x64 aligned extended frame, + * except for the CME blocks configured as force intra. + * HEVC : number CME blocks (CTU) in 64x64 aligned extended frame, + * except for the CME blocks configured as force intra. + */ + struct { + /* Number of CTU (HEVC: 64x64; H.264: 64x16) for CME inter-frame prediction. */ + RK_U32 num_ctu : 16; + RK_U32 reserved : 16; + } reg206; + + /* + * ST_CPLX_SPT + * Address offset: 0x33C Access type: read only + * Spatial complexity(MADI) for current encoding frame + */ + struct { + /* Mean absolute differences for current encoding frame. */ + RK_U32 madi; + } reg207; + + /* + * ST_BNUM_B16 + * Address offset: 0x340 Access type: read only + * Number of valid 16x16 blocks for one frame. + */ + struct { + /* Number of valid 16x16 blocks for one frame. */ + RK_U32 num_b16; + } reg208; +} Vepu541H264eRegSet; + +/* return register is a subset of the whole register. */ +typedef struct Vepu541H264eRegRet_t { + /* + * INT_STA + * Address offset: 0x001c Access type: read and write, write one to clear + * VEPU interrupt status + */ + struct { + /* One frame encode finish interrupt status */ + RK_U32 enc_done_sta : 1; + /* Link table finish interrupt status */ + RK_U32 lkt_done_sta : 1; + /* Safe clear finish interrupt status */ + RK_U32 sclr_done_sta : 1; + /* One slice encode finish interrupt status */ + RK_U32 enc_slice_done_sta : 1; + /* Bit stream overflow interrupt status */ + RK_U32 oflw_done_sta : 1; + /* AXI write response fifo full interrupt status */ + RK_U32 brsp_done_sta : 1; + /* AXI write response channel error interrupt status */ + RK_U32 berr_done_sta : 1; + /* AXI read channel error interrupt status */ + RK_U32 rerr_done_sta : 1; + /* timeout error interrupt status */ + RK_U32 wdg_done_sta : 1; + RK_U32 reserved : 23; + } hw_status; /* reg007 */ + + /* + * ST_BSL + * Address offset: 0x210 Access type: read only + * Bit stream length for current frame + */ + struct { + /* Bit stream length for current frame. */ + RK_U32 bs_lgth : 27; + RK_U32 reserved : 5; + } st_bsl; /* reg132 */ + + /* + * ST_SSE_L32 + * Address offset: 0x214 Access type: read only + * Low 32 bits of encoding distortion (SSE) + */ + struct { + RK_U32 sse_l32; + } st_sse_l32; /* reg133 */ + + /* + * ST_SSE_QP + * Address offset: 0x218 Access type: read only + * High 8 bits of encoding distortion (SSE) and sum of QP for the encoded frame + */ + struct { + /* Sum of QP for the encoded frame. */ + RK_U32 qp_sum : 22; + RK_U32 reserved : 2; + /* High bits of encoding distortion(SSE). */ + RK_U32 sse_h8 : 8; + } st_sse_qp; /* reg134 */ + + /* + * ST_SAO + * Address offset: 0x21C Access type: read only + * Number of CTUs which adjusted by SAO + */ + struct { + /* Number of CTUs whose CHROMA component are adjusted by SAO. */ + RK_U32 sao_cnum : 12; + /* Number of CTUs whose LUMA component are adjusted by SAO. */ + RK_U32 sao_ynum : 12; + RK_U32 reserved : 8; + } st_sao; /* reg135 */ + + /* reg gap 136~137 */ + RK_U32 reg_136_137[2]; + + /* + * ST_ENC + * Address offset: 0x228 Access type: read only + * VEPU working status + */ + struct { + /* + * VEPU working status. + * 2'h0: Idle. + * 2'h1: Working in register conifguration mode. + * 2'h2: Working in link table configuration mode. + */ + RK_U32 st_enc : 2; + /* + * Status of safe clear. + * 1'h0: Safe clear is finished or not started. + * 1'h1: VEPU is performing safe clear. + */ + RK_U32 st_sclr : 1; + RK_U32 reserved : 29; + } st_enc; /* reg138 */ + + /* + * ST_LKT + * Address offset: 0x22C Access type: read only + * Status of link table mode encoding + */ + struct { + /* Number of frames has been encoded since link table mode started. */ + RK_U32 fnum_enc : 8; + /* Number of frames has been configured since link table mode started. */ + RK_U32 fnum_cfg : 8; + /* + * Number of frames has been encoded since link table mode started, + * updated only when corresponding link table node send interrupt + * (VEPU_ENC_PIC_node_int==1). + */ + RK_U32 fnum_int : 8; + RK_U32 reserved : 8; + } st_lkt; /* reg139 */ + + /* + * ST_NADR + * Address offset: 0x230 Access type: read only + * Address of the processing link table node + */ + struct { + /* High 28 bits of the address for the processing linke table node. */ + RK_U32 node_addr; + } ST_NADR; /* reg140 */ + + /* + * ST_BSB + * Address offset: 0x234 Access type: read only + * Status of bit stream buffer + */ + struct { + /* High 28 bits of bit stream buffer write address. */ + RK_U32 bsbw_addr; + } st_bsb; /* reg141 */ + + /* + * ST_BUS + * Address offset: 0x238 Access type: read only + * VEPU bus status + */ + struct { + /* + * AXI write response idle. + * [6]: Reconstructed picture channel (AXI0_WID==5) + * [5]: ME information channel (AXI0_WID==4) + * [4]: Co-located Mv channel (AXI0_WID==3) + * [3]: Down-sampled picture channel (AXI0_WID==2) + * [2]: Bit stream channel (AXI0_WID==1) + * [1]: Link table node channel (AXI0_WID==0) + * [0]: Reserved + */ + RK_U32 axib_idl : 7; + /* + * AXI write response outstanding overflow. + * [6]: Reconstructed picture channel (AXI0_WID==5) + * [5]: ME information channel (AXI0_WID==4) + * [4]: Co-located Mv channel (AXI0_WID==3) + * [3]: Down-sampled picture channel (AXI0_WID==2) + * [2]: Bit stream channel (AXI0_WID==1) + * [1]: Link table node channel (AXI0_WID==0) + * [0]: Reserved. + */ + RK_U32 axib_ovfl : 7; + /* + * AXI write response error. + * [6]: Reconstructed picture channel (AXI0_WID==5) + * [5]: ME information channel (AXI0_WID==4) + * [4]: Co-located Mv channel (AXI0_WID==3) + * [3]: Down-sampled picture channel (AXI0_WID==2) + * [2]: Bit stream channel (AXI0_WID==1) + * [1]: Link table node channel (AXI0_WID==0) + * [0]: Reserved. + */ + RK_U32 axib_err : 7; + /* + * AXI read error. + * [5]: ROI configuration (AXI0_ARID==7) + * [4]: Down-sampled picture (AXI0_ARID==6) + * [3]: Co-located Mv (AXI0_ARID==5) + * [2]: Link table (AXI0_ARID==4) + * [1]: Reference picture (AXI0_ARID==1,2,3,8) + * [0]: Video source load (AXI1) + */ + RK_U32 axir_err : 6; + RK_U32 reserved : 5; + } st_bus; /* reg142 */ + + /* + * ST_SNUM + * Address offset: 0x23C Access type: read only + * Slice number status + */ + RK_U32 st_slice_number; + + /* + * ST_SLEN + * Address offset: 0x240 Access type: read only + * Status of slice length + */ + RK_U32 st_slice_length; + + /* + * ST_PNUM_P64 + * Address offset: 0x244 Access type: read only + * Number of 64x64 inter predicted blocks + */ + RK_U32 st_lvl64_inter_num; + + /* + * ST_PNUM_P32 + * Address offset: 0x248 Access type: read only + * Number of 32x32 inter predicted blocks + */ + RK_U32 st_lvl32_inter_num; + + /* + * ST_PNUM_P16 + * Address offset: 0x24C Access type: read only + * Number of 16x16 inter predicted blocks + */ + RK_U32 st_lvl16_inter_num; + + /* + * ST_PNUM_P8 + * Address offset: 0x250 Access type: read only + * Number of 8x8 inter predicted blocks + */ + RK_U32 st_lvl8_inter_num; + + /* + * ST_PNUM_I32 + * Address offset: 0x254 Access type: read only + * Number of 32x32 intra predicted blocks + */ + RK_U32 st_lvl32_intra_num; + + /* + * ST_PNUM_I16 + * Address offset: 0x258 Access type: read only + * Number of 16x16 intra predicted blocks + */ + RK_U32 st_lvl16_intra_num; + + /* + * ST_PNUM_I8 + * Address offset: 0x25C Access type: read only + * Number of 8x8 intra predicted blocks + */ + RK_U32 st_lvl8_intra_num; + + /* + * ST_PNUM_I4 + * Address offset: 0x260 Access type: read only + * Number of 4x4 intra predicted blocks + */ + RK_U32 st_lvl4_intra_num; + + /* + * ST_B8_QP0~51 + * Address offset: 0x264~0x330 Access type: read only + * Number of block8x8s with QP=0~51 + */ + RK_U32 st_cu_num_qp[52]; + + /* + * ST_CPLX_TMP + * Address offset: 0x334 Access type: read only + * Temporal complexity(MADP) for current encoding and reference frame + */ + RK_U32 st_madp; + + /* + * ST_BNUM_CME + * Address offset: 0x338 Access type: read only + * Number of CME blocks in frame. + * H.264: number CME blocks (4 MBs) in 16x64 aligned extended frame, + * except for the CME blocks configured as force intra. + * HEVC : number CME blocks (CTU) in 64x64 aligned extended frame, + * except for the CME blocks configured as force intra. + */ + RK_U32 st_ctu_num; + + /* + * ST_CPLX_SPT + * Address offset: 0x33C Access type: read only + * Spatial complexity(MADI) for current encoding frame + */ + RK_U32 st_madi; + + /* + * ST_BNUM_B16 + * Address offset: 0x340 Access type: read only + * Number of valid 16x16 blocks for one frame. + */ + RK_U32 st_mb_num; +} Vepu541H264eRegRet; + +#endif /* HAL_H264E_VEPU541_REG_H */ diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu541_reg_l2.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu541_reg_l2.h new file mode 100644 index 000000000..0b896b2b3 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu541_reg_l2.h @@ -0,0 +1,412 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU541_REG_L2_H +#define HAL_H264E_VEPU541_REG_L2_H + +#include "rk_type.h" + +/* + * L2CFG_ADDR + * Address offset: 0x3F0 Access type: read and write + * Level2 configuration address + */ +/* + * L2CFG_WDATA + * Address offset: 0x3F4 Access type: read and write + * L2 configuration write data + */ +/* + * L2 configuration write data. + * + * Single access: + * write address to VEPU_L2CFG_ADDR then write data to VEPU_L2CFG_WDATA. + * + * Burst access: + * write the start address to VEPU_L2CFG_ADDR then write datas + * (to VEPU_L2CFG_WDATA) consecutively. + * Address will be auto increased after write VEPU_L2CFG_WDATA, + * no need to configure VEPU_L2CFG_ADDR. + */ + +/* + * L2CFG_RDATA + * Address offset: 0x3F8 Access type: read and write + * L2 configuration read data + */ + +typedef struct Vepu541H264eRegL2Set_t { + /* + * IPRD_TTHDY4_0_H264 ~ IPRD_TTHDY4_1_H264 + * Address: 0x0004~0x0008 Access type: read and write + * The texture thredsholds for H.264 LUMA 4x4 intra prediction + */ + RK_U16 iprd_tthdy4[4]; + + /* + * IPRD_TTHDC8_0_H264 ~ IPRD_TTHDC8_1_H264 + * Address: 0x000C~0x0010 Access type: read and write + * The texture threshold for H.264 CHROMA 8x8 intra prediction. + */ + RK_U16 iprd_tthdc8[4]; + + /* + * IPRD_TTHDY8_0_H264 ~ IPRD_TTHDY8_1_H264 + * Address: 0x0014~0x0018 Access type: read and write + * The texture thredsholds for H.264 LUMA 8x8 intra prediction + */ + RK_U16 iprd_tthdy8[4]; + + /* + * IPRD_TTHD_UL_H264 + * Address: 0x001C Access type: read and write + * Texture thredsholds of up and left MB for H.264 LUMA intra prediction. + */ + RK_U32 iprd_tthd_ul; + + /* + * IPRD_WGTY8_H264 + * Address: 0x0020 Access type: read and write + * Weights of the cost for H.264 LUMA 8x8 intra prediction + */ + RK_U8 iprd_wgty8[4]; + + /* + * IPRD_WGTY4_H264 + * Address: 0x0024 Access type: read and write + * Weights of the cost for H.264 LUMA 4x4 intra prediction + */ + RK_U8 iprd_wgty4[4]; + + /* + * IPRD_WGTY16_H264 + * Address: 0x0028 Access type: read and write + * Weights of the cost for H.264 LUMA 16x16 intra prediction + */ + RK_U8 iprd_wgty16[4]; + + /* + * IPRD_WGTC8_H264 + * Address: 0x002C Access type: read and write + * Weights of the cost for H.264 CHROMA 8x8 intra prediction + */ + RK_U8 iprd_wgtc8[4]; + + /* + * QNT_BIAS_COMB + * Address: 0x0030 Access type: read and write + * Quantization bias for H.264 and HEVC. + */ + struct { + /* Quantization bias for HEVC and H.264 I frame. */ + RK_U32 qnt_bias_i : 10; + /* Quantization bias for HEVC and H.264 P frame. */ + RK_U32 qnt_bias_p : 10; + RK_U32 reserved : 12; + } qnt_bias_comb; + + /* + * ATR_THD0_H264 + * Address: 0x0034 Access type: read and write + * H.264 anti ringing noise threshold configuration0. + */ + struct { + /* The 1st threshold for H.264 anti-ringing-noise. */ + RK_U32 atr_thd0 : 12; + RK_U32 reserved0 : 4; + /* The 2nd threshold for H.264 anti-ringing-noise. */ + RK_U32 atr_thd1 : 12; + RK_U32 reserved1 : 4; + } atr_thd0_h264; + + /* + * ATR_THD1_H264 + * Address: 0x0038 Access type: read and write + * H.264 anti ringing noise threshold configuration1. + */ + struct { + /* The 3rd threshold for H.264 anti-ringing-noise. */ + RK_U32 atr_thd2 : 12; + RK_U32 reserved0 : 4; + /* QP threshold of P frame for H.264 anti-ringing-nois. */ + RK_U32 atr_qp : 6; + RK_U32 reserved1 : 10; + } atr_thd1_h264; + + /* + * ATR_WGT16_H264 + * Address: 0x003C Access type: read and write + * Weights of 16x16 cost for H.264 anti ringing noise. + */ + struct { + /* The 1st weight for H.264 16x16 anti-ringing-noise. */ + RK_U32 atr_lv16_wgt0 : 8; + /* The 2nd weight for H.264 16x16 anti-ringing-noise. */ + RK_U32 atr_lv16_wgt1 : 8; + /* The 3rd weight for H.264 16x16 anti-ringing-noise. */ + RK_U32 atr_lv16_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt16_h264; + + /* + * ATR_WGT8_H264 + * Address: 0x0040 Access type: read and write + * Weights of 8x8 cost for H.264 anti ringing noise. + */ + struct { + /* The 1st weight for H.264 8x8 anti-ringing-noise. */ + RK_U32 atr_lv8_wgt0 : 8; + /* The 2nd weight for H.264 8x8 anti-ringing-noise. */ + RK_U32 atr_lv8_wgt1 : 8; + /* The 3rd weight for H.264 8x8 anti-ringing-noise. */ + RK_U32 atr_lv8_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt8_h264; + + /* + * ATR_WGT4_H264 + * Address: 0x0044 Access type: read and write + * Weights of 4x4 cost for H.264 anti ringing noise. + */ + struct { + /* The 1st weight for H.264 4x4 anti-ringing-noise. */ + RK_U32 atr_lv4_wgt0 : 8; + /* The 2nd weight for H.264 4x4 anti-ringing-noise. */ + RK_U32 atr_lv4_wgt1 : 8; + /* The 3rd weight for H.264 4x4 anti-ringing-noise. */ + RK_U32 atr_lv4_wgt2 : 8; + RK_U32 reserved : 8; + } atr_wgt4_h264; + + /* + * ATF_TTHD0_H264 ~ ATF_TTHD1_H264 + * Address: 0x0048~0x004C Access type: read and write + * Texture threshold configuration for H.264 anti-flicker + */ + RK_U16 atf_tthd[4]; + + /* + * ATF_STHD0_H264 + * Address: 0x0050 Access type: read and write + * (CME) SAD threshold configuration1 for H.264 anti-flicker. + */ + struct { + /* (CME) SAD threshold0 of texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_sthd_10 : 14; + RK_U32 reserved0 : 2; + /* Max (CME) SAD threshold for H.264 anti-flicker. */ + RK_U32 atf_sthd_max : 14; + RK_U32 reserved1 : 2; + } atf_sthd0_h264; + + /* + * ATF_STHD1_H264 + * Address: 0x0054 Access type: read and write + * (CME) SAD threshold configuration1 for H.264 anti-flicker. + */ + struct { + /* (CME) SAD threshold1 of texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_sthd_11 : 14; + RK_U32 reserved0 : 2; + /* (CME) SAD threshold0 of texture interval2 for H.264 anti-flicker. */ + RK_U32 atf_sthd_20 : 14; + RK_U32 reserved1 : 2; + } atf_sthd1_h264; + + /* + * ATF_WGT0_H264 + * Address: 0x0058 Access type: read and write + * Weight configuration0 for H.264 anti-flicker. + */ + struct { + /* The 1st weight in texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_wgt10 : 9; + RK_U32 reserved0 : 7; + /* The 2nd weight in texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_wgt11 : 9; + RK_U32 reserved1 : 7; + } atf_wgt0_h264; + + /* + * ATF_WGT1_H264 + * Address: 0x005C Access type: read and write + * Weight configuration1 for H.264 anti-flicker. + */ + struct { + /* The 3rd weight in texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_wgt12 : 9; + RK_U32 reserved0 : 7; + /* The 1st weight in texture interval2 for H.264 anti-flicker. */ + RK_U32 atf_wgt20 : 9; + RK_U32 reserved1 : 7; + } atf_wgt1_h264; + + /* + * ATF_WGT2_H264 + * Address: 0x0060 Access type: read and write + * Weight configuration2 for H.264 anti-flicker. + */ + struct { + /* The 2nd weight in texture interval2 for H.264 anti-flicker. */ + RK_U32 atf_wgt21 : 9; + RK_U32 reserved0 : 7; + /* The weight in texture interval3 for H.264 anti-flicker. */ + RK_U32 atf_wgt30 : 9; + RK_U32 reserved1 : 7; + } atf_wgt2_h264; + + /* + * ATF_OFST0_H264 + * Address: 0x0064 Access type: read and write + * Offset configuration0 for H.264 anti-flicker. + */ + struct { + /* The 1st offset in texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_ofst10 : 14; + RK_U32 reserved0 : 2; + /* The 2nd offset in texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_ofst11 : 14; + RK_U32 reserved1 : 2; + } atf_ofst0_h264; + + /* + * ATF_OFST1_H264 + * Address: 0x0068 Access type: read and write + * Offset configuration1 for H.264 anti-flicker. + */ + struct { + /* The 3rd offset in texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_ofst12 : 14; + RK_U32 reserved0 : 2; + /* The 1st offset in texture interval2 for H.264 anti-flicker. */ + RK_U32 atf_ofst20 : 14; + RK_U32 reserved1 : 2; + } atf_ofst1_h264; + + /* + * ATF_OFST2_H264 + * Address: 0x006C Access type: read and write + * Offset configuration2 for H.264 anti-flicker. + */ + struct { + /* The 2nd offset in texture interval1 for H.264 anti-flicker. */ + RK_U32 atf_ofst21 : 14; + RK_U32 reserved0 : 2; + /* The offset in texture interval3 for H.264 anti-flicker. */ + RK_U32 atf_ofst30 : 14; + RK_U32 reserved1 : 2; + } atf_ofst2_h264; + + /* + * IPRD_WGT_QP0_HEVC ~ IPRD_WGT_QP51_HEVC + * Address: 0x0070 ~ 0x013C Access type: read and write + * Weight of SATD cost when QP is 0~51 for HEVC intra prediction. + */ + RK_U32 iprd_wgt_qp[52]; + + /* + * RDO_WGTA_QP0_COMB ~ RDO_WGTA_QP51_COMB + * Address: 0x0140 ~ 0x020C Access type: read and write + * Weight of group A for HEVC and H.264 RDO mode decision when QP is 0~51. + */ + RK_U32 wgt_qp_grpa[52]; + + /* + * RDO_WGTB_QP0_COMB ~ RDO_WGTB_QP51_COMB + * Address: 0x0210 ~ 0x02DC Access type: read and write + * Weight of group B for HEVC and H.264 RDO mode decision when QP is 0~51. + */ + RK_U32 wgt_qp_grpb[52]; + + /* + * MADI_CFG + * Address: 0x02E0 Access type: read and write + * MADI configuration for CU32 and CU64. + */ + /* + * MADI generation mode for CU32 and CU64. + * 1'h0: Follow 32x32 and 64x64 MADI functions. + * 1'h1: Calculated by the mean of corresponding CU16 MADIs. + */ + RK_U32 madi_mode; + + /* + * AQ_TTHD0 ~ AQ_TTHD3 + * Address: 0x02E4 ~ 0x02F0 Access type: read and write + * Texture threshold configuration for adaptive QP adjustment. + */ + /* Texture threshold for adaptive QP adjustment. */ + RK_U8 aq_tthd[16]; + + /* + * AQ_STP0 ~ AQ_STP3 + * Address: 0x02F4 ~ 0x300 Access type: read and write + * Adjustment step configuration0 for adaptive QP adjustment. + */ + /* + * MADI generation mode for CU32 and CU64. + * 1'h0: Follow 32x32 and 64x64 MADI functions. + * 1'h1: Calculated by the mean of corresponding CU16 MADIs. + */ + /* QP adjust step when current texture strength is between n-1 and n step. */ + RK_S8 aq_step[16]; + + /* + * RME_MVD_PNSH_H264 + * Address: 0x0304 Access type: read and write + * RME MVD(motion vector difference) cost penalty, H.264 only. + */ + struct { + /* MVD cost penalty enable. */ + RK_U32 mvd_pnlt_e : 1; + /* MVD cost penalty coefficienc. */ + RK_U32 mvd_pnlt_coef : 5; + /* MVD cost penalty constant. */ + RK_U32 mvd_pnlt_cnst : 14; + /* Low threshold of the MVs which should be punished. */ + RK_U32 mvd_pnlt_lthd : 4; + /* High threshold of the MVs which should be punished. */ + RK_U32 mvd_pnlt_hthd : 4; + RK_U32 reserved : 4; + } rme_mvd_penalty; + + /* + * ATR1_THD0_H264 + * Address: 0x0308 Access type: read and write + * H.264 anti ringing noise threshold configuration0 of group1. + */ + struct { + /* The 1st threshold for H.264 anti-ringing-noise of group1. */ + RK_U32 atr1_thd0 : 12; + RK_U32 reserved0 : 4; + /* The 2nd threshold for H.264 anti-ringing-noise of group1. */ + RK_U32 atr1_thd1 : 12; + RK_U32 reserved1 : 4; + } atr1_thd0_h264; + + /* + * ATR1_THD0_H264 + * Address: 0x030C Access type: read and write + * H.264 anti ringing noise threshold configuration1 of group1. + */ + struct { + /* The 3rd threshold for H.264 anti-ringing-noise of group1. */ + RK_U32 atr1_thd2 : 12; + RK_U32 reserved0 : 20; + } atr1_thd1_h264; +} Vepu541H264eRegL2Set; + +#endif /* HAL_H264E_VEPU541_REG_L2_H */ diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu580.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu580.c new file mode 100644 index 000000000..998406975 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu580.c @@ -0,0 +1,2579 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264e_vepu580" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" +#include "mpp_rc.h" + +#include "h264e_sps.h" +#include "h264e_pps.h" +#include "h264e_dpb.h" +#include "h264e_slice.h" + +#include "hal_h264e_debug.h" +#include "hal_bufs.h" +#include "mpp_enc_hal.h" +#include "rkv_enc_def.h" +#include "vepu5xx_common.h" +#include "vepu580_common.h" +#include "hal_h264e_vepu580_reg.h" +#include "mpp_enc_cb_param.h" +#include "hal_h264e_stream_amend.h" + +#define DUMP_REG 0 +#define MAX_TASK_CNT 2 + +typedef struct Vepu580RoiH264BsCfg_t { + RK_U64 force_inter : 42; + RK_U64 mode_mask : 9; + RK_U64 reserved : 10; + RK_U64 force_intra : 1; + RK_U64 qp_adj_en : 1; + RK_U64 amv_en : 1; +} Vepu580RoiH264BsCfg; + +typedef struct HalH264eVepu580Ctx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_S32 frame_cnt; + RK_U32 task_cnt; + + /* buffers management */ + HalBufs hw_recn; + RK_S32 pixel_buf_fbc_hdr_size; + RK_S32 pixel_buf_fbc_bdy_size; + RK_S32 pixel_buf_size; + RK_S32 thumb_buf_size; + RK_S32 max_buf_cnt; + MppDevRegOffCfgs *offsets; + + /* external line buffer over 4K */ + MppBufferGroup ext_line_buf_grp; + MppBuffer ext_line_bufs[MAX_TASK_CNT]; + RK_S32 ext_line_buf_size; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eDpb *dpb; + H264eFrmInfo *frms; + + /* async encode TSVC info */ + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + + /* syntax for output to enc_impl */ + EncRcTaskInfo hal_rc_cfg; + + /* roi */ + void *roi_data; + MppBufferGroup roi_grp; + MppBuffer roi_base_cfg_buf; + RK_S32 roi_base_buf_size; + + /* osd */ + Vepu5xxOsdCfg osd_cfg; + + /* finetune */ + void *tune; + MppBuffer qpmap_base_cfg_buf; + MppBuffer qpmap_qp_cfg_buf; + RK_U8* md_flag_buf; + RK_S32 qpmap_base_cfg_size; + RK_S32 qpmap_qp_cfg_size; + RK_S32 md_flag_size; + + /* two-pass deflicker */ + MppBuffer buf_pass1; + + /* register */ + HalVepu580RegSet *regs_sets; + HalH264eVepuStreamAmend *amend_sets; + + H264ePrefixNal *prefix_sets; + H264eSlice *slice_sets; + + /* frame parallel info */ + RK_S32 task_idx; + RK_S32 curr_idx; + RK_S32 prev_idx; + RK_S32 slot_to_dchs_txid[H264E_MAX_REFS_CNT]; + HalVepu580RegSet *regs_set; + HalH264eVepuStreamAmend *amend; + H264ePrefixNal *prefix; + H264eSlice *slice; + + MppBuffer ext_line_buf; + + /* slice low delay output callback */ + MppCbCtx *output_cb; + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + MppDevPollCfg *poll_cfgs; +} HalH264eVepu580Ctx; + +#define CHROMA_KLUT_TAB_SIZE (24 * sizeof(RK_U32)) + +static RK_U32 h264e_klut_weight[30] = { + 0x0a000010, 0x00064000, 0x14000020, 0x000c8000, + 0x28000040, 0x00194000, 0x50800080, 0x0032c000, + 0xa1000100, 0x00658000, 0x42800200, 0x00cb0001, + 0x85000400, 0x01964002, 0x0a000800, 0x032c8005, + 0x14001000, 0x0659400a, 0x28802000, 0x0cb2c014, + 0x51004000, 0x1965c028, 0xa2808000, 0x32cbc050, + 0x4500ffff, 0x659780a1, 0x8a81fffe, 0xCC000142, + 0xFF83FFFF, 0x000001FF, +}; + +static RK_U32 disable_rcb_buf = 0; + +static RK_U32 h264_mode_bias[16] = { + 0, 2, 4, 6, + 8, 10, 12, 14, + 16, 18, 20, 24, + 28, 32, 64, 128 +}; + +static RK_S32 h264_aq_tthd_default[16] = { + 0, 0, 0, 0, + 3, 3, 5, 5, + 8, 8, 8, 15, + 15, 20, 25, 35, +}; + +static RK_S32 h264_P_aq_step_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 7, 8, +}; + +static RK_S32 h264_I_aq_step_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 8, +}; + +#include "hal_h264e_vepu580_tune.c" + +static void setup_ext_line_bufs(HalH264eVepu580Ctx *ctx) +{ + RK_U32 i; + + for (i = 0; i < ctx->task_cnt; i++) { + if (ctx->ext_line_bufs[i]) + continue; + + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_bufs[i], + ctx->ext_line_buf_size); + } +} + +static void clear_ext_line_bufs(HalH264eVepu580Ctx *ctx) +{ + RK_U32 i; + + for (i = 0; i < ctx->task_cnt; i++) { + if (ctx->ext_line_bufs[i]) { + mpp_buffer_put(ctx->ext_line_bufs[i]); + ctx->ext_line_bufs[i] = NULL; + } + } +} + +static MPP_RET hal_h264e_vepu580_deinit(void *hal) +{ + HalH264eVepu580Ctx *p = (HalH264eVepu580Ctx *)hal; + RK_U32 i; + + hal_h264e_dbg_func("enter %p\n", p); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + clear_ext_line_bufs(p); + + if (p->amend_sets) { + for (i = 0; i < p->task_cnt; i++) + h264e_vepu_stream_amend_deinit(&p->amend_sets[i]); + } + + MPP_FREE(p->regs_sets); + MPP_FREE(p->amend_sets); + MPP_FREE(p->prefix_sets); + MPP_FREE(p->slice_sets); + MPP_FREE(p->reorder); + MPP_FREE(p->marking); + MPP_FREE(p->poll_cfgs); + + if (p->ext_line_buf_grp) { + mpp_buffer_group_put(p->ext_line_buf_grp); + p->ext_line_buf_grp = NULL; + } + + if (p->hw_recn) { + hal_bufs_deinit(p->hw_recn); + p->hw_recn = NULL; + } + + if (p->roi_base_cfg_buf) { + mpp_buffer_put(p->roi_base_cfg_buf); + p->roi_base_cfg_buf = NULL; + p->roi_base_buf_size = 0; + } + + if (p->roi_grp) { + mpp_buffer_group_put(p->roi_grp); + p->roi_grp = NULL; + } + + if (p->offsets) { + mpp_dev_multi_offset_deinit(p->offsets); + p->offsets = NULL; + } + + if (p->buf_pass1) { + mpp_buffer_put(p->buf_pass1); + p->buf_pass1 = NULL; + } + + if (p->tune) { + vepu580_h264e_tune_deinit(p->tune); + p->tune = NULL; + } + + if (p->qpmap_base_cfg_buf) { + mpp_buffer_put(p->qpmap_base_cfg_buf); + p->qpmap_base_cfg_buf = NULL; + } + + if (p->qpmap_qp_cfg_buf) { + mpp_buffer_put(p->qpmap_qp_cfg_buf); + p->qpmap_qp_cfg_buf = NULL; + } + + if (p->md_flag_buf) { + MPP_FREE(p->md_flag_buf); + } + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu580_init(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu580Ctx *p = (HalH264eVepu580Ctx *)hal; + MPP_RET ret = MPP_OK; + RK_U32 i; + + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + + mpp_env_get_u32("disable_rcb_buf", &disable_rcb_buf, 0); + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + p->task_cnt = cfg->task_cnt; + mpp_assert(p->task_cnt && p->task_cnt <= MAX_TASK_CNT); + + ret = hal_bufs_init(&p->hw_recn); + if (ret) { + mpp_err_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + p->regs_sets = mpp_malloc(HalVepu580RegSet, p->task_cnt); + if (NULL == p->regs_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init register buffer failed\n"); + goto DONE; + } + p->amend_sets = mpp_malloc(HalH264eVepuStreamAmend, p->task_cnt); + if (NULL == p->amend_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + if (p->task_cnt > 1) { + p->prefix_sets = mpp_malloc(H264ePrefixNal, p->task_cnt); + if (NULL == p->prefix_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + p->slice_sets = mpp_malloc(H264eSlice, p->task_cnt); + if (NULL == p->slice_sets) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + p->reorder = mpp_malloc(H264eReorderInfo, 1); + if (NULL == p->reorder) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + + p->marking = mpp_malloc(H264eMarkingInfo, 1); + if (NULL == p->marking) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init amend data failed\n"); + goto DONE; + } + } + + p->poll_slice_max = 8; + p->poll_cfg_size = (sizeof(p->poll_cfgs) + sizeof(RK_S32) * p->poll_slice_max); + p->poll_cfgs = mpp_malloc_size(MppDevPollCfg, p->poll_cfg_size * p->task_cnt); + if (NULL == p->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init poll cfg buffer failed\n"); + goto DONE; + } + + p->osd_cfg.reg_base = &p->regs_sets->reg_osd; + p->osd_cfg.dev = p->dev; + p->osd_cfg.reg_cfg = NULL; + p->osd_cfg.plt_cfg = &p->cfg->plt_cfg; + p->osd_cfg.osd_data = NULL; + p->osd_cfg.osd_data2 = NULL; + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 2; + hw->qp_delta_row = 2; + hw->extra_buf = 1; + hw->qbias_i = 683; + hw->qbias_p = 341; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, h264_aq_tthd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, h264_aq_tthd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, h264_I_aq_step_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, h264_P_aq_step_default, sizeof(hw->aq_step_p)); + + for (i = 0; i < MPP_ARRAY_ELEMS(hw->mode_bias); i++) + hw->mode_bias[i] = 8; + + hw->skip_sad = 8; + hw->skip_bias = 8; + } + mpp_dev_multi_offset_init(&p->offsets, 24); + p->osd_cfg.reg_cfg = p->offsets; + + p->tune = vepu580_h264e_tune_init(p); + p->output_cb = cfg->output_cb; + + cfg->cap_recn_out = 1; + + for (i = 0; i < p->task_cnt; i++) + h264e_vepu_stream_amend_init(&p->amend_sets[i]); + + memset(p->slot_to_dchs_txid, 0, sizeof(p->slot_to_dchs_txid)); +DONE: + if (ret) + hal_h264e_vepu580_deinit(hal); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +/* + * NOTE: recon / refer buffer is FBC data buffer. + * And FBC data require extra 16 lines space for hardware io. + */ +static void setup_hal_bufs(HalH264eVepu580Ctx *ctx) +{ + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + RK_S32 alignment_w = 64; + RK_S32 alignment_h = 16; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment_w); + RK_S32 aligned_h = MPP_ALIGN(prep->height, alignment_h) + 16; + RK_S32 pixel_buf_fbc_hdr_size = MPP_ALIGN(aligned_w * aligned_h / 64, SZ_8K); + RK_S32 pixel_buf_fbc_bdy_size = aligned_w * aligned_h * 3 / 2; + RK_S32 pixel_buf_size = pixel_buf_fbc_hdr_size + pixel_buf_fbc_bdy_size; + RK_S32 thumb_buf_size = MPP_ALIGN(aligned_w / 64 * aligned_h / 64 * 256, SZ_8K); + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + MppEncRefCfg ref_cfg = cfg->ref_cfg; + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + if (new_max_cnt < MPP_MAX(new_max_cnt, info->dpb_size + 1)) + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > SZ_4K) { + /* 480 bytes for each ctu above 3072 */ + RK_S32 ext_line_buf_size = (aligned_w - 3 * SZ_1K) / 64 * 480; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + clear_ext_line_bufs(ctx); + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + + ctx->ext_line_buf_size = ext_line_buf_size; + setup_ext_line_bufs(ctx); + } else { + clear_ext_line_bufs(ctx); + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + if ((ctx->pixel_buf_fbc_hdr_size != pixel_buf_fbc_hdr_size) || + (ctx->pixel_buf_fbc_bdy_size != pixel_buf_fbc_bdy_size) || + (ctx->pixel_buf_size != pixel_buf_size) || + (ctx->thumb_buf_size != thumb_buf_size) || + (new_max_cnt > old_max_cnt)) { + size_t sizes[2]; + + hal_h264e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->pixel_buf_size, pixel_buf_size, + old_max_cnt, new_max_cnt); + + /* pixel buffer */ + sizes[0] = pixel_buf_size; + /* thumb buffer */ + sizes[1] = thumb_buf_size; + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_bufs_setup(ctx->hw_recn, new_max_cnt, 2, sizes); + + ctx->pixel_buf_fbc_hdr_size = pixel_buf_fbc_hdr_size; + ctx->pixel_buf_fbc_bdy_size = pixel_buf_fbc_bdy_size; + ctx->pixel_buf_size = pixel_buf_size; + ctx->thumb_buf_size = thumb_buf_size; + ctx->max_buf_cnt = new_max_cnt; + } +} + +static MPP_RET hal_h264e_vepu580_prepare(void *hal) +{ + HalH264eVepu580Ctx *ctx = (HalH264eVepu580Ctx *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->hw_recn, i); + + prep->change_res = 0; + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_U32 update_vepu580_syntax(HalH264eVepu580Ctx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + ctx->dpb = desc->p; + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu580_get_task(void *hal, HalEncTask *task) +{ + HalH264eVepu580Ctx *ctx = (HalH264eVepu580Ctx *)hal; + MppEncCfgSet *cfg_set = ctx->cfg; + MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg_set->ref_cfg; + MppEncH264HwCfg *hw_cfg = &cfg_set->h264.hw_cfg; + RK_U32 updated = update_vepu580_syntax(ctx, &task->syntax); + EncFrmStatus *frm_status = &task->rc_task->frm; + H264eFrmInfo *frms = ctx->frms; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) + setup_hal_bufs(ctx); + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(task->frame); + + mpp_meta_get_ptr_d(meta, KEY_ROI_DATA2, (void **)&ctx->roi_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA, (void **)&ctx->osd_cfg.osd_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA2, (void **)&ctx->osd_cfg.osd_data2, NULL); + } + + if (ctx->dpb) { + h264e_dpb_hal_start(ctx->dpb, frms->curr_idx); + h264e_dpb_hal_start(ctx->dpb, frms->refr_idx); + } + + task->flags.reg_idx = ctx->task_idx; + task->flags.curr_idx = frms->curr_idx; + task->flags.refr_idx = frms->refr_idx; + task->part_first = 1; + task->part_last = 0; + + ctx->ext_line_buf = ctx->ext_line_bufs[ctx->task_idx]; + ctx->regs_set = &ctx->regs_sets[ctx->task_idx]; + ctx->amend = &ctx->amend_sets[ctx->task_idx]; + ctx->osd_cfg.reg_base = &ctx->regs_set->reg_osd; + + /* if not VEPU1/2, update log2_max_frame_num_minus4 in hw_cfg */ + hw_cfg->hw_log2_max_frame_num_minus4 = ctx->sps->log2_max_frame_num_minus4; + + if (ctx->task_cnt > 1 && (ref->lt_cfg_cnt || ref->st_cfg_cnt > 1)) { + H264ePrefixNal *prefix = &ctx->prefix_sets[ctx->task_idx]; + H264eSlice *slice = &ctx->slice_sets[ctx->task_idx]; + + //store async encode TSVC info + if (ctx->prefix) + memcpy(prefix, ctx->prefix, sizeof(H264ePrefixNal)); + else + prefix = NULL; + + if (ctx->slice) { + memcpy(slice, ctx->slice, sizeof(H264eSlice)); + + /* + * Generally, reorder and marking are shared by dpb and slice. + * However, async encoding TSVC will change reorder and marking in each task. + * Therefore, malloc a special space for async encoding TSVC. + */ + ctx->amend->reorder = ctx->reorder; + ctx->amend->marking = ctx->marking; + } + + h264e_vepu_stream_amend_config(ctx->amend, task->packet, ctx->cfg, + slice, prefix); + } else { + h264e_vepu_stream_amend_config(ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + } + + if (ctx->task_cnt > 1) + ctx->task_idx = !ctx->task_idx; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static void setup_vepu580_normal(HalVepu580RegSet *regs) +{ + hal_h264e_dbg_func("enter\n"); + + /* reg001 ENC_STRT */ + regs->reg_ctl.enc_strt.lkt_num = 0; + regs->reg_ctl.enc_strt.vepu_cmd = 1; + regs->reg_ctl.func_en.cke = 1; + regs->reg_ctl.func_en.resetn_hw_en = 1; + regs->reg_ctl.func_en.enc_done_tmvp_en = 1; + + /* reg002 ENC_CLR */ + regs->reg_ctl.enc_clr.safe_clr = 0; + regs->reg_ctl.enc_clr.force_clr = 0; + + /* reg004 INT_EN */ + regs->reg_ctl.int_en.enc_done_en = 1; + regs->reg_ctl.int_en.lkt_node_done_en = 1; + regs->reg_ctl.int_en.sclr_done_en = 1; + regs->reg_ctl.int_en.slc_done_en = 0; + regs->reg_ctl.int_en.bsf_oflw_en = 1; + regs->reg_ctl.int_en.brsp_otsd_en = 1; + regs->reg_ctl.int_en.wbus_err_en = 1; + regs->reg_ctl.int_en.rbus_err_en = 1; + regs->reg_ctl.int_en.wdg_en = 1; + + /* reg005 INT_MSK */ + regs->reg_ctl.int_msk.enc_done_msk = 0; + regs->reg_ctl.int_msk.lkt_node_done_msk = 0; + regs->reg_ctl.int_msk.sclr_done_msk = 0; + regs->reg_ctl.int_msk.slc_done_msk = 0; + regs->reg_ctl.int_msk.bsf_oflw_msk = 0; + regs->reg_ctl.int_msk.brsp_otsd_msk = 0; + regs->reg_ctl.int_msk.wbus_err_msk = 0; + regs->reg_ctl.int_msk.rbus_err_msk = 0; + regs->reg_ctl.int_msk.wdg_msk = 0; + + regs->reg_ctl.enc_wdg.vs_load_thd = 0x1fffff; + regs->reg_ctl.enc_wdg.rfp_load_thd = 0; + + /* reg015 DTRNS_MAP */ + regs->reg_ctl.dtrns_map.cmvw_bus_ordr = 0; + regs->reg_ctl.dtrns_map.dspw_bus_ordr = 0; + regs->reg_ctl.dtrns_map.rfpw_bus_ordr = 0; + regs->reg_ctl.dtrns_map.src_bus_edin = 0; + regs->reg_ctl.dtrns_map.meiw_bus_edin = 0; + regs->reg_ctl.dtrns_map.bsw_bus_edin = 7; + regs->reg_ctl.dtrns_map.lktr_bus_edin = 0; + regs->reg_ctl.dtrns_map.roir_bus_edin = 0; + regs->reg_ctl.dtrns_map.lktw_bus_edin = 0; + regs->reg_ctl.dtrns_map.afbc_bsize = 1; + + regs->reg_ctl.dtrns_cfg.axi_brsp_cke = 0; + regs->reg_ctl.dtrns_cfg.dspr_otsd = 1; + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET setup_vepu580_prep(HalVepu580RegSet *regs, MppEncPrepCfg *prep, + HalEncTask *task) +{ + VepuFmtCfg cfg; + MppFrameFormat fmt = prep->format; + MPP_RET ret = vepu5xx_set_fmt(&cfg, fmt); + RK_U32 hw_fmt = cfg.format; + RK_S32 y_stride; + RK_S32 c_stride; + + hal_h264e_dbg_func("enter\n"); + + /* do nothing when color format is not supported */ + if (ret) + return ret; + + regs->reg_base.enc_rsl.pic_wd8_m1 = MPP_ALIGN(prep->width, 16) / 8 - 1; + regs->reg_base.src_fill.pic_wfill = MPP_ALIGN(prep->width, 16) - prep->width; + regs->reg_base.enc_rsl.pic_hd8_m1 = MPP_ALIGN(prep->height, 16) / 8 - 1; + regs->reg_base.src_fill.pic_hfill = MPP_ALIGN(prep->height, 16) - prep->height; + + regs->reg_ctl.dtrns_map.src_bus_edin = cfg.src_endian; + + regs->reg_base.src_fmt.src_cfmt = hw_fmt; + regs->reg_base.src_fmt.alpha_swap = cfg.alpha_swap; + regs->reg_base.src_fmt.rbuv_swap = cfg.rbuv_swap; + regs->reg_base.src_fmt.out_fmt = (hw_fmt == VEPU5xx_FMT_YUV400) ? 0 : 1; + + if (MPP_FRAME_FMT_IS_YUV(fmt)) + regs->reg_base.src_fmt.src_range = 1; + else + regs->reg_base.src_fmt.src_range = (prep->range == MPP_FRAME_RANGE_JPEG) ? 1 : 0; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + y_stride = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!y_stride) + y_stride = MPP_ALIGN(prep->width, 16); + } else if (prep->hor_stride) { + y_stride = prep->hor_stride; + } else { + if (hw_fmt == VEPU5xx_FMT_BGRA8888 ) + y_stride = prep->width * 4; + else if (hw_fmt == VEPU5xx_FMT_BGR888 ) + y_stride = prep->width * 3; + else if (hw_fmt == VEPU5xx_FMT_BGR565 || + hw_fmt == VEPU5xx_FMT_YUYV422 || + hw_fmt == VEPU5xx_FMT_UYVY422) + y_stride = prep->width * 2; + else + y_stride = prep->width; + } + + switch (hw_fmt) { + case VEPU5xx_FMT_YUV444SP : { + c_stride = y_stride * 2; + } break; + case VEPU5xx_FMT_YUV422SP : + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV444P : { + c_stride = y_stride; + } break; + default : { + c_stride = y_stride / 2; + } break; + } + + if (hw_fmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = get_rgb2yuv_cfg(prep->range, prep->color); + + hal_h264e_dbg_flow("input color range %d colorspace %d", prep->range, prep->color); + + regs->reg_base.src_udfy.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + regs->reg_base.src_udfy.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + regs->reg_base.src_udfy.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + + regs->reg_base.src_udfu.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + regs->reg_base.src_udfu.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + regs->reg_base.src_udfu.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + + regs->reg_base.src_udfv.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + regs->reg_base.src_udfv.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + regs->reg_base.src_udfv.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + + regs->reg_base.src_udfo.csc_ofst_y = cfg_coeffs->_2y.offset; + regs->reg_base.src_udfo.csc_ofst_u = cfg_coeffs->_2u.offset; + regs->reg_base.src_udfo.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h264e_dbg_flow("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } else { + regs->reg_base.src_udfy.csc_wgt_b2y = cfg.weight[0]; + regs->reg_base.src_udfy.csc_wgt_g2y = cfg.weight[1]; + regs->reg_base.src_udfy.csc_wgt_r2y = cfg.weight[2]; + + regs->reg_base.src_udfu.csc_wgt_b2u = cfg.weight[3]; + regs->reg_base.src_udfu.csc_wgt_g2u = cfg.weight[4]; + regs->reg_base.src_udfu.csc_wgt_r2u = cfg.weight[5]; + + regs->reg_base.src_udfv.csc_wgt_b2v = cfg.weight[6]; + regs->reg_base.src_udfv.csc_wgt_g2v = cfg.weight[7]; + regs->reg_base.src_udfv.csc_wgt_r2v = cfg.weight[8]; + + regs->reg_base.src_udfo.csc_ofst_y = cfg.offset[0]; + regs->reg_base.src_udfo.csc_ofst_u = cfg.offset[1]; + regs->reg_base.src_udfo.csc_ofst_v = cfg.offset[2]; + } + + regs->reg_base.src_proc.afbcd_en = (MPP_FRAME_FMT_IS_FBC(fmt) != 0) ? 1 : 0; + regs->reg_base.src_strd0.src_strd0 = y_stride; + regs->reg_base.src_strd1.src_strd1 = c_stride; + + regs->reg_base.src_proc.src_mirr = prep->mirroring > 0; + regs->reg_base.src_proc.src_rot = prep->rotation; + regs->reg_base.src_proc.txa_en = 0; + + regs->reg_base.sli_cfg.sli_crs_en = 1; + + regs->reg_base.pic_ofst.pic_ofst_y = 0; + regs->reg_base.pic_ofst.pic_ofst_x = 0; + + hal_h264e_dbg_func("leave\n"); + + return ret; +} + +static MPP_RET vepu580_h264e_save_pass1_patch(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) +{ + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 64); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + regs->reg_base.enc_pic.cur_frm_ref = 1; + regs->reg_base.rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + regs->reg_base.rfpw_b_addr = regs->reg_base.rfpw_h_addr; + regs->reg_base.enc_pic.rec_fbc_dis = 1; + + mpp_dev_multi_offset_update(ctx->offsets, 164, width_align * height_align); + + /* NOTE: disable split to avoid lowdelay slice output */ + regs->reg_base.sli_splt.sli_splt = 0; + regs->reg_base.enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu580_h264e_use_pass1_patch(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) +{ + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 hor_stride = MPP_ALIGN(prep->width, 64); + RK_S32 ver_stride = MPP_ALIGN(prep->height, 16); + RK_S32 frame_size = hor_stride * ver_stride; + RK_S32 fd_in = mpp_buffer_get_fd(ctx->buf_pass1); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_base.src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + regs->reg_base.src_fmt.alpha_swap = 0; + regs->reg_base.src_fmt.rbuv_swap = 0; + regs->reg_base.src_fmt.out_fmt = 1; + + regs->reg_base.src_proc.afbcd_en = 0; + regs->reg_base.src_strd0.src_strd0 = hor_stride; + regs->reg_base.src_strd1.src_strd1 = hor_stride; + + regs->reg_base.src_proc.src_mirr = 0; + regs->reg_base.src_proc.src_rot = 0; + regs->reg_base.src_proc.txa_en = 0; + + regs->reg_base.pic_ofst.pic_ofst_y = 0; + regs->reg_base.pic_ofst.pic_ofst_x = 0; + + + regs->reg_base.adr_src0 = fd_in; + regs->reg_base.adr_src1 = fd_in; + regs->reg_base.adr_src2 = fd_in; + + mpp_dev_multi_offset_update(ctx->offsets, 161, frame_size); + mpp_dev_multi_offset_update(ctx->offsets, 162, frame_size); + + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + +static void setup_vepu580_codec(HalVepu580RegSet *regs, H264eSps *sps, + H264ePps *pps, H264eSlice *slice) +{ + hal_h264e_dbg_func("enter\n"); + + regs->reg_base.enc_pic.enc_stnd = 0; + regs->reg_base.enc_pic.cur_frm_ref = slice->nal_reference_idc > 0; + regs->reg_base.enc_pic.bs_scp = 1; + + regs->reg_base.synt_nal.nal_ref_idc = slice->nal_reference_idc; + regs->reg_base.synt_nal.nal_unit_type = slice->nalu_type; + + regs->reg_base.synt_sps.max_fnum = sps->log2_max_frame_num_minus4; + regs->reg_base.synt_sps.drct_8x8 = sps->direct8x8_inference; + regs->reg_base.synt_sps.mpoc_lm4 = sps->log2_max_poc_lsb_minus4; + + regs->reg_base.synt_pps.etpy_mode = pps->entropy_coding_mode; + regs->reg_base.synt_pps.trns_8x8 = pps->transform_8x8_mode; + regs->reg_base.synt_pps.csip_flag = pps->constrained_intra_pred; + regs->reg_base.synt_pps.num_ref0_idx = pps->num_ref_idx_l0_default_active - 1; + regs->reg_base.synt_pps.num_ref1_idx = pps->num_ref_idx_l1_default_active - 1; + regs->reg_base.synt_pps.pic_init_qp = pps->pic_init_qp; + regs->reg_base.synt_pps.cb_ofst = pps->chroma_qp_index_offset; + regs->reg_base.synt_pps.cr_ofst = pps->second_chroma_qp_index_offset; + regs->reg_base.synt_pps.wght_pred = pps->weighted_pred; + regs->reg_base.synt_pps.dbf_cp_flg = pps->deblocking_filter_control; + + regs->reg_base.synt_sli0.sli_type = (slice->slice_type == H264_I_SLICE) ? (2) : (0); + regs->reg_base.synt_sli0.pps_id = slice->pic_parameter_set_id; + regs->reg_base.synt_sli0.drct_smvp = 0; + regs->reg_base.synt_sli0.num_ref_ovrd = slice->num_ref_idx_override; + regs->reg_base.synt_sli0.cbc_init_idc = slice->cabac_init_idc; + regs->reg_base.synt_sli0.frm_num = slice->frame_num; + + regs->reg_base.synt_sli1.idr_pid = (slice->slice_type == H264_I_SLICE) ? slice->idr_pic_id : (RK_U32)(-1); + regs->reg_base.synt_sli1.poc_lsb = slice->pic_order_cnt_lsb; + + + regs->reg_base.synt_sli2.dis_dblk_idc = slice->disable_deblocking_filter_idc; + regs->reg_base.synt_sli2.sli_alph_ofst = slice->slice_alpha_c0_offset_div2; + + h264e_reorder_rd_rewind(slice->reorder); + { /* reorder process */ + H264eRplmo rplmo; + MPP_RET ret = h264e_reorder_rd_op(slice->reorder, &rplmo); + + if (MPP_OK == ret) { + regs->reg_base.synt_sli2.ref_list0_rodr = 1; + regs->reg_base.synt_sli2.rodr_pic_idx = rplmo.modification_of_pic_nums_idc; + + switch (rplmo.modification_of_pic_nums_idc) { + case 0 : + case 1 : { + regs->reg_base.synt_sli2.rodr_pic_num = rplmo.abs_diff_pic_num_minus1; + } break; + case 2 : { + regs->reg_base.synt_sli2.rodr_pic_num = rplmo.long_term_pic_idx; + } break; + default : { + mpp_err_f("invalid modification_of_pic_nums_idc %d\n", + rplmo.modification_of_pic_nums_idc); + } break; + } + } else { + // slice->ref_pic_list_modification_flag; + regs->reg_base.synt_sli2.ref_list0_rodr = 0; + regs->reg_base.synt_sli2.rodr_pic_idx = 0; + regs->reg_base.synt_sli2.rodr_pic_num = 0; + } + } + + /* clear all mmco arg first */ + regs->reg_base.synt_refm0.nopp_flg = 0; + regs->reg_base.synt_refm0.ltrf_flg = 0; + regs->reg_base.synt_refm0.arpm_flg = 0; + regs->reg_base.synt_refm0.mmco4_pre = 0; + regs->reg_base.synt_refm0.mmco_type0 = 0; + regs->reg_base.synt_refm0.mmco_parm0 = 0; + regs->reg_base.synt_refm0.mmco_type1 = 0; + regs->reg_base.synt_refm1.mmco_parm1 = 0; + regs->reg_base.synt_refm0.mmco_type2 = 0; + regs->reg_base.synt_refm1.mmco_parm2 = 0; + regs->reg_base.synt_refm2.long_term_frame_idx0 = 0; + regs->reg_base.synt_refm2.long_term_frame_idx1 = 0; + regs->reg_base.synt_refm2.long_term_frame_idx2 = 0; + + h264e_marking_rd_rewind(slice->marking); + + /* only update used parameter */ + if (slice->slice_type == H264_I_SLICE) { + regs->reg_base.synt_refm0.nopp_flg = slice->no_output_of_prior_pics; + regs->reg_base.synt_refm0.ltrf_flg = slice->long_term_reference_flag; + } else { + if (!h264e_marking_is_empty(slice->marking)) { + H264eMmco mmco; + + regs->reg_base.synt_refm0.arpm_flg = 1; + + /* max 3 mmco */ + do { + RK_S32 type = 0; + RK_S32 param_0 = 0; + RK_S32 param_1 = 0; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_base.synt_refm0.mmco_type0 = type; + regs->reg_base.synt_refm0.mmco_parm0 = param_0; + regs->reg_base.synt_refm2.long_term_frame_idx0 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_base.synt_refm0.mmco_type1 = type; + regs->reg_base.synt_refm1.mmco_parm1 = param_0; + regs->reg_base.synt_refm2.long_term_frame_idx1 = param_1; + + if (h264e_marking_is_empty(slice->marking)) + break; + + h264e_marking_rd_op(slice->marking, &mmco); + type = mmco.mmco; + param_0 = 0; + param_1 = 0; + switch (type) { + case 1 : { + param_0 = mmco.difference_of_pic_nums_minus1; + } break; + case 2 : { + param_0 = mmco.long_term_pic_num; + } break; + case 3 : { + param_0 = mmco.difference_of_pic_nums_minus1; + param_1 = mmco.long_term_frame_idx; + } break; + case 4 : { + param_0 = mmco.max_long_term_frame_idx_plus1; + } break; + case 5 : { + } break; + case 6 : { + param_0 = mmco.long_term_frame_idx; + } break; + default : { + mpp_err_f("unsupported mmco 0 %d\n", type); + type = 0; + } break; + } + + regs->reg_base.synt_refm0.mmco_type2 = type; + regs->reg_base.synt_refm1.mmco_parm2 = param_0; + regs->reg_base.synt_refm2.long_term_frame_idx2 = param_1; + } while (0); + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu580_rdo_pred(HalVepu580RegSet *regs, H264eSps *sps, + H264ePps *pps, H264eSlice *slice) +{ + hal_h264e_dbg_func("enter\n"); + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_rc_klut.klut_ofst.chrm_klut_ofst = 0; + memcpy(®s->reg_rc_klut.klut_wgt0, &h264e_klut_weight[0], CHROMA_KLUT_TAB_SIZE); + } else { + regs->reg_rc_klut.klut_ofst.chrm_klut_ofst = 3; + memcpy(®s->reg_rc_klut.klut_wgt0, &h264e_klut_weight[4], CHROMA_KLUT_TAB_SIZE); + } + + regs->reg_base.iprd_csts.vthd_y = 9; + regs->reg_base.iprd_csts.vthd_c = 63; + + regs->reg_base.rdo_cfg.rect_size = (sps->profile_idc == H264_PROFILE_BASELINE && + sps->level_idc <= H264_LEVEL_3_0) ? 1 : 0; + regs->reg_base.rdo_cfg.inter_4x4 = 1; + regs->reg_base.rdo_cfg.vlc_lmt = (sps->profile_idc < H264_PROFILE_MAIN) && + !pps->entropy_coding_mode; + regs->reg_base.rdo_cfg.chrm_spcl = 1; + regs->reg_base.rdo_cfg.rdo_mask = 0; + regs->reg_base.rdo_cfg.ccwa_e = 1; + regs->reg_base.rdo_cfg.scl_lst_sel = pps->pic_scaling_matrix_present; + regs->reg_base.rdo_cfg.atr_e = 1; + regs->reg_base.rdo_cfg.atf_intra_e = 1; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu580_rdo_bias_cfg(Vepu580RdoCfg *regs, MppEncHwCfg *hw) +{ + RK_U8 bias = h264_mode_bias[hw->mode_bias[1]]; + + regs->rdo_intra_atf_wgt0.atf_rdo_intra_wgt00 = bias > 24 ? bias : 24; + regs->rdo_intra_atf_wgt0.atf_rdo_intra_wgt01 = bias > 22 ? bias : 22; + regs->rdo_intra_atf_wgt0.atf_rdo_intra_wgt02 = bias > 21 ? bias : 21; + regs->rdo_intra_atf_wgt1.atf_rdo_intra_wgt10 = bias > 22 ? bias : 22; + regs->rdo_intra_atf_wgt1.atf_rdo_intra_wgt11 = bias > 21 ? bias : 21; + regs->rdo_intra_atf_wgt1.atf_rdo_intra_wgt12 = bias > 20 ? bias : 20; + regs->rdo_intra_atf_wgt2.atf_rdo_intra_wgt20 = bias > 20 ? bias : 20; + regs->rdo_intra_atf_wgt2.atf_rdo_intra_wgt21 = bias > 19 ? bias : 19; + regs->rdo_intra_atf_wgt2.atf_rdo_intra_wgt22 = bias > 18 ? bias : 18; + regs->rdo_intra_atf_wgt3.atf_rdo_intra_wgt30 = bias; + regs->rdo_intra_atf_wgt3.atf_rdo_intra_wgt31 = bias; + regs->rdo_intra_atf_wgt3.atf_rdo_intra_wgt32 = bias; + + if (hw->skip_bias_en) { + bias = hw->skip_bias; + + regs->rdo_skip_cime_thd0.atf_rdo_skip_cime_thd0 = hw->skip_sad < 10 ? hw->skip_sad : 10; + regs->rdo_skip_cime_thd0.atf_rdo_skip_cime_thd1 = hw->skip_sad < 8 ? hw->skip_sad : 8; + regs->rdo_skip_cime_thd1.atf_rdo_skip_cime_thd2 = hw->skip_sad < 15 ? hw->skip_sad : 15; + regs->rdo_skip_cime_thd1.atf_rdo_skip_cime_thd3 = hw->skip_sad; + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt00 = bias > 20 ? bias : 20; + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt10 = bias; + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt11 = bias; + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt12 = bias; + regs->rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt20 = bias; + regs->rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt21 = bias; + regs->rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt22 = bias; + regs->rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt30 = bias; + regs->rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt31 = bias; + regs->rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt32 = bias; + regs->rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt40 = bias; + regs->rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt41 = bias; + regs->rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt42 = bias; + } +} + +static void setup_vepu580_rdo_cfg(Vepu580RdoCfg *regs) +{ + hal_h264e_dbg_func("enter\n"); + + /* 0x2000 */ + regs->rdo_sqi_cfg.atf_pskip_en = 1; + + /* 0x20CC ~ 0x20D0 */ + regs->rdo_intra_cime_thd0.atf_rdo_intra_cime_thd0 = 28; + regs->rdo_intra_cime_thd0.atf_rdo_intra_cime_thd1 = 44; + regs->rdo_intra_cime_thd1.atf_rdo_intra_cime_thd2 = 72; + + /* 0x20D4 ~ 0x20E0 */ + regs->rdo_intra_var_thd0.atf_rdo_intra_var_thd00 = 25; + regs->rdo_intra_var_thd0.atf_rdo_intra_var_thd01 = 64; + regs->rdo_intra_var_thd1.atf_rdo_intra_var_thd10 = 25; + regs->rdo_intra_var_thd1.atf_rdo_intra_var_thd11 = 64; + regs->rdo_intra_var_thd2.atf_rdo_intra_var_thd20 = 70; + regs->rdo_intra_var_thd2.atf_rdo_intra_var_thd21 = 100; + regs->rdo_intra_var_thd3.atf_rdo_intra_var_thd30 = 70; + regs->rdo_intra_var_thd3.atf_rdo_intra_var_thd31 = 100; + + /* 0x20E4 ~ 0x20F0 */ + regs->rdo_intra_atf_wgt0.atf_rdo_intra_wgt00 = 24; + regs->rdo_intra_atf_wgt0.atf_rdo_intra_wgt01 = 22; + regs->rdo_intra_atf_wgt0.atf_rdo_intra_wgt02 = 21; + regs->rdo_intra_atf_wgt1.atf_rdo_intra_wgt10 = 22; + regs->rdo_intra_atf_wgt1.atf_rdo_intra_wgt11 = 21; + regs->rdo_intra_atf_wgt1.atf_rdo_intra_wgt12 = 20; + regs->rdo_intra_atf_wgt2.atf_rdo_intra_wgt20 = 20; + regs->rdo_intra_atf_wgt2.atf_rdo_intra_wgt21 = 19; + regs->rdo_intra_atf_wgt2.atf_rdo_intra_wgt22 = 18; + regs->rdo_intra_atf_wgt3.atf_rdo_intra_wgt30 = 16; + regs->rdo_intra_atf_wgt3.atf_rdo_intra_wgt31 = 16; + regs->rdo_intra_atf_wgt3.atf_rdo_intra_wgt32 = 16; + + /* 0x211C ~ 0x2130 */ + regs->rdo_skip_cime_thd0.atf_rdo_skip_cime_thd0 = 10; + regs->rdo_skip_cime_thd0.atf_rdo_skip_cime_thd1 = 8; + regs->rdo_skip_cime_thd1.atf_rdo_skip_cime_thd2 = 15; + regs->rdo_skip_cime_thd1.atf_rdo_skip_cime_thd3 = 25; + regs->rdo_skip_var_thd0.atf_rdo_skip_var_thd10 = 25; + regs->rdo_skip_var_thd0.atf_rdo_skip_var_thd11 = 40; + regs->rdo_skip_var_thd1.atf_rdo_skip_var_thd20 = 25; + regs->rdo_skip_var_thd1.atf_rdo_skip_var_thd21 = 40; + regs->rdo_skip_var_thd2.atf_rdo_skip_var_thd30 = 70; + regs->rdo_skip_var_thd2.atf_rdo_skip_var_thd31 = 100; + regs->rdo_skip_var_thd3.atf_rdo_skip_var_thd40 = 70; + regs->rdo_skip_var_thd3.atf_rdo_skip_var_thd41 = 100; + + /* 0x2134 ~ 0x2140 */ + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt00 = 20; + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt10 = 16; + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt11 = 16; + regs->rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt12 = 16; + regs->rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt20 = 16; + regs->rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt21 = 16; + regs->rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt22 = 16; + regs->rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt30 = 16; + regs->rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt31 = 16; + regs->rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt32 = 16; + regs->rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt40 = 16; + regs->rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt41 = 16; + regs->rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt42 = 16; + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu580_rc_base(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx, EncRcTask *rc_task) +{ + EncRcTaskInfo *rc_info = &rc_task->info; + H264eSlice *slice = ctx->slice; + MppEncCfgSet *cfg = ctx->cfg; + MppEncHwCfg *hw = &cfg->hw; + H264eSps *sps = ctx->sps; + MppEncRcCfg *rc = &cfg->rc; + RK_S32 mb_w = sps->pic_width_in_mbs; + RK_S32 mb_h = sps->pic_height_in_mbs; + RK_U32 qp_target = rc_info->quality_target; + RK_U32 qp_min = rc_info->quality_min; + RK_U32 qp_max = rc_info->quality_max; + RK_U32 qpmap_mode = 1; + RK_S32 mb_target_bits_mul_16 = (rc_info->bit_target << 4) / (mb_w * mb_h); + RK_S32 mb_target_bits; + RK_S32 negative_bits_thd; + RK_S32 positive_bits_thd; + + hal_h264e_dbg_rc("bittarget %d qp [%d %d %d]\n", rc_info->bit_target, + qp_min, qp_target, qp_max); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_rc_klut.roi_qthd0.qpmin_area0 = qp_min; + regs->reg_rc_klut.roi_qthd0.qpmax_area0 = qp_max; + regs->reg_rc_klut.roi_qthd0.qpmin_area1 = qp_min; + regs->reg_rc_klut.roi_qthd0.qpmax_area1 = qp_max; + regs->reg_rc_klut.roi_qthd0.qpmin_area2 = qp_min; + + regs->reg_rc_klut.roi_qthd1.qpmax_area2 = qp_max; + regs->reg_rc_klut.roi_qthd1.qpmin_area3 = qp_min; + regs->reg_rc_klut.roi_qthd1.qpmax_area3 = qp_max; + regs->reg_rc_klut.roi_qthd1.qpmin_area4 = qp_min; + regs->reg_rc_klut.roi_qthd1.qpmax_area4 = qp_max; + + regs->reg_rc_klut.roi_qthd2.qpmin_area5 = qp_min; + regs->reg_rc_klut.roi_qthd2.qpmax_area5 = qp_max; + regs->reg_rc_klut.roi_qthd2.qpmin_area6 = qp_min; + regs->reg_rc_klut.roi_qthd2.qpmax_area6 = qp_max; + regs->reg_rc_klut.roi_qthd2.qpmin_area7 = qp_min; + + regs->reg_rc_klut.roi_qthd3.qpmax_area7 = qp_max; + regs->reg_rc_klut.roi_qthd3.qpmap_mode = qpmap_mode; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + regs->reg_base.enc_pic.pic_qp = qp_target; + regs->reg_base.rc_qp.rc_max_qp = qp_target; + regs->reg_base.rc_qp.rc_min_qp = qp_target; + + return; + } + + if (mb_target_bits_mul_16 >= 0x100000) + mb_target_bits_mul_16 = 0x50000; + + mb_target_bits = (mb_target_bits_mul_16 * mb_w) >> 4; + negative_bits_thd = 0 - 5 * mb_target_bits / 16; + positive_bits_thd = 5 * mb_target_bits / 16; + + regs->reg_base.enc_pic.pic_qp = qp_target; + regs->reg_base.rc_cfg.rc_en = 1; + regs->reg_base.rc_cfg.aq_en = 1; + regs->reg_base.rc_cfg.aq_mode = 0; + regs->reg_base.rc_cfg.rc_ctu_num = mb_w; + regs->reg_base.rc_qp.rc_qp_range = (slice->slice_type == H264_I_SLICE) ? + hw->qp_delta_row_i : hw->qp_delta_row; + regs->reg_base.rc_qp.rc_max_qp = qp_max; + regs->reg_base.rc_qp.rc_min_qp = qp_min; + regs->reg_base.rc_tgt.ctu_ebit = mb_target_bits_mul_16; + + regs->reg_rc_klut.rc_adj0.qp_adj0 = -2; + regs->reg_rc_klut.rc_adj0.qp_adj1 = -1; + regs->reg_rc_klut.rc_adj0.qp_adj2 = 0; + regs->reg_rc_klut.rc_adj0.qp_adj3 = 1; + regs->reg_rc_klut.rc_adj0.qp_adj4 = 2; + regs->reg_rc_klut.rc_adj1.qp_adj5 = 0; + regs->reg_rc_klut.rc_adj1.qp_adj6 = 0; + regs->reg_rc_klut.rc_adj1.qp_adj7 = 0; + regs->reg_rc_klut.rc_adj1.qp_adj8 = 1; + + regs->reg_rc_klut.rc_dthd_0_8[0] = 4 * negative_bits_thd; + regs->reg_rc_klut.rc_dthd_0_8[1] = negative_bits_thd; + regs->reg_rc_klut.rc_dthd_0_8[2] = positive_bits_thd; + regs->reg_rc_klut.rc_dthd_0_8[3] = 4 * positive_bits_thd; + regs->reg_rc_klut.rc_dthd_0_8[4] = 0x7FFFFFFF; + regs->reg_rc_klut.rc_dthd_0_8[5] = 0x7FFFFFFF; + regs->reg_rc_klut.rc_dthd_0_8[6] = 0x7FFFFFFF; + regs->reg_rc_klut.rc_dthd_0_8[7] = 0x7FFFFFFF; + regs->reg_rc_klut.rc_dthd_0_8[8] = 0x7FFFFFFF; + + { + /* 0x1070 ~ 0x1074 */ + regs->reg_rc_klut.md_sad_thd.md_sad_thd0 = 4; + regs->reg_rc_klut.md_sad_thd.md_sad_thd1 = 9; + regs->reg_rc_klut.md_sad_thd.md_sad_thd2 = 15; + + regs->reg_rc_klut.madi_thd.madi_thd0 = 4; + regs->reg_rc_klut.madi_thd.madi_thd1 = 9; + regs->reg_rc_klut.madi_thd.madi_thd2 = 15; + } + + if (cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC) { + regs->reg_base.rc_qp.rc_qp_range = 0; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu580_io_buf(HalVepu580RegSet *regs, MppDevRegOffCfgs *offsets, + HalEncTask *task) +{ + MppFrame frm = task->frame; + MppPacket pkt = task->packet; + MppBuffer buf_in = mpp_frame_get_buffer(frm); + MppBuffer buf_out = task->output; + MppFrameFormat fmt = mpp_frame_get_fmt(frm); + RK_S32 hor_stride = mpp_frame_get_hor_stride(frm); + RK_S32 ver_stride = mpp_frame_get_ver_stride(frm); + RK_S32 fd_in = mpp_buffer_get_fd(buf_in); + RK_U32 off_in[2] = {0}; + RK_U32 off_out = mpp_packet_get_length(pkt); + size_t siz_out = mpp_buffer_get_size(buf_out); + RK_S32 fd_out = mpp_buffer_get_fd(buf_out); + + hal_h264e_dbg_func("enter\n"); + + regs->reg_base.adr_src0 = fd_in; + regs->reg_base.adr_src1 = fd_in; + regs->reg_base.adr_src2 = fd_in; + + regs->reg_base.bsbb_addr = fd_out; + regs->reg_base.bsbr_addr = fd_out; + regs->reg_base.adr_bsbs = fd_out; + regs->reg_base.bsbt_addr = fd_out; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + off_in[0] = mpp_frame_get_fbc_offset(frm);; + off_in[1] = 0; + } else if (MPP_FRAME_FMT_IS_YUV(fmt)) { + VepuFmtCfg cfg; + + vepu5xx_set_fmt(&cfg, fmt); + switch (cfg.format) { + case VEPU5xx_FMT_BGRA8888 : + case VEPU5xx_FMT_BGR888 : + case VEPU5xx_FMT_BGR565 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV422SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV422P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 3 / 2; + } break; + case VEPU5xx_FMT_YUV420P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 5 / 4; + } break; + case VEPU5xx_FMT_YUV400 : + case VEPU5xx_FMT_YUYV422 : + case VEPU5xx_FMT_UYVY422 : { + off_in[0] = 0; + off_in[1] = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + off_in[0] = hor_stride * ver_stride; + off_in[1] = hor_stride * ver_stride * 2; + } break; + default : { + off_in[0] = 0; + off_in[1] = 0; + } break; + } + } + + mpp_dev_multi_offset_update(offsets, 161, off_in[0]); + mpp_dev_multi_offset_update(offsets, 162, off_in[1]); + mpp_dev_multi_offset_update(offsets, 172, siz_out); + mpp_dev_multi_offset_update(offsets, 175, off_out); + + hal_h264e_dbg_func("leave\n"); +} + +static MPP_RET vepu580_h264_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h) +{ + Vepu580RoiH264BsCfg *ptr = (Vepu580RoiH264BsCfg *)buf; + RK_S32 mb_w = MPP_ALIGN(w, 16) / 16; + RK_S32 mb_h = MPP_ALIGN(h, 16) / 16; + RK_S32 stride_h = MPP_ALIGN(mb_w, 4); + Vepu580RoiH264BsCfg cfg; + MPP_RET ret = MPP_NOK; + + if (NULL == buf || NULL == region) { + mpp_err_f("invalid buf %p roi %p\n", buf, region); + goto DONE; + } + + RK_S32 roi_width = (region->w + 15) / 16; + RK_S32 roi_height = (region->h + 15) / 16; + RK_S32 pos_x_init = region->x / 16; + RK_S32 pos_y_init = region->y / 16; + RK_S32 pos_x_end = pos_x_init + roi_width; + RK_S32 pos_y_end = pos_y_init + roi_height; + RK_S32 x, y; + + pos_x_end = MPP_MIN(pos_x_end, mb_w); + pos_y_end = MPP_MIN(pos_y_end, mb_h); + pos_x_init = MPP_MAX(pos_x_init, 0); + pos_y_init = MPP_MAX(pos_y_init, 0); + + mpp_assert(pos_x_end > pos_x_init); + mpp_assert(pos_y_end > pos_y_init); + + cfg.force_intra = 1; + + ptr += pos_y_init * stride_h + pos_x_init; + roi_width = pos_x_end - pos_x_init; + roi_height = pos_y_end - pos_y_init; + + for (y = 0; y < roi_height; y++) { + Vepu580RoiH264BsCfg *dst = ptr; + + for (x = 0; x < roi_width; x++, dst++) + memcpy(dst, &cfg, sizeof(cfg)); + + ptr += stride_h; + } +DONE: + return ret; +} + +static MPP_RET setup_vepu580_intra_refresh(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx, RK_U32 refresh_idx) +{ + MPP_RET ret = MPP_OK; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 w = mb_w * 16; + RK_U32 h = mb_h * 16; + MppEncROIRegion *region = NULL; + RK_U32 refresh_num = ctx->cfg->rc.refresh_num; + RK_U32 stride_h = MPP_ALIGN(mb_w, 4); + RK_U32 stride_v = MPP_ALIGN(mb_h, 4); + RK_S32 roi_base_buf_size = stride_h * stride_v * 8; + RK_U32 i = 0; + + hal_h264e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en) { + ret = MPP_ERR_VALUE; + goto RET; + } + + if (ctx->roi_base_buf_size < roi_base_buf_size) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + if (ctx->roi_base_cfg_buf) + mpp_buffer_put(ctx->roi_base_cfg_buf); + mpp_buffer_get(ctx->roi_grp, &ctx->roi_base_cfg_buf, roi_base_buf_size); + ctx->roi_base_buf_size = roi_base_buf_size; + } + + mpp_assert(ctx->roi_base_cfg_buf); + RK_S32 base_cfg_fd = mpp_buffer_get_fd(ctx->roi_base_cfg_buf); + void *base_cfg_buf = mpp_buffer_get_ptr(ctx->roi_base_cfg_buf); + Vepu580RoiH264BsCfg base_cfg; + Vepu580RoiH264BsCfg *base_cfg_ptr = (Vepu580RoiH264BsCfg *)base_cfg_buf; + + base_cfg.force_intra = 0; + base_cfg.qp_adj_en = 1; + + for (i = 0; i < stride_h * stride_v; i++, base_cfg_ptr++) + memcpy(base_cfg_ptr, &base_cfg, sizeof(base_cfg)); + + region = mpp_calloc(MppEncROIRegion, 1); + + if (NULL == region) { + mpp_err_f("Failed to calloc for MppEncROIRegion !\n"); + ret = MPP_ERR_MALLOC; + } + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + region->x = 0; + region->w = w; + if (refresh_idx > 0) { + region->y = refresh_idx * 16 * refresh_num - 32; + region->h = 16 * refresh_num + 32; + } else { + region->y = refresh_idx * 16 * refresh_num; + region->h = 16 * refresh_num; + } + regs->reg_base.me_rnge.cme_srch_v = 1; + } else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) { + region->y = 0; + region->h = h; + if (refresh_idx > 0) { + region->x = refresh_idx * 16 * refresh_num - 32; + region->w = 16 * refresh_num + 32; + } else { + region->x = refresh_idx * 16 * refresh_num; + region->w = 16 * refresh_num; + } + regs->reg_base.me_rnge.cme_srch_h = 1; + } + + region->intra = 1; + region->quality = -ctx->cfg->rc.qp_delta_ip; + + region->area_map_en = 1; + region->qp_area_idx = 1; + region->abs_qp_en = 0; + + regs->reg_base.enc_pic.roi_en = 1; + regs->reg_base.roi_addr = base_cfg_fd; + vepu580_h264_set_one_roi(base_cfg_buf, region, w, h); + mpp_free(region); + mpp_buffer_sync_end(ctx->roi_base_cfg_buf); + +RET: + hal_h264e_dbg_func("leave, ret %d\n", ret); + return ret; +} + +static void setup_vepu580_roi(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) +{ + hal_h264e_dbg_func("enter\n"); + + /* memset register on start so do not clear registers again here */ + if (ctx->roi_data) { + /* roi setup */ + RK_U32 mb_w = MPP_ALIGN(ctx->cfg->prep.width, 64) / 16; + RK_U32 mb_h = MPP_ALIGN(ctx->cfg->prep.height, 64) / 16; + RK_U32 base_cfg_size = mb_w * mb_h * 8; + RK_U32 qp_cfg_size = mb_w * mb_h * 2; + RK_U32 amv_cfg_size = mb_w * mb_h / 4; + RK_U32 mv_cfg_size = mb_w * mb_h * 96 / 4; + MppEncROICfg2 *cfg = (MppEncROICfg2 *)ctx->roi_data; + + if (mpp_buffer_get_size(cfg->base_cfg_buf) >= base_cfg_size) { + regs->reg_base.enc_pic.roi_en = 1; + regs->reg_base.roi_addr = mpp_buffer_get_fd(cfg->base_cfg_buf); + } else { + mpp_err("roi base cfg buf not enough, roi is invalid"); + } + + if (cfg->roi_qp_en) { + if (mpp_buffer_get_size(cfg->qp_cfg_buf) >= qp_cfg_size) { + regs->reg_base.roi_qp_addr = mpp_buffer_get_fd(cfg->qp_cfg_buf); + regs->reg_base.roi_en.roi_qp_en = 1; + } else { + mpp_err("roi qp cfg buf not enough, roi is invalid"); + } + } + + if (cfg->roi_amv_en) { + if (mpp_buffer_get_size(cfg->amv_cfg_buf) >= amv_cfg_size) { + regs->reg_base.qoi_amv_addr = mpp_buffer_get_fd(cfg->amv_cfg_buf); + regs->reg_base.roi_en.roi_amv_en = 1; + } else { + mpp_err("roi amv cfg buf not enough, roi is invalid"); + } + } + + if (cfg->roi_mv_en) { + if (mpp_buffer_get_size(cfg->mv_cfg_buf) >= mv_cfg_size) { + regs->reg_base.qoi_mv_addr = mpp_buffer_get_fd(cfg->mv_cfg_buf); + regs->reg_base.roi_en.roi_mv_en = 1; + } else { + mpp_err("roi mv cfg buf not enough, roi is invalid"); + } + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu580_recn_refr(HalH264eVepu580Ctx *ctx, HalVepu580RegSet *regs) +{ + H264eFrmInfo *frms = ctx->frms; + HalBufs bufs = ctx->hw_recn; + RK_S32 fbc_hdr_size = ctx->pixel_buf_fbc_hdr_size; + + HalBuf *curr = hal_bufs_get_buf(bufs, frms->curr_idx); + HalBuf *refr = hal_bufs_get_buf(bufs, frms->refr_idx); + + hal_h264e_dbg_func("enter\n"); + + if (curr && curr->cnt) { + MppBuffer buf_pixel = curr->buf[0]; + MppBuffer buf_thumb = curr->buf[1]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg_base.rfpw_h_addr = fd; + regs->reg_base.rfpw_b_addr = fd; + regs->reg_base.dspw_addr = mpp_buffer_get_fd(buf_thumb); + } + + if (refr && refr->cnt) { + MppBuffer buf_pixel = refr->buf[0]; + MppBuffer buf_thumb = refr->buf[1]; + RK_S32 fd = mpp_buffer_get_fd(buf_pixel); + + mpp_assert(buf_pixel); + mpp_assert(buf_thumb); + + regs->reg_base.rfpr_h_addr = fd; + regs->reg_base.rfpr_b_addr = fd; + regs->reg_base.dspr_addr = mpp_buffer_get_fd(buf_thumb); + } + + mpp_dev_multi_offset_update(ctx->offsets, 164, fbc_hdr_size); + mpp_dev_multi_offset_update(ctx->offsets, 166, fbc_hdr_size); + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu580_split(HalVepu580RegSet *regs, MppEncCfgSet *enc_cfg) +{ + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h264e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_base.sli_splt.sli_splt = 0; + regs->reg_base.sli_splt.sli_splt_mode = 0; + regs->reg_base.sli_splt.sli_splt_cpst = 0; + regs->reg_base.sli_splt.sli_max_num_m1 = 0; + regs->reg_base.sli_splt.sli_flsh = 0; + regs->reg_base.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.sli_byte.sli_splt_byte = 0; + regs->reg_base.enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_base.sli_splt.sli_splt = 1; + regs->reg_base.sli_splt.sli_splt_mode = 0; + regs->reg_base.sli_splt.sli_splt_cpst = 0; + regs->reg_base.sli_splt.sli_max_num_m1 = 500; + regs->reg_base.sli_splt.sli_flsh = 1; + regs->reg_base.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.sli_byte.sli_splt_byte = cfg->split_arg; + regs->reg_base.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.int_en.slc_done_en = regs->reg_base.enc_pic.slen_fifo; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + RK_U32 mb_w = MPP_ALIGN(enc_cfg->prep.width, 16) / 16; + RK_U32 mb_h = MPP_ALIGN(enc_cfg->prep.height, 16) / 16; + RK_U32 slice_num = (mb_w * mb_h + cfg->split_arg - 1) / cfg->split_arg; + + regs->reg_base.sli_splt.sli_splt = 1; + regs->reg_base.sli_splt.sli_splt_mode = 1; + regs->reg_base.sli_splt.sli_splt_cpst = 0; + regs->reg_base.sli_splt.sli_max_num_m1 = 500; + regs->reg_base.sli_splt.sli_flsh = 1; + regs->reg_base.sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg_base.sli_byte.sli_splt_byte = 0; + regs->reg_base.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + + if ((cfg->split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) || + (regs->reg_base.enc_pic.slen_fifo && (slice_num > VEPU580_SLICE_FIFO_LEN))) + regs->reg_ctl.int_en.slc_done_en = 1; + + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h264e_dbg_func("leave\n"); +} + +static void calc_cime_parameter(HalVepu580RegSet *regs, H264eSps *sps) +{ + Vepu580BaseCfg *base_regs = ®s->reg_base; + RK_S32 x_gmv = base_regs->gmv.gmv_x; + RK_S32 y_gmv = base_regs->gmv.gmv_y; + RK_S32 srch_w = base_regs->me_rnge.cme_srch_h * 4; + RK_S32 srch_h = base_regs->me_rnge.cme_srch_v * 4; + RK_S32 frm_sta = 0, frm_end = 0, pic_w = 0; + RK_S32 pic_wd64 = MPP_ALIGN(sps->pic_width_in_mbs * 16, 64) / 64; + + // calc cime_linebuf_w + { + if (x_gmv - srch_w < 0) { + frm_sta = (x_gmv - srch_w - 15) / 16; + } else { + frm_sta = (x_gmv - srch_w) / 16; + } + frm_sta = mpp_clip(frm_sta, 0, pic_wd64 - 1); + + if (x_gmv + srch_w < 0) { + frm_end = pic_wd64 - 1 + (x_gmv + srch_w) / 16; + } else { + frm_end = pic_wd64 - 1 + (x_gmv + srch_w + 15) / 16; + } + frm_end = mpp_clip(frm_end, 0, pic_wd64 - 1); + + pic_w = (frm_end - frm_sta + 1) * 64; + base_regs->me_cach.cme_linebuf_w = ((pic_w != 0) ? pic_w : 64) / 64; + } + + // calc cime_cacha_h and cime_cacha_max + { + RK_U32 cime_cacha_max = 2464; + RK_U32 ctu_4_h = 1, ramb_h; + RK_U32 cur_srch_16_w, cur_srch_4_h, cur_srch_max; + RK_U32 cime_cacha_h = ctu_4_h; + + if ((x_gmv % 16 - srch_w % 16) < 0) { + cur_srch_16_w = (16 + (x_gmv % 16 - srch_w % 16) % 16 + srch_w * 2 + 15) / 16 + 1; + } else { + cur_srch_16_w = ((x_gmv % 16 - srch_w % 16) % 16 + srch_w * 2 + 15) / 16 + 1; + } + + if ((y_gmv % 4 - srch_h % 4) < 0) { + cur_srch_4_h = (4 + (y_gmv % 4 - srch_h % 4) % 4 + srch_h * 2 + 3) / 4 + ctu_4_h; + } else { + cur_srch_4_h = ((y_gmv % 4 - srch_h % 4) % 4 + srch_h * 2 + 3) / 4 + ctu_4_h; + } + + cur_srch_max = cur_srch_4_h; + + if (base_regs->me_cach.cme_linebuf_w < cur_srch_16_w) { + cur_srch_16_w = base_regs->me_cach.cme_linebuf_w; + } + + ramb_h = cur_srch_4_h; + while ((cime_cacha_h < cur_srch_max) && (cime_cacha_max > + ((cime_cacha_h - ctu_4_h) * base_regs->me_cach.cme_linebuf_w * 4 + (ramb_h * 4 * cur_srch_16_w)))) { + cime_cacha_h = cime_cacha_h + ctu_4_h; + + if (ramb_h > 2 * ctu_4_h) { + ramb_h = ramb_h - ctu_4_h; + } else { + ramb_h = ctu_4_h; + } + } + + if (cur_srch_4_h == ctu_4_h) { + cime_cacha_h = cime_cacha_h + ctu_4_h; + ramb_h = 0; + } + + if (cime_cacha_max < ((cime_cacha_h - ctu_4_h) * base_regs->me_cach.cme_linebuf_w * 4 + (ramb_h * 4 * cur_srch_16_w))) { + cime_cacha_h = cime_cacha_h - ctu_4_h; + } + base_regs->me_cach.cme_rama_h = cime_cacha_h; + + /* cime_cacha_max */ + { + RK_U32 ram_col_h = (cime_cacha_h - ctu_4_h) / ctu_4_h; + base_regs->me_cach.cme_rama_max = ram_col_h * base_regs->me_cach.cme_linebuf_w + cur_srch_16_w; + } + } +} + +static void setup_vepu580_me(HalVepu580RegSet *regs, H264eSps *sps, + H264eSlice *slice) +{ + RK_S32 level_idc = sps->level_idc; + RK_S32 cime_w = 176; + RK_S32 cime_h = 112; + RK_S32 cime_blk_w_max = 44; + RK_S32 cime_blk_h_max = 28; + + hal_h264e_dbg_func("enter\n"); + /* + * Step 1. limit the mv range by level_idc + * For level 1 and level 1b the vertical MV range is [-64,+63.75] + * For level 1.1, 1.2, 1.3 and 2 the vertical MV range is [-128,+127.75] + */ + switch (level_idc) { + case H264_LEVEL_1_0 : + case H264_LEVEL_1_b : { + cime_blk_h_max = 12; + } break; + case H264_LEVEL_1_1 : + case H264_LEVEL_1_2 : + case H264_LEVEL_1_3 : + case H264_LEVEL_2_0 : { + cime_blk_h_max = 28; + } break; + default : { + cime_blk_h_max = 28; + } break; + } + + if (cime_w < cime_blk_w_max * 4) + cime_blk_w_max = cime_w / 4; + + if (cime_h < cime_blk_h_max * 4) + cime_blk_h_max = cime_h / 4; + + /* + * Step 2. limit the mv range by image size + */ + if (cime_blk_w_max / 4 * 2 > (sps->pic_width_in_mbs * 2 + 1) / 2) + cime_blk_w_max = (sps->pic_width_in_mbs * 2 + 1) / 2 / 2 * 4; + + if (cime_blk_h_max / 4 > MPP_ALIGN(sps->pic_height_in_mbs * 16, 64) / 128 * 4) + cime_blk_h_max = MPP_ALIGN(sps->pic_height_in_mbs * 16, 64) / 128 * 16; + + regs->reg_base.me_rnge.cme_srch_h = cime_blk_w_max / 4; + regs->reg_base.me_rnge.cme_srch_v = cime_blk_h_max / 4; + regs->reg_base.me_rnge.rme_srch_h = 7; + regs->reg_base.me_rnge.rme_srch_v = 5; + regs->reg_base.me_rnge.dlt_frm_num = 0; + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_base.me_cfg.pmv_mdst_h = 0; + regs->reg_base.me_cfg.pmv_mdst_v = 0; + } else { + regs->reg_base.me_cfg.pmv_mdst_h = 5; + regs->reg_base.me_cfg.pmv_mdst_v = 5; + } + regs->reg_base.me_cfg.mv_limit = (sps->level_idc > 20) ? 2 : ((sps->level_idc >= 11) ? 1 : 0);//2; + regs->reg_base.me_cfg.pmv_num = 2; + regs->reg_base.me_cfg.rme_dis = 0; + regs->reg_base.me_cfg.fme_dis = 0; + regs->reg_base.me_cfg.lvl4_ovrd_en = 0; + + calc_cime_parameter(regs, sps); + + hal_h264e_dbg_func("leave\n"); +} + +#define H264E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) + +static RK_U32 h264e_lambda_default[58] = { + 0x00000003, 0x00000005, 0x00000006, 0x00000007, + 0x00000009, 0x0000000b, 0x0000000e, 0x00000012, + 0x00000016, 0x0000001c, 0x00000024, 0x0000002d, + 0x00000039, 0x00000048, 0x0000005b, 0x00000073, + 0x00000091, 0x000000b6, 0x000000e6, 0x00000122, + 0x0000016d, 0x000001cc, 0x00000244, 0x000002db, + 0x00000399, 0x00000489, 0x000005b6, 0x00000733, + 0x00000912, 0x00000b6d, 0x00000e66, 0x00001224, + 0x000016db, 0x00001ccc, 0x00002449, 0x00002db7, + 0x00003999, 0x00004892, 0x00005b6f, 0x00007333, + 0x00009124, 0x0000b6de, 0x0000e666, 0x00012249, + 0x00016dbc, 0x0001cccc, 0x00024492, 0x0002db79, + 0x00039999, 0x00048924, 0x0005b6f2, 0x00073333, + 0x00091249, 0x000b6de5, 0x000e6666, 0x00122492, + 0x0016dbcb, 0x001ccccc, +}; + +static void setup_vepu580_l2(HalVepu580RegSet *regs, H264eSlice *slice, MppEncHwCfg *hw) +{ + RK_U32 i; + + hal_h264e_dbg_func("enter\n"); + + regs->reg_s3.iprd_wgt_qp_hevc_0_51[0] = 0; + /* ~ */ + regs->reg_s3.iprd_wgt_qp_hevc_0_51[51] = 0; + + if (slice->slice_type == H264_I_SLICE) { + memcpy(regs->reg_s3.rdo_wgta_qp_grpa_0_51, &h264e_lambda_default[6], H264E_LAMBDA_TAB_SIZE); + } else { + memcpy(regs->reg_s3.rdo_wgta_qp_grpa_0_51, &h264e_lambda_default[6], H264E_LAMBDA_TAB_SIZE); + } + memset(regs->reg_s3.iprd_wgt_qp_hevc_0_51, 0, H264E_LAMBDA_TAB_SIZE); + + regs->reg_rc_klut.madi_cfg.madi_mode = 0; + regs->reg_rc_klut.madi_cfg.madi_thd = 25; + + regs->reg_s3.lvl32_intra_CST_THD0.lvl4_intra_cst_thd0 = 1; + regs->reg_s3.lvl32_intra_CST_THD0.lvl4_intra_cst_thd1 = 4; + regs->reg_s3.lvl32_intra_CST_THD1.lvl4_intra_cst_thd2 = 9; + regs->reg_s3.lvl32_intra_CST_THD1.lvl4_intra_cst_thd3 = 36; + + regs->reg_s3.lvl16_intra_CST_THD0.lvl8_intra_chrm_cst_thd0 = 1; + regs->reg_s3.lvl16_intra_CST_THD0.lvl8_intra_chrm_cst_thd1 = 4; + regs->reg_s3.lvl16_intra_CST_THD1.lvl8_intra_chrm_cst_thd2 = 9; + regs->reg_s3.lvl16_intra_CST_THD1.lvl8_intra_chrm_cst_thd3 = 36; + + regs->reg_s3.lvl8_intra_CST_THD0.lvl8_intra_cst_thd0 = 1; + regs->reg_s3.lvl8_intra_CST_THD0.lvl8_intra_cst_thd1 = 4; + regs->reg_s3.lvl8_intra_CST_THD1.lvl8_intra_cst_thd2 = 9; + regs->reg_s3.lvl8_intra_CST_THD1.lvl8_intra_cst_thd3 = 36; + + regs->reg_s3.lvl16_intra_UL_CST_THD.lvl16_intra_ul_cst_thld = 0; + regs->reg_s3.lvl32_intra_CST_WGT0.lvl8_intra_cst_wgt0 = 48; + regs->reg_s3.lvl32_intra_CST_WGT0.lvl8_intra_cst_wgt1 = 60; + regs->reg_s3.lvl32_intra_CST_WGT0.lvl8_intra_cst_wgt2 = 40; + regs->reg_s3.lvl32_intra_CST_WGT0.lvl8_intra_cst_wgt3 = 48; + + regs->reg_s3.lvl32_intra_CST_WGT1.lvl4_intra_cst_wgt0 = 48; + regs->reg_s3.lvl32_intra_CST_WGT1.lvl4_intra_cst_wgt1 = 60; + regs->reg_s3.lvl32_intra_CST_WGT1.lvl4_intra_cst_wgt2 = 40; + regs->reg_s3.lvl32_intra_CST_WGT1.lvl4_intra_cst_wgt3 = 48; + + regs->reg_s3.lvl16_intra_CST_WGT0.lvl16_intra_cst_wgt0 = 48; + regs->reg_s3.lvl16_intra_CST_WGT0.lvl16_intra_cst_wgt1 = 60; + regs->reg_s3.lvl16_intra_CST_WGT0.lvl16_intra_cst_wgt2 = 40; + regs->reg_s3.lvl16_intra_CST_WGT0.lvl16_intra_cst_wgt3 = 48; + /* 0x1728 */ + regs->reg_s3.lvl16_intra_CST_WGT1.lvl8_intra_chrm_cst_wgt0 = 36; + regs->reg_s3.lvl16_intra_CST_WGT1.lvl8_intra_chrm_cst_wgt1 = 42; + regs->reg_s3.lvl16_intra_CST_WGT1.lvl8_intra_chrm_cst_wgt2 = 28; + regs->reg_s3.lvl16_intra_CST_WGT1.lvl8_intra_chrm_cst_wgt3 = 32; + + regs->reg_s3.RDO_QUANT.quant_f_bias_P = 171; + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_s3.RDO_QUANT.quant_f_bias_I = 683; + regs->reg_s3.ATR_THD0.atr_thd0 = 1; + regs->reg_s3.ATR_THD0.atr_thd1 = 4; + regs->reg_s3.ATR_THD1.atr_thd2 = 36; + } else { + regs->reg_s3.RDO_QUANT.quant_f_bias_I = 583; + regs->reg_s3.ATR_THD0.atr_thd0 = 4; + regs->reg_s3.ATR_THD0.atr_thd1 = 16; + regs->reg_s3.ATR_THD1.atr_thd2 = 81; + } + regs->reg_s3.ATR_THD1.atr_thdqp = 45; + + if (slice->slice_type == H264_I_SLICE) { + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt0 = 16; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt1 = 16; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt2 = 16; + + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt0 = 22; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt1 = 21; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt2 = 20; + + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt0 = 20; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt1 = 18; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt2 = 16; + } else { + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt0 = 25; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt1 = 20; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt2 = 16; + + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt0 = 25; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt1 = 20; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt2 = 18; + + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt0 = 25; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt1 = 20; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt2 = 16; + } + /* CIME */ + { + /* 0x1760 */ + regs->reg_s3.cime_sqi_cfg.cime_sad_mod_sel = 0; + regs->reg_s3.cime_sqi_cfg.cime_sad_use_big_block = 1; + regs->reg_s3.cime_sqi_cfg.cime_pmv_set_zero = 1; + regs->reg_s3.cime_sqi_cfg.cime_pmv_num = 3; + + /* 0x1764 */ + regs->reg_s3.cime_sqi_thd.cime_mvd_th0 = 32; + regs->reg_s3.cime_sqi_thd.cime_mvd_th1 = 80; + regs->reg_s3.cime_sqi_thd.cime_mvd_th2 = 128; + + /* 0x1768 */ + regs->reg_s3.cime_sqi_multi0.cime_multi0 = 4; + regs->reg_s3.cime_sqi_multi0.cime_multi1 = 8; + regs->reg_s3.cime_sqi_multi1.cime_multi2 = 24; + regs->reg_s3.cime_sqi_multi1.cime_multi3 = 24; + } + + /* RIME && FME */ + { + /* 0x1770 */ + regs->reg_s3.rime_sqi_thd.cime_sad_th0 = 50; + regs->reg_s3.rime_sqi_thd.rime_mvd_th0 = 3; + regs->reg_s3.rime_sqi_thd.rime_mvd_th1 = 8; + regs->reg_s3.rime_sqi_multi.rime_multi0 = 4; + regs->reg_s3.rime_sqi_multi.rime_multi1 = 32; + regs->reg_s3.rime_sqi_multi.rime_multi2 = 128; + + /* 0x1778 */ + regs->reg_s3.fme_sqi_thd0.cime_sad_pu16_th = 2; + + /* 0x177C */ + regs->reg_s3.fme_sqi_thd1.move_lambda = 1; + } + + if (slice->slice_type == H264_I_SLICE) { + for (i = 0; i < MPP_ARRAY_ELEMS(h264_aq_tthd_default); i++) { + regs->reg_rc_klut.aq_tthd[i] = hw->aq_thrd_i[i]; + regs->reg_rc_klut.aq_step[i] = hw->aq_step_i[i] & 0x3f; + } + } else { + for (i = 0; i < MPP_ARRAY_ELEMS(h264_P_aq_step_default); i++) { + regs->reg_rc_klut.aq_tthd[i] = hw->aq_thrd_p[i]; + regs->reg_rc_klut.aq_step[i] = hw->aq_step_p[i] & 0x3f; + } + } + + hal_h264e_dbg_func("leave\n"); +} + +static void setup_vepu580_ext_line_buf(HalVepu580RegSet *regs, HalH264eVepu580Ctx *ctx) +{ + RK_S32 offset = 0; + RK_S32 fd; + + if (!ctx->ext_line_buf) { + regs->reg_base.ebufb_addr = 0; + regs->reg_base.ebufb_addr = 0; + return; + } + + fd = mpp_buffer_get_fd(ctx->ext_line_buf); + offset = ctx->ext_line_buf_size; + + regs->reg_base.ebuft_addr = fd; + regs->reg_base.ebufb_addr = fd; + + mpp_dev_multi_offset_update(ctx->offsets, 182, offset); + + /* rcb info for sram */ + if (!disable_rcb_buf) { + MppDevRcbInfoCfg rcb_cfg; + + rcb_cfg.reg_idx = 183; + rcb_cfg.size = offset; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); + + rcb_cfg.reg_idx = 182; + rcb_cfg.size = 0; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); + } +} + +static MPP_RET setup_vepu580_dual_core(HalH264eVepu580Ctx *ctx, H264SliceType slice_type, + RK_S32 curr_slot, RK_S32 refr_slot) +{ + Vepu580BaseCfg *reg_base = &ctx->regs_set->reg_base; + RK_U32 dchs_ofst = 9; + RK_U32 dchs_rxe = 1; + RK_U32 dchs_txe = 1; + RK_U32 rxid = 0; + + if (ctx->task_cnt == 1) + return MPP_OK; + + if (curr_slot < 0 || curr_slot >= H264E_MAX_REFS_CNT || refr_slot < 0 || refr_slot >= H264E_MAX_REFS_CNT) { + mpp_loge_f("dual core setup failed! invalid frame slot index. curr_slot:%d, refr_slot:%d", + curr_slot, refr_slot); + return MPP_ERR_UNKNOW; + } + + if (slice_type == H264_I_SLICE) { + ctx->curr_idx = 0; + ctx->prev_idx = 0; + dchs_rxe = 0; + rxid = 0; + } else { + rxid = ctx->slot_to_dchs_txid[refr_slot]; + } + + if (!reg_base->enc_pic.cur_frm_ref) + dchs_txe = 0; + + ctx->slot_to_dchs_txid[curr_slot] = ctx->curr_idx; + + reg_base->dual_core.dchs_txid = ctx->curr_idx; + reg_base->dual_core.dchs_rxid = rxid; + reg_base->dual_core.dchs_txe = dchs_txe; + reg_base->dual_core.dchs_rxe = dchs_rxe; + reg_base->dual_core.dchs_ofst = dchs_ofst; + + ctx->prev_idx = ctx->curr_idx++; + if (ctx->curr_idx > 3) + ctx->curr_idx = 0; + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu580_gen_regs(void *hal, HalEncTask *task) +{ + HalH264eVepu580Ctx *ctx = (HalH264eVepu580Ctx *)hal; + HalVepu580RegSet *regs = ctx->regs_set; + MppEncCfgSet *cfg = ctx->cfg; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + EncRcTask *rc_task = task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + MPP_RET ret = MPP_OK; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h264e_dbg_func("enter %p\n", hal); + hal_h264e_dbg_detail("frame %d generate regs now", ctx->frms->seq_idx); + + /* register setup */ + memset(regs, 0, sizeof(*regs)); + + setup_vepu580_normal(regs); + ret = setup_vepu580_prep(regs, &ctx->cfg->prep, task); + if (ret) + return ret; + + setup_vepu580_codec(regs, sps, pps, slice); + setup_vepu580_dual_core(ctx, slice->slice_type, task->flags.curr_idx, task->flags.refr_idx); + setup_vepu580_rdo_pred(regs, sps, pps, slice); + setup_vepu580_rdo_cfg(®s->reg_rdo); + setup_vepu580_rdo_bias_cfg(®s->reg_rdo, &cfg->hw); + + // scl cfg + memcpy(®s->reg_scl, vepu580_540_h264_flat_scl_tab, sizeof(vepu580_540_h264_flat_scl_tab)); + + setup_vepu580_rc_base(regs, ctx, rc_task); + setup_vepu580_io_buf(regs, ctx->offsets, task); + setup_vepu580_roi(regs, ctx); + setup_vepu580_recn_refr(ctx, regs); + + regs->reg_base.meiw_addr = task->md_info ? mpp_buffer_get_fd(task->md_info) : 0; + regs->reg_base.enc_pic.mei_stor = task->md_info ? 1 : 0; + regs->reg_base.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg_base.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + setup_vepu580_split(regs, cfg); + setup_vepu580_me(regs, sps, slice); + + if (frm_status->is_i_refresh) + setup_vepu580_intra_refresh(regs, ctx, frm_status->seq_idx % cfg->rc.gop); + + if (cfg->tune.deblur_en && (!rc_task->info.complex_scene) && + cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC && + cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + if (MPP_OK != setup_vepu580_qpmap_buf(ctx)) + mpp_err("qpmap malloc buffer failed!\n"); + } + + vepu580_set_osd(&ctx->osd_cfg); + setup_vepu580_l2(regs, slice, &cfg->hw); + setup_vepu580_ext_line_buf(regs, ctx); + vepu580_h264e_tune_reg_patch(ctx->tune); + + /* two pass register patch */ + if (frm->save_pass1) + vepu580_h264e_save_pass1_patch(regs, ctx); + + if (frm->use_pass1) + vepu580_h264e_use_pass1_patch(regs, ctx); + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu580_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu580Ctx *ctx = (HalH264eVepu580Ctx *)hal; + HalVepu580RegSet *regs = ctx->regs_set; + + (void) task; + + hal_h264e_dbg_func("enter %p\n", hal); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = ®s->reg_ctl; + wr_cfg.size = sizeof(regs->reg_ctl); + wr_cfg.offset = VEPU580_CONTROL_CFG_OFFSET; +#if DUMP_REG + { + RK_U32 i; + RK_U32 *reg = (RK_U32)wr_cfg.reg; + for ( i = 0; i < sizeof(regs->reg_ctl) / sizeof(RK_U32); i++) { + /* code */ + mpp_log("reg[%d] = 0x%08x\n", i, reg[i]); + } + + } +#endif + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = ®s->reg_base; + wr_cfg.size = sizeof(regs->reg_base); + wr_cfg.offset = VEPU580_BASE_CFG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = ®s->reg_rc_klut; + wr_cfg.size = sizeof(regs->reg_rc_klut); + wr_cfg.offset = VEPU580_RC_KLUT_CFG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = ®s->reg_s3; + wr_cfg.size = sizeof(regs->reg_s3); + wr_cfg.offset = VEPU580_SECTION_3_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + wr_cfg.reg = ®s->reg_rdo; + wr_cfg.size = sizeof(regs->reg_rdo); + wr_cfg.offset = VEPU580_RDO_CFG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_scl; + wr_cfg.size = sizeof(regs->reg_scl); + wr_cfg.offset = VEPU580_SCL_CFG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + wr_cfg.reg = ®s->reg_osd; + wr_cfg.size = sizeof(regs->reg_osd); + wr_cfg.offset = VEPU580_OSD_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->offsets); + if (ret) { + mpp_err_f("set register offsets failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_ctl.int_sta; + rd_cfg.size = sizeof(RK_U32); + rd_cfg.offset = VEPU580_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + rd_cfg.reg = ®s->reg_st; + rd_cfg.size = sizeof(regs->reg_st); + rd_cfg.offset = VEPU580_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + /* send request to hardware */ + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static MPP_RET hal_h264e_vepu580_status_check(HalVepu580RegSet *regs) +{ + MPP_RET ret = MPP_OK; + + if (regs->reg_ctl.int_sta.lkt_node_done_sta) + hal_h264e_dbg_detail("lkt_done finish"); + + if (regs->reg_ctl.int_sta.enc_done_sta) + hal_h264e_dbg_detail("enc_done finish"); + + if (regs->reg_ctl.int_sta.slc_done_sta) + hal_h264e_dbg_detail("enc_slice finsh"); + + if (regs->reg_ctl.int_sta.sclr_done_sta) + hal_h264e_dbg_detail("safe clear finsh"); + + if (regs->reg_ctl.int_sta.bsf_oflw_sta) { + mpp_err_f("bit stream overflow"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.brsp_otsd_sta) { + mpp_err_f("bus write full"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wbus_err_sta) { + mpp_err_f("bus write error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.rbus_err_sta) { + mpp_err_f("bus read error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wdg_sta) { + ret = MPP_NOK; + mpp_err_f("wdg timeout"); + } + + return ret; +} + +static MPP_RET hal_h264e_vepu580_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu580Ctx *ctx = (HalH264eVepu580Ctx *)hal; + HalVepu580RegSet *regs = &ctx->regs_sets[task->flags.reg_idx]; + RK_U32 split_out = ctx->cfg->split.split_out; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + H264NaluType type = (task->rc_task->frm.is_idr != 0) ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppEncH264HwCfg *hw_cfg = &ctx->cfg->h264.hw_cfg; + RK_S32 i; + + hal_h264e_dbg_func("enter %p\n", hal); + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (task->rc_task->frm.save_pass1) + split_out = 0; + + /* update split_out in hw_cfg */ + hw_cfg->hw_split_out = split_out; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len; + RK_U32 slice_last; + MppDevPollCfg *poll_cfg = (MppDevPollCfg *)((char *)ctx->poll_cfgs + + task->flags.reg_idx * ctx->poll_cfg_size); + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = ((split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) != 0) ? 1 : ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].last; + slice_len = poll_cfg->slice_info[i].length; + + mpp_packet_add_segment_info(pkt, type, offset, slice_len); + offset += slice_len; + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) { + param.length = slice_len; + + if (slice_last) + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + else + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + + mpp_callback(ctx->output_cb, ¶m); + } + } + } while (!slice_last); + + ret = hal_h264e_vepu580_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + ret = hal_h264e_vepu580_status_check(regs); + if (!ret) + task->hw_length += regs->reg_st.bs_lgth_l32; + } + + mpp_packet_add_segment_info(pkt, type, offset, regs->reg_st.bs_lgth_l32); + } + + if (!(split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) && !ret) { + HalH264eVepuStreamAmend *amend = &ctx->amend_sets[task->flags.reg_idx]; + + if (amend->enable) { + amend->old_length = task->hw_length; + amend->slice->is_multi_slice = (ctx->cfg->split.split_mode > 0); + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + task->hw_length = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = task->hw_length; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + + hal_h264e_dbg_func("leave %p ret %d\n", hal, ret); + + return ret; +} + +static MPP_RET hal_h264e_vepu580_ret_task(void * hal, HalEncTask * task) +{ + HalH264eVepu580Ctx *ctx = (HalH264eVepu580Ctx *)hal; + HalVepu580RegSet *regs = &ctx->regs_sets[task->flags.reg_idx]; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + + hal_h264e_dbg_func("enter %p\n", hal); + + // update total hardware length + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = regs->reg_st.qp_sum / mbs; + rc_info->madi = (regs->reg_st.st_bnum_b16.num_b16 == 0) ? 0 : + regs->reg_st.madi / regs->reg_st.st_bnum_b16.num_b16; + rc_info->madp = (regs->reg_st.st_bnum_cme.num_ctu == 0) ? 0 : + regs->reg_st.madp / regs->reg_st.st_bnum_cme.num_ctu; + rc_info->iblk4_prop = (regs->reg_st.st_pnum_i4.pnum_i4 + + regs->reg_st.st_pnum_i8.pnum_i8 + + regs->reg_st.st_pnum_i16.pnum_i16) * 256 / mbs; + + rc_info->sse = ((RK_S64)regs->reg_st.sse_h32 << 16) + (regs->reg_st.st_sse_bsl.sse_l16 & 0xffff); + rc_info->lvl16_inter_num = regs->reg_st.st_pnum_p16.pnum_p16; + rc_info->lvl8_inter_num = regs->reg_st.st_pnum_p8.pnum_p8; + rc_info->lvl16_intra_num = regs->reg_st.st_pnum_i16.pnum_i16; + rc_info->lvl8_intra_num = regs->reg_st.st_pnum_i8.pnum_i8; + rc_info->lvl4_intra_num = regs->reg_st.st_pnum_i4.pnum_i4; + + ctx->hal_rc_cfg.bit_real = rc_info->bit_real; + ctx->hal_rc_cfg.quality_real = rc_info->quality_real; + ctx->hal_rc_cfg.iblk4_prop = rc_info->iblk4_prop; + + task->hal_ret.data = &ctx->hal_rc_cfg; + task->hal_ret.number = 1; + + //RK_U32 madi_th_cnt0 = ctx->regs_set->reg_st.madi_b16num0; + RK_U32 madi_th_cnt1 = ctx->regs_set->reg_st.madi_b16num1; + RK_U32 madi_th_cnt2 = ctx->regs_set->reg_st.madi_b16num2; + RK_U32 madi_th_cnt3 = ctx->regs_set->reg_st.madi_b16num3; + //RK_U32 madp_th_cnt0 = ctx->regs_set->reg_st.md_sad_b16num0; + RK_U32 madp_th_cnt1 = ctx->regs_set->reg_st.md_sad_b16num1; + RK_U32 madp_th_cnt2 = ctx->regs_set->reg_st.md_sad_b16num2; + RK_U32 madp_th_cnt3 = ctx->regs_set->reg_st.md_sad_b16num3; + + RK_U32 md_cnt = (24 * madp_th_cnt3 + 22 * madp_th_cnt2 + 17 * madp_th_cnt1) >> 2; + RK_U32 madi_cnt = (6 * madi_th_cnt3 + 5 * madi_th_cnt2 + 4 * madi_th_cnt1) >> 2; + + rc_info->motion_level = 0; + if (md_cnt * 100 > 15 * mbs) + rc_info->motion_level = 200; + else if (md_cnt * 100 > 5 * mbs) + rc_info->motion_level = 100; + else + rc_info->motion_level = 0; + + rc_info->complex_level = 0; + if (madi_cnt * 100 > 30 * mbs) + rc_info->complex_level = 2; + else if (madi_cnt * 100 > 13 * mbs) + rc_info->complex_level = 1; + else + rc_info->complex_level = 0; + + hal_h264e_dbg_rc("motion_level %u, complex_level %u\n", rc_info->motion_level, rc_info->complex_level); + + vepu580_h264e_tune_stat_update(ctx->tune, task); + + mpp_dev_multi_offset_reset(ctx->offsets); + + if (ctx->dpb) { + h264e_dpb_hal_end(ctx->dpb, task->flags.curr_idx); + h264e_dpb_hal_end(ctx->dpb, task->flags.refr_idx); + } + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu580 = { + .name = "hal_h264e_vepu580", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu580Ctx), + .flag = 0, + .init = hal_h264e_vepu580_init, + .deinit = hal_h264e_vepu580_deinit, + .prepare = hal_h264e_vepu580_prepare, + .get_task = hal_h264e_vepu580_get_task, + .gen_regs = hal_h264e_vepu580_gen_regs, + .start = hal_h264e_vepu580_start, + .wait = hal_h264e_vepu580_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu580_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu580) diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu580.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu580.h new file mode 100644 index 000000000..1d2c0abc7 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu580.h @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU580_H +#define HAL_H264E_VEPU580_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h264e_vepu580; + +#endif /* HAL_H264E_VEPU541_H */ \ No newline at end of file diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu580_reg.h b/mpp/hal/rkenc/h264e/hal_h264e_vepu580_reg.h new file mode 100644 index 000000000..3e102296a --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu580_reg.h @@ -0,0 +1,2930 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU580_REG_H +#define HAL_H264E_VEPU580_REG_H + +#include "rk_type.h" + +#define VEPU580_CONTROL_CFG_OFFSET (0 * sizeof(RK_U32)) +#define VEPU580_BASE_CFG_OFFSET (160 * sizeof(RK_U32)) +#define VEPU580_RC_KLUT_CFG_OFFSET (1024 * sizeof(RK_U32)) +#define VEPU580_SECTION_3_OFFSET (1472 * sizeof(RK_U32)) +#define VEPU580_RDO_CFG_OFFSET (2048 * sizeof(RK_U32)) +#define VEPU580_SCL_CFG_OFFSET (2176 * sizeof(RK_U32)) +#define VEPU580_OSD_OFFSET (3072 * sizeof(RK_U32)) +#define VEPU580_STATUS_OFFSET (4096 * sizeof(RK_U32)) +#define VEPU580_DBG_OFFSET (5120 * sizeof(RK_U32)) +#define VEPU580_REG_BASE_HW_STATUS 0x2c + +typedef struct { + RK_U32 lt_pos_x : 10; + RK_U32 reserved0 : 6; + RK_U32 lt_pos_y : 10; + RK_U32 reserved1 : 6; +} OsdLtPos; + +typedef struct { + RK_U32 rb_pos_x : 10; + RK_U32 reserved0 : 6; + RK_U32 rb_pos_y : 10; + RK_U32 reserved1 : 6; +} OsdRbPos; + +typedef struct OSD_POS_NEW { + OsdLtPos lt; /* left-top */ + OsdRbPos rb; /* right-bottom */ +} OSD_POS_NEW; + +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct Vepu580ControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 reserved : 2; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } version; + + /* 0x4 - 0xc */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 2; + RK_U32 reserved : 22; + } enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } enc_clr; + + /* 0x18 - 0x1c */ + RK_U32 reserved6_7[2]; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 slc_done_en : 1; + RK_U32 bsf_oflw_en : 1; + RK_U32 brsp_otsd_en : 1; + RK_U32 wbus_err_en : 1; + RK_U32 rbus_err_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 reserved : 22; + } int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 slc_done_msk : 1; + RK_U32 bsf_oflw_msk : 1; + RK_U32 brsp_otsd_msk : 1; + RK_U32 wbus_err_msk : 1; + RK_U32 rbus_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_msk : 1; + RK_U32 reserved : 22; + } int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 slc_done_clr : 1; + RK_U32 bsf_oflw_clr : 1; + RK_U32 brsp_otsd_clr : 1; + RK_U32 wbus_err_clr : 1; + RK_U32 rbus_err_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_clr : 1; + RK_U32 reserved : 22; + } int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 slc_done_sta : 1; + + RK_U32 bsf_oflw_sta : 1; + RK_U32 brsp_otsd_sta : 1; + RK_U32 wbus_err_sta : 1; + RK_U32 rbus_err_sta : 1; + + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_sta : 1; + RK_U32 reserved : 22; + } int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 lpfw_bus_ordr : 1; + RK_U32 cmvw_bus_ordr : 1; + RK_U32 dspw_bus_ordr : 1; + RK_U32 rfpw_bus_ordr : 1; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 3; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 afbc_bsize : 1; + RK_U32 ebufw_bus_ordr : 1; + RK_U32 rec_nfbc_bus_edin : 3; + } dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 reserved : 7; + RK_U32 dspr_otsd : 1; + RK_U32 reserved1 : 8; + RK_U32 axi_brsp_cke : 8; + RK_U32 reserved2 : 8; + } dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 rfp_load_thd : 8; + } enc_wdg; + + /* 0x0000003c reg15 */ + struct { + RK_U32 hurry_en : 1; + RK_U32 hurry_low : 3; + RK_U32 hurry_mid : 3; + RK_U32 hurry_high : 3; + RK_U32 reserved : 22; + } qos_cfg; + + /* 0x00000040 reg16 */ + struct { + RK_U32 qos_period : 16; + RK_U32 reserved : 16; + } qos_perd; + + /* 0x00000044 reg17 */ + RK_U32 hurry_thd_low; + + /* 0x00000048 reg18 */ + RK_U32 hurry_thd_mid; + + /* 0x0000004c reg19 */ + RK_U32 hurry_thd_high; + + /* 0x00000050 reg20 */ + struct { + RK_U32 idle_en_core : 1; + RK_U32 idle_en_axi : 1; + RK_U32 idle_en_ahb : 1; + RK_U32 reserved : 29; + } enc_idle_en; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 enc_done_tmvp_en : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 reserved : 28; + } func_en; + + /* 0x00000058 reg22 */ + struct { + RK_U32 tq8_ckg : 1; + RK_U32 tq4_ckg : 1; + RK_U32 bits_ckg_8x8 : 1; + RK_U32 bits_ckg_4x4_1 : 1; + RK_U32 bits_ckg_4x4_0 : 1; + RK_U32 inter_mode_ckg : 1; + RK_U32 inter_ctrl_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 reserved : 22; + } rdo_ckg; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } enc_id; +} Vepu580ControlCfg; + +/* class: buffer/video syntax */ +/* 0x00000280 reg160 - 0x000003f4 reg253*/ +typedef struct Vepu580BaseCfg_t { + /* 0x00000280 reg160 */ + RK_U32 adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 cmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 cmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 bsbr_addr; + + /* 0x000002bc reg175 */ + RK_U32 adr_bsbs; + + /* 0x000002c0 reg176 */ + RK_U32 lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 roi_addr; + + /* 0x000002cc reg179 */ + RK_U32 roi_qp_addr; + + /* 0x000002d0 reg180 */ + RK_U32 qoi_amv_addr; + + /* 0x000002d4 reg181 */ + RK_U32 qoi_mv_addr; + + /* 0x000002d8 reg182 */ + RK_U32 ebuft_addr; + + /* 0x000002dc reg183 */ + RK_U32 ebufb_addr; + + /* 0x2e0 - 0x2fc */ + RK_U32 reserved184_191[8]; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 1; + RK_U32 roi_en : 1; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 reserved : 3; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur : 5; + RK_U32 log2_ctu_num : 5; + RK_U32 reserved1 : 6; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } enc_pic; + + /* 0x00000304 reg193 */ + struct { + RK_U32 dchs_txid : 2; + RK_U32 dchs_rxid : 2; + RK_U32 dchs_txe : 1; + RK_U32 dchs_rxe : 1; + RK_U32 reserved : 10; + RK_U32 dchs_ofst : 11; + RK_U32 reserved1 : 5; + } dual_core; + + /* 0x308 - 0x30c */ + RK_U32 reserved194_195[2]; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_range : 1; + RK_U32 out_fmt : 1; + RK_U32 reserved : 24; + } src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 reserved0 : 26; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 txa_en : 1; + RK_U32 afbcd_en : 1; + RK_U32 reserved1 : 1; + } src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 17; + RK_U32 reserved : 15; + } src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } src_strd1; + + /* 0x33c - 0x34c */ + RK_U32 reserved207_211[5]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 aq_mode : 1; + RK_U32 reserved : 9; + RK_U32 rc_ctu_num : 20; + } rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } rc_tgt; + + /* 0x35c */ + RK_U32 reserved_215; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } sli_cnum; + + /* 0x36c */ + RK_U32 reserved_219; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cme_srch_h : 4; + RK_U32 cme_srch_v : 4; + RK_U32 rme_srch_h : 3; + RK_U32 rme_srch_v : 3; + RK_U32 reserved : 2; + RK_U32 dlt_frm_num : 16; + } me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 pmv_mdst_h : 8; + RK_U32 pmv_mdst_v : 8; + RK_U32 mv_limit : 2; + RK_U32 pmv_num : 2; + RK_U32 colmv_stor : 1; + RK_U32 colmv_load : 1; + RK_U32 rme_dis : 3; + RK_U32 reserved : 2; + RK_U32 fme_dis : 3; + RK_U32 reserved1 : 1; + RK_U32 lvl4_ovrd_en : 1; + } me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cme_rama_max : 11; + RK_U32 cme_rama_h : 5; + RK_U32 cach_l2_tag : 2; + RK_U32 cme_linebuf_w : 9; + RK_U32 reserved : 5; + } me_cach; + + /* 0x37c */ + RK_U32 reserved_223; + + /* 0x00000380 reg224 */ + struct { + RK_U32 gmv_x : 13; + RK_U32 reserved : 3; + RK_U32 gmv_y : 13; + RK_U32 reserved1 : 3; + } gmv; + + /* 0x384 - 0x38c */ + RK_U32 reserved225_227[3]; + + /* 0x00000390 reg228 */ + struct { + RK_U32 roi_qp_en : 1; + RK_U32 roi_amv_en : 1; + RK_U32 roi_mv_en : 1; + RK_U32 reserved : 29; + } roi_en; + + /* 0x394 - 0x39c */ + RK_U32 reserved229_231[3]; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 rect_size : 1; + RK_U32 inter_4x4 : 1; + RK_U32 arb_sel : 1; + RK_U32 vlc_lmt : 1; + RK_U32 chrm_spcl : 1; + RK_U32 rdo_mask : 8; + RK_U32 ccwa_e : 1; + RK_U32 reserved : 1; + RK_U32 atr_e : 1; + RK_U32 reserved1 : 3; + RK_U32 atf_intra_e : 1; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved2 : 10; + } rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 vthd_y : 12; + RK_U32 reserved : 4; + RK_U32 vthd_c : 12; + RK_U32 reserved1 : 4; + } iprd_csts; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_ref_idc : 2; + RK_U32 nal_unit_type : 5; + RK_U32 reserved : 25; + } synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 max_fnum : 4; + RK_U32 drct_8x8 : 1; + RK_U32 mpoc_lm4 : 4; + RK_U32 reserved : 23; + } synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 etpy_mode : 1; + RK_U32 trns_8x8 : 1; + RK_U32 csip_flag : 1; + RK_U32 num_ref0_idx : 2; + RK_U32 num_ref1_idx : 2; + RK_U32 pic_init_qp : 6; + RK_U32 cb_ofst : 5; + RK_U32 cr_ofst : 5; + RK_U32 wght_pred : 1; + RK_U32 dbf_cp_flg : 1; + RK_U32 reserved : 7; + } synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 sli_type : 2; + RK_U32 pps_id : 8; + RK_U32 drct_smvp : 1; + RK_U32 num_ref_ovrd : 1; + RK_U32 cbc_init_idc : 2; + RK_U32 reserved : 2; + RK_U32 frm_num : 16; + } synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 idr_pid : 16; + RK_U32 poc_lsb : 16; + } synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 rodr_pic_idx : 2; + RK_U32 ref_list0_rodr : 1; + RK_U32 sli_beta_ofst : 4; + RK_U32 sli_alph_ofst : 4; + RK_U32 dis_dblk_idc : 2; + RK_U32 reserved : 3; + RK_U32 rodr_pic_num : 16; + } synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 nopp_flg : 1; + RK_U32 ltrf_flg : 1; + RK_U32 arpm_flg : 1; + RK_U32 mmco4_pre : 1; + RK_U32 mmco_type0 : 3; + RK_U32 mmco_parm0 : 16; + RK_U32 mmco_type1 : 3; + RK_U32 mmco_type2 : 3; + RK_U32 reserved : 3; + } synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 mmco_parm1 : 16; + RK_U32 mmco_parm2 : 16; + } synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 long_term_frame_idx0 : 4; + RK_U32 long_term_frame_idx1 : 4; + RK_U32 long_term_frame_idx2 : 4; + RK_U32 reserved : 20; + } synt_refm2; + + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } synt_refm3_hevc; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } synt_long_refm0; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } synt_long_refm1; + + /* 0x3e0 - 0x3ec */ + RK_U32 reserved248_251[4]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 mv_v_lmt_thd : 14; + RK_U32 reserved : 1; + RK_U32 mv_v_lmt_en : 1; + RK_U32 reserved1 : 15; + RK_U32 sli_crs_en : 1; + } sli_cfg; + + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 8; + RK_U32 reserved : 8; + RK_U32 tile_y : 8; + RK_U32 reserved1 : 8; + } tile_pos; +} Vepu580BaseCfg; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x000010e0 reg1080 */ +typedef struct Vepu580RcKlutCfg_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 24; + RK_U32 qpmap_mode : 2; + } roi_qthd3; + + /* 0x00001040 reg1040 */ + struct { + RK_U32 madi_mode : 1; + RK_U32 reserved : 15; + RK_U32 madi_thd : 8; + RK_U32 reserved1 : 8; + } madi_cfg; + + /* 0x00001044 reg1041 - 0x00001050 reg1044 */ + RK_U8 aq_tthd[16]; + + /* 0x00001054 reg1045 */ + /* + * 0x00001054 reg1045 - 0x00001060 reg1048 + * only low 6 bits is valid for per step. + */ + RK_U8 aq_step[16]; + + /* 0x1064 - 0x106c */ + RK_U32 reserved1049_1051[3]; + + /* 0x00001070 reg1052 */ + struct { + RK_U32 md_sad_thd0 : 8; + RK_U32 md_sad_thd1 : 8; + RK_U32 md_sad_thd2 : 8; + RK_U32 reserved : 8; + } md_sad_thd; + + /* 0x00001074 reg1053 */ + struct { + RK_U32 madi_thd0 : 8; + RK_U32 madi_thd1 : 8; + RK_U32 madi_thd2 : 8; + RK_U32 reserved : 8; + } madi_thd; + + /* 0x1078 - 0x107c */ + RK_U32 reserved1054_1055[2]; + + /* 0x00001080 reg1056 */ + struct { + RK_U32 chrm_klut_ofst : 3; + RK_U32 reserved : 29; + } klut_ofst; + + /* 0x00001084 reg1057 */ + struct { + RK_U32 chrm_klut_wgt0 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt1_l9 : 9; + } klut_wgt0; + + /* 0x00001088 reg1058 */ + struct { + RK_U32 chrm_klut_wgt1_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt2 : 18; + } klut_wgt1; + + /* 0x0000108c reg1059 */ + struct { + RK_U32 chrm_klut_wgt3 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt4_l9 : 9; + } klut_wgt2; + + /* 0x00001090 reg1060 */ + struct { + RK_U32 chrm_klut_wgt4_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt5 : 18; + } klut_wgt3; + + /* 0x00001094 reg1061 */ + struct { + RK_U32 chrm_klut_wgt6 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt7_l9 : 9; + } klut_wgt4; + + /* 0x00001098 reg1062 */ + struct { + RK_U32 chrm_klut_wgt7_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt8 : 18; + } klut_wgt5; + + /* 0x0000109c reg1063 */ + struct { + RK_U32 chrm_klut_wgt9 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt10_l9 : 9; + } klut_wgt6; + + /* 0x000010a0 reg1064 */ + struct { + RK_U32 chrm_klut_wgt10_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt11 : 18; + } klut_wgt7; + + /* 0x000010a4 reg1065 */ + struct { + RK_U32 chrm_klut_wgt12 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt13_l9 : 9; + } klut_wgt8; + + /* 0x000010a8 reg1066 */ + struct { + RK_U32 chrm_klut_wgt13_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt14 : 18; + } klut_wgt9; + + /* 0x000010ac reg1067 */ + struct { + RK_U32 chrm_klut_wgt15 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt16_l9 : 9; + } klut_wgt10; + + /* 0x000010b0 reg1068 */ + struct { + RK_U32 chrm_klut_wgt16_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt17 : 18; + } klut_wgt11; + + /* 0x000010b4 reg1069 */ + struct { + RK_U32 chrm_klut_wgt18 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt19_l9 : 9; + } klut_wgt12; + + /* 0x000010b8 reg1070 */ + struct { + RK_U32 chrm_klut_wgt19_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt20 : 18; + } klut_wgt13; + + /* 0x000010bc reg1071 */ + struct { + RK_U32 chrm_klut_wgt21 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt22_l9 : 9; + } klut_wgt14; + + /* 0x000010c0 reg1072 */ + struct { + RK_U32 chrm_klut_wgt22_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt23 : 18; + } klut_wgt15; + + /* 0x000010c4 reg1073 */ + struct { + RK_U32 chrm_klut_wgt24 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt25_l9 : 9; + } klut_wgt16; + + /* 0x000010c8 reg1074 */ + struct { + RK_U32 chrm_klut_wgt25_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt26 : 18; + } klut_wgt17; + + /* 0x000010cc reg1075 */ + struct { + RK_U32 chrm_klut_wgt27 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt28_l9 : 9; + } klut_wgt18; + + /* 0x000010d0 reg1076 */ + struct { + RK_U32 chrm_klut_wgt28_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt29 : 18; + } klut_wgt19; + + /* 0x000010d4 reg1077 */ + struct { + RK_U32 chrm_klut_wgt30 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt31_l9 : 9; + } klut_wgt20; + + /* 0x000010d8 reg1078 */ + struct { + RK_U32 chrm_klut_wgt31_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt32 : 18; + } klut_wgt21; + + /* 0x000010dc reg1079 */ + struct { + RK_U32 chrm_klut_wgt33 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt34_l9 : 9; + } klut_wgt22; + + /* 0x000010e0 reg1080 */ + struct { + RK_U32 chrm_klut_wgt34_h9 : 9; + RK_U32 reserved : 23; + } klut_wgt23; +} Vepu580RcKlutCfg; + +/* class: iprd/iprd_wgt/rdo_wgta/prei_dif/sobel */ +/* 0x00001700 reg1472 - 0x00001cd4 reg1845 */ +typedef struct Vepu580Section3_t { + /* 0x1700 */ + struct { + RK_U32 lvl4_intra_cst_thd0 : 12; + RK_U32 reserve0 : 4; + RK_U32 lvl4_intra_cst_thd1 : 12; + RK_U32 reserve1 : 4; + } lvl32_intra_CST_THD0; + + /* 0x1704 */ + struct { + RK_U32 lvl4_intra_cst_thd2 : 12; + RK_U32 reserve0 : 4; + RK_U32 lvl4_intra_cst_thd3 : 12; + RK_U32 reserve1 : 4; + } lvl32_intra_CST_THD1; + + /* 0x1708 */ + struct { + RK_U32 lvl8_intra_chrm_cst_thd0 : 12; + RK_U32 reserve0 : 4; + RK_U32 lvl8_intra_chrm_cst_thd1 : 12; + RK_U32 reserve1 : 4; + } lvl16_intra_CST_THD0; + + /* 0x170c */ + struct { + RK_U32 lvl8_intra_chrm_cst_thd2 : 12; + RK_U32 reserve0 : 4; + RK_U32 lvl8_intra_chrm_cst_thd3 : 12; + RK_U32 reserve1 : 4; + } lvl16_intra_CST_THD1; + + /* 0x1710 */ + struct { + RK_U32 lvl8_intra_cst_thd0 : 12; + RK_U32 reserve0 : 4; + RK_U32 lvl8_intra_cst_thd1 : 12; + RK_U32 reserve1 : 4; + } lvl8_intra_CST_THD0; // only 264 + + /* 0x1714 */ + struct { + RK_U32 lvl8_intra_cst_thd2 : 12; + RK_U32 reserve0 : 4; + RK_U32 lvl8_intra_cst_thd3 : 12; + RK_U32 reserve1 : 4; + } lvl8_intra_CST_THD1; // only 264 + + /* 0x1718 */ + struct { + RK_U32 lvl16_intra_ul_cst_thld : 12; + RK_U32 reserve0 : 20; + } lvl16_intra_UL_CST_THD; // only 264 + + /* 0x171c */ + struct { + RK_U32 lvl8_intra_cst_wgt0 : 8; + + RK_U32 lvl8_intra_cst_wgt1 : 8; + + RK_U32 lvl8_intra_cst_wgt2 : 8; + + RK_U32 lvl8_intra_cst_wgt3 : 8; + + } lvl32_intra_CST_WGT0; + + /* 0x1720 */ + struct { + RK_U32 lvl4_intra_cst_wgt0 : 8; + + RK_U32 lvl4_intra_cst_wgt1 : 8; + + RK_U32 lvl4_intra_cst_wgt2 : 8; + + RK_U32 lvl4_intra_cst_wgt3 : 8; + + } lvl32_intra_CST_WGT1; // + + /* 0x1724 */ + struct { + RK_U32 lvl16_intra_cst_wgt0 : 8; + + RK_U32 lvl16_intra_cst_wgt1 : 8; + + RK_U32 lvl16_intra_cst_wgt2 : 8; + + RK_U32 lvl16_intra_cst_wgt3 : 8; + + } lvl16_intra_CST_WGT0; // 7.10 + + /* 0x1728 */ + struct { + RK_U32 lvl8_intra_chrm_cst_wgt0 : 8; + + RK_U32 lvl8_intra_chrm_cst_wgt1 : 8; + + RK_U32 lvl8_intra_chrm_cst_wgt2 : 8; + + RK_U32 lvl8_intra_chrm_cst_wgt3 : 8; + + } lvl16_intra_CST_WGT1; // + + /* 0x172c */ + RK_U32 reserved_1483; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 quant_f_bias_I : 10; + RK_U32 quant_f_bias_P : 10; + RK_U32 reserve : 12; + } RDO_QUANT; + + /* 0x1734 - 0x173c */ + RK_U32 reserved1485_1487[3]; + + /* 0x00001740 reg1488 */ + // atr + struct { + RK_U32 atr_thd0 : 12; + RK_U32 reserve0 : 4; + RK_U32 atr_thd1 : 12; + RK_U32 reserve1 : 4; + } ATR_THD0; // only 264 + + /* 0x1744 */ + struct { + RK_U32 atr_thd2 : 12; + RK_U32 reserve0 : 4; + RK_U32 atr_thdqp : 6; + RK_U32 reserve1 : 10; + } ATR_THD1; // only 264 + + /* 0x1748 */ + struct { + RK_U32 atr1_thd0 : 12; + RK_U32 reserve0 : 4; + RK_U32 atr1_thd1 : 12; + RK_U32 reserve1 : 4; + } ATR_THD10; // only 264 + + /* 0x174c */ + struct { + RK_U32 atr1_thd2 : 12; + RK_U32 reserve1 : 20; + } ATR_THD11; // only 264 + + /* 0x00001750 reg1492 */ + struct { + RK_U32 lvl16_atr_wgt0 : 8; + RK_U32 lvl16_atr_wgt1 : 8; + RK_U32 lvl16_atr_wgt2 : 8; + RK_U32 reserved : 8; + } Lvl16_ATR_WGT; // only 264 + + /* 0x1754 */ + struct { + RK_U32 lvl8_atr_wgt0 : 8; + RK_U32 lvl8_atr_wgt1 : 8; + RK_U32 lvl8_atr_wgt2 : 8; + RK_U32 reserved : 8; + } Lvl8_ATR_WGT; // only 264 + + /* 0x1758 */ + struct { + RK_U32 lvl4_atr_wgt0 : 8; + RK_U32 lvl4_atr_wgt1 : 8; + RK_U32 lvl4_atr_wgt2 : 8; + RK_U32 reserved : 8; + } Lvl4_ATR_WGT; // only 264 + + /* 0x175c */ + RK_U32 reserved_1495; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_sad_mod_sel : 1; + RK_U32 cime_sad_use_big_block : 1; + RK_U32 cime_pmv_set_zero : 1; + RK_U32 reserved : 5; + RK_U32 cime_pmv_num : 2; + RK_U32 reserved1 : 22; + } cime_sqi_cfg; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_sqi_thd; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_multi0 : 10; + RK_U32 reserved : 6; + RK_U32 cime_multi1 : 10; + RK_U32 reserved1 : 6; + } cime_sqi_multi0; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi2 : 10; + RK_U32 reserved : 6; + RK_U32 cime_multi3 : 10; + RK_U32 reserved1 : 6; + } cime_sqi_multi1; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 cime_sad_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_mvd_th0 : 4; + RK_U32 reserved1 : 4; + RK_U32 rime_mvd_th1 : 4; + RK_U32 reserved2 : 4; + } rime_sqi_thd; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_sqi_multi; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 cime_sad_pu16_th : 12; + RK_U32 reserved : 4; + RK_U32 cime_sad_pu32_th : 12; + RK_U32 reserved1 : 4; + } fme_sqi_thd0; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cime_sad_pu64_th : 12; + RK_U32 reserved : 4; + RK_U32 move_lambda : 4; + RK_U32 reserved1 : 12; + } fme_sqi_thd1; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 reg1536 - 0x000018cc reg1587 */ + // struct { + // RK_U32 wgt_qp0 : 20; + // RK_U32 reserved : 12; + // } iprd_wgt_qp_hevc_0_51[52]; + RK_U32 iprd_wgt_qp_hevc_0_51[52]; + + /* 0x18d0 - 0x18fc */ + RK_U32 reserved1588_1599[12]; + + /* wgt_qp48_grpa */ + /* 0x00001900 reg1600 - 0x19cc */ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} Vepu580Section3; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x00002c98 reg2854 */ +typedef struct Vepu580RdoCfg_t { + /* 0x00002000 reg2048 */ + struct { + RK_U32 atf_pskip_en : 1; + RK_U32 reserved : 31; + } rdo_sqi_cfg; + + /* 0x00002004 reg2049 */ + struct { + RK_U32 cu64_rdo_inter_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_inter_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_inter_cime_thd0; + + /* 0x00002008 reg2050 */ + struct { + RK_U32 cu64_rdo_inter_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b64_inter_cime_thd1; + + /* 0x0000200c reg2051 */ + struct { + RK_U32 cu64_rdo_inter_var_thd00 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_inter_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_inter_var_thd0; + + /* 0x00002010 reg2052 */ + struct { + RK_U32 cu64_rdo_inter_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_inter_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_inter_var_thd1; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 cu64_rdo_inter_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_inter_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_inter_var_thd2; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 cu64_rdo_inter_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_inter_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_inter_var_thd3; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 cu64_rdo_inter_atf_wgt00 : 8; + RK_U32 cu64_rdo_inter_atf_wgt01 : 8; + RK_U32 cu64_rdo_inter_atf_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_b64_inter_atf_wgt0; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 cu64_rdo_inter_atf_wgt10 : 8; + RK_U32 cu64_rdo_inter_atf_wgt11 : 8; + RK_U32 cu64_rdo_inter_atf_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_b64_inter_atf_wgt1; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 cu64_rdo_inter_atf_wgt20 : 8; + RK_U32 cu64_rdo_inter_atf_wgt21 : 8; + RK_U32 cu64_rdo_inter_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b64_inter_atf_wgt2; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 cu64_rdo_inter_atf_wgt30 : 8; + RK_U32 cu64_rdo_inter_atf_wgt31 : 8; + RK_U32 cu64_rdo_inter_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b64_inter_atf_wgt3; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 cu64_rdo_skip_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_skip_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_skip_cime_thd0; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 cu64_rdo_skip_cime_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_skip_cime_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_skip_cime_thd1; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 cu64_rdo_skip_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_skip_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_skip_var_thd0; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 cu64_rdo_skip_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_skip_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_skip_var_thd1; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 cu64_rdo_skip_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_skip_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_skip_var_thd2; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 cu64_rdo_skip_var_thd40 : 12; + RK_U32 reserved : 4; + RK_U32 cu64_rdo_skip_var_thd41 : 12; + RK_U32 reserved1 : 4; + } rdo_b64_skip_var_thd3; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 cu64_rdo_skip_atf_wgt00 : 8; + RK_U32 cu64_rdo_skip_atf_wgt10 : 8; + RK_U32 cu64_rdo_skip_atf_wgt11 : 8; + RK_U32 cu64_rdo_skip_atf_wgt12 : 8; + } rdo_b64_skip_atf_wgt0; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 cu64_rdo_skip_atf_wgt20 : 8; + RK_U32 cu64_rdo_skip_atf_wgt21 : 8; + RK_U32 cu64_rdo_skip_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b64_skip_atf_wgt1; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 cu64_rdo_skip_atf_wgt30 : 8; + RK_U32 cu64_rdo_skip_atf_wgt31 : 8; + RK_U32 cu64_rdo_skip_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b64_skip_atf_wgt2; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 cu64_rdo_skip_atf_wgt40 : 8; + RK_U32 cu64_rdo_skip_atf_wgt41 : 8; + RK_U32 cu64_rdo_skip_atf_wgt42 : 8; + RK_U32 reserved : 8; + } rdo_b64_skip_atf_wgt3; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 cu32_rdo_intra_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_intra_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_intra_cime_thd0; + + /* 0x00002058 reg2070 */ + struct { + RK_U32 cu32_rdo_intra_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b32_intra_cime_thd1; + + /* 0x0000205c reg2071 */ + struct { + RK_U32 cu32_rdo_intra_var_thd00 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_intra_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_intra_var_thd0; + + /* 0x00002060 reg2072 */ + struct { + RK_U32 cu32_rdo_intra_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_intra_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_intra_var_thd1; + + /* 0x00002064 reg2073 */ + struct { + RK_U32 cu32_rdo_intra_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_intra_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_intra_var_thd2; + + /* 0x00002068 reg2074 */ + struct { + RK_U32 cu32_rdo_intra_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_intra_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_intra_var_thd3; + + /* 0x0000206c reg2075 */ + struct { + RK_U32 cu32_rdo_intra_atf_wgt00 : 8; + RK_U32 cu32_rdo_intra_atf_wgt01 : 8; + RK_U32 cu32_rdo_intra_atf_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_b32_intra_atf_wgt0; + + /* 0x00002070 reg2076 */ + struct { + RK_U32 cu32_rdo_intra_atf_wgt10 : 8; + RK_U32 cu32_rdo_intra_atf_wgt11 : 8; + RK_U32 cu32_rdo_intra_atf_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_b32_intra_atf_wgt1; + + /* 0x00002074 reg2077 */ + struct { + RK_U32 cu32_rdo_intra_atf_wgt20 : 8; + RK_U32 cu32_rdo_intra_atf_wgt21 : 8; + RK_U32 cu32_rdo_intra_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b32_intra_atf_wgt2; + + /* 0x00002078 reg2078 */ + struct { + RK_U32 cu32_rdo_intra_atf_wgt30 : 8; + RK_U32 cu32_rdo_intra_atf_wgt31 : 8; + RK_U32 cu32_rdo_intra_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b32_intra_atf_wgt3; + + /* 0x0000207c reg2079 */ + struct { + RK_U32 cu32_rdo_inter_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_inter_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_inter_cime_thd0; + + /* 0x00002080 reg2080 */ + struct { + RK_U32 cu32_rdo_inter_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b32_inter_cime_thd1; + + /* 0x00002084 reg2081 */ + struct { + RK_U32 cu32_rdo_inter_var_thd00 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_inter_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_inter_var_thd0; + + /* 0x00002088 reg2082 */ + struct { + RK_U32 cu32_rdo_inter_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_inter_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_inter_var_thd1; + + /* 0x0000208c reg2083 */ + struct { + RK_U32 cu32_rdo_inter_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_inter_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_inter_var_thd2; + + /* 0x00002090 reg2084 */ + struct { + RK_U32 cu32_rdo_inter_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_inter_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_inter_var_thd3; + + /* 0x00002094 reg2085 */ + struct { + RK_U32 cu32_rdo_inter_atf_wgt00 : 8; + RK_U32 cu32_rdo_inter_atf_wgt01 : 8; + RK_U32 cu32_rdo_inter_atf_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_b32_inter_atf_wgt0; + + /* 0x00002098 reg2086 */ + struct { + RK_U32 cu32_rdo_inter_atf_wgt10 : 8; + RK_U32 cu32_rdo_inter_atf_wgt11 : 8; + RK_U32 cu32_rdo_inter_atf_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_b32_inter_atf_wgt1; + + /* 0x0000209c reg2087 */ + struct { + RK_U32 cu32_rdo_inter_atf_wgt20 : 8; + RK_U32 cu32_rdo_inter_atf_wgt21 : 8; + RK_U32 cu32_rdo_inter_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b32_inter_atf_wgt2; + + /* 0x000020a0 reg2088 */ + struct { + RK_U32 cu32_rdo_inter_atf_wgt30 : 8; + RK_U32 cu32_rdo_inter_atf_wgt31 : 8; + RK_U32 cu32_rdo_inter_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b32_inter_atf_wgt3; + + /* 0x000020a4 reg2089 */ + struct { + RK_U32 cu32_rdo_skip_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_skip_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_skip_cime_thd0; + + /* 0x000020a8 reg2090 */ + struct { + RK_U32 cu32_rdo_skip_cime_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_skip_cime_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_skip_cime_thd1; + + /* 0x000020ac reg2091 */ + struct { + RK_U32 cu32_rdo_skip_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_skip_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_sskip_var_thd0; + + /* 0x000020b0 reg2092 */ + struct { + RK_U32 cu32_rdo_skip_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_skip_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_sskip_var_thd1; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 cu32_rdo_skip_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_skip_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_sskip_var_thd2; + + /* 0x000020b8 reg2094 */ + struct { + RK_U32 cu32_rdo_skip_var_thd40 : 12; + RK_U32 reserved : 4; + RK_U32 cu32_rdo_skip_var_thd41 : 12; + RK_U32 reserved1 : 4; + } rdo_b32_sskip_var_thd3; + + /* 0x000020bc reg2095 */ + struct { + RK_U32 cu32_rdo_skip_atf_wgt00 : 8; + RK_U32 cu32_rdo_skip_atf_wgt10 : 8; + RK_U32 cu32_rdo_skip_atf_wgt11 : 8; + RK_U32 cu32_rdo_skip_atf_wgt12 : 8; + } rdo_b32_skip_atf_wgt0; + + /* 0x000020c0 reg2096 */ + struct { + RK_U32 cu32_rdo_skip_atf_wgt20 : 8; + RK_U32 cu32_rdo_skip_atf_wgt21 : 8; + RK_U32 cu32_rdo_skip_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b32_skip_atf_wgt1; + + /* 0x000020c4 reg2097 */ + struct { + RK_U32 cu32_rdo_skip_atf_wgt30 : 8; + RK_U32 cu32_rdo_skip_atf_wgt31 : 8; + RK_U32 cu32_rdo_skip_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b32_skip_atf_wgt2; + + /* 0x000020c8 reg2098 */ + struct { + RK_U32 cu32_rdo_skip_atf_wgt40 : 8; + RK_U32 cu32_rdo_skip_atf_wgt41 : 8; + RK_U32 cu32_rdo_skip_atf_wgt42 : 8; + RK_U32 reserved : 8; + } rdo_b32_skip_atf_wgt3; + + /* 0x000020cc reg2099 */ + struct { + RK_U32 atf_rdo_intra_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_intra_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_intra_cime_thd0; + + /* 0x000020d0 reg2100 */ + struct { + RK_U32 atf_rdo_intra_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_intra_cime_thd1; + + /* 0x000020d4 reg2101 */ + struct { + RK_U32 atf_rdo_intra_var_thd00 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_intra_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_intra_var_thd0; + + /* 0x000020d8 reg2102 */ + struct { + RK_U32 atf_rdo_intra_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_intra_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_intra_var_thd1; + + /* 0x000020dc reg2103 */ + struct { + RK_U32 atf_rdo_intra_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_intra_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_intra_var_thd2; + + /* 0x000020e0 reg2104 */ + struct { + RK_U32 atf_rdo_intra_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_intra_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_intra_var_thd3; + + /* 0x000020e4 reg2105 */ + struct { + RK_U32 atf_rdo_intra_wgt00 : 8; + RK_U32 atf_rdo_intra_wgt01 : 8; + RK_U32 atf_rdo_intra_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_intra_atf_wgt0; + + /* 0x000020e8 reg2106 */ + struct { + RK_U32 atf_rdo_intra_wgt10 : 8; + RK_U32 atf_rdo_intra_wgt11 : 8; + RK_U32 atf_rdo_intra_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_intra_atf_wgt1; + + /* 0x000020ec reg2107 */ + struct { + RK_U32 atf_rdo_intra_wgt20 : 8; + RK_U32 atf_rdo_intra_wgt21 : 8; + RK_U32 atf_rdo_intra_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_intra_atf_wgt2; + + /* 0x000020f0 reg2108 */ + struct { + RK_U32 atf_rdo_intra_wgt30 : 8; + RK_U32 atf_rdo_intra_wgt31 : 8; + RK_U32 atf_rdo_intra_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_intra_atf_wgt3; + + /* 0x000020f4 reg2109 */ + struct { + RK_U32 cu16_rdo_inter_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu16_rdo_inter_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_inter_cime_thd0; + + /* 0x000020f8 reg2110 */ + struct { + RK_U32 cu16_rdo_inter_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b16_inter_cime_thd1; + + /* 0x000020fc reg2111 */ + struct { + RK_U32 cu16_rdo_inter_var_thd00 : 12; + RK_U32 reserved : 4; + RK_U32 cu16_rdo_inter_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_inter_var_thd0; + + /* 0x00002100 reg2112 */ + struct { + RK_U32 cu16_rdo_inter_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu16_rdo_inter_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_inter_var_thd1; + + /* 0x00002104 reg2113 */ + struct { + RK_U32 cu16_rdo_inter_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu16_rdo_inter_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_inter_var_thd2; + + /* 0x00002108 reg2114 */ + struct { + RK_U32 cu16_rdo_inter_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu16_rdo_inter_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_inter_var_thd3; + + /* 0x0000210c reg2115 */ + struct { + RK_U32 cu16_rdo_inter_atf_wgt00 : 8; + RK_U32 cu16_rdo_inter_atf_wgt01 : 8; + RK_U32 cu16_rdo_inter_atf_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_b16_inter_atf_wgt0; + + /* 0x00002110 reg2116 */ + struct { + RK_U32 cu16_rdo_inter_atf_wgt10 : 8; + RK_U32 cu16_rdo_inter_atf_wgt11 : 8; + RK_U32 cu16_rdo_inter_atf_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_b16_inter_atf_wgt1; + + /* 0x00002114 reg2117 */ + struct { + RK_U32 cu16_rdo_inter_atf_wgt20 : 8; + RK_U32 cu16_rdo_inter_atf_wgt21 : 8; + RK_U32 cu16_rdo_inter_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b16_inter_atf_wgt2; + + /* 0x00002118 reg2118 */ + struct { + RK_U32 cu16_rdo_inter_atf_wgt30 : 8; + RK_U32 cu16_rdo_inter_atf_wgt31 : 8; + RK_U32 cu16_rdo_inter_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b16_inter_atf_wgt3; + + /* 0x0000211c reg2119 */ + struct { + RK_U32 atf_rdo_skip_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_skip_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_skip_cime_thd0; + + /* 0x00002120 reg2120 */ + struct { + RK_U32 atf_rdo_skip_cime_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_skip_cime_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_skip_cime_thd1; + + /* 0x00002124 reg2121 */ + struct { + RK_U32 atf_rdo_skip_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_skip_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_skip_var_thd0; + + /* 0x00002128 reg2122 */ + struct { + RK_U32 atf_rdo_skip_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_skip_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_skip_var_thd1; + + /* 0x0000212c reg2123 */ + struct { + RK_U32 atf_rdo_skip_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_skip_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_skip_var_thd2; + + /* 0x00002130 reg2124 */ + struct { + RK_U32 atf_rdo_skip_var_thd40 : 12; + RK_U32 reserved : 4; + RK_U32 atf_rdo_skip_var_thd41 : 12; + RK_U32 reserved1 : 4; + } rdo_skip_var_thd3; + + /* 0x00002134 reg2125 */ + struct { + RK_U32 atf_rdo_skip_atf_wgt00 : 8; + RK_U32 atf_rdo_skip_atf_wgt10 : 8; + RK_U32 atf_rdo_skip_atf_wgt11 : 8; + RK_U32 atf_rdo_skip_atf_wgt12 : 8; + } rdo_skip_atf_wgt0; + + /* 0x00002138 reg2126 */ + struct { + RK_U32 atf_rdo_skip_atf_wgt20 : 8; + RK_U32 atf_rdo_skip_atf_wgt21 : 8; + RK_U32 atf_rdo_skip_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_skip_atf_wgt1; + + /* 0x0000213c reg2127 */ + struct { + RK_U32 atf_rdo_skip_atf_wgt30 : 8; + RK_U32 atf_rdo_skip_atf_wgt31 : 8; + RK_U32 atf_rdo_skip_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_skip_atf_wgt2; + + /* 0x00002140 reg2128 */ + struct { + RK_U32 atf_rdo_skip_atf_wgt40 : 8; + RK_U32 atf_rdo_skip_atf_wgt41 : 8; + RK_U32 atf_rdo_skip_atf_wgt42 : 8; + RK_U32 reserved : 8; + } rdo_skip_atf_wgt3; + + /* 0x00002144 reg2129 */ + struct { + RK_U32 cu8_rdo_intra_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_intra_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_intra_cime_thd0; + + /* 0x00002148 reg2130 */ + struct { + RK_U32 cu8_rdo_intra_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b8_intra_cime_thd1; + + /* 0x0000214c reg2131 */ + struct { + RK_U32 cu8_rdo_intra_var_thd00 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_intra_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_intra_var_thd0; + + /* 0x00002150 reg2132 */ + struct { + RK_U32 cu8_rdo_intra_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_intra_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_intra_var_thd1; + + /* 0x00002154 reg2133 */ + struct { + RK_U32 cu8_rdo_intra_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_intra_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_intra_var_thd2; + + /* 0x00002158 reg2134 */ + struct { + RK_U32 cu8_rdo_intra_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_intra_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_intra_var_thd3; + + /* 0x0000215c reg2135 */ + struct { + RK_U32 cu8_rdo_intra_atf_wgt00 : 8; + RK_U32 cu8_rdo_intra_atf_wgt01 : 8; + RK_U32 cu8_rdo_intra_atf_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_b8_intra_atf_wgt0; + + /* 0x00002160 reg2136 */ + struct { + RK_U32 cu8_rdo_intra_atf_wgt10 : 8; + RK_U32 cu8_rdo_intra_atf_wgt11 : 8; + RK_U32 cu8_rdo_intra_atf_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_b8_intra_atf_wgt1; + + /* 0x00002164 reg2137 */ + struct { + RK_U32 cu8_rdo_intra_atf_wgt20 : 8; + RK_U32 cu8_rdo_intra_atf_wgt21 : 8; + RK_U32 cu8_rdo_intra_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b8_intra_atf_wgt2; + + /* 0x00002168 reg2138 */ + struct { + RK_U32 cu8_rdo_intra_atf_wgt30 : 8; + RK_U32 cu8_rdo_intra_atf_wgt31 : 8; + RK_U32 cu8_rdo_intra_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b8_intra_atf_wgt3; + + /* 0x0000216c reg2139 */ + struct { + RK_U32 cu8_rdo_inter_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_inter_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_inter_cime_thd0; + + /* 0x00002170 reg2140 */ + struct { + RK_U32 cu8_rdo_inter_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b8_inter_cime_thd1; + + /* 0x00002174 reg2141 */ + struct { + RK_U32 cu8_rdo_inter_var_thd00 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_inter_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_inter_var_thd0; + + /* 0x00002178 reg2142 */ + struct { + RK_U32 cu8_rdo_inter_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_inter_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_inter_var_thd1; + + /* 0x0000217c reg2143 */ + struct { + RK_U32 cu8_rdo_inter_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_inter_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_inter_var_thd2; + + /* 0x00002180 reg2144 */ + struct { + RK_U32 cu8_rdo_inter_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_inter_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_inter_var_thd3; + + /* 0x00002184 reg2145 */ + struct { + RK_U32 cu8_rdo_inter_atf_wgt00 : 8; + RK_U32 cu8_rdo_inter_atf_wgt01 : 8; + RK_U32 cu8_rdo_inter_atf_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_b8_inter_atf_wgt0; + + /* 0x00002188 reg2146 */ + struct { + RK_U32 cu8_rdo_inter_atf_wgt10 : 8; + RK_U32 cu8_rdo_inter_atf_wgt11 : 8; + RK_U32 cu8_rdo_inter_atf_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_b8_inter_atf_wgt1; + + /* 0x0000218c reg2147 */ + struct { + RK_U32 cu8_rdo_inter_atf_wgt20 : 8; + RK_U32 cu8_rdo_inter_atf_wgt21 : 8; + RK_U32 cu8_rdo_inter_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b8_inter_atf_wgt2; + + /* 0x00002190 reg2148 */ + struct { + RK_U32 cu8_rdo_inter_atf_wgt30 : 8; + RK_U32 cu8_rdo_inter_atf_wgt31 : 8; + RK_U32 cu8_rdo_inter_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b8_inter_atf_wgt3; + + /* 0x00002194 reg2149 */ + struct { + RK_U32 cu8_rdo_skip_cime_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_skip_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_skip_cime_thd0; + + /* 0x00002198 reg2150 */ + struct { + RK_U32 cu8_rdo_skip_cime_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_skip_cime_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_skip_cime_thd1; + + /* 0x0000219c reg2151 */ + struct { + RK_U32 cu8_rdo_skip_var_thd10 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_skip_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_skip_var_thd0; + + /* 0x000021a0 reg2152 */ + struct { + RK_U32 cu8_rdo_skip_var_thd20 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_skip_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_skip_var_thd1; + + /* 0x000021a4 reg2153 */ + struct { + RK_U32 cu8_rdo_skip_var_thd30 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_skip_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_skip_var_thd2; + + /* 0x000021a8 reg2154 */ + struct { + RK_U32 cu8_rdo_skip_var_thd40 : 12; + RK_U32 reserved : 4; + RK_U32 cu8_rdo_skip_var_thd41 : 12; + RK_U32 reserved1 : 4; + } rdo_b8_skip_var_thd3; + + /* 0x000021ac reg2155 */ + struct { + RK_U32 cu8_rdo_skip_atf_wgt00 : 8; + RK_U32 cu8_rdo_skip_atf_wgt10 : 8; + RK_U32 cu8_rdo_skip_atf_wgt11 : 8; + RK_U32 cu8_rdo_skip_atf_wgt12 : 8; + } rdo_b8_skip_atf_wgt0; + + /* 0x000021b0 reg2156 */ + struct { + RK_U32 cu8_rdo_skip_atf_wgt20 : 8; + RK_U32 cu8_rdo_skip_atf_wgt21 : 8; + RK_U32 cu8_rdo_skip_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b8_skip_atf_wgt1; + + /* 0x000021b4 reg2157 */ + struct { + RK_U32 cu8_rdo_skip_atf_wgt30 : 8; + RK_U32 cu8_rdo_skip_atf_wgt31 : 8; + RK_U32 cu8_rdo_skip_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b8_skip_atf_wgt2; + + /* 0x000021b8 reg2158 */ + struct { + RK_U32 cu8_rdo_skip_atf_wgt40 : 8; + RK_U32 cu8_rdo_skip_atf_wgt41 : 8; + RK_U32 cu8_rdo_skip_atf_wgt42 : 8; + RK_U32 reserved : 8; + } rdo_b8_skip_atf_wgt3; + + /* 0x000021bc reg2159 */ + struct { + RK_U32 rdo_segment_cu64_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu64_th1 : 12; + RK_U32 reserved1 : 4; + } rdo_segment_b64_thd0; + + /* 0x000021c0 reg2160 */ + struct { + RK_U32 rdo_segment_cu64_th2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu64_th3 : 4; + RK_U32 rdo_segment_cu64_th4 : 4; + RK_U32 rdo_segment_cu64_th5_minus1 : 4; + RK_U32 rdo_segment_cu64_th6_minus1 : 4; + } rdo_segment_b64_thd1; + + /* 0x000021c4 reg2161 */ + struct { + RK_U32 rdo_segment_cu32_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu32_th1 : 12; + RK_U32 reserved1 : 4; + } rdo_segment_b32_thd0; + + /* 0x000021c8 reg2162 */ + struct { + RK_U32 rdo_segment_cu32_th2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu32_th3 : 2; + RK_U32 reserved1 : 2; + RK_U32 rdo_segment_cu32_th4 : 2; + RK_U32 reserved2 : 2; + RK_U32 rdo_segment_cu32_th5_minus1 : 2; + RK_U32 reserved3 : 2; + RK_U32 rdo_segment_cu32_th6_minus1 : 2; + RK_U32 reserved4 : 2; + } rdo_segment_b32_thd1; + + /* 0x000021cc reg2163 */ + struct { + RK_U32 rdo_segment_cu64_multi : 8; + RK_U32 rdo_segment_cu32_multi : 8; + RK_U32 rdo_smear_cu16_multi : 8; + RK_U32 reserved : 8; + } rdo_segment_multi; + + /* 0x000021d0 reg2164 */ + struct { + RK_U32 rdo_smear_cu16_cime_sad_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cu16_cime_sad_th1 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_smear_thd0; + + /* 0x000021d4 reg2165 */ + struct { + RK_U32 rdo_smear_cu16_cime_sad_th2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cu16_cime_sad_th3 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_smear_thd1; + + /* 0x000021d8 reg2166 */ + struct { + RK_U32 pre_intra32_cst_var_th00 : 12; + RK_U32 reserved : 4; + RK_U32 pre_intra32_cst_var_th01 : 12; + RK_U32 reserved1 : 1; + RK_U32 pre_intra32_mode_th : 3; + } preintra_b32_cst_var_thd; + + /* 0x000021dc reg2167 */ + struct { + RK_U32 pre_intra32_cst_wgt00 : 8; + RK_U32 reserved : 8; + RK_U32 pre_intra32_cst_wgt01 : 8; + RK_U32 reserved1 : 8; + } preintra_b32_cst_wgt; + + /* 0x000021e0 reg2168 */ + struct { + RK_U32 pre_intra16_cst_var_th00 : 12; + RK_U32 reserved : 4; + RK_U32 pre_intra16_cst_var_th01 : 12; + RK_U32 reserved1 : 1; + RK_U32 pre_intra16_mode_th : 3; + } preintra_b16_cst_var_thd; + + /* 0x000021e4 reg2169 */ + struct { + RK_U32 pre_intra16_cst_wgt00 : 8; + RK_U32 reserved : 8; + RK_U32 pre_intra16_cst_wgt01 : 8; + RK_U32 reserved1 : 8; + } preintra_b16_cst_wgt; +} Vepu580RdoCfg; + +/* class: scaling list */ +/* 0x00002200 reg2200 - 0x00003084 reg3105*/ +typedef struct Vepu580SclCfg_t { + /* 0x00002200 */ + RK_U16 intra8_y[64]; + RK_U16 intra8_u[64]; + RK_U16 intra8_v[64]; + RK_U16 inter8_y[64]; + RK_U16 inter8_u[64]; + RK_U16 inter8_v[64]; + /* 0x00002500 */ + RK_U32 q_iq_16_32[480]; + /* 0x00002c80 */ + RK_U32 q_dc_y16; + RK_U32 q_dc_u16; + RK_U32 q_dc_v16; + RK_U32 q_dc_v32; + /* 0x00002c90 */ + RK_U32 iq_dc_0; + RK_U32 iq_dc_1; + /* 0x00002c98 */ + RK_U32 scal_clk_sel; +} Vepu580SclCfg; + +/* class: osd */ +/* 0x00003000 reg3072 - 0x00003084 reg3105*/ +typedef struct Vepu580Osd_t { + /* 0x00003000 reg3072 */ + struct { + RK_U32 osd_lu_inv_en : 8; + RK_U32 osd_ch_inv_en : 8; + RK_U32 osd_lu_inv_msk : 8; + RK_U32 osd_ch_inv_msk : 8; + } osd_inv_en; + + /* 0x00003004 reg3073 */ + struct { + RK_U32 osd_ithd_r0 : 4; + RK_U32 osd_ithd_r1 : 4; + RK_U32 osd_ithd_r2 : 4; + RK_U32 osd_ithd_r3 : 4; + RK_U32 osd_ithd_r4 : 4; + RK_U32 osd_ithd_r5 : 4; + RK_U32 osd_ithd_r6 : 4; + RK_U32 osd_ithd_r7 : 4; + } osd_inv_thd; + + /* 0x00003008 reg3074 */ + struct { + RK_U32 osd_en : 8; + RK_U32 osd_itype : 8; + RK_U32 osd_plt_cks : 1; + RK_U32 osd_plt_typ : 1; + RK_U32 reserved : 14; + } osd_cfg; + + /* 0x300c */ + RK_U32 reserved_3075; + + /* 0x00003010 reg3076 - 0x0000304c reg3091*/ + OSD_POS_NEW osd_pos[8]; + + /* 0x00003050 reg3092 - 0x0000306c reg3099 */ + RK_U32 osd_addr[8]; + + /* 0x3070 - 0x307c */ + RK_U32 reserved3100_3103[4]; + + /* 0x03080-0x347c reg3104-reg3360 */ + RK_U32 plt[256]; +} Vepu580Osd; + +/* class: st */ +/* 0x00004000 reg4096 - 0x000042cc reg4275 */ +typedef struct Vepu580Status_t { + /* 0x00004000 reg4096 */ + RK_U32 bs_lgth_l32; + + /* 0x00004004 reg4097 */ + struct { + RK_U32 bs_lgth_h8 : 8; + RK_U32 reserved : 8; + RK_U32 sse_l16 : 16; + } st_sse_bsl; + + /* 0x00004008 reg4098 */ + RK_U32 sse_h32; + + /* 0x0000400c reg4099 */ + RK_U32 qp_sum; + + /* 0x00004010 reg4100 */ + struct { + RK_U32 sao_cnum : 16; + RK_U32 sao_ynum : 16; + } st_sao; + + /* 0x00004014 reg4101 */ + RK_U32 rdo_head_bits; + + /* 0x00004018 reg4102 */ + struct { + RK_U32 rdo_head_bits_h8 : 8; + RK_U32 reserved : 8; + RK_U32 rdo_res_bits_l16 : 16; + } st_head_res_bl; + + /* 0x0000401c reg4103 */ + RK_U32 rdo_res_bits_h24; + + /* 0x00004020 reg4104 */ + struct { + RK_U32 st_enc : 2; + RK_U32 st_sclr : 1; + RK_U32 reserved : 29; + } st_enc; + + /* 0x00004024 reg4105 */ + struct { + RK_U32 fnum_cfg_done : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 fnum_enc_done : 8; + } st_lkt; + + /* 0x00004028 reg4106 */ + RK_U32 node_addr; + + /* 0x0000402c reg4107 */ + struct { + RK_U32 bsbw_ovfl : 1; + RK_U32 reserved : 2; + RK_U32 bsbw_addr : 28; + RK_U32 reserved1 : 1; + } st_bsb; + + /* 0x00004030 reg4108 */ + struct { + RK_U32 axib_idl : 8; + RK_U32 axib_ovfl : 8; + RK_U32 axib_err : 8; + RK_U32 axir_err : 7; + RK_U32 reserved : 1; + } st_bus; + + /* 0x00004034 reg4109 */ + struct { + RK_U32 sli_num : 6; + RK_U32 reserved : 26; + } st_snum; + + /* 0x00004038 reg4110 */ + struct { + RK_U32 sli_len : 25; + RK_U32 reserved : 7; + } st_slen; + + /* 0x403c - 0x40fc */ + RK_U32 reserved4111_4159[49]; + + /* 0x00004100 reg4160 */ + struct { + RK_U32 pnum_p64 : 17; + RK_U32 reserved : 15; + } st_pnum_p64; + + /* 0x00004104 reg4161 */ + struct { + RK_U32 pnum_p32 : 19; + RK_U32 reserved : 13; + } st_pnum_p32; + + /* 0x00004108 reg4162 */ + struct { + RK_U32 pnum_p16 : 21; + RK_U32 reserved : 11; + } st_pnum_p16; + + /* 0x0000410c reg4163 */ + struct { + RK_U32 pnum_p8 : 23; + RK_U32 reserved : 9; + } st_pnum_p8; + + /* 0x00004110 reg4164 */ + struct { + RK_U32 pnum_i32 : 19; + RK_U32 reserved : 13; + } st_pnum_i32; + + /* 0x00004114 reg4165 */ + struct { + RK_U32 pnum_i16 : 21; + RK_U32 reserved : 11; + } st_pnum_i16; + + /* 0x00004118 reg4166 */ + struct { + RK_U32 pnum_i8 : 23; + RK_U32 reserved : 9; + } st_pnum_i8; + + /* 0x0000411c reg4167 */ + struct { + RK_U32 pnum_i4 : 23; + RK_U32 reserved : 9; + } st_pnum_i4; + + /* 0x00004120 reg4168 */ + RK_U32 madp; + + /* 0x00004124 reg4169 */ + struct { + RK_U32 num_ctu : 21; + RK_U32 reserved : 11; + } st_bnum_cme; + + /* 0x00004128 reg4170 */ + RK_U32 madi; + + /* 0x0000412c reg4171 */ + struct { + RK_U32 num_b16 : 23; + RK_U32 reserved : 9; + } st_bnum_b16; + + /* 0x00004130 reg4172 */ + RK_U32 num_madi_max_b16; + + /* 0x00004134 reg4173 */ + RK_U32 md_sad_b16num0; + + /* 0x00004138 reg4174 */ + RK_U32 md_sad_b16num1; + + /* 0x0000413c reg4175 */ + RK_U32 md_sad_b16num2; + + /* 0x00004140 reg4176 */ + RK_U32 md_sad_b16num3; + + /* 0x00004144 reg4177 */ + RK_U32 madi_b16num0; + + /* 0x00004148 reg4178 */ + RK_U32 madi_b16num1; + + /* 0x0000414c reg4179 */ + RK_U32 madi_b16num2; + + /* 0x00004150 reg4180 */ + RK_U32 madi_b16num3; + + /* 0x4154 - 0x41fc */ + RK_U32 reserved4181_4223[43]; + + /* 0x00004200 reg4224 - 0x000042cc reg4275 */ + // b8num_qp0-51 + /* + * RK_U32 b8num_qp0 : 22; + * RK_U32 reserved : 10; + */ + RK_U32 st_b8_qp[52]; +} Vepu580Status; + +/* class: dbg/st/axipn */ +/* 0x00005000 reg5120 - 0x00005354 reg5333*/ +typedef struct Vepu580Dbg_t { + /* 0x00005000 reg5120 */ + struct { + RK_U32 pp_tout : 1; + RK_U32 cme_tout : 1; + RK_U32 swn_tout : 1; + RK_U32 rme_tout : 1; + RK_U32 fme_tout : 1; + RK_U32 rdo_tout : 1; + RK_U32 lpf_tout : 1; + RK_U32 etpy_tout : 1; + RK_U32 frm_tout : 1; + RK_U32 reserved : 23; + } st_wdg; + + /* 0x00005004 reg5121 */ + struct { + RK_U32 pp_wrk : 1; + RK_U32 cme_wrk : 1; + RK_U32 swn_wrk : 1; + RK_U32 rme_wrk : 1; + RK_U32 fme_wrk : 1; + RK_U32 rdo_wrk : 1; + RK_U32 lpf_wrk : 1; + RK_U32 etpy_wrk : 1; + RK_U32 frm_wrk : 1; + RK_U32 reserved : 23; + } st_ppl; + + /* 0x00005008 reg5122 */ + struct { + RK_U32 pp_pos_x : 16; + RK_U32 pp_pos_y : 16; + } st_ppl_pos_pp; + + /* 0x0000500c reg5123 */ + struct { + RK_U32 cme_pos_x : 16; + RK_U32 cme_pos_y : 16; + } st_ppl_pos_cme; + + /* 0x00005010 reg5124 */ + struct { + RK_U32 swin_pos_x : 16; + RK_U32 swin_pos_y : 16; + } st_ppl_pos_swin; + + /* 0x00005014 reg5125 */ + struct { + RK_U32 rme_pos_x : 16; + RK_U32 rme_pos_y : 16; + } st_ppl_pos_rme; + + /* 0x00005018 reg5126 */ + struct { + RK_U32 fme_pos_x : 16; + RK_U32 fme_pos_y : 16; + } st_ppl_pos_fme; + + /* 0x0000501c reg5127 */ + struct { + RK_U32 rdo_pos_x : 16; + RK_U32 rdo_pos_y : 16; + } st_ppl_pos_rdo; + + /* 0x00005020 reg5128 */ + struct { + RK_U32 lpf_pos_x : 16; + RK_U32 lpf_pos_y : 16; + } st_ppl_pos_lpf; + + /* 0x00005024 reg5129 */ + struct { + RK_U32 etpy_pos_x : 16; + RK_U32 etpy_pos_y : 16; + } st_ppl_pos_etpy; + + /* 0x00005028 reg5130 */ + struct { + RK_U32 sli_num : 15; + RK_U32 reserved : 17; + } st_sli_num; + + /* 0x0000502c reg5131 */ + struct { + RK_U32 lkt_err : 3; + RK_U32 reserved : 29; + } st_lkt_err; + + /* 0x5030 - 0x50fc */ + RK_U32 reserved5132_5183[52]; + + /* 0x00005100 reg5184 */ + struct { + RK_U32 empty_oafifo : 1; + RK_U32 full_cmd_oafifo : 1; + RK_U32 full_data_oafifo : 1; + RK_U32 empty_iafifo : 1; + RK_U32 full_cmd_iafifo : 1; + RK_U32 full_info_iafifo : 1; + RK_U32 fbd_brq_st : 4; + RK_U32 fbd_hdr_vld : 1; + RK_U32 fbd_bmng_end : 1; + RK_U32 nfbd_req_st : 4; + RK_U32 acc_axi_cmd : 8; + RK_U32 reserved : 8; + } dbg_pp_st; + + /* 0x00005104 reg5185 */ + struct { + RK_U32 cur_state_cime : 2; + RK_U32 cur_state_ds : 3; + RK_U32 cur_state_ref : 2; + RK_U32 cur_state_cst : 2; + RK_U32 reserved : 23; + } dbg_cime_st; + + /* 0x00005108 reg5186 */ + RK_U32 swin_dbg_inf; + + /* 0x0000510c reg5187 */ + struct { + RK_U32 bbrq_cmps_left_len2 : 1; + RK_U32 bbrq_cmps_left_len1 : 1; + RK_U32 cmps_left_len0 : 1; + RK_U32 bbrq_rdy2 : 1; + RK_U32 dcps_vld2 : 1; + RK_U32 bbrq_rdy1 : 1; + RK_U32 dcps_vld1 : 1; + RK_U32 bbrq_rdy0 : 1; + RK_U32 dcps_vld0 : 1; + RK_U32 hb_rdy2 : 1; + RK_U32 bbrq_vld2 : 1; + RK_U32 hb_rdy1 : 1; + RK_U32 bbrq_vld1 : 1; + RK_U32 hb_rdy0 : 1; + RK_U32 bbrq_vld0 : 1; + RK_U32 idle_msb2 : 1; + RK_U32 idle_msb1 : 1; + RK_U32 idle_msb0 : 1; + RK_U32 cur_state_dcps : 1; + RK_U32 cur_state_bbrq : 1; + RK_U32 cur_state_hb : 1; + RK_U32 cke_bbrq_dcps : 1; + RK_U32 cke_dcps : 1; + RK_U32 cke_bbrq : 1; + RK_U32 rdy_lwcd_rsp : 1; + RK_U32 vld_lwcd_rsp : 1; + RK_U32 rdy_lwcd_req : 1; + RK_U32 vld_lwcd_req : 1; + RK_U32 rdy_lwrsp : 1; + RK_U32 vld_lwrsp : 1; + RK_U32 rdy_lwreq : 1; + RK_U32 vld_lwreq : 1; + } dbg_fbd_hhit0; + + /* 0x5110 */ + RK_U32 reserved_5188; + + /* 0x00005114 reg5189 */ + struct { + RK_U32 mscnt_clr : 1; + RK_U32 reserved : 31; + } dbg_cach_clr; + + /* 0x00005118 reg5190 */ + RK_U32 l1_mis; + + /* 0x0000511c reg5191 */ + RK_U32 l2_mis; + + /* 0x00005120 reg5192 */ + RK_U32 rdo_st; + + /* 0x00005124 reg5193 */ + RK_U32 rdo_if; + + /* 0x00005128 reg5194 */ + struct { + RK_U32 sh_st_cs : 4; + RK_U32 rsd_st_cs : 4; + RK_U32 sd_st_cs : 5; + RK_U32 etpy_rdy : 1; + RK_U32 reserved : 18; + } dbg_etpy; + + /* 0x0000512c reg5195 */ + struct { + RK_U32 crdy_ppr : 1; + RK_U32 cvld_ppr : 1; + RK_U32 drdy_ppw : 1; + RK_U32 dvld_ppw : 1; + RK_U32 crdy_ppw : 1; + RK_U32 cvld_ppw : 1; + RK_U32 reserved : 26; + } dbg_dma_pp; + + /* 0x00005130 reg5196 */ + struct { + RK_U32 axi_wrdy : 8; + RK_U32 axi_wvld : 8; + RK_U32 axi_awrdy : 8; + RK_U32 axi_awvld : 8; + } dbg_dma_w; + + /* 0x00005134 reg5197 */ + struct { + RK_U32 axi_otsd_read : 16; + RK_U32 axi_arrdy : 7; + RK_U32 reserved : 1; + RK_U32 axi_arvld : 7; + RK_U32 reserved1 : 1; + } dbg_dma_r; + + /* 0x00005138 reg5198 */ + struct { + RK_U32 dfifo0_lvl : 4; + RK_U32 dfifo1_lvl : 4; + RK_U32 dfifo2_lvl : 4; + RK_U32 dfifo3_lvl : 4; + RK_U32 dfifo4_lvl : 4; + RK_U32 dfifo5_lvl : 4; + RK_U32 reserved : 6; + RK_U32 cmd_vld : 1; + RK_U32 reserved1 : 1; + } dbg_dma_rfpr; + + /* 0x0000513c reg5199 */ + struct { + RK_U32 meiw_busy : 1; + RK_U32 dspw_busy : 1; + RK_U32 bsw_rdy : 1; + RK_U32 bsw_flsh : 1; + RK_U32 bsw_busy : 1; + RK_U32 crpw_busy : 1; + RK_U32 lktw_busy : 1; + RK_U32 lpfw_busy : 1; + RK_U32 roir_busy : 1; + RK_U32 dspr_crdy : 1; + RK_U32 dspr_cvld : 1; + RK_U32 lktr_busy : 1; + RK_U32 lpfr_otsd : 4; + RK_U32 rfpr_otsd : 12; + RK_U32 dspr_otsd : 4; + } dbg_dma_ch_st; + + /* 0x00005140 reg5200 */ + struct { + RK_U32 cpip_st : 2; + RK_U32 mvp_st : 3; + RK_U32 qpd6_st : 2; + RK_U32 cmd_st : 2; + RK_U32 reserved : 23; + } dbg_tctrl_cime_st; + + /* 0x00005144 reg5201 */ + struct { + RK_U32 cme_byps : 1; + RK_U32 swin_byps : 1; + RK_U32 rme_byps : 1; + RK_U32 intra_byps : 1; + RK_U32 fme_byps : 1; + RK_U32 rdo_byps : 1; + RK_U32 lpf_byps : 1; + RK_U32 etpy_byps : 1; + RK_U32 reserved : 24; + } dbg_tctrl; + + /* 0x5148 */ + RK_U32 reserved_5202; + + /* 0x0000514c reg5203 */ + RK_U32 dbg_lpf_st; + + /* 0x00005150 reg5204 */ + RK_U32 dbg_topc_lpfr; + + /* 0x00005154 reg5205 */ + RK_U32 dbg0_cache; + + /* 0x00005158 reg5206 */ + RK_U32 dbg1_cache; + + /* 0x0000515c reg5207 */ + RK_U32 dbg2_cache; + + /* 0x5160 - 0x51fc */ + RK_U32 reserved5208_5247[40]; + + /* 0x00005200 reg5248 */ + RK_U32 frame_cyc; + + /* 0x00005204 reg5249 */ + RK_U32 pp_fcyc; + + /* 0x00005208 reg5250 */ + RK_U32 cme_fcyc; + + /* 0x0000520c reg5251 */ + RK_U32 cme_dspr_fcyc; + + /* 0x00005210 reg5252 */ + RK_U32 ldr_fcyc; + + /* 0x00005214 reg5253 */ + RK_U32 rme_fcyc; + + /* 0x00005218 reg5254 */ + RK_U32 fme_fcyc; + + /* 0x0000521c reg5255 */ + RK_U32 rdo_fcyc; + + /* 0x00005220 reg5256 */ + RK_U32 lpf_fcyc; + + /* 0x00005224 reg5257 */ + RK_U32 etpy_fcyc; + + /* 0x5228 - 0x52fc */ + RK_U32 reserved5258_5311[54]; + + /* 0x00005300 reg5312 */ + struct { + RK_U32 axip_e : 1; + RK_U32 axip_clr : 1; + RK_U32 axip_mod : 1; + RK_U32 reserved : 29; + } axip0_cmd; + + /* 0x00005304 reg5313 */ + struct { + RK_U32 axip_ltcy_id : 4; + RK_U32 axip_ltcy_thd : 12; + RK_U32 reserved : 16; + } axip0_ltcy; + + /* 0x00005308 reg5314 */ + struct { + RK_U32 axip_cnt_typ : 1; + RK_U32 axip_cnt_ddr : 2; + RK_U32 axip_cnt_rid : 5; + RK_U32 axip_cnt_wid : 5; + RK_U32 reserved : 19; + } axip0_cnt; + + /* 0x530c */ + RK_U32 reserved_5315; + + /* 0x00005310 reg5316 */ + struct { + RK_U32 axip_e : 1; + RK_U32 axip_clr : 1; + RK_U32 axip_mod : 1; + RK_U32 reserved : 29; + } axip1_cmd; + + /* 0x00005314 reg5317 */ + struct { + RK_U32 axip_ltcy_id : 4; + RK_U32 axip_ltcy_thd : 12; + RK_U32 reserved : 16; + } axip1_ltcy; + + /* 0x00005318 reg5318 */ + struct { + RK_U32 axip_cnt_typ : 1; + RK_U32 axip_cnt_ddr : 2; + RK_U32 axip_cnt_rid : 5; + RK_U32 axip_cnt_wid : 5; + RK_U32 reserved : 19; + } axip1_cnt; + + /* 0x531c */ + RK_U32 reserved_5319; + + /* 0x00005320 reg5320 */ + struct { + RK_U32 axip_max_ltcy : 16; + RK_U32 reserved : 16; + } st_axip0_maxl; + + /* 0x00005324 reg5321 */ + RK_U32 axip0_num_ltcy; + + /* 0x00005328 reg5322 */ + RK_U32 axip0_sum_ltcy; + + /* 0x0000532c reg5323 */ + RK_U32 axip0_rbyt; + + /* 0x00005330 reg5324 */ + RK_U32 axip0_wbyt; + + /* 0x00005334 reg5325 */ + RK_U32 axip0_wrk_cyc; + + /* 0x5338 - 0x533c */ + RK_U32 reserved5326_5327[2]; + + /* 0x00005340 reg5328 */ + struct { + RK_U32 axip_max_ltcy : 16; + RK_U32 reserved : 16; + } st_axip1_maxl; + + /* 0x00005344 reg5329 */ + RK_U32 axip1_num_ltcy; + + /* 0x00005348 reg5330 */ + RK_U32 axip1_sum_ltcy; + + /* 0x0000534c reg5331 */ + RK_U32 axip1_rbyt; + + /* 0x00005350 reg5332 */ + RK_U32 axip1_wbyt; + + /* 0x00005354 reg5333 */ + RK_U32 axip1_wrk_cyc; +} Vepu580Dbg; + +/* class: mmu */ +/* 0x0000f000 reg15360 - 0x0000f064 reg15385 */ + +typedef struct HalVepu580Reg_t { + Vepu580ControlCfg reg_ctl; + Vepu580BaseCfg reg_base; + Vepu580RcKlutCfg reg_rc_klut; + Vepu580Section3 reg_s3; + Vepu580RdoCfg reg_rdo; + Vepu580SclCfg reg_scl; + Vepu580Osd reg_osd; + Vepu580Status reg_st; + Vepu580Dbg reg_dbg; +} HalVepu580RegSet; + +#endif diff --git a/mpp/hal/rkenc/h264e/hal_h264e_vepu580_tune.c b/mpp/hal/rkenc/h264e/hal_h264e_vepu580_tune.c new file mode 100644 index 000000000..11b320e44 --- /dev/null +++ b/mpp/hal/rkenc/h264e/hal_h264e_vepu580_tune.c @@ -0,0 +1,386 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vepu580_tune.h" + +#define HAL_H264E_DBG_CONTENT (0x00000200) +#define hal_h264e_dbg_content(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_CONTENT, fmt, ## __VA_ARGS__) + +/* + * Please follow the configuration below: + * + * FRAME_CONTENT_ANALYSIS_NUM >= 5 + * MD_WIN_LEN >= 3 + * MD_SHOW_LEN == 4 + */ + +typedef struct HalH264eVepu580Tune_t { + HalH264eVepu580Ctx *ctx; + + /* motion and texture statistic of previous frames */ + RK_S32 curr_scene_motion_flag; + /* motion and texture statistic of previous frames */ + RK_S32 ap_motion_flag; + // level: 0~2: 0 <--> static, 1 <-->medium motion, 2 <--> large motion + RK_S32 md_madp[MD_WIN_LEN]; + // level: 0~2: 0 <--> simple texture, 1 <--> medium texture, 2 <--> complex texture + RK_S32 txtr_madi[FRAME_CONTENT_ANALYSIS_NUM]; + RK_S32 scene_motion_flag_matrix[FRAME_MOTION_ANALYSIS_NUM]; + RK_S32 md_flag_matrix[MD_SHOW_LEN]; + + RK_S32 pre_madp[2]; + RK_S32 pre_madi[2]; +} HalH264eVepu580Tune; + +static RK_S32 mb_avg_madp_thd[6] = {192, 128, 64, 192, 128, 64}; + +static RK_S32 atr_wgt[4][9] = { + {22, 19, 16, 22, 19, 18, 22, 19, 16}, + {19, 19, 19, 19, 19, 19, 19, 19, 19}, + {22, 19, 16, 22, 19, 18, 22, 19, 16}, + {20, 20, 20, 20, 20, 20, 20, 20, 20}, +}; + +static RK_S32 skip_atf_wgt[4][13] = { + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 intra_atf_wgt[4][12] = { + {24, 22, 21, 22, 21, 20, 20, 19, 18, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {22, 21, 20, 21, 20, 19, 20, 19, 18, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 cime_multi[4][4] = { + {4, 8, 24, 24}, + {4, 7, 20, 20}, + {4, 7, 20, 20}, + {4, 4, 4, 4}, +}; + +static RK_S32 rime_multi[4][3] = { + {4, 32, 128}, + {4, 16, 64}, + {4, 16, 64}, + {4, 4, 4}, +}; + +static HalH264eVepu580Tune *vepu580_h264e_tune_init(HalH264eVepu580Ctx *ctx) +{ + HalH264eVepu580Tune *tune = mpp_malloc(HalH264eVepu580Tune, 1); + RK_S32 scene_mode = ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 0 : 1; + + if (NULL == tune) + return tune; + + tune->ctx = ctx; + tune->curr_scene_motion_flag = 0; + tune->ap_motion_flag = scene_mode; + memset(tune->md_madp, 0, sizeof(tune->md_madp)); + memset(tune->txtr_madi, 0, sizeof(tune->txtr_madi)); + memset(tune->md_flag_matrix, 0, sizeof(tune->md_flag_matrix)); + memset(tune->scene_motion_flag_matrix, 0, sizeof(tune->scene_motion_flag_matrix)); + tune->pre_madi[0] = tune->pre_madi[1] = -1; + tune->pre_madp[0] = tune->pre_madp[1] = -1; + + return tune; +} + +static void vepu580_h264e_tune_deinit(void *tune) +{ + MPP_FREE(tune); +} + +static void vepu580_h264e_tune_reg_patch(void *p) +{ + HalH264eVepu580Tune *tune = (HalH264eVepu580Tune *)p; + HalH264eVepu580Ctx *ctx = NULL; + RK_S32 scene_mode = 0; + + if (NULL == tune) + return; + + ctx = tune->ctx; + scene_mode = ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 0 : 1; + + H264eSlice *slice = ctx->slice; + HalVepu580RegSet *regs = ctx->regs_set; + tune->ap_motion_flag = scene_mode; + RK_U32 scene_motion_flag = tune->ap_motion_flag * 2 + tune->curr_scene_motion_flag; + MppEncHwCfg *hw = &ctx->cfg->hw; + + if (scene_motion_flag > 3) { + mpp_err_f("scene_motion_flag is a wrong value %d\n", scene_motion_flag); + return; + } + + /* modify register here */ + if (slice->slice_type != H264_I_SLICE) { + RK_U32 *src = (tune->curr_scene_motion_flag || + ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC) ? + &h264e_klut_weight[0] : &h264e_klut_weight[4]; + memcpy(®s->reg_rc_klut.klut_wgt0, src, CHROMA_KLUT_TAB_SIZE); + } + + regs->reg_rc_klut.md_sad_thd.md_sad_thd0 = 4; + regs->reg_rc_klut.md_sad_thd.md_sad_thd1 = 9; + regs->reg_rc_klut.md_sad_thd.md_sad_thd2 = 15; + regs->reg_rc_klut.madi_thd.madi_thd0 = 4; + regs->reg_rc_klut.madi_thd.madi_thd1 = 9; + regs->reg_rc_klut.madi_thd.madi_thd2 = 15; + + if (tune->curr_scene_motion_flag) { + regs->reg_s3.lvl16_intra_UL_CST_THD.lvl16_intra_ul_cst_thld = 2501; + regs->reg_s3.RDO_QUANT.quant_f_bias_P = 341; + regs->reg_base.iprd_csts.vthd_y = 0; + regs->reg_base.iprd_csts.vthd_c = 0; + regs->reg_rc_klut.klut_ofst.chrm_klut_ofst = 0; + regs->reg_base.rdo_cfg.atf_intra_e = 0; + regs->reg_rdo.rdo_sqi_cfg.atf_pskip_en = 0; + regs->reg_s3.ATR_THD1.atr_thdqp = 51; + regs->reg_s3.cime_sqi_cfg.cime_pmv_set_zero = 0; + regs->reg_s3.rime_sqi_thd.cime_sad_th0 = 0; + regs->reg_s3.fme_sqi_thd0.cime_sad_pu16_th = 0; + regs->reg_s3.fme_sqi_thd1.move_lambda = 8; + } + + regs->reg_rdo.rdo_intra_cime_thd0.atf_rdo_intra_cime_thd0 = 28; + regs->reg_rdo.rdo_intra_cime_thd0.atf_rdo_intra_cime_thd1 = 44; + regs->reg_rdo.rdo_intra_cime_thd1.atf_rdo_intra_cime_thd2 = 72; + regs->reg_rdo.rdo_intra_atf_wgt0.atf_rdo_intra_wgt00 = intra_atf_wgt[scene_motion_flag][0]; + regs->reg_rdo.rdo_intra_atf_wgt0.atf_rdo_intra_wgt01 = intra_atf_wgt[scene_motion_flag][1]; + regs->reg_rdo.rdo_intra_atf_wgt0.atf_rdo_intra_wgt02 = intra_atf_wgt[scene_motion_flag][2]; + regs->reg_rdo.rdo_intra_atf_wgt1.atf_rdo_intra_wgt10 = intra_atf_wgt[scene_motion_flag][3]; + regs->reg_rdo.rdo_intra_atf_wgt1.atf_rdo_intra_wgt11 = intra_atf_wgt[scene_motion_flag][4]; + regs->reg_rdo.rdo_intra_atf_wgt1.atf_rdo_intra_wgt12 = intra_atf_wgt[scene_motion_flag][5]; + regs->reg_rdo.rdo_intra_atf_wgt2.atf_rdo_intra_wgt20 = intra_atf_wgt[scene_motion_flag][6]; + regs->reg_rdo.rdo_intra_atf_wgt2.atf_rdo_intra_wgt21 = intra_atf_wgt[scene_motion_flag][7]; + regs->reg_rdo.rdo_intra_atf_wgt2.atf_rdo_intra_wgt22 = intra_atf_wgt[scene_motion_flag][8]; + regs->reg_rdo.rdo_intra_atf_wgt3.atf_rdo_intra_wgt30 = intra_atf_wgt[scene_motion_flag][9]; + regs->reg_rdo.rdo_intra_atf_wgt3.atf_rdo_intra_wgt31 = intra_atf_wgt[scene_motion_flag][10]; + regs->reg_rdo.rdo_intra_atf_wgt3.atf_rdo_intra_wgt32 = intra_atf_wgt[scene_motion_flag][11]; + + regs->reg_rdo.rdo_skip_cime_thd0.atf_rdo_skip_cime_thd0 = 10; + regs->reg_rdo.rdo_skip_cime_thd0.atf_rdo_skip_cime_thd1 = 8; + regs->reg_rdo.rdo_skip_cime_thd1.atf_rdo_skip_cime_thd2 = 15; + regs->reg_rdo.rdo_skip_cime_thd1.atf_rdo_skip_cime_thd3 = 25; + regs->reg_rdo.rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt00 = skip_atf_wgt[scene_motion_flag][0]; + regs->reg_rdo.rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt10 = skip_atf_wgt[scene_motion_flag][1]; + regs->reg_rdo.rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt11 = skip_atf_wgt[scene_motion_flag][2]; + regs->reg_rdo.rdo_skip_atf_wgt0.atf_rdo_skip_atf_wgt12 = skip_atf_wgt[scene_motion_flag][3]; + regs->reg_rdo.rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt20 = skip_atf_wgt[scene_motion_flag][4]; + regs->reg_rdo.rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt21 = skip_atf_wgt[scene_motion_flag][5]; + regs->reg_rdo.rdo_skip_atf_wgt1.atf_rdo_skip_atf_wgt22 = skip_atf_wgt[scene_motion_flag][6]; + regs->reg_rdo.rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt30 = skip_atf_wgt[scene_motion_flag][7]; + regs->reg_rdo.rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt31 = skip_atf_wgt[scene_motion_flag][8]; + regs->reg_rdo.rdo_skip_atf_wgt2.atf_rdo_skip_atf_wgt32 = skip_atf_wgt[scene_motion_flag][9]; + regs->reg_rdo.rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt40 = skip_atf_wgt[scene_motion_flag][10]; + regs->reg_rdo.rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt41 = skip_atf_wgt[scene_motion_flag][11]; + regs->reg_rdo.rdo_skip_atf_wgt3.atf_rdo_skip_atf_wgt42 = skip_atf_wgt[scene_motion_flag][12]; + + if (slice->slice_type != H264_I_SLICE) { + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt0 = atr_wgt[scene_motion_flag][0]; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt1 = atr_wgt[scene_motion_flag][1]; + regs->reg_s3.Lvl16_ATR_WGT.lvl16_atr_wgt2 = atr_wgt[scene_motion_flag][2]; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt0 = atr_wgt[scene_motion_flag][3]; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt1 = atr_wgt[scene_motion_flag][4]; + regs->reg_s3.Lvl8_ATR_WGT.lvl8_atr_wgt2 = atr_wgt[scene_motion_flag][5]; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt0 = atr_wgt[scene_motion_flag][6]; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt1 = atr_wgt[scene_motion_flag][7]; + regs->reg_s3.Lvl4_ATR_WGT.lvl4_atr_wgt2 = atr_wgt[scene_motion_flag][8]; + } + + regs->reg_s3.cime_sqi_multi0.cime_multi0 = cime_multi[scene_motion_flag][0]; + regs->reg_s3.cime_sqi_multi0.cime_multi1 = cime_multi[scene_motion_flag][1]; + regs->reg_s3.cime_sqi_multi1.cime_multi2 = cime_multi[scene_motion_flag][2]; + regs->reg_s3.cime_sqi_multi1.cime_multi3 = cime_multi[scene_motion_flag][3]; + + regs->reg_s3.rime_sqi_multi.rime_multi0 = rime_multi[scene_motion_flag][0]; + regs->reg_s3.rime_sqi_multi.rime_multi1 = rime_multi[scene_motion_flag][1]; + regs->reg_s3.rime_sqi_multi.rime_multi2 = rime_multi[scene_motion_flag][2]; + + if (hw->qbias_en) { + regs->reg_s3.RDO_QUANT.quant_f_bias_I = (hw->qbias_i != 0) ? hw->qbias_i : 683; + regs->reg_s3.RDO_QUANT.quant_f_bias_P = (hw->qbias_p != 0) ? hw->qbias_p : 341; + } +} + +static void vepu580_h264e_tune_stat_update(void *p, HalEncTask *task) +{ + HalH264eVepu580Tune *tune = (HalH264eVepu580Tune *)p; + HalH264eVepu580Ctx *ctx = NULL; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_S32 scene_mode = 0; + + if (NULL == tune) + return; + + ctx = tune->ctx; + scene_mode = ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 0 : 1; + tune->ap_motion_flag = scene_mode; + /* update statistic info here */ + RK_S32 mb_num = 0; + RK_S32 madp = 0; + RK_S32 md_flag = 0; + RK_S32 nScore = 0; + RK_S32 j; + RK_S32 nScoreT = ((MD_WIN_LEN - 2) * 6 + 2 * 8 + 2 * 11 + 2 * 13) / 2; + RK_S32 i = 0; + RK_S32 mvbit = 10; + RK_S32 madp_cnt_statistics[5]; + HalVepu580RegSet *regs = &ctx->regs_sets[task->flags.reg_idx]; + + for (i = 0; i < 5; i++) { + madp_cnt_statistics[i] = regs->reg_st.md_sad_b16num0 * madp_num_map[i][0] + + regs->reg_st.md_sad_b16num1 * madp_num_map[i][1] + + regs->reg_st.md_sad_b16num2 * madp_num_map[i][2] + + regs->reg_st.md_sad_b16num3 * madp_num_map[i][3]; + } + + rc_info->madi = + tune->pre_madi[0] = (regs->reg_st.st_bnum_b16.num_b16 == 0) ? 0 : + regs->reg_st.madi / regs->reg_st.st_bnum_b16.num_b16; + rc_info->madp = + tune->pre_madp[0] = (regs->reg_st.st_bnum_cme.num_ctu == 0) ? 0 : + regs->reg_st.madp / regs->reg_st.st_bnum_cme.num_ctu; + + mb_num = regs->reg_st.madi_b16num0 + regs->reg_st.madi_b16num1 + + regs->reg_st.madi_b16num2 + regs->reg_st.madi_b16num3; + mb_num = (mb_num != 0) ? mb_num : 1; + if (0 != tune->ap_motion_flag) + mvbit = 15; + + madp = MOTION_LEVEL_STILL; + if (0 != madp_cnt_statistics[4]) { + RK_S32 base = tune->ap_motion_flag * 3; + + for (i = 0; i < 3; i++, base++) { + if (tune->pre_madp[0] >= mb_avg_madp_thd[base]) { + if (madp_cnt_statistics[0] > mb_num * ctu_madp_cnt_thd[base][0] >> mvbit || + madp_cnt_statistics[1] > mb_num * ctu_madp_cnt_thd[base][1] >> mvbit || + madp_cnt_statistics[2] > mb_num * ctu_madp_cnt_thd[base][2] >> mvbit) { + madp = MOTION_LEVEL_BIG_MOTION; + } else if ((madp_cnt_statistics[0] > mb_num * ctu_madp_cnt_thd[base][3] >> mvbit || + madp_cnt_statistics[1] > mb_num * ctu_madp_cnt_thd[base][4] >> mvbit) && + madp_cnt_statistics[3] < mb_num * ctu_madp_cnt_thd[base][5] >> mvbit) { + madp = MOTION_LEVEL_BIG_MOTION; + } else if (madp_cnt_statistics[3] < mb_num * ctu_madp_cnt_thd[base][6] >> mvbit) { + madp = MOTION_LEVEL_BIG_MOTION; + } else if (madp_cnt_statistics[3] < mb_num * ctu_madp_cnt_thd[base][7] >> mvbit) { + madp = MOTION_LEVEL_MOTION; + } + break; + } + } + } else { + madp = MOTION_LEVEL_UNKNOW_SCENE; + } + + if (MOTION_LEVEL_UNKNOW_SCENE != madp) { + nScore = madp * 13 + tune->md_madp[0] * 11 + tune->md_madp[1] * 8; + } else { + nScore = tune->md_madp[0] * 11 + tune->md_madp[1] * 8; + nScoreT -= 13; + } + + for (j = 2; j < MD_WIN_LEN; j++) { + nScore += tune->md_madp[j] * 6; + } + + if (nScore >= nScoreT) { + md_flag = 1; + } + + tune->curr_scene_motion_flag = 0; + if (tune->md_flag_matrix[0] && tune->md_flag_matrix[1] && tune->md_flag_matrix[2]) { + tune->curr_scene_motion_flag = 1; + } else if ((tune->md_flag_matrix[0] && tune->md_flag_matrix[1]) || (tune->md_flag_matrix[1] && tune->md_flag_matrix[2] && tune->md_flag_matrix[3])) { + tune->curr_scene_motion_flag = md_flag; + } + + if (MOTION_LEVEL_UNKNOW_SCENE != madp) { + for (j = MD_WIN_LEN - 2; j >= 0; j--) { + tune->md_madp[j + 1] = tune->md_madp[j]; + } + tune->md_madp[0] = madp; + } + for (j = MD_SHOW_LEN - 2; j >= 0; j--) { + tune->md_flag_matrix[j + 1] = tune->md_flag_matrix[j]; + } + + tune->md_flag_matrix[0] = md_flag; + + for (j = FRAME_MOTION_ANALYSIS_NUM - 2; j >= 0; j--) { + tune->scene_motion_flag_matrix[j + 1] = tune->scene_motion_flag_matrix[j]; + } + tune->scene_motion_flag_matrix[0] = tune->curr_scene_motion_flag; + + tune->pre_madi[1] = tune->pre_madi[0]; + tune->pre_madp[1] = tune->pre_madp[0]; +} + +static MPP_RET setup_vepu580_qpmap_buf(HalH264eVepu580Ctx *ctx) +{ + MPP_RET ret = MPP_OK; + RK_S32 mb_w = MPP_ALIGN(ctx->cfg->prep.width, 64) / 16; + RK_S32 mb_h = MPP_ALIGN(ctx->cfg->prep.height, 16) / 16; + RK_S32 qpmap_base_cfg_size = ctx->qpmap_base_cfg_size + = mb_w * mb_h * 8; + RK_S32 qpmap_qp_cfg_size = ctx->qpmap_qp_cfg_size + = mb_w * mb_h * 2; + RK_S32 md_flag_size = ctx->md_flag_size + = mb_w * mb_h; + + if (!ctx->cfg->tune.deblur_en) { + mpp_log("deblurring is closed!\n"); + goto __RET; + } + + if (NULL == ctx->qpmap_base_cfg_buf) { + mpp_buffer_get(NULL, &ctx->qpmap_base_cfg_buf, qpmap_base_cfg_size); + if (!ctx->qpmap_base_cfg_buf) { + mpp_err("qpmap_base_cfg_buf malloc fail, qpmap invalid\n"); + ret = MPP_ERR_VALUE; + goto __RET; + } + } + + if (NULL == ctx->qpmap_qp_cfg_buf) { + mpp_buffer_get(NULL, &ctx->qpmap_qp_cfg_buf, qpmap_qp_cfg_size); + if (!ctx->qpmap_qp_cfg_buf) { + mpp_err("qpmap_qp_cfg_buf malloc fail, qpmap invalid\n"); + ret = MPP_ERR_VALUE; + goto __RET; + } + } + + if (NULL == ctx->md_flag_buf) { + ctx->md_flag_buf = mpp_malloc(RK_U8, md_flag_size); + if (!ctx->md_flag_buf) { + mpp_err("md_flag_buf malloc fail, qpmap invalid\n"); + ret = MPP_ERR_VALUE; + goto __RET; + } + } + +__RET: + hal_h264e_dbg_func("leave, ret %d\n", ret); + return ret; +} \ No newline at end of file diff --git a/mpp/hal/rkenc/h265e/CMakeLists.txt b/mpp/hal/rkenc/h265e/CMakeLists.txt new file mode 100644 index 000000000..fd6fb4d67 --- /dev/null +++ b/mpp/hal/rkenc/h265e/CMakeLists.txt @@ -0,0 +1,21 @@ +# vim: syntax=cmake +include_directories(.) +include_directories(../../common/h265/) +include_directories(../common/) +# mpp/codec/enc/h265 for h265 syntax +include_directories(../../../codec/enc/h265/) + +# hal h265 encoder sourse +set(HAL_H265E_SRC + ) + +add_hal_source(HAL_H265E_SRC HAVE_VEPU541 hal_h265e_vepu541.c) +add_hal_source(HAL_H265E_SRC HAVE_VEPU580 hal_h265e_vepu580.c) +add_hal_source(HAL_H265E_SRC HAVE_VEPU540C hal_h265e_vepu540c.c) +add_hal_source(HAL_H265E_SRC HAVE_VEPU510 hal_h265e_vepu510.c) +add_hal_source(HAL_H265E_SRC HAVE_VEPU511 hal_h265e_vepu511.c) +add_hal_source(HAL_H265E_SRC HAVE_VEPU511A hal_h265e_vepu511a.c) + +if (HAL_H265E_SRC) + add_library(hal_h265e_vepu5xx OBJECT ${HAL_H265E_SRC}) +endif() diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c new file mode 100644 index 000000000..49f439243 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.c @@ -0,0 +1,2617 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h265e_v510" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" +#include "mpp_enc_cb_param.h" + +#include "rkv_enc_def.h" +#include "h265e_syntax_new.h" +#include "h265e_dpb.h" +#include "hal_bufs.h" +#include "hal_h265e_debug.h" +#include "hal_h265e_vepu510.h" +#include "hal_h265e_vepu510_reg.h" +#include "hal_h265e_stream_amend.h" + +#include "vepu5xx_common.h" +#include "vepu510_common.h" + +#define MAX_FRAME_TASK_NUM 2 +#define H265E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) + +#define hal_h265e_err(fmt, ...) \ + do {\ + mpp_err_f(fmt, ## __VA_ARGS__);\ + } while (0) + +typedef struct Vepu510H265Fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 frame_type; + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; + RK_U32 st_smear_cnt[5]; + RK_S32 reg_idx; + RK_U32 acc_cover16_num; + RK_U32 acc_bndry16_num; + RK_U32 acc_zero_mv; + RK_S8 tgt_sub_real_lvl[6]; +} Vepu510H265Fbk; + +typedef struct Vepu510H265eFrmCfg_t { + RK_S32 frame_count; + RK_S32 frame_type; + + /* dchs cfg on frame parallel */ + RK_S32 dchs_curr_idx; + RK_S32 dchs_prev_idx; + + /* hal dpb management slot idx */ + RK_S32 hal_curr_idx; + RK_S32 hal_refr_idx; + + /* regs cfg */ + H265eV510RegSet *regs_set; + H265eV510StatusElem *regs_ret; + + /* hardware return info collection cfg */ + Vepu510H265Fbk feedback; + + /* osd cfg */ + Vepu5xxOsdCfg osd_cfg; + void *roi_data; + + /* roi buffer for qpmap or gdr */ + MppBuffer roir_buf; + RK_S32 roir_buf_size; + void *roi_base_cfg_sw_buf; + + /* variable length cfg */ + MppDevRegOffCfgs *reg_cfg; +} Vepu510H265eFrmCfg; + +typedef struct H265eV510HalContext_t { + MppDev dev; + void *regs; + void *reg_out; + Vepu510H265eFrmCfg *frms[MAX_FRAME_TASK_NUM]; + + /* current used frame config */ + Vepu510H265eFrmCfg *frm; + + /* slice split poll cfg */ + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + MppDevPollCfg *poll_cfgs; + MppCbCtx *output_cb; + + /* @frame_cnt starts from ZERO */ + RK_S32 frame_count; + + /* frame parallel info */ + RK_S32 task_cnt; + RK_S32 task_idx; + + /* dchs cfg */ + RK_S32 curr_idx; + RK_S32 prev_idx; + RK_S32 slot_to_dchs_txid[MAX_REFS]; + + Vepu510H265Fbk feedback; + Vepu510H265Fbk last_frame_fb; + void *dump_files; + RK_U32 frame_cnt_gen_ready; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + MppBufferGroup roi_grp; + void *roi_data; + MppEncCfgSet *cfg; + MppDevRegOffCfgs *reg_cfg; + H265eSyntax_new *syn; + H265eDpb *dpb; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + HalBufs dpb_bufs; + RK_S32 fbc_header_len; + RK_U32 title_num; + + RK_S32 qpmap_en; + RK_S32 smart_en; + RK_S32 sp_enc_en; + + /* external line buffer over 3K */ + MppBufferGroup ext_line_buf_grp; + RK_S32 ext_line_buf_size; + MppBuffer ext_line_buf; + MppBuffer buf_pass1; + MppBuffer ext_line_bufs[MAX_FRAME_TASK_NUM]; + + void *tune; +} H265eV510HalContext; + +#include "hal_h265e_vepu510_tune.c" + +static RK_S32 atf_b32_skip_thd2[4] = {15, 15, 15, 200}; +static RK_S32 atf_b32_skip_thd3[4] = {72, 72, 72, 1000}; +static RK_S32 atf_b32_skip_wgt0[4] = {16, 20, 20, 16}; +static RK_S32 atf_b32_skip_wgt3[4] = {16, 16, 16, 17}; +static RK_S32 atf_b16_skip_thd2[4] = {15, 15, 15, 200}; +static RK_S32 atf_b16_skip_thd3[4] = {25, 25, 25, 1000}; +static RK_S32 atf_b16_skip_wgt0[4] = {16, 20, 20, 16}; +static RK_S32 atf_b16_skip_wgt3[4] = {16, 16, 16, 17}; +static RK_S32 atf_b32_intra_thd0[4] = {20, 20, 20, 24}; +static RK_S32 atf_b32_intra_thd1[4] = {40, 40, 40, 48}; +static RK_S32 atf_b32_intra_thd2[4] = {60, 72, 72, 96}; +static RK_S32 atf_b32_intra_wgt0[4] = {16, 22, 27, 28}; +static RK_S32 atf_b32_intra_wgt1[4] = {16, 20, 25, 26}; +static RK_S32 atf_b32_intra_wgt2[4] = {16, 18, 20, 24}; +static RK_S32 atf_b16_intra_thd0[4] = {20, 20, 20, 24}; +static RK_S32 atf_b16_intra_thd1[4] = {40, 40, 40, 48}; +static RK_S32 atf_b16_intra_thd2[4] = {60, 72, 72, 96}; +static RK_S32 atf_b16_intra_wgt0[4] = {16, 22, 27, 28}; +static RK_S32 atf_b16_intra_wgt1[4] = {16, 20, 25, 26}; +static RK_S32 atf_b16_intra_wgt2[4] = {16, 18, 20, 24}; + +static RK_S32 smear_qp_strength[8] = {4, 6, 7, 7, 3, 5, 7, 7}; +static RK_S32 smear_strength[8] = {1, 1, 1, 1, 1, 1, 1, 1}; +static RK_S32 smear_common_intra_r_dep0[8] = {224, 224, 200, 200, 224, 224, 200, 200}; +static RK_S32 smear_common_intra_r_dep1[8] = {224, 224, 180, 200, 224, 224, 180, 200}; +static RK_S32 smear_bndry_intra_r_dep0[8] = {240, 240, 240, 240, 240, 240, 240, 240}; +static RK_S32 smear_bndry_intra_r_dep1[8] = {240, 240, 240, 240, 240, 240, 240, 240}; +static RK_S32 smear_thre_madp_stc_cover0[8] = {20, 22, 22, 22, 20, 22, 22, 30}; +static RK_S32 smear_thre_madp_stc_cover1[8] = {20, 22, 22, 22, 20, 22, 22, 30}; +static RK_S32 smear_thre_madp_mov_cover0[8] = {10, 9, 9, 9, 10, 9, 9, 6}; +static RK_S32 smear_thre_madp_mov_cover1[8] = {10, 9, 9, 9, 10, 9, 9, 6}; + +static RK_S32 smear_flag_cover_thd0[8] = {12, 13, 13, 13, 12, 13, 13, 17}; +static RK_S32 smear_flag_cover_thd1[8] = {61, 70, 70, 70, 61, 70, 70, 90}; +static RK_S32 smear_flag_bndry_thd0[8] = {12, 12, 12, 12, 12, 12, 12, 12}; +static RK_S32 smear_flag_bndry_thd1[8] = {73, 73, 73, 73, 73, 73, 73, 73}; + +static RK_S32 smear_flag_cover_wgt[3] = {1, 0, -3}; +static RK_S32 smear_flag_cover_intra_wgt0[3] = { -12, 0, 12}; +static RK_S32 smear_flag_cover_intra_wgt1[3] = { -12, 0, 12}; +static RK_S32 smear_flag_bndry_wgt[3] = {0, 0, 0}; +static RK_S32 smear_flag_bndry_intra_wgt0[3] = { -12, 0, 12}; +static RK_S32 smear_flag_bndry_intra_wgt1[3] = { -12, 0, 12}; + +static RK_U32 rdo_lambda_table_I[60] = { + 0x00000012, 0x00000017, + 0x0000001d, 0x00000024, 0x0000002e, 0x0000003a, + 0x00000049, 0x0000005c, 0x00000074, 0x00000092, + 0x000000b8, 0x000000e8, 0x00000124, 0x00000170, + 0x000001cf, 0x00000248, 0x000002df, 0x0000039f, + 0x0000048f, 0x000005bf, 0x0000073d, 0x0000091f, + 0x00000b7e, 0x00000e7a, 0x0000123d, 0x000016fb, + 0x00001cf4, 0x0000247b, 0x00002df6, 0x000039e9, + 0x000048f6, 0x00005bed, 0x000073d1, 0x000091ec, + 0x0000b7d9, 0x0000e7a2, 0x000123d7, 0x00016fb2, + 0x0001cf44, 0x000247ae, 0x0002df64, 0x00039e89, + 0x00048f5c, 0x0005bec8, 0x00073d12, 0x00091eb8, + 0x000b7d90, 0x000e7a23, 0x00123d71, 0x0016fb20, + 0x001cf446, 0x00247ae1, 0x002df640, 0x0039e88c, + 0x0048f5c3, 0x005bec81, 0x0073d119, 0x0091eb85, + 0x00b7d902, 0x00e7a232 +}; + +static RK_U32 rdo_lambda_table_P[60] = { + 0x0000002c, 0x00000038, 0x00000044, 0x00000058, + 0x00000070, 0x00000089, 0x000000b0, 0x000000e0, + 0x00000112, 0x00000160, 0x000001c0, 0x00000224, + 0x000002c0, 0x00000380, 0x00000448, 0x00000580, + 0x00000700, 0x00000890, 0x00000b00, 0x00000e00, + 0x00001120, 0x00001600, 0x00001c00, 0x00002240, + 0x00002c00, 0x00003800, 0x00004480, 0x00005800, + 0x00007000, 0x00008900, 0x0000b000, 0x0000e000, + 0x00011200, 0x00016000, 0x0001c000, 0x00022400, + 0x0002c000, 0x00038000, 0x00044800, 0x00058000, + 0x00070000, 0x00089000, 0x000b0000, 0x000e0000, + 0x00112000, 0x00160000, 0x001c0000, 0x00224000, + 0x002c0000, 0x00380000, 0x00448000, 0x00580000, + 0x00700000, 0x00890000, 0x00b00000, 0x00e00000, + 0x01120000, 0x01600000, 0x01c00000, 0x02240000, +}; + +static RK_U8 vepu510_h265_cqm_intra8[64] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115 +}; + +static RK_U8 vepu510_h265_cqm_inter8[64] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91 +}; + +static void setup_ext_line_bufs(H265eV510HalContext *ctx) +{ + RK_S32 i; + + for (i = 0; i < ctx->task_cnt; i++) { + if (ctx->ext_line_bufs[i]) + continue; + + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_bufs[i], + ctx->ext_line_buf_size); + } +} + +static void clear_ext_line_bufs(H265eV510HalContext *ctx) +{ + RK_S32 i; + + for (i = 0; i < ctx->task_cnt; i++) { + if (ctx->ext_line_bufs[i]) { + mpp_buffer_put(ctx->ext_line_bufs[i]); + ctx->ext_line_bufs[i] = NULL; + } + } +} + +static MPP_RET vepu510_h265_setup_hal_bufs(H265eV510HalContext *ctx) +{ + MPP_RET ret = MPP_OK; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + RK_U32 frame_size; + VepuFmt input_fmt = VEPU5xx_FMT_YUV420P; + RK_S32 mb_wd64, mb_h64; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + RK_S32 alignment = 32; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment); + + hal_h265e_enter(); + + mb_wd64 = (prep->width + 63) / 64; + mb_h64 = (prep->height + 63) / 64 + 1; + + frame_size = MPP_ALIGN(prep->width, 16) * MPP_ALIGN(prep->height, 16); + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + input_fmt = (VepuFmt)fmt->format; + switch (input_fmt) { + case VEPU5xx_FMT_YUV400: + break; + case VEPU5xx_FMT_YUV420P: + case VEPU5xx_FMT_YUV420SP: { + frame_size = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV422P: + case VEPU5xx_FMT_YUV422SP: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: + case VEPU5xx_FMT_BGR565: { + frame_size *= 2; + } break; + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_YUV444SP: + case VEPU5xx_FMT_YUV444P: { + frame_size *= 3; + } break; + case VEPU5xx_FMT_BGRA8888: { + frame_size *= 4; + } break; + default: { + hal_h265e_err("invalid src color space: %d\n", input_fmt); + return MPP_NOK; + } + } + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > SZ_4K) { + RK_S32 ctu_w = (aligned_w + 31) / 32; + RK_S32 ext_line_buf_size = ((ctu_w - 113) * 27 + 15) / 16 * 16 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + clear_ext_line_bufs(ctx); + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + setup_ext_line_bufs(ctx); + ctx->ext_line_buf_size = ext_line_buf_size; + } else { + clear_ext_line_bufs(ctx); + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + if (frame_size > ctx->frame_size || new_max_cnt > old_max_cnt) { + size_t size[4] = {0}; + RK_S32 ctu_w = (prep->width + 31) / 32; + RK_S32 ctu_h = (prep->height + 31) / 32; + + hal_bufs_deinit(ctx->dpb_bufs); + hal_bufs_init(&ctx->dpb_bufs); + + ctx->fbc_header_len = MPP_ALIGN(((mb_wd64 * mb_h64) << 6), SZ_8K); + size[0] = ctx->fbc_header_len + ((mb_wd64 * mb_h64) << 12) * 3 / 2; //fbc_h + fbc_b + size[1] = (mb_wd64 * mb_h64 << 8); + size[2] = MPP_ALIGN(mb_wd64 * mb_h64 * 16 * 4, 256) * 16; + /* smear bufs */ + size[3] = MPP_ALIGN(ctu_w, 16) * MPP_ALIGN(ctu_h, 16); + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_h265e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->frame_size, frame_size, old_max_cnt, new_max_cnt); + + hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, MPP_ARRAY_ELEMS(size), size); + + ctx->frame_size = frame_size; + ctx->max_buf_cnt = new_max_cnt; + } + hal_h265e_leave(); + return ret; +} + +static void vepu510_h265_set_atr_regs(H265eVepu510Sqi *reg_sqi, MppEncSceneMode sm, int atr_level) +{ + // atr_level 0~3 + // 0 close + // 1 weak + // 2 medium + // 3 strong + H265eVepu510Sqi *reg = reg_sqi; + (void)sm; + if (atr_level == 0) { + reg->block_opt_cfg.block_en = 0; + reg->cmplx_opt_cfg.cmplx_en = 0; + reg->line_opt_cfg.line_en = 0; + } else { + reg->block_opt_cfg.block_en = 0; + reg->cmplx_opt_cfg.cmplx_en = 0; + reg->line_opt_cfg.line_en = 1; + } + + if (atr_level == 3) { + reg->block_opt_cfg.block_thre_cst_best_mad = 1000; + reg->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + reg->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + reg->block_opt_cfg.block_delta_qp_flag = 3; + + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 4; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 30;//20 + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 30;//20 + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7;//7 + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 6;//8 + + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 50; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 50; + + reg->subj_opt_dqp0.line_thre_qp = 20; + reg->subj_opt_dqp0.block_strength = 4; + reg->subj_opt_dqp0.block_thre_qp = 30; + reg->subj_opt_dqp0.cmplx_strength = 4; + reg->subj_opt_dqp0.cmplx_thre_qp = 34; + reg->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + } else if (atr_level == 2) { + reg->block_opt_cfg.block_thre_cst_best_mad = 1000; + reg->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + reg->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + reg->block_opt_cfg.block_delta_qp_flag = 3; + + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 3; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 20; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 20; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 8; + + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 60; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 60; + + reg->subj_opt_dqp0.line_thre_qp = 25; + reg->subj_opt_dqp0.block_strength = 4; + reg->subj_opt_dqp0.block_thre_qp = 30; + reg->subj_opt_dqp0.cmplx_strength = 4; + reg->subj_opt_dqp0.cmplx_thre_qp = 34; + reg->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + } else { + reg->block_opt_cfg.block_thre_cst_best_mad = 1000; + reg->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + reg->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + reg->block_opt_cfg.block_delta_qp_flag = 3; + + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 6000; + reg->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 300; + reg->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 1280; + + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + reg->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 512; + + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 3; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 20; + reg->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 20; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + reg->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 8; + + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 70; + reg->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 70; + + reg->subj_opt_dqp0.line_thre_qp = 30; + reg->subj_opt_dqp0.block_strength = 4; + reg->subj_opt_dqp0.block_thre_qp = 30; + reg->subj_opt_dqp0.cmplx_strength = 4; + reg->subj_opt_dqp0.cmplx_thre_qp = 34; + reg->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + } +} + +static void vepu510_h265_set_anti_blur_regs(H265eVepu510Sqi *reg_sqi, int anti_blur_level) +{ + H265eVepu510Sqi *reg = reg_sqi; + if (anti_blur_level >= 1) + reg->subj_anti_blur_thd.anti_blur_en = 1; + else + reg->subj_anti_blur_thd.anti_blur_en = 0; + reg->subj_anti_blur_thd.blur_low_madi_thd = 5; + reg->subj_anti_blur_thd.blur_high_madi_thd = 27; + reg->subj_anti_blur_thd.blur_low_cnt_thd = 0; + reg->subj_anti_blur_thd.blur_hight_cnt_thd = 0; + reg->subj_anti_blur_thd.blur_sum_cnt_thd = 5; + + reg->subj_anti_blur_sao.blur_motion_thd = 32; + reg->subj_anti_blur_sao.sao_ofst_thd_eo_luma = 2; + reg->subj_anti_blur_sao.sao_ofst_thd_bo_luma = 4; + reg->subj_anti_blur_sao.sao_ofst_thd_eo_chroma = 2; + reg->subj_anti_blur_sao.sao_ofst_thd_bo_chroma = 4; +} + +static void vepu510_h265_set_anti_stripe_regs(H265eVepu510Sqi *reg_sqi, int atl_level) +{ + pre_cst_par* pre_i32 = (pre_cst_par*)®_sqi->preintra32_cst; + pre_cst_par* pre_i16 = (pre_cst_par*)®_sqi->preintra16_cst; + + pre_i32->cst_madi_thd0.madi_thd0 = 5; + pre_i32->cst_madi_thd0.madi_thd1 = 15; + pre_i32->cst_madi_thd0.madi_thd2 = 5; + pre_i32->cst_madi_thd0.madi_thd3 = 3; + pre_i32->cst_madi_thd1.madi_thd4 = 3; + pre_i32->cst_madi_thd1.madi_thd5 = 6; + pre_i32->cst_madi_thd1.madi_thd6 = 7; + pre_i32->cst_madi_thd1.madi_thd7 = 5; + pre_i32->cst_madi_thd2.madi_thd8 = 10; + pre_i32->cst_madi_thd2.madi_thd9 = 5; + pre_i32->cst_madi_thd2.madi_thd10 = 7; + pre_i32->cst_madi_thd2.madi_thd11 = 5; + pre_i32->cst_madi_thd3.madi_thd12 = 7; + pre_i32->cst_madi_thd3.madi_thd13 = 5; + pre_i32->cst_madi_thd3.mode_th = 5; + + pre_i32->cst_wgt0.wgt0 = 20; + pre_i32->cst_wgt0.wgt1 = 18; + pre_i32->cst_wgt0.wgt2 = 19; + pre_i32->cst_wgt0.wgt3 = 18; + pre_i32->cst_wgt1.wgt4 = 12; + pre_i32->cst_wgt1.wgt5 = 6; + pre_i32->cst_wgt1.wgt6 = 13; + pre_i32->cst_wgt1.wgt7 = 9; + pre_i32->cst_wgt2.wgt8 = 12; + pre_i32->cst_wgt2.wgt9 = 6; + pre_i32->cst_wgt2.wgt10 = 13; + pre_i32->cst_wgt2.wgt11 = 9; + pre_i32->cst_wgt3.wgt12 = 18; + pre_i32->cst_wgt3.wgt13 = 17; + pre_i32->cst_wgt3.wgt14 = 17; + + pre_i16->cst_madi_thd0.madi_thd0 = 5; + pre_i16->cst_madi_thd0.madi_thd1 = 15; + pre_i16->cst_madi_thd0.madi_thd2 = 5; + pre_i16->cst_madi_thd0.madi_thd3 = 3; + pre_i16->cst_madi_thd1.madi_thd4 = 3; + pre_i16->cst_madi_thd1.madi_thd5 = 6; + pre_i16->cst_madi_thd1.madi_thd6 = 7; + pre_i16->cst_madi_thd1.madi_thd7 = 5; + pre_i16->cst_madi_thd2.madi_thd8 = 10; + pre_i16->cst_madi_thd2.madi_thd9 = 5; + pre_i16->cst_madi_thd2.madi_thd10 = 7; + pre_i16->cst_madi_thd2.madi_thd11 = 5; + pre_i16->cst_madi_thd3.madi_thd12 = 7; + pre_i16->cst_madi_thd3.madi_thd13 = 5; + pre_i16->cst_madi_thd3.mode_th = 5; + + pre_i16->cst_wgt0.wgt0 = 20; + pre_i16->cst_wgt0.wgt1 = 18; + pre_i16->cst_wgt0.wgt2 = 19; + pre_i16->cst_wgt0.wgt3 = 18; + pre_i16->cst_wgt1.wgt4 = 12; + pre_i16->cst_wgt1.wgt5 = 6; + pre_i16->cst_wgt1.wgt6 = 13; + pre_i16->cst_wgt1.wgt7 = 9; + pre_i16->cst_wgt2.wgt8 = 12; + pre_i16->cst_wgt2.wgt9 = 6; + pre_i16->cst_wgt2.wgt10 = 13; + pre_i16->cst_wgt2.wgt11 = 9; + pre_i16->cst_wgt3.wgt12 = 18; + pre_i16->cst_wgt3.wgt13 = 17; + pre_i16->cst_wgt3.wgt14 = 17; + + pre_i32->cst_madi_thd3.qp_thd = 28; + pre_i32->cst_wgt3.lambda_mv_bit_0 = 5; // lv32 + pre_i32->cst_wgt3.lambda_mv_bit_1 = 4; // lv16 + pre_i16->cst_wgt3.lambda_mv_bit_0 = 4; // lv8 + pre_i16->cst_wgt3.lambda_mv_bit_1 = 3; // lv4 + if (atl_level >= 1) + pre_i32->cst_wgt3.anti_strp_e = 1; + else + pre_i32->cst_wgt3.anti_strp_e = 0; +} + +static void vepu510_h265_rdo_cfg(H265eV510HalContext *ctx, H265eVepu510Sqi *reg, MppEncSceneMode sm) +{ + reg->subj_opt_cfg.subj_opt_en = 1; + reg->subj_opt_cfg.subj_opt_strength = 3; + reg->subj_opt_cfg.aq_subj_en = (sm == MPP_ENC_SCENE_MODE_IPC); + reg->subj_opt_cfg.aq_subj_strength = 4; + + /* skin_opt */ + reg->skin_opt_cfg.skin_en = 0; + reg->skin_opt_cfg.skin_strength = 3; + reg->skin_opt_cfg.thre_uvsqr16_skin = 128; + reg->skin_opt_cfg.skin_thre_cst_best_mad = 1000; + reg->skin_opt_cfg.skin_thre_cst_best_grdn_blk = 98; + reg->skin_opt_cfg.frame_skin_ratio = 3; + reg->skin_chrm_thd.thre_sum_mad_intra = 3; + reg->skin_chrm_thd.thre_sum_grdn_blk_intra = 3; + reg->skin_chrm_thd.vld_thre_skin_v = 7; + reg->skin_chrm_thd.thre_min_skin_u = 107; + reg->skin_chrm_thd.thre_max_skin_u = 129; + reg->skin_chrm_thd.thre_min_skin_v = 135; + reg->subj_opt_dqp1.skin_thre_qp = 31; + + /* 0x00002100 reg2112 */ + reg->cudecis_thd0.base_thre_rough_mad32_intra = 9; + reg->cudecis_thd0.delta0_thre_rough_mad32_intra = 10; + reg->cudecis_thd0.delta1_thre_rough_mad32_intra = 55; + reg->cudecis_thd0.delta2_thre_rough_mad32_intra = 55; + reg->cudecis_thd0.delta3_thre_rough_mad32_intra = 66; + reg->cudecis_thd0.delta4_thre_rough_mad32_intra_low5 = 2; + + /* 0x00002104 reg2113 */ + reg->cudecis_thd1.delta4_thre_rough_mad32_intra_high2 = 2; + reg->cudecis_thd1.delta5_thre_rough_mad32_intra = 74; + reg->cudecis_thd1.delta6_thre_rough_mad32_intra = 106; + reg->cudecis_thd1.base_thre_fine_mad32_intra = 8; + reg->cudecis_thd1.delta0_thre_fine_mad32_intra = 0; + reg->cudecis_thd1.delta1_thre_fine_mad32_intra = 13; + reg->cudecis_thd1.delta2_thre_fine_mad32_intra_low3 = 6; + + /* 0x00002108 reg2114 */ + reg->cudecis_thd2.delta2_thre_fine_mad32_intra_high2 = 1; + reg->cudecis_thd2.delta3_thre_fine_mad32_intra = 17; + reg->cudecis_thd2.delta4_thre_fine_mad32_intra = 23; + reg->cudecis_thd2.delta5_thre_fine_mad32_intra = 50; + reg->cudecis_thd2.delta6_thre_fine_mad32_intra = 54; + reg->cudecis_thd2.base_thre_str_edge_mad32_intra = 6; + reg->cudecis_thd2.delta0_thre_str_edge_mad32_intra = 0; + reg->cudecis_thd2.delta1_thre_str_edge_mad32_intra = 0; + + /* 0x0000210c reg2115 */ + reg->cudecis_thd3.delta2_thre_str_edge_mad32_intra = 3; + reg->cudecis_thd3.delta3_thre_str_edge_mad32_intra = 8; + reg->cudecis_thd3.base_thre_str_edge_bgrad32_intra = 25; + reg->cudecis_thd3.delta0_thre_str_edge_bgrad32_intra = 0; + reg->cudecis_thd3.delta1_thre_str_edge_bgrad32_intra = 0; + reg->cudecis_thd3.delta2_thre_str_edge_bgrad32_intra = 7; + reg->cudecis_thd3.delta3_thre_str_edge_bgrad32_intra = 19; + reg->cudecis_thd3.base_thre_mad16_intra = 6; + reg->cudecis_thd3.delta0_thre_mad16_intra = 0; + + /* 0x00002110 reg2116 */ + reg->cudecis_thd4.delta1_thre_mad16_intra = 3; + reg->cudecis_thd4.delta2_thre_mad16_intra = 3; + reg->cudecis_thd4.delta3_thre_mad16_intra = 24; + reg->cudecis_thd4.delta4_thre_mad16_intra = 28; + reg->cudecis_thd4.delta5_thre_mad16_intra = 40; + reg->cudecis_thd4.delta6_thre_mad16_intra = 52; + reg->cudecis_thd4.delta0_thre_mad16_ratio_intra = 7; + + /* 0x00002114 reg2117 */ + reg->cudecis_thd5.delta1_thre_mad16_ratio_intra = 7; + reg->cudecis_thd5.delta2_thre_mad16_ratio_intra = 2; + reg->cudecis_thd5.delta3_thre_mad16_ratio_intra = 2; + reg->cudecis_thd5.delta4_thre_mad16_ratio_intra = 0; + reg->cudecis_thd5.delta5_thre_mad16_ratio_intra = 0; + reg->cudecis_thd5.delta6_thre_mad16_ratio_intra = 0; + reg->cudecis_thd5.delta7_thre_mad16_ratio_intra = 4; + reg->cudecis_thd5.delta0_thre_rough_bgrad32_intra = 1; + reg->cudecis_thd5.delta1_thre_rough_bgrad32_intra = 5; + reg->cudecis_thd5.delta2_thre_rough_bgrad32_intra_low4 = 8; + + /* 0x00002118 reg2118 */ + reg->cudecis_thd6.delta2_thre_rough_bgrad32_intra_high2 = 2; + reg->cudecis_thd6.delta3_thre_rough_bgrad32_intra = 540; + reg->cudecis_thd6.delta4_thre_rough_bgrad32_intra = 692; + reg->cudecis_thd6.delta5_thre_rough_bgrad32_intra_low10 = 866; + + /* 0x0000211c reg2119 */ + reg->cudecis_thd7.delta5_thre_rough_bgrad32_intra_high1 = 1; + reg->cudecis_thd7.delta6_thre_rough_bgrad32_intra = 3286; + reg->cudecis_thd7.delta7_thre_rough_bgrad32_intra = 6620; + reg->cudecis_thd7.delta0_thre_bgrad16_ratio_intra = 8; + reg->cudecis_thd7.delta1_thre_bgrad16_ratio_intra_low2 = 3; + + /* 0x00002120 reg2120 */ + reg->cudecis_thdt8.delta1_thre_bgrad16_ratio_intra_high2 = 2; + reg->cudecis_thdt8.delta2_thre_bgrad16_ratio_intra = 15; + reg->cudecis_thdt8.delta3_thre_bgrad16_ratio_intra = 15; + reg->cudecis_thdt8.delta4_thre_bgrad16_ratio_intra = 13; + reg->cudecis_thdt8.delta5_thre_bgrad16_ratio_intra = 13; + reg->cudecis_thdt8.delta6_thre_bgrad16_ratio_intra = 7; + reg->cudecis_thdt8.delta7_thre_bgrad16_ratio_intra = 15; + reg->cudecis_thdt8.delta0_thre_fme_ratio_inter = 4; + reg->cudecis_thdt8.delta1_thre_fme_ratio_inter = 4; + + /* 0x00002124 reg2121 */ + reg->cudecis_thd9.delta2_thre_fme_ratio_inter = 3; + reg->cudecis_thd9.delta3_thre_fme_ratio_inter = 2; + reg->cudecis_thd9.delta4_thre_fme_ratio_inter = 0; + reg->cudecis_thd9.delta5_thre_fme_ratio_inter = 0; + reg->cudecis_thd9.delta6_thre_fme_ratio_inter = 0; + reg->cudecis_thd9.delta7_thre_fme_ratio_inter = 0; + reg->cudecis_thd9.base_thre_fme32_inter = 4; + reg->cudecis_thd9.delta0_thre_fme32_inter = 2; + reg->cudecis_thd9.delta1_thre_fme32_inter = 7; + reg->cudecis_thd9.delta2_thre_fme32_inter = 12; + + /* 0x00002128 reg2122 */ + reg->cudecis_thd10.delta3_thre_fme32_inter = 23; + reg->cudecis_thd10.delta4_thre_fme32_inter = 41; + reg->cudecis_thd10.delta5_thre_fme32_inter = 71; + reg->cudecis_thd10.delta6_thre_fme32_inter = 123; + reg->cudecis_thd10.thre_cme32_inter = 48; + + /* 0x0000212c reg2123 */ + reg->cudecis_thd11.delta0_thre_mad_fme_ratio_inter = 0; + reg->cudecis_thd11.delta1_thre_mad_fme_ratio_inter = 7; + reg->cudecis_thd11.delta2_thre_mad_fme_ratio_inter = 7; + reg->cudecis_thd11.delta3_thre_mad_fme_ratio_inter = 6; + reg->cudecis_thd11.delta4_thre_mad_fme_ratio_inter = 5; + reg->cudecis_thd11.delta5_thre_mad_fme_ratio_inter = 4; + reg->cudecis_thd11.delta6_thre_mad_fme_ratio_inter = 4; + reg->cudecis_thd11.delta7_thre_mad_fme_ratio_inter = 4; + + vepu510_h265_set_anti_stripe_regs(reg, ctx->cfg->tune.atl_str); + if (ctx->frame_type == INTRA_FRAME) + vepu510_h265_set_atr_regs(reg, sm, ctx->cfg->tune.atr_str_i); + else + vepu510_h265_set_atr_regs(reg, sm, ctx->cfg->tune.atr_str_p); + + if (ctx->frame_type == INTRA_FRAME) + vepu510_h265_set_anti_blur_regs(reg, ctx->cfg->tune.sao_str_i); + else + vepu510_h265_set_anti_blur_regs(reg, ctx->cfg->tune.sao_str_p); +} + +static void vepu510_h265_atf_cfg(H265eVepu510Sqi *reg, RK_S32 atf_str) +{ + rdo_skip_par *p_rdo_skip = NULL; + rdo_noskip_par *p_rdo_noskip = NULL; + + p_rdo_skip = ®->rdo_b32_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 5 ; + p_rdo_skip->atf_thd0.madp_thd1 = 10 ; + p_rdo_skip->atf_thd1.madp_thd2 = atf_b32_skip_thd2[atf_str]; + p_rdo_skip->atf_thd1.madp_thd3 = atf_b32_skip_thd3[atf_str]; + p_rdo_skip->atf_wgt0.wgt0 = atf_b32_skip_wgt0[atf_str]; + p_rdo_skip->atf_wgt0.wgt1 = 16 ; + p_rdo_skip->atf_wgt0.wgt2 = 16 ; + p_rdo_skip->atf_wgt0.wgt3 = atf_b32_skip_wgt3[atf_str]; + + p_rdo_noskip = ®->rdo_b32_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 16; + p_rdo_noskip->atf_wgt.wgt1 = 16; + p_rdo_noskip->atf_wgt.wgt2 = 16; + + p_rdo_noskip = ®->rdo_b32_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = atf_b32_intra_thd0[atf_str]; + p_rdo_noskip->ratf_thd0.madp_thd1 = atf_b32_intra_thd1[atf_str]; + p_rdo_noskip->ratf_thd1.madp_thd2 = atf_b32_intra_thd2[atf_str]; + p_rdo_noskip->atf_wgt.wgt0 = atf_b32_intra_wgt0[atf_str]; + p_rdo_noskip->atf_wgt.wgt1 = atf_b32_intra_wgt1[atf_str]; + p_rdo_noskip->atf_wgt.wgt2 = atf_b32_intra_wgt2[atf_str]; + + p_rdo_skip = ®->rdo_b16_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 1 ; + p_rdo_skip->atf_thd0.madp_thd1 = 10 ; + p_rdo_skip->atf_thd1.madp_thd2 = atf_b16_skip_thd2[atf_str]; + p_rdo_skip->atf_thd1.madp_thd3 = atf_b16_skip_thd3[atf_str]; + p_rdo_skip->atf_wgt0.wgt0 = atf_b16_skip_wgt0[atf_str]; + p_rdo_skip->atf_wgt0.wgt1 = 16 ; + p_rdo_skip->atf_wgt0.wgt2 = 16 ; + p_rdo_skip->atf_wgt0.wgt3 = atf_b16_skip_wgt3[atf_str]; + p_rdo_skip->atf_wgt1.wgt4 = 16 ; + + p_rdo_noskip = ®->rdo_b16_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 16; + p_rdo_noskip->atf_wgt.wgt1 = 16; + p_rdo_noskip->atf_wgt.wgt2 = 16; + p_rdo_noskip->atf_wgt.wgt3 = 16; + + p_rdo_noskip = ®->rdo_b16_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = atf_b16_intra_thd0[atf_str]; + p_rdo_noskip->ratf_thd0.madp_thd1 = atf_b16_intra_thd1[atf_str]; + p_rdo_noskip->ratf_thd1.madp_thd2 = atf_b16_intra_thd2[atf_str]; + p_rdo_noskip->atf_wgt.wgt0 = atf_b16_intra_wgt0[atf_str]; + p_rdo_noskip->atf_wgt.wgt1 = atf_b16_intra_wgt1[atf_str]; + p_rdo_noskip->atf_wgt.wgt2 = atf_b16_intra_wgt2[atf_str]; + p_rdo_noskip->atf_wgt.wgt3 = 16; +} + +static void vepu510_h265_smear_cfg(H265eVepu510Sqi *reg, H265eV510HalContext *ctx) +{ + RK_S32 frame_num = ctx->frame_num; + RK_S32 frame_keyint = (ctx->cfg->rc.gop > 0) ? ctx->cfg->rc.gop : 0x7FFFFFFF; + RK_U32 cover_num = ctx->feedback.acc_cover16_num; + RK_U32 bndry_num = ctx->feedback.acc_bndry16_num; + RK_U32 st_ctu_num = ctx->feedback.st_ctu_num; + RK_S32 deblur_en = ctx->cfg->tune.deblur_en; + RK_S32 deblur_str = ctx->cfg->tune.deblur_str; + RK_S16 flag_cover = 0; + RK_S16 flag_bndry = 0; + + if (cover_num * 1000 < smear_flag_cover_thd0[deblur_str] * st_ctu_num) + flag_cover = 0; + else if (cover_num * 1000 < smear_flag_cover_thd1[deblur_str] * st_ctu_num) + flag_cover = 1; + else + flag_cover = 2; + + if (bndry_num * 1000 < smear_flag_bndry_thd0[deblur_str] * st_ctu_num) + flag_bndry = 0; + else if (bndry_num * 1000 < smear_flag_bndry_thd1[deblur_str] * st_ctu_num) + flag_bndry = 1; + else + flag_bndry = 2; + + reg->subj_opt_dpth_thd.common_thre_num_grdn_point_dep0 = 64; + reg->subj_opt_dpth_thd.common_thre_num_grdn_point_dep1 = 32; + reg->subj_opt_dpth_thd.common_thre_num_grdn_point_dep2 = 16; + reg->subj_opt_inrar_coef.common_rdo_cu_intra_r_coef_dep0 = smear_common_intra_r_dep0[deblur_str] + smear_flag_cover_intra_wgt0[flag_bndry]; + reg->subj_opt_inrar_coef.common_rdo_cu_intra_r_coef_dep1 = smear_common_intra_r_dep1[deblur_str] + smear_flag_cover_intra_wgt1[flag_bndry]; + + /* anti smear */ + reg->smear_opt_cfg0.anti_smear_en = 1; + if (deblur_en == 0) + reg->smear_opt_cfg0.anti_smear_en = 0; + reg->smear_opt_cfg0.smear_strength = smear_strength[deblur_str] + smear_flag_bndry_wgt[flag_cover]; + reg->smear_opt_cfg0.thre_mv_inconfor_cime = 8; + reg->smear_opt_cfg0.thre_mv_confor_cime = 2; + reg->smear_opt_cfg0.thre_mv_inconfor_cime_gmv = 8; + reg->smear_opt_cfg0.thre_mv_confor_cime_gmv = 2; + reg->smear_opt_cfg0.thre_num_mv_confor_cime = 3; + reg->smear_opt_cfg0.thre_num_mv_confor_cime_gmv = 2; + reg->smear_opt_cfg0.frm_static = 1; + + if (((frame_num) % frame_keyint == 0) || reg->smear_opt_cfg0.frm_static == 0 || (frame_num) % frame_keyint == 1) { + reg->smear_opt_cfg0.smear_load_en = 0; + } else { + reg->smear_opt_cfg0.smear_load_en = 1; + } + + if (((frame_num) % frame_keyint == 0) || reg->smear_opt_cfg0.frm_static == 0 || (frame_num) % frame_keyint == frame_keyint - 1) { + reg->smear_opt_cfg0.smear_stor_en = 0; + } else { + reg->smear_opt_cfg0.smear_stor_en = 1; + } + + reg->smear_opt_cfg1.dist0_frm_avg = 0; + reg->smear_opt_cfg1.thre_dsp_static = 10; + reg->smear_opt_cfg1.thre_dsp_mov = 15; + reg->smear_opt_cfg1.thre_dist_mv_confor_cime = 32; + + reg->smear_madp_thd.thre_madp_stc_dep0 = 10; + reg->smear_madp_thd.thre_madp_stc_dep1 = 8; + reg->smear_madp_thd.thre_madp_stc_dep2 = 8; + reg->smear_madp_thd.thre_madp_mov_dep0 = 16; + reg->smear_madp_thd.thre_madp_mov_dep1 = 18; + reg->smear_madp_thd.thre_madp_mov_dep2 = 20; + + reg->smear_stat_thd.thre_num_pt_stc_dep0 = 47; + reg->smear_stat_thd.thre_num_pt_stc_dep1 = 11; + reg->smear_stat_thd.thre_num_pt_stc_dep2 = 3; + reg->smear_stat_thd.thre_num_pt_mov_dep0 = 47; + reg->smear_stat_thd.thre_num_pt_mov_dep1 = 11; + reg->smear_stat_thd.thre_num_pt_mov_dep2 = 3; + + reg->smear_bmv_dist_thd0.thre_ratio_dist_mv_confor_cime_gmv0 = 21; + reg->smear_bmv_dist_thd0.thre_ratio_dist_mv_confor_cime_gmv1 = 16; + reg->smear_bmv_dist_thd0.thre_ratio_dist_mv_inconfor_cime_gmv0 = 48; + reg->smear_bmv_dist_thd0.thre_ratio_dist_mv_inconfor_cime_gmv1 = 34; + + reg->smear_bmv_dist_thd1.thre_ratio_dist_mv_inconfor_cime_gmv2 = 32; + reg->smear_bmv_dist_thd1.thre_ratio_dist_mv_inconfor_cime_gmv3 = 29; + reg->smear_bmv_dist_thd1.thre_ratio_dist_mv_inconfor_cime_gmv4 = 27; + + reg->smear_min_bndry_gmv.thre_min_num_confor_csu0_bndry_cime_gmv = 0; + reg->smear_min_bndry_gmv.thre_max_num_confor_csu0_bndry_cime_gmv = 3; + reg->smear_min_bndry_gmv.thre_min_num_inconfor_csu0_bndry_cime_gmv = 0; + reg->smear_min_bndry_gmv.thre_max_num_inconfor_csu0_bndry_cime_gmv = 3; + reg->smear_min_bndry_gmv.thre_split_dep0 = 2; + reg->smear_min_bndry_gmv.thre_zero_srgn = 8; + reg->smear_min_bndry_gmv.madi_thre_dep0 = 22; + reg->smear_min_bndry_gmv.madi_thre_dep1 = 18; + + reg->smear_madp_cov_thd.thre_madp_stc_cover0 = smear_thre_madp_stc_cover0[deblur_str]; + reg->smear_madp_cov_thd.thre_madp_stc_cover1 = smear_thre_madp_stc_cover1[deblur_str]; + reg->smear_madp_cov_thd.thre_madp_mov_cover0 = smear_thre_madp_mov_cover0[deblur_str]; + reg->smear_madp_cov_thd.thre_madp_mov_cover1 = smear_thre_madp_mov_cover1[deblur_str]; + reg->smear_madp_cov_thd.smear_qp_strength = smear_qp_strength[deblur_str] + smear_flag_cover_wgt[flag_cover]; + reg->smear_madp_cov_thd.smear_thre_qp = 30; + + reg->subj_opt_dqp1.bndry_rdo_cu_intra_r_coef_dep0 = smear_bndry_intra_r_dep0[deblur_str] + smear_flag_bndry_intra_wgt0[flag_bndry]; + reg->subj_opt_dqp1.bndry_rdo_cu_intra_r_coef_dep1 = smear_bndry_intra_r_dep1[deblur_str] + smear_flag_bndry_intra_wgt1[flag_bndry]; +} + +static void vepu510_h265_global_cfg_set(H265eV510HalContext *ctx, H265eV510RegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + H265eVepu510Param *reg_param = ®s->reg_param; + H265eVepu510Sqi *reg_sqi = ®s->reg_sqi; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + RK_S32 atf_str = ctx->cfg->tune.anti_flicker_str; + RK_S32 lambda_idx = 0; + + vepu510_h265_rdo_cfg(ctx, reg_sqi, sm); + vepu510_h265_atf_cfg(reg_sqi, atf_str); + vepu510_h265_smear_cfg(reg_sqi, ctx); + memcpy(®_param->pprd_lamb_satd_0_51[0], lamd_satd_qp_510, sizeof(lamd_satd_qp)); + + if (ctx->frame_type == INTRA_FRAME) { + reg_param->iprd_lamb_satd_ofst.lambda_satd_offset = 11; + lambda_idx = ctx->cfg->tune.lambda_idx_i; + memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], + &rdo_lambda_table_I[lambda_idx], H265E_LAMBDA_TAB_SIZE); + } else { + reg_param->iprd_lamb_satd_ofst.lambda_satd_offset = 11; + lambda_idx = ctx->cfg->tune.lambda_idx_p; + memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], + &rdo_lambda_table_P[lambda_idx], H265E_LAMBDA_TAB_SIZE); + } + + reg_param->qnt_bias_comb.qnt_f_bias_i = 171; + reg_param->qnt_bias_comb.qnt_f_bias_p = 85; + if (hw->qbias_en) { + reg_param->qnt_bias_comb.qnt_f_bias_i = hw->qbias_i; + reg_param->qnt_bias_comb.qnt_f_bias_p = hw->qbias_p; + } else if (ctx->smart_en || ctx->sp_enc_en) { + reg_param->qnt_bias_comb.qnt_f_bias_i = 144; + } + + /* CIME */ + { + reg_param->me_sqi_comb.cime_pmv_num = 1; + reg_param->me_sqi_comb.cime_fuse = 1; + reg_param->me_sqi_comb.itp_mode = 1; + reg_param->me_sqi_comb.move_lambda = (sm == MPP_ENC_SCENE_MODE_IPC) ? 2 : 8; + reg_param->me_sqi_comb.rime_lvl_mrg = 1; + reg_param->me_sqi_comb.rime_prelvl_en = 3; + reg_param->me_sqi_comb.rime_prersu_en = 0; + reg_param->cime_mvd_th_comb.cime_mvd_th0 = 8; + reg_param->cime_mvd_th_comb.cime_mvd_th1 = 20; + reg_param->cime_mvd_th_comb.cime_mvd_th2 = 32; + reg_param->cime_madp_th_comb.cime_madp_th = (sm == MPP_ENC_SCENE_MODE_IPC) ? 16 : 0; + + if (sm == MPP_ENC_SCENE_MODE_IPC) { + reg_param->cime_multi_comb.cime_multi0 = 8; + reg_param->cime_multi_comb.cime_multi1 = 12; + reg_param->cime_multi_comb.cime_multi2 = 16; + reg_param->cime_multi_comb.cime_multi3 = 20; + } else { + reg_param->cime_multi_comb.cime_multi0 = 4; + reg_param->cime_multi_comb.cime_multi1 = 4; + reg_param->cime_multi_comb.cime_multi2 = 4; + reg_param->cime_multi_comb.cime_multi3 = 4; + } + } + + /* RIME && FME */ + if (sm == MPP_ENC_SCENE_MODE_IPC) { + reg_param->rime_mvd_th_comb.rime_mvd_th0 = 1; + reg_param->rime_mvd_th_comb.rime_mvd_th1 = 2; + reg_param->rime_mvd_th_comb.fme_madp_th = 0; + reg_param->rime_madp_th_comb.rime_madp_th0 = 8; + reg_param->rime_madp_th_comb.rime_madp_th1 = 16; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 8; + reg_param->rime_multi_comb.rime_multi2 = 12; + } else { + reg_param->rime_mvd_th_comb.rime_mvd_th0 = 0; + reg_param->rime_mvd_th_comb.rime_mvd_th1 = 0; + reg_param->rime_mvd_th_comb.fme_madp_th = 30; + reg_param->rime_madp_th_comb.rime_madp_th0 = 0; + reg_param->rime_madp_th_comb.rime_madp_th1 = 0; + reg_param->rime_multi_comb.rime_multi0 = 4; + reg_param->rime_multi_comb.rime_multi1 = 4; + reg_param->rime_multi_comb.rime_multi2 = 4; + } + + { + /* 0x1064 */ + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + /* 0x1068 */ + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + /* 0x106C */ + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; + + /* 0x177C */ + reg_param->cmv_st_th_comb.cmv_th0 = 64; + reg_param->cmv_st_th_comb.cmv_th1 = 96; + reg_param->cmv_st_th_comb.cmv_th2 = 128; + } +} + +MPP_RET hal_h265e_v510_deinit(void *hal) +{ + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + RK_S32 i = 0; + + hal_h265e_enter(); + MPP_FREE(ctx->poll_cfgs); + MPP_FREE(ctx->input_fmt); + hal_bufs_deinit(ctx->dpb_bufs); + + for (i = 0; i < ctx->task_cnt; i++) { + Vepu510H265eFrmCfg *frm = ctx->frms[i]; + + if (!frm) + continue; + + if (frm->roir_buf) { + mpp_buffer_put(frm->roir_buf); + frm->roir_buf = NULL; + frm->roir_buf_size = 0; + } + + MPP_FREE(frm->roi_base_cfg_sw_buf); + + if (frm->reg_cfg) { + mpp_dev_multi_offset_deinit(frm->reg_cfg); + frm->reg_cfg = NULL; + } + + MPP_FREE(frm->regs_set); + MPP_FREE(frm->regs_ret); + MPP_FREE(ctx->frms[i]); + } + + clear_ext_line_bufs(ctx); + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + + if (ctx->buf_pass1) { + mpp_buffer_put(ctx->buf_pass1); + ctx->buf_pass1 = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + if (ctx->reg_cfg) { + mpp_dev_multi_offset_deinit(ctx->reg_cfg); + ctx->reg_cfg = NULL; + } + + if (ctx->roi_grp) { + mpp_buffer_group_put(ctx->roi_grp); + ctx->roi_grp = NULL; + } + + if (ctx->tune) { + vepu510_h265e_tune_deinit(ctx->tune); + ctx->tune = NULL; + } + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v510_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + RK_S32 i = 0; + + mpp_env_get_u32("hal_h265e_debug", &hal_h265e_debug, 0); + hal_h265e_enter(); + + ctx->task_cnt = cfg->task_cnt; + mpp_assert(ctx->task_cnt && ctx->task_cnt <= MAX_FRAME_TASK_NUM); + if (ctx->task_cnt > MAX_FRAME_TASK_NUM) + ctx->task_cnt = MAX_FRAME_TASK_NUM; + + for (i = 0; i < ctx->task_cnt; i++) { + Vepu510H265eFrmCfg *frm_cfg = mpp_calloc(Vepu510H265eFrmCfg, 1); + + frm_cfg->regs_set = mpp_calloc(H265eV510RegSet, 1); + frm_cfg->regs_ret = mpp_calloc(H265eV510StatusElem, 1); + frm_cfg->frame_type = INTRA_FRAME; + ctx->frms[i] = frm_cfg; + } + + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + hal_bufs_init(&ctx->dpb_bufs); + + ctx->frame_count = -1; + ctx->frame_cnt_gen_ready = 0; + ctx->enc_mode = 1; + cfg->cap_recn_out = 1; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + mpp_dev_multi_offset_init(&ctx->reg_cfg, 24); + ctx->dev = cfg->dev; + ctx->frame_type = INTRA_FRAME; + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + RK_U32 j; + + hw->qp_delta_row_i = 2; + hw->qp_delta_row = 2; + hw->qbias_i = 171; + hw->qbias_p = 85; + hw->qbias_en = 0; + + for (j = 0; j < MPP_ARRAY_ELEMS(hw->mode_bias); j++) + hw->mode_bias[j] = 8; + } + + ctx->poll_slice_max = 8; + ctx->poll_cfg_size = (sizeof(ctx->poll_cfgs) + sizeof(RK_S32) * ctx->poll_slice_max) * 2; + ctx->poll_cfgs = mpp_malloc_size(MppDevPollCfg, ctx->poll_cfg_size); + + if (NULL == ctx->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init poll cfg buffer failed\n"); + goto DONE; + } + + ctx->output_cb = cfg->output_cb; + cfg->cap_recn_out = 1; + + ctx->tune = vepu510_h265e_tune_init(ctx); + memset(ctx->slot_to_dchs_txid, 0, sizeof(ctx->slot_to_dchs_txid)); + +DONE: + if (ret) + hal_h265e_v510_deinit(hal); + + hal_h265e_leave(); + return ret; +} + +static MPP_RET hal_h265e_vepu510_prepare(void *hal) +{ + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h265e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + vepu510_h265_setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->dpb_bufs, i); + + prep->change_res = 0; + } + + hal_h265e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET +vepu510_h265_set_patch_info(H265eSyntax_new *syn, VepuFmt input_fmt, MppDevRegOffCfgs *offsets, HalEncTask *task) +{ + RK_U32 hor_stride = syn->pp.hor_stride; + RK_U32 ver_stride = (syn->pp.ver_stride != 0) ? syn->pp.ver_stride : syn->pp.pic_height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + mpp_err("VEPU_510 unsupports FBC format input.\n"); + + ret = MPP_NOK; + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV400: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride * 2; + } break; + default: { + hal_h265e_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + mpp_dev_multi_offset_update(offsets, 161, u_offset); + mpp_dev_multi_offset_update(offsets, 162, v_offset); + + return ret; +} + + +#if 0 +static MPP_RET vepu510_h265_set_roi_regs(H265eV510HalContext *ctx, H265eVepu510Frame *regs) +{ + /* memset register on start so do not clear registers again here */ + if (ctx->roi_data) { + /* roi setup */ + MppEncROICfg2 *cfg = ( MppEncROICfg2 *)ctx->roi_data; + + regs->reg0192_enc_pic.roi_en = 1; + regs->reg0178_roi_addr = mpp_dev_get_iova_address(ctx->dev, cfg->base_cfg_buf, 0); + if (cfg->roi_qp_en) { + regs->reg0179_roi_qp_addr = mpp_dev_get_iova_address(ctx->dev, cfg->qp_cfg_buf, 0); + regs->reg0228_roi_en.roi_qp_en = 1; + } + + if (cfg->roi_amv_en) { + regs->reg0180_roi_amv_addr = mpp_dev_get_iova_address(ctx->dev, cfg->amv_cfg_buf, 0); + regs->reg0228_roi_en.roi_amv_en = 1; + } + + if (cfg->roi_mv_en) { + regs->reg0181_roi_mv_addr = mpp_dev_get_iova_address(ctx->dev, cfg->mv_cfg_buf, 0); + regs->reg0228_roi_en.roi_mv_en = 1; + } + } + + return MPP_OK; +} +#endif + +static MPP_RET vepu510_h265_set_rc_regs(H265eV510HalContext *ctx, H265eV510RegSet *regs, HalEncTask *task) +{ + H265eSyntax_new *syn = ctx->syn; + EncRcTaskInfo *rc_cfg = &task->rc_task->info; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + Vepu510RcRoi *reg_rc = ®s->reg_rc_roi; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + MppEncH265Cfg *h265 = &cfg->h265; + RK_S32 mb_wd32 = (syn->pp.pic_width + 31) / 32; + RK_S32 mb_h32 = (syn->pp.pic_height + 31) / 32; + + RK_U32 ctu_target_bits_mul_16 = (rc_cfg->bit_target << 4) / (mb_wd32 * mb_h32); + RK_U32 ctu_target_bits; + RK_S32 negative_bits_thd, positive_bits_thd; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + reg_frm->common.enc_pic.pic_qp = rc_cfg->quality_target; + reg_frm->synt_sli1.sli_qp = rc_cfg->quality_target; + reg_frm->common.rc_qp.rc_max_qp = rc_cfg->quality_target; + reg_frm->common.rc_qp.rc_min_qp = rc_cfg->quality_target; + } else { + if (ctu_target_bits_mul_16 >= 0x100000) { + ctu_target_bits_mul_16 = 0x50000; + } + ctu_target_bits = (ctu_target_bits_mul_16 * mb_wd32) >> 4; + negative_bits_thd = 0 - 5 * ctu_target_bits / 16; + positive_bits_thd = 5 * ctu_target_bits / 16; + + reg_frm->common.enc_pic.pic_qp = rc_cfg->quality_target; + reg_frm->synt_sli1.sli_qp = rc_cfg->quality_target; + reg_frm->common.rc_cfg.rc_en = 1; + reg_frm->common.rc_cfg.aq_en = 1; + reg_frm->common.rc_cfg.rc_ctu_num = mb_wd32; + + reg_frm->common.rc_qp.rc_max_qp = rc_cfg->quality_max; + reg_frm->common.rc_qp.rc_min_qp = rc_cfg->quality_min; + reg_frm->common.rc_tgt.ctu_ebit = ctu_target_bits_mul_16; + + if (ctx->smart_en || ctx->sp_enc_en) { + reg_frm->common.rc_qp.rc_qp_range = 0; + } else { + reg_frm->common.rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? + hw->qp_delta_row_i : hw->qp_delta_row; + } + + { + /* fixed frame qp */ + RK_S32 fqp_min, fqp_max; + + if (ctx->frame_type == INTRA_FRAME) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 0) && (fqp_max <= 51)) { + reg_frm->common.enc_pic.pic_qp = fqp_min; + reg_frm->synt_sli1.sli_qp = fqp_min; + reg_frm->common.rc_qp.rc_qp_range = 0; + } + } + + reg_rc->rc_dthd_0_8[0] = 2 * negative_bits_thd; + reg_rc->rc_dthd_0_8[1] = negative_bits_thd; + reg_rc->rc_dthd_0_8[2] = positive_bits_thd; + reg_rc->rc_dthd_0_8[3] = 2 * positive_bits_thd; + reg_rc->rc_dthd_0_8[4] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[5] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[6] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[7] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[8] = 0x7FFFFFFF; + + reg_rc->rc_adj0.qp_adj0 = -2; + reg_rc->rc_adj0.qp_adj1 = -1; + reg_rc->rc_adj0.qp_adj2 = 0; + reg_rc->rc_adj0.qp_adj3 = 1; + reg_rc->rc_adj0.qp_adj4 = 2; + reg_rc->rc_adj1.qp_adj5 = 0; + reg_rc->rc_adj1.qp_adj6 = 0; + reg_rc->rc_adj1.qp_adj7 = 0; + reg_rc->rc_adj1.qp_adj8 = 0; + } + + reg_rc->roi_qthd0.qpmin_area0 = h265->qpmin_map[0] > 0 ? h265->qpmin_map[0] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area0 = h265->qpmax_map[0] > 0 ? h265->qpmax_map[0] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area1 = h265->qpmin_map[1] > 0 ? h265->qpmin_map[1] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area1 = h265->qpmax_map[1] > 0 ? h265->qpmax_map[1] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area2 = h265->qpmin_map[2] > 0 ? h265->qpmin_map[2] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area2 = h265->qpmax_map[2] > 0 ? h265->qpmax_map[2] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area3 = h265->qpmin_map[3] > 0 ? h265->qpmin_map[3] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area3 = h265->qpmax_map[3] > 0 ? h265->qpmax_map[3] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area4 = h265->qpmin_map[4] > 0 ? h265->qpmin_map[4] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area4 = h265->qpmax_map[4] > 0 ? h265->qpmax_map[4] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area5 = h265->qpmin_map[5] > 0 ? h265->qpmin_map[5] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area5 = h265->qpmax_map[5] > 0 ? h265->qpmax_map[5] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area6 = h265->qpmin_map[6] > 0 ? h265->qpmin_map[6] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area6 = h265->qpmax_map[6] > 0 ? h265->qpmax_map[6] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area7 = h265->qpmin_map[7] > 0 ? h265->qpmin_map[7] : rc_cfg->quality_min; + reg_rc->roi_qthd3.qpmax_area7 = h265->qpmax_map[7] > 0 ? h265->qpmax_map[7] : rc_cfg->quality_max; + reg_rc->roi_qthd3.qpmap_mode = h265->qpmap_mode; + + return MPP_OK; +} + +static MPP_RET vepu510_h265_set_pp_regs(H265eV510RegSet *regs, VepuFmtCfg *fmt, MppEncPrepCfg *prep_cfg) +{ + Vepu510ControlCfg *reg_ctl = ®s->reg_ctl; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 stridey = 0; + RK_S32 stridec = 0; + + reg_ctl->dtrns_map.src_bus_edin = fmt->src_endian; + reg_frm->common.src_fmt.src_cfmt = fmt->format; + reg_frm->common.src_fmt.alpha_swap = fmt->alpha_swap; + reg_frm->common.src_fmt.rbuv_swap = fmt->rbuv_swap; + reg_frm->common.src_fmt.out_fmt = (fmt->format == VEPU5xx_FMT_YUV400) ? 0 : 1; + reg_frm->common.src_proc.src_mirr = prep_cfg->mirroring > 0; + reg_frm->common.src_proc.src_rot = prep_cfg->rotation; + reg_frm->common.src_proc.tile4x4_en = 0; + + if (prep_cfg->hor_stride) { + if (MPP_FRAME_FMT_IS_TILE(prep_cfg->format)) { + reg_frm->common.src_proc.tile4x4_en = 1; + + switch (prep_cfg->format & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV400: + stridey = prep_cfg->hor_stride * 4; + break; + case MPP_FMT_YUV420P: + case MPP_FMT_YUV420SP: + stridey = prep_cfg->hor_stride * 4 * 3 / 2; + break; + case MPP_FMT_YUV422P: + case MPP_FMT_YUV422SP: + stridey = prep_cfg->hor_stride * 4 * 2; + break; + case MPP_FMT_YUV444P: + case MPP_FMT_YUV444SP: + stridey = prep_cfg->hor_stride * 4 * 3; + break; + default: + mpp_err("Unsupported input format 0x%08x, with TILE mask.\n", fmt); + return MPP_ERR_VALUE; + break; + } + } else { + stridey = prep_cfg->hor_stride; + } + } else { + if (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_BGRA8888) + stridey = prep_cfg->width * 4; + else if (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_BGR888) + stridey = prep_cfg->width * 3; + else if (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_BGR565 || + reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_YUYV422 || + reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_UYVY422) + stridey = prep_cfg->width * 2; + } + + stridec = (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_YUV420SP || + reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_YUV422SP || + reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_YUV444P) ? + stridey : stridey / 2; + + if (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_YUV444SP) + stridec = stridey * 2; + + if (reg_frm->common.src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = cfg_coeffs = get_rgb2yuv_cfg(prep_cfg->range, prep_cfg->color); + + hal_h265e_dbg_simple("input color range %d colorspace %d", prep_cfg->range, prep_cfg->color); + + reg_frm->common.src_udfy.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + reg_frm->common.src_udfy.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + reg_frm->common.src_udfy.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + + reg_frm->common.src_udfu.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + reg_frm->common.src_udfu.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + reg_frm->common.src_udfu.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + + reg_frm->common.src_udfv.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + reg_frm->common.src_udfv.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + reg_frm->common.src_udfv.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + + reg_frm->common.src_udfo.csc_ofst_y = cfg_coeffs->_2y.offset; + reg_frm->common.src_udfo.csc_ofst_u = cfg_coeffs->_2u.offset; + reg_frm->common.src_udfo.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h265e_dbg_simple("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } + + reg_frm->common.src_strd0.src_strd0 = stridey; + reg_frm->common.src_strd1.src_strd1 = stridec; + + return MPP_OK; +} + +static void vepu510_h265_set_slice_regs(H265eSyntax_new *syn, H265eVepu510Frame *regs) +{ + regs->synt_sps.smpl_adpt_ofst_e = syn->pp.sample_adaptive_offset_enabled_flag; + regs->synt_sps.num_st_ref_pic = syn->pp.num_short_term_ref_pic_sets; + regs->synt_sps.num_lt_ref_pic = syn->pp.num_long_term_ref_pics_sps; + regs->synt_sps.lt_ref_pic_prsnt = syn->pp.long_term_ref_pics_present_flag; + regs->synt_sps.tmpl_mvp_e = syn->pp.sps_temporal_mvp_enabled_flag; + regs->synt_sps.log2_max_poc_lsb = syn->pp.log2_max_pic_order_cnt_lsb_minus4; + regs->synt_sps.strg_intra_smth = syn->pp.strong_intra_smoothing_enabled_flag; + + regs->synt_pps.dpdnt_sli_seg_en = syn->pp.dependent_slice_segments_enabled_flag; + regs->synt_pps.out_flg_prsnt_flg = syn->pp.output_flag_present_flag; + regs->synt_pps.num_extr_sli_hdr = syn->pp.num_extra_slice_header_bits; + regs->synt_pps.sgn_dat_hid_en = syn->pp.sign_data_hiding_enabled_flag; + regs->synt_pps.cbc_init_prsnt_flg = syn->pp.cabac_init_present_flag; + regs->synt_pps.pic_init_qp = syn->pp.init_qp_minus26 + 26; + regs->synt_pps.cu_qp_dlt_en = syn->pp.cu_qp_delta_enabled_flag; + regs->synt_pps.chrm_qp_ofst_prsn = syn->pp.pps_slice_chroma_qp_offsets_present_flag; + regs->synt_pps.lp_fltr_acrs_sli = syn->pp.pps_loop_filter_across_slices_enabled_flag; + regs->synt_pps.dblk_fltr_ovrd_en = syn->pp.deblocking_filter_override_enabled_flag; + regs->synt_pps.lst_mdfy_prsnt_flg = syn->pp.lists_modification_present_flag; + regs->synt_pps.sli_seg_hdr_extn = syn->pp.slice_segment_header_extension_present_flag; + regs->synt_pps.cu_qp_dlt_depth = syn->pp.diff_cu_qp_delta_depth; + regs->synt_pps.lpf_fltr_acrs_til = syn->pp.loop_filter_across_tiles_enabled_flag; + regs->synt_pps.csip_flag = syn->pp.constrained_intra_pred_flag; + + regs->synt_sli0.cbc_init_flg = syn->sp.cbc_init_flg; + regs->synt_sli0.mvd_l1_zero_flg = syn->sp.mvd_l1_zero_flg; + regs->synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + regs->synt_sli0.num_refidx_l1_act = syn->sp.num_refidx_l1_act; + regs->synt_sli0.num_refidx_l0_act = syn->sp.num_refidx_l0_act; + + regs->synt_sli0.num_refidx_act_ovrd = syn->sp.num_refidx_act_ovrd; + + regs->synt_sli0.sli_sao_chrm_flg = syn->sp.sli_sao_chrm_flg; + regs->synt_sli0.sli_sao_luma_flg = syn->sp.sli_sao_luma_flg; + regs->synt_sli0.sli_tmprl_mvp_e = syn->sp.sli_tmprl_mvp_en; + regs->common.enc_pic.num_pic_tot_cur_hevc = syn->sp.tot_poc_num; + + regs->synt_sli0.pic_out_flg = syn->sp.pic_out_flg; + regs->synt_sli0.sli_type = syn->sp.slice_type; + regs->synt_sli0.sli_rsrv_flg = syn->sp.slice_rsrv_flg; + regs->synt_sli0.dpdnt_sli_seg_flg = syn->sp.dpdnt_sli_seg_flg; + regs->synt_sli0.sli_pps_id = syn->sp.sli_pps_id; + regs->synt_sli0.no_out_pri_pic = syn->sp.no_out_pri_pic; + + regs->synt_sli1.sp_tc_ofst_div2 = syn->sp.sli_tc_ofst_div2;; + regs->synt_sli1.sp_beta_ofst_div2 = syn->sp.sli_beta_ofst_div2; + regs->synt_sli1.sli_lp_fltr_acrs_sli = syn->sp.sli_lp_fltr_acrs_sli; + regs->synt_sli1.sp_dblk_fltr_dis = syn->sp.sli_dblk_fltr_dis; + regs->synt_sli1.dblk_fltr_ovrd_flg = syn->sp.dblk_fltr_ovrd_flg; + regs->synt_sli1.sli_cb_qp_ofst = syn->sp.sli_cb_qp_ofst; + regs->synt_sli1.max_mrg_cnd = 3;//syn->sp.max_mrg_cnd; + + regs->synt_sli1.col_ref_idx = syn->sp.col_ref_idx; + regs->synt_sli1.col_frm_l0_flg = syn->sp.col_frm_l0_flg; + regs->synt_sli2.sli_poc_lsb = syn->sp.sli_poc_lsb; + regs->synt_sli2.sli_hdr_ext_len = syn->sp.sli_hdr_ext_len; +} + +static void vepu510_h265_set_ref_regs(H265eSyntax_new *syn, H265eVepu510Frame *regs) +{ + regs->synt_refm0.st_ref_pic_flg = syn->sp.st_ref_pic_flg; + regs->synt_refm0.poc_lsb_lt0 = syn->sp.poc_lsb_lt0; + regs->synt_refm0.num_lt_pic = syn->sp.num_lt_pic; + + regs->synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->synt_refm1.used_by_lt_flg0 = syn->sp.used_by_lt_flg0; + regs->synt_refm1.used_by_lt_flg1 = syn->sp.used_by_lt_flg1; + regs->synt_refm1.used_by_lt_flg2 = syn->sp.used_by_lt_flg2; + regs->synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->synt_refm1.dlt_poc_msb_prsnt1 = syn->sp.dlt_poc_msb_prsnt1; + regs->synt_refm1.num_negative_pics = syn->sp.num_neg_pic; + regs->synt_refm1.num_pos_pic = syn->sp.num_pos_pic; + + regs->synt_refm1.used_by_s0_flg = syn->sp.used_by_s0_flg; + regs->synt_refm2.dlt_poc_s0_m10 = syn->sp.dlt_poc_s0_m10; + regs->synt_refm2.dlt_poc_s0_m11 = syn->sp.dlt_poc_s0_m11; + regs->synt_refm3.dlt_poc_s0_m12 = syn->sp.dlt_poc_s0_m12; + regs->synt_refm3.dlt_poc_s0_m13 = syn->sp.dlt_poc_s0_m13; + + regs->synt_long_refm0.poc_lsb_lt1 = syn->sp.poc_lsb_lt1; + regs->synt_long_refm1.dlt_poc_msb_cycl1 = syn->sp.dlt_poc_msb_cycl1; + regs->synt_long_refm0.poc_lsb_lt2 = syn->sp.poc_lsb_lt2; + regs->synt_refm1.dlt_poc_msb_prsnt2 = syn->sp.dlt_poc_msb_prsnt2; + regs->synt_long_refm1.dlt_poc_msb_cycl2 = syn->sp.dlt_poc_msb_cycl2; + regs->synt_sli1.lst_entry_l0 = syn->sp.lst_entry_l0; + regs->synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; +} + +static void vepu510_h265_set_me_regs(H265eV510HalContext *ctx, H265eSyntax_new *syn, H265eVepu510Frame *regs) +{ + regs->common.me_rnge.cime_srch_dwnh = 15; + regs->common.me_rnge.cime_srch_uph = 15; + regs->common.me_rnge.cime_srch_rgtw = 12; + regs->common.me_rnge.cime_srch_lftw = 12; + regs->common.me_cfg.rme_srch_h = 3; + regs->common.me_cfg.rme_srch_v = 3; + + regs->common.me_cfg.srgn_max_num = 54; + regs->common.me_cfg.cime_dist_thre = 1024; + regs->common.me_cfg.rme_dis = 0; + regs->common.me_cfg.fme_dis = 0; + regs->common.me_rnge.dlt_frm_num = 0x1; + + if (syn->pp.sps_temporal_mvp_enabled_flag && + (ctx->frame_type != INTRA_FRAME)) { + if (ctx->last_frame_type == INTRA_FRAME) { + regs->common.me_cach.colmv_load_hevc = 0; + } else { + regs->common.me_cach.colmv_load_hevc = 1; + } + regs->common.me_cach.colmv_stor_hevc = 1; + } + + regs->common.me_cach.cime_zero_thre = (ctx->cfg->tune.scene_mode == + MPP_ENC_SCENE_MODE_IPC) ? 1024 : 64; + regs->common.me_cach.fme_prefsu_en = 0; +} + +void vepu510_h265_set_hw_address(H265eV510HalContext *ctx, H265eVepu510Frame *regs, HalEncTask *task) +{ + HalEncTask *enc_task = task; + HalBuf *recon_buf, *ref_buf; + MppBuffer md_info_buf = enc_task->md_info; + Vepu510H265eFrmCfg *frm = ctx->frm; + H265eSyntax_new *syn = ctx->syn; + + hal_h265e_enter(); + + regs->common.adr_src0 = mpp_buffer_get_fd(enc_task->input); + regs->common.adr_src1 = regs->common.adr_src0; + regs->common.adr_src2 = regs->common.adr_src0; + + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_curr_idx); + ref_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_refr_idx); + + if (!syn->sp.non_reference_flag) { + regs->common.rfpw_h_addr = mpp_buffer_get_fd(recon_buf->buf[0]); + regs->common.rfpw_b_addr = regs->common.rfpw_h_addr; + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, ctx->fbc_header_len); + } + regs->common.rfpr_h_addr = mpp_buffer_get_fd(ref_buf->buf[0]); + regs->common.rfpr_b_addr = regs->common.rfpr_h_addr; + regs->common.colmvw_addr = mpp_buffer_get_fd(recon_buf->buf[2]); + regs->common.colmvr_addr = mpp_buffer_get_fd(ref_buf->buf[2]); + regs->common.dspw_addr = mpp_buffer_get_fd(recon_buf->buf[1]); + regs->common.dspr_addr = mpp_buffer_get_fd(ref_buf->buf[1]); + + mpp_dev_multi_offset_update(ctx->reg_cfg, 166, ctx->fbc_header_len); + + if (md_info_buf) { + regs->common.enc_pic.mei_stor = 1; + regs->common.meiw_addr = mpp_buffer_get_fd(md_info_buf); + } else { + regs->common.enc_pic.mei_stor = 0; + regs->common.meiw_addr = 0; + } + + regs->common.bsbt_addr = mpp_buffer_get_fd(enc_task->output); + /* TODO: stream size relative with syntax */ + regs->common.bsbb_addr = regs->common.bsbt_addr; + regs->common.bsbr_addr = regs->common.bsbt_addr; + regs->common.adr_bsbs = regs->common.bsbt_addr; + + regs->common.rfpt_h_addr = 0xffffffff; + regs->common.rfpb_h_addr = 0; + regs->common.rfpt_b_addr = 0xffffffff; + regs->common.adr_rfpb_b = 0; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 174, mpp_packet_get_length(task->packet)); + mpp_dev_multi_offset_update(ctx->reg_cfg, 172, mpp_buffer_get_size(enc_task->output)); + + regs->common.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->common.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + /* smear bufs */ + regs->common.adr_smear_rd = mpp_buffer_get_fd(ref_buf->buf[3]); + regs->common.adr_smear_wr = mpp_buffer_get_fd(recon_buf->buf[3]); +} + +static MPP_RET vepu510_h265e_save_pass1_patch(H265eV510RegSet *regs, H265eV510HalContext *ctx, + RK_S32 tiles_enabled_flag) +{ + H265eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 width = ctx->cfg->prep.width; + RK_S32 height = ctx->cfg->prep.height; + RK_S32 width_align = MPP_ALIGN(width, 16); + RK_S32 height_align = MPP_ALIGN(height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + reg_frm->common.enc_pic.cur_frm_ref = 1; + reg_frm->common.rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + reg_frm->common.rfpw_b_addr = reg_frm->common.rfpw_h_addr; + reg_frm->common.enc_pic.rec_fbc_dis = 1; + + if (tiles_enabled_flag) + reg_frm->synt_pps.lpf_fltr_acrs_til = 0; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, 0); + + /* NOTE: disable split to avoid lowdelay slice output */ + reg_frm->common.sli_splt.sli_splt = 0; + reg_frm->common.enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu510_h265e_use_pass1_patch(H265eV510RegSet *regs, H265eV510HalContext *ctx) +{ + Vepu510ControlCfg *reg_ctl = ®s->reg_ctl; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + RK_U32 hor_stride = MPP_ALIGN(ctx->cfg->prep.width, 16); + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + MPP_RET ret = MPP_OK; + + hal_h265e_dbg_func("enter\n"); + + reg_ctl->dtrns_map.src_bus_edin = fmt->src_endian; + reg_frm->common.src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + reg_frm->common.src_fmt.alpha_swap = 0; + reg_frm->common.src_fmt.rbuv_swap = 0; + reg_frm->common.src_fmt.out_fmt = 1; + reg_frm->common.src_fmt.src_rcne = 1; + + reg_frm->common.src_strd0.src_strd0 = hor_stride; + reg_frm->common.src_strd1.src_strd1 = 3 * hor_stride; + + reg_frm->common.src_proc.src_mirr = 0; + reg_frm->common.src_proc.src_rot = 0; + + reg_frm->common.adr_src0 = mpp_buffer_get_fd(ctx->buf_pass1); + reg_frm->common.adr_src1 = reg_frm->common.adr_src0; + reg_frm->common.adr_src2 = 0; + + /* input cb addr */ + ret = mpp_dev_multi_offset_update(ctx->reg_cfg, 161, 2 * hor_stride); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); + + return MPP_OK; +} + +static void setup_vepu510_ext_line_buf(H265eV510HalContext *ctx, H265eV510RegSet *regs) +{ + MppDevRcbInfoCfg rcb_cfg; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 offset = 0; + RK_S32 fd; + + if (ctx->ext_line_buf) { + fd = mpp_buffer_get_fd(ctx->ext_line_buf); + offset = ctx->ext_line_buf_size; + + reg_frm->common.ebufb_addr = fd; + reg_frm->common.ebuft_addr = fd; + mpp_dev_multi_offset_update(ctx->reg_cfg, 178, ctx->ext_line_buf_size); + } else { + reg_frm->common.ebufb_addr = 0; + reg_frm->common.ebuft_addr = 0; + } + + /* rcb info for sram */ + rcb_cfg.reg_idx = 179; + rcb_cfg.size = offset; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); + + rcb_cfg.reg_idx = 178; + rcb_cfg.size = 0; + + mpp_dev_ioctl(ctx->dev, MPP_DEV_RCB_INFO, &rcb_cfg); +} + +static MPP_RET setup_vepu510_dual_core(H265eV510HalContext *ctx, RK_S32 curr_slot, RK_S32 refr_slot) +{ + Vepu510H265eFrmCfg *frm = ctx->frm; + H265eV510RegSet *regs = frm->regs_set; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + RK_U32 dchs_ofst = 9; + RK_U32 dchs_dly = 0; + RK_U32 dchs_rxe = 1; + RK_U32 dchs_txe = 1; + RK_U32 rxid = 0; + + if (ctx->task_cnt == 1) + return MPP_OK; + + if (curr_slot < 0 || curr_slot >= MAX_REFS || refr_slot < 0 || refr_slot >= MAX_REFS) { + mpp_loge_f("dual core setup failed! invalid frame slot index. curr_slot:%d, refr_slot:%d", + curr_slot, refr_slot); + return MPP_ERR_UNKNOW; + } + + if (ctx->frame_type == INTRA_FRAME) { + ctx->curr_idx = 0; + ctx->prev_idx = 0; + dchs_rxe = 0; + rxid = 0; + } else { + rxid = ctx->slot_to_dchs_txid[refr_slot]; + } + + if (!reg_frm->common.enc_pic.cur_frm_ref) + dchs_txe = 0; + + ctx->slot_to_dchs_txid[curr_slot] = ctx->curr_idx; + + reg_frm->common.dual_core.dchs_txid = ctx->curr_idx; + reg_frm->common.dual_core.dchs_rxid = rxid; + reg_frm->common.dual_core.dchs_txe = dchs_txe; + reg_frm->common.dual_core.dchs_rxe = dchs_rxe; + reg_frm->common.dual_core.dchs_ofst = dchs_ofst; + reg_frm->common.dual_core.dchs_dly = dchs_dly; + + ctx->prev_idx = ctx->curr_idx++; + if (ctx->curr_idx > 3) + ctx->curr_idx = 0; + + return MPP_OK; +} + +static void setup_vepu510_split(H265eV510RegSet *regs, MppEncCfgSet *enc_cfg, RK_U32 title_en) +{ + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h265e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_frm.common.sli_splt.sli_splt = 0; + regs->reg_frm.common.sli_splt.sli_splt_mode = 0; + regs->reg_frm.common.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.common.sli_splt.sli_max_num_m1 = 0; + regs->reg_frm.common.sli_splt.sli_flsh = 0; + regs->reg_frm.common.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.common.sli_byte.sli_splt_byte = 0; + regs->reg_frm.common.enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_frm.common.sli_splt.sli_splt = 1; + regs->reg_frm.common.sli_splt.sli_splt_mode = 0; + regs->reg_frm.common.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.common.sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.common.sli_splt.sli_flsh = 1; + regs->reg_frm.common.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.common.sli_byte.sli_splt_byte = cfg->split_arg; + regs->reg_frm.common.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = regs->reg_frm.common.enc_pic.slen_fifo ; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + RK_U32 mb_w = MPP_ALIGN(enc_cfg->prep.width, 32) / 32; + RK_U32 mb_h = MPP_ALIGN(enc_cfg->prep.height, 32) / 32; + RK_U32 slice_num = 0; + + if (title_en) + mb_w = mb_w / 2; + + slice_num = (mb_w * mb_h + cfg->split_arg - 1) / cfg->split_arg; + + regs->reg_frm.common.sli_splt.sli_splt = 1; + regs->reg_frm.common.sli_splt.sli_splt_mode = 1; + regs->reg_frm.common.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.common.sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.common.sli_splt.sli_flsh = 1; + regs->reg_frm.common.sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg_frm.common.sli_byte.sli_splt_byte = 0; + regs->reg_frm.common.enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + if ((cfg->split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) || + (regs->reg_frm.common.enc_pic.slen_fifo && (slice_num > VEPU510_SLICE_FIFO_LEN))) + regs->reg_ctl.int_en.vslc_done_en = 1; + + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu510_h265_set_scaling_list(H265eV510HalContext *ctx) +{ + Vepu510H265eFrmCfg *frm_cfg = ctx->frm; + H265eV510RegSet *regs = frm_cfg->regs_set; + Vepu510SclCfg *s = ®s->reg_scl; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U32 scl_lst_sel = regs->reg_frm.rdo_cfg.scl_lst_sel; + RK_U8 idx; + + hal_h265e_dbg_func("enter\n"); + + if (scl_lst_sel == 1) { + for (idx = 0; idx < 64; idx++) { + /* TU8 intra Y/U/V */ + p[idx + 64 * 0] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 1] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 2] = vepu510_h265_cqm_intra8[63 - idx]; + + /* TU8 inter Y/U/V */ + p[idx + 64 * 3] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 4] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 5] = vepu510_h265_cqm_inter8[63 - idx]; + + /* TU16 intra Y/U/V AC */ + p[idx + 64 * 6] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 7] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 8] = vepu510_h265_cqm_intra8[63 - idx]; + + /* TU16 inter Y/U/V AC */ + p[idx + 64 * 9] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 10] = vepu510_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 11] = vepu510_h265_cqm_inter8[63 - idx]; + + /* TU32 intra/inter Y AC */ + p[idx + 64 * 12] = vepu510_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 13] = vepu510_h265_cqm_inter8[63 - idx]; + } + + s->tu_dc0.tu16_intra_y_dc = 16; + s->tu_dc0.tu16_intra_u_dc = 16; + s->tu_dc0.tu16_intra_v_dc = 16; + s->tu_dc0.tu16_inter_y_dc = 16; + s->tu_dc1.tu16_inter_u_dc = 16; + s->tu_dc1.tu16_inter_v_dc = 16; + s->tu_dc1.tu32_intra_y_dc = 16; + s->tu_dc1.tu32_inter_y_dc = 16; + } else if (scl_lst_sel == 2) { + //TODO: Update scaling list for (scaling_list_mode == 2) + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h265e_dbg_func("leave\n"); +} + +MPP_RET hal_h265e_v510_gen_regs(void *hal, HalEncTask *task) +{ + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + HalEncTask *enc_task = task; + EncRcTask *rc_task = enc_task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + H265eSyntax_new *syn = ctx->syn; + Vepu510H265eFrmCfg *frm_cfg = ctx->frm; + H265eV510RegSet *regs = frm_cfg->regs_set; + RK_U32 pic_width_align8, pic_height_align8; + RK_S32 pic_wd32, pic_h32; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + Vepu510ControlCfg *reg_ctl = ®s->reg_ctl; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + Vepu510RcRoi *reg_klut = ®s->reg_rc_roi; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + MPP_RET ret = MPP_OK; + + hal_h265e_enter(); + pic_width_align8 = (syn->pp.pic_width + 7) & (~7); + pic_height_align8 = (syn->pp.pic_height + 7) & (~7); + pic_wd32 = (syn->pp.pic_width + 31) / 32; + pic_h32 = (syn->pp.pic_height + 31) / 32; + + hal_h265e_dbg_simple("frame %d | type %d | start gen regs", + ctx->frame_count, ctx->frame_type); + vepu510_h265e_tune_aq_prepare(ctx->tune); + memset(regs, 0, sizeof(H265eV510RegSet)); + + reg_ctl->enc_strt.lkt_num = 0; + reg_ctl->enc_strt.vepu_cmd = ctx->enc_mode; + reg_ctl->enc_clr.safe_clr = 0x0; + reg_ctl->enc_clr.force_clr = 0x0; + + reg_ctl->int_en.enc_done_en = 1; + reg_ctl->int_en.lkt_node_done_en = 1; + reg_ctl->int_en.sclr_done_en = 1; + reg_ctl->int_en.vslc_done_en = 0; + reg_ctl->int_en.vbsf_oflw_en = 1; + reg_ctl->int_en.vbuf_lens_en = 1; + reg_ctl->int_en.enc_err_en = 1; + reg_ctl->int_en.vsrc_err_en = 1; + reg_ctl->int_en.wdg_en = 1; + reg_ctl->int_en.lkt_err_int_en = 0; + reg_ctl->int_en.lkt_err_stop_en = 1; + reg_ctl->int_en.lkt_force_stop_en = 1; + reg_ctl->int_en.jslc_done_en = 1; + reg_ctl->int_en.jbsf_oflw_en = 1; + reg_ctl->int_en.jbuf_lens_en = 1; + reg_ctl->int_en.dvbm_err_en = 0; + + reg_ctl->dtrns_map.jpeg_bus_edin = 0x0; + reg_ctl->dtrns_map.src_bus_edin = 0x0; + reg_ctl->dtrns_map.meiw_bus_edin = 0x0; + reg_ctl->dtrns_map.bsw_bus_edin = 0x7; + reg_ctl->dtrns_map.lktw_bus_edin = 0x0; + reg_ctl->dtrns_map.rec_nfbc_bus_edin = 0x0; + + reg_ctl->dtrns_cfg.axi_brsp_cke = 0x0; + reg_ctl->enc_wdg.vs_load_thd = 0; + + reg_ctl->opt_strg.cke = 1; + reg_ctl->opt_strg.resetn_hw_en = 1; + reg_ctl->opt_strg.rfpr_err_e = 1; + + reg_frm->common.enc_rsl.pic_wd8_m1 = pic_width_align8 / 8 - 1; + reg_frm->common.src_fill.pic_wfill = ((syn->pp.pic_width & 0x7) != 0) + ? (8 - (syn->pp.pic_width & 0x7)) : 0; + reg_frm->common.enc_rsl.pic_hd8_m1 = pic_height_align8 / 8 - 1; + reg_frm->common.src_fill.pic_hfill = ((syn->pp.pic_height & 0x7) != 0) + ? (8 - (syn->pp.pic_height & 0x7)) : 0; + + reg_frm->common.enc_pic.enc_stnd = 1; //H265 + reg_frm->common.enc_pic.cur_frm_ref = !syn->sp.non_reference_flag; //current frame will be refered + reg_frm->common.enc_pic.bs_scp = 1; + reg_frm->common.enc_pic.log2_ctu_num_hevc = mpp_ceil_log2(pic_wd32 * pic_h32); + + reg_frm->common.src_proc.src_mirr = 0; + reg_frm->common.src_proc.src_rot = 0; + reg_frm->common.src_proc.tile4x4_en = 0; + + reg_klut->klut_ofst.chrm_klut_ofst = (ctx->frame_type == INTRA_FRAME) ? 6 : + (sm == MPP_ENC_SCENE_MODE_IPC ? 9 : 6); + + reg_frm->sao_cfg.sao_lambda_multi = 5; + + setup_vepu510_split(regs, ctx->cfg, syn->pp.tiles_enabled_flag); + + if (ctx->task_cnt > 1) + setup_vepu510_dual_core(ctx, task->flags.curr_idx, task->flags.refr_idx); + + vepu510_h265_set_me_regs(ctx, syn, reg_frm); + + reg_frm->rdo_cfg.chrm_spcl = 0; + reg_frm->rdo_cfg.cu_inter_e = 0xdb; + reg_frm->rdo_cfg.lambda_qp_use_avg_cu16_flag = (sm == MPP_ENC_SCENE_MODE_IPC); + reg_frm->rdo_cfg.yuvskip_calc_en = 1; + reg_frm->rdo_cfg.atf_e = (sm == MPP_ENC_SCENE_MODE_IPC); + reg_frm->rdo_cfg.atr_e = 1; + + if (syn->pp.num_long_term_ref_pics_sps) { + reg_frm->rdo_cfg.ltm_col = 0; + reg_frm->rdo_cfg.ltm_idx0l0 = 1; + } else { + reg_frm->rdo_cfg.ltm_col = 0; + reg_frm->rdo_cfg.ltm_idx0l0 = 0; + } + + reg_frm->rdo_cfg.ccwa_e = 1; + reg_frm->rdo_cfg.scl_lst_sel = syn->pp.scaling_list_enabled_flag; + reg_frm->synt_nal.nal_unit_type = h265e_get_nal_type(&syn->sp, ctx->frame_type); + + vepu510_h265_set_scaling_list(ctx); + vepu510_h265_set_hw_address(ctx, reg_frm, task); + vepu510_h265_set_pp_regs(regs, fmt, &ctx->cfg->prep); + vepu510_h265_set_rc_regs(ctx, regs, task); + vepu510_h265_set_slice_regs(syn, reg_frm); + vepu510_h265_set_ref_regs(syn, reg_frm); + ret = vepu510_h265_set_patch_info(syn, (VepuFmt)fmt->format, ctx->reg_cfg, enc_task); + if (ret) + return ret; + + setup_vepu510_ext_line_buf(ctx, regs); + + /* ROI configure */ + if (ctx->roi_data) + vepu510_set_roi(®s->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + /*paramet cfg*/ + vepu510_h265_global_cfg_set(ctx, regs); + vepu510_h265e_tune_reg_patch(ctx->tune, task); + + /* two pass register patch */ + if (frm->save_pass1) + vepu510_h265e_save_pass1_patch(regs, ctx, syn->pp.tiles_enabled_flag); + + if (frm->use_pass1) + vepu510_h265e_use_pass1_patch(regs, ctx); + + + ctx->frame_num++; + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v510_start(void *hal, HalEncTask *enc_task) +{ + MPP_RET ret = MPP_OK; + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + Vepu510H265eFrmCfg *frm = ctx->frm; + RK_U32 *regs = (RK_U32*)frm->regs_set; + H265eV510RegSet *hw_regs = frm->regs_set; + H265eV510StatusElem *reg_out = (H265eV510StatusElem *)frm->regs_ret; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + RK_U32 i = 0; + + hal_h265e_enter(); + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + cfg.reg = (RK_U32*)&hw_regs->reg_ctl; + cfg.size = sizeof(Vepu510ControlCfg); + cfg.offset = VEPU510_CTL_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_CTL_REGS) { + regs = (RK_U32*)&hw_regs->reg_ctl; + for (i = 0; i < sizeof(Vepu510ControlCfg) / 4; i++) { + hal_h265e_dbg_ctl("ctl reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_frm; + cfg.size = sizeof(H265eVepu510Frame); + cfg.offset = VEPU510_FRAME_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_REGS) { + regs = (RK_U32*)(&hw_regs->reg_frm); + for (i = 0; i < 32; i++) { + hal_h265e_dbg_regs("hw add cfg reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + regs += 32; + for (i = 0; i < (sizeof(H265eVepu510Frame) - 128) / 4; i++) { + hal_h265e_dbg_regs("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + cfg.reg = &hw_regs->reg_rc_roi; + cfg.size = sizeof(Vepu510RcRoi); + cfg.offset = VEPU510_RC_ROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_RCKUT_REGS) { + regs = (RK_U32*)&hw_regs->reg_rc_roi; + for (i = 0; i < sizeof(Vepu510RcRoi) / 4; i++) { + hal_h265e_dbg_rckut("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_param; + cfg.size = sizeof(H265eVepu510Param); + cfg.offset = VEPU510_PARAM_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_param; + for (i = 0; i < sizeof(H265eVepu510Param) / 4; i++) { + hal_h265e_dbg_wgt("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_sqi; + cfg.size = sizeof(H265eVepu510Sqi); + cfg.offset = VEPU510_SQI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg.reg = &hw_regs->reg_scl; + cfg.size = sizeof(hw_regs->reg_scl); + cfg.offset = VEPU510_SCL_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->reg_cfg); + if (ret) { + mpp_err_f("set register offsets failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU510_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->st; + cfg1.size = sizeof(H265eV510StatusElem) - 4; + cfg1.offset = VEPU510_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + hal_h265e_leave(); + return ret; +} + +static MPP_RET vepu510_h265_set_feedback(H265eV510HalContext *ctx, HalEncTask *enc_task) +{ + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&enc_task->rc_task->info; + Vepu510H265eFrmCfg *frm = ctx->frms[enc_task->flags.reg_idx]; + Vepu510H265Fbk *fb = &frm->feedback; + MppEncCfgSet *cfg = ctx->cfg; + RK_S32 mb8_num = MPP_ALIGN(cfg->prep.width, 8) * MPP_ALIGN(cfg->prep.height, 8) / 64; + RK_S32 mb4_num = (mb8_num << 2); + H265eV510StatusElem *elem = (H265eV510StatusElem *)frm->regs_ret; + RK_U32 hw_status = elem->hw_status; + + hal_h265e_enter(); + + fb->qp_sum += elem->st.qp_sum; + fb->out_strm_size += elem->st.bs_lgth_l32; + fb->sse_sum += (RK_S64)(elem->st.sse_h32 << 16) + + (elem->st.st_sse_bsl.sse_l16 & 0xffff); + + fb->hw_status = hw_status; + hal_h265e_dbg_detail("hw_status: 0x%08x", hw_status); + if (hw_status & RKV_ENC_INT_LINKTABLE_FINISH) + hal_h265e_err("RKV_ENC_INT_LINKTABLE_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_FRAME_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_FRAME_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_SLICE_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_SLICE_FINISH"); + + if (hw_status & RKV_ENC_INT_SAFE_CLEAR_FINISH) + hal_h265e_err("RKV_ENC_INT_SAFE_CLEAR_FINISH"); + + if (hw_status & RKV_ENC_INT_BIT_STREAM_OVERFLOW) + hal_h265e_err("RKV_ENC_INT_BIT_STREAM_OVERFLOW"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_FULL) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_FULL"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_ERROR"); + + if (hw_status & RKV_ENC_INT_BUS_READ_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_READ_ERROR"); + + if (hw_status & RKV_ENC_INT_TIMEOUT_ERROR) + hal_h265e_err("RKV_ENC_INT_TIMEOUT_ERROR"); + + fb->st_mb_num += elem->st.st_bnum_b16.num_b16; + + fb->st_lvl64_inter_num += elem->st.st_pnum_p64.pnum_p64; + fb->st_lvl32_inter_num += elem->st.st_pnum_p32.pnum_p32; + fb->st_lvl32_intra_num += elem->st.st_pnum_i32.pnum_i32; + fb->st_lvl16_inter_num += elem->st.st_pnum_p16.pnum_p16; + fb->st_lvl16_intra_num += elem->st.st_pnum_i16.pnum_i16; + fb->st_lvl8_inter_num += elem->st.st_pnum_p8.pnum_p8; + fb->st_lvl8_intra_num += elem->st.st_pnum_i8.pnum_i8; + fb->st_lvl4_intra_num += elem->st.st_pnum_i4.pnum_i4; + ctx->feedback.acc_cover16_num = elem->st.st_skin_sum1.acc_cover16_num; + ctx->feedback.acc_bndry16_num = elem->st.st_skin_sum2.acc_bndry16_num; + ctx->feedback.acc_zero_mv = elem->st.acc_zero_mv; + ctx->feedback.st_ctu_num = elem->st.st_bnum_b16.num_b16; + memcpy(&fb->st_cu_num_qp[0], &elem->st.st_b8_qp, 52 * sizeof(RK_U32)); + + if (mb4_num > 0) + hal_rc_ret->iblk4_prop = ((((fb->st_lvl4_intra_num + fb->st_lvl8_intra_num) << 2) + + (fb->st_lvl16_intra_num << 4) + + (fb->st_lvl32_intra_num << 6)) << 8) / mb4_num; + + if (mb8_num > 0) { + hal_rc_ret->quality_real = fb->qp_sum / mb8_num; + } + + hal_h265e_leave(); + return MPP_OK; +} + +static MPP_RET hal_h265e_vepu510_status_check(H265eV510RegSet *regs) +{ + MPP_RET ret = MPP_OK; + + if (regs->reg_ctl.int_sta.lkt_node_done_sta) + hal_h265e_dbg_detail("lkt_done finish"); + + if (regs->reg_ctl.int_sta.enc_done_sta) + hal_h265e_dbg_detail("enc_done finish"); + + if (regs->reg_ctl.int_sta.vslc_done_sta) + hal_h265e_dbg_detail("enc_slice finsh"); + + if (regs->reg_ctl.int_sta.sclr_done_sta) + hal_h265e_dbg_detail("safe clear finsh"); + + if (regs->reg_ctl.int_sta.vbsf_oflw_sta) { + mpp_err_f("bit stream overflow"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.vbuf_lens_sta) { + mpp_err_f("bus write full"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.enc_err_sta) { + mpp_err_f("bus error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wdg_sta) { + mpp_err_f("wdg timeout"); + ret = MPP_NOK; + } + + return ret; +} + +//#define DUMP_DATA +MPP_RET hal_h265e_v510_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + HalEncTask *enc_task = task; + MppPacket pkt = enc_task->packet; + RK_U32 split_out = ctx->cfg->split.split_out; + RK_S32 task_idx = task->flags.reg_idx; + Vepu510H265eFrmCfg *frm = ctx->frms[task_idx]; + H265eV510RegSet *regs = frm->regs_set; + RK_U32 offset = mpp_packet_get_length(pkt); + RK_U32 seg_offset = offset; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + RK_U32 type = reg_frm->synt_nal.nal_unit_type; + H265eV510StatusElem *elem = (H265eV510StatusElem *)frm->regs_ret; + + hal_h265e_enter(); + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (enc_task->rc_task->frm.save_pass1) + split_out = 0; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len = 0; + RK_U32 slice_last = 0; + MppDevPollCfg *poll_cfg = (MppDevPollCfg *)((char *)ctx->poll_cfgs); + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + RK_S32 i = 0; + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = split_out & MPP_ENC_SPLIT_OUT_LOWDELAY ? 1 : ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].vepu510.sli_lst; + slice_len = poll_cfg->slice_info[i].vepu510.sli_len; + param.length = slice_len; + + mpp_packet_add_segment_info(pkt, type, seg_offset, slice_len); + seg_offset += slice_len; + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) { + param.length = slice_len; + if (slice_last) + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + else + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + + mpp_callback(ctx->output_cb, ¶m); + } + } + } while (!slice_last); + + ret = hal_h265e_vepu510_status_check(regs); + if (!ret) + task->hw_length += elem->st.bs_lgth_l32; + + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + ret = hal_h265e_vepu510_status_check(regs); + if (!ret) + task->hw_length += elem->st.bs_lgth_l32; + } + mpp_packet_add_segment_info(pkt, type, offset, elem->st.bs_lgth_l32); + } + +#ifdef DUMP_DATA + static FILE *fp_fbd = NULL; + static FILE *fp_fbh = NULL; + static FILE *fp_dws = NULL; + HalBuf *recon_buf; + static RK_U32 frm_num = 0; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.recon_pic.slot_idx); + char file_name[20] = ""; + size_t rec_size = mpp_buffer_get_size(recon_buf->buf[0]); + size_t dws_size = mpp_buffer_get_size(recon_buf->buf[1]); + + void *ptr = mpp_buffer_get_ptr(recon_buf->buf[0]); + void *dws_ptr = mpp_buffer_get_ptr(recon_buf->buf[1]); + + sprintf(&file_name[0], "fbd%d.bin", frm_num); + if (fp_fbd != NULL) { + fclose(fp_fbd); + fp_fbd = NULL; + } else { + fp_fbd = fopen(file_name, "wb+"); + } + if (fp_fbd) { + fwrite(ptr + ctx->fbc_header_len, 1, rec_size - ctx->fbc_header_len, fp_fbd); + fflush(fp_fbd); + } + + sprintf(&file_name[0], "fbh%d.bin", frm_num); + + if (fp_fbh != NULL) { + fclose(fp_fbh); + fp_fbh = NULL; + } else { + fp_fbh = fopen(file_name, "wb+"); + } + + if (fp_fbh) { + fwrite(ptr , 1, ctx->fbc_header_len, fp_fbh); + fflush(fp_fbh); + } + + sprintf(&file_name[0], "dws%d.bin", frm_num); + + if (fp_dws != NULL) { + fclose(fp_dws); + fp_dws = NULL; + } else { + fp_dws = fopen(file_name, "wb+"); + } + + if (fp_dws) { + fwrite(dws_ptr , 1, dws_size, fp_dws); + fflush(fp_dws); + } + frm_num++; +#endif + if (ret) + mpp_err_f("poll cmd failed %d status %d \n", ret, elem->hw_status); + + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_v510_get_task(void *hal, HalEncTask *task) +{ + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + Vepu510H265eFrmCfg *frm_cfg = NULL; + MppFrame frame = task->frame; + EncFrmStatus *frm_status = &task->rc_task->frm; + RK_S32 task_idx = ctx->task_idx; + + hal_h265e_enter(); + + ctx->syn = (H265eSyntax_new *)task->syntax.data; + ctx->dpb = (H265eDpb*)ctx->syn->dpb; + ctx->smart_en = (ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC); + ctx->qpmap_en = ctx->cfg->tune.deblur_en; + ctx->sp_enc_en = ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SE; + + if (vepu510_h265_setup_hal_bufs(ctx)) { + hal_h265e_err("vepu541_h265_allocate_buffers failed, free buffers and return\n"); + task->flags.err |= HAL_ENC_TASK_ERR_ALLOC; + return MPP_ERR_MALLOC; + } + + ctx->last_frame_type = ctx->frame_type; + frm_cfg = ctx->frms[task_idx]; + ctx->frm = frm_cfg; + + if (frm_status->is_intra) { + ctx->frame_type = INTRA_FRAME; + } else { + ctx->frame_type = INTER_P_FRAME; + } + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + } + + task->part_first = 1; + task->part_last = 0; + task->flags.reg_idx = ctx->task_idx; + ctx->ext_line_buf = ctx->ext_line_bufs[ctx->task_idx]; + frm_cfg->frame_count = ctx->frame_count++; + + ctx->task_idx++; + if (ctx->task_idx >= ctx->task_cnt) + ctx->task_idx = 0; + + frm_cfg->hal_curr_idx = ctx->syn->sp.recon_pic.slot_idx; + frm_cfg->hal_refr_idx = ctx->syn->sp.ref_pic.slot_idx; + + h265e_dpb_hal_start(ctx->dpb, frm_cfg->hal_curr_idx); + h265e_dpb_hal_start(ctx->dpb, frm_cfg->hal_refr_idx); + + memset(&frm_cfg->feedback, 0, sizeof(Vepu510H265Fbk)); + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v510_ret_task(void *hal, HalEncTask *task) +{ + H265eV510HalContext *ctx = (H265eV510HalContext *)hal; + HalEncTask *enc_task = task; + RK_S32 task_idx = task->flags.reg_idx; + Vepu510H265eFrmCfg *frm = ctx->frms[task_idx]; + Vepu510H265Fbk *fb = &frm->feedback; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + + hal_h265e_enter(); + + vepu510_h265_set_feedback(ctx, enc_task); + mpp_buffer_sync_partial_begin(enc_task->output, offset, fb->out_strm_size); + hal_h265e_amend_temporal_id(task, fb->out_strm_size); + + rc_info->sse = fb->sse_sum; + rc_info->lvl64_inter_num = fb->st_lvl64_inter_num; + rc_info->lvl32_inter_num = fb->st_lvl32_inter_num; + rc_info->lvl16_inter_num = fb->st_lvl16_inter_num; + rc_info->lvl8_inter_num = fb->st_lvl8_inter_num; + rc_info->lvl32_intra_num = fb->st_lvl32_intra_num; + rc_info->lvl16_intra_num = fb->st_lvl16_intra_num; + rc_info->lvl8_intra_num = fb->st_lvl8_intra_num; + rc_info->lvl4_intra_num = fb->st_lvl4_intra_num; + + enc_task->hw_length = fb->out_strm_size; + enc_task->length += fb->out_strm_size; + + h265e_dpb_hal_end(ctx->dpb, frm->hal_curr_idx); + h265e_dpb_hal_end(ctx->dpb, frm->hal_refr_idx); + + vepu510_h265e_tune_stat_update(ctx->tune, enc_task); + + hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); + hal_h265e_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_h265e_vepu510 = { + .name = "hal_h265e_v510", + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(H265eV510HalContext), + .flag = 0, + .init = hal_h265e_v510_init, + .deinit = hal_h265e_v510_deinit, + .prepare = hal_h265e_vepu510_prepare, + .get_task = hal_h265e_v510_get_task, + .gen_regs = hal_h265e_v510_gen_regs, + .start = hal_h265e_v510_start, + .wait = hal_h265e_v510_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h265e_v510_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h265e_vepu510) diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.h new file mode 100644 index 000000000..6310ccbe1 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265E_VEPU510_H +#define HAL_H265E_VEPU510_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h265e_vepu510; + +#endif /* HAL_H265E_VEPU510_H */ diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_reg.h new file mode 100644 index 000000000..3227d8f79 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_reg.h @@ -0,0 +1,822 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265E_VEPU510_REG_H +#define HAL_H265E_VEPU510_REG_H + +#include "rk_type.h" +#include "vepu510_common.h" + +typedef struct PreCstPar_t { + struct { + RK_U32 madi_thd0 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd1 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd2 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd3 : 7; + RK_U32 reserved3 : 1; + } cst_madi_thd0; + + /* 0x000020c4 reg2097 */ + struct { + RK_U32 madi_thd4 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd5 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd6 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd7 : 7; + RK_U32 reserved3 : 1; + } cst_madi_thd1; + + /* 0x000020c8 reg2098 */ + struct { + RK_U32 madi_thd8 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd9 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd10 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd11 : 7; + RK_U32 reserved3 : 1; + } cst_madi_thd2; + + /* 0x000020cc reg2099 */ + struct { + RK_U32 madi_thd12 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd13 : 7; + RK_U32 reserved1 : 1; + RK_U32 mode_th : 3; + RK_U32 reserved2 : 1; + RK_U32 qp_thd : 6; + RK_U32 reserved3 : 6; + } cst_madi_thd3; + + /* 0x000020d0 reg2100 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } cst_wgt0; + + /* 0x000020d4 reg2101 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 wgt5 : 8; + RK_U32 wgt6 : 8; + RK_U32 wgt7 : 8; + } cst_wgt1; + + /* 0x000020d8 reg2102 */ + struct { + RK_U32 wgt8 : 8; + RK_U32 wgt9 : 8; + RK_U32 wgt10 : 8; + RK_U32 wgt11 : 8; + } cst_wgt2; + + /* 0x000020dc reg2103 */ + struct { + RK_U32 wgt12 : 8; + RK_U32 wgt13 : 8; + RK_U32 wgt14 : 8; + RK_U32 lambda_mv_bit_0 : 3; + RK_U32 reserved : 1; + RK_U32 lambda_mv_bit_1 : 3; + RK_U32 anti_strp_e : 1; + } cst_wgt3; +} pre_cst_par; + +/* class: buffer/video syntax */ +/* 0x00000270 reg156 - 0x000003f4 reg253*/ +typedef struct H265eVepu510Frame_t { + Vepu510FrmCommon common; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 ltm_col : 1; + RK_U32 ltm_idx0l0 : 1; + RK_U32 chrm_spcl : 1; + RK_U32 cu_inter_e : 12; + RK_U32 reserved : 8; + RK_U32 ccwa_e : 1; + RK_U32 scl_lst_sel : 2; + RK_U32 lambda_qp_use_avg_cu16_flag : 1; + RK_U32 yuvskip_calc_en : 1; + RK_U32 atf_e : 1; + RK_U32 atr_e : 1; + RK_U32 reserved1 : 2; + } rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 rdo_mark_mode : 9; + RK_U32 reserved : 23; + } iprd_csts; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_unit_type : 6; + RK_U32 reserved : 26; + } synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 smpl_adpt_ofst_e : 1; + RK_U32 num_st_ref_pic : 7; + RK_U32 lt_ref_pic_prsnt : 1; + RK_U32 num_lt_ref_pic : 6; + RK_U32 tmpl_mvp_e : 1; + RK_U32 log2_max_poc_lsb : 4; + RK_U32 strg_intra_smth : 1; + RK_U32 reserved : 11; + } synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 dpdnt_sli_seg_en : 1; + RK_U32 out_flg_prsnt_flg : 1; + RK_U32 num_extr_sli_hdr : 3; + RK_U32 sgn_dat_hid_en : 1; + RK_U32 cbc_init_prsnt_flg : 1; + RK_U32 pic_init_qp : 6; + RK_U32 cu_qp_dlt_en : 1; + RK_U32 chrm_qp_ofst_prsn : 1; + RK_U32 lp_fltr_acrs_sli : 1; + RK_U32 dblk_fltr_ovrd_en : 1; + RK_U32 lst_mdfy_prsnt_flg : 1; + RK_U32 sli_seg_hdr_extn : 1; + RK_U32 cu_qp_dlt_depth : 2; + RK_U32 lpf_fltr_acrs_til : 1; + RK_U32 csip_flag : 1; + RK_U32 reserved : 9; + } synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 reserved : 3; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_l1_act : 2; + RK_U32 num_refidx_l0_act : 2; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_e : 1; + RK_U32 pic_out_flg : 1; + RK_U32 sli_type : 2; + RK_U32 sli_rsrv_flg : 7; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 sli_pps_id : 6; + RK_U32 no_out_pri_pic : 1; + } synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 sp_tc_ofst_div2 : 4; + RK_U32 sp_beta_ofst_div2 : 4; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sp_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_U32 sli_cb_qp_ofst : 5; + RK_U32 sli_qp : 6; + RK_U32 max_mrg_cnd : 2; + RK_U32 reserved : 1; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 lst_entry_l0 : 4; + RK_U32 reserved1 : 1; + } synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 sli_poc_lsb : 16; + RK_U32 sli_hdr_ext_len : 9; + RK_U32 reserved : 7; + } synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 st_ref_pic_flg : 1; + RK_U32 poc_lsb_lt0 : 16; + RK_U32 lt_idx_sps : 5; + RK_U32 num_lt_pic : 2; + RK_U32 st_ref_pic_idx : 6; + RK_U32 num_lt_sps : 2; + } synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 used_by_s0_flg : 4; + RK_U32 num_pos_pic : 1; + RK_U32 num_negative_pics : 5; + RK_U32 dlt_poc_msb_cycl0 : 16; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + } synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 dlt_poc_s0_m10 : 16; + RK_U32 dlt_poc_s0_m11 : 16; + } synt_refm2; + + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } synt_refm3; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } synt_long_refm0; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } synt_long_refm1; + + struct { + RK_U32 sao_lambda_multi : 3; + RK_U32 reserved : 29; + } sao_cfg; + + /* 0x3e4 - 0x3ec */ + RK_U32 reserved249_251[3]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 tile_w_m1 : 9; + RK_U32 reserved : 7; + RK_U32 tile_h_m1 : 9; + RK_U32 reserved1 : 6; + RK_U32 tile_en : 1; + } tile_cfg; + + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 9; + RK_U32 reserved : 7; + RK_U32 tile_y : 9; + RK_U32 reserved1 : 7; + } tile_pos_hevc; +} H265eVepu510Frame; + +/* class: param */ +/* 0x00001700 reg1472 - 0x000019cc reg1651 */ +typedef struct H265eVepu510Param_t { + /* 0x00001700 reg1472 - 0x0000172c reg1483*/ + RK_U32 reserved_1472_1483[12]; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 qnt_f_bias_i : 10; + RK_U32 qnt_f_bias_p : 10; + RK_U32 reserve : 12; + } qnt_bias_comb; + + /* 0x00001734 reg1485 - 0x0000175c reg1495*/ + RK_U32 reserved1485_1495[11]; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 itp_mode : 1; + RK_U32 reserved : 1; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 reserved1 : 17; + } me_sqi_comb; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th_comb; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 reserved : 20; + } cime_madp_th_comb; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi_comb; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th_comb; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th_comb; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi_comb; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th_comb; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 reg1536 - 0x000018cc reg1587*/ + RK_U32 pprd_lamb_satd_0_51[52]; + + /* 0x000018d0 reg1588 */ + struct { + RK_U32 lambda_satd_offset : 5; + RK_U32 reserved : 27; + } iprd_lamb_satd_ofst; + + /* 0x18d4 - 0x18fc */ + RK_U32 reserved1589_1599[11]; + + /* 0x00001900 reg1600 - 0x000019cc reg1651*/ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} H265eVepu510Param; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x000020fc reg2111 */ +typedef struct H265eVepu510SqiCfg_t { + /* 0x00002000 reg2048 */ + struct { + RK_U32 subj_opt_en : 1; + RK_U32 subj_opt_strength : 3; + RK_U32 aq_subj_en : 1; + RK_U32 aq_subj_strength : 3; + RK_U32 reserved : 4; + RK_U32 thre_sum_grdn_point : 20; + } subj_opt_cfg; + + /* 0x00002004 reg2049 */ + struct { + RK_U32 common_thre_num_grdn_point_dep0 : 8; + RK_U32 common_thre_num_grdn_point_dep1 : 8; + RK_U32 common_thre_num_grdn_point_dep2 : 8; + RK_U32 reserved : 8; + } subj_opt_dpth_thd; + + /* 0x00002008 reg2050 */ + struct { + RK_U32 common_rdo_cu_intra_r_coef_dep0 : 8; + RK_U32 common_rdo_cu_intra_r_coef_dep1 : 8; + RK_U32 reserved : 16; + } subj_opt_inrar_coef; + + /* 0x200c */ + RK_U32 reserved_2051; + + /* 0x00002010 reg2052 */ + struct { + RK_U32 anti_smear_en : 1; + RK_U32 frm_static : 1; + RK_U32 smear_stor_en : 1; + RK_U32 smear_load_en : 1; + RK_U32 smear_strength : 3; + RK_U32 reserved : 1; + RK_U32 thre_mv_inconfor_cime : 4; + RK_U32 thre_mv_confor_cime : 2; + RK_U32 thre_mv_confor_cime_gmv : 2; + RK_U32 thre_mv_inconfor_cime_gmv : 4; + RK_U32 thre_num_mv_confor_cime : 2; + RK_U32 thre_num_mv_confor_cime_gmv : 2; + RK_U32 reserved1 : 8; + } smear_opt_cfg0; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 dist0_frm_avg : 14; + RK_U32 thre_dsp_static : 5; + RK_U32 thre_dsp_mov : 5; + RK_U32 thre_dist_mv_confor_cime : 7; + RK_U32 reserved : 1; + } smear_opt_cfg1; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 thre_madp_stc_dep0 : 4; + RK_U32 thre_madp_stc_dep1 : 4; + RK_U32 thre_madp_stc_dep2 : 4; + RK_U32 thre_madp_mov_dep0 : 6; + RK_U32 thre_madp_mov_dep1 : 6; + RK_U32 thre_madp_mov_dep2 : 6; + RK_U32 reserved : 2; + } smear_madp_thd; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 thre_num_pt_stc_dep0 : 6; + RK_U32 thre_num_pt_stc_dep1 : 4; + RK_U32 thre_num_pt_stc_dep2 : 2; + RK_U32 reserved : 4; + RK_U32 thre_num_pt_mov_dep0 : 6; + RK_U32 thre_num_pt_mov_dep1 : 4; + RK_U32 thre_num_pt_mov_dep2 : 2; + RK_U32 reserved1 : 4; + } smear_stat_thd; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 thre_ratio_dist_mv_confor_cime_gmv0 : 5; + RK_U32 reserved : 3; + RK_U32 thre_ratio_dist_mv_confor_cime_gmv1 : 5; + RK_U32 reserved1 : 3; + RK_U32 thre_ratio_dist_mv_inconfor_cime_gmv0 : 6; + RK_U32 reserved2 : 2; + RK_U32 thre_ratio_dist_mv_inconfor_cime_gmv1 : 6; + RK_U32 reserved3 : 2; + } smear_bmv_dist_thd0; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 thre_ratio_dist_mv_inconfor_cime_gmv2 : 6; + RK_U32 reserved : 2; + RK_U32 thre_ratio_dist_mv_inconfor_cime_gmv3 : 6; + RK_U32 reserved1 : 2; + RK_U32 thre_ratio_dist_mv_inconfor_cime_gmv4 : 6; + RK_U32 reserved2 : 10; + } smear_bmv_dist_thd1; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 thre_min_num_confor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_max_num_confor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_min_num_inconfor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_max_num_inconfor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_split_dep0 : 2; + RK_U32 thre_zero_srgn : 5; + RK_U32 reserved : 1; + RK_U32 madi_thre_dep0 : 8; + RK_U32 madi_thre_dep1 : 8; + } smear_min_bndry_gmv; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 thre_madp_stc_cover0 : 6; + RK_U32 thre_madp_stc_cover1 : 6; + RK_U32 thre_madp_mov_cover0 : 5; + RK_U32 thre_madp_mov_cover1 : 5; + RK_U32 smear_qp_strength : 4; + RK_U32 smear_thre_qp : 6; + } smear_madp_cov_thd; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 skin_en : 1; + RK_U32 skin_strength : 3; + RK_U32 thre_uvsqr16_skin : 8; + RK_U32 skin_thre_cst_best_mad : 10; + RK_U32 skin_thre_cst_best_grdn_blk : 7; + RK_U32 reserved : 1; + RK_U32 frame_skin_ratio : 2; + } skin_opt_cfg; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 thre_sum_mad_intra : 2; + RK_U32 thre_sum_grdn_blk_intra : 2; + RK_U32 vld_thre_skin_v : 3; + RK_U32 reserved : 1; + RK_U32 thre_min_skin_u : 8; + RK_U32 thre_max_skin_u : 8; + RK_U32 thre_min_skin_v : 8; + } skin_chrm_thd; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 block_en : 1; + RK_U32 reserved : 1; + RK_U32 block_thre_cst_best_mad : 10; + RK_U32 reserved1 : 4; + RK_U32 block_thre_cst_best_grdn_blk : 6; + RK_U32 reserved2 : 2; + RK_U32 thre_num_grdnt_point_cmplx : 2; + RK_U32 block_delta_qp_flag : 2; + RK_U32 reserved3 : 4; + } block_opt_cfg; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 cmplx_thre_cst_best_mad_dep0 : 13; + RK_U32 reserved : 3; + RK_U32 cmplx_thre_cst_best_mad_dep1 : 13; + RK_U32 reserved1 : 2; + RK_U32 cmplx_en : 1; + } cmplx_opt_cfg; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 cmplx_thre_cst_best_mad_dep2 : 13; + RK_U32 reserved : 3; + RK_U32 cmplx_thre_cst_best_grdn_blk_dep0 : 11; + RK_U32 reserved1 : 5; + } cmplx_bst_mad_thd; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 cmplx_thre_cst_best_grdn_blk_dep1 : 11; + RK_U32 reserved : 5; + RK_U32 cmplx_thre_cst_best_grdn_blk_dep2 : 11; + RK_U32 reserved1 : 5; + } cmplx_bst_grdn_thd; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 line_en : 1; + RK_U32 line_thre_min_cst_best_grdn_blk_dep0 : 5; + RK_U32 line_thre_min_cst_best_grdn_blk_dep1 : 5; + RK_U32 line_thre_min_cst_best_grdn_blk_dep2 : 5; + RK_U32 line_thre_ratio_best_grdn_blk_dep0 : 4; + RK_U32 line_thre_ratio_best_grdn_blk_dep1 : 4; + RK_U32 reserved : 8; + } line_opt_cfg; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 line_thre_max_cst_best_grdn_blk_dep0 : 7; + RK_U32 reserved : 1; + RK_U32 line_thre_max_cst_best_grdn_blk_dep1 : 7; + RK_U32 reserved1 : 1; + RK_U32 line_thre_max_cst_best_grdn_blk_dep2 : 7; + RK_U32 reserved2 : 9; + } line_cst_bst_grdn; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 line_thre_qp : 6; + RK_U32 block_strength : 3; + RK_U32 block_thre_qp : 6; + RK_U32 cmplx_strength : 3; + RK_U32 cmplx_thre_qp : 6; + RK_U32 cmplx_thre_max_grdn_blk : 6; + RK_U32 reserved : 2; + } subj_opt_dqp0; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 skin_thre_qp : 6; + RK_U32 reserved : 2; + RK_U32 bndry_rdo_cu_intra_r_coef_dep0 : 8; + RK_U32 bndry_rdo_cu_intra_r_coef_dep1 : 8; + RK_U32 reserved1 : 8; + } subj_opt_dqp1; + + /* 0x2058 - 0x205c */ + RK_U32 reserved2070_2071[2]; + + /* 0x00002060 reg2072 - 0x0000206c reg2075 */ + rdo_skip_par rdo_b32_skip; + + /* 0x00002070 reg2076 - 0x0000207c reg2079*/ + rdo_skip_par rdo_b16_skip; + + /* 0x00002080 reg2080 - 0x00002088 reg2082 */ + rdo_noskip_par rdo_b32_inter; + + /* 0x0000208c reg2083 - 0x00002094 reg2085 */ + rdo_noskip_par rdo_b16_inter; + + /* 0x00002098 reg2086 - 0x000020a4 reg2088 */ + rdo_noskip_par rdo_b32_intra; + + /* 0x000020a8 reg2089 - 0x000020ac reg2091 */ + rdo_noskip_par rdo_b16_intra; + + /* 0x000020b0 reg2092 */ + struct { + RK_U32 blur_low_madi_thd : 7; + RK_U32 reserved : 1; + RK_U32 blur_high_madi_thd : 7; + RK_U32 reserved1 : 1; + RK_U32 blur_low_cnt_thd : 4; + RK_U32 blur_hight_cnt_thd : 4; + RK_U32 blur_sum_cnt_thd : 4; + RK_U32 anti_blur_en : 1; + RK_U32 reserved2 : 3; + } subj_anti_blur_thd; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 blur_motion_thd : 12; + RK_U32 sao_ofst_thd_eo_luma : 3; + RK_U32 reserved : 1; + RK_U32 sao_ofst_thd_bo_luma : 3; + RK_U32 reserved1 : 1; + RK_U32 sao_ofst_thd_eo_chroma : 3; + RK_U32 reserved2 : 1; + RK_U32 sao_ofst_thd_bo_chroma : 3; + RK_U32 reserved3 : 5; + } subj_anti_blur_sao; + + /* 0x000020b8 reg2094 - 0x000020bc reg2095*/ + RK_U32 reserved_2094_2095[2]; + + /* 0x000020c0 reg2096 - 0x000020dc reg2103 */ + pre_cst_par preintra32_cst; + + /* 0x000020e0 reg2104 - 0x000020fc reg2111 */ + pre_cst_par preintra16_cst; + + /* 0x00002100 reg2112 */ + struct { + RK_U32 base_thre_rough_mad32_intra : 4; + RK_U32 delta0_thre_rough_mad32_intra : 4; + RK_U32 delta1_thre_rough_mad32_intra : 6; + RK_U32 delta2_thre_rough_mad32_intra : 6; + RK_U32 delta3_thre_rough_mad32_intra : 7; + RK_U32 delta4_thre_rough_mad32_intra_low5 : 5; + } cudecis_thd0; + + /* 0x00002104 reg2113 */ + struct { + RK_U32 delta4_thre_rough_mad32_intra_high2 : 2; + RK_U32 delta5_thre_rough_mad32_intra : 7; + RK_U32 delta6_thre_rough_mad32_intra : 7; + RK_U32 base_thre_fine_mad32_intra : 4; + RK_U32 delta0_thre_fine_mad32_intra : 4; + RK_U32 delta1_thre_fine_mad32_intra : 5; + RK_U32 delta2_thre_fine_mad32_intra_low3 : 3; + } cudecis_thd1; + + /* 0x00002108 reg2114 */ + struct { + RK_U32 delta2_thre_fine_mad32_intra_high2 : 2; + RK_U32 delta3_thre_fine_mad32_intra : 5; + RK_U32 delta4_thre_fine_mad32_intra : 5; + RK_U32 delta5_thre_fine_mad32_intra : 6; + RK_U32 delta6_thre_fine_mad32_intra : 6; + RK_U32 base_thre_str_edge_mad32_intra : 3; + RK_U32 delta0_thre_str_edge_mad32_intra : 2; + RK_U32 delta1_thre_str_edge_mad32_intra : 3; + } cudecis_thd2; + + /* 0x0000210c reg2115 */ + struct { + RK_U32 delta2_thre_str_edge_mad32_intra : 3; + RK_U32 delta3_thre_str_edge_mad32_intra : 4; + RK_U32 base_thre_str_edge_bgrad32_intra : 5; + RK_U32 delta0_thre_str_edge_bgrad32_intra : 2; + RK_U32 delta1_thre_str_edge_bgrad32_intra : 3; + RK_U32 delta2_thre_str_edge_bgrad32_intra : 4; + RK_U32 delta3_thre_str_edge_bgrad32_intra : 5; + RK_U32 base_thre_mad16_intra : 3; + RK_U32 delta0_thre_mad16_intra : 3; + } cudecis_thd3; + + /* 0x00002110 reg2116 */ + struct { + RK_U32 delta1_thre_mad16_intra : 3; + RK_U32 delta2_thre_mad16_intra : 4; + RK_U32 delta3_thre_mad16_intra : 5; + RK_U32 delta4_thre_mad16_intra : 5; + RK_U32 delta5_thre_mad16_intra : 6; + RK_U32 delta6_thre_mad16_intra : 6; + RK_U32 delta0_thre_mad16_ratio_intra : 3; + } cudecis_thd4; + + /* 0x00002114 reg2117 */ + struct { + RK_U32 delta1_thre_mad16_ratio_intra : 3; + RK_U32 delta2_thre_mad16_ratio_intra : 3; + RK_U32 delta3_thre_mad16_ratio_intra : 3; + RK_U32 delta4_thre_mad16_ratio_intra : 3; + RK_U32 delta5_thre_mad16_ratio_intra : 3; + RK_U32 delta6_thre_mad16_ratio_intra : 3; + RK_U32 delta7_thre_mad16_ratio_intra : 3; + RK_U32 delta0_thre_rough_bgrad32_intra : 3; + RK_U32 delta1_thre_rough_bgrad32_intra : 4; + RK_U32 delta2_thre_rough_bgrad32_intra_low4 : 4; + } cudecis_thd5; + + /* 0x00002118 reg2118 */ + struct { + RK_U32 delta2_thre_rough_bgrad32_intra_high2 : 2; + RK_U32 delta3_thre_rough_bgrad32_intra : 10; + RK_U32 delta4_thre_rough_bgrad32_intra : 10; + RK_U32 delta5_thre_rough_bgrad32_intra_low10 : 10; + } cudecis_thd6; + + /* 0x0000211c reg2119 */ + struct { + RK_U32 delta5_thre_rough_bgrad32_intra_high1 : 1; + RK_U32 delta6_thre_rough_bgrad32_intra : 12; + RK_U32 delta7_thre_rough_bgrad32_intra : 13; + RK_U32 delta0_thre_bgrad16_ratio_intra : 4; + RK_U32 delta1_thre_bgrad16_ratio_intra_low2 : 2; + } cudecis_thd7; + + /* 0x00002120 reg2120 */ + struct { + RK_U32 delta1_thre_bgrad16_ratio_intra_high2 : 2; + RK_U32 delta2_thre_bgrad16_ratio_intra : 4; + RK_U32 delta3_thre_bgrad16_ratio_intra : 4; + RK_U32 delta4_thre_bgrad16_ratio_intra : 4; + RK_U32 delta5_thre_bgrad16_ratio_intra : 4; + RK_U32 delta6_thre_bgrad16_ratio_intra : 4; + RK_U32 delta7_thre_bgrad16_ratio_intra : 4; + RK_U32 delta0_thre_fme_ratio_inter : 3; + RK_U32 delta1_thre_fme_ratio_inter : 3; + } cudecis_thdt8; + + /* 0x00002124 reg2121 */ + struct { + RK_U32 delta2_thre_fme_ratio_inter : 3; + RK_U32 delta3_thre_fme_ratio_inter : 3; + RK_U32 delta4_thre_fme_ratio_inter : 3; + RK_U32 delta5_thre_fme_ratio_inter : 3; + RK_U32 delta6_thre_fme_ratio_inter : 3; + RK_U32 delta7_thre_fme_ratio_inter : 3; + RK_U32 base_thre_fme32_inter : 3; + RK_U32 delta0_thre_fme32_inter : 3; + RK_U32 delta1_thre_fme32_inter : 4; + RK_U32 delta2_thre_fme32_inter : 4; + } cudecis_thd9; + + /* 0x00002128 reg2122 */ + struct { + RK_U32 delta3_thre_fme32_inter : 5; + RK_U32 delta4_thre_fme32_inter : 6; + RK_U32 delta5_thre_fme32_inter : 7; + RK_U32 delta6_thre_fme32_inter : 8; + RK_U32 thre_cme32_inter : 6; + } cudecis_thd10; + + /* 0x0000212c reg2123 */ + struct { + RK_U32 delta0_thre_mad_fme_ratio_inter : 4; + RK_U32 delta1_thre_mad_fme_ratio_inter : 4; + RK_U32 delta2_thre_mad_fme_ratio_inter : 4; + RK_U32 delta3_thre_mad_fme_ratio_inter : 4; + RK_U32 delta4_thre_mad_fme_ratio_inter : 4; + RK_U32 delta5_thre_mad_fme_ratio_inter : 4; + RK_U32 delta6_thre_mad_fme_ratio_inter : 4; + RK_U32 delta7_thre_mad_fme_ratio_inter : 4; + } cudecis_thd11; +} H265eVepu510Sqi; + +typedef struct H265eV510RegSet_t { + Vepu510ControlCfg reg_ctl; + H265eVepu510Frame reg_frm; + Vepu510RcRoi reg_rc_roi; + H265eVepu510Param reg_param; + H265eVepu510Sqi reg_sqi; + Vepu510SclCfg reg_scl; + Vepu510Dbg reg_dbg; +} H265eV510RegSet; + +typedef struct H265eV510StatusElem_t { + RK_U32 hw_status; + Vepu510Status st; +} H265eV510StatusElem; + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c new file mode 100644 index 000000000..8014db513 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu510_tune.c @@ -0,0 +1,343 @@ +/* + * Copyright 2024 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hal_enc_task.h" +#include "hal_h265e_vepu510_reg.h" + +typedef struct HalH265eVepu510Tune_t { + H265eV510HalContext *ctx; + + RK_U8 *qm_mv_buf; /* qpmap move flag buffer */ + RK_U32 qm_mv_buf_size; + Vepu510NpuOut *obj_out; /* object map from npu */ + + RK_S32 pre_madp[2]; + RK_S32 pre_madi[2]; +} HalH265eVepu510Tune; + +static RK_U32 aq_thd_default[16] = { + 0, 0, 0, 0, 3, 3, 5, 5, + 8, 8, 15, 15, 20, 25, 25, 25 +}; + +static RK_S32 aq_qp_delta_default[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 1, 2, 3, 4, 5, 6, 7, 8 +}; + +static RK_U32 aq_thd_smt_I[16] = { + 1, 2, 3, 3, 3, 3, 5, 5, + 8, 8, 13, 15, 20, 25, 25, 25 +}; + +static RK_S32 aq_qp_delta_smt_I[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 1, 2, 3, 5, 7, 8, 9, 9 +}; + +static RK_U32 aq_thd_smt_P[16] = { + 0, 0, 0, 0, 3, 3, 5, 5, + 8, 8, 15, 15, 20, 25, 25, 25 +}; + +static RK_S32 aq_qp_delta_smt_P[16] = { + -8, -7, -6, -5, -4, -3, -2, -1, + 1, 2, 3, 4, 6, 7, 9, 9 +}; + +static HalH265eVepu510Tune *vepu510_h265e_tune_init(H265eV510HalContext *ctx) +{ + HalH265eVepu510Tune *tune = mpp_calloc(HalH265eVepu510Tune, 1); + + if (NULL == tune) + return tune; + + tune->ctx = ctx; + tune->pre_madi[0] = tune->pre_madi[1] = -1; + tune->pre_madp[0] = tune->pre_madp[1] = -1; + + return tune; +} + +static void vepu510_h265e_tune_deinit(void *tune) +{ + HalH265eVepu510Tune *t = (HalH265eVepu510Tune *)tune; + + MPP_FREE(t->qm_mv_buf); + MPP_FREE(tune); +} + +static void vepu510_h265e_tune_aq_prepare(HalH265eVepu510Tune *tune) +{ + if (tune == NULL) { + return; + } + + H265eV510HalContext *ctx = tune->ctx; + MppEncHwCfg *hw = &ctx->cfg->hw; + + if (ctx->smart_en) { + memcpy(hw->aq_thrd_i, aq_thd_smt_I, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, aq_thd_smt_P, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, aq_qp_delta_smt_I, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, aq_qp_delta_smt_P, sizeof(hw->aq_step_p)); + } else { + memcpy(hw->aq_thrd_i, aq_thd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, aq_thd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, aq_qp_delta_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, aq_qp_delta_default, sizeof(hw->aq_step_p)); + } +} + +static void vepu510_h265e_tune_aq(HalH265eVepu510Tune *tune) +{ + H265eV510HalContext *ctx = tune->ctx; + Vepu510H265eFrmCfg *frm_cfg = ctx->frm; + H265eV510RegSet *regs = frm_cfg->regs_set; + Vepu510RcRoi *r = ®s->reg_rc_roi; + MppEncHwCfg *hw = &ctx->cfg->hw; + RK_U32 i = 0; + RK_S32 aq_step[16]; + + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + if (ctx->frame_type == INTRA_FRAME) { + r->aq_tthd[i] = hw->aq_thrd_i[i]; + aq_step[i] = hw->aq_step_i[i] & 0x1F; + } else { + r->aq_tthd[i] = hw->aq_thrd_p[i]; + aq_step[i] = hw->aq_step_p[i] & 0x1F; + } + } + + r->aq_stp0.aq_stp_s0 = aq_step[0]; + r->aq_stp0.aq_stp_0t1 = aq_step[1]; + r->aq_stp0.aq_stp_1t2 = aq_step[2]; + r->aq_stp0.aq_stp_2t3 = aq_step[3]; + r->aq_stp0.aq_stp_3t4 = aq_step[4]; + r->aq_stp0.aq_stp_4t5 = aq_step[5]; + r->aq_stp1.aq_stp_5t6 = aq_step[6]; + r->aq_stp1.aq_stp_6t7 = aq_step[7]; + r->aq_stp1.aq_stp_7t8 = 0; + r->aq_stp1.aq_stp_8t9 = aq_step[8]; + r->aq_stp1.aq_stp_9t10 = aq_step[9]; + r->aq_stp1.aq_stp_10t11 = aq_step[10]; + r->aq_stp2.aq_stp_11t12 = aq_step[11]; + r->aq_stp2.aq_stp_12t13 = aq_step[12]; + r->aq_stp2.aq_stp_13t14 = aq_step[13]; + r->aq_stp2.aq_stp_14t15 = aq_step[14]; + r->aq_stp2.aq_stp_b15 = aq_step[15]; + + r->aq_clip.aq16_rnge = 5; + r->aq_clip.aq32_rnge = 5; + r->aq_clip.aq8_rnge = 10; + r->aq_clip.aq16_dif0 = 12; + r->aq_clip.aq16_dif1 = 12; + r->aq_clip.aq_rme_en = 1; + r->aq_clip.aq_cme_en = 1; +} + +static MPP_RET vepu510_h265e_tune_qpmap_init(HalH265eVepu510Tune *tune) +{ + H265eV510HalContext *ctx = tune->ctx; + Vepu510H265eFrmCfg *frm = ctx->frm; + H265eV510RegSet *regs = frm->regs_set; + H265eVepu510Frame *reg_frm = ®s->reg_frm; + RK_S32 w32 = MPP_ALIGN(ctx->cfg->prep.width, 32); + RK_S32 h32 = MPP_ALIGN(ctx->cfg->prep.height, 32); + RK_S32 roir_buf_fd = -1; + + if (frm->roi_data) { + //TODO: external qpmap buffer + } else { + if (NULL == frm->roir_buf) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + + //TODO: bmap_mdc_dpth = 1 ??? + frm->roir_buf_size = w32 * h32 / 256 * 4; + mpp_buffer_get(ctx->roi_grp, &frm->roir_buf, frm->roir_buf_size); + } + + roir_buf_fd = mpp_buffer_get_fd(frm->roir_buf); + } + + if (frm->roir_buf == NULL) { + mpp_err("failed to get roir_buf\n"); + return MPP_ERR_MALLOC; + } + reg_frm->common.adr_roir = roir_buf_fd; + + if (tune->qm_mv_buf == NULL) { + tune->qm_mv_buf_size = w32 * h32 / 256; + tune->qm_mv_buf = mpp_calloc(RK_U8, tune->qm_mv_buf_size); + if (NULL == tune->qm_mv_buf) { + mpp_err("failed to get qm_mv_buf\n"); + return MPP_ERR_MALLOC; + } + } + + hal_h265e_dbg_ctl("roir_buf_fd %d, size %d qm_mv_buf %p size %d\n", + roir_buf_fd, frm->roir_buf_size, tune->qm_mv_buf, + tune->qm_mv_buf_size); + return MPP_OK; +} + +static void vepu510_h265e_tune_qpmap(void *p, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH265eVepu510Tune *tune = (HalH265eVepu510Tune *)p; + + (void)task; + hal_h265e_dbg_func("enter\n"); + + ret = vepu510_h265e_tune_qpmap_init(tune); + if (ret != MPP_OK) { + mpp_err("failed to init qpmap\n"); + return; + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu510_h265e_tune_reg_patch(void *p, HalEncTask *task) +{ + HalH265eVepu510Tune *tune = (HalH265eVepu510Tune *)p; + + if (NULL == tune) + return; + H265eV510HalContext *ctx = tune->ctx; + + vepu510_h265e_tune_aq(tune); + + if (ctx->qpmap_en && (task->md_info != NULL)) { + vepu510_h265e_tune_qpmap(tune, task); + } +} + +static void vepu510_h265e_tune_stat_update(void *p, HalEncTask *task) +{ + HalH265eVepu510Tune *tune = (HalH265eVepu510Tune *)p; + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&task->rc_task->info; + + if (NULL == tune) + return; + + hal_h265e_dbg_func("enter\n"); + H265eV510HalContext *ctx = tune->ctx;; + RK_S32 task_idx = task->flags.reg_idx; + Vepu510H265eFrmCfg *frm = ctx->frms[task_idx]; + Vepu510H265Fbk *fb = &frm->feedback; + H265eV510RegSet *regs_set = frm->regs_set; + H265eV510StatusElem *elem = frm->regs_ret; + MppEncCfgSet *cfg = ctx->cfg; + RK_S32 w32 = MPP_ALIGN(cfg->prep.width, 32); + RK_S32 h32 = MPP_ALIGN(cfg->prep.height, 32); + RK_U32 b16_num = MPP_ALIGN(cfg->prep.width, 16) * MPP_ALIGN(cfg->prep.height, 16) / 256; + RK_U32 madi_cnt = 0, madp_cnt = 0; + + RK_U32 madi_th_cnt0 = elem->st.st_madi_lt_num0.madi_th_lt_cnt0 + + elem->st.st_madi_rt_num0.madi_th_rt_cnt0 + + elem->st.st_madi_lb_num0.madi_th_lb_cnt0 + + elem->st.st_madi_rb_num0.madi_th_rb_cnt0; + RK_U32 madi_th_cnt1 = elem->st.st_madi_lt_num0.madi_th_lt_cnt1 + + elem->st.st_madi_rt_num0.madi_th_rt_cnt1 + + elem->st.st_madi_lb_num0.madi_th_lb_cnt1 + + elem->st.st_madi_rb_num0.madi_th_rb_cnt1; + RK_U32 madi_th_cnt2 = elem->st.st_madi_lt_num1.madi_th_lt_cnt2 + + elem->st.st_madi_rt_num1.madi_th_rt_cnt2 + + elem->st.st_madi_lb_num1.madi_th_lb_cnt2 + + elem->st.st_madi_rb_num1.madi_th_rb_cnt2; + RK_U32 madi_th_cnt3 = elem->st.st_madi_lt_num1.madi_th_lt_cnt3 + + elem->st.st_madi_rt_num1.madi_th_rt_cnt3 + + elem->st.st_madi_lb_num1.madi_th_lb_cnt3 + + elem->st.st_madi_rb_num1.madi_th_rb_cnt3; + RK_U32 madp_th_cnt0 = elem->st.st_madp_lt_num0.madp_th_lt_cnt0 + + elem->st.st_madp_rt_num0.madp_th_rt_cnt0 + + elem->st.st_madp_lb_num0.madp_th_lb_cnt0 + + elem->st.st_madp_rb_num0.madp_th_rb_cnt0; + RK_U32 madp_th_cnt1 = elem->st.st_madp_lt_num0.madp_th_lt_cnt1 + + elem->st.st_madp_rt_num0.madp_th_rt_cnt1 + + elem->st.st_madp_lb_num0.madp_th_lb_cnt1 + + elem->st.st_madp_rb_num0.madp_th_rb_cnt1; + RK_U32 madp_th_cnt2 = elem->st.st_madp_lt_num1.madp_th_lt_cnt2 + + elem->st.st_madp_rt_num1.madp_th_rt_cnt2 + + elem->st.st_madp_lb_num1.madp_th_lb_cnt2 + + elem->st.st_madp_rb_num1.madp_th_rb_cnt2; + RK_U32 madp_th_cnt3 = elem->st.st_madp_lt_num1.madp_th_lt_cnt3 + + elem->st.st_madp_rt_num1.madp_th_rt_cnt3 + + elem->st.st_madp_lb_num1.madp_th_lb_cnt3 + + elem->st.st_madp_rb_num1.madp_th_rb_cnt3; + + madi_cnt = (6 * madi_th_cnt3 + 5 * madi_th_cnt2 + 4 * madi_th_cnt1) >> 2; + hal_rc_ret->complex_level = (madi_cnt * 100 > 30 * b16_num) ? 2 : + (madi_cnt * 100 > 13 * b16_num) ? 1 : 0; + + { + RK_U32 md_cnt = 0, motion_level = 0; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt3 + 11 * madp_th_cnt2 + 8 * madp_th_cnt1) >> 2; + else + md_cnt = (24 * madp_th_cnt3 + 22 * madp_th_cnt2 + 17 * madp_th_cnt1) >> 2; + + if (md_cnt * 100 > 15 * b16_num) + motion_level = 200; + else if (md_cnt * 100 > 5 * b16_num) + motion_level = 100; + else if (md_cnt * 100 > (b16_num >> 2)) + motion_level = 1; + else + motion_level = 0; + hal_rc_ret->motion_level = motion_level; + } + hal_h265e_dbg_st("frame %d complex_level %d motion_level %d\n", + ctx->frame_num - 1, hal_rc_ret->complex_level, hal_rc_ret->motion_level); + + fb->st_madi = madi_th_cnt0 * regs_set->reg_rc_roi.madi_st_thd.madi_th0 + + madi_th_cnt1 * (regs_set->reg_rc_roi.madi_st_thd.madi_th0 + + regs_set->reg_rc_roi.madi_st_thd.madi_th1) / 2 + + madi_th_cnt2 * (regs_set->reg_rc_roi.madi_st_thd.madi_th1 + + regs_set->reg_rc_roi.madi_st_thd.madi_th2) / 2 + + madi_th_cnt3 * regs_set->reg_rc_roi.madi_st_thd.madi_th2; + + madi_cnt = madi_th_cnt0 + madi_th_cnt1 + madi_th_cnt2 + madi_th_cnt3; + if (madi_cnt) + fb->st_madi = fb->st_madi / madi_cnt; + + fb->st_madp = madp_th_cnt0 * regs_set->reg_rc_roi.madp_st_thd0.madp_th0 + + madp_th_cnt1 * (regs_set->reg_rc_roi.madp_st_thd0.madp_th0 + + regs_set->reg_rc_roi.madp_st_thd0.madp_th1) / 2 + + madp_th_cnt2 * (regs_set->reg_rc_roi.madp_st_thd0.madp_th1 + + regs_set->reg_rc_roi.madp_st_thd1.madp_th2) / 2 + + madp_th_cnt3 * regs_set->reg_rc_roi.madp_st_thd1.madp_th2; + + madp_cnt = madp_th_cnt0 + madp_th_cnt1 + madp_th_cnt2 + madp_th_cnt3; + if (madp_cnt) + fb->st_madp = fb->st_madp / madp_cnt; + + fb->st_mb_num += elem->st.st_bnum_b16.num_b16; + fb->frame_type = (task->rc_task->frm.is_intra != 0) ? INTRA_FRAME : INTER_P_FRAME; + hal_rc_ret->bit_real += fb->out_strm_size * 8; + + hal_rc_ret->madi = elem->st.madi16_sum / fb->st_mb_num; + hal_rc_ret->madp = elem->st.madp16_sum / fb->st_mb_num; + hal_rc_ret->dsp_y_avg = elem->st.dsp_y_sum / (w32 / 4 * h32 / 4); + + hal_h265e_dbg_st("frame %d bit_real %d quality_real %d dsp_y_avg %3d\n", ctx->frame_num - 1, + hal_rc_ret->bit_real, hal_rc_ret->quality_real, hal_rc_ret->dsp_y_avg); + + hal_h265e_dbg_func("leave\n"); +} \ No newline at end of file diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu511.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu511.c new file mode 100644 index 000000000..89b717dcd --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu511.c @@ -0,0 +1,2967 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h265e_v511" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" +#include "mpp_enc_cb_param.h" + +#include "rkv_enc_def.h" +#include "h265e_syntax_new.h" +#include "h265e_dpb.h" +#include "hal_bufs.h" +#include "hal_h265e_debug.h" +#include "hal_h265e_vepu511.h" +#include "hal_h265e_vepu511_reg.h" +#include "hal_h265e_stream_amend.h" + +#include "vepu5xx_common.h" +#include "vepu511_common.h" + +#define H265E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) +#define H265E_SMEAR_STR_NUM (8) + +#define hal_h265e_err(fmt, ...) \ + do {\ + mpp_err_f(fmt, ## __VA_ARGS__);\ + } while (0) + +typedef struct Vepu511H265Fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 frame_type; + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; + RK_U32 st_smear_cnt[5]; + RK_S32 reg_idx; + RK_U32 acc_cover16_num; + RK_U32 acc_bndry16_num; + RK_U32 acc_zero_mv; + RK_S8 tgt_sub_real_lvl[6]; +} Vepu511H265Fbk; + +typedef struct Vepu511H265eFrmCfg_t { + RK_S32 frame_count; + RK_S32 frame_type; + + /* dchs cfg on frame parallel */ + RK_S32 dchs_curr_idx; + RK_S32 dchs_prev_idx; + + /* hal dpb management slot idx */ + RK_S32 hal_curr_idx; + RK_S32 hal_refr_idx; + + /* regs cfg */ + H265eV511RegSet *regs_set; + H265eV511StatusElem *regs_ret; + + /* hardware return info collection cfg */ + Vepu511H265Fbk feedback; + + void *roi_data; + + /* roi buffer for qpmap or gdr */ + MppBuffer roir_buf; + RK_S32 roir_buf_size; + void *roi_base_cfg_sw_buf; + + /* variable length cfg */ + MppDevRegOffCfgs *reg_cfg; +} Vepu511H265eFrmCfg; + +typedef struct H265eV511HalContext_t { + MppDev dev; + void *regs; + void *reg_out; + + /* single frame config for single core */ + Vepu511H265eFrmCfg *frm; + + /* slice split poll cfg */ + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + MppDevPollCfg *poll_cfgs; + MppCbCtx *output_cb; + + /* @frame_cnt starts from ZERO */ + RK_S32 frame_count; + + /* dchs cfg */ + RK_S32 curr_idx; + RK_S32 prev_idx; + + Vepu511H265Fbk feedback; + Vepu511H265Fbk last_frame_fb; + void *dump_files; + RK_U32 frame_cnt_gen_ready; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + MppBufferGroup roi_grp; + void *roi_data; + Vepu511OsdCfg osd_cfg; + + MppEncCfgSet *cfg; + MppDevRegOffCfgs *reg_cfg; + H265eSyntax_new *syn; + H265eDpb *dpb; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + HalBufs dpb_bufs; + RK_S32 fbc_header_len; + RK_U32 title_num; + RK_S32 smear_size; + + RK_S32 qpmap_en; + RK_S32 smart_en; + + /* external line buffer over 3K */ + MppBufferGroup ext_line_buf_grp; + RK_S32 ext_line_buf_size; + MppBuffer ext_line_buf; + MppBuffer buf_pass1; + + void *tune; +} H265eV511HalContext; + +static const RK_U32 lambda_tbl_pre_intra[52] = { + 4206, 4945, 5814, 6835, 8035, 9446, 11105, 13056, + 15348, 18044, 21213, 24938, 29318, 34467, 40521, 47637, + 56003, 65839, 77402, 90996, 106977, 125765, 147852, 173819, + 204346, 240234, 983, 1206, 1479, 1813, 2223, 2727, + 3344, 4100, 5028, 6166, 7561, 9272, 11371, 13944, + 17099, 20969, 25714, 31533, 38669, 47420, 58150, 71310, + 87447, 107236, 131504, 161263, +}; + +static const RK_U32 lambda_tbl_pre_inter[52] = { + 760, 959, 1210, 1526, 1925, 2428, 3063, 3864, + 4874, 6147, 7754, 9781, 12337, 15562, 19629, 24760, + 31231, 39394, 49691, 62678, 79061, 99725, 125790, 158668, + 200140, 252451, 579, 730, 919, 1159, 1461, 1993, + 2898, 3652, 4601, 5411, 6818, 7362, 9276, 11688, + 14725, 18553, 25324, 31906, 40200, 50649, 68724, 74217, + 101300, 127630, 148435, 187017, +}; + +static RK_U32 rdo_lambda_table_I[60] = { + 0x00000012, 0x00000017, + 0x0000001d, 0x00000024, 0x0000002e, 0x0000003a, + 0x00000049, 0x0000005c, 0x00000074, 0x00000092, + 0x000000b8, 0x000000e8, 0x00000124, 0x00000170, + 0x000001cf, 0x00000248, 0x000002df, 0x0000039f, + 0x0000048f, 0x000005bf, 0x0000073d, 0x0000091f, + 0x00000b7e, 0x00000e7a, 0x0000123d, 0x000016fb, + 0x00001cf4, 0x0000247b, 0x00002df6, 0x000039e9, + 0x000048f6, 0x00005bed, 0x000073d1, 0x000091ec, + 0x0000b7d9, 0x0000e7a2, 0x000123d7, 0x00016fb2, + 0x0001cf44, 0x000247ae, 0x0002df64, 0x00039e89, + 0x00048f5c, 0x0005bec8, 0x00073d12, 0x00091eb8, + 0x000b7d90, 0x000e7a23, 0x00123d71, 0x0016fb20, + 0x001cf446, 0x00247ae1, 0x002df640, 0x0039e88c, + 0x0048f5c3, 0x005bec81, 0x0073d119, 0x0091eb85, + 0x00b7d902, 0x00e7a232 +}; + +static RK_U32 rdo_lambda_table_P[60] = { + 0x0000002c, 0x00000038, 0x00000044, 0x00000058, + 0x00000070, 0x00000089, 0x000000b0, 0x000000e0, + 0x00000112, 0x00000160, 0x000001c0, 0x00000224, + 0x000002c0, 0x00000380, 0x00000448, 0x00000580, + 0x00000700, 0x00000890, 0x00000b00, 0x00000e00, + 0x00001120, 0x00001600, 0x00001c00, 0x00002240, + 0x00002c00, 0x00003800, 0x00004480, 0x00005800, + 0x00007000, 0x00008900, 0x0000b000, 0x0000e000, + 0x00011200, 0x00016000, 0x0001c000, 0x00022400, + 0x0002c000, 0x00038000, 0x00044800, 0x00058000, + 0x00070000, 0x00089000, 0x000b0000, 0x000e0000, + 0x00112000, 0x00160000, 0x001c0000, 0x00224000, + 0x002c0000, 0x00380000, 0x00448000, 0x00580000, + 0x00700000, 0x00890000, 0x00b00000, 0x00e00000, + 0x01120000, 0x01600000, 0x01c00000, 0x02240000, +}; + +/* scale_iq */ +static RK_U8 vepu511_h265_cqm_intra8[64] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115 +}; + +/* scale_iq */ +static RK_U8 vepu511_h265_cqm_inter8[64] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91 +}; + +/* scale_q = (65536 + scale_iq / 2) / scale_iq */ +static RK_U16 vepu511_h265_cqm_intra8_q[64] = { + 4096, 4096, 4096, 4096, 3855, 3641, 3121, 2731, + 4096, 4096, 4096, 4096, 3855, 3449, 2979, 2621, + 4096, 4096, 3855, 3641, 3277, 2979, 2621, 2260, + 4096, 4096, 3641, 3121, 2731, 2427, 2114, 1820, + 3855, 3855, 3277, 2731, 2185, 1872, 1598, 1394, + 3641, 3449, 2979, 2427, 1872, 1489, 1214, 1008, + 3121, 2979, 2621, 2114, 1598, 1214, 936, 745, + 2731, 2621, 2260, 1820, 1394, 1008, 745, 570 +}; + +/* scale_q = (65536 + scale_iq / 2) / scale_iq */ +static RK_U16 vepu511_h265_cqm_inter8_q[64] = { + 4096, 4096, 4096, 4096, 3855, 3641, 3277, 2731, + 4096, 4096, 4096, 3855, 3641, 3277, 2731, 2621, + 4096, 4096, 3855, 3641, 3277, 2731, 2621, 2341, + 4096, 3855, 3641, 3277, 2731, 2621, 2341, 1986, + 3855, 3641, 3277, 2731, 2621, 2341, 1986, 1598, + 3641, 3277, 2731, 2621, 2341, 1986, 1598, 1214, + 3277, 2731, 2621, 2341, 1986, 1598, 1214, 923, + 2731, 2621, 2341, 1986, 1598, 1214, 923, 720 +}; + +void save_to_file_511(char *name, void *ptr, size_t size) +{ + FILE *fp = fopen(name, "w+b"); + if (fp) { + fwrite(ptr, 1, size, fp); + fclose(fp); + } else + mpp_err("create file %s failed\n", name); +} + +void vepu511_h265e_dump(H265eV511HalContext *ctx, HalEncTask *enc_task __maybe_unused) +{ + H265eSyntax_new *syn = ctx->syn; + HalBuf *hal_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.ref_pic.slot_idx); + size_t buf_size = mpp_buffer_get_size(hal_buf->buf[0]); + size_t dws_size = mpp_buffer_get_size(hal_buf->buf[1]); + void *ptr = mpp_buffer_get_ptr(hal_buf->buf[0]); + void *dws_ptr = mpp_buffer_get_ptr(hal_buf->buf[1]); + RK_U32 frm_num = ctx->frm->frame_count; + RK_S32 pid = getpid(); + char name[128]; + size_t name_len = sizeof(name) - 1; + + snprintf(name, name_len, "/mnt/sdcard/dump/refr_fbd_%d_frm%d.bin", pid, frm_num); + save_to_file_511(name, ptr + ctx->fbc_header_len, buf_size - ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/refr_fbh_%d_frm%d.bin", pid, frm_num); + save_to_file_511(name, ptr, ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/refr_dsp_%d_frm%d.bin", pid, frm_num); + save_to_file_511(name, dws_ptr, dws_size); + + hal_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.recon_pic.slot_idx); + buf_size = mpp_buffer_get_size(hal_buf->buf[0]); + dws_size = mpp_buffer_get_size(hal_buf->buf[1]); + ptr = mpp_buffer_get_ptr(hal_buf->buf[0]); + dws_ptr = mpp_buffer_get_ptr(hal_buf->buf[1]); + + snprintf(name, name_len, "/mnt/sdcard/dump/recn_fbd_%d_frm%d_slot%d.bin", pid, frm_num, syn->sp.recon_pic.slot_idx); + save_to_file_511(name, ptr + ctx->fbc_header_len, buf_size - ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/recn_fbh_%d_frm%d_slot%d.bin", pid, frm_num, syn->sp.recon_pic.slot_idx); + save_to_file_511(name, ptr, ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/recn_dsp_%d_frm%d_slot%d.bin", pid, frm_num, syn->sp.recon_pic.slot_idx); + save_to_file_511(name, dws_ptr, dws_size); + +} + +static void setup_ext_line_bufs(H265eV511HalContext *ctx) +{ + if (ctx->ext_line_buf) + return; + + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_buf, + ctx->ext_line_buf_size); +} + +static void clear_ext_line_bufs(H265eV511HalContext *ctx) +{ + if (ctx->ext_line_buf) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + } +} + +static MPP_RET vepu511_h265_setup_hal_bufs(H265eV511HalContext *ctx) +{ + MPP_RET ret = MPP_OK; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + RK_U32 frame_size; + VepuFmt input_fmt = VEPU5xx_FMT_YUV420P; + RK_S32 mb_wd64, mb_h64; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + RK_S32 alignment = 32; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment); + RK_S32 smear_size = 0; + RK_S32 smear_r_size = 0; + + hal_h265e_enter(); + + mb_wd64 = (prep->width + 63) / 64; + mb_h64 = (prep->height + 63) / 64 + 1; + + frame_size = MPP_ALIGN(prep->width, 16) * MPP_ALIGN(prep->height, 16); + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + input_fmt = (VepuFmt)fmt->format; + switch (input_fmt) { + case VEPU5xx_FMT_YUV400: + break; + case VEPU5xx_FMT_YUV420P: + case VEPU5xx_FMT_YUV420SP: { + frame_size = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV422P: + case VEPU5xx_FMT_YUV422SP: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: + case VEPU5xx_FMT_BGR565: { + frame_size *= 2; + } break; + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_YUV444SP: + case VEPU5xx_FMT_YUV444P: { + frame_size *= 3; + } break; + case VEPU5xx_FMT_BGRA8888: { + frame_size *= 4; + } break; + default: { + hal_h265e_err("invalid src color space: %d\n", input_fmt); + return MPP_NOK; + } + } + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > SZ_4K) { + RK_S32 ctu_w = (aligned_w + 31) / 32; + RK_S32 ext_line_buf_size = ((ctu_w - 113) * 27 + 15) / 16 * 16 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + clear_ext_line_bufs(ctx); + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + setup_ext_line_bufs(ctx); + ctx->ext_line_buf_size = ext_line_buf_size; + } else { + clear_ext_line_bufs(ctx); + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + smear_size = MPP_ALIGN(prep->width, 256) / 256 * MPP_ALIGN(prep->height, 32) / 32 * 16; + smear_r_size = MPP_ALIGN(prep->height, 256) / 256 * MPP_ALIGN(prep->width, 32) / 32 * 16; + smear_size = MPP_MAX(smear_size, smear_r_size) * 2; + + if (frame_size > ctx->frame_size || new_max_cnt > old_max_cnt || + smear_size != ctx->smear_size) { + size_t size[4] = {0}; + + hal_bufs_deinit(ctx->dpb_bufs); + hal_bufs_init(&ctx->dpb_bufs); + + ctx->fbc_header_len = MPP_ALIGN(((mb_wd64 * mb_h64) << 6), SZ_8K); + size[0] = ctx->fbc_header_len + ((mb_wd64 * mb_h64) << 12) * 3 / 2; //fbc_h + fbc_b + size[1] = (mb_wd64 * mb_h64 << 8); + size[2] = MPP_ALIGN(mb_wd64 * mb_h64 * 16 * 4, 256) * 16; + /* smear bufs */ + size[3] = smear_size; + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_h265e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->frame_size, frame_size, old_max_cnt, new_max_cnt); + + hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, MPP_ARRAY_ELEMS(size), size); + + ctx->smear_size = smear_size; + ctx->frame_size = frame_size; + ctx->max_buf_cnt = new_max_cnt; + } + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_vepu511_deinit(void *hal) +{ + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + + hal_h265e_enter(); + MPP_FREE(ctx->poll_cfgs); + MPP_FREE(ctx->input_fmt); + hal_bufs_deinit(ctx->dpb_bufs); + + if (ctx->frm) { + if (ctx->frm->roir_buf) { + mpp_buffer_put(ctx->frm->roir_buf); + ctx->frm->roir_buf = NULL; + ctx->frm->roir_buf_size = 0; + } + + MPP_FREE(ctx->frm->roi_base_cfg_sw_buf); + + if (ctx->frm->reg_cfg) { + mpp_dev_multi_offset_deinit(ctx->frm->reg_cfg); + ctx->frm->reg_cfg = NULL; + } + + MPP_FREE(ctx->frm->regs_set); + MPP_FREE(ctx->frm->regs_ret); + MPP_FREE(ctx->frm); + } + + clear_ext_line_bufs(ctx); + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + + if (ctx->buf_pass1) { + mpp_buffer_put(ctx->buf_pass1); + ctx->buf_pass1 = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + if (ctx->reg_cfg) { + mpp_dev_multi_offset_deinit(ctx->reg_cfg); + ctx->reg_cfg = NULL; + } + + if (ctx->roi_grp) { + mpp_buffer_group_put(ctx->roi_grp); + ctx->roi_grp = NULL; + } + + if (ctx->tune) { + // vepu511_h265e_tune_deinit(ctx->tune); + ctx->tune = NULL; + } + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu511_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + + mpp_env_get_u32("hal_h265e_debug", &hal_h265e_debug, 0); + hal_h265e_enter(); + + /* single core uses single frame config */ + ctx->frm = mpp_calloc(Vepu511H265eFrmCfg, 1); + ctx->frm->regs_set = mpp_calloc(H265eV511RegSet, 1); + ctx->frm->regs_ret = mpp_calloc(H265eV511StatusElem, 1); + ctx->frm->frame_type = INTRA_FRAME; + + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + hal_bufs_init(&ctx->dpb_bufs); + + ctx->frame_count = -1; + ctx->frame_cnt_gen_ready = 0; + ctx->enc_mode = 1; + cfg->cap_recn_out = 1; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + mpp_dev_multi_offset_init(&ctx->reg_cfg, 24); + ctx->dev = cfg->dev; + ctx->frame_type = INTRA_FRAME; + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + RK_U32 j; + + hw->qp_delta_row_i = 2; + hw->qp_delta_row = 2; + hw->qbias_i = 171; + hw->qbias_p = 85; + hw->qbias_en = 0; + + for (j = 0; j < MPP_ARRAY_ELEMS(hw->mode_bias); j++) + hw->mode_bias[j] = 8; + } + + ctx->poll_slice_max = 8; + ctx->poll_cfg_size = (sizeof(ctx->poll_cfgs) + sizeof(RK_S32) * ctx->poll_slice_max) * 2; + ctx->poll_cfgs = mpp_malloc_size(MppDevPollCfg, ctx->poll_cfg_size); + + if (NULL == ctx->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init poll cfg buffer failed\n"); + goto DONE; + } + + ctx->output_cb = cfg->output_cb; + cfg->cap_recn_out = 1; + + // ctx->tune = vepu511_h265e_tune_init(ctx); + +DONE: + if (ret) + hal_h265e_vepu511_deinit(hal); + + hal_h265e_leave(); + return ret; +} + +static MPP_RET hal_h265e_vepu511_prepare(void *hal) +{ + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h265e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + vepu511_h265_setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->dpb_bufs, i); + + prep->change_res = 0; + } + + hal_h265e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET +vepu511_h265_set_patch_info(H265eSyntax_new *syn, VepuFmt input_fmt, MppDevRegOffCfgs *offsets, HalEncTask *task) +{ + RK_U32 hor_stride = syn->pp.hor_stride; + RK_U32 ver_stride = (syn->pp.ver_stride != 0) ? syn->pp.ver_stride : syn->pp.pic_height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + u_offset = mpp_frame_get_fbc_offset(task->frame); + v_offset = u_offset; + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV400: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride * 2; + } break; + default: { + hal_h265e_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + mpp_dev_multi_offset_update(offsets, 161, u_offset); + mpp_dev_multi_offset_update(offsets, 162, v_offset); + + return ret; +} + +static MPP_RET vepu511_h265e_save_pass1_patch(H265eV511RegSet *regs, H265eV511HalContext *ctx, + RK_S32 tiles_enabled_flag) +{ + RK_S32 width = ctx->cfg->prep.width; + RK_S32 height = ctx->cfg->prep.height; + RK_S32 width_align = MPP_ALIGN(width, 16); + RK_S32 height_align = MPP_ALIGN(height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + regs->reg_frm.reg0192_enc_pic.cur_frm_ref = 1; + regs->reg_frm.reg0163_rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + regs->reg_frm.reg0164_rfpw_b_addr = regs->reg_frm.reg0163_rfpw_h_addr; + regs->reg_frm.reg0192_enc_pic.rec_fbc_dis = 1; + regs->reg_frm.reg0223_me_ref_comb.rfpw_mode = 0; + + if (tiles_enabled_flag) + regs->reg_frm.reg0238_synt_pps.lp_fltr_acrs_sli = 0; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, width_align * height_align); + + /* NOTE: disable split to avoid lowdelay slice output */ + regs->reg_frm.reg0216_sli_splt.sli_splt = 0; + regs->reg_frm.reg0192_enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu511_h265e_use_pass1_patch(H265eV511RegSet *regs, H265eV511HalContext *ctx) +{ + Vepu511ControlCfg *reg_ctl = ®s->reg_ctl; + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + RK_S32 y_stride = width_align; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + MPP_RET ret = MPP_OK; + + hal_h265e_dbg_func("enter\n"); + + regs->reg_frm.reg0192_enc_pic.rfpr_compress_mode = 1; + reg_ctl->dtrns_map.src_bus_edin = fmt->src_endian; + regs->reg_frm.reg0198_src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + regs->reg_frm.reg0198_src_fmt.out_fmt = 1; + regs->reg_frm.reg0198_src_fmt.alpha_swap = 0; + regs->reg_frm.reg0198_src_fmt.rbuv_swap = 0; + + regs->reg_frm.reg0205_src_strd0.src_strd0 = y_stride; + regs->reg_frm.reg0206_src_strd1.src_strd1 = y_stride; + + regs->reg_frm.reg0203_src_proc.rkfbcd_en = 0; + regs->reg_frm.reg0203_src_proc.src_mirr = 0; + regs->reg_frm.reg0203_src_proc.src_rot = 0; + + regs->reg_frm.reg0204_pic_ofst.pic_ofst_y = 0; + regs->reg_frm.reg0204_pic_ofst.pic_ofst_x = 0; + + regs->reg_frm.reg0160_adr_src0 = mpp_buffer_get_fd(ctx->buf_pass1); + regs->reg_frm.reg0161_adr_src1 = regs->reg_frm.reg0160_adr_src0; + regs->reg_frm.reg0162_adr_src2 = 0; + + /* input cb addr */ + ret = mpp_dev_multi_offset_update(ctx->reg_cfg, 161, width_align * height_align); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); + + return MPP_OK; +} + +static void setup_vepu511_ext_line_buf(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + RK_S32 fd; + + if (ctx->ext_line_buf) { + fd = mpp_buffer_get_fd(ctx->ext_line_buf); + + regs->reg_frm.reg0179_adr_ebufb = fd; + regs->reg_frm.reg0178_adr_ebuft = fd; + mpp_dev_multi_offset_update(ctx->reg_cfg, 178, ctx->ext_line_buf_size); + } else { + regs->reg_frm.reg0179_adr_ebufb = 0; + regs->reg_frm.reg0178_adr_ebuft = 0; + } +} + +static void vepu511_h265_set_scaling_list(H265eV511RegSet *regs) +{ + Vepu511SclCfg *s = ®s->reg_scl_jpgtbl.scl; + Vepu511SclCfgExt *s_ext = ®s->reg_scl_jpgtbl.scl_ext; + RK_U32 scl_lst_sel = regs->reg_frm.reg0232_rdo_cfg.scl_lst_sel; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U16 *q = (RK_U16 *)&s_ext->tu8_intra_y[0]; + RK_U8 idx; + + hal_h265e_dbg_func("enter\n"); + + if (scl_lst_sel == 1) { + for (idx = 0; idx < 64; idx++) { + /* TU8 intra Y/U/V */ + p[idx + 64 * 0] = vepu511_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 1] = vepu511_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 2] = vepu511_h265_cqm_intra8[63 - idx]; + + q[idx + 64 * 0] = vepu511_h265_cqm_intra8_q[63 - idx]; + q[idx + 64 * 1] = vepu511_h265_cqm_intra8_q[63 - idx]; + q[idx + 64 * 2] = vepu511_h265_cqm_intra8_q[63 - idx]; + + /* TU8 inter Y/U/V */ + p[idx + 64 * 3] = vepu511_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 4] = vepu511_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 5] = vepu511_h265_cqm_inter8[63 - idx]; + + q[idx + 64 * 3] = vepu511_h265_cqm_inter8_q[63 - idx]; + q[idx + 64 * 4] = vepu511_h265_cqm_inter8_q[63 - idx]; + q[idx + 64 * 5] = vepu511_h265_cqm_inter8_q[63 - idx]; + + /* TU16 intra Y/U/V AC */ + p[idx + 64 * 6] = vepu511_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 7] = vepu511_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 8] = vepu511_h265_cqm_intra8[63 - idx]; + + + q[idx + 64 * 6] = vepu511_h265_cqm_intra8_q[63 - idx]; + q[idx + 64 * 7] = vepu511_h265_cqm_intra8_q[63 - idx]; + q[idx + 64 * 8] = vepu511_h265_cqm_intra8_q[63 - idx]; + + /* TU16 inter Y/U/V AC */ + p[idx + 64 * 9] = vepu511_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 10] = vepu511_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 11] = vepu511_h265_cqm_inter8[63 - idx]; + + q[idx + 64 * 9] = vepu511_h265_cqm_inter8_q[63 - idx]; + q[idx + 64 * 10] = vepu511_h265_cqm_inter8_q[63 - idx]; + q[idx + 64 * 11] = vepu511_h265_cqm_inter8_q[63 - idx]; + + /* TU32 intra/inter Y AC */ + p[idx + 64 * 12] = vepu511_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 13] = vepu511_h265_cqm_inter8[63 - idx]; + + q[idx + 64 * 12] = vepu511_h265_cqm_intra8_q[63 - idx]; + q[idx + 64 * 13] = vepu511_h265_cqm_inter8_q[63 - idx]; + } + + s->tu_dc0.tu16_intra_y_dc = 16; + s->tu_dc0.tu16_intra_u_dc = 16; + s->tu_dc0.tu16_intra_v_dc = 16; + s->tu_dc0.tu16_inter_y_dc = 16; + s->tu_dc1.tu16_inter_u_dc = 16; + s->tu_dc1.tu16_inter_v_dc = 16; + s->tu_dc1.tu32_intra_y_dc = 16; + s->tu_dc1.tu32_inter_y_dc = 16; + + s_ext->tu_dc0.tu16_intra_y_dc = 4096; + s_ext->tu_dc0.tu16_intra_u_dc = 4096; + s_ext->tu_dc1.tu16_intra_v_dc = 4096; + s_ext->tu_dc1.tu16_inter_y_dc = 4096; + s_ext->tu_dc2.tu16_inter_u_dc = 4096; + s_ext->tu_dc2.tu16_inter_v_dc = 4096; + s_ext->tu_dc3.tu32_intra_y_dc = 4096; + s_ext->tu_dc3.tu32_inter_y_dc = 4096; + } else if (scl_lst_sel == 2) { + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu511_h265_set_normal(H265eV511RegSet *regs) +{ + Vepu511ControlCfg *reg_ctl = ®s->reg_ctl; + + reg_ctl->enc_strt.vepu_cmd = 1; + reg_ctl->enc_clr.safe_clr = 0; + reg_ctl->enc_clr.force_clr = 0; + reg_ctl->enc_clr.dvbm_clr = 0; + + reg_ctl->int_en.enc_done_en = 1; + reg_ctl->int_en.lkt_node_done_en = 1; + reg_ctl->int_en.sclr_done_en = 1; + reg_ctl->int_en.vslc_done_en = 1; + reg_ctl->int_en.vbsf_oflw_en = 1; + reg_ctl->int_en.vbuf_lens_en = 1; + reg_ctl->int_en.enc_err_en = 1; + reg_ctl->int_en.vsrc_err_en = 1; + reg_ctl->int_en.wdg_en = 1; + reg_ctl->int_en.lkt_err_int_en = 1; + reg_ctl->int_en.lkt_err_stop_en = 1; + reg_ctl->int_en.lkt_force_stop_en = 1; + reg_ctl->int_en.jslc_done_en = 1; + reg_ctl->int_en.jbsf_oflw_en = 1; + reg_ctl->int_en.jbuf_lens_en = 1; + reg_ctl->int_en.dvbm_err_en = 0; + + reg_ctl->dtrns_map.jpeg_bus_edin = 0x7; + reg_ctl->int_clr.enc_done_clr = 1; + + reg_ctl->dtrns_map.src_bus_edin = 0x0; + reg_ctl->dtrns_map.meiw_bus_edin = 0x0; + reg_ctl->dtrns_map.bsw_bus_edin = 0x7; + reg_ctl->dtrns_map.lktr_bus_edin = 0x0; + reg_ctl->dtrns_map.roir_bus_edin = 0x0; + reg_ctl->dtrns_map.lktw_bus_edin = 0x0; + reg_ctl->dtrns_map.rec_nfbc_bus_edin = 0x0; + + reg_ctl->dtrns_cfg.axi_brsp_cke = 0x1fff; + reg_ctl->enc_wdg.vs_load_thd = 0x1fffff; + reg_ctl->opt_strg.cke = 1; + reg_ctl->opt_strg.sram_ckg_en = 1; + reg_ctl->opt_strg.rfpr_err_e = 1; + reg_ctl->opt_strg.resetn_hw_en = 1; + + /* enable rdo clk gating */ + { + RK_U32 *rdo_ckg = (RK_U32*)®s->reg_ctl.rdo_ckg_hevc; + + *rdo_ckg = 0xffffffff; + } +} + +static void vepu511_h265_set_prep(void *hal, HalEncTask *task, H265eV511RegSet *regs) +{ + static RK_U32 cu_inter_e[4] = { (3 << 6) | (3 << 3) | (3 << 0), (1 << 6) | (3 << 3) | (3 << 0), + (1 << 6) | (3 << 3) | (3 << 0), (0 << 6) | (3 << 3) | (3 << 0) + }; + static RK_U32 intra_pu4_mode_num[4] = { 2, 1, 1, 1 }; + static RK_U32 intra_pu8_mode_num[4] = { 2, 1, 1, 1 }; + static RK_U32 intra_pu16_mode_num[4] = { 2, 1, 1, 1 }; + static RK_U32 intra_pu32_mode_num[4] = { 2, 1, 1, 1 }; + + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + HevcVepu511Frame *reg_frm = ®s->reg_frm; + HevcVepu511RcRoi *reg_klut = ®s->reg_rc_roi; + H265eSyntax_new *syn = (H265eSyntax_new *)task->syntax.data; + RK_U32 pic_width_align8 = MPP_ALIGN(syn->pp.pic_width, 8); + RK_U32 pic_height_align8 = MPP_ALIGN(syn->pp.pic_height, 8); + RK_U32 pic_wd32 = MPP_ALIGN(syn->pp.pic_width, 32) >> 5; + RK_U32 pic_h32 = MPP_ALIGN(syn->pp.pic_height, 32) >> 5; + + hal_h265e_enter(); + + reg_frm->reg0196_enc_rsl.pic_wd8_m1 = (pic_width_align8 >> 3) - 1; + reg_frm->reg0196_enc_rsl.pic_hd8_m1 = (pic_height_align8 >> 3) - 1; + reg_frm->reg0197_src_fill.pic_wfill = pic_width_align8 - syn->pp.pic_width; + reg_frm->reg0197_src_fill.pic_hfill = pic_height_align8 - syn->pp.pic_height; + + /* H.265 mode */ + reg_frm->reg0192_enc_pic.enc_stnd = 1; + /* current frame will be refered */ + reg_frm->reg0192_enc_pic.cur_frm_ref = !syn->sp.non_reference_flag; + + reg_frm->reg0192_enc_pic.bs_scp = 1; + reg_frm->reg0192_enc_pic.log2_ctu_num_hevc = mpp_ceil_log2(pic_wd32 * pic_h32); + + reg_klut->klut_ofst.chrm_klut_ofst = ((ctx->frame_type == INTRA_FRAME) || + (ctx->cfg->tune.scene_mode != MPP_ENC_SCENE_MODE_IPC)) ? 6 : 9; + + reg_frm->reg0192_enc_pic.rfpr_compress_mode = 0; + reg_frm->reg0192_enc_pic.rec_fbc_dis = 0; + + reg_frm->reg0232_rdo_cfg.chrm_spcl = 0; + + /* + * H265 Max Inter/Intra cu prediction Mode. + * More prediction modes lead to better compression performance but increase computational cycles. + * + * Default speed preset configuration to 0.67 PPC, ~40 FPS for 4K resolution at 500MHz: + * - Set Inter prediction 32/16/8 CUs at 1/3/2 and Intra 32/16/8/4 CUs at 1, + * Maximize the number of modes while ensuring the prediction hierarchy remains unchanged. + * - Set cime_fuse = 1, disable dual-window search for higher real-time performance. + * - Set fme_lvl_mrg = 1, enable FME's depth1 and depth2 joint search, + * improves real-time performance but will reduce the compression ratio. + * - Set cime_srch_lftw/rgtw/uph/dwnh = 12/12/15/15, expand CIME search range degraded real-time performance. + * - Set rime_prelvl_en = 0, disable RIME pre-level to improve real-time performance. + * - Set fmdc_adju_split32 = 0, enable CU32 block prediction. + * Setting fmdc_adju_split32 = 1 restricts prediction to CU16/8 only, improving real-time performance. + */ + reg_frm->reg0232_rdo_cfg.cu_inter_e = (3 << 6) | (3 << 3) | (3 << 0); + reg_frm->reg0233_rdo_intra_mode.intra_pu4_mode_num = 2; + reg_frm->reg0233_rdo_intra_mode.intra_pu8_mode_num = 2; + reg_frm->reg0233_rdo_intra_mode.intra_pu16_mode_num = 2; + reg_frm->reg0233_rdo_intra_mode.intra_pu32_mode_num = 2; + + if (ctx->frame_type == INTER_P_FRAME) { + RK_U32 speed_idx = ctx->cfg->tune.speed; + + // 0 - 0.63ppc; 1 - 0.68ppc; 2 - 0.69ppc; 3 - 0.7ppc + reg_frm->reg0232_rdo_cfg.cu_inter_e = cu_inter_e[speed_idx]; + reg_frm->reg0233_rdo_intra_mode.intra_pu4_mode_num = intra_pu4_mode_num[speed_idx]; + reg_frm->reg0233_rdo_intra_mode.intra_pu8_mode_num = intra_pu8_mode_num[speed_idx]; + reg_frm->reg0233_rdo_intra_mode.intra_pu16_mode_num = intra_pu16_mode_num[speed_idx]; + reg_frm->reg0233_rdo_intra_mode.intra_pu32_mode_num = intra_pu32_mode_num[speed_idx]; + } + + if (syn->pp.num_long_term_ref_pics_sps) { + reg_frm->reg0232_rdo_cfg.ltm_col = 0; + reg_frm->reg0232_rdo_cfg.ltm_idx0l0 = 1; + } else { + reg_frm->reg0232_rdo_cfg.ltm_col = 0; + reg_frm->reg0232_rdo_cfg.ltm_idx0l0 = 0; + } + + reg_frm->reg0232_rdo_cfg.ccwa_e = 1; + reg_frm->reg0232_rdo_cfg.scl_lst_sel = syn->pp.scaling_list_enabled_flag; + + { + RK_U32 i_nal_type = 0; + + if (ctx->frame_type == INTRA_FRAME) + i_nal_type = NAL_IDR_W_RADL; + else if (ctx->frame_type == INTER_P_FRAME) + i_nal_type = NAL_TRAIL_R; + else + i_nal_type = NAL_TRAIL_R; + + reg_frm->reg0236_synt_nal.nal_unit_type = i_nal_type; + } +} + +static void vepu511_h265_set_split(H265eV511RegSet *regs, MppEncCfgSet *enc_cfg) +{ + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h265e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_frm.reg0216_sli_splt.sli_splt = 0; + regs->reg_frm.reg0216_sli_splt.sli_splt_mode = 0; + regs->reg_frm.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_frm.reg0216_sli_splt.sli_max_num_m1 = 0; + regs->reg_frm.reg0216_sli_splt.sli_flsh = 0; + regs->reg_frm.reg0218_sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.reg0217_sli_byte.sli_splt_byte = 0; + regs->reg_frm.reg0192_enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_frm.reg0216_sli_splt.sli_splt = 1; + regs->reg_frm.reg0216_sli_splt.sli_splt_mode = 0; + regs->reg_frm.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_frm.reg0216_sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.reg0216_sli_splt.sli_flsh = 1; + regs->reg_frm.reg0218_sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.reg0217_sli_byte.sli_splt_byte = cfg->split_arg; + regs->reg_frm.reg0192_enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = (cfg->split_out != 0) ? 1 : 0; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + regs->reg_frm.reg0216_sli_splt.sli_splt = 1; + regs->reg_frm.reg0216_sli_splt.sli_splt_mode = 1; + regs->reg_frm.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_frm.reg0216_sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.reg0216_sli_splt.sli_flsh = 1; + regs->reg_frm.reg0218_sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg_frm.reg0217_sli_byte.sli_splt_byte = 0; + regs->reg_frm.reg0192_enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = (cfg->split_out != 0) ? 1 : 0; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu511_h265_set_me_regs(H265eV511HalContext *ctx, H265eSyntax_new *syn, H265eV511RegSet *regs) +{ + HevcVepu511Param *s = ®s->reg_param; + HevcVepu511Frame *reg_frm = ®s->reg_frm; + + reg_frm->reg0220_me_rnge.cime_srch_dwnh = 15; + reg_frm->reg0220_me_rnge.cime_srch_uph = 15; + reg_frm->reg0220_me_rnge.cime_srch_rgtw = 12; + reg_frm->reg0220_me_rnge.cime_srch_lftw = 12; + reg_frm->reg0221_me_cfg.rme_srch_h = 3; + reg_frm->reg0221_me_cfg.rme_srch_v = 3; + reg_frm->reg0221_me_cfg.srgn_max_num = 72; + reg_frm->reg0221_me_cfg.cime_dist_thre = 1024; + reg_frm->reg0221_me_cfg.rme_dis = 0; + reg_frm->reg0221_me_cfg.fme_dis = 0; + reg_frm->reg0220_me_rnge.dlt_frm_num = 0; + + if (syn->pp.sps_temporal_mvp_enabled_flag && (ctx->frame_type != INTRA_FRAME)) { + if (ctx->last_frame_type == INTRA_FRAME) + reg_frm->reg0222_me_cach.colmv_load = 0; + else + reg_frm->reg0222_me_cach.colmv_load = 1; + + reg_frm->reg0222_me_cach.colmv_stor = 1; + } + + reg_frm->reg0222_me_cach.cime_zero_thre = 64; + reg_frm->reg0222_me_cach.fme_prefsu_en = 0; + + /* CIME: 0x1760 - 0x176C */ + s->me_sqi_cfg.cime_pmv_num = 1; + s->me_sqi_cfg.cime_fuse = 0; + s->me_sqi_cfg.move_lambda = 2; + s->me_sqi_cfg.rime_lvl_mrg = 0; + s->me_sqi_cfg.rime_prelvl_en = 3; + s->me_sqi_cfg.rime_prersu_en = 0; + s->me_sqi_cfg.fme_lvl_mrg = 0; + + s->cime_mvd_th.cime_mvd_th0 = 8; + s->cime_mvd_th.cime_mvd_th1 = 20; + s->cime_mvd_th.cime_mvd_th2 = 32; + s->cime_madp_th.cime_madp_th = 16; + s->cime_madp_th.ratio_consi_cfg = 8; + s->cime_madp_th.ratio_bmv_dist = 8; + s->cime_multi.cime_multi0 = 8; + s->cime_multi.cime_multi1 = 12; + s->cime_multi.cime_multi2 = 16; + s->cime_multi.cime_multi3 = 20; + + /* RFME: 0x1770 - 0x177C */ + s->rime_mvd_th.rime_mvd_th0 = 1; + s->rime_mvd_th.rime_mvd_th1 = 2; + s->rime_mvd_th.fme_madp_th = 10; + s->rime_madp_th.rime_madp_th0 = 8; + s->rime_madp_th.rime_madp_th1 = 16; + s->rime_multi.rime_multi0 = 4; + s->rime_multi.rime_multi1 = 8; + s->rime_multi.rime_multi2 = 12; + s->cmv_st_th.cmv_th0 = 64; + s->cmv_st_th.cmv_th1 = 96; + s->cmv_st_th.cmv_th2 = 128; + + if (ctx->cfg->tune.scene_mode != MPP_ENC_SCENE_MODE_IPC) { + s->me_sqi_cfg.move_lambda = 8; + s->cime_madp_th.cime_madp_th = 0; + s->rime_madp_th.rime_madp_th0 = 0; + s->rime_madp_th.rime_madp_th1 = 0; + s->cime_multi.cime_multi0 = 4; + s->cime_multi.cime_multi1 = 4; + s->cime_multi.cime_multi2 = 4; + s->cime_multi.cime_multi3 = 4; + s->rime_multi.rime_multi0 = 4; + s->rime_multi.rime_multi1 = 4; + s->rime_multi.rime_multi2 = 4; + } else if (ctx->smart_en) { + s->cime_multi.cime_multi0 = 4; + s->cime_multi.cime_multi1 = 6; + s->cime_multi.cime_multi2 = 8; + s->cime_multi.cime_multi3 = 12; + s->rime_multi.rime_multi0 = 4; + s->rime_multi.rime_multi1 = 4; + s->rime_multi.rime_multi2 = 4; + } +} + +static void vepu511_h265_set_hw_address(H265eV511HalContext *ctx, HevcVepu511Frame *regs, + HalEncTask *task) +{ + HalEncTask *enc_task = task; + HalBuf *recon_buf, *ref_buf; + MppBuffer md_info_buf = enc_task->md_info; + Vepu511H265eFrmCfg *frm = ctx->frm; + H265eSyntax_new *syn = ctx->syn; + + hal_h265e_enter(); + + regs->reg0160_adr_src0 = mpp_buffer_get_fd(enc_task->input); + regs->reg0161_adr_src1 = regs->reg0160_adr_src0; + regs->reg0162_adr_src2 = regs->reg0160_adr_src0; + + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_curr_idx); + ref_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_refr_idx); + + if (!syn->sp.non_reference_flag) { + regs->reg0163_rfpw_h_addr = mpp_buffer_get_fd(recon_buf->buf[0]); + regs->reg0164_rfpw_b_addr = regs->reg0163_rfpw_h_addr; + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, ctx->fbc_header_len); + } + regs->reg0165_rfpr_h_addr = mpp_buffer_get_fd(ref_buf->buf[0]); + regs->reg0166_rfpr_b_addr = regs->reg0165_rfpr_h_addr; + regs->reg0167_cmvw_addr = mpp_buffer_get_fd(recon_buf->buf[2]); + regs->reg0168_cmvr_addr = mpp_buffer_get_fd(ref_buf->buf[2]); + regs->reg0169_dspw_addr = mpp_buffer_get_fd(recon_buf->buf[1]); + regs->reg0170_dspr_addr = mpp_buffer_get_fd(ref_buf->buf[1]); + + mpp_dev_multi_offset_update(ctx->reg_cfg, 166, ctx->fbc_header_len); + + if (md_info_buf) { + regs->reg0192_enc_pic.mei_stor = 1; + regs->reg0171_meiw_addr = mpp_buffer_get_fd(md_info_buf); + } else { + regs->reg0192_enc_pic.mei_stor = 0; + regs->reg0171_meiw_addr = 0; + } + + regs->reg0172_bsbt_addr = mpp_buffer_get_fd(enc_task->output); + /* TODO: stream size relative with syntax */ + regs->reg0173_bsbb_addr = regs->reg0172_bsbt_addr; + regs->reg0175_bsbr_addr = regs->reg0172_bsbt_addr; + regs->reg0174_bsbs_addr = regs->reg0172_bsbt_addr; + + regs->reg0180_adr_rfpt_h = 0xffffffff; + regs->reg0181_adr_rfpb_h = 0; + regs->reg0182_adr_rfpt_b = 0xffffffff; + regs->reg0183_adr_rfpb_b = 0; + regs->reg0186_adr_roir = 0; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 174, mpp_packet_get_length(task->packet)); + mpp_dev_multi_offset_update(ctx->reg_cfg, 172, mpp_buffer_get_size(enc_task->output)); + + regs->reg0204_pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg0204_pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + /* smear bufs */ + regs->reg0184_adr_smr_rd = mpp_buffer_get_fd(ref_buf->buf[3]); + regs->reg0185_adr_smr_wr = mpp_buffer_get_fd(recon_buf->buf[3]); +} + +static void vepu511_h265_set_pp_regs(H265eV511RegSet *regs, VepuFmtCfg *fmt, + MppEncPrepCfg *prep_cfg, HalEncTask *task) +{ + Vepu511ControlCfg *reg_ctl = ®s->reg_ctl; + HevcVepu511Frame *reg_frm = ®s->reg_frm; + RK_S32 stridey = 0; + RK_S32 stridec = 0; + + reg_ctl->dtrns_map.src_bus_edin = fmt->src_endian; + reg_frm->reg0198_src_fmt.src_cfmt = fmt->format; + reg_frm->reg0198_src_fmt.alpha_swap = fmt->alpha_swap; + reg_frm->reg0198_src_fmt.rbuv_swap = fmt->rbuv_swap; + reg_frm->reg0198_src_fmt.out_fmt = (fmt->format == VEPU5xx_FMT_YUV400) ? 0 : 1; + reg_frm->reg0203_src_proc.src_mirr = prep_cfg->mirroring > 0; + reg_frm->reg0203_src_proc.src_rot = prep_cfg->rotation; + + if (MPP_FRAME_FMT_IS_FBC(prep_cfg->format)) { + reg_frm->reg0203_src_proc.rkfbcd_en = 1; + + stridey = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!stridey) + stridey = MPP_ALIGN(prep_cfg->hor_stride, 64) >> 2; + } else if (prep_cfg->hor_stride) + stridey = prep_cfg->hor_stride; + else { + if (reg_frm->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_BGRA8888) + stridey = prep_cfg->width * 4; + else if (reg_frm->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_BGR888) + stridey = prep_cfg->width * 3; + else if (reg_frm->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_BGR565 || + reg_frm->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_YUYV422 || + reg_frm->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_UYVY422) + stridey = prep_cfg->width * 2; + } + + switch (fmt->format) { + case VEPU5xx_FMT_YUV444SP : { + stridec = stridey * 2; + } break; + case VEPU5xx_FMT_YUV422SP : + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV444P : { + stridec = stridey; + } break; + default : { + stridec = stridey / 2; + } break; + } + + if (reg_frm->reg0198_src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + reg_frm->reg0199_src_udfy.csc_wgt_r2y = 77; + reg_frm->reg0199_src_udfy.csc_wgt_g2y = 150; + reg_frm->reg0199_src_udfy.csc_wgt_b2y = 29; + + reg_frm->reg0200_src_udfu.csc_wgt_r2u = -43; + reg_frm->reg0200_src_udfu.csc_wgt_g2u = -85; + reg_frm->reg0200_src_udfu.csc_wgt_b2u = 128; + + reg_frm->reg0201_src_udfv.csc_wgt_r2v = 128; + reg_frm->reg0201_src_udfv.csc_wgt_g2v = -107; + reg_frm->reg0201_src_udfv.csc_wgt_b2v = -21; + + reg_frm->reg0202_src_udfo.csc_ofst_y = 0; + reg_frm->reg0202_src_udfo.csc_ofst_u = 128; + reg_frm->reg0202_src_udfo.csc_ofst_v = 128; + } + + reg_frm->reg0205_src_strd0.src_strd0 = stridey; + reg_frm->reg0206_src_strd1.src_strd1 = stridec; +} + +static void vepu511_h265_set_vsp_filtering(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + HevcVepu511Frame *s = ®s->reg_frm; + MppEncCfgSet *cfg = ctx->cfg; + MppEncHwCfg *hw = &cfg->hw; + RK_U8 bit_chg_lvl = ctx->last_frame_fb.tgt_sub_real_lvl[5]; /* [0, 2] */ + RK_U8 corner_str = 0, edge_str = 0, internal_str = 0; /* [0, 3] */ + + if (cfg->tune.deblur_en && (cfg->tune.deblur_str % 2 == 0) && + (hw->flt_str_i == 0) && (hw->flt_str_p == 0)) { + if (bit_chg_lvl == 2 && ctx->frame_type != INTRA_FRAME) { + corner_str = 3; + edge_str = 3; + internal_str = 3; + } else if (bit_chg_lvl > 0) { + corner_str = 2; + edge_str = 2; + internal_str = 2; + } + } else { + if (ctx->frame_type == INTRA_FRAME) { + corner_str = hw->flt_str_i; + edge_str = hw->flt_str_i; + internal_str = hw->flt_str_i; + } else { + corner_str = hw->flt_str_p; + edge_str = hw->flt_str_p; + internal_str = hw->flt_str_p; + } + } + + s->reg0207_src_flt_cfg.pp_corner_filter_strength = corner_str; + s->reg0207_src_flt_cfg.pp_edge_filter_strength = edge_str; + s->reg0207_src_flt_cfg.pp_internal_filter_strength = internal_str; +} + +static void vepu511_h265_set_rc_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs, + HalEncTask *task) +{ + H265eSyntax_new *syn = (H265eSyntax_new *)task->syntax.data; + EncRcTaskInfo *rc_cfg = &task->rc_task->info; + HevcVepu511Frame *reg_frm = ®s->reg_frm; + HevcVepu511RcRoi *reg_rc = ®s->reg_rc_roi; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + MppEncH265Cfg *h265 = &cfg->h265; + RK_S32 mb_wd32 = (syn->pp.pic_width + 31) / 32; + RK_S32 mb_h32 = (syn->pp.pic_height + 31) / 32; + + RK_U32 ctu_target_bits_mul_16 = (rc_cfg->bit_target << 4) / (mb_wd32 * mb_h32); + RK_U32 ctu_target_bits; + RK_S32 negative_bits_thd, positive_bits_thd; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + reg_frm->reg0192_enc_pic.pic_qp = rc_cfg->quality_target; + reg_frm->reg0240_synt_sli1.sli_qp = rc_cfg->quality_target; + + reg_frm->reg213_rc_qp.rc_max_qp = rc_cfg->quality_target; + reg_frm->reg213_rc_qp.rc_min_qp = rc_cfg->quality_target; + reg_frm->reg212_rc_cfg.rc_ctu_num = 1; + } else { + if (ctu_target_bits_mul_16 >= 0x100000) + ctu_target_bits_mul_16 = 0x50000; + ctu_target_bits = (ctu_target_bits_mul_16 * mb_wd32) >> 4; + negative_bits_thd = 0 - 5 * ctu_target_bits / 16; + positive_bits_thd = 5 * ctu_target_bits / 16; + + reg_frm->reg0192_enc_pic.pic_qp = rc_cfg->quality_target; + reg_frm->reg0240_synt_sli1.sli_qp = rc_cfg->quality_target; + reg_frm->reg212_rc_cfg.rc_en = 1; + reg_frm->reg212_rc_cfg.aq_en = 1; + reg_frm->reg212_rc_cfg.rc_ctu_num = mb_wd32; + reg_frm->reg213_rc_qp.rc_max_qp = rc_cfg->quality_max; + reg_frm->reg213_rc_qp.rc_min_qp = rc_cfg->quality_min; + reg_frm->reg214_rc_tgt.ctu_ebit = ctu_target_bits_mul_16; + + if (ctx->smart_en) { + reg_frm->reg213_rc_qp.rc_qp_range = 0; + } else { + reg_frm->reg213_rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? + hw->qp_delta_row_i : hw->qp_delta_row; + } + + { + /* fixed frame qp */ + RK_S32 fqp_min, fqp_max; + + if (ctx->frame_type == INTRA_FRAME) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 0) && (fqp_max <= 51)) { + reg_frm->reg0192_enc_pic.pic_qp = fqp_min; + reg_frm->reg0240_synt_sli1.sli_qp = fqp_min; + reg_frm->reg213_rc_qp.rc_qp_range = 0; + } + } + + reg_rc->rc_dthd_0_8[0] = 2 * negative_bits_thd; + reg_rc->rc_dthd_0_8[1] = negative_bits_thd; + reg_rc->rc_dthd_0_8[2] = positive_bits_thd; + reg_rc->rc_dthd_0_8[3] = 2 * positive_bits_thd; + reg_rc->rc_dthd_0_8[4] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[5] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[6] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[7] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[8] = 0x7FFFFFFF; + + reg_rc->rc_adj0.qp_adj0 = -2; + reg_rc->rc_adj0.qp_adj1 = -1; + reg_rc->rc_adj0.qp_adj2 = 0; + reg_rc->rc_adj0.qp_adj3 = 1; + reg_rc->rc_adj0.qp_adj4 = 2; + reg_rc->rc_adj1.qp_adj5 = 0; + reg_rc->rc_adj1.qp_adj6 = 0; + reg_rc->rc_adj1.qp_adj7 = 0; + reg_rc->rc_adj1.qp_adj8 = 0; + + reg_rc->roi_qthd0.qpmin_area0 = h265->qpmin_map[0] > 0 ? h265->qpmin_map[0] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area0 = h265->qpmax_map[0] > 0 ? h265->qpmax_map[0] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area1 = h265->qpmin_map[1] > 0 ? h265->qpmin_map[1] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area1 = h265->qpmax_map[1] > 0 ? h265->qpmax_map[1] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area2 = h265->qpmin_map[2] > 0 ? h265->qpmin_map[2] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area2 = h265->qpmax_map[2] > 0 ? h265->qpmax_map[2] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area3 = h265->qpmin_map[3] > 0 ? h265->qpmin_map[3] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area3 = h265->qpmax_map[3] > 0 ? h265->qpmax_map[3] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area4 = h265->qpmin_map[4] > 0 ? h265->qpmin_map[4] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area4 = h265->qpmax_map[4] > 0 ? h265->qpmax_map[4] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area5 = h265->qpmin_map[5] > 0 ? h265->qpmin_map[5] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area5 = h265->qpmax_map[5] > 0 ? h265->qpmax_map[5] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area6 = h265->qpmin_map[6] > 0 ? h265->qpmin_map[6] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area6 = h265->qpmax_map[6] > 0 ? h265->qpmax_map[6] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area7 = h265->qpmin_map[7] > 0 ? h265->qpmin_map[7] : rc_cfg->quality_min; + reg_rc->roi_qthd3.qpmax_area7 = h265->qpmax_map[7] > 0 ? h265->qpmax_map[7] : rc_cfg->quality_max; + } +} + +static void vepu511_h265_set_quant_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + HevcVepu511Param *s = ®s->reg_param; + RK_U8 th0 = 3, th1 = 6, th2 = 13; + RK_U16 bias_i0 = 171, bias_i1 = 171, bias_i2 = 171, bias_i3 = 171; + RK_U16 bias_p0 = 85, bias_p1 = 85, bias_p2 = 85, bias_p3 = 85; + RK_U32 frm_type = ctx->frame_type; + + if (!hw->qbias_en) { + if (ctx->smart_en) { + bias_i0 = bias_i1 = bias_i3 = 144; + bias_i2 = (frm_type == INTRA_FRAME) ? 144 : 171; + } else { + bias_i0 = bias_i1 = bias_i3 = 171; + bias_i2 = (frm_type == INTRA_FRAME) ? 171 : 220; + } + + /* used for venc_info log */ + hw->qbias_arr[IFRAME_THD0] = hw->qbias_arr[PFRAME_THD0] = th0; + hw->qbias_arr[IFRAME_THD1] = hw->qbias_arr[PFRAME_THD1] = th1; + hw->qbias_arr[IFRAME_THD2] = hw->qbias_arr[PFRAME_THD2] = th2; + hw->qbias_arr[IFRAME_BIAS0] = hw->qbias_arr[PFRAME_IBLK_BIAS0] = bias_i0; + hw->qbias_arr[IFRAME_BIAS1] = hw->qbias_arr[PFRAME_IBLK_BIAS1] = bias_i1; + hw->qbias_arr[IFRAME_BIAS2] = hw->qbias_arr[PFRAME_IBLK_BIAS2] = bias_i2; + hw->qbias_arr[IFRAME_BIAS3] = hw->qbias_arr[PFRAME_IBLK_BIAS3] = bias_i3; + hw->qbias_arr[PFRAME_PBLK_BIAS0] = bias_p0; + hw->qbias_arr[PFRAME_PBLK_BIAS1] = bias_p1; + hw->qbias_arr[PFRAME_PBLK_BIAS2] = bias_p2; + hw->qbias_arr[PFRAME_PBLK_BIAS3] = bias_p3; + } else { + if (frm_type == INTRA_FRAME) { + th0 = hw->qbias_arr[IFRAME_THD0]; + th1 = hw->qbias_arr[IFRAME_THD1]; + th2 = hw->qbias_arr[IFRAME_THD2]; + bias_i0 = hw->qbias_arr[IFRAME_BIAS0]; + bias_i1 = hw->qbias_arr[IFRAME_BIAS1]; + bias_i2 = hw->qbias_arr[IFRAME_BIAS2]; + bias_i3 = hw->qbias_arr[IFRAME_BIAS3]; + } else { + th0 = hw->qbias_arr[PFRAME_THD0]; + th1 = hw->qbias_arr[PFRAME_THD1]; + th2 = hw->qbias_arr[PFRAME_THD2]; + bias_i0 = hw->qbias_arr[PFRAME_IBLK_BIAS0]; + bias_i1 = hw->qbias_arr[PFRAME_IBLK_BIAS1]; + bias_i2 = hw->qbias_arr[PFRAME_IBLK_BIAS2]; + bias_i3 = hw->qbias_arr[PFRAME_IBLK_BIAS3]; + bias_p0 = hw->qbias_arr[PFRAME_PBLK_BIAS0]; + bias_p1 = hw->qbias_arr[PFRAME_PBLK_BIAS1]; + bias_p2 = hw->qbias_arr[PFRAME_PBLK_BIAS2]; + bias_p3 = hw->qbias_arr[PFRAME_PBLK_BIAS3]; + } + } + + s->bias_madi_thd_comb.bias_madi_th0 = th0; + s->bias_madi_thd_comb.bias_madi_th1 = th1; + s->bias_madi_thd_comb.bias_madi_th2 = th2; + s->qnt0_i_bias_comb.bias_i_val0 = bias_i0; + s->qnt0_i_bias_comb.bias_i_val1 = bias_i1; + s->qnt0_i_bias_comb.bias_i_val2 = bias_i2; + s->qnt1_i_bias_comb.bias_i_val3 = bias_i3; + s->qnt0_p_bias_comb.bias_p_val0 = bias_p0; + s->qnt0_p_bias_comb.bias_p_val1 = bias_p1; + s->qnt0_p_bias_comb.bias_p_val2 = bias_p2; + s->qnt1_p_bias_comb.bias_p_val3 = bias_p3; +} + +static void vepu511_h265_set_atr_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + HevcVepu511Sqi *s = ®s->reg_sqi; + RK_U32 str = ctx->frame_type == INTRA_FRAME ? + ctx->cfg->tune.atr_str_i : ctx->cfg->tune.atr_str_p; + + /* 0 - disable; 1 - weak; 2 - medium; 3 - strong */ + if (str == 0) { + s->block_opt_cfg.block_en = 0; /* block_en and cmplx_en are not used so far(20240708) */ + s->cmplx_opt_cfg.cmplx_en = 0; + s->line_opt_cfg.line_en = 0; + } else { + s->block_opt_cfg.block_en = 0; + s->cmplx_opt_cfg.cmplx_en = 0; + s->line_opt_cfg.line_en = 1; + } + + if (str == 3) { + s->block_opt_cfg.block_thre_cst_best_mad = 1000; + s->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + s->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + s->block_opt_cfg.block_delta_qp_flag = 3; + + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 4; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 255; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 255; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 7; + + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 60; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 60; + + s->subj_opt_dqp0.line_thre_qp = 25; + s->subj_opt_dqp0.block_strength = 4; + s->subj_opt_dqp0.block_thre_qp = 30; + s->subj_opt_dqp0.cmplx_strength = 4; + s->subj_opt_dqp0.cmplx_thre_qp = 34; + s->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + + s->subj_opt_rdo_split.line_rdo_split_rcoef_d0 = 11; + s->subj_opt_rdo_split.line_rdo_split_rcoef_d1 = 12; + } else if (str == 2) { + s->block_opt_cfg.block_thre_cst_best_mad = 1000; + s->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + s->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + s->block_opt_cfg.block_delta_qp_flag = 3; + + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 4; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 30; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 30; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 6; + + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 50; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 50; + + s->subj_opt_dqp0.line_thre_qp = 30; + s->subj_opt_dqp0.block_strength = 4; + s->subj_opt_dqp0.block_thre_qp = 30; + s->subj_opt_dqp0.cmplx_strength = 4; + s->subj_opt_dqp0.cmplx_thre_qp = 34; + s->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + + s->subj_opt_rdo_split.line_rdo_split_rcoef_d0 = 11; + s->subj_opt_rdo_split.line_rdo_split_rcoef_d1 = 13; + } else { + s->block_opt_cfg.block_thre_cst_best_mad = 1000; + s->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + s->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + s->block_opt_cfg.block_delta_qp_flag = 3; + + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 6000; + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 300; + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 1280; + + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 512; + + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 3; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 20; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 20; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 8; + + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 60; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 60; + + s->subj_opt_dqp0.line_thre_qp = 30; + s->subj_opt_dqp0.block_strength = 4; + s->subj_opt_dqp0.block_thre_qp = 30; + s->subj_opt_dqp0.cmplx_strength = 4; + s->subj_opt_dqp0.cmplx_thre_qp = 34; + s->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + + s->subj_opt_rdo_split.line_rdo_split_rcoef_d0 = 11; + s->subj_opt_rdo_split.line_rdo_split_rcoef_d1 = 13; + } +} + +static void vepu511_h265_set_smear_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + HevcVepu511Sqi *s = ®s->reg_sqi; + RK_S32 frm_num = ctx->frame_num; + RK_S32 gop = (ctx->cfg->rc.gop > 0) ? ctx->cfg->rc.gop : 1; //TODO: gop = 0 + RK_U32 cover_num = ctx->last_frame_fb.acc_cover16_num; + RK_U32 bndry_num = ctx->last_frame_fb.acc_bndry16_num; + RK_U32 st_ctu_num = ctx->last_frame_fb.st_ctu_num; + RK_S32 deblur_en = ctx->cfg->tune.deblur_en; + RK_S32 str = ctx->cfg->tune.deblur_str; + RK_S16 flag_cover = 0; + RK_S16 flag_bndry = 0; + + static RK_U8 qp_strength[H265E_SMEAR_STR_NUM] = { 5, 5, 5, 5, 5, 5, 5, 5 }; + static RK_U8 smear_strength[H265E_SMEAR_STR_NUM] = { 3, 3, 3, 3, 3, 3, 3, 3 }; + static RK_U8 bndry_intra_r_dep0[H265E_SMEAR_STR_NUM] = { 24, 24, 24, 24, 24, 24, 24, 24 }; + static RK_U8 bndry_intra_r_dep1[H265E_SMEAR_STR_NUM] = { 24, 24, 24, 24, 24, 24, 24, 24 }; + + static RK_U8 flag_cover_thd0[H265E_SMEAR_STR_NUM] = { 12, 13, 13, 17, 12, 13, 13, 17 }; + static RK_U8 flag_cover_thd1[H265E_SMEAR_STR_NUM] = { 61, 70, 70, 90, 61, 70, 70, 90 }; + static RK_U8 flag_bndry_thd0[H265E_SMEAR_STR_NUM] = { 12, 12, 12, 12, 12, 12, 12, 12 }; + static RK_U8 flag_bndry_thd1[H265E_SMEAR_STR_NUM] = { 73, 73, 73, 73, 73, 73, 73, 73 }; + + static RK_U8 smear_cfc_en[H265E_SMEAR_STR_NUM] = {0, 0, 1, 1, 0, 0, 1, 1}; + static RK_U8 thre_dsp_mov[H265E_SMEAR_STR_NUM] = {15, 15, 46, 46, 15, 15, 46, 46}; + static RK_U8 thre_madp_mov_dep0[H265E_SMEAR_STR_NUM] = {16, 16, 48, 48, 16, 16, 48, 48}; + static RK_U8 thre_madp_mov_dep1[H265E_SMEAR_STR_NUM] = {18, 18, 50, 50, 18, 18, 50, 50}; + static RK_U8 thre_madp_mov_dep2[H265E_SMEAR_STR_NUM] = {20, 20, 52, 52, 20, 20, 52, 52}; + static RK_U8 thre_madp_stc_cover0[H265E_SMEAR_STR_NUM] = { 20, 22, 22, 22, 20, 22, 22, 30 }; + static RK_U8 thre_madp_stc_cover1[H265E_SMEAR_STR_NUM] = { 20, 22, 22, 22, 20, 22, 22, 30 }; + + static RK_S8 flag_cover_wgt[3] = { 1, 0, -3 }; + static RK_S8 flag_bndry_wgt[3] = { 0, 0, 0 }; + static RK_S8 flag_bndry_intra_wgt0[3] = { -12, 0, 12 }; + static RK_S8 flag_bndry_intra_wgt1[3] = { -12, 0, 12 }; + + flag_cover = (cover_num * 1000 < flag_cover_thd0[str] * st_ctu_num) ? 0 : + (cover_num * 1000 < flag_cover_thd1[str] * st_ctu_num) ? 1 : 2; + + flag_bndry = (bndry_num * 1000 < flag_bndry_thd0[str] * st_ctu_num) ? 0 : + (bndry_num * 1000 < flag_bndry_thd1[str] * st_ctu_num) ? 1 : 2; + + /* anti smear */ + s->smear_opt_cfg0.anti_smear_en = deblur_en; + s->smear_opt_cfg0.smear_strength = (smear_strength[str] > 2) ? + (smear_strength[str] + flag_bndry_wgt[flag_bndry]) : smear_strength[str]; + + s->smear_opt_cfg0.thre_mv_inconfor_cime = 8; + s->smear_opt_cfg0.thre_mv_confor_cime = 0; + s->smear_opt_cfg0.thre_mv_inconfor_cime_gmv = 8; + s->smear_opt_cfg0.thre_mv_confor_cime_gmv = 0; + s->smear_opt_cfg0.thre_num_mv_confor_cime = 3; + s->smear_opt_cfg0.thre_num_mv_confor_cime_gmv = 2; + s->smear_opt_cfg0.frm_static = 1; + s->smear_opt_cfg0.smear_cfc_en = smear_cfc_en[str]; + + s->smear_opt_cfg0.smear_load_en = ((frm_num % gop == 0) || + (s->smear_opt_cfg0.frm_static == 0) || (frm_num % gop == 1)) ? 0 : 1; + s->smear_opt_cfg0.smear_stor_en = ((frm_num % gop == 0) || + (s->smear_opt_cfg0.frm_static == 0) || (frm_num % gop == gop - 1)) ? 0 : 1; + + s->smear_opt_cfg1.dist0_frm_avg = 0; + s->smear_opt_cfg1.thre_dsp_static = 10; + s->smear_opt_cfg1.thre_dsp_mov = thre_dsp_mov[str]; + s->smear_opt_cfg1.thre_dist_mv_confor_cime = 32; + + s->smear_madp_thd.thre_madp_stc_dep0 = 10; + s->smear_madp_thd.thre_madp_stc_dep1 = 8; + s->smear_madp_thd.thre_madp_stc_dep2 = 8; + s->smear_madp_thd.thre_madp_mov_dep0 = thre_madp_mov_dep0[str]; + s->smear_madp_thd.thre_madp_mov_dep1 = thre_madp_mov_dep1[str]; + s->smear_madp_thd.thre_madp_mov_dep2 = thre_madp_mov_dep2[str]; + + s->smear_stat_thd.thre_num_pt_stc_dep0 = 47; + s->smear_stat_thd.thre_num_pt_stc_dep1 = 11; + s->smear_stat_thd.thre_num_pt_stc_dep2 = 3; + s->smear_stat_thd.thre_num_pt_mov_dep0 = 47; + s->smear_stat_thd.thre_num_pt_mov_dep1 = 11; + s->smear_stat_thd.thre_num_pt_mov_dep2 = 3; + + s->smear_bmv_dist_thd0.confor_cime_gmv0 = 21; + s->smear_bmv_dist_thd0.confor_cime_gmv1 = 16; + s->smear_bmv_dist_thd0.inconfor_cime_gmv0 = 48; + s->smear_bmv_dist_thd0.inconfor_cime_gmv1 = 34; + + s->smear_bmv_dist_thd1.inconfor_cime_gmv2 = 32; + s->smear_bmv_dist_thd1.inconfor_cime_gmv3 = 29; + s->smear_bmv_dist_thd1.inconfor_cime_gmv4 = 27; + + s->smear_min_bndry_gmv.thre_min_num_confor_csu0_bndry_cime_gmv = 0; + s->smear_min_bndry_gmv.thre_max_num_confor_csu0_bndry_cime_gmv = 3; + s->smear_min_bndry_gmv.thre_min_num_inconfor_csu0_bndry_cime_gmv = 0; + s->smear_min_bndry_gmv.thre_max_num_inconfor_csu0_bndry_cime_gmv = 3; + s->smear_min_bndry_gmv.thre_split_dep0 = 2; + s->smear_min_bndry_gmv.thre_zero_srgn = 8; + s->smear_min_bndry_gmv.madi_thre_dep0 = 22; + s->smear_min_bndry_gmv.madi_thre_dep1 = 18; + + s->smear_madp_cov_thd.thre_madp_stc_cover0 = thre_madp_stc_cover0[str]; + s->smear_madp_cov_thd.thre_madp_stc_cover1 = thre_madp_stc_cover1[str]; + s->smear_madp_cov_thd.thre_madp_mov_cover0 = 12; + s->smear_madp_cov_thd.thre_madp_mov_cover1 = 12; + s->smear_madp_cov_thd.smear_qp_strength = qp_strength[str] + + flag_cover_wgt[flag_cover]; + s->smear_madp_cov_thd.smear_thre_qp = 25; + + s->subj_opt_dqp1.bndry_rdo_mode_intra_jcoef_d0 = bndry_intra_r_dep0[str] + + flag_bndry_intra_wgt0[flag_bndry]; + s->subj_opt_dqp1.bndry_rdo_mode_intra_jcoef_d1 = bndry_intra_r_dep1[str] + + flag_bndry_intra_wgt1[flag_bndry]; + + s->smear_opt_rmd_intra.cover_rmd_mode_intra_jcoef_d0 = 16; + s->smear_opt_rmd_intra.cover_rmd_mode_intra_jcoef_d1 = 16; + s->smear_opt_rmd_intra.cover_rdo_mode_intra_jcoef_d0 = 16; + s->smear_opt_rmd_intra.cover_rdo_mode_intra_jcoef_d1 = 16; + + s->smear_opt_cfg_coef.cfc_rmd_mode_intra_jcoef_d0 = 20; + s->smear_opt_cfg_coef.cfc_rmd_mode_intra_jcoef_d1 = 20; + s->smear_opt_cfg_coef.cfc_rdo_mode_intra_jcoef_d0 = 20; + s->smear_opt_cfg_coef.cfc_rdo_mode_intra_jcoef_d1 = 20; +} + +static void vepu511_h265_set_anti_stripe_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + static RK_U32 pre_i32_cst_thd[3][16] = { + { 4, 14, 4, 3, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5, 28 }, + { 4, 14, 4, 3, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5, 28 }, + { 6, 17, 6, 4, 4, 7, 8, 6, 12, 6, 8, 6, 8, 6, 5, 28 } + }; + + static RK_U32 pre_i32_cst_wgt[3][15] = { + { 19, 17, 18, 17, 13, 8, 14, 10, 13, 8, 14, 10, 17, 17, 17 }, + { 20, 18, 19, 18, 12, 6, 13, 9, 12, 6, 13, 9, 18, 17, 17 }, + { 22, 19, 20, 19, 11, 5, 12, 8, 11, 5, 12, 8, 19, 18, 18 } + }; + + static RK_U32 pre_i16_cst_thd[3][15] = { + { 4, 14, 4, 4, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5 }, + { 4, 14, 4, 4, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5 }, + { 6, 18, 6, 4, 4, 7, 8, 6, 12, 6, 8, 6, 8, 6, 5 } + }; + + static RK_U32 pre_i16_cst_wgt[3][15] = { + { 19, 17, 18, 17, 13, 8, 14, 10, 13, 8, 14, 10, 17, 17, 17 }, + { 20, 18, 19, 18, 12, 6, 13, 9, 12, 6, 13, 9, 18, 17, 17 }, + { 22, 19, 18, 19, 11, 5, 12, 8, 11, 5, 12, 8, 19, 18, 18 } + }; + + HevcVepu511Sqi *s = ®s->reg_sqi; + RK_U32 str = ctx->cfg->tune.atl_str; + RK_U32 str_idx = 0; + RK_U32 idx = 0; + + s->pre_i32_cst_wgt3.anti_strp_e = !!ctx->cfg->tune.atl_str; + + if (str == 0) + return; + + s->pre_i32_cst_wgt3.i32_lambda_mv_bit = 4; + s->pre_i32_cst_wgt3.i16_lambda_mv_bit = 3; + s->pre_i16_cst_wgt3.i8_lambda_mv_bit = 3; + s->pre_i16_cst_wgt3.i4_lambda_mv_bit = 3; + + /* 0 - disable; 1 - weak; 2 - medium; 3 - strong */ + str_idx = str - 1; + for (idx = 0; idx < MPP_ARRAY_ELEMS(s->pre_i32_cst_thd); idx++) + s->pre_i32_cst_thd[idx] = pre_i32_cst_thd[str_idx][idx]; + s->pre_i32_cst_thd3.mode_th = pre_i32_cst_thd[str_idx][14]; + s->pre_i32_cst_thd3.qp_thd = pre_i32_cst_thd[str_idx][15]; + + for (idx = 0; idx < MPP_ARRAY_ELEMS(s->pre_i32_cst_wgt); idx++) + s->pre_i32_cst_wgt[idx] = pre_i32_cst_wgt[str_idx][idx]; + + for (idx = 0; idx < MPP_ARRAY_ELEMS(s->pre_i16_cst_thd); idx++) + s->pre_i16_cst_thd[idx] = pre_i16_cst_thd[str_idx][idx]; + s->pre_i16_cst_thd3.mode_th = pre_i16_cst_thd[str_idx][14]; + + for (idx = 0; idx < MPP_ARRAY_ELEMS(s->pre_i16_cst_wgt); idx++) + s->pre_i16_cst_wgt[idx] = pre_i16_cst_wgt[str_idx][idx]; +} + +static MPP_RET vepu511_h265_set_rdo_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + HevcVepu511RcRoi *reg_rc = ®s->reg_rc_roi; + static RK_U32 fmdc_adju_split32[4] = { 0, 0, 0, 1 }; + static RK_U32 fmdc_adju_intra32[4] = { 0, 0, 15, 0 }; + + reg_rc->cudecis_thd0.base_thre_rough_mad32_intra = 9; + reg_rc->cudecis_thd0.delta0_thre_rough_mad32_intra = 10; + reg_rc->cudecis_thd0.delta1_thre_rough_mad32_intra = 55; + reg_rc->cudecis_thd0.delta2_thre_rough_mad32_intra = 55; + reg_rc->cudecis_thd0.delta3_thre_rough_mad32_intra = 66; + reg_rc->cudecis_thd0.delta4_thre_rough_mad32_intra_low5 = 2; + + reg_rc->cudecis_thd1.delta4_thre_rough_mad32_intra_high2 = 2; + reg_rc->cudecis_thd1.delta5_thre_rough_mad32_intra = 74; + reg_rc->cudecis_thd1.delta6_thre_rough_mad32_intra = 106; + reg_rc->cudecis_thd1.base_thre_fine_mad32_intra = 8; + reg_rc->cudecis_thd1.delta0_thre_fine_mad32_intra = 0; + reg_rc->cudecis_thd1.delta1_thre_fine_mad32_intra = 13; + reg_rc->cudecis_thd1.delta2_thre_fine_mad32_intra_low3 = 6; + + reg_rc->cudecis_thd2.delta2_thre_fine_mad32_intra_high2 = 1; + reg_rc->cudecis_thd2.delta3_thre_fine_mad32_intra = 17; + reg_rc->cudecis_thd2.delta4_thre_fine_mad32_intra = 23; + reg_rc->cudecis_thd2.delta5_thre_fine_mad32_intra = 50; + reg_rc->cudecis_thd2.delta6_thre_fine_mad32_intra = 54; + reg_rc->cudecis_thd2.base_thre_str_edge_mad32_intra = 6; + reg_rc->cudecis_thd2.delta0_thre_str_edge_mad32_intra = 0; + reg_rc->cudecis_thd2.delta1_thre_str_edge_mad32_intra = 0; + + reg_rc->cudecis_thd3.delta2_thre_str_edge_mad32_intra = 3; + reg_rc->cudecis_thd3.delta3_thre_str_edge_mad32_intra = 8; + reg_rc->cudecis_thd3.base_thre_str_edge_bgrad32_intra = 25; + reg_rc->cudecis_thd3.delta0_thre_str_edge_bgrad32_intra = 0; + reg_rc->cudecis_thd3.delta1_thre_str_edge_bgrad32_intra = 0; + reg_rc->cudecis_thd3.delta2_thre_str_edge_bgrad32_intra = 7; + reg_rc->cudecis_thd3.delta3_thre_str_edge_bgrad32_intra = 19; + reg_rc->cudecis_thd3.base_thre_mad16_intra = 6; + reg_rc->cudecis_thd3.delta0_thre_mad16_intra = 0; + + reg_rc->cudecis_thd4.delta1_thre_mad16_intra = 3; + reg_rc->cudecis_thd4.delta2_thre_mad16_intra = 3; + reg_rc->cudecis_thd4.delta3_thre_mad16_intra = 24; + reg_rc->cudecis_thd4.delta4_thre_mad16_intra = 28; + reg_rc->cudecis_thd4.delta5_thre_mad16_intra = 40; + reg_rc->cudecis_thd4.delta6_thre_mad16_intra = 52; + reg_rc->cudecis_thd4.delta0_thre_mad16_ratio_intra = 7; + + reg_rc->cudecis_thd5.delta1_thre_mad16_ratio_intra = 7; + reg_rc->cudecis_thd5.delta2_thre_mad16_ratio_intra = 2; + reg_rc->cudecis_thd5.delta3_thre_mad16_ratio_intra = 2; + reg_rc->cudecis_thd5.delta4_thre_mad16_ratio_intra = 0; + reg_rc->cudecis_thd5.delta5_thre_mad16_ratio_intra = 0; + reg_rc->cudecis_thd5.delta6_thre_mad16_ratio_intra = 0; + reg_rc->cudecis_thd5.delta7_thre_mad16_ratio_intra = 4; + reg_rc->cudecis_thd5.delta0_thre_rough_bgrad32_intra = 1; + reg_rc->cudecis_thd5.delta1_thre_rough_bgrad32_intra = 5; + reg_rc->cudecis_thd5.delta2_thre_rough_bgrad32_intra_low4 = 8; + + reg_rc->cudecis_thd6.delta2_thre_rough_bgrad32_intra_high2 = 2; + reg_rc->cudecis_thd6.delta3_thre_rough_bgrad32_intra = 540; + reg_rc->cudecis_thd6.delta4_thre_rough_bgrad32_intra = 692; + reg_rc->cudecis_thd6.delta5_thre_rough_bgrad32_intra_low10 = 866; + + reg_rc->cudecis_thd7.delta5_thre_rough_bgrad32_intra_high1 = 1; + reg_rc->cudecis_thd7.delta6_thre_rough_bgrad32_intra = 3286; + reg_rc->cudecis_thd7.delta7_thre_rough_bgrad32_intra = 6620; + reg_rc->cudecis_thd7.delta0_thre_bgrad16_ratio_intra = 8; + reg_rc->cudecis_thd7.delta1_thre_bgrad16_ratio_intra_low2 = 3; + + reg_rc->cudecis_thd8.delta1_thre_bgrad16_ratio_intra_high2 = 2; + reg_rc->cudecis_thd8.delta2_thre_bgrad16_ratio_intra = 15; + reg_rc->cudecis_thd8.delta3_thre_bgrad16_ratio_intra = 15; + reg_rc->cudecis_thd8.delta4_thre_bgrad16_ratio_intra = 13; + reg_rc->cudecis_thd8.delta5_thre_bgrad16_ratio_intra = 13; + reg_rc->cudecis_thd8.delta6_thre_bgrad16_ratio_intra = 7; + reg_rc->cudecis_thd8.delta7_thre_bgrad16_ratio_intra = 15; + reg_rc->cudecis_thd8.delta0_thre_fme_ratio_inter = 4; + reg_rc->cudecis_thd8.delta1_thre_fme_ratio_inter = 4; + + reg_rc->cudecis_thd9.delta2_thre_fme_ratio_inter = 3; + reg_rc->cudecis_thd9.delta3_thre_fme_ratio_inter = 2; + reg_rc->cudecis_thd9.delta4_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.delta5_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.delta6_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.delta7_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.base_thre_fme32_inter = 4; + reg_rc->cudecis_thd9.delta0_thre_fme32_inter = 2; + reg_rc->cudecis_thd9.delta1_thre_fme32_inter = 7; + reg_rc->cudecis_thd9.delta2_thre_fme32_inter = 12; + + reg_rc->cudecis_thd10.delta3_thre_fme32_inter = 23; + reg_rc->cudecis_thd10.delta4_thre_fme32_inter = 41; + reg_rc->cudecis_thd10.delta5_thre_fme32_inter = 71; + reg_rc->cudecis_thd10.delta6_thre_fme32_inter = 123; + reg_rc->cudecis_thd10.thre_cme32_inter = 48; + + reg_rc->cudecis_thd11.delta0_thre_mad_fme_ratio_inter = 0; + reg_rc->cudecis_thd11.delta1_thre_mad_fme_ratio_inter = 7; + reg_rc->cudecis_thd11.delta2_thre_mad_fme_ratio_inter = 7; + reg_rc->cudecis_thd11.delta3_thre_mad_fme_ratio_inter = 6; + reg_rc->cudecis_thd11.delta4_thre_mad_fme_ratio_inter = 5; + reg_rc->cudecis_thd11.delta5_thre_mad_fme_ratio_inter = 4; + reg_rc->cudecis_thd11.delta6_thre_mad_fme_ratio_inter = 4; + reg_rc->cudecis_thd11.delta7_thre_mad_fme_ratio_inter = 4; + + reg_rc->cudecis_thd12.delta0_thre_cme32_static_inter = 1; + reg_rc->cudecis_thd12.delta1_thre_cme32_static_inter = 3; + reg_rc->cudecis_thd12.delta2_thre_cme32_static_inter = 6; + reg_rc->cudecis_thd12.delta3_thre_cme32_static_inter = 9; + reg_rc->cudecis_thd12.delta4_thre_cme32_static_inter = 10; + reg_rc->cudecis_thd12.delta5_thre_cme32_static_inter = 11; + reg_rc->cudecis_thd12.delta6_thre_cme32_static_inter = 12; + reg_rc->cudecis_thd12.delta7_thre_cme32_static_inter = 15; + + reg_rc->fmdc_adj1.fmdc_adju_split32 = 0; + reg_rc->fmdc_adj1.fmdc_adju_intra32 = 0; + + if (ctx->frame_type == INTER_P_FRAME) { + RK_U32 speed_idx = ctx->cfg->tune.speed; + + // 0 - 0.63ppc; 1 - 0.68ppc; 2 - 0.69ppc; 3 - 0.7ppc + reg_rc->fmdc_adj1.fmdc_adju_split32 = fmdc_adju_split32[speed_idx]; + reg_rc->fmdc_adj1.fmdc_adju_intra32 = fmdc_adju_intra32[speed_idx]; + + if (speed_idx >= 1) { + reg_rc->cudecis_thd9.base_thre_fme32_inter = 0; + reg_rc->cudecis_thd9.delta0_thre_fme32_inter = 0; + reg_rc->cudecis_thd9.delta1_thre_fme32_inter = 0; + reg_rc->cudecis_thd9.delta2_thre_fme32_inter = 0; + reg_rc->cudecis_thd10.delta3_thre_fme32_inter = 0; + reg_rc->cudecis_thd10.delta4_thre_fme32_inter = 0; + reg_rc->cudecis_thd10.delta5_thre_fme32_inter = 0; + reg_rc->cudecis_thd10.delta6_thre_fme32_inter = 0; + } + } + + return MPP_OK; +} + +static void vepu511_h265_set_sao_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + static const RK_U32 blur_low_madi_thd[2][4] = {{5, 5, 5, 5}, + {4, 4, 4, 4} + }; + static const RK_U32 blur_high_madi_thd[2][4] = {{27, 27, 27, 27}, + {36, 32, 32, 32} + }; + static const RK_U32 blur_low_cnt_thd[2][4] = {{15, 2, 3, 2}, + {4, 4, 3, 3} + }; + static const RK_U32 blur_high_cnt_thd[2][4] = {{15, 2, 3, 2}, + {4, 4, 3, 3} + }; + static const RK_U32 blur_sum_cnt_thd[2][4] = {{15, 10, 10, 8}, + {14, 12, 12, 8} + }; + static const RK_U32 blur_motion_thd[2][4] = {{32, 32, 32, 32}, + {32, 32, 32, 32} + }; + + HevcVepu511Sqi *sqi = ®s->reg_sqi; + RK_U32 mode_idx = (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) ? 0 : 1; + RK_U32 str = ctx->frame_type == INTRA_FRAME ? + ctx->cfg->tune.sao_str_i : ctx->cfg->tune.sao_str_p; + RK_U32 str_idx = 0; + + /* Weight values are set to 4 to disable SAO subjective optimization. + * They are not under the control of anti_blur_en. + */ + sqi->subj_anti_blur_wgt3.merge_cost_dist_eo_wgt0 = 4; + sqi->subj_anti_blur_wgt3.merge_cost_dist_bo_wgt0 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_dist_eo_wgt1 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_dist_bo_wgt1 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_bit_eo_wgt0 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_bit_bo_wgt0 = 4; + + if (str == 0) + return; + + str_idx = str - 1; + sqi->subj_anti_blur_wgt3.merge_cost_dist_eo_wgt0 = 2; + sqi->subj_anti_blur_wgt3.merge_cost_dist_bo_wgt0 = 3; + sqi->subj_anti_blur_wgt4.merge_cost_dist_eo_wgt1 = 8; + sqi->subj_anti_blur_wgt4.merge_cost_dist_bo_wgt1 = 6; + sqi->subj_anti_blur_wgt4.merge_cost_bit_eo_wgt0 = 8; + sqi->subj_anti_blur_wgt4.merge_cost_bit_bo_wgt0 = 6; + + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_eo_wgt0 = 12; + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_bo_wgt0 = 12; + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_eo_wgt1 = 24; + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_bo_wgt1 = 20; + + sqi->subj_anti_blur_wgt1.notmerge_ofst_lambda_eo_wgt0 = 20; + sqi->subj_anti_blur_wgt1.notmerge_ofst_lambda_bo_wgt0 = 20; + sqi->subj_anti_blur_wgt1.notmerge_compare_dist_eo_wgt0 = 12; + sqi->subj_anti_blur_wgt1.notmerge_compare_dist_bo_wgt0 = 12; + + sqi->subj_anti_blur_wgt2.notmerge_compare_dist_eo_wgt1 = 24; + sqi->subj_anti_blur_wgt2.notmerge_compare_dist_bo_wgt1 = 20; + sqi->subj_anti_blur_wgt2.notmerge_compare_rate_eo_wgt0 = 20; + sqi->subj_anti_blur_wgt2.notmerge_compare_rate_bo_wgt0 = 20; + + sqi->subj_anti_blur_wgt3.sao_mode_compare_dist_eo_wgt0 = 24; + sqi->subj_anti_blur_wgt3.sao_mode_compare_dist_bo_wgt0 = 20; + + sqi->subj_anti_blur_thd.anti_blur_en = 1; + sqi->subj_anti_blur_thd.scene_mode = mode_idx; + sqi->subj_anti_blur_sao.sao_ofst_thd_eo_luma = 4; + sqi->subj_anti_blur_sao.sao_ofst_thd_bo_luma = 4; + sqi->subj_anti_blur_sao.sao_ofst_thd_eo_chroma = 4; + sqi->subj_anti_blur_sao.sao_ofst_thd_bo_chroma = 4; + + sqi->subj_anti_blur_thd.blur_low_madi_thd = blur_low_madi_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_high_madi_thd = blur_high_madi_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_low_cnt_thd = blur_low_cnt_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_hight_cnt_thd = blur_high_cnt_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_sum_cnt_thd = blur_sum_cnt_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_sao.blur_motion_thd = blur_motion_thd[mode_idx][str_idx]; +} + +static void vepu511_h265_set_slice_regs(H265eV511HalContext *ctx, H265eSyntax_new *syn, HevcVepu511Frame *regs) +{ + regs->reg0237_synt_sps.smpl_adpt_ofst_e = syn->pp.sample_adaptive_offset_enabled_flag; + regs->reg0237_synt_sps.num_st_ref_pic = syn->pp.num_short_term_ref_pic_sets; + regs->reg0237_synt_sps.num_lt_ref_pic = syn->pp.num_long_term_ref_pics_sps; + regs->reg0237_synt_sps.lt_ref_pic_prsnt = syn->pp.long_term_ref_pics_present_flag; + regs->reg0237_synt_sps.tmpl_mvp_e = syn->pp.sps_temporal_mvp_enabled_flag; + regs->reg0237_synt_sps.log2_max_poc_lsb = syn->pp.log2_max_pic_order_cnt_lsb_minus4; + regs->reg0237_synt_sps.strg_intra_smth = syn->pp.strong_intra_smoothing_enabled_flag; + + regs->reg0238_synt_pps.dpdnt_sli_seg_en = syn->pp.dependent_slice_segments_enabled_flag; + regs->reg0238_synt_pps.out_flg_prsnt_flg = syn->pp.output_flag_present_flag; + regs->reg0238_synt_pps.num_extr_sli_hdr = syn->pp.num_extra_slice_header_bits; + regs->reg0238_synt_pps.sgn_dat_hid_en = syn->pp.sign_data_hiding_enabled_flag; + regs->reg0238_synt_pps.cbc_init_prsnt_flg = syn->pp.cabac_init_present_flag; + regs->reg0238_synt_pps.pic_init_qp = syn->pp.init_qp_minus26 + 26; + regs->reg0238_synt_pps.cu_qp_dlt_en = syn->pp.cu_qp_delta_enabled_flag; + regs->reg0238_synt_pps.chrm_qp_ofst_prsn = syn->pp.pps_slice_chroma_qp_offsets_present_flag; + regs->reg0238_synt_pps.lp_fltr_acrs_sli = syn->pp.pps_loop_filter_across_slices_enabled_flag; + regs->reg0238_synt_pps.dblk_fltr_ovrd_en = syn->pp.deblocking_filter_override_enabled_flag; + regs->reg0238_synt_pps.lst_mdfy_prsnt_flg = syn->pp.lists_modification_present_flag; + regs->reg0238_synt_pps.sli_seg_hdr_extn = syn->pp.slice_segment_header_extension_present_flag; + regs->reg0238_synt_pps.cu_qp_dlt_depth = syn->pp.diff_cu_qp_delta_depth; + regs->reg0238_synt_pps.lp_fltr_acrs_til = syn->pp.loop_filter_across_tiles_enabled_flag; + + regs->reg0239_synt_sli0.cbc_init_flg = syn->sp.cbc_init_flg; + regs->reg0239_synt_sli0.mvd_l1_zero_flg = syn->sp.mvd_l1_zero_flg; + regs->reg0239_synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + regs->reg0239_synt_sli0.num_refidx_l1_act = syn->sp.num_refidx_l1_act; + regs->reg0239_synt_sli0.num_refidx_l0_act = syn->sp.num_refidx_l0_act; + + regs->reg0239_synt_sli0.num_refidx_act_ovrd = syn->sp.num_refidx_act_ovrd; + + regs->reg0239_synt_sli0.sli_sao_chrm_flg = syn->sp.sli_sao_chrm_flg; + regs->reg0239_synt_sli0.sli_sao_luma_flg = syn->sp.sli_sao_luma_flg; + regs->reg0239_synt_sli0.sli_tmprl_mvp_e = syn->sp.sli_tmprl_mvp_en; + regs->reg0192_enc_pic.num_pic_tot_cur_hevc = syn->sp.tot_poc_num; + + regs->reg0239_synt_sli0.pic_out_flg = syn->sp.pic_out_flg; + regs->reg0239_synt_sli0.sli_type = syn->sp.slice_type; + regs->reg0239_synt_sli0.sli_rsrv_flg = syn->sp.slice_rsrv_flg; + regs->reg0239_synt_sli0.dpdnt_sli_seg_flg = syn->sp.dpdnt_sli_seg_flg; + regs->reg0239_synt_sli0.sli_pps_id = syn->sp.sli_pps_id; + regs->reg0239_synt_sli0.no_out_pri_pic = syn->sp.no_out_pri_pic; + + + regs->reg0240_synt_sli1.sp_tc_ofst_div2 = syn->sp.sli_tc_ofst_div2;; + regs->reg0240_synt_sli1.sp_beta_ofst_div2 = syn->sp.sli_beta_ofst_div2; + regs->reg0240_synt_sli1.sli_lp_fltr_acrs_sli = syn->sp.sli_lp_fltr_acrs_sli; + regs->reg0240_synt_sli1.sp_dblk_fltr_dis = syn->sp.sli_dblk_fltr_dis; + regs->reg0240_synt_sli1.dblk_fltr_ovrd_flg = syn->sp.dblk_fltr_ovrd_flg; + regs->reg0240_synt_sli1.sli_cb_qp_ofst = (syn->pp.pps_slice_chroma_qp_offsets_present_flag != 0) ? + syn->sp.sli_cb_qp_ofst : syn->pp.pps_cb_qp_offset; + + if (ctx->cfg->tune.speed == 0) // 0.63ppc + regs->reg0240_synt_sli1.max_mrg_cnd = 3; + else + regs->reg0240_synt_sli1.max_mrg_cnd = 2; + + regs->reg0240_synt_sli1.col_ref_idx = syn->sp.col_ref_idx; + regs->reg0240_synt_sli1.col_frm_l0_flg = syn->sp.col_frm_l0_flg; + regs->reg0241_synt_sli2.sli_poc_lsb = syn->sp.sli_poc_lsb; + regs->reg0241_synt_sli2.sli_hdr_ext_len = syn->sp.sli_hdr_ext_len; +} + +static void vepu511_h265_set_ref_regs(H265eSyntax_new *syn, HevcVepu511Frame *regs) +{ + regs->reg0242_synt_refm0.st_ref_pic_flg = syn->sp.st_ref_pic_flg; + regs->reg0242_synt_refm0.poc_lsb_lt0 = syn->sp.poc_lsb_lt0; + regs->reg0242_synt_refm0.num_lt_pic = syn->sp.num_lt_pic; + + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->reg0243_synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->reg0243_synt_refm1.used_by_lt_flg0 = syn->sp.used_by_lt_flg0; + regs->reg0243_synt_refm1.used_by_lt_flg1 = syn->sp.used_by_lt_flg1; + regs->reg0243_synt_refm1.used_by_lt_flg2 = syn->sp.used_by_lt_flg2; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->reg0243_synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt1 = syn->sp.dlt_poc_msb_prsnt1; + regs->reg0243_synt_refm1.num_negative_pics = syn->sp.num_neg_pic; + regs->reg0243_synt_refm1.num_pos_pic = syn->sp.num_pos_pic; + + regs->reg0243_synt_refm1.used_by_s0_flg = syn->sp.used_by_s0_flg; + regs->reg0244_synt_refm2.dlt_poc_s0_m10 = syn->sp.dlt_poc_s0_m10; + regs->reg0244_synt_refm2.dlt_poc_s0_m11 = syn->sp.dlt_poc_s0_m11; + regs->reg0245_synt_refm3.dlt_poc_s0_m12 = syn->sp.dlt_poc_s0_m12; + regs->reg0245_synt_refm3.dlt_poc_s0_m13 = syn->sp.dlt_poc_s0_m13; + + regs->reg0246_synt_long_refm0.poc_lsb_lt1 = syn->sp.poc_lsb_lt1; + regs->reg0247_synt_long_refm1.dlt_poc_msb_cycl1 = syn->sp.dlt_poc_msb_cycl1; + regs->reg0246_synt_long_refm0.poc_lsb_lt2 = syn->sp.poc_lsb_lt2; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt2 = syn->sp.dlt_poc_msb_prsnt2; + regs->reg0247_synt_long_refm1.dlt_poc_msb_cycl2 = syn->sp.dlt_poc_msb_cycl2; + regs->reg0240_synt_sli1.lst_entry_l0 = syn->sp.lst_entry_l0; + regs->reg0239_synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + return; +} + +static void vepu511_h265_set_atf_regs(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + static RK_U8 b32_skip_wgt0[3] = { 24, 14, 12 }; + static RK_U8 b32_skip_wgt1[3] = { 20, 12, 10 }; + static RK_U8 b32_skip_wgt2[3] = { 20, 12, 10 }; + static RK_U8 b16_skip_wgt0[3] = { 24, 14, 12 }; + static RK_U8 b16_skip_wgt1[3] = { 20, 10, 8 }; + static RK_U8 b16_skip_wgt2[3] = { 20, 10, 8 }; + static RK_U8 b32_inter_wgt0[3] = { 24, 26, 28 }; + static RK_U8 b32_inter_wgt1[3] = { 20, 22, 26 }; + static RK_U8 b32_inter_wgt2[3] = { 20, 22, 26 }; + static RK_U8 b16_inter_wgt0[3] = { 32, 40, 44 }; + static RK_U8 b16_inter_wgt1[3] = { 28, 40, 44 }; + static RK_U8 b16_inter_wgt2[3] = { 28, 40, 44 }; + static RK_U8 b32_intra_wgt0[3] = { 32, 36, 42 }; + static RK_U8 b32_intra_wgt1[3] = { 32, 36, 42 }; + static RK_U8 b32_intra_wgt2[3] = { 32, 36, 42 }; + static RK_U8 b16_intra_wgt0[3] = { 40, 44, 48 }; + static RK_U8 b16_intra_wgt1[3] = { 40, 44, 48 }; + static RK_U8 b16_intra_wgt2[3] = { 40, 44, 48 }; + + HevcVepu511Sqi *reg = ®s->reg_sqi; + RK_U32 str = ctx->cfg->tune.atf_str; + RdoSkipPar *p_rdo_skip = NULL; + RdoNoSkipPar *p_rdo_noskip = NULL; + RK_U32 str_idx = 0; + + reg->rdo_b32_skip.atf_thd0.flckr_en = !!str; + reg->rdo_b32_skip.atf_thd0.flckr_frame_qp_en = !!str; + reg->rdo_b32_skip.atf_thd0.flckr_lgt_chng_en = !!str; + + if (str == 0) + return; + + /* 0 - disable; 1 - weak; 2 - medium; 3 - strong */ + str_idx = str - 1; + reg->dark_brgt_opt_cfg.thre_max_luma_dark = 20; + reg->dark_brgt_opt_cfg.thre_min_luma_bright = 235; + reg->dark_brgt_opt_cfg.thre_ratio_dark_bright = 48; + + p_rdo_skip = ®->rdo_b32_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 1; + p_rdo_skip->atf_thd0.madp_thd1 = 20; + p_rdo_skip->atf_thd1.madp_thd2 = 40; + p_rdo_skip->atf_thd1.madp_thd3 = 60; + p_rdo_skip->atf_wgt0.wgt0 = b32_skip_wgt0[str_idx]; + p_rdo_skip->atf_wgt0.wgt1 = b32_skip_wgt1[str_idx]; + p_rdo_skip->atf_wgt0.wgt2 = b32_skip_wgt2[str_idx]; + p_rdo_skip->atf_wgt0.wgt3 = 0; + + p_rdo_noskip = ®->rdo_b32_inter; + p_rdo_noskip->atf_thd0.madp_thd0 = 8; + p_rdo_noskip->atf_thd0.madp_thd1 = 16; + p_rdo_noskip->atf_thd1.madp_thd2 = 32; + p_rdo_noskip->atf_wgt.wgt0 = b32_inter_wgt0[str_idx]; + p_rdo_noskip->atf_wgt.wgt1 = b32_inter_wgt1[str_idx]; + p_rdo_noskip->atf_wgt.wgt2 = b32_inter_wgt2[str_idx]; + + p_rdo_noskip = ®->rdo_b32_intra; + p_rdo_noskip->atf_thd0.madp_thd0 = 400; + p_rdo_noskip->atf_thd0.madp_thd1 = 400; + p_rdo_noskip->atf_thd1.madp_thd2 = 400; + p_rdo_noskip->atf_wgt.wgt0 = b32_intra_wgt0[str_idx]; + p_rdo_noskip->atf_wgt.wgt1 = b32_intra_wgt1[str_idx]; + p_rdo_noskip->atf_wgt.wgt2 = b32_intra_wgt2[str_idx]; + + p_rdo_skip = ®->rdo_b16_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 1; + p_rdo_skip->atf_thd0.madp_thd1 = 20; + p_rdo_skip->atf_thd1.madp_thd2 = 40; + p_rdo_skip->atf_thd1.madp_thd3 = 60; + p_rdo_skip->atf_wgt0.wgt0 = b16_skip_wgt0[str_idx]; + p_rdo_skip->atf_wgt0.wgt1 = b16_skip_wgt1[str_idx]; + p_rdo_skip->atf_wgt0.wgt2 = b16_skip_wgt2[str_idx]; + p_rdo_skip->atf_wgt0.wgt3 = 2; + + p_rdo_noskip = ®->rdo_b16_inter; + p_rdo_noskip->atf_thd0.madp_thd0 = 8; + p_rdo_noskip->atf_thd0.madp_thd1 = 16; + p_rdo_noskip->atf_thd1.madp_thd2 = 32; + p_rdo_noskip->atf_wgt.wgt0 = b16_inter_wgt0[str_idx]; + p_rdo_noskip->atf_wgt.wgt1 = b16_inter_wgt1[str_idx]; + p_rdo_noskip->atf_wgt.wgt2 = b16_inter_wgt2[str_idx]; + + p_rdo_noskip = ®->rdo_b16_intra; + p_rdo_noskip->atf_thd0.madp_thd0 = 150; + p_rdo_noskip->atf_thd0.madp_thd1 = 150; + p_rdo_noskip->atf_thd1.madp_thd2 = 150; + p_rdo_noskip->atf_wgt.wgt0 = b16_intra_wgt0[str_idx]; + p_rdo_noskip->atf_wgt.wgt1 = b16_intra_wgt1[str_idx]; + p_rdo_noskip->atf_wgt.wgt2 = b16_intra_wgt2[str_idx]; + p_rdo_noskip->atf_wgt.wgt3 = 25; +} + +static void vepu511_h265_set_aq(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + HevcVepu511RcRoi *rc_regs = ®s->reg_rc_roi; + RK_S32 *aq_step, *aq_thd, *aq_rnge; + + if (ctx->frame_type == INTRA_FRAME) { + aq_thd = (RK_S32 *)&hw->aq_thrd_i[0]; + aq_step = &hw->aq_step_i[0]; + aq_rnge = &hw->aq_rnge_arr[0]; + } else { + aq_thd = (RK_S32 *)&hw->aq_thrd_p[0]; + aq_step = &hw->aq_step_p[0]; + aq_rnge = &hw->aq_rnge_arr[5]; + } + + rc_regs->aq_stp0.aq_stp_s0 = aq_step[0] & 0x1f; + rc_regs->aq_stp0.aq_stp_0t1 = aq_step[1] & 0x1f; + rc_regs->aq_stp0.aq_stp_1t2 = aq_step[2] & 0x1f; + rc_regs->aq_stp0.aq_stp_2t3 = aq_step[3] & 0x1f; + rc_regs->aq_stp0.aq_stp_3t4 = aq_step[4] & 0x1f; + rc_regs->aq_stp0.aq_stp_4t5 = aq_step[5] & 0x1f; + rc_regs->aq_stp1.aq_stp_5t6 = aq_step[6] & 0x1f; + rc_regs->aq_stp1.aq_stp_6t7 = aq_step[7] & 0x1f; + rc_regs->aq_stp1.aq_stp_7t8 = 0; + rc_regs->aq_stp1.aq_stp_8t9 = aq_step[8] & 0x1f; + rc_regs->aq_stp1.aq_stp_9t10 = aq_step[9] & 0x1f; + rc_regs->aq_stp1.aq_stp_10t11 = aq_step[10] & 0x1f; + rc_regs->aq_stp2.aq_stp_11t12 = aq_step[11] & 0x1f; + rc_regs->aq_stp2.aq_stp_12t13 = aq_step[12] & 0x1f; + rc_regs->aq_stp2.aq_stp_13t14 = aq_step[13] & 0x1f; + rc_regs->aq_stp2.aq_stp_14t15 = aq_step[14] & 0x1f; + rc_regs->aq_stp2.aq_stp_b15 = aq_step[15]; + + rc_regs->aq_tthd0.aq_tthd0 = aq_thd[0] & 0xff; + rc_regs->aq_tthd0.aq_tthd1 = aq_thd[1] & 0xff; + rc_regs->aq_tthd0.aq_tthd2 = aq_thd[2] & 0xff; + rc_regs->aq_tthd0.aq_tthd3 = aq_thd[3] & 0xff; + rc_regs->aq_tthd1.aq_tthd4 = aq_thd[4] & 0xff; + rc_regs->aq_tthd1.aq_tthd5 = aq_thd[5] & 0xff; + rc_regs->aq_tthd1.aq_tthd6 = aq_thd[6] & 0xff; + rc_regs->aq_tthd1.aq_tthd7 = aq_thd[7] & 0xff; + rc_regs->aq_tthd2.aq_tthd8 = aq_thd[8] & 0xff; + rc_regs->aq_tthd2.aq_tthd9 = aq_thd[9] & 0xff; + rc_regs->aq_tthd2.aq_tthd10 = aq_thd[10] & 0xff; + rc_regs->aq_tthd2.aq_tthd11 = aq_thd[11] & 0xff; + rc_regs->aq_tthd3.aq_tthd12 = aq_thd[12] & 0xff; + rc_regs->aq_tthd3.aq_tthd13 = aq_thd[13] & 0xff; + rc_regs->aq_tthd3.aq_tthd14 = aq_thd[14] & 0xff; + rc_regs->aq_tthd3.aq_tthd15 = aq_thd[15] & 0xff; + + rc_regs->aq_clip.aq16_rnge = aq_rnge[0]; + rc_regs->aq_clip.aq32_rnge = aq_rnge[1]; + rc_regs->aq_clip.aq8_rnge = aq_rnge[2]; + rc_regs->aq_clip.aq16_dif0 = aq_rnge[3]; + rc_regs->aq_clip.aq16_dif1 = aq_rnge[4]; + + rc_regs->aq_clip.aq_cme_en = 1; + rc_regs->aq_clip.aq_subj_cme_en = 0; + rc_regs->aq_clip.aq_rme_en = 1; + rc_regs->aq_clip.aq_subj_rme_en = 1; +} + +static void vepu511_h265_set_subj_opt_regs(H265eV511RegSet *regs) +{ + HevcVepu511Sqi *s = ®s->reg_sqi; + + s->subj_opt_cfg.subj_opt_en = 1; + s->subj_opt_cfg.subj_opt_strength = 3; + s->subj_opt_cfg.aq_subj_en = 1; + s->subj_opt_cfg.aq_subj_strength = 4; + s->subj_opt_cfg.thre_sum_grdn_point = 1800; + s->subj_opt_dpth_thd.common_thre_num_grdn_point_dep0 = 64; + s->subj_opt_dpth_thd.common_thre_num_grdn_point_dep1 = 32; + s->subj_opt_dpth_thd.common_thre_num_grdn_point_dep2 = 16; + + // Set the RDO split cost coefficient. + // Priority: smear takes precedence over anti-ring. + if (s->smear_opt_cfg0.anti_smear_en == 1) { + s->subj_opt_rdo_split.choose_cu16_split_jcoef = 8; + } else if (s->line_opt_cfg.line_en == 1) { + s->subj_opt_rdo_split.choose_cu16_split_jcoef = 8; + } +} + +static void vepu511_h265_global_cfg_set(H265eV511HalContext *ctx, H265eV511RegSet *regs) +{ + HevcVepu511Frame *reg_frm = ®s->reg_frm; + HevcVepu511Param *reg_param = ®s->reg_param; + RK_S32 lambda_idx = ctx->cfg->tune.lambda_idx_i; + + reg_frm->reg0248_sao_cfg.sao_lambda_multi = ctx->cfg->h265.sao_cfg.sao_bit_ratio; + + if (ctx->frame_type == INTRA_FRAME) + memcpy(®_param->pprd_lamb_satd_0_51[0], + lambda_tbl_pre_intra, sizeof(lambda_tbl_pre_intra)); + else + memcpy(®_param->pprd_lamb_satd_0_51[0], + lambda_tbl_pre_inter, sizeof(lambda_tbl_pre_inter)); + + { + RK_U32 *lambda_tbl; + + if (ctx->frame_type == INTRA_FRAME) { + lambda_tbl = &rdo_lambda_table_I[lambda_idx]; + } else { + lambda_idx = ctx->cfg->tune.lambda_idx_p; + lambda_tbl = &rdo_lambda_table_P[lambda_idx]; + } + + memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], lambda_tbl, H265E_LAMBDA_TAB_SIZE); + } + + /* 0x1064 */ + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + /* 0x1068 */ + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + /* 0x106C */ + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; + regs->reg_param.prmd_intra_lamb_ofst.lambda_luma_offset = 11; + regs->reg_param.prmd_intra_lamb_ofst.lambda_chroma_offset = 11; +} + +MPP_RET hal_h265e_vepu511_gen_regs(void *hal, HalEncTask *task) +{ + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + Vepu511H265eFrmCfg *frm_cfg = ctx->frm; + H265eV511RegSet *regs = frm_cfg->regs_set; + MPP_RET ret = MPP_OK; + + HalEncTask *enc_task = task; + H265eSyntax_new *syn = ctx->syn; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + HevcVepu511Frame *reg_frm = ®s->reg_frm; + EncFrmStatus *frm = &task->rc_task->frm; + + hal_h265e_enter(); + + hal_h265e_dbg_simple("frame %d | type %d | start gen regs11", + ctx->frame_num, ctx->frame_type); + + memset(regs, 0, sizeof(H265eV511RegSet)); + + vepu511_h265_set_normal(regs); + vepu511_h265_set_prep(ctx, task, regs); + vepu511_h265_set_me_regs(ctx, syn , regs); + vepu511_h265_set_split(regs, ctx->cfg); + vepu511_h265_set_hw_address(ctx, reg_frm, task); + vepu511_h265_set_pp_regs(regs, fmt, &ctx->cfg->prep, task); + vepu511_h265_set_vsp_filtering(ctx, regs); + vepu511_h265_set_rc_regs(ctx, regs, task); + vepu511_h265_set_rdo_regs(ctx, regs); + vepu511_h265_set_quant_regs(ctx, regs); + vepu511_h265_set_sao_regs(ctx, regs); + vepu511_h265_set_slice_regs(ctx, syn, reg_frm); + vepu511_h265_set_ref_regs(syn, reg_frm); + + ret = vepu511_h265_set_patch_info(syn, (VepuFmt)fmt->format, ctx->reg_cfg, enc_task); + if (ret) + return ret; + + setup_vepu511_ext_line_buf(ctx, regs); + vepu511_h265_set_atf_regs(ctx, regs); + vepu511_h265_set_anti_stripe_regs(ctx, regs); + vepu511_h265_set_atr_regs(ctx, regs); + vepu511_h265_set_smear_regs(ctx, regs); + vepu511_h265_set_scaling_list(regs); + vepu511_h265_set_aq(ctx, regs); + vepu511_h265_set_subj_opt_regs(regs); + + if (ctx->osd_cfg.osd_data3) + vepu511_set_osd(&ctx->osd_cfg); + + if (ctx->roi_data) + vepu511_set_roi(®s->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + + /*paramet cfg*/ + vepu511_h265_global_cfg_set(ctx, regs); + + /* two pass register patch */ + if (frm->save_pass1) + vepu511_h265e_save_pass1_patch(regs, ctx, syn->pp.tiles_enabled_flag); + + if (frm->use_pass1) + vepu511_h265e_use_pass1_patch(regs, ctx); + + ctx->frame_num++; + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu511_start(void *hal, HalEncTask *enc_task) +{ + MPP_RET ret = MPP_OK; + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + Vepu511H265eFrmCfg *frm = ctx->frm; + RK_U32 *regs = (RK_U32*)frm->regs_set; + H265eV511RegSet *hw_regs = frm->regs_set; + H265eV511StatusElem *reg_out = (H265eV511StatusElem *)frm->regs_ret; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + RK_U32 i = 0; + + hal_h265e_enter(); + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + cfg.reg = (RK_U32*)&hw_regs->reg_ctl; + cfg.size = sizeof(Vepu511ControlCfg); + cfg.offset = VEPU511_CTL_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_CTL_REGS) { + regs = (RK_U32*)&hw_regs->reg_ctl; + for (i = 0; i < sizeof(Vepu511ControlCfg) / 4; i++) { + hal_h265e_dbg_ctl("ctl reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_frm; + cfg.size = sizeof(HevcVepu511Frame); + cfg.offset = VEPU511_FRAME_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_REGS) { + regs = (RK_U32*)(&hw_regs->reg_frm); + for (i = 0; i < 32; i++) { + hal_h265e_dbg_regs("hw add cfg reg[%04x]: 0x%08x\n", i * 4, regs[i]); + } + regs += 32; + for (i = 0; i < (sizeof(HevcVepu511Frame) - 128) / 4; i++) { + hal_h265e_dbg_regs("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + cfg.reg = &hw_regs->reg_rc_roi; + cfg.size = sizeof(HevcVepu511RcRoi); + cfg.offset = VEPU511_RC_ROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_RCKUT_REGS) { + regs = (RK_U32*)&hw_regs->reg_rc_roi; + for (i = 0; i < sizeof(HevcVepu511RcRoi) / 4; i++) { + hal_h265e_dbg_rckut("set rc roi reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_param; + cfg.size = sizeof(HevcVepu511Param); + cfg.offset = VEPU511_PARAM_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_param; + for (i = 0; i < sizeof(HevcVepu511Param) / 4; i++) { + hal_h265e_dbg_wgt("set param reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_sqi; + cfg.size = sizeof(HevcVepu511Sqi); + cfg.offset = VEPU511_SQI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_sqi; + for (i = 0; i < sizeof(HevcVepu511Sqi) / 4; i++) { + hal_h265e_dbg_wgt("set sqi reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_scl_jpgtbl; + cfg.size = sizeof(hw_regs->reg_scl_jpgtbl); + cfg.offset = VEPU511_SCL_JPGTBL_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_scl_jpgtbl; + for (i = 0; i < sizeof(Vepu511SclCfg) / 4; i++) { + hal_h265e_dbg_wgt("set scl reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_osd; + cfg.size = sizeof(hw_regs->reg_osd); + cfg.offset = VEPU511_OSD_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_osd; + for (i = 0; i < sizeof(Vepu511OsdComb) / 4; i++) { + hal_h265e_dbg_wgt("set osd reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->reg_cfg); + if (ret) { + mpp_err_f("set register offsets failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU511_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->st; + cfg1.size = sizeof(H265eV511StatusElem) - 4; + cfg1.offset = VEPU511_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + hal_h265e_leave(); + return ret; +} + +static MPP_RET vepu511_h265_set_feedback(H265eV511HalContext *ctx, HalEncTask *enc_task) +{ + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&enc_task->rc_task->info; + Vepu511H265Fbk *fb = &ctx->frm->feedback; + MppEncCfgSet *cfg = ctx->cfg; + RK_S32 mb8_num = MPP_ALIGN(cfg->prep.width, 8) * MPP_ALIGN(cfg->prep.height, 8) / 64; + RK_S32 mb4_num = (mb8_num << 2); + H265eV511StatusElem *elem = (H265eV511StatusElem *)ctx->frm->regs_ret; + RK_U32 hw_status = elem->hw_status; + + hal_h265e_enter(); + + fb->qp_sum += elem->st.qp_sum; + fb->out_strm_size += elem->st.bs_lgth_l32; + fb->sse_sum += (RK_S64)(elem->st.sse_h32 << 16) + + (elem->st.st_sse_bsl.sse_l16 & 0xffff); + + fb->hw_status = hw_status; + hal_h265e_dbg_detail("hw_status: 0x%08x", hw_status); + if (hw_status & RKV_ENC_INT_LINKTABLE_FINISH) + hal_h265e_err("RKV_ENC_INT_LINKTABLE_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_FRAME_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_FRAME_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_SLICE_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_SLICE_FINISH"); + + if (hw_status & RKV_ENC_INT_SAFE_CLEAR_FINISH) + hal_h265e_err("RKV_ENC_INT_SAFE_CLEAR_FINISH"); + + if (hw_status & RKV_ENC_INT_BIT_STREAM_OVERFLOW) + hal_h265e_err("RKV_ENC_INT_BIT_STREAM_OVERFLOW"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_FULL) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_FULL"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_ERROR"); + + if (hw_status & RKV_ENC_INT_BUS_READ_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_READ_ERROR"); + + if (hw_status & RKV_ENC_INT_TIMEOUT_ERROR) + hal_h265e_err("RKV_ENC_INT_TIMEOUT_ERROR"); + + fb->st_mb_num += elem->st.st_bnum_b16.num_b16; + + fb->st_lvl64_inter_num += elem->st.st_pnum_p64.pnum_p64; + fb->st_lvl32_inter_num += elem->st.st_pnum_p32.pnum_p32; + fb->st_lvl32_intra_num += elem->st.st_pnum_i32.pnum_i32; + fb->st_lvl16_inter_num += elem->st.st_pnum_p16.pnum_p16; + fb->st_lvl16_intra_num += elem->st.st_pnum_i16.pnum_i16; + fb->st_lvl8_inter_num += elem->st.st_pnum_p8.pnum_p8; + fb->st_lvl8_intra_num += elem->st.st_pnum_i8.pnum_i8; + fb->st_lvl4_intra_num += elem->st.st_pnum_i4.pnum_i4; + + ctx->feedback.acc_cover16_num = elem->st.st_cover_sum.acc_cover16_num; + ctx->feedback.acc_bndry16_num = elem->st.st_bndry16_sum.acc_bndry16_num; + ctx->feedback.acc_zero_mv = elem->st.acc_zero_mv; + ctx->feedback.st_ctu_num = elem->st.st_bnum_b16.num_b16; + memcpy(&fb->st_cu_num_qp[0], &elem->st.st_b8_qp, 52 * sizeof(RK_U32)); + + if (mb4_num > 0) + hal_rc_ret->iblk4_prop = ((((fb->st_lvl4_intra_num + fb->st_lvl8_intra_num) << 2) + + (fb->st_lvl16_intra_num << 4) + + (fb->st_lvl32_intra_num << 6)) << 8) / mb4_num; + + if (mb8_num > 0) { + hal_rc_ret->quality_real = fb->qp_sum / mb8_num; + } + + hal_h265e_leave(); + return MPP_OK; +} + +static MPP_RET hal_h265e_vepu511_status_check(H265eV511RegSet *regs) +{ + MPP_RET ret = MPP_OK; + + if (regs->reg_ctl.int_sta.lkt_node_done_sta) + hal_h265e_dbg_detail("lkt_done finish"); + + if (regs->reg_ctl.int_sta.enc_done_sta) + hal_h265e_dbg_detail("enc_done finish"); + + if (regs->reg_ctl.int_sta.vslc_done_sta) + hal_h265e_dbg_detail("enc_slice finsh"); + + if (regs->reg_ctl.int_sta.sclr_done_sta) + hal_h265e_dbg_detail("safe clear finsh"); + + if (regs->reg_ctl.int_sta.vbsf_oflw_sta) { + mpp_err_f("bit stream overflow"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.vbuf_lens_sta) { + mpp_err_f("bus write full"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.enc_err_sta) { + mpp_err_f("bus error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wdg_sta) { + mpp_err_f("wdg timeout"); + ret = MPP_NOK; + } + + return ret; +} + +static void vepu511_h265e_update_tune_stat(H265eV511HalContext *ctx, HalEncTask *task) +{ + Vepu511H265Fbk *fb = &ctx->frm->feedback; + H265eV511RegSet *regs = ctx->frm->regs_set; + HevcVepu511RcRoi *s = ®s->reg_rc_roi; + MppEncCfgSet *cfg = ctx->cfg; + Vepu511Status *st = &ctx->frm->regs_ret->st; + EncRcTaskInfo *info = (EncRcTaskInfo *)&task->rc_task->info; + RK_U32 b16_num = MPP_ALIGN(cfg->prep.width, 16) * MPP_ALIGN(cfg->prep.height, 16) / 256; + RK_U32 madi_cnt = 0, madp_cnt = 0; + + RK_U32 madi_th_cnt0 = st->st_madi_lt_num0.madi_th_lt_cnt0 + + st->st_madi_rt_num0.madi_th_rt_cnt0 + + st->st_madi_lb_num0.madi_th_lb_cnt0 + + st->st_madi_rb_num0.madi_th_rb_cnt0; + RK_U32 madi_th_cnt1 = st->st_madi_lt_num0.madi_th_lt_cnt1 + + st->st_madi_rt_num0.madi_th_rt_cnt1 + + st->st_madi_lb_num0.madi_th_lb_cnt1 + + st->st_madi_rb_num0.madi_th_rb_cnt1; + RK_U32 madi_th_cnt2 = st->st_madi_lt_num1.madi_th_lt_cnt2 + + st->st_madi_rt_num1.madi_th_rt_cnt2 + + st->st_madi_lb_num1.madi_th_lb_cnt2 + + st->st_madi_rb_num1.madi_th_rb_cnt2; + RK_U32 madi_th_cnt3 = st->st_madi_lt_num1.madi_th_lt_cnt3 + + st->st_madi_rt_num1.madi_th_rt_cnt3 + + st->st_madi_lb_num1.madi_th_lb_cnt3 + + st->st_madi_rb_num1.madi_th_rb_cnt3; + RK_U32 madp_th_cnt0 = st->st_madp_lt_num0.madp_th_lt_cnt0 + + st->st_madp_rt_num0.madp_th_rt_cnt0 + + st->st_madp_lb_num0.madp_th_lb_cnt0 + + st->st_madp_rb_num0.madp_th_rb_cnt0; + RK_U32 madp_th_cnt1 = st->st_madp_lt_num0.madp_th_lt_cnt1 + + st->st_madp_rt_num0.madp_th_rt_cnt1 + + st->st_madp_lb_num0.madp_th_lb_cnt1 + + st->st_madp_rb_num0.madp_th_rb_cnt1; + RK_U32 madp_th_cnt2 = st->st_madp_lt_num1.madp_th_lt_cnt2 + + st->st_madp_rt_num1.madp_th_rt_cnt2 + + st->st_madp_lb_num1.madp_th_lb_cnt2 + + st->st_madp_rb_num1.madp_th_rb_cnt2; + RK_U32 madp_th_cnt3 = st->st_madp_lt_num1.madp_th_lt_cnt3 + + st->st_madp_rt_num1.madp_th_rt_cnt3 + + st->st_madp_lb_num1.madp_th_lb_cnt3 + + st->st_madp_rb_num1.madp_th_rb_cnt3; + + madi_cnt = (6 * madi_th_cnt3 + 5 * madi_th_cnt2 + 4 * madi_th_cnt1) >> 2; + info->complex_level = (madi_cnt * 100 > 30 * b16_num) ? 2 : + (madi_cnt * 100 > 13 * b16_num) ? 1 : 0; + + { + RK_U32 md_cnt = 0, motion_level = 0; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt3 + 11 * madp_th_cnt2 + 8 * madp_th_cnt1) >> 2; + else + md_cnt = (24 * madp_th_cnt3 + 22 * madp_th_cnt2 + 17 * madp_th_cnt1) >> 2; + + if (md_cnt * 100 > 15 * b16_num) + motion_level = 200; + else if (md_cnt * 100 > 5 * b16_num) + motion_level = 100; + else if (md_cnt * 100 > (b16_num >> 2)) + motion_level = 1; + else + motion_level = 0; + info->motion_level = motion_level; + } + hal_h265e_dbg_st("frame %d complex_level %d motion_level %d\n", + ctx->frame_num - 1, info->complex_level, info->motion_level); + + fb->st_madi = madi_th_cnt0 * s->madi_st_thd.madi_th0 + + madi_th_cnt1 * (s->madi_st_thd.madi_th0 + s->madi_st_thd.madi_th1) / 2 + + madi_th_cnt2 * (s->madi_st_thd.madi_th1 + s->madi_st_thd.madi_th2) / 2 + + madi_th_cnt3 * s->madi_st_thd.madi_th2; + + madi_cnt = madi_th_cnt0 + madi_th_cnt1 + madi_th_cnt2 + madi_th_cnt3; + if (madi_cnt) + fb->st_madi = fb->st_madi / madi_cnt; + + fb->st_madp = madp_th_cnt0 * s->madp_st_thd0.madp_th0 + + madp_th_cnt1 * (s->madp_st_thd0.madp_th0 + s->madp_st_thd0.madp_th1) / 2 + + madp_th_cnt2 * (s->madp_st_thd0.madp_th1 + s->madp_st_thd1.madp_th2) / 2 + + madp_th_cnt3 * s->madp_st_thd1.madp_th2; + + madp_cnt = madp_th_cnt0 + madp_th_cnt1 + madp_th_cnt2 + madp_th_cnt3; + if (madp_cnt) + fb->st_madp = fb->st_madp / madp_cnt; + + fb->st_mb_num += st->st_bnum_b16.num_b16; + fb->frame_type = (task->rc_task->frm.is_intra != 0) ? INTRA_FRAME : INTER_P_FRAME; + info->bit_real = fb->out_strm_size * 8; + info->madi = fb->st_madi; + info->madp = fb->st_madp; + + hal_h265e_dbg_st("frame %d bit_real %d quality_real %d madi %d madp %d\n", + ctx->frame_num - 1, info->bit_real, info->quality_real, info->madi, info->madp); +} + +//#define DUMP_DATA +MPP_RET hal_h265e_vepu511_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + HalEncTask *enc_task = task; + MppPacket pkt = enc_task->packet; + RK_U32 split_out = ctx->cfg->split.split_out; + H265eV511RegSet *regs = ctx->frm->regs_set; + RK_U32 offset = mpp_packet_get_length(pkt); + RK_U32 seg_offset = offset; + HevcVepu511Frame *reg_frm = ®s->reg_frm; + RK_U32 type = reg_frm->reg0236_synt_nal.nal_unit_type; + H265eV511StatusElem *elem = (H265eV511StatusElem *)ctx->frm->regs_ret; + + hal_h265e_enter(); + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (enc_task->rc_task->frm.save_pass1) + split_out = 0; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len = 0; + RK_U32 slice_last = 0; + MppDevPollCfg *poll_cfg = (MppDevPollCfg *)((char *)ctx->poll_cfgs); + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + RK_S32 i = 0; + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = split_out & MPP_ENC_SPLIT_OUT_LOWDELAY ? 1 : ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].vepu511.sli_lst; + slice_len = poll_cfg->slice_info[i].vepu511.sli_len; + param.length = slice_len; + + mpp_packet_add_segment_info(pkt, type, seg_offset, slice_len); + seg_offset += slice_len; + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) { + param.length = slice_len; + if (slice_last) + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + else + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + + mpp_callback(ctx->output_cb, ¶m); + } + } + } while (!slice_last); + + ret = hal_h265e_vepu511_status_check(regs); + if (!ret) + task->hw_length += elem->st.bs_lgth_l32; + + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + ret = hal_h265e_vepu511_status_check(regs); + if (!ret) + task->hw_length += elem->st.bs_lgth_l32; + } + mpp_packet_add_segment_info(pkt, type, offset, elem->st.bs_lgth_l32); + } + +#ifdef DUMP_DATA + vepu511_h265e_dump(ctx, task); +#endif + + if (ret) + mpp_err_f("poll cmd failed %d status %d \n", ret, elem->hw_status); + + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_vepu511_get_task(void *hal, HalEncTask *task) +{ + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + MppFrame frame = task->frame; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h265e_enter(); + + ctx->syn = (H265eSyntax_new *)task->syntax.data; + ctx->dpb = (H265eDpb*)ctx->syn->dpb; + ctx->smart_en = (ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC); + ctx->qpmap_en = ctx->cfg->tune.deblur_en; + + if (!task->rc_task->frm.reencode) { + if (vepu511_h265_setup_hal_bufs(ctx)) { + hal_h265e_err("vepu541_h265_allocate_buffers failed, free buffers and return\n"); + task->flags.err |= HAL_ENC_TASK_ERR_ALLOC; + return MPP_ERR_MALLOC; + } + ctx->last_frame_fb = ctx->feedback; + } + + ctx->last_frame_type = ctx->frame_type; + + if (frm_status->is_intra) { + ctx->frame_type = INTRA_FRAME; + } else { + ctx->frame_type = INTER_P_FRAME; + } + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA3, (void **)&ctx->osd_cfg.osd_data3, NULL); + } + + ctx->frm->frame_count = ++ctx->frame_count; + task->part_first = 1; + task->part_last = 0; + + ctx->frm->hal_curr_idx = ctx->syn->sp.recon_pic.slot_idx; + ctx->frm->hal_refr_idx = ctx->syn->sp.ref_pic.slot_idx; + + h265e_dpb_hal_start(ctx->dpb, ctx->frm->hal_curr_idx); + h265e_dpb_hal_start(ctx->dpb, ctx->frm->hal_refr_idx); + + memset(&ctx->frm->feedback, 0, sizeof(Vepu511H265Fbk)); + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu511_ret_task(void *hal, HalEncTask *task) +{ + H265eV511HalContext *ctx = (H265eV511HalContext *)hal; + HalEncTask *enc_task = task; + Vepu511H265Fbk *fb = &ctx->frm->feedback; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + + hal_h265e_enter(); + + vepu511_h265_set_feedback(ctx, enc_task); + mpp_buffer_sync_partial_begin(enc_task->output, offset, fb->out_strm_size); + hal_h265e_amend_temporal_id(task, fb->out_strm_size); + + rc_info->sse = fb->sse_sum; + rc_info->lvl64_inter_num = fb->st_lvl64_inter_num; + rc_info->lvl32_inter_num = fb->st_lvl32_inter_num; + rc_info->lvl16_inter_num = fb->st_lvl16_inter_num; + rc_info->lvl8_inter_num = fb->st_lvl8_inter_num; + rc_info->lvl32_intra_num = fb->st_lvl32_intra_num; + rc_info->lvl16_intra_num = fb->st_lvl16_intra_num; + rc_info->lvl8_intra_num = fb->st_lvl8_intra_num; + rc_info->lvl4_intra_num = fb->st_lvl4_intra_num; + + enc_task->hw_length = fb->out_strm_size; + enc_task->length += fb->out_strm_size; + + h265e_dpb_hal_end(ctx->dpb, ctx->frm->hal_curr_idx); + h265e_dpb_hal_end(ctx->dpb, ctx->frm->hal_refr_idx); + + vepu511_h265e_update_tune_stat(ctx, enc_task); + + hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); + hal_h265e_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_h265e_vepu511 = { + .name = "hal_h265e_v511", + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(H265eV511HalContext), + .flag = 0, + .init = hal_h265e_vepu511_init, + .deinit = hal_h265e_vepu511_deinit, + .prepare = hal_h265e_vepu511_prepare, + .get_task = hal_h265e_vepu511_get_task, + .gen_regs = hal_h265e_vepu511_gen_regs, + .start = hal_h265e_vepu511_start, + .wait = hal_h265e_vepu511_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h265e_vepu511_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RV1126B, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h265e_vepu511) diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu511.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu511.h new file mode 100644 index 000000000..c0db03f66 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu511.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265E_VEPU511_H +#define HAL_H265E_VEPU511_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h265e_vepu511; + +#endif /* HAL_H265E_VEPU511_H */ \ No newline at end of file diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu511_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu511_reg.h new file mode 100644 index 000000000..693751282 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu511_reg.h @@ -0,0 +1,1857 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265E_VEPU511_REG_H +#define HAL_H265E_VEPU511_REG_H + +#include "rk_type.h" +#include "vepu511_common.h" + +/* class: buffer/video syntax */ +/* 0x00000270 reg156 -0x000003fc reg0255 */ +typedef struct HevcVepu511Frame_t { + /* 0x00000270 reg156 - 0x0000027c reg159 */ + vepu511_online online_addr; + + /* 0x00000280 reg160 */ + RK_U32 reg0160_adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 reg0161_adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 reg0162_adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 reg0163_rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 reg0164_rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 reg0165_rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 reg0166_rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 reg0167_cmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 reg0168_cmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 reg0169_dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 reg0170_dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 reg0171_meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 reg0172_bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 reg0173_bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 reg0174_bsbs_addr; + + /* 0x000002bc reg175 */ + RK_U32 reg0175_bsbr_addr; + + /* 0x000002c0 reg176 */ + RK_U32 reg0176_lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 reg0177_lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 reg0178_adr_ebuft; + + /* 0x000002cc reg179 */ + RK_U32 reg0179_adr_ebufb; + + /* 0x000002d0 reg180 */ + RK_U32 reg0180_adr_rfpt_h; + + /* 0x000002d4 reg181 */ + RK_U32 reg0181_adr_rfpb_h; + + /* 0x000002d8 reg182 */ + RK_U32 reg0182_adr_rfpt_b; + + /* 0x000002dc reg183 */ + RK_U32 reg0183_adr_rfpb_b; + + /* 0x000002e0 reg184 */ + RK_U32 reg0184_adr_smr_rd; + + /* 0x000002e4 reg185 */ + RK_U32 reg0185_adr_smr_wr; + + /* 0x000002e8 reg186 */ + RK_U32 reg0186_adr_roir; + + /* 0x000002ec reg187 */ + RK_U32 reg0187_eslf_badr; + + /* 0x000002f0 reg188 */ + RK_U32 reg0188_rfp1r_h_addr; + + /* 0x000002f4 reg189 */ + RK_U32 reg0189_rfp1r_b_addr; + + /* 0x000002f8 reg190 */ + RK_U32 reg0190_dsp1r_addr; + + /* 0x000002fc reg191 */ + RK_U32 reserved191; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 meiw_mode : 1; + RK_U32 reserved : 2; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur_hevc : 5; + RK_U32 log2_ctu_num_hevc : 5; + RK_U32 rfpr_compress_mode : 1; + RK_U32 reserved1 : 2; + RK_U32 eslf_out_e_jpeg : 1; + RK_U32 jpeg_slen_fifo : 1; + RK_U32 eslf_out_e : 1; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } reg0192_enc_pic; + + /* 0x00000304 reg193 */ + struct { + RK_U32 dchs_txid : 2; + RK_U32 dchs_rxid : 2; + RK_U32 dchs_txe : 1; + RK_U32 dchs_rxe : 1; + RK_U32 reserved : 2; + RK_U32 dchs_dly : 8; + RK_U32 dchs_ofst : 10; + RK_U32 reserved1 : 6; + } reg0193_dual_core; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 frm_id_match : 1; + RK_U32 reserved : 3; + RK_U32 source_id : 1; + RK_U32 src_id_match : 1; + RK_U32 reserved1 : 2; + RK_U32 ch_id : 2; + RK_U32 vrsp_rtn_en : 1; + RK_U32 vinf_req_en : 1; + RK_U32 reserved2 : 12; + } reg0194_enc_id; + + /* 0x0000030c reg195 */ + RK_U32 bsp_size; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } reg0196_enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } reg0197_src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_rcne : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved : 21; + } reg0198_src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } reg0199_src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } reg0200_src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } reg0201_src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } reg0202_src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 cr_force_value : 8; + RK_U32 cb_force_value : 8; + RK_U32 chroma_force_en : 1; + RK_U32 reserved : 9; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 tile4x4_en : 1; + RK_U32 rkfbcd_en : 1; + RK_U32 reserved1 : 1; + } reg0203_src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } reg0204_pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 21; + RK_U32 reserved : 11; + } reg0205_src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } reg0206_src_strd1; + + /* 0x0000033c reg207 */ + struct { + RK_U32 pp_corner_filter_strength : 2; + RK_U32 reserved : 2; + RK_U32 pp_edge_filter_strength : 2; + RK_U32 reserved1 : 2; + RK_U32 pp_internal_filter_strength : 2; + RK_U32 reserved2 : 22; + } reg0207_src_flt_cfg; + + /* 0x340 - 0x34c */ + RK_U32 reserved208_211[4]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 reserved : 10; + RK_U32 rc_ctu_num : 20; + } reg212_rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } reg213_rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } reg214_rc_tgt; + + /* 0x0000035c reg215 */ + struct { + RK_U32 eslf_rptr : 10; + RK_U32 eslf_wptr : 10; + RK_U32 eslf_blen : 10; + RK_U32 eslf_updt : 2; + } eslf_buf; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } reg0216_sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } reg0217_sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } reg0218_sli_cnum; + + /* 0x0000036c reg219 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } vbs_pad; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cime_srch_dwnh : 4; + RK_U32 cime_srch_uph : 4; + RK_U32 cime_srch_rgtw : 4; + RK_U32 cime_srch_lftw : 4; + RK_U32 dlt_frm_num : 16; + } reg0220_me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 srgn_max_num : 7; + RK_U32 cime_dist_thre : 13; + RK_U32 rme_srch_h : 2; + RK_U32 rme_srch_v : 2; + RK_U32 rme_dis : 3; + RK_U32 reserved1 : 1; + RK_U32 fme_dis : 3; + RK_U32 reserved2 : 1; + } reg0221_me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cime_zero_thre : 13; + RK_U32 reserved : 15; + RK_U32 fme_prefsu_en : 2; + RK_U32 colmv_stor : 1; + RK_U32 colmv_load : 1; + } reg0222_me_cach; + + /* 0x0000037c reg223 */ + struct { + RK_U32 ref_num : 1; + RK_U32 thre_zero_sad_dep0_cme : 6; + RK_U32 thre_zero_sad_dep1_cme : 6; + RK_U32 thre_zero_diff_dep1_cme : 3; + RK_U32 thre_zero_num_dep1_cme : 3; + RK_U32 thre_num_hit_dep1_cme : 2; + RK_U32 reserved : 7; + RK_U32 rfpw_mode : 1; + RK_U32 rfpr_mode : 1; + RK_U32 rfp1r_mode : 1; + RK_U32 reserved1 : 1; + } reg0223_me_ref_comb; + + /* 0x380 - 0x39c */ + RK_U32 reserved224_231[8]; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 ltm_col : 1; + RK_U32 ltm_idx0l0 : 1; + RK_U32 chrm_spcl : 1; + RK_U32 cu_inter_e : 12; + RK_U32 reserved : 1; + RK_U32 cu32_split_lambda_qp_sel : 3; + RK_U32 reserved1 : 4; + RK_U32 ccwa_e : 1; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved2 : 2; + RK_U32 atf_e : 1; + RK_U32 atr_e : 1; + RK_U32 reserved3 : 2; + } reg0232_rdo_cfg; + + struct { + RK_U32 intra_pu32_mode_num : 2; + RK_U32 intra_pu16_mode_num : 2; + RK_U32 intra_pu8_mode_num : 2; + RK_U32 intra_pu4_mode_num : 2; + RK_U32 reserved : 24; + } reg0233_rdo_intra_mode; + + /* 0x000003a8 reg234 */ + struct { + RK_U32 rdoqx_pixel_e : 1; + RK_U32 rdoqx_cgzero_e : 1; + RK_U32 rdoqx_lastxy_e : 1; + RK_U32 rdoq4_rdoq_e : 1; + RK_U32 reserved1 : 4; + RK_U32 rdoq_intra_r_coef : 5; + RK_U32 reserved2 : 19; + } reg0234_rdoq_cfg; + + /* 0x3ac */ + RK_U32 reserved_235; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_unit_type : 6; + RK_U32 reserved : 26; + } reg0236_synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 smpl_adpt_ofst_e : 1; + RK_U32 num_st_ref_pic : 7; + RK_U32 lt_ref_pic_prsnt : 1; + RK_U32 num_lt_ref_pic : 6; + RK_U32 tmpl_mvp_e : 1; + RK_U32 log2_max_poc_lsb : 4; + RK_U32 strg_intra_smth : 1; + RK_U32 reserved : 11; + } reg0237_synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 dpdnt_sli_seg_en : 1; + RK_U32 out_flg_prsnt_flg : 1; + RK_U32 num_extr_sli_hdr : 3; + RK_U32 sgn_dat_hid_en : 1; + RK_U32 cbc_init_prsnt_flg : 1; + RK_U32 pic_init_qp : 6; + RK_U32 cu_qp_dlt_en : 1; + RK_U32 chrm_qp_ofst_prsn : 1; + RK_U32 lp_fltr_acrs_sli : 1; + RK_U32 dblk_fltr_ovrd_en : 1; + RK_U32 lst_mdfy_prsnt_flg : 1; + RK_U32 sli_seg_hdr_extn : 1; + RK_U32 cu_qp_dlt_depth : 2; + RK_U32 lp_fltr_acrs_til : 1; + RK_U32 csip_flag : 1; + RK_U32 reserved : 9; + } reg0238_synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 mrg_up_flg : 1; + RK_U32 mrg_lft_flg : 1; + RK_U32 reserved : 1; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_l1_act : 2; + RK_U32 num_refidx_l0_act : 2; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_e : 1; + RK_U32 pic_out_flg : 1; + RK_U32 sli_type : 2; + RK_U32 sli_rsrv_flg : 7; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 sli_pps_id : 6; + RK_U32 no_out_pri_pic : 1; + } reg0239_synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 sp_tc_ofst_div2 : 4; + RK_U32 sp_beta_ofst_div2 : 4; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sp_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_U32 sli_cb_qp_ofst : 5; + RK_U32 sli_qp : 6; + RK_U32 max_mrg_cnd : 2; + RK_U32 reserved : 1; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 lst_entry_l0 : 4; + RK_U32 reserved1 : 1; + } reg0240_synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 sli_poc_lsb : 16; + RK_U32 sli_hdr_ext_len : 9; + RK_U32 reserved : 7; + } reg0241_synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 st_ref_pic_flg : 1; + RK_U32 poc_lsb_lt0 : 16; + RK_U32 lt_idx_sps : 5; + RK_U32 num_lt_pic : 2; + RK_U32 st_ref_pic_idx : 6; + RK_U32 num_lt_sps : 2; + } reg0242_synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 used_by_s0_flg : 4; + RK_U32 num_pos_pic : 1; + RK_U32 num_negative_pics : 5; + RK_U32 dlt_poc_msb_cycl0 : 16; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + } reg0243_synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 dlt_poc_s0_m10 : 16; + RK_U32 dlt_poc_s0_m11 : 16; + } reg0244_synt_refm2; + + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } reg0245_synt_refm3; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } reg0246_synt_long_refm0; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } reg0247_synt_long_refm1; + + /* 0x000003e0 reg248 */ + struct { + RK_U32 sao_lambda_multi : 3; + RK_U32 reserved : 29; + } reg0248_sao_cfg; + + /* 0x3e4 - 0x3ec */ + RK_U32 reserved249_251[3]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 tile_w_m1 : 9; + RK_U32 reserved : 7; + RK_U32 tile_h_m1 : 9; + RK_U32 reserved1 : 6; + RK_U32 tile_en : 1; + } reg0252_tile_cfg; + + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 9; + RK_U32 reserved : 7; + RK_U32 tile_y : 9; + RK_U32 reserved1 : 7; + } reg0253_tile_pos; + + /* 0x000003f8 reg254 */ + struct { + RK_U32 slice_sta_x : 9; + RK_U32 reserved1 : 7; + RK_U32 slice_sta_y : 10; + RK_U32 reserved2 : 5; + RK_U32 slice_enc_ena : 1; + } slice_enc_cfg0; + + /* 0x000003fc reg255 */ + struct { + RK_U32 slice_end_x : 9; + RK_U32 reserved : 7; + RK_U32 slice_end_y : 10; + RK_U32 reserved1 : 6; + } slice_enc_cfg1; +} HevcVepu511Frame; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x00001160 reg1112 */ +typedef struct HevcVepu511RcRoi_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 26; + } roi_qthd3; + + /* 0x00001040 reg1040 */ + RK_U32 reserved_1040; + + /* 0x00001044 reg1041 */ + struct { + RK_U32 aq_tthd0 : 8; + RK_U32 aq_tthd1 : 8; + RK_U32 aq_tthd2 : 8; + RK_U32 aq_tthd3 : 8; + } aq_tthd0; + + /* 0x00001048 reg1042 */ + struct { + RK_U32 aq_tthd4 : 8; + RK_U32 aq_tthd5 : 8; + RK_U32 aq_tthd6 : 8; + RK_U32 aq_tthd7 : 8; + } aq_tthd1; + + /* 0x0000104c reg1043 */ + struct { + RK_U32 aq_tthd8 : 8; + RK_U32 aq_tthd9 : 8; + RK_U32 aq_tthd10 : 8; + RK_U32 aq_tthd11 : 8; + } aq_tthd2; + + /* 0x00001050 reg1044 */ + struct { + RK_U32 aq_tthd12 : 8; + RK_U32 aq_tthd13 : 8; + RK_U32 aq_tthd14 : 8; + RK_U32 aq_tthd15 : 8; + } aq_tthd3; + + /* 0x00001054 reg1045 */ + struct { + RK_U32 aq_stp_s0 : 5; + RK_U32 aq_stp_0t1 : 5; + RK_U32 aq_stp_1t2 : 5; + RK_U32 aq_stp_2t3 : 5; + RK_U32 aq_stp_3t4 : 5; + RK_U32 aq_stp_4t5 : 5; + RK_U32 reserved : 2; + } aq_stp0; + + /* 0x00001058 reg1046 */ + struct { + RK_U32 aq_stp_5t6 : 5; + RK_U32 aq_stp_6t7 : 5; + RK_U32 aq_stp_7t8 : 5; + RK_U32 aq_stp_8t9 : 5; + RK_U32 aq_stp_9t10 : 5; + RK_U32 aq_stp_10t11 : 5; + RK_U32 reserved : 2; + } aq_stp1; + + /* 0x0000105c reg1047 */ + struct { + RK_U32 aq_stp_11t12 : 5; + RK_U32 aq_stp_12t13 : 5; + RK_U32 aq_stp_13t14 : 5; + RK_U32 aq_stp_14t15 : 5; + RK_U32 aq_stp_b15 : 5; + RK_U32 reserved : 7; + } aq_stp2; + + /* 0x00001060 reg1048 */ + struct { + RK_U32 aq16_rnge : 4; + RK_U32 aq32_rnge : 4; + RK_U32 aq8_rnge : 5; + RK_U32 aq16_dif0 : 5; + RK_U32 aq16_dif1 : 5; + RK_U32 reserved : 1; + RK_U32 aq_cme_en : 1; + RK_U32 aq_subj_cme_en : 1; + RK_U32 aq_rme_en : 1; + RK_U32 aq_subj_rme_en : 1; + RK_U32 reserved1 : 4; + } aq_clip; + + /* 0x00001064 reg1049 */ + struct { + RK_U32 madi_th0 : 8; + RK_U32 madi_th1 : 8; + RK_U32 madi_th2 : 8; + RK_U32 reserved : 8; + } madi_st_thd; + + /* 0x00001068 reg1050 */ + struct { + RK_U32 madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_th1 : 12; + RK_U32 reserved1 : 4; + } madp_st_thd0; + + /* 0x0000106c reg1051 */ + struct { + RK_U32 madp_th2 : 12; + RK_U32 reserved : 20; + } madp_st_thd1; + + /* 0x1070 - 0x1078 */ + RK_U32 reserved1070_1078[3]; + + /* 0x0000107c reg1055 */ + struct { + RK_U32 chrm_klut_ofst : 4; + RK_U32 reserved : 28; + } klut_ofst; + + /* 0x00001080 reg1056 */ + struct { + RK_U32 fmdc_adju_intra16 : 4; + RK_U32 fmdc_adju_inter16 : 4; + RK_U32 fmdc_adju_split16 : 4; + RK_U32 fmdc_adju_res_intra16 : 4; + RK_U32 fmdc_adju_res_inter16 : 4; + RK_U32 fmdc_adju_res_zeromv16 : 4; + RK_U32 fmdc_adju_pri : 5; + RK_U32 reserved : 3; + } fmdc_adj0; + + /* 0x00001084 reg1057 */ + struct { + RK_U32 fmdc_adju_intra32 : 4; + RK_U32 fmdc_adju_inter32 : 4; + RK_U32 fmdc_adju_split32 : 4; + RK_U32 fmdc_adju_res_intra32 : 4; + RK_U32 fmdc_adju_res_inter32 : 4; + RK_U32 fmdc_adju_res_zeromv32 : 4; + RK_U32 fmdc_adju_split8 : 4; + RK_U32 fmdc_adju_lt_ref32 : 4; + } fmdc_adj1; + + /* 0x1088 */ + RK_U32 reserved_1058; + + /* 0x0000108c reg1059 */ + struct { + RK_U32 bmap_en : 1; + RK_U32 bmap_pri : 5; + RK_U32 bmap_qpmin : 6; + RK_U32 bmap_qpmax : 6; + RK_U32 bmap_mdc_dpth : 1; + RK_U32 reserved : 13; + } bmap_cfg; + + /* 0x00001090 reg1060 - 0x0000112c reg1099 */ + Vepu511RoiCfg roi_cfg; + + /* 0x00001130 reg1100 */ + struct { + RK_U32 base_thre_rough_mad32_intra : 4; + RK_U32 delta0_thre_rough_mad32_intra : 4; + RK_U32 delta1_thre_rough_mad32_intra : 6; + RK_U32 delta2_thre_rough_mad32_intra : 6; + RK_U32 delta3_thre_rough_mad32_intra : 7; + RK_U32 delta4_thre_rough_mad32_intra_low5 : 5; + } cudecis_thd0; + + /* 0x00001134 reg1101 */ + struct { + RK_U32 delta4_thre_rough_mad32_intra_high2 : 2; + RK_U32 delta5_thre_rough_mad32_intra : 7; + RK_U32 delta6_thre_rough_mad32_intra : 7; + RK_U32 base_thre_fine_mad32_intra : 4; + RK_U32 delta0_thre_fine_mad32_intra : 4; + RK_U32 delta1_thre_fine_mad32_intra : 5; + RK_U32 delta2_thre_fine_mad32_intra_low3 : 3; + } cudecis_thd1; + + /* 0x00001138 reg1102 */ + struct { + RK_U32 delta2_thre_fine_mad32_intra_high2 : 2; + RK_U32 delta3_thre_fine_mad32_intra : 5; + RK_U32 delta4_thre_fine_mad32_intra : 5; + RK_U32 delta5_thre_fine_mad32_intra : 6; + RK_U32 delta6_thre_fine_mad32_intra : 6; + RK_U32 base_thre_str_edge_mad32_intra : 3; + RK_U32 delta0_thre_str_edge_mad32_intra : 2; + RK_U32 delta1_thre_str_edge_mad32_intra : 3; + } cudecis_thd2; + + /* 0x0000113c reg1103 */ + struct { + RK_U32 delta2_thre_str_edge_mad32_intra : 3; + RK_U32 delta3_thre_str_edge_mad32_intra : 4; + RK_U32 base_thre_str_edge_bgrad32_intra : 5; + RK_U32 delta0_thre_str_edge_bgrad32_intra : 2; + RK_U32 delta1_thre_str_edge_bgrad32_intra : 3; + RK_U32 delta2_thre_str_edge_bgrad32_intra : 4; + RK_U32 delta3_thre_str_edge_bgrad32_intra : 5; + RK_U32 base_thre_mad16_intra : 3; + RK_U32 delta0_thre_mad16_intra : 3; + } cudecis_thd3; + + /* 0x00001140 reg1104 */ + struct { + RK_U32 delta1_thre_mad16_intra : 3; + RK_U32 delta2_thre_mad16_intra : 4; + RK_U32 delta3_thre_mad16_intra : 5; + RK_U32 delta4_thre_mad16_intra : 5; + RK_U32 delta5_thre_mad16_intra : 6; + RK_U32 delta6_thre_mad16_intra : 6; + RK_U32 delta0_thre_mad16_ratio_intra : 3; + } cudecis_thd4; + + /* 0x00001144 reg1105 */ + struct { + RK_U32 delta1_thre_mad16_ratio_intra : 3; + RK_U32 delta2_thre_mad16_ratio_intra : 3; + RK_U32 delta3_thre_mad16_ratio_intra : 3; + RK_U32 delta4_thre_mad16_ratio_intra : 3; + RK_U32 delta5_thre_mad16_ratio_intra : 3; + RK_U32 delta6_thre_mad16_ratio_intra : 3; + RK_U32 delta7_thre_mad16_ratio_intra : 3; + RK_U32 delta0_thre_rough_bgrad32_intra : 3; + RK_U32 delta1_thre_rough_bgrad32_intra : 4; + RK_U32 delta2_thre_rough_bgrad32_intra_low4 : 4; + } cudecis_thd5; + + /* 0x00001148 reg1106 */ + struct { + RK_U32 delta2_thre_rough_bgrad32_intra_high2 : 2; + RK_U32 delta3_thre_rough_bgrad32_intra : 10; + RK_U32 delta4_thre_rough_bgrad32_intra : 10; + RK_U32 delta5_thre_rough_bgrad32_intra_low10 : 10; + } cudecis_thd6; + + /* 0x0000114c reg1107 */ + struct { + RK_U32 delta5_thre_rough_bgrad32_intra_high1 : 1; + RK_U32 delta6_thre_rough_bgrad32_intra : 12; + RK_U32 delta7_thre_rough_bgrad32_intra : 13; + RK_U32 delta0_thre_bgrad16_ratio_intra : 4; + RK_U32 delta1_thre_bgrad16_ratio_intra_low2 : 2; + } cudecis_thd7; + + /* 0x00001150 reg1108 */ + struct { + RK_U32 delta1_thre_bgrad16_ratio_intra_high2 : 2; + RK_U32 delta2_thre_bgrad16_ratio_intra : 4; + RK_U32 delta3_thre_bgrad16_ratio_intra : 4; + RK_U32 delta4_thre_bgrad16_ratio_intra : 4; + RK_U32 delta5_thre_bgrad16_ratio_intra : 4; + RK_U32 delta6_thre_bgrad16_ratio_intra : 4; + RK_U32 delta7_thre_bgrad16_ratio_intra : 4; + RK_U32 delta0_thre_fme_ratio_inter : 3; + RK_U32 delta1_thre_fme_ratio_inter : 3; + } cudecis_thd8; + + /* 0x00001154 reg1109 */ + struct { + RK_U32 delta2_thre_fme_ratio_inter : 3; + RK_U32 delta3_thre_fme_ratio_inter : 3; + RK_U32 delta4_thre_fme_ratio_inter : 3; + RK_U32 delta5_thre_fme_ratio_inter : 3; + RK_U32 delta6_thre_fme_ratio_inter : 3; + RK_U32 delta7_thre_fme_ratio_inter : 3; + RK_U32 base_thre_fme32_inter : 3; + RK_U32 delta0_thre_fme32_inter : 3; + RK_U32 delta1_thre_fme32_inter : 4; + RK_U32 delta2_thre_fme32_inter : 4; + } cudecis_thd9; + + /* 0x00001158 reg1110 */ + struct { + RK_U32 delta3_thre_fme32_inter : 5; + RK_U32 delta4_thre_fme32_inter : 6; + RK_U32 delta5_thre_fme32_inter : 7; + RK_U32 delta6_thre_fme32_inter : 8; + RK_U32 thre_cme32_inter : 6; + } cudecis_thd10; + + /* 0x0000115c reg1111 */ + struct { + RK_U32 delta0_thre_mad_fme_ratio_inter : 4; + RK_U32 delta1_thre_mad_fme_ratio_inter : 4; + RK_U32 delta2_thre_mad_fme_ratio_inter : 4; + RK_U32 delta3_thre_mad_fme_ratio_inter : 4; + RK_U32 delta4_thre_mad_fme_ratio_inter : 4; + RK_U32 delta5_thre_mad_fme_ratio_inter : 4; + RK_U32 delta6_thre_mad_fme_ratio_inter : 4; + RK_U32 delta7_thre_mad_fme_ratio_inter : 4; + } cudecis_thd11; + + /* 0x00001160 reg1112 */ + struct { + RK_U32 delta0_thre_cme32_static_inter : 4; + RK_U32 delta1_thre_cme32_static_inter : 4; + RK_U32 delta2_thre_cme32_static_inter : 4; + RK_U32 delta3_thre_cme32_static_inter : 4; + RK_U32 delta4_thre_cme32_static_inter : 4; + RK_U32 delta5_thre_cme32_static_inter : 4; + RK_U32 delta6_thre_cme32_static_inter : 4; + RK_U32 delta7_thre_cme32_static_inter : 4; + } cudecis_thd12; +} HevcVepu511RcRoi; + +/* class: iprd/iprd_wgt/rdo_wgta/prei_dif*/ +/* 0x00001700 reg1472 - 0x00001cd4 reg1845 */ +typedef struct HevcVepu511Param_t { + /* 0x00001700 reg1472 - 0x0000172c reg1483*/ + RK_U32 reserved_1472_1483[12]; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 bias_madi_th0 : 8; + RK_U32 bias_madi_th1 : 8; + RK_U32 bias_madi_th2 : 8; + RK_U32 reserved : 8; + } bias_madi_thd_comb; + + /* 0x00001734 reg1485 */ + struct { + RK_U32 bias_i_val0 : 10; + RK_U32 bias_i_val1 : 10; + RK_U32 bias_i_val2 : 10; + RK_U32 reserved : 2; + } qnt0_i_bias_comb; + + /* 0x00001738 reg1486 */ + struct { + RK_U32 bias_i_val3 : 10; + RK_U32 reserved : 22; + } qnt1_i_bias_comb; + + /* 0x0000173c reg1487 */ + struct { + RK_U32 bias_p_val0 : 10; + RK_U32 bias_p_val1 : 10; + RK_U32 bias_p_val2 : 10; + RK_U32 reserved : 2; + } qnt0_p_bias_comb; + + /* 0x00001740 reg1488 */ + struct { + RK_U32 bias_p_val3 : 10; + RK_U32 reserved : 22; + } qnt1_p_bias_comb; + + /* 0x00001744 reg1489 */ + struct { + RK_U32 light_change_en : 1; + RK_U32 light_ratio_mult1 : 5; + RK_U32 light_ratio_mult2 : 4; + RK_U32 light_thre_csu1_cnt : 2; + RK_U32 srch_rgn_en : 1; + RK_U32 reserved : 3; + RK_U32 light_thre_madp : 8; + RK_U32 light_thre_lightmadp : 8; + } light_cfg; + + /* 0x1748 - 0x175c */ + RK_U32 reserved1490_1495[6]; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 reserved : 2; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 fme_lvl_mrg : 1; + RK_U32 reserved1 : 16; + } me_sqi_cfg; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 ratio_consi_cfg : 4; + RK_U32 ratio_bmv_dist : 4; + RK_U32 reserved : 12; + } cime_madp_th; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 reg1536 - 0x000018cc reg1587*/ + RK_U32 pprd_lamb_satd_0_51[52]; + + /* 0x000018d0 reg1588 */ + struct { + RK_U32 lambda_luma_offset : 5; + RK_U32 lambda_chroma_offset : 5; + RK_U32 reserved : 22; + } prmd_intra_lamb_ofst; + + /* 0x18d4 - 0x18fc */ + RK_U32 reserved1589_1599[11]; + + /* 0x00001900 reg1600 - 0x000019cc reg1651*/ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} HevcVepu511Param; + +typedef struct RdoSkipPar_t { + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + /* only b32 skip support */ + RK_U32 reserved1 : 1; + RK_U32 flckr_frame_qp_en : 1; + RK_U32 flckr_lgt_chng_en : 1; + RK_U32 flckr_en : 1; + } atf_thd0; + + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd3 : 12; + RK_U32 reserved1 : 4; + } atf_thd1; + + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt0; + + RK_U32 reserved; +} RdoSkipPar; + +typedef struct RdoNoSkipPar_t { + struct { + RK_U32 madp_thd0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_thd1 : 12; + RK_U32 reserved1 : 4; + } atf_thd0; + + struct { + RK_U32 madp_thd2 : 12; + RK_U32 reserved : 4; + /* only rdo_b32_inter support */ + RK_U32 atf_bypass_pri_flag : 1; + RK_U32 reserved1 : 15; + } atf_thd1; + + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } atf_wgt; +} RdoNoSkipPar; + +/* 0x00002000 reg2048 - 0x0000216c reg2139 */ +typedef struct HevcVepu511Sqi_t { + /* 0x00002000 reg2048 */ + struct { + RK_U32 subj_opt_en : 1; + RK_U32 subj_opt_strength : 3; + RK_U32 aq_subj_en : 1; + RK_U32 aq_subj_strength : 3; + RK_U32 bndry_cmplx_static_choose_en : 2; + RK_U32 feature_cal_en : 1; + RK_U32 reserved : 1; + RK_U32 thre_sum_grdn_point : 20; + } subj_opt_cfg; + + /* 0x00002004 reg2049 */ + struct { + RK_U32 common_thre_num_grdn_point_dep0 : 8; + RK_U32 common_thre_num_grdn_point_dep1 : 8; + RK_U32 common_thre_num_grdn_point_dep2 : 8; + RK_U32 reserved : 8; + } subj_opt_dpth_thd; + + /* 0x00002008 reg2050 */ + struct { + RK_U32 cover_rdo_mode_intra_jcoef_d0 : 6; + RK_U32 cover_rdo_mode_intra_jcoef_d1 : 6; + RK_U32 cover_rmd_mode_intra_jcoef_d0 : 6; + RK_U32 cover_rmd_mode_intra_jcoef_d1 : 6; + RK_U32 cover_rdoq_rcoef_d0 : 4; + RK_U32 cover_rdoq_rcoef_d1 : 4; + } smear_opt_rmd_intra; + + /* 0x0000200c reg2051 */ + struct { + RK_U32 cfc_rmd_mode_intra_jcoef_d0 : 6; + RK_U32 cfc_rmd_mode_intra_jcoef_d1 : 6; + RK_U32 cfc_rdo_mode_intra_jcoef_d0 : 6; + RK_U32 cfc_rdo_mode_intra_jcoef_d1 : 6; + RK_U32 cfc_rdoq_rcoef_d0 : 4; + RK_U32 cfc_rdoq_rcoef_d1 : 4; + } smear_opt_cfg_coef; + + /* 0x00002010 reg2052 */ + struct { + RK_U32 anti_smear_en : 1; + RK_U32 frm_static : 1; + RK_U32 smear_stor_en : 1; + RK_U32 smear_load_en : 1; + RK_U32 smear_strength : 3; + RK_U32 reserved : 1; + RK_U32 thre_mv_inconfor_cime : 4; + RK_U32 thre_mv_confor_cime : 2; + RK_U32 thre_mv_confor_cime_gmv : 2; + RK_U32 thre_mv_inconfor_cime_gmv : 4; + RK_U32 thre_num_mv_confor_cime : 2; + RK_U32 thre_num_mv_confor_cime_gmv : 2; + RK_U32 ref1_subj_opt_en : 1; + RK_U32 smear_cfc_en : 1; + RK_U32 reserved1 : 6; + } smear_opt_cfg0; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 dist0_frm_avg : 14; + RK_U32 thre_dsp_static : 5; + RK_U32 thre_dsp_mov : 5; + RK_U32 thre_dist_mv_confor_cime : 7; + RK_U32 reserved : 1; + } smear_opt_cfg1; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 thre_madp_stc_dep0 : 4; + RK_U32 thre_madp_stc_dep1 : 4; + RK_U32 thre_madp_stc_dep2 : 4; + RK_U32 thre_madp_mov_dep0 : 6; + RK_U32 thre_madp_mov_dep1 : 6; + RK_U32 thre_madp_mov_dep2 : 6; + RK_U32 reserved : 2; + } smear_madp_thd; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 thre_num_pt_stc_dep0 : 6; + RK_U32 thre_num_pt_stc_dep1 : 4; + RK_U32 thre_num_pt_stc_dep2 : 2; + RK_U32 reserved : 4; + RK_U32 thre_num_pt_mov_dep0 : 6; + RK_U32 thre_num_pt_mov_dep1 : 4; + RK_U32 thre_num_pt_mov_dep2 : 2; + RK_U32 reserved1 : 4; + } smear_stat_thd; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 confor_cime_gmv0 : 5; + RK_U32 reserved : 3; + RK_U32 confor_cime_gmv1 : 5; + RK_U32 reserved1 : 3; + RK_U32 inconfor_cime_gmv0 : 6; + RK_U32 reserved2 : 2; + RK_U32 inconfor_cime_gmv1 : 6; + RK_U32 reserved3 : 2; + } smear_bmv_dist_thd0; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 inconfor_cime_gmv2 : 6; + RK_U32 reserved : 2; + RK_U32 inconfor_cime_gmv3 : 6; + RK_U32 reserved1 : 2; + RK_U32 inconfor_cime_gmv4 : 6; + RK_U32 reserved2 : 10; + } smear_bmv_dist_thd1; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 thre_min_num_confor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_max_num_confor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_min_num_inconfor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_max_num_inconfor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_split_dep0 : 2; + RK_U32 thre_zero_srgn : 5; + RK_U32 reserved : 1; + RK_U32 madi_thre_dep0 : 8; + RK_U32 madi_thre_dep1 : 8; + } smear_min_bndry_gmv; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 thre_madp_stc_cover0 : 6; + RK_U32 thre_madp_stc_cover1 : 6; + RK_U32 thre_madp_mov_cover0 : 5; + RK_U32 thre_madp_mov_cover1 : 5; + RK_U32 smear_qp_strength : 4; + RK_U32 smear_thre_qp : 6; + } smear_madp_cov_thd; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 skin_en : 1; + RK_U32 skin_strength : 3; + RK_U32 thre_uvsqr16_skin : 8; + RK_U32 skin_thre_cst_best_mad : 10; + RK_U32 skin_thre_cst_best_grdn_blk : 7; + RK_U32 reserved : 1; + RK_U32 frame_skin_ratio : 2; + } skin_opt_cfg; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 thre_sum_mad_intra : 2; + RK_U32 thre_sum_grdn_blk_intra : 2; + RK_U32 vld_thre_skin_v : 3; + RK_U32 reserved : 1; + RK_U32 thre_min_skin_u : 8; + RK_U32 thre_max_skin_u : 8; + RK_U32 thre_min_skin_v : 8; + } skin_chrm_thd; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 block_en : 1; + RK_U32 reserved : 1; + RK_U32 block_thre_cst_best_mad : 10; + RK_U32 reserved1 : 4; + RK_U32 block_thre_cst_best_grdn_blk : 6; + RK_U32 reserved2 : 2; + RK_U32 thre_num_grdnt_point_cmplx : 2; + RK_U32 block_delta_qp_flag : 2; + RK_U32 reserved3 : 4; + } block_opt_cfg; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 cmplx_thre_cst_best_mad_dep0 : 13; + RK_U32 reserved : 3; + RK_U32 cmplx_thre_cst_best_mad_dep1 : 13; + RK_U32 reserved1 : 2; + RK_U32 cmplx_en : 1; + } cmplx_opt_cfg; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 cmplx_thre_cst_best_mad_dep2 : 13; + RK_U32 reserved : 3; + RK_U32 cmplx_thre_cst_best_grdn_blk_dep0 : 11; + RK_U32 reserved1 : 5; + } cmplx_bst_mad_thd; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 cmplx_thre_cst_best_grdn_blk_dep1 : 11; + RK_U32 reserved : 5; + RK_U32 cmplx_thre_cst_best_grdn_blk_dep2 : 11; + RK_U32 reserved1 : 5; + } cmplx_bst_grdn_thd; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 line_en : 1; + RK_U32 line_thre_min_cst_best_grdn_blk_dep0 : 5; + RK_U32 line_thre_min_cst_best_grdn_blk_dep1 : 8; + RK_U32 line_thre_min_cst_best_grdn_blk_dep2 : 8; + RK_U32 line_thre_ratio_best_grdn_blk_dep0 : 4; + RK_U32 line_thre_ratio_best_grdn_blk_dep1 : 4; + RK_U32 reserved : 2; + } line_opt_cfg; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 line_thre_max_cst_best_grdn_blk_dep0 : 7; + RK_U32 reserved : 1; + RK_U32 line_thre_max_cst_best_grdn_blk_dep1 : 8; + RK_U32 line_thre_max_cst_best_grdn_blk_dep2 : 8; + RK_U32 reserved1 : 8; + } line_cst_bst_grdn; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 line_thre_qp : 6; + RK_U32 block_strength : 3; + RK_U32 block_thre_qp : 6; + RK_U32 cmplx_strength : 3; + RK_U32 cmplx_thre_qp : 6; + RK_U32 cmplx_thre_max_grdn_blk : 6; + RK_U32 reserved : 2; + } subj_opt_dqp0; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 skin_thre_qp : 6; + RK_U32 smear_frame_thre_qp : 6; + RK_U32 bndry_rdo_mode_intra_jcoef_d0 : 6; + RK_U32 bndry_rdo_mode_intra_jcoef_d1 : 6; + RK_U32 skin_thre_madp : 8; + } subj_opt_dqp1; + + /* 0x00002058 reg2070 */ + struct { + RK_U32 line_rdo_split_rcoef_d0 : 5; + RK_U32 line_rdo_split_rcoef_d1 : 5; + RK_U32 choose_cu32_split_jcoef : 6; + RK_U32 choose_cu16_split_jcoef : 5; + RK_U32 reserved : 11; + } subj_opt_rdo_split; + + /* 0x0000205c reg2071 */ + struct { + RK_U32 lid_grdn_blk_cu16_th : 8; + RK_U32 lid_rmd_intra_jcoef_ang : 5; + RK_U32 lid_rdo_intra_rcoef_ang : 5; + RK_U32 lid_rmd_intra_jcoef_dp : 6; + RK_U32 lid_rdo_intra_rcoef_dp : 6; + RK_U32 lid_en : 1; + RK_U32 reserved : 1; + } line_intra_dir_cfg; + + /* 0x00002060 reg2072 - 0x206c reg2075 */ + RdoSkipPar rdo_b32_skip; + + /* 0x00002070 reg2076 - 0x0000207c reg2079 */ + RdoSkipPar rdo_b16_skip; + + /* 0x00002080 reg2080 - 0x00002088 reg2082 */ + RdoNoSkipPar rdo_b32_inter; + + /* 0x0000208c reg2083 - 0x00002094 reg2085 */ + RdoNoSkipPar rdo_b16_inter; + + /* 0x00002098 reg2086 - 0x000020a0 reg2088 */ + RdoNoSkipPar rdo_b32_intra; + + /* 0x000020a4 reg2089 - 0x000020ac reg2091 */ + RdoNoSkipPar rdo_b16_intra; + + /* 0x000020b0 reg2092 */ + struct { + RK_U32 ref1_rmd_mode_lr_jcoef_d0 : 5; + RK_U32 ref1_rmd_mode_lr_jcoef_d1 : 5; + RK_U32 ref1_rdo_mode_lr_jcoef_d0 : 5; + RK_U32 ref1_rdo_mode_lr_jcoef_d1 : 5; + RK_U32 ref1_rmd_mv_lr_jcoef_d0 : 5; + RK_U32 ref1_rmd_mv_lr_jcoef_d1 : 5; + RK_U32 reserved : 2; + } smear_ref1_cfg0; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 ref1_rdo_inter_tu_res_joef_d0 : 5; + RK_U32 ref1_rdo_inter_tu_res_joef_d1 : 5; + RK_U32 ref1_rdoq_zero_mv_rcoef_d0 : 5; + RK_U32 ref1_rdoq_zero_mv_rcoef_d1 : 5; + RK_U32 ref1_rmd_inter_lr_jcoef_d0 : 5; + RK_U32 ref1_rmd_inter_lr_jcoef_d1 : 5; + RK_U32 reserved : 2; + } smear_ref1_cfg1; + + /* 0x000020b8 reg2094 - 0x000020bc reg2095*/ + RK_U32 reserved_2094_2095[2]; + + /* 0x000020c0 reg2096 */ + struct { + RK_U32 thre_max_luma_dark : 8; + RK_U32 thre_min_luma_bright : 8; + RK_U32 thre_ratio_dark_bright : 6; + RK_U32 reserved : 2; + RK_U32 thre_qp_dark_bright : 6; + RK_U32 reserved1 : 1; + RK_U32 dark_bright_en : 1; + } dark_brgt_opt_cfg; + + /* 0x000020c4 reg2097 */ + struct { + RK_U32 madp_th_dep0_dark_bright : 8; + RK_U32 madp_th_dep1_dark_bright : 8; + RK_U32 madi_th_dep0_dark_bright : 6; + RK_U32 reserved : 2; + RK_U32 madi_th_dep1_dark_bright : 6; + RK_U32 reserved1 : 2; + } dark_brgt_madi_thd; + + /* 0x000020c8 reg2098 */ + struct { + RK_U32 dark_bright_inter_res_j_coef_wgt_dep0 : 8; + RK_U32 dark_bright_inter_res_j_coef_wgt_dep1 : 8; + RK_U32 dark_bright_intra_j_coef_wgt_dep0 : 8; + RK_U32 dark_bright_intra_j_coef_wgt_dep1 : 8; + } dark_brgt_wgt0; + + /* 0x000020cc reg2099 */ + struct { + RK_U32 dark_bright_nsp_j_coef_wgt_dep0 : 6; + RK_U32 reserved : 2; + RK_U32 dark_bright_nsp_j_coef_wgt_dep1 : 6; + RK_U32 reserved1 : 18; + } dark_brgt_wgt1; + + /* 0x000020d0 reg2100 */ + struct { + RK_U32 cmplx_static_en : 1; + RK_U32 cmplx_static_lgt_chng_en : 1; + RK_U32 thre_qp_cmplx_static : 6; + RK_U32 madp_th0_dep0_cmplx_static : 6; + RK_U32 madp_th1_dep0_cmplx_static : 8; + RK_U32 madp_th2_dep0_cmplx_static : 10; + } cmplx_statc_cfg; + + /* 0x000020d4 reg2101 */ + struct { + RK_U32 num_grdn_point_th1_dep0_cmplx_static : 8; + RK_U32 num_grdn_point_th2_dep0_cmplx_static : 8; + RK_U32 madi_th1_dep0_cmplx_static : 6; + RK_U32 reserved : 2; + RK_U32 madi_th2_dep0_cmplx_static : 6; + RK_U32 reserved1 : 2; + } cmplx_statc_thd0; + + /* 0x000020d8 reg2102 */ + struct { + RK_U32 madp_th0_dep1_cmplx_static : 6; + RK_U32 madp_th1_dep1_cmplx_static : 8; + RK_U32 madp_th2_dep1_cmplx_static : 10; + RK_U32 static_num_thre_dep1_cmplx_static : 2; + RK_U32 srch_rgn_mv_th_cmplx_static : 5; + RK_U32 reserved : 1; + } cmplx_statc_thd1; + + /* 0x000020dc reg2103 */ + struct { + RK_U32 num_grdn_point_th1_dep1_cmplx_static : 6; + RK_U32 num_grdn_point_th2_dep1_cmplx_static : 6; + RK_U32 madi_th1_dep1_cmplx_static : 6; + RK_U32 madi_th2_dep1_cmplx_static : 6; + RK_U32 cmplx_static_num_cu16_th : 3; + RK_U32 cmplx_static_frame_qp_en : 1; + RK_U32 cmplx_static_ratio_light_madp_th : 2; + RK_U32 reserved : 2; + } cmplx_statc_thd2; + + /* 0x000020e0 reg2104 */ + struct { + RK_U32 cmplx_static_inter_res_j_coef_wgt1_dep0 : 8; + RK_U32 cmplx_static_inter_res_j_coef_wgt2_dep0 : 8; + RK_U32 cmplx_static_inter_res_j_coef_wgt1_dep1 : 8; + RK_U32 cmplx_static_inter_res_j_coef_wgt2_dep1 : 8; + } cmplx_statc_wgt0; + + /* 0x000020e4 reg2105 */ + struct { + RK_U32 cmplx_static_intra_j_coef_wgt1_dep0 : 8; + RK_U32 cmplx_static_intra_j_coef_wgt2_dep0 : 8; + RK_U32 cmplx_static_intra_j_coef_wgt1_dep1 : 8; + RK_U32 cmplx_static_intra_j_coef_wgt2_dep1 : 8; + } cmplx_statc_wgt1; + + /* 0x000020e8 reg2106 */ + struct { + RK_U32 cmplx_static_split_rcoef_w1d0 : 6; + RK_U32 cmplx_static_split_rcoef_w1d1 : 6; + RK_U32 cmplx_static_split_rcoef_w2d0 : 6; + RK_U32 cmplx_static_split_rcoef_w2d1 : 6; + RK_U32 reserved : 8; + } cmplx_statc_wgt2; + + /* 0x20ec - 0x20fc */ + RK_U32 reserved2107_2111[5]; + + /* 0x00002100 reg2112 */ + struct { + RK_U32 blur_low_madi_thd : 7; + RK_U32 reserved : 1; + RK_U32 blur_high_madi_thd : 7; + RK_U32 reserved1 : 1; + RK_U32 blur_low_cnt_thd : 4; + RK_U32 blur_hight_cnt_thd : 4; + RK_U32 blur_sum_cnt_thd : 4; + RK_U32 anti_blur_en : 1; + RK_U32 scene_mode : 1; + RK_U32 reserved2 : 2; + } subj_anti_blur_thd; + + /* 0x00002104 reg2113 */ + struct { + RK_U32 blur_motion_thd : 12; + RK_U32 sao_ofst_thd_eo_luma : 3; + RK_U32 reserved : 1; + RK_U32 sao_ofst_thd_bo_luma : 3; + RK_U32 reserved1 : 1; + RK_U32 sao_ofst_thd_eo_chroma : 3; + RK_U32 reserved2 : 1; + RK_U32 sao_ofst_thd_bo_chroma : 3; + RK_U32 reserved3 : 5; + } subj_anti_blur_sao; + + /* 0x00002108 reg2114 */ + struct { + RK_U32 notmerge_ofst_dist_eo_wgt0 : 8; + RK_U32 notmerge_ofst_dist_bo_wgt0 : 8; + RK_U32 notmerge_ofst_dist_eo_wgt1 : 8; + RK_U32 notmerge_ofst_dist_bo_wgt1 : 8; + } subj_anti_blur_wgt0; + + /* 0x0000210c reg2115 */ + struct { + RK_U32 notmerge_ofst_lambda_eo_wgt0 : 8; + RK_U32 notmerge_ofst_lambda_bo_wgt0 : 8; + RK_U32 notmerge_compare_dist_eo_wgt0 : 8; + RK_U32 notmerge_compare_dist_bo_wgt0 : 8; + } subj_anti_blur_wgt1; + + /* 0x00002110 reg2116 */ + struct { + RK_U32 notmerge_compare_dist_eo_wgt1 : 8; + RK_U32 notmerge_compare_dist_bo_wgt1 : 8; + RK_U32 notmerge_compare_rate_eo_wgt0 : 8; + RK_U32 notmerge_compare_rate_bo_wgt0 : 8; + } subj_anti_blur_wgt2; + + /* 0x00002114 reg2117 */ + struct { + RK_U32 sao_mode_compare_dist_eo_wgt0 : 8; + RK_U32 sao_mode_compare_dist_bo_wgt0 : 8; + RK_U32 merge_cost_dist_eo_wgt0 : 8; + RK_U32 merge_cost_dist_bo_wgt0 : 8; + } subj_anti_blur_wgt3; + + /* 0x00002118 reg2118 */ + struct { + RK_U32 merge_cost_dist_eo_wgt1 : 8; + RK_U32 merge_cost_dist_bo_wgt1 : 8; + RK_U32 merge_cost_bit_eo_wgt0 : 8; + RK_U32 merge_cost_bit_bo_wgt0 : 8; + } subj_anti_blur_wgt4; + + /* 0x211c */ + RK_U32 reserved_2119; + + union { + RK_U8 pre_i32_cst_thd[14]; + + struct { + /* 0x00002120 reg2120 */ + struct { + RK_U32 madi_thd0 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd1 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd2 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd3 : 7; + RK_U32 reserved3 : 1; + } pre_i32_cst_thd0; + + /* 0x00002124 reg2121 */ + struct { + RK_U32 madi_thd4 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd5 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd6 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd7 : 7; + RK_U32 reserved3 : 1; + } pre_i32_cst_thd1; + + /* 0x00002128 reg2122 */ + struct { + RK_U32 madi_thd8 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd9 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd10 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd11 : 7; + RK_U32 reserved3 : 1; + } pre_i32_cst_thd2; + + /* 0x0000212c reg2123 */ + struct { + RK_U32 madi_thd12 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd13 : 7; + RK_U32 reserved1 : 1; + RK_U32 mode_th : 3; + RK_U32 reserved2 : 1; + RK_U32 qp_thd : 6; + RK_U32 reserved3 : 6; + } pre_i32_cst_thd3; + }; + }; + + union { + RK_U8 pre_i32_cst_wgt[15]; + + struct { + /* 0x00002130 reg2124 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } pre_i32_cst_wgt0; + + /* 0x00002134 reg2125 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 wgt5 : 8; + RK_U32 wgt6 : 8; + RK_U32 wgt7 : 8; + } pre_i32_cst_wgt1; + + /* 0x00002138 reg2126 */ + struct { + RK_U32 wgt8 : 8; + RK_U32 wgt9 : 8; + RK_U32 wgt10 : 8; + RK_U32 wgt11 : 8; + } pre_i32_cst_wgt2; + /* 0x0000213c reg2127 */ + struct { + RK_U32 wgt12 : 8; + RK_U32 wgt13 : 8; + RK_U32 wgt14 : 8; + RK_U32 i32_lambda_mv_bit : 3; + RK_U32 reserved : 1; + RK_U32 i16_lambda_mv_bit : 3; + RK_U32 anti_strp_e : 1; + } pre_i32_cst_wgt3; + }; + }; + + union { + RK_U8 pre_i16_cst_thd[14]; + + struct { + /* 0x00002140 reg2128 */ + struct { + RK_U32 madi_thd0 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd1 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd2 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd3 : 7; + RK_U32 reserved3 : 1; + } pre_i16_cst_thd0; + + /* 0x00002144 reg2129 */ + struct { + RK_U32 madi_thd4 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd5 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd6 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd7 : 7; + RK_U32 reserved3 : 1; + } pre_i16_cst_thd1; + + /* 0x00002148 reg2130 */ + struct { + RK_U32 madi_thd8 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd9 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd10 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd11 : 7; + RK_U32 reserved3 : 1; + } pre_i16_cst_thd2; + + /* 0x0000214c reg2131 */ + struct { + RK_U32 madi_thd12 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd13 : 7; + RK_U32 reserved1 : 1; + RK_U32 mode_th : 3; + RK_U32 reserved2 : 13; + } pre_i16_cst_thd3; + }; + }; + + union { + RK_U8 pre_i16_cst_wgt[15]; + + struct { + /* 0x00002150 reg2132 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } pre_i16_cst_wgt0; + + /* 0x00002154 reg2133 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 wgt5 : 8; + RK_U32 wgt6 : 8; + RK_U32 wgt7 : 8; + } pre_i16_cst_wgt1; + + /* 0x00002158 reg2134 */ + struct { + RK_U32 wgt8 : 8; + RK_U32 wgt9 : 8; + RK_U32 wgt10 : 8; + RK_U32 wgt11 : 8; + } pre_i16_cst_wgt2; + /* 0x0000215c reg2135 */ + struct { + RK_U32 wgt12 : 8; + RK_U32 wgt13 : 8; + RK_U32 wgt14 : 8; + RK_U32 i8_lambda_mv_bit : 3; + RK_U32 reserved : 1; + RK_U32 i4_lambda_mv_bit : 3; + RK_U32 reserved1 : 1; + } pre_i16_cst_wgt3; + }; + }; + + /* 0x00002160 reg2136 */ + struct { + RK_U32 offset_thd : 4; + RK_U32 offset_diff_thd : 4; + RK_U32 weak_texture_offset_thd : 3; + RK_U32 weak_texture_offset_diff_thd : 3; + RK_U32 reserved : 18; + } atr_thd; + + /* 0x00002164 reg2137 - 0x0000216c reg2139 */ + RK_U32 reserved_2137_2139[3]; +} HevcVepu511Sqi; + +typedef struct H265eV511RegSet_t { + Vepu511ControlCfg reg_ctl; + HevcVepu511Frame reg_frm; + HevcVepu511RcRoi reg_rc_roi; + HevcVepu511Param reg_param; + HevcVepu511Sqi reg_sqi; + Vepu511SclJpgTbl reg_scl_jpgtbl; + Vepu511OsdComb reg_osd; + Vepu511Status reg_st; + Vepu511Dbg reg_dbg; +} H265eV511RegSet; + +typedef struct H265eV511StatusElem_t { + RK_U32 hw_status; + Vepu511Status st; +} H265eV511StatusElem; + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu511a.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu511a.c new file mode 100644 index 000000000..5b8f1fca4 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu511a.c @@ -0,0 +1,2944 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_h265e_v511a" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_packet_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_enc_hal.h" +#include "mpp_enc_cb_param.h" + +#include "rkv_enc_def.h" +#include "h265e_syntax_new.h" +#include "h265e_dpb.h" +#include "hal_bufs.h" +#include "hal_h265e_debug.h" +#include "hal_h265e_vepu511a_reg.h" +#include "hal_h265e_stream_amend.h" + +#include "vepu5xx_common.h" +#include "vepu511a_common.h" + +#define H265E_LAMBDA_TAB_SIZE (52 * sizeof(RK_U32)) +#define H265E_SMEAR_STR_NUM (8) + +#define hal_h265e_err(fmt, ...) \ + do {\ + mpp_loge_f(fmt, ## __VA_ARGS__);\ + } while (0) + +typedef struct Vepu511aH265Fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 frame_type; + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; + RK_U32 st_smear_cnt[5]; + RK_S32 reg_idx; + RK_U32 acc_cover16_num; + RK_U32 acc_bndry16_num; + RK_U32 acc_zero_mv; + RK_S8 tgt_sub_real_lvl[6]; +} Vepu511aH265Fbk; + +typedef struct Vepu511aH265eFrmCfg_t { + RK_S32 frame_count; + RK_S32 frame_type; + + /* dchs cfg on frame parallel */ + RK_S32 dchs_curr_idx; + RK_S32 dchs_prev_idx; + + /* hal dpb management slot idx */ + RK_S32 hal_curr_idx; + RK_S32 hal_refr_idx; + + /* regs cfg */ + H265eV511ARegSet *regs_set; + H265eV511AStatusElem *regs_ret; + + /* hardware return info collection cfg */ + Vepu511aH265Fbk feedback; + + void *roi_data; + + /* roi buffer for qpmap or gdr */ + MppBuffer roir_buf; + RK_S32 roir_buf_size; + void *roi_base_cfg_sw_buf; + + /* variable length cfg */ + MppDevRegOffCfgs *reg_cfg; +} Vepu511aH265eFrmCfg; + +typedef struct H265eV511AHalContext_t { + MppDev dev; + void *regs; + void *reg_out; + + Vepu511aH265eFrmCfg *frm; + + /* slice split poll cfg */ + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + MppDevPollCfg *poll_cfgs; + MppCbCtx *output_cb; + + /* @frame_cnt starts from ZERO */ + RK_S32 frame_count; + + /* dchs cfg */ + RK_S32 curr_idx; + RK_S32 prev_idx; + + Vepu511aH265Fbk feedback; + Vepu511aH265Fbk last_frame_fb; + void *dump_files; + RK_U32 frame_cnt_gen_ready; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + MppBufferGroup roi_grp; + void *roi_data; + + MppEncCfgSet *cfg; + MppDevRegOffCfgs *reg_cfg; + H265eSyntax_new *syn; + H265eDpb *dpb; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + HalBufs dpb_bufs; + RK_S32 fbc_header_len; + RK_U32 title_num; + RK_S32 smear_size; + + RK_S32 qpmap_en; + RK_S32 smart_en; + + /* external line buffer over 3K */ + MppBufferGroup ext_line_buf_grp; + RK_S32 ext_line_buf_size; + MppBuffer ext_line_buf; + MppBuffer buf_pass1; + + void *tune; +} H265eV511AHalContext; + +#include "hal_h265e_vepu511a_tune.c" + +static const RK_U32 lambda_tbl_pre_intra[52] = { + 4206, 4945, 5814, 6835, 8035, 9446, 11105, 13056, + 15348, 18044, 21213, 24938, 29318, 34467, 40521, 47637, + 56003, 65839, 77402, 90996, 106977, 125765, 147852, 173819, + 204346, 240234, 983, 1206, 1479, 1813, 2223, 2727, + 3344, 4100, 5028, 6166, 7561, 9272, 11371, 13944, + 17099, 20969, 25714, 31533, 38669, 47420, 58150, 71310, + 87447, 107236, 131504, 161263, +}; + +static const RK_U32 lambda_tbl_pre_inter[52] = { + 760, 959, 1210, 1526, 1925, 2428, 3063, 3864, + 4874, 6147, 7754, 9781, 12337, 15562, 19629, 24760, + 31231, 39394, 49691, 62678, 79061, 99725, 125790, 158668, + 200140, 252451, 579, 730, 919, 1159, 1461, 1993, + 2898, 3652, 4601, 5411, 6818, 7362, 9276, 11688, + 14725, 18553, 25324, 31906, 40200, 50649, 68724, 74217, + 101300, 127630, 148435, 187017, +}; + +static RK_U32 rdo_lambda_table_I[60] = { + 0x00000012, 0x00000017, + 0x0000001d, 0x00000024, 0x0000002e, 0x0000003a, + 0x00000049, 0x0000005c, 0x00000074, 0x00000092, + 0x000000b8, 0x000000e8, 0x00000124, 0x00000170, + 0x000001cf, 0x00000248, 0x000002df, 0x0000039f, + 0x0000048f, 0x000005bf, 0x0000073d, 0x0000091f, + 0x00000b7e, 0x00000e7a, 0x0000123d, 0x000016fb, + 0x00001cf4, 0x0000247b, 0x00002df6, 0x000039e9, + 0x000048f6, 0x00005bed, 0x000073d1, 0x000091ec, + 0x0000b7d9, 0x0000e7a2, 0x000123d7, 0x00016fb2, + 0x0001cf44, 0x000247ae, 0x0002df64, 0x00039e89, + 0x00048f5c, 0x0005bec8, 0x00073d12, 0x00091eb8, + 0x000b7d90, 0x000e7a23, 0x00123d71, 0x0016fb20, + 0x001cf446, 0x00247ae1, 0x002df640, 0x0039e88c, + 0x0048f5c3, 0x005bec81, 0x0073d119, 0x0091eb85, + 0x00b7d902, 0x00e7a232 +}; + +static RK_U32 rdo_lambda_table_P[60] = { + 0x0000002c, 0x00000038, 0x00000044, 0x00000058, + 0x00000070, 0x00000089, 0x000000b0, 0x000000e0, + 0x00000112, 0x00000160, 0x000001c0, 0x00000224, + 0x000002c0, 0x00000380, 0x00000448, 0x00000580, + 0x00000700, 0x00000890, 0x00000b00, 0x00000e00, + 0x00001120, 0x00001600, 0x00001c00, 0x00002240, + 0x00002c00, 0x00003800, 0x00004480, 0x00005800, + 0x00007000, 0x00008900, 0x0000b000, 0x0000e000, + 0x00011200, 0x00016000, 0x0001c000, 0x00022400, + 0x0002c000, 0x00038000, 0x00044800, 0x00058000, + 0x00070000, 0x00089000, 0x000b0000, 0x000e0000, + 0x00112000, 0x00160000, 0x001c0000, 0x00224000, + 0x002c0000, 0x00380000, 0x00448000, 0x00580000, + 0x00700000, 0x00890000, 0x00b00000, 0x00e00000, + 0x01120000, 0x01600000, 0x01c00000, 0x02240000, +}; + +static RK_U8 vepu511a_h265_cqm_intra8[64] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115 +}; + +static RK_U8 vepu511a_h265_cqm_inter8[64] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91 +}; + +void save_to_file_511a(char *name, void *ptr, size_t size) +{ + FILE *fp = fopen(name, "w+b"); + if (fp) { + fwrite(ptr, 1, size, fp); + fclose(fp); + } else + mpp_err("create file %s failed\n", name); +} + +void vepu511a_h265e_dump(H265eV511AHalContext *ctx, HalEncTask *enc_task __maybe_unused) +{ + H265eSyntax_new *syn = ctx->syn; + HalBuf *hal_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.ref_pic.slot_idx); + size_t buf_size = mpp_buffer_get_size(hal_buf->buf[0]); + size_t dws_size = mpp_buffer_get_size(hal_buf->buf[1]); + void *ptr = mpp_buffer_get_ptr(hal_buf->buf[0]); + void *dws_ptr = mpp_buffer_get_ptr(hal_buf->buf[1]); + RK_U32 frm_num = ctx->frm->frame_count; + RK_S32 pid = getpid(); + char name[128]; + size_t name_len = sizeof(name) - 1; + + snprintf(name, name_len, "/mnt/sdcard/dump/refr_fbd_%d_frm%d.bin", pid, frm_num); + save_to_file_511a(name, ptr + ctx->fbc_header_len, buf_size - ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/refr_fbh_%d_frm%d.bin", pid, frm_num); + save_to_file_511a(name, ptr, ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/refr_dsp_%d_frm%d.bin", pid, frm_num); + save_to_file_511a(name, dws_ptr, dws_size); + + hal_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.recon_pic.slot_idx); + buf_size = mpp_buffer_get_size(hal_buf->buf[0]); + dws_size = mpp_buffer_get_size(hal_buf->buf[1]); + ptr = mpp_buffer_get_ptr(hal_buf->buf[0]); + dws_ptr = mpp_buffer_get_ptr(hal_buf->buf[1]); + + snprintf(name, name_len, "/mnt/sdcard/dump/recn_fbd_%d_frm%d_slot%d.bin", pid, frm_num, syn->sp.recon_pic.slot_idx); + save_to_file_511a(name, ptr + ctx->fbc_header_len, buf_size - ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/recn_fbh_%d_frm%d_slot%d.bin", pid, frm_num, syn->sp.recon_pic.slot_idx); + save_to_file_511a(name, ptr, ctx->fbc_header_len); + + snprintf(name, name_len, "/mnt/sdcard/dump/recn_dsp_%d_frm%d_slot%d.bin", pid, frm_num, syn->sp.recon_pic.slot_idx); + save_to_file_511a(name, dws_ptr, dws_size); + +} + +static void setup_ext_line_bufs(H265eV511AHalContext *ctx) +{ + if (ctx->ext_line_buf) + return; + + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_buf, + ctx->ext_line_buf_size); +} + +static void clear_ext_line_bufs(H265eV511AHalContext *ctx) +{ + if (ctx->ext_line_buf) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + } +} + +static MPP_RET vepu511a_h265_setup_hal_bufs(H265eV511AHalContext *ctx) +{ + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + RK_U32 frame_size; + VepuFmt input_fmt = VEPU5xx_FMT_YUV420P; + RK_S32 mb_wd64, mb_h64; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + RK_S32 alignment = 32; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment); + RK_S32 smear_size = 0; + RK_S32 smear_r_size = 0; + + hal_h265e_enter(); + + mb_wd64 = (prep->width + 63) / 64; + mb_h64 = (prep->height + 63) / 64 + 1; + + frame_size = MPP_ALIGN(prep->width, 16) * MPP_ALIGN(prep->height, 16); + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + input_fmt = (VepuFmt)fmt->format; + switch (input_fmt) { + case VEPU5xx_FMT_YUV400: + break; + case VEPU5xx_FMT_YUV420P: + case VEPU5xx_FMT_YUV420SP: { + frame_size = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV422P: + case VEPU5xx_FMT_YUV422SP: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: + case VEPU5xx_FMT_BGR565: { + frame_size *= 2; + } break; + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_YUV444SP: + case VEPU5xx_FMT_YUV444P: { + frame_size *= 3; + } break; + case VEPU5xx_FMT_BGRA8888: { + frame_size *= 4; + } break; + default: { + hal_h265e_err("invalid src color space: %d\n", input_fmt); + return MPP_NOK; + } + } + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > SZ_4K) { + RK_S32 ctu_w = (aligned_w + 31) / 32; + RK_S32 ext_line_buf_size = ((ctu_w - 113) * 27 + 15) / 16 * 16 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + clear_ext_line_bufs(ctx); + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + setup_ext_line_bufs(ctx); + ctx->ext_line_buf_size = ext_line_buf_size; + } else { + clear_ext_line_bufs(ctx); + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + smear_size = MPP_ALIGN(prep->width, 256) / 256 * MPP_ALIGN(prep->height, 32) / 32 * 16; + smear_r_size = MPP_ALIGN(prep->height, 256) / 256 * MPP_ALIGN(prep->width, 32) / 32 * 16; + smear_size = MPP_MAX(smear_size, smear_r_size) * 2; + + if (frame_size > ctx->frame_size || new_max_cnt > old_max_cnt || + smear_size != ctx->smear_size) { + size_t size[4] = {0}; + + hal_bufs_deinit(ctx->dpb_bufs); + hal_bufs_init(&ctx->dpb_bufs); + + ctx->fbc_header_len = MPP_ALIGN(((mb_wd64 * mb_h64) << 6), SZ_8K); + size[0] = ctx->fbc_header_len + ((mb_wd64 * mb_h64) << 12) * 3 / 2; //fbc_h + fbc_b + size[1] = (mb_wd64 * mb_h64 << 8); + size[2] = MPP_ALIGN(mb_wd64 * mb_h64 * 16 * 4, 256) * 16; + /* smear bufs */ + size[3] = smear_size; + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_h265e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->frame_size, frame_size, old_max_cnt, new_max_cnt); + + hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, MPP_ARRAY_ELEMS(size), size); + + ctx->smear_size = smear_size; + ctx->frame_size = frame_size; + ctx->max_buf_cnt = new_max_cnt; + } + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu511a_deinit(void *hal) +{ + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + hal_h265e_enter(); + MPP_FREE(ctx->poll_cfgs); + MPP_FREE(ctx->input_fmt); + hal_bufs_deinit(ctx->dpb_bufs); + + if (ctx->frm) { + if (ctx->frm->roir_buf) { + mpp_buffer_put(ctx->frm->roir_buf); + ctx->frm->roir_buf = NULL; + ctx->frm->roir_buf_size = 0; + } + + MPP_FREE(ctx->frm->roi_base_cfg_sw_buf); + + if (ctx->frm->reg_cfg) { + mpp_dev_multi_offset_deinit(ctx->frm->reg_cfg); + ctx->frm->reg_cfg = NULL; + } + + MPP_FREE(ctx->frm->regs_set); + MPP_FREE(ctx->frm->regs_ret); + MPP_FREE(ctx->frm); + } + + clear_ext_line_bufs(ctx); + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + + if (ctx->buf_pass1) { + mpp_buffer_put(ctx->buf_pass1); + ctx->buf_pass1 = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + if (ctx->reg_cfg) { + mpp_dev_multi_offset_deinit(ctx->reg_cfg); + ctx->reg_cfg = NULL; + } + + if (ctx->roi_grp) { + mpp_buffer_group_put(ctx->roi_grp); + ctx->roi_grp = NULL; + } + + if (ctx->tune) { + vepu511a_h265e_tune_deinit(ctx->tune); + ctx->tune = NULL; + } + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu511a_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + + mpp_env_get_u32("hal_h265e_debug", &hal_h265e_debug, 0); + hal_h265e_enter(); + + /* single core uses single frame config */ + ctx->frm = mpp_calloc(Vepu511aH265eFrmCfg, 1); + ctx->frm->regs_set = mpp_calloc(H265eV511ARegSet, 1); + ctx->frm->regs_ret = mpp_calloc(H265eV511AStatusElem, 1); + ctx->frm->frame_type = INTRA_FRAME; + + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + hal_bufs_init(&ctx->dpb_bufs); + + ctx->frame_count = -1; + ctx->frame_cnt_gen_ready = 0; + ctx->enc_mode = 1; + cfg->cap_recn_out = 1; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_loge_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + mpp_dev_multi_offset_init(&ctx->reg_cfg, 24); + ctx->dev = cfg->dev; + ctx->frame_type = INTRA_FRAME; + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + RK_U32 j; + + hw->qp_delta_row_i = 2; + hw->qp_delta_row = 2; + hw->qbias_i = 171; + hw->qbias_p = 85; + hw->qbias_en = 0; + + for (j = 0; j < MPP_ARRAY_ELEMS(hw->mode_bias); j++) + hw->mode_bias[j] = 8; + } + + ctx->poll_slice_max = 8; + ctx->poll_cfg_size = (sizeof(ctx->poll_cfgs) + sizeof(RK_S32) * ctx->poll_slice_max) * 2; + ctx->poll_cfgs = mpp_malloc_size(MppDevPollCfg, ctx->poll_cfg_size); + + if (NULL == ctx->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_loge_f("init poll cfg buffer failed\n"); + goto DONE; + } + + ctx->output_cb = cfg->output_cb; + cfg->cap_recn_out = 1; + + ctx->tune = vepu511a_h265e_tune_init(ctx); + +DONE: + if (ret) + hal_h265e_vepu511a_deinit(hal); + + hal_h265e_leave(); + return ret; +} + +static MPP_RET hal_h265e_vepu511a_prepare(void *hal) +{ + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h265e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + vepu511a_h265_setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->dpb_bufs, i); + + prep->change_res = 0; + } + + hal_h265e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET +vepu511a_h265_set_patch_info(H265eSyntax_new *syn, VepuFmt input_fmt, MppDevRegOffCfgs *offsets, HalEncTask *task) +{ + RK_U32 hor_stride = syn->pp.hor_stride; + RK_U32 ver_stride = syn->pp.ver_stride ? syn->pp.ver_stride : syn->pp.pic_height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + u_offset = mpp_frame_get_fbc_offset(task->frame); + v_offset = u_offset; + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV400: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride * 2; + } break; + default: { + hal_h265e_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + mpp_dev_multi_offset_update(offsets, 161, u_offset); + mpp_dev_multi_offset_update(offsets, 162, v_offset); + + return ret; +} + +static MPP_RET vepu511a_h265e_save_pass1_patch(H265eV511ARegSet *regs, H265eV511AHalContext *ctx, + RK_S32 tiles_enabled_flag) +{ + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 width = ctx->cfg->prep.width; + RK_S32 height = ctx->cfg->prep.height; + RK_S32 width_align = MPP_ALIGN(width, 16); + RK_S32 height_align = MPP_ALIGN(height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + reg_frm->common.enc_pic.cur_frm_ref = 1; + reg_frm->common.rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + reg_frm->common.rfpw_b_addr = reg_frm->common.rfpw_h_addr; + reg_frm->common.enc_pic.rec_fbc_dis = 1; + reg_frm->common.me_ref_comb.rfpw_mode = 0; + + if (tiles_enabled_flag) + reg_frm->synt_pps.lpf_fltr_acrs_til = 0; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, width_align * height_align); + + /* NOTE: disable split to avoid lowdelay slice output */ + reg_frm->common.sli_splt.sli_splt = 0; + reg_frm->common.enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu511a_h265e_use_pass1_patch(H265eV511ARegSet *regs, H265eV511AHalContext *ctx) +{ + Vepu511aControlCfg *reg_ctl = ®s->reg_ctl; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 width_align = MPP_ALIGN(ctx->cfg->prep.width, 16); + RK_S32 height_align = MPP_ALIGN(ctx->cfg->prep.height, 16); + RK_S32 y_stride = width_align; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + MPP_RET ret = MPP_OK; + + hal_h265e_dbg_func("enter\n"); + + reg_frm->common.enc_pic.rfpr_compress_mode = 1; + reg_ctl->dtrns_map.src_bus_edin = fmt->src_endian; + reg_frm->common.src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + reg_frm->common.src_fmt.alpha_swap = 0; + reg_frm->common.src_fmt.rbuv_swap = 0; + reg_frm->common.src_fmt.out_fmt = 1; + + reg_frm->common.src_strd0.src_strd0 = y_stride; + reg_frm->common.src_strd1.src_strd1 = y_stride; + + reg_frm->common.src_proc.rkfbcd_en = 0; + reg_frm->common.src_proc.src_mirr = 0; + reg_frm->common.src_proc.src_rot = 0; + + reg_frm->common.adr_src0 = mpp_buffer_get_fd(ctx->buf_pass1); + reg_frm->common.adr_src1 = reg_frm->common.adr_src0; + + /* input cb addr */ + ret = mpp_dev_multi_offset_update(ctx->reg_cfg, 161, width_align * height_align); + if (ret) + mpp_loge_f("set input cb addr offset failed %d\n", ret); + + return MPP_OK; +} + +static void setup_vepu511a_ext_line_buf(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 fd; + + if (ctx->ext_line_buf) { + fd = mpp_buffer_get_fd(ctx->ext_line_buf); + + reg_frm->common.ebufb_addr = fd; + reg_frm->common.ebuft_addr = fd; + mpp_dev_multi_offset_update(ctx->reg_cfg, 178, ctx->ext_line_buf_size); + } else { + reg_frm->common.ebufb_addr = 0; + reg_frm->common.ebuft_addr = 0; + } +} + +static void vepu511a_h265_set_scaling_list(H265eV511ARegSet *regs) +{ + H265eVepu511aSclCfg *s = ®s->reg_scl; + RK_U8 *p = (RK_U8 *)&s->tu8_intra_y[0]; + RK_U32 scl_lst_sel = regs->reg_frm.rdo_cfg.scl_lst_sel; + RK_U8 idx; + + hal_h265e_dbg_func("enter\n"); + + if (scl_lst_sel == 1) { + for (idx = 0; idx < 64; idx++) { + /* TU8 intra Y/U/V */ + p[idx + 64 * 0] = vepu511a_h265_cqm_intra8[63 - idx]; + + p[idx + 64 * 1] = vepu511a_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 2] = vepu511a_h265_cqm_intra8[63 - idx]; + + /* TU8 inter Y/U/V */ + p[idx + 64 * 3] = vepu511a_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 4] = vepu511a_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 5] = vepu511a_h265_cqm_inter8[63 - idx]; + + /* TU16 intra Y/U/V AC */ + p[idx + 64 * 6] = vepu511a_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 7] = vepu511a_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 8] = vepu511a_h265_cqm_intra8[63 - idx]; + + /* TU16 inter Y/U/V AC */ + p[idx + 64 * 9] = vepu511a_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 10] = vepu511a_h265_cqm_inter8[63 - idx]; + p[idx + 64 * 11] = vepu511a_h265_cqm_inter8[63 - idx]; + + /* TU32 intra/inter Y AC */ + p[idx + 64 * 12] = vepu511a_h265_cqm_intra8[63 - idx]; + p[idx + 64 * 13] = vepu511a_h265_cqm_inter8[63 - idx]; + } + + s->tu_dc0.tu16_intra_y_dc = 16; + s->tu_dc0.tu16_intra_u_dc = 16; + s->tu_dc0.tu16_intra_v_dc = 16; + s->tu_dc0.tu16_inter_y_dc = 16; + s->tu_dc1.tu16_inter_u_dc = 16; + s->tu_dc1.tu16_inter_v_dc = 16; + s->tu_dc1.tu32_intra_y_dc = 16; + s->tu_dc1.tu32_inter_y_dc = 16; + } else if (scl_lst_sel == 2) { + mpp_log_f("scaling_list_mode 2 is not supported yet\n"); + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu511a_h265_set_normal(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + Vepu511aControlCfg *reg_ctl = ®s->reg_ctl; + + reg_ctl->enc_strt.lkt_num = 0; + reg_ctl->enc_strt.vepu_cmd = ctx->enc_mode; + reg_ctl->enc_clr.safe_clr = 0; + reg_ctl->enc_clr.force_clr = 0; + + reg_ctl->int_en.enc_done_en = 1; + reg_ctl->int_en.lkt_node_done_en = 1; + reg_ctl->int_en.sclr_done_en = 1; + reg_ctl->int_en.vslc_done_en = 1; + reg_ctl->int_en.vbsf_oflw_en = 1; + reg_ctl->int_en.vbuf_lens_en = 1; + reg_ctl->int_en.enc_err_en = 1; + reg_ctl->int_en.vsrc_err_en = 1; + reg_ctl->int_en.wdg_en = 1; + reg_ctl->int_en.lkt_err_int_en = 1; + reg_ctl->int_en.lkt_err_int_en = 1; + reg_ctl->int_en.lkt_err_stop_en = 1; + reg_ctl->int_en.lkt_force_stop_en = 1; + reg_ctl->int_en.jslc_done_en = 1; + reg_ctl->int_en.jbsf_oflw_en = 1; + reg_ctl->int_en.jbuf_lens_en = 1; + reg_ctl->int_en.dvbm_err_en = 0; + + reg_ctl->int_clr.enc_done_clr = 1; + + reg_ctl->dtrns_map.jpeg_bus_edin = 0x7; + reg_ctl->int_clr.enc_done_clr = 1; + + reg_ctl->dtrns_map.jpeg_bus_edin = 0x7; + reg_ctl->dtrns_map.src_bus_edin = 0x0; + reg_ctl->dtrns_map.meiw_bus_edin = 0x0; + reg_ctl->dtrns_map.bsw_bus_edin = 0x7; + reg_ctl->dtrns_map.lktr_bus_edin = 0x0; + reg_ctl->dtrns_map.roir_bus_edin = 0x0; + reg_ctl->dtrns_map.lktw_bus_edin = 0x0; + reg_ctl->dtrns_map.rec_nfbc_bus_edin = 0x0; + + reg_ctl->dtrns_cfg.axi_brsp_cke = 0x3ff; + reg_ctl->dtrns_cfg.axi_brsp_cke = 0x3ff; + reg_ctl->enc_wdg.vs_load_thd = 0; + reg_ctl->opt_strg.cke = 1; + reg_ctl->opt_strg.resetn_hw_en = 0; + reg_ctl->opt_strg.rfpr_err_e = 1; + reg_ctl->opt_strg.sram_ckg_en = 0; + + /* enable rdo clk gating */ + { + RK_U32 *rdo_ckg = (RK_U32*)®s->reg_ctl.reg0022.rdo_ckg_hevc; + + *rdo_ckg = 0x0; + } + +} + +static void vepu511a_h265_set_prep(void *hal, HalEncTask *task, H265eV511ARegSet *regs) +{ + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + Vepu511aRcRoi *reg_klut = ®s->reg_rc_roi; + H265eSyntax_new *syn = (H265eSyntax_new *)task->syntax.data; + RK_U32 pic_width_align8, pic_height_align8; + RK_S32 pic_wd32, pic_h32; + MppEncSceneMode sm = ctx->cfg->tune.scene_mode; + + hal_h265e_enter(); + + pic_width_align8 = (syn->pp.pic_width + 7) & (~7); + pic_height_align8 = (syn->pp.pic_height + 7) & (~7); + pic_wd32 = (syn->pp.pic_width + 31) / 32; + pic_h32 = (syn->pp.pic_height + 31) / 32; + + reg_frm->common.enc_rsl.pic_wd8_m1 = pic_width_align8 / 8 - 1; + reg_frm->common.enc_rsl.pic_hd8_m1 = pic_height_align8 / 8 - 1; + reg_frm->common.src_fill.pic_wfill = (syn->pp.pic_width & 0x7) + ? (8 - (syn->pp.pic_width & 0x7)) : 0; + reg_frm->common.src_fill.pic_hfill = (syn->pp.pic_height & 0x7) + ? (8 - (syn->pp.pic_height & 0x7)) : 0; + + /* H.265 mode */ + reg_frm->common.enc_pic.enc_stnd = 1; + /* current frame will be refered */ + reg_frm->common.enc_pic.cur_frm_ref = !syn->sp.non_reference_flag; + + reg_frm->common.enc_pic.bs_scp = 1; + reg_frm->common.enc_pic.log2_ctu_num_hevc = mpp_ceil_log2(pic_wd32 * pic_h32); + + reg_klut->klut_ofst.chrm_klut_ofst = (ctx->frame_type == INTRA_FRAME) ? 6 : + (sm == MPP_ENC_SCENE_MODE_IPC ? 9 : 6); + + reg_frm->common.enc_pic.rfpr_compress_mode = 0; + reg_frm->common.enc_pic.rec_fbc_dis = 0; + + if (syn->pp.num_long_term_ref_pics_sps) { + reg_frm->rdo_cfg.ltm_col = 0; + reg_frm->rdo_cfg.ltm_idx0l0 = 1; + } else { + reg_frm->rdo_cfg.ltm_col = 0; + reg_frm->rdo_cfg.ltm_idx0l0 = 0; + } + + reg_frm->rdo_cfg.ccwa_e = 1; + reg_frm->rdo_cfg.scl_lst_sel = syn->pp.scaling_list_enabled_flag; + + { + RK_U32 i_nal_type = 0; + + if (ctx->frame_type == INTRA_FRAME) + i_nal_type = NAL_IDR_W_RADL; + else if (ctx->frame_type == INTER_P_FRAME ) + i_nal_type = NAL_TRAIL_R; + else + i_nal_type = NAL_TRAIL_R; + + reg_frm->synt_nal.nal_unit_type = i_nal_type; + } +} + +static void vepu511a_h265_set_split(H265eV511ARegSet *regs, MppEncCfgSet *enc_cfg) +{ + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h265e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_frm.common.sli_splt.sli_splt = 0; + regs->reg_frm.common.sli_splt.sli_splt_mode = 0; + regs->reg_frm.common.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.common.sli_splt.sli_max_num_m1 = 0; + regs->reg_frm.common.sli_splt.sli_flsh = 0; + regs->reg_frm.common.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.common.sli_byte.sli_splt_byte = 0; + regs->reg_frm.common.enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_frm.common.sli_splt.sli_splt = 1; + regs->reg_frm.common.sli_splt.sli_splt_mode = 0; + regs->reg_frm.common.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.common.sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.common.sli_splt.sli_flsh = 1; + regs->reg_frm.common.sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_frm.common.sli_byte.sli_splt_byte = cfg->split_arg; + regs->reg_frm.common.enc_pic.slen_fifo = cfg->split_out ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = cfg->split_out ? 1 : 0; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + regs->reg_frm.common.sli_splt.sli_splt = 1; + regs->reg_frm.common.sli_splt.sli_splt_mode = 1; + regs->reg_frm.common.sli_splt.sli_splt_cpst = 0; + regs->reg_frm.common.sli_splt.sli_max_num_m1 = 500; + regs->reg_frm.common.sli_splt.sli_flsh = 1; + regs->reg_frm.common.sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg_frm.common.sli_byte.sli_splt_byte = 0; + regs->reg_frm.common.enc_pic.slen_fifo = cfg->split_out ? 1 : 0; + regs->reg_ctl.int_en.vslc_done_en = cfg->split_out ? 1 : 0; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu511a_h265_set_me_regs(H265eV511AHalContext *ctx, H265eSyntax_new *syn, H265eV511ARegSet *regs) +{ + H265eVepu511aParam *s = ®s->reg_param; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + + reg_frm->common.me_rnge.cime_srch_dwnh = 15; + reg_frm->common.me_rnge.cime_srch_uph = 15; + reg_frm->common.me_rnge.cime_srch_rgtw = 12; + reg_frm->common.me_rnge.cime_srch_lftw = 12; + reg_frm->common.me_cfg.rme_srch_h = 3; + reg_frm->common.me_cfg.rme_srch_v = 3; + + reg_frm->common.me_cfg.srgn_max_num = 54; + reg_frm->common.me_cfg.cime_dist_thre = 1024; + reg_frm->common.me_cfg.rme_dis = 0; + reg_frm->common.me_cfg.fme_dis = 0; + reg_frm->common.me_rnge.dlt_frm_num = 0x1; + + if (syn->pp.sps_temporal_mvp_enabled_flag && (ctx->frame_type != INTRA_FRAME)) { + if (ctx->last_frame_type == INTRA_FRAME) + reg_frm->common.me_cach.colmv_load_hevc = 0; + else + reg_frm->common.me_cach.colmv_load_hevc = 1; + + reg_frm->common.me_cach.colmv_stor_hevc = 1; + } + + reg_frm->common.me_cach.cime_zero_thre = 64; + reg_frm->common.me_cach.fme_prefsu_en = 0; + + /* CIME: 0x1760 - 0x176C */ + s->me_sqi_comb.cime_pmv_num = 1; + s->me_sqi_comb.cime_fuse = 1; + s->me_sqi_comb.move_lambda = 2; + s->me_sqi_comb.rime_lvl_mrg = 0; + s->me_sqi_comb.rime_prelvl_en = 0; + s->me_sqi_comb.rime_prersu_en = 0; + s->me_sqi_comb.fme_lvl_mrg = 1; + + s->cime_mvd_th_comb.cime_mvd_th0 = 8; + s->cime_mvd_th_comb.cime_mvd_th1 = 20; + s->cime_mvd_th_comb.cime_mvd_th2 = 32; + s->cime_madp_th_comb.cime_madp_th = 16; + s->cime_madp_th_comb.ratio_consi_cfg = 8; + s->cime_madp_th_comb.ratio_bmv_dist = 8; + s->cime_multi_comb.cime_multi0 = 8; + s->cime_multi_comb.cime_multi1 = 12; + s->cime_multi_comb.cime_multi2 = 16; + s->cime_multi_comb.cime_multi3 = 20; + + /* RFME: 0x1770 - 0x177C */ + s->rime_mvd_th_comb.rime_mvd_th0 = 1; + s->rime_mvd_th_comb.rime_mvd_th1 = 2; + s->rime_mvd_th_comb.fme_madp_th = 10; + s->rime_madp_th_comb.rime_madp_th0 = 8; + s->rime_madp_th_comb.rime_madp_th1 = 16; + s->rime_multi_comb.rime_multi0 = 4; + s->rime_multi_comb.rime_multi1 = 8; + s->rime_multi_comb.rime_multi2 = 12; + s->cmv_st_th_comb.cmv_th0 = 64; + s->cmv_st_th_comb.cmv_th1 = 96; + s->cmv_st_th_comb.cmv_th2 = 128; + + if (ctx->cfg->tune.scene_mode != MPP_ENC_SCENE_MODE_IPC) { + s->me_sqi_comb.move_lambda = 8; + s->cime_madp_th_comb.cime_madp_th = 0; + s->rime_madp_th_comb.rime_madp_th0 = 0; + s->rime_madp_th_comb.rime_madp_th1 = 0; + s->cime_multi_comb.cime_multi0 = 4; + s->cime_multi_comb.cime_multi1 = 4; + s->cime_multi_comb.cime_multi2 = 4; + s->cime_multi_comb.cime_multi3 = 4; + s->rime_multi_comb.rime_multi0 = 4; + s->rime_multi_comb.rime_multi1 = 4; + s->rime_multi_comb.rime_multi2 = 4; + } else if (ctx->smart_en) { + s->cime_multi_comb.cime_multi0 = 4; + s->cime_multi_comb.cime_multi1 = 6; + s->cime_multi_comb.cime_multi2 = 8; + s->cime_multi_comb.cime_multi3 = 12; + s->rime_multi_comb.rime_multi0 = 4; + s->rime_multi_comb.rime_multi1 = 4; + s->rime_multi_comb.rime_multi2 = 4; + } +} + +static void vepu511a_set_speed(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + H265eVepu511aParam *s = ®s->reg_param; + RK_S32 ppc_level = ctx->cfg->tune.speed; + + /* Speed mode 0-3 (ppc = pixels per cycle): + * 0 - slowest (ppc 0.35, best quality) + * 1 - slow (ppc 0.4) + * 2 - medium (ppc 0.5) + * 3 - fastest (ppc 0.55, lowest quality) + */ + hal_h265e_dbg_func("enter\n"); + hal_h265e_dbg_detail("vepu511a_set_speed ppc_level %d\n", ppc_level); + + switch (ppc_level) { + case 0: + default: { // speed mode 0: slowest (ppc 0.35, best quality) + if (ctx->frame_type == INTRA_FRAME) { + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 2; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 2; + } else if (ctx->frame_type == INTER_P_FRAME) { + reg_frm->rdo_cfg.pu32_inter_interpolation_num_big_lvl = 3; + reg_frm->rdo_cfg.pu16_inter_interpolation_num_big_lvl = 3; + reg_frm->rdo_cfg.pu8_inter_interpolation_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu32_inter_interpolation_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_inter_interpolation_num_small_lvl = 3; + reg_frm->rdo_intra_mode.pu8_inter_interpolation_num_small_lvl = 3; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 2; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 1; + } + + s->me_sqi_comb.fme_lvl_mrg = 0; + s->me_sqi_comb.rime_prelvl_en = 3; + break; + } + + case 1: { // speed mode 1: slow (ppc 0.4) + if (ctx->frame_type == INTRA_FRAME) { + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 2; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 2; + } else if (ctx->frame_type == INTER_P_FRAME) { + reg_frm->rdo_cfg.pu32_inter_interpolation_num_big_lvl = 2; + reg_frm->rdo_cfg.pu16_inter_interpolation_num_big_lvl = 2; + reg_frm->rdo_cfg.pu8_inter_interpolation_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu32_inter_interpolation_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_inter_interpolation_num_small_lvl = 2; + reg_frm->rdo_intra_mode.pu8_inter_interpolation_num_small_lvl = 3; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 2; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 1; + } + + s->me_sqi_comb.fme_lvl_mrg = 0; + s->me_sqi_comb.rime_prelvl_en = 3; + break; + } + + case 2: { // speed mode 2: medium (ppc 0.5) + if (ctx->frame_type == INTRA_FRAME) { + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 1; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 2; + } else if (ctx->frame_type == INTER_P_FRAME) { + reg_frm->rdo_cfg.pu32_inter_interpolation_num_big_lvl = 1; + reg_frm->rdo_cfg.pu16_inter_interpolation_num_big_lvl = 1; + reg_frm->rdo_cfg.pu8_inter_interpolation_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu32_inter_interpolation_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_inter_interpolation_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu8_inter_interpolation_num_small_lvl = 3; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 1; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 1; + } + + s->me_sqi_comb.fme_lvl_mrg = 1; + s->me_sqi_comb.rime_prelvl_en = 2; + break; + } + + case 3: { // speed mode 3: fastest (ppc 0.55, lowest quality) + if (ctx->frame_type == INTRA_FRAME) { + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 1; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 2; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 2; + } else if (ctx->frame_type == INTER_P_FRAME) { + reg_frm->rdo_cfg.pu32_inter_interpolation_num_big_lvl = 1; + reg_frm->rdo_cfg.pu16_inter_interpolation_num_big_lvl = 3; + reg_frm->rdo_cfg.pu8_inter_interpolation_num_big_lvl = 0; + reg_frm->rdo_intra_mode.pu32_inter_interpolation_num_small_lvl = 0; + reg_frm->rdo_intra_mode.pu16_inter_interpolation_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu8_inter_interpolation_num_small_lvl = 3; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_big_lvl = 1; + reg_frm->rdo_intra_mode.pu4_intra_mode_num = 1; + reg_frm->rdo_intra_mode.pu32_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu16_intra_mode_num_small_lvl = 1; + reg_frm->rdo_intra_mode.pu8_intra_mode_num_small_lvl = 1; + } + + s->me_sqi_comb.fme_lvl_mrg = 1; + s->me_sqi_comb.rime_prelvl_en = 2; + break; + } + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu511a_h265_set_hw_address(H265eV511AHalContext *ctx, H265eVepu511aFrame *regs, + HalEncTask *task) +{ + HalEncTask *enc_task = task; + HalBuf *recon_buf, *ref_buf; + MppBuffer md_info_buf = enc_task->md_info; + Vepu511aH265eFrmCfg *frm = ctx->frm; + H265eSyntax_new *syn = ctx->syn; + + hal_h265e_enter(); + + regs->common.adr_src0 = mpp_buffer_get_fd(enc_task->input); + regs->common.adr_src1 = regs->common.adr_src0; + regs->common.adr_src2 = regs->common.adr_src0; + + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_curr_idx); + ref_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_refr_idx); + + if (!syn->sp.non_reference_flag) { + regs->common.rfpw_h_addr = mpp_buffer_get_fd(recon_buf->buf[0]); + regs->common.rfpw_b_addr = regs->common.rfpw_h_addr; + mpp_dev_multi_offset_update(ctx->reg_cfg, 164, ctx->fbc_header_len); + } + regs->common.rfpr_h_addr = mpp_buffer_get_fd(ref_buf->buf[0]); + regs->common.rfpr_b_addr = regs->common.rfpr_h_addr; + regs->common.colmvw_addr = mpp_buffer_get_fd(recon_buf->buf[2]); + regs->common.colmvr_addr = mpp_buffer_get_fd(ref_buf->buf[2]); + regs->common.dspw_addr = mpp_buffer_get_fd(recon_buf->buf[1]); + regs->common.dspr_addr = mpp_buffer_get_fd(ref_buf->buf[1]); + + mpp_dev_multi_offset_update(ctx->reg_cfg, 166, ctx->fbc_header_len); + + if (md_info_buf) { + regs->common.enc_pic.mei_stor = 1; + regs->common.meiw_addr = mpp_buffer_get_fd(md_info_buf); + } else { + regs->common.enc_pic.mei_stor = 0; + regs->common.meiw_addr = 0; + } + + regs->common.bsbt_addr = mpp_buffer_get_fd(enc_task->output); + /* TODO: stream size relative with syntax */ + regs->common.bsbb_addr = regs->common.bsbt_addr; + regs->common.bsbr_addr = regs->common.bsbt_addr; + regs->common.adr_bsbs = regs->common.bsbt_addr; + + regs->common.rfpt_h_addr = 0xffffffff; + regs->common.rfpb_h_addr = 0; + regs->common.rfpt_b_addr = 0xffffffff; + regs->common.adr_rfpb_b = 0; + regs->common.adr_roir = 0; + + mpp_dev_multi_offset_update(ctx->reg_cfg, 174, mpp_packet_get_length(task->packet)); + mpp_dev_multi_offset_update(ctx->reg_cfg, 172, mpp_buffer_get_size(enc_task->output)); + + regs->common.pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->common.pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + /* smear bufs */ + regs->common.adr_smear_rd = mpp_buffer_get_fd(ref_buf->buf[3]); + regs->common.adr_smear_wr = mpp_buffer_get_fd(recon_buf->buf[3]); +} + +static void vepu511a_h265_set_pp_regs(H265eV511ARegSet *regs, VepuFmtCfg *fmt, + MppEncPrepCfg *prep_cfg, HalEncTask *task) +{ + Vepu511aControlCfg *reg_ctl = ®s->reg_ctl; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 stridey = 0; + RK_S32 stridec = 0; + + reg_ctl->dtrns_map.src_bus_edin = fmt->src_endian; + reg_frm->common.src_fmt.src_cfmt = fmt->format; + reg_frm->common.src_fmt.alpha_swap = fmt->alpha_swap; + reg_frm->common.src_fmt.rbuv_swap = fmt->rbuv_swap; + reg_frm->common.src_fmt.out_fmt = (fmt->format == VEPU5xx_FMT_YUV400) ? 0 : 1; + reg_frm->common.src_proc.src_mirr = prep_cfg->mirroring > 0; + reg_frm->common.src_proc.src_rot = prep_cfg->rotation; + + if (MPP_FRAME_FMT_IS_FBC(prep_cfg->format)) { + reg_frm->common.src_proc.rkfbcd_en = 1; + + stridey = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!stridey) + stridey = MPP_ALIGN(prep_cfg->hor_stride, 64) >> 2; + } else if (prep_cfg->hor_stride) { + if (MPP_FRAME_FMT_IS_TILE(prep_cfg->format)) { + reg_frm->common.src_proc.tile4x4_en = 1; + + switch (prep_cfg->format & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV400: + stridey = prep_cfg->hor_stride * 4; + break; + case MPP_FMT_YUV420P: + case MPP_FMT_YUV420SP: + stridey = prep_cfg->hor_stride * 4 * 3 / 2; + break; + case MPP_FMT_YUV422P: + case MPP_FMT_YUV422SP: + stridey = prep_cfg->hor_stride * 4 * 2; + break; + case MPP_FMT_YUV444P: + case MPP_FMT_YUV444SP: + stridey = prep_cfg->hor_stride * 4 * 3; + break; + default: + mpp_err("Unsupported input format 0x%08x, with TILE mask.\n", fmt); + break; + } + } else { + stridey = prep_cfg->hor_stride; + } + } else { + if (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_BGRA8888) + stridey = prep_cfg->width * 4; + else if (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_BGR888) + stridey = prep_cfg->width * 3; + else if (reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_BGR565 || + reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_YUYV422 || + reg_frm->common.src_fmt.src_cfmt == VEPU5xx_FMT_UYVY422) + stridey = prep_cfg->width * 2; + } + + switch (fmt->format) { + case VEPU5xx_FMT_YUV444SP : { + stridec = stridey * 2; + } break; + case VEPU5xx_FMT_YUV422SP : + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV444P : { + stridec = stridey; + } break; + default : { + stridec = stridey / 2; + } break; + } + + if (reg_frm->common.src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + reg_frm->common.src_udfy.csc_wgt_r2y = 77; + reg_frm->common.src_udfy.csc_wgt_g2y = 150; + reg_frm->common.src_udfy.csc_wgt_b2y = 29; + + reg_frm->common.src_udfu.csc_wgt_r2u = -43; + reg_frm->common.src_udfu.csc_wgt_g2u = -85; + reg_frm->common.src_udfu.csc_wgt_b2u = 128; + + reg_frm->common.src_udfv.csc_wgt_r2v = 128; + reg_frm->common.src_udfv.csc_wgt_g2v = -107; + reg_frm->common.src_udfv.csc_wgt_b2v = -21; + + reg_frm->common.src_udfo.csc_ofst_y = 0; + reg_frm->common.src_udfo.csc_ofst_u = 128; + reg_frm->common.src_udfo.csc_ofst_v = 128; + } + + reg_frm->common.src_strd0.src_strd0 = stridey; + reg_frm->common.src_strd1.src_strd1 = stridec; +} + +static void vepu511a_h265_set_rc_regs(H265eV511AHalContext *ctx, H265eV511ARegSet *regs, + HalEncTask *task) +{ + H265eSyntax_new *syn = (H265eSyntax_new *)task->syntax.data; + EncRcTaskInfo *rc_cfg = &task->rc_task->info; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + Vepu511aRcRoi *reg_rc = ®s->reg_rc_roi; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + MppEncH265Cfg *h265 = &cfg->h265; + RK_S32 mb_wd32 = (syn->pp.pic_width + 31) / 32; + RK_S32 mb_h32 = (syn->pp.pic_height + 31) / 32; + + RK_U32 ctu_target_bits_mul_16 = (rc_cfg->bit_target << 4) / (mb_wd32 * mb_h32); + RK_U32 ctu_target_bits; + RK_S32 negative_bits_thd, positive_bits_thd; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + reg_frm->common.enc_pic.pic_qp = rc_cfg->quality_target; + reg_frm->synt_sli1.sli_qp = rc_cfg->quality_target; + reg_frm->common.rc_qp.rc_max_qp = rc_cfg->quality_target; + reg_frm->common.rc_qp.rc_min_qp = rc_cfg->quality_target; + reg_frm->common.rc_cfg.rc_ctu_num = 1; + } else { + if (ctu_target_bits_mul_16 >= 0x100000) { + ctu_target_bits_mul_16 = 0x50000; + } + ctu_target_bits = (ctu_target_bits_mul_16 * mb_wd32) >> 4; + negative_bits_thd = 0 - 5 * ctu_target_bits / 16; + positive_bits_thd = 5 * ctu_target_bits / 16; + + reg_frm->common.enc_pic.pic_qp = rc_cfg->quality_target; + reg_frm->synt_sli1.sli_qp = rc_cfg->quality_target; + reg_frm->common.rc_cfg.rc_en = 1; + reg_frm->common.rc_cfg.aq_en = 1; + reg_frm->common.rc_cfg.rc_ctu_num = mb_wd32; + + reg_frm->common.rc_qp.rc_max_qp = rc_cfg->quality_max; + reg_frm->common.rc_qp.rc_min_qp = rc_cfg->quality_min; + reg_frm->common.rc_tgt.ctu_ebit = ctu_target_bits_mul_16; + + if (ctx->smart_en) { + reg_frm->common.rc_qp.rc_qp_range = 0; + } else { + reg_frm->common.rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? + hw->qp_delta_row_i : hw->qp_delta_row; + } + + { + /* fixed frame qp */ + RK_S32 fqp_min, fqp_max; + + if (ctx->frame_type == INTRA_FRAME) { + fqp_min = rc->fqp_min_i; + fqp_max = rc->fqp_max_i; + } else { + fqp_min = rc->fqp_min_p; + fqp_max = rc->fqp_max_p; + } + + if ((fqp_min == fqp_max) && (fqp_min >= 0) && (fqp_max <= 51)) { + reg_frm->common.enc_pic.pic_qp = fqp_min; + reg_frm->synt_sli1.sli_qp = fqp_min; + reg_frm->common.rc_qp.rc_qp_range = 0; + } + } + + reg_rc->rc_dthd_0_8[0] = 2 * negative_bits_thd; + reg_rc->rc_dthd_0_8[1] = negative_bits_thd; + reg_rc->rc_dthd_0_8[2] = positive_bits_thd; + reg_rc->rc_dthd_0_8[3] = 2 * positive_bits_thd; + reg_rc->rc_dthd_0_8[4] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[5] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[6] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[7] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[8] = 0x7FFFFFFF; + + reg_rc->rc_adj0.qp_adj0 = -2; + reg_rc->rc_adj0.qp_adj1 = -1; + reg_rc->rc_adj0.qp_adj2 = 0; + reg_rc->rc_adj0.qp_adj3 = 1; + reg_rc->rc_adj0.qp_adj4 = 2; + reg_rc->rc_adj1.qp_adj5 = 0; + reg_rc->rc_adj1.qp_adj6 = 0; + reg_rc->rc_adj1.qp_adj7 = 0; + reg_rc->rc_adj1.qp_adj8 = 0; + } + + reg_rc->roi_qthd0.qpmin_area0 = h265->qpmin_map[0] > 0 ? h265->qpmin_map[0] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area0 = h265->qpmax_map[0] > 0 ? h265->qpmax_map[0] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area1 = h265->qpmin_map[1] > 0 ? h265->qpmin_map[1] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area1 = h265->qpmax_map[1] > 0 ? h265->qpmax_map[1] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area2 = h265->qpmin_map[2] > 0 ? h265->qpmin_map[2] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area2 = h265->qpmax_map[2] > 0 ? h265->qpmax_map[2] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area3 = h265->qpmin_map[3] > 0 ? h265->qpmin_map[3] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area3 = h265->qpmax_map[3] > 0 ? h265->qpmax_map[3] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area4 = h265->qpmin_map[4] > 0 ? h265->qpmin_map[4] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area4 = h265->qpmax_map[4] > 0 ? h265->qpmax_map[4] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area5 = h265->qpmin_map[5] > 0 ? h265->qpmin_map[5] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area5 = h265->qpmax_map[5] > 0 ? h265->qpmax_map[5] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area6 = h265->qpmin_map[6] > 0 ? h265->qpmin_map[6] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area6 = h265->qpmax_map[6] > 0 ? h265->qpmax_map[6] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area7 = h265->qpmin_map[7] > 0 ? h265->qpmin_map[7] : rc_cfg->quality_min; + reg_rc->roi_qthd3.qpmax_area7 = h265->qpmax_map[7] > 0 ? h265->qpmax_map[7] : rc_cfg->quality_max; + reg_rc->roi_cfg.fmdc_adj1_hevc.fmdc_adju_split32 = 0; +} + +static void vepu511a_h265_set_quant_regs(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + H265eVepu511aParam *s = ®s->reg_param; + RK_U8 th0 = 3, th1 = 6, th2 = 13; + RK_U16 bias_i0 = 171, bias_i1 = 171, bias_i2 = 171, bias_i3 = 171; + RK_U16 bias_p0 = 85, bias_p1 = 85, bias_p2 = 85, bias_p3 = 85; + RK_U32 frm_type = ctx->frame_type; + + if (!hw->qbias_en) { + if (ctx->smart_en) { + bias_i0 = bias_i1 = bias_i3 = 144; + bias_i2 = (frm_type == INTRA_FRAME) ? 144 : 171; + } else { + bias_i0 = bias_i1 = bias_i3 = 171; + bias_i2 = (frm_type == INTRA_FRAME) ? 171 : 220; + } + + /* used for venc_info log */ + hw->qbias_arr[IFRAME_THD0] = hw->qbias_arr[PFRAME_THD0] = th0; + hw->qbias_arr[IFRAME_THD1] = hw->qbias_arr[PFRAME_THD1] = th1; + hw->qbias_arr[IFRAME_THD2] = hw->qbias_arr[PFRAME_THD2] = th2; + hw->qbias_arr[IFRAME_BIAS0] = hw->qbias_arr[PFRAME_IBLK_BIAS0] = bias_i0; + hw->qbias_arr[IFRAME_BIAS1] = hw->qbias_arr[PFRAME_IBLK_BIAS1] = bias_i1; + hw->qbias_arr[IFRAME_BIAS2] = hw->qbias_arr[PFRAME_IBLK_BIAS2] = bias_i2; + hw->qbias_arr[IFRAME_BIAS3] = hw->qbias_arr[PFRAME_IBLK_BIAS3] = bias_i3; + hw->qbias_arr[PFRAME_PBLK_BIAS0] = bias_p0; + hw->qbias_arr[PFRAME_PBLK_BIAS1] = bias_p1; + hw->qbias_arr[PFRAME_PBLK_BIAS2] = bias_p2; + hw->qbias_arr[PFRAME_PBLK_BIAS3] = bias_p3; + } else { + if (frm_type == INTRA_FRAME) { + th0 = hw->qbias_arr[IFRAME_THD0]; + th1 = hw->qbias_arr[IFRAME_THD1]; + th2 = hw->qbias_arr[IFRAME_THD2]; + bias_i0 = hw->qbias_arr[IFRAME_BIAS0]; + bias_i1 = hw->qbias_arr[IFRAME_BIAS1]; + bias_i2 = hw->qbias_arr[IFRAME_BIAS2]; + bias_i3 = hw->qbias_arr[IFRAME_BIAS3]; + } else { + th0 = hw->qbias_arr[PFRAME_THD0]; + th1 = hw->qbias_arr[PFRAME_THD1]; + th2 = hw->qbias_arr[PFRAME_THD2]; + bias_i0 = hw->qbias_arr[PFRAME_IBLK_BIAS0]; + bias_i1 = hw->qbias_arr[PFRAME_IBLK_BIAS1]; + bias_i2 = hw->qbias_arr[PFRAME_IBLK_BIAS2]; + bias_i3 = hw->qbias_arr[PFRAME_IBLK_BIAS3]; + bias_p0 = hw->qbias_arr[PFRAME_PBLK_BIAS0]; + bias_p1 = hw->qbias_arr[PFRAME_PBLK_BIAS1]; + bias_p2 = hw->qbias_arr[PFRAME_PBLK_BIAS2]; + bias_p3 = hw->qbias_arr[PFRAME_PBLK_BIAS3]; + } + } + + s->bias_madi_thd_comb.bias_madi_th0 = th0; + s->bias_madi_thd_comb.bias_madi_th1 = th1; + s->bias_madi_thd_comb.bias_madi_th2 = th2; + s->qnt0_i_bias_comb.bias_i_val0 = bias_i0; + s->qnt0_i_bias_comb.bias_i_val1 = bias_i1; + s->qnt0_i_bias_comb.bias_i_val2 = bias_i2; + s->qnt1_i_bias_comb.bias_i_val3 = bias_i3; + s->qnt0_p_bias_comb.bias_p_val0 = bias_p0; + s->qnt0_p_bias_comb.bias_p_val1 = bias_p1; + s->qnt0_p_bias_comb.bias_p_val2 = bias_p2; + s->qnt1_p_bias_comb.bias_p_val3 = bias_p3; +} + +static void vepu511a_h265_set_atr_regs(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aSqi *s = ®s->reg_sqi; + RK_U32 str = ctx->frame_type == INTRA_FRAME ? + ctx->cfg->tune.atr_str_i : ctx->cfg->tune.atr_str_p; + + /* 0 - disable; 1 - weak; 2 - medium; 3 - strong */ + if (str == 0) { + s->block_opt_cfg.block_en = 0; /* block_en and cmplx_en are not used so far(20240708) */ + s->cmplx_opt_cfg.cmplx_en = 0; + s->line_opt_cfg.line_en = 0; + } else { + s->block_opt_cfg.block_en = 0; + s->cmplx_opt_cfg.cmplx_en = 0; + s->line_opt_cfg.line_en = 1; + } + + if (str == 3) { + s->block_opt_cfg.block_thre_cst_best_mad = 1000; + s->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + s->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + s->block_opt_cfg.block_delta_qp_flag = 3; + + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 4; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 255; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 255; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 7; + + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 60; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 60; + + s->subj_opt_dqp0.line_thre_qp = 25; + s->subj_opt_dqp0.block_strength = 4; + s->subj_opt_dqp0.block_thre_qp = 30; + s->subj_opt_dqp0.cmplx_strength = 4; + s->subj_opt_dqp0.cmplx_thre_qp = 34; + s->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + + s->subj_opt_rdo_split.line_rdo_split_rcoef_d0 = 11; + s->subj_opt_rdo_split.line_rdo_split_rcoef_d1 = 12; + } else if (str == 2) { + s->block_opt_cfg.block_thre_cst_best_mad = 1000; + s->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + s->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + s->block_opt_cfg.block_delta_qp_flag = 3; + + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 4000; + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 200; + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 977; + + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 488; + + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 4; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 30; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 30; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 6; + + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 50; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 50; + + s->subj_opt_dqp0.line_thre_qp = 30; + s->subj_opt_dqp0.block_strength = 4; + s->subj_opt_dqp0.block_thre_qp = 30; + s->subj_opt_dqp0.cmplx_strength = 4; + s->subj_opt_dqp0.cmplx_thre_qp = 34; + s->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + + s->subj_opt_rdo_split.line_rdo_split_rcoef_d0 = 11; + s->subj_opt_rdo_split.line_rdo_split_rcoef_d1 = 13; + } else { + s->block_opt_cfg.block_thre_cst_best_mad = 1000; + s->block_opt_cfg.block_thre_cst_best_grdn_blk = 39; + s->block_opt_cfg.thre_num_grdnt_point_cmplx = 3; + s->block_opt_cfg.block_delta_qp_flag = 3; + + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep0 = 6000; + s->cmplx_opt_cfg.cmplx_thre_cst_best_mad_dep1 = 2000; + + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_mad_dep2 = 300; + s->cmplx_bst_mad_thd.cmplx_thre_cst_best_grdn_blk_dep0 = 1280; + + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep1 = 0; + s->cmplx_bst_grdn_thd.cmplx_thre_cst_best_grdn_blk_dep2 = 512; + + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep0 = 3; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep1 = 20; + s->line_opt_cfg.line_thre_min_cst_best_grdn_blk_dep2 = 20; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep0 = 7; + s->line_opt_cfg.line_thre_ratio_best_grdn_blk_dep1 = 8; + + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep0 = 1; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep1 = 60; + s->line_cst_bst_grdn.line_thre_max_cst_best_grdn_blk_dep2 = 60; + + s->subj_opt_dqp0.line_thre_qp = 30; + s->subj_opt_dqp0.block_strength = 4; + s->subj_opt_dqp0.block_thre_qp = 30; + s->subj_opt_dqp0.cmplx_strength = 4; + s->subj_opt_dqp0.cmplx_thre_qp = 34; + s->subj_opt_dqp0.cmplx_thre_max_grdn_blk = 32; + + s->subj_opt_rdo_split.line_rdo_split_rcoef_d0 = 11; + s->subj_opt_rdo_split.line_rdo_split_rcoef_d1 = 13; + } +} + +static void vepu511a_h265_set_smear_regs(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aSqi *s = ®s->reg_sqi; + RK_S32 frm_num = ctx->frame_num; + RK_S32 gop = (ctx->cfg->rc.gop > 0) ? ctx->cfg->rc.gop : 0x7FFFFFFF; + RK_U32 cover_num = ctx->last_frame_fb.acc_cover16_num; + RK_U32 bndry_num = ctx->last_frame_fb.acc_bndry16_num; + RK_U32 st_ctu_num = ctx->last_frame_fb.st_ctu_num; + RK_S32 str = ctx->cfg->tune.deblur_str; + RK_S16 flag_cover = 0; + RK_S16 flag_bndry = 0; + + static RK_U8 flag_cover_thd0[H265E_SMEAR_STR_NUM] = { 12, 13, 13, 17, 12, 13, 13, 17 }; + static RK_U8 flag_cover_thd1[H265E_SMEAR_STR_NUM] = { 61, 70, 70, 90, 61, 70, 70, 90 }; + static RK_U8 smear_cfc_en[H265E_SMEAR_STR_NUM] = {0, 0, 1, 1, 0, 0, 1, 1}; + static RK_U8 thre_dsp_mov[H265E_SMEAR_STR_NUM] = {15, 15, 46, 46, 15, 15, 46, 46}; + static RK_U8 thre_madp_mov_dep0[H265E_SMEAR_STR_NUM] = {16, 16, 48, 48, 16, 16, 48, 48}; + static RK_U8 thre_madp_mov_dep1[H265E_SMEAR_STR_NUM] = {18, 18, 50, 50, 18, 18, 50, 50}; + static RK_U8 thre_madp_mov_dep2[H265E_SMEAR_STR_NUM] = {20, 20, 52, 52, 20, 20, 52, 52}; + static RK_U8 thre_madp_stc_cover0[H265E_SMEAR_STR_NUM] = { 20, 22, 22, 22, 20, 22, 22, 30 }; + static RK_U8 thre_madp_stc_cover1[H265E_SMEAR_STR_NUM] = { 20, 22, 22, 22, 20, 22, 22, 30 }; + + static RK_S8 flag_cover_wgt[3] = { 1, 0, -3 }; + static RK_S8 flag_bndry_wgt[3] = { 0, 0, 0 }; + static RK_S8 flag_bndry_intra_wgt0[3] = { -12, 0, 12 }; + static RK_S8 flag_bndry_intra_wgt1[3] = { -12, 0, 12 }; + + flag_cover = (cover_num * 1000 < flag_cover_thd0[str] * st_ctu_num) ? 0 : + (cover_num * 1000 < flag_cover_thd1[str] * st_ctu_num) ? 1 : 2; + + flag_bndry = (bndry_num * 1000 < 12 * st_ctu_num) ? 0 : + (bndry_num * 1000 < 73 * st_ctu_num) ? 1 : 2; + + /* anti smear */ + s->smear_opt_cfg0.anti_smear_en = ctx->cfg->tune.deblur_en; + s->smear_opt_cfg0.smear_strength = 3 + flag_bndry_wgt[flag_bndry]; + + s->smear_opt_cfg0.thre_mv_inconfor_cime = 8; + s->smear_opt_cfg0.thre_mv_confor_cime = 0; + s->smear_opt_cfg0.thre_mv_inconfor_cime_gmv = 8; + s->smear_opt_cfg0.thre_mv_confor_cime_gmv = 0; + s->smear_opt_cfg0.thre_num_mv_confor_cime = 3; + s->smear_opt_cfg0.thre_num_mv_confor_cime_gmv = 2; + s->smear_opt_cfg0.frm_static = 1; + s->smear_opt_cfg0.smear_cfc_en = smear_cfc_en[str]; + + s->smear_opt_cfg0.smear_load_en = ((frm_num % gop == 0) || + (s->smear_opt_cfg0.frm_static == 0) || (frm_num % gop == 1)) ? 0 : 1; + s->smear_opt_cfg0.smear_stor_en = ((frm_num % gop == 0) || + (s->smear_opt_cfg0.frm_static == 0) || (frm_num % gop == gop - 1)) ? 0 : 1; + + s->smear_opt_cfg1.dist0_frm_avg = 0; + s->smear_opt_cfg1.thre_dsp_static = 10; + s->smear_opt_cfg1.thre_dsp_mov = thre_dsp_mov[str]; + s->smear_opt_cfg1.thre_dist_mv_confor_cime = 32; + + s->smear_madp_thd.thre_madp_stc_dep0 = 10; + s->smear_madp_thd.thre_madp_stc_dep1 = 8; + s->smear_madp_thd.thre_madp_stc_dep2 = 8; + s->smear_madp_thd.thre_madp_mov_dep0 = thre_madp_mov_dep0[str]; + s->smear_madp_thd.thre_madp_mov_dep1 = thre_madp_mov_dep1[str]; + s->smear_madp_thd.thre_madp_mov_dep2 = thre_madp_mov_dep2[str]; + + s->smear_stat_thd.thre_num_pt_stc_dep0 = 47; + s->smear_stat_thd.thre_num_pt_stc_dep1 = 11; + s->smear_stat_thd.thre_num_pt_stc_dep2 = 3; + s->smear_stat_thd.thre_num_pt_mov_dep0 = 47; + s->smear_stat_thd.thre_num_pt_mov_dep1 = 11; + s->smear_stat_thd.thre_num_pt_mov_dep2 = 3; + + s->smear_bmv_dist_thd0.confor_cime_gmv0 = 21; + s->smear_bmv_dist_thd0.confor_cime_gmv1 = 16; + s->smear_bmv_dist_thd0.inconfor_cime_gmv0 = 48; + s->smear_bmv_dist_thd0.inconfor_cime_gmv1 = 34; + + s->smear_bmv_dist_thd1.inconfor_cime_gmv2 = 32; + s->smear_bmv_dist_thd1.inconfor_cime_gmv3 = 29; + s->smear_bmv_dist_thd1.inconfor_cime_gmv4 = 27; + + s->smear_min_bndry_gmv.thre_min_num_confor_csu0_bndry_cime_gmv = 0; + s->smear_min_bndry_gmv.thre_max_num_confor_csu0_bndry_cime_gmv = 3; + s->smear_min_bndry_gmv.thre_min_num_inconfor_csu0_bndry_cime_gmv = 0; + s->smear_min_bndry_gmv.thre_max_num_inconfor_csu0_bndry_cime_gmv = 3; + s->smear_min_bndry_gmv.thre_split_dep0 = 2; + s->smear_min_bndry_gmv.madi_thre_dep0 = 22; + s->smear_min_bndry_gmv.madi_thre_dep1 = 18; + + s->smear_madp_cov_thd.thre_madp_stc_cover0 = thre_madp_stc_cover0[str]; + s->smear_madp_cov_thd.thre_madp_stc_cover1 = thre_madp_stc_cover1[str]; + s->smear_madp_cov_thd.thre_madp_mov_cover0 = 12; + s->smear_madp_cov_thd.thre_madp_mov_cover1 = 12; + s->smear_madp_cov_thd.smear_qp_strength = 5 + flag_cover_wgt[flag_cover]; + s->smear_madp_cov_thd.smear_thre_qp = 25; + + s->subj_opt_dqp1.bndry_rdo_mode_intra_jcoef_d0 = 24 + flag_bndry_intra_wgt0[flag_bndry]; + s->subj_opt_dqp1.bndry_rdo_mode_intra_jcoef_d1 = 24 + flag_bndry_intra_wgt1[flag_bndry]; + + s->subj_opt_inrar_coef.cover_rmd_mode_intra_jcoef_d0 = 16; + s->subj_opt_inrar_coef.cover_rmd_mode_intra_jcoef_d1 = 16; + s->subj_opt_inrar_coef.cover_rdo_mode_intra_jcoef_d0 = 16; + s->subj_opt_inrar_coef.cover_rdo_mode_intra_jcoef_d1 = 16; + + s->smear_opt_cfc_coef.cfc_rmd_mode_intra_jcoef_d0 = 20; + s->smear_opt_cfc_coef.cfc_rmd_mode_intra_jcoef_d1 = 20; + s->smear_opt_cfc_coef.cfc_rdo_mode_intra_jcoef_d0 = 20; + s->smear_opt_cfc_coef.cfc_rdo_mode_intra_jcoef_d1 = 20; +} + +static void vepu511a_h265_set_anti_stripe_regs(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aSqi *s = ®s->reg_sqi; + pre_cst_par* pre_i32 = (pre_cst_par*)&s->preintra32_cst; + pre_cst_par* pre_i16 = (pre_cst_par*)&s->preintra16_cst; + RK_U32 str = ctx->cfg->tune.atl_str; + RK_U32 str_idx = 0; + RK_U32 idx = 0; + + static RK_U32 pre_i32_cst_thd[3][16] = { + { 4, 14, 4, 3, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5, 28 }, + { 4, 14, 4, 3, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5, 28 }, + { 6, 17, 6, 4, 4, 7, 8, 6, 12, 6, 8, 6, 8, 6, 5, 28 } + }; + + static RK_U32 pre_i32_cst_wgt[3][15] = { + { 19, 17, 18, 17, 13, 8, 14, 10, 13, 8, 14, 10, 17, 17, 17 }, + { 20, 18, 19, 18, 12, 6, 13, 9, 12, 6, 13, 9, 18, 17, 17 }, + { 22, 19, 20, 19, 11, 5, 12, 8, 11, 5, 12, 8, 19, 18, 18 } + }; + + static RK_U32 pre_i16_cst_thd[3][15] = { + { 4, 14, 4, 4, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5 }, + { 4, 14, 4, 4, 3, 5, 6, 4, 9, 4, 6, 4, 6, 4, 5 }, + { 6, 18, 6, 4, 4, 7, 8, 6, 12, 6, 8, 6, 8, 6, 5 } + }; + + static RK_U32 pre_i16_cst_wgt[3][15] = { + { 19, 17, 18, 17, 13, 8, 14, 10, 13, 8, 14, 10, 17, 17, 17 }, + { 20, 18, 19, 18, 12, 6, 13, 9, 12, 6, 13, 9, 18, 17, 17 }, + { 22, 19, 18, 19, 11, 5, 12, 8, 11, 5, 12, 8, 19, 18, 18 } + }; + + pre_i32->cst_wgt3.anti_strp_e = !!ctx->cfg->tune.atl_str; + + if (str == 0) + return; + + pre_i32->cst_wgt3.lambda_mv_bit_0 = 4; + pre_i32->cst_wgt3.lambda_mv_bit_1 = 3; + pre_i16->cst_wgt3.lambda_mv_bit_0 = 3; + pre_i16->cst_wgt3.lambda_mv_bit_1 = 3; + + /* 0 - disable; 1 - weak; 2 - medium; 3 - strong */ + str_idx = str - 1; + for (idx = 0; idx < MPP_ARRAY_ELEMS(pre_i32->cst_madi_thd); idx++) + pre_i32->cst_madi_thd[idx] = pre_i32_cst_thd[str_idx][idx]; + pre_i32->cst_madi_thd3.mode_th = pre_i32_cst_thd[str_idx][14]; + pre_i32->cst_madi_thd3.qp_thd = pre_i32_cst_thd[str_idx][15]; + + for (idx = 0; idx < MPP_ARRAY_ELEMS(pre_i32->cst_wgt); idx++) + pre_i32->cst_wgt[idx] = pre_i32_cst_wgt[str_idx][idx]; + + for (idx = 0; idx < MPP_ARRAY_ELEMS(pre_i16->cst_madi_thd); idx++) + pre_i16->cst_madi_thd[idx] = pre_i16_cst_thd[str_idx][idx]; + pre_i16->cst_madi_thd3.mode_th = pre_i16_cst_thd[str_idx][14]; + + for (idx = 0; idx < MPP_ARRAY_ELEMS(pre_i16->cst_wgt); idx++) + pre_i16->cst_wgt[idx] = pre_i16_cst_wgt[str_idx][idx]; +} + +static MPP_RET vepu511a_h265_set_rdo_regs(H265eV511ARegSet *regs) +{ + Vepu511aRcRoi *reg_rc = ®s->reg_rc_roi; + + reg_rc->cudecis_thd0.base_thre_rough_mad32_intra = 9; + reg_rc->cudecis_thd0.delta0_thre_rough_mad32_intra = 10; + reg_rc->cudecis_thd0.delta1_thre_rough_mad32_intra = 55; + reg_rc->cudecis_thd0.delta2_thre_rough_mad32_intra = 55; + reg_rc->cudecis_thd0.delta3_thre_rough_mad32_intra = 66; + reg_rc->cudecis_thd0.delta4_thre_rough_mad32_intra_low5 = 2; + + reg_rc->cudecis_thd1.delta4_thre_rough_mad32_intra_high2 = 2; + reg_rc->cudecis_thd1.delta5_thre_rough_mad32_intra = 74; + reg_rc->cudecis_thd1.delta6_thre_rough_mad32_intra = 106; + reg_rc->cudecis_thd1.base_thre_fine_mad32_intra = 8; + reg_rc->cudecis_thd1.delta0_thre_fine_mad32_intra = 0; + reg_rc->cudecis_thd1.delta1_thre_fine_mad32_intra = 13; + reg_rc->cudecis_thd1.delta2_thre_fine_mad32_intra_low3 = 6; + + reg_rc->cudecis_thd2.delta2_thre_fine_mad32_intra_high2 = 1; + reg_rc->cudecis_thd2.delta3_thre_fine_mad32_intra = 17; + reg_rc->cudecis_thd2.delta4_thre_fine_mad32_intra = 23; + reg_rc->cudecis_thd2.delta5_thre_fine_mad32_intra = 50; + reg_rc->cudecis_thd2.delta6_thre_fine_mad32_intra = 54; + reg_rc->cudecis_thd2.base_thre_str_edge_mad32_intra = 6; + reg_rc->cudecis_thd2.delta0_thre_str_edge_mad32_intra = 0; + reg_rc->cudecis_thd2.delta1_thre_str_edge_mad32_intra = 0; + + reg_rc->cudecis_thd3.delta2_thre_str_edge_mad32_intra = 3; + reg_rc->cudecis_thd3.delta3_thre_str_edge_mad32_intra = 8; + reg_rc->cudecis_thd3.base_thre_str_edge_bgrad32_intra = 25; + reg_rc->cudecis_thd3.delta0_thre_str_edge_bgrad32_intra = 0; + reg_rc->cudecis_thd3.delta1_thre_str_edge_bgrad32_intra = 0; + reg_rc->cudecis_thd3.delta2_thre_str_edge_bgrad32_intra = 7; + reg_rc->cudecis_thd3.delta3_thre_str_edge_bgrad32_intra = 19; + reg_rc->cudecis_thd3.base_thre_mad16_intra = 6; + reg_rc->cudecis_thd3.delta0_thre_mad16_intra = 0; + + reg_rc->cudecis_thd4.delta1_thre_mad16_intra = 3; + reg_rc->cudecis_thd4.delta2_thre_mad16_intra = 3; + reg_rc->cudecis_thd4.delta3_thre_mad16_intra = 24; + reg_rc->cudecis_thd4.delta4_thre_mad16_intra = 28; + reg_rc->cudecis_thd4.delta5_thre_mad16_intra = 40; + reg_rc->cudecis_thd4.delta6_thre_mad16_intra = 52; + reg_rc->cudecis_thd4.delta0_thre_mad16_ratio_intra = 7; + + reg_rc->cudecis_thd5.delta1_thre_mad16_ratio_intra = 7; + reg_rc->cudecis_thd5.delta2_thre_mad16_ratio_intra = 2; + reg_rc->cudecis_thd5.delta3_thre_mad16_ratio_intra = 2; + reg_rc->cudecis_thd5.delta4_thre_mad16_ratio_intra = 0; + reg_rc->cudecis_thd5.delta5_thre_mad16_ratio_intra = 0; + reg_rc->cudecis_thd5.delta6_thre_mad16_ratio_intra = 0; + reg_rc->cudecis_thd5.delta7_thre_mad16_ratio_intra = 4; + reg_rc->cudecis_thd5.delta0_thre_rough_bgrad32_intra = 1; + reg_rc->cudecis_thd5.delta1_thre_rough_bgrad32_intra = 5; + reg_rc->cudecis_thd5.delta2_thre_rough_bgrad32_intra_low4 = 8; + + reg_rc->cudecis_thd6.delta2_thre_rough_bgrad32_intra_high2 = 2; + reg_rc->cudecis_thd6.delta3_thre_rough_bgrad32_intra = 540; + reg_rc->cudecis_thd6.delta4_thre_rough_bgrad32_intra = 692; + reg_rc->cudecis_thd6.delta5_thre_rough_bgrad32_intra_low10 = 866; + + reg_rc->cudecis_thd7.delta5_thre_rough_bgrad32_intra_high1 = 1; + reg_rc->cudecis_thd7.delta6_thre_rough_bgrad32_intra = 3286; + reg_rc->cudecis_thd7.delta7_thre_rough_bgrad32_intra = 6620; + reg_rc->cudecis_thd7.delta0_thre_bgrad16_ratio_intra = 8; + reg_rc->cudecis_thd7.delta1_thre_bgrad16_ratio_intra_low2 = 3; + + reg_rc->cudecis_thd8.delta1_thre_bgrad16_ratio_intra_high2 = 2; + reg_rc->cudecis_thd8.delta2_thre_bgrad16_ratio_intra = 15; + reg_rc->cudecis_thd8.delta3_thre_bgrad16_ratio_intra = 15; + reg_rc->cudecis_thd8.delta4_thre_bgrad16_ratio_intra = 13; + reg_rc->cudecis_thd8.delta5_thre_bgrad16_ratio_intra = 13; + reg_rc->cudecis_thd8.delta6_thre_bgrad16_ratio_intra = 7; + reg_rc->cudecis_thd8.delta7_thre_bgrad16_ratio_intra = 15; + reg_rc->cudecis_thd8.delta0_thre_fme_ratio_inter = 4; + reg_rc->cudecis_thd8.delta1_thre_fme_ratio_inter = 4; + + reg_rc->cudecis_thd9.delta2_thre_fme_ratio_inter = 3; + reg_rc->cudecis_thd9.delta3_thre_fme_ratio_inter = 2; + reg_rc->cudecis_thd9.delta4_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.delta5_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.delta6_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.delta7_thre_fme_ratio_inter = 0; + reg_rc->cudecis_thd9.base_thre_fme32_inter = 4; + reg_rc->cudecis_thd9.delta0_thre_fme32_inter = 2; + reg_rc->cudecis_thd9.delta1_thre_fme32_inter = 7; + reg_rc->cudecis_thd9.delta2_thre_fme32_inter = 12; + + reg_rc->cudecis_thd10.delta3_thre_fme32_inter = 23; + reg_rc->cudecis_thd10.delta4_thre_fme32_inter = 41; + reg_rc->cudecis_thd10.delta5_thre_fme32_inter = 71; + reg_rc->cudecis_thd10.delta6_thre_fme32_inter = 123; + reg_rc->cudecis_thd10.thre_cme32_inter = 48; + + reg_rc->cudecis_thd11.delta0_thre_mad_fme_ratio_inter = 0; + reg_rc->cudecis_thd11.delta1_thre_mad_fme_ratio_inter = 7; + reg_rc->cudecis_thd11.delta2_thre_mad_fme_ratio_inter = 7; + reg_rc->cudecis_thd11.delta3_thre_mad_fme_ratio_inter = 6; + reg_rc->cudecis_thd11.delta4_thre_mad_fme_ratio_inter = 5; + reg_rc->cudecis_thd11.delta5_thre_mad_fme_ratio_inter = 4; + reg_rc->cudecis_thd11.delta6_thre_mad_fme_ratio_inter = 4; + reg_rc->cudecis_thd11.delta7_thre_mad_fme_ratio_inter = 4; + + reg_rc->cudecis_thd12.delta0_thre_mad_fme_ratio_inter = 1; + reg_rc->cudecis_thd12.delta1_thre_mad_fme_ratio_inter = 3; + reg_rc->cudecis_thd12.delta2_thre_mad_fme_ratio_inter = 6; + reg_rc->cudecis_thd12.delta3_thre_mad_fme_ratio_inter = 9; + reg_rc->cudecis_thd12.delta4_thre_mad_fme_ratio_inter = 10; + reg_rc->cudecis_thd12.delta5_thre_mad_fme_ratio_inter = 11; + reg_rc->cudecis_thd12.delta6_thre_mad_fme_ratio_inter = 12; + reg_rc->cudecis_thd12.delta7_thre_mad_fme_ratio_inter = 15; + + return MPP_OK; +} + +static void vepu511a_h265_set_sao_regs(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aSqi *sqi = ®s->reg_sqi; + RK_U32 mode_idx = (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) ? 0 : 1; + RK_U32 str = ctx->frame_type == INTRA_FRAME ? + ctx->cfg->tune.sao_str_i : ctx->cfg->tune.sao_str_p; + RK_U32 str_idx = 0; + + static const RK_U32 blur_low_madi_thd[2][4] = { + { 5, 5, 5, 5 }, { 4, 4, 4, 4 } + }; + static const RK_U32 blur_high_madi_thd[2][4] = { + { 27, 27, 27, 27 }, { 36, 32, 32, 32 } + }; + static const RK_U32 blur_low_cnt_thd[2][4] = { + { 15, 2, 3, 2 }, { 4, 4, 3, 3 } + }; + static const RK_U32 blur_high_cnt_thd[2][4] = { + { 15, 2, 3, 2 }, { 4, 4, 3, 3 } + }; + static const RK_U32 blur_sum_cnt_thd[2][4] = { + { 15, 10, 10, 8 }, { 14, 12, 12, 8 } + }; + static const RK_U32 blur_motion_thd[2][4] = { + { 32, 32, 32, 32 }, { 32, 32, 32, 32 } + }; + + /* Weight values are set to 4 to disable SAO subjective optimization. + * They are not under the control of anti_blur_en. + */ + sqi->subj_anti_blur_wgt3.merge_cost_dist_eo_wgt0 = 4; + sqi->subj_anti_blur_wgt3.merge_cost_dist_bo_wgt0 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_dist_eo_wgt1 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_dist_bo_wgt1 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_bit_eo_wgt0 = 4; + sqi->subj_anti_blur_wgt4.merge_cost_bit_bo_wgt0 = 4; + + if (str == 0) { + sqi->subj_anti_blur_thd.anti_blur_en = 0; + return; + } + + str_idx = str - 1; + sqi->subj_anti_blur_wgt3.merge_cost_dist_eo_wgt0 = 2; + sqi->subj_anti_blur_wgt3.merge_cost_dist_bo_wgt0 = 3; + sqi->subj_anti_blur_wgt4.merge_cost_dist_eo_wgt1 = 8; + sqi->subj_anti_blur_wgt4.merge_cost_dist_bo_wgt1 = 6; + sqi->subj_anti_blur_wgt4.merge_cost_bit_eo_wgt0 = 8; + sqi->subj_anti_blur_wgt4.merge_cost_bit_bo_wgt0 = 6; + + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_eo_wgt0 = 12; + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_bo_wgt0 = 12; + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_eo_wgt1 = 24; + sqi->subj_anti_blur_wgt0.notmerge_ofst_dist_bo_wgt1 = 20; + + sqi->subj_anti_blur_wgt1.notmerge_ofst_lambda_eo_wgt0 = 20; + sqi->subj_anti_blur_wgt1.notmerge_ofst_lambda_bo_wgt0 = 20; + sqi->subj_anti_blur_wgt1.notmerge_compare_dist_eo_wgt0 = 12; + sqi->subj_anti_blur_wgt1.notmerge_compare_dist_bo_wgt0 = 12; + + sqi->subj_anti_blur_wgt2.notmerge_compare_dist_eo_wgt1 = 24; + sqi->subj_anti_blur_wgt2.notmerge_compare_dist_bo_wgt1 = 20; + sqi->subj_anti_blur_wgt2.notmerge_compare_rate_eo_wgt0 = 20; + sqi->subj_anti_blur_wgt2.notmerge_compare_rate_bo_wgt0 = 20; + + sqi->subj_anti_blur_wgt3.sao_mode_compare_dist_eo_wgt0 = 24; + sqi->subj_anti_blur_wgt3.sao_mode_compare_dist_bo_wgt0 = 20; + + sqi->subj_anti_blur_thd.anti_blur_en = 1; + sqi->subj_anti_blur_thd.scene_mode = mode_idx; + sqi->subj_anti_blur_sao.sao_ofst_thd_eo_luma = 4; + sqi->subj_anti_blur_sao.sao_ofst_thd_bo_luma = 4; + sqi->subj_anti_blur_sao.sao_ofst_thd_eo_chroma = 4; + sqi->subj_anti_blur_sao.sao_ofst_thd_bo_chroma = 4; + + sqi->subj_anti_blur_thd.blur_low_madi_thd = blur_low_madi_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_high_madi_thd = blur_high_madi_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_low_cnt_thd = blur_low_cnt_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_hight_cnt_thd = blur_high_cnt_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_thd.blur_sum_cnt_thd = blur_sum_cnt_thd[mode_idx][str_idx]; + sqi->subj_anti_blur_sao.blur_motion_thd = blur_motion_thd[mode_idx][str_idx]; +} + +static void vepu511a_h265_set_slice_regs(H265eSyntax_new *syn, H265eVepu511aFrame *regs) +{ + regs->synt_sps.smpl_adpt_ofst_e = syn->pp.sample_adaptive_offset_enabled_flag; + regs->synt_sps.num_st_ref_pic = syn->pp.num_short_term_ref_pic_sets; + regs->synt_sps.num_lt_ref_pic = syn->pp.num_long_term_ref_pics_sps; + regs->synt_sps.lt_ref_pic_prsnt = syn->pp.long_term_ref_pics_present_flag; + regs->synt_sps.tmpl_mvp_e = syn->pp.sps_temporal_mvp_enabled_flag; + regs->synt_sps.log2_max_poc_lsb = syn->pp.log2_max_pic_order_cnt_lsb_minus4; + regs->synt_sps.strg_intra_smth = syn->pp.strong_intra_smoothing_enabled_flag; + + regs->synt_pps.dpdnt_sli_seg_en = syn->pp.dependent_slice_segments_enabled_flag; + regs->synt_pps.out_flg_prsnt_flg = syn->pp.output_flag_present_flag; + regs->synt_pps.num_extr_sli_hdr = syn->pp.num_extra_slice_header_bits; + regs->synt_pps.sgn_dat_hid_en = syn->pp.sign_data_hiding_enabled_flag; + regs->synt_pps.cbc_init_prsnt_flg = syn->pp.cabac_init_present_flag; + regs->synt_pps.pic_init_qp = syn->pp.init_qp_minus26 + 26; + regs->synt_pps.cu_qp_dlt_en = syn->pp.cu_qp_delta_enabled_flag; + regs->synt_pps.lp_fltr_acrs_sli = syn->pp.pps_loop_filter_across_slices_enabled_flag; + regs->synt_pps.dblk_fltr_ovrd_en = syn->pp.deblocking_filter_override_enabled_flag; + regs->synt_pps.lst_mdfy_prsnt_flg = syn->pp.lists_modification_present_flag; + regs->synt_pps.sli_seg_hdr_extn = syn->pp.slice_segment_header_extension_present_flag; + regs->synt_pps.cu_qp_dlt_depth = syn->pp.diff_cu_qp_delta_depth; + regs->synt_pps.lpf_fltr_acrs_til = syn->pp.loop_filter_across_tiles_enabled_flag; + + regs->synt_sli0.cbc_init_flg = syn->sp.cbc_init_flg; + regs->synt_sli0.mvd_l1_zero_flg = syn->sp.mvd_l1_zero_flg; + regs->synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + regs->synt_sli0.num_refidx_l1_act = syn->sp.num_refidx_l1_act; + regs->synt_sli0.num_refidx_l0_act = syn->sp.num_refidx_l0_act; + + regs->synt_sli0.num_refidx_act_ovrd = syn->sp.num_refidx_act_ovrd; + + regs->synt_sli0.sli_sao_chrm_flg = syn->sp.sli_sao_chrm_flg; + regs->synt_sli0.sli_sao_luma_flg = syn->sp.sli_sao_luma_flg; + regs->synt_sli0.sli_tmprl_mvp_e = syn->sp.sli_tmprl_mvp_en; + regs->common.enc_pic.num_pic_tot_cur_hevc = syn->sp.tot_poc_num; + + regs->synt_sli0.pic_out_flg = syn->sp.pic_out_flg; + regs->synt_sli0.sli_type = syn->sp.slice_type; + regs->synt_sli0.sli_rsrv_flg = syn->sp.slice_rsrv_flg; + regs->synt_sli0.dpdnt_sli_seg_flg = syn->sp.dpdnt_sli_seg_flg; + regs->synt_sli0.sli_pps_id = syn->sp.sli_pps_id; + regs->synt_sli0.no_out_pri_pic = syn->sp.no_out_pri_pic; + + + regs->synt_sli1.sp_tc_ofst_div2 = syn->sp.sli_tc_ofst_div2;; + regs->synt_sli1.sp_beta_ofst_div2 = syn->sp.sli_beta_ofst_div2; + regs->synt_sli1.sli_lp_fltr_acrs_sli = syn->sp.sli_lp_fltr_acrs_sli; + regs->synt_sli1.sp_dblk_fltr_dis = syn->sp.sli_dblk_fltr_dis; + regs->synt_sli1.dblk_fltr_ovrd_flg = syn->sp.dblk_fltr_ovrd_flg; + regs->synt_sli1.sli_cb_qp_ofst = syn->pp.pps_slice_chroma_qp_offsets_present_flag ? + syn->sp.sli_cb_qp_ofst : syn->pp.pps_cb_qp_offset; + regs->synt_sli1.max_mrg_cnd = 3; + + regs->synt_sli1.col_ref_idx = syn->sp.col_ref_idx; + regs->synt_sli1.col_frm_l0_flg = syn->sp.col_frm_l0_flg; + regs->synt_sli2.sli_poc_lsb = syn->sp.sli_poc_lsb; + regs->synt_sli2.sli_hdr_ext_len = syn->sp.sli_hdr_ext_len; +} + +static void vepu511a_h265_set_ref_regs(H265eSyntax_new *syn, H265eVepu511aFrame *regs) +{ + regs->synt_refm0.st_ref_pic_flg = syn->sp.st_ref_pic_flg; + regs->synt_refm0.poc_lsb_lt0 = syn->sp.poc_lsb_lt0; + regs->synt_refm0.num_lt_pic = syn->sp.num_lt_pic; + + regs->synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->synt_refm1.used_by_lt_flg0 = syn->sp.used_by_lt_flg0; + regs->synt_refm1.used_by_lt_flg1 = syn->sp.used_by_lt_flg1; + regs->synt_refm1.used_by_lt_flg2 = syn->sp.used_by_lt_flg2; + regs->synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->synt_refm1.dlt_poc_msb_prsnt1 = syn->sp.dlt_poc_msb_prsnt1; + regs->synt_refm1.num_negative_pics = syn->sp.num_neg_pic; + regs->synt_refm1.num_pos_pic = syn->sp.num_pos_pic; + + regs->synt_refm1.used_by_s0_flg = syn->sp.used_by_s0_flg; + regs->synt_refm2.dlt_poc_s0_m10 = syn->sp.dlt_poc_s0_m10; + regs->synt_refm2.dlt_poc_s0_m11 = syn->sp.dlt_poc_s0_m11; + regs->synt_refm3.dlt_poc_s0_m12 = syn->sp.dlt_poc_s0_m12; + regs->synt_refm3.dlt_poc_s0_m13 = syn->sp.dlt_poc_s0_m13; + + regs->synt_long_refm0.poc_lsb_lt1 = syn->sp.poc_lsb_lt1; + regs->synt_long_refm1.dlt_poc_msb_cycl1 = syn->sp.dlt_poc_msb_cycl1; + regs->synt_long_refm0.poc_lsb_lt2 = syn->sp.poc_lsb_lt2; + regs->synt_refm1.dlt_poc_msb_prsnt2 = syn->sp.dlt_poc_msb_prsnt2; + regs->synt_long_refm1.dlt_poc_msb_cycl2 = syn->sp.dlt_poc_msb_cycl2; + regs->synt_sli1.lst_entry_l0 = syn->sp.lst_entry_l0; + regs->synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + return; +} + +static void vepu511a_h265_set_atf_regs(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aSqi *reg = ®s->reg_sqi; + RK_U32 str = ctx->cfg->tune.atf_str; + rdo_b32_skip_par *p_rdo_b32_skip = NULL; + rdo_b32_noskip_par *p_rdo_b32_noskip = NULL; + rdo_skip_par *p_rdo_skip = NULL; + rdo_noskip_par *p_rdo_noskip = NULL; + RK_U32 str_idx = 0; + + static RK_U8 b32_skip_wgt0[3] = { 24, 14, 12 }; + static RK_U8 b32_skip_wgt1[3] = { 20, 12, 10 }; + static RK_U8 b32_skip_wgt2[3] = { 20, 12, 10 }; + static RK_U8 b16_skip_wgt0[3] = { 24, 14, 12 }; + static RK_U8 b16_skip_wgt1[3] = { 20, 10, 8 }; + static RK_U8 b16_skip_wgt2[3] = { 20, 10, 8 }; + static RK_U8 b32_inter_wgt0[3] = { 24, 26, 28 }; + static RK_U8 b32_inter_wgt1[3] = { 20, 22, 26 }; + static RK_U8 b32_inter_wgt2[3] = { 20, 22, 26 }; + static RK_U8 b16_inter_wgt0[3] = { 32, 40, 44 }; + static RK_U8 b16_inter_wgt1[3] = { 28, 40, 44 }; + static RK_U8 b16_inter_wgt2[3] = { 28, 40, 44 }; + static RK_U8 b32_intra_wgt0[3] = { 32, 36, 42 }; + static RK_U8 b32_intra_wgt1[3] = { 32, 36, 42 }; + static RK_U8 b32_intra_wgt2[3] = { 32, 36, 42 }; + static RK_U8 b16_intra_wgt0[3] = { 40, 44, 48 }; + static RK_U8 b16_intra_wgt1[3] = { 40, 44, 48 }; + static RK_U8 b16_intra_wgt2[3] = { 40, 44, 48 }; + + reg->rdo_b32_skip.atf_thd0.flckr_en = !!str; + reg->rdo_b32_skip.atf_thd0.flckr_frame_qp_en = !!str; + reg->rdo_b32_skip.atf_thd0.flckr_lgt_chng_en = !!str; + + if (str == 0) + return; + + /* 0 - disable; 1 - weak; 2 - medium; 3 - strong */ + str_idx = str - 1; + reg->dark_brgt_opt_cfg.thre_max_luma_dark = 20; + reg->dark_brgt_opt_cfg.thre_min_luma_bright = 235; + reg->dark_brgt_opt_cfg.thre_ratio_dark_bright = 48; + + p_rdo_b32_skip = ®->rdo_b32_skip; + p_rdo_b32_skip->atf_thd0.madp_thd0 = 1; + p_rdo_b32_skip->atf_thd0.madp_thd1 = 20; + p_rdo_b32_skip->atf_thd1.madp_thd2 = 40; + p_rdo_b32_skip->atf_thd1.madp_thd3 = 60; + p_rdo_b32_skip->atf_wgt0.wgt0 = b32_skip_wgt0[str_idx]; + p_rdo_b32_skip->atf_wgt0.wgt1 = b32_skip_wgt1[str_idx]; + p_rdo_b32_skip->atf_wgt0.wgt2 = b32_skip_wgt2[str_idx]; + p_rdo_b32_skip->atf_wgt0.wgt3 = 0; + + p_rdo_b32_noskip = ®->rdo_b32_inter; + p_rdo_b32_noskip->atf_thd0.madp_thd0 = 8; + p_rdo_b32_noskip->atf_thd0.madp_thd1 = 16; + p_rdo_b32_noskip->atf_thd1.madp_thd2 = 32; + p_rdo_b32_noskip->atf_thd1.flckr_zero_mv_j_coef = 16; + p_rdo_b32_noskip->atf_wgt.wgt0 = b32_inter_wgt0[str_idx]; + p_rdo_b32_noskip->atf_wgt.wgt1 = b32_inter_wgt1[str_idx]; + p_rdo_b32_noskip->atf_wgt.wgt2 = b32_inter_wgt2[str_idx]; + + p_rdo_noskip = ®->rdo_b32_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = 400; + p_rdo_noskip->ratf_thd0.madp_thd1 = 400; + p_rdo_noskip->ratf_thd1.madp_thd2 = 400; + p_rdo_noskip->atf_wgt.wgt0 = b32_intra_wgt0[str_idx]; + p_rdo_noskip->atf_wgt.wgt1 = b32_intra_wgt1[str_idx]; + p_rdo_noskip->atf_wgt.wgt2 = b32_intra_wgt2[str_idx]; + + p_rdo_skip = ®->rdo_b16_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 1; + p_rdo_skip->atf_thd0.madp_thd1 = 20; + p_rdo_skip->atf_thd1.madp_thd2 = 40; + p_rdo_skip->atf_thd1.madp_thd3 = 60; + p_rdo_skip->atf_wgt0.wgt0 = b16_skip_wgt0[str_idx]; + p_rdo_skip->atf_wgt0.wgt1 = b16_skip_wgt1[str_idx]; + p_rdo_skip->atf_wgt0.wgt2 = b16_skip_wgt2[str_idx]; + p_rdo_skip->atf_wgt0.wgt3 = 2; + + p_rdo_noskip = ®->rdo_b16_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 8; + p_rdo_noskip->ratf_thd0.madp_thd1 = 16; + p_rdo_noskip->ratf_thd1.madp_thd2 = 32; + p_rdo_noskip->atf_wgt.wgt0 = b16_inter_wgt0[str_idx]; + p_rdo_noskip->atf_wgt.wgt1 = b16_inter_wgt1[str_idx]; + p_rdo_noskip->atf_wgt.wgt2 = b16_inter_wgt2[str_idx]; + + p_rdo_noskip = ®->rdo_b16_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = 150; + p_rdo_noskip->ratf_thd0.madp_thd1 = 150; + p_rdo_noskip->ratf_thd1.madp_thd2 = 150; + p_rdo_noskip->atf_wgt.wgt0 = b16_intra_wgt0[str_idx]; + p_rdo_noskip->atf_wgt.wgt1 = b16_intra_wgt1[str_idx]; + p_rdo_noskip->atf_wgt.wgt2 = b16_intra_wgt2[str_idx]; + p_rdo_noskip->atf_wgt.wgt3 = 25; +} + +static void vepu511a_h265_set_aq(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + Vepu511aRcRoi *rc_regs = ®s->reg_rc_roi; + RK_S32 *aq_step, *aq_rnge; + RK_U32 *aq_thd; + RK_U32 i; + + if (ctx->frame_type == INTRA_FRAME) { + aq_thd = &hw->aq_thrd_i[0]; + aq_step = &hw->aq_step_i[0]; + aq_rnge = &hw->aq_rnge_arr[0]; + } else { + aq_thd = &hw->aq_thrd_p[0]; + aq_step = &hw->aq_step_p[0]; + aq_rnge = &hw->aq_rnge_arr[5]; + } + + rc_regs->aq_stp0.aq_stp_s0 = aq_step[0] & 0x1f; + rc_regs->aq_stp0.aq_stp_0t1 = aq_step[1] & 0x1f; + rc_regs->aq_stp0.aq_stp_1t2 = aq_step[2] & 0x1f; + rc_regs->aq_stp0.aq_stp_2t3 = aq_step[3] & 0x1f; + rc_regs->aq_stp0.aq_stp_3t4 = aq_step[4] & 0x1f; + rc_regs->aq_stp0.aq_stp_4t5 = aq_step[5] & 0x1f; + rc_regs->aq_stp1.aq_stp_5t6 = aq_step[6] & 0x1f; + rc_regs->aq_stp1.aq_stp_6t7 = aq_step[7] & 0x1f; + rc_regs->aq_stp1.aq_stp_7t8 = 0; + rc_regs->aq_stp1.aq_stp_8t9 = aq_step[8] & 0x1f; + rc_regs->aq_stp1.aq_stp_9t10 = aq_step[9] & 0x1f; + rc_regs->aq_stp1.aq_stp_10t11 = aq_step[10] & 0x1f; + rc_regs->aq_stp2.aq_stp_11t12 = aq_step[11] & 0x1f; + rc_regs->aq_stp2.aq_stp_12t13 = aq_step[12] & 0x1f; + rc_regs->aq_stp2.aq_stp_13t14 = aq_step[13] & 0x1f; + rc_regs->aq_stp2.aq_stp_14t15 = aq_step[14] & 0x1f; + rc_regs->aq_stp2.aq_stp_b15 = aq_step[15]; + + for (i = 0; i < 16; i++) + rc_regs->aq_tthd[i] = aq_thd[i]; + + rc_regs->aq_clip.aq16_rnge = aq_rnge[0]; + rc_regs->aq_clip.aq32_rnge = aq_rnge[1]; + rc_regs->aq_clip.aq8_rnge = aq_rnge[2]; + rc_regs->aq_clip.aq16_dif0 = aq_rnge[3]; + rc_regs->aq_clip.aq16_dif1 = aq_rnge[4]; + + rc_regs->aq_clip.aq_rme_en = 1; + rc_regs->aq_clip.aq_cme_en = 1; + rc_regs->aq_clip.aq_subj_cme_en = 0; + rc_regs->aq_clip.aq_subj_rme_en = 1; +} + +static void vepu511a_h265_set_subj_opt_regs(H265eV511ARegSet *regs) +{ + H265eVepu511aSqi *s = ®s->reg_sqi; + + s->subj_opt_cfg.subj_opt_en = 1; + s->subj_opt_cfg.aq_subj_en = 1; + s->subj_opt_cfg.thre_sum_grdn_point = 1800; + s->subj_opt_dpth_thd.common_thre_num_grdn_point_dep0 = 64; + s->subj_opt_dpth_thd.common_thre_num_grdn_point_dep1 = 32; + s->subj_opt_dpth_thd.common_thre_num_grdn_point_dep2 = 16; + + // Set the RDO split cost coefficient. + // Priority: smear takes precedence over anti-ring. + if (s->smear_opt_cfg0.anti_smear_en == 1) { + s->subj_opt_rdo_split.choose_cu16_split_jcoef = 8; + } else if (s->line_opt_cfg.line_en == 1) { + s->subj_opt_rdo_split.choose_cu16_split_jcoef = 8; + } +} + +static void vepu511a_h265_global_cfg_set(H265eV511AHalContext *ctx, H265eV511ARegSet *regs) +{ + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + H265eVepu511aParam *reg_param = ®s->reg_param; + RK_S32 lambda_idx_p = ctx->cfg->tune.lambda_idx_i; + + reg_frm->sao_cfg.sao_lambda_multi = ctx->cfg->h265.sao_cfg.sao_bit_ratio; + + if (ctx->frame_type == INTRA_FRAME) { + memcpy(®_param->pprd_lamb_satd_0_51[0], lambda_tbl_pre_intra, sizeof(lambda_tbl_pre_intra)); + } else { + memcpy(®_param->pprd_lamb_satd_0_51[0], lambda_tbl_pre_inter, sizeof(lambda_tbl_pre_inter)); + } + + { + RK_U32 *lambda_tbl; + + if (ctx->frame_type == INTRA_FRAME) { + lambda_tbl = &rdo_lambda_table_I[lambda_idx_p]; + } else { + lambda_idx_p = ctx->cfg->tune.lambda_idx_p; + lambda_tbl = &rdo_lambda_table_P[lambda_idx_p]; + } + + memcpy(®_param->rdo_wgta_qp_grpa_0_51[0], lambda_tbl, H265E_LAMBDA_TAB_SIZE); + } + + /* 0x1064 */ + regs->reg_rc_roi.madi_st_thd.madi_th0 = 5; + regs->reg_rc_roi.madi_st_thd.madi_th1 = 12; + regs->reg_rc_roi.madi_st_thd.madi_th2 = 20; + /* 0x1068 */ + regs->reg_rc_roi.madp_st_thd0.madp_th0 = 4 << 4; + regs->reg_rc_roi.madp_st_thd0.madp_th1 = 9 << 4; + /* 0x106C */ + regs->reg_rc_roi.madp_st_thd1.madp_th2 = 15 << 4; + regs->reg_param.prmd_intra_lamb_ofst.lambda_luma_offset = 11; + regs->reg_param.prmd_intra_lamb_ofst.lambda_chroma_offset = 11; + +} + +MPP_RET hal_h265e_vepu511a_gen_regs(void *hal, HalEncTask *task) +{ + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + Vepu511aH265eFrmCfg *frm_cfg = ctx->frm; + H265eV511ARegSet *regs = frm_cfg->regs_set; + MPP_RET ret = MPP_OK; + + HalEncTask *enc_task = task; + H265eSyntax_new *syn = ctx->syn; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + EncFrmStatus *frm = &task->rc_task->frm; + + hal_h265e_enter(); + + hal_h265e_dbg_simple("frame %d | type %d | start gen regs11", + ctx->frame_num, ctx->frame_type); + + memset(regs, 0, sizeof(H265eV511ARegSet)); + + vepu511a_h265_set_normal(ctx, regs); + vepu511a_h265_set_prep(ctx, task, regs); + vepu511a_h265_set_me_regs(ctx, syn , regs); + vepu511a_h265_set_split(regs, ctx->cfg); + vepu511a_set_speed(ctx, regs); + vepu511a_h265_set_hw_address(ctx, reg_frm, task); + vepu511a_h265_set_pp_regs(regs, fmt, &ctx->cfg->prep, task); + vepu511a_h265_set_rc_regs(ctx, regs, task); + vepu511a_h265_set_rdo_regs(regs); + vepu511a_h265_set_quant_regs(ctx, regs); + vepu511a_h265_set_sao_regs(ctx, regs); + vepu511a_h265_set_slice_regs(syn, reg_frm); + vepu511a_h265_set_ref_regs(syn, reg_frm); + + ret = vepu511a_h265_set_patch_info(syn, (VepuFmt)fmt->format, ctx->reg_cfg, enc_task); + if (ret) + return ret; + + setup_vepu511a_ext_line_buf(ctx, regs); + vepu511a_h265_set_atf_regs(ctx, regs); + vepu511a_h265_set_anti_stripe_regs(ctx, regs); + vepu511a_h265_set_atr_regs(ctx, regs); + vepu511a_h265_set_smear_regs(ctx, regs); + vepu511a_h265_set_scaling_list(regs); + vepu511a_h265_set_aq(ctx, regs); + vepu511a_h265_set_subj_opt_regs(regs); + + if (ctx->roi_data) + vepu511a_set_roi(®s->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + + /*paramet cfg*/ + vepu511a_h265_global_cfg_set(ctx, regs); + vepu511a_h265e_tune_reg_patch(ctx->tune, task); + + /* two pass register patch */ + if (frm->save_pass1) + vepu511a_h265e_save_pass1_patch(regs, ctx, syn->pp.tiles_enabled_flag); + + if (frm->use_pass1) + vepu511a_h265e_use_pass1_patch(regs, ctx); + + ctx->frame_num++; + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu511a_start(void *hal, HalEncTask *enc_task) +{ + MPP_RET ret = MPP_OK; + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + Vepu511aH265eFrmCfg *frm = ctx->frm; + RK_U32 *regs = (RK_U32*)frm->regs_set; + H265eV511ARegSet *hw_regs = frm->regs_set; + H265eV511AStatusElem *reg_out = (H265eV511AStatusElem *)frm->regs_ret; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + RK_U32 i = 0; + + hal_h265e_enter(); + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + cfg.reg = (RK_U32*)&hw_regs->reg_ctl; + cfg.size = sizeof(Vepu511aControlCfg); + cfg.offset = VEPU511A_CTL_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_CTL_REGS) { + regs = (RK_U32*)&hw_regs->reg_ctl; + for (i = 0; i < sizeof(Vepu511aControlCfg) / 4; i++) { + hal_h265e_dbg_ctl("ctl reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_frm; + cfg.size = sizeof(H265eVepu511aFrame); + cfg.offset = VEPU511A_FRAME_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_REGS) { + regs = (RK_U32*)(&hw_regs->reg_frm); + for (i = 0; i < 32; i++) { + hal_h265e_dbg_regs("hw add cfg reg[%04x]: 0x%08x\n", i * 4, regs[i]); + } + regs += 32; + for (i = 0; i < (sizeof(H265eVepu511aFrame) - 128) / 4; i++) { + hal_h265e_dbg_regs("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + cfg.reg = &hw_regs->reg_rc_roi; + cfg.size = sizeof(Vepu511aRcRoi); + cfg.offset = VEPU511A_RC_ROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_RCKUT_REGS) { + regs = (RK_U32*)&hw_regs->reg_rc_roi; + for (i = 0; i < sizeof(Vepu511aRcRoi) / 4; i++) { + hal_h265e_dbg_rckut("set rc roi reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_param; + cfg.size = sizeof(H265eVepu511aParam); + cfg.offset = VEPU511A_PARAM_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_param; + for (i = 0; i < sizeof(H265eVepu511aParam) / 4; i++) { + hal_h265e_dbg_wgt("set param reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_sqi; + cfg.size = sizeof(H265eVepu511aSqi); + cfg.offset = VEPU511A_SQI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_sqi; + for (i = 0; i < sizeof(H265eVepu511aSqi) / 4; i++) { + hal_h265e_dbg_wgt("set sqi reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_scl; + cfg.size = sizeof(hw_regs->reg_scl); + cfg.offset = VEPU511A_SCL_OFFSET ; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_loge_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_scl; + for (i = 0; i < sizeof(H265eVepu511aSclCfg) / 4; i++) { + hal_h265e_dbg_wgt("set scl reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, ctx->reg_cfg); + if (ret) { + mpp_loge_f("set register offsets failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU511A_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_loge_f("set register read failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->st; + cfg1.size = sizeof(H265eV511AStatusElem) - 4; + cfg1.offset = VEPU511A_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_loge_f("set register read failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_loge_f("send cmd failed %d\n", ret); + } + hal_h265e_leave(); + return ret; +} + +static MPP_RET vepu511a_h265_set_feedback(H265eV511AHalContext *ctx, HalEncTask *enc_task) +{ + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&enc_task->rc_task->info; + Vepu511aH265Fbk *fb = &ctx->frm->feedback; + MppEncCfgSet *cfg = ctx->cfg; + RK_S32 mb8_num = MPP_ALIGN(cfg->prep.width, 8) * MPP_ALIGN(cfg->prep.height, 8) / 64; + RK_S32 mb4_num = (mb8_num << 2); + H265eV511AStatusElem *elem = (H265eV511AStatusElem *)ctx->frm->regs_ret; + RK_U32 hw_status = elem->hw_status; + + hal_h265e_enter(); + + fb->qp_sum += elem->st.qp_sum; + fb->out_strm_size += elem->st.bs_lgth_l32; + fb->sse_sum += (RK_S64)(elem->st.sse_h32 << 16) + + (elem->st.st_sse_bsl.sse_l16 & 0xffff); + + fb->hw_status = hw_status; + hal_h265e_dbg_detail("hw_status: 0x%08x", hw_status); + if (hw_status & RKV_ENC_INT_LINKTABLE_FINISH) + hal_h265e_err("RKV_ENC_INT_LINKTABLE_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_FRAME_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_FRAME_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_SLICE_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_SLICE_FINISH"); + + if (hw_status & RKV_ENC_INT_SAFE_CLEAR_FINISH) + hal_h265e_err("RKV_ENC_INT_SAFE_CLEAR_FINISH"); + + if (hw_status & RKV_ENC_INT_BIT_STREAM_OVERFLOW) + hal_h265e_err("RKV_ENC_INT_BIT_STREAM_OVERFLOW"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_FULL) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_FULL"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_ERROR"); + + if (hw_status & RKV_ENC_INT_BUS_READ_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_READ_ERROR"); + + if (hw_status & RKV_ENC_INT_TIMEOUT_ERROR) + hal_h265e_err("RKV_ENC_INT_TIMEOUT_ERROR"); + + fb->st_mb_num += elem->st.st_bnum_b16.num_b16; + + fb->st_lvl64_inter_num += elem->st.st_pnum_p64.pnum_p64; + fb->st_lvl32_inter_num += elem->st.st_pnum_p32.pnum_p32; + fb->st_lvl32_intra_num += elem->st.st_pnum_i32.pnum_i32; + fb->st_lvl16_inter_num += elem->st.st_pnum_p16.pnum_p16; + fb->st_lvl16_intra_num += elem->st.st_pnum_i16.pnum_i16; + fb->st_lvl8_inter_num += elem->st.st_pnum_p8.pnum_p8; + fb->st_lvl8_intra_num += elem->st.st_pnum_i8.pnum_i8; + fb->st_lvl4_intra_num += elem->st.st_pnum_i4.pnum_i4; + + ctx->feedback.acc_cover16_num = elem->st.st_skin_sum1.num1_point_skin; + ctx->feedback.acc_bndry16_num = elem->st.st_skin_sum2.num2_point_skin; + ctx->feedback.acc_zero_mv = elem->st.st_mv_zero_sum.acc_zero_mv; + ctx->feedback.st_ctu_num = elem->st.st_bnum_b16.num_b16; + memcpy(&fb->st_cu_num_qp[0], &elem->st.st_b8_qp, 52 * sizeof(RK_U32)); + + if (mb4_num > 0) + hal_rc_ret->iblk4_prop = ((((fb->st_lvl4_intra_num + fb->st_lvl8_intra_num) << 2) + + (fb->st_lvl16_intra_num << 4) + + (fb->st_lvl32_intra_num << 6)) << 8) / mb4_num; + + if (mb8_num > 0) { + hal_rc_ret->quality_real = fb->qp_sum / mb8_num; + } + + hal_h265e_leave(); + return MPP_OK; +} + +static MPP_RET hal_h265e_vepu511a_status_check(H265eV511ARegSet *regs) +{ + MPP_RET ret = MPP_OK; + + if (regs->reg_ctl.int_sta.lkt_node_done_sta) + hal_h265e_dbg_detail("lkt_done finish"); + + if (regs->reg_ctl.int_sta.enc_done_sta) + hal_h265e_dbg_detail("enc_done finish"); + + if (regs->reg_ctl.int_sta.vslc_done_sta) + hal_h265e_dbg_detail("enc_slice finsh"); + + if (regs->reg_ctl.int_sta.sclr_done_sta) + hal_h265e_dbg_detail("safe clear finsh"); + + if (regs->reg_ctl.int_sta.vbsf_oflw_sta) { + mpp_loge_f("bit stream overflow"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.vbuf_lens_sta) { + mpp_loge_f("bus write full"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.enc_err_sta) { + mpp_loge_f("bus error"); + ret = MPP_NOK; + } + + if (regs->reg_ctl.int_sta.wdg_sta) { + mpp_loge_f("wdg timeout"); + ret = MPP_NOK; + } + + return ret; +} + +static void vepu511a_h265e_update_tune_stat(H265eV511AHalContext *ctx, HalEncTask *task) +{ + Vepu511aH265Fbk *fb = &ctx->frm->feedback; + H265eV511ARegSet *regs = ctx->frm->regs_set; + Vepu511aRcRoi *s = ®s->reg_rc_roi; + MppEncCfgSet *cfg = ctx->cfg; + Vepu511aStatus *st = &ctx->frm->regs_ret->st; + EncRcTaskInfo *info = (EncRcTaskInfo *)&task->rc_task->info; + RK_U32 b16_num = MPP_ALIGN(cfg->prep.width, 16) * MPP_ALIGN(cfg->prep.height, 16) / 256; + RK_U32 madi_cnt = 0, madp_cnt = 0; + + RK_U32 madi_th_cnt0 = st->st_madi_lt_num0.madi_th_lt_cnt0 + + st->st_madi_rt_num0.madi_th_rt_cnt0 + + st->st_madi_lb_num0.madi_th_lb_cnt0 + + st->st_madi_rb_num0.madi_th_rb_cnt0; + RK_U32 madi_th_cnt1 = st->st_madi_lt_num0.madi_th_lt_cnt1 + + st->st_madi_rt_num0.madi_th_rt_cnt1 + + st->st_madi_lb_num0.madi_th_lb_cnt1 + + st->st_madi_rb_num0.madi_th_rb_cnt1; + RK_U32 madi_th_cnt2 = st->st_madi_lt_num1.madi_th_lt_cnt2 + + st->st_madi_rt_num1.madi_th_rt_cnt2 + + st->st_madi_lb_num1.madi_th_lb_cnt2 + + st->st_madi_rb_num1.madi_th_rb_cnt2; + RK_U32 madi_th_cnt3 = st->st_madi_lt_num1.madi_th_lt_cnt3 + + st->st_madi_rt_num1.madi_th_rt_cnt3 + + st->st_madi_lb_num1.madi_th_lb_cnt3 + + st->st_madi_rb_num1.madi_th_rb_cnt3; + RK_U32 madp_th_cnt0 = st->st_madp_lt_num0.madp_th_lt_cnt0 + + st->st_madp_rt_num0.madp_th_rt_cnt0 + + st->st_madp_lb_num0.madp_th_lb_cnt0 + + st->st_madp_rb_num0.madp_th_rb_cnt0; + RK_U32 madp_th_cnt1 = st->st_madp_lt_num0.madp_th_lt_cnt1 + + st->st_madp_rt_num0.madp_th_rt_cnt1 + + st->st_madp_lb_num0.madp_th_lb_cnt1 + + st->st_madp_rb_num0.madp_th_rb_cnt1; + RK_U32 madp_th_cnt2 = st->st_madp_lt_num1.madp_th_lt_cnt2 + + st->st_madp_rt_num1.madp_th_rt_cnt2 + + st->st_madp_lb_num1.madp_th_lb_cnt2 + + st->st_madp_rb_num1.madp_th_rb_cnt2; + RK_U32 madp_th_cnt3 = st->st_madp_lt_num1.madp_th_lt_cnt3 + + st->st_madp_rt_num1.madp_th_rt_cnt3 + + st->st_madp_lb_num1.madp_th_lb_cnt3 + + st->st_madp_rb_num1.madp_th_rb_cnt3; + + madi_cnt = (6 * madi_th_cnt3 + 5 * madi_th_cnt2 + 4 * madi_th_cnt1) >> 2; + info->complex_level = (madi_cnt * 100 > 30 * b16_num) ? 2 : + (madi_cnt * 100 > 13 * b16_num) ? 1 : 0; + + { + RK_U32 md_cnt = 0, motion_level = 0; + + if (ctx->smart_en) + md_cnt = (12 * madp_th_cnt3 + 11 * madp_th_cnt2 + 8 * madp_th_cnt1) >> 2; + else + md_cnt = (24 * madp_th_cnt3 + 22 * madp_th_cnt2 + 17 * madp_th_cnt1) >> 2; + + if (md_cnt * 100 > 15 * b16_num) + motion_level = 200; + else if (md_cnt * 100 > 5 * b16_num) + motion_level = 100; + else if (md_cnt * 100 > (b16_num >> 2)) + motion_level = 1; + else + motion_level = 0; + info->motion_level = motion_level; + } + hal_h265e_dbg_st("frame %d complex_level %d motion_level %d\n", + ctx->frame_num - 1, info->complex_level, info->motion_level); + + fb->st_madi = madi_th_cnt0 * s->madi_st_thd.madi_th0 + + madi_th_cnt1 * (s->madi_st_thd.madi_th0 + s->madi_st_thd.madi_th1) / 2 + + madi_th_cnt2 * (s->madi_st_thd.madi_th1 + s->madi_st_thd.madi_th2) / 2 + + madi_th_cnt3 * s->madi_st_thd.madi_th2; + + madi_cnt = madi_th_cnt0 + madi_th_cnt1 + madi_th_cnt2 + madi_th_cnt3; + if (madi_cnt) + fb->st_madi = fb->st_madi / madi_cnt; + + fb->st_madp = madp_th_cnt0 * s->madp_st_thd0.madp_th0 + + madp_th_cnt1 * (s->madp_st_thd0.madp_th0 + s->madp_st_thd0.madp_th1) / 2 + + madp_th_cnt2 * (s->madp_st_thd0.madp_th1 + s->madp_st_thd1.madp_th2) / 2 + + madp_th_cnt3 * s->madp_st_thd1.madp_th2; + + madp_cnt = madp_th_cnt0 + madp_th_cnt1 + madp_th_cnt2 + madp_th_cnt3; + if (madp_cnt) + fb->st_madp = fb->st_madp / madp_cnt; + + fb->st_mb_num += st->st_bnum_b16.num_b16; + fb->frame_type = task->rc_task->frm.is_intra ? INTRA_FRAME : INTER_P_FRAME; + info->bit_real = fb->out_strm_size * 8; + info->madi = fb->st_madi; + info->madp = fb->st_madp; + + hal_h265e_dbg_st("frame %d bit_real %d quality_real %d madi %d madp %d\n", + ctx->frame_num - 1, info->bit_real, info->quality_real, info->madi, info->madp); +} + +//#define DUMP_DATA +MPP_RET hal_h265e_vepu511a_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + HalEncTask *enc_task = task; + MppPacket pkt = enc_task->packet; + RK_U32 split_out = ctx->cfg->split.split_out; + H265eV511ARegSet *regs = ctx->frm->regs_set; + RK_U32 offset = mpp_packet_get_length(pkt); + RK_U32 seg_offset = offset; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_U32 type = reg_frm->synt_nal.nal_unit_type; + H265eV511AStatusElem *elem = (H265eV511AStatusElem *)ctx->frm->regs_ret; + + hal_h265e_enter(); + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (enc_task->rc_task->frm.save_pass1) + split_out = 0; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len = 0; + RK_U32 slice_last = 0; + MppDevPollCfg *poll_cfg = (MppDevPollCfg *)((char *)ctx->poll_cfgs); + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + RK_S32 i = 0; + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].vepu511.sli_lst; + slice_len = poll_cfg->slice_info[i].vepu511.sli_len; + param.length = slice_len; + + mpp_packet_add_segment_info(pkt, type, seg_offset, slice_len); + seg_offset += slice_len; + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) { + param.length = slice_len; + if (slice_last) + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + else + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + + mpp_callback(ctx->output_cb, ¶m); + } + } + } while (!slice_last); + + ret = hal_h265e_vepu511a_status_check(regs); + if (!ret) + task->hw_length += elem->st.bs_lgth_l32; + + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_loge_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + ret = hal_h265e_vepu511a_status_check(regs); + if (!ret) + task->hw_length += elem->st.bs_lgth_l32; + } + mpp_packet_add_segment_info(pkt, type, offset, elem->st.bs_lgth_l32); + } + +#ifdef DUMP_DATA + vepu511a_h265e_dump(ctx, task); +#endif + + if (ret) + mpp_loge_f("poll cmd failed %d status %d \n", ret, elem->hw_status); + + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_vepu511a_get_task(void *hal, HalEncTask *task) +{ + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + MppFrame frame = task->frame; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h265e_enter(); + + ctx->syn = (H265eSyntax_new *)task->syntax.data; + ctx->dpb = (H265eDpb*)ctx->syn->dpb; + ctx->smart_en = (ctx->cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC); + ctx->qpmap_en = ctx->cfg->tune.deblur_en; + + if (!task->rc_task->frm.reencode) { + if (vepu511a_h265_setup_hal_bufs(ctx)) { + hal_h265e_err("vepu541_h265_allocate_buffers failed, free buffers and return\n"); + task->flags.err |= HAL_ENC_TASK_ERR_ALLOC; + return MPP_ERR_MALLOC; + } + ctx->last_frame_fb = ctx->feedback; + } + + ctx->last_frame_type = ctx->frame_type; + + if (frm_status->is_intra) { + ctx->frame_type = INTRA_FRAME; + } else { + ctx->frame_type = INTER_P_FRAME; + } + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + // mpp_meta_get_ptr_d(meta, KEY_OSD_DATA3, (void **)&ctx->osd_cfg.osd_data3, NULL); + } + + ctx->frm->frame_count = ++ctx->frame_count; + task->part_first = 1; + task->part_last = 0; + + ctx->frm->hal_curr_idx = ctx->syn->sp.recon_pic.slot_idx; + ctx->frm->hal_refr_idx = ctx->syn->sp.ref_pic.slot_idx; + + h265e_dpb_hal_start(ctx->dpb, ctx->frm->hal_curr_idx); + h265e_dpb_hal_start(ctx->dpb, ctx->frm->hal_refr_idx); + + memset(&ctx->frm->feedback, 0, sizeof(Vepu511aH265Fbk)); + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_vepu511a_ret_task(void *hal, HalEncTask *task) +{ + H265eV511AHalContext *ctx = (H265eV511AHalContext *)hal; + HalEncTask *enc_task = task; + Vepu511aH265Fbk *fb = &ctx->frm->feedback; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + + hal_h265e_enter(); + + vepu511a_h265_set_feedback(ctx, enc_task); + mpp_buffer_sync_partial_begin(enc_task->output, offset, fb->out_strm_size); + hal_h265e_amend_temporal_id(task, fb->out_strm_size); + + rc_info->sse = fb->sse_sum; + rc_info->lvl64_inter_num = fb->st_lvl64_inter_num; + rc_info->lvl32_inter_num = fb->st_lvl32_inter_num; + rc_info->lvl16_inter_num = fb->st_lvl16_inter_num; + rc_info->lvl8_inter_num = fb->st_lvl8_inter_num; + rc_info->lvl32_intra_num = fb->st_lvl32_intra_num; + rc_info->lvl16_intra_num = fb->st_lvl16_intra_num; + rc_info->lvl8_intra_num = fb->st_lvl8_intra_num; + rc_info->lvl4_intra_num = fb->st_lvl4_intra_num; + + enc_task->hw_length = fb->out_strm_size; + enc_task->length += fb->out_strm_size; + + h265e_dpb_hal_end(ctx->dpb, ctx->frm->hal_curr_idx); + h265e_dpb_hal_end(ctx->dpb, ctx->frm->hal_refr_idx); + + vepu511a_h265e_update_tune_stat(ctx, enc_task); + + hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); + hal_h265e_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_h265e_vepu511a = { + .name = "hal_h265e_v511a", + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(H265eV511AHalContext), + .flag = 0, + .init = hal_h265e_vepu511a_init, + .deinit = hal_h265e_vepu511a_deinit, + .prepare = hal_h265e_vepu511a_prepare, + .get_task = hal_h265e_vepu511a_get_task, + .gen_regs = hal_h265e_vepu511a_gen_regs, + .start = hal_h265e_vepu511a_start, + .wait = hal_h265e_vepu511a_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h265e_vepu511a_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h265e_vepu511a) diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu511a_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu511a_reg.h new file mode 100644 index 000000000..b97730ff4 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu511a_reg.h @@ -0,0 +1,1127 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_H265E_VEPU511A_REG_H +#define HAL_H265E_VEPU511A_REG_H + +#include "rk_type.h" +#include "vepu511a_common.h" + +typedef struct PreCstPar_t { + union { + RK_U8 cst_madi_thd[14]; + + struct { + /* 0x00002120 reg2120 - 0x00002140 reg2128 */ + struct { + RK_U32 madi_thd0 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd1 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd2 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd3 : 7; + RK_U32 reserved3 : 1; + } cst_madi_thd0; + + /* 0x00002124 reg2121 */ + struct { + RK_U32 madi_thd4 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd5 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd6 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd7 : 7; + RK_U32 reserved3 : 1; + } cst_madi_thd1; + + /* 0x00002128 reg2122 */ + struct { + RK_U32 madi_thd8 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd9 : 7; + RK_U32 reserved1 : 1; + RK_U32 madi_thd10 : 7; + RK_U32 reserved2 : 1; + RK_U32 madi_thd11 : 7; + RK_U32 reserved3 : 1; + } cst_madi_thd2; + + /* 0x0000212c reg2123 */ + struct { + RK_U32 madi_thd12 : 7; + RK_U32 reserved : 1; + RK_U32 madi_thd13 : 7; + RK_U32 reserved1 : 1; + RK_U32 mode_th : 3; + RK_U32 reserved2 : 1; + RK_U32 qp_thd : 6; + RK_U32 reserved3 : 6; + } cst_madi_thd3; + }; + }; + + union { + RK_U8 cst_wgt[15]; + + struct { + /* 0x00002130 reg2124 */ + struct { + RK_U32 wgt0 : 8; + RK_U32 wgt1 : 8; + RK_U32 wgt2 : 8; + RK_U32 wgt3 : 8; + } cst_wgt0; + + /* 0x00002134 reg2125 */ + struct { + RK_U32 wgt4 : 8; + RK_U32 wgt5 : 8; + RK_U32 wgt6 : 8; + RK_U32 wgt7 : 8; + } cst_wgt1; + + /* 0x00002138 reg2126 */ + struct { + RK_U32 wgt8 : 8; + RK_U32 wgt9 : 8; + RK_U32 wgt10 : 8; + RK_U32 wgt11 : 8; + } cst_wgt2; + + /* 0x0000213c reg2127 */ + struct { + RK_U32 wgt12 : 8; + RK_U32 wgt13 : 8; + RK_U32 wgt14 : 8; + RK_U32 lambda_mv_bit_0 : 3; + RK_U32 reserved : 1; + RK_U32 lambda_mv_bit_1 : 3; + RK_U32 anti_strp_e : 1; + } cst_wgt3; + }; + }; +} pre_cst_par; + +/* class: buffer/video syntax */ +/* 0x00000270 reg156 - 0x00000538 reg334 */ +typedef struct H265eVepu511aFrame_t { + /* 0x00000270 reg156 - 0x0000039c reg231 */ + Vepu511aFrmCommon common; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 ltm_col : 1; + RK_U32 ltm_idx0l0 : 1; + RK_U32 reserved1 : 1; + RK_U32 pu8_inter_interpolation_num_big_lvl : 3; + RK_U32 pu16_inter_interpolation_num_big_lvl : 3; + RK_U32 pu32_inter_interpolation_num_big_lvl : 3; + RK_U32 pu64_inter_interpolation_num_big_lvl : 3; + RK_U32 reserved2 : 1; + RK_U32 cu32_split_lambda_qp_sel : 3; + RK_U32 reserved3 : 4; + RK_U32 ccwa_e : 1; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved4 : 2; + RK_U32 atf_e : 1; + RK_U32 atr_e : 1; + RK_U32 reserved5 : 2; + } rdo_cfg; + + struct { + RK_U32 pu32_intra_mode_num_big_lvl : 2; + RK_U32 pu16_intra_mode_num_big_lvl : 2; + RK_U32 pu8_intra_mode_num_big_lvl : 2; + RK_U32 pu4_intra_mode_num : 2; + RK_U32 pu32_intra_mode_num_small_lvl : 2; + RK_U32 pu16_intra_mode_num_small_lvl : 2; + RK_U32 pu8_intra_mode_num_small_lvl : 2; + RK_U32 reserved1 : 2; + RK_U32 pu8_inter_interpolation_num_small_lvl : 3; + RK_U32 pu16_inter_interpolation_num_small_lvl : 3; + RK_U32 pu32_inter_interpolation_num_small_lvl : 3; + RK_U32 pu64_inter_interpolation_num_small_lvl : 3; + RK_U32 reserved2 : 4; + } rdo_intra_mode; + + /* 0x000003a8 reg234 */ + struct { + RK_U32 rdoqx_pixel_e : 1; + RK_U32 rdoqx_cgzero_e : 1; + RK_U32 rdoqx_lastxy_e : 1; + RK_U32 rdoq4_rdoq_e : 1; + RK_U32 reserved : 4; + RK_U32 rdoq_intra_r_coef : 5; + RK_U32 reserved1 : 19; + } rdoq_cfg_hevc; + + /* 0x3ac */ + RK_U32 reserved_235; + + /* 0x000003b0 reg236 */ + struct { + RK_U32 nal_unit_type : 6; + RK_U32 reserved : 26; + } synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 smpl_adpt_ofst_e : 1; + RK_U32 num_st_ref_pic : 7; + RK_U32 lt_ref_pic_prsnt : 1; + RK_U32 num_lt_ref_pic : 6; + RK_U32 tmpl_mvp_e : 1; + RK_U32 log2_max_poc_lsb : 4; + RK_U32 strg_intra_smth : 1; + RK_U32 reserved : 11; + } synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 dpdnt_sli_seg_en : 1; + RK_U32 out_flg_prsnt_flg : 1; + RK_U32 num_extr_sli_hdr : 3; + RK_U32 sgn_dat_hid_en : 1; + RK_U32 cbc_init_prsnt_flg : 1; + RK_U32 pic_init_qp : 6; + RK_U32 cu_qp_dlt_en : 1; + RK_U32 chrm_qp_ofst_prsn : 1; + RK_U32 lp_fltr_acrs_sli : 1; + RK_U32 dblk_fltr_ovrd_en : 1; + RK_U32 lst_mdfy_prsnt_flg : 1; + RK_U32 sli_seg_hdr_extn : 1; + RK_U32 cu_qp_dlt_depth : 2; + RK_U32 lpf_fltr_acrs_til : 1; + RK_U32 csip_flag : 1; + RK_U32 reserved : 9; + } synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 mrg_up_flg : 1; + RK_U32 mrg_lft_flg : 1; + RK_U32 reserved : 1; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_l1_act : 2; + RK_U32 num_refidx_l0_act : 2; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_e : 1; + RK_U32 pic_out_flg : 1; + RK_U32 sli_type : 2; + RK_U32 sli_rsrv_flg : 7; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 sli_pps_id : 6; + RK_U32 no_out_pri_pic : 1; + } synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 sp_tc_ofst_div2 : 4; + RK_U32 sp_beta_ofst_div2 : 4; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sp_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_U32 sli_cb_qp_ofst : 5; + RK_U32 sli_qp : 6; + RK_U32 max_mrg_cnd : 2; + RK_U32 reserved : 1; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 lst_entry_l0 : 4; + RK_U32 reserved1 : 1; + } synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 sli_poc_lsb : 16; + RK_U32 sli_hdr_ext_len : 9; + RK_U32 reserved : 7; + } synt_sli2; + + /* 0x000003c8 reg242 */ + struct { + RK_U32 st_ref_pic_flg : 1; + RK_U32 poc_lsb_lt0 : 16; + RK_U32 lt_idx_sps : 5; + RK_U32 num_lt_pic : 2; + RK_U32 st_ref_pic_idx : 6; + RK_U32 num_lt_sps : 2; + } synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 used_by_s0_flg : 4; + RK_U32 num_pos_pic : 1; + RK_U32 num_negative_pics : 5; + RK_U32 dlt_poc_msb_cycl0 : 16; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + } synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 dlt_poc_s0_m10 : 16; + RK_U32 dlt_poc_s0_m11 : 16; + } synt_refm2; + + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } synt_refm3; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } synt_long_refm0; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } synt_long_refm1; + + /* 0x000003e0 reg248 */ + struct { + RK_U32 sao_lambda_multi : 3; + RK_U32 reserved : 29; + } sao_cfg; + + /* 0x3e4 - 0x3ec */ + RK_U32 reserved249_251[3]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 tile_w_m1 : 9; + RK_U32 reserved : 7; + RK_U32 tile_h_m1 : 9; + RK_U32 reserved1 : 6; + RK_U32 tile_en : 1; + } tile_cfg; + + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 9; + RK_U32 reserved : 7; + RK_U32 tile_y : 9; + RK_U32 reserved1 : 7; + } tile_pos_hevc; + + /* 0x000003f8 reg254 */ + struct { + RK_U32 slice_sta_x : 9; + RK_U32 reserved1 : 7; + RK_U32 slice_sta_y : 10; + RK_U32 reserved2 : 5; + RK_U32 slice_enc_ena : 1; + } slice_enc_cfg0; + + /* 0x000003fc reg255 */ + struct { + RK_U32 slice_end_x : 9; + RK_U32 reserved : 7; + RK_U32 slice_end_y : 10; + RK_U32 reserved1 : 6; + } slice_enc_cfg1; + + /* 0x400 reg256 - 0x51c reg327*/ + RK_U32 reserved256_327[72]; + + /* 0x00000520 reg328 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_md : 28; + } adr_md_vpp; + + /* 0x00000524 reg329 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_od : 28; + } adr_od_vpp; + + /* 0x00000528 reg330 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_ref_mdw : 28; + } adr_ref_mdw; + + /* 0x0000052c reg331 */ + struct { + RK_U32 reserved : 4; + RK_U32 base_addr_ref_mdr : 28; + } adr_ref_mdr; + + /* 0x00000530 reg332 */ + struct { + RK_U32 sto_stride_md : 8; + RK_U32 sto_stride_od : 8; + RK_U32 cur_frm_en_md : 1; + RK_U32 ref_frm_en_md : 1; + RK_U32 switch_sad_md : 2; + RK_U32 night_mode_en_md : 1; + RK_U32 flycatkin_flt_en_md : 1; + RK_U32 en_od : 1; + RK_U32 background_en_od : 1; + RK_U32 sad_comp_en_od : 1; + RK_U32 reserved : 6; + RK_U32 vepu_pp_en : 1; + } vpp_base_cfg; + + /* 0x00000534 reg333 */ + struct { + RK_U32 thres_sad_md : 12; + RK_U32 thres_move_md : 3; + RK_U32 reserved : 1; + RK_U32 thres_dust_move_md : 4; + RK_U32 thres_dust_blk_md : 3; + RK_U32 reserved1 : 1; + RK_U32 thres_dust_chng_md : 8; + } thd_md_vpp; + + /* 0x00000538 reg334 */ + struct { + RK_U32 thres_complex_od : 12; + RK_U32 thres_complex_cnt_od : 3; + RK_U32 thres_sad_od : 14; + RK_U32 reserved : 3; + } thd_od_vpp; +} H265eVepu511aFrame; + +/* class: param */ +/* 0x00001700 reg1472 - 0x000019cc reg1651*/ +typedef struct H265eVepu511aParam_t { + /* 0x00001700 reg1472 - 0x0000172c reg1483*/ + RK_U32 reserved_1472_1483[12]; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 bias_madi_th0 : 8; + RK_U32 bias_madi_th1 : 8; + RK_U32 bias_madi_th2 : 8; + RK_U32 reserved : 8; + } bias_madi_thd_comb; + + /* 0x00001734 reg1485 */ + struct { + RK_U32 bias_i_val0 : 10; + RK_U32 bias_i_val1 : 10; + RK_U32 bias_i_val2 : 10; + RK_U32 reserved : 2; + } qnt0_i_bias_comb; + + /* 0x00001738 reg1486 */ + struct { + RK_U32 bias_i_val3 : 10; + RK_U32 reserved : 22; + } qnt1_i_bias_comb; + + /* 0x0000173c reg1487 */ + struct { + RK_U32 bias_p_val0 : 10; + RK_U32 bias_p_val1 : 10; + RK_U32 bias_p_val2 : 10; + RK_U32 reserved : 2; + } qnt0_p_bias_comb; + + /* 0x00001740 reg1488 */ + struct { + RK_U32 bias_p_val3 : 10; + RK_U32 reserved : 22; + } qnt1_p_bias_comb; + + /* 0x00001744 reg1489 */ + struct { + RK_U32 light_change_en : 1; + RK_U32 light_ratio_mult1 : 5; + RK_U32 light_ratio_mult2 : 4; + RK_U32 light_thre_csu1_cnt : 2; + RK_U32 srch_rgn_en : 1; + RK_U32 srch_rgn_mode_light : 1; + RK_U32 reserved1 : 2; + RK_U32 light_thre_madp : 8; + RK_U32 light_thre_lightmadp : 8; + } light_cfg_comb; + + /* 0x1748 reg1490 */ + struct { + RK_U32 light_change_zero_mv_j_coef : 5; + RK_U32 reserved1 : 27; + } light_wgt_hevc; + + /* 0x174c - 0x175c */ + RK_U32 reserved1491_1495[5]; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 reserved1 : 2; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 fme_lvl_mrg : 1; + RK_U32 thre_zero_srgn : 5; + RK_U32 reserved2 : 11; + } me_sqi_comb; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th_comb; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 ratio_consi_cfg : 4; + RK_U32 ratio_bmv_dist : 4; + RK_U32 reserved : 12; + } cime_madp_th_comb; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi_comb; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th_comb; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th_comb; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi_comb; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th_comb; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 reg1536 - 0x000018cc reg1587*/ + RK_U32 pprd_lamb_satd_0_51[52]; + + /* 0x000018d0 reg1588 */ + struct { + RK_U32 lambda_luma_offset : 5; + RK_U32 lambda_chroma_offset : 5; + RK_U32 reserved : 22; + } prmd_intra_lamb_ofst; + + /* 0x18d4 - 0x18fc */ + RK_U32 reserved1589_1599[11]; + + /* 0x00001900 reg1600 - 0x000019cc reg1651*/ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} H265eVepu511aParam; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x00002160 reg2136 */ +typedef struct H265eVepu511aSqiCfg_t { + /* 0x00002000 reg2048 */ + struct { + RK_U32 subj_opt_en : 1; + RK_U32 reserved1 : 3; + RK_U32 aq_subj_en : 1; + RK_U32 reserved2 : 3; + RK_U32 bndry_cmplx_static_choose_en : 2; + RK_U32 feature_cal_en : 1; + RK_U32 reserved3 : 1; + RK_U32 thre_sum_grdn_point : 20; + } subj_opt_cfg; + + /* 0x00002004 reg2049 */ + struct { + RK_U32 common_thre_num_grdn_point_dep0 : 8; + RK_U32 common_thre_num_grdn_point_dep1 : 8; + RK_U32 common_thre_num_grdn_point_dep2 : 8; + RK_U32 reserved : 8; + } subj_opt_dpth_thd; + + /* 0x00002008 reg2050 */ + struct { + RK_U32 cover_rdo_mode_intra_jcoef_d0 : 6; + RK_U32 cover_rdo_mode_intra_jcoef_d1 : 6; + RK_U32 cover_rmd_mode_intra_jcoef_d0 : 6; + RK_U32 cover_rmd_mode_intra_jcoef_d1 : 6; + RK_U32 cover_rdoq_rcoef_d0 : 4; + RK_U32 cover_rdoq_rcoef_d1 : 4; + } subj_opt_inrar_coef; + + /* 0x0000200c reg2051 */ + struct { + RK_U32 cfc_rmd_mode_intra_jcoef_d0 : 6; + RK_U32 cfc_rmd_mode_intra_jcoef_d1 : 6; + RK_U32 cfc_rdo_mode_intra_jcoef_d0 : 6; + RK_U32 cfc_rdo_mode_intra_jcoef_d1 : 6; + RK_U32 cfc_rdoq_rcoef_d0 : 4; + RK_U32 cfc_rdoq_rcoef_d1 : 4; + } smear_opt_cfc_coef; + + /* 0x00002010 reg2052 */ + struct { + RK_U32 anti_smear_en : 1; + RK_U32 frm_static : 1; + RK_U32 smear_stor_en : 1; + RK_U32 smear_load_en : 1; + RK_U32 smear_strength : 3; + RK_U32 reserved : 1; + RK_U32 thre_mv_inconfor_cime : 4; + RK_U32 thre_mv_confor_cime : 2; + RK_U32 thre_mv_confor_cime_gmv : 2; + RK_U32 thre_mv_inconfor_cime_gmv : 4; + RK_U32 thre_num_mv_confor_cime : 2; + RK_U32 thre_num_mv_confor_cime_gmv : 2; + RK_U32 ref1_subj_opt_en : 1; + RK_U32 smear_cfc_en : 1; + RK_U32 reserved1 : 6; + } smear_opt_cfg0; + + /* 0x00002014 reg2053 */ + struct { + RK_U32 dist0_frm_avg : 14; + RK_U32 thre_dsp_static : 5; + RK_U32 thre_dsp_mov : 5; + RK_U32 thre_dist_mv_confor_cime : 7; + RK_U32 reserved : 1; + } smear_opt_cfg1; + + /* 0x00002018 reg2054 */ + struct { + RK_U32 thre_madp_stc_dep0 : 4; + RK_U32 thre_madp_stc_dep1 : 4; + RK_U32 thre_madp_stc_dep2 : 4; + RK_U32 thre_madp_mov_dep0 : 6; + RK_U32 thre_madp_mov_dep1 : 6; + RK_U32 thre_madp_mov_dep2 : 6; + RK_U32 reserved : 2; + } smear_madp_thd; + + /* 0x0000201c reg2055 */ + struct { + RK_U32 thre_num_pt_stc_dep0 : 6; + RK_U32 thre_num_pt_stc_dep1 : 4; + RK_U32 thre_num_pt_stc_dep2 : 2; + RK_U32 reserved : 4; + RK_U32 thre_num_pt_mov_dep0 : 6; + RK_U32 thre_num_pt_mov_dep1 : 4; + RK_U32 thre_num_pt_mov_dep2 : 2; + RK_U32 reserved1 : 4; + } smear_stat_thd; + + /* 0x00002020 reg2056 */ + struct { + RK_U32 confor_cime_gmv0 : 5; + RK_U32 reserved : 3; + RK_U32 confor_cime_gmv1 : 5; + RK_U32 reserved1 : 3; + RK_U32 inconfor_cime_gmv0 : 6; + RK_U32 reserved2 : 2; + RK_U32 inconfor_cime_gmv1 : 6; + RK_U32 reserved3 : 2; + } smear_bmv_dist_thd0; + + /* 0x00002024 reg2057 */ + struct { + RK_U32 inconfor_cime_gmv2 : 6; + RK_U32 reserved : 2; + RK_U32 inconfor_cime_gmv3 : 6; + RK_U32 reserved1 : 2; + RK_U32 inconfor_cime_gmv4 : 6; + RK_U32 reserved2 : 10; + } smear_bmv_dist_thd1; + + /* 0x00002028 reg2058 */ + struct { + RK_U32 thre_min_num_confor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_max_num_confor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_min_num_inconfor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_max_num_inconfor_csu0_bndry_cime_gmv : 2; + RK_U32 thre_split_dep0 : 2; + RK_U32 reserved1 : 6; + RK_U32 madi_thre_dep0 : 8; + RK_U32 madi_thre_dep1 : 8; + } smear_min_bndry_gmv; + + /* 0x0000202c reg2059 */ + struct { + RK_U32 thre_madp_stc_cover0 : 6; + RK_U32 thre_madp_stc_cover1 : 6; + RK_U32 thre_madp_mov_cover0 : 5; + RK_U32 thre_madp_mov_cover1 : 5; + RK_U32 smear_qp_strength : 4; + RK_U32 smear_thre_qp : 6; + } smear_madp_cov_thd; + + /* 0x00002030 reg2060 */ + struct { + RK_U32 skin_en : 1; + RK_U32 skin_strength : 3; + RK_U32 thre_uvsqr16_skin : 8; + RK_U32 skin_thre_cst_best_mad : 10; + RK_U32 skin_thre_cst_best_grdn_blk : 7; + RK_U32 reserved : 1; + RK_U32 frame_skin_ratio : 2; + } skin_opt_cfg; + + /* 0x00002034 reg2061 */ + struct { + RK_U32 thre_sum_mad_intra : 2; + RK_U32 thre_sum_grdn_blk_intra : 2; + RK_U32 vld_thre_skin_v : 3; + RK_U32 reserved : 1; + RK_U32 thre_min_skin_u : 8; + RK_U32 thre_max_skin_u : 8; + RK_U32 thre_min_skin_v : 8; + } skin_chrm_thd; + + /* 0x00002038 reg2062 */ + struct { + RK_U32 block_en : 1; + RK_U32 reserved : 1; + RK_U32 block_thre_cst_best_mad : 10; + RK_U32 reserved1 : 4; + RK_U32 block_thre_cst_best_grdn_blk : 6; + RK_U32 reserved2 : 2; + RK_U32 thre_num_grdnt_point_cmplx : 2; + RK_U32 block_delta_qp_flag : 2; + RK_U32 reserved3 : 4; + } block_opt_cfg; + + /* 0x0000203c reg2063 */ + struct { + RK_U32 cmplx_thre_cst_best_mad_dep0 : 13; + RK_U32 reserved : 3; + RK_U32 cmplx_thre_cst_best_mad_dep1 : 13; + RK_U32 reserved1 : 2; + RK_U32 cmplx_en : 1; + } cmplx_opt_cfg; + + /* 0x00002040 reg2064 */ + struct { + RK_U32 cmplx_thre_cst_best_mad_dep2 : 13; + RK_U32 reserved : 3; + RK_U32 cmplx_thre_cst_best_grdn_blk_dep0 : 11; + RK_U32 reserved1 : 5; + } cmplx_bst_mad_thd; + + /* 0x00002044 reg2065 */ + struct { + RK_U32 cmplx_thre_cst_best_grdn_blk_dep1 : 11; + RK_U32 reserved : 5; + RK_U32 cmplx_thre_cst_best_grdn_blk_dep2 : 11; + RK_U32 reserved1 : 5; + } cmplx_bst_grdn_thd; + + /* 0x00002048 reg2066 */ + struct { + RK_U32 line_en : 1; + RK_U32 line_thre_min_cst_best_grdn_blk_dep0 : 5; + RK_U32 line_thre_min_cst_best_grdn_blk_dep1 : 8; + RK_U32 line_thre_min_cst_best_grdn_blk_dep2 : 8; + RK_U32 line_thre_ratio_best_grdn_blk_dep0 : 4; + RK_U32 line_thre_ratio_best_grdn_blk_dep1 : 4; + RK_U32 reserved : 2; + } line_opt_cfg; + + /* 0x0000204c reg2067 */ + struct { + RK_U32 line_thre_max_cst_best_grdn_blk_dep0 : 7; + RK_U32 reserved : 1; + RK_U32 line_thre_max_cst_best_grdn_blk_dep1 : 8; + RK_U32 line_thre_max_cst_best_grdn_blk_dep2 : 8; + RK_U32 reserved1 : 8; + } line_cst_bst_grdn; + + /* 0x00002050 reg2068 */ + struct { + RK_U32 line_thre_qp : 6; + RK_U32 block_strength : 3; + RK_U32 block_thre_qp : 6; + RK_U32 cmplx_strength : 3; + RK_U32 cmplx_thre_qp : 6; + RK_U32 cmplx_thre_max_grdn_blk : 6; + RK_U32 reserved : 2; + } subj_opt_dqp0; + + /* 0x00002054 reg2069 */ + struct { + RK_U32 skin_thre_qp : 6; + RK_U32 smear_frame_thre_qp : 6; + RK_U32 bndry_rdo_mode_intra_jcoef_d0 : 6; + RK_U32 bndry_rdo_mode_intra_jcoef_d1 : 6; + RK_U32 skin_thre_madp : 8; + } subj_opt_dqp1; + + /* 0x00002058 reg2070 */ + struct { + RK_U32 line_rdo_split_rcoef_d0 : 5; + RK_U32 line_rdo_split_rcoef_d1 : 5; + RK_U32 choose_cu32_split_jcoef : 6; + RK_U32 choose_cu16_split_jcoef : 5; + RK_U32 reserved : 11; + } subj_opt_rdo_split; + + /* 0x0000205c reg2071 */ + struct { + RK_U32 lid_grdn_blk_cu16_th : 8; + RK_U32 lid_rmd_intra_jcoef_ang : 5; + RK_U32 lid_rdo_intra_rcoef_ang : 5; + RK_U32 lid_rmd_intra_jcoef_dp : 6; + RK_U32 lid_rdo_intra_rcoef_dp : 6; + RK_U32 lid_en : 1; + RK_U32 reserved : 1; + } line_intra_dir_cfg; + + /* 0x00002060 reg2072 - 0x0000206c reg 2076*/ + rdo_b32_skip_par rdo_b32_skip; + + /* 0x00002070 reg2076 - 0x0000207c reg2079*/ + rdo_skip_par rdo_b16_skip; + + /* 0x00002080 reg2080 - 0x00002088 reg2082 */ + rdo_b32_noskip_par rdo_b32_inter; + + /* 0x0000208c reg2083 - 0x00002094 reg2085 */ + rdo_noskip_par rdo_b16_inter; + + /* 0x00002098 reg2086 - 0x000020a0 reg2087 */ + rdo_noskip_par rdo_b32_intra; + + /* 0x000020a4 reg2088 - 0x000020ac reg2091 */ + rdo_noskip_par rdo_b16_intra; + + /* 0x000020b0 reg2092 */ + struct { + RK_U32 ref1_rmd_mode_lr_jcoef_d0 : 5; + RK_U32 ref1_rmd_mode_lr_jcoef_d1 : 5; + RK_U32 ref1_rdo_mode_lr_jcoef_d0 : 5; + RK_U32 ref1_rdo_mode_lr_jcoef_d1 : 5; + RK_U32 ref1_rmd_mv_lr_jcoef_d0 : 5; + RK_U32 ref1_rmd_mv_lr_jcoef_d1 : 5; + RK_U32 reserved : 2; + } smear_ref1_cfg0; + + /* 0x000020b4 reg2093 */ + struct { + RK_U32 ref1_rdo_inter_tu_res_joef_d0 : 5; + RK_U32 ref1_rdo_inter_tu_res_joef_d1 : 5; + RK_U32 ref1_rdoq_zero_mv_rcoef_d0 : 5; + RK_U32 ref1_rdoq_zero_mv_rcoef_d1 : 5; + RK_U32 ref1_rmd_inter_lr_jcoef_d0 : 5; + RK_U32 ref1_rmd_inter_lr_jcoef_d1 : 5; + RK_U32 reserved : 2; + } smear_ref1_cfg1; + + /* 0x000020b8 reg2094 - 0x000020bc reg2095*/ + RK_U32 reserved_2094_2095[2]; + + /* 0x000020c0 reg2096 */ + struct { + RK_U32 thre_max_luma_dark : 8; + RK_U32 thre_min_luma_bright : 8; + RK_U32 thre_ratio_dark_bright : 6; + RK_U32 reserved : 2; + RK_U32 thre_qp_dark_bright : 6; + RK_U32 reserved1 : 1; + RK_U32 dark_bright_en : 1; + } dark_brgt_opt_cfg; + + /* 0x000020c4 reg2097 */ + struct { + RK_U32 madp_th_dep0_dark_bright : 8; + RK_U32 madp_th_dep1_dark_bright : 8; + RK_U32 madi_th_dep0_dark_bright : 6; + RK_U32 reserved : 2; + RK_U32 madi_th_dep1_dark_bright : 6; + RK_U32 reserved1 : 2; + } dark_brgt_madi_thd; + + /* 0x000020c8 reg2098 */ + struct { + RK_U32 dark_bright_inter_res_j_coef_wgt_dep0 : 8; + RK_U32 dark_bright_inter_res_j_coef_wgt_dep1 : 8; + RK_U32 dark_bright_intra_j_coef_wgt_dep0 : 8; + RK_U32 dark_bright_intra_j_coef_wgt_dep1 : 8; + } dark_brgt_wgt0; + + /* 0x000020cc reg2099 */ + struct { + RK_U32 dark_bright_split_rcoef_d0 : 6; + RK_U32 reserved : 2; + RK_U32 dark_bright_split_rcoef_d1 : 6; + RK_U32 reserved1 : 18; + } dark_brgt_wgt1; + + /* 0x000020d0 reg2100 */ + struct { + RK_U32 cmplx_static_en : 1; + RK_U32 cmplx_static_lgt_chng_en : 1; + RK_U32 thre_qp_cmplx_static : 6; + RK_U32 madp_th0_dep0_cmplx_static : 6; + RK_U32 madp_th1_dep0_cmplx_static : 8; + RK_U32 madp_th2_dep0_cmplx_static : 10; + } cmplx_statc_cfg; + + /* 0x000020d4 reg2101 */ + struct { + RK_U32 num_grdn_point_th1_dep0_cmplx_static : 8; + RK_U32 num_grdn_point_th2_dep0_cmplx_static : 8; + RK_U32 madi_th1_dep0_cmplx_static : 6; + RK_U32 reserved : 2; + RK_U32 madi_th2_dep0_cmplx_static : 6; + RK_U32 reserved1 : 2; + } cmplx_statc_thd0; + + /* 0x000020d8 reg2102 */ + struct { + RK_U32 madp_th0_dep1_cmplx_static : 6; + RK_U32 madp_th1_dep1_cmplx_static : 8; + RK_U32 madp_th2_dep1_cmplx_static : 10; + RK_U32 static_num_thre_dep1_cmplx_static : 2; + RK_U32 srch_rgn_mv_th_cmplx_static : 5; + RK_U32 reserved : 1; + } cmplx_statc_thd1; + + /* 0x000020dc reg2103 */ + struct { + RK_U32 num_grdn_point_th1_dep1_cmplx_static : 6; + RK_U32 num_grdn_point_th2_dep1_cmplx_static : 6; + RK_U32 madi_th1_dep1_cmplx_static : 6; + RK_U32 madi_th2_dep1_cmplx_static : 6; + RK_U32 num_cu16_th : 3; + RK_U32 frame_qp_en : 1; + RK_U32 ratio_light_madp_th : 2; + RK_U32 reserved : 2; + } cmplx_statc_thd2; + + /* 0x000020e0 reg2104 */ + struct { + RK_U32 inter_res_j_coef_wgt1_dep0 : 8; + RK_U32 inter_res_j_coef_wgt2_dep0 : 8; + RK_U32 inter_res_j_coef_wgt1_dep1 : 8; + RK_U32 inter_res_j_coef_wgt2_dep1 : 8; + } cmplx_statc_wgt0; + + /* 0x000020e4 reg2105 */ + struct { + RK_U32 intra_j_coef_wgt1_dep0 : 8; + RK_U32 intra_j_coef_wgt2_dep0 : 8; + RK_U32 intra_j_coef_wgt1_dep1 : 8; + RK_U32 intra_j_coef_wgt2_dep1 : 8; + } cmplx_statc_wgt1; + + /* 0x000020e8 reg2106 */ + struct { + RK_U32 split_rcoef_w1d0 : 6; + RK_U32 split_rcoef_w1d1 : 6; + RK_U32 split_rcoef_w2d0 : 6; + RK_U32 split_rcoef_w2d1 : 6; + RK_U32 reserved : 8; + } cmplx_statc_wgt2; + + /* 0x20ec - 0x20fc */ + RK_U32 reserved2107_2111[5]; + + /* 0x00002100 reg2112 */ + struct { + RK_U32 blur_low_madi_thd : 7; + RK_U32 reserved : 1; + RK_U32 blur_high_madi_thd : 7; + RK_U32 reserved1 : 1; + RK_U32 blur_low_cnt_thd : 4; + RK_U32 blur_hight_cnt_thd : 4; + RK_U32 blur_sum_cnt_thd : 4; + RK_U32 anti_blur_en : 1; + RK_U32 scene_mode : 1; + RK_U32 reserved2 : 2; + } subj_anti_blur_thd; + + /* 0x00002104 reg2113 */ + struct { + RK_U32 blur_motion_thd : 12; + RK_U32 sao_ofst_thd_eo_luma : 3; + RK_U32 reserved : 1; + RK_U32 sao_ofst_thd_bo_luma : 3; + RK_U32 reserved1 : 1; + RK_U32 sao_ofst_thd_eo_chroma : 3; + RK_U32 reserved2 : 1; + RK_U32 sao_ofst_thd_bo_chroma : 3; + RK_U32 reserved3 : 5; + } subj_anti_blur_sao; + + /* 0x00002108 reg2114 */ + struct { + RK_U32 notmerge_ofst_dist_eo_wgt0 : 8; + RK_U32 notmerge_ofst_dist_bo_wgt0 : 8; + RK_U32 notmerge_ofst_dist_eo_wgt1 : 8; + RK_U32 notmerge_ofst_dist_bo_wgt1 : 8; + } subj_anti_blur_wgt0; + + /* 0x0000210c reg2115 */ + struct { + RK_U32 notmerge_ofst_lambda_eo_wgt0 : 8; + RK_U32 notmerge_ofst_lambda_bo_wgt0 : 8; + RK_U32 notmerge_compare_dist_eo_wgt0 : 8; + RK_U32 notmerge_compare_dist_bo_wgt0 : 8; + } subj_anti_blur_wgt1; + + /* 0x00002110 reg2116 */ + struct { + RK_U32 notmerge_compare_dist_eo_wgt1 : 8; + RK_U32 notmerge_compare_dist_bo_wgt1 : 8; + RK_U32 notmerge_compare_rate_eo_wgt0 : 8; + RK_U32 notmerge_compare_rate_bo_wgt0 : 8; + } subj_anti_blur_wgt2; + + /* 0x00002114 reg2117 */ + struct { + RK_U32 sao_mode_compare_dist_eo_wgt0 : 8; + RK_U32 sao_mode_compare_dist_bo_wgt0 : 8; + RK_U32 merge_cost_dist_eo_wgt0 : 8; + RK_U32 merge_cost_dist_bo_wgt0 : 8; + } subj_anti_blur_wgt3; + + /* 0x00002118 reg2118 */ + struct { + RK_U32 merge_cost_dist_eo_wgt1 : 8; + RK_U32 merge_cost_dist_bo_wgt1 : 8; + RK_U32 merge_cost_bit_eo_wgt0 : 8; + RK_U32 merge_cost_bit_bo_wgt0 : 8; + } subj_anti_blur_wgt4; + + /* 0x211c */ + RK_U32 reserved_2119; + + /* 0x00002120 reg2120 - 0x0000213c reg2127 */ + pre_cst_par preintra32_cst; + + /* 0x00002140 reg2128 - 0x0000215c reg2135 */ + pre_cst_par preintra16_cst; + + /* 0x00002160 reg2136 */ + struct { + RK_U32 offset_thd : 4; + RK_U32 offset_diff_thd : 4; + RK_U32 weak_texture_offset_thd : 3; + RK_U32 weak_texture_offset_diff_thd : 3; + RK_U32 reserved : 18; + } atr_thd_hevc; +} H265eVepu511aSqi; + +/* class: scaling list */ +/* 0x00002200 reg2176- 0x00002c9c reg2855*/ +typedef struct H265eVepu511aSclCfg_t { + /* 0x2200 - 0x2584 iq_scal_y8_intra_ac0 ~ iq_scal_list_dc1 only HEVC*/ + RK_U32 tu8_intra_y[16]; + RK_U32 tu8_intra_u[16]; + RK_U32 tu8_intra_v[16]; + RK_U32 tu8_inter_y[16]; + RK_U32 tu8_inter_u[16]; + RK_U32 tu8_inter_v[16]; + RK_U32 tu16_intra_y_ac[16]; + RK_U32 tu16_intra_u_ac[16]; + RK_U32 tu16_intra_v_ac[16]; + RK_U32 tu16_inter_y_ac[16]; + RK_U32 tu16_inter_u_ac[16]; + RK_U32 tu16_inter_v_ac[16]; + RK_U32 tu32_intra_y_ac[16]; + RK_U32 tu32_inter_y_ac[16]; + + /* 0x2580 */ + struct { + RK_U32 tu16_intra_y_dc : 8; + RK_U32 tu16_intra_u_dc : 8; + RK_U32 tu16_intra_v_dc : 8; + RK_U32 tu16_inter_y_dc : 8; + } tu_dc0; + + /* 0x2584 reg 2401*/ + struct { + RK_U32 tu16_inter_u_dc : 8; + RK_U32 tu16_inter_v_dc : 8; + RK_U32 tu32_intra_y_dc : 8; + RK_U32 tu32_inter_y_dc : 8; + } tu_dc1; + + /* 0x2588 reg 2402 - 0x258c reg 2403*/ + RK_U32 reserved2402_2403[2]; + + /* 0x2590 reg 2404 - 0x2c9c reg 2855*/ + RK_U32 q_y8_intra[32]; + RK_U32 q_u8_intra[32]; + RK_U32 q_v8_intra[32]; + RK_U32 q_y8_inter[32]; + RK_U32 q_u8_inter[32]; + RK_U32 q_v8_inter[32]; + RK_U32 q_y16_intra[32]; + RK_U32 q_u16_intra[32]; + RK_U32 q_v16_intra[32]; + RK_U32 q_y16_inter[32]; + RK_U32 q_u16_inter[32]; + RK_U32 q_v16_inter[32]; + RK_U32 q_y32_intra[32]; + RK_U32 q_y32_inter[32]; + + RK_U32 q_list[4]; +} H265eVepu511aSclCfg; + +typedef struct H265eV511ARegSet_t { + Vepu511aControlCfg reg_ctl; + H265eVepu511aFrame reg_frm; + Vepu511aRcRoi reg_rc_roi; + H265eVepu511aParam reg_param; + H265eVepu511aSqi reg_sqi; + H265eVepu511aSclCfg reg_scl; + Vepu511aDbg reg_dbg; +} H265eV511ARegSet; + +typedef struct H265eV511AStatusElem_t { + RK_U32 hw_status; + Vepu511aStatus st; +} H265eV511AStatusElem; + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu511a_tune.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu511a_tune.c new file mode 100644 index 000000000..c81171e15 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu511a_tune.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#include "hal_enc_task.h" +#include "hal_h265e_vepu511a_reg.h" + +typedef struct HalH265eVepu511aTune_t { + H265eV511AHalContext *ctx; + + MppBuffer md_info; /* internal md info buffer */ + RK_U8 *qm_mv_buf; /* qpmap move flag buffer */ + RK_U32 qm_mv_buf_size; +} HalH265eVepu511aTune; + +static HalH265eVepu511aTune *vepu511a_h265e_tune_init(H265eV511AHalContext *ctx) +{ + HalH265eVepu511aTune *tune = mpp_calloc(HalH265eVepu511aTune, 1); + + hal_h265e_dbg_func("enter\n"); + + if (NULL == tune) + return tune; + + tune->ctx = ctx; + + hal_h265e_dbg_func("leave\n"); + + return tune; +} + +static void vepu511a_h265e_tune_deinit(void *tune) +{ + HalH265eVepu511aTune *t = (HalH265eVepu511aTune *)tune; + + hal_h265e_dbg_func("enter\n"); + + if (t->md_info) { + mpp_buffer_put(t->md_info); + t->md_info = NULL; + } + + MPP_FREE(t->qm_mv_buf); + MPP_FREE(tune); + hal_h265e_dbg_func("leave\n"); +} + +static MPP_RET vepu511a_h265e_tune_qpmap_init(HalH265eVepu511aTune *tune, MppBuffer md_info) +{ + H265eV511AHalContext *ctx = tune->ctx; + Vepu511aH265eFrmCfg *frm = ctx->frm; + H265eV511ARegSet *regs = frm->regs_set; + H265eVepu511aFrame *reg_frm = ®s->reg_frm; + RK_S32 w32 = MPP_ALIGN(ctx->cfg->prep.width, 32); + RK_S32 h32 = MPP_ALIGN(ctx->cfg->prep.height, 32); + RK_S32 roir_buf_fd = -1; + + hal_h265e_dbg_func("enter\n"); + + if (frm->roi_data) { + //TODO: external qpmap buffer + } else { + if (NULL == frm->roir_buf) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + + //TODO: bmap_mdc_dpth = 1 ??? + frm->roir_buf_size = w32 * h32 / 256 * 4; + mpp_buffer_get(ctx->roi_grp, &frm->roir_buf, frm->roir_buf_size); + } + + roir_buf_fd = mpp_buffer_get_fd(frm->roir_buf); + } + + if (NULL == frm->roir_buf) { + mpp_err("failed to get roir_buf\n"); + return MPP_ERR_MALLOC; + } + reg_frm->common.adr_roir = roir_buf_fd; + + if (NULL == tune->qm_mv_buf) { + tune->qm_mv_buf_size = w32 * h32 / 256; + tune->qm_mv_buf = mpp_calloc(RK_U8, tune->qm_mv_buf_size); + if (NULL == tune->qm_mv_buf) { + mpp_err("failed to get qm_mv_buf\n"); + return MPP_ERR_MALLOC; + } + } + + if (NULL == md_info) { + RK_S32 meir_size = w32 * h32 / 256 * 4; /* max 4 bytes for each CU16 */ + if (NULL == tune->md_info) { + mpp_buffer_get(NULL, &tune->md_info, meir_size); + } + + if (tune->md_info) { + reg_frm->common.enc_pic.mei_stor = 1; + reg_frm->common.meiw_addr = mpp_buffer_get_fd(tune->md_info); + } else { + reg_frm->common.enc_pic.mei_stor = 0; + reg_frm->common.meiw_addr = 0; + return MPP_ERR_MALLOC; + } + hal_h265e_dbg_ctl("md_info_internal %p, size %d\n", tune->md_info, meir_size); + } + + hal_h265e_dbg_ctl("roir_buf_fd %d, size %d qm_mv_buf %p size %d\n", + roir_buf_fd, frm->roir_buf_size, tune->qm_mv_buf, + tune->qm_mv_buf_size); + hal_h265e_dbg_func("leave\n"); + + return MPP_OK; +} + +static void vepu511a_h265e_tune_qpmap(void *p, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH265eVepu511aTune *tune = (HalH265eVepu511aTune *)p; + + (void)task; + hal_h265e_dbg_func("enter\n"); + + ret = vepu511a_h265e_tune_qpmap_init(tune, task->md_info); + if (ret != MPP_OK) { + mpp_err("failed to init qpmap\n"); + return; + } + + hal_h265e_dbg_func("leave\n"); +} + +static void vepu511a_h265e_tune_reg_patch(void *p, HalEncTask *task) +{ + HalH265eVepu511aTune *tune = (HalH265eVepu511aTune *)p; + + hal_h265e_dbg_func("enter\n"); + + if (NULL == tune) + return; + H265eV511AHalContext *ctx = tune->ctx; + + if (ctx->qpmap_en) { + vepu511a_h265e_tune_qpmap(tune, task); + } + + hal_h265e_dbg_func("leave\n"); +} \ No newline at end of file diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu540c.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu540c.c new file mode 100644 index 000000000..0248fa392 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu540c.c @@ -0,0 +1,1716 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265e_v540c" + +#include + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" + +#include "hal_h265e_debug.h" +#include "h265e_syntax_new.h" +#include "hal_h265e_stream_amend.h" +#include "hal_bufs.h" +#include "rkv_enc_def.h" +#include "vepu5xx_common.h" +#include "vepu540c_common.h" +#include "hal_h265e_vepu540c.h" +#include "hal_h265e_vepu540c_reg.h" + +#define MAX_TITLE_NUM 2 + +#define hal_h265e_err(fmt, ...) \ + do {\ + mpp_err_f(fmt, ## __VA_ARGS__);\ + } while (0) + +typedef struct vepu540c_h265_fbk_t { + vepu540c_hw_status hw_status; + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; +} vepu540c_h265_fbk; + +typedef struct H265eV540cHalContext_t { + MppDev dev; + void *regs; + void *reg_out[MAX_TITLE_NUM]; + + vepu540c_h265_fbk feedback; + void *dump_files; + RK_U32 frame_cnt_gen_ready; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + /* @frame_cnt starts from ZERO */ + RK_U32 frame_cnt; + void *roi_data; + MppEncCfgSet *cfg; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + HalBufs dpb_bufs; + RK_S32 fbc_header_len; + RK_U32 title_num; + + /* external line buffer over 3K */ + MppBufferGroup ext_line_buf_grp; + RK_S32 ext_line_buf_size; + MppBuffer ext_line_buf; +} H265eV540cHalContext; + +#define TILE_BUF_SIZE MPP_ALIGN(128 * 1024, 256) + +static RK_U32 aq_thd_default[16] = { + 0, 0, 0, 0, + 3, 3, 5, 5, + 8, 8, 8, 15, + 15, 20, 25, 25 +}; + +static RK_S32 aq_qp_dealt_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 6, 8, +}; + +static MPP_RET vepu540c_h265_setup_hal_bufs(H265eV540cHalContext *ctx) +{ + MPP_RET ret = MPP_OK; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + RK_U32 frame_size; + VepuFmt input_fmt = VEPU5xx_FMT_YUV420P; + RK_S32 mb_wd64, mb_h64; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 2; + RK_S32 alignment = 32; + RK_S32 aligned_w = MPP_ALIGN(prep->width, alignment); + + hal_h265e_enter(); + + mb_wd64 = (prep->width + 63) / 64; + mb_h64 = (prep->height + 63) / 64; + + frame_size = MPP_ALIGN(prep->width, 16) * MPP_ALIGN(prep->height, 16); + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + input_fmt = (VepuFmt)fmt->format; + switch (input_fmt) { + case VEPU5xx_FMT_YUV400: + break; + case VEPU5xx_FMT_YUV420P: + case VEPU5xx_FMT_YUV420SP: { + frame_size = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV422P: + case VEPU5xx_FMT_YUV422SP: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: + case VEPU5xx_FMT_BGR565: { + frame_size *= 2; + } break; + case VEPU5xx_FMT_BGR888: { + frame_size *= 3; + } break; + case VEPU5xx_FMT_BGRA8888: { + frame_size *= 4; + } break; + default: { + hal_h265e_err("invalid src color space: %d\n", input_fmt); + return MPP_NOK; + } + } + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (aligned_w > (3 * SZ_1K)) { + RK_S32 ext_line_buf_size = (aligned_w / 32 - 91) * 26 * 16; + + if (NULL == ctx->ext_line_buf_grp) + mpp_buffer_group_get_internal(&ctx->ext_line_buf_grp, MPP_BUFFER_TYPE_ION); + else if (ext_line_buf_size != ctx->ext_line_buf_size) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + } + + mpp_assert(ctx->ext_line_buf_grp); + + if (NULL == ctx->ext_line_buf) + mpp_buffer_get(ctx->ext_line_buf_grp, &ctx->ext_line_buf, ext_line_buf_size); + + ctx->ext_line_buf_size = ext_line_buf_size; + } else { + if (ctx->ext_line_buf) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + } + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_clear(ctx->ext_line_buf_grp); + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + ctx->ext_line_buf_size = 0; + } + + if (frame_size > ctx->frame_size || new_max_cnt > old_max_cnt) { + size_t size[3] = {0}; + + hal_bufs_deinit(ctx->dpb_bufs); + hal_bufs_init(&ctx->dpb_bufs); + + ctx->fbc_header_len = MPP_ALIGN(((mb_wd64 * mb_h64) << 6), SZ_8K); + size[0] = ctx->fbc_header_len + ((mb_wd64 * mb_h64) << 12) * 3 / 2; //fbc_h + fbc_b + size[1] = (mb_wd64 * mb_h64 << 8); + size[2] = MPP_ALIGN(mb_wd64 * mb_h64 * 16 * 4, 256) * 16; + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_h265e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->frame_size, frame_size, old_max_cnt, new_max_cnt); + + hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, 3, size); + + ctx->frame_size = frame_size; + ctx->max_buf_cnt = new_max_cnt; + } + hal_h265e_leave(); + return ret; +} + +static void vepu540c_h265_rdo_cfg (vepu540c_rdo_cfg *reg) +{ + rdo_skip_par *p_rdo_skip = NULL; + rdo_noskip_par *p_rdo_noskip = NULL; + pre_cst_par *p_pre_cst = NULL; + + reg->rdo_segment_cfg.rdo_segment_multi = 28; + reg->rdo_segment_cfg.rdo_segment_en = 1; + reg->rdo_smear_cfg_comb.rdo_smear_en = 0; + reg->rdo_smear_cfg_comb.rdo_smear_lvl16_multi = 9; + reg->rdo_segment_cfg.rdo_smear_lvl8_multi = 8; + reg->rdo_segment_cfg.rdo_smear_lvl4_multi = 8; + reg->rdo_smear_cfg_comb.rdo_smear_dlt_qp = 0 ; + reg->rdo_smear_cfg_comb.rdo_smear_order_state = 0; + reg->rdo_smear_cfg_comb.stated_mode = 0; + reg->rdo_smear_cfg_comb.online_en = 0; + reg->rdo_smear_cfg_comb.smear_stride = 0; + reg->rdo_smear_madp_thd0_comb.rdo_smear_madp_cur_thd0 = 0 ; + reg->rdo_smear_madp_thd0_comb.rdo_smear_madp_cur_thd1 = 24; + reg->rdo_smear_madp_thd1_comb.rdo_smear_madp_cur_thd2 = 48; + reg->rdo_smear_madp_thd1_comb.rdo_smear_madp_cur_thd3 = 64; + reg->rdo_smear_madp_thd2_comb.rdo_smear_madp_around_thd0 = 16; + reg->rdo_smear_madp_thd2_comb.rdo_smear_madp_around_thd1 = 32; + reg->rdo_smear_madp_thd3_comb.rdo_smear_madp_around_thd2 = 48; + reg->rdo_smear_madp_thd3_comb.rdo_smear_madp_around_thd3 = 96; + reg->rdo_smear_madp_thd4_comb.rdo_smear_madp_around_thd4 = 48; + reg->rdo_smear_madp_thd4_comb.rdo_smear_madp_around_thd5 = 24; + reg->rdo_smear_madp_thd5_comb.rdo_smear_madp_ref_thd0 = 96; + reg->rdo_smear_madp_thd5_comb.rdo_smear_madp_ref_thd1 = 48; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd0 = 1 ; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd1 = 3; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd2 = 1 ; + reg->rdo_smear_cnt_thd0_comb.rdo_smear_cnt_cur_thd3 = 3; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd0 = 1 ; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd1 = 4 ; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd2 = 1 ; + reg->rdo_smear_cnt_thd1_comb.rdo_smear_cnt_around_thd3 = 4 ; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd4 = 0; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd5 = 3; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd6 = 0; + reg->rdo_smear_cnt_thd2_comb.rdo_smear_cnt_around_thd7 = 3; + reg->rdo_smear_cnt_thd3_comb.rdo_smear_cnt_ref_thd0 = 1; + reg->rdo_smear_cnt_thd3_comb.rdo_smear_cnt_ref_thd1 = 3; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_small_cur_th0 = 6; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_big_cur_th0 = 9; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_small_cur_th1 = 6; + reg->rdo_smear_resi_thd0_comb.rdo_smear_resi_big_cur_th1 = 9; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_small_around_th0 = 6; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_big_around_th0 = 11; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_small_around_th1 = 6; + reg->rdo_smear_resi_thd1_comb.rdo_smear_resi_big_around_th1 = 8; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_small_around_th2 = 9; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_big_around_th2 = 20; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_small_around_th3 = 6; + reg->rdo_smear_resi_thd2_comb.rdo_smear_resi_big_around_th3 = 20; + reg->rdo_smear_resi_thd3_comb.rdo_smear_resi_small_ref_th0 = 7; + reg->rdo_smear_resi_thd3_comb.rdo_smear_resi_big_ref_th0 = 16; + reg->rdo_smear_st_thd0_comb.rdo_smear_resi_th0 = 9; + reg->rdo_smear_st_thd0_comb.rdo_smear_resi_th1 = 6; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th0 = 1; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th1 = 5; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th2 = 1; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th3 = 3; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th4 = 1; + reg->rdo_smear_st_thd1_comb.rdo_smear_madp_cnt_th5 = 2; + + p_rdo_skip = ®->rdo_b32_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 5 ; + p_rdo_skip->atf_thd0.madp_thd1 = 10 ; + p_rdo_skip->atf_thd1.madp_thd2 = 15 ; + p_rdo_skip->atf_thd1.madp_thd3 = 72; + p_rdo_skip->atf_wgt0.wgt0 = 20; + p_rdo_skip->atf_wgt0.wgt1 = 16; + p_rdo_skip->atf_wgt0.wgt2 = 16; + p_rdo_skip->atf_wgt0.wgt3 = 16; + p_rdo_skip->atf_wgt1.wgt4 = 16; + + p_rdo_noskip = ®->rdo_b32_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 16; + p_rdo_noskip->atf_wgt.wgt1 = 16; + p_rdo_noskip->atf_wgt.wgt2 = 16; + p_rdo_noskip->atf_wgt.wgt3 = 16; + + p_rdo_noskip = ®->rdo_b32_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 27; + p_rdo_noskip->atf_wgt.wgt1 = 25; + p_rdo_noskip->atf_wgt.wgt2 = 20; + p_rdo_noskip->atf_wgt.wgt3 = 19; + + p_rdo_skip = ®->rdo_b16_skip; + p_rdo_skip->atf_thd0.madp_thd0 = 1; + p_rdo_skip->atf_thd0.madp_thd1 = 10 ; + p_rdo_skip->atf_thd1.madp_thd2 = 15 ; + p_rdo_skip->atf_thd1.madp_thd3 = 25 ; + p_rdo_skip->atf_wgt0.wgt0 = 20 ; + p_rdo_skip->atf_wgt0.wgt1 = 16; + p_rdo_skip->atf_wgt0.wgt2 = 16; + p_rdo_skip->atf_wgt0.wgt3 = 16; + p_rdo_skip->atf_wgt1.wgt4 = 16; + + p_rdo_noskip = ®->rdo_b16_inter; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 16; + p_rdo_noskip->atf_wgt.wgt1 = 16; + p_rdo_noskip->atf_wgt.wgt2 = 16; + p_rdo_noskip->atf_wgt.wgt3 = 16; + + p_rdo_noskip = ®->rdo_b16_intra; + p_rdo_noskip->ratf_thd0.madp_thd0 = 20; + p_rdo_noskip->ratf_thd0.madp_thd1 = 40; + p_rdo_noskip->ratf_thd1.madp_thd2 = 72; + p_rdo_noskip->atf_wgt.wgt0 = 27; + p_rdo_noskip->atf_wgt.wgt1 = 25; + p_rdo_noskip->atf_wgt.wgt2 = 20; + p_rdo_noskip->atf_wgt.wgt3 = 16; + + reg->rdo_b32_intra_atf_cnt_thd.thd0 = 1; + reg->rdo_b32_intra_atf_cnt_thd.thd1 = 4; + reg->rdo_b32_intra_atf_cnt_thd.thd2 = 1; + reg->rdo_b32_intra_atf_cnt_thd.thd3 = 4; + + reg->rdo_b16_intra_atf_cnt_thd_comb.thd0 = 1; + reg->rdo_b16_intra_atf_cnt_thd_comb.thd1 = 4; + reg->rdo_b16_intra_atf_cnt_thd_comb.thd2 = 1; + reg->rdo_b16_intra_atf_cnt_thd_comb.thd3 = 4; + reg->rdo_atf_resi_thd_comb.big_th0 = 16; + reg->rdo_atf_resi_thd_comb.big_th1 = 16; + reg->rdo_atf_resi_thd_comb.small_th0 = 8; + reg->rdo_atf_resi_thd_comb.small_th1 = 8; + + p_pre_cst = ®->preintra32_cst; + p_pre_cst->cst_madi_thd0.madi_thd0 = 5; + p_pre_cst->cst_madi_thd0.madi_thd1 = 3; + p_pre_cst->cst_madi_thd0.madi_thd2 = 3; + p_pre_cst->cst_madi_thd0.madi_thd3 = 6; + p_pre_cst->cst_madi_thd1.madi_thd4 = 7; + p_pre_cst->cst_madi_thd1.madi_thd5 = 10; + p_pre_cst->cst_wgt0.wgt0 = 20; + p_pre_cst->cst_wgt0.wgt1 = 18; + p_pre_cst->cst_wgt0.wgt2 = 19; + p_pre_cst->cst_wgt0.wgt3 = 18; + p_pre_cst->cst_wgt1.wgt4 = 6; + p_pre_cst->cst_wgt1.wgt5 = 9; + p_pre_cst->cst_wgt1.wgt6 = 14; + p_pre_cst->cst_wgt1.wgt7 = 18; + p_pre_cst->cst_wgt2.wgt8 = 17; + p_pre_cst->cst_wgt2.wgt9 = 17; + p_pre_cst->cst_wgt2.mode_th = 5; + + p_pre_cst = ®->preintra16_cst; + p_pre_cst->cst_madi_thd0.madi_thd0 = 5; + p_pre_cst->cst_madi_thd0.madi_thd1 = 3; + p_pre_cst->cst_madi_thd0.madi_thd2 = 3; + p_pre_cst->cst_madi_thd0.madi_thd3 = 6; + p_pre_cst->cst_madi_thd1.madi_thd4 = 5; + p_pre_cst->cst_madi_thd1.madi_thd5 = 7; + p_pre_cst->cst_wgt0.wgt0 = 20; + p_pre_cst->cst_wgt0.wgt1 = 18; + p_pre_cst->cst_wgt0.wgt2 = 19; + p_pre_cst->cst_wgt0.wgt3 = 18; + p_pre_cst->cst_wgt1.wgt4 = 6; + p_pre_cst->cst_wgt1.wgt5 = 9; + p_pre_cst->cst_wgt1.wgt6 = 14; + p_pre_cst->cst_wgt1.wgt7 = 18; + p_pre_cst->cst_wgt2.wgt8 = 17; + p_pre_cst->cst_wgt2.wgt9 = 17; + p_pre_cst->cst_wgt2.mode_th = 5; + + reg->preintra_sqi_cfg.pre_intra_qp_thd = 28; + reg->preintra_sqi_cfg.pre_intra4_lambda_mv_bit = 3; + reg->preintra_sqi_cfg.pre_intra8_lambda_mv_bit = 4; + reg->preintra_sqi_cfg.pre_intra16_lambda_mv_bit = 4; + reg->preintra_sqi_cfg.pre_intra32_lambda_mv_bit = 5; + reg->rdo_atr_i_cu32_madi_cfg0.i_cu32_madi_thd0 = 3; + reg->rdo_atr_i_cu32_madi_cfg0.i_cu32_madi_thd1 = 35; + reg->rdo_atr_i_cu32_madi_cfg0.i_cu32_madi_thd2 = 25; + reg->rdo_atr_i_cu32_madi_cfg1.i_cu32_madi_cnt_thd3 = 0; + reg->rdo_atr_i_cu32_madi_cfg1.i_cu32_madi_thd4 = 20; + reg->rdo_atr_i_cu32_madi_cfg1.i_cu32_madi_cost_multi = 24; + reg->rdo_atr_i_cu16_madi_cfg0.i_cu16_madi_thd0 = 4; + reg->rdo_atr_i_cu16_madi_cfg0.i_cu16_madi_thd1 = 6; + reg->rdo_atr_i_cu16_madi_cfg0.i_cu16_madi_cost_multi = 24; + +} + +static void vepu540c_h265_global_cfg_set(H265eV540cHalContext *ctx, H265eV540cRegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + RK_U32 i; + hevc_vepu540c_rc_roi *rc_regs = ®s->reg_rc_roi; + hevc_vepu540c_wgt *reg_wgt = ®s->reg_wgt; + vepu540c_rdo_cfg *reg_rdo = ®s->reg_rdo; + vepu540c_h265_rdo_cfg(reg_rdo); + + if (ctx->frame_type == INTRA_FRAME) { + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + rc_regs->aq_tthd[i] = hw->aq_thrd_i[i]; + rc_regs->aq_step[i] = hw->aq_step_i[i] & 0x3f; + } + reg_wgt->iprd_lamb_satd_ofst.lambda_satd_offset = 11; + memcpy(®_wgt->rdo_wgta_qp_grpa_0_51[0], lamd_moda_qp, sizeof(lamd_moda_qp)); + } else { + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + rc_regs->aq_tthd[i] = hw->aq_thrd_p[i]; + rc_regs->aq_step[i] = hw->aq_step_p[i] & 0x3f; + } + reg_wgt->iprd_lamb_satd_ofst.lambda_satd_offset = 11; + memcpy(®_wgt->rdo_wgta_qp_grpa_0_51[0], lamd_modb_qp, sizeof(lamd_modb_qp)); + } + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_i = 171; + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_p = 85; + if (hw->qbias_en) { + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_i = hw->qbias_i; + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_p = hw->qbias_p; + } + /* CIME */ + { + /* 0x1760 */ + regs->reg_wgt.me_sqi_cfg.cime_pmv_num = 1; + regs->reg_wgt.me_sqi_cfg.cime_fuse = 1; + regs->reg_wgt.me_sqi_cfg.itp_mode = 0; + regs->reg_wgt.me_sqi_cfg.move_lambda = 2; + regs->reg_wgt.me_sqi_cfg.rime_lvl_mrg = 0; + regs->reg_wgt.me_sqi_cfg.rime_prelvl_en = 3; + regs->reg_wgt.me_sqi_cfg.rime_prersu_en = 3; + + /* 0x1764 */ + regs->reg_wgt.cime_mvd_th.cime_mvd_th0 = 8; + regs->reg_wgt.cime_mvd_th.cime_mvd_th1 = 20; + regs->reg_wgt.cime_mvd_th.cime_mvd_th2 = 32; + + /* 0x1768 */ + regs->reg_wgt.cime_madp_th.cime_madp_th = 16; + + /* 0x176c */ + regs->reg_wgt.cime_multi.cime_multi0 = 8; + regs->reg_wgt.cime_multi.cime_multi1 = 12; + regs->reg_wgt.cime_multi.cime_multi2 = 16; + regs->reg_wgt.cime_multi.cime_multi3 = 20; + } + + /* RIME && FME */ + { + /* 0x1770 */ + regs->reg_wgt.rime_mvd_th.rime_mvd_th0 = 1; + regs->reg_wgt.rime_mvd_th.rime_mvd_th1 = 2; + regs->reg_wgt.rime_mvd_th.fme_madp_th = 0; + + /* 0x1774 */ + regs->reg_wgt.rime_madp_th.rime_madp_th0 = 8; + regs->reg_wgt.rime_madp_th.rime_madp_th1 = 16; + + /* 0x1778 */ + regs->reg_wgt.rime_multi.rime_multi0 = 4; + regs->reg_wgt.rime_multi.rime_multi1 = 8; + regs->reg_wgt.rime_multi.rime_multi2 = 12; + + /* 0x177C */ + regs->reg_wgt.cmv_st_th.cmv_th0 = 64; + regs->reg_wgt.cmv_st_th.cmv_th1 = 96; + regs->reg_wgt.cmv_st_th.cmv_th2 = 128; + } +} + +MPP_RET hal_h265e_v540c_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + RK_U32 i = 0; + + mpp_env_get_u32("hal_h265e_debug", &hal_h265e_debug, 0); + + hal_h265e_enter(); + + for ( i = 0; i < MAX_TITLE_NUM; i++) { + ctx->reg_out[i] = mpp_calloc(H265eV540cStatusElem, 1); + } + + ctx->regs = mpp_calloc(H265eV540cRegSet, 1); + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + hal_bufs_init(&ctx->dpb_bufs); + + ctx->frame_cnt = 0; + ctx->frame_cnt_gen_ready = 0; + ctx->enc_mode = 1; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + + ctx->dev = cfg->dev; + ctx->frame_type = INTRA_FRAME; + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 2; + hw->qp_delta_row = 2; + hw->qbias_i = 171; + hw->qbias_p = 85; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, aq_thd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, aq_thd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, aq_qp_dealt_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, aq_qp_dealt_default, sizeof(hw->aq_step_p)); + } + + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_v540c_deinit(void *hal) +{ + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + RK_U32 i = 0; + + hal_h265e_enter(); + MPP_FREE(ctx->regs); + + for ( i = 0; i < MAX_TITLE_NUM; i++) { + MPP_FREE(ctx->reg_out[i]); + } + + MPP_FREE(ctx->input_fmt); + hal_bufs_deinit(ctx->dpb_bufs); + + if (ctx->ext_line_buf) { + mpp_buffer_put(ctx->ext_line_buf); + ctx->ext_line_buf = NULL; + } + + if (ctx->ext_line_buf_grp) { + mpp_buffer_group_put(ctx->ext_line_buf_grp); + ctx->ext_line_buf_grp = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + hal_h265e_leave(); + return MPP_OK; +} + +static MPP_RET hal_h265e_vepu540c_prepare(void *hal) +{ + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h265e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + vepu540c_h265_setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->dpb_bufs, i); + + prep->change_res = 0; + } + + hal_h265e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET +vepu540c_h265_set_patch_info(MppDev dev, H265eSyntax_new *syn, VepuFmt input_fmt, HalEncTask *task) +{ + RK_U32 hor_stride = syn->pp.hor_stride; + RK_U32 ver_stride = (syn->pp.ver_stride != 0) ? syn->pp.ver_stride : syn->pp.pic_height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + u_offset = mpp_frame_get_fbc_offset(task->frame); + v_offset = 0; + mpp_log("fbc case u_offset = %d", u_offset); + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV400: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + default: { + hal_h265e_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + + /* input cb addr */ + if (u_offset) { + ret = mpp_dev_set_reg_offset(dev, 161, u_offset); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); + } + + /* input cr addr */ + if (v_offset) { + ret = mpp_dev_set_reg_offset(dev, 162, v_offset); + if (ret) + mpp_err_f("set input cr addr offset failed %d\n", ret); + } + + return ret; +} + + +#if 0 +static MPP_RET vepu540c_h265_set_roi_regs(H265eV540cHalContext *ctx, hevc_vepu540c_base *regs) +{ + /* memset register on start so do not clear registers again here */ + if (ctx->roi_data) { + /* roi setup */ + MppEncROICfg2 *cfg = ( MppEncROICfg2 *)ctx->roi_data; + + regs->reg0192_enc_pic.roi_en = 1; + regs->reg0178_roi_addr = mpp_dev_get_iova_address(ctx->dev, cfg->base_cfg_buf, 0); + if (cfg->roi_qp_en) { + regs->reg0179_roi_qp_addr = mpp_dev_get_iova_address(ctx->dev, cfg->qp_cfg_buf, 0); + regs->reg0228_roi_en.roi_qp_en = 1; + } + + if (cfg->roi_amv_en) { + regs->reg0180_roi_amv_addr = mpp_dev_get_iova_address(ctx->dev, cfg->amv_cfg_buf, 0); + regs->reg0228_roi_en.roi_amv_en = 1; + } + + if (cfg->roi_mv_en) { + regs->reg0181_roi_mv_addr = mpp_dev_get_iova_address(ctx->dev, cfg->mv_cfg_buf, 0); + regs->reg0228_roi_en.roi_mv_en = 1; + } + } + + return MPP_OK; +} +#endif + +static MPP_RET vepu540c_h265_set_rc_regs(H265eV540cHalContext *ctx, H265eV540cRegSet *regs, HalEncTask *task) +{ + H265eSyntax_new *syn = (H265eSyntax_new *)task->syntax.data; + EncRcTaskInfo *rc_cfg = &task->rc_task->info; + hevc_vepu540c_base *reg_base = ®s->reg_base; + hevc_vepu540c_rc_roi *reg_rc = ®s->reg_rc_roi; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + MppEncH265Cfg *h265 = &cfg->h265; + RK_S32 mb_wd32 = (syn->pp.pic_width + 31) / 32; + RK_S32 mb_h32 = (syn->pp.pic_height + 31) / 32; + + RK_U32 ctu_target_bits_mul_16 = (rc_cfg->bit_target << 4) / (mb_wd32 * mb_h32); + RK_U32 ctu_target_bits; + RK_S32 negative_bits_thd, positive_bits_thd; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + reg_base->reg0192_enc_pic.pic_qp = rc_cfg->quality_target; + reg_base->reg0240_synt_sli1.sli_qp = rc_cfg->quality_target; + + reg_base->reg213_rc_qp.rc_max_qp = rc_cfg->quality_target; + reg_base->reg213_rc_qp.rc_min_qp = rc_cfg->quality_target; + } else { + if (ctu_target_bits_mul_16 >= 0x100000) { + ctu_target_bits_mul_16 = 0x50000; + } + ctu_target_bits = (ctu_target_bits_mul_16 * mb_wd32) >> 4; + negative_bits_thd = 0 - 5 * ctu_target_bits / 16; + positive_bits_thd = 5 * ctu_target_bits / 16; + + reg_base->reg0192_enc_pic.pic_qp = rc_cfg->quality_target; + reg_base->reg0240_synt_sli1.sli_qp = rc_cfg->quality_target; + reg_base->reg212_rc_cfg.rc_en = 1; + reg_base->reg212_rc_cfg.aq_en = 1; + reg_base->reg212_rc_cfg.aq_mode = 0; + reg_base->reg212_rc_cfg.rc_ctu_num = mb_wd32; + reg_base->reg213_rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? + hw->qp_delta_row_i : hw->qp_delta_row; + reg_base->reg213_rc_qp.rc_max_qp = rc_cfg->quality_max; + reg_base->reg213_rc_qp.rc_min_qp = rc_cfg->quality_min; + reg_base->reg214_rc_tgt.ctu_ebit = ctu_target_bits_mul_16; + + reg_rc->rc_dthd_0_8[0] = 4 * negative_bits_thd; + reg_rc->rc_dthd_0_8[1] = negative_bits_thd; + reg_rc->rc_dthd_0_8[2] = positive_bits_thd; + reg_rc->rc_dthd_0_8[3] = 4 * positive_bits_thd; + reg_rc->rc_dthd_0_8[4] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[5] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[6] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[7] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[8] = 0x7FFFFFFF; + + reg_rc->rc_adj0.qp_adj0 = -2; + reg_rc->rc_adj0.qp_adj1 = -1; + reg_rc->rc_adj0.qp_adj2 = 0; + reg_rc->rc_adj0.qp_adj3 = 1; + reg_rc->rc_adj0.qp_adj4 = 2; + reg_rc->rc_adj1.qp_adj5 = 0; + reg_rc->rc_adj1.qp_adj6 = 0; + reg_rc->rc_adj1.qp_adj7 = 0; + reg_rc->rc_adj1.qp_adj8 = 0; + } + + reg_rc->roi_qthd0.qpmin_area0 = h265->qpmin_map[0] > 0 ? h265->qpmin_map[0] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area0 = h265->qpmax_map[0] > 0 ? h265->qpmax_map[0] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area1 = h265->qpmin_map[1] > 0 ? h265->qpmin_map[1] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area1 = h265->qpmax_map[1] > 0 ? h265->qpmax_map[1] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area2 = h265->qpmin_map[2] > 0 ? h265->qpmin_map[2] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area2 = h265->qpmax_map[2] > 0 ? h265->qpmax_map[2] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area3 = h265->qpmin_map[3] > 0 ? h265->qpmin_map[3] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area3 = h265->qpmax_map[3] > 0 ? h265->qpmax_map[3] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area4 = h265->qpmin_map[4] > 0 ? h265->qpmin_map[4] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area4 = h265->qpmax_map[4] > 0 ? h265->qpmax_map[4] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area5 = h265->qpmin_map[5] > 0 ? h265->qpmin_map[5] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area5 = h265->qpmax_map[5] > 0 ? h265->qpmax_map[5] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area6 = h265->qpmin_map[6] > 0 ? h265->qpmin_map[6] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area6 = h265->qpmax_map[6] > 0 ? h265->qpmax_map[6] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area7 = h265->qpmin_map[7] > 0 ? h265->qpmin_map[7] : rc_cfg->quality_min; + reg_rc->roi_qthd3.qpmax_area7 = h265->qpmax_map[7] > 0 ? h265->qpmax_map[7] : rc_cfg->quality_max; + reg_rc->roi_qthd3.qpmap_mode = h265->qpmap_mode; + + return MPP_OK; +} + +static MPP_RET vepu540c_h265_set_pp_regs(H265eV540cRegSet *regs, VepuFmtCfg *fmt, MppEncPrepCfg *prep_cfg) +{ + hevc_vepu540c_control_cfg *reg_ctl = ®s->reg_ctl; + hevc_vepu540c_base *reg_base = ®s->reg_base; + RK_S32 stridey = 0; + RK_S32 stridec = 0; + + reg_ctl->reg0012_dtrns_map.src_bus_edin = fmt->src_endian; + reg_base->reg0198_src_fmt.src_cfmt = fmt->format; + reg_base->reg0198_src_fmt.alpha_swap = fmt->alpha_swap; + reg_base->reg0198_src_fmt.rbuv_swap = fmt->rbuv_swap; + reg_base->reg0198_src_fmt.out_fmt = (fmt->format == VEPU5xx_FMT_YUV400) ? 0 : 1; + reg_base->reg0203_src_proc.src_mirr = prep_cfg->mirroring > 0; + reg_base->reg0203_src_proc.src_rot = prep_cfg->rotation; + + if (prep_cfg->hor_stride) { + stridey = prep_cfg->hor_stride; + } else { + if (reg_base->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_BGRA8888 ) + stridey = prep_cfg->width * 4; + else if (reg_base->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_BGR888 ) + stridey = prep_cfg->width * 3; + else if (reg_base->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_BGR565 || + reg_base->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_YUYV422 || + reg_base->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_UYVY422) + stridey = prep_cfg->width * 2; + } + + stridec = (reg_base->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_YUV422SP || + reg_base->reg0198_src_fmt.src_cfmt == VEPU5xx_FMT_YUV420SP) ? + stridey : stridey / 2; + + if (reg_base->reg0198_src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = cfg_coeffs = get_rgb2yuv_cfg(prep_cfg->range, prep_cfg->color); + + hal_h265e_dbg_simple("input color range %d colorspace %d", prep_cfg->range, prep_cfg->color); + + reg_base->reg0199_src_udfy.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + reg_base->reg0199_src_udfy.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + reg_base->reg0199_src_udfy.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + + reg_base->reg0200_src_udfu.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + reg_base->reg0200_src_udfu.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + reg_base->reg0200_src_udfu.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + + reg_base->reg0201_src_udfv.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + reg_base->reg0201_src_udfv.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + reg_base->reg0201_src_udfv.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + + reg_base->reg0202_src_udfo.csc_ofst_y = cfg_coeffs->_2y.offset; + reg_base->reg0202_src_udfo.csc_ofst_u = cfg_coeffs->_2u.offset; + reg_base->reg0202_src_udfo.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h265e_dbg_simple("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } + + reg_base->reg0205_src_strd0.src_strd0 = stridey; + reg_base->reg0206_src_strd1.src_strd1 = stridec; + + return MPP_OK; +} + +static void vepu540c_h265_set_slice_regs(H265eSyntax_new *syn, hevc_vepu540c_base *regs) +{ + regs->reg0237_synt_sps.smpl_adpt_ofst_e = syn->pp.sample_adaptive_offset_enabled_flag; + regs->reg0237_synt_sps.num_st_ref_pic = syn->pp.num_short_term_ref_pic_sets; + regs->reg0237_synt_sps.num_lt_ref_pic = syn->pp.num_long_term_ref_pics_sps; + regs->reg0237_synt_sps.lt_ref_pic_prsnt = syn->pp.long_term_ref_pics_present_flag; + regs->reg0237_synt_sps.tmpl_mvp_e = syn->pp.sps_temporal_mvp_enabled_flag; + regs->reg0237_synt_sps.log2_max_poc_lsb = syn->pp.log2_max_pic_order_cnt_lsb_minus4; + regs->reg0237_synt_sps.strg_intra_smth = syn->pp.strong_intra_smoothing_enabled_flag; + + regs->reg0238_synt_pps.dpdnt_sli_seg_en = syn->pp.dependent_slice_segments_enabled_flag; + regs->reg0238_synt_pps.out_flg_prsnt_flg = syn->pp.output_flag_present_flag; + regs->reg0238_synt_pps.num_extr_sli_hdr = syn->pp.num_extra_slice_header_bits; + regs->reg0238_synt_pps.sgn_dat_hid_en = syn->pp.sign_data_hiding_enabled_flag; + regs->reg0238_synt_pps.cbc_init_prsnt_flg = syn->pp.cabac_init_present_flag; + regs->reg0238_synt_pps.pic_init_qp = syn->pp.init_qp_minus26 + 26; + regs->reg0238_synt_pps.cu_qp_dlt_en = syn->pp.cu_qp_delta_enabled_flag; + regs->reg0238_synt_pps.chrm_qp_ofst_prsn = syn->pp.pps_slice_chroma_qp_offsets_present_flag; + regs->reg0238_synt_pps.lp_fltr_acrs_sli = syn->pp.pps_loop_filter_across_slices_enabled_flag; + regs->reg0238_synt_pps.dblk_fltr_ovrd_en = syn->pp.deblocking_filter_override_enabled_flag; + regs->reg0238_synt_pps.lst_mdfy_prsnt_flg = syn->pp.lists_modification_present_flag; + regs->reg0238_synt_pps.sli_seg_hdr_extn = syn->pp.slice_segment_header_extension_present_flag; + regs->reg0238_synt_pps.cu_qp_dlt_depth = syn->pp.diff_cu_qp_delta_depth; + regs->reg0238_synt_pps.lpf_fltr_acrs_til = syn->pp.loop_filter_across_tiles_enabled_flag; + + regs->reg0239_synt_sli0.cbc_init_flg = syn->sp.cbc_init_flg; + regs->reg0239_synt_sli0.mvd_l1_zero_flg = syn->sp.mvd_l1_zero_flg; + regs->reg0239_synt_sli0.mrg_up_flg = syn->sp.merge_up_flag; + regs->reg0239_synt_sli0.mrg_lft_flg = syn->sp.merge_left_flag; + regs->reg0239_synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + regs->reg0239_synt_sli0.num_refidx_l1_act = syn->sp.num_refidx_l1_act; + regs->reg0239_synt_sli0.num_refidx_l0_act = syn->sp.num_refidx_l0_act; + + regs->reg0239_synt_sli0.num_refidx_act_ovrd = syn->sp.num_refidx_act_ovrd; + + regs->reg0239_synt_sli0.sli_sao_chrm_flg = syn->sp.sli_sao_chrm_flg; + regs->reg0239_synt_sli0.sli_sao_luma_flg = syn->sp.sli_sao_luma_flg; + regs->reg0239_synt_sli0.sli_tmprl_mvp_e = syn->sp.sli_tmprl_mvp_en; + regs->reg0192_enc_pic.num_pic_tot_cur = syn->sp.tot_poc_num; + + regs->reg0239_synt_sli0.pic_out_flg = syn->sp.pic_out_flg; + regs->reg0239_synt_sli0.sli_type = syn->sp.slice_type; + regs->reg0239_synt_sli0.sli_rsrv_flg = syn->sp.slice_rsrv_flg; + regs->reg0239_synt_sli0.dpdnt_sli_seg_flg = syn->sp.dpdnt_sli_seg_flg; + regs->reg0239_synt_sli0.sli_pps_id = syn->sp.sli_pps_id; + regs->reg0239_synt_sli0.no_out_pri_pic = syn->sp.no_out_pri_pic; + + + regs->reg0240_synt_sli1.sp_tc_ofst_div2 = syn->sp.sli_tc_ofst_div2;; + regs->reg0240_synt_sli1.sp_beta_ofst_div2 = syn->sp.sli_beta_ofst_div2; + regs->reg0240_synt_sli1.sli_lp_fltr_acrs_sli = syn->sp.sli_lp_fltr_acrs_sli; + regs->reg0240_synt_sli1.sp_dblk_fltr_dis = syn->sp.sli_dblk_fltr_dis; + regs->reg0240_synt_sli1.dblk_fltr_ovrd_flg = syn->sp.dblk_fltr_ovrd_flg; + regs->reg0240_synt_sli1.sli_cb_qp_ofst = syn->sp.sli_cb_qp_ofst; + regs->reg0240_synt_sli1.max_mrg_cnd = syn->sp.max_mrg_cnd; + + regs->reg0240_synt_sli1.col_ref_idx = syn->sp.col_ref_idx; + regs->reg0240_synt_sli1.col_frm_l0_flg = syn->sp.col_frm_l0_flg; + regs->reg0241_synt_sli2.sli_poc_lsb = syn->sp.sli_poc_lsb; + regs->reg0241_synt_sli2.sli_hdr_ext_len = syn->sp.sli_hdr_ext_len; + +} + +static void vepu540c_h265_set_ref_regs(H265eSyntax_new *syn, hevc_vepu540c_base *regs) +{ + regs->reg0242_synt_refm0.st_ref_pic_flg = syn->sp.st_ref_pic_flg; + regs->reg0242_synt_refm0.poc_lsb_lt0 = syn->sp.poc_lsb_lt0; + regs->reg0242_synt_refm0.num_lt_pic = syn->sp.num_lt_pic; + + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->reg0243_synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->reg0243_synt_refm1.used_by_lt_flg0 = syn->sp.used_by_lt_flg0; + regs->reg0243_synt_refm1.used_by_lt_flg1 = syn->sp.used_by_lt_flg1; + regs->reg0243_synt_refm1.used_by_lt_flg2 = syn->sp.used_by_lt_flg2; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->reg0243_synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt1 = syn->sp.dlt_poc_msb_prsnt1; + regs->reg0243_synt_refm1.num_negative_pics = syn->sp.num_neg_pic; + regs->reg0243_synt_refm1.num_pos_pic = syn->sp.num_pos_pic; + + regs->reg0243_synt_refm1.used_by_s0_flg = syn->sp.used_by_s0_flg; + regs->reg0244_synt_refm2.dlt_poc_s0_m10 = syn->sp.dlt_poc_s0_m10; + regs->reg0244_synt_refm2.dlt_poc_s0_m11 = syn->sp.dlt_poc_s0_m11; + regs->reg0245_synt_refm3.dlt_poc_s0_m12 = syn->sp.dlt_poc_s0_m12; + regs->reg0245_synt_refm3.dlt_poc_s0_m13 = syn->sp.dlt_poc_s0_m13; + + regs->reg0246_synt_long_refm0.poc_lsb_lt1 = syn->sp.poc_lsb_lt1; + regs->reg0247_synt_long_refm1.dlt_poc_msb_cycl1 = syn->sp.dlt_poc_msb_cycl1; + regs->reg0246_synt_long_refm0.poc_lsb_lt2 = syn->sp.poc_lsb_lt2; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt2 = syn->sp.dlt_poc_msb_prsnt2; + regs->reg0247_synt_long_refm1.dlt_poc_msb_cycl2 = syn->sp.dlt_poc_msb_cycl2; + regs->reg0240_synt_sli1.lst_entry_l0 = syn->sp.lst_entry_l0; + regs->reg0239_synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + return; +} +static void vepu540c_h265_set_me_regs(H265eV540cHalContext *ctx, H265eSyntax_new *syn, hevc_vepu540c_base *regs) +{ + + RK_S32 x_gmv = 0; + RK_S32 y_gmv = 0; + RK_S32 srch_lftw, srch_rgtw, srch_uph, srch_dwnh; + RK_S32 frm_sta = 0, frm_end = 0, pic_w = 0; + RK_S32 pic_wdt_align = ((regs->reg0196_enc_rsl.pic_wd8_m1 + 1) * 8 + 31) / 32 ; + + + regs->reg0220_me_rnge.cime_srch_dwnh = 15; + regs->reg0220_me_rnge.cime_srch_uph = 14; + regs->reg0220_me_rnge.cime_srch_rgtw = 12; + regs->reg0220_me_rnge.cime_srch_lftw = 12; + regs->reg0221_me_cfg.rme_srch_h = 3; + regs->reg0221_me_cfg.rme_srch_v = 3; + + regs->reg0221_me_cfg.srgn_max_num = 72; + regs->reg0221_me_cfg.cime_dist_thre = 1024; + regs->reg0221_me_cfg.rme_dis = 0; + regs->reg0221_me_cfg.fme_dis = 0; + regs->reg0220_me_rnge.dlt_frm_num = 0x1; + srch_lftw = regs->reg0220_me_rnge.cime_srch_lftw * 4; + srch_rgtw = regs->reg0220_me_rnge.cime_srch_rgtw * 4; + srch_uph = regs->reg0220_me_rnge.cime_srch_uph * 2; + srch_dwnh = regs->reg0220_me_rnge.cime_srch_dwnh * 2; + + if (syn->pp.sps_temporal_mvp_enabled_flag && + (ctx->frame_type != INTRA_FRAME)) { + if (ctx->last_frame_type == INTRA_FRAME) { + regs->reg0222_me_cach.colmv_load = 0; + } else { + regs->reg0222_me_cach.colmv_load = 1; + } + regs->reg0222_me_cach.colmv_stor = 1; + } + // calc cme_linebuf_w + { + if (x_gmv - srch_lftw < 0) { + frm_sta = (x_gmv - srch_lftw - 15) / 16; + } else { + frm_sta = (x_gmv - srch_lftw) / 16; + } + if (x_gmv + srch_rgtw < 0) { + frm_end = pic_wdt_align - 1 + (x_gmv + srch_rgtw) / 16; + } else { + frm_end = pic_wdt_align - 1 + (x_gmv + srch_rgtw + 15) / 16; + } + + if (frm_sta < 0) { + frm_sta = 0; + } else if (frm_sta > pic_wdt_align - 1) { + frm_sta = pic_wdt_align - 1; + } + frm_end = mpp_clip(frm_end, 0, pic_wdt_align - 1); + pic_w = (frm_end - frm_sta + 1) * 32; + regs->reg0222_me_cach.cme_linebuf_w = pic_w / 32; + } + + // calc cime_hgt_rama and cime_size_rama + { + RK_U32 rama_size = 1796; + RK_U32 ramb_h; + RK_U32 ctu_2_h = 4; + RK_U32 ctu_8_w = 1 ; + RK_U32 cur_srch_8_w, cur_srch_2_h, cur_srch_h; + + if ((y_gmv % 8 - srch_uph % 8) < 0) { + cur_srch_2_h = (8 + (y_gmv % 8 - srch_uph % 8) % 8 + srch_uph + srch_dwnh) / 2 + ctu_2_h; + } else { + cur_srch_2_h = ((y_gmv % 8 - srch_uph % 8) % 8 + srch_uph + srch_dwnh) / 2 + ctu_2_h; + } + regs->reg0222_me_cach.cime_size_rama = (cur_srch_2_h + 3) / 4 * 4; + + if ((x_gmv % 8 - srch_lftw % 8) < 0) { + cur_srch_8_w = (8 + (x_gmv % 8 - srch_lftw % 8) % 8 + srch_lftw + srch_rgtw + 7) / 8 + ctu_8_w; + } else { + cur_srch_8_w = ((x_gmv % 8 - srch_lftw % 8) % 8 + srch_lftw + srch_rgtw + 7) / 8 + ctu_8_w; + } + + cur_srch_h = ctu_2_h; + ramb_h = cur_srch_2_h; + while ((rama_size > ((cur_srch_h - ctu_2_h) * regs->reg0222_me_cach.cme_linebuf_w + (ramb_h * cur_srch_8_w))) + && (cur_srch_h < regs->reg0222_me_cach.cime_size_rama)) { + cur_srch_h = cur_srch_h + ctu_2_h; + if (ramb_h > ctu_2_h * 2) { + ramb_h = ramb_h - ctu_2_h; + } else { + ramb_h = ctu_2_h; + } + } + + if (cur_srch_2_h == ctu_2_h * 2) { + cur_srch_h = cur_srch_h + ctu_2_h; + ramb_h = ctu_2_h; + } + + if (rama_size < ((cur_srch_h - ctu_2_h) * regs->reg0222_me_cach.cme_linebuf_w + (ramb_h * cur_srch_8_w))) { + cur_srch_h = cur_srch_h - ctu_2_h; + } + + regs->reg0222_me_cach.cime_size_rama = ((cur_srch_h - ctu_2_h) * regs->reg0222_me_cach.cme_linebuf_w + ctu_2_h * cur_srch_8_w) / 4; + regs->reg0222_me_cach.cime_hgt_rama = cur_srch_h / 2; + regs->reg0222_me_cach.fme_prefsu_en = 1; + } + +} + +void vepu540c_h265_set_hw_address(H265eV540cHalContext *ctx, hevc_vepu540c_base *regs, HalEncTask *task) +{ + HalEncTask *enc_task = task; + HalBuf *recon_buf, *ref_buf; + MppBuffer md_info_buf = enc_task->md_info; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + + hal_h265e_enter(); + + regs->reg0160_adr_src0 = mpp_buffer_get_fd(enc_task->input); + regs->reg0161_adr_src1 = regs->reg0160_adr_src0; + regs->reg0162_adr_src2 = regs->reg0160_adr_src0; + + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.recon_pic.slot_idx); + ref_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.ref_pic.slot_idx); + + if (!syn->sp.non_reference_flag) { + regs->reg0163_rfpw_h_addr = mpp_buffer_get_fd(recon_buf->buf[0]); + regs->reg0164_rfpw_b_addr = regs->reg0163_rfpw_h_addr; + mpp_dev_set_reg_offset(ctx->dev, 164, ctx->fbc_header_len); + } + regs->reg0165_rfpr_h_addr = mpp_buffer_get_fd(ref_buf->buf[0]); + regs->reg0166_rfpr_b_addr = regs->reg0165_rfpr_h_addr; + regs->reg0167_cmvw_addr = mpp_buffer_get_fd(recon_buf->buf[2]); + regs->reg0168_cmvr_addr = mpp_buffer_get_fd(ref_buf->buf[2]); + regs->reg0169_dspw_addr = mpp_buffer_get_fd(recon_buf->buf[1]); + regs->reg0170_dspr_addr = mpp_buffer_get_fd(ref_buf->buf[1]); + + mpp_dev_set_reg_offset(ctx->dev, 166, ctx->fbc_header_len); + + if (md_info_buf) { + regs->reg0192_enc_pic.mei_stor = 1; + regs->reg0171_meiw_addr = mpp_buffer_get_fd(md_info_buf); + } else { + regs->reg0192_enc_pic.mei_stor = 0; + regs->reg0171_meiw_addr = 0; + } + + regs->reg0172_bsbt_addr = mpp_buffer_get_fd(enc_task->output); + /* TODO: stream size relative with syntax */ + regs->reg0173_bsbb_addr = regs->reg0172_bsbt_addr; + regs->reg0175_bsbr_addr = regs->reg0172_bsbt_addr; + regs->reg0174_adr_bsbs = regs->reg0172_bsbt_addr; + + regs->reg0180_adr_rfpt_h = 0xffffffff; + regs->reg0181_adr_rfpb_h = 0; + regs->reg0182_adr_rfpt_b = 0xffffffff; + regs->reg0183_adr_rfpb_b = 0; + + + mpp_dev_set_reg_offset(ctx->dev, 174, mpp_packet_get_length(task->packet)); + mpp_dev_set_reg_offset(ctx->dev, 172, mpp_buffer_get_size(enc_task->output)); + + regs->reg0204_pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg0204_pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); +} + +static void setup_vepu540c_ext_line_buf(H265eV540cHalContext *ctx, H265eV540cRegSet *regs) +{ + if (ctx->ext_line_buf) { + RK_S32 fd = mpp_buffer_get_fd(ctx->ext_line_buf); + + regs->reg_base.reg0179_adr_ebufb = fd; + regs->reg_base.reg0178_adr_ebuft = fd; + mpp_dev_set_reg_offset(ctx->dev, 178, ctx->ext_line_buf_size); + } else { + regs->reg_base.reg0179_adr_ebufb = 0; + regs->reg_base.reg0178_adr_ebuft = 0; + } +} + +static void vepu540c_h265_set_split(H265eV540cRegSet *regs, MppEncCfgSet *enc_cfg, RK_U32 title_en) +{ + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h265e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_base.reg0216_sli_splt.sli_splt = 0; + regs->reg_base.reg0216_sli_splt.sli_splt_mode = 0; + regs->reg_base.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_base.reg0216_sli_splt.sli_max_num_m1 = 0; + regs->reg_base.reg0216_sli_splt.sli_flsh = 0; + regs->reg_base.reg0218_sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.reg0217_sli_byte.sli_splt_byte = 0; + regs->reg_base.reg0192_enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_base.reg0216_sli_splt.sli_splt = 1; + regs->reg_base.reg0216_sli_splt.sli_splt_mode = 0; + regs->reg_base.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_base.reg0216_sli_splt.sli_max_num_m1 = 500; + regs->reg_base.reg0216_sli_splt.sli_flsh = 1; + regs->reg_base.reg0218_sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.reg0217_sli_byte.sli_splt_byte = cfg->split_arg; + regs->reg_base.reg0192_enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.reg0008_int_en.vslc_done_en = regs->reg_base.reg0192_enc_pic.slen_fifo; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + RK_U32 mb_w = MPP_ALIGN(enc_cfg->prep.width, 64) / 64; + RK_U32 mb_h = MPP_ALIGN(enc_cfg->prep.height, 64) / 64; + RK_U32 slice_num = 0; + + if (title_en) + mb_w = mb_w / 2; + + slice_num = (mb_w * mb_h + cfg->split_arg - 1) / cfg->split_arg; + + regs->reg_base.reg0216_sli_splt.sli_splt = 1; + regs->reg_base.reg0216_sli_splt.sli_splt_mode = 1; + regs->reg_base.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_base.reg0216_sli_splt.sli_max_num_m1 = 500; + regs->reg_base.reg0216_sli_splt.sli_flsh = 1; + regs->reg_base.reg0218_sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg_base.reg0217_sli_byte.sli_splt_byte = 0; + regs->reg_base.reg0192_enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + + if ((cfg->split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) || + (regs->reg_base.reg0192_enc_pic.slen_fifo && (slice_num > VEPU540C_SLICE_FIFO_LEN))) + regs->reg_ctl.reg0008_int_en.vslc_done_en = 1 ; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h265e_dbg_func("leave\n"); +} + +MPP_RET hal_h265e_v540c_gen_regs(void *hal, HalEncTask *task) +{ + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + HalEncTask *enc_task = task; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + H265eV540cRegSet *regs = ctx->regs; + RK_U32 pic_width_align8, pic_height_align8; + RK_S32 pic_wd32, pic_h32; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + hevc_vepu540c_control_cfg *reg_ctl = ®s->reg_ctl; + hevc_vepu540c_base *reg_base = ®s->reg_base; + hevc_vepu540c_rc_roi *reg_klut = ®s->reg_rc_roi; + + hal_h265e_enter(); + pic_width_align8 = (syn->pp.pic_width + 7) & (~7); + pic_height_align8 = (syn->pp.pic_height + 7) & (~7); + pic_wd32 = (syn->pp.pic_width + 31) / 32; + pic_h32 = (syn->pp.pic_height + 31) / 32; + + hal_h265e_dbg_simple("frame %d | type %d | start gen regs", + ctx->frame_cnt, ctx->frame_type); + + memset(regs, 0, sizeof(H265eV540cRegSet)); + + reg_ctl->reg0004_enc_strt.lkt_num = 0; + reg_ctl->reg0004_enc_strt.vepu_cmd = ctx->enc_mode; + reg_ctl->reg0005_enc_clr.safe_clr = 0x0; + reg_ctl->reg0005_enc_clr.force_clr = 0x0; + + reg_ctl->reg0008_int_en.enc_done_en = 1; + reg_ctl->reg0008_int_en.lkt_node_done_en = 1; + reg_ctl->reg0008_int_en.sclr_done_en = 1; + reg_ctl->reg0008_int_en.vslc_done_en = 0; + reg_ctl->reg0008_int_en.vbsf_oflw_en = 1; + reg_ctl->reg0008_int_en.vbuf_lens_en = 1; + reg_ctl->reg0008_int_en.enc_err_en = 1; + reg_ctl->reg0008_int_en.dvbm_fcfg_en = 1; + reg_ctl->reg0008_int_en.wdg_en = 1; + reg_ctl->reg0008_int_en.lkt_err_int_en = 0; + reg_ctl->reg0008_int_en.lkt_err_stop_en = 1; + reg_ctl->reg0008_int_en.lkt_force_stop_en = 1; + reg_ctl->reg0008_int_en.jslc_done_en = 1; + reg_ctl->reg0008_int_en.jbsf_oflw_en = 1; + reg_ctl->reg0008_int_en.jbuf_lens_en = 1; + reg_ctl->reg0008_int_en.dvbm_dcnt_en = 1; + + reg_ctl->reg0012_dtrns_map.jpeg_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.src_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.meiw_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.bsw_bus_edin = 0x7; + reg_ctl->reg0012_dtrns_map.lktr_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.roir_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.lktw_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.rec_nfbc_bus_edin = 0x0; + /* enable rdo clk gating */ + { + RK_U32 *rdo_ckg = (RK_U32*)®_ctl->reg0022_rdo_ckg; + + *rdo_ckg = 0xffffffff; + } +// reg_ctl->reg0013_dtrns_cfg.dspr_otsd = (ctx->frame_type == INTER_P_FRAME); + reg_ctl->reg0013_dtrns_cfg.axi_brsp_cke = 0x0; + reg_ctl->reg0014_enc_wdg.vs_load_thd = 0x1fffff; + reg_ctl->reg0014_enc_wdg.rfp_load_thd = 0xff; + + reg_ctl->reg0021_func_en.cke = 1; + reg_ctl->reg0021_func_en.resetn_hw_en = 1; + reg_ctl->reg0021_func_en.enc_done_tmvp_en = 1; + + reg_base->reg0196_enc_rsl.pic_wd8_m1 = pic_width_align8 / 8 - 1; + reg_base->reg0197_src_fill.pic_wfill = ((syn->pp.pic_width & 0x7) != 0) + ? (8 - (syn->pp.pic_width & 0x7)) : 0; + reg_base->reg0196_enc_rsl.pic_hd8_m1 = pic_height_align8 / 8 - 1; + reg_base->reg0197_src_fill.pic_hfill = ((syn->pp.pic_height & 0x7) != 0) + ? (8 - (syn->pp.pic_height & 0x7)) : 0; + + reg_base->reg0192_enc_pic.enc_stnd = 1; //H265 + reg_base->reg0192_enc_pic.cur_frm_ref = !syn->sp.non_reference_flag; //current frame will be refered + reg_base->reg0192_enc_pic.bs_scp = 1; + reg_base->reg0192_enc_pic.log2_ctu_num = mpp_ceil_log2(pic_wd32 * pic_h32); + + reg_base->reg0203_src_proc.src_mirr = 0; + reg_base->reg0203_src_proc.src_rot = 0; + + reg_klut->klut_ofst.chrm_klut_ofst = (ctx->frame_type == INTRA_FRAME) ? 6 : + (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 9 : 6); + reg_klut->klut_ofst.inter_chrm_dist_multi = 4; + reg_base->reg0248_sao_cfg.sao_lambda_multi = 5; + + vepu540c_h265_set_me_regs(ctx, syn, reg_base); + + reg_base->reg0232_rdo_cfg.chrm_spcl = 0; + reg_base->reg0232_rdo_cfg.cu_inter_e = 0x0092; + reg_base->reg0232_rdo_cfg.cu_intra_e = 0xe; + reg_base->reg0232_rdo_cfg.lambda_qp_use_avg_cu16_flag = 1; + reg_base->reg0232_rdo_cfg.yuvskip_calc_en = 1; + reg_base->reg0232_rdo_cfg.atf_e = 1; + reg_base->reg0232_rdo_cfg.atr_e = 1; + + if (syn->pp.num_long_term_ref_pics_sps) { + reg_base->reg0232_rdo_cfg.ltm_col = 0; + reg_base->reg0232_rdo_cfg.ltm_idx0l0 = 1; + } else { + reg_base->reg0232_rdo_cfg.ltm_col = 0; + reg_base->reg0232_rdo_cfg.ltm_idx0l0 = 0; + } + + reg_base->reg0232_rdo_cfg.ccwa_e = 1; + reg_base->reg0232_rdo_cfg.scl_lst_sel = syn->pp.scaling_list_enabled_flag; + reg_base->reg0236_synt_nal.nal_unit_type = h265e_get_nal_type(&syn->sp, ctx->frame_type); + + vepu540c_h265_set_hw_address(ctx, reg_base, task); + vepu540c_h265_set_pp_regs(regs, fmt, &ctx->cfg->prep); + vepu540c_h265_set_rc_regs(ctx, regs, task); + vepu540c_h265_set_slice_regs(syn, reg_base); + vepu540c_h265_set_ref_regs(syn, reg_base); + vepu540c_h265_set_patch_info(ctx->dev, syn, (VepuFmt)fmt->format, enc_task); + setup_vepu540c_ext_line_buf(ctx, ctx->regs); + vepu540c_h265_set_split(regs, ctx->cfg, syn->pp.tiles_enabled_flag); + + /* ROI configure */ + if (ctx->roi_data) + vepu540c_set_roi(®s->reg_rc_roi.roi_cfg, ctx->roi_data, + ctx->cfg->prep.width, ctx->cfg->prep.height); + /*paramet cfg*/ + vepu540c_h265_global_cfg_set(ctx, regs); + + ctx->frame_num++; + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v540c_start(void *hal, HalEncTask *enc_task) +{ + MPP_RET ret = MPP_OK; + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + RK_U32 *regs = (RK_U32*)ctx->regs; + H265eV540cRegSet *hw_regs = ctx->regs; + H265eV540cStatusElem *reg_out = (H265eV540cStatusElem *)ctx->reg_out[0]; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + RK_U32 i = 0; + hal_h265e_enter(); + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + cfg.reg = (RK_U32*)&hw_regs->reg_ctl; + cfg.size = sizeof(hevc_vepu540c_control_cfg); + cfg.offset = VEPU540C_CTL_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_CTL_REGS) { + regs = (RK_U32*)&hw_regs->reg_ctl; + for (i = 0; i < sizeof(hevc_vepu540c_control_cfg) / 4; i++) { + hal_h265e_dbg_ctl("ctl reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_base; + cfg.size = sizeof(hevc_vepu540c_base); + cfg.offset = VEPU540C_BASE_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_REGS) { + regs = (RK_U32*)(&hw_regs->reg_base); + for (i = 0; i < 32; i++) { + hal_h265e_dbg_regs("hw add cfg reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + regs += 32; + for (i = 0; i < (sizeof(hevc_vepu540c_base) - 128) / 4; i++) { + hal_h265e_dbg_regs("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + cfg.reg = &hw_regs->reg_rc_roi; + cfg.size = sizeof(hevc_vepu540c_rc_roi); + cfg.offset = VEPU540C_RCROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_RCKUT_REGS) { + regs = (RK_U32*)&hw_regs->reg_rc_roi; + for (i = 0; i < sizeof(hevc_vepu540c_rc_roi) / 4; i++) { + hal_h265e_dbg_rckut("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_wgt; + cfg.size = sizeof(hevc_vepu540c_wgt); + cfg.offset = VEPU540C_WEG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_wgt; + for (i = 0; i < sizeof(hevc_vepu540c_wgt) / 4; i++) { + hal_h265e_dbg_wgt("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_rdo; + cfg.size = sizeof(vepu540c_rdo_cfg); + cfg.offset = VEPU540C_RDOCFG_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU540C_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->st; + cfg1.size = sizeof(H265eV540cStatusElem) - 4; + cfg1.offset = VEPU540C_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + hal_h265e_leave(); + return ret; +} + +static MPP_RET vepu540c_h265_set_feedback(H265eV540cHalContext *ctx, HalEncTask *enc_task) +{ + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&enc_task->rc_task->info; + vepu540c_h265_fbk *fb = &ctx->feedback; + MppEncCfgSet *cfg = ctx->cfg; + RK_S32 mb64_num = ((cfg->prep.width + 63) / 64) * ((cfg->prep.height + 63) / 64); + RK_S32 mb8_num = (mb64_num << 6); + RK_S32 mb4_num = (mb8_num << 2); + H265eV540cStatusElem *elem = (H265eV540cStatusElem *)ctx->reg_out[0]; + vepu540c_hw_status hw_status = elem->hw_status; + + hal_h265e_enter(); + + fb->qp_sum += elem->st.qp_sum; + + fb->out_strm_size += elem->st.bs_lgth_l32; + + fb->sse_sum += (RK_S64)(elem->st.sse_h32 << 16) + + (elem->st.st_sse_bsl.sse_l16 & 0xffff) ; + + fb->hw_status = hw_status; + hal_h265e_dbg_detail("hw_status: 0x%08x", hw_status.val); + if (hw_status.int_sta.enc_done_sta) + hal_h265e_dbg_detail("RKV_ENC_INT_ENC_DONE"); + + if (hw_status.int_sta.lkt_node_done_sta) + hal_h265e_dbg_detail("RKV_ENC_INT_LKT_NODE_DONE"); + + if (hw_status.int_sta.sclr_done_sta) + hal_h265e_dbg_detail("RKV_ENC_INT_SCLR_DONE"); + + if (hw_status.int_sta.vslc_done_sta) + hal_h265e_dbg_detail("RKV_ENC_INT_VSLC_DONE"); + + if (hw_status.int_sta.vbsf_oflw_sta) + hal_h265e_err("RKV_ENC_INT_VBSF_OFLOW"); + + if (hw_status.int_sta.vbuf_lens_sta) + hal_h265e_err("RKV_ENC_INT_VBUF_LENS"); + + if (hw_status.int_sta.enc_err_sta) + hal_h265e_err("RKV_ENC_INT_ENC_ERR"); + + if (hw_status.int_sta.dvbm_fcfg_sta) + hal_h265e_err("RKV_ENC_INT_DVBM_FCFG"); + + if (hw_status.int_sta.wdg_sta) + hal_h265e_err("RKV_ENC_INT_WDG_TIMEOUT"); + + // fb->st_madi += elem->st.madi; + //fb->st_madp += elem->st.madp; + fb->st_mb_num += elem->st.st_bnum_b16.num_b16; + // fb->st_ctu_num += elem->st.st_bnum_cme.num_ctu; + + fb->st_lvl64_inter_num += elem->st.st_pnum_p64.pnum_p64; + fb->st_lvl32_inter_num += elem->st.st_pnum_p32.pnum_p32; + fb->st_lvl32_intra_num += elem->st.st_pnum_i32.pnum_i32; + fb->st_lvl16_inter_num += elem->st.st_pnum_p16.pnum_p16; + fb->st_lvl16_intra_num += elem->st.st_pnum_i16.pnum_i16; + fb->st_lvl8_inter_num += elem->st.st_pnum_p8.pnum_p8; + fb->st_lvl8_intra_num += elem->st.st_pnum_i8.pnum_i8; + fb->st_lvl4_intra_num += elem->st.st_pnum_i4.pnum_i4; + memcpy(&fb->st_cu_num_qp[0], &elem->st.st_b8_qp, 52 * sizeof(RK_U32)); + + hal_rc_ret->bit_real += fb->out_strm_size * 8; + + if (fb->st_mb_num) { + fb->st_madi = fb->st_madi / fb->st_mb_num; + } else { + fb->st_madi = 0; + } + if (fb->st_ctu_num) { + fb->st_madp = fb->st_madp / fb->st_ctu_num; + } else { + fb->st_madp = 0; + } + + if (mb4_num > 0) + hal_rc_ret->iblk4_prop = ((((fb->st_lvl4_intra_num + fb->st_lvl8_intra_num) << 2) + + (fb->st_lvl16_intra_num << 4) + + (fb->st_lvl32_intra_num << 6)) << 8) / mb4_num; + + if (mb64_num > 0) { + /* + hal_cfg[k].inter_lv8_prop = ((fb->st_lvl8_inter_num + (fb->st_lvl16_inter_num << 2) + + (fb->st_lvl32_inter_num << 4) + + (fb->st_lvl64_inter_num << 6)) << 8) / mb8_num;*/ + + hal_rc_ret->quality_real = fb->qp_sum / mb8_num; + // hal_cfg[k].sse = fb->sse_sum / mb64_num; + } + + hal_rc_ret->madi = fb->st_madi; + hal_rc_ret->madp = fb->st_madp; + hal_h265e_leave(); + return MPP_OK; +} + + +//#define DUMP_DATA +MPP_RET hal_h265e_v540c_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + HalEncTask *enc_task = task; + H265eV540cStatusElem *elem = (H265eV540cStatusElem *)ctx->reg_out; + hal_h265e_enter(); + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + +#ifdef DUMP_DATA + static FILE *fp_fbd = NULL; + static FILE *fp_fbh = NULL; + static FILE *fp_dws = NULL; + HalBuf *recon_buf; + static RK_U32 frm_num = 0; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.recon_pic.slot_idx); + char file_name[20] = ""; + size_t rec_size = mpp_buffer_get_size(recon_buf->buf[0]); + size_t dws_size = mpp_buffer_get_size(recon_buf->buf[1]); + + void *ptr = mpp_buffer_get_ptr(recon_buf->buf[0]); + void *dws_ptr = mpp_buffer_get_ptr(recon_buf->buf[1]); + + sprintf(&file_name[0], "fbd%d.bin", frm_num); + if (fp_fbd != NULL) { + fclose(fp_fbd); + fp_fbd = NULL; + } else { + fp_fbd = fopen(file_name, "wb+"); + } + if (fp_fbd) { + fwrite(ptr + ctx->fbc_header_len, 1, rec_size - ctx->fbc_header_len, fp_fbd); + fflush(fp_fbd); + } + + sprintf(&file_name[0], "fbh%d.bin", frm_num); + + if (fp_fbh != NULL) { + fclose(fp_fbh); + fp_fbh = NULL; + } else { + fp_fbh = fopen(file_name, "wb+"); + } + + if (fp_fbh) { + fwrite(ptr , 1, ctx->fbc_header_len, fp_fbh); + fflush(fp_fbh); + } + + + sprintf(&file_name[0], "dws%d.bin", frm_num); + + if (fp_dws != NULL) { + fclose(fp_dws); + fp_dws = NULL; + } else { + fp_dws = fopen(file_name, "wb+"); + } + + if (fp_dws) { + fwrite(dws_ptr , 1, dws_size, fp_dws); + fflush(fp_dws); + } + frm_num++; +#endif + if (ret) + mpp_err_f("poll cmd failed %d status %d \n", ret, elem->hw_status.val); + + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_v540c_get_task(void *hal, HalEncTask *task) +{ + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + MppFrame frame = task->frame; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h265e_enter(); + + if (vepu540c_h265_setup_hal_bufs(ctx)) { + hal_h265e_err("vepu541_h265_allocate_buffers failed, free buffers and return\n"); + task->flags.err |= HAL_ENC_TASK_ERR_ALLOC; + return MPP_ERR_MALLOC; + } + + ctx->last_frame_type = ctx->frame_type; + if (frm_status->is_intra) { + ctx->frame_type = INTRA_FRAME; + } else { + ctx->frame_type = INTER_P_FRAME; + } + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + } + memset(&ctx->feedback, 0, sizeof(vepu540c_h265_fbk)); + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v540c_ret_task(void *hal, HalEncTask *task) +{ + H265eV540cHalContext *ctx = (H265eV540cHalContext *)hal; + HalEncTask *enc_task = task; + vepu540c_h265_fbk *fb = &ctx->feedback; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + + hal_h265e_enter(); + + vepu540c_h265_set_feedback(ctx, enc_task); + mpp_buffer_sync_partial_begin(enc_task->output, offset, fb->out_strm_size); + hal_h265e_amend_temporal_id(task, fb->out_strm_size); + + rc_info->sse = fb->sse_sum; + rc_info->lvl64_inter_num = fb->st_lvl64_inter_num; + rc_info->lvl32_inter_num = fb->st_lvl32_inter_num; + rc_info->lvl16_inter_num = fb->st_lvl16_inter_num; + rc_info->lvl8_inter_num = fb->st_lvl8_inter_num; + rc_info->lvl32_intra_num = fb->st_lvl32_intra_num; + rc_info->lvl16_intra_num = fb->st_lvl16_intra_num; + rc_info->lvl8_intra_num = fb->st_lvl8_intra_num; + rc_info->lvl4_intra_num = fb->st_lvl4_intra_num; + + enc_task->hw_length = fb->out_strm_size; + enc_task->length += fb->out_strm_size; + + hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); + + hal_h265e_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_h265e_vepu540c = { + .name = "hal_h265e_v540c", + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(H265eV540cHalContext), + .flag = 0, + .init = hal_h265e_v540c_init, + .deinit = hal_h265e_v540c_deinit, + .prepare = hal_h265e_vepu540c_prepare, + .get_task = hal_h265e_v540c_get_task, + .gen_regs = hal_h265e_v540c_gen_regs, + .start = hal_h265e_v540c_start, + .wait = hal_h265e_v540c_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h265e_v540c_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h265e_vepu540c) diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu540c.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu540c.h new file mode 100644 index 000000000..43d992984 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu540c.h @@ -0,0 +1,24 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_VEPU540C_H +#define HAL_H265E_VEPU540C_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h265e_vepu540c; + +#endif /* HAL_H265E_VEPU540C_H */ diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu540c_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu540c_reg.h new file mode 100644 index 000000000..90b551c21 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu540c_reg.h @@ -0,0 +1,1085 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_VEPU540C_REG_H +#define HAL_H265E_VEPU540C_REG_H + +#include "rk_type.h" +#include "vepu540c_common.h" +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct HevcVepu540cControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 h264_cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 reserved : 2; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } reg0001_version; + + /* 0x4 - 0xc */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 3; + RK_U32 reserved : 21; + } reg0004_enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } reg0005_enc_clr; + + /* 0x18 */ + struct { + RK_U32 vswm_lcnt_soft : 14; + RK_U32 vswm_fcnt_soft : 8; + RK_U32 reserved : 2; + RK_U32 dvbm_ack_soft : 1; + RK_U32 dvbm_ack_sel : 1; + RK_U32 dvbm_inf_sel : 1; + RK_U32 reserved1 : 5; + } reg0006_vs_ldly; + + /* 0x1c */ + RK_U32 reserved007; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 vslc_done_en : 1; + RK_U32 vbsf_oflw_en : 1; + RK_U32 vbuf_lens_en : 1; + RK_U32 enc_err_en : 1; + RK_U32 dvbm_fcfg_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 lkt_err_stop_en : 1; + RK_U32 lkt_force_stop_en : 1; + RK_U32 jslc_done_en : 1; + RK_U32 jbsf_oflw_en : 1; + RK_U32 jbuf_lens_en : 1; + RK_U32 dvbm_dcnt_en : 1; + RK_U32 reserved : 16; + } reg0008_int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 vslc_done_msk : 1; + RK_U32 vbsf_oflw_msk : 1; + RK_U32 vbuf_lens_msk : 1; + RK_U32 enc_err_msk : 1; + RK_U32 dvbm_fcfg_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_int_msk : 1; + RK_U32 lkt_err_stop_msk : 1; + RK_U32 lkt_force_stop_msk : 1; + RK_U32 jslc_done_msk : 1; + RK_U32 jbsf_oflw_msk : 1; + RK_U32 jbuf_lens_msk : 1; + RK_U32 dvbm_dcnt_msk : 1; + RK_U32 reserved : 16; + } reg0009_int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 vslc_done_clr : 1; + RK_U32 vbsf_oflw_clr : 1; + RK_U32 vbuf_lens_clr : 1; + RK_U32 enc_err_clr : 1; + RK_U32 dvbm_fcfg_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_int_clr : 1; + RK_U32 lkt_err_stop_clr : 1; + RK_U32 lkt_force_stop_clr : 1; + RK_U32 jslc_done_clr : 1; + RK_U32 jbsf_oflw_clr : 1; + RK_U32 jbuf_lens_clr : 1; + RK_U32 dvbm_dcnt_clr : 1; + RK_U32 reserved : 16; + } reg0010_int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 vslc_done_sta : 1; + RK_U32 vbsf_oflw_sta : 1; + RK_U32 vbuf_lens_sta : 1; + RK_U32 enc_err_sta : 1; + RK_U32 dvbm_fcfg_sta : 1; + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_int_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + RK_U32 jslc_done_sta : 1; + RK_U32 jbsf_oflw_sta : 1; + RK_U32 jbuf_lens_sta : 1; + RK_U32 dvbm_dcnt_sta : 1; + RK_U32 reserved : 16; + } reg0011_int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 jpeg_bus_edin : 4; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 4; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 rec_nfbc_bus_edin : 4; + } reg0012_dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 reserved : 16; + RK_U32 axi_brsp_cke : 10; + RK_U32 reserved1 : 6; + } reg0013_dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 rfp_load_thd : 8; + } reg0014_enc_wdg; + + /* 0x0000003c reg15 */ + struct { + RK_U32 hurry_en : 1; + RK_U32 hurry_low : 3; + RK_U32 hurry_mid : 3; + RK_U32 hurry_high : 3; + RK_U32 reserved : 22; + } reg0015_qos_cfg; + + /* 0x00000040 reg16 */ + struct { + RK_U32 qos_period : 16; + RK_U32 reserved : 16; + } reg0016_qos_perd; + + /* 0x00000044 reg17 */ + RK_U32 reg0017_hurry_thd_low; + + /* 0x00000048 reg18 */ + RK_U32 reg0018_hurry_thd_mid; + + /* 0x0000004c reg19 */ + RK_U32 reg0019_hurry_thd_high; + + /* 0x00000050 reg20 */ + struct { + RK_U32 idle_en_core : 1; + RK_U32 idle_en_axi : 1; + RK_U32 idle_en_ahb : 1; + RK_U32 reserved : 29; + } reg0020_enc_idle_en; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 enc_done_tmvp_en : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 link_err_stop : 1; + RK_U32 reserved : 27; + } reg0021_func_en; + + /* 0x00000058 reg22 */ + struct { + RK_U32 recon32_ckg : 1; + RK_U32 iqit32_ckg : 1; + RK_U32 q32_ckg : 1; + RK_U32 t32_ckg : 1; + RK_U32 cabac32_ckg : 1; + RK_U32 recon16_ckg : 1; + RK_U32 iqit16_ckg : 1; + RK_U32 q16_ckg : 1; + RK_U32 t16_ckg : 1; + RK_U32 cabac16_ckg : 1; + RK_U32 recon8_ckg : 1; + RK_U32 iqit8_ckg : 1; + RK_U32 q8_ckg : 1; + RK_U32 t8_ckg : 1; + RK_U32 cabac8_ckg : 1; + RK_U32 recon4_ckg : 1; + RK_U32 iqit4_ckg : 1; + RK_U32 q4_ckg : 1; + RK_U32 t4_ckg : 1; + RK_U32 cabac4_ckg : 1; + RK_U32 intra32_ckg : 1; + RK_U32 intra16_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 reserved : 7; + } reg0022_rdo_ckg; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } reg0023_enc_id; + + + /* 0x00000060 reg24 */ + struct { + RK_U32 dvbm_en : 1; + RK_U32 src_badr_sel : 1; + RK_U32 vinf_frm_match : 1; + RK_U32 reserved : 1; + RK_U32 vrsp_half_cycle : 4; + RK_U32 reserved1 : 24; + } reg0024_dvbm_cfg; + + /* 0x00000064 - 0x6c*/ + RK_U32 reg025_027[3]; + + /* 0x00000070*/ + struct { + RK_U32 reserved : 4; + RK_U32 lkt_addr : 28; + } reg0028_lkt_base_addr; + + /* 0x74 - 0xfc */ + RK_U32 reserved29_63[35]; + + struct { + RK_U32 node_core_id : 2; + RK_U32 node_int : 1; + RK_U32 reserved : 1; + RK_U32 task_id : 12; + RK_U32 reserved1 : 16; + } reg0064_lkt_node_cfg; + + /* 0x00000104 reg65 */ + struct { + RK_U32 pcfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_pcfg : 28; + } reg0065_lkt_addr_pcfg; + + /* 0x00000108 reg66 */ + struct { + RK_U32 rc_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_rc_cfg : 28; + } reg0066_lkt_addr_rc_cfg; + + /* 0x0000010c reg67 */ + struct { + RK_U32 par_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_par_cfg : 28; + } reg0067_lkt_addr_par_cfg; + + /* 0x00000110 reg68 */ + struct { + RK_U32 sqi_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_sqi_cfg : 28; + } reg0068_lkt_addr_sqi_cfg; + + /* 0x00000114 reg69 */ + struct { + RK_U32 scal_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_scal_cfg : 28; + } reg0069_lkt_addr_scal_cfg; + + /* 0x00000118 reg70 */ + struct { + RK_U32 pp_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_pp_cfg : 28; + } reg0070_lkt_addr_osd_cfg; + + /* 0x0000011c reg71 */ + struct { + RK_U32 st_out_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_st : 28; + } reg0071_lkt_addr_st; + + /* 0x00000120 reg72 */ + struct { + RK_U32 nxt_node_vld : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_nxt : 28; + } reg0072_lkt_addr_nxt; +} hevc_vepu540c_control_cfg; + +/* class: buffer/video syntax */ +/* 0x00000280 reg160 - 0x000003f4 reg253*/ +typedef struct HevcVepu540cBase_t { + vepu540c_online online_addr; + /* 0x00000280 reg160 */ + RK_U32 reg0160_adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 reg0161_adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 reg0162_adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 reg0163_rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 reg0164_rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 reg0165_rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 reg0166_rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 reg0167_cmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 reg0168_cmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 reg0169_dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 reg0170_dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 reg0171_meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 reg0172_bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 reg0173_bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 reg0174_adr_bsbs; + + /* 0x000002bc reg175 */ + RK_U32 reg0175_bsbr_addr; + + /* 0x000002c0 reg176 */ + RK_U32 reg0176_lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 reg0177_lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 reg0178_adr_ebuft; + + /* 0x000002cc reg179 */ + RK_U32 reg0179_adr_ebufb; + + /* 0x000002d0 reg180 */ + RK_U32 reg0180_adr_rfpt_h; + + /* 0x000002d4 reg181 */ + RK_U32 reg0181_adr_rfpb_h; + + /* 0x000002d8 reg182 */ + RK_U32 reg0182_adr_rfpt_b; + + /* 0x000002dc reg183 */ + RK_U32 reg0183_adr_rfpb_b; + + /* 0x000002e0 reg184 */ + RK_U32 reg0184_adr_smr_rd; + + /* 0x000002e4 reg185 */ + RK_U32 reg0185_adr_smr_wr; + + /* 0x000002e8 reg186 */ + RK_U32 reg0186_adr_roir; + + /* 0x2ec - 0x2fc */ + RK_U32 reserved187_191[5]; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 reserved : 3; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur : 5; + RK_U32 log2_ctu_num : 5; + RK_U32 reserved1 : 6; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } reg0192_enc_pic; + + + /* 0x304 */ + RK_U32 reserved_193; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 reserved : 8; + RK_U32 ch_id : 2; + RK_U32 vrsp_rtn_en : 1; + RK_U32 reserved1 : 13; + } reg0194_dvbm_id; + + /* 0x0000030c reg195 */ + RK_U32 bsp_size; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } reg0196_enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } reg0197_src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_rcne : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved : 21; + } reg0198_src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } reg0199_src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } reg0200_src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } reg0201_src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } reg0202_src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 reserved : 26; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 reserved1 : 3; + } reg0203_src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } reg0204_pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 17; + RK_U32 reserved : 15; + } reg0205_src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } reg0206_src_strd1; + + /* 0x0000033c reg207 */ + struct { + RK_U32 pp_corner_filter_strength : 2; + RK_U32 reserved : 2; + RK_U32 pp_edge_filter_strength : 2; + RK_U32 reserved1 : 2; + RK_U32 pp_internal_filter_strength : 2; + RK_U32 reserved2 : 22; + } reg0207_src_flt_cfg; + + /* 0x340 - 0x34c */ + RK_U32 reserved208_211[4]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 aq_mode : 1; + RK_U32 reserved : 9; + RK_U32 rc_ctu_num : 20; + } reg212_rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } reg213_rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } reg214_rc_tgt; + + /* 0x35c */ + RK_U32 reserved_215; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } reg0216_sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } reg0217_sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } reg0218_sli_cnum; + + /* 0x0000036c reg219 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } reg0218_uvc_cfg; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cime_srch_dwnh : 4; + RK_U32 cime_srch_uph : 4; + RK_U32 cime_srch_rgtw : 4; + RK_U32 cime_srch_lftw : 4; + RK_U32 dlt_frm_num : 16; + } reg0220_me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 srgn_max_num : 7; + RK_U32 cime_dist_thre : 13; + RK_U32 rme_srch_h : 2; + RK_U32 rme_srch_v : 2; + RK_U32 rme_dis : 3; + RK_U32 reserved1 : 1; + RK_U32 fme_dis : 3; + RK_U32 reserved2 : 1; + } reg0221_me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cime_size_rama : 10; + RK_U32 reserved : 1; + RK_U32 cime_hgt_rama : 5; + RK_U32 reserved1 : 2; + RK_U32 cme_linebuf_w : 10; + RK_U32 fme_prefsu_en : 2; + RK_U32 colmv_stor : 1; + RK_U32 colmv_load : 1; + } reg0222_me_cach; + + + /* 0x37c - 0x39c */ + RK_U32 reserved223_231[9]; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 ltm_col : 1; + RK_U32 ltm_idx0l0 : 1; + RK_U32 chrm_spcl : 1; + RK_U32 cu_inter_e : 12; + RK_U32 reserved : 4; + RK_U32 cu_intra_e : 4; + RK_U32 ccwa_e : 1; + RK_U32 scl_lst_sel : 2; + RK_U32 lambda_qp_use_avg_cu16_flag : 1; + RK_U32 yuvskip_calc_en : 1; + RK_U32 atf_e : 1; + RK_U32 atr_e : 1; + RK_U32 reserved1 : 2; + } reg0232_rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 rdo_mark_mode : 9; + RK_U32 reserved : 23; + } reg0233_iprd_csts; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + + struct { + RK_U32 nal_unit_type : 6; + RK_U32 reserved : 26; + } reg0236_synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 smpl_adpt_ofst_e : 1; + RK_U32 num_st_ref_pic : 7; + RK_U32 lt_ref_pic_prsnt : 1; + RK_U32 num_lt_ref_pic : 6; + RK_U32 tmpl_mvp_e : 1; + RK_U32 log2_max_poc_lsb : 4; + RK_U32 strg_intra_smth : 1; + RK_U32 reserved : 11; + } reg0237_synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 dpdnt_sli_seg_en : 1; + RK_U32 out_flg_prsnt_flg : 1; + RK_U32 num_extr_sli_hdr : 3; + RK_U32 sgn_dat_hid_en : 1; + RK_U32 cbc_init_prsnt_flg : 1; + RK_U32 pic_init_qp : 6; + RK_U32 cu_qp_dlt_en : 1; + RK_U32 chrm_qp_ofst_prsn : 1; + RK_U32 lp_fltr_acrs_sli : 1; + RK_U32 dblk_fltr_ovrd_en : 1; + RK_U32 lst_mdfy_prsnt_flg : 1; + RK_U32 sli_seg_hdr_extn : 1; + RK_U32 cu_qp_dlt_depth : 2; + RK_U32 lpf_fltr_acrs_til : 1; + RK_U32 reserved : 10; + } reg0238_synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 mrg_up_flg : 1; + RK_U32 mrg_lft_flg : 1; + RK_U32 reserved : 1; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_l1_act : 2; + RK_U32 num_refidx_l0_act : 2; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_e : 1; + RK_U32 pic_out_flg : 1; + RK_U32 sli_type : 2; + RK_U32 sli_rsrv_flg : 7; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 sli_pps_id : 6; + RK_U32 no_out_pri_pic : 1; + } reg0239_synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 sp_tc_ofst_div2 : 4; + RK_U32 sp_beta_ofst_div2 : 4; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sp_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_U32 sli_cb_qp_ofst : 5; + RK_U32 sli_qp : 6; + RK_U32 max_mrg_cnd : 2; + RK_U32 reserved : 1; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 lst_entry_l0 : 4; + RK_U32 reserved1 : 1; + } reg0240_synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 sli_poc_lsb : 16; + RK_U32 sli_hdr_ext_len : 9; + RK_U32 reserved : 7; + } reg0241_synt_sli2; + + /* 0x000003c8 reg242 */ + + struct { + RK_U32 st_ref_pic_flg : 1; + RK_U32 poc_lsb_lt0 : 16; + RK_U32 lt_idx_sps : 5; + RK_U32 num_lt_pic : 2; + RK_U32 st_ref_pic_idx : 6; + RK_U32 num_lt_sps : 2; + } reg0242_synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 used_by_s0_flg : 4; + RK_U32 num_pos_pic : 1; + RK_U32 num_negative_pics : 5; + RK_U32 dlt_poc_msb_cycl0 : 16; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + } reg0243_synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 dlt_poc_s0_m10 : 16; + RK_U32 dlt_poc_s0_m11 : 16; + } reg0244_synt_refm2; + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } reg0245_synt_refm3; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } reg0246_synt_long_refm0; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } reg0247_synt_long_refm1; + + struct { + RK_U32 sao_lambda_multi : 3; + RK_U32 reserved : 29; + } reg0248_sao_cfg; + + /* 0x3e4 - 0x3ec */ + RK_U32 reserved249_251[3]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 tile_w_m1 : 8; + RK_U32 reserved : 8; + RK_U32 tile_h_m1 : 8; + RK_U32 reserved1 : 7; + RK_U32 tile_en : 1; + } reg0252_tile_cfg; + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 8; + RK_U32 reserved : 8; + RK_U32 tile_y : 8; + RK_U32 reserved1 : 8; + } reg0253_tile_pos; + + /* 0x3f8 - 0x3fc */ + RK_U32 reserved254_255[2]; + + /* 0x00000400 reg256 - 0x00000480 reg288 */ + Vepu540cJpegReg jpegReg; + +} hevc_vepu540c_base; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x000010e0 reg1080 */ +typedef struct HevcVepu540cRcRoi_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 24; + RK_U32 qpmap_mode : 2; + } roi_qthd3; + + /* 0x00001040 reg1040 */ + RK_U32 reserved_1040; + + /* 0x00001044 reg1041 - 0x00001050 reg1044 */ + RK_U8 aq_tthd[16]; + + /* + * 0x00001054 reg1045 - 0x00001060 reg1048 + * only low 6 bits is valid for per step. + */ + RK_U8 aq_step[16]; + + /* 0x00001064 reg1049 */ + struct { + RK_U32 madi_th0 : 8; + RK_U32 madi_th1 : 8; + RK_U32 madi_th2 : 8; + RK_U32 reserved : 8; + } madi_st_thd; + + /* 0x00001068 reg1050 */ + struct { + RK_U32 madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 madp_th1 : 12; + RK_U32 reserved1 : 4; + } madp_st_thd0; + + /* 0x0000106c reg1051 */ + struct { + RK_U32 madp_th2 : 12; + RK_U32 reserved : 20; + } madp_st_thd1; + + /* 0x1078 - 0x107c */ + RK_U32 reserved1052_1054[3]; + + /* 0x0000107c reg1055 */ + struct { + RK_U32 chrm_klut_ofst : 4; + RK_U32 reserved : 4; + RK_U32 inter_chrm_dist_multi : 6; + RK_U32 reserved1 : 18; + } klut_ofst; + + /*0x00001080 reg1056 - 0x0000110c reg1091 */ + Vepu540cRoiCfg roi_cfg; +} hevc_vepu540c_rc_roi; + +/* class: iprd/iprd_wgt/rdo_wgta/prei_dif*/ +/* 0x00001700 reg1472 - 0x00001cd4 reg1845 */ +typedef struct HevcVepu540cWgt_t { + /* 0x00001700 - 0x0000172c reg1472 */ + RK_U32 reserved1472_1483[12]; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 qnt_bias_i : 10; + RK_U32 qnt_bias_p : 10; + RK_U32 reserved : 12; + } reg1484_qnt_bias_comb; + + /* 0x1734 - 0x175c */ + RK_U32 reserved1485_1495[11]; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_pmv_num : 1; + RK_U32 cime_fuse : 1; + RK_U32 itp_mode : 1; + RK_U32 reserved : 1; + RK_U32 move_lambda : 4; + RK_U32 rime_lvl_mrg : 2; + RK_U32 rime_prelvl_en : 2; + RK_U32 rime_prersu_en : 3; + RK_U32 reserved1 : 17; + } me_sqi_cfg; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_mvd_th; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_madp_th : 12; + RK_U32 reserved : 20; + } cime_madp_th; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi0 : 8; + RK_U32 cime_multi1 : 8; + RK_U32 cime_multi2 : 8; + RK_U32 cime_multi3 : 8; + } cime_multi; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 rime_mvd_th0 : 3; + RK_U32 reserved : 1; + RK_U32 rime_mvd_th1 : 3; + RK_U32 reserved1 : 9; + RK_U32 fme_madp_th : 12; + RK_U32 reserved2 : 4; + } rime_mvd_th; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_madp_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_madp_th1 : 12; + RK_U32 reserved1 : 4; + } rime_madp_th; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_multi; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cmv_th0 : 8; + RK_U32 cmv_th1 : 8; + RK_U32 cmv_th2 : 8; + RK_U32 reserved : 8; + } cmv_st_th; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 reg1536 */ + struct { + RK_U32 lambda_satd_offset : 5; + RK_U32 reserved : 27; + } iprd_lamb_satd_ofst; + + /* 0x1804 - 0x18fc */ + RK_U32 reserved1537_1599[63];; + + /* wgt_qp48_grpa */ + /* 0x00001900 reg1600 */ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; +} hevc_vepu540c_wgt; + +typedef struct H265eV540cRegSet_t { + hevc_vepu540c_control_cfg reg_ctl; + hevc_vepu540c_base reg_base; + hevc_vepu540c_rc_roi reg_rc_roi; + hevc_vepu540c_wgt reg_wgt; + vepu540c_rdo_cfg reg_rdo; + vepu540c_scl_cfg reg_scl; + vepu540c_jpeg_tab jpeg_table; + vepu540c_dbg reg_dbg; +} H265eV540cRegSet; + +typedef struct H265eV540cStatusElem_t { + vepu540c_hw_status hw_status; + vepu540c_status st; +} H265eV540cStatusElem; + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu541.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu541.c new file mode 100644 index 000000000..696121611 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu541.c @@ -0,0 +1,2070 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265e_v541" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_frame_impl.h" + +#include "h265e_syntax_new.h" +#include "hal_h265e_debug.h" +#include "hal_h265e_stream_amend.h" +#include "hal_h265e_vepu541_reg.h" +#include "hal_h265e_vepu54x_reg_l2.h" +#include "vepu541_common.h" +#include "vepu5xx_common.h" +#include "rkv_enc_def.h" +#include "mpp_enc_hal.h" +#include "hal_bufs.h" +#include "mpp_enc_ref.h" + +#define hal_h265e_err(fmt, ...) \ + do {\ + mpp_err_f(fmt, ## __VA_ARGS__);\ + } while (0) +#define VEPU541_L2_SIZE 768 + +#define TILE_BUF_SIZE MPP_ALIGN(128 * 1024, 256) + +typedef struct vepu541_h265_fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; +} vepu541_h265_fbk; + +typedef struct H265eV541HalContext_t { + MppDev dev; + void *regs; + void *l2_regs; + void *reg_out; + + vepu541_h265_fbk feedback; + void *dump_files; + RK_U32 frame_cnt_gen_ready; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + /* @frame_cnt starts from ZERO */ + RK_U32 frame_cnt; + Vepu5xxOsdCfg osd_cfg; + MppEncROICfg *roi_data; + MppEncROICfg2 *roi_data2; + Vepu541RoiCfg *roi_buf_tmp; + MppBufferGroup roi_grp; + MppBuffer roi_buf; + RK_U32 roi_buf_size; + MppBuffer qpmap; + + MppEncCfgSet *cfg; + + MppBufferGroup tile_grp; + MppBuffer hw_tile_buf[2]; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + HalBufs dpb_bufs; + RK_U32 is_vepu540; + RK_S32 fbc_header_len; +} H265eV541HalContext; + +static RK_U32 aq_thd_default[16] = { + 0, 0, 0, 0, + 3, 3, 5, 5, + 8, 8, 8, 15, + 15, 20, 25, 35 +}; + +static RK_S32 aq_qp_dealt_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 4, 5, 7, 8, +}; + +static RK_U16 lvl32_intra_cst_thd[4] = {2, 6, 16, 36}; + +static RK_U16 lvl16_intra_cst_thd[4] = {2, 6, 16, 36}; + +static RK_U8 lvl32_intra_cst_wgt[8] = {23, 22, 21, 20, 22, 24, 26}; + +static RK_U8 lvl16_intra_cst_wgt[8] = {17, 17, 17, 18, 17, 18, 18}; + +static RK_U16 atr_thd[4] = {0, 0, 0, 0}; + +static RK_U8 lvl16_4_atr_wgt[12] = {0}; + +//RK_U16 atf_thd[14] = {0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 16, 16, 16, 16}; /*thd 4, sad 4, wgt 6*/ +static RK_U16 atf_thd[14] = {4, 36, 4, 36, 4, 36, 4, 36, 0, 4, 22, 22, 22, 22}; /*thd 4, sad 4, wgt 6*/ + +static RK_U16 atf_sad_ofst[4] = {0, 0, 0, 0}; + +static MPP_RET vepu54x_h265_setup_hal_bufs(H265eV541HalContext *ctx) +{ + MPP_RET ret = MPP_OK; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + RK_U32 frame_size; + VepuFmt input_fmt = VEPU5xx_FMT_YUV420P; + RK_S32 mb_wd64, mb_h64; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 2; + + hal_h265e_enter(); + + mb_wd64 = (prep->width + 63) / 64; + mb_h64 = (prep->height + 63) / 64 + 1; + + frame_size = MPP_ALIGN(prep->width, 16) * MPP_ALIGN(prep->height, 16); + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + input_fmt = (VepuFmt)fmt->format; + switch (input_fmt) { + case VEPU5xx_FMT_YUV400: + break; + case VEPU5xx_FMT_YUV420P: + case VEPU5xx_FMT_YUV420SP: { + frame_size = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV422P: + case VEPU5xx_FMT_YUV422SP: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: + case VEPU5xx_FMT_BGR565: { + frame_size *= 2; + } break; + case VEPU5xx_FMT_BGR888: { + frame_size *= 3; + } break; + case VEPU5xx_FMT_BGRA8888: { + frame_size *= 4; + } break; + default: { + hal_h265e_err("invalid src color space: %d\n", input_fmt); + return MPP_NOK; + } + } + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (frame_size > ctx->frame_size || new_max_cnt > old_max_cnt) { + size_t size[3] = {0}; + + hal_bufs_deinit(ctx->dpb_bufs); + hal_bufs_init(&ctx->dpb_bufs); + + ctx->fbc_header_len = MPP_ALIGN(((mb_wd64 * mb_h64) << 6), SZ_8K); + size[0] = ctx->fbc_header_len + ((mb_wd64 * mb_h64) << 12) * 3 / 2; //fbc_h + fbc_b + size[1] = (mb_wd64 * mb_h64 << 8); + size[2] = MPP_ALIGN(mb_wd64 * mb_h64 * 16 * 4, 256); + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_h265e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->frame_size, frame_size, old_max_cnt, new_max_cnt); + + hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, 3, size); + + ctx->frame_size = frame_size; + ctx->max_buf_cnt = new_max_cnt; + } + hal_h265e_leave(); + return ret; +} + +static void vepu540_h265_set_l2_regs(H265eV54xL2RegSet *reg) +{ + reg->pre_intra_cla0_B0.pre_intra_cla0_m0 = 10; + reg->pre_intra_cla0_B0.pre_intra_cla0_m1 = 11; + reg->pre_intra_cla0_B0.pre_intra_cla0_m2 = 12; + reg->pre_intra_cla0_B0.pre_intra_cla0_m3 = 13; + reg->pre_intra_cla0_B0.pre_intra_cla0_m4 = 14; + reg->pre_intra_cla0_B1.pre_intra_cla0_m5 = 9; + reg->pre_intra_cla0_B1.pre_intra_cla0_m6 = 15; + reg->pre_intra_cla0_B1.pre_intra_cla0_m7 = 8; + reg->pre_intra_cla0_B1.pre_intra_cla0_m8 = 16; + reg->pre_intra_cla0_B1.pre_intra_cla0_m9 = 7; + + reg->pre_intra_cla1_B0.pre_intra_cla1_m0 = 10; + reg->pre_intra_cla1_B0.pre_intra_cla1_m1 = 9; + reg->pre_intra_cla1_B0.pre_intra_cla1_m2 = 8; + reg->pre_intra_cla1_B0.pre_intra_cla1_m3 = 7; + reg->pre_intra_cla1_B0.pre_intra_cla1_m4 = 6; + reg->pre_intra_cla1_B1.pre_intra_cla1_m5 = 11; + reg->pre_intra_cla1_B1.pre_intra_cla1_m6 = 5; + reg->pre_intra_cla1_B1.pre_intra_cla1_m7 = 12; + reg->pre_intra_cla1_B1.pre_intra_cla1_m8 = 4; + reg->pre_intra_cla1_B1.pre_intra_cla1_m9 = 13; + + reg->pre_intra_cla2_B0.pre_intra_cla2_m0 = 18; + reg->pre_intra_cla2_B0.pre_intra_cla2_m1 = 17; + reg->pre_intra_cla2_B0.pre_intra_cla2_m2 = 16; + reg->pre_intra_cla2_B0.pre_intra_cla2_m3 = 15; + reg->pre_intra_cla2_B0.pre_intra_cla2_m4 = 14; + reg->pre_intra_cla2_B1.pre_intra_cla2_m5 = 19; + reg->pre_intra_cla2_B1.pre_intra_cla2_m6 = 13; + reg->pre_intra_cla2_B1.pre_intra_cla2_m7 = 20; + reg->pre_intra_cla2_B1.pre_intra_cla2_m8 = 12; + reg->pre_intra_cla2_B1.pre_intra_cla2_m9 = 21; + + reg->pre_intra_cla3_B0.pre_intra_cla3_m0 = 18; + reg->pre_intra_cla3_B0.pre_intra_cla3_m1 = 19; + reg->pre_intra_cla3_B0.pre_intra_cla3_m2 = 20; + reg->pre_intra_cla3_B0.pre_intra_cla3_m3 = 21; + reg->pre_intra_cla3_B0.pre_intra_cla3_m4 = 22; + reg->pre_intra_cla3_B1.pre_intra_cla3_m5 = 17; + reg->pre_intra_cla3_B1.pre_intra_cla3_m6 = 23; + reg->pre_intra_cla3_B1.pre_intra_cla3_m7 = 16; + reg->pre_intra_cla3_B1.pre_intra_cla3_m8 = 24; + reg->pre_intra_cla3_B1.pre_intra_cla3_m9 = 15; + + reg->pre_intra_cla4_B0.pre_intra_cla4_m0 = 25; + reg->pre_intra_cla4_B0.pre_intra_cla4_m1 = 26; + reg->pre_intra_cla4_B0.pre_intra_cla4_m2 = 24; + reg->pre_intra_cla4_B0.pre_intra_cla4_m3 = 23; + reg->pre_intra_cla4_B0.pre_intra_cla4_m4 = 22; + reg->pre_intra_cla4_B1.pre_intra_cla4_m5 = 27; + reg->pre_intra_cla4_B1.pre_intra_cla4_m6 = 21; + reg->pre_intra_cla4_B1.pre_intra_cla4_m7 = 28; + reg->pre_intra_cla4_B1.pre_intra_cla4_m8 = 20; + reg->pre_intra_cla4_B1.pre_intra_cla4_m9 = 29; + ; + reg->pre_intra_cla5_B0.pre_intra_cla5_m0 = 27; + reg->pre_intra_cla5_B0.pre_intra_cla5_m1 = 26; + reg->pre_intra_cla5_B0.pre_intra_cla5_m2 = 28; + reg->pre_intra_cla5_B0.pre_intra_cla5_m3 = 29; + reg->pre_intra_cla5_B0.pre_intra_cla5_m4 = 30; + reg->pre_intra_cla5_B1.pre_intra_cla5_m5 = 25; + reg->pre_intra_cla5_B1.pre_intra_cla5_m6 = 31; + reg->pre_intra_cla5_B1.pre_intra_cla5_m7 = 24; + reg->pre_intra_cla5_B1.pre_intra_cla5_m8 = 32; + reg->pre_intra_cla5_B1.pre_intra_cla5_m9 = 23; + ; + reg->pre_intra_cla6_B0.pre_intra_cla6_m0 = 34; + reg->pre_intra_cla6_B0.pre_intra_cla6_m1 = 33; + reg->pre_intra_cla6_B0.pre_intra_cla6_m2 = 32; + reg->pre_intra_cla6_B0.pre_intra_cla6_m3 = 31; + reg->pre_intra_cla6_B0.pre_intra_cla6_m4 = 30; + reg->pre_intra_cla6_B1.pre_intra_cla6_m5 = 2 ; + reg->pre_intra_cla6_B1.pre_intra_cla6_m6 = 29; + reg->pre_intra_cla6_B1.pre_intra_cla6_m7 = 3 ; + reg->pre_intra_cla6_B1.pre_intra_cla6_m8 = 28; + reg->pre_intra_cla6_B1.pre_intra_cla6_m9 = 4 ; + ; + reg->pre_intra_cla7_B0.pre_intra_cla7_m0 = 34; + reg->pre_intra_cla7_B0.pre_intra_cla7_m1 = 2 ; + reg->pre_intra_cla7_B0.pre_intra_cla7_m2 = 3 ; + reg->pre_intra_cla7_B0.pre_intra_cla7_m3 = 4 ; + reg->pre_intra_cla7_B0.pre_intra_cla7_m4 = 5 ; + reg->pre_intra_cla7_B1.pre_intra_cla7_m5 = 33; + reg->pre_intra_cla7_B1.pre_intra_cla7_m6 = 6 ; + reg->pre_intra_cla7_B1.pre_intra_cla7_m7 = 32; + reg->pre_intra_cla7_B1.pre_intra_cla7_m8 = 7 ; + reg->pre_intra_cla7_B1.pre_intra_cla7_m9 = 31; + ; + reg->pre_intra_cla8_B0.pre_intra_cla8_m0 = 10; + reg->pre_intra_cla8_B0.pre_intra_cla8_m1 = 26; + reg->pre_intra_cla8_B0.pre_intra_cla8_m2 = 18; + reg->pre_intra_cla8_B0.pre_intra_cla8_m3 = 34; + reg->pre_intra_cla8_B0.pre_intra_cla8_m4 = 6 ; + reg->pre_intra_cla8_B1.pre_intra_cla8_m5 = 14; + reg->pre_intra_cla8_B1.pre_intra_cla8_m6 = 22; + reg->pre_intra_cla8_B1.pre_intra_cla8_m7 = 30; + reg->pre_intra_cla8_B1.pre_intra_cla8_m8 = 2 ; + reg->pre_intra_cla8_B1.pre_intra_cla8_m9 = 24; + ; + reg->pre_intra_cla9_B0.pre_intra_cla9_m0 = 0 ; + reg->pre_intra_cla9_B0.pre_intra_cla9_m1 = 0 ; + reg->pre_intra_cla9_B0.pre_intra_cla9_m2 = 0 ; + reg->pre_intra_cla9_B0.pre_intra_cla9_m3 = 0 ; + reg->pre_intra_cla9_B0.pre_intra_cla9_m4 = 0 ; + reg->pre_intra_cla9_B1.pre_intra_cla9_m5 = 0 ; + reg->pre_intra_cla9_B1.pre_intra_cla9_m6 = 0 ; + reg->pre_intra_cla9_B1.pre_intra_cla9_m7 = 0 ; + reg->pre_intra_cla9_B1.pre_intra_cla9_m8 = 0 ; + reg->pre_intra_cla9_B1.pre_intra_cla9_m9 = 0 ; + + reg->pre_intra_cla10_B0.pre_intra_cla10_m0 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m1 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m2 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m3 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m4 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m5 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m6 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m7 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m8 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m9 = 0; + + reg->pre_intra_cla11_B0.pre_intra_cla11_m0 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m1 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m2 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m3 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m4 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m5 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m6 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m7 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m8 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m9 = 0; + + reg->pre_intra_cla12_B0.pre_intra_cla12_m0 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m1 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m2 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m3 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m4 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m5 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m6 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m7 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m8 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m9 = 0; + + reg->pre_intra_cla13_B0.pre_intra_cla13_m0 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m1 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m2 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m3 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m4 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m5 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m6 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m7 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m8 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m9 = 0; + + reg->pre_intra_cla14_B0.pre_intra_cla14_m0 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m1 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m2 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m3 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m4 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m5 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m6 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m7 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m8 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m9 = 0; + + reg->pre_intra_cla15_B0.pre_intra_cla15_m0 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m1 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m2 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m3 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m4 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m5 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m6 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m7 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m8 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m9 = 0; + + reg->pre_intra_cla16_B0.pre_intra_cla16_m0 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m1 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m2 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m3 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m4 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m5 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m6 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m7 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m8 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m9 = 0; + + reg->i16_sobel_t_hevc.intra_l16_sobel_t0 = 64 ; + reg->i16_sobel_t_hevc.intra_l16_sobel_t1 = 200; + reg->i16_sobel_a_00_hevc.intra_l16_sobel_a0_qp0 = 32 ; + reg->i16_sobel_a_00_hevc.intra_l16_sobel_a0_qp1 = 32 ; + reg->i16_sobel_a_00_hevc.intra_l16_sobel_a0_qp2 = 32 ; + reg->i16_sobel_a_00_hevc.intra_l16_sobel_a0_qp3 = 32 ; + reg->i16_sobel_a_00_hevc.intra_l16_sobel_a0_qp4 = 32 ; + reg->i16_sobel_a_01_hevc.intra_l16_sobel_a0_qp5 = 32 ; + reg->i16_sobel_a_01_hevc.intra_l16_sobel_a0_qp6 = 32 ; + reg->i16_sobel_a_01_hevc.intra_l16_sobel_a0_qp7 = 32 ; + reg->i16_sobel_a_01_hevc.intra_l16_sobel_a0_qp8 = 32 ; + reg->i16_sobel_b_00_hevc.intra_l16_sobel_b0_qp0 = 0 ; + reg->i16_sobel_b_00_hevc.intra_l16_sobel_b0_qp1 = 0 ; + reg->i16_sobel_b_01_hevc.intra_l16_sobel_b0_qp2 = 0 ; + reg->i16_sobel_b_01_hevc.intra_l16_sobel_b0_qp3 = 0 ; + reg->i16_sobel_b_02_hevc.intra_l16_sobel_b0_qp4 = 0 ; + reg->i16_sobel_b_02_hevc.intra_l16_sobel_b0_qp5 = 0 ; + reg->i16_sobel_b_03_hevc.intra_l16_sobel_b0_qp6 = 0 ; + reg->i16_sobel_b_03_hevc.intra_l16_sobel_b0_qp7 = 0 ; + reg->i16_sobel_b_04_hevc.intra_l16_sobel_b0_qp8 = 0 ; + reg->i16_sobel_c_00_hevc.intra_l16_sobel_c0_qp0 = 13; + reg->i16_sobel_c_00_hevc.intra_l16_sobel_c0_qp1 = 13; + reg->i16_sobel_c_00_hevc.intra_l16_sobel_c0_qp2 = 13; + reg->i16_sobel_c_00_hevc.intra_l16_sobel_c0_qp3 = 13; + reg->i16_sobel_c_00_hevc.intra_l16_sobel_c0_qp4 = 13; + reg->i16_sobel_c_01_hevc.intra_l16_sobel_c0_qp5 = 13; + reg->i16_sobel_c_01_hevc.intra_l16_sobel_c0_qp6 = 13; + reg->i16_sobel_c_01_hevc.intra_l16_sobel_c0_qp7 = 13; + reg->i16_sobel_c_01_hevc.intra_l16_sobel_c0_qp8 = 13; + reg->i16_sobel_d_00_hevc.intra_l16_sobel_d0_qp0 = 23750; + reg->i16_sobel_d_00_hevc.intra_l16_sobel_d0_qp1 = 23750; + reg->i16_sobel_d_01_hevc.intra_l16_sobel_d0_qp2 = 23750; + reg->i16_sobel_d_01_hevc.intra_l16_sobel_d0_qp3 = 23750; + reg->i16_sobel_d_02_hevc.intra_l16_sobel_d0_qp4 = 23750; + reg->i16_sobel_d_02_hevc.intra_l16_sobel_d0_qp5 = 23750; + reg->i16_sobel_d_03_hevc.intra_l16_sobel_d0_qp6 = 23750; + reg->i16_sobel_d_03_hevc.intra_l16_sobel_d0_qp7 = 23750; + reg->i16_sobel_d_04_hevc.intra_l16_sobel_d0_qp8 = 23750; + + reg->i16_sobel_e_00_17_hevc[0] = 20000; + reg->i16_sobel_e_00_17_hevc[2] = 20000; + reg->i16_sobel_e_00_17_hevc[4] = 20000; + reg->i16_sobel_e_00_17_hevc[6] = 20000; + reg->i16_sobel_e_00_17_hevc[8] = 20000; + reg->i16_sobel_e_00_17_hevc[10] = 20000; + reg->i16_sobel_e_00_17_hevc[12] = 20000; + reg->i16_sobel_e_00_17_hevc[14] = 20000; + reg->i16_sobel_e_00_17_hevc[16] = 20000; + reg->i16_sobel_e_00_17_hevc[1] = 0; + reg->i16_sobel_e_00_17_hevc[3] = 0; + reg->i16_sobel_e_00_17_hevc[5] = 0; + reg->i16_sobel_e_00_17_hevc[7] = 0; + reg->i16_sobel_e_00_17_hevc[9] = 0; + reg->i16_sobel_e_00_17_hevc[11] = 0; + reg->i16_sobel_e_00_17_hevc[13] = 0; + reg->i16_sobel_e_00_17_hevc[15] = 0; + reg->i16_sobel_e_00_17_hevc[17] = 0; + + reg->i32_sobel_t_00_hevc.intra_l32_sobel_t2 = 640 ; + reg->i32_sobel_t_00_hevc.intra_l32_sobel_t3 = 0 ; + reg->i32_sobel_t_01_hevc.intra_l32_sobel_t4 = 8 ; + reg->i32_sobel_t_02_hevc.intra_l32_sobel_t5 = 100 ; + reg->i32_sobel_t_02_hevc.intra_l32_sobel_t6 = 100 ; + + reg->i32_sobel_a_hevc.intra_l32_sobel_a1_qp0 = 18; + reg->i32_sobel_a_hevc.intra_l32_sobel_a1_qp1 = 18; + reg->i32_sobel_a_hevc.intra_l32_sobel_a1_qp2 = 18; + reg->i32_sobel_a_hevc.intra_l32_sobel_a1_qp3 = 18; + reg->i32_sobel_a_hevc.intra_l32_sobel_a1_qp4 = 18; + + reg->i32_sobel_b_00_hevc.intra_l32_sobel_b1_qp0 = 0; + reg->i32_sobel_b_00_hevc.intra_l32_sobel_b1_qp1 = 0; + reg->i32_sobel_b_01_hevc.intra_l32_sobel_b1_qp2 = 0; + reg->i32_sobel_b_01_hevc.intra_l32_sobel_b1_qp3 = 0; + reg->i32_sobel_b_02_hevc.intra_l32_sobel_b1_qp4 = 0; + + reg->i32_sobel_c_hevc.intra_l32_sobel_c1_qp0 = 18; + reg->i32_sobel_c_hevc.intra_l32_sobel_c1_qp1 = 18; + reg->i32_sobel_c_hevc.intra_l32_sobel_c1_qp2 = 18; + reg->i32_sobel_c_hevc.intra_l32_sobel_c1_qp3 = 18; + reg->i32_sobel_c_hevc.intra_l32_sobel_c1_qp4 = 18; + + reg->i32_sobel_d_00_hevc.intra_l32_sobel_d1_qp0 = 0; + reg->i32_sobel_d_00_hevc.intra_l32_sobel_d1_qp1 = 0; + reg->i32_sobel_d_01_hevc.intra_l32_sobel_d1_qp2 = 0; + reg->i32_sobel_d_01_hevc.intra_l32_sobel_d1_qp3 = 0; + reg->i32_sobel_d_02_hevc.intra_l32_sobel_d1_qp4 = 0; + + reg->i32_sobel_e_00_09_hevc[0] = 20000; + reg->i32_sobel_e_00_09_hevc[2] = 20000; + reg->i32_sobel_e_00_09_hevc[4] = 20000; + reg->i32_sobel_e_00_09_hevc[6] = 20000; + reg->i32_sobel_e_00_09_hevc[8] = 20000; + + reg->i32_sobel_e_00_09_hevc[1] = 0; + reg->i32_sobel_e_00_09_hevc[3] = 0; + reg->i32_sobel_e_00_09_hevc[5] = 0; + reg->i32_sobel_e_00_09_hevc[7] = 0; + reg->i32_sobel_e_00_09_hevc[9] = 0; +} +static void vepu541_h265_set_l2_regs(H265eV541HalContext *ctx, H265eV54xL2RegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + RK_U32 i; + + memcpy(®s->lvl32_intra_CST_THD0, lvl32_intra_cst_thd, sizeof(lvl32_intra_cst_thd)); + memcpy(®s->lvl16_intra_CST_THD0, lvl16_intra_cst_thd, sizeof(lvl16_intra_cst_thd)); + memcpy(®s->lvl32_intra_CST_WGT0, lvl32_intra_cst_wgt, sizeof(lvl32_intra_cst_wgt)); + memcpy(®s->lvl16_intra_CST_WGT0, lvl16_intra_cst_wgt, sizeof(lvl16_intra_cst_wgt)); + regs->rdo_quant.quant_f_bias_I = 171; + regs->rdo_quant.quant_f_bias_P = 85; + memcpy(®s->atr_thd0, atr_thd, sizeof(atr_thd)); + memcpy(®s->lvl16_atr_wgt, lvl16_4_atr_wgt, sizeof(lvl16_4_atr_wgt)); + if (!ctx->is_vepu540) { + memcpy(®s->thd_541.atf_thd0, atf_thd, sizeof(atf_thd)); + regs->thd_541.atf_thd0.atf_thd0_i32 = 0; + regs->thd_541.atf_thd0.atf_thd1_i32 = 63; + regs->thd_541.atf_thd1.atf_thd0_i16 = 0; + regs->thd_541.atf_thd1.atf_thd1_i16 = 63; + regs->thd_541.atf_sad_thd0.atf_thd0_p64 = 0; + regs->thd_541.atf_sad_thd0.atf_thd1_p64 = 63; + regs->thd_541.atf_sad_thd1.atf_thd0_p32 = 0; + regs->thd_541.atf_sad_thd1.atf_thd1_p32 = 63; + regs->thd_541.atf_sad_wgt0.atf_thd0_p16 = 0; + regs->thd_541.atf_sad_wgt0.atf_thd1_p16 = 63; + } else { + memcpy(®s->thd_540.atf_thd0, atf_thd, sizeof(atf_thd)); + regs->thd_540.atf_thd0.atf_thd0_i32 = 0; + regs->thd_540.atf_thd0.atf_thd1_i32 = 63; + regs->thd_540.atf_thd1.atf_thd0_i16 = 0; + regs->thd_540.atf_thd1.atf_thd1_i16 = 63; + regs->thd_540.atf_sad_thd0.atf_thd0_p64 = 0; + regs->thd_540.atf_sad_thd0.atf_thd1_p64 = 63; + regs->thd_540.atf_sad_thd1.atf_thd0_p32 = 0; + regs->thd_540.atf_sad_thd1.atf_thd1_p32 = 63; + regs->thd_540.atf_sad_wgt0.atf_thd0_p16 = 0; + regs->thd_540.atf_sad_wgt0.atf_thd1_p16 = 63; + vepu540_h265_set_l2_regs(regs); + } + + if (ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + regs->atf_sad_wgt1.atf_wgt_i16 = 19; + regs->atf_sad_wgt1.atf_wgt_i32 = 19; + regs->atf_sad_wgt2.atf_wgt_p32 = 13; + regs->atf_sad_wgt2.atf_wgt_p64 = 13; + regs->atf_sad_ofst0.atf_wgt_p16 = 13; + } else { + regs->atf_sad_wgt1.atf_wgt_i16 = 16; + regs->atf_sad_wgt1.atf_wgt_i32 = 16; + regs->atf_sad_wgt2.atf_wgt_p32 = 16; + regs->atf_sad_wgt2.atf_wgt_p64 = 16; + regs->atf_sad_ofst0.atf_wgt_p16 = 16; + } + + memcpy(®s->atf_sad_ofst1, atf_sad_ofst, sizeof(atf_sad_ofst)); + memcpy(®s->lamd_satd_qp[0], lamd_satd_qp, sizeof(lamd_satd_qp)); + memcpy(®s->lamd_moda_qp[0], lamd_moda_qp, sizeof(lamd_moda_qp)); + memcpy(®s->lamd_modb_qp[0], lamd_modb_qp, sizeof(lamd_modb_qp)); + + if (ctx->frame_type == INTRA_FRAME) { + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + regs->aq_tthd[i] = hw->aq_thrd_i[i]; + regs->aq_step[i] = hw->aq_step_i[i] & 0x3f; + } + } else { + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + regs->aq_tthd[i] = hw->aq_thrd_p[i]; + regs->aq_step[i] = hw->aq_step_p[i] & 0x3f; + } + } + + if (hw->qbias_en) { + regs->rdo_quant.quant_f_bias_I = hw->qbias_i; + regs->rdo_quant.quant_f_bias_P = hw->qbias_p; + } + + MppDevRegWrCfg cfg; + cfg.reg = regs; + if (ctx->is_vepu540) { + cfg.size = sizeof(H265eV54xL2RegSet); + } else { + cfg.size = VEPU541_L2_SIZE ; + } + cfg.offset = VEPU541_REG_BASE_L2; + mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); +} + +MPP_RET hal_h265e_v541_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + + mpp_env_get_u32("hal_h265e_debug", &hal_h265e_debug, 0); + hal_h265e_enter(); + ctx->reg_out = mpp_calloc(H265eV541IoctlOutputElem, 1); + ctx->regs = mpp_calloc(H265eV541RegSet, 1); + ctx->l2_regs = mpp_calloc(H265eV54xL2RegSet, 1); + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + hal_bufs_init(&ctx->dpb_bufs); + + ctx->frame_cnt = 0; + ctx->frame_cnt_gen_ready = 0; + ctx->enc_mode = RKV_ENC_MODE; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + + ctx->dev = cfg->dev; + { + RockchipSocType soc_type = mpp_get_soc_type(); + + if (soc_type == ROCKCHIP_SOC_RK3566 || soc_type == ROCKCHIP_SOC_RK3568) + ctx->is_vepu540 = 1; + } + + ctx->osd_cfg.reg_base = ctx->regs; + ctx->osd_cfg.dev = ctx->dev; + ctx->osd_cfg.reg_cfg = NULL; + ctx->osd_cfg.plt_cfg = &ctx->cfg->plt_cfg; + ctx->osd_cfg.osd_data = NULL; + ctx->osd_cfg.osd_data2 = NULL; + + ctx->frame_type = INTRA_FRAME; + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + + hw->qp_delta_row_i = 0; + hw->qp_delta_row = 1; + hw->qbias_i = 171; + hw->qbias_p = 85; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, aq_thd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, aq_thd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, aq_qp_dealt_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, aq_qp_dealt_default, sizeof(hw->aq_step_p)); + } + + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_v541_deinit(void *hal) +{ + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + hal_h265e_enter(); + MPP_FREE(ctx->regs); + MPP_FREE(ctx->l2_regs); + MPP_FREE(ctx->reg_out); + MPP_FREE(ctx->input_fmt); + MPP_FREE(ctx->roi_buf_tmp); + + if (ctx->roi_buf) { + mpp_buffer_put(ctx->roi_buf); + ctx->roi_buf = NULL; + } + hal_bufs_deinit(ctx->dpb_bufs); + + if (ctx->roi_grp) { + mpp_buffer_group_put(ctx->roi_grp); + ctx->roi_grp = NULL; + } + + if (ctx->hw_tile_buf[0]) { + mpp_buffer_put(ctx->hw_tile_buf[0]); + ctx->hw_tile_buf[0] = NULL; + } + + if (ctx->hw_tile_buf[1]) { + mpp_buffer_put(ctx->hw_tile_buf[1]); + ctx->hw_tile_buf[1] = NULL; + } + + if (ctx->tile_grp) { + mpp_buffer_group_put(ctx->tile_grp); + ctx->tile_grp = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + hal_h265e_leave(); + return MPP_OK; +} + +static MPP_RET hal_h265e_vepu54x_prepare(void *hal) +{ + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h265e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + vepu54x_h265_setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->dpb_bufs, i); + + prep->change_res = 0; + } + + hal_h265e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET +vepu541_h265_set_patch_info(MppDev dev, H265eSyntax_new *syn, VepuFmt input_fmt, HalEncTask *task) +{ + RK_U32 hor_stride = syn->pp.hor_stride; + RK_U32 ver_stride = (syn->pp.ver_stride != 0) ? syn->pp.ver_stride : syn->pp.pic_height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + u_offset = mpp_frame_get_fbc_offset(task->frame); + v_offset = 0; + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + default: { + hal_h265e_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + + /* input cb addr */ + if (u_offset) { + mpp_dev_set_reg_offset(dev, 71, u_offset); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); + } + + /* input cr addr */ + if (v_offset) { + mpp_dev_set_reg_offset(dev, 72, v_offset); + if (ret) + mpp_err_f("set input cr addr offset failed %d\n", ret); + } + + mpp_dev_set_reg_offset(dev, 83, mpp_buffer_get_size(task->output)); + if (ret) + mpp_err_f("set output max addr offset failed %d\n", ret); + + return ret; +} + +MPP_RET vepu541_h265_set_roi(void *dst_buf, void *src_buf, RK_S32 w, RK_S32 h) +{ + Vepu541RoiCfg *src = (Vepu541RoiCfg *)src_buf; + Vepu541RoiCfg *dst = (Vepu541RoiCfg *)dst_buf; + RK_S32 mb_w = MPP_ALIGN(w, 64) / 64; + RK_S32 mb_h = MPP_ALIGN(h, 64) / 64; + RK_S32 ctu_line = mb_w; + RK_S32 i, j, cu16cnt; + + for (j = 0; j < mb_h; j++) { + for ( i = 0; i < mb_w; i++) { + RK_S32 ctu_addr = j * ctu_line + i; + RK_S32 cu16_num_line = ctu_line * 4; + for ( cu16cnt = 0; cu16cnt < 16; cu16cnt++) { + RK_S32 cu16_x; + RK_S32 cu16_y; + RK_S32 cu16_addr_in_frame; + cu16_x = cu16cnt & 3; + cu16_y = cu16cnt / 4; + cu16_x += i * 4; + cu16_y += j * 4; + cu16_addr_in_frame = cu16_x + cu16_y * cu16_num_line; + dst[ctu_addr * 16 + cu16cnt] = src[cu16_addr_in_frame]; + } + } + } + return MPP_OK; +} + +static MPP_RET setup_vepu541_intra_refresh(H265eV541RegSet *regs, H265eV541HalContext *ctx, RK_U32 refresh_idx) +{ + MPP_RET ret = MPP_OK; + RK_U32 h = ctx->cfg->prep.height; + RK_U32 w = ctx->cfg->prep.width; + MppEncROIRegion *region = NULL; + RK_U32 stride_h = MPP_ALIGN(w / 16, 4); + RK_U32 stride_v = MPP_ALIGN(h / 16, 4); + RK_U32 i = 0; + RK_U32 roi_buf_size; + + hal_h265e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en) { + ret = MPP_ERR_VALUE; + goto RET; + } + + roi_buf_size = vepu541_get_roi_buf_size(w, h); + if (ctx->roi_buf_size < roi_buf_size) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + if (ctx->roi_buf) + mpp_buffer_put(ctx->roi_buf); + MPP_FREE(ctx->roi_buf_tmp); + ctx->roi_buf_tmp = mpp_calloc_size(Vepu541RoiCfg, roi_buf_size); + mpp_buffer_get(ctx->roi_grp, &ctx->roi_buf, roi_buf_size); + ctx->roi_buf_size = roi_buf_size; + } + + mpp_assert(ctx->roi_buf); + mpp_assert(ctx->roi_buf_tmp); + RK_S32 fd = mpp_buffer_get_fd(ctx->roi_buf); + void *buf = ctx->roi_buf_tmp; + void *dst_buf = mpp_buffer_get_ptr(ctx->roi_buf); + Vepu541RoiCfg cfg; + Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf; + cfg.force_intra = 0; + cfg.reserved = 0; + cfg.qp_area_idx = 0; + cfg.qp_area_en = 1; + cfg.qp_adj = 0; + cfg.qp_adj_mode = 0; + + for (i = 0; i < stride_h * stride_v; i++, ptr++) + memcpy(ptr, &cfg, sizeof(cfg)); + + region = mpp_calloc(MppEncROIRegion, 1); + + if (NULL == region) { + mpp_err_f("Failed to calloc for MppEncROIRegion !\n"); + ret = MPP_ERR_MALLOC; + } + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + region->x = 0; + region->w = w; + if (refresh_idx > 0) { + region->y = refresh_idx * 64 * ctx->cfg->rc.refresh_num - 128; + region->h = 64 * ctx->cfg->rc.refresh_num + 128; + } else { + region->y = refresh_idx * 64 * ctx->cfg->rc.refresh_num; + region->h = 64 * ctx->cfg->rc.refresh_num; + } + regs->me_rnge.cime_srch_v = 1; + } else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) { + region->y = 0; + region->h = h; + if (refresh_idx > 0) { + region->x = refresh_idx * 64 * ctx->cfg->rc.refresh_num - 128; + region->w = 64 * ctx->cfg->rc.refresh_num + 128; + } else { + region->x = refresh_idx * 64 * ctx->cfg->rc.refresh_num; + region->w = 64 * ctx->cfg->rc.refresh_num; + } + regs->me_rnge.cime_srch_h = 1; + } + + region->intra = 1; + region->quality = -ctx->cfg->rc.qp_delta_ip; + + region->area_map_en = 1; + region->qp_area_idx = 1; + region->abs_qp_en = 0; + + regs->enc_pic.roi_en = 1; + regs->roi_addr_hevc = fd; + vepu541_set_one_roi(buf, region, w, h); + vepu541_h265_set_roi(dst_buf, buf, w, h); + mpp_free(region); + mpp_buffer_sync_end(ctx->roi_buf); + +RET: + hal_h265e_dbg_func("leave, ret %d\n", ret); + return ret; +} + +static MPP_RET +vepu541_h265_set_roi_regs(H265eV541HalContext *ctx, H265eV541RegSet *regs) +{ + if (ctx->roi_data2) { + MppEncROICfg2 *cfg = ( MppEncROICfg2 *)ctx->roi_data2; + + regs->enc_pic.roi_en = 1; + regs->roi_addr_hevc = mpp_buffer_get_fd(cfg->base_cfg_buf); + } else if (ctx->qpmap) { + regs->enc_pic.roi_en = 1; + regs->roi_addr_hevc = mpp_buffer_get_fd(ctx->qpmap); + } else { + MppEncROICfg *cfg = (MppEncROICfg*)ctx->roi_data; + RK_U32 h = ctx->cfg->prep.height; + RK_U32 w = ctx->cfg->prep.width; + RK_U8 *roi_base; + + if (!cfg) + return MPP_OK; + + if (cfg->number && cfg->regions) { + RK_U32 roi_buf_size = vepu541_get_roi_buf_size(w, h); + + if (!ctx->roi_buf || roi_buf_size != ctx->roi_buf_size) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + else if (roi_buf_size != ctx->roi_buf_size) { + if (ctx->roi_buf) { + mpp_buffer_put(ctx->roi_buf); + ctx->roi_buf = NULL; + } + MPP_FREE(ctx->roi_buf_tmp); + mpp_buffer_group_clear(ctx->roi_grp); + } + mpp_assert(ctx->roi_grp); + if (NULL == ctx->roi_buf) + mpp_buffer_get(ctx->roi_grp, &ctx->roi_buf, roi_buf_size); + + if (ctx->roi_buf_tmp == NULL) + ctx->roi_buf_tmp = (Vepu541RoiCfg*)mpp_malloc(RK_U8, roi_buf_size); + + ctx->roi_buf_size = roi_buf_size; + } + + regs->enc_pic.roi_en = 1; + regs->roi_addr_hevc = mpp_buffer_get_fd(ctx->roi_buf); + roi_base = (RK_U8 *)mpp_buffer_get_ptr(ctx->roi_buf); + vepu541_set_roi(ctx->roi_buf_tmp, cfg, w, h); + vepu541_h265_set_roi(roi_base, ctx->roi_buf_tmp, w, h); + } + } + + return MPP_OK; +} + +static MPP_RET vepu541_h265_set_rc_regs(H265eV541HalContext *ctx, H265eV541RegSet *regs, HalEncTask *task) +{ + H265eSyntax_new *syn = (H265eSyntax_new *)task->syntax.data; + EncRcTaskInfo *rc_cfg = &task->rc_task->info; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + MppEncH265Cfg *h265 = &cfg->h265; + RK_S32 mb_wd64, mb_h64; + mb_wd64 = (syn->pp.pic_width + 63) / 64; + mb_h64 = (syn->pp.pic_height + 63) / 64; + + RK_U32 ctu_target_bits_mul_16 = (rc_cfg->bit_target << 4) / (mb_wd64 * mb_h64); + RK_U32 ctu_target_bits; + RK_S32 negative_bits_thd, positive_bits_thd; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + regs->enc_pic.pic_qp = rc_cfg->quality_target; + regs->synt_sli1.sli_qp = rc_cfg->quality_target; + + regs->rc_qp.rc_max_qp = rc_cfg->quality_target; + regs->rc_qp.rc_min_qp = rc_cfg->quality_target; + } else { + if (ctu_target_bits_mul_16 >= 0x100000) { + ctu_target_bits_mul_16 = 0x50000; + } + ctu_target_bits = (ctu_target_bits_mul_16 * mb_wd64) >> 4; + negative_bits_thd = 0 - 5 * ctu_target_bits / 16; + positive_bits_thd = 5 * ctu_target_bits / 16; + + regs->enc_pic.pic_qp = rc_cfg->quality_target; + regs->synt_sli1.sli_qp = rc_cfg->quality_target; + regs->rc_cfg.rc_en = 1; + regs->rc_cfg.aqmode_en = 1; + regs->rc_cfg.qp_mode = 1; + + regs->rc_cfg.rc_ctu_num = mb_wd64; + + regs->rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? + hw->qp_delta_row_i : hw->qp_delta_row; + regs->rc_qp.rc_max_qp = rc_cfg->quality_max; + regs->rc_qp.rc_min_qp = rc_cfg->quality_min; + regs->rc_tgt.ctu_ebits = ctu_target_bits_mul_16; + + regs->rc_erp0.bits_thd0 = 2 * negative_bits_thd; + regs->rc_erp1.bits_thd1 = negative_bits_thd; + regs->rc_erp2.bits_thd2 = positive_bits_thd; + regs->rc_erp3.bits_thd3 = 2 * positive_bits_thd; + regs->rc_erp4.bits_thd4 = 0x7FFFFFFF; + regs->rc_erp5.bits_thd5 = 0x7FFFFFFF; + regs->rc_erp6.bits_thd6 = 0x7FFFFFFF; + regs->rc_erp7.bits_thd7 = 0x7FFFFFFF; + regs->rc_erp8.bits_thd8 = 0x7FFFFFFF; + + regs->rc_adj0.qp_adjust0 = -2; + regs->rc_adj0.qp_adjust1 = -1; + regs->rc_adj0.qp_adjust2 = 0; + regs->rc_adj0.qp_adjust3 = 1; + regs->rc_adj0.qp_adjust4 = 2; + regs->rc_adj1.qp_adjust5 = 0; + regs->rc_adj1.qp_adjust6 = 0; + regs->rc_adj1.qp_adjust7 = 0; + regs->rc_adj1.qp_adjust8 = 0; + + regs->qpmap0.qpmin_area0 = h265->qpmin_map[0] > 0 ? h265->qpmin_map[0] : rc_cfg->quality_min; + regs->qpmap0.qpmax_area0 = h265->qpmax_map[0] > 0 ? h265->qpmax_map[0] : rc_cfg->quality_max; + regs->qpmap0.qpmin_area1 = h265->qpmin_map[1] > 0 ? h265->qpmin_map[1] : rc_cfg->quality_min; + regs->qpmap0.qpmax_area1 = h265->qpmax_map[1] > 0 ? h265->qpmax_map[1] : rc_cfg->quality_max; + regs->qpmap0.qpmin_area2 = h265->qpmin_map[2] > 0 ? h265->qpmin_map[2] : rc_cfg->quality_min;; + regs->qpmap1.qpmax_area2 = h265->qpmax_map[2] > 0 ? h265->qpmax_map[2] : rc_cfg->quality_max; + regs->qpmap1.qpmin_area3 = h265->qpmin_map[3] > 0 ? h265->qpmin_map[3] : rc_cfg->quality_min;; + regs->qpmap1.qpmax_area3 = h265->qpmax_map[3] > 0 ? h265->qpmax_map[3] : rc_cfg->quality_max; + regs->qpmap1.qpmin_area4 = h265->qpmin_map[4] > 0 ? h265->qpmin_map[4] : rc_cfg->quality_min;; + regs->qpmap1.qpmax_area4 = h265->qpmax_map[4] > 0 ? h265->qpmax_map[4] : rc_cfg->quality_max; + regs->qpmap2.qpmin_area5 = h265->qpmin_map[5] > 0 ? h265->qpmin_map[5] : rc_cfg->quality_min;; + regs->qpmap2.qpmax_area5 = h265->qpmax_map[5] > 0 ? h265->qpmax_map[5] : rc_cfg->quality_max; + regs->qpmap2.qpmin_area6 = h265->qpmin_map[6] > 0 ? h265->qpmin_map[6] : rc_cfg->quality_min;; + regs->qpmap2.qpmax_area6 = h265->qpmax_map[6] > 0 ? h265->qpmax_map[6] : rc_cfg->quality_max; + regs->qpmap2.qpmin_area7 = h265->qpmin_map[7] > 0 ? h265->qpmin_map[7] : rc_cfg->quality_min;; + regs->qpmap3.qpmax_area7 = h265->qpmax_map[7] > 0 ? h265->qpmax_map[7] : rc_cfg->quality_max; + regs->qpmap3.qpmap_mode = h265->qpmap_mode; + } + if (ctx->frame_type == INTRA_FRAME) { + regs->enc_pic.rdo_wgt_sel = 0; + } else { + regs->enc_pic.rdo_wgt_sel = 1; + } + return MPP_OK; +} + +static MPP_RET vepu541_h265_set_pp_regs(VepuFmtCfg *fmt, H265eV541HalContext *ctx, HalEncTask *task) +{ + RK_S32 stridey = 0; + RK_S32 stridec = 0; + H265eV541RegSet *regs = ctx->regs; + MppEncPrepCfg *prep_cfg = &ctx->cfg->prep; + MppFrameFormat prep_fmt = prep_cfg->format; + + regs->dtrns_map.src_bus_edin = fmt->src_endian; + regs->src_fmt.src_cfmt = fmt->format; + regs->src_fmt.alpha_swap = fmt->alpha_swap; + regs->src_fmt.rbuv_swap = fmt->rbuv_swap; + regs->src_fmt.src_range = fmt->src_range; + regs->src_fmt.out_fmt_cfg = (fmt->format == VEPU5xx_FMT_YUV400) ? 1 : 0; + regs->src_proc.src_mirr = prep_cfg->mirroring > 0; + regs->src_proc.src_rot = prep_cfg->rotation; + + if (!ctx->frame_num && (prep_fmt == MPP_FMT_YUV420SP_VU || prep_fmt == MPP_FMT_YUV422SP_VU)) + mpp_logw("Warning: nv21/nv42 fmt not supported, will encode as nv12/nv24.\n"); + + if (MPP_FRAME_FMT_IS_FBC(prep_fmt)) { + stridey = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!stridey) + stridey = MPP_ALIGN(prep_cfg->hor_stride, 16); + } else if (prep_cfg->hor_stride) { + stridey = prep_cfg->hor_stride; + } else { + if (regs->src_fmt.src_cfmt == VEPU5xx_FMT_BGRA8888) + stridey = prep_cfg->width * 4; + else if (regs->src_fmt.src_cfmt == VEPU5xx_FMT_BGR888) + stridey = prep_cfg->width * 3; + else if (regs->src_fmt.src_cfmt == VEPU5xx_FMT_BGR565 || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUYV422 || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_UYVY422) + stridey = prep_cfg->width * 2; + } + + stridec = (regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV422SP || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV420SP) ? + stridey : stridey / 2; + + if (regs->src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = cfg_coeffs = get_rgb2yuv_cfg(prep_cfg->range, prep_cfg->color); + + hal_h265e_dbg_simple("input color range %d colorspace %d", prep_cfg->range, prep_cfg->color); + + regs->src_udfy.wght_r2y = cfg_coeffs->_2y.r_coeff; + regs->src_udfy.wght_g2y = cfg_coeffs->_2y.g_coeff; + regs->src_udfy.wght_b2y = cfg_coeffs->_2y.b_coeff; + + regs->src_udfu.wght_r2u = cfg_coeffs->_2u.r_coeff; + regs->src_udfu.wght_g2u = cfg_coeffs->_2u.g_coeff; + regs->src_udfu.wght_b2u = cfg_coeffs->_2u.b_coeff; + + regs->src_udfv.wght_r2v = cfg_coeffs->_2v.r_coeff; + regs->src_udfv.wght_g2v = cfg_coeffs->_2v.g_coeff; + regs->src_udfv.wght_b2v = cfg_coeffs->_2v.b_coeff; + + regs->src_udfo.ofst_y = cfg_coeffs->_2y.offset; + regs->src_udfo.ofst_u = cfg_coeffs->_2u.offset; + regs->src_udfo.ofst_v = cfg_coeffs->_2v.offset; + + hal_h265e_dbg_simple("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } + + regs->src_strid.src_ystrid = stridey; + regs->src_strid.src_cstrid = stridec; + + return MPP_OK; +} + +static void vepu541_h265_set_slice_regs(H265eSyntax_new *syn, H265eV541RegSet *regs) +{ + regs->synt_sps.smpl_adpt_ofst_en = syn->pp.sample_adaptive_offset_enabled_flag;//slice->m_sps->m_bUseSAO; + regs->synt_sps.num_st_ref_pic = syn->pp.num_short_term_ref_pic_sets; + regs->synt_sps.num_lt_ref_pic = syn->pp.num_long_term_ref_pics_sps; + regs->synt_sps.lt_ref_pic_prsnt = syn->pp.long_term_ref_pics_present_flag; + regs->synt_sps.tmpl_mvp_en = syn->pp.sps_temporal_mvp_enabled_flag; + regs->synt_sps.log2_max_poc_lsb = syn->pp.log2_max_pic_order_cnt_lsb_minus4; + regs->synt_sps.strg_intra_smth = syn->pp.strong_intra_smoothing_enabled_flag; + + regs->synt_pps.dpdnt_sli_seg_en = syn->pp.dependent_slice_segments_enabled_flag; + regs->synt_pps.out_flg_prsnt_flg = syn->pp.output_flag_present_flag; + regs->synt_pps.num_extr_sli_hdr = syn->pp.num_extra_slice_header_bits; + regs->synt_pps.sgn_dat_hid_en = syn->pp.sign_data_hiding_enabled_flag; + regs->synt_pps.cbc_init_prsnt_flg = syn->pp.cabac_init_present_flag; + regs->synt_pps.pic_init_qp = syn->pp.init_qp_minus26 + 26; + regs->synt_pps.cu_qp_dlt_en = syn->pp.cu_qp_delta_enabled_flag; + regs->synt_pps.chrm_qp_ofst_prsn = syn->pp.pps_slice_chroma_qp_offsets_present_flag; + regs->synt_pps.lp_fltr_acrs_sli = syn->pp.pps_loop_filter_across_slices_enabled_flag; + regs->synt_pps.dblk_fltr_ovrd_en = syn->pp.deblocking_filter_override_enabled_flag; + regs->synt_pps.lst_mdfy_prsnt_flg = syn->pp.lists_modification_present_flag; + regs->synt_pps.sli_seg_hdr_extn = syn->pp.slice_segment_header_extension_present_flag; + regs->synt_pps.cu_qp_dlt_depth = syn->pp.diff_cu_qp_delta_depth; + regs->synt_pps.lpf_fltr_acrs_til = syn->pp.loop_filter_across_tiles_enabled_flag; + + regs->synt_sli0.cbc_init_flg = syn->sp.cbc_init_flg; + regs->synt_sli0.mvd_l1_zero_flg = syn->sp.mvd_l1_zero_flg; + regs->synt_sli0.merge_up_flag = syn->sp.merge_up_flag; + regs->synt_sli0.merge_left_flag = syn->sp.merge_left_flag; + regs->synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + regs->synt_sli0.num_refidx_l1_act = syn->sp.num_refidx_l1_act; + regs->synt_sli0.num_refidx_l0_act = syn->sp.num_refidx_l0_act; + + regs->synt_sli0.num_refidx_act_ovrd = syn->sp.num_refidx_act_ovrd; + + regs->synt_sli0.sli_sao_chrm_flg = syn->sp.sli_sao_chrm_flg; + regs->synt_sli0.sli_sao_luma_flg = syn->sp.sli_sao_luma_flg; + regs->synt_sli0.sli_tmprl_mvp_en = syn->sp.sli_tmprl_mvp_en; + regs->enc_pic.tot_poc_num = syn->sp.tot_poc_num; + + regs->synt_sli0.pic_out_flg = syn->sp.pic_out_flg; + regs->synt_sli0.sli_type = syn->sp.slice_type; + regs->synt_sli0.sli_rsrv_flg = syn->sp.slice_rsrv_flg; + regs->synt_sli0.dpdnt_sli_seg_flg = syn->sp.dpdnt_sli_seg_flg; + regs->synt_sli0.sli_pps_id = syn->sp.sli_pps_id; + regs->synt_sli0.no_out_pri_pic = syn->sp.no_out_pri_pic; + + + regs->synt_sli1.sli_tc_ofst_div2 = syn->sp.sli_tc_ofst_div2;; + regs->synt_sli1.sli_beta_ofst_div2 = syn->sp.sli_beta_ofst_div2; + regs->synt_sli1.sli_lp_fltr_acrs_sli = syn->sp.sli_lp_fltr_acrs_sli; + regs->synt_sli1.sli_dblk_fltr_dis = syn->sp.sli_dblk_fltr_dis; + regs->synt_sli1.dblk_fltr_ovrd_flg = syn->sp.dblk_fltr_ovrd_flg; + regs->synt_sli1.sli_cb_qp_ofst = (syn->pp.pps_slice_chroma_qp_offsets_present_flag != 0) ? + syn->sp.sli_cb_qp_ofst : syn->pp.pps_cb_qp_offset; + regs->synt_sli1.max_mrg_cnd = syn->sp.max_mrg_cnd; + + regs->synt_sli1.col_ref_idx = syn->sp.col_ref_idx; + regs->synt_sli1.col_frm_l0_flg = syn->sp.col_frm_l0_flg; + regs->synt_sli2_rodr.sli_poc_lsb = syn->sp.sli_poc_lsb; + regs->synt_sli2_rodr.sli_hdr_ext_len = syn->sp.sli_hdr_ext_len; + +} + +static void vepu541_h265_set_ref_regs(H265eSyntax_new *syn, H265eV541RegSet *regs) +{ + regs->synt_ref_mark0.st_ref_pic_flg = syn->sp.st_ref_pic_flg; + regs->synt_ref_mark0.poc_lsb_lt0 = syn->sp.poc_lsb_lt0; + regs->synt_ref_mark0.num_lt_pic = syn->sp.num_lt_pic; + + regs->synt_ref_mark1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->synt_ref_mark1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->synt_ref_mark1.used_by_lt_flg0 = syn->sp.used_by_lt_flg0; + regs->synt_ref_mark1.used_by_lt_flg1 = syn->sp.used_by_lt_flg1; + regs->synt_ref_mark1.used_by_lt_flg2 = syn->sp.used_by_lt_flg2; + regs->synt_ref_mark1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->synt_ref_mark1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->synt_ref_mark1.dlt_poc_msb_prsnt1 = syn->sp.dlt_poc_msb_prsnt1; + regs->synt_ref_mark1.num_neg_pic = syn->sp.num_neg_pic; + regs->synt_ref_mark1.num_pos_pic = syn->sp.num_pos_pic; + + regs->synt_ref_mark1.used_by_s0_flg = syn->sp.used_by_s0_flg; + regs->synt_ref_mark2.dlt_poc_s0_m10 = syn->sp.dlt_poc_s0_m10; + regs->synt_ref_mark2.dlt_poc_s0_m11 = syn->sp.dlt_poc_s0_m11; + regs->synt_ref_mark3.dlt_poc_s0_m12 = syn->sp.dlt_poc_s0_m12; + regs->synt_ref_mark3.dlt_poc_s0_m13 = syn->sp.dlt_poc_s0_m13; + + regs->synt_ref_mark4.poc_lsb_lt1 = syn->sp.poc_lsb_lt1; + regs->synt_ref_mark5.dlt_poc_msb_cycl1 = syn->sp.dlt_poc_msb_cycl1; + regs->synt_ref_mark4.poc_lsb_lt2 = syn->sp.poc_lsb_lt2; + regs->synt_ref_mark1.dlt_poc_msb_prsnt2 = syn->sp.dlt_poc_msb_prsnt2; + regs->synt_ref_mark5.dlt_poc_msb_cycl2 = syn->sp.dlt_poc_msb_cycl2; + regs->synt_sli1.lst_entry_l0 = syn->sp.lst_entry_l0; + regs->synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + return; +} +static void vepu541_h265_set_me_regs(H265eV541HalContext *ctx, H265eSyntax_new *syn, H265eV541RegSet *regs) +{ + + RK_U32 cime_w = 11, cime_h = 7; + RK_S32 merangx = (cime_w + 1) * 32; + RK_S32 merangy = (cime_h + 1) * 32; + RK_S32 pic_wd64 = MPP_ALIGN(syn->pp.pic_width, 64) >> 6; + + if (merangx > 384) { + merangx = 384; + } + if (merangy > 320) { + merangy = 320; + } + + if (syn->pp.pic_width < merangx + 60 || syn->pp.pic_width <= 352) { + if (merangx > syn->pp.pic_width ) { + merangx = syn->pp.pic_width; + } + merangx = merangx / 4 * 2; + } + + if (syn->pp.pic_height < merangy + 60 || syn->pp.pic_height <= 288) { + if (merangy > syn->pp.pic_height) { + merangy = syn->pp.pic_height; + } + merangy = merangy / 4 * 2; + } + + { + RK_S32 merange_x = merangx / 2; + RK_S32 merange_y = merangy / 2; + RK_S32 mxneg = ((-(merange_x << 2)) >> 2) / 4; + RK_S32 myneg = ((-(merange_y << 2)) >> 2) / 4; + RK_S32 mxpos = (((merange_x << 2) - 4) >> 2) / 4; + RK_S32 mypos = (((merange_y << 2) - 4) >> 2) / 4; + + mxneg = MPP_MIN(abs(mxneg), mxpos) * 4; + myneg = MPP_MIN(abs(myneg), mypos) * 4; + + merangx = mxneg * 2; + merangy = myneg * 2; + } + regs->me_rnge.cime_srch_h = merangx / 32; + regs->me_rnge.cime_srch_v = merangy / 32; + + regs->me_rnge.rime_srch_h = 7; + regs->me_rnge.rime_srch_v = 5; + regs->me_rnge.dlt_frm_num = 0x1; + + regs->me_cnst.pmv_mdst_h = 5; + regs->me_cnst.pmv_mdst_v = 5; + regs->me_cnst.mv_limit = 0; + regs->me_cnst.mv_num = 2; + + if (syn->pp.sps_temporal_mvp_enabled_flag && + (ctx->frame_type != INTRA_FRAME)) { + if (ctx->last_frame_type == INTRA_FRAME) { + regs->me_cnst.colmv_load = 0; + } else { + regs->me_cnst.colmv_load = 1; + } + regs->me_cnst.colmv_store = 1; + } + + if (syn->pp.pic_width > 2688) { + regs->me_ram.cime_rama_h = 12; + } else if (syn->pp.pic_width > 2048) { + regs->me_ram.cime_rama_h = 16; + } else { + regs->me_ram.cime_rama_h = 20; + } + + { + RK_S32 swin_scope_wd16 = (regs->me_rnge.cime_srch_h + 3 + 1) / 4 * 2 + 1; + RK_S32 tmpMin = (regs->me_rnge.cime_srch_v + 3) / 4 * 2 + 1; + if (regs->me_ram.cime_rama_h / 4 < tmpMin) { + tmpMin = regs->me_ram.cime_rama_h / 4; + } + regs->me_ram.cime_rama_max = + (pic_wd64 * (tmpMin - 1)) + ((pic_wd64 >= swin_scope_wd16) ? swin_scope_wd16 : pic_wd64 * 2); + } + regs->me_ram.cach_l2_tag = 0x0; + + pic_wd64 = pic_wd64 << 6; + + if (pic_wd64 <= 512) + regs->me_ram.cach_l2_tag = 0x0; + else if (pic_wd64 <= 1024) + regs->me_ram.cach_l2_tag = 0x1; + else if (pic_wd64 <= 2048) + regs->me_ram.cach_l2_tag = 0x2; + else if (pic_wd64 <= 4096) + regs->me_ram.cach_l2_tag = 0x3; +} + +static void vepu540_h265_set_me_ram(H265eSyntax_new *syn, H265eV541RegSet *regs, + RK_U32 index, RK_S32 tile_start_x) +{ + RK_U32 cime_w = 11, cime_h = 7; + RK_U32 pic_cime_temp = 0; + if (syn->pp.tiles_enabled_flag == 0) { + pic_cime_temp = ((regs->enc_rsl.pic_wd8_m1 + 1) * 8 + 63) / 64 * 64; + regs->me_ram.cime_linebuf_w = pic_cime_temp / 64; + } else { + RK_S32 pic_wd64 = MPP_ALIGN(syn->pp.pic_width, 64) >> 6; + RK_S32 tile_ctu_stax = tile_start_x; + RK_S32 tile_ctu_endx = tile_start_x + syn->pp.column_width_minus1[index]; + RK_S32 cime_srch_w = regs->me_rnge.cime_srch_h; + + if (tile_ctu_stax < (cime_srch_w + 3) / 4) { + if (tile_ctu_endx + 1 + (cime_srch_w + 3) / 4 > pic_wd64) + pic_cime_temp = pic_wd64 * 64; + else + pic_cime_temp = (tile_ctu_endx + 1 + (cime_srch_w + 3) / 4) * 64; + } else { + if (tile_ctu_endx + 1 + (cime_srch_w + 3) / 4 > pic_wd64) + pic_cime_temp = (pic_wd64 - tile_ctu_stax + (cime_srch_w + 3) / 4) * 64; + else + pic_cime_temp = (tile_ctu_endx - tile_ctu_stax + 1 + (cime_srch_w + 3) / 4 * 2) * 64; + } + regs->me_ram.cime_linebuf_w = pic_cime_temp / 64; + + } + + { + + RK_S32 w_temp = 1296; + RK_S32 h_temp = 4; + RK_S32 h_val_0 = 4; + RK_S32 h_val_1 = 24; + + while ((w_temp > ((h_temp - h_val_0)*regs->me_ram.cime_linebuf_w * 4 + ((h_val_1 - h_temp) * 4 * 7))) + && (h_temp < 17)) { + h_temp = h_temp + h_val_0; + } + if (w_temp < (RK_S32)((h_temp - h_val_0)*regs->me_ram.cime_linebuf_w * 4 + ((h_val_1 - h_temp) * 4 * 7))) + h_temp = h_temp - h_val_0; + + regs->me_ram.cime_rama_h = h_temp; + } + + // calc cime_rama_max + { + RK_S32 pic_wd64 = pic_cime_temp / 64; + RK_S32 swin_scope_wd16 = (cime_w + 3 + 1) / 4 * 2 + 1; + RK_S32 tmpMin = (cime_h + 3) / 4 * 2 + 1; + if (regs->me_ram.cime_rama_h / 4 < tmpMin) { + tmpMin = regs->me_ram.cime_rama_h / 4; + } + regs->me_ram.cime_rama_max = (pic_wd64 * (tmpMin - 1)) + ((pic_wd64 >= swin_scope_wd16) ? swin_scope_wd16 : pic_wd64 * 2); + } + + hal_h265e_dbg_detail("cime_rama_h %d, cime_rama_max %d, cime_linebuf_w %d", + regs->me_ram.cime_rama_h, regs->me_ram.cime_rama_max, regs->me_ram.cime_linebuf_w); +} +void vepu54x_h265_set_hw_address(H265eV541HalContext *ctx, H265eV541RegSet *regs, HalEncTask *task) +{ + HalEncTask *enc_task = task; + HalBuf *recon_buf, *ref_buf; + MppBuffer md_info_buf = enc_task->md_info; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + + hal_h265e_enter(); + + regs->adr_srcy_hevc = mpp_buffer_get_fd(enc_task->input); + regs->adr_srcu_hevc = regs->adr_srcy_hevc; + regs->adr_srcv_hevc = regs->adr_srcy_hevc; + + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.recon_pic.slot_idx); + ref_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.ref_pic.slot_idx); + if (!syn->sp.non_reference_flag) { + regs->rfpw_h_addr_hevc = mpp_buffer_get_fd(recon_buf->buf[0]); + regs->rfpw_b_addr_hevc = regs->rfpw_h_addr_hevc; + + mpp_dev_set_reg_offset(ctx->dev, 75, ctx->fbc_header_len); + } + + regs->dspw_addr_hevc = mpp_buffer_get_fd(recon_buf->buf[1]); + regs->cmvw_addr_hevc = mpp_buffer_get_fd(recon_buf->buf[2]); + regs->rfpr_h_addr_hevc = mpp_buffer_get_fd(ref_buf->buf[0]); + regs->rfpr_b_addr_hevc = regs->rfpr_h_addr_hevc; + regs->dspr_addr_hevc = mpp_buffer_get_fd(ref_buf->buf[1]); + regs->cmvr_addr_hevc = mpp_buffer_get_fd(ref_buf->buf[2]); + + mpp_dev_set_reg_offset(ctx->dev, 77, ctx->fbc_header_len); + + if (syn->pp.tiles_enabled_flag) { + if (NULL == ctx->tile_grp) + mpp_buffer_group_get_internal(&ctx->tile_grp, MPP_BUFFER_TYPE_ION); + + mpp_assert(ctx->tile_grp); + + if (NULL == ctx->hw_tile_buf[0]) { + mpp_buffer_get(ctx->tile_grp, &ctx->hw_tile_buf[0], TILE_BUF_SIZE); + } + + if (NULL == ctx->hw_tile_buf[1]) { + mpp_buffer_get(ctx->tile_grp, &ctx->hw_tile_buf[1], TILE_BUF_SIZE); + } + + regs->lpfw_addr_hevc = mpp_buffer_get_fd(ctx->hw_tile_buf[0]); + regs->lpfr_addr_hevc = mpp_buffer_get_fd(ctx->hw_tile_buf[1]); + } + + if (md_info_buf) { + regs->enc_pic.mei_stor = 1; + regs->meiw_addr_hevc = mpp_buffer_get_fd(md_info_buf); + } else { + regs->enc_pic.mei_stor = 0; + regs->meiw_addr_hevc = 0; + } + + regs->bsbb_addr_hevc = mpp_buffer_get_fd(enc_task->output); + /* TODO: stream size relative with syntax */ + regs->bsbt_addr_hevc = regs->bsbb_addr_hevc; + regs->bsbr_addr_hevc = regs->bsbb_addr_hevc; + regs->bsbw_addr_hevc = regs->bsbb_addr_hevc; + + mpp_dev_set_reg_offset(ctx->dev, 86, mpp_packet_get_length(task->packet)); + + regs->pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); +} + +static void setup_vepu541_split(H265eV541RegSet *regs, MppEncSliceSplit *cfg) +{ + hal_h265e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->sli_spl.sli_splt = 0; + regs->sli_spl.sli_splt_mode = 0; + regs->sli_spl.sli_splt_cpst = 0; + regs->sli_spl.sli_max_num_m1 = 0; + regs->sli_spl.sli_flsh = 0; + regs->sli_spl.sli_splt_cnum_m1 = 0; + + regs->sli_spl_byte.sli_splt_byte = 0; + regs->enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->sli_spl.sli_splt = 1; + regs->sli_spl.sli_splt_mode = 0; + regs->sli_spl.sli_splt_cpst = 0; + regs->sli_spl.sli_max_num_m1 = 500; + regs->sli_spl.sli_flsh = 1; + regs->sli_spl.sli_splt_cnum_m1 = 0; + + regs->sli_spl_byte.sli_splt_byte = cfg->split_arg; + regs->enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + regs->sli_spl.sli_splt = 1; + regs->sli_spl.sli_splt_mode = 1; + regs->sli_spl.sli_splt_cpst = 0; + regs->sli_spl.sli_max_num_m1 = 500; + regs->sli_spl.sli_flsh = 1; + regs->sli_spl.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->sli_spl_byte.sli_splt_byte = 0; + regs->enc_pic.slen_fifo = 0; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h265e_dbg_func("leave\n"); +} + +MPP_RET hal_h265e_v541_gen_regs(void *hal, HalEncTask *task) +{ + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + HalEncTask *enc_task = task; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + H265eV541RegSet *regs = ctx->regs; + RK_U32 pic_width_align8, pic_height_align8; + RK_S32 pic_wd64, pic_h64; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h265e_enter(); + pic_width_align8 = (syn->pp.pic_width + 7) & (~7); + pic_height_align8 = (syn->pp.pic_height + 7) & (~7); + pic_wd64 = (syn->pp.pic_width + 63) / 64; + pic_h64 = (syn->pp.pic_height + 63) / 64; + + hal_h265e_dbg_simple("frame %d | type %d | start gen regs", + ctx->frame_cnt, ctx->frame_type); + + + memset(regs, 0, sizeof(H265eV541RegSet)); + regs->enc_strt.lkt_num = 0; + regs->enc_strt.rkvenc_cmd = ctx->enc_mode; + regs->enc_strt.enc_cke = 1; + regs->enc_clr.safe_clr = 0x0; + + regs->lkt_addr.lkt_addr = 0x0; + regs->int_en.enc_done_en = 1; + regs->int_en.lkt_done_en = 1; + regs->int_en.sclr_done_en = 1; + regs->int_en.slc_done_en = 1; + regs->int_en.bsf_ovflw_en = 1; + regs->int_en.brsp_ostd_en = 1; + regs->int_en.wbus_err_en = 1; + regs->int_en.rbus_err_en = 1; + regs->int_en.wdg_en = 0; + + regs->enc_rsl.pic_wd8_m1 = pic_width_align8 / 8 - 1; + regs->enc_rsl.pic_wfill = ((syn->pp.pic_width & 0x7) != 0) + ? (8 - (syn->pp.pic_width & 0x7)) : 0; + regs->enc_rsl.pic_hd8_m1 = pic_height_align8 / 8 - 1; + regs->enc_rsl.pic_hfill = ((syn->pp.pic_height & 0x7) != 0) + ? (8 - (syn->pp.pic_height & 0x7)) : 0; + + regs->enc_pic.enc_stnd = 1; //H265 + regs->enc_pic.cur_frm_ref = !syn->sp.non_reference_flag; //current frame will be refered + regs->enc_pic.bs_scp = 1; + regs->enc_pic.node_int = 0; + regs->enc_pic.log2_ctu_num = ceil(log2((double)pic_wd64 * pic_h64)); + + regs->enc_pic.rdo_wgt_sel = (ctx->frame_type == INTRA_FRAME) ? 0 : 1; + + regs->enc_wdg.vs_load_thd = 0; + regs->enc_wdg.rfp_load_thd = 0; + + if (ctx->is_vepu540) { + regs->dtrns_cfg_540.cime_dspw_orsd = (ctx->frame_type == INTER_P_FRAME); + regs->dtrns_cfg_540.axi_brsp_cke = 0x0; + } else { + regs->dtrns_cfg_541.cime_dspw_orsd = (ctx->frame_type == INTER_P_FRAME); + regs->dtrns_cfg_541.axi_brsp_cke = 0x0; + } + + regs->dtrns_map.lpfw_bus_ordr = 0x0; + regs->dtrns_map.cmvw_bus_ordr = 0x0; + regs->dtrns_map.dspw_bus_ordr = 0x0; + regs->dtrns_map.rfpw_bus_ordr = 0x0; + regs->dtrns_map.src_bus_edin = 0x0; + regs->dtrns_map.meiw_bus_edin = 0x0; + regs->dtrns_map.bsw_bus_edin = 0x7; + regs->dtrns_map.lktr_bus_edin = 0x0; + regs->dtrns_map.roir_bus_edin = 0x0; + regs->dtrns_map.lktw_bus_edin = 0x0; + regs->dtrns_map.afbc_bsize = 0x1; + + + regs->src_proc.src_mirr = 0; + regs->src_proc.src_rot = 0; + regs->src_proc.txa_en = 1; + regs->src_proc.afbcd_en = (MPP_FRAME_FMT_IS_FBC(syn->pp.mpp_format) != 0) ? 1 : 0; + + if (!ctx->is_vepu540) + vepu541_h265_set_patch_info(ctx->dev, syn, (VepuFmt)fmt->format, task); + + regs->klut_ofst.chrm_kult_ofst = (ctx->frame_type == INTRA_FRAME) ? 0 : 3; + memcpy(®s->klut_wgt0, &klut_weight[0], sizeof(klut_weight)); + + regs->adr_srcy_hevc = mpp_buffer_get_fd(enc_task->input); + regs->adr_srcu_hevc = regs->adr_srcy_hevc; + regs->adr_srcv_hevc = regs->adr_srcy_hevc; + + setup_vepu541_split(regs, &ctx->cfg->split); + + vepu541_h265_set_me_regs(ctx, syn, regs); + + regs->rdo_cfg.chrm_special = 1; + regs->rdo_cfg.cu_inter_en = 0xf; + regs->rdo_cfg.cu_intra_en = 0xf; + + if (syn->pp.num_long_term_ref_pics_sps) { + regs->rdo_cfg.ltm_col = 0; + regs->rdo_cfg.ltm_idx0l0 = 1; + } else { + regs->rdo_cfg.ltm_col = 0; + regs->rdo_cfg.ltm_idx0l0 = 0; + } + + regs->rdo_cfg.chrm_klut_en = 1; + regs->rdo_cfg.seq_scaling_matrix_present_flg = syn->pp.scaling_list_enabled_flag; + regs->synt_nal.nal_unit_type = h265e_get_nal_type(&syn->sp, ctx->frame_type); + + vepu54x_h265_set_hw_address(ctx, regs, task); + vepu541_h265_set_pp_regs(fmt, ctx, task); + + vepu541_h265_set_rc_regs(ctx, regs, task); + + vepu541_h265_set_slice_regs(syn, regs); + + vepu541_h265_set_ref_regs(syn, regs); + if (ctx->is_vepu540) { + vepu540_set_osd(&ctx->osd_cfg); + } else { + vepu541_set_osd(&ctx->osd_cfg); + } + /* ROI configure */ + vepu541_h265_set_roi_regs(ctx, regs); + + if (frm_status->is_i_refresh) + setup_vepu541_intra_refresh(regs, ctx, frm_status->seq_idx % ctx->cfg->rc.gop); + + ctx->frame_num++; + + hal_h265e_leave(); + return MPP_OK; +} +void hal_h265e_v540_set_uniform_tile(H265eV541RegSet *regs, H265eSyntax_new *syn, + RK_U32 index, RK_S32 tile_start_x) +{ + if (syn->pp.tiles_enabled_flag) { + RK_S32 mb_h = MPP_ALIGN(syn->pp.pic_height, 64) / 64; + RK_S32 tile_width = syn->pp.column_width_minus1[index] + 1; + + regs->tile_cfg.tile_width_m1 = tile_width - 1; + regs->tile_cfg.tile_height_m1 = mb_h - 1; + regs->rc_cfg.rc_ctu_num = tile_width; + regs->tile_cfg.tile_en = syn->pp.tiles_enabled_flag; + regs->tile_pos.tile_x = tile_start_x; + regs->tile_pos.tile_y = 0; + if (index > 0) { + RK_U32 tmp = regs->lpfr_addr_hevc; + regs->lpfr_addr_hevc = regs->lpfw_addr_hevc; + regs->lpfw_addr_hevc = tmp; + } + + hal_h265e_dbg_detail("tile_x %d, rc_ctu_num %d, tile_width_m1 %d", + regs->tile_pos.tile_x, regs->rc_cfg.rc_ctu_num, + regs->tile_cfg.tile_width_m1); + } +} + +MPP_RET hal_h265e_v540_start(void *hal, HalEncTask *enc_task) +{ + MPP_RET ret = MPP_OK; + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + RK_U32 length = 0, k = 0; + H265eV541IoctlOutputElem *reg_out = (H265eV541IoctlOutputElem *)ctx->reg_out; + H265eSyntax_new *syn = (H265eSyntax_new *)enc_task->syntax.data; + RK_U32 title_num = (syn->pp.num_tile_columns_minus1 + 1) * (syn->pp.num_tile_rows_minus1 + 1); + hal_h265e_enter(); + RK_U32 stream_len = 0; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + RK_S32 tile_start_x = 0; + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + for (k = 0; k < title_num; k++) { //v540 no support link list + RK_U32 i; + RK_U32 *regs = (RK_U32*)ctx->regs; + H265eV541RegSet *hw_regs = ctx->regs; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + + vepu540_h265_set_me_ram(syn, hw_regs, k, tile_start_x); + + /* set input info */ + vepu541_h265_set_l2_regs(ctx, (H265eV54xL2RegSet*)ctx->l2_regs); + vepu541_h265_set_patch_info(ctx->dev, syn, (VepuFmt)fmt->format, enc_task); + if (title_num > 1) + hal_h265e_v540_set_uniform_tile(hw_regs, syn, k, tile_start_x); + if (k > 0) { + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + + offset += stream_len; + hw_regs->bsbb_addr_hevc = mpp_buffer_get_fd(enc_task->output); + hw_regs->bsbw_addr_hevc = hw_regs->bsbb_addr_hevc; + mpp_dev_set_reg_offset(ctx->dev, 86, offset); + mpp_dev_set_reg_offset(ctx->dev, 75, ctx->fbc_header_len); + mpp_dev_set_reg_offset(ctx->dev, 77, ctx->fbc_header_len); + } + + cfg.reg = ctx->regs; + cfg.size = sizeof(H265eV541RegSet); + cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU541_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + cfg1.reg = ®_out->st_bsl; + cfg1.size = sizeof(H265eV541IoctlOutputElem) - 4; + cfg1.offset = VEPU541_REG_BASE_STATISTICS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + for (i = 0; i < sizeof(H265eV541RegSet) / 4; i++) { + hal_h265e_dbg_regs("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + + if (k < title_num - 1) { + vepu541_h265_fbk *fb = &ctx->feedback; + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + + stream_len += reg_out->st_bsl.bs_lgth; + fb->qp_sum += reg_out->st_sse_qp.qp_sum; + fb->out_strm_size += reg_out->st_bsl.bs_lgth; + fb->sse_sum += reg_out->st_sse_l32.sse_l32 + + ((RK_S64)(reg_out->st_sse_qp.sse_h8 & 0xff) << 32); + fb->st_madi += reg_out->st_madi; + fb->st_madp += reg_out->st_madi; + fb->st_mb_num += reg_out->st_mb_num; + fb->st_ctu_num += reg_out->st_ctu_num; + + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } + + } + tile_start_x += (syn->pp.column_width_minus1[k] + 1); + } + + hal_h265e_dbg_detail("vpu client is sending %d regs", length); + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_v541_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + RK_U32 length = 0; + HalEncTask *enc_task = task; + H265eV541IoctlOutputElem *reg_out = (H265eV541IoctlOutputElem *)ctx->reg_out; + RK_U32 i; + RK_U32 *regs = (RK_U32*)ctx->regs; + hal_h265e_enter(); + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + vepu541_h265_set_l2_regs(ctx, (H265eV54xL2RegSet*)ctx->l2_regs); + + do { + MppDevRegWrCfg cfg; + + cfg.reg = ctx->regs; + cfg.size = sizeof(H265eV541RegSet); + cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + MppDevRegRdCfg cfg1; + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU541_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + cfg1.reg = ®_out->st_bsl; + cfg1.size = sizeof(H265eV541IoctlOutputElem) - 4; + cfg1.offset = VEPU541_REG_BASE_STATISTICS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + for (i = 0; i < sizeof(H265eV541RegSet) / 4; i++) { + hal_h265e_dbg_regs("set reg[%04d]: 0%08x\n", i, regs[i]); + } + + hal_h265e_dbg_detail("vpu client is sending %d regs", length); + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_v54x_start(void *hal, HalEncTask *task) +{ + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + task->hw_length = 0; + if (ctx->is_vepu540) { + return hal_h265e_v540_start(hal, task); + } else { + return hal_h265e_v541_start(hal, task); + } + return MPP_OK; +} + +static MPP_RET vepu541_h265_set_feedback(H265eV541HalContext *ctx, HalEncTask *enc_task) +{ + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&enc_task->rc_task->info; + vepu541_h265_fbk *fb = &ctx->feedback; + MppEncCfgSet *cfg = ctx->cfg; + RK_S32 mb64_num = ((cfg->prep.width + 63) / 64) * ((cfg->prep.height + 63) / 64); + RK_S32 mb8_num = (mb64_num << 6); + RK_S32 mb4_num = (mb8_num << 2); + + hal_h265e_enter(); + H265eV541IoctlOutputElem *elem = (H265eV541IoctlOutputElem *)ctx->reg_out; + RK_U32 hw_status = elem->hw_status; + fb->qp_sum += elem->st_sse_qp.qp_sum; + fb->out_strm_size += elem->st_bsl.bs_lgth; + fb->sse_sum += elem->st_sse_l32.sse_l32 + + ((RK_S64)(elem->st_sse_qp.sse_h8 & 0xff) << 32); + + fb->hw_status = hw_status; + hal_h265e_dbg_detail("hw_status: 0x%08x", hw_status); + if (hw_status & RKV_ENC_INT_LINKTABLE_FINISH) + hal_h265e_err("RKV_ENC_INT_LINKTABLE_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_FRAME_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_FRAME_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_SLICE_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_SLICE_FINISH"); + + if (hw_status & RKV_ENC_INT_SAFE_CLEAR_FINISH) + hal_h265e_err("RKV_ENC_INT_SAFE_CLEAR_FINISH"); + + if (hw_status & RKV_ENC_INT_BIT_STREAM_OVERFLOW) + hal_h265e_err("RKV_ENC_INT_BIT_STREAM_OVERFLOW"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_FULL) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_FULL"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_ERROR"); + + if (hw_status & RKV_ENC_INT_BUS_READ_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_READ_ERROR"); + + if (hw_status & RKV_ENC_INT_TIMEOUT_ERROR) + hal_h265e_err("RKV_ENC_INT_TIMEOUT_ERROR"); + + fb->st_madi += elem->st_madi; + fb->st_madp += elem->st_madp; + fb->st_mb_num += elem->st_mb_num; + fb->st_ctu_num += elem->st_ctu_num; + + if (fb->st_mb_num) { + fb->st_madi = fb->st_madi / fb->st_mb_num; + } else { + fb->st_madi = 0; + } + if (fb->st_ctu_num) { + fb->st_madp = fb->st_madp / fb->st_ctu_num; + } else { + fb->st_madp = 0; + } + + fb->st_lvl64_inter_num = elem->st_lvl64_inter_num; + fb->st_lvl32_inter_num = elem->st_lvl32_inter_num; + fb->st_lvl32_intra_num = elem->st_lvl32_intra_num; + fb->st_lvl16_inter_num = elem->st_lvl16_inter_num; + fb->st_lvl16_intra_num = elem->st_lvl16_intra_num; + fb->st_lvl8_inter_num = elem->st_lvl8_inter_num; + fb->st_lvl8_intra_num = elem->st_lvl8_intra_num; + fb->st_lvl4_intra_num = elem->st_lvl4_intra_num; + memcpy(&fb->st_cu_num_qp[0], &elem->st_cu_num_qp[0], sizeof(elem->st_cu_num_qp)); + + hal_rc_ret->madi = fb->st_madi; + hal_rc_ret->madp = fb->st_madp; + hal_rc_ret->bit_real = fb->out_strm_size * 8; + + if (mb4_num > 0) + hal_rc_ret->iblk4_prop = ((((fb->st_lvl4_intra_num + fb->st_lvl8_intra_num) << 2) + + (fb->st_lvl16_intra_num << 4) + + (fb->st_lvl32_intra_num << 6)) << 8) / mb4_num; + + if (mb64_num > 0) { + /* + hal_cfg[k].inter_lv8_prop = ((fb->st_lvl8_inter_num + (fb->st_lvl16_inter_num << 2) + + (fb->st_lvl32_inter_num << 4) + + (fb->st_lvl64_inter_num << 6)) << 8) / mb8_num;*/ + + hal_rc_ret->quality_real = fb->qp_sum / mb8_num; + // hal_cfg[k].sse = fb->sse_sum / mb64_num; + } + + hal_h265e_leave(); + + return MPP_OK; +} + + +MPP_RET hal_h265e_v541_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + HalEncTask *enc_task = task; + H265eV541IoctlOutputElem *elem = (H265eV541IoctlOutputElem *)ctx->reg_out; + hal_h265e_enter(); + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d status %d \n", ret, elem->hw_status); + + hal_h265e_leave(); + return ret; +} + +MPP_RET hal_h265e_v541_get_task(void *hal, HalEncTask *task) +{ + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + MppFrame frame = task->frame; + EncFrmStatus *frm_status = &task->rc_task->frm; + + hal_h265e_enter(); + + if (vepu54x_h265_setup_hal_bufs(ctx)) { + hal_h265e_err("vepu541_h265_allocate_buffers failed, free buffers and return\n"); + task->flags.err |= HAL_ENC_TASK_ERR_ALLOC; + return MPP_ERR_MALLOC; + } + + if (!frm_status->reencode) + ctx->last_frame_type = ctx->frame_type; + + if (frm_status->is_intra) { + ctx->frame_type = INTRA_FRAME; + } else { + ctx->frame_type = INTER_P_FRAME; + } + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr_d(meta, KEY_ROI_DATA, (void **)&ctx->roi_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_ROI_DATA2, (void **)&ctx->roi_data2, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA, (void **)&ctx->osd_cfg.osd_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA2, (void **)&ctx->osd_cfg.osd_data2, NULL); + mpp_meta_get_buffer_d(meta, KEY_QPMAP0, &ctx->qpmap, NULL); + } + memset(&ctx->feedback, 0, sizeof(vepu541_h265_fbk)); + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v541_ret_task(void *hal, HalEncTask *task) +{ + H265eV541HalContext *ctx = (H265eV541HalContext *)hal; + HalEncTask *enc_task = task; + vepu541_h265_fbk *fb = &ctx->feedback; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + + hal_h265e_enter(); + + vepu541_h265_set_feedback(ctx, enc_task); + mpp_buffer_sync_partial_begin(enc_task->output, offset, fb->out_strm_size); + hal_h265e_amend_temporal_id(task, fb->out_strm_size); + + rc_info->sse = fb->sse_sum; + rc_info->lvl64_inter_num = fb->st_lvl64_inter_num; + rc_info->lvl32_inter_num = fb->st_lvl32_inter_num; + rc_info->lvl16_inter_num = fb->st_lvl16_inter_num; + rc_info->lvl8_inter_num = fb->st_lvl8_inter_num; + rc_info->lvl32_intra_num = fb->st_lvl32_intra_num; + rc_info->lvl16_intra_num = fb->st_lvl16_intra_num; + rc_info->lvl8_intra_num = fb->st_lvl8_intra_num; + rc_info->lvl4_intra_num = fb->st_lvl4_intra_num; + + enc_task->hw_length = fb->out_strm_size; + enc_task->length += fb->out_strm_size; + + hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); + + hal_h265e_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_h265e_vepu541 = { + .name = "h265e_v541_v2", + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(H265eV541HalContext), + .flag = 0, + .init = hal_h265e_v541_init, + .deinit = hal_h265e_v541_deinit, + .prepare = hal_h265e_vepu54x_prepare, + .get_task = hal_h265e_v541_get_task, + .gen_regs = hal_h265e_v541_gen_regs, + .start = hal_h265e_v54x_start, + .wait = hal_h265e_v541_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h265e_v541_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h265e_vepu541) diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu541.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu541.h new file mode 100644 index 000000000..2ddf8bffd --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu541.h @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_VEPU541_H +#define HAL_H265E_VEPU541_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h265e_vepu541; + +#endif /* HAL_H265E_VEPU541_H */ + diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu541_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu541_reg.h new file mode 100644 index 000000000..7b2193560 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu541_reg.h @@ -0,0 +1,990 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_VEPU541_REG_H +#define HAL_H265E_VEPU541_REG_H + +#include "rk_type.h" + +/* OSD position */ +typedef struct { + RK_U32 lt_pos_x : 8; /* left-top */ + RK_U32 lt_pos_y : 8; + RK_U32 rd_pos_x : 8; /* right-bottom */ + RK_U32 rd_pos_y : 8; +} OsdPos; + +/* OSD palette */ +typedef struct { + RK_U32 y : 8; + RK_U32 u : 8; + RK_U32 v : 8; + RK_U32 alpha : 8; +} OsdPlt; +typedef struct { + RK_U32 axi_brsp_cke : 7; + RK_U32 cime_dspw_orsd : 1; + RK_U32 reserve : 24; +} v541_dtrns_cfg; + +typedef struct { + RK_U32 Reserve0 : 7; + RK_U32 cime_dspw_orsd : 1; + RK_U32 reserve1 : 8; + RK_U32 axi_brsp_cke : 8; + RK_U32 reserve2 : 8; +} v540_dtrns_cfg; + +typedef struct H265eV541RegSet_t { + + /* reg[000] */ + /* 0x0 - VERSION, swreg01 */ + struct { + RK_U32 rkvenc_ver : 32; //default : 0x0000_0001 + } version; + + /* 0x4 - swreg02, ENC_STRT */ + struct { + RK_U32 lkt_num : 8; + RK_U32 rkvenc_cmd : 2; + RK_U32 reserve : 6; + RK_U32 enc_cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 enc_done_tmvp_en : 1; + RK_U32 Reserve : 13; + } enc_strt; + + /* 0x8 - ENC_CLR */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserve : 30; + } enc_clr;//swreg03 + + /* 0xc - swreg04, LKT_ADDR */ + struct { + RK_U32 lkt_addr : 32; + } lkt_addr; + + /* 0x10 - swreg05, INT_EN */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 slc_done_en : 1; + RK_U32 bsf_ovflw_en : 1; + RK_U32 brsp_ostd_en : 1; + RK_U32 wbus_err_en : 1; + RK_U32 rbus_err_en : 1; + RK_U32 wdg_en : 1; + RK_U32 reserve : 23; + } int_en; + + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 slc_done_msk : 1; + RK_U32 bsf_folw_msk : 1; + RK_U32 brsp_otsd_msk : 1; + RK_U32 wbus_err_msk : 1; + RK_U32 rbus_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 reserved : 23;; + } int_msk; //swreg06, INT_MSK + + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 slc_done_clr : 1; + RK_U32 bsf_folw_clr : 1; + RK_U32 brsp_otsd_clr : 1; + RK_U32 wbus_err_clr : 1; + RK_U32 rbus_err_clr : 1; + RK_U32 wdg_msk : 1; + RK_U32 reserved : 23; + } int_clr; //swreg07, INT_CLR + + /* 0x1C - swreg08, INT_STA */ + struct { + RK_U32 reserve : 32; + } int_stus; + + RK_U32 reserved_0x20_0x2c[4]; + + /* 0x30 - swreg09, ENC_RSL */ + struct { + RK_U32 pic_wd8_m1 : 9; + RK_U32 reserve0 : 1; + RK_U32 pic_wfill : 6; + RK_U32 pic_hd8_m1 : 9; + RK_U32 reserve1 : 1; + RK_U32 pic_hfill : 6; + } enc_rsl; + + /* 0x34 - ENC_PIC */ + struct { + RK_U32 enc_stnd : 1; + RK_U32 roi_en : 1; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 rdo_wgt_sel : 1; + RK_U32 reserved : 2; + RK_U32 pic_qp : 6; + RK_U32 tot_poc_num : 5; + RK_U32 log2_ctu_num : 4; + RK_U32 atr_thd_sel : 1; + RK_U32 dchs_rxid : 2; + RK_U32 dchs_txid : 2; + RK_U32 dchs_rxe : 1; + RK_U32 satd_byps_en : 1; + RK_U32 slen_fifo : 1; + RK_U32 node_int : 1; + } enc_pic; //swreg10 + + struct { + RK_U32 vs_load_thd : 24; + RK_U32 rfp_load_thd : 8; + } enc_wdg; //swreg11, ENC_WDG + + /* 0x3c - DTRNS_MAP */ + struct { + RK_U32 lpfw_bus_ordr : 1; /* vepu540 used */ + RK_U32 cmvw_bus_ordr : 1; + RK_U32 dspw_bus_ordr : 1; + RK_U32 rfpw_bus_ordr : 1; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 3; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 afbc_bsize : 1; + RK_U32 reserved : 4; + } dtrns_map; //swreg12 + + union { + v541_dtrns_cfg dtrns_cfg_541; + v540_dtrns_cfg dtrns_cfg_540; + }; + + /* 0x44 - SRC_FMT */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_range : 1; + RK_U32 out_fmt_cfg : 1; //vepu540 + RK_U32 reserve : 24; + } src_fmt; + + /* 0x48 - SRC_UDFY */ + struct { + RK_S32 wght_b2y : 9; + RK_S32 wght_g2y : 9; + RK_S32 wght_r2y : 9; + RK_S32 reserved : 5; + } src_udfy; + + /* 0x4c - SRC_UDFU */ + struct { + RK_S32 wght_b2u : 9; + RK_S32 wght_g2u : 9; + RK_S32 wght_r2u : 9; + RK_S32 reserved : 5; + } src_udfu; + + /* 0x50 - SRC_UDFV */ + struct { + RK_S32 wght_b2v : 9; + RK_S32 wght_g2v : 9; + RK_S32 wght_r2v : 9; + RK_S32 reserved : 5; + } src_udfv; + + /* 0x54 - SRC_UDFO */ + struct { + RK_U32 ofst_v : 8; + RK_U32 ofst_u : 8; + RK_U32 ofst_y : 5; + RK_U32 reserve : 11; + } src_udfo; + + /* 0x58 - SRC_PROC */ + struct { + RK_U32 reserved0 : 26; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 txa_en : 1; + RK_U32 afbcd_en : 1; + RK_U32 reserved1 : 1; + } src_proc; + + /* 0x5c - MMU0_DTE_ADDR */ + struct { + RK_U32 tile_width_m1 : 6; + RK_U32 reserved0 : 10; + RK_U32 tile_height_m1 : 6; + RK_U32 reserved1 : 9; + RK_U32 tile_en : 1; + } tile_cfg; + + /* 0x60 - MMU1_DTE_ADDR */ + struct { + RK_U32 tile_x : 6; + RK_U32 reserved0 : 10; + RK_U32 tile_y : 6; + RK_U32 reserved1 : 10; + } tile_pos; + + /* 0x64 - KLUT_OFST */ + struct { + RK_U32 chrm_kult_ofst : 3; + RK_U32 reserved : 29; + } klut_ofst; + + /* 0x68-0xc4 - KLUT_WGT */ + struct { + RK_U32 chrm_klut_wgt0 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt1 : 9; + } klut_wgt0; + + struct { + RK_U32 chrm_klut_wgt1 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt2 : 18; + } klut_wgt1; + + struct { + RK_U32 chrm_klut_wgt3 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt4 : 9; + } klut_wgt2; + + struct { + RK_U32 chrm_klut_wgt4 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt5 : 18; + } klut_wgt3; + + struct { + RK_U32 chrm_klut_wgt6 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt7 : 9; + } klut_wgt4; + + struct { + RK_U32 chrm_klut_wgt7 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt8 : 18; + } klut_wgt5; + + struct { + RK_U32 chrm_klut_wgt9 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt10 : 9; + } klut_wgt6; + + struct { + RK_U32 chrm_klut_wgt10 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt11 : 18; + } klut_wgt7; + + struct { + RK_U32 chrm_klut_wgt12 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt13 : 9; + } klut_wgt8; + + struct { + RK_U32 chrm_klut_wgt13 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt14 : 18; + } klut_wgt9; + + struct { + RK_U32 chrm_klut_wgt15 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt16 : 9; + } klut_wgt10; + + struct { + RK_U32 chrm_klut_wgt16 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt17 : 18; + } klut_wgt11; + + struct { + RK_U32 chrm_klut_wgt18 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt19 : 9; + } klut_wgt12; + + struct { + RK_U32 chrm_klut_wgt19 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt20 : 18; + } klut_wgt13; + + struct { + RK_U32 chrm_klut_wgt21 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt22 : 9; + } klut_wgt14; + + struct { + RK_U32 chrm_klut_wgt22 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt23 : 18; + } klut_wgt15; + + struct { + RK_U32 chrm_klut_wgt24 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt25 : 9; + } klut_wgt16; + + struct { + RK_U32 chrm_klut_wgt25 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt26 : 18; + } klut_wgt17; + + struct { + RK_U32 chrm_klut_wgt27 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt28 : 9; + } klut_wgt18; + + struct { + RK_U32 chrm_klut_wgt28 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt29 : 18; + } klut_wgt19; + + struct { + RK_U32 chrm_klut_wgt30 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt31 : 9; + } klut_wgt20; + + struct { + RK_U32 chrm_klut_wgt31 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt32 : 18; + } klut_wgt21; + + struct { + RK_U32 chrm_klut_wgt33 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt34 : 9; + } klut_wgt22; + + /* 0xc4 - klut_wgt23 */ + struct { + RK_U32 chrm_klut_wgt34 : 9; + RK_U32 reserved : 23; + } klut_wgt23; + + /* 0xc8 - RC_CFG */ + struct { + RK_U32 rc_en : 1; + RK_U32 aqmode_en : 1; + RK_U32 qp_mode : 1; + RK_U32 reserved : 13; + RK_U32 rc_ctu_num : 16; + } rc_cfg; + + /* 0xcc - RC_QP */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } rc_qp; + + /* 0xd0 - swreg55, RC_TGT */ + struct { + RK_U32 ctu_ebits : 20; + RK_U32 reserve : 12; + } rc_tgt; + + /* 0xd4 - RC_ADJ0 */ + struct { + RK_S32 qp_adjust0 : 5; + RK_S32 qp_adjust1 : 5; + RK_S32 qp_adjust2 : 5; + RK_S32 qp_adjust3 : 5; + RK_S32 qp_adjust4 : 5; + RK_S32 reserved : 7; + } rc_adj0; + + /* 0xd8 - RCADJ1 */ + struct { + RK_S32 qp_adjust5 : 5; + RK_S32 qp_adjust6 : 5; + RK_S32 qp_adjust7 : 5; + RK_S32 qp_adjust8 : 5; + RK_S32 reserved : 12; + } rc_adj1; + + /* 0xdc-0xfc swreg47, */ + struct { + RK_S32 bits_thd0; + } rc_erp0; //RC_ERP0 + + struct { + RK_S32 bits_thd1; + } rc_erp1; //swreg48, RC_ERP1 + + struct { + RK_S32 bits_thd2; + } rc_erp2; //swreg49, RC_ERP2 + + struct { + RK_S32 bits_thd3; + } rc_erp3; //swreg50, RC_ERP3 + + struct { + RK_S32 bits_thd4; + } rc_erp4; //swreg51, RC_ERP4 + + /* 0xec-0xf8 */ + struct { + RK_S32 bits_thd5; + } rc_erp5; + + struct { + RK_S32 bits_thd6; + } rc_erp6; + + struct { + RK_S32 bits_thd7; + } rc_erp7; + + /* 0xfc - RC_ERP8 */ + struct { + RK_S32 bits_thd8; + } rc_erp8; + + /* 0x100 - QPMAP0 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } qpmap0; + + /* 0x104 - QPMAP1 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } qpmap1; + + /* 0x108 - QPMAP2 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } qpmap2; + + /* 0x10c - QPMAP3 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 24; + RK_U32 qpmap_mode : 2; + } qpmap3; + + /* 0x110 - PIC_OFST */ + struct { + RK_U32 pic_ofst_y : 13; + RK_U32 reserved0 : 3; + RK_U32 pic_ofst_x : 13; + RK_U32 reserved1 : 3; + } pic_ofst; + + /* 0x114 - swreg23, SRC_STRID */ + struct { + RK_U32 src_ystrid : 16; + RK_U32 src_cstrid : 16; + } src_strid; + + RK_U32 adr_srcy_hevc; /* 0x118 */ + RK_U32 adr_srcu_hevc; + RK_U32 adr_srcv_hevc; + RK_U32 roi_addr_hevc; + RK_U32 rfpw_h_addr_hevc; + RK_U32 rfpw_b_addr_hevc; + RK_U32 rfpr_h_addr_hevc; + RK_U32 rfpr_b_addr_hevc; + RK_U32 cmvw_addr_hevc; + RK_U32 cmvr_addr_hevc; + RK_U32 dspw_addr_hevc; + RK_U32 dspr_addr_hevc; + RK_U32 meiw_addr_hevc; + RK_U32 bsbt_addr_hevc; + RK_U32 bsbb_addr_hevc; + RK_U32 bsbr_addr_hevc; + RK_U32 bsbw_addr_hevc; /* 0x158 */ + + /* 0x15c - swreg41, SLI_SPL */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 sli_max_num_m1 : 10; + RK_U32 sli_flsh : 1; + RK_U32 reserve : 2; + RK_U32 sli_splt_cnum_m1 : 16; + } sli_spl; + + /* 0x160 - swreg42, SLI_SPL_BYTE */ + struct { + RK_U32 sli_splt_byte : 18; + RK_U32 reserve : 14; + } sli_spl_byte; + + /* 0x164 - swreg43, ME_RNGE */ + struct { + RK_U32 cime_srch_h : 4; + RK_U32 cime_srch_v : 4; + RK_U32 rime_srch_h : 3; + RK_U32 rime_srch_v : 3; + RK_U32 reserved : 2; + RK_U32 dlt_frm_num : 16; + } me_rnge; + + /* 0x168 - swreg44, ME_CNST */ + struct { + RK_U32 pmv_mdst_h : 8; + RK_U32 pmv_mdst_v : 8; + RK_U32 mv_limit : 2; + RK_U32 mv_num : 2; + RK_U32 colmv_store : 1; + RK_U32 colmv_load : 1; + RK_U32 rime_dis_en : 5; /* used for rtl debug */ + RK_U32 fme_dis_en : 5; /* used for rtl debug */ + } me_cnst; + + /* 0x16c - ME_RAM */ + struct { + RK_U32 cime_rama_max : 11; + RK_U32 cime_rama_h : 5; + RK_U32 cach_l2_tag : 2; + RK_U32 cime_linebuf_w: 8; /*only used for 540*/ + RK_U32 reserved : 6; + } me_ram; + + /*0x170 - SYNT_REF_MARK4*/ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } synt_ref_mark4; + + /*0x174 SYNT_REF_MARK5*/ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } synt_ref_mark5; + + struct { + RK_U32 osd_ch_inv_en : 8; + RK_U32 osd_itype : 8; + RK_U32 osd_lu_inv_msk : 8; + RK_U32 osd_ch_inv_msk : 8; + } osd_inv_cfg; + RK_U32 lpfw_addr_hevc; + RK_U32 lpfr_addr_hevc; + RK_U32 reserved_0x184_0x190[4]; + + /* 0x194 - REG_THD, reserved */ + RK_U32 reg_thd; + + /* 0x198 - swreg56, RDO_CFG */ + struct { + RK_U32 ltm_col : 1; + RK_U32 ltm_idx0l0 : 1; + RK_U32 chrm_special : 1; + RK_U32 rdoq_en : 1; /* may be used in the future */ + RK_U32 reserved0 : 2; + RK_U32 cu_inter_en : 4; + RK_U32 reserved1 : 9; + RK_U32 cu_intra_en : 4; + RK_U32 chrm_klut_en : 1; + RK_U32 seq_scaling_matrix_present_flg : 2; + RK_U32 reserved2 : 5; + RK_U32 stad_byps_flg : 1; /*only for 540*/ + } rdo_cfg; + + /* 0x19c - swreg57, SYNT_NAL */ + struct { + RK_U32 nal_unit_type : 6; + RK_U32 reserve : 26; + } synt_nal; + + /* 0x1a0 - swreg58, SYNT_SPS */ + struct { + RK_U32 smpl_adpt_ofst_en : 1; + RK_U32 num_st_ref_pic : 7; + RK_U32 lt_ref_pic_prsnt : 1; + RK_U32 num_lt_ref_pic : 6; + RK_U32 tmpl_mvp_en : 1; + RK_U32 log2_max_poc_lsb : 4; + RK_U32 strg_intra_smth : 1; + RK_U32 reserved : 11; + } synt_sps; + + /* 0x1a4 - swreg59, SYNT_PPS */ + struct { + RK_U32 dpdnt_sli_seg_en : 1; + RK_U32 out_flg_prsnt_flg : 1; + RK_U32 num_extr_sli_hdr : 3; + RK_U32 sgn_dat_hid_en : 1; + RK_U32 cbc_init_prsnt_flg : 1; + RK_U32 pic_init_qp : 6; + RK_U32 cu_qp_dlt_en : 1; + RK_U32 chrm_qp_ofst_prsn : 1; + RK_U32 lp_fltr_acrs_sli : 1; + RK_U32 dblk_fltr_ovrd_en : 1; + RK_U32 lst_mdfy_prsnt_flg : 1; + RK_U32 sli_seg_hdr_extn : 1; + RK_U32 cu_qp_dlt_depth : 2; + RK_U32 lpf_fltr_acrs_til : 1; /*only for 540*/ + RK_U32 reserved : 10; + } synt_pps; + + /* 0x1a8 - swreg60, SYNT_SLI0 */ + struct { + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 merge_up_flag : 1; + RK_U32 merge_left_flag : 1; + RK_U32 reserved : 1; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_l1_act : 2; + RK_U32 num_refidx_l0_act : 2; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_en : 1; + RK_U32 pic_out_flg : 1; + RK_U32 sli_type : 2; + RK_U32 sli_rsrv_flg : 7; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 sli_pps_id : 6; + RK_U32 no_out_pri_pic : 1; + } synt_sli0; + + /* 0x1ac - swreg61, SYNT_SLI1 */ + struct { + RK_S32 sli_tc_ofst_div2 : 4; + RK_S32 sli_beta_ofst_div2 : 4; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sli_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_S32 sli_cb_qp_ofst : 5; + RK_U32 sli_qp : 6; + RK_U32 max_mrg_cnd : 3; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 lst_entry_l0 : 4; + RK_U32 reserved : 1; + } synt_sli1; + + /* 0x1b0 - swreg62, SYNT_SLI2_RODR */ + struct { + RK_U32 sli_poc_lsb : 16; + RK_U32 sli_hdr_ext_len : 9; + RK_U32 reserve : 7; + } synt_sli2_rodr; + + /* 0x1b4 - swreg63, SYNT_REF_MARK0 */ + struct { + RK_U32 st_ref_pic_flg : 1; + RK_U32 poc_lsb_lt0 : 16; + RK_U32 lt_idx_sps : 5; + RK_U32 num_lt_pic : 2; + RK_U32 st_ref_pic_idx : 6; + RK_U32 num_lt_sps : 2; + } synt_ref_mark0; + + /* 0x1b8 - swreg64, SYNT_REF_MARK1 */ + struct { + RK_U32 used_by_s0_flg : 4; + RK_U32 num_pos_pic : 1; + RK_U32 num_neg_pic : 5; + RK_U32 dlt_poc_msb_cycl0 : 16; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + } synt_ref_mark1; + + RK_U32 reserved_0x1bc; /* not used for a long time */ + + /* 0x1c0 - OSD_CFG */ + struct { + RK_U32 osd_en : 8; + RK_U32 osd_inv : 8; + RK_U32 osd_clk_sel : 1; + RK_U32 osd_plt_type : 1; + RK_U32 reserved : 14; + } osd_cfg; + + /* 0x1c4 - OSD_INV */ + struct { + RK_U32 osd_inv_r0 : 4; + RK_U32 osd_inv_r1 : 4; + RK_U32 osd_inv_r2 : 4; + RK_U32 osd_inv_r3 : 4; + RK_U32 osd_inv_r4 : 4; + RK_U32 osd_inv_r5 : 4; + RK_U32 osd_inv_r6 : 4; + RK_U32 osd_inv_r7 : 4; + } osd_inv; + + /* 0x1c8 - SYNT_REF_MARK2 */ + struct { + RK_U32 dlt_poc_s0_m10 : 16; + RK_U32 dlt_poc_s0_m11 : 16; + } synt_ref_mark2; + + /* 0x1cc - SYNT_REF_MARK3 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } synt_ref_mark3; + + /* 0x1d0-0x1ec - OSD_POS0-OSD_POS7 */ + OsdPos osd_pos[8]; + + /* 0x1f0-0x20c - OSD_ADDR0-OSD_ADDR7 */ + RK_U32 osd_addr[8]; + + /* 0x210 - ST_BSL */ + struct { + RK_U32 bs_lgth : 32; + } st_bsl; + + /* 0x214 - ST_SSE_L32 */ + struct { + RK_U32 sse_l32 : 32; + } st_sse_l32; + + /* 0x218 - ST_SSE_QP */ + struct { + RK_U32 qp_sum : 24; /* sum of valid CU8x8s' QP */ + RK_U32 sse_h8 : 8; + } st_sse_qp; + + /* 0x21c - ST_SAO */ + struct { + RK_U32 slice_scnum : 12; + RK_U32 slice_slnum : 12; + RK_U32 reserve : 8; + } st_sao; + + /* 0x220 - MMU0_STA, used by hardware?? */ + RK_U32 mmu0_sta; + RK_U32 mmu1_sta; + + /* 0x228 - ST_ENC */ + struct { + RK_U32 st_enc : 2; + RK_U32 axiw_cln : 2; + RK_U32 axir_cln : 2; + RK_U32 reserve : 26; + } st_enc; + + /* 0x22c - ST_LKT */ + struct { + RK_U32 fnum_enc : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 reserve : 8; + } st_lkt; + + /* 0x230 - ST_NOD */ + struct { + RK_U32 node_addr : 32; + } st_nod; + + /* 0x234 - ST_BSB */ + struct { + RK_U32 Bsbw_ovfl : 1; + RK_U32 reserve : 2; + RK_U32 bsbw_addr : 29; + } st_bsb; + + /* 0x238 - ST_DTRNS */ + struct { + RK_U32 axib_idl : 7; + RK_U32 axib_ful : 7; + RK_U32 axib_err : 7; + RK_U32 axir_err : 6; + RK_U32 reserve : 5; + } st_dtrns; + + /* 0x23c - ST_SNUM */ + struct { + RK_U32 slice_num : 6; + RK_U32 reserve : 26; + } st_snum; + + /* 0x240 - ST_SLEN */ + struct { + RK_U32 slice_len : 23; + RK_U32 reserve : 9; + } st_slen; + + /* 0x244-0x340 - debug registers + * ST_LVL64_INTER_NUM etc. + */ + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_ctu_num; /* used for MADP calculation */ + RK_U32 st_madi; + RK_U32 st_mb_num; /* used for MADI calculation */ + +} H265eV541RegSet; + +typedef struct H265eV541IoctlExtraInfoElem_t { + RK_U32 reg_idx; + RK_U32 offset; +} H265eV541IoctlExtraInfoElem; + +typedef struct H265eV541IoctlExtraInfo_t { + RK_U32 magic; + RK_U32 cnt; + H265eV541IoctlExtraInfoElem elem[20]; +} H265eV541IoctlExtraInfo; + +typedef struct H265eV541IoctlOutputElem_t { + RK_U32 hw_status; + + struct { + RK_U32 bs_lgth : 32; + } st_bsl; + + /* 0x214 - ST_SSE_L32 */ + struct { + RK_U32 sse_l32 : 32; + } st_sse_l32; + + /* 0x218 - ST_SSE_QP */ + struct { + RK_U32 qp_sum : 24; /* sum of valid CU8x8s' QP */ + RK_U32 sse_h8 : 8; + } st_sse_qp; + + /* 0x21c - ST_SAO */ + struct { + RK_U32 slice_scnum : 12; + RK_U32 slice_slnum : 12; + RK_U32 reserve : 8; + } st_sao; + + /* 0x220 - MMU0_STA, used by hardware?? */ + RK_U32 mmu0_sta; + RK_U32 mmu1_sta; + + /* 0x228 - ST_ENC */ + struct { + RK_U32 st_enc : 2; + RK_U32 axiw_cln : 2; + RK_U32 axir_cln : 2; + RK_U32 reserve : 26; + } st_enc; + + /* 0x22c - ST_LKT */ + struct { + RK_U32 fnum_enc : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 reserve : 8; + } st_lkt; + + /* 0x230 - ST_NOD */ + struct { + RK_U32 node_addr : 32; + } st_nod; + + /* 0x234 - ST_BSB */ + struct { + RK_U32 Bsbw_ovfl : 1; + RK_U32 reserve : 2; + RK_U32 bsbw_addr : 29; + } st_bsb; + + /* 0x238 - ST_DTRNS */ + struct { + RK_U32 axib_idl : 7; + RK_U32 axib_ful : 7; + RK_U32 axib_err : 7; + RK_U32 axir_err : 6; + RK_U32 reserve : 5; + } st_dtrns; + + /* 0x23c - ST_SNUM */ + struct { + RK_U32 slice_num : 6; + RK_U32 reserve : 26; + } st_snum; + + /* 0x240 - ST_SLEN */ + struct { + RK_U32 slice_len : 23; + RK_U32 reserve : 9; + } st_slen; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_ctu_num; /* used for MADP calculation */ + RK_U32 st_madi; + RK_U32 st_mb_num; /* used for MADI calculation */ +} H265eV541IoctlOutputElem; + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu54x_reg_l2.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu54x_reg_l2.h new file mode 100644 index 000000000..261b79467 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu54x_reg_l2.h @@ -0,0 +1,827 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_VEPU54X_REG_L2_H +#define HAL_H265E_VEPU54X_REG_L2_H + +#include "rk_type.h" + +typedef struct { + /* 0x48 - ATF_THD0 */ + struct { + RK_U32 atf_thd0_i32 : 6; + RK_U32 reserved0 : 10; + RK_U32 atf_thd1_i32 : 6; + RK_U32 reserved1 : 10; + } atf_thd0; + + /* 0x4c - ATF_THD1 */ + struct { + RK_U32 atf_thd0_i16 : 6; + RK_U32 reserved0 : 10; + RK_U32 atf_thd1_i16 : 6; + RK_U32 reserved1 : 10; + } atf_thd1; + + /* 0x50 - ATF_SAD_THD0 */ + struct { + RK_U32 atf_thd0_p64 : 6; + RK_U32 reserved0 : 10; + RK_U32 atf_thd1_p64 : 6; + RK_U32 reserved1 : 10; + } atf_sad_thd0; + + /* 0x54 - ATF_SAD_THD1 */ + struct { + RK_U32 atf_thd0_p32 : 6; + RK_U32 reserved0 : 10; + RK_U32 atf_thd1_p32 : 6; + RK_U32 reserved1 : 10; + } atf_sad_thd1; + + /* 0x58 - ATF_SAD_WGT0 */ + struct { + RK_U32 atf_thd0_p16 : 6; + RK_U32 reserved0 : 10; + RK_U32 atf_thd1_p16 : 6; + RK_U32 reserved1 : 10; + } atf_sad_wgt0; +} vepu541_intra_thd; + +typedef struct { + /* 0x48 - ATF_THD0 */ + struct { + RK_U32 atf_thd0_i32 : 10; + RK_U32 reserved0 : 6; + RK_U32 atf_thd1_i32 : 10; + RK_U32 reserved1 : 6; + } atf_thd0; + + /* 0x4c - ATF_THD1 */ + struct { + RK_U32 atf_thd0_i16 : 10; + RK_U32 reserved0 : 6; + RK_U32 atf_thd1_i16 : 10; + RK_U32 reserved1 : 6; + } atf_thd1; + + /* 0x50 - ATF_SAD_THD0 */ + struct { + RK_U32 atf_thd0_p64 : 10; + RK_U32 reserved0 : 6; + RK_U32 atf_thd1_p64 : 10; + RK_U32 reserved1 : 6; + } atf_sad_thd0; + + /* 0x54 - ATF_SAD_THD1 */ + struct { + RK_U32 atf_thd0_p32 : 10; + RK_U32 reserved0 : 6; + RK_U32 atf_thd1_p32 : 10; + RK_U32 reserved1 : 6; + } atf_sad_thd1; + + /* 0x58 - ATF_SAD_WGT0 */ + struct { + RK_U32 atf_thd0_p16 : 10; + RK_U32 reserved0 : 6; + RK_U32 atf_thd1_p16 : 10; + RK_U32 reserved1 : 6; + } atf_sad_wgt0; +} vepu540_intra_thd; + + +typedef struct H265eV54xL2RegSet_t { + /* L2 Register: 0x4 */ + struct { + RK_U32 lvl32_intra_cst_thd0 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl32_intra_cst_thd1 : 12; + RK_U32 reserved1 : 4; + } lvl32_intra_CST_THD0; + + struct { + RK_U32 lvl32_intra_cst_thd2 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl32_intra_cst_thd3 : 12; + RK_U32 reserved1 : 4; + } lvl32_intra_CST_THD1; + + struct { + RK_U32 lvl16_intra_cst_thd0 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl16_intra_cst_thd1 : 12; + RK_U32 reserved1 : 4; + } lvl16_intra_CST_THD0; + + struct { + RK_U32 lvl16_intra_cst_thd2 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl16_intra_cst_thd3 : 12; + RK_U32 reserved1 : 4; + } lvl16_intra_CST_THD1; + + /* 0x14-0x1c - reserved */ + RK_U32 lvl8_intra_CST_THD0; + RK_U32 lvl8_intra_CST_THD1; + RK_U32 lvl16_intra_UL_CST_THD; + + struct { + RK_U32 lvl32_intra_cst_wgt0 : 8; + RK_U32 lvl32_intra_cst_wgt1 : 8; + RK_U32 lvl32_intra_cst_wgt2 : 8; + RK_U32 lvl32_intra_cst_wgt3 : 8; + } lvl32_intra_CST_WGT0; + + struct { + RK_U32 lvl32_intra_cst_wgt4 : 8; + RK_U32 lvl32_intra_cst_wgt5 : 8; + RK_U32 lvl32_intra_cst_wgt6 : 8; + RK_U32 reserved2 : 8; + } lvl32_intra_CST_WGT1; + + struct { + RK_U32 lvl16_intra_cst_wgt0 : 8; + RK_U32 lvl16_intra_cst_wgt1 : 8; + RK_U32 lvl16_intra_cst_wgt2 : 8; + RK_U32 lvl16_intra_cst_wgt3 : 8; + } lvl16_intra_CST_WGT0; + + struct { + RK_U32 lvl16_intra_cst_wgt4 : 8; + RK_U32 lvl16_intra_cst_wgt5 : 8; + RK_U32 lvl16_intra_cst_wgt6 : 8; + RK_U32 reserved2 : 8; + } lvl16_intra_CST_WGT1; + + /* 0x30 - RDO_QUANT */ + struct { + RK_U32 quant_f_bias_I : 10; + RK_U32 quant_f_bias_P : 10; + RK_U32 reserved : 12; + } rdo_quant; + + /* 0x34 - ATR_THD0, reserved */ + struct { + RK_U32 atr_thd0 : 12; + RK_U32 reserved0 : 4; + RK_U32 atr_thd1 : 12; + RK_U32 reserved1 : 4; + } atr_thd0; + + /* 0x38 - ATR_THD1, reserved */ + struct { + RK_U32 atr_thd2 : 12; + RK_U32 reserved0 : 4; + RK_U32 atr_thdqp : 6; + RK_U32 reserved1 : 10; + } atr_thd1; + + /* 0x3c - Lvl16_ATR_WGT, reserved */ + struct { + RK_U32 lvl16_atr_wgt0 : 8; + RK_U32 lvl16_atr_wgt1 : 8; + RK_U32 lvl16_atr_wgt2 : 8; + RK_U32 reserved : 8; + } lvl16_atr_wgt; + + /* 0x40 - Lvl8_ATR_WGT, reserved */ + struct { + RK_U32 lvl8_atr_wgt0 : 8; + RK_U32 lvl8_atr_wgt1 : 8; + RK_U32 lvl8_atr_wgt2 : 8; + RK_U32 reserved : 8; + } lvl8_atr_wgt; + + /* 0x44 - Lvl4_ATR_WGT, reserved */ + struct { + RK_U32 lvl4_atr_wgt0 : 8; + RK_U32 lvl4_atr_wgt1 : 8; + RK_U32 lvl4_atr_wgt2 : 8; + RK_U32 reserved : 8; + } lvl4_atr_wgt; + + union { + vepu541_intra_thd thd_541; + vepu540_intra_thd thd_540; + }; + + /* 0x5c - ATF_SAD_WGT1 */ + struct { + RK_U32 atf_wgt_i16 : 6; + RK_U32 reserved0 : 10; + RK_U32 atf_wgt_i32 : 6; + RK_U32 reserved1 : 10; + } atf_sad_wgt1; + + /* 0x60 - ATF_SAD_WGT2 */ + struct { + RK_U32 atf_wgt_p32 : 6; + RK_U32 reserved0 : 10; + RK_U32 atf_wgt_p64 : 6; + RK_U32 reserved1 : 10; + } atf_sad_wgt2; + + /* 0x64 - ATF_SAD_OFST0 */ + struct { + RK_U32 atf_wgt_p16 : 6; + RK_U32 reserved : 26; + } atf_sad_ofst0; + + /* 0x68 - ATF_SAD_OFST1, reserved */ + struct { + RK_U32 atf_sad_ofst12 : 14; + RK_U32 reserved0 : 2; + RK_U32 atf_sad_ofst20 : 14; + RK_U32 reserved1 : 2; + } atf_sad_ofst1; + + /* 0x6c - ATF_SAD_OFST2, reserved */ + struct { + RK_U32 atf_sad_ofst21 : 14; + RK_U32 reserved0 : 2; + RK_U32 atf_sad_ofst30 : 14; + RK_U32 reserved1 : 2; + } atf_sad_ofst2; + + /* 0x70-0x13c - LAMD_SATD_qp */ + RK_U32 lamd_satd_qp[52]; + + /* 0x140-0x20c - LAMD_MOD_qp, combo for I and P */ + RK_U32 lamd_moda_qp[52]; + /* 0x210-0x2dc */ + RK_U32 lamd_modb_qp[52]; + + /* 0x2e0 - MADI_CFG */ + struct { + RK_U32 reserved : 16; + RK_U32 madi_thd : 8; + RK_U32 reserved1 : 8; + } madi_cfg; + + /* 0x2e4 - AQ_THD0 - 0x2f0 - AQ_THD3 */ + RK_U8 aq_tthd[16]; + + /* + * 0x2f4 - AQ_QP_DLT0 - 0x300 - AQ_QP_DLT3 + * only low 6 bits is valid for per step. + */ + RK_U8 aq_step[16]; + + /*0x304-0x30c*/ + RK_U32 reserve[3]; + /*pre_intra class mode */ + // 0x0310~0x394 + // 0x0310 + struct { + RK_U32 pre_intra_cla0_m0 : 6; + RK_U32 pre_intra_cla0_m1 : 6; + RK_U32 pre_intra_cla0_m2 : 6; + RK_U32 pre_intra_cla0_m3 : 6; + RK_U32 pre_intra_cla0_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla0_B0; + + // 0x0314 + struct { + RK_U32 pre_intra_cla0_m5 : 6; + RK_U32 pre_intra_cla0_m6 : 6; + RK_U32 pre_intra_cla0_m7 : 6; + RK_U32 pre_intra_cla0_m8 : 6; + RK_U32 pre_intra_cla0_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla0_B1; + + // 0x0318 + struct { + RK_U32 pre_intra_cla1_m0 : 6; + RK_U32 pre_intra_cla1_m1 : 6; + RK_U32 pre_intra_cla1_m2 : 6; + RK_U32 pre_intra_cla1_m3 : 6; + RK_U32 pre_intra_cla1_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla1_B0; + + // 0x031c + struct { + RK_U32 pre_intra_cla1_m5 : 6; + RK_U32 pre_intra_cla1_m6 : 6; + RK_U32 pre_intra_cla1_m7 : 6; + RK_U32 pre_intra_cla1_m8 : 6; + RK_U32 pre_intra_cla1_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla1_B1; + + // 0x0320 + struct { + RK_U32 pre_intra_cla2_m0 : 6; + RK_U32 pre_intra_cla2_m1 : 6; + RK_U32 pre_intra_cla2_m2 : 6; + RK_U32 pre_intra_cla2_m3 : 6; + RK_U32 pre_intra_cla2_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla2_B0; + + // 0x0324 + struct { + RK_U32 pre_intra_cla2_m5 : 6; + RK_U32 pre_intra_cla2_m6 : 6; + RK_U32 pre_intra_cla2_m7 : 6; + RK_U32 pre_intra_cla2_m8 : 6; + RK_U32 pre_intra_cla2_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla2_B1; + + // 0x0328 + struct { + RK_U32 pre_intra_cla3_m0 : 6; + RK_U32 pre_intra_cla3_m1 : 6; + RK_U32 pre_intra_cla3_m2 : 6; + RK_U32 pre_intra_cla3_m3 : 6; + RK_U32 pre_intra_cla3_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla3_B0; + + // 0x032c + struct { + RK_U32 pre_intra_cla3_m5 : 6; + RK_U32 pre_intra_cla3_m6 : 6; + RK_U32 pre_intra_cla3_m7 : 6; + RK_U32 pre_intra_cla3_m8 : 6; + RK_U32 pre_intra_cla3_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla3_B1; + + // 0x0330 + struct { + RK_U32 pre_intra_cla4_m0 : 6; + RK_U32 pre_intra_cla4_m1 : 6; + RK_U32 pre_intra_cla4_m2 : 6; + RK_U32 pre_intra_cla4_m3 : 6; + RK_U32 pre_intra_cla4_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla4_B0; + + // 0x0334 + struct { + RK_U32 pre_intra_cla4_m5 : 6; + RK_U32 pre_intra_cla4_m6 : 6; + RK_U32 pre_intra_cla4_m7 : 6; + RK_U32 pre_intra_cla4_m8 : 6; + RK_U32 pre_intra_cla4_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla4_B1; + + // 0x0338 + struct { + RK_U32 pre_intra_cla5_m0 : 6; + RK_U32 pre_intra_cla5_m1 : 6; + RK_U32 pre_intra_cla5_m2 : 6; + RK_U32 pre_intra_cla5_m3 : 6; + RK_U32 pre_intra_cla5_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla5_B0; + + // 0x033c + struct { + RK_U32 pre_intra_cla5_m5 : 6; + RK_U32 pre_intra_cla5_m6 : 6; + RK_U32 pre_intra_cla5_m7 : 6; + RK_U32 pre_intra_cla5_m8 : 6; + RK_U32 pre_intra_cla5_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla5_B1; + + // 0x0340 + struct { + RK_U32 pre_intra_cla6_m0 : 6; + RK_U32 pre_intra_cla6_m1 : 6; + RK_U32 pre_intra_cla6_m2 : 6; + RK_U32 pre_intra_cla6_m3 : 6; + RK_U32 pre_intra_cla6_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla6_B0; + + // 0x0344 + struct { + RK_U32 pre_intra_cla6_m5 : 6; + RK_U32 pre_intra_cla6_m6 : 6; + RK_U32 pre_intra_cla6_m7 : 6; + RK_U32 pre_intra_cla6_m8 : 6; + RK_U32 pre_intra_cla6_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla6_B1; + + // 0x0348 + struct { + RK_U32 pre_intra_cla7_m0 : 6; + RK_U32 pre_intra_cla7_m1 : 6; + RK_U32 pre_intra_cla7_m2 : 6; + RK_U32 pre_intra_cla7_m3 : 6; + RK_U32 pre_intra_cla7_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla7_B0; + + // 0x034c + struct { + RK_U32 pre_intra_cla7_m5 : 6; + RK_U32 pre_intra_cla7_m6 : 6; + RK_U32 pre_intra_cla7_m7 : 6; + RK_U32 pre_intra_cla7_m8 : 6; + RK_U32 pre_intra_cla7_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla7_B1; + + // 0x0350 + struct { + RK_U32 pre_intra_cla8_m0 : 6; + RK_U32 pre_intra_cla8_m1 : 6; + RK_U32 pre_intra_cla8_m2 : 6; + RK_U32 pre_intra_cla8_m3 : 6; + RK_U32 pre_intra_cla8_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla8_B0; + + // 0x0354 + struct { + RK_U32 pre_intra_cla8_m5 : 6; + RK_U32 pre_intra_cla8_m6 : 6; + RK_U32 pre_intra_cla8_m7 : 6; + RK_U32 pre_intra_cla8_m8 : 6; + RK_U32 pre_intra_cla8_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla8_B1; + + // 0x0358 + struct { + RK_U32 pre_intra_cla9_m0 : 6; + RK_U32 pre_intra_cla9_m1 : 6; + RK_U32 pre_intra_cla9_m2 : 6; + RK_U32 pre_intra_cla9_m3 : 6; + RK_U32 pre_intra_cla9_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla9_B0; + + // 0x035c + struct { + RK_U32 pre_intra_cla9_m5 : 6; + RK_U32 pre_intra_cla9_m6 : 6; + RK_U32 pre_intra_cla9_m7 : 6; + RK_U32 pre_intra_cla9_m8 : 6; + RK_U32 pre_intra_cla9_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla9_B1; + + // 0x0360 + struct { + RK_U32 pre_intra_cla10_m0 : 6; + RK_U32 pre_intra_cla10_m1 : 6; + RK_U32 pre_intra_cla10_m2 : 6; + RK_U32 pre_intra_cla10_m3 : 6; + RK_U32 pre_intra_cla10_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla10_B0; + + // 0x0364 + struct { + RK_U32 pre_intra_cla10_m5 : 6; + RK_U32 pre_intra_cla10_m6 : 6; + RK_U32 pre_intra_cla10_m7 : 6; + RK_U32 pre_intra_cla10_m8 : 6; + RK_U32 pre_intra_cla10_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla10_B1; + + // 0x0368 + struct { + RK_U32 pre_intra_cla11_m0 : 6; + RK_U32 pre_intra_cla11_m1 : 6; + RK_U32 pre_intra_cla11_m2 : 6; + RK_U32 pre_intra_cla11_m3 : 6; + RK_U32 pre_intra_cla11_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla11_B0; + + // 0x036c + struct { + RK_U32 pre_intra_cla11_m5 : 6; + RK_U32 pre_intra_cla11_m6 : 6; + RK_U32 pre_intra_cla11_m7 : 6; + RK_U32 pre_intra_cla11_m8 : 6; + RK_U32 pre_intra_cla11_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla11_B1; + + // 0x0370 + struct { + RK_U32 pre_intra_cla12_m0 : 6; + RK_U32 pre_intra_cla12_m1 : 6; + RK_U32 pre_intra_cla12_m2 : 6; + RK_U32 pre_intra_cla12_m3 : 6; + RK_U32 pre_intra_cla12_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla12_B0; + + // 0x0374 + struct { + RK_U32 pre_intra_cla12_m5 : 6; + RK_U32 pre_intra_cla12_m6 : 6; + RK_U32 pre_intra_cla12_m7 : 6; + RK_U32 pre_intra_cla12_m8 : 6; + RK_U32 pre_intra_cla12_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla12_B1; + + // 0x0378 + struct { + RK_U32 pre_intra_cla13_m0 : 6; + RK_U32 pre_intra_cla13_m1 : 6; + RK_U32 pre_intra_cla13_m2 : 6; + RK_U32 pre_intra_cla13_m3 : 6; + RK_U32 pre_intra_cla13_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla13_B0; + + // 0x037c + struct { + RK_U32 pre_intra_cla13_m5 : 6; + RK_U32 pre_intra_cla13_m6 : 6; + RK_U32 pre_intra_cla13_m7 : 6; + RK_U32 pre_intra_cla13_m8 : 6; + RK_U32 pre_intra_cla13_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla13_B1; + + // 0x0380 + struct { + RK_U32 pre_intra_cla14_m0 : 6; + RK_U32 pre_intra_cla14_m1 : 6; + RK_U32 pre_intra_cla14_m2 : 6; + RK_U32 pre_intra_cla14_m3 : 6; + RK_U32 pre_intra_cla14_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla14_B0; + + // 0x0384 + struct { + RK_U32 pre_intra_cla14_m5 : 6; + RK_U32 pre_intra_cla14_m6 : 6; + RK_U32 pre_intra_cla14_m7 : 6; + RK_U32 pre_intra_cla14_m8 : 6; + RK_U32 pre_intra_cla14_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla14_B1; + + // 0x0388 + struct { + RK_U32 pre_intra_cla15_m0 : 6; + RK_U32 pre_intra_cla15_m1 : 6; + RK_U32 pre_intra_cla15_m2 : 6; + RK_U32 pre_intra_cla15_m3 : 6; + RK_U32 pre_intra_cla15_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla15_B0; + + // 0x038c + struct { + RK_U32 pre_intra_cla15_m5 : 6; + RK_U32 pre_intra_cla15_m6 : 6; + RK_U32 pre_intra_cla15_m7 : 6; + RK_U32 pre_intra_cla15_m8 : 6; + RK_U32 pre_intra_cla15_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla15_B1; + + // 0x0390 + struct { + RK_U32 pre_intra_cla16_m0 : 6; + RK_U32 pre_intra_cla16_m1 : 6; + RK_U32 pre_intra_cla16_m2 : 6; + RK_U32 pre_intra_cla16_m3 : 6; + RK_U32 pre_intra_cla16_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla16_B0; + + // 0x0394 + struct { + RK_U32 pre_intra_cla16_m5 : 6; + RK_U32 pre_intra_cla16_m6 : 6; + RK_U32 pre_intra_cla16_m7 : 6; + RK_U32 pre_intra_cla16_m8 : 6; + RK_U32 pre_intra_cla16_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla16_B1; + + // 0x0398 0x03fC + RK_U32 reg_L2reserved1[26]; + + // 0x400 + RK_U32 reg_rdo_ckg_hevc; + + // 0x404~0x40c + RK_U32 reg_L2reserved2[3]; + + // 0x410 + struct { + RK_U32 intra_l16_sobel_t0 : 12; + RK_U32 reserved0 : 4; + RK_U32 intra_l16_sobel_t1 : 12; + RK_U32 reserved1 : 4; + } i16_sobel_t_hevc; + + struct { + RK_U32 intra_l16_sobel_a0_qp0 : 6; + RK_U32 intra_l16_sobel_a0_qp1 : 6; + RK_U32 intra_l16_sobel_a0_qp2 : 6; + RK_U32 intra_l16_sobel_a0_qp3 : 6; + RK_U32 intra_l16_sobel_a0_qp4 : 6; + RK_U32 reserved0 : 2; + } i16_sobel_a_00_hevc; + + struct { + RK_U32 intra_l16_sobel_a0_qp5 : 6; + RK_U32 intra_l16_sobel_a0_qp6 : 6; + RK_U32 intra_l16_sobel_a0_qp7 : 6; + RK_U32 intra_l16_sobel_a0_qp8 : 6; + RK_U32 reserved0 : 8; + } i16_sobel_a_01_hevc; + + struct { + RK_U32 intra_l16_sobel_b0_qp0 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_b0_qp1 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_00_hevc; + + struct { + RK_U32 intra_l16_sobel_b0_qp2 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_b0_qp3 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_01_hevc; + + struct { + RK_U32 intra_l16_sobel_b0_qp4 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_b0_qp5 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_02_hevc; + + struct { + RK_U32 intra_l16_sobel_b0_qp6 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_b0_qp7 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_03_hevc; + + struct { + RK_U32 intra_l16_sobel_b0_qp8 : 15; + RK_U32 reserved0 : 17; + } i16_sobel_b_04_hevc; + + struct { + RK_U32 intra_l16_sobel_c0_qp0 : 6; + RK_U32 intra_l16_sobel_c0_qp1 : 6; + RK_U32 intra_l16_sobel_c0_qp2 : 6; + RK_U32 intra_l16_sobel_c0_qp3 : 6; + RK_U32 intra_l16_sobel_c0_qp4 : 6; + RK_U32 reserved0 : 2; + } i16_sobel_c_00_hevc; + + struct { + RK_U32 intra_l16_sobel_c0_qp5 : 6; + RK_U32 intra_l16_sobel_c0_qp6 : 6; + RK_U32 intra_l16_sobel_c0_qp7 : 6; + RK_U32 intra_l16_sobel_c0_qp8 : 6; + RK_U32 reserved0 : 8; + } i16_sobel_c_01_hevc; + + struct { + RK_U32 intra_l16_sobel_d0_qp0 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_d0_qp1 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_00_hevc; + + struct { + RK_U32 intra_l16_sobel_d0_qp2 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_d0_qp3 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_01_hevc; + + struct { + RK_U32 intra_l16_sobel_d0_qp4 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_d0_qp5 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_02_hevc; + + struct { + RK_U32 intra_l16_sobel_d0_qp6 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l16_sobel_d0_qp7 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_03_hevc; + + struct { + RK_U32 intra_l16_sobel_d0_qp8 : 15; + RK_U32 reserved0 : 17; + } i16_sobel_d_04_hevc; + + RK_U32 i16_sobel_e_00_17_hevc[18];// 0 2 4 ... low 32bit ; 1 3 5 ... high 2bit + + // 0x494 + struct { + RK_U32 intra_l32_sobel_t2 : 12; + RK_U32 reserved0 : 4; + RK_U32 intra_l32_sobel_t3 : 12; + RK_U32 reserved1 : 4; + } i32_sobel_t_00_hevc; + + struct { + RK_U32 intra_l32_sobel_t4 : 6; + RK_U32 reserved0 : 24; + + } i32_sobel_t_01_hevc; + + struct { + RK_U32 intra_l32_sobel_t5 : 12; + RK_U32 reserved0 : 4; + RK_U32 intra_l32_sobel_t6 : 12; + RK_U32 reserved1 : 4; + } i32_sobel_t_02_hevc; + + struct { + RK_U32 intra_l32_sobel_a1_qp0 : 6; + RK_U32 intra_l32_sobel_a1_qp1 : 6; + RK_U32 intra_l32_sobel_a1_qp2 : 6; + RK_U32 intra_l32_sobel_a1_qp3 : 6; + RK_U32 intra_l32_sobel_a1_qp4 : 6; + RK_U32 reserved0 : 2; + } i32_sobel_a_hevc; + + struct { + RK_U32 intra_l32_sobel_b1_qp0 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l32_sobel_b1_qp1 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_b_00_hevc; + + struct { + RK_U32 intra_l32_sobel_b1_qp2 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l32_sobel_b1_qp3 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_b_01_hevc; + + struct { + RK_U32 intra_l32_sobel_b1_qp4 : 15; + RK_U32 reserved0 : 17; + } i32_sobel_b_02_hevc; + + struct { + RK_U32 intra_l32_sobel_c1_qp0 : 6; + RK_U32 intra_l32_sobel_c1_qp1 : 6; + RK_U32 intra_l32_sobel_c1_qp2 : 6; + RK_U32 intra_l32_sobel_c1_qp3 : 6; + RK_U32 intra_l32_sobel_c1_qp4 : 6; + RK_U32 reserved0 : 2; + } i32_sobel_c_hevc; + + struct { + RK_U32 intra_l32_sobel_d1_qp0 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l32_sobel_d1_qp1 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_d_00_hevc; + + struct { + RK_U32 intra_l32_sobel_d1_qp2 : 15; + RK_U32 reserved0 : 1; + RK_U32 intra_l32_sobel_d1_qp3 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_d_01_hevc; + + struct { + RK_U32 intra_l32_sobel_d1_qp4 : 15; + RK_U32 reserved0 : 17; + } i32_sobel_d_02_hevc; + // 0x4c0~0x4e4 + RK_U32 i32_sobel_e_00_09_hevc[10];// 0 2 4 ... low 32bit ; 1 3 5 ... high 9bit +} H265eV54xL2RegSet; + +#endif /* HAL_H265E_VEPU54X_REG_L2_H */ diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu580.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu580.c new file mode 100644 index 000000000..aa11e6854 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu580.c @@ -0,0 +1,3494 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h265e_v580" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" +#include "mpp_dmabuf.h" + +#include "hal_h265e_debug.h" +#include "h265e_syntax_new.h" +#include "hal_h265e_stream_amend.h" +#include "hal_bufs.h" +#include "rkv_enc_def.h" +#include "h265e_dpb.h" +#include "vepu5xx_common.h" +#include "vepu580_common.h" +#include "hal_h265e_vepu580.h" +#include "hal_h265e_vepu580_reg.h" +#include "mpp_enc_cb_param.h" + +#include "mpp_service.h" + +#define MAX_FRAME_TASK_NUM 2 +#define MAX_TILE_NUM 4 +#define MAX_REGS_SET ((MAX_FRAME_TASK_NUM) * (MAX_TILE_NUM)) + +#define hal_h265e_err(fmt, ...) \ + do {\ + mpp_err_f(fmt, ## __VA_ARGS__);\ + } while (0) + +typedef struct vepu580_h265_fbk_t { + RK_U32 hw_status; /* 0:corret, 1:error */ + RK_U32 qp_sum; + RK_U32 out_strm_size; + RK_U32 out_hw_strm_size; + RK_S64 sse_sum; + RK_U32 st_lvl64_inter_num; + RK_U32 st_lvl32_inter_num; + RK_U32 st_lvl16_inter_num; + RK_U32 st_lvl8_inter_num; + RK_U32 st_lvl32_intra_num; + RK_U32 st_lvl16_intra_num; + RK_U32 st_lvl8_intra_num; + RK_U32 st_lvl4_intra_num; + RK_U32 st_cu_num_qp[52]; + RK_U32 st_madp; + RK_U32 st_madi; + RK_U32 st_md_sad_b16num0; + RK_U32 st_md_sad_b16num1; + RK_U32 st_md_sad_b16num2; + RK_U32 st_md_sad_b16num3; + RK_U32 st_madi_b16num0; + RK_U32 st_madi_b16num1; + RK_U32 st_madi_b16num2; + RK_U32 st_madi_b16num3; + RK_U32 st_mb_num; + RK_U32 st_ctu_num; +} Vepu580H265Fbk; + +typedef struct Vepu580RoiHevcBsCfg_t { + RK_U8 amv_en : 1; + RK_U8 qp_adj : 1; + RK_U8 force_split : 1; + RK_U8 force_intra : 2; + RK_U8 force_inter : 2; +} Vepu580RoiHevcBsCfg; + +typedef struct Vepu580MdInfo_t { + RK_U8 vld; + RK_U16 sad[16]; +} Vepu580MdInfo; + +typedef struct Vepu580RoiHevcQpCfg_t { + RK_U16 reserved : 4; + /* + * Qp area index + * The choosed qp area index. + */ + RK_U16 qp_area_idx : 4; + /* + * Qp_adj + * Qp_adj + * in absolute qp mode qp_adj is the final qp used by encoder + * in relative qp mode qp_adj is a adjustment to final qp + */ + RK_S16 qp_adj : 7; + /* + * Qp_adj_mode + * Qp adjustment mode + * 1 - absolute qp mode: + * the 16x16 MB qp is set to the qp_adj value + * 0 - relative qp mode + * the 16x16 MB qp is adjusted by qp_adj value + */ + RK_U16 qp_adj_mode : 1; +} Vepu580RoiHevcQpCfg; + +typedef struct Vepu580H265eFrmCfg_t { + RK_S32 frame_count; + RK_S32 frame_type; + + /* dchs cfg on frame parallel */ + RK_S32 dchs_curr_idx; + RK_S32 dchs_prev_idx; + + /* hal dpb management slot idx */ + RK_S32 hal_curr_idx; + RK_S32 hal_refr_idx; + + /* regs cfg */ + H265eV580RegSet *regs_set[MAX_TILE_NUM]; + H265eV580StatusElem *regs_ret[MAX_TILE_NUM]; + + /* hardware return info collection cfg */ + Vepu580H265Fbk feedback; + + /* tile buffer */ + MppBuffer hw_tile_buf[MAX_TILE_NUM]; + MppBuffer hw_tile_stream[MAX_TILE_NUM - 1]; + + /* osd cfg */ + Vepu5xxOsdCfg osd_cfg; + void *roi_data; + + /* gdr roi cfg */ + MppBuffer roi_base_cfg_buf; + void *roi_base_cfg_sw_buf; + RK_S32 roi_base_buf_size; + + /* variable length cfg */ + MppDevRegOffCfgs *reg_cfg; +} Vepu580H265eFrmCfg; + +typedef struct H265eV580HalContext_t { + MppDev dev; + Vepu580H265eFrmCfg *frms[MAX_FRAME_TASK_NUM]; + + /* current used frame config */ + Vepu580H265eFrmCfg *frm; + + /* slice split poll cfg */ + RK_S32 poll_slice_max; + RK_S32 poll_cfg_size; + + /* @frame_cnt starts from ZERO */ + RK_U32 frame_count; + + /* frame parallel info */ + RK_S32 task_cnt; + RK_S32 task_idx; + + /* dchs cfg */ + RK_S32 curr_idx; + RK_S32 prev_idx; + RK_S32 slot_to_dchs_txid[MAX_REFS]; + + /* debug cfg */ + void *dump_files; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + MppBufferGroup roi_grp; + MppBufferGroup qpmap_grp; + + MppEncCfgSet *cfg; + H265eSyntax_new *syn; + H265eDpb *dpb; + + /* single frame tile parallel info */ + MppBufferGroup tile_grp; + RK_U32 tile_num; + RK_U32 tile_parall_en; + RK_U32 tile_dump_err; + + MppBuffer buf_pass1; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + HalBufs dpb_bufs; + RK_S32 fbc_header_len; + + MppDevPollCfg *poll_cfgs; + MppCbCtx *output_cb; + + /* finetune */ + void *tune; + MppBuffer md_info_buf; /* md info buffer for deblurring */ + MppBuffer qpmap_base_cfg_buf; + MppBuffer qpmap_qp_cfg_buf; + RK_U8* md_flag_buf; + RK_S32 md_info_buf_size; + RK_S32 qpmap_base_cfg_size; + RK_S32 qpmap_qp_cfg_size; + RK_S32 md_flag_size; +} H265eV580HalContext; + +static RK_U32 aq_thd_default[16] = { + 0, 0, 0, 0, + 3, 3, 5, 5, + 8, 8, 8, 15, + 15, 20, 25, 35 +}; + +static RK_U32 h265e_mode_bias[16] = { + 0, 2, 4, 6, + 8, 10, 12, 14, + 16, 18, 20, 24, + 28, 32, 64, 128 +}; + +static RK_S32 aq_qp_dealt_default[16] = { + -8, -7, -6, -5, + -4, -3, -2, -1, + 0, 1, 2, 3, + 5, 7, 8, 9, +}; + + +static RK_U16 lvl32_intra_cst_thd[4] = {2, 6, 16, 36}; + +static RK_U16 lvl16_intra_cst_thd[4] = {2, 6, 16, 36}; + +static RK_U8 lvl32_intra_cst_wgt[8] = {23, 22, 21, 20, 22, 24, 26}; + +static RK_U8 lvl16_intra_cst_wgt[8] = {17, 17, 17, 18, 17, 18, 18}; + +#include "hal_h265e_vepu580_tune.c" + +static void vepu580_h265_set_me_ram(H265eSyntax_new *syn, hevc_vepu580_base *regs, + RK_U32 index, RK_S32 tile_start_x) +{ + RK_S32 frm_sta = 0, frm_end = 0, pic_w = 0; + RK_S32 srch_w = regs->reg0220_me_rnge.cme_srch_h * 4; + RK_S32 srch_h = regs->reg0220_me_rnge.cme_srch_v * 4; + RK_S32 x_gmv = regs->reg0224_gmv.gmv_x; + RK_S32 y_gmv = regs->reg0224_gmv.gmv_y; + RK_U32 pic_wd64 = ((regs->reg0196_enc_rsl.pic_wd8_m1 + 1) * 8 + 63) / 64; + + if (!syn->pp.tiles_enabled_flag) { + if (x_gmv - srch_w < 0) { + frm_sta = (x_gmv - srch_w - 15) / 16; + } else { + frm_sta = (x_gmv - srch_w) / 16; + } + frm_sta = mpp_clip(frm_sta, 0, pic_wd64 - 1); + if (x_gmv + srch_w < 0) { + frm_end = pic_wd64 - 1 + (x_gmv + srch_w) / 16; + } else { + frm_end = pic_wd64 - 1 + (x_gmv + srch_w + 15) / 16; + } + frm_end = mpp_clip(frm_end, 0, pic_wd64 - 1); + } else { + RK_S32 tile_ctu_stax = tile_start_x; + RK_S32 tile_ctu_endx = tile_start_x + syn->pp.column_width_minus1[index]; + + if (x_gmv - srch_w < 0) { + frm_sta = tile_ctu_stax + (x_gmv - srch_w - 15) / 16; + } else { + frm_sta = tile_ctu_stax + (x_gmv - srch_w) / 16; + } + frm_sta = mpp_clip(frm_sta, 0, pic_wd64 - 1); + + if (x_gmv + srch_w < 0) { + frm_end = tile_ctu_endx + (x_gmv + srch_w) / 16; + } else { + frm_end = tile_ctu_endx + (x_gmv + srch_w + 15) / 16; + } + frm_end = mpp_clip(frm_end, 0, pic_wd64 - 1); + } + pic_w = (frm_end - frm_sta + 1) * 64; + regs->reg0222_me_cach.cme_linebuf_w = ((pic_w != 0) ? pic_w : 64) / 64; + { + RK_U32 cime_rama_max = 2464; + RK_U32 ctu_4_h = 4, ramb_h; + RK_U32 cur_srch_16_w, cur_srch_4_h, cur_srch_max; + RK_U32 cime_rama_h = ctu_4_h; + + if ((x_gmv % 16 - srch_w % 16) < 0) { + cur_srch_16_w = (16 + (x_gmv % 16 - srch_w % 16) % 16 + srch_w * 2 + 15) / 16 + 1; + } else { + cur_srch_16_w = ((x_gmv % 16 - srch_w % 16) % 16 + srch_w * 2 + 15) / 16 + 1; + } + if ((y_gmv % 4 - srch_h % 4) < 0) { + cur_srch_4_h = (4 + (y_gmv % 4 - srch_h % 4) % 4 + srch_h * 2 + 3) / 4 + ctu_4_h; + } else { + cur_srch_4_h = ((y_gmv % 4 - srch_h % 4) % 4 + srch_h * 2 + 3) / 4 + ctu_4_h; + } + cur_srch_max = MPP_ALIGN(cur_srch_4_h, 4); + if (regs->reg0222_me_cach.cme_linebuf_w < cur_srch_16_w) { + cur_srch_16_w = regs->reg0222_me_cach.cme_linebuf_w; + } + ramb_h = cur_srch_4_h; + while ((cime_rama_h < cur_srch_max) && (cime_rama_max > + ((cime_rama_h - ctu_4_h) * regs->reg0222_me_cach.cme_linebuf_w * 4 + (ramb_h * 4 * cur_srch_16_w)))) { + cime_rama_h = cime_rama_h + ctu_4_h; + if (ramb_h > 2 * ctu_4_h) { + ramb_h = ramb_h - ctu_4_h; + } else { + ramb_h = ctu_4_h; + } + } + if (cur_srch_4_h == ctu_4_h) { + cime_rama_h = cime_rama_h + ctu_4_h; + ramb_h = 0; + } + if (cime_rama_max < ((cime_rama_h - ctu_4_h) * regs->reg0222_me_cach.cme_linebuf_w * 4 + (ramb_h * 4 * cur_srch_16_w))) { + cime_rama_h = cime_rama_h - ctu_4_h; + } + regs->reg0222_me_cach.cme_rama_h = cime_rama_h; /* cime_rama_max */ + + { + RK_U32 ram_col_h = (cime_rama_h - ctu_4_h) / ctu_4_h; + regs->reg0222_me_cach.cme_rama_max = ram_col_h * regs->reg0222_me_cach.cme_linebuf_w + cur_srch_16_w; + } + + } + + hal_h265e_dbg_detail("cime_rama_h %d, cime_rama_max %d, cime_linebuf_w %d", + regs->reg0222_me_cach.cme_rama_h, regs->reg0222_me_cach.cme_rama_max, regs->reg0222_me_cach.cme_linebuf_w); +} + +static MPP_RET vepu580_h265_setup_hal_bufs(H265eV580HalContext *ctx) +{ + MPP_RET ret = MPP_OK; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + RK_U32 frame_size; + RK_S32 mb_wd64, mb_h64; + MppEncRefCfg ref_cfg = ctx->cfg->ref_cfg; + MppEncPrepCfg *prep = &ctx->cfg->prep; + RK_S32 old_max_cnt = ctx->max_buf_cnt; + RK_S32 new_max_cnt = 4; + + hal_h265e_enter(); + + mb_wd64 = (prep->width + 63) / 64; + mb_h64 = (prep->height + 63) / 64 + 1; + + frame_size = MPP_ALIGN(prep->width, 16) * MPP_ALIGN(prep->height, 16); + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + + if (ref_cfg) { + MppEncCpbInfo *info = mpp_enc_ref_cfg_get_cpb_info(ref_cfg); + new_max_cnt = MPP_MAX(new_max_cnt, info->dpb_size + 1); + } + + if (frame_size > ctx->frame_size || new_max_cnt > old_max_cnt) { + size_t size[3] = {0}; + + hal_bufs_deinit(ctx->dpb_bufs); + hal_bufs_init(&ctx->dpb_bufs); + + ctx->fbc_header_len = MPP_ALIGN(((mb_wd64 * mb_h64) << 6), SZ_8K); + size[0] = ctx->fbc_header_len + ((mb_wd64 * mb_h64) << 12) * 3 / 2; //fbc_h + fbc_b + size[1] = (mb_wd64 * mb_h64 << 8); + size[2] = MPP_ALIGN(mb_wd64 * mb_h64 * 16 * 6, 256); + new_max_cnt = MPP_MAX(new_max_cnt, old_max_cnt); + + hal_h265e_dbg_detail("frame size %d -> %d max count %d -> %d\n", + ctx->frame_size, frame_size, old_max_cnt, new_max_cnt); + + hal_bufs_setup(ctx->dpb_bufs, new_max_cnt, 3, size); + + ctx->frame_size = frame_size; + ctx->max_buf_cnt = new_max_cnt; + } + hal_h265e_leave(); + return ret; +} + +static void vepu580_h265_sobel_cfg(hevc_vepu580_wgt *reg) +{ + reg->pre_intra_cla0_B0.pre_intra_cla0_m0 = 10; + reg->pre_intra_cla0_B0.pre_intra_cla0_m1 = 11; + reg->pre_intra_cla0_B0.pre_intra_cla0_m2 = 12; + reg->pre_intra_cla0_B0.pre_intra_cla0_m3 = 13; + reg->pre_intra_cla0_B0.pre_intra_cla0_m4 = 14; + + reg->pre_intra_cla0_B1.pre_intra_cla0_m5 = 9; + reg->pre_intra_cla0_B1.pre_intra_cla0_m6 = 15; + reg->pre_intra_cla0_B1.pre_intra_cla0_m7 = 8; + reg->pre_intra_cla0_B1.pre_intra_cla0_m8 = 16; + reg->pre_intra_cla0_B1.pre_intra_cla0_m9 = 7; + + reg->pre_intra_cla1_B0.pre_intra_cla1_m0 = 10; + reg->pre_intra_cla1_B0.pre_intra_cla1_m1 = 9; + reg->pre_intra_cla1_B0.pre_intra_cla1_m2 = 8; + reg->pre_intra_cla1_B0.pre_intra_cla1_m3 = 7; + reg->pre_intra_cla1_B0.pre_intra_cla1_m4 = 6; + reg->pre_intra_cla1_B1.pre_intra_cla1_m5 = 11; + reg->pre_intra_cla1_B1.pre_intra_cla1_m6 = 5; + reg->pre_intra_cla1_B1.pre_intra_cla1_m7 = 12; + reg->pre_intra_cla1_B1.pre_intra_cla1_m8 = 4; + reg->pre_intra_cla1_B1.pre_intra_cla1_m9 = 13; + + reg->pre_intra_cla2_B0.pre_intra_cla2_m0 = 18; + reg->pre_intra_cla2_B0.pre_intra_cla2_m1 = 17; + reg->pre_intra_cla2_B0.pre_intra_cla2_m2 = 16; + reg->pre_intra_cla2_B0.pre_intra_cla2_m3 = 15; + reg->pre_intra_cla2_B0.pre_intra_cla2_m4 = 14; + reg->pre_intra_cla2_B1.pre_intra_cla2_m5 = 19; + reg->pre_intra_cla2_B1.pre_intra_cla2_m6 = 13; + reg->pre_intra_cla2_B1.pre_intra_cla2_m7 = 20; + reg->pre_intra_cla2_B1.pre_intra_cla2_m8 = 12; + reg->pre_intra_cla2_B1.pre_intra_cla2_m9 = 21; + + reg->pre_intra_cla3_B0.pre_intra_cla3_m0 = 18; + reg->pre_intra_cla3_B0.pre_intra_cla3_m1 = 19; + reg->pre_intra_cla3_B0.pre_intra_cla3_m2 = 20; + reg->pre_intra_cla3_B0.pre_intra_cla3_m3 = 21; + reg->pre_intra_cla3_B0.pre_intra_cla3_m4 = 22; + reg->pre_intra_cla3_B1.pre_intra_cla3_m5 = 17; + reg->pre_intra_cla3_B1.pre_intra_cla3_m6 = 23; + reg->pre_intra_cla3_B1.pre_intra_cla3_m7 = 16; + reg->pre_intra_cla3_B1.pre_intra_cla3_m8 = 24; + reg->pre_intra_cla3_B1.pre_intra_cla3_m9 = 15; + + reg->pre_intra_cla4_B0.pre_intra_cla4_m0 = 25; + reg->pre_intra_cla4_B0.pre_intra_cla4_m1 = 26; + reg->pre_intra_cla4_B0.pre_intra_cla4_m2 = 24; + reg->pre_intra_cla4_B0.pre_intra_cla4_m3 = 23; + reg->pre_intra_cla4_B0.pre_intra_cla4_m4 = 22; + reg->pre_intra_cla4_B1.pre_intra_cla4_m5 = 27; + reg->pre_intra_cla4_B1.pre_intra_cla4_m6 = 21; + reg->pre_intra_cla4_B1.pre_intra_cla4_m7 = 28; + reg->pre_intra_cla4_B1.pre_intra_cla4_m8 = 20; + reg->pre_intra_cla4_B1.pre_intra_cla4_m9 = 29; + + reg->pre_intra_cla5_B0.pre_intra_cla5_m0 = 27; + reg->pre_intra_cla5_B0.pre_intra_cla5_m1 = 26; + reg->pre_intra_cla5_B0.pre_intra_cla5_m2 = 28; + reg->pre_intra_cla5_B0.pre_intra_cla5_m3 = 29; + reg->pre_intra_cla5_B0.pre_intra_cla5_m4 = 30; + reg->pre_intra_cla5_B1.pre_intra_cla5_m5 = 25; + reg->pre_intra_cla5_B1.pre_intra_cla5_m6 = 31; + reg->pre_intra_cla5_B1.pre_intra_cla5_m7 = 24; + reg->pre_intra_cla5_B1.pre_intra_cla5_m8 = 32; + reg->pre_intra_cla5_B1.pre_intra_cla5_m9 = 23; + + reg->pre_intra_cla6_B0.pre_intra_cla6_m0 = 34; + reg->pre_intra_cla6_B0.pre_intra_cla6_m1 = 33; + reg->pre_intra_cla6_B0.pre_intra_cla6_m2 = 32; + reg->pre_intra_cla6_B0.pre_intra_cla6_m3 = 31; + reg->pre_intra_cla6_B0.pre_intra_cla6_m4 = 30; + reg->pre_intra_cla6_B1.pre_intra_cla6_m5 = 2; + reg->pre_intra_cla6_B1.pre_intra_cla6_m6 = 29; + reg->pre_intra_cla6_B1.pre_intra_cla6_m7 = 3; + reg->pre_intra_cla6_B1.pre_intra_cla6_m8 = 28; + reg->pre_intra_cla6_B1.pre_intra_cla6_m9 = 4; + + reg->pre_intra_cla7_B0.pre_intra_cla7_m0 = 34; + reg->pre_intra_cla7_B0.pre_intra_cla7_m1 = 2; + reg->pre_intra_cla7_B0.pre_intra_cla7_m2 = 3; + reg->pre_intra_cla7_B0.pre_intra_cla7_m3 = 4; + reg->pre_intra_cla7_B0.pre_intra_cla7_m4 = 5; + reg->pre_intra_cla7_B1.pre_intra_cla7_m5 = 33; + reg->pre_intra_cla7_B1.pre_intra_cla7_m6 = 6; + reg->pre_intra_cla7_B1.pre_intra_cla7_m7 = 32; + reg->pre_intra_cla7_B1.pre_intra_cla7_m8 = 7; + reg->pre_intra_cla7_B1.pre_intra_cla7_m9 = 31; + + reg->pre_intra_cla8_B0.pre_intra_cla8_m0 = 10; + reg->pre_intra_cla8_B0.pre_intra_cla8_m1 = 26; + reg->pre_intra_cla8_B0.pre_intra_cla8_m2 = 18; + reg->pre_intra_cla8_B0.pre_intra_cla8_m3 = 34; + reg->pre_intra_cla8_B0.pre_intra_cla8_m4 = 6; + reg->pre_intra_cla8_B1.pre_intra_cla8_m5 = 14; + reg->pre_intra_cla8_B1.pre_intra_cla8_m6 = 22; + reg->pre_intra_cla8_B1.pre_intra_cla8_m7 = 30; + reg->pre_intra_cla8_B1.pre_intra_cla8_m8 = 2; + reg->pre_intra_cla8_B1.pre_intra_cla8_m9 = 24; + + reg->pre_intra_cla9_B0.pre_intra_cla9_m0 = 0; + reg->pre_intra_cla9_B0.pre_intra_cla9_m1 = 0; + reg->pre_intra_cla9_B0.pre_intra_cla9_m2 = 0; + reg->pre_intra_cla9_B0.pre_intra_cla9_m3 = 0; + reg->pre_intra_cla9_B0.pre_intra_cla9_m4 = 0; + reg->pre_intra_cla9_B1.pre_intra_cla9_m5 = 0; + reg->pre_intra_cla9_B1.pre_intra_cla9_m6 = 0; + reg->pre_intra_cla9_B1.pre_intra_cla9_m7 = 0; + reg->pre_intra_cla9_B1.pre_intra_cla9_m8 = 0; + reg->pre_intra_cla9_B1.pre_intra_cla9_m9 = 0; + + reg->pre_intra_cla10_B0.pre_intra_cla10_m0 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m1 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m2 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m3 = 0; + reg->pre_intra_cla10_B0.pre_intra_cla10_m4 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m5 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m6 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m7 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m8 = 0; + reg->pre_intra_cla10_B1.pre_intra_cla10_m9 = 0; + + reg->pre_intra_cla11_B0.pre_intra_cla11_m0 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m1 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m2 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m3 = 0; + reg->pre_intra_cla11_B0.pre_intra_cla11_m4 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m5 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m6 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m7 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m8 = 0; + reg->pre_intra_cla11_B1.pre_intra_cla11_m9 = 0; + + reg->pre_intra_cla12_B0.pre_intra_cla12_m0 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m1 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m2 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m3 = 0; + reg->pre_intra_cla12_B0.pre_intra_cla12_m4 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m5 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m6 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m7 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m8 = 0; + reg->pre_intra_cla12_B1.pre_intra_cla12_m9 = 0; + + reg->pre_intra_cla13_B0.pre_intra_cla13_m0 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m1 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m2 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m3 = 0; + reg->pre_intra_cla13_B0.pre_intra_cla13_m4 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m5 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m6 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m7 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m8 = 0; + reg->pre_intra_cla13_B1.pre_intra_cla13_m9 = 0; + + reg->pre_intra_cla14_B0.pre_intra_cla14_m0 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m1 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m2 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m3 = 0; + reg->pre_intra_cla14_B0.pre_intra_cla14_m4 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m5 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m6 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m7 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m8 = 0; + reg->pre_intra_cla14_B1.pre_intra_cla14_m9 = 0; + + reg->pre_intra_cla15_B0.pre_intra_cla15_m0 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m1 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m2 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m3 = 0; + reg->pre_intra_cla15_B0.pre_intra_cla15_m4 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m5 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m6 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m7 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m8 = 0; + reg->pre_intra_cla15_B1.pre_intra_cla15_m9 = 0; + + reg->pre_intra_cla16_B0.pre_intra_cla16_m0 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m1 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m2 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m3 = 0; + reg->pre_intra_cla16_B0.pre_intra_cla16_m4 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m5 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m6 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m7 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m8 = 0; + reg->pre_intra_cla16_B1.pre_intra_cla16_m9 = 0; + + reg->i16_sobel_t.intra_l16_sobel_t0 = 64; + reg->i16_sobel_t.intra_l16_sobel_t1 = 200; + reg->i16_sobel_a_00.intra_l16_sobel_a0_qp0 = 32; + reg->i16_sobel_a_00.intra_l16_sobel_a0_qp1 = 32; + reg->i16_sobel_a_00.intra_l16_sobel_a0_qp2 = 32; + reg->i16_sobel_a_00.intra_l16_sobel_a0_qp3 = 32; + reg->i16_sobel_a_00.intra_l16_sobel_a0_qp4 = 32; + reg->i16_sobel_a_01.intra_l16_sobel_a0_qp5 = 32; + reg->i16_sobel_a_01.intra_l16_sobel_a0_qp6 = 32; + reg->i16_sobel_a_01.intra_l16_sobel_a0_qp7 = 32; + reg->i16_sobel_a_01.intra_l16_sobel_a0_qp8 = 32; + reg->i16_sobel_b_00.intra_l16_sobel_b0_qp0 = 0; + reg->i16_sobel_b_00.intra_l16_sobel_b0_qp1 = 0; + reg->i16_sobel_b_01.intra_l16_sobel_b0_qp2 = 0; + reg->i16_sobel_b_01.intra_l16_sobel_b0_qp3 = 0; + reg->i16_sobel_b_02.intra_l16_sobel_b0_qp4 = 0; + reg->i16_sobel_b_02.intra_l16_sobel_b0_qp5 = 0; + reg->i16_sobel_b_03.intra_l16_sobel_b0_qp6 = 0; + reg->i16_sobel_b_03.intra_l16_sobel_b0_qp7 = 0; + reg->i16_sobel_b_04.intra_l16_sobel_b0_qp8 = 0; + reg->i16_sobel_c_00.intra_l16_sobel_c0_qp0 = 13; + reg->i16_sobel_c_00.intra_l16_sobel_c0_qp1 = 13; + reg->i16_sobel_c_00.intra_l16_sobel_c0_qp2 = 13; + reg->i16_sobel_c_00.intra_l16_sobel_c0_qp3 = 13; + reg->i16_sobel_c_00.intra_l16_sobel_c0_qp4 = 13; + reg->i16_sobel_c_01.intra_l16_sobel_c0_qp5 = 13; + reg->i16_sobel_c_01.intra_l16_sobel_c0_qp6 = 13; + reg->i16_sobel_c_01.intra_l16_sobel_c0_qp7 = 13; + reg->i16_sobel_c_01.intra_l16_sobel_c0_qp8 = 13; + reg->i16_sobel_d_00.intra_l16_sobel_d0_qp0 = 23750; + reg->i16_sobel_d_00.intra_l16_sobel_d0_qp1 = 23750; + reg->i16_sobel_d_01.intra_l16_sobel_d0_qp2 = 23750; + reg->i16_sobel_d_01.intra_l16_sobel_d0_qp3 = 23750; + reg->i16_sobel_d_02.intra_l16_sobel_d0_qp4 = 23750; + reg->i16_sobel_d_02.intra_l16_sobel_d0_qp5 = 23750; + reg->i16_sobel_d_03.intra_l16_sobel_d0_qp6 = 23750; + reg->i16_sobel_d_03.intra_l16_sobel_d0_qp7 = 23750; + reg->i16_sobel_d_04.intra_l16_sobel_d0_qp8 = 23750; + + reg->intra_l16_sobel_e0_qp0_low = 20000; + reg->intra_l16_sobel_e0_qp1_low = 20000; + reg->intra_l16_sobel_e0_qp2_low = 20000; + reg->intra_l16_sobel_e0_qp3_low = 20000; + reg->intra_l16_sobel_e0_qp4_low = 20000; + reg->intra_l16_sobel_e0_qp5_low = 20000; + reg->intra_l16_sobel_e0_qp6_low = 20000; + reg->intra_l16_sobel_e0_qp7_low = 20000; + reg->intra_l16_sobel_e0_qp8_low = 20000; + reg->i16_sobel_e_01.intra_l16_sobel_e0_qp0_high = 0; + reg->i16_sobel_e_03.intra_l16_sobel_e0_qp1_high = 0; + reg->i16_sobel_e_05.intra_l16_sobel_e0_qp2_high = 0; + reg->i16_sobel_e_07.intra_l16_sobel_e0_qp3_high = 0; + reg->i16_sobel_e_09.intra_l16_sobel_e0_qp4_high = 0; + reg->i16_sobel_e_11.intra_l16_sobel_e0_qp5_high = 0; + reg->i16_sobel_e_13.intra_l16_sobel_e0_qp6_high = 0; + reg->i16_sobel_e_15.intra_l16_sobel_e0_qp7_high = 0; + reg->i16_sobel_e_17.intra_l16_sobel_e0_qp8_high = 0; + + reg->i32_sobel_t_00.intra_l32_sobel_t2 = 64; + reg->i32_sobel_t_00.intra_l32_sobel_t3 = 400; + reg->i32_sobel_t_01.intra_l32_sobel_t4 = 8; + reg->i32_sobel_t_02.intra_l32_sobel_t5 = 100; + reg->i32_sobel_t_02.intra_l32_sobel_t6 = 100; + + reg->i32_sobel_a.intra_l32_sobel_a1_qp0 = 18; + reg->i32_sobel_a.intra_l32_sobel_a1_qp1 = 18; + reg->i32_sobel_a.intra_l32_sobel_a1_qp2 = 18; + reg->i32_sobel_a.intra_l32_sobel_a1_qp3 = 18; + reg->i32_sobel_a.intra_l32_sobel_a1_qp4 = 18; + + reg->i32_sobel_b_00.intra_l32_sobel_b1_qp0 = 0; + reg->i32_sobel_b_00.intra_l32_sobel_b1_qp1 = 0; + reg->i32_sobel_b_01.intra_l32_sobel_b1_qp2 = 0; + reg->i32_sobel_b_01.intra_l32_sobel_b1_qp3 = 0; + reg->i32_sobel_b_02.intra_l32_sobel_b1_qp4 = 0; + + reg->i32_sobel_c.intra_l32_sobel_c1_qp0 = 16; + reg->i32_sobel_c.intra_l32_sobel_c1_qp1 = 16; + reg->i32_sobel_c.intra_l32_sobel_c1_qp2 = 16; + reg->i32_sobel_c.intra_l32_sobel_c1_qp3 = 16; + reg->i32_sobel_c.intra_l32_sobel_c1_qp4 = 16; + + reg->i32_sobel_d_00.intra_l32_sobel_d1_qp0 = 0; + reg->i32_sobel_d_00.intra_l32_sobel_d1_qp1 = 0; + reg->i32_sobel_d_01.intra_l32_sobel_d1_qp2 = 0; + reg->i32_sobel_d_01.intra_l32_sobel_d1_qp3 = 0; + reg->i32_sobel_d_02.intra_l32_sobel_d1_qp4 = 0; + + reg->intra_l32_sobel_e1_qp0_low = 20000; + reg->intra_l32_sobel_e1_qp1_low = 20000; + reg->intra_l32_sobel_e1_qp2_low = 20000; + reg->intra_l32_sobel_e1_qp3_low = 20000; + reg->intra_l32_sobel_e1_qp4_low = 20000; + + reg->i32_sobel_e_01.intra_l32_sobel_e1_qp0_high = 0; + reg->i32_sobel_e_03.intra_l32_sobel_e1_qp1_high = 0; + reg->i32_sobel_e_05.intra_l32_sobel_e1_qp2_high = 0; + reg->i32_sobel_e_07.intra_l32_sobel_e1_qp3_high = 0; + reg->i32_sobel_e_09.intra_l32_sobel_e1_qp4_high = 0; +} + +static void vepu580_h265_rdo_bias_cfg (vepu580_rdo_cfg *reg, MppEncHwCfg *hw) +{ + RdoAtfCfg* p_rdo_atf; + RdoAtfSkipCfg* p_rdo_atf_skip; + RK_U8 bias = h265e_mode_bias[hw->mode_bias[4]]; + + p_rdo_atf = ®->rdo_b64_inter_atf; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = bias; + + if (hw->skip_bias_en) { + bias = h265e_mode_bias[hw->skip_bias]; + + p_rdo_atf_skip = ®->rdo_b64_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = hw->skip_sad < 24 ? hw->skip_sad : 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = hw->skip_sad < 4 ? hw->skip_sad : 4; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = hw->skip_sad < 6 ? hw->skip_sad : 6; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = hw->skip_sad; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = bias > 24 ? bias : 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = bias < 4 ? bias : 4; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = bias < 6 ? bias : 6; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = bias < 8 ? bias : 8; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = bias < 10 ? bias : 10; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = bias < 10 ? bias : 10; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = bias < 10 ? bias : 10; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = bias < 14 ? bias : 14; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = bias < 14 ? bias : 14; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = bias < 15 ? bias : 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = bias < 15 ? bias : 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = bias < 15 ? bias : 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = bias; + } + + bias = h265e_mode_bias[hw->mode_bias[0]]; + + p_rdo_atf = ®->rdo_b32_intra_atf; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias > 26 ? bias : 26; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = bias > 24 ? bias : 24; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = bias > 23 ? bias : 23; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = bias > 21 ? bias : 21; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = bias > 19 ? bias : 19; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = bias > 18 ? bias : 18; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = bias; + + bias = h265e_mode_bias[hw->mode_bias[5]]; + + p_rdo_atf = ®->rdo_b32_inter_atf; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = bias; + + if (hw->skip_bias_en) { + bias = h265e_mode_bias[hw->skip_bias]; + + p_rdo_atf_skip = ®->rdo_b32_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = hw->skip_sad < 24 ? hw->skip_sad : 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = hw->skip_sad < 4 ? hw->skip_sad : 4; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = hw->skip_sad < 6 ? hw->skip_sad : 6; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = hw->skip_sad; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias > 18 ? bias : 18; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = bias < 11 ? bias : 11; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = bias < 11 ? bias : 11; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = bias < 11 ? bias : 11; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = bias < 13 ? bias : 13; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = bias < 13 ? bias : 13; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = bias < 13 ? bias : 13; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = bias < 15 ? bias : 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = bias < 15 ? bias : 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = bias < 15 ? bias : 15; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = bias; + } + + bias = h265e_mode_bias[hw->mode_bias[1]]; + + p_rdo_atf = ®->rdo_b16_intra_atf; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias > 26 ? bias : 26; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = bias > 24 ? bias : 24; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = bias > 23 ? bias : 23; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = bias > 21 ? bias : 21; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = bias > 19 ? bias : 19; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = bias > 18 ? bias : 18; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = bias; + + bias = h265e_mode_bias[hw->mode_bias[6]]; + + p_rdo_atf = ®->rdo_b16_inter_atf; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = bias; + + if (hw->skip_bias_en) { + bias = h265e_mode_bias[hw->skip_bias]; + + p_rdo_atf_skip = ®->rdo_b16_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = hw->skip_sad < 24 ? hw->skip_sad : 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = hw->skip_sad < 24 ? hw->skip_sad : 24; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = hw->skip_sad < 48 ? hw->skip_sad : 48; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = hw->skip_sad; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = bias; + } + + bias = h265e_mode_bias[hw->mode_bias[2]]; + + p_rdo_atf = ®->rdo_b8_intra_atf; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias > 26 ? bias : 26; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = bias > 25 ? bias : 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = bias > 24 ? bias : 24; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = bias > 23 ? bias : 23; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = bias > 21 ? bias : 21; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = bias > 19 ? bias : 19; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = bias > 18 ? bias : 18; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = bias; + + bias = h265e_mode_bias[hw->mode_bias[7]]; + + p_rdo_atf = ®->rdo_b8_inter_atf; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = bias; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = bias; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = bias; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = bias; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = bias; + + if (hw->skip_bias_en) { + bias = h265e_mode_bias[hw->skip_bias]; + + p_rdo_atf_skip = ®->rdo_b8_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = hw->skip_sad < 24 ? hw->skip_sad : 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = hw->skip_sad < 24 ? hw->skip_sad : 24; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = hw->skip_sad < 48 ? hw->skip_sad : 48; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = hw->skip_sad; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = bias; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = bias; + } +} + +static void vepu580_h265_rdo_cfg (vepu580_rdo_cfg *reg) +{ + RdoAtfCfg* p_rdo_atf; + RdoAtfSkipCfg* p_rdo_atf_skip; + reg->rdo_sqi_cfg.rdo_segment_en = 1; + reg->rdo_sqi_cfg.rdo_smear_en = 1; + p_rdo_atf = ®->rdo_b64_inter_atf; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 32; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 144; + p_rdo_atf->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 300; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd00 = 31; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd01 = 400; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd10 = 31; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd11 = 400; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd20 = 31; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd21 = 400; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd30 = 31; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd31 = 400; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = 16; + + p_rdo_atf_skip = ®->rdo_b64_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 4; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 6; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 8; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd10 = 31; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd11 = 400; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd20 = 31; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd21 = 400; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd30 = 31; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd31 = 400; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd40 = 31; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd41 = 400; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = 10; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = 10; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = 10; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = 14; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = 14; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = 16; + + p_rdo_atf = ®->rdo_b32_intra_atf; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 48; + p_rdo_atf->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 64; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd00 = 31; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd01 = 400; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd10 = 31; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd11 = 400; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd20 = 31; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd21 = 400; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd30 = 31; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd31 = 400; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 26; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = 25; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = 24; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = 23; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = 21; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = 19; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = 18; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = 16; + + p_rdo_atf = ®->rdo_b32_inter_atf; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 32; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 144; + p_rdo_atf->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 300; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd00 = 31; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd01 = 400; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd10 = 31; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd11 = 400; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd20 = 31; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd21 = 400; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd30 = 31; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd31 = 400; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = 16; + + p_rdo_atf_skip = ®->rdo_b32_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 4; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 6; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 8; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd10 = 31; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd11 = 400; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd20 = 31; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd21 = 400; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd30 = 31; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd31 = 400; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd40 = 31; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd41 = 400; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 18; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = 11; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = 11; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = 11; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = 13; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = 13; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = 13; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = 15; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = 15; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = 16; + + p_rdo_atf = ®->rdo_b16_intra_atf; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 48; + p_rdo_atf->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 64; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd00 = 31; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd01 = 400; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd10 = 31; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd11 = 400; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd20 = 31; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd21 = 400; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd30 = 31; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd31 = 400; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 26; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = 25; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = 24; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = 23; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = 21; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = 19; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = 18; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = 16; + + p_rdo_atf = ®->rdo_b16_inter_atf; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 32; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 144; + p_rdo_atf->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 300; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd00 = 31; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd01 = 400; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd10 = 31; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd11 = 400; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd20 = 31; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd21 = 400; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd30 = 31; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd31 = 400; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = 16; + + p_rdo_atf_skip = ®->rdo_b16_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 24; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 48; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 96; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd10 = 31; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd11 = 400; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd20 = 31; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd21 = 400; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd30 = 31; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd31 = 400; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd40 = 31; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd41 = 400; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = 16; + + p_rdo_atf = ®->rdo_b8_intra_atf; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 48; + p_rdo_atf->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 64; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd00 = 31; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd01 = 400; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd10 = 31; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd11 = 400; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd20 = 31; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd21 = 400; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd30 = 31; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd31 = 400; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 26; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = 25; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = 25; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = 24; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = 23; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = 21; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = 19; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = 18; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = 16; + + p_rdo_atf = ®->rdo_b8_inter_atf; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 32; + p_rdo_atf->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 144; + p_rdo_atf->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 300; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd00 = 31; + p_rdo_atf->rdo_b_var_thd0.cu_rdo_var_thd01 = 400; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd10 = 31; + p_rdo_atf->rdo_b_var_thd1.cu_rdo_var_thd11 = 400; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd20 = 31; + p_rdo_atf->rdo_b_var_thd2.cu_rdo_var_thd21 = 400; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd30 = 31; + p_rdo_atf->rdo_b_var_thd3.cu_rdo_var_thd31 = 400; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = 16; + p_rdo_atf->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = 16; + p_rdo_atf->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = 16; + p_rdo_atf->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = 16; + p_rdo_atf->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = 16; + + p_rdo_atf_skip = ®->rdo_b8_skip_atf; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p_rdo_atf_skip->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 24; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 48; + p_rdo_atf_skip->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 96; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd10 = 31; + p_rdo_atf_skip->rdo_b_var_thd0.cu_rdo_var_thd11 = 400; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd20 = 31; + p_rdo_atf_skip->rdo_b_var_thd1.cu_rdo_var_thd21 = 400; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd30 = 31; + p_rdo_atf_skip->rdo_b_var_thd2.cu_rdo_var_thd31 = 400; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd40 = 31; + p_rdo_atf_skip->rdo_b_var_thd3.cu_rdo_var_thd41 = 400; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = 16; + p_rdo_atf_skip->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = 16; + + reg->rdo_segment_b64_thd0.rdo_segment_cu64_th0 = 160; + reg->rdo_segment_b64_thd0.rdo_segment_cu64_th1 = 96; + reg->rdo_segment_b64_thd1.rdo_segment_cu64_th2 = 30; + reg->rdo_segment_b64_thd1.rdo_segment_cu64_th3 = 0; + reg->rdo_segment_b64_thd1.rdo_segment_cu64_th4 = 1; + reg->rdo_segment_b64_thd1.rdo_segment_cu64_th5_minus1 = 4; + reg->rdo_segment_b64_thd1.rdo_segment_cu64_th6_minus1 = 11; + + reg->rdo_segment_b32_thd0.rdo_segment_cu32_th0 = 160; + reg->rdo_segment_b32_thd0.rdo_segment_cu32_th1 = 96; + reg->rdo_segment_b32_thd1.rdo_segment_cu32_th2 = 30; + reg->rdo_segment_b32_thd1.rdo_segment_cu32_th3 = 0; + reg->rdo_segment_b32_thd1.rdo_segment_cu32_th4 = 1; + reg->rdo_segment_b32_thd1.rdo_segment_cu32_th5_minus1 = 2; + reg->rdo_segment_b32_thd1.rdo_segment_cu32_th6_minus1 = 3; + + reg->rdo_segment_multi.rdo_segment_cu64_multi = 22; + reg->rdo_segment_multi.rdo_segment_cu32_multi = 22; + reg->rdo_segment_multi.rdo_smear_cu16_multi = 6; + + reg->rdo_b16_smear_thd0.rdo_smear_cu16_cime_sad_th0 = 64; + reg->rdo_b16_smear_thd0.rdo_smear_cu16_cime_sad_th1 = 32; + reg->rdo_b16_smear_thd1.rdo_smear_cu16_cime_sad_th2 = 36; + reg->rdo_b16_smear_thd1.rdo_smear_cu16_cime_sad_th3 = 64; + + + reg->preintra_b32_cst_var_thd.pre_intra32_cst_var_th00 = 9; + reg->preintra_b32_cst_var_thd.pre_intra32_cst_var_th01 = 4; + reg->preintra_b32_cst_var_thd.pre_intra32_mode_th = 5; + + reg->preintra_b32_cst_wgt.pre_intra32_cst_wgt00 = 31; + reg->preintra_b32_cst_wgt.pre_intra32_cst_wgt01 = 25; + + reg->preintra_b16_cst_var_thd.pre_intra16_cst_var_th00 = 9; + reg->preintra_b16_cst_var_thd.pre_intra16_cst_var_th01 = 4; + reg->preintra_b16_cst_var_thd.pre_intra16_mode_th = 5; + + reg->preintra_b16_cst_wgt.pre_intra16_cst_wgt00 = 31; + reg->preintra_b16_cst_wgt.pre_intra16_cst_wgt01 = 25; +} + +static void vepu580_h265_scl_cfg(vepu580_rdo_cfg *reg) +{ + static RK_U32 vepu580_h265_scl_tab[] = { + /* 0x2200 */ + 0x10001000, 0x10001000, 0x0e390f0f, 0x0aab0c31, 0x10001000, 0x10001000, 0x0d790f0f, 0x0a3d0ba3, + 0x10001000, 0x0e390f0f, 0x0ba30ccd, 0x08d40a3d, 0x10001000, 0x0c310e39, 0x097b0aab, 0x071c0842, + 0x0f0f0f0f, 0x0aab0ccd, 0x07500889, 0x0572063e, 0x0d790e39, 0x097b0ba3, 0x05d10750, 0x03f004be, + 0x0ba30c31, 0x08420a3d, 0x04be063e, 0x02e903a8, 0x0a3d0aab, 0x071c08d4, 0x03f00572, 0x023a02e9, + 0x10001000, 0x10001000, 0x0e390f0f, 0x0aab0c31, 0x10001000, 0x10001000, 0x0d790f0f, 0x0a3d0ba3, + 0x10001000, 0x0e390f0f, 0x0ba30ccd, 0x08d40a3d, 0x10001000, 0x0c310e39, 0x097b0aab, 0x071c0842, + 0x0f0f0f0f, 0x0aab0ccd, 0x07500889, 0x0572063e, 0x0d790e39, 0x097b0ba3, 0x05d10750, 0x03f004be, + 0x0ba30c31, 0x08420a3d, 0x04be063e, 0x02e903a8, 0x0a3d0aab, 0x071c08d4, 0x03f00572, 0x023a02e9, + 0x10001000, 0x10001000, 0x0e390f0f, 0x0aab0c31, 0x10001000, 0x10001000, 0x0d790f0f, 0x0a3d0ba3, + 0x10001000, 0x0e390f0f, 0x0ba30ccd, 0x08d40a3d, 0x10001000, 0x0c310e39, 0x097b0aab, 0x071c0842, + 0x0f0f0f0f, 0x0aab0ccd, 0x07500889, 0x0572063e, 0x0d790e39, 0x097b0ba3, 0x05d10750, 0x03f004be, + 0x0ba30c31, 0x08420a3d, 0x04be063e, 0x02e903a8, 0x0a3d0aab, 0x071c08d4, 0x03f00572, 0x023a02e9, + 0x10001000, 0x10001000, 0x0e390f0f, 0x0aab0ccd, 0x10001000, 0x0f0f1000, 0x0ccd0e39, 0x0a3d0aab, + 0x10001000, 0x0e390f0f, 0x0aab0ccd, 0x09250a3d, 0x0f0f1000, 0x0ccd0e39, 0x0a3d0aab, 0x07c20925, + 0x0e390f0f, 0x0aab0ccd, 0x09250a3d, 0x063e07c2, 0x0ccd0e39, 0x0a3d0aab, 0x07c20925, 0x04be063e, + 0x0aab0ccd, 0x09250a3d, 0x063e07c2, 0x039b04be, 0x0a3d0aab, 0x07c20925, 0x04be063e, 0x02d0039b, + 0x10001000, 0x10001000, 0x0e390f0f, 0x0aab0ccd, 0x10001000, 0x0f0f1000, 0x0ccd0e39, 0x0a3d0aab, + 0x10001000, 0x0e390f0f, 0x0aab0ccd, 0x09250a3d, 0x0f0f1000, 0x0ccd0e39, 0x0a3d0aab, 0x07c20925, + 0x0e390f0f, 0x0aab0ccd, 0x09250a3d, 0x063e07c2, 0x0ccd0e39, 0x0a3d0aab, 0x07c20925, 0x04be063e, + 0x0aab0ccd, 0x09250a3d, 0x063e07c2, 0x039b04be, 0x0a3d0aab, 0x07c20925, 0x04be063e, 0x02d0039b, + 0x10001000, 0x10001000, 0x0e390f0f, 0x0aab0ccd, 0x10001000, 0x0f0f1000, 0x0ccd0e39, 0x0a3d0aab, + 0x10001000, 0x0e390f0f, 0x0aab0ccd, 0x09250a3d, 0x0f0f1000, 0x0ccd0e39, 0x0a3d0aab, 0x07c20925, + 0x0e390f0f, 0x0aab0ccd, 0x09250a3d, 0x063e07c2, 0x0ccd0e39, 0x0a3d0aab, 0x07c20925, 0x04be063e, + 0x0aab0ccd, 0x09250a3d, 0x063e07c2, 0x039b04be, 0x0a3d0aab, 0x07c20925, 0x04be063e, 0x02d0039b, + 0x10001000, 0x10001000, 0x10001000, 0x10101010, 0x0e390f0f, 0x0aab0c31, 0x10001000, 0x18151211, + 0x10001000, 0x10001000, 0x0e390f0f, 0x10101010, 0x0d790f0f, 0x0a3d0ba3, 0x0aab0c31, 0x19161311, + 0x10001000, 0x0e390f0f, 0x10001000, 0x12111010, 0x0ba30ccd, 0x08d40a3d, 0x10001000, 0x1d191614, + 0x10001000, 0x0c310e39, 0x0d790f0f, 0x15121010, 0x097b0aab, 0x071c0842, 0x0a3d0ba3, 0x241f1b18, + 0x0f0f0f0f, 0x0aab0ccd, 0x10001000, 0x18141111, 0x07500889, 0x0572063e, 0x0e390f0f, 0x2f29231e, + 0x0d790e39, 0x097b0ba3, 0x0ba30ccd, 0x1b161312, 0x05d10750, 0x03f004be, 0x08d40a3d, 0x41362c23, + 0x0ba30c31, 0x08420a3d, 0x10001000, 0x1f191615, 0x04be063e, 0x02e903a8, 0x0c310e39, 0x58463629, + 0x0a3d0aab, 0x071c08d4, 0x097b0aab, 0x241d1918, 0x03f00572, 0x023a02e9, 0x071c0842, 0x7358412f, + 0x10001000, 0x10001000, 0x0f0f0f0f, 0x10101010, 0x0e390f0f, 0x0aab0c31, 0x0aab0ccd, 0x18151211, + 0x10001000, 0x10001000, 0x07500889, 0x10101010, 0x0d790f0f, 0x0a3d0ba3, 0x0572063e, 0x19161311, + 0x10001000, 0x0e390f0f, 0x0d790e39, 0x12111010, 0x0ba30ccd, 0x08d40a3d, 0x097b0ba3, 0x1d191614, + 0x10001000, 0x0c310e39, 0x05d10750, 0x15121010, 0x097b0aab, 0x071c0842, 0x03f004be, 0x241f1b18, + 0x0f0f0f0f, 0x0aab0ccd, 0x0ba30c31, 0x18141111, 0x07500889, 0x0572063e, 0x08420a3d, 0x2f29231e, + 0x0d790e39, 0x097b0ba3, 0x04be063e, 0x1b161312, 0x05d10750, 0x03f004be, 0x02e903a8, 0x41362c23, + 0x0ba30c31, 0x08420a3d, 0x0a3d0aab, 0x1f191615, 0x04be063e, 0x02e903a8, 0x071c08d4, 0x58463629, + 0x0a3d0aab, 0x071c08d4, 0x03f00572, 0x241d1918, 0x03f00572, 0x023a02e9, 0x023a02e9, 0x7358412f, + 0x10001000, 0x10001000, 0x10001000, 0x10101010, 0x0e390f0f, 0x0aab0c31, 0x10001000, 0x18151211, + 0x10001000, 0x10001000, 0x0e390f0f, 0x10101010, 0x0d790f0f, 0x0a3d0ba3, 0x0aab0ccd, 0x19161311, + 0x10001000, 0x0e390f0f, 0x10001000, 0x12111010, 0x0ba30ccd, 0x08d40a3d, 0x0f0f1000, 0x1d191614, + 0x10001000, 0x0c310e39, 0x0ccd0e39, 0x15121010, 0x097b0aab, 0x071c0842, 0x0a3d0aab, 0x241f1b18, + 0x0f0f0f0f, 0x0aab0ccd, 0x10001000, 0x18141111, 0x07500889, 0x0572063e, 0x0e390f0f, 0x2f29231e, + 0x0d790e39, 0x097b0ba3, 0x0aab0ccd, 0x1b161312, 0x05d10750, 0x03f004be, 0x09250a3d, 0x41362c23, + 0x0ba30c31, 0x08420a3d, 0x0f0f1000, 0x1f191615, 0x04be063e, 0x02e903a8, 0x0ccd0e39, 0x58463629, + 0x0a3d0aab, 0x071c08d4, 0x0a3d0aab, 0x241d1918, 0x03f00572, 0x023a02e9, 0x07c20925, 0x7358412f, + 0x10001000, 0x10001000, 0x0e390f0f, 0x10101010, 0x0e390f0f, 0x0aab0ccd, 0x0aab0ccd, 0x18141211, + 0x10001000, 0x0f0f1000, 0x09250a3d, 0x11101010, 0x0ccd0e39, 0x0a3d0aab, 0x063e07c2, 0x19181412, + 0x10001000, 0x0e390f0f, 0x0ccd0e39, 0x12111010, 0x0aab0ccd, 0x09250a3d, 0x0a3d0aab, 0x1c191814, + 0x0f0f1000, 0x0ccd0e39, 0x07c20925, 0x14121110, 0x0a3d0aab, 0x07c20925, 0x04be063e, 0x211c1918, + 0x0e390f0f, 0x0aab0ccd, 0x0aab0ccd, 0x18141211, 0x09250a3d, 0x063e07c2, 0x09250a3d, 0x29211c19, + 0x0ccd0e39, 0x0a3d0aab, 0x063e07c2, 0x19181412, 0x07c20925, 0x04be063e, 0x039b04be, 0x3629211c, + 0x0aab0ccd, 0x09250a3d, 0x0a3d0aab, 0x1c191814, 0x063e07c2, 0x039b04be, 0x07c20925, 0x47362921, + 0x0a3d0aab, 0x07c20925, 0x04be063e, 0x211c1918, 0x04be063e, 0x02d0039b, 0x02d0039b, 0x5b473629, + 0x10001000, 0x10001000, 0x10101010, 0x10101010, 0x0e390f0f, 0x0aab0ccd, 0x10101010, 0x18141211, + 0x10001000, 0x0f0f1000, 0x12111211, 0x11101010, 0x0ccd0e39, 0x0a3d0aab, 0x18141815, 0x19181412, + 0x10001000, 0x0e390f0f, 0x10101010, 0x12111010, 0x0aab0ccd, 0x09250a3d, 0x11101010, 0x1c191814, + 0x0f0f1000, 0x0ccd0e39, 0x14121311, 0x14121110, 0x0a3d0aab, 0x07c20925, 0x19181916, 0x211c1918, + 0x0e390f0f, 0x0aab0ccd, 0x10101010, 0x18141211, 0x09250a3d, 0x063e07c2, 0x12111211, 0x29211c19, + 0x0ccd0e39, 0x0a3d0aab, 0x18141614, 0x19181412, 0x07c20925, 0x04be063e, 0x1c191d19, 0x3629211c, + 0x0aab0ccd, 0x09250a3d, 0x11101010, 0x1c191814, 0x063e07c2, 0x039b04be, 0x14121512, 0x47362921, + 0x0a3d0aab, 0x07c20925, 0x19181b18, 0x211c1918, 0x04be063e, 0x02d0039b, 0x211c241f, 0x5b473629, + 0x10001000, 0x10001000, 0x12111111, 0x10101010, 0x0e390f0f, 0x0aab0ccd, 0x18141814, 0x18141211, + 0x10001000, 0x0f0f1000, 0x1c19231e, 0x11101010, 0x0ccd0e39, 0x0a3d0aab, 0x29212f29, 0x19181412, + 0x10001000, 0x0e390f0f, 0x14121312, 0x12111010, 0x0aab0ccd, 0x09250a3d, 0x19181b16, 0x1c191814, + 0x0f0f1000, 0x0ccd0e39, 0x211c2c23, 0x14121110, 0x0a3d0aab, 0x07c20925, 0x36294136, 0x211c1918, + 0x0e390f0f, 0x0aab0ccd, 0x18141615, 0x18141211, 0x09250a3d, 0x063e07c2, 0x1c191f19, 0x29211c19, + 0x0ccd0e39, 0x0a3d0aab, 0x29213629, 0x19181412, 0x07c20925, 0x04be063e, 0x47365846, 0x3629211c, + 0x0aab0ccd, 0x09250a3d, 0x19181918, 0x1c191814, 0x063e07c2, 0x039b04be, 0x211c241d, 0x47362921, + 0x0a3d0aab, 0x07c20925, 0x3629412f, 0x211c1918, 0x04be063e, 0x02d0039b, 0x5b477358, 0x5b473629, + 0x10101010, 0x18151211, 0x10101010, 0x18141211, 0x10101010, 0x19161311, 0x11101010, 0x19181412, + 0x12111010, 0x1d191614, 0x12111010, 0x1c191814, 0x15121010, 0x241f1b18, 0x14121110, 0x211c1918, + 0x18141111, 0x2f29231e, 0x18141211, 0x29211c19, 0x1b161312, 0x41362c23, 0x19181412, 0x3629211c, + 0x1f191615, 0x58463629, 0x1c191814, 0x47362921, 0x241d1918, 0x7358412f, 0x211c1918, 0x5b473629, + 0x10101010, 0x18151211, 0x10101010, 0x18141211, 0x10101010, 0x19161311, 0x11101010, 0x19181412, + 0x12111010, 0x1d191614, 0x12111010, 0x1c191814, 0x15121010, 0x241f1b18, 0x14121110, 0x211c1918, + 0x18141111, 0x2f29231e, 0x18141211, 0x29211c19, 0x1b161312, 0x41362c23, 0x19181412, 0x3629211c, + 0x1f191615, 0x58463629, 0x1c191814, 0x47362921, 0x241d1918, 0x7358412f, 0x211c1918, 0x5b473629, + 0x10101010, 0x18151211, 0x10101010, 0x18141211, 0x10101010, 0x19161311, 0x11101010, 0x19181412, + 0x12111010, 0x1d191614, 0x12111010, 0x1c191814, 0x15121010, 0x241f1b18, 0x14121110, 0x211c1918, + 0x18141111, 0x2f29231e, 0x18141211, 0x29211c19, 0x1b161312, 0x41362c23, 0x19181412, 0x3629211c, + 0x1f191615, 0x58463629, 0x1c191814, 0x47362921, 0x241d1918, 0x7358412f, 0x211c1918, 0x5b473629, + 0x10001000, 0x10001000, 0x10001000, 0x10001000, 0x10101010, 0x10101010, + }; + + hal_h265e_dbg_func("enter\n"); + + memcpy(®->scaling_list_reg[0], vepu580_h265_scl_tab, sizeof(vepu580_h265_scl_tab)); + + hal_h265e_dbg_func("leave\n"); +} +static void vepu580_h265_global_cfg_set(H265eV580HalContext *ctx, H265eV580RegSet *regs) +{ + MppEncHwCfg *hw = &ctx->cfg->hw; + RK_U32 i; + hevc_vepu580_rc_klut *rc_regs = ®s->reg_rc_klut; + hevc_vepu580_wgt *reg_wgt = ®s->reg_wgt; + vepu580_rdo_cfg *reg_rdo = ®s->reg_rdo; + + vepu580_h265_sobel_cfg(reg_wgt); + vepu580_h265_rdo_cfg(reg_rdo); + vepu580_h265_rdo_bias_cfg(reg_rdo, hw); + vepu580_h265_scl_cfg(reg_rdo); + + memcpy(®_wgt->iprd_wgt_qp_hevc_0_51[0], lamd_satd_qp, sizeof(lamd_satd_qp)); + + if (ctx->frame_type == INTRA_FRAME) { + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + rc_regs->aq_tthd[i] = hw->aq_thrd_i[i]; + rc_regs->aq_step[i] = hw->aq_step_i[i] & 0x3f; + } + memcpy(®_wgt->rdo_wgta_qp_grpa_0_51[0], lamd_moda_qp, sizeof(lamd_moda_qp)); + } else { + for (i = 0; i < MPP_ARRAY_ELEMS(aq_thd_default); i++) { + rc_regs->aq_tthd[i] = hw->aq_thrd_p[i]; + rc_regs->aq_step[i] = hw->aq_step_p[i] & 0x3f; + } + memcpy(®_wgt->rdo_wgta_qp_grpa_0_51[0], lamd_modb_qp, sizeof(lamd_modb_qp)); + } + //to be done + rc_regs->madi_cfg.madi_mode = 0; + rc_regs->madi_cfg.madi_thd = 25; + rc_regs->md_sad_thd.md_sad_thd0 = 20; + rc_regs->md_sad_thd.md_sad_thd1 = 30; + rc_regs->md_sad_thd.md_sad_thd2 = 40; + rc_regs->madi_thd.madi_thd0 = 25; + rc_regs->madi_thd.madi_thd1 = 35; + rc_regs->madi_thd.madi_thd2 = 45; + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_i = 171; + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_p = 85; + + memcpy(®_wgt->lvl32_intra_CST_THD0, lvl32_intra_cst_thd, sizeof(lvl32_intra_cst_thd)); + memcpy(®_wgt->lvl16_intra_CST_THD0, lvl16_intra_cst_thd, sizeof(lvl16_intra_cst_thd)); + memcpy(®_wgt->lvl32_intra_CST_WGT0, lvl32_intra_cst_wgt, sizeof(lvl32_intra_cst_wgt)); + memcpy(®_wgt->lvl16_intra_CST_WGT0, lvl16_intra_cst_wgt, sizeof(lvl16_intra_cst_wgt)); + + reg_wgt->cime_sqi_cfg.cime_sad_mod_sel = 0; + reg_wgt->cime_sqi_cfg.cime_sad_use_big_block = 0; + reg_wgt->cime_sqi_cfg.cime_pmv_set_zero = 1; + reg_wgt->cime_sqi_cfg.cime_pmv_num = 3; + reg_wgt->cime_sqi_thd.cime_mvd_th0 = 32; + reg_wgt->cime_sqi_thd.cime_mvd_th1 = 80; + reg_wgt->cime_sqi_thd.cime_mvd_th2 = 128; + reg_wgt->cime_sqi_multi0.cime_multi0 = 16; + reg_wgt->cime_sqi_multi0.cime_multi1 = 32; + reg_wgt->cime_sqi_multi1.cime_multi2 = 96; + reg_wgt->cime_sqi_multi1.cime_multi3 = 96; + reg_wgt->rime_sqi_thd.cime_sad_th0 = 48; + reg_wgt->rime_sqi_thd.rime_mvd_th0 = 3; + reg_wgt->rime_sqi_thd.rime_mvd_th1 = 8; + reg_wgt->rime_sqi_multi.rime_multi0 = 16; + reg_wgt->rime_sqi_multi.rime_multi1 = 16; + reg_wgt->rime_sqi_multi.rime_multi2 = 128; + reg_wgt->fme_sqi_thd0.cime_sad_pu16_th = 16; + reg_wgt->fme_sqi_thd0.cime_sad_pu32_th = 16; + reg_wgt->fme_sqi_thd1.cime_sad_pu64_th = 16; + reg_wgt->fme_sqi_thd1.move_lambda = 1; +} + +MPP_RET hal_h265e_v580_deinit(void *hal) +{ + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + RK_S32 i; + + hal_h265e_enter(); + + for (i = 0; i < ctx->task_cnt; i++) { + Vepu580H265eFrmCfg *frm = ctx->frms[i]; + RK_U32 j; + + if (!frm) + continue; + + for (j = 0; j < MAX_TILE_NUM; j++) { + MPP_FREE(frm->regs_set[j]); + MPP_FREE(frm->regs_ret[j]); + } + + for (j = 0; j < MAX_TILE_NUM; j++) { + if (frm->hw_tile_buf[j]) { + mpp_buffer_put(frm->hw_tile_buf[j]); + frm->hw_tile_buf[j] = NULL; + } + } + + for (j = 0; j < MAX_TILE_NUM - 1; j++) { + if (frm->hw_tile_stream[j]) { + mpp_buffer_put(frm->hw_tile_stream[j]); + frm->hw_tile_stream[j] = NULL; + } + } + + if (frm->roi_base_cfg_buf) { + mpp_buffer_put(frm->roi_base_cfg_buf); + frm->roi_base_cfg_buf = NULL; + frm->roi_base_buf_size = 0; + } + + MPP_FREE(frm->roi_base_cfg_sw_buf); + + if (frm->reg_cfg) { + mpp_dev_multi_offset_deinit(frm->reg_cfg); + frm->reg_cfg = NULL; + } + + MPP_FREE(ctx->frms[i]); + } + + MPP_FREE(ctx->poll_cfgs); + MPP_FREE(ctx->input_fmt); + hal_bufs_deinit(ctx->dpb_bufs); + + if (ctx->tile_grp) { + mpp_buffer_group_put(ctx->tile_grp); + ctx->tile_grp = NULL; + } + + if (ctx->roi_grp) { + mpp_buffer_group_put(ctx->roi_grp); + ctx->roi_grp = NULL; + } + + if (ctx->buf_pass1) { + mpp_buffer_put(ctx->buf_pass1); + ctx->buf_pass1 = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + if (ctx->tune) { + vepu580_h265e_tune_deinit(ctx->tune); + ctx->tune = NULL; + } + + if (ctx->md_info_buf) { + mpp_buffer_put(ctx->md_info_buf); + ctx->md_info_buf = NULL; + } + + if (ctx->qpmap_base_cfg_buf) { + mpp_buffer_put(ctx->qpmap_base_cfg_buf); + ctx->qpmap_base_cfg_buf = NULL; + } + + if (ctx->qpmap_qp_cfg_buf) { + mpp_buffer_put(ctx->qpmap_qp_cfg_buf); + ctx->qpmap_qp_cfg_buf = NULL; + } + + if (ctx->md_flag_buf) { + MPP_FREE(ctx->md_flag_buf); + } + + if (ctx->qpmap_grp) { + mpp_buffer_group_put(ctx->qpmap_grp); + ctx->qpmap_grp = NULL; + } + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v580_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + RK_S32 i = 0; + + mpp_env_get_u32("hal_h265e_debug", &hal_h265e_debug, 0); + + hal_h265e_enter(); + + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + hal_bufs_init(&ctx->dpb_bufs); + + ctx->frame_count = 0; + ctx->enc_mode = RKV_ENC_MODE; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + goto DONE; + } + + ctx->dev = cfg->dev; + ctx->task_cnt = cfg->task_cnt; + mpp_assert(ctx->task_cnt && ctx->task_cnt <= MAX_FRAME_TASK_NUM); + + if (ctx->task_cnt > MAX_FRAME_TASK_NUM) + ctx->task_cnt = MAX_FRAME_TASK_NUM; + + for (i = 0; i < cfg->task_cnt; i++) { + Vepu580H265eFrmCfg *frm_cfg = mpp_calloc(Vepu580H265eFrmCfg, 1); + + frm_cfg->regs_set[0] = mpp_calloc(H265eV580RegSet, 1); + frm_cfg->regs_ret[0] = mpp_calloc(H265eV580StatusElem, 1); + + frm_cfg->osd_cfg.reg_base = &frm_cfg->regs_set[0]->reg_osd_cfg; + + /* setup osd cfg */ + frm_cfg->osd_cfg.dev = ctx->dev; + frm_cfg->osd_cfg.plt_cfg = &ctx->cfg->plt_cfg; + frm_cfg->osd_cfg.osd_data = NULL; + frm_cfg->osd_cfg.osd_data2 = NULL; + mpp_dev_multi_offset_init(&frm_cfg->reg_cfg, 24); + frm_cfg->osd_cfg.reg_cfg = frm_cfg->reg_cfg; + + frm_cfg->frame_type = INTRA_FRAME; + + ctx->frms[i] = frm_cfg; + } + + { /* setup default hardware config */ + MppEncHwCfg *hw = &cfg->cfg->hw; + RK_U32 j; + + hw->qp_delta_row_i = 2; + hw->qp_delta_row = 2; + hw->qbias_i = 171; + hw->qbias_p = 85; + hw->qbias_en = 0; + + memcpy(hw->aq_thrd_i, aq_thd_default, sizeof(hw->aq_thrd_i)); + memcpy(hw->aq_thrd_p, aq_thd_default, sizeof(hw->aq_thrd_p)); + memcpy(hw->aq_step_i, aq_qp_dealt_default, sizeof(hw->aq_step_i)); + memcpy(hw->aq_step_p, aq_qp_dealt_default, sizeof(hw->aq_step_p)); + + for (j = 0; j < MPP_ARRAY_ELEMS(hw->mode_bias); j++) + hw->mode_bias[j] = 8; + + hw->skip_sad = 8; + hw->skip_bias = 8; + } + + ctx->tune = vepu580_h265e_tune_init(ctx); + + { + // check parall tile ability + const MppServiceCmdCap *cap = mpp_get_mpp_service_cmd_cap(); + + ctx->tile_parall_en = cap->send_cmd > MPP_CMD_SET_SESSION_FD; + } + + ctx->poll_slice_max = 8; + ctx->poll_cfg_size = (sizeof(ctx->poll_cfgs) + sizeof(RK_S32) * ctx->poll_slice_max) * 2; + ctx->poll_cfgs = mpp_malloc_size(MppDevPollCfg, ctx->poll_cfg_size); + + if (NULL == ctx->poll_cfgs) { + ret = MPP_ERR_MALLOC; + mpp_err_f("init poll cfg buffer failed\n"); + goto DONE; + } + ctx->output_cb = cfg->output_cb; + cfg->cap_recn_out = 1; + memset(ctx->slot_to_dchs_txid, 0, sizeof(ctx->slot_to_dchs_txid)); +DONE: + if (ret) + hal_h265e_v580_deinit(hal); + + hal_h265e_leave(); + return ret; +} +static MPP_RET hal_h265e_vepu580_prepare(void *hal) +{ + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + MppEncPrepCfg *prep = &ctx->cfg->prep; + + hal_h265e_dbg_func("enter %p\n", hal); + + if (prep->change_res) { + RK_S32 i; + + // pre-alloc required buffers to reduce first frame delay + vepu580_h265_setup_hal_bufs(ctx); + for (i = 0; i < ctx->max_buf_cnt; i++) + hal_bufs_get_buf(ctx->dpb_bufs, i); + + prep->change_res = 0; + } + + hal_h265e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET +vepu580_h265_set_patch_info(MppDevRegOffCfgs *cfgs, H265eSyntax_new *syn, + VepuFmt input_fmt, HalEncTask *task) +{ + MppFrameFormat fmt = mpp_frame_get_fmt(task->frame); + RK_U32 hor_stride = syn->pp.hor_stride; + RK_U32 ver_stride = (syn->pp.ver_stride != 0) ? syn->pp.ver_stride : syn->pp.pic_height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + if (task->rc_task->frm.use_pass1) + fmt = MPP_FMT_YUV420SP; + + if (MPP_FRAME_FMT_IS_FBC(fmt)) { + u_offset = mpp_frame_get_fbc_offset(task->frame); + v_offset = 0; + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV400: + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride; + } break; + case VEPU5xx_FMT_YUV444P : { + u_offset = hor_stride * ver_stride; + v_offset = hor_stride * ver_stride * 2; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + default: { + hal_h265e_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + + /* input cb addr */ + ret = mpp_dev_multi_offset_update(cfgs, 161, u_offset); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); + + /* input cr addr */ + ret = mpp_dev_multi_offset_update(cfgs, 162, v_offset); + if (ret) + mpp_err_f("set input cr addr offset failed %d\n", ret); + + return ret; +} + +typedef struct refresh_area { + RK_S32 roi_ctu_x_sta; + RK_S32 roi_ctu_y_sta; + RK_S32 roi_ctu_x_end; + RK_S32 roi_ctu_y_end; +} RefreshArea; + +static MPP_RET cal_refresh_area(RK_S32 ctu_w, RK_S32 ctu_h, RK_U32 refresh_idx, + MppEncRcRefreshMode refresh_mode, RK_U32 refresh_num, RefreshArea *area) +{ + MPP_RET ret = MPP_OK; + RK_U32 refresh_ctu_h = 0; + + if (refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + area->roi_ctu_x_sta = 0; + area->roi_ctu_x_end = ctu_w - 1; + + if (refresh_idx > 0) { + refresh_ctu_h = refresh_num + 1; + area->roi_ctu_y_sta = refresh_num * refresh_idx - 1; + } else { + refresh_ctu_h = refresh_num; + area->roi_ctu_y_sta = 0; + } + + area->roi_ctu_y_end = area->roi_ctu_y_sta + refresh_ctu_h - 1; + } else { + area->roi_ctu_y_sta = 0; + area->roi_ctu_y_end = ctu_h - 1; + + if (refresh_idx > 0) { + refresh_ctu_h = refresh_num + 1; + area->roi_ctu_x_sta = refresh_num * refresh_idx - 1; + } else { + refresh_ctu_h = refresh_num; + area->roi_ctu_x_sta = 0; + } + + area->roi_ctu_x_end = area->roi_ctu_x_sta + refresh_ctu_h - 1; + } + + area->roi_ctu_x_end = MPP_MIN(area->roi_ctu_x_end, ctu_w - 1); + area->roi_ctu_y_end = MPP_MIN(area->roi_ctu_y_end, ctu_h - 1); + area->roi_ctu_x_sta = MPP_MAX(area->roi_ctu_x_sta, 0); + area->roi_ctu_y_sta = MPP_MAX(area->roi_ctu_y_sta, 0); + + hal_h265e_dbg_detail("size in ctu : %d x %d, refresh_num %d, refresh_idx %d, area x[%d, %d], y[%d, %d]", + ctu_w, ctu_h, refresh_num, refresh_idx, + area->roi_ctu_x_sta, area->roi_ctu_x_end, + area->roi_ctu_y_sta, area->roi_ctu_y_end); + + return ret; +} + +static MPP_RET setup_intra_refresh(H265eV580HalContext *ctx, RK_U32 refresh_idx) +{ + Vepu580H265eFrmCfg *frm = ctx->frm; + H265eV580RegSet *regs = frm->regs_set[0]; + RK_U32 w = ctx->cfg->prep.width; + RK_U32 h = ctx->cfg->prep.height; + RK_S32 ctu_w = MPP_ALIGN(w, 64) / 64; + RK_S32 ctu_h = MPP_ALIGN(h, 64) / 64; + RK_S32 roi_base_cfg_buf_size = ctu_w * ctu_h * 64; + MppEncROICfg2 *external_roi_cfg = (MppEncROICfg2 *)frm->roi_data; + RK_U8 *roi_base_cfg_hw_ptr = NULL; + RK_S32 roi_base_cfg_buf_fd = 0; + RefreshArea cur_area; + RK_S32 j, k; + MPP_RET ret = MPP_OK; + + hal_h265e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en) { + ret = MPP_ERR_VALUE; + goto __RET; + } + + if (frm->roi_data) { + roi_base_cfg_hw_ptr = mpp_buffer_get_ptr(external_roi_cfg->base_cfg_buf); + roi_base_cfg_buf_fd = mpp_buffer_get_fd(external_roi_cfg->base_cfg_buf); + } else { + if (frm->roi_base_buf_size < roi_base_cfg_buf_size) { + if (NULL == ctx->roi_grp) + mpp_buffer_group_get_internal(&ctx->roi_grp, MPP_BUFFER_TYPE_ION); + if (frm->roi_base_cfg_buf) + mpp_buffer_put(frm->roi_base_cfg_buf); + MPP_FREE(frm->roi_base_cfg_sw_buf); + frm->roi_base_cfg_sw_buf = mpp_malloc(RK_U8, roi_base_cfg_buf_size); + mpp_buffer_get(ctx->roi_grp, &frm->roi_base_cfg_buf, roi_base_cfg_buf_size); + } + roi_base_cfg_hw_ptr = mpp_buffer_get_ptr(frm->roi_base_cfg_buf); + roi_base_cfg_buf_fd = mpp_buffer_get_fd(frm->roi_base_cfg_buf); + } + + frm->roi_base_buf_size = roi_base_cfg_buf_size; + + memset(frm->roi_base_cfg_sw_buf, 0, roi_base_cfg_buf_size); + + if (MPP_OK != cal_refresh_area(ctu_w, ctu_h, refresh_idx, ctx->cfg->rc.refresh_mode, ctx->cfg->rc.refresh_num, &cur_area)) { + ret = MPP_ERR_VALUE; + mpp_err_f("setting refresh area out of range"); + goto __RET; + } + + RK_U8 *ptr = frm->roi_base_cfg_sw_buf; + for (j = 0; j < ctu_h; j++) { + for (k = 0; k < ctu_w; k++) { + if (j <= cur_area.roi_ctu_y_end && j >= cur_area.roi_ctu_y_sta && + k <= cur_area.roi_ctu_x_end && k >= cur_area.roi_ctu_x_sta) { + + memset(ptr + 22, 0x55, 20); //176~336 + *(ptr + 21) = 0x54; //170~175 + *(ptr + 42) = 0x05; //336~339 + } + ptr += 64; + } + } + + memcpy(roi_base_cfg_hw_ptr, frm->roi_base_cfg_sw_buf, roi_base_cfg_buf_size); + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) + regs->reg_base.reg0220_me_rnge.cme_srch_v = 1; + else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) + regs->reg_base.reg0220_me_rnge.cme_srch_h = 1; + + regs->reg_base.reg0192_enc_pic.roi_en = 1; + regs->reg_base.reg0178_roi_addr = roi_base_cfg_buf_fd; + mpp_buffer_sync_end(frm->roi_base_cfg_buf); + +__RET: + hal_h265e_dbg_func("leave, ret %d\n", ret); + return ret; +} + + +static MPP_RET vepu580_h265_set_roi_regs(H265eV580HalContext *ctx, hevc_vepu580_base *regs) +{ + Vepu580H265eFrmCfg *frm = ctx->frm; + + /* memset register on start so do not clear registers again here */ + if (frm->roi_data) { + /* roi setup */ + RK_U32 ctu_w = MPP_ALIGN(ctx->cfg->prep.width, 64) / 64; + RK_U32 ctu_h = MPP_ALIGN(ctx->cfg->prep.height, 64) / 64; + RK_U32 base_cfg_size = ctu_w * ctu_h * 64; + RK_U32 qp_cfg_size = ctu_w * ctu_h * 256; + RK_U32 amv_cfg_size = ctu_w * ctu_h * 512; + RK_U32 mv_cfg_size = ctu_w * ctu_h * 4; + MppEncROICfg2 *cfg = (MppEncROICfg2 *)frm->roi_data; + + if (mpp_buffer_get_size(cfg->base_cfg_buf) >= base_cfg_size) { + regs->reg0192_enc_pic.roi_en = 1; + regs->reg0178_roi_addr = mpp_buffer_get_fd(cfg->base_cfg_buf); + } else { + mpp_err("roi base cfg buf not enough, roi is invalid"); + } + + if (cfg->roi_qp_en) { + if (mpp_buffer_get_size(cfg->qp_cfg_buf) >= qp_cfg_size) { + regs->reg0179_roi_qp_addr = mpp_buffer_get_fd(cfg->qp_cfg_buf); + regs->reg0228_roi_en.roi_qp_en = 1; + } else { + mpp_err("roi qp cfg buf not enough, roi is invalid"); + } + } + + if (cfg->roi_amv_en) { + if (mpp_buffer_get_size(cfg->amv_cfg_buf) >= amv_cfg_size) { + regs->reg0180_roi_amv_addr = mpp_buffer_get_fd(cfg->amv_cfg_buf); + regs->reg0228_roi_en.roi_amv_en = 1; + } else { + mpp_err("roi amv cfg buf not enough, roi is invalid"); + } + } + + if (cfg->roi_mv_en) { + if (mpp_buffer_get_size(cfg->mv_cfg_buf) >= mv_cfg_size) { + regs->reg0181_roi_mv_addr = mpp_buffer_get_fd(cfg->mv_cfg_buf); + regs->reg0228_roi_en.roi_mv_en = 1; + } else { + mpp_err("roi mv cfg buf not enough, roi is invalid"); + } + } + } + + return MPP_OK; +} + +static MPP_RET vepu580_h265_set_rc_regs(H265eV580HalContext *ctx, H265eV580RegSet *regs, HalEncTask *task) +{ + H265eSyntax_new *syn = ctx->syn; + EncRcTaskInfo *rc_cfg = &task->rc_task->info; + hevc_vepu580_base *reg_base = ®s->reg_base; + hevc_vepu580_rc_klut *reg_rc = ®s->reg_rc_klut; + MppEncCfgSet *cfg = ctx->cfg; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg *hw = &cfg->hw; + MppEncH265Cfg *h265 = &cfg->h265; + RK_S32 mb_wd64, mb_h64; + mb_wd64 = (syn->pp.pic_width + 63) / 64; + mb_h64 = (syn->pp.pic_height + 63) / 64; + + RK_U32 ctu_target_bits_mul_16 = (rc_cfg->bit_target << 4) / (mb_wd64 * mb_h64); + RK_U32 ctu_target_bits; + RK_S32 negative_bits_thd, positive_bits_thd; + + if (rc->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + reg_base->reg0192_enc_pic.pic_qp = rc_cfg->quality_target; + reg_base->reg0240_synt_sli1.sli_qp = rc_cfg->quality_target; + + reg_base->reg213_rc_qp.rc_max_qp = rc_cfg->quality_target; + reg_base->reg213_rc_qp.rc_min_qp = rc_cfg->quality_target; + } else { + if (ctu_target_bits_mul_16 >= 0x100000) { + ctu_target_bits_mul_16 = 0x50000; + } + ctu_target_bits = (ctu_target_bits_mul_16 * mb_wd64) >> 4; + negative_bits_thd = 0 - 5 * ctu_target_bits / 16; + positive_bits_thd = 5 * ctu_target_bits / 16; + + reg_base->reg0192_enc_pic.pic_qp = rc_cfg->quality_target; + reg_base->reg0240_synt_sli1.sli_qp = rc_cfg->quality_target; + reg_base->reg212_rc_cfg.rc_en = 1; + reg_base->reg212_rc_cfg.aq_en = 1; + reg_base->reg212_rc_cfg.aq_mode = 1; + reg_base->reg212_rc_cfg.rc_ctu_num = mb_wd64; + reg_base->reg213_rc_qp.rc_qp_range = (ctx->frame_type == INTRA_FRAME) ? + hw->qp_delta_row_i : hw->qp_delta_row; + reg_base->reg213_rc_qp.rc_max_qp = rc_cfg->quality_max; + reg_base->reg213_rc_qp.rc_min_qp = rc_cfg->quality_min; + reg_base->reg214_rc_tgt.ctu_ebit = ctu_target_bits_mul_16; + + reg_rc->rc_dthd_0_8[0] = 2 * negative_bits_thd; + reg_rc->rc_dthd_0_8[1] = negative_bits_thd; + reg_rc->rc_dthd_0_8[2] = positive_bits_thd; + reg_rc->rc_dthd_0_8[3] = 2 * positive_bits_thd; + reg_rc->rc_dthd_0_8[4] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[5] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[6] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[7] = 0x7FFFFFFF; + reg_rc->rc_dthd_0_8[8] = 0x7FFFFFFF; + + reg_rc->rc_adj0.qp_adj0 = -2; + reg_rc->rc_adj0.qp_adj1 = -1; + reg_rc->rc_adj0.qp_adj2 = 0; + reg_rc->rc_adj0.qp_adj3 = 1; + reg_rc->rc_adj0.qp_adj4 = 2; + reg_rc->rc_adj1.qp_adj5 = 0; + reg_rc->rc_adj1.qp_adj6 = 0; + reg_rc->rc_adj1.qp_adj7 = 0; + reg_rc->rc_adj1.qp_adj8 = 0; + + if (rc->rc_mode == MPP_ENC_RC_MODE_SMTRC) { + reg_base->reg213_rc_qp.rc_qp_range = 0; + } + } + + reg_rc->roi_qthd0.qpmin_area0 = h265->qpmin_map[0] > 0 ? h265->qpmin_map[0] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area0 = h265->qpmax_map[0] > 0 ? h265->qpmax_map[0] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area1 = h265->qpmin_map[1] > 0 ? h265->qpmin_map[1] : rc_cfg->quality_min; + reg_rc->roi_qthd0.qpmax_area1 = h265->qpmax_map[1] > 0 ? h265->qpmax_map[1] : rc_cfg->quality_max; + reg_rc->roi_qthd0.qpmin_area2 = h265->qpmin_map[2] > 0 ? h265->qpmin_map[2] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area2 = h265->qpmax_map[2] > 0 ? h265->qpmax_map[2] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area3 = h265->qpmin_map[3] > 0 ? h265->qpmin_map[3] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area3 = h265->qpmax_map[3] > 0 ? h265->qpmax_map[3] : rc_cfg->quality_max; + reg_rc->roi_qthd1.qpmin_area4 = h265->qpmin_map[4] > 0 ? h265->qpmin_map[4] : rc_cfg->quality_min; + reg_rc->roi_qthd1.qpmax_area4 = h265->qpmax_map[4] > 0 ? h265->qpmax_map[4] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area5 = h265->qpmin_map[5] > 0 ? h265->qpmin_map[5] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area5 = h265->qpmax_map[5] > 0 ? h265->qpmax_map[5] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area6 = h265->qpmin_map[6] > 0 ? h265->qpmin_map[6] : rc_cfg->quality_min; + reg_rc->roi_qthd2.qpmax_area6 = h265->qpmax_map[6] > 0 ? h265->qpmax_map[6] : rc_cfg->quality_max; + reg_rc->roi_qthd2.qpmin_area7 = h265->qpmin_map[7] > 0 ? h265->qpmin_map[7] : rc_cfg->quality_min; + reg_rc->roi_qthd3.qpmax_area7 = h265->qpmax_map[7] > 0 ? h265->qpmax_map[7] : rc_cfg->quality_max; + reg_rc->roi_qthd3.qpmap_mode = h265->qpmap_mode; + + return MPP_OK; +} + +static MPP_RET vepu580_h265_set_pp_regs(H265eV580RegSet *regs, VepuFmtCfg *fmt, + MppEncPrepCfg *prep_cfg, HalEncTask *task) +{ + hevc_vepu580_control_cfg *reg_ctl = ®s->reg_ctl; + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_S32 stridey = 0; + RK_S32 stridec = 0; + + reg_ctl->reg0012_dtrns_map.src_bus_edin = fmt->src_endian; + reg_base->reg0198_src_fmt.src_cfmt = fmt->format; + reg_base->reg0198_src_fmt.alpha_swap = fmt->alpha_swap; + reg_base->reg0198_src_fmt.rbuv_swap = fmt->rbuv_swap; + reg_base->reg0198_src_fmt.out_fmt = (fmt->format == VEPU5xx_FMT_YUV400) ? 0 : 1; + reg_base->reg0203_src_proc.src_mirr = prep_cfg->mirroring > 0; + reg_base->reg0203_src_proc.src_rot = prep_cfg->rotation; + + if (MPP_FRAME_FMT_IS_YUV(prep_cfg->format)) + reg_base->reg0198_src_fmt.src_range = 1; + else + reg_base->reg0198_src_fmt.src_range = (prep_cfg->range == MPP_FRAME_RANGE_JPEG) ? 1 : 0; + + if (MPP_FRAME_FMT_IS_FBC(prep_cfg->format)) { + stridey = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!stridey) + stridey = MPP_ALIGN(prep_cfg->width, 16); + } else if (prep_cfg->hor_stride) { + stridey = prep_cfg->hor_stride; + } else { + if (fmt->format == VEPU5xx_FMT_BGRA8888 ) + stridey = prep_cfg->width * 4; + else if (fmt->format == VEPU5xx_FMT_BGR888 ) + stridey = prep_cfg->width * 3; + else if (fmt->format == VEPU5xx_FMT_BGR565 || + fmt->format == VEPU5xx_FMT_YUYV422 || + fmt->format == VEPU5xx_FMT_UYVY422) + stridey = prep_cfg->width * 2; + else + stridey = prep_cfg->width; + } + + switch (fmt->format) { + case VEPU5xx_FMT_YUV444SP : { + stridec = stridey * 2; + } break; + case VEPU5xx_FMT_YUV422SP : + case VEPU5xx_FMT_YUV420SP : + case VEPU5xx_FMT_YUV444P : { + stridec = stridey; + } break; + default : { + stridec = stridey / 2; + } break; + } + + if (reg_base->reg0198_src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + const VepuRgb2YuvCfg *cfg_coeffs = cfg_coeffs = get_rgb2yuv_cfg(prep_cfg->range, prep_cfg->color); + + hal_h265e_dbg_simple("input color range %d colorspace %d", prep_cfg->range, prep_cfg->color); + + reg_base->reg0199_src_udfy.csc_wgt_r2y = cfg_coeffs->_2y.r_coeff; + reg_base->reg0199_src_udfy.csc_wgt_g2y = cfg_coeffs->_2y.g_coeff; + reg_base->reg0199_src_udfy.csc_wgt_b2y = cfg_coeffs->_2y.b_coeff; + + reg_base->reg0200_src_udfu.csc_wgt_r2u = cfg_coeffs->_2u.r_coeff; + reg_base->reg0200_src_udfu.csc_wgt_g2u = cfg_coeffs->_2u.g_coeff; + reg_base->reg0200_src_udfu.csc_wgt_b2u = cfg_coeffs->_2u.b_coeff; + + reg_base->reg0201_src_udfv.csc_wgt_r2v = cfg_coeffs->_2v.r_coeff; + reg_base->reg0201_src_udfv.csc_wgt_g2v = cfg_coeffs->_2v.g_coeff; + reg_base->reg0201_src_udfv.csc_wgt_b2v = cfg_coeffs->_2v.b_coeff; + + reg_base->reg0202_src_udfo.csc_ofst_y = cfg_coeffs->_2y.offset; + reg_base->reg0202_src_udfo.csc_ofst_u = cfg_coeffs->_2u.offset; + reg_base->reg0202_src_udfo.csc_ofst_v = cfg_coeffs->_2v.offset; + + hal_h265e_dbg_simple("use color range %d colorspace %d", cfg_coeffs->dst_range, cfg_coeffs->color); + } + + reg_base->reg0205_src_strd0.src_strd0 = stridey; + reg_base->reg0206_src_strd1.src_strd1 = stridec; + + return MPP_OK; +} + +static void vepu580_h265_set_slice_regs(H265eSyntax_new *syn, hevc_vepu580_base *regs) +{ + regs->reg0237_synt_sps.smpl_adpt_ofst_e = syn->pp.sample_adaptive_offset_enabled_flag;//slice->m_sps->m_bUseSAO; + regs->reg0237_synt_sps.num_st_ref_pic = syn->pp.num_short_term_ref_pic_sets; + regs->reg0237_synt_sps.num_lt_ref_pic = syn->pp.num_long_term_ref_pics_sps; + regs->reg0237_synt_sps.lt_ref_pic_prsnt = syn->pp.long_term_ref_pics_present_flag; + regs->reg0237_synt_sps.tmpl_mvp_e = syn->pp.sps_temporal_mvp_enabled_flag; + regs->reg0237_synt_sps.log2_max_poc_lsb = syn->pp.log2_max_pic_order_cnt_lsb_minus4; + regs->reg0237_synt_sps.strg_intra_smth = syn->pp.strong_intra_smoothing_enabled_flag; + + regs->reg0238_synt_pps.dpdnt_sli_seg_en = syn->pp.dependent_slice_segments_enabled_flag; + regs->reg0238_synt_pps.out_flg_prsnt_flg = syn->pp.output_flag_present_flag; + regs->reg0238_synt_pps.num_extr_sli_hdr = syn->pp.num_extra_slice_header_bits; + regs->reg0238_synt_pps.sgn_dat_hid_en = syn->pp.sign_data_hiding_enabled_flag; + regs->reg0238_synt_pps.cbc_init_prsnt_flg = syn->pp.cabac_init_present_flag; + regs->reg0238_synt_pps.pic_init_qp = syn->pp.init_qp_minus26 + 26; + regs->reg0238_synt_pps.cu_qp_dlt_en = syn->pp.cu_qp_delta_enabled_flag; + regs->reg0238_synt_pps.chrm_qp_ofst_prsn = syn->pp.pps_slice_chroma_qp_offsets_present_flag; + regs->reg0238_synt_pps.lp_fltr_acrs_sli = syn->pp.pps_loop_filter_across_slices_enabled_flag; + regs->reg0238_synt_pps.dblk_fltr_ovrd_en = syn->pp.deblocking_filter_override_enabled_flag; + regs->reg0238_synt_pps.lst_mdfy_prsnt_flg = syn->pp.lists_modification_present_flag; + regs->reg0238_synt_pps.sli_seg_hdr_extn = syn->pp.slice_segment_header_extension_present_flag; + regs->reg0238_synt_pps.cu_qp_dlt_depth = syn->pp.diff_cu_qp_delta_depth; + regs->reg0238_synt_pps.lpf_fltr_acrs_til = syn->pp.loop_filter_across_tiles_enabled_flag; + + regs->reg0239_synt_sli0.cbc_init_flg = syn->sp.cbc_init_flg; + regs->reg0239_synt_sli0.mvd_l1_zero_flg = syn->sp.mvd_l1_zero_flg; + regs->reg0239_synt_sli0.mrg_up_flg = syn->sp.merge_up_flag; + regs->reg0239_synt_sli0.mrg_lft_flg = syn->sp.merge_left_flag; + regs->reg0239_synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + regs->reg0239_synt_sli0.num_refidx_l1_act = syn->sp.num_refidx_l1_act; + regs->reg0239_synt_sli0.num_refidx_l0_act = syn->sp.num_refidx_l0_act; + + regs->reg0239_synt_sli0.num_refidx_act_ovrd = syn->sp.num_refidx_act_ovrd; + + regs->reg0239_synt_sli0.sli_sao_chrm_flg = syn->sp.sli_sao_chrm_flg; + regs->reg0239_synt_sli0.sli_sao_luma_flg = syn->sp.sli_sao_luma_flg; + regs->reg0239_synt_sli0.sli_tmprl_mvp_e = syn->sp.sli_tmprl_mvp_en; + regs->reg0192_enc_pic.num_pic_tot_cur = syn->sp.tot_poc_num; + + regs->reg0239_synt_sli0.pic_out_flg = syn->sp.pic_out_flg; + regs->reg0239_synt_sli0.sli_type = syn->sp.slice_type; + regs->reg0239_synt_sli0.sli_rsrv_flg = syn->sp.slice_rsrv_flg; + regs->reg0239_synt_sli0.dpdnt_sli_seg_flg = syn->sp.dpdnt_sli_seg_flg; + regs->reg0239_synt_sli0.sli_pps_id = syn->sp.sli_pps_id; + regs->reg0239_synt_sli0.no_out_pri_pic = syn->sp.no_out_pri_pic; + + + regs->reg0240_synt_sli1.sp_tc_ofst_div2 = syn->sp.sli_tc_ofst_div2; + regs->reg0240_synt_sli1.sp_beta_ofst_div2 = syn->sp.sli_beta_ofst_div2; + regs->reg0240_synt_sli1.sli_lp_fltr_acrs_sli = syn->sp.sli_lp_fltr_acrs_sli; + regs->reg0240_synt_sli1.sp_dblk_fltr_dis = syn->sp.sli_dblk_fltr_dis; + regs->reg0240_synt_sli1.dblk_fltr_ovrd_flg = syn->sp.dblk_fltr_ovrd_flg; + regs->reg0240_synt_sli1.sli_cb_qp_ofst = (syn->pp.pps_slice_chroma_qp_offsets_present_flag != 0) ? + syn->sp.sli_cb_qp_ofst : syn->pp.pps_cb_qp_offset; + regs->reg0240_synt_sli1.max_mrg_cnd = syn->sp.max_mrg_cnd; + + regs->reg0240_synt_sli1.col_ref_idx = syn->sp.col_ref_idx; + regs->reg0240_synt_sli1.col_frm_l0_flg = syn->sp.col_frm_l0_flg; + regs->reg0241_synt_sli2.sli_poc_lsb = syn->sp.sli_poc_lsb; + regs->reg0241_synt_sli2.sli_hdr_ext_len = syn->sp.sli_hdr_ext_len; + +} + +static void vepu580_h265_set_ref_regs(H265eSyntax_new *syn, hevc_vepu580_base *regs) +{ + regs->reg0242_synt_refm0.st_ref_pic_flg = syn->sp.st_ref_pic_flg; + regs->reg0242_synt_refm0.poc_lsb_lt0 = syn->sp.poc_lsb_lt0; + regs->reg0242_synt_refm0.num_lt_pic = syn->sp.num_lt_pic; + + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->reg0243_synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->reg0243_synt_refm1.used_by_lt_flg0 = syn->sp.used_by_lt_flg0; + regs->reg0243_synt_refm1.used_by_lt_flg1 = syn->sp.used_by_lt_flg1; + regs->reg0243_synt_refm1.used_by_lt_flg2 = syn->sp.used_by_lt_flg2; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt0 = syn->sp.dlt_poc_msb_prsnt0; + regs->reg0243_synt_refm1.dlt_poc_msb_cycl0 = syn->sp.dlt_poc_msb_cycl0; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt1 = syn->sp.dlt_poc_msb_prsnt1; + regs->reg0243_synt_refm1.num_negative_pics = syn->sp.num_neg_pic; + regs->reg0243_synt_refm1.num_pos_pic = syn->sp.num_pos_pic; + + regs->reg0243_synt_refm1.used_by_s0_flg = syn->sp.used_by_s0_flg; + regs->reg0244_synt_refm2.dlt_poc_s0_m10 = syn->sp.dlt_poc_s0_m10; + regs->reg0244_synt_refm2.dlt_poc_s0_m11 = syn->sp.dlt_poc_s0_m11; + regs->reg0245_synt_refm3.dlt_poc_s0_m12 = syn->sp.dlt_poc_s0_m12; + regs->reg0245_synt_refm3.dlt_poc_s0_m13 = syn->sp.dlt_poc_s0_m13; + + regs->reg0246_synt_long_refm0.poc_lsb_lt1 = syn->sp.poc_lsb_lt1; + regs->reg0247_synt_long_refm1.dlt_poc_msb_cycl1 = syn->sp.dlt_poc_msb_cycl1; + regs->reg0246_synt_long_refm0.poc_lsb_lt2 = syn->sp.poc_lsb_lt2; + regs->reg0243_synt_refm1.dlt_poc_msb_prsnt2 = syn->sp.dlt_poc_msb_prsnt2; + regs->reg0247_synt_long_refm1.dlt_poc_msb_cycl2 = syn->sp.dlt_poc_msb_cycl2; + regs->reg0240_synt_sli1.lst_entry_l0 = syn->sp.lst_entry_l0; + regs->reg0239_synt_sli0.ref_pic_lst_mdf_l0 = syn->sp.ref_pic_lst_mdf_l0; + + return; +} + +static MPP_RET hal_h265e_v580_send_regs(MppDev dev, H265eV580RegSet *hw_regs, H265eV580StatusElem *reg_out) +{ + RK_U32 *regs = (RK_U32*)hw_regs; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + MPP_RET ret = MPP_OK; + RK_U32 i; + + cfg.reg = (RK_U32*)&hw_regs->reg_ctl; + cfg.size = sizeof(hevc_vepu580_control_cfg); + cfg.offset = VEPU580_CTL_OFFSET; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto FAILE; + } + + if (hal_h265e_debug & HAL_H265E_DBG_CTL_REGS) { + regs = (RK_U32*)&hw_regs->reg_ctl; + for (i = 0; i < sizeof(hevc_vepu580_control_cfg) / 4; i++) { + hal_h265e_dbg_ctl("ctl reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_base; + cfg.size = sizeof(hevc_vepu580_base); + cfg.offset = VEPU580_BASE_OFFSET; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto FAILE; + } + + if (hal_h265e_debug & HAL_H265E_DBG_REGS) { + regs = (RK_U32*)(&hw_regs->reg_base); + for (i = 0; i < 32; i++) { + hal_h265e_dbg_regs("hw add cfg reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + regs += 32; + for (i = 0; i < (sizeof(hevc_vepu580_base) - 128) / 4; i++) { + hal_h265e_dbg_regs("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_rc_klut; + cfg.size = sizeof(hevc_vepu580_rc_klut); + cfg.offset = VEPU580_RCKULT_OFFSET; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &cfg); + + if (hal_h265e_debug & HAL_H265E_DBG_RCKUT_REGS) { + regs = (RK_U32*)&hw_regs->reg_rc_klut; + for (i = 0; i < sizeof(hevc_vepu580_rc_klut) / 4; i++) { + hal_h265e_dbg_rckut("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + if (ret) { + mpp_err_f("set rc kult write failed %d\n", ret); + goto FAILE; + } + + cfg.reg = &hw_regs->reg_wgt; + cfg.size = sizeof(hevc_vepu580_wgt); + cfg.offset = VEPU580_WEG_OFFSET; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto FAILE; + } + + if (hal_h265e_debug & HAL_H265E_DBG_WGT_REGS) { + regs = (RK_U32*)&hw_regs->reg_wgt; + for (i = 0; i < sizeof(hevc_vepu580_wgt) / 4; i++) { + hal_h265e_dbg_wgt("set reg[%04x]: 0%08x\n", i * 4, regs[i]); + } + } + + cfg.reg = &hw_regs->reg_rdo; + cfg.size = sizeof(vepu580_rdo_cfg); + cfg.offset = VEPU580_RDOCFG_OFFSET; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto FAILE; + } + + cfg.reg = &hw_regs->reg_osd_cfg; + cfg.size = sizeof(vepu580_osd_cfg); + cfg.offset = VEPU580_OSD_OFFSET; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto FAILE; + } + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU580_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + goto FAILE; + } + + cfg1.reg = ®_out->st; + cfg1.size = sizeof(H265eV580StatusElem) - 4; + cfg1.offset = VEPU580_STATUS_OFFSET; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + goto FAILE; + } +FAILE: + return ret; +} + +static MPP_RET setup_vepu580_dual_core(H265eV580HalContext *ctx, RK_S32 curr_slot, RK_S32 refr_slot) +{ + Vepu580H265eFrmCfg *frm = ctx->frm; + H265eV580RegSet *regs = frm->regs_set[0]; + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_U32 dchs_ofst = 9; + RK_U32 dchs_rxe = 1; + RK_U32 dchs_txe = 1; + RK_U32 rxid = 0; + + if (curr_slot < 0 || curr_slot >= MAX_REFS || refr_slot < 0 || refr_slot >= MAX_REFS) { + mpp_loge_f("dual core setup failed! invalid frame slot index. curr_slot:%d, refr_slot:%d", + curr_slot, refr_slot); + return MPP_ERR_UNKNOW; + } + + if (frm->frame_type == INTRA_FRAME) { + ctx->curr_idx = 0; + ctx->prev_idx = 0; + dchs_rxe = 0; + rxid = 0; + } else { + rxid = ctx->slot_to_dchs_txid[refr_slot]; + } + + if (!reg_base->reg0192_enc_pic.cur_frm_ref) + dchs_txe = 0; + + ctx->slot_to_dchs_txid[curr_slot] = ctx->curr_idx; + + reg_base->reg0193_dual_core.dchs_txid = ctx->curr_idx; + reg_base->reg0193_dual_core.dchs_rxid = rxid; + reg_base->reg0193_dual_core.dchs_txe = dchs_txe; + reg_base->reg0193_dual_core.dchs_rxe = dchs_rxe; + reg_base->reg0193_dual_core.dchs_ofst = dchs_ofst; + + ctx->prev_idx = ctx->curr_idx++; + if (ctx->curr_idx > 3) + ctx->curr_idx = 0; + + return MPP_OK; +} + +static void vepu580_h265_set_me_regs(H265eV580HalContext *ctx, H265eSyntax_new *syn, hevc_vepu580_base *regs) +{ + + RK_U32 cime_w = 11, cime_h = 7; + RK_S32 merangx = (cime_w + 1) * 32; + RK_S32 merangy = (cime_h + 1) * 32; + RK_S32 pic_wd64 = MPP_ALIGN(syn->pp.pic_width, 64) >> 6; + + if (merangx > 384) { + merangx = 384; + } + if (merangy > 320) { + merangy = 320; + } + + if (syn->pp.pic_width < merangx + 60 || syn->pp.pic_width <= 352) { + if (merangx > syn->pp.pic_width ) { + merangx = syn->pp.pic_width; + } + merangx = merangx / 4 * 2; + } + + if (syn->pp.pic_height < merangy + 60 || syn->pp.pic_height <= 288) { + if (merangy > syn->pp.pic_height) { + merangy = syn->pp.pic_height; + } + merangy = merangy / 4 * 2; + } + + { + RK_S32 merange_x = merangx / 2; + RK_S32 merange_y = merangy / 2; + RK_S32 mxneg = ((-(merange_x << 2)) >> 2) / 4; + RK_S32 myneg = ((-(merange_y << 2)) >> 2) / 4; + RK_S32 mxpos = (((merange_x << 2) - 4) >> 2) / 4; + RK_S32 mypos = (((merange_y << 2) - 4) >> 2) / 4; + + mxneg = MPP_MIN(abs(mxneg), mxpos) * 4; + myneg = MPP_MIN(abs(myneg), mypos) * 4; + + merangx = mxneg * 2; + merangy = myneg * 2; + } + regs->reg0220_me_rnge.cme_srch_h = merangx / 32; + regs->reg0220_me_rnge.cme_srch_v = merangy / 32; + + regs->reg0220_me_rnge.rme_srch_h = 7; + regs->reg0220_me_rnge.rme_srch_v = 5; + regs->reg0220_me_rnge.dlt_frm_num = 0x1; + + regs->reg0221_me_cfg.pmv_mdst_h = 5; + regs->reg0221_me_cfg.pmv_mdst_v = 5; + regs->reg0221_me_cfg.mv_limit = 0; + regs->reg0221_me_cfg.pmv_num = 2; + + //regs->reg0221_me_cfg.rme_dis = 0; + // regs->reg0221_me_cfg.rme_dis = 2; + + + + if (syn->pp.sps_temporal_mvp_enabled_flag && + (ctx->frame_type != INTRA_FRAME)) { + if (ctx->last_frame_type == INTRA_FRAME) { + regs->reg0221_me_cfg.colmv_load = 0; + } else { + regs->reg0221_me_cfg.colmv_load = 1; + } + regs->reg0221_me_cfg.colmv_stor = 1; + } + + if (syn->pp.pic_width > 2688) { + regs->reg0222_me_cach.cme_rama_h = 12; + } else if (syn->pp.pic_width > 2048) { + regs->reg0222_me_cach.cme_rama_h = 16; + } else { + regs->reg0222_me_cach.cme_rama_h = 20; + } + + { + RK_S32 swin_scope_wd16 = (regs->reg0220_me_rnge.cme_srch_h + 3 + 1) / 4 * 2 + 1; + RK_S32 tmpMin = (regs->reg0220_me_rnge.cme_srch_v + 3) / 4 * 2 + 1; + if (regs->reg0222_me_cach.cme_rama_h / 4 < tmpMin) { + tmpMin = regs->reg0222_me_cach.cme_rama_h / 4; + } + regs->reg0222_me_cach.cme_rama_max = + (pic_wd64 * (tmpMin - 1)) + ((pic_wd64 >= swin_scope_wd16) ? swin_scope_wd16 : pic_wd64 * 2); + } + regs->reg0222_me_cach.cach_l2_tag = 0x0; + + pic_wd64 = pic_wd64 << 6; + + if (pic_wd64 <= 512) + regs->reg0222_me_cach.cach_l2_tag = 0x0; + else if (pic_wd64 <= 1024) + regs->reg0222_me_cach.cach_l2_tag = 0x1; + else if (pic_wd64 <= 2048) + regs->reg0222_me_cach.cach_l2_tag = 0x2; + else if (pic_wd64 <= 4096) + regs->reg0222_me_cach.cach_l2_tag = 0x3; + +} + +static MppBuffer vepu580_h265_get_md_info_buf(H265eV580HalContext *ctx) +{ + RK_S32 w = ctx->cfg->prep.width; + RK_S32 h = ctx->cfg->prep.height; + RK_S32 buf_size = (MPP_ALIGN(w, 64) >> 6) * (MPP_ALIGN(h, 64) >> 6) * 32; + + /* prepare md info internal buffer when deblur is enabled */ + if (ctx->cfg->tune.deblur_en && (buf_size > ctx->md_info_buf_size)) { + if (ctx->md_info_buf) { + mpp_buffer_put(ctx->md_info_buf); + ctx->md_info_buf = NULL; + } + + if (!ctx->qpmap_grp) + mpp_buffer_group_get_internal(&ctx->qpmap_grp, MPP_BUFFER_TYPE_ION); + + mpp_buffer_get(ctx->qpmap_grp, &ctx->md_info_buf, buf_size); + if (!ctx->md_info_buf) + mpp_err_f("failed to get md info buffer\n"); + else { + hal_h265e_dbg_flow("get md info internal buffer %p size %d %d\n", + ctx->md_info_buf, buf_size, ctx->md_info_buf_size); + ctx->md_info_buf_size = buf_size; + } + } + + return ctx->md_info_buf; +} + +void vepu580_h265_set_hw_address(H265eV580HalContext *ctx, HalEncTask *task) +{ + Vepu580H265eFrmCfg *frm = ctx->frm; + hevc_vepu580_base *regs = &frm->regs_set[0]->reg_base; + HalEncTask *enc_task = task; + HalBuf *recon_buf, *ref_buf; + H265eSyntax_new *syn = ctx->syn; + + hal_h265e_enter(); + + regs->reg0160_adr_src0 = mpp_buffer_get_fd(enc_task->input); + regs->reg0161_adr_src1 = regs->reg0160_adr_src0; + regs->reg0162_adr_src2 = regs->reg0160_adr_src0; + + recon_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_curr_idx); + ref_buf = hal_bufs_get_buf(ctx->dpb_bufs, frm->hal_refr_idx); + + if (!syn->sp.non_reference_flag) { + regs->reg0163_rfpw_h_addr = mpp_buffer_get_fd(recon_buf->buf[0]); + regs->reg0164_rfpw_b_addr = regs->reg0163_rfpw_h_addr; + + mpp_dev_multi_offset_update(frm->reg_cfg, 164, ctx->fbc_header_len); + } + regs->reg0165_rfpr_h_addr = mpp_buffer_get_fd(ref_buf->buf[0]); + regs->reg0166_rfpr_b_addr = regs->reg0165_rfpr_h_addr; + regs->reg0167_cmvw_addr = mpp_buffer_get_fd(recon_buf->buf[2]); + regs->reg0168_cmvr_addr = mpp_buffer_get_fd(ref_buf->buf[2]); + regs->reg0169_dspw_addr = mpp_buffer_get_fd(recon_buf->buf[1]); + regs->reg0170_dspr_addr = mpp_buffer_get_fd(ref_buf->buf[1]); + + mpp_dev_multi_offset_update(frm->reg_cfg, 166, ctx->fbc_header_len); + + if (syn->pp.tiles_enabled_flag) { + RK_U32 tile_num = (syn->pp.num_tile_columns_minus1 + 1) * (syn->pp.num_tile_rows_minus1 + 1); + RK_U32 i = 0; + RK_U32 max_tile_buf_size = MPP_ALIGN(((MPP_ALIGN(syn->pp.pic_height, 64) + 64) << 5), 256); + + if (NULL == ctx->tile_grp) + mpp_buffer_group_get_internal(&ctx->tile_grp, MPP_BUFFER_TYPE_ION); + + mpp_assert(ctx->tile_grp); + + for (i = 0; i < MAX_TILE_NUM; i++) { + if (NULL == frm->hw_tile_buf[i]) { + mpp_buffer_get(ctx->tile_grp, &frm->hw_tile_buf[i], max_tile_buf_size); + } + } + + if (NULL == frm->hw_tile_stream[0]) { + mpp_buffer_get(ctx->tile_grp, &frm->hw_tile_stream[0], ctx->frame_size / tile_num); + } + + if (tile_num > 2) { + if (NULL == frm->hw_tile_stream[1]) { + mpp_buffer_get(ctx->tile_grp, &frm->hw_tile_stream[1], ctx->frame_size / tile_num); + } + if (NULL == frm->hw_tile_stream[2]) { + mpp_buffer_get(ctx->tile_grp, &frm->hw_tile_stream[2], ctx->frame_size / tile_num); + } + } + + regs->reg0176_lpfw_addr = mpp_buffer_get_fd(frm->hw_tile_buf[0]); + regs->reg0177_lpfr_addr = mpp_buffer_get_fd(frm->hw_tile_buf[1]); + } + + { + if (!enc_task->md_info) + enc_task->md_info = vepu580_h265_get_md_info_buf(ctx); + + if (enc_task->md_info) { + regs->reg0192_enc_pic.mei_stor = 1; + regs->reg0171_meiw_addr = mpp_buffer_get_fd(enc_task->md_info); + } else { + regs->reg0192_enc_pic.mei_stor = 0; + regs->reg0171_meiw_addr = 0; + } + } + + regs->reg0172_bsbt_addr = mpp_buffer_get_fd(enc_task->output); + /* TODO: stream size relative with syntax */ + regs->reg0173_bsbb_addr = regs->reg0172_bsbt_addr; + regs->reg0174_bsbr_addr = regs->reg0172_bsbt_addr; + regs->reg0175_adr_bsbs = regs->reg0172_bsbt_addr; + + mpp_dev_multi_offset_update(frm->reg_cfg, 175, mpp_packet_get_length(task->packet)); + mpp_dev_multi_offset_update(frm->reg_cfg, 172, mpp_buffer_get_size(enc_task->output)); + + regs->reg0204_pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->reg0204_pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); +} + +static MPP_RET vepu580_h265e_save_pass1_patch(H265eV580RegSet *regs, H265eV580HalContext *ctx, + RK_S32 tiles_enabled_flag) +{ + Vepu580H265eFrmCfg *frm = ctx->frm; + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_S32 width = ctx->cfg->prep.width; + RK_S32 height = ctx->cfg->prep.height; + RK_S32 width_align = MPP_ALIGN(width, 64); + RK_S32 height_align = MPP_ALIGN(height, 16); + + if (NULL == ctx->buf_pass1) { + mpp_buffer_get(NULL, &ctx->buf_pass1, width_align * height_align * 3 / 2); + if (!ctx->buf_pass1) { + mpp_err("buf_pass1 malloc fail, debreath invaild"); + return MPP_NOK; + } + } + + reg_base->reg0192_enc_pic.cur_frm_ref = 1; + reg_base->reg0163_rfpw_h_addr = mpp_buffer_get_fd(ctx->buf_pass1); + reg_base->reg0164_rfpw_b_addr = reg_base->reg0163_rfpw_h_addr; + reg_base->reg0192_enc_pic.rec_fbc_dis = 1; + + if (tiles_enabled_flag) + reg_base->reg0238_synt_pps.lpf_fltr_acrs_til = 0; + + mpp_dev_multi_offset_update(frm->reg_cfg, 164, width_align * height_align); + + /* NOTE: disable split to avoid lowdelay slice output */ + regs->reg_base.reg0216_sli_splt.sli_splt = 0; + regs->reg_base.reg0192_enc_pic.slen_fifo = 0; + + return MPP_OK; +} + +static MPP_RET vepu580_h265e_use_pass1_patch(H265eV580RegSet *regs, H265eV580HalContext *ctx) +{ + Vepu580H265eFrmCfg *frm = ctx->frm; + hevc_vepu580_control_cfg *reg_ctl = ®s->reg_ctl; + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_U32 hor_stride = MPP_ALIGN(ctx->cfg->prep.width, 64); + RK_U32 ver_stride = MPP_ALIGN(ctx->cfg->prep.height, 16); + RK_U32 frame_size = hor_stride * ver_stride; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + MPP_RET ret = MPP_OK; + + reg_ctl->reg0012_dtrns_map.src_bus_edin = fmt->src_endian; + reg_base->reg0198_src_fmt.src_cfmt = VEPU5xx_FMT_YUV420SP; + reg_base->reg0198_src_fmt.alpha_swap = 0; + reg_base->reg0198_src_fmt.rbuv_swap = 0; + reg_base->reg0198_src_fmt.out_fmt = 1; + reg_base->reg0203_src_proc.afbcd_en = 0; + reg_base->reg0205_src_strd0.src_strd0 = hor_stride; + reg_base->reg0206_src_strd1.src_strd1 = hor_stride; + reg_base->reg0203_src_proc.src_mirr = 0; + reg_base->reg0203_src_proc.src_rot = 0; + reg_base->reg0204_pic_ofst.pic_ofst_x = 0; + reg_base->reg0204_pic_ofst.pic_ofst_y = 0; + reg_base->reg0160_adr_src0 = mpp_buffer_get_fd(ctx->buf_pass1); + reg_base->reg0161_adr_src1 = reg_base->reg0160_adr_src0; + reg_base->reg0162_adr_src2 = reg_base->reg0160_adr_src0; + + /* input cb addr */ + ret = mpp_dev_multi_offset_update(frm->reg_cfg, 161, frame_size); + if (ret) + mpp_err_f("set input cb addr offset failed %d\n", ret); + + /* input cr addr */ + ret = mpp_dev_multi_offset_update(frm->reg_cfg, 162, frame_size); + if (ret) + mpp_err_f("set input cr addr offset failed %d\n", ret); + + return MPP_OK; +} + +static void vepu580_setup_split(H265eV580RegSet *regs, MppEncCfgSet *enc_cfg, RK_U32 title_en) +{ + MppEncSliceSplit *cfg = &enc_cfg->split; + + hal_h265e_dbg_func("enter\n"); + + switch (cfg->split_mode) { + case MPP_ENC_SPLIT_NONE : { + regs->reg_base.reg0216_sli_splt.sli_splt = 0; + regs->reg_base.reg0216_sli_splt.sli_splt_mode = 0; + regs->reg_base.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_base.reg0216_sli_splt.sli_max_num_m1 = 0; + regs->reg_base.reg0216_sli_splt.sli_flsh = 0; + regs->reg_base.reg0218_sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.reg0217_sli_byte.sli_splt_byte = 0; + regs->reg_base.reg0192_enc_pic.slen_fifo = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + regs->reg_base.reg0216_sli_splt.sli_splt = 1; + regs->reg_base.reg0216_sli_splt.sli_splt_mode = 0; + regs->reg_base.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_base.reg0216_sli_splt.sli_max_num_m1 = 500; + regs->reg_base.reg0216_sli_splt.sli_flsh = 1; + regs->reg_base.reg0218_sli_cnum.sli_splt_cnum_m1 = 0; + + regs->reg_base.reg0217_sli_byte.sli_splt_byte = cfg->split_arg; + regs->reg_base.reg0192_enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + regs->reg_ctl.reg0008_int_en.slc_done_en = regs->reg_base.reg0192_enc_pic.slen_fifo; + } break; + case MPP_ENC_SPLIT_BY_CTU : { + RK_U32 mb_w = MPP_ALIGN(enc_cfg->prep.width, 64) / 64; + RK_U32 mb_h = MPP_ALIGN(enc_cfg->prep.height, 64) / 64; + RK_U32 slice_num = 0; + + if (title_en) + mb_w = mb_w / 2; + + slice_num = (mb_w * mb_h + cfg->split_arg - 1) / cfg->split_arg; + + regs->reg_base.reg0216_sli_splt.sli_splt = 1; + regs->reg_base.reg0216_sli_splt.sli_splt_mode = 1; + regs->reg_base.reg0216_sli_splt.sli_splt_cpst = 0; + regs->reg_base.reg0216_sli_splt.sli_max_num_m1 = 500; + regs->reg_base.reg0216_sli_splt.sli_flsh = 1; + regs->reg_base.reg0218_sli_cnum.sli_splt_cnum_m1 = cfg->split_arg - 1; + + regs->reg_base.reg0217_sli_byte.sli_splt_byte = 0; + regs->reg_base.reg0192_enc_pic.slen_fifo = (cfg->split_out != 0) ? 1 : 0; + + if ((cfg->split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) || + (regs->reg_base.reg0192_enc_pic.slen_fifo && (slice_num > VEPU580_SLICE_FIFO_LEN))) + regs->reg_ctl.reg0008_int_en.slc_done_en = 1 ; + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", cfg->split_mode); + } break; + } + + hal_h265e_dbg_func("leave\n"); +} + +MPP_RET hal_h265e_v580_gen_regs(void *hal, HalEncTask *task) +{ + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + HalEncTask *enc_task = task; + EncRcTask *rc_task = enc_task->rc_task; + EncFrmStatus *frm = &rc_task->frm; + H265eSyntax_new *syn = ctx->syn; + Vepu580H265eFrmCfg *frm_cfg = ctx->frm; + H265eV580RegSet *regs = frm_cfg->regs_set[0]; + RK_U32 pic_width_align8, pic_height_align8; + RK_S32 pic_wd64, pic_h64; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + hevc_vepu580_control_cfg *reg_ctl = ®s->reg_ctl; + hevc_vepu580_base *reg_base = ®s->reg_base; + hevc_vepu580_rc_klut *reg_klut = ®s->reg_rc_klut; + MppEncCfgSet *cfg = ctx->cfg; + + hal_h265e_enter(); + pic_width_align8 = (syn->pp.pic_width + 7) & (~7); + pic_height_align8 = (syn->pp.pic_height + 7) & (~7); + pic_wd64 = (syn->pp.pic_width + 63) / 64; + pic_h64 = (syn->pp.pic_height + 63) / 64; + + hal_h265e_dbg_simple("frame %d | type %d | start gen regs", + frm_cfg->frame_count, ctx->frame_type); + + memset(regs, 0, sizeof(H265eV580RegSet)); + + if (ctx->task_cnt > 1) + setup_vepu580_dual_core(ctx, task->flags.curr_idx, task->flags.refr_idx); + + reg_ctl->reg0004_enc_strt.lkt_num = 0; + reg_ctl->reg0004_enc_strt.vepu_cmd = ctx->enc_mode; + reg_ctl->reg0005_enc_clr.safe_clr = 0x0; + reg_ctl->reg0005_enc_clr.force_clr = 0x0; + + reg_ctl->reg0008_int_en.enc_done_en = 1; + reg_ctl->reg0008_int_en.lkt_node_done_en = 1; + reg_ctl->reg0008_int_en.sclr_done_en = 1; + reg_ctl->reg0008_int_en.slc_done_en = 0; + reg_ctl->reg0008_int_en.bsf_oflw_en = 1; + reg_ctl->reg0008_int_en.brsp_otsd_en = 1; + reg_ctl->reg0008_int_en.wbus_err_en = 1; + reg_ctl->reg0008_int_en.rbus_err_en = 1; + reg_ctl->reg0008_int_en.wdg_en = 1; + reg_ctl->reg0008_int_en.lkt_err_int_en = 0; + + reg_ctl->reg0012_dtrns_map.lpfw_bus_ordr = 0x0; + reg_ctl->reg0012_dtrns_map.cmvw_bus_ordr = 0x0; + reg_ctl->reg0012_dtrns_map.dspw_bus_ordr = 0x0; + reg_ctl->reg0012_dtrns_map.rfpw_bus_ordr = 0x0; + reg_ctl->reg0012_dtrns_map.src_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.meiw_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.bsw_bus_edin = 0x7; + reg_ctl->reg0012_dtrns_map.lktr_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.roir_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.lktw_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.afbc_bsize = 0x1; + reg_ctl->reg0012_dtrns_map.ebufw_bus_ordr = 0x0; + + reg_ctl->reg0013_dtrns_cfg.dspr_otsd = (ctx->frame_type == INTER_P_FRAME); + reg_ctl->reg0013_dtrns_cfg.axi_brsp_cke = 0x0; + reg_ctl->reg0014_enc_wdg.vs_load_thd = 0x1fffff; + reg_ctl->reg0014_enc_wdg.rfp_load_thd = 0; + + reg_ctl->reg0021_func_en.cke = 1; + reg_ctl->reg0021_func_en.resetn_hw_en = 1; + reg_ctl->reg0021_func_en.enc_done_tmvp_en = 1; + + reg_base->reg0196_enc_rsl.pic_wd8_m1 = pic_width_align8 / 8 - 1; + reg_base->reg0197_src_fill.pic_wfill = ((syn->pp.pic_width & 0x7) != 0) + ? (8 - (syn->pp.pic_width & 0x7)) : 0; + reg_base->reg0196_enc_rsl.pic_hd8_m1 = pic_height_align8 / 8 - 1; + reg_base->reg0197_src_fill.pic_hfill = ((syn->pp.pic_height & 0x7) != 0) + ? (8 - (syn->pp.pic_height & 0x7)) : 0; + + reg_base->reg0192_enc_pic.enc_stnd = 1; //H265 + reg_base->reg0192_enc_pic.cur_frm_ref = !syn->sp.non_reference_flag; //current frame will be refered + reg_base->reg0192_enc_pic.bs_scp = 1; + reg_base->reg0192_enc_pic.log2_ctu_num = ceil(log2((double)pic_wd64 * pic_h64)); + + reg_base->reg0203_src_proc.src_mirr = 0; + reg_base->reg0203_src_proc.src_rot = 0; + reg_base->reg0203_src_proc.txa_en = 1; + reg_base->reg0203_src_proc.afbcd_en = (MPP_FRAME_FMT_IS_FBC(syn->pp.mpp_format) != 0) ? 1 : 0; + + reg_klut->klut_ofst.chrm_klut_ofst = (ctx->frame_type == INTRA_FRAME) ? 0 : 3; + memcpy(®_klut->klut_wgt0, &klut_weight[0], sizeof(klut_weight)); + + vepu580_h265_set_me_regs(ctx, syn, reg_base); + + reg_base->reg0232_rdo_cfg.chrm_spcl = 1; + reg_base->reg0232_rdo_cfg.cu_inter_e = 0x06db; + reg_base->reg0232_rdo_cfg.cu_intra_e = 0xf; + + if (syn->pp.num_long_term_ref_pics_sps) { + reg_base->reg0232_rdo_cfg.ltm_col = 0; + reg_base->reg0232_rdo_cfg.ltm_idx0l0 = 1; + } else { + reg_base->reg0232_rdo_cfg.ltm_col = 0; + reg_base->reg0232_rdo_cfg.ltm_idx0l0 = 0; + } + + reg_base->reg0232_rdo_cfg.ccwa_e = 1; + reg_base->reg0232_rdo_cfg.scl_lst_sel = syn->pp.scaling_list_enabled_flag; + reg_base->reg0236_synt_nal.nal_unit_type = h265e_get_nal_type(&syn->sp, ctx->frame_type); + + vepu580_h265_set_hw_address(ctx, task); + vepu580_h265_set_pp_regs(regs, fmt, &ctx->cfg->prep, task); + vepu580_h265_set_rc_regs(ctx, regs, task); + vepu580_h265_set_slice_regs(syn, reg_base); + vepu580_h265_set_ref_regs(syn, reg_base); + + vepu580_set_osd(&ctx->frm->osd_cfg); + /* ROI configure */ + vepu580_h265_set_roi_regs(ctx, reg_base); + if (frm->is_i_refresh) + setup_intra_refresh(ctx, frm->seq_idx % ctx->cfg->rc.gop); + + if (cfg->tune.deblur_en && (!rc_task->info.complex_scene) && + cfg->rc.rc_mode == MPP_ENC_RC_MODE_SMTRC && task->md_info && + cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC) { + if (MPP_OK != vepu580_setup_qpmap_buf(ctx)) + mpp_err("qpmap malloc buffer failed!\n"); + } + + /*paramet cfg*/ + vepu580_h265_global_cfg_set(ctx, regs); + + vepu580_h265e_tune_reg_patch(ctx->tune); + + vepu580_setup_split(regs, cfg, syn->pp.tiles_enabled_flag); + + hal_h265e_leave(); + return MPP_OK; +} + +void hal_h265e_v580_set_uniform_tile(hevc_vepu580_base *regs, H265eSyntax_new *syn, + RK_U32 index, RK_S32 tile_start_x) +{ + if (syn->pp.tiles_enabled_flag) { + RK_S32 mb_h = MPP_ALIGN(syn->pp.pic_height, 64) / 64; + RK_S32 tile_width = syn->pp.column_width_minus1[index] + 1; + + if (!regs->reg0192_enc_pic.cur_frm_ref && + !(regs->reg0238_synt_pps.lpf_fltr_acrs_til && + regs->reg0238_synt_pps.lp_fltr_acrs_sli && + regs->reg0240_synt_sli1.sli_lp_fltr_acrs_sli && + regs->reg0237_synt_sps.smpl_adpt_ofst_e && + (regs->reg0239_synt_sli0.sli_sao_luma_flg || + (regs->reg0239_synt_sli0.sli_sao_chrm_flg && regs->reg0198_src_fmt.out_fmt)))) { + regs->reg0193_dual_core.dchs_txe = 0; + regs->reg0193_dual_core.dchs_rxe = 0; + } else if (index > 0) { + regs->reg0193_dual_core.dchs_txid = index; + regs->reg0193_dual_core.dchs_rxid = index - 1; + regs->reg0193_dual_core.dchs_txe = 1; + regs->reg0193_dual_core.dchs_rxe = 1; + } else { + regs->reg0193_dual_core.dchs_txid = index; + regs->reg0193_dual_core.dchs_rxid = 0; + regs->reg0193_dual_core.dchs_txe = 1; + regs->reg0193_dual_core.dchs_rxe = 0; + } + /* dual core runtime offset should set to 2 to avoid data access conflict */ + regs->reg0193_dual_core.dchs_ofst = 2; + + if (index == syn->pp.num_tile_columns_minus1) { + regs->reg0193_dual_core.dchs_txid = 0; + regs->reg0193_dual_core.dchs_txe = 0; + } + regs->reg0252_tile_cfg.tile_w_m1 = tile_width - 1; + regs->reg0252_tile_cfg.tile_h_m1 = mb_h - 1; + regs->reg212_rc_cfg.rc_ctu_num = tile_width; + regs->reg0252_tile_cfg.tile_en = syn->pp.tiles_enabled_flag; + regs->reg0253_tile_pos.tile_x = tile_start_x; + regs->reg0253_tile_pos.tile_y = 0; + + hal_h265e_dbg_detail("tile_x %d, rc_ctu_num %d, tile_width_m1 %d", + regs->reg0253_tile_pos.tile_x, regs->reg212_rc_cfg.rc_ctu_num, + regs->reg0252_tile_cfg.tile_w_m1); + } +} + +MPP_RET hal_h265e_v580_start(void *hal, HalEncTask *enc_task) +{ + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + H265eSyntax_new *syn = ctx->syn; + RK_U32 tile_num = (syn->pp.num_tile_columns_minus1 + 1) * (syn->pp.num_tile_rows_minus1 + 1); + RK_U32 stream_len = 0; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + Vepu580H265eFrmCfg *frm = ctx->frm; + RK_U32 k = 0; + MPP_RET ret = MPP_OK; + RK_S32 tile_start_x = 0; + + hal_h265e_enter(); + + ctx->tile_num = tile_num; + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + if (tile_num > MAX_TILE_NUM) { + mpp_log("tile_num big then support %d, max %d", tile_num, MAX_TILE_NUM); + return MPP_NOK; + } + + for (k = 0; k < tile_num; k++) { + H265eV580RegSet *hw_regs = frm->regs_set[k]; + hevc_vepu580_base *reg_base = NULL; + H265eV580StatusElem *reg_out = frm->regs_ret[k]; + + if (!hw_regs) { + hw_regs = mpp_malloc(H265eV580RegSet, 1); + frm->regs_set[k] = hw_regs; + } + if (!reg_out) { + reg_out = mpp_malloc(H265eV580StatusElem, 1); + frm->regs_ret[k] = reg_out; + } + + reg_base = &hw_regs->reg_base; + + if (k) + memcpy(hw_regs, frm->regs_set[0], sizeof(*hw_regs)); + + vepu580_h265_set_me_ram(syn, reg_base, k, tile_start_x); + + /* set input info */ + vepu580_h265_set_patch_info(frm->reg_cfg, syn, (VepuFmt)fmt->format, enc_task); + if (tile_num > 1) + hal_h265e_v580_set_uniform_tile(reg_base, syn, k, tile_start_x); + + if (k) { + RK_U32 offset = 0; + + reg_base->reg0176_lpfw_addr = mpp_buffer_get_fd(frm->hw_tile_buf[k]); + reg_base->reg0177_lpfr_addr = mpp_buffer_get_fd(frm->hw_tile_buf[k - 1]); + + if (!ctx->tile_parall_en) { + offset = mpp_packet_get_length(enc_task->packet); + offset += stream_len; + + reg_base->reg0173_bsbb_addr = mpp_buffer_get_fd(enc_task->output); + + mpp_dev_multi_offset_update(frm->reg_cfg, 175, offset); + mpp_dev_multi_offset_update(frm->reg_cfg, 172, mpp_buffer_get_size(enc_task->output)); + } else { + reg_base->reg0172_bsbt_addr = mpp_buffer_get_fd(frm->hw_tile_stream[k - 1]); + /* TODO: stream size relative with syntax */ + reg_base->reg0173_bsbb_addr = reg_base->reg0172_bsbt_addr; + reg_base->reg0174_bsbr_addr = reg_base->reg0172_bsbt_addr; + reg_base->reg0175_adr_bsbs = reg_base->reg0172_bsbt_addr; + + mpp_dev_multi_offset_update(frm->reg_cfg, 175, 0); + mpp_dev_multi_offset_update(frm->reg_cfg, 172, mpp_buffer_get_size(frm->hw_tile_stream[k - 1])); + } + + offset = ctx->fbc_header_len; + + mpp_dev_multi_offset_update(frm->reg_cfg, 166, offset); + mpp_dev_multi_offset_update(frm->reg_cfg, 164, offset); + } + + if (enc_task->rc_task->frm.save_pass1) + vepu580_h265e_save_pass1_patch(hw_regs, ctx, syn->pp.tiles_enabled_flag); + + if (enc_task->rc_task->frm.use_pass1) + vepu580_h265e_use_pass1_patch(hw_regs, ctx); + + hal_h265e_v580_send_regs(ctx->dev, hw_regs, reg_out); + + mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, frm->reg_cfg); + + if (k < tile_num - 1) { + if (!ctx->tile_parall_en) { + Vepu580H265Fbk *fb = &frm->feedback; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } + stream_len += reg_out->st.bs_lgth_l32; + fb->qp_sum += reg_out->st.qp_sum; + fb->out_strm_size += reg_out->st.bs_lgth_l32; + fb->sse_sum += (RK_S64)(reg_out->st.sse_h32 << 16) + + (reg_out->st.st_sse_bsl.sse_l16 & 0xffff); + fb->st_madi += reg_out->st.madi; + fb->st_madp += reg_out->st.madp; + fb->st_mb_num += reg_out->st.st_bnum_b16.num_b16; + fb->st_ctu_num += reg_out->st.st_bnum_cme.num_ctu; + } else + mpp_dev_ioctl(ctx->dev, MPP_DEV_DELIMIT, NULL); + } + tile_start_x += (syn->pp.column_width_minus1[k] + 1); + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + hal_h265e_leave(); + return ret; +} + +static MPP_RET vepu580_h265_set_feedback(H265eV580HalContext *ctx, HalEncTask *enc_task, RK_U32 index) +{ + EncRcTaskInfo *hal_rc_ret = (EncRcTaskInfo *)&enc_task->rc_task->info; + Vepu580H265eFrmCfg *frm = ctx->frms[enc_task->flags.reg_idx]; + Vepu580H265Fbk *fb = &frm->feedback; + MppEncCfgSet *cfg = ctx->cfg; + RK_S32 mb64_num = ((cfg->prep.width + 63) / 64) * ((cfg->prep.height + 63) / 64); + RK_S32 mb8_num = (mb64_num << 6); + RK_S32 mb4_num = (mb8_num << 2); + + hal_h265e_enter(); + H265eV580StatusElem *elem = frm->regs_ret[index]; + RK_U32 hw_status = elem->hw_status; + + fb->qp_sum += elem->st.qp_sum; + + fb->out_strm_size += elem->st.bs_lgth_l32; + + fb->sse_sum += (RK_S64)(elem->st.sse_h32 << 16) + + (elem->st.st_sse_bsl.sse_l16 & 0xffff); + + fb->hw_status = hw_status; + hal_h265e_dbg_detail("hw_status: 0x%08x", hw_status); + if (hw_status & RKV_ENC_INT_LINKTABLE_FINISH) + hal_h265e_err("RKV_ENC_INT_LINKTABLE_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_FRAME_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_FRAME_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_SLICE_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_SLICE_FINISH"); + + if (hw_status & RKV_ENC_INT_SAFE_CLEAR_FINISH) + hal_h265e_err("RKV_ENC_INT_SAFE_CLEAR_FINISH"); + + if (hw_status & RKV_ENC_INT_BIT_STREAM_OVERFLOW) + hal_h265e_err("RKV_ENC_INT_BIT_STREAM_OVERFLOW"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_FULL) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_FULL"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_ERROR"); + + if (hw_status & RKV_ENC_INT_BUS_READ_ERROR) + hal_h265e_err("RKV_ENC_INT_BUS_READ_ERROR"); + + if (hw_status & RKV_ENC_INT_TIMEOUT_ERROR) + hal_h265e_err("RKV_ENC_INT_TIMEOUT_ERROR"); + + fb->st_madi += elem->st.madi; + fb->st_madp += elem->st.madp; + fb->st_mb_num += elem->st.st_bnum_b16.num_b16; + fb->st_ctu_num += elem->st.st_bnum_cme.num_ctu; + + fb->st_lvl64_inter_num += elem->st.st_pnum_p64.pnum_p64; + fb->st_lvl32_inter_num += elem->st.st_pnum_p32.pnum_p32; + fb->st_lvl32_intra_num += elem->st.st_pnum_i32.pnum_i32; + fb->st_lvl16_inter_num += elem->st.st_pnum_p16.pnum_p16; + fb->st_lvl16_intra_num += elem->st.st_pnum_i16.pnum_i16; + fb->st_lvl8_inter_num += elem->st.st_pnum_p8.pnum_p8; + fb->st_lvl8_intra_num += elem->st.st_pnum_i8.pnum_i8; + fb->st_lvl4_intra_num += elem->st.st_pnum_i4.pnum_i4; + memcpy(&fb->st_cu_num_qp[0], &elem->st.st_b8_qp0, 52 * sizeof(RK_U32)); + + if (index == (ctx->tile_num - 1)) { + hal_rc_ret->bit_real += fb->out_strm_size * 8; + + if (fb->st_mb_num) { + fb->st_madi = fb->st_madi / fb->st_mb_num; + } else { + fb->st_madi = 0; + } + if (fb->st_ctu_num) { + fb->st_madp = fb->st_madp / fb->st_ctu_num; + } else { + fb->st_madp = 0; + } + + if (mb4_num > 0) + hal_rc_ret->iblk4_prop = ((((fb->st_lvl4_intra_num + fb->st_lvl8_intra_num) << 2) + + (fb->st_lvl16_intra_num << 4) + + (fb->st_lvl32_intra_num << 6)) << 8) / mb4_num; + + if (mb64_num > 0) { + /* + hal_cfg[k].inter_lv8_prop = ((fb->st_lvl8_inter_num + (fb->st_lvl16_inter_num << 2) + + (fb->st_lvl32_inter_num << 4) + + (fb->st_lvl64_inter_num << 6)) << 8) / mb8_num;*/ + + hal_rc_ret->quality_real = fb->qp_sum / mb8_num; + // hal_cfg[k].sse = fb->sse_sum / mb64_num; + } + + hal_rc_ret->madi += fb->st_madi; + hal_rc_ret->madp += fb->st_madp; + } + hal_h265e_leave(); + return MPP_OK; +} + +void save_to_file(char *name, void *ptr, size_t size) +{ + FILE *fp = fopen(name, "w+b"); + if (fp) { + fwrite(ptr, 1, size, fp); + fclose(fp); + } else + mpp_err("create file %s failed\n", name); +} + +void dump_files(H265eV580HalContext *ctx, HalEncTask *enc_task) +{ + H265eSyntax_new *syn = ctx->syn; + HalBuf *hal_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.ref_pic.slot_idx); + size_t buf_size = mpp_buffer_get_size(hal_buf->buf[0]); + size_t dws_size = mpp_buffer_get_size(hal_buf->buf[1]); + void *ptr = mpp_buffer_get_ptr(hal_buf->buf[0]); + void *dws_ptr = mpp_buffer_get_ptr(hal_buf->buf[1]); + RK_U32 frm_num = ctx->frms[enc_task->flags.reg_idx]->frame_count; + RK_S32 pid = getpid(); + char name[128]; + size_t name_len = sizeof(name) - 1; + + snprintf(name, name_len, "/data/refr_fbd_%d_frm%d.bin", pid, frm_num); + save_to_file(name, ptr + ctx->fbc_header_len, buf_size - ctx->fbc_header_len); + + snprintf(name, name_len, "/data/refr_fbh_%d_frm%d.bin", pid, frm_num); + save_to_file(name, ptr, ctx->fbc_header_len); + + snprintf(name, name_len, "/data/refr_dsp_%d_frm%d.bin", pid, frm_num); + save_to_file(name, dws_ptr, dws_size); + + hal_buf = hal_bufs_get_buf(ctx->dpb_bufs, syn->sp.recon_pic.slot_idx); + buf_size = mpp_buffer_get_size(hal_buf->buf[0]); + dws_size = mpp_buffer_get_size(hal_buf->buf[1]); + ptr = mpp_buffer_get_ptr(hal_buf->buf[0]); + dws_ptr = mpp_buffer_get_ptr(hal_buf->buf[1]); + + snprintf(name, name_len, "/data/recn_fbd_%d_frm%d.bin", pid, frm_num); + save_to_file(name, ptr + ctx->fbc_header_len, buf_size - ctx->fbc_header_len); + + snprintf(name, name_len, "/data/recn_fbh_%d_frm%d.bin", pid, frm_num); + save_to_file(name, ptr, ctx->fbc_header_len); + + snprintf(name, name_len, "/data/recn_dsp_%d_frm%d.bin", pid, frm_num); + save_to_file(name, dws_ptr, dws_size); +} + +static MPP_RET hal_h265e_vepu580_status_check(RK_U32 hw_status) +{ + MPP_RET ret = MPP_OK; + + if (hw_status & RKV_ENC_INT_LINKTABLE_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_LINKTABLE_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_FRAME_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_FRAME_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_SLICE_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_ONE_SLICE_FINISH"); + + if (hw_status & RKV_ENC_INT_SAFE_CLEAR_FINISH) + hal_h265e_dbg_detail("RKV_ENC_INT_SAFE_CLEAR_FINISH"); + + if (hw_status & RKV_ENC_INT_BIT_STREAM_OVERFLOW) + hal_h265e_err("RKV_ENC_INT_BIT_STREAM_OVERFLOW"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_FULL) { + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_FULL"); + ret = MPP_NOK; + } + + if (hw_status & RKV_ENC_INT_BUS_WRITE_ERROR) { + hal_h265e_err("RKV_ENC_INT_BUS_WRITE_ERROR"); + ret = MPP_NOK; + } + + if (hw_status & RKV_ENC_INT_BUS_READ_ERROR) { + hal_h265e_err("RKV_ENC_INT_BUS_READ_ERROR"); + ret = MPP_NOK; + } + + if (hw_status & RKV_ENC_INT_TIMEOUT_ERROR) { + hal_h265e_err("RKV_ENC_INT_TIMEOUT_ERROR"); + ret = MPP_NOK; + } + + return ret; +} + +MPP_RET hal_h265e_v580_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + HalEncTask *enc_task = task; + RK_U32 split_out = ctx->cfg->split.split_out; + RK_S32 task_idx = task->flags.reg_idx; + Vepu580H265eFrmCfg *frm = ctx->frms[task_idx]; + + hal_h265e_enter(); + + if (enc_task->flags.err) { + hal_h265e_err("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + + /* if pass1 mode, it will disable split mode and the split out need to be disable */ + if (enc_task->rc_task->frm.save_pass1) + split_out = 0; + + if (split_out) { + EncOutParam param; + RK_U32 slice_len = 0; + RK_U32 slice_last = 0; + RK_U32 finish_cnt = 0; + RK_U32 tile1_offset = 0; + MppPacket pkt = enc_task->packet; + RK_U32 offset = mpp_packet_get_length(pkt); + RK_U32 seg_offset = offset; + void* ptr = mpp_packet_get_pos(pkt); + H265eV580RegSet *regs = frm->regs_set[0]; + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_U32 type = reg_base->reg0236_synt_nal.nal_unit_type; + MppDevPollCfg *poll_cfg = (MppDevPollCfg *)((char *)ctx->poll_cfgs); + + param.task = task; + param.base = mpp_packet_get_data(task->packet); + + do { + RK_S32 i = 0; + poll_cfg->poll_type = 0; + poll_cfg->poll_ret = 0; + poll_cfg->count_max = ((split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) != 0) ? 1 : ctx->poll_slice_max; + poll_cfg->count_ret = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, poll_cfg); + + for (i = 0; i < poll_cfg->count_ret; i++) { + slice_last = poll_cfg->slice_info[i].last; + slice_len = poll_cfg->slice_info[i].length; + param.length = slice_len; + + if (finish_cnt > 0) { + MppBuffer buf = frm->hw_tile_stream[finish_cnt - 1]; + void *tile1_ptr = mpp_buffer_get_ptr(buf); + + mpp_buffer_sync_ro_partial_begin(buf, tile1_offset, slice_len); + memcpy(ptr + seg_offset, tile1_ptr + tile1_offset, slice_len); + tile1_offset += slice_len; + } else { + MppBuffer buf = enc_task->output; + + mpp_buffer_sync_ro_partial_begin(buf, offset, slice_len); + } + + ctx->output_cb->cmd = ENC_OUTPUT_SLICE; + if (slice_last) { + finish_cnt++; + tile1_offset = 0; + if (ctx->tile_parall_en) { + if (finish_cnt + 1 > ctx->tile_num) { + ctx->output_cb->cmd = ENC_OUTPUT_FINISH; + } + } + } + + mpp_packet_add_segment_info(pkt, type, seg_offset, slice_len); + + if (split_out & MPP_ENC_SPLIT_OUT_LOWDELAY) + mpp_callback(ctx->output_cb, ¶m); + + seg_offset += slice_len; + } + + if (ctx->tile_parall_en) { + if (finish_cnt + 1 > ctx->tile_num) { + break; + } + } else if (slice_last) { + break; + } + } while (1); + } else { + H265eV580StatusElem *elem = frm->regs_ret[0]; + H265eV580RegSet *regs = frm->regs_set[0]; + hevc_vepu580_base *reg_base = ®s->reg_base; + RK_U32 type = reg_base->reg0236_synt_nal.nal_unit_type; + MppPacket pkt = enc_task->packet; + RK_U32 offset = mpp_packet_get_length(pkt); + RK_U32 i = 0; + + if (ctx->tile_parall_en) { + for (i = 0; i < ctx->tile_num; i ++) + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + } else { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + } + + for (i = 0; i < ctx->tile_num; i++) { + H265eV580StatusElem *elem_ret = frm->regs_ret[i]; + RK_U32 hw_status = elem_ret->hw_status; + RK_U32 tile_size = elem_ret->st.bs_lgth_l32; + + ret = hal_h265e_vepu580_status_check(hw_status); + if (ret) + break; + mpp_packet_add_segment_info(pkt, type, offset, tile_size); + offset += tile_size; + + if (ctx->tile_dump_err && + (hw_status & (RKV_ENC_INT_BUS_WRITE_ERROR | RKV_ENC_INT_BUS_READ_ERROR))) { + dump_files(ctx, enc_task); + break; + } + } + + if (ret) + mpp_err_f("poll cmd failed %d status %d \n", ret, elem->hw_status); + } + + hal_h265e_leave(); + + return ret; +} + +MPP_RET hal_h265e_v580_get_task(void *hal, HalEncTask *task) +{ + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + Vepu580H265eFrmCfg *frm_cfg = NULL; + EncFrmStatus *frm_status = &task->rc_task->frm; + MppFrame frame = task->frame; + RK_S32 task_idx = ctx->task_idx; + + hal_h265e_enter(); + + task->part_first = 1; + task->part_last = 0; + task->flags.reg_idx = task_idx; + + if (!frm_status->reencode) { + ctx->syn = (H265eSyntax_new *)task->syntax.data; + ctx->dpb = (H265eDpb*)ctx->syn->dpb; + + if (vepu580_h265_setup_hal_bufs(ctx)) { + hal_h265e_err("vepu541_h265_allocate_buffers failed, free buffers and return\n"); + task->flags.err |= HAL_ENC_TASK_ERR_ALLOC; + return MPP_ERR_MALLOC; + } + + ctx->last_frame_type = ctx->frame_type; + + frm_cfg = ctx->frms[task_idx]; + ctx->frm = frm_cfg; + + if (mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr_d(meta, KEY_ROI_DATA2, (void **)&frm_cfg->roi_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA, (void **)&frm_cfg->osd_cfg.osd_data, NULL); + mpp_meta_get_ptr_d(meta, KEY_OSD_DATA2, (void **)&frm_cfg->osd_cfg.osd_data2, NULL); + } else { + frm_cfg->roi_data = NULL; + frm_cfg->osd_cfg.osd_data = NULL; + frm_cfg->osd_cfg.osd_data2 = NULL; + } + + frm_cfg->frame_count = ctx->frame_count++; + + ctx->task_idx++; + if (ctx->task_idx >= ctx->task_cnt) + ctx->task_idx = 0; + + frm_cfg->hal_curr_idx = ctx->syn->sp.recon_pic.slot_idx; + frm_cfg->hal_refr_idx = ctx->syn->sp.ref_pic.slot_idx; + } else { + /* reencode path may change the frame type */ + frm_cfg = ctx->frm; + } + + h265e_dpb_hal_start(ctx->dpb, frm_cfg->hal_curr_idx); + h265e_dpb_hal_start(ctx->dpb, frm_cfg->hal_refr_idx); + + ctx->frame_type = (frm_status->is_intra != 0) ? INTRA_FRAME : INTER_P_FRAME; + frm_cfg->frame_type = ctx->frame_type; + mpp_dev_multi_offset_reset(frm_cfg->reg_cfg); + memset(&frm_cfg->feedback, 0, sizeof(frm_cfg->feedback)); + + hal_h265e_leave(); + return MPP_OK; +} + +MPP_RET hal_h265e_v580_ret_task(void *hal, HalEncTask *task) +{ + H265eV580HalContext *ctx = (H265eV580HalContext *)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + HalEncTask *enc_task = task; + RK_S32 task_idx = task->flags.reg_idx; + Vepu580H265eFrmCfg *frm = ctx->frms[task_idx]; + Vepu580H265Fbk *fb = &frm->feedback; + H265eSyntax_new *syn = (H265eSyntax_new *) enc_task->syntax.data; + RK_U32 offset = mpp_packet_get_length(enc_task->packet); + + hal_h265e_enter(); + + if (ctx->tile_parall_en) { + RK_U32 i = 0, stream_len = 0; + void* ptr = mpp_packet_get_pos(enc_task->packet); + + for (i = 0; i < ctx->tile_num; i ++) { + vepu580_h265_set_feedback(ctx, enc_task, i); + if (!ctx->cfg->split.split_out) { + if (i) { //copy tile 1 stream + RK_U32 len = fb->out_strm_size - stream_len; + MppBuffer buf = frm->hw_tile_stream[i - 1]; + RK_U8 *tile1_ptr = mpp_buffer_get_ptr(buf); + + mpp_buffer_sync_partial_begin(buf, 0, len); + + if (syn->sp.temporal_id && len > 5) + tile1_ptr[5] = (tile1_ptr[5] & 0xf8) | ((syn->sp.temporal_id + 1) & 0x7); + + memcpy(ptr + stream_len + offset, tile1_ptr, len); + } else { + MppBuffer buf = enc_task->output; + RK_U32 len = fb->out_strm_size; + RK_U8 *stream_ptr = (RK_U8 *) ptr; + + mpp_buffer_sync_partial_begin(buf, offset, len); + + if (syn->sp.temporal_id) { + stream_ptr[5] = (stream_ptr[5] & 0xf8) | ((syn->sp.temporal_id + 1) & 0x7); + } + } + stream_len = fb->out_strm_size; + } + } + } else { + vepu580_h265_set_feedback(ctx, enc_task, ctx->tile_num - 1); + mpp_buffer_sync_partial_begin(enc_task->output, offset, fb->out_strm_size); + hal_h265e_amend_temporal_id(task, fb->out_strm_size); + } + + rc_info->sse = fb->sse_sum; + rc_info->lvl64_inter_num = fb->st_lvl64_inter_num; + rc_info->lvl32_inter_num = fb->st_lvl32_inter_num; + rc_info->lvl16_inter_num = fb->st_lvl16_inter_num; + rc_info->lvl8_inter_num = fb->st_lvl8_inter_num; + rc_info->lvl32_intra_num = fb->st_lvl32_intra_num; + rc_info->lvl16_intra_num = fb->st_lvl16_intra_num; + rc_info->lvl8_intra_num = fb->st_lvl8_intra_num; + rc_info->lvl4_intra_num = fb->st_lvl4_intra_num; + + enc_task->hw_length = fb->out_strm_size; + enc_task->length += fb->out_strm_size; + + vepu580_h265e_tune_stat_update(ctx->tune, rc_info); + + h265e_dpb_hal_end(ctx->dpb, frm->hal_curr_idx); + h265e_dpb_hal_end(ctx->dpb, frm->hal_refr_idx); + + hal_h265e_dbg_detail("output stream size %d\n", fb->out_strm_size); + + hal_h265e_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_h265e_vepu580 = { + .name = "hal_h265e_v580", + .coding = MPP_VIDEO_CodingHEVC, + .ctx_size = sizeof(H265eV580HalContext), + .flag = 0, + .init = hal_h265e_v580_init, + .deinit = hal_h265e_v580_deinit, + .prepare = hal_h265e_vepu580_prepare, + .get_task = hal_h265e_v580_get_task, + .gen_regs = hal_h265e_v580_gen_regs, + .start = hal_h265e_v580_start, + .wait = hal_h265e_v580_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h265e_v580_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h265e_vepu580) diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu580.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu580.h new file mode 100644 index 000000000..b1867897e --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu580.h @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_VEPU580_H +#define HAL_H265E_VEPU580_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h265e_vepu580; + +#endif /* HAL_H265E_VEPU580_H */ diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu580_reg.h b/mpp/hal/rkenc/h265e/hal_h265e_vepu580_reg.h new file mode 100644 index 000000000..bc75e59b7 --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu580_reg.h @@ -0,0 +1,3268 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H265E_VEPU580_REG_H +#define HAL_H265E_VEPU580_REG_H + +#include "rk_type.h" + +#define VEPU580_CTL_OFFSET (0 * sizeof(RK_U32)) +#define VEPU580_BASE_OFFSET (160 * sizeof(RK_U32)) +#define VEPU580_RCKULT_OFFSET (1024 * sizeof(RK_U32)) +#define VEPU580_WEG_OFFSET (1472 * sizeof(RK_U32)) +#define VEPU580_RDOCFG_OFFSET (2048 * sizeof(RK_U32)) +#define VEPU580_OSD_OFFSET (3072 * sizeof(RK_U32)) +#define VEPU580_STATUS_OFFSET (4096 * sizeof(RK_U32)) +#define VEPU580_DEBUG_OFFSET (5120 * sizeof(RK_U32)) +#define VEPU580_REG_BASE_HW_STATUS 0x2c + +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct HevcVepu580ControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 h264_cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 reserved : 2; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } reg0001_version; + + /* 0x4 - 0xc */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 2; + RK_U32 reserved : 22; + } reg0004_enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } reg0005_enc_clr; + + /* 0x18 - 0x1c */ + RK_U32 reserved6_7[2]; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 slc_done_en : 1; + RK_U32 bsf_oflw_en : 1; + RK_U32 brsp_otsd_en : 1; + RK_U32 wbus_err_en : 1; + RK_U32 rbus_err_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 reserved : 22; + } reg0008_int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 slc_done_msk : 1; + RK_U32 bsf_oflw_msk : 1; + RK_U32 brsp_otsd_msk : 1; + RK_U32 wbus_err_msk : 1; + RK_U32 rbus_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_msk : 1; + RK_U32 reserved : 22; + } reg0009_int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 slc_done_clr : 1; + RK_U32 bsf_oflw_clr : 1; + RK_U32 brsp_otsd_clr : 1; + RK_U32 wbus_err_clr : 1; + RK_U32 rbus_err_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_clr : 1; + RK_U32 reserved : 22; + } reg0010_int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 slc_done_sta : 1; + RK_U32 bsf_oflw_sta : 1; + RK_U32 brsp_otsd_sta : 1; + RK_U32 wbus_err_sta : 1; + RK_U32 rbus_err_sta : 1; + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_sta : 1; + RK_U32 reserved : 22; + } reg0011_int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 lpfw_bus_ordr : 1; + RK_U32 cmvw_bus_ordr : 1; + RK_U32 dspw_bus_ordr : 1; + RK_U32 rfpw_bus_ordr : 1; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 3; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 afbc_bsize : 1; + RK_U32 ebufw_bus_ordr : 1; + RK_U32 rec_nfbc_bus_edin : 3; + } reg0012_dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 reserved : 7; + RK_U32 dspr_otsd : 1; + RK_U32 reserved1 : 8; + RK_U32 axi_brsp_cke : 8; + RK_U32 reserved2 : 8; + } reg0013_dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 rfp_load_thd : 8; + } reg0014_enc_wdg; + + /* 0x0000003c reg15 */ + struct { + RK_U32 hurry_en : 1; + RK_U32 hurry_low : 3; + RK_U32 hurry_mid : 3; + RK_U32 hurry_high : 3; + RK_U32 reserved : 22; + } reg0015_qos_cfg; + + /* 0x00000040 reg16 */ + struct { + RK_U32 qos_period : 16; + RK_U32 reserved : 16; + } reg0016_qos_perd; + + /* 0x00000044 reg17 */ + RK_U32 reg0017_hurry_thd_low; + + /* 0x00000048 reg18 */ + RK_U32 reg0018_hurry_thd_mid; + + /* 0x0000004c reg19 */ + RK_U32 reg0019_hurry_thd_high; + + /* 0x00000050 reg20 */ + struct { + RK_U32 idle_en_core : 1; + RK_U32 idle_en_axi : 1; + RK_U32 idle_en_ahb : 1; + RK_U32 reserved : 29; + } reg0020_enc_idle_en; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 enc_done_tmvp_en : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 reserved : 28; + } reg0021_func_en; + + /* 0x00000058 reg22 */ + struct { + RK_U32 recon32_ckg : 1; + RK_U32 iqit32_ckg : 1; + RK_U32 q32_ckg : 1; + RK_U32 t32_ckg : 1; + RK_U32 cabac32_ckg : 1; + RK_U32 recon16_ckg : 1; + RK_U32 iqit16_ckg : 1; + RK_U32 q16_ckg : 1; + RK_U32 t16_ckg : 1; + RK_U32 cabac16_ckg : 1; + RK_U32 recon8_ckg : 1; + RK_U32 iqit8_ckg : 1; + RK_U32 q8_ckg : 1; + RK_U32 t8_ckg : 1; + RK_U32 cabac8_ckg : 1; + RK_U32 recon4_ckg : 1; + RK_U32 iqit4_ckg : 1; + RK_U32 q4_ckg : 1; + RK_U32 t4_ckg : 1; + RK_U32 cabac4_ckg : 1; + RK_U32 intra32_ckg : 1; + RK_U32 intra16_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 reserved : 7; + } reg0022_rdo_ckg_hevc; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } reg0023_enc_id; +} hevc_vepu580_control_cfg; + +/* class: buffer/video syntax */ +/* 0x00000280 reg160 - 0x000003f4 reg253*/ +typedef struct HevcVepu580Base_t { + /* 0x00000280 reg160 */ + RK_U32 reg0160_adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 reg0161_adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 reg0162_adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 reg0163_rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 reg0164_rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 reg0165_rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 reg0166_rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 reg0167_cmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 reg0168_cmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 reg0169_dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 reg0170_dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 reg0171_meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 reg0172_bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 reg0173_bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 reg0174_bsbr_addr; + + /* 0x000002bc reg175 */ + RK_U32 reg0175_adr_bsbs; + + /* 0x000002c0 reg176 */ + RK_U32 reg0176_lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 reg0177_lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 reg0178_roi_addr; + + /* 0x000002cc reg179 */ + RK_U32 reg0179_roi_qp_addr; + + /* 0x000002d0 reg180 */ + RK_U32 reg0180_roi_amv_addr; + + /* 0x000002d4 reg181 */ + RK_U32 reg0181_roi_mv_addr; + + /* 0x000002d8 reg182 */ + RK_U32 reg0182_ebuft_addr; + + /* 0x000002dc reg183 */ + RK_U32 reg183_ebufb_addr; + + /* 0x2e0 - 0x2fc */ + RK_U32 reserved184_191[8]; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 1; + RK_U32 roi_en : 1; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 reserved : 3; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur : 5; + RK_U32 log2_ctu_num : 5; + RK_U32 reserved1 : 6; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } reg0192_enc_pic; + + /* 0x00000304 reg193 */ + struct { + RK_U32 dchs_txid : 2; + RK_U32 dchs_rxid : 2; + RK_U32 dchs_txe : 1; + RK_U32 dchs_rxe : 1; + RK_U32 reserved : 10; + RK_U32 dchs_ofst : 11; + RK_U32 reserved1 : 5; + } reg0193_dual_core; + + /* 0x308 - 0x30c */ + RK_U32 reserved194_195[2]; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } reg0196_enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } reg0197_src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_range : 1; + RK_U32 out_fmt : 1; + RK_U32 reserved : 24; + } reg0198_src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } reg0199_src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } reg0200_src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } reg0201_src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } reg0202_src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 reserved0 : 26; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 txa_en : 1; + RK_U32 afbcd_en : 1; + RK_U32 reserved1 : 1; + } reg0203_src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } reg0204_pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 17; + RK_U32 reserved : 15; + } reg0205_src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } reg0206_src_strd1; + + /* 0x33c - 0x34c */ + RK_U32 reserved207_211[5]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 aq_mode : 1; + RK_U32 reserved : 9; + RK_U32 rc_ctu_num : 20; + } reg212_rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } reg213_rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } reg214_rc_tgt; + + /* 0x35c */ + RK_U32 reserved_215; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } reg0216_sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } reg0217_sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } reg0218_sli_cnum; + + /* 0x36c */ + RK_U32 reserved_219; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cme_srch_h : 4; + RK_U32 cme_srch_v : 4; + RK_U32 rme_srch_h : 3; + RK_U32 rme_srch_v : 3; + RK_U32 reserved : 2; + RK_U32 dlt_frm_num : 16; + } reg0220_me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 pmv_mdst_h : 8; + RK_U32 pmv_mdst_v : 8; + RK_U32 mv_limit : 2; + RK_U32 pmv_num : 2; + RK_U32 colmv_stor : 1; + RK_U32 colmv_load : 1; + RK_U32 reserved1 : 1; + RK_U32 rme_dis : 4; + RK_U32 reserved2 : 1; + RK_U32 fme_dis : 4; + } reg0221_me_cfg; + + + /* 0x00000378 reg222 */ + struct { + RK_U32 cme_rama_max : 11; + RK_U32 cme_rama_h : 5; + RK_U32 cach_l2_tag : 2; + RK_U32 cme_linebuf_w : 9; + RK_U32 reserved : 5; + } reg0222_me_cach; + + /* 0x37c */ + RK_U32 reserved_223; + + /* 0x00000380 reg224 */ + struct { + RK_U32 gmv_x : 13; + RK_U32 reserved : 3; + RK_U32 gmv_y : 13; + RK_U32 reserved1 : 3; + } reg0224_gmv; + + /* 0x384 - 0x38c */ + RK_U32 reserved225_227[3]; + + /* 0x00000390 reg228 */ + struct { + RK_U32 roi_qp_en : 1; + RK_U32 roi_amv_en : 1; + RK_U32 roi_mv_en : 1; + RK_U32 reserved : 29; + } reg0228_roi_en; + + /* 0x394 - 0x39c */ + RK_U32 reserved229_231[3]; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 ltm_col : 1; + RK_U32 ltm_idx0l0 : 1; + RK_U32 chrm_spcl : 1; + RK_U32 cu_inter_e : 12; + RK_U32 reserved : 4; + RK_U32 cu_intra_e : 4; + RK_U32 ccwa_e : 1; + RK_U32 scl_lst_sel : 2; + RK_U32 reserved1 : 2; + RK_U32 satd_byps_flg : 4; + } reg0232_rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 vthd_y : 12; + RK_U32 reserved : 4; + RK_U32 vthd_c : 12; + RK_U32 reserved1 : 4; + } reg0233_iprd_csts; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + + struct { + RK_U32 nal_unit_type : 6; + RK_U32 reserved : 26; + } reg0236_synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 smpl_adpt_ofst_e : 1; + RK_U32 num_st_ref_pic : 7; + RK_U32 lt_ref_pic_prsnt : 1; + RK_U32 num_lt_ref_pic : 6; + RK_U32 tmpl_mvp_e : 1; + RK_U32 log2_max_poc_lsb : 4; + RK_U32 strg_intra_smth : 1; + RK_U32 reserved : 11; + } reg0237_synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 dpdnt_sli_seg_en : 1; + RK_U32 out_flg_prsnt_flg : 1; + RK_U32 num_extr_sli_hdr : 3; + RK_U32 sgn_dat_hid_en : 1; + RK_U32 cbc_init_prsnt_flg : 1; + RK_U32 pic_init_qp : 6; + RK_U32 cu_qp_dlt_en : 1; + RK_U32 chrm_qp_ofst_prsn : 1; + RK_U32 lp_fltr_acrs_sli : 1; + RK_U32 dblk_fltr_ovrd_en : 1; + RK_U32 lst_mdfy_prsnt_flg : 1; + RK_U32 sli_seg_hdr_extn : 1; + RK_U32 cu_qp_dlt_depth : 2; + RK_U32 lpf_fltr_acrs_til : 1; + RK_U32 reserved : 10; + } reg0238_synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 mrg_up_flg : 1; + RK_U32 mrg_lft_flg : 1; + RK_U32 reserved : 1; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_l1_act : 2; + RK_U32 num_refidx_l0_act : 2; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_e : 1; + RK_U32 pic_out_flg : 1; + RK_U32 sli_type : 2; + RK_U32 sli_rsrv_flg : 7; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 sli_pps_id : 6; + RK_U32 no_out_pri_pic : 1; + } reg0239_synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 sp_tc_ofst_div2 : 4; + RK_U32 sp_beta_ofst_div2 : 4; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sp_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_U32 sli_cb_qp_ofst : 5; + RK_U32 sli_qp : 6; + RK_U32 max_mrg_cnd : 2; + RK_U32 reserved : 1; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 lst_entry_l0 : 4; + RK_U32 reserved1 : 1; + } reg0240_synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 sli_poc_lsb : 16; + RK_U32 sli_hdr_ext_len : 9; + RK_U32 reserved : 7; + } reg0241_synt_sli2; + + /* 0x000003c8 reg242 */ + + struct { + RK_U32 st_ref_pic_flg : 1; + RK_U32 poc_lsb_lt0 : 16; + RK_U32 lt_idx_sps : 5; + RK_U32 num_lt_pic : 2; + RK_U32 st_ref_pic_idx : 6; + RK_U32 num_lt_sps : 2; + } reg0242_synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 used_by_s0_flg : 4; + RK_U32 num_pos_pic : 1; + RK_U32 num_negative_pics : 5; + RK_U32 dlt_poc_msb_cycl0 : 16; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + } reg0243_synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 dlt_poc_s0_m10 : 16; + RK_U32 dlt_poc_s0_m11 : 16; + } reg0244_synt_refm2; + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } reg0245_synt_refm3; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } reg0246_synt_long_refm0; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } reg0247_synt_long_refm1; + + /* 0x3e0 - 0x3ec */ + RK_U32 reserved248_251[4]; + + /* 0x000003f0 reg252 */ + + struct { + RK_U32 tile_w_m1 : 8; + RK_U32 reserved : 8; + RK_U32 tile_h_m1 : 8; + RK_U32 reserved1 : 7; + RK_U32 tile_en : 1; + } reg0252_tile_cfg; + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 8; + RK_U32 reserved : 8; + RK_U32 tile_y : 8; + RK_U32 reserved1 : 8; + } reg0253_tile_pos; +} hevc_vepu580_base; + +/* class: rc/roi/aq/klut */ +/* 0x00001000 reg1024 - 0x000010e0 reg1080 */ +typedef struct HevcVepu580RcKlut_t { + /* 0x00001000 reg1024 */ + struct { + RK_U32 qp_adj0 : 5; + RK_U32 qp_adj1 : 5; + RK_U32 qp_adj2 : 5; + RK_U32 qp_adj3 : 5; + RK_U32 qp_adj4 : 5; + RK_U32 reserved : 7; + } rc_adj0; + + /* 0x00001004 reg1025 */ + struct { + RK_U32 qp_adj5 : 5; + RK_U32 qp_adj6 : 5; + RK_U32 qp_adj7 : 5; + RK_U32 qp_adj8 : 5; + RK_U32 reserved : 12; + } rc_adj1; + + /* 0x00001008 reg1026 - 0x00001028 reg1034 */ + RK_U32 rc_dthd_0_8[9]; + + /* 0x102c */ + RK_U32 reserved_1035; + + /* 0x00001030 reg1036 */ + struct { + RK_U32 qpmin_area0 : 6; + RK_U32 qpmax_area0 : 6; + RK_U32 qpmin_area1 : 6; + RK_U32 qpmax_area1 : 6; + RK_U32 qpmin_area2 : 6; + RK_U32 reserved : 2; + } roi_qthd0; + + /* 0x00001034 reg1037 */ + struct { + RK_U32 qpmax_area2 : 6; + RK_U32 qpmin_area3 : 6; + RK_U32 qpmax_area3 : 6; + RK_U32 qpmin_area4 : 6; + RK_U32 qpmax_area4 : 6; + RK_U32 reserved : 2; + } roi_qthd1; + + /* 0x00001038 reg1038 */ + struct { + RK_U32 qpmin_area5 : 6; + RK_U32 qpmax_area5 : 6; + RK_U32 qpmin_area6 : 6; + RK_U32 qpmax_area6 : 6; + RK_U32 qpmin_area7 : 6; + RK_U32 reserved : 2; + } roi_qthd2; + + /* 0x0000103c reg1039 */ + struct { + RK_U32 qpmax_area7 : 6; + RK_U32 reserved : 24; + RK_U32 qpmap_mode : 2; + } roi_qthd3; + + /* 0x00001040 reg1040 */ + struct { + RK_U32 madi_mode : 1; + RK_U32 reserved : 15; + RK_U32 madi_thd : 8; + RK_U32 reserved1 : 8; + } madi_cfg; + + /* 0x00001044 reg1041 - 0x00001050 reg1044 */ + RK_U8 aq_tthd[16]; + /* + * 0x00001054 reg1045 - 0x00001060 reg1048 + * only low 6bits is valid for per step. + */ + RK_U8 aq_step[16]; + + /* 0x1064 - 0x106c */ + RK_U32 reserved1049_1051[3]; + + /* 0x00001070 reg1052 */ + struct { + RK_U32 md_sad_thd0 : 8; + RK_U32 md_sad_thd1 : 8; + RK_U32 md_sad_thd2 : 8; + RK_U32 reserved : 8; + } md_sad_thd; + + /* 0x00001074 reg1053 */ + struct { + RK_U32 madi_thd0 : 8; + RK_U32 madi_thd1 : 8; + RK_U32 madi_thd2 : 8; + RK_U32 reserved : 8; + } madi_thd; + + /* 0x1078 - 0x107c */ + RK_U32 reserved1054_1055[2]; + + /* 0x00001080 reg1056 */ + struct { + RK_U32 chrm_klut_ofst : 3; + RK_U32 reserved : 29; + } klut_ofst; + + /* 0x00001084 reg1057 */ + struct { + RK_U32 chrm_klut_wgt0 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt1_l9 : 9; + } klut_wgt0; + + /* 0x00001088 reg1058 */ + struct { + RK_U32 chrm_klut_wgt1_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt2 : 18; + } klut_wgt1; + + /* 0x0000108c reg1059 */ + struct { + RK_U32 chrm_klut_wgt3 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt4_l9 : 9; + } klut_wgt2; + + /* 0x00001090 reg1060 */ + struct { + RK_U32 chrm_klut_wgt4_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt5 : 18; + } klut_wgt3; + + /* 0x00001094 reg1061 */ + struct { + RK_U32 chrm_klut_wgt6 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt7_l9 : 9; + } klut_wgt4; + + /* 0x00001098 reg1062 */ + struct { + RK_U32 chrm_klut_wgt7_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt8 : 18; + } klut_wgt5; + + /* 0x0000109c reg1063 */ + struct { + RK_U32 chrm_klut_wgt9 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt10_l9 : 9; + } klut_wgt6; + + /* 0x000010a0 reg1064 */ + struct { + RK_U32 chrm_klut_wgt10_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt11 : 18; + } klut_wgt7; + + /* 0x000010a4 reg1065 */ + struct { + RK_U32 chrm_klut_wgt12 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt13_l9 : 9; + } klut_wgt8; + + /* 0x000010a8 reg1066 */ + struct { + RK_U32 chrm_klut_wgt13_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt14 : 18; + } klut_wgt9; + + /* 0x000010ac reg1067 */ + struct { + RK_U32 chrm_klut_wgt15 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt16_l9 : 9; + } klut_wgt10; + + /* 0x000010b0 reg1068 */ + struct { + RK_U32 chrm_klut_wgt16_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt17 : 18; + } klut_wgt11; + + /* 0x000010b4 reg1069 */ + struct { + RK_U32 chrm_klut_wgt18 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt19_l9 : 9; + } klut_wgt12; + + /* 0x000010b8 reg1070 */ + struct { + RK_U32 chrm_klut_wgt19_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt20 : 18; + } klut_wgt13; + + /* 0x000010bc reg1071 */ + struct { + RK_U32 chrm_klut_wgt21 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt22_l9 : 9; + } klut_wgt14; + + /* 0x000010c0 reg1072 */ + struct { + RK_U32 chrm_klut_wgt22_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt23 : 18; + } klut_wgt15; + + /* 0x000010c4 reg1073 */ + struct { + RK_U32 chrm_klut_wgt24 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt25_l9 : 9; + } klut_wgt16; + + /* 0x000010c8 reg1074 */ + struct { + RK_U32 chrm_klut_wgt25_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt26 : 18; + } klut_wgt17; + + /* 0x000010cc reg1075 */ + struct { + RK_U32 chrm_klut_wgt27 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt28_l9 : 9; + } klut_wgt18; + + /* 0x000010d0 reg1076 */ + struct { + RK_U32 chrm_klut_wgt28_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt29 : 18; + } klut_wgt19; + + /* 0x000010d4 reg1077 */ + struct { + RK_U32 chrm_klut_wgt30 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt31_l9 : 9; + } klut_wgt20; + + /* 0x000010d8 reg1078 */ + struct { + RK_U32 chrm_klut_wgt31_h9 : 9; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt32 : 18; + } klut_wgt21; + + /* 0x000010dc reg1079 */ + struct { + RK_U32 chrm_klut_wgt33 : 18; + RK_U32 reserved : 5; + RK_U32 chrm_klut_wgt34_l9 : 9; + } klut_wgt22; + + /* 0x000010e0 reg1080 */ + struct { + RK_U32 chrm_klut_wgt34_h9 : 9; + RK_U32 reserved : 23; + } klut_wgt23; +} hevc_vepu580_rc_klut; + +/* class: iprd/iprd_wgt/rdo_wgta/prei_dif/sobel */ +/* 0x00001700 reg1472 - 0x00001cd4 reg1845 */ +typedef struct HevcVepu580Wgt_t { + /* 0x00001700 reg1472 */ + struct { + RK_U32 lvl32_intra_cst_thd0 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl32_intra_cst_thd1 : 12; + RK_U32 reserved1 : 4; + } lvl32_intra_CST_THD0; + + /* 0x1704 */ + struct { + RK_U32 lvl32_intra_cst_thd2 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl32_intra_cst_thd3 : 12; + RK_U32 reserved1 : 4; + } lvl32_intra_CST_THD1; + + /* 0x1708 */ + struct { + RK_U32 lvl16_intra_cst_thd0 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl16_intra_cst_thd1 : 12; + RK_U32 reserved1 : 4; + } lvl16_intra_CST_THD0; + + /* 0x170c */ + struct { + RK_U32 lvl16_intra_cst_thd2 : 12; + RK_U32 reserved0 : 4; + RK_U32 lvl16_intra_cst_thd3 : 12; + RK_U32 reserved1 : 4; + } lvl16_intra_CST_THD1; + + /* 0x10-0x18 - reserved */ + RK_U32 reserved_0x1710_0x0x1718[3]; + + /* 0x171c */ + struct { + RK_U32 lvl32_intra_cst_wgt0 : 8; + RK_U32 lvl32_intra_cst_wgt1 : 8; + RK_U32 lvl32_intra_cst_wgt2 : 8; + RK_U32 lvl32_intra_cst_wgt3 : 8; + } lvl32_intra_CST_WGT0; + + /* 0x1720 */ + struct { + RK_U32 lvl32_intra_cst_wgt4 : 8; + RK_U32 lvl32_intra_cst_wgt5 : 8; + RK_U32 lvl32_intra_cst_wgt6 : 8; + RK_U32 reserved2 : 8; + } lvl32_intra_CST_WGT1; + + /* 0x1724 */ + struct { + RK_U32 lvl16_intra_cst_wgt0 : 8; + RK_U32 lvl16_intra_cst_wgt1 : 8; + RK_U32 lvl16_intra_cst_wgt2 : 8; + RK_U32 lvl16_intra_cst_wgt3 : 8; + } lvl16_intra_CST_WGT0; + + /* 0x1728 */ + struct { + RK_U32 lvl16_intra_cst_wgt4 : 8; + RK_U32 lvl16_intra_cst_wgt5 : 8; + RK_U32 lvl16_intra_cst_wgt6 : 8; + RK_U32 reserved2 : 8; + } lvl16_intra_CST_WGT1; + + + /* 0x172c */ + RK_U32 reserved_1483; + + /* 0x00001730 reg1484 */ + struct { + RK_U32 qnt_bias_i : 10; + RK_U32 qnt_bias_p : 10; + RK_U32 reserved : 12; + } reg1484_qnt_bias_comb; + + /* 0x1734 - 0x175c */ + RK_U32 reserved1485_1495[11]; + + /* 0x00001760 reg1496 */ + struct { + RK_U32 cime_sad_mod_sel : 1; + RK_U32 cime_sad_use_big_block : 1; + RK_U32 cime_pmv_set_zero : 1; + RK_U32 reserved : 5; + RK_U32 cime_pmv_num : 2; + RK_U32 reserved1 : 22; + } cime_sqi_cfg; + + /* 0x00001764 reg1497 */ + struct { + RK_U32 cime_mvd_th0 : 9; + RK_U32 reserved : 1; + RK_U32 cime_mvd_th1 : 9; + RK_U32 reserved1 : 1; + RK_U32 cime_mvd_th2 : 9; + RK_U32 reserved2 : 3; + } cime_sqi_thd; + + /* 0x00001768 reg1498 */ + struct { + RK_U32 cime_multi0 : 10; + RK_U32 reserved : 6; + RK_U32 cime_multi1 : 10; + RK_U32 reserved1 : 6; + } cime_sqi_multi0; + + /* 0x0000176c reg1499 */ + struct { + RK_U32 cime_multi2 : 10; + RK_U32 reserved : 6; + RK_U32 cime_multi3 : 10; + RK_U32 reserved1 : 6; + } cime_sqi_multi1; + + /* 0x00001770 reg1500 */ + struct { + RK_U32 cime_sad_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rime_mvd_th0 : 4; + RK_U32 reserved1 : 4; + RK_U32 rime_mvd_th1 : 4; + RK_U32 reserved2 : 4; + } rime_sqi_thd; + + /* 0x00001774 reg1501 */ + struct { + RK_U32 rime_multi0 : 10; + RK_U32 rime_multi1 : 10; + RK_U32 rime_multi2 : 10; + RK_U32 reserved : 2; + } rime_sqi_multi; + + /* 0x00001778 reg1502 */ + struct { + RK_U32 cime_sad_pu16_th : 12; + RK_U32 reserved : 4; + RK_U32 cime_sad_pu32_th : 12; + RK_U32 reserved1 : 4; + } fme_sqi_thd0; + + /* 0x0000177c reg1503 */ + struct { + RK_U32 cime_sad_pu64_th : 12; + RK_U32 reserved : 4; + RK_U32 move_lambda : 4; + RK_U32 reserved1 : 12; + } fme_sqi_thd1; + + /* 0x1780 - 0x17fc */ + RK_U32 reserved1504_1535[32]; + + /* 0x00001800 reg1536 - 0x000018cc reg1587 */ + // struct { + // RK_U32 wgt_qp0 : 20; + // RK_U32 reserved : 12; + // } iprd_wgt_qp_hevc_0_51[52]; + RK_U32 iprd_wgt_qp_hevc_0_51[52]; + + /* 0x18d0 - 0x18fc */ + RK_U32 reserved1588_1599[12]; + + /* wgt_qp48_grpa */ + /* 0x00001900 reg1600 */ + RK_U32 rdo_wgta_qp_grpa_0_51[52]; + + /* 0x19d0 - 0x1afc */ + RK_U32 reserved1652_1727[76]; + // 0x1b00 + + struct { + RK_U32 pre_intra_cla0_m0 : 6; + RK_U32 pre_intra_cla0_m1 : 6; + RK_U32 pre_intra_cla0_m2 : 6; + RK_U32 pre_intra_cla0_m3 : 6; + RK_U32 pre_intra_cla0_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla0_B0; + + // 0x1b04 + struct { + RK_U32 pre_intra_cla0_m5 : 6; + RK_U32 pre_intra_cla0_m6 : 6; + RK_U32 pre_intra_cla0_m7 : 6; + RK_U32 pre_intra_cla0_m8 : 6; + RK_U32 pre_intra_cla0_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla0_B1; + + // 0x1b08 + struct { + RK_U32 pre_intra_cla1_m0 : 6; + RK_U32 pre_intra_cla1_m1 : 6; + RK_U32 pre_intra_cla1_m2 : 6; + RK_U32 pre_intra_cla1_m3 : 6; + RK_U32 pre_intra_cla1_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla1_B0; + + // 0x1b0c + struct { + RK_U32 pre_intra_cla1_m5 : 6; + RK_U32 pre_intra_cla1_m6 : 6; + RK_U32 pre_intra_cla1_m7 : 6; + RK_U32 pre_intra_cla1_m8 : 6; + RK_U32 pre_intra_cla1_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla1_B1; + + // 0x1b10 + // 0x0320 + struct { + RK_U32 pre_intra_cla2_m0 : 6; + RK_U32 pre_intra_cla2_m1 : 6; + RK_U32 pre_intra_cla2_m2 : 6; + RK_U32 pre_intra_cla2_m3 : 6; + RK_U32 pre_intra_cla2_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla2_B0; + + // 0x1b14 + struct { + RK_U32 pre_intra_cla2_m5 : 6; + RK_U32 pre_intra_cla2_m6 : 6; + RK_U32 pre_intra_cla2_m7 : 6; + RK_U32 pre_intra_cla2_m8 : 6; + RK_U32 pre_intra_cla2_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla2_B1; + + // 0x1b18 + struct { + RK_U32 pre_intra_cla3_m0 : 6; + RK_U32 pre_intra_cla3_m1 : 6; + RK_U32 pre_intra_cla3_m2 : 6; + RK_U32 pre_intra_cla3_m3 : 6; + RK_U32 pre_intra_cla3_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla3_B0; + + // 0x1b1c + struct { + RK_U32 pre_intra_cla3_m5 : 6; + RK_U32 pre_intra_cla3_m6 : 6; + RK_U32 pre_intra_cla3_m7 : 6; + RK_U32 pre_intra_cla3_m8 : 6; + RK_U32 pre_intra_cla3_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla3_B1; + + // 0x1b20 + struct { + RK_U32 pre_intra_cla4_m0 : 6; + RK_U32 pre_intra_cla4_m1 : 6; + RK_U32 pre_intra_cla4_m2 : 6; + RK_U32 pre_intra_cla4_m3 : 6; + RK_U32 pre_intra_cla4_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla4_B0; + + // 0x1b24 + struct { + RK_U32 pre_intra_cla4_m5 : 6; + RK_U32 pre_intra_cla4_m6 : 6; + RK_U32 pre_intra_cla4_m7 : 6; + RK_U32 pre_intra_cla4_m8 : 6; + RK_U32 pre_intra_cla4_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla4_B1; + + // 0x1b28 + struct { + RK_U32 pre_intra_cla5_m0 : 6; + RK_U32 pre_intra_cla5_m1 : 6; + RK_U32 pre_intra_cla5_m2 : 6; + RK_U32 pre_intra_cla5_m3 : 6; + RK_U32 pre_intra_cla5_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla5_B0; + + // 0x1b2c + struct { + RK_U32 pre_intra_cla5_m5 : 6; + RK_U32 pre_intra_cla5_m6 : 6; + RK_U32 pre_intra_cla5_m7 : 6; + RK_U32 pre_intra_cla5_m8 : 6; + RK_U32 pre_intra_cla5_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla5_B1; + + // 0x1b30 + struct { + RK_U32 pre_intra_cla6_m0 : 6; + RK_U32 pre_intra_cla6_m1 : 6; + RK_U32 pre_intra_cla6_m2 : 6; + RK_U32 pre_intra_cla6_m3 : 6; + RK_U32 pre_intra_cla6_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla6_B0; + + // 0x1b34 + struct { + RK_U32 pre_intra_cla6_m5 : 6; + RK_U32 pre_intra_cla6_m6 : 6; + RK_U32 pre_intra_cla6_m7 : 6; + RK_U32 pre_intra_cla6_m8 : 6; + RK_U32 pre_intra_cla6_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla6_B1; + + // 0x1b38 + struct { + RK_U32 pre_intra_cla7_m0 : 6; + RK_U32 pre_intra_cla7_m1 : 6; + RK_U32 pre_intra_cla7_m2 : 6; + RK_U32 pre_intra_cla7_m3 : 6; + RK_U32 pre_intra_cla7_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla7_B0; + + // 0x1b3c + struct { + RK_U32 pre_intra_cla7_m5 : 6; + RK_U32 pre_intra_cla7_m6 : 6; + RK_U32 pre_intra_cla7_m7 : 6; + RK_U32 pre_intra_cla7_m8 : 6; + RK_U32 pre_intra_cla7_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla7_B1; + + // 0x1b40 + struct { + RK_U32 pre_intra_cla8_m0 : 6; + RK_U32 pre_intra_cla8_m1 : 6; + RK_U32 pre_intra_cla8_m2 : 6; + RK_U32 pre_intra_cla8_m3 : 6; + RK_U32 pre_intra_cla8_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla8_B0; + + // 0x1b44 + struct { + RK_U32 pre_intra_cla8_m5 : 6; + RK_U32 pre_intra_cla8_m6 : 6; + RK_U32 pre_intra_cla8_m7 : 6; + RK_U32 pre_intra_cla8_m8 : 6; + RK_U32 pre_intra_cla8_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla8_B1; + + // 0x1b48 + struct { + RK_U32 pre_intra_cla9_m0 : 6; + RK_U32 pre_intra_cla9_m1 : 6; + RK_U32 pre_intra_cla9_m2 : 6; + RK_U32 pre_intra_cla9_m3 : 6; + RK_U32 pre_intra_cla9_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla9_B0; + + // 0x1b4c + struct { + RK_U32 pre_intra_cla9_m5 : 6; + RK_U32 pre_intra_cla9_m6 : 6; + RK_U32 pre_intra_cla9_m7 : 6; + RK_U32 pre_intra_cla9_m8 : 6; + RK_U32 pre_intra_cla9_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla9_B1; + + // 0x1b50 + struct { + RK_U32 pre_intra_cla10_m0 : 6; + RK_U32 pre_intra_cla10_m1 : 6; + RK_U32 pre_intra_cla10_m2 : 6; + RK_U32 pre_intra_cla10_m3 : 6; + RK_U32 pre_intra_cla10_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla10_B0; + + // 0x1b54 + struct { + RK_U32 pre_intra_cla10_m5 : 6; + RK_U32 pre_intra_cla10_m6 : 6; + RK_U32 pre_intra_cla10_m7 : 6; + RK_U32 pre_intra_cla10_m8 : 6; + RK_U32 pre_intra_cla10_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla10_B1; + + // 0x1b58 + struct { + RK_U32 pre_intra_cla11_m0 : 6; + RK_U32 pre_intra_cla11_m1 : 6; + RK_U32 pre_intra_cla11_m2 : 6; + RK_U32 pre_intra_cla11_m3 : 6; + RK_U32 pre_intra_cla11_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla11_B0; + + // 0x1b5c + struct { + RK_U32 pre_intra_cla11_m5 : 6; + RK_U32 pre_intra_cla11_m6 : 6; + RK_U32 pre_intra_cla11_m7 : 6; + RK_U32 pre_intra_cla11_m8 : 6; + RK_U32 pre_intra_cla11_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla11_B1; + + // 0x1b60 + struct { + RK_U32 pre_intra_cla12_m0 : 6; + RK_U32 pre_intra_cla12_m1 : 6; + RK_U32 pre_intra_cla12_m2 : 6; + RK_U32 pre_intra_cla12_m3 : 6; + RK_U32 pre_intra_cla12_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla12_B0; + + // 0x1b64 + struct { + RK_U32 pre_intra_cla12_m5 : 6; + RK_U32 pre_intra_cla12_m6 : 6; + RK_U32 pre_intra_cla12_m7 : 6; + RK_U32 pre_intra_cla12_m8 : 6; + RK_U32 pre_intra_cla12_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla12_B1; + + // 0x1b68 + struct { + RK_U32 pre_intra_cla13_m0 : 6; + RK_U32 pre_intra_cla13_m1 : 6; + RK_U32 pre_intra_cla13_m2 : 6; + RK_U32 pre_intra_cla13_m3 : 6; + RK_U32 pre_intra_cla13_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla13_B0; + + // 0x1b6c + struct { + RK_U32 pre_intra_cla13_m5 : 6; + RK_U32 pre_intra_cla13_m6 : 6; + RK_U32 pre_intra_cla13_m7 : 6; + RK_U32 pre_intra_cla13_m8 : 6; + RK_U32 pre_intra_cla13_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla13_B1; + + // 0x1b70 + struct { + RK_U32 pre_intra_cla14_m0 : 6; + RK_U32 pre_intra_cla14_m1 : 6; + RK_U32 pre_intra_cla14_m2 : 6; + RK_U32 pre_intra_cla14_m3 : 6; + RK_U32 pre_intra_cla14_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla14_B0; + + // 0x1b74 + struct { + RK_U32 pre_intra_cla14_m5 : 6; + RK_U32 pre_intra_cla14_m6 : 6; + RK_U32 pre_intra_cla14_m7 : 6; + RK_U32 pre_intra_cla14_m8 : 6; + RK_U32 pre_intra_cla14_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla14_B1; + + // 0x1b78 + struct { + RK_U32 pre_intra_cla15_m0 : 6; + RK_U32 pre_intra_cla15_m1 : 6; + RK_U32 pre_intra_cla15_m2 : 6; + RK_U32 pre_intra_cla15_m3 : 6; + RK_U32 pre_intra_cla15_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla15_B0; + + // 0x1b7c + struct { + RK_U32 pre_intra_cla15_m5 : 6; + RK_U32 pre_intra_cla15_m6 : 6; + RK_U32 pre_intra_cla15_m7 : 6; + RK_U32 pre_intra_cla15_m8 : 6; + RK_U32 pre_intra_cla15_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla15_B1; + + // 0x1b80 + struct { + RK_U32 pre_intra_cla16_m0 : 6; + RK_U32 pre_intra_cla16_m1 : 6; + RK_U32 pre_intra_cla16_m2 : 6; + RK_U32 pre_intra_cla16_m3 : 6; + RK_U32 pre_intra_cla16_m4 : 6; + RK_U32 reserved : 2; + } pre_intra_cla16_B0; + + // 0x1b84 + struct { + RK_U32 pre_intra_cla16_m5 : 6; + RK_U32 pre_intra_cla16_m6 : 6; + RK_U32 pre_intra_cla16_m7 : 6; + RK_U32 pre_intra_cla16_m8 : 6; + RK_U32 pre_intra_cla16_m9 : 6; + RK_U32 reserved : 2; + } pre_intra_cla16_B1; + + /* 0x1b88 - 0x1bfc */ + RK_U32 reserved1762_1791[30]; + + /* 0x00001c00 reg1792 */ + struct { + RK_U32 intra_l16_sobel_t0 : 12; + RK_U32 reserved : 4; + RK_U32 intra_l16_sobel_t1 : 12; + RK_U32 reserved1 : 4; + } i16_sobel_t; + + /* 0x00001c04 reg1793 */ + struct { + RK_U32 intra_l16_sobel_a0_qp0 : 6; + RK_U32 intra_l16_sobel_a0_qp1 : 6; + RK_U32 intra_l16_sobel_a0_qp2 : 6; + RK_U32 intra_l16_sobel_a0_qp3 : 6; + RK_U32 intra_l16_sobel_a0_qp4 : 6; + RK_U32 reserved : 2; + } i16_sobel_a_00; + + /* 0x00001c08 reg1794 */ + struct { + RK_U32 intra_l16_sobel_a0_qp5 : 6; + RK_U32 intra_l16_sobel_a0_qp6 : 6; + RK_U32 intra_l16_sobel_a0_qp7 : 6; + RK_U32 intra_l16_sobel_a0_qp8 : 6; + RK_U32 reserved : 8; + } i16_sobel_a_01; + + /* 0x00001c0c reg1795 */ + struct { + RK_U32 intra_l16_sobel_b0_qp0 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_b0_qp1 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_00; + + /* 0x00001c10 reg1796 */ + struct { + RK_U32 intra_l16_sobel_b0_qp2 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_b0_qp3 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_01; + + /* 0x00001c14 reg1797 */ + struct { + RK_U32 intra_l16_sobel_b0_qp4 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_b0_qp5 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_02; + + /* 0x00001c18 reg1798 */ + struct { + RK_U32 intra_l16_sobel_b0_qp6 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_b0_qp7 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_b_03; + + /* 0x00001c1c reg1799 */ + struct { + RK_U32 intra_l16_sobel_b0_qp8 : 15; + RK_U32 reserved : 17; + } i16_sobel_b_04; + + /* 0x00001c20 reg1800 */ + struct { + RK_U32 intra_l16_sobel_c0_qp0 : 6; + RK_U32 intra_l16_sobel_c0_qp1 : 6; + RK_U32 intra_l16_sobel_c0_qp2 : 6; + RK_U32 intra_l16_sobel_c0_qp3 : 6; + RK_U32 intra_l16_sobel_c0_qp4 : 6; + RK_U32 reserved : 2; + } i16_sobel_c_00; + + /* 0x00001c24 reg1801 */ + struct { + RK_U32 intra_l16_sobel_c0_qp5 : 6; + RK_U32 intra_l16_sobel_c0_qp6 : 6; + RK_U32 intra_l16_sobel_c0_qp7 : 6; + RK_U32 intra_l16_sobel_c0_qp8 : 6; + RK_U32 reserved : 8; + } i16_sobel_c_01; + + /* 0x00001c28 reg1802 */ + struct { + RK_U32 intra_l16_sobel_d0_qp0 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_d0_qp1 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_00; + + /* 0x00001c2c reg1803 */ + struct { + RK_U32 intra_l16_sobel_d0_qp2 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_d0_qp3 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_01; + + /* 0x00001c30 reg1804 */ + struct { + RK_U32 intra_l16_sobel_d0_qp4 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_d0_qp5 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_02; + + /* 0x00001c34 reg1805 */ + struct { + RK_U32 intra_l16_sobel_d0_qp6 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l16_sobel_d0_qp7 : 15; + RK_U32 reserved1 : 1; + } i16_sobel_d_03; + + /* 0x00001c38 reg1806 */ + struct { + RK_U32 intra_l16_sobel_d0_qp8 : 15; + RK_U32 reserved : 17; + } i16_sobel_d_04; + + /* 0x00001c3c reg1807 */ + RK_U32 intra_l16_sobel_e0_qp0_low; + + /* 0x00001c40 reg1808 */ + struct { + RK_U32 intra_l16_sobel_e0_qp0_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_01; + + /* 0x00001c44 reg1809 */ + RK_U32 intra_l16_sobel_e0_qp1_low; + + /* 0x00001c48 reg1810 */ + struct { + RK_U32 intra_l16_sobel_e0_qp1_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_03; + + /* 0x00001c4c reg1811 */ + RK_U32 intra_l16_sobel_e0_qp2_low; + + /* 0x00001c50 reg1812 */ + struct { + RK_U32 intra_l16_sobel_e0_qp2_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_05; + + /* 0x00001c54 reg1813 */ + RK_U32 intra_l16_sobel_e0_qp3_low; + + /* 0x00001c58 reg1814 */ + struct { + RK_U32 intra_l16_sobel_e0_qp3_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_07; + + /* 0x00001c5c reg1815 */ + RK_U32 intra_l16_sobel_e0_qp4_low; + + /* 0x00001c60 reg1816 */ + struct { + RK_U32 intra_l16_sobel_e0_qp4_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_09; + + /* 0x00001c64 reg1817 */ + RK_U32 intra_l16_sobel_e0_qp5_low; + + /* 0x00001c68 reg1818 */ + struct { + RK_U32 intra_l16_sobel_e0_qp5_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_11; + + /* 0x00001c6c reg1819 */ + RK_U32 intra_l16_sobel_e0_qp6_low; + + /* 0x00001c70 reg1820 */ + struct { + RK_U32 intra_l16_sobel_e0_qp6_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_13; + + /* 0x00001c74 reg1821 */ + RK_U32 intra_l16_sobel_e0_qp7_low; + + /* 0x00001c78 reg1822 */ + struct { + RK_U32 intra_l16_sobel_e0_qp7_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_15; + + /* 0x00001c7c reg1823 */ + RK_U32 intra_l16_sobel_e0_qp8_low; + + /* 0x00001c80 reg1824 */ + struct { + RK_U32 intra_l16_sobel_e0_qp8_high : 2; + RK_U32 reserved : 30; + } i16_sobel_e_17; + + /* 0x00001c84 reg1825 */ + struct { + RK_U32 intra_l32_sobel_t2 : 12; + RK_U32 reserved : 4; + RK_U32 intra_l32_sobel_t3 : 12; + RK_U32 reserved1 : 4; + } i32_sobel_t_00; + + /* 0x00001c88 reg1826 */ + struct { + RK_U32 intra_l32_sobel_t4 : 6; + RK_U32 reserved : 26; + } i32_sobel_t_01; + + /* 0x00001c8c reg1827 */ + struct { + RK_U32 intra_l32_sobel_t5 : 12; + RK_U32 reserved : 4; + RK_U32 intra_l32_sobel_t6 : 12; + RK_U32 reserved1 : 4; + } i32_sobel_t_02; + + /* 0x00001c90 reg1828 */ + struct { + RK_U32 intra_l32_sobel_a1_qp0 : 6; + RK_U32 intra_l32_sobel_a1_qp1 : 6; + RK_U32 intra_l32_sobel_a1_qp2 : 6; + RK_U32 intra_l32_sobel_a1_qp3 : 6; + RK_U32 intra_l32_sobel_a1_qp4 : 6; + RK_U32 reserved : 2; + } i32_sobel_a; + + /* 0x00001c94 reg1829 */ + struct { + RK_U32 intra_l32_sobel_b1_qp0 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l32_sobel_b1_qp1 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_b_00; + + /* 0x00001c98 reg1830 */ + struct { + RK_U32 intra_l32_sobel_b1_qp2 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l32_sobel_b1_qp3 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_b_01; + + /* 0x00001c9c reg1831 */ + struct { + RK_U32 intra_l32_sobel_b1_qp4 : 15; + RK_U32 reserved : 17; + } i32_sobel_b_02; + + /* 0x00001ca0 reg1832 */ + struct { + RK_U32 intra_l32_sobel_c1_qp0 : 6; + RK_U32 intra_l32_sobel_c1_qp1 : 6; + RK_U32 intra_l32_sobel_c1_qp2 : 6; + RK_U32 intra_l32_sobel_c1_qp3 : 6; + RK_U32 intra_l32_sobel_c1_qp4 : 6; + RK_U32 reserved : 2; + } i32_sobel_c; + + /* 0x00001ca4 reg1833 */ + struct { + RK_U32 intra_l32_sobel_d1_qp0 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l32_sobel_d1_qp1 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_d_00; + + /* 0x00001ca8 reg1834 */ + struct { + RK_U32 intra_l32_sobel_d1_qp2 : 15; + RK_U32 reserved : 1; + RK_U32 intra_l32_sobel_d1_qp3 : 15; + RK_U32 reserved1 : 1; + } i32_sobel_d_01; + + /* 0x00001cac reg1835 */ + struct { + RK_U32 intra_l32_sobel_d1_qp4 : 15; + RK_U32 reserved : 17; + } i32_sobel_d_02; + + /* 0x00001cb0 reg1836 */ + RK_U32 intra_l32_sobel_e1_qp0_low; + + /* 0x00001cb4 reg1837 */ + struct { + RK_U32 intra_l32_sobel_e1_qp0_high : 9; + RK_U32 reserved : 23; + } i32_sobel_e_01; + + /* 0x00001cb8 reg1838 */ + RK_U32 intra_l32_sobel_e1_qp1_low; + + /* 0x00001cbc reg1839 */ + struct { + RK_U32 intra_l32_sobel_e1_qp1_high : 9; + RK_U32 reserved : 23; + } i32_sobel_e_03; + + /* 0x00001cc0 reg1840 */ + RK_U32 intra_l32_sobel_e1_qp2_low; + + /* 0x00001cc4 reg1841 */ + struct { + RK_U32 intra_l32_sobel_e1_qp2_high : 9; + RK_U32 reserved : 23; + } i32_sobel_e_05; + + /* 0x00001cc8 reg1842 */ + RK_U32 intra_l32_sobel_e1_qp3_low; + + /* 0x00001ccc reg1843 */ + struct { + RK_U32 intra_l32_sobel_e1_qp3_high : 9; + RK_U32 reserved : 23; + } i32_sobel_e_07; + + /* 0x00001cd0 reg1844 */ + RK_U32 intra_l32_sobel_e1_qp4_low; + + /* 0x00001cd4 reg1845 */ + struct { + RK_U32 intra_l32_sobel_e1_qp4_high : 9; + RK_U32 reserved : 23; + } i32_sobel_e_09; +} hevc_vepu580_wgt; + +typedef struct { + struct { + RK_U32 cu_rdo_cime_thd0 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b_cime_thd0; + + struct { + RK_U32 cu_rdo_cime_thd2 : 12; + RK_U32 reserved : 20; + } rdo_b_cime_thd1; + + struct { + RK_U32 cu_rdo_var_thd00 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd01 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd0; + + struct { + RK_U32 cu_rdo_var_thd10 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd1; + + struct { + RK_U32 cu_rdo_var_thd20 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd2; + + struct { + RK_U32 cu_rdo_var_thd30 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd3; + + struct { + RK_U32 cu_rdo_atf_wgt00 : 8; + RK_U32 cu_rdo_atf_wgt01 : 8; + RK_U32 cu_rdo_atf_wgt02 : 8; + RK_U32 reserved : 8; + } rdo_b_atf_wgt0; + + struct { + RK_U32 cu_rdo_atf_wgt10 : 8; + RK_U32 cu_rdo_atf_wgt11 : 8; + RK_U32 cu_rdo_atf_wgt12 : 8; + RK_U32 reserved : 8; + } rdo_b_atf_wgt1; + + struct { + RK_U32 cu_rdo_atf_wgt20 : 8; + RK_U32 cu_rdo_atf_wgt21 : 8; + RK_U32 cu_rdo_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b_atf_wgt2; + + struct { + RK_U32 cu_rdo_atf_wgt30 : 8; + RK_U32 cu_rdo_atf_wgt31 : 8; + RK_U32 cu_rdo_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b_atf_wgt3; +} RdoAtfCfg; + + +typedef struct { + struct { + RK_U32 cu_rdo_cime_thd0 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_cime_thd1 : 12; + RK_U32 reserved1 : 4; + } rdo_b_cime_thd0; + + struct { + RK_U32 cu_rdo_cime_thd2 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_cime_thd3 : 12; + RK_U32 reserved1 : 4; + } rdo_b_cime_thd1; + + struct { + RK_U32 cu_rdo_var_thd10 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd11 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd0; + + struct { + RK_U32 cu_rdo_var_thd20 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd21 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd1; + + struct { + RK_U32 cu_rdo_var_thd30 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd31 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd2; + + struct { + RK_U32 cu_rdo_var_thd40 : 12; + RK_U32 reserved0 : 4; + RK_U32 cu_rdo_var_thd41 : 12; + RK_U32 reserved1 : 4; + } rdo_b_var_thd3; + + struct { + RK_U32 cu_rdo_atf_wgt00 : 8; + RK_U32 cu_rdo_atf_wgt10 : 8; + RK_U32 cu_rdo_atf_wgt11 : 8; + RK_U32 cu_rdo_atf_wgt12 : 8; + } rdo_b_atf_wgt0; + + struct { + RK_U32 cu_rdo_atf_wgt20 : 8; + RK_U32 cu_rdo_atf_wgt21 : 8; + RK_U32 cu_rdo_atf_wgt22 : 8; + RK_U32 reserved : 8; + } rdo_b_atf_wgt1; + + struct { + RK_U32 cu_rdo_atf_wgt30 : 8; + RK_U32 cu_rdo_atf_wgt31 : 8; + RK_U32 cu_rdo_atf_wgt32 : 8; + RK_U32 reserved : 8; + } rdo_b_atf_wgt2; + + struct { + RK_U32 cu_rdo_atf_wgt40 : 8; + RK_U32 cu_rdo_atf_wgt41 : 8; + RK_U32 cu_rdo_atf_wgt42 : 8; + RK_U32 reserved : 8; + } rdo_b_atf_wgt3; +} RdoAtfSkipCfg; + +/* class: rdo/q_i */ +/* 0x00002000 reg2048 - 0x00002c98 reg2854 */ +typedef struct Vepu580RdoCfg_t { + /* 0x00002000 reg2048 */ + struct { + RK_U32 rdo_segment_en : 1; + RK_U32 rdo_smear_en : 1; + RK_U32 reserved : 30; + } rdo_sqi_cfg; + // 0x2004 - 0x2028 start VEPU_RDO_B64_INTER_CIME_THD0 + RdoAtfCfg rdo_b64_inter_atf; + // 0x202c - 0x2050 + RdoAtfSkipCfg rdo_b64_skip_atf; + // 0x2054 - 0x2078 + RdoAtfCfg rdo_b32_intra_atf; + // 0x207c - 0x20a0 + RdoAtfCfg rdo_b32_inter_atf; + // 0x20a4 - 0x20c8 + RdoAtfSkipCfg rdo_b32_skip_atf; + // 0x20cc - 0x20f0 + RdoAtfCfg rdo_b16_intra_atf; + // 0x20f4 - 0x2118 + RdoAtfCfg rdo_b16_inter_atf; + // 0x211c - 0x2140 + RdoAtfSkipCfg rdo_b16_skip_atf; + // 0x2144 - 0x2168 + RdoAtfCfg rdo_b8_intra_atf; + // 0x216c - 0x2190 + RdoAtfCfg rdo_b8_inter_atf; + // 0x2194 - 0x21b8 + RdoAtfSkipCfg rdo_b8_skip_atf; + + /* 0x000021bc reg2159 */ + struct { + RK_U32 rdo_segment_cu64_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu64_th1 : 12; + RK_U32 reserved1 : 4; + } rdo_segment_b64_thd0; + + /* 0x000021c0 reg2160 */ + struct { + RK_U32 rdo_segment_cu64_th2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu64_th3 : 4; + RK_U32 rdo_segment_cu64_th4 : 4; + RK_U32 rdo_segment_cu64_th5_minus1 : 4; + RK_U32 rdo_segment_cu64_th6_minus1 : 4; + } rdo_segment_b64_thd1; + + /* 0x000021c4 reg2161 */ + struct { + RK_U32 rdo_segment_cu32_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu32_th1 : 12; + RK_U32 reserved1 : 4; + } rdo_segment_b32_thd0; + + /* 0x000021c8 reg2162 */ + struct { + RK_U32 rdo_segment_cu32_th2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_segment_cu32_th3 : 2; + RK_U32 reserved1 : 2; + RK_U32 rdo_segment_cu32_th4 : 2; + RK_U32 reserved2 : 2; + RK_U32 rdo_segment_cu32_th5_minus1 : 2; + RK_U32 reserved3 : 2; + RK_U32 rdo_segment_cu32_th6_minus1 : 2; + RK_U32 reserved4 : 2; + } rdo_segment_b32_thd1; + + /* 0x000021cc reg2163 */ + struct { + RK_U32 rdo_segment_cu64_multi : 8; + RK_U32 rdo_segment_cu32_multi : 8; + RK_U32 rdo_smear_cu16_multi : 8; + RK_U32 reserved : 8; + } rdo_segment_multi; + + /* 0x000021d0 reg2164 */ + struct { + RK_U32 rdo_smear_cu16_cime_sad_th0 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cu16_cime_sad_th1 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_smear_thd0; + + /* 0x000021d4 reg2165 */ + struct { + RK_U32 rdo_smear_cu16_cime_sad_th2 : 12; + RK_U32 reserved : 4; + RK_U32 rdo_smear_cu16_cime_sad_th3 : 12; + RK_U32 reserved1 : 4; + } rdo_b16_smear_thd1; + + /* 0x000021d8 reg2166 */ + struct { + RK_U32 pre_intra32_cst_var_th00 : 12; + RK_U32 reserved : 4; + RK_U32 pre_intra32_cst_var_th01 : 12; + RK_U32 reserved1 : 1; + RK_U32 pre_intra32_mode_th : 3; + } preintra_b32_cst_var_thd; + + /* 0x000021dc reg2167 */ + struct { + RK_U32 pre_intra32_cst_wgt00 : 8; + RK_U32 reserved : 8; + RK_U32 pre_intra32_cst_wgt01 : 8; + RK_U32 reserved1 : 8; + } preintra_b32_cst_wgt; + + /* 0x000021e0 reg2168 */ + struct { + RK_U32 pre_intra16_cst_var_th00 : 12; + RK_U32 reserved : 4; + RK_U32 pre_intra16_cst_var_th01 : 12; + RK_U32 reserved1 : 1; + RK_U32 pre_intra16_mode_th : 3; + } preintra_b16_cst_var_thd; + + /* 0x000021e4 reg2169 */ + struct { + RK_U32 pre_intra16_cst_wgt00 : 8; + RK_U32 reserved : 8; + RK_U32 pre_intra16_cst_wgt01 : 8; + RK_U32 reserved1 : 8; + } preintra_b16_cst_wgt; + + RK_U32 reserved_0x21e8_0x21fc[6]; + + // 0x2200 ~ 0x2c94 + RK_U32 scaling_list_reg[678]; /* total number really: 678 */ + // 0x2c98 + RK_U32 scal_cfg_reg; +} vepu580_rdo_cfg; + +/* class: osd */ +/* 0x00003000 reg3072 - 0x00003084 reg3105*/ +typedef struct Vepu580OsdCfg_t { + /* 0x00003000 reg3072 */ + struct { + RK_U32 osd_lu_inv_en : 8; + RK_U32 osd_ch_inv_en : 8; + RK_U32 osd_lu_inv_msk : 8; + RK_U32 osd_ch_inv_msk : 8; + } osd_inv_en; + + /* 0x00003004 reg3073 */ + struct { + RK_U32 osd_ithd_r0 : 4; + RK_U32 osd_ithd_r1 : 4; + RK_U32 osd_ithd_r2 : 4; + RK_U32 osd_ithd_r3 : 4; + RK_U32 osd_ithd_r4 : 4; + RK_U32 osd_ithd_r5 : 4; + RK_U32 osd_ithd_r6 : 4; + RK_U32 osd_ithd_r7 : 4; + } osd_inv_thd; + + /* 0x00003008 reg3074 */ + struct { + RK_U32 osd_en : 8; + RK_U32 osd_itype : 8; + RK_U32 osd_plt_cks : 1; + RK_U32 osd_plt_typ : 1; + RK_U32 reserved : 14; + } osd_cfg; + + /* 0x300c */ + RK_U32 reserved_3075; + + /* 0x00003010 reg3076 */ + struct { + RK_U32 osd0_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd0_lt_y : 10; + RK_U32 reserved1 : 6; + } osd0_lt_pos; + + /* 0x00003014 reg3077 */ + struct { + RK_U32 osd0_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd0_rb_y : 10; + RK_U32 reserved1 : 6; + } osd0_rb_pos; + + /* 0x00003018 reg3078 */ + struct { + RK_U32 osd1_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd1_lt_y : 10; + RK_U32 reserved1 : 6; + } osd1_lt_pos; + + /* 0x0000301c reg3079 */ + struct { + RK_U32 osd1_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd1_rb_y : 10; + RK_U32 reserved1 : 6; + } osd1_rb_pos; + + /* 0x00003020 reg3080 */ + struct { + RK_U32 osd2_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd2_lt_y : 10; + RK_U32 reserved1 : 6; + } osd2_lt_pos; + + /* 0x00003024 reg3081 */ + struct { + RK_U32 osd2_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd2_rb_y : 10; + RK_U32 reserved1 : 6; + } osd2_rb_pos; + + /* 0x00003028 reg3082 */ + struct { + RK_U32 osd3_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd3_lt_y : 10; + RK_U32 reserved1 : 6; + } osd3_lt_pos; + + /* 0x0000302c reg3083 */ + struct { + RK_U32 osd3_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd3_rb_y : 10; + RK_U32 reserved1 : 6; + } osd3_rb_pos; + + /* 0x00003030 reg3084 */ + struct { + RK_U32 osd4_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd4_lt_y : 10; + RK_U32 reserved1 : 6; + } osd4_lt_pos; + + /* 0x00003034 reg3085 */ + struct { + RK_U32 osd4_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd4_rb_y : 10; + RK_U32 reserved1 : 6; + } osd4_rb_pos; + + /* 0x00003038 reg3086 */ + struct { + RK_U32 osd5_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd5_lt_y : 10; + RK_U32 reserved1 : 6; + } osd5_lt_pos; + + /* 0x0000303c reg3087 */ + struct { + RK_U32 osd5_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd5_rb_y : 10; + RK_U32 reserved1 : 6; + } osd5_rb_pos; + + /* 0x00003040 reg3088 */ + struct { + RK_U32 osd6_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd6_lt_y : 10; + RK_U32 reserved1 : 6; + } osd6_lt_pos; + + /* 0x00003044 reg3089 */ + struct { + RK_U32 osd6_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd6_rb_y : 10; + RK_U32 reserved1 : 6; + } osd6_rb_pos; + + /* 0x00003048 reg3090 */ + struct { + RK_U32 osd7_lt_x : 10; + RK_U32 reserved : 6; + RK_U32 osd7_lt_y : 10; + RK_U32 reserved1 : 6; + } osd7_lt_pos; + + /* 0x0000304c reg3091 */ + struct { + RK_U32 osd7_rb_x : 10; + RK_U32 reserved : 6; + RK_U32 osd7_rb_y : 10; + RK_U32 reserved1 : 6; + } osd7_rb_pos; + + /* 0x00003050 reg3092 */ + RK_U32 osd0_addr; + + /* 0x00003054 reg3093 */ + RK_U32 osd1_addr; + + /* 0x00003058 reg3094 */ + RK_U32 osd2_addr; + + /* 0x0000305c reg3095 */ + RK_U32 osd3_addr; + + /* 0x00003060 reg3096 */ + RK_U32 osd4_addr; + + /* 0x00003064 reg3097 */ + RK_U32 osd5_addr; + + /* 0x00003068 reg3098 */ + RK_U32 osd6_addr; + + /* 0x0000306c reg3099 */ + RK_U32 osd7_addr; + + /* 0x3070 - 0x307c */ + RK_U32 reserved3100_3103[4]; + /* 0x03080-0x347c reg3104-reg3360 */ + RK_U32 plt[256]; +} vepu580_osd_cfg; + +/* class: st */ +/* 0x00004000 reg4096 - 0x000042cc reg4275 */ +typedef struct Vepu580Status_t { + /* 0x00004000 reg4096 */ + RK_U32 bs_lgth_l32; + + /* 0x00004004 reg4097 */ + struct { + RK_U32 bs_lgth_h8 : 8; + RK_U32 reserved : 8; + RK_U32 sse_l16 : 16; + } st_sse_bsl; + + /* 0x00004008 reg4098 */ + RK_U32 sse_h32; + + /* 0x0000400c reg4099 */ + RK_U32 qp_sum; + + /* 0x00004010 reg4100 */ + struct { + RK_U32 sao_cnum : 16; + RK_U32 sao_ynum : 16; + } st_sao; + + /* 0x00004014 reg4101 */ + RK_U32 rdo_head_bits; + + /* 0x00004018 reg4102 */ + struct { + RK_U32 rdo_head_bits_h8 : 8; + RK_U32 reserved : 8; + RK_U32 rdo_res_bits_l16 : 16; + } st_head_res_bl; + + /* 0x0000401c reg4103 */ + RK_U32 rdo_res_bits_h24; + + /* 0x00004020 reg4104 */ + struct { + RK_U32 st_enc : 2; + RK_U32 st_sclr : 1; + RK_U32 reserved : 29; + } st_enc; + + /* 0x00004024 reg4105 */ + struct { + RK_U32 fnum_cfg_done : 8; + RK_U32 fnum_cfg : 8; + RK_U32 fnum_int : 8; + RK_U32 fnum_enc_done : 8; + } st_lkt; + + /* 0x00004028 reg4106 */ + RK_U32 node_addr; + + /* 0x0000402c reg4107 */ + struct { + RK_U32 bsbw_ovfl : 1; + RK_U32 reserved : 2; + RK_U32 bsbw_addr : 28; + RK_U32 reserved1 : 1; + } st_bsb; + + /* 0x00004030 reg4108 */ + struct { + RK_U32 axib_idl : 8; + RK_U32 axib_ovfl : 8; + RK_U32 axib_err : 8; + RK_U32 axir_err : 7; + RK_U32 reserved : 1; + } st_bus; + + /* 0x00004034 reg4109 */ + struct { + RK_U32 sli_num : 6; + RK_U32 reserved : 26; + } st_snum; + + /* 0x00004038 reg4110 */ + struct { + RK_U32 sli_len : 25; + RK_U32 reserved : 7; + } st_slen; + + /* 0x403c - 0x40fc */ + RK_U32 reserved4111_4159[49]; + + /* 0x00004100 reg4160 */ + struct { + RK_U32 pnum_p64 : 17; + RK_U32 reserved : 15; + } st_pnum_p64; + + /* 0x00004104 reg4161 */ + struct { + RK_U32 pnum_p32 : 19; + RK_U32 reserved : 13; + } st_pnum_p32; + + /* 0x00004108 reg4162 */ + struct { + RK_U32 pnum_p16 : 21; + RK_U32 reserved : 11; + } st_pnum_p16; + + /* 0x0000410c reg4163 */ + struct { + RK_U32 pnum_p8 : 23; + RK_U32 reserved : 9; + } st_pnum_p8; + + /* 0x00004110 reg4164 */ + struct { + RK_U32 pnum_i32 : 19; + RK_U32 reserved : 13; + } st_pnum_i32; + + /* 0x00004114 reg4165 */ + struct { + RK_U32 pnum_i16 : 21; + RK_U32 reserved : 11; + } st_pnum_i16; + + /* 0x00004118 reg4166 */ + struct { + RK_U32 pnum_i8 : 23; + RK_U32 reserved : 9; + } st_pnum_i8; + + /* 0x0000411c reg4167 */ + struct { + RK_U32 pnum_i4 : 23; + RK_U32 reserved : 9; + } st_pnum_i4; + + /* 0x00004120 reg4168 */ + RK_U32 madp; + + /* 0x00004124 reg4169 */ + struct { + RK_U32 num_ctu : 21; + RK_U32 reserved : 11; + } st_bnum_cme; + + /* 0x00004128 reg4170 */ + RK_U32 madi; + + /* 0x0000412c reg4171 */ + struct { + RK_U32 num_b16 : 23; + RK_U32 reserved : 9; + } st_bnum_b16; + + /* 0x00004130 reg4172 */ + RK_U32 num_madi_max_b16; + + /* 0x00004134 reg4173 */ + RK_U32 md_sad_b16num0; + + /* 0x00004138 reg4174 */ + RK_U32 md_sad_b16num1; + + /* 0x0000413c reg4175 */ + RK_U32 md_sad_b16num2; + + /* 0x00004140 reg4176 */ + RK_U32 md_sad_b16num3; + + /* 0x00004144 reg4177 */ + RK_U32 madi_b16num0; + + /* 0x00004148 reg4178 */ + RK_U32 madi_b16num1; + + /* 0x0000414c reg4179 */ + RK_U32 madi_b16num2; + + /* 0x00004150 reg4180 */ + RK_U32 madi_b16num3; + + /* 0x4154 - 0x41fc */ + RK_U32 reserved4181_4223[43]; + + /* 0x00004200 reg4224 */ + struct { + RK_U32 b8num_qp0 : 22; + RK_U32 reserved : 10; + } st_b8_qp0; + + /* 0x00004204 reg4225 */ + struct { + RK_U32 b8num_qp1 : 22; + RK_U32 reserved : 10; + } st_b8_qp1; + + /* 0x00004208 reg4226 */ + struct { + RK_U32 b8num_qp2 : 22; + RK_U32 reserved : 10; + } st_b8_qp2; + + /* 0x0000420c reg4227 */ + struct { + RK_U32 b8num_qp3 : 22; + RK_U32 reserved : 10; + } st_b8_qp3; + + /* 0x00004210 reg4228 */ + struct { + RK_U32 b8num_qp4 : 22; + RK_U32 reserved : 10; + } st_b8_qp4; + + /* 0x00004214 reg4229 */ + struct { + RK_U32 b8num_qp5 : 22; + RK_U32 reserved : 10; + } st_b8_qp5; + + /* 0x00004218 reg4230 */ + struct { + RK_U32 b8num_qp6 : 22; + RK_U32 reserved : 10; + } st_b8_qp6; + + /* 0x0000421c reg4231 */ + struct { + RK_U32 b8num_qp7 : 22; + RK_U32 reserved : 10; + } st_b8_qp7; + + /* 0x00004220 reg4232 */ + struct { + RK_U32 b8num_qp8 : 22; + RK_U32 reserved : 10; + } st_b8_qp8; + + /* 0x00004224 reg4233 */ + struct { + RK_U32 b8num_qp9 : 22; + RK_U32 reserved : 10; + } st_b8_qp9; + + /* 0x00004228 reg4234 */ + struct { + RK_U32 b8num_qp10 : 22; + RK_U32 reserved : 10; + } st_b8_qp10; + + /* 0x0000422c reg4235 */ + struct { + RK_U32 b8num_qp11 : 22; + RK_U32 reserved : 10; + } st_b8_qp11; + + /* 0x00004230 reg4236 */ + struct { + RK_U32 b8num_qp12 : 22; + RK_U32 reserved : 10; + } st_b8_qp12; + + /* 0x00004234 reg4237 */ + struct { + RK_U32 b8num_qp13 : 22; + RK_U32 reserved : 10; + } st_b8_qp13; + + /* 0x00004238 reg4238 */ + struct { + RK_U32 b8num_qp14 : 22; + RK_U32 reserved : 10; + } st_b8_qp14; + + /* 0x0000423c reg4239 */ + struct { + RK_U32 b8num_qp15 : 22; + RK_U32 reserved : 10; + } st_b8_qp15; + + /* 0x00004240 reg4240 */ + struct { + RK_U32 b8num_qp16 : 22; + RK_U32 reserved : 10; + } st_b8_qp16; + + /* 0x00004244 reg4241 */ + struct { + RK_U32 b8num_qp17 : 22; + RK_U32 reserved : 10; + } st_b8_qp17; + + /* 0x00004248 reg4242 */ + struct { + RK_U32 b8num_qp18 : 22; + RK_U32 reserved : 10; + } st_b8_qp18; + + /* 0x0000424c reg4243 */ + struct { + RK_U32 b8num_qp19 : 22; + RK_U32 reserved : 10; + } st_b8_qp19; + + /* 0x00004250 reg4244 */ + struct { + RK_U32 b8num_qp20 : 22; + RK_U32 reserved : 10; + } st_b8_qp20; + + /* 0x00004254 reg4245 */ + struct { + RK_U32 b8num_qp21 : 22; + RK_U32 reserved : 10; + } st_b8_qp21; + + /* 0x00004258 reg4246 */ + struct { + RK_U32 b8num_qp22 : 22; + RK_U32 reserved : 10; + } st_b8_qp22; + + /* 0x0000425c reg4247 */ + struct { + RK_U32 b8num_qp23 : 22; + RK_U32 reserved : 10; + } st_b8_qp23; + + /* 0x00004260 reg4248 */ + struct { + RK_U32 b8num_qp24 : 22; + RK_U32 reserved : 10; + } st_b8_qp24; + + /* 0x00004264 reg4249 */ + struct { + RK_U32 b8num_qp25 : 22; + RK_U32 reserved : 10; + } st_b8_qp25; + + /* 0x00004268 reg4250 */ + struct { + RK_U32 b8num_qp26 : 22; + RK_U32 reserved : 10; + } st_b8_qp26; + + /* 0x0000426c reg4251 */ + struct { + RK_U32 b8num_qp27 : 22; + RK_U32 reserved : 10; + } st_b8_qp27; + + /* 0x00004270 reg4252 */ + struct { + RK_U32 b8num_qp28 : 22; + RK_U32 reserved : 10; + } st_b8_qp28; + + /* 0x00004274 reg4253 */ + struct { + RK_U32 b8num_qp29 : 22; + RK_U32 reserved : 10; + } st_b8_qp29; + + /* 0x00004278 reg4254 */ + struct { + RK_U32 b8num_qp30 : 22; + RK_U32 reserved : 10; + } st_b8_qp30; + + /* 0x0000427c reg4255 */ + struct { + RK_U32 b8num_qp31 : 22; + RK_U32 reserved : 10; + } st_b8_qp31; + + /* 0x00004280 reg4256 */ + struct { + RK_U32 b8num_qp32 : 22; + RK_U32 reserved : 10; + } st_b8_qp32; + + /* 0x00004284 reg4257 */ + struct { + RK_U32 b8num_qp33 : 22; + RK_U32 reserved : 10; + } st_b8_qp33; + + /* 0x00004288 reg4258 */ + struct { + RK_U32 b8num_qp34 : 22; + RK_U32 reserved : 10; + } st_b8_qp34; + + /* 0x0000428c reg4259 */ + struct { + RK_U32 b8num_qp35 : 22; + RK_U32 reserved : 10; + } st_b8_qp35; + + /* 0x00004290 reg4260 */ + struct { + RK_U32 b8num_qp36 : 22; + RK_U32 reserved : 10; + } st_b8_qp36; + + /* 0x00004294 reg4261 */ + struct { + RK_U32 b8num_qp37 : 22; + RK_U32 reserved : 10; + } st_b8_qp37; + + /* 0x00004298 reg4262 */ + struct { + RK_U32 b8num_qp38 : 22; + RK_U32 reserved : 10; + } st_b8_qp38; + + /* 0x0000429c reg4263 */ + struct { + RK_U32 b8num_qp39 : 22; + RK_U32 reserved : 10; + } st_b8_qp39; + + /* 0x000042a0 reg4264 */ + struct { + RK_U32 b8num_qp40 : 22; + RK_U32 reserved : 10; + } st_b8_qp40; + + /* 0x000042a4 reg4265 */ + struct { + RK_U32 b8num_qp41 : 22; + RK_U32 reserved : 10; + } st_b8_qp41; + + /* 0x000042a8 reg4266 */ + struct { + RK_U32 b8num_qp42 : 22; + RK_U32 reserved : 10; + } st_b8_qp42; + + /* 0x000042ac reg4267 */ + struct { + RK_U32 b8num_qp43 : 22; + RK_U32 reserved : 10; + } st_b8_qp43; + + /* 0x000042b0 reg4268 */ + struct { + RK_U32 b8num_qp44 : 22; + RK_U32 reserved : 10; + } st_b8_qp44; + + /* 0x000042b4 reg4269 */ + struct { + RK_U32 b8num_qp45 : 22; + RK_U32 reserved : 10; + } st_b8_qp45; + + /* 0x000042b8 reg4270 */ + struct { + RK_U32 b8num_qp46 : 22; + RK_U32 reserved : 10; + } st_b8_qp46; + + /* 0x000042bc reg4271 */ + struct { + RK_U32 b8num_qp47 : 22; + RK_U32 reserved : 10; + } st_b8_qp47; + + /* 0x000042c0 reg4272 */ + struct { + RK_U32 b8num_qp48 : 22; + RK_U32 reserved : 10; + } st_b8_qp48; + + /* 0x000042c4 reg4273 */ + struct { + RK_U32 b8num_qp49 : 22; + RK_U32 reserved : 10; + } st_b8_qp49; + + /* 0x000042c8 reg4274 */ + struct { + RK_U32 b8num_qp50 : 22; + RK_U32 reserved : 10; + } st_b8_qp50; + + /* 0x000042cc reg4275 */ + struct { + RK_U32 b8num_qp51 : 22; + RK_U32 reserved : 10; + } st_b8_qp51; +} vepu580Status; + +/* class: dbg/st/axipn */ +/* 0x00005000 reg5120 - 0x00005354 reg5333*/ +typedef struct Vepu580Dbg_t { + /* 0x00005000 reg5120 */ + struct { + RK_U32 pp_tout : 1; + RK_U32 cme_tout : 1; + RK_U32 swn_tout : 1; + RK_U32 rme_tout : 1; + RK_U32 fme_tout : 1; + RK_U32 rdo_tout : 1; + RK_U32 lpf_tout : 1; + RK_U32 etpy_tout : 1; + RK_U32 frm_tout : 1; + RK_U32 reserved : 23; + } st_wdg; + + /* 0x00005004 reg5121 */ + struct { + RK_U32 pp_wrk : 1; + RK_U32 cme_wrk : 1; + RK_U32 swn_wrk : 1; + RK_U32 rme_wrk : 1; + RK_U32 fme_wrk : 1; + RK_U32 rdo_wrk : 1; + RK_U32 lpf_wrk : 1; + RK_U32 etpy_wrk : 1; + RK_U32 frm_wrk : 1; + RK_U32 reserved : 23; + } st_ppl; + + /* 0x00005008 reg5122 */ + struct { + RK_U32 pp_pos_x : 16; + RK_U32 pp_pos_y : 16; + } st_ppl_pos_pp; + + /* 0x0000500c reg5123 */ + struct { + RK_U32 cme_pos_x : 16; + RK_U32 cme_pos_y : 16; + } st_ppl_pos_cme; + + /* 0x00005010 reg5124 */ + struct { + RK_U32 swin_pos_x : 16; + RK_U32 swin_pos_y : 16; + } st_ppl_pos_swin; + + /* 0x00005014 reg5125 */ + struct { + RK_U32 rme_pos_x : 16; + RK_U32 rme_pos_y : 16; + } st_ppl_pos_rme; + + /* 0x00005018 reg5126 */ + struct { + RK_U32 fme_pos_x : 16; + RK_U32 fme_pos_y : 16; + } st_ppl_pos_fme; + + /* 0x0000501c reg5127 */ + struct { + RK_U32 rdo_pos_x : 16; + RK_U32 rdo_pos_y : 16; + } st_ppl_pos_rdo; + + /* 0x00005020 reg5128 */ + struct { + RK_U32 lpf_pos_x : 16; + RK_U32 lpf_pos_y : 16; + } st_ppl_pos_lpf; + + /* 0x00005024 reg5129 */ + struct { + RK_U32 etpy_pos_x : 16; + RK_U32 etpy_pos_y : 16; + } st_ppl_pos_etpy; + + /* 0x00005028 reg5130 */ + struct { + RK_U32 sli_num : 15; + RK_U32 reserved : 17; + } st_sli_num; + + /* 0x0000502c reg5131 */ + struct { + RK_U32 lkt_err : 3; + RK_U32 reserved : 29; + } st_lkt_err; + + /* 0x5030 - 0x50fc */ + RK_U32 reserved5132_5183[52]; + + /* 0x00005100 reg5184 */ + struct { + RK_U32 empty_oafifo : 1; + RK_U32 full_cmd_oafifo : 1; + RK_U32 full_data_oafifo : 1; + RK_U32 empty_iafifo : 1; + RK_U32 full_cmd_iafifo : 1; + RK_U32 full_info_iafifo : 1; + RK_U32 fbd_brq_st : 4; + RK_U32 fbd_hdr_vld : 1; + RK_U32 fbd_bmng_end : 1; + RK_U32 nfbd_req_st : 4; + RK_U32 acc_axi_cmd : 8; + RK_U32 reserved : 8; + } dbg_pp_st; + + /* 0x00005104 reg5185 */ + struct { + RK_U32 cur_state_cime : 2; + RK_U32 cur_state_ds : 3; + RK_U32 cur_state_ref : 2; + RK_U32 cur_state_cst : 2; + RK_U32 reserved : 23; + } dbg_cime_st; + + /* 0x00005108 reg5186 */ + RK_U32 swin_dbg_inf; + + /* 0x0000510c reg5187 */ + struct { + RK_U32 bbrq_cmps_left_len2 : 1; + RK_U32 bbrq_cmps_left_len1 : 1; + RK_U32 cmps_left_len0 : 1; + RK_U32 bbrq_rdy2 : 1; + RK_U32 dcps_vld2 : 1; + RK_U32 bbrq_rdy1 : 1; + RK_U32 dcps_vld1 : 1; + RK_U32 bbrq_rdy0 : 1; + RK_U32 dcps_vld0 : 1; + RK_U32 hb_rdy2 : 1; + RK_U32 bbrq_vld2 : 1; + RK_U32 hb_rdy1 : 1; + RK_U32 bbrq_vld1 : 1; + RK_U32 hb_rdy0 : 1; + RK_U32 bbrq_vld0 : 1; + RK_U32 idle_msb2 : 1; + RK_U32 idle_msb1 : 1; + RK_U32 idle_msb0 : 1; + RK_U32 cur_state_dcps : 1; + RK_U32 cur_state_bbrq : 1; + RK_U32 cur_state_hb : 1; + RK_U32 cke_bbrq_dcps : 1; + RK_U32 cke_dcps : 1; + RK_U32 cke_bbrq : 1; + RK_U32 rdy_lwcd_rsp : 1; + RK_U32 vld_lwcd_rsp : 1; + RK_U32 rdy_lwcd_req : 1; + RK_U32 vld_lwcd_req : 1; + RK_U32 rdy_lwrsp : 1; + RK_U32 vld_lwrsp : 1; + RK_U32 rdy_lwreq : 1; + RK_U32 vld_lwreq : 1; + } dbg_fbd_hhit0; + + /* 0x5110 */ + RK_U32 reserved_5188; + + /* 0x00005114 reg5189 */ + struct { + RK_U32 mscnt_clr : 1; + RK_U32 reserved : 31; + } dbg_cach_clr; + + /* 0x00005118 reg5190 */ + RK_U32 l1_mis; + + /* 0x0000511c reg5191 */ + RK_U32 l2_mis; + + /* 0x00005120 reg5192 */ + RK_U32 rdo_st; + + /* 0x00005124 reg5193 */ + RK_U32 rdo_if; + + /* 0x00005128 reg5194 */ + struct { + RK_U32 h264_sh_st_cs : 4; + RK_U32 rsd_st_cs : 4; + RK_U32 h264_sd_st_cs : 5; + RK_U32 etpy_rdy : 1; + RK_U32 reserved : 18; + } dbg_etpy; + + /* 0x0000512c reg5195 */ + struct { + RK_U32 crdy_ppr : 1; + RK_U32 cvld_ppr : 1; + RK_U32 drdy_ppw : 1; + RK_U32 dvld_ppw : 1; + RK_U32 crdy_ppw : 1; + RK_U32 cvld_ppw : 1; + RK_U32 reserved : 26; + } dbg_dma_pp; + + /* 0x00005130 reg5196 */ + struct { + RK_U32 axi_wrdy : 8; + RK_U32 axi_wvld : 8; + RK_U32 axi_awrdy : 8; + RK_U32 axi_awvld : 8; + } dbg_dma_w; + + /* 0x00005134 reg5197 */ + struct { + RK_U32 axi_otsd_read : 16; + RK_U32 axi_arrdy : 7; + RK_U32 reserved : 1; + RK_U32 axi_arvld : 7; + RK_U32 reserved1 : 1; + } dbg_dma_r; + + /* 0x00005138 reg5198 */ + struct { + RK_U32 dfifo0_lvl : 4; + RK_U32 dfifo1_lvl : 4; + RK_U32 dfifo2_lvl : 4; + RK_U32 dfifo3_lvl : 4; + RK_U32 dfifo4_lvl : 4; + RK_U32 dfifo5_lvl : 4; + RK_U32 reserved : 6; + RK_U32 cmd_vld : 1; + RK_U32 reserved1 : 1; + } dbg_dma_rfpr; + + /* 0x0000513c reg5199 */ + struct { + RK_U32 meiw_busy : 1; + RK_U32 dspw_busy : 1; + RK_U32 bsw_rdy : 1; + RK_U32 bsw_flsh : 1; + RK_U32 bsw_busy : 1; + RK_U32 crpw_busy : 1; + RK_U32 lktw_busy : 1; + RK_U32 lpfw_busy : 1; + RK_U32 roir_busy : 1; + RK_U32 dspr_crdy : 1; + RK_U32 dspr_cvld : 1; + RK_U32 lktr_busy : 1; + RK_U32 lpfr_otsd : 4; + RK_U32 rfpr_otsd : 12; + RK_U32 dspr_otsd : 4; + } dbg_dma_ch_st; + + /* 0x00005140 reg5200 */ + struct { + RK_U32 cpip_st : 2; + RK_U32 mvp_st : 3; + RK_U32 qpd6_st : 2; + RK_U32 cmd_st : 2; + RK_U32 reserved : 23; + } dbg_tctrl_cime_st; + + /* 0x00005144 reg5201 */ + struct { + RK_U32 cme_byps : 1; + RK_U32 swin_byps : 1; + RK_U32 rme_byps : 1; + RK_U32 intra_byps : 1; + RK_U32 fme_byps : 1; + RK_U32 rdo_byps : 1; + RK_U32 lpf_byps : 1; + RK_U32 etpy_byps : 1; + RK_U32 reserved : 24; + } dbg_tctrl; + + /* 0x5148 */ + RK_U32 reserved_5202; + + /* 0x0000514c reg5203 */ + RK_U32 dbg_lpf_st; + + /* 0x00005150 reg5204 */ + RK_U32 dbg_topc_lpfr; + + /* 0x00005154 reg5205 */ + RK_U32 dbg0_cache; + + /* 0x00005158 reg5206 */ + RK_U32 dbg1_cache; + + /* 0x0000515c reg5207 */ + RK_U32 dbg2_cache; + + /* 0x5160 - 0x51fc */ + RK_U32 reserved5208_5247[40]; + + /* 0x00005200 reg5248 */ + RK_U32 frame_cyc; + + /* 0x00005204 reg5249 */ + RK_U32 pp_fcyc; + + /* 0x00005208 reg5250 */ + RK_U32 cme_fcyc; + + /* 0x0000520c reg5251 */ + RK_U32 cme_dspr_fcyc; + + /* 0x00005210 reg5252 */ + RK_U32 ldr_fcyc; + + /* 0x00005214 reg5253 */ + RK_U32 rme_fcyc; + + /* 0x00005218 reg5254 */ + RK_U32 fme_fcyc; + + /* 0x0000521c reg5255 */ + RK_U32 rdo_fcyc; + + /* 0x00005220 reg5256 */ + RK_U32 lpf_fcyc; + + /* 0x00005224 reg5257 */ + RK_U32 etpy_fcyc; + + /* 0x5228 - 0x52fc */ + RK_U32 reserved5258_5311[54]; + + /* 0x00005300 reg5312 */ + struct { + RK_U32 axip_e : 1; + RK_U32 axip_clr : 1; + RK_U32 axip_mod : 1; + RK_U32 reserved : 29; + } axip0_cmd; + + /* 0x00005304 reg5313 */ + struct { + RK_U32 axip_ltcy_id : 4; + RK_U32 axip_ltcy_thd : 12; + RK_U32 reserved : 16; + } axip0_ltcy; + + /* 0x00005308 reg5314 */ + struct { + RK_U32 axip_cnt_typ : 1; + RK_U32 axip_cnt_ddr : 2; + RK_U32 axip_cnt_rid : 5; + RK_U32 axip_cnt_wid : 5; + RK_U32 reserved : 19; + } axip0_cnt; + + /* 0x530c */ + RK_U32 reserved_5315; + + /* 0x00005310 reg5316 */ + struct { + RK_U32 axip_e : 1; + RK_U32 axip_clr : 1; + RK_U32 axip_mod : 1; + RK_U32 reserved : 29; + } axip1_cmd; + + /* 0x00005314 reg5317 */ + struct { + RK_U32 axip_ltcy_id : 4; + RK_U32 axip_ltcy_thd : 12; + RK_U32 reserved : 16; + } axip1_ltcy; + + /* 0x00005318 reg5318 */ + struct { + RK_U32 axip_cnt_typ : 1; + RK_U32 axip_cnt_ddr : 2; + RK_U32 axip_cnt_rid : 5; + RK_U32 axip_cnt_wid : 5; + RK_U32 reserved : 19; + } axip1_cnt; + + /* 0x531c */ + RK_U32 reserved_5319; + + /* 0x00005320 reg5320 */ + struct { + RK_U32 axip_max_ltcy : 16; + RK_U32 reserved : 16; + } st_axip0_maxl; + + /* 0x00005324 reg5321 */ + RK_U32 axip0_num_ltcy; + + /* 0x00005328 reg5322 */ + RK_U32 axip0_sum_ltcy; + + /* 0x0000532c reg5323 */ + RK_U32 axip0_rbyt; + + /* 0x00005330 reg5324 */ + RK_U32 axip0_wbyt; + + /* 0x00005334 reg5325 */ + RK_U32 axip0_wrk_cyc; + + /* 0x5338 - 0x533c */ + RK_U32 reserved5326_5327[2]; + + /* 0x00005340 reg5328 */ + struct { + RK_U32 axip_max_ltcy : 16; + RK_U32 reserved : 16; + } st_axip1_maxl; + + /* 0x00005344 reg5329 */ + RK_U32 axip1_num_ltcy; + + /* 0x00005348 reg5330 */ + RK_U32 axip1_sum_ltcy; + + /* 0x0000534c reg5331 */ + RK_U32 axip1_rbyt; + + /* 0x00005350 reg5332 */ + RK_U32 axip1_wbyt; + + /* 0x00005354 reg5333 */ + RK_U32 axip1_wrk_cyc; +} Vepu580_dbg; + +typedef struct H265eV580RegSet_t { + hevc_vepu580_control_cfg reg_ctl; + hevc_vepu580_base reg_base; + hevc_vepu580_rc_klut reg_rc_klut; + hevc_vepu580_wgt reg_wgt; + vepu580_rdo_cfg reg_rdo; + vepu580_osd_cfg reg_osd_cfg; + Vepu580_dbg reg_dbg; +} H265eV580RegSet; + +typedef struct H265eV580StatusElem_t { + RK_U32 hw_status; + vepu580Status st; +} H265eV580StatusElem; + +#endif diff --git a/mpp/hal/rkenc/h265e/hal_h265e_vepu580_tune.c b/mpp/hal/rkenc/h265e/hal_h265e_vepu580_tune.c new file mode 100644 index 000000000..29e11d89e --- /dev/null +++ b/mpp/hal/rkenc/h265e/hal_h265e_vepu580_tune.c @@ -0,0 +1,680 @@ +/* + * Copyright 2021 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vepu580_tune.h" +#include "hal_h265e_vepu580_reg.h" + +#define HAL_H265E_DBG_CONTENT (0x00200000) +#define hal_h264e_dbg_content(fmt, ...) hal_h264e_dbg_f(HAL_H264E_DBG_CONTENT, fmt, ## __VA_ARGS__) + +#define CTU_BASE_CFG_BYTE 64 +#define CTU_QP_CFG_BYTE 192 + +/* + * Please follow the configuration below: + * + * FRAME_CONTENT_ANALYSIS_NUM >= 5 + * MD_WIN_LEN >= 3 + * MD_SHOW_LEN == 4 + */ + +typedef struct HalH265eVepu580Tune_t { + H265eV580HalContext *ctx; + + /* motion and texture statistic of previous frames */ + RK_S32 curr_scene_motion_flag; + /* motion and texture statistic of previous frames */ + RK_S32 ap_motion_flag; + // level: 0~2: 0 <--> static, 1 <-->medium motion, 2 <--> large motion + RK_S32 md_madp[MD_WIN_LEN]; + // level: 0~2: 0 <--> simple texture, 1 <--> medium texture, 2 <--> complex texture + RK_S32 txtr_madi[FRAME_CONTENT_ANALYSIS_NUM]; + RK_S32 scene_motion_flag_matrix[FRAME_MOTION_ANALYSIS_NUM]; + RK_S32 md_flag_matrix[MD_SHOW_LEN]; + + RK_S32 pre_madp[2]; + RK_S32 pre_madi[2]; +} HalH265eVepu580Tune; + +static RK_S32 ctu_avg_madp_thd[6] = {896, 640, 384, 896, 640, 384}; + +static RK_U8 lvl32_preintra_cst_wgt[4][8] = { + {21, 20, 19, 18, 20, 22, 24, 16}, + {19, 18, 17, 16, 18, 20, 21, 16}, + {20, 19, 18, 17, 19, 21, 22, 16}, + {16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_U8 lvl16_preintra_cst_wgt[4][8] = { + {21, 20, 19, 18, 20, 22, 24, 16}, + {19, 18, 17, 16, 18, 20, 21, 16}, + {20, 19, 18, 17, 19, 21, 22, 16}, + {16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 skip_b64_atf_wgt[4][13] = { + {16, 13, 14, 15, 14, 14, 15, 15, 15, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 14, 15, 16, 14, 14, 15, 15, 15, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 intra_b32_atf_wgt[4][12] = { + {24, 23, 23, 23, 22, 21, 20, 19, 18, 16, 16, 16}, + {21, 20, 19, 20, 19, 18, 19, 18, 18, 18, 18, 17}, + {20, 19, 18, 19, 18, 17, 18, 17, 17, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 skip_b32_atf_wgt[4][13] = { + {16, 13, 14, 15, 14, 14, 15, 15, 15, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {18, 14, 14, 15, 14, 14, 15, 15, 15, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 intra_b16_atf_wgt[4][12] = { + {24, 23, 23, 23, 22, 21, 20, 19, 18, 16, 16, 16}, + {21, 20, 19, 20, 19, 18, 19, 18, 18, 18, 18, 17}, + {20, 19, 18, 19, 18, 17, 18, 17, 17, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 skip_b16_atf_wgt[4][13] = { + {16, 13, 14, 15, 14, 14, 15, 15, 15, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 intra_b8_atf_wgt[4][12] = { + {24, 23, 23, 23, 22, 21, 20, 19, 18, 16, 16, 16}, + {21, 20, 19, 20, 19, 18, 19, 18, 18, 18, 18, 17}, + {20, 19, 18, 19, 18, 17, 18, 17, 17, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_S32 skip_b8_atf_wgt[4][13] = { + {16, 13, 14, 15, 14, 14, 15, 15, 15, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_U32 intra_lvl16_sobel_a[4][9] = { + {32, 32, 32, 32, 32, 32, 32, 32, 32}, + {16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_U32 intra_lvl16_sobel_c[4][9] = { + {13, 13, 13, 13, 13, 13, 13, 13, 13}, + {16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static RK_U32 intra_lvl16_sobel_d[4][9] = { + {23750, 23750, 23750, 23750, 23750, 23750, 23750, 23750, 23750}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; + +static RK_U32 intra_lvl32_sobel_a[4][5] = { + {18, 18, 18, 18, 18}, + {16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16}, +}; + +static RK_U32 intra_lvl32_sobel_c[4][5] = { + {16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16}, + {16, 16, 16, 16, 16}, +}; + +static RK_U32 qnt_bias_i[4] = { + 128, 128, 128, 128 +}; + +static RK_U32 qnt_bias_p[4] = { + 60, 60, 85, 85 +}; + +static RK_U32 rime_sqi_cime_sad_th[4] = { + 48, 0, 0, 0 +}; + +static RK_U32 fme_sqi_cime_sad_pu16_th[4] = { + 16, 0, 0, 0 +}; + +static RK_U32 fme_sqi_cime_sad_pu32_th[4] = { + 16, 0, 0, 0 +}; + +static RK_U32 fme_sqi_cime_sad_pu64_th[4] = { + 16, 0, 0, 0 +}; + +static RK_U32 chrm_klut_ofst[4] = { + 3, 0, 0, 0 +}; + +static RK_S32 pre_intra_b32_cost[4][2] = { + {31, 30}, + {23, 20}, + {31, 30}, + {23, 20}, +}; + +static RK_S32 pre_intra_b16_cost[4][2] = { + {31, 30}, + {23, 20}, + {31, 30}, + {23, 20}, +}; + +static RK_S32 cime_multi[4][4] = { + {4, 8, 24, 24}, + {4, 7, 20, 20}, + {4, 8, 24, 24}, + {4, 4, 4, 4}, +}; + +static RK_S32 rime_multi[4][3] = { + {4, 32, 128}, + {4, 16, 64}, + {4, 32, 128}, + {4, 4, 4}, +}; + +static HalH265eVepu580Tune *vepu580_h265e_tune_init(H265eV580HalContext *ctx) +{ + HalH265eVepu580Tune *tune = mpp_malloc(HalH265eVepu580Tune, 1); + RK_S32 scene_mode = ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 0 : 1; + + if (NULL == tune) + return tune; + + tune->ctx = ctx; + tune->curr_scene_motion_flag = 0; + tune->ap_motion_flag = scene_mode; + memset(tune->md_madp, 0, sizeof(tune->md_madp)); + memset(tune->txtr_madi, 0, sizeof(tune->txtr_madi)); + memset(tune->md_flag_matrix, 0, sizeof(tune->md_flag_matrix)); + memset(tune->scene_motion_flag_matrix, 0, sizeof(tune->scene_motion_flag_matrix)); + tune->pre_madi[0] = tune->pre_madi[1] = -1; + tune->pre_madp[0] = tune->pre_madp[1] = -1; + + return tune; +} + +static void vepu580_h265e_tune_deinit(void *tune) +{ + MPP_FREE(tune); +} + +static void vepu580_h265e_tune_atf(H265eV580HalContext *ctx, RK_U32 sm_flag) +{ + H265eV580RegSet *regs = ctx->frm->regs_set[0]; + vepu580_rdo_cfg *reg_rdo = ®s->reg_rdo; + RdoAtfSkipCfg *s; + RdoAtfCfg* p; + RK_U32 atf_idx = (ctx->cfg->tune.vmaf_opt != 0) ? 3 : sm_flag; + + s = ®_rdo->rdo_b64_skip_atf; + s->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 1; + s->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 2; + s->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 4; + s->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 6; + + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = skip_b64_atf_wgt[atf_idx][0]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = skip_b64_atf_wgt[atf_idx][1]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = skip_b64_atf_wgt[atf_idx][2]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = skip_b64_atf_wgt[atf_idx][3]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = skip_b64_atf_wgt[atf_idx][4]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = skip_b64_atf_wgt[atf_idx][5]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = skip_b64_atf_wgt[atf_idx][6]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = skip_b64_atf_wgt[atf_idx][7]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = skip_b64_atf_wgt[atf_idx][8]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = skip_b64_atf_wgt[atf_idx][9]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = skip_b64_atf_wgt[atf_idx][10]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = skip_b64_atf_wgt[atf_idx][11]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = skip_b64_atf_wgt[atf_idx][12]; + + p = ®_rdo->rdo_b32_intra_atf; + p->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 48; + p->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 64; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = intra_b32_atf_wgt[atf_idx][0]; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = intra_b32_atf_wgt[atf_idx][1]; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = intra_b32_atf_wgt[atf_idx][2]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = intra_b32_atf_wgt[atf_idx][3]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = intra_b32_atf_wgt[atf_idx][4]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = intra_b32_atf_wgt[atf_idx][5]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = intra_b32_atf_wgt[atf_idx][6]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = intra_b32_atf_wgt[atf_idx][7]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = intra_b32_atf_wgt[atf_idx][8]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = intra_b32_atf_wgt[atf_idx][9]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = intra_b32_atf_wgt[atf_idx][10]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = intra_b32_atf_wgt[atf_idx][11]; + + s = ®_rdo->rdo_b32_skip_atf; + s->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 1; + s->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 2; + s->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 4; + s->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 6; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = skip_b32_atf_wgt[atf_idx][0]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = skip_b32_atf_wgt[atf_idx][1]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = skip_b32_atf_wgt[atf_idx][2]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = skip_b32_atf_wgt[atf_idx][3]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = skip_b32_atf_wgt[atf_idx][4]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = skip_b32_atf_wgt[atf_idx][5]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = skip_b32_atf_wgt[atf_idx][6]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = skip_b32_atf_wgt[atf_idx][7]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = skip_b32_atf_wgt[atf_idx][8]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = skip_b32_atf_wgt[atf_idx][9]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = skip_b32_atf_wgt[atf_idx][10]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = skip_b32_atf_wgt[atf_idx][11]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = skip_b32_atf_wgt[atf_idx][12]; + + p = ®_rdo->rdo_b16_intra_atf; + p->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 48; + p->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 64; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = intra_b16_atf_wgt[atf_idx][0]; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = intra_b16_atf_wgt[atf_idx][1]; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = intra_b16_atf_wgt[atf_idx][2]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = intra_b16_atf_wgt[atf_idx][3]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = intra_b16_atf_wgt[atf_idx][4]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = intra_b16_atf_wgt[atf_idx][5]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = intra_b16_atf_wgt[atf_idx][6]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = intra_b16_atf_wgt[atf_idx][7]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = intra_b16_atf_wgt[atf_idx][8]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = intra_b16_atf_wgt[atf_idx][9]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = intra_b16_atf_wgt[atf_idx][10]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = intra_b16_atf_wgt[atf_idx][11]; + + s = ®_rdo->rdo_b16_skip_atf; + s->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 1; + s->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 2; + s->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 4; + s->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 6; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = skip_b16_atf_wgt[atf_idx][0]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = skip_b16_atf_wgt[atf_idx][1]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = skip_b16_atf_wgt[atf_idx][2]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = skip_b16_atf_wgt[atf_idx][3]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = skip_b16_atf_wgt[atf_idx][4]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = skip_b16_atf_wgt[atf_idx][5]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = skip_b16_atf_wgt[atf_idx][6]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = skip_b16_atf_wgt[atf_idx][7]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = skip_b16_atf_wgt[atf_idx][8]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = skip_b16_atf_wgt[atf_idx][9]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = skip_b16_atf_wgt[atf_idx][10]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = skip_b16_atf_wgt[atf_idx][11]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = skip_b16_atf_wgt[atf_idx][12]; + + p = ®_rdo->rdo_b8_intra_atf; + p->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 24; + p->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 48; + p->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 64; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = intra_b8_atf_wgt[atf_idx][0]; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt01 = intra_b8_atf_wgt[atf_idx][1]; + p->rdo_b_atf_wgt0.cu_rdo_atf_wgt02 = intra_b8_atf_wgt[atf_idx][2]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt10 = intra_b8_atf_wgt[atf_idx][3]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt11 = intra_b8_atf_wgt[atf_idx][4]; + p->rdo_b_atf_wgt1.cu_rdo_atf_wgt12 = intra_b8_atf_wgt[atf_idx][5]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt20 = intra_b8_atf_wgt[atf_idx][6]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt21 = intra_b8_atf_wgt[atf_idx][7]; + p->rdo_b_atf_wgt2.cu_rdo_atf_wgt22 = intra_b8_atf_wgt[atf_idx][8]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt30 = intra_b8_atf_wgt[atf_idx][9]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt31 = intra_b8_atf_wgt[atf_idx][10]; + p->rdo_b_atf_wgt3.cu_rdo_atf_wgt32 = intra_b8_atf_wgt[atf_idx][11]; + + s = ®_rdo->rdo_b8_skip_atf; + s->rdo_b_cime_thd0.cu_rdo_cime_thd0 = 1; + s->rdo_b_cime_thd0.cu_rdo_cime_thd1 = 2; + s->rdo_b_cime_thd1.cu_rdo_cime_thd2 = 4; + s->rdo_b_cime_thd1.cu_rdo_cime_thd3 = 6; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt00 = skip_b8_atf_wgt[atf_idx][0]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt10 = skip_b8_atf_wgt[atf_idx][1]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt11 = skip_b8_atf_wgt[atf_idx][2]; + s->rdo_b_atf_wgt0.cu_rdo_atf_wgt12 = skip_b8_atf_wgt[atf_idx][3]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt20 = skip_b8_atf_wgt[atf_idx][4]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt21 = skip_b8_atf_wgt[atf_idx][5]; + s->rdo_b_atf_wgt1.cu_rdo_atf_wgt22 = skip_b8_atf_wgt[atf_idx][6]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt30 = skip_b8_atf_wgt[atf_idx][7]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt31 = skip_b8_atf_wgt[atf_idx][8]; + s->rdo_b_atf_wgt2.cu_rdo_atf_wgt32 = skip_b8_atf_wgt[atf_idx][9]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt40 = skip_b8_atf_wgt[atf_idx][10]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt41 = skip_b8_atf_wgt[atf_idx][11]; + s->rdo_b_atf_wgt3.cu_rdo_atf_wgt42 = skip_b8_atf_wgt[atf_idx][12]; +} + +static void vepu580_h265e_tune_reg_patch(void *p) +{ + HalH265eVepu580Tune *tune = (HalH265eVepu580Tune *)p; + H265eV580HalContext *ctx = NULL; + RK_S32 scene_mode = 0; + + if (NULL == tune) + return; + + ctx = tune->ctx; + scene_mode = ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 0 : 1; + tune->ap_motion_flag = scene_mode; + /* modify register here */ + H265eV580RegSet *regs = ctx->frm->regs_set[0]; + hevc_vepu580_rc_klut *rc_regs = ®s->reg_rc_klut; + hevc_vepu580_wgt *reg_wgt = ®s->reg_wgt; + vepu580_rdo_cfg *reg_rdo = ®s->reg_rdo; + RK_U32 scene_motion_flag = tune->ap_motion_flag * 2 + tune->curr_scene_motion_flag; + MppEncHwCfg *hw = &ctx->cfg->hw; + RK_S32 vmaf_opt = ctx->cfg->tune.vmaf_opt; + RK_U32 pre_intra_idx = (vmaf_opt != 0) ? 3 : scene_motion_flag; + + if (scene_motion_flag > 3) { + mpp_err_f("scene_motion_flag is a wrong value %d\n", scene_motion_flag); + return; + } + + memcpy(®_wgt->lvl32_intra_CST_WGT0, lvl32_preintra_cst_wgt[pre_intra_idx], + sizeof(lvl32_preintra_cst_wgt[pre_intra_idx])); + memcpy(®_wgt->lvl16_intra_CST_WGT0, lvl16_preintra_cst_wgt[pre_intra_idx], + sizeof(lvl16_preintra_cst_wgt[pre_intra_idx])); + + /* Do not adjust the ATF weight when skip bias is enabled */ + if (!hw->skip_bias_en) + vepu580_h265e_tune_atf(ctx, scene_motion_flag); + + reg_rdo->preintra_b32_cst_wgt.pre_intra32_cst_wgt00 = pre_intra_b32_cost[scene_motion_flag][0]; + reg_rdo->preintra_b32_cst_wgt.pre_intra32_cst_wgt01 = pre_intra_b32_cost[scene_motion_flag][1]; + reg_rdo->preintra_b16_cst_wgt.pre_intra16_cst_wgt00 = pre_intra_b16_cost[scene_motion_flag][0]; + reg_rdo->preintra_b16_cst_wgt.pre_intra16_cst_wgt01 = pre_intra_b16_cost[scene_motion_flag][1]; + + rc_regs->md_sad_thd.md_sad_thd0 = 7; + rc_regs->md_sad_thd.md_sad_thd1 = 15; + rc_regs->md_sad_thd.md_sad_thd2 = 25; + rc_regs->madi_thd.madi_thd0 = 4; + rc_regs->madi_thd.madi_thd1 = 9; + rc_regs->madi_thd.madi_thd2 = 15; + + reg_wgt->cime_sqi_cfg.cime_pmv_set_zero = !tune->curr_scene_motion_flag; + reg_wgt->cime_sqi_multi0.cime_multi0 = cime_multi[scene_motion_flag][0]; + reg_wgt->cime_sqi_multi0.cime_multi1 = cime_multi[scene_motion_flag][1]; + reg_wgt->cime_sqi_multi1.cime_multi2 = cime_multi[scene_motion_flag][2]; + reg_wgt->cime_sqi_multi1.cime_multi3 = cime_multi[scene_motion_flag][3]; + + reg_wgt->rime_sqi_multi.rime_multi0 = rime_multi[scene_motion_flag][0]; + reg_wgt->rime_sqi_multi.rime_multi1 = rime_multi[scene_motion_flag][1]; + reg_wgt->rime_sqi_multi.rime_multi2 = rime_multi[scene_motion_flag][2]; + + if (tune->curr_scene_motion_flag) { + reg_wgt->fme_sqi_thd1.move_lambda = 8; + } + + reg_rdo->rdo_sqi_cfg.rdo_segment_en = (vmaf_opt != 0) ? 0 : !tune->curr_scene_motion_flag; + reg_rdo->rdo_sqi_cfg.rdo_smear_en = (vmaf_opt != 0) ? 0 : !tune->curr_scene_motion_flag; + + reg_wgt->i16_sobel_a_00.intra_l16_sobel_a0_qp0 = intra_lvl16_sobel_a[scene_motion_flag][0]; + reg_wgt->i16_sobel_a_00.intra_l16_sobel_a0_qp1 = intra_lvl16_sobel_a[scene_motion_flag][1]; + reg_wgt->i16_sobel_a_00.intra_l16_sobel_a0_qp2 = intra_lvl16_sobel_a[scene_motion_flag][2]; + reg_wgt->i16_sobel_a_00.intra_l16_sobel_a0_qp3 = intra_lvl16_sobel_a[scene_motion_flag][3]; + reg_wgt->i16_sobel_a_00.intra_l16_sobel_a0_qp4 = intra_lvl16_sobel_a[scene_motion_flag][4]; + reg_wgt->i16_sobel_a_01.intra_l16_sobel_a0_qp5 = intra_lvl16_sobel_a[scene_motion_flag][5]; + reg_wgt->i16_sobel_a_01.intra_l16_sobel_a0_qp6 = intra_lvl16_sobel_a[scene_motion_flag][6]; + reg_wgt->i16_sobel_a_01.intra_l16_sobel_a0_qp7 = intra_lvl16_sobel_a[scene_motion_flag][7]; + reg_wgt->i16_sobel_a_01.intra_l16_sobel_a0_qp8 = intra_lvl16_sobel_a[scene_motion_flag][8]; + reg_wgt->i16_sobel_c_00.intra_l16_sobel_c0_qp0 = intra_lvl16_sobel_c[scene_motion_flag][0]; + reg_wgt->i16_sobel_c_00.intra_l16_sobel_c0_qp1 = intra_lvl16_sobel_c[scene_motion_flag][1]; + reg_wgt->i16_sobel_c_00.intra_l16_sobel_c0_qp2 = intra_lvl16_sobel_c[scene_motion_flag][2]; + reg_wgt->i16_sobel_c_00.intra_l16_sobel_c0_qp3 = intra_lvl16_sobel_c[scene_motion_flag][3]; + reg_wgt->i16_sobel_c_00.intra_l16_sobel_c0_qp4 = intra_lvl16_sobel_c[scene_motion_flag][4]; + reg_wgt->i16_sobel_c_01.intra_l16_sobel_c0_qp5 = intra_lvl16_sobel_c[scene_motion_flag][5]; + reg_wgt->i16_sobel_c_01.intra_l16_sobel_c0_qp6 = intra_lvl16_sobel_c[scene_motion_flag][6]; + reg_wgt->i16_sobel_c_01.intra_l16_sobel_c0_qp7 = intra_lvl16_sobel_c[scene_motion_flag][7]; + reg_wgt->i16_sobel_c_01.intra_l16_sobel_c0_qp8 = intra_lvl16_sobel_c[scene_motion_flag][8]; + reg_wgt->i16_sobel_d_00.intra_l16_sobel_d0_qp0 = intra_lvl16_sobel_d[scene_motion_flag][0]; + reg_wgt->i16_sobel_d_00.intra_l16_sobel_d0_qp1 = intra_lvl16_sobel_d[scene_motion_flag][1]; + reg_wgt->i16_sobel_d_01.intra_l16_sobel_d0_qp2 = intra_lvl16_sobel_d[scene_motion_flag][2]; + reg_wgt->i16_sobel_d_01.intra_l16_sobel_d0_qp3 = intra_lvl16_sobel_d[scene_motion_flag][3]; + reg_wgt->i16_sobel_d_02.intra_l16_sobel_d0_qp4 = intra_lvl16_sobel_d[scene_motion_flag][4]; + reg_wgt->i16_sobel_d_02.intra_l16_sobel_d0_qp5 = intra_lvl16_sobel_d[scene_motion_flag][5]; + reg_wgt->i16_sobel_d_03.intra_l16_sobel_d0_qp6 = intra_lvl16_sobel_d[scene_motion_flag][6]; + reg_wgt->i16_sobel_d_03.intra_l16_sobel_d0_qp7 = intra_lvl16_sobel_d[scene_motion_flag][7]; + reg_wgt->i16_sobel_d_04.intra_l16_sobel_d0_qp8 = intra_lvl16_sobel_d[scene_motion_flag][8]; + reg_wgt->i32_sobel_a.intra_l32_sobel_a1_qp0 = intra_lvl32_sobel_a[scene_motion_flag][0]; + reg_wgt->i32_sobel_a.intra_l32_sobel_a1_qp1 = intra_lvl32_sobel_a[scene_motion_flag][1]; + reg_wgt->i32_sobel_a.intra_l32_sobel_a1_qp2 = intra_lvl32_sobel_a[scene_motion_flag][2]; + reg_wgt->i32_sobel_a.intra_l32_sobel_a1_qp3 = intra_lvl32_sobel_a[scene_motion_flag][3]; + reg_wgt->i32_sobel_a.intra_l32_sobel_a1_qp4 = intra_lvl32_sobel_a[scene_motion_flag][4]; + reg_wgt->i32_sobel_c.intra_l32_sobel_c1_qp0 = intra_lvl32_sobel_c[scene_motion_flag][0]; + reg_wgt->i32_sobel_c.intra_l32_sobel_c1_qp1 = intra_lvl32_sobel_c[scene_motion_flag][1]; + reg_wgt->i32_sobel_c.intra_l32_sobel_c1_qp2 = intra_lvl32_sobel_c[scene_motion_flag][2]; + reg_wgt->i32_sobel_c.intra_l32_sobel_c1_qp3 = intra_lvl32_sobel_c[scene_motion_flag][3]; + reg_wgt->i32_sobel_c.intra_l32_sobel_c1_qp4 = intra_lvl32_sobel_c[scene_motion_flag][4]; + + if (hw->qbias_en) { + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_i = (hw->qbias_i != 0) ? hw->qbias_i : 171; + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_p = (hw->qbias_p != 0) ? hw->qbias_p : 85; + } else { + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_i = qnt_bias_i[scene_motion_flag]; + reg_wgt->reg1484_qnt_bias_comb.qnt_bias_p = qnt_bias_p[scene_motion_flag]; + } + + reg_wgt->rime_sqi_thd.cime_sad_th0 = rime_sqi_cime_sad_th[scene_motion_flag]; + reg_wgt->fme_sqi_thd0.cime_sad_pu16_th = fme_sqi_cime_sad_pu16_th[scene_motion_flag]; + reg_wgt->fme_sqi_thd0.cime_sad_pu32_th = fme_sqi_cime_sad_pu32_th[scene_motion_flag]; + reg_wgt->fme_sqi_thd1.cime_sad_pu64_th = fme_sqi_cime_sad_pu64_th[scene_motion_flag]; + rc_regs->klut_ofst.chrm_klut_ofst = chrm_klut_ofst[scene_motion_flag]; +} + +static void vepu580_h265e_tune_stat_update(void *p, EncRcTaskInfo *rc_info) +{ + HalH265eVepu580Tune *tune = (HalH265eVepu580Tune *)p; + H265eV580HalContext *ctx = NULL; + RK_S32 scene_mode = 0; + + if (NULL == tune) + return; + + ctx = tune->ctx; + scene_mode = ctx->cfg->tune.scene_mode == MPP_ENC_SCENE_MODE_IPC ? 0 : 1; + tune->ap_motion_flag = scene_mode; + /* update statistic info here */ + RK_S32 j; + RK_S32 i = 0; + RK_S32 mvbit = 10; + Vepu580H265Fbk *fb = &ctx->frm->feedback; + + for (i = 0; i < (RK_S32)ctx->tile_num; i++) { + H265eV580StatusElem *elem = ctx->frm->regs_ret[i]; + + fb->st_md_sad_b16num0 += elem->st.md_sad_b16num0; + fb->st_md_sad_b16num1 += elem->st.md_sad_b16num1; + fb->st_md_sad_b16num2 += elem->st.md_sad_b16num2; + fb->st_md_sad_b16num3 += elem->st.md_sad_b16num3; + fb->st_madi_b16num0 += elem->st.madi_b16num0; + fb->st_madi_b16num1 += elem->st.madi_b16num1; + fb->st_madi_b16num2 += elem->st.madi_b16num2; + fb->st_madi_b16num3 += elem->st.madi_b16num3; + } + + RK_S32 mb_num = (fb->st_mb_num != 0) ? fb->st_mb_num : 1; + RK_S32 madp = 0; + RK_S32 md_flag = 0; + RK_S32 nScore = 0; + RK_S32 nScoreT = ((MD_WIN_LEN - 2) * 6 + 2 * 8 + 2 * 11 + 2 * 13) / 2; + RK_S32 madp_cnt_statistics[5]; + RK_U32 md_cnt = (24 * fb->st_md_sad_b16num3 + 22 * fb->st_md_sad_b16num2 + 17 * + fb->st_md_sad_b16num1) >> 2; + RK_U32 madi_cnt = (6 * fb->st_madi_b16num3 + 5 * fb->st_madi_b16num2 + 4 * + fb->st_madi_b16num1) >> 2; + RK_U32 mbs = ((ctx->cfg->prep.width + 15) / 16) * ((ctx->cfg->prep.height + 15) / 16); + for (i = 0; i < 5; i++) { + madp_cnt_statistics[i] = fb->st_md_sad_b16num0 * madp_num_map[i][0] + + fb->st_md_sad_b16num1 * madp_num_map[i][1] + + fb->st_md_sad_b16num2 * madp_num_map[i][2] + + fb->st_md_sad_b16num3 * madp_num_map[i][3]; + } + + tune->pre_madi[0] = fb->st_madi; + tune->pre_madp[0] = fb->st_madp; + + if (0 != tune->ap_motion_flag) + mvbit = 15; + + madp = MOTION_LEVEL_STILL; + if (0 != madp_cnt_statistics[4]) { + RK_S32 base = tune->ap_motion_flag * 3; + + for (i = 0; i < 3; i++, base++) { + if (tune->pre_madp[0] >= ctu_avg_madp_thd[i]) { + if (madp_cnt_statistics[0] > mb_num * ctu_madp_cnt_thd[base][0] >> mvbit || + madp_cnt_statistics[1] > mb_num * ctu_madp_cnt_thd[base][1] >> mvbit || + madp_cnt_statistics[2] > mb_num * ctu_madp_cnt_thd[base][2] >> mvbit) { + madp = MOTION_LEVEL_BIG_MOTION; + } else if ((madp_cnt_statistics[0] > mb_num * ctu_madp_cnt_thd[base][3] >> mvbit || + madp_cnt_statistics[1] > mb_num * ctu_madp_cnt_thd[base][4] >> mvbit) && + madp_cnt_statistics[3] < mb_num * ctu_madp_cnt_thd[base][5] >> mvbit) { + madp = MOTION_LEVEL_BIG_MOTION; + } else if (madp_cnt_statistics[3] < mb_num * ctu_madp_cnt_thd[base][6] >> mvbit) { + madp = MOTION_LEVEL_BIG_MOTION; + } else if (madp_cnt_statistics[3] < mb_num * ctu_madp_cnt_thd[base][7] >> mvbit) { + madp = MOTION_LEVEL_MOTION; + } + break; + } + } + } else { + madp = MOTION_LEVEL_UNKNOW_SCENE; + } + + if (MOTION_LEVEL_UNKNOW_SCENE != madp) { + nScore = madp * 13 + tune->md_madp[0] * 11 + tune->md_madp[1] * 8; + } else { + nScore = tune->md_madp[0] * 11 + tune->md_madp[1] * 8; + nScoreT -= 13; + } + + for (j = 2; j < MD_WIN_LEN; j++) { + nScore += tune->md_madp[j] * 6; + } + + if (nScore >= nScoreT) { + md_flag = 1; + } + + tune->curr_scene_motion_flag = 0; + if (tune->md_flag_matrix[0] && tune->md_flag_matrix[1] && tune->md_flag_matrix[2]) { + tune->curr_scene_motion_flag = 1; + } else if ((tune->md_flag_matrix[0] && tune->md_flag_matrix[1]) || + (tune->md_flag_matrix[1] && tune->md_flag_matrix[2] && tune->md_flag_matrix[3])) { + tune->curr_scene_motion_flag = md_flag; + } + + if (MOTION_LEVEL_UNKNOW_SCENE != madp) { + for (j = MD_WIN_LEN - 2; j >= 0; j--) { + tune->md_madp[j + 1] = tune->md_madp[j]; + } + tune->md_madp[0] = madp; + } + for (j = MD_SHOW_LEN - 2; j >= 0; j--) { + tune->md_flag_matrix[j + 1] = tune->md_flag_matrix[j]; + } + tune->md_flag_matrix[0] = md_flag; + + for (j = FRAME_MOTION_ANALYSIS_NUM - 2; j >= 0; j--) { + tune->scene_motion_flag_matrix[j + 1] = tune->scene_motion_flag_matrix[j]; + } + tune->scene_motion_flag_matrix[0] = tune->curr_scene_motion_flag; + + tune->pre_madi[1] = tune->pre_madi[0]; + tune->pre_madp[1] = tune->pre_madp[0]; + + rc_info->motion_level = 0; + if (md_cnt * 100 > 15 * mbs) + rc_info->motion_level = 200; + else if (md_cnt * 100 > 5 * mbs) + rc_info->motion_level = 100; + else + rc_info->motion_level = 0; + + rc_info->complex_level = 0; + if (madi_cnt * 100 > 30 * mbs) + rc_info->complex_level = 2; + else if (madi_cnt * 100 > 13 * mbs) + rc_info->complex_level = 1; + else + rc_info->complex_level = 0; + hal_h265e_dbg_detail("motion_level = %u, complex_level = %u\n", rc_info->motion_level, + rc_info->complex_level); +} + +static MPP_RET vepu580_setup_qpmap_buf(H265eV580HalContext *ctx) +{ + MPP_RET ret = MPP_OK; + RK_S32 w = ctx->cfg->prep.width; + RK_S32 h = ctx->cfg->prep.height; + RK_S32 ctu_w = MPP_ALIGN(w, 64) / 64; + RK_S32 ctu_h = MPP_ALIGN(h, 64) / 64; + RK_S32 qpmap_base_cfg_size = ctx->qpmap_base_cfg_size + = ctu_w * ctu_h * 64; + RK_S32 qpmap_qp_cfg_size = ctx->qpmap_qp_cfg_size + = ctu_w * ctu_h * 192; + RK_S32 md_flag_size = ctx->md_flag_size + = ctu_w * ctu_h * 16; + + if (!ctx->cfg->tune.deblur_en) { + mpp_log("deblurring is closed!\n"); + goto __RET; + } + + if (NULL == ctx->qpmap_base_cfg_buf) { + mpp_buffer_get(NULL, &ctx->qpmap_base_cfg_buf, qpmap_base_cfg_size); + if (!ctx->qpmap_base_cfg_buf) { + mpp_err("qpmap_base_cfg_buf malloc fail, qpmap invalid\n"); + ret = MPP_ERR_VALUE; + goto __RET; + } + } + + if (NULL == ctx->qpmap_qp_cfg_buf) { + mpp_buffer_get(NULL, &ctx->qpmap_qp_cfg_buf, qpmap_qp_cfg_size); + if (!ctx->qpmap_qp_cfg_buf) { + mpp_err("qpmap_qp_cfg_buf malloc fail, qpmap invalid\n"); + ret = MPP_ERR_VALUE; + goto __RET; + } + } + + if (NULL == ctx->md_flag_buf) { + ctx->md_flag_buf = mpp_malloc(RK_U8, md_flag_size); + if (!ctx->md_flag_buf) { + mpp_err("md_flag_buf malloc fail, qpmap invalid\n"); + ret = MPP_ERR_VALUE; + goto __RET; + } + } + +__RET: + hal_h265e_dbg_func("leave, ret %d\n", ret); + return ret; +} \ No newline at end of file diff --git a/mpp/hal/rkenc/jpege/CMakeLists.txt b/mpp/hal/rkenc/jpege/CMakeLists.txt new file mode 100644 index 000000000..f0bab7cbb --- /dev/null +++ b/mpp/hal/rkenc/jpege/CMakeLists.txt @@ -0,0 +1,15 @@ +# vim: syntax=cmake +include_directories(.) +include_directories(../../common/jpeg/) +include_directories(../common/) + +# hal jpeg encoder sourse +set(HAL_JPEGE_SRC) + +add_hal_source(HAL_JPEGE_SRC HAVE_VEPU540C hal_jpege_vepu540c.c) +add_hal_source(HAL_JPEGE_SRC HAVE_VEPU511 hal_jpege_vepu511.c) +add_hal_source(HAL_JPEGE_SRC HAVE_VEPU720 hal_jpege_vpu720.c) + +if (HAL_JPEGE_SRC) + add_library(hal_jpege_rkv OBJECT ${HAL_JPEGE_SRC}) +endif() diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vepu511.c b/mpp/hal/rkenc/jpege/hal_jpege_vepu511.c new file mode 100644 index 000000000..5aa6027bc --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vepu511.c @@ -0,0 +1,679 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_jpege_v511" + +#include + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" + +#include "hal_jpege_debug.h" +#include "jpege_syntax.h" +#include "hal_bufs.h" +#include "rkv_enc_def.h" +#include "vepu5xx_common.h" +#include "vepu511_common.h" +#include "hal_jpege_vepu511.h" +#include "hal_jpege_vepu511_reg.h" +#include "hal_jpege_hdr.h" + +typedef struct JpegeV511HalContext_t { + MppDev dev; + void *regs; + void *reg_out; + + void *dump_files; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + /* @frame_cnt starts from ZERO */ + RK_U32 frame_cnt; + void *roi_data; + MppEncCfgSet *cfg; + Vepu511OsdCfg osd_cfg; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + RK_S32 fbc_header_len; + RK_U32 title_num; + + JpegeBits bits; + JpegeSyntax syntax; + HalJpegeRc hal_rc; +} JpegeV511HalContext; + +MPP_RET hal_jpege_vepu511_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + + mpp_env_get_u32("hal_jpege_debug", &hal_jpege_debug, 0); + hal_jpege_enter(); + + ctx->reg_out = mpp_calloc(JpegV511Status, 1); + ctx->regs = mpp_calloc(JpegV511RegSet, 1); + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + ctx->frame_cnt = 0; + ctx->enc_mode = 1; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + + ctx->dev = cfg->dev; + jpege_bits_init(&ctx->bits); + mpp_assert(ctx->bits); + hal_jpege_rc_init(&ctx->hal_rc); + + hal_jpege_leave(); + return ret; +} + +MPP_RET hal_jpege_vepu511_deinit(void *hal) +{ + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + + hal_jpege_enter(); + jpege_bits_deinit(ctx->bits); + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->reg_out); + MPP_FREE(ctx->input_fmt); + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + hal_jpege_leave(); + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu511_prepare(void *hal) +{ + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + + hal_jpege_dbg_func("enter %p\n", hal); + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + + hal_jpege_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET vepu511_jpeg_set_patch_info(MppDev dev, JpegeSyntax *syn, + VepuFmt input_fmt, + HalEncTask *task) +{ + RK_U32 hor_stride = syn->hor_stride; + RK_U32 ver_stride = (syn->ver_stride != 0) ? syn->ver_stride : syn->height; + RK_U32 frame_size = hor_stride * ver_stride; + RK_U32 u_offset = 0, v_offset = 0; + MPP_RET ret = MPP_OK; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + u_offset = mpp_frame_get_fbc_offset(task->frame); + v_offset = u_offset; + } else { + switch (input_fmt) { + case VEPU5xx_FMT_YUV420P: { + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } break; + case VEPU5xx_FMT_YUV420SP: + case VEPU5xx_FMT_YUV422SP: { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV422P: { + u_offset = frame_size; + v_offset = frame_size * 3 / 2; + } break; + case VEPU5xx_FMT_YUV400 : + case VEPU5xx_FMT_YUYV422: + case VEPU5xx_FMT_UYVY422: { + u_offset = 0; + v_offset = 0; + } break; + case VEPU5xx_FMT_YUV444SP : { + u_offset = frame_size; + v_offset = frame_size; + } break; + case VEPU5xx_FMT_YUV444P : { + u_offset = frame_size; + v_offset = frame_size * 2; + } break; + case VEPU5xx_FMT_BGR565: + case VEPU5xx_FMT_BGR888: + case VEPU5xx_FMT_BGRA8888: { + u_offset = 0; + v_offset = 0; + } break; + default: { + mpp_err("unknown color space: %d\n", input_fmt); + u_offset = frame_size; + v_offset = frame_size * 5 / 4; + } + } + } + + /* input cb addr */ + if (u_offset) + mpp_dev_set_reg_offset(dev, 265, u_offset); + + /* input cr addr */ + if (v_offset) + mpp_dev_set_reg_offset(dev, 266, v_offset); + + return ret; +} + +MPP_RET vepu511_set_jpeg_reg(Vepu511JpegCfg *cfg) +{ + HalEncTask *task = ( HalEncTask *)cfg->enc_task; + JpegeSyntax *syn = (JpegeSyntax *)task->syntax.data; + JpegVepu511Frame *regs = (JpegVepu511Frame *)cfg->jpeg_reg_base; + VepuFmtCfg *fmt = (VepuFmtCfg *)cfg->input_fmt; + RK_U32 pic_width_align8, pic_height_align8; + RK_S32 stridey = 0; + RK_S32 stridec = 0; + + pic_width_align8 = (syn->width + 7) & (~7); + pic_height_align8 = (syn->height + 7) & (~7); + + regs->adr_src0 = mpp_buffer_get_fd(task->input); + regs->adr_src1 = regs->adr_src0; + regs->adr_src2 = regs->adr_src0; + + vepu511_jpeg_set_patch_info(cfg->dev, syn, (VepuFmt)fmt->format, task); + + regs->adr_bsbt = mpp_buffer_get_fd(task->output); + regs->adr_bsbb = regs->adr_bsbt; + regs->adr_bsbs = regs->adr_bsbt; + regs->adr_bsbr = regs->adr_bsbt; + + mpp_dev_set_reg_offset(cfg->dev, 258, task->length + task->hw_length); + mpp_dev_set_reg_offset(cfg->dev, 256, mpp_buffer_get_size(task->output)); + + regs->enc_rsl.pic_wd8_m1 = pic_width_align8 / 8 - 1; + regs->src_fill.pic_wfill = ((syn->width & 0x7) != 0) + ? (8 - (syn->width & 0x7)) : 0; + regs->enc_rsl.pic_hd8_m1 = pic_height_align8 / 8 - 1; + regs->src_fill.pic_hfill = ((syn->height & 0x7) != 0) + ? (8 - (syn->height & 0x7)) : 0; + + regs->src_fmt.src_cfmt = fmt->format; + regs->src_fmt.alpha_swap = fmt->alpha_swap; + regs->src_fmt.rbuv_swap = fmt->rbuv_swap; + regs->src_fmt.src_range_trns_en = 0; + regs->src_fmt.src_range_trns_sel = 0; + regs->src_fmt.chroma_ds_mode = 0; + regs->src_proc.src_mirr = syn->mirroring > 0; + regs->src_proc.src_rot = syn->rotation; + + if (MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(task->frame))) { + regs->src_proc.rkfbcd_en = 1; + + stridey = mpp_frame_get_fbc_hdr_stride(task->frame); + if (!stridey) + stridey = MPP_ALIGN(syn->hor_stride, 16) >> 2; + } else if (syn->hor_stride) { + stridey = syn->hor_stride; + } else { + if (regs->src_fmt.src_cfmt == VEPU5xx_FMT_BGRA8888) + stridey = syn->width * 4; + else if (regs->src_fmt.src_cfmt == VEPU5xx_FMT_BGR888 || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV444P || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV444SP) + stridey = syn->width * 3; + else if (regs->src_fmt.src_cfmt == VEPU5xx_FMT_BGR565 || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUYV422 || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_UYVY422) + stridey = syn->width * 2; + } + + stridec = (regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV422SP || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV420SP || + regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV444P) ? + stridey : stridey / 2; + + if (regs->src_fmt.src_cfmt == VEPU5xx_FMT_YUV444SP) + stridec = stridey * 2; + + if (regs->src_fmt.src_cfmt < VEPU5xx_FMT_ARGB1555) { + regs->src_udfy.csc_wgt_r2y = 66; + regs->src_udfy.csc_wgt_g2y = 129; + regs->src_udfy.csc_wgt_b2y = 25; + + regs->src_udfu.csc_wgt_r2u = -38; + regs->src_udfu.csc_wgt_g2u = -74; + regs->src_udfu.csc_wgt_b2u = 112; + + regs->src_udfv.csc_wgt_r2v = 112; + regs->src_udfv.csc_wgt_g2v = -94; + regs->src_udfv.csc_wgt_b2v = -18; + + regs->src_udfo.csc_ofst_y = 16; + regs->src_udfo.csc_ofst_u = 128; + regs->src_udfo.csc_ofst_v = 128; + } + + regs->src_strd0.src_strd0 = stridey; + regs->src_strd1.src_strd1 = stridec; + regs->pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + regs->pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + + regs->y_cfg.bias_y = 0; + regs->u_cfg.bias_u = 0; + regs->v_cfg.bias_v = 0; + + regs->base_cfg.jpeg_ri = syn->restart_ri; + regs->base_cfg.jpeg_out_mode = 0; + regs->base_cfg.jpeg_start_rst_m = 0; + regs->base_cfg.jpeg_pic_last_ecs = 1; + regs->base_cfg.jpeg_stnd = 1; //enable + + regs->uvc_cfg.uvc_partition0_len = 0; + regs->uvc_cfg.uvc_partition_len = 0; + regs->uvc_cfg.uvc_skip_len = 0; + return MPP_OK; +} + +static void hal_jpege_vepu511_set_roi(JpegeV511HalContext *ctx) +{ + MppJpegROICfg *roi_cfg = (MppJpegROICfg *)ctx->roi_data; + JpegV511RegSet *regs = ctx->regs; + Vepu511JpegRoi *reg_regions = ®s->reg_frm.roi_cfg[0]; + MppJpegROIRegion *region; + RK_U32 frame_width = ctx->cfg->prep.width; + RK_U32 frame_height = ctx->cfg->prep.height; + RK_S32 i; + + if (roi_cfg == NULL) + return; + + if (roi_cfg->non_roi_en) { + if (roi_cfg->non_roi_level <= MPP_MAX_JPEG_ROI_LEVEL) { + reg_regions->roi_cfg1.frm_rdoq_en = 1; + reg_regions->roi_cfg1.frm_rdoq_level = roi_cfg->non_roi_level; + } else { + mpp_err_f("none roi level[%d] is invalid\n", roi_cfg->non_roi_level); + } + } + + for (i = 0; i < MPP_MAX_JPEG_ROI_NUM; i++) { + region = &roi_cfg->regions[i]; + if (!region->roi_en) + continue; + + if (region->w == 0 || region->h == 0 || + region->x + region->w > frame_width || + region->y + region->h > frame_height) { + mpp_err_f("region[%d]: x[%d] y[%d] w[%d] h[%d] is invalid, frame width[%d] height[%d]\n", + i, region->x, region->y, region->w, + region->h, frame_width, frame_height); + continue; + } + + if (region->level > MPP_MAX_JPEG_ROI_LEVEL) { + mpp_err_f("region[%d]: roi level[%d] is invalid\n", i, region->level); + continue; + } + + reg_regions->roi_cfg0.roi0_rdoq_en = 1; + reg_regions->roi_cfg0.roi0_rdoq_start_x = MPP_ALIGN(region->x, 16) >> 3; + reg_regions->roi_cfg0.roi0_rdoq_start_y = MPP_ALIGN(region->y, 16) >> 3; + reg_regions->roi_cfg0.roi0_rdoq_level = region->level; + reg_regions->roi_cfg1.roi0_rdoq_width_m1 = (MPP_ALIGN(region->w, 16) >> 3) - 1; + reg_regions->roi_cfg1.roi0_rdoq_height_m1 = (MPP_ALIGN(region->h, 16) >> 3) - 1; + reg_regions++; + } +} + +MPP_RET hal_jpege_vepu511_gen_regs(void *hal, HalEncTask *task) +{ + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + JpegV511RegSet *regs = ctx->regs; + Vepu511ControlCfg *reg_ctl = ®s->reg_ctl; + JpegVepu511Frame *jpeg_frm = ®s->reg_frm; + JpegeBits bits = ctx->bits; + size_t length = mpp_packet_get_length(task->packet); + RK_U8 *buf = mpp_buffer_get_ptr(task->output); + size_t size = mpp_buffer_get_size(task->output); + JpegeSyntax *syntax = &ctx->syntax; + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + Vepu511JpegCfg cfg; + RK_S32 bitpos; + + hal_jpege_enter(); + cfg.enc_task = task; + cfg.jpeg_reg_base = jpeg_frm; + cfg.dev = ctx->dev; + cfg.input_fmt = ctx->input_fmt; + + memset(regs, 0, sizeof(JpegV511RegSet)); + + if (syntax->q_mode == JPEG_QFACTOR) { + syntax->q_factor = 100 - task->rc_task->info.quality_target; + hal_jpege_rc_update(&ctx->hal_rc, syntax); + } + + /* write header to output buffer */ + jpege_bits_setup(bits, buf, (RK_U32)size); + /* seek length bytes data */ + jpege_seek_bits(bits, length << 3); + /* NOTE: write header will update qtable */ + write_jpeg_header(bits, syntax, &ctx->hal_rc); + + bitpos = jpege_bits_get_bitpos(bits); + length = (bitpos + 7) >> 3; + task->hw_length = length - task->length; + mpp_buffer_sync_partial_end(task->output, 0, length); + + reg_ctl->enc_strt.lkt_num = 0; + reg_ctl->enc_strt.vepu_cmd = ctx->enc_mode; + reg_ctl->enc_clr.safe_clr = 0x0; + reg_ctl->enc_clr.force_clr = 0x0; + + reg_ctl->int_en.enc_done_en = 1; + reg_ctl->int_en.lkt_node_done_en = 1; + reg_ctl->int_en.sclr_done_en = 1; + reg_ctl->int_en.vslc_done_en = 1; + reg_ctl->int_en.vbsf_oflw_en = 1; + + reg_ctl->int_en.jbuf_lens_en = 1; + reg_ctl->int_en.enc_err_en = 1; + reg_ctl->int_en.vsrc_err_en = 1; + reg_ctl->int_en.wdg_en = 1; + reg_ctl->int_en.lkt_err_int_en = 0; + reg_ctl->int_en.lkt_err_stop_en = 0; + reg_ctl->int_en.lkt_force_stop_en = 0; + reg_ctl->int_en.jslc_done_en = 0; + reg_ctl->int_en.jbsf_oflw_en = 0; + reg_ctl->int_en.dvbm_err_en = 0; + + reg_ctl->dtrns_map.jpeg_bus_edin = 0x7; + reg_ctl->dtrns_map.src_bus_edin = 0x0; + reg_ctl->dtrns_map.meiw_bus_edin = 0x0; + reg_ctl->dtrns_map.bsw_bus_edin = 0x0; + reg_ctl->dtrns_map.lktr_bus_edin = 0x0; + reg_ctl->dtrns_map.roir_bus_edin = 0x0; + reg_ctl->dtrns_map.lktw_bus_edin = 0x0; + reg_ctl->dtrns_map.rec_nfbc_bus_edin = 0x0; + reg_ctl->dtrns_cfg.jsrc_bus_edin = fmt->src_endian; + regs->reg_frm.video_enc_pic.enc_stnd = 2; // disable h264 or hevc + + reg_ctl->dtrns_cfg.axi_brsp_cke = 0x0; + reg_ctl->enc_wdg.vs_load_thd = 0x1fffff; + regs->reg_frm.video_enc_pic.jpeg_slen_fifo = 0; + + vepu511_set_jpeg_reg(&cfg); + hal_jpege_vepu511_set_roi(ctx); + + if (ctx->osd_cfg.osd_data3) + vepu511_set_osd(&ctx->osd_cfg); + + { + RK_U16 *tbl = ®s->reg_table.qua_tab0[0]; + RK_U32 i, j; + + for ( i = 0; i < 8; i++) { + for ( j = 0; j < 8; j++) { + tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[0][j * 8 + i]; + } + } + tbl += 64; + for ( i = 0; i < 8; i++) { + for ( j = 0; j < 8; j++) { + tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[1][j * 8 + i]; + } + } + tbl += 64; + for ( i = 0; i < 8; i++) { + for ( j = 0; j < 8; j++) { + tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[1][j * 8 + i]; + } + } + } + ctx->frame_num++; + + hal_jpege_leave(); + return MPP_OK; +} + +MPP_RET hal_jpege_vepu511_start(void *hal, HalEncTask *enc_task) +{ + MPP_RET ret = MPP_OK; + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + JpegV511RegSet *hw_regs = ctx->regs; + JpegV511Status *reg_out = ctx->reg_out; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + hal_jpege_enter(); + + if (enc_task->flags.err) { + mpp_err_f("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + cfg.reg = (RK_U32*)&hw_regs->reg_ctl; + cfg.size = sizeof(Vepu511ControlCfg); + cfg.offset = VEPU511_CTL_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg.reg = &hw_regs->reg_table; + cfg.size = sizeof(Vepu511JpegTable); + cfg.offset = VEPU511_JPEGE_TABLE_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg.reg = &hw_regs->reg_frm; + cfg.size = sizeof(JpegVepu511Frame); + cfg.offset = VEPU511_JPEGE_FRAME_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg.reg = &hw_regs->reg_osd; + cfg.size = sizeof(Vepu511Osd); + cfg.offset = VEPU511_JPEGE_OSD_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU511_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->st; + cfg1.size = sizeof(JpegV511Status) - 4; + cfg1.offset = VEPU511_JPEGE_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + hal_jpege_leave(); + return ret; +} + +static MPP_RET hal_jpege_vepu511_status_check(void *hal) +{ + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + JpegV511Status *elem = (JpegV511Status *)ctx->reg_out; + + RK_U32 hw_status = elem->hw_status; + + if (hw_status & RKV_ENC_INT_LINKTABLE_FINISH) + mpp_err_f("RKV_ENC_INT_LINKTABLE_FINISH"); + + if (hw_status & RKV_ENC_INT_ONE_SLICE_FINISH) + mpp_err_f("RKV_ENC_INT_ONE_SLICE_FINISH"); + + if (hw_status & RKV_ENC_INT_SAFE_CLEAR_FINISH) + mpp_err_f("RKV_ENC_INT_SAFE_CLEAR_FINISH"); + + if (hw_status & RKV_ENC_INT_BIT_STREAM_OVERFLOW) + mpp_err_f("RKV_ENC_INT_BIT_STREAM_OVERFLOW"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_FULL) + mpp_err_f("RKV_ENC_INT_BUS_WRITE_FULL"); + + if (hw_status & RKV_ENC_INT_BUS_WRITE_ERROR) + mpp_err_f("RKV_ENC_INT_BUS_WRITE_ERROR"); + + if (hw_status & RKV_ENC_INT_BUS_READ_ERROR) + mpp_err_f("RKV_ENC_INT_BUS_READ_ERROR"); + + if (hw_status & RKV_ENC_INT_TIMEOUT_ERROR) + mpp_err_f("RKV_ENC_INT_TIMEOUT_ERROR"); + + return MPP_OK; +} + +MPP_RET hal_jpege_vepu511_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + HalEncTask *enc_task = task; + JpegV511Status *elem = (JpegV511Status *)ctx->reg_out; + hal_jpege_enter(); + + if (enc_task->flags.err) { + mpp_err_f("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + hal_jpege_vepu511_status_check(hal); + task->hw_length += elem->st.jpeg_head_bits_l32; + } + + hal_jpege_leave(); + return ret; +} + +MPP_RET hal_jpege_vepu511_get_task(void *hal, HalEncTask *task) +{ + JpegeV511HalContext *ctx = (JpegeV511HalContext *)hal; + MppFrame frame = task->frame; + EncFrmStatus *frm_status = &task->rc_task->frm; + JpegeSyntax *syntax = (JpegeSyntax *)task->syntax.data; + + hal_jpege_enter(); + + memcpy(&ctx->syntax, syntax, sizeof(ctx->syntax)); + ctx->last_frame_type = ctx->frame_type; + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr(meta, KEY_JPEG_ROI_DATA, (void **)&ctx->roi_data); + mpp_meta_get_ptr(meta, KEY_OSD_DATA3, (void **)&ctx->osd_cfg.osd_data3); + + } + + if (ctx->cfg->jpeg.update) { + hal_jpege_rc_update(&ctx->hal_rc, syntax); + ctx->cfg->jpeg.update = 0; + } + + task->rc_task->frm.is_intra = 1; + + hal_jpege_leave(); + return MPP_OK; +} + +MPP_RET hal_jpege_vepu511_ret_task(void *hal, HalEncTask *task) +{ + (void)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + hal_jpege_enter(); + + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = rc_info->quality_target; + + hal_jpege_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_jpege_vepu511 = { + .name = "hal_jpege_v511", + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegeV511HalContext), + .flag = 0, + .init = hal_jpege_vepu511_init, + .deinit = hal_jpege_vepu511_deinit, + .prepare = hal_jpege_vepu511_prepare, + .get_task = hal_jpege_vepu511_get_task, + .gen_regs = hal_jpege_vepu511_gen_regs, + .start = hal_jpege_vepu511_start, + .wait = hal_jpege_vepu511_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_jpege_vepu511_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RV1126B, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_jpege_vepu511) diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vepu511.h b/mpp/hal/rkenc/jpege/hal_jpege_vepu511.h new file mode 100644 index 000000000..1c2b25057 --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vepu511.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_JPEGE_VEPU511_H +#define HAL_JPEGE_VEPU511_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_jpege_vepu511; +#define MPP_MAX_JPEG_ROI_NUM 16 +#define MPP_MAX_JPEG_ROI_LEVEL 63 + +#endif /* HAL_JPEGE_VEPU511_H */ diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vepu511_reg.h b/mpp/hal/rkenc/jpege/hal_jpege_vepu511_reg.h new file mode 100644 index 000000000..03e2d2b98 --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vepu511_reg.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_JPEGE_VEPU511_REG_H +#define HAL_JPEGE_VEPU511_REG_H + +#include "rk_type.h" +#include "vepu511_common.h" + +#define VEPU511_JPEGE_FRAME_OFFSET (0x300) +#define VEPU511_JPEGE_TABLE_OFFSET (0x2ca0) +#define VEPU511_JPEGE_OSD_OFFSET (0x3138) +#define VEPU511_JPEGE_STATUS_OFFSET (0x4000) +#define VEPU511_JPEGE_INT_OFFSET (0x2c) + +typedef struct JpegVepu511Frame_t { + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 meiw_mode : 1; + RK_U32 reserved0 : 2; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur_hevc : 5; + RK_U32 log2_ctu_num_hevc : 5; + RK_U32 rfpr_compress_mode : 1; + RK_U32 reserved1 : 2; + RK_U32 eslf_out_e_jpeg : 1; + RK_U32 jpeg_slen_fifo : 1; + RK_U32 eslf_out_e : 1; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } video_enc_pic; + + RK_U32 reserved_reg304; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 frm_id_match : 1; + RK_U32 reserved : 3; + RK_U32 source_id : 1; + RK_U32 src_id_match : 1; + RK_U32 reserved1 : 2; + RK_U32 ch_id : 2; + RK_U32 vrsp_rtn_en : 1; + RK_U32 vinf_req_en : 1; + RK_U32 reserved2 : 12; + } enc_id; + + /* 0x0000030c reg195 - 0x000003fc reg255 */ + RK_U32 reserved195_255[61]; + + /* 0x00000400 reg256 */ + RK_U32 adr_bsbt; + + /* 0x00000404 reg257 */ + RK_U32 adr_bsbb; + + /* 0x00000408 reg258 */ + RK_U32 adr_bsbs; + + /* 0x0000040c reg259 */ + RK_U32 adr_bsbr; + + /* 0x00000410 reg260 */ + RK_U32 adr_vsy_b; + + /* 0x00000414 reg261 */ + RK_U32 adr_vsc_b; + + /* 0x00000418 reg262 */ + RK_U32 adr_vsy_t; + + /* 0x0000041c reg263 */ + RK_U32 adr_vsc_t; + + /* 0x00000420 reg264 */ + RK_U32 adr_src0; + + /* 0x00000424 reg265 */ + RK_U32 adr_src1; + + /* 0x00000428 reg266 */ + RK_U32 adr_src2; + + /* 0x0000042c reg267 */ + RK_U32 bsp_size; + + /* 0x430 - 0x43c */ + RK_U32 reserved268_271[4]; + + /* 0x00000440 reg272 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 1; + RK_U32 pp0_vnum_m1 : 4; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 1; + RK_U32 pp0_jnum_m1 : 4; + } enc_rsl; + + /* 0x00000444 reg273 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } src_fill; + + /* 0x00000448 reg274 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 reserved : 2; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved1 : 21; + } src_fmt; + + /* 0x0000044c reg275 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } src_udfy; + + /* 0x00000450 reg276 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } src_udfu; + + /* 0x00000454 reg277 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } src_udfv; + + /* 0x00000458 reg278 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } src_udfo; + + /* 0x0000045c reg279 */ + struct { + RK_U32 cr_force_value : 8; + RK_U32 cb_force_value : 8; + RK_U32 chroma_force_en : 1; + RK_U32 reserved : 9; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 reserved1 : 1; + RK_U32 rkfbcd_en : 1; + RK_U32 reserved2 : 1; + } src_proc; + + /* 0x00000460 reg280 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } pic_ofst; + + /* 0x00000464 reg281 */ + struct { + RK_U32 src_strd0 : 21; + RK_U32 reserved : 11; + } src_strd0; + + /* 0x00000468 reg282 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } src_strd1; + + /* 0x0000046c reg283 */ + struct { + RK_U32 pp_corner_filter_strength : 2; + RK_U32 reserved : 2; + RK_U32 pp_edge_filter_strength : 2; + RK_U32 reserved1 : 2; + RK_U32 pp_internal_filter_strength : 2; + RK_U32 reserved2 : 22; + } src_flt_cfg; + + /* 0x00000470 reg284 */ + struct { + RK_U32 bias_y : 15; + RK_U32 reserved : 17; + } y_cfg; + + /* 0x00000474 reg285 */ + struct { + RK_U32 bias_u : 15; + RK_U32 reserved : 17; + } u_cfg; + + /* 0x00000478 reg286 */ + struct { + RK_U32 bias_v : 15; + RK_U32 reserved : 17; + } v_cfg; + + /* 0x0000047c reg287 */ + struct { + RK_U32 jpeg_ri : 25; + RK_U32 jpeg_out_mode : 1; + RK_U32 jpeg_start_rst_m : 3; + RK_U32 jpeg_pic_last_ecs : 1; + RK_U32 reserved : 1; + RK_U32 jpeg_stnd : 1; + } base_cfg; + + /* 0x00000480 reg288 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } uvc_cfg; + + /* 0x00000484 reg289 */ + RK_U32 adr_eslf; + + /* 0x00000488 reg290 */ + struct { + RK_U32 eslf_rptr : 10; + RK_U32 eslf_wptr : 10; + RK_U32 eslf_blen : 10; + RK_U32 eslf_updt : 2; + } eslf_buf; + + /* 0x48c */ + RK_U32 reserved_291; + + /* 0x00000490 reg292 - 0x0000050c reg323*/ + Vepu511JpegRoi roi_cfg[16]; +} JpegVepu511Frame; + +typedef struct JpegV511RegSet_t { + Vepu511ControlCfg reg_ctl; + /* 0x300 - 0x50c */ + JpegVepu511Frame reg_frm; + /* 0x2ca0 - 0x2e1c */ + Vepu511JpegTable reg_table; + /* 0x00003138 reg3150 - 0x00003264 reg3225 */ + Vepu511Osd reg_osd; + /* 0x00005000 reg5120 - 0x00005230 reg5260*/ + Vepu511Dbg reg_dbg; +} JpegV511RegSet; + +typedef struct JpegV511Status_t { + RK_U32 hw_status; + Vepu511Status st; +} JpegV511Status; + +#endif diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vepu540c.c b/mpp/hal/rkenc/jpege/hal_jpege_vepu540c.c new file mode 100644 index 000000000..6f009d845 --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vepu540c.c @@ -0,0 +1,431 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_jpege_v540c" + +#include + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_soc.h" +#include "mpp_common.h" +#include "mpp_frame_impl.h" + +#include "hal_jpege_debug.h" +#include "jpege_syntax.h" +#include "hal_bufs.h" +#include "rkv_enc_def.h" +#include "vepu5xx_common.h" +#include "vepu540c_common.h" +#include "hal_jpege_vepu540c.h" +#include "hal_jpege_vepu540c_reg.h" +#include "hal_jpege_hdr.h" + +typedef struct jpegeV540cHalContext_t { + MppDev dev; + void *regs; + void *reg_out; + + void *dump_files; + + RK_S32 frame_type; + RK_S32 last_frame_type; + + /* @frame_cnt starts from ZERO */ + RK_U32 frame_cnt; + void *roi_data; + MppEncCfgSet *cfg; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + void *input_fmt; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + RK_S32 fbc_header_len; + RK_U32 title_num; + + JpegeBits bits; + JpegeSyntax syntax; + HalJpegeRc hal_rc; +} jpegeV540cHalContext; + +MPP_RET hal_jpege_v540c_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + + mpp_env_get_u32("hal_jpege_debug", &hal_jpege_debug, 0); + + hal_jpege_enter(); + + ctx->reg_out = mpp_calloc(JpegV540cStatus, 1); + ctx->regs = mpp_calloc(JpegV540cRegSet, 1); + ctx->input_fmt = mpp_calloc(VepuFmtCfg, 1); + ctx->cfg = cfg->cfg; + + ctx->frame_cnt = 0; + ctx->enc_mode = 1; + cfg->type = VPU_CLIENT_RKVENC; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + + ctx->dev = cfg->dev; + jpege_bits_init(&ctx->bits); + mpp_assert(ctx->bits); + hal_jpege_rc_init(&ctx->hal_rc); + + hal_jpege_leave(); + return ret; +} + +MPP_RET hal_jpege_v540c_deinit(void *hal) +{ + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + + hal_jpege_enter(); + jpege_bits_deinit(ctx->bits); + MPP_FREE(ctx->regs); + + MPP_FREE(ctx->reg_out); + + MPP_FREE(ctx->input_fmt); + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + hal_jpege_leave(); + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu540c_prepare(void *hal) +{ + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + + hal_jpege_dbg_func("enter %p\n", hal); + VepuFmtCfg *fmt = (VepuFmtCfg *)ctx->input_fmt; + vepu5xx_set_fmt(fmt, ctx->cfg->prep.format); + + hal_jpege_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +MPP_RET hal_jpege_v540c_gen_regs(void *hal, HalEncTask *task) +{ + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + JpegV540cRegSet *regs = ctx->regs; + jpeg_vepu540c_control_cfg *reg_ctl = ®s->reg_ctl; + jpeg_vepu540c_base *reg_base = ®s->reg_base; + JpegeBits bits = ctx->bits; + size_t length = mpp_packet_get_length(task->packet); + RK_U8 *buf = mpp_buffer_get_ptr(task->output); + size_t size = mpp_buffer_get_size(task->output); + JpegeSyntax *syntax = &ctx->syntax; + Vepu540cJpegCfg cfg; + RK_S32 bitpos; + + hal_jpege_enter(); + cfg.enc_task = task; + cfg.jpeg_reg_base = ®_base->jpegReg; + cfg.dev = ctx->dev; + cfg.input_fmt = ctx->input_fmt; + + memset(regs, 0, sizeof(JpegV540cRegSet)); + + if (syntax->q_mode == JPEG_QFACTOR) { + syntax->q_factor = 100 - task->rc_task->info.quality_target; + hal_jpege_rc_update(&ctx->hal_rc, syntax); + } + + /* write header to output buffer */ + jpege_bits_setup(bits, buf, (RK_U32)size); + /* seek length bytes data */ + jpege_seek_bits(bits, length << 3); + /* NOTE: write header will update qtable */ + write_jpeg_header(bits, syntax, &ctx->hal_rc); + + bitpos = jpege_bits_get_bitpos(bits); + length = (bitpos + 7) >> 3; + task->hw_length = length - task->length; + mpp_buffer_sync_partial_end(task->output, 0, length); + reg_ctl->reg0004_enc_strt.lkt_num = 0; + reg_ctl->reg0004_enc_strt.vepu_cmd = ctx->enc_mode; + reg_ctl->reg0005_enc_clr.safe_clr = 0x0; + reg_ctl->reg0005_enc_clr.force_clr = 0x0; + + reg_ctl->reg0008_int_en.enc_done_en = 1; + reg_ctl->reg0008_int_en.lkt_node_done_en = 1; + reg_ctl->reg0008_int_en.sclr_done_en = 1; + reg_ctl->reg0008_int_en.slc_done_en = 1; + reg_ctl->reg0008_int_en.bsf_oflw_en = 1; + reg_ctl->reg0008_int_en.brsp_otsd_en = 1; + reg_ctl->reg0008_int_en.wbus_err_en = 1; + reg_ctl->reg0008_int_en.rbus_err_en = 1; + reg_ctl->reg0008_int_en.wdg_en = 1; + reg_ctl->reg0008_int_en.lkt_err_int_en = 0; + + reg_ctl->reg0012_dtrns_map.jpeg_bus_edin = 0x7; + reg_ctl->reg0012_dtrns_map.src_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.meiw_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.bsw_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.lktr_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.roir_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.lktw_bus_edin = 0x0; + reg_ctl->reg0012_dtrns_map.rec_nfbc_bus_edin = 0x0; + reg_base->reg0192_enc_pic.enc_stnd = 2; // disable h264 or hevc + + reg_ctl->reg0013_dtrns_cfg.axi_brsp_cke = 0x0; + reg_ctl->reg0014_enc_wdg.vs_load_thd = 0x1fffff; + reg_ctl->reg0014_enc_wdg.rfp_load_thd = 0; + + vepu540c_set_jpeg_reg(&cfg); + { + RK_U16 *tbl = ®s->jpeg_table.qua_tab0[0]; + RK_U32 i, j; + + for ( i = 0; i < 8; i++) { + for ( j = 0; j < 8; j++) { + tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[0][j * 8 + i]; + } + } + tbl += 64; + for ( i = 0; i < 8; i++) { + for ( j = 0; j < 8; j++) { + tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[1][j * 8 + i]; + } + } + tbl += 64; + for ( i = 0; i < 8; i++) { + for ( j = 0; j < 8; j++) { + tbl[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[1][j * 8 + i]; + } + } + } + ctx->frame_num++; + + hal_jpege_leave(); + return MPP_OK; +} + +MPP_RET hal_jpege_v540c_start(void *hal, HalEncTask *enc_task) +{ + MPP_RET ret = MPP_OK; + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + JpegV540cRegSet *hw_regs = ctx->regs; + JpegV540cStatus *reg_out = ctx->reg_out; + MppDevRegWrCfg cfg; + MppDevRegRdCfg cfg1; + hal_jpege_enter(); + + if (enc_task->flags.err) { + mpp_err_f("enc_task->flags.err %08x, return e arly", + enc_task->flags.err); + return MPP_NOK; + } + + cfg.reg = (RK_U32*)&hw_regs->reg_ctl; + cfg.size = sizeof(jpeg_vepu540c_control_cfg); + cfg.offset = VEPU540C_CTL_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg.reg = &hw_regs->jpeg_table; + cfg.size = sizeof(vepu540c_jpeg_tab); + cfg.offset = VEPU540C_JPEGTAB_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg.reg = &hw_regs->reg_base; + cfg.size = sizeof(jpeg_vepu540c_base); + cfg.offset = VEPU540C_BASE_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->hw_status; + cfg1.size = sizeof(RK_U32); + cfg1.offset = VEPU540C_REG_BASE_HW_STATUS; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + cfg1.reg = ®_out->st; + cfg1.size = sizeof(JpegV540cStatus) - 4; + cfg1.offset = VEPU540C_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg1); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + return ret; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + hal_jpege_leave(); + return ret; +} + +//#define DUMP_DATA +static MPP_RET hal_jpege_vepu540c_status_check(void *hal) +{ + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + JpegV540cStatus *elem = (JpegV540cStatus *)ctx->reg_out; + + vepu540c_hw_status hw_status = elem->hw_status; + + hal_jpege_dbg_detail("hw_status: 0x%08x", hw_status.val); + if (hw_status.int_sta.enc_done_sta) + hal_jpege_dbg_detail("RKV_ENC_INT_ENC_DONE"); + + if (hw_status.int_sta.wdg_sta) + mpp_err_f("RKV_ENC_INT_WDG_TIMEOUT"); + + if (hw_status.int_sta.jslc_done_sta) + hal_jpege_dbg_detail("RKV_ENC_INT_JSL_DONE"); + + if (hw_status.int_sta.jbsf_oflw_sta) + mpp_err_f("RKV_ENC_INT_JBSF_OFLOW"); + + + return MPP_OK; +} + + + +MPP_RET hal_jpege_v540c_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + HalEncTask *enc_task = task; + JpegV540cStatus *elem = (JpegV540cStatus *)ctx->reg_out; + hal_jpege_enter(); + + if (enc_task->flags.err) { + mpp_err_f("enc_task->flags.err %08x, return early", + enc_task->flags.err); + return MPP_NOK; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + ret = MPP_ERR_VPUHW; + } else { + hal_jpege_vepu540c_status_check(hal); + task->hw_length += elem->st.jpeg_head_bits_l32; + } + + hal_jpege_leave(); + return ret; +} + +MPP_RET hal_jpege_v540c_get_task(void *hal, HalEncTask *task) +{ + jpegeV540cHalContext *ctx = (jpegeV540cHalContext *)hal; + MppFrame frame = task->frame; + EncFrmStatus *frm_status = &task->rc_task->frm; + JpegeSyntax *syntax = (JpegeSyntax *)task->syntax.data; + + hal_jpege_enter(); + + memcpy(&ctx->syntax, syntax, sizeof(ctx->syntax)); + + ctx->last_frame_type = ctx->frame_type; + + if (!frm_status->reencode && mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + + mpp_meta_get_ptr(meta, KEY_ROI_DATA, (void **)&ctx->roi_data); + } + + if (ctx->cfg->jpeg.update) { + hal_jpege_rc_update(&ctx->hal_rc, syntax); + ctx->cfg->jpeg.update = 0; + } + task->rc_task->frm.is_intra = 1; + + hal_jpege_leave(); + return MPP_OK; +} + +MPP_RET hal_jpege_v540c_ret_task(void *hal, HalEncTask *task) +{ + (void)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + hal_jpege_enter(); + + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = rc_info->quality_target; + + hal_jpege_leave(); + return MPP_OK; +} + +const MppEncHalApi hal_jpege_vepu540c = { + .name = "hal_jpege_v540c", + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(jpegeV540cHalContext), + .flag = 0, + .init = hal_jpege_v540c_init, + .deinit = hal_jpege_v540c_deinit, + .prepare = hal_jpege_vepu540c_prepare, + .get_task = hal_jpege_v540c_get_task, + .gen_regs = hal_jpege_v540c_gen_regs, + .start = hal_jpege_v540c_start, + .wait = hal_jpege_v540c_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_jpege_v540c_ret_task, + .client = VPU_CLIENT_RKVENC, + .soc_type = { + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3562, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_jpege_vepu540c) diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vepu540c.h b/mpp/hal/rkenc/jpege/hal_jpege_vepu540c.h new file mode 100644 index 000000000..0e0172ef7 --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vepu540c.h @@ -0,0 +1,24 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGE_VEPU540C_H +#define HAL_JPEGE_VEPU540C_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_jpege_vepu540c; + +#endif /* HAL_JPEGE_VEPU540C_H */ diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vepu540c_reg.h b/mpp/hal/rkenc/jpege/hal_jpege_vepu540c_reg.h new file mode 100644 index 000000000..22c8091b9 --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vepu540c_reg.h @@ -0,0 +1,858 @@ +/* + * Copyright 2022 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGE_VEPU540C_REG_H +#define HAL_JPEGE_VEPU540C_REG_H + +#include "rk_type.h" +#include "vepu540c_common.h" + +/* class: control/link */ +/* 0x00000000 reg0 - 0x00000120 reg72 */ +typedef struct JpegVepu540cControlCfg_t { + /* 0x00000000 reg0 */ + struct { + RK_U32 sub_ver : 8; + RK_U32 h264_cap : 1; + RK_U32 hevc_cap : 1; + RK_U32 reserved : 2; + RK_U32 res_cap : 4; + RK_U32 osd_cap : 2; + RK_U32 filtr_cap : 2; + RK_U32 bfrm_cap : 1; + RK_U32 fbc_cap : 2; + RK_U32 reserved1 : 1; + RK_U32 ip_id : 8; + } reg0001_version; + + /* 0x4 - 0xc */ + RK_U32 reserved1_3[3]; + + /* 0x00000010 reg4 */ + struct { + RK_U32 lkt_num : 8; + RK_U32 vepu_cmd : 3; + RK_U32 reserved : 21; + } reg0004_enc_strt; + + /* 0x00000014 reg5 */ + struct { + RK_U32 safe_clr : 1; + RK_U32 force_clr : 1; + RK_U32 reserved : 30; + } reg0005_enc_clr; + + /* 0x18 */ + struct { + RK_U32 vswm_lcnt_soft : 14; + RK_U32 vswm_fcnt_soft : 8; + RK_U32 reserved : 2; + RK_U32 dvbm_ack_soft : 1; + RK_U32 dvbm_ack_sel : 1; + RK_U32 reserved1 : 6; + } reg0006_vs_ldly; + + /* 0x1c */ + RK_U32 reserved007; + + /* 0x00000020 reg8 */ + struct { + RK_U32 enc_done_en : 1; + RK_U32 lkt_node_done_en : 1; + RK_U32 sclr_done_en : 1; + RK_U32 slc_done_en : 1; + RK_U32 bsf_oflw_en : 1; + RK_U32 brsp_otsd_en : 1; + RK_U32 wbus_err_en : 1; + RK_U32 rbus_err_en : 1; + RK_U32 wdg_en : 1; + RK_U32 lkt_err_int_en : 1; + RK_U32 lkt_err_stop_en : 1; + RK_U32 lkt_force_stop_en : 1; + RK_U32 jslc_done_en : 1; + RK_U32 jbsf_oflw_en : 1; + RK_U32 reserved : 18; + } reg0008_int_en; + + /* 0x00000024 reg9 */ + struct { + RK_U32 enc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 slc_done_msk : 1; + RK_U32 bsf_oflw_msk : 1; + RK_U32 brsp_otsd_msk : 1; + RK_U32 wbus_err_msk : 1; + RK_U32 rbus_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_err_msk : 1; + RK_U32 lkt_err_stop_msk : 1; + RK_U32 lkt_force_stop_msk : 1; + RK_U32 jslc_done_msk : 1; + RK_U32 jbsf_oflw_msk : 1; + RK_U32 reserved : 18; + } reg0009_int_msk; + + /* 0x00000028 reg10 */ + struct { + RK_U32 enc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 slc_done_clr : 1; + RK_U32 bsf_oflw_clr : 1; + RK_U32 brsp_otsd_clr : 1; + RK_U32 wbus_err_clr : 1; + RK_U32 rbus_err_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_err_clr : 1; + RK_U32 lkt_err_stop_msk : 1; + RK_U32 lkt_force_stop_msk : 1; + RK_U32 jslc_done_clr : 1; + RK_U32 jbsf_oflw_clr : 1; + RK_U32 reserved : 18; + } reg0010_int_clr; + + /* 0x0000002c reg11 */ + struct { + RK_U32 enc_done_sta : 1; + RK_U32 lkt_node_done_sta : 1; + RK_U32 sclr_done_sta : 1; + RK_U32 slc_done_sta : 1; + RK_U32 bsf_oflw_sta : 1; + RK_U32 brsp_otsd_sta : 1; + RK_U32 wbus_err_sta : 1; + RK_U32 rbus_err_sta : 1; + RK_U32 wdg_sta : 1; + RK_U32 lkt_err_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + RK_U32 jslc_done_sta : 1; + RK_U32 jbsf_oflw_sta : 1; + RK_U32 reserved : 18; + } reg0011_int_sta; + + /* 0x00000030 reg12 */ + struct { + RK_U32 jpeg_bus_edin : 4; + RK_U32 src_bus_edin : 4; + RK_U32 meiw_bus_edin : 4; + RK_U32 bsw_bus_edin : 4; + RK_U32 lktr_bus_edin : 4; + RK_U32 roir_bus_edin : 4; + RK_U32 lktw_bus_edin : 4; + RK_U32 rec_nfbc_bus_edin : 4; + } reg0012_dtrns_map; + + /* 0x00000034 reg13 */ + struct { + RK_U32 reserved : 16; + RK_U32 axi_brsp_cke : 10; + RK_U32 reserved1 : 6; + } reg0013_dtrns_cfg; + + /* 0x00000038 reg14 */ + struct { + RK_U32 vs_load_thd : 24; + RK_U32 rfp_load_thd : 8; + } reg0014_enc_wdg; + + /* 0x0000003c reg15 */ + struct { + RK_U32 hurry_en : 1; + RK_U32 hurry_low : 3; + RK_U32 hurry_mid : 3; + RK_U32 hurry_high : 3; + RK_U32 reserved : 22; + } reg0015_qos_cfg; + + /* 0x00000040 reg16 */ + struct { + RK_U32 qos_period : 16; + RK_U32 reserved : 16; + } reg0016_qos_perd; + + /* 0x00000044 reg17 */ + RK_U32 reg0017_hurry_thd_low; + + /* 0x00000048 reg18 */ + RK_U32 reg0018_hurry_thd_mid; + + /* 0x0000004c reg19 */ + RK_U32 reg0019_hurry_thd_high; + + /* 0x00000050 reg20 */ + struct { + RK_U32 idle_en_core : 1; + RK_U32 idle_en_axi : 1; + RK_U32 idle_en_ahb : 1; + RK_U32 reserved : 29; + } reg0020_enc_idle_en; + + /* 0x00000054 reg21 */ + struct { + RK_U32 cke : 1; + RK_U32 resetn_hw_en : 1; + RK_U32 enc_done_tmvp_en : 1; + RK_U32 sram_ckg_en : 1; + RK_U32 link_err_stop : 1; + RK_U32 reserved : 27; + } reg0021_func_en; + + /* 0x00000058 reg22 */ + struct { + RK_U32 recon32_ckg : 1; + RK_U32 iqit32_ckg : 1; + RK_U32 q32_ckg : 1; + RK_U32 t32_ckg : 1; + RK_U32 cabac32_ckg : 1; + RK_U32 recon16_ckg : 1; + RK_U32 iqit16_ckg : 1; + RK_U32 q16_ckg : 1; + RK_U32 t16_ckg : 1; + RK_U32 cabac16_ckg : 1; + RK_U32 recon8_ckg : 1; + RK_U32 iqit8_ckg : 1; + RK_U32 q8_ckg : 1; + RK_U32 t8_ckg : 1; + RK_U32 cabac8_ckg : 1; + RK_U32 recon4_ckg : 1; + RK_U32 iqit4_ckg : 1; + RK_U32 q4_ckg : 1; + RK_U32 t4_ckg : 1; + RK_U32 cabac4_ckg : 1; + RK_U32 intra32_ckg : 1; + RK_U32 intra16_ckg : 1; + RK_U32 intra8_ckg : 1; + RK_U32 intra4_ckg : 1; + RK_U32 inter_pred_ckg : 1; + RK_U32 reserved : 7; + } reg0022_rdo_ckg; + + /* 0x0000005c reg23 */ + struct { + RK_U32 core_id : 2; + RK_U32 reserved : 30; + } reg0023_enc_id; + + + /* 0x00000060 reg24 */ + struct { + RK_U32 dvbm_en : 1; + RK_U32 reserved0 : 1; + RK_U32 vinf_frm_match : 1; + RK_U32 vrsp_rtn_en : 1; + RK_U32 vrsp_half_cycle : 4; + RK_U32 reserved : 24; + } reg0024_dvbm_cfg; + + /* 0x00000064 - 0x6c*/ + RK_U32 reg025_027[3]; + + /* 0x00000070*/ + struct { + RK_U32 reserved : 4; + RK_U32 lkt_addr : 28; + } reg0028_lkt_base_addr; + + /* 0x74 - 0xfc */ + RK_U32 reserved29_63[35]; + + struct { + RK_U32 node_core_id : 2; + RK_U32 node_int : 1; + RK_U32 reserved : 1; + RK_U32 task_id : 12; + RK_U32 reserved1 : 16; + } reg0064_lkt_node_cfg; + + /* 0x00000104 reg65 */ + struct { + RK_U32 pcfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_pcfg : 28; + } reg0065_lkt_addr_pcfg; + + /* 0x00000108 reg66 */ + struct { + RK_U32 rc_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_rc_cfg : 28; + } reg0066_lkt_addr_rc_cfg; + + /* 0x0000010c reg67 */ + struct { + RK_U32 par_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_par_cfg : 28; + } reg0067_lkt_addr_par_cfg; + + /* 0x00000110 reg68 */ + struct { + RK_U32 sqi_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_sqi_cfg : 28; + } reg0068_lkt_addr_sqi_cfg; + + /* 0x00000114 reg69 */ + struct { + RK_U32 scal_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_scal_cfg : 28; + } reg0069_lkt_addr_scal_cfg; + + /* 0x00000118 reg70 */ + struct { + RK_U32 pp_cfg_rd_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_pp_cfg : 28; + } reg0070_lkt_addr_osd_cfg; + + /* 0x0000011c reg71 */ + struct { + RK_U32 st_out_en : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_st : 28; + } reg0071_lkt_addr_st; + + /* 0x00000120 reg72 */ + struct { + RK_U32 nxt_node_vld : 1; + RK_U32 reserved : 3; + RK_U32 lkt_addr_nxt : 28; + } reg0072_lkt_addr_nxt; + + +} jpeg_vepu540c_control_cfg; + +/* class: buffer/video syntax */ +/* 0x00000280 reg160 - 0x000003f4 reg253*/ +typedef struct JpegVepu540cBase_t { + vepu540c_online online_addr; + /* 0x00000280 reg160 */ + RK_U32 reg0160_adr_src0; + + /* 0x00000284 reg161 */ + RK_U32 reg0161_adr_src1; + + /* 0x00000288 reg162 */ + RK_U32 reg0162_adr_src2; + + /* 0x0000028c reg163 */ + RK_U32 reg0163_rfpw_h_addr; + + /* 0x00000290 reg164 */ + RK_U32 reg0164_rfpw_b_addr; + + /* 0x00000294 reg165 */ + RK_U32 reg0165_rfpr_h_addr; + + /* 0x00000298 reg166 */ + RK_U32 reg0166_rfpr_b_addr; + + /* 0x0000029c reg167 */ + RK_U32 reg0167_cmvw_addr; + + /* 0x000002a0 reg168 */ + RK_U32 reg0168_cmvr_addr; + + /* 0x000002a4 reg169 */ + RK_U32 reg0169_dspw_addr; + + /* 0x000002a8 reg170 */ + RK_U32 reg0170_dspr_addr; + + /* 0x000002ac reg171 */ + RK_U32 reg0171_meiw_addr; + + /* 0x000002b0 reg172 */ + RK_U32 reg0172_bsbt_addr; + + /* 0x000002b4 reg173 */ + RK_U32 reg0173_bsbb_addr; + + /* 0x000002b8 reg174 */ + RK_U32 reg0174_bsbr_addr; + + /* 0x000002bc reg175 */ + RK_U32 reg0175_adr_bsbs; + + /* 0x000002c0 reg176 */ + RK_U32 reg0176_lpfw_addr; + + /* 0x000002c4 reg177 */ + RK_U32 reg0177_lpfr_addr; + + /* 0x000002c8 reg178 */ + RK_U32 reg0178_adr_ebuft; + + /* 0x000002cc reg179 */ + RK_U32 reg0179_adr_ebufb; + + /* 0x000002d0 reg180 */ + RK_U32 reg0180_adr_rfpt_h; + + /* 0x000002d4 reg181 */ + RK_U32 reg0181_adr_rfpb_h; + + /* 0x000002d8 reg182 */ + RK_U32 reg0182_adr_rfpt_b; + + /* 0x000002dc reg183 */ + RK_U32 reg0183_adr_rfpb_b; + + /* 0x000002e0 reg184 */ + RK_U32 reg0184_adr_smr_rd; + + /* 0x000002e4 reg185 */ + RK_U32 reg0185_adr_smr_wr; + + /* 0x000002e8 reg186 */ + RK_U32 reg0186_adr_roir; + + /* 0x2ec - 0x2fc */ + RK_U32 reserved187_191[5]; + + /* 0x00000300 reg192 */ + struct { + RK_U32 enc_stnd : 2; + RK_U32 cur_frm_ref : 1; + RK_U32 mei_stor : 1; + RK_U32 bs_scp : 1; + RK_U32 reserved : 3; + RK_U32 pic_qp : 6; + RK_U32 num_pic_tot_cur : 5; + RK_U32 log2_ctu_num : 5; + RK_U32 reserved1 : 6; + RK_U32 slen_fifo : 1; + RK_U32 rec_fbc_dis : 1; + } reg0192_enc_pic; + + + /* 0x304 */ + RK_U32 reserved_193; + + /* 0x00000308 reg194 */ + struct { + RK_U32 frame_id : 8; + RK_U32 reserved : 8; + RK_U32 ch_id : 2; + RK_U32 reserved1 : 14; + } reg0194_dvbm_id; + + /* 0x0000030c reg195 */ + RK_U32 bsp_size; + + /* 0x00000310 reg196 */ + struct { + RK_U32 pic_wd8_m1 : 11; + RK_U32 reserved : 5; + RK_U32 pic_hd8_m1 : 11; + RK_U32 reserved1 : 5; + } reg0196_enc_rsl; + + /* 0x00000314 reg197 */ + struct { + RK_U32 pic_wfill : 6; + RK_U32 reserved : 10; + RK_U32 pic_hfill : 6; + RK_U32 reserved1 : 10; + } reg0197_src_fill; + + /* 0x00000318 reg198 */ + struct { + RK_U32 alpha_swap : 1; + RK_U32 rbuv_swap : 1; + RK_U32 src_cfmt : 4; + RK_U32 src_rcne : 1; + RK_U32 out_fmt : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + RK_U32 chroma_ds_mode : 1; + RK_U32 reserved : 21; + } reg0198_src_fmt; + + /* 0x0000031c reg199 */ + struct { + RK_U32 csc_wgt_b2y : 9; + RK_U32 csc_wgt_g2y : 9; + RK_U32 csc_wgt_r2y : 9; + RK_U32 reserved : 5; + } reg0199_src_udfy; + + /* 0x00000320 reg200 */ + struct { + RK_U32 csc_wgt_b2u : 9; + RK_U32 csc_wgt_g2u : 9; + RK_U32 csc_wgt_r2u : 9; + RK_U32 reserved : 5; + } reg0200_src_udfu; + + /* 0x00000324 reg201 */ + struct { + RK_U32 csc_wgt_b2v : 9; + RK_U32 csc_wgt_g2v : 9; + RK_U32 csc_wgt_r2v : 9; + RK_U32 reserved : 5; + } reg0201_src_udfv; + + /* 0x00000328 reg202 */ + struct { + RK_U32 csc_ofst_v : 8; + RK_U32 csc_ofst_u : 8; + RK_U32 csc_ofst_y : 5; + RK_U32 reserved : 11; + } reg0202_src_udfo; + + /* 0x0000032c reg203 */ + struct { + RK_U32 reserved : 26; + RK_U32 src_mirr : 1; + RK_U32 src_rot : 2; + RK_U32 reserved1 : 3; + } reg0203_src_proc; + + /* 0x00000330 reg204 */ + struct { + RK_U32 pic_ofst_x : 14; + RK_U32 reserved : 2; + RK_U32 pic_ofst_y : 14; + RK_U32 reserved1 : 2; + } reg0204_pic_ofst; + + /* 0x00000334 reg205 */ + struct { + RK_U32 src_strd0 : 17; + RK_U32 reserved : 15; + } reg0205_src_strd0; + + /* 0x00000338 reg206 */ + struct { + RK_U32 src_strd1 : 16; + RK_U32 reserved : 16; + } reg0206_src_strd1; + + /* 0x0000033c reg207 */ + struct { + RK_U32 pp_corner_filter_strength : 2; + RK_U32 reserved : 2; + RK_U32 pp_edge_filter_strength : 2; + RK_U32 reserved1 : 2; + RK_U32 pp_internal_filter_strength : 2; + RK_U32 reserved2 : 22; + } reg0207_src_flt_cfg; + + /* 0x340 - 0x34c */ + RK_U32 reserved208_211[4]; + + /* 0x00000350 reg212 */ + struct { + RK_U32 rc_en : 1; + RK_U32 aq_en : 1; + RK_U32 aq_mode : 1; + RK_U32 reserved : 9; + RK_U32 rc_ctu_num : 20; + } reg212_rc_cfg; + + /* 0x00000354 reg213 */ + struct { + RK_U32 reserved : 16; + RK_U32 rc_qp_range : 4; + RK_U32 rc_max_qp : 6; + RK_U32 rc_min_qp : 6; + } reg213_rc_qp; + + /* 0x00000358 reg214 */ + struct { + RK_U32 ctu_ebit : 20; + RK_U32 reserved : 12; + } reg214_rc_tgt; + + /* 0x35c */ + RK_U32 reserved_215; + + /* 0x00000360 reg216 */ + struct { + RK_U32 sli_splt : 1; + RK_U32 sli_splt_mode : 1; + RK_U32 sli_splt_cpst : 1; + RK_U32 reserved : 12; + RK_U32 sli_flsh : 1; + RK_U32 sli_max_num_m1 : 15; + RK_U32 reserved1 : 1; + } reg0216_sli_splt; + + /* 0x00000364 reg217 */ + struct { + RK_U32 sli_splt_byte : 20; + RK_U32 reserved : 12; + } reg0217_sli_byte; + + /* 0x00000368 reg218 */ + struct { + RK_U32 sli_splt_cnum_m1 : 20; + RK_U32 reserved : 12; + } reg0218_sli_cnum; + + /* 0x0000036c reg219 */ + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 reserved : 2; + } reg0218_uvc_cfg; + + /* 0x00000370 reg220 */ + struct { + RK_U32 cime_srch_dwnh : 4; + RK_U32 cime_srch_uph : 4; + RK_U32 cime_srch_rgtw : 4; + RK_U32 cime_srch_lftw : 4; + RK_U32 dlt_frm_num : 16; + } reg0220_me_rnge; + + /* 0x00000374 reg221 */ + struct { + RK_U32 srgn_max_num : 7; + RK_U32 cime_dist_thre : 10; + RK_U32 reserved : 3; + RK_U32 rme_srch_h : 2; + RK_U32 rme_srch_v : 2; + RK_U32 rme_dis : 3; + RK_U32 reserved1 : 1; + RK_U32 fme_dis : 3; + RK_U32 reserved2 : 1; + } reg0221_me_cfg; + + /* 0x00000378 reg222 */ + struct { + RK_U32 cime_size_rama : 10; + RK_U32 reserved : 1; + RK_U32 cime_hgt_rama : 5; + RK_U32 reserved1 : 2; + RK_U32 cme_linebuf_w : 10; + RK_U32 fme_prefsu_en : 2; + RK_U32 colmv_stor : 1; + RK_U32 colmv_load : 1; + } reg0222_me_cach; + + + /* 0x37c - 0x39c */ + RK_U32 reserved223_231[9]; + + /* 0x000003a0 reg232 */ + struct { + RK_U32 ltm_col : 1; + RK_U32 ltm_idx0l0 : 1; + RK_U32 chrm_spcl : 1; + RK_U32 cu_inter_e : 12; + RK_U32 reserved : 4; + RK_U32 cu_intra_e : 4; + RK_U32 ccwa_e : 1; + RK_U32 scl_lst_sel : 2; + RK_U32 lambda_qp_use_avg_cu16_flag : 1; + RK_U32 yuvskip_calc_en : 1; + RK_U32 atf_e : 1; + RK_U32 atr_e : 1; + RK_U32 reserved1 : 2; + } reg0232_rdo_cfg; + + /* 0x000003a4 reg233 */ + struct { + RK_U32 rdo_mark_mode : 9; + RK_U32 reserved : 23; + } reg0233_iprd_csts; + + /* 0x3a8 - 0x3ac */ + RK_U32 reserved234_235[2]; + + /* 0x000003b0 reg236 */ + + struct { + RK_U32 nal_unit_type : 6; + RK_U32 reserved : 26; + } reg0236_synt_nal; + + /* 0x000003b4 reg237 */ + struct { + RK_U32 smpl_adpt_ofst_e : 1; + RK_U32 num_st_ref_pic : 7; + RK_U32 lt_ref_pic_prsnt : 1; + RK_U32 num_lt_ref_pic : 6; + RK_U32 tmpl_mvp_e : 1; + RK_U32 log2_max_poc_lsb : 4; + RK_U32 strg_intra_smth : 1; + RK_U32 reserved : 11; + } reg0237_synt_sps; + + /* 0x000003b8 reg238 */ + struct { + RK_U32 dpdnt_sli_seg_en : 1; + RK_U32 out_flg_prsnt_flg : 1; + RK_U32 num_extr_sli_hdr : 3; + RK_U32 sgn_dat_hid_en : 1; + RK_U32 cbc_init_prsnt_flg : 1; + RK_U32 pic_init_qp : 6; + RK_U32 cu_qp_dlt_en : 1; + RK_U32 chrm_qp_ofst_prsn : 1; + RK_U32 lp_fltr_acrs_sli : 1; + RK_U32 dblk_fltr_ovrd_en : 1; + RK_U32 lst_mdfy_prsnt_flg : 1; + RK_U32 sli_seg_hdr_extn : 1; + RK_U32 cu_qp_dlt_depth : 2; + RK_U32 lpf_fltr_acrs_til : 1; + RK_U32 reserved : 10; + } reg0238_synt_pps; + + /* 0x000003bc reg239 */ + struct { + RK_U32 cbc_init_flg : 1; + RK_U32 mvd_l1_zero_flg : 1; + RK_U32 mrg_up_flg : 1; + RK_U32 mrg_lft_flg : 1; + RK_U32 reserved : 1; + RK_U32 ref_pic_lst_mdf_l0 : 1; + RK_U32 num_refidx_l1_act : 2; + RK_U32 num_refidx_l0_act : 2; + RK_U32 num_refidx_act_ovrd : 1; + RK_U32 sli_sao_chrm_flg : 1; + RK_U32 sli_sao_luma_flg : 1; + RK_U32 sli_tmprl_mvp_e : 1; + RK_U32 pic_out_flg : 1; + RK_U32 sli_type : 2; + RK_U32 sli_rsrv_flg : 7; + RK_U32 dpdnt_sli_seg_flg : 1; + RK_U32 sli_pps_id : 6; + RK_U32 no_out_pri_pic : 1; + } reg0239_synt_sli0; + + /* 0x000003c0 reg240 */ + struct { + RK_U32 sp_tc_ofst_div2 : 4; + RK_U32 sp_beta_ofst_div2 : 4; + RK_U32 sli_lp_fltr_acrs_sli : 1; + RK_U32 sp_dblk_fltr_dis : 1; + RK_U32 dblk_fltr_ovrd_flg : 1; + RK_U32 sli_cb_qp_ofst : 5; + RK_U32 sli_qp : 6; + RK_U32 max_mrg_cnd : 2; + RK_U32 reserved : 1; + RK_U32 col_ref_idx : 1; + RK_U32 col_frm_l0_flg : 1; + RK_U32 lst_entry_l0 : 4; + RK_U32 reserved1 : 1; + } reg0240_synt_sli1; + + /* 0x000003c4 reg241 */ + struct { + RK_U32 sli_poc_lsb : 16; + RK_U32 sli_hdr_ext_len : 9; + RK_U32 reserved : 7; + } reg0241_synt_sli2; + + /* 0x000003c8 reg242 */ + + struct { + RK_U32 st_ref_pic_flg : 1; + RK_U32 poc_lsb_lt0 : 16; + RK_U32 lt_idx_sps : 5; + RK_U32 num_lt_pic : 2; + RK_U32 st_ref_pic_idx : 6; + RK_U32 num_lt_sps : 2; + } reg0242_synt_refm0; + + /* 0x000003cc reg243 */ + struct { + RK_U32 used_by_s0_flg : 4; + RK_U32 num_pos_pic : 1; + RK_U32 num_negative_pics : 5; + RK_U32 dlt_poc_msb_cycl0 : 16; + RK_U32 dlt_poc_msb_prsnt0 : 1; + RK_U32 dlt_poc_msb_prsnt1 : 1; + RK_U32 dlt_poc_msb_prsnt2 : 1; + RK_U32 used_by_lt_flg0 : 1; + RK_U32 used_by_lt_flg1 : 1; + RK_U32 used_by_lt_flg2 : 1; + } reg0243_synt_refm1; + + /* 0x000003d0 reg244 */ + struct { + RK_U32 dlt_poc_s0_m10 : 16; + RK_U32 dlt_poc_s0_m11 : 16; + } reg0244_synt_refm2; + /* 0x000003d4 reg245 */ + struct { + RK_U32 dlt_poc_s0_m12 : 16; + RK_U32 dlt_poc_s0_m13 : 16; + } reg0245_synt_refm3; + + /* 0x000003d8 reg246 */ + struct { + RK_U32 poc_lsb_lt1 : 16; + RK_U32 poc_lsb_lt2 : 16; + } reg0246_synt_long_refm0; + + /* 0x000003dc reg247 */ + struct { + RK_U32 dlt_poc_msb_cycl1 : 16; + RK_U32 dlt_poc_msb_cycl2 : 16; + } reg0247_synt_long_refm1; + + struct { + RK_U32 sao_lambda_multi : 4; + RK_U32 reserved : 20; + RK_U32 reserved1 : 8; + } reg0248_sao_cfg; + + /* 0x3e4 - 0x3ec */ + RK_U32 reserved249_251[3]; + + /* 0x000003f0 reg252 */ + struct { + RK_U32 tile_w_m1 : 8; + RK_U32 reserved : 8; + RK_U32 tile_h_m1 : 8; + RK_U32 reserved1 : 7; + RK_U32 tile_en : 1; + } reg0252_tile_cfg; + /* 0x000003f4 reg253 */ + struct { + RK_U32 tile_x : 8; + RK_U32 reserved : 8; + RK_U32 tile_y : 8; + RK_U32 reserved1 : 8; + } reg0253_tile_pos; + + /* 0x3f8 - 0x3fc */ + RK_U32 reserved254_255[2]; + + /* 0x00000400 reg256 - 0x00000480 reg288 */ + Vepu540cJpegReg jpegReg; + +} jpeg_vepu540c_base; + +typedef struct JpegV540cRegSet_t { + jpeg_vepu540c_control_cfg reg_ctl; + jpeg_vepu540c_base reg_base; + vepu540c_jpeg_tab jpeg_table; + vepu540c_dbg reg_dbg; +} JpegV540cRegSet; + +typedef struct JpegV540cStatus_t { + vepu540c_hw_status hw_status; + vepu540c_status st; +} JpegV540cStatus; + +#endif diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vpu720.c b/mpp/hal/rkenc/jpege/hal_jpege_vpu720.c new file mode 100644 index 000000000..6725340ee --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vpu720.c @@ -0,0 +1,762 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_jpege_vpu720" + +#include + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_common.h" +#include "mpp_platform.h" +#include "mpp_buffer_impl.h" +#include "mpp_enc_hal.h" + +#include "jpege_syntax.h" +#include "hal_hw_id.h" +#include "hal_jpege_hdr.h" +#include "hal_jpege_debug.h" +#include "hal_jpege_vpu720.h" +#include "hal_jpege_vpu720_reg.h" + +typedef enum JpegeVpu720InFmt_e { + JPEGE_VPU720_IN_FMT_TILE_400, + JPEGE_VPU720_IN_FMT_TILE_420, + JPEGE_VPU720_IN_FMT_TILE_422, + JPEGE_VPU720_IN_FMT_TILE_444, + JPEGE_VPU720_IN_FMT_YUV422SP, + JPEGE_VPU720_IN_FMT_YUV422P, + JPEGE_VPU720_IN_FMT_YUV420SP, + JPEGE_VPU720_IN_FMT_YUV420P, + JPEGE_VPU720_IN_FMT_YUYV, + JPEGE_VPU720_IN_FMT_UYVY, + JPEGE_VPU720_IN_FMT_YUV400, + JPEGE_VPU720_IN_FMT_RESERVED, + JPEGE_VPU720_IN_FMT_YUV444SP, + JPEGE_VPU720_IN_FMT_YUV444P, +} JpegeVpu720InFmt; + +typedef enum JpegeVpu720OutFmt_e { + JPEGE_VPU720_OUT_FMT_400 = 0, + JPEGE_VPU720_OUT_FMT_420 = 1, + JPEGE_VPU720_OUT_FMT_422 = 2, + JPEGE_VPU720_OUT_FMT_444 = 3, +} JpegeVpu720OutFmt; + +typedef enum JpegeVpu720EncCmd_e { + JPEG_VPU720_ENC_MODE_NONE, + JPEG_VPU720_ENC_MODE_ONE_FRAME, + JPEG_VPU720_ENC_MODE_MULTI_FRAME_START, + JPEG_VPU720_ENC_MODE_MULTI_FRAME_UPDATE, + JPEG_VPU720_ENC_MODE_LKT_FORCE_PAUSE, + JPEG_VPU720_ENC_MODE_LKT_CONTINUE, + JPEG_VPU720_ENC_MODE_SAFE_CLR, + JPEG_VPU720_ENC_MODE_FORCE_CLR, + JPEG_VPU720_ENC_MODE_FORCE_BUTT, +} JpegeVpu720EncCmd; + +typedef enum JPEGVpu720ColorRangeTrans_t { + JPEG_VPU720_COLOR_RANGE_FULL_TO_LIMIT, + JPEG_VPU720_COLOR_RANGE_LIMIT_TO_FULL, +} JPEGVpu720ColorRangeTrans; + +typedef enum JPEGVpu720ChromaDownSampleMode_t { + JPEG_VPU720_CHROMA_DOWN_SAMPLE_MODE_Average, + JPEG_VPU720_CHROMA_DOWN_SAMPLE_MODE_Discard, +} JPEGVpu720ChromaDownSampleMode; + +typedef struct JpegeVpu720FmtCfg_t { + JpegeVpu720InFmt input_format; + JpegeVpu720OutFmt out_format; + MppFrameColorRange src_range; + MppFrameColorRange dst_range; + JPEGVpu720ChromaDownSampleMode chroma_ds_mode; + RK_U32 uv_swap; + RK_U32 mirror; + RK_U32 fix_chroma_en; + RK_U32 fix_chroma_u; + RK_U32 fix_chroma_v; + RK_U32 out_nb_comp; + RK_U32 y_stride; + RK_U32 uv_stride; + RK_U32 u_offset; + RK_U32 v_offset; +} JpegeVpu720FmtCfg; + +typedef struct JpegeVpu720HalCtx_t { + MppDev dev; + void *regs; + + /* @frame_cnt starts from ZERO */ + RK_U32 frame_cnt; + MppEncCfgSet *cfg; + + RK_U32 enc_mode; + RK_U32 frame_size; + RK_S32 max_buf_cnt; + RK_S32 hdr_status; + JpegeVpu720FmtCfg fmt_cfg; + RK_U8 *src_buf; + RK_U8 *dst_buf; + RK_S32 buf_size; + RK_U32 frame_num; + + JpegeBits bits; + JpegeSyntax syntax; + RK_S32 hal_start_pos; + + MppBufferGroup group; + MppBuffer qtbl_buffer; + RK_U16 *qtbl_sw_buf; + HalJpegeRc hal_rc; + + RK_U32 is_vpu730; + void *roi_data; +} JpegeVpu720HalCtx; + +#define JPEGE_VPU720_QTABLE_SIZE (64 * 3) + +static MPP_RET hal_jpege_vpu720_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + JpegeVpu720HalCtx *ctx = (JpegeVpu720HalCtx *)hal; + + mpp_env_get_u32("hal_jpege_debug", &hal_jpege_debug, 0); + + hal_jpege_enter(); + + ctx->regs = mpp_calloc(JpegeVpu720Reg, 1); + ctx->cfg = cfg->cfg; + + ctx->frame_cnt = 0; + ctx->enc_mode = JPEG_VPU720_ENC_MODE_ONE_FRAME; + cfg->type = VPU_CLIENT_JPEG_ENC; + ctx->is_vpu730 = (HWID_JPEGE_VPU730 == mpp_get_client_hw_id(cfg->type) ? 1 : 0); + + ret = mpp_dev_init(&cfg->dev, cfg->type); + + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + + ctx->dev = cfg->dev; + jpege_bits_init(&ctx->bits); + mpp_assert(ctx->bits); + if (ctx->group == NULL) { + ret = mpp_buffer_group_get_internal(&ctx->group, MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err_f("mpp_buffer_group_get failed ret %d\n", ret); + return ret; + } + } + + ret = mpp_buffer_get(ctx->group, &ctx->qtbl_buffer, JPEGE_VPU720_QTABLE_SIZE * sizeof(RK_U16)); + mpp_buffer_attach_dev(ctx->qtbl_buffer, ctx->dev); + ctx->qtbl_sw_buf = (RK_U16 *)mpp_calloc(RK_U16, JPEGE_VPU720_QTABLE_SIZE); + hal_jpege_rc_init(&ctx->hal_rc); + + hal_jpege_leave(); + return ret; +} + +static MPP_RET hal_jpege_vpu720_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + JpegeVpu720HalCtx *ctx = (JpegeVpu720HalCtx *)hal; + + hal_jpege_enter(); + jpege_bits_deinit(ctx->bits); + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->qtbl_sw_buf); + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + if (ctx->qtbl_buffer) { + ret = mpp_buffer_put(ctx->qtbl_buffer); + if (ret) { + mpp_err_f("put qtbl buffer failed\n"); + } + } + + if (ctx->group) { + ret = mpp_buffer_group_put(ctx->group); + if (ret) { + mpp_err_f("group free buffer failed\n"); + } + } + + hal_jpege_leave(); + return MPP_OK; +} + +static MPP_RET jpege_vpu720_setup_format(void *hal, HalEncTask *task) +{ + JpegeVpu720HalCtx *ctx = (JpegeVpu720HalCtx *) hal; + MppFrameFormat in_fmt = ctx->cfg->prep.format & MPP_FRAME_FMT_MASK; + JpegeVpu720FmtCfg *fmt_cfg = &ctx->fmt_cfg; + JpegeSyntax *syntax = &ctx->syntax; + MppFrameChromaFormat out_fmt = syntax->format_out; + RK_U32 hor_stride = mpp_frame_get_hor_stride(task->frame); + RK_U32 ver_stride = mpp_frame_get_ver_stride(task->frame); + + hal_jpege_enter(); + + memset(fmt_cfg, 0, sizeof(JpegeVpu720FmtCfg)); + + if (MPP_FRAME_FMT_IS_TILE(ctx->cfg->prep.format)) { + switch (in_fmt) { + case MPP_FMT_YUV400: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_TILE_400; + fmt_cfg->y_stride = hor_stride * 4; + fmt_cfg->out_format = JPEGE_VPU720_OUT_FMT_400; + break; + case MPP_FMT_YUV420P: + case MPP_FMT_YUV420SP: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_TILE_420; + fmt_cfg->y_stride = hor_stride * 4 * 3 / 2; + break; + case MPP_FMT_YUV422P: + case MPP_FMT_YUV422SP: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_TILE_422; + fmt_cfg->y_stride = hor_stride * 4 * 2; + break; + case MPP_FMT_YUV444P: + case MPP_FMT_YUV444SP: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_TILE_444; + fmt_cfg->y_stride = hor_stride * 4 * 3; + break; + default: + mpp_err("Unsupported input format 0x%08x, with TILE mask.\n", in_fmt); + return MPP_ERR_VALUE; + break; + } + } else { + switch (in_fmt) { + case MPP_FMT_YUV400: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV400; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->out_format = JPEGE_VPU720_OUT_FMT_400; + break; + case MPP_FMT_YUV420P: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV420P; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride >> 1; + fmt_cfg->u_offset = hor_stride * ver_stride; + fmt_cfg->v_offset = fmt_cfg->u_offset + fmt_cfg->uv_stride * (ver_stride >> 1); + break; + case MPP_FMT_YUV420SP: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV420SP; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride; + fmt_cfg->u_offset = hor_stride * ver_stride; + break; + case MPP_FMT_YUV420SP_VU: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV420SP; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride; + fmt_cfg->u_offset = hor_stride * ver_stride; + fmt_cfg->uv_swap = 1; + break; + case MPP_FMT_YUV422P: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV422P; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride >> 1; + fmt_cfg->u_offset = hor_stride * ver_stride; + fmt_cfg->v_offset = fmt_cfg->u_offset + fmt_cfg->uv_stride * ver_stride; + break; + case MPP_FMT_YUV422SP: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV422SP; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride; + fmt_cfg->u_offset = hor_stride * ver_stride; + break; + case MPP_FMT_YUV422SP_VU: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV422SP; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride; + fmt_cfg->u_offset = hor_stride * ver_stride; + fmt_cfg->uv_swap = 1; + break; + case MPP_FMT_YUV422_YUYV: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUYV; + fmt_cfg->y_stride = hor_stride; + break; + case MPP_FMT_YUV422_UYVY: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_UYVY; + fmt_cfg->y_stride = hor_stride; + break; + case MPP_FMT_YUV422_YVYU: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUYV; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_swap = 1; + break; + case MPP_FMT_YUV422_VYUY: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_UYVY; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_swap = 1; + break; + case MPP_FMT_YUV444SP: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV444SP; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride << 1; + fmt_cfg->u_offset = hor_stride * ver_stride; + break; + case MPP_FMT_YUV444P: + fmt_cfg->input_format = JPEGE_VPU720_IN_FMT_YUV444P; + fmt_cfg->y_stride = hor_stride; + fmt_cfg->uv_stride = hor_stride; + fmt_cfg->u_offset = hor_stride * ver_stride; + fmt_cfg->v_offset = fmt_cfg->u_offset << 1; + break; + default : + mpp_err("Unsupported input format 0x%08x\n", in_fmt); + return MPP_ERR_VALUE; + break; + } + } + + switch (out_fmt) { + case MPP_CHROMA_400: + ctx->fmt_cfg.out_format = JPEGE_VPU720_OUT_FMT_400; + break; + case MPP_CHROMA_420: + ctx->fmt_cfg.out_format = JPEGE_VPU720_OUT_FMT_420; + break; + case MPP_CHROMA_422: + ctx->fmt_cfg.out_format = JPEGE_VPU720_OUT_FMT_422; + break; + case MPP_CHROMA_444: + ctx->fmt_cfg.out_format = JPEGE_VPU720_OUT_FMT_444; + break; + default: + ctx->fmt_cfg.out_format = JPEGE_VPU720_OUT_FMT_420; + break; + } + ctx->fmt_cfg.out_nb_comp = ctx->syntax.nb_components; + + switch (ctx->cfg->prep.chroma_ds_mode) { + case MPP_FRAME_CHORMA_DOWN_SAMPLE_MODE_AVERAGE: + ctx->fmt_cfg.chroma_ds_mode = JPEG_VPU720_CHROMA_DOWN_SAMPLE_MODE_Average; + break; + case MPP_FRAME_CHORMA_DOWN_SAMPLE_MODE_DISCARD: + ctx->fmt_cfg.chroma_ds_mode = JPEG_VPU720_CHROMA_DOWN_SAMPLE_MODE_Discard; + break; + default: + ctx->fmt_cfg.chroma_ds_mode = JPEG_VPU720_CHROMA_DOWN_SAMPLE_MODE_Average; + break; + } + + hal_jpege_dbg_detail("JPEG format: in 0x%x out 0x%x, hw in_fmt %d, out_fmt %d, ds_mode %d\n", + ctx->cfg->prep.format, ctx->cfg->prep.format_out, + ctx->fmt_cfg.input_format, ctx->fmt_cfg.out_format, + ctx->fmt_cfg.chroma_ds_mode); + + if (ctx->cfg->prep.mirroring) + ctx->fmt_cfg.mirror = 1; + + if (ctx->cfg->prep.fix_chroma_en) { + ctx->fmt_cfg.fix_chroma_en = 1; + ctx->fmt_cfg.fix_chroma_u = ctx->cfg->prep.fix_chroma_u & 0xff; + ctx->fmt_cfg.fix_chroma_v = ctx->cfg->prep.fix_chroma_v & 0xff; + } + + ctx->fmt_cfg.src_range = (ctx->cfg->prep.range == MPP_FRAME_RANGE_UNSPECIFIED) ? + MPP_FRAME_RANGE_JPEG : ctx->cfg->prep.range; + ctx->fmt_cfg.dst_range = (ctx->cfg->prep.range_out == MPP_FRAME_RANGE_UNSPECIFIED) ? + MPP_FRAME_RANGE_JPEG : ctx->cfg->prep.range_out; + hal_jpege_leave(); + return MPP_OK; +} + +#define JPEGE_VPU730_ROI_LEVEL_MAX 63 + +static MPP_RET hal_jpege_vpu730_set_roi(JpegeVpu720HalCtx *ctx) +{ + MPP_RET ret = MPP_OK; + MppJpegROICfg *roi_cfg = (MppJpegROICfg *) ctx->roi_data; + rk_u32 frame_width = ctx->cfg->prep.width; + rk_u32 frame_height = ctx->cfg->prep.height; + JpegeVpu720Reg *regs = (JpegeVpu720Reg *)ctx->regs; + JpegeVpu730RoiReg *roi_reg = regs->reg_rdo.reg_roi; + MppJpegROIRegion *region; + rk_u32 i; + + if (!roi_cfg) + return ret; + + if (roi_cfg->non_roi_en) { + if (roi_cfg->non_roi_level <= JPEGE_VPU730_ROI_LEVEL_MAX) { + regs->reg_rdo.reg_frm_rdoq_cfg.en = 1; + regs->reg_rdo.reg_frm_rdoq_cfg.level = roi_cfg->non_roi_level; + } else { + mpp_err_f("invalid roi level %d for none-roi reigon\n", roi_cfg->non_roi_level); + } + } + + for (i = 0; i < JPEGE_VPU730_REG_ROI_NUM; i++) { + region = &roi_cfg->regions[i]; + + if (!region || !region->roi_en) + continue; + + if (region->w == 0 || region->h == 0 || region->x + region->w > frame_width || + region->y + region->h > frame_height) { + mpp_err_f("region[%d]: x[%d] y[%d] w[%d] h[%d] is out of image, frame width[%d] height[%d]\n", + i, region->x, region->y, region->w, + region->h, frame_width, frame_height); + continue; + } + + if (region->level > JPEGE_VPU730_ROI_LEVEL_MAX) { + mpp_err_f("region[%d]: roi level %d is invlaid\n", i, region->level); + continue; + } + + roi_reg[i].rdoq_cfg.en = 1; + roi_reg[i].rdoq_cfg.level = region->level; + roi_reg[i].rdoq_pos.start_x_in16 = MPP_ALIGN(region->x, 16) >> 4; + roi_reg[i].rdoq_pos.start_y_in16 = MPP_ALIGN(region->y, 16) >> 4; + roi_reg[i].rdoq_size.width_in16_m1 = (MPP_ALIGN(region->w, 16) >> 4) - 1; + roi_reg[i].rdoq_size.height_in16_m1 = (MPP_ALIGN(region->h, 16) >> 4) - 1; + } + + return ret; +} + +MPP_RET hal_jpege_vpu720_gen_regs(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + JpegeVpu720HalCtx *ctx = (JpegeVpu720HalCtx *) hal; + JpegeVpu720Reg *regs = ctx->regs; + JpegeVpu720BaseReg *reg_base = ®s->reg_base; + JpegeBits bits = ctx->bits; + size_t length = mpp_packet_get_length(task->packet); + RK_U8 *buf = mpp_buffer_get_ptr(task->output); + size_t size = mpp_buffer_get_size(task->output); + JpegeSyntax *syntax = &ctx->syntax; + RK_U8 *qtbl_base = (RK_U8 *)mpp_buffer_get_ptr(ctx->qtbl_buffer); + RK_S32 bitpos; + RK_U32 i, j; + RK_U32 encode_width; + RK_U32 encode_height; + + hal_jpege_enter(); + + jpege_vpu720_setup_format(hal, task); + + memset(regs, 0, sizeof(JpegeVpu720Reg)); + + mpp_buffer_sync_begin(task->output); + + if (syntax->q_mode == JPEG_QFACTOR) { + syntax->q_factor = 100 - task->rc_task->info.quality_target; + hal_jpege_rc_update(&ctx->hal_rc, syntax); + } + + jpege_bits_setup(bits, buf, (RK_U32)size); + jpege_seek_bits(bits, length << 3); + write_jpeg_header(bits, syntax, &ctx->hal_rc); + + bitpos = jpege_bits_get_bitpos(bits); + length = (bitpos + 7) >> 3; + task->hw_length = length - task->length; + mpp_buffer_sync_partial_end(task->output, 0, length); + + reg_base->reg001_enc_strt.lkt_num = 0; + reg_base->reg001_enc_strt.vepu_cmd = ctx->enc_mode; + + // interupt + reg_base->reg004_int_en.fenc_done_en = 1; + reg_base->reg004_int_en.lkt_node_done_en = 1; + reg_base->reg004_int_en.sclr_done_en = 1; + reg_base->reg004_int_en.vslc_done_en = 1; + reg_base->reg004_int_en.vbsb_oflw_en = 1; + reg_base->reg004_int_en.vbsb_sct_en = 1; + reg_base->reg004_int_en.fenc_err_en = 1; + reg_base->reg004_int_en.wdg_en = 1; + reg_base->reg004_int_en.lkt_oerr_en = 1; + reg_base->reg004_int_en.lkt_estp_en = 1; + reg_base->reg004_int_en.lkt_fstp_en = 1; + reg_base->reg004_int_en.lkt_note_stp_en = 1; + reg_base->reg004_int_en.lkt_data_error_en = 1; + + reg_base->reg005_int_msk.fenc_done_msk = 1; + reg_base->reg005_int_msk.lkt_node_done_msk = 1; + reg_base->reg005_int_msk.sclr_done_msk = 1; + reg_base->reg005_int_msk.vslc_done_msk = 1; + reg_base->reg005_int_msk.vbsb_oflw_msk = 1; + reg_base->reg005_int_msk.vbsb_sct_msk = 1; + reg_base->reg005_int_msk.fenc_err_msk = 1; + reg_base->reg005_int_msk.wdg_msk = 1; + reg_base->reg005_int_msk.lkt_oerr_msk = 1; + reg_base->reg005_int_msk.lkt_estp_msk = 1; + reg_base->reg005_int_msk.lkt_fstp_msk = 1; + reg_base->reg005_int_msk.lkt_note_stp_msk = 1; + reg_base->reg005_int_msk.lkt_data_error_msk = 1; + + reg_base->reg008_cru_ctrl.resetn_hw_en = 1; + reg_base->reg008_cru_ctrl.sram_ckg_en = 1; + reg_base->reg008_cru_ctrl.cke = 1; + + reg_base->reg042_dbus_endn.jbsw_bus_edin = 0xf; + reg_base->reg042_dbus_endn.vsl_bus_edin = 0; + reg_base->reg042_dbus_endn.ecs_len_edin = 0xf; + reg_base->reg042_dbus_endn.sw_qtbl_edin = 0; + + reg_base->reg011_wdg_jpeg = syntax->mcu_cnt * 1000; + + reg_base->reg026_axi_perf_ctrl0.perf_work_e = 1; + reg_base->reg026_axi_perf_ctrl0.perf_clr_e = 1; + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + ctx->qtbl_sw_buf[i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[0][j * 8 + i]; + ctx->qtbl_sw_buf[64 + i * 8 + j] = 0x8000 / ctx->hal_rc.qtables[1][j * 8 + i]; + } + } + + memcpy(&ctx->qtbl_sw_buf[64 * 2], &ctx->qtbl_sw_buf[64], sizeof(RK_U16) * 64); + + encode_width = MPP_ALIGN(syntax->width, syntax->mcu_width); + encode_height = MPP_ALIGN(syntax->height, syntax->mcu_height); + reg_base->reg029_sw_enc_rsl.pic_wd8_m1 = encode_width / 8 - 1; + reg_base->reg029_sw_enc_rsl.pic_hd8_m1 = encode_height / 8 - 1; + reg_base->reg030_sw_src_fill.pic_wfill_jpeg = encode_width - syntax->width; + reg_base->reg030_sw_src_fill.pic_hfill_jpeg = encode_height - syntax->height; + + reg_base->reg032_sw_src_fmt.src_fmt = ctx->fmt_cfg.input_format; + reg_base->reg032_sw_src_fmt.out_fmt = ctx->fmt_cfg.out_format; + reg_base->reg032_sw_src_fmt.rbuv_swap_jpeg = ctx->fmt_cfg.uv_swap; + reg_base->reg032_sw_src_fmt.chroma_ds_mode = ctx->fmt_cfg.chroma_ds_mode; + reg_base->reg032_sw_src_fmt.src_mirr_jpeg = ctx->fmt_cfg.mirror; + reg_base->reg032_sw_src_fmt.chroma_force_en = ctx->fmt_cfg.fix_chroma_en; + reg_base->reg032_sw_src_fmt.u_force_value = ctx->fmt_cfg.fix_chroma_u; + reg_base->reg032_sw_src_fmt.v_force_value = ctx->fmt_cfg.fix_chroma_v; + + if (ctx->fmt_cfg.src_range != ctx->fmt_cfg.dst_range) { + reg_base->reg032_sw_src_fmt.src_range_trns_en = 1; + if (ctx->fmt_cfg.src_range == MPP_FRAME_RANGE_MPEG) + reg_base->reg032_sw_src_fmt.src_range_trns_sel = JPEG_VPU720_COLOR_RANGE_LIMIT_TO_FULL; + else + reg_base->reg032_sw_src_fmt.src_range_trns_sel = JPEG_VPU720_COLOR_RANGE_FULL_TO_LIMIT; + } + + reg_base->reg033_sw_pic_ofst.pic_ofst_x = mpp_frame_get_offset_x(task->frame); + reg_base->reg033_sw_pic_ofst.pic_ofst_y = mpp_frame_get_offset_y(task->frame); + + reg_base->reg034_sw_src_strd_0.src_strd_0 = ctx->fmt_cfg.y_stride; + reg_base->reg035_sw_src_strd_1.src_strd_1 = ctx->fmt_cfg.uv_stride; + + reg_base->reg036_sw_jpeg_enc_cfg.rst_intv = syntax->restart_ri; + reg_base->reg036_sw_jpeg_enc_cfg.rst_m = 0; + reg_base->reg036_sw_jpeg_enc_cfg.pic_last_ecs = 1; + + reg_base->reg022_adr_src0 = mpp_buffer_get_fd(task->input); + reg_base->reg023_adr_src1 = reg_base->reg022_adr_src0; + reg_base->reg024_adr_src2 = reg_base->reg022_adr_src0; + + reg_base->reg017_adr_bsbt = mpp_buffer_get_fd(task->output); + reg_base->reg018_adr_bsbb = reg_base->reg017_adr_bsbt; + reg_base->reg019_adr_bsbr = reg_base->reg017_adr_bsbt; + reg_base->reg020_adr_bsbs = reg_base->reg017_adr_bsbt; + + reg_base->reg016_adr_qtbl = mpp_buffer_get_fd(ctx->qtbl_buffer); + memcpy(qtbl_base, ctx->qtbl_sw_buf, JPEGE_VPU720_QTABLE_SIZE * sizeof(RK_U16)); + mpp_buffer_sync_end(ctx->qtbl_buffer); + + mpp_dev_set_reg_offset(ctx->dev, 20, length); + mpp_dev_set_reg_offset(ctx->dev, 17, mpp_buffer_get_size(task->output)); + mpp_dev_set_reg_offset(ctx->dev, 23, ctx->fmt_cfg.u_offset); + mpp_dev_set_reg_offset(ctx->dev, 24, ctx->fmt_cfg.v_offset); + + ctx->frame_num++; + + if (ctx->is_vpu730) + hal_jpege_vpu730_set_roi(ctx); + + hal_jpege_leave(); + return ret; +} + +MPP_RET hal_jpege_vpu720_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + JpegeVpu720HalCtx *ctx = (JpegeVpu720HalCtx *) hal; + JpegeVpu720Reg *regs = ctx->regs; + MppDevRegWrCfg cfg_base; + MppDevRegRdCfg cfg_st; + + hal_jpege_enter(); + + if (task->flags.err) { + mpp_err_f("task->flags.err 0x%08x, return early\n", task->flags.err); + return MPP_NOK; + } + + if (hal_jpege_debug & HAL_JPEGE_DBG_DETAIL) { + RK_U32 i = 0; + RK_U32 *reg = (RK_U32 *)regs; + + for (i = 0; i < 43; i++) { + mpp_log_f("set reg[%03d] : %04x : 0x%08x\n", i, i * 4, reg[i]); + } + } + + cfg_base.reg = ®s->reg_base; + cfg_base.size = sizeof(JpegeVpu720BaseReg); + cfg_base.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg_base); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + return ret; + } + + if (ctx->is_vpu730) { + cfg_base.reg = ®s->reg_rdo; + cfg_base.size = sizeof(JpegeVpu730RdoReg); + cfg_base.offset = JPEGE_VPU730_REG_ROI_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &cfg_base); + + if (ret) { + mpp_err_f("set RDO register write failed %d\n", ret); + return ret; + } + } + + cfg_st.reg = ®s->int_state; + cfg_st.size = sizeof(RK_U32); + cfg_st.offset = JPEGE_VPU720_REG_BASE_INT_STATE; + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg_st); + if (ret) { + mpp_err_f("set register to read int state failed %d\n", ret); + } + cfg_st.reg = ®s->reg_st; + cfg_st.size = sizeof(JpegeVpu720StatusReg); + cfg_st.offset = JPEGE_VPU720_REG_STATUS_OFFSET; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &cfg_st); + + if (ret) { + mpp_err_f("set register to read hw status failed %d\n", ret); + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + } + + hal_jpege_leave(); + return MPP_OK; +} + +MPP_RET hal_jpege_vpu720_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + JpegeVpu720HalCtx *ctx = (JpegeVpu720HalCtx *) hal; + JpegeVpu720Reg *regs = (JpegeVpu720Reg *)ctx->regs; + JpegeVpu720StatusReg *reg_st = ®s->reg_st; + RK_U32 int_state = regs->int_state; + + hal_jpege_enter(); + + if (task->flags.err) { + mpp_err_f("task->flags.err 0x%08x, return earyl\n", task->flags.err); + return ret = MPP_NOK; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + mpp_err_f("poll cmd failed %d\n", ret); + return ret = MPP_ERR_VPUHW; + } else { + if (int_state & 0x170) + mpp_err_f("JPEG encoder hw error 0x%08x\n", int_state); + else + hal_jpege_dbg_simple("JPEG encoder int state 0x%08x\n", int_state); + + hal_jpege_dbg_detail("hw length %d, cycle %d\n", + reg_st->st_bsl_l32_jpeg_head_bits, + reg_st->st_perf_working_cnt); + task->hw_length += reg_st->st_bsl_l32_jpeg_head_bits; + } + + hal_jpege_leave(); + return MPP_OK; +} + +MPP_RET hal_jpege_vpu720_get_task(void *hal, HalEncTask *task) +{ + JpegeVpu720HalCtx *ctx = (JpegeVpu720HalCtx *) hal; + JpegeSyntax *syntax = (JpegeSyntax *) task->syntax.data; + + hal_jpege_enter(); + memcpy(&ctx->syntax, syntax, sizeof(ctx->syntax)); + + if (mpp_frame_has_meta(task->frame)) { + MppMeta meta = mpp_frame_get_meta(task->frame); + + mpp_meta_get_ptr(meta, KEY_JPEG_ROI_DATA, (void **)&ctx->roi_data); + } + + if (ctx->cfg->jpeg.update) { + hal_jpege_rc_update(&ctx->hal_rc, syntax); + ctx->cfg->jpeg.update = 0; + } + + task->rc_task->frm.is_intra = 1; + + // TODO config rc + hal_jpege_leave(); + return MPP_OK; +} + +MPP_RET hal_jpege_vpu720_ret_task(void *hal, HalEncTask *task) +{ + (void)hal; + EncRcTaskInfo * rc_info = &task->rc_task->info; + + hal_jpege_enter(); + + task->length += task->hw_length; + + // setup bit length for rate control + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = rc_info->quality_target; + mpp_buffer_sync_ro_begin(task->output); + + hal_jpege_leave(); + return MPP_OK; +} +const MppEncHalApi hal_jpege_vpu720 = { + .name = "hal_jpege_vpu720", + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegeVpu720HalCtx), + .flag = 0, + .init = hal_jpege_vpu720_init, + .deinit = hal_jpege_vpu720_deinit, + .prepare = NULL, + .get_task = hal_jpege_vpu720_get_task, + .gen_regs = hal_jpege_vpu720_gen_regs, + .start = hal_jpege_vpu720_start, + .wait = hal_jpege_vpu720_wait, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_jpege_vpu720_ret_task, + .client = VPU_CLIENT_JPEG_ENC, + .soc_type = { + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_jpege_vpu720) diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vpu720.h b/mpp/hal/rkenc/jpege/hal_jpege_vpu720.h new file mode 100644 index 000000000..8a7577413 --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vpu720.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_JPEGE_VPU720_H +#define HAL_JPEGE_VPU720_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_jpege_vpu720; + +#endif /* HAL_JPEGE_VPU720_H */ diff --git a/mpp/hal/rkenc/jpege/hal_jpege_vpu720_reg.h b/mpp/hal/rkenc/jpege/hal_jpege_vpu720_reg.h new file mode 100644 index 000000000..1064cf9d0 --- /dev/null +++ b/mpp/hal/rkenc/jpege/hal_jpege_vpu720_reg.h @@ -0,0 +1,591 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_JPEGE_VPU720_REG_H +#define HAL_JPEGE_VPU720_REG_H + +#include "rk_type.h" + +typedef struct JpegeVpu720BaseReg_t { + // 0x0000, IP version + RK_U32 reg000_version; + // 0x0004, Start Command + struct { + // Number of new nodes added to link table + RK_U32 lkt_num : 8; + /** + * @brief VEPU command + * 0 -- N/A + * 1 -- One-frame encoding by register configuration + * 2 -- Multi-frame encoding start with link table mode + * 3 -- Multi-frame encoding update (with link table mode) + * 4 -- link table encoding force pause + * 5 -- continue link table encoder when link table stop + * 6 -- safe_clr + * 7 -- force_clr + */ + RK_U32 vepu_cmd : 4; + RK_U32 : 20; + } reg001_enc_strt; + + /*reserved 0x8 ~ 0xC*/ + RK_U32 reg002_003[2]; + + // 0x0010, Interrupt Enable + struct { + // One frame encoding finish interrupt enable + RK_U32 fenc_done_en : 1; + // Link table one node finish interrupt enable + RK_U32 lkt_node_done_en : 1; + // Safe clear finish interrupt enable + RK_U32 sclr_done_en : 1; + // One slice of video encoding finish interrupt enable + RK_U32 vslc_done_en : 1; + // Video bit stream buffer overflow interrupt enable + RK_U32 vbsb_oflw_en : 1; + // Video bit stream buffer write section interrupt enable + RK_U32 vbsb_sct_en : 1; + // Frame encoding error interrupt enable + RK_U32 fenc_err_en : 1; + // Watch dog (timeout) interrupt enable + RK_U32 wdg_en : 1; + // Link table operation error interrupt enable + RK_U32 lkt_oerr_en : 1; + // Link table encoding error stop interrupt enable + RK_U32 lkt_estp_en : 1; + // Link cmd force pause interrupt enable + RK_U32 lkt_fstp_en : 1; + // Link table note stop interrupt enable + RK_U32 lkt_note_stp_en : 1; + RK_U32 lkt_data_error_en : 1; + RK_U32 : 19; + } reg004_int_en; + + // 0x0014, Interrupt Mask + struct { + RK_U32 fenc_done_msk : 1; + RK_U32 lkt_node_done_msk : 1; + RK_U32 sclr_done_msk : 1; + RK_U32 vslc_done_msk : 1; + RK_U32 vbsb_oflw_msk : 1; + RK_U32 vbsb_sct_msk : 1; + RK_U32 fenc_err_msk : 1; + RK_U32 wdg_msk : 1; + RK_U32 lkt_oerr_msk : 1; + RK_U32 lkt_estp_msk : 1; + RK_U32 lkt_fstp_msk : 1; + RK_U32 lkt_note_stp_msk : 1; + RK_U32 lkt_data_error_msk : 1; + RK_U32 : 19; + } reg005_int_msk; + + // 0x0018, Interrupt Clear + struct { + RK_U32 fenc_done_clr : 1; + RK_U32 lkt_node_done_clr : 1; + RK_U32 sclr_done_clr : 1; + RK_U32 vslc_done_clr : 1; + RK_U32 vbsb_oflw_clr : 1; + RK_U32 vbsb_sct_clr : 1; + RK_U32 fenc_err_clr : 1; + RK_U32 wdg_clr : 1; + RK_U32 lkt_oerr_clr : 1; + RK_U32 lkt_estp_clr : 1; + RK_U32 lkt_fstp_clr : 1; + RK_U32 lkt_note_stp_clr : 1; + RK_U32 lkt_data_error_clr : 1; + RK_U32 : 19; + } reg006_int_clr; + + // 0x001c, Interrupt State; + struct { + RK_U32 fenc_done_state : 1; + RK_U32 lkt_node_done_state : 1; + RK_U32 sclr_done_state : 1; + RK_U32 vslc_done_state : 1; + RK_U32 vbsb_oflw_state : 1; + RK_U32 vbsb_sct_state : 1; + RK_U32 fenc_err_state : 1; + RK_U32 wdg_state : 1; + RK_U32 lkt_oerr_state : 1; + RK_U32 lkt_estp_state : 1; + RK_U32 lkt_fstp_state : 1; + RK_U32 lkt_note_stp_state : 1; + RK_U32 lkt_data_error_state : 1; + RK_U32 : 19; + } reg007_int_state; + + // 0x0020, Clock and RST CTRL + struct { + // Encoder auto reset core clock domain when frame finished + RK_U32 resetn_hw_en : 1; + // Encoder SRAM auto clock gating enable + RK_U32 sram_ckg_en : 1; + // Auto clock gating enable + RK_U32 cke : 1; + RK_U32 : 29; + } reg008_cru_ctrl; + + // 0x0024, Fast link table cfg buffer addr, 128 byte aligned + RK_U32 reg009_lkt_base_addr; + + // 0x0028, Link table node operation configuration + struct { + // Only the ejpeg with the same core ID can use this node + RK_U32 core_id : 4; + // The enable of lkt error stop next frame + RK_U32 lkt_err_stop_en : 1; + // The enable of lkt frame stop when the frame end + RK_U32 lkt_node_stop_en : 1; + RK_U32 : 10; + /** + * @brief Data swap for link table read channel. + * bit[3] -- swap 64 bits in 128 bits + * bit[2] -- swap 32 bits in 64 bits; + * bit[1] -- swap 16 bits in 32 bits; + * bit[0] -- swap 8 bits in 16 bits; + */ + RK_U32 lktr_bus_edin : 4; + /** + * @brief + * Data swap for link table write channel. + * bit[3] -- swap 64 bits in 128 bits + * bit[2] -- swap 32 bits in 64 bits; + * bit[1] -- swap 16 bits in 32 bits; + * bit[0] -- swap 8 bits in 16 bits; + */ + RK_U32 lktw_bus_edin : 4; + RK_U32 : 8; + } reg010_node_ocfg; + + // 0x002c, watch dog configure register + RK_U32 reg011_wdg_jpeg; + + // reserved, 0x0030 + RK_U32 reg012; + + // 0x0034, low delay esc operation configuration. Bit[0-30] : read ecs num. + RK_U32 reg013_low_delay_ecs_ocfg; + // 0x0038, low delay packet operation configuration. Bit[0-30] : read packet num. + RK_U32 reg014_low_delay_packet_ocfg; + + // reserved, 0x003c + RK_U32 reg015; + + // 0x0040, Address of JPEG Q table buffer, 128 byte aligned + RK_U32 reg016_adr_qtbl; + // 0x0044, Top address of JPEG Bit stream buffer, 16 byte aligned + RK_U32 reg017_adr_bsbt; + // 0x0048, Bottom address of JPEG bit stream buffer, 16 byte aligned + RK_U32 reg018_adr_bsbb; + // 0x004c, Read Address of JPEG bit stream buffer, 1 byte aligned + RK_U32 reg019_adr_bsbr; + // 0x0050, Start address of JPEG bit stream buffer, 1 byte aligned + RK_U32 reg020_adr_bsbs; + // 0x0054, Base address of ECS length buffer, 8 byte align + RK_U32 reg021_adr_ecs_len; + // 0x0058, Base address of the 1st storage area for video source buffer + RK_U32 reg022_adr_src0; + // 0x005c, Base address of the 2nd storage area for video source buffer + RK_U32 reg023_adr_src1; + // 0x0060, Base address of the 3rd storage area for video source buffer + RK_U32 reg024_adr_src2; + + // reserved, 0x0064 + RK_U32 reg025; + + // 0x0068, rk jpeg encoder axi performance ctrl0 description + struct { + RK_U32 perf_work_e : 1; + RK_U32 perf_clr_e : 1; + RK_U32 perf_frm_type : 1; + RK_U32 cnt_type : 1; + RK_U32 rd_latency_id : 4; + RK_U32 rd_latency_thr : 12; + RK_U32 : 12; + } reg026_axi_perf_ctrl0; + + // 0x006c, rk jpeg encoder axi performance ctrl1 description + struct { + RK_U32 addr_align_type : 2; + RK_U32 ar_cnt_id_type : 1; + RK_U32 aw_cnt_id_type : 1; + RK_U32 ar_count_id : 4; + RK_U32 aw_count_id : 4; + RK_U32 rd_total_bytes_mode : 1; + RK_U32 : 19; + } reg027_axi_perf_ctrl1; + + // 0x0070, reserved + RK_U32 reg028; + + // 0x0074, picture size + struct { + // Ceil(encoding picture height / 8) -1 + RK_U32 pic_wd8_m1 : 13; + RK_U32 : 3; + // Ceil(encoding picture height / 8) -1 + RK_U32 pic_hd8_m1 : 13; + RK_U32 : 3; + } reg029_sw_enc_rsl; + + // 0x0078, JPEG source filling pixels for align + struct { + RK_U32 pic_wfill_jpeg : 6; + RK_U32 : 10; + RK_U32 pic_hfill_jpeg : 6; + RK_U32 : 10; + } reg030_sw_src_fill; + + /* reserved 0x7c */ + RK_U32 reg031; + + // 0x0080, JPEG source format + struct { + RK_U32 : 1; + RK_U32 rbuv_swap_jpeg : 1; + /** + * @brief srouce color format + * 4'h0: tile400 + * 4'h1: tile420 + * 4'h2: tile422 + * 4'h3: tile444 + * 4'h4: YUV422SP + * 4'h5: YUV422P + * 4'h6: YUV420SP + * 4'h7: YUV420P + * 4'h8: YUYV422 + * 4'h9: UYVY422 + * 4'ha: YUV400 + * 4'hc: YUV444SP + * 4'hd: YUV444P + * Others: Reserved + */ + RK_U32 src_fmt : 4; + /** + * @brief color format of output from preprocess + * 2'h0: YUV400; + * 2'h1: YUV420; + * 2'h2: YUV422; + * 2'h3: YUV444; + * + */ + RK_U32 out_fmt : 2; + RK_U32 : 1; + RK_U32 src_range_trns_en : 1; + RK_U32 src_range_trns_sel : 1; + /** + * @brief Chroma downsample mode + * 0 -- Average + * 1 -- Drop + */ + RK_U32 chroma_ds_mode : 1; + // Chroma value will be force to some value + RK_U32 chroma_force_en : 1; + RK_U32 : 2; + // 1 00 src mirror image + RK_U32 src_mirr_jpeg : 1; + RK_U32 u_force_value : 8; + RK_U32 v_force_value : 8; + } reg032_sw_src_fmt; + + // 0x0084, encoding picture offset + struct { + RK_U32 pic_ofst_x : 16; + RK_U32 pic_ofst_y : 16; + } reg033_sw_pic_ofst; + + // 0x0088, JPEG source stride0 + struct { + RK_U32 src_strd_0 : 20; + RK_U32 : 12; + } reg034_sw_src_strd_0; + + // 0x008c, JPEG source stride1 + struct { + RK_U32 src_strd_1 : 19; + RK_U32 : 13; + } reg035_sw_src_strd_1; + + // 0x0090, JPEG common config + struct { + /* the number of MCU in the restart interval */ + RK_U32 rst_intv : 16; + RK_U32 : 9; + /** + * @brief JPEG encoder output mode + * 1'b0: frame by frame, without interrupt at any ECS; + * 1'b1: low latency mode, with interrupt per ECS, flush all the + * bit stream after each ECS finished. + */ + RK_U32 out_mode : 1; + /* the number of the fisrt RSTm */ + RK_U32 rst_m : 3; + /** + * @brief Indicate if the current ECS is the last ECS of the whole picture. + * If it is the last ecs, add EOI. + */ + RK_U32 pic_last_ecs : 1; + /** + * @brief reload Q table or not + * 0 -- load Q table for current task + * 1 -- no need to load Q table + */ + RK_U32 jpeg_qtble_noload : 1; + RK_U32 : 1; + } reg036_sw_jpeg_enc_cfg; + + // 0x0094, Low dealy packet size config + RK_U32 reg037_bsp_size_jpeg; + + // 0x0098, Bit stream output padding config + struct { + RK_U32 uvc_partition0_len : 12; + RK_U32 uvc_partition_len : 12; + RK_U32 uvc_skip_len : 6; + RK_U32 : 2; + } reg038_sw_uvc_cfg; + + // 0x009c, Y Quantify rounding + struct { + /* bias for Y at quantization */ + RK_U32 bias_y : 15; + RK_U32 : 17; + } reg039_sw_jpeg_y_cfg; + + // 0x00a0, U Quantify rounding + struct { + + /* bias for U at quantization */ + RK_U32 bias_u : 15; + RK_U32 : 17; + } reg040_sw_jpeg_u_cfg; + + // 0x00a4, V Quantify rounding + struct { + /* bias for V at quantization */ + RK_U32 bias_v : 15; + RK_U32 : 17; + } reg041_sw_jpeg_v_cfg; + + // 0x00a8, Data bus endian + struct { + /** + * @brief Data swap for jpeg bit stream write channel + * [3]: Swap 64 bits in 128 bits + * [2]: Swap 32 bits in 64 bits + * [1]: Swap 16 bits in 32 bits + * [0]: Swap 8 bits in 16 bits + */ + RK_U32 jbsw_bus_edin : 4; + // Data swap for video source loading channel. + RK_U32 vsl_bus_edin : 4; + // Data swap for lkt state write channel + RK_U32 ecs_len_edin : 4; + // Data swap for qtbl read channel + RK_U32 sw_qtbl_edin : 4; + } reg042_dbus_endn; + +} JpegeVpu720BaseReg; + +typedef struct JpegeVpu720StatusReg_t { + // 0x00c0, Low 32 bits of JPEG header bits length. + RK_U32 st_bsl_l32_jpeg_head_bits; + // 0x00c4, High 32 bits of JPEG header bits length + RK_U32 st_bsl_h32_jpeg_head_bits; + + // 0x00c8, Y and U source range + struct { + RK_U32 y_max_value : 8; + RK_U32 y_min_value : 8; + RK_U32 u_max_value : 8; + RK_U32 u_min_vlaue : 8; + } st_vsp_value0; + + // 0x00cc, V source range and total_ecs_num_minus + struct { + RK_U32 v_max_value : 8; + RK_U32 v_min_vlaue : 8; + RK_U32 total_ecs_num_minus1 : 8; + } st_vsp_value1; + + // 0x00d0, bit[0-15] + RK_U32 st_perf_rd_max_latency_num0; + // 0x00d4 + RK_U32 st_perf_rd_latency_samp_num; + // 0x00d8 + RK_U32 st_perf_rd_latency_acc_sum; + // 0x00dc + RK_U32 st_perf_rd_axi_total_byte; + // 0x00e0 + RK_U32 st_perf_wr_axi_total_byte; + // 0x00e4 + RK_U32 st_perf_working_cnt; + + RK_U32 sw_reserved_00e8_00ec[2]; + + // 0x00f0 + struct { + RK_U32 vsp_work_flag : 1; + RK_U32 jpeg_core_work_flag : 1; + RK_U32 dma_wr_work_flag : 1; + RK_U32 dma_work_flag : 1; + } st_wdg; + + // 0x00f4 + RK_U32 st_ppl_pos; + // 0x00f8 + RK_U32 st_core_pos; + + // 0x00fc, Bus status + struct { + RK_U32 ejpeg_arready : 1; + RK_U32 ejpeg_cfg_arvalid : 1; + RK_U32 ejpeg_cfg_arvalid_type : 1; + RK_U32 ejpeg_cfg_arready : 1; + RK_U32 ejpeg_vsp_arvalid : 1; + RK_U32 ejpeg_vsp_arready : 1; + RK_U32 rkejpeg_arvalid : 1; + RK_U32 ejpeg_cfg_ar_cnt : 2; + RK_U32 rkejpeg_arready : 1; + RK_U32 rkejpeg_ravlid : 1; + RK_U32 rkejpeg_rid : 4; + RK_U32 rkejpeg_rresp : 2; + RK_U32 rkejpeg_rready : 1; + RK_U32 axi_wr_state_cs : 1; + RK_U32 ejpeg_strmd_awvalid : 1; + RK_U32 ejpeg_strmd_awtype : 1; + RK_U32 ejpeg_strmd_awready : 1; + RK_U32 ejpeg_strmd_wvalid : 1; + RK_U32 ejpeg_strmd_wready : 1; + RK_U32 ejpeg_cfg_awvalid : 1; + RK_U32 ejpeg_cfg_awready : 1; + RK_U32 rkejpeg_awvalid : 1; + RK_U32 rkejpeg_awid : 1; + RK_U32 rkejpeg_wvalid : 1; + RK_U32 rkejpeg_wready : 1; + RK_U32 ejpeg_freeze_flag : 1; + RK_U32 : 1; + } st_bus; + + // 0x0100, vsp_dbg_status + RK_U32 dbg_ppl; + // 0x0104, jpeg core dbg status + RK_U32 dbg_jpeg_core; + // reserved, 0x0108 + RK_U32 sw_reserved_0108; + // 0x010c, The bit stream write address status + RK_U32 st_adr_jbsbw; + // 0x0110, ECS length buffer write address status + RK_U32 st_adr_ecs_len; + // 0x0114, the 1st storage aread for video source buffer read address status + RK_U32 st_adr_src0_jpeg; + // 0x0118, the 2nd storage aread for video source buffer read address status + RK_U32 st_adr_src1_jpeg; + // 0x011c, the 3rd storage aread for video source buffer read address status + RK_U32 st_adr_src2_jpeg; + + // 0x0120, low delay packet num status + struct { + RK_U32 bs_packet_num : 16; + RK_U32 bs_packet_lst : 1; + } st_low_delay_packet_num; + + // 0x0124, low delay ecs_len num status + struct { + RK_U32 ecs_len_num : 16; + RK_U32 ecs_len_lst : 1; + } st_ecs_len_num; + + // 0x0128, JPEG common status + struct { + /** + * @brief + * 0: idle + * 1: cru open + * 2: lkt cfg load + * 3: qtbl_cfg_load + * 4:enc + * 5:frame end + * 6:cru_close + * 7:lkt_error_stop + * 8:lkt_force_stop + * 9:lkt_node_stop + */ + RK_U32 jpeg_enc_state : 4; + RK_U32 lkt_mode_en : 1; + } st_enc; + + // 0x012c, Link table num + struct { + RK_U32 lkt_cfg_num : 8; + RK_U32 lkt_done_num : 8; + RK_U32 lkt_int_num : 8; + RK_U32 lkt_cfg_load_num : 8; + } st_lkt_num; + + // 0x0130, link table cfg info + struct { + RK_U32 lkt_core_id : 4; + RK_U32 : 4; + RK_U32 lkt_stop_flag : 1; + RK_U32 lkt_node_int : 1; + RK_U32 lkt_task_id : 12; + RK_U32 : 10; + } st_lkt_info; + + //0x0134, next read addr for lkt_cfg + RK_U32 st_lkt_cfg_next_addr; + //0x0138, lkt state buffer write addr + RK_U32 st_lkt_waddr; +} JpegeVpu720StatusReg; + +#define JPEGE_VPU720_REG_BASE_INT_STATE (0x1c) +#define JPEGE_VPU720_REG_STATUS_OFFSET (0xc0) + +#define JPEGE_VPU730_REG_ROI_OFFSET 0x0300 +#define JPEGE_VPU730_REG_ROI_NUM 16 + +typedef struct JpegeVpu730FrmRdoqCfg_t { + rk_u32 en : 1; + rk_u32 level : 6; + rk_u32 : 25; +} JpegeVpu730FrmRdoCfg; + +typedef struct JpegeVpu730RoiReg_t { + struct { + rk_u32 en : 1; + rk_u32 level : 6; + rk_u32 : 25; + } rdoq_cfg; + + struct { + rk_u32 start_x_in16 : 12; + rk_u32 : 4; + rk_u32 start_y_in16 : 12; + rk_u32 : 4; + } rdoq_pos; + + struct { + rk_u32 width_in16_m1 : 12; + rk_u32 : 4; + rk_u32 height_in16_m1 : 12; + rk_u32 : 4; + } rdoq_size; +} JpegeVpu730RoiReg; + +typedef struct JpegeVpu730RdoReg_t { + JpegeVpu730FrmRdoCfg reg_frm_rdoq_cfg; + JpegeVpu730RoiReg reg_roi[JPEGE_VPU730_REG_ROI_NUM]; +} JpegeVpu730RdoReg; + +typedef struct JpegeVpu720RegSet_t { + JpegeVpu720BaseReg reg_base; + JpegeVpu720StatusReg reg_st; + JpegeVpu730RdoReg reg_rdo; + RK_U32 int_state; +} JpegeVpu720Reg; + +#endif /* HAL_JPEGE_VPU720_REG_H */ \ No newline at end of file diff --git a/mpp/hal/vpu/CMakeLists.txt b/mpp/hal/vpu/CMakeLists.txt new file mode 100644 index 000000000..151e46104 --- /dev/null +++ b/mpp/hal/vpu/CMakeLists.txt @@ -0,0 +1,39 @@ +# vim: syntax=cmake + +add_subdirectory(common) + +if( HAVE_H263D ) + add_subdirectory(h263d) +endif() + +if( HAVE_MPEG2D ) + add_subdirectory(m2vd) +endif() + +if( HAVE_MPEG4D ) + add_subdirectory(mpg4d) +endif() + +if( HAVE_VP8D ) + add_subdirectory(vp8d) +endif() + +if( HAVE_JPEGD ) + add_subdirectory(jpegd) +endif() + +if( HAVE_AV1D ) + add_subdirectory(av1d) +endif() + +if( HAVE_JPEGE ) + add_subdirectory(jpege) +endif() + +if( HAVE_H264E ) + add_subdirectory(h264e) +endif() + +if( HAVE_VP8E) + add_subdirectory(vp8e) +endif() diff --git a/mpp/hal/vpu/av1d/CMakeLists.txt b/mpp/hal/vpu/av1d/CMakeLists.txt new file mode 100644 index 000000000..9f4221363 --- /dev/null +++ b/mpp/hal/vpu/av1d/CMakeLists.txt @@ -0,0 +1,11 @@ +# vim: syntax=cmake +include_directories(../../common/av1/) + +# hal av1d decoder sourse +set(HAL_AV1D_SRC) + +add_hal_source(HAL_AV1D_SRC HAVE_AV1D_VPU hal_av1d_vdpu.c) + +if (HAL_AV1D_SRC) + add_library(hal_av1d_vpu OBJECT ${HAL_AV1D_SRC}) +endif() diff --git a/mpp/hal/vpu/av1d/hal_av1d_vdpu.c b/mpp/hal/vpu/av1d/hal_av1d_vdpu.c new file mode 100644 index 000000000..cef60303c --- /dev/null +++ b/mpp/hal/vpu/av1d/hal_av1d_vdpu.c @@ -0,0 +1,2430 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_av1d_vdpu" + +#include +#include +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_bitput.h" +#include "mpp_hal.h" +#include "mpp_dec_cb_param.h" +#include "mpp_device.h" +#include "mpp_env.h" +#include "hal_bufs.h" + +#include "hal_av1d_vdpu.h" +#include "hal_av1d_vdpu_reg.h" +#include "hal_av1d_common.h" +#include "av1d_syntax.h" +#include "film_grain_noise_table.h" + +#define VDPU_FAST_REG_SET_CNT 3 + +#define AV1_TILE_INFO_SIZE AV1_MAX_TILES * 16 +#define GM_GLOBAL_MODELS_PER_FRAME 7 +#define GLOBAL_MODEL_TOTAL_SIZE (6 * 4 + 4 * 2) +#define GLOBAL_MODEL_SIZE GM_GLOBAL_MODELS_PER_FRAME * GLOBAL_MODEL_TOTAL_SIZE +#define MaxTiles 128 + +#define DUMP_AV1_DATAS 0 + +typedef enum AV1D_FILT_TYPE_E { + DB_DATA_COL, + DB_CTRL_COL, + CDEF_COL, + SR_COL, + LR_COL, + RFC_COL, + FILT_TYPE_BUT, +} Av1dFiltType_e; + +typedef struct filt_info_t { + RK_U32 size; + RK_U32 offset; +} filtInfo; + +typedef struct av1d_rkv_buf_t { + RK_U32 valid; + VdpuAv1dRegSet *regs; +} av1dVdpuBuf; + +typedef struct VdpuAv1dRegCtx_t { + av1dVdpuBuf reg_buf[VDPU_FAST_REG_SET_CNT]; + MppBuffer prob_tbl_base; + MppBuffer prob_tbl_out_base; + MppBuffer tile_info; + MppBuffer film_grain_mem; + MppBuffer global_model; + MppBuffer filter_mem; + MppBuffer tile_buf; + filtInfo filt_info[FILT_TYPE_BUT]; + + AV1CDFs *cdfs; + Av1MvCDFs *cdfs_ndvc; + AV1CDFs default_cdfs; + Av1MvCDFs default_cdfs_ndvc; + AV1CDFs cdfs_last[AV1_NUM_REF_FRAMES]; + Av1MvCDFs cdfs_last_ndvc[AV1_NUM_REF_FRAMES]; + RK_U32 refresh_frame_flags; + + RK_U32 width; + RK_U32 height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_U32 luma_size ; + RK_U32 chroma_size; + + AV1FilmGrainMemory fgsmem; + + RK_S8 prev_out_buffer_i; + RK_U8 fbc_en; + RK_U8 resolution_change; + RK_U8 tile_transpose; + RK_U32 ref_frame_sign_bias[AV1_REF_LIST_SIZE]; + + VdpuAv1dRegSet *regs; + HalBufs tile_out_bufs; + RK_U32 tile_out_count; + size_t tile_out_size; + + RK_U32 num_tile_cols; +} VdpuAv1dRegCtx; + +static MPP_RET hal_av1d_alloc_res(void *hal) +{ + MPP_RET ret = MPP_OK; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + RK_U32 max_cnt = (p_hal->fast_mode != 0) ? VDPU_FAST_REG_SET_CNT : 1; + RK_U32 i = 0; + INP_CHECK(ret, NULL == p_hal); + + MEM_CHECK(ret, p_hal->reg_ctx = mpp_calloc_size(void, sizeof(VdpuAv1dRegCtx))); + VdpuAv1dRegCtx *reg_ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + MppBufferGroup group = p_hal->cfg->buf_group; + + //!< malloc buffers + for (i = 0; i < max_cnt; i++) { + reg_ctx->reg_buf[i].regs = mpp_calloc(VdpuAv1dRegSet, 1); + memset(reg_ctx->reg_buf[i].regs, 0, sizeof(VdpuAv1dRegSet)); + } + + if (!p_hal->fast_mode) { + reg_ctx->regs = reg_ctx->reg_buf[0].regs; + } + + BUF_CHECK(ret, mpp_buffer_get(group, ®_ctx->prob_tbl_base, MPP_ALIGN(sizeof(AV1CDFs), 2048))); + BUF_CHECK(ret, mpp_buffer_get(group, ®_ctx->prob_tbl_out_base, MPP_ALIGN(sizeof(AV1CDFs), 2048))); + BUF_CHECK(ret, mpp_buffer_get(group, ®_ctx->tile_info, AV1_TILE_INFO_SIZE)); + BUF_CHECK(ret, mpp_buffer_get(group, ®_ctx->film_grain_mem, MPP_ALIGN(sizeof(AV1FilmGrainMemory), 2048))); + BUF_CHECK(ret, mpp_buffer_get(group, ®_ctx->global_model, MPP_ALIGN(GLOBAL_MODEL_SIZE, 2048))); + BUF_CHECK(ret, mpp_buffer_get(group, ®_ctx->tile_buf, MPP_ALIGN(32 * MaxTiles, 4096))); + +__RETURN: + return ret; +__FAILED: + return ret; +} + +static void vdpu_av1d_filtermem_release(VdpuAv1dRegCtx *ctx) +{ + BUF_PUT(ctx->filter_mem); +} + +static MPP_RET vdpu_av1d_filtermem_alloc(Av1dHalCtx *p_hal, VdpuAv1dRegCtx *ctx, DXVA_PicParams_AV1 *dxva) +{ + RK_U32 size = 0; + RK_U32 pic_height = MPP_ALIGN(dxva->height, 64); + RK_U32 height_in_sb = pic_height / 64; + RK_U32 stripe_num = ((pic_height + 8) + 63) / 64; + RK_U32 max_bit_depth = 10; + RK_U32 num_tile_cols = 1 << dxva->tile_cols_log2;//dxva->tiles.cols; + filtInfo *filt_info = ctx->filt_info; + + /* db tile col data buffer */ + // asic_buff->db_data_col_offset = 0; + // asic_buff->db_data_col_tsize = NEXT_MULTIPLE(pic_height * 12 * max_bit_depth / 8, 128); + // size = asic_buff->db_data_col_tsize * num_tile_cols; + // asic_buff->db_ctrl_col_offset = size; + + filt_info[DB_DATA_COL].offset = 0; + filt_info[DB_DATA_COL].size = MPP_ALIGN(pic_height * 12 * max_bit_depth / 8, 128); + size += filt_info[DB_DATA_COL].size * num_tile_cols; + + + /* db tile col ctrl buffer */ + filt_info[DB_CTRL_COL].offset = size; + filt_info[DB_CTRL_COL].size = MPP_ALIGN(pic_height * 2 * 16 / 4, 128); + size += filt_info[DB_CTRL_COL].size * num_tile_cols; + + // size += asic_buff->db_ctrl_col_tsize * num_tile_cols; + // asic_buff->cdef_col_offset = size; + + /* cdef tile col buffer */ + filt_info[CDEF_COL].offset = size; + filt_info[CDEF_COL].size = MPP_ALIGN(height_in_sb * 44 * max_bit_depth * 16 / 8, 128); + size += filt_info[CDEF_COL].size * num_tile_cols; + // asic_buff->cdef_col_tsize = NEXT_MULTIPLE(height_in_sb * 44 * max_bit_depth * 16 / 8, 128); + // size += asic_buff->cdef_col_tsize * num_tile_cols; + // asic_buff->sr_col_offset = size; + + /* sr tile col buffer */ + filt_info[SR_COL].offset = size; + filt_info[SR_COL].size = MPP_ALIGN(height_in_sb * (3040 + 1280), 128); + size += filt_info[SR_COL].size * num_tile_cols; + // asic_buff->sr_col_tsize = NEXT_MULTIPLE(height_in_sb * (3040 + 1280), 128); + // size += asic_buff->sr_col_tsize * num_tile_cols; + // asic_buff->lr_col_offset = size; + + /* lr tile col buffer */ + filt_info[LR_COL].offset = size; + filt_info[LR_COL].size = MPP_ALIGN(stripe_num * 1536 * max_bit_depth / 8, 128); + size += filt_info[LR_COL].size * num_tile_cols; + // asic_buff->lr_col_tsize = NEXT_MULTIPLE(stripe_num * 1536 * max_bit_depth / 8, 128); + // size += asic_buff->lr_col_tsize * num_tile_cols; + // if (dec_cont->use_multicore) { + // asic_buff->rfc_col_offset = size; + // asic_buff->rfc_col_size = NEXT_MULTIPLE(asic_buff->height, 8) / 8 * 16 * 2; + // size += asic_buff->rfc_col_size * num_tile_cols; + // } + if (!mpp_buffer_get(p_hal->cfg->buf_group, &ctx->filter_mem, MPP_ALIGN(size, SZ_4K))) + return MPP_NOK; + + return MPP_OK; +} + +static void hal_av1d_release_res(void *hal) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + VdpuAv1dRegCtx *reg_ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + RK_U32 i = 0; + RK_U32 loop = (p_hal->fast_mode != 0) ? MPP_ARRAY_ELEMS(reg_ctx->reg_buf) : 1; + + for (i = 0; i < loop; i++) + MPP_FREE(reg_ctx->reg_buf[i].regs); + + BUF_PUT(reg_ctx->prob_tbl_base); + BUF_PUT(reg_ctx->prob_tbl_out_base); + BUF_PUT(reg_ctx->tile_info); + BUF_PUT(reg_ctx->film_grain_mem); + BUF_PUT(reg_ctx->global_model); + BUF_PUT(reg_ctx->tile_buf); + vdpu_av1d_filtermem_release(reg_ctx); + hal_bufs_deinit(reg_ctx->tile_out_bufs); + + MPP_FREE(p_hal->reg_ctx); +} + +MPP_RET vdpu_av1d_deinit(void *hal) +{ + hal_av1d_release_res(hal); + + return MPP_OK; +} + +MPP_RET vdpu_av1d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + mpp_env_get_u32("hal_av1d_debug", &hal_av1d_debug, 0); + + INP_CHECK(ret, NULL == p_hal); + + p_hal->cfg = cfg; + p_hal->fast_mode = cfg->cfg->base.fast_parse && cfg->support_fast_mode; + + FUN_CHECK(hal_av1d_alloc_res(hal)); + + { + VdpuAv1dRegCtx *reg_ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + + reg_ctx->cdfs = ®_ctx->default_cdfs; + reg_ctx->cdfs_ndvc = ®_ctx->default_cdfs_ndvc; + reg_ctx->tile_transpose = 1; + } + + mpp_slots_set_prop(cfg->frame_slots, SLOTS_HOR_ALIGN, mpp_align_16); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_VER_ALIGN, mpp_align_8); + mpp_slots_set_prop(cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + +__RETURN: + return MPP_OK; +__FAILED: + vdpu_av1d_deinit(hal); + + return ret; +} + +static void set_ref_width(VdpuAv1dRegSet *regs, RK_U32 i, RK_U32 val) +{ + if (i == 0) { + regs->swreg33.sw_ref0_width = val; + } else if (i == 1) { + regs->swreg34.sw_ref1_width = val; + } else if (i == 2) { + regs->swreg35.sw_ref2_width = val; + } else if (i == 3) { + regs->swreg43.sw_ref3_width = val; + } else if (i == 4) { + regs->swreg44.sw_ref4_width = val; + } else if (i == 5) { + regs->swreg45.sw_ref5_width = val; + } else if (i == 6) { + regs->swreg46.sw_ref6_width = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_height(VdpuAv1dRegSet *regs, RK_U32 i, RK_U32 val) +{ + if (i == 0) { + regs->swreg33.sw_ref0_height = val; + } else if (i == 1) { + regs->swreg34.sw_ref1_height = val; + } else if (i == 2) { + regs->swreg35.sw_ref2_height = val; + } else if (i == 3) { + regs->swreg43.sw_ref3_height = val; + } else if (i == 4) { + regs->swreg44.sw_ref4_height = val; + } else if (i == 5) { + regs->swreg45.sw_ref5_height = val; + } else if (i == 6) { + regs->swreg46.sw_ref6_height = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_hor_scale(VdpuAv1dRegSet *regs, RK_U32 i, RK_U32 val) +{ + if (i == 0) { + regs->swreg36.sw_ref0_hor_scale = val; + } else if (i == 1) { + regs->swreg37.sw_ref1_hor_scale = val; + } else if (i == 2) { + regs->swreg38.sw_ref2_hor_scale = val; + } else if (i == 3) { + regs->swreg39.sw_ref3_hor_scale = val; + } else if (i == 4) { + regs->swreg40.sw_ref4_hor_scale = val; + } else if (i == 5) { + regs->swreg41.sw_ref5_hor_scale = val; + } else if (i == 6) { + regs->swreg42.sw_ref6_hor_scale = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_ver_scale(VdpuAv1dRegSet *regs, RK_U32 i, RK_U32 val) +{ + if (i == 0) { + regs->swreg36.sw_ref0_ver_scale = val; + } else if (i == 1) { + regs->swreg37.sw_ref1_ver_scale = val; + } else if (i == 2) { + regs->swreg38.sw_ref2_ver_scale = val; + } else if (i == 3) { + regs->swreg39.sw_ref3_ver_scale = val; + } else if (i == 4) { + regs->swreg40.sw_ref4_ver_scale = val; + } else if (i == 5) { + regs->swreg41.sw_ref5_ver_scale = val; + } else if (i == 6) { + regs->swreg42.sw_ref6_ver_scale = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_lum_base(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val, HalBufs bufs) +{ + HalBuf *tile_out_buf; + tile_out_buf = hal_bufs_get_buf(bufs, val); + // MppBuffer framebuf = NULL; + // mpp_buf_slot_get_prop(slots, val, SLOT_BUFFER, &framebuf); + if (tile_out_buf == NULL) { + mpp_err_f("get slots frame buff fail"); + return; + } + val = mpp_buffer_get_fd(tile_out_buf->buf[0]); + if (i == 0) { + regs->addr_cfg.swreg67.sw_refer0_ybase_lsb = val; + } else if (i == 1) { + regs->addr_cfg.swreg69.sw_refer1_ybase_lsb = val; + } else if (i == 2) { + regs->addr_cfg.swreg71.sw_refer2_ybase_lsb = val; + } else if (i == 3) { + regs->addr_cfg.swreg73.sw_refer3_ybase_lsb = val; + } else if (i == 4) { + regs->addr_cfg.swreg75.sw_refer4_ybase_lsb = val; + } else if (i == 5) { + regs->addr_cfg.swreg77.sw_refer5_ybase_lsb = val; + } else if (i == 6) { + regs->addr_cfg.swreg79.sw_refer6_ybase_lsb = val; + } else { + mpp_err( "Error: trying to set invalid reference index."); + } +} + +static void set_ref_lum_base_msb(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val) +{ + if (i == 0) { + regs->addr_cfg.swreg66.sw_refer0_ybase_msb = val; + } else if (i == 1) { + regs->addr_cfg.swreg68.sw_refer1_ybase_msb = val; + } else if (i == 2) { + regs->addr_cfg.swreg70.sw_refer2_ybase_msb = val; + } else if (i == 3) { + regs->addr_cfg.swreg72.sw_refer3_ybase_msb = val; + } else if (i == 4) { + regs->addr_cfg.swreg74.sw_refer4_ybase_msb = val; + } else if (i == 5) { + regs->addr_cfg.swreg76.sw_refer5_ybase_msb = val; + } else if (i == 6) { + regs->addr_cfg.swreg78.sw_refer6_ybase_msb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_cb_base(Av1dHalCtx *p_hal, RK_S32 i, RK_S32 val, HalBufs bufs, RK_U32 offset) +{ + VdpuAv1dRegCtx *ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + HalBuf *tile_out_buf; + MppDev dev = p_hal->cfg->dev; + + tile_out_buf = hal_bufs_get_buf(bufs, val); + // MppBuffer framebuf = NULL; + + // mpp_buf_slot_get_prop(slots, val, SLOT_BUFFER, &framebuf); + if (tile_out_buf == NULL) { + mpp_err_f("get slots frame buff fail"); + return; + } + val = mpp_buffer_get_fd(tile_out_buf->buf[0]); + + if (i == 0) { + mpp_dev_set_reg_offset(dev, 101, offset); + regs->addr_cfg.swreg101.sw_refer0_cbase_lsb = val; + } else if (i == 1) { + mpp_dev_set_reg_offset(dev, 103, offset); + regs->addr_cfg.swreg103.sw_refer1_cbase_lsb = val; + } else if (i == 2) { + mpp_dev_set_reg_offset(dev, 105, offset); + regs->addr_cfg.swreg105.sw_refer2_cbase_lsb = val; + } else if (i == 3) { + mpp_dev_set_reg_offset(dev, 107, offset); + regs->addr_cfg.swreg107.sw_refer3_cbase_lsb = val; + } else if (i == 4) { + mpp_dev_set_reg_offset(dev, 109, offset); + regs->addr_cfg.swreg109.sw_refer4_cbase_lsb = val; + } else if (i == 5) { + mpp_dev_set_reg_offset(dev, 111, offset); + regs->addr_cfg.swreg111.sw_refer5_cbase_lsb = val; + } else if (i == 6) { + mpp_dev_set_reg_offset(dev, 113, offset); + regs->addr_cfg.swreg113.sw_refer6_cbase_lsb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_cb_base_msb(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val) +{ + if (i == 0) { + regs->addr_cfg.swreg100.sw_refer0_cbase_msb = val; + } else if (i == 1) { + regs->addr_cfg.swreg102.sw_refer1_cbase_msb = val; + } else if (i == 2) { + regs->addr_cfg.swreg104.sw_refer2_cbase_msb = val; + } else if (i == 3) { + regs->addr_cfg.swreg106.sw_refer3_cbase_msb = val; + } else if (i == 4) { + regs->addr_cfg.swreg108.sw_refer4_cbase_msb = val; + } else if (i == 5) { + regs->addr_cfg.swreg110.sw_refer5_cbase_msb = val; + } else if (i == 6) { + regs->addr_cfg.swreg112.sw_refer6_cbase_msb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + + +static void set_ref_dbase(Av1dHalCtx *p_hal, RK_S32 i, RK_S32 val, HalBufs bufs, RK_U32 offset) +{ + VdpuAv1dRegCtx *ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + HalBuf *tile_out_buf; + MppDev dev = p_hal->cfg->dev; + + tile_out_buf = hal_bufs_get_buf(bufs, val); + // MppBuffer framebuf = NULL; + + // mpp_buf_slot_get_prop(slots, val, SLOT_BUFFER, &framebuf); + if (tile_out_buf == NULL) { + mpp_err_f("get slots frame buff fail"); + return; + } + val = mpp_buffer_get_fd(tile_out_buf->buf[0]); + if (i == 0) { + mpp_dev_set_reg_offset(dev, 135, offset); + regs->addr_cfg.swreg135.sw_refer0_dbase_lsb = val; + } else if (i == 1) { + mpp_dev_set_reg_offset(dev, 137, offset); + regs->addr_cfg.swreg137.sw_refer1_dbase_lsb = val; + } else if (i == 2) { + mpp_dev_set_reg_offset(dev, 139, offset); + regs->addr_cfg.swreg139.sw_refer2_dbase_lsb = val; + } else if (i == 3) { + mpp_dev_set_reg_offset(dev, 141, offset); + regs->addr_cfg.swreg141.sw_refer3_dbase_lsb = val; + } else if (i == 4) { + mpp_dev_set_reg_offset(dev, 143, offset); + regs->addr_cfg.swreg143.sw_refer4_dbase_lsb = val; + } else if (i == 5) { + mpp_dev_set_reg_offset(dev, 145, offset); + regs->addr_cfg.swreg145.sw_refer5_dbase_lsb = val; + } else if (i == 6) { + mpp_dev_set_reg_offset(dev, 147, offset); + regs->addr_cfg.swreg147.sw_refer6_dbase_lsb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_dbase_msb(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val) +{ + if (i == 0) { + regs->addr_cfg.swreg134.sw_refer0_dbase_msb = val; + } else if (i == 1) { + regs->addr_cfg.swreg136.sw_refer1_dbase_msb = val; + } else if (i == 2) { + regs->addr_cfg.swreg138.sw_refer2_dbase_msb = val; + } else if (i == 3) { + regs->addr_cfg.swreg140.sw_refer3_dbase_msb = val; + } else if (i == 4) { + regs->addr_cfg.swreg142.sw_refer4_dbase_msb = val; + } else if (i == 5) { + regs->addr_cfg.swreg144.sw_refer5_dbase_msb = val; + } else if (i == 6) { + regs->addr_cfg.swreg146.sw_refer6_dbase_msb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_ty_base(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val, HalBufs bufs) +{ + // MppBuffer framebuf = NULL; + // mpp_buf_slot_get_prop(slots, val, SLOT_BUFFER, &framebuf); + HalBuf *tile_out_buf; + tile_out_buf = hal_bufs_get_buf(bufs, val); + + if (tile_out_buf == NULL) { + mpp_err_f("get slots frame buff fail"); + } + val = mpp_buffer_get_fd(tile_out_buf->buf[0]); + + if (i == 0) { + regs->swreg192.sw_refer0_tybase_lsb = val; + } else if (i == 1) { + regs->swreg194.sw_refer1_tybase_lsb = val; + } else if (i == 2) { + regs->swreg196.sw_refer2_tybase_lsb = val; + } else if (i == 3) { + regs->swreg198.sw_refer3_tybase_lsb = val; + } else if (i == 4) { + regs->swreg200.sw_refer4_tybase_lsb = val; + } else if (i == 5) { + regs->swreg202.sw_refer5_tybase_lsb = val; + } else if (i == 6) { + regs->swreg204.sw_refer6_tybase_lsb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_ty_base_msb(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val) +{ + if (i == 0) { + regs->swreg191.sw_refer0_tybase_msb = val; + } else if (i == 1) { + regs->swreg193.sw_refer1_tybase_msb = val; + } else if (i == 2) { + regs->swreg195.sw_refer2_tybase_msb = val; + } else if (i == 3) { + regs->swreg197.sw_refer3_tybase_msb = val; + } else if (i == 4) { + regs->swreg199.sw_refer4_tybase_msb = val; + } else if (i == 5) { + regs->swreg201.sw_refer5_tybase_msb = val; + } else if (i == 6) { + regs->swreg203.sw_refer6_tybase_msb = val; + } else { + mpp_err(" trying to set invalid reference index."); + } +} + +static void set_ref_tc_base(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val, HalBufs bufs) +{ + // MppBuffer framebuf = NULL; + // mpp_buf_slot_get_prop(slots, val, SLOT_BUFFER, &framebuf); + HalBuf *tile_out_buf; + tile_out_buf = hal_bufs_get_buf(bufs, val); + + if (tile_out_buf == NULL) { + mpp_err_f("get slots frame buff fail"); + } + val = mpp_buffer_get_fd(tile_out_buf->buf[0]); + + if (i == 0) { + regs->swreg226.sw_refer0_tcbase_lsb = val; + } else if (i == 1) { + regs->swreg228.sw_refer1_tcbase_lsb = val; + } else if (i == 2) { + regs->swreg230.sw_refer2_tcbase_lsb = val; + } else if (i == 3) { + regs->swreg232.sw_refer3_tcbase_lsb = val; + } else if (i == 4) { + regs->swreg234.sw_refer4_tcbase_lsb = val; + } else if (i == 5) { + regs->swreg236.sw_refer5_tcbase_lsb = val; + } else if (i == 6) { + regs->swreg238.sw_refer6_tcbase_lsb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + + +static void set_ref_tc_base_msb(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val) +{ + if (i == 0) { + regs->swreg225.sw_refer0_tcbase_msb = val; + } else if (i == 1) { + regs->swreg227.sw_refer1_tcbase_msb = val; + } else if (i == 2) { + regs->swreg229.sw_refer2_tcbase_msb = val; + } else if (i == 3) { + regs->swreg231.sw_refer3_tcbase_msb = val; + } else if (i == 4) { + regs->swreg233.sw_refer4_tcbase_msb = val; + } else if (i == 5) { + regs->swreg235.sw_refer5_tcbase_msb = val; + } else if (i == 6) { + regs->swreg237.sw_refer6_tcbase_msb = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +static void set_ref_sign_bias(VdpuAv1dRegSet *regs, RK_S32 i, RK_S32 val) +{ + if (i == 0) { + regs->swreg59.sw_ref0_sign_bias = val; + } else if (i == 1) { + regs->swreg59.sw_ref1_sign_bias = val; + } else if (i == 2) { + regs->swreg59.sw_ref2_sign_bias = val; + } else if (i == 3) { + regs->swreg59.sw_ref3_sign_bias = val; + } else if (i == 4) { + regs->swreg9.sw_ref4_sign_bias = val; + } else if (i == 5) { + regs->swreg9.sw_ref5_sign_bias = val; + } else if (i == 6) { + regs->swreg9.sw_ref6_sign_bias = val; + } else { + mpp_err("Error: trying to set invalid reference index."); + } +} + +#define MAX_FRAME_DISTANCE 31 + +static RK_S32 GetRelativeDist(DXVA_PicParams_AV1 *dxva, RK_S32 a, RK_S32 b) +{ + if (!dxva->order_hint_bits) return 0; + const RK_S32 bits = dxva->order_hint_bits - 1; + + RK_S32 diff = a - b; + RK_S32 m = 1 << bits; + diff = (diff & (m - 1)) - (diff & m); + return diff; +} + +#define POPULATE_REF_OFFSET(index) \ + { \ + RK_S32 ref_offset[AV1_NUM_REF_FRAMES - 1]; \ + RK_S32 idx = refs_selected[(index) - 1]; \ + ref_offset[0] = GetRelativeDist(dxva, dxva->frame_refs[idx].order_hint, \ + dxva->frame_refs[idx].lst_frame_offset); \ + ref_offset[1] = GetRelativeDist(dxva, dxva->frame_refs[idx].order_hint, \ + dxva->frame_refs[idx].lst2_frame_offset); \ + ref_offset[2] = GetRelativeDist(dxva, dxva->frame_refs[idx].order_hint, \ + dxva->frame_refs[idx].lst3_frame_offset); \ + ref_offset[3] = GetRelativeDist(dxva, dxva->frame_refs[idx].order_hint, \ + dxva->frame_refs[idx].gld_frame_offset); \ + ref_offset[4] = GetRelativeDist(dxva, dxva->frame_refs[idx].order_hint, \ + dxva->frame_refs[idx].bwd_frame_offset); \ + ref_offset[5] = GetRelativeDist(dxva, dxva->frame_refs[idx].order_hint, \ + dxva->frame_refs[idx].alt2_frame_offset); \ + ref_offset[6] = GetRelativeDist(dxva, dxva->frame_refs[idx].order_hint, \ + dxva->frame_refs[idx].alt_frame_offset); \ + if(index == 1) { \ + regs->swreg20.sw_mf1_last_offset = ref_offset[0]; \ + regs->swreg21.sw_mf1_last2_offset = ref_offset[1]; \ + regs->swreg22.sw_mf1_last3_offset = ref_offset[2]; \ + regs->swreg23.sw_mf1_golden_offset = ref_offset[3]; \ + regs->swreg24.sw_mf1_bwdref_offset = ref_offset[4]; \ + regs->swreg25.sw_mf1_altref2_offset = ref_offset[5]; \ + regs->swreg26.sw_mf1_altref_offset = ref_offset[6]; \ + }else if(index == 2) { \ + regs->swreg27.sw_mf2_last_offset = ref_offset[0]; \ + regs->swreg47.sw_mf2_last2_offset = ref_offset[1]; \ + regs->swreg47.sw_mf2_last3_offset = ref_offset[2]; \ + regs->swreg47.sw_mf2_golden_offset = ref_offset[3]; \ + regs->swreg48.sw_mf2_bwdref_offset = ref_offset[4]; \ + regs->swreg48.sw_mf2_altref2_offset = ref_offset[5]; \ + regs->swreg48.sw_mf2_altref_offset = ref_offset[6]; \ + }else { \ + regs->swreg184.sw_mf3_last_offset = ref_offset[0]; \ + regs->swreg185.sw_mf3_last2_offset = ref_offset[1]; \ + regs->swreg186.sw_mf3_last3_offset = ref_offset[2]; \ + regs->swreg187.sw_mf3_golden_offset = ref_offset[3]; \ + regs->swreg188.sw_mf3_bwdref_offset = ref_offset[4]; \ + regs->swreg257.sw_mf3_altref2_offset = ref_offset[5]; \ + regs->swreg262.sw_mf3_altref_offset = ref_offset[6]; \ + } \ +} + + +static void set_frame_sign_bias(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + RK_U32 i = 0; + VdpuAv1dRegCtx *reg_ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + if (!dxva->order_hint_bits || dxva->format.frame_type == AV1_FRAME_INTRA_ONLY || + dxva->format.frame_type == AV1_FRAME_KEY) { + for (i = 0; i < AV1_REF_LIST_SIZE; i++) { + reg_ctx->ref_frame_sign_bias[i] = 0; + } + return; + } + + // Identify the nearest forward and backward references. + for (i = 0; i < AV1_ACTIVE_REFS_EX; i++) { + if (dxva->frame_refs[i].Index >= 0) { + RK_S32 ref_frame_offset = dxva->frame_refs[i].order_hint; + RK_S32 rel_off = GetRelativeDist(dxva, ref_frame_offset, dxva->order_hint); + reg_ctx->ref_frame_sign_bias[i + 1] = (rel_off <= 0) ? 0 : 1; + AV1D_DBG(AV1D_DBG_LOG, "frame_refs[%d] order_hint %d ref_frame_offset %d\n", + i, dxva->order_hint, ref_frame_offset); + } + } +} + +static void vdpu_av1d_set_prob(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + VdpuAv1dRegCtx *reg_ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + const int mv_cdf_offset = offsetof(AV1CDFs, mv_cdf); + RK_U8* prob_base = mpp_buffer_get_ptr(reg_ctx->prob_tbl_base); + VdpuAv1dRegSet *regs = reg_ctx->regs; + + memcpy(prob_base, dxva->cdfs, sizeof(AV1CDFs)); + if (dxva->format.frame_type == AV1_FRAME_INTRA_ONLY || + dxva->format.frame_type == AV1_FRAME_KEY) { + // Overwrite MV context area with intrabc MV context + memcpy(prob_base + mv_cdf_offset, dxva->cdfs_ndvc, sizeof(Av1MvCDFs)); + } + mpp_buffer_sync_end(reg_ctx->prob_tbl_base); + + regs->addr_cfg.swreg171.sw_prob_tab_out_base_lsb = mpp_buffer_get_fd(reg_ctx->prob_tbl_out_base); + regs->addr_cfg.swreg173.sw_prob_tab_base_lsb = mpp_buffer_get_fd(reg_ctx->prob_tbl_base); +} + +static void vdpu_av1d_set_reference_frames(Av1dHalCtx *p_hal, VdpuAv1dRegCtx *ctx, DXVA_PicParams_AV1 *dxva) +{ + RK_U32 tmp1, tmp2, i; + RK_U32 cur_height, cur_width; + RK_U8 max_ref_frames = AV1_NUM_REF_FRAMES; + RK_U8 prev_valid = 0; + + VdpuAv1dRegSet *regs = ctx->regs; + RK_S32 ref_count[AV1DEC_MAX_PIC_BUFFERS] = {0}; + + RK_U32 ref_scale_e = 1; + RK_U32 y_stride = ctx->luma_size; + RK_U32 uv_stride = y_stride / 2; + RK_U32 mv_offset = ctx->luma_size + ctx->chroma_size + 64; + + if (!dxva->coding.intrabc) { + for (i = 0; i < AV1_REF_LIST_SIZE - 1; i++) { + if (dxva->frame_refs[i].Index >= 0) + ref_count[dxva->frame_refs[i].Index]++; + } + + for (i = 0; i < AV1DEC_MAX_PIC_BUFFERS; i++) { + if (ref_count[i]) + regs->swreg4.sw_ref_frames++; + } + } else + regs->swreg4.sw_ref_frames = 1; + + cur_width = dxva->width; + cur_height = dxva->height; + + set_frame_sign_bias(p_hal, dxva); + + for (i = AV1_REF_FRAME_LAST; i < max_ref_frames; i++) { + RK_U32 ref = i - 1; + RK_S32 idx = 0; + if (dxva->coding.intrabc) { + idx = dxva->CurrPicTextureIndex; + tmp1 = cur_width; + tmp2 = cur_height; + } else { + tmp1 = dxva->frame_refs[ref].width; + tmp2 = dxva->frame_refs[ref].height; + if (dxva->frame_refs[ref].Index > 0) { + idx = dxva->frame_refs[ref].Index; + } + } + + set_ref_width(regs, ref, tmp1); + set_ref_height(regs, ref, tmp2); + tmp1 = ((tmp1 << AV1_REF_SCALE_SHIFT) + cur_width / 2) / cur_width; + tmp2 = ((tmp2 << AV1_REF_SCALE_SHIFT) + cur_height / 2) / cur_height; + + set_ref_hor_scale(regs, ref, tmp1); + set_ref_ver_scale(regs, ref, tmp2); + + /* Keep ref_scale_e always 1 for hw bug */ + // if (tmp1 != (1 << AV1_REF_SCALE_SHIFT) || + // tmp2 != (1 << AV1_REF_SCALE_SHIFT)) { + // ref_scale_e = 1; + // } + + if (idx == ctx->prev_out_buffer_i) { + prev_valid = 1; + } + + set_ref_lum_base(regs, ref, idx, ctx->tile_out_bufs); + set_ref_cb_base(p_hal, ref, idx, ctx->tile_out_bufs, y_stride); + set_ref_dbase (p_hal, ref, idx, ctx->tile_out_bufs, mv_offset); + + set_ref_lum_base_msb(regs, ref, 0); + set_ref_cb_base_msb(regs, ref, 0); + set_ref_dbase_msb (regs, ref, 0); + + if (0) { + set_ref_ty_base(regs, ref, idx, ctx->tile_out_bufs); + set_ref_tc_base(regs, ref, idx, ctx->tile_out_bufs); + set_ref_ty_base_msb(regs, ref, 0); + set_ref_tc_base_msb(regs, ref, 0); + } + set_ref_sign_bias(regs, ref, ctx->ref_frame_sign_bias[i]); + } + + regs->swreg184.sw_ref0_gm_mode = dxva->frame_refs[0].wmtype; + regs->swreg185.sw_ref1_gm_mode = dxva->frame_refs[1].wmtype; + regs->swreg186.sw_ref2_gm_mode = dxva->frame_refs[2].wmtype; + regs->swreg187.sw_ref3_gm_mode = dxva->frame_refs[3].wmtype; + regs->swreg188.sw_ref4_gm_mode = dxva->frame_refs[4].wmtype; + regs->swreg257.sw_ref5_gm_mode = dxva->frame_refs[5].wmtype; + regs->swreg262.sw_ref6_gm_mode = dxva->frame_refs[6].wmtype; + + + if (dxva->coding.intrabc) { + ctx->prev_out_buffer_i = dxva->CurrPicTextureIndex; + } else if (!prev_valid) { + ctx->prev_out_buffer_i = dxva->frame_refs[0].Index; // LAST + } + + { + RK_S32 gld_buf_idx = AV1_REF_FRAME_GOLDEN - AV1_REF_FRAME_LAST; + RK_S32 alt_buf_idx = AV1_REF_FRAME_ALTREF - AV1_REF_FRAME_LAST; + RK_S32 lst_buf_idx = AV1_REF_FRAME_LAST - AV1_REF_FRAME_LAST; + RK_S32 bwd_buf_idx = AV1_REF_FRAME_BWDREF - AV1_REF_FRAME_LAST; + RK_S32 alt2_buf_idx = AV1_REF_FRAME_ALTREF2 - AV1_REF_FRAME_LAST; + RK_S32 lst2_buf_idx = AV1_REF_FRAME_LAST2 - AV1_REF_FRAME_LAST; + + RK_S32 cur_frame_offset = dxva->order_hint; + RK_S32 alt_frame_offset = 0; + RK_S32 gld_frame_offset = 0; + RK_S32 bwd_frame_offset = 0; + RK_S32 alt2_frame_offset = 0; + RK_S32 refs_selected[3] = {0, 0, 0}; + RK_S32 cur_mi_cols = (dxva->width + 7) >> 3; + RK_S32 cur_mi_rows = (dxva->height + 7) >> 3; + RK_U8 mf_types[3] = {0, 0, 0}; + RK_S32 ref_stamp = 2; + RK_S32 ref_ind = 0; + RK_S32 rf; + + if (dxva->frame_refs[alt_buf_idx].Index >= 0) + alt_frame_offset = dxva->frame_refs[alt_buf_idx].order_hint; + if (dxva->frame_refs[gld_buf_idx].Index >= 0) + gld_frame_offset = dxva->frame_refs[gld_buf_idx].order_hint; + if (dxva->frame_refs[bwd_buf_idx].Index >= 0) + bwd_frame_offset = dxva->frame_refs[bwd_buf_idx].order_hint; + if (dxva->frame_refs[alt2_buf_idx].Index >= 0) + alt2_frame_offset = dxva->frame_refs[alt2_buf_idx].order_hint; + + AV1D_DBG(AV1D_DBG_LOG, "frame_offset[%d %d %d %d] lst_idx %d alt_off %d\n", + alt_frame_offset, + gld_frame_offset, + bwd_frame_offset, + alt2_frame_offset, + dxva->frame_refs[lst_buf_idx].Index, + dxva->frame_refs[lst_buf_idx].alt_frame_offset); + + if (dxva->frame_refs[lst_buf_idx].Index >= 0) { + const RK_S32 alt_frame_offset_in_lst = + dxva->frame_refs[lst_buf_idx].alt_frame_offset; + + const RK_S32 is_lst_overlay = (alt_frame_offset_in_lst == gld_frame_offset); + if (!is_lst_overlay) { + RK_S32 lst_mi_cols = + (dxva->frame_refs[lst_buf_idx].width + 7) >> 3; + RK_S32 lst_mi_rows = + (dxva->frame_refs[lst_buf_idx].height + 7) >> 3; + // TODO(stan): what's the difference btw key_frame and intra_only? + RK_S32 lst_intra_only = + dxva->frame_refs[lst_buf_idx].intra_only || + dxva->frame_refs[lst_buf_idx].is_intra_frame; + if (lst_mi_cols == cur_mi_cols && lst_mi_rows == cur_mi_rows && + !lst_intra_only) { + mf_types[ref_ind] = AV1_REF_FRAME_LAST; + refs_selected[ref_ind++] = lst_buf_idx; + } + } + ref_stamp--; + } + + if (GetRelativeDist(dxva, bwd_frame_offset, cur_frame_offset) > 0) { + RK_S32 bwd_mi_cols = + (dxva->frame_refs[bwd_buf_idx].width + 7) >> 3; + RK_S32 bwd_mi_rows = + (dxva->frame_refs[bwd_buf_idx].height + 7) >> 3; + RK_S32 bwd_intra_only = dxva->frame_refs[bwd_buf_idx].intra_only || + dxva->frame_refs[bwd_buf_idx].is_intra_frame; + if (bwd_mi_cols == cur_mi_cols && bwd_mi_rows == cur_mi_rows && + !bwd_intra_only) { + mf_types[ref_ind] = AV1_REF_FRAME_BWDREF; + refs_selected[ref_ind++] = bwd_buf_idx; + ref_stamp--; + } + } + + if (GetRelativeDist(dxva, alt2_frame_offset, cur_frame_offset) > 0) { + RK_S32 alt2_mi_cols = + (dxva->frame_refs[alt2_buf_idx].width + 7) >> 3; + RK_S32 alt2_mi_rows = + (dxva->frame_refs[alt2_buf_idx].height + 7) >> 3; + RK_S32 alt2_intra_only = + dxva->frame_refs[alt2_buf_idx].intra_only || + dxva->frame_refs[alt2_buf_idx].is_intra_frame; + if (alt2_mi_cols == cur_mi_cols && alt2_mi_rows == cur_mi_rows && + !alt2_intra_only) { + mf_types[ref_ind] = AV1_REF_FRAME_ALTREF2; + refs_selected[ref_ind++] = alt2_buf_idx; + ref_stamp--; + } + } + + if (GetRelativeDist(dxva, alt_frame_offset, cur_frame_offset) > 0 && + ref_stamp >= 0) { + RK_S32 alt_mi_cols = + (dxva->frame_refs[alt_buf_idx].width + 7) >> 3; + RK_S32 alt_mi_rows = + (dxva->frame_refs[alt_buf_idx].height + 7) >> 3; + RK_S32 alt_intra_only = dxva->frame_refs[alt_buf_idx].intra_only || + dxva->frame_refs[alt_buf_idx].is_intra_frame; + if (alt_mi_cols == cur_mi_cols && alt_mi_rows == cur_mi_rows && + !alt_intra_only) { + mf_types[ref_ind] = AV1_REF_FRAME_ALTREF; + refs_selected[ref_ind++] = alt_buf_idx; + ref_stamp--; + } + } + + if (ref_stamp >= 0 && dxva->frame_refs[lst2_buf_idx].Index >= 0) { + RK_S32 lst2_mi_cols = + (dxva->frame_refs[lst2_buf_idx].width + 7) >> 3; + RK_S32 lst2_mi_rows = + (dxva->frame_refs[lst2_buf_idx].height + 7) >> 3; + RK_S32 lst2_intra_only = + dxva->frame_refs[lst2_buf_idx].intra_only || + dxva->frame_refs[lst2_buf_idx].is_intra_frame; + if (lst2_mi_cols == cur_mi_cols && lst2_mi_rows == cur_mi_rows && + !lst2_intra_only) { + mf_types[ref_ind] = AV1_REF_FRAME_LAST2; + refs_selected[ref_ind++] = lst2_buf_idx; + ref_stamp--; + } + } + + RK_S32 cur_offset[AV1_NUM_REF_FRAMES - 1]; + RK_S32 cur_roffset[AV1_NUM_REF_FRAMES - 1]; + for ( rf = 0; rf < AV1_NUM_REF_FRAMES - 1; ++rf) { + RK_S32 buf_idx = dxva->frame_refs[rf].Index; + if (buf_idx >= 0) { + cur_offset[rf] = + GetRelativeDist(dxva, cur_frame_offset, + dxva->frame_refs[rf].order_hint); + cur_roffset[rf] = + GetRelativeDist(dxva, dxva->frame_refs[rf].order_hint, + cur_frame_offset); + AV1D_DBG(AV1D_DBG_LOG, "buf_idx[%d]=%d offset[%d : %d] hin %d\n", rf, buf_idx, cur_offset[rf], cur_roffset[rf], dxva->frame_refs[rf].order_hint); + } else { + cur_offset[rf] = 0; + cur_roffset[rf] = 0; + } + } + + regs->swreg11.sw_use_temporal0_mvs = 0; + regs->swreg11.sw_use_temporal1_mvs = 0; + regs->swreg11.sw_use_temporal2_mvs = 0; + regs->swreg11.sw_use_temporal3_mvs = 0; + + if (dxva->coding.use_ref_frame_mvs && ref_ind > 0 && + cur_offset[mf_types[0] - AV1_REF_FRAME_LAST] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[0] - AV1_REF_FRAME_LAST] >= -MAX_FRAME_DISTANCE) { + regs->swreg11.sw_use_temporal0_mvs = 1; + POPULATE_REF_OFFSET(1) + } + + if (dxva->coding.use_ref_frame_mvs && ref_ind > 1 && + cur_offset[mf_types[1] - AV1_REF_FRAME_LAST] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[1] - AV1_REF_FRAME_LAST] >= -MAX_FRAME_DISTANCE) { + regs->swreg11.sw_use_temporal1_mvs = 1; + POPULATE_REF_OFFSET(2) + } + + if (dxva->coding.use_ref_frame_mvs && ref_ind > 2 && + cur_offset[mf_types[2] - AV1_REF_FRAME_LAST] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[2] - AV1_REF_FRAME_LAST] >= -MAX_FRAME_DISTANCE) { + regs->swreg11.sw_use_temporal2_mvs = 1; + POPULATE_REF_OFFSET(3) + } + + // Pass one additional frame that will contain the segment information + if (dxva->segmentation.enabled && + dxva->primary_ref_frame < AV1_REFS_PER_FRAME) { + // Primary ref frame is zero based + RK_S32 prim_buf_idx = dxva->frame_refs[dxva->primary_ref_frame].Index; + + if (prim_buf_idx >= 0) { + HalBuf *tile_out_buf; + + y_stride = ctx->luma_size ; + uv_stride = y_stride / 2; + mv_offset = y_stride + uv_stride + 64; + + tile_out_buf = hal_bufs_get_buf(ctx->tile_out_bufs, prim_buf_idx); + regs->addr_cfg.swreg80.sw_segment_read_base_msb = 0; + regs->addr_cfg.swreg81.sw_segment_read_base_lsb = mpp_buffer_get_fd(tile_out_buf->buf[0]); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 81, mv_offset); + regs->swreg11.sw_use_temporal3_mvs = 1; + } + } + if (dxva->primary_ref_frame < AV1_REFS_PER_FRAME) { + RK_S32 prim_buf_idx = dxva->primary_ref_frame; + ctx->resolution_change = + cur_mi_cols != + (RK_S32)((dxva->frame_refs[prim_buf_idx].width + 7) >> + 3) || + cur_mi_rows != + (RK_S32)((dxva->frame_refs[prim_buf_idx].height + 7) >> + 3); + } + + regs->swreg184.sw_cur_last_offset = cur_offset[0]; + regs->swreg185.sw_cur_last2_offset = cur_offset[1]; + regs->swreg186.sw_cur_last3_offset = cur_offset[2]; + regs->swreg187.sw_cur_golden_offset = cur_offset[3]; + regs->swreg188.sw_cur_bwdref_offset = cur_offset[4]; + regs->swreg257.sw_cur_altref2_offset = cur_offset[5]; + regs->swreg262.sw_cur_altref_offset = cur_offset[6]; + + regs->swreg184.sw_cur_last_roffset = cur_roffset[0]; + regs->swreg185.sw_cur_last2_roffset = cur_roffset[1]; + regs->swreg186.sw_cur_last3_roffset = cur_roffset[2]; + regs->swreg187.sw_cur_golden_roffset = cur_roffset[3]; + regs->swreg188.sw_cur_bwdref_roffset = cur_roffset[4]; + regs->swreg257.sw_cur_altref2_roffset = cur_roffset[5]; + regs->swreg262.sw_cur_altref_roffset = cur_roffset[6]; + + /* Index start from 0 */ + regs->swreg9.sw_mf1_type = mf_types[0] - AV1_REF_FRAME_LAST; + regs->swreg9.sw_mf2_type = mf_types[1] - AV1_REF_FRAME_LAST; + regs->swreg9.sw_mf3_type = mf_types[2] - AV1_REF_FRAME_LAST; + AV1D_DBG(AV1D_DBG_LOG, "mf_types[%d %d %d]\n", mf_types[0], mf_types[1], mf_types[2]); + } + regs->swreg5.sw_ref_scaling_enable = ref_scale_e; +} +#undef MAX_FRAME_DISTANCE + +static void vdpu_av1d_superres_params(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + // Compute and store scaling paramers needed for superres +#define SUPERRES_SCALE_BITS 3 +#define SCALE_NUMERATOR 8 +#define SUPERRES_SCALE_DENOMINATOR_MIN (SCALE_NUMERATOR + 1) + +#define RS_SUBPEL_BITS 6 +#define RS_SUBPEL_MASK ((1 << RS_SUBPEL_BITS) - 1) +#define RS_SCALE_SUBPEL_BITS 14 +#define RS_SCALE_SUBPEL_MASK ((1 << RS_SCALE_SUBPEL_BITS) - 1) +#define RS_SCALE_EXTRA_BITS (RS_SCALE_SUBPEL_BITS - RS_SUBPEL_BITS) +#define RS_SCALE_EXTRA_OFF (1 << (RS_SCALE_EXTRA_BITS - 1)) + VdpuAv1dRegCtx *ctx = p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + RK_U8 superres_scale_denominator = SCALE_NUMERATOR; + RK_U32 superres_luma_step = 0; + RK_U32 superres_chroma_step = 0; + RK_U32 superres_luma_step_invra = 0; + RK_U32 superres_chroma_step_invra = 0; + RK_U32 superres_init_luma_subpel_x = 0; + RK_U32 superres_init_chroma_subpel_x = 0; + RK_U32 superres_is_scaled = 1; + RK_U32 width = 0; + if (dxva->coding.superres) { + superres_scale_denominator = regs->swreg9.sw_scale_denom_minus9 + 9; + } + + if (superres_scale_denominator > SCALE_NUMERATOR) { + width = (dxva->upscaled_width * SCALE_NUMERATOR + + (superres_scale_denominator / 2)) / + superres_scale_denominator; + RK_U32 min_w = MPP_MIN(16, dxva->upscaled_width); + if (width < min_w) width = min_w; + if (width == dxva->upscaled_width) { + superres_is_scaled = 0; + superres_luma_step = RS_SCALE_SUBPEL_BITS; + superres_chroma_step = RS_SCALE_SUBPEL_BITS; + superres_luma_step_invra = RS_SCALE_SUBPEL_BITS; + superres_chroma_step_invra = RS_SCALE_SUBPEL_BITS; + superres_init_luma_subpel_x = 0; + superres_init_chroma_subpel_x = 0; + goto end; + } + { + RK_S32 upscaledLumaPlaneW = dxva->upscaled_width; + RK_S32 downscaledLumaPlaneW = width; + + RK_S32 downscaledChromaPlaneW = (downscaledLumaPlaneW + 1) >> 1; + RK_S32 upscaledChromaPlaneW = (upscaledLumaPlaneW + 1) >> 1; + + RK_S32 stepLumaX = ((downscaledLumaPlaneW << RS_SCALE_SUBPEL_BITS) + + (upscaledLumaPlaneW / 2)) / + upscaledLumaPlaneW; + RK_S32 stepChromaX = ((downscaledChromaPlaneW << RS_SCALE_SUBPEL_BITS) + + (upscaledChromaPlaneW / 2)) / + upscaledChromaPlaneW; + RK_S32 errLuma = (upscaledLumaPlaneW * stepLumaX) - + (downscaledLumaPlaneW << RS_SCALE_SUBPEL_BITS); + RK_S32 errChroma = (upscaledChromaPlaneW * stepChromaX) - + (downscaledChromaPlaneW << RS_SCALE_SUBPEL_BITS); + RK_S32 initialLumaSubpelX = + ((-((upscaledLumaPlaneW - downscaledLumaPlaneW) + << (RS_SCALE_SUBPEL_BITS - 1)) + + upscaledLumaPlaneW / 2) / + upscaledLumaPlaneW + + (1 << (RS_SCALE_EXTRA_BITS - 1)) - errLuma / 2) & + RS_SCALE_SUBPEL_MASK; + RK_S32 initialChromaSubpelX = + ((-((upscaledChromaPlaneW - downscaledChromaPlaneW) + << (RS_SCALE_SUBPEL_BITS - 1)) + + upscaledChromaPlaneW / 2) / + upscaledChromaPlaneW + + (1 << (RS_SCALE_EXTRA_BITS - 1)) - errChroma / 2) & + RS_SCALE_SUBPEL_MASK; + + superres_luma_step = stepLumaX; + superres_chroma_step = stepChromaX; + superres_luma_step_invra = + ((upscaledLumaPlaneW << RS_SCALE_SUBPEL_BITS) + + (downscaledLumaPlaneW / 2)) / + downscaledLumaPlaneW; + superres_chroma_step_invra = + ((upscaledChromaPlaneW << RS_SCALE_SUBPEL_BITS) + + (downscaledChromaPlaneW / 2)) / + downscaledChromaPlaneW; + superres_init_luma_subpel_x = initialLumaSubpelX; + superres_init_chroma_subpel_x = initialChromaSubpelX; + } + } else { + superres_luma_step = RS_SCALE_SUBPEL_BITS; + superres_chroma_step = RS_SCALE_SUBPEL_BITS; + superres_luma_step_invra = RS_SCALE_SUBPEL_BITS; + superres_chroma_step_invra = RS_SCALE_SUBPEL_BITS; + superres_init_luma_subpel_x = 0; + superres_init_chroma_subpel_x = 0; + superres_is_scaled = 0; + } +end: + regs->swreg51.sw_superres_luma_step = superres_luma_step; + regs->swreg51.sw_superres_chroma_step = superres_chroma_step; + regs->swreg298.sw_superres_luma_step_invra = superres_luma_step_invra; + regs->swreg298.sw_superres_chroma_step_invra = superres_chroma_step_invra; + regs->swreg52.sw_superres_init_luma_subpel_x = superres_init_luma_subpel_x; + regs->swreg52.sw_superres_init_chroma_subpel_x = superres_init_chroma_subpel_x; + regs->swreg5.sw_superres_is_scaled = superres_is_scaled; + + regs->addr_cfg.swreg89.sw_superres_colbuf_base_lsb = mpp_buffer_get_fd(ctx->filter_mem); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 89, ctx->filt_info[SR_COL].offset); +} + + +static void vdpu_av1d_set_picture_dimensions(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + /* Write dimensions for the current picture + (This is needed when scaling is used) */ + VdpuAv1dRegCtx *ctx = p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + + regs->swreg4.sw_pic_width_in_cbs = MPP_ALIGN(dxva->width, 8) >> 3; + regs->swreg4.sw_pic_height_in_cbs = MPP_ALIGN(dxva->height, 8) >> 3; + regs->swreg12.sw_pic_width_pad = MPP_ALIGN(dxva->width, 8) - dxva->width; + regs->swreg12.sw_pic_height_pad = MPP_ALIGN(dxva->height, 8) - dxva->height; + + regs->swreg8.sw_superres_pic_width = dxva->upscaled_width; + regs->swreg9.sw_scale_denom_minus9 = dxva->superres_denom; + + vdpu_av1d_superres_params(p_hal, dxva); +} + +static void vdpu_av1d_set_segmentation(VdpuAv1dRegCtx *ctx, DXVA_PicParams_AV1 *dxva) +{ + RK_U32 segval[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; + VdpuAv1dRegSet *regs = ctx->regs; + RK_U8 s, i, j; + RK_U8 segsign = 0; + RK_U8 preskip_segid = 0; + RK_U8 last_active_seg = 0; + /* Segmentation */ + regs->swreg13.sw_segment_temp_upd_e = dxva->segmentation.temporal_update; + regs->swreg13.sw_segment_upd_e = dxva->segmentation.update_map; + regs->swreg13.sw_segment_e = dxva->segmentation.enabled; + + //dec->error_resilient || dec->resolution_change; + regs->swreg5.sw_error_resilient = dxva->coding.error_resilient_mode; + + if ((!dxva->format.frame_type || dxva->format.frame_type == AV1_FRAME_INTRA_ONLY) + || regs->swreg5.sw_error_resilient) { + regs->swreg11.sw_use_temporal3_mvs = 0; + } + + regs->swreg14.sw_filt_level0 = dxva->loop_filter.filter_level[0]; + regs->swreg15.sw_filt_level1 = dxva->loop_filter.filter_level[1]; + regs->swreg16.sw_filt_level2 = dxva->loop_filter.filter_level_u; + regs->swreg17.sw_filt_level3 = dxva->loop_filter.filter_level_v; + + /* Set filter level and QP for every segment ID. Initialize all + * segments with default QP and filter level. */ + for (s = 0; s < AV1_MAX_SEGMENTS; s++) { + segval[s][AV1_SEG_LVL_ALT_Q] = 0; + segval[s][AV1_SEG_LVL_ALT_LF_Y_V] = 0; + segval[s][AV1_SEG_LVL_ALT_LF_Y_H] = 0; + segval[s][AV1_SEG_LVL_ALT_LF_U] = 0; + segval[s][AV1_SEG_LVL_ALT_LF_V] = 0; + segval[s][AV1_SEG_LVL_REF_FRAME] = 0; /* segment ref_frame disabled */ + segval[s][AV1_SEG_LVL_SKIP] = 0; /* segment skip disabled */ + segval[s][AV1_SEG_LVL_GLOBALMV] = 0; /* global motion */ + } + /* If a feature is enabled for a segment, overwrite the default. */ + if (dxva->segmentation.enabled) { + RK_S32 (*segdata)[AV1_SEG_LVL_MAX] = dxva->segmentation.feature_data; + + for (s = 0; s < AV1_MAX_SEGMENTS; s++) { + if (dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_ALT_Q)) { + segval[s][AV1_SEG_LVL_ALT_Q] = + MPP_CLIP3(0, 255, MPP_ABS(segdata[s][AV1_SEG_LVL_ALT_Q])); + segsign |= (segdata[s][AV1_SEG_LVL_ALT_Q] < 0) << s; + } + + if (dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_ALT_LF_Y_V)) + segval[s][AV1_SEG_LVL_ALT_LF_Y_V] = + MPP_CLIP3(-63, 63, segdata[s][AV1_SEG_LVL_ALT_LF_Y_V]); + + if (dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_ALT_LF_Y_H)) + segval[s][AV1_SEG_LVL_ALT_LF_Y_H] = + MPP_CLIP3(-63, 63, segdata[s][AV1_SEG_LVL_ALT_LF_Y_H]); + + if (dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_ALT_LF_U)) + segval[s][AV1_SEG_LVL_ALT_LF_U] = + MPP_CLIP3(-63, 63, segdata[s][AV1_SEG_LVL_ALT_LF_U]); + + if (dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_ALT_LF_V)) + segval[s][AV1_SEG_LVL_ALT_LF_V] = + MPP_CLIP3(-63, 63, segdata[s][AV1_SEG_LVL_ALT_LF_V]); + + if (dxva->format.frame_type && + dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_REF_FRAME)) + segval[s][AV1_SEG_LVL_REF_FRAME] = + segdata[s][AV1_SEG_LVL_REF_FRAME] + 1; + + if (dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_SKIP)) + segval[s][AV1_SEG_LVL_SKIP] = 1; + if (dxva->segmentation.feature_mask[s] & (1 << AV1_SEG_LVL_GLOBALMV)) + segval[s][AV1_SEG_LVL_GLOBALMV] = 1; + } + } + + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + if (dxva->segmentation.feature_mask[i] & (1 << j)) { + preskip_segid |= j >= AV1_SEG_LVL_REF_FRAME; + last_active_seg = MPP_MAX(i, last_active_seg); + } + } + } + + regs->swreg9.sw_last_active_seg = last_active_seg; + regs->swreg5.sw_preskip_segid = preskip_segid; + + regs->swreg12.sw_seg_quant_sign = segsign; + /* Write QP, filter level, ref frame and skip for every segment */ + regs->swreg14.sw_quant_seg0 = segval[0][AV1_SEG_LVL_ALT_Q]; + regs->swreg14.sw_filt_level_delta0_seg0 = segval[0][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg20.sw_filt_level_delta1_seg0 = segval[0][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg20.sw_filt_level_delta2_seg0 = segval[0][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg20.sw_filt_level_delta3_seg0 = segval[0][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg14.sw_refpic_seg0 = segval[0][AV1_SEG_LVL_REF_FRAME]; + regs->swreg14.sw_skip_seg0 = segval[0][AV1_SEG_LVL_SKIP]; + regs->swreg20.sw_global_mv_seg0 = segval[0][AV1_SEG_LVL_GLOBALMV]; + + regs->swreg15.sw_quant_seg1 = segval[1][AV1_SEG_LVL_ALT_Q]; + regs->swreg15.sw_filt_level_delta0_seg1 = segval[1][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg21.sw_filt_level_delta1_seg1 = segval[1][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg21.sw_filt_level_delta2_seg1 = segval[1][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg21.sw_filt_level_delta3_seg1 = segval[1][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg15.sw_refpic_seg1 = segval[1][AV1_SEG_LVL_REF_FRAME]; + regs->swreg15.sw_skip_seg1 = segval[1][AV1_SEG_LVL_SKIP]; + regs->swreg21.sw_global_mv_seg1 = segval[1][AV1_SEG_LVL_GLOBALMV]; + + regs->swreg16.sw_quant_seg2 = segval[2][AV1_SEG_LVL_ALT_Q]; + regs->swreg16.sw_filt_level_delta0_seg2 = segval[2][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg22.sw_filt_level_delta1_seg2 = segval[2][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg22.sw_filt_level_delta2_seg2 = segval[2][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg22.sw_filt_level_delta3_seg2 = segval[2][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg16.sw_refpic_seg2 = segval[2][AV1_SEG_LVL_REF_FRAME]; + regs->swreg16.sw_skip_seg2 = segval[2][AV1_SEG_LVL_SKIP]; + regs->swreg22.sw_global_mv_seg2 = segval[2][AV1_SEG_LVL_GLOBALMV]; + + regs->swreg17.sw_quant_seg3 = segval[3][AV1_SEG_LVL_ALT_Q]; + regs->swreg17.sw_filt_level_delta0_seg3 = segval[3][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg23.sw_filt_level_delta1_seg3 = segval[3][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg23.sw_filt_level_delta2_seg3 = segval[3][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg23.sw_filt_level_delta3_seg3 = segval[3][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg17.sw_refpic_seg3 = segval[3][AV1_SEG_LVL_REF_FRAME]; + regs->swreg17.sw_skip_seg3 = segval[3][AV1_SEG_LVL_SKIP]; + regs->swreg23.sw_global_mv_seg3 = segval[3][AV1_SEG_LVL_GLOBALMV]; + + regs->swreg18.sw_quant_seg4 = segval[4][AV1_SEG_LVL_ALT_Q]; + regs->swreg18.sw_filt_level_delta0_seg4 = segval[4][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg24.sw_filt_level_delta1_seg4 = segval[4][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg24.sw_filt_level_delta2_seg4 = segval[4][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg24.sw_filt_level_delta3_seg4 = segval[4][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg18.sw_refpic_seg4 = segval[4][AV1_SEG_LVL_REF_FRAME]; + regs->swreg18.sw_skip_seg4 = segval[4][AV1_SEG_LVL_SKIP]; + regs->swreg24.sw_global_mv_seg4 = segval[4][AV1_SEG_LVL_GLOBALMV]; + + regs->swreg19.sw_quant_seg5 = segval[5][AV1_SEG_LVL_ALT_Q]; + regs->swreg19.sw_filt_level_delta0_seg5 = segval[5][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg25.sw_filt_level_delta1_seg5 = segval[5][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg25.sw_filt_level_delta2_seg5 = segval[5][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg25.sw_filt_level_delta3_seg5 = segval[5][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg19.sw_refpic_seg5 = segval[5][AV1_SEG_LVL_REF_FRAME]; + regs->swreg19.sw_skip_seg5 = segval[5][AV1_SEG_LVL_SKIP]; + regs->swreg25.sw_global_mv_seg5 = segval[5][AV1_SEG_LVL_GLOBALMV]; + + regs->swreg31.sw_quant_seg6 = segval[6][AV1_SEG_LVL_ALT_Q]; + regs->swreg31.sw_filt_level_delta0_seg6 = segval[6][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg26.sw_filt_level_delta1_seg6 = segval[6][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg26.sw_filt_level_delta2_seg6 = segval[6][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg26.sw_filt_level_delta3_seg6 = segval[6][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg31.sw_refpic_seg6 = segval[6][AV1_SEG_LVL_REF_FRAME]; + regs->swreg31.sw_skip_seg6 = segval[6][AV1_SEG_LVL_SKIP]; + regs->swreg26.sw_global_mv_seg6 = segval[6][AV1_SEG_LVL_GLOBALMV]; + + regs->swreg32.sw_quant_seg7 = segval[7][AV1_SEG_LVL_ALT_Q]; + regs->swreg32.sw_filt_level_delta0_seg7 = segval[7][AV1_SEG_LVL_ALT_LF_Y_V]; + regs->swreg27.sw_filt_level_delta1_seg7 = segval[7][AV1_SEG_LVL_ALT_LF_Y_H]; + regs->swreg27.sw_filt_level_delta2_seg7 = segval[7][AV1_SEG_LVL_ALT_LF_U]; + regs->swreg27.sw_filt_level_delta3_seg7 = segval[7][AV1_SEG_LVL_ALT_LF_V]; + regs->swreg32.sw_refpic_seg7 = segval[7][AV1_SEG_LVL_REF_FRAME]; + regs->swreg32.sw_skip_seg7 = segval[7][AV1_SEG_LVL_SKIP]; + regs->swreg27.sw_global_mv_seg7 = segval[7][AV1_SEG_LVL_GLOBALMV]; +} + +static void vdpu_av1d_set_loopfilter(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + VdpuAv1dRegCtx *ctx = p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + regs->swreg3.sw_filtering_dis = (dxva->loop_filter.filter_level[0] == 0) && (dxva->loop_filter.filter_level[1] == 0); + regs->swreg5.sw_filt_level_base_gt32 = dxva->loop_filter.filter_level[0] > 32; + regs->swreg30.sw_filt_sharpness = dxva->loop_filter.sharpness_level; + if (dxva->loop_filter.mode_ref_delta_enabled) { + regs->swreg59.sw_filt_ref_adj_0 = dxva->loop_filter.ref_deltas[0]; + regs->swreg59.sw_filt_ref_adj_1 = dxva->loop_filter.ref_deltas[1]; + regs->swreg59.sw_filt_ref_adj_2 = dxva->loop_filter.ref_deltas[2]; + regs->swreg59.sw_filt_ref_adj_3 = dxva->loop_filter.ref_deltas[3]; + regs->swreg30.sw_filt_ref_adj_4 = dxva->loop_filter.ref_deltas[4]; + regs->swreg30.sw_filt_ref_adj_5 = dxva->loop_filter.ref_deltas[5]; + regs->swreg49.sw_filt_ref_adj_7 = dxva->loop_filter.ref_deltas[6]; + regs->swreg49.sw_filt_ref_adj_6 = dxva->loop_filter.ref_deltas[7]; + regs->swreg30.sw_filt_mb_adj_0 = dxva->loop_filter.mode_deltas[0]; + regs->swreg30.sw_filt_mb_adj_1 = dxva->loop_filter.mode_deltas[1]; + } else { + regs->swreg59.sw_filt_ref_adj_0 = 0; + regs->swreg59.sw_filt_ref_adj_1 = 0; + regs->swreg59.sw_filt_ref_adj_2 = 0; + regs->swreg59.sw_filt_ref_adj_3 = 0; + regs->swreg30.sw_filt_ref_adj_4 = 0; + regs->swreg30.sw_filt_ref_adj_5 = 0; + regs->swreg49.sw_filt_ref_adj_7 = 0; + regs->swreg49.sw_filt_ref_adj_6 = 0; + regs->swreg30.sw_filt_mb_adj_0 = 0; + regs->swreg30.sw_filt_mb_adj_1 = 0; + } + + regs->addr_cfg.swreg179.sw_dec_vert_filt_base_lsb = mpp_buffer_get_fd(ctx->filter_mem); + regs->addr_cfg.swreg183.sw_dec_bsd_ctrl_base_lsb = mpp_buffer_get_fd(ctx->filter_mem); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 183, ctx->filt_info[DB_CTRL_COL].offset); +} + +static void vdpu_av1d_set_global_model(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + VdpuAv1dRegCtx *ctx = p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + RK_U8 *dst = (RK_U8 *) mpp_buffer_get_ptr(ctx->global_model); + RK_S32 ref_frame, i; + + for (ref_frame = 0; ref_frame < GM_GLOBAL_MODELS_PER_FRAME; ++ref_frame) { + mpp_assert(dxva->frame_refs[ref_frame].wmtype <= 3); + + /* In DDR wmmat order is 0, 1, 3, 2, 4, 5 */ + for (i = 0; i < 6; ++i) { + if (i == 2) + *(RK_S32 *)(dst) = dxva->frame_refs[ref_frame].wmmat[3]; + else if (i == 3) + *(RK_S32 *)(dst) = dxva->frame_refs[ref_frame].wmmat[2]; + else + *(RK_S32 *)(dst) = dxva->frame_refs[ref_frame].wmmat[i]; + dst += 4; + } + + *(RK_S16 *)(dst) = dxva->frame_refs[ref_frame].alpha;//-32768; + dst += 2; + *(RK_S16 *)(dst) = dxva->frame_refs[ref_frame].beta;//-32768; + dst += 2; + *(RK_S16 *)(dst) = dxva->frame_refs[ref_frame].gamma;//-32768; + dst += 2; + *(RK_S16 *)(dst) = dxva->frame_refs[ref_frame].delta;//-32768; + dst += 2; + AV1D_DBG(AV1D_DBG_LOG, "ref_frame[%d] alpa %d beta %d gamma %d delta %d\n", + ref_frame, + dxva->frame_refs[ref_frame].alpha, + dxva->frame_refs[ref_frame].beta, + dxva->frame_refs[ref_frame].gamma, + dxva->frame_refs[ref_frame].delta); + } + mpp_buffer_sync_end(ctx->global_model); + + regs->addr_cfg.swreg82.sw_global_model_base_msb = 0; + regs->addr_cfg.swreg83.sw_global_model_base_lsb = mpp_buffer_get_fd(ctx->global_model); +} + +static void vdpu_av1d_set_tile_info_regs(VdpuAv1dRegCtx *ctx, DXVA_PicParams_AV1 *dxva) +{ + int transpose = ctx->tile_transpose; + VdpuAv1dRegSet *regs = ctx->regs; + size_t context_update_tile_id = dxva->tiles.context_update_id; + size_t context_update_y = context_update_tile_id / dxva->tiles.cols; + size_t context_update_x = context_update_tile_id % dxva->tiles.cols; + + regs->swreg11.sw_multicore_expect_context_update = (0 == context_update_x); + if (transpose) { + context_update_tile_id = + context_update_x * dxva->tiles.rows + context_update_y; + } + regs->swreg10.sw_tile_enable = (dxva->tiles.cols > 1) || (dxva->tiles.rows > 1); + regs->swreg10.sw_num_tile_cols_8k = dxva->tiles.cols; + regs->swreg10.sw_num_tile_rows_8k_av1 = dxva->tiles.rows; + regs->swreg9.sw_context_update_tile_id = context_update_tile_id; + regs->swreg10.sw_tile_transpose = transpose; + regs->swreg11.sw_dec_tile_size_mag = dxva->tiles.tile_sz_mag; + if (regs->swreg10.sw_tile_enable) AV1D_DBG(AV1D_DBG_LOG, "NOTICE: tile enabled.\n"); + + regs->addr_cfg.swreg167.sw_tile_base_lsb = mpp_buffer_get_fd(ctx->tile_info);// + regs->addr_cfg.swreg166.sw_tile_base_msb = 0; +} + +static int check_tile_width(DXVA_PicParams_AV1 *dxva, RK_S32 width, RK_S32 leftmost) +{ + RK_S32 valid = 1; + if (!leftmost && dxva->coding.use_128x128_superblock == 0 && dxva->coding.superres && width == 1) { + AV1D_DBG(AV1D_DBG_LOG, "WARNING: Superres used and tile width == 64\n"); + valid = 0; + } + + const RK_S32 sb_size_log2 = (dxva->coding.use_128x128_superblock != 0) ? 7 : 6; + RK_S32 tile_width_pixels = (width << sb_size_log2); + if (dxva->coding.superres) { + tile_width_pixels = + (tile_width_pixels * (9 + dxva->superres_denom) + 4) / 8; + } + if (tile_width_pixels > 4096) { + if (dxva->coding.superres) + AV1D_LOG("WARNING: Tile width after superres > 4096\n"); + else + AV1D_LOG("WARNING: Tile width > 4096\n"); + valid = 0; + } + return valid; +} + +static void vdpu_av1d_set_tile_info_mem(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + VdpuAv1dRegCtx *ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + + RK_S32 transpose = ctx->tile_transpose; + RK_S32 tmp = dxva->frame_tag_size + dxva->offset_to_dct_parts; + RK_U32 stream_len = p_hal->strm_len - tmp; + RK_U8 *p1 = (RK_U8*)mpp_buffer_get_ptr(ctx->tile_info); + RK_S32 size0 = (transpose != 0) ? dxva->tiles.cols : dxva->tiles.rows; + RK_S32 size1 = (transpose != 0) ? dxva->tiles.rows : dxva->tiles.cols; + RK_S32 tile0, tile1; + RK_U32 not_valid_tile_dimension = 0; + RK_U32 tiles[2][64]; + + /* convert to per tile position */ + { + RK_U8 val = 0, i; + + for (i = 0; i < dxva->tiles.cols; i++) { + tiles[0][i] = val; + val += dxva->tiles.widths[i]; + } + tiles[0][i] = val; + + val = 0; + for (i = 0; i < dxva->tiles.rows; i++) { + tiles[1][i] = val; + val += dxva->tiles.heights[i]; + } + tiles[1][i] = val; + } + + // Write tile dimensions + for (tile0 = 0; tile0 < size0; tile0++) { + for (tile1 = 0; tile1 < size1; tile1++) { + RK_S32 tile_y = (transpose != 0) ? tile1 : tile0; + RK_S32 tile_x = (transpose != 0) ? tile0 : tile1; + RK_S32 tile_id = (transpose != 0) ? tile1 * size0 + tile0 : tile0 * size1 + tile1; + RK_U32 start, end; + + RK_U32 y0 = tiles[1][tile_y]; + RK_U32 y1 = tiles[1][tile_y + 1]; + RK_U32 x0 = tiles[0][tile_x]; + RK_U32 x1 = tiles[0][tile_x + 1]; + + RK_U8 leftmost = (tile_x == dxva->tiles.cols - 1); + if (!not_valid_tile_dimension) + not_valid_tile_dimension = !check_tile_width(dxva, x1 - x0, leftmost); + if ((x0 << ((dxva->coding.use_128x128_superblock != 0) ? 7 : 6)) >= dxva->width || + (y0 << ((dxva->coding.use_128x128_superblock != 0) ? 7 : 6)) >= dxva->height) + not_valid_tile_dimension = 1; + + // tile size in SB units (width,height) + *p1++ = x1 - x0; + *p1++ = 0; + *p1++ = 0; + *p1++ = 0; + *p1++ = y1 - y0; + *p1++ = 0; + *p1++ = 0; + *p1++ = 0; + + // tile start position (offset from sw_stream0_base) + start = dxva->tiles.tile_offset_start[tile_id]; + *p1++ = start & 255; + *p1++ = (start >> 8) & 255; + *p1++ = (start >> 16) & 255; + *p1++ = (start >> 24) & 255; + if (!not_valid_tile_dimension) { + if ((start + 1) > stream_len) + not_valid_tile_dimension = 1; + } + + // # of bytes in tile data + end = dxva->tiles.tile_offset_end[tile_id]; + *p1++ = end & 255; + *p1++ = (end >> 8) & 255; + *p1++ = (end >> 16) & 255; + *p1++ = (end >> 24) & 255; + if (!not_valid_tile_dimension) { + if (end > stream_len) + not_valid_tile_dimension = 1; + } + AV1D_DBG(AV1D_DBG_LOG, "tile_info[%d][%d]: start=%08x end=%08x x0:x1=%d:%d y0:y1=%d:%d\n", + tile0, tile1, start, end, x0, x1, y0, y1); + } + } + mpp_buffer_sync_end(ctx->tile_info); +} + +static void vdpu_av1d_set_cdef(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + RK_U32 luma_pri_strength = 0; + RK_U16 luma_sec_strength = 0; + RK_U32 chroma_pri_strength = 0; + RK_U16 chroma_sec_strength = 0; + VdpuAv1dRegCtx *ctx = p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + RK_S32 i; + + /* CDEF */ + regs->swreg7.sw_cdef_bits = dxva->cdef.bits; + regs->swreg7.sw_cdef_damping = dxva->cdef.damping; + + for (i = 0; i < 8; i++) { + if (i == (1 << (dxva->cdef.bits))) break; + luma_pri_strength |= dxva->cdef.y_strengths[i].primary << (i * 4); + luma_sec_strength |= dxva->cdef.y_strengths[i].secondary << (i * 2); + chroma_pri_strength |= dxva->cdef.uv_strengths[i].primary << (i * 4); + chroma_sec_strength |= dxva->cdef.uv_strengths[i].secondary << (i * 2); + } + + regs->swreg263.sw_cdef_luma_primary_strength = luma_pri_strength; + regs->swreg53.sw_cdef_luma_secondary_strength = luma_sec_strength; + regs->swreg264.sw_cdef_chroma_primary_strength = chroma_pri_strength; + regs->swreg53.sw_cdef_chroma_secondary_strength = chroma_sec_strength; + + // tile column buffer; repurpose some encoder specific base + regs->addr_cfg.swreg85.sw_cdef_colbuf_base_lsb = mpp_buffer_get_fd(ctx->filter_mem); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 85, ctx->filt_info[CDEF_COL].offset); +} + +static void vdpu_av1d_set_lr(Av1dHalCtx *p_hal, DXVA_PicParams_AV1 *dxva) +{ + VdpuAv1dRegCtx *ctx = p_hal->reg_ctx; + VdpuAv1dRegSet *regs = ctx->regs; + RK_U16 lr_type = 0; + RK_U16 lr_unit_size = 0; + RK_S32 i = 0; + + for (i = 0; i < 3; i++) { + lr_type |= dxva->loop_filter.frame_restoration_type[i] << (i * 2); + lr_unit_size |= dxva->loop_filter.log2_restoration_unit_size[i] << (i * 2); + } + regs->swreg18.sw_lr_type = lr_type; + regs->swreg19.sw_lr_unit_size = lr_unit_size; + regs->addr_cfg.swreg91.sw_lr_colbuf_base_lsb = mpp_buffer_get_fd(ctx->filter_mem); + mpp_dev_set_reg_offset(p_hal->cfg->dev, 91, ctx->filt_info[LR_COL].offset); +} + +static void init_scaling_function(RK_U8 scaling_points[][2], RK_U8 num_points, + RK_U8 scaling_lut[]) +{ + RK_S32 i, point; + + if (num_points == 0) { + memset(scaling_lut, 0, 256); + return; + } + + for (i = 0; i < scaling_points[0][0]; i++) + scaling_lut[i] = scaling_points[0][1]; + + for (point = 0; point < num_points - 1; point++) { + RK_S32 x ; + RK_S32 delta_y = scaling_points[point + 1][1] - scaling_points[point][1]; + RK_S32 delta_x = scaling_points[point + 1][0] - scaling_points[point][0]; + RK_S64 delta = + (delta_x != 0) ? delta_y * ((65536 + (delta_x >> 1)) / delta_x) : 0; + for (x = 0; x < delta_x; x++) { + scaling_lut[scaling_points[point][0] + x] = + scaling_points[point][1] + (RK_S32)((x * delta + 32768) >> 16); + } + } + + for (i = scaling_points[num_points - 1][0]; i < 256; i++) + scaling_lut[i] = scaling_points[num_points - 1][1]; +} + +static void vdpu_av1d_set_fgs(VdpuAv1dRegCtx *ctx, DXVA_PicParams_AV1 *dxva) +{ + VdpuAv1dRegSet *regs = ctx->regs; + RK_S32 ar_coeffs_y[24]; + RK_S32 ar_coeffs_cb[25]; + RK_S32 ar_coeffs_cr[25]; + RK_S32 luma_grain_block[73][82]; + RK_S32 cb_grain_block[38][44]; + RK_S32 cr_grain_block[38][44]; + RK_S32 ar_coeff_lag; + RK_S32 ar_coeff_shift; + RK_S32 grain_scale_shift; + RK_S32 bitdepth; + RK_S32 grain_center; + RK_S32 grain_min; + RK_S32 grain_max; + RK_S32 i, j; + RK_U8 *ptr = mpp_buffer_get_ptr(ctx->film_grain_mem); + if (!dxva->film_grain.apply_grain) { + regs->swreg7.sw_apply_grain = 0; + // store reset params + // asic_buff->fg_params[asic_buff->out_buffer_i] = dec->fg_params; + return; + } + /* struct Av1FilmGrainParams *fg_params = &dec->fg_params; + if (!dec->update_parameters) { + RK_S32 active_ref = dec->film_grain_params_ref_idx; + RK_S32 index_ref = Av1BufferQueueGetRef(dec_cont->bq, active_ref); + u16 random_seed = fg_params->random_seed; + *fg_params = asic_buff->fg_params[index_ref]; + fg_params->random_seed = random_seed; + } + asic_buff->fg_params[asic_buff->out_buffer_i] = *fg_params;*/ + + // film grain applied on secondary output + // sw_ctrl->sw_apply_grain = dec_cont->pp_enabled ? 1 : 0; + regs->swreg7.sw_num_y_points_b = dxva->film_grain.num_y_points > 0; + regs->swreg7.sw_num_cb_points_b = dxva->film_grain.num_cb_points > 0; + regs->swreg7.sw_num_cr_points_b = dxva->film_grain.num_cr_points > 0; + regs->swreg8.sw_scaling_shift = dxva->film_grain.scaling_shift_minus8 + 8; + if (! dxva->film_grain.chroma_scaling_from_luma) { + regs->swreg28.sw_cb_mult = dxva->film_grain.cb_mult - 128; + regs->swreg28.sw_cb_luma_mult = dxva->film_grain.cb_luma_mult - 128; + regs->swreg28.sw_cb_offset = dxva->film_grain.cb_offset - 256; + regs->swreg29.sw_cr_mult = dxva->film_grain.cr_mult - 128; + regs->swreg29.sw_cr_luma_mult = dxva->film_grain.cr_luma_mult - 128; + regs->swreg29.sw_cr_offset = dxva->film_grain.cr_offset - 256; + } else { + regs->swreg28.sw_cb_mult = 0; + regs->swreg28.sw_cb_luma_mult = 64; + regs->swreg28.sw_cb_offset = 0; + regs->swreg29.sw_cr_mult = 0; + regs->swreg29.sw_cr_luma_mult = 64; + regs->swreg29.sw_cr_offset = 0; + } + regs->swreg7.sw_overlap_flag = dxva->film_grain.overlap_flag; + regs->swreg7.sw_clip_to_restricted_range = dxva->film_grain.clip_to_restricted_range; + regs->swreg7.sw_chroma_scaling_from_luma = dxva->film_grain.chroma_scaling_from_luma; + regs->swreg7.sw_random_seed = dxva->film_grain.grain_seed; + + init_scaling_function(dxva->film_grain.scaling_points_y, dxva->film_grain.num_y_points, + ctx->fgsmem.scaling_lut_y); + + if (dxva->film_grain.chroma_scaling_from_luma) { + memcpy(ctx->fgsmem.scaling_lut_cb, ctx->fgsmem.scaling_lut_y, + sizeof(*ctx->fgsmem.scaling_lut_y) * 256); + memcpy(ctx->fgsmem.scaling_lut_cr, ctx->fgsmem.scaling_lut_y, + sizeof(*ctx->fgsmem.scaling_lut_y) * 256); + } else { + init_scaling_function(dxva->film_grain.scaling_points_cb, + dxva->film_grain.num_cb_points, ctx->fgsmem.scaling_lut_cb); + init_scaling_function(dxva->film_grain.scaling_points_cr, + dxva->film_grain.num_cr_points, ctx->fgsmem.scaling_lut_cr); + } + + + for (i = 0; i < 25; i++) { + if (i < 24) { + ar_coeffs_y[i] = dxva->film_grain.ar_coeffs_y[i] - 128; + } + ar_coeffs_cb[i] = dxva->film_grain.ar_coeffs_cb[i] - 128; + ar_coeffs_cr[i] = dxva->film_grain.ar_coeffs_cr[i] - 128; + } + + ar_coeff_lag = dxva->film_grain.ar_coeff_lag; + ar_coeff_shift = dxva->film_grain.ar_coeff_shift_minus6 + 6; + grain_scale_shift = dxva->film_grain.grain_scale_shift; + bitdepth = dxva->bitdepth; + grain_center = 128 << (bitdepth - 8); + grain_min = 0 - grain_center; + grain_max = (256 << (bitdepth - 8)) - 1 - grain_center; + + GenerateLumaGrainBlock(luma_grain_block, bitdepth, dxva->film_grain.num_y_points, + grain_scale_shift, ar_coeff_lag, ar_coeffs_y, + ar_coeff_shift, grain_min, grain_max, + dxva->film_grain.grain_seed); + + GenerateChromaGrainBlock( + luma_grain_block, cb_grain_block, cr_grain_block, bitdepth, + dxva->film_grain.num_y_points, dxva->film_grain.num_cb_points, + dxva->film_grain.num_cr_points, grain_scale_shift, ar_coeff_lag, ar_coeffs_cb, + ar_coeffs_cr, ar_coeff_shift, grain_min, grain_max, + dxva->film_grain.chroma_scaling_from_luma, dxva->film_grain.grain_seed); + + for (i = 0; i < 64; i++) { + for (j = 0; j < 64; j++) { + ctx->fgsmem.cropped_luma_grain_block[i * 64 + j] = + luma_grain_block[i + 9][j + 9]; + } + } + + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + ctx->fgsmem.cropped_chroma_grain_block[i * 64 + 2 * j] = + cb_grain_block[i + 6][j + 6]; + ctx->fgsmem.cropped_chroma_grain_block[i * 64 + 2 * j + 1] = + cr_grain_block[i + 6][j + 6]; + } + } + + memcpy(ptr, &ctx->fgsmem, sizeof(AV1FilmGrainMemory)); + mpp_buffer_sync_end(ctx->film_grain_mem); + + regs->addr_cfg.swreg94.sw_filmgrain_base_msb = 0; + regs->addr_cfg.swreg95.sw_filmgrain_base_lsb = mpp_buffer_get_fd(ctx->film_grain_mem); + + if (regs->swreg7.sw_apply_grain) AV1D_DBG(AV1D_DBG_LOG, "NOTICE: filmgrain enabled.\n"); +} + +static MPP_RET vdpu_av1d_setup_tile_bufs(void *hal, DXVA_PicParams_AV1 *dxva) +{ + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + VdpuAv1dRegCtx *ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + RK_U32 out_w = MPP_ALIGN(dxva->max_width * dxva->bitdepth, 16 * 8) / 8; + RK_U32 num_sbs = (MPP_ALIGN(dxva->max_width, 64) / 64 + 1) * (MPP_ALIGN(dxva->max_height, 64) / 64 + 1); + RK_U32 dir_mvs_size = MPP_ALIGN(num_sbs * 24 * 128 / 8, 16) * 2; + RK_U32 out_h = MPP_ALIGN(dxva->max_height, 16); + RK_U32 luma_size = out_w * out_h; + RK_U32 chroma_size = luma_size >> 1; + RK_U32 tile_out_size = luma_size + chroma_size + dir_mvs_size + 512; + + if (tile_out_size <= ctx->tile_out_size) + return MPP_OK; + + ctx->hor_stride = out_w; + ctx->luma_size = luma_size; + ctx->chroma_size = chroma_size; + ctx->tile_out_size = tile_out_size; + + if (ctx->tile_out_bufs) { + hal_bufs_deinit(ctx->tile_out_bufs); + ctx->tile_out_bufs = NULL; + } + hal_bufs_init(&ctx->tile_out_bufs); + if (!ctx->tile_out_bufs) { + mpp_err_f("tile out bufs init fail\n"); + return MPP_ERR_NOMEM; + } + ctx->tile_out_count = mpp_buf_slot_get_count(p_hal->cfg->frame_slots); + hal_bufs_setup(ctx->tile_out_bufs, ctx->tile_out_count, 1, &ctx->tile_out_size); + + return MPP_OK; +} + +MPP_RET vdpu_av1d_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + VdpuAv1dRegCtx *ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + VdpuAv1dRegSet *regs; + DXVA_PicParams_AV1 *dxva = (DXVA_PicParams_AV1*)task->dec.syntax.data; + MppFrame mframe; + MppBuffer buffer = NULL; + MppBuffer streambuf = NULL; + RK_U32 height = dxva->height; + RK_U32 width = dxva->width; + RK_U32 hor_stride; + RK_U32 ver_stride; + HalBuf *tile_out_buf; + RK_U32 num_tile_cols = 1 << dxva->tile_cols_log2; + MppHalCfg *cfg = p_hal->cfg; + + INP_CHECK(ret, NULL == p_hal); + + ctx->refresh_frame_flags = dxva->refresh_frame_flags; + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + mpp_err_f("parse err %d ref err %d\n", + task->dec.flags.parse_err, task->dec.flags.ref_err); + goto __RETURN; + } + + if (p_hal->fast_mode) { + RK_U32 i = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(ctx->reg_buf); i++) { + if (!ctx->reg_buf[i].valid) { + task->dec.reg_index = i; + ctx->regs = ctx->reg_buf[i].regs; + ctx->reg_buf[i].valid = 1; + break; + } + } + } + + regs = ctx->regs; + memset(regs, 0, sizeof(*regs)); + + vdpu_av1d_setup_tile_bufs(p_hal, dxva); + + if (!ctx->filter_mem || height > ctx->height || num_tile_cols > ctx->num_tile_cols) { + if (ctx->filter_mem) + vdpu_av1d_filtermem_release(ctx); + ret = vdpu_av1d_filtermem_alloc(p_hal, ctx, dxva); + if (!ret) { + mpp_err("filt buffer get fail\n"); + vdpu_av1d_filtermem_release(ctx); + } + } + + ctx->width = width; + ctx->height = height; + ctx->num_tile_cols = num_tile_cols; + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_FRAME_PTR, &mframe); + mpp_buf_slot_get_prop(cfg->frame_slots, task->dec.output, SLOT_BUFFER, &buffer); + mpp_buf_slot_get_prop(cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + tile_out_buf = hal_bufs_get_buf(ctx->tile_out_bufs, task->dec.output); + hor_stride = mpp_frame_get_hor_stride(mframe); + ver_stride = mpp_frame_get_ver_stride(mframe); + + ctx->ver_stride = ver_stride; + + p_hal->strm_len = (RK_S32)mpp_packet_get_length(task->dec.input_packet); + + ctx->fbc_en = !!MPP_FRAME_FMT_IS_FBC(mpp_frame_get_fmt(mframe)); + + AV1D_DBG(AV1D_DBG_LOG, "bitdepth %d fmt %d [%d : %d] wxh [%d : %d] uxv [%d : %d]\n", + dxva->bitdepth, mpp_frame_get_fmt(mframe), + dxva->format.subsampling_x, dxva->format.subsampling_y, + ctx->width, ctx->height, + ctx->hor_stride, ctx->ver_stride); + + regs->swreg1.sw_dec_abort_e = 0; + regs->swreg1.sw_dec_e = 1; + regs->swreg1.sw_dec_tile_int_e = 0; + regs->swreg2.sw_dec_clk_gate_e = 1; + + regs->swreg3.sw_dec_mode = 17; // av1 mode + regs->swreg3.sw_skip_mode = dxva->coding.skip_mode; + regs->swreg3.sw_dec_out_ec_byte_word = 0; // word align + regs->swreg3.sw_write_mvs_e = 1; + regs->swreg3.sw_dec_out_ec_bypass = 1; + + regs->swreg5.sw_tempor_mvp_e = dxva->coding.use_ref_frame_mvs; + regs->swreg5.sw_delta_lf_res_log = dxva->loop_filter.delta_lf_res; + regs->swreg5.sw_delta_lf_multi = dxva->loop_filter.delta_lf_multi; + regs->swreg5.sw_delta_lf_present = dxva->loop_filter.delta_lf_present; + regs->swreg5.sw_disable_cdf_update = dxva->coding.disable_cdf_update; + regs->swreg5.sw_allow_warp = dxva->coding.warped_motion; + regs->swreg5.sw_show_frame = dxva->format.show_frame; + regs->swreg5.sw_switchable_motion_mode = dxva->coding.switchable_motion_mode; + regs->swreg5.sw_enable_cdef = !(dxva->cdef.bits == 0 && dxva->cdef.damping == 0 && + dxva->cdef.y_strengths[0].primary == 0 && + dxva->cdef.y_strengths[0].secondary == 0 && + dxva->cdef.uv_strengths[0].primary == 0 && + dxva->cdef.uv_strengths[0].secondary == 0); + regs->swreg5.sw_allow_masked_compound = dxva->coding.masked_compound; + regs->swreg5.sw_allow_interintra = dxva->coding.interintra_compound; + regs->swreg5.sw_enable_intra_edge_filter = dxva->coding.intra_edge_filter; + regs->swreg5.sw_allow_filter_intra = dxva->coding.filter_intra; + regs->swreg5.sw_enable_jnt_comp = dxva->coding.jnt_comp; + regs->swreg5.sw_enable_dual_filter = dxva->coding.dual_filter; + regs->swreg5.sw_reduced_tx_set_used = dxva->coding.reduced_tx_set; + regs->swreg5.sw_allow_screen_content_tools = dxva->coding.screen_content_tools; + regs->swreg5.sw_allow_intrabc = dxva->coding.intrabc; + + regs->swreg5.sw_force_interger_mv = dxva->coding.integer_mv; + + vdpu_av1d_set_global_model(p_hal, dxva); + vdpu_av1d_set_tile_info_mem(p_hal, dxva); + + if ((dxva->format.frame_type && (dxva->format.frame_type != AV1_FRAME_INTRA_ONLY)) + || dxva->coding.intrabc) { + vdpu_av1d_set_reference_frames(p_hal, ctx, dxva); + } + vdpu_av1d_set_segmentation(ctx, dxva); + vdpu_av1d_set_loopfilter(p_hal, dxva); + vdpu_av1d_set_picture_dimensions(p_hal, dxva); + vdpu_av1d_set_cdef(p_hal, dxva); + vdpu_av1d_set_lr(p_hal, dxva); + vdpu_av1d_set_fgs(ctx, dxva); + vdpu_av1d_set_prob(p_hal, dxva); + vdpu_av1d_set_tile_info_regs(ctx, dxva); + +#if DUMP_AV1_DATAS/* dump buffer */ + { + char name[128]; + char *path = "/data/video"; + static int g_frame_num = 0; + FILE *fp; + RK_U32 i; + RK_U32 *data; + RK_U32 size; + + data = mpp_buffer_get_ptr(ctx->global_model); + size = MPP_ALIGN(GLOBAL_MODEL_SIZE, 2048); + memset(name, 0, sizeof(name)); + sprintf(name, "%s/global_mode_%d.txt", path, g_frame_num); + fp = fopen(name, "wb"); + for ( i = 0; i < size / 4; i++) + fprintf(fp, "%08x\n", data[i]); + fflush(fp); + fclose(fp); + + data = mpp_buffer_get_ptr(ctx->tile_info); + size = AV1_TILE_INFO_SIZE; + memset(name, 0, sizeof(name)); + sprintf(name, "%s/tile_info_%d.txt", path, g_frame_num); + fp = fopen(name, "wb"); + for ( i = 0; i < size / 4; i++) + fprintf(fp, "%08x\n", data[i]); + fflush(fp); + fclose(fp); + + data = mpp_buffer_get_ptr(streambuf); + size = MPP_ALIGN(p_hal->strm_len, 1); + memset(name, 0, sizeof(name)); + sprintf(name, "%s/stream_%d.txt", path, g_frame_num); + fp = fopen(name, "wb"); + fwrite((RK_U8*)data, 1, size, fp); + fflush(fp); + fclose(fp); + + data = mpp_buffer_get_ptr(ctx->film_grain_mem); + size = MPP_ALIGN(sizeof(AV1FilmGrainMemory), 2048); + memset(name, 0, sizeof(name)); + sprintf(name, "%s/film_grain_mem_%d.txt", path, g_frame_num); + fp = fopen(name, "wb"); + for ( i = 0; i < size / 4; i++) + fprintf(fp, "%08x\n", data[i]); + fflush(fp); + fclose(fp); + + data = mpp_buffer_get_ptr(ctx->prob_tbl_base); + size = MPP_ALIGN(sizeof(AV1CDFs), 2048); + memset(name, 0, sizeof(name)); + sprintf(name, "%s/prob_tbl_%d.txt", path, g_frame_num); + fp = fopen(name, "wb"); + for ( i = 0; i < size / 4; i++) + fprintf(fp, "%08x\n", data[i]); + fflush(fp); + fclose(fp); + + data = mpp_buffer_get_ptr(ctx->prob_tbl_out_base); + size = MPP_ALIGN(sizeof(AV1CDFs), 2048); + memset(name, 0, sizeof(name)); + sprintf(name, "%s/prob_tbl_out_%d.txt", path, g_frame_num); + fp = fopen(name, "wb"); + for ( i = 0; i < size / 4; i++) + fprintf(fp, "%08x\n", data[i]); + fflush(fp); + fclose(fp); + + g_frame_num ++; + } +#endif + + regs->swreg7.sw_blackwhite_e = dxva->format.mono_chrome; + regs->swreg7.sw_clip_to_restricted_range = dxva->film_grain.clip_to_restricted_range; + regs->swreg7.sw_delta_q_res_log = dxva->quantization.delta_q_res; + regs->swreg7.sw_delta_q_present = dxva->quantization.delta_q_present; + + regs->swreg8.sw_idr_pic_e = dxva->format.frame_type == AV1_FRAME_KEY || + dxva->format.frame_type == AV1_FRAME_INTRA_ONLY; + regs->swreg8.sw_quant_base_qindex = dxva->quantization.base_qindex; + regs->swreg8.sw_bit_depth_y_minus8 = dxva->bitdepth - 8; + regs->swreg8.sw_bit_depth_c_minus8 = dxva->bitdepth - 8; + + regs->swreg11.sw_mcomp_filt_type = dxva->interp_filter; + regs->swreg11.sw_high_prec_mv_e = dxva->coding.high_precision_mv; + regs->swreg11.sw_comp_pred_mode = (dxva->coding.reference_mode != 0) ? 2 : 0; + regs->swreg11.sw_transform_mode = (dxva->coding.tx_mode != 0) ? (dxva->coding.tx_mode + 2) : 0; + regs->swreg12.sw_max_cb_size = (dxva->coding.use_128x128_superblock != 0) ? 7 : 6; + regs->swreg12.sw_min_cb_size = 3; + + /* unused in comdel */ + regs->swreg12.sw_av1_comp_pred_fixed_ref = 0; + regs->swreg13.sw_comp_pred_var_ref0_av1 = 0; + regs->swreg13.sw_comp_pred_var_ref1_av1 = 0; + regs->swreg14.sw_filt_level_seg0 = 0; + regs->swreg15.sw_filt_level_seg1 = 0; + regs->swreg16.sw_filt_level_seg2 = 0; + regs->swreg17.sw_filt_level_seg3 = 0; + regs->swreg18.sw_filt_level_seg4 = 0; + regs->swreg19.sw_filt_level_seg5 = 0; + regs->swreg31.sw_filt_level_seg6 = 0; + regs->swreg32.sw_filt_level_seg7 = 0; + + + regs->swreg13.sw_qp_delta_y_dc_av1 = dxva->quantization.y_dc_delta_q; + regs->swreg13.sw_qp_delta_ch_dc_av1 = dxva->quantization.u_dc_delta_q; + regs->swreg13.sw_qp_delta_ch_ac_av1 = dxva->quantization.u_ac_delta_q; + regs->swreg47.sw_qmlevel_y = dxva->quantization.qm_y; + regs->swreg48.sw_qmlevel_u = dxva->quantization.qm_u; + regs->swreg49.sw_qmlevel_v = dxva->quantization.qm_v; + + regs->swreg13.sw_lossless_e = dxva->coded_lossless; + regs->swreg28.sw_quant_delta_v_dc = dxva->quantization.v_dc_delta_q; + regs->swreg29.sw_quant_delta_v_ac = dxva->quantization.v_ac_delta_q; + + regs->swreg31.sw_skip_ref0 = (dxva->skip_ref0 != 0) ? dxva->skip_ref0 : 1; + regs->swreg32.sw_skip_ref1 = (dxva->skip_ref1 != 0) ? dxva->skip_ref1 : 1; + + /*input out put buf cfg*/ + { + // RK_U32 out_w = MPP_ALIGN(4 * width * bit_depth, 128) / 8; + // RK_U32 out_h = height / 4; + // RK_U32 y_stride = out_w * out_h; + // RK_U32 uv_stride = y_stride / 2; + + RK_U32 y_stride = ctx->luma_size; + RK_U32 uv_stride = y_stride / 2; + RK_U32 mv_offset = y_stride + uv_stride + 64; + RK_U32 offset = (dxva->frame_tag_size & (~0xf)); + + regs->addr_cfg.swreg65.sw_dec_out_ybase_lsb = mpp_buffer_get_fd(tile_out_buf->buf[0]);//mpp_buffer_get_fd(buffer); + regs->addr_cfg.swreg99.sw_dec_out_cbase_lsb = mpp_buffer_get_fd(tile_out_buf->buf[0]); + mpp_dev_set_reg_offset(cfg->dev, 99, y_stride); + regs->addr_cfg.swreg133.sw_dec_out_dbase_lsb = mpp_buffer_get_fd(tile_out_buf->buf[0]); + mpp_dev_set_reg_offset(cfg->dev, 133, mv_offset); + + /* if (ctx->fbc_en) { + regs->swreg190.sw_dec_out_tybase_lsb = 0;// TODO: + regs->swreg224.sw_dec_out_tcbase_lsb = 0;// TODO: + }*/ + + regs->swreg258.sw_strm_buffer_len = MPP_ALIGN(p_hal->strm_len, 128);// + regs->swreg5.sw_strm_start_bit = (dxva->frame_tag_size & 0xf) * 8; // bit start to decode + regs->swreg6.sw_stream_len = MPP_ALIGN(p_hal->strm_len, 128);//p_hal->strm_len - offset; + regs->swreg259.sw_strm_start_offset = 0; + regs->addr_cfg.swreg168.sw_stream_base_msb = 0; + regs->addr_cfg.swreg169.sw_stream_base_lsb = mpp_buffer_get_fd(streambuf); + mpp_dev_set_reg_offset(cfg->dev, 169, offset); + + AV1D_DBG(AV1D_DBG_LOG, "stream len %d\n", p_hal->strm_len); + AV1D_DBG(AV1D_DBG_LOG, "stream offset %d\n", offset); + AV1D_DBG(AV1D_DBG_LOG, "stream tag_size %d\n", dxva->frame_tag_size); + AV1D_DBG(AV1D_DBG_LOG, "stream start_bit %d\n", regs->swreg5.sw_strm_start_bit); + } + regs->swreg314.sw_dec_alignment = 64; + + regs->addr_cfg.swreg175.sw_mc_sync_curr_base_lsb = mpp_buffer_get_fd(ctx->tile_buf); + regs->addr_cfg.swreg177.sw_mc_sync_left_base_lsb = mpp_buffer_get_fd(ctx->tile_buf); + + regs->swreg55.sw_apf_disable = 0; + regs->swreg55.sw_apf_threshold = 8; + regs->swreg58.sw_dec_buswidth = 2; + regs->swreg58.sw_dec_max_burst = 16; + regs->swreg266.sw_error_conceal_e = 0; + regs->swreg265.sw_axi_rd_ostd_threshold = 64; + regs->swreg265.sw_axi_wr_ostd_threshold = 64; + + regs->swreg318.sw_ext_timeout_cycles = 0xfffffff; + regs->swreg318.sw_ext_timeout_override_e = 1; + regs->swreg319.sw_timeout_cycles = 0xfffffff; + regs->swreg319.sw_timeout_override_e = 1; + + /* pp cfg */ + regs->vdpu_av1d_pp_cfg.swreg320.sw_pp_out_e = 1; + regs->vdpu_av1d_pp_cfg.swreg322.sw_pp_in_format = 0; + regs->vdpu_av1d_pp_cfg.swreg394.sw_pp0_dup_hor = 1; + regs->vdpu_av1d_pp_cfg.swreg394.sw_pp0_dup_ver = 1; + regs->vdpu_av1d_pp_cfg.swreg331.sw_pp_in_height = height / 2; + regs->vdpu_av1d_pp_cfg.swreg331.sw_pp_in_width = width / 2; + regs->vdpu_av1d_pp_cfg.swreg332.sw_pp_out_height = height; + regs->vdpu_av1d_pp_cfg.swreg332.sw_pp_out_width = width; + regs->vdpu_av1d_pp_cfg.swreg329.sw_pp_out_y_stride = hor_stride; + regs->vdpu_av1d_pp_cfg.swreg329.sw_pp_out_c_stride = hor_stride; + + // regs->vdpu_av1d_pp_cfg.swreg337.sw_pp_in_y_stride = hor_stride; + // regs->vdpu_av1d_pp_cfg.swreg337.sw_pp_in_c_stride = hor_stride; + if (ctx->fbc_en) { + RK_U32 vir_left = 0, vir_right = 0, vir_top = 0, vir_bottom = 0; + RK_U32 bypass_filter = !regs->swreg5.sw_superres_is_scaled && + !regs->swreg5.sw_enable_cdef && + !regs->swreg14.sw_filt_level0 && + !regs->swreg15.sw_filt_level1 && + !regs->swreg18.sw_lr_type; + + regs->vdpu_av1d_pp_cfg.swreg329.sw_pp_out_y_stride = dxva->bitdepth > 8 ? + width * 2 : width; + regs->vdpu_av1d_pp_cfg.swreg329.sw_pp_out_c_stride = dxva->bitdepth > 8 ? + width * 2 : width; + regs->swreg58.sw_dec_axi_wd_id_e = 1; + regs->swreg58.sw_dec_axi_rd_id_e = 1; + regs->vdpu_av1d_pp_cfg.swreg320.sw_pp_out_tile_e = 1; + regs->vdpu_av1d_pp_cfg.swreg321.sw_pp_tile_size = 2; + + vir_left = 0; + if (((vir_left + width) % 16)) + vir_right = 16 - ((vir_left + width) % 16); + else + vir_right = 0; + + if (!bypass_filter) + vir_top = 8; + else + vir_top = 0; + + if (((vir_top + height) % 16)) + vir_bottom = 16 - ((vir_top + height) % 16); + else + vir_bottom = 0; + + regs->vdpu_av1d_pp_cfg.swreg503.sw_pp0_virtual_top = vir_top; + regs->vdpu_av1d_pp_cfg.swreg503.sw_pp0_virtual_left = vir_left; + regs->vdpu_av1d_pp_cfg.swreg503.sw_pp0_virtual_bottom = vir_bottom; + regs->vdpu_av1d_pp_cfg.swreg503.sw_pp0_virtual_right = vir_right; + mpp_frame_set_offset_y(mframe, vir_top); + mpp_frame_set_ver_stride(mframe, vir_top + height + vir_bottom); + regs->vdpu_av1d_pp_cfg.swreg322.sw_pp_out_format = 0; + regs->vdpu_av1d_pp_cfg.swreg326.sw_pp_out_lu_base_lsb = mpp_buffer_get_fd(buffer); + regs->vdpu_av1d_pp_cfg.swreg328.sw_pp_out_ch_base_lsb = mpp_buffer_get_fd(buffer); + regs->vdpu_av1d_pp_cfg.swreg505.sw_pp0_afbc_tile_base_lsb = mpp_buffer_get_fd(buffer); + } else { + RK_U32 out_w = hor_stride; + RK_U32 out_h = ver_stride; + RK_U32 y_stride = out_w * out_h; + RK_U32 out_fmt = 0; + + if ((mpp_frame_get_fmt(mframe) & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV420SP) + out_fmt = 3; + + /* + * out_fmt: + * 0 is 8bit or 10bit output by syntax + * 3 is force 8bit output + */ + regs->vdpu_av1d_pp_cfg.swreg322.sw_pp_out_format = out_fmt; + regs->vdpu_av1d_pp_cfg.swreg326.sw_pp_out_lu_base_lsb = mpp_buffer_get_fd(buffer); + regs->vdpu_av1d_pp_cfg.swreg328.sw_pp_out_ch_base_lsb = mpp_buffer_get_fd(buffer); + mpp_dev_set_reg_offset(cfg->dev, 328, y_stride); + } + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu_av1d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + INP_CHECK(ret, NULL == p_hal); + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + goto __RETURN; + } + + VdpuAv1dRegCtx *reg_ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + VdpuAv1dRegSet *regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + MppDev dev = p_hal->cfg->dev; +#if DUMP_AV1_DATAS + { + RK_U32 i = 0; + RK_U32 *p = (RK_U32*)regs; + char fname[128]; + FILE *fp_in = NULL; + static RK_U32 g_frame_no = 0; + + sprintf(fname, "/data/video/reg_%d_in.txt", g_frame_no++); + fp_in = fopen(fname, "wb"); + for (i = 0; i < sizeof(*regs) / 4; i++, p++) + fprintf(fp_in, "reg[%3d] = %08x\n", i, *p); + + fflush(fp_in); + fclose(fp_in); + } +#endif + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = regs; + wr_cfg.size = sizeof(*regs); + wr_cfg.offset = 0; + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = sizeof(*regs); + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + /* send request to hardware */ + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu_av1d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + INP_CHECK(ret, NULL == p_hal); + VdpuAv1dRegCtx *reg_ctx = (VdpuAv1dRegCtx *)p_hal->reg_ctx; + VdpuAv1dRegSet *p_regs = (p_hal->fast_mode != 0) ? + reg_ctx->reg_buf[task->dec.reg_index].regs : + reg_ctx->regs; + + if (task->dec.flags.parse_err || + task->dec.flags.ref_err) { + goto __SKIP_HARD; + } + + ret = mpp_dev_ioctl(p_hal->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); +#if DUMP_AV1_DATAS + { + char fname[128]; + FILE *fp_in = NULL; + static RK_U32 g_frame_no = 0; + RK_U32 *p = (RK_U32*)p_regs; + RK_U32 i; + + sprintf(fname, "/data/video/reg_%d_out.txt", g_frame_no++); + fp_in = fopen(fname, "wb"); + for (i = 0; i < sizeof(*p_regs) / 4; i++, p++) + fprintf(fp_in, "reg[%3d] = %08x\n", i, *p); + + fflush(fp_in); + fclose(fp_in); + } +#endif + +__SKIP_HARD: + if (p_hal->cfg->dec_cb) { + DecCbHalDone m_ctx; + RK_U32 *prob_out = (RK_U32*)mpp_buffer_get_ptr(reg_ctx->prob_tbl_out_base); + + mpp_buffer_sync_ro_begin(reg_ctx->prob_tbl_out_base); + m_ctx.task = mpp_buffer_get_ptr(reg_ctx->prob_tbl_out_base);//(void *)&task->dec; + m_ctx.regs = (RK_U32 *)prob_out; + if (!p_regs->swreg1.sw_dec_rdy_int/* decode err */) + m_ctx.hard_err = 1; + else + m_ctx.hard_err = 0; + + mpp_callback(p_hal->cfg->dec_cb, &m_ctx); + } + if (p_hal->fast_mode) + reg_ctx->reg_buf[task->dec.reg_index].valid = 0; + + (void)task; +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu_av1d_reset(void *hal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + INP_CHECK(ret, NULL == p_hal); + + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu_av1d_flush(void *hal) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + INP_CHECK(ret, NULL == p_hal); + +__RETURN: + return ret = MPP_OK; +} + +MPP_RET vdpu_av1d_control(void *hal, MpiCmd cmd_type, void *param) +{ + MPP_RET ret = MPP_ERR_UNKNOW; + Av1dHalCtx *p_hal = (Av1dHalCtx *)hal; + + INP_CHECK(ret, NULL == p_hal); + + switch ((MpiCmd)cmd_type) { + case MPP_DEC_SET_FRAME_INFO: { + MppFrameFormat fmt = mpp_frame_get_fmt((MppFrame)param); + RK_U32 imgwidth = mpp_frame_get_width((MppFrame)param); + RK_U32 imgheight = mpp_frame_get_height((MppFrame)param); + + AV1D_DBG(AV1D_DBG_LOG, "control info: fmt %d, w %d, h %d\n", fmt, imgwidth, imgheight); + if ((fmt & MPP_FRAME_FMT_MASK) == MPP_FMT_YUV422SP) { + mpp_slots_set_prop(p_hal->cfg->frame_slots, SLOTS_LEN_ALIGN, mpp_align_wxh2yuv422); + } + break; + } + case MPP_DEC_SET_OUTPUT_FORMAT: { + + } break; + default: + break; + } + +__RETURN: + return ret = MPP_OK; +} + +const MppHalApi hal_av1d_vdpu = { + .name = "av1d_vdpu", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingAV1, + .ctx_size = sizeof(Av1dHalCtx), + .flag = 0, + .init = vdpu_av1d_init, + .deinit = vdpu_av1d_deinit, + .reg_gen = vdpu_av1d_gen_regs, + .start = vdpu_av1d_start, + .wait = vdpu_av1d_wait, + .reset = vdpu_av1d_reset, + .flush = vdpu_av1d_flush, + .control = vdpu_av1d_control, + .client = VPU_CLIENT_AV1DEC, + .soc_type = { + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_av1d_vdpu) diff --git a/mpp/hal/vpu/av1d/hal_av1d_vdpu.h b/mpp/hal/vpu/av1d/hal_av1d_vdpu.h new file mode 100644 index 000000000..db8e6bb11 --- /dev/null +++ b/mpp/hal/vpu/av1d/hal_av1d_vdpu.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AV1D_VDPU_H +#define HAL_AV1D_VDPU_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_av1d_vdpu; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H264D_VDPU34X_H */ \ No newline at end of file diff --git a/mpp/hal/vpu/av1d/hal_av1d_vdpu_reg.h b/mpp/hal/vpu/av1d/hal_av1d_vdpu_reg.h new file mode 100644 index 000000000..43f36c913 --- /dev/null +++ b/mpp/hal/vpu/av1d/hal_av1d_vdpu_reg.h @@ -0,0 +1,2442 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_AV1D_VDPU_REG_H +#define HAL_AV1D_VDPU_REG_H + +#include "mpp_device.h" + +/* swreg64 - swreg183 */ +typedef struct VdpuAv1dBase_t { + struct { + RK_U32 sw_dec_out_ybase_msb : 32; + } swreg64; + + struct { + RK_U32 sw_dec_out_ybase_lsb : 32; + } swreg65; + + struct { + RK_U32 sw_refer0_ybase_msb : 32; + } swreg66; + + struct { + RK_U32 sw_refer0_ybase_lsb : 32; + } swreg67; + + struct { + RK_U32 sw_refer1_ybase_msb : 32; + } swreg68; + + struct { + RK_U32 sw_refer1_ybase_lsb : 32; + } swreg69; + + struct { + RK_U32 sw_refer2_ybase_msb : 32; + } swreg70; + + struct { + RK_U32 sw_refer2_ybase_lsb : 32; + } swreg71; + + struct { + RK_U32 sw_refer3_ybase_msb : 32; + } swreg72; + + struct { + RK_U32 sw_refer3_ybase_lsb : 32; + } swreg73; + + struct { + RK_U32 sw_refer4_ybase_msb : 32; + } swreg74; + + struct { + RK_U32 sw_refer4_ybase_lsb : 32; + } swreg75; + + struct { + RK_U32 sw_refer5_ybase_msb : 32; + } swreg76; + + struct { + RK_U32 sw_refer5_ybase_lsb : 32; + } swreg77; + + struct { + RK_U32 sw_refer6_ybase_msb : 32; + } swreg78; + + struct { + RK_U32 sw_refer6_ybase_lsb : 32; + } swreg79; + + struct { + RK_U32 sw_segment_read_base_msb : 32; + } swreg80; + + struct { + RK_U32 sw_segment_read_base_lsb : 32; + } swreg81; + + struct { + RK_U32 sw_global_model_base_msb : 32; + } swreg82; + + struct { + RK_U32 sw_global_model_base_lsb : 32; + } swreg83; + + struct { + RK_U32 sw_cdef_colbuf_base_msb : 32; + } swreg84; + + struct { + RK_U32 sw_cdef_colbuf_base_lsb : 32; + } swreg85; + + struct { + RK_U32 sw_cdef_left_colbuf_base_msb : 32; + } swreg86; + + struct { + RK_U32 sw_cdef_left_colbuf_base_lsb : 32; + } swreg87; + + struct { + RK_U32 sw_superres_colbuf_base_msb : 32; + } swreg88; + + struct { + RK_U32 sw_superres_colbuf_base_lsb : 32; + } swreg89; + + struct { + RK_U32 sw_lr_colbuf_base_msb : 32; + } swreg90; + + struct { + RK_U32 sw_lr_colbuf_base_lsb : 32; + } swreg91; + + struct { + RK_U32 sw_superres_left_colbuf_base_msb : 32; + } swreg92; + + struct { + RK_U32 sw_superres_left_colbuf_base_lsb : 32; + } swreg93; + + struct { + RK_U32 sw_filmgrain_base_msb : 32; + } swreg94; + + struct { + RK_U32 sw_filmgrain_base_lsb : 32; + } swreg95; + + struct { + RK_U32 sw_lr_left_colbuf_base_msb : 32; + } swreg96; + + struct { + RK_U32 sw_lr_left_colbuf_base_lsb : 32; + } swreg97; + + struct { + RK_U32 sw_dec_out_cbase_msb : 32; + } swreg98; + + struct { + RK_U32 sw_dec_out_cbase_lsb : 32; + } swreg99; + + struct { + RK_U32 sw_refer0_cbase_msb : 32; + } swreg100; + + struct { + RK_U32 sw_refer0_cbase_lsb : 32; + } swreg101; + + struct { + RK_U32 sw_refer1_cbase_msb : 32; + } swreg102; + + struct { + RK_U32 sw_refer1_cbase_lsb : 32; + } swreg103; + + struct { + RK_U32 sw_refer2_cbase_msb : 32; + } swreg104; + + struct { + RK_U32 sw_refer2_cbase_lsb : 32; + } swreg105; + + struct { + RK_U32 sw_refer3_cbase_msb : 32; + } swreg106; + + struct { + RK_U32 sw_refer3_cbase_lsb : 32; + } swreg107; + + struct { + RK_U32 sw_refer4_cbase_msb : 32; + } swreg108; + + struct { + RK_U32 sw_refer4_cbase_lsb : 32; + } swreg109; + + struct { + RK_U32 sw_refer5_cbase_msb : 32; + } swreg110; + + struct { + RK_U32 sw_refer5_cbase_lsb : 32; + } swreg111; + + struct { + RK_U32 sw_refer6_cbase_msb : 32; + } swreg112; + + struct { + RK_U32 sw_refer6_cbase_lsb : 32; + } swreg113; + + struct { + RK_U32 sw_dec_left_vert_filt_base_msb : 32; + } swreg114; + + struct { + RK_U32 sw_dec_left_vert_filt_base_lsb : 32; + } swreg115; + + struct { + RK_U32 sw_dec_left_bsd_ctrl_base_msb : 32; + } swreg116; + + struct { + RK_U32 sw_dec_left_bsd_ctrl_base_lsb : 32; + } swreg117; + + RK_U32 reserved_118_131[14]; + struct { + RK_U32 sw_dec_out_dbase_msb : 32; + } swreg132; + + struct { + RK_U32 sw_dec_out_dbase_lsb : 32; + } swreg133; + + struct { + RK_U32 sw_refer0_dbase_msb : 32; + } swreg134; + + struct { + RK_U32 sw_refer0_dbase_lsb : 32; + } swreg135; + + struct { + RK_U32 sw_refer1_dbase_msb : 32; + } swreg136; + + struct { + RK_U32 sw_refer1_dbase_lsb : 32; + } swreg137; + + struct { + RK_U32 sw_refer2_dbase_msb : 32; + } swreg138; + + struct { + RK_U32 sw_refer2_dbase_lsb : 32; + } swreg139; + + struct { + RK_U32 sw_refer3_dbase_msb : 32; + } swreg140; + + struct { + RK_U32 sw_refer3_dbase_lsb : 32; + } swreg141; + + struct { + RK_U32 sw_refer4_dbase_msb : 32; + } swreg142; + + struct { + RK_U32 sw_refer4_dbase_lsb : 32; + } swreg143; + + struct { + RK_U32 sw_refer5_dbase_msb : 32; + } swreg144; + + struct { + RK_U32 sw_refer5_dbase_lsb : 32; + } swreg145; + + struct { + RK_U32 sw_refer6_dbase_msb : 32; + } swreg146; + + struct { + RK_U32 sw_refer6_dbase_lsb : 32; + } swreg147; + + RK_U32 reserved_148_165[18]; + struct { + RK_U32 sw_tile_base_msb : 32; + } swreg166; + + struct { + RK_U32 sw_tile_base_lsb : 32; + } swreg167; + + struct { + RK_U32 sw_stream_base_msb : 32; + } swreg168; + + struct { + RK_U32 sw_stream_base_lsb : 32; + } swreg169; + + struct { + RK_U32 sw_prob_tab_out_base_msb : 32; + } swreg170; + + struct { + RK_U32 sw_prob_tab_out_base_lsb : 32; + } swreg171; + + struct { + RK_U32 sw_prob_tab_base_msb : 32; + } swreg172; + + struct { + RK_U32 sw_prob_tab_base_lsb : 32; + } swreg173; + + struct { + RK_U32 sw_mc_sync_curr_base_msb : 32; + } swreg174; + + struct { + RK_U32 sw_mc_sync_curr_base_lsb : 32; + } swreg175; + + struct { + RK_U32 sw_mc_sync_left_base_msb : 32; + } swreg176; + + struct { + RK_U32 sw_mc_sync_left_base_lsb : 32; + } swreg177; + + struct { + RK_U32 sw_dec_vert_filt_base_msb : 32; + } swreg178; + + struct { + RK_U32 sw_dec_vert_filt_base_lsb : 32; + } swreg179; + + RK_U32 reserved_180_181[2]; + struct { + RK_U32 sw_dec_bsd_ctrl_base_msb : 32; + } swreg182; + + struct { + RK_U32 sw_dec_bsd_ctrl_base_lsb : 32; + } swreg183; +} VdpuAv1dBase; + +/* swreg320 - swreg511 */ +typedef struct VdpuAv1dPPCfg_t { + + struct { + RK_U32 sw_pp_out_e : 1; + RK_U32 sw_pp_cr_first : 1; + RK_U32 sw_pp_out_mode : 1; + RK_U32 sw_pp_out_tile_e : 1; + RK_U32 sw_pp_status : 4; + RK_U32 sw_pp_in_blk_size : 3; + RK_U32 sw_pp_out_p010_fmt : 2; + RK_U32 sw_pp_out_rgb_fmt : 5; + RK_U32 sw_rgb_range_max : 12; + RK_U32 sw_pp_rgb_planar : 1; + RK_U32 reserved0 : 1; + } swreg320; + + struct { + RK_U32 sw_rgb_range_min : 9; + RK_U32 sw_pp_tile_size : 2; + RK_U32 reserved0 : 5; + RK_U32 sw_pp_in_swap : 4; + RK_U32 sw_pp_out_swap : 4; + RK_U32 sw_pp_in_a1_swap : 4; + RK_U32 sw_pp_in_a2_swap : 4; + } swreg321; + + struct { + RK_U32 sw_scale_hratio : 18; + RK_U32 sw_pp_out_format : 5; + RK_U32 sw_ver_scale_mode : 2; + RK_U32 sw_hor_scale_mode : 2; + RK_U32 sw_pp_in_format : 5; + } swreg322; + + struct { + RK_U32 sw_scale_wratio : 18; + RK_U32 sw_rangemap_coef_c : 5; + RK_U32 sw_rangemap_coef_y : 5; + RK_U32 sw_pp_vc1_adv_e : 1; + RK_U32 sw_ycbcr_range : 1; + RK_U32 sw_rangemap_c_e : 1; + RK_U32 sw_rangemap_y_e : 1; + } swreg323; + + struct { + RK_U32 sw_hscale_invra : 16; + RK_U32 sw_wscale_invra : 16; + } swreg324; + + struct { + RK_U32 sw_pp_out_lu_base_msb : 32; + } swreg325; + + struct { + RK_U32 sw_pp_out_lu_base_lsb : 32; + } swreg326; + + struct { + RK_U32 sw_pp_out_ch_base_msb : 32; + } swreg327; + + struct { + RK_U32 sw_pp_out_ch_base_lsb : 32; + } swreg328; + + struct { + RK_U32 sw_pp_out_c_stride : 16; + RK_U32 sw_pp_out_y_stride : 16; + } swreg329; + + struct { + RK_U32 sw_crop_starty : 13; + RK_U32 sw_rotation_mode : 2; + RK_U32 reserved0 : 1; + RK_U32 sw_crop_startx : 13; + RK_U32 sw_flip_mode : 2; + RK_U32 sw_pad_sel : 1; + } swreg330; + + struct { + RK_U32 sw_pp_in_height : 16; + RK_U32 sw_pp_in_width : 16; + } swreg331; + + struct { + RK_U32 sw_pp_out_height : 16; + RK_U32 sw_pp_out_width : 16; + } swreg332; + + struct { + RK_U32 sw_pp_out_lu_bot_base_msb : 32; + } swreg333; + + struct { + RK_U32 sw_pp_out_lu_bot_base_lsb : 32; + } swreg334; + + struct { + RK_U32 sw_pp_crop2_starty : 13; + RK_U32 reserved0 : 3; + RK_U32 sw_pp_crop2_startx : 13; + RK_U32 reserved1 : 3; + // RK_U32 sw_pp_out_ch_bot_base_msb : 32; + } swreg335; + + struct { + RK_U32 sw_pp_crop2_out_height : 16; + RK_U32 sw_pp_crop2_out_width : 16; + // RK_U32 sw_pp_out_ch_bot_base_lsb : 32; + } swreg336; + + struct { + RK_U32 sw_pp_in_c_stride : 16; + RK_U32 sw_pp_in_y_stride : 16; + } swreg337; + + struct { + RK_U32 sw_pp_in_lu_base_msb : 32; + } swreg338; + + struct { + RK_U32 sw_pp_in_lu_base_lsb : 32; + } swreg339; + + struct { + RK_U32 sw_pp_in_ch_base_msb : 32; + } swreg340; + + struct { + RK_U32 sw_pp_in_ch_base_lsb : 32; + } swreg341; + + struct { + RK_U32 sw_pp1_out_e : 1; + RK_U32 sw_pp1_cr_first : 1; + RK_U32 sw_pp1_out_mode : 1; + RK_U32 sw_pp1_out_tile_e : 1; + RK_U32 reserved0 : 7; + RK_U32 sw_pp1_out_p010_fmt : 2; + RK_U32 sw_pp1_out_rgb_fmt : 5; + RK_U32 reserved1 : 12; + RK_U32 sw_pp1_rgb_planar : 1; + RK_U32 reserved2 : 1; + } swreg342; + + struct { + RK_U32 reserved0 : 9; + RK_U32 sw_pp1_tile_size : 2; + RK_U32 reserved1 : 9; + RK_U32 sw_pp1_out_swap : 4; + RK_U32 reserved2 : 8; + } swreg343; + + struct { + RK_U32 sw_pp1_scale_hratio : 18; + RK_U32 sw_pp1_out_format : 5; + RK_U32 sw_pp1_ver_scale_mode : 2; + RK_U32 sw_pp1_hor_scale_mode : 2; + RK_U32 reserved0 : 5; + } swreg344; + + struct { + RK_U32 sw_pp1_scale_wratio : 18; + RK_U32 reserved0 : 14; + } swreg345; + + struct { + RK_U32 sw_pp1_hscale_invra : 16; + RK_U32 sw_pp1_wscale_invra : 16; + } swreg346; + + struct { + RK_U32 sw_pp1_out_lu_base_msb : 32; + } swreg347; + + struct { + RK_U32 sw_pp1_out_lu_base_lsb : 32; + } swreg348; + + struct { + RK_U32 sw_pp1_out_ch_base_msb : 32; + } swreg349; + + struct { + RK_U32 sw_pp1_out_ch_base_lsb : 32; + } swreg350; + + struct { + RK_U32 sw_pp1_out_c_stride : 16; + RK_U32 sw_pp1_out_y_stride : 16; + } swreg351; + + struct { + RK_U32 sw_pp1_crop_starty : 13; + RK_U32 sw_pp1_rotation_mode : 2; + RK_U32 reserved0 : 1; + RK_U32 sw_pp1_crop_startx : 13; + RK_U32 sw_pp1_flip_mode : 2; + RK_U32 sw_pp1_pad_sel : 1; + } swreg352; + + struct { + RK_U32 sw_pp1_in_height : 16; + RK_U32 sw_pp1_in_width : 16; + } swreg353; + + struct { + RK_U32 sw_pp1_out_height : 16; + RK_U32 sw_pp1_out_width : 16; + } swreg354; + + struct { + RK_U32 sw_pp1_out_lu_bot_base_msb : 32; + } swreg355; + + struct { + RK_U32 sw_pp1_out_lu_bot_base_lsb : 32; + } swreg356; + + struct { + RK_U32 sw_pp1_crop2_starty : 13; + RK_U32 reserved0 : 3; + RK_U32 sw_pp1_crop2_startx : 13; + RK_U32 reserved1 : 3; + // RK_U32 sw_pp1_out_ch_bot_base_msb : 32; + } swreg357; + + struct { + RK_U32 sw_pp1_crop2_out_height : 16; + RK_U32 sw_pp1_crop2_out_width : 16; + // RK_U32 sw_pp1_out_ch_bot_base_lsb : 32; + } swreg358; + + struct { + RK_U32 sw_pp2_out_e : 1; + RK_U32 sw_pp2_cr_first : 1; + RK_U32 sw_pp2_out_mode : 1; + RK_U32 sw_pp2_out_tile_e : 1; + RK_U32 reserved0 : 7; + RK_U32 sw_pp2_out_p010_fmt : 2; + RK_U32 sw_pp2_out_rgb_fmt : 5; + RK_U32 reserved1 : 12; + RK_U32 sw_pp2_rgb_planar : 1; + RK_U32 reserved2 : 1; + } swreg359; + + struct { + RK_U32 reserved0 : 9; + RK_U32 sw_pp2_tile_size : 2; + RK_U32 reserved1 : 9; + RK_U32 sw_pp2_out_swap : 4; + RK_U32 reserved2 : 8; + } swreg360; + + struct { + RK_U32 sw_pp2_scale_hratio : 18; + RK_U32 sw_pp2_out_format : 5; + RK_U32 sw_pp2_ver_scale_mode : 2; + RK_U32 sw_pp2_hor_scale_mode : 2; + RK_U32 reserved0 : 5; + } swreg361; + + struct { + RK_U32 sw_pp2_scale_wratio : 18; + RK_U32 reserved0 : 5; + RK_U32 reserved1 : 5; + RK_U32 reserved2 : 1; + RK_U32 reserved4 : 1; + RK_U32 reserved3 : 1; + RK_U32 reserved5 : 1; + } swreg362; + + struct { + RK_U32 sw_pp2_hscale_invra : 16; + RK_U32 sw_pp2_wscale_invra : 16; + } swreg363; + + struct { + RK_U32 sw_pp2_out_lu_base_msb : 32; + } swreg364; + + struct { + RK_U32 sw_pp2_out_lu_base_lsb : 32; + } swreg365; + + struct { + RK_U32 sw_pp2_out_ch_base_msb : 32; + } swreg366; + + struct { + RK_U32 sw_pp2_out_ch_base_lsb : 32; + } swreg367; + + struct { + RK_U32 sw_pp2_out_c_stride : 16; + RK_U32 sw_pp2_out_y_stride : 16; + } swreg368; + + struct { + RK_U32 sw_pp2_crop_starty : 13; + RK_U32 sw_pp2_rotation_mode : 2; + RK_U32 reserved0 : 1; + RK_U32 sw_pp2_crop_startx : 13; + RK_U32 sw_pp2_flip_mode : 2; + RK_U32 sw_pp2_pad_sel : 1; + } swreg369; + + struct { + RK_U32 sw_pp2_in_height : 16; + RK_U32 sw_pp2_in_width : 16; + } swreg370; + + struct { + RK_U32 sw_pp2_out_height : 16; + RK_U32 sw_pp2_out_width : 16; + } swreg371; + + struct { + // RK_U32 sw_pp2_out_b_base_msb : 32; + RK_U32 sw_pp2_out_lu_bot_base_msb : 32; + } swreg372; + + struct { + // RK_U32 sw_pp2_out_b_base_lsb : 32; + RK_U32 sw_pp2_out_lu_bot_base_lsb : 32; + } swreg373; + + struct { + RK_U32 sw_pp2_crop2_starty : 13; + RK_U32 reserved0 : 3; + RK_U32 sw_pp2_crop2_startx : 13; + RK_U32 reserved1 : 3; + // RK_U32 sw_pp2_out_ch_bot_base_msb : 32; + } swreg374; + + struct { + RK_U32 sw_pp2_crop2_out_height : 16; + RK_U32 sw_pp2_crop2_out_width : 16; + // RK_U32 sw_pp2_out_ch_bot_base_lsb : 32; + } swreg375; + + struct { + RK_U32 sw_pp3_out_e : 1; + RK_U32 sw_pp3_cr_first : 1; + RK_U32 sw_pp3_out_mode : 1; + RK_U32 sw_pp3_out_tile_e : 1; + RK_U32 reserved0 : 7; + RK_U32 sw_pp3_out_p010_fmt : 2; + RK_U32 sw_pp3_out_rgb_fmt : 5; + RK_U32 reserved1 : 12; + RK_U32 sw_pp3_rgb_planar : 1; + RK_U32 reserved2 : 1; + } swreg376; + + struct { + RK_U32 reserved0 : 9; + RK_U32 sw_pp3_tile_size : 2; + RK_U32 reserved1 : 9; + RK_U32 sw_pp3_out_swap : 4; + RK_U32 reserved2 : 8; + } swreg377; + + struct { + RK_U32 sw_pp3_scale_hratio : 18; + RK_U32 sw_pp3_out_format : 5; + RK_U32 sw_pp3_ver_scale_mode : 2; + RK_U32 sw_pp3_hor_scale_mode : 2; + RK_U32 reserved0 : 5; + } swreg378; + + struct { + RK_U32 sw_pp3_scale_wratio : 18; + RK_U32 reserved0 : 5; + RK_U32 reserved1 : 5; + RK_U32 reserved2 : 1; + RK_U32 reserved4 : 1; + RK_U32 reserved3 : 1; + RK_U32 reserved5 : 1; + } swreg379; + + struct { + RK_U32 sw_pp3_hscale_invra : 16; + RK_U32 sw_pp3_wscale_invra : 16; + } swreg380; + + struct { + // RK_U32 sw_pp3_out_r_base_msb : 32; + RK_U32 sw_pp3_out_lu_base_msb : 32; + } swreg381; + + struct { + // RK_U32 sw_pp3_out_r_base_lsb : 32; + RK_U32 sw_pp3_out_lu_base_lsb : 32; + } swreg382; + + struct { + // RK_U32 sw_pp3_out_g_base_msb : 32; + RK_U32 sw_pp3_out_ch_base_msb : 32; + } swreg383; + + struct { + // RK_U32 sw_pp3_out_g_base_lsb : 32; + RK_U32 sw_pp3_out_ch_base_lsb : 32; + } swreg384; + + struct { + RK_U32 sw_pp3_out_c_stride : 16; + RK_U32 sw_pp3_out_y_stride : 16; + } swreg385; + + struct { + RK_U32 sw_pp3_crop_starty : 13; + RK_U32 sw_pp3_rotation_mode : 2; + RK_U32 reserved0 : 1; + RK_U32 sw_pp3_crop_startx : 13; + RK_U32 sw_pp3_flip_mode : 2; + RK_U32 sw_pp3_pad_sel : 1; + } swreg386; + + struct { + RK_U32 sw_pp3_in_height : 16; + RK_U32 sw_pp3_in_width : 16; + } swreg387; + + struct { + RK_U32 sw_pp3_out_height : 16; + RK_U32 sw_pp3_out_width : 16; + } swreg388; + + struct { + // RK_U32 sw_pp3_out_b_base_msb : 32; + RK_U32 sw_pp3_out_lu_bot_base_msb : 32; + } swreg389; + + struct { + // RK_U32 sw_pp3_out_b_base_lsb : 32; + RK_U32 sw_pp3_out_lu_bot_base_lsb : 32; + } swreg390; + + struct { + RK_U32 sw_pp3_crop2_starty : 13; + RK_U32 reserved0 : 3; + RK_U32 sw_pp3_crop2_startx : 13; + RK_U32 reserved1 : 3; + // RK_U32 sw_pp3_out_ch_bot_base_msb : 32; + } swreg391; + + struct { + RK_U32 sw_pp3_crop2_out_height : 16; + RK_U32 sw_pp3_crop2_out_width : 16; + // RK_U32 sw_pp3_out_ch_bot_base_lsb : 32; + } swreg392; + + struct { + RK_U32 sw_pp3_out_alpha : 8; + RK_U32 sw_pp2_out_alpha : 8; + RK_U32 sw_pp1_out_alpha : 8; + RK_U32 sw_pp0_out_alpha : 8; + } swreg393; + + struct { + RK_U32 sw_pp1_dup_ver : 8; + RK_U32 sw_pp1_dup_hor : 8; + RK_U32 sw_pp0_dup_ver : 8; + RK_U32 sw_pp0_dup_hor : 8; + } swreg394; + + struct { + RK_U32 sw_pp3_dup_ver : 8; + RK_U32 sw_pp3_dup_hor : 8; + RK_U32 sw_pp2_dup_ver : 8; + RK_U32 sw_pp2_dup_hor : 8; + } swreg395; + + struct { + RK_U32 sw_pp0_scale1_out_height : 16; + RK_U32 sw_pp0_scale1_out_width : 16; + } swreg396; + + struct { + RK_U32 sw_pp1_scale1_out_height : 16; + RK_U32 sw_pp1_scale1_out_width : 16; + } swreg397; + + struct { + RK_U32 sw_pp2_scale1_out_height : 16; + RK_U32 sw_pp2_scale1_out_width : 16; + } swreg398; + + struct { + RK_U32 sw_pp3_scale1_out_height : 16; + RK_U32 sw_pp3_scale1_out_width : 16; + } swreg399; + + struct { + RK_U32 sw_dec_in_pool_base_msb : 32; + } swreg400; + + struct { + RK_U32 sw_dec_in_pool_base_lsb : 32; + } swreg401; + + struct { + RK_U32 sw_dec_in_bufpool_size : 32; + } swreg402; + + struct { + RK_U32 sw_dec_out_pool_base_msb : 32; + } swreg403; + + struct { + RK_U32 sw_dec_out_pool_base_lsb : 32; + } swreg404; + + struct { + RK_U32 sw_dec_out_bufpool_size : 32; + } swreg405; + + struct { + RK_U32 sw_dec_priv_pool_base_msb : 32; + } swreg406; + + struct { + RK_U32 sw_dec_priv_pool_base_lsb : 32; + } swreg407; + + struct { + RK_U32 sw_dec_priv_pool_size : 32; + } swreg408; + + struct { + RK_U32 sw_dec_in_nsa_id : 4; + RK_U32 sw_dec_out_nsa_id : 4; + RK_U32 sw_dec_priv_nsa_id : 4; + RK_U32 sw_dec_pub_nsa_id : 4; + RK_U32 reserved0 : 16; + } swreg409; + + struct { + RK_U32 sw_contrast_off1 : 12; + RK_U32 sw_contrast_off2 : 12; + RK_U32 reserved0 : 2; + RK_U32 sw_dither_select_b : 2; + RK_U32 sw_dither_select_g : 2; + RK_U32 sw_dither_select_r : 2; + } swreg410; + + struct { + RK_U32 sw_color_coefff : 10; + RK_U32 sw_contrast_thr2 : 10; + RK_U32 sw_contrast_thr1 : 10; + RK_U32 reserved0 : 2; + } swreg411; + + struct { + RK_U32 sw_color_coeffa1 : 16; + RK_U32 sw_color_coeffa2 : 16; + } swreg412; + + struct { + RK_U32 sw_color_coeffb : 16; + RK_U32 sw_color_coeffc : 16; + } swreg413; + + struct { + RK_U32 sw_color_coeffd : 16; + RK_U32 sw_color_coeffe : 16; + } swreg414; + + struct { + RK_U32 sw_pp1_contrast_off1 : 12; + RK_U32 sw_pp1_contrast_off2 : 12; + RK_U32 reserved0 : 2; + RK_U32 sw_pp1_dither_select_b : 2; + RK_U32 sw_pp1_dither_select_g : 2; + RK_U32 sw_pp1_dither_select_r : 2; + } swreg415; + + struct { + RK_U32 sw_pp1_color_coefff : 10; + RK_U32 sw_pp1_contrast_thr2 : 10; + RK_U32 sw_pp1_contrast_thr1 : 10; + RK_U32 reserved0 : 2; + } swreg416; + + struct { + RK_U32 sw_pp1_color_coeffa1 : 16; + RK_U32 sw_pp1_color_coeffa2 : 16; + } swreg417; + + struct { + RK_U32 sw_pp1_color_coeffb : 16; + RK_U32 sw_pp1_color_coeffc : 16; + } swreg418; + + struct { + RK_U32 sw_pp1_color_coeffd : 16; + RK_U32 sw_pp1_color_coeffe : 16; + } swreg419; + + struct { + RK_U32 sw_pp2_contrast_off1 : 12; + RK_U32 sw_pp2_contrast_off2 : 12; + RK_U32 reserved0 : 2; + RK_U32 sw_pp2_dither_select_b : 2; + RK_U32 sw_pp2_dither_select_g : 2; + RK_U32 sw_pp2_dither_select_r : 2; + } swreg420; + + struct { + RK_U32 sw_pp2_color_coefff : 10; + RK_U32 sw_pp2_contrast_thr2 : 10; + RK_U32 sw_pp2_contrast_thr1 : 10; + RK_U32 reserved0 : 2; + } swreg421; + + struct { + RK_U32 sw_pp2_color_coeffa1 : 16; + RK_U32 sw_pp2_color_coeffa2 : 16; + } swreg422; + + struct { + RK_U32 sw_pp2_color_coeffb : 16; + RK_U32 sw_pp2_color_coeffc : 16; + } swreg423; + + struct { + RK_U32 sw_pp2_color_coeffd : 16; + RK_U32 sw_pp2_color_coeffe : 16; + } swreg424; + + struct { + RK_U32 sw_pp3_contrast_off1 : 12; + RK_U32 sw_pp3_contrast_off2 : 12; + RK_U32 reserved0 : 2; + RK_U32 sw_pp3_dither_select_b : 2; + RK_U32 sw_pp3_dither_select_g : 2; + RK_U32 sw_pp3_dither_select_r : 2; + } swreg425; + + struct { + RK_U32 sw_pp3_color_coefff : 10; + RK_U32 sw_pp3_contrast_thr2 : 10; + RK_U32 sw_pp3_contrast_thr1 : 10; + RK_U32 reserved0 : 2; + } swreg426; + + struct { + RK_U32 sw_pp3_color_coeffa1 : 16; + RK_U32 sw_pp3_color_coeffa2 : 16; + } swreg427; + + struct { + RK_U32 sw_pp3_color_coeffb : 16; + RK_U32 sw_pp3_color_coeffc : 16; + } swreg428; + + struct { + RK_U32 sw_pp3_color_coeffd : 16; + RK_U32 sw_pp3_color_coeffe : 16; + } swreg429; + + struct { + RK_U32 sw_delogo0_h : 10; + RK_U32 sw_delogo0_w : 10; + RK_U32 reserved0 : 8; + RK_U32 sw_delogo0_show_border : 1; + RK_U32 sw_delogo0_mode : 3; + } swreg430; + + struct { + RK_U32 sw_delogo0_y : 16; + RK_U32 sw_delogo0_x : 16; + } swreg431; + + struct { + RK_U32 sw_delogo0_fillV : 10; + RK_U32 sw_delogo0_fillU : 10; + RK_U32 sw_delogo0_fillY : 10; + RK_U32 reserved0 : 2; + } swreg432; + + struct { + RK_U32 sw_delogo1_h : 14; + RK_U32 sw_delogo1_w : 14; + RK_U32 sw_delogo1_show_border : 1; + RK_U32 sw_delogo1_mode : 3; + } swreg433; + + struct { + RK_U32 sw_delogo1_y : 16; + RK_U32 sw_delogo1_x : 16; + } swreg434; + + struct { + RK_U32 sw_delogo1_fillV : 10; + RK_U32 sw_delogo1_fillU : 10; + RK_U32 sw_delogo1_fillY : 10; + RK_U32 reserved0 : 2; + } swreg435; + + struct { + RK_U32 sw_delogo0_ratio_h : 16; + RK_U32 sw_delogo0_ratio_w : 16; + } swreg436; + + struct { + RK_U32 sw_pp1_hcale_invra_ext : 8; + RK_U32 sw_pp1_wscale_invra_ext : 8; + RK_U32 sw_pp0_hcale_invra_ext : 8; + RK_U32 sw_pp0_wscale_invra_ext : 8; + } swreg437; + + struct { + RK_U32 sw_pp0_x_filter_size : 12; + RK_U32 sw_pp0_y_filter_size : 12; + RK_U32 reserved0 : 8; + } swreg438; + + struct { + RK_U32 sw_pp0_lanczos_tbl_base_msb : 32; + } swreg439; + + struct { + RK_U32 sw_pp0_lanczos_tbl_base_lsb : 32; + } swreg440; + + struct { + RK_U32 sw_pp1_x_filter_size : 12; + RK_U32 sw_pp1_y_filter_size : 12; + RK_U32 reserved0 : 8; + } swreg441; + + struct { + RK_U32 sw_pp1_lanczos_tbl_base_msb : 32; + } swreg442; + + struct { + RK_U32 sw_pp1_lanczos_tbl_base_lsb : 32; + } swreg443; + + struct { + RK_U32 sw_pp3_hcale_invra_ext : 8; + RK_U32 sw_pp3_wscale_invra_ext : 8; + RK_U32 sw_pp2_hcale_invra_ext : 8; + RK_U32 sw_pp2_wscale_invra_ext : 8; + } swreg444; + + struct { + RK_U32 sw_pp2_x_filter_size : 12; + RK_U32 sw_pp2_y_filter_size : 12; + RK_U32 reserved0 : 8; + } swreg445; + + struct { + RK_U32 sw_pp2_lanczos_tbl_base_msb : 32; + } swreg446; + + struct { + RK_U32 sw_pp2_lanczos_tbl_base_lsb : 32; + } swreg447; + + struct { + RK_U32 sw_pp3_x_filter_size : 12; + RK_U32 sw_pp3_y_filter_size : 12; + RK_U32 reserved0 : 8; + } swreg448; + + struct { + RK_U32 sw_pp3_lanczos_tbl_base_msb : 32; + } swreg449; + + struct { + RK_U32 sw_pp3_lanczos_tbl_base_lsb : 32; + } swreg450; + + struct { + RK_U32 sw_pp4_out_e : 1; + RK_U32 sw_pp4_cr_first : 1; + RK_U32 sw_pp4_out_mode : 1; + RK_U32 sw_pp4_out_tile_e : 1; + RK_U32 reserved0 : 7; + RK_U32 sw_pp4_out_p010_fmt : 2; + RK_U32 sw_pp4_out_rgb_fmt : 5; + RK_U32 reserved1 : 12; + RK_U32 sw_pp4_rgb_planar : 1; + RK_U32 reserved2 : 1; + } swreg451; + + struct { + RK_U32 reserved0 : 20; + RK_U32 sw_pp4_out_swap : 4; + RK_U32 reserved1 : 8; + } swreg452; + + struct { + RK_U32 sw_pp4_scale_hratio : 18; + RK_U32 sw_pp4_out_format : 5; + RK_U32 sw_pp4_ver_scale_mode : 2; + RK_U32 sw_pp4_hor_scale_mode : 2; + RK_U32 reserved0 : 5; + } swreg453; + + struct { + RK_U32 sw_pp4_scale_wratio : 18; + RK_U32 reserved0 : 5; + RK_U32 reserved1 : 5; + RK_U32 reserved2 : 1; + RK_U32 reserved4 : 1; + RK_U32 reserved3 : 1; + RK_U32 reserved5 : 1; + } swreg454; + + struct { + RK_U32 sw_pp4_hscale_invra : 16; + RK_U32 sw_pp4_wscale_invra : 16; + } swreg455; + + struct { + // RK_U32 sw_pp4_out_r_base_msb : 32; + RK_U32 sw_pp4_out_lu_base_msb : 32; + } swreg456; + + struct { + // RK_U32 sw_pp4_out_r_base_lsb : 32; + RK_U32 sw_pp4_out_lu_base_lsb : 32; + } swreg457; + + struct { + // RK_U32 sw_pp4_out_g_base_msb : 32; + RK_U32 sw_pp4_out_ch_base_msb : 32; + } swreg458; + + struct { + // RK_U32 sw_pp4_out_g_base_lsb : 32; + RK_U32 sw_pp4_out_ch_base_lsb : 32; + } swreg459; + + struct { + RK_U32 sw_pp4_out_c_stride : 16; + RK_U32 sw_pp4_out_y_stride : 16; + } swreg460; + + struct { + RK_U32 sw_pp4_crop_starty : 13; + RK_U32 sw_pp4_rotation_mode : 2; + RK_U32 reserved0 : 1; + RK_U32 sw_pp4_crop_startx : 13; + RK_U32 sw_pp4_flip_mode : 2; + RK_U32 sw_pp4_pad_sel : 1; + } swreg461; + + struct { + RK_U32 sw_pp4_in_height : 16; + RK_U32 sw_pp4_in_width : 16; + } swreg462; + + struct { + RK_U32 sw_pp4_out_height : 16; + RK_U32 sw_pp4_out_width : 16; + } swreg463; + + struct { + // RK_U32 sw_pp4_out_b_base_msb : 32; + RK_U32 sw_pp4_out_lu_bot_base_msb : 32; + } swreg464; + + struct { + // RK_U32 sw_pp4_out_b_base_lsb : 32; + RK_U32 sw_pp4_out_lu_bot_base_lsb : 32; + } swreg465; + + struct { + RK_U32 sw_pp4_crop2_starty : 13; + RK_U32 reserved0 : 3; + RK_U32 sw_pp4_crop2_startx : 13; + RK_U32 reserved1 : 3; + // RK_U32 sw_pp4_out_ch_bot_base_msb : 32; + } swreg466; + + struct { + RK_U32 sw_pp4_crop2_out_height : 16; + RK_U32 sw_pp4_crop2_out_width : 16; + // RK_U32 sw_pp4_out_ch_bot_base_lsb : 32; + } swreg467; + + struct { + RK_U32 sw_pp4_contrast_off1 : 12; + RK_U32 sw_pp4_contrast_off2 : 12; + RK_U32 reserved0 : 2; + RK_U32 sw_pp4_dither_select_b : 2; + RK_U32 sw_pp4_dither_select_g : 2; + RK_U32 sw_pp4_dither_select_r : 2; + } swreg468; + + struct { + RK_U32 sw_pp4_color_coefff : 10; + RK_U32 sw_pp4_contrast_thr2 : 10; + RK_U32 sw_pp4_contrast_thr1 : 10; + RK_U32 reserved0 : 2; + } swreg469; + + struct { + RK_U32 sw_pp4_color_coeffa1 : 16; + RK_U32 sw_pp4_color_coeffa2 : 16; + } swreg470; + + struct { + RK_U32 sw_pp4_color_coeffb : 16; + RK_U32 sw_pp4_color_coeffc : 16; + } swreg471; + + struct { + RK_U32 sw_pp4_color_coeffd : 16; + RK_U32 sw_pp4_color_coeffe : 16; + } swreg472; + + struct { + RK_U32 sw_pp4_out_alpha : 8; + RK_U32 sw_pp4_dup_hor : 8; + RK_U32 sw_pp4_hcale_invra_ext : 8; + RK_U32 sw_pp4_wscale_invra_ext : 8; + } swreg473; + + struct { + RK_U32 sw_pp4_x_filter_size : 12; + RK_U32 sw_pp4_y_filter_size : 12; + RK_U32 reserved0 : 8; + } swreg474; + + struct { + RK_U32 sw_pp4_lanczos_tbl_base_msb : 32; + } swreg475; + + struct { + RK_U32 sw_pp4_lanczos_tbl_base_lsb : 32; + } swreg476; + + struct { + RK_U32 sw_pp5_out_e : 1; + RK_U32 sw_pp5_cr_first : 1; + RK_U32 sw_pp5_out_mode : 1; + RK_U32 sw_pp5_out_tile_e : 1; + RK_U32 reserved0 : 7; + RK_U32 sw_pp5_out_p010_fmt : 2; + RK_U32 sw_pp5_out_rgb_fmt : 5; + RK_U32 reserved1 : 12; + RK_U32 sw_pp5_rgb_planar : 1; + RK_U32 reserved2 : 1; + } swreg477; + + struct { + RK_U32 reserved0 : 20; + RK_U32 sw_pp5_out_swap : 4; + RK_U32 reserved1 : 8; + } swreg478; + + struct { + RK_U32 sw_pp5_scale_hratio : 18; + RK_U32 sw_pp5_out_format : 5; + RK_U32 sw_pp5_ver_scale_mode : 2; + RK_U32 sw_pp5_hor_scale_mode : 2; + RK_U32 reserved0 : 5; + } swreg479; + + struct { + RK_U32 sw_pp5_scale_wratio : 18; + RK_U32 reserved0 : 5; + RK_U32 reserved1 : 5; + RK_U32 reserved2 : 1; + RK_U32 reserved4 : 1; + RK_U32 reserved3 : 1; + RK_U32 reserved5 : 1; + } swreg480; + + struct { + RK_U32 sw_pp5_hscale_invra : 16; + RK_U32 sw_pp5_wscale_invra : 16; + } swreg481; + + struct { + // RK_U32 sw_pp5_out_r_base_msb : 32; + RK_U32 sw_pp5_out_lu_base_msb : 32; + } swreg482; + + struct { + // RK_U32 sw_pp5_out_r_base_lsb : 32; + RK_U32 sw_pp5_out_lu_base_lsb : 32; + } swreg483; + + struct { + // RK_U32 sw_pp5_out_g_base_msb : 32; + RK_U32 sw_pp5_out_ch_base_msb : 32; + } swreg484; + + struct { + // RK_U32 sw_pp5_out_g_base_lsb : 32; + RK_U32 sw_pp5_out_ch_base_lsb : 32; + } swreg485; + + struct { + RK_U32 sw_pp5_out_c_stride : 16; + RK_U32 sw_pp5_out_y_stride : 16; + } swreg486; + + struct { + RK_U32 sw_pp5_crop_starty : 13; + RK_U32 sw_pp5_rotation_mode : 2; + RK_U32 reserved0 : 1; + RK_U32 sw_pp5_crop_startx : 13; + RK_U32 sw_pp5_flip_mode : 2; + RK_U32 sw_pp5_pad_sel : 1; + } swreg487; + + struct { + RK_U32 sw_pp5_in_height : 16; + RK_U32 sw_pp5_in_width : 16; + } swreg488; + + struct { + RK_U32 sw_pp5_out_height : 16; + RK_U32 sw_pp5_out_width : 16; + } swreg489; + + struct { + // RK_U32 sw_pp5_out_b_base_msb : 32; + RK_U32 sw_pp5_out_lu_bot_base_msb : 32; + } swreg490; + + struct { + // RK_U32 sw_pp5_out_b_base_lsb : 32; + RK_U32 sw_pp5_out_lu_bot_base_lsb : 32; + } swreg491; + + struct { + RK_U32 sw_pp5_crop2_starty : 13; + RK_U32 reserved0 : 3; + RK_U32 sw_pp5_crop2_startx : 13; + RK_U32 reserved1 : 3; + // RK_U32 sw_pp5_out_ch_bot_base_msb : 32; + } swreg492; + + struct { + RK_U32 sw_pp5_crop2_out_height : 16; + RK_U32 sw_pp5_crop2_out_width : 16; + // RK_U32 sw_pp5_out_ch_bot_base_lsb : 32; + } swreg493; + + struct { + RK_U32 sw_pp5_contrast_off1 : 12; + RK_U32 sw_pp5_contrast_off2 : 12; + RK_U32 reserved0 : 2; + RK_U32 sw_pp5_dither_select_b : 2; + RK_U32 sw_pp5_dither_select_g : 2; + RK_U32 sw_pp5_dither_select_r : 2; + } swreg494; + + struct { + RK_U32 sw_pp5_color_coefff : 10; + RK_U32 sw_pp5_contrast_thr2 : 10; + RK_U32 sw_pp5_contrast_thr1 : 10; + RK_U32 reserved0 : 2; + } swreg495; + + struct { + RK_U32 sw_pp5_color_coeffa1 : 16; + RK_U32 sw_pp5_color_coeffa2 : 16; + } swreg496; + + struct { + RK_U32 sw_pp5_color_coeffb : 16; + RK_U32 sw_pp5_color_coeffc : 16; + } swreg497; + + struct { + RK_U32 sw_pp5_color_coeffd : 16; + RK_U32 sw_pp5_color_coeffe : 16; + } swreg498; + + struct { + RK_U32 sw_pp5_out_alpha : 8; + RK_U32 sw_pp5_dup_hor : 8; + RK_U32 sw_pp5_hcale_invra_ext : 8; + RK_U32 sw_pp5_wscale_invra_ext : 8; + } swreg499; + + struct { + RK_U32 sw_pp5_x_filter_size : 12; + RK_U32 sw_pp5_y_filter_size : 12; + RK_U32 reserved0 : 8; + } swreg500; + + struct { + RK_U32 sw_pp5_lanczos_tbl_base_msb : 32; + } swreg501; + + struct { + RK_U32 sw_pp5_lanczos_tbl_base_lsb : 32; + } swreg502; + + struct { + RK_U32 sw_pp1_virtual_top : 4; + RK_U32 sw_pp1_virtual_left : 4; + RK_U32 sw_pp1_virtual_bottom : 4; + RK_U32 sw_pp1_virtual_right : 4; + RK_U32 sw_pp0_virtual_top : 4; + RK_U32 sw_pp0_virtual_left : 4; + RK_U32 sw_pp0_virtual_bottom : 4; + RK_U32 sw_pp0_virtual_right : 4; + } swreg503; + + struct { + RK_U32 sw_pp0_afbc_tile_base_msb : 32; + } swreg504; + + struct { + RK_U32 sw_pp0_afbc_tile_base_lsb : 32; + } swreg505; + + struct { + RK_U32 sw_pp1_afbc_tile_base_msb : 32; + } swreg506; + + struct { + RK_U32 sw_pp1_afbc_tile_base_lsb : 32; + } swreg507; + + struct { + RK_U32 sw_pp0_padV : 10; + RK_U32 sw_pp0_padU : 10; + RK_U32 sw_pp0_padY : 10; + RK_U32 sw_pp0_src_sel_mode : 2; + } swreg508; + + struct { + RK_U32 sw_pp1_padV : 10; + RK_U32 sw_pp1_padU : 10; + RK_U32 sw_pp1_padY : 10; + RK_U32 sw_pp1_src_sel_mode : 2; + } swreg509; + + struct { + RK_U32 sw_pp2_padV : 10; + RK_U32 sw_pp2_padU : 10; + RK_U32 sw_pp2_padY : 10; + RK_U32 sw_pp2_src_sel_mode : 2; + } swreg510; + + struct { + RK_U32 sw_pp3_padV : 10; + RK_U32 sw_pp3_padU : 10; + RK_U32 sw_pp3_padY : 10; + RK_U32 sw_pp3_src_sel_mode : 2; + } swreg511; + +} VdpuAv1dPPCfg; + +typedef struct VdpuAv1dRegSet_t { + struct { + RK_U32 reserved0 : 4; + RK_U32 reserved1 : 8; + RK_U32 reserved2 : 4; + RK_U32 reserved3 : 4; + RK_U32 reserved4 : 12; + } swreg0; + + struct { + RK_U32 sw_dec_e : 1; + RK_U32 reserved0 : 1; + RK_U32 sw_dec_bus_int_dis : 1; + RK_U32 sw_dec_timeout_source : 1; + + RK_U32 sw_dec_irq_dis : 1; + RK_U32 sw_dec_abort_e : 1; + RK_U32 sw_dec_self_reset_dis : 1; + RK_U32 sw_dec_tile_int_e : 1; + + RK_U32 sw_dec_irq : 1; + RK_U32 reserved1 : 2; + RK_U32 sw_dec_abort_int : 1; + + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 reserved2 : 1; + + RK_U32 sw_dec_error_int : 1; + RK_U32 reserved3 : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserved4 : 2; + RK_U32 sw_dec_ext_timeout_int : 1; + RK_U32 reserved5 : 1; + RK_U32 sw_dec_tile_int : 1; + + RK_U32 reserved6 : 8; + } swreg1; + + struct { + RK_U32 reserved0 : 4; + RK_U32 sw_drm_e : 1; + RK_U32 reserved1 : 5; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 reserved2 : 1; + + RK_U32 sw_dec_tab_swap : 4; + RK_U32 reserved3 : 4; + RK_U32 sw_dec_dirmv_swap : 4; + RK_U32 sw_dec_pic_swap : 4; + RK_U32 sw_dec_strm_swap : 4; + } swreg2; + + struct { + RK_U32 reserved0 : 8; + RK_U32 sw_dec_out_ec_bypass : 1; + RK_U32 reserved1 : 3; + RK_U32 sw_write_mvs_e : 1; + RK_U32 reserved2 : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 sw_dec_out_ec_byte_word : 1; + RK_U32 reserved3 : 9; + RK_U32 sw_skip_mode : 1; + RK_U32 sw_dec_mode : 5; + } swreg3; + + struct { + RK_U32 sw_ref_frames : 4; + RK_U32 reserved0 : 2; + RK_U32 sw_pic_height_in_cbs : 13; + RK_U32 sw_pic_width_in_cbs : 13; + } swreg4; + + struct { + RK_U32 sw_ref_scaling_enable : 1; + RK_U32 sw_filt_level_base_gt32 : 1; + RK_U32 sw_error_resilient : 1; + RK_U32 sw_force_interger_mv : 1; + + RK_U32 sw_allow_intrabc : 1; + RK_U32 sw_allow_screen_content_tools : 1; + RK_U32 sw_reduced_tx_set_used : 1; + RK_U32 sw_enable_dual_filter : 1; + + RK_U32 sw_enable_jnt_comp : 1; + RK_U32 sw_allow_filter_intra : 1; + RK_U32 sw_enable_intra_edge_filter : 1; + RK_U32 sw_tempor_mvp_e : 1;//RK_U32 reserved0 : 1; + + RK_U32 sw_allow_interintra : 1; + RK_U32 sw_allow_masked_compound : 1; + RK_U32 sw_enable_cdef : 1; + RK_U32 sw_switchable_motion_mode : 1; + + RK_U32 sw_show_frame : 1; + RK_U32 sw_superres_is_scaled : 1; + RK_U32 sw_allow_warp : 1; + RK_U32 sw_disable_cdf_update : 1; + + RK_U32 sw_preskip_segid : 1; + RK_U32 sw_delta_lf_present : 1; + RK_U32 sw_delta_lf_multi : 1; + RK_U32 sw_delta_lf_res_log : 2; + + // RK_U32 reserved1 : -14; + RK_U32 sw_strm_start_bit : 7; + } swreg5; + + struct { + RK_U32 sw_stream_len : 32; + } swreg6; + + struct { + RK_U32 sw_delta_q_present : 1; + RK_U32 sw_delta_q_res_log : 2; + RK_U32 sw_cdef_damping : 2; + RK_U32 sw_cdef_bits : 2; + RK_U32 sw_apply_grain : 1; + RK_U32 sw_num_y_points_b : 1; + RK_U32 sw_num_cb_points_b : 1; + RK_U32 sw_num_cr_points_b : 1; + RK_U32 sw_overlap_flag : 1; + RK_U32 sw_clip_to_restricted_range : 1; + RK_U32 sw_chroma_scaling_from_luma : 1; + RK_U32 sw_random_seed : 16; + RK_U32 sw_blackwhite_e : 1; + RK_U32 reserved0 : 1; + } swreg7; + + struct { + RK_U32 sw_scaling_shift : 4; + RK_U32 sw_bit_depth_c_minus8 : 2; + RK_U32 sw_bit_depth_y_minus8 : 2; + RK_U32 sw_quant_base_qindex : 8; + RK_U32 sw_idr_pic_e : 1; + RK_U32 sw_superres_pic_width : 15; + } swreg8; + + struct { + RK_U32 reserved0 : 2; + RK_U32 sw_ref4_sign_bias : 1; + RK_U32 sw_ref5_sign_bias : 1; + RK_U32 sw_ref6_sign_bias : 1; + RK_U32 sw_mf1_type : 3; + RK_U32 sw_mf2_type : 3; + RK_U32 sw_mf3_type : 3; + RK_U32 sw_scale_denom_minus9 : 3; + RK_U32 sw_last_active_seg : 3; + RK_U32 sw_context_update_tile_id : 12; + } swreg9; + + struct { + RK_U32 sw_tile_transpose : 1; + RK_U32 sw_tile_enable : 1; + RK_U32 sw_multicore_full_width : 8; + RK_U32 sw_num_tile_rows_8k_av1 : 7; + RK_U32 sw_num_tile_cols_8k : 7; + RK_U32 sw_multicore_tile_start_x : 8; + } swreg10; + + struct { + RK_U32 sw_use_temporal3_mvs : 1; + RK_U32 sw_use_temporal2_mvs : 1; + RK_U32 sw_use_temporal1_mvs : 1; + RK_U32 sw_use_temporal0_mvs : 1; + RK_U32 sw_comp_pred_mode : 2; + RK_U32 reserved0 : 1; + RK_U32 sw_high_prec_mv_e : 1; + RK_U32 sw_mcomp_filt_type : 3; + RK_U32 sw_multicore_expect_context_update : 1; + RK_U32 sw_multicore_sbx_offset : 7; + RK_U32 sw_multicore_tile_col : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_transform_mode : 3; + RK_U32 sw_dec_tile_size_mag : 2; + } swreg11; + + struct { + RK_U32 reserved0 : 2; + RK_U32 sw_seg_quant_sign : 8; + RK_U32 sw_max_cb_size : 3; + RK_U32 sw_min_cb_size : 3; + RK_U32 sw_av1_comp_pred_fixed_ref : 3; + RK_U32 sw_multicore_tile_width : 7; + RK_U32 sw_pic_height_pad : 3; + RK_U32 sw_pic_width_pad : 3; + } swreg12; + + struct { + RK_U32 sw_segment_e : 1; + RK_U32 sw_segment_upd_e : 1; + RK_U32 sw_segment_temp_upd_e : 1; + RK_U32 sw_comp_pred_var_ref0_av1 : 3; + RK_U32 sw_comp_pred_var_ref1_av1 : 3; + RK_U32 sw_lossless_e : 1; + RK_U32 reserved0 : 1; + RK_U32 sw_qp_delta_ch_ac_av1 : 7; + RK_U32 sw_qp_delta_ch_dc_av1 : 7; + RK_U32 sw_qp_delta_y_dc_av1 : 7; + } swreg13; + + struct { + RK_U32 sw_quant_seg0 : 8; + RK_U32 sw_filt_level_seg0 : 6; + RK_U32 sw_skip_seg0 : 1; + RK_U32 sw_refpic_seg0 : 4; + RK_U32 sw_filt_level_delta0_seg0 : 7; + RK_U32 sw_filt_level0 : 6; + } swreg14; + + struct { + RK_U32 sw_quant_seg1 : 8; + RK_U32 sw_filt_level_seg1 : 6; + RK_U32 sw_skip_seg1 : 1; + RK_U32 sw_refpic_seg1 : 4; + RK_U32 sw_filt_level_delta0_seg1 : 7; + RK_U32 sw_filt_level1 : 6; + } swreg15; + + struct { + RK_U32 sw_quant_seg2 : 8; + RK_U32 sw_filt_level_seg2 : 6; + RK_U32 sw_skip_seg2 : 1; + RK_U32 sw_refpic_seg2 : 4; + RK_U32 sw_filt_level_delta0_seg2 : 7; + RK_U32 sw_filt_level2 : 6; + } swreg16; + + struct { + RK_U32 sw_quant_seg3 : 8; + RK_U32 sw_filt_level_seg3 : 6; + RK_U32 sw_skip_seg3 : 1; + RK_U32 sw_refpic_seg3 : 4; + RK_U32 sw_filt_level_delta0_seg3 : 7; + RK_U32 sw_filt_level3 : 6; + } swreg17; + + struct { + RK_U32 sw_quant_seg4 : 8; + RK_U32 sw_filt_level_seg4 : 6; + RK_U32 sw_skip_seg4 : 1; + RK_U32 sw_refpic_seg4 : 4; + RK_U32 sw_filt_level_delta0_seg4 : 7; + RK_U32 sw_lr_type : 6; + } swreg18; + + struct { + RK_U32 sw_quant_seg5 : 8; + RK_U32 sw_filt_level_seg5 : 6; + RK_U32 sw_skip_seg5 : 1; + RK_U32 sw_refpic_seg5 : 4; + RK_U32 sw_filt_level_delta0_seg5 : 7; + RK_U32 sw_lr_unit_size : 6; + } swreg19; + + struct { + RK_U32 sw_filt_level_delta1_seg0 : 7; + RK_U32 sw_filt_level_delta2_seg0 : 7; + RK_U32 sw_filt_level_delta3_seg0 : 7; + RK_U32 sw_global_mv_seg0 : 1; + RK_U32 sw_mf1_last_offset : 9; + RK_U32 reserved0 : 1; + } swreg20; + + struct { + RK_U32 sw_filt_level_delta1_seg1 : 7; + RK_U32 sw_filt_level_delta2_seg1 : 7; + RK_U32 sw_filt_level_delta3_seg1 : 7; + RK_U32 sw_global_mv_seg1 : 1; + RK_U32 sw_mf1_last2_offset : 9; + RK_U32 reserved0 : 1; + } swreg21; + + struct { + RK_U32 sw_filt_level_delta1_seg2 : 7; + RK_U32 sw_filt_level_delta2_seg2 : 7; + RK_U32 sw_filt_level_delta3_seg2 : 7; + RK_U32 sw_global_mv_seg2 : 1; + RK_U32 sw_mf1_last3_offset : 9; + RK_U32 reserved0 : 1; + } swreg22; + + struct { + RK_U32 sw_filt_level_delta1_seg3 : 7; + RK_U32 sw_filt_level_delta2_seg3 : 7; + RK_U32 sw_filt_level_delta3_seg3 : 7; + RK_U32 sw_global_mv_seg3 : 1; + RK_U32 sw_mf1_golden_offset : 9; + RK_U32 reserved0 : 1; + } swreg23; + + struct { + RK_U32 sw_filt_level_delta1_seg4 : 7; + RK_U32 sw_filt_level_delta2_seg4 : 7; + RK_U32 sw_filt_level_delta3_seg4 : 7; + RK_U32 sw_global_mv_seg4 : 1; + RK_U32 sw_mf1_bwdref_offset : 9; + RK_U32 reserved0 : 1; + } swreg24; + + struct { + RK_U32 sw_filt_level_delta1_seg5 : 7; + RK_U32 sw_filt_level_delta2_seg5 : 7; + RK_U32 sw_filt_level_delta3_seg5 : 7; + RK_U32 sw_global_mv_seg5 : 1; + RK_U32 sw_mf1_altref2_offset : 9; + RK_U32 reserved0 : 1; + } swreg25; + + struct { + RK_U32 sw_filt_level_delta1_seg6 : 7; + RK_U32 sw_filt_level_delta2_seg6 : 7; + RK_U32 sw_filt_level_delta3_seg6 : 7; + RK_U32 sw_global_mv_seg6 : 1; + RK_U32 sw_mf1_altref_offset : 9; + RK_U32 reserved0 : 1; + } swreg26; + + struct { + RK_U32 sw_filt_level_delta1_seg7 : 7; + RK_U32 sw_filt_level_delta2_seg7 : 7; + RK_U32 sw_filt_level_delta3_seg7 : 7; + RK_U32 sw_global_mv_seg7 : 1; + RK_U32 sw_mf2_last_offset : 9; + RK_U32 reserved0 : 1; + } swreg27; + + struct { + RK_U32 sw_cb_offset : 9; + RK_U32 sw_cb_luma_mult : 8; + RK_U32 sw_cb_mult : 8; + RK_U32 sw_quant_delta_v_dc : 7; + } swreg28; + + struct { + RK_U32 sw_cr_offset : 9; + RK_U32 sw_cr_luma_mult : 8; + RK_U32 sw_cr_mult : 8; + RK_U32 sw_quant_delta_v_ac : 7; + } swreg29; + + struct { + RK_U32 sw_filt_ref_adj_5 : 7; + RK_U32 sw_filt_ref_adj_4 : 7; + RK_U32 sw_filt_mb_adj_1 : 7; + RK_U32 sw_filt_mb_adj_0 : 7; + RK_U32 sw_filt_sharpness : 3; + RK_U32 reserved0 : 1; + } swreg30; + + struct { + RK_U32 sw_quant_seg6 : 8; + RK_U32 sw_filt_level_seg6 : 6; + RK_U32 sw_skip_seg6 : 1; + RK_U32 sw_refpic_seg6 : 4; + RK_U32 sw_filt_level_delta0_seg6 : 7; + RK_U32 sw_skip_ref0 : 4; + RK_U32 reserved0 : 2; + } swreg31; + + struct { + RK_U32 sw_quant_seg7 : 8; + RK_U32 sw_filt_level_seg7 : 6; + RK_U32 sw_skip_seg7 : 1; + RK_U32 sw_refpic_seg7 : 4; + RK_U32 sw_filt_level_delta0_seg7 : 7; + RK_U32 sw_skip_ref1 : 4; + RK_U32 reserved0 : 2; + } swreg32; + + struct { + RK_U32 sw_ref0_height : 16; + RK_U32 sw_ref0_width : 16; + } swreg33; + + struct { + RK_U32 sw_ref1_height : 16; + RK_U32 sw_ref1_width : 16; + } swreg34; + + struct { + RK_U32 sw_ref2_height : 16; + RK_U32 sw_ref2_width : 16; + } swreg35; + + struct { + RK_U32 sw_ref0_ver_scale : 16; + RK_U32 sw_ref0_hor_scale : 16; + } swreg36; + + struct { + RK_U32 sw_ref1_ver_scale : 16; + RK_U32 sw_ref1_hor_scale : 16; + } swreg37; + + struct { + RK_U32 sw_ref2_ver_scale : 16; + RK_U32 sw_ref2_hor_scale : 16; + } swreg38; + + struct { + RK_U32 sw_ref3_ver_scale : 16; + RK_U32 sw_ref3_hor_scale : 16; + } swreg39; + + struct { + RK_U32 sw_ref4_ver_scale : 16; + RK_U32 sw_ref4_hor_scale : 16; + } swreg40; + + struct { + RK_U32 sw_ref5_ver_scale : 16; + RK_U32 sw_ref5_hor_scale : 16; + } swreg41; + + struct { + RK_U32 sw_ref6_ver_scale : 16; + RK_U32 sw_ref6_hor_scale : 16; + } swreg42; + struct { + RK_U32 sw_ref3_height : 16; + RK_U32 sw_ref3_width : 16; + } swreg43; + + struct { + RK_U32 sw_ref4_height : 16; + RK_U32 sw_ref4_width : 16; + } swreg44; + + struct { + RK_U32 sw_ref5_height : 16; + RK_U32 sw_ref5_width : 16; + } swreg45; + + struct { + RK_U32 sw_ref6_height : 16; + RK_U32 sw_ref6_width : 16; + } swreg46; + + struct { + RK_U32 sw_mf2_last2_offset : 9; + RK_U32 sw_mf2_last3_offset : 9; + RK_U32 sw_mf2_golden_offset : 9; + RK_U32 sw_qmlevel_y : 4; + RK_U32 reserved0 : 1; + } swreg47; + + struct { + RK_U32 sw_mf2_bwdref_offset : 9; + RK_U32 sw_mf2_altref2_offset : 9; + RK_U32 sw_mf2_altref_offset : 9; + RK_U32 sw_qmlevel_u : 4; + RK_U32 reserved0 : 1; + } swreg48; + + struct { + RK_U32 sw_filt_ref_adj_6 : 7; + RK_U32 sw_filt_ref_adj_7 : 7; + RK_U32 sw_qmlevel_v : 4; + RK_U32 reserved0 : 14; + } swreg49; + + struct { + RK_U32 SW_DEC_MAX_OWIDTH : 16; + RK_U32 SW_DEC_AV1_PROF : 1; + RK_U32 reserved0 : 15; + } swreg50; + + struct { + RK_U32 sw_superres_chroma_step : 14; + RK_U32 sw_superres_luma_step : 14; + RK_U32 reserved0 : 4; + } swreg51; + + struct { + RK_U32 sw_superres_init_chroma_subpel_x : 14; + RK_U32 sw_superres_init_luma_subpel_x : 14; + RK_U32 reserved0 : 4; + } swreg52; + + struct { + RK_U32 sw_cdef_chroma_secondary_strength : 16; + RK_U32 sw_cdef_luma_secondary_strength : 16; + } swreg53; + + struct { + RK_U32 reserved0 : 5; + RK_U32 SW_DEC_ADDR64_SUPPORTED : 1; + RK_U32 reserved1 : 11; + RK_U32 SW_DEC_RFC_EXIST : 2; + RK_U32 reserved2 : 13; + } swreg54; + + struct { + RK_U32 sw_apf_threshold : 16; + RK_U32 reserved0 : 14; + RK_U32 sw_apf_single_pu_mode : 1; + RK_U32 sw_apf_disable : 1; + } swreg55; + + struct { + RK_U32 SW_DEC_MAX_OHEIGHT : 15; + RK_U32 SW_DEC_DATA_S_W : 2; + RK_U32 SW_DEC_ADDR_S_W : 1; + RK_U32 SW_DEC_DATA_M_W : 2; + RK_U32 SW_DEC_ADDR_M_W : 1; + RK_U32 SW_DEC_SLAVE_BUS : 2; + RK_U32 SW_DEC_MASTER_BUS : 2; + RK_U32 SW_DEC_JOINT : 1; + RK_U32 reserved0 : 6; + } swreg56; + + struct { + RK_U32 reserved0 : 6; + RK_U32 fuse_dec_av1 : 1; + RK_U32 reserved1 : 25; + } swreg57; + + struct { + RK_U32 sw_dec_max_burst : 8; + RK_U32 sw_dec_buswidth : 3; + RK_U32 sw_dec_multicore_mode : 2; + RK_U32 sw_dec_axi_wd_id_e : 1; + RK_U32 sw_dec_axi_rd_id_e : 1; + RK_U32 reserved0 : 2; + RK_U32 sw_dec_mc_polltime : 10; + RK_U32 sw_dec_mc_pollmode : 2; + RK_U32 reserved1 : 3; + } swreg58; + + struct { + RK_U32 sw_filt_ref_adj_3 : 7; + RK_U32 sw_filt_ref_adj_2 : 7; + RK_U32 sw_filt_ref_adj_1 : 7; + RK_U32 sw_filt_ref_adj_0 : 7; + RK_U32 sw_ref0_sign_bias : 1; + RK_U32 sw_ref1_sign_bias : 1; + RK_U32 sw_ref2_sign_bias : 1; + RK_U32 sw_ref3_sign_bias : 1; + } swreg59; + + struct { + RK_U32 sw_dec_axi_rd_id : 16; + RK_U32 sw_dec_axi_wr_id : 16; + } swreg60; + + struct { + RK_U32 reserved0 : 12; + RK_U32 fuse_pp_maxw_352 : 1; + RK_U32 fuse_pp_maxw_720 : 1; + RK_U32 fuse_pp_maxw_1280 : 1; + RK_U32 fuse_pp_maxw_1920 : 1; + RK_U32 fuse_pp_maxw_4k : 1; + RK_U32 reserved1 : 12; + RK_U32 fuse_pp_ablend : 1; + RK_U32 fuse_pp_scaling : 1; + RK_U32 fuse_pp_pp : 1; + } swreg61; + + struct { + RK_U32 sw_cu_location_y : 16; + RK_U32 sw_cu_location_x : 16; + } swreg62; + + struct { + RK_U32 sw_perf_cycle_count : 32; + } swreg63; + + /* swreg64 - swreg183 */ + VdpuAv1dBase addr_cfg; + + struct { + RK_U32 sw_cur_last_roffset : 9; + RK_U32 sw_cur_last_offset : 9; + RK_U32 sw_mf3_last_offset : 9; + RK_U32 sw_ref0_gm_mode : 2; + RK_U32 reserved0 : 3; + } swreg184; + + struct { + RK_U32 sw_cur_last2_roffset : 9; + RK_U32 sw_cur_last2_offset : 9; + RK_U32 sw_mf3_last2_offset : 9; + RK_U32 sw_ref1_gm_mode : 2; + RK_U32 reserved0 : 3; + } swreg185; + + struct { + RK_U32 sw_cur_last3_roffset : 9; + RK_U32 sw_cur_last3_offset : 9; + RK_U32 sw_mf3_last3_offset : 9; + RK_U32 sw_ref2_gm_mode : 2; + RK_U32 reserved0 : 3; + } swreg186; + + struct { + RK_U32 sw_cur_golden_roffset : 9; + RK_U32 sw_cur_golden_offset : 9; + RK_U32 sw_mf3_golden_offset : 9; + RK_U32 sw_ref3_gm_mode : 2; + RK_U32 reserved0 : 3; + } swreg187; + + struct { + RK_U32 sw_cur_bwdref_roffset : 9; + RK_U32 sw_cur_bwdref_offset : 9; + RK_U32 sw_mf3_bwdref_offset : 9; + RK_U32 sw_ref4_gm_mode : 2; + RK_U32 reserved0 : 3; + } swreg188; + + struct { + RK_U32 sw_dec_out_tybase_msb : 32; + } swreg189; + + struct { + RK_U32 sw_dec_out_tybase_lsb : 32; + } swreg190; + + struct { + RK_U32 sw_refer0_tybase_msb : 32; + } swreg191; + + struct { + RK_U32 sw_refer0_tybase_lsb : 32; + } swreg192; + + struct { + RK_U32 sw_refer1_tybase_msb : 32; + } swreg193; + + struct { + RK_U32 sw_refer1_tybase_lsb : 32; + } swreg194; + + struct { + RK_U32 sw_refer2_tybase_msb : 32; + } swreg195; + + struct { + RK_U32 sw_refer2_tybase_lsb : 32; + } swreg196; + + struct { + RK_U32 sw_refer3_tybase_msb : 32; + } swreg197; + + struct { + RK_U32 sw_refer3_tybase_lsb : 32; + } swreg198; + + struct { + RK_U32 sw_refer4_tybase_msb : 32; + } swreg199; + + struct { + RK_U32 sw_refer4_tybase_lsb : 32; + } swreg200; + + struct { + RK_U32 sw_refer5_tybase_msb : 32; + } swreg201; + + struct { + RK_U32 sw_refer5_tybase_lsb : 32; + } swreg202; + + struct { + RK_U32 sw_refer6_tybase_msb : 32; + } swreg203; + + struct { + RK_U32 sw_refer6_tybase_lsb : 32; + } swreg204; + + RK_U32 reserved_205_222[18]; + struct { + RK_U32 sw_dec_out_tcbase_msb : 32; + } swreg223; + + struct { + RK_U32 sw_dec_out_tcbase_lsb : 32; + } swreg224; + + struct { + RK_U32 sw_refer0_tcbase_msb : 32; + } swreg225; + + struct { + RK_U32 sw_refer0_tcbase_lsb : 32; + } swreg226; + + struct { + RK_U32 sw_refer1_tcbase_msb : 32; + } swreg227; + + struct { + RK_U32 sw_refer1_tcbase_lsb : 32; + } swreg228; + + struct { + RK_U32 sw_refer2_tcbase_msb : 32; + } swreg229; + + struct { + RK_U32 sw_refer2_tcbase_lsb : 32; + } swreg230; + + struct { + RK_U32 sw_refer3_tcbase_msb : 32; + } swreg231; + + struct { + RK_U32 sw_refer3_tcbase_lsb : 32; + } swreg232; + + struct { + RK_U32 sw_refer4_tcbase_msb : 32; + } swreg233; + + struct { + RK_U32 sw_refer4_tcbase_lsb : 32; + } swreg234; + + struct { + RK_U32 sw_refer5_tcbase_msb : 32; + } swreg235; + + struct { + RK_U32 sw_refer5_tcbase_lsb : 32; + } swreg236; + + struct { + RK_U32 sw_refer6_tcbase_msb : 32; + } swreg237; + + struct { + RK_U32 sw_refer6_tcbase_lsb : 32; + } swreg238; + + RK_U32 reserved_239_256[18]; + struct { + RK_U32 sw_cur_altref2_roffset : 9; + RK_U32 sw_cur_altref2_offset : 9; + RK_U32 sw_mf3_altref2_offset : 9; + RK_U32 sw_ref5_gm_mode : 2; + RK_U32 reserved0 : 3; + } swreg257; + + struct { + RK_U32 sw_strm_buffer_len : 32; + } swreg258; + + struct { + RK_U32 sw_strm_start_offset : 32; + } swreg259; + + struct { + RK_U32 reserved0 : 21; + RK_U32 sw_ppd_blend_exist : 1; + RK_U32 reserved1 : 1; + RK_U32 sw_ppd_dith_exist : 1; + RK_U32 sw_ablend_crop_e : 1; + RK_U32 sw_pp_format_p010_e : 1; + RK_U32 sw_pp_format_customer1_e : 1; + RK_U32 sw_pp_crop_exist : 1; + RK_U32 sw_pp_up_level : 1; + RK_U32 sw_pp_down_level : 2; + RK_U32 sw_pp_exist : 1; + } swreg260; + + struct { + RK_U32 sw_dec_error_code : 8; + RK_U32 reserved0 : 24; + } swreg261; + + struct { + RK_U32 sw_cur_altref_roffset : 9; + RK_U32 sw_cur_altref_offset : 9; + RK_U32 sw_mf3_altref_offset : 9; + RK_U32 sw_ref6_gm_mode : 2; + RK_U32 reserved0 : 3; + } swreg262; + + struct { + RK_U32 sw_cdef_luma_primary_strength : 32; + } swreg263; + + struct { + RK_U32 sw_cdef_chroma_primary_strength : 32; + } swreg264; + + struct { + RK_U32 sw_axi_arqos : 4; + RK_U32 sw_axi_awqos : 4; + + RK_U32 sw_axi_wr_ostd_threshold : 10; + RK_U32 sw_axi_rd_ostd_threshold : 10; + + RK_U32 reserved0 : 3; + RK_U32 sw_axi_wr_4k_dis : 1; + } swreg265; + + struct { + RK_U32 reserved0 : 5; + RK_U32 sw_128bit_mode : 1; + RK_U32 reserved1 : 4; + RK_U32 sw_wr_shaper_bypass : 1; + RK_U32 reserved2 : 19; + RK_U32 sw_error_conceal_e : 1; + RK_U32 reserved3 : 1; + } swreg266; + + RK_U32 reserved_267_297[31]; + struct { + RK_U32 sw_superres_chroma_step_invra : 16; + RK_U32 sw_superres_luma_step_invra : 16; + } swreg298; + + struct { + RK_U32 sw_dec_pred_dataout_cnt : 32; + } swreg299; + + struct { + RK_U32 sw_dec_axi_r_len_cnt : 32; + } swreg300; + + struct { + RK_U32 sw_dec_axi_r_dat_cnt : 32; + } swreg301; + + struct { + RK_U32 sw_dec_axi_r_req_cnt : 32; + } swreg302; + + struct { + RK_U32 sw_dec_axi_rlast_cnt : 32; + } swreg303; + + struct { + RK_U32 sw_dec_axi_w_len_cnt : 32; + } swreg304; + + struct { + RK_U32 sw_dec_axi_w_dat_cnt : 32; + } swreg305; + + struct { + RK_U32 sw_dec_axi_w_req_cnt : 32; + } swreg306; + + struct { + RK_U32 sw_dec_axi_wlast_cnt : 32; + } swreg307; + + struct { + RK_U32 sw_dec_axi_w_ack : 32; + } swreg308; + + struct { + RK_U32 hw_build_id : 32; + } swreg309; + + struct { + RK_U32 hw_syn_id : 16; + RK_U32 reserved0 : 16; + } swreg310; + + struct { + RK_U32 reserved0 : 32; + } swreg311; + + struct { + RK_U32 reserved0 : 32; + } swreg312; + + struct { + RK_U32 reserved0 : 32; + } swreg313; + + struct { + RK_U32 sw_dec_alignment : 16; + RK_U32 reserved0 : 16; + } swreg314; + + struct { + RK_U32 sw_tile_left : 32; + } swreg315; + + RK_U32 reserved_316; + struct { + RK_U32 reserved0 : 28; + RK_U32 sw_pp_line_cnt_sel : 2; + RK_U32 reserved1 : 2; + } swreg317; + + struct { + RK_U32 sw_ext_timeout_cycles : 31; + RK_U32 sw_ext_timeout_override_e : 1; + } swreg318; + + struct { + RK_U32 sw_timeout_cycles : 31; + RK_U32 sw_timeout_override_e : 1; + } swreg319; + + VdpuAv1dPPCfg vdpu_av1d_pp_cfg; + +} VdpuAv1dRegSet; + +#endif diff --git a/mpp/hal/vpu/common/CMakeLists.txt b/mpp/hal/vpu/common/CMakeLists.txt new file mode 100644 index 000000000..43c88e0d8 --- /dev/null +++ b/mpp/hal/vpu/common/CMakeLists.txt @@ -0,0 +1,7 @@ +# vim: syntax=cmake +include_directories(.) + +# hal vepu541 common module +add_library(hal_vepu_common OBJECT + vepu_common.c + ) diff --git a/mpp/hal/vpu/common/vepu_common.c b/mpp/hal/vpu/common/vepu_common.c new file mode 100644 index 000000000..2aa2d0e2b --- /dev/null +++ b/mpp/hal/vpu/common/vepu_common.c @@ -0,0 +1,350 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "vepu_common" + +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_frame.h" + +#include "vepu_common.h" + +static VepuFormatCfg vepu_yuv_cfg[MPP_FMT_YUV_BUTT] = { + //MPP_FMT_YUV420SP + { .format = VEPU_FMT_YUV420SEMIPLANAR, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV420SP_10BIT + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422SP + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422SP_10BIT + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV420P + { .format = VEPU_FMT_YUV420PLANAR, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV420SP_VU + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422P + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422SP_VU + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422_YUYV + { .format = VEPU_FMT_YUYV422INTERLEAVED, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422_YVYU + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422_UYVY + { .format = VEPU_FMT_UYVY422INTERLEAVED, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV422_VYUY + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV400 + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV440SP + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV411SP + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_YUV444SP + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, +}; + +static VepuFormatCfg vepu_rgb_cfg[MPP_FMT_RGB_BUTT - MPP_FRAME_FMT_RGB] = { + //MPP_FMT_RGB565, ff: rgb565be, bin(rrrr,rggg,gggb,bbbb) mem MSB-->LSB(gggb,bbbb,rrrr,rggg) + { .format = VEPU_FMT_RGB565, .r_mask = 15, .g_mask = 10, .b_mask = 4, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_BGR565, ff: bgr565be, bin(bbbb,bggg,gggr,rrrr) mem MSB-->LSB(gggr,rrrr,bbbb,bggg) + { .format = VEPU_FMT_RGB565, .r_mask = 4, .g_mask = 10, .b_mask = 15, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_RGB555, ff: rgb555be, bin(0rrr,rrgg,gggb,bbbb) mem MSB-->LSB(gggb,bbbb,0rrr,rrgg) + { .format = VEPU_FMT_RGB555, .r_mask = 14, .g_mask = 9, .b_mask = 4, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_BGR555, ff: bgr555be, bin(0bbb,bbgg,gggr,rrrr) mem MSB-->LSB(gggr,rrrr,0bbb,bbgg) + { .format = VEPU_FMT_RGB555, .r_mask = 4, .g_mask = 9, .b_mask = 14, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_RGB444, ff: rgb444be, bin(0000,rrrr,gggg,bbbb) + { .format = VEPU_FMT_RGB444, .r_mask = 11, .g_mask = 7, .b_mask = 3, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_BGR444, ff: bgr444be, bin(0000,bbbb,gggg,rrrr) + { .format = VEPU_FMT_RGB444, .r_mask = 3, .g_mask = 7, .b_mask = 11, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_RGB888, ff: rgb24, bin(rrrr,rrrr,gggg,gggg,bbbb,bbbb) + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 0, }, + //MPP_FMT_BGR888, ff: bgr24, bin(bbbb,bbbb,gggg,gggg,rrrr,rrrr) + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 0, }, + //MPP_FMT_RGB101010, bin(00rr,rrrr,rrrr,gggg,gggg,ggbb,bbbb,bbbb) + { .format = VEPU_FMT_RGB101010, .r_mask = 29, .g_mask = 19, .b_mask = 9, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_BGR101010, bin(00bb,bbbb,bbbb,gggg,gggg,ggrr,rrrr,rrrr) + { .format = VEPU_FMT_RGB101010, .r_mask = 9, .g_mask = 19, .b_mask = 29, .swap_8_in = 1, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_ARGB8888, argb, bin(aaaa,aaaa,rrrr,rrrr,gggg,gggg,bbbb,bbbb) + { .format = VEPU_FMT_RGB888, .r_mask = 15, .g_mask = 23, .b_mask = 31, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + //MPP_FMT_ABGR8888, ffmepg: rgba, bin(aaaa,aaaa,bbbb,bbbb,gggg,gggg,rrrr,rrrr) + { .format = VEPU_FMT_RGB888, .r_mask = 31, .g_mask = 23, .b_mask = 15, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + //MPP_FMT_BGRA8888, ff: bgra, bin(bbbb,bbbb,gggg,gggg,rrrr,rrrr,aaaa,aaaa) + { .format = VEPU_FMT_RGB888, .r_mask = 23, .g_mask = 15, .b_mask = 7, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + //MPP_FMT_RGBA8888, ff: rgba, bin(rrrr,rrrr,gggg,gggg,bbbb,bbbb,aaaa,aaaa) + { .format = VEPU_FMT_RGB888, .r_mask = 7, .g_mask = 15, .b_mask = 23, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, +}; +static VepuFormatCfg vepu_rgb_le_cfg[MPP_FMT_RGB_BUTT - MPP_FRAME_FMT_RGB] = { + //for little endian format + //MPP_FMT_RGB565LE, ff: rgb565le, bin(gggb,bbbb,rrrr,rggg) + { .format = VEPU_FMT_RGB565, .r_mask = 15, .g_mask = 10, .b_mask = 4, .swap_8_in = 0, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_BGR565LE, ff: bgr565le, bin(gggr,rrrr,bbbb,bggg) + { .format = VEPU_FMT_RGB565, .r_mask = 4, .g_mask = 10, .b_mask = 15, .swap_8_in = 0, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_RGB555LE, ff: rgb555le, bin(gggb,bbbb,0rrr,rrgg) + { .format = VEPU_FMT_RGB555, .r_mask = 14, .g_mask = 9, .b_mask = 4, .swap_8_in = 0, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_BGR555LE, ff: bgr555le, bin(gggr,rrrr,0bbb,bbgg) + { .format = VEPU_FMT_RGB555, .r_mask = 4, .g_mask = 9, .b_mask = 14, .swap_8_in = 0, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_RGB444LE, ff: rgb444le, bin(gggg,bbbb,0000,rrrr) + { .format = VEPU_FMT_RGB444, .r_mask = 11, .g_mask = 7, .b_mask = 3, .swap_8_in = 0, .swap_16_in = 1, .swap_32_in = 1, }, + //MPP_FMT_BGR444LE, ff: bgr444le, bin(gggg,rrrr,0000,bbbb) + { .format = VEPU_FMT_RGB444, .r_mask = 3, .g_mask = 7, .b_mask = 11, .swap_8_in = 0, .swap_16_in = 1, .swap_32_in = 1, }, + + //MPP_FMT_RGB888, ff: rgb24, bin(rrrr,rrrr,gggg,gggg,bbbb,bbbb) + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 0, }, + //MPP_FMT_BGR888, ff: bgr24, bin(bbbb,bbbb,gggg,gggg,rrrr,rrrr) + { .format = VEPU_FMT_BUTT, .r_mask = 0, .g_mask = 0, .b_mask = 0, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 0, }, + + //MPP_FMT_RGB101010, bin(00rr,rrrr,rrrr,gggg,gggg,ggbb,bbbb,bbbb) + { .format = VEPU_FMT_RGB101010, .r_mask = 29, .g_mask = 19, .b_mask = 9, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + //MPP_FMT_BGR101010, bin(00bb,bbbb,bbbb,gggg,gggg,ggrr,rrrr,rrrr) + { .format = VEPU_FMT_RGB101010, .r_mask = 9, .g_mask = 19, .b_mask = 29, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + + //MPP_FMT_ARGB8888LE, argb, bin(aaaa,aaaa,rrrr,rrrr,gggg,gggg,bbbb,bbbb) + { .format = VEPU_FMT_RGB888, .r_mask = 23, .g_mask = 15, .b_mask = 7, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + //MPP_FMT_ABGR8888LE, ffmepg: rgba, bin(aaaa,aaaa,bbbb,bbbb,gggg,gggg,rrrr,rrrr) + { .format = VEPU_FMT_RGB888, .r_mask = 7, .g_mask = 15, .b_mask = 23, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + //MPP_FMT_BGRA8888LE, ff: bgra, bin(bbbb,bbbb,gggg,gggg,rrrr,rrrr,aaaa,aaaa) + { .format = VEPU_FMT_RGB888, .r_mask = 15, .g_mask = 23, .b_mask = 31, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, + //MPP_FMT_RGBA8888LE, ff: rgba, bin(rrrr,rrrr,gggg,gggg,bbbb,bbbb,aaaa,aaaa) + { .format = VEPU_FMT_RGB888, .r_mask = 31, .g_mask = 23, .b_mask = 15, .swap_8_in = 0, .swap_16_in = 0, .swap_32_in = 1, }, +}; + +MPP_RET get_vepu_fmt(VepuFormatCfg *cfg, MppFrameFormat format) +{ + VepuFormatCfg *fmt_cfg = NULL; + MPP_RET ret = MPP_OK; + + if (MPP_FRAME_FMT_IS_FBC(format)) { + mpp_err_f("unsupport frame format %x\n", format); + } else if (MPP_FRAME_FMT_IS_YUV(format)) { + if (!MPP_FRAME_FMT_IS_LE(format)) + fmt_cfg = &vepu_yuv_cfg[format - MPP_FRAME_FMT_YUV]; + } else if (MPP_FRAME_FMT_IS_RGB(format)) { + if (MPP_FRAME_FMT_IS_LE(format)) { + fmt_cfg = &vepu_rgb_le_cfg[(format & MPP_FRAME_FMT_MASK) - MPP_FRAME_FMT_RGB]; + } else + fmt_cfg = &vepu_rgb_cfg[format - MPP_FRAME_FMT_RGB]; + } else { + memset(cfg, 0, sizeof(*cfg)); + cfg->format = VEPU_FMT_BUTT; + } + + if (fmt_cfg && fmt_cfg->format != VEPU_FMT_BUTT) { + memcpy(cfg, fmt_cfg, sizeof(*cfg)); + } else { + mpp_err_f("unsupport frame format %x\n", format); + cfg->format = VEPU_FMT_BUTT; + ret = MPP_NOK; + } + + return ret; +} + +static RK_S32 check_stride_by_pixel(RK_S32 workaround, RK_S32 width, + RK_S32 hor_stride, RK_S32 pixel_size) +{ + if (!workaround && hor_stride < width * pixel_size) { + mpp_log("warning: stride by bytes %d is smarller than width %d mutiple by pixel size %d\n", + hor_stride, width, pixel_size); + mpp_log("multiple stride %d by pixel size %d and set new byte stride to %d\n", + hor_stride, pixel_size, hor_stride * pixel_size); + workaround = 1; + } + + return workaround; +} + +static RK_S32 check_8_pixel_aligned(RK_S32 workaround, RK_S32 hor_stride, + RK_S32 pixel_aign, RK_S32 pixel_size, + const char *fmt_name) +{ + if (!workaround && hor_stride != MPP_ALIGN_GEN(hor_stride, pixel_aign * pixel_size)) { + mpp_log("warning: vepu only support 8 aligned horizontal stride in pixel for %s with pixel size %d\n", + fmt_name, pixel_size); + mpp_log("set byte stride to %d to match the requirement\n", + MPP_ALIGN_GEN(hor_stride, pixel_aign * pixel_size)); + workaround = 1; + } + + return workaround; +} + +RK_U32 get_vepu_pixel_stride(VepuStrideCfg *cfg, RK_U32 width, RK_U32 stride, MppFrameFormat fmt) +{ + RK_U32 hor_stride = stride; + RK_U32 pixel_size = 1; + + if (cfg->fmt != fmt) { + memset(cfg, 0, sizeof(VepuStrideCfg)); + cfg->fmt = fmt; + } + + if (cfg->stride != stride || cfg->width != width) { + cfg->not_8_pixel = 0; + cfg->is_pixel_stride = 0; + cfg->stride = stride; + cfg->width = width; + } + + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP : { + if (check_8_pixel_aligned(cfg->not_8_pixel, hor_stride, 8, 1, "YUV420SP")) { + hor_stride = MPP_ALIGN(hor_stride, 8); + cfg->not_8_pixel = 1; + } + } break; + case MPP_FMT_YUV420P : { + if (check_8_pixel_aligned(cfg->not_8_pixel, hor_stride, 16, 1, "YUV420P")) { + hor_stride = MPP_ALIGN(hor_stride, 8); + cfg->not_8_pixel = 1; + } + } break; + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_UYVY : { + if (check_stride_by_pixel(cfg->is_pixel_stride, cfg->width, + hor_stride, 2)) { + hor_stride *= 2; + cfg->is_pixel_stride = 1; + } + + if (check_8_pixel_aligned(cfg->not_8_pixel, hor_stride, 8, 2, "YUV422_interleave")) { + hor_stride = MPP_ALIGN(hor_stride, 16); + cfg->not_8_pixel = 1; + } + + hor_stride /= 2; + pixel_size = 2; + } break; + case MPP_FMT_RGB565 : + case MPP_FMT_BGR565 : + case MPP_FMT_RGB555 : + case MPP_FMT_BGR555 : + case MPP_FMT_RGB444 : + case MPP_FMT_BGR444 : { + if (check_stride_by_pixel(cfg->is_pixel_stride, cfg->width, + hor_stride, 2)) { + hor_stride *= 2; + cfg->is_pixel_stride = 1; + } + + if (check_8_pixel_aligned(cfg->not_8_pixel, hor_stride, 8, 2, "32bit RGB")) { + hor_stride = MPP_ALIGN(hor_stride, 16); + cfg->not_8_pixel = 1; + } + + hor_stride /= 2; + pixel_size = 2; + } break; + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_RGBA8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGB101010 : + case MPP_FMT_BGR101010 : { + if (check_stride_by_pixel(cfg->is_pixel_stride, cfg->width, + hor_stride, 4)) { + hor_stride *= 4; + cfg->is_pixel_stride = 1; + } + + if (check_8_pixel_aligned(cfg->not_8_pixel, hor_stride, 8, 4, "16bit RGB")) { + hor_stride = MPP_ALIGN(hor_stride, 32); + cfg->not_8_pixel = 1; + } + + hor_stride /= 4; + pixel_size = 4; + } break; + default: { + mpp_err_f("invalid fmt %d", fmt); + } + } + cfg->pixel_stride = hor_stride; + cfg->pixel_size = pixel_size; + + return hor_stride; +} + +MPP_RET get_vepu_offset_cfg(VepuOffsetCfg *cfg) +{ + MPP_RET ret = MPP_OK; + MppFrameFormat fmt = cfg->fmt; + RK_U32 hor_stride = cfg->hor_stride; + RK_U32 ver_stride = cfg->ver_stride; + RK_U32 offset_x = cfg->offset_x; + RK_U32 offset_y = cfg->offset_y; + RK_U32 offset_c = hor_stride * ver_stride; + + memset(cfg->offset_byte, 0, sizeof(cfg->offset_byte)); + memset(cfg->offset_pixel, 0, sizeof(cfg->offset_pixel)); + + if (offset_x || offset_y) { + switch (fmt) { + case MPP_FMT_YUV420SP : { + cfg->offset_byte[0] = offset_y * hor_stride + offset_x; + cfg->offset_byte[1] = offset_y / 2 * hor_stride + offset_x + offset_c; + } break; + case MPP_FMT_YUV420P : { + cfg->offset_byte[0] = offset_y * hor_stride + offset_x; + cfg->offset_byte[1] = (offset_y / 2) * (hor_stride / 2) + (offset_x / 2) + offset_c; + cfg->offset_byte[2] = (offset_y / 2) * (hor_stride / 2) + (offset_x / 2) + offset_c * 5 / 4; + } break; + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_UYVY : { + mpp_assert((offset_x & 1) == 0); + cfg->offset_byte[0] = offset_y * hor_stride + offset_x * 2; + } break; + case MPP_FMT_RGB565 : + case MPP_FMT_BGR565 : + case MPP_FMT_RGB555 : + case MPP_FMT_BGR555 : + case MPP_FMT_RGB444 : + case MPP_FMT_BGR444 : { + cfg->offset_byte[0] = offset_y * hor_stride + offset_x * 2; + } break; + case MPP_FMT_RGB101010 : + case MPP_FMT_BGR101010 : + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGBA8888 : { + cfg->offset_byte[0] = offset_y * hor_stride + offset_x * 4; + } break; + default : { + } break; + } + } else { + switch (fmt) { + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420P : { + RK_U32 offset = hor_stride * ver_stride; + + cfg->offset_byte[1] = offset; + + if (fmt == MPP_FMT_YUV420P) + offset = hor_stride * ver_stride * 5 / 4; + + cfg->offset_byte[2] = offset; + } break; + default : { + } break; + } + } + + return ret; +} diff --git a/mpp/hal/vpu/common/vepu_common.h b/mpp/hal/vpu/common/vepu_common.h new file mode 100644 index 000000000..9b1602ffd --- /dev/null +++ b/mpp/hal/vpu/common/vepu_common.h @@ -0,0 +1,91 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef VEPU_COMMON_H +#define VEPU_COMMON_H + +#include "mpp_frame.h" + +typedef enum VepuFormat_e { + VEPU_FMT_YUV420PLANAR, //0 + VEPU_FMT_YUV420SEMIPLANAR, //1 + VEPU_FMT_YUYV422INTERLEAVED, //2 + VEPU_FMT_UYVY422INTERLEAVED, //3 + VEPU_FMT_RGB565, //4 + VEPU_FMT_RGB555, //5 + VEPU_FMT_RGB444, //6 + VEPU_FMT_RGB888, //7 + VEPU_FMT_RGB101010, //8 + VEPU_FMT_BUTT, //9 +} VepuFmt; + +typedef struct VepuFormatCfg_t { + VepuFmt format; + RK_U8 r_mask; + RK_U8 g_mask; + RK_U8 b_mask; + RK_U8 swap_8_in; + RK_U8 swap_16_in; + RK_U8 swap_32_in; +} VepuFormatCfg; + +typedef struct VepuStrideCfg_t { + MppFrameFormat fmt; + RK_S32 not_8_pixel; + RK_S32 is_pixel_stride; + + RK_U32 width; + RK_U32 stride; + + RK_U32 pixel_stride; + RK_U32 pixel_size; +} VepuStrideCfg; + +typedef struct VepuOffsetCfg_t { + /* input parameter */ + MppFrameFormat fmt; + /* width / height by pixel */ + RK_U32 width; + RK_U32 height; + /* stride by byte */ + RK_U32 hor_stride; + RK_U32 ver_stride; + /* offset by pixel */ + RK_U32 offset_x; + RK_U32 offset_y; + + /* output parameter */ + /* offset by byte */ + RK_U32 offset_byte[3]; + + /* offset by pixel */ + RK_U32 offset_pixel[3]; +} VepuOffsetCfg; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET get_vepu_fmt(VepuFormatCfg *cfg, MppFrameFormat format); +RK_U32 get_vepu_pixel_stride(VepuStrideCfg *cfg, RK_U32 width, + RK_U32 stride, MppFrameFormat fmt); + +MPP_RET get_vepu_offset_cfg(VepuOffsetCfg *cfg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/hal/vpu/h263d/CMakeLists.txt b/mpp/hal/vpu/h263d/CMakeLists.txt new file mode 100644 index 000000000..b9eb0e2b4 --- /dev/null +++ b/mpp/hal/vpu/h263d/CMakeLists.txt @@ -0,0 +1,11 @@ +# vim: syntax=cmake + +# hal h263 decoder sourse +set(HAL_H263D_SRC) + +add_hal_source(HAL_H263D_SRC HAVE_VDPU1 hal_h263d_vdpu1.c) +add_hal_source(HAL_H263D_SRC HAVE_VDPU2 hal_h263d_vdpu2.c) + +if (HAL_H263D_SRC) + add_library(hal_h263d_api OBJECT ${HAL_H263D_SRC}) +endif() diff --git a/mpp/hal/vpu/h263d/hal_h263d_base.h b/mpp/hal/vpu/h263d/hal_h263d_base.h new file mode 100644 index 000000000..78b5f7e20 --- /dev/null +++ b/mpp/hal/vpu/h263d/hal_h263d_base.h @@ -0,0 +1,38 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H263D_BASE_H +#define HAL_H263D_BASE_H + +#include "mpp_hal.h" + +#define H263D_HAL_DBG_REG_PUT (0x00000001) +#define H263D_HAL_DBG_REG_GET (0x00000002) + +extern RK_U32 hal_h263d_debug; + +typedef struct h263d_reg_context { + MppHalCfg *cfg; + + // save fd for curr/ref0/ref1 for reg_gen + RK_S32 vpu_fd; + RK_S32 fd_curr; + RK_S32 fd_ref0; + + void *regs; +} hal_h263_ctx; + +#endif diff --git a/mpp/hal/vpu/h263d/hal_h263d_vdpu1.c b/mpp/hal/vpu/h263d/hal_h263d_vdpu1.c new file mode 100644 index 000000000..4ae77d3ba --- /dev/null +++ b/mpp/hal/vpu/h263d/hal_h263d_vdpu1.c @@ -0,0 +1,325 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vpu_h263d" + +#include +#include + +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_env.h" + +#include "h263d_syntax.h" +#include "hal_h263d_vdpu1.h" +#include "hal_h263d_vdpu1_reg.h" +#include "hal_h263d_base.h" + +static void vpu1_h263d_setup_regs_by_syntax(hal_h263_ctx *ctx, MppSyntax syntax) +{ + Vpu1H263dRegSet_t *regs = (Vpu1H263dRegSet_t*)ctx->regs; + DXVA2_DecodeBufferDesc **data = syntax.data; + DXVA_PicParams_H263 *pp = NULL; + RK_U32 stream_length = 0; + RK_U32 stream_used = 0; + RK_U32 i; + + for (i = 0; i < syntax.number; i++) { + DXVA2_DecodeBufferDesc *desc = data[i]; + switch (desc->CompressedBufferType) { + case DXVA2_PictureParametersBufferType : { + pp = (DXVA_PicParams_H263 *)desc->pvPVPState; + } break; + case DXVA2_BitStreamDateBufferType : { + stream_length = desc->DataSize; + stream_used = desc->DataOffset; + } break; + default : { + mpp_err_f("found invalid buffer descriptor type %d\n", desc->CompressedBufferType); + } break; + } + } + + mpp_assert(pp); + mpp_assert(stream_length); + mpp_assert(stream_used); + + regs->SwReg04.sw_pic_mb_width = (pp->vop_width + 15) >> 4; + regs->SwReg04.sw_pic_mb_hight_p = (pp->vop_height + 15) >> 4; + regs->SwReg04.sw_mb_width_off = pp->vop_width & 0xf; + regs->SwReg04.sw_mb_height_off = pp->vop_height & 0xf; + + regs->SwReg03.sw_dec_mode = 2; + regs->SwReg03.sw_filtering_dis = 1; + regs->SwReg18.sw_h263_vc1_rc = 0; + regs->SwReg06.sw_init_qp = pp->vop_quant; + regs->SwReg05.sw_sync_markers_e = 1; + + { + /* + * update stream base address here according to consumed bit length + * 1. hardware start address has to be 64 bit align + * 2. hardware need to know which is the start bit in + * 2. pass (10bit fd + (offset << 10)) register value to kernel + */ + RK_U32 val = regs->SwReg12.sw_rlc_vlc_base; + RK_U32 consumed_bytes = stream_used >> 3; + RK_U32 consumed_bytes_align = consumed_bytes & (~0x7); + RK_U32 start_bit_offset = stream_used & 0x3F; + RK_U32 left_bytes = stream_length - consumed_bytes_align; + + if (consumed_bytes_align) + mpp_dev_set_reg_offset(ctx->cfg->dev, 12, consumed_bytes_align); + regs->SwReg12.sw_rlc_vlc_base = val; + regs->SwReg05.sw_strm_start_bit = start_bit_offset; + regs->SwReg06.sw_stream_len = left_bytes; + } + + regs->SwReg05.sw_vop_time_incr = pp->vop_time_increment_resolution; + + switch (pp->vop_coding_type) { + case H263_P_VOP : { + regs->SwReg03.sw_pic_inter_e = 1; + + if (ctx->fd_ref0 >= 0) { + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_ref0; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_ref0; + } else { + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_curr; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_curr; + } + } break; + case H263_I_VOP : { + regs->SwReg03.sw_pic_inter_e = 0; + + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_curr; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_curr; + } break; + default : { + /* no nothing */ + } break; + } + + regs->SwReg18.sw_fcode_fwd_hor = 1; + regs->SwReg18.sw_fcode_fwd_ver = 1; + regs->SwReg18.sw_prev_anc_type = (pp->prev_coding_type == H263_P_VOP); +} + +MPP_RET hal_vpu1_h263d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + Vpu1H263dRegSet_t *regs = NULL; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + + mpp_env_get_u32("hal_h263d_debug", &hal_h263d_debug, 0); + + mpp_assert(hal); + mpp_assert(cfg); + + regs = mpp_calloc(Vpu1H263dRegSet_t, 1); + if (NULL == regs) { + mpp_err_f("failed to malloc register ret\n"); + ret = MPP_ERR_MALLOC; + goto ERR_RET; + } + + ctx->cfg = cfg; + ctx->regs = (void*)regs; + + return ret; +ERR_RET: + if (regs) { + mpp_free(regs); + regs = NULL; + } + + return ret; +} + +MPP_RET hal_vpu1_h263d_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + + mpp_assert(hal); + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + ctx->cfg = NULL; + + return ret; +} + +MPP_RET hal_vpu1_h263d_gen_regs(void *hal, HalTaskInfo *syn) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + HalDecTask *task = &syn->dec; + MppBuffer buf_frm_curr = NULL; + MppBuffer buf_frm_ref0 = NULL; + MppBuffer buf_pkt = NULL; + Vpu1H263dRegSet_t *regs = (Vpu1H263dRegSet_t*)ctx->regs; + + mpp_assert(task->valid); + mpp_assert(task->input >= 0); + mpp_assert(task->output >= 0); + + memset(regs, 0, sizeof(Vpu1H263dRegSet_t)); + + /* + * basic register configuration setup here + */ + regs->SwReg02.sw_dec_out_endian = 1; + regs->SwReg02.sw_dec_in_endian = 1; + regs->SwReg02.sw_dec_inswap32_e = 1; + regs->SwReg02.sw_dec_outswap32_e = 1; + regs->SwReg02.sw_dec_strswap32_e = 1; + regs->SwReg02.sw_dec_strendian_e = 1; + regs->SwReg02.sw_dec_max_burst = 16; + regs->SwReg55.sw_apf_threshold = 1; + regs->SwReg02.sw_dec_timeout_e = 1; + regs->SwReg02.sw_dec_clk_gate_e = 1; + regs->SwReg01.sw_dec_en = 1; + regs->SwReg49.sw_pred_bc_tap_0_0 = -1; + regs->SwReg49.sw_pred_bc_tap_0_1 = 3; + regs->SwReg49.sw_pred_bc_tap_0_2 = -6; + regs->SwReg34.sw_pred_bc_tap_0_3 = 20; + + /* setup buffer for input / output / reference */ + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->input, SLOT_BUFFER, &buf_pkt); + mpp_assert(buf_pkt); + + if (task->input >= 0) + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, task->output, SLOT_BUFFER, &buf_frm_curr); + if (task->refer[0] >= 0) + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, task->refer[0], SLOT_BUFFER, &buf_frm_ref0); + + /* address registers setup first */ + ctx->fd_curr = mpp_buffer_get_fd(buf_frm_curr); + ctx->fd_ref0 = (buf_frm_ref0) ? (mpp_buffer_get_fd(buf_frm_ref0)) : (-1); + regs->SwReg13.dec_out_st_adr = (RK_U32)ctx->fd_curr; + regs->SwReg12.sw_rlc_vlc_base = mpp_buffer_get_fd(buf_pkt); + + /* setup other registers, here will update packet address */ + vpu1_h263d_setup_regs_by_syntax(ctx, task->syntax); + + return ret; +} + +MPP_RET hal_vpu1_h263d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + MppDev dev = ctx->cfg->dev; + RK_U32 *regs = (RK_U32 *)ctx->regs; + + if (hal_h263d_debug & H263D_HAL_DBG_REG_PUT) { + RK_U32 reg_count = (sizeof(Vpu1H263dRegSet_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = regs; + wr_cfg.size = sizeof(Vpu1H263dRegSet_t); + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = sizeof(Vpu1H263dRegSet_t); + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +MPP_RET hal_vpu1_h263d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + MppDev dev = ctx->cfg->dev; + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (hal_h263d_debug & H263D_HAL_DBG_REG_GET) { + RK_U32 *regs = (RK_U32 *)ctx->regs; + RK_U32 reg_count = (sizeof(Vpu1H263dRegSet_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + + (void)task; + return ret; +} + +const MppHalApi hal_h263d_vdpu1 = { + .name = "h263d_vdpu1", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingH263, + .ctx_size = sizeof(hal_h263_ctx), + .flag = 0, + .init = hal_vpu1_h263d_init, + .deinit = hal_vpu1_h263d_deinit, + .reg_gen = hal_vpu1_h263d_gen_regs, + .start = hal_vpu1_h263d_start, + .wait = hal_vpu1_h263d_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU1, + .soc_type = { + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h263d_vdpu1) diff --git a/mpp/hal/vpu/h263d/hal_h263d_vdpu1.h b/mpp/hal/vpu/h263d/hal_h263d_vdpu1.h new file mode 100644 index 000000000..eb96818be --- /dev/null +++ b/mpp/hal/vpu/h263d/hal_h263d_vdpu1.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H263D_VDPU1_H +#define HAL_H263D_VDPU1_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET hal_vpu1_h263d_init(void *hal, MppHalCfg *cfg); +MPP_RET hal_vpu1_h263d_deinit(void *hal); +MPP_RET hal_vpu1_h263d_gen_regs(void *hal, HalTaskInfo *syn); +MPP_RET hal_vpu1_h263d_start(void *hal, HalTaskInfo *task); +MPP_RET hal_vpu1_h263d_wait(void *hal, HalTaskInfo *task); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_H263_VDPU1_H */ diff --git a/mpp/hal/vpu/h263d/hal_h263d_vdpu1_reg.h b/mpp/hal/vpu/h263d/hal_h263d_vdpu1_reg.h new file mode 100644 index 000000000..a34563f9a --- /dev/null +++ b/mpp/hal/vpu/h263d/hal_h263d_vdpu1_reg.h @@ -0,0 +1,275 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H263D_VDPU1_REG_TBL_H +#define HAL_H263D_VDPU1_REG_TBL_H + +#include "rk_type.h" +/* Number registers for the decoder */ +#define DEC_VDPU1_REGISTERS (101) + +typedef struct { + RK_U32 SwReg00; + + struct { + RK_U32 sw_dec_en : 1; + RK_U32 reserve0 : 3; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve1 : 3; + RK_U32 sw_dec_irq : 1; + RK_U32 reserve2 : 3; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserve3 : 5; + RK_U32 sw_dec_pic_inf : 1; + RK_U32 reserve4 : 7; + } SwReg01; + + struct { + RK_U32 sw_dec_max_burst : 5; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_tiled_mode_lsb : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_tiled_mode_msb : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_dec_axi_rd_id : 8; + } SwReg02; + + struct { + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 reserve0 : 1; + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; + RK_U32 sw_skip_mode : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_dec_mode : 4; + } SwReg03; + + struct { + RK_U32 sw_reserve0 : 5; + RK_U32 sw_topfieldfirst_e : 1; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } SwReg04; + + struct { + RK_U32 sw_vop_time_incr : 16; + RK_U32 sw_intradc_vlc_thr : 3; + RK_U32 sw_ch_qp_offset : 5; + RK_U32 sw_type1_quant_e : 1; + RK_U32 sw_sync_markers_e : 1; + RK_U32 sw_strm_start_bit : 6; + } SwReg05; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_init_qp : 6; + RK_U32 sw_start_code_e : 1; + } SwReg06; + + struct { + RK_U32 sw_framenum : 16; + RK_U32 sw_framenum_len : 5; + RK_U32 reserve0 : 5; + RK_U32 sw_weight_bipr_idc : 2; + RK_U32 sw_weight_pred_e : 1; + RK_U32 sw_dir_8x8_infer_e : 1; + RK_U32 sw_blackwhite_e : 1; + RK_U32 sw_cabac_e : 1; + } SwReg07; + + struct { + RK_U32 sw_idr_pic_id : 16; + RK_U32 sw_idr_pic_e : 1; + RK_U32 sw_refpic_mk_len : 11; + RK_U32 sw_8x8trans_flag_e : 1; + RK_U32 sw_rdpic_cnt_pres : 1; + RK_U32 sw_filt_ctrl_pres : 1; + RK_U32 sw_const_intra_e : 1; + } SwReg08; + + struct { + RK_U32 sw_poc_length : 8; + RK_U32 reserve0 : 6; + RK_U32 sw_refidx0_active : 5; + RK_U32 sw_refidx1_active : 5; + RK_U32 sw_pps_id : 8; + } SwReg09; + + struct { + RK_U32 sw_diff_mv_base : 32; + } SwReg10; + + RK_U32 SwReg11; + + struct { + RK_U32 sw_rlc_vlc_base : 32; + } SwReg12; + + struct { + RK_U32 dec_out_st_adr : 32; + } SwReg13; + + /* MPP passes fd of reference frame to kernel + * with the whole register rather than higher 30-bit. + * At the same time, the lower 2-bit will be assigned + * by kernel. + * */ + struct { + //RK_U32 sw_refer0_topc_e : 1; + //RK_U32 sw_refer0_field_e : 1; + RK_U32 sw_refer0_base : 32; + } SwReg14; + + struct { + //RK_U32 sw_refer1_topc_e : 1; + //RK_U32 sw_refer1_field_e : 1; + RK_U32 sw_refer1_base : 32; + } SwReg15; + + struct { + //RK_U32 sw_refer2_topc_e : 1; + //RK_U32 sw_refer2_field_e : 1; + RK_U32 sw_refer2_base : 32; + } SwReg16; + + struct { + //RK_U32 sw_refer3_topc_e : 1; + //RK_U32 sw_refer3_field_e : 1; + RK_U32 sw_refer3_base : 32; + } SwReg17; + + struct { + RK_U32 sw_prev_anc_type : 1; + RK_U32 sw_h263_vc1_rc : 1; + RK_U32 sw_mv_accuracy_fwd : 1; + RK_U32 sw_fcode_bwd_ver : 4; + RK_U32 sw_fcode_bwd_hor : 4; + RK_U32 sw_fcode_fwd_ver : 4; + RK_U32 sw_fcode_fwd_hor : 4; + RK_U32 sw_alt_scan_flag_e : 1; + RK_U32 reserve0 : 12; + } SwReg18; + + struct { + //RK_U32 sw_refer5_topc_e : 1; + //RK_U32 sw_refer5_field_e : 1; + RK_U32 sw_refer5_base : 32; + } SwReg19; + + struct { + //RK_U32 sw_refer6_topc_e : 1; + //RK_U32 sw_refer6_field_e : 1; + RK_U32 sw_refer6_base : 32; + } SwReg20; + + struct { + //RK_U32 sw_refer7_topc_e : 1; + //RK_U32 sw_refer7_field_e : 1; + RK_U32 sw_refer7_base : 32; + } SwReg21; + + + RK_U32 SwReg22_33[12]; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_1_1 : 10; + RK_U32 sw_pred_bc_tap_1_0 : 10; + RK_U32 sw_pred_bc_tap_0_3 : 10; + } SwReg34; + + RK_U32 SwReg35_39[5]; + + struct { + RK_U32 sw_qtable_base : 32; + } SwReg40; + + struct { + RK_U32 sw_dir_mv_base : 32; + } SwReg41; + + RK_U32 SwReg42_47[6]; + + struct { + RK_U32 reserve0 : 15; + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + } SwReg48; + + struct { + RK_U32 reserve0 : 2; + RK_U32 sw_pred_bc_tap_0_2 : 10; + RK_U32 sw_pred_bc_tap_0_1 : 10; + RK_U32 sw_pred_bc_tap_0_0 : 10; + } SwReg49; + + RK_U32 SwReg50; + + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 reserve0 : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } SwReg51; + + RK_U32 SwReg52_54[3]; + + struct { + RK_U32 sw_apf_threshold : 14; + RK_U32 reserve0 : 18; + } SwReg55; + + RK_U32 SwReg56_100[45]; +} Vpu1H263dRegSet_t; + +#endif /* HAL_H263_VDPU1_REG_TBL_H */ diff --git a/mpp/hal/vpu/h263d/hal_h263d_vdpu2.c b/mpp/hal/vpu/h263d/hal_h263d_vdpu2.c new file mode 100644 index 000000000..9b8587f02 --- /dev/null +++ b/mpp/hal/vpu/h263d/hal_h263d_vdpu2.c @@ -0,0 +1,336 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vpu_h263d" + +#include +#include + +#include "mpp_err.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_env.h" + +#include "h263d_syntax.h" +#include "hal_h263d_vdpu2.h" +#include "hal_h263d_vdpu2_reg.h" +#include "hal_h263d_base.h" + +static void vpu2_h263d_setup_regs_by_syntax(hal_h263_ctx *ctx, MppSyntax syntax) +{ + Vpu2H263dRegSet_t *regs = (Vpu2H263dRegSet_t*)ctx->regs; + DXVA2_DecodeBufferDesc **data = syntax.data; + DXVA_PicParams_H263 *pp = NULL; + RK_U32 stream_length = 0; + RK_U32 stream_used = 0; + RK_U32 i; + + for (i = 0; i < syntax.number; i++) { + DXVA2_DecodeBufferDesc *desc = data[i]; + switch (desc->CompressedBufferType) { + case DXVA2_PictureParametersBufferType : { + pp = (DXVA_PicParams_H263 *)desc->pvPVPState; + } break; + case DXVA2_BitStreamDateBufferType : { + stream_length = desc->DataSize; + stream_used = desc->DataOffset; + } break; + default : { + mpp_err_f("found invalid buffer descriptor type %d\n", desc->CompressedBufferType); + } break; + } + } + + mpp_assert(pp); + mpp_assert(stream_length); + mpp_assert(stream_used); + + regs->reg120.sw_pic_mb_width = (pp->vop_width + 15) >> 4; + regs->reg120.sw_pic_mb_hight_p = (pp->vop_height + 15) >> 4; + regs->reg120.sw_mb_width_off = pp->vop_width & 0xf; + regs->reg120.sw_mb_height_off = pp->vop_height & 0xf; + + regs->reg53_dec_mode = 2; + regs->reg50_dec_ctrl.sw_filtering_dis = 1; + regs->reg136.sw_rounding = 0; + regs->reg51_stream_info.sw_init_qp = pp->vop_quant; + regs->reg122.sw_sync_markers_en = 1; + + { + /* + * update stream base address here according to consumed bit length + * 1. hardware start address has to be 64 bit align + * 2. hardware need to know which is the start bit in + * 2. pass (10bit fd + (offset << 10)) register value to kernel + */ + RK_U32 val = regs->reg64_input_stream_base; + RK_U32 consumed_bytes = stream_used >> 3; + RK_U32 consumed_bytes_align = consumed_bytes & (~0x7); + RK_U32 start_bit_offset = stream_used & 0x3F; + RK_U32 left_bytes = stream_length - consumed_bytes_align; + + if (consumed_bytes_align) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 64, consumed_bytes_align); + } + regs->reg64_input_stream_base = val; + regs->reg122.sw_stream_start_word = start_bit_offset; + regs->reg51_stream_info.sw_stream_len = left_bytes; + } + + regs->reg122.sw_vop_time_incr = pp->vop_time_increment_resolution; + + switch (pp->vop_coding_type) { + case H263_P_VOP : { + regs->reg57_enable_ctrl.sw_pic_inter_e = 1; + + if (ctx->fd_ref0 >= 0) { + regs->reg131_ref0_base = (RK_U32)ctx->fd_ref0; + regs->reg148_ref1_base = (RK_U32)ctx->fd_ref0; + } else { + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + } + } break; + case H263_I_VOP : { + regs->reg57_enable_ctrl.sw_pic_inter_e = 0; + + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + } break; + default : { + /* no nothing */ + } break; + } + + regs->reg136.sw_hrz_bit_of_fwd_mv = 1; + regs->reg136.sw_vrz_bit_of_fwd_mv = 1; + regs->reg136.sw_prev_pic_type = (pp->prev_coding_type == H263_P_VOP); +} + +MPP_RET hal_vpu2_h263d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + Vpu2H263dRegSet_t *regs = NULL; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + + mpp_env_get_u32("hal_h263d_debug", &hal_h263d_debug, 0); + + mpp_assert(hal); + mpp_assert(cfg); + + regs = mpp_calloc(Vpu2H263dRegSet_t, 1); + if (NULL == regs) { + mpp_err_f("failed to malloc register ret\n"); + ret = MPP_ERR_MALLOC; + goto ERR_RET; + } + + ctx->cfg = cfg; + ctx->regs = (void*)regs; + + return ret; +ERR_RET: + if (regs) { + mpp_free(regs); + regs = NULL; + } + + return ret; +} + +MPP_RET hal_vpu2_h263d_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + + mpp_assert(hal); + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + ctx->cfg = NULL; + + return ret; +} + +MPP_RET hal_vpu2_h263d_gen_regs(void *hal, HalTaskInfo *syn) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + HalDecTask *task = &syn->dec; + MppBuffer buf_frm_curr = NULL; + MppBuffer buf_frm_ref0 = NULL; + MppBuffer buf_pkt = NULL; + Vpu2H263dRegSet_t *regs = (Vpu2H263dRegSet_t*)ctx->regs; + + mpp_assert(task->valid); + mpp_assert(task->input >= 0); + mpp_assert(task->output >= 0); + + memset(regs, 0, sizeof(Vpu2H263dRegSet_t)); + + /* + * basic register configuration setup here + */ + regs->reg54_endian.sw_dec_out_endian = 1; + regs->reg54_endian.sw_dec_in_endian = 1; + regs->reg54_endian.sw_dec_inswap32_e = 1; + regs->reg54_endian.sw_dec_outswap32_e = 1; + regs->reg54_endian.sw_dec_strswap32_e = 1; + regs->reg54_endian.sw_dec_strendian_e = 1; + regs->reg56_axi_ctrl.sw_dec_max_burst = 16; + regs->reg52_error_concealment.sw_apf_threshold = 1; + regs->reg57_enable_ctrl.sw_dec_timeout_e = 1; + regs->reg57_enable_ctrl.sw_dec_clk_gate_e = 1; + regs->reg57_enable_ctrl.sw_dec_e = 1; + regs->reg59.sw_pred_bc_tap_0_0 = -1; + regs->reg59.sw_pred_bc_tap_0_1 = 3; + regs->reg59.sw_pred_bc_tap_0_2 = -6; + regs->reg153.sw_pred_bc_tap_0_3 = 20; + + /* setup buffer for input / output / reference */ + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->input, SLOT_BUFFER, &buf_pkt); + mpp_assert(buf_pkt); + + if (task->input >= 0) + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, task->output, SLOT_BUFFER, &buf_frm_curr); + if (task->refer[0] >= 0) + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, task->refer[0], SLOT_BUFFER, &buf_frm_ref0); + + /* address registers setup first */ + ctx->fd_curr = mpp_buffer_get_fd(buf_frm_curr); + ctx->fd_ref0 = (buf_frm_ref0) ? (mpp_buffer_get_fd(buf_frm_ref0)) : (-1); + regs->reg63_cur_pic_base = (RK_U32)ctx->fd_curr; + regs->reg64_input_stream_base = mpp_buffer_get_fd(buf_pkt); + + /* setup other registers, here will update packet address */ + vpu2_h263d_setup_regs_by_syntax(ctx, task->syntax); + + return ret; +} + +MPP_RET hal_vpu2_h263d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + MppDev dev = ctx->cfg->dev; + RK_U32 *regs = (RK_U32 *)ctx->regs; + + if (hal_h263d_debug & H263D_HAL_DBG_REG_PUT) { + RK_U32 reg_count = (sizeof(Vpu2H263dRegSet_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = regs; + wr_cfg.size = sizeof(Vpu2H263dRegSet_t); + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = sizeof(Vpu2H263dRegSet_t); + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +MPP_RET hal_vpu2_h263d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_h263_ctx *ctx = (hal_h263_ctx *)hal; + MppDev dev = ctx->cfg->dev; + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (hal_h263d_debug & H263D_HAL_DBG_REG_GET) { + RK_U32 *regs = (RK_U32 *)ctx->regs; + RK_U32 reg_count = (sizeof(Vpu2H263dRegSet_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + + (void)task; + return ret; +} + + +const MppHalApi hal_h263d_vdpu2 = { + .name = "h263d_vdpu2", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingH263, + .ctx_size = sizeof(hal_h263_ctx), + .flag = 0, + .init = hal_vpu2_h263d_init, + .deinit = hal_vpu2_h263d_deinit, + .reg_gen = hal_vpu2_h263d_gen_regs, + .start = hal_vpu2_h263d_start, + .wait = hal_vpu2_h263d_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_h263d_vdpu2) diff --git a/mpp/hal/vpu/h263d/hal_h263d_vdpu2.h b/mpp/hal/vpu/h263d/hal_h263d_vdpu2.h new file mode 100644 index 000000000..6b6778f00 --- /dev/null +++ b/mpp/hal/vpu/h263d/hal_h263d_vdpu2.h @@ -0,0 +1,36 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H263D_VDPU2_H +#define HAL_H263D_VDPU2_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET hal_vpu2_h263d_init(void *hal, MppHalCfg *cfg); +MPP_RET hal_vpu2_h263d_deinit(void *hal); +MPP_RET hal_vpu2_h263d_gen_regs(void *hal, HalTaskInfo *syn); +MPP_RET hal_vpu2_h263d_start(void *hal, HalTaskInfo *task); +MPP_RET hal_vpu2_h263d_wait(void *hal, HalTaskInfo *task); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/hal/vpu/h263d/hal_h263d_vdpu2_reg.h b/mpp/hal/vpu/h263d/hal_h263d_vdpu2_reg.h new file mode 100644 index 000000000..2f6f44df2 --- /dev/null +++ b/mpp/hal/vpu/h263d/hal_h263d_vdpu2_reg.h @@ -0,0 +1,399 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H263D_VDPU2_REG_H +#define HAL_H263D_VDPU2_REG_H + +#include "rk_type.h" + +typedef struct { + RK_U32 reg00_49[50]; + + struct { + RK_U32 sw_dec_out_tiled_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_divx_enable : 1; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_priority_mode : 1; + RK_U32 sw_refbu2_thr : 12; + RK_U32 sw_refbu2_picid : 5; + RK_U32 reserve1 : 2; + } reg50_dec_ctrl; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 reserve1 : 1; + RK_U32 sw_init_qp : 6; + RK_U32 reserve2 : 1; + } reg51_stream_info; + + struct { + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + RK_U32 sw_apf_threshold : 14; + RK_U32 sw_reserve : 1; + } reg52_error_concealment; + + RK_U32 reg53_dec_mode; + + struct { + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 reserve3 : 26; + } reg54_endian; + + struct { + RK_U32 sw_dec_irq : 1; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buf_empty_int: 1; + RK_U32 reserve1 : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_b_pic_inf : 1; + RK_U32 reserve2 : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserve3 : 18; + } reg55_Interrupt; + + struct { + RK_U32 sw_dec_axi_rn_id : 8; + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 sw_dec_max_burst : 5; + RK_U32 reserve0 : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 reserve1 : 9; + } reg56_axi_ctrl; + + struct { + RK_U32 sw_dec_e : 1; + RK_U32 sw_refbu2_buf_e : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 reserve : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_start_code_e : 1; + RK_U32 reserve1 : 8; + RK_U32 sw_dec_ahb_hlock_e : 1; + } reg57_enable_ctrl; + + struct { + RK_U32 sw_soft_rst : 1; + RK_U32 reverse0 : 31; + } reg58; + + struct { + RK_U32 reserve : 2; + RK_S32 sw_pred_bc_tap_0_2 : 10; + RK_S32 sw_pred_bc_tap_0_1 : 10; + RK_S32 sw_pred_bc_tap_0_0 : 10; + } reg59; + + RK_U32 reg60_addit_ch_st_base; + RK_U32 reg61_qtable_base; + RK_U32 reg62_directmv_base; + RK_U32 reg63_cur_pic_base; + RK_U32 reg64_input_stream_base; + + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 sw_reserve : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } reg65_refpicbuf_ctrl; + + struct { + RK_U32 build_version : 3; + RK_U32 product_IDen : 1; + RK_U32 minor_version : 8; + RK_U32 major_version : 4; + RK_U32 product_numer : 16; + } reg66_id; + + struct { + RK_U32 sw_reserve : 25; + RK_U32 sw_dec_rtl_rom : 1; + RK_U32 sw_dec_rv_prof : 2; + RK_U32 sw_ref_buff2_exist : 1; + RK_U32 sw_dec_divx_prof : 1; + RK_U32 sw_dec_refbu_ilace : 1; + RK_U32 sw_dec_jpeg_exten : 1; + } reg67_synthesis_cfg; + + struct { + RK_U32 sw_refbu_top_sum : 16; + RK_U32 sw_refbu_bot_sum : 16; + } reg68_sum_of_partitions; + + struct { + RK_U32 sw_refbu_intra_sum : 16; + RK_U32 sw_refbu_hit_sum : 16; + } reg69_sum_inf; + + struct { + RK_U32 sw_refbu_mv_sum : 22; + RK_U32 sw_reserve : 10; + } reg70_sum_mv; + + RK_U32 reg71_119_reserve[49]; + + struct { + RK_U32 sw_reserve0 : 5; + RK_U32 sw_topfieldfirst_e : 1; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } reg120; + + struct { + RK_U32 sw_reserve : 5; + RK_U32 sw_vp7_version : 1; + RK_U32 sw_dc_match0 : 3; + RK_U32 sw_dc_match1 : 3; + RK_U32 sw_eable_bilinear : 1; + RK_U32 sw_remain_mv : 1; + RK_U32 sw_reserve1 : 6; + RK_U32 sw_dct2_start_bit : 6; + RK_U32 sw_dct1_start_bit : 6; + } reg121; + + struct { + RK_U32 sw_vop_time_incr : 16; + RK_U32 sw_intradc_vlc_thr : 3; + RK_U32 sw_ch_qp_offset : 5; + RK_U32 sw_quant_type_1_en : 1; + RK_U32 sw_sync_markers_en : 1; + RK_U32 sw_stream_start_word: 6; + } reg122; + + struct { + RK_U32 sw_dc_comp1 : 16; + RK_U32 sw_dc_comp0 : 16; + } reg123; + + struct { + RK_U32 sw_stream1_len : 24; + RK_U32 sw_coeffs_part_am : 4; + RK_U32 sw_reserve : 4; + } reg124; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_5_3 : 10; + RK_U32 sw_pred_bc_tap_5_2 : 10; + RK_U32 sw_pred_bc_tap_5_1 : 10; + } reg125; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_6_2 : 10; + RK_U32 sw_pred_bc_tap_6_1 : 10; + RK_U32 sw_pred_bc_tap_6_0 : 10; + } reg126; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_7_1 : 10; + RK_U32 sw_pred_bc_tap_7_0 : 10; + RK_U32 sw_pred_bc_tap_6_3 : 10; + } reg127; + + struct { + RK_U32 sw_pred_tap_6_4 : 2; + RK_U32 sw_pred_tap_6_M1 : 2; + RK_U32 sw_pred_tap_4_4 : 2; + RK_U32 sw_pred_tap_4_M1 : 2; + RK_U32 sw_pred_tap_2_4 : 2; + RK_U32 sw_pred_tap_2_M1 : 2; + RK_U32 sw_pred_bc_tap_7_3 : 10; + RK_U32 sw_pred_bc_tap_7_2 : 10; + } reg128; + + struct { + RK_U32 sw_filt_level_3 : 6; + RK_U32 sw_filt_level_2 : 6; + RK_U32 sw_filt_level_1 : 6; + RK_U32 sw_filt_level_0 : 6; + RK_U32 reserve : 8; + } reg129; + + struct { + RK_U32 sw_quant_1 : 11; + RK_U32 sw_quant_0 : 11; + RK_U32 sw_quant_delta_1 : 5; + RK_U32 sw_quant_delta_0 : 5; + } reg130; + + + RK_U32 reg131_ref0_base; + + struct { + RK_U32 sw_filt_mb_adj_3 : 7; + RK_U32 sw_filt_mb_adj_2 : 7; + RK_U32 sw_filt_mb_adj_1 : 7; + RK_U32 sw_filt_mb_adj_0 : 7; + RK_U32 sw_filt_sharpness : 3; + RK_U32 sw_filt_type : 1; + } reg132; + + + struct { + RK_U32 sw_filt_ref_adj_3 : 7; + RK_U32 sw_filt_ref_adj_2 : 7; + RK_U32 sw_filt_ref_adj_1 : 7; + RK_U32 sw_filt_ref_adj_0 : 7; + RK_U32 sw_reserve : 4; + } reg133; + + RK_U32 reg134_ref2_base; + RK_U32 reg135_ref3_base; + + struct { + RK_U32 sw_prev_pic_type : 1; + RK_U32 sw_rounding : 1; + RK_U32 sw_fwd_mv_y_resolution : 1; + RK_U32 sw_vrz_bit_of_bwd_mv : 4; + RK_U32 sw_hrz_bit_of_bwd_mv : 4; + RK_U32 sw_vrz_bit_of_fwd_mv : 4; + RK_U32 sw_hrz_bit_of_fwd_mv : 4; + RK_U32 sw_alt_scan : 1; + RK_U32 sw_reserve : 12; + } reg136; + + struct { + RK_U32 sw_trb_per_trd_d0 : 27; + RK_U32 sw_reserve : 5; + } reg137; + + struct { + RK_U32 sw_trb_per_trd_dm1 : 27; + RK_U32 sw_reserve : 5; + } reg138; + + struct { + RK_U32 sw_trb_per_trd_d1 : 27; + RK_U32 sw_reserve : 5; + } reg139; + + RK_U32 reg_dct_strm_base[5]; + RK_U32 reg145_bitpl_ctrl_base; + RK_U32 reg_dct_strm1_base[2]; + + RK_U32 reg148_ref1_base; + + RK_U32 reg149_segment_map_base; + + + struct { + RK_U32 sw_dct_start_bit_7 : 6; + RK_U32 sw_dct_start_bit_6 : 6; + RK_U32 sw_dct_start_bit_5 : 6; + RK_U32 sw_dct_start_bit_4 : 6; + RK_U32 sw_dct_start_bit_3 : 6; + RK_U32 sw_reserve : 2; + } reg150; + + struct { + RK_U32 sw_quant_3 : 11; + RK_U32 sw_quant_2 : 11; + RK_U32 sw_quant_delta_3 : 5; + RK_U32 sw_quant_delta_2 : 5; + } reg151; + + struct { + RK_U32 sw_quant_5 : 11; + RK_U32 sw_quant_4 : 11; + RK_U32 sw_quant_delta_4 : 5; + RK_U32 sw_reserve : 5; + } reg152; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_1_1 : 10; + RK_U32 sw_pred_bc_tap_1_0 : 10; + RK_U32 sw_pred_bc_tap_0_3 : 10; + } reg153; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_2_0 : 10; + RK_U32 sw_pred_bc_tap_1_3 : 10; + RK_U32 sw_pred_bc_tap_1_2 : 10; + } reg154; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_2_3 : 10; + RK_U32 sw_pred_bc_tap_2_2 : 10; + RK_U32 sw_pred_bc_tap_2_1 : 10; + } reg155; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_3_2 : 10; + RK_U32 sw_pred_bc_tap_3_1 : 10; + RK_U32 sw_pred_bc_tap_3_0 : 10; + } reg156; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_4_1 : 10; + RK_U32 sw_pred_bc_tap_4_0 : 10; + RK_U32 sw_pred_bc_tap_3_3 : 10; + } reg157; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_5_0 : 10; + RK_U32 sw_pred_bc_tap_4_3 : 10; + RK_U32 sw_pred_bc_tap_4_2 : 10; + } reg158; +} Vpu2H263dRegSet_t; + + +#endif + diff --git a/mpp/hal/vpu/h264e/CMakeLists.txt b/mpp/hal/vpu/h264e/CMakeLists.txt new file mode 100644 index 000000000..52af8feee --- /dev/null +++ b/mpp/hal/vpu/h264e/CMakeLists.txt @@ -0,0 +1,16 @@ +# vim: syntax=cmake +include_directories(.) +include_directories(../../common/h264/) +include_directories(../../../codec/enc/h264/) +include_directories(../common/) + +# hal h264 encoder sourse +set(HAL_H264E_SRC) + +add_hal_source(HAL_H264E_SRC HAVE_VEPU2 hal_h264e_vepu2_v2.c) +add_hal_source(HAL_H264E_SRC HAVE_VEPU1 hal_h264e_vepu1_v2.c) + +if (HAL_H264E_SRC) + list(APPEND HAL_H264E_SRC hal_h264e_vpu_tbl.c hal_h264e_vepu_v2.c) + add_library(hal_h264e_vpu OBJECT ${HAL_H264E_SRC}) +endif() diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu1_reg_tbl.h b/mpp/hal/vpu/h264e/hal_h264e_vepu1_reg_tbl.h new file mode 100644 index 000000000..3eca1a0c1 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu1_reg_tbl.h @@ -0,0 +1,232 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU1_REG_TBL_H +#define HAL_H264E_VEPU1_REG_TBL_H + +#include "rk_type.h" + +/* RK3288 Encoder registers. */ +#define VEPU_REG_INTERRUPT 0x004 +#define VEPU_REG_INTERRUPT_SLICE_READY MPP_BIT(8) +#define VEPU_REG_INTERRUPT_TIMEOUT MPP_BIT(6) +#define VEPU_REG_INTERRUPT_BUFFER_FULL MPP_BIT(5) +#define VEPU_REG_INTERRUPT_RESET MPP_BIT(4) +#define VEPU_REG_INTERRUPT_BUS_ERROR MPP_BIT(3) +#define VEPU_REG_INTERRUPT_FRAME_READY MPP_BIT(2) +#define VEPU_REG_INTERRUPT_DIS_BIT MPP_BIT(1) +#define VEPU_REG_INTERRUPT_BIT MPP_BIT(0) + +#define VEPU_REG_AXI_CTRL 0x008 +#define VEPU_REG_AXI_CTRL_WRITE_ID(x) (((x) & 0xff) << 24) +#define VEPU_REG_AXI_CTRL_READ_ID(x) (((x) & 0xff) << 16) +#define VEPU_REG_OUTPUT_SWAP16 MPP_BIT(15) +#define VEPU_REG_INPUT_SWAP16 MPP_BIT(14) +#define VEPU_REG_INPUT_SWAP16_(x) (((x) & 1) << 14) +#define VEPU_REG_AXI_CTRL_BURST_LEN(x) (((x) & 0x3f) << 8) +#define VEPU_REG_AXI_CTRL_BURST_DISABLE MPP_BIT(7) +#define VEPU_REG_AXI_CTRL_INCREMENT_MODE MPP_BIT(6) +#define VEPU_REG_AXI_CTRL_BURST_DISCARD MPP_BIT(5) +#define VEPU_REG_CLK_GATING_EN MPP_BIT(4) +#define VEPU_REG_OUTPUT_SWAP32 MPP_BIT(3) +#define VEPU_REG_INPUT_SWAP32 MPP_BIT(2) +#define VEPU_REG_INPUT_SWAP32_(x) (((x) & 1) << 2) +#define VEPU_REG_OUTPUT_SWAP8 MPP_BIT(1) +#define VEPU_REG_INPUT_SWAP8 MPP_BIT(0) +#define VEPU_REG_INPUT_SWAP8_(x) ((x) & 1) + +#define VEPU_REG_ADDR_OUTPUT_STREAM 0x014 +#define VEPU_REG_ADDR_OUTPUT_CTRL 0x018 +#define VEPU_REG_ADDR_REF_LUMA 0x01c +#define VEPU_REG_ADDR_REF_CHROMA 0x020 + +#define VEPU_REG_ADDR_REC_LUMA 0x024 +#define VEPU_REG_ADDR_REC_CHROMA 0x028 + +#define VEPU_REG_ADDR_IN_LUMA 0x02c +#define VEPU_REG_ADDR_IN_CB 0x030 +#define VEPU_REG_ADDR_IN_CR 0x034 + +#define VEPU_REG_ENCODE_CTRL 0x038 +#define VEPU_REG_INTERRUPT_TIMEOUT_EN MPP_BIT(31) +#define VEPU_REG_MV_WRITE_EN MPP_BIT(30) +#define VEPU_REG_SIZE_TABLE_PRESENT MPP_BIT(29) +#define VEPU_REG_INTERRUPT_SLICE_READY_EN MPP_BIT(28) +#define VEPU_REG_MB_WIDTH(x) (((x) & 0x1ff) << 19) +#define VEPU_REG_MB_HEIGHT(x) (((x) & 0x1ff) << 10) +#define VEPU_REG_RECON_WRITE_DIS MPP_BIT(6) +#define VEPU_REG_PIC_TYPE(x) (((x) & 0x3) << 3) +#define VEPU_REG_ENCODE_FORMAT(x) (((x) & 0x3) << 1) +#define VEPU_REG_ENCODE_ENABLE MPP_BIT(0) + +#define VEPU_REG_ENC_INPUT_IMAGE_CTRL 0x03c +#define VEPU_REG_IN_IMG_CHROMA_OFFSET(x) (((x) & 0x7) << 29) +#define VEPU_REG_IN_IMG_LUMA_OFFSET(x) (((x) & 0x7) << 26) +#define VEPU_REG_IN_IMG_CTRL_ROW_LEN(x) (((x) & 0x3fff) << 12) +#define VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(x) (((x) & 0x3) << 10) +#define VEPU_REG_IN_IMG_CTRL_OVRFLB(x) (((x) & 0xf) << 6) +#define VEPU_REG_IN_IMG_CTRL_FMT(x) (((x) & 0xf) << 2) +#define VEPU_REG_IN_IMG_ROTATE_MODE(x) (((x) & 0x3) << 0) + +#define VEPU_REG_ENC_CTRL0 0x040 +#define VEPU_REG_PPS_INIT_QP(x) (((x) & 0x3f) << 26) +#define VEPU_REG_SLICE_FILTER_ALPHA(x) (((x) & 0xf) << 22) +#define VEPU_REG_SLICE_FILTER_BETA(x) (((x) & 0xf) << 18) +#define VEPU_REG_CHROMA_QP_OFFSET(x) (((x) & 0x1f) << 13) +#define VEPU_REG_IDR_PIC_ID(x) (((x) & 0xf) << 1) +#define VEPU_REG_CONSTRAINED_INTRA_PREDICTION MPP_BIT(0) + +#define VEPU_REG_ENC_CTRL1 0x044 +#define VEPU_REG_PPS_ID(x) (((x) & 0xff) << 24) +#define VEPU_REG_INTRA_PRED_MODE(x) (((x) & 0xff) << 16) +#define VEPU_REG_FRAME_NUM(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_ENC_CTRL2 0x048 +#define VEPU_REG_DEBLOCKING_FILTER_MODE(x) (((x) & 0x3) << 30) +#define VEPU_REG_H264_SLICE_SIZE(x) (((x) & 0x7f) << 23) +#define VEPU_REG_DISABLE_QUARTER_PIXEL_MV MPP_BIT(22) +#define VEPU_REG_H264_TRANS8X8_MODE MPP_BIT(21) +#define VEPU_REG_CABAC_INIT_IDC(x) (((x) & 0x3) << 19) +#define VEPU_REG_ENTROPY_CODING_MODE MPP_BIT(18) +#define VEPU_REG_H264_INTER4X4_MODE MPP_BIT(17) +#define VEPU_REG_H264_STREAM_MODE MPP_BIT(16) +#define VEPU_REG_INTRA16X16_MODE(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_ENC_CTRL3 0x04c +#define VEPU_REG_SPLIT_MV_MODE_EN MPP_BIT(30) +#define VEPU_REG_QMV_PENALTY(x) (((x) & 0x3ff) << 20) +#define VEPU_REG_4MV_PENALTY(x) (((x) & 0x3ff) << 10) +#define VEPU_REG_1MV_PENALTY(x) (((x) & 0x3ff) << 0) + +#define VEPU_REG_ENC_CTRL_4 0x054 +#define VEPU_REG_SKIP_MACROBLOCK_PENALTY(x) (((x) & 0xff) << 24) +#define VEPU_REG_COMPLETED_SLICES(x) (((x) & 0xff) << 16) +#define VEPU_REG_INTER_MODE(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_STR_HDR_REM_MSB 0x058 +#define VEPU_REG_STR_HDR_REM_LSB 0x05c +#define VEPU_REG_STR_BUF_LIMIT 0x060 + +#define VEPU_REG_MAD_CTRL 0x064 +#define VEPU_REG_MAD_QP_ADJUSTMENT(x) (((x) & 0xf) << 28) +#define VEPU_REG_MAD_THRESHOLD(x) (((x) & 0x3f) << 22) +#define VEPU_REG_QP_SUM(x) (((x) & 0x001fffff) * 2) + +#define VEPU_REG_QP_VAL 0x06c +#define VEPU_REG_H264_LUMA_INIT_QP(x) (((x) & 0x3f) << 26) +#define VEPU_REG_H264_QP_MAX(x) (((x) & 0x3f) << 20) +#define VEPU_REG_H264_QP_MIN(x) (((x) & 0x3f) << 14) +#define VEPU_REG_H264_CHKPT_DISTANCE(x) (((x) & 0xfff) << 0) + +#define VEPU_REG_CHECKPOINT(i) (0x070 + ((i) * 0x4)) +#define VEPU_REG_CHECKPOINT_CHECK0(x) (((x) & 0xffff)) +#define VEPU_REG_CHECKPOINT_CHECK1(x) (((x) & 0xffff) << 16) +#define VEPU_REG_CHECKPOINT_RESULT(x) ((((x) >> (16 - 16 \ + * (i & 1))) & 0xffff) \ + * 32) + +#define VEPU_REG_CHKPT_WORD_ERR(i) (0x084 + ((i) * 0x4)) +#define VEPU_REG_CHKPT_WORD_ERR_CHK0(x) (((x) & 0xffff)) +#define VEPU_REG_CHKPT_WORD_ERR_CHK1(x) (((x) & 0xffff) << 16) + +#define VEPU_REG_CHKPT_DELTA_QP 0x090 +#define VEPU_REG_CHKPT_DELTA_QP_CHK0(x) (((x) & 0x0f) << 0) +#define VEPU_REG_CHKPT_DELTA_QP_CHK1(x) (((x) & 0x0f) << 4) +#define VEPU_REG_CHKPT_DELTA_QP_CHK2(x) (((x) & 0x0f) << 8) +#define VEPU_REG_CHKPT_DELTA_QP_CHK3(x) (((x) & 0x0f) << 12) +#define VEPU_REG_CHKPT_DELTA_QP_CHK4(x) (((x) & 0x0f) << 16) +#define VEPU_REG_CHKPT_DELTA_QP_CHK5(x) (((x) & 0x0f) << 20) +#define VEPU_REG_CHKPT_DELTA_QP_CHK6(x) (((x) & 0x0f) << 24) + +#define VEPU_REG_RLC_CTRL 0x094 +#define VEPU_REG_STREAM_START_OFFSET(x) (((x) & 0x3f) << 23) +#define VEPU_REG_RLC_SUM (((x) & 0x007fffff) << 0) +#define VEPU_REG_RLC_SUM_OUT(x) (((x) & 0x007fffff) * 4) + +#define VEPU_REG_MB_CTRL 0x098 +#define VEPU_REG_MB_CNT_SET(x) (((x) & 0xffff) << 16) +#define VEPU_REG_MB_CNT_OUT(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_ADDR_NEXT_PIC 0x09c + +#define VEPU_REG_STABLILIZATION_OUTPUT 0x0a0 +#define VEPU_REG_STABLE_MODE_SEL(x) (((x) & 0x3) << 30) +#define VEPU_REG_STABLE_MIN_VALUE(x) (((x) & 0xffffff) << 0) + +#define VEPU_REG_STABLE_MOTION_SUM 0x0a4 +#define VEPU_REG_ADDR_CABAC_TBL 0x0cc +#define VEPU_REG_ADDR_MV_OUT 0x0d0 + +#define VEPU_REG_RGB2YUV_CONVERSION_COEF1 0x0d4 +#define VEPU_REG_RGB2YUV_CONVERSION_COEFB(x) (((x) & 0xffff) << 16) +#define VEPU_REG_RGB2YUV_CONVERSION_COEFA(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_RGB2YUV_CONVERSION_COEF2 0x0d8 +#define VEPU_REG_RGB2YUV_CONVERSION_COEFE(x) (((x) & 0xffff) << 16) +#define VEPU_REG_RGB2YUV_CONVERSION_COEFC(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_RGB_MASK_MSB 0x0dc +#define VEPU_REG_RGB_MASK_B_MSB(x) (((x) & 0x1f) << 26) +#define VEPU_REG_RGB_MASK_G_MSB(x) (((x) & 0x1f) << 21) +#define VEPU_REG_RGB_MASK_R_MSB(x) (((x) & 0x1f) << 16) +#define VEPU_REG_RGB2YUV_CONVERSION_COEFF(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_INTRA_AREA_CTRL 0x0e0 +#define VEPU_REG_INTRA_AREA_LEFT(x) (((x) & 0xff) << 24) +#define VEPU_REG_INTRA_AREA_RIGHT(x) (((x) & 0xff) << 16) +#define VEPU_REG_INTRA_AREA_TOP(x) (((x) & 0xff) << 8) +#define VEPU_REG_INTRA_AREA_BOTTOM(x) (((x) & 0xff) << 0) + +#define VEPU_REG_CIR_INTRA_CTRL 0x0e4 +#define VEPU_REG_CIR_INTRA_FIRST_MB(x) (((x) & 0xffff) << 16) +#define VEPU_REG_CIR_INTRA_INTERVAL(x) (((x) & 0xffff) << 0) + +#define VEPU_REG_ROI1 0x0f0 +#define VEPU_REG_ROI1_LEFT_MB(x) (((x) & 0xff) << 24) +#define VEPU_REG_ROI1_RIGHT_MB(x) (((x) & 0xff) << 16) +#define VEPU_REG_ROI1_TOP_MB(x) (((x) & 0xff) << 8) +#define VEPU_REG_ROI1_BOTTOM_MB(x) (((x) & 0xff) << 0) + +#define VEPU_REG_ROI2 0x0f4 +#define VEPU_REG_ROI2_LEFT_MB(x) (((x) & 0xff) << 24) +#define VEPU_REG_ROI2_RIGHT_MB(x) (((x) & 0xff) << 16) +#define VEPU_REG_ROI2_TOP_MB(x) (((x) & 0xff) << 8) +#define VEPU_REG_ROI2_BOTTOM_MB(x) (((x) & 0xff) << 0) + +#define VEPU_REG_MVC_RELATE 0x0f8 +#define VEPU_REG_ZERO_MV_FAVOR_D2(x) (((x) & 0xf) << 28) +#define VEPU_REG_PENALTY_4X4MV(x) (((x) & 0x1ff) << 19) +#define VEPU_REG_MVC_PRIORITY_ID(x) (((x) & 0x7) << 16) +#define VEPU_REG_MVC_VIEW_ID(x) (((x) & 0x7) << 13) +#define VEPU_REG_MVC_TEMPORAL_ID(x) (((x) & 0x7) << 10) +#define VEPU_REG_MVC_ANCHOR_PIC_FLAG MPP_BIT(9) +#define VEPU_REG_MVC_INTER_VIEW_FLAG MPP_BIT(8) +#define VEPU_REG_ROI_QP_DELTA_1 (((x) & 0xf) << 4) +#define VEPU_REG_ROI_QP_DELTA_2 (((x) & 0xf) << 0) + +#define VEPU_REG_DMV_PENALTY_TBL(i) (0x180 + ((i) * 0x4)) +#define VEPU_REG_DMV_PENALTY_TABLE_BIT(x, i) (x << i * 8) + +#define VEPU_REG_DMV_Q_PIXEL_PENALTY_TBL(i) (0x200 + ((i) * 0x4)) +#define VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(x, i) (x << i * 8) + +#define VEPU1_H264E_NUM_REGS 164 + +typedef struct H264eVpu1RegSet_t { + RK_U32 val[VEPU1_H264E_NUM_REGS]; +} H264eVpu1RegSet; + +#endif diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.c b/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.c new file mode 100644 index 000000000..f07fe0eb2 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.c @@ -0,0 +1,750 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264e_vepu1_v2" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_frame.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_rc.h" +#include "mpp_packet_impl.h" + +#include "mpp_enc_hal.h" +#include "h264e_debug.h" +#include "h264e_sps.h" +#include "h264e_pps.h" +#include "h264e_slice.h" + +#include "hal_h264e_debug.h" +#include "hal_h264e_vpu_tbl.h" +#include "hal_h264e_vepu_v2.h" +#include "hal_h264e_stream_amend.h" + +#include "hal_h264e_vepu1_reg_tbl.h" + +typedef struct HalH264eVepu1Ctx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_S32 frame_cnt; + + /* buffers management */ + HalH264eVepuBufs hw_bufs; + + /* preprocess config */ + HalH264eVepuPrep hw_prep; + + /* input / recon / refer address config */ + HalH264eVepuAddr hw_addr; + VepuOffsetCfg hw_offset; + + /* macroblock ratecontrol config */ + HalH264eVepuMbRc hw_mbrc; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eSlice *slice; + H264eFrmInfo *frms; + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + H264ePrefixNal *prefix; + + /* special TSVC stream header fixup */ + HalH264eVepuStreamAmend amend; + + /* vepu1 macroblock ratecontrol context */ + HalH264eVepuMbRcCtx rc_ctx; + + H264eVpu1RegSet regs_set; + H264eVpu1RegSet regs_get; +} HalH264eVepu1Ctx; + +static MPP_RET hal_h264e_vepu1_deinit_v2(void *hal) +{ + HalH264eVepu1Ctx *p = (HalH264eVepu1Ctx *)hal; + + hal_h264e_dbg_func("enter %p\n", p); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + h264e_vepu_buf_deinit(&p->hw_bufs); + + if (p->rc_ctx) { + h264e_vepu_mbrc_deinit(p->rc_ctx); + p->rc_ctx = NULL; + } + + h264e_vepu_stream_amend_deinit(&p->amend); + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu1_init_v2(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu1Ctx *p = (HalH264eVepu1Ctx *)hal; + MPP_RET ret = MPP_OK; + + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_VEPU1; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + + ret = h264e_vepu_buf_init(&p->hw_bufs); + if (ret) { + mpp_err_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + ret = h264e_vepu_mbrc_init(&p->rc_ctx, &p->hw_mbrc); + if (ret) { + mpp_err_f("init mb rate control failed ret: %d\n", ret); + goto DONE; + } + + /* create buffer to TSVC stream */ + h264e_vepu_stream_amend_init(&p->amend); + +DONE: + if (ret) + hal_h264e_vepu1_deinit_v2(hal); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +static RK_U32 update_vepu1_syntax(HalH264eVepu1Ctx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu1_get_task_v2(void *hal, HalEncTask *task) +{ + HalH264eVepu1Ctx *ctx = (HalH264eVepu1Ctx *)hal; + RK_U32 updated = update_vepu1_syntax(ctx, &task->syntax); + MppEncPrepCfg *prep = &ctx->cfg->prep; + HalH264eVepuPrep *hw_prep = &ctx->hw_prep; + HalH264eVepuAddr *hw_addr = &ctx->hw_addr; + HalH264eVepuBufs *hw_bufs = &ctx->hw_bufs; + VepuOffsetCfg *hw_offset = &ctx->hw_offset; + H264eFrmInfo *frms = ctx->frms; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) { + h264e_vepu_buf_set_frame_size(hw_bufs, prep->width, prep->height); + + /* preprocess setup */ + if (h264e_vepu_prep_setup(hw_prep, prep)) + return MPP_NOK; + + h264e_vepu_mbrc_setup(ctx->rc_ctx, ctx->cfg); + } + + if (updated & SYN_TYPE_FLAG(H264E_SYN_SLICE)) { + H264eSlice *slice = ctx->slice; + + h264e_vepu_buf_set_cabac_idc(hw_bufs, slice->cabac_init_idc); + } + + h264e_vepu_prep_get_addr(hw_prep, task->input, &hw_addr->orig); + + MppBuffer recn = h264e_vepu_buf_get_frame_buffer(hw_bufs, frms->curr_idx); + MppBuffer refr = h264e_vepu_buf_get_frame_buffer(hw_bufs, frms->refr_idx); + + hw_addr->recn[0] = mpp_buffer_get_fd(recn); + hw_addr->refr[0] = mpp_buffer_get_fd(refr); + hw_addr->recn[1] = hw_addr->recn[0]; + hw_addr->refr[1] = hw_addr->refr[0]; + + hw_offset->fmt = prep->format; + hw_offset->width = prep->width; + hw_offset->height = prep->height; + hw_offset->hor_stride = prep->hor_stride; + hw_offset->ver_stride = prep->ver_stride; + hw_offset->offset_x = mpp_frame_get_offset_x(task->frame); + hw_offset->offset_y = mpp_frame_get_offset_y(task->frame); + + get_vepu_offset_cfg(hw_offset); + + h264e_vepu_stream_amend_config(&ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_S32 setup_output_packet(HalH264eVepu1Ctx *ctx, RK_U32 *reg, MppBuffer buf, RK_U32 offset) +{ + RK_U32 offset8 = offset & (~0x7); + RK_S32 fd = mpp_buffer_get_fd(buf); + RK_U32 hdr_rem_msb = 0; + RK_U32 hdr_rem_lsb = 0; + RK_U32 limit = 0; + + if (offset) { + RK_U8 *buf32 = (RK_U8 *)mpp_buffer_get_ptr(buf) + offset8; + + hdr_rem_msb = MPP_RB32(buf32); + hdr_rem_lsb = MPP_RB32(buf32 + 4); + } + + hal_h264e_dbg_detail("offset %d offset8 %d\n", offset, offset8); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_OUTPUT_STREAM, fd); + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_OUTPUT_STREAM >> 2, offset8); + + /* output buffer size is 64 bit address then 8 multiple size */ + limit = mpp_buffer_get_size(buf); + limit -= offset8; + limit >>= 3; + limit &= ~7; + H264E_HAL_SET_REG(reg, VEPU_REG_STR_BUF_LIMIT, limit); + + hal_h264e_dbg_detail("msb %08x lsb %08x", hdr_rem_msb, hdr_rem_lsb); + + H264E_HAL_SET_REG(reg, VEPU_REG_STR_HDR_REM_MSB, hdr_rem_msb); + H264E_HAL_SET_REG(reg, VEPU_REG_STR_HDR_REM_LSB, hdr_rem_lsb); + + return (offset - offset8) * 8; +} + +static MPP_RET hal_h264e_vepu1_gen_regs_v2(void *hal, HalEncTask *task) +{ + //MPP_RET ret = MPP_OK; + HalH264eVepu1Ctx *ctx = (HalH264eVepu1Ctx *)hal; + HalH264eVepuBufs *hw_bufs = &ctx->hw_bufs; + HalH264eVepuPrep *hw_prep = &ctx->hw_prep; + HalH264eVepuAddr *hw_addr = &ctx->hw_addr; + HalH264eVepuMbRc *hw_mbrc = &ctx->hw_mbrc; + VepuOffsetCfg *hw_offset = &ctx->hw_offset; + EncRcTaskInfo *rc_info = &task->rc_task->info; + EncFrmStatus *frm = &task->rc_task->frm; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + RK_U32 *reg = ctx->regs_set.val; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 offset = mpp_packet_get_length(task->packet); + RK_U32 first_free_bit = 0; + RK_U32 val = 0; + RK_S32 i = 0; + + if (hw_prep->rotation) { + mb_w = ctx->sps->pic_height_in_mbs; + mb_h = ctx->sps->pic_width_in_mbs; + } + + hw_mbrc->qp_init = rc_info->quality_target; + hw_mbrc->qp_max = rc_info->quality_max; + hw_mbrc->qp_min = rc_info->quality_min; + + hal_h264e_dbg_func("enter %p\n", hal); + + hal_h264e_dbg_detail("frame %d generate regs now", frm->seq_idx); + + // prepare mb rc config + h264e_vepu_mbrc_prepare(ctx->rc_ctx, &ctx->hw_mbrc, task->rc_task); + + h264e_vepu_slice_split_cfg(ctx->slice, &ctx->hw_mbrc, task->rc_task, ctx->cfg); + + /* setup output address with offset */ + first_free_bit = setup_output_packet(ctx, reg, task->output, offset); + /* set extra byte for header */ + hw_mbrc->hdr_strm_size = offset; + hw_mbrc->hdr_free_size = first_free_bit / 8; + hw_mbrc->out_strm_size = 0; + + /* + * The hardware needs only the value for luma plane, because + * values of other planes are calculated internally based on + * format setting. + */ + val = VEPU_REG_INTRA_AREA_TOP(mb_h) + | VEPU_REG_INTRA_AREA_BOTTOM(mb_h) + | VEPU_REG_INTRA_AREA_LEFT(mb_w) + | VEPU_REG_INTRA_AREA_RIGHT(mb_w); + H264E_HAL_SET_REG(reg, VEPU_REG_INTRA_AREA_CTRL, val); //FIXED + + val = VEPU_REG_AXI_CTRL_WRITE_ID(0) + | VEPU_REG_AXI_CTRL_READ_ID(0) + | VEPU_REG_OUTPUT_SWAP16 + | VEPU_REG_INPUT_SWAP16_(hw_prep->swap_16_in) + | VEPU_REG_AXI_CTRL_BURST_LEN(16) + | VEPU_REG_OUTPUT_SWAP32 + | VEPU_REG_INPUT_SWAP32_(hw_prep->swap_32_in) + | VEPU_REG_OUTPUT_SWAP8 + | VEPU_REG_INPUT_SWAP8_(hw_prep->swap_8_in); + H264E_HAL_SET_REG(reg, VEPU_REG_AXI_CTRL, val); + + val = VEPU_REG_MAD_QP_ADJUSTMENT (hw_mbrc->mad_qp_change) + | VEPU_REG_MAD_THRESHOLD(hw_mbrc->mad_threshold); + H264E_HAL_SET_REG(reg, VEPU_REG_MAD_CTRL, val); + + val = 0; + if (mb_w * mb_h > 3600) + val = VEPU_REG_DISABLE_QUARTER_PIXEL_MV; + val |= VEPU_REG_CABAC_INIT_IDC(slice->cabac_init_idc); + if (pps->entropy_coding_mode) + val |= VEPU_REG_ENTROPY_CODING_MODE; + if (pps->transform_8x8_mode) + val |= VEPU_REG_H264_TRANS8X8_MODE; + if (sps->profile_idc > 31) + val |= VEPU_REG_H264_INTER4X4_MODE; + /*reg |= VEPU_REG_H264_STREAM_MODE;*/ + val |= VEPU_REG_H264_SLICE_SIZE(hw_mbrc->slice_size_mb_rows) + | VEPU_REG_INTRA16X16_MODE(h264_intra16_favor[hw_mbrc->qp_init]); + + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL2, val); + + RK_U32 scaler = MPP_MAX(1, 200 / (mb_w + mb_h)); + RK_U32 skip_penalty = MPP_MIN(255, h264_skip_sad_penalty[hw_mbrc->qp_init] * scaler); + RK_U32 overfill_r = ((hw_prep->src_w & 0x0f) != 0) ? + ((16 - (hw_prep->src_w & 0x0f)) / 4) : 0; + RK_U32 overfill_b = ((hw_prep->src_h & 0x0f) != 0) ? + (16 - (hw_prep->src_h & 0x0f)) : 0; + + val = VEPU_REG_SKIP_MACROBLOCK_PENALTY(skip_penalty) + | VEPU_REG_INTER_MODE(h264_inter_favor[hw_mbrc->qp_init]); + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL_4, val); + + val = VEPU_REG_STREAM_START_OFFSET(first_free_bit); + H264E_HAL_SET_REG(reg, VEPU_REG_RLC_CTRL, val); + + // When offset is zero row length should be total 16 aligned width + val = VEPU_REG_IN_IMG_CHROMA_OFFSET(0) + | VEPU_REG_IN_IMG_LUMA_OFFSET(0) + | VEPU_REG_IN_IMG_CTRL_ROW_LEN(hw_prep->pixel_stride) + | VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r) + | VEPU_REG_IN_IMG_CTRL_OVRFLB(overfill_b) + | VEPU_REG_IN_IMG_CTRL_FMT(hw_prep->src_fmt) + | VEPU_REG_IN_IMG_ROTATE_MODE(hw_prep->rotation); + + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_INPUT_IMAGE_CTRL, val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[0]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[1]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(0), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[2]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[3]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(1), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[4]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[5]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(2), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[6]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[7]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(3), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[8]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[9]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(4), val); + + val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[0]) + | VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[1]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(0), val); + + val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[2]) + | VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[3]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(1), val); + + val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[4]) + | VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[5]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(2), val); + + val = VEPU_REG_CHKPT_DELTA_QP_CHK6(hw_mbrc->cp_delta_qp[6]) + | VEPU_REG_CHKPT_DELTA_QP_CHK5(hw_mbrc->cp_delta_qp[5]) + | VEPU_REG_CHKPT_DELTA_QP_CHK4(hw_mbrc->cp_delta_qp[4]) + | VEPU_REG_CHKPT_DELTA_QP_CHK3(hw_mbrc->cp_delta_qp[3]) + | VEPU_REG_CHKPT_DELTA_QP_CHK2(hw_mbrc->cp_delta_qp[2]) + | VEPU_REG_CHKPT_DELTA_QP_CHK1(hw_mbrc->cp_delta_qp[1]) + | VEPU_REG_CHKPT_DELTA_QP_CHK0(hw_mbrc->cp_delta_qp[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_DELTA_QP, val); + + val = VEPU_REG_PPS_INIT_QP(pps->pic_init_qp) + | VEPU_REG_SLICE_FILTER_ALPHA(slice->slice_alpha_c0_offset_div2) + | VEPU_REG_SLICE_FILTER_BETA(slice->slice_beta_offset_div2) + | VEPU_REG_CHROMA_QP_OFFSET(pps->chroma_qp_index_offset) + | VEPU_REG_IDR_PIC_ID(slice->idr_pic_id); + + if (pps->constrained_intra_pred) + val |= VEPU_REG_CONSTRAINED_INTRA_PREDICTION; + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL0, val); + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_NEXT_PIC, 0); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_MV_OUT, 0); + + MppBuffer cabac_table = hw_bufs->cabac_table; + RK_S32 cabac_table_fd = cabac_table ? mpp_buffer_get_fd(cabac_table) : 0; + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_CABAC_TBL, cabac_table_fd); + + val = VEPU_REG_ROI1_TOP_MB(mb_h) + | VEPU_REG_ROI1_BOTTOM_MB(mb_h) + | VEPU_REG_ROI1_LEFT_MB(mb_w) + | VEPU_REG_ROI1_RIGHT_MB(mb_w); + H264E_HAL_SET_REG(reg, VEPU_REG_ROI1, val); + + val = VEPU_REG_ROI2_TOP_MB(mb_h) + | VEPU_REG_ROI2_BOTTOM_MB(mb_h) + | VEPU_REG_ROI2_LEFT_MB(mb_w) + | VEPU_REG_ROI2_RIGHT_MB(mb_w); + H264E_HAL_SET_REG(reg, VEPU_REG_ROI2, val); + H264E_HAL_SET_REG(reg, VEPU_REG_STABLILIZATION_OUTPUT, 0); + + val = VEPU_REG_RGB2YUV_CONVERSION_COEFB(hw_prep->color_conversion_coeff_b) + | VEPU_REG_RGB2YUV_CONVERSION_COEFA(hw_prep->color_conversion_coeff_a); + H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF1, val); + + val = VEPU_REG_RGB2YUV_CONVERSION_COEFE(hw_prep->color_conversion_coeff_e) + | VEPU_REG_RGB2YUV_CONVERSION_COEFC(hw_prep->color_conversion_coeff_c); + H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF2, val); + + val = VEPU_REG_RGB2YUV_CONVERSION_COEFF(hw_prep->color_conversion_coeff_f) + | VEPU_REG_RGB_MASK_B_MSB(hw_prep->b_mask_msb) + | VEPU_REG_RGB_MASK_G_MSB(hw_prep->g_mask_msb) + | VEPU_REG_RGB_MASK_R_MSB(hw_prep->r_mask_msb); + H264E_HAL_SET_REG(reg, VEPU_REG_RGB_MASK_MSB, val); + + { + RK_U32 diff_mv_penalty[3] = {0}; + diff_mv_penalty[0] = h264_diff_mv_penalty4p[hw_mbrc->qp_init]; + diff_mv_penalty[1] = h264_diff_mv_penalty[hw_mbrc->qp_init]; + diff_mv_penalty[2] = h264_diff_mv_penalty[hw_mbrc->qp_init]; + + val = VEPU_REG_1MV_PENALTY(diff_mv_penalty[1]) + | VEPU_REG_QMV_PENALTY(diff_mv_penalty[2]) + | VEPU_REG_4MV_PENALTY(diff_mv_penalty[0]); + } + + val |= VEPU_REG_SPLIT_MV_MODE_EN; + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL3, val); + + val = VEPU_REG_H264_LUMA_INIT_QP(hw_mbrc->qp_init) + | VEPU_REG_H264_QP_MAX(hw_mbrc->qp_max) + | VEPU_REG_H264_QP_MIN(hw_mbrc->qp_min) + | VEPU_REG_H264_CHKPT_DISTANCE(hw_mbrc->cp_distance_mbs); + H264E_HAL_SET_REG(reg, VEPU_REG_QP_VAL, val); + + val = VEPU_REG_ZERO_MV_FAVOR_D2(10); + H264E_HAL_SET_REG(reg, VEPU_REG_MVC_RELATE, val); + + val = VEPU_REG_PPS_ID(pps->pps_id) + | VEPU_REG_INTRA_PRED_MODE(h264_prev_mode_favor[hw_mbrc->qp_init]) + | VEPU_REG_FRAME_NUM(slice->frame_num); + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL1, val); + + { + RK_U8 dmv_penalty[128] = {0}; + RK_U8 dmv_qpel_penalty[128] = {0}; + + for (i = 0; i < 128; i++) { + dmv_penalty[i] = i; + dmv_qpel_penalty[i] = MPP_MIN(255, exp_golomb_signed(i)); + } + + for (i = 0; i < 128; i += 4) { + val = VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i], 3); + val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 1], 2); + val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 2], 1); + val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 3], 0); + H264E_HAL_SET_REG(reg, VEPU_REG_DMV_PENALTY_TBL(i / 4), val); + + val = VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(dmv_qpel_penalty[i], 3); + val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(dmv_qpel_penalty[i + 1], 2); + val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(dmv_qpel_penalty[i + 2], 1); + val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(dmv_qpel_penalty[i + 3], 0); + H264E_HAL_SET_REG(reg, VEPU_REG_DMV_Q_PIXEL_PENALTY_TBL(i / 4), val); + } + } + + /* set buffers addr */ + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_LUMA, hw_addr->orig[0]); + if (hw_offset->offset_byte[0]) + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_IN_LUMA >> 2, + hw_offset->offset_byte[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_CB, hw_addr->orig[1]); + if (hw_offset->offset_byte[1]) + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_IN_CB >> 2, + hw_offset->offset_byte[1]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_CR, hw_addr->orig[2]); + if (hw_offset->offset_byte[2]) + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_IN_CR >> 2, + hw_offset->offset_byte[2]); + + MppBuffer nal_size_table = h264e_vepu_buf_get_nal_size_table(hw_bufs); + RK_S32 nal_size_table_fd = nal_size_table ? mpp_buffer_get_fd(nal_size_table) : 0; + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_OUTPUT_CTRL, nal_size_table_fd); + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REC_LUMA, hw_addr->recn[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REC_CHROMA, hw_addr->recn[1]); + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_REC_CHROMA >> 2, hw_bufs->yuv_size); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REF_LUMA, hw_addr->refr[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REF_CHROMA, hw_addr->refr[1]); + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_REF_CHROMA >> 2, hw_bufs->yuv_size); + + /* set important encode mode info */ + val = VEPU_REG_INTERRUPT_TIMEOUT_EN + | VEPU_REG_SIZE_TABLE_PRESENT + | VEPU_REG_MB_HEIGHT(mb_h) + | VEPU_REG_MB_WIDTH(mb_w) + | VEPU_REG_PIC_TYPE(slice->idr_flag) + | VEPU_REG_ENCODE_FORMAT(3) + | VEPU_REG_ENCODE_ENABLE; + H264E_HAL_SET_REG(reg, VEPU_REG_ENCODE_CTRL, val); + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu1_start_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_NOK; + HalH264eVepu1Ctx *ctx = (HalH264eVepu1Ctx *)hal; + (void)task; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (ctx->dev) { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = sizeof(ctx->regs_set); + + do { + wr_cfg.reg = &ctx->regs_set; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &ctx->regs_get; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + } else + mpp_err("invalid NULL device ctx\n"); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static void h264e_vepu1_get_mbrc(HalH264eVepuMbRc *mb_rc, H264eVpu1RegSet *reg) +{ + RK_S32 i = 0; + RK_U32 cpt_prev = 0; + RK_U32 overflow = 0; + RK_U32 cpt_idx = VEPU_REG_CHECKPOINT(0) / 4; + RK_U32 *reg_val = reg->val; + + mb_rc->hw_status = reg_val[VEPU_REG_INTERRUPT / 4]; + mb_rc->out_strm_size = reg_val[VEPU_REG_STR_BUF_LIMIT / 4] / 8 - mb_rc->hdr_free_size; + mb_rc->qp_sum = VEPU_REG_QP_SUM(reg_val[VEPU_REG_MAD_CTRL / 4]); + mb_rc->less_mad_count = VEPU_REG_MB_CNT_SET(reg_val[VEPU_REG_MB_CTRL / 4]); + mb_rc->rlc_count = VEPU_REG_RLC_SUM_OUT(reg_val[VEPU_REG_RLC_CTRL / 4]); + + for (i = 0; i < VEPU_CHECK_POINTS_MAX; i++) { + RK_U32 cpt = VEPU_REG_CHECKPOINT_RESULT(reg_val[cpt_idx]); + + if (cpt < cpt_prev) + overflow += (1 << 21); + + cpt_prev = cpt; + mb_rc->cp_usage[i] = cpt + overflow; + cpt_idx += (i & 1); + } +} + +static MPP_RET hal_h264e_vepu1_wait_v2(void *hal, HalEncTask *task) +{ + HalH264eVepu1Ctx *ctx = (HalH264eVepu1Ctx *)hal; + HalH264eVepuMbRc *hw_mbrc = &ctx->hw_mbrc; + H264NaluType type = (task->rc_task->frm.is_idr != 0) ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + MPP_RET ret = MPP_NOK; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (ctx->dev) { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } else { + mpp_err("invalid NULL device ctx\n"); + return ret; + } + + h264e_vepu1_get_mbrc(hw_mbrc, &ctx->regs_get); + h264e_vepu_mbrc_update(ctx->rc_ctx, hw_mbrc); + + mpp_packet_add_segment_info(pkt, type, offset, hw_mbrc->out_strm_size); + + { + HalH264eVepuStreamAmend *amend = &ctx->amend; + + if (amend->enable) { + amend->old_length = hw_mbrc->out_strm_size; + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + ctx->hw_mbrc.out_strm_size = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = hw_mbrc->out_strm_size; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + + task->hw_length += ctx->hw_mbrc.out_strm_size; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu1_ret_task_v2(void *hal, HalEncTask *task) +{ + HalH264eVepu1Ctx *ctx = (HalH264eVepu1Ctx *)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + + hal_h264e_dbg_func("enter %p\n", hal); + + task->length += task->hw_length; + + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = ctx->hw_mbrc.qp_sum / mbs; + + hal_h264e_dbg_rc("real bit %d quality %d\n", rc_info->bit_real, rc_info->quality_real); + + task->hal_ret.data = rc_info; + task->hal_ret.number = 1; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu1 = { + .name = "hal_h264e_vepu1", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu1Ctx), + .flag = 0, + .init = hal_h264e_vepu1_init_v2, + .deinit = hal_h264e_vepu1_deinit_v2, + .prepare = NULL, + .get_task = hal_h264e_vepu1_get_task_v2, + .gen_regs = hal_h264e_vepu1_gen_regs_v2, + .start = hal_h264e_vepu1_start_v2, + .wait = hal_h264e_vepu1_wait_v2, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu1_ret_task_v2, + .client = VPU_CLIENT_VEPU1, + .soc_type = { + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu1) diff --git a/mpp/codec/inc/h264e_api.h b/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.h similarity index 76% rename from mpp/codec/inc/h264e_api.h rename to mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.h index 90949d83e..d8a85f599 100644 --- a/mpp/codec/inc/h264e_api.h +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.h @@ -1,22 +1,24 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __H264E_API_H__ -#define __H264E_API_H__ - - - -#endif /*__H264E_API_H__*/ \ No newline at end of file +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU1_H +#define HAL_H264E_VEPU1_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h264e_vepu1; + +#endif diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu2_reg_tbl.h b/mpp/hal/vpu/h264e/hal_h264e_vepu2_reg_tbl.h new file mode 100644 index 000000000..ddeec23e6 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu2_reg_tbl.h @@ -0,0 +1,615 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU2_REG_TBL_H +#define HAL_H264E_VEPU2_REG_TBL_H + +#include "rk_type.h" + +/* RK3228 Encoder registers. */ +#define VEPU_REG_VP8_QUT_1ST(i) (0x000 + ((i) * 0x24)) +#define VEPU_REG_VP8_QUT_DC_Y2(x) (((x) & 0x3fff) << 16) +#define VEPU_REG_VP8_QUT_DC_Y1(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_QUT_2ND(i) (0x004 + ((i) * 0x24)) +#define VEPU_REG_VP8_QUT_AC_Y1(x) (((x) & 0x3fff) << 16) +#define VEPU_REG_VP8_QUT_DC_CHR(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_QUT_3RD(i) (0x008 + ((i) * 0x24)) +#define VEPU_REG_VP8_QUT_AC_CHR(x) (((x) & 0x3fff) << 16) +#define VEPU_REG_VP8_QUT_AC_Y2(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_QUT_4TH(i) (0x00c + ((i) * 0x24)) +#define VEPU_REG_VP8_QUT_ZB_DC_CHR(x) (((x) & 0x1ff) << 18) +#define VEPU_REG_VP8_QUT_ZB_DC_Y2(x) (((x) & 0x1ff) << 9) +#define VEPU_REG_VP8_QUT_ZB_DC_Y1(x) (((x) & 0x1ff) << 0) +#define VEPU_REG_VP8_QUT_5TH(i) (0x010 + ((i) * 0x24)) +#define VEPU_REG_VP8_QUT_ZB_AC_CHR(x) (((x) & 0x1ff) << 18) +#define VEPU_REG_VP8_QUT_ZB_AC_Y2(x) (((x) & 0x1ff) << 9) +#define VEPU_REG_VP8_QUT_ZB_AC_Y1(x) (((x) & 0x1ff) << 0) +#define VEPU_REG_VP8_QUT_6TH(i) (0x014 + ((i) * 0x24)) +#define VEPU_REG_VP8_QUT_RND_DC_CHR(x) (((x) & 0xff) << 16) +#define VEPU_REG_VP8_QUT_RND_DC_Y2(x) (((x) & 0xff) << 8) +#define VEPU_REG_VP8_QUT_RND_DC_Y1(x) (((x) & 0xff) << 0) +#define VEPU_REG_VP8_QUT_7TH(i) (0x018 + ((i) * 0x24)) +#define VEPU_REG_VP8_QUT_RND_AC_CHR(x) (((x) & 0xff) << 16) +#define VEPU_REG_VP8_QUT_RND_AC_Y2(x) (((x) & 0xff) << 8) +#define VEPU_REG_VP8_QUT_RND_AC_Y1(x) (((x) & 0xff) << 0) +#define VEPU_REG_VP8_QUT_8TH(i) (0x01c + ((i) * 0x24)) +#define VEPU_REG_VP8_SEG_FILTER_LEVEL(x) (((x) & 0x3f) << 25) +#define VEPU_REG_VP8_DEQUT_DC_CHR(x) (((x) & 0xff) << 17) +#define VEPU_REG_VP8_DEQUT_DC_Y2(x) (((x) & 0x1ff) << 8) +#define VEPU_REG_VP8_DEQUT_DC_Y1(x) (((x) & 0xff) << 0) +#define VEPU_REG_VP8_QUT_9TH(i) (0x020 + ((i) * 0x24)) +#define VEPU_REG_VP8_DEQUT_AC_CHR(x) (((x) & 0x1ff) << 18) +#define VEPU_REG_VP8_DEQUT_AC_Y2(x) (((x) & 0x1ff) << 9) +#define VEPU_REG_VP8_DEQUT_AC_Y1(x) (((x) & 0x1ff) << 0) +#define VEPU_REG_ADDR_VP8_SEG_MAP 0x06c +#define VEPU_REG_VP8_INTRA_4X4_PENALTY(i) (0x070 + ((i) * 0x4)) +#define VEPU_REG_VP8_INTRA_4X4_PENALTY_0(x) (((x) & 0xfff) << 0) +#define VEPU_REG_VP8_INTRA_4x4_PENALTY_1(x) (((x) & 0xfff) << 16) +#define VEPU_REG_VP8_INTRA_16X16_PENALTY(i) (0x084 + ((i) * 0x4)) +#define VEPU_REG_VP8_INTRA_16X16_PENALTY_0(x) (((x) & 0xfff) << 0) +#define VEPU_REG_VP8_INTRA_16X16_PENALTY_1(x) (((x) & 0xfff) << 16) +#define VEPU_REG_VP8_CONTROL 0x0a0 +#define VEPU_REG_VP8_LF_MODE_DELTA_BPRED(x) (((x) & 0x1f) << 24) +#define VEPU_REG_VP8_LF_REF_DELTA_INTRA_MB(x) (((x) & 0x7f) << 16) +#define VEPU_REG_VP8_INTER_TYPE_BIT_COST(x) (((x) & 0xfff) << 0) +#define VEPU_REG_VP8_REF_FRAME_VAL 0x0a4 +#define VEPU_REG_VP8_COEF_DMV_PENALTY(x) (((x) & 0xfff) << 16) +#define VEPU_REG_VP8_REF_FRAME(x) (((x) & 0xfff) << 0) +#define VEPU_REG_VP8_LOOP_FILTER_REF_DELTA 0x0a8 +#define VEPU_REG_VP8_LF_REF_DELTA_ALT_REF(x) (((x) & 0x7f) << 16) +#define VEPU_REG_VP8_LF_REF_DELTA_LAST_REF(x) (((x) & 0x7f) << 8) +#define VEPU_REG_VP8_LF_REF_DELTA_GOLDEN(x) (((x) & 0x7f) << 0) +#define VEPU_REG_VP8_LOOP_FILTER_MODE_DELTA 0x0ac +#define VEPU_REG_VP8_LF_MODE_DELTA_SPLITMV(x) (((x) & 0x7f) << 16) +#define VEPU_REG_VP8_LF_MODE_DELTA_ZEROMV(x) (((x) & 0x7f) << 8) +#define VEPU_REG_VP8_LF_MODE_DELTA_NEWMV(x) (((x) & 0x7f) << 0) +#define VEPU_REG_INTRA_SLICE_BITMAP(i) (0x0b0 + ((i) * 0x4)) +#define VEPU_REG_ADDR_VP8_DCT_PART(i) (0x0b0 + ((i) * 0x4)) +#define VEPU_REG_INTRA_AREA_CTRL 0x0b8 +#define VEPU_REG_INTRA_AREA_TOP(x) (((x) & 0xff) << 24) +#define VEPU_REG_INTRA_AREA_BOTTOM(x) (((x) & 0xff) << 16) +#define VEPU_REG_INTRA_AREA_LEFT(x) (((x) & 0xff) << 8) +#define VEPU_REG_INTRA_AREA_RIGHT(x) (((x) & 0xff) << 0) +#define VEPU_REG_CIR_INTRA_CTRL 0x0bc +#define VEPU_REG_CIR_INTRA_FIRST_MB(x) (((x) & 0xffff) << 16) +#define VEPU_REG_CIR_INTRA_INTERVAL(x) (((x) & 0xffff) << 0) +#define VEPU_REG_ADDR_IN_LUMA 0x0c0 +#define VEPU_REG_ADDR_IN_CB 0x0c4 +#define VEPU_REG_ADDR_IN_CR 0x0c8 +#define VEPU_REG_STR_HDR_REM_MSB 0x0cc +#define VEPU_REG_STR_HDR_REM_LSB 0x0d0 +#define VEPU_REG_STR_BUF_LIMIT 0x0d4 +#define VEPU_REG_AXI_CTRL 0x0d8 +#define VEPU_REG_AXI_CTRL_READ_ID(x) (((x) & 0xff) << 24) +#define VEPU_REG_AXI_CTRL_WRITE_ID(x) (((x) & 0xff) << 16) +#define VEPU_REG_AXI_CTRL_BURST_LEN(x) (((x) & 0x3f) << 8) +#define VEPU_REG_AXI_CTRL_INCREMENT_MODE(x) (((x) & 0x01) << 2) +#define VEPU_REG_AXI_CTRL_BIRST_DISCARD(x) (((x) & 0x01) << 1) +#define VEPU_REG_AXI_CTRL_BIRST_DISABLE MPP_BIT(0) +#define VEPU_QP_ADJUST_MAD_DELTA_ROI 0x0dc +#define VEPU_REG_ROI_QP_DELTA_1 (((x) & 0xf) << 12) +#define VEPU_REG_ROI_QP_DELTA_2 (((x) & 0xf) << 8) +#define VEPU_REG_MAD_QP_ADJUSTMENT (((x) & 0xf) << 0) +#define VEPU_REG_ADDR_REF_LUMA 0x0e0 +#define VEPU_REG_ADDR_REF_CHROMA 0x0e4 +#define VEPU_REG_QP_SUM_DIV2 0x0e8 +#define VEPU_REG_QP_SUM(x) (((x) & 0x001fffff) * 2) +#define VEPU_REG_ENC_CTRL0 0x0ec +#define VEPU_REG_DISABLE_QUARTER_PIXEL_MV MPP_BIT(28) +#define VEPU_REG_DEBLOCKING_FILTER_MODE(x) (((x) & 0x3) << 24) +#define VEPU_REG_CABAC_INIT_IDC(x) (((x) & 0x3) << 21) +#define VEPU_REG_ENTROPY_CODING_MODE MPP_BIT(20) +#define VEPU_REG_H264_TRANS8X8_MODE MPP_BIT(17) +#define VEPU_REG_H264_INTER4X4_MODE MPP_BIT(16) +#define VEPU_REG_H264_STREAM_MODE MPP_BIT(15) +#define VEPU_REG_H264_SLICE_SIZE(x) (((x) & 0x7f) << 8) +#define VEPU_REG_ENC_OVER_FILL_STRM_OFFSET 0x0f0 +#define VEPU_REG_STREAM_START_OFFSET(x) (((x) & 0x3f) << 16) +#define VEPU_REG_SKIP_MACROBLOCK_PENALTY(x) (((x) & 0xff) << 8) +#define VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(x) (((x) & 0x3) << 4) +#define VEPU_REG_IN_IMG_CTRL_OVRFLB(x) (((x) & 0xf) << 0) +#define VEPU_REG_INPUT_LUMA_INFO 0x0f4 +#define VEPU_REG_IN_IMG_CHROMA_OFFSET(x) (((x) & 0x7) << 20) +#define VEPU_REG_IN_IMG_LUMA_OFFSET(x) (((x) & 0x7) << 16) +#define VEPU_REG_IN_IMG_CTRL_ROW_LEN(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_RLC_SUM 0x0f8 +#define VEPU_REG_RLC_SUM_OUT(x) (((x) & 0x007fffff) * 4) +#define VEPU_REG_SPLIT_PENALTY_4X4 0x0f8 +#define VEPU_REG_VP8_SPLIT_PENALTY_4X4 (((x) & 0x1ff) << 19) +#define VEPU_REG_ADDR_REC_LUMA 0x0fc +#define VEPU_REG_ADDR_REC_CHROMA 0x100 +#define VEPU_REG_CHECKPOINT(i) (0x104 + ((i) * 0x4)) +#define VEPU_REG_CHECKPOINT_CHECK0(x) (((x) & 0xffff)) +#define VEPU_REG_CHECKPOINT_CHECK1(x) (((x) & 0xffff) << 16) +#define VEPU_REG_CHECKPOINT_RESULT(x) ((((x) >> (16 - 16 \ + * (i & 1))) & 0xffff) \ + * 32) +#define VEPU_REG_VP8_SEG0_QUANT_AC_Y1 0x104 +#define VEPU_REG_VP8_SEG0_RND_AC_Y1(x) (((x) & 0xff) << 23) +#define VEPU_REG_VP8_SEG0_ZBIN_AC_Y1(x) (((x) & 0x1ff) << 14) +#define VEPU_REG_VP8_SEG0_QUT_AC_Y1(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_SEG0_QUANT_DC_Y2 0x108 +#define VEPU_REG_VP8_SEG0_RND_DC_Y2(x) (((x) & 0xff) << 23) +#define VEPU_REG_VP8_SEG0_ZBIN_DC_Y2(x) (((x) & 0x1ff) << 14) +#define VEPU_REG_VP8_SEG0_QUT_DC_Y2(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_SEG0_QUANT_AC_Y2 0x10c +#define VEPU_REG_VP8_SEG0_RND_AC_Y2(x) (((x) & 0xff) << 23) +#define VEPU_REG_VP8_SEG0_ZBIN_AC_Y2(x) (((x) & 0x1ff) << 14) +#define VEPU_REG_VP8_SEG0_QUT_AC_Y2(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_SEG0_QUANT_DC_CHR 0x110 +#define VEPU_REG_VP8_SEG0_RND_DC_CHR(x) (((x) & 0xff) << 23) +#define VEPU_REG_VP8_SEG0_ZBIN_DC_CHR(x) (((x) & 0x1ff) << 14) +#define VEPU_REG_VP8_SEG0_QUT_DC_CHR(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_SEG0_QUANT_AC_CHR 0x114 +#define VEPU_REG_VP8_SEG0_RND_AC_CHR(x) (((x) & 0xff) << 23) +#define VEPU_REG_VP8_SEG0_ZBIN_AC_CHR(x) (((x) & 0x1ff) << 14) +#define VEPU_REG_VP8_SEG0_QUT_AC_CHR(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_VP8_SEG0_QUANT_DQUT 0x118 +#define VEPU_REG_VP8_MV_REF_IDX1(x) (((x) & 0x03) << 26) +#define VEPU_REG_VP8_SEG0_DQUT_DC_Y2(x) (((x) & 0x1ff) << 17) +#define VEPU_REG_VP8_SEG0_DQUT_AC_Y1(x) (((x) & 0x1ff) << 8) +#define VEPU_REG_VP8_SEG0_DQUT_DC_Y1(x) (((x) & 0xff) << 0) +#define VEPU_REG_CHKPT_WORD_ERR(i) (0x118 + ((i) * 0x4)) +#define VEPU_REG_CHKPT_WORD_ERR_CHK0(x) (((x) & 0xffff)) +#define VEPU_REG_CHKPT_WORD_ERR_CHK1(x) (((x) & 0xffff) << 16) +#define VEPU_REG_VP8_SEG0_QUANT_DQUT_1 0x11c +#define VEPU_REG_VP8_SEGMENT_MAP_UPDATE MPP_BIT(30) +#define VEPU_REG_VP8_SEGMENT_EN MPP_BIT(29) +#define VEPU_REG_VP8_MV_REF_IDX2_EN MPP_BIT(28) +#define VEPU_REG_VP8_MV_REF_IDX2(x) (((x) & 0x03) << 26) +#define VEPU_REG_VP8_SEG0_DQUT_AC_CHR(x) (((x) & 0x1ff) << 17) +#define VEPU_REG_VP8_SEG0_DQUT_DC_CHR(x) (((x) & 0xff) << 9) +#define VEPU_REG_VP8_SEG0_DQUT_AC_Y2(x) (((x) & 0x1ff) << 0) +#define VEPU_REG_VP8_BOOL_ENC_VALUE 0x120 +#define VEPU_REG_CHKPT_DELTA_QP 0x124 +#define VEPU_REG_CHKPT_DELTA_QP_CHK0(x) (((x) & 0x0f) << 0) +#define VEPU_REG_CHKPT_DELTA_QP_CHK1(x) (((x) & 0x0f) << 4) +#define VEPU_REG_CHKPT_DELTA_QP_CHK2(x) (((x) & 0x0f) << 8) +#define VEPU_REG_CHKPT_DELTA_QP_CHK3(x) (((x) & 0x0f) << 12) +#define VEPU_REG_CHKPT_DELTA_QP_CHK4(x) (((x) & 0x0f) << 16) +#define VEPU_REG_CHKPT_DELTA_QP_CHK5(x) (((x) & 0x0f) << 20) +#define VEPU_REG_CHKPT_DELTA_QP_CHK6(x) (((x) & 0x0f) << 24) +#define VEPU_REG_VP8_ENC_CTRL2 0x124 +#define VEPU_REG_VP8_ZERO_MV_PENALTY_FOR_REF2(x) (((x) & 0xff) << 24) +#define VEPU_REG_VP8_FILTER_SHARPNESS(x) (((x) & 0x07) << 21) +#define VEPU_REG_VP8_FILTER_LEVEL(x) (((x) & 0x3f) << 15) +#define VEPU_REG_VP8_DCT_PARTITION_CNT(x) (((x) & 0x03) << 13) +#define VEPU_REG_VP8_BOOL_ENC_VALUE_BITS(x) (((x) & 0x1f) << 8) +#define VEPU_REG_VP8_BOOL_ENC_RANGE(x) (((x) & 0xff) << 0) +#define VEPU_REG_ENC_CTRL1 0x128 +#define VEPU_REG_MAD_THRESHOLD(x) (((x) & 0x3f) << 24) +#define VEPU_REG_COMPLETED_SLICES(x) (((x) & 0xff) << 16) +#define VEPU_REG_IN_IMG_CTRL_FMT(x) (((x) & 0xf) << 4) +#define VEPU_REG_IN_IMG_ROTATE_MODE(x) (((x) & 0x3) << 2) +#define VEPU_REG_SIZE_TABLE_PRESENT MPP_BIT(0) +#define VEPU_REG_INTRA_INTER_MODE 0x12c +#define VEPU_REG_INTRA16X16_MODE(x) (((x) & 0xffff) << 16) +#define VEPU_REG_INTER_MODE(x) (((x) & 0xffff) << 0) +#define VEPU_REG_ENC_CTRL2 0x130 +#define VEPU_REG_PPS_INIT_QP(x) (((x) & 0x3f) << 26) +#define VEPU_REG_SLICE_FILTER_ALPHA(x) (((x) & 0xf) << 22) +#define VEPU_REG_SLICE_FILTER_BETA(x) (((x) & 0xf) << 18) +#define VEPU_REG_CHROMA_QP_OFFSET(x) (((x) & 0x1f) << 13) +#define VEPU_REG_FILTER_DISABLE MPP_BIT(5) +#define VEPU_REG_IDR_PIC_ID(x) (((x) & 0xf) << 1) +#define VEPU_REG_CONSTRAINED_INTRA_PREDICTION MPP_BIT(0) +#define VEPU_REG_ADDR_OUTPUT_STREAM 0x134 +#define VEPU_REG_ADDR_OUTPUT_CTRL 0x138 +#define VEPU_REG_ADDR_NEXT_PIC 0x13c +#define VEPU_REG_ADDR_MV_OUT 0x140 +#define VEPU_REG_ADDR_CABAC_TBL 0x144 +#define VEPU_REG_ROI1 0x148 +#define VEPU_REG_ROI1_TOP_MB(x) (((x) & 0xff) << 24) +#define VEPU_REG_ROI1_BOTTOM_MB(x) (((x) & 0xff) << 16) +#define VEPU_REG_ROI1_LEFT_MB(x) (((x) & 0xff) << 8) +#define VEPU_REG_ROI1_RIGHT_MB(x) (((x) & 0xff) << 0) +#define VEPU_REG_ROI2 0x14c +#define VEPU_REG_ROI2_TOP_MB(x) (((x) & 0xff) << 24) +#define VEPU_REG_ROI2_BOTTOM_MB(x) (((x) & 0xff) << 16) +#define VEPU_REG_ROI2_LEFT_MB(x) (((x) & 0xff) << 8) +#define VEPU_REG_ROI2_RIGHT_MB(x) (((x) & 0xff) << 0) +#define VEPU_REG_STABLE_MATRIX(i) (0x150 + ((i) * 0x4)) +#define VEPU_REG_STABLE_MOTION_SUM 0x174 +#define VEPU_REG_STABLILIZATION_OUTPUT 0x178 +#define VEPU_REG_STABLE_MIN_VALUE(x) (((x) & 0xffffff) << 8) +#define VEPU_REG_STABLE_MODE_SEL(x) (((x) & 0x3) << 6) +#define VEPU_REG_STABLE_HOR_GMV(x) (((x) & 0x3f) << 0) +#define VEPU_REG_RGB2YUV_CONVERSION_COEF1 0x17c +#define VEPU_REG_RGB2YUV_CONVERSION_COEFB(x) (((x) & 0xffff) << 16) +#define VEPU_REG_RGB2YUV_CONVERSION_COEFA(x) (((x) & 0xffff) << 0) +#define VEPU_REG_RGB2YUV_CONVERSION_COEF2 0x180 +#define VEPU_REG_RGB2YUV_CONVERSION_COEFE(x) (((x) & 0xffff) << 16) +#define VEPU_REG_RGB2YUV_CONVERSION_COEFC(x) (((x) & 0xffff) << 0) +#define VEPU_REG_RGB2YUV_CONVERSION_COEF3 0x184 +#define VEPU_REG_RGB2YUV_CONVERSION_COEFF(x) (((x) & 0xffff) << 0) +#define VEPU_REG_RGB_MASK_MSB 0x188 +#define VEPU_REG_RGB_MASK_B_MSB(x) (((x) & 0x1f) << 16) +#define VEPU_REG_RGB_MASK_G_MSB(x) (((x) & 0x1f) << 8) +#define VEPU_REG_RGB_MASK_R_MSB(x) (((x) & 0x1f) << 0) +#define VEPU_REG_MV_PENALTY 0x18c +#define VEPU_REG_1MV_PENALTY(x) (((x) & 0x3ff) << 21) +#define VEPU_REG_QMV_PENALTY(x) (((x) & 0x3ff) << 11) +#define VEPU_REG_4MV_PENALTY(x) (((x) & 0x3ff) << 1) +#define VEPU_REG_SPLIT_MV_MODE_EN MPP_BIT(0) +#define VEPU_REG_QP_VAL 0x190 +#define VEPU_REG_H264_LUMA_INIT_QP(x) (((x) & 0x3f) << 26) +#define VEPU_REG_H264_QP_MAX(x) (((x) & 0x3f) << 20) +#define VEPU_REG_H264_QP_MIN(x) (((x) & 0x3f) << 14) +#define VEPU_REG_H264_CHKPT_DISTANCE(x) (((x) & 0xfff) << 0) +#define VEPU_REG_VP8_SEG0_QUANT_DC_Y1 0x190 +#define VEPU_REG_VP8_SEG0_RND_DC_Y1(x) (((x) & 0xff) << 23) +#define VEPU_REG_VP8_SEG0_ZBIN_DC_Y1(x) (((x) & 0x1ff) << 14) +#define VEPU_REG_VP8_SEG0_QUT_DC_Y1(x) (((x) & 0x3fff) << 0) +#define VEPU_REG_MVC_RELATE 0x198 +#define VEPU_REG_ZERO_MV_FAVOR_D2(x) (((x) & 0xf) << 20) +#define VEPU_REG_PENALTY_4X4MV(x) (((x) & 0x1ff) << 11) +#define VEPU_REG_MVC_VIEW_ID(x) (((x) & 0x7) << 8) +#define VEPU_REG_MVC_ANCHOR_PIC_FLAG MPP_BIT(7) +#define VEPU_REG_MVC_PRIORITY_ID(x) (((x) & 0x7) << 4) +#define VEPU_REG_MVC_TEMPORAL_ID(x) (((x) & 0x7) << 1) +#define VEPU_REG_MVC_INTER_VIEW_FLAG MPP_BIT(0) +#define VEPU_REG_ENCODE_START 0x19c +#define VEPU_REG_MB_HEIGHT(x) (((x) & 0x1ff) << 20) +#define VEPU_REG_MB_WIDTH(x) (((x) & 0x1ff) << 8) +#define VEPU_REG_PIC_TYPE(x) (((x) & 0x3) << 6) +#define VEPU_REG_ENCODE_FORMAT(x) (((x) & 0x3) << 4) +#define VEPU_REG_ENCODE_ENABLE MPP_BIT(0) +#define VEPU_REG_MB_CTRL 0x1a0 +#define VEPU_REG_MB_CNT_OUT(x) (((x) & 0xffff) << 16) +#define VEPU_REG_MB_CNT_SET(x) (((x) & 0xffff) << 0) +#define VEPU_REG_DATA_ENDIAN 0x1a4 +#define VEPU_REG_INPUT_SWAP8 MPP_BIT(31) +#define VEPU_REG_INPUT_SWAP8_(x) (((x) & 1) << 31) +#define VEPU_REG_INPUT_SWAP16 MPP_BIT(30) +#define VEPU_REG_INPUT_SWAP16_(x) (((x) & 1) << 30) +#define VEPU_REG_INPUT_SWAP32 MPP_BIT(29) +#define VEPU_REG_INPUT_SWAP32_(x) (((x) & 1) << 29) +#define VEPU_REG_OUTPUT_SWAP8 MPP_BIT(28) +#define VEPU_REG_OUTPUT_SWAP16 MPP_BIT(27) +#define VEPU_REG_OUTPUT_SWAP32 MPP_BIT(26) +#define VEPU_REG_TEST_IRQ MPP_BIT(24) +#define VEPU_REG_TEST_COUNTER(x) (((x) & 0xf) << 20) +#define VEPU_REG_TEST_REG MPP_BIT(19) +#define VEPU_REG_TEST_MEMORY MPP_BIT(18) +#define VEPU_REG_TEST_LEN(x) (((x) & 0x3ffff) << 0) +#define VEPU_REG_ENC_CTRL3 0x1a8 +#define VEPU_REG_PPS_ID(x) (((x) & 0xff) << 24) +#define VEPU_REG_INTRA_PRED_MODE(x) (((x) & 0xff) << 16) +#define VEPU_REG_FRAME_NUM(x) (((x) & 0xffff) << 0) +#define VEPU_REG_ENC_CTRL4 0x1ac +#define VEPU_REG_MV_PENALTY_16X8_8X16(x) (((x) & 0x3ff) << 20) +#define VEPU_REG_MV_PENALTY_8X8(x) (((x) & 0x3ff) << 10) +#define VEPU_REG_MV_PENALTY_8X4_4X8(x) (((x) & 0x3ff) << 0) +#define VEPU_REG_ADDR_VP8_PROB_CNT 0x1b0 +#define VEPU_REG_INTERRUPT 0x1b4 +#define VEPU_REG_INTERRUPT_NON MPP_BIT(28) +#define VEPU_REG_MV_WRITE_EN MPP_BIT(24) +#define VEPU_REG_RECON_WRITE_DIS MPP_BIT(20) +#define VEPU_REG_INTERRUPT_SLICE_READY_EN MPP_BIT(16) +#define VEPU_REG_CLK_GATING_EN MPP_BIT(12) +#define VEPU_REG_INTERRUPT_TIMEOUT_EN MPP_BIT(10) +#define VEPU_REG_INTERRUPT_RESET MPP_BIT(9) +#define VEPU_REG_INTERRUPT_DIS_BIT MPP_BIT(8) +#define VEPU_REG_INTERRUPT_TIMEOUT MPP_BIT(6) +#define VEPU_REG_INTERRUPT_BUFFER_FULL MPP_BIT(5) +#define VEPU_REG_INTERRUPT_BUS_ERROR MPP_BIT(4) +#define VEPU_REG_INTERRUPT_FUSE MPP_BIT(3) +#define VEPU_REG_INTERRUPT_SLICE_READY MPP_BIT(2) +#define VEPU_REG_INTERRUPT_FRAME_READY MPP_BIT(1) +#define VEPU_REG_INTERRUPT_BIT MPP_BIT(0) +#define VEPU_REG_DMV_PENALTY_TBL(i) (0x1E0 + ((i) * 0x4)) +#define VEPU_REG_DMV_PENALTY_TABLE_BIT(x, i) (x << i * 8) +#define VEPU_REG_DMV_Q_PIXEL_PENALTY_TBL(i) (0x260 + ((i) * 0x4)) +#define VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT(x, i) (x << i * 8) + +/* vpu decoder register */ +#define VDPU_REG_DEC_CTRL0 0x0c8 +#define VDPU_REG_REF_BUF_CTRL2_REFBU2_PICID(x) (((x) & 0x1f) << 25) +#define VDPU_REG_REF_BUF_CTRL2_REFBU2_THR(x) (((x) & 0xfff) << 13) +#define VDPU_REG_CONFIG_TILED_MODE_LSB MPP_BIT(12) +#define VDPU_REG_CONFIG_DEC_ADV_PRE_DIS MPP_BIT(11) +#define VDPU_REG_CONFIG_DEC_SCMD_DIS MPP_BIT(10) +#define VDPU_REG_DEC_CTRL0_SKIP_MODE MPP_BIT(9) +#define VDPU_REG_DEC_CTRL0_FILTERING_DIS MPP_BIT(8) +#define VDPU_REG_DEC_CTRL0_PIC_FIXED_QUANT MPP_BIT(7) +#define VDPU_REG_CONFIG_DEC_LATENCY(x) (((x) & 0x3f) << 1) +#define VDPU_REG_CONFIG_TILED_MODE_MSB(x) MPP_BIT(0) +#define VDPU_REG_CONFIG_DEC_OUT_TILED_E MPP_BIT(0) +#define VDPU_REG_STREAM_LEN 0x0cc +#define VDPU_REG_DEC_CTRL3_INIT_QP(x) (((x) & 0x3f) << 25) +#define VDPU_REG_DEC_STREAM_LEN_HI MPP_BIT(24) +#define VDPU_REG_DEC_CTRL3_STREAM_LEN(x) (((x) & 0xffffff) << 0) +#define VDPU_REG_ERROR_CONCEALMENT 0x0d0 +#define VDPU_REG_REF_BUF_CTRL2_APF_THRESHOLD(x) (((x) & 0x3fff) << 17) +#define VDPU_REG_ERR_CONC_STARTMB_X(x) (((x) & 0x1ff) << 8) +#define VDPU_REG_ERR_CONC_STARTMB_Y(x) (((x) & 0xff) << 0) +#define VDPU_REG_DEC_FORMAT 0x0d4 +#define VDPU_REG_DEC_CTRL0_DEC_MODE(x) (((x) & 0xf) << 0) +#define VDPU_REG_DATA_ENDIAN 0x0d8 +#define VDPU_REG_CONFIG_DEC_STRENDIAN_E MPP_BIT(5) +#define VDPU_REG_CONFIG_DEC_STRSWAP32_E MPP_BIT(4) +#define VDPU_REG_CONFIG_DEC_OUTSWAP32_E MPP_BIT(3) +#define VDPU_REG_CONFIG_DEC_INSWAP32_E MPP_BIT(2) +#define VDPU_REG_CONFIG_DEC_OUT_ENDIAN MPP_BIT(1) +#define VDPU_REG_CONFIG_DEC_IN_ENDIAN MPP_BIT(0) +#define VDPU_REG_INTERRUPT 0x0dc +#define VDPU_REG_INTERRUPT_DEC_TIMEOUT MPP_BIT(13) +#define VDPU_REG_INTERRUPT_DEC_ERROR_INT MPP_BIT(12) +#define VDPU_REG_INTERRUPT_DEC_PIC_INF MPP_BIT(10) +#define VDPU_REG_INTERRUPT_DEC_SLICE_INT MPP_BIT(9) +#define VDPU_REG_INTERRUPT_DEC_ASO_INT MPP_BIT(8) +#define VDPU_REG_INTERRUPT_DEC_BUFFER_INT MPP_BIT(6) +#define VDPU_REG_INTERRUPT_DEC_BUS_INT MPP_BIT(5) +#define VDPU_REG_INTERRUPT_DEC_RDY_INT MPP_BIT(4) +#define VDPU_REG_INTERRUPT_DEC_IRQ_DIS MPP_BIT(1) +#define VDPU_REG_INTERRUPT_DEC_IRQ MPP_BIT(0) +#define VDPU_REG_AXI_CTRL 0x0e0 +#define VDPU_REG_AXI_DEC_SEL MPP_BIT(23) +#define VDPU_REG_CONFIG_DEC_DATA_DISC_E MPP_BIT(22) +#define VDPU_REG_PARAL_BUS_E(x) MPP_BIT(21) +#define VDPU_REG_CONFIG_DEC_MAX_BURST(x) (((x) & 0x1f) << 16) +#define VDPU_REG_DEC_CTRL0_DEC_AXI_WR_ID(x) (((x) & 0xff) << 8) +#define VDPU_REG_CONFIG_DEC_AXI_RD_ID(x) (((x) & 0xff) << 0) +#define VDPU_REG_EN_FLAGS 0x0e4 +#define VDPU_REG_AHB_HLOCK_E MPP_BIT(31) +#define VDPU_REG_CACHE_E MPP_BIT(29) +#define VDPU_REG_PREFETCH_SINGLE_CHANNEL_E MPP_BIT(28) +#define VDPU_REG_INTRA_3_CYCLE_ENHANCE MPP_BIT(27) +#define VDPU_REG_INTRA_DOUBLE_SPEED MPP_BIT(26) +#define VDPU_REG_INTER_DOUBLE_SPEED MPP_BIT(25) +#define VDPU_REG_DEC_CTRL3_START_CODE_E MPP_BIT(22) +#define VDPU_REG_DEC_CTRL3_CH_8PIX_ILEAV_E MPP_BIT(21) +#define VDPU_REG_DEC_CTRL0_RLC_MODE_E MPP_BIT(20) +#define VDPU_REG_DEC_CTRL0_DIVX3_E MPP_BIT(19) +#define VDPU_REG_DEC_CTRL0_PJPEG_E MPP_BIT(18) +#define VDPU_REG_DEC_CTRL0_PIC_INTERLACE_E MPP_BIT(17) +#define VDPU_REG_DEC_CTRL0_PIC_FIELDMODE_E MPP_BIT(16) +#define VDPU_REG_DEC_CTRL0_PIC_B_E MPP_BIT(15) +#define VDPU_REG_DEC_CTRL0_PIC_INTER_E MPP_BIT(14) +#define VDPU_REG_DEC_CTRL0_PIC_TOPFIELD_E MPP_BIT(13) +#define VDPU_REG_DEC_CTRL0_FWD_INTERLACE_E MPP_BIT(12) +#define VDPU_REG_DEC_CTRL0_SORENSON_E MPP_BIT(11) +#define VDPU_REG_DEC_CTRL0_WRITE_MVS_E MPP_BIT(10) +#define VDPU_REG_DEC_CTRL0_REF_TOPFIELD_E MPP_BIT(9) +#define VDPU_REG_DEC_CTRL0_REFTOPFIRST_E MPP_BIT(8) +#define VDPU_REG_DEC_CTRL0_SEQ_MBAFF_E MPP_BIT(7) +#define VDPU_REG_DEC_CTRL0_PICORD_COUNT_E MPP_BIT(6) +#define VDPU_REG_CONFIG_DEC_TIMEOUT_E MPP_BIT(5) +#define VDPU_REG_CONFIG_DEC_CLK_GATE_E MPP_BIT(4) +#define VDPU_REG_DEC_CTRL0_DEC_OUT_DIS MPP_BIT(2) +#define VDPU_REG_REF_BUF_CTRL2_REFBU2_BUF_E MPP_BIT(1) +#define VDPU_REG_INTERRUPT_DEC_E MPP_BIT(0) +#define VDPU_REG_SOFT_RESET 0x0e8 +#define VDPU_REG_PRED_FLT 0x0ec +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_0(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_1(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_2(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_ADDITIONAL_CHROMA_ADDRESS 0x0f0 +#define VDPU_REG_ADDR_QTABLE 0x0f4 +#define VDPU_REG_DIRECT_MV_ADDR 0x0f8 +#define VDPU_REG_ADDR_DST 0x0fc +#define VDPU_REG_ADDR_STR 0x100 +#define VDPU_REG_REFBUF_RELATED 0x104 +#define VDPU_REG_FWD_PIC(i) (0x128 + ((i) * 0x4)) +#define VDPU_REG_FWD_PIC_PINIT_RLIST_F5(x) (((x) & 0x1f) << 25) +#define VDPU_REG_FWD_PIC_PINIT_RLIST_F4(x) (((x) & 0x1f) << 20) +#define VDPU_REG_FWD_PIC_PINIT_RLIST_F3(x) (((x) & 0x1f) << 15) +#define VDPU_REG_FWD_PIC_PINIT_RLIST_F2(x) (((x) & 0x1f) << 10) +#define VDPU_REG_FWD_PIC_PINIT_RLIST_F1(x) (((x) & 0x1f) << 5) +#define VDPU_REG_FWD_PIC_PINIT_RLIST_F0(x) (((x) & 0x1f) << 0) +#define VDPU_REG_REF_PIC(i) (0x130 + ((i) * 0x4)) +#define VDPU_REG_REF_PIC_REFER1_NBR(x) (((x) & 0xffff) << 16) +#define VDPU_REG_REF_PIC_REFER0_NBR(x) (((x) & 0xffff) << 0) +#define VDPU_REG_H264_ADDR_REF(i) (0x150 + ((i) * 0x4)) +#define VDPU_REG_ADDR_REF_FIELD_E MPP_BIT(1) +#define VDPU_REG_ADDR_REF_TOPC_E MPP_BIT(0) +#define VDPU_REG_INITIAL_REF_PIC_LIST0 0x190 +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F5(x) (((x) & 0x1f) << 25) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F4(x) (((x) & 0x1f) << 20) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F3(x) (((x) & 0x1f) << 15) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F2(x) (((x) & 0x1f) << 10) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F1(x) (((x) & 0x1f) << 5) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F0(x) (((x) & 0x1f) << 0) +#define VDPU_REG_INITIAL_REF_PIC_LIST1 0x194 +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F11(x) (((x) & 0x1f) << 25) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F10(x) (((x) & 0x1f) << 20) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F9(x) (((x) & 0x1f) << 15) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F8(x) (((x) & 0x1f) << 10) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F7(x) (((x) & 0x1f) << 5) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F6(x) (((x) & 0x1f) << 0) +#define VDPU_REG_INITIAL_REF_PIC_LIST2 0x198 +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F15(x) (((x) & 0x1f) << 15) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F14(x) (((x) & 0x1f) << 10) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F13(x) (((x) & 0x1f) << 5) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_F12(x) (((x) & 0x1f) << 0) +#define VDPU_REG_INITIAL_REF_PIC_LIST3 0x19c +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B5(x) (((x) & 0x1f) << 25) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B4(x) (((x) & 0x1f) << 20) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B3(x) (((x) & 0x1f) << 15) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B2(x) (((x) & 0x1f) << 10) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B1(x) (((x) & 0x1f) << 5) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B0(x) (((x) & 0x1f) << 0) +#define VDPU_REG_INITIAL_REF_PIC_LIST4 0x1a0 +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B11(x) (((x) & 0x1f) << 25) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B10(x) (((x) & 0x1f) << 20) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B9(x) (((x) & 0x1f) << 15) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B8(x) (((x) & 0x1f) << 10) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B7(x) (((x) & 0x1f) << 5) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B6(x) (((x) & 0x1f) << 0) +#define VDPU_REG_INITIAL_REF_PIC_LIST5 0x1a4 +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B15(x) (((x) & 0x1f) << 15) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B14(x) (((x) & 0x1f) << 10) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B13(x) (((x) & 0x1f) << 5) +#define VDPU_REG_BD_REF_PIC_BINIT_RLIST_B12(x) (((x) & 0x1f) << 0) +#define VDPU_REG_INITIAL_REF_PIC_LIST6 0x1a8 +#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F3(x) (((x) & 0x1f) << 15) +#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F2(x) (((x) & 0x1f) << 10) +#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F1(x) (((x) & 0x1f) << 5) +#define VDPU_REG_BD_P_REF_PIC_PINIT_RLIST_F0(x) (((x) & 0x1f) << 0) +#define VDPU_REG_LT_REF 0x1ac +#define VDPU_REG_VALID_REF 0x1b0 +#define VDPU_REG_H264_PIC_MB_SIZE 0x1b8 +#define VDPU_REG_DEC_CTRL2_CH_QP_OFFSET2(x) (((x) & 0x1f) << 22) +#define VDPU_REG_DEC_CTRL2_CH_QP_OFFSET(x) (((x) & 0x1f) << 17) +#define VDPU_REG_DEC_CTRL1_PIC_MB_HEIGHT_P(x) (((x) & 0xff) << 9) +#define VDPU_REG_DEC_CTRL1_PIC_MB_WIDTH(x) (((x) & 0x1ff) << 0) +#define VDPU_REG_H264_CTRL 0x1bc +#define VDPU_REG_DEC_CTRL4_WEIGHT_BIPR_IDC(x) (((x) & 0x3) << 16) +#define VDPU_REG_DEC_CTRL1_REF_FRAMES(x) (((x) & 0x1f) << 0) +#define VDPU_REG_CURRENT_FRAME 0x1c0 +#define VDPU_REG_DEC_CTRL5_FILT_CTRL_PRES MPP_BIT(31) +#define VDPU_REG_DEC_CTRL5_RDPIC_CNT_PRES MPP_BIT(30) +#define VDPU_REG_DEC_CTRL4_FRAMENUM_LEN(x) (((x) & 0x1f) << 16) +#define VDPU_REG_DEC_CTRL4_FRAMENUM(x) (((x) & 0xffff) << 0) +#define VDPU_REG_REF_FRAME 0x1c4 +#define VDPU_REG_DEC_CTRL5_REFPIC_MK_LEN(x) (((x) & 0x7ff) << 16) +#define VDPU_REG_DEC_CTRL5_IDR_PIC_ID(x) (((x) & 0xffff) << 0) +#define VDPU_REG_DEC_CTRL6 0x1c8 +#define VDPU_REG_DEC_CTRL6_PPS_ID(x) (((x) & 0xff) << 24) +#define VDPU_REG_DEC_CTRL6_REFIDX1_ACTIVE(x) (((x) & 0x1f) << 19) +#define VDPU_REG_DEC_CTRL6_REFIDX0_ACTIVE(x) (((x) & 0x1f) << 14) +#define VDPU_REG_DEC_CTRL6_POC_LENGTH(x) (((x) & 0xff) << 0) +#define VDPU_REG_ENABLE_FLAG 0x1cc +#define VDPU_REG_DEC_CTRL5_IDR_PIC_E MPP_BIT(8) +#define VDPU_REG_DEC_CTRL4_DIR_8X8_INFER_E MPP_BIT(7) +#define VDPU_REG_DEC_CTRL4_BLACKWHITE_E MPP_BIT(6) +#define VDPU_REG_DEC_CTRL4_CABAC_E MPP_BIT(5) +#define VDPU_REG_DEC_CTRL4_WEIGHT_PRED_E MPP_BIT(4) +#define VDPU_REG_DEC_CTRL5_CONST_INTRA_E MPP_BIT(3) +#define VDPU_REG_DEC_CTRL5_8X8TRANS_FLAG_E MPP_BIT(2) +#define VDPU_REG_DEC_CTRL2_TYPE1_QUANT_E MPP_BIT(1) +#define VDPU_REG_DEC_CTRL2_FIELDPIC_FLAG_E MPP_BIT(0) +#define VDPU_REG_VP8_PIC_MB_SIZE 0x1e0 +#define VDPU_REG_DEC_PIC_MB_WIDTH(x) (((x) & 0x1ff) << 23) +#define VDPU_REG_DEC_MB_WIDTH_OFF(x) (((x) & 0xf) << 19) +#define VDPU_REG_DEC_PIC_MB_HEIGHT_P(x) (((x) & 0xff) << 11) +#define VDPU_REG_DEC_MB_HEIGHT_OFF(x) (((x) & 0xf) << 7) +#define VDPU_REG_DEC_CTRL1_PIC_MB_W_EXT(x) (((x) & 0x7) << 3) +#define VDPU_REG_DEC_CTRL1_PIC_MB_H_EXT(x) (((x) & 0x7) << 0) +#define VDPU_REG_VP8_DCT_START_BIT 0x1e4 +#define VDPU_REG_DEC_CTRL4_DCT1_START_BIT(x) (((x) & 0x3f) << 26) +#define VDPU_REG_DEC_CTRL4_DCT2_START_BIT(x) (((x) & 0x3f) << 20) +#define VDPU_REG_DEC_CTRL4_VC1_HEIGHT_EXT MPP_BIT(13) +#define VDPU_REG_DEC_CTRL4_BILIN_MC_E MPP_BIT(12) +#define VDPU_REG_VP8_CTRL0 0x1e8 +#define VDPU_REG_DEC_CTRL2_STRM_START_BIT(x) (((x) & 0x3f) << 26) +#define VDPU_REG_DEC_CTRL2_STRM1_START_BIT(x) (((x) & 0x3f) << 18) +#define VDPU_REG_DEC_CTRL2_BOOLEAN_VALUE(x) (((x) & 0xff) << 8) +#define VDPU_REG_DEC_CTRL2_BOOLEAN_RANGE(x) (((x) & 0xff) << 0) +#define VDPU_REG_VP8_DATA_VAL 0x1f0 +#define VDPU_REG_DEC_CTRL6_COEFFS_PART_AM(x) (((x) & 0xf) << 24) +#define VDPU_REG_DEC_CTRL6_STREAM1_LEN(x) (((x) & 0xffffff) << 0) +#define VDPU_REG_PRED_FLT7 0x1f4 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_1(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_2(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_3(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT8 0x1f8 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_0(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_1(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_2(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT9 0x1fc +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_6_3(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_0(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_1(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT10 0x200 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_2(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_7_3(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_BD_REF_PIC_PRED_TAP_2_M1(x) (((x) & 0x3) << 10) +#define VDPU_REG_BD_REF_PIC_PRED_TAP_2_4(x) (((x) & 0x3) << 8) +#define VDPU_REG_BD_REF_PIC_PRED_TAP_4_M1(x) (((x) & 0x3) << 6) +#define VDPU_REG_BD_REF_PIC_PRED_TAP_4_4(x) (((x) & 0x3) << 4) +#define VDPU_REG_BD_REF_PIC_PRED_TAP_6_M1(x) (((x) & 0x3) << 2) +#define VDPU_REG_BD_REF_PIC_PRED_TAP_6_4(x) (((x) & 0x3) << 0) +#define VDPU_REG_FILTER_LEVEL 0x204 +#define VDPU_REG_REF_PIC_LF_LEVEL_0(x) (((x) & 0x3f) << 18) +#define VDPU_REG_REF_PIC_LF_LEVEL_1(x) (((x) & 0x3f) << 12) +#define VDPU_REG_REF_PIC_LF_LEVEL_2(x) (((x) & 0x3f) << 6) +#define VDPU_REG_REF_PIC_LF_LEVEL_3(x) (((x) & 0x3f) << 0) +#define VDPU_REG_VP8_QUANTER0 0x208 +#define VDPU_REG_REF_PIC_QUANT_DELTA_0(x) (((x) & 0x1f) << 27) +#define VDPU_REG_REF_PIC_QUANT_DELTA_1(x) (((x) & 0x1f) << 22) +#define VDPU_REG_REF_PIC_QUANT_0(x) (((x) & 0x7ff) << 11) +#define VDPU_REG_REF_PIC_QUANT_1(x) (((x) & 0x7ff) << 0) +#define VDPU_REG_VP8_ADDR_REF0 0x20c +#define VDPU_REG_FILTER_MB_ADJ 0x210 +#define VDPU_REG_REF_PIC_FILT_TYPE_E MPP_BIT(31) +#define VDPU_REG_REF_PIC_FILT_SHARPNESS(x) (((x) & 0x7) << 28) +#define VDPU_REG_FILT_MB_ADJ_0(x) (((x) & 0x7f) << 21) +#define VDPU_REG_FILT_MB_ADJ_1(x) (((x) & 0x7f) << 14) +#define VDPU_REG_FILT_MB_ADJ_2(x) (((x) & 0x7f) << 7) +#define VDPU_REG_FILT_MB_ADJ_3(x) (((x) & 0x7f) << 0) +#define VDPU_REG_FILTER_REF_ADJ 0x214 +#define VDPU_REG_REF_PIC_ADJ_0(x) (((x) & 0x7f) << 21) +#define VDPU_REG_REF_PIC_ADJ_1(x) (((x) & 0x7f) << 14) +#define VDPU_REG_REF_PIC_ADJ_2(x) (((x) & 0x7f) << 7) +#define VDPU_REG_REF_PIC_ADJ_3(x) (((x) & 0x7f) << 0) +#define VDPU_REG_VP8_ADDR_REF2_5(i) (0x218 + ((i) * 0x4)) +#define VDPU_REG_VP8_GREF_SIGN_BIAS MPP_BIT(0) +#define VDPU_REG_VP8_AREF_SIGN_BIAS MPP_BIT(0) +#define VDPU_REG_VP8_DCT_BASE(i) (0x230 + ((i) * 0x4)) +#define VDPU_REG_VP8_ADDR_CTRL_PART 0x244 +#define VDPU_REG_VP8_ADDR_REF1 0x250 +#define VDPU_REG_VP8_SEGMENT_VAL 0x254 +#define VDPU_REG_FWD_PIC1_SEGMENT_BASE(x) ((x) << 0) +#define VDPU_REG_FWD_PIC1_SEGMENT_UPD_E MPP_BIT(1) +#define VDPU_REG_FWD_PIC1_SEGMENT_E MPP_BIT(0) +#define VDPU_REG_VP8_DCT_START_BIT2 0x258 +#define VDPU_REG_DEC_CTRL7_DCT3_START_BIT(x) (((x) & 0x3f) << 24) +#define VDPU_REG_DEC_CTRL7_DCT4_START_BIT(x) (((x) & 0x3f) << 18) +#define VDPU_REG_DEC_CTRL7_DCT5_START_BIT(x) (((x) & 0x3f) << 12) +#define VDPU_REG_DEC_CTRL7_DCT6_START_BIT(x) (((x) & 0x3f) << 6) +#define VDPU_REG_DEC_CTRL7_DCT7_START_BIT(x) (((x) & 0x3f) << 0) +#define VDPU_REG_VP8_QUANTER1 0x25c +#define VDPU_REG_REF_PIC_QUANT_DELTA_2(x) (((x) & 0x1f) << 27) +#define VDPU_REG_REF_PIC_QUANT_DELTA_3(x) (((x) & 0x1f) << 22) +#define VDPU_REG_REF_PIC_QUANT_2(x) (((x) & 0x7ff) << 11) +#define VDPU_REG_REF_PIC_QUANT_3(x) (((x) & 0x7ff) << 0) +#define VDPU_REG_VP8_QUANTER2 0x260 +#define VDPU_REG_REF_PIC_QUANT_DELTA_4(x) (((x) & 0x1f) << 27) +#define VDPU_REG_REF_PIC_QUANT_4(x) (((x) & 0x7ff) << 11) +#define VDPU_REG_REF_PIC_QUANT_5(x) (((x) & 0x7ff) << 0) +#define VDPU_REG_PRED_FLT1 0x264 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_0_3(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_0(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_1(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT2 0x268 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_2(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_1_3(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_0(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT3 0x26c +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_1(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_2(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_2_3(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT4 0x270 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_0(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_1(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_2(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT5 0x274 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_3_3(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_0(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_1(x) (((x) & 0x3ff) << 2) +#define VDPU_REG_PRED_FLT6 0x278 +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_2(x) (((x) & 0x3ff) << 22) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_4_3(x) (((x) & 0x3ff) << 12) +#define VDPU_REG_PRED_FLT_PRED_BC_TAP_5_0(x) (((x) & 0x3ff) << 2) + +#define VEPU2_H264E_NUM_REGS 184 + +typedef struct h264e_vepu2_reg_set_t { + RK_U32 val[VEPU2_H264E_NUM_REGS]; +} H264eVpu2RegSet; + +#endif diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.c b/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.c new file mode 100644 index 000000000..f71ff68b1 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.c @@ -0,0 +1,826 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_h264e_vepu2_v2" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_frame.h" +#include "mpp_common.h" +#include "mpp_device.h" +#include "mpp_rc.h" +#include "mpp_packet_impl.h" + +#include "mpp_enc_hal.h" +#include "h264e_debug.h" +#include "h264e_sps.h" +#include "h264e_pps.h" +#include "h264e_slice.h" + +#include "hal_h264e_debug.h" + +#include "hal_h264e_vpu_tbl.h" +#include "hal_h264e_vepu_v2.h" +#include "hal_h264e_stream_amend.h" + +#include "hal_h264e_vepu2_reg_tbl.h" + +typedef struct HalH264eVepu2Ctx_t { + MppEncCfgSet *cfg; + + MppDev dev; + RK_S32 frame_cnt; + + /* buffers management */ + HalH264eVepuBufs hw_bufs; + + /* preprocess config */ + HalH264eVepuPrep hw_prep; + + /* input / recon / refer address config */ + HalH264eVepuAddr hw_addr; + VepuOffsetCfg hw_offset; + + /* macroblock ratecontrol config */ + HalH264eVepuMbRc hw_mbrc; + + /* syntax for input from enc_impl */ + RK_U32 updated; + H264eSps *sps; + H264ePps *pps; + H264eSlice *slice; + H264eFrmInfo *frms; + H264eReorderInfo *reorder; + H264eMarkingInfo *marking; + H264ePrefixNal *prefix; + + /* special TSVC stream header fixup */ + HalH264eVepuStreamAmend amend; + + /* vepu2 macroblock ratecontrol context */ + HalH264eVepuMbRcCtx rc_ctx; + + H264eVpu2RegSet regs_set; + H264eVpu2RegSet regs_get; +} HalH264eVepu2Ctx; + +static MPP_RET hal_h264e_vepu2_deinit_v2(void *hal) +{ + HalH264eVepu2Ctx *p = (HalH264eVepu2Ctx *)hal; + + hal_h264e_dbg_func("enter %p\n", p); + + if (p->dev) { + mpp_dev_deinit(p->dev); + p->dev = NULL; + } + + h264e_vepu_buf_deinit(&p->hw_bufs); + + if (p->rc_ctx) { + h264e_vepu_mbrc_deinit(p->rc_ctx); + p->rc_ctx = NULL; + } + + h264e_vepu_stream_amend_deinit(&p->amend); + + hal_h264e_dbg_func("leave %p\n", p); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu2_init_v2(void *hal, MppEncHalCfg *cfg) +{ + HalH264eVepu2Ctx *p = (HalH264eVepu2Ctx *)hal; + MPP_RET ret = MPP_OK; + + hal_h264e_dbg_func("enter %p\n", p); + + p->cfg = cfg->cfg; + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_VEPU2; + + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed ret: %d\n", ret); + goto DONE; + } + p->dev = cfg->dev; + + ret = h264e_vepu_buf_init(&p->hw_bufs); + if (ret) { + mpp_err_f("init vepu buffer failed ret: %d\n", ret); + goto DONE; + } + + ret = h264e_vepu_mbrc_init(&p->rc_ctx, &p->hw_mbrc); + if (ret) { + mpp_err_f("init mb rate control failed ret: %d\n", ret); + goto DONE; + } + + /* create buffer to TSVC stream */ + h264e_vepu_stream_amend_init(&p->amend); + +DONE: + if (ret) + hal_h264e_vepu2_deinit_v2(hal); + + hal_h264e_dbg_func("leave %p\n", p); + return ret; +} + +static RK_U32 update_vepu2_syntax(HalH264eVepu2Ctx *ctx, MppSyntax *syntax) +{ + H264eSyntaxDesc *desc = syntax->data; + RK_S32 syn_num = syntax->number; + RK_U32 updated = 0; + RK_S32 i; + + for (i = 0; i < syn_num; i++, desc++) { + switch (desc->type) { + case H264E_SYN_CFG : { + hal_h264e_dbg_detail("update cfg"); + ctx->cfg = desc->p; + } break; + case H264E_SYN_SPS : { + hal_h264e_dbg_detail("update sps"); + ctx->sps = desc->p; + } break; + case H264E_SYN_PPS : { + hal_h264e_dbg_detail("update pps"); + ctx->pps = desc->p; + } break; + case H264E_SYN_DPB : { + hal_h264e_dbg_detail("update dpb"); + } break; + case H264E_SYN_SLICE : { + hal_h264e_dbg_detail("update slice"); + ctx->slice = desc->p; + } break; + case H264E_SYN_FRAME : { + hal_h264e_dbg_detail("update frames"); + ctx->frms = desc->p; + } break; + case H264E_SYN_PREFIX : { + hal_h264e_dbg_detail("update prefix nal"); + ctx->prefix = desc->p; + } break; + default : { + mpp_log_f("invalid syntax type %d\n", desc->type); + } break; + } + + updated |= SYN_TYPE_FLAG(desc->type); + } + + return updated; +} + +static MPP_RET hal_h264e_vepu2_get_task_v2(void *hal, HalEncTask *task) +{ + HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal; + RK_U32 updated = update_vepu2_syntax(ctx, &task->syntax); + MppEncPrepCfg *prep = &ctx->cfg->prep; + HalH264eVepuPrep *hw_prep = &ctx->hw_prep; + HalH264eVepuAddr *hw_addr = &ctx->hw_addr; + HalH264eVepuBufs *hw_bufs = &ctx->hw_bufs; + VepuOffsetCfg *hw_offset = &ctx->hw_offset; + H264eFrmInfo *frms = ctx->frms; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (updated & SYN_TYPE_FLAG(H264E_SYN_CFG)) { + h264e_vepu_buf_set_frame_size(hw_bufs, prep->width, prep->height); + + /* preprocess setup */ + if (h264e_vepu_prep_setup(hw_prep, prep)) + return MPP_NOK; + + h264e_vepu_mbrc_setup(ctx->rc_ctx, ctx->cfg); + } + + if (updated & SYN_TYPE_FLAG(H264E_SYN_SLICE)) { + H264eSlice *slice = ctx->slice; + + h264e_vepu_buf_set_cabac_idc(hw_bufs, slice->cabac_init_idc); + } + + h264e_vepu_prep_get_addr(hw_prep, task->input, &hw_addr->orig); + + MppBuffer recn = h264e_vepu_buf_get_frame_buffer(hw_bufs, frms->curr_idx); + MppBuffer refr = h264e_vepu_buf_get_frame_buffer(hw_bufs, frms->refr_idx); + + hw_addr->recn[0] = mpp_buffer_get_fd(recn); + hw_addr->refr[0] = mpp_buffer_get_fd(refr); + hw_addr->recn[1] = hw_addr->recn[0]; + hw_addr->refr[1] = hw_addr->refr[0]; + + hw_offset->fmt = prep->format; + hw_offset->width = prep->width; + hw_offset->height = prep->height; + hw_offset->hor_stride = prep->hor_stride; + hw_offset->ver_stride = prep->ver_stride; + hw_offset->offset_x = mpp_frame_get_offset_x(task->frame); + hw_offset->offset_y = mpp_frame_get_offset_y(task->frame); + + get_vepu_offset_cfg(hw_offset); + + h264e_vepu_stream_amend_config(&ctx->amend, task->packet, ctx->cfg, + ctx->slice, ctx->prefix); + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static RK_S32 setup_output_packet(HalH264eVepu2Ctx *ctx, RK_U32 *reg, MppBuffer buf, RK_U32 offset) +{ + RK_U32 offset8 = offset & (~0x7); + RK_S32 fd = mpp_buffer_get_fd(buf); + RK_U32 hdr_rem_msb = 0; + RK_U32 hdr_rem_lsb = 0; + RK_U32 limit = 0; + + if (offset) { + RK_U8 *buf32 = (RK_U8 *)mpp_buffer_get_ptr(buf) + offset8; + + hdr_rem_msb = MPP_RB32(buf32); + hdr_rem_lsb = MPP_RB32(buf32 + 4); + } + + hal_h264e_dbg_detail("offset %d offset8 %d\n", offset, offset8); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_OUTPUT_STREAM, fd); + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_OUTPUT_STREAM >> 2, offset8); + + /* output buffer size is 64 bit address then 8 multiple size */ + limit = mpp_buffer_get_size(buf); + limit -= offset8; + limit >>= 3; + limit &= ~7; + H264E_HAL_SET_REG(reg, VEPU_REG_STR_BUF_LIMIT, limit); + + hal_h264e_dbg_detail("msb %08x lsb %08x", hdr_rem_msb, hdr_rem_lsb); + + H264E_HAL_SET_REG(reg, VEPU_REG_STR_HDR_REM_MSB, hdr_rem_msb); + H264E_HAL_SET_REG(reg, VEPU_REG_STR_HDR_REM_LSB, hdr_rem_lsb); + + return (offset - offset8) * 8; +} + +static MPP_RET setup_intra_refresh(HalH264eVepu2Ctx *ctx, EncFrmStatus *frm) +{ + MPP_RET ret = MPP_OK; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 refresh_num = ctx->cfg->rc.refresh_num; + MppEncCfgSet *cfg = ctx->cfg; + RK_U32 *reg = ctx->regs_set.val; + RK_U32 val = 0; + RK_S32 top = 0; + RK_S32 left = 0; + RK_S32 right = 0; + RK_S32 bottom = 0; + RK_U32 refresh_idx = frm->seq_idx % cfg->rc.gop; + + hal_h264e_dbg_func("enter\n"); + + if (!ctx->cfg->rc.refresh_en || !frm->is_i_refresh) { + goto RET; + } + + if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_ROW) { + left = 0; + right = mb_w; + top = refresh_idx * refresh_num - 2; + bottom = (refresh_idx + 1) * refresh_num - 1; + top = mpp_clip(top, 0, mb_h); + bottom = mpp_clip(bottom, 0, mb_h); + } else if (ctx->cfg->rc.refresh_mode == MPP_ENC_RC_INTRA_REFRESH_COL) { + top = 0; + bottom = mb_h; + left = refresh_idx * refresh_num - 2; + right = (refresh_idx + 1) * refresh_num - 1; + left = mpp_clip(left, 0, mb_w); + right = mpp_clip(right, 0, mb_w); + } + +RET: + val = VEPU_REG_INTRA_AREA_TOP(top) + | VEPU_REG_INTRA_AREA_BOTTOM(bottom) + | VEPU_REG_INTRA_AREA_LEFT(left) + | VEPU_REG_INTRA_AREA_RIGHT(right); + H264E_HAL_SET_REG(reg, VEPU_REG_INTRA_AREA_CTRL, val); + + hal_h264e_dbg_func("leave, ret %d\n", ret); + + return ret; +} + +static MPP_RET hal_h264e_vepu2_gen_regs_v2(void *hal, HalEncTask *task) +{ + //MPP_RET ret = MPP_OK; + HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal; + HalH264eVepuBufs *hw_bufs = &ctx->hw_bufs; + HalH264eVepuPrep *hw_prep = &ctx->hw_prep; + HalH264eVepuAddr *hw_addr = &ctx->hw_addr; + HalH264eVepuMbRc *hw_mbrc = &ctx->hw_mbrc; + VepuOffsetCfg *hw_offset = &ctx->hw_offset; + EncRcTaskInfo *rc_info = &task->rc_task->info; + EncFrmStatus *frm = &task->rc_task->frm; + H264eSps *sps = ctx->sps; + H264ePps *pps = ctx->pps; + H264eSlice *slice = ctx->slice; + RK_U32 *reg = ctx->regs_set.val; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 offset = mpp_packet_get_length(task->packet); + RK_U32 first_free_bit = 0; + RK_U32 val = 0; + RK_S32 i = 0; + + if (hw_prep->rotation) { + mb_w = ctx->sps->pic_height_in_mbs; + mb_h = ctx->sps->pic_width_in_mbs; + } + + hw_mbrc->qp_init = rc_info->quality_target; + hw_mbrc->qp_max = rc_info->quality_max; + hw_mbrc->qp_min = rc_info->quality_min; + + hal_h264e_dbg_func("enter %p\n", hal); + + hal_h264e_dbg_detail("frame %d generate regs now", frm->seq_idx); + + // prepare mb rc config + h264e_vepu_mbrc_prepare(ctx->rc_ctx, &ctx->hw_mbrc, task->rc_task); + h264e_vepu_slice_split_cfg(ctx->slice, &ctx->hw_mbrc, task->rc_task, ctx->cfg); + + /* setup output address with offset */ + first_free_bit = setup_output_packet(ctx, reg, task->output, offset); + + /* set extra byte for header */ + hw_mbrc->hdr_strm_size = offset; + hw_mbrc->hdr_free_size = first_free_bit / 8; + hw_mbrc->out_strm_size = 0; + + /* + * The hardware needs only the value for luma plane, because + * values of other planes are calculated internally based on + * format setting. + */ + setup_intra_refresh(ctx, frm); + + val = VEPU_REG_AXI_CTRL_READ_ID(0); + val |= VEPU_REG_AXI_CTRL_WRITE_ID(0); + val |= VEPU_REG_AXI_CTRL_BURST_LEN(16); + val |= VEPU_REG_AXI_CTRL_INCREMENT_MODE(0); + val |= VEPU_REG_AXI_CTRL_BIRST_DISCARD(0); + H264E_HAL_SET_REG(reg, VEPU_REG_AXI_CTRL, val); + + H264E_HAL_SET_REG(reg, VEPU_QP_ADJUST_MAD_DELTA_ROI, + hw_mbrc->mad_qp_change); + + val = 0; + if (mb_w * mb_h > 3600) + val = VEPU_REG_DISABLE_QUARTER_PIXEL_MV; + val |= VEPU_REG_CABAC_INIT_IDC(slice->cabac_init_idc); + if (pps->entropy_coding_mode) + val |= VEPU_REG_ENTROPY_CODING_MODE; + if (pps->transform_8x8_mode) + val |= VEPU_REG_H264_TRANS8X8_MODE; + if (sps->profile_idc > 31) + val |= VEPU_REG_H264_INTER4X4_MODE; + /*reg |= VEPU_REG_H264_STREAM_MODE;*/ + val |= VEPU_REG_H264_SLICE_SIZE(hw_mbrc->slice_size_mb_rows); + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL0, val); + + RK_U32 scaler = MPP_MAX(1, 200 / (mb_w + mb_h)); + + RK_U32 skip_penalty = MPP_MIN(255, h264_skip_sad_penalty[hw_mbrc->qp_init] * scaler); + + RK_U32 overfill_r = ((hw_prep->src_w & 0x0f) != 0) ? + ((16 - (hw_prep->src_w & 0x0f)) / 4) : 0; + + RK_U32 overfill_b = ((hw_prep->src_h & 0x0f) != 0) ? + (16 - (hw_prep->src_h & 0x0f)) : 0; + + val = VEPU_REG_STREAM_START_OFFSET(first_free_bit) | + VEPU_REG_SKIP_MACROBLOCK_PENALTY(skip_penalty) | + VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r) | + VEPU_REG_IN_IMG_CTRL_OVRFLB(overfill_b); + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_OVER_FILL_STRM_OFFSET, val); + + // When offset is zero row length should be total 16 aligned width + val = VEPU_REG_IN_IMG_CHROMA_OFFSET(0) + | VEPU_REG_IN_IMG_LUMA_OFFSET(0) + | VEPU_REG_IN_IMG_CTRL_ROW_LEN(hw_prep->pixel_stride); + + H264E_HAL_SET_REG(reg, VEPU_REG_INPUT_LUMA_INFO, val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[0]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[1]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(0), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[2]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[3]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(1), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[4]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[5]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(2), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[6]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[7]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(3), val); + + val = VEPU_REG_CHECKPOINT_CHECK1(hw_mbrc->cp_target[8]) + | VEPU_REG_CHECKPOINT_CHECK0(hw_mbrc->cp_target[9]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHECKPOINT(4), val); + + val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[0]) + | VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[1]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(0), val); + + val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[2]) + | VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[3]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(1), val); + + val = VEPU_REG_CHKPT_WORD_ERR_CHK1(hw_mbrc->cp_error[4]) + | VEPU_REG_CHKPT_WORD_ERR_CHK0(hw_mbrc->cp_error[5]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_WORD_ERR(2), val); + + val = VEPU_REG_CHKPT_DELTA_QP_CHK6(hw_mbrc->cp_delta_qp[6]) + | VEPU_REG_CHKPT_DELTA_QP_CHK5(hw_mbrc->cp_delta_qp[5]) + | VEPU_REG_CHKPT_DELTA_QP_CHK4(hw_mbrc->cp_delta_qp[4]) + | VEPU_REG_CHKPT_DELTA_QP_CHK3(hw_mbrc->cp_delta_qp[3]) + | VEPU_REG_CHKPT_DELTA_QP_CHK2(hw_mbrc->cp_delta_qp[2]) + | VEPU_REG_CHKPT_DELTA_QP_CHK1(hw_mbrc->cp_delta_qp[1]) + | VEPU_REG_CHKPT_DELTA_QP_CHK0(hw_mbrc->cp_delta_qp[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_CHKPT_DELTA_QP, val); + + val = VEPU_REG_MAD_THRESHOLD(hw_mbrc->mad_threshold) + | VEPU_REG_IN_IMG_CTRL_FMT(hw_prep->src_fmt) + | VEPU_REG_IN_IMG_ROTATE_MODE(hw_prep->rotation) + | VEPU_REG_SIZE_TABLE_PRESENT; //FIXED + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL1, val); + + val = VEPU_REG_INTRA16X16_MODE(h264_intra16_favor[hw_mbrc->qp_init]) + | VEPU_REG_INTER_MODE(h264_inter_favor[hw_mbrc->qp_init]); + H264E_HAL_SET_REG(reg, VEPU_REG_INTRA_INTER_MODE, val); + + val = VEPU_REG_PPS_INIT_QP(pps->pic_init_qp) + | VEPU_REG_SLICE_FILTER_ALPHA(slice->slice_alpha_c0_offset_div2) + | VEPU_REG_SLICE_FILTER_BETA(slice->slice_beta_offset_div2) + | VEPU_REG_CHROMA_QP_OFFSET(pps->chroma_qp_index_offset) + | VEPU_REG_IDR_PIC_ID(slice->idr_pic_id); + + if (slice->disable_deblocking_filter_idc) + val |= VEPU_REG_FILTER_DISABLE; + + if (pps->constrained_intra_pred) + val |= VEPU_REG_CONSTRAINED_INTRA_PREDICTION; + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL2, val); + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_NEXT_PIC, 0); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_MV_OUT, 0); + + MppBuffer cabac_table = hw_bufs->cabac_table; + RK_S32 cabac_table_fd = cabac_table ? mpp_buffer_get_fd(cabac_table) : 0; + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_CABAC_TBL, cabac_table_fd); + + val = VEPU_REG_ROI1_TOP_MB(mb_h) + | VEPU_REG_ROI1_BOTTOM_MB(mb_h) + | VEPU_REG_ROI1_LEFT_MB(mb_w) + | VEPU_REG_ROI1_RIGHT_MB(mb_w); + H264E_HAL_SET_REG(reg, VEPU_REG_ROI1, val); + + val = VEPU_REG_ROI2_TOP_MB(mb_h) + | VEPU_REG_ROI2_BOTTOM_MB(mb_h) + | VEPU_REG_ROI2_LEFT_MB(mb_w) + | VEPU_REG_ROI2_RIGHT_MB(mb_w); + H264E_HAL_SET_REG(reg, VEPU_REG_ROI2, val); + H264E_HAL_SET_REG(reg, VEPU_REG_STABLILIZATION_OUTPUT, 0); + + val = VEPU_REG_RGB2YUV_CONVERSION_COEFB(hw_prep->color_conversion_coeff_b) + | VEPU_REG_RGB2YUV_CONVERSION_COEFA(hw_prep->color_conversion_coeff_a); + H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF1, val); + + val = VEPU_REG_RGB2YUV_CONVERSION_COEFE(hw_prep->color_conversion_coeff_e) + | VEPU_REG_RGB2YUV_CONVERSION_COEFC(hw_prep->color_conversion_coeff_c); + H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF2, val); + + val = VEPU_REG_RGB2YUV_CONVERSION_COEFF(hw_prep->color_conversion_coeff_f); + H264E_HAL_SET_REG(reg, VEPU_REG_RGB2YUV_CONVERSION_COEF3, val); + + val = VEPU_REG_RGB_MASK_B_MSB(hw_prep->b_mask_msb) + | VEPU_REG_RGB_MASK_G_MSB(hw_prep->g_mask_msb) + | VEPU_REG_RGB_MASK_R_MSB(hw_prep->r_mask_msb); + H264E_HAL_SET_REG(reg, VEPU_REG_RGB_MASK_MSB, val); //FIXED + + { + RK_U32 diff_mv_penalty[3] = {0}; + diff_mv_penalty[0] = h264_diff_mv_penalty4p[hw_mbrc->qp_init]; + diff_mv_penalty[1] = h264_diff_mv_penalty[hw_mbrc->qp_init]; + diff_mv_penalty[2] = h264_diff_mv_penalty[hw_mbrc->qp_init]; + + val = VEPU_REG_1MV_PENALTY(diff_mv_penalty[1]) + | VEPU_REG_QMV_PENALTY(diff_mv_penalty[2]) + | VEPU_REG_4MV_PENALTY(diff_mv_penalty[0]); + } + + val |= VEPU_REG_SPLIT_MV_MODE_EN; + H264E_HAL_SET_REG(reg, VEPU_REG_MV_PENALTY, val); + + val = VEPU_REG_H264_LUMA_INIT_QP(hw_mbrc->qp_init) + | VEPU_REG_H264_QP_MAX(hw_mbrc->qp_max) + | VEPU_REG_H264_QP_MIN(hw_mbrc->qp_min) + | VEPU_REG_H264_CHKPT_DISTANCE(hw_mbrc->cp_distance_mbs); + H264E_HAL_SET_REG(reg, VEPU_REG_QP_VAL, val); + + val = VEPU_REG_ZERO_MV_FAVOR_D2(10); + H264E_HAL_SET_REG(reg, VEPU_REG_MVC_RELATE, val); + + val = VEPU_REG_OUTPUT_SWAP32 + | VEPU_REG_OUTPUT_SWAP16 + | VEPU_REG_OUTPUT_SWAP8 + | VEPU_REG_INPUT_SWAP8_(hw_prep->swap_8_in) + | VEPU_REG_INPUT_SWAP16_(hw_prep->swap_16_in) + | VEPU_REG_INPUT_SWAP32_(hw_prep->swap_32_in); + H264E_HAL_SET_REG(reg, VEPU_REG_DATA_ENDIAN, val); + + val = VEPU_REG_PPS_ID(pps->pps_id) + | VEPU_REG_INTRA_PRED_MODE(h264_prev_mode_favor[hw_mbrc->qp_init]) + | VEPU_REG_FRAME_NUM(slice->frame_num); + H264E_HAL_SET_REG(reg, VEPU_REG_ENC_CTRL3, val); + + val = VEPU_REG_INTERRUPT_TIMEOUT_EN; + H264E_HAL_SET_REG(reg, VEPU_REG_INTERRUPT, val); + + { + RK_U8 dmv_penalty[128] = {0}; + RK_U8 dmv_qpel_penalty[128] = {0}; + + for (i = 0; i < 128; i++) { + dmv_penalty[i] = i; + dmv_qpel_penalty[i] = MPP_MIN(255, exp_golomb_signed(i)); + } + + for (i = 0; i < 128; i += 4) { + val = VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i], 3); + val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 1], 2); + val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 2], 1); + val |= VEPU_REG_DMV_PENALTY_TABLE_BIT(dmv_penalty[i + 3], 0); + H264E_HAL_SET_REG(reg, VEPU_REG_DMV_PENALTY_TBL(i / 4), val); + + val = VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT( + dmv_qpel_penalty[i], 3); + val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT( + dmv_qpel_penalty[i + 1], 2); + val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT( + dmv_qpel_penalty[i + 2], 1); + val |= VEPU_REG_DMV_Q_PIXEL_PENALTY_TABLE_BIT( + dmv_qpel_penalty[i + 3], 0); + H264E_HAL_SET_REG(reg, VEPU_REG_DMV_Q_PIXEL_PENALTY_TBL(i / 4), val); + } + } + + /* set buffers addr */ + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_LUMA, hw_addr->orig[0]); + if (hw_offset->offset_byte[0]) + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_IN_LUMA >> 2, + hw_offset->offset_byte[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_CB, hw_addr->orig[1]); + if (hw_offset->offset_byte[1]) + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_IN_CB >> 2, + hw_offset->offset_byte[1]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_IN_CR, hw_addr->orig[2]); + if (hw_offset->offset_byte[2]) + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_IN_CR >> 2, + hw_offset->offset_byte[2]); + + MppBuffer nal_size_table = h264e_vepu_buf_get_nal_size_table(hw_bufs); + RK_S32 nal_size_table_fd = nal_size_table ? mpp_buffer_get_fd(nal_size_table) : 0; + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_OUTPUT_CTRL, nal_size_table_fd); + + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REC_LUMA, hw_addr->recn[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REC_CHROMA, hw_addr->recn[1]); + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_REC_CHROMA >> 2, hw_bufs->yuv_size); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REF_LUMA, hw_addr->refr[0]); + H264E_HAL_SET_REG(reg, VEPU_REG_ADDR_REF_CHROMA, hw_addr->refr[1]); + mpp_dev_set_reg_offset(ctx->dev, VEPU_REG_ADDR_REF_CHROMA >> 2, hw_bufs->yuv_size); + + /* set important encode mode info */ + val = VEPU_REG_MB_HEIGHT(mb_h) + | VEPU_REG_MB_WIDTH(mb_w) + | VEPU_REG_PIC_TYPE(slice->idr_flag) + | VEPU_REG_ENCODE_FORMAT(3) + | VEPU_REG_ENCODE_ENABLE; + H264E_HAL_SET_REG(reg, VEPU_REG_ENCODE_START, val); + + ctx->frame_cnt++; + + hal_h264e_dbg_func("leave %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu2_start_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal; + (void)task; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (ctx->dev) { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = sizeof(ctx->regs_set); + + do { + wr_cfg.reg = &ctx->regs_set; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = &ctx->regs_get; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + } else + mpp_err("invalid NULL device ctx\n"); + + hal_h264e_dbg_func("leave %p\n", hal); + + return ret; +} + +static void h264e_vepu2_get_mbrc(HalH264eVepuMbRc *mb_rc, H264eVpu2RegSet *reg) +{ + RK_S32 i = 0; + RK_U32 cpt_prev = 0; + RK_U32 overflow = 0; + RK_U32 cpt_idx = VEPU_REG_CHECKPOINT(0) / 4; + RK_U32 *reg_val = reg->val; + + mb_rc->hw_status = reg_val[VEPU_REG_INTERRUPT / 4]; + mb_rc->out_strm_size = reg_val[VEPU_REG_STR_BUF_LIMIT / 4] / 8 - mb_rc->hdr_free_size; + mb_rc->qp_sum = ((reg_val[VEPU_REG_QP_SUM_DIV2 / 4] >> 11) & 0x001fffff) * 2; + mb_rc->less_mad_count = (reg_val[VEPU_REG_MB_CTRL / 4] >> 16) & 0xffff; + mb_rc->rlc_count = reg_val[VEPU_REG_RLC_SUM / 4] & 0x3fffff; + + for (i = 0; i < VEPU_CHECK_POINTS_MAX; i++) { + RK_U32 cpt = VEPU_REG_CHECKPOINT_RESULT(reg_val[cpt_idx]); + + if (cpt < cpt_prev) + overflow += (1 << 21); + + cpt_prev = cpt; + mb_rc->cp_usage[i] = cpt + overflow; + cpt_idx += (i & 1); + } +} + +static MPP_RET hal_h264e_vepu2_wait_v2(void *hal, HalEncTask *task) +{ + HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal; + HalH264eVepuMbRc *hw_mbrc = &ctx->hw_mbrc; + H264NaluType type = (task->rc_task->frm.is_idr != 0) ? H264_NALU_TYPE_IDR : H264_NALU_TYPE_SLICE; + MppPacket pkt = task->packet; + RK_S32 offset = mpp_packet_get_length(pkt); + MPP_RET ret = MPP_NOK; + + hal_h264e_dbg_func("enter %p\n", hal); + + if (ctx->dev) { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } else { + mpp_err("invalid NULL device ctx\n"); + return ret; + } + + h264e_vepu2_get_mbrc(hw_mbrc, &ctx->regs_get); + h264e_vepu_mbrc_update(ctx->rc_ctx, hw_mbrc); + + mpp_packet_add_segment_info(pkt, type, offset, hw_mbrc->out_strm_size); + + { + HalH264eVepuStreamAmend *amend = &ctx->amend; + + if (amend->enable) { + amend->old_length = hw_mbrc->out_strm_size; + h264e_vepu_stream_amend_proc(amend, &ctx->cfg->h264.hw_cfg); + ctx->hw_mbrc.out_strm_size = amend->new_length; + } else if (amend->prefix) { + /* check prefix value */ + amend->old_length = hw_mbrc->out_strm_size; + h264e_vepu_stream_amend_sync_ref_idc(amend); + } + } + + task->hw_length += ctx->hw_mbrc.out_strm_size; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +static MPP_RET hal_h264e_vepu2_ret_task_v2(void *hal, HalEncTask *task) +{ + HalH264eVepu2Ctx *ctx = (HalH264eVepu2Ctx *)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + RK_U32 mb_w = ctx->sps->pic_width_in_mbs; + RK_U32 mb_h = ctx->sps->pic_height_in_mbs; + RK_U32 mbs = mb_w * mb_h; + + hal_h264e_dbg_func("enter %p\n", hal); + + task->length += task->hw_length; + + rc_info->bit_real = task->hw_length * 8; + rc_info->quality_real = ctx->hw_mbrc.qp_sum / mbs; + + hal_h264e_dbg_rc("real bit %d quality %d\n", rc_info->bit_real, rc_info->quality_real); + + task->hal_ret.data = rc_info; + task->hal_ret.number = 1; + + hal_h264e_dbg_func("leave %p\n", hal); + + return MPP_OK; +} + +const MppEncHalApi hal_h264e_vepu2 = { + .name = "hal_h264e_vepu2", + .coding = MPP_VIDEO_CodingAVC, + .ctx_size = sizeof(HalH264eVepu2Ctx), + .flag = 0, + .init = hal_h264e_vepu2_init_v2, + .deinit = hal_h264e_vepu2_deinit_v2, + .prepare = NULL, + .get_task = hal_h264e_vepu2_get_task_v2, + .gen_regs = hal_h264e_vepu2_gen_regs_v2, + .start = hal_h264e_vepu2_start_v2, + .wait = hal_h264e_vepu2_wait_v2, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_h264e_vepu2_ret_task_v2, + .client = VPU_CLIENT_VEPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RV1108, + ROCKCHIP_SOC_RV1109, + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_h264e_vepu2) diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.h b/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.h new file mode 100644 index 000000000..991206115 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU2_H +#define HAL_H264E_VEPU2_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_h264e_vepu2; + +#endif diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.c b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.c new file mode 100644 index 000000000..8b0544e4a --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.c @@ -0,0 +1,714 @@ +/* + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "hal_h264e_vepu_v2" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_buffer.h" +#include "mpp_enc_ref.h" + +#include "vepu_common.h" + +#include "h264e_slice.h" +#include "hal_h264e_debug.h" +#include "hal_h264e_vepu_v2.h" +#include "hal_h264e_vpu_tbl_v2.h" + +typedef struct HalH264eVepuMbRcImpl_t { + RK_S32 width; + RK_S32 height; + RK_S32 mb_w; + RK_S32 mb_h; + + RK_S32 pels; + RK_S32 mbs; + + RK_S32 bits_per_pic; + + RK_S32 mb_bit_rc_enable; + + /* frame rate control */ + RK_S32 fps_in_num; + RK_S32 fps_in_denom; + RK_S32 fps_out_num; + RK_S32 fps_out_denom; + + RK_S32 fps_count; + RK_S32 fps_step; + RK_S32 fps_threshold; + + /* + * MAD based QP adjustment + * mad_qp_change [-8..7] + * mad_threshold MAD threshold div256 + */ + RK_S32 mad_qp_change; + RK_S32 mad_threshold; + + /* + * check point parameter + */ + RK_S32 check_point_count; + RK_S32 check_point_distance; + + /* estimated first I frame qp */ + RK_S32 qp_init_est; + + RK_S32 frame_type; + RK_S32 pre_frame_type; +} HalH264eVepuMbRcImpl; + +RK_S32 exp_golomb_signed(RK_S32 val) +{ + RK_S32 tmp = 0; + + if (val > 0) + val = 2 * val; + else + val = -2 * val + 1; + + while (val >> ++tmp) + ; + + return tmp * 2 - 1; +} + +static void vepu_swap_endian(RK_U32 *buf, RK_S32 size_bytes) +{ + RK_U32 i = 0; + RK_S32 words = size_bytes / 4; + RK_U32 val, val2, tmp, tmp2; + + mpp_assert((size_bytes % 8) == 0); + + while (words > 0) { + val = buf[i]; + tmp = 0; + + tmp |= (val & 0xFF) << 24; + tmp |= (val & 0xFF00) << 8; + tmp |= (val & 0xFF0000) >> 8; + tmp |= (val & 0xFF000000) >> 24; + { + val2 = buf[i + 1]; + tmp2 = 0; + + tmp2 |= (val2 & 0xFF) << 24; + tmp2 |= (val2 & 0xFF00) << 8; + tmp2 |= (val2 & 0xFF0000) >> 8; + tmp2 |= (val2 & 0xFF000000) >> 24; + + buf[i] = tmp2; + words--; + i++; + } + buf[i] = tmp; + words--; + i++; + } +} + +static void vepu_write_cabac_table(MppBuffer buf, RK_S32 cabac_init_idc) +{ + const RK_S32(*context)[460][2]; + RK_S32 i, j, qp; + RK_U8 table[H264E_CABAC_TABLE_BUF_SIZE] = {0}; + + for (qp = 0; qp < 52; qp++) { /* All QP values */ + for (j = 0; j < 2; j++) { /* Intra/Inter */ + if (j == 0) + /*lint -e(545) */ + context = &h264_context_init_intra; + else + /*lint -e(545) */ + context = &h264_context_init[cabac_init_idc]; + + for (i = 0; i < 460; i++) { + RK_S32 m = (RK_S32)(*context)[i][0]; + RK_S32 n = (RK_S32)(*context)[i][1]; + + RK_S32 pre_ctx_state = MPP_CLIP3(1, 126, ((m * (RK_S32)qp) >> 4) + n); + + if (pre_ctx_state <= 63) + table[qp * 464 * 2 + j * 464 + i] = + (RK_U8)((63 - pre_ctx_state) << 1); + else + table[qp * 464 * 2 + j * 464 + i] = + (RK_U8)(((pre_ctx_state - 64) << 1) | 1); + } + } + } + + vepu_swap_endian((RK_U32 *)table, H264E_CABAC_TABLE_BUF_SIZE); + mpp_buffer_write(buf, 0, table, H264E_CABAC_TABLE_BUF_SIZE); +} + +MPP_RET h264e_vepu_buf_init(HalH264eVepuBufs *bufs) +{ + MPP_RET ret = MPP_OK; + + hal_h264e_dbg_buffer("enter %p\n", bufs); + + memset(bufs, 0, sizeof(*bufs)); + + // do not create buffer on cavlc case + bufs->cabac_init_idc = -1; + ret = mpp_buffer_group_get_internal(&bufs->group, MPP_BUFFER_TYPE_ION); + if (ret) + mpp_err_f("get buffer group failed ret %d\n", ret); + + hal_h264e_dbg_buffer("leave %p\n", bufs); + + return ret; +} + +MPP_RET h264e_vepu_buf_deinit(HalH264eVepuBufs *bufs) +{ + RK_S32 i; + + hal_h264e_dbg_buffer("enter %p\n", bufs); + + if (bufs->cabac_table) + mpp_buffer_put(bufs->cabac_table); + + if (bufs->nal_size_table) + mpp_buffer_put(bufs->nal_size_table); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(bufs->frm_buf); i++) { + if (bufs->frm_buf[i]) + mpp_buffer_put(bufs->frm_buf[i]); + } + + if (bufs->group) + mpp_buffer_group_put(bufs->group); + + memset(bufs, 0, sizeof(*bufs)); + bufs->cabac_init_idc = -1; + + hal_h264e_dbg_buffer("leave %p\n", bufs); + + return MPP_OK; +} + +MPP_RET h264e_vepu_buf_set_cabac_idc(HalH264eVepuBufs *bufs, RK_S32 idc) +{ + hal_h264e_dbg_buffer("enter %p\n", bufs); + + if (idc >= 0 && !bufs->cabac_table) + mpp_buffer_get(bufs->group, &bufs->cabac_table, H264E_CABAC_TABLE_BUF_SIZE); + + if (bufs->cabac_table && idc != bufs->cabac_init_idc && idc >= 0) + vepu_write_cabac_table(bufs->cabac_table, idc); + + bufs->cabac_init_idc = idc; + + hal_h264e_dbg_buffer("leave %p\n", bufs); + + return MPP_OK; +} + +MPP_RET h264e_vepu_buf_set_frame_size(HalH264eVepuBufs *bufs, RK_S32 w, RK_S32 h) +{ + RK_S32 aligned_w = MPP_ALIGN(w, 16); + RK_S32 aligned_h = MPP_ALIGN(h, 16); + size_t yuv_size = aligned_w * aligned_h; + size_t frm_size = yuv_size * 3 / 2; + RK_S32 i; + RK_S32 cnt = (RK_S32)MPP_ARRAY_ELEMS(bufs->frm_buf); + + hal_h264e_dbg_buffer("enter %p\n", bufs); + + mpp_assert(frm_size); + + if (frm_size != bufs->frm_size) { + if (bufs->frm_size) { + /* reallocate only on larger frame size to save time */ + mpp_log("new frame size [%d:%d] require buffer %d not equal to %d\n", + w, h, frm_size, bufs->frm_size); + } + + for (i = 0; i < cnt; i++) { + if (bufs->frm_buf[i]) { + mpp_buffer_put(bufs->frm_buf[i]); + bufs->frm_buf[i] = NULL; + bufs->frm_cnt--; + } + } + } + + bufs->mb_h = aligned_h >> 4; + if (bufs->mb_h) + bufs->nal_tab_size = MPP_ALIGN((bufs->mb_h + 1) * sizeof(RK_U32), 8); + else + bufs->nal_tab_size = 0; + + bufs->yuv_size = yuv_size; + bufs->frm_size = frm_size; + + hal_h264e_dbg_buffer("leave %p\n", bufs); + + return MPP_OK; +} + +MppBuffer h264e_vepu_buf_get_nal_size_table(HalH264eVepuBufs *bufs) +{ + MppBuffer buf = bufs->nal_size_table; + + hal_h264e_dbg_buffer("enter %p\n", bufs); + + if (NULL == buf) { + mpp_buffer_get(bufs->group, &buf, bufs->nal_tab_size); + mpp_assert(buf); + bufs->nal_size_table = buf; + } + + hal_h264e_dbg_buffer("leave %p\n", bufs); + + return buf; +} + +MppBuffer h264e_vepu_buf_get_frame_buffer(HalH264eVepuBufs *bufs, RK_S32 index) +{ + MppBuffer buf = bufs->frm_buf[index]; + + hal_h264e_dbg_buffer("enter\n", bufs); + + if (NULL == buf) { + mpp_buffer_get(bufs->group, &buf, bufs->frm_size); + mpp_assert(buf); + bufs->frm_buf[index] = buf; + bufs->frm_cnt++; + } + + hal_h264e_dbg_buffer("leave %p\n", bufs); + + return buf; +} + +MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg) +{ + MPP_RET ret = MPP_OK; + MppFrameFormat format = cfg->format; + VepuFormatCfg fmt_cfg; + RK_U32 width = cfg->width; + RK_U32 height = cfg->height; + RK_U32 rotation = 0; + + hal_h264e_dbg_buffer("enter\n"); + + // do not support mirroring + if (cfg->mirroring) + mpp_err_f("Warning: do not support mirroring\n"); + + if (cfg->rotation == MPP_ENC_ROT_90) + rotation = 1; + else if (cfg->rotation == MPP_ENC_ROT_270) + rotation = 2; + else if (cfg->rotation != MPP_ENC_ROT_0) + mpp_err_f("Warning: only support 90 or 270 degree rotate, request rotate %d", rotation); + + if (rotation) + MPP_SWAP(RK_U32, width, height); + + prep->src_fmt = format; + prep->rotation = rotation; + prep->src_w = width; + prep->src_h = height; + + if (!get_vepu_fmt(&fmt_cfg, format)) { + prep->r_mask_msb = fmt_cfg.r_mask; + prep->g_mask_msb = fmt_cfg.g_mask; + prep->b_mask_msb = fmt_cfg.b_mask; + prep->swap_8_in = fmt_cfg.swap_8_in; + prep->swap_16_in = fmt_cfg.swap_16_in; + prep->swap_32_in = fmt_cfg.swap_32_in; + prep->src_fmt = fmt_cfg.format; + } else { + prep->src_fmt = VEPU_FMT_BUTT; + } + + if (format < MPP_FRAME_FMT_RGB) { + // YUV case + if (prep->src_fmt == VEPU_FMT_BUTT) { + mpp_err("vepu do not support input frame format %d\n", format); + ret = MPP_NOK; + } + + prep->color_conversion_coeff_a = 0; + prep->color_conversion_coeff_b = 0; + prep->color_conversion_coeff_c = 0; + prep->color_conversion_coeff_e = 0; + prep->color_conversion_coeff_f = 0; + } else { + + if (prep->src_fmt == VEPU_FMT_BUTT) { + mpp_err("vepu do not support input frame format %d\n", format); + ret = MPP_NOK; + } + + switch (cfg->color) { + case MPP_FRAME_SPC_RGB : { + /* BT.601 */ + /* Y = 0.2989 R + 0.5866 G + 0.1145 B + * Cb = 0.5647 (B - Y) + 128 + * Cr = 0.7132 (R - Y) + 128 + */ + prep->color_conversion_coeff_a = 19589; + prep->color_conversion_coeff_b = 38443; + prep->color_conversion_coeff_c = 7504; + prep->color_conversion_coeff_e = 37008; + prep->color_conversion_coeff_f = 46740; + } break; + case MPP_FRAME_SPC_BT709 : { + /* BT.709 */ + /* Y = 0.2126 R + 0.7152 G + 0.0722 B + * Cb = 0.5389 (B - Y) + 128 + * Cr = 0.6350 (R - Y) + 128 + */ + prep->color_conversion_coeff_a = 13933; + prep->color_conversion_coeff_b = 46871; + prep->color_conversion_coeff_c = 4732; + prep->color_conversion_coeff_e = 35317; + prep->color_conversion_coeff_f = 41615; + } break; + default : { + prep->color_conversion_coeff_a = 19589; + prep->color_conversion_coeff_b = 38443; + prep->color_conversion_coeff_c = 7504; + prep->color_conversion_coeff_e = 37008; + prep->color_conversion_coeff_f = 46740; + } break; + } + } + + /* NOTE: vepu only support 8bit encoding and stride must match with width align to 16 */ + RK_S32 hor_stride = cfg->hor_stride; + RK_S32 ver_stride = cfg->ver_stride; + VepuStrideCfg *stride_cfg = &prep->stride_cfg; + + prep->offset_cb = 0; + prep->offset_cr = 0; + get_vepu_pixel_stride(stride_cfg, prep->src_w, hor_stride, format); + prep->pixel_stride = stride_cfg->pixel_stride; + hor_stride = stride_cfg->pixel_stride * stride_cfg->pixel_size; + + switch (format & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP : { + prep->offset_cb = hor_stride * ver_stride; + prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); + prep->size_c = hor_stride / 2 * MPP_ALIGN(prep->src_h / 2, 8); + } break; + case MPP_FMT_YUV420P : { + prep->offset_cb = hor_stride * ver_stride; + prep->offset_cr = prep->offset_cb + ((hor_stride * ver_stride) / 4); + prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); + prep->size_c = hor_stride / 2 * MPP_ALIGN(prep->src_h / 2, 8); + } break; + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_UYVY : { + prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); + prep->size_c = 0; + } break; + case MPP_FMT_RGB565 : + case MPP_FMT_BGR565 : + case MPP_FMT_RGB555 : + case MPP_FMT_BGR555 : + case MPP_FMT_RGB444 : + case MPP_FMT_BGR444 : { + prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); + prep->size_c = 0; + } break; + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_RGBA8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGB101010 : + case MPP_FMT_BGR101010 : { + prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); + prep->size_c = 0; + } break; + default: { + mpp_err_f("invalid format %d", format); + ret = MPP_NOK; + } + } + + hal_h264e_dbg_buffer("leave\n"); + + return ret; +} + +MPP_RET h264e_vepu_prep_get_addr(HalH264eVepuPrep *prep, MppBuffer buffer, + RK_U32 (*addr)[3]) +{ + RK_U32 fd = (RK_U32)mpp_buffer_get_fd(buffer); + size_t size = mpp_buffer_get_size(buffer); + + hal_h264e_dbg_buffer("enter\n"); + + (*addr)[0] = fd; + (*addr)[1] = fd; + (*addr)[2] = fd; + + if (size < prep->size_y) + mpp_err("warnning: input buffer size 0x%x is smaller than required size 0x%x", + size, prep->size_y); + + if (prep->size_c && (prep->offset_cb || prep->offset_cr)) { + if (prep->offset_cb && (size < prep->offset_cb + prep->size_c)) + mpp_err("warnning: input buffer size 0x%x is smaller than cb requirement 0x%x + 0x%x", + size, prep->offset_cb, prep->size_c); + + if (prep->offset_cr && (size < prep->offset_cr + prep->size_c)) + mpp_err("warnning: input buffer size 0x%x is smaller than cb requirement 0x%x + 0x%x", + size, prep->offset_cr, prep->size_c); + } + + hal_h264e_dbg_buffer("leave\n"); + + return MPP_OK; +} + +MPP_RET h264e_vepu_mbrc_init(HalH264eVepuMbRcCtx *ctx, HalH264eVepuMbRc *mbrc) +{ + MPP_RET ret = MPP_OK; + HalH264eVepuMbRcImpl *p = mpp_calloc(HalH264eVepuMbRcImpl, 1); + if (!p) { + mpp_err_f("failed to alloc rate control context\n"); + ret = MPP_ERR_NOMEM; + } + + memset(mbrc, 0, sizeof(*mbrc)); + mbrc->qp_init = -1; + mbrc->qp_max = 48; + mbrc->qp_min = 16; + + *ctx = p; + return ret; +} + +MPP_RET h264e_vepu_mbrc_deinit(HalH264eVepuMbRcCtx ctx) +{ + MPP_FREE(ctx); + return MPP_OK; +} + +MPP_RET h264e_vepu_mbrc_setup(HalH264eVepuMbRcCtx ctx, MppEncCfgSet*cfg) +{ + HalH264eVepuMbRcImpl *p = (HalH264eVepuMbRcImpl *)ctx; + MppEncPrepCfg *prep = &cfg->prep; + MppEncRcCfg *rc = &cfg->rc; + MppEncHwCfg* hw_cfg = &cfg->hw; + + hal_h264e_dbg_func("enter\n"); + + // get necessary parameter from config + p->width = prep->width; + p->height = prep->height; + p->mb_w = MPP_ALIGN(prep->width, 16) / 16; + p->mb_h = MPP_ALIGN(prep->height, 16) / 16; + p->pels = p->width * p->height; + p->mbs = p->mb_w * p->mb_h; + p->bits_per_pic = axb_div_c(rc->bps_target, rc->fps_out_denom, + rc->fps_out_num); + + mpp_assert(p->pels); + + // frame rate control + mpp_assert(rc->fps_out_num / rc->fps_out_denom <= rc->fps_in_num / rc->fps_in_denom); + + p->fps_in_num = rc->fps_in_num; + p->fps_in_denom = rc->fps_in_denom; + p->fps_out_num = rc->fps_out_num; + p->fps_out_denom = rc->fps_out_denom; + + p->fps_step = rc->fps_in_denom * rc->fps_out_num; + p->fps_threshold = rc->fps_in_num * rc->fps_out_denom; + p->fps_count = p->fps_threshold; + + // if not constant + p->mb_bit_rc_enable = !hw_cfg->mb_rc_disable && (rc->rc_mode != MPP_ENC_RC_MODE_FIXQP); + + hal_h264e_dbg_rc("estimated init qp %d\n", p->qp_init_est); + + // init first frame mad parameter + p->mad_qp_change = 2; + p->mad_threshold = 256 * 6; + + // init check point position + if (p->mb_bit_rc_enable) { + p->check_point_count = MPP_MIN(p->mb_h - 1, VEPU_CHECK_POINTS_MAX); + p->check_point_distance = p->mbs / (p->check_point_count + 1); + } else { + p->check_point_count = 0; + p->check_point_distance = 0; + } + + p->frame_type = INTRA_FRAME; + p->pre_frame_type = INTRA_FRAME; + + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + +#define WORD_CNT_MAX 65535 + +MPP_RET h264e_vepu_mbrc_prepare(HalH264eVepuMbRcCtx ctx, HalH264eVepuMbRc *mbrc, + EncRcTask *rc_task) +{ + HalH264eVepuMbRcImpl *p = (HalH264eVepuMbRcImpl *)ctx; + EncFrmStatus *frm = &rc_task->frm; + EncRcTaskInfo *info = &rc_task->info; + + RK_S32 i; + const RK_S32 sscale = 256; + RK_S32 scaler, srcPrm; + RK_S32 tmp, nonZeroTarget; + RK_S32 coeffCntMax = p->mbs * 24 * 16; + + mbrc->qp_init = info->quality_target; + mbrc->qp_min = info->quality_min; + mbrc->qp_max = info->quality_max; + mbrc->mad_qp_change = 0; + mbrc->mad_threshold = 0; + mbrc->cp_distance_mbs = 0; + + if (!p->mb_bit_rc_enable) + return MPP_OK; + + p->pre_frame_type = p->frame_type; + p->frame_type = (frm->is_intra != 0) ? INTRA_FRAME : INTER_P_FRAME; + + if (mbrc->rlc_count == 0) { + mbrc->rlc_count = 1; + } + + srcPrm = axb_div_c(mbrc->out_strm_size * 8, 256, mbrc->rlc_count); + /* Disable Mb Rc for Intra Slices, because coeffTarget will be wrong */ + if (frm->is_intra || srcPrm == 0) + return 0; + + /* Required zero cnt */ + nonZeroTarget = axb_div_c(info->bit_target, 256, srcPrm); + nonZeroTarget = MPP_MIN(coeffCntMax, MPP_MAX(0, nonZeroTarget)); + nonZeroTarget = MPP_MIN(0x7FFFFFFFU / 1024U, (RK_U32)nonZeroTarget); + + if (nonZeroTarget > 0) { + scaler = axb_div_c(nonZeroTarget, sscale, (RK_S32) p->mbs); + } else { + return 0; + } + + if ((p->frame_type != p->pre_frame_type) || (mbrc->rlc_count == 0)) { + for (i = 0; i < VEPU_CHECK_POINTS_MAX; i++) { + tmp = (scaler * (p->check_point_distance * (i + 1) + 1)) / sscale; + tmp = MPP_MIN(WORD_CNT_MAX, tmp / 32 + 1); + if (tmp < 0) tmp = WORD_CNT_MAX; /* Detect overflow */ + mbrc->cp_target[i] = tmp; /* div32 for regs */ + } + + tmp = axb_div_c(p->bits_per_pic, 256, srcPrm); + } else { + for (i = 0; i < VEPU_CHECK_POINTS_MAX; i++) { + tmp = (RK_S32) (mbrc->cp_usage[i] * scaler) / sscale; + tmp = MPP_MIN(WORD_CNT_MAX, tmp / 32 + 1); + if (tmp < 0) tmp = WORD_CNT_MAX; /* Detect overflow */ + mbrc->cp_target[i] = tmp; /* div32 for regs */ + } + tmp = axb_div_c(p->bits_per_pic, 256, srcPrm); + } + + mbrc->cp_error[0] = -tmp * 3; + mbrc->cp_delta_qp[0] = 3; + mbrc->cp_error[1] = -tmp * 2; + mbrc->cp_delta_qp[1] = 2; + mbrc->cp_error[2] = -tmp * 1; + mbrc->cp_delta_qp[2] = 1; + mbrc->cp_error[3] = tmp * 1; + mbrc->cp_delta_qp[3] = 0; + mbrc->cp_error[4] = tmp * 2; + mbrc->cp_delta_qp[4] = -1; + mbrc->cp_error[5] = tmp * 3; + mbrc->cp_delta_qp[5] = -2; + mbrc->cp_error[6] = tmp * 4; + mbrc->cp_delta_qp[6] = -3; + + for (i = 0; i < VEPU_CTRL_LEVELS; i++) { + tmp = mbrc->cp_error[i]; + tmp = mpp_clip(tmp / 4, -32768, 32767); + mbrc->cp_error[i] = tmp; + } + + mbrc->cp_distance_mbs = p->check_point_distance; + + return MPP_OK; +} + +MPP_RET h264e_vepu_slice_split_cfg(H264eSlice *slice, HalH264eVepuMbRc *mbrc, + EncRcTask *rc_task, MppEncCfgSet *cfg) +{ + MppEncSliceSplit *split = &cfg->split; + EncRcTaskInfo *info = &rc_task->info; + RK_U32 slice_mb_rows = 0; + + hal_h264e_dbg_func("enter\n"); + + switch (split->split_mode) { + case MPP_ENC_SPLIT_NONE : { + mbrc->slice_size_mb_rows = 0; + } break; + case MPP_ENC_SPLIT_BY_BYTE : { + RK_U32 mb_per_col = (cfg->prep.height + 15) / 16; + mpp_assert(split->split_arg > 0); + RK_U32 slice_num = info->bit_target / (split->split_arg * 8); + + if (slice_num <= 0) + slice_num = 4; + + slice_mb_rows = (mb_per_col + slice_num - 1) / slice_num; + mbrc->slice_size_mb_rows = mpp_clip(slice_mb_rows, 2, 127); + } break; + case MPP_ENC_SPLIT_BY_CTU : { + mpp_assert(split->split_arg > 0); + RK_U32 mb_per_line = (cfg->prep.width + 15) / 16; + + slice_mb_rows = (split->split_arg + mb_per_line - 1) / mb_per_line; + mbrc->slice_size_mb_rows = mpp_clip(slice_mb_rows, 2, 127); + } break; + default : { + mpp_log_f("invalide slice split mode %d\n", split->split_mode); + } break; + } + + slice->is_multi_slice = (mbrc->slice_size_mb_rows > 0); + + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + +MPP_RET h264e_vepu_mbrc_update(HalH264eVepuMbRcCtx ctx, HalH264eVepuMbRc *mbrc) +{ + HalH264eVepuMbRcImpl *p = (HalH264eVepuMbRcImpl *)ctx; + (void) p; + (void) mbrc; + + hal_h264e_dbg_func("enter\n"); + hal_h264e_dbg_func("leave\n"); + return MPP_OK; +} + diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.h b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.h new file mode 100644 index 000000000..66b5ebc67 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.h @@ -0,0 +1,220 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VEPU_V2_H +#define HAL_H264E_VEPU_V2_H + +#include "mpp_enc_cfg.h" +#include "mpp_rc.h" +#include "vepu_common.h" + +#define H264E_HAL_SET_REG(reg, addr, val) \ + do { \ + reg[(addr)>>2] = (RK_U32)(val); \ + if (hal_h264e_debug & 0/*H264E_HAL_LOG_INFO*/) \ + mpp_log("line(%d) set reg[%03d/%03x]: %08x", __LINE__, (addr)>>2, addr, val); \ + } while (0) + +typedef enum H264eVpuFrameType_t { + H264E_VPU_FRAME_P = 0, + H264E_VPU_FRAME_I = 1 +} H264eVpuFrameType; + +#define VEPU_CTRL_LEVELS 7 +#define VEPU_CHECK_POINTS_MAX 10 + +typedef struct HalH264eVepuInput_t { + /* Hardware config format */ + RK_S32 src_fmt; + RK_S32 src_w; + RK_S32 src_h; + + VepuStrideCfg stride_cfg; + RK_S32 pixel_stride; + + size_t size_y; + size_t size_c; + + RK_U32 offset_cb; + RK_U32 offset_cr; + + RK_U8 r_mask_msb; + RK_U8 g_mask_msb; + RK_U8 b_mask_msb; + RK_U8 swap_8_in; + RK_U8 swap_16_in; + RK_U8 swap_32_in; + + RK_U32 color_conversion_coeff_a; + RK_U32 color_conversion_coeff_b; + RK_U32 color_conversion_coeff_c; + RK_U32 color_conversion_coeff_e; + RK_U32 color_conversion_coeff_f; + + RK_U32 rotation; +} HalH264eVepuPrep; + +typedef struct HalH264eVepuFrmAddr_t { + // original frame Y/Cb/Cr/RGB address + RK_U32 orig[3]; + // reconstruction frame + RK_U32 recn[2]; + RK_U32 refr[2]; +} HalH264eVepuAddr; + +/* + * Vepu buffer allocater + * There are three internal buffer for Vepu encoder: + * 1. cabac table input buffer + * 2. nal size table output buffer + * 3. recon / refer frame buffer + */ +typedef struct HalH264eVepuBufs_t { + MppBufferGroup group; + + /* cabac table buffer */ + RK_S32 cabac_init_idc; + MppBuffer cabac_table; + + /* + * nal size table buffer + * table size must be 64-bit multiple, space for zero at the end of table + * Atleast 1 macroblock row in every slice + */ + RK_S32 mb_h; + RK_S32 nal_tab_size; + MppBuffer nal_size_table; + + /* + * recon / refer frame buffer + * sync with encoder using slot index + */ + size_t frm_size; + size_t yuv_size; + RK_S32 frm_cnt; + MppBuffer frm_buf[H264E_MAX_REFS_CNT + 1]; +} HalH264eVepuBufs; + +typedef struct HalH264eVepuMbRc_t { + /* VEPU MB rate control parameter for config to hardware */ + RK_S32 qp_init; + RK_S32 qp_min; + RK_S32 qp_max; + + /* + * VEPU MB can have max 10 check points (cp). + * + * On each check point hardware will check the target bit and + * error bits and change qp according to delta qp step + * + * cp_distance_mbs check point distance in mbs (0 = disabled) + * cp_target bitrate target at each check point + * cp_error error bit level step for each delta qp + * cp_delta_qp delta qp applied on when on bit rate error amount + */ + RK_S32 cp_distance_mbs; + RK_S32 cp_target[VEPU_CHECK_POINTS_MAX]; + RK_S32 cp_error[VEPU_CTRL_LEVELS]; + RK_S32 cp_delta_qp[VEPU_CTRL_LEVELS]; + + /* + * MAD based QP adjustment + * mad_qp_change [-8..7] + * mad_threshold MAD threshold div256 + */ + RK_S32 mad_qp_change; + RK_S32 mad_threshold; + + /* slice split by mb row (0 = one slice) */ + RK_S32 slice_size_mb_rows; + + /* favor and penalty for mode decision */ + + /* + * VEPU MB rate control parameter which is read from hardware + * out_strm_size output stream size (bits) + * qp_sum QP Sum div2 output + * rlc_count RLC codeword count div4 output max 255*255*384/4 + */ + RK_U32 hdr_strm_size; + RK_U32 hdr_free_size; + RK_U32 out_strm_size; + RK_S32 qp_sum; + RK_S32 rlc_count; + + RK_S32 cp_usage[VEPU_CHECK_POINTS_MAX]; + /* Macroblock count with MAD value under threshold output */ + RK_S32 less_mad_count; + /* MB count output */ + RK_S32 mb_count; + + /* hardware encoding status 0 - corret 1 - error */ + RK_U32 hw_status; +} HalH264eVepuMbRc; + +typedef void *HalH264eVepuMbRcCtx; + + + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 exp_golomb_signed(RK_S32 val); + +/* buffer management function */ +MPP_RET h264e_vepu_buf_init(HalH264eVepuBufs *bufs); +MPP_RET h264e_vepu_buf_deinit(HalH264eVepuBufs *bufs); + +MPP_RET h264e_vepu_buf_set_cabac_idc(HalH264eVepuBufs *bufs, RK_S32 idc); +MPP_RET h264e_vepu_buf_set_frame_size(HalH264eVepuBufs *bufs, RK_S32 w, RK_S32 h); + +MppBuffer h264e_vepu_buf_get_nal_size_table(HalH264eVepuBufs *bufs); +MppBuffer h264e_vepu_buf_get_frame_buffer(HalH264eVepuBufs *bufs, RK_S32 index); + +/* preprocess setup function */ +MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg); +MPP_RET h264e_vepu_prep_get_addr(HalH264eVepuPrep *prep, MppBuffer buffer, + RK_U32 (*addr)[3]); + +/* macroblock bitrate control function */ +MPP_RET h264e_vepu_mbrc_init(HalH264eVepuMbRcCtx *ctx, HalH264eVepuMbRc *mbrc); +MPP_RET h264e_vepu_mbrc_deinit(HalH264eVepuMbRcCtx ctx); + +MPP_RET h264e_vepu_mbrc_setup(HalH264eVepuMbRcCtx ctx, MppEncCfgSet *cfg); +MPP_RET h264e_vepu_slice_split_cfg(H264eSlice *slice, HalH264eVepuMbRc *mbrc, + EncRcTask *rc_task, MppEncCfgSet *set_cfg); + +/* + * generate hardware MB rc config by: + * 1 - HalH264eVepuMbRcCtx ctx + * The previous frame encoding status + * 2 - RcSyntax + * Provide current frame target bitrate related info + * 3 - EncFrmStatus + * Provide dpb related info like I / P frame, temporal id, refer distance + * + * Then output the HalH264eVepuMbRc for register generation + */ +MPP_RET h264e_vepu_mbrc_prepare(HalH264eVepuMbRcCtx ctx, HalH264eVepuMbRc *mbrc, + EncRcTask *rc_task); +MPP_RET h264e_vepu_mbrc_update(HalH264eVepuMbRcCtx ctx, HalH264eVepuMbRc *mbrc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl.c b/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl.c new file mode 100644 index 000000000..18f5f0207 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl.c @@ -0,0 +1,705 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hal_h264e_vpu_tbl.h" + +/* H.264 motion estimation parameters */ +const RK_U32 h264_prev_mode_favor[52] = { + 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 24, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 46, + 49, 51, 55, 58, 61, 65, 69, 73, 78, 82, 87, 93, 98, 104, 110, + 117, 124, 132, 140 +}; + +/* sqrt(2^((qp-12)/3))*8 */ +const RK_U32 h264_diff_mv_penalty[52] = { + 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, + 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, + 20, 23, 26, 29, 32, 36, 40, 45, 51, 57, + 64, 72, 81, 91, 102, 114, 128, 144, 161, 181, + 203, 228, 256, 287, 323, 362, 406, 456, 512, 575, + 645, 724 +}; + +/* 31*sqrt(2^((qp-12)/3))/4 */ +const RK_U32 h264_diff_mv_penalty4p[52] = { + 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, + 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, + 20, 22, 25, 28, 31, 35, 39, 44, 49, 55, + 62, 70, 78, 88, 98, 110, 124, 139, 156, 175, + 197, 221, 248, 278, 312, 351, 394, 442, 496, 557, + 625, 701 +}; + +const RK_U32 h264_intra16_favor[52] = { + 24, 24, 24, 26, 27, 30, 32, 35, 39, 43, 48, 53, 58, 64, 71, 78, + 85, 93, 102, 111, 121, 131, 142, 154, 167, 180, 195, 211, 229, + 248, 271, 296, 326, 361, 404, 457, 523, 607, 714, 852, 1034, + 1272, 1588, 2008, 2568, 3318, 4323, 5672, 7486, 9928, 13216, + 17648 +}; + +const RK_U32 h264_inter_favor[52] = { + 0, 0, 0, 0, 0, 0, 45, 48, 51, 53, 55, 60, 62, 67, 69, 72, + 78, 84, 90, 96, 110, 120, 135, 152, 170, 189, 210, 235, 265, + 297, 335, 376, 420, 470, 522, 572, 620, 670, 724, 770, 820, + 867, 915, 970, 1020, 1076, 1132, 1180, 1230, 1275, 1320, 1370 +}; + +const RK_U32 h264_skip_sad_penalty[52] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 233, 205, 182, 163, + 146, 132, 120, 109, 100, 92, 84, 78, 71, 66, 61, 56, 52, 48, + 44, 41, 38, 35, 32, 30, 27, 25, 23, 21, 19, 17, 15, 14, + 12, 11, 9, 8, 7, 5, 4, 3, 2, 1 +}; + +const RK_S32 h264_context_init_intra[460][2] = { + /* 0 -> 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28, 127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 -> 23 unsused for I */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, + + /* 24 -> 39 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + + /* 40 -> 53 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, + + /* 54 -> 59 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, + + /* 60 -> 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 -> 87 */ + { 0, 11 }, { 1, 55 }, { 0, 69 }, { -17, 127 }, + { -13, 102 }, { 0, 82 }, { -7, 74 }, { -21, 107 }, + { -27, 127 }, { -31, 127 }, { -24, 127 }, { -18, 95 }, + { -27, 127 }, { -21, 114 }, { -30, 127 }, { -17, 123 }, + { -12, 115 }, { -16, 122 }, + + /* 88 -> 104 */ + { -11, 115 }, { -12, 63 }, { -2, 68 }, { -15, 84 }, + { -13, 104 }, { -3, 70 }, { -8, 93 }, { -10, 90 }, + { -30, 127 }, { -1, 74 }, { -6, 97 }, { -7, 91 }, + { -20, 127 }, { -4, 56 }, { -5, 82 }, { -7, 76 }, + { -22, 125 }, + + /* 105 -> 135 */ + { -7, 93 }, { -11, 87 }, { -3, 77 }, { -5, 71 }, + { -4, 63 }, { -4, 68 }, { -12, 84 }, { -7, 62 }, + { -7, 65 }, { 8, 61 }, { 5, 56 }, { -2, 66 }, + { 1, 64 }, { 0, 61 }, { -2, 78 }, { 1, 50 }, + { 7, 52 }, { 10, 35 }, { 0, 44 }, { 11, 38 }, + { 1, 45 }, { 0, 46 }, { 5, 44 }, { 31, 17 }, + { 1, 51 }, { 7, 50 }, { 28, 19 }, { 16, 33 }, + { 14, 62 }, { -13, 108 }, { -15, 100 }, + + /* 136 -> 165 */ + { -13, 101 }, { -13, 91 }, { -12, 94 }, { -10, 88 }, + { -16, 84 }, { -10, 86 }, { -7, 83 }, { -13, 87 }, + { -19, 94 }, { 1, 70 }, { 0, 72 }, { -5, 74 }, + { 18, 59 }, { -8, 102 }, { -15, 100 }, { 0, 95 }, + { -4, 75 }, { 2, 72 }, { -11, 75 }, { -3, 71 }, + { 15, 46 }, { -13, 69 }, { 0, 62 }, { 0, 65 }, + { 21, 37 }, { -15, 72 }, { 9, 57 }, { 16, 54 }, + { 0, 62 }, { 12, 72 }, + + /* 166 -> 196 */ + { 24, 0 }, { 15, 9 }, { 8, 25 }, { 13, 18 }, + { 15, 9 }, { 13, 19 }, { 10, 37 }, { 12, 18 }, + { 6, 29 }, { 20, 33 }, { 15, 30 }, { 4, 45 }, + { 1, 58 }, { 0, 62 }, { 7, 61 }, { 12, 38 }, + { 11, 45 }, { 15, 39 }, { 11, 42 }, { 13, 44 }, + { 16, 45 }, { 12, 41 }, { 10, 49 }, { 30, 34 }, + { 18, 42 }, { 10, 55 }, { 17, 51 }, { 17, 46 }, + { 0, 89 }, { 26, -19 }, { 22, -17 }, + + /* 197 -> 226 */ + { 26, -17 }, { 30, -25 }, { 28, -20 }, { 33, -23 }, + { 37, -27 }, { 33, -23 }, { 40, -28 }, { 38, -17 }, + { 33, -11 }, { 40, -15 }, { 41, -6 }, { 38, 1 }, + { 41, 17 }, { 30, -6 }, { 27, 3 }, { 26, 22 }, + { 37, -16 }, { 35, -4 }, { 38, -8 }, { 38, -3 }, + { 37, 3 }, { 38, 5 }, { 42, 0 }, { 35, 16 }, + { 39, 22 }, { 14, 48 }, { 27, 37 }, { 21, 60 }, + { 12, 68 }, { 2, 97 }, + + /* 227 -> 251 */ + { -3, 71 }, { -6, 42 }, { -5, 50 }, { -3, 54 }, + { -2, 62 }, { 0, 58 }, { 1, 63 }, { -2, 72 }, + { -1, 74 }, { -9, 91 }, { -5, 67 }, { -5, 27 }, + { -3, 39 }, { -2, 44 }, { 0, 46 }, { -16, 64 }, + { -8, 68 }, { -10, 78 }, { -6, 77 }, { -10, 86 }, + { -12, 92 }, { -15, 55 }, { -10, 60 }, { -6, 62 }, + { -4, 65 }, + + /* 252 -> 275 */ + { -12, 73 }, { -8, 76 }, { -7, 80 }, { -9, 88 }, + { -17, 110 }, { -11, 97 }, { -20, 84 }, { -11, 79 }, + { -6, 73 }, { -4, 74 }, { -13, 86 }, { -13, 96 }, + { -11, 97 }, { -19, 117 }, { -8, 78 }, { -5, 33 }, + { -4, 48 }, { -2, 53 }, { -3, 62 }, { -13, 71 }, + { -10, 79 }, { -12, 86 }, { -13, 90 }, { -14, 97 }, + + /* 276 special case, bypass used */ + { 0, 0 }, + + /* 277 -> 307 */ + { -6, 93 }, { -6, 84 }, { -8, 79 }, { 0, 66 }, + { -1, 71 }, { 0, 62 }, { -2, 60 }, { -2, 59 }, + { -5, 75 }, { -3, 62 }, { -4, 58 }, { -9, 66 }, + { -1, 79 }, { 0, 71 }, { 3, 68 }, { 10, 44 }, + { -7, 62 }, { 15, 36 }, { 14, 40 }, { 16, 27 }, + { 12, 29 }, { 1, 44 }, { 20, 36 }, { 18, 32 }, + { 5, 42 }, { 1, 48 }, { 10, 62 }, { 17, 46 }, + { 9, 64 }, { -12, 104 }, { -11, 97 }, + + /* 308 -> 337 */ + { -16, 96 }, { -7, 88 }, { -8, 85 }, { -7, 85 }, + { -9, 85 }, { -13, 88 }, { 4, 66 }, { -3, 77 }, + { -3, 76 }, { -6, 76 }, { 10, 58 }, { -1, 76 }, + { -1, 83 }, { -7, 99 }, { -14, 95 }, { 2, 95 }, + { 0, 76 }, { -5, 74 }, { 0, 70 }, { -11, 75 }, + { 1, 68 }, { 0, 65 }, { -14, 73 }, { 3, 62 }, + { 4, 62 }, { -1, 68 }, { -13, 75 }, { 11, 55 }, + { 5, 64 }, { 12, 70 }, + + /* 338 -> 368 */ + { 15, 6 }, { 6, 19 }, { 7, 16 }, { 12, 14 }, + { 18, 13 }, { 13, 11 }, { 13, 15 }, { 15, 16 }, + { 12, 23 }, { 13, 23 }, { 15, 20 }, { 14, 26 }, + { 14, 44 }, { 17, 40 }, { 17, 47 }, { 24, 17 }, + { 21, 21 }, { 25, 22 }, { 31, 27 }, { 22, 29 }, + { 19, 35 }, { 14, 50 }, { 10, 57 }, { 7, 63 }, + { -2, 77 }, { -4, 82 }, { -3, 94 }, { 9, 69 }, + { -12, 109 }, { 36, -35 }, { 36, -34 }, + + /* 369 -> 398 */ + { 32, -26 }, { 37, -30 }, { 44, -32 }, { 34, -18 }, + { 34, -15 }, { 40, -15 }, { 33, -7 }, { 35, -5 }, + { 33, 0 }, { 38, 2 }, { 33, 13 }, { 23, 35 }, + { 13, 58 }, { 29, -3 }, { 26, 0 }, { 22, 30 }, + { 31, -7 }, { 35, -15 }, { 34, -3 }, { 34, 3 }, + { 36, -1 }, { 34, 5 }, { 32, 11 }, { 35, 5 }, + { 34, 12 }, { 39, 11 }, { 30, 29 }, { 34, 26 }, + { 29, 39 }, { 19, 66 }, + + /* 399 -> 435 */ + { 31, 21 }, { 31, 31 }, { 25, 50 }, + { -17, 120 }, { -20, 112 }, { -18, 114 }, { -11, 85 }, + { -15, 92 }, { -14, 89 }, { -26, 71 }, { -15, 81 }, + { -14, 80 }, { 0, 68 }, { -14, 70 }, { -24, 56 }, + { -23, 68 }, { -24, 50 }, { -11, 74 }, { 23, -13 }, + { 26, -13 }, { 40, -15 }, { 49, -14 }, { 44, 3 }, + { 45, 6 }, { 44, 34 }, { 33, 54 }, { 19, 82 }, + { -3, 75 }, { -1, 23 }, { 1, 34 }, { 1, 43 }, + { 0, 54 }, { -2, 55 }, { 0, 61 }, { 1, 64 }, + { 0, 68 }, { -9, 92 }, + + /* 436 -> 459 */ + { -14, 106 }, { -13, 97 }, { -15, 90 }, { -12, 90 }, + { -18, 88 }, { -10, 73 }, { -9, 79 }, { -14, 86 }, + { -10, 73 }, { -10, 70 }, { -10, 69 }, { -5, 66 }, + { -9, 64 }, { -5, 58 }, { 2, 59 }, { 21, -10 }, + { 24, -11 }, { 28, -8 }, { 28, -1 }, { 29, 3 }, + { 29, 9 }, { 35, 20 }, { 29, 36 }, { 14, 67 } +}; + +const RK_S32 h264_context_init[3][460][2] = { + /* cabac_init_idc == 0 */ + { + /* 0 -> 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28, 127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 -> 23 */ + { 23, 33 }, { 23, 2 }, { 21, 0 }, { 1, 9 }, + { 0, 49 }, { -37, 118 }, { 5, 57 }, { -13, 78 }, + { -11, 65 }, { 1, 62 }, { 12, 49 }, { -4, 73 }, + { 17, 50 }, + + /* 24 -> 39 */ + { 18, 64 }, { 9, 43 }, { 29, 0 }, { 26, 67 }, + { 16, 90 }, { 9, 104 }, { -46, 127 }, { -20, 104 }, + { 1, 67 }, { -13, 78 }, { -11, 65 }, { 1, 62 }, + { -6, 86 }, { -17, 95 }, { -6, 61 }, { 9, 45 }, + + /* 40 -> 53 */ + { -3, 69 }, { -6, 81 }, { -11, 96 }, { 6, 55 }, + { 7, 67 }, { -5, 86 }, { 2, 88 }, { 0, 58 }, + { -3, 76 }, { -10, 94 }, { 5, 54 }, { 4, 69 }, + { -3, 81 }, { 0, 88 }, + + /* 54 -> 59 */ + { -7, 67 }, { -5, 74 }, { -4, 74 }, { -5, 80 }, + { -7, 72 }, { 1, 58 }, + + /* 60 -> 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 -> 87 */ + { 0, 45 }, { -4, 78 }, { -3, 96 }, { -27, 126 }, + { -28, 98 }, { -25, 101 }, { -23, 67 }, { -28, 82 }, + { -20, 94 }, { -16, 83 }, { -22, 110 }, { -21, 91 }, + { -18, 102 }, { -13, 93 }, { -29, 127 }, { -7, 92 }, + { -5, 89 }, { -7, 96 }, { -13, 108 }, { -3, 46 }, + { -1, 65 }, { -1, 57 }, { -9, 93 }, { -3, 74 }, + { -9, 92 }, { -8, 87 }, { -23, 126 }, { 5, 54 }, + { 6, 60 }, { 6, 59 }, { 6, 69 }, { -1, 48 }, + { 0, 68 }, { -4, 69 }, { -8, 88 }, + + /* 105 -> 165 */ + { -2, 85 }, { -6, 78 }, { -1, 75 }, { -7, 77 }, + { 2, 54 }, { 5, 50 }, { -3, 68 }, { 1, 50 }, + { 6, 42 }, { -4, 81 }, { 1, 63 }, { -4, 70 }, + { 0, 67 }, { 2, 57 }, { -2, 76 }, { 11, 35 }, + { 4, 64 }, { 1, 61 }, { 11, 35 }, { 18, 25 }, + { 12, 24 }, { 13, 29 }, { 13, 36 }, { -10, 93 }, + { -7, 73 }, { -2, 73 }, { 13, 46 }, { 9, 49 }, + { -7, 100 }, { 9, 53 }, { 2, 53 }, { 5, 53 }, + { -2, 61 }, { 0, 56 }, { 0, 56 }, { -13, 63 }, + { -5, 60 }, { -1, 62 }, { 4, 57 }, { -6, 69 }, + { 4, 57 }, { 14, 39 }, { 4, 51 }, { 13, 68 }, + { 3, 64 }, { 1, 61 }, { 9, 63 }, { 7, 50 }, + { 16, 39 }, { 5, 44 }, { 4, 52 }, { 11, 48 }, + { -5, 60 }, { -1, 59 }, { 0, 59 }, { 22, 33 }, + { 5, 44 }, { 14, 43 }, { -1, 78 }, { 0, 60 }, + { 9, 69 }, + + /* 166 -> 226 */ + { 11, 28 }, { 2, 40 }, { 3, 44 }, { 0, 49 }, + { 0, 46 }, { 2, 44 }, { 2, 51 }, { 0, 47 }, + { 4, 39 }, { 2, 62 }, { 6, 46 }, { 0, 54 }, + { 3, 54 }, { 2, 58 }, { 4, 63 }, { 6, 51 }, + { 6, 57 }, { 7, 53 }, { 6, 52 }, { 6, 55 }, + { 11, 45 }, { 14, 36 }, { 8, 53 }, { -1, 82 }, + { 7, 55 }, { -3, 78 }, { 15, 46 }, { 22, 31 }, + { -1, 84 }, { 25, 7 }, { 30, -7 }, { 28, 3 }, + { 28, 4 }, { 32, 0 }, { 34, -1 }, { 30, 6 }, + { 30, 6 }, { 32, 9 }, { 31, 19 }, { 26, 27 }, + { 26, 30 }, { 37, 20 }, { 28, 34 }, { 17, 70 }, + { 1, 67 }, { 5, 59 }, { 9, 67 }, { 16, 30 }, + { 18, 32 }, { 18, 35 }, { 22, 29 }, { 24, 31 }, + { 23, 38 }, { 18, 43 }, { 20, 41 }, { 11, 63 }, + { 9, 59 }, { 9, 64 }, { -1, 94 }, { -2, 89 }, + { -9, 108 }, + + /* 227 -> 275 */ + { -6, 76 }, { -2, 44 }, { 0, 45 }, { 0, 52 }, + { -3, 64 }, { -2, 59 }, { -4, 70 }, { -4, 75 }, + { -8, 82 }, { -17, 102 }, { -9, 77 }, { 3, 24 }, + { 0, 42 }, { 0, 48 }, { 0, 55 }, { -6, 59 }, + { -7, 71 }, { -12, 83 }, { -11, 87 }, { -30, 119 }, + { 1, 58 }, { -3, 29 }, { -1, 36 }, { 1, 38 }, + { 2, 43 }, { -6, 55 }, { 0, 58 }, { 0, 64 }, + { -3, 74 }, { -10, 90 }, { 0, 70 }, { -4, 29 }, + { 5, 31 }, { 7, 42 }, { 1, 59 }, { -2, 58 }, + { -3, 72 }, { -3, 81 }, { -11, 97 }, { 0, 58 }, + { 8, 5 }, { 10, 14 }, { 14, 18 }, { 13, 27 }, + { 2, 40 }, { 0, 58 }, { -3, 70 }, { -6, 79 }, + { -8, 85 }, + + /* 276 special case, bypass used */ + { 0, 0 }, + + /* 277 -> 337 */ + { -13, 106 }, { -16, 106 }, { -10, 87 }, { -21, 114 }, + { -18, 110 }, { -14, 98 }, { -22, 110 }, { -21, 106 }, + { -18, 103 }, { -21, 107 }, { -23, 108 }, { -26, 112 }, + { -10, 96 }, { -12, 95 }, { -5, 91 }, { -9, 93 }, + { -22, 94 }, { -5, 86 }, { 9, 67 }, { -4, 80 }, + { -10, 85 }, { -1, 70 }, { 7, 60 }, { 9, 58 }, + { 5, 61 }, { 12, 50 }, { 15, 50 }, { 18, 49 }, + { 17, 54 }, { 10, 41 }, { 7, 46 }, { -1, 51 }, + { 7, 49 }, { 8, 52 }, { 9, 41 }, { 6, 47 }, + { 2, 55 }, { 13, 41 }, { 10, 44 }, { 6, 50 }, + { 5, 53 }, { 13, 49 }, { 4, 63 }, { 6, 64 }, + { -2, 69 }, { -2, 59 }, { 6, 70 }, { 10, 44 }, + { 9, 31 }, { 12, 43 }, { 3, 53 }, { 14, 34 }, + { 10, 38 }, { -3, 52 }, { 13, 40 }, { 17, 32 }, + { 7, 44 }, { 7, 38 }, { 13, 50 }, { 10, 57 }, + { 26, 43 }, + + /* 338 -> 398 */ + { 14, 11 }, { 11, 14 }, { 9, 11 }, { 18, 11 }, + { 21, 9 }, { 23, -2 }, { 32, -15 }, { 32, -15 }, + { 34, -21 }, { 39, -23 }, { 42, -33 }, { 41, -31 }, + { 46, -28 }, { 38, -12 }, { 21, 29 }, { 45, -24 }, + { 53, -45 }, { 48, -26 }, { 65, -43 }, { 43, -19 }, + { 39, -10 }, { 30, 9 }, { 18, 26 }, { 20, 27 }, + { 0, 57 }, { -14, 82 }, { -5, 75 }, { -19, 97 }, + { -35, 125 }, { 27, 0 }, { 28, 0 }, { 31, -4 }, + { 27, 6 }, { 34, 8 }, { 30, 10 }, { 24, 22 }, + { 33, 19 }, { 22, 32 }, { 26, 31 }, { 21, 41 }, + { 26, 44 }, { 23, 47 }, { 16, 65 }, { 14, 71 }, + { 8, 60 }, { 6, 63 }, { 17, 65 }, { 21, 24 }, + { 23, 20 }, { 26, 23 }, { 27, 32 }, { 28, 23 }, + { 28, 24 }, { 23, 40 }, { 24, 32 }, { 28, 29 }, + { 23, 42 }, { 19, 57 }, { 22, 53 }, { 22, 61 }, + { 11, 86 }, + + /* 399 -> 435 */ + { 12, 40 }, { 11, 51 }, { 14, 59 }, + { -4, 79 }, { -7, 71 }, { -5, 69 }, { -9, 70 }, + { -8, 66 }, { -10, 68 }, { -19, 73 }, { -12, 69 }, + { -16, 70 }, { -15, 67 }, { -20, 62 }, { -19, 70 }, + { -16, 66 }, { -22, 65 }, { -20, 63 }, { 9, -2 }, + { 26, -9 }, { 33, -9 }, { 39, -7 }, { 41, -2 }, + { 45, 3 }, { 49, 9 }, { 45, 27 }, { 36, 59 }, + { -6, 66 }, { -7, 35 }, { -7, 42 }, { -8, 45 }, + { -5, 48 }, { -12, 56 }, { -6, 60 }, { -5, 62 }, + { -8, 66 }, { -8, 76 }, + + /* 436 -> 459 */ + { -5, 85 }, { -6, 81 }, { -10, 77 }, { -7, 81 }, + { -17, 80 }, { -18, 73 }, { -4, 74 }, { -10, 83 }, + { -9, 71 }, { -9, 67 }, { -1, 61 }, { -8, 66 }, + { -14, 66 }, { 0, 59 }, { 2, 59 }, { 21, -13 }, + { 33, -14 }, { 39, -7 }, { 46, -2 }, { 51, 2 }, + { 60, 6 }, { 61, 17 }, { 55, 34 }, { 42, 62 }, + }, + + /* cabac_init_idc == 1 */ + { + /* 0 -> 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28, 127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 -> 23 */ + { 22, 25 }, { 34, 0 }, { 16, 0 }, { -2, 9 }, + { 4, 41 }, { -29, 118 }, { 2, 65 }, { -6, 71 }, + { -13, 79 }, { 5, 52 }, { 9, 50 }, { -3, 70 }, + { 10, 54 }, + + /* 24 -> 39 */ + { 26, 34 }, { 19, 22 }, { 40, 0 }, { 57, 2 }, + { 41, 36 }, { 26, 69 }, { -45, 127 }, { -15, 101 }, + { -4, 76 }, { -6, 71 }, { -13, 79 }, { 5, 52 }, + { 6, 69 }, { -13, 90 }, { 0, 52 }, { 8, 43 }, + + /* 40 -> 53 */ + { -2, 69 }, { -5, 82 }, { -10, 96 }, { 2, 59 }, + { 2, 75 }, { -3, 87 }, { -3, 100 }, { 1, 56 }, + { -3, 74 }, { -6, 85 }, { 0, 59 }, { -3, 81 }, + { -7, 86 }, { -5, 95 }, + + /* 54 -> 59 */ + { -1, 66 }, { -1, 77 }, { 1, 70 }, { -2, 86 }, + { -5, 72 }, { 0, 61 }, + + /* 60 -> 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 -> 104 */ + { 13, 15 }, { 7, 51 }, { 2, 80 }, { -39, 127 }, + { -18, 91 }, { -17, 96 }, { -26, 81 }, { -35, 98 }, + { -24, 102 }, { -23, 97 }, { -27, 119 }, { -24, 99 }, + { -21, 110 }, { -18, 102 }, { -36, 127 }, { 0, 80 }, + { -5, 89 }, { -7, 94 }, { -4, 92 }, { 0, 39 }, + { 0, 65 }, { -15, 84 }, { -35, 127 }, { -2, 73 }, + { -12, 104 }, { -9, 91 }, { -31, 127 }, { 3, 55 }, + { 7, 56 }, { 7, 55 }, { 8, 61 }, { -3, 53 }, + { 0, 68 }, { -7, 74 }, { -9, 88 }, + + /* 105 -> 165 */ + { -13, 103 }, { -13, 91 }, { -9, 89 }, { -14, 92 }, + { -8, 76 }, { -12, 87 }, { -23, 110 }, { -24, 105 }, + { -10, 78 }, { -20, 112 }, { -17, 99 }, { -78, 127 }, + { -70, 127 }, { -50, 127 }, { -46, 127 }, { -4, 66 }, + { -5, 78 }, { -4, 71 }, { -8, 72 }, { 2, 59 }, + { -1, 55 }, { -7, 70 }, { -6, 75 }, { -8, 89 }, + { -34, 119 }, { -3, 75 }, { 32, 20 }, { 30, 22 }, + { -44, 127 }, { 0, 54 }, { -5, 61 }, { 0, 58 }, + { -1, 60 }, { -3, 61 }, { -8, 67 }, { -25, 84 }, + { -14, 74 }, { -5, 65 }, { 5, 52 }, { 2, 57 }, + { 0, 61 }, { -9, 69 }, { -11, 70 }, { 18, 55 }, + { -4, 71 }, { 0, 58 }, { 7, 61 }, { 9, 41 }, + { 18, 25 }, { 9, 32 }, { 5, 43 }, { 9, 47 }, + { 0, 44 }, { 0, 51 }, { 2, 46 }, { 19, 38 }, + { -4, 66 }, { 15, 38 }, { 12, 42 }, { 9, 34 }, + { 0, 89 }, + + /* 166 -> 226 */ + { 4, 45 }, { 10, 28 }, { 10, 31 }, { 33, -11 }, + { 52, -43 }, { 18, 15 }, { 28, 0 }, { 35, -22 }, + { 38, -25 }, { 34, 0 }, { 39, -18 }, { 32, -12 }, + { 102, -94 }, { 0, 0 }, { 56, -15 }, { 33, -4 }, + { 29, 10 }, { 37, -5 }, { 51, -29 }, { 39, -9 }, + { 52, -34 }, { 69, -58 }, { 67, -63 }, { 44, -5 }, + { 32, 7 }, { 55, -29 }, { 32, 1 }, { 0, 0 }, + { 27, 36 }, { 33, -25 }, { 34, -30 }, { 36, -28 }, + { 38, -28 }, { 38, -27 }, { 34, -18 }, { 35, -16 }, + { 34, -14 }, { 32, -8 }, { 37, -6 }, { 35, 0 }, + { 30, 10 }, { 28, 18 }, { 26, 25 }, { 29, 41 }, + { 0, 75 }, { 2, 72 }, { 8, 77 }, { 14, 35 }, + { 18, 31 }, { 17, 35 }, { 21, 30 }, { 17, 45 }, + { 20, 42 }, { 18, 45 }, { 27, 26 }, { 16, 54 }, + { 7, 66 }, { 16, 56 }, { 11, 73 }, { 10, 67 }, + { -10, 116 }, + + /* 227 -> 275 */ + { -23, 112 }, { -15, 71 }, { -7, 61 }, { 0, 53 }, + { -5, 66 }, { -11, 77 }, { -9, 80 }, { -9, 84 }, + { -10, 87 }, { -34, 127 }, { -21, 101 }, { -3, 39 }, + { -5, 53 }, { -7, 61 }, { -11, 75 }, { -15, 77 }, + { -17, 91 }, { -25, 107 }, { -25, 111 }, { -28, 122 }, + { -11, 76 }, { -10, 44 }, { -10, 52 }, { -10, 57 }, + { -9, 58 }, { -16, 72 }, { -7, 69 }, { -4, 69 }, + { -5, 74 }, { -9, 86 }, { 2, 66 }, { -9, 34 }, + { 1, 32 }, { 11, 31 }, { 5, 52 }, { -2, 55 }, + { -2, 67 }, { 0, 73 }, { -8, 89 }, { 3, 52 }, + { 7, 4 }, { 10, 8 }, { 17, 8 }, { 16, 19 }, + { 3, 37 }, { -1, 61 }, { -5, 73 }, { -1, 70 }, + { -4, 78 }, + + /* 276 special case, bypass used */ + { 0, 0 }, + + /* 277 -> 337 */ + { -21, 126 }, { -23, 124 }, { -20, 110 }, { -26, 126 }, + { -25, 124 }, { -17, 105 }, { -27, 121 }, { -27, 117 }, + { -17, 102 }, { -26, 117 }, { -27, 116 }, { -33, 122 }, + { -10, 95 }, { -14, 100 }, { -8, 95 }, { -17, 111 }, + { -28, 114 }, { -6, 89 }, { -2, 80 }, { -4, 82 }, + { -9, 85 }, { -8, 81 }, { -1, 72 }, { 5, 64 }, + { 1, 67 }, { 9, 56 }, { 0, 69 }, { 1, 69 }, + { 7, 69 }, { -7, 69 }, { -6, 67 }, { -16, 77 }, + { -2, 64 }, { 2, 61 }, { -6, 67 }, { -3, 64 }, + { 2, 57 }, { -3, 65 }, { -3, 66 }, { 0, 62 }, + { 9, 51 }, { -1, 66 }, { -2, 71 }, { -2, 75 }, + { -1, 70 }, { -9, 72 }, { 14, 60 }, { 16, 37 }, + { 0, 47 }, { 18, 35 }, { 11, 37 }, { 12, 41 }, + { 10, 41 }, { 2, 48 }, { 12, 41 }, { 13, 41 }, + { 0, 59 }, { 3, 50 }, { 19, 40 }, { 3, 66 }, + { 18, 50 }, + + /* 338 -> 398 */ + { 19, -6 }, { 18, -6 }, { 14, 0 }, { 26, -12 }, + { 31, -16 }, { 33, -25 }, { 33, -22 }, { 37, -28 }, + { 39, -30 }, { 42, -30 }, { 47, -42 }, { 45, -36 }, + { 49, -34 }, { 41, -17 }, { 32, 9 }, { 69, -71 }, + { 63, -63 }, { 66, -64 }, { 77, -74 }, { 54, -39 }, + { 52, -35 }, { 41, -10 }, { 36, 0 }, { 40, -1 }, + { 30, 14 }, { 28, 26 }, { 23, 37 }, { 12, 55 }, + { 11, 65 }, { 37, -33 }, { 39, -36 }, { 40, -37 }, + { 38, -30 }, { 46, -33 }, { 42, -30 }, { 40, -24 }, + { 49, -29 }, { 38, -12 }, { 40, -10 }, { 38, -3 }, + { 46, -5 }, { 31, 20 }, { 29, 30 }, { 25, 44 }, + { 12, 48 }, { 11, 49 }, { 26, 45 }, { 22, 22 }, + { 23, 22 }, { 27, 21 }, { 33, 20 }, { 26, 28 }, + { 30, 24 }, { 27, 34 }, { 18, 42 }, { 25, 39 }, + { 18, 50 }, { 12, 70 }, { 21, 54 }, { 14, 71 }, + { 11, 83 }, + + /* 399 -> 435 */ + { 25, 32 }, { 21, 49 }, { 21, 54 }, + { -5, 85 }, { -6, 81 }, { -10, 77 }, { -7, 81 }, + { -17, 80 }, { -18, 73 }, { -4, 74 }, { -10, 83 }, + { -9, 71 }, { -9, 67 }, { -1, 61 }, { -8, 66 }, + { -14, 66 }, { 0, 59 }, { 2, 59 }, { 17, -10 }, + { 32, -13 }, { 42, -9 }, { 49, -5 }, { 53, 0 }, + { 64, 3 }, { 68, 10 }, { 66, 27 }, { 47, 57 }, + { -5, 71 }, { 0, 24 }, { -1, 36 }, { -2, 42 }, + { -2, 52 }, { -9, 57 }, { -6, 63 }, { -4, 65 }, + { -4, 67 }, { -7, 82 }, + + /* 436 -> 459 */ + { -3, 81 }, { -3, 76 }, { -7, 72 }, { -6, 78 }, + { -12, 72 }, { -14, 68 }, { -3, 70 }, { -6, 76 }, + { -5, 66 }, { -5, 62 }, { 0, 57 }, { -4, 61 }, + { -9, 60 }, { 1, 54 }, { 2, 58 }, { 17, -10 }, + { 32, -13 }, { 42, -9 }, { 49, -5 }, { 53, 0 }, + { 64, 3 }, { 68, 10 }, { 66, 27 }, { 47, 57 }, + }, + + /* cabac_init_idc == 2 */ + { + /* 0 -> 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28, 127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 -> 23 */ + { 29, 16 }, { 25, 0 }, { 14, 0 }, { -10, 51 }, + { -3, 62 }, { -27, 99 }, { 26, 16 }, { -4, 85 }, + { -24, 102 }, { 5, 57 }, { 6, 57 }, { -17, 73 }, + { 14, 57 }, + + /* 24 -> 39 */ + { 20, 40 }, { 20, 10 }, { 29, 0 }, { 54, 0 }, + { 37, 42 }, { 12, 97 }, { -32, 127 }, { -22, 117 }, + { -2, 74 }, { -4, 85 }, { -24, 102 }, { 5, 57 }, + { -6, 93 }, { -14, 88 }, { -6, 44 }, { 4, 55 }, + + /* 40 -> 53 */ + { -11, 89 }, { -15, 103 }, { -21, 116 }, { 19, 57 }, + { 20, 58 }, { 4, 84 }, { 6, 96 }, { 1, 63 }, + { -5, 85 }, { -13, 106 }, { 5, 63 }, { 6, 75 }, + { -3, 90 }, { -1, 101 }, + + /* 54 -> 59 */ + { 3, 55 }, { -4, 79 }, { -2, 75 }, { -12, 97 }, + { -7, 50 }, { 1, 60 }, + + /* 60 -> 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 -> 104 */ + { 7, 34 }, { -9, 88 }, { -20, 127 }, { -36, 127 }, + { -17, 91 }, { -14, 95 }, { -25, 84 }, { -25, 86 }, + { -12, 89 }, { -17, 91 }, { -31, 127 }, { -14, 76 }, + { -18, 103 }, { -13, 90 }, { -37, 127 }, { 11, 80 }, + { 5, 76 }, { 2, 84 }, { 5, 78 }, { -6, 55 }, + { 4, 61 }, { -14, 83 }, { -37, 127 }, { -5, 79 }, + { -11, 104 }, { -11, 91 }, { -30, 127 }, { 0, 65 }, + { -2, 79 }, { 0, 72 }, { -4, 92 }, { -6, 56 }, + { 3, 68 }, { -8, 71 }, { -13, 98 }, + + /* 105 -> 165 */ + { -4, 86 }, { -12, 88 }, { -5, 82 }, { -3, 72 }, + { -4, 67 }, { -8, 72 }, { -16, 89 }, { -9, 69 }, + { -1, 59 }, { 5, 66 }, { 4, 57 }, { -4, 71 }, + { -2, 71 }, { 2, 58 }, { -1, 74 }, { -4, 44 }, + { -1, 69 }, { 0, 62 }, { -7, 51 }, { -4, 47 }, + { -6, 42 }, { -3, 41 }, { -6, 53 }, { 8, 76 }, + { -9, 78 }, { -11, 83 }, { 9, 52 }, { 0, 67 }, + { -5, 90 }, { 1, 67 }, { -15, 72 }, { -5, 75 }, + { -8, 80 }, { -21, 83 }, { -21, 64 }, { -13, 31 }, + { -25, 64 }, { -29, 94 }, { 9, 75 }, { 17, 63 }, + { -8, 74 }, { -5, 35 }, { -2, 27 }, { 13, 91 }, + { 3, 65 }, { -7, 69 }, { 8, 77 }, { -10, 66 }, + { 3, 62 }, { -3, 68 }, { -20, 81 }, { 0, 30 }, + { 1, 7 }, { -3, 23 }, { -21, 74 }, { 16, 66 }, + { -23, 124 }, { 17, 37 }, { 44, -18 }, { 50, -34 }, + { -22, 127 }, + + /* 166 -> 226 */ + { 4, 39 }, { 0, 42 }, { 7, 34 }, { 11, 29 }, + { 8, 31 }, { 6, 37 }, { 7, 42 }, { 3, 40 }, + { 8, 33 }, { 13, 43 }, { 13, 36 }, { 4, 47 }, + { 3, 55 }, { 2, 58 }, { 6, 60 }, { 8, 44 }, + { 11, 44 }, { 14, 42 }, { 7, 48 }, { 4, 56 }, + { 4, 52 }, { 13, 37 }, { 9, 49 }, { 19, 58 }, + { 10, 48 }, { 12, 45 }, { 0, 69 }, { 20, 33 }, + { 8, 63 }, { 35, -18 }, { 33, -25 }, { 28, -3 }, + { 24, 10 }, { 27, 0 }, { 34, -14 }, { 52, -44 }, + { 39, -24 }, { 19, 17 }, { 31, 25 }, { 36, 29 }, + { 24, 33 }, { 34, 15 }, { 30, 20 }, { 22, 73 }, + { 20, 34 }, { 19, 31 }, { 27, 44 }, { 19, 16 }, + { 15, 36 }, { 15, 36 }, { 21, 28 }, { 25, 21 }, + { 30, 20 }, { 31, 12 }, { 27, 16 }, { 24, 42 }, + { 0, 93 }, { 14, 56 }, { 15, 57 }, { 26, 38 }, + { -24, 127 }, + + /* 227 -> 275 */ + { -24, 115 }, { -22, 82 }, { -9, 62 }, { 0, 53 }, + { 0, 59 }, { -14, 85 }, { -13, 89 }, { -13, 94 }, + { -11, 92 }, { -29, 127 }, { -21, 100 }, { -14, 57 }, + { -12, 67 }, { -11, 71 }, { -10, 77 }, { -21, 85 }, + { -16, 88 }, { -23, 104 }, { -15, 98 }, { -37, 127 }, + { -10, 82 }, { -8, 48 }, { -8, 61 }, { -8, 66 }, + { -7, 70 }, { -14, 75 }, { -10, 79 }, { -9, 83 }, + { -12, 92 }, { -18, 108 }, { -4, 79 }, { -22, 69 }, + { -16, 75 }, { -2, 58 }, { 1, 58 }, { -13, 78 }, + { -9, 83 }, { -4, 81 }, { -13, 99 }, { -13, 81 }, + { -6, 38 }, { -13, 62 }, { -6, 58 }, { -2, 59 }, + { -16, 73 }, { -10, 76 }, { -13, 86 }, { -9, 83 }, + { -10, 87 }, + + /* 276 special case, bypass used */ + { 0, 0 }, + + /* 277 -> 337 */ + { -22, 127 }, { -25, 127 }, { -25, 120 }, { -27, 127 }, + { -19, 114 }, { -23, 117 }, { -25, 118 }, { -26, 117 }, + { -24, 113 }, { -28, 118 }, { -31, 120 }, { -37, 124 }, + { -10, 94 }, { -15, 102 }, { -10, 99 }, { -13, 106 }, + { -50, 127 }, { -5, 92 }, { 17, 57 }, { -5, 86 }, + { -13, 94 }, { -12, 91 }, { -2, 77 }, { 0, 71 }, + { -1, 73 }, { 4, 64 }, { -7, 81 }, { 5, 64 }, + { 15, 57 }, { 1, 67 }, { 0, 68 }, { -10, 67 }, + { 1, 68 }, { 0, 77 }, { 2, 64 }, { 0, 68 }, + { -5, 78 }, { 7, 55 }, { 5, 59 }, { 2, 65 }, + { 14, 54 }, { 15, 44 }, { 5, 60 }, { 2, 70 }, + { -2, 76 }, { -18, 86 }, { 12, 70 }, { 5, 64 }, + { -12, 70 }, { 11, 55 }, { 5, 56 }, { 0, 69 }, + { 2, 65 }, { -6, 74 }, { 5, 54 }, { 7, 54 }, + { -6, 76 }, { -11, 82 }, { -2, 77 }, { -2, 77 }, + { 25, 42 }, + + /* 338 -> 398 */ + { 17, -13 }, { 16, -9 }, { 17, -12 }, { 27, -21 }, + { 37, -30 }, { 41, -40 }, { 42, -41 }, { 48, -47 }, + { 39, -32 }, { 46, -40 }, { 52, -51 }, { 46, -41 }, + { 52, -39 }, { 43, -19 }, { 32, 11 }, { 61, -55 }, + { 56, -46 }, { 62, -50 }, { 81, -67 }, { 45, -20 }, + { 35, -2 }, { 28, 15 }, { 34, 1 }, { 39, 1 }, + { 30, 17 }, { 20, 38 }, { 18, 45 }, { 15, 54 }, + { 0, 79 }, { 36, -16 }, { 37, -14 }, { 37, -17 }, + { 32, 1 }, { 34, 15 }, { 29, 15 }, { 24, 25 }, + { 34, 22 }, { 31, 16 }, { 35, 18 }, { 31, 28 }, + { 33, 41 }, { 36, 28 }, { 27, 47 }, { 21, 62 }, + { 18, 31 }, { 19, 26 }, { 36, 24 }, { 24, 23 }, + { 27, 16 }, { 24, 30 }, { 31, 29 }, { 22, 41 }, + { 22, 42 }, { 16, 60 }, { 15, 52 }, { 14, 60 }, + { 3, 78 }, { -16, 123 }, { 21, 53 }, { 22, 56 }, + { 25, 61 }, + + /* 399 -> 435 */ + { 21, 33 }, { 19, 50 }, { 17, 61 }, + { -3, 78 }, { -8, 74 }, { -9, 72 }, { -10, 72 }, + { -18, 75 }, { -12, 71 }, { -11, 63 }, { -5, 70 }, + { -17, 75 }, { -14, 72 }, { -16, 67 }, { -8, 53 }, + { -14, 59 }, { -9, 52 }, { -11, 68 }, { 9, -2 }, + { 30, -10 }, { 31, -4 }, { 33, -1 }, { 33, 7 }, + { 31, 12 }, { 37, 23 }, { 31, 38 }, { 20, 64 }, + { -9, 71 }, { -7, 37 }, { -8, 44 }, { -11, 49 }, + { -10, 56 }, { -12, 59 }, { -8, 63 }, { -9, 67 }, + { -6, 68 }, { -10, 79 }, + + /* 436 -> 459 */ + { -3, 78 }, { -8, 74 }, { -9, 72 }, { -10, 72 }, + { -18, 75 }, { -12, 71 }, { -11, 63 }, { -5, 70 }, + { -17, 75 }, { -14, 72 }, { -16, 67 }, { -8, 53 }, + { -14, 59 }, { -9, 52 }, { -11, 68 }, { 9, -2 }, + { 30, -10 }, { 31, -4 }, { 33, -1 }, { 33, 7 }, + { 31, 12 }, { 37, 23 }, { 31, 38 }, { 20, 64 }, + } +}; diff --git a/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl.h b/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl.h new file mode 100644 index 000000000..518cc5cae --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl.h @@ -0,0 +1,34 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VPU_TBL_H +#define HAL_H264E_VPU_TBL_H + +#include "rk_type.h" + +/* H.264 motion estimation parameters */ +extern const RK_U32 h264_prev_mode_favor[52]; +/* sqrt(2^((qp-12)/3))*8 */ +extern const RK_U32 h264_diff_mv_penalty[52]; +/* 31*sqrt(2^((qp-12)/3))/4 */ +extern const RK_U32 h264_diff_mv_penalty4p[52]; +extern const RK_U32 h264_intra16_favor[52]; +extern const RK_U32 h264_inter_favor[52]; +extern const RK_U32 h264_skip_sad_penalty[52]; +extern const RK_S32 h264_context_init_intra[460][2]; +extern const RK_S32 h264_context_init[3][460][2]; + +#endif diff --git a/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl_v2.h b/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl_v2.h new file mode 100644 index 000000000..82ce20161 --- /dev/null +++ b/mpp/hal/vpu/h264e/hal_h264e_vpu_tbl_v2.h @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_H264E_VPU_TBL_H +#define HAL_H264E_VPU_TBL_H + +#include "rk_type.h" + +#define H264E_CABAC_TABLE_BUF_SIZE (52*2*464) + +/* H.264 motion estimation parameters */ +extern const RK_U32 h264_prev_mode_favor[52]; +/* sqrt(2^((qp-12)/3))*8 */ +extern const RK_U32 h264_diff_mv_penalty[52]; +/* 31*sqrt(2^((qp-12)/3))/4 */ +extern const RK_U32 h264_diff_mv_penalty4p[52]; +extern const RK_U32 h264_intra16_favor[52]; +extern const RK_U32 h264_inter_favor[52]; +extern const RK_U32 h264_skip_sad_penalty[52]; +extern const RK_S32 h264_context_init_intra[460][2]; +extern const RK_S32 h264_context_init[3][460][2]; + +#endif diff --git a/mpp/hal/vpu/jpegd/CMakeLists.txt b/mpp/hal/vpu/jpegd/CMakeLists.txt new file mode 100644 index 000000000..485c65bf8 --- /dev/null +++ b/mpp/hal/vpu/jpegd/CMakeLists.txt @@ -0,0 +1,16 @@ +# vim: syntax=cmake + +# hal jpeg decoder sourse +set(HAL_JPEGD_SRC + hal_jpegd_common.c + hal_jpegd_vpu7xx_com.c + ) + +add_hal_source(HAL_JPEGD_SRC HAVE_VDPU2 hal_jpegd_vdpu2.c) +add_hal_source(HAL_JPEGD_SRC HAVE_VDPU1 hal_jpegd_vdpu1.c) +add_hal_source(HAL_JPEGD_SRC HAVE_VDPU720 hal_jpegd_rkv.c) +add_hal_source(HAL_JPEGD_SRC HAVE_VDPU730 hal_jpegd_vpu730.c) + +if (HAL_JPEGD_SRC) + add_library(hal_jpegd_api OBJECT ${HAL_JPEGD_SRC}) +endif() diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_base.h b/mpp/hal/vpu/jpegd/hal_jpegd_base.h new file mode 100644 index 000000000..7571c1564 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_base.h @@ -0,0 +1,59 @@ +/* + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGD_BASE_H +#define HAL_JPEGD_BASE_H + +#include + +#include "mpp_hal.h" +#include "mpp_env.h" +#include "mpp_device.h" + +typedef struct PPInfo_t { + /* PP parameters */ + RK_U8 pp_enable; /* 0 - disable; 1 - enable */ + RK_U8 pp_in_fmt; /* PP input format */ + RK_U8 pp_out_fmt;/* PP output format */ + RK_U8 dither_enable; /* for PP output RGB565 */ + RK_U32 crop_width; + RK_U32 crop_height; + RK_U32 crop_x; + RK_U32 crop_y; +} PPInfo; + +typedef struct JpegdHalCtx { + MppHalCfg *cfg; + void *regs; + MppBuffer pTableBase; + + MppFrameFormat output_fmt; + RK_U32 set_output_fmt_flag; + RK_U32 hal_debug_enable; + RK_U32 frame_count; + RK_U32 output_yuv_count; + RK_U8 scale; + + RK_S32 pkt_fd; /* input stream's physical address(fd) */ + RK_S32 frame_fd; /* output picture's physical address(fd) */ + + RK_U32 have_pp; + PPInfo pp_info; +} JpegdHalCtx; + +extern RK_U32 hal_jpegd_debug; + +#endif /* HAL_JPEGD_COMMON_H */ diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_common.c b/mpp/hal/vpu/jpegd/hal_jpegd_common.c new file mode 100644 index 000000000..395c0dbcb --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_common.c @@ -0,0 +1,537 @@ +/* + * + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "HAL_JPEGD_COMMON" + +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_bitread.h" +#include "mpp_bitput.h" +#include "mpp_platform.h" +#include "mpp_device.h" +#include "osal_2str.h" + +#include "hal_dec_task.h" +#include "jpegd_syntax.h" +#include "hal_jpegd_common.h" + +static PpRgbCfg pp_rgb_cfgs[PP_RGB_CFG_LENTH] = { + // ff: rgb565be, bin(rrrr,rggg, gggb,bbbb) mem MSB-->LSB(gggb,bbbb, rrrr,rggg) + { + .fmt = MPP_FMT_RGB565, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 1, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 0, .g_padd = 5, .b_padd = 11, + .r_dither = 2, .g_dither = 3, .b_dither = 2, + .r_mask = 0xf800f800, .g_mask = 0x07e007e0, .b_mask = 0x001f001f + }, + // ff: bgr565be, bin(bbbb,bggg, gggr,rrrr) mem MSB-->LSB(gggr,rrrr, bbbb,bggg) + { + .fmt = MPP_FMT_BGR565, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 1, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 11, .g_padd = 5, .b_padd = 0, + .r_dither = 2, .g_dither = 3, .b_dither = 2, + .r_mask = 0x001f001f, .g_mask = 0x07e007e0, .b_mask = 0xf800f800 + }, + // ff: rgb555be, bin(0rrr,rrgg, gggb,bbbb) mem MSB-->LSB(gggb,bbbb, 0rrr,rrgg) + { + .fmt = MPP_FMT_RGB555, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 1, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 1, .g_padd = 6, .b_padd = 11, + .r_dither = 2, .g_dither = 2, .b_dither = 2, + .r_mask = 0x7c007c00, .g_mask = 0x03e003e0, .b_mask = 0x001f001f + }, + // ff: bgr555be, bin(0bbb,bbgg, gggr,rrrr) mem MSB-->LSB(gggr,rrrr, 0bbb,bbgg) + { + .fmt = MPP_FMT_BGR555, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 1, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 11, .g_padd = 6, .b_padd = 1, + .r_dither = 2, .g_dither = 2, .b_dither = 2, + .r_mask = 0x001f001f, .g_mask = 0x03e003e0, .b_mask = 0x7c007c00 + }, + // ff: rgb444be, bin(0000,rrrr, gggg,bbbb) mem MSB-->LSB(gggg,bbbb, 0000,rrrr) + { + .fmt = MPP_FMT_RGB444, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 0, .swap_16 = 1, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 12, .g_padd = 0, .b_padd = 4, + .r_dither = 1, .g_dither = 1, .b_dither = 1, + .r_mask = 0x000f000f, .g_mask = 0xf000f000, .b_mask = 0x0f000f00 + }, + // ff: bgr444be, bin(0000,bbbb, gggg,rrrr) mem MSB-->LSB(gggg,rrrr, 0000,bbbb) + { + .fmt = MPP_FMT_BGR444, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 0, .swap_16 = 1, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 4, .g_padd = 0, .b_padd = 12, .r_mask = 0x0f000f00, + .r_dither = 1, .g_dither = 1, .b_dither = 1, + .g_mask = 0xf000f000, .b_mask = 0x000f000f + }, + // ff: argb, bin(aaaa,aaaa, rrrr,rrrr, gggg,gggg, bbbb,bbbb) + { + .fmt = MPP_FMT_ARGB8888, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 16, .g_padd = 8, .b_padd = 0, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0x0000ff00 | 0xff, + .g_mask = 0x00ff0000 | 0xff, + .b_mask = 0xff000000 | 0xff + }, + // ff: rgba, bin(aaaa,aaaa, bbbb,bbbb, gggg,gggg, rrrr,rrrr) + { + .fmt = MPP_FMT_ABGR8888, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 0, .g_padd = 8, .b_padd = 16, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0xff000000 | 0xff, + .g_mask = 0x00ff0000 | 0xff, + .b_mask = 0x0000ff00 | 0xff + }, + // ff: bgra, bin(bbbb,bbbb, gggg,gggg, rrrr,rrrr, aaaa,aaaa) + { + .fmt = MPP_FMT_BGRA8888, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 8, .g_padd = 16, .b_padd = 24, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0x00ff0000 | (0xff << 24), + .g_mask = 0x0000ff00 | (0xff << 24), + .b_mask = 0x000000ff | (0xff << 24) + }, + // ff: rgba, bin(rrrr,rrrr, gggg,gggg, bbbb,bbbb, aaaa,aaaa) + { + .fmt = MPP_FMT_RGBA8888, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 24, .g_padd = 16, .b_padd = 8, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0x000000ff | (0xff << 24), + .g_mask = 0x0000ff00 | (0xff << 24), + .b_mask = 0x00ff0000 | (0xff << 24) + }, +}; + +static PpRgbCfg pp_rgb_le_cfgs[PP_RGB_CFG_LENTH] = { + // ff: rgb565le, bin(gggb,bbbb, rrrr,rggg) mem MSB-->LSB(rrrr,rggg, gggb,bbbb) + { + .fmt = MPP_FMT_RGB565 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 0, .swap_16 = 1, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 0, .g_padd = 5, .b_padd = 11, + .r_dither = 2, .g_dither = 3, .b_dither = 2, + .r_mask = 0xf800f800, .g_mask = 0x07e007e0, .b_mask = 0x001f001f + }, + // ff: bgr565le, bin(gggr,rrrr, bbbb,bggg) mem MSB-->LSB(bbbb,bggg, gggr,rrrr) + { + .fmt = MPP_FMT_BGR565 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 0, .swap_16 = 1, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 11, .g_padd = 5, .b_padd = 0, + .r_dither = 2, .g_dither = 3, .b_dither = 2, + .r_mask = 0x001f001f, .g_mask = 0x07e007e0, .b_mask = 0xf800f800 + }, + // ff: rgb555le, bin(gggb,bbbb, 0rrr,rrgg) mem MSB-->LSB(0rrr,rrgg, gggb,bbbb) + { + .fmt = MPP_FMT_RGB555 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 0, .swap_16 = 1, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 1, .g_padd = 6, .b_padd = 11, + .r_dither = 2, .g_dither = 2, .b_dither = 2, + .r_mask = 0x7c007c00, .g_mask = 0x03e003e0, .b_mask = 0x001f001f + }, + // ff: bgr555le, bin(gggr,rrrr, 0bbb,bbgg) mem MSB-->LSB(0bbb,bbgg, gggr,rrrr) + { + .fmt = MPP_FMT_BGR555 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 0, .swap_16 = 1, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 11, .g_padd = 6, .b_padd = 1, + .r_dither = 2, .g_dither = 2, .b_dither = 2, + .r_mask = 0x001f001f, .g_mask = 0x03e003e0, .b_mask = 0x7c007c00 + }, + // ff: rgb444le, bin(gggg,bbbb, 0000,rrrr) mem MSB-->LSB(0000,rrrr, gggg,bbbb) + { + .fmt = MPP_FMT_RGB444 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 1, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 12, .g_padd = 0, .b_padd = 4, + .r_dither = 1, .g_dither = 1, .b_dither = 1, + .r_mask = 0x000f000f, .g_mask = 0xf000f000, .b_mask = 0x0f000f00 + }, + // ff: bgr444le, bin(gggg,rrrr, 0000,bbbb) mem MSB-->LSB(0000,bbbb, gggg,rrrr) + { + .fmt = MPP_FMT_BGR444 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_RGB565, + .out_endian = 1, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 1, + .r_padd = 4, .g_padd = 0, .b_padd = 12, .r_mask = 0x0f000f00, + .r_dither = 1, .g_dither = 1, .b_dither = 1, + .g_mask = 0xf000f000, .b_mask = 0x000f000f + }, + //in memory: [31:0] A:R:G:B 8:8:8:8 little endian + { + .fmt = MPP_FMT_ARGB8888 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 8, .g_padd = 16, .b_padd = 24, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0x00ff0000 | (0xff << 24), + .g_mask = 0x0000ff00 | (0xff << 24), + .b_mask = 0x000000ff | (0xff << 24) + }, + //in memory: [31:0] A:B:G:R 8:8:8:8 little endian + { + .fmt = MPP_FMT_ABGR8888 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 24, .g_padd = 16, .b_padd = 8, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0x000000ff | (0xff << 24), + .g_mask = 0x0000ff00 | (0xff << 24), + .b_mask = 0x00ff0000 | (0xff << 24) + }, + //in memory: [31:0] B:G:R:A 8:8:8:8 little endian + { + .fmt = MPP_FMT_BGRA8888 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 16, .g_padd = 8, .b_padd = 0, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0x0000ff00 | 0xff, + .g_mask = 0x00ff0000 | 0xff, + .b_mask = 0xff000000 | 0xff + }, + //in memory: [31:0] R:G:B:A 8:8:8:8 little endian + { + .fmt = MPP_FMT_RGBA8888 | MPP_FRAME_FMT_LE_MASK, .pp_out_fmt = PP_OUT_FORMAT_ARGB, + .out_endian = 0, .swap_16 = 0, .swap_32 = 1, .rgb_in_32 = 0, + .r_padd = 0, .g_padd = 8, .b_padd = 16, + .r_dither = 0, .g_dither = 0, .b_dither = 0, + .r_mask = 0xff000000 | 0xff, + .g_mask = 0x00ff0000 | 0xff, + .b_mask = 0x0000ff00 | 0xff + }, +}; + +PpRgbCfg* get_pp_rgb_Cfg(MppFrameFormat fmt) +{ + PpRgbCfg* cfg = NULL; + PpRgbCfg* cfg_array = NULL; + RK_U8 i = 0; + + if (MPP_FRAME_FMT_IS_LE(fmt)) + cfg_array = pp_rgb_le_cfgs; + else + cfg_array = pp_rgb_cfgs; + + for (i = 0; i < PP_RGB_CFG_LENTH; i++) { + if (cfg_array[i].fmt == fmt) { + cfg = &cfg_array[i]; + break; + } + } + + return cfg; +} + +RK_U32 jpegd_vdpu_tail_0xFF_patch(MppBuffer stream, RK_U32 length) +{ + RK_U8 *p = mpp_buffer_get_ptr(stream); + RK_U8 *end = p + length; + + if (end[-1] == 0xD9 && end[-2] == 0xFF) { + end -= 2; + + do { + if (end[-1] == 0xFF) { + end--; + length--; + continue; + } + break; + } while (1); + + end[0] = 0xff; + end[1] = 0xD9; + } + + return length; +} + +void jpegd_write_qp_ac_dc_table(JpegdHalCtx *ctx, + JpegdSyntax*syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = syntax; + RK_U32 *base = (RK_U32 *)mpp_buffer_get_ptr(ctx->pTableBase); + RK_U8 table_tmp[QUANTIZE_TABLE_LENGTH] = {0}; + RK_U32 idx, table_word = 0, table_value = 0; + RK_U32 shifter = 32; + AcTable *ac_ptr0 = NULL, *ac_ptr1 = NULL; + DcTable *dc_ptr0 = NULL, *dc_ptr1 = NULL; + RK_U32 i, j = 0; + + /* Quantize tables for all components + * length = 64 * 3 (Bytes) + */ + for (j = 0; j < s->qtable_cnt; j++) { + idx = s->quant_index[j]; /* quantize table index used by j component */ + + for (i = 0; i < QUANTIZE_TABLE_LENGTH; i++) { + table_tmp[zzOrder[i]] = (RK_U8) s->quant_matrixes[idx][i]; + } + + /* could memcpy be OK?? */ + for (i = 0; i < QUANTIZE_TABLE_LENGTH; i += 4) { + /* transfer to big endian */ + table_word = (table_tmp[i] << 24) | + (table_tmp[i + 1] << 16) | + (table_tmp[i + 2] << 8) | + table_tmp[i + 3]; + *base = table_word; + base++; + } + } + + /* write AC and DC tables + * memory: AC(Y) - AC(UV) - DC(Y) - DC(UV) + * length = 162 + 162 + 12 + 12 (Bytes) + */ + { + /* this trick is done because hardware always wants + * luma table as ac hardware table 0 */ + if (s->ac_index[0] == HUFFMAN_TABLE_ID_ZERO) { + /* Luma's AC uses Huffman table zero */ + ac_ptr0 = &(s->ac_table[HUFFMAN_TABLE_ID_ZERO]); + ac_ptr1 = &(s->ac_table[HUFFMAN_TABLE_ID_ONE]); + } else { + ac_ptr0 = &(s->ac_table[HUFFMAN_TABLE_ID_ONE]); + ac_ptr1 = &(s->ac_table[HUFFMAN_TABLE_ID_ZERO]); + } + + /* write luma AC table */ + for (i = 0; i < MAX_AC_HUFFMAN_TABLE_LENGTH; i++) { + if (i < ac_ptr0->actual_length) + table_value = (RK_U8) ac_ptr0->vals[i]; + else + table_value = 0; + + /* transfer to big endian */ + if (shifter == 32) + table_word = (table_value << (shifter - 8)); + else + table_word |= (table_value << (shifter - 8)); + + shifter -= 8; + if (shifter == 0) { + /* write 4 Bytes(32 bit) */ + *base = table_word; + base++; + shifter = 32; + } + } + + /* write chroma AC table */ + for (i = 0; i < MAX_AC_HUFFMAN_TABLE_LENGTH; i++) { + /* chroma's AC table must be zero for YUV400 */ + if ((s->yuv_mode != JPEGDEC_YUV400) && (i < ac_ptr1->actual_length)) + table_value = (RK_U8) ac_ptr1->vals[i]; + else + table_value = 0; + + /* transfer to big endian */ + if (shifter == 32) + table_word = (table_value << (shifter - 8)); + else + table_word |= (table_value << (shifter - 8)); + + shifter -= 8; + if (shifter == 0) { + /* write 4 Bytes(32 bit) */ + *base = table_word; + base++; + shifter = 32; + } + } + + /* this trick is done because hardware always wants + * luma table as dc hardware table 0 */ + if (s->dc_index[0] == HUFFMAN_TABLE_ID_ZERO) { + /* Luma's DC uses Huffman table zero */ + dc_ptr0 = &(s->dc_table[HUFFMAN_TABLE_ID_ZERO]); + dc_ptr1 = &(s->dc_table[HUFFMAN_TABLE_ID_ONE]); + } else { + dc_ptr0 = &(s->dc_table[HUFFMAN_TABLE_ID_ONE]); + dc_ptr1 = &(s->dc_table[HUFFMAN_TABLE_ID_ZERO]); + } + + /* write luma DC table */ + for (i = 0; i < MAX_DC_HUFFMAN_TABLE_LENGTH; i++) { + if (i < dc_ptr0->actual_length) + table_value = (RK_U8) dc_ptr0->vals[i]; + else + table_value = 0; + + /* transfer to big endian */ + if (shifter == 32) + table_word = (table_value << (shifter - 8)); + else + table_word |= (table_value << (shifter - 8)); + + shifter -= 8; + if (shifter == 0) { + /* write 4 Bytes(32 bit) */ + *base = table_word; + base++; + shifter = 32; + } + } + + /* write chroma DC table */ + for (i = 0; i < MAX_DC_HUFFMAN_TABLE_LENGTH; i++) { + /* chroma's DC table must be zero for YUV400 */ + if ((s->yuv_mode != JPEGDEC_YUV400) && (i < dc_ptr1->actual_length)) + table_value = (RK_U8) dc_ptr1->vals[i]; + else + table_value = 0; + + /* transfer to big endian */ + if (shifter == 32) + table_word = (table_value << (shifter - 8)); + else + table_word |= (table_value << (shifter - 8)); + + shifter -= 8; + if (shifter == 0) { + /* write 4 Bytes(32 bit) */ + *base = table_word; + base++; + shifter = 32; + } + } + } + + /* four-byte padding zero */ + for (i = 0; i < 4; i++) { + table_value = 0; + + if (shifter == 32) + table_word = (table_value << (shifter - 8)); + else + table_word |= (table_value << (shifter - 8)); + + shifter -= 8; + + if (shifter == 0) { + *base = table_word; + base++; + shifter = 32; + } + } + jpegd_dbg_func("exit\n"); + return; +} + +MPP_RET jpegd_setup_output_fmt(JpegdHalCtx *ctx, JpegdSyntax *s, RK_S32 output) +{ + jpegd_dbg_func("enter\n"); + RK_U32 pp_in_fmt = 0; + RK_U32 stride = 0; + PPInfo *pp_info = &ctx->pp_info; + MppFrame frm = NULL; + MPP_RET ret = MPP_OK; + + if (ctx->have_pp && ctx->set_output_fmt_flag && + ctx->output_fmt != s->output_fmt) { + MppFrameFormat fmt = MPP_FMT_BUTT; + + /* Using pp to convert all format to yuv420sp */ + switch (s->output_fmt) { + case MPP_FMT_YUV400: + pp_in_fmt = PP_IN_FORMAT_YUV400; + break; + case MPP_FMT_YUV420SP: + pp_in_fmt = PP_IN_FORMAT_YUV420SEMI; + break; + case MPP_FMT_YUV422SP: + pp_in_fmt = PP_IN_FORMAT_YUV422SEMI; + break; + case MPP_FMT_YUV440SP: + pp_in_fmt = PP_IN_FORMAT_YUV440SEMI; + break; + case MPP_FMT_YUV411SP: + pp_in_fmt = PP_IN_FORMAT_YUV411_SEMI; + break; + case MPP_FMT_YUV444SP: + pp_in_fmt = PP_IN_FORMAT_YUV444_SEMI; + break; + default: + jpegd_dbg_hal("other output format %d\n", s->output_fmt); + break; + } + + pp_info->pp_enable = 1; + pp_info->pp_in_fmt = pp_in_fmt; + + fmt = ctx->output_fmt; + + if (MPP_FRAME_FMT_IS_LE(fmt)) { + fmt &= MPP_FRAME_FMT_MASK; + } + + switch (fmt) { + case MPP_FMT_RGB565 : + case MPP_FMT_BGR565 : + case MPP_FMT_RGB555 : + case MPP_FMT_BGR555 : + case MPP_FMT_RGB444 : + case MPP_FMT_BGR444 : { + pp_info->pp_out_fmt = PP_OUT_FORMAT_RGB565; + stride = s->hor_stride * 2; + } break; + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_RGBA8888 : + case MPP_FMT_BGRA8888 : { + pp_info->pp_out_fmt = PP_OUT_FORMAT_ARGB; + stride = s->hor_stride * 4; + } break; + default : { + pp_info->pp_out_fmt = PP_OUT_FORMAT_YUV420INTERLAVE; + } break; + } + + jpegd_dbg_hal("Post Process! pp_in_fmt:%d, pp_out_fmt:%d", + pp_in_fmt, pp_info->pp_out_fmt); + } else { + /* keep original output format */ + ctx->output_fmt = s->output_fmt; + pp_info->pp_enable = 0; + } + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, output, + SLOT_FRAME_PTR, &frm); + mpp_frame_set_fmt(frm, ctx->output_fmt); + mpp_frame_set_hor_stride_pixel(frm, s->hor_stride); + /* update RGBX format byte stride and pixel stride */ + if (stride) + mpp_frame_set_hor_stride(frm, stride); + + jpegd_dbg_func("exit\n"); + return ret; +} + +MPP_RET jpeg_image_check_size(RK_U32 hor_stride, RK_U32 ver_stride) +{ + MPP_RET ret = MPP_OK; + + if (hor_stride > MAX_WIDTH || ver_stride > MAX_HEIGHT || + hor_stride < MIN_WIDTH || ver_stride < MIN_HEIGHT || + hor_stride * ver_stride > MAX_STREAM_LENGTH) { + mpp_err_f("unsupported resolution: %dx%d\n", hor_stride, ver_stride); + ret = MPP_NOK; + } + + return ret; +} diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_common.h b/mpp/hal/vpu/jpegd/hal_jpegd_common.h new file mode 100644 index 000000000..487824401 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_common.h @@ -0,0 +1,83 @@ +/* + * + * Copyright 2015 - 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAL_JPEGD_COMMON_H +#define HAL_JPEGD_COMMON_H + +#include "hal_jpegd_base.h" + +#define BRIGHTNESS 4 /* -128 ~ 127 */ +#define CONTRAST 0 /* -64 ~ 64 */ +#define SATURATION 0 /* -64 ~ 128 */ +#define PP_IN_FORMAT_YUV422INTERLAVE 0 +#define PP_IN_FORMAT_YUV420SEMI 1 +#define PP_IN_FORMAT_YUV420PLANAR 2 +#define PP_IN_FORMAT_YUV400 3 +#define PP_IN_FORMAT_YUV422SEMI 4 +#define PP_IN_FORMAT_YUV420SEMITIELED 5 +#define PP_IN_FORMAT_YUV440SEMI 6 +#define PP_IN_FORMAT_YUV444_SEMI 7 +#define PP_IN_FORMAT_YUV411_SEMI 8 + +#define PP_OUT_FORMAT_RGB565 0 +#define PP_OUT_FORMAT_ARGB 1 +#define PP_OUT_FORMAT_YUV422INTERLAVE 3 +#define PP_OUT_FORMAT_YUV420INTERLAVE 5 + +#define MIN_WIDTH (48) /* 48 Bytes */ +#define MIN_HEIGHT (48) /* 48 Bytes */ +#define MAX_WIDTH (8*1024) /* 4K Bytes */ +#define MAX_HEIGHT (8*1024) /* 4K Bytes */ +#define MAX_STREAM_LENGTH (MAX_WIDTH * MAX_HEIGHT) /* 16M Bytes */ + +static const RK_U8 zzOrder[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +#define PP_RGB_CFG_LENTH (10) +typedef struct PpRgbCfg_t { + MppFrameFormat fmt; + RK_U8 pp_out_fmt; + RK_U8 out_endian; + RK_U8 swap_16; + RK_U8 swap_32; + RK_U8 rgb_in_32; + RK_U8 r_padd; + RK_U8 g_padd; + RK_U8 b_padd; + RK_U8 r_dither; + RK_U8 g_dither; + RK_U8 b_dither; + RK_U32 r_mask; + RK_U32 g_mask; + RK_U32 b_mask; +} PpRgbCfg; + +PpRgbCfg* get_pp_rgb_Cfg(MppFrameFormat fmt); +RK_U32 jpegd_vdpu_tail_0xFF_patch(MppBuffer stream, RK_U32 length); + +void jpegd_write_qp_ac_dc_table(JpegdHalCtx *ctx, + JpegdSyntax*syntax); + +MPP_RET jpegd_setup_output_fmt(JpegdHalCtx *ctx, JpegdSyntax *syntax, + RK_S32 output); + +MPP_RET jpeg_image_check_size(RK_U32 hor_stride, RK_U32 ver_stride); + +#endif /* HAL_JPEGD_COMMON_H */ diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_rkv.c b/mpp/hal/vpu/jpegd/hal_jpegd_rkv.c new file mode 100644 index 000000000..ae635884c --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_rkv.c @@ -0,0 +1,679 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "hal_jpegd_rkv" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_frame.h" +#include "mpp_common.h" +#include "mpp_buffer_impl.h" +#include "mpp_dec_cb_param.h" + +#include "jpegd_syntax.h" +#include "hal_jpegd_base.h" +#include "hal_jpegd_common.h" +#include "hal_jpegd_vpu7xx_com.h" +#include "hal_jpegd_rkv.h" +#include "hal_jpegd_rkv_reg.h" + +static MPP_RET hal_jpegd_rkv_init(void *hal, MppHalCfg *cfg) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + if (NULL == ctx) { + ctx = (JpegdHalCtx *)mpp_calloc(JpegdHalCtx, 1); + if (NULL == ctx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + } + + ctx->cfg = cfg; + + /* allocate regs buffer */ + if (ctx->regs == NULL) { + ctx->regs = mpp_calloc_size(void, sizeof(JpegRegSet)); + if (ctx->regs == NULL) { + mpp_err("hal jpegd reg alloc failed\n"); + + jpegd_dbg_func("exit\n"); + return MPP_ERR_NOMEM; + } + } + + ret = mpp_buffer_get(ctx->cfg->buf_group, &ctx->pTableBase, RKD_TABLE_SIZE); + if (ret) { + mpp_err_f("Get table buffer failed, ret %d\n", ret); + } + + mpp_buffer_attach_dev(ctx->pTableBase, ctx->cfg->dev); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET setup_output_fmt(JpegdHalCtx *ctx, JpegdSyntax *syntax, RK_S32 out_idx) +{ + + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdSyntax *s = syntax; + JpegRegSet *regs = (JpegRegSet *)ctx->regs; + RK_U32 stride = syntax->hor_stride; + MppFrame frm = NULL; + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, out_idx, SLOT_FRAME_PTR, &frm); + + if (ctx->scale) { + if (ctx->scale == 2) + regs->reg2_sys.scaledown_mode = SCALEDOWN_HALF; + if (ctx->scale == 4) + regs->reg2_sys.scaledown_mode = SCALEDOWN_QUARTER; + if (ctx->scale == 8) + regs->reg2_sys.scaledown_mode = SCALEDOWN_ONE_EIGHTS; + } else { + regs->reg2_sys.scaledown_mode = SCALEDOWN_DISABLE; + } + + mpp_frame_set_hor_stride_pixel(frm, stride); + + if (ctx->set_output_fmt_flag && (ctx->output_fmt != s->output_fmt)) { // PP enable + if (MPP_FRAME_FMT_IS_YUV(ctx->output_fmt) && s->output_fmt != MPP_FMT_YUV400) { + if (ctx->output_fmt == MPP_FMT_YUV420SP) + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_NV12; + else if (ctx->output_fmt == MPP_FMT_YUV422_YUYV) + /* Only support yuv422 and yuv444. + * Other format transformation won't report hardware irq error, + * and won't get a correct YUV image. + */ + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_YUYV; + else if (ctx->output_fmt == MPP_FMT_YUV422_YVYU) { + regs->reg2_sys.out_cbcr_swap = 1; + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_YUYV; + } else if (ctx->output_fmt == MPP_FMT_YUV420SP_VU) { + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_NV12; + regs->reg2_sys.out_cbcr_swap = 1; + } + } else if (MPP_FRAME_FMT_IS_RGB(ctx->output_fmt)) { + if (ctx->output_fmt == MPP_FMT_RGB888) { + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_RGB888; + mpp_frame_set_hor_stride(frm, stride * 3); + } else if (ctx->output_fmt == (MPP_FMT_BGR565 | MPP_FRAME_FMT_LE_MASK) || + ctx->output_fmt == MPP_FMT_RGB565) { // bgr565le or rgb565be + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_RGB565; + mpp_frame_set_hor_stride(frm, stride * 2); + } else { + mpp_err_f("unsupported output format %d\n", ctx->output_fmt); + ret = MPP_NOK; + } + MppFrameColorRange color_range = MPP_FRAME_RANGE_UNSPECIFIED; + color_range = mpp_frame_get_color_range(frm); + if (color_range != MPP_FRAME_RANGE_MPEG) + regs->reg2_sys.yuv2rgb_range = YUV_TO_RGB_FULL_RANGE; + else + regs->reg2_sys.yuv2rgb_range = YUV_TO_RGB_LIMIT_RANGE; + } + } else { //keep original format + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_NO_TRANS; + ctx->output_fmt = s->output_fmt; + } + + if (MPP_FRAME_FMT_IS_TILE(ctx->output_fmt)) + regs->reg2_sys.dec_out_sequence = OUTPUT_TILE; + else + regs->reg2_sys.dec_out_sequence = OUTPUT_RASTER; + + jpegd_dbg_hal("convert format %d to format %d\n", s->output_fmt, ctx->output_fmt); + + if ((s->yuv_mode == YUV_MODE_420 && regs->reg2_sys.yuv_out_format == YUV_OUT_FMT_NO_TRANS) || + (regs->reg2_sys.yuv_out_format == YUV_OUT_FMT_2_NV12)) + regs->reg2_sys.fill_down_e = 1; + else + regs->reg2_sys.fill_down_e = s->fill_bottom; + regs->reg2_sys.fill_right_e = s->fill_right; + + mpp_frame_set_fmt(frm, ctx->output_fmt); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET jpegd_gen_regs(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdSyntax *s = syntax; + JpegRegSet *regs = (JpegRegSet *)ctx->regs; + + regs->reg1_int.dec_e = 1; + regs->reg1_int.dec_timeout_e = 1; + regs->reg1_int.buf_empty_e = 1; + + regs->reg3_pic_size.pic_width_m1 = s->width - 1; + regs->reg3_pic_size.pic_height_m1 = s->height - 1; + + if (s->sample_precision != DCT_SAMPLE_PRECISION_8 || s->qtbl_entry > TBL_ENTRY_3) + return MPP_NOK; + + regs->reg4_pic_fmt.pixel_depth = BIT_DEPTH_8; + if (s->nb_components == 1) { + regs->reg4_pic_fmt.htables_sel = TBL_ENTRY_1; + } + + if (s->nb_components > 1) { + regs->reg4_pic_fmt.qtables_sel = (s->qtbl_entry > 1) ? TBL_ENTRY_3 : TBL_ENTRY_2; + regs->reg4_pic_fmt.htables_sel = (s->htbl_entry > 0x0f) ? TBL_ENTRY_3 : TBL_ENTRY_2; + } else { + regs->reg4_pic_fmt.qtables_sel = TBL_ENTRY_1; + regs->reg4_pic_fmt.htables_sel = TBL_ENTRY_1; + } + + if (s->restart_interval) { + regs->reg4_pic_fmt.dri_e = RST_ENABLE; + regs->reg4_pic_fmt.dri_mcu_num_m1 = s->restart_interval - 1; + } + + switch (s->yuv_mode) { + case JPEGDEC_YUV400: + case JPEGDEC_YUV420: + case JPEGDEC_YUV422: + regs->reg4_pic_fmt.jpeg_mode = s->yuv_mode; + break; + case JPEGDEC_YUV411: + regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_411; + break; + case JPEGDEC_YUV440: + regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_440; + break; + case JPEGDEC_YUV444: + regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_444; + break; + default: + mpp_err_f("unsupported yuv mode %d\n", s->yuv_mode); + break; + } + + RK_U32 out_width = MPP_ALIGN(s->width, 16); + RK_U32 out_height = s->height; + out_width = out_width >> regs->reg2_sys.scaledown_mode; + out_width = MPP_ALIGN(out_width, 16); + out_height = (regs->reg2_sys.fill_down_e != 0) ? MPP_ALIGN(out_height, 16) : MPP_ALIGN(out_height, 8); + out_height = out_height >> regs->reg2_sys.scaledown_mode; + jpegd_dbg_hal("output scale %d, width %d, height %d\n", regs->reg2_sys.scaledown_mode, out_width, out_height); + + RK_U32 y_hor_stride = out_width >> 4; + RK_U32 y_virstride = 0; + RK_U32 uv_hor_virstride = 0; + + switch (regs->reg2_sys.yuv_out_format) { + case YUV_OUT_FMT_2_RGB888: + y_hor_stride *= 3; + break; + case YUV_OUT_FMT_2_RGB565: + case YUV_OUT_FMT_2_YUYV: + y_hor_stride *= 2; + break; + case YUV_OUT_FMT_NO_TRANS: + switch (regs->reg4_pic_fmt.jpeg_mode) { + case YUV_MODE_440: + case YUV_MODE_444: + uv_hor_virstride = y_hor_stride * 2; + break; + case YUV_MODE_411: + uv_hor_virstride = y_hor_stride >> 1; + break; + case YUV_MODE_400: + uv_hor_virstride = 0; + break; + default: + uv_hor_virstride = y_hor_stride; + break; + } + break; + case YUV_OUT_FMT_2_NV12: + uv_hor_virstride = y_hor_stride; + break; + } + + y_virstride = y_hor_stride * out_height; + if (regs->reg2_sys.dec_out_sequence == OUTPUT_TILE) { + // The new JPEG decoder supports tile 4x4 output by default. + if (mpp_get_soc_type() >= ROCKCHIP_SOC_RK3576) { + switch (regs->reg2_sys.yuv_out_format) { + case YUV_OUT_FMT_2_YUYV: + y_hor_stride = y_hor_stride * 4 * 2; + break; + case YUV_OUT_FMT_NO_TRANS: + switch (regs->reg4_pic_fmt.jpeg_mode) { + case YUV_MODE_422: + case YUV_MODE_440: + y_hor_stride = y_hor_stride * 4 * 2; + break; + case YUV_MODE_444: + y_hor_stride = y_hor_stride * 4 * 3; + break; + case YUV_MODE_411: + case YUV_MODE_420: + y_hor_stride = y_hor_stride * 4 * 3 / 2; + break; + case YUV_MODE_400: + y_hor_stride = y_hor_stride * 4; + break; + default: + return MPP_NOK; + break; + } + break; + case YUV_OUT_FMT_2_NV12: + y_hor_stride = y_hor_stride * 4 * 3 / 2; + break; + } + + uv_hor_virstride = 0; + } else { + y_hor_stride <<= 3; + uv_hor_virstride <<= 3; + } + } + + regs->reg5_hor_virstride.y_hor_virstride = y_hor_stride & 0xffff; + regs->reg5_hor_virstride.uv_hor_virstride = uv_hor_virstride & 0xffff; + regs->reg6_y_virstride.y_virstride = y_virstride; + + regs->reg7_tbl_len.y_hor_virstride_h = (y_hor_stride >> 16) & 1; + + if (s->qtable_cnt) + regs->reg7_tbl_len.qtbl_len = regs->reg4_pic_fmt.qtables_sel * 8 - 1; + else + regs->reg7_tbl_len.qtbl_len = 0; + + // 8 bit precision 12, 12 bit precision 16; + regs->reg7_tbl_len.htbl_value_len = regs->reg4_pic_fmt.htables_sel * ((regs->reg4_pic_fmt.pixel_depth != 0) ? 16 : 12) - 1; + + switch (regs->reg4_pic_fmt.htables_sel) { + case TBL_ENTRY_0 : + regs->reg7_tbl_len.htbl_mincode_len = 0; + regs->reg7_tbl_len.htbl_value_len = 0; + break; + case TBL_ENTRY_2 : + regs->reg7_tbl_len.htbl_mincode_len = (s->nb_components - 1) * 6 - 1; + break; + case TBL_ENTRY_1 : + case TBL_ENTRY_3 : + regs->reg7_tbl_len.htbl_mincode_len = s->nb_components * 6 - 1; + break; + default : + mpp_err_f("unsupported htable_sel %d\n", regs->reg4_pic_fmt.htables_sel); + break; + } + + RK_U32 strm_offset = 0; + RK_U32 hw_strm_offset = 0; + RK_U8 start_byte = 0; + RK_U32 table_fd = mpp_buffer_get_fd(ctx->pTableBase); + + if (table_fd <= 0) { + mpp_err_f("get table_fd failed\n"); + return MPP_NOK; + } + + strm_offset = s->strm_offset; + hw_strm_offset = strm_offset - strm_offset % 16; + start_byte = strm_offset % 16; + + regs->reg8_strm_len.stream_len = (MPP_ALIGN((s->pkt_len - hw_strm_offset), 16) - 1) >> 4; + regs->reg8_strm_len.strm_start_byte = start_byte; + + regs->reg9_qtbl_base = table_fd; + regs->reg10_htbl_mincode_base = table_fd; + regs->reg11_htbl_value_base = table_fd; + regs->reg13_dec_out_base = ctx->frame_fd; + regs->reg12_strm_base = ctx->pkt_fd; + + mpp_dev_set_reg_offset(ctx->cfg->dev, 12, hw_strm_offset); + mpp_dev_set_reg_offset(ctx->cfg->dev, 10, RKD_HUFFMAN_MINCODE_TBL_OFFSET); + mpp_dev_set_reg_offset(ctx->cfg->dev, 11, RKD_HUFFMAN_VALUE_TBL_OFFSET); + + regs->reg14_strm_error.error_prc_mode = 1; + regs->reg14_strm_error.strm_ffff_err_mode = 2; + regs->reg14_strm_error.strm_other_mark_mode = 2; + regs->reg14_strm_error.strm_dri_seq_err_mode = 0; + + regs->reg16_clk_gate.val = 0xff; + + regs->reg30_perf_latency_ctrl0.axi_perf_work_e = 1; + regs->reg30_perf_latency_ctrl0.axi_perf_clr_e = 1; + regs->reg30_perf_latency_ctrl0.axi_cnt_type = 1; + regs->reg30_perf_latency_ctrl0.rd_latency_id = 0xa; + + jpegd_vpu7xx_write_htbl(ctx, s); + + jpegd_vpu7xx_write_qtbl(ctx, s); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_rkv_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + + jpegd_dbg_func("enter\n"); + + if (ctx->pTableBase) { + ret = mpp_buffer_put(ctx->pTableBase); + if (ret) { + mpp_err_f("put buffer failed\n"); + return ret; + } + } + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + ctx->output_fmt = MPP_FMT_YUV420SP; + ctx->set_output_fmt_flag = 0; + ctx->hal_debug_enable = 0; + ctx->frame_count = 0; + ctx->output_yuv_count = 0; + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_rkv_gen_regs(void *hal, HalTaskInfo *syn) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + JpegdSyntax *s = (JpegdSyntax *)syn->dec.syntax.data; + + MppBuffer strm_buf = NULL; + MppBuffer output_buf = NULL; + + if (syn->dec.flags.parse_err) + goto __RETURN; + + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, syn->dec.input, SLOT_BUFFER, & strm_buf); + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, syn->dec.output, SLOT_BUFFER, &output_buf); + + ctx->pkt_fd = mpp_buffer_get_fd(strm_buf); + if (ctx->pkt_fd <= 0) { + mpp_err_f("get pkt_fd failed\n"); + goto __RETURN; + } + + ctx->frame_fd = mpp_buffer_get_fd(output_buf); + if (ctx->frame_fd <= 0) { + mpp_err_f("get frame_fd failed\n"); + goto __RETURN; + } + + memset(ctx->regs, 0, sizeof(JpegRegSet)); + + setup_output_fmt(ctx, s, syn->dec.output); + + ret = jpegd_gen_regs(ctx, s); + mpp_buffer_sync_end(strm_buf); + mpp_buffer_sync_end(ctx->pTableBase); + + if (ret != MPP_OK) { + mpp_err_f("generate registers failed\n"); + goto __RETURN; + } + + syn->dec.valid = 1; + jpegd_dbg_func("exit\n"); + return ret; + +__RETURN: + syn->dec.flags.parse_err = 1; + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_rkv_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx * ctx = (JpegdHalCtx *)hal; + MppDev dev = ctx->cfg->dev; + RK_U32 *regs = (RK_U32 *)ctx->regs; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __RETURN; + + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = JPEGD_REG_NUM * sizeof(RK_U32); + RK_U8 i = 0; + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + if (jpegd_debug & JPEGD_DBG_HAL_INFO) { + for (i = 0; i < JPEGD_REG_NUM; i++) { + mpp_log_f("send reg[%d]=0x%08x\n", i, regs[i]); + } + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto __RETURN; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + goto __RETURN; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + goto __RETURN; + } + + jpegd_dbg_func("exit\n"); + return ret; + +__RETURN: + task->dec.flags.parse_err = 1; + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_rkv_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + MppDev dev = ctx->cfg->dev; + JpegRegSet *reg_out = ctx->regs; + RK_U32 errinfo = 0; + RK_U8 i = 0; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __SKIP_HARD; + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + + if (ret) { + task->dec.flags.parse_err = 1; + mpp_err_f("poll cmd failed %d\n", ret); + } + +__SKIP_HARD: + if (ctx->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)reg_out; + if (!reg_out->reg1_int.dec_irq || !reg_out->reg1_int.dec_rdy_sta + || reg_out->reg1_int.dec_bus_sta || reg_out->reg1_int.dec_error_sta + || reg_out->reg1_int.dec_timeout_sta + || reg_out->reg1_int.dec_buf_empty_sta) { + mpp_err("decode result: failed, irq 0x%08x\n", ((RK_U32 *)reg_out)[1]); + errinfo = 1; + } + param.hard_err = errinfo; + mpp_callback(ctx->cfg->dec_cb, ¶m); + } + if (jpegd_debug & JPEGD_DBG_HAL_INFO) { + for (i = 0; i < JPEGD_REG_NUM; i++) { + mpp_log_f("read regs[%d]=0x%08x\n", i, ((RK_U32*)reg_out)[i]); + } + } + + jpegd_dbg_hal("decode one frame in cycles: %d\n", reg_out->reg39_perf_working_cnt); + if (jpegd_debug & JPEGD_DBG_IO) { + FILE *jpg_file; + char name[32]; + MppBuffer outputBuf = NULL; + void *base = NULL; + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, task->dec.output, SLOT_BUFFER, &outputBuf); + base = mpp_buffer_get_ptr(outputBuf); + + snprintf(name, sizeof(name) - 1, "/data/tmp/output%02d.yuv", ctx->output_yuv_count); + jpg_file = fopen(name, "wb+"); + if (jpg_file) { + JpegdSyntax *s = (JpegdSyntax *) task->dec.syntax.data; + RK_U32 width = s->hor_stride; + RK_U32 height = s->ver_stride; + + fwrite(base, width * height * 3, 1, jpg_file); + jpegd_dbg_io("frame_%02d output YUV(%d*%d) saving to %s\n", ctx->output_yuv_count, + width, height, name); + fclose(jpg_file); + ctx->output_yuv_count++; + } + } + + memset(®_out->reg1_int, 0, sizeof(RK_U32)); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_rkv_control(void *hal, MpiCmd cmd_type, void *param) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + + if (NULL == JpegHalCtx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + + switch (cmd_type) { + case MPP_DEC_SET_OUTPUT_FORMAT: { + MppFrameFormat output_fmt = *((MppFrameFormat *)param); + RockchipSocType soc_type = mpp_get_soc_type(); + MppFrameFormat frm_fmt = output_fmt & MPP_FRAME_FMT_MASK; + + if (MPP_FRAME_FMT_IS_FBC(output_fmt)) { + ret = MPP_ERR_VALUE; + } + + if (MPP_FRAME_FMT_IS_TILE(output_fmt)) { + if (soc_type < ROCKCHIP_SOC_RK3576 || MPP_FRAME_FMT_IS_RGB(output_fmt)) { + ret = MPP_ERR_VALUE; + } + } + + if (MPP_FRAME_FMT_IS_RGB(output_fmt)) { + // The new JPEG decoder defaults to no RGB support. + if (soc_type >= ROCKCHIP_SOC_RK3576) { + ret = MPP_ERR_VALUE; + } else if (soc_type >= ROCKCHIP_SOC_RK3588) { + // only rgb565be and rgb888 supported + if (output_fmt != MPP_FMT_RGB555 && output_fmt != MPP_FMT_RGB888 ) { + ret = MPP_ERR_VALUE; + } + } else { + // only bgr565le and rgb 888 supported + if (frm_fmt != (MPP_FMT_BGR565 | MPP_FRAME_FMT_LE_MASK) + && output_fmt != MPP_FMT_RGB888) { + ret = MPP_ERR_VALUE; + } + } + } + + if (ret) { + mpp_err_f("invalid output format 0x%x\n", output_fmt); + } else { + JpegHalCtx->output_fmt = output_fmt; + JpegHalCtx->set_output_fmt_flag = 1; + jpegd_dbg_hal("output_format: 0x%x\n", JpegHalCtx->output_fmt); + } + } break; + //TODO support scale and tile output + default : + break; + } + + jpegd_dbg_func("exit ret %d\n", ret); + return ret; +} + +const MppHalApi hal_jpegd_rkv = { + .name = "jpegd_rkv", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegdHalCtx), + .flag = 0, + .init = hal_jpegd_rkv_init, + .deinit = hal_jpegd_rkv_deinit, + .reg_gen = hal_jpegd_rkv_gen_regs, + .start = hal_jpegd_rkv_start, + .wait = hal_jpegd_rkv_wait, + .reset = NULL, + .flush = NULL, + .control = hal_jpegd_rkv_control, + .client = VPU_CLIENT_JPEG_DEC, + .soc_type = { + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3562, + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_RV1126B, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_jpegd_rkv) diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_rkv.h b/mpp/hal/vpu/jpegd/hal_jpegd_rkv.h new file mode 100644 index 000000000..d4e428ae2 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_rkv.h @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAL_JPEGD_RKV_H +#define HAL_JPEGD_RKV_H + +#include "rk_type.h" + +#include "mpp_hal.h" + +extern const MppHalApi hal_jpegd_rkv; + +#endif /* HAL_JPEGD_RKV_H */ diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_rkv_reg.h b/mpp/hal/vpu/jpegd/hal_jpegd_rkv_reg.h new file mode 100644 index 000000000..f903dedf8 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_rkv_reg.h @@ -0,0 +1,256 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAL_JPEGD_RKV_REG_H +#define HAL_JPEGD_RKV_REG_H + +#define JPEGD_REG_NUM (42) + +typedef struct { + struct { + RK_U32 minor_ver : 8; + RK_U32 bit_depth : 1; + RK_U32 : 7; + RK_U32 prod_num : 16; + } reg0_id; + + struct { + RK_U32 dec_e : 1; + RK_U32 dec_irq_dis : 1; + RK_U32 dec_timeout_e : 1; + RK_U32 buf_empty_e : 1; + RK_U32 buf_empty_reload_p : 1; + RK_U32 soft_rst_en_p : 1; + RK_U32 dec_irq_raw : 1; + RK_U32 wait_reset_e : 1; + RK_U32 dec_irq : 1; + RK_U32 dec_rdy_sta : 1; + RK_U32 dec_bus_sta : 1; + RK_U32 dec_error_sta : 1; + RK_U32 dec_timeout_sta : 1; + RK_U32 dec_buf_empty_sta : 1; + RK_U32 soft_rest_rdy : 1; + RK_U32 buf_empty_force_end_flag : 1; + RK_U32 care_strm_error_e : 1; + RK_U32 low_delay_out_sta : 1; + RK_U32 lkt_operation_error_sta : 1; + RK_U32 lkt_mode_int_sta : 1; + RK_U32 lkt_force_stop_sta : 1; + RK_U32 lkt_node_int_sta : 1; + RK_U32 lkt_err_stop_sta : 1; + RK_U32 lkt_data_err_sta : 1; + RK_U32 : 8; + } reg1_int; + + struct { + RK_U32 in_endian : 1; + RK_U32 in_swap32_e : 1; + RK_U32 in_swap64_e : 1; + RK_U32 str_endian : 1; + RK_U32 str_swap32_e : 1; + RK_U32 str_swap64_e : 1; + RK_U32 out_endian : 1; + RK_U32 out_swap32_e : 1; + RK_U32 out_swap64_e : 1; + RK_U32 out_cbcr_swap : 1; + RK_U32 out_byte_swap : 1; + RK_U32 : 1; + RK_U32 scaledown_mode : 2; + RK_U32 : 2; + RK_U32 time_out_mode : 1; + RK_U32 force_softrest_valid : 1; + RK_U32 : 2; + RK_U32 fbc_e : 1; + RK_U32 allow_16x8_cp_flag : 1; + RK_U32 fbc_force_uncompress : 1; + // 0 -- rgb565/rgb888, 1 -- bgr565, bgr888 + RK_U32 bgr_sequence : 1; + RK_U32 fill_down_e : 1; + RK_U32 fill_right_e : 1; + RK_U32 dec_out_sequence : 1; + RK_U32 yuv_out_format : 3; + RK_U32 yuv2rgb_rec : 1; + RK_U32 yuv2rgb_range : 1; + + } reg2_sys; + + struct { + RK_U32 pic_width_m1 : 16; + RK_U32 pic_height_m1 : 16; + } reg3_pic_size; + + struct { + RK_U32 jpeg_mode : 3; + RK_U32 : 1; + RK_U32 pixel_depth : 3; + RK_U32 : 1; + RK_U32 qtables_sel : 2; + RK_U32 : 2; + RK_U32 htables_sel : 2; + RK_U32 : 1; + RK_U32 dri_e : 1; + RK_U32 dri_mcu_num_m1 : 16; + } reg4_pic_fmt; + + struct { + RK_U32 y_hor_virstride : 16; + RK_U32 uv_hor_virstride : 16; + } reg5_hor_virstride; + + struct { + RK_U32 : 4; + RK_U32 y_virstride : 28; + } reg6_y_virstride; + + struct { + RK_U32 qtbl_len : 5; + RK_U32 : 3; + RK_U32 htbl_mincode_len : 5; + RK_U32 : 3; + RK_U32 htbl_value_len : 6; + RK_U32 : 2; + RK_U32 y_hor_virstride_h : 1; + RK_U32 : 7; + } reg7_tbl_len; + + struct { + RK_U32 strm_start_byte : 4; + RK_U32 stream_len : 28; + } reg8_strm_len; + + RK_U32 reg9_qtbl_base; //64 bytes align + + RK_U32 reg10_htbl_mincode_base; //64 bytes align + + RK_U32 reg11_htbl_value_base; //64 bytes align + + RK_U32 reg12_strm_base; //16 bytes align + + RK_U32 reg13_dec_out_base; //64 bytes align + + struct { + RK_U32 error_prc_mode : 1; + RK_U32 strm_r0_err_mode : 2; + RK_U32 strm_r1_err_mode : 2; + RK_U32 strm_ffff_err_mode : 2;//default skip 0xffff + RK_U32 strm_other_mark_mode : 2; + RK_U32 strm_dri_seq_err_mode : 1; + RK_U32 : 6; + RK_U32 hfm_force_stop : 5; + RK_U32 : 11; + } reg14_strm_error; + + struct { + RK_U32 strm_r0_marker : 8; + RK_U32 strm_r0_mask : 8; + RK_U32 strm_r1_marker : 8; + RK_U32 strm_r1_mask : 8; + } reg15_strm_mask; + + union { + struct { + RK_U32 dec_clkgate_e : 1; + RK_U32 dec_strm_gate_e : 1; + RK_U32 dec_huffman_gate_e : 1; + RK_U32 dec_izq_gate_e : 1; + RK_U32 dec_idct_gate_e : 1; + RK_U32 busifd_gate_e : 1; + RK_U32 post_prs_gate_e : 1; + RK_U32 dec_sram_gate_e : 1; + RK_U32 : 24; + }; + RK_U32 val; + } reg16_clk_gate; + + // 0x0044, bit[16:0] + RK_U32 reg17_low_delay_output; + // 0x0048, bit[16:0] + RK_U32 reg18_low_delay_output_status; + + // 0x004c ~ 0x0074 + RK_U32 reg19_29[11]; + + // 0x0078 + struct { + RK_U32 axi_perf_work_e : 1; + RK_U32 axi_perf_clr_e : 1; + RK_U32 axi_perf_frm_type : 1; + RK_U32 axi_cnt_type : 1; + RK_U32 rd_latency_id : 4; + RK_U32 rd_latency_thr : 12; + RK_U32 : 12; + } reg30_perf_latency_ctrl0; + + struct { + RK_U32 addr_align_type : 2; + RK_U32 ar_cnt_id_type : 1; + RK_U32 aw_cnt_id_type : 1; + RK_U32 ar_count_id : 4; + RK_U32 aw_count_id : 4; + RK_U32 rd_totoal_bytes_mode : 1; + RK_U32 : 19; + } reg31_perf_latency_ctrl1; + + struct { + RK_U32 mcu_pos_x : 16; + RK_U32 mcu_pos_y : 16; + } reg32_dbg_mcu_pos; + + struct { + RK_U32 stream_dri_seq_err_sta : 1; + RK_U32 stream_r0_err_sta : 1; + RK_U32 stream_r1_err_sta : 1; + RK_U32 stream_ffff_err_sta : 1; + RK_U32 stream_other_mark_err_sta : 1; + RK_U32 : 3; + RK_U32 huffman_mcu_cnt_l : 1; + RK_U32 huffman_mcu_cnt_m : 1; + RK_U32 huffman_eoi_without_end : 1; + RK_U32 huffman_end_without_eoi : 1; + RK_U32 huffman_overflow : 1; + RK_U32 huffman_buf_empty : 1; + RK_U32 : 2; + RK_U32 first_error_idx : 4; + RK_U32 : 12; + } regs33_dbg_error_info; + + struct { + RK_U32 rd_max_latency_num_ch0 : 16; + RK_U32 : 16; + } reg34_perf_rd_max_latency_num0; + + RK_U32 reg35_perf_rd_latency_samp_num; + + RK_U32 reg36_perf_rd_latency_acc_sum; + + RK_U32 reg37_perf_rd_axi_total_byte; + + RK_U32 reg38_perf_wr_axi_total_byte; + + RK_U32 reg39_perf_working_cnt; + + struct { + RK_U32 bus_status_flag : 19; + RK_U32 : 13; + } reg40_dbg_bus_sta; + + struct { + RK_U32 work_status_flag : 18; + RK_U32 : 14; + } reg41_dbg_work_sta; + +} JpegRegSet; + +#endif /* HAL_JPEGD_RKV_REG_H */ \ No newline at end of file diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1.c b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1.c new file mode 100644 index 000000000..0d22fa4db --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1.c @@ -0,0 +1,1078 @@ +/* + * + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "HAL_JPEGD_VDPU1" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_frame.h" +#include "mpp_common.h" + +#include "jpegd_syntax.h" +#include "hal_jpegd_common.h" +#include "hal_jpegd_vdpu1.h" +#include "hal_jpegd_vdpu1_reg.h" +#include "mpp_dec_cb_param.h" + +static void +jpegd_write_code_word_number(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = syntax; + AcTable *ac_ptr0 = NULL, *ac_ptr1 = NULL; + DcTable *dc_ptr0 = NULL, *dc_ptr1 = NULL; + + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &info->regs; + + /* first, select the table we'll use. + * this trick is done because hardware always wants luma + * table as AC hardware table 0. + */ + if (s->ac_index[0] == HUFFMAN_TABLE_ID_ZERO) { + /* Luma's AC uses Huffman table zero */ + ac_ptr0 = &(s->ac_table[HUFFMAN_TABLE_ID_ZERO]); + ac_ptr1 = &(s->ac_table[HUFFMAN_TABLE_ID_ONE]); + } else { + ac_ptr0 = &(s->ac_table[HUFFMAN_TABLE_ID_ONE]); + ac_ptr1 = &(s->ac_table[HUFFMAN_TABLE_ID_ZERO]); + } + + /* write AC table 1 (luma) */ + reg->reg16.sw_ac1_code1_cnt = ac_ptr0->bits[0]; + reg->reg16.sw_ac1_code2_cnt = ac_ptr0->bits[1]; + reg->reg16.sw_ac1_code3_cnt = ac_ptr0->bits[2]; + reg->reg16.sw_ac1_code4_cnt = ac_ptr0->bits[3]; + reg->reg16.sw_ac1_code5_cnt = ac_ptr0->bits[4]; + reg->reg16.sw_ac1_code6_cnt = ac_ptr0->bits[5]; + + reg->reg17.sw_ac1_code7_cnt = ac_ptr0->bits[6]; + reg->reg17.sw_ac1_code8_cnt = ac_ptr0->bits[7]; + reg->reg17.sw_ac1_code9_cnt = ac_ptr0->bits[8]; + reg->reg17.sw_ac1_code10_cnt = ac_ptr0->bits[9]; + + reg->reg18.sw_ac1_code11_cnt = ac_ptr0->bits[10]; + reg->reg18.sw_ac1_code12_cnt = ac_ptr0->bits[11]; + reg->reg18.sw_ac1_code13_cnt = ac_ptr0->bits[12]; + reg->reg18.sw_ac1_code14_cnt = ac_ptr0->bits[13]; + + reg->reg19.sw_ac1_code15_cnt = ac_ptr0->bits[14]; + reg->reg19.sw_ac1_code16_cnt = ac_ptr0->bits[15]; + + /* table AC2 (the not-luma table) */ + reg->reg19.sw_ac2_code1_cnt = ac_ptr1->bits[0]; + reg->reg19.sw_ac2_code2_cnt = ac_ptr1->bits[1]; + reg->reg19.sw_ac2_code3_cnt = ac_ptr1->bits[2]; + reg->reg19.sw_ac2_code4_cnt = ac_ptr1->bits[3]; + + reg->reg20.sw_ac2_code5_cnt = ac_ptr1->bits[4]; + reg->reg20.sw_ac2_code6_cnt = ac_ptr1->bits[5]; + reg->reg20.sw_ac2_code7_cnt = ac_ptr1->bits[6]; + reg->reg20.sw_ac2_code8_cnt = ac_ptr1->bits[7]; + + reg->reg21.sw_ac2_code9_cnt = ac_ptr1->bits[8]; + reg->reg21.sw_ac2_code10_cnt = ac_ptr1->bits[9]; + reg->reg21.sw_ac2_code11_cnt = ac_ptr1->bits[10]; + reg->reg21.sw_ac2_code12_cnt = ac_ptr1->bits[11]; + + reg->reg22.sw_ac2_code13_cnt = ac_ptr1->bits[12]; + reg->reg22.sw_ac2_code14_cnt = ac_ptr1->bits[13]; + reg->reg22.sw_ac2_code15_cnt = ac_ptr1->bits[14]; + reg->reg22.sw_ac2_code16_cnt = ac_ptr1->bits[15]; + + /* first, select the table we'll use. + * this trick is done because hardware always wants luma + * table as DC hardware table 0. + */ + if (s->dc_index[0] == HUFFMAN_TABLE_ID_ZERO) { + /* Luma's DC uses Huffman table zero */ + dc_ptr0 = &(s->dc_table[HUFFMAN_TABLE_ID_ZERO]); + dc_ptr1 = &(s->dc_table[HUFFMAN_TABLE_ID_ONE]); + } else { + dc_ptr0 = &(s->dc_table[HUFFMAN_TABLE_ID_ONE]); + dc_ptr1 = &(s->dc_table[HUFFMAN_TABLE_ID_ZERO]); + } + + /* write DC table 1 (luma) */ + reg->reg23.sw_dc1_code1_cnt = dc_ptr0->bits[0]; + reg->reg23.sw_dc1_code2_cnt = dc_ptr0->bits[1]; + reg->reg23.sw_dc1_code3_cnt = dc_ptr0->bits[2]; + reg->reg23.sw_dc1_code4_cnt = dc_ptr0->bits[3]; + reg->reg23.sw_dc1_code5_cnt = dc_ptr0->bits[4]; + reg->reg23.sw_dc1_code6_cnt = dc_ptr0->bits[5]; + reg->reg23.sw_dc1_code7_cnt = dc_ptr0->bits[6]; + reg->reg23.sw_dc1_code8_cnt = dc_ptr0->bits[7]; + + reg->reg24.sw_dc1_code9_cnt = dc_ptr0->bits[8]; + reg->reg24.sw_dc1_code10_cnt = dc_ptr0->bits[9]; + reg->reg24.sw_dc1_code11_cnt = dc_ptr0->bits[10]; + reg->reg24.sw_dc1_code12_cnt = dc_ptr0->bits[11]; + reg->reg24.sw_dc1_code13_cnt = dc_ptr0->bits[12]; + reg->reg24.sw_dc1_code14_cnt = dc_ptr0->bits[13]; + reg->reg24.sw_dc1_code15_cnt = dc_ptr0->bits[14]; + reg->reg24.sw_dc1_code16_cnt = dc_ptr0->bits[15]; + + /* table DC2 (the not-luma table) */ + reg->reg25.sw_dc2_code1_cnt = dc_ptr1->bits[0]; + reg->reg25.sw_dc2_code2_cnt = dc_ptr1->bits[1]; + reg->reg25.sw_dc2_code3_cnt = dc_ptr1->bits[2]; + reg->reg25.sw_dc2_code4_cnt = dc_ptr1->bits[3]; + reg->reg25.sw_dc2_code5_cnt = dc_ptr1->bits[4]; + reg->reg25.sw_dc2_code6_cnt = dc_ptr1->bits[5]; + reg->reg25.sw_dc2_code7_cnt = dc_ptr1->bits[6]; + reg->reg25.sw_dc2_code8_cnt = dc_ptr1->bits[7]; + + reg->reg26.sw_dc2_code9_cnt = dc_ptr1->bits[8]; + reg->reg26.sw_dc2_code10_cnt = dc_ptr1->bits[9]; + reg->reg26.sw_dc2_code11_cnt = dc_ptr1->bits[10]; + reg->reg26.sw_dc2_code12_cnt = dc_ptr1->bits[11]; + reg->reg26.sw_dc2_code13_cnt = dc_ptr1->bits[12]; + reg->reg26.sw_dc2_code14_cnt = dc_ptr1->bits[13]; + reg->reg26.sw_dc2_code15_cnt = dc_ptr1->bits[14]; + reg->reg26.sw_dc2_code16_cnt = dc_ptr1->bits[15]; + + jpegd_dbg_func("exit\n"); + return; +} + +static void +jpegd_set_stream_offset(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = syntax; + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &info->regs; + RK_U32 offset = 0, byte_cnt = 0; + RK_U32 bit_pos_in_byte = 0; + RK_U32 strm_len_by_hw = 0; + + /* calculate and set stream start address to hw, + * the offset must be 8-byte aligned. + */ + offset = (s->strm_offset & (~7)); + reg->reg12_input_stream_base = ctx->pkt_fd; + if (offset) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 12, offset); + } + + /* calculate and set stream start bit to hardware + * change current pos to bus address style + * remove three lowest bits and add the difference to bitPosInWord + * used as bit pos in word not as bit pos in byte actually... + */ + byte_cnt = ((uintptr_t) s->cur_pos & (7)); + bit_pos_in_byte = byte_cnt * 8; /* 1 Byte = 8 bits */ + reg->reg5.sw_strm0_start_bit = bit_pos_in_byte; + + /* set up stream length for HW. + * length = size of original buffer - stream we already decoded in SW + */ + strm_len_by_hw = s->pkt_len - offset; + reg->reg6_stream_info.sw_stream_len = strm_len_by_hw; + reg->reg5.sw_jpeg_stream_all = 1; + + jpegd_dbg_func("exit\n"); + return; +} + +static void +jpegd_set_chroma_table_id(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = syntax; + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &info->regs; + + /* this trick is done because hw always wants + * luma table as ac hw table 1 + */ + if (s->ac_index[0] == HUFFMAN_TABLE_ID_ZERO) { + reg->reg5.sw_cb_ac_vlctable = s->ac_index[1]; + reg->reg5.sw_cr_ac_vlctable = s->ac_index[2]; + } else { + if (s->ac_index[0] == s->ac_index[1]) + reg->reg5.sw_cb_ac_vlctable = 0; + else + reg->reg5.sw_cb_ac_vlctable = 1; + + if (s->ac_index[0] == s->ac_index[2]) + reg->reg5.sw_cr_ac_vlctable = 0; + else + reg->reg5.sw_cr_ac_vlctable = 1; + } + + /* Third DC table selectors */ + if (s->dc_index[0] == HUFFMAN_TABLE_ID_ZERO) { + reg->reg5.sw_cb_dc_vlctable = s->dc_index[1]; + reg->reg5.sw_cr_dc_vlctable = s->dc_index[2]; + } else { + if (s->dc_index[0] == s->dc_index[1]) + reg->reg5.sw_cb_dc_vlctable = 0; + else + reg->reg5.sw_cb_dc_vlctable = 1; + + if (s->dc_index[0] == s->dc_index[2]) + reg->reg5.sw_cr_dc_vlctable = 0; + else + reg->reg5.sw_cr_dc_vlctable = 1; + } + + reg->reg5.sw_cr_dc_vlctable3 = 0; + reg->reg5.sw_cb_dc_vlctable3 = 0; + + jpegd_dbg_func("exit\n"); + return; +} + +static MPP_RET jpegd_setup_pp(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *regs = &info->regs; + post_processor_reg *post = ®s->post; + JpegdSyntax *s = syntax; + + RK_U32 in_color = ctx->pp_info.pp_in_fmt; + RK_U32 out_color = ctx->pp_info.pp_out_fmt; + RK_U32 dither = ctx->pp_info.dither_enable; + RK_U32 crop_width = ctx->pp_info.crop_width; + RK_U32 crop_height = ctx->pp_info.crop_height; + RK_U32 crop_x = ctx->pp_info.crop_x; + RK_U32 crop_y = ctx->pp_info.crop_y; + RK_U32 in_width = s->hor_stride; + RK_U32 in_height = s->ver_stride; + RK_U32 out_width = s->hor_stride; + RK_U32 out_height = s->ver_stride; + RK_U32 uv_offset = s->hor_stride * s->ver_stride; + + int video_range = 1; + + post->reg61_dev_conf.sw_pp_axi_rd_id = 0; + post->reg61_dev_conf.sw_pp_axi_wr_id = 0; + post->reg61_dev_conf.sw_pp_scmd_dis = 1; + post->reg61_dev_conf.sw_pp_max_burst = 16; + post->reg61_dev_conf.sw_pp_in_a2_endsel = 1; + post->reg61_dev_conf.sw_pp_in_a1_swap32 = 1; + post->reg61_dev_conf.sw_pp_in_a1_endian = 1; + post->reg61_dev_conf.sw_pp_in_swap32_e = 1; + post->reg61_dev_conf.sw_pp_in_endian = 1; + post->reg61_dev_conf.sw_pp_out_endian = 1; + post->reg61_dev_conf.sw_pp_out_swap32_e = 1; + + post->reg63_pp_in_lu_base = 0; + + post->reg88_mask_1_size.sw_ext_orig_width = in_width >> 4; + + post->reg61_dev_conf.sw_pp_clk_gate_e = 0; + post->reg61_dev_conf.sw_pp_ahb_hlock_e = 1; + post->reg61_dev_conf.sw_pp_data_disc_e = 1; + + if (crop_width <= 0) { + post->reg92_display.sw_pp_in_w_ext = (((in_width / 16) & 0xE00) >> 9); + post->reg72_crop.sw_pp_in_width = ((in_width / 16) & 0x1FF); + post->reg92_display.sw_pp_in_h_ext = (((in_height / 16) & 0x700) >> 8); + post->reg72_crop.sw_pp_in_height = ((in_height / 16) & 0x0FF); + } else { + post->reg92_display.sw_pp_in_w_ext = + (((crop_width / 16) & 0xE00) >> 9); + post->reg72_crop.sw_pp_in_width = ((crop_width / 16) & 0x1FF); + post->reg92_display.sw_pp_in_h_ext = + (((crop_height / 16) & 0x700) >> 8); + post->reg72_crop.sw_pp_in_height = ((crop_height / 16) & 0x0FF); + + post->reg92_display.sw_crop_startx_ext = + (((crop_x / 16) & 0xE00) >> 9); + post->reg71_color_coeff_1.sw_crop_startx = + ((crop_x / 16) & 0x1FF); + post->reg92_display.sw_crop_starty_ext = + (((crop_y / 16) & 0x700) >> 8); + post->reg72_crop.sw_crop_starty = + ((crop_y / 16) & 0x0FF); + + if (crop_width & 0x0F) { + post->reg85_ctrl.sw_pp_crop8_r_e = 1; + } else { + post->reg85_ctrl.sw_pp_crop8_r_e = 0; + } + if (crop_height & 0x0F) { + post->reg85_ctrl.sw_pp_crop8_d_e = 1; + } else { + post->reg85_ctrl.sw_pp_crop8_d_e = 0; + } + in_width = crop_width; + in_height = crop_height; + } + + post->reg92_display.sw_display_width = out_width; + post->reg85_ctrl.sw_pp_out_width = out_width; + post->reg85_ctrl.sw_pp_out_height = out_height; + post->reg66_pp_out_lu_base = ctx->frame_fd; + + switch (in_color) { + case PP_IN_FORMAT_YUV422INTERLAVE: + case PP_IN_FORMAT_YUV420SEMI: + case PP_IN_FORMAT_YUV420PLANAR: + case PP_IN_FORMAT_YUV400: + case PP_IN_FORMAT_YUV422SEMI: + case PP_IN_FORMAT_YUV420SEMITIELED: + case PP_IN_FORMAT_YUV440SEMI: + post->reg85_ctrl.sw_pp_in_format = in_color; + break; + case PP_IN_FORMAT_YUV444_SEMI: + post->reg85_ctrl.sw_pp_in_format = 7; + post->reg86_mask_1.sw_pp_in_format_es = 0; + break; + case PP_IN_FORMAT_YUV411_SEMI: + post->reg85_ctrl.sw_pp_in_format = 0; + post->reg86_mask_1.sw_pp_in_format_es = 1; + break; + default: + mpp_err_f("unsupported format:%d", in_color); + return -1; + } + + post->reg72_crop.sw_rangemap_coef_y = 9; + post->reg86_mask_1.sw_rangemap_coef_c = 9; + /* brightness */ + post->reg71_color_coeff_1.sw_color_coefff = BRIGHTNESS; + + if (out_color <= PP_OUT_FORMAT_ARGB) { + /*Bt.601*/ + unsigned int a = 298; + unsigned int b = 409; + unsigned int c = 208; + unsigned int d = 100; + unsigned int e = 516; + + /*Bt.709 + unsigned int a = 298; + unsigned int b = 459; + unsigned int c = 137; + unsigned int d = 55; + unsigned int e = 544;*/ + + int satur = 0, tmp; + if (video_range != 0) { + /*Bt.601*/ + a = 256; + b = 350; + c = 179; + d = 86; + e = 443; + /*Bt.709 + a = 256; + b = 403; + c = 120; + d = 48; + e = 475;*/ + + post->reg79_scaling_0.sw_ycbcr_range = video_range; + } + int contrast = CONTRAST; + if (contrast != 0) { + int thr1y, thr2y, off1, off2, thr1, thr2, a1, a2; + if (video_range == 0) { + int tmp1, tmp2; + /* Contrast */ + thr1 = (219 * (contrast + 128)) / 512; + thr1y = (219 - 2 * thr1) / 2; + thr2 = 219 - thr1; + thr2y = 219 - thr1y; + + tmp1 = (thr1y * 256) / thr1; + tmp2 = ((thr2y - thr1y) * 256) / (thr2 - thr1); + off1 = ((thr1y - ((tmp2 * thr1) / 256)) * a) / 256; + off2 = ((thr2y - ((tmp1 * thr2) / 256)) * a) / 256; + + tmp1 = (64 * (contrast + 128)) / 128; + tmp2 = 256 * (128 - tmp1); + a1 = (tmp2 + off2) / thr1; + a2 = a1 + (256 * (off2 - 1)) / (thr2 - thr1); + } else { + /* Contrast */ + thr1 = (64 * (contrast + 128)) / 128; + thr1y = 128 - thr1; + thr2 = 256 - thr1; + thr2y = 256 - thr1y; + a1 = (thr1y * 256) / thr1; + a2 = ((thr2y - thr1y) * 256) / (thr2 - thr1); + off1 = thr1y - (a2 * thr1) / 256; + off2 = thr2y - (a1 * thr2) / 256; + } + + if (a1 > 1023) + a1 = 1023; + else if (a1 < 0) + a1 = 0; + + if (a2 > 1023) + a2 = 1023; + else if (a2 < 0) + a2 = 0; + + if (thr1 > 255) + thr1 = 255; + else if (thr1 < 0) + thr1 = 0; + + if (thr2 > 255) + thr2 = 255; + else if (thr2 < 0) + thr2 = 0; + + if (off1 > 511) + off1 = 511; + else if (off1 < -512) + off1 = -512; + + if (off2 > 511) + off2 = 511; + else if (off2 < -512) + off2 = -512; + + post->reg68_contrast_adjust.sw_contrast_thr1 = thr1; + post->reg69.sw_contrast_thr2 = thr2; + post->reg68_contrast_adjust.sw_contrast_off1 = off1; + post->reg68_contrast_adjust.sw_contrast_off2 = off2; + + post->reg69.sw_color_coeffa1 = a1; + post->reg69.sw_color_coeffa2 = a2; + } else { + post->reg68_contrast_adjust.sw_contrast_thr1 = 55; + post->reg69.sw_contrast_thr2 = 165; + post->reg68_contrast_adjust.sw_contrast_off1 = 0; + post->reg68_contrast_adjust.sw_contrast_off2 = 0; + + tmp = a; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + + post->reg69.sw_color_coeffa1 = tmp; + post->reg69.sw_color_coeffa2 = tmp; + } + + /* saturation */ + satur = 64 + SATURATION; + + tmp = (satur * (int) b) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + post->reg70_color_coeff_0.sw_color_coeffb = (unsigned int) tmp; + + tmp = (satur * (int) c) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + post->reg70_color_coeff_0.sw_color_coeffc = (unsigned int) tmp; + + tmp = (satur * (int) d) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + post->reg70_color_coeff_0.sw_color_coeffd = (unsigned int) tmp; + + tmp = (satur * (int) e) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + post->reg71_color_coeff_1.sw_color_coeffe = (unsigned int) tmp; + } + + if (out_color <= PP_OUT_FORMAT_ARGB) { + PpRgbCfg *cfg = get_pp_rgb_Cfg(ctx->output_fmt); + post->reg82_r_mask = cfg->r_mask; + post->reg83_g_mask = cfg->g_mask; + post->reg84_b_mask = cfg->b_mask; + post->reg79_scaling_0.sw_rgb_r_padd = cfg->r_padd; + post->reg79_scaling_0.sw_rgb_g_padd = cfg->g_padd; + post->reg80_scaling_1.sw_rgb_b_padd = cfg->b_padd; + + if (dither) { + jpegd_dbg_hal("we do dither."); + post->reg91_pip_2.sw_dither_select_r = cfg->r_dither; + post->reg91_pip_2.sw_dither_select_r = cfg->g_dither; + post->reg91_pip_2.sw_dither_select_r = cfg->b_dither; + } else { + jpegd_dbg_hal("we do not dither."); + } + + post->reg79_scaling_0.sw_rgb_pix_in32 = cfg->rgb_in_32; + post->reg85_ctrl.sw_pp_out_swap16_e = cfg->swap_16; + post->reg61_dev_conf.sw_pp_out_swap32_e = cfg->swap_32; + post->reg61_dev_conf.sw_pp_out_endian = cfg->out_endian; + + post->reg85_ctrl.sw_pp_out_format = 0; + + } else if (out_color == PP_OUT_FORMAT_YUV422INTERLAVE) { + post->reg85_ctrl.sw_pp_out_format = 3; + } else if (out_color == PP_OUT_FORMAT_YUV420INTERLAVE) { + post->reg85_ctrl.sw_pp_out_format = 5; + } else { + mpp_err_f("unsuppotred format:%d", out_color); + return -1; + } + + post->reg71_color_coeff_1.sw_rotation_mode = 0; + + unsigned int inw, inh; + unsigned int outw, outh; + + inw = in_width - 1; + inh = in_height - 1; + outw = out_width - 1; + outh = out_height - 1; + + if (inw < outw) { + post->reg80_scaling_1.sw_hor_scale_mode = 1; + post->reg79_scaling_0.sw_scale_wratio = (outw << 16) / inw; + post->reg81_scaling_2.sw_wscale_invra = (inw << 16) / outw; + } else if (inw > outw) { + post->reg80_scaling_1.sw_hor_scale_mode = 2; + post->reg81_scaling_2.sw_wscale_invra = ((outw + 1) << 16) / (inw + 1); + } else + post->reg80_scaling_1.sw_hor_scale_mode = 0; + + if (inh < outh) { + post->reg80_scaling_1.sw_ver_scale_mode = 1; + post->reg80_scaling_1.sw_scale_hratio = (outh << 16) / inh; + post->reg81_scaling_2.sw_hscale_invra = (inh << 16) / outh; + } else if (inh > outh) { + post->reg80_scaling_1.sw_ver_scale_mode = 2; + post->reg81_scaling_2.sw_hscale_invra = + ((outh + 1) << 16) / (inh + 1) + 1; + } else + post->reg80_scaling_1.sw_ver_scale_mode = 0; + + post->reg60_interrupt.sw_pp_pipeline_e = ctx->pp_info.pp_enable; + + if (ctx->pp_info.pp_enable) { + post->reg60_interrupt.sw_pp_pipeline_e = 1; + regs->reg3.sw_dec_out_dis = 1; + + regs->reg13_cur_pic_base = 0; + regs->reg14_sw_jpg_ch_out_base = 0; + + post->reg66_pp_out_lu_base = ctx->frame_fd; + post->reg67_pp_out_ch_base = ctx->frame_fd; + + if (uv_offset) + mpp_dev_set_reg_offset(ctx->cfg->dev, 67, uv_offset); + + jpegd_dbg_hal("output_frame_fd:%x, reg67:%x", ctx->frame_fd, + post->reg67_pp_out_ch_base); + } else { + // output without pp + post->reg60_interrupt.sw_pp_pipeline_e = 0; + regs->reg3.sw_dec_out_dis = 0; + + post->reg66_pp_out_lu_base = 0; + post->reg67_pp_out_ch_base = 0; + + regs->reg13_cur_pic_base = ctx->frame_fd; + regs->reg14_sw_jpg_ch_out_base = ctx->frame_fd; + + if (uv_offset) + mpp_dev_set_reg_offset(ctx->cfg->dev, 14, uv_offset); + + jpegd_dbg_hal("output_frame_fd:%x, reg14:%x", ctx->frame_fd, + regs->reg14_sw_jpg_ch_out_base); + } + + jpegd_dbg_func("exit\n"); + return 0; +} + +static MPP_RET jpegd_regs_init(JpegRegSet *reg) +{ + jpegd_dbg_func("enter\n"); + memset(reg, 0, sizeof(JpegRegSet)); + reg->reg2_dec_ctrl.sw_dec_out_tiled_e = 0; + reg->reg2_dec_ctrl.sw_dec_scmd_dis = DEC_VDPU1_SCMD_DISABLE; + reg->reg2_dec_ctrl.sw_dec_latency = DEC_VDPU1_LATENCY_COMPENSATION; + + reg->reg2_dec_ctrl.sw_dec_in_endian = DEC_VDPU1_BIG_ENDIAN; + reg->reg2_dec_ctrl.sw_dec_out_endian = DEC_VDPU1_LITTLE_ENDIAN; + reg->reg2_dec_ctrl.sw_dec_strendian_e = DEC_VDPU1_LITTLE_ENDIAN; + reg->reg2_dec_ctrl.sw_dec_outswap32_e = DEC_VDPU1_LITTLE_ENDIAN; + reg->reg2_dec_ctrl.sw_dec_inswap32_e = 1; + reg->reg2_dec_ctrl.sw_dec_strswap32_e = 1; + + reg->reg1_interrupt.sw_dec_irq_dis = 0; + + reg->reg2_dec_ctrl.sw_dec_axi_rn_id = 0xff; + reg->reg3.sw_dec_axi_wr_id = 0; + reg->reg2_dec_ctrl.sw_dec_max_burst = DEC_VDPU1_BUS_BURST_LENGTH_16; + reg->reg2_dec_ctrl.sw_dec_data_disc_e = DEC_VDPU1_DATA_DISCARD_ENABLE; + + reg->reg2_dec_ctrl.sw_dec_timeout_e = 1; + reg->reg2_dec_ctrl.sw_dec_clk_gate_e = 1; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET jpegd_gen_regs(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &info->regs; + JpegdSyntax *s = syntax; + + jpegd_regs_init(reg); + + /* Enable jpeg mode */ + reg->reg1_interrupt.sw_dec_e = 1; + + reg->reg3.sw_filtering_dis = 1; + + /* JPEG decoder */ + reg->reg3.sw_dec_mode = 3; + reg->reg3.sw_pjpeg_e = 0; /* Set JPEG operation mode */ + reg->reg3.sw_dec_out_dis = 0; + reg->reg3.sw_rlc_mode_e = 0; + + /* frame size, round up the number of mbs */ + reg->reg4.sw_pic_mb_h_ext = ((((s->ver_stride) >> (4)) & 0x700) >> 8); + reg->reg4.sw_pic_mb_w_ext = ((((s->hor_stride) >> (4)) & 0xE00) >> 9); + reg->reg4.sw_pic_mb_width = ((s->hor_stride) >> (4)) & 0x1FF; + reg->reg4.sw_pic_mb_height_p = ((s->ver_stride) >> (4)) & 0x0FF; + + reg->reg7.sw_pjpeg_fildown_e = s->fill_bottom; + /* Set spectral selection start coefficient */ + reg->reg7.sw_pjpeg_ss = s->scan_start; + /* Set spectral selection end coefficient */ + reg->reg7.sw_pjpeg_se = s->scan_end; + /* Set the point transform used in the preceding scan */ + reg->reg7.sw_pjpeg_ah = s->prev_shift; + /* Set the point transform value */ + reg->reg7.sw_pjpeg_al = s->point_transform; + + reg->reg5.sw_jpeg_qtables = s->qtable_cnt; + reg->reg5.sw_jpeg_mode = s->yuv_mode; + reg->reg5.sw_jpeg_filright_e = s->fill_right; + + reg->reg15.sw_jpeg_slice_h = 0; + /* + * Set bit 21 of reg148 to 1, notifying hardware to decode + * jpeg including DRI segment + */ + reg->reg5.sw_sync_marker_e = 1; + + /* tell hardware that height is 8-pixel aligned, but not 16-pixel aligned */ + if ((s->height % 16) && ((s->height % 16) <= 8) && + (s->yuv_mode == JPEGDEC_YUV422 || + s->yuv_mode == JPEGDEC_YUV444 || + s->yuv_mode == JPEGDEC_YUV411)) { + reg->reg15.sw_jpeg_height8_flag = 1; + } + + /* write VLC code word number to register */ + jpegd_write_code_word_number(ctx, s); + + /* Create AC/DC/QP tables for hardware */ + jpegd_write_qp_ac_dc_table(ctx, s); + + /* Select which tables the chromas use */ + jpegd_set_chroma_table_id(ctx, s); + + /* write table base */ + reg->reg40_qtable_base = mpp_buffer_get_fd(ctx->pTableBase); + if (reg->reg40_qtable_base <= 0) { + mpp_err_f("get qtable_base failed\n"); + return MPP_NOK; + } + + /* set up stream position for HW decode */ + jpegd_set_stream_offset(ctx, s); + + /* set restart interval */ + if (s->restart_interval) { + reg->reg5.sw_sync_marker_e = 1; + /* + * If exists DRI segment, bit 0 to bit 15 of reg8 + * is set to restart interval + */ + reg->reg8.sw_pjpeg_rest_freq = s->restart_interval; + } else { + reg->reg5.sw_sync_marker_e = 0; + } + + jpegd_setup_pp(ctx, syntax); + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET hal_jpegd_vdpu1_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + + mpp_env_get_u32("hal_jpegd_debug", &hal_jpegd_debug, 0); + + mpp_assert(JpegHalCtx); + + jpegd_dbg_func("enter\n"); + + JpegHalCtx->cfg = cfg; + JpegHalCtx->have_pp = cfg->hw_info->cap_jpg_pp_out; + + /* allocate regs buffer */ + if (JpegHalCtx->regs == NULL) { + JpegHalCtx->regs = mpp_calloc_size(void, sizeof(JpegdIocRegInfo)); + if (JpegHalCtx->regs == NULL) { + mpp_err("hal jpegd reg alloc failed\n"); + + jpegd_dbg_func("exit\n"); + return MPP_ERR_NOMEM; + } + } + JpegdIocRegInfo *info = (JpegdIocRegInfo *)JpegHalCtx->regs; + memset(info, 0, sizeof(JpegdIocRegInfo)); + + ret = mpp_buffer_get(JpegHalCtx->cfg->buf_group, &JpegHalCtx->pTableBase, + JPEGD_BASELINE_TABLE_SIZE); + if (ret) { + mpp_err_f("get table buffer failed ret %d\n", ret); + return ret; + } + + PPInfo *pp_info = &(JpegHalCtx->pp_info); + memset(pp_info, 0, sizeof(PPInfo)); + pp_info->pp_enable = 0; + pp_info->pp_in_fmt = PP_IN_FORMAT_YUV420SEMI; + pp_info->pp_out_fmt = PP_OUT_FORMAT_YUV420INTERLAVE; + + JpegHalCtx->output_fmt = MPP_FMT_YUV420SP; + JpegHalCtx->set_output_fmt_flag = 0; + + /* init dbg stuff */ + JpegHalCtx->hal_debug_enable = 0; + JpegHalCtx->frame_count = 0; + JpegHalCtx->output_yuv_count = 0; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET hal_jpegd_vdpu1_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + + jpegd_dbg_func("enter\n"); + + if (JpegHalCtx->pTableBase) { + ret = mpp_buffer_put(JpegHalCtx->pTableBase); + if (ret) { + mpp_err_f("put buffer failed\n"); + return ret; + } + } + + if (JpegHalCtx->regs) { + mpp_free(JpegHalCtx->regs); + JpegHalCtx->regs = NULL; + } + + JpegHalCtx->output_fmt = MPP_FMT_YUV420SP; + JpegHalCtx->set_output_fmt_flag = 0; + JpegHalCtx->hal_debug_enable = 0; + JpegHalCtx->frame_count = 0; + JpegHalCtx->output_yuv_count = 0; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET hal_jpegd_vdpu1_gen_regs(void *hal, HalTaskInfo *syn) +{ + jpegd_dbg_func("enter\n"); + if (NULL == hal || NULL == syn) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + JpegdSyntax *syntax = (JpegdSyntax *)syn->dec.syntax.data; + MppBuffer streambuf = NULL; + MppBuffer outputBuf = NULL; + + if (syn->dec.flags.parse_err) + goto RET; + + ret = jpeg_image_check_size(syntax->hor_stride, syntax->ver_stride); + if (ret) + goto RET; + + if (syn->dec.valid) { + jpegd_setup_output_fmt(JpegHalCtx, syntax, syn->dec.output); + if (ret) { + mpp_err_f("setup output format %x failed\n", syntax->output_fmt); + goto RET; + } + + /* input stream address */ + mpp_buf_slot_get_prop(JpegHalCtx->cfg->packet_slots, syn->dec.input, + SLOT_BUFFER, &streambuf); + JpegHalCtx->pkt_fd = mpp_buffer_get_fd(streambuf); + if (JpegHalCtx->pkt_fd <= 0) { + mpp_err_f("get pkt_fd failed\n"); + goto RET; + } + + syntax->pkt_len = jpegd_vdpu_tail_0xFF_patch(streambuf, syntax->pkt_len); + + /* output picture address */ + mpp_buf_slot_get_prop(JpegHalCtx->cfg->frame_slots, syn->dec.output, + SLOT_BUFFER, &outputBuf); + JpegHalCtx->frame_fd = mpp_buffer_get_fd(outputBuf); + if (JpegHalCtx->frame_fd <= 0) { + mpp_err_f("get frame_fd failed\n"); + goto RET; + } + + ret = jpegd_gen_regs(JpegHalCtx, syntax); + mpp_buffer_sync_end(streambuf); + mpp_buffer_sync_end(JpegHalCtx->pTableBase); + if (ret != MPP_OK) { + mpp_err_f("generate registers failed\n"); + goto RET; + } + } + + + jpegd_dbg_func("exit\n"); + return ret; + +RET: + syn->dec.valid = 0; + syn->dec.flags.parse_err = 1; + jpegd_dbg_func("exit\n"); + + return ret; +} + +static MPP_RET hal_jpegd_vdpu1_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + RK_U32 *regs = (RK_U32 *)JpegHalCtx->regs; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __RETURN; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev dev = JpegHalCtx->cfg->dev; + MppIoctlVersion ioctl_version = mpp_get_ioctl_version(); + RK_U32 reg_size = ioctl_version ? + sizeof(((JpegdIocRegInfo *)0)->regs) : + sizeof(JpegdIocRegInfo) - EXTRA_INFO_SIZE; + + if (ROCKCHIP_SOC_RK3036 == mpp_get_soc_type() && + IOCTL_VCODEC_SERVICE == ioctl_version) + reg_size -= sizeof(((JpegdIocRegInfo *)0)->regs_diff); + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto __RETURN; + } + + reg_size = sizeof(((JpegdIocRegInfo *)0)->regs); + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + goto __RETURN; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + goto __RETURN; + } + } while (0); + + jpegd_dbg_func("exit\n"); + return ret; + +__RETURN: + task->dec.flags.parse_err = 1; + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vdpu1_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + JpegRegSet *reg_out = JpegHalCtx->regs; + RK_U32 errinfo = 1; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __SKIP_HARD; + + ret = mpp_dev_ioctl(JpegHalCtx->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + task->dec.flags.parse_err = 1; + mpp_err_f("poll cmd failed %d\n", ret); + } + +__SKIP_HARD: + if (JpegHalCtx->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)reg_out; + if (reg_out->reg1_interrupt.sw_dec_bus_int) { + mpp_err_f("IRQ BUS ERROR!"); + } else if (reg_out->reg1_interrupt.sw_dec_error_int) { + /* + * NOTE: It is a bug of VDPU1, when sample color is YUV422, + * YUV444, YUV411, the height could be aligned with 8 but not 16 + */ + if (JpegHalCtx->output_fmt != MPP_FMT_YUV420SP) + ret = MPP_OK; + else + mpp_err_f("IRQ STREAM ERROR! %d", JpegHalCtx->output_fmt); + } else if (reg_out->reg1_interrupt.sw_dec_timeout) { + mpp_err_f("IRQ TIMEOUT!"); + } else if (reg_out->reg1_interrupt.sw_dec_buffer_int) { + mpp_err_f("IRQ BUFFER EMPTY!"); + } else if (reg_out->reg1_interrupt.sw_dec_irq) { + errinfo = 0; + jpegd_dbg_hal("DECODE SUCCESS!"); + } + param.hard_err = errinfo; + mpp_callback(JpegHalCtx->cfg->dec_cb, ¶m); + } + + /* debug information */ + if (jpegd_debug & JPEGD_DBG_IO) { + static FILE *jpg_file; + static char name[64]; + MppBuffer outputBuf = NULL; + void *base = NULL; + mpp_buf_slot_get_prop(JpegHalCtx->cfg->frame_slots, task->dec.output, + SLOT_BUFFER, &outputBuf); + base = mpp_buffer_get_ptr(outputBuf); + + snprintf(name, sizeof(name) - 1, "/data/tmp/output%02d.yuv", + JpegHalCtx->output_yuv_count); + jpg_file = fopen(name, "wb+"); + if (jpg_file) { + JpegdSyntax *s = (JpegdSyntax *)task->dec.syntax.data; + RK_U32 width = s->hor_stride; + RK_U32 height = s->ver_stride; + + fwrite(base, width * height * 3 / 2, 1, jpg_file); + jpegd_dbg_io("frame_%02d output YUV(%d*%d) saving to %s\n", + JpegHalCtx->output_yuv_count, + width, height, name); + + fclose(jpg_file); + JpegHalCtx->output_yuv_count++; + } + } + + memset(®_out->reg1_interrupt, 0, sizeof(RK_U32)); + jpegd_dbg_func("exit\n"); + + return ret; +} + +static MPP_RET hal_jpegd_vdpu1_control(void *hal, MpiCmd cmd_type, void *param) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + if (NULL == JpegHalCtx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + + switch (cmd_type) { + case MPP_DEC_SET_OUTPUT_FORMAT: { + JpegHalCtx->output_fmt = *((MppFrameFormat *)param); + JpegHalCtx->set_output_fmt_flag = 1; + jpegd_dbg_hal("output_format: 0x%x\n", JpegHalCtx->output_fmt); + + if (!MPP_FRAME_FMT_IS_YUV(JpegHalCtx->output_fmt) && !MPP_FRAME_FMT_IS_RGB(JpegHalCtx->output_fmt)) { + mpp_err_f("invalid output format 0x%x\n", JpegHalCtx->output_fmt); + ret = MPP_ERR_VALUE; + } + } break; + default : + break; + } + + jpegd_dbg_func("exit ret %d\n", ret); + return ret; +} + +const MppHalApi hal_jpegd_vdpu1 = { + .name = "jpegd_vdpu1", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegdHalCtx), + .flag = 0, + .init = hal_jpegd_vdpu1_init, + .deinit = hal_jpegd_vdpu1_deinit, + .reg_gen = hal_jpegd_vdpu1_gen_regs, + .start = hal_jpegd_vdpu1_start, + .wait = hal_jpegd_vdpu1_wait, + .reset = NULL, + .flush = NULL, + .control = hal_jpegd_vdpu1_control, + .client = VPU_CLIENT_VDPU1, + .soc_type = { + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_jpegd_vdpu1) diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1.h b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1.h new file mode 100644 index 000000000..da9d4ada1 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1.h @@ -0,0 +1,24 @@ +/* + * + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAL_JPEGD_VDPU1_H +#define HAL_JPEGD_VDPU1_H + +#include "rk_type.h" + +extern const MppHalApi hal_jpegd_vdpu1; + +#endif /* HAL_JPEGD_VDPU1_H */ diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1_reg.h b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1_reg.h new file mode 100644 index 000000000..721359123 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu1_reg.h @@ -0,0 +1,613 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAL_JPEGD_VDPU1_REG_H +#define HAL_JPEGD_VDPU1_REG_H + +#include "vcodec_service.h" + +#define JPEGD_REG_NUM (101) + +#define DEC_VDPU1_LITTLE_ENDIAN (1) +#define DEC_VDPU1_BIG_ENDIAN (0) + +#define DEC_VDPU1_BUS_BURST_LENGTH_16 (16) + +#define DEC_VDPU1_SCMD_DISABLE (0) +#define DEC_VDPU1_LATENCY_COMPENSATION (0) +#define DEC_VDPU1_DATA_DISCARD_ENABLE (0) + +typedef struct { + struct { + RK_U32 sw_pp_e : 1; + RK_U32 sw_pp_pipeline_e : 1; + RK_U32 reserved3 : 2; + RK_U32 sw_pp_irq_dis : 1; + RK_U32 reserved2 : 3; + RK_U32 sw_pp_irq : 1; + RK_U32 reserved1 : 3; + RK_U32 sw_pp_rdy_int : 1; + RK_U32 sw_pp_bus_int : 1; + RK_U32 reserved0 : 18; + } reg60_interrupt; + + struct { + RK_U32 sw_pp_max_burst : 5; + RK_U32 sw_pp_out_swap32_e : 1; + RK_U32 sw_pp_out_endian : 1; + RK_U32 sw_pp_in_endian : 1; + RK_U32 sw_pp_clk_gate_e : 1; + RK_U32 sw_pp_data_disc_e : 1; + RK_U32 sw_pp_in_swap32_e : 1; + RK_U32 sw_pp_in_a1_endian : 1; + RK_U32 sw_pp_in_a1_swap32 : 1; + RK_U32 sw_pp_in_a2_endsel : 1; + RK_U32 sw_pp_scmd_dis : 1; + RK_U32 sw_pp_ahb_hlock_e : 1; + RK_U32 sw_pp_axi_wr_id : 8; + RK_U32 sw_pp_axi_rd_id : 8; + } reg61_dev_conf; + + struct { + RK_U32 sw_deint_edge_det : 15; + RK_U32 sw_deint_blend_e : 1; + RK_U32 sw_deint_threshold : 14; + RK_U32 reserved0 : 1; + RK_U32 sw_deint_e : 1; + } reg62_deinterlace; + + RK_U32 reg63_pp_in_lu_base; + RK_U32 reg64_pp_in_cb_base; + RK_U32 reg65_pp_in_cr_base; + RK_U32 reg66_pp_out_lu_base; + RK_U32 reg67_pp_out_ch_base; + + struct { + RK_U32 sw_contrast_off1 : 10; + RK_U32 sw_contrast_off2 : 10; + RK_U32 reserved0 : 4; + RK_U32 sw_contrast_thr1 : 8; + } reg68_contrast_adjust; + + struct { + RK_U32 sw_contrast_thr2 : 8; + RK_U32 sw_color_coeffa1 : 10; + RK_U32 sw_color_coeffa2 : 10; + RK_U32 sw_pp_out_cr_first : 1; + RK_U32 sw_pp_out_start_ch : 1; + RK_U32 sw_pp_in_cr_first : 1; + RK_U32 sw_pp_in_start_ch : 1; + } reg69; + + struct { + RK_U32 sw_color_coeffb : 10; + RK_U32 sw_color_coeffc : 10; + RK_U32 sw_color_coeffd : 10; + RK_U32 reserved0 : 2; + } reg70_color_coeff_0; + + struct { + RK_U32 sw_color_coeffe : 10; + RK_U32 sw_color_coefff : 8; + RK_U32 sw_rotation_mode : 3; + RK_U32 sw_crop_startx : 9; + RK_U32 reserved0 : 2; + } reg71_color_coeff_1; + + struct { + RK_U32 sw_pp_in_width : 9; + RK_U32 sw_pp_in_height : 8; + RK_U32 reserved1 : 1; + RK_U32 sw_rangemap_coef_y : 5; + RK_U32 reserved0 : 1; + RK_U32 sw_crop_starty : 8; + } reg72_crop; + + RK_U32 reg73_pp_bot_yin_base; + RK_U32 reg74_pp_bot_cin_base; + + RK_U32 reg75_reg78[4]; + + struct { + RK_U32 sw_scale_wratio : 18; + RK_U32 sw_rgb_g_padd : 5; + RK_U32 sw_rgb_r_padd : 5; + RK_U32 sw_rgb_pix_in32 : 1; + RK_U32 sw_ycbcr_range : 1; + RK_U32 sw_rangemap_c_e : 1; + RK_U32 sw_rangemap_y_e : 1; + } reg79_scaling_0; + + struct { + RK_U32 sw_scale_hratio : 18; + RK_U32 sw_rgb_b_padd : 5; + RK_U32 sw_ver_scale_mode : 2; + RK_U32 sw_hor_scale_mode : 2; + RK_U32 sw_pp_in_struct : 3; + RK_U32 sw_pp_fast_scale_e : 1; + RK_U32 reserved0 : 1; + } reg80_scaling_1; + + struct { + RK_U32 sw_wscale_invra : 16; + RK_U32 sw_hscale_invra : 16; + } reg81_scaling_2; + + RK_U32 reg82_r_mask; + RK_U32 reg83_g_mask; + RK_U32 reg84_b_mask; + + struct { + RK_U32 sw_pp_crop8_d_e : 1; + RK_U32 sw_pp_crop8_r_e : 1; + RK_U32 sw_pp_out_swap16_e : 1; + RK_U32 sw_pp_out_tiled_e : 1; + RK_U32 sw_pp_out_width : 11; + RK_U32 sw_pp_out_height : 11; + RK_U32 sw_pp_out_format : 3; + RK_U32 sw_pp_in_format : 3; + } reg85_ctrl; + + struct { + RK_U32 sw_mask1_startx : 11; + RK_U32 sw_mask1_starty : 11; + RK_U32 sw_mask1_ablend_e : 1; + RK_U32 sw_rangemap_coef_c : 5; + RK_U32 reserved0 : 1; + RK_U32 sw_pp_in_format_es : 3; + } reg86_mask_1; + + struct { + RK_U32 sw_mask2_startx : 11; + RK_U32 sw_mask2_starty : 11; + RK_U32 sw_mask2_ablend_e : 1; + RK_U32 reserved : 9; + } reg87_mask_2; + + struct { + RK_U32 sw_mask1_endx : 11; + RK_U32 sw_mask1_endy : 11; + RK_U32 sw_mask1_e : 1; + RK_U32 sw_ext_orig_width : 9; + } reg88_mask_1_size; + + struct { + RK_U32 sw_mask2_endx : 11; + RK_U32 sw_mask2_endy : 11; + RK_U32 sw_mask2_e : 1; + RK_U32 reserved0 : 9; + } reg89_mask_2_size; + + struct { + RK_U32 sw_down_cross : 11; + RK_U32 reserved1 : 4; + RK_U32 sw_up_cross : 11; + RK_U32 sw_down_cross_e : 1; + RK_U32 sw_up_cross_e : 1; + RK_U32 sw_left_cross_e : 1; + RK_U32 sw_right_cross_e : 1; + RK_U32 reserved0 : 2; + } reg90_pip_1; + + struct { + RK_U32 sw_left_cross : 11; + RK_U32 sw_right_cross : 11; + RK_U32 sw_pp_tiled_mode : 2; + RK_U32 sw_dither_select_b : 2; + RK_U32 sw_dither_select_g : 2; + RK_U32 sw_dither_select_r : 2; + } reg91_pip_2; + + struct { + RK_U32 sw_display_width : 12; + RK_U32 reserved0 : 8; + RK_U32 sw_crop_startx_ext : 3; + RK_U32 sw_crop_starty_ext : 3; + RK_U32 sw_pp_in_w_ext : 3; + RK_U32 sw_pp_in_h_ext : 3; + } reg92_display; + + RK_U32 reg93_ablend1_base; + RK_U32 reg94_ablend2_base; + RK_U32 reg95_ablend2_scanl; + + RK_U32 reg96_reg97[2]; + + struct { + RK_U32 sw_pp_out_w_ext : 1; + RK_U32 sw_pp_out_h_ext : 1; + RK_U32 reserved : 30; + } reg98_pp_out_ext; + + RK_U32 reg99_fuse; + RK_U32 reg100_synthesis; +} post_processor_reg; + +typedef struct { + struct { + RK_U32 build_version : 3; + RK_U32 product_IDen : 1; + RK_U32 minor_version : 8; + RK_U32 major_version : 4; + RK_U32 product_numer : 16; + } reg0_id; + + struct { + RK_U32 sw_dec_e : 1; + RK_U32 reserved4 : 3; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserved3 : 3; + RK_U32 sw_dec_irq : 1; + RK_U32 reserved2 : 3; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserved1 : 5; + RK_U32 sw_dec_pic_inf : 1; + RK_U32 reserved0 : 7; + } reg1_interrupt; + + struct { + RK_U32 sw_dec_max_burst : 5; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_priority_mode : 1; /* Not used */ + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_dec_out_tiled_e : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_dec_axi_rn_id : 8; + } reg2_dec_ctrl; + + struct { + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 sw_dec_ahb_hlock_e : 1; /* Not used */ + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; /* Not used */ + RK_U32 sw_skip_mode : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_dec_mode : 4; + } reg3; + + struct { + RK_U32 sw_pic_mb_h_ext : 3; + RK_U32 sw_pic_mb_w_ext : 3; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_height_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } reg4; + + /* stream decoding table selects */ + struct { + RK_U32 sw_cb_dc_vlctable3 : 1; + RK_U32 sw_cr_dc_vlctable3 : 1; + RK_U32 sw_cb_dc_vlctable : 1; + RK_U32 sw_cr_dc_vlctable : 1; + RK_U32 sw_cb_ac_vlctable : 1; + RK_U32 sw_cr_ac_vlctable : 1; + RK_U32 sw_jpeg_stream_all : 1; + RK_U32 sw_jpeg_filright_e : 1; + RK_U32 sw_jpeg_mode : 3; + RK_U32 sw_jpeg_qtables : 2; + RK_U32 reserved0 : 12; + RK_U32 sw_sync_marker_e : 1; + RK_U32 sw_strm0_start_bit : 6; + } reg5; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_init_qp : 6; + RK_U32 sw_start_code_e : 1; + } reg6_stream_info; + + struct { + RK_U32 sw_pjpeg_se : 8; + RK_U32 sw_pjpeg_ss : 8; + RK_U32 sw_pjpeg_al : 4; + RK_U32 sw_pjpeg_ah : 4; + RK_U32 sw_pjpeg_hdiv8 : 1; + RK_U32 sw_pjpeg_wdiv8 : 1; + RK_U32 sw_pjpeg_fildown_e : 1; + RK_U32 reserved0 : 5; + } reg7; + + struct { + RK_U32 sw_pjpeg_rest_freq : 16; + RK_U32 reserved0 : 16; + } reg8; + + /* Not used for JPEG */ + struct { + RK_U32 sw_stream1_len : 24; + RK_U32 sw_coeffs_part_am : 4; + RK_U32 reserved0 : 4; + } reg9; + + /* Not used for JPEG */ + RK_U32 reg10_segment_map_base; + + /* Not used for JPEG */ + struct { + RK_U32 sw_dct_start_bit_7 : 6; + RK_U32 sw_dct_start_bit_6 : 6; + RK_U32 sw_dct_start_bit_5 : 6; + RK_U32 sw_dct_start_bit_4 : 6; + RK_U32 sw_dct_start_bit_3 : 6; + RK_U32 reserved0 : 2; + } reg11; + + /* sw_rlc_vlc_base */ + RK_U32 reg12_input_stream_base; + /* sw_dec_out_base */ + RK_U32 reg13_cur_pic_base; /* Decoder output base */ + RK_U32 reg14_sw_jpg_ch_out_base; /* sw_ch_out_base */ + + struct { + RK_U32 sw_jpeg_slice_h : 8; + RK_U32 sw_roi_en : 1; + RK_U32 sw_roi_decode : 1; + RK_U32 sw_roi_out_sel : 2; + RK_U32 sw_roi_distance : 4; + RK_U32 sw_roi_sample_size : 2; + RK_U32 sw_jpegroi_in_swap32 : 1; + RK_U32 sw_jpegroi_in_endian : 1; + RK_U32 sw_jpeg_height8_flag : 1; + RK_U32 reserved0 : 11; + } reg15; + + struct { + RK_U32 sw_ac1_code1_cnt : 2; + RK_U32 reserved3 : 1; + RK_U32 sw_ac1_code2_cnt : 3; + RK_U32 reserved2 : 1; + RK_U32 sw_ac1_code3_cnt : 4; + RK_U32 sw_ac1_code4_cnt : 5; + RK_U32 sw_ac1_code5_cnt : 6; + RK_U32 reserved1 : 2; + RK_U32 sw_ac1_code6_cnt : 7; + RK_U32 reserved0 : 1; + } reg16; + + struct { + RK_U32 sw_ac1_code7_cnt : 8; + RK_U32 sw_ac1_code8_cnt : 8; + RK_U32 sw_ac1_code9_cnt : 8; + RK_U32 sw_ac1_code10_cnt : 8; + } reg17; + + struct { + RK_U32 sw_ac1_code11_cnt : 8; + RK_U32 sw_ac1_code12_cnt : 8; + RK_U32 sw_ac1_code13_cnt : 8; + RK_U32 sw_ac1_code14_cnt : 8; + } reg18; + + struct { + RK_U32 sw_ac1_code15_cnt : 8; + RK_U32 sw_ac1_code16_cnt : 8; + RK_U32 sw_ac2_code1_cnt : 2; + RK_U32 reserved1 : 1; + RK_U32 sw_ac2_code2_cnt : 3; + RK_U32 reserved0 : 1; + RK_U32 sw_ac2_code3_cnt : 4; + RK_U32 sw_ac2_code4_cnt : 5; + } reg19; + + struct { + RK_U32 sw_ac2_code5_cnt : 6; + RK_U32 reserved1 : 2; + RK_U32 sw_ac2_code6_cnt : 7; + RK_U32 reserved0 : 1; + RK_U32 sw_ac2_code7_cnt : 8; + RK_U32 sw_ac2_code8_cnt : 8; + } reg20; + + struct { + RK_U32 sw_ac2_code9_cnt : 8; + RK_U32 sw_ac2_code10_cnt : 8; + RK_U32 sw_ac2_code11_cnt : 8; + RK_U32 sw_ac2_code12_cnt : 8; + } reg21; + + struct { + RK_U32 sw_ac2_code13_cnt : 8; + RK_U32 sw_ac2_code14_cnt : 8; + RK_U32 sw_ac2_code15_cnt : 8; + RK_U32 sw_ac2_code16_cnt : 8; + } reg22; + + struct { + RK_U32 sw_dc1_code1_cnt : 2; + RK_U32 reserved1 : 2; + RK_U32 sw_dc1_code2_cnt : 3; + RK_U32 reserved0 : 1; + RK_U32 sw_dc1_code3_cnt : 4; + RK_U32 sw_dc1_code4_cnt : 4; + RK_U32 sw_dc1_code5_cnt : 4; + RK_U32 sw_dc1_code6_cnt : 4; + RK_U32 sw_dc1_code7_cnt : 4; + RK_U32 sw_dc1_code8_cnt : 4; + } reg23; + + struct { + RK_U32 sw_dc1_code9_cnt : 4; + RK_U32 sw_dc1_code10_cnt : 4; + RK_U32 sw_dc1_code11_cnt : 4; + RK_U32 sw_dc1_code12_cnt : 4; + RK_U32 sw_dc1_code13_cnt : 4; + RK_U32 sw_dc1_code14_cnt : 4; + RK_U32 sw_dc1_code15_cnt : 4; + RK_U32 sw_dc1_code16_cnt : 4; + } reg24; + + struct { + RK_U32 sw_dc2_code1_cnt : 2; + RK_U32 reserved1 : 2; + RK_U32 sw_dc2_code2_cnt : 3; + RK_U32 reserved0 : 1; + RK_U32 sw_dc2_code3_cnt : 4; + RK_U32 sw_dc2_code4_cnt : 4; + RK_U32 sw_dc2_code5_cnt : 4; + RK_U32 sw_dc2_code6_cnt : 4; + RK_U32 sw_dc2_code7_cnt : 4; + RK_U32 sw_dc2_code8_cnt : 4; + } reg25; + + struct { + RK_U32 sw_dc2_code9_cnt : 4; + RK_U32 sw_dc2_code10_cnt : 4; + RK_U32 sw_dc2_code11_cnt : 4; + RK_U32 sw_dc2_code12_cnt : 4; + RK_U32 sw_dc2_code13_cnt : 4; + RK_U32 sw_dc2_code14_cnt : 4; + RK_U32 sw_dc2_code15_cnt : 4; + RK_U32 sw_dc2_code16_cnt : 4; + } reg26; + + struct { + RK_U32 sw_dc3_code1_cnt : 2; + RK_U32 reserved1 : 2; + RK_U32 sw_dc3_code2_cnt : 3; + RK_U32 reserved0 : 1; + RK_U32 sw_dc3_code3_cnt : 4; + RK_U32 sw_dc3_code4_cnt : 4; + RK_U32 sw_dc3_code5_cnt : 4; + RK_U32 sw_dc3_code6_cnt : 4; + RK_U32 sw_dc3_code7_cnt : 4; + RK_U32 sw_dc3_code8_cnt : 4; + } reg27; + + struct { + RK_U32 sw_dc3_code9_cnt : 4; + RK_U32 sw_dc3_code10_cnt : 4; + RK_U32 sw_dc3_code11_cnt : 4; + RK_U32 sw_dc3_code12_cnt : 4; + RK_U32 sw_dc3_code13_cnt : 4; + RK_U32 sw_dc3_code14_cnt : 4; + RK_U32 sw_dc3_code15_cnt : 4; + RK_U32 sw_dc3_code16_cnt : 4; + } reg28; + + /* Not used for JPEG */ + RK_U32 reg29_reg39[11]; /* reg29 - reg39 */ + + RK_U32 reg40_qtable_base; + RK_U32 reg41_directmv_base; + RK_U32 reg42_pjpeg_dccb_base; + RK_U32 reg43_pjpeg_dccr_base; + + /* Not used for JPEG */ + RK_U32 reg44_reg50[7]; /* reg44 - reg50 */ + + /* Not used for JPEG */ + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 reserved0 : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } reg51_refpicbuf_ctrl; + + /* Not used for JPEG */ + struct { + RK_U32 sw_refbu_intra_sum : 16; + RK_U32 sw_refbu_hit_sum : 16; + } reg52_sum_inf; + + /* Not used for JPEG */ + struct { + RK_U32 sw_refbu_mv_sum : 22; + RK_U32 reserved0 : 10; + } reg53_sum_mv; + + /* Not used for JPEG */ + struct { + RK_U32 reserved0 : 17; + RK_U32 sw_dec_tiled_l : 2; /* sw_priority_mode */ + RK_U32 sw_dec_vp8snap_e : 1; + RK_U32 sw_dec_mvc_prof : 2; + RK_U32 sw_dec_avs_prof : 1; + RK_U32 sw_dec_vp8_prof : 1; + RK_U32 sw_dec_vp7_prof : 1; + RK_U32 sw_dec_rtl_rom : 1; + RK_U32 sw_dec_rv_prof : 2; + RK_U32 sw_ref_buff2_exist : 1; + RK_U32 reserved : 1; + RK_U32 sw_dec_refbu_ilace : 1; + RK_U32 sw_dec_jpeg_exten : 1; + } reg54_synthesis_cfg; + + /* Not used for JPEG */ + struct { + RK_U32 sw_apf_threshold : 14; + RK_U32 sw_refbu2_picid : 5; + RK_U32 sw_refbu2_thr : 12; + RK_U32 sw_refbu2_buf_e : 1; + } reg55; + + /* Not used for JPEG */ + struct { + RK_U32 sw_refbu_bot_sum : 16; + RK_U32 sw_refbu_top_sum : 16; + } reg56_sum_of_partitions; + + RK_U32 reg57_decoder_fuse; /* Not used */ + RK_U32 reg58_debug; + + /* Not used for JPEG */ + RK_U32 reg59_addit_ch_st_base; + post_processor_reg post; +} JpegRegSet; + +typedef struct JpegdIocRegInfo_t { + JpegRegSet regs; + + /* vepu_reg_num - vdpu_reg_num */ + RK_U32 regs_diff[164 - JPEGD_REG_NUM]; + RK_U8 extra_info[EXTRA_INFO_SIZE]; +} JpegdIocRegInfo; + +#endif diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2.c b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2.c new file mode 100644 index 000000000..7c5c4143a --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2.c @@ -0,0 +1,1057 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define MODULE_TAG "HAL_JPEG_VDPU2" + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_frame.h" +#include "mpp_common.h" + +#include "jpegd_syntax.h" +#include "hal_jpegd_common.h" +#include "hal_jpegd_vdpu2.h" +#include "hal_jpegd_vdpu2_reg.h" +#include "mpp_dec_cb_param.h" + +static MPP_RET jpegd_regs_init(JpegRegSet *reg) +{ + jpegd_dbg_func("enter\n"); + memset(reg, 0, sizeof(JpegRegSet)); + reg->reg50_dec_ctrl.sw_dec_out_tiled_e = 0; + reg->reg50_dec_ctrl.sw_dec_scmd_dis = DEC_SCMD_DISABLE; + reg->reg50_dec_ctrl.sw_dec_latency = DEC_LATENCY_COMPENSATION; + + reg->reg54_endian.sw_dec_in_endian = DEC_BIG_ENDIAN; + reg->reg54_endian.sw_dec_out_endian = DEC_LITTLE_ENDIAN; + reg->reg54_endian.sw_dec_strendian_e = DEC_LITTLE_ENDIAN; + reg->reg54_endian.sw_dec_outswap32_e = DEC_LITTLE_ENDIAN; + reg->reg54_endian.sw_dec_inswap32_e = 1; + reg->reg54_endian.sw_dec_strswap32_e = 1; + + reg->reg55_Interrupt.sw_dec_irq_dis = 0; + + reg->reg56_axi_ctrl.sw_dec_axi_rn_id = 0xff; + reg->reg56_axi_ctrl.sw_dec_axi_wr_id = 0; + reg->reg56_axi_ctrl.sw_dec_max_burst = DEC_BUS_BURST_LENGTH_16; + reg->reg56_axi_ctrl.sw_dec_data_disc_e = DEC_DATA_DISCARD_ENABLE; + + reg->reg57_enable_ctrl.sw_dec_timeout_e = 1; + reg->reg57_enable_ctrl.sw_dec_clk_gate_e = 1; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static void jpegd_write_code_word_number(JpegdHalCtx *ctx, + JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = syntax; + AcTable *ac_ptr0 = NULL, *ac_ptr1 = NULL; + DcTable *dc_ptr0 = NULL, *dc_ptr1 = NULL; + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &(info->regs); + + /* first, select the table we'll use. + * this trick is done because hardware always wants luma + * table as AC hardware table 0. + */ + if (s->ac_index[0] == HUFFMAN_TABLE_ID_ZERO) { + /* Luma's AC uses Huffman table zero */ + ac_ptr0 = &(s->ac_table[HUFFMAN_TABLE_ID_ZERO]); + ac_ptr1 = &(s->ac_table[HUFFMAN_TABLE_ID_ONE]); + } else { + ac_ptr0 = &(s->ac_table[HUFFMAN_TABLE_ID_ONE]); + ac_ptr1 = &(s->ac_table[HUFFMAN_TABLE_ID_ZERO]); + } + + /* write AC table 0 (luma) */ + reg->reg134.sw_ac1_code1_cnt = ac_ptr0->bits[0]; + reg->reg134.sw_ac1_code2_cnt = ac_ptr0->bits[1]; + reg->reg134.sw_ac1_code3_cnt = ac_ptr0->bits[2]; + reg->reg134.sw_ac1_code4_cnt = ac_ptr0->bits[3]; + reg->reg134.sw_ac1_code5_cnt = ac_ptr0->bits[4]; + reg->reg134.sw_ac1_code6_cnt = ac_ptr0->bits[5]; + + reg->reg135.sw_ac1_code7_cnt = ac_ptr0->bits[6]; + reg->reg135.sw_ac1_code8_cnt = ac_ptr0->bits[7]; + reg->reg135.sw_ac1_code9_cnt = ac_ptr0->bits[8]; + reg->reg135.sw_ac1_code10_cnt = ac_ptr0->bits[9]; + + reg->reg136.sw_ac1_code11_cnt = ac_ptr0->bits[10]; + reg->reg136.sw_ac1_code12_cnt = ac_ptr0->bits[11]; + reg->reg136.sw_ac1_code13_cnt = ac_ptr0->bits[12]; + reg->reg136.sw_ac1_code14_cnt = ac_ptr0->bits[13]; + + reg->reg137.sw_ac1_code15_cnt = ac_ptr0->bits[14]; + reg->reg137.sw_ac1_code16_cnt = ac_ptr0->bits[15]; + + /* AC table 1 (the not-luma table) */ + reg->reg137.sw_ac2_code1_cnt = ac_ptr1->bits[0]; + reg->reg137.sw_ac2_code2_cnt = ac_ptr1->bits[1]; + reg->reg137.sw_ac2_code3_cnt = ac_ptr1->bits[2]; + reg->reg137.sw_ac2_code4_cnt = ac_ptr1->bits[3]; + + reg->reg138.sw_ac2_code5_cnt = ac_ptr1->bits[4]; + reg->reg138.sw_ac2_code6_cnt = ac_ptr1->bits[5]; + reg->reg138.sw_ac2_code7_cnt = ac_ptr1->bits[6]; + reg->reg138.sw_ac2_code8_cnt = ac_ptr1->bits[7]; + + reg->reg139.sw_ac2_code9_cnt = ac_ptr1->bits[8]; + reg->reg139.sw_ac2_code10_cnt = ac_ptr1->bits[9]; + reg->reg139.sw_ac2_code11_cnt = ac_ptr1->bits[10]; + reg->reg139.sw_ac2_code12_cnt = ac_ptr1->bits[11]; + + reg->reg140.sw_ac2_code13_cnt = ac_ptr1->bits[12]; + reg->reg140.sw_ac2_code14_cnt = ac_ptr1->bits[13]; + reg->reg140.sw_ac2_code15_cnt = ac_ptr1->bits[14]; + reg->reg140.sw_ac2_code16_cnt = ac_ptr1->bits[15]; + + /* first, select the table we'll use. + * this trick is done because hardware always wants luma + * table as DC hardware table 0. + */ + if (s->dc_index[0] == HUFFMAN_TABLE_ID_ZERO) { + /* Luma's DC uses Huffman table zero */ + dc_ptr0 = &(s->dc_table[HUFFMAN_TABLE_ID_ZERO]); + dc_ptr1 = &(s->dc_table[HUFFMAN_TABLE_ID_ONE]); + } else { + dc_ptr0 = &(s->dc_table[HUFFMAN_TABLE_ID_ONE]); + dc_ptr1 = &(s->dc_table[HUFFMAN_TABLE_ID_ZERO]); + } + + /* write DC table 0 (luma) */ + reg->reg141.sw_dc1_code1_cnt = dc_ptr0->bits[0]; + reg->reg141.sw_dc1_code2_cnt = dc_ptr0->bits[1]; + reg->reg141.sw_dc1_code3_cnt = dc_ptr0->bits[2]; + reg->reg141.sw_dc1_code4_cnt = dc_ptr0->bits[3]; + reg->reg141.sw_dc1_code5_cnt = dc_ptr0->bits[4]; + reg->reg141.sw_dc1_code6_cnt = dc_ptr0->bits[5]; + reg->reg141.sw_dc1_code7_cnt = dc_ptr0->bits[6]; + reg->reg141.sw_dc1_code8_cnt = dc_ptr0->bits[7]; + + reg->reg142.sw_dc1_code9_cnt = dc_ptr0->bits[8]; + reg->reg142.sw_dc1_code10_cnt = dc_ptr0->bits[9]; + reg->reg142.sw_dc1_code11_cnt = dc_ptr0->bits[10]; + reg->reg142.sw_dc1_code12_cnt = dc_ptr0->bits[11]; + reg->reg142.sw_dc1_code13_cnt = dc_ptr0->bits[12]; + reg->reg142.sw_dc1_code14_cnt = dc_ptr0->bits[13]; + reg->reg142.sw_dc1_code15_cnt = dc_ptr0->bits[14]; + reg->reg142.sw_dc1_code16_cnt = dc_ptr0->bits[15]; + + /* DC table 1 (the not-luma table) */ + reg->reg143.sw_dc2_code1_cnt = dc_ptr1->bits[0]; + reg->reg143.sw_dc2_code2_cnt = dc_ptr1->bits[1]; + reg->reg143.sw_dc2_code3_cnt = dc_ptr1->bits[2]; + reg->reg143.sw_dc2_code4_cnt = dc_ptr1->bits[3]; + reg->reg143.sw_dc2_code5_cnt = dc_ptr1->bits[4]; + reg->reg143.sw_dc2_code6_cnt = dc_ptr1->bits[5]; + reg->reg143.sw_dc2_code7_cnt = dc_ptr1->bits[6]; + reg->reg143.sw_dc2_code8_cnt = dc_ptr1->bits[7]; + + reg->reg144.sw_dc2_code9_cnt = dc_ptr1->bits[8]; + reg->reg144.sw_dc2_code10_cnt = dc_ptr1->bits[9]; + reg->reg144.sw_dc2_code11_cnt = dc_ptr1->bits[10]; + reg->reg144.sw_dc2_code12_cnt = dc_ptr1->bits[11]; + reg->reg144.sw_dc2_code13_cnt = dc_ptr1->bits[12]; + reg->reg144.sw_dc2_code14_cnt = dc_ptr1->bits[13]; + reg->reg144.sw_dc2_code15_cnt = dc_ptr1->bits[14]; + reg->reg144.sw_dc2_code16_cnt = dc_ptr1->bits[15]; + + jpegd_dbg_func("exit\n"); + return; +} + +static void +jpegd_set_chroma_table_id(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = syntax; + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &(info->regs); + + /* this trick is done because hardware always wants + * luma table as ac hardward table 0 + */ + if (s->ac_index[0] == HUFFMAN_TABLE_ID_ZERO) { + reg->reg122.sw_cb_ac_vlctable = s->ac_index[1]; + reg->reg122.sw_cr_ac_vlctable = s->ac_index[2]; + } else { + if (s->ac_index[0] == s->ac_index[1]) + reg->reg122.sw_cb_ac_vlctable = 0; + else + reg->reg122.sw_cb_ac_vlctable = 1; + + if (s->ac_index[0] == s->ac_index[2]) + reg->reg122.sw_cr_ac_vlctable = 0; + else + reg->reg122.sw_cr_ac_vlctable = 1; + } + + if (s->dc_index[0] == HUFFMAN_TABLE_ID_ZERO) { + reg->reg122.sw_cb_dc_vlctable = s->dc_index[1]; + reg->reg122.sw_cr_dc_vlctable = s->dc_index[2]; + } else { + if (s->dc_index[0] == s->dc_index[1]) + reg->reg122.sw_cb_dc_vlctable = 0; + else + reg->reg122.sw_cb_dc_vlctable = 1; + + if (s->dc_index[0] == s->dc_index[2]) + reg->reg122.sw_cr_dc_vlctable = 0; + else + reg->reg122.sw_cr_dc_vlctable = 1; + } + + reg->reg122.sw_cr_dc_vlctable3 = 0; + reg->reg122.sw_cb_dc_vlctable3 = 0; + + jpegd_dbg_func("exit\n"); + return; +} + +static void +jpegd_set_stream_offset(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdSyntax *s = syntax; + + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &(info->regs); + RK_U32 offset = 0, byte_cnt = 0; + RK_U32 bit_pos_in_byte = 0; + RK_U32 strm_len_by_hw = 0; + /* calculate and set stream start address to hw, + * the offset must be 8-byte aligned. + */ + offset = (s->strm_offset & (~7)); + reg->reg64_rlc_vlc_base = ctx->pkt_fd; + if (offset) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 64, offset); + } + /* calculate and set stream start bit to hardware + * change current pos to bus address style + * remove three lowest bits and add the difference to bitPosInWord + * used as bit pos in word not as bit pos in byte actually... + */ + byte_cnt = ((uintptr_t) s->cur_pos & (7)); + bit_pos_in_byte = byte_cnt * 8; /* 1 Byte = 8 bits */ + reg->reg122.sw_strm_start_bit = bit_pos_in_byte; + + /* set up stream length for HW. + * length = size of original buffer - stream we already decoded in SW + */ + strm_len_by_hw = s->pkt_len - offset; + reg->reg51_stream_info.sw_stream_len = strm_len_by_hw; + reg->reg122.sw_jpeg_stream_all = 1; + + jpegd_dbg_func("exit\n"); + return; +} + +static MPP_RET jpegd_setup_pp(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &(info->regs); + JpegdSyntax *s = syntax; + + RK_U32 in_color = ctx->pp_info.pp_in_fmt; + RK_U32 out_color = ctx->pp_info.pp_out_fmt; + RK_U32 dither = ctx->pp_info.dither_enable; + RK_U32 crop_width = ctx->pp_info.crop_width; + RK_U32 crop_height = ctx->pp_info.crop_height; + RK_U32 crop_x = ctx->pp_info.crop_x; + RK_U32 crop_y = ctx->pp_info.crop_y; + RK_U32 in_width = s->hor_stride; + RK_U32 in_height = s->ver_stride; + RK_U32 out_width = s->hor_stride; + RK_U32 out_height = s->ver_stride; + RK_U32 uv_offset = s->hor_stride * s->ver_stride; + + reg->reg0.sw_pp_axi_rd_id = 0; + reg->reg0.sw_pp_axi_wr_id = 0; + reg->reg0.sw_pp_scmd_dis = 1; + reg->reg0.sw_pp_max_burst = 16; + + reg->reg18_pp_in_lu_base = 0; + reg->reg34.sw_ext_orig_width = in_width >> 4; + + reg->reg37.sw_pp_in_a2_endsel = 1; + reg->reg37.sw_pp_in_a1_swap32 = 1; + reg->reg37.sw_pp_in_a1_endian = 1; + reg->reg37.sw_pp_in_swap32_e = 1; + reg->reg37.sw_pp_in_endian = 1; + reg->reg37.sw_pp_out_endian = 1; + reg->reg37.sw_pp_out_swap32_e = 1; + + reg->reg41.sw_pp_clk_gate_e = 1; + reg->reg41.sw_pp_ahb_hlock_e = 1; + reg->reg41.sw_pp_data_disc_e = 1; + + if (crop_width <= 0) { + reg->reg34.sw_pp_in_w_ext = (((in_width / 16) & 0xE00) >> 9); + reg->reg34.sw_pp_in_width = ((in_width / 16) & 0x1FF); + reg->reg34.sw_pp_in_h_ext = (((in_height / 16) & 0x700) >> 8); + reg->reg34.sw_pp_in_height = ((in_height / 16) & 0x0FF); + } else { + reg->reg34.sw_pp_in_w_ext = (((crop_width / 16) & 0xE00) >> 9); + reg->reg34.sw_pp_in_width = ((crop_width / 16) & 0x1FF); + reg->reg34.sw_pp_in_h_ext = (((crop_height / 16) & 0x700) >> 8); + reg->reg34.sw_pp_in_height = ((crop_height / 16) & 0x0FF); + + reg->reg14.sw_crop_startx_ext = (((crop_x / 16) & 0xE00) >> 9); + reg->reg14.sw_crop_startx = ((crop_x / 16) & 0x1FF); + reg->reg14.sw_crop_starty_ext = (((crop_y / 16) & 0x700) >> 8); + reg->reg14.sw_crop_starty = ((crop_y / 16) & 0x0FF); + + if (crop_width & 0x0F) { + reg->reg14.sw_pp_crop8_r_e = 1; + } else { + reg->reg14.sw_pp_crop8_r_e = 0; + } + if (crop_height & 0x0F) { + reg->reg14.sw_pp_crop8_d_e = 1; + } else { + reg->reg14.sw_pp_crop8_d_e = 0; + } + in_width = crop_width; + in_height = crop_height; + } + + reg->reg39.sw_display_width = out_width; + reg->reg35.sw_pp_out_width = out_width; + reg->reg35.sw_pp_out_height = out_height; + + switch (in_color) { + case PP_IN_FORMAT_YUV422INTERLAVE: + case PP_IN_FORMAT_YUV420SEMI: + case PP_IN_FORMAT_YUV420PLANAR: + case PP_IN_FORMAT_YUV400: + case PP_IN_FORMAT_YUV422SEMI: + case PP_IN_FORMAT_YUV420SEMITIELED: + case PP_IN_FORMAT_YUV440SEMI: + reg->reg38.sw_pp_in_format = in_color; + break; + case PP_IN_FORMAT_YUV444_SEMI: + reg->reg38.sw_pp_in_format = 7; + reg->reg38.sw_pp_in_format_es = 0; + break; + case PP_IN_FORMAT_YUV411_SEMI: + reg->reg38.sw_pp_in_format = 0; + reg->reg38.sw_pp_in_format_es = 1; + break; + default: + mpp_err_f("unsupported format:%d", in_color); + return MPP_NOK; + } + + RK_U32 video_range = 1; + + reg->reg15.sw_rangemap_coef_y = 9; + reg->reg15.sw_rangemap_coef_c = 9; + reg->reg3.sw_pp_color_coefff = BRIGHTNESS; /* brightness */ + + if (out_color <= PP_OUT_FORMAT_ARGB) { + /*Bt.601*/ + unsigned int a = 298; + unsigned int b = 409; + unsigned int c = 208; + unsigned int d = 100; + unsigned int e = 516; + + /*Bt.709 + unsigned int a = 298; + unsigned int b = 459; + unsigned int c = 137; + unsigned int d = 55; + unsigned int e = 544;*/ + + int satur = 0, tmp; + if (video_range != 0) { + /*Bt.601*/ + a = 256; + b = 350; + c = 179; + d = 86; + e = 443; + /*Bt.709 + a = 256; + b = 403; + c = 120; + d = 48; + e = 475;*/ + + reg->reg15.sw_ycbcr_range = video_range; + } + int contrast = CONTRAST; + if (contrast != 0) { + int thr1y, thr2y, off1, off2, thr1, thr2, a1, a2; + if (video_range == 0) { + int tmp1, tmp2; + /* Contrast */ + thr1 = (219 * (contrast + 128)) / 512; + thr1y = (219 - 2 * thr1) / 2; + thr2 = 219 - thr1; + thr2y = 219 - thr1y; + + tmp1 = (thr1y * 256) / thr1; + tmp2 = ((thr2y - thr1y) * 256) / (thr2 - thr1); + off1 = ((thr1y - ((tmp2 * thr1) / 256)) * a) / 256; + off2 = ((thr2y - ((tmp1 * thr2) / 256)) * a) / 256; + + tmp1 = (64 * (contrast + 128)) / 128; + tmp2 = 256 * (128 - tmp1); + a1 = (tmp2 + off2) / thr1; + a2 = a1 + (256 * (off2 - 1)) / (thr2 - thr1); + } else { + /* Contrast */ + thr1 = (64 * (contrast + 128)) / 128; + thr1y = 128 - thr1; + thr2 = 256 - thr1; + thr2y = 256 - thr1y; + a1 = (thr1y * 256) / thr1; + a2 = ((thr2y - thr1y) * 256) / (thr2 - thr1); + off1 = thr1y - (a2 * thr1) / 256; + off2 = thr2y - (a1 * thr2) / 256; + } + + if (a1 > 1023) + a1 = 1023; + else if (a1 < 0) + a1 = 0; + + if (a2 > 1023) + a2 = 1023; + else if (a2 < 0) + a2 = 0; + + if (thr1 > 255) + thr1 = 255; + else if (thr1 < 0) + thr1 = 0; + + if (thr2 > 255) + thr2 = 255; + else if (thr2 < 0) + thr2 = 0; + + if (off1 > 511) + off1 = 511; + else if (off1 < -512) + off1 = -512; + + if (off2 > 511) + off2 = 511; + else if (off2 < -512) + off2 = -512; + + reg->reg31.sw_contrast_thr1 = thr1; + reg->reg31.sw_contrast_thr2 = thr2; + reg->reg32.sw_contrast_off1 = off1; + reg->reg32.sw_contrast_off2 = off2; + + reg->reg1.sw_color_coeffa1 = a1; + reg->reg1.sw_color_coeffa2 = a2; + } else { + reg->reg31.sw_contrast_thr1 = 55; + reg->reg31.sw_contrast_thr2 = 165; + reg->reg32.sw_contrast_off1 = 0; + reg->reg32.sw_contrast_off2 = 0; + + tmp = a; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + + reg->reg1.sw_color_coeffa1 = tmp; + reg->reg1.sw_color_coeffa2 = tmp; + } + + reg->reg37.sw_pp_out_endian = 0; + + satur = 64 + SATURATION; /* saturation */ + tmp = (satur * (int) b) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + reg->reg1.sw_color_coeffb = (unsigned int) tmp; + + tmp = (satur * (int) c) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + reg->reg2.sw_color_coeffc = (unsigned int) tmp; + + tmp = (satur * (int) d) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + reg->reg2.sw_color_coeffd = (unsigned int) tmp; + + tmp = (satur * (int) e) / 64; + if (tmp > 1023) + tmp = 1023; + else if (tmp < 0) + tmp = 0; + reg->reg2.sw_color_coeffe = (unsigned int) tmp; + } + + if (out_color <= PP_OUT_FORMAT_ARGB) { + PpRgbCfg *cfg = get_pp_rgb_Cfg(ctx->output_fmt); + reg->reg9_r_mask = cfg->r_mask; + reg->reg10_g_mask = cfg->g_mask; + reg->reg11_b_mask = cfg->b_mask; + reg->reg16.sw_rgb_r_padd = cfg->r_padd; + reg->reg16.sw_rgb_g_padd = cfg->g_padd; + reg->reg16.sw_rgb_b_padd = cfg->b_padd; + + if (dither) { + jpegd_dbg_hal("we do dither."); + reg->reg36.sw_dither_select_r = cfg->r_dither; + reg->reg36.sw_dither_select_g = cfg->g_dither; + reg->reg36.sw_dither_select_b = cfg->b_dither; + } else { + jpegd_dbg_hal("we do not dither."); + } + + reg->reg37.sw_rgb_pix_in32 = cfg->rgb_in_32; + reg->reg37.sw_pp_out_swap16_e = cfg->swap_16; + reg->reg37.sw_pp_out_swap32_e = cfg->swap_32; + reg->reg37.sw_pp_out_endian = cfg->out_endian; + + reg->reg38.sw_pp_out_format = 0; + + } else if (out_color == PP_OUT_FORMAT_YUV422INTERLAVE) { + reg->reg38.sw_pp_out_format = 3; + } else if (out_color == PP_OUT_FORMAT_YUV420INTERLAVE) { + reg->reg38.sw_pp_out_format = 5; + } else { + mpp_err_f("unsuppotred format:%d", out_color); + return -1; + } + + reg->reg38.sw_rotation_mode = 0; + + unsigned int inw, inh; + unsigned int outw, outh; + + inw = in_width - 1; + inh = in_height - 1; + outw = out_width - 1; + outh = out_height - 1; + + if (inw < outw) { + reg->reg4.sw_hor_scale_mode = 1; + reg->reg4.sw_scale_wratio = (outw << 16) / inw; + reg->reg6.sw_wscale_invra = (inw << 16) / outw; + } else if (inw > outw) { + reg->reg4.sw_hor_scale_mode = 2; + reg->reg6.sw_wscale_invra = ((outw + 1) << 16) / (inw + 1); + } else + reg->reg4.sw_hor_scale_mode = 0; + + if (inh < outh) { + reg->reg4.sw_ver_scale_mode = 1; + reg->reg5.sw_scale_hratio = (outh << 16) / inh; + reg->reg6.sw_hscale_invra = (inh << 16) / outh; + } else if (inh > outh) { + reg->reg4.sw_ver_scale_mode = 2; + reg->reg6.sw_hscale_invra = ((outh + 1) << 16) / (inh + 1) + 1; + } else + reg->reg4.sw_ver_scale_mode = 0; + + reg->reg41.sw_pp_pipeline_e = ctx->pp_info.pp_enable; + + jpegd_dbg_hal("pp_enable %d\n", ctx->pp_info.pp_enable); + + if (ctx->pp_info.pp_enable) { + reg->reg41.sw_pp_pipeline_e = 1; + reg->reg57_enable_ctrl.sw_dec_out_dis = 1; + + reg->reg63_dec_out_base = 0; + reg->reg131_jpg_ch_out_base = 0; + + reg->reg21_pp_out_lu_base = ctx->frame_fd; + reg->reg22_pp_out_ch_base = ctx->frame_fd; + + if (uv_offset) + mpp_dev_set_reg_offset(ctx->cfg->dev, 22, uv_offset); + + jpegd_dbg_hal("output_frame_fd:%x, reg22:%x", ctx->frame_fd, + reg->reg22_pp_out_ch_base); + } else { + // output without pp + reg->reg41.sw_pp_pipeline_e = 0; + reg->reg57_enable_ctrl.sw_dec_out_dis = 0; + + reg->reg21_pp_out_lu_base = 0; + reg->reg22_pp_out_ch_base = 0; + + reg->reg63_dec_out_base = ctx->frame_fd; + reg->reg131_jpg_ch_out_base = ctx->frame_fd; + + if (uv_offset) + mpp_dev_set_reg_offset(ctx->cfg->dev, 131, uv_offset); + + jpegd_dbg_hal("output_frame_fd:%x, reg131:%x", ctx->frame_fd, + reg->reg131_jpg_ch_out_base); + } + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static +MPP_RET jpegd_gen_regs(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + MPP_RET ret = MPP_OK; + jpegd_dbg_func("enter\n"); + JpegdIocRegInfo *info = (JpegdIocRegInfo *)ctx->regs; + JpegRegSet *reg = &(info->regs); + JpegdSyntax *s = syntax; + + jpegd_regs_init(reg); + + reg->reg50_dec_ctrl.sw_filtering_dis = 1; + reg->reg53_dec_mode = DEC_MODE_JPEG; + + reg->reg57_enable_ctrl.sw_dec_e = 1; /* Enable jpeg mode */ + reg->reg57_enable_ctrl.sw_pjpeg_e = 0; + reg->reg57_enable_ctrl.sw_dec_out_dis = 0; + reg->reg57_enable_ctrl.sw_rlc_mode_e = 0; + + /* frame size, round up the number of mbs */ + reg->reg120.sw_pic_mb_h_ext = ((((s->ver_stride) >> (4)) & 0x700) >> 8); + reg->reg120.sw_pic_mb_w_ext = ((((s->hor_stride) >> (4)) & 0xE00) >> 9); + reg->reg120.sw_pic_mb_width = ((s->hor_stride) >> (4)) & 0x1FF; + reg->reg120.sw_pic_mb_hight_p = ((s->ver_stride) >> (4)) & 0x0FF; + + reg->reg121.sw_pjpeg_fildown_e = s->fill_bottom; + /* Set spectral selection start coefficient */ + reg->reg121.sw_pjpeg_ss = s->scan_start; + /* Set spectral selection end coefficient */ + reg->reg121.sw_pjpeg_se = s->scan_end; + /* Set the point transform used in the preceding scan */ + reg->reg121.sw_pjpeg_ah = s->prev_shift; + /* Set the point transform value */ + reg->reg121.sw_pjpeg_al = s->point_transform; + + reg->reg122.sw_jpeg_qtables = s->qtable_cnt; + reg->reg122.sw_jpeg_mode = s->yuv_mode; + reg->reg122.sw_jpeg_filright_e = s->fill_right; + + reg->reg148.sw_slice_h = 0; + /* Set bit 21 of reg148 to 1, notifying hardware to decode jpeg + * including DRI segment + */ + reg->reg148.sw_syn_marker_e = 1; + + /* tell hardware that height is 8-pixel aligned, + * but not 16-pixel aligned + */ + if ((s->height % 16) && ((s->height % 16) <= 8) && + (!ctx->pp_info.pp_enable) && + (s->yuv_mode == JPEGDEC_YUV422 || + s->yuv_mode == JPEGDEC_YUV444 || + s->yuv_mode == JPEGDEC_YUV411)) { + reg->reg148.sw_jpeg_height8_flag = 1; + } + + /* write VLC code word number to register */ + jpegd_write_code_word_number(ctx, s); + + /* Create AC/DC/QP tables for hardware */ + jpegd_write_qp_ac_dc_table(ctx, s); + + /* Select which tables the chromas use */ + jpegd_set_chroma_table_id(ctx, s); + + /* write table base */ + reg->reg61_qtable_base = mpp_buffer_get_fd(ctx->pTableBase); + if (reg->reg61_qtable_base <= 0) { + mpp_err_f("get qtable_base failed\n"); + return MPP_NOK; + } + /* set up stream position for HW decode */ + jpegd_set_stream_offset(ctx, s); + + /* set restart interval */ + if (s->restart_interval) { + reg->reg122.sw_sync_marker_e = 1; + /* If exists DRI segment, bit 0 to bit 15 of reg123 is set + * to restart interval */ + reg->reg123.sw_pjpeg_rest_freq = s->restart_interval; + } else { + reg->reg122.sw_sync_marker_e = 0; + } + + jpegd_setup_pp(ctx, syntax); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vdpu2_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + + mpp_env_get_u32("hal_jpegd_debug", &hal_jpegd_debug, 0); + + mpp_assert(JpegHalCtx); + + jpegd_dbg_func("enter\n"); + + JpegHalCtx->cfg = cfg; + JpegHalCtx->have_pp = cfg->hw_info->cap_jpg_pp_out; + + //init regs + JpegdIocRegInfo *info = NULL; + info = mpp_calloc(JpegdIocRegInfo, 1); + if (info == NULL) { + mpp_err_f("allocate jpegd ioctl info failed\n"); + return MPP_ERR_NOMEM; + } + memset(info, 0, sizeof(JpegdIocRegInfo)); + JpegHalCtx->regs = (void *)info; + + ret = mpp_buffer_get(JpegHalCtx->cfg->buf_group, &JpegHalCtx->pTableBase, + JPEGD_BASELINE_TABLE_SIZE); + if (ret) { + mpp_err_f("get buffer failed\n"); + return ret; + } + + PPInfo *pp_info = &(JpegHalCtx->pp_info); + memset(pp_info, 0, sizeof(PPInfo)); + pp_info->pp_enable = 0; + pp_info->pp_in_fmt = PP_IN_FORMAT_YUV420SEMI; + pp_info->pp_out_fmt = PP_OUT_FORMAT_YUV420INTERLAVE; + + JpegHalCtx->output_fmt = MPP_FMT_YUV420SP; + JpegHalCtx->set_output_fmt_flag = 0; + + //init dbg stuff + JpegHalCtx->hal_debug_enable = 0; + JpegHalCtx->frame_count = 0; + JpegHalCtx->output_yuv_count = 0; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET hal_jpegd_vdpu2_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + + jpegd_dbg_func("enter\n"); + + if (JpegHalCtx->pTableBase) { + ret = mpp_buffer_put(JpegHalCtx->pTableBase); + if (ret) { + mpp_err_f("put table buffer failed\n"); + return ret; + } + } + + if (JpegHalCtx->regs) { + mpp_free(JpegHalCtx->regs); + JpegHalCtx->regs = NULL; + } + + JpegHalCtx->set_output_fmt_flag = 0; + JpegHalCtx->hal_debug_enable = 0; + JpegHalCtx->frame_count = 0; + JpegHalCtx->output_yuv_count = 0; + + jpegd_dbg_func("exit\n"); + return MPP_OK; +} + +static MPP_RET hal_jpegd_vdpu2_gen_regs(void *hal, HalTaskInfo *syn) +{ + jpegd_dbg_func("enter\n"); + if (NULL == hal || NULL == syn) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + JpegdSyntax *syntax = (JpegdSyntax *)syn->dec.syntax.data; + MppBuffer streambuf = NULL; + MppBuffer outputBuf = NULL; + + if (syn->dec.flags.parse_err) + goto RET; + + ret = jpeg_image_check_size(syntax->hor_stride, syntax->ver_stride); + if (ret) + goto RET; + + if (syn->dec.valid) { + ret = jpegd_setup_output_fmt(JpegHalCtx, syntax, syn->dec.output); + if (ret) { + mpp_err_f("setup output format %x failed\n", syntax->output_fmt); + goto RET; + } + + /* input stream address */ + mpp_buf_slot_get_prop(JpegHalCtx->cfg->packet_slots, syn->dec.input, + SLOT_BUFFER, &streambuf); + JpegHalCtx->pkt_fd = mpp_buffer_get_fd(streambuf); + if (JpegHalCtx->pkt_fd <= 0) { + mpp_err_f("get pkt_fd failed\n"); + goto RET; + } + syntax->pkt_len = jpegd_vdpu_tail_0xFF_patch(streambuf, syntax->pkt_len); + + /* output picture address */ + mpp_buf_slot_get_prop(JpegHalCtx->cfg->frame_slots, syn->dec.output, + SLOT_BUFFER, &outputBuf); + JpegHalCtx->frame_fd = mpp_buffer_get_fd(outputBuf); + if (JpegHalCtx->frame_fd <= 0) { + mpp_err_f("get frame_fd failed\n"); + goto RET; + } + + ret = jpegd_gen_regs(JpegHalCtx, syntax); + mpp_buffer_sync_end(streambuf); + mpp_buffer_sync_end(JpegHalCtx->pTableBase); + if (ret != MPP_OK) { + mpp_err_f("generate registers failed\n"); + goto RET; + } + } + + return ret; +RET: + syn->dec.valid = 0; + syn->dec.flags.parse_err = 1; + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vdpu2_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + RK_U32 *regs = (RK_U32 *)JpegHalCtx->regs; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __RETURN; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + MppDev *dev = JpegHalCtx->cfg->dev; + RK_U32 reg_size = mpp_get_ioctl_version() ? + sizeof(((JpegdIocRegInfo *)0)->regs) : + sizeof(JpegdIocRegInfo) - EXTRA_INFO_SIZE; + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto __RETURN; + } + + reg_size = sizeof(((JpegdIocRegInfo *)0)->regs); + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + goto __RETURN; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + goto __RETURN; + } + } while (0); + + jpegd_dbg_func("exit\n"); + return ret; + +__RETURN: + task->dec.flags.parse_err = 1; + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vdpu2_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + JpegRegSet *reg_out = JpegHalCtx->regs; + RK_U32 errinfo = 1; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __SKIP_HARD; + + ret = mpp_dev_ioctl(JpegHalCtx->cfg->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) { + task->dec.flags.parse_err = 1; + mpp_err_f("poll cmd failed %d\n", ret); + } + +__SKIP_HARD: + if (JpegHalCtx->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)reg_out; + if (reg_out->reg55_Interrupt.sw_dec_bus_int) { + mpp_err_f("IRQ BUS ERROR!"); + } else if (reg_out->reg55_Interrupt.sw_dec_error_int) { + mpp_err_f("IRQ STREAM ERROR!"); + } else if (reg_out->reg55_Interrupt.sw_dec_timeout) { + mpp_err_f("IRQ TIMEOUT!"); + } else if (reg_out->reg55_Interrupt.sw_dec_buffer_int) { + mpp_err_f("IRQ BUFFER EMPTY!"); + } else if (reg_out->reg55_Interrupt.sw_dec_irq) { + errinfo = 0; + jpegd_dbg_result("DECODE SUCCESS!"); + } + param.hard_err = errinfo; + mpp_callback(JpegHalCtx->cfg->dec_cb, ¶m); + } + + /* debug information */ + if (jpegd_debug & JPEGD_DBG_IO) { + static FILE *jpg_file; + static char name[64]; + MppBuffer outputBuf = NULL; + void *base = NULL; + mpp_buf_slot_get_prop(JpegHalCtx->cfg->frame_slots, task->dec.output, + SLOT_BUFFER, &outputBuf); + base = mpp_buffer_get_ptr(outputBuf); + + snprintf(name, sizeof(name) - 1, "/data/tmp/output%02d.yuv", + JpegHalCtx->output_yuv_count); + jpg_file = fopen(name, "wb+"); + if (jpg_file) { + JpegdSyntax *syntax = (JpegdSyntax *)task->dec.syntax.data; + RK_U32 width = syntax->hor_stride; + RK_U32 height = syntax->ver_stride; + + fwrite(base, width * height * 3 / 2, 1, jpg_file); + jpegd_dbg_io("frame_%02d output YUV(%d*%d) saving to %s\n", + JpegHalCtx->output_yuv_count, + width, height, name); + fclose(jpg_file); + JpegHalCtx->output_yuv_count++; + } + } + + memset(®_out->reg55_Interrupt, 0, sizeof(RK_U32)); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vdpu2_control(void *hal, MpiCmd cmd_type, + void *param) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + if (NULL == JpegHalCtx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + + switch (cmd_type) { + case MPP_DEC_SET_OUTPUT_FORMAT: { + JpegHalCtx->output_fmt = *((MppFrameFormat *)param); + JpegHalCtx->set_output_fmt_flag = 1; + jpegd_dbg_hal("output_format: 0x%x\n", JpegHalCtx->output_fmt); + + if (!MPP_FRAME_FMT_IS_YUV(JpegHalCtx->output_fmt) && !MPP_FRAME_FMT_IS_RGB(JpegHalCtx->output_fmt)) { + mpp_err_f("invalid output format 0x%x\n", JpegHalCtx->output_fmt); + ret = MPP_ERR_VALUE; + } + } break; + default : + break; + } + + jpegd_dbg_func("exit ret %d\n", ret); + return ret; +} + +const MppHalApi hal_jpegd_vdpu2 = { + .name = "jpegd_vdpu2", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegdHalCtx), + .flag = 0, + .init = hal_jpegd_vdpu2_init, + .deinit = hal_jpegd_vdpu2_deinit, + .reg_gen = hal_jpegd_vdpu2_gen_regs, + .start = hal_jpegd_vdpu2_start, + .wait = hal_jpegd_vdpu2_wait, + .reset = NULL, + .flush = NULL, + .control = hal_jpegd_vdpu2_control, + .client = VPU_CLIENT_VDPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RV1108, + ROCKCHIP_SOC_RV1109, + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_jpegd_vdpu2) diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2.h b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2.h new file mode 100644 index 000000000..bdbfdfe97 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2.h @@ -0,0 +1,23 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGD_VDPU2_H +#define HAL_JPEGD_VDPU2_H +#include "rk_type.h" + +extern const MppHalApi hal_jpegd_vdpu2; + +#endif /* HAL_JPEGD_VDPU2_H */ diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2_reg.h b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2_reg.h new file mode 100644 index 000000000..cd73da29f --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vdpu2_reg.h @@ -0,0 +1,677 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGD_VDPU2_REG_H +#define HAL_JPEGD_VDPU2_REG_H + +#include "vcodec_service.h" + +#define JPEGD_REG_NUM (159) + +#define DEC_MODE_JPEG (3) +#define DEC_LITTLE_ENDIAN (1) +#define DEC_BIG_ENDIAN (0) + +#define DEC_BUS_BURST_LENGTH_16 (16) +#define DEC_SCMD_DISABLE (0) +#define DEC_LATENCY_COMPENSATION (0) +#define DEC_DATA_DISCARD_ENABLE (0) + +typedef struct JpegRegSet { + struct { + RK_U32 sw_pp_max_burst : 5; + RK_U32 sw_pp_scmd_dis : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_pp_axi_rd_id : 8; + RK_U32 sw_pp_axi_wr_id : 8; + } reg0; + + struct { + RK_U32 sw_color_coeffa1 : 10; + RK_U32 sw_color_coeffa2 : 10; + RK_U32 sw_color_coeffb : 10; + } reg1; + + struct { + RK_U32 sw_color_coeffc : 10; + RK_U32 sw_color_coeffd : 10; + RK_U32 sw_color_coeffe : 10; + } reg2; + + struct { + RK_U32 sw_pp_color_coefff : 8; + } reg3; + + struct { + RK_U32 sw_scale_wratio : 18; + RK_U32 sw_hor_scale_mode : 2; + RK_U32 sw_ver_scale_mode : 2; + } reg4; + + struct { + RK_U32 sw_scale_hratio : 18; + } reg5; + + struct { + RK_U32 sw_wscale_invra : 16; + RK_U32 sw_hscale_invra : 16; + } reg6; + + RK_U32 reg7; + RK_U32 reg8; + RK_U32 reg9_r_mask; + RK_U32 reg10_g_mask; + RK_U32 reg11_b_mask; + RK_U32 reg12_pp_bot_yin_base; + RK_U32 reg13_pp_bot_cin_base; + + struct { + RK_U32 sw_crop_startx : 9; + RK_U32 sw_crop_starty_ext : 3; + RK_U32 sw_reserved_1 : 4; + RK_U32 sw_crop_starty : 8; + RK_U32 sw_crop_startx_ext : 3; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_pp_crop8_d_e : 1; + RK_U32 sw_pp_crop8_r_e : 1; + } reg14; + + struct { + RK_U32 sw_rangemap_coef_y : 5; + RK_U32 sw_ycbcr_range : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_rangemap_coef_c : 5; + } reg15; + + struct { + RK_U32 sw_rgb_r_padd : 5; + RK_U32 sw_reserved_1 : 3; + RK_U32 sw_rgb_g_padd : 5; + RK_U32 sw_reserved_2 : 3; + RK_U32 sw_rgb_b_padd : 5; + } reg16; + + RK_U32 reg17; + RK_U32 reg18_pp_in_lu_base; + RK_U32 reg19; + RK_U32 reg20; + RK_U32 reg21_pp_out_lu_base; + RK_U32 reg22_pp_out_ch_base; + RK_U32 reg23; + RK_U32 reg24; + RK_U32 reg25; + RK_U32 reg26; + RK_U32 reg27; + RK_U32 reg28; + RK_U32 reg29; + RK_U32 reg30; + + struct { + RK_U32 sw_contrast_thr1 : 8; + RK_U32 sw_contrast_thr2 : 8; + } reg31; + + struct { + RK_U32 sw_contrast_off1 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 sw_contrast_off2 : 10; + } reg32; + + RK_U32 reg33; + + struct { + RK_U32 sw_pp_in_width : 9; + RK_U32 sw_pp_in_w_ext : 3; + RK_U32 sw_ext_orig_width : 9; + RK_U32 sw_pp_in_height : 8; + RK_U32 sw_pp_in_h_ext : 3; + } reg34; + + struct { + RK_U32 sw_pp_out_width : 11; + RK_U32 sw_reserved_1 : 5; + RK_U32 sw_pp_out_height : 11; + } reg35; + + struct { + RK_U32 sw_dither_select_r : 2; + RK_U32 sw_dither_select_g : 2; + RK_U32 sw_dither_select_b : 2; + } reg36; + + struct { + RK_U32 sw_pp_in_endian : 1; + RK_U32 sw_pp_in_a1_endian : 1; + RK_U32 sw_pp_in_a2_endsel : 1; + RK_U32 sw_pp_out_endian : 1; + RK_U32 sw_rgb_pix_in32 : 1; + RK_U32 sw_reserved_1 : 3; + RK_U32 sw_pp_in_swap32_e : 1; + RK_U32 sw_pp_in_a1_swap32 : 1; + RK_U32 sw_pp_out_swap16_e : 1; + RK_U32 sw_pp_out_swap32_e : 1; + RK_U32 sw_reserved_2 : 4; + RK_U32 sw_pp_in_start_ch : 1; + RK_U32 sw_pp_out_start_ch : 1; + RK_U32 sw_pp_in_cr_first : 1; + RK_U32 sw_pp_out_cr_first : 1; + RK_U32 sw_reserved_3 : 4; + RK_U32 sw_pp_in_struct : 3; + } reg37; + + struct { + RK_U32 sw_rotation_mode : 3; + RK_U32 sw_reserved_1 : 5; + RK_U32 sw_pp_in_format : 3; + RK_U32 sw_pp_out_format : 3; + RK_U32 sw_reserved_2 : 2; + RK_U32 sw_pp_in_format_es : 3; + } reg38; + + struct { + RK_U32 sw_display_width : 12; + } reg39; + + RK_U32 reg40; + + struct { + RK_U32 sw_pp_e : 1; + RK_U32 sw_deint_blend_e : 1; + RK_U32 sw_deint_e : 1; + RK_U32 sw_pp_clk_gate_e : 1; + RK_U32 sw_pp_pipeline_e : 1; + RK_U32 sw_reserved_1 : 3; + RK_U32 sw_rangemap_y_e : 1; + RK_U32 sw_rangemap_c_e : 1; + RK_U32 sw_reserved_2 : 6; + RK_U32 sw_pp_data_disc_e : 1; + RK_U32 sw_reserved_3 : 3; + RK_U32 sw_mask1_e : 1; + RK_U32 sw_mask2_e : 1; + RK_U32 sw_mask1_ablend_e : 1; + RK_U32 sw_mask2_ablend_e : 1; + RK_U32 sw_up_cross_e : 1; + RK_U32 sw_down_cross_e : 1; + RK_U32 sw_left_cross_e : 1; + RK_U32 sw_right_cross_e : 1; + RK_U32 sw_pp_ahb_hlock_e : 1; + } reg41; + + RK_U32 ppReg2[8]; + struct { + RK_U32 sw_dec_out_tiled_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_skip_mode : 1; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_priority_mode : 1; + RK_U32 sw_refbu2_thr : 12; + RK_U32 sw_refbu2_picid : 5; + RK_U32 reserve1 : 2; + } reg50_dec_ctrl; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 reserve1 : 1; + RK_U32 sw_init_qp : 6; + RK_U32 reserve2 : 1; + } reg51_stream_info; + + struct { + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + RK_U32 sw_apf_threshold : 14; + RK_U32 sw_reserve : 1; + } reg52_error_concealment; + + RK_U32 reg53_dec_mode; + + struct { + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 reserve3 : 26; + } reg54_endian; + + struct { + RK_U32 sw_dec_irq : 1; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 reserve1 : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_pic_inf : 1; + RK_U32 reserve2 : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserve3 : 18; + } reg55_Interrupt; + + struct { + RK_U32 sw_dec_axi_rn_id : 8; + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 sw_dec_max_burst : 5; + RK_U32 resever : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 resever1 : 9; + } reg56_axi_ctrl; + + struct { + RK_U32 sw_dec_e : 1; + RK_U32 sw_refbu2_buf_e : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 resever : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_start_code_e : 1; + RK_U32 resever1 : 8; + RK_U32 sw_dec_ahb_hlock_e : 1; + } reg57_enable_ctrl; + + RK_U32 reg58_soft_rest; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_0_2 : 10; + RK_U32 sw_pred_bc_tap_0_1 : 10; + RK_U32 sw_pred_bc_tap_0_0 : 10; + } reg59; + + RK_U32 reg60_addit_ch_st_base; + RK_U32 reg61_qtable_base; + RK_U32 reg62_directmv_base; + RK_U32 reg63_dec_out_base; + RK_U32 reg64_rlc_vlc_base; + + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 sw_reserve : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } reg65_refpicbuf_ctrl; + + struct { + RK_U32 build_version : 3; + RK_U32 product_IDen : 1; + RK_U32 minor_version : 8; + RK_U32 major_version : 4; + RK_U32 product_numer : 16; + } reg66_id; + + struct { + RK_U32 sw_reserve : 25; + RK_U32 sw_dec_rtl_rom : 1; + RK_U32 sw_dec_rv_prof : 2; + RK_U32 sw_ref_buff2_exist : 1; + RK_U32 sw_dec_divx_prof : 1; + RK_U32 sw_dec_refbu_ilace : 1; + RK_U32 sw_dec_jpeg_exten : 1; + } reg67_synthesis_cfg; + + struct { + RK_U32 sw_refbu_top_sum : 16; + RK_U32 sw_refbu_bot_sum : 16; + } reg68_sum_of_partitions; + + struct { + RK_U32 sw_refbu_intra_sum : 16; + RK_U32 sw_refbu_hit_sum : 16; + } reg69_sum_inf; + + struct { + RK_U32 sw_refbu_mv_sum : 22; + RK_U32 sw_reserve : 10; + } reg70_sum_mv; + + RK_U32 reg71_119_reserve[49]; + + struct { + RK_U32 sw_pic_mb_h_ext : 3; + RK_U32 sw_pic_mb_w_ext : 3; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } reg120; + + struct { + RK_U32 sw_pjpeg_se : 8; + RK_U32 sw_pjpeg_ss : 8; + RK_U32 sw_pjpeg_al : 4; + RK_U32 sw_pjpeg_ah : 4; + RK_U32 sw_pjpeg_hdiv8 : 1; + RK_U32 sw_pjpeg_wdiv8 : 1; + RK_U32 sw_pjpeg_fildown_e : 1; + } reg121; + + struct { + RK_U32 sw_cb_dc_vlctable3 : 1; + RK_U32 sw_cr_dc_vlctable3 : 1; + RK_U32 sw_cb_dc_vlctable : 1; + RK_U32 sw_cr_dc_vlctable : 1; + RK_U32 sw_cb_ac_vlctable : 1; + RK_U32 sw_cr_ac_vlctable : 1; + RK_U32 sw_jpeg_stream_all : 1; + RK_U32 sw_jpeg_filright_e : 1; + RK_U32 sw_jpeg_mode : 3; + RK_U32 sw_jpeg_qtables : 2; + RK_U32 sw_reserved_1 : 12; + RK_U32 sw_sync_marker_e : 1; + RK_U32 sw_strm_start_bit : 6; + } reg122; + + struct { + RK_U32 sw_pjpeg_rest_freq : 16; + } reg123; + + struct { + RK_U32 sw_stream1_len : 24; + RK_U32 sw_coeffs_part_am : 4; + RK_U32 sw_reserved : 4; + } reg124; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_5_3 : 10; + RK_U32 sw_pred_bc_tap_5_2 : 10; + RK_U32 sw_pred_bc_tap_5_1 : 10; + } reg125; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_6_2 : 10; + RK_U32 sw_pred_bc_tap_6_1 : 10; + RK_U32 sw_pred_bc_tap_6_0 : 10; + } reg126; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_7_1 : 10; + RK_U32 sw_pred_bc_tap_7_0 : 10; + RK_U32 sw_pred_bc_tap_6_3 : 10; + } reg127; + + struct { + RK_U32 sw_pred_tap_6_4 : 2; + RK_U32 sw_pred_tap_6_M1 : 2; + RK_U32 sw_pred_tap_4_4 : 2; + RK_U32 sw_pred_tap_4_M1 : 2; + RK_U32 sw_pred_tap_2_4 : 2; + RK_U32 sw_pred_tap_2_M1 : 2; + RK_U32 sw_pred_bc_tap_7_3 : 10; + RK_U32 sw_pred_bc_tap_7_2 : 10; + } reg128; + + struct { + RK_U32 sw_filt_level_3 : 6; + RK_U32 sw_filt_level_2 : 6; + RK_U32 sw_filt_level_1 : 6; + RK_U32 sw_filt_level_0 : 6; + RK_U32 resever : 8; + } reg129; + + struct { + RK_U32 sw_quant_1 : 11; + RK_U32 sw_quant_0 : 11; + RK_U32 sw_quant_delta_1 : 5; + RK_U32 sw_quant_delta_0 : 5; + } reg130; + + + RK_U32 reg131_jpg_ch_out_base; + + struct { + RK_U32 sw_filt_mb_adj_3 : 7; + RK_U32 sw_filt_mb_adj_2 : 7; + RK_U32 sw_filt_mb_adj_1 : 7; + RK_U32 sw_filt_mb_adj_0 : 7; + RK_U32 sw_filt_sharpness : 3; + RK_U32 sw_filt_type : 1; + } reg132; + + + struct { + RK_U32 sw_filt_ref_adj_3 : 7; + RK_U32 sw_filt_ref_adj_2 : 7; + RK_U32 sw_filt_ref_adj_1 : 7; + RK_U32 sw_filt_ref_adj_0 : 7; + RK_U32 sw_reserved : 4; + } reg133; + + struct { + RK_U32 sw_ac1_code1_cnt : 2; + RK_U32 sw_reserved_1 : 1; + RK_U32 sw_ac1_code2_cnt : 3; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_ac1_code3_cnt : 4; + RK_U32 sw_ac1_code4_cnt : 5; + RK_U32 sw_ac1_code5_cnt : 6; + RK_U32 sw_reserved_3 : 2; + RK_U32 sw_ac1_code6_cnt : 7; + } reg134; + + struct { + RK_U32 sw_ac1_code7_cnt : 8; + RK_U32 sw_ac1_code8_cnt : 8; + RK_U32 sw_ac1_code9_cnt : 8; + RK_U32 sw_ac1_code10_cnt : 8; + } reg135; + + struct { + RK_U32 sw_ac1_code11_cnt : 8; + RK_U32 sw_ac1_code12_cnt : 8; + RK_U32 sw_ac1_code13_cnt : 8; + RK_U32 sw_ac1_code14_cnt : 8; + } reg136; + + struct { + RK_U32 sw_ac1_code15_cnt : 8; + RK_U32 sw_ac1_code16_cnt : 8; + RK_U32 sw_ac2_code1_cnt : 2; + RK_U32 sw_reserved_1 : 1; + RK_U32 sw_ac2_code2_cnt : 3; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_ac2_code3_cnt : 4; + RK_U32 sw_ac2_code4_cnt : 5; + } reg137; + + struct { + RK_U32 sw_ac2_code5_cnt : 6; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_ac2_code6_cnt : 7; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_ac2_code7_cnt : 8; + RK_U32 sw_ac2_code8_cnt : 8; + } reg138; + + struct { + RK_U32 sw_ac2_code9_cnt : 8; + RK_U32 sw_ac2_code10_cnt : 8; + RK_U32 sw_ac2_code11_cnt : 8; + RK_U32 sw_ac2_code12_cnt : 8; + } reg139; + + struct { + RK_U32 sw_ac2_code13_cnt : 8; + RK_U32 sw_ac2_code14_cnt : 8; + RK_U32 sw_ac2_code15_cnt : 8; + RK_U32 sw_ac2_code16_cnt : 8; + } reg140; + + struct { + RK_U32 sw_dc1_code1_cnt : 2; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_dc1_code2_cnt : 3; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_dc1_code3_cnt : 4; + RK_U32 sw_dc1_code4_cnt : 4; + RK_U32 sw_dc1_code5_cnt : 4; + RK_U32 sw_dc1_code6_cnt : 4; + RK_U32 sw_dc1_code7_cnt : 4; + RK_U32 sw_dc1_code8_cnt : 4; + } reg141; + + struct { + RK_U32 sw_dc1_code9_cnt : 4; + RK_U32 sw_dc1_code10_cnt : 4; + RK_U32 sw_dc1_code11_cnt : 4; + RK_U32 sw_dc1_code12_cnt : 4; + RK_U32 sw_dc1_code13_cnt : 4; + RK_U32 sw_dc1_code14_cnt : 4; + RK_U32 sw_dc1_code15_cnt : 4; + RK_U32 sw_dc1_code16_cnt : 4; + } reg142; + + struct { + RK_U32 sw_dc2_code1_cnt : 2; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_dc2_code2_cnt : 3; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_dc2_code3_cnt : 4; + RK_U32 sw_dc2_code4_cnt : 4; + RK_U32 sw_dc2_code5_cnt : 4; + RK_U32 sw_dc2_code6_cnt : 4; + RK_U32 sw_dc2_code7_cnt : 4; + RK_U32 sw_dc2_code8_cnt : 4; + } reg143; + + struct { + RK_U32 sw_dc2_code9_cnt : 4; + RK_U32 sw_dc2_code10_cnt : 4; + RK_U32 sw_dc2_code11_cnt : 4; + RK_U32 sw_dc2_code12_cnt : 4; + RK_U32 sw_dc2_code13_cnt : 4; + RK_U32 sw_dc2_code14_cnt : 4; + RK_U32 sw_dc2_code15_cnt : 4; + RK_U32 sw_dc2_code16_cnt : 4; + } reg144; + + RK_U32 reg145_bitpl_ctrl_base; + RK_U32 reg_dct_strm1_base[2]; + + struct { + RK_U32 sw_slice_h : 8; + RK_U32 sw_reserved_1 : 12; + RK_U32 sw_jpeg_height8_flag : 1; + RK_U32 sw_syn_marker_e : 1; + RK_U32 sw_reserved_2 : 10; + } reg148; + + RK_U32 reg149_segment_map_base; + + struct { + RK_U32 sw_dct_start_bit_7 : 6; + RK_U32 sw_dct_start_bit_6 : 6; + RK_U32 sw_dct_start_bit_5 : 6; + RK_U32 sw_dct_start_bit_4 : 6; + RK_U32 sw_dct_start_bit_3 : 6; + RK_U32 sw_reserved : 2; + } reg150; + + struct { + RK_U32 sw_quant_3 : 11; + RK_U32 sw_quant_2 : 11; + RK_U32 sw_quant_delta_3 : 5; + RK_U32 sw_quant_delta_2 : 5; + } reg151; + + struct { + RK_U32 sw_quant_5 : 11; + RK_U32 sw_quant_4 : 11; + RK_U32 sw_quant_delta_4 : 5; + RK_U32 sw_reserved : 5; + } reg152; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_1_1 : 10; + RK_U32 sw_pred_bc_tap_1_0 : 10; + RK_U32 sw_pred_bc_tap_0_3 : 10; + } reg153; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_2_0 : 10; + RK_U32 sw_pred_bc_tap_1_3 : 10; + RK_U32 sw_pred_bc_tap_1_2 : 10; + } reg154; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_2_3 : 10; + RK_U32 sw_pred_bc_tap_2_2 : 10; + RK_U32 sw_pred_bc_tap_2_1 : 10; + } reg155; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_3_2 : 10; + RK_U32 sw_pred_bc_tap_3_1 : 10; + RK_U32 sw_pred_bc_tap_3_0 : 10; + } reg156; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_4_1 : 10; + RK_U32 sw_pred_bc_tap_4_0 : 10; + RK_U32 sw_pred_bc_tap_3_3 : 10; + } reg157; + + struct { + RK_U32 resever : 2; + RK_U32 sw_pred_bc_tap_5_0 : 10; + RK_U32 sw_pred_bc_tap_4_3 : 10; + RK_U32 sw_pred_bc_tap_4_2 : 10; + } reg158; +} JpegRegSet; + +typedef struct JpegdIocRegInfo_t { + JpegRegSet regs; + + /* vepu_reg_num - vdpu_reg_num */ + RK_U32 regs_diff[184 - JPEGD_REG_NUM]; + RK_U8 extra_info[EXTRA_INFO_SIZE]; +} JpegdIocRegInfo; + +#endif /* HAL_JPEGD_VDPU2_REG_H */ diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vpu730.c b/mpp/hal/vpu/jpegd/hal_jpegd_vpu730.c new file mode 100644 index 000000000..b695d2099 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vpu730.c @@ -0,0 +1,667 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_jpegd_vpu730" + +#include "mpp_common.h" +#include "mpp_debug.h" +#include "mpp_env.h" + +#include "mpp_buffer_impl.h" +#include "mpp_dec_cb_param.h" + +#include "jpegd_syntax.h" +#include "hal_jpegd_base.h" +#include "hal_jpegd_common.h" + +#include "hal_jpegd_vpu7xx_com.h" +#include "hal_jpegd_vpu730.h" +#include "hal_jpegd_vpu730_reg.h" + +static MPP_RET hal_jpegd_vpu730_init(void *hal, MppHalCfg *cfg) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + + if (NULL == ctx) { + ctx = (JpegdHalCtx *)mpp_calloc(JpegdHalCtx, 1); + + if (NULL == ctx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + } + + mpp_env_get_u32("hal_jpegd_debug", &hal_jpegd_debug, 0); + + ctx->cfg = cfg; + /* allocate regs buffer */ + if (ctx->regs == NULL) { + ctx->regs = mpp_calloc_size(void, sizeof(JpegdVpu730Reg)); + + if (ctx->regs == NULL) { + mpp_err("hal jpegd reg alloc failed\n"); + jpegd_dbg_func("exit\n"); + return MPP_ERR_NOMEM; + } + } + + ret = mpp_buffer_get(ctx->cfg->buf_group, &ctx->pTableBase, RKD_TABLE_SIZE); + + if (ret) + mpp_err_f("Get table buffer failed, ret %d\n", ret); + + mpp_buffer_attach_dev(ctx->pTableBase, ctx->cfg->dev); + + jpegd_dbg_func("exit\n"); + + return ret; +} + +static MPP_RET hal_jpegd_vpu730_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + + jpegd_dbg_func("enter\n"); + + if (ctx->pTableBase) { + ret = mpp_buffer_put(ctx->pTableBase); + + if (ret) { + mpp_err_f("put buffer failed\n"); + return ret; + } + } + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + ctx->output_fmt = MPP_FMT_YUV420SP; + ctx->set_output_fmt_flag = 0; + ctx->hal_debug_enable = 0; + ctx->frame_count = 0; + ctx->output_yuv_count = 0; + + jpegd_dbg_func("exit\n"); + + return ret; +} + +static MPP_RET setup_output_fmt(JpegdHalCtx *ctx, JpegdSyntax *syntax, RK_S32 out_idx) +{ + + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdSyntax *s = syntax; + JpegdVpu730Reg *regs = (JpegdVpu730Reg *)ctx->regs; + RK_U32 stride = syntax->hor_stride; + MppFrame frm = NULL; + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, out_idx, SLOT_FRAME_PTR, &frm); + + if (ctx->scale) { + if (ctx->scale == 2) + regs->reg2_sys.scaledown_mode = SCALEDOWN_HALF; + if (ctx->scale == 4) + regs->reg2_sys.scaledown_mode = SCALEDOWN_QUARTER; + if (ctx->scale == 8) + regs->reg2_sys.scaledown_mode = SCALEDOWN_ONE_EIGHTS; + } else { + regs->reg2_sys.scaledown_mode = SCALEDOWN_DISABLE; + } + + mpp_frame_set_hor_stride_pixel(frm, stride); + + if (ctx->set_output_fmt_flag && (ctx->output_fmt != s->output_fmt)) { // PP enable + if (MPP_FRAME_FMT_IS_YUV(ctx->output_fmt) && s->output_fmt != MPP_FMT_YUV400) { + if (ctx->output_fmt == MPP_FMT_YUV420SP) + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_NV12; + else if (ctx->output_fmt == MPP_FMT_YUV422_YUYV) + /* Only support yuv422 and yuv444. + * Other format transformation won't report hardware irq error, + * and won't get a correct YUV image. + */ + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_YUYV; + else if (ctx->output_fmt == MPP_FMT_YUV422_YVYU) { + regs->reg2_sys.out_cbcr_swap = 1; + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_YUYV; + } else if (ctx->output_fmt == MPP_FMT_YUV420SP_VU) { + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_NV12; + regs->reg2_sys.out_cbcr_swap = 1; + } + } else if (MPP_FRAME_FMT_IS_RGB(ctx->output_fmt)) { + if (ctx->output_fmt == MPP_FMT_RGB888 || ctx->output_fmt == MPP_FMT_BGR888) { + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_RGB888; + regs->reg2_sys.bgr_sequence = (ctx->output_fmt == MPP_FMT_BGR888); + mpp_frame_set_hor_stride(frm, stride * 3); + } else if (ctx->output_fmt == MPP_FMT_BGR565 || ctx->output_fmt == MPP_FMT_RGB565) { + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_2_RGB565; + regs->reg2_sys.bgr_sequence = (ctx->output_fmt == MPP_FMT_BGR565); + mpp_frame_set_hor_stride(frm, stride * 2); + } else { + mpp_err_f("unsupported output format %d\n", ctx->output_fmt); + ret = MPP_NOK; + } + MppFrameColorRange color_range = MPP_FRAME_RANGE_UNSPECIFIED; + color_range = mpp_frame_get_color_range(frm); + + if (color_range != MPP_FRAME_RANGE_MPEG) + regs->reg2_sys.yuv2rgb_range = YUV_TO_RGB_FULL_RANGE; + else + regs->reg2_sys.yuv2rgb_range = YUV_TO_RGB_LIMIT_RANGE; + } + } else { //keep original format + regs->reg2_sys.yuv_out_format = YUV_OUT_FMT_NO_TRANS; + ctx->output_fmt = s->output_fmt; + } + + if (MPP_FRAME_FMT_IS_TILE(ctx->output_fmt)) + regs->reg2_sys.dec_out_sequence = OUTPUT_TILE; + else + regs->reg2_sys.dec_out_sequence = OUTPUT_RASTER; + + jpegd_dbg_hal("convert format %d to format %d\n", s->output_fmt, ctx->output_fmt); + + if ((s->yuv_mode == YUV_MODE_420 && regs->reg2_sys.yuv_out_format == YUV_OUT_FMT_NO_TRANS) || + (regs->reg2_sys.yuv_out_format == YUV_OUT_FMT_2_NV12)) + regs->reg2_sys.fill_down_e = 1; + else + regs->reg2_sys.fill_down_e = s->fill_bottom; + regs->reg2_sys.fill_right_e = s->fill_right; + + mpp_frame_set_fmt(frm, ctx->output_fmt); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET jpegd_gen_regs(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdSyntax *s = syntax; + JpegdVpu730Reg *regs = (JpegdVpu730Reg *)ctx->regs; + + regs->reg66_int_en.dec_done_int_en = 1; + regs->reg66_int_en.safe_reset_int_en = 1; + regs->reg66_int_en.bus_error_int_en = 1; + regs->reg66_int_en.timeout_int_en = 1; + regs->reg66_int_en.buffer_empty_int_en = 1; + + regs->reg67_int_mask.dec_done_int_mask = 1; + regs->reg67_int_mask.safe_reset_int_mask = 1; + regs->reg67_int_mask.bus_error_int_mask = 1; + regs->reg67_int_mask.timeout_int_mask = 1; + regs->reg67_int_mask.buffer_empty_int_mask = 1; + + regs->reg3_pic_size.pic_width_m1 = s->width - 1; + regs->reg3_pic_size.pic_height_m1 = s->height - 1; + + if (s->sample_precision != DCT_SAMPLE_PRECISION_8 || s->qtbl_entry > TBL_ENTRY_3) + return MPP_NOK; + + regs->reg4_pic_fmt.pixel_depth = BIT_DEPTH_8; + if (s->nb_components == 1) { + regs->reg4_pic_fmt.htables_sel = TBL_ENTRY_1; + } + + if (s->nb_components > 1) { + regs->reg4_pic_fmt.qtables_sel = (s->qtbl_entry > 1) ? TBL_ENTRY_3 : TBL_ENTRY_2; + regs->reg4_pic_fmt.htables_sel = (s->htbl_entry > 0x0f) ? TBL_ENTRY_3 : TBL_ENTRY_2; + } else { + regs->reg4_pic_fmt.qtables_sel = TBL_ENTRY_1; + regs->reg4_pic_fmt.htables_sel = TBL_ENTRY_1; + } + + if (s->restart_interval) { + regs->reg4_pic_fmt.dri_e = RST_ENABLE; + regs->reg4_pic_fmt.dri_mcu_num_m1 = s->restart_interval - 1; + } + + switch (s->yuv_mode) { + case JPEGDEC_YUV400: + case JPEGDEC_YUV420: + case JPEGDEC_YUV422: + regs->reg4_pic_fmt.jpeg_mode = s->yuv_mode; + break; + case JPEGDEC_YUV411: + regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_411; + break; + case JPEGDEC_YUV440: + regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_440; + break; + case JPEGDEC_YUV444: + regs->reg4_pic_fmt.jpeg_mode = YUV_MODE_444; + break; + default: + mpp_err_f("unsupported yuv mode %d\n", s->yuv_mode); + break; + } + + RK_U32 out_width = MPP_ALIGN(s->width, 16); + RK_U32 out_height = s->height; + out_width = out_width >> regs->reg2_sys.scaledown_mode; + out_width = MPP_ALIGN(out_width, 16); + out_height = regs->reg2_sys.fill_down_e ? MPP_ALIGN(out_height, 16) : MPP_ALIGN(out_height, 8); + out_height = out_height >> regs->reg2_sys.scaledown_mode; + jpegd_dbg_hal("output scale %d, width %d, height %d\n", regs->reg2_sys.scaledown_mode, out_width, out_height); + + RK_U32 y_hor_stride = out_width >> 4; + RK_U32 y_virstride = 0; + RK_U32 uv_hor_virstride = 0; + + switch (regs->reg2_sys.yuv_out_format) { + case YUV_OUT_FMT_2_RGB888: + y_hor_stride *= 3; + break; + case YUV_OUT_FMT_2_RGB565: + case YUV_OUT_FMT_2_YUYV: + y_hor_stride *= 2; + break; + case YUV_OUT_FMT_NO_TRANS: + switch (regs->reg4_pic_fmt.jpeg_mode) { + case YUV_MODE_440: + case YUV_MODE_444: + uv_hor_virstride = y_hor_stride * 2; + break; + case YUV_MODE_411: + uv_hor_virstride = y_hor_stride >> 1; + break; + case YUV_MODE_400: + uv_hor_virstride = 0; + break; + default: + uv_hor_virstride = y_hor_stride; + break; + } + break; + case YUV_OUT_FMT_2_NV12: + uv_hor_virstride = y_hor_stride; + break; + } + + y_virstride = y_hor_stride * out_height; + if (regs->reg2_sys.dec_out_sequence == OUTPUT_TILE) { + // The new JPEG decoder supports tile 4x4 output by default. + if (mpp_get_soc_type() >= ROCKCHIP_SOC_RK3576) { + switch (regs->reg2_sys.yuv_out_format) { + case YUV_OUT_FMT_2_YUYV: + y_hor_stride = y_hor_stride * 4 * 2; + break; + case YUV_OUT_FMT_NO_TRANS: + switch (regs->reg4_pic_fmt.jpeg_mode) { + case YUV_MODE_422: + case YUV_MODE_440: + y_hor_stride = y_hor_stride * 4 * 2; + break; + case YUV_MODE_444: + y_hor_stride = y_hor_stride * 4 * 3; + break; + case YUV_MODE_411: + case YUV_MODE_420: + y_hor_stride = y_hor_stride * 4 * 3 / 2; + break; + case YUV_MODE_400: + y_hor_stride = y_hor_stride * 4; + break; + default: + return MPP_NOK; + break; + } + break; + case YUV_OUT_FMT_2_NV12: + y_hor_stride = y_hor_stride * 4 * 3 / 2; + break; + } + + uv_hor_virstride = 0; + } else { + y_hor_stride <<= 3; + uv_hor_virstride <<= 3; + } + } + + regs->reg5_hor_virstride.y_hor_virstride = y_hor_stride & 0xffff; + regs->reg5_hor_virstride.uv_hor_virstride = uv_hor_virstride & 0xffff; + regs->reg6_y_virstride.y_virstride = y_virstride; + + regs->reg7_tbl_len.y_hor_virstride_h = (y_hor_stride >> 16) & 1; + + if (s->qtable_cnt) + regs->reg7_tbl_len.qtbl_len = regs->reg4_pic_fmt.qtables_sel * 8 - 1; + else + regs->reg7_tbl_len.qtbl_len = 0; + + // 8 bit precision 12, 12 bit precision 16; + regs->reg7_tbl_len.htbl_value_len = regs->reg4_pic_fmt.htables_sel * (regs->reg4_pic_fmt.pixel_depth ? 16 : 12) - 1; + + switch (regs->reg4_pic_fmt.htables_sel) { + case TBL_ENTRY_0 : + regs->reg7_tbl_len.htbl_mincode_len = 0; + regs->reg7_tbl_len.htbl_value_len = 0; + break; + case TBL_ENTRY_2 : + regs->reg7_tbl_len.htbl_mincode_len = (s->nb_components - 1) * 6 - 1; + break; + case TBL_ENTRY_1 : + case TBL_ENTRY_3 : + regs->reg7_tbl_len.htbl_mincode_len = s->nb_components * 6 - 1; + break; + default : + mpp_err_f("unsupported htable_sel %d\n", regs->reg4_pic_fmt.htables_sel); + break; + } + + RK_U32 strm_offset = 0; + RK_U32 hw_strm_offset = 0; + RK_U8 start_byte = 0; + RK_U32 table_fd = mpp_buffer_get_fd(ctx->pTableBase); + + if (table_fd <= 0) { + mpp_err_f("get table_fd failed\n"); + return MPP_NOK; + } + + strm_offset = s->strm_offset; + hw_strm_offset = strm_offset - strm_offset % 16; + start_byte = strm_offset % 16; + + regs->reg8_strm_len.stream_len = (MPP_ALIGN((s->pkt_len - hw_strm_offset), 16) - 1) >> 4; + regs->reg8_strm_len.strm_start_byte = start_byte; + + regs->reg9_qtbl_base = table_fd; + regs->reg10_htbl_mincode_base = table_fd; + regs->reg11_htbl_value_base = table_fd; + regs->reg13_dec_out_base = ctx->frame_fd; + regs->reg12_strm_base = ctx->pkt_fd; + + mpp_dev_set_reg_offset(ctx->cfg->dev, 12, hw_strm_offset); + mpp_dev_set_reg_offset(ctx->cfg->dev, 10, RKD_HUFFMAN_MINCODE_TBL_OFFSET); + mpp_dev_set_reg_offset(ctx->cfg->dev, 11, RKD_HUFFMAN_VALUE_TBL_OFFSET); + + regs->reg14_strm_error.error_prc_mode = 1; + regs->reg14_strm_error.strm_ffff_err_mode = 2; + regs->reg14_strm_error.strm_other_mark_mode = 2; + regs->reg14_strm_error.strm_dri_seq_err_mode = 0; + + regs->reg16_clk_gate.val = 0xff; + + regs->reg30_perf_latency_ctrl0.axi_perf_work_e = 1; + regs->reg30_perf_latency_ctrl0.axi_perf_clr_e = 1; + regs->reg30_perf_latency_ctrl0.axi_cnt_type = 1; + regs->reg30_perf_latency_ctrl0.rd_latency_id = 0xa; + + jpegd_vpu7xx_write_htbl(ctx, s); + + jpegd_vpu7xx_write_qtbl(ctx, s); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vpu730_gen_regs(void *hal, HalTaskInfo *syn) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + JpegdSyntax *s = (JpegdSyntax *)syn->dec.syntax.data; + + MppBuffer strm_buf = NULL; + MppBuffer output_buf = NULL; + + if (syn->dec.flags.parse_err) + goto __RETURN; + + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, syn->dec.input, SLOT_BUFFER, & strm_buf); + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, syn->dec.output, SLOT_BUFFER, &output_buf); + + ctx->pkt_fd = mpp_buffer_get_fd(strm_buf); + if (ctx->pkt_fd <= 0) { + mpp_err_f("get pkt_fd failed\n"); + goto __RETURN; + } + + ctx->frame_fd = mpp_buffer_get_fd(output_buf); + if (ctx->frame_fd <= 0) { + mpp_err_f("get frame_fd failed\n"); + goto __RETURN; + } + + memset(ctx->regs, 0, sizeof(JpegdVpu730Reg)); + + setup_output_fmt(ctx, s, syn->dec.output); + + ret = jpegd_gen_regs(ctx, s); + mpp_buffer_sync_end(strm_buf); + mpp_buffer_sync_end(ctx->pTableBase); + + if (ret != MPP_OK) { + mpp_err_f("generate registers failed\n"); + goto __RETURN; + } + + syn->dec.valid = 1; + jpegd_dbg_func("exit\n"); + return ret; + +__RETURN: + syn->dec.flags.parse_err = 1; + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vpu730_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx * ctx = (JpegdHalCtx *)hal; + MppDev dev = ctx->cfg->dev; + RK_U32 *regs = (RK_U32 *)ctx->regs; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __RETURN; + + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = JPEGD_VPU730_REG_NUM * sizeof(RK_U32); + RK_U8 i = 0; + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + if (jpegd_debug & JPEGD_DBG_HAL_INFO) { + for (i = 0; i < JPEGD_VPU730_REG_NUM; i++) { + mpp_log_f("send reg[%d]=0x%08x\n", i, regs[i]); + } + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + goto __RETURN; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + goto __RETURN; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + goto __RETURN; + } + + jpegd_dbg_func("exit\n"); + return ret; + +__RETURN: + task->dec.flags.parse_err = 1; + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vpu730_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + JpegdHalCtx *ctx = (JpegdHalCtx *)hal; + MppDev dev = ctx->cfg->dev; + JpegdVpu730Reg *reg_out = ctx->regs; + RK_U32 errinfo = 0; + RK_U8 i = 0; + + jpegd_dbg_func("enter\n"); + if (task->dec.flags.parse_err) + goto __SKIP_HARD; + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + + if (ret) { + task->dec.flags.parse_err = 1; + mpp_err_f("poll cmd failed %d\n", ret); + } + +__SKIP_HARD: + if (ctx->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)reg_out; + if (!reg_out->reg69_int_sta.dec_done_int_sta || reg_out->reg69_int_sta.bus_error_int_sta + || reg_out->reg69_int_sta.dec_error_int_sta || reg_out->reg69_int_sta.timeout_int_sta + || reg_out->reg69_int_sta.buffer_empty_int_sta) { + mpp_err("decode result: failed, irq 0x%08x\n", ((RK_U32 *)reg_out)[1]); + errinfo = 1; + } + param.hard_err = errinfo; + mpp_callback(ctx->cfg->dec_cb, ¶m); + } + if (jpegd_debug & JPEGD_DBG_HAL_INFO) { + for (i = 0; i < JPEGD_VPU730_REG_NUM; i++) { + mpp_log_f("read regs[%d]=0x%08x\n", i, ((RK_U32*)reg_out)[i]); + } + } + + jpegd_dbg_hal("decode one frame in cycles: %d\n", reg_out->reg39_perf_working_cnt); + + if (jpegd_debug & JPEGD_DBG_IO) { + FILE *jpg_file; + char name[32]; + MppBuffer outputBuf = NULL; + void *base = NULL; + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, task->dec.output, SLOT_BUFFER, &outputBuf); + base = mpp_buffer_get_ptr(outputBuf); + + snprintf(name, sizeof(name) - 1, "/data/tmp/output%02d.yuv", ctx->output_yuv_count); + jpg_file = fopen(name, "wb+"); + if (jpg_file) { + JpegdSyntax *s = (JpegdSyntax *) task->dec.syntax.data; + RK_U32 width = s->hor_stride; + RK_U32 height = s->ver_stride; + + fwrite(base, width * height * 3, 1, jpg_file); + jpegd_dbg_io("frame_%02d output YUV(%d*%d) saving to %s\n", ctx->output_yuv_count, + width, height, name); + fclose(jpg_file); + ctx->output_yuv_count++; + } + } + + memset(®_out->reg69_int_sta, 0, sizeof(RK_U32)); + + jpegd_dbg_func("exit\n"); + return ret; +} + +static MPP_RET hal_jpegd_vpu730_control(void *hal, MpiCmd cmd_type, void *param) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdHalCtx *JpegHalCtx = (JpegdHalCtx *)hal; + + if (NULL == JpegHalCtx) { + mpp_err_f("NULL pointer"); + return MPP_ERR_NULL_PTR; + } + + switch (cmd_type) { + case MPP_DEC_SET_OUTPUT_FORMAT: { + MppFrameFormat output_fmt = *((MppFrameFormat *)param); + RockchipSocType soc_type = mpp_get_soc_type(); + + if (MPP_FRAME_FMT_IS_FBC(output_fmt)) { + ret = MPP_ERR_VALUE; + } + + if (MPP_FRAME_FMT_IS_TILE(output_fmt)) { + if (soc_type < ROCKCHIP_SOC_RK3576 || MPP_FRAME_FMT_IS_RGB(output_fmt)) { + ret = MPP_ERR_VALUE; + } + } + + if (MPP_FRAME_FMT_IS_RGB(output_fmt)) { + if (soc_type == ROCKCHIP_SOC_RK3572) { + ret = MPP_ERR_VALUE; + } else if (soc_type == ROCKCHIP_SOC_RK3538 || soc_type == ROCKCHIP_SOC_RK3539) { + if (output_fmt != MPP_FMT_BGR888 && output_fmt != MPP_FMT_RGB888 && + output_fmt != MPP_FMT_RGB565 && output_fmt != MPP_FMT_BGR565) { + ret = MPP_ERR_VALUE; + } + } + } + + if (ret) { + mpp_err_f("invalid output format 0x%x\n", output_fmt); + } else { + JpegHalCtx->output_fmt = output_fmt; + JpegHalCtx->set_output_fmt_flag = 1; + jpegd_dbg_hal("output_format: 0x%x\n", JpegHalCtx->output_fmt); + } + } break; + default : + break; + } + + jpegd_dbg_func("exit ret %d\n", ret); + return ret; +} + +const MppHalApi hal_jpegd_vpu730 = { + .name = "jpegd_vpu730", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(JpegdHalCtx), + .flag = 0, + .init = hal_jpegd_vpu730_init, + .deinit = hal_jpegd_vpu730_deinit, + .reg_gen = hal_jpegd_vpu730_gen_regs, + .start = hal_jpegd_vpu730_start, + .wait = hal_jpegd_vpu730_wait, + .reset = NULL, + .flush = NULL, + .control = hal_jpegd_vpu730_control, + .client = VPU_CLIENT_JPEG_DEC, + .soc_type = { + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_jpegd_vpu730) \ No newline at end of file diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vpu730.h b/mpp/hal/vpu/jpegd/hal_jpegd_vpu730.h new file mode 100644 index 000000000..8509eeb53 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vpu730.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_JPEGD_VPU730_H +#define HAL_JPEGD_VPU730_H + +#include "rk_type.h" + +#include "mpp_hal.h" + +extern const MppHalApi hal_jpegd_vpu730; + +#endif /* HAL_JPEGD_VPU730_H */ \ No newline at end of file diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vpu730_reg.h b/mpp/hal/vpu/jpegd/hal_jpegd_vpu730_reg.h new file mode 100644 index 000000000..5a80e5e63 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vpu730_reg.h @@ -0,0 +1,344 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_JPEGD_VPU730_REG_H +#define HAL_JPEGD_VPU730_REG_H + +#include "rk_type.h" + +#define JPEGD_VPU730_REG_NUM 70 + +typedef struct { + struct { + rk_u32 minor_ver : 8; + rk_u32 bit_depth : 1; + rk_u32 : 7; + rk_u32 prod_num : 16; + } reg0_id; + + struct { + rk_u32 ltb_cfg_num : 8; + rk_u32 cmd : 6; + rk_u32 : 18; + } reg1_cmd; + + struct { + rk_u32 in_endian : 1; + rk_u32 in_swap32_e : 1; + rk_u32 in_swap64_e : 1; + rk_u32 str_endian : 1; + rk_u32 str_swap32_e : 1; + rk_u32 str_swap64_e : 1; + rk_u32 out_endian : 1; + rk_u32 out_swap32_e : 1; + rk_u32 out_swap64_e : 1; + rk_u32 out_cbcr_swap : 1; + rk_u32 out_byte_swap : 1; + rk_u32 care_strm_error_e : 1; + rk_u32 scaledown_mode : 2; + rk_u32 : 4; + rk_u32 wait_reset_e : 1; + rk_u32 buf_empty_force_end_flag : 1; + rk_u32 fbc_e : 1; + rk_u32 allow_16x8_cp_flag : 1; + rk_u32 fbc_force_uncompress : 1; + rk_u32 bgr_sequence : 1; + rk_u32 fill_down_e : 1; + rk_u32 fill_right_e : 1; + rk_u32 dec_out_sequence : 1; + rk_u32 yuv_out_format : 3; + rk_u32 yuv2rgb_rec : 1; + rk_u32 yuv2rgb_range : 1; + } reg2_sys; + + struct { + rk_u32 pic_width_m1 : 16; + rk_u32 pic_height_m1 : 16; + } reg3_pic_size; + + struct { + rk_u32 jpeg_mode : 3; + rk_u32 : 1; + rk_u32 pixel_depth : 3; + rk_u32 : 1; + rk_u32 qtables_sel : 2; + rk_u32 : 2; + rk_u32 htables_sel : 2; + rk_u32 : 1; + rk_u32 dri_e : 1; + rk_u32 dri_mcu_num_m1 : 16; + } reg4_pic_fmt; + + struct { + rk_u32 y_hor_virstride : 16; + rk_u32 uv_hor_virstride : 16; + } reg5_hor_virstride; + + struct { + rk_u32 : 4; + rk_u32 y_virstride : 28; + } reg6_y_virstride; + + struct { + rk_u32 qtbl_len : 5; + rk_u32 : 3; + rk_u32 htbl_mincode_len : 5; + rk_u32 : 3; + rk_u32 htbl_value_len : 6; + rk_u32 : 2; + rk_u32 y_hor_virstride_h : 1; + rk_u32 : 7; + } reg7_tbl_len; + + struct { + rk_u32 strm_start_byte : 4; + rk_u32 stream_len : 28; + } reg8_strm_len; + + rk_u32 reg9_qtbl_base; + rk_u32 reg10_htbl_mincode_base; + rk_u32 reg11_htbl_value_base; + rk_u32 reg12_strm_base; + rk_u32 reg13_dec_out_base; + + struct { + rk_u32 error_prc_mode : 1; + rk_u32 strm_r0_err_mode : 2; + rk_u32 strm_r1_err_mode : 2; + rk_u32 strm_ffff_err_mode : 2; + rk_u32 strm_other_mark_mode : 2; + rk_u32 strm_dri_seq_err_mode : 1; + rk_u32 : 6; + rk_u32 hfm_force_stop : 5; + rk_u32 : 11; + } reg14_strm_error; + + struct { + rk_u32 strm_r0_marker : 8; + rk_u32 strm_r0_mask : 8; + rk_u32 strm_r1_marker : 8; + rk_u32 strm_r1_mask : 8; + } reg15_strm_mask; + + union { + struct { + rk_u32 dec_clk_gate_e : 1; + rk_u32 dec_strm_gate_e : 1; + rk_u32 dec_huffman_gate_e : 1; + rk_u32 dec_izq_gate_e : 1; + rk_u32 dec_idct_gate_e : 1; + rk_u32 busifd_gate_e : 1; + rk_u32 post_prs_gate_e : 1; + rk_u32 dec_sram_gate_e : 1; + rk_u32 : 24; + }; + rk_u32 val; + } reg16_clk_gate; + + struct { + rk_u32 perf_cnt0_sel : 4; + rk_u32 : 4; + rk_u32 perf_cnt1_sel : 4; + rk_u32 : 4; + rk_u32 perf_cnt2_sel : 4; + rk_u32 : 11; + rk_u32 perf_cnt_e : 1; + } reg17_perf_cnt_sel; + + rk_u32 reg18_perf_cnt0; + rk_u32 reg19_perf_cnt1; + rk_u32 reg20_perf_cnt2; + + struct { + rk_u32 low_delay_output : 17; + rk_u32 : 15; + } reg21_low_delay_output; + + struct { + rk_u32 watchdog : 32; + } reg22_watchdog; + + rk_u32 reg23_28[6]; + + struct { + rk_u32 st_low_delay_output : 16; + rk_u32 : 1; + rk_u32 buwrmaster_frame_rdy : 1; + rk_u32 : 14; + } reg29_st_low_delay_output; + + struct { + rk_u32 axi_perf_work_e : 1; + rk_u32 axi_perf_clr_e : 1; + rk_u32 axi_frm_type : 1; + rk_u32 axi_cnt_type : 1; + rk_u32 rd_latency_id : 4; + rk_u32 rd_latency_thr : 12; + rk_u32 : 12; + } reg30_perf_latency_ctrl0; + + struct { + rk_u32 addr_align_type : 2; + rk_u32 ar_cnt_id_type : 1; + rk_u32 aw_cnt_id_type : 1; + rk_u32 ar_count_id : 4; + rk_u32 aw_count_id : 4; + rk_u32 rd_band_width_mode : 1; + rk_u32 : 19; + } reg30_perf_latency_ctrl1; + + struct { + rk_u32 mcu_pos_x : 16; + rk_u32 mcu_pos_y : 16; + } reg32_dbg_mcu_pos; + + struct { + rk_u32 stream_dri_seq_err_sta : 1; + rk_u32 stream_r0_err_sta : 1; + rk_u32 stream_r1_err_sta : 1; + rk_u32 stream_ffff_err_sta : 1; + rk_u32 stream_other_mark_err_sta : 1; + rk_u32 : 3; + rk_u32 huffman_mcu_cnt_l : 1; + rk_u32 huffman_mcu_cnt_m : 1; + rk_u32 huffman_eoi_without_end : 1; + rk_u32 huffman_end_without_eoi : 1; + rk_u32 huffman_overflow : 1; + rk_u32 huffman_buf_empty : 1; + rk_u32 : 2; + rk_u32 first_error_idx : 4; + rk_u32 : 12; + } reg33_dbg_error_info; + + struct { + RK_U32 rd_max_latency_num_ch0 : 16; + RK_U32 : 16; + } reg34_perf_rd_max_latency_num0; + + rk_u32 reg35_perf_rd_latency_samp_num; + rk_u32 reg36_perf_rd_latency_acc_sum; + rk_u32 reg37_perf_rd_axi_total_byte; + rk_u32 reg38_perf_wr_axi_total_byte; + rk_u32 reg39_perf_working_cnt; + + struct { + rk_u32 bus_status_flag : 19; + rk_u32 : 13; + } reg40_dbg_bus_sta; + + struct { + rk_u32 work_status_flag : 18; + rk_u32 : 14; + } reg41_dbg_work_sta; + + struct { + rk_u32 dec_state : 8; + rk_u32 ltb_mode : 14; + } reg42_dbg_sta; + + struct { + rk_u32 ltb_total_num : 8; + rk_u32 ltb_decoded_num : 8; + rk_u32 ltb_done_int_num : 8; + rk_u32 ltb_loaded_num : 8; + } reg43_st_link_num; + + struct { + rk_u32 ltb_core_id : 4; + rk_u32 ltb_stop_flag : 1; + rk_u32 ltb_node_int : 1; + rk_u32 ltb_task_id : 12; + } reg44_st_link_info; + + struct { + rk_u32 ltb_rd_addr_next : 32; + } reg45_st_link_rd_addr_next; + + struct { + rk_u32 ltb_wr_addr_next : 32; + } reg46_st_link_wr_addr; + + rk_u32 reg47_63[17]; + + struct { + rk_u32 ltb_start_addr : 32; + } reg64_ltb_start_addr; + + struct { + rk_u32 core_id : 4; + rk_u32 ltb_task_error_stop_int_en : 1; + rk_u32 ltb_task_node_stop_int_en : 1; + } reg65_link_mode; + + struct { + rk_u32 dec_done_int_en : 1; + rk_u32 safe_reset_int_en : 1; + rk_u32 bus_error_int_en : 1; + rk_u32 dec_error_int_en : 1; + rk_u32 timeout_int_en : 1; + rk_u32 buffer_empty_int_en : 1; + rk_u32 low_delay_out_int_en : 1; + rk_u32 ltb_operation_error_int_en : 1; + rk_u32 ltb_node_done_int_en : 1; + rk_u32 ltb_force_stop_int_en : 1; + rk_u32 ltb_node_stop_int_en : 1; + rk_u32 ltb_error_stop_int_en : 1; + rk_u32 ltb_data_error_int_en : 1; + rk_u32 : 19; + } reg66_int_en; + + struct { + rk_u32 dec_done_int_mask : 1; + rk_u32 safe_reset_int_mask : 1; + rk_u32 bus_error_int_mask : 1; + rk_u32 dec_error_int_mask : 1; + rk_u32 timeout_int_mask : 1; + rk_u32 buffer_empty_int_mask : 1; + rk_u32 low_delay_out_int_mask : 1; + rk_u32 ltb_operation_error_int_mask : 1; + rk_u32 ltb_node_done_int_mask : 1; + rk_u32 ltb_force_stop_int_mask : 1; + rk_u32 ltb_node_stop_int_mask : 1; + rk_u32 ltb_error_stop_int_mask : 1; + rk_u32 ltb_data_error_int_mask : 1; + rk_u32 : 19; + } reg67_int_mask; + + struct { + rk_u32 dec_done_int_clear : 1; + rk_u32 safe_reset_int_clear : 1; + rk_u32 bus_error_int_clear : 1; + rk_u32 dec_error_int_clear : 1; + rk_u32 timeout_int_clear : 1; + rk_u32 buffer_empty_int_clear : 1; + rk_u32 low_delay_out_int_clear : 1; + rk_u32 ltb_operation_error_int_clear : 1; + rk_u32 ltb_node_done_int_clear : 1; + rk_u32 ltb_force_stop_int_clear : 1; + rk_u32 ltb_node_stop_int_clear : 1; + rk_u32 ltb_error_stop_int_clear : 1; + rk_u32 ltb_data_error_int_clear : 1; + rk_u32 : 19; + } reg68_int_clear; + + struct { + rk_u32 dec_done_int_sta : 1; + rk_u32 safe_reset_int_sta : 1; + rk_u32 bus_error_int_sta : 1; + rk_u32 dec_error_int_sta : 1; + rk_u32 timeout_int_sta : 1; + rk_u32 buffer_empty_int_sta : 1; + rk_u32 low_delay_out_int_sta : 1; + rk_u32 ltb_operation_error_int_sta : 1; + rk_u32 ltb_node_done_int_sta : 1; + rk_u32 ltb_force_stop_int_sta : 1; + rk_u32 ltb_node_stop_int_sta : 1; + rk_u32 ltb_error_stop_int_sta : 1; + rk_u32 ltb_data_error_int_sta : 1; + rk_u32 : 19; + } reg69_int_sta; +} JpegdVpu730Reg; + +#endif /* HAL_JPEGD_VPU730_REG_H */ \ No newline at end of file diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vpu7xx_com.c b/mpp/hal/vpu/jpegd/hal_jpegd_vpu7xx_com.c new file mode 100644 index 000000000..2d25dd9fb --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vpu7xx_com.c @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "hal_jpegd_vpu7xx_com.h" + +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "jpegd_syntax.h" +#include "hal_jpegd_common.h" + +MPP_RET jpegd_vpu7xx_write_qtbl(JpegdHalCtx *ctx, JpegdSyntax *syntax) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + JpegdSyntax *s = syntax; + RK_U16 *base = (RK_U16 *)mpp_buffer_get_ptr(ctx->pTableBase); + RK_U16 table_tmp[QUANTIZE_TABLE_LENGTH] = {0}; + RK_U32 i, j , idx; + + for (j = 0; j < s->nb_components; j++) { + idx = s->quant_index[j]; + + //turn zig-zag order to raster-scan order + for (i = 0; i < QUANTIZE_TABLE_LENGTH; i++) { + table_tmp[zzOrder[i]] = s->quant_matrixes[idx][i]; + } + + memcpy(base + j * QUANTIZE_TABLE_LENGTH, table_tmp, sizeof(RK_U16) * QUANTIZE_TABLE_LENGTH); + } + + if (jpegd_debug & JPEGD_DBG_HAL_TBL) { + RK_U8 *data = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase); + + mpp_log("--------------Quant tbl----------------------\n"); + for (i = 0; i < RKD_QUANTIZATION_TBL_SIZE; i += 8) { + mpp_log("%02x%02x%02x%02x%02x%02x%02x%02x\n", + data[i + 7], data[i + 6], data[i + 5], data[i + 4], + data[i + 3], data[i + 2], data[i + 1], data[i + 0]); + } + } + + jpegd_dbg_func("exit\n"); + return ret; + +} + +MPP_RET jpegd_vpu7xx_write_htbl(JpegdHalCtx *ctx, JpegdSyntax *jpegd_syntax) +{ + jpegd_dbg_func("enter\n"); + MPP_RET ret = MPP_OK; + + JpegdSyntax *s = jpegd_syntax; + void * htbl_ptr[6] = {NULL}; + RK_U32 i, j, k = 0; + RK_U8 *p_htbl_value = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_VALUE_TBL_OFFSET; + RK_U16 *p_htbl_mincode = (RK_U16 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_MINCODE_TBL_OFFSET / 2; + RK_U16 min_code_ac[16] = {0}; + RK_U16 min_code_dc[16] = {0}; + RK_U16 acc_addr_ac[16] = {0}; + RK_U16 acc_addr_dc[16] = {0}; + RK_U8 htbl_value[192] = {0}; + RK_U16 code = 0; + RK_S32 addr = 0; + RK_U32 len = 0; + AcTable *ac_ptr; + DcTable *dc_ptr; + + htbl_ptr[0] = &s->dc_table[s->dc_index[0]]; + htbl_ptr[1] = &s->ac_table[s->ac_index[0]]; + + htbl_ptr[2] = &s->dc_table[s->dc_index[1]]; + htbl_ptr[3] = &s->ac_table[s->ac_index[1]]; + + htbl_ptr[4] = htbl_ptr[2]; + htbl_ptr[5] = htbl_ptr[3]; + + for (k = 0; k < s->nb_components; k++) { + dc_ptr = (DcTable *)htbl_ptr[k * 2]; + ac_ptr = (AcTable *)htbl_ptr[k * 2 + 1]; + + len = dc_ptr->bits[0]; + code = addr = 0; + min_code_dc[0] = 0; + acc_addr_dc[0] = 0; + + for (j = 0; j < 16; j++) { + len = dc_ptr->bits[j]; + + if (len == 0 && j > 0) { + if (code > (min_code_dc[j - 1] << 1)) + min_code_dc[j] = code; + else + min_code_dc[j] = min_code_dc[j - 1] << 1; + } else { + min_code_dc[j] = code; + } + + code += len; + addr += len; + acc_addr_dc[j] = addr; + code <<= 1; + + } + + if (dc_ptr->bits[15]) + min_code_dc[0] = min_code_dc[15] + dc_ptr->bits[15] - 1; + else + min_code_dc[0] = min_code_dc[15]; + + len = ac_ptr->bits[0]; + code = addr = 0; + min_code_ac[0] = 0; + acc_addr_ac[0] = 0; + for (j = 0; j < 16; j++) { + len = ac_ptr->bits[j]; + + if (len == 0 && j > 0) { + if (code > (min_code_ac[j - 1] << 1)) + min_code_ac[j] = code; + else + min_code_ac[j] = min_code_ac[j - 1] << 1; + } else { + min_code_ac[j] = code; + } + + code += len; + addr += len; + acc_addr_ac[j] = addr; + code <<= 1; + } + + if (ac_ptr->bits[15]) + min_code_ac[0] = min_code_ac[15] + ac_ptr->bits[15] - 1; + else + min_code_ac[0] = min_code_ac[15]; + + for (i = 0; i < 16; i++) { + *p_htbl_mincode++ = min_code_dc[i]; + } + + for (i = 0; i < 8; i++) { + *p_htbl_mincode++ = acc_addr_dc[2 * i] | acc_addr_dc[2 * i + 1] << 8; + } + + for (i = 0; i < 16; i++) { + *p_htbl_mincode++ = min_code_ac[i]; + } + + for (i = 0; i < 8; i++) { + *p_htbl_mincode++ = acc_addr_ac[2 * i] | acc_addr_ac[2 * i + 1] << 8; + } + + for (i = 0; i < MAX_DC_HUFFMAN_TABLE_LENGTH; i++) { + htbl_value[i] = dc_ptr->vals[i]; + } + + for (i = 0; i < MAX_AC_HUFFMAN_TABLE_LENGTH; i++) { + htbl_value[i + 16] = ac_ptr->vals[i]; + } + + for (i = 0; i < 12 * 16; i++) { + *p_htbl_value++ = htbl_value[i]; + } + } + + if (jpegd_debug & JPEGD_DBG_HAL_TBL) { + RK_U8 *data = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_VALUE_TBL_OFFSET; + + mpp_log("--------------huffman value tbl----------------------\n"); + for (i = 0; i < RKD_HUFFMAN_VALUE_TBL_SIZE; i += 8) { + mpp_log("%02x%02x%02x%02x%02x%02x%02x%02x\n", + data[i + 7], data[i + 6], data[i + 5], data[i + 4], + data[i + 3], data[i + 2], data[i + 1], data[i + 0]); + } + + data = NULL; + data = (RK_U8 *)mpp_buffer_get_ptr(ctx->pTableBase) + RKD_HUFFMAN_MINCODE_TBL_OFFSET; + + mpp_log("--------------huffman mincode tbl----------------------\n"); + for (i = 0; i < RKD_HUFFMAN_MINCODE_TBL_SIZE; i += 8) { + mpp_log("%02x%02x%02x%02x%02x%02x%02x%02x\n", + data[i + 7], data[i + 6], data[i + 5], data[i + 4], + data[i + 3], data[i + 2], data[i + 1], data[i + 0]); + } + } + + jpegd_dbg_func("exit\n"); + return ret; +} \ No newline at end of file diff --git a/mpp/hal/vpu/jpegd/hal_jpegd_vpu7xx_com.h b/mpp/hal/vpu/jpegd/hal_jpegd_vpu7xx_com.h new file mode 100644 index 000000000..eae2b1252 --- /dev/null +++ b/mpp/hal/vpu/jpegd/hal_jpegd_vpu7xx_com.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_JPEGD_VPU7xx_COM_H +#define HAL_JPEGD_VPU7xx_COM_H + +#include "jpegd_syntax.h" +#include "hal_jpegd_base.h" + +#define RKV_JPEGD_LITTLE_ENDIAN (0) +#define RKV_JPEGD_BIG_ENDIAN (1) + +#define SCALEDOWN_DISABLE (0) +#define SCALEDOWN_HALF (1) +#define SCALEDOWN_QUARTER (2) +#define SCALEDOWN_ONE_EIGHTS (3) + +#define OUTPUT_RASTER (0) +#define OUTPUT_TILE (1) + +#define TIMEOUT_MODE_CYCLE_24 (0) +#define TIMEOUT_MODE_CYCLE_18 (1) + +#define OUT_SEQUENCE_RASTER (0) +#define OUT_SEQUENCE_TILE (1) + +#define YUV_TO_RGB_REC_BT601 (0) +#define YUV_TO_RGB_REC_BT709 (1) + +#define YUV_TO_RGB_FULL_RANGE (1) +#define YUV_TO_RGB_LIMIT_RANGE (0) + +#define YUV_OUT_FMT_NO_TRANS (0) +#define YUV_OUT_FMT_2_RGB888 (1) +#define YUV_OUT_FMT_2_RGB565 (2) +// Not support YUV400 transmit to NV12 +#define YUV_OUT_FMT_2_NV12 (3) +// Only support YUV422 or YUV444, YUV444 should scaledown uv +#define YUV_OUT_FMT_2_YUYV (4) + +#define YUV_MODE_400 (0) +#define YUV_MODE_411 (1) +#define YUV_MODE_420 (2) +#define YUV_MODE_422 (3) +#define YUV_MODE_440 (4) +#define YUV_MODE_444 (5) + +#define BIT_DEPTH_8 (0) +#define BIT_DEPTH_12 (1) + +// No quantization/huffman table or table is the same as previous +#define TBL_ENTRY_0 (0) +// Grayscale picture with only 1 quantization/huffman table +#define TBL_ENTRY_1 (1) +// Common case, one table for luma, one for chroma +#define TBL_ENTRY_2 (2) +// 3 table entries, one for luma, one for cb, one for cr +#define TBL_ENTRY_3 (3) + +// Restart interval marker disable +#define RST_DISABLE (0) +// Restart interval marker enable +#define RST_ENABLE (1) + +// Support 8-bit precision only +#define NB_COMPONENTS (3) +#define RKD_QUANTIZATION_TBL_SIZE (8*8*2*NB_COMPONENTS) +#define RKD_HUFFMAN_MINCODE_TBL_SIZE (16*3*2*NB_COMPONENTS) +#define RKD_HUFFMAN_VALUE_TBL_SIZE (16*12*NB_COMPONENTS) +#define RKD_HUFFMAN_MINCODE_TBL_OFFSET (RKD_QUANTIZATION_TBL_SIZE) +#define RKD_HUFFMAN_VALUE_TBL_OFFSET (RKD_HUFFMAN_MINCODE_TBL_OFFSET + MPP_ALIGN(RKD_HUFFMAN_MINCODE_TBL_SIZE, 64)) +#define RKD_TABLE_SIZE (RKD_HUFFMAN_VALUE_TBL_OFFSET + RKD_HUFFMAN_VALUE_TBL_SIZE) + +MPP_RET jpegd_vpu7xx_write_qtbl(JpegdHalCtx *ctx, JpegdSyntax *syntax); +MPP_RET jpegd_vpu7xx_write_htbl(JpegdHalCtx *ctx, JpegdSyntax *jpegd_syntax); + +#endif /* HAL_JPEGD_VPU7xx_COM_H */ \ No newline at end of file diff --git a/mpp/hal/vpu/jpege/CMakeLists.txt b/mpp/hal/vpu/jpege/CMakeLists.txt new file mode 100644 index 000000000..73b6b3f1a --- /dev/null +++ b/mpp/hal/vpu/jpege/CMakeLists.txt @@ -0,0 +1,13 @@ +# vim: syntax=cmake +include_directories(../common/) +include_directories(../../common/jpeg/) + +set(HAL_JPEGE_SRC) + +add_hal_source(HAL_JPEGE_SRC HAVE_VEPU1 hal_jpege_vepu1_v2.c) +add_hal_source(HAL_JPEGE_SRC HAVE_VEPU2 hal_jpege_vepu2_v2.c) + +if (HAL_JPEGE_SRC) + list(APPEND HAL_JPEGE_SRC hal_jpege_base.c) + add_library(hal_jpege_vpu OBJECT ${HAL_JPEGE_SRC}) +endif() \ No newline at end of file diff --git a/mpp/hal/vpu/jpege/hal_jpege_base.c b/mpp/hal/vpu/jpege/hal_jpege_base.c new file mode 100644 index 000000000..c7adac918 --- /dev/null +++ b/mpp/hal/vpu/jpege/hal_jpege_base.c @@ -0,0 +1,68 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_jpege_base" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "hal_jpege_debug.h" +#include "hal_jpege_base.h" + +const RK_U32 qp_reorder_table[64] = { + 0, 8, 16, 24, 1, 9, 17, 25, 32, 40, 48, 56, 33, 41, 49, 57, + 2, 10, 18, 26, 3, 11, 19, 27, 34, 42, 50, 58, 35, 43, 51, 59, + 4, 12, 20, 28, 5, 13, 21, 29, 36, 44, 52, 60, 37, 45, 53, 61, + 6, 14, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + +const RK_U16 jpege_restart_marker[8] = { + 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, + 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, +}; + +void get_msb_lsb_at_pos(RK_U32 *msb, RK_U32 *lsb, RK_U8 *buf, RK_U32 bytepos) +{ + RK_U32 val32; + RK_S32 left_byte = bytepos & 0x7; + RK_U8 *tmp = buf + (bytepos & (~0x7)); + + // clear the rest bytes in 64bit + if (left_byte) { + RK_U32 i; + + for (i = left_byte; i < 8; i++) + tmp[i] = 0; + } + + val32 = (tmp[0] << 24) | + (tmp[1] << 16) | + (tmp[2] << 8) | + (tmp[3] << 0); + + *msb = val32; + + if (left_byte > 4) { + val32 = (tmp[4] << 24) | + (tmp[5] << 16) | + (tmp[6] << 8); + } else + val32 = 0; + + *lsb = val32; +} diff --git a/mpp/hal/vpu/jpege/hal_jpege_base.h b/mpp/hal/vpu/jpege/hal_jpege_base.h new file mode 100644 index 000000000..f2da82d9c --- /dev/null +++ b/mpp/hal/vpu/jpege/hal_jpege_base.h @@ -0,0 +1,75 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGE_BASE_H +#define HAL_JPEGE_BASE_H + +#include "mpp_device.h" +#include "hal_enc_task.h" + +#include "vepu_common.h" + +#include "jpege_syntax.h" +#include "hal_jpege_hdr.h" + +typedef struct hal_jpege_ctx_s { + MppDev dev; + MppClientType type; + + JpegeBits bits; + /* NOTE: regs should reserve space for extra_info */ + void *regs; + void *regs_out; + RK_U32 reg_size; + RK_S32 task_cnt; + RK_S32 task_idx; + + MppEncCfgSet *cfg; + JpegeSyntax syntax; + JpegeFeedback feedback; + + /* For part encode mode */ + RK_U32 mcu_h; + RK_U32 mcu_y; + RK_U8 *base; + size_t size; + RK_U32 sw_bit; + RK_U32 part_bytepos; + RK_U32 part_x_fill; + RK_U32 part_y_fill; + RK_U32 rst_marker_idx; + + HalJpegeRc hal_rc; + RK_S32 hal_start_pos; + VepuStrideCfg stride_cfg; + + void *ctx_ext; +} HalJpegeCtx; + +extern const RK_U32 qp_reorder_table[QUANTIZE_TABLE_SIZE]; +extern const RK_U16 jpege_restart_marker[8]; + +#ifdef __cplusplus +extern "C" { +#endif + +void get_msb_lsb_at_pos(RK_U32 *msb, RK_U32 *lsb, RK_U8 *buf, RK_U32 bytepos); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_JPEGE_BASE_H */ diff --git a/mpp/hal/vpu/jpege/hal_jpege_vepu1_v2.c b/mpp/hal/vpu/jpege/hal_jpege_vepu1_v2.c new file mode 100644 index 000000000..f6ba31049 --- /dev/null +++ b/mpp/hal/vpu/jpege/hal_jpege_vepu1_v2.c @@ -0,0 +1,637 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_jpege_vepu1" + +#include + +#include "mpp_env.h" +#include "mpp_common.h" +#include "mpp_mem.h" +#include "mpp_platform.h" + +#include "mpp_enc_hal.h" +#include "vcodec_service.h" + +#include "hal_jpege_debug.h" +#include "hal_jpege_base.h" + +#define VEPU_JPEGE_VEPU1_NUM_REGS 164 + +typedef struct jpege_vepu1_reg_set_t { + RK_U32 val[VEPU_JPEGE_VEPU1_NUM_REGS]; +} jpege_vepu1_reg_set; + +static MPP_RET hal_jpege_vepu1_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + + mpp_env_get_u32("hal_jpege_debug", &hal_jpege_debug, 0); + hal_jpege_dbg_func("enter hal %p cfg %p\n", hal, cfg); + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_VEPU1; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + ctx->dev = cfg->dev; + + jpege_bits_init(&ctx->bits); + mpp_assert(ctx->bits); + + ctx->cfg = cfg->cfg; + ctx->reg_size = sizeof(RK_U32) * VEPU_JPEGE_VEPU1_NUM_REGS; + ctx->regs = mpp_calloc_size(void, ctx->reg_size + EXTRA_INFO_SIZE); + if (NULL == ctx->regs) { + mpp_err_f("failed to malloc vepu1 regs\n"); + return MPP_NOK; + } + + ctx->regs_out = mpp_calloc_size(void, ctx->reg_size + EXTRA_INFO_SIZE); + if (NULL == ctx->regs_out) { + mpp_err_f("failed to malloc vepu2 regs\n"); + return MPP_NOK; + } + + hal_jpege_rc_init(&ctx->hal_rc); + hal_jpege_dbg_func("leave hal %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu1_deinit(void *hal) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + if (ctx->bits) { + jpege_bits_deinit(ctx->bits); + ctx->bits = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->regs_out); + hal_jpege_dbg_func("leave hal %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu1_get_task(void *hal, HalEncTask *task) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + JpegeSyntax *syntax = (JpegeSyntax *)task->syntax.data; + hal_jpege_dbg_func("enter hal %p\n", hal); + + memcpy(&ctx->syntax, syntax, sizeof(ctx->syntax)); + + ctx->hal_start_pos = mpp_packet_get_length(task->packet); + + /* prepare for part encoding */ + ctx->mcu_y = 0; + ctx->mcu_h = syntax->mcu_ver_cnt; + ctx->sw_bit = 0; + ctx->part_bytepos = 0; + ctx->part_x_fill = 0; + ctx->part_y_fill = 0; + task->part_first = 1; + task->part_last = 0; + + if (ctx->cfg->jpeg.update) { + hal_jpege_rc_update(&ctx->hal_rc, syntax); + ctx->cfg->jpeg.update = 0; + } + + task->rc_task->frm.is_intra = 1; + + hal_jpege_dbg_func("leave hal %p\n", hal); + + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu1_set_extra_info(MppDev dev, JpegeSyntax *syntax, + RK_U32 start_mbrow) +{ + MppFrameFormat fmt = syntax->format; + RK_U32 hor_stride = syntax->hor_stride; + RK_U32 ver_stride = syntax->ver_stride; + RK_U32 offset = 0; + + switch (fmt) { + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420P : { + if (start_mbrow) { + offset = 16 * start_mbrow * hor_stride; + + mpp_dev_set_reg_offset(dev, 11, offset); + } + + offset = hor_stride * ver_stride + hor_stride * start_mbrow * 16 / 2; + if (fmt == MPP_FMT_YUV420P) + offset = hor_stride * start_mbrow * 16 / 4 + hor_stride * ver_stride; + + mpp_dev_set_reg_offset(dev, 12, offset); + + if (fmt == MPP_FMT_YUV420P) + offset = hor_stride * start_mbrow * 16 / 4 + hor_stride * ver_stride * 5 / 4; + + mpp_dev_set_reg_offset(dev, 13, offset); + } break; + default : { + if (start_mbrow) { + offset = start_mbrow * hor_stride; + + mpp_dev_set_reg_offset(dev, 11, offset); + } + } break; + } + + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu1_gen_regs(void *hal, HalEncTask *task) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + MppBuffer input = task->input; + MppBuffer output = task->output; + JpegeSyntax *syntax = &ctx->syntax; + RK_U32 width = syntax->width; + RK_U32 width_align = MPP_ALIGN(width, 16); + RK_U32 height = syntax->height; + MppFrameFormat fmt = syntax->format; + RK_U32 hor_stride = 0; + RK_U32 ver_stride = MPP_ALIGN(height, 16); + JpegeBits bits = ctx->bits; + RK_U32 *regs = (RK_U32 *)ctx->regs; + size_t length = mpp_packet_get_length(task->packet); + RK_U8 *buf = mpp_buffer_get_ptr(output); + size_t size = mpp_buffer_get_size(output); + RK_S32 bitpos; + RK_S32 bytepos; + RK_U32 x_fill = 0; + RK_U32 y_fill = 0; + VepuFormatCfg fmt_cfg; + RK_U32 rotation = 0; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + // do not support mirroring + if (syntax->mirroring) + mpp_err_f("Warning: do not support mirroring\n"); + + if (syntax->rotation == MPP_ENC_ROT_90) + rotation = 1; + else if (syntax->rotation == MPP_ENC_ROT_270) + rotation = 2; + else if (syntax->rotation != MPP_ENC_ROT_0) + mpp_err_f("Warning: only support 90 or 270 degree rotate, request rotate %d", syntax->rotation); + if (rotation) { + MPP_SWAP(RK_U32, width, height); + MPP_SWAP(RK_U32, width_align, ver_stride); + } + + hor_stride = get_vepu_pixel_stride(&ctx->stride_cfg, width, + syntax->hor_stride, fmt); + + //hor_stride must be align with 8, and ver_stride mus align with 2 + if ((hor_stride & 0x7) || (ver_stride & 0x1) || (hor_stride >= (1 << 15))) { + mpp_err_f("illegal resolution, hor_stride %d, ver_stride %d, width %d, height %d\n", + syntax->hor_stride, syntax->ver_stride, + syntax->width, syntax->height); + } + + x_fill = (width_align - width) / 4; + y_fill = (ver_stride - height); + mpp_assert(x_fill <= 3); + mpp_assert(y_fill <= 15); + ctx->part_x_fill = x_fill; + ctx->part_y_fill = y_fill; + + mpp_buffer_sync_begin(output); + + if (syntax->q_mode == JPEG_QFACTOR) { + syntax->q_factor = 100 - task->rc_task->info.quality_target; + hal_jpege_rc_update(&ctx->hal_rc, syntax); + } + /* write header to output buffer */ + jpege_bits_setup(bits, buf, (RK_U32)size); + /* seek length bytes data */ + jpege_seek_bits(bits, length << 3); + /* NOTE: write header will update qtable */ + write_jpeg_header(bits, syntax, &ctx->hal_rc); + + memset(regs, 0, sizeof(RK_U32) * VEPU_JPEGE_VEPU1_NUM_REGS); + regs[11] = mpp_buffer_get_fd(input); + regs[12] = mpp_buffer_get_fd(input); + regs[13] = regs[12]; + + bitpos = jpege_bits_get_bitpos(bits); + bytepos = (bitpos + 7) >> 3; + ctx->base = buf; + ctx->size = size; + ctx->sw_bit = bitpos; + ctx->part_bytepos = bytepos; + + get_msb_lsb_at_pos(®s[22], ®s[23], buf, bytepos); + + mpp_buffer_sync_end(output); + + if (!get_vepu_fmt(&fmt_cfg, fmt)) { + RK_U32 deflt_cfg = ((0 & (255)) << 24) | + ((0 & (255)) << 16) | + ((1 & (1)) << 15) | + ((16 & (63)) << 8) | + ((0 & (1)) << 6) | + ((0 & (1)) << 5) | + ((1 & (1)) << 4) | + ((1 & (1)) << 3) | + ((1 & (1)) << 1); + + regs[2] = deflt_cfg | (fmt_cfg.swap_8_in & 1) | + (fmt_cfg.swap_32_in & 1) << 2 | + (fmt_cfg.swap_16_in & 1) << 14; + } + + regs[5] = mpp_buffer_get_fd(output); + if (bytepos) + mpp_dev_set_reg_offset(ctx->dev, 5, bytepos); + + regs[14] = (1 << 31) | + (0 << 30) | + (0 << 29) | + ((width_align >> 4) << 19) | + ((ver_stride >> 4) << 10) | + (1 << 3) | (2 << 1); + + regs[15] = (0 << 29) | + (0 << 26) | + (hor_stride << 12) | + (x_fill << 10) | + (y_fill << 6) | + (fmt_cfg.format << 2) | rotation; + + regs[24] = size - bytepos; + + regs[37] = ((bytepos & 7) * 8) << 23; + + { + RK_U32 coeffA; + RK_U32 coeffB; + RK_U32 coeffC; + RK_U32 coeffE; + RK_U32 coeffF; + + switch (syntax->color_conversion_type) { + case 0 : { /* BT.601 */ + /* + * Y = 0.2989 R + 0.5866 G + 0.1145 B + * Cb = 0.5647 (B - Y) + 128 + * Cr = 0.7132 (R - Y) + 128 + */ + coeffA = 19589; + coeffB = 38443; + coeffC = 7504; + coeffE = 37008; + coeffF = 46740; + } break; + case 1 : { /* BT.709 */ + /* + * Y = 0.2126 R + 0.7152 G + 0.0722 B + * Cb = 0.5389 (B - Y) + 128 + * Cr = 0.6350 (R - Y) + 128 + */ + coeffA = 13933; + coeffB = 46871; + coeffC = 4732; + coeffE = 35317; + coeffF = 41615; + } break; + case 2 : { + coeffA = syntax->coeffA; + coeffB = syntax->coeffB; + coeffC = syntax->coeffC; + coeffE = syntax->coeffE; + coeffF = syntax->coeffF; + } break; + default : { + mpp_err("invalid color conversion type %d\n", + syntax->color_conversion_type); + coeffA = 19589; + coeffB = 38443; + coeffC = 7504; + coeffE = 37008; + coeffF = 46740; + } break; + } + + regs[53] = coeffA | (coeffB << 16); + regs[54] = coeffC | (coeffE << 16); + regs[55] = ((fmt_cfg.b_mask & 0x1f) << 26) | + ((fmt_cfg.g_mask & 0x1f) << 21) | + ((fmt_cfg.r_mask & 0x1f) << 16) | coeffF; + } + + regs[20] = ((syntax->part_rows & 0xff) << 16) | jpege_restart_marker[0]; + + regs[14] |= 0x001; + + { + RK_S32 i; + + for (i = 0; i < 16; i++) { + /* qtable need to reorder in particular order */ + regs[i + 64] = ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 0]] << 24 | + ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 1]] << 16 | + ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 2]] << 8 | + ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 3]]; + } + for (i = 0; i < 16; i++) { + /* qtable need to reorder in particular order */ + regs[i + 80] = ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 0]] << 24 | + ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 1]] << 16 | + ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 2]] << 8 | + ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 3]]; + } + } + + hal_jpege_dbg_func("leave hal %p\n", hal); + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu1_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + hal_jpege_vepu1_set_extra_info(ctx->dev, &ctx->syntax, 0); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = ctx->reg_size; + + wr_cfg.reg = ctx->regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ctx->regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_jpege_dbg_func("leave hal %p\n", hal); + (void)task; + return ret; +} + +static MPP_RET hal_jpege_vepu1_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + JpegeBits bits = ctx->bits; + RK_U32 *regs = (RK_U32 *)ctx->regs; + JpegeFeedback *feedback = &ctx->feedback; + RK_U32 val; + RK_U32 sw_bit = 0; + RK_U32 hw_bit = 0; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + if (ctx->dev) { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + val = regs[1]; + hal_jpege_dbg_output("hw_status %08x\n", val); + feedback->hw_status = val & 0x70; + val = regs[24]; + + sw_bit = jpege_bits_get_bitpos(bits); + hw_bit = val; + + // NOTE: hardware will return 64 bit access byte count + feedback->stream_length = ((sw_bit / 8) & (~0x7)) + hw_bit / 8; + task->length = feedback->stream_length; + task->hw_length = task->length - ctx->hal_start_pos; + hal_jpege_dbg_output("stream bit: sw %d hw %d total %d hw_length %d\n", + sw_bit, hw_bit, feedback->stream_length, task->hw_length); + + hal_jpege_dbg_func("leave hal %p\n", hal); + return ret; +} + +static MPP_RET hal_jpege_vepu1_part_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + JpegeSyntax *syntax = (JpegeSyntax *)task->syntax.data; + RK_U32 mcu_w = syntax->mcu_hor_cnt; + RK_U32 mcu_h = syntax->mcu_ver_cnt; + RK_U32 mcu_y = ctx->mcu_y; + RK_U32 part_mcu_h = syntax->part_rows; + RK_U32 *regs = (RK_U32 *)ctx->regs; + RK_U32 part_enc_h; + RK_U32 part_enc_mcu_h; + RK_U32 part_y_fill; + RK_U32 part_not_end; + + hal_jpege_dbg_func("enter part start %p\n", hal); + + /* Fix register for each part encoding */ + task->part_first = !mcu_y; + if (mcu_y + part_mcu_h < mcu_h) { + part_enc_h = part_mcu_h * 16; + part_enc_mcu_h = part_mcu_h; + part_y_fill = 0; + part_not_end = 1; + task->part_last = 0; + } else { + part_enc_h = syntax->height - mcu_y * 16; + part_enc_mcu_h = MPP_ALIGN(part_enc_h, 16) / 16;; + part_y_fill = ctx->part_y_fill; + part_not_end = 0; + task->part_last = 1; + } + + hal_jpege_dbg_detail("part first %d last %d\n", task->part_first, task->part_last); + + get_msb_lsb_at_pos(®s[22], ®s[23], ctx->base, ctx->part_bytepos); + + regs[24] = ctx->size - ctx->part_bytepos; + + regs[15] = (regs[15] & 0xfffffc3f) | (part_y_fill << 6); + + regs[37] = ((ctx->part_bytepos & 7) * 8) << 23; + + regs[5] = mpp_buffer_get_fd(task->output); + if (ctx->part_bytepos) + mpp_dev_set_reg_offset(ctx->dev, 5, ctx->part_bytepos); + + regs[14] = (1 << 31) | + (0 << 30) | + (0 << 29) | + (mcu_w << 19) | + (part_enc_mcu_h << 10) | + (1 << 3) | (2 << 1) | 1; + + regs[20] = part_not_end << 24 | jpege_restart_marker[ctx->rst_marker_idx & 7]; + ctx->rst_marker_idx++; + + hal_jpege_vepu1_set_extra_info(ctx->dev, syntax, mcu_y); + ctx->mcu_y += part_enc_mcu_h; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = ctx->reg_size; + + wr_cfg.reg = ctx->regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ctx->regs_out; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_jpege_dbg_func("leave part start %p\n", hal); + (void)task; + return ret; +} + +static MPP_RET hal_jpege_vepu1_part_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + RK_U32 *regs = ctx->regs_out; + JpegeFeedback *feedback = &ctx->feedback; + RK_U32 hw_bit = 0; + + hal_jpege_dbg_func("enter part wait %p\n", hal); + + if (ctx->dev) { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + hal_jpege_dbg_detail("hw_status %08x\n", regs[1]); + + hw_bit = regs[24]; + + hal_jpege_dbg_detail("byte pos %d -> %d\n", ctx->part_bytepos, + (ctx->part_bytepos & (~7)) + (hw_bit / 8)); + ctx->part_bytepos = (ctx->part_bytepos & (~7)) + (hw_bit / 8); + + feedback->stream_length = ctx->part_bytepos; + task->length = ctx->part_bytepos; + task->hw_length = task->length - ctx->hal_start_pos; + + hal_jpege_dbg_detail("stream_length %d, hw_byte %d", + feedback->stream_length, hw_bit / 8); + + hal_jpege_dbg_output("stream bit: sw %d hw %d total %d hw_length %d\n", + ctx->sw_bit, hw_bit, feedback->stream_length, task->hw_length); + + hal_jpege_dbg_func("leave part wait %p\n", hal); + return ret; +} + +static MPP_RET hal_jpege_vepu1_ret_task(void *hal, HalEncTask *task) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + + task->rc_task->info.bit_real = ctx->feedback.stream_length * 8; + task->hal_ret.data = &ctx->feedback; + task->hal_ret.number = 1; + task->rc_task->info.quality_real = task->rc_task->info.quality_target; + + return MPP_OK; +} + +const MppEncHalApi hal_jpege_vepu1 = { + .name = "hal_jpege_vepu1", + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(HalJpegeCtx), + .flag = 0, + .init = hal_jpege_vepu1_init, + .deinit = hal_jpege_vepu1_deinit, + .prepare = NULL, + .get_task = hal_jpege_vepu1_get_task, + .gen_regs = hal_jpege_vepu1_gen_regs, + .start = hal_jpege_vepu1_start, + .wait = hal_jpege_vepu1_wait, + .part_start = hal_jpege_vepu1_part_start, + .part_wait = hal_jpege_vepu1_part_wait, + .ret_task = hal_jpege_vepu1_ret_task, + .client = VPU_CLIENT_VEPU1, + .soc_type = { + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_jpege_vepu1) diff --git a/mpp/hal/vpu/jpege/hal_jpege_vepu1_v2.h b/mpp/hal/vpu/jpege/hal_jpege_vepu1_v2.h new file mode 100644 index 000000000..8a314031b --- /dev/null +++ b/mpp/hal/vpu/jpege/hal_jpege_vepu1_v2.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_JPEGE_VEPU1_V2_H +#define HAL_JPEGE_VEPU1_V2_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_jpege_vepu1; + +#endif diff --git a/mpp/hal/vpu/jpege/hal_jpege_vepu2_v2.c b/mpp/hal/vpu/jpege/hal_jpege_vepu2_v2.c new file mode 100644 index 000000000..3960f67ea --- /dev/null +++ b/mpp/hal/vpu/jpege/hal_jpege_vepu2_v2.c @@ -0,0 +1,1082 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_jpege_vepu2" + +#include + +#include "mpp_env.h" +#include "mpp_common.h" +#include "mpp_mem.h" +#include "mpp_platform.h" +#include "mpp_dmabuf.h" + +#include "mpp_enc_hal.h" +#include "vcodec_service.h" + +#include "hal_jpege_debug.h" +#include "hal_jpege_base.h" + +#define VEPU_JPEGE_VEPU2_NUM_REGS 184 +#define VEPU2_REG_INPUT_Y 48 +#define VEPU2_REG_INPUT_U 49 +#define VEPU2_REG_INPUT_V 50 + +typedef struct jpege_vepu2_reg_set_t { + RK_U32 val[VEPU_JPEGE_VEPU2_NUM_REGS]; +} jpege_vepu2_reg_set; + +#define MAX_CORE_NUM 4 + +typedef struct JpegeMultiCoreCtx_t { + RK_U32 multi_core_enabled; + RK_U32 partion_num; + MppDevRegOffCfgs *reg_cfg; + + MppBufferGroup partions_group; + MppBuffer partions_buf[MAX_CORE_NUM - 1]; + RK_U32 buf_size; + + RK_U32 part_rows[MAX_CORE_NUM]; + RK_U32 ecs_cnt[MAX_CORE_NUM]; + + void *regs_base; + void *regs[MAX_CORE_NUM]; + void *regs_out[MAX_CORE_NUM]; +} JpegeMultiCoreCtx; + +MPP_RET hal_jpege_vepu2_init(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + MppClientType type; + RK_U32 vcodec_type = mpp_get_vcodec_type(); + + mpp_env_get_u32("hal_jpege_debug", &hal_jpege_debug, 0); + hal_jpege_dbg_func("enter hal %p cfg %p\n", hal, cfg); + + /* update output to MppEnc */ + type = ((vcodec_type & HAVE_VEPU2_JPEG) != 0) ? + VPU_CLIENT_VEPU2_JPEG : VPU_CLIENT_VEPU2; + + cfg->type = type; + ret = mpp_dev_init(&cfg->dev, type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + ctx->dev = cfg->dev; + ctx->type = cfg->type; + ctx->task_cnt = cfg->task_cnt; + + jpege_bits_init(&ctx->bits); + mpp_assert(ctx->bits); + + ctx->cfg = cfg->cfg; + ctx->reg_size = sizeof(RK_U32) * VEPU_JPEGE_VEPU2_NUM_REGS; + ctx->regs = mpp_calloc_size(void, (ctx->reg_size + EXTRA_INFO_SIZE) * ctx->task_cnt); + if (NULL == ctx->regs) { + mpp_err_f("failed to malloc vepu2 regs\n"); + return MPP_NOK; + } + + ctx->regs_out = mpp_calloc_size(void, (ctx->reg_size + EXTRA_INFO_SIZE) * ctx->task_cnt); + if (NULL == ctx->regs_out) { + mpp_err_f("failed to malloc vepu2 regs\n"); + return MPP_NOK; + } + + hal_jpege_rc_init(&ctx->hal_rc); + + hal_jpege_dbg_func("leave hal %p\n", hal); + return MPP_OK; +} + +MPP_RET hal_jpege_vepu2_deinit(void *hal) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + if (ctx->bits) { + jpege_bits_deinit(ctx->bits); + ctx->bits = NULL; + } + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + if (ctx->ctx_ext) { + JpegeMultiCoreCtx *ctx_ext = ctx->ctx_ext; + RK_U32 i; + + if (ctx_ext->reg_cfg) { + mpp_dev_multi_offset_deinit(ctx_ext->reg_cfg); + ctx_ext->reg_cfg = NULL; + } + + for (i = 0; i < MAX_CORE_NUM - 1; i++) + if (ctx_ext->partions_buf[i]) + mpp_buffer_put(ctx_ext->partions_buf[i]); + + if (ctx_ext->partions_group) { + mpp_buffer_group_put(ctx_ext->partions_group); + ctx_ext->partions_group = NULL; + } + + MPP_FREE(ctx_ext->regs_base); + MPP_FREE(ctx->ctx_ext); + } + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->regs_out); + + hal_jpege_dbg_func("leave hal %p\n", hal); + return MPP_OK; +} + +MPP_RET hal_jpege_vepu2_get_task(void *hal, HalEncTask *task) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + JpegeSyntax *syntax = (JpegeSyntax *)task->syntax.data; + JpegeMultiCoreCtx *ctx_ext = (JpegeMultiCoreCtx *)ctx->ctx_ext; + RK_U32 i = 0; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + memcpy(&ctx->syntax, syntax, sizeof(ctx->syntax)); + + ctx->hal_start_pos = mpp_packet_get_length(task->packet); + + /* prepare for part encoding */ + ctx->mcu_y = 0; + ctx->mcu_h = syntax->mcu_ver_cnt; + ctx->sw_bit = 0; + ctx->part_bytepos = 0; + ctx->part_x_fill = 0; + ctx->part_y_fill = 0; + ctx->rst_marker_idx = 0; + task->part_first = 1; + task->part_last = 0; + task->flags.reg_idx = 0; + + /* rk3588 4 core frame parallel */ + if (ctx->task_cnt > 1) { + task->flags.reg_idx = ctx->task_idx++; + if (ctx->task_idx >= ctx->task_cnt) + ctx->task_idx = 0; + goto MULTI_CORE_SPLIT_DONE; + } + + /* Split single task to multi cores on rk3588 */ + if (ctx_ext) + ctx_ext->multi_core_enabled = 0; + + if (ctx->type == VPU_CLIENT_VEPU2_JPEG) { + RK_U32 width = ctx->cfg->prep.width; + RK_U32 height = ctx->cfg->prep.height; + RK_U32 buf_size = width * height / 2; + + /* small image do not need to split into four segments */ + if (width * height <= 1280 * 720 && (height <= 720 || width <= 720)) + goto MULTI_CORE_SPLIT_DONE; + + if (!ctx_ext) { + ctx_ext = mpp_calloc(JpegeMultiCoreCtx, 1); + ctx->ctx_ext = ctx_ext; + } + + mpp_assert(ctx_ext); + + if (!ctx_ext->partions_group) { + mpp_buffer_group_get_internal(&ctx_ext->partions_group, MPP_BUFFER_TYPE_DMA_HEAP | MPP_BUFFER_FLAGS_CACHABLE); + if (!ctx_ext->partions_group) + mpp_buffer_group_get_internal(&ctx_ext->partions_group, MPP_BUFFER_TYPE_ION); + } + + mpp_assert(ctx_ext->partions_group); + + if (ctx_ext->buf_size != buf_size) { + MppBuffer buf = NULL; + + for (i = 0; i < MAX_CORE_NUM - 1; i++) { + buf = ctx_ext->partions_buf[i]; + if (buf) + mpp_buffer_put(buf); + } + + mpp_buffer_group_clear(ctx_ext->partions_group); + + for (i = 0; i < MAX_CORE_NUM - 1; i++) { + mpp_buffer_get(ctx_ext->partions_group, &buf, buf_size); + mpp_assert(buf); + ctx_ext->partions_buf[i] = buf; + } + + ctx_ext->buf_size = buf_size; + } + + if (!ctx_ext->regs_base) { + void *regs_base = mpp_calloc_size(void, ctx->reg_size * MAX_CORE_NUM * 2); + size_t reg_size = ctx->reg_size; + + ctx_ext->regs_base = regs_base; + for (i = 0; i < MAX_CORE_NUM; i++) { + ctx_ext->regs[i] = regs_base; + regs_base += reg_size; + + ctx_ext->regs_out[i] = regs_base; + regs_base += reg_size; + } + } + + { + RK_U32 mb_w = MPP_ALIGN(width, 16) / 16; + RK_U32 mb_h = MPP_ALIGN(height, 16) / 16; + RK_U32 part_rows = MPP_ALIGN(mb_h, 4) / 4; + + ctx_ext->partion_num = 0; + + if (ctx->cfg->split.split_mode == MPP_ENC_SPLIT_BY_CTU) { + RK_U32 ecs_num = (mb_h + syntax->part_rows - 1) / syntax->part_rows; + RK_U32 *core_ecs = ctx_ext->ecs_cnt; + + if (ecs_num > 24 || ecs_num <= 8) { + RK_U32 divider = ecs_num > 24 ? 8 : 1; + RK_U32 quotient = ecs_num / divider; + RK_U32 remainder = ecs_num % divider; + RK_U32 runs = quotient / MAX_CORE_NUM; + RK_U32 runs_left = quotient % MAX_CORE_NUM; + + if (runs > 0) { + for (i = 0; i < MAX_CORE_NUM; i++) + core_ecs[i] = runs * divider; + } + + for (i = 0; i < runs_left; i++) + core_ecs[i] += divider; + + core_ecs[MAX_CORE_NUM - 1] += remainder; + } else if (ecs_num > 20) { + core_ecs[0] = core_ecs[1] = 8; + core_ecs[2] = (ecs_num - 8 * 2) / 2; + core_ecs[3] = ecs_num - 8 * 2 - core_ecs[2]; + } else if (ecs_num > 16) { + core_ecs[0] = 8; + core_ecs[1] = core_ecs[2] = 4; + core_ecs[3] = ecs_num - 8 - 4 * 2; + } else if (ecs_num > 8) { + core_ecs[0] = core_ecs[1] = 4; + core_ecs[2] = (ecs_num - 4 * 2) / 2; + core_ecs[3] = ecs_num - 4 * 2 - core_ecs[2]; + } + + for (i = 0; i < MAX_CORE_NUM; i++) { + ctx_ext->part_rows[i] = core_ecs[i] * syntax->part_rows; + hal_jpege_dbg_detail("part %d, ecs %d, rows %d", i, core_ecs[i], + ctx_ext->part_rows[i]); + if (core_ecs[i]) + ctx_ext->partion_num++; + } + } else { + for (i = 0; i < MAX_CORE_NUM; i++) { + part_rows = (mb_h >= part_rows) ? part_rows : mb_h; + + ctx_ext->part_rows[i] = part_rows; + ctx_ext->ecs_cnt[i] = 1; + + hal_jpege_dbg_detail("part %d row %d restart %d\n", + i, part_rows, mb_w * part_rows); + + if (part_rows) + ctx_ext->partion_num++; + + if (i == 0 && !ctx->syntax.restart_ri) + ctx->syntax.restart_ri = mb_w * part_rows; + + mb_h -= part_rows; + } + } + } + + if (!ctx_ext->reg_cfg) + mpp_dev_multi_offset_init(&ctx_ext->reg_cfg, 24); + + syntax->low_delay = 1; + ctx_ext->multi_core_enabled = 1; + } + + if (ctx->cfg->jpeg.update) { + hal_jpege_rc_update(&ctx->hal_rc, syntax); + ctx->cfg->jpeg.update = 0; + } + + task->rc_task->frm.is_intra = 1; + +MULTI_CORE_SPLIT_DONE: + + hal_jpege_dbg_func("leave hal %p\n", hal); + + return MPP_OK; +} + +static MPP_RET hal_jpege_vepu2_set_extra_info(MppDev dev, JpegeSyntax *syntax, + RK_U32 start_mbrow) +{ + VepuOffsetCfg cfg; + + cfg.fmt = syntax->format; + cfg.width = syntax->width; + cfg.height = syntax->height; + cfg.hor_stride = syntax->hor_stride; + cfg.ver_stride = syntax->ver_stride; + cfg.offset_x = syntax->offset_x; + cfg.offset_y = syntax->offset_y + start_mbrow * 16; + + get_vepu_offset_cfg(&cfg); + + if (cfg.offset_byte[0]) + mpp_dev_set_reg_offset(dev, VEPU2_REG_INPUT_Y, cfg.offset_byte[0]); + + if (cfg.offset_byte[1]) + mpp_dev_set_reg_offset(dev, VEPU2_REG_INPUT_U, cfg.offset_byte[1]); + + if (cfg.offset_byte[2]) + mpp_dev_set_reg_offset(dev, VEPU2_REG_INPUT_V, cfg.offset_byte[2]); + + return MPP_OK; +} + +MPP_RET hal_jpege_vepu2_gen_regs(void *hal, HalEncTask *task) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + MppBuffer input = task->input; + MppBuffer output = task->output; + JpegeSyntax *syntax = &ctx->syntax; + RK_U32 width = syntax->width; + RK_U32 width_align = MPP_ALIGN(width, 16); + RK_U32 height = syntax->height; + MppFrameFormat fmt = syntax->format; + RK_U32 hor_stride = 0; + RK_U32 ver_stride = MPP_ALIGN(height, 16); + JpegeBits bits = ctx->bits; + RK_S32 reg_idx = task->flags.reg_idx; + RK_U32 *regs = (RK_U32 *)((RK_U8 *)ctx->regs + ctx->reg_size * reg_idx); + size_t length = mpp_packet_get_length(task->packet); + RK_U8 *buf = mpp_buffer_get_ptr(output); + size_t size = mpp_buffer_get_size(output); + RK_S32 bitpos; + RK_S32 bytepos; + RK_U32 x_fill = 0; + RK_U32 y_fill = 0; + VepuFormatCfg fmt_cfg; + RK_U32 rotation = 0; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + // do not support mirroring + if (syntax->mirroring) + mpp_err_f("Warning: do not support mirroring\n"); + + if (syntax->rotation == MPP_ENC_ROT_90) + rotation = 1; + else if (syntax->rotation == MPP_ENC_ROT_270) + rotation = 2; + else if (syntax->rotation != MPP_ENC_ROT_0) + mpp_err_f("Warning: only support 90 or 270 degree rotate, request rotate %d", syntax->rotation); + if (rotation) { + MPP_SWAP(RK_U32, width, height); + MPP_SWAP(RK_U32, width_align, ver_stride); + } + hor_stride = get_vepu_pixel_stride(&ctx->stride_cfg, width, + syntax->hor_stride, fmt); + + //hor_stride must be align with 8, and ver_stride mus align with 2 + if ((hor_stride & 0x7) || (ver_stride & 0x1) || (hor_stride >= (1 << 15))) { + mpp_err_f("illegal resolution, hor_stride %d, ver_stride %d, width %d, height %d\n", + syntax->hor_stride, syntax->ver_stride, + syntax->width, syntax->height); + } + + x_fill = (width_align - width) / 4; + y_fill = (ver_stride - height); + mpp_assert(x_fill <= 3); + mpp_assert(y_fill <= 15); + ctx->part_x_fill = x_fill; + ctx->part_y_fill = y_fill; + + mpp_buffer_sync_begin(output); + + if (syntax->q_mode == JPEG_QFACTOR) { + syntax->q_factor = 100 - task->rc_task->info.quality_target; + hal_jpege_rc_update(&ctx->hal_rc, syntax); + } + + /* write header to output buffer */ + jpege_bits_setup(bits, buf, (RK_U32)size); + /* seek length bytes data */ + jpege_seek_bits(bits, length << 3); + /* NOTE: write header will update qtable */ + write_jpeg_header(bits, syntax, &ctx->hal_rc); + + memset(regs, 0, sizeof(RK_U32) * VEPU_JPEGE_VEPU2_NUM_REGS); + // input address setup + regs[VEPU2_REG_INPUT_Y] = mpp_buffer_get_fd(input); + regs[VEPU2_REG_INPUT_U] = regs[VEPU2_REG_INPUT_Y]; + regs[VEPU2_REG_INPUT_V] = regs[VEPU2_REG_INPUT_Y]; + + // output address setup + bitpos = jpege_bits_get_bitpos(bits); + bytepos = (bitpos + 7) >> 3; + ctx->base = buf; + ctx->size = size; + ctx->sw_bit = bitpos; + ctx->part_bytepos = bytepos; + + get_msb_lsb_at_pos(®s[51], ®s[52], buf, bytepos); + + mpp_buffer_sync_end(output); + + regs[53] = size - bytepos; + + // bus config + regs[54] = 16 << 8; + + regs[60] = (((bytepos & 7) * 8) << 16) | + (x_fill << 4) | + (y_fill); + regs[61] = hor_stride; + + regs[77] = mpp_buffer_get_fd(output); + if (bytepos) + mpp_dev_set_reg_offset(ctx->dev, 77, bytepos); + /* 95 - 97 color conversion parameter */ + { + RK_U32 coeffA; + RK_U32 coeffB; + RK_U32 coeffC; + RK_U32 coeffE; + RK_U32 coeffF; + + switch (syntax->color_conversion_type) { + case 0 : { /* BT.601 */ + /* + * Y = 0.2989 R + 0.5866 G + 0.1145 B + * Cb = 0.5647 (B - Y) + 128 + * Cr = 0.7132 (R - Y) + 128 + */ + coeffA = 19589; + coeffB = 38443; + coeffC = 7504; + coeffE = 37008; + coeffF = 46740; + } break; + case 1 : { /* BT.709 */ + /* + * Y = 0.2126 R + 0.7152 G + 0.0722 B + * Cb = 0.5389 (B - Y) + 128 + * Cr = 0.6350 (R - Y) + 128 + */ + coeffA = 13933; + coeffB = 46871; + coeffC = 4732; + coeffE = 35317; + coeffF = 41615; + } break; + case 2 : { + coeffA = syntax->coeffA; + coeffB = syntax->coeffB; + coeffC = syntax->coeffC; + coeffE = syntax->coeffE; + coeffF = syntax->coeffF; + } break; + default : { + mpp_err("invalid color conversion type %d\n", + syntax->color_conversion_type); + coeffA = 19589; + coeffB = 38443; + coeffC = 7504; + coeffE = 37008; + coeffF = 46740; + } break; + } + + regs[95] = coeffA | (coeffB << 16); + regs[96] = coeffC | (coeffE << 16); + regs[97] = coeffF; + } + + regs[103] = (width_align >> 4) << 8 | + (ver_stride >> 4) << 20 | + (1 << 6) | /* intra coding */ + (2 << 4) | /* format jpeg */ + 1; /* encoder start */ + + if (!get_vepu_fmt(&fmt_cfg, fmt)) { + regs[74] = (fmt_cfg.format << 4) | + (rotation << 2); + regs[98] = (fmt_cfg.b_mask & 0x1f) << 16 | + (fmt_cfg.g_mask & 0x1f) << 8 | + (fmt_cfg.r_mask & 0x1f); + regs[105] = 7 << 26 | (fmt_cfg.swap_32_in & 1) << 29 | + (fmt_cfg.swap_16_in & 1) << 30 | + (fmt_cfg.swap_8_in & 1) << 31; + } + + regs[107] = ((syntax->part_rows & 0xff) << 16) | + jpege_restart_marker[ctx->rst_marker_idx & 7]; + + /* encoder interrupt */ + regs[109] = 1 << 12 | /* clock gating */ + 1 << 10; /* enable timeout interrupt */ + + if (syntax->low_delay) { + /* slice encode end by RST */ + regs[107] |= (1 << 24); + /* slice interrupt enable */ + regs[109] |= (1 << 16); + } + + /* 0 ~ 31 quantization tables */ + { + RK_S32 i; + + for (i = 0; i < 16; i++) { + /* qtable need to reorder in particular order */ + regs[i] = ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 0]] << 24 | + ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 1]] << 16 | + ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 2]] << 8 | + ctx->hal_rc.qtables[0][qp_reorder_table[i * 4 + 3]]; + } + for (i = 0; i < 16; i++) { + /* qtable need to reorder in particular order */ + regs[i + 16] = ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 0]] << 24 | + ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 1]] << 16 | + ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 2]] << 8 | + ctx->hal_rc.qtables[1][qp_reorder_table[i * 4 + 3]]; + } + } + + hal_jpege_dbg_func("leave hal %p\n", hal); + return MPP_OK; +} + +static MPP_RET multi_core_start(HalJpegeCtx *ctx, HalEncTask *task) +{ + JpegeMultiCoreCtx *ctx_ext = ctx->ctx_ext; + JpegeSyntax *syntax = &ctx->syntax; + MppDevRegOffCfgs *reg_cfg = ctx_ext->reg_cfg; + MppDev dev = ctx->dev; + RK_S32 reg_idx = task->flags.reg_idx; + RK_U32 *src = (RK_U32 *)((RK_U8 *)ctx->regs + ctx->reg_size * reg_idx); + RK_U32 reg_size = ctx->reg_size; + MPP_RET ret = MPP_OK; + RK_U32 partion_num = ctx_ext->partion_num; + RK_U32 mcu_y = 0; + RK_U32 i; + + hal_jpege_dbg_detail("start %d partions\n", partion_num); + + for (i = 0; i < partion_num; i++) { + RK_U32 part_not_end = i < partion_num - 1; + RK_U32 part_not_start = i > 0; + RK_U32 *regs = (RK_U32 *)ctx_ext->regs[i]; + RK_U32 part_enc_mcu_h = ctx_ext->part_rows[i]; + RK_U32 part_x_fill = ctx->part_x_fill; + RK_U32 part_y_fill = ctx->part_y_fill; + RK_U32 part_bytepos = ctx->part_bytepos; + + // it only needs to fill the partition on the right and below. + if (syntax->rotation == MPP_ENC_ROT_90) { + if (part_not_end) + part_x_fill = 0; + } else if (syntax->rotation == MPP_ENC_ROT_0 || syntax->rotation == MPP_ENC_ROT_180) { + if (part_not_end) + part_y_fill = 0; + } else if (syntax->rotation == MPP_ENC_ROT_270) { + if (part_not_start) + part_x_fill = 0; + } else + mpp_err_f("input rotation %d not supported", syntax->rotation); + + memcpy(regs, src, reg_size); + + mpp_dev_multi_offset_reset(reg_cfg); + + if (i == 0) { + get_msb_lsb_at_pos(®s[51], ®s[52], ctx->base, part_bytepos); + regs[77] = mpp_buffer_get_fd(task->output); + regs[53] = mpp_buffer_get_size(task->output) - part_bytepos; + regs[60] = (((part_bytepos & 7) * 8) << 16) | + (part_x_fill << 4) | + (part_y_fill); + /* the stream offset had been setup */ + } else { + MppBuffer buf = ctx_ext->partions_buf[i - 1]; + + regs[77] = mpp_buffer_get_fd(buf); + regs[53] = mpp_buffer_get_size(buf); + regs[60] = (((0 & 7) * 8) << 16) | + (part_x_fill << 4) | + (part_y_fill); + } + + regs[103] = syntax->mcu_hor_cnt << 8 | + (part_enc_mcu_h) << 20 | + (1 << 6) | /* intra coding */ + (2 << 4) | /* format jpeg */ + 1; /* encoder start */ + + hal_jpege_dbg_detail("part %d, part_not_end 0x%x, rst_marker_idx %d", + i, part_not_end, ctx->rst_marker_idx); + regs[107] = part_not_end << 24 | ((syntax->part_rows & 0xff) << 16) | + jpege_restart_marker[ctx->rst_marker_idx & 7]; + ctx->rst_marker_idx += ctx_ext->ecs_cnt[i]; + + VepuOffsetCfg cfg; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.fmt = syntax->format; + cfg.width = syntax->width; + cfg.height = syntax->height; + cfg.hor_stride = syntax->hor_stride; + cfg.ver_stride = syntax->ver_stride; + cfg.offset_x = syntax->offset_x; + cfg.offset_y = syntax->offset_y + mcu_y * 16; + + if (syntax->rotation == MPP_ENC_ROT_90 || syntax->rotation == MPP_ENC_ROT_270) { + regs[103] = part_enc_mcu_h << 8 | + (syntax->mcu_hor_cnt) << 20 | + (1 << 6) | /* intra coding */ + (2 << 4) | /* format jpeg */ + 1; /* encoder start */ + + /* + * It is opposite that position of partitions + * of rotation 90 degree and rotation 270 degree. + */ + if (syntax->rotation == MPP_ENC_ROT_270) + cfg.offset_x = syntax->offset_x + + (syntax->mcu_ver_cnt - ctx_ext->part_rows[0] - mcu_y) * 16; + else + cfg.offset_x = syntax->offset_x + mcu_y * 16; + + cfg.offset_y = syntax->offset_y; + } + + get_vepu_offset_cfg(&cfg); + mpp_dev_multi_offset_update(reg_cfg, VEPU2_REG_INPUT_Y, cfg.offset_byte[0]); + mpp_dev_multi_offset_update(reg_cfg, VEPU2_REG_INPUT_U, cfg.offset_byte[1]); + mpp_dev_multi_offset_update(reg_cfg, VEPU2_REG_INPUT_V, cfg.offset_byte[2]); + + mcu_y += part_enc_mcu_h; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ctx_ext->regs_out[i]; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_OFFS, reg_cfg); + if (ret) { + mpp_err_f("set register offsets failed %d\n", ret); + break; + } + + if (i < partion_num - 1) { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_DELIMIT, NULL); + if (ret) { + mpp_err_f("send delimit failed %d\n", ret); + break; + } + } + } while (0); + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) + mpp_err_f("send cmd failed %d\n", ret); + + return ret; +} + +static MPP_RET multi_core_wait(HalJpegeCtx *ctx, HalEncTask *task) +{ + JpegeMultiCoreCtx *ctx_ext = (JpegeMultiCoreCtx *)ctx->ctx_ext; + JpegeFeedback *feedback = &ctx->feedback; + RK_U32 sw_bit = 0; + RK_U32 hw_bit = 0; + MPP_RET ret = MPP_OK; + RK_U32 val; + RK_U32 i; + + hal_jpege_dbg_detail("poll partion_num %d\n", ctx_ext->partion_num); + + for (i = 0; i < ctx_ext->partion_num; i++) { + RK_U32 *regs = ctx_ext->regs_out[i]; + + hal_jpege_dbg_detail("poll reg %d %p", i, regs); + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (i == 0) { + RK_S32 fd = mpp_buffer_get_fd(task->output); + + val = regs[109]; + hal_jpege_dbg_output("hw_status %08x\n", val); + feedback->hw_status = val & 0x70; + val = regs[53]; + sw_bit = jpege_bits_get_bitpos(ctx->bits); + hw_bit = val; + feedback->stream_length = ((sw_bit / 8) & (~0x7)) + hw_bit / 8; + hal_jpege_dbg_detail("partion len = %d", hw_bit / 8); + task->length = feedback->stream_length; + task->hw_length = task->length - ctx->hal_start_pos; + + mpp_dmabuf_sync_partial_begin(fd, 1, 0, task->length, __FUNCTION__); + } else { + void *stream_ptr = mpp_buffer_get_ptr(task->output); + void *partion_ptr = mpp_buffer_get_ptr(ctx_ext->partions_buf[i - 1]); + RK_S32 partion_fd = mpp_buffer_get_fd(ctx_ext->partions_buf[i - 1]); + RK_U32 partion_len = 0; + + val = regs[109]; + hal_jpege_dbg_output("hw_status %08x\n", val); + feedback->hw_status = val & 0x70; + partion_len = regs[53] / 8; + hal_jpege_dbg_detail("partion_len = %d", partion_len); + + mpp_dmabuf_sync_partial_begin(partion_fd, 1, 0, partion_len, __FUNCTION__); + + memcpy(stream_ptr + feedback->stream_length, partion_ptr, partion_len); + feedback->stream_length += partion_len; + task->length = feedback->stream_length; + task->hw_length += partion_len; + } + } + + hal_jpege_dbg_output("stream bit: sw %d hw %d total %d hw_length %d\n", + sw_bit, hw_bit, feedback->stream_length, task->hw_length); + + return ret; +} + +MPP_RET hal_jpege_vepu2_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + JpegeMultiCoreCtx *ctx_ext = (JpegeMultiCoreCtx *)ctx->ctx_ext; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + if (ctx_ext && ctx_ext->multi_core_enabled) { + multi_core_start(ctx, task); + } else { + hal_jpege_vepu2_set_extra_info(ctx->dev, &ctx->syntax, 0); + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = ctx->reg_size; + RK_S32 reg_idx = task->flags.reg_idx; + RK_U32 *regs = (RK_U32 *)((RK_U8 *)ctx->regs + reg_size * reg_idx); + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + } + hal_jpege_dbg_func("leave hal %p\n", hal); + (void)task; + return ret; +} + +MPP_RET hal_jpege_vepu2_wait(void *hal, HalEncTask *task) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + JpegeMultiCoreCtx *ctx_ext = (JpegeMultiCoreCtx *)ctx->ctx_ext; + MPP_RET ret = MPP_OK; + + hal_jpege_dbg_func("enter hal %p\n", hal); + + if (ctx_ext && ctx_ext->multi_core_enabled) { + multi_core_wait(ctx, task); + } else { + JpegeFeedback *feedback = &ctx->feedback; + JpegeBits bits = ctx->bits; + RK_S32 reg_idx = task->flags.reg_idx; + RK_U32 *regs = (RK_U32 *)((RK_U8 *)ctx->regs + ctx->reg_size * reg_idx); + RK_U32 sw_bit = 0; + RK_U32 hw_bit = 0; + RK_U32 val; + + if (ctx->dev) { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + val = regs[109]; + hal_jpege_dbg_output("hw_status %08x\n", val); + feedback->hw_status = val & 0x70; + val = regs[53]; + + sw_bit = jpege_bits_get_bitpos(bits); + hw_bit = val; + + // NOTE: hardware will return 64 bit access byte count + feedback->stream_length = ((sw_bit / 8) & (~0x7)) + hw_bit / 8; + task->length = feedback->stream_length; + task->hw_length = task->length - ctx->hal_start_pos; + + hal_jpege_dbg_output("stream bit: sw %d hw %d total %d hw_length %d\n", + sw_bit, hw_bit, feedback->stream_length, task->hw_length); + } + + hal_jpege_dbg_func("leave hal %p\n", hal); + return ret; +} + +MPP_RET hal_jpege_vepu2_part_start(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + JpegeSyntax *syntax = (JpegeSyntax *)task->syntax.data; + RK_U32 mcu_w = syntax->mcu_hor_cnt; + RK_U32 mcu_h = syntax->mcu_ver_cnt; + RK_U32 mcu_y = ctx->mcu_y; + RK_U32 part_mcu_h = syntax->part_rows; + RK_S32 reg_idx = task->flags.reg_idx; + RK_U32 *regs = (RK_U32 *)((RK_U8 *)ctx->regs + ctx->reg_size * reg_idx); + RK_U32 part_enc_h; + RK_U32 part_enc_mcu_h; + RK_U32 part_y_fill; + RK_U32 part_not_end; + + hal_jpege_dbg_func("enter part start %p\n", hal); + + /* Fix register for each part encoding */ + task->part_first = !mcu_y; + if (mcu_y + part_mcu_h < mcu_h) { + part_enc_h = part_mcu_h * 16; + part_enc_mcu_h = part_mcu_h; + part_y_fill = 0; + part_not_end = 1; + task->part_last = 0; + } else { + part_enc_h = syntax->height - mcu_y * 16; + part_enc_mcu_h = MPP_ALIGN(part_enc_h, 16) / 16;; + part_y_fill = ctx->part_y_fill; + part_not_end = 0; + task->part_last = 1; + } + + hal_jpege_dbg_detail("part first %d last %d\n", task->part_first, task->part_last); + + get_msb_lsb_at_pos(®s[51], ®s[52], ctx->base, ctx->part_bytepos); + + regs[53] = ctx->size - ctx->part_bytepos; + + regs[60] = (((ctx->part_bytepos & 7) * 8) << 16) | + (ctx->part_x_fill << 4) | + (part_y_fill); + + regs[77] = mpp_buffer_get_fd(task->output); + if (ctx->part_bytepos) + mpp_dev_set_reg_offset(ctx->dev, 77, ctx->part_bytepos); + + regs[103] = mcu_w << 8 | + (part_enc_mcu_h) << 20 | + (1 << 6) | /* intra coding */ + (2 << 4) | /* format jpeg */ + 1; /* encoder start */ + + hal_jpege_dbg_detail("part_not_end 0x%x, rst_marker_idx %d", + part_not_end, ctx->rst_marker_idx); + regs[107] = part_not_end << 24 | jpege_restart_marker[ctx->rst_marker_idx & 7]; + ctx->rst_marker_idx++; + + hal_jpege_vepu2_set_extra_info(ctx->dev, syntax, mcu_y); + ctx->mcu_y += part_enc_mcu_h; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = ctx->reg_size; + + wr_cfg.reg = ctx->regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ctx->regs_out; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + hal_jpege_dbg_func("leave part start %p\n", hal); + (void)task; + return ret; +} + +MPP_RET hal_jpege_vepu2_part_wait(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + RK_S32 reg_idx = task->flags.reg_idx; + RK_U32 *regs = (RK_U32 *)((RK_U8 *)ctx->regs_out + ctx->reg_size * reg_idx); + JpegeFeedback *feedback = &ctx->feedback; + RK_U32 hw_bit = 0; + + hal_jpege_dbg_func("enter part wait %p\n", hal); + + if (ctx->dev) { + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + } + + hal_jpege_dbg_detail("hw_status %08x\n", regs[109]); + + hw_bit = regs[53]; + + hal_jpege_dbg_detail("byte pos %d -> %d\n", ctx->part_bytepos, + (ctx->part_bytepos & (~7)) + (hw_bit / 8)); + ctx->part_bytepos = (ctx->part_bytepos & (~7)) + (hw_bit / 8); + + feedback->stream_length = ctx->part_bytepos; + task->length = ctx->part_bytepos; + task->hw_length = task->length - ctx->hal_start_pos; + + hal_jpege_dbg_detail("stream_length %d, hw_byte %d", + feedback->stream_length, hw_bit / 8); + + hal_jpege_dbg_output("stream bit: sw %d hw %d total %d hw_length %d\n", + ctx->sw_bit, hw_bit, feedback->stream_length, task->hw_length); + + hal_jpege_dbg_func("leave part wait %p\n", hal); + return ret; +} + +MPP_RET hal_jpege_vepu2_ret_task(void *hal, HalEncTask *task) +{ + HalJpegeCtx *ctx = (HalJpegeCtx *)hal; + EncRcTaskInfo *rc_info = &task->rc_task->info; + + task->rc_task->info.bit_real = ctx->feedback.stream_length * 8; + task->hal_ret.data = &ctx->feedback; + task->hal_ret.number = 1; + + rc_info->quality_real = rc_info->quality_target; + + return MPP_OK; +} + +const MppEncHalApi hal_jpege_vepu2 = { + .name = "hal_jpege_vepu2", + .coding = MPP_VIDEO_CodingMJPEG, + .ctx_size = sizeof(HalJpegeCtx), + .flag = 0, + .init = hal_jpege_vepu2_init, + .deinit = hal_jpege_vepu2_deinit, + .prepare = NULL, + .get_task = hal_jpege_vepu2_get_task, + .gen_regs = hal_jpege_vepu2_gen_regs, + .start = hal_jpege_vepu2_start, + .wait = hal_jpege_vepu2_wait, + .part_start = hal_jpege_vepu2_part_start, + .part_wait = hal_jpege_vepu2_part_wait, + .ret_task = hal_jpege_vepu2_ret_task, + .client = VPU_CLIENT_VEPU2, + .soc_type = { + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RV1108, + ROCKCHIP_SOC_RV1109, + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_jpege_vepu2) diff --git a/mpp/hal/vpu/jpege/hal_jpege_vepu2_v2.h b/mpp/hal/vpu/jpege/hal_jpege_vepu2_v2.h new file mode 100644 index 000000000..2f13b340c --- /dev/null +++ b/mpp/hal/vpu/jpege/hal_jpege_vepu2_v2.h @@ -0,0 +1,24 @@ +/* + * + * copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAL_JPEGE_VEPU2_V2_H +#define HAL_JPEGE_VEPU2_V2_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_jpege_vepu2; + +#endif diff --git a/mpp/hal/vpu/m2vd/CMakeLists.txt b/mpp/hal/vpu/m2vd/CMakeLists.txt new file mode 100644 index 000000000..717b85d3f --- /dev/null +++ b/mpp/hal/vpu/m2vd/CMakeLists.txt @@ -0,0 +1,11 @@ +# vim: syntax=cmake + +# hal mpeg2 decoder sourse +set(HAL_M2VD_SRC) + +add_hal_source(HAL_M2VD_SRC HAVE_VDPU1 hal_m2vd_vdpu1.c) +add_hal_source(HAL_M2VD_SRC HAVE_VDPU2 hal_m2vd_vdpu2.c) + +if(HAL_M2VD_SRC) + add_library(hal_mpeg2d_api OBJECT ${HAL_M2VD_SRC}) +endif() diff --git a/mpp/hal/vpu/m2vd/hal_m2vd_base.h b/mpp/hal/vpu/m2vd/hal_m2vd_base.h new file mode 100644 index 000000000..a07e16d16 --- /dev/null +++ b/mpp/hal/vpu/m2vd/hal_m2vd_base.h @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M2VD_BASE_H +#define HAL_M2VD_BASE_H + +#include + +#include "mpp_debug.h" + +#include "mpp_hal.h" +#include "mpp_buf_slot.h" +#include "mpp_device.h" + +#include "m2vd_syntax.h" + +#define M2VD_BUF_SIZE_QPTAB (256) +#define DEC_LITTLE_ENDIAN 1 +#define DEC_BIG_ENDIAN 0 +#define DEC_BUS_BURST_LENGTH_UNDEFINED 0 +#define DEC_BUS_BURST_LENGTH_4 5 +#define DEC_BUS_BURST_LENGTH_8 8 +#define DEC_BUS_BURST_LENGTH_16 16 + +#define M2VH_DBG_FUNCTION (0x00000001) +#define M2VH_DBG_REG (0x00000002) +#define M2VH_DBG_DUMP_REG (0x00000004) +#define M2VH_DBG_IRQ (0x00000008) + +extern RK_U32 hal_m2vd_debug; + +#define m2vh_dbg_func(tag) \ + do {\ + if (M2VH_DBG_FUNCTION & hal_m2vd_debug)\ + { mpp_log("%s: line(%d), func(%s)", tag, __LINE__, __FUNCTION__); }\ + } while (0) + +typedef enum M2VDPicCodingType_e { + M2VD_CODING_TYPE_I = 1, + M2VD_CODING_TYPE_P = 2, + M2VD_CODING_TYPE_B = 3, + M2VD_CODING_TYPE_D = 4 +} M2VDPicCodingType; + +typedef enum M2VDPicStruct_e { + M2VD_PIC_STRUCT_TOP_FIELD = 1, + M2VD_PIC_STRUCT_BOTTOM_FIELD = 2, + M2VD_PIC_STRUCT_FRAME = 3 +} M2VDPicStruct; + +typedef struct M2vdHalCtx_t { + MppHalCfg *cfg; + void *regs; + MppBuffer qp_table; + RK_U32 dec_frame_cnt; + FILE *fp_reg_in; + FILE *fp_reg_out; + RK_U32 reg_len; +} M2vdHalCtx; + +#endif // HAL_M2VD_BASE_H diff --git a/mpp/hal/vpu/m2vd/hal_m2vd_vdpu1.c b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu1.c new file mode 100644 index 000000000..fac0f45c0 --- /dev/null +++ b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu1.c @@ -0,0 +1,335 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_m2vd_vdpu1" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_env.h" + +#include "hal_m2vd_base.h" +#include "hal_m2vd_vdpu1_reg.h" +#include "hal_m2vd_vpu1.h" + +static MPP_RET hal_m2vd_vdpu1_deinit(void *hal); +static MPP_RET hal_m2vd_vdpu1_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *ctx = (M2vdHalCtx *)hal; + M2vdVdpu1Reg_t *regs = NULL; + + mpp_env_get_u32("hal_m2vd_debug", &hal_m2vd_debug, 0); + + mpp_assert(hal); + mpp_assert(cfg); + + regs = mpp_calloc(M2vdVdpu1Reg_t, 1); + if (NULL == regs) { + mpp_err_f("failed to malloc register ret\n"); + ret = MPP_ERR_MALLOC; + goto __ERR_RET; + } + + ctx->reg_len = M2VD_VDPU1_REG_NUM; + ctx->cfg = cfg; + ctx->regs = (void*)regs; + + if (!ctx->cfg || !ctx->cfg->dev || !ctx->cfg->buf_group) { + mpp_err_f("invalid cfg %p dev %p buf_group %p\n", ctx->cfg, + ctx->cfg ? ctx->cfg->dev : NULL, + ctx->cfg ? ctx->cfg->buf_group : NULL); + ret = MPP_ERR_NULL_PTR; + goto __ERR_RET; + } + + ret = mpp_buffer_get(ctx->cfg->buf_group, &ctx->qp_table, M2VD_BUF_SIZE_QPTAB); + if (ret) { + mpp_err("m2v_hal_qtable_base get buffer failed\n"); + goto __ERR_RET; + } + + return ret; + +__ERR_RET: + if (ctx) + hal_m2vd_vdpu1_deinit(ctx); + + return ret; +} + +static MPP_RET hal_m2vd_vdpu1_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *p = (M2vdHalCtx *)hal; + + if (p->qp_table) { + ret = mpp_buffer_put(p->qp_table); + p->qp_table = NULL; + if (MPP_OK != ret) { + mpp_err("m2v_hal qp_table put buffer failed\n"); + return ret; + } + } + + if (p->regs) { + mpp_free(p->regs); + p->regs = NULL; + } + + p->cfg = NULL; + + return ret; +} + +static MPP_RET hal_m2vd_vdpu1_init_hwcfg(M2vdHalCtx *ctx) +{ + M2vdVdpu1Reg_t *p_regs = (M2vdVdpu1Reg_t *)ctx->regs; + + memset(p_regs, 0, sizeof(M2vdVdpu1Reg_t)); + p_regs->sw02.dec_axi_rn_id = 0; + p_regs->sw02.dec_timeout_e = 1; + p_regs->sw02.dec_strswap32_e = 1; + p_regs->sw02.dec_strendian_e = 1; + p_regs->sw02.dec_inswap32_e = 1; + p_regs->sw02.dec_outswap32_e = 1; + + p_regs->sw02.dec_clk_gate_e = 1; + p_regs->sw02.dec_in_endian = 1; + p_regs->sw02.dec_out_endian = 1; + + p_regs->sw02.dec_out_tiled_e = 0; + p_regs->sw02.dec_max_burst = DEC_BUS_BURST_LENGTH_16; + p_regs->sw02.dec_scmd_dis = 0; + p_regs->sw02.dec_adv_pre_dis = 0; + p_regs->sw55.apf_threshold = 8; + p_regs->sw02.dec_latency = 0; + p_regs->sw02.dec_data_disc_e = 0; + p_regs->sw01.dec_irq = 0; + p_regs->sw02.dec_axi_rn_id = 0; + p_regs->sw03.dec_axi_wr_id = 0; + p_regs->sw03.dec_mode = 8; + + return MPP_OK; +} + +static MPP_RET hal_m2vd_vdpu1_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + + if (task->dec.valid) { + void *q_table = NULL; + MppBuffer streambuf = NULL; + MppBuffer framebuf = NULL; + M2vdHalCtx *ctx = (M2vdHalCtx *)hal; + M2VDDxvaParam *dx = (M2VDDxvaParam *)task->dec.syntax.data; + M2vdVdpu1Reg_t *p_regs = (M2vdVdpu1Reg_t*) ctx->regs; + + task->dec.valid = 0; + q_table = mpp_buffer_get_ptr(ctx->qp_table); + memcpy(q_table, dx->qp_tab, M2VD_BUF_SIZE_QPTAB); + mpp_buffer_sync_end(ctx->qp_table); + + hal_m2vd_vdpu1_init_hwcfg(ctx); + + p_regs->sw18.mv_accuracy_fwd = 1; + p_regs->sw18.mv_accuracy_bwd = 1; + if (dx->seq_ext_head_dec_flag) { + p_regs->sw03.dec_mode = 5; + p_regs->sw18.fcode_fwd_hor = dx->pic.full_pel_forward_vector; + p_regs->sw18.fcode_fwd_ver = dx->pic.forward_f_code; + p_regs->sw18.fcode_bwd_hor = dx->pic.full_pel_backward_vector; + p_regs->sw18.fcode_bwd_ver = dx->pic.backward_f_code; + } else { + p_regs->sw03.dec_mode = 6; + p_regs->sw18.fcode_fwd_hor = dx->pic.forward_f_code; + p_regs->sw18.fcode_fwd_ver = dx->pic.forward_f_code; + p_regs->sw18.fcode_bwd_hor = dx->pic.backward_f_code; + p_regs->sw18.fcode_bwd_ver = dx->pic.backward_f_code; + if (dx->pic.full_pel_forward_vector) + p_regs->sw18.mv_accuracy_fwd = 0; + if (dx->pic.full_pel_backward_vector) + p_regs->sw18.mv_accuracy_bwd = 0; + } + + p_regs->sw04.pic_mb_width = (dx->seq.decode_width + 15) >> 4; + p_regs->sw04.pic_mb_height_p = (dx->seq.decode_height + 15) >> 4; + p_regs->sw03.pic_interlace_e = 1 - dx->seq_ext.progressive_sequence; + if (dx->pic_code_ext.picture_structure == M2VD_PIC_STRUCT_FRAME) + p_regs->sw03.pic_fieldmode_e = 0; + else { + p_regs->sw03.pic_fieldmode_e = 1; + p_regs->sw03.pic_topfield_e = dx->pic_code_ext.picture_structure == 1; + } + if (dx->pic.picture_coding_type == M2VD_CODING_TYPE_B) + p_regs->sw03.pic_b_e = 1; + else + p_regs->sw03.pic_b_e = 0; + if (dx->pic.picture_coding_type == M2VD_CODING_TYPE_I) + p_regs->sw03.pic_inter_e = 0; + else + p_regs->sw03.pic_inter_e = 1; + + p_regs->sw04.topfieldfirst_e = dx->pic_code_ext.top_field_first; + p_regs->sw03.fwd_interlace_e = 0; + p_regs->sw03.write_mvs_e = 0; + p_regs->sw04.alt_scan_e = dx->pic_code_ext.alternate_scan; + p_regs->sw18.alt_scan_flag_e = dx->pic_code_ext.alternate_scan; + + p_regs->sw05.qscale_type = dx->pic_code_ext.q_scale_type; + p_regs->sw05.intra_dc_prec = dx->pic_code_ext.intra_dc_precision; + p_regs->sw05.con_mv_e = dx->pic_code_ext.concealment_motion_vectors; + p_regs->sw05.intra_vlc_tab = dx->pic_code_ext.intra_vlc_format; + p_regs->sw05.frame_pred_dct = dx->pic_code_ext.frame_pred_frame_dct; + p_regs->sw06.init_qp = 1; + + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + p_regs->sw12.rlc_vlc_base = mpp_buffer_get_fd(streambuf); + if (dx->bitstream_offset) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 12, dx->bitstream_offset); + } + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->CurrPic.Index7Bits, SLOT_BUFFER, &framebuf); + + if ((dx->pic_code_ext.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) || + (dx->pic_code_ext.picture_structure == M2VD_PIC_STRUCT_FRAME)) { + p_regs->sw13.dec_out_base = mpp_buffer_get_fd(framebuf); + } else { + p_regs->sw13.dec_out_base = mpp_buffer_get_fd(framebuf); + mpp_dev_set_reg_offset(ctx->cfg->dev, 13, MPP_ALIGN(dx->seq.decode_width, 16)); + } + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[0].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw14.refer0_base = mpp_buffer_get_fd(framebuf); + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[1].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw15.refer1_base = mpp_buffer_get_fd(framebuf); + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[2].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw16.refer2_base = mpp_buffer_get_fd(framebuf); + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[3].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw17.refer3_base = mpp_buffer_get_fd(framebuf); + + p_regs->sw40.qtable_base = mpp_buffer_get_fd(ctx->qp_table); + + p_regs->sw48.startmb_x = 0; + p_regs->sw48.startmb_y = 0; + p_regs->sw03.dec_out_dis = 0; + p_regs->sw03.filtering_dis = 1; + p_regs->sw06.stream_len = dx->bitstream_length; + p_regs->sw05.stream_start_bit = dx->bitstream_start_bit; + p_regs->sw01.dec_e = 1; + + task->dec.valid = 1; + ctx->dec_frame_cnt++; + } + + return ret; +} + +static MPP_RET hal_m2vd_vdpu1_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *ctx = (M2vdHalCtx *)hal; + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 *regs = (RK_U32 *)ctx->regs; + RK_U32 reg_size = sizeof(M2vdVdpu1Reg_t); + MppDev dev = ctx->cfg->dev; + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +static MPP_RET hal_m2vd_vdpu1_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *ctx = (M2vdHalCtx *)hal; + MppDev dev = ctx->cfg->dev; + M2vdVdpu1Reg_t* reg_out = (M2vdVdpu1Reg_t * )ctx->regs; + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (reg_out->sw01.dec_error_int | reg_out->sw01.dec_buffer_int) { + if (ctx->cfg->dec_cb) + mpp_callback(ctx->cfg->dec_cb, NULL); + } + + (void)task; + + return ret; +} + +const MppHalApi hal_m2vd_vdpu1 = { + .name = "m2vd_vdpu1", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMPEG2, + .ctx_size = sizeof(M2vdHalCtx), + .flag = 0, + .init = hal_m2vd_vdpu1_init, + .deinit = hal_m2vd_vdpu1_deinit, + .reg_gen = hal_m2vd_vdpu1_gen_regs, + .start = hal_m2vd_vdpu1_start, + .wait = hal_m2vd_vdpu1_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU1, + .soc_type = { + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_m2vd_vdpu1) diff --git a/mpp/hal/vpu/m2vd/hal_m2vd_vdpu1_reg.h b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu1_reg.h new file mode 100644 index 000000000..3cf6580ad --- /dev/null +++ b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu1_reg.h @@ -0,0 +1,210 @@ +/* + * Copyright 2018 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M2VD_VDPU1_REG_H +#define HAL_M2VD_VDPU1_REG_H + +#include "rk_type.h" + +#define M2VD_VDPU1_REG_NUM (101) + +typedef struct { + struct { + RK_U32 build_version : 3; + RK_U32 product_IDen : 1; + RK_U32 minor_version : 8; + RK_U32 major_version : 4; + RK_U32 product_numer : 16; + } sw00; + + struct { + RK_U32 dec_e : 1; + RK_U32 reserve0 : 3; + RK_U32 dec_irq_dis : 1; + RK_U32 reserve1 : 3; + RK_U32 dec_irq : 1; + RK_U32 reserve2 : 3; + RK_U32 dec_rdy_int : 1; + RK_U32 dec_bus_int : 1; + RK_U32 dec_buffer_int : 1; + RK_U32 dec_aso_int : 1; + RK_U32 dec_error_int : 1; + RK_U32 dec_slice_int : 1; + RK_U32 dec_timeout : 1; + RK_U32 reserve3 : 5; + RK_U32 dec_pic_inf : 1; + RK_U32 reserve4 : 7; + } sw01; + + struct { + RK_U32 dec_max_burst : 5; + RK_U32 dec_scmd_dis : 1; + RK_U32 dec_adv_pre_dis : 1; + RK_U32 priority_mode : 1; //chang + RK_U32 dec_out_endian : 1; + RK_U32 dec_in_endian : 1; + RK_U32 dec_clk_gate_e : 1; + RK_U32 dec_latency : 6; + RK_U32 dec_out_tiled_e : 1; + RK_U32 dec_data_disc_e : 1; + RK_U32 dec_outswap32_e : 1; + RK_U32 dec_inswap32_e : 1; + RK_U32 dec_strendian_e : 1; + RK_U32 dec_strswap32_e : 1; + RK_U32 dec_timeout_e : 1; + RK_U32 dec_axi_rn_id : 8; + } sw02; + + struct { + RK_U32 dec_axi_wr_id : 8; + RK_U32 dec_ahb_hlock_e : 1; + RK_U32 picord_count_e : 1; + RK_U32 seq_mbaff_e : 1; + RK_U32 reftopfirst_e : 1; + RK_U32 write_mvs_e : 1; + RK_U32 pic_fixed_quant : 1; + RK_U32 filtering_dis : 1; + RK_U32 dec_out_dis : 1; + RK_U32 ref_topfield_e : 1; + RK_U32 sorenson_e : 1; + RK_U32 fwd_interlace_e : 1; + RK_U32 pic_topfield_e : 1; + RK_U32 pic_inter_e : 1; + RK_U32 pic_b_e : 1; + RK_U32 pic_fieldmode_e : 1; + RK_U32 pic_interlace_e : 1; + RK_U32 pjpeg_e : 1; + RK_U32 divx3_e : 1; + RK_U32 skip_mode : 1; + RK_U32 rlc_mode_e : 1; + RK_U32 dec_mode : 4; + } sw03; + + struct { + RK_U32 ref_frames : 5; + RK_U32 topfieldfirst_e : 1; + RK_U32 alt_scan_e : 1; + RK_U32 mb_height_off : 4; + RK_U32 pic_mb_height_p : 8; + RK_U32 mb_width_off : 4; + RK_U32 pic_mb_width : 9; + } sw04; + + struct { + RK_U32 frame_pred_dct : 1; + RK_U32 intra_vlc_tab : 1; + RK_U32 intra_dc_prec : 2; + RK_U32 con_mv_e : 1; + RK_U32 reserve : 19; + RK_U32 qscale_type : 1; + RK_U32 reserve1 : 1; + RK_U32 stream_start_bit : 6; + } sw05; + + struct { + RK_U32 stream_len : 24; + RK_U32 ch_8pix_ileav_e : 1; + RK_U32 init_qp : 6; + RK_U32 start_code_e : 1; + } sw06; + + RK_U32 Reg07_11[5]; + + struct { + RK_U32 rlc_vlc_base : 32; + } sw12; + + struct { + RK_U32 dec_out_base : 32; + } sw13; + + struct { + RK_U32 refer0_base : 32; + } sw14; + + struct { + RK_U32 refer1_base : 32; + } sw15; + + struct { + RK_U32 refer2_base : 32; + } sw16; + + struct { + RK_U32 refer3_base : 32; + } sw17; + + struct { + RK_U32 reserve : 1; + RK_U32 mv_accuracy_bwd : 1; + RK_U32 mv_accuracy_fwd : 1; + RK_U32 fcode_bwd_ver : 4; + RK_U32 fcode_bwd_hor : 4; + RK_U32 fcode_fwd_ver : 4; + RK_U32 fcode_fwd_hor : 4; + RK_U32 alt_scan_flag_e : 1; + RK_U32 reserve1 : 12; + } sw18; + + RK_U32 sw19_39[21]; + + struct { + RK_U32 qtable_base : 32; + } sw40; + + struct { + RK_U32 dir_mv_base : 32; + } sw41; + + RK_U32 sw42_47[6]; + + struct { + RK_U32 reserve : 15; + RK_U32 startmb_y : 8; + RK_U32 startmb_x : 9; + } sw48; + + RK_U32 sw49_50[2]; + + struct { + RK_U32 refbu_y_offset : 9; + RK_U32 reserve0 : 3; + RK_U32 refbu_fparmod_e : 1; + RK_U32 refbu_eval_e : 1; + RK_U32 refbu_picid : 5; + RK_U32 refbu_thr : 12; + RK_U32 refbu_e : 1; + } sw51; + + struct { + RK_U32 refbu_intra_sum : 16; + RK_U32 refbu_hit_sum : 16; + } sw52; + + RK_U32 sw53_54[2]; + + struct { + RK_U32 apf_threshold : 14; + RK_U32 refbu2_picid : 5; + RK_U32 refbu2_thr : 12; + RK_U32 refbu2_buf_e : 1; + } sw55; + + RK_U32 sw56_100[45]; + +} M2vdVdpu1Reg_t; + +#endif // HAL_M2VD_VDPU1_REG_H diff --git a/mpp/hal/vpu/m2vd/hal_m2vd_vdpu2.c b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu2.c new file mode 100644 index 000000000..c2a61a1c5 --- /dev/null +++ b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu2.c @@ -0,0 +1,422 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_m2vd_vdpu2" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_env.h" + +#include "hal_m2vd_base.h" +#include "hal_m2vd_vdpu2_reg.h" +#include "hal_m2vd_vpu2.h" + +static MPP_RET hal_m2vd_vdpu2_deinit(void *hal); +static MPP_RET hal_m2vd_vdpu2_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *p = (M2vdHalCtx *)hal; + M2vdVdpu2Reg *reg = NULL; + + mpp_env_get_u32("hal_m2vd_debug", &hal_m2vd_debug, 0); + + mpp_assert(hal); + mpp_assert(cfg); + + m2vh_dbg_func("enter\n"); + + reg = mpp_calloc(M2vdVdpu2Reg, 1); + if (NULL == reg) { + mpp_err_f("failed to malloc register ret\n"); + ret = MPP_ERR_MALLOC; + goto __ERR_RET; + } + + p->reg_len = M2VD_VDPU2_REG_NUM; + p->cfg = cfg; + p->regs = (void*)reg; + + if (!p->cfg || !p->cfg->dev || !p->cfg->buf_group) { + mpp_err_f("invalid cfg %p dev %p buf_group %p\n", p->cfg, + p->cfg ? p->cfg->dev : NULL, + p->cfg ? p->cfg->buf_group : NULL); + ret = MPP_ERR_NULL_PTR; + goto __ERR_RET; + } + + ret = mpp_buffer_get(p->cfg->buf_group, &p->qp_table, M2VD_BUF_SIZE_QPTAB); + if (ret) { + mpp_err("m2v_hal qtable_base get buffer failed\n"); + goto __ERR_RET; + } + + if (M2VH_DBG_DUMP_REG & hal_m2vd_debug) { + p->fp_reg_in = fopen("/sdcard/m2vd_dbg_reg_in.txt", "wb"); + if (p->fp_reg_in == NULL) { + mpp_log("file open error: %s", "/sdcard/m2vd_dbg_reg_in.txt"); + } + p->fp_reg_out = fopen("/sdcard/m2vd_dbg_reg_out.txt", "wb"); + if (p->fp_reg_out == NULL) { + mpp_log("file open error: %s", "/sdcard/m2vd_dbg_reg_out.txt"); + } + } else { + p->fp_reg_in = NULL; + p->fp_reg_out = NULL; + } + + m2vh_dbg_func("leave\n"); + + return ret; + +__ERR_RET: + if (p) + hal_m2vd_vdpu2_deinit(p); + + return ret; +} + +static MPP_RET hal_m2vd_vdpu2_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *p = (M2vdHalCtx *)hal; + + m2vh_dbg_func("enter\n"); + + if (p->qp_table) { + ret = mpp_buffer_put(p->qp_table); + p->qp_table = NULL; + if (ret) { + mpp_err("m2v_hal qp_table put buffer failed\n"); + return ret; + } + } + + if (p->regs) { + mpp_free(p->regs); + p->regs = NULL; + } + + if (p->fp_reg_in) { + fclose(p->fp_reg_in); + p->fp_reg_in = NULL; + } + if (p->fp_reg_out) { + fclose(p->fp_reg_out); + p->fp_reg_out = NULL; + } + + p->cfg = NULL; + + m2vh_dbg_func("leave\n"); + return ret; +} + +static MPP_RET hal_m2vd_vdpu2_init_hwcfg(M2vdHalCtx *ctx) +{ + + M2vdVdpu2Reg *p_regs = (M2vdVdpu2Reg *)ctx->regs; + + memset(p_regs, 0, sizeof(M2vdVdpu2Reg)); + + p_regs->sw56.dec_axi_rn_id = 0; + p_regs->sw57.dec_timeout_e = 1; + p_regs->sw54.dec_strswap32_e = 1; //change + p_regs->sw54.dec_strendian_e = DEC_LITTLE_ENDIAN; + p_regs->sw54.dec_inswap32_e = 1; //change + p_regs->sw54.dec_outswap32_e = 1; //change + + + p_regs->sw57.dec_clk_gate_e = 1; //change + p_regs->sw54.dec_in_endian = DEC_LITTLE_ENDIAN; //change + p_regs->sw54.dec_out_endian = DEC_LITTLE_ENDIAN; + + p_regs->sw50.dec_out_tiled_e = 0; + p_regs->sw56.dec_max_burst = DEC_BUS_BURST_LENGTH_16; + p_regs->sw50.dec_scmd_dis = 0; + p_regs->sw50.dec_adv_pre_dis = 0; + p_regs->sw52.apf_threshold = 8; + + p_regs->sw50.dec_latency = 0; + p_regs->sw56.dec_data_disc_e = 0; + + p_regs->sw55.dec_irq = 0; + p_regs->sw56.dec_axi_rn_id = 0; + p_regs->sw56.dec_axi_wr_id = 0; + + p_regs->sw53.sw_dec_mode = 8; + + p_regs->ppReg[0] = 0; + p_regs->sw136.mv_accuracy_fwd = 1; + p_regs->sw136.mv_accuracy_bwd = 1; + + return MPP_OK; +} + +static MPP_RET hal_m2vd_vdpu2_gen_regs(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + + if (task->dec.valid) { + void *q_table = NULL; + MppBuffer streambuf = NULL; + MppBuffer framebuf = NULL; + M2vdHalCtx *ctx = (M2vdHalCtx *)hal; + M2VDDxvaParam *dx = (M2VDDxvaParam *)task->dec.syntax.data; + M2vdVdpu2Reg *p_regs = ctx->regs; + + task->dec.valid = 0; + q_table = mpp_buffer_get_ptr(ctx->qp_table); + memcpy(q_table, dx->qp_tab, M2VD_BUF_SIZE_QPTAB); + mpp_buffer_sync_end(ctx->qp_table); + + hal_m2vd_vdpu2_init_hwcfg(ctx); + + p_regs->sw136.mv_accuracy_fwd = 1; + p_regs->sw136.mv_accuracy_bwd = 1; + if (dx->seq_ext_head_dec_flag) { + p_regs->sw53.sw_dec_mode = 5; + p_regs->sw136.fcode_fwd_hor = dx->pic.full_pel_forward_vector; + p_regs->sw136.fcode_fwd_ver = dx->pic.forward_f_code; + p_regs->sw136.fcode_bwd_hor = dx->pic.full_pel_backward_vector; + p_regs->sw136.fcode_bwd_ver = dx->pic.backward_f_code; + + } else { + p_regs->sw53.sw_dec_mode = 6; + p_regs->sw136.fcode_fwd_hor = dx->pic.forward_f_code; + p_regs->sw136.fcode_fwd_ver = dx->pic.forward_f_code; + p_regs->sw136.fcode_bwd_hor = dx->pic.backward_f_code; + p_regs->sw136.fcode_bwd_ver = dx->pic.backward_f_code; + if (dx->pic.full_pel_forward_vector) + p_regs->sw136.mv_accuracy_fwd = 0; + if (dx->pic.full_pel_backward_vector) + p_regs->sw136.mv_accuracy_bwd = 0; + } + + p_regs->sw120.pic_mb_width = (dx->seq.decode_width + 15) >> 4; + p_regs->sw120.pic_mb_height_p = (dx->seq.decode_height + 15) >> 4; + p_regs->sw57.pic_interlace_e = 1 - dx->seq_ext.progressive_sequence; + if (dx->pic_code_ext.picture_structure == M2VD_PIC_STRUCT_FRAME) + p_regs->sw57.pic_fieldmode_e = 0; + else { + p_regs->sw57.pic_fieldmode_e = 1; + p_regs->sw57.pic_topfield_e = dx->pic_code_ext.picture_structure == 1; + } + if (dx->pic.picture_coding_type == M2VD_CODING_TYPE_B) + p_regs->sw57.pic_b_e = 1; + else + p_regs->sw57.pic_b_e = 0; + if (dx->pic.picture_coding_type == M2VD_CODING_TYPE_I) + p_regs->sw57.pic_inter_e = 0; + else + p_regs->sw57.pic_inter_e = 1; + + p_regs->sw120.topfieldfirst_e = dx->pic_code_ext.top_field_first; + p_regs->sw57.fwd_interlace_e = 0; + p_regs->sw57.write_mvs_e = 0;//concealment_motion_vectors; + p_regs->sw120.alt_scan_e = dx->pic_code_ext.alternate_scan; + p_regs->sw136.alt_scan_flag_e = dx->pic_code_ext.alternate_scan; + + p_regs->sw122.qscale_type = dx->pic_code_ext.q_scale_type; + p_regs->sw122.intra_dc_prec = dx->pic_code_ext.intra_dc_precision; + p_regs->sw122.con_mv_e = dx->pic_code_ext.concealment_motion_vectors; + p_regs->sw122.intra_vlc_tab = dx->pic_code_ext.intra_vlc_format; + p_regs->sw122.frame_pred_dct = dx->pic_code_ext.frame_pred_frame_dct; + p_regs->sw51.init_qp = 1; + + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + p_regs->sw64.VLC_base = mpp_buffer_get_fd(streambuf); + if (dx->bitstream_offset) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 64, dx->bitstream_offset); + } + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->CurrPic.Index7Bits, SLOT_BUFFER, &framebuf); + + + if ((dx->pic_code_ext.picture_structure == M2VD_PIC_STRUCT_TOP_FIELD) || + (dx->pic_code_ext.picture_structure == M2VD_PIC_STRUCT_FRAME)) { + p_regs->sw63.cur_pic_base = mpp_buffer_get_fd(framebuf); //just index need map + } else { + p_regs->sw63.cur_pic_base = mpp_buffer_get_fd(framebuf); + mpp_dev_set_reg_offset(ctx->cfg->dev, 63, MPP_ALIGN(dx->seq.decode_width, 16)); + } + + //ref & qtable config + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[0].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw131.ref0 = mpp_buffer_get_fd(framebuf); //just index need map + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[1].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw148.ref1 = mpp_buffer_get_fd(framebuf); //just index need map + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[2].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw134.ref2 = mpp_buffer_get_fd(framebuf); //just index need map + + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, dx->frame_refs[3].Index7Bits, SLOT_BUFFER, &framebuf); + p_regs->sw135.ref3 = mpp_buffer_get_fd(framebuf); //just index need map + + p_regs->sw61.slice_table = mpp_buffer_get_fd(ctx->qp_table); + + p_regs->sw52.startmb_x = 0; + p_regs->sw52.startmb_y = 0; + p_regs->sw57.dec_out_dis = 0; + p_regs->sw50.filtering_dis = 1; + + p_regs->sw51.stream_len = dx->bitstream_length; + p_regs->sw122.stream_start_bit = dx->bitstream_start_bit; + p_regs->sw57.dec_e = 1; + + if (M2VH_DBG_REG & hal_m2vd_debug) { + RK_U32 j = 0; + RK_U32 *p_reg = (RK_U32 *)p_regs; + for (j = 50; j < 159; j++) { + mpp_log("reg[%d] = 0x%08x", j, p_reg[j]); + } + } + if (ctx->fp_reg_in) { + int k = 0; + RK_U32 *p_reg = (RK_U32*)p_regs; + mpp_log("fwrite regs start"); + fprintf(ctx->fp_reg_in, "Frame #%d\n", ctx->dec_frame_cnt); + for (k = 0; k < M2VD_VDPU2_REG_NUM; k++) + fprintf(ctx->fp_reg_in, "[(D)%03d, (X)%03x] %08x\n", k, k, p_reg[k]); + fflush(ctx->fp_reg_in); + } + + task->dec.valid = 1; + ctx->dec_frame_cnt++; + } + return ret; + +} + +static MPP_RET hal_m2vd_vdpu2_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *ctx = (M2vdHalCtx *)hal; + + m2vh_dbg_func("enter\n"); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 *regs = (RK_U32 *)ctx->regs; + RK_U32 reg_size = sizeof(M2vdVdpu2Reg); + MppDev dev = ctx->cfg->dev; + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + m2vh_dbg_func("leave\n"); + return ret; +} + +static MPP_RET hal_m2vd_vdpu2_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + M2vdHalCtx *ctx = (M2vdHalCtx *)hal; + MppDev dev = ctx->cfg->dev; + M2vdVdpu2Reg* reg_out = (M2vdVdpu2Reg * )ctx->regs; + + m2vh_dbg_func("enter\n"); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (ctx->fp_reg_out) { + int k = 0; + RK_U32 *p_reg = (RK_U32*)®_out; + fprintf(ctx->fp_reg_out, "Frame #%d\n", ctx->dec_frame_cnt); + for (k = 0; k < M2VD_VDPU2_REG_NUM; k++) + fprintf(ctx->fp_reg_out, "[(D)%03d, (X)%03x] %08x\n", k, k, p_reg[k]); + fflush(ctx->fp_reg_out); + } + if (reg_out->sw55.dec_error_int | reg_out->sw55.dec_buffer_int) { + if (ctx->cfg->dec_cb) + mpp_callback(ctx->cfg->dec_cb, NULL); + } + + if (M2VH_DBG_IRQ & hal_m2vd_debug) + mpp_log("mpp_device_wait_reg return interrupt:%08x", reg_out->sw55); + + (void)task; + m2vh_dbg_func("leave\n"); + return ret; +} + +const MppHalApi hal_m2vd_vdpu2 = { + .name = "m2vd_vdpu2", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMPEG2, + .ctx_size = sizeof(M2vdHalCtx), + .flag = 0, + .init = hal_m2vd_vdpu2_init, + .deinit = hal_m2vd_vdpu2_deinit, + .reg_gen = hal_m2vd_vdpu2_gen_regs, + .start = hal_m2vd_vdpu2_start, + .wait = hal_m2vd_vdpu2_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_m2vd_vdpu2) diff --git a/mpp/hal/vpu/m2vd/hal_m2vd_vdpu2_reg.h b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu2_reg.h new file mode 100644 index 000000000..417210368 --- /dev/null +++ b/mpp/hal/vpu/m2vd/hal_m2vd_vdpu2_reg.h @@ -0,0 +1,206 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M2VD_VDPU2_REG_H +#define HAL_M2VD_VDPU2_REG_H + +#include "rk_type.h" + +#define M2VD_VDPU2_REG_NUM 159 + +typedef struct M2vdVdpu2Reg_t { + RK_U32 ppReg[50]; + + struct { + RK_U32 dec_out_tiled_e : 1; + RK_U32 dec_latency : 6; + RK_U32 pic_fixed_quant : 1; + RK_U32 filtering_dis : 1; + RK_U32 skip_mode : 1; + RK_U32 dec_scmd_dis : 1; + RK_U32 dec_adv_pre_dis : 1; + RK_U32 priority_mode : 1; //chang + RK_U32 refbu2_thr : 12; + RK_U32 refbu2_picid : 5; + RK_U32 reserve1 : 2; + } sw50; + + struct { + RK_U32 stream_len : 24; + RK_U32 reserve1 : 1; + RK_U32 init_qp : 6; + RK_U32 reserve2 : 1; + } sw51; + + struct { + RK_U32 startmb_y : 8; + RK_U32 startmb_x : 9; + RK_U32 apf_threshold : 14; + RK_U32 reserve : 1; + } sw52; + + struct { + RK_U32 sw_dec_mode; + } sw53; + + struct { + RK_U32 dec_in_endian : 1; + RK_U32 dec_out_endian : 1; + RK_U32 dec_inswap32_e : 1; + RK_U32 dec_outswap32_e : 1; + RK_U32 dec_strswap32_e : 1; + RK_U32 dec_strendian_e : 1; + RK_U32 reserve3 : 26; + } sw54; + + struct { + RK_U32 dec_irq : 1; + RK_U32 dec_irq_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 dec_rdy_int : 1; + RK_U32 dec_bus_int : 1; + RK_U32 dec_buffer_int : 1; + RK_U32 reserve1 : 1; + RK_U32 dec_aso_int : 1; + RK_U32 dec_slice_int : 1; + RK_U32 dec_pic_inf : 1; + RK_U32 reserve2 : 1; + RK_U32 dec_error_int : 1; + RK_U32 dec_timeout : 1; + RK_U32 reserve3 : 18; + } sw55; + + struct { + RK_U32 dec_axi_rn_id : 8; + RK_U32 dec_axi_wr_id : 8; + RK_U32 dec_max_burst : 5; + RK_U32 resever : 1; + RK_U32 dec_data_disc_e : 1; + RK_U32 resever1 : 9; + } sw56; + + struct { + RK_U32 dec_e : 1; + RK_U32 refbu2_buf_e : 1; + RK_U32 dec_out_dis : 1; + RK_U32 resever : 1; + RK_U32 dec_clk_gate_e : 1; + RK_U32 dec_timeout_e : 1; + RK_U32 picord_count_e : 1; + RK_U32 seq_mbaff_e : 1; + RK_U32 reftopfirst_e : 1; + RK_U32 ref_topfield_e : 1; + RK_U32 write_mvs_e : 1; + RK_U32 sorenson_e : 1; + RK_U32 fwd_interlace_e : 1; + RK_U32 pic_topfield_e : 1; + RK_U32 pic_inter_e : 1; + RK_U32 pic_b_e : 1; + RK_U32 pic_fieldmode_e : 1; + RK_U32 pic_interlace_e : 1; + RK_U32 pjpeg_e : 1; + RK_U32 divx3_e : 1; + RK_U32 rlc_mode_e : 1; + RK_U32 ch_8pix_ileav_e : 1; + RK_U32 start_code_e : 1; + RK_U32 resever1 : 8; + RK_U32 dec_ahb_hlock_e : 1; + + } sw57; + + RK_U32 reserve0[3]; + + struct { + RK_U32 slice_table; + } sw61; + + struct { + RK_U32 directmv_reg; + } sw62; + + struct { + RK_U32 cur_pic_base; + } sw63; + + struct { + RK_U32 VLC_base; + } sw64; + + RK_U32 reserve1[55]; + + struct { + RK_U32 ref_frames : 5; + RK_U32 topfieldfirst_e : 1; + RK_U32 alt_scan_e : 1; + RK_U32 mb_height_off : 4; + RK_U32 pic_mb_height_p : 8; + RK_U32 mb_width_off : 4; + RK_U32 pic_mb_width : 9; + } sw120; + + RK_U32 reserve2; + + struct { + RK_U32 frame_pred_dct : 1; + RK_U32 intra_vlc_tab : 1; + RK_U32 intra_dc_prec : 2; + RK_U32 con_mv_e : 1; + RK_U32 reserve : 19; + RK_U32 qscale_type : 1; + RK_U32 reserve1 : 1; + RK_U32 stream_start_bit : 6; + } sw122; + + RK_U32 reserve3[8]; + + struct { + RK_U32 ref0; + } sw131; + + RK_U32 reserve4[2]; + + struct { + RK_U32 ref2; + } sw134; + + struct { + RK_U32 ref3; + } sw135; + + struct { + RK_U32 reserve : 1; + RK_U32 mv_accuracy_bwd : 1; + RK_U32 mv_accuracy_fwd : 1; + RK_U32 fcode_bwd_ver : 4; + RK_U32 fcode_bwd_hor : 4; + RK_U32 fcode_fwd_ver : 4; + RK_U32 fcode_fwd_hor : 4; + RK_U32 alt_scan_flag_e : 1; + RK_U32 reserve1 : 12; + } sw136; + + RK_U32 reserve5[11]; + + struct { + RK_U32 ref1; + + } sw148; + + RK_U32 reserve6[10]; + +} M2vdVdpu2Reg; + +#endif diff --git a/mpp/hal/vpu/m2vd/hal_m2vd_vpu1.h b/mpp/hal/vpu/m2vd/hal_m2vd_vpu1.h new file mode 100644 index 000000000..327f2beb0 --- /dev/null +++ b/mpp/hal/vpu/m2vd/hal_m2vd_vpu1.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_MV2D_VPU1_H +#define HAL_MV2D_VPU1_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_m2vd_vdpu1; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_MV2D_VPU1_H */ diff --git a/mpp/hal/vpu/m2vd/hal_m2vd_vpu2.h b/mpp/hal/vpu/m2vd/hal_m2vd_vpu2.h new file mode 100644 index 000000000..5b8dea350 --- /dev/null +++ b/mpp/hal/vpu/m2vd/hal_m2vd_vpu2.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_MV2D_VPU2_H +#define HAL_MV2D_VPU2_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi hal_m2vd_vdpu2; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_MV2D_VPU2_H */ diff --git a/mpp/hal/vpu/mpg4d/CMakeLists.txt b/mpp/hal/vpu/mpg4d/CMakeLists.txt new file mode 100644 index 000000000..fb8a32479 --- /dev/null +++ b/mpp/hal/vpu/mpg4d/CMakeLists.txt @@ -0,0 +1,13 @@ +# vim: syntax=cmake + +# hal mpeg4 decoder sourse +set(HAL_MPEG4D_SRC + hal_m4vd_com.c + ) + +add_hal_source(HAL_MPEG4D_SRC HAVE_VDPU1 hal_m4vd_vdpu1.c) +add_hal_source(HAL_MPEG4D_SRC HAVE_VDPU2 hal_m4vd_vdpu2.c) + +if (HAL_MPEG4D_SRC) + add_library(hal_mpeg4d_api OBJECT ${HAL_MPEG4D_SRC}) +endif() diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_com.c b/mpp/hal/vpu/mpg4d/hal_m4vd_com.c new file mode 100644 index 000000000..50892eaef --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_com.c @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mpp_debug.h" +#include "hal_m4vd_com.h" + +RK_U8 default_intra_matrix[64] = { + 8, 17, 18, 19, 21, 23, 25, 27, + 17, 18, 19, 21, 23, 25, 27, 28, + 20, 21, 22, 23, 24, 26, 28, 30, + 21, 22, 23, 24, 26, 28, 30, 32, + 22, 23, 24, 26, 28, 30, 32, 35, + 23, 24, 26, 28, 30, 32, 35, 38, + 25, 26, 28, 30, 32, 35, 38, 41, + 27, 28, 30, 32, 35, 38, 41, 45 +}; + +RK_U8 default_inter_matrix[64] = { + 16, 17, 18, 19, 20, 21, 22, 23, + 17, 18, 19, 20, 21, 22, 23, 24, + 18, 19, 20, 21, 22, 23, 24, 25, + 19, 20, 21, 22, 23, 24, 26, 27, + 20, 21, 22, 23, 25, 26, 27, 28, + 21, 22, 23, 24, 26, 27, 28, 30, + 22, 23, 24, 26, 27, 28, 30, 31, + 23, 24, 25, 27, 28, 30, 31, 33 +}; + +void vpu_mpg4d_get_buffer_by_index(hal_mpg4_ctx *ctx, RK_S32 index, MppBuffer *buffer) +{ + if (index >= 0) { + mpp_buf_slot_get_prop(ctx->cfg->frame_slots, index, SLOT_BUFFER, buffer); + mpp_assert(*buffer); + } +} diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_com.h b/mpp/hal/vpu/mpg4d/hal_m4vd_com.h new file mode 100644 index 000000000..22ab1b2a9 --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_com.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M4VD_COM_H +#define HAL_M4VD_COM_H + +#include "mpp_hal.h" +#include "mpp_device.h" + +#include "mpg4d_syntax.h" + +#define MPG4D_HAL_DBG_REG_PUT (0x00000001) +#define MPG4D_HAL_DBG_REG_GET (0x00000002) + +extern RK_U32 hal_mpg4d_debug; + +#define MPEG4_MAX_MV_BUF_SIZE ((1920/16)*(1088/16)*4*sizeof(RK_U32)) + +typedef struct mpeg4d_reg_context { + MppHalCfg *cfg; + + // save fd for curr/ref0/ref1 for reg_gen + RK_S32 fd_curr; + RK_S32 fd_ref0; + RK_S32 fd_ref1; + RK_U32 bitstrm_len; + + // mv info buffer + // NOTE: mv buffer fix to 1080p size for convenience + MppBuffer mv_buf; + MppBuffer qp_table; + + void *regs; +} hal_mpg4_ctx; + +extern RK_U8 default_inter_matrix[64]; +extern RK_U8 default_intra_matrix[64]; + +extern void vpu_mpg4d_get_buffer_by_index(hal_mpg4_ctx *ctx, RK_S32 index, MppBuffer *buffer); + +#endif /* HAL_M4VD_COM_H */ diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1.c b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1.c new file mode 100644 index 000000000..cf7ad94d7 --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1.c @@ -0,0 +1,473 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_m4vd_vdpu1" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_buffer.h" +#include "mpp_common.h" + +#include "mpg4d_syntax.h" +#include "hal_m4vd_com.h" +#include "hal_m4vd_vdpu1.h" +#include "hal_m4vd_vdpu1_reg.h" +#include "mpp_dec_cb_param.h" + +static MPP_RET vdpu1_mpg4d_deinit(void *hal); + +static void vdpu1_mpg4d_setup_regs_by_syntax(hal_mpg4_ctx *ctx, MppSyntax syntax) +{ + M4vdVdpu1Regs_t *regs = ctx->regs; + DXVA2_DecodeBufferDesc **data = syntax.data; + DXVA_PicParams_MPEG4_PART2 *pp = NULL; + DXVA_QmatrixData *qm = NULL; + RK_S32 mv_buf_fd = mpp_buffer_get_fd(ctx->mv_buf); + RK_U32 stream_length = 0; + RK_U32 stream_used = 0; + RK_U32 i; + + for (i = 0; i < syntax.number; i++) { + DXVA2_DecodeBufferDesc *desc = data[i]; + switch (desc->CompressedBufferType) { + case DXVA2_PictureParametersBufferType : { + pp = (DXVA_PicParams_MPEG4_PART2 *)desc->pvPVPState; + } break; + case DXVA2_InverseQuantizationMatrixBufferType : { + qm = (DXVA_QmatrixData *)desc->pvPVPState; + } break; + case DXVA2_BitStreamDateBufferType : { + stream_length = desc->DataSize; + stream_used = desc->DataOffset; + ctx->bitstrm_len = stream_length; + } break; + default : { + mpp_err_f("found invalid buffer descriptor type %d\n", desc->CompressedBufferType); + } break; + } + } + + mpp_assert(pp); + mpp_assert(qm); + mpp_assert(stream_length); + mpp_assert(stream_used); + + // copy qp table to buffer + { + RK_U8 *dst = (RK_U8 *)mpp_buffer_get_ptr(ctx->qp_table); + RK_U8 *src = (qm->bNewQmatrix[0] != 0) ? (qm->Qmatrix[0]) : (default_intra_matrix); + + memcpy(dst, src, 64); + dst += 64; + + src = (qm->bNewQmatrix[1] != 0) ? (qm->Qmatrix[1]) : (default_inter_matrix); + memcpy(dst, src, 64); + } + + regs->SwReg04.sw_pic_mb_width = (pp->vop_width + 15) >> 4; + regs->SwReg04.sw_pic_mb_hight_p = (pp->vop_height + 15) >> 4; + + if (pp->custorm_version == 4) { + regs->SwReg04.sw_mb_width_off = pp->vop_width & 0xf; + regs->SwReg04.sw_mb_height_off = pp->vop_height & 0xf; + } else { + regs->SwReg04.sw_mb_width_off = 0; + regs->SwReg04.sw_mb_height_off = 0; + } + + regs->SwReg03.sw_dec_mode = 1; + + /* note: When comparing bit 19 of reg136(that is sw_alt_scan_flag_e) with bit 6 of + ** reg120(that is sw_alt_scan_e), we may be confused about the function of + ** these two bits. According to C Model, just sw_alt_scan_flag_e is set, + ** but not sw_alt_scan_e. + */ + regs->SwReg18.sw_alt_scan_flag_e = pp->alternate_vertical_scan_flag; + regs->SwReg48.sw_startmb_x = 0; + regs->SwReg48.sw_startmb_y = 0; + regs->SwReg03.sw_filtering_dis = 1; + regs->SwReg18.sw_mpeg4_vc1_rc = pp->vop_rounding_type; + regs->SwReg05.sw_intradc_vlc_thr = pp->intra_dc_vlc_thr; + regs->SwReg06.sw_init_qp = pp->vop_quant; + regs->SwReg05.sw_sync_markers_e = 1; + + { + /* + * update stream base address here according to consumed bit length + * 1. hardware start address has to be 64 bit align + * 2. hardware need to know which is the start bit in + * 2. pass (10bit fd + (offset << 10)) register value to kernel + */ + RK_U32 val = regs->SwReg12.sw_rlc_vlc_base; + RK_U32 consumed_bytes = stream_used >> 3; + RK_U32 consumed_bytes_align = consumed_bytes & (~0x7); + RK_U32 start_bit_offset = stream_used & 0x3F; + RK_U32 left_bytes = stream_length - consumed_bytes_align; + + regs->SwReg12.sw_rlc_vlc_base = val; + if (consumed_bytes_align) + mpp_dev_set_reg_offset(ctx->cfg->dev, 12, consumed_bytes_align); + regs->SwReg05.sw_strm_start_bit = start_bit_offset; + regs->SwReg06.sw_stream_len = left_bytes; + } + regs->SwReg05.sw_vop_time_incr = pp->vop_time_increment_resolution; + + switch (pp->vop_coding_type) { + case MPEG4_B_VOP : { + RK_U32 time_bp = pp->time_bp; + RK_U32 time_pp = pp->time_pp; + + RK_U32 trb_per_trd_d0 = MPP_DIV((((RK_S64)(1 * time_bp + 0)) << 27) + 1 * (time_pp - 1), time_pp); + RK_U32 trb_per_trd_d1 = MPP_DIV((((RK_S64)(2 * time_bp + 1)) << 27) + 2 * (time_pp - 0), 2 * time_pp + 1); + RK_U32 trb_per_trd_dm1 = MPP_DIV((((RK_S64)(2 * time_bp - 1)) << 27) + 2 * (time_pp - 1), 2 * time_pp - 1); + + regs->SwReg03.sw_pic_b_e = 1; + regs->SwReg03.sw_pic_inter_e = 1; + regs->SwReg18.sw_mpeg4_vc1_rc = 0; + regs->SwReg14.sw_refer0_base = 1; + + mpp_assert(ctx->fd_ref1 >= 0); + if (ctx->fd_ref1 >= 0) { + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_ref1; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_ref1; + } else { + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_curr; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_curr; + } + + mpp_assert(ctx->fd_ref0 >= 0); + if (ctx->fd_ref0 >= 0) { + regs->SwReg16.sw_refer2_base = (RK_U32)ctx->fd_ref0; + regs->SwReg17.sw_refer3_base = (RK_U32)ctx->fd_ref0; + } else { + regs->SwReg16.sw_refer2_base = (RK_U32)ctx->fd_curr; + regs->SwReg17.sw_refer3_base = (RK_U32)ctx->fd_curr; + } + + regs->SwReg18.sw_fcode_fwd_hor = pp->vop_fcode_forward; + regs->SwReg18.sw_fcode_fwd_ver = pp->vop_fcode_forward; + regs->SwReg18.sw_fcode_bwd_hor = pp->vop_fcode_backward; + regs->SwReg18.sw_fcode_bwd_ver = pp->vop_fcode_backward; + regs->SwReg03.sw_write_mvs_e = 0; + regs->SwReg41.sw_dir_mv_base = mv_buf_fd; + regs->SwReg19.sw_refer5_base = trb_per_trd_d0; + regs->SwReg21.sw_refer7_base = trb_per_trd_d1; + regs->SwReg20.sw_refer6_base = trb_per_trd_dm1; + } break; + case MPEG4_P_VOP : { + regs->SwReg03.sw_pic_b_e = 0; + regs->SwReg03.sw_pic_inter_e = 1; + + if (ctx->fd_ref0 >= 0) { + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_ref0; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_ref0; + } else { + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_curr; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_curr; + } + regs->SwReg16.sw_refer2_base = (RK_U32)ctx->fd_curr; + regs->SwReg17.sw_refer3_base = (RK_U32)ctx->fd_curr; + + regs->SwReg18.sw_fcode_fwd_hor = pp->vop_fcode_forward; + regs->SwReg18.sw_fcode_fwd_ver = pp->vop_fcode_forward; + regs->SwReg03.sw_write_mvs_e = 1; + regs->SwReg41.sw_dir_mv_base = mv_buf_fd; + } break; + case MPEG4_I_VOP : { + regs->SwReg03.sw_pic_b_e = 0; + regs->SwReg03.sw_pic_inter_e = 0; + + regs->SwReg14.sw_refer0_base = (RK_U32)ctx->fd_curr; + regs->SwReg15.sw_refer1_base = (RK_U32)ctx->fd_curr; + regs->SwReg16.sw_refer2_base = (RK_U32)ctx->fd_curr; + regs->SwReg17.sw_refer3_base = (RK_U32)ctx->fd_curr; + + regs->SwReg03.sw_write_mvs_e = 0; + regs->SwReg41.sw_dir_mv_base = mv_buf_fd; + + regs->SwReg18.sw_fcode_fwd_hor = 1; + regs->SwReg18.sw_fcode_fwd_ver = 1; + } break; + default : { + /* no nothing */ + } break; + } + + if (pp->interlaced) { + regs->SwReg03.sw_pic_interlace_e = 1; + regs->SwReg03.sw_pic_fieldmode_e = 0; + regs->SwReg04.sw_topfieldfirst_e = pp->top_field_first; + } + + regs->SwReg18.sw_prev_anc_type = pp->prev_coding_type; + regs->SwReg05.sw_type1_quant_e = pp->quant_type; + regs->SwReg40.sw_qtable_base = mpp_buffer_get_fd(ctx->qp_table); + regs->SwReg18.sw_mv_accuracy_fwd = pp->quarter_sample; + +} + +static MPP_RET vdpu1_mpg4d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + M4vdVdpu1Regs_t *regs = NULL; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + + mpp_assert(hal); + mpp_assert(cfg); + + mpp_env_get_u32("hal_mpg4d_debug", &hal_mpg4d_debug, 0); + + ctx->cfg = cfg; + if (!cfg->dev || !cfg->buf_group) { + mpp_err_f("invalid cfg dev %p buf_group %p\n", cfg->dev, cfg->buf_group); + return MPP_ERR_NULL_PTR; + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->mv_buf, MPEG4_MAX_MV_BUF_SIZE); + if (ret) { + mpp_err_f("failed to get mv buffer ret %d\n", ret); + goto ERR_RET; + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->qp_table, 64 * 2 * sizeof(RK_U8)); + if (ret) { + mpp_err_f("failed to get qp talbe buffer ret %d\n", ret); + goto ERR_RET; + } + + regs = mpp_calloc(M4vdVdpu1Regs_t, 1); + if (NULL == regs) { + mpp_err_f("failed to malloc register ret\n"); + ret = MPP_ERR_MALLOC; + goto ERR_RET; + } + + ctx->regs = regs; + + return ret; + +ERR_RET: + vdpu1_mpg4d_deinit(ctx); + return ret; +} + +static MPP_RET vdpu1_mpg4d_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + + mpp_assert(hal); + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + if (ctx->qp_table) { + mpp_buffer_put(ctx->qp_table); + ctx->qp_table = NULL; + } + + if (ctx->mv_buf) { + mpp_buffer_put(ctx->mv_buf); + ctx->mv_buf = NULL; + } + + ctx->cfg = NULL; + + return ret; +} + +static MPP_RET vdpu1_mpg4d_gen_regs(void *hal, HalTaskInfo *syn) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + HalDecTask *task = &syn->dec; + MppBuffer buf_frm_curr = NULL; + MppBuffer buf_frm_ref0 = NULL; + MppBuffer buf_frm_ref1 = NULL; + MppBuffer buf_pkt = NULL; + M4vdVdpu1Regs_t *regs = ctx->regs; + + mpp_assert(task->valid); + mpp_assert(task->input >= 0); + mpp_assert(task->output >= 0); + + memset(regs, 0, sizeof(M4vdVdpu1Regs_t)); + + /* + * basic register configuration setup here + */ + regs->SwReg02.sw_dec_out_endian = 1; + regs->SwReg02.sw_dec_in_endian = 1; + regs->SwReg02.sw_dec_inswap32_e = 1; + regs->SwReg02.sw_dec_outswap32_e = 1; + regs->SwReg02.sw_dec_strswap32_e = 1; + regs->SwReg02.sw_dec_strendian_e = 1; + regs->SwReg02.sw_dec_max_burst = 16; + regs->SwReg55.sw_apf_threshold = 1; + regs->SwReg02.sw_dec_timeout_e = 1; + regs->SwReg02.sw_dec_clk_gate_e = 1; + regs->SwReg01.sw_dec_en = 1; + regs->SwReg49.sw_pred_bc_tap_0_0 = -1; + regs->SwReg49.sw_pred_bc_tap_0_1 = 3; + regs->SwReg49.sw_pred_bc_tap_0_2 = -6; + regs->SwReg34.sw_pred_bc_tap_0_3 = 20; + + /* setup buffer for input / output / reference */ + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->input, SLOT_BUFFER, &buf_pkt); + mpp_assert(buf_pkt); + vpu_mpg4d_get_buffer_by_index(ctx, task->output, &buf_frm_curr); + vpu_mpg4d_get_buffer_by_index(ctx, task->refer[0], &buf_frm_ref0); + vpu_mpg4d_get_buffer_by_index(ctx, task->refer[1], &buf_frm_ref1); + + /* address registers setup first */ + ctx->fd_curr = mpp_buffer_get_fd(buf_frm_curr); + ctx->fd_ref0 = (buf_frm_ref0) ? (mpp_buffer_get_fd(buf_frm_ref0)) : (-1); + ctx->fd_ref1 = (buf_frm_ref1) ? (mpp_buffer_get_fd(buf_frm_ref1)) : (-1); + regs->SwReg13.dec_out_st_adr = (RK_U32)ctx->fd_curr; + regs->SwReg12.sw_rlc_vlc_base = mpp_buffer_get_fd(buf_pkt); + + /* setup other registers, here will update packet address */ + vdpu1_mpg4d_setup_regs_by_syntax(ctx, task->syntax); + /* memset tails to zero for stream buffer */ + { + RK_U8 *ptr = (RK_U8 *)mpp_buffer_get_ptr(buf_pkt); + RK_U32 strm_len = MPP_ALIGN(ctx->bitstrm_len, 16) + 64; + memset(ptr + ctx->bitstrm_len, 0, strm_len - ctx->bitstrm_len); + } + + return ret; +} + +static MPP_RET vdpu1_mpg4d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + MppDev dev = ctx->cfg->dev; + RK_U32* regs = (RK_U32 *)ctx->regs; + + if (hal_mpg4d_debug & MPG4D_HAL_DBG_REG_PUT) { + RK_U32 reg_count = (sizeof(M4vdVdpu1Regs_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 2; i < reg_count; i++) { + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = sizeof(M4vdVdpu1Regs_t); + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +static MPP_RET vdpu1_mpg4d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + MppDev dev = ctx->cfg->dev; + M4vdVdpu1Regs_t *regs = (M4vdVdpu1Regs_t *)ctx->regs; + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (hal_mpg4d_debug & MPG4D_HAL_DBG_REG_GET) { + RK_U32 reg_count = (sizeof(M4vdVdpu1Regs_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) { + mpp_log("reg[%03d]: %08x\n", i, ((RK_U32 *)regs)[i]); + } + } + if (ctx->cfg->dec_cb) { + DecCbHalDone param; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)ctx->regs; + param.hard_err = !regs->SwReg01.sw_dec_rdy_int; + + mpp_callback(ctx->cfg->dec_cb, ¶m); + } + + memset(®s->SwReg01, 0, sizeof(RK_U32)); + + (void)task; + return ret; +} + +const MppHalApi vdpu1_mpg4d = { + .name = "mpg4d_vdpu1", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMPEG4, + .ctx_size = sizeof(hal_mpg4_ctx), + .flag = 0, + .init = vdpu1_mpg4d_init, + .deinit = vdpu1_mpg4d_deinit, + .reg_gen = vdpu1_mpg4d_gen_regs, + .start = vdpu1_mpg4d_start, + .wait = vdpu1_mpg4d_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU1, + .soc_type = { + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(vdpu1_mpg4d) diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1.h b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1.h new file mode 100644 index 000000000..b6d1faabd --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M4VD_VDPU1_REG_H +#define HAL_M4VD_VDPU1_REG_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi vdpu1_mpg4d; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_M4VD_VDPU1_REG_H */ diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1_reg.h b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1_reg.h new file mode 100644 index 000000000..bd68cc119 --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu1_reg.h @@ -0,0 +1,276 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M4V_VDPU1_REG_TBL_H +#define HAL_M4V_VDPU1_REG_TBL_H + +#include "rk_type.h" + +/* Number registers for the decoder */ +#define DEC_VDPU1_REGISTERS (101) + +typedef struct { + RK_U32 SwReg00; + + struct { + RK_U32 sw_dec_en : 1; + RK_U32 reserve0 : 3; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve1 : 3; + RK_U32 sw_dec_irq : 1; + RK_U32 reserve2 : 3; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserve3 : 5; + RK_U32 sw_dec_pic_inf : 1; + RK_U32 reserve4 : 7; + } SwReg01; + + struct { + RK_U32 sw_dec_max_burst : 5; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_tiled_mode_lsb : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_tiled_mode_msb : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_dec_axi_rd_id : 8; + } SwReg02; + + struct { + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 reserve0 : 1; + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; + RK_U32 sw_skip_mode : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_dec_mode : 4; + } SwReg03; + + struct { + RK_U32 sw_reserve0 : 5; + RK_U32 sw_topfieldfirst_e : 1; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } SwReg04; + + struct { + RK_U32 sw_vop_time_incr : 16; + RK_U32 sw_intradc_vlc_thr : 3; + RK_U32 sw_ch_qp_offset : 5; + RK_U32 sw_type1_quant_e : 1; + RK_U32 sw_sync_markers_e : 1; + RK_U32 sw_strm_start_bit : 6; + } SwReg05; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_init_qp : 6; + RK_U32 sw_start_code_e : 1; + } SwReg06; + + struct { + RK_U32 sw_framenum : 16; + RK_U32 sw_framenum_len : 5; + RK_U32 reserve0 : 5; + RK_U32 sw_weight_bipr_idc : 2; + RK_U32 sw_weight_pred_e : 1; + RK_U32 sw_dir_8x8_infer_e : 1; + RK_U32 sw_blackwhite_e : 1; + RK_U32 sw_cabac_e : 1; + } SwReg07; + + struct { + RK_U32 sw_idr_pic_id : 16; + RK_U32 sw_idr_pic_e : 1; + RK_U32 sw_refpic_mk_len : 11; + RK_U32 sw_8x8trans_flag_e : 1; + RK_U32 sw_rdpic_cnt_pres : 1; + RK_U32 sw_filt_ctrl_pres : 1; + RK_U32 sw_const_intra_e : 1; + } SwReg08; + + struct { + RK_U32 sw_poc_length : 8; + RK_U32 reserve0 : 6; + RK_U32 sw_refidx0_active : 5; + RK_U32 sw_refidx1_active : 5; + RK_U32 sw_pps_id : 8; + } SwReg09; + + struct { + RK_U32 sw_diff_mv_base : 32; + } SwReg10; + + RK_U32 SwReg11; + + struct { + RK_U32 sw_rlc_vlc_base : 32; + } SwReg12; + + struct { + RK_U32 dec_out_st_adr : 32; + } SwReg13; + + /* MPP passes fd of reference frame to kernel + * with the whole register rather than higher 30-bit. + * At the same time, the lower 2-bit will be assigned + * by kernel. + * */ + struct { + //RK_U32 sw_refer0_topc_e : 1; + //RK_U32 sw_refer0_field_e : 1; + RK_U32 sw_refer0_base : 32; + } SwReg14; + + struct { + //RK_U32 sw_refer1_topc_e : 1; + //RK_U32 sw_refer1_field_e : 1; + RK_U32 sw_refer1_base : 32; + } SwReg15; + + struct { + //RK_U32 sw_refer2_topc_e : 1; + //RK_U32 sw_refer2_field_e : 1; + RK_U32 sw_refer2_base : 32; + } SwReg16; + + struct { + //RK_U32 sw_refer3_topc_e : 1; + //RK_U32 sw_refer3_field_e : 1; + RK_U32 sw_refer3_base : 32; + } SwReg17; + + struct { + RK_U32 sw_prev_anc_type : 1; + RK_U32 sw_mpeg4_vc1_rc : 1; + RK_U32 sw_mv_accuracy_fwd : 1; + RK_U32 sw_fcode_bwd_ver : 4; + RK_U32 sw_fcode_bwd_hor : 4; + RK_U32 sw_fcode_fwd_ver : 4; + RK_U32 sw_fcode_fwd_hor : 4; + RK_U32 sw_alt_scan_flag_e : 1; + RK_U32 reserve0 : 12; + } SwReg18; + + struct { + //RK_U32 sw_refer5_topc_e : 1; + //RK_U32 sw_refer5_field_e : 1; + RK_U32 sw_refer5_base : 32; + } SwReg19; + + struct { + //RK_U32 sw_refer6_topc_e : 1; + //RK_U32 sw_refer6_field_e : 1; + RK_U32 sw_refer6_base : 32; + } SwReg20; + + struct { + //RK_U32 sw_refer7_topc_e : 1; + //RK_U32 sw_refer7_field_e : 1; + RK_U32 sw_refer7_base : 32; + } SwReg21; + + + RK_U32 SwReg22_33[12]; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_1_1 : 10; + RK_U32 sw_pred_bc_tap_1_0 : 10; + RK_U32 sw_pred_bc_tap_0_3 : 10; + } SwReg34; + + RK_U32 SwReg35_39[5]; + + struct { + RK_U32 sw_qtable_base : 32; + } SwReg40; + + struct { + RK_U32 sw_dir_mv_base : 32; + } SwReg41; + + RK_U32 SwReg42_47[6]; + + struct { + RK_U32 reserve0 : 15; + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + } SwReg48; + + struct { + RK_U32 reserve0 : 2; + RK_U32 sw_pred_bc_tap_0_2 : 10; + RK_U32 sw_pred_bc_tap_0_1 : 10; + RK_U32 sw_pred_bc_tap_0_0 : 10; + } SwReg49; + + RK_U32 SwReg50; + + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 reserve0 : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } SwReg51; + + RK_U32 SwReg52_54[3]; + + struct { + RK_U32 sw_apf_threshold : 14; + RK_U32 reserve0 : 18; + } SwReg55; + + RK_U32 SwReg56_100[45]; +} M4vdVdpu1Regs_t; + +#endif /* HAL_M4V_VDPU1_REG_TBL_H */ diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2.c b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2.c new file mode 100644 index 000000000..a6c2fa2ce --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2.c @@ -0,0 +1,481 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_m4vd_vdpu2" + +#include +#include + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_buffer.h" +#include "mpp_common.h" + +#include "mpg4d_syntax.h" +#include "hal_m4vd_com.h" +#include "hal_m4vd_vdpu2.h" +#include "hal_m4vd_vdpu2_reg.h" +#include "mpp_dec_cb_param.h" + +static MPP_RET vdpu2_mpg4d_deinit(void *hal); + +static void vdpu2_mpg4d_setup_regs_by_syntax(hal_mpg4_ctx *ctx, MppSyntax syntax) +{ + M4vdVdpu2Regs_t *regs = ctx->regs; + DXVA2_DecodeBufferDesc **data = syntax.data; + DXVA_PicParams_MPEG4_PART2 *pp = NULL; + DXVA_QmatrixData *qm = NULL; + RK_S32 mv_buf_fd = mpp_buffer_get_fd(ctx->mv_buf); + RK_U32 stream_length = 0; + RK_U32 stream_used = 0; + RK_U32 i; + + for (i = 0; i < syntax.number; i++) { + DXVA2_DecodeBufferDesc *desc = data[i]; + switch (desc->CompressedBufferType) { + case DXVA2_PictureParametersBufferType : { + pp = (DXVA_PicParams_MPEG4_PART2 *)desc->pvPVPState; + } break; + case DXVA2_InverseQuantizationMatrixBufferType : { + qm = (DXVA_QmatrixData *)desc->pvPVPState; + } break; + case DXVA2_BitStreamDateBufferType : { + stream_length = desc->DataSize; + stream_used = desc->DataOffset; + ctx->bitstrm_len = stream_length; + } break; + default : { + mpp_err_f("found invalid buffer descriptor type %d\n", desc->CompressedBufferType); + } break; + } + } + + mpp_assert(pp); + mpp_assert(qm); + mpp_assert(stream_length); + mpp_assert(stream_used); + + // copy qp table to buffer + { + RK_U8 *dst = (RK_U8 *)mpp_buffer_get_ptr(ctx->qp_table); + RK_U8 *src = (qm->bNewQmatrix[0] != 0) ? (qm->Qmatrix[0]) : (default_intra_matrix); + + memcpy(dst, src, 64); + dst += 64; + + src = (qm->bNewQmatrix[1] != 0) ? (qm->Qmatrix[1]) : (default_inter_matrix); + memcpy(dst, src, 64); + } + + regs->reg120.sw_pic_mb_width = (pp->vop_width + 15) >> 4; + regs->reg120.sw_pic_mb_hight_p = (pp->vop_height + 15) >> 4; + if (pp->custorm_version == 4) { + regs->reg120.sw_mb_width_off = pp->vop_width & 0xf; + regs->reg120.sw_mb_height_off = pp->vop_height & 0xf; + } else { + regs->reg120.sw_mb_width_off = 0; + regs->reg120.sw_mb_height_off = 0; + } + regs->reg53_dec_mode = 1; + + /* note: When comparing bit 19 of reg136(that is sw_alt_scan_flag_e) with bit 6 of + ** reg120(that is sw_alt_scan_e), we may be confused about the function of + ** these two bits. According to C Model, just sw_alt_scan_flag_e is set, + ** but not sw_alt_scan_e. + */ + regs->reg136.sw_alt_scan_flag_e = pp->alternate_vertical_scan_flag; + regs->reg52_error_concealment.sw_xdim_mbst = 0; + regs->reg52_error_concealment.sw_ydim_mbst = 0; + regs->reg50_dec_ctrl.sw_dblk_flt_dis = 1; + regs->reg136.sw_rounding = pp->vop_rounding_type; + regs->reg122.sw_intradc_vlc_thr = pp->intra_dc_vlc_thr; + regs->reg51_stream_info.sw_qp_init_val = pp->vop_quant; + regs->reg122.sw_sync_markers_en = 1; + + { + /* + * update stream base address here according to consumed bit length + * 1. hardware start address has to be 64 bit align + * 2. hardware need to know which is the start bit in + * 2. pass (10bit fd + (offset << 10)) register value to kernel + */ + RK_U32 val = regs->reg64_input_stream_base; + RK_U32 consumed_bytes = stream_used >> 3; + RK_U32 consumed_bytes_align = consumed_bytes & (~0x7); + RK_U32 start_bit_offset = stream_used & 0x3F; + RK_U32 left_bytes = stream_length - consumed_bytes_align; + + regs->reg64_input_stream_base = val; + if (consumed_bytes_align) + mpp_dev_set_reg_offset(ctx->cfg->dev, 64, consumed_bytes_align); + regs->reg122.sw_stream_start_word = start_bit_offset; + regs->reg51_stream_info.sw_stream_len = left_bytes; + } + regs->reg122.sw_vop_time_incr = pp->vop_time_increment_resolution; + + switch (pp->vop_coding_type) { + case MPEG4_B_VOP : { + RK_U32 time_bp = pp->time_bp; + RK_U32 time_pp = pp->time_pp; + + RK_U32 trb_per_trd_d0 = MPP_DIV((((RK_S64)(1 * time_bp + 0)) << 27) + 1 * (time_pp - 1), time_pp); + RK_U32 trb_per_trd_d1 = MPP_DIV((((RK_S64)(2 * time_bp + 1)) << 27) + 2 * (time_pp - 0), 2 * time_pp + 1); + RK_U32 trb_per_trd_dm1 = MPP_DIV((((RK_S64)(2 * time_bp - 1)) << 27) + 2 * (time_pp - 1), 2 * time_pp - 1); + + regs->reg57_enable_ctrl.sw_pic_type_sel1 = 1; + regs->reg57_enable_ctrl.sw_pic_type_sel0 = 1; + regs->reg136.sw_rounding = 0; + regs->reg131_ref0_base = 1; + + mpp_assert(ctx->fd_ref1 >= 0); + if (ctx->fd_ref1 >= 0) { + regs->reg131_ref0_base = (RK_U32)ctx->fd_ref1; + regs->reg148_ref1_base = (RK_U32)ctx->fd_ref1; + } else { + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + } + + mpp_assert(ctx->fd_ref0 >= 0); + if (ctx->fd_ref0 >= 0) { + regs->reg134_ref2_base = (RK_U32)ctx->fd_ref0; + regs->reg135_ref3_base = (RK_U32)ctx->fd_ref0; + } else { + regs->reg134_ref2_base = (RK_U32)ctx->fd_curr; + regs->reg135_ref3_base = (RK_U32)ctx->fd_curr; + } + + regs->reg136.sw_hrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg136.sw_vrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg136.sw_hrz_bit_of_bwd_mv = pp->vop_fcode_backward; + regs->reg136.sw_vrz_bit_of_bwd_mv = pp->vop_fcode_backward; + regs->reg57_enable_ctrl.sw_dmmv_wr_en = 0; + regs->reg62_directmv_base = mv_buf_fd; + regs->reg137.sw_trb_per_trd_d0 = trb_per_trd_d0; + regs->reg139.sw_trb_per_trd_d1 = trb_per_trd_d1; + regs->reg138.sw_trb_per_trd_dm1 = trb_per_trd_dm1; + } break; + case MPEG4_P_VOP : { + regs->reg57_enable_ctrl.sw_pic_type_sel1 = 0; + regs->reg57_enable_ctrl.sw_pic_type_sel0 = 1; + + if (ctx->fd_ref0 >= 0) { + regs->reg131_ref0_base = (RK_U32)ctx->fd_ref0; + regs->reg148_ref1_base = (RK_U32)ctx->fd_ref0; + } else { + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + } + regs->reg134_ref2_base = (RK_U32)ctx->fd_curr; + regs->reg135_ref3_base = (RK_U32)ctx->fd_curr; + + regs->reg136.sw_hrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg136.sw_vrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg57_enable_ctrl.sw_dmmv_wr_en = 1; + regs->reg62_directmv_base = mv_buf_fd; + } break; + case MPEG4_I_VOP : { + regs->reg57_enable_ctrl.sw_pic_type_sel1 = 0; + regs->reg57_enable_ctrl.sw_pic_type_sel0 = 0; + + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + regs->reg134_ref2_base = (RK_U32)ctx->fd_curr; + regs->reg135_ref3_base = (RK_U32)ctx->fd_curr; + + regs->reg57_enable_ctrl.sw_dmmv_wr_en = 0; + regs->reg62_directmv_base = mv_buf_fd; + + regs->reg136.sw_hrz_bit_of_fwd_mv = 1; + regs->reg136.sw_vrz_bit_of_fwd_mv = 1; + } break; + default : { + /* no nothing */ + } break; + } + + if (pp->interlaced) { + regs->reg57_enable_ctrl.sw_curpic_code_sel = 1; + regs->reg57_enable_ctrl.sw_curpic_stru_sel = 0; + regs->reg120.sw_topfieldfirst_e = pp->top_field_first; + } + + regs->reg136.sw_prev_pic_type = pp->prev_coding_type; + regs->reg122.sw_quant_type_1_en = pp->quant_type; + regs->reg61_qtable_base = mpp_buffer_get_fd(ctx->qp_table); + regs->reg136.sw_fwd_mv_y_resolution = pp->quarter_sample; + +} + +static MPP_RET vdpu2_mpg4d_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + M4vdVdpu2Regs_t *regs = NULL; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + + mpp_assert(hal); + mpp_assert(cfg); + + mpp_env_get_u32("hal_mpg4d_debug", &hal_mpg4d_debug, 0); + + ctx->cfg = cfg; + if (!cfg->dev || !cfg->buf_group) { + mpp_err_f("invalid cfg dev %p buf_group %p\n", cfg->dev, cfg->buf_group); + return MPP_ERR_NULL_PTR; + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->mv_buf, MPEG4_MAX_MV_BUF_SIZE); + if (ret) { + mpp_err_f("failed to get mv buffer ret %d\n", ret); + goto ERR_RET; + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->qp_table, 64 * 2 * sizeof(RK_U8)); + if (ret) { + mpp_err_f("failed to get qp talbe buffer ret %d\n", ret); + goto ERR_RET; + } + + regs = mpp_calloc(M4vdVdpu2Regs_t, 1); + if (NULL == regs) { + mpp_err_f("failed to malloc register ret\n"); + ret = MPP_ERR_MALLOC; + goto ERR_RET; + } + + ctx->regs = regs; + + return ret; + +ERR_RET: + vdpu2_mpg4d_deinit(ctx); + return ret; +} + +static MPP_RET vdpu2_mpg4d_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + + mpp_assert(hal); + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + if (ctx->qp_table) { + mpp_buffer_put(ctx->qp_table); + ctx->qp_table = NULL; + } + + if (ctx->mv_buf) { + mpp_buffer_put(ctx->mv_buf); + ctx->mv_buf = NULL; + } + + ctx->cfg = NULL; + + return ret; +} + +static MPP_RET vdpu2_mpg4d_gen_regs(void *hal, HalTaskInfo *syn) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + HalDecTask *task = &syn->dec; + MppBuffer buf_frm_curr = NULL; + MppBuffer buf_frm_ref0 = NULL; + MppBuffer buf_frm_ref1 = NULL; + MppBuffer buf_pkt = NULL; + M4vdVdpu2Regs_t *regs = ctx->regs; + + mpp_assert(task->valid); + mpp_assert(task->input >= 0); + mpp_assert(task->output >= 0); + + memset(regs, 0, sizeof(M4vdVdpu2Regs_t)); + + /* + * basic register configuration setup here + */ + regs->reg54_endian.sw_dec_out_endian = 1; + regs->reg54_endian.sw_dec_in_endian = 1; + regs->reg54_endian.sw_dec_in_wordsp = 1; + regs->reg54_endian.sw_dec_out_wordsp = 1; + regs->reg54_endian.sw_dec_strswap32_e = 1; + regs->reg54_endian.sw_dec_strendian_e = 1; + regs->reg56_axi_ctrl.sw_dec_max_burlen = 16; + regs->reg52_error_concealment.sw_adv_pref_thrd = 1; + regs->reg57_enable_ctrl.sw_timeout_sts_en = 1; + regs->reg57_enable_ctrl.sw_dec_clkgate_en = 1; + regs->reg57_enable_ctrl.sw_dec_st_work = 1; + regs->reg59.sw_pflt_set0_tap0 = -1; + regs->reg59.sw_pflt_set0_tap1 = 3; + regs->reg59.sw_pflt_set0_tap2 = -6; + regs->reg153.sw_pred_bc_tap_0_3 = 20; + + /* setup buffer for input / output / reference */ + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->input, SLOT_BUFFER, &buf_pkt); + mpp_assert(buf_pkt); + vpu_mpg4d_get_buffer_by_index(ctx, task->output, &buf_frm_curr); + vpu_mpg4d_get_buffer_by_index(ctx, task->refer[0], &buf_frm_ref0); + vpu_mpg4d_get_buffer_by_index(ctx, task->refer[1], &buf_frm_ref1); + + /* address registers setup first */ + ctx->fd_curr = mpp_buffer_get_fd(buf_frm_curr); + ctx->fd_ref0 = (buf_frm_ref0) ? (mpp_buffer_get_fd(buf_frm_ref0)) : (-1); + ctx->fd_ref1 = (buf_frm_ref1) ? (mpp_buffer_get_fd(buf_frm_ref1)) : (-1); + regs->reg63_cur_pic_base = (RK_U32)ctx->fd_curr; + regs->reg64_input_stream_base = mpp_buffer_get_fd(buf_pkt); + + /* setup other registers, here will update packet address */ + vdpu2_mpg4d_setup_regs_by_syntax(ctx, task->syntax); + /* memset tails to zero for stream buffer */ + { + RK_U8 *ptr = (RK_U8 *)mpp_buffer_get_ptr(buf_pkt); + RK_U32 strm_len = MPP_ALIGN(ctx->bitstrm_len, 16) + 64; + memset(ptr + ctx->bitstrm_len, 0, strm_len - ctx->bitstrm_len); + } + + return ret; +} + +static MPP_RET vdpu2_mpg4d_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + MppDev dev = ctx->cfg->dev; + RK_U32* regs = (RK_U32 *)ctx->regs; + + if (hal_mpg4d_debug & MPG4D_HAL_DBG_REG_PUT) { + RK_U32 reg_count = (sizeof(M4vdVdpu2Regs_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) { + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = sizeof(M4vdVdpu2Regs_t); + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +static MPP_RET vdpu2_mpg4d_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + MppDev dev = ctx->cfg->dev; + M4vdVdpu2Regs_t *regs = (M4vdVdpu2Regs_t *)ctx->regs; + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + if (hal_mpg4d_debug & MPG4D_HAL_DBG_REG_GET) { + RK_U32 reg_count = (sizeof(M4vdVdpu2Regs_t) / sizeof(RK_U32)); + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) { + mpp_log("reg[%03d]: %08x\n", i, ((RK_U32 *)regs)[i]); + } + } + + if (ctx->cfg->dec_cb) { + DecCbHalDone param = { 0 }; + + if (!regs->reg55_Interrupt.sw_dec_rdy_int) + param.hard_err = 1; + + param.task = (void *)&task->dec; + param.regs = (RK_U32 *)ctx->regs; + + mpp_callback(ctx->cfg->dec_cb, ¶m); + } + + (void)task; + return ret; +} + +const MppHalApi vdpu2_mpg4d = { + .name = "mpg4d_vdpu2", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingMPEG4, + .ctx_size = sizeof(hal_mpg4_ctx), + .flag = 0, + .init = vdpu2_mpg4d_init, + .deinit = vdpu2_mpg4d_deinit, + .reg_gen = vdpu2_mpg4d_gen_regs, + .start = vdpu2_mpg4d_start, + .wait = vdpu2_mpg4d_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(vdpu2_mpg4d) diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2.h b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2.h new file mode 100644 index 000000000..891fca246 --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M4VD_VDPU2_REG_H +#define HAL_M4VD_VDPU2_REG_H + +#include "mpp_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppHalApi vdpu2_mpg4d; + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_M4VD_VDPU2_REG_H */ diff --git a/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2_reg.h b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2_reg.h new file mode 100644 index 000000000..4a2384efb --- /dev/null +++ b/mpp/hal/vpu/mpg4d/hal_m4vd_vdpu2_reg.h @@ -0,0 +1,397 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_M4V_VDPU2_REG_TBL_H +#define HAL_M4V_VDPU2_REG_TBL_H + +#include "rk_type.h" + +typedef struct { + RK_U32 reg00_49[50]; + + struct { + RK_U32 sw_dec_tiled_msb : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_dblk_flt_dis : 1; + RK_U32 sw_skip_sel : 1; + RK_U32 sw_dec_ascmd0_dis : 1; + RK_U32 sw_adv_pref_dis : 1; + RK_U32 sw_dec_tiled_lsb : 1; + RK_U32 sw_refbuf_thrd : 12; + RK_U32 sw_refbuf_pid : 5; + RK_U32 reserve1 : 2; + } reg50_dec_ctrl; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 reserve1 : 1; + RK_U32 sw_qp_init_val : 6; + RK_U32 reserve2 : 1; + } reg51_stream_info; + + struct { + RK_U32 sw_ydim_mbst : 8; + RK_U32 sw_xdim_mbst : 9; + RK_U32 sw_adv_pref_thrd : 14; + RK_U32 sw_reserve : 1; + } reg52_error_concealment; + + RK_U32 reg53_dec_mode; + + struct { + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_in_wordsp : 1; + RK_U32 sw_dec_out_wordsp : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 reserve3 : 26; + } reg54_endian; + + struct { + RK_U32 sw_dec_irq : 1; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_pp_bus_sts : 1; + RK_U32 sw_buf_emt_sts : 1; + RK_U32 reserve1 : 1; + RK_U32 sw_aso_det_sts : 1; + RK_U32 sw_slice_det_sts : 1; + RK_U32 sw_bslice_det_sts : 1; + RK_U32 reserve2 : 1; + RK_U32 sw_error_det_sts : 1; + RK_U32 sw_timeout_det_sts : 1; + RK_U32 reserve3 : 18; + } reg55_Interrupt; + + struct { + RK_U32 sw_dec_axi_id_rd : 8; + RK_U32 sw_dec_axi_id_wr : 8; + RK_U32 sw_dec_max_burlen : 5; + RK_U32 reserve0 : 1; + RK_U32 sw_dec_data_discd_en: 1; + RK_U32 reserve1 : 9; + } reg56_axi_ctrl; + + struct { + RK_U32 sw_dec_st_work : 1; + RK_U32 sw_refpic_buf2_en : 1; + RK_U32 sw_dec_wr_extmem_dis : 1; + RK_U32 reserve : 1; + RK_U32 sw_dec_clkgate_en : 1; + RK_U32 sw_timeout_sts_en : 1; + RK_U32 sw_rd_cnt_tab_en : 1; + RK_U32 sw_sequ_mbaff_en : 1; + RK_U32 sw_first_reftop_en : 1; + RK_U32 sw_reftop_en : 1; + RK_U32 sw_dmmv_wr_en : 1; + RK_U32 sw_sorspa_en : 1; + RK_U32 sw_fwd_refpic_mode_sel : 1; + RK_U32 sw_pic_decfield_sel : 1; + RK_U32 sw_pic_type_sel0 : 1; + RK_U32 sw_pic_type_sel1 : 1; + RK_U32 sw_curpic_stru_sel : 1; + RK_U32 sw_curpic_code_sel : 1; + RK_U32 sw_prog_jpeg_en : 1; + RK_U32 sw_divx3_en : 1; + RK_U32 sw_rlc_mode_en : 1; + RK_U32 sw_addit_ch_fmt_wen : 1; + RK_U32 sw_st_code_exist : 1; + RK_U32 reserve1 : 8; + RK_U32 sw_dec_timeout_mode : 1; + } reg57_enable_ctrl; + + struct { + RK_U32 sw_soft_rst : 1; + RK_U32 reverse0 : 31; + } reg58; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pflt_set0_tap2 : 10; + RK_U32 sw_pflt_set0_tap1 : 10; + RK_U32 sw_pflt_set0_tap0 : 10; + } reg59; + + RK_U32 reg60_addit_ch_st_base; + RK_U32 reg61_qtable_base; + RK_U32 reg62_directmv_base; + RK_U32 reg63_cur_pic_base; + RK_U32 reg64_input_stream_base; + + struct { + RK_U32 sw_refbuf_y_ofset : 9; + RK_U32 sw_reserve : 3; + RK_U32 sw_refbuf_fildpar_mod_e : 1; + RK_U32 sw_refbuf_idcal_e : 1; + RK_U32 sw_refbuf_picid : 5; + RK_U32 sw_refbu_thr_level : 12; + RK_U32 sw_refbu_e : 1; + } reg65_refpicbuf_ctrl; + + struct { + RK_U32 build_ver : 3; + RK_U32 ascii_id_en : 1; + RK_U32 minor_num : 8; + RK_U32 major_num : 4; + RK_U32 prod_id : 16; + } reg66_id; + + struct { + RK_U32 sw_reserve : 25; + RK_U32 rom_imp_type : 1; + RK_U32 rv_allow_flag : 2; + RK_U32 refbuf2_allow_flag : 1; + RK_U32 divx_allow_flag : 1; + RK_U32 refbuf_allow_flag : 1; + RK_U32 jpeg_allow_flag : 1; + } reg67_synthesis_cfg; + + struct { + RK_U32 sw_refbuf_sum_bot : 16; + RK_U32 sw_refbuf_sum_top : 16; + } reg68_sum_of_partitions; + + struct { + RK_U32 sw_luma_sum_intra : 16; + RK_U32 sw_refbuf_sum_hit : 16; + } reg69_sum_inf; + + struct { + RK_U32 sw_ycomp_mv_sum : 22; + RK_U32 sw_reserve : 10; + } reg70_sum_mv; + + RK_U32 reg71_119_reserve[49]; + + struct { + RK_U32 sw_reserve0 : 5; + RK_U32 sw_topfieldfirst_e : 1; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } reg120; + + struct { + RK_U32 sw_reserve : 5; + RK_U32 sw_vp7_version : 1; + RK_U32 sw_dc_match0 : 3; + RK_U32 sw_dc_match1 : 3; + RK_U32 sw_eable_bilinear : 1; + RK_U32 sw_remain_mv : 1; + RK_U32 sw_reserve1 : 6; + RK_U32 sw_dct2_start_bit : 6; + RK_U32 sw_dct1_start_bit : 6; + } reg121; + + struct { + RK_U32 sw_vop_time_incr : 16; + RK_U32 sw_intradc_vlc_thr : 3; + RK_U32 sw_ch_qp_offset : 5; + RK_U32 sw_quant_type_1_en : 1; + RK_U32 sw_sync_markers_en : 1; + RK_U32 sw_stream_start_word: 6; + } reg122; + + struct { + RK_U32 sw_dc_comp1 : 16; + RK_U32 sw_dc_comp0 : 16; + } reg123; + + struct { + RK_U32 sw_stream1_len : 24; + RK_U32 sw_coeffs_part_am : 4; + RK_U32 sw_reserve : 4; + } reg124; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_5_3 : 10; + RK_U32 sw_pred_bc_tap_5_2 : 10; + RK_U32 sw_pred_bc_tap_5_1 : 10; + } reg125; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_6_2 : 10; + RK_U32 sw_pred_bc_tap_6_1 : 10; + RK_U32 sw_pred_bc_tap_6_0 : 10; + } reg126; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_7_1 : 10; + RK_U32 sw_pred_bc_tap_7_0 : 10; + RK_U32 sw_pred_bc_tap_6_3 : 10; + } reg127; + + struct { + RK_U32 sw_pred_tap_6_4 : 2; + RK_U32 sw_pred_tap_6_M1 : 2; + RK_U32 sw_pred_tap_4_4 : 2; + RK_U32 sw_pred_tap_4_M1 : 2; + RK_U32 sw_pred_tap_2_4 : 2; + RK_U32 sw_pred_tap_2_M1 : 2; + RK_U32 sw_pred_bc_tap_7_3 : 10; + RK_U32 sw_pred_bc_tap_7_2 : 10; + } reg128; + + struct { + RK_U32 sw_filt_level_3 : 6; + RK_U32 sw_filt_level_2 : 6; + RK_U32 sw_filt_level_1 : 6; + RK_U32 sw_filt_level_0 : 6; + RK_U32 reserve : 8; + } reg129; + + struct { + RK_U32 sw_quant_1 : 11; + RK_U32 sw_quant_0 : 11; + RK_U32 sw_quant_delta_1 : 5; + RK_U32 sw_quant_delta_0 : 5; + } reg130; + + + RK_U32 reg131_ref0_base; + + struct { + RK_U32 sw_filt_mb_adj_3 : 7; + RK_U32 sw_filt_mb_adj_2 : 7; + RK_U32 sw_filt_mb_adj_1 : 7; + RK_U32 sw_filt_mb_adj_0 : 7; + RK_U32 sw_filt_sharpness : 3; + RK_U32 sw_filt_type : 1; + } reg132; + + + struct { + RK_U32 sw_filt_ref_adj_3 : 7; + RK_U32 sw_filt_ref_adj_2 : 7; + RK_U32 sw_filt_ref_adj_1 : 7; + RK_U32 sw_filt_ref_adj_0 : 7; + RK_U32 sw_reserve : 4; + } reg133; + + RK_U32 reg134_ref2_base; + RK_U32 reg135_ref3_base; + + struct { + RK_U32 sw_prev_pic_type : 1; + RK_U32 sw_rounding : 1; + RK_U32 sw_fwd_mv_y_resolution : 1; + RK_U32 sw_vrz_bit_of_bwd_mv : 4; + RK_U32 sw_hrz_bit_of_bwd_mv : 4; + RK_U32 sw_vrz_bit_of_fwd_mv : 4; + RK_U32 sw_hrz_bit_of_fwd_mv : 4; + RK_U32 sw_alt_scan_flag_e : 1; + RK_U32 sw_reserve : 12; + } reg136; + + struct { + RK_U32 sw_trb_per_trd_d0 : 27; + RK_U32 sw_reserve : 5; + } reg137; + + struct { + RK_U32 sw_trb_per_trd_dm1 : 27; + RK_U32 sw_reserve : 5; + } reg138; + + struct { + RK_U32 sw_trb_per_trd_d1 : 27; + RK_U32 sw_reserve : 5; + } reg139; + + RK_U32 reg_dct_strm_base[5]; + RK_U32 reg145_bitpl_ctrl_base; + RK_U32 reg_dct_strm1_base[2]; + + RK_U32 reg148_ref1_base; + + RK_U32 reg149_segment_map_base; + + + struct { + RK_U32 sw_dct_start_bit_7 : 6; + RK_U32 sw_dct_start_bit_6 : 6; + RK_U32 sw_dct_start_bit_5 : 6; + RK_U32 sw_dct_start_bit_4 : 6; + RK_U32 sw_dct_start_bit_3 : 6; + RK_U32 sw_reserve : 2; + } reg150; + + struct { + RK_U32 sw_quant_3 : 11; + RK_U32 sw_quant_2 : 11; + RK_U32 sw_quant_delta_3 : 5; + RK_U32 sw_quant_delta_2 : 5; + } reg151; + + struct { + RK_U32 sw_quant_5 : 11; + RK_U32 sw_quant_4 : 11; + RK_U32 sw_quant_delta_4 : 5; + RK_U32 sw_reserve : 5; + } reg152; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_1_1 : 10; + RK_U32 sw_pred_bc_tap_1_0 : 10; + RK_U32 sw_pred_bc_tap_0_3 : 10; + } reg153; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_2_0 : 10; + RK_U32 sw_pred_bc_tap_1_3 : 10; + RK_U32 sw_pred_bc_tap_1_2 : 10; + } reg154; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_2_3 : 10; + RK_U32 sw_pred_bc_tap_2_2 : 10; + RK_U32 sw_pred_bc_tap_2_1 : 10; + } reg155; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_3_2 : 10; + RK_U32 sw_pred_bc_tap_3_1 : 10; + RK_U32 sw_pred_bc_tap_3_0 : 10; + } reg156; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_4_1 : 10; + RK_U32 sw_pred_bc_tap_4_0 : 10; + RK_U32 sw_pred_bc_tap_3_3 : 10; + } reg157; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_5_0 : 10; + RK_U32 sw_pred_bc_tap_4_3 : 10; + RK_U32 sw_pred_bc_tap_4_2 : 10; + } reg158; +} M4vdVdpu2Regs_t; + +#endif /* HAL_M4V_VDPU2_REG_TBL_H */ diff --git a/mpp/hal/vpu/vp8d/CMakeLists.txt b/mpp/hal/vpu/vp8d/CMakeLists.txt new file mode 100644 index 000000000..998e5d26e --- /dev/null +++ b/mpp/hal/vpu/vp8d/CMakeLists.txt @@ -0,0 +1,12 @@ +# vim: syntax=cmake +include_directories(.) + +# hal vp8 decoder sourse +set(HAL_VP8D_SRC) + +add_hal_source(HAL_VP8D_SRC HAVE_VDPU1 hal_vp8d_vdpu1.c) +add_hal_source(HAL_VP8D_SRC HAVE_VDPU2 hal_vp8d_vdpu2.c) + +if (HAL_VP8D_SRC) + add_library(hal_vp8d_api OBJECT ${HAL_VP8D_SRC}) +endif() \ No newline at end of file diff --git a/mpp/hal/vpu/vp8d/hal_vp8d_base.h b/mpp/hal/vpu/vp8d/hal_vp8d_base.h new file mode 100644 index 000000000..ba6b7f2fa --- /dev/null +++ b/mpp/hal/vpu/vp8d/hal_vp8d_base.h @@ -0,0 +1,57 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8D_BASE_H +#define HAL_VP8D_BASE_H + +#include + +#include "mpp_hal.h" +#include "mpp_buf_slot.h" +#include "mpp_device.h" + +#include "hal_dec_task.h" + +#include "vp8d_syntax.h" + +#define VP8H_DBG_FUNCTION (0x00000001) +#define VP8H_DBG_REG (0x00000002) +#define VP8H_DBG_DUMP_REG (0x00000004) +#define VP8H_DBG_IRQ (0x00000008) + +extern RK_U32 hal_vp8d_debug; + +#define vp8h_dbg(flag, fmt, ...) \ + mpp_dbg_f(hal_vp8d_debug, flag, fmt, ## __VA_ARGS__) + +#define FUN_T(tag) \ + do {\ + if (VP8H_DBG_FUNCTION & hal_vp8d_debug)\ + { mpp_log("%s: line(%d), func(%s)", tag, __LINE__, __FUNCTION__); }\ + } while (0) + +typedef struct VP8DHalContext { + MppHalCfg *cfg; + void *regs; + RK_U8 reg_size; + MppBuffer probe_table; + MppBuffer seg_map; + RK_U32 dec_frame_cnt; + FILE *fp_reg_in; + FILE *fp_reg_out; +} VP8DHalContext_t; + +#endif diff --git a/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1.c b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1.c new file mode 100644 index 000000000..8335ed989 --- /dev/null +++ b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1.c @@ -0,0 +1,703 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp8d_vdpu1" + +#include + +#include "rk_type.h" +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "hal_vp8d_vdpu1.h" +#include "hal_vp8d_vdpu1_reg.h" + +#define CLIP3(l, h, v) ((v) < (l) ? (l) : ((v) > (h) ? (h) : (v))) + +/* VP8 6-tap filter coefficients */ +static const RK_S32 mcFilter[8][6] = { + { 0, 0, 128, 0, 0, 0 }, + { 0, -6, 123, 12, -1, 0 }, + { 2, -11, 108, 36, -8, 1 }, + { 0, -9, 93, 50, -6, 0 }, + { 3, -16, 77, 77, -16, 3 }, + { 0, -6, 50, 93, -9, 0 }, + { 1, -8, 36, 108, -11, 2 }, + { 0, -1, 12, 123, -6, 0 } +}; + +static MPP_RET hal_vp8d_vdpu1_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + + mpp_env_get_u32("hal_vp8d_debug", &hal_vp8d_debug, 0); + + FUN_T("enter\n"); + + if (!cfg || !cfg->dev || !cfg->buf_group) { + mpp_err_f("invalid cfg %p dev %p buf_group %p\n", cfg, + cfg ? cfg->dev : NULL, cfg ? cfg->buf_group : NULL); + return MPP_ERR_NULL_PTR; + } + + ctx->cfg = cfg; + + if (NULL == ctx->regs) { + ctx->regs = mpp_calloc_size(void, sizeof(VP8DRegSet_t)); + if (NULL == ctx->regs) { + mpp_err("hal_vp8 reg alloc failed\n"); + ret = MPP_ERR_MALLOC; + goto ERR_RET; + } + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->probe_table, VP8D_PROB_TABLE_SIZE); + if (ret) { + mpp_err("hal_vp8 probe_table get buffer failed\n"); + goto ERR_RET; + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->seg_map, VP8D_MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("hal_vp8 seg_map get buffer failed\n"); + goto ERR_RET; + } + //configure + + FUN_T("leave\n"); + return ret; +ERR_RET: + if (ctx->probe_table) { + mpp_buffer_put(ctx->probe_table); + ctx->probe_table = NULL; + } + + if (ctx->seg_map) { + mpp_buffer_put(ctx->seg_map); + ctx->seg_map = NULL; + } + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + ctx->cfg = NULL; + + FUN_T("leave\n"); + return ret; +} + +static MPP_RET hal_vp8d_vdpu1_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + + FUN_T("enter\n"); + + if (ctx->probe_table) { + ret = mpp_buffer_put(ctx->probe_table); + if (ret) { + mpp_err("hal_vp8 probe table put buffer failed\n"); + } + ctx->probe_table = NULL; + } + + if (ctx->seg_map) { + ret = mpp_buffer_put(ctx->seg_map); + if (ret) { + mpp_err("hal_vp8 seg map put buffer failed\n"); + } + ctx->seg_map = NULL; + } + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + ctx->cfg = NULL; + + FUN_T("leave\n"); + return ret; +} + +static MPP_RET hal_vp8_init_hwcfg(VP8DHalContext_t *ctx) +{ + + VP8DRegSet_t *reg = (VP8DRegSet_t *)ctx->regs; + + FUN_T("enter\n"); + memset(reg, 0, sizeof(VP8DRegSet_t)); + + reg->reg1_interrupt.sw_dec_e = 1; + + reg->reg2_dec_ctrl.sw_dec_out_tiled_e = 0; + reg->reg2_dec_ctrl.sw_dec_scmd_dis = 0; + reg->reg2_dec_ctrl.sw_dec_adv_pre_dis = 0; + reg->reg2_dec_ctrl.sw_dec_latency = 0; + + reg->reg2_dec_ctrl.sw_dec_in_endian = 1; + reg->reg2_dec_ctrl.sw_dec_out_endian = 1; + reg->reg2_dec_ctrl.sw_dec_inswap32_e = 1; + reg->reg2_dec_ctrl.sw_dec_outswap32_e = 1; + reg->reg2_dec_ctrl.sw_dec_strswap32_e = 1; + reg->reg2_dec_ctrl.sw_dec_strendian_e = 1; + reg->reg2_dec_ctrl.sw_dec_axi_rn_id = 0; + + reg->reg2_dec_ctrl.sw_dec_data_disc_e = 0; + reg->reg2_dec_ctrl.sw_dec_max_burst = 16; + reg->reg2_dec_ctrl.sw_dec_timeout_e = 1; + reg->reg2_dec_ctrl.sw_dec_clk_gate_e = 1; + + reg->reg3.sw_dec_out_dis = 0; + reg->reg3.sw_dec_axi_wr_id = 0; + reg->reg3.sw_dec_mode = DEC_MODE_VP8; + + reg->reg1_interrupt.sw_dec_irq = 0; + + reg->reg10_segment_map_base = mpp_buffer_get_fd(ctx->seg_map); + reg->reg40_qtable_base = mpp_buffer_get_fd(ctx->probe_table); + + FUN_T("leave\n"); + return MPP_OK; +} + +static MPP_RET hal_vp8d_pre_filter_tap_set(VP8DHalContext_t *ctx) +{ + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + + FUN_T("enter\n"); + regs->reg49.sw_pred_bc_tap_0_0 = mcFilter[0][1]; + regs->reg49.sw_pred_bc_tap_0_1 = mcFilter[0][2]; + regs->reg49.sw_pred_bc_tap_0_2 = mcFilter[0][3]; + regs->reg34.sw_pred_bc_tap_0_3 = mcFilter[0][4]; + regs->reg34.sw_pred_bc_tap_1_0 = mcFilter[1][1]; + regs->reg34.sw_pred_bc_tap_1_1 = mcFilter[1][2]; + regs->reg35.sw_pred_bc_tap_1_2 = mcFilter[1][3]; + regs->reg35.sw_pred_bc_tap_1_3 = mcFilter[1][4]; + regs->reg35.sw_pred_bc_tap_2_0 = mcFilter[2][1]; + regs->reg36.sw_pred_bc_tap_2_1 = mcFilter[2][2]; + regs->reg36.sw_pred_bc_tap_2_2 = mcFilter[2][3]; + regs->reg36.sw_pred_bc_tap_2_3 = mcFilter[2][4]; + + regs->reg37.sw_pred_bc_tap_3_0 = mcFilter[3][1]; + regs->reg37.sw_pred_bc_tap_3_1 = mcFilter[3][2]; + regs->reg37.sw_pred_bc_tap_3_2 = mcFilter[3][3]; + regs->reg38.sw_pred_bc_tap_3_3 = mcFilter[3][4]; + regs->reg38.sw_pred_bc_tap_4_0 = mcFilter[4][1]; + regs->reg38.sw_pred_bc_tap_4_1 = mcFilter[4][2]; + regs->reg39.sw_pred_bc_tap_4_2 = mcFilter[4][3]; + regs->reg39.sw_pred_bc_tap_4_3 = mcFilter[4][4]; + regs->reg39.sw_pred_bc_tap_5_0 = mcFilter[5][1]; + + regs->reg42.sw_pred_bc_tap_5_1 = mcFilter[5][2]; + regs->reg42.sw_pred_bc_tap_5_2 = mcFilter[5][3]; + regs->reg42.sw_pred_bc_tap_5_3 = mcFilter[5][4]; + + regs->reg43.sw_pred_bc_tap_6_0 = mcFilter[6][1]; + regs->reg43.sw_pred_bc_tap_6_1 = mcFilter[6][2]; + regs->reg43.sw_pred_bc_tap_6_2 = mcFilter[6][3]; + + regs->reg44.sw_pred_bc_tap_6_3 = mcFilter[6][4]; + regs->reg44.sw_pred_bc_tap_7_0 = mcFilter[7][1]; + regs->reg44.sw_pred_bc_tap_7_1 = mcFilter[7][2]; + + regs->reg45.sw_pred_bc_tap_7_2 = mcFilter[7][3]; + regs->reg45.sw_pred_bc_tap_7_3 = mcFilter[7][4]; + + regs->reg45.sw_pred_tap_2_M1 = mcFilter[2][0]; + regs->reg45.sw_pred_tap_2_4 = mcFilter[2][5]; + regs->reg45.sw_pred_tap_4_M1 = mcFilter[4][0]; + regs->reg45.sw_pred_tap_4_4 = mcFilter[4][5]; + regs->reg45.sw_pred_tap_6_M1 = mcFilter[6][0]; + regs->reg45.sw_pred_tap_6_4 = mcFilter[6][5]; + + FUN_T("leave\n"); + return MPP_OK; +} + +static MPP_RET +hal_vp8d_dct_partition_cfg(VP8DHalContext_t *ctx, HalTaskInfo *task) +{ + RK_U32 i = 0, len = 0, len1 = 0; + RK_U32 extraBytesPacked = 0; + RK_U32 addr = 0, byte_offset = 0; + RK_U32 fd = 0; + MppBuffer streambuf = NULL; + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + DXVA_PicParams_VP8 *pic_param = (DXVA_PicParams_VP8 *)task->dec.syntax.data; + + + FUN_T("enter\n"); + + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->dec.input, + SLOT_BUFFER, &streambuf); + fd = mpp_buffer_get_fd(streambuf); + regs->reg27_bitpl_ctrl_base = fd; + if (pic_param->stream_start_offset) + mpp_dev_set_reg_offset(ctx->cfg->dev, 27, pic_param->stream_start_offset); + regs->reg5.sw_strm1_start_bit = pic_param->stream_start_bit; + + /* calculate dct partition length here instead */ + if (pic_param->decMode == VP8HWD_VP8 && !pic_param->frame_type) + extraBytesPacked += 7; + + len = pic_param->streamEndPos + pic_param->frameTagSize + - pic_param->dctPartitionOffsets[0]; + len += ((1 << pic_param->log2_nbr_of_dct_partitions) - 1) * 3; + len1 = extraBytesPacked + pic_param->dctPartitionOffsets[0]; + len += (len1 & 0x7); + regs->reg6.sw_stream_len = len; + + len = pic_param->offsetToDctParts + pic_param->frameTagSize - + (pic_param->stream_start_offset - extraBytesPacked); + len++; + + regs->reg9.sw_stream1_len = len; + regs->reg9.sw_coeffs_part_am = (1 << pic_param->log2_nbr_of_dct_partitions); + regs->reg9.sw_coeffs_part_am--; + for (i = 0; i < (RK_U32)(1 << pic_param->log2_nbr_of_dct_partitions); i++) { + addr = extraBytesPacked + pic_param->dctPartitionOffsets[i]; + byte_offset = addr & 0x7; + addr = addr & 0xFFFFFFF8; + + if (i == 0) { + regs->reg12_input_stream_base = fd; + if (addr) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 12, addr); + } + } else if (i <= 5) { + regs->reg_dct_strm0_base[i - 1] = fd; + if (addr) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 21 + i, addr); + } + } else { + regs->reg_dct_strm1_base[i - 6] = fd; + if (addr) { + mpp_dev_set_reg_offset(ctx->cfg->dev, 22 + i, addr); + } + } + + switch (i) { + case 0: + regs->reg5.sw_strm0_start_bit = byte_offset * 8; + break; + case 1: + regs->reg7.sw_dct1_start_bit = byte_offset * 8; + break; + case 2: + regs->reg7.sw_dct2_start_bit = byte_offset * 8; + break; + case 3: + regs->reg11.sw_dct_start_bit_3 = byte_offset * 8; + break; + case 4: + regs->reg11.sw_dct_start_bit_4 = byte_offset * 8; + break; + case 5: + regs->reg11.sw_dct_start_bit_5 = byte_offset * 8; + break; + case 6: + regs->reg11.sw_dct_start_bit_6 = byte_offset * 8; + break; + case 7: + regs->reg11.sw_dct_start_bit_7 = byte_offset * 8; + break; + default: + break; + } + } + + FUN_T("leave\n"); + return MPP_OK; +} + +static void hal_vp8hw_asic_probe_update(DXVA_PicParams_VP8 *p, RK_U8 *probTbl) +{ + RK_U8 *dst; + RK_U32 i, j, k; + + FUN_T("enter\n"); + /* first probs */ + dst = probTbl; + + dst[0] = p->probe_skip_false; + dst[1] = p->prob_intra; + dst[2] = p->prob_last; + dst[3] = p->prob_golden; + dst[4] = p->stVP8Segments.mb_segment_tree_probs[0]; + dst[5] = p->stVP8Segments.mb_segment_tree_probs[1]; + dst[6] = p->stVP8Segments.mb_segment_tree_probs[2]; + dst[7] = 0; /*unused*/ + + dst += 8; + dst[0] = p->intra_16x16_prob[0]; + dst[1] = p->intra_16x16_prob[1]; + dst[2] = p->intra_16x16_prob[2]; + dst[3] = p->intra_16x16_prob[3]; + dst[4] = p->intra_chroma_prob[0]; + dst[5] = p->intra_chroma_prob[1]; + dst[6] = p->intra_chroma_prob[2]; + dst[7] = 0; /*unused*/ + + /* mv probs */ + dst += 8; + dst[0] = p->vp8_mv_update_probs[0][0]; /* is short */ + dst[1] = p->vp8_mv_update_probs[1][0]; + dst[2] = p->vp8_mv_update_probs[0][1]; /* sign */ + dst[3] = p->vp8_mv_update_probs[1][1]; + dst[4] = p->vp8_mv_update_probs[0][8 + 9]; + dst[5] = p->vp8_mv_update_probs[0][9 + 9]; + dst[6] = p->vp8_mv_update_probs[1][8 + 9]; + dst[7] = p->vp8_mv_update_probs[1][9 + 9]; + dst += 8; + for ( i = 0 ; i < 2 ; ++i ) { + for ( j = 0 ; j < 8 ; j += 4 ) { + dst[0] = p->vp8_mv_update_probs[i][j + 9 + 0]; + dst[1] = p->vp8_mv_update_probs[i][j + 9 + 1]; + dst[2] = p->vp8_mv_update_probs[i][j + 9 + 2]; + dst[3] = p->vp8_mv_update_probs[i][j + 9 + 3]; + dst += 4; + } + } + for ( i = 0 ; i < 2 ; ++i ) { + dst[0] = p->vp8_mv_update_probs[i][0 + 2]; + dst[1] = p->vp8_mv_update_probs[i][1 + 2]; + dst[2] = p->vp8_mv_update_probs[i][2 + 2]; + dst[3] = p->vp8_mv_update_probs[i][3 + 2]; + dst[4] = p->vp8_mv_update_probs[i][4 + 2]; + dst[5] = p->vp8_mv_update_probs[i][5 + 2]; + dst[6] = p->vp8_mv_update_probs[i][6 + 2]; + dst[7] = 0; /*unused*/ + dst += 8; + } + + /* coeff probs (header part) */ + dst = (RK_U8*)probTbl; + dst += (8 * 7); + for ( i = 0 ; i < 4 ; ++i ) { + for ( j = 0 ; j < 8 ; ++j ) { + for ( k = 0 ; k < 3 ; ++k ) { + dst[0] = p->vp8_coef_update_probs[i][j][k][0]; + dst[1] = p->vp8_coef_update_probs[i][j][k][1]; + dst[2] = p->vp8_coef_update_probs[i][j][k][2]; + dst[3] = p->vp8_coef_update_probs[i][j][k][3]; + dst += 4; + } + } + } + + /* coeff probs (footer part) */ + dst = (RK_U8*)probTbl; + dst += (8 * 55); + for ( i = 0 ; i < 4 ; ++i ) { + for ( j = 0 ; j < 8 ; ++j ) { + for ( k = 0 ; k < 3 ; ++k ) { + dst[0] = p->vp8_coef_update_probs[i][j][k][4]; + dst[1] = p->vp8_coef_update_probs[i][j][k][5]; + dst[2] = p->vp8_coef_update_probs[i][j][k][6]; + dst[3] = p->vp8_coef_update_probs[i][j][k][7]; + dst[4] = p->vp8_coef_update_probs[i][j][k][8]; + dst[5] = p->vp8_coef_update_probs[i][j][k][9]; + dst[6] = p->vp8_coef_update_probs[i][j][k][10]; + dst[7] = 0; /*unused*/ + dst += 8; + } + } + } + FUN_T("leave\n"); + return ; +} + +static MPP_RET hal_vp8d_vdpu1_gen_regs(void* hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 mb_width = 0, mb_height = 0; + MppBuffer framebuf = NULL; + RK_U8 *segmap_ptr = NULL; + RK_U8 *probe_ptr = NULL; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + DXVA_PicParams_VP8 *pic_param = (DXVA_PicParams_VP8 *)task->dec.syntax.data; + MppHalCfg *cfg = ctx->cfg; + + FUN_T("enter\n"); + + hal_vp8_init_hwcfg(ctx); + mb_width = (pic_param->width + 15) >> 4; + mb_height = (pic_param->height + 15) >> 4; + + regs->reg4.sw_pic_mb_width = mb_width & 0x1FF; + regs->reg4.sw_pic_mb_hight_p = mb_height & 0xFF; + regs->reg4.sw_pic_mb_w_ext = mb_width >> 9; + regs->reg4.sw_pic_mb_h_ext = mb_height >> 8; + + if (!pic_param->frame_type) { + segmap_ptr = mpp_buffer_get_ptr(ctx->seg_map); + if (NULL != segmap_ptr) { + memset(segmap_ptr, 0, VP8D_MAX_SEGMAP_SIZE); + } + } + + probe_ptr = mpp_buffer_get_ptr(ctx->probe_table); + if (NULL != probe_ptr) { + hal_vp8hw_asic_probe_update(pic_param, probe_ptr); + } + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->CurrPic.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg13_cur_pic_base = mpp_buffer_get_fd(framebuf); + if (!pic_param->frame_type) { //key frame + if ((mb_width * mb_height) << 8 > 0x400000) { + mpp_log("mb_width*mb_height is big then 0x400000,iommu err"); + } + regs->reg14_ref0_base = regs->reg13_cur_pic_base; + mpp_dev_set_reg_offset(cfg->dev, 14, (mb_width * mb_height) << 8); + } else if (pic_param->lst_fb_idx.Index7Bits < 0x7f) { //config ref0 base + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->lst_fb_idx.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg14_ref0_base = mpp_buffer_get_fd(framebuf); + } else { + regs->reg14_ref0_base = regs->reg13_cur_pic_base; + } + + /* golden reference */ + if (pic_param->gld_fb_idx.Index7Bits < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->gld_fb_idx.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg18_golden_ref_base = mpp_buffer_get_fd(framebuf); + } else { + regs->reg18_golden_ref_base = regs->reg13_cur_pic_base; + } + + if (pic_param->ref_frame_sign_bias_golden) { + mpp_dev_set_reg_offset(cfg->dev, 18, pic_param->ref_frame_sign_bias_golden); + } + + /* alternate reference */ + if (pic_param->alt_fb_idx.Index7Bits < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->alt_fb_idx.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg19.alternate_ref_base = mpp_buffer_get_fd(framebuf); + } else { + regs->reg19.alternate_ref_base = regs->reg13_cur_pic_base; + } + + if (pic_param->ref_frame_sign_bias_altref) { + mpp_dev_set_reg_offset(cfg->dev, 19, pic_param->ref_frame_sign_bias_altref); + } + + if (pic_param->stVP8Segments.segmentation_enabled || pic_param->stVP8Segments.update_mb_segmentation_map) { + mpp_dev_set_reg_offset(cfg->dev, 10, (pic_param->stVP8Segments.segmentation_enabled + + (pic_param->stVP8Segments.update_mb_segmentation_map << 1))); + } + + regs->reg3.sw_pic_inter_e = pic_param->frame_type; + regs->reg3.sw_skip_mode = !pic_param->mb_no_coeff_skip; + + if (!pic_param->stVP8Segments.segmentation_enabled) { + regs->reg32.sw_filt_level_0 = pic_param->filter_level; + } else if (pic_param->stVP8Segments.update_mb_segmentation_data) { + regs->reg32.sw_filt_level_0 = + pic_param->stVP8Segments.segment_feature_data[1][0]; + regs->reg32.sw_filt_level_1 = + pic_param->stVP8Segments.segment_feature_data[1][1]; + regs->reg32.sw_filt_level_2 = + pic_param->stVP8Segments.segment_feature_data[1][2]; + regs->reg32.sw_filt_level_3 = + pic_param->stVP8Segments.segment_feature_data[1][3]; + } else { + regs->reg32.sw_filt_level_0 = CLIP3(0, 63, + (RK_S32)pic_param->filter_level + + pic_param->stVP8Segments.segment_feature_data[1][0]); + regs->reg32.sw_filt_level_1 = CLIP3(0, 63, + (RK_S32)pic_param->filter_level + + pic_param->stVP8Segments.segment_feature_data[1][1]); + regs->reg32.sw_filt_level_2 = CLIP3(0, 63, + (RK_S32)pic_param->filter_level + + pic_param->stVP8Segments.segment_feature_data[1][2]); + regs->reg32.sw_filt_level_3 = CLIP3(0, 63, + (RK_S32)pic_param->filter_level + + pic_param->stVP8Segments.segment_feature_data[1][3]); + } + + regs->reg30.sw_filt_type = pic_param->filter_type; + regs->reg30.sw_filt_sharpness = pic_param->sharpness; + + if (pic_param->filter_level == 0) + regs->reg3.sw_filtering_dis = 1; + + if (pic_param->version != 3) + regs->reg7.sw_ch_mv_res = 1; + + if (pic_param->decMode == VP8HWD_VP8 && (pic_param->version & 0x3)) + regs->reg7.sw_bilin_mc_e = 1; + + regs->reg5.sw_boolean_value = pic_param->bool_value; + regs->reg5.sw_boolean_range = pic_param->bool_range; + + { + if (!pic_param->stVP8Segments.segmentation_enabled) + regs->reg33.sw_quant_0 = pic_param->y1ac_delta_q; + else if (pic_param->stVP8Segments.update_mb_segmentation_data) { /* absolute mode */ + regs->reg33.sw_quant_0 = + pic_param->stVP8Segments.segment_feature_data[0][0]; + regs->reg33.sw_quant_1 = + pic_param->stVP8Segments.segment_feature_data[0][1]; + regs->reg46.sw_quant_2 = pic_param->stVP8Segments.segment_feature_data[0][2]; + regs->reg46.sw_quant_3 = pic_param->stVP8Segments.segment_feature_data[0][3]; + } else { /* delta mode */ + regs->reg33.sw_quant_0 = CLIP3(0, 127, + pic_param->y1ac_delta_q + + pic_param->stVP8Segments.segment_feature_data[0][0]); + regs->reg33.sw_quant_1 = CLIP3(0, 127, + pic_param->y1ac_delta_q + + pic_param->stVP8Segments.segment_feature_data[0][1]); + regs->reg46.sw_quant_2 = CLIP3(0, 127, + pic_param->y1ac_delta_q + + pic_param->stVP8Segments.segment_feature_data[0][2]); + regs->reg46.sw_quant_3 = CLIP3(0, 127, + pic_param->y1ac_delta_q + + pic_param->stVP8Segments.segment_feature_data[0][3]); + } + + regs->reg33.sw_quant_delta_0 = pic_param->y1dc_delta_q; + regs->reg33.sw_quant_delta_1 = pic_param->y2dc_delta_q; + regs->reg46.sw_quant_delta_2 = pic_param->y2ac_delta_q; + regs->reg46.sw_quant_delta_3 = pic_param->uvdc_delta_q; + regs->reg47.sw_quant_delta_4 = pic_param->uvac_delta_q; + + if (pic_param->mode_ref_lf_delta_enabled) { + regs->reg31.sw_filt_ref_adj_0 = pic_param->ref_lf_deltas[0]; + regs->reg31.sw_filt_ref_adj_1 = pic_param->ref_lf_deltas[1]; + regs->reg31.sw_filt_ref_adj_2 = pic_param->ref_lf_deltas[2]; + regs->reg31.sw_filt_ref_adj_3 = pic_param->ref_lf_deltas[3]; + regs->reg30.sw_filt_mb_adj_0 = pic_param->mode_lf_deltas[0]; + regs->reg30.sw_filt_mb_adj_1 = pic_param->mode_lf_deltas[1]; + regs->reg30.sw_filt_mb_adj_2 = pic_param->mode_lf_deltas[2]; + regs->reg30.sw_filt_mb_adj_3 = pic_param->mode_lf_deltas[3]; + } + } + + if ((pic_param->version & 0x3) == 0) + hal_vp8d_pre_filter_tap_set(ctx); + + hal_vp8d_dct_partition_cfg(ctx, task); + + mpp_buffer_sync_end(ctx->probe_table); + mpp_buffer_sync_end(ctx->seg_map); + + FUN_T("leave\n"); + return ret; +} + +static MPP_RET hal_vp8d_vdpu1_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + MppDev dev = ctx->cfg->dev; + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + + FUN_T("enter\n"); + + if (hal_vp8d_debug & VP8H_DBG_REG) { + RK_U32 *p = ctx->regs; + RK_U32 i = 0; + + for (i = 0; i < VP8D_REG_NUM; i++) + mpp_log_f("vp8d: regs[%02d]=%08X\n", i, *p++); + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = sizeof(VP8DRegSet_t); + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + FUN_T("leave\n"); + + (void)task; + return ret; +} + +static MPP_RET hal_vp8d_vdpu1_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + MppDev dev = ctx->cfg->dev; + + FUN_T("enter\n"); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + (void)task; + FUN_T("leave\n"); + return ret; +} + +const MppHalApi hal_vp8d_vdpu1 = { + .name = "vp8d_vdpu1", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingVP8, + .ctx_size = sizeof(VP8DHalContext_t), + .flag = 0, + .init = hal_vp8d_vdpu1_init, + .deinit = hal_vp8d_vdpu1_deinit, + .reg_gen = hal_vp8d_vdpu1_gen_regs, + .start = hal_vp8d_vdpu1_start, + .wait = hal_vp8d_vdpu1_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU1, + .soc_type = { + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_vp8d_vdpu1) diff --git a/mpp/codec/inc/vp8d_api.h b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1.h similarity index 77% rename from mpp/codec/inc/vp8d_api.h rename to mpp/hal/vpu/vp8d/hal_vp8d_vdpu1.h index f0fd46cfc..c383c758d 100644 --- a/mpp/codec/inc/vp8d_api.h +++ b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1.h @@ -1,22 +1,24 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VP8D_API_H__ -#define __VP8D_API_H__ - - - -#endif /*__VP8D_API_H__*/ \ No newline at end of file +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8D_VDPU1_H +#define HAL_VP8D_VDPU1_H + +#include "hal_vp8d_base.h" + +extern const MppHalApi hal_vp8d_vdpu1; + +#endif diff --git a/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1_reg.h b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1_reg.h new file mode 100644 index 000000000..256fba130 --- /dev/null +++ b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu1_reg.h @@ -0,0 +1,401 @@ +/* + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HAL_VP8D_VDPU1_REG_H +#define HAL_VP8D_VDPU1_REG_H + +#include "rk_type.h" + +#define VP8HWD_VP7 1 +#define VP8HWD_VP8 2 +#define VP8HWD_WEBP 3 + +#define DEC_MODE_VP7 9 +#define DEC_MODE_VP8 10 + +#define VP8D_PROB_TABLE_SIZE (1<<16) +#define VP8D_MAX_SEGMAP_SIZE (2048 + 1024) + +#define VP8D_REG_NUM 101 + +typedef struct { + struct { + RK_U32 build_version : 3; + RK_U32 product_IDen : 1; + RK_U32 minor_version : 8; + RK_U32 major_version : 4; + RK_U32 product_numer : 16; + } reg0_id; + + struct { + RK_U32 sw_dec_e : 1; + RK_U32 reserve4 : 3; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve3 : 3; + RK_U32 sw_dec_irq : 1; + RK_U32 reserve2 : 3; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reseved1 : 5; + RK_U32 sw_dec_pic_inf : 1; + RK_U32 reserved0 : 7; + } reg1_interrupt; + + struct { + RK_U32 sw_dec_max_burst : 5; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_priority_mode : 1; /* Not used */ + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_dec_out_tiled_e : 1; /* Not used */ + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_dec_axi_rn_id : 8; + } reg2_dec_ctrl; + + struct { + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 sw_dec_ahb_hlock_e : 1; /* Not used */ + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; /* Not used */ + RK_U32 sw_skip_mode : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_dec_mode : 4; + } reg3; + + struct { + RK_U32 sw_pic_mb_h_ext : 3; + RK_U32 sw_pic_mb_w_ext : 3; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } reg4; + + struct { + RK_U32 sw_boolean_range : 8; + RK_U32 sw_boolean_value : 8; + RK_U32 reserved1 : 2; + RK_U32 sw_strm1_start_bit : 6; + RK_U32 reserved0 : 2; + RK_U32 sw_strm0_start_bit : 6; + } reg5; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_init_qp : 6; + RK_U32 sw_start_code_e : 1; + } reg6; + + struct { + RK_U32 reserved1 : 5; + RK_U32 sw_vp7_version : 1; + RK_U32 sw_dc_match1 : 3; + RK_U32 sw_dc_match0 : 3; + RK_U32 sw_bilin_mc_e : 1; + RK_U32 sw_ch_mv_res : 1; + RK_U32 reserved0 : 6; + RK_U32 sw_dct2_start_bit : 6; + RK_U32 sw_dct1_start_bit : 6; + } reg7; + + struct { + RK_U32 sw_dc_comp1 : 16; + RK_U32 sw_dc_comp0 : 16; + } reg8; + + struct { + RK_U32 sw_stream1_len : 24; + RK_U32 sw_coeffs_part_am : 4; + RK_U32 reserved0 : 4; + } reg9; + + RK_U32 reg10_segment_map_base; + + struct { + RK_U32 sw_dct_start_bit_7 : 6; + RK_U32 sw_dct_start_bit_6 : 6; + RK_U32 sw_dct_start_bit_5 : 6; + RK_U32 sw_dct_start_bit_4 : 6; + RK_U32 sw_dct_start_bit_3 : 6; + RK_U32 reserved0 : 2; + } reg11; + + RK_U32 reg12_input_stream_base; + RK_U32 reg13_cur_pic_base; /* Decoder output base */ + RK_U32 reg14_ref0_base; /* sw_ch_out_base */ + RK_U32 reg15_17[3]; /* Not used */ + + RK_U32 reg18_golden_ref_base; + + union { + RK_U32 alternate_ref_base; /* sw_refer5_base */ + struct { + RK_U32 sw_scan_map_5 : 6; + RK_U32 sw_scan_map_4 : 6; + RK_U32 sw_scan_map_3 : 6; + RK_U32 sw_scan_map_2 : 6; + RK_U32 sw_scan_map_1 : 6; + RK_U32 reserved0 : 2; + }; + } reg19; + + struct { + RK_U32 sw_scan_map_10 : 6; + RK_U32 sw_scan_map_9 : 6; + RK_U32 sw_scan_map_8 : 6; + RK_U32 sw_scan_map_7 : 6; + RK_U32 sw_scan_map_6 : 6; + RK_U32 reserved0 : 2; + } reg20; + + struct { + RK_U32 sw_scan_map_15 : 6; + RK_U32 sw_scan_map_14 : 6; + RK_U32 sw_scan_map_13 : 6; + RK_U32 sw_scan_map_12 : 6; + RK_U32 sw_scan_map_11 : 6; + RK_U32 reserved0 : 2; + } reg21; + + RK_U32 reg_dct_strm0_base[5]; /* From reg22 to reg26 */ + RK_U32 reg27_bitpl_ctrl_base; + RK_U32 reg_dct_strm1_base[2]; /* From reg28 to reg29 */ + + struct { + RK_U32 sw_filt_mb_adj_3 : 7; + RK_U32 sw_filt_mb_adj_2 : 7; + RK_U32 sw_filt_mb_adj_1 : 7; + RK_U32 sw_filt_mb_adj_0 : 7; + RK_U32 sw_filt_sharpness : 3; + RK_U32 sw_filt_type : 1; + } reg30; + + struct { + RK_U32 sw_filt_ref_adj_3 : 7; + RK_U32 sw_filt_ref_adj_2 : 7; + RK_U32 sw_filt_ref_adj_1 : 7; + RK_U32 sw_filt_ref_adj_0 : 7; + RK_U32 reserved0 : 4; + } reg31; + + struct { + RK_U32 sw_filt_level_3 : 6; + RK_U32 sw_filt_level_2 : 6; + RK_U32 sw_filt_level_1 : 6; + RK_U32 sw_filt_level_0 : 6; + RK_U32 reserved0 : 8; + } reg32; + + struct { + RK_U32 sw_quant_1 : 11; + RK_U32 sw_quant_0 : 11; + RK_U32 sw_quant_delta_1 : 5; + RK_U32 sw_quant_delta_0 : 5; + } reg33; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_1_1 : 10; + RK_S32 sw_pred_bc_tap_1_0 : 10; + RK_S32 sw_pred_bc_tap_0_3 : 10; + } reg34; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_2_0 : 10; + RK_S32 sw_pred_bc_tap_1_3 : 10; + RK_S32 sw_pred_bc_tap_1_2 : 10; + } reg35; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_2_3 : 10; + RK_S32 sw_pred_bc_tap_2_2 : 10; + RK_S32 sw_pred_bc_tap_2_1 : 10; + } reg36; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_3_2 : 10; + RK_S32 sw_pred_bc_tap_3_1 : 10; + RK_S32 sw_pred_bc_tap_3_0 : 10; + } reg37; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_4_1 : 10; + RK_S32 sw_pred_bc_tap_4_0 : 10; + RK_S32 sw_pred_bc_tap_3_3 : 10; + } reg38; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_5_0 : 10; + RK_S32 sw_pred_bc_tap_4_3 : 10; + RK_S32 sw_pred_bc_tap_4_2 : 10; + } reg39; + + RK_U32 reg40_qtable_base; + RK_U32 reg41_directmv_base; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_5_3 : 10; + RK_S32 sw_pred_bc_tap_5_2 : 10; + RK_S32 sw_pred_bc_tap_5_1 : 10; + } reg42; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_6_2 : 10; + RK_S32 sw_pred_bc_tap_6_1 : 10; + RK_S32 sw_pred_bc_tap_6_0 : 10; + } reg43; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_7_1 : 10; + RK_S32 sw_pred_bc_tap_7_0 : 10; + RK_S32 sw_pred_bc_tap_6_3 : 10; + } reg44; + + struct { + RK_U32 sw_pred_tap_6_4 : 2; + RK_U32 sw_pred_tap_6_M1 : 2; + RK_U32 sw_pred_tap_4_4 : 2; + RK_U32 sw_pred_tap_4_M1 : 2; + RK_U32 sw_pred_tap_2_4 : 2; + RK_U32 sw_pred_tap_2_M1 : 2; + RK_S32 sw_pred_bc_tap_7_3 : 10; + RK_S32 sw_pred_bc_tap_7_2 : 10; + } reg45; + + struct { + RK_U32 sw_quant_3 : 11; + RK_U32 sw_quant_2 : 11; + RK_U32 sw_quant_delta_3 : 5; + RK_U32 sw_quant_delta_2 : 5; + } reg46; + + struct { + RK_U32 sw_quant_5 : 11; + RK_U32 sw_quant_4 : 11; + RK_U32 reserved : 5; + RK_U32 sw_quant_delta_4 : 5; + } reg47; + + struct { + RK_U32 reserved0 : 15; + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + } reg48; + + struct { + RK_U32 reserved0 : 2; + RK_S32 sw_pred_bc_tap_0_2 : 10; + RK_S32 sw_pred_bc_tap_0_1 : 10; + RK_S32 sw_pred_bc_tap_0_0 : 10; + } reg49; + + RK_U32 reg50; + + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 reserve0 : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } reg51_refpicbuf_ctrl; + + struct { + RK_U32 sw_refbu_intra_sum : 16; + RK_U32 sw_refbu_hit_sum : 16; + } reg52_sum_inf; + + struct { + RK_U32 sw_refbu_mv_sum : 22; + RK_U32 reserve0 : 10; + } reg53_sum_mv; + + struct { + RK_U32 reserve0 : 17; + /* sw_priority_mode */ + RK_U32 sw_dec_tiled_l : 2; + RK_U32 sw_dec_vp8snap_e : 1; + RK_U32 sw_dec_mvc_prof : 2; + RK_U32 sw_dec_avs_prof : 1; + RK_U32 sw_dec_vp8_prof : 1; + RK_U32 sw_dec_vp7_prof : 1; + RK_U32 sw_dec_rtl_rom : 1; + RK_U32 sw_dec_rv_prof : 2; + RK_U32 sw_ref_buff2_exist : 1; + RK_U32 reserve1 : 1; + RK_U32 sw_dec_refbu_ilace : 1; + RK_U32 sw_dec_jpeg_exten : 1; + } reg54_synthesis_cfg; + + struct { + RK_U32 sw_apf_threshold : 14; + RK_U32 sw_refbu2_picid : 5; + RK_U32 sw_refbu2_thr : 12; + RK_U32 sw_refbu2_buf_e : 1; + } reg55; + + struct { + RK_U32 sw_refbu_bot_sum : 16; + RK_U32 sw_refbu_top_sum : 16; + } reg56_sum_of_partitions; + + /* Not used */ + RK_U32 reg57_decoder_fuse; + RK_U32 reg58_debug; + + RK_U32 reg59_addit_ch_st_base; + RK_U32 reg60_100_post_processor[41]; +} VP8DRegSet_t; + +#endif diff --git a/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2.c b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2.c new file mode 100644 index 000000000..7d4457e27 --- /dev/null +++ b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2.c @@ -0,0 +1,721 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp8d_vdpu2" + +#include + +#include "rk_type.h" +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "hal_vp8d_vdpu2.h" +#include "hal_vp8d_vdpu2_reg.h" + +#define CLIP3(l, h, v) ((v) < (l) ? (l) : ((v) > (h) ? (h) : (v))) + +/* VP8 6-tap filter coefficients */ +static const RK_S32 mcFilter[8][6] = { + { 0, 0, 128, 0, 0, 0 }, + { 0, -6, 123, 12, -1, 0 }, + { 2, -11, 108, 36, -8, 1 }, + { 0, -9, 93, 50, -6, 0 }, + { 3, -16, 77, 77, -16, 3 }, + { 0, -6, 50, 93, -9, 0 }, + { 1, -8, 36, 108, -11, 2 }, + { 0, -1, 12, 123, -6, 0 } +}; + +static MPP_RET hal_vp8d_vdpu2_init(void *hal, MppHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + + mpp_env_get_u32("hal_vp8d_debug", &hal_vp8d_debug, 0); + + FUN_T("FUN_IN"); + + if (!cfg || !cfg->dev || !cfg->buf_group) { + mpp_err_f("invalid cfg %p dev %p buf_group %p\n", cfg, + cfg ? cfg->dev : NULL, cfg ? cfg->buf_group : NULL); + return MPP_ERR_NULL_PTR; + } + + ctx->cfg = cfg; + + if (NULL == ctx->regs) { + ctx->regs = mpp_calloc_size(void, sizeof(VP8DRegSet_t)); + if (NULL == ctx->regs) { + mpp_err("hal_vp8 reg alloc failed\n"); + ret = MPP_ERR_NOMEM; + goto ERR_RET; + } + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->probe_table, VP8D_PROB_TABLE_SIZE); + if (ret) { + mpp_err("hal_vp8 probe_table get buffer failed\n"); + goto ERR_RET; + } + + ret = mpp_buffer_get(cfg->buf_group, &ctx->seg_map, VP8D_MAX_SEGMAP_SIZE); + if (ret) { + mpp_err("hal_vp8 seg_map get buffer failed\n"); + goto ERR_RET; + } + + //configure + + FUN_T("FUN_OUT"); + return ret; +ERR_RET: + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + if (ctx->probe_table) { + mpp_buffer_put(ctx->probe_table); + ctx->probe_table = NULL; + } + + if (ctx->seg_map) { + mpp_buffer_put(ctx->seg_map); + ctx->seg_map = NULL; + } + + ctx->cfg = NULL; + + FUN_T("FUN_OUT"); + return ret; +} + +static MPP_RET hal_vp8d_vdpu2_deinit(void *hal) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + + FUN_T("FUN_IN"); + + if (ctx->probe_table) { + ret = mpp_buffer_put(ctx->probe_table); + if (ret) { + mpp_err("hal_vp8 probe table put buffer failed\n"); + } + ctx->probe_table = NULL; + } + + if (ctx->seg_map) { + ret = mpp_buffer_put(ctx->seg_map); + if (ret) { + mpp_err("hal_vp8 seg map put buffer failed\n"); + } + ctx->seg_map = NULL; + } + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + ctx->cfg = NULL;; + + FUN_T("FUN_OUT"); + return ret; +} + +static MPP_RET hal_vp8_init_hwcfg(VP8DHalContext_t *ctx) +{ + + VP8DRegSet_t *reg = (VP8DRegSet_t *)ctx->regs; + + FUN_T("FUN_IN"); + memset(reg, 0, sizeof(VP8DRegSet_t)); + reg->reg50_dec_ctrl.sw_dec_out_tiled_e = 0; + reg->reg50_dec_ctrl.sw_dec_scmd_dis = 0; + reg->reg50_dec_ctrl.sw_dec_adv_pre_dis = 0; + reg->reg50_dec_ctrl.sw_dec_latency = 0; + + reg->reg53_dec_mode = DEC_MODE_VP8; + + reg->reg54_endian.sw_dec_in_endian = 1; + reg->reg54_endian.sw_dec_out_endian = 1; + reg->reg54_endian.sw_dec_inswap32_e = 1; + reg->reg54_endian.sw_dec_outswap32_e = 1; + reg->reg54_endian.sw_dec_strswap32_e = 1; + reg->reg54_endian.sw_dec_strendian_e = 1; + + reg->reg55_Interrupt.sw_dec_irq = 0; + + reg->reg56_axi_ctrl.sw_dec_axi_rn_id = 0; + reg->reg56_axi_ctrl.sw_dec_axi_wr_id = 0; + + reg->reg56_axi_ctrl.sw_dec_data_disc_e = 0; + reg->reg56_axi_ctrl.sw_dec_max_burst = 16; + reg->reg57_enable_ctrl.sw_dec_timeout_e = 1; + reg->reg57_enable_ctrl.sw_dec_clk_gate_e = 1; + reg->reg57_enable_ctrl.sw_dec_out_dis = 0; + + reg->reg149_segment_map_base = mpp_buffer_get_fd(ctx->seg_map); + reg->reg61_qtable_base = mpp_buffer_get_fd(ctx->probe_table); + + FUN_T("FUN_OUT"); + return MPP_OK; +} + +static MPP_RET hal_vp8d_pre_filter_tap_set(VP8DHalContext_t *ctx) +{ + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + + FUN_T("FUN_IN"); + regs->reg59.sw_pred_bc_tap_0_0 = mcFilter[0][1]; + regs->reg59.sw_pred_bc_tap_0_1 = mcFilter[0][2]; + regs->reg59.sw_pred_bc_tap_0_2 = mcFilter[0][3]; + regs->reg153.sw_pred_bc_tap_0_3 = mcFilter[0][4]; + regs->reg153.sw_pred_bc_tap_1_0 = mcFilter[1][1]; + regs->reg153.sw_pred_bc_tap_1_1 = mcFilter[1][2]; + regs->reg154.sw_pred_bc_tap_1_2 = mcFilter[1][3]; + regs->reg154.sw_pred_bc_tap_1_3 = mcFilter[1][4]; + regs->reg154.sw_pred_bc_tap_2_0 = mcFilter[2][1]; + regs->reg155.sw_pred_bc_tap_2_1 = mcFilter[2][2]; + regs->reg155.sw_pred_bc_tap_2_2 = mcFilter[2][3]; + regs->reg155.sw_pred_bc_tap_2_3 = mcFilter[2][4]; + + regs->reg156.sw_pred_bc_tap_3_0 = mcFilter[3][1]; + regs->reg156.sw_pred_bc_tap_3_1 = mcFilter[3][2]; + regs->reg156.sw_pred_bc_tap_3_2 = mcFilter[3][3]; + regs->reg157.sw_pred_bc_tap_3_3 = mcFilter[3][4]; + regs->reg157.sw_pred_bc_tap_4_0 = mcFilter[4][1]; + regs->reg157.sw_pred_bc_tap_4_1 = mcFilter[4][2]; + regs->reg158.sw_pred_bc_tap_4_2 = mcFilter[4][3]; + regs->reg158.sw_pred_bc_tap_4_3 = mcFilter[4][4]; + regs->reg158.sw_pred_bc_tap_5_0 = mcFilter[5][1]; + + regs->reg125.sw_pred_bc_tap_5_1 = mcFilter[5][2]; + + regs->reg125.sw_pred_bc_tap_5_2 = mcFilter[5][3]; + + regs->reg125.sw_pred_bc_tap_5_3 = mcFilter[5][4]; + regs->reg126.sw_pred_bc_tap_6_0 = mcFilter[6][1]; + regs->reg126.sw_pred_bc_tap_6_1 = mcFilter[6][2]; + regs->reg126.sw_pred_bc_tap_6_2 = mcFilter[6][3]; + regs->reg127.sw_pred_bc_tap_6_3 = mcFilter[6][4]; + regs->reg127.sw_pred_bc_tap_7_0 = mcFilter[7][1]; + regs->reg127.sw_pred_bc_tap_7_1 = mcFilter[7][2]; + regs->reg128.sw_pred_bc_tap_7_2 = mcFilter[7][3]; + regs->reg128.sw_pred_bc_tap_7_3 = mcFilter[7][4]; + + regs->reg128.sw_pred_tap_2_M1 = mcFilter[2][0]; + regs->reg128.sw_pred_tap_2_4 = mcFilter[2][5]; + regs->reg128.sw_pred_tap_4_M1 = mcFilter[4][0]; + regs->reg128.sw_pred_tap_4_4 = mcFilter[4][5]; + regs->reg128.sw_pred_tap_6_M1 = mcFilter[6][0]; + regs->reg128.sw_pred_tap_6_4 = mcFilter[6][5]; + + FUN_T("FUN_OUT"); + return MPP_OK; +} + +static MPP_RET hal_vp8d_dct_partition_cfg(VP8DHalContext_t *ctx, + HalTaskInfo *task) +{ + RK_U32 i = 0, len = 0, len1 = 0; + RK_U32 extraBytesPacked = 0; + RK_U32 addr = 0, byte_offset = 0; + RK_U32 fd = 0; + MppBuffer streambuf = NULL; + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + DXVA_PicParams_VP8 *pic_param = (DXVA_PicParams_VP8 *)task->dec.syntax.data; + + FUN_T("FUN_IN"); + + mpp_buf_slot_get_prop(ctx->cfg->packet_slots, task->dec.input, SLOT_BUFFER, &streambuf); + fd = mpp_buffer_get_fd(streambuf); + regs->reg145_bitpl_ctrl_base = fd; + if (pic_param->stream_start_offset) + mpp_dev_set_reg_offset(ctx->cfg->dev, 145, pic_param->stream_start_offset); + + regs->reg122.sw_strm1_start_bit = pic_param->stream_start_bit; + + /* calculate dct partition length here instead */ + if (pic_param->decMode == VP8HWD_VP8 && !pic_param->frame_type) + extraBytesPacked += 7; + len = pic_param->streamEndPos + pic_param->frameTagSize + - pic_param->dctPartitionOffsets[0]; + len += ((1 << pic_param->log2_nbr_of_dct_partitions) - 1) * 3; + len1 = extraBytesPacked + pic_param->dctPartitionOffsets[0]; + len += (len1 & 0x7); + regs->reg51_stream_info.sw_stream_len = len; + + len = pic_param->offsetToDctParts + pic_param->frameTagSize - + (pic_param->stream_start_offset - extraBytesPacked); + len++; + + regs->reg124.sw_stream1_len = len; + regs->reg124.sw_coeffs_part_am = + (1 << pic_param->log2_nbr_of_dct_partitions) - 1; + for (i = 0; i < (RK_U32)(1 << pic_param->log2_nbr_of_dct_partitions); i++) { + addr = extraBytesPacked + pic_param->dctPartitionOffsets[i]; + byte_offset = addr & 0x7; + addr = addr & 0xFFFFFFF8; + + if (i == 0) { + regs->reg64_input_stream_base = fd; + if (addr) + mpp_dev_set_reg_offset(ctx->cfg->dev, 64, addr); + } else if (i <= 5) { + regs->reg_dct_strm_base[i - 1] = fd; + if (addr) + mpp_dev_set_reg_offset(ctx->cfg->dev, 139 + i, addr); + } else { + regs->reg_dct_strm1_base[i - 6] = fd; + if (addr) + mpp_dev_set_reg_offset(ctx->cfg->dev, 140 + i, addr); + } + + switch (i) { + case 0: + regs->reg122.sw_strm_start_bit = byte_offset * 8; + break; + case 1: + regs->reg121.sw_dct1_start_bit = byte_offset * 8; + break; + case 2: + regs->reg121.sw_dct2_start_bit = byte_offset * 8; + break; + case 3: + regs->reg150.sw_dct_start_bit_3 = byte_offset * 8; + break; + case 4: + regs->reg150.sw_dct_start_bit_4 = byte_offset * 8; + break; + case 5: + regs->reg150.sw_dct_start_bit_5 = byte_offset * 8; + break; + case 6: + regs->reg150.sw_dct_start_bit_6 = byte_offset * 8; + break; + case 7: + regs->reg150.sw_dct_start_bit_7 = byte_offset * 8; + break; + default: + break; + } + } + + FUN_T("FUN_OUT"); + return MPP_OK; +} + +static void hal_vp8hw_asic_probe_update(DXVA_PicParams_VP8 *p, RK_U8 *probTbl) +{ + RK_U8 *dst; + RK_U32 i, j, k; + + FUN_T("FUN_IN"); + /* first probs */ + dst = probTbl; + + dst[0] = p->probe_skip_false; + dst[1] = p->prob_intra; + dst[2] = p->prob_last; + dst[3] = p->prob_golden; + dst[4] = p->stVP8Segments.mb_segment_tree_probs[0]; + dst[5] = p->stVP8Segments.mb_segment_tree_probs[1]; + dst[6] = p->stVP8Segments.mb_segment_tree_probs[2]; + dst[7] = 0; /*unused*/ + + dst += 8; + dst[0] = p->intra_16x16_prob[0]; + dst[1] = p->intra_16x16_prob[1]; + dst[2] = p->intra_16x16_prob[2]; + dst[3] = p->intra_16x16_prob[3]; + dst[4] = p->intra_chroma_prob[0]; + dst[5] = p->intra_chroma_prob[1]; + dst[6] = p->intra_chroma_prob[2]; + dst[7] = 0; /*unused*/ + + /* mv probs */ + dst += 8; + dst[0] = p->vp8_mv_update_probs[0][0]; /* is short */ + dst[1] = p->vp8_mv_update_probs[1][0]; + dst[2] = p->vp8_mv_update_probs[0][1]; /* sign */ + dst[3] = p->vp8_mv_update_probs[1][1]; + dst[4] = p->vp8_mv_update_probs[0][8 + 9]; + dst[5] = p->vp8_mv_update_probs[0][9 + 9]; + dst[6] = p->vp8_mv_update_probs[1][8 + 9]; + dst[7] = p->vp8_mv_update_probs[1][9 + 9]; + dst += 8; + for ( i = 0 ; i < 2 ; ++i ) { + for ( j = 0 ; j < 8 ; j += 4 ) { + dst[0] = p->vp8_mv_update_probs[i][j + 9 + 0]; + dst[1] = p->vp8_mv_update_probs[i][j + 9 + 1]; + dst[2] = p->vp8_mv_update_probs[i][j + 9 + 2]; + dst[3] = p->vp8_mv_update_probs[i][j + 9 + 3]; + dst += 4; + } + } + for ( i = 0 ; i < 2 ; ++i ) { + dst[0] = p->vp8_mv_update_probs[i][0 + 2]; + dst[1] = p->vp8_mv_update_probs[i][1 + 2]; + dst[2] = p->vp8_mv_update_probs[i][2 + 2]; + dst[3] = p->vp8_mv_update_probs[i][3 + 2]; + dst[4] = p->vp8_mv_update_probs[i][4 + 2]; + dst[5] = p->vp8_mv_update_probs[i][5 + 2]; + dst[6] = p->vp8_mv_update_probs[i][6 + 2]; + dst[7] = 0; /*unused*/ + dst += 8; + } + + /* coeff probs (header part) */ + dst = (RK_U8*)probTbl; + dst += (8 * 7); + for ( i = 0 ; i < 4 ; ++i ) { + for ( j = 0 ; j < 8 ; ++j ) { + for ( k = 0 ; k < 3 ; ++k ) { + dst[0] = p->vp8_coef_update_probs[i][j][k][0]; + dst[1] = p->vp8_coef_update_probs[i][j][k][1]; + dst[2] = p->vp8_coef_update_probs[i][j][k][2]; + dst[3] = p->vp8_coef_update_probs[i][j][k][3]; + dst += 4; + } + } + } + + /* coeff probs (footer part) */ + dst = (RK_U8*)probTbl; + dst += (8 * 55); + for ( i = 0 ; i < 4 ; ++i ) { + for ( j = 0 ; j < 8 ; ++j ) { + for ( k = 0 ; k < 3 ; ++k ) { + dst[0] = p->vp8_coef_update_probs[i][j][k][4]; + dst[1] = p->vp8_coef_update_probs[i][j][k][5]; + dst[2] = p->vp8_coef_update_probs[i][j][k][6]; + dst[3] = p->vp8_coef_update_probs[i][j][k][7]; + dst[4] = p->vp8_coef_update_probs[i][j][k][8]; + dst[5] = p->vp8_coef_update_probs[i][j][k][9]; + dst[6] = p->vp8_coef_update_probs[i][j][k][10]; + dst[7] = 0; /*unused*/ + dst += 8; + } + } + } + FUN_T("FUN_OUT"); + return ; +} + +static MPP_RET hal_vp8d_vdpu2_gen_regs(void* hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + RK_U32 mb_width = 0, mb_height = 0; + MppBuffer framebuf = NULL; + RK_U8 *segmap_ptr = NULL; + RK_U8 *probe_ptr = NULL; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + DXVA_PicParams_VP8 *pic_param = (DXVA_PicParams_VP8 *)task->dec.syntax.data; + MppHalCfg *cfg = ctx->cfg; + + FUN_T("FUN_IN"); + + hal_vp8_init_hwcfg(ctx); + mb_width = (pic_param->width + 15) >> 4; + mb_height = (pic_param->height + 15) >> 4; + // mpp_log("mb_width = %d mb_height = %d", mb_width, mb_height); + regs->reg120.sw_pic_mb_width = mb_width & 0x1FF; + regs->reg120.sw_pic_mb_hight_p = mb_height & 0xFF; + regs->reg120.sw_pic_mb_w_ext = mb_width >> 9; + regs->reg120.sw_pic_mb_h_ext = mb_height >> 8; + + if (!pic_param->frame_type) { + segmap_ptr = mpp_buffer_get_ptr(ctx->seg_map); + if (NULL != segmap_ptr) { + memset(segmap_ptr, 0, VP8D_MAX_SEGMAP_SIZE); + } + } + + probe_ptr = mpp_buffer_get_ptr(ctx->probe_table); + if (NULL != probe_ptr) { + hal_vp8hw_asic_probe_update(pic_param, probe_ptr); + } + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->CurrPic.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg63_cur_pic_base = mpp_buffer_get_fd(framebuf); + if (!pic_param->frame_type) { //key frame + + regs->reg131_ref0_base = regs->reg63_cur_pic_base; + + mpp_dev_set_reg_offset(cfg->dev, 131, mb_width * mb_height); + } else if (pic_param->lst_fb_idx.Index7Bits < 0x7f) { //config ref0 base + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->lst_fb_idx.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg131_ref0_base = mpp_buffer_get_fd(framebuf); + } else { + regs->reg131_ref0_base = regs->reg63_cur_pic_base; + } + + /* golden reference */ + if (pic_param->gld_fb_idx.Index7Bits < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->gld_fb_idx.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg136_golden_ref_base = mpp_buffer_get_fd(framebuf); + } else { + regs->reg136_golden_ref_base = regs->reg63_cur_pic_base; + } + + regs->reg136_golden_ref_base = regs->reg136_golden_ref_base; + if (pic_param->ref_frame_sign_bias_golden) { + mpp_dev_set_reg_offset(cfg->dev, 136, pic_param->ref_frame_sign_bias_golden); + } + + /* alternate reference */ + if (pic_param->alt_fb_idx.Index7Bits < 0x7f) { + mpp_buf_slot_get_prop(cfg->frame_slots, pic_param->alt_fb_idx.Index7Bits, SLOT_BUFFER, &framebuf); + regs->reg137.alternate_ref_base = mpp_buffer_get_fd(framebuf); + } else { + regs->reg137.alternate_ref_base = regs->reg63_cur_pic_base; + } + + regs->reg137.alternate_ref_base = regs->reg137.alternate_ref_base; + if (pic_param->ref_frame_sign_bias_altref) + mpp_dev_set_reg_offset(cfg->dev, 137, pic_param->ref_frame_sign_bias_altref); + + regs->reg149_segment_map_base = regs->reg149_segment_map_base; + if (pic_param->stVP8Segments.segmentation_enabled + (pic_param->stVP8Segments.update_mb_segmentation_map << 1)) + mpp_dev_set_reg_offset(cfg->dev, 149, pic_param->stVP8Segments.segmentation_enabled + + (pic_param->stVP8Segments.update_mb_segmentation_map << 1)); + + regs->reg57_enable_ctrl.sw_pic_inter_e = pic_param->frame_type; + regs->reg50_dec_ctrl.sw_skip_mode = !pic_param->mb_no_coeff_skip; + + if (!pic_param->stVP8Segments.segmentation_enabled) { + regs->reg129.sw_filt_level_0 = pic_param->filter_level; + } else if (pic_param->stVP8Segments.update_mb_segmentation_data) { + regs->reg129.sw_filt_level_0 = pic_param->stVP8Segments.segment_feature_data[1][0]; + regs->reg129.sw_filt_level_1 = pic_param->stVP8Segments.segment_feature_data[1][1]; + regs->reg129.sw_filt_level_2 = pic_param->stVP8Segments.segment_feature_data[1][2]; + regs->reg129.sw_filt_level_3 = pic_param->stVP8Segments.segment_feature_data[1][3]; + } else { + regs->reg129.sw_filt_level_0 = CLIP3(0, 63, (RK_S32)pic_param->filter_level + pic_param->stVP8Segments.segment_feature_data[1][0]); + regs->reg129.sw_filt_level_1 = CLIP3(0, 63, (RK_S32)pic_param->filter_level + pic_param->stVP8Segments.segment_feature_data[1][1]); + regs->reg129.sw_filt_level_2 = CLIP3(0, 63, (RK_S32)pic_param->filter_level + pic_param->stVP8Segments.segment_feature_data[1][2]); + regs->reg129.sw_filt_level_3 = CLIP3(0, 63, (RK_S32)pic_param->filter_level + pic_param->stVP8Segments.segment_feature_data[1][3]); + } + + regs->reg132.sw_filt_type = pic_param->filter_type; + regs->reg132.sw_filt_sharpness = pic_param->sharpness; + + if (pic_param->filter_level == 0) { + regs->reg50_dec_ctrl.sw_filtering_dis = 1; + } + + if (pic_param->version != 3) { + regs->reg121.sw_romain_mv = 1; + } + + if (pic_param->decMode == VP8HWD_VP8 && (pic_param->version & 0x3)) { + regs->reg121.sw_eable_bilinear = 1; + } + regs->reg122.sw_boolean_value = pic_param->bool_value; + regs->reg122.sw_boolean_range = pic_param->bool_range; + + { + if (!pic_param->stVP8Segments.segmentation_enabled) + regs->reg130.sw_quant_0 = pic_param->y1ac_delta_q; + else if (pic_param->stVP8Segments.update_mb_segmentation_data) { /* absolute mode */ + regs->reg130.sw_quant_0 = pic_param->stVP8Segments.segment_feature_data[0][0]; + regs->reg130.sw_quant_1 = pic_param->stVP8Segments.segment_feature_data[0][1]; + regs->reg151.sw_quant_2 = pic_param->stVP8Segments.segment_feature_data[0][2]; + regs->reg151.sw_quant_3 = pic_param->stVP8Segments.segment_feature_data[0][3]; + } else { /* delta mode */ + regs->reg130.sw_quant_0 = CLIP3(0, 127, pic_param->y1ac_delta_q + pic_param->stVP8Segments.segment_feature_data[0][0]); + regs->reg130.sw_quant_1 = CLIP3(0, 127, pic_param->y1ac_delta_q + pic_param->stVP8Segments.segment_feature_data[0][1]); + regs->reg151.sw_quant_2 = CLIP3(0, 127, pic_param->y1ac_delta_q + pic_param->stVP8Segments.segment_feature_data[0][2]); + regs->reg151.sw_quant_3 = CLIP3(0, 127, pic_param->y1ac_delta_q + pic_param->stVP8Segments.segment_feature_data[0][3]); + } + + regs->reg130.sw_quant_delta_0 = pic_param->y1dc_delta_q; + regs->reg130.sw_quant_delta_1 = pic_param->y2dc_delta_q; + regs->reg151.sw_quant_delta_2 = pic_param->y2ac_delta_q; + regs->reg151.sw_quant_delta_3 = pic_param->uvdc_delta_q; + regs->reg152.sw_quant_delta_4 = pic_param->uvac_delta_q; + + if (pic_param->mode_ref_lf_delta_enabled) { + regs->reg133.sw_filt_ref_adj_0 = pic_param->ref_lf_deltas[0]; + regs->reg133.sw_filt_ref_adj_1 = pic_param->ref_lf_deltas[1]; + regs->reg133.sw_filt_ref_adj_2 = pic_param->ref_lf_deltas[2]; + regs->reg133.sw_filt_ref_adj_3 = pic_param->ref_lf_deltas[3]; + regs->reg132.sw_filt_mb_adj_0 = pic_param->mode_lf_deltas[0]; + regs->reg132.sw_filt_mb_adj_1 = pic_param->mode_lf_deltas[1]; + regs->reg132.sw_filt_mb_adj_2 = pic_param->mode_lf_deltas[2]; + regs->reg132.sw_filt_mb_adj_3 = pic_param->mode_lf_deltas[3]; + } + + } + + if ((pic_param->version & 0x3) == 0) + hal_vp8d_pre_filter_tap_set(ctx); + + hal_vp8d_dct_partition_cfg(ctx, task); + regs->reg57_enable_ctrl.sw_dec_e = 1; + + mpp_buffer_sync_end(ctx->probe_table); + mpp_buffer_sync_end(ctx->seg_map); + + FUN_T("FUN_OUT"); + return ret; +} + +static void hal_vp8d_vdpu2_dump_info(void *hal, HalTaskInfo *task) +{ + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + (void)task; + FILE *fp; + char name[256]; + static RK_U32 frame_cnt = 0; + RK_U32 i; + RK_U32 *p; + + sprintf(name, "/data/video/reg_%d.bin", frame_cnt++); + fp = fopen(name, "ab+"); + if (fp) { + p = (RK_U32*)ctx->regs; + + for (i = 0; i < VP8D_REG_NUM; i++) + fprintf(fp, "reg[%d] %#08x\n", i, p[i]); + fclose(fp); + } + + sprintf(name, "/data/video/seg_map_%d.bin", frame_cnt); + fp = fopen(name, "ab+"); + if (fp) { + p = (RK_U32*)mpp_buffer_get_ptr(ctx->seg_map); + + for (i = 0; i < mpp_buffer_get_size(ctx->seg_map) / 4; i++) + fprintf(fp, "%#08x\n", p[i]); + fclose(fp); + } + + sprintf(name, "/data/video/probe_%d.bin", frame_cnt); + fp = fopen(name, "ab+"); + if (fp) { + p = (RK_U32*)mpp_buffer_get_ptr(ctx->probe_table); + + for (i = 0; i < mpp_buffer_get_size(ctx->probe_table) / 4; i++) + fprintf(fp, "%#08x\n", p[i]); + fclose(fp); + } +} + +static MPP_RET hal_vp8d_vdpu2_start(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + MppDev dev = ctx->cfg->dev; + VP8DRegSet_t *regs = (VP8DRegSet_t *)ctx->regs; + + FUN_T("FUN_IN"); + if (hal_vp8d_debug & VP8H_DBG_DUMP_REG) + hal_vp8d_vdpu2_dump_info(hal, task); + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = sizeof(VP8DRegSet_t); + + wr_cfg.reg = regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + FUN_T("FUN_OUT"); + + (void)task; + return ret; +} + +static MPP_RET hal_vp8d_vdpu2_wait(void *hal, HalTaskInfo *task) +{ + MPP_RET ret = MPP_OK; + VP8DHalContext_t *ctx = (VP8DHalContext_t *)hal; + MppDev dev = ctx->cfg->dev; + + FUN_T("FUN_IN"); + + ret = mpp_dev_ioctl(dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + (void)task; + FUN_T("FUN_OUT"); + return ret; +} + +const MppHalApi hal_vp8d_vdpu2 = { + .name = "vp8d_vdpu2", + .type = MPP_CTX_DEC, + .coding = MPP_VIDEO_CodingVP8, + .ctx_size = sizeof(VP8DHalContext_t), + .flag = 0, + .init = hal_vp8d_vdpu2_init, + .deinit = hal_vp8d_vdpu2_deinit, + .reg_gen = hal_vp8d_vdpu2_gen_regs, + .start = hal_vp8d_vdpu2_start, + .wait = hal_vp8d_vdpu2_wait, + .reset = NULL, + .flush = NULL, + .control = NULL, + .client = VPU_CLIENT_VDPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_DEC_HAL_API_REGISTER(hal_vp8d_vdpu2) diff --git a/mpp/codec/inc/vp8e_api.h b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2.h similarity index 77% rename from mpp/codec/inc/vp8e_api.h rename to mpp/hal/vpu/vp8d/hal_vp8d_vdpu2.h index 71c6a1fc7..852949bb1 100644 --- a/mpp/codec/inc/vp8e_api.h +++ b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2.h @@ -1,22 +1,24 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VP8E_API_H__ -#define __VP8E_API_H__ - - - -#endif /*__VP8E_API_H__*/ \ No newline at end of file +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8D_VDPU2_H +#define HAL_VP8D_VDPU2_H + +#include "hal_vp8d_base.h" + +extern const MppHalApi hal_vp8d_vdpu2; + +#endif diff --git a/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2_reg.h b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2_reg.h new file mode 100644 index 000000000..627c6a6ac --- /dev/null +++ b/mpp/hal/vpu/vp8d/hal_vp8d_vdpu2_reg.h @@ -0,0 +1,414 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8D_VDPU2_REG_H +#define HAL_VP8D_VDPU2_REG_H +#include "rk_type.h" + +#define VP8HWD_VP7 1 +#define VP8HWD_VP8 2 +#define VP8HWD_WEBP 3 + +#define DEC_MODE_VP7 9 +#define DEC_MODE_VP8 10 + +#define VP8D_PROB_TABLE_SIZE (1<<16) /* TODO */ +#define VP8D_MAX_SEGMAP_SIZE (2048 + 1024) //1920*1080 + +#define VP8D_REG_NUM 159 + +typedef struct { + RK_U32 ppReg[50]; + struct { + RK_U32 sw_dec_out_tiled_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_skip_mode : 1; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_priority_mode : 1; + RK_U32 sw_refbu2_thr : 12; + RK_U32 sw_refbu2_picid : 5; + RK_U32 reserve1 : 2; + } reg50_dec_ctrl; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 reserve1 : 1; + RK_U32 sw_init_qp : 6; + RK_U32 reserve2 : 1; + } reg51_stream_info; + + struct { + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + RK_U32 sw_apf_threshold : 14; + RK_U32 sw_reserve : 1; + } reg52_error_concealment; + + RK_U32 reg53_dec_mode; + + struct { + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 reserve3 : 26; + } reg54_endian; + + struct { + RK_U32 sw_dec_irq : 1; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buffer_int : 1; + RK_U32 reserve1 : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_pic_inf : 1; + RK_U32 reserve2 : 1; + RK_U32 sw_dec_error_int: 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserve3 : 18; + } reg55_Interrupt; + + struct { + RK_U32 sw_dec_axi_rn_id : 8; + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 sw_dec_max_burst : 5; + RK_U32 resever : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 resever1 : 9; + } reg56_axi_ctrl; + + struct { + RK_U32 sw_dec_e : 1; + RK_U32 sw_refbu2_buf_e : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 resever : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1 ; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_start_code_e : 1; + RK_U32 resever1 : 8; + RK_U32 sw_dec_ahb_hlock_e : 1; + + } reg57_enable_ctrl; + + RK_U32 reg58_soft_rest; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_0_2 : 10; + RK_S32 sw_pred_bc_tap_0_1 : 10; + RK_S32 sw_pred_bc_tap_0_0 : 10; + } reg59; + + RK_U32 reg60_addit_ch_st_base; + RK_U32 reg61_qtable_base; + RK_U32 reg62_directmv_base; + RK_U32 reg63_cur_pic_base; + RK_U32 reg64_input_stream_base; + + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 sw_reserve : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } reg65_refpicbuf_ctrl; + + struct { + RK_U32 build_version : 3; + RK_U32 product_IDen : 1; + RK_U32 minor_version : 8; + RK_U32 major_version : 4; + RK_U32 product_numer : 16; + } reg66_id; + + struct { + RK_U32 sw_reserve : 25; + RK_U32 sw_dec_rtl_rom : 1; + RK_U32 sw_dec_rv_prof : 2; + RK_U32 sw_ref_buff2_exist : 1; + RK_U32 sw_dec_divx_prof : 1; + RK_U32 sw_dec_refbu_ilace : 1; + RK_U32 sw_dec_jpeg_exten : 1; + } reg67_synthesis_cfg; + + struct { + RK_U32 sw_refbu_top_sum : 16; + RK_U32 sw_refbu_bot_sum : 16; + } reg68_sum_of_partitions; + + struct { + RK_U32 sw_refbu_intra_sum : 16; + RK_U32 sw_refbu_hit_sum : 16; + } reg69_sum_inf; + + struct { + RK_U32 sw_refbu_mv_sum : 22; + RK_U32 sw_reserve : 10; + } reg70_sum_mv; + + RK_U32 reg71_119_reserve[49]; + + struct { + RK_U32 sw_pic_mb_h_ext : 3; + RK_U32 sw_pic_mb_w_ext : 3; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } reg120; + + struct { + RK_U32 sw_resever : 5; + RK_U32 sw_vp7_version : 1; + RK_U32 sw_dc_match0 : 3; + RK_U32 sw_dc_match1 : 3; + RK_U32 sw_eable_bilinear : 1; + RK_U32 sw_romain_mv : 1; + RK_U32 sw_resever1 : 6; + RK_U32 sw_dct2_start_bit : 6; + RK_U32 sw_dct1_start_bit : 6; + } reg121; + + struct { + RK_U32 sw_boolean_range : 8; + RK_U32 sw_boolean_value : 8; + RK_U32 sw_multistream_e : 1; + RK_U32 sw_huffman_e : 1; + RK_U32 sw_strm1_start_bit : 6; + RK_U32 sw_resever : 2; + RK_U32 sw_strm_start_bit : 6; + } reg122; + + struct { + RK_U32 sw_dc_comp1 : 16; + RK_U32 sw_dc_comp0 : 16; + } reg123; + + struct { + RK_U32 sw_stream1_len : 24; + RK_U32 sw_coeffs_part_am : 4; + RK_U32 sw_resever : 4; + } reg124; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_5_3 : 10; + RK_S32 sw_pred_bc_tap_5_2 : 10; + RK_S32 sw_pred_bc_tap_5_1 : 10; + } reg125; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_6_2 : 10; + RK_S32 sw_pred_bc_tap_6_1 : 10; + RK_S32 sw_pred_bc_tap_6_0 : 10; + } reg126; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_7_1 : 10; + RK_S32 sw_pred_bc_tap_7_0 : 10; + RK_S32 sw_pred_bc_tap_6_3 : 10; + } reg127; + + struct { + RK_U32 sw_pred_tap_6_4 : 2; + RK_U32 sw_pred_tap_6_M1 : 2; + RK_U32 sw_pred_tap_4_4 : 2; + RK_U32 sw_pred_tap_4_M1 : 2; + RK_U32 sw_pred_tap_2_4 : 2; + RK_U32 sw_pred_tap_2_M1 : 2; + RK_S32 sw_pred_bc_tap_7_3 : 10; + RK_S32 sw_pred_bc_tap_7_2 : 10; + } reg128; + + struct { + RK_U32 sw_filt_level_3 : 6; + RK_U32 sw_filt_level_2 : 6; + RK_U32 sw_filt_level_1 : 6; + RK_U32 sw_filt_level_0 : 6; + RK_U32 resever : 8; + } reg129; + + struct { + RK_U32 sw_quant_1 : 11; + RK_U32 sw_quant_0 : 11; + RK_U32 sw_quant_delta_1 : 5; + RK_U32 sw_quant_delta_0 : 5; + } reg130; + + + RK_U32 reg131_ref0_base; + + struct { + RK_U32 sw_filt_mb_adj_3 : 7; + RK_U32 sw_filt_mb_adj_2 : 7; + RK_U32 sw_filt_mb_adj_1 : 7; + RK_U32 sw_filt_mb_adj_0 : 7; + RK_U32 sw_filt_sharpness : 3; + RK_U32 sw_filt_type : 1; + } reg132; + + + struct { + RK_U32 sw_filt_ref_adj_3 : 7; + RK_U32 sw_filt_ref_adj_2 : 7; + RK_U32 sw_filt_ref_adj_1 : 7; + RK_U32 sw_filt_ref_adj_0 : 7; + RK_U32 sw_resver : 4; + } reg133; + + RK_U32 reg134; + RK_U32 reg135; + + RK_U32 reg136_golden_ref_base; + + union { + RK_U32 alternate_ref_base; + struct { + RK_U32 sw_scan_map_5 : 6; + RK_U32 sw_scan_map_4 : 6; + RK_U32 sw_scan_map_3 : 6; + RK_U32 sw_scan_map_2 : 6; + RK_U32 sw_scan_map_1 : 6; + RK_U32 sw_resver : 2; + }; + } reg137; + + struct { + RK_U32 sw_scan_map_10 : 6; + RK_U32 sw_scan_map_9 : 6; + RK_U32 sw_scan_map_8 : 6; + RK_U32 sw_scan_map_7 : 6; + RK_U32 sw_scan_map_6 : 6; + RK_U32 sw_resver : 2; + } reg138; + + struct { + RK_U32 sw_scan_map_15 : 6; + RK_U32 sw_scan_map_14 : 6; + RK_U32 sw_scan_map_13 : 6; + RK_U32 sw_scan_map_12 : 6; + RK_U32 sw_scan_map_11 : 6; + RK_U32 sw_resver : 2; + } reg139; + + RK_U32 reg_dct_strm_base[5]; + RK_U32 reg145_bitpl_ctrl_base; + RK_U32 reg_dct_strm1_base[2]; + + struct { + RK_U32 sw_slice_h : 8; + RK_U32 sw_resver : 24; + } reg148; + + RK_U32 reg149_segment_map_base; + + + struct { + RK_U32 sw_dct_start_bit_7 : 6; + RK_U32 sw_dct_start_bit_6 : 6; + RK_U32 sw_dct_start_bit_5 : 6; + RK_U32 sw_dct_start_bit_4 : 6; + RK_U32 sw_dct_start_bit_3 : 6; + RK_U32 sw_resver : 2; + } reg150; + + struct { + RK_U32 sw_quant_3 : 11; + RK_U32 sw_quant_2 : 11; + RK_U32 sw_quant_delta_3 : 5; + RK_U32 sw_quant_delta_2 : 5; + } reg151; + + struct { + RK_U32 sw_quant_5 : 11; + RK_U32 sw_quant_4 : 11; + RK_U32 sw_resver : 5; + RK_U32 sw_quant_delta_4 : 5; + } reg152; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_1_1 : 10; + RK_S32 sw_pred_bc_tap_1_0 : 10; + RK_S32 sw_pred_bc_tap_0_3 : 10; + } reg153; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_2_0 : 10; + RK_S32 sw_pred_bc_tap_1_3 : 10; + RK_S32 sw_pred_bc_tap_1_2 : 10; + } reg154; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_2_3 : 10; + RK_S32 sw_pred_bc_tap_2_2 : 10; + RK_S32 sw_pred_bc_tap_2_1 : 10; + } reg155; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_3_2 : 10; + RK_S32 sw_pred_bc_tap_3_1 : 10; + RK_S32 sw_pred_bc_tap_3_0 : 10; + } reg156; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_4_1 : 10; + RK_S32 sw_pred_bc_tap_4_0 : 10; + RK_S32 sw_pred_bc_tap_3_3 : 10; + } reg157; + + struct { + RK_U32 resever : 2; + RK_S32 sw_pred_bc_tap_5_0 : 10; + RK_S32 sw_pred_bc_tap_4_3 : 10; + RK_S32 sw_pred_bc_tap_4_2 : 10; + } reg158; +} VP8DRegSet_t; + +#endif diff --git a/mpp/hal/vpu/vp8e/CMakeLists.txt b/mpp/hal/vpu/vp8e/CMakeLists.txt new file mode 100644 index 000000000..c0dfb0779 --- /dev/null +++ b/mpp/hal/vpu/vp8e/CMakeLists.txt @@ -0,0 +1,16 @@ +# vim: syntax=cmake +include_directories(../common/) + +set(HAL_VP8E_SRC + hal_vp8e_putbit.c + hal_vp8e_table.c + hal_vp8e_entropy.c + hal_vp8e_base.c + ) + +add_hal_source(HAL_VP8E_SRC HAVE_VEPU1 hal_vp8e_vepu1_v2.c) +add_hal_source(HAL_VP8E_SRC HAVE_VEPU2 hal_vp8e_vepu2_v2.c) + +if (HAL_VP8E_SRC) + add_library(hal_vp8e_api OBJECT ${HAL_VP8E_SRC}) +endif() diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_base.c b/mpp/hal/vpu/vp8e/hal_vp8e_base.c new file mode 100644 index 000000000..0063ebbc3 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_base.c @@ -0,0 +1,1685 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp8e_base" + +#include + +#include "mpp_mem.h" +#include "mpp_buffer.h" +#include "mpp_common.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_putbit.h" +#include "hal_vp8e_table.h" +#include "hal_vp8e_debug.h" + +static MPP_RET set_frame_params(void *hal) +{ + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + { + RK_S32 i; + Pps *pps = ctx->ppss.pps; + Vp8eSps *sps = &ctx->sps; + + for (i = 0; i < 4; i++) { + pps->qp_sgm[i] = ctx->rc->qp_hdr; + pps->level_sgm[i] = sps->filter_level; + } + } + + return MPP_OK; +} + +static MPP_RET set_filter(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eSps *sps = &ctx->sps; + + if (sps->auto_filter_level) { + RK_U32 qp = 36; + Pps *p_pps = ctx->ppss.pps; + if (ctx->frame_type == VP8E_FRM_KEY) { + RK_S32 tmp = (qp * 64) / 128 + 8; + sps->filter_level = MPP_CLIP3(0, 63, tmp); + p_pps->level_sgm[0] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[0] * 64) / 128 + 8); + p_pps->level_sgm[1] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[1] * 64) / 128 + 8); + p_pps->level_sgm[2] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[2] * 64) / 128 + 8); + p_pps->level_sgm[3] = MPP_CLIP3(0, 63, (p_pps->qp_sgm[3] * 64) / 128 + 8); + } else { + sps->filter_level = inter_level_tbl[qp]; + p_pps->level_sgm[0] = inter_level_tbl[p_pps->qp_sgm[0]]; + p_pps->level_sgm[1] = inter_level_tbl[p_pps->qp_sgm[1]]; + p_pps->level_sgm[2] = inter_level_tbl[p_pps->qp_sgm[2]]; + p_pps->level_sgm[3] = inter_level_tbl[p_pps->qp_sgm[3]]; + } + } + + if (sps->auto_filter_sharpness) { + sps->filter_sharpness = 0; + } + + if (!sps->filter_delta_enable) + return MPP_NOK; + + if (sps->filter_delta_enable == 2) { + sps->filter_delta_enable = 1; + return MPP_NOK; + } + + if (sps->filter_level == 0) { + sps->ref_delta[0] = 0; /* Intra frame */ + sps->ref_delta[1] = 0; /* Last frame */ + sps->ref_delta[2] = 0; /* Golden frame */ + sps->ref_delta[3] = 0; /* Altref frame */ + sps->mode_delta[0] = 0; /* BPRED */ + sps->mode_delta[1] = 0; /* Zero */ + sps->mode_delta[2] = 0; /* New mv */ + sps->mode_delta[3] = 0; /* Split mv */ + return MPP_NOK; + } + + if (!ctx->picbuf.cur_pic->ipf && !ctx->picbuf.cur_pic->grf && + !ctx->picbuf.cur_pic->arf) { + memcpy(sps->ref_delta, sps->old_ref_delta, sizeof(sps->ref_delta)); + memcpy(sps->mode_delta, sps->old_mode_delta, sizeof(sps->mode_delta)); + return MPP_NOK; + } + + sps->ref_delta[0] = 2; /* Intra frame */ + sps->ref_delta[1] = 0; /* Last frame */ + sps->ref_delta[2] = -2; /* Golden frame */ + sps->ref_delta[3] = -2; /* Altref frame */ + + sps->mode_delta[0] = 4; /* BPRED */ + sps->mode_delta[1] = -2; /* Zero */ + sps->mode_delta[2] = 2; /* New mv */ + sps->mode_delta[3] = 4; /* Split mv */ + + { + RK_U32 i = 0; + for (i = 0; i < 4; i++) { + sps->ref_delta[i] = MPP_CLIP3(-0x3f, 0x3f, sps->ref_delta[i]); + sps->mode_delta[i] = MPP_CLIP3(-0x3f, 0x3f, sps->mode_delta[i]); + } + } + return MPP_OK; +} + +static MPP_RET set_segmentation(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8ePps *ppss = &ctx->ppss; + Pps *pps = ppss->pps; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + { + RK_S32 qp = ctx->rc->qp_hdr; + + if (hw_cfg->roi1_delta_qp) + pps->qp_sgm[1] = MPP_CLIP3(0, 127, qp - hw_cfg->roi1_delta_qp); + + if (hw_cfg->roi2_delta_qp) + pps->qp_sgm[2] = MPP_CLIP3(0, 127, qp - hw_cfg->roi2_delta_qp); + } + + { + RK_U32 x, y, mb, mask, id; + RK_U32 *map = mpp_buffer_get_ptr(buffers->hw_segment_map_buf); + RK_U32 *map_bck = map; + RK_U32 mapSize = (ctx->mb_per_frame + 15) / 16 * 8; + + mpp_buffer_sync_begin(buffers->hw_segment_map_buf); + + if (hw_cfg->roi1_delta_qp || hw_cfg->roi2_delta_qp) { + pps->segment_enabled = 1; + + memset(pps->sgm.id_cnt, 0, sizeof(pps->sgm.id_cnt)); + + for (y = 0, mb = 0, mask = 0; y < ctx->mb_per_col; y++) { + for (x = 0; x < ctx->mb_per_row; x++) { + id = 0; + if ((x >= hw_cfg->roi1_left) && (x <= hw_cfg->roi1_right) && + (y >= hw_cfg->roi1_top) && (y <= hw_cfg->roi1_bottom)) + id = 1; + if ((x >= hw_cfg->roi1_left) && (x <= hw_cfg->roi2_right) && + (y >= hw_cfg->roi2_top) && (y <= hw_cfg->roi2_bottom)) + id = 2; + + pps->sgm.id_cnt[id]++; + + mask |= id << (28 - 4 * (mb % 8)); + if ((mb % 8) == 7) { + *map++ = mask; + mask = 0; + } + mb++; + } + } + *map++ = mask; + vp8e_swap_endian(map_bck, mapSize); + } else if (pps->segment_enabled && pps->sgm.map_modified) { + memset(pps->sgm.id_cnt, 0, sizeof(pps->sgm.id_cnt)); + + for (mb = 0, mask = 0; mb < mapSize / 4; mb++) { + mask = map[mb]; + for (x = 0; x < 8; x++) { + if (mb * 8 + x < ctx->mb_per_frame) { + id = (mask >> (28 - 4 * x)) & 0xF; + pps->sgm.id_cnt[id]++; + } + } + } + vp8e_swap_endian(map_bck, mapSize); + } + + mpp_buffer_sync_end(buffers->hw_segment_map_buf); + } + if (ctx->picbuf.cur_pic->i_frame || !pps->segment_enabled) { + memset(ppss->qp_sgm, 0xff, sizeof(ppss->qp_sgm)); + memset(ppss->level_sgm, 0xff, sizeof(ppss->level_sgm)); + ppss->prev_pps = NULL; + } else + ppss->prev_pps = ppss->pps; + + return MPP_OK; +} + +static void set_intra_pred_penalties(Vp8eHwCfg *hw_cfg, RK_U32 qp) +{ + RK_S32 i, tmp; + + /* Intra 4x4 mode */ + tmp = qp * 2 + 8; + for (i = 0; i < 10; i++) { + hw_cfg->intra_b_mode_penalty[i] = (intra4_mode_tree_penalty_tbl[i] * tmp) >> 8; + } + + /* Intra 16x16 mode */ + tmp = qp * 2 + 64; + for (i = 0; i < 4; i++) { + hw_cfg->intra_mode_penalty[i] = (intra16_mode_tree_penalty_tbl[i] * tmp) >> 8; + } + + /* If favor has not been set earlier by testId use default */ + if (hw_cfg->intra_16_favor == -1) + hw_cfg->intra_16_favor = qp * 1024 / 128; +} + +static void set_hdr_segmentation(Vp8ePutBitBuf *bitbuf, Vp8ePps *ppss, + Vp8eHalEntropy *entropy) +{ + RK_S32 i, tmp; + RK_U8 data_modified = 0; + + Pps *pps = ppss->pps; + Sgm *sgm = &ppss->pps->sgm; + + if (memcmp(ppss->qp_sgm, pps->qp_sgm, sizeof(ppss->qp_sgm))) + data_modified = 1; + + if (memcmp(ppss->level_sgm, pps->level_sgm, sizeof(ppss->level_sgm))) + data_modified = 1; + + if (!ppss->prev_pps) { + sgm->map_modified = 1; + } + + vp8e_put_lit(bitbuf, sgm->map_modified, 1); + vp8e_put_lit(bitbuf, data_modified, 1); + + if (data_modified) { + vp8e_put_lit(bitbuf, 1, 1); + + for (i = 0; i < SGM_CNT; i++) { + tmp = pps->qp_sgm[i]; + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 7); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + + for (i = 0; i < SGM_CNT; i++) { + tmp = pps->level_sgm[i]; + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 6); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + } + + if (sgm->map_modified) { + RK_S32 sum1 = sgm->id_cnt[0] + sgm->id_cnt[1]; + RK_S32 sum2 = sgm->id_cnt[2] + sgm->id_cnt[3]; + + tmp = 255 * sum1 / (sum1 + sum2); + entropy->segment_prob[0] = MPP_CLIP3(1, 255, tmp); + + tmp = (sum1 != 0) ? 255 * sgm->id_cnt[0] / sum1 : 255; + entropy->segment_prob[1] = MPP_CLIP3(1, 255, tmp); + + tmp = (sum2 != 0) ? 255 * sgm->id_cnt[2] / sum2 : 255; + entropy->segment_prob[2] = MPP_CLIP3(1, 255, tmp); + + for (i = 0; i < 3; i++) { + if (sgm->id_cnt[i] != 0) { + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, entropy->segment_prob[i], 8); + } else { + vp8e_put_lit(bitbuf, 0, 1); + } + } + } + + memcpy(ppss->qp_sgm, pps->qp_sgm, sizeof(ppss->qp_sgm)); + memcpy(ppss->level_sgm, pps->level_sgm, sizeof(ppss->level_sgm)); +} + +static void set_filter_level_delta(Vp8ePutBitBuf *bitbuf, Vp8eSps *sps) +{ + RK_S32 i, tmp; + RK_U8 update = 0; + RK_S32 mode_update[4]; + RK_S32 ref_update[4]; + + for (i = 0; i < 4; i++) { + mode_update[i] = sps->mode_delta[i] != sps->old_mode_delta[i]; + ref_update[i] = sps->ref_delta[i] != sps->old_ref_delta[i]; + if (mode_update[i] || ref_update[i]) + update = 1; + } + + if (!sps->refresh_entropy) + update = 1; + + vp8e_put_lit(bitbuf, update, 1); + if (!update) + return; + + for (i = 0; i < 4; i++) { + vp8e_put_lit(bitbuf, ref_update[i], 1); + if (ref_update[i]) { + tmp = sps->ref_delta[i]; + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 6); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + } + + for (i = 0; i < 4; i++) { + vp8e_put_lit(bitbuf, mode_update[i], 1); + if (mode_update[i]) { + tmp = sps->mode_delta[i]; + vp8e_put_lit(bitbuf, MPP_ABS(tmp), 6); + vp8e_put_lit(bitbuf, tmp < 0, 1); + } + } + + memcpy(sps->old_ref_delta, sps->ref_delta, sizeof(sps->ref_delta)); + memcpy(sps->old_mode_delta, sps->mode_delta, sizeof(sps->mode_delta)); +} + +static MPP_RET set_frame_header(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eSps *sps = &ctx->sps; + Pps *pps = ctx->ppss.pps; + + Vp8ePutBitBuf *bitbuf = &ctx->bitbuf[1]; + HalVp8eRefPic *cur_pic = ctx->picbuf.cur_pic; + Vp8eHalEntropy *entropy = &ctx->entropy; + + if (cur_pic->i_frame) { + vp8e_put_lit(bitbuf, sps->color_type, 1); + + vp8e_put_lit(bitbuf, sps->clamp_type, 1); + } + + vp8e_put_lit(bitbuf, pps->segment_enabled, 1); + if (pps->segment_enabled) + set_hdr_segmentation(bitbuf, &ctx->ppss, entropy); + + vp8e_put_lit(bitbuf, sps->filter_type, 1); + + vp8e_put_lit(bitbuf, sps->filter_level, 6); + + vp8e_put_lit(bitbuf, sps->filter_sharpness, 3); + + vp8e_put_lit(bitbuf, sps->filter_delta_enable, 1); + if (sps->filter_delta_enable) { + /* Filter level delta references reset by key frame */ + if (cur_pic->i_frame) { + memset(sps->old_ref_delta, 0, sizeof(sps->ref_delta)); + memset(sps->old_mode_delta, 0, sizeof(sps->mode_delta)); + } + set_filter_level_delta(bitbuf, sps); + } + + vp8e_put_lit(bitbuf, sps->dct_partitions, 2); + + vp8e_put_lit(bitbuf, ctx->rc->qp_hdr, 7); + + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + + if (!cur_pic->i_frame) { + HalVp8eRefPic *ref_pic_list = ctx->picbuf.ref_pic_list; + + vp8e_put_lit(bitbuf, cur_pic->grf, 1); /* Grf refresh */ + vp8e_put_lit(bitbuf, cur_pic->arf, 1); /* Arf refresh */ + + if (!cur_pic->grf) { + if (ref_pic_list[0].grf) { + vp8e_put_lit(bitbuf, 1, 2); /* Ipf -> grf */ + } else if (ref_pic_list[2].grf) { + vp8e_put_lit(bitbuf, 2, 2); /* Arf -> grf */ + } else { + vp8e_put_lit(bitbuf, 0, 2); /* Not updated */ + } + } + + if (!cur_pic->arf) { + if (ref_pic_list[0].arf) { + vp8e_put_lit(bitbuf, 1, 2); /* Ipf -> arf */ + } else if (ref_pic_list[1].arf) { + vp8e_put_lit(bitbuf, 2, 2); /* Grf -> arf */ + } else { + vp8e_put_lit(bitbuf, 0, 2); /* Not updated */ + } + } + + vp8e_put_lit(bitbuf, sps->sing_bias[1], 1); /* Grf */ + vp8e_put_lit(bitbuf, sps->sing_bias[2], 1); /* Arf */ + } + + vp8e_put_lit(bitbuf, sps->refresh_entropy, 1); + if (!cur_pic->i_frame) { + vp8e_put_lit(bitbuf, cur_pic->ipf, 1); + } + vp8e_calc_coeff_prob(bitbuf, &entropy->coeff_prob, &entropy->old_coeff_prob); + vp8e_put_lit(bitbuf, 1, 1); + vp8e_put_lit(bitbuf, entropy->skip_false_prob, 8); + + if (cur_pic->i_frame) + return MPP_OK; + + vp8e_put_lit(bitbuf, entropy->intra_prob, 8); + vp8e_put_lit(bitbuf, entropy->last_prob, 8); + vp8e_put_lit(bitbuf, entropy->gf_prob, 8); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_put_lit(bitbuf, 0, 1); + vp8e_calc_mv_prob(bitbuf, &entropy->mv_prob, &entropy->old_mv_prob); + + return MPP_OK; +} + +static MPP_RET set_new_frame(void *hal) +{ + RK_S32 i; + RK_S32 qp; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eSps *sps = &ctx->sps; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + hw_cfg->output_strm_size /= 8; + hw_cfg->output_strm_size &= (~0x07); + + { + hw_cfg->output_strm_offset += ctx->bitbuf[1].byte_cnt; + hw_cfg->first_free_bit = (hw_cfg->output_strm_offset & 0x07) * 8; + } + + if (hw_cfg->first_free_bit != 0) { + RK_U32 val; + RK_U8 *pTmp = (RK_U8 *)((size_t)(ctx->bitbuf[1].data) & (~0x07)); + + for (val = 6; val >= hw_cfg->first_free_bit / 8; val--) { + pTmp[val] = 0; + } + + val = pTmp[0] << 24; + val |= pTmp[1] << 16; + val |= pTmp[2] << 8; + val |= pTmp[3]; + + hw_cfg->strm_start_msb = val; + + if (hw_cfg->first_free_bit > 32) { + val = pTmp[4] << 24; + val |= pTmp[5] << 16; + val |= pTmp[6] << 8; + + hw_cfg->strm_start_lsb = val; + } else { + hw_cfg->strm_start_lsb = 0; + } + } else { + hw_cfg->strm_start_msb = hw_cfg->strm_start_lsb = 0; + } + + if (sps->quarter_pixel_mv == 0) { + hw_cfg->disable_qp_mv = 1; + } else if (sps->quarter_pixel_mv == 1) { + if (ctx->mb_per_frame > 8160) + hw_cfg->disable_qp_mv = 1; + else + hw_cfg->disable_qp_mv = 0; + } else { + hw_cfg->disable_qp_mv = 0; + } + + hw_cfg->enable_cabac = 1; + + if (sps->split_mv == 0) + hw_cfg->split_mv_mode = 0; + else if (sps->split_mv == 1) { + if (ctx->mb_per_frame > 1584) + hw_cfg->split_mv_mode = 0; + else + hw_cfg->split_mv_mode = 1; + } else + hw_cfg->split_mv_mode = 1; + + qp = ctx->rc->qp_hdr; + if (hw_cfg->inter_favor == -1) { + RK_S32 tmp = 128 - ctx->entropy.intra_prob; + + if (tmp < 0) { + hw_cfg->inter_favor = tmp & 0xFFFF; + } else { + tmp = qp * 2 - 40; + hw_cfg->inter_favor = MPP_MAX(0, tmp); + } + } + + if (hw_cfg->diff_mv_penalty[0] == -1) + hw_cfg->diff_mv_penalty[0] = 64 / 2; + if (hw_cfg->diff_mv_penalty[1] == -1) + hw_cfg->diff_mv_penalty[1] = 60 / 2 * 32; + if (hw_cfg->diff_mv_penalty[2] == -1) + hw_cfg->diff_mv_penalty[2] = 8; + if (hw_cfg->skip_penalty == -1) + hw_cfg->skip_penalty = (qp >= 100) ? (3 * qp / 4) : 0; /* Zero/nearest/near */ + if (hw_cfg->golden_penalty == -1) + hw_cfg->golden_penalty = MPP_MAX(0, 5 * qp / 4 - 10); + if (hw_cfg->split_penalty[0] == 0) + hw_cfg->split_penalty[0] = MPP_MIN(1023, vp8_split_penalty_tbl[qp] / 2); + if (hw_cfg->split_penalty[1] == 0) + hw_cfg->split_penalty[1] = MPP_MIN(1023, (2 * vp8_split_penalty_tbl[qp] + 40) / 4); + if (hw_cfg->split_penalty[3] == 0) + hw_cfg->split_penalty[3] = MPP_MIN(511, (8 * vp8_split_penalty_tbl[qp] + 500) / 16); + + for (i = 0; i < 128; i++) { + RK_S32 y, x; + + hw_cfg->dmv_penalty[i] = i * 2; + y = vp8e_calc_cost_mv(i * 2, ctx->entropy.mv_prob[0]); /* mv y */ + x = vp8e_calc_cost_mv(i * 2, ctx->entropy.mv_prob[1]); /* mv x */ + hw_cfg->dmv_qpel_penalty[i] = MPP_MIN(255, (y + x + 1) / 2 * weight_tbl[qp] >> 8); + } + + for (i = 0; i < 4; i++) { + qp = ctx->ppss.pps->qp_sgm[i]; + hw_cfg->y1_quant_dc[i] = ctx->qp_y1[qp].quant[0]; + hw_cfg->y1_quant_ac[i] = ctx->qp_y1[qp].quant[1]; + hw_cfg->y2_quant_dc[i] = ctx->qp_y2[qp].quant[0]; + hw_cfg->y2_quant_ac[i] = ctx->qp_y2[qp].quant[1]; + hw_cfg->ch_quant_dc[i] = ctx->qp_ch[qp].quant[0]; + hw_cfg->ch_quant_ac[i] = ctx->qp_ch[qp].quant[1]; + hw_cfg->y1_zbin_dc[i] = ctx->qp_y1[qp].zbin[0]; + hw_cfg->y1_zbin_ac[i] = ctx->qp_y1[qp].zbin[1]; + hw_cfg->y2_zbin_dc[i] = ctx->qp_y2[qp].zbin[0]; + hw_cfg->y2_zbin_ac[i] = ctx->qp_y2[qp].zbin[1]; + hw_cfg->ch_zbin_dc[i] = ctx->qp_ch[qp].zbin[0]; + hw_cfg->ch_zbin_ac[i] = ctx->qp_ch[qp].zbin[1]; + hw_cfg->y1_round_dc[i] = ctx->qp_y1[qp].round[0]; + hw_cfg->y1_round_ac[i] = ctx->qp_y1[qp].round[1]; + hw_cfg->y2_round_dc[i] = ctx->qp_y2[qp].round[0]; + hw_cfg->y2_round_ac[i] = ctx->qp_y2[qp].round[1]; + hw_cfg->ch_round_dc[i] = ctx->qp_ch[qp].round[0]; + hw_cfg->ch_round_ac[i] = ctx->qp_ch[qp].round[1]; + hw_cfg->y1_dequant_dc[i] = ctx->qp_y1[qp].dequant[0]; + hw_cfg->y1_dequant_ac[i] = ctx->qp_y1[qp].dequant[1]; + hw_cfg->y2_dequant_dc[i] = ctx->qp_y2[qp].dequant[0]; + hw_cfg->y2_dequant_ac[i] = ctx->qp_y2[qp].dequant[1]; + hw_cfg->ch_dequant_dc[i] = ctx->qp_ch[qp].dequant[0]; + hw_cfg->ch_dequant_ac[i] = ctx->qp_ch[qp].dequant[1]; + + hw_cfg->filter_level[i] = ctx->ppss.pps->level_sgm[i]; + } + + hw_cfg->bool_enc_value = ctx->bitbuf[1].bottom; + hw_cfg->bool_enc_value_bits = 24 - ctx->bitbuf[1].bits_left; + hw_cfg->bool_enc_range = ctx->bitbuf[1].range; + + if (ctx->picbuf.cur_pic->i_frame) + hw_cfg->frame_coding_type = 1; + else + hw_cfg->frame_coding_type = 0; + + hw_cfg->size_tbl_base = mpp_buffer_get_fd(buffers->hw_size_table_buf); + + hw_cfg->dct_partitions = sps->dct_partitions; + hw_cfg->filter_disable = sps->filter_type; + hw_cfg->filter_sharpness = sps->filter_sharpness; + hw_cfg->segment_enable = ctx->ppss.pps->segment_enabled; + hw_cfg->segment_map_update = ctx->ppss.pps->sgm.map_modified; + + ctx->ppss.pps->sgm.map_modified = 0; + + for (i = 0; i < 4; i++) { + hw_cfg->lf_ref_delta[i] = sps->ref_delta[i]; + hw_cfg->lf_mode_delta[i] = sps->mode_delta[i]; + } + + set_intra_pred_penalties(hw_cfg, qp); + + memset(mpp_buffer_get_ptr(buffers->hw_prob_count_buf), + 0, VP8_PROB_COUNT_BUF_SIZE); + mpp_buffer_sync_end(buffers->hw_prob_count_buf); + + return MPP_OK; +} + +static MPP_RET set_code_frame(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *) hal; + + vp8e_init_entropy(ctx); + set_segmentation(ctx); + set_filter(ctx); + set_frame_header(ctx); + set_new_frame(ctx); + vp8e_write_entropy_tables(ctx); + + return MPP_OK; +} + +static void reset_refpic(HalVp8eRefPic *refPic) +{ + refPic->poc = -1; + refPic->i_frame = 0; + refPic->p_frame = 0; + refPic->show = 0; + refPic->ipf = 0; + refPic->arf = 0; + refPic->grf = 0; + refPic->search = 0; +} + +static void init_ref_pic_list(HalVp8ePicBuf *picbuf) +{ + RK_S32 i, j; + + HalVp8eRefPic *ref_pic = picbuf->ref_pic; + HalVp8eRefPic *cur_pic = picbuf->cur_pic; + HalVp8eRefPic *ref_pic_list = picbuf->ref_pic_list; + + j = 0; + for (i = 0; i < picbuf->size + 1; i++) { + if (ref_pic[i].ipf && (&ref_pic[i] != cur_pic)) { + ref_pic_list[j++] = ref_pic[i]; + break; + } + } + + for (i = 0; i < picbuf->size + 1; i++) { + if (ref_pic[i].grf && (&ref_pic[i] != cur_pic)) { + ref_pic_list[j++] = ref_pic[i]; + break; + } + } + + for (i = 0; i < picbuf->size + 1; i++) { + if (ref_pic[i].arf && (&ref_pic[i] != cur_pic)) { + ref_pic_list[j] = ref_pic[i]; + break; + } + } + + for (i = 0; i < picbuf->size; i++) { + ref_pic_list[i].ipf = 0; + ref_pic_list[i].grf = 0; + ref_pic_list[i].arf = 0; + } +} + +static MPP_RET init_picbuf(void *hal) +{ + RK_S32 i = 0; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + HalVp8ePicBuf *buf = &ctx->picbuf; + + if (buf->cur_pic->i_frame) { + buf->cur_pic->p_frame = 0; + buf->cur_pic->ipf = 1; + buf->cur_pic->grf = 1; + buf->cur_pic->arf = 1; + + for (i = 0; i < 4; i++) { + if (&buf->ref_pic[i] != buf->cur_pic) { + reset_refpic(&buf->ref_pic[i]); + } + } + } + + for (i = 0; i < 3; i++) { + reset_refpic(&buf->ref_pic_list[i]); + } + + init_ref_pic_list(buf); + + return MPP_OK; +} + +static MPP_RET set_picbuf_ref(void *hal) +{ + RK_S32 i = 0; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + HalVp8ePicBuf *pic_buf = &ctx->picbuf; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + HalVp8eRefPic *ref_pic_list = pic_buf->ref_pic_list; + + { + RK_S32 no_grf = 0; + RK_S32 no_arf = 0; + if (pic_buf->size < 2) { + no_grf = 1; + pic_buf->cur_pic->grf = 0; + } + if (pic_buf->size < 3) { + no_arf = 1; + pic_buf->cur_pic->arf = 0; + } + + for (i = 0; i < pic_buf->size; i++) { + if (pic_buf->cur_pic->grf || no_grf) + pic_buf->ref_pic_list[i].grf = 0; + if (pic_buf->cur_pic->arf || no_arf) + pic_buf->ref_pic_list[i].arf = 0; + } + } + { + RK_S32 ref_idx = -1; + RK_S32 ref_idx2 = -1; + + for (i = 0; i < 3; i++) { + if ((i < pic_buf->size) && ref_pic_list[i].search) { + if (ref_idx == -1) + ref_idx = i; + else if (ref_idx2 == -1) + ref_idx2 = i; + else + ref_pic_list[i].search = 0; + } else { + ref_pic_list[i].search = 0; + } + } + + if (ref_idx == -1) + ref_idx = 0; + + hw_cfg->mv_ref_idx[0] = hw_cfg->mv_ref_idx[1] = ref_idx; + + if (pic_buf->cur_pic->p_frame) { + pic_buf->ref_pic_list[ref_idx].search = 1; + + hw_cfg->internal_img_lum_base_r[0] = ref_pic_list[ref_idx].picture.lum; + hw_cfg->internal_img_chr_base_r[0] = ref_pic_list[ref_idx].picture.cb; + hw_cfg->internal_img_lum_base_r[1] = ref_pic_list[ref_idx].picture.lum; + hw_cfg->internal_img_chr_base_r[1] = ref_pic_list[ref_idx].picture.cb; + hw_cfg->mv_ref_idx[0] = hw_cfg->mv_ref_idx[1] = ref_idx; + hw_cfg->ref2_enable = 0; + + if (ref_idx2 != -1) { + hw_cfg->internal_img_lum_base_r[1] = ref_pic_list[ref_idx2].picture.lum; + hw_cfg->internal_img_chr_base_r[1] = ref_pic_list[ref_idx2].picture.cb; + hw_cfg->mv_ref_idx[1] = ref_idx2; + hw_cfg->ref2_enable = 1; + } + } + } + hw_cfg->rec_write_disable = 0; + + if (!pic_buf->cur_pic->picture.lum) { + HalVp8eRefPic *cur_pic = pic_buf->cur_pic; + HalVp8eRefPic *cand; + RK_S32 recIdx = -1; + + for (i = 0; i < pic_buf->size + 1; i++) { + cand = &pic_buf->ref_pic[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) { + cur_pic->picture.lum = pic_buf->ref_pic[recIdx].picture.lum; + pic_buf->ref_pic[recIdx].picture.lum = 0; + } else { + hw_cfg->rec_write_disable = 1; + } + } + + hw_cfg->internal_img_lum_base_w = pic_buf->cur_pic->picture.lum; + hw_cfg->internal_img_chr_base_w = pic_buf->cur_pic->picture.cb; + + return MPP_OK; +} + +void write_ivf_header(void *hal, RK_U8 *dst) +{ + RK_U8 data[IVF_HDR_BYTES] = {0}; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + MppEncPrepCfg *prep = &ctx->cfg->prep; + MppEncRcCfg *rc = &ctx->cfg->rc; + + data[0] = 'D'; + data[1] = 'K'; + data[2] = 'I'; + data[3] = 'F'; + + data[6] = 32; + + data[8] = 'V'; + data[9] = 'P'; + data[10] = '8'; + data[11] = '0'; + + data[12] = prep->width & 0xff; + data[13] = (prep->width >> 8) & 0xff; + data[14] = prep->height & 0xff; + data[15] = (prep->height >> 8) & 0xff; + + data[16] = rc->fps_out_num & 0xff; + data[17] = (rc->fps_out_num >> 8) & 0xff; + data[18] = (rc->fps_out_num >> 16) & 0xff; + data[19] = (rc->fps_out_num >> 24) & 0xff; + + data[20] = rc->fps_out_denom & 0xff; + data[21] = (rc->fps_out_denom >> 8) & 0xff; + data[22] = (rc->fps_out_denom >> 16) & 0xff; + data[23] = (rc->fps_out_denom >> 24) & 0xff; + + data[24] = ctx->frame_cnt & 0xff; + data[25] = (ctx->frame_cnt >> 8) & 0xff; + data[26] = (ctx->frame_cnt >> 16) & 0xff; + data[27] = (ctx->frame_cnt >> 24) & 0xff; + + memcpy(dst, data, IVF_HDR_BYTES); +} + +static void write_ivf_frame(void *hal, RK_U8 *out) +{ + RK_U8 data[IVF_FRM_BYTES]; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + RK_S32 byte_cnt = ctx->frame_size; + + data[0] = byte_cnt & 0xff; + data[1] = (byte_cnt >> 8) & 0xff; + data[2] = (byte_cnt >> 16) & 0xff; + data[3] = (byte_cnt >> 24) & 0xff; + + data[4] = ctx->frame_cnt & 0xff; + data[5] = (ctx->frame_cnt >> 8) & 0xff; + data[6] = (ctx->frame_cnt >> 16) & 0xff; + data[7] = (ctx->frame_cnt >> 24) & 0xff; + data[8] = (ctx->frame_cnt >> 32) & 0xff; + data[9] = (ctx->frame_cnt >> 40) & 0xff; + data[10] = (ctx->frame_cnt >> 48) & 0xff; + data[11] = (ctx->frame_cnt >> 56) & 0xff; + + memcpy(out, data, IVF_FRM_BYTES); +} + +static MPP_RET set_frame_tag(void *hal) +{ + RK_S32 tmp = 0; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + HalVp8ePicBuf *pic_buf = &ctx->picbuf; + HalVp8eRefPic *cur_pic = pic_buf->cur_pic; + Vp8ePutBitBuf *bitbuf = &ctx->bitbuf[0]; + RK_S32 pic_height_in_pixel; + RK_S32 pic_width_in_pixel; + RK_S32 h_scaling; + RK_S32 v_scaling; + + tmp = ((ctx->bitbuf[1].byte_cnt) << 5) | + (((cur_pic->show != 0) ? 1 : 0) << 4) | + (ctx->sps.profile << 1) | + ((cur_pic->i_frame != 0) ? 0 : 1); + + vp8e_put_byte(bitbuf, tmp & 0xff); + + vp8e_put_byte(bitbuf, (tmp >> 8) & 0xff); + + vp8e_put_byte(bitbuf, (tmp >> 16) & 0xff); + + if (!cur_pic->i_frame) + return MPP_NOK; + + vp8e_put_byte(bitbuf, 0x9d); + vp8e_put_byte(bitbuf, 0x01); + vp8e_put_byte(bitbuf, 0x2a); + + if (ctx->hw_cfg.input_rotation) { + pic_height_in_pixel = ctx->sps.pic_width_in_pixel; + pic_width_in_pixel = ctx->sps.pic_height_in_pixel; + h_scaling = ctx->sps.vertical_scaling; + v_scaling = ctx->sps.horizontal_scaling; + } else { + pic_height_in_pixel = ctx->sps.pic_height_in_pixel; + pic_width_in_pixel = ctx->sps.pic_width_in_pixel; + h_scaling = ctx->sps.horizontal_scaling; + v_scaling = ctx->sps.vertical_scaling; + } + + tmp = pic_width_in_pixel | (h_scaling << 14); + vp8e_put_byte(bitbuf, tmp & 0xff); + vp8e_put_byte(bitbuf, tmp >> 8); + + tmp = pic_height_in_pixel | (v_scaling << 14); + vp8e_put_byte(bitbuf, tmp & 0xff); + vp8e_put_byte(bitbuf, tmp >> 8); + + return MPP_OK; +} + +static MPP_RET set_data_part_size(void *hal) +{ + RK_S32 i = 0; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (!ctx->sps.dct_partitions) + return MPP_NOK; + + for (i = 2; i < ctx->sps.partition_cnt - 1; i++) { + Vp8ePutBitBuf *bitbuf = ctx->bitbuf; + RK_S32 tmp = bitbuf[i].data - bitbuf[i].p_data; + vp8e_put_byte(&bitbuf[1], tmp & 0xff); + vp8e_put_byte(&bitbuf[1], (tmp >> 8) & 0xff); + vp8e_put_byte(&bitbuf[1], (tmp >> 16) & 0xff); + } + + return MPP_OK; +} + +static MPP_RET update_picbuf(HalVp8ePicBuf *picbuf) +{ + RK_S32 i , j; + + HalVp8eRefPic *ref_pic_list = picbuf->ref_pic_list; + HalVp8eRefPic *ref_pic = picbuf->ref_pic; + HalVp8eRefPic *cur_pic = picbuf->cur_pic; + + picbuf->last_pic = picbuf->cur_pic; + + for (i = 0; i < picbuf->size + 1; i++) { + if (&ref_pic[i] == cur_pic) + continue; + if (cur_pic->ipf) + ref_pic[i].ipf = 0; + if (cur_pic->grf) + ref_pic[i].grf = 0; + if (cur_pic->arf) + ref_pic[i].arf = 0; + } + + for (i = 0; i < picbuf->size; i++) { + for (j = 0; j < picbuf->size + 1; j++) { + if (ref_pic_list[i].grf) + ref_pic[j].grf = 0; + if (ref_pic_list[i].arf) + ref_pic[j].arf = 0; + } + } + + for (i = 0; i < picbuf->size; i++) { + if (ref_pic_list[i].grf) + ref_pic_list[i].refPic->grf = 1; + if (ref_pic_list[i].arf) + ref_pic_list[i].refPic->arf = 1; + } + + for (i = 0; i < picbuf->size + 1; i++) { + HalVp8eRefPic *tmp = &ref_pic[i]; + if (!tmp->ipf && !tmp->arf && !tmp->grf) { + picbuf->cur_pic = &ref_pic[i]; + break; + } + } + + return MPP_OK; +} + +static MPP_RET set_parameter(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eSps *sps = &ctx->sps; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + MppEncPrepCfg *set = &ctx->cfg->prep; + + RK_S32 width = set->width; + RK_S32 height = set->height; + RK_S32 width_align = MPP_ALIGN(set->width, 16); + RK_S32 height_align = MPP_ALIGN(set->height, 16); + RK_U32 stride; + RK_U32 rotation = 0; + + // do not support mirroring + if (set->mirroring) + mpp_err_f("Warning: do not support mirroring\n"); + + if (set->rotation == MPP_ENC_ROT_90) + rotation = 1; + else if (set->rotation == MPP_ENC_ROT_270) + rotation = 2; + else if (set->rotation != MPP_ENC_ROT_0) + mpp_err_f("Warning: only support 90 or 270 degree rotate, request rotate %d", rotation); + + if (rotation) { + MPP_SWAP(RK_S32, width, height); + MPP_SWAP(RK_S32, width_align, height_align); + } + + stride = get_vepu_pixel_stride(&ctx->stride_cfg, width, + set->hor_stride, set->format); + + ctx->mb_per_frame = width_align / 16 * height_align / 16; + ctx->mb_per_row = width_align / 16; + ctx->mb_per_col = height_align / 16; + + sps->pic_width_in_pixel = width_align; + sps->pic_height_in_pixel = height_align; + sps->pic_width_in_mbs = width_align / 16; + sps->pic_height_in_mbs = height_align / 16; + sps->horizontal_scaling = 0; + sps->vertical_scaling = 0; + sps->color_type = 0; + sps->clamp_type = 0; + sps->dct_partitions = 0; + sps->partition_cnt = 2 + (1 << sps->dct_partitions); + sps->profile = 1; + sps->filter_type = 0; + sps->filter_level = 0; + sps->filter_sharpness = 0; + sps->auto_filter_level = 1; + sps->auto_filter_sharpness = 1; + sps->quarter_pixel_mv = 1; + sps->split_mv = 1; + sps->refresh_entropy = 1; + memset(sps->sing_bias, 0, sizeof(sps->sing_bias)); + + sps->filter_delta_enable = 1; + memset(sps->ref_delta, 0, sizeof(sps->ref_delta)); + memset(sps->mode_delta, 0, sizeof(sps->mode_delta)); + + hw_cfg->input_rotation = rotation; + + { + RK_U32 tmp = 0; + RK_U32 hor_offset_src = 0; + RK_U32 ver_offset_src = 0; + RK_U8 video_stab = 0; + + if (set->format == MPP_FMT_YUV420SP || set->format == MPP_FMT_YUV420P) { + tmp = ver_offset_src; + tmp *= stride; + tmp += hor_offset_src; + hw_cfg->input_lum_base += (tmp & (~7)); + hw_cfg->input_luma_base_offset = tmp & 7; + + if (video_stab) + hw_cfg->vs_next_luma_base += (tmp & (~7)); + + if (set->format == MPP_FMT_YUV420P) { + tmp = ver_offset_src / 2; + tmp *= stride / 2; + tmp += hor_offset_src / 2; + + hw_cfg->input_cb_base += (tmp & (~7)); + hw_cfg->input_cr_base += (tmp & (~7)); + hw_cfg->input_chroma_base_offset = tmp & 7; + } else { + tmp = ver_offset_src / 2; + tmp *= stride / 2; + tmp += hor_offset_src / 2; + tmp *= 2; + + hw_cfg->input_cb_base += (tmp & (~7)); + hw_cfg->input_chroma_base_offset = tmp & 7; + } + } else if (set->format <= MPP_FMT_BGR444 && set->format >= MPP_FMT_RGB565) { + tmp = ver_offset_src; + tmp *= stride; + tmp += hor_offset_src; + tmp *= 2; + + hw_cfg->input_lum_base += (tmp & (~7)); + hw_cfg->input_luma_base_offset = tmp & 7; + hw_cfg->input_chroma_base_offset = (hw_cfg->input_luma_base_offset / 4) * 4; + + if (video_stab) + hw_cfg->vs_next_luma_base += (tmp & (~7)); + } else { + tmp = ver_offset_src; + tmp *= stride; + tmp += hor_offset_src; + tmp *= 4; + + hw_cfg->input_lum_base += (tmp & (~7)); + hw_cfg->input_luma_base_offset = (tmp & 7) / 2; + + if (video_stab) + hw_cfg->vs_next_luma_base += (tmp & (~7)); + } + + hw_cfg->mbs_in_row = width_align / 16; + hw_cfg->mbs_in_col = height_align / 16; + hw_cfg->pixels_on_row = stride; + } + if (width & 0x0F) + hw_cfg->x_fill = (16 - (width & 0x0F)) / 4; + else + hw_cfg->x_fill = 0; + + if (height & 0x0F) + hw_cfg->y_fill = 16 - (height & 0x0F); + else + hw_cfg->y_fill = 0; + + hw_cfg->vs_mode = 0; + + switch (set->color) { + case MPP_FRAME_SPC_RGB: /* BT.601 */ + default: + /* Y = 0.2989 R + 0.5866 G + 0.1145 B + * Cb = 0.5647 (B - Y) + 128 + * Cr = 0.7132 (R - Y) + 128 + */ + hw_cfg->rgb_coeff_a = 19589; + hw_cfg->rgb_coeff_b = 38443; + hw_cfg->rgb_coeff_c = 7504; + hw_cfg->rgb_coeff_e = 37008; + hw_cfg->rgb_coeff_f = 46740; + break; + + case MPP_FRAME_SPC_BT709: /* BT.709 */ + /* Y = 0.2126 R + 0.7152 G + 0.0722 B + * Cb = 0.5389 (B - Y) + 128 + * Cr = 0.6350 (R - Y) + 128 + */ + hw_cfg->rgb_coeff_a = 13933; + hw_cfg->rgb_coeff_b = 46871; + hw_cfg->rgb_coeff_c = 732; + hw_cfg->rgb_coeff_e = 35317; + hw_cfg->rgb_coeff_f = 41615; + break; + } + + hw_cfg->r_mask_msb = hw_cfg->g_mask_msb = hw_cfg->b_mask_msb = 0; + VepuFormatCfg fmt_cfg; + if (!get_vepu_fmt(&fmt_cfg, set->format)) { + hw_cfg->input_format = fmt_cfg.format; + hw_cfg->r_mask_msb = fmt_cfg.r_mask; + hw_cfg->g_mask_msb = fmt_cfg.g_mask; + hw_cfg->b_mask_msb = fmt_cfg.b_mask; + } else + return MPP_NOK; + + return MPP_OK; +} + +static MPP_RET set_picbuf(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + // find one dpb for current picture + { + RK_U32 i = 0; + RK_S32 width = ctx->sps.pic_width_in_mbs * 16; + RK_S32 height = ctx->sps.pic_height_in_mbs * 16; + HalVp8ePicBuf *picbuf = &ctx->picbuf; + + memset(picbuf->ref_pic, 0, sizeof(picbuf->ref_pic)); + memset(picbuf->ref_pic_list, 0, sizeof(picbuf->ref_pic_list)); + + for (i = 0; i < REF_FRAME_COUNT + 1; i++) { + picbuf->ref_pic[i].picture.lum_width = width; + picbuf->ref_pic[i].picture.lum_height = height; + picbuf->ref_pic[i].picture.ch_width = width / 2; + picbuf->ref_pic[i].picture.ch_height = height / 2; + picbuf->ref_pic[i].picture.lum = 0; + picbuf->ref_pic[i].picture.cb = 0; + } + + picbuf->cur_pic = &picbuf->ref_pic[0]; + } + + ctx->ppss.size = 1; + ctx->ppss.store = (Pps *)mpp_calloc(Pps, 1); + if (ctx->ppss.store == NULL) { + mpp_err("failed to malloc ppss store.\n"); + goto __ERR_RET; + } + + ctx->ppss.pps = ctx->ppss.store; + ctx->ppss.pps->segment_enabled = 0; + ctx->ppss.pps->sgm.map_modified = 0; + + return MPP_OK; + +__ERR_RET: + return MPP_NOK; +} + +static MPP_RET alloc_buffer(void *hal) +{ + MPP_RET ret = MPP_OK; + + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + MppEncPrepCfg *pre = &ctx->cfg->prep; + RK_U32 mb_total = ctx->mb_per_frame; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + //set coding format as VP8 + hw_cfg->coding_type = 1; + + ret = mpp_buffer_group_get_internal(&buffers->hw_buf_grp, + MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err("buf group get failed ret %d\n", ret); + goto __ERR_RET; + } + + //add 128 bytes to avoid kernel crash + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_luma_buf, + MPP_ALIGN(mb_total * (16 * 16), SZ_4K) + SZ_4K); + if (ret) { + mpp_err("hw_luma_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + { + RK_U32 i = 0; + for (i = 0; i < 2; i++) { + //add 128 bytes to avoid kernel crash + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_cbcr_buf[i], + MPP_ALIGN(mb_total * (2 * 8 * 8), SZ_4K) + SZ_4K); + if (ret) { + mpp_err("hw_cbcr_buf[%d] get failed ret %d\n", i, ret); + goto __ERR_RET; + } + } + } + hw_cfg->internal_img_lum_base_w = mpp_buffer_get_fd(buffers->hw_luma_buf); + hw_cfg->internal_img_chr_base_w = mpp_buffer_get_fd(buffers->hw_cbcr_buf[0]); + + hw_cfg->internal_img_lum_base_r[0] = mpp_buffer_get_fd(buffers->hw_luma_buf); + hw_cfg->internal_img_chr_base_r[0] = mpp_buffer_get_fd(buffers->hw_cbcr_buf[1]); + { + /* NAL size table, table size must be 64-bit multiple, + * space for SEI, MVC prefix, filler and zero at the end of table. + * At least 1 macroblock row in every slice. + * Also used for VP8 partitions. */ + RK_U32 size_tbl = MPP_ALIGN(sizeof(RK_U32) * (pre->height + 4), 8); + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_size_table_buf, size_tbl); + if (ret) { + mpp_err("hw_size_table_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + } + { + RK_U32 cabac_tbl_size = 8 * 55 + 8 * 96; + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_cabac_table_buf, + cabac_tbl_size); + if (ret) { + mpp_err("hw_cabac_table_buf get failed\n"); + goto __ERR_RET; + } + } + hw_cfg->cabac_tbl_base = mpp_buffer_get_fd(buffers->hw_cabac_table_buf); + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_mv_output_buf, + mb_total * 4); + if (ret) { + mpp_err("hw_mv_output_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + + hw_cfg->mv_output_base = mpp_buffer_get_fd(buffers->hw_mv_output_buf); + + memset(mpp_buffer_get_ptr(buffers->hw_mv_output_buf), 0, sizeof(RK_U32) * mb_total); + mpp_buffer_sync_end(buffers->hw_mv_output_buf); + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_prob_count_buf, VP8_PROB_COUNT_BUF_SIZE); + if (ret) { + mpp_err("hw_prob_count_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + + hw_cfg->prob_count_base = mpp_buffer_get_fd(buffers->hw_prob_count_buf); + { + /* VP8: Segmentation map, 4 bits/mb, 64-bit multiple. */ + RK_U32 segment_map_size = (mb_total * 4 + 63) / 64 * 8; + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_segment_map_buf, segment_map_size); + if (ret) { + mpp_err("hw_segment_map_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + + hw_cfg->segment_map_base = mpp_buffer_get_fd(buffers->hw_segment_map_buf); + memset(mpp_buffer_get_ptr(buffers->hw_segment_map_buf), 0, segment_map_size / 4); + mpp_buffer_sync_end(buffers->hw_segment_map_buf); + } + { + RK_U32 i = 0; + + ctx->picbuf.size = 1; + for (i = 0; i < 1; i++) + ctx->picbuf.ref_pic[i].picture.lum = mpp_buffer_get_fd(buffers->hw_luma_buf); + for (i = 0; i < 2; i++) + ctx->picbuf.ref_pic[i].picture.cb = mpp_buffer_get_fd(buffers->hw_cbcr_buf[i]); + } + { + RK_U32 pic_size = MPP_ALIGN(pre->width, 16) * MPP_ALIGN(pre->height, 16) * 3 / 2; + RK_U32 out_size = pic_size / 2; + + ret = mpp_buffer_get(buffers->hw_buf_grp, &buffers->hw_out_buf, out_size); + if (ret) { + mpp_err("hw_out_buf get failed ret %d\n", ret); + goto __ERR_RET; + } + } + ctx->regs = mpp_calloc(RK_U32, ctx->reg_size); + if (!ctx->regs) { + mpp_err("failed to calloc regs.\n"); + goto __ERR_RET; + } + + hw_cfg->intra_16_favor = -1; + hw_cfg->prev_mode_favor = -1; + hw_cfg->inter_favor = -1; + hw_cfg->skip_penalty = -1; + hw_cfg->diff_mv_penalty[0] = -1; + hw_cfg->diff_mv_penalty[1] = -1; + hw_cfg->diff_mv_penalty[2] = -1; + hw_cfg->split_penalty[0] = 0; + hw_cfg->split_penalty[1] = 0; + hw_cfg->split_penalty[2] = 0x3FF; + hw_cfg->split_penalty[3] = 0; + hw_cfg->zero_mv_favor = 0; + + hw_cfg->intra_area_top = hw_cfg->intra_area_bottom = 255; + hw_cfg->intra_area_left = hw_cfg->intra_area_right = 255; + hw_cfg->roi1_top = hw_cfg->roi1_bottom = 255; + hw_cfg->roi1_left = hw_cfg->roi1_right = 255; + hw_cfg->roi2_top = hw_cfg->roi2_bottom = 255; + hw_cfg->roi2_left = hw_cfg->roi2_right = 255; + + return ret; + +__ERR_RET: + if (buffers) + hal_vp8e_buf_free(hal); + + return ret; +} + +MPP_RET hal_vp8e_enc_strm_code(void *hal, HalEncTask *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + VepuOffsetCfg hw_offset; + + MppEncCfgSet *cfg = ctx->cfg; + MppEncPrepCfg *prep = &cfg->prep; + + { + RK_U32 i = 0; + for (i = 0; i < 9; i++) { + ctx->p_out_buf[i] = NULL; + ctx->stream_size[i] = 0; + } + } + + { + hw_offset.fmt = prep->format; + + hw_offset.width = prep->width; + hw_offset.height = prep->height; + hw_offset.hor_stride = prep->hor_stride; + hw_offset.ver_stride = prep->ver_stride; + hw_offset.offset_x = mpp_frame_get_offset_x(task->frame); + hw_offset.offset_y = mpp_frame_get_offset_y(task->frame); + + get_vepu_offset_cfg(&hw_offset); + } + + { + HalEncTask *enc_task = task; + + hw_cfg->input_lum_base = mpp_buffer_get_fd(enc_task->input); + hw_cfg->input_cb_base = hw_cfg->input_lum_base; + hw_cfg->input_cr_base = hw_cfg->input_cb_base; + hw_cfg->input_lum_offset = hw_offset.offset_byte[0]; + hw_cfg->input_cb_offset = hw_offset.offset_byte[1]; + hw_cfg->input_cr_offset = hw_offset.offset_byte[2]; + } + + // split memory for vp8 partition + { + RK_S32 offset = 0; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + RK_U8 *p_end = NULL; + RK_U32 buf_size = mpp_buffer_get_size(buffers->hw_out_buf); + RK_U32 bus_addr = mpp_buffer_get_fd(buffers->hw_out_buf); + RK_U8 *p_start = mpp_buffer_get_ptr(buffers->hw_out_buf); + + p_end = p_start + 3; + if (ctx->frame_type == VP8E_FRM_KEY) + p_end += 7;// frame tag len:I frame 10 byte, P frmae 3 byte. + vp8e_set_buffer(&ctx->bitbuf[0], p_start, p_end - p_start); + + offset = p_end - p_start; + hw_cfg->output_strm_base = bus_addr; + hw_cfg->output_strm_offset = offset; + + p_start = p_end; + p_end = p_start + buf_size / 10; + p_end = (RK_U8 *)((size_t)p_end & ~0x7); + vp8e_set_buffer(&ctx->bitbuf[1], p_start, p_end - p_start); + + offset += p_end - p_start; + hw_cfg->partition_Base[0] = bus_addr; + hw_cfg->partition_offset[0] = offset; + + p_start = p_end; + p_end = mpp_buffer_get_ptr(buffers->hw_out_buf) + buf_size; + p_end = (RK_U8 *)((size_t)p_end & ~0x7); + vp8e_set_buffer(&ctx->bitbuf[2], p_start, p_end - p_start); + + offset += p_end - p_start; + hw_cfg->partition_Base[1] = bus_addr; + hw_cfg->partition_offset[1] = offset; + hw_cfg->output_strm_size = p_end - p_start; + + p_start = p_end; + } + + { + HalVp8ePicBuf *pic_buf = &ctx->picbuf; + + pic_buf->cur_pic->show = 1; + pic_buf->cur_pic->poc = ctx->frame_cnt; + pic_buf->cur_pic->i_frame = (ctx->frame_type == VP8E_FRM_KEY); + + init_picbuf(ctx); + + if (ctx->frame_type == VP8E_FRM_P) { + pic_buf->cur_pic->p_frame = 1; + pic_buf->cur_pic->arf = 1; + pic_buf->cur_pic->grf = 1; + pic_buf->cur_pic->ipf = 1; + pic_buf->ref_pic_list[0].search = 1; + pic_buf->ref_pic_list[1].search = 1; + pic_buf->ref_pic_list[2].search = 1; + } + + if (ctx->rc->frame_coded == 0) + return MPP_OK; + + if (ctx->rc->golden_picture_rate) { + pic_buf->cur_pic->grf = 1; + if (!pic_buf->cur_pic->arf) + pic_buf->ref_pic_list[1].arf = 1; + } + } + set_frame_params(ctx); + set_picbuf_ref(ctx); + set_code_frame(ctx); + + return MPP_OK; +} + +MPP_RET hal_vp8e_init_qp_table(void *hal) +{ + RK_S32 i = 0, j = 0; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + for (i = 0; i < QINDEX_RANGE; i++) { + RK_S32 tmp = 0; + Vp8eQp * qp = &ctx->qp_y1[i]; + + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = dc_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + } else { + tmp = ac_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + } + + qp->quant[j] = MPP_MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((q_zbin_factors_tbl[i] * tmp) + 64) >> 7; + qp->round[j] = (q_rounding_factors_tbl[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + + qp = &ctx->qp_y2[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = dc_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + tmp = tmp * 2; + } else { + tmp = ac_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + tmp = (tmp * 155) / 100; + if (tmp < 8) + tmp = 8; + } + qp->quant[j] = MPP_MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((q_zbin_factors_tbl[i] * tmp) + 64) >> 7; + qp->round[j] = (q_rounding_factors_tbl[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + + qp = &ctx->qp_ch[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = dc_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + if (tmp > 132) + tmp = 132; + } else { + tmp = ac_q_lookup_tbl[MPP_CLIP3(0, QINDEX_RANGE - 1, i)]; + } + qp->quant[j] = MPP_MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((q_zbin_factors_tbl[i] * tmp) + 64) >> 7; + qp->round[j] = (q_rounding_factors_tbl[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + } + + return MPP_OK; +} + +MPP_RET hal_vp8e_update_buffers(void *hal, HalEncTask *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + const RK_U32 hw_offset = ctx->hw_cfg.first_free_bit / 8; + RK_U32 *part = (RK_U32 *)mpp_buffer_get_ptr(buffers->hw_size_table_buf); + + mpp_buffer_sync_begin(buffers->hw_size_table_buf); + + ctx->bitbuf[1].byte_cnt += part[0] - hw_offset; + ctx->bitbuf[1].data += part[0] - hw_offset; + + ctx->bitbuf[2].byte_cnt = part[1]; + ctx->bitbuf[2].data += part[1]; + ctx->bitbuf[3].byte_cnt = part[2]; + ctx->bitbuf[3].data += part[2]; + + set_frame_tag(ctx); + + if (vp8e_buffer_gap(&ctx->bitbuf[1], 4) == MPP_OK) { + set_data_part_size(ctx); + } + + ctx->prev_frame_lost = 0; + + ctx->p_out_buf[0] = (RK_U32 *)ctx->bitbuf[0].p_data; + ctx->p_out_buf[1] = (RK_U32 *)ctx->bitbuf[2].p_data; + if (ctx->sps.dct_partitions) + ctx->p_out_buf[2] = (RK_U32 *)ctx->bitbuf[3].p_data; + + ctx->stream_size[0] = ctx->bitbuf[0].byte_cnt + + ctx->bitbuf[1].byte_cnt; + ctx->stream_size[1] = ctx->bitbuf[2].byte_cnt; + + if (ctx->sps.dct_partitions) + ctx->stream_size[2] = ctx->bitbuf[3].byte_cnt; + + ctx->frame_size = ctx->stream_size[0] + ctx->stream_size[1] + + ctx->stream_size[2]; + + update_picbuf(&ctx->picbuf); + { + HalEncTask *enc_task = task; + RK_U8 *p_out = mpp_buffer_get_ptr(enc_task->output); + RK_S32 disable_ivf = ctx->cfg->vp8.disable_ivf; + + mpp_buffer_sync_begin(buffers->hw_size_table_buf); + + if (!disable_ivf) { + p_out += enc_task->length; + + if (ctx->frame_size) { + write_ivf_frame(ctx, p_out); + + p_out += IVF_FRM_BYTES; + enc_task->length += IVF_FRM_BYTES; + } + } + + memcpy(p_out, ctx->p_out_buf[0], ctx->stream_size[0]); + p_out += ctx->stream_size[0]; + enc_task->length += ctx->stream_size[0]; + + memcpy(p_out, ctx->p_out_buf[1], ctx->stream_size[1]); + p_out += ctx->stream_size[1]; + enc_task->length += ctx->stream_size[1]; + + memcpy(p_out, ctx->p_out_buf[2], ctx->stream_size[2]); + p_out += ctx->stream_size[2]; + enc_task->length += ctx->stream_size[2]; + + mpp_buffer_sync_end(buffers->hw_size_table_buf); + } + return MPP_OK; +} + +MPP_RET hal_vp8e_setup(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (set_parameter(ctx)) { + mpp_err("set vp8e parameter failed"); + return MPP_NOK; + } + + if (set_picbuf(ctx)) { + mpp_err("set vp8e picbuf failed, no enough memory"); + return MPP_ERR_NOMEM; + } + + ret = alloc_buffer(ctx); + + return ret; +} + +MPP_RET hal_vp8e_buf_free(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + + if (buffers->hw_luma_buf) { + mpp_buffer_put(buffers->hw_luma_buf); + buffers->hw_luma_buf = NULL; + } + + { + RK_U32 i = 0; + for (i = 0; i < 2; i++) { + if (buffers->hw_cbcr_buf[i]) { + mpp_buffer_put(buffers->hw_cbcr_buf[i]); + buffers->hw_cbcr_buf[i] = NULL; + } + } + } + + if (buffers->hw_size_table_buf) { + mpp_buffer_put(buffers->hw_size_table_buf); + buffers->hw_size_table_buf = NULL; + } + + if (buffers->hw_cabac_table_buf) { + mpp_buffer_put(buffers->hw_cabac_table_buf); + buffers->hw_cabac_table_buf = NULL; + } + + if (buffers->hw_mv_output_buf) { + mpp_buffer_put(buffers->hw_mv_output_buf); + buffers->hw_mv_output_buf = NULL; + } + + if (buffers->hw_prob_count_buf) { + mpp_buffer_put(buffers->hw_prob_count_buf); + buffers->hw_prob_count_buf = NULL; + } + + if (buffers->hw_segment_map_buf) { + mpp_buffer_put(buffers->hw_segment_map_buf); + buffers->hw_segment_map_buf = NULL; + } + + if (buffers->hw_out_buf) { + mpp_buffer_put(buffers->hw_out_buf); + buffers->hw_out_buf = NULL; + } + + if (buffers->hw_buf_grp) { + mpp_buffer_group_put(buffers->hw_buf_grp); + buffers->hw_buf_grp = NULL; + } + + return MPP_OK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_base.h b/mpp/hal/vpu/vp8e/hal_vp8e_base.h new file mode 100644 index 000000000..f6b1ad158 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_base.h @@ -0,0 +1,385 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8E_BASE_H +#define HAL_VP8E_BASE_H + +#include "mpp_device.h" + +#include "vp8e_syntax.h" +#include "vepu_common.h" +#include "hal_enc_task.h" +#include "hal_vp8e_entropy.h" + +#define VP8_PROB_COUNT_MV_OFFSET (222) +#define VP8_PROB_COUNT_BUF_SIZE (244*2) + +#define mask_7b (RK_U32)0x0000007F + +#define INPUT_YUV420PLANAR 0x00 +#define INPUT_YUV420SEMIPLANAR 0x01 +#define INPUT_YUYV422INTERLEAVED 0x02 +#define INPUT_UYVY422INTERLEAVED 0x03 +#define INPUT_RGB565 0x04 +#define INPUT_RGB555 0x05 +#define INPUT_RGB444 0x06 +#define INPUT_RGB888 0x07 +#define INPUT_RGB101010 0x08 +#define INPUT_YUYV422TILED 0x09 + +#define IVF_HDR_BYTES 32 +#define IVF_FRM_BYTES 12 + +typedef enum vp8_frm_type_e { + VP8E_FRM_KEY = 0, + VP8E_FRM_P, +} Vp8FrmType; + +typedef struct vp8e_hal_vpu_buffers_t { + MppBufferGroup hw_buf_grp; + + MppBuffer hw_rec_buf[2]; + MppBuffer hw_luma_buf; + MppBuffer hw_cbcr_buf[2]; + MppBuffer hw_cabac_table_buf; + MppBuffer hw_size_table_buf; + MppBuffer hw_segment_map_buf; + MppBuffer hw_prob_count_buf; + MppBuffer hw_mv_output_buf; + MppBuffer hw_out_buf; +} Vp8eVpuBuf; + +#define PENALTY_TABLE_SIZE 128 + +/** + * pps definition + */ + +#define SGM_CNT 4 + +typedef struct sgm_t { + RK_U8 map_modified; + RK_S32 id_cnt[SGM_CNT]; +} Sgm; + +typedef struct { + Sgm sgm; + RK_S32 qp; + RK_U8 segment_enabled; + RK_S32 qp_sgm[SGM_CNT]; + RK_S32 level_sgm[SGM_CNT]; +} Pps; + +typedef struct { + Pps *store; + RK_S32 size; + Pps *pps; + Pps *prev_pps; + RK_S32 qp_sgm[SGM_CNT]; + RK_S32 level_sgm[SGM_CNT]; +} Vp8ePps; + + +/** + * QP definition + */ + +#define QINDEX_RANGE 128 + +typedef struct { + RK_S32 quant[2]; + RK_S32 zbin[2]; + RK_S32 round[2]; + RK_S32 dequant[2]; +} Vp8eQp; + +/** + * sps definition + */ + +typedef struct vp8e_sps_t { + RK_S32 pic_width_in_mbs; + RK_S32 pic_height_in_mbs; + RK_S32 pic_width_in_pixel; + RK_S32 pic_height_in_pixel; + RK_S32 horizontal_scaling; + RK_S32 vertical_scaling; + RK_S32 color_type; + RK_S32 clamp_type; + RK_S32 dct_partitions; + RK_S32 partition_cnt; + RK_S32 profile; + RK_S32 filter_type; + RK_S32 filter_level; + RK_S32 filter_sharpness; + RK_S32 quarter_pixel_mv; + RK_S32 split_mv; + RK_S32 sing_bias[3]; + + RK_S32 auto_filter_level; + RK_S32 auto_filter_sharpness; + RK_U8 filter_delta_enable; + RK_S32 mode_delta[4]; + RK_S32 old_mode_delta[4]; + RK_S32 ref_delta[4]; + RK_S32 old_ref_delta[4]; + RK_S32 refresh_entropy; +} Vp8eSps; + +/** + * entropy definition + */ + +typedef struct vp8e_hal_entropy_t { + RK_S32 skip_false_prob; + RK_S32 intra_prob; + RK_S32 last_prob; + RK_S32 gf_prob; + RK_S32 kf_y_mode_prob[4]; + RK_S32 y_mode_prob[4]; + RK_S32 kf_uv_mode_prob[3]; + RK_S32 uv_mode_prob[3]; + RK_S32 kf_b_mode_prob[10][10][9]; + RK_S32 b_mode_prob[9]; + RK_S32 coeff_prob[4][8][3][11]; + RK_S32 old_coeff_prob[4][8][3][11]; + RK_S32 mv_ref_prob[4]; + RK_S32 mv_prob[2][19]; + RK_S32 old_mv_prob[2][19]; + RK_S32 sub_mv_partprob[3]; + RK_S32 sub_mv_ref_prob[5][3]; + RK_S32 default_coeff_prob_flag; + RK_S32 update_coeff_prob_flag; + RK_S32 segment_prob[3]; +} Vp8eHalEntropy; + +/** + * picture definition + */ + +#define REF_FRAME_COUNT 3 + +typedef struct { + RK_S32 lum_width; + RK_S32 lum_height; + RK_S32 ch_width; + RK_S32 ch_height; + RK_U32 lum; + RK_U32 cb; +} HalVp8ePic; + +typedef struct hal_vp8e_refpic_t { + HalVp8ePic picture; + Vp8eHalEntropy *entropy; + RK_S32 poc; + + RK_U8 i_frame; + RK_U8 p_frame; + RK_U8 show; + RK_U8 ipf; + RK_U8 arf; + RK_U8 grf; + RK_U8 search; + struct hal_vp8e_refpic_t *refPic; +} HalVp8eRefPic; + +typedef struct { + RK_S32 size; /* Amount of allocated reference pictures */ + HalVp8ePic input; /* Input picture */ + HalVp8eRefPic ref_pic[REF_FRAME_COUNT + 1]; /* Reference picture store */ + HalVp8eRefPic ref_pic_list[REF_FRAME_COUNT]; /* Reference picture list */ + HalVp8eRefPic *cur_pic; /* Pointer to picture under reconstruction */ + HalVp8eRefPic *last_pic; /* Last picture */ +} HalVp8ePicBuf; + +typedef struct { + RK_U32 irq_disable; + RK_U32 mbs_in_col; + RK_U32 mbs_in_row; + RK_U32 rounding_ctrl; + RK_U32 frame_coding_type; + RK_U32 coding_type; + RK_U32 pixels_on_row; + RK_U32 x_fill; + RK_U32 y_fill; + RK_U32 filter_disable; + RK_U32 enable_cabac; + RK_U32 input_format; + RK_U32 input_rotation; + RK_U32 output_strm_base; + RK_U32 output_strm_offset; + RK_U32 output_strm_size; + RK_U32 first_free_bit; + RK_U32 strm_start_msb; + RK_U32 strm_start_lsb; + RK_U32 size_tbl_base; + RK_U32 int_slice_ready; + RK_U32 rec_write_disable; + RK_U32 recon_img_id; + RK_U32 internal_img_lum_base_w; + RK_U32 internal_img_chr_base_w; + RK_U32 internal_img_lum_base_r[2]; + RK_U32 internal_img_chr_base_r[2]; + RK_U32 input_lum_base; + RK_U32 input_lum_offset; + RK_U32 input_cb_base; + RK_U32 input_cb_offset; + RK_U32 input_cr_base; + RK_U32 input_cr_offset; + RK_U32 cp_distance_mbs; //TODO maybe useless + RK_U32 rlc_count; //TODO read from reg + RK_U32 qp_sum; //TODO read from reg + RK_U8 dmv_penalty[PENALTY_TABLE_SIZE]; + RK_U8 dmv_qpel_penalty[PENALTY_TABLE_SIZE]; + RK_U32 input_luma_base_offset; + RK_U32 input_chroma_base_offset; + RK_U32 disable_qp_mv; + RK_U32 vs_next_luma_base; + RK_U32 vs_mode; + RK_U32 asic_cfg_reg; + RK_S32 intra_16_favor; + RK_S32 prev_mode_favor; + RK_S32 inter_favor; + RK_S32 skip_penalty; + RK_S32 golden_penalty; + RK_S32 diff_mv_penalty[3]; + RK_U32 mad_count; + RK_U32 cir_start; + RK_U32 cir_interval; + RK_U32 intra_area_top; + RK_U32 intra_area_left; + RK_U32 intra_area_bottom; + RK_U32 intra_area_right; + RK_U32 roi1_top; + RK_U32 roi1_left; + RK_U32 roi1_bottom; + RK_U32 roi1_right; + RK_U32 roi2_top; + RK_U32 roi2_left; + RK_U32 roi2_bottom; + RK_U32 roi2_right; + RK_S32 roi1_delta_qp; + RK_S32 roi2_delta_qp; + RK_U32 mv_output_base; + RK_U32 cabac_tbl_base; + RK_U32 prob_count_base; + RK_U32 segment_map_base; + RK_U16 rgb_coeff_a; + RK_U16 rgb_coeff_b; + RK_U16 rgb_coeff_c; + RK_U16 rgb_coeff_e; + RK_U16 rgb_coeff_f; + RK_U8 r_mask_msb; + RK_U8 g_mask_msb; + RK_U8 b_mask_msb; + RK_U32 partition_Base[8]; + RK_U32 partition_offset[8]; + RK_U16 y1_quant_dc[4]; + RK_U16 y1_quant_ac[4]; + RK_U16 y2_quant_dc[4]; + RK_U16 y2_quant_ac[4]; + RK_U16 ch_quant_dc[4]; + RK_U16 ch_quant_ac[4]; + RK_U16 y1_zbin_dc[4]; + RK_U16 y1_zbin_ac[4]; + RK_U16 y2_zbin_dc[4]; + RK_U16 y2_zbin_ac[4]; + RK_U16 ch_zbin_dc[4]; + RK_U16 ch_zbin_ac[4]; + RK_U8 y1_round_dc[4]; + RK_U8 y1_round_ac[4]; + RK_U8 y2_round_dc[4]; + RK_U8 y2_round_ac[4]; + RK_U8 ch_round_dc[4]; + RK_U8 ch_round_ac[4]; + RK_U16 y1_dequant_dc[4]; + RK_U16 y1_dequant_ac[4]; + RK_U16 y2_dequant_dc[4]; + RK_U16 y2_dequant_ac[4]; + RK_U16 ch_dequant_dc[4]; + RK_U16 ch_dequant_ac[4]; + RK_U32 segment_enable; + RK_U32 segment_map_update; + RK_U32 mv_ref_idx[2]; + RK_U32 ref2_enable; + RK_U32 bool_enc_value; + RK_U32 bool_enc_value_bits; + RK_U32 bool_enc_range; + RK_U32 dct_partitions; + RK_U32 filter_level[4]; + RK_U32 filter_sharpness; + RK_U32 intra_mode_penalty[4]; + RK_U32 intra_b_mode_penalty[10]; + RK_U32 zero_mv_favor; + RK_U32 split_mv_mode; + RK_U32 split_penalty[4]; + RK_S32 lf_ref_delta[4]; + RK_S32 lf_mode_delta[4]; +} Vp8eHwCfg; + +typedef struct hal_vp8e_ctx_s { + Vp8eFeedback feedback; + MppDev dev; + + void *regs; + void *buffers; + RK_U32 reg_size; + + MppEncCfgSet *cfg; + + Vp8eSps sps; + Vp8ePps ppss; + //TODO remove vp8_rc + Vp8eRc *rc; + Vp8eHwCfg hw_cfg; + Vp8eHalEntropy entropy; + HalVp8ePicBuf picbuf; + Vp8ePutBitBuf bitbuf[4]; + Vp8eQp qp_y1[QINDEX_RANGE]; + Vp8eQp qp_y2[QINDEX_RANGE]; + Vp8eQp qp_ch[QINDEX_RANGE]; + RK_U32 prev_frame_lost; + RK_U32 *p_out_buf[9]; + RK_U32 stream_size[9]; + RK_U32 frame_size; + + RK_U32 buffer_ready; + RK_U32 ivf_hdr_rdy; + RK_U64 frame_cnt; + RK_U32 last_frm_intra; + Vp8FrmType frame_type; + + RK_U32 mb_per_frame; + RK_U32 mb_per_row; + RK_U32 mb_per_col; + VepuStrideCfg stride_cfg; +} HalVp8eCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET hal_vp8e_update_buffers(void *hal, HalEncTask *task); +MPP_RET hal_vp8e_enc_strm_code(void *hal, HalEncTask *info); +MPP_RET hal_vp8e_init_qp_table(void *hal); +MPP_RET hal_vp8e_setup(void *hal); +MPP_RET hal_vp8e_buf_free(void *hal); +void write_ivf_header(void *hal, RK_U8 *dst); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_VP8E_BASE_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_debug.h b/mpp/hal/vpu/vp8e/hal_vp8e_debug.h new file mode 100644 index 000000000..56783c235 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_debug.h @@ -0,0 +1,56 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8E_DEBUG_H +#define HAL_VP8E_DEBUG_H + +#include "mpp_debug.h" + +#define VP8E_DBG_HAL_FUNCTION (0x00000001) +#define VP8E_DBG_HAL_REG (0x00000002) +#define VP8E_DBG_HAL_DUMP_REG (0x00000004) +#define VP8E_DBG_HAL_IRQ (0x00000008) +#define VP8E_DBG_HAL_DUMP_IVF (0x00000010) + +#define VP8E_DBG(flag, fmt, ...) mpp_dbg(hal_vp8e_debug, flag, fmt, ## __VA_ARGS__) +#define VP8E_DBG_F(flag, fmt, ...) mpp_dbg_f(hal_vp8e_debug, flag, fmt, ## __VA_ARGS__) + +#define vp8e_hal_err(fmt, ...) \ + do {\ + mpp_err_f(fmt, ## __VA_ARGS__);\ + } while (0) + +#define vp8e_hal_dbg(type, fmt, ...) \ + do {\ + if (hal_vp8e_debug & type)\ + mpp_log(fmt, ## __VA_ARGS__);\ + } while (0) + +#define vp8e_hal_enter() \ + do {\ + if (hal_vp8e_debug & VP8E_DBG_HAL_FUNCTION)\ + mpp_log("line(%d), func(%s), enter", __LINE__, __FUNCTION__);\ + } while (0) + +#define vp8e_hal_leave() \ + do {\ + if (hal_vp8e_debug & VP8E_DBG_HAL_FUNCTION)\ + mpp_log("line(%d), func(%s), leave", __LINE__, __FUNCTION__);\ + } while (0) + +extern RK_U32 hal_vp8e_debug; + +#endif /* HAL_VP8E_DEBUG_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_entropy.c b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.c new file mode 100644 index 000000000..5130e7cbb --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.c @@ -0,0 +1,423 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hal_vp8e_entropy" + +#include + +#include "mpp_common.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_entropy.h" +#include "hal_vp8e_putbit.h" +#include "hal_vp8e_table.h" + +#define COST_BOOL(prob, bin)\ + ((bin) ? vp8_prob_cost_tbl[255 - (prob)] : vp8_prob_cost_tbl[prob]) + +static RK_U32 calc_mvprob(RK_U32 left, RK_U32 right, RK_U32 prob) +{ + RK_U32 p; + + if (left + right) { + p = (left * 255) / (left + right); + p &= -2; + if (!p) + p = 1; + } else + p = prob; + + return p; +} + +static RK_U32 update_prob(RK_U32 prob, RK_U32 left, RK_U32 right, + RK_U32 old_prob, RK_U32 new_prob, RK_U32 fixed) +{ + RK_S32 u, s; + + u = (RK_S32)fixed + ((vp8_prob_cost_tbl[255 - prob] - vp8_prob_cost_tbl[prob]) >> 8); + s = ((RK_S32)left * (vp8_prob_cost_tbl[old_prob] - vp8_prob_cost_tbl[new_prob]) + + (RK_S32)right * (vp8_prob_cost_tbl[255 - old_prob] - vp8_prob_cost_tbl[255 - new_prob])) >> 8; + + return (s > u); +} + +static RK_S32 get_cost_tree(Vp8eTree const *tree, RK_S32 *prob) +{ + RK_S32 bit_cost = 0; + RK_S32 value = tree->value; + RK_S32 number = tree->number; + RK_S32 const *index = tree->index; + + while (number--) { + bit_cost += COST_BOOL(prob[*index++], (value >> number) & 1); + } + + return bit_cost; +} + +MPP_RET vp8e_init_entropy(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + Vp8eHalEntropy *entropy = &ctx->entropy; + + entropy->update_coeff_prob_flag = 0; + if (!ctx->sps.refresh_entropy || ctx->picbuf.cur_pic->i_frame) { + if (!entropy->default_coeff_prob_flag) { + memcpy(entropy->coeff_prob, default_prob_coeff_tbl, sizeof(default_prob_coeff_tbl)); + entropy->update_coeff_prob_flag = 1; + } + memcpy(entropy->mv_prob, default_prob_mv_tbl, sizeof(default_prob_mv_tbl)); + entropy->default_coeff_prob_flag = 1; + } + + memcpy(entropy->old_coeff_prob, entropy->coeff_prob, sizeof(entropy->coeff_prob)); + if (ctx->frame_cnt == 0 || !ctx->last_frm_intra) + memcpy(entropy->old_mv_prob, entropy->mv_prob, sizeof(entropy->mv_prob)); + + entropy->skip_false_prob = default_skip_false_prob_tbl[ctx->rc->qp_hdr]; + + if (ctx->frame_cnt == 0) + return MPP_OK; + + if ((!ctx->picbuf.cur_pic->ipf) && (!ctx->picbuf.cur_pic->grf) && + (!ctx->picbuf.cur_pic->arf)) + return MPP_OK; + + if (ctx->prev_frame_lost) + return MPP_OK; + { + RK_S32 i, j, k, l; + + RK_U32 p, left, right; + RK_U32 old_p, upd_p = 0; + + RK_U32 type; + RK_U32 branch_cnt[2]; + RK_U16 *p_tmp = NULL; + + RK_U16 *p_cnt = (RK_U16 *)mpp_buffer_get_ptr(buffers->hw_prob_count_buf); + + mpp_buffer_sync_end(buffers->hw_prob_count_buf); + + for (i = 0; i < 4; i++) { + for (j = 0; j < 7; j++) { + for (k = 0; k < 3; k++) { + RK_S32 tmp, ii; + + tmp = i * 7 * 3 + j * 3 + k; + tmp += 2 * 4 * 7 * 3; + ii = offset_tbl[tmp]; + + right = ii >= 0 ? p_cnt[ii] : 0; + + for (l = 2; l--;) { + old_p = entropy->coeff_prob[i][j][k][l]; + upd_p = coeff_update_prob_tbl[i][j][k][l]; + + tmp -= 4 * 7 * 3; + ii = offset_tbl[tmp]; + left = ii >= 0 ? p_cnt[ii] : 0; + if (left + right) { + p = ((left * 256) + ((left + right) >> 1)) / (left + right); + if (p > 255) p = 255; + } else + p = old_p; + + if (update_prob(upd_p, left, right, old_p, p, 8)) { + entropy->coeff_prob[i][j][k][l] = p; + entropy->update_coeff_prob_flag = 1; + } + right += left; + } + } + } + } + + if (entropy->update_coeff_prob_flag) + entropy->default_coeff_prob_flag = 0; + + p_tmp = p_cnt + VP8_PROB_COUNT_MV_OFFSET; + for (i = 0; i < 2; i++) { + left = *p_tmp++; + right = *p_tmp++; + + p = calc_mvprob(left, right, entropy->old_mv_prob[i][0]); + + if (update_prob(mv_update_prob_tbl[i][0], left, right, + entropy->old_mv_prob[i][0], p, 6)) + entropy->mv_prob[i][0] = p; + + right += left; + left = *p_tmp++; + right -= left - p_tmp[0]; + + p = calc_mvprob(left, right, entropy->old_mv_prob[i][1]); + if (update_prob(mv_update_prob_tbl[i][1], left, right, + entropy->old_mv_prob[i][1], p, 6)) + entropy->mv_prob[i][1] = p; + + for (j = 0; j < 2; j++) { + left = *p_tmp++; + right = *p_tmp++; + p = calc_mvprob(left, right, entropy->old_mv_prob[i][4 + j]); + if (update_prob(mv_update_prob_tbl[i][4 + j], left, right, + entropy->old_mv_prob[i][4 + j], p, 6)) + entropy->mv_prob[i][4 + j] = p; + branch_cnt[j] = left + right; + } + + p = calc_mvprob(branch_cnt[0], branch_cnt[1], entropy->old_mv_prob[i][3]); + if (update_prob(mv_update_prob_tbl[i][3], branch_cnt[0], branch_cnt[1], + entropy->old_mv_prob[i][3], p, 6)) + entropy->mv_prob[i][3] = p; + + type = branch_cnt[0] + branch_cnt[1]; + + for (j = 0; j < 2; j++) { + left = *p_tmp++; + right = *p_tmp++; + p = calc_mvprob(left, right, entropy->old_mv_prob[i][7 + j]); + if (update_prob(mv_update_prob_tbl[i][7 + j], left, right, + entropy->old_mv_prob[i][7 + j], p, 6)) + entropy->mv_prob[i][7 + j] = p; + branch_cnt[j] = left + right; + } + + p = calc_mvprob(branch_cnt[0], branch_cnt[1], entropy->old_mv_prob[i][6]); + if (update_prob(mv_update_prob_tbl[i][6], branch_cnt[0], branch_cnt[1], + entropy->old_mv_prob[i][6], p, 6)) + entropy->mv_prob[i][6] = p; + + p = calc_mvprob(type, branch_cnt[0] + branch_cnt[1], + entropy->old_mv_prob[i][2]); + if (update_prob(mv_update_prob_tbl[i][2], type, branch_cnt[0] + branch_cnt[1], + entropy->old_mv_prob[i][2], p, 6)) + entropy->mv_prob[i][2] = p; + } + } + { + entropy->last_prob = 255; + entropy->gf_prob = 128; + memcpy(entropy->y_mode_prob, y_mode_prob_tbl, sizeof(y_mode_prob_tbl)); + memcpy(entropy->uv_mode_prob, uv_mode_prob_tbl, sizeof(uv_mode_prob_tbl)); + } + return MPP_OK; +} + +MPP_RET vp8e_swap_endian(RK_U32 *buf, RK_U32 bytes) +{ + RK_U32 i = 0; + RK_S32 words = bytes / 4; + + while (words > 0) { + RK_U32 val = buf[i]; + RK_U32 tmp = 0; + + tmp |= (val & 0xFF) << 24; + tmp |= (val & 0xFF00) << 8; + tmp |= (val & 0xFF0000) >> 8; + tmp |= (val & 0xFF000000) >> 24; + + { + RK_U32 val2 = buf[i + 1]; + RK_U32 tmp2 = 0; + + tmp2 |= (val2 & 0xFF) << 24; + tmp2 |= (val2 & 0xFF00) << 8; + tmp2 |= (val2 & 0xFF0000) >> 8; + tmp2 |= (val2 & 0xFF000000) >> 24; + + buf[i] = tmp2; + words--; + i++; + } + + buf[i] = tmp; + words--; + i++; + } + return MPP_OK; +} + + +MPP_RET vp8e_write_entropy_tables(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eVpuBuf *buffers = (Vp8eVpuBuf *)ctx->buffers; + Vp8eHalEntropy *entropy = &ctx->entropy; + + RK_U8 *table = (RK_U8 *)mpp_buffer_get_ptr(buffers->hw_cabac_table_buf); + /* Write probability tables to ASIC linear memory, reg + mem */ + memset(table, 0, 56); // use 56 bytes + table[0] = entropy->skip_false_prob; + table[1] = entropy->intra_prob; + table[2] = entropy->last_prob; + table[3] = entropy->gf_prob; + table[4] = entropy->segment_prob[0]; + table[5] = entropy->segment_prob[1]; + table[6] = entropy->segment_prob[2]; + + table[8] = entropy->y_mode_prob[0]; + table[9] = entropy->y_mode_prob[1]; + table[10] = entropy->y_mode_prob[2]; + table[11] = entropy->y_mode_prob[3]; + table[12] = entropy->uv_mode_prob[0]; + table[13] = entropy->uv_mode_prob[1]; + table[14] = entropy->uv_mode_prob[2]; + + /* MV probabilities x+y: short, sign, size 8-9 */ + table[16] = entropy->mv_prob[1][0]; + table[17] = entropy->mv_prob[0][0]; + table[18] = entropy->mv_prob[1][1]; + table[19] = entropy->mv_prob[0][1]; + table[20] = entropy->mv_prob[1][17]; + table[21] = entropy->mv_prob[1][18]; + table[22] = entropy->mv_prob[0][17]; + table[23] = entropy->mv_prob[0][18]; + { + RK_S32 i, j, k, l; + /* MV X size */ + for (i = 0; i < 8; i++) + table[24 + i] = entropy->mv_prob[1][9 + i]; + + /* MV Y size */ + for (i = 0; i < 8; i++) + table[32 + i] = entropy->mv_prob[0][9 + i]; + + /* MV X short tree */ + for (i = 0; i < 7; i++) + table[40 + i] = entropy->mv_prob[1][2 + i]; + + /* MV Y short tree */ + for (i = 0; i < 7; i++) + table[48 + i] = entropy->mv_prob[0][2 + i]; + + /* Update the ASIC table when needed. */ + if (entropy->update_coeff_prob_flag) { + 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->coeff_prob[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->coeff_prob[i][j][k][l]; + } + *table++ = entropy->coeff_prob[i][j][k][3]; + } + } + } + table = mpp_buffer_get_ptr(buffers->hw_cabac_table_buf); + if (entropy->update_coeff_prob_flag) + vp8e_swap_endian((RK_U32 *) table, 56 + 8 * 48 + 8 * 96); + else + vp8e_swap_endian((RK_U32 *) table, 56); + + mpp_buffer_sync_end(buffers->hw_cabac_table_buf); + + return MPP_OK; +} + +RK_S32 vp8e_calc_cost_mv(RK_S32 mvd, RK_S32 *mv_prob) +{ + RK_S32 i = 0; + RK_S32 bit_cost = 0; + + RK_S32 tmp = MPP_ABS(mvd >> 1); + + if (tmp < 8) { + bit_cost += COST_BOOL(mv_prob[0], 0); + bit_cost += get_cost_tree(&mv_tree_tbl[tmp], mv_prob + 2); + if (!tmp) + return bit_cost; + + /* Sign */ + bit_cost += COST_BOOL(mv_prob[1], mvd < 0); + return bit_cost; + } + + bit_cost += COST_BOOL(mv_prob[0], 1); + + for (i = 0; i < 3; i++) { + bit_cost += COST_BOOL(mv_prob[9 + i], (tmp >> i) & 1); + } + + for (i = 9; i > 3; i--) { + bit_cost += COST_BOOL(mv_prob[9 + i], (tmp >> i) & 1); + } + + if (tmp > 15) { + bit_cost += COST_BOOL(mv_prob[9 + 3], (tmp >> 3) & 1); + } + + bit_cost += COST_BOOL(mv_prob[1], mvd < 0); + + return bit_cost; +} + +MPP_RET vp8e_calc_coeff_prob(Vp8ePutBitBuf *bitbuf, RK_S32 (*curr)[4][8][3][11], + RK_S32 (*prev)[4][8][3][11]) +{ + RK_S32 i, j, k, l; + RK_S32 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 = coeff_update_prob_tbl[i][j][k][l]; + old = (RK_S32) (*prev)[i][j][k][l]; + new = (RK_S32) (*curr)[i][j][k][l]; + + if (new == old) { + vp8e_put_bool(bitbuf, prob, 0); + } else { + vp8e_put_bool(bitbuf, prob, 1); + vp8e_put_lit(bitbuf, new, 8); + } + } + } + } + } + return MPP_OK; +} + +MPP_RET vp8e_calc_mv_prob(Vp8ePutBitBuf *bitbuf, RK_S32 (*curr)[2][19], + RK_S32 (*prev)[2][19]) +{ + RK_S32 i, j; + RK_S32 prob, new, old; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 19; j++) { + prob = mv_update_prob_tbl[i][j]; + old = (RK_S32) (*prev)[i][j]; + new = (RK_S32) (*curr)[i][j]; + + if (new == old) { + vp8e_put_bool(bitbuf, prob, 0); + } else { + vp8e_put_bool(bitbuf, prob, 1); + vp8e_put_lit(bitbuf, new >> 1, 7); + } + } + } + return MPP_OK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_entropy.h b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.h new file mode 100644 index 000000000..d17e1dfc1 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_entropy.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_VP8E_ENTROPY_H +#define HAL_VP8E_ENTROPY_H + +#include "rk_type.h" + +#include "hal_vp8e_putbit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vp8e_init_entropy(void *hal); +MPP_RET vp8e_write_entropy_tables(void *hal); +RK_S32 vp8e_calc_cost_mv(RK_S32 mvd, RK_S32 *mv_prob); +MPP_RET vp8e_calc_coeff_prob(Vp8ePutBitBuf *bitbuf, + RK_S32 (*curr)[4][8][3][11], RK_S32 (*prev)[4][8][3][11]); +MPP_RET vp8e_calc_mv_prob(Vp8ePutBitBuf *bitbuf, + RK_S32 (*curr)[2][19], RK_S32 (*prev)[2][19]); +MPP_RET vp8e_swap_endian(RK_U32 *buf, RK_U32 bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_VP8E_ENTROPY_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_putbit.c b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.c new file mode 100644 index 000000000..56cb17d4b --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.c @@ -0,0 +1,104 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp8e_putbit" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_putbit.h" + +MPP_RET vp8e_set_buffer(Vp8ePutBitBuf *bitbuf, RK_U8 *data, RK_S32 size) +{ + if ((bitbuf == NULL) || (data == NULL) || (size < 1)) + return MPP_NOK; + + bitbuf->data = data; + bitbuf->p_data = data; + bitbuf->size = size; + + bitbuf->range = 255; + bitbuf->bottom = 0; + bitbuf->bits_left = 24; + + bitbuf->byte_cnt = 0; + + return MPP_OK; +} + +MPP_RET vp8e_put_bool(Vp8ePutBitBuf *bitbuf, RK_S32 prob, RK_S32 bool_value) +{ + RK_S32 split = 1 + ((bitbuf->range - 1) * prob >> 8); + + if (bool_value) { + bitbuf->bottom += split; + bitbuf->range -= split; + } else { + bitbuf->range = split; + } + + while (bitbuf->range < 128) { + if (bitbuf->bottom < 0) { + RK_U8 *data = bitbuf->data; + while (*--data == 255) { + *data = 0; + } + (*data)++; + } + bitbuf->range <<= 1; + bitbuf->bottom <<= 1; + + if (!--bitbuf->bits_left) { + *bitbuf->data++ = (bitbuf->bottom >> 24) & 0xff; + bitbuf->byte_cnt++; + bitbuf->bottom &= 0xffffff; /* Keep 3 bytes */ + bitbuf->bits_left = 8; + } + } + return MPP_OK; +} + +MPP_RET vp8e_put_lit(Vp8ePutBitBuf *bitbuf, RK_S32 value, + RK_S32 number) +{ + while (number--) { + vp8e_put_bool(bitbuf, 128, (value >> number) & 0x1); + } + return MPP_OK; +} + +MPP_RET vp8e_put_byte(Vp8ePutBitBuf *bitbuf, RK_S32 byte) +{ + *bitbuf->data++ = byte; + bitbuf->byte_cnt++; + return MPP_OK; +} + +MPP_RET vp8e_buffer_gap(Vp8ePutBitBuf *bitbuf, RK_S32 gap) +{ + if ((bitbuf->data - bitbuf->p_data) + gap > bitbuf->size) { + bitbuf->size = 0; + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET vp8e_buffer_overflow(Vp8ePutBitBuf *bitbuf) +{ + if (bitbuf->size > 0) + return MPP_OK; + + return MPP_NOK; +} diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_putbit.h b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.h new file mode 100644 index 000000000..f27cdd1af --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_putbit.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8E_PUT_BIT_H +#define HAL_VP8E_PUT_BIT_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef struct { + RK_U8 *data; + RK_U8 *p_data; + RK_S32 size; + RK_S32 byte_cnt; + + RK_S32 range; + RK_S32 bottom; + RK_S32 bits_left; +} Vp8ePutBitBuf; + +typedef struct { + RK_S32 value; + RK_S32 number; + RK_S32 index[9]; +} Vp8eTree; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vp8e_put_lit(Vp8ePutBitBuf *bitbuf, RK_S32 value, RK_S32 number); +MPP_RET vp8e_buffer_gap(Vp8ePutBitBuf *bitbuf, RK_S32 gap); +MPP_RET vp8e_buffer_overflow(Vp8ePutBitBuf *bitbuf); +MPP_RET vp8e_put_byte(Vp8ePutBitBuf *bitbuf, RK_S32 byte); +MPP_RET vp8e_put_bool(Vp8ePutBitBuf *bitbuf, RK_S32 prob, RK_S32 boolValue); +MPP_RET vp8e_set_buffer(Vp8ePutBitBuf *bitbuf, RK_U8 *data, RK_S32 size); + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_VP8E_PUTBIT_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_table.c b/mpp/hal/vpu/vp8e/hal_vp8e_table.c new file mode 100644 index 000000000..29be02862 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_table.c @@ -0,0 +1,579 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#include "hal_vp8e_table.h" + +RK_S32 const default_prob_coeff_tbl[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} + } + } +}; + +RK_S32 const default_prob_mv_tbl[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 + } +}; + +RK_S32 const vp8_prob_cost_tbl[] = { + 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 +}; + +RK_S32 const coeff_update_prob_tbl[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} + } + } +}; + +RK_S32 const mv_update_prob_tbl[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 + } +}; + +RK_S32 const default_skip_false_prob_tbl[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, +}; + +RK_S32 const y_mode_prob_tbl[4] = { + 112, 86, 140, 37 +}; + +RK_S32 const uv_mode_prob_tbl[3] = { + 162, 101, 204 +}; + +Vp8eTree const mv_tree_tbl[] = { + {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 */ +}; + +RK_S32 const dc_q_lookup_tbl[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 +}; + +RK_S32 const ac_q_lookup_tbl[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 +}; + +RK_S32 const q_rounding_factors_tbl[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 +}; + +RK_S32 const q_zbin_factors_tbl[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 +}; + +RK_S32 const zbin_boost_tbl[16] = { + 0, 0, 8, 10, 12, 14, 16, 20, 24, 28, + 32, 36, 40, 44, 44, 44 +}; + +RK_S32 const vp8_split_penalty_tbl[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 +}; + +RK_S32 const weight_tbl[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 +}; + +RK_S32 const intra4_mode_tree_penalty_tbl[] = { + 280, 622, 832, 1177, 1240, 1341, 1085, 1259, 1357, 1495 +}; + +RK_S32 const intra16_mode_tree_penalty_tbl[] = { + 305, 841, 914, 1082 +}; + +RK_S32 const inter_level_tbl[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 +}; + +RK_S32 const offset_tbl[] = { + -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 +}; diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_table.h b/mpp/hal/vpu/vp8e/hal_vp8e_table.h new file mode 100644 index 000000000..840ea1c91 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_table.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef HAL_VP8E_TABLE_H +#define HAL_VP8E_TABLE_H + +#include "hal_vp8e_base.h" +#include "hal_vp8e_putbit.h" + +extern RK_S32 const default_prob_coeff_tbl[4][8][3][11]; + +extern RK_S32 const default_prob_mv_tbl[2][19]; + +extern RK_S32 const vp8_prob_cost_tbl[]; + +extern RK_S32 const coeff_update_prob_tbl[4][8][3][11]; + +extern RK_S32 const mv_update_prob_tbl[2][19]; + +extern RK_S32 const default_skip_false_prob_tbl[128]; + +extern RK_S32 const y_mode_prob_tbl[4]; + +extern RK_S32 const uv_mode_prob_tbl[3]; + +extern Vp8eTree const mv_tree_tbl[]; + +extern RK_S32 const dc_q_lookup_tbl[QINDEX_RANGE]; + +extern RK_S32 const ac_q_lookup_tbl[QINDEX_RANGE]; + +extern RK_S32 const q_rounding_factors_tbl[QINDEX_RANGE]; + +extern RK_S32 const q_zbin_factors_tbl[QINDEX_RANGE]; + +extern RK_S32 const zbin_boost_tbl[16]; + +extern RK_S32 const vp8_split_penalty_tbl[128]; + +extern RK_S32 const weight_tbl[128]; + +extern RK_S32 const intra4_mode_tree_penalty_tbl[]; + +extern RK_S32 const intra16_mode_tree_penalty_tbl[]; + +extern const RK_S32 inter_level_tbl[128]; + +extern RK_S32 const offset_tbl[]; + +#endif /* HAL_VP8E_TBL_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_reg.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_reg.h new file mode 100644 index 000000000..7095a3470 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_reg.h @@ -0,0 +1,455 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8E_VEPU1_REG_H +#define HAL_VP8E_VEPU1_REG_H + +#include "rk_type.h" + +typedef struct { + RK_U32 sw0; + + struct { + RK_U32 val : 32; + } sw1; + + struct { + RK_U32 val : 32; + } sw2; + + RK_U32 sw3_4[2]; + + struct { + RK_U32 base_stream : 32; + } sw5; + + struct { + RK_U32 base_control : 32; + } sw6; + + struct { + RK_U32 base_ref_lum : 32; + } sw7; + + struct { + RK_U32 base_ref_chr : 32; + } sw8; + + struct { + RK_U32 base_rec_lum : 32; + } sw9; + + struct { + RK_U32 base_rec_chr : 32; + } sw10; + + struct { + RK_U32 base_in_lum : 32; + } sw11; + + struct { + RK_U32 base_in_cb : 32; + } sw12; + + struct { + RK_U32 base_in_cr : 32; + } sw13; + + struct { + RK_U32 enable : 1; + RK_U32 encoding_mode : 2; + RK_U32 picture_type : 2; + RK_U32 : 1; + RK_U32 rec_write_disable : 1; + RK_U32 : 3; + RK_U32 height : 9; + RK_U32 width : 9; + RK_U32 int_slice_ready : 1; + RK_U32 nal_size_write : 1; + RK_U32 mv_write : 1; + RK_U32 int_timeout : 1; + } sw14; + + struct { + RK_U32 input_rot : 2; + RK_U32 input_format : 4; + RK_U32 y_fill : 4; + RK_U32 x_fill : 2; + RK_U32 row_length : 14; + RK_U32 lum_offset : 3; + RK_U32 chr_offset : 3; + } sw15; + + struct { + RK_U32 base_ref_lum2 : 32; + } sw16; + + struct { + RK_U32 base_ref_chr2 : 32; + } sw17; + + struct { + RK_U32 ip_intra16_favor : 16; + RK_U32 stream_mode : 1; + RK_U32 inter_4_restrict : 1; + RK_U32 cabac_enable : 1; + RK_U32 cabac_initidc : 2; + RK_U32 transform_8x8 : 1; + RK_U32 disable_qp_mv : 1; + RK_U32 slice_size : 7; + RK_U32 deblocking : 2; + } sw18; + + struct { + RK_U32 dmv_penalty1p : 10; + RK_U32 dmv_penalty4p : 10; + RK_U32 dmv_penaltyqp : 10; + RK_U32 split_mv : 1; + RK_U32 : 1; + } sw19; + + struct { + RK_U32 split_penalty_8x4 : 10; + RK_U32 split_penalty_8x8 : 10; + RK_U32 split_penalty_16x8 : 10; + RK_U32 : 2; + } sw20; + + struct { + RK_U32 inter_favor : 16; + RK_U32 num_slices_ready : 8; + RK_U32 skip_penalty : 8; + } sw21; + + struct { + RK_U32 strm_hdr_rem1 : 32; + } sw22; + + struct { + RK_U32 strm_hdr_rem2 : 32; + } sw23; + + struct { + RK_U32 strm_buf_limit : 32; + } sw24; + + struct { + RK_U32 qp_sum : 21; + RK_U32 : 1; + RK_U32 mad_threshold : 6; + RK_U32 mad_qp_delta : 4; + } sw25; + + struct { + RK_U32 base_prob_count : 32; + } sw26; + + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 y1_zbin_dc : 9; + RK_U32 y1_round_dc : 8; + RK_U32 : 1; + } sw27; + + struct { + RK_U32 y1_quant_ac : 14; + RK_U32 y1_zbin_ac : 9; + RK_U32 y1_round_ac : 8; + RK_U32 : 1; + } sw28; + + struct { + RK_U32 y2_quant_dc : 14; + RK_U32 y2_zbin_dc : 9; + RK_U32 y2_round_dc : 8; + RK_U32 : 1; + } sw29; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 y2_zbin_ac : 9; + RK_U32 y2_round_ac : 8; + RK_U32 : 1; + } sw30; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 ch_zbin_dc : 9; + RK_U32 ch_round_dc : 8; + RK_U32 : 1; + } sw31; + + struct { + RK_U32 ch_quant_ac : 14; + RK_U32 ch_zbin_ac : 9; + RK_U32 ch_round_ac : 8; + RK_U32 : 1; + } sw32; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_dc : 9; + RK_U32 mv_ref_idx : 2; + RK_U32 : 4; + } sw33; + + struct { + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 ch_dequant_ac : 9; + RK_U32 mv_ref_idx2 : 2; + RK_U32 ref2_enable : 1; + RK_U32 segment_enable : 1; + RK_U32 segment_map_update : 1; + RK_U32 : 1; + } sw34; + + struct { + RK_U32 bool_enc_value : 32; + } sw35; + + struct { + RK_U32 bool_enc_range : 8; + RK_U32 bool_enc_value_bits : 5; + RK_U32 dct_partition_count : 2; + RK_U32 filter_level : 6; + RK_U32 filter_sharpness : 3; + RK_U32 golden_penalty : 8; + } sw36; + + struct { + RK_U32 rlc_sum : 23; + RK_U32 start_offset : 6; + RK_U32 : 3; + } sw37; + + struct { + RK_U32 mb_count : 16; + RK_U32 mad_count : 16; + } sw38; + + struct { + RK_U32 base_next_lum : 32; + } sw39; + + struct { + RK_U32 stab_minimum : 24; + RK_U32 : 6; + RK_U32 stab_mode : 2; + } sw40; + RK_U32 sw41_50[10]; + + struct { + RK_U32 base_cabac_ctx : 32; + } sw51; + + struct { + RK_U32 base_mv_write : 32; + } sw52; + + struct { + RK_U32 rgb_coeff_a : 16; + RK_U32 rgb_coeff_b : 16; + } sw53; + + struct { + RK_U32 rgb_coeff_c : 16; + RK_U32 rgb_coeff_e : 16; + } sw54; + + struct { + RK_U32 rgb_coeff_f : 16; + RK_U32 r_mask_msb : 5; + RK_U32 g_mask_msb : 5; + RK_U32 b_mask_msb : 5; + RK_U32 : 1; + } sw55; + + struct { + RK_U32 intra_area_bottom : 8; + RK_U32 intra_area_top : 8; + RK_U32 intra_area_right : 8; + RK_U32 intra_area_left : 8; + } sw56; + + struct { + RK_U32 cir_interval : 16; + RK_U32 cir_start : 16; + } sw57; + + struct { + RK_U32 base_partition1 : 32; + } sw58; + + struct { + RK_U32 base_partition2 : 32; + } sw59; + + struct { + RK_U32 roi1_bottom : 8; + RK_U32 roi1_top : 8; + RK_U32 roi1_right : 8; + RK_U32 roi1_left : 8; + } sw60; + + struct { + RK_U32 roi2_bottom : 8; + RK_U32 roi2_top : 8; + RK_U32 roi2_right : 8; + RK_U32 roi2_left : 8; + } sw61; + + struct { + RK_U32 roi2_delta_qp : 4; + RK_U32 roi1_delta_qp : 4; + RK_U32 mvc_inter_view_flag : 1; + RK_U32 mvc_anchor_pic_flag : 1; + RK_U32 mvc_temporal_id : 3; + RK_U32 mvc_view_id : 3; + RK_U32 mvc_priority_id : 3; + RK_U32 split_penalty4x4 : 9; + RK_U32 zero_mv_favor : 4; + } sw62; + + RK_U32 sw63; + + struct { + RK_U32 mode0_penalty : 12; + RK_U32 mode1_penalty : 12; + RK_U32 : 8; + } sw64; + + struct { + RK_U32 mode2_penalty : 12; + RK_U32 mode3_penalty : 12; + RK_U32 : 8; + } sw65; + + struct { + RK_U32 b_mode_0_penalty : 12; + RK_U32 b_mode_1_penalty : 12; + RK_U32 : 8; + } sw66_70[5]; + + struct { + RK_U32 base_segment_map : 32; + } sw71; + + union { + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 y1_zbin_dc : 9; + RK_U32 y1_round_dc : 8; + RK_U32 : 1; + } num_0; + + struct { + RK_U32 y1_quant_ac : 14; + RK_U32 y1_zbin_ac : 9; + RK_U32 y1_round_ac : 8; + RK_U32 : 1; + } num_1; + + struct { + RK_U32 y2_quant_dc : 14; + RK_U32 y2_zbin_dc : 9; + RK_U32 y2_round_dc : 8; + RK_U32 : 1; + } num_2; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 y2_zbin_ac : 9; + RK_U32 y2_round_ac : 8; + RK_U32 : 1; + } num_3; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 ch_zbin_dc : 9; + RK_U32 ch_round_dc : 8; + RK_U32 : 1; + } num_4; + + struct { + RK_U32 ch_quant_ac : 14; + RK_U32 ch_zbin_ac : 9; + RK_U32 ch_round_ac : 8; + RK_U32 : 1; + } num_5; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_dc : 9; + RK_U32 : 6; + } num_6; + + struct { + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 ch_dequant_ac : 9; + RK_U32 filter_level : 6; + } num_7; + + } sw72_95[24]; + + struct { + RK_U32 penalty_0 : 8; + RK_U32 penalty_1 : 8; + RK_U32 penalty_2 : 8; + RK_U32 penalty_3 : 8; + } sw96_127[32]; + + struct { + RK_U32 qpel_penalty_0 : 8; + RK_U32 qpel_penalty_1 : 8; + RK_U32 qpel_penalty_2 : 8; + RK_U32 qpel_penalty_3 : 8; + } sw128_159[32]; + + + struct { + RK_U32 cost_inter : 12; + RK_U32 dmv_cost_const : 12; + RK_U32 : 8; + } sw160; + + struct { + RK_U32 cost_golden_ref : 12; + RK_U32 : 20; + } sw161; + + struct { + RK_U32 lf_ref_delta0 : 7; //vp8_loopfilter_intra + RK_U32 lf_ref_delta1 : 7; //vp8_loopfilter_lastref + RK_U32 lf_ref_delta2 : 7; //vp8_loopfilter_glodenref + RK_U32 lf_ref_delta3 : 7; //vp8_loopfilter_alterf + RK_U32 : 4; + } sw162; + + struct { + RK_U32 lf_mode_delta0 : 7; //vp8_loopfilter_bpred + RK_U32 lf_mode_delta1 : 7; //vp8_loopfilter_zeromv + RK_U32 lf_mode_delta2 : 7; //vp8_loopfilter_newmv + RK_U32 lf_mode_delta3 : 7; //vp8_loopfilter_splitmv + RK_U32 : 4; + } sw163; + +} Vp8eVepu1Reg_t; + +#endif /* HAL_VP8E_VEPU1_REG_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_v2.c b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_v2.c new file mode 100644 index 000000000..f70dfeae4 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_v2.c @@ -0,0 +1,544 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp8e_vepu1_v2" + +#include + +#include "mpp_mem.h" +#include "mpp_rc.h" +#include "mpp_common.h" +#include "vp8e_syntax.h" + +#include "hal_vp8e_base.h" +#include "hal_vp8e_vepu1_v2.h" +#include "hal_vp8e_vepu1_reg.h" +#include "hal_vp8e_debug.h" + +#define SWREG_AMOUNT_VEPU1 (164) +#define HW_STATUS_MASK 0x58 +#define HW_STATUS_BUFFER_FULL 0x20 +#define HW_STATUS_FRAME_READY 0x04 + +static MPP_RET vp8e_vpu_frame_start(void *hal) +{ + RK_S32 i = 0; + HalVp8eCtx *ctx = (HalVp8eCtx *) hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu1Reg_t *regs = (Vp8eVepu1Reg_t *) ctx->regs; + + memset(regs, 0, sizeof(Vp8eVepu1Reg_t)); + + regs->sw1.val = (hw_cfg->irq_disable != 0) ? (regs->sw1.val | 0x02) : + (regs->sw1.val & 0xfffffffd); + + + if (hw_cfg->input_format < INPUT_RGB565) + regs->sw2.val = 0xd00f; + + else if (hw_cfg->input_format < INPUT_RGB888) + regs->sw2.val = 0xd00f; + else + regs->sw2.val = 0x900e; + + regs->sw5.base_stream = hw_cfg->output_strm_base; + mpp_dev_set_reg_offset(ctx->dev, 5, hw_cfg->output_strm_offset); + + regs->sw6.base_control = hw_cfg->size_tbl_base; + regs->sw14.nal_size_write = (hw_cfg->size_tbl_base != 0); + regs->sw14.mv_write = (hw_cfg->mv_output_base != 0); + + regs->sw7.base_ref_lum = hw_cfg->internal_img_lum_base_r[0]; + regs->sw8.base_ref_chr = hw_cfg->internal_img_chr_base_r[0]; + regs->sw9.base_rec_lum = hw_cfg->internal_img_lum_base_w; + regs->sw10.base_rec_chr = hw_cfg->internal_img_chr_base_w; + + regs->sw11.base_in_lum = hw_cfg->input_lum_base; + if (hw_cfg->input_lum_offset) + mpp_dev_set_reg_offset(ctx->dev, 11, hw_cfg->input_lum_offset); + + regs->sw12.base_in_cb = hw_cfg->input_cb_base; + if (hw_cfg->input_cb_offset) + mpp_dev_set_reg_offset(ctx->dev, 12, hw_cfg->input_cb_offset); + + regs->sw13.base_in_cr = hw_cfg->input_cr_base; + if (hw_cfg->input_cr_offset) + mpp_dev_set_reg_offset(ctx->dev, 13, hw_cfg->input_cr_offset); + + regs->sw14.int_timeout = 1; + regs->sw14.int_slice_ready = hw_cfg->int_slice_ready; + regs->sw14.rec_write_disable = hw_cfg->rec_write_disable; + regs->sw14.width = hw_cfg->mbs_in_row; + regs->sw14.height = hw_cfg->mbs_in_col; + regs->sw14.picture_type = hw_cfg->frame_coding_type; + regs->sw14.encoding_mode = hw_cfg->coding_type; + + regs->sw15.chr_offset = hw_cfg->input_chroma_base_offset; + regs->sw15.lum_offset = hw_cfg->input_luma_base_offset; + regs->sw15.row_length = hw_cfg->pixels_on_row; + regs->sw15.x_fill = hw_cfg->x_fill; + regs->sw15.y_fill = hw_cfg->y_fill; + regs->sw15.input_format = hw_cfg->input_format; + regs->sw15.input_rot = hw_cfg->input_rotation; + + regs->sw18.cabac_enable = hw_cfg->enable_cabac; + regs->sw18.ip_intra16_favor = hw_cfg->intra_16_favor; + regs->sw21.inter_favor = hw_cfg->inter_favor; + regs->sw18.disable_qp_mv = hw_cfg->disable_qp_mv; + regs->sw18.deblocking = hw_cfg->filter_disable; + regs->sw21.skip_penalty = hw_cfg->skip_penalty; + regs->sw19.split_mv = hw_cfg->split_mv_mode; + regs->sw20.split_penalty_16x8 = hw_cfg->split_penalty[0]; + regs->sw20.split_penalty_8x8 = hw_cfg->split_penalty[1]; + regs->sw20.split_penalty_8x4 = hw_cfg->split_penalty[2]; + regs->sw62.split_penalty4x4 = hw_cfg->split_penalty[3]; + regs->sw62.zero_mv_favor = hw_cfg->zero_mv_favor; + + regs->sw22.strm_hdr_rem1 = hw_cfg->strm_start_msb; + regs->sw23.strm_hdr_rem2 = hw_cfg->strm_start_lsb; + regs->sw24.strm_buf_limit = hw_cfg->output_strm_size; + + regs->sw16.base_ref_lum2 = hw_cfg->internal_img_lum_base_r[1]; + regs->sw17.base_ref_chr2 = hw_cfg->internal_img_chr_base_r[1]; + + regs->sw27.y1_quant_dc = hw_cfg->y1_quant_dc[0]; + regs->sw28.y1_quant_ac = hw_cfg->y1_quant_ac[0]; + regs->sw29.y2_quant_dc = hw_cfg->y2_quant_dc[0]; + regs->sw30.y2_quant_ac = hw_cfg->y2_quant_ac[0]; + regs->sw31.ch_quant_dc = hw_cfg->ch_quant_dc[0]; + regs->sw32.ch_quant_ac = hw_cfg->ch_quant_ac[0]; + + regs->sw27.y1_zbin_dc = hw_cfg->y1_zbin_dc[0]; + regs->sw28.y1_zbin_ac = hw_cfg->y1_zbin_ac[0]; + regs->sw29.y2_zbin_dc = hw_cfg->y2_zbin_dc[0]; + regs->sw30.y2_zbin_ac = hw_cfg->y2_zbin_ac[0]; + regs->sw31.ch_zbin_dc = hw_cfg->ch_zbin_dc[0]; + regs->sw32.ch_zbin_ac = hw_cfg->ch_zbin_ac[0]; + + regs->sw27.y1_round_dc = hw_cfg->y1_round_dc[0]; + regs->sw28.y1_round_ac = hw_cfg->y1_round_ac[0]; + regs->sw29.y2_round_dc = hw_cfg->y2_round_dc[0]; + regs->sw30.y2_round_ac = hw_cfg->y2_round_ac[0]; + regs->sw31.ch_round_dc = hw_cfg->ch_round_dc[0]; + regs->sw32.ch_round_ac = hw_cfg->ch_round_ac[0]; + + regs->sw33.y1_dequant_dc = hw_cfg->y1_dequant_dc[0]; + regs->sw33.y1_dequant_ac = hw_cfg->y1_dequant_ac[0]; + regs->sw33.y2_dequant_dc = hw_cfg->y2_dequant_dc[0]; + regs->sw34.y2_dequant_ac = hw_cfg->y2_dequant_ac[0]; + regs->sw34.ch_dequant_dc = hw_cfg->ch_dequant_dc[0]; + regs->sw34.ch_dequant_ac = hw_cfg->ch_dequant_ac[0]; + + regs->sw33.mv_ref_idx = hw_cfg->mv_ref_idx[0]; + regs->sw34.mv_ref_idx2 = hw_cfg->mv_ref_idx[1]; + regs->sw34.ref2_enable = hw_cfg->ref2_enable; + + regs->sw35.bool_enc_value = hw_cfg->bool_enc_value; + regs->sw36.bool_enc_value_bits = hw_cfg->bool_enc_value_bits; + regs->sw36.bool_enc_range = hw_cfg->bool_enc_range; + + regs->sw36.filter_level = hw_cfg->filter_level[0]; + regs->sw36.golden_penalty = hw_cfg->golden_penalty; + regs->sw36.filter_sharpness = hw_cfg->filter_sharpness; + regs->sw36.dct_partition_count = hw_cfg->dct_partitions; + + regs->sw37.start_offset = hw_cfg->first_free_bit; + + regs->sw39.base_next_lum = hw_cfg->vs_next_luma_base; + regs->sw40.stab_mode = hw_cfg->vs_mode; + + regs->sw19.dmv_penalty4p = hw_cfg->diff_mv_penalty[0]; + regs->sw19.dmv_penalty1p = hw_cfg->diff_mv_penalty[1]; + regs->sw19.dmv_penaltyqp = hw_cfg->diff_mv_penalty[2]; + + regs->sw51.base_cabac_ctx = hw_cfg->cabac_tbl_base; + regs->sw52.base_mv_write = hw_cfg->mv_output_base; + + regs->sw53.rgb_coeff_a = hw_cfg->rgb_coeff_a; + regs->sw53.rgb_coeff_b = hw_cfg->rgb_coeff_b; + regs->sw54.rgb_coeff_c = hw_cfg->rgb_coeff_c; + regs->sw54.rgb_coeff_e = hw_cfg->rgb_coeff_e; + regs->sw55.rgb_coeff_f = hw_cfg->rgb_coeff_f; + + regs->sw55.r_mask_msb = hw_cfg->r_mask_msb; + regs->sw55.g_mask_msb = hw_cfg->g_mask_msb; + regs->sw55.b_mask_msb = hw_cfg->b_mask_msb; + + regs->sw57.cir_start = hw_cfg->cir_start; + regs->sw57.cir_interval = hw_cfg->cir_interval; + + regs->sw56.intra_area_left = hw_cfg->intra_area_left; + regs->sw56.intra_area_right = hw_cfg->intra_area_right; + regs->sw56.intra_area_top = hw_cfg->intra_area_top; + regs->sw56.intra_area_bottom = hw_cfg->intra_area_bottom; + regs->sw60.roi1_left = hw_cfg->roi1_left; + regs->sw60.roi1_right = hw_cfg->roi1_right; + regs->sw60.roi1_top = hw_cfg->roi1_top; + regs->sw60.roi1_bottom = hw_cfg->roi1_bottom; + + regs->sw61.roi2_left = hw_cfg->roi2_left; + regs->sw61.roi2_right = hw_cfg->roi2_right; + regs->sw61.roi2_top = hw_cfg->roi2_top; + regs->sw61.roi2_bottom = hw_cfg->roi2_bottom; + + regs->sw58.base_partition1 = hw_cfg->partition_Base[0]; + mpp_dev_set_reg_offset(ctx->dev, 58, hw_cfg->partition_offset[0]); + regs->sw59.base_partition2 = hw_cfg->partition_Base[1]; + mpp_dev_set_reg_offset(ctx->dev, 59, hw_cfg->partition_offset[1]); + regs->sw26.base_prob_count = hw_cfg->prob_count_base; + + regs->sw64.mode0_penalty = hw_cfg->intra_mode_penalty[0]; + regs->sw64.mode1_penalty = hw_cfg->intra_mode_penalty[1]; + regs->sw65.mode2_penalty = hw_cfg->intra_mode_penalty[2]; + regs->sw65.mode3_penalty = hw_cfg->intra_mode_penalty[3]; + + for (i = 0; i < 5; i++) { + regs->sw66_70[i].b_mode_0_penalty = hw_cfg->intra_b_mode_penalty[2 * i]; + regs->sw66_70[i].b_mode_1_penalty = hw_cfg->intra_b_mode_penalty[2 * i + 1]; + } + + regs->sw34.segment_enable = hw_cfg->segment_enable; + regs->sw34.segment_map_update = hw_cfg->segment_map_update; + regs->sw71.base_segment_map = hw_cfg->segment_map_base; + + for (i = 0; i < 3; i++) { + regs->sw72_95[0 + i * 8].num_0.y1_quant_dc = hw_cfg->y1_quant_dc[1 + i]; + regs->sw72_95[0 + i * 8].num_0.y1_zbin_dc = hw_cfg->y1_zbin_dc[1 + i]; + regs->sw72_95[0 + i * 8].num_0.y1_round_dc = hw_cfg->y1_round_dc[1 + i]; + + regs->sw72_95[1 + i * 8].num_1.y1_quant_ac = hw_cfg->y1_quant_ac[1 + i]; + regs->sw72_95[1 + i * 8].num_1.y1_zbin_ac = hw_cfg->y1_zbin_ac[1 + i]; + regs->sw72_95[1 + i * 8].num_1.y1_round_ac = hw_cfg->y1_round_ac[1 + i]; + + regs->sw72_95[2 + i * 8].num_2.y2_quant_dc = hw_cfg->y2_quant_dc[1 + i]; + regs->sw72_95[2 + i * 8].num_2.y2_zbin_dc = hw_cfg->y2_zbin_dc[1 + i]; + regs->sw72_95[2 + i * 8].num_2.y2_round_dc = hw_cfg->y2_round_dc[1 + i]; + + regs->sw72_95[3 + i * 8].num_3.y2_quant_ac = hw_cfg->y2_quant_ac[1 + i]; + regs->sw72_95[3 + i * 8].num_3.y2_zbin_ac = hw_cfg->y2_zbin_ac[1 + i]; + regs->sw72_95[3 + i * 8].num_3.y2_round_ac = hw_cfg->y2_round_ac[1 + i]; + + regs->sw72_95[4 + i * 8].num_4.ch_quant_dc = hw_cfg->ch_quant_dc[1 + i]; + regs->sw72_95[4 + i * 8].num_4.ch_zbin_dc = hw_cfg->ch_zbin_dc[1 + i]; + regs->sw72_95[4 + i * 8].num_4.ch_round_dc = hw_cfg->ch_round_dc[1 + i]; + + regs->sw72_95[5 + i * 8].num_5.ch_quant_ac = hw_cfg->ch_quant_ac[1 + i]; + regs->sw72_95[5 + i * 8].num_5.ch_zbin_ac = hw_cfg->ch_zbin_ac[1 + i]; + regs->sw72_95[5 + i * 8].num_5.ch_round_ac = hw_cfg->ch_round_ac[1 + i]; + + regs->sw72_95[6 + i * 8].num_6.y1_dequant_dc = hw_cfg->y1_dequant_dc[1 + i]; + regs->sw72_95[6 + i * 8].num_6.y1_dequant_ac = hw_cfg->y1_dequant_ac[1 + i]; + regs->sw72_95[6 + i * 8].num_6.y2_dequant_dc = hw_cfg->y2_dequant_dc[1 + i]; + + regs->sw72_95[7 + i * 8].num_7.y2_dequant_ac = hw_cfg->y2_dequant_ac[1 + i]; + regs->sw72_95[7 + i * 8].num_7.ch_dequant_dc = hw_cfg->ch_dequant_dc[1 + i]; + regs->sw72_95[7 + i * 8].num_7.ch_dequant_ac = hw_cfg->ch_dequant_ac[1 + i]; + regs->sw72_95[7 + i * 8].num_7.filter_level = hw_cfg->filter_level[1 + i]; + + } + + regs->sw162.lf_ref_delta0 = hw_cfg->lf_ref_delta[0] & mask_7b; + regs->sw162.lf_ref_delta1 = hw_cfg->lf_ref_delta[1] & mask_7b; + regs->sw162.lf_ref_delta2 = hw_cfg->lf_ref_delta[2] & mask_7b; + regs->sw162.lf_ref_delta3 = hw_cfg->lf_ref_delta[3] & mask_7b; + regs->sw163.lf_mode_delta0 = hw_cfg->lf_mode_delta[0] & mask_7b; + regs->sw163.lf_mode_delta1 = hw_cfg->lf_mode_delta[1] & mask_7b; + regs->sw163.lf_mode_delta2 = hw_cfg->lf_mode_delta[2] & mask_7b; + regs->sw163.lf_mode_delta3 = hw_cfg->lf_mode_delta[3] & mask_7b; + + RK_S32 j = 0; + + for (j = 0; j < 32; j++) { + regs->sw96_127[j].penalty_0 = hw_cfg->dmv_penalty[j * 4 + 3]; + regs->sw96_127[j].penalty_1 = hw_cfg->dmv_penalty[j * 4 + 2]; + regs->sw96_127[j].penalty_2 = hw_cfg->dmv_penalty[j * 4 + 1]; + regs->sw96_127[j].penalty_3 = hw_cfg->dmv_penalty[j * 4]; + + regs->sw128_159[j].qpel_penalty_0 = hw_cfg->dmv_qpel_penalty[j * 4 + 3]; + regs->sw128_159[j].qpel_penalty_1 = hw_cfg->dmv_qpel_penalty[j * 4 + 2]; + regs->sw128_159[j].qpel_penalty_2 = hw_cfg->dmv_qpel_penalty[j * 4 + 1]; + regs->sw128_159[j].qpel_penalty_3 = hw_cfg->dmv_qpel_penalty[j * 4]; + } + + regs->sw14.enable = 1; + + return MPP_OK; +} + +static MPP_RET hal_vp8e_vepu1_init_v2(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + + ctx->cfg = cfg->cfg; + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_VEPU1; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + ctx->dev = cfg->dev; + + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_dev_init success.\n"); + + ctx->buffers = mpp_calloc(Vp8eVpuBuf, 1); + if (ctx->buffers == NULL) { + mpp_err("failed to malloc buffers"); + return MPP_ERR_NOMEM; + } + ctx->buffer_ready = 0; + ctx->frame_cnt = 0; + ctx->frame_type = VP8E_FRM_KEY; + ctx->prev_frame_lost = 0; + ctx->frame_size = 0; + ctx->ivf_hdr_rdy = 0; + ctx->reg_size = SWREG_AMOUNT_VEPU1; + + hw_cfg->irq_disable = 0; + + hw_cfg->rounding_ctrl = 0; + hw_cfg->cp_distance_mbs = 0; + hw_cfg->recon_img_id = 0; + hw_cfg->input_lum_base = 0; + hw_cfg->input_cb_base = 0; + hw_cfg->input_cr_base = 0; + + hal_vp8e_init_qp_table(hal); + + return ret; +} + +static MPP_RET hal_vp8e_vepu1_deinit_v2(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + hal_vp8e_buf_free(ctx); + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->buffers); + + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_dev_deinit success.\n"); + + return ret; +} + +static MPP_RET hal_vp8e_vepu1_gen_regs_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + ctx->rc->qp_hdr = MPP_CLIP3(0, 127, task->rc_task->info.quality_target); + + if (!ctx->buffer_ready) { + ret = hal_vp8e_setup(hal); + if (ret) { + mpp_err("failed to init hal vp8e\n"); + return ret; + } else { + ctx->buffer_ready = 1; + } + } + + memset(ctx->stream_size, 0, sizeof(ctx->stream_size)); + + hal_vp8e_enc_strm_code(ctx, task); + vp8e_vpu_frame_start(ctx); + + return MPP_OK; +} + +static MPP_RET hal_vp8e_vepu1_start_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (VP8E_DBG_HAL_DUMP_REG & hal_vp8e_debug) { + RK_U32 i = 0; + RK_U32 *tmp = (RK_U32 *)ctx->regs; + + for (; i < ctx->reg_size; i++) + mpp_log("reg[%d]:%x\n", i, tmp[i]); + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = ctx->reg_size * sizeof(RK_U32); + + wr_cfg.reg = ctx->regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ctx->regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +static void vp8e_update_hw_cfg(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu1Reg_t * regs = (Vp8eVepu1Reg_t *)ctx->regs; + + hw_cfg->output_strm_base = regs->sw24.strm_buf_limit / 8; + hw_cfg->qp_sum = regs->sw25.qp_sum * 2; + hw_cfg->mad_count = regs->sw38.mad_count; + hw_cfg->rlc_count = regs->sw37.rlc_sum * 4; + + hw_cfg->intra_16_favor = -1; + hw_cfg->inter_favor = -1; + hw_cfg->diff_mv_penalty[0] = -1; + hw_cfg->diff_mv_penalty[1] = -1; + hw_cfg->diff_mv_penalty[2] = -1; + hw_cfg->skip_penalty = -1; + hw_cfg->golden_penalty = -1; + hw_cfg->split_penalty[0] = 0; + hw_cfg->split_penalty[1] = 0; + hw_cfg->split_penalty[3] = 0; + +} + +static MPP_RET hal_vp8e_vepu1_wait_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eFeedback *fb = &ctx->feedback; + Vp8eVepu1Reg_t *regs = (Vp8eVepu1Reg_t *)ctx->regs; + RK_S32 sw_length = task->length; + + if (NULL == ctx->dev) { + mpp_err_f("invalid dev ctx\n"); + return MPP_NOK; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + fb->hw_status = regs->sw1.val & HW_STATUS_MASK; + if (regs->sw1.val & HW_STATUS_FRAME_READY) + vp8e_update_hw_cfg(ctx); + else if (regs->sw1.val & HW_STATUS_BUFFER_FULL) + ctx->bitbuf[1].size = 0; + + hal_vp8e_update_buffers(ctx, task); + + ctx->last_frm_intra = task->rc_task->frm.is_intra; + ctx->frame_cnt++; + + task->rc_task->info.bit_real = ctx->frame_size << 3; + task->hw_length = task->length - sw_length; + + return ret; +} + +static MPP_RET hal_vp8e_vepu1_get_task_v2(void *hal, HalEncTask *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eSyntax* syntax = (Vp8eSyntax*)task->syntax.data; + //ctx->cfg = syntax->cfg; + RK_U32 i; + + for (i = 0; i < task->syntax.number; i++) { + if (syntax[i].type == VP8E_SYN_CFG) { + ctx->cfg = (MppEncCfgSet*)syntax[i].data; + } + if (syntax[i].type == VP8E_SYN_RC) { + ctx->rc = (Vp8eRc*) syntax[i].data; + } + } + + ctx->frame_type = (task->rc_task->frm.is_intra != 0) ? VP8E_FRM_KEY : VP8E_FRM_P; + + if (!ctx->cfg->vp8.disable_ivf && !ctx->ivf_hdr_rdy) { + RK_U8 *p_out = mpp_buffer_get_ptr(task->output); + + write_ivf_header(hal, p_out); + task->length += IVF_HDR_BYTES; + + ctx->ivf_hdr_rdy = 1; + } + + return MPP_OK; +} + +static MPP_RET hal_vp8e_vepu1_ret_task_v2(void *hal, HalEncTask *task) +{ + (void)hal; + (void)task; + + return MPP_OK; +} + +const MppEncHalApi hal_vp8e_vepu1 = { + .name = "hal_vp8e_vepu1", + .coding = MPP_VIDEO_CodingVP8, + .ctx_size = sizeof(HalVp8eCtx), + .flag = 0, + .init = hal_vp8e_vepu1_init_v2, + .deinit = hal_vp8e_vepu1_deinit_v2, + .prepare = NULL, + .get_task = hal_vp8e_vepu1_get_task_v2, + .gen_regs = hal_vp8e_vepu1_gen_regs_v2, + .start = hal_vp8e_vepu1_start_v2, + .wait = hal_vp8e_vepu1_wait_v2, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_vp8e_vepu1_ret_task_v2, + .client = VPU_CLIENT_VEPU1, + .soc_type = { + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_vp8e_vepu1) diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_v2.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_v2.h new file mode 100644 index 000000000..347ee4963 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu1_v2.h @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8E_VEPU1_V2_H +#define HAL_VP8E_VEPU1_V2_H + +#include "hal_vp8e_base.h" +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_vp8e_vepu1; + +#endif /* HAL_VP8E_VEPU1_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_reg.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_reg.h new file mode 100644 index 000000000..70835b2f9 --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_reg.h @@ -0,0 +1,498 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8E_VEPU2_REG_H +#define HAL_VP8E_VEPU2_REG_H + +#include "rk_type.h" + +typedef struct { + union { + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 : 2; + RK_U32 y2_quant_dc : 14; + RK_U32 : 2; + } num_0; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 : 2; + RK_U32 y1_quant_ac : 14; + RK_U32 : 2; + } num_1; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 : 2; + RK_U32 ch_quant_ac : 14; + RK_U32 : 2; + } num_2; + + struct { + RK_U32 y1_zbin_dc : 9; + RK_U32 y2_zbin_dc : 9; + RK_U32 ch_zbin_dc : 9; + RK_U32 : 5; + } num_3; + + struct { + RK_U32 y1_zbin_ac : 9; + RK_U32 y2_zbin_ac : 9; + RK_U32 ch_zbin_ac : 9; + RK_U32 : 5; + } num_4; + + struct { + RK_U32 y1_round_dc : 8; + RK_U32 y2_round_dc : 8; + RK_U32 ch_round_dc : 8; + RK_U32 : 8; + } num_5; + + struct { + RK_U32 y1_round_ac : 8; + RK_U32 y2_round_ac : 8; + RK_U32 ch_round_ac : 8; + RK_U32 : 8; + } num_6; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y2_dequant_dc : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 filter_level : 6; + RK_U32 : 1; + } num_7; + + struct { + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_ac : 9; + RK_U32 : 5; + } num_8; + + } sw0_26[27]; + + struct { + RK_U32 base_segment_map : 32; + } sw27; + + struct { + RK_U32 b_mode_0_penalty : 12; + RK_U32 : 4; + RK_U32 b_mode_1_penalty : 12; + RK_U32 : 4; + } sw28_32[5]; + + struct { + RK_U32 mode0_penalty : 12; + RK_U32 : 4; + RK_U32 mode1_penalty : 12; + RK_U32 : 4; + } sw33; + + struct { + RK_U32 mode2_penalty : 12; + RK_U32 : 4; + RK_U32 mode3_penalty : 12; + RK_U32 : 4; + } sw34; + + RK_U32 sw35_39[5]; + + struct { + RK_U32 cost_inter : 12; + RK_U32 : 4; + RK_U32 lf_ref_delta0 : 7; + RK_U32 : 1; + RK_U32 lf_mode_delta0 : 7; + RK_U32 : 1; + } sw40; + + struct { + RK_U32 cost_golden_ref : 12; + RK_U32 : 4; + RK_U32 dmv_cost_const : 12; + RK_U32 : 4; + } sw41; + + struct { + RK_U32 lf_ref_delta2 : 7; + RK_U32 : 1; + RK_U32 lf_ref_delta1 : 7; + RK_U32 : 1; + RK_U32 lf_ref_delta3 : 7; + RK_U32 : 9; + } sw42; + + struct { + RK_U32 lf_mode_delta2 : 7; + RK_U32 : 1; + RK_U32 lf_mode_delta1 : 7; + RK_U32 : 1; + RK_U32 lf_mode_delta3 : 7; + RK_U32 : 9; + } sw43; + + struct { + RK_U32 base_partition1 : 32; + } sw44; + + struct { + RK_U32 base_partition2 : 32; + } sw45; + + struct { + RK_U32 intra_area_right : 8; + RK_U32 intra_area_left : 8; + RK_U32 intra_area_bottom : 8; + RK_U32 intra_area_top : 8; + } sw46; + + struct { + RK_U32 cir_interval : 16; + RK_U32 cir_start : 16; + } sw47; + + struct { + RK_U32 base_in_lum : 32; + } sw48; + + struct { + RK_U32 base_in_cb : 32; + } sw49; + + struct { + RK_U32 base_in_cr : 32; + } sw50; + + struct { + RK_U32 strm_hdr_rem1 : 32; + } sw51; + + struct { + RK_U32 strm_hdr_rem2 : 32; + } sw52; + + struct { + RK_U32 strm_buf_limit : 32; + } sw53; + + struct { + RK_U32 val : 32; + } sw54; + + RK_U32 sw55; + + struct { + RK_U32 base_ref_lum : 32; + } sw56; + + struct { + RK_U32 base_ref_chr : 32; + } sw57; + + struct { + RK_U32 : 11; + RK_U32 qp_sum : 21; + } sw58; + + struct { + RK_U32 : 8; + RK_U32 slice_size : 7; + RK_U32 strea_mmode : 1; + RK_U32 inter4_restrict : 1; + RK_U32 transform_8x8 : 1; + RK_U32 : 2; + RK_U32 cabac_enable : 1; + RK_U32 cabac_init_idc : 2; + RK_U32 : 1; + RK_U32 deblocking : 2; + RK_U32 : 2; + RK_U32 disable_qp_mv : 1; + RK_U32 : 3; + } sw59; + + struct { + RK_U32 y_fill : 4; + RK_U32 x_fill : 2; + RK_U32 : 2; + RK_U32 skip_penalty : 8; + RK_U32 start_offset : 6; + RK_U32 : 10; + } sw60; + + struct { + RK_U32 row_length : 14; + RK_U32 : 2; + RK_U32 lum_offset : 3; + RK_U32 : 1; + RK_U32 chr_offset : 3; + RK_U32 : 9; + } sw61; + + struct { + RK_U32 rlc_sum : 23; + RK_U32 : 9; + } sw62; + + struct { + RK_U32 base_rec_lum : 32; + } sw63; + + struct { + RK_U32 base_rec_chr : 32; + } sw64; + + struct { + RK_U32 y1_quant_ac : 14; + RK_U32 y1_zbin_ac : 9; + RK_U32 y1_round_ac : 8; + RK_U32 : 1; + } sw65; + + struct { + RK_U32 y2_quant_dc : 14; + RK_U32 y2_zbin_dc : 9; + RK_U32 y2_round_dc : 8; + RK_U32 : 1; + } sw66; + + struct { + RK_U32 y2_quant_ac : 14; + RK_U32 y2_zbin_ac : 9; + RK_U32 y2_round_ac : 8; + RK_U32 : 1; + } sw67; + + struct { + RK_U32 ch_quant_dc : 14; + RK_U32 ch_zbin_dc : 9; + RK_U32 ch_round_dc : 8; + RK_U32 : 1; + } sw68; + + struct { + RK_U32 ch_quant_ac : 14; + RK_U32 ch_zbin_ac : 9; + RK_U32 ch_round_ac : 8; + RK_U32 : 1; + } sw69; + + struct { + RK_U32 y1_dequant_dc : 8; + RK_U32 y1_dequant_ac : 9; + RK_U32 y2_dequant_dc : 9; + RK_U32 mv_ref_idx : 2 ; + RK_U32 : 4; + } sw70; + + struct { + RK_U32 y2_dequant_ac : 9; + RK_U32 ch_dequant_dc : 8; + RK_U32 ch_dequant_ac : 9; + RK_U32 mv_ref_idx2 : 2; + RK_U32 ref2_enable : 1; + RK_U32 segment_enable : 1; + RK_U32 segment_map_update : 1; + RK_U32 : 1; + } sw71; + + struct { + RK_U32 bool_enc_value : 32; + } sw72; + + struct { + RK_U32 bool_enc_range : 8; + RK_U32 bool_enc_value_bits : 5; + RK_U32 dct_partition_count : 2; + RK_U32 filter_level : 6; + RK_U32 filter_sharpness : 3; + RK_U32 golden_penalty : 8; + } sw73; + + struct { + RK_U32 nal_size_write : 1; + RK_U32 : 1; + RK_U32 input_rot : 2; + RK_U32 input_format : 4; + RK_U32 : 8; + RK_U32 num_slices_ready : 8; + RK_U32 mad_threshold : 6; + RK_U32 : 2; + } sw74; + + struct { + RK_U32 inter_favor : 16; + RK_U32 ip_intra_16_favor : 16; + } sw75; + + struct { + RK_U32 base_ref_lum2 : 32; + } sw76; + + struct { + RK_U32 base_stream : 32; + } sw77; + + struct { + RK_U32 base_control : 32; + } sw78; + + struct { + RK_U32 base_next_lum : 32; + } sw79; + + struct { + RK_U32 base_mv_write : 32; + } sw80; + + struct { + RK_U32 base_cabac_ctx : 32; + } sw81; + + struct { + RK_U32 roi1_right : 8; + RK_U32 roi1_left : 8; + RK_U32 roi1_bottom : 8; + RK_U32 roi1_top : 8; + } sw82; + + struct { + RK_U32 roi2_right : 8; + RK_U32 roi2_left : 8; + RK_U32 roi2_bottom : 8; + RK_U32 roi2_top : 8; + } sw83; + + RK_U32 sw84_93[10]; + + struct { + RK_U32 stab_gmvx : 6; + RK_U32 stab_mode : 2; + RK_U32 stab_minimum : 24; + } sw94; + + struct { + RK_U32 rgb_coeff_a : 16; + RK_U32 rgb_coeff_b : 16; + } sw95; + + struct { + RK_U32 rgb_coeff_c : 16; + RK_U32 rgb_coeff_e : 16; + } sw96; + + struct { + RK_U32 rgb_coeff_f : 16; + RK_U32 : 16; + } sw97; + + struct { + RK_U32 r_mask_msb : 5; + RK_U32 : 3; + RK_U32 g_mask_msb : 5; + RK_U32 : 3; + RK_U32 b_mask_msb : 5; + RK_U32 : 11; + } sw98; + + struct { + RK_U32 split_mv : 1; + RK_U32 dmv_penalty_4p : 10; + RK_U32 dmv_penalty_qp : 10; + RK_U32 dmv_penalty_1p : 10; + RK_U32 : 1; + } sw99; + + struct { + RK_U32 y1_quant_dc : 14; + RK_U32 y1_zbin_dc : 9; + RK_U32 y1_round_dc : 8; + RK_U32 : 1; + } sw100; + + RK_U32 sw101; + + struct { + RK_U32 mvc_inter_view_flag : 1; + RK_U32 mvc_temporal_id : 3; + RK_U32 mvc_priority_id : 3; + RK_U32 mvc_anchor_pic_flag : 1; + RK_U32 mvc_view_id : 3; + RK_U32 split_penalty_4x4 : 9; + RK_U32 zero_mv_favor : 4; + RK_U32 : 8; + } sw102; + + struct { + RK_U32 enable : 1; + RK_U32 : 3; + RK_U32 encoding_mode : 2; + RK_U32 picture_type : 2; + RK_U32 width : 9; + RK_U32 : 3; + RK_U32 height : 9; + RK_U32 : 3; + } sw103; + + struct { + RK_U32 mad_count : 16; + RK_U32 mb_count : 16; + } sw104; + + struct { + RK_U32 val : 32; + } sw105; + + struct { + RK_U32 base_ref_chr2 : 32; + } sw106; + + struct { + RK_U32 split_penalty_8x4 : 10; + RK_U32 split_penalty_8x8 : 10; + RK_U32 split_penalty_16x8 : 10; + RK_U32 : 2; + } sw107; + + struct { + RK_U32 base_prob_count : 32; + } sw108; + + struct { + RK_U32 val : 16; + RK_U32 int_slice_ready : 1; + RK_U32 : 3; + RK_U32 rec_write_disable : 1; + RK_U32 : 3; + RK_U32 mv_write : 1; + RK_U32 : 7; + } sw109; + + RK_U32 sw110_119[10]; + + struct { + RK_U32 penalty_0 : 8; + RK_U32 penalty_1 : 8; + RK_U32 penalty_2 : 8; + RK_U32 penalty_3 : 8; + } sw120_183[64]; + +} Vp8eVepu2Reg_t; + +#endif /* HAL_VP8E_VEPU2_REG_H */ diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_v2.c b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_v2.c new file mode 100644 index 000000000..5712356fb --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_v2.c @@ -0,0 +1,552 @@ +/* + * Copyright 2017 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "hal_vp8e_vepu2_v2" + +#include + +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_enc_hal.h" +#include "hal_vp8e_base.h" +#include "hal_vp8e_vepu2_v2.h" +#include "hal_vp8e_vepu2_reg.h" + +#include "mpp_rc.h" +#include "vp8e_syntax.h" +#include "hal_vp8e_debug.h" + +#define SWREG_AMOUNT_VEPU2 (184) +#define HW_STATUS_MASK 0x250 +#define HW_STATUS_BUFFER_FULL 0x20 +#define HW_STATUS_FRAME_READY 0x02 + +static MPP_RET vp8e_vpu_frame_start(void *hal) +{ + RK_S32 i; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu2Reg_t *regs = (Vp8eVepu2Reg_t *)ctx->regs; + + memset(regs, 0, sizeof(Vp8eVepu2Reg_t)); + + regs->sw109.val = (hw_cfg->irq_disable != 0) ? (regs->sw109.val | 0x0100) : + (regs->sw109.val & 0xfeff); + + //((0 & (255)) << 24) | ((0 & (255)) << 16) | ((16 & (63)) << 8) | ((0 & (1)) << 2) | ((0 & (1)) << 1); + regs->sw54.val = 0x1000; + + if (hw_cfg->input_format < INPUT_RGB565) { + regs->sw105.val = 0xfc000000; + } else if (hw_cfg->input_format < INPUT_RGB888) { + regs->sw105.val = 0xfc000000; + } else { + regs->sw105.val = 0x3c000000; + } + + regs->sw77.base_stream = hw_cfg->output_strm_base; + mpp_dev_set_reg_offset(ctx->dev, 77, hw_cfg->output_strm_offset); + regs->sw78.base_control = hw_cfg->size_tbl_base; + regs->sw74.nal_size_write = hw_cfg->size_tbl_base != 0; + regs->sw109.mv_write = hw_cfg->mv_output_base != 0; + + regs->sw56.base_ref_lum = hw_cfg->internal_img_lum_base_r[0]; + regs->sw57.base_ref_chr = hw_cfg->internal_img_chr_base_r[0]; + regs->sw63.base_rec_lum = hw_cfg->internal_img_lum_base_w; + regs->sw64.base_rec_chr = hw_cfg->internal_img_chr_base_w; + + regs->sw48.base_in_lum = hw_cfg->input_lum_base; + if (hw_cfg->input_lum_offset) + mpp_dev_set_reg_offset(ctx->dev, 48, hw_cfg->input_lum_offset); + + regs->sw49.base_in_cb = hw_cfg->input_cb_base; + if (hw_cfg->input_cb_offset) + mpp_dev_set_reg_offset(ctx->dev, 49, hw_cfg->input_cb_offset); + + regs->sw50.base_in_cr = hw_cfg->input_cr_base; + if (hw_cfg->input_cr_offset) + mpp_dev_set_reg_offset(ctx->dev, 50, hw_cfg->input_cr_offset); + + // regs->sw109.int_timeout = 1 & 1; + regs->sw109.val |= 0x0400; + regs->sw109.int_slice_ready = hw_cfg->int_slice_ready; + regs->sw109.rec_write_disable = hw_cfg->rec_write_disable; + regs->sw103.width = hw_cfg->mbs_in_row; + regs->sw103.height = hw_cfg->mbs_in_col; + regs->sw103.picture_type = hw_cfg->frame_coding_type; + regs->sw103.encoding_mode = hw_cfg->coding_type; + + regs->sw61.chr_offset = hw_cfg->input_chroma_base_offset; + regs->sw61.lum_offset = hw_cfg->input_luma_base_offset; + regs->sw61.row_length = hw_cfg->pixels_on_row; + regs->sw60.x_fill = hw_cfg->x_fill; + regs->sw60.y_fill = hw_cfg->y_fill; + regs->sw74.input_format = hw_cfg->input_format; + regs->sw74.input_rot = hw_cfg->input_rotation; + + regs->sw59.cabac_enable = hw_cfg->enable_cabac; + regs->sw75.ip_intra_16_favor = hw_cfg->intra_16_favor; + regs->sw75.inter_favor = hw_cfg->inter_favor; + regs->sw59.disable_qp_mv = hw_cfg->disable_qp_mv; + regs->sw59.deblocking = hw_cfg->filter_disable; + regs->sw60.skip_penalty = hw_cfg->skip_penalty; + regs->sw99.split_mv = hw_cfg->split_mv_mode; + regs->sw107.split_penalty_16x8 = hw_cfg->split_penalty[0]; + regs->sw107.split_penalty_8x8 = hw_cfg->split_penalty[1]; + regs->sw107.split_penalty_8x4 = hw_cfg->split_penalty[2]; + regs->sw102.split_penalty_4x4 = hw_cfg->split_penalty[3]; + regs->sw102.zero_mv_favor = hw_cfg->zero_mv_favor; + + regs->sw51.strm_hdr_rem1 = hw_cfg->strm_start_msb; + regs->sw52.strm_hdr_rem2 = hw_cfg->strm_start_lsb; + regs->sw53.strm_buf_limit = hw_cfg->output_strm_size; + + regs->sw76.base_ref_lum2 = hw_cfg->internal_img_lum_base_r[1]; + regs->sw106.base_ref_chr2 = hw_cfg->internal_img_chr_base_r[1]; + + regs->sw100.y1_quant_dc = hw_cfg->y1_quant_dc[0]; + regs->sw65.y1_quant_ac = hw_cfg->y1_quant_ac[0]; + regs->sw66.y2_quant_dc = hw_cfg->y2_quant_dc[0]; + regs->sw67.y2_quant_ac = hw_cfg->y2_quant_ac[0]; + regs->sw68.ch_quant_dc = hw_cfg->ch_quant_dc[0]; + regs->sw69.ch_quant_ac = hw_cfg->ch_quant_ac[0]; + + regs->sw100.y1_zbin_dc = hw_cfg->y1_zbin_dc[0]; + regs->sw65.y1_zbin_ac = hw_cfg->y1_zbin_ac[0]; + regs->sw66.y2_zbin_dc = hw_cfg->y2_zbin_dc[0]; + regs->sw67.y2_zbin_ac = hw_cfg->y2_zbin_ac[0]; + regs->sw68.ch_zbin_dc = hw_cfg->ch_zbin_dc[0]; + regs->sw69.ch_zbin_ac = hw_cfg->ch_zbin_ac[0]; + + regs->sw100.y1_round_dc = hw_cfg->y1_round_dc[0]; + regs->sw65.y1_round_ac = hw_cfg->y1_round_ac[0]; + regs->sw66.y2_round_dc = hw_cfg->y2_round_dc[0]; + regs->sw67.y2_round_ac = hw_cfg->y2_round_ac[0]; + regs->sw68.ch_round_dc = hw_cfg->ch_round_dc[0]; + regs->sw69.ch_round_ac = hw_cfg->ch_round_ac[0]; + + regs->sw70.y1_dequant_dc = hw_cfg->y1_dequant_dc[0]; + regs->sw70.y1_dequant_ac = hw_cfg->y1_dequant_ac[0]; + regs->sw70.y2_dequant_dc = hw_cfg->y2_dequant_dc[0]; + regs->sw71.y2_dequant_ac = hw_cfg->y2_dequant_ac[0]; + regs->sw71.ch_dequant_dc = hw_cfg->ch_dequant_dc[0]; + regs->sw71.ch_dequant_ac = hw_cfg->ch_dequant_ac[0]; + + regs->sw70.mv_ref_idx = hw_cfg->mv_ref_idx[0]; + regs->sw71.mv_ref_idx2 = hw_cfg->mv_ref_idx[1]; + regs->sw71.ref2_enable = hw_cfg->ref2_enable; + + regs->sw72.bool_enc_value = hw_cfg->bool_enc_value; + regs->sw73.bool_enc_value_bits = hw_cfg->bool_enc_value_bits; + regs->sw73.bool_enc_range = hw_cfg->bool_enc_range; + + regs->sw73.filter_level = hw_cfg->filter_level[0]; + regs->sw73.golden_penalty = hw_cfg->golden_penalty; + regs->sw73.filter_sharpness = hw_cfg->filter_sharpness; + regs->sw73.dct_partition_count = hw_cfg->dct_partitions; + + regs->sw60.start_offset = hw_cfg->first_free_bit; + + regs->sw79.base_next_lum = hw_cfg->vs_next_luma_base; + regs->sw94.stab_mode = hw_cfg->vs_mode; + + regs->sw99.dmv_penalty_4p = hw_cfg->diff_mv_penalty[0]; + regs->sw99.dmv_penalty_1p = hw_cfg->diff_mv_penalty[1]; + regs->sw99.dmv_penalty_qp = hw_cfg->diff_mv_penalty[2]; + + regs->sw81.base_cabac_ctx = hw_cfg->cabac_tbl_base; + regs->sw80.base_mv_write = hw_cfg->mv_output_base; + + regs->sw95.rgb_coeff_a = hw_cfg->rgb_coeff_a; + regs->sw95.rgb_coeff_b = hw_cfg->rgb_coeff_b; + regs->sw96.rgb_coeff_c = hw_cfg->rgb_coeff_c; + regs->sw96.rgb_coeff_e = hw_cfg->rgb_coeff_e; + regs->sw97.rgb_coeff_f = hw_cfg->rgb_coeff_f; + + regs->sw98.r_mask_msb = hw_cfg->r_mask_msb; + regs->sw98.g_mask_msb = hw_cfg->g_mask_msb; + regs->sw98.b_mask_msb = hw_cfg->b_mask_msb; + + regs->sw47.cir_start = hw_cfg->cir_start; + regs->sw47.cir_interval = hw_cfg->cir_interval; + + regs->sw46.intra_area_left = hw_cfg->intra_area_left; + regs->sw46.intra_area_right = hw_cfg->intra_area_right; + regs->sw46.intra_area_top = hw_cfg->intra_area_top; + regs->sw46.intra_area_bottom = hw_cfg->intra_area_bottom ; + regs->sw82.roi1_left = hw_cfg->roi1_left; + regs->sw82.roi1_right = hw_cfg->roi1_right; + regs->sw82.roi1_top = hw_cfg->roi1_top; + regs->sw82.roi1_bottom = hw_cfg->roi1_bottom; + + regs->sw83.roi2_left = hw_cfg->roi2_left; + regs->sw83.roi2_right = hw_cfg->roi2_right; + regs->sw83.roi2_top = hw_cfg->roi2_top; + regs->sw83.roi2_bottom = hw_cfg->roi2_bottom; + + regs->sw44.base_partition1 = hw_cfg->partition_Base[0]; + mpp_dev_set_reg_offset(ctx->dev, 44, hw_cfg->partition_offset[0]); + regs->sw45.base_partition2 = hw_cfg->partition_Base[1]; + mpp_dev_set_reg_offset(ctx->dev, 45, hw_cfg->partition_offset[1]); + regs->sw108.base_prob_count = hw_cfg->prob_count_base; + + regs->sw33.mode0_penalty = hw_cfg->intra_mode_penalty[0]; + regs->sw33.mode1_penalty = hw_cfg->intra_mode_penalty[1]; + regs->sw34.mode2_penalty = hw_cfg->intra_mode_penalty[2]; + regs->sw34.mode3_penalty = hw_cfg->intra_mode_penalty[3]; + + for (i = 0 ; i < 5; i++) { + regs->sw28_32[i].b_mode_0_penalty = hw_cfg->intra_b_mode_penalty[2 * i]; + regs->sw28_32[i].b_mode_1_penalty = hw_cfg->intra_b_mode_penalty[2 * i + 1]; + } + + regs->sw71.segment_enable = hw_cfg->segment_enable; + regs->sw71.segment_map_update = hw_cfg->segment_map_update; + regs->sw27.base_segment_map = hw_cfg->segment_map_base; + + for (i = 0; i < 3; i++) { + regs->sw0_26[0 + i * 9].num_0.y1_quant_dc = hw_cfg->y1_quant_dc[1 + i]; + regs->sw0_26[0 + i * 9].num_0.y2_quant_dc = hw_cfg->y2_quant_dc[1 + i]; + + regs->sw0_26[1 + i * 9].num_1.ch_quant_dc = hw_cfg->ch_quant_dc[1 + i]; + regs->sw0_26[1 + i * 9].num_1.y1_quant_ac = hw_cfg->y1_quant_ac[1 + i]; + + regs->sw0_26[2 + i * 9].num_2.y2_quant_ac = hw_cfg->y2_quant_ac[1 + i]; + regs->sw0_26[2 + i * 9].num_2.ch_quant_ac = hw_cfg->ch_quant_ac[1 + i]; + + regs->sw0_26[3 + i * 9].num_3.y1_zbin_dc = hw_cfg->y1_zbin_dc[1 + i]; + regs->sw0_26[3 + i * 9].num_3.y2_zbin_dc = hw_cfg->y2_zbin_dc[1 + i]; + regs->sw0_26[3 + i * 9].num_3.ch_zbin_dc = hw_cfg->ch_zbin_dc[1 + i]; + + regs->sw0_26[4 + i * 9].num_4.y1_zbin_ac = hw_cfg->y1_zbin_ac[1 + i]; + regs->sw0_26[4 + i * 9].num_4.y2_zbin_ac = hw_cfg->y2_zbin_ac[1 + i]; + regs->sw0_26[4 + i * 9].num_4.ch_zbin_ac = hw_cfg->ch_zbin_ac[1 + i]; + + regs->sw0_26[5 + i * 9].num_5.y1_round_dc = hw_cfg->y1_round_dc[1 + i]; + regs->sw0_26[5 + i * 9].num_5.y2_round_dc = hw_cfg->y2_round_dc[1 + i]; + regs->sw0_26[5 + i * 9].num_5.ch_round_dc = hw_cfg->ch_round_dc[1 + i]; + + regs->sw0_26[6 + i * 9].num_6.y1_round_ac = hw_cfg->y1_round_ac[1 + i]; + regs->sw0_26[6 + i * 9].num_6.y2_round_ac = hw_cfg->y2_round_ac[1 + i]; + regs->sw0_26[6 + i * 9].num_6.ch_round_ac = hw_cfg->ch_round_ac[1 + i]; + + regs->sw0_26[7 + i * 9].num_7.y1_dequant_dc = hw_cfg->y1_dequant_dc[1 + i]; + regs->sw0_26[7 + i * 9].num_7.y2_dequant_dc = hw_cfg->y2_dequant_dc[1 + i]; + regs->sw0_26[7 + i * 9].num_7.ch_dequant_dc = hw_cfg->ch_dequant_dc[1 + i]; + regs->sw0_26[7 + i * 9].num_7.filter_level = hw_cfg->filter_level[1 + i]; + + regs->sw0_26[8 + i * 9].num_8.y1_dequant_ac = hw_cfg->y1_dequant_ac[1 + i]; + regs->sw0_26[8 + i * 9].num_8.y2_dequant_ac = hw_cfg->y2_dequant_ac[1 + i]; + regs->sw0_26[8 + i * 9].num_8.ch_dequant_ac = hw_cfg->ch_dequant_ac[1 + i]; + } + + regs->sw40.lf_ref_delta0 = hw_cfg->lf_ref_delta[0] & mask_7b; + regs->sw42.lf_ref_delta1 = hw_cfg->lf_ref_delta[1] & mask_7b; + regs->sw42.lf_ref_delta2 = hw_cfg->lf_ref_delta[2] & mask_7b; + regs->sw42.lf_ref_delta3 = hw_cfg->lf_ref_delta[3] & mask_7b; + regs->sw40.lf_mode_delta0 = hw_cfg->lf_mode_delta[0] & mask_7b; + regs->sw43.lf_mode_delta1 = hw_cfg->lf_mode_delta[1] & mask_7b; + regs->sw43.lf_mode_delta2 = hw_cfg->lf_mode_delta[2] & mask_7b; + regs->sw43.lf_mode_delta3 = hw_cfg->lf_mode_delta[3] & mask_7b; + + RK_S32 j = 0; + for (j = 0; j < 32; j++) { + regs->sw120_183[j].penalty_0 = hw_cfg->dmv_penalty[j * 4 + 3]; + regs->sw120_183[j].penalty_1 = hw_cfg->dmv_penalty[j * 4 + 2]; + regs->sw120_183[j].penalty_2 = hw_cfg->dmv_penalty[j * 4 + 1]; + regs->sw120_183[j].penalty_3 = hw_cfg->dmv_penalty[j * 4]; + + regs->sw120_183[j + 32].penalty_0 = hw_cfg->dmv_qpel_penalty[j * 4 + 3]; + regs->sw120_183[j + 32].penalty_1 = hw_cfg->dmv_qpel_penalty[j * 4 + 2]; + regs->sw120_183[j + 32].penalty_2 = hw_cfg->dmv_qpel_penalty[j * 4 + 1]; + regs->sw120_183[j + 32].penalty_3 = hw_cfg->dmv_qpel_penalty[j * 4]; + } + + regs->sw103.enable = 0x1; + + return MPP_OK; +} + +static MPP_RET hal_vp8e_vepu2_init_v2(void *hal, MppEncHalCfg *cfg) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + + ctx->cfg = cfg->cfg; + + /* update output to MppEnc */ + cfg->type = VPU_CLIENT_VEPU2; + ret = mpp_dev_init(&cfg->dev, cfg->type); + if (ret) { + mpp_err_f("mpp_dev_init failed. ret: %d\n", ret); + return ret; + } + ctx->dev = cfg->dev; + + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_dev_init success.\n"); + + ctx->buffers = mpp_calloc(Vp8eVpuBuf, 1); + if (ctx->buffers == NULL) { + mpp_err("failed to malloc buffers"); + return MPP_ERR_NOMEM; + } + //memset(ctx->buffers, 0, sizeof(Vp8eVpuBuf)); + + ctx->buffer_ready = 0; + ctx->frame_cnt = 0; + ctx->frame_type = VP8E_FRM_KEY; + ctx->prev_frame_lost = 0; + ctx->frame_size = 0; + ctx->ivf_hdr_rdy = 0; + ctx->reg_size = SWREG_AMOUNT_VEPU2; + + hw_cfg->irq_disable = 0; + + hw_cfg->rounding_ctrl = 0; + hw_cfg->cp_distance_mbs = 0; + hw_cfg->recon_img_id = 0; + hw_cfg->input_lum_base = 0; + hw_cfg->input_cb_base = 0; + hw_cfg->input_cr_base = 0; + + hal_vp8e_init_qp_table(hal); + + return ret; +} + +static MPP_RET hal_vp8e_vepu2_deinit_v2(void *hal) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + hal_vp8e_buf_free(ctx); + + if (ctx->dev) { + mpp_dev_deinit(ctx->dev); + ctx->dev = NULL; + } + + MPP_FREE(ctx->regs); + MPP_FREE(ctx->buffers); + + vp8e_hal_dbg(VP8E_DBG_HAL_FUNCTION, "mpp_dev_deinit success.\n"); + + return ret; +} + +static MPP_RET hal_vp8e_vepu2_gen_regs_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + ctx->rc->qp_hdr = MPP_CLIP3(0, 127, task->rc_task->info.quality_target); + + if (!ctx->buffer_ready) { + ret = hal_vp8e_setup(hal); + if (ret) { + mpp_err("failed to init hal vp8e\n"); + return ret; + } else { + ctx->buffer_ready = 1; + } + } + + memset(ctx->stream_size, 0, sizeof(ctx->stream_size)); + + hal_vp8e_enc_strm_code(ctx, task); + vp8e_vpu_frame_start(ctx); + + return MPP_OK; +} + +static MPP_RET hal_vp8e_vepu2_start_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + if (VP8E_DBG_HAL_DUMP_REG & hal_vp8e_debug) { + RK_U32 i = 0; + RK_U32 *tmp = (RK_U32 *)ctx->regs; + + for (; i < ctx->reg_size; i++) + mpp_log("reg[%d]:%x\n", i, tmp[i]); + } + + do { + MppDevRegWrCfg wr_cfg; + MppDevRegRdCfg rd_cfg; + RK_U32 reg_size = ctx->reg_size * sizeof(RK_U32); + + wr_cfg.reg = ctx->regs; + wr_cfg.size = reg_size; + wr_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_WR, &wr_cfg); + if (ret) { + mpp_err_f("set register write failed %d\n", ret); + break; + } + + rd_cfg.reg = ctx->regs; + rd_cfg.size = reg_size; + rd_cfg.offset = 0; + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_REG_RD, &rd_cfg); + if (ret) { + mpp_err_f("set register read failed %d\n", ret); + break; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_SEND, NULL); + if (ret) { + mpp_err_f("send cmd failed %d\n", ret); + break; + } + } while (0); + + (void)task; + return ret; +} + +static void vp8e_update_hw_cfg(void *hal) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eHwCfg *hw_cfg = &ctx->hw_cfg; + Vp8eVepu2Reg_t *regs = (Vp8eVepu2Reg_t *) ctx->regs; + + hw_cfg->output_strm_base = regs->sw53.strm_buf_limit / 8; + hw_cfg->qp_sum = regs->sw58.qp_sum * 2; + hw_cfg->mad_count = regs->sw104.mad_count; + hw_cfg->rlc_count = regs->sw62.rlc_sum * 3; + + hw_cfg->intra_16_favor = -1; + hw_cfg->inter_favor = -1; + hw_cfg->diff_mv_penalty[0] = -1; + hw_cfg->diff_mv_penalty[1] = -1; + hw_cfg->diff_mv_penalty[2] = -1; + hw_cfg->skip_penalty = -1; + hw_cfg->golden_penalty = -1; + hw_cfg->split_penalty[0] = 0; + hw_cfg->split_penalty[1] = 0; + hw_cfg->split_penalty[3] = 0; +} + +static MPP_RET hal_vp8e_vepu2_wait_v2(void *hal, HalEncTask *task) +{ + MPP_RET ret = MPP_OK; + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + + Vp8eFeedback *fb = &ctx->feedback; + Vp8eVepu2Reg_t *regs = (Vp8eVepu2Reg_t *) ctx->regs; + RK_S32 sw_length = task->length; + + if (NULL == ctx->dev) { + mpp_err_f("invalid dev ctx\n"); + return MPP_NOK; + } + + ret = mpp_dev_ioctl(ctx->dev, MPP_DEV_CMD_POLL, NULL); + if (ret) + mpp_err_f("poll cmd failed %d\n", ret); + + fb->hw_status = regs->sw109.val & HW_STATUS_MASK; + if (regs->sw109.val & HW_STATUS_FRAME_READY) + vp8e_update_hw_cfg(ctx); + else if (regs->sw109.val & HW_STATUS_BUFFER_FULL) + ctx->bitbuf[1].size = 0; + + hal_vp8e_update_buffers(ctx, task); + + ctx->last_frm_intra = task->rc_task->frm.is_intra; + ctx->frame_cnt++; + + task->rc_task->info.bit_real = ctx->frame_size << 3; + task->hw_length = task->length - sw_length; + return ret; +} + +static MPP_RET hal_vp8e_vepu2_get_task_v2(void *hal, HalEncTask *task) +{ + HalVp8eCtx *ctx = (HalVp8eCtx *)hal; + Vp8eSyntax* syntax = (Vp8eSyntax*)task->syntax.data; + //ctx->cfg = syntax->cfg; + RK_U32 i; + + for (i = 0; i < task->syntax.number; i++) { + if (syntax[i].type == VP8E_SYN_CFG) { + ctx->cfg = (MppEncCfgSet*)syntax[i].data; + } + if (syntax[i].type == VP8E_SYN_RC) { + ctx->rc = (Vp8eRc*) syntax[i].data; + } + } + + ctx->frame_type = (task->rc_task->frm.is_intra != 0) ? VP8E_FRM_KEY : VP8E_FRM_P; + + if (!ctx->cfg->vp8.disable_ivf && !ctx->ivf_hdr_rdy) { + RK_U8 *p_out = mpp_buffer_get_ptr(task->output); + + write_ivf_header(hal, p_out); + task->length += IVF_HDR_BYTES; + + ctx->ivf_hdr_rdy = 1; + } + + return MPP_OK; +} + +static MPP_RET hal_vp8e_vepu2_ret_task_v2(void *hal, HalEncTask *task) +{ + (void)hal; + (void)task; + return MPP_OK; +} + +const MppEncHalApi hal_vp8e_vepu2 = { + .name = "hal_vp8e_vepu2", + .coding = MPP_VIDEO_CodingVP8, + .ctx_size = sizeof(HalVp8eCtx), + .flag = 0, + .init = hal_vp8e_vepu2_init_v2, + .deinit = hal_vp8e_vepu2_deinit_v2, + .prepare = NULL, + .get_task = hal_vp8e_vepu2_get_task_v2, + .gen_regs = hal_vp8e_vepu2_gen_regs_v2, + .start = hal_vp8e_vepu2_start_v2, + .wait = hal_vp8e_vepu2_wait_v2, + .part_start = NULL, + .part_wait = NULL, + .ret_task = hal_vp8e_vepu2_ret_task_v2, + .client = VPU_CLIENT_VEPU2, + .soc_type = { + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RV1108, + ROCKCHIP_SOC_RV1109, + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_BUTT + }, +}; + +MPP_ENC_HAL_API_REGISTER(hal_vp8e_vepu2) diff --git a/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_v2.h b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_v2.h new file mode 100644 index 000000000..8c64063ed --- /dev/null +++ b/mpp/hal/vpu/vp8e/hal_vp8e_vepu2_v2.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HAL_VP8E_VEPU2_V2_H +#define HAL_VP8E_VEPU2_V2_H + +#include "mpp_enc_hal.h" + +extern const MppEncHalApi hal_vp8e_vepu2; + +#endif /* HAL_VP8E_VEPU2_H */ diff --git a/mpp/hal/worker/libv4l2/CMakeLists.txt b/mpp/hal/worker/libv4l2/CMakeLists.txt deleted file mode 100644 index b66fe4acf..000000000 --- a/mpp/hal/worker/libv4l2/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -# vim: syntax=cmake diff --git a/mpp/hal/worker/libvpu/vpu.c b/mpp/hal/worker/libvpu/vpu.c deleted file mode 100644 index ca9aeac8d..000000000 --- a/mpp/hal/worker/libvpu/vpu.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "vpu" - -#include -#include -#include -#include - -#include "mpp_log.h" - -#include "vpu.h" - -#define VPU_IOC_MAGIC 'l' -#define VPU_IOC_SET_CLIENT_TYPE _IOW(VPU_IOC_MAGIC, 1, unsigned long) -#define VPU_IOC_GET_HW_FUSE_STATUS _IOW(VPU_IOC_MAGIC, 2, unsigned long) -#define VPU_IOC_SET_REG _IOW(VPU_IOC_MAGIC, 3, unsigned long) -#define VPU_IOC_GET_REG _IOW(VPU_IOC_MAGIC, 4, unsigned long) -#define VPU_IOC_PROBE_IOMMU_STATUS _IOR(VPU_IOC_MAGIC, 5, unsigned long) - -typedef struct VPUReq { - RK_U32 *req; - RK_U32 size; -} VPUReq_t; - -static int vpu_service_status = -1; -static int vpu_service_iommu_status = -1; -#define VPU_SERVICE_TEST \ - do { \ - if (vpu_service_status < 0) { \ - vpu_service_status = (access("/dev/vpu_service", F_OK) == 0); \ - } \ - } while (0) - -int VPUClientInit(VPU_CLIENT_TYPE type) -{ - VPU_SERVICE_TEST; - int ret; - int fd; - if (type != VPU_DEC_HEVC) { - fd = open("/dev/vpu_service", O_RDWR); - } else { - fd = open("/dev/hevc_service", O_RDWR); - type = VPU_DEC; - } - if (fd == -1) { - mpp_err_f("failed to open vpu_service\n"); - return -1; - } - ret = ioctl(fd, VPU_IOC_SET_CLIENT_TYPE, (RK_U32)type); - if (ret) { - mpp_err_f("ioctl VPU_IOC_SET_CLIENT_TYPE failed ret %d errno %d\n", ret, errno); - return -2; - } - return fd; -} - -RK_S32 VPUClientRelease(int socket) -{ - VPU_SERVICE_TEST; - int fd = socket; - if (fd > 0) { - close(fd); - } - return VPU_SUCCESS; -} - -RK_S32 VPUClientSendReg(int socket, RK_U32 *regs, RK_U32 nregs) -{ - VPU_SERVICE_TEST; - int fd = socket; - RK_S32 ret; - VPUReq_t req; - nregs *= sizeof(RK_U32); - req.req = regs; - req.size = nregs; - ret = (RK_S32)ioctl(fd, VPU_IOC_SET_REG, &req); - if (ret) - mpp_err_f("ioctl VPU_IOC_SET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno)); - - return ret; -} - -RK_S32 VPUClientWaitResult(int socket, RK_U32 *regs, RK_U32 nregs, VPU_CMD_TYPE *cmd, RK_S32 *len) -{ - VPU_SERVICE_TEST; - int fd = socket; - RK_S32 ret; - VPUReq_t req; - (void)len; - nregs *= sizeof(RK_U32); - req.req = regs; - req.size = nregs; - ret = (RK_S32)ioctl(fd, VPU_IOC_GET_REG, &req); - if (ret) { - mpp_err_f("ioctl VPU_IOC_GET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno)); - *cmd = VPU_SEND_CONFIG_ACK_FAIL; - } else - *cmd = VPU_SEND_CONFIG_ACK_OK; - - return ret; -} - -RK_S32 VPUClientGetHwCfg(int socket, RK_U32 *cfg, RK_U32 cfg_size) -{ - VPU_SERVICE_TEST; - int fd = socket; - RK_S32 ret; - VPUReq_t req; - req.req = cfg; - req.size = cfg_size; - ret = (RK_S32)ioctl(fd, VPU_IOC_GET_HW_FUSE_STATUS, &req); - if (ret) - mpp_err_f("ioctl VPU_IOC_GET_HW_FUSE_STATUS failed ret %d\n", ret); - - return ret; -} - -RK_S32 VPUClientGetIOMMUStatus() -{ - int ret = 0; - if (vpu_service_iommu_status < 0) { - int fd = -1; - fd = open("/dev/vpu_service", O_RDWR); - if (fd >= 0) { - ret = (RK_S32)ioctl(fd, VPU_IOC_PROBE_IOMMU_STATUS, &vpu_service_iommu_status); - if (ret) { - vpu_service_iommu_status = 0; - mpp_err_f("VPUClient: ioctl VPU_IOC_PROBE_IOMMU_STATUS failed ret %d, disable iommu\n", ret); - } - close(fd); - } else { - vpu_service_iommu_status = 0; - } - mpp_log("vpu_service_iommu_status %d", vpu_service_iommu_status); - } - - return vpu_service_iommu_status; -} -RK_U32 VPUCheckSupportWidth() -{ - VPUHwDecConfig_t hwCfg; - int fd = -1; - fd = open("/dev/vpu_service", O_RDWR); - memset(&hwCfg, 0, sizeof(VPUHwDecConfig_t)); - if (fd >= 0) { - if (VPUClientGetHwCfg(fd, (RK_U32*)&hwCfg, sizeof(hwCfg))) { - mpp_err_f("Get HwCfg failed\n"); - close(fd); - return -1; - } - close(fd); - fd = -1; - } - return hwCfg.maxDecPicWidth; -} - diff --git a/mpp/inc/mpi_impl.h b/mpp/inc/mpi_impl.h new file mode 100644 index 000000000..9db7083ec --- /dev/null +++ b/mpp/inc/mpi_impl.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPI_IMPL_H +#define MPI_IMPL_H + +#include "rk_mpi.h" + +#include "mpp_list.h" +#include "mpp.h" + +#define MPI_DBG_FUNCTION (0x00000001) + +#define mpi_dbg(flag, fmt, ...) mpp_dbg(mpi_debug, flag, fmt, ## __VA_ARGS__) +#define mpi_dbg_f(flag, fmt, ...) mpp_dbg_f(mpi_debug, flag, fmt, ## __VA_ARGS__) + +#define mpi_dbg_func(fmt, ...) mpi_dbg_f(MPI_DBG_FUNCTION, fmt, ## __VA_ARGS__) + +typedef struct MpiImpl_t MpiImpl; + +struct MpiImpl_t { + MpiImpl *check; + struct list_head list; + + MppCtxType type; + MppCodingType coding; + + RK_S32 ctx_id; + MppApi *api; + Mpp *ctx; +}; + +extern RK_U32 mpi_debug; + +#endif /* MPI_IMPL_H */ diff --git a/mpp/inc/mpp.h b/mpp/inc/mpp.h new file mode 100644 index 000000000..d31f556f3 --- /dev/null +++ b/mpp/inc/mpp.h @@ -0,0 +1,238 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_H +#define MPP_H + +#include "mpp_queue.h" +#include "mpp_task_impl.h" + +#include "mpp_dec.h" +#include "mpp_enc.h" +#include "mpp_impl.h" +#include "kmpp_obj.h" +#include "kmpp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MPP_DBG_FUNCTION (0x00000001) +#define MPP_DBG_PACKET (0x00000002) +#define MPP_DBG_FRAME (0x00000004) +#define MPP_DBG_BUFFER (0x00000008) + +/* + * mpp notify event flags + * When event happens mpp will signal deocder / encoder with different flag. + * These event will wake up the codec thread or hal thread + */ +#define MPP_INPUT_ENQUEUE (0x00000001) +#define MPP_OUTPUT_DEQUEUE (0x00000002) +#define MPP_INPUT_DEQUEUE (0x00000004) +#define MPP_OUTPUT_ENQUEUE (0x00000008) +#define MPP_RESET (0xFFFFFFFF) + +/* mpp dec event flags */ +#define MPP_DEC_NOTIFY_PACKET_ENQUEUE (MPP_INPUT_ENQUEUE) +#define MPP_DEC_NOTIFY_FRAME_DEQUEUE (MPP_OUTPUT_DEQUEUE) +#define MPP_DEC_NOTIFY_EXT_BUF_GRP_READY (0x00000010) +#define MPP_DEC_NOTIFY_INFO_CHG_DONE (0x00000020) +#define MPP_DEC_NOTIFY_BUFFER_VALID (0x00000040) +#define MPP_DEC_NOTIFY_TASK_ALL_DONE (0x00000080) +#define MPP_DEC_NOTIFY_TASK_HND_VALID (0x00000100) +#define MPP_DEC_NOTIFY_TASK_PREV_DONE (0x00000200) +#define MPP_DEC_NOTIFY_BUFFER_MATCH (0x00000400) +#define MPP_DEC_NOTIFY_SLOT_VALID (0x00004000) +#define MPP_DEC_CONTROL (0x00010000) +#define MPP_DEC_RESET (MPP_RESET) + +/* mpp enc event flags */ +#define MPP_ENC_NOTIFY_FRAME_ENQUEUE (MPP_INPUT_ENQUEUE) +#define MPP_ENC_NOTIFY_PACKET_DEQUEUE (MPP_OUTPUT_DEQUEUE) +#define MPP_ENC_NOTIFY_FRAME_DEQUEUE (MPP_INPUT_DEQUEUE) +#define MPP_ENC_NOTIFY_PACKET_ENQUEUE (MPP_OUTPUT_ENQUEUE) +#define MPP_ENC_CONTROL (0x00000010) +#define MPP_ENC_RESET (MPP_RESET) + +typedef enum MppIOMode_e { + MPP_IO_MODE_DEFAULT = -1, + MPP_IO_MODE_NORMAL = 0, + MPP_IO_MODE_TASK = 1, + MPP_IO_MODE_BUTT, +} MppIoMode; + +/* + * mpp hierarchy + * + * mpp layer create mpp_dec or mpp_dec instance + * mpp_dec create its parser and hal module + * mpp_enc create its control and hal module + * + * +-------+ + * | | + * +-------------+ mpp +-------------+ + * | | | | + * | +-------+ | + * | | + * | | + * | | + * +-----+-----+ +-----+-----+ + * | | | | + * +---+ mpp_dec +--+ +--+ mpp_enc +---+ + * | | | | | | | | + * | +-----------+ | | +-----------+ | + * | | | | + * | | | | + * | | | | + * +-------v------+ +-----v-----+ +-----v-----+ +------v-------+ + * | | | | | | | | + * | dec_parser | | dec_hal | | enc_hal | | enc_control | + * | | | | | | | | + * +--------------+ +-----------+ +-----------+ +--------------+ + */ + +typedef struct Mpp { + /* Public members that were previously public in C++ class */ + MppList *mPktIn; + MppList *mPktOut; + MppList *mFrmIn; + MppList *mFrmOut; + /* counters for debug */ + RK_U32 mPacketPutCount; + RK_U32 mPacketGetCount; + RK_U32 mFramePutCount; + RK_U32 mFrameGetCount; + RK_U32 mTaskPutCount; + RK_U32 mTaskGetCount; + + /* + * packet buffer group + * - packets in I/O, can be ion buffer or normal buffer + * frame buffer group + * - frames in I/O, normally should be a ion buffer group + */ + MppBufferGroup mPacketGroup; + MppBufferGroup mFrameGroup; + RK_U32 mExternalBufferMode; + + /* + * Mpp task queue for advance task mode + */ + /* + * Task data flow: + * | + * user | mpp + * mInputTaskQueue + * mUsrInPort -> | -> mMppInPort + * | | + * | v + * | process + * | | + * | v + * mUsrOutPort <- | <- mMppOutPort + * mOutputTaskQueue + */ + MppPort mUsrInPort; + MppPort mUsrOutPort; + MppPort mMppInPort; + MppPort mMppOutPort; + MppTaskQueue mInputTaskQueue; + MppTaskQueue mOutputTaskQueue; + RK_S32 mInputTaskCount; + RK_S32 mOutputTaskCount; + + MppPollType mInputTimeout; + MppPollType mOutputTimeout; + + MppTask mInputTask; + MppTask mEosTask; + + MppCtx mCtx; + MppDec mDec; + MppEnc mEnc; + + RK_U32 mEncAyncIo; + RK_U32 mEncAyncProc; + MppIoMode mIoMode; + RK_U32 mDisableThread; + + /* dump info for debug */ + MppDump mDump; + + /* kmpp infos */ + Kmpp *mKmpp; + KmppObj mVencInitKcfg; + + MppCtxType mType; + MppCodingType mCoding; + + RK_U32 mInitDone; + + RK_U32 mStatus; + + /* decoder paramter before init */ + MppDecCfg mDecCfg; + RK_U32 mParserFastMode; + RK_U32 mParserNeedSplit; + RK_U32 mParserInternalPts; /* for MPEG2/MPEG4 */ + RK_U32 mImmediateOut; + /* backup extra packet for seek */ + MppPacket mExtraPacket; +} Mpp; + +MPP_RET mpp_ctx_create(Mpp **mpp, MppCtx ctx); +MPP_RET mpp_ctx_destroy(Mpp *mpp); +MPP_RET mpp_ctx_init(Mpp *mpp, MppCtxType type, MppCodingType coding); +void mpp_clear(Mpp *mpp); + +/* Control functions */ +MPP_RET mpp_start(Mpp *mpp); +MPP_RET mpp_stop(Mpp *mpp); +MPP_RET mpp_pause(Mpp *mpp); +MPP_RET mpp_resume(Mpp *mpp); + +/* Data processing functions */ +MPP_RET mpp_put_packet(Mpp *mpp, MppPacket packet); +MPP_RET mpp_get_frame(Mpp *mpp, MppFrame *frame); +MPP_RET mpp_get_frame_noblock(Mpp *mpp, MppFrame *frame); + +MPP_RET mpp_put_frame(Mpp *mpp, MppFrame frame); +MPP_RET mpp_get_packet(Mpp *mpp, MppPacket *packet); + +/* Task queue functions */ +MPP_RET mpp_poll(Mpp *mpp, MppPortType type, MppPollType timeout); +MPP_RET mpp_dequeue(Mpp *mpp, MppPortType type, MppTask *task); +MPP_RET mpp_enqueue(Mpp *mpp, MppPortType type, MppTask task); + +/* Decode function */ +MPP_RET mpp_decode(Mpp *mpp, MppPacket packet, MppFrame *frame); + +/* System functions */ +MPP_RET mpp_reset(Mpp *mpp); +MPP_RET mpp_control(Mpp *mpp, MpiCmd cmd, MppParam param); + +/* Notification functions */ +MPP_RET mpp_notify_flag(Mpp *mpp, RK_U32 flag); +MPP_RET mpp_notify_group(Mpp *mpp, MppBufferGroup group); + +MPP_RET mpp_control_mpp(Mpp *mpp, MpiCmd cmd, MppParam param); +MPP_RET mpp_control_osal(Mpp *mpp, MpiCmd cmd, MppParam param); +MPP_RET mpp_control_codec(Mpp *mpp, MpiCmd cmd, MppParam param); +MPP_RET mpp_control_dec(Mpp *mpp, MpiCmd cmd, MppParam param); +MPP_RET mpp_control_enc(Mpp *mpp, MpiCmd cmd, MppParam param); +MPP_RET mpp_control_isp(Mpp *mpp, MpiCmd cmd, MppParam param); + +/* for special encoder async io mode */ +MPP_RET mpp_put_frame_async(Mpp *mpp, MppFrame frame); +MPP_RET mpp_get_packet_async(Mpp *mpp, MppPacket *packet); + +void mpp_set_io_mode(Mpp *mpp, MppIoMode mode); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_H */ diff --git a/mpp/inc/mpp_cfg.h b/mpp/inc/mpp_cfg.h new file mode 100644 index 000000000..882fb2f5c --- /dev/null +++ b/mpp/inc/mpp_cfg.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_CFG_H +#define MPP_CFG_H + +#include "mpp_internal.h" +#include "kmpp_obj_impl.h" + +/* header size 128 byte */ +typedef struct MppCfgInfoHead_t { + char version[116]; + RK_S32 info_size; + RK_S32 info_count; + RK_S32 node_count; +} MppCfgInfoHead; + +#ifdef __cplusplus +extern "C" { +#endif + +#define MPP_CFG_SET_s8(entry, cfg, val) (kmpp_obj_impl_set_s8)(entry, cfg, val) +#define MPP_CFG_GET_s8(entry, cfg, val) (kmpp_obj_impl_get_s8)(entry, cfg, (RK_S8 *)(val)) +#define MPP_CFG_SET_u8(entry, cfg, val) (kmpp_obj_impl_set_u8)(entry, cfg, val) +#define MPP_CFG_GET_u8(entry, cfg, val) (kmpp_obj_impl_get_u8)(entry, cfg, (RK_U8 *)(val)) +#define MPP_CFG_SET_s16(entry, cfg, val) (kmpp_obj_impl_set_s16)(entry, cfg, val) +#define MPP_CFG_GET_s16(entry, cfg, val) (kmpp_obj_impl_get_s16)(entry, cfg, (RK_S16 *)(val)) +#define MPP_CFG_SET_u16(entry, cfg, val) (kmpp_obj_impl_set_u16)(entry, cfg, val) +#define MPP_CFG_GET_u16(entry, cfg, val) (kmpp_obj_impl_get_u16)(entry, cfg, (RK_U16 *)(val)) +#define MPP_CFG_SET_s32(entry, cfg, val) (kmpp_obj_impl_set_s32)(entry, cfg, val) +#define MPP_CFG_GET_s32(entry, cfg, val) (kmpp_obj_impl_get_s32)(entry, cfg, (RK_S32 *)(val)) +#define MPP_CFG_SET_u32(entry, cfg, val) (kmpp_obj_impl_set_u32)(entry, cfg, val) +#define MPP_CFG_GET_u32(entry, cfg, val) (kmpp_obj_impl_get_u32)(entry, cfg, (RK_U32 *)(val)) +#define MPP_CFG_SET_s64(entry, cfg, val) (kmpp_obj_impl_set_s64)(entry, cfg, val) +#define MPP_CFG_GET_s64(entry, cfg, val) (kmpp_obj_impl_get_s64)(entry, cfg, (RK_S64 *)(val)) +#define MPP_CFG_SET_u64(entry, cfg, val) (kmpp_obj_impl_set_u64)(entry, cfg, val) +#define MPP_CFG_GET_u64(entry, cfg, val) (kmpp_obj_impl_get_u64)(entry, cfg, (RK_U64 *)(val)) +#define MPP_CFG_SET_st(entry, cfg, val) (kmpp_obj_impl_set_st)(entry, cfg, val) +#define MPP_CFG_GET_st(entry, cfg, val) (kmpp_obj_impl_get_st)(entry, cfg, (void *)(val)) +#define MPP_CFG_SET_arr(entry, cfg, val) (kmpp_obj_impl_set_arr)(entry, cfg, val) +#define MPP_CFG_GET_arr(entry, cfg, val) (kmpp_obj_impl_get_arr)(entry, cfg, (void *)(val)) +#define MPP_CFG_SET_ptr(entry, cfg, val) (kmpp_obj_impl_set_ptr)(entry, cfg, val) +#define MPP_CFG_GET_ptr(entry, cfg, val) (kmpp_obj_impl_get_ptr)(entry, cfg, (void **)(val)) + +#define CHECK_CFG_ENTRY(node, name, type) \ + check_cfg_entry(node, name, type, __FUNCTION__) + +MPP_RET check_cfg_entry(KmppEntry *node, const char *name, ElemType type, + const char *func); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_CFG_H */ diff --git a/mpp/inc/mpp_dec_cfg.h b/mpp/inc/mpp_dec_cfg.h new file mode 100644 index 000000000..1f3ee6db5 --- /dev/null +++ b/mpp/inc/mpp_dec_cfg.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_DEC_CFG_H +#define MPP_DEC_CFG_H + +#include "mpp_bit.h" +#include "mpp_frame.h" +#include "rk_vdec_cmd.h" + +typedef enum MppVprocMode_e { + MPP_VPROC_MODE_NONE = 0, + /* + * Deinterlacing interlaced video stream only. + * If video is marked as progressive, it won't be deinterlaced. + */ + MPP_VPROC_MODE_DEINTELACE = (1U << 0), + /* + * Both interlaced and progressive video will be sending to Vproc for Detection. + * - For progressive vide, output directly during detection and adjust later + * according to IEP result. + * - For interlaced video, interlaceing directly and adjust later according to + * IEP result. + */ + MPP_VPROC_MODE_DETECTION = (1U << 1), + MPP_VPROC_MODE_ALL = (0xFFFFFFFFU), +} MppVprocMode; + +typedef enum FastPlayMode_e { + MPP_DISABLE_FAST_PLAY, + MPP_ENABLE_FAST_PLAY, + // first gop fast play when poc include negative value, otherwise enable fast play all time + MPP_ENABLE_FAST_PLAY_ONCE, +} FastPlayMode; + +typedef struct MppDecBaseCfg_t { + MppCtxType type; + MppCodingType coding; + RK_S32 hw_type; + RK_U32 batch_mode; + + MppFrameFormat out_fmt; + RK_U32 fast_out; + RK_U32 fast_parse; + RK_U32 split_parse; + RK_U32 internal_pts; + RK_U32 sort_pts; + RK_U32 disable_error; + RK_U32 enable_vproc; /* MppVprocMode */ + RK_U32 enable_fast_play; + RK_U32 enable_hdr_meta; + RK_U32 enable_thumbnail; + RK_U32 enable_mvc; + RK_U32 disable_dpb_chk; + RK_U32 disable_thread; + RK_U32 codec_mode; + RK_U32 dis_err_clr_mark; +} MppDecBaseCfg; + +typedef struct MppDecCbCfg_t { + /* notify packet process done and can accept new packet */ + MppExtCbFunc pkt_rdy_cb; + MppExtCbCtx pkt_rdy_ctx; + RK_S32 pkt_rdy_cmd; + + /* notify frame ready for output */ + MppExtCbFunc frm_rdy_cb; + MppExtCbCtx frm_rdy_ctx; + RK_S32 frm_rdy_cmd; +} MppDecCbCfg; + +typedef struct MppDecStatusCfg_t { + RK_S32 width; + RK_S32 height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_S32 buf_size; + + RK_U32 hal_support_fast_mode; + RK_U32 hal_task_count; + RK_U32 vproc_task_count; +} MppDecStatusCfg; + +typedef struct MppDecCfgSet_t { + MppDecBaseCfg base; + MppDecStatusCfg status; + MppDecCbCfg cb; +} MppDecCfgSet; + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_dec_cfg_set_default(void *entry, KmppObj obj, const char *caller); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEC_CFG_H */ diff --git a/mpp/inc/mpp_enc_cfg.h b/mpp/inc/mpp_enc_cfg.h new file mode 100644 index 000000000..6dc5c2ec0 --- /dev/null +++ b/mpp/inc/mpp_enc_cfg.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_ENC_CFG_H +#define MPP_ENC_CFG_H + +#include "rk_venc_cfg.h" +#include "rk_venc_cmd.h" +#include "rk_venc_ref.h" +#include "mpp_rc_defs.h" + +#include "kmpp_obj.h" + +/* + * MppEncCfgSet shows the relationship between different configuration + * Due to the huge amount of configurable parameters we need to setup + * only minimum amount of necessary parameters. + * + * For normal user rc and prep config are enough. + */ +#define POS_TO_FLAG(p, pos) ((rk_u8*)(p) + ((rk_u32)(pos) & 0xffff)) +#define POS_TO_ELEM(p, pos) ((rk_u8*)(p) + ((rk_u32)(pos) >> 16)) + +typedef struct MppEncCfgSet_t { + MppEncBaseCfg base; + + // esential config + MppEncPrepCfg prep; + MppEncRcCfg rc; + + // hardware related config + MppEncHwCfg hw; + + // codec detail config + MppEncH264Cfg h264; + MppEncH265Cfg h265; + MppEncJpegCfg jpeg; + MppEncVp8Cfg vp8; + + MppEncSliceSplit split; + MppEncRefCfg ref_cfg; + union { + MppEncROICfg roi; + /* for kmpp venc roi */ + MppEncROICfgLegacy roi_legacy; + }; + /* for kmpp venc osd */ + MppEncOSDData3 osd; + MppEncOSDPltCfg plt_cfg; + MppEncOSDPlt plt_data; + /* for kmpp venc ref */ + MppEncRefParam ref_param; + + // quality fine tuning config + MppEncFineTuneCfg tune; +} MppEncCfgSet; + +#ifdef __cplusplus +extern "C" { +#endif + +rk_u32 *mpp_enc_cfg_prep_change(MppEncCfgSet *cfg); +rk_u32 *mpp_enc_cfg_rc_change(MppEncCfgSet *cfg); +rk_u32 *mpp_enc_cfg_hw_change(MppEncCfgSet *cfg); +rk_u32 *mpp_enc_cfg_tune_change(MppEncCfgSet *cfg); +rk_u32 *mpp_enc_cfg_h264_change(MppEncCfgSet *cfg); +rk_u32 *mpp_enc_cfg_h265_change(MppEncCfgSet *cfg); +rk_u32 *mpp_enc_cfg_jpeg_change(MppEncCfgSet *cfg); +rk_u32 *mpp_enc_cfg_vp8_change(MppEncCfgSet *cfg); + +#define KMPP_OBJ_NAME mpp_enc_cfg +#define KMPP_OBJ_INTF_TYPE MppEncCfg +#include "kmpp_obj_func.h" + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENC_CFG_H */ diff --git a/mpp/inc/mpp_impl.h b/mpp/inc/mpp_impl.h new file mode 100644 index 000000000..e4b6b500c --- /dev/null +++ b/mpp/inc/mpp_impl.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_IMPL_H +#define MPP_IMPL_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef void* MppDump; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_dump_init(MppDump *info); +MPP_RET mpp_dump_deinit(MppDump *info); + +MPP_RET mpp_ops_init(MppDump info, MppCtxType type, MppCodingType coding); + +MPP_RET mpp_ops_dec_put_pkt(MppDump info, MppPacket pkt); +MPP_RET mpp_ops_dec_get_frm(MppDump info, MppFrame frame); +MPP_RET mpp_ops_enc_put_frm(MppDump info, MppFrame frame); +MPP_RET mpp_ops_enc_get_pkt(MppDump info, MppPacket pkt); + +MPP_RET mpp_ops_ctrl(MppDump info, MpiCmd cmd); +MPP_RET mpp_ops_reset(MppDump info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/inc/mpp_info.h b/mpp/inc/mpp_info.h new file mode 100644 index 000000000..a6534941b --- /dev/null +++ b/mpp/inc/mpp_info.h @@ -0,0 +1,31 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_INFO_H +#define MPP_INFO_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void show_mpp_version(void); +const char *get_mpp_version(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_INFO_H */ diff --git a/mpp/inc/mpp_internal.h b/mpp/inc/mpp_internal.h new file mode 100644 index 000000000..325cc2fdd --- /dev/null +++ b/mpp/inc/mpp_internal.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_INTERNAL_H +#define MPP_INTERNAL_H + +#include "rk_type.h" +#include "mpp_err.h" + +/* + * All mpp / kmpp internal interface object list here. + */ +typedef void* MppTrie; +typedef void* MppCfgObj; + +/* MppObjDef - mpp object name size and access table trie definition */ +typedef void* MppObjDef; +/* MppObj - mpp object for string name access and function access */ +typedef void* MppObj; +typedef void* MppIoc; + +/* KmppObjDef - mpp kernel object name size and access table trie definition */ +typedef void* KmppObjDef; +/* KmppObj - mpp kernel object for string name access and function access */ +typedef void* KmppObj; + +/* + * kernel - userspace transaction trie node ctx info (64 bit) definition + * + * +------+--------------------+---------------------------+ + * | 8bit | 24 bit | 32 bit | + * +------+--------------------+---------------------------+ + * + * bit 0~3 - 4-bit entry type (EntryType) + * 0 - invalid entry + * 1 - trie self info node + * 2 - access location table node + * 3 - ioctl cmd node + * + * bit 4~7 - 4-bit entry flag (EntryFlag) for different entry type + */ +typedef enum EntryType_e { + ENTRY_TYPE_NONE = 0x0, /* invalid entry type */ + ENTRY_TYPE_VAL = 0x1, /* 32-bit value */ + ENTRY_TYPE_STR = 0x2, /* string info property */ + ENTRY_TYPE_LOC_TBL = 0x3, /* entry location table */ + ENTRY_TYPE_BUTT, +} EntryType; + +/* + * 4-bit extention flag for different entry property + * EntryValFlag - for ENTRY_TYPE_VAL + * EntryValFlag - for ENTRY_TYPE_STR + * EntryLocTblFlag - for ENTRY_TYPE_LOC_TBL + */ +typedef enum EntryValFlag_e { + /* + * 0 - value is unsigned value + * 1 - value is signed value + */ + VALUE_SIGNED = 0x1, +} EntryValFlag; + +typedef enum EntryValUsage_e { + VALUE_NORMAL = 0x0, + + VALUE_TRIE = 0x10, + /* trie info value */ + VALUE_TRIE_INFO = (VALUE_TRIE + 1), + /* trie offset from the trie root */ + VALUE_TRIE_OFFSET = (VALUE_TRIE + 2), + + /* ioctl cmd */ + VALUE_IOCTL_CMD = 0x20, +} EntryValUsage; + +typedef enum EntryStrFlag_e { + STRING_NORMAL = 0x0, + /* string is trie self info */ + STRING_TRIE = 0x1, +} EntryStrFlag; + +typedef enum EntryLocTblFlag_e { + /* + * bit 4 - element can be accessed by kernel + * bit 5 - element can be accessed by userspace + * bit 6 - element is read-only + */ + LOCTBL_KERNEL = 0x1, + LOCTBL_USERSPACE = 0x2, + LOCTBL_READONLY = 0x4, +} EntryLocTblFlag; + +typedef enum ElemType_e { + /* commaon fix size value */ + ELEM_TYPE_FIX = 0x0, + ELEM_TYPE_s32 = (ELEM_TYPE_FIX + 0), + ELEM_TYPE_u32 = (ELEM_TYPE_FIX + 1), + ELEM_TYPE_s64 = (ELEM_TYPE_FIX + 2), + ELEM_TYPE_u64 = (ELEM_TYPE_FIX + 3), + /* pointer type stored by 64-bit */ + ELEM_TYPE_ptr = (ELEM_TYPE_FIX + 4), + /* value only structure */ + ELEM_TYPE_st = (ELEM_TYPE_FIX + 5), + + /* kernel and userspace share data */ + ELEM_TYPE_SHARE = 0x6, + /* share memory between kernel and userspace */ + ELEM_TYPE_shm = (ELEM_TYPE_SHARE + 0), + + /* kernel access only data */ + ELEM_TYPE_KERNEL = 0x8, + /* kenrel object poineter */ + ELEM_TYPE_kobj = (ELEM_TYPE_KERNEL + 0), + /* kenrel normal data poineter */ + ELEM_TYPE_kptr = (ELEM_TYPE_KERNEL + 1), + /* kernel function poineter */ + ELEM_TYPE_kfp = (ELEM_TYPE_KERNEL + 2), + + /* userspace access only data */ + ELEM_TYPE_USER = 0xc, + /* userspace object poineter */ + ELEM_TYPE_uobj = (ELEM_TYPE_USER + 0), + /* userspace normal data poineter */ + ELEM_TYPE_uptr = (ELEM_TYPE_USER + 1), + /* userspace function poineter */ + ELEM_TYPE_ufp = (ELEM_TYPE_USER + 2), + + /* array type data */ + ELEM_TYPE_arr = 0x10, + ELEM_TYPE_s8 = 0x11, + ELEM_TYPE_u8 = 0x12, + ELEM_TYPE_s16 = 0x13, + ELEM_TYPE_u16 = 0x14, + /* variable size data */ + ELEM_TYPE_var = 0x15, + ELEM_TYPE_BUTT = 0x16, +} ElemType; + +typedef union KmppEntry_u { + rk_u64 val; + union { + EntryType type : 4; + struct { + EntryType prop : 4; + EntryValFlag flag : 4; + EntryValUsage usage : 8; + rk_u32 reserve : 16; + rk_u32 val; + } v; + struct { + EntryType prop : 4; + EntryValFlag flag : 4; + rk_u32 len : 24; + rk_u32 offset; + } str; + struct { + EntryType type : 4; + EntryLocTblFlag flag : 4; + ElemType elem_type : 8; + rk_u16 elem_size; + rk_u16 elem_offset; + rk_u16 flag_offset; /* define by ElemFlagType */ + } tbl; + }; +} KmppEntry; + +#endif /* MPP_INTERNAL_H */ diff --git a/mpp/inc/mpp_sys.h b/mpp/inc/mpp_sys.h new file mode 100644 index 000000000..3da801e41 --- /dev/null +++ b/mpp/inc/mpp_sys.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SYS_H +#define MPP_SYS_H + +#include "mpi_impl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_sys_attach(MpiImpl *ctx); +rk_s32 mpp_sys_detach(MpiImpl *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SYS_H */ diff --git a/mpp/legacy/CMakeLists.txt b/mpp/legacy/CMakeLists.txt index 406105f32..5ff71db64 100644 --- a/mpp/legacy/CMakeLists.txt +++ b/mpp/legacy/CMakeLists.txt @@ -4,9 +4,37 @@ include_directories(.) # ---------------------------------------------------------------------------- # add mpp implement # ---------------------------------------------------------------------------- -add_library(mpp_legacy STATIC +set (MPP_LEGACY_SRC + vpu.c vpu_api.cpp vpu_api_legacy.cpp + vpu_api_mlvec.cpp + vpu_mem_legacy.c + rk_list.cpp + ../mpp_info.c ) -set_target_properties(mpp_legacy PROPERTIES FOLDER "mpp/legacy") -target_link_libraries(mpp_legacy osal) + +set(VPU_VERSION "0") +set(VPU_ABI_VERSION "1") + +# NOTE: link_directories should be before add_library or add_executable +link_directories(${CMAKE_BINARY_DIR}/mpp) + +add_library(${VPU_SHARED} SHARED ${MPP_LEGACY_SRC}) +add_dependencies(${VPU_SHARED} ${MPP_SHARED}) +set_target_properties(${VPU_SHARED} PROPERTIES FOLDER "mpp/legacy") +set_target_properties(${VPU_SHARED} PROPERTIES CLEAN_DIRECT_OUTPUT 1) +set_target_properties(${VPU_SHARED} PROPERTIES C_VISIBILITY_PRESET default) +set_target_properties(${VPU_SHARED} PROPERTIES CXX_VISIBILITY_PRESET default) + +# NOTE: due to legacy libray naming issue we can not support version on Android +if (NOT ANDROID) +set_target_properties(${VPU_SHARED} PROPERTIES VERSION ${MPP_VERSION}) +set_target_properties(${VPU_SHARED} PROPERTIES SOVERSION ${MPP_ABI_VERSION}) +endif() + +# force dynamic link +target_link_libraries(${VPU_SHARED} ${ASAN_LIB} + -Wl,-Bdynamic dl lib${MPP_SHARED}.so) + +install(TARGETS ${VPU_SHARED} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/osal/mpp_list.cpp b/mpp/legacy/rk_list.cpp similarity index 51% rename from osal/mpp_list.cpp rename to mpp/legacy/rk_list.cpp index f779e33a4..3513c13f9 100644 --- a/osal/mpp_list.cpp +++ b/mpp/legacy/rk_list.cpp @@ -1,57 +1,49 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_list" +#define ALOG_TAG "rk_list" -#include -#include -#include #include +#include +#include +#include "rk_list.h" #include "mpp_log.h" -#include "mpp_list.h" +//#define _RK_LIST_DEUBG +#define _RK_LIST_ERROR +#ifdef _RK_LIST_DEUBG #define LIST_DEBUG(fmt, ...) mpp_log(fmt, ## __VA_ARGS__) -#define LIST_ERROR(fmt, ...) mpp_err(fmt, ## __VA_ARGS__) +#else +#define LIST_DEBUG(fmt, ...) /* not debugging: nothing */ +#endif -RK_U32 mpp_list::keys = 0; +#ifdef _RK_LIST_ERROR +#define LIST_ERROR(fmt, ...) mpp_err(fmt, ## __VA_ARGS__) +#else +#define LIST_ERROR(fmt, ...) +#endif -typedef struct mpp_list_node { - mpp_list_node* prev; - mpp_list_node* next; - RK_U32 key; - RK_S32 size; -} mpp_list_node; +typedef struct rk_list_node { + rk_list_node* prev; + rk_list_node* next; + RK_U32 key; + RK_S32 size; +} rk_list_node; -static inline void list_node_init(mpp_list_node *node) +static inline void list_node_init(rk_list_node *node) { node->prev = node->next = node; } -static inline void list_node_init_with_key_and_size(mpp_list_node *node, RK_U32 key, RK_S32 size) +static inline void list_node_init_with_key_and_size(rk_list_node *node, RK_U32 key, RK_S32 size) { list_node_init(node); node->key = key; node->size = size; } -static mpp_list_node* create_list(void *data, RK_S32 size, RK_U32 key) +static rk_list_node* create_list(void *data, RK_S32 size, RK_U32 key) { - mpp_list_node *node = (mpp_list_node*)malloc(sizeof(mpp_list_node) + size); + rk_list_node *node = (rk_list_node*)malloc(sizeof(rk_list_node) + size); if (node) { void *dst = (void*)(node + 1); list_node_init_with_key_and_size(node, key, size); @@ -62,7 +54,7 @@ static mpp_list_node* create_list(void *data, RK_S32 size, RK_U32 key) return node; } -static inline void _mpp_list_add(mpp_list_node * _new, mpp_list_node * prev, mpp_list_node * next) +static inline void _rk_list_add(rk_list_node * _new, rk_list_node * prev, rk_list_node * next) { next->prev = _new; _new->next = next; @@ -70,170 +62,159 @@ static inline void _mpp_list_add(mpp_list_node * _new, mpp_list_node * prev, mpp prev->next = _new; } -static inline void mpp_list_add(mpp_list_node *_new, mpp_list_node *head) +static inline void rk_list_add(rk_list_node *_new, rk_list_node *head) { - _mpp_list_add(_new, head, head->next); + _rk_list_add(_new, head, head->next); } -static inline void mpp_list_add_tail(mpp_list_node *_new, mpp_list_node *head) +static inline void rk_list_add_tail(rk_list_node *_new, rk_list_node *head) { - _mpp_list_add(_new, head->prev, head); + _rk_list_add(_new, head->prev, head); } -RK_S32 mpp_list::add_at_head(void *data, RK_S32 size) +RK_S32 rk_list::add_at_head(void *data, RK_S32 size) { RK_S32 ret = -EINVAL; + pthread_mutex_lock(&mutex); if (head) { - mpp_list_node *node = create_list(data, size, 0); + rk_list_node *node = create_list(data, size, 0); if (node) { - mpp_list_add(node, head); + rk_list_add(node, head); count++; ret = 0; } else { ret = -ENOMEM; } } + pthread_mutex_unlock(&mutex); return ret; } -RK_S32 mpp_list::add_at_tail(void *data, RK_S32 size) +RK_S32 rk_list::add_at_tail(void *data, RK_S32 size) { RK_S32 ret = -EINVAL; + pthread_mutex_lock(&mutex); if (head) { - mpp_list_node *node = create_list(data, size, 0); + rk_list_node *node = create_list(data, size, 0); if (node) { - mpp_list_add_tail(node, head); + rk_list_add_tail(node, head); count++; ret = 0; } else { ret = -ENOMEM; } } + pthread_mutex_unlock(&mutex); return ret; } -static void release_list(mpp_list_node*node, void *data, RK_S32 size) +static void release_list(rk_list_node*node, void *data, RK_S32 size) { void *src = (void*)(node + 1); if (node->size == size) { - if (data) - memcpy(data, src, size); + memcpy(data, src, size); } else { LIST_ERROR("node size check failed when release_list"); size = (size < node->size) ? (size) : (node->size); - if (data) - memcpy(data, src, size); + memcpy(data, src, size); } free(node); } -static inline void _mpp_list_del(mpp_list_node *prev, mpp_list_node *next) +static inline void _rk_list_del(rk_list_node *prev, rk_list_node *next) { next->prev = prev; prev->next = next; } -static inline void mpp_list_del_init(mpp_list_node *node) +static inline void rk_list_del_init(rk_list_node *node) { - _mpp_list_del(node->prev, node->next); + _rk_list_del(node->prev, node->next); list_node_init(node); } -static inline int list_is_last(const mpp_list_node *list, const mpp_list_node *head) -{ - return list->next == head; -} - -static inline void _list_del_node_no_lock(mpp_list_node *node, void *data, RK_S32 size) +static inline void _list_del_node_no_lock(rk_list_node *node, void *data, RK_S32 size) { - mpp_list_del_init(node); + rk_list_del_init(node); release_list(node, data, size); } -RK_S32 mpp_list::del_at_head(void *data, RK_S32 size) +RK_S32 rk_list::del_at_head(void *data, RK_S32 size) { RK_S32 ret = -EINVAL; + pthread_mutex_lock(&mutex); if (head && count) { _list_del_node_no_lock(head->next, data, size); count--; ret = 0; } + pthread_mutex_unlock(&mutex); return ret; } -RK_S32 mpp_list::del_at_tail(void *data, RK_S32 size) +RK_S32 rk_list::del_at_tail(void *data, RK_S32 size) { RK_S32 ret = -EINVAL; + pthread_mutex_lock(&mutex); if (head && count) { _list_del_node_no_lock(head->prev, data, size); count--; ret = 0; } + pthread_mutex_unlock(&mutex); return ret; } -RK_S32 mpp_list::list_is_empty() +RK_S32 rk_list::list_is_empty() { + pthread_mutex_lock(&mutex); RK_S32 ret = (count == 0); + pthread_mutex_unlock(&mutex); return ret; } -RK_S32 mpp_list::list_size() +RK_S32 rk_list::list_size() { + pthread_mutex_lock(&mutex); RK_S32 ret = count; + pthread_mutex_unlock(&mutex); return ret; } -RK_S32 mpp_list::add_by_key(void *data, RK_S32 size, RK_U32 *key) +RK_S32 rk_list::add_by_key(void *data, RK_S32 size, RK_U32 *key) { RK_S32 ret = 0; - if (head) { - RK_U32 list_key = get_key(); - *key = list_key; - mpp_list_node *node = create_list(data, size, list_key); - if (node) { - mpp_list_add_tail(node, head); - count++; - ret = 0; - } else { - ret = -ENOMEM; - } - } + (void)data; + (void)size; + (void)key; return ret; } -RK_S32 mpp_list::del_by_key(void *data, RK_S32 size, RK_U32 key) +RK_S32 rk_list::del_by_key(void *data, RK_S32 size, RK_U32 key) { RK_S32 ret = 0; - if (head && count) { - struct mpp_list_node *tmp = head->next; - ret = -EINVAL; - while (tmp->next != head) { - if (tmp->key == key) { - _list_del_node_no_lock(tmp, data, size); - count--; - break; - } - } - } + (void)data; + (void)size; + (void)key; return ret; } -RK_S32 mpp_list::show_by_key(void *data, RK_U32 key) +RK_S32 rk_list::show_by_key(void *data, RK_U32 key) { - RK_S32 ret = -EINVAL; + RK_S32 ret = 0; (void)data; (void)key; return ret; } -RK_S32 mpp_list::flush() +RK_S32 rk_list::flush() { + pthread_mutex_lock(&mutex); if (head) { while (count) { - mpp_list_node* node = head->next; - mpp_list_del_init(node); + rk_list_node* node = head->next; + rk_list_del_init(node); if (destroy) { destroy((void*)(node + 1)); } @@ -241,51 +222,22 @@ RK_S32 mpp_list::flush() count--; } } + pthread_mutex_unlock(&mutex); return 0; } -void mpp_list::lock() -{ - mMutex.lock(); -} - -void mpp_list::unlock() -{ - mMutex.unlock(); -} - -RK_S32 mpp_list::trylock() -{ - return mMutex.trylock(); -} - -Mutex *mpp_list::mutex() -{ - return &mMutex; -} - -RK_U32 mpp_list::get_key() -{ - return keys++; -} - -void mpp_list::wait() -{ - mCondition.wait(mMutex); -} - -void mpp_list::signal() -{ - mCondition.signal(); -} - -mpp_list::mpp_list(node_destructor func) +rk_list::rk_list(node_destructor func) : destroy(NULL), head(NULL), count(0) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex, &attr); + pthread_mutexattr_destroy(&attr); destroy = func; - head = (mpp_list_node*)malloc(sizeof(mpp_list_node)); + head = (rk_list_node*)malloc(sizeof(rk_list_node)); if (NULL == head) { LIST_ERROR("failed to allocate list header"); } else { @@ -293,12 +245,13 @@ mpp_list::mpp_list(node_destructor func) } } -mpp_list::~mpp_list() +rk_list::~rk_list() { flush(); if (head) free(head); head = NULL; destroy = NULL; + pthread_mutex_destroy(&mutex); } #if BUILD_RK_LIST_TEST @@ -312,21 +265,21 @@ mpp_list::~mpp_list() #define COUNT_ADD 100 #define COUNT_DEL 99 -volatile int err = 0; +static volatile int err = 0; -static int mpp_list_fifo_test(mpp_list *list_0) +static int rk_list_fifo_test(rk_list *list_0) { int count; VPUMemLinear_t m; for (count = 0; count < COUNT_ADD; count++) { err |= VPUMallocLinear(&m, 100); if (err) { - printf("VPUMallocLinear in mpp_list_fifo_test\n"); + printf("VPUMallocLinear in rk_list_fifo_test\n"); break; } err |= list_0->add_at_head(&m, sizeof(m)); if (err) { - printf("add_at_head in mpp_list_fifo_test\n"); + printf("add_at_head in rk_list_fifo_test\n"); break; } } @@ -335,12 +288,12 @@ static int mpp_list_fifo_test(mpp_list *list_0) for (count = 0; count < COUNT_DEL; count++) { err |= list_0->del_at_tail(&m, sizeof(m)); if (err) { - printf("del_at_tail in mpp_list_fifo_test\n"); + printf("del_at_tail in rk_list_fifo_test\n"); break; } err |= VPUFreeLinear(&m); if (err) { - printf("VPUFreeLinear in mpp_list_fifo_test\n"); + printf("VPUFreeLinear in rk_list_fifo_test\n"); break; } } @@ -348,7 +301,7 @@ static int mpp_list_fifo_test(mpp_list *list_0) return err; } -static int mpp_list_filo_test(mpp_list *list_0) +static int rk_list_filo_test(rk_list *list_0) { int count; VPUMemLinear_t m; @@ -356,23 +309,23 @@ static int mpp_list_filo_test(mpp_list *list_0) if (count & 1) { err |= list_0->del_at_head(&m, sizeof(m)); if (err) { - printf("del_at_head in mpp_list_filo_test\n"); + printf("del_at_head in rk_list_filo_test\n"); break; } err |= VPUFreeLinear(&m); if (err) { - printf("VPUFreeLinear in mpp_list_fifo_test\n"); + printf("VPUFreeLinear in rk_list_fifo_test\n"); break; } } else { err |= VPUMallocLinear(&m, 100); if (err) { - printf("VPUMallocLinear in mpp_list_filo_test\n"); + printf("VPUMallocLinear in rk_list_filo_test\n"); break; } err |= list_0->add_at_head(&m, sizeof(m)); if (err) { - printf("add_at_head in mpp_list_fifo_test\n"); + printf("add_at_head in rk_list_fifo_test\n"); break; } } @@ -382,14 +335,14 @@ static int mpp_list_filo_test(mpp_list *list_0) } -void *mpp_list_test_loop_0(void *pdata) +void *rk_list_test_loop_0(void *pdata) { int i; - mpp_list *list_0 = (mpp_list *)pdata; + rk_list *list_0 = (rk_list *)pdata; - printf("mpp_list test 0 loop start\n"); + printf("rk_list test 0 loop start\n"); for (i = 0; i < LOOP_RK_LIST; i++) { - err |= mpp_list_filo_test(list_0); + err |= rk_list_filo_test(list_0); if (err) break; } @@ -401,27 +354,27 @@ void *mpp_list_test_loop_0(void *pdata) return NULL; } -int mpp_list_test_0() +int rk_list_test_0() { int i, err = 0; - printf("mpp_list test 0 FIFO start\n"); + printf("rk_list test 0 FIFO start\n"); - mpp_list *list_0 = new mpp_list((node_destructor)VPUFreeLinear); + rk_list *list_0 = new rk_list((node_destructor)VPUFreeLinear); pthread_t mThread; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_create(&mThread, &attr, mpp_list_test_loop_0, (void*)list_0); + pthread_create(&mThread, &attr, rk_list_test_loop_0, (void*)list_0); pthread_attr_destroy(&attr); for (i = 0; i < LOOP_RK_LIST; i++) { - err |= mpp_list_fifo_test(list_0); + err |= rk_list_fifo_test(list_0); if (err) break; } if (err) { - printf("main : found mpp_list operation err %d\n", err); + printf("main : found rk_list operation err %d\n", err); } else { printf("main : test done and found no err\n"); } @@ -429,7 +382,7 @@ int mpp_list_test_0() void *dummy; pthread_join(mThread, &dummy); - printf("mpp_list test 0 end size %d\n", list_0->list_size()); + printf("rk_list test 0 end size %d\n", list_0->list_size()); delete list_0; return err; } @@ -438,7 +391,7 @@ int mpp_list_test_0() typedef int (*RK_LIST_TEST_FUNC)(void); RK_LIST_TEST_FUNC test_func[TOTAL_RK_LIST_TEST_COUNT] = { - mpp_list_test_0, + rk_list_test_0, }; int main(int argc, char *argv[]) diff --git a/mpp/legacy/rk_list.h b/mpp/legacy/rk_list.h new file mode 100644 index 000000000..d4737c886 --- /dev/null +++ b/mpp/legacy/rk_list.h @@ -0,0 +1,49 @@ +#ifndef RK_LIST_H +#define RK_LIST_H + +#include +#include "rk_type.h" +// desctructor of list node +typedef void *(*node_destructor)(void *); + +struct rk_list_node; +class rk_list +{ +public: + rk_list(node_destructor func); + ~rk_list(); + + // for FIFO or FILO implement + // adding functions support simple structure like C struct or C++ class pointer, + // do not support C++ object + RK_S32 add_at_head(void *data, RK_S32 size); + RK_S32 add_at_tail(void *data, RK_S32 size); + // deleting function will copy the stored data to input pointer with size as size + // if NULL is passed to deleting functions, the node will be delete directly + RK_S32 del_at_head(void *data, RK_S32 size); + RK_S32 del_at_tail(void *data, RK_S32 size); + + // for status check + RK_S32 list_is_empty(); + RK_S32 list_size(); + + // for vector implement - not implemented yet + // adding function will return a key + RK_S32 add_by_key(void *data, RK_S32 size, RK_U32 *key); + RK_S32 del_by_key(void *data, RK_S32 size, RK_U32 key); + RK_S32 show_by_key(void *data, RK_U32 key); + + RK_S32 flush(); + +private: + pthread_mutex_t mutex; + node_destructor destroy; + struct rk_list_node *head; + RK_S32 count; + + rk_list(); + rk_list(const rk_list &); + rk_list &operator=(const rk_list &); +}; + +#endif /* RK_LIST_H */ diff --git a/mpp/legacy/vpu.c b/mpp/legacy/vpu.c new file mode 100644 index 000000000..540eadc98 --- /dev/null +++ b/mpp/legacy/vpu.c @@ -0,0 +1,357 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vpu" + +#include +#include +#include + +#include "vpu.h" +#include "rk_mpi.h" + +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_platform.h" + +#include "mpp_service.h" +#include "vcodec_service.h" + +#define VPU_EXTRA_INFO_SIZE 12 +#define VPU_EXTRA_INFO_MAGIC (0x4C4A46) +#define VPU_MPP_FLAGS_MULTI_MSG (0x00000001) +#define VPU_MPP_FLAGS_LAST_MSG (0x00000002) + +#define MPX_PATCH_NUM 16 + +typedef struct VpuPatchInfo_t { + RK_U32 reg_idx; + RK_U32 offset; +} VpuPatchInfo; + +typedef struct VpuExtraInfo_t { + RK_U32 magic; // Fix magic value 0x4C4A46 + RK_U32 count; // valid patch info count + VpuPatchInfo patchs[MPX_PATCH_NUM]; +} VpuExtraInfo; + +typedef struct VPUReq { + RK_U32 *req; + RK_U32 size; +} VPUReq_t; + +static RK_U32 vpu_debug = 0; + +/* 0 original version, > 1 for others version */ +static RK_S32 ioctl_version = 0; + +static RK_S32 vpu_api_set_client_type(int dev, RK_S32 client_type) +{ + static RK_S32 vpu_api_ioctl_version = -1; + RK_S32 ret; + + if (ioctl_version > 0) { + MppReqV1 mpp_req; + RK_U32 vcodec_type; + RK_U32 client_data; + + vcodec_type = mpp_get_vcodec_type(); + + switch (client_type) { + case VPU_ENC: + if (vcodec_type & HAVE_VDPU1) + client_data = VPU_CLIENT_VEPU1; + else if (vcodec_type & HAVE_VDPU2) + client_data = VPU_CLIENT_VEPU2; + break; + default: + break; + } + + mpp_req.cmd = MPP_CMD_INIT_CLIENT_TYPE; + mpp_req.flag = 0; + mpp_req.size = sizeof(client_data); + mpp_req.offset = 0; + mpp_req.data_ptr = REQ_DATA_PTR(&client_data); + ret = (RK_S32)ioctl(dev, MPP_IOC_CFG_V1, &mpp_req); + } else { + if (vpu_api_ioctl_version < 0) { + ret = ioctl(dev, VPU_IOC_SET_CLIENT_TYPE, client_type); + if (!ret) { + vpu_api_ioctl_version = 0; + } else { + ret = ioctl(dev, VPU_IOC_SET_CLIENT_TYPE_U32, client_type); + if (!ret) + vpu_api_ioctl_version = 1; + } + + if (ret) + mpp_err_f("can not find valid client type ioctl\n"); + + mpp_assert(ret == 0); + } else { + RK_U32 cmd = (vpu_api_ioctl_version == 0) ? + (VPU_IOC_SET_CLIENT_TYPE) : + (VPU_IOC_SET_CLIENT_TYPE_U32); + + ret = ioctl(dev, cmd, client_type); + } + } + + if (ret) + mpp_err_f("set client type failed ret %d errno %d\n", ret, errno); + + return ret; +} + + +int VPUClientInit(VPU_CLIENT_TYPE type) +{ + int ret; + int fd; + const char *path; + MppCtxType ctx_type; + MppCodingType coding = MPP_VIDEO_CodingAutoDetect; + + switch (type) { + case VPU_DEC_HEVC: + coding = MPP_VIDEO_CodingHEVC; + ctx_type = MPP_CTX_DEC; + type = VPU_DEC; + break; + case VPU_DEC_AVSPLUS: + coding = MPP_VIDEO_CodingAVSPLUS; + ctx_type = MPP_CTX_DEC; + type = VPU_DEC; + break; + case VPU_DEC_RKV: + type = VPU_DEC; + ctx_type = MPP_CTX_DEC; + break; + case VPU_DEC: + case VPU_DEC_PP: + case VPU_PP: + ctx_type = MPP_CTX_DEC; + break; + case VPU_ENC: + case VPU_ENC_RKV: + ctx_type = MPP_CTX_ENC; + break; + default: + return -1; + break; + } + + path = mpp_get_vcodec_dev_name(ctx_type, coding); + fd = open(path, O_RDWR | O_CLOEXEC); + + mpp_env_get_u32("vpu_debug", &vpu_debug, 0); + + ioctl_version = mpp_get_ioctl_version(); + + if (fd == -1) { + mpp_err_f("failed to open %s, errno = %d, error msg: %s\n", + path, errno, strerror(errno)); + return -1; + } + + ret = vpu_api_set_client_type(fd, type); + if (ret) { + return -2; + } + + return fd; +} + +RK_S32 VPUClientRelease(int socket) +{ + int fd = socket; + if (fd > 0) { + close(fd); + } + return VPU_SUCCESS; +} + +RK_S32 VPUClientSendReg(int socket, RK_U32 *regs, RK_U32 nregs) +{ + int fd = socket; + RK_S32 ret; + VPUReq_t req; + + if (vpu_debug) { + RK_U32 i; + + for (i = 0; i < nregs; i++) + mpp_log("set reg[%03d]: %08x\n", i, regs[i]); + } + + if (ioctl_version > 0) { + MppReqV1 reqs[3]; + RK_U32 reg_size = nregs; + + VpuExtraInfo *extra_info = (VpuExtraInfo*)(regs + (nregs - VPU_EXTRA_INFO_SIZE)); + + reqs[0].cmd = MPP_CMD_SET_REG_WRITE; + reqs[0].flag = 0; + reqs[0].offset = 0; + reqs[0].size = reg_size * sizeof(RK_U32); + reqs[0].data_ptr = REQ_DATA_PTR((void*)regs); + reqs[0].flag |= VPU_MPP_FLAGS_MULTI_MSG; + + reqs[1].cmd = MPP_CMD_SET_REG_READ; + reqs[1].flag = 0; + reqs[1].offset = 0; + reqs[1].size = reg_size * sizeof(RK_U32); + reqs[1].data_ptr = REQ_DATA_PTR((void*)regs); + + if (extra_info && extra_info->magic == VPU_EXTRA_INFO_MAGIC) { + reg_size = nregs - VPU_EXTRA_INFO_SIZE; + reqs[2].cmd = MPP_CMD_SET_REG_ADDR_OFFSET; + reqs[2].flag = 0; + reqs[2].offset = 0; + reqs[2].size = extra_info->count * sizeof(extra_info->patchs[0]); + reqs[2].data_ptr = REQ_DATA_PTR((void *)&extra_info->patchs[0]); + + reqs[0].size = reg_size * sizeof(RK_U32); + reqs[1].size = reg_size * sizeof(RK_U32); + reqs[1].flag |= VPU_MPP_FLAGS_MULTI_MSG; + reqs[2].flag |= VPU_MPP_FLAGS_LAST_MSG; + ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &reqs); + } else { + MppReqV1 reqs_tmp[2]; + reqs[1].flag |= VPU_MPP_FLAGS_LAST_MSG; + memcpy(reqs_tmp, reqs, sizeof(MppReqV1) * 2); + ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &reqs_tmp); + } + + } else { + nregs *= sizeof(RK_U32); + req.req = regs; + req.size = nregs; + ret = (RK_S32)ioctl(fd, VPU_IOC_SET_REG, &req); + } + + if (ret) + mpp_err_f("ioctl VPU_IOC_SET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno)); + + return ret; +} + +RK_S32 VPUClientSendReg2(RK_S32 socket, RK_S32 offset, RK_S32 size, void *param) +{ + RK_S32 ret = 0; + + if (param == NULL) { + mpp_err_f("input param is NULL"); + return 1; + } + + ret = (RK_S32)ioctl(socket, VPU_IOC_WRITE(offset, size), param); + if (ret) + mpp_err_f("ioctl VPU_IOC_WRITE failed ret %d", ret); + + return ret; +} + +RK_S32 VPUClientWaitResult(int socket, RK_U32 *regs, RK_U32 nregs, VPU_CMD_TYPE *cmd, RK_S32 *len) +{ + int fd = socket; + RK_S32 ret; + VPUReq_t req; + (void)len; + + if (ioctl_version > 0) { + MppReqV1 mpp_req; + RK_U32 reg_size = nregs; + VpuExtraInfo *extra_info = (VpuExtraInfo*)(regs + (nregs - VPU_EXTRA_INFO_SIZE)); + + if (extra_info && extra_info->magic == VPU_EXTRA_INFO_MAGIC) { + reg_size -= 2; + } else { + reg_size -= VPU_EXTRA_INFO_SIZE; + } + + mpp_req.cmd = MPP_CMD_POLL_HW_FINISH; + mpp_req.flag = 0; + mpp_req.offset = 0; + mpp_req.size = reg_size * sizeof(RK_U32); + mpp_req.data_ptr = REQ_DATA_PTR((void*)regs); + ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &mpp_req); + } else { + nregs *= sizeof(RK_U32); + req.req = regs; + req.size = nregs; + + ret = (RK_S32)ioctl(fd, VPU_IOC_GET_REG, &req); + } + + if (ret) { + mpp_err_f("ioctl VPU_IOC_GET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno)); + *cmd = VPU_SEND_CONFIG_ACK_FAIL; + } else + *cmd = VPU_SEND_CONFIG_ACK_OK; + + if (vpu_debug) { + RK_U32 i; + + for (i = 0; i < nregs; i++) { + mpp_log("get reg[%03d]: %08x\n", i, regs[i]); + } + } + + return ret; +} + +RK_S32 VPUClientGetHwCfg(int socket, RK_U32 *cfg, RK_U32 cfg_size) +{ + int fd = socket; + RK_S32 ret; + VPUReq_t req; + req.req = cfg; + req.size = cfg_size; + ret = (RK_S32)ioctl(fd, VPU_IOC_GET_HW_FUSE_STATUS, &req); + if (ret) + mpp_err_f("ioctl VPU_IOC_GET_HW_FUSE_STATUS failed ret %d\n", ret); + + return ret; +} + +RK_U32 VPUCheckSupportWidth() +{ + VPUHwDecConfig_t hwCfg; + int fd = -1; + fd = open("/dev/vpu_service", O_RDWR | O_CLOEXEC); + if (fd < 0) { + fd = open("/dev/vpu-service", O_RDWR | O_CLOEXEC); + } + memset(&hwCfg, 0, sizeof(VPUHwDecConfig_t)); + if (fd >= 0) { + if (VPUClientGetHwCfg(fd, (RK_U32*)&hwCfg, sizeof(hwCfg))) { + mpp_err_f("Get HwCfg failed\n"); + close(fd); + return -1; + } + close(fd); + fd = -1; + } + return hwCfg.maxDecPicWidth; +} + +RK_S32 VPUClientGetIOMMUStatus() +{ + return 1; +} diff --git a/mpp/legacy/vpu_api.cpp b/mpp/legacy/vpu_api.cpp index 512fe2c87..8ffee9500 100644 --- a/mpp/legacy/vpu_api.cpp +++ b/mpp/legacy/vpu_api.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * Copyright 2015 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,23 +17,29 @@ #define MODULE_TAG "vpu_api" #include +#include +#include -#include "mpp_log.h" #include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_soc.h" -#include "vpu_api_legacy.h" #include "vpu_api.h" +#include "vpu_api_legacy.h" +#include "vpu_mem_legacy.h" -static RK_S32 vpu_api_init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size) +static RK_S32 +vpu_api_init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size) { - mpp_log("vpu_api_init in, extra_size: %d", extra_size); + vpu_api_dbg_func("vpu_api_init in, extra_size: %d", extra_size); if (ctx == NULL) { mpp_log("vpu_api_init fail, input invalid"); return VPU_API_ERR_UNKNOW; } - - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_init fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; @@ -42,14 +48,15 @@ static RK_S32 vpu_api_init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_ return api->init(ctx, extraData, extra_size); } -static RK_S32 vpu_api_decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut) +static RK_S32 +vpu_api_decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut) { if (ctx == NULL) { mpp_log("vpu_api_decode fail, input invalid"); return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_decode fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; @@ -64,13 +71,13 @@ static RK_S32 vpu_api_sendstream(VpuCodecContext *ctx, VideoPacket_t *pkt) return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_sendstream fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; } - return api->decode_sendstream(ctx, pkt); + return api->decode_sendstream(pkt); } static RK_S32 vpu_api_getframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut) @@ -80,7 +87,7 @@ static RK_S32 vpu_api_getframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut) return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_getframe fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; @@ -89,14 +96,15 @@ static RK_S32 vpu_api_getframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut) return api->decode_getoutframe(ctx, aDecOut); } -static RK_S32 vpu_api_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm) +static RK_S32 +vpu_api_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm) { if (ctx == NULL) { mpp_log("vpu_api_decode fail, input invalid"); return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_sendframe fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; @@ -112,7 +120,7 @@ static RK_S32 vpu_api_getstream(VpuCodecContext *ctx, EncoderOut_t *aEncOut) return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_getframe fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; @@ -121,16 +129,16 @@ static RK_S32 vpu_api_getstream(VpuCodecContext *ctx, EncoderOut_t *aEncOut) return api->encoder_getstream(ctx, aEncOut); } - - -static RK_S32 vpu_api_encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut) +static RK_S32 +vpu_api_encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, + EncoderOut_t *aEncOut) { if (ctx == NULL) { mpp_log("vpu_api_encode fail, input invalid"); return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_encode fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; @@ -141,12 +149,13 @@ static RK_S32 vpu_api_encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, static RK_S32 vpu_api_flush(VpuCodecContext *ctx) { + if (ctx == NULL) { mpp_log("vpu_api_encode fail, input invalid"); return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_flush fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; @@ -155,152 +164,296 @@ static RK_S32 vpu_api_flush(VpuCodecContext *ctx) return api->flush(ctx); } -static RK_S32 vpu_api_control(VpuCodecContext *ctx, VPU_API_CMD cmdType, void *param) +static RK_S32 +vpu_api_control(VpuCodecContext *ctx, VPU_API_CMD cmdType, void *param) { if (ctx == NULL) { mpp_log("vpu_api_decode fail, input invalid"); return VPU_API_ERR_UNKNOW; } - VpuApi* api = (VpuApi*)(ctx->vpuApiObj); + VpuApiLegacy* api = (VpuApiLegacy*)(ctx->vpuApiObj); if (api == NULL) { mpp_log("vpu_api_decode fail, vpu api invalid"); return VPU_API_ERR_UNKNOW; } + vpu_api_dbg_func("enter\n"); + switch (cmdType) { + case VPU_API_SET_VPUMEM_CONTEXT: { + vpu_display_mem_pool_impl *p_mempool = + (vpu_display_mem_pool_impl *)param; + + param = (void*)p_mempool->group; + break; + } + default: { + break; + } + } + + vpu_api_dbg_func("pass to mpi\n"); return api->control(ctx, cmdType, param); } -RK_S32 vpu_open_context(VpuCodecContext **ctx) -{ - mpp_log("vpu_open_context in"); - VpuCodecContext *s = *ctx; +static const char *codec_paths[] = { + "/vendor/lib/librk_vpuapi.so", + "/system/lib/librk_vpuapi.so", + "/system/lib/librk_on2.so", + "/usr/lib/librk_codec.so", +}; - if (!s) { - s = mpp_malloc(VpuCodecContext, 1); - if (!s) { - mpp_err("Input context has not been properly allocated"); - return -1; +class VpulibDlsym +{ +public: + void *rkapi_hdl; + RK_S32 (*rkvpu_open_cxt)(VpuCodecContext **ctx); + RK_S32 (*rkvpu_close_cxt)(VpuCodecContext **ctx); + VpulibDlsym() : + rkapi_hdl(NULL), + rkvpu_open_cxt(NULL), + rkvpu_close_cxt(NULL) { + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(codec_paths); i++) { + rkapi_hdl = dlopen(codec_paths[i], RTLD_LAZY | RTLD_GLOBAL); + if (rkapi_hdl) + break; } - memset(s, 0, sizeof(VpuCodecContext)); - s->enableparsing = 1; - VpuApi* api = new VpuApi(); - if (api == NULL) { - mpp_err("Vpu api object has not been properly allocated"); - return -1; + if (rkapi_hdl) { + rkvpu_open_cxt = (RK_S32 (*)(VpuCodecContext **ctx)) + dlsym(rkapi_hdl, "vpu_open_context"); + rkvpu_close_cxt = (RK_S32 (*)(VpuCodecContext **ctx)) + dlsym(rkapi_hdl, "vpu_close_context"); + mpp_log("dlopen vpu lib %s success\n", codec_paths[i]); } - - s->vpuApiObj = (void*)api; - s->init = vpu_api_init; - s->decode = vpu_api_decode; - s->encode = vpu_api_encode; - s->flush = vpu_api_flush; - s->control = vpu_api_control; - s->decode_sendstream = vpu_api_sendstream; - s->decode_getframe = vpu_api_getframe; - s->encoder_sendframe = vpu_api_sendframe; - s->encoder_getstream = vpu_api_getstream; - - *ctx = s; - return 0; } - if (!s->vpuApiObj) { - mpp_err("Input context has not been properly allocated and is not NULL either"); - return -1; - } - return 0; -} - -RK_S32 vpu_close_context(VpuCodecContext **ctx) -{ - mpp_log("vpu_close_context in"); - VpuCodecContext *s = *ctx; - - if (s) { - VpuApi* api = (VpuApi*)(s->vpuApiObj); - if (s->vpuApiObj) { - delete api; - s->vpuApiObj = NULL; + ~VpulibDlsym() { + if (rkapi_hdl) { + dlclose(rkapi_hdl); + rkapi_hdl = NULL; } - mpp_free(s->extradata); - mpp_free(s->private_data); - mpp_free(s); - *ctx = s = NULL; - - mpp_log("vpu_close_context ok"); } - return 0; -} +}; +static VpulibDlsym gVpulib; - -RK_S32 VPUMallocLinear(VPUMemLinear_t *p, RK_U32 size) +static RK_S32 check_orign_vpu() { - (void)p; - (void)size; - return 0; + return (gVpulib.rkapi_hdl) ? (MPP_OK) : (MPP_NOK); } -RK_S32 VPUFreeLinear(VPUMemLinear_t *p) +static RK_S32 open_orign_vpu(VpuCodecContext **ctx) { - (void)p; - return 0; + if (gVpulib.rkvpu_open_cxt && ctx) { + return (gVpulib.rkvpu_open_cxt)(ctx); + } + return MPP_NOK; } -RK_S32 VPUMemDuplicate(VPUMemLinear_t *dst, VPUMemLinear_t *src) +static RK_S32 close_orign_vpu(VpuCodecContext **ctx) { - (void)dst; - (void)src; - return 0; + if (gVpulib.rkvpu_close_cxt && ctx) { + return (gVpulib.rkvpu_close_cxt)(ctx); + } + return MPP_NOK; } -RK_S32 VPUMemLink(VPUMemLinear_t *p) +/* + * old libvpu path will input a NULL pointer in *ctx + * new libvpu path will input non-NULL pointer in *ctx + */ +RK_S32 vpu_open_context(VpuCodecContext **ctx) { - (void)p; - return 0; -} + VpuCodecContext *s = *ctx; + RK_S32 ret = -1; + RK_U32 force_original = 0; + RK_U32 force_mpp_mode = 0; + RK_U32 use_mpp = 0; + + CODEC_TYPE codecType = CODEC_NONE; + OMX_RK_VIDEO_CODINGTYPE videoCoding = OMX_RK_VIDEO_CodingUnused; + RK_U32 width = 0; + RK_U32 height = 0; + void *extradata = NULL; + RK_S32 extradata_size = 0; + EXtraCfg_t extra_cfg; + memset(&extra_cfg, 0, sizeof(EXtraCfg_t)); + + mpp_env_get_u32("vpu_api_debug", &vpu_api_debug, 0); + vpu_api_dbg_func("enter\n"); + + mpp_env_get_u32("use_original", &force_original, 0); + mpp_env_get_u32("use_mpp_mode", &force_mpp_mode, 0); + + /* if there is no original vpuapi library force to mpp path */ + if (check_orign_vpu()) + force_mpp_mode = 1; + + if (force_original) { + /* force mpp mode here */ + use_mpp = 0; + } else if (force_mpp_mode) { + /* force mpp mode here */ + use_mpp = 1; + } else if (!access("/dev/mpp_service", F_OK)) { + /* if mpp_service exist, force mpp mode */ + use_mpp = 1; + } else if (!!access("/dev/rkvdec", F_OK)) { + /* if there is no rkvdec it means the platform must be vpu1 */ + if (s && s->videoCoding == OMX_RK_VIDEO_CodingHEVC && + (!access("/dev/hevc-service", F_OK) + || !access("/dev/hevc_service", F_OK))) { + /* if this is a hevc request and exist hevc_service for decoding use mpp */ + use_mpp = 1; + } else { + /* otherwise use original vpuapi path */ + use_mpp = 0; + } + } else if (NULL == s) { + /* caller is original vpuapi path. Force use original vpuapi path */ + use_mpp = 0; + } else { + if (s->videoCoding == OMX_RK_VIDEO_CodingAVC + && s->codecType == CODEC_DECODER && s->width <= 1920 + && s->height <= 1088 && !s->extra_cfg.mpp_mode + && mpp_get_soc_type() != ROCKCHIP_SOC_RK3399) { + /* H.264 smaller than 1080p use original vpuapi library for better error process */ + // NOTE: rk3399 need better performance + use_mpp = 0; + } else { + MppCtxType type = (s->codecType == CODEC_DECODER) ? (MPP_CTX_DEC) : + (s->codecType == CODEC_ENCODER) + ? (MPP_CTX_ENC) : (MPP_CTX_BUTT); + MppCodingType coding = (MppCodingType)s->videoCoding; + + if (MPP_OK == mpp_check_support_format(type, coding)) { + /* If current mpp can support this format use mpp */ + use_mpp = 1; + } else { + /* unsupport format use vpuapi library */ + use_mpp = 0; + } + } + } -RK_S32 VPUMemFlush(VPUMemLinear_t *p) -{ - (void)p; - return 0; -} + /* + * No matter what is the old context just release it. + * But we need to save to pre-configured parameter + */ + if (s) { + codecType = s->codecType; + videoCoding = s->videoCoding; + width = s->width; + height = s->height; + extradata = s->extradata; + extradata_size = s->extradata_size; + extra_cfg = s->extra_cfg; + + free(s); + s = NULL; + } -RK_S32 VPUMemClean(VPUMemLinear_t *p) -{ - (void)p; - return 0; -} + if (!use_mpp) { + vpu_api_dbg_func("use vpuapi path\n"); + ret = open_orign_vpu(&s); + if (!ret && s) { + // for safety + s->extra_cfg.ori_vpu = 1; + extra_cfg.ori_vpu = 1; + } + } else { + vpu_api_dbg_func("use mpp path\n"); + + s = mpp_calloc(VpuCodecContext, 1); + if (s) { + s->enableparsing = 1; + + VpuApiLegacy* api = new VpuApiLegacy(); + + if (api) { + s->vpuApiObj = (void*)api; + s->init = vpu_api_init; + s->decode = vpu_api_decode; + s->encode = vpu_api_encode; + s->flush = vpu_api_flush; + s->control = vpu_api_control; + s->decode_sendstream = vpu_api_sendstream; + s->decode_getframe = vpu_api_getframe; + s->encoder_sendframe = vpu_api_sendframe; + s->encoder_getstream = vpu_api_getstream; + + s->extra_cfg.ori_vpu = 0; + extra_cfg.ori_vpu = 0; + + ret = 0; + } else { + mpp_err("Vpu api object has not been properly allocated"); + mpp_free(s); + s = NULL; + } + } else { + mpp_err("Input context has not been properly allocated"); + } + } -RK_S32 VPUMemInvalidate(VPUMemLinear_t *p) -{ - (void)p; - return 0; -} + if (s) { + s->codecType = codecType; + s->videoCoding = videoCoding; + s->width = width; + s->height = height; + s->extradata = extradata; + s->extradata_size = extradata_size; + s->extra_cfg = extra_cfg; + } + *ctx = s; -vpu_display_mem_pool* open_vpu_memory_pool() -{ - return NULL; + vpu_api_dbg_func("leave\n"); + return ret; } -void close_vpu_memory_pool(vpu_display_mem_pool *p) +RK_S32 vpu_close_context(VpuCodecContext **ctx) { - (void)p; -} + vpu_api_dbg_func("enter\n"); + VpuCodecContext *s = *ctx; + RK_S32 ret = -1; + RK_U32 force_original = 0; -int create_vpu_memory_pool_allocator(vpu_display_mem_pool **ipool, int num, int size) -{ - (void)ipool; - (void)num; - (void)size; - return 0; -} + mpp_env_get_u32("force_original", &force_original, 0); -void release_vpu_memory_pool_allocator(vpu_display_mem_pool *ipool) -{ - (void)ipool; -} + if (s) { + if (s->extra_cfg.ori_vpu) { + ret = close_orign_vpu(ctx); + mpp_log("org vpu_close_context ok"); + } else { + if (s->flush) + s->flush(s); + + VpuApiLegacy* api = (VpuApiLegacy*)(s->vpuApiObj); + if (s->vpuApiObj) { + delete api; + s->vpuApiObj = NULL; + } + + if (s->extradata_size > 0) { + s->extradata_size = 0; + s->extradata = NULL; + } + + if (s->private_data) + mpp_free(s->private_data); + + mpp_free(s); + ret = 0; + } + + *ctx = s = NULL; + } + vpu_api_dbg_func("leave\n"); + + return ret; +} diff --git a/mpp/legacy/vpu_api_legacy.cpp b/mpp/legacy/vpu_api_legacy.cpp index 9f33fb85d..0bf63fa5e 100644 --- a/mpp/legacy/vpu_api_legacy.cpp +++ b/mpp/legacy/vpu_api_legacy.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * Copyright 2015 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,131 +16,1844 @@ #define MODULE_TAG "vpu_api_legacy" -#include "mpp_log.h" +#include "string.h" + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" #include "vpu_api_legacy.h" +#include "mpp_packet_impl.h" +#include "mpp_buffer_impl.h" +#include "mpp_frame.h" +#include "mpp_compat.h" + +#define VPU_API_ENC_INPUT_TIMEOUT 100 + +RK_U32 vpu_api_debug = 0; -VpuApi::VpuApi() +static MppFrameFormat vpu_pic_type_remap_to_mpp(EncInputPictureType type) { - mpp_log_f("in\n"); - mpp_log_f("ok\n"); + MppFrameFormat ret = MPP_FMT_BUTT; + switch (type) { + case ENC_INPUT_YUV420_PLANAR : { + ret = MPP_FMT_YUV420P; + } break; + case ENC_INPUT_YUV420_SEMIPLANAR : { + ret = MPP_FMT_YUV420SP; + } break; + case ENC_INPUT_YUV420_SEMIPLANAR_VU : { + ret = MPP_FMT_YUV420SP_VU; + } break; + case ENC_INPUT_YUV422_INTERLEAVED_YUYV : { + ret = MPP_FMT_YUV422_YUYV; + } break; + case ENC_INPUT_YUV422_INTERLEAVED_UYVY : { + ret = MPP_FMT_YUV422_UYVY; + } break; + case ENC_INPUT_RGB565 : { + ret = MPP_FMT_RGB565; + } break; + case ENC_INPUT_BGR565 : { + ret = MPP_FMT_BGR565; + } break; + case ENC_INPUT_RGB555 : { + ret = MPP_FMT_RGB555; + } break; + case ENC_INPUT_BGR555 : { + ret = MPP_FMT_BGR555; + } break; + case ENC_INPUT_RGB444 : { + ret = MPP_FMT_RGB444; + } break; + case ENC_INPUT_BGR444 : { + ret = MPP_FMT_BGR444; + } break; + case ENC_INPUT_RGB888 : { + ret = MPP_FMT_RGB888; + } break; + case ENC_INPUT_BGR888 : { + ret = MPP_FMT_BGR888; + } break; + case ENC_INPUT_RGB101010 : { + ret = MPP_FMT_RGB101010; + } break; + case ENC_INPUT_BGR101010 : { + ret = MPP_FMT_BGR101010; + } break; + default : { + mpp_err("There is no match format, err!!!!!!"); + } break; + } + return ret; } -VpuApi::~VpuApi() +static MPP_RET vpu_api_set_enc_cfg(MppCtx mpp_ctx, MppApi *mpi, MppEncCfg enc_cfg, + MppCodingType coding, MppFrameFormat fmt, + EncParameter_t *cfg) { - mpp_log_f("in\n"); - mpp_log_f("ok\n"); + MPP_RET ret = MPP_OK; + RK_S32 width = cfg->width; + RK_S32 height = cfg->height; + RK_S32 bps = cfg->bitRate; + RK_S32 fps_in = cfg->framerate; + RK_S32 fps_out = (cfg->framerateout) ? (cfg->framerateout) : (fps_in); + RK_S32 gop = (cfg->intraPicRate) ? (cfg->intraPicRate) : (fps_out); + RK_S32 qp_init = (coding == MPP_VIDEO_CodingAVC) ? (26) : + (coding == MPP_VIDEO_CodingMJPEG) ? (10) : + (coding == MPP_VIDEO_CodingVP8) ? (56) : + (coding == MPP_VIDEO_CodingHEVC) ? (26) : (0); + RK_S32 qp = (cfg->qp) ? (cfg->qp) : (qp_init); + RK_S32 profile = cfg->profileIdc; + RK_S32 level = cfg->levelIdc; + RK_S32 cabac_en = cfg->enableCabac; + RK_S32 rc_mode = cfg->rc_mode; + RK_U32 is_fix_qp = (rc_mode == MPP_ENC_RC_MODE_FIXQP) ? 1 : 0; + + RK_S32 qp_max = (cfg->reserved[0] & 0xFF00) >> 8; + RK_S32 qp_min = cfg->reserved[0] & 0x00FF; + + if (qp_max == 0 || qp_max < qp) { + qp_max = 51; + } + if (qp_min == 0 || qp_min > qp) { + qp_min = 10; + } + + mpp_log("setup encoder rate control config:\n"); + mpp_log("width %4d height %4d format %d:%x\n", width, height, cfg->format, fmt); + mpp_log("rc_mode %s qp %d bps %d\n", (rc_mode) ? ("CBR") : ("CQP"), qp, bps); + mpp_log("fps in %d fps out %d gop %d\n", fps_in, fps_out, gop); + mpp_log("setup encoder stream feature config:\n"); + mpp_log("profile %d level %d cabac %d\n", profile, level, cabac_en); + mpp_log("setup encoder qp_init %d qp_min %d qp_max %d\n", qp, qp_min, qp_max); + + mpp_assert(width); + mpp_assert(height); + mpp_assert(qp); + + mpp_enc_cfg_set_s32(enc_cfg, "prep:width", width); + mpp_enc_cfg_set_s32(enc_cfg, "prep:height", height); + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420P: + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_VU : { + mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", MPP_ALIGN(width, 16)); + } break; + case MPP_FMT_RGB565: + case MPP_FMT_BGR565: + case MPP_FMT_RGB555: + case MPP_FMT_BGR555: { + mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", 2 * MPP_ALIGN(width, 16)); + } break; + case MPP_FMT_RGB888 : + case MPP_FMT_BGR888 : { + mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", 3 * MPP_ALIGN(width, 16)); + } break; + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGBA8888 : { + mpp_enc_cfg_set_s32(enc_cfg, "prep:hor_stride", 4 * MPP_ALIGN(width, 16)); + } break; + default: { + mpp_err("unsupport format 0x%x\n", fmt & MPP_FRAME_FMT_MASK); + } break; + } + mpp_enc_cfg_set_s32(enc_cfg, "prep:ver_stride", MPP_ALIGN(height, 8)); + mpp_enc_cfg_set_s32(enc_cfg, "prep:format", fmt); + + mpp_enc_cfg_set_s32(enc_cfg, "rc:mode", is_fix_qp ? MPP_ENC_RC_MODE_FIXQP : + (rc_mode ? MPP_ENC_RC_MODE_CBR : MPP_ENC_RC_MODE_VBR)); + mpp_enc_cfg_set_s32(enc_cfg, "rc:bps_target", bps); + mpp_enc_cfg_set_s32(enc_cfg, "rc:bps_max", bps * 17 / 16); + mpp_enc_cfg_set_s32(enc_cfg, "rc:bps_min", rc_mode ? bps * 15 / 16 : bps * 1 / 16); + mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_in_flex", 0); + mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_in_num", fps_in); + mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_in_denom", 1); + mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_out_flex", 0); + mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_out_num", fps_out); + mpp_enc_cfg_set_s32(enc_cfg, "rc:fps_out_denom", 1); + mpp_enc_cfg_set_s32(enc_cfg, "rc:gop", gop); + + mpp_enc_cfg_set_s32(enc_cfg, "codec:type", coding); + switch (coding) { + case MPP_VIDEO_CodingAVC : { + mpp_enc_cfg_set_s32(enc_cfg, "h264:profile", profile); + mpp_enc_cfg_set_s32(enc_cfg, "h264:level", level); + mpp_enc_cfg_set_s32(enc_cfg, "h264:cabac_en", cabac_en); + mpp_enc_cfg_set_s32(enc_cfg, "h264:cabac_idc", 0); + mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_init", is_fix_qp ? qp : -1); + mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_min", is_fix_qp ? qp : qp_min); + mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_max", is_fix_qp ? qp : qp_max); + mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_min_i", is_fix_qp ? 10 : qp_min); + mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_max_i", is_fix_qp ? 51 : qp_max); + mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_step", 4); + mpp_enc_cfg_set_s32(enc_cfg, "h264:qp_delta_ip", 3); + } break; + case MPP_VIDEO_CodingVP8 : { + mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_init", -1); + mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_min", 0); + mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_max", 127); + mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_min_i", 0); + mpp_enc_cfg_set_s32(enc_cfg, "vp8:qp_max_i", 127); + } break; + case MPP_VIDEO_CodingMJPEG : { + mpp_enc_cfg_set_s32(enc_cfg, "jpeg:quant", qp); + } break; + default : { + mpp_err_f("support encoder coding type %d\n", coding); + } break; + } + + ret = mpi->control(mpp_ctx, MPP_ENC_SET_CFG, enc_cfg); + if (ret) { + mpp_err("setup enc config failed ret %d\n", ret); + goto RET; + } +RET: + return ret; } -RK_S32 VpuApi::init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size) +static int is_valid_dma_fd(int fd) { - mpp_log_f("in\n"); - (void)ctx; - (void)extraData; - (void)extra_size; - mpp_log_f("ok\n"); - return 0; + int ret = 1; + /* detect input file handle */ + int fs_flag = fcntl(fd, F_GETFL, NULL); + int fd_flag = fcntl(fd, F_GETFD, NULL); + + if (fs_flag == -1 || fd_flag == -1) { + ret = 0; + } + + return ret; } -RK_S32 VpuApi::send_stream(RK_U8* buf, RK_U32 size, RK_S64 timestamp, RK_S32 usePts) +static int copy_align_raw_buffer_to_dest(RK_U8 *dst, RK_U8 *src, RK_U32 width, + RK_U32 height, MppFrameFormat fmt) { - mpp_log_f("in\n"); - (void)buf; - (void)size; - (void)timestamp; - (void)usePts; - mpp_log_f("ok\n"); - return 0; + int ret = 1; + RK_U32 index = 0; + RK_U8 *dst_buf = dst; + RK_U8 *src_buf = src; + RK_U32 row = 0; + RK_U32 hor_stride = MPP_ALIGN(width, 16); + RK_U32 ver_stride = MPP_ALIGN(height, 8); + RK_U8 *dst_u = dst_buf + hor_stride * ver_stride; + RK_U8 *dst_v = dst_u + hor_stride * ver_stride / 4; + + switch (fmt) { + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_VU : { + for (row = 0; row < height; row++) { + memcpy(dst_buf + row * hor_stride, src_buf + index, width); + index += width; + } + for (row = 0; row < height / 2; row++) { + memcpy(dst_u + row * hor_stride, src_buf + index, width); + index += width; + } + } break; + case MPP_FMT_YUV420P : { + for (row = 0; row < height; row++) { + memcpy(dst_buf + row * hor_stride, src_buf + index, width); + index += width; + } + for (row = 0; row < height / 2; row++) { + memcpy(dst_u + row * hor_stride / 2, src_buf + index, width / 2); + index += width / 2; + } + for (row = 0; row < height / 2; row++) { + memcpy(dst_v + row * hor_stride / 2, src_buf + index, width / 2); + index += width / 2; + } + } break; + case MPP_FMT_RGB888 : + case MPP_FMT_BGR888 : { + for (row = 0; row < height; row++) { + memcpy(dst_buf + row * hor_stride * 3, src_buf + row * width * 3, width * 3); + } + } break; + case MPP_FMT_ABGR8888 : + case MPP_FMT_ARGB8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGBA8888 : { + for (row = 0; row < height; row++) { + memcpy(dst_buf + row * hor_stride * 4, src_buf + row * width * 4, width * 4); + } + } break; + default : { + mpp_err("unsupport align fmt:%d now\n", fmt); + } break; + } + + return ret; } -RK_S32 VpuApi::get_frame(DecoderOut_t *aDecOut) +VpuApiLegacy::VpuApiLegacy() : + mpp_ctx(NULL), + mpi(NULL), + init_ok(0), + frame_count(0), + set_eos(0), + frm_info(NULL), + memGroup(NULL), + format(MPP_FMT_YUV420P), + mInputTimeOutMs(0), + fd_input(-1), + fd_output(-1), + mEosSet(0), + enc_cfg(NULL), + enc_hdr_pkt(NULL), + enc_hdr_buf(NULL), + enc_hdr_buf_size(0), + dec_out_frm_struct_type(0) { - mpp_log_f("in\n"); - (void)aDecOut; - mpp_log_f("ok\n"); - return 0; + vpu_api_dbg_func("enter\n"); + + mpp_create(&mpp_ctx, &mpi); + mpp_frame_init(&frm_info); + + memset(&frm_rdy_cb, 0, sizeof(FrameRdyCB)); + memset(&enc_param, 0, sizeof(enc_param)); + + mlvec = NULL; + memset(&mlvec_dy_cfg, 0, sizeof(mlvec_dy_cfg)); + + vpu_api_dbg_func("leave\n"); } -RK_S32 VpuApi::flush(VpuCodecContext *ctx) +VpuApiLegacy::~VpuApiLegacy() { - mpp_log_f("in\n"); - (void)ctx; - mpp_log_f("ok\n"); - return 0; + vpu_api_dbg_func("enter\n"); + + mpp_frame_deinit(&frm_info); + mpp_destroy(mpp_ctx); + + if (memGroup) { + mpp_buffer_group_put(memGroup); + memGroup = NULL; + } + + if (enc_cfg) { + mpp_enc_cfg_deinit(enc_cfg); + enc_cfg = NULL; + } + + if (mlvec) { + vpu_api_mlvec_deinit(mlvec); + mlvec = NULL; + } + + if (enc_hdr_pkt) { + mpp_packet_deinit(&enc_hdr_pkt); + enc_hdr_pkt = NULL; + } + MPP_FREE(enc_hdr_buf); + enc_hdr_buf_size = 0; + + vpu_api_dbg_func("leave\n"); } -RK_S32 VpuApi::decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut) +static RK_S32 init_frame_info(VpuCodecContext *ctx, MppCtx mpp_ctx, MppApi *mpi, + MppFrame frame_info, VPU_GENERIC *p) { - mpp_log_f("in\n"); - (void)ctx; - (void)pkt; - (void)aDecOut; - mpp_log_f("ok\n"); - return 0; + RK_S32 ret = -1; + RK_U32 fbcOutFmt = 0; + + if (ctx->private_data) + fbcOutFmt = *(RK_U32 *)ctx->private_data; + + if (ctx->extra_cfg.bit_depth + || ctx->extra_cfg.yuv_format) { + if (ctx->extra_cfg.bit_depth == 10) + p->CodecType = (ctx->extra_cfg.yuv_format == 1) + ? MPP_FMT_YUV422SP_10BIT : MPP_FMT_YUV420SP_10BIT; + else + p->CodecType = (ctx->extra_cfg.yuv_format == 1) + ? MPP_FMT_YUV422SP : MPP_FMT_YUV420SP; + } else { + /**hightest of p->ImgWidth bit show current dec bitdepth + * 0 - 8bit + * 1 - 10bit + **/ + if (p->ImgWidth & 0x80000000) + p->CodecType = (p->ImgWidth & 0x40000000) + ? MPP_FMT_YUV422SP_10BIT : MPP_FMT_YUV420SP_10BIT; + else + p->CodecType = (p->ImgWidth & 0x40000000) + ? MPP_FMT_YUV422SP : MPP_FMT_YUV420SP; + } + p->ImgWidth = (p->ImgWidth & 0xFFFF); + + mpp_frame_set_width(frame_info, p->ImgWidth); + mpp_frame_set_height(frame_info, p->ImgHeight); + mpp_frame_set_fmt(frame_info, (MppFrameFormat)(p->CodecType | fbcOutFmt)); + + ret = mpi->control(mpp_ctx, MPP_DEC_SET_FRAME_INFO, (MppParam)frame_info); + /* output the parameters used */ + p->ImgHorStride = mpp_frame_get_hor_stride(frame_info); + p->ImgVerStride = mpp_frame_get_ver_stride(frame_info); + p->BufSize = mpp_frame_get_buf_size(frame_info); + + return ret; } -RK_S32 VpuApi::decode_sendstream(VpuCodecContext *ctx, VideoPacket_t *pkt) + +RK_S32 VpuApiLegacy::init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size) { - mpp_log_f("in\n"); - (void)ctx; - (void)pkt; - mpp_log_f("ok\n"); - return 0; + vpu_api_dbg_func("enter\n"); + + MPP_RET ret = MPP_OK; + MppCtxType type; + + if (mpp_ctx == NULL || mpi == NULL) { + mpp_err("found invalid context input"); + return MPP_ERR_NULL_PTR; + } + + if (CODEC_DECODER == ctx->codecType) { + type = MPP_CTX_DEC; + } else if (CODEC_ENCODER == ctx->codecType) { + type = MPP_CTX_ENC; + } else { + mpp_err("found invalid codec type %d\n", ctx->codecType); + return MPP_ERR_VPU_CODEC_INIT; + } + + ret = mpp_init(mpp_ctx, type, (MppCodingType)ctx->videoCoding); + if (ret) { + mpp_err_f(" init error. \n"); + return ret; + } + + if (MPP_CTX_ENC == type) { + EncParameter_t *param = (EncParameter_t*)ctx->private_data; + MppCodingType coding = (MppCodingType)ctx->videoCoding; + MppPollType block = (MppPollType)VPU_API_ENC_INPUT_TIMEOUT; + MppEncSeiMode sei_mode = MPP_ENC_SEI_MODE_DISABLE; + + /* setup input / output block mode */ + ret = mpi->control(mpp_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block); + if (MPP_OK != ret) + mpp_err("mpi control MPP_SET_INPUT_TIMEOUT failed\n"); + + /* disable sei by default */ + ret = mpi->control(mpp_ctx, MPP_ENC_SET_SEI_CFG, &sei_mode); + if (ret) + mpp_err("mpi control MPP_ENC_SET_SEI_CFG failed ret %d\n", ret); + + if (memGroup == NULL) { + ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err("memGroup mpp_buffer_group_get failed %d\n", ret); + return ret; + } + } + + ret = mpp_enc_cfg_init(&enc_cfg); + if (ret) { + mpp_err("mpp_enc_cfg_init failed %d\n", ret); + mpp_buffer_group_put(memGroup); + memGroup = NULL; + return ret; + } + + format = vpu_pic_type_remap_to_mpp((EncInputPictureType)param->format); + + memcpy(&enc_param, param, sizeof(enc_param)); + + if (MPP_OK == vpu_api_mlvec_check_cfg(param)) { + if (NULL == mlvec) { + vpu_api_mlvec_init(&mlvec); + vpu_api_mlvec_setup(mlvec, mpp_ctx, mpi, enc_cfg); + } + } + + if (mlvec) + vpu_api_mlvec_set_st_cfg(mlvec, (VpuApiMlvecStaticCfg *)param); + + vpu_api_set_enc_cfg(mpp_ctx, mpi, enc_cfg, coding, format, param); + + if (!mlvec) { + if (NULL == enc_hdr_pkt) { + if (NULL == enc_hdr_buf) { + enc_hdr_buf_size = SZ_1K; + enc_hdr_buf = mpp_calloc_size(RK_U8, enc_hdr_buf_size); + } + + if (enc_hdr_buf) + mpp_packet_init(&enc_hdr_pkt, enc_hdr_buf, enc_hdr_buf_size); + } + + mpp_assert(enc_hdr_pkt); + if (enc_hdr_pkt) { + ret = mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, enc_hdr_pkt); + ctx->extradata_size = mpp_packet_get_length(enc_hdr_pkt); + ctx->extradata = mpp_packet_get_data(enc_hdr_pkt); + } + } + } else { /* MPP_CTX_DEC */ + vpug.CodecType = ctx->codecType; + vpug.ImgWidth = ctx->width; + vpug.ImgHeight = ctx->height; + + init_frame_info(ctx, mpp_ctx, mpi, frm_info, &vpug); + + if (extraData != NULL) { + MppPacket pkt = NULL; + + mpp_packet_init(&pkt, extraData, extra_size); + mpp_packet_set_extra_data(pkt); + mpi->decode_put_packet(mpp_ctx, pkt); + mpp_packet_deinit(&pkt); + } + + RK_U32 flag = 0; + ret = mpi->control(mpp_ctx, MPP_DEC_SET_ENABLE_DEINTERLACE, &flag); + if (ret) + mpp_err_f("disable mpp deinterlace failed ret %d\n", ret); + } + + init_ok = 1; + + vpu_api_dbg_func("leave\n"); + return ret; } -RK_S32 VpuApi:: decode_getoutframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut) +RK_S32 VpuApiLegacy::flush(VpuCodecContext *ctx) { - mpp_log_f("in\n"); (void)ctx; - (void)aDecOut; - mpp_log_f("ok\n"); + vpu_api_dbg_func("enter\n"); + if (mpi && mpi->reset && init_ok) { + mpi->reset(mpp_ctx); + set_eos = 0; + mEosSet = 0; + } + vpu_api_dbg_func("leave\n"); return 0; } -RK_S32 VpuApi::encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut) +static void setup_VPU_FRAME_from_mpp_frame(VpuCodecContext *ctx, VPU_FRAME *vframe, MppFrame mframe) { - mpp_log_f("in\n"); - (void)ctx; - (void)aEncInStrm; - (void)aEncOut; - mpp_log_f("ok\n"); - return 0; + MppBuffer buf = mpp_frame_get_buffer(mframe); + RK_U64 pts = mpp_frame_get_pts(mframe); + RK_U32 mode = mpp_frame_get_mode(mframe); + + MppFrameColorRange colorRan = mpp_frame_get_color_range(mframe); + MppFrameColorTransferCharacteristic colorTrc = mpp_frame_get_color_trc(mframe); + MppFrameColorPrimaries colorPri = mpp_frame_get_color_primaries(mframe); + MppFrameColorSpace colorSpa = mpp_frame_get_colorspace(mframe); + + if (buf) + mpp_buffer_inc_ref(buf); + + vframe->CodingType = ctx->videoCoding; + vframe->DisplayWidth = mpp_frame_get_width(mframe); + vframe->DisplayHeight = mpp_frame_get_height(mframe); + vframe->FrameWidth = mpp_frame_get_hor_stride(mframe); + vframe->FrameHeight = mpp_frame_get_ver_stride(mframe); + + vframe->ColorRange = (colorRan == MPP_FRAME_RANGE_JPEG); + vframe->ColorPrimaries = colorPri; + vframe->ColorTransfer = colorTrc; + vframe->ColorCoeffs = colorSpa; + + if (mode == MPP_FRAME_FLAG_FRAME) + vframe->FrameType = 0; + else { + RK_U32 field_order = mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK; + if (field_order == MPP_FRAME_FLAG_TOP_FIRST) + vframe->FrameType = 1; + else if (field_order == MPP_FRAME_FLAG_BOT_FIRST) + vframe->FrameType = 2; + else if (field_order == MPP_FRAME_FLAG_DEINTERLACED) + vframe->FrameType = 4; + } + vframe->ErrorInfo = mpp_frame_get_errinfo(mframe) | mpp_frame_get_discard(mframe); + vframe->ShowTime.TimeHigh = (RK_U32)(pts >> 32); + vframe->ShowTime.TimeLow = (RK_U32)pts; + switch (mpp_frame_get_fmt(mframe) & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP: { + vframe->ColorType = VPU_OUTPUT_FORMAT_YUV420_SEMIPLANAR; + vframe->OutputWidth = 0x20; + } break; + case MPP_FMT_YUV420SP_10BIT: { + vframe->ColorType = VPU_OUTPUT_FORMAT_YUV420_SEMIPLANAR; + vframe->ColorType |= VPU_OUTPUT_FORMAT_BIT_10; + vframe->OutputWidth = 0x22; + } break; + case MPP_FMT_YUV422SP: { + vframe->ColorType = VPU_OUTPUT_FORMAT_YUV422; + vframe->OutputWidth = 0x10; + } break; + case MPP_FMT_YUV422SP_10BIT: { + vframe->ColorType = VPU_OUTPUT_FORMAT_YUV422; + vframe->ColorType |= VPU_OUTPUT_FORMAT_BIT_10; + vframe->OutputWidth = 0x23; + } break; + case MPP_FMT_YUV444SP: { + vframe->ColorType = VPU_OUTPUT_FORMAT_YUV444; + vframe->OutputWidth = 0x11; + } break; + default: { + } break; + } + + switch (mpp_frame_get_fmt(mframe) & MPP_FRAME_FBC_MASK) { + case MPP_FRAME_FBC_AFBC_V1: { + vframe->ColorType |= VPU_OUTPUT_FORMAT_FBC_AFBC_V1; + } break; + case MPP_FRAME_FBC_AFBC_V2: { + vframe->ColorType |= VPU_OUTPUT_FORMAT_FBC_AFBC_V2; + } break; + default: { + } break; + } + + switch (colorTrc) { + case MPP_FRAME_TRC_SMPTEST2084: { + vframe->ColorType |= VPU_OUTPUT_FORMAT_DYNCRANGE_HDR10; //HDR10 + } break; + case MPP_FRAME_TRC_ARIB_STD_B67: { + vframe->ColorType |= VPU_OUTPUT_FORMAT_DYNCRANGE_HDR_HLG; //HDR_HLG + } break; + default: { + } break; + } + + if (buf) { + MppBufferImpl *p = (MppBufferImpl*)buf; + void *ptr = (p->mode == MPP_BUFFER_INTERNAL) ? + mpp_buffer_get_ptr(buf) : NULL; + RK_S32 fd = mpp_buffer_get_fd(buf); + + vframe->FrameBusAddr[0] = fd; + vframe->FrameBusAddr[1] = fd; + vframe->vpumem.vir_addr = (RK_U32*)ptr; + vframe->vpumem.phy_addr = fd; + + vframe->vpumem.size = vframe->FrameWidth * vframe->FrameHeight * 3 / 2; + vframe->vpumem.offset = (RK_U32*)buf; + } } -RK_S32 VpuApi::encoder_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm) +static void setup_video_frame_meta(VideoFrame_t *videoFrame, MppFrame mframe) { - mpp_log_f("in\n"); - (void)ctx; - (void)aEncInStrm; - mpp_log_f("ok\n"); - return 0; + if (mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_MIXED) { + MppMeta meta = NULL; + RK_S32 yOffset = 0; + RK_S32 uvOffset = 0; + + meta = mpp_frame_get_meta(mframe); + mpp_meta_get_s32(meta, KEY_DEC_TBN_Y_OFFSET, &yOffset); + mpp_meta_get_s32(meta, KEY_DEC_TBN_UV_OFFSET, &uvOffset); + if (yOffset && uvOffset) { + videoFrame->thumbInfo.enable = 1; + videoFrame->thumbInfo.yOffset = yOffset; + videoFrame->thumbInfo.uvOffset = uvOffset; + } else { + videoFrame->thumbInfo.enable = 0; + } + } + + if (MPP_FRAME_FMT_IS_HDR(mpp_frame_get_fmt(mframe))) { + MppMeta meta = NULL; + RK_S32 offset = 0; + RK_S32 size = 0; + + meta = mpp_frame_get_meta(mframe); + mpp_meta_get_s32(meta, KEY_HDR_META_OFFSET, &offset); + mpp_meta_get_s32(meta, KEY_HDR_META_SIZE, &size); + videoFrame->hdrInfo.isHdr = 1; + videoFrame->hdrInfo.offset = offset; + videoFrame->hdrInfo.size = size; + } + + videoFrame->viewId = mpp_frame_get_viewid(mframe); } -RK_S32 VpuApi::encoder_getstream(VpuCodecContext *ctx, EncoderOut_t *aEncOut) +RK_S32 VpuApiLegacy::decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut) { - mpp_log_f("in\n"); - (void)ctx; - (void)aEncOut; - mpp_log_f("ok\n"); - return 0; + MPP_RET ret = MPP_OK; + MppFrame mframe = NULL; + MppPacket packet = NULL; + + vpu_api_dbg_func("enter\n"); + + if (ctx->videoCoding == OMX_RK_VIDEO_CodingMJPEG) { + MppTask task = NULL; + + if (!init_ok) { + mpp_err("init failed!\n"); + return VPU_API_ERR_VPU_CODEC_INIT; + } + + /* check input param */ + if (!pkt || !aDecOut) { + mpp_err("invalid input %p and output %p\n", pkt, aDecOut); + return VPU_API_ERR_UNKNOW; + } + + if (pkt->size <= 0) { + mpp_err("invalid input size %d\n", pkt->size); + return VPU_API_ERR_UNKNOW; + } + + /* try import input buffer and output buffer */ + RK_S32 fd = -1; + RK_U32 width = ctx->width; + RK_U32 height = ctx->height; + RK_U32 hor_stride = MPP_ALIGN(width, 16); + RK_U32 ver_stride = MPP_ALIGN(height, 16); + MppBuffer str_buf = NULL; /* input */ + MppBuffer pic_buf = NULL; /* output */ + + ret = mpp_frame_init(&mframe); + if (MPP_OK != ret) { + mpp_err_f("mpp_frame_init failed\n"); + goto DECODE_OUT; + } + + fd = (RK_S32)(pkt->pts & 0xffffffff); + if (fd_input < 0) { + fd_input = is_valid_dma_fd(fd); + } + + if (fd_input) { + MppBufferInfo inputCommit; + + memset(&inputCommit, 0, sizeof(inputCommit)); + inputCommit.type = MPP_BUFFER_TYPE_ION; + inputCommit.size = pkt->size; + inputCommit.fd = fd; + + ret = mpp_buffer_import(&str_buf, &inputCommit); + if (ret) { + mpp_err_f("import input picture buffer failed\n"); + goto DECODE_OUT; + } + } else { + if (NULL == pkt->data) { + ret = MPP_ERR_NULL_PTR; + goto DECODE_OUT; + } + + ret = mpp_buffer_get(memGroup, &str_buf, pkt->size); + if (ret) { + mpp_err_f("allocate input picture buffer failed\n"); + goto DECODE_OUT; + } + memcpy((RK_U8*) mpp_buffer_get_ptr(str_buf), pkt->data, pkt->size); + } + + fd = (RK_S32)(aDecOut->timeUs & 0xffffffff); + if (fd_output < 0) { + fd_output = is_valid_dma_fd(fd); + } + + if (fd_output) { + MppBufferInfo outputCommit; + + memset(&outputCommit, 0, sizeof(outputCommit)); + /* in order to avoid interface change use space in output to transmit information */ + outputCommit.type = MPP_BUFFER_TYPE_ION; + outputCommit.fd = fd; + outputCommit.size = width * height * 3 / 2; + outputCommit.ptr = (void*)aDecOut->data; + + ret = mpp_buffer_import(&pic_buf, &outputCommit); + if (ret) { + mpp_err_f("import output stream buffer failed\n"); + goto DECODE_OUT; + } + } else { + ret = mpp_buffer_get(memGroup, &pic_buf, hor_stride * ver_stride * 3 / 2); + if (ret) { + mpp_err_f("allocate output stream buffer failed\n"); + goto DECODE_OUT; + } + } + + mpp_packet_init_with_buffer(&packet, str_buf); /* input */ + mpp_frame_set_buffer(mframe, pic_buf); /* output */ + + vpu_api_dbg_func("mpp import input fd %d output fd %d", + mpp_buffer_get_fd(str_buf), mpp_buffer_get_fd(pic_buf)); + + ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK); + if (ret) { + mpp_err("mpp input poll failed\n"); + goto DECODE_OUT; + } + + ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task); + if (ret) { + mpp_err("mpp task input dequeue failed\n"); + goto DECODE_OUT; + } + + mpp_task_meta_set_packet(task, KEY_INPUT_PACKET, packet); + mpp_task_meta_set_frame (task, KEY_OUTPUT_FRAME, mframe); + + ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task); + if (ret) { + mpp_err("mpp task input enqueue failed\n"); + goto DECODE_OUT; + } + + pkt->size = 0; + task = NULL; + + ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK); + if (ret) { + mpp_err("mpp output poll failed\n"); + goto DECODE_OUT; + } + + ret = mpi->dequeue(mpp_ctx, MPP_PORT_OUTPUT, &task); + if (ret) { + mpp_err("ret %d mpp task output dequeue failed\n", ret); + goto DECODE_OUT; + } + + if (task) { + MppFrame frame_out = NULL; + + mpp_task_meta_get_frame(task, KEY_OUTPUT_FRAME, &frame_out); + mpp_assert(frame_out == mframe); + vpu_api_dbg_func("decoded frame %d\n", frame_count); + frame_count++; + + ret = mpi->enqueue(mpp_ctx, MPP_PORT_OUTPUT, task); + if (ret) { + mpp_err("mpp task output enqueue failed\n"); + goto DECODE_OUT; + } + task = NULL; + } + + // copy decoded frame into output buffer, and set outpub frame size + if (mframe != NULL) { + MppBuffer buf_out = mpp_frame_get_buffer(mframe); + size_t len = mpp_buffer_get_size(buf_out); + aDecOut->size = len; + + if (fd_output) { + mpp_log_f("fd for output is invalid!\n"); + // TODO: check frame format and allocate correct buffer + aDecOut->data = mpp_malloc(RK_U8, width * height * 3 / 2); + memcpy(aDecOut->data, (RK_U8*) mpp_buffer_get_ptr(pic_buf), aDecOut->size); + } + + vpu_api_dbg_func("get frame %p size %d\n", mframe, len); + + mpp_frame_deinit(&mframe); + } else { + mpp_log("outputPacket is NULL!"); + } + + DECODE_OUT: + if (str_buf) { + mpp_buffer_put(str_buf); + str_buf = NULL; + } + + if (pic_buf) { + mpp_buffer_put(pic_buf); + pic_buf = NULL; + } + } else { + mpp_packet_init(&packet, pkt->data, pkt->size); + mpp_packet_set_pts(packet, pkt->pts); + if (pkt->nFlags & OMX_BUFFERFLAG_EOS) { + mpp_packet_set_eos(packet); + } + + vpu_api_dbg_input("input size %-6d flag %x pts %lld\n", + pkt->size, pkt->nFlags, pkt->pts); + + ret = mpi->decode(mpp_ctx, packet, &mframe); + if (MPP_OK == ret) { + pkt->size = 0; + } + if (ret || NULL == mframe) { + aDecOut->size = 0; + } else { + VPU_FRAME *vframe = NULL; + MppBuffer buf = mpp_frame_get_buffer(mframe); + + if (dec_out_frm_struct_type) { + VideoFrame_t *videoFrame = (VideoFrame_t *)aDecOut->data; + vframe = &videoFrame->vpuFrame; + memset(videoFrame, 0, sizeof(VideoFrame_t)); + aDecOut->size = sizeof(VideoFrame_t); + setup_video_frame_meta(videoFrame, mframe); + } else { + vframe = (VPU_FRAME *)aDecOut->data; + memset(vframe, 0, sizeof(VPU_FRAME)); + aDecOut->size = sizeof(VPU_FRAME); + } + + setup_VPU_FRAME_from_mpp_frame(ctx, vframe, mframe); + + aDecOut->timeUs = mpp_frame_get_pts(mframe); + frame_count++; + + if (mpp_frame_get_eos(mframe)) { + set_eos = 1; + if (buf == NULL) { + aDecOut->size = 0; + } + } + if (vpu_api_debug & VPU_API_DBG_OUTPUT) { + mpp_log("get one frame pts %lld, fd 0x%x, poc %d, errinfo %x, discard %d, eos %d, verr %d", + aDecOut->timeUs, + ((buf) ? (mpp_buffer_get_fd(buf)) : (-1)), + mpp_frame_get_poc(mframe), + mpp_frame_get_errinfo(mframe), + mpp_frame_get_discard(mframe), + mpp_frame_get_eos(mframe), vframe->ErrorInfo); + } + + /* + * IMPORTANT: mframe is malloced from mpi->decode_get_frame + * So we need to deinit mframe here. But the buffer in the frame should not be free with mframe. + * Because buffer need to be set to vframe->vpumem.offset and send to display. + * The we have to clear the buffer pointer in mframe then release mframe. + */ + mpp_frame_deinit(&mframe); + } + } + + if (packet) + mpp_packet_deinit(&packet); + + if (mframe) + mpp_frame_deinit(&mframe); + + vpu_api_dbg_func("leave ret %d\n", ret); + return ret; } -RK_S32 VpuApi::perform(RK_U32 cmd, RK_U32 *data) +RK_S32 VpuApiLegacy::decode_sendstream(VideoPacket_t *pkt) { - mpp_log_f("in\n"); - (void)cmd; - (void)data; - mpp_log_f("ok\n"); + vpu_api_dbg_func("enter\n"); + + RK_S32 ret = MPP_OK; + MppPacket mpkt = NULL; + + if (!init_ok) { + return VPU_API_ERR_VPU_CODEC_INIT; + } + + mpp_packet_init(&mpkt, pkt->data, pkt->size); + mpp_packet_set_pts(mpkt, pkt->pts); + if (pkt->nFlags & OMX_BUFFERFLAG_EOS) { + mpp_packet_set_eos(mpkt); + } + + vpu_api_dbg_input("input size %-6d flag %x pts %lld\n", + pkt->size, pkt->nFlags, pkt->pts); + + ret = mpi->decode_put_packet(mpp_ctx, mpkt); + if (ret == MPP_OK) { + pkt->size = 0; + } else if (mInputTimeOutMs == 0) { + /* reduce cpu overhead here */ + msleep(1); + } + + mpp_packet_deinit(&mpkt); + + vpu_api_dbg_func("leave ret %d\n", ret); + /* NOTE: always return success for old player compatibility */ + return MPP_OK; +} + +RK_S32 VpuApiLegacy::decode_getoutframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut) +{ + RK_S32 ret = 0; + VPU_FRAME *vframe = NULL; + MppFrame mframe = NULL; + + vpu_api_dbg_func("enter\n"); + + if (!init_ok) { + return VPU_API_ERR_VPU_CODEC_INIT; + } + + if (NULL == mpi) { + aDecOut->size = 0; + return 0; + } + + if (set_eos) { + aDecOut->size = 0; + mEosSet = 1; + return VPU_API_EOS_STREAM_REACHED; + } + + ret = mpi->decode_get_frame(mpp_ctx, &mframe); + if (ret || NULL == mframe) { + aDecOut->size = 0; + } else { + MppBuffer buf = mpp_frame_get_buffer(mframe); + + if (dec_out_frm_struct_type) { + VideoFrame_t *videoFrame = (VideoFrame_t *)aDecOut->data; + vframe = &videoFrame->vpuFrame; + memset(videoFrame, 0, sizeof(VideoFrame_t)); + aDecOut->size = sizeof(VideoFrame_t); + setup_video_frame_meta(videoFrame, mframe); + } else { + vframe = (VPU_FRAME *)aDecOut->data; + memset(vframe, 0, sizeof(VPU_FRAME)); + aDecOut->size = sizeof(VPU_FRAME); + } + + setup_VPU_FRAME_from_mpp_frame(ctx, vframe, mframe); + + aDecOut->timeUs = mpp_frame_get_pts(mframe); + frame_count++; + + if (mpp_frame_get_eos(mframe) && !mpp_frame_get_info_change(mframe)) { + set_eos = 1; + if (buf == NULL) { + aDecOut->size = 0; + mEosSet = 1; + ret = VPU_API_EOS_STREAM_REACHED; + } else { + aDecOut->nFlags |= VPU_API_EOS_STREAM_REACHED; + } + } + if (vpu_api_debug & VPU_API_DBG_OUTPUT) { + mpp_log("get one frame pts %lld, fd 0x%x, poc %d, errinfo %x, discard %d, eos %d, verr %d", + aDecOut->timeUs, + ((buf) ? (mpp_buffer_get_fd(buf)) : (-1)), + mpp_frame_get_poc(mframe), + mpp_frame_get_errinfo(mframe), + mpp_frame_get_discard(mframe), + mpp_frame_get_eos(mframe), vframe->ErrorInfo); + } + + /* + * IMPORTANT: mframe is malloced from mpi->decode_get_frame + * So we need to deinit mframe here. But the buffer in the frame should not be free with mframe. + * Because buffer need to be set to vframe->vpumem.offset and send to display. + * The we have to clear the buffer pointer in mframe then release mframe. + */ + mpp_frame_deinit(&mframe); + } + + vpu_api_dbg_func("leave ret %d\n", ret); + + return ret; +} + +RK_S32 VpuApiLegacy::encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut) +{ + MPP_RET ret = MPP_OK; + MppTask task = NULL; + vpu_api_dbg_func("enter\n"); + + if (!init_ok) + return VPU_API_ERR_VPU_CODEC_INIT; + + /* check input param */ + if (!aEncInStrm || !aEncOut) { + mpp_err("invalid input %p and output %p\n", aEncInStrm, aEncOut); + return VPU_API_ERR_UNKNOW; + } + + if (NULL == aEncInStrm->buf || 0 == aEncInStrm->size) { + mpp_err("invalid input buffer %p size %d\n", aEncInStrm->buf, aEncInStrm->size); + return VPU_API_ERR_UNKNOW; + } + + /* try import input buffer and output buffer */ + RK_S32 fd = -1; + RK_U32 width = ctx->width; + RK_U32 height = ctx->height; + RK_U32 hor_stride = MPP_ALIGN(width, 16); + RK_U32 ver_stride = MPP_ALIGN(height, 16); + MppFrame frame = NULL; + MppPacket packet = NULL; + MppBuffer pic_buf = NULL; + MppBuffer str_buf = NULL; + + ret = mpp_frame_init(&frame); + if (MPP_OK != ret) { + mpp_err_f("mpp_frame_init failed\n"); + goto ENCODE_OUT; + } + + mpp_frame_set_width(frame, width); + mpp_frame_set_height(frame, height); + mpp_frame_set_ver_stride(frame, ver_stride); + switch (format & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420P : + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_VU : { + mpp_frame_set_hor_stride(frame, hor_stride); + } break; + case MPP_FMT_RGB565: + case MPP_FMT_BGR565: + case MPP_FMT_RGB555: + case MPP_FMT_BGR555: { + mpp_frame_set_hor_stride(frame, hor_stride * 2); + } break; + case MPP_FMT_RGB888 : + case MPP_FMT_BGR888 : { + mpp_frame_set_hor_stride(frame, hor_stride * 3); + } break; + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGBA8888 : { + mpp_frame_set_hor_stride(frame, hor_stride * 4); + } break; + default: { + mpp_err("unsupport format 0x%x\n", format & MPP_FRAME_FMT_MASK); + } break; + } + mpp_frame_set_fmt(frame, (MppFrameFormat)(format & MPP_FRAME_FMT_MASK)); + if (aEncInStrm->nFlags) { + mpp_log_f("found eos\n"); + mpp_frame_set_eos(frame, 1); + } + + fd = aEncInStrm->bufPhyAddr; + if (fd_input < 0) { + fd_input = is_valid_dma_fd(fd); + } + if (fd_input) { + MppBufferInfo inputCommit; + + memset(&inputCommit, 0, sizeof(inputCommit)); + inputCommit.type = MPP_BUFFER_TYPE_ION; + inputCommit.size = aEncInStrm->size; + inputCommit.fd = fd; + + ret = mpp_buffer_import(&pic_buf, &inputCommit); + if (ret) { + mpp_err_f("import input picture buffer failed\n"); + goto ENCODE_OUT; + } + } else { + if (NULL == aEncInStrm->buf) { + ret = MPP_ERR_NULL_PTR; + goto ENCODE_OUT; + } + + ret = mpp_buffer_get(memGroup, &pic_buf, aEncInStrm->size); + if (ret) { + mpp_err_f("allocate input picture buffer failed\n"); + goto ENCODE_OUT; + } + memcpy((RK_U8*) mpp_buffer_get_ptr(pic_buf), aEncInStrm->buf, aEncInStrm->size); + } + + fd = (RK_S32)(aEncOut->timeUs & 0xffffffff); + + if (fd_output < 0) { + fd_output = is_valid_dma_fd(fd); + } + if (fd_output) { + RK_S32 *tmp = (RK_S32*)(&aEncOut->timeUs); + MppBufferInfo outputCommit; + + memset(&outputCommit, 0, sizeof(outputCommit)); + /* in order to avoid interface change use space in output to transmit information */ + outputCommit.type = MPP_BUFFER_TYPE_ION; + outputCommit.fd = fd; + outputCommit.size = tmp[1]; + outputCommit.ptr = (void*)aEncOut->data; + + ret = mpp_buffer_import(&str_buf, &outputCommit); + if (ret) { + mpp_err_f("import output stream buffer failed\n"); + goto ENCODE_OUT; + } + } else { + ret = mpp_buffer_get(memGroup, &str_buf, hor_stride * ver_stride); + if (ret) { + mpp_err_f("allocate output stream buffer failed\n"); + goto ENCODE_OUT; + } + } + + mpp_frame_set_buffer(frame, pic_buf); + mpp_packet_init_with_buffer(&packet, str_buf); + mpp_packet_set_length(packet, 0); + + vpu_api_dbg_func("mpp import input fd %d output fd %d", + mpp_buffer_get_fd(pic_buf), mpp_buffer_get_fd(str_buf)); + + ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK); + if (ret) { + mpp_err("mpp input poll failed\n"); + goto ENCODE_OUT; + } + + ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task); + if (ret) { + mpp_err("mpp task input dequeue failed\n"); + goto ENCODE_OUT; + } + if (task == NULL) { + mpp_err("mpi dequeue from MPP_PORT_INPUT fail, task equal with NULL!"); + goto ENCODE_OUT; + } + + mpp_task_meta_set_frame (task, KEY_INPUT_FRAME, frame); + mpp_task_meta_set_packet(task, KEY_OUTPUT_PACKET, packet); + + ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task); + if (ret) { + mpp_err("mpp task input enqueue failed\n"); + goto ENCODE_OUT; + } + task = NULL; + + ret = mpi->poll(mpp_ctx, MPP_PORT_OUTPUT, MPP_POLL_BLOCK); + if (ret) { + mpp_err("mpp output poll failed\n"); + goto ENCODE_OUT; + } + + ret = mpi->dequeue(mpp_ctx, MPP_PORT_OUTPUT, &task); + if (ret) { + mpp_err("ret %d mpp task output dequeue failed\n", ret); + goto ENCODE_OUT; + } + + mpp_assert(task); + + if (task) { + MppFrame frame_out = NULL; + MppFrame packet_out = NULL; + + mpp_task_meta_get_packet(task, KEY_OUTPUT_PACKET, &packet_out); + + mpp_assert(packet_out == packet); + vpu_api_dbg_func("encoded frame %d\n", frame_count); + frame_count++; + + ret = mpi->enqueue(mpp_ctx, MPP_PORT_OUTPUT, task); + if (ret) { + mpp_err("mpp task output enqueue failed\n"); + goto ENCODE_OUT; + } + task = NULL; + + ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK); + if (ret) { + mpp_err("mpp input poll failed\n"); + goto ENCODE_OUT; + } + + // dequeue task from MPP_PORT_INPUT + ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task); + if (ret) { + mpp_log_f("failed to dequeue from input port ret %d\n", ret); + goto ENCODE_OUT; + } + mpp_assert(task); + ret = mpp_task_meta_get_frame(task, KEY_INPUT_FRAME, &frame_out); + mpp_assert(frame_out == frame); + ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task); + if (ret) { + mpp_err("mpp task output enqueue failed\n"); + goto ENCODE_OUT; + } + task = NULL; + } + + // copy encoded stream into output buffer, and set output stream size + if (packet) { + RK_U32 eos = mpp_packet_get_eos(packet); + RK_S64 pts = mpp_packet_get_pts(packet); + size_t length = mpp_packet_get_length(packet); + MppMeta meta = mpp_packet_get_meta(packet); + RK_S32 is_intra = 0; + + if (!fd_output) { + RK_U8 *src = (RK_U8 *)mpp_packet_get_data(packet); + size_t buffer = MPP_ALIGN(length, SZ_4K); + + aEncOut->data = mpp_malloc(RK_U8, buffer); + + if (ctx->videoCoding == OMX_RK_VIDEO_CodingAVC) { + // remove first 00 00 00 01 + length -= 4; + memcpy(aEncOut->data, src + 4, length); + } else { + memcpy(aEncOut->data, src, length); + } + } + + mpp_meta_get_s32(meta, KEY_OUTPUT_INTRA, &is_intra); + + aEncOut->size = (RK_S32)length; + aEncOut->timeUs = pts; + aEncOut->keyFrame = is_intra; + + vpu_api_dbg_output("get packet %p size %d pts %lld keyframe %d eos %d\n", + packet, length, pts, aEncOut->keyFrame, eos); + + mpp_packet_deinit(&packet); + } else { + mpp_log("outputPacket is NULL!"); + } + +ENCODE_OUT: + if (pic_buf) { + mpp_buffer_put(pic_buf); + pic_buf = NULL; + } + + if (str_buf) { + mpp_buffer_put(str_buf); + str_buf = NULL; + } + + if (frame) + mpp_frame_deinit(&frame); + + if (packet) + mpp_packet_deinit(&packet); + + vpu_api_dbg_func("leave ret %d\n", ret); + + return ret; +} + +RK_S32 VpuApiLegacy::encoder_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm) +{ + RK_S32 ret = 0; + vpu_api_dbg_func("enter\n"); + + RK_U32 width = ctx->width; + RK_U32 height = ctx->height; + RK_U32 hor_stride = MPP_ALIGN(width, 16); + RK_U32 ver_stride = MPP_ALIGN(height, 8); + RK_S64 pts = aEncInStrm->timeUs; + RK_S32 fd = aEncInStrm->bufPhyAddr; + RK_U32 size = aEncInStrm->size; + + /* try import input buffer and output buffer */ + MppFrame frame = NULL; + + ret = mpp_frame_init(&frame); + if (MPP_OK != ret) { + mpp_err_f("mpp_frame_init failed\n"); + goto FUNC_RET; + } + + mpp_frame_set_width(frame, width); + mpp_frame_set_height(frame, height); + mpp_frame_set_ver_stride(frame, ver_stride); + mpp_frame_set_pts(frame, pts); + switch (format & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420P : + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_VU : { + mpp_frame_set_hor_stride(frame, hor_stride); + } break; + case MPP_FMT_RGB565: + case MPP_FMT_BGR565: + case MPP_FMT_RGB555: + case MPP_FMT_BGR555: { + mpp_frame_set_hor_stride(frame, hor_stride * 2); + } break; + case MPP_FMT_RGB888 : + case MPP_FMT_BGR888 : { + mpp_frame_set_hor_stride(frame, hor_stride * 3); + } break; + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGBA8888 : { + mpp_frame_set_hor_stride(frame, hor_stride * 4); + } break; + default: { + mpp_err("unsupport format 0x%x\n", format & MPP_FRAME_FMT_MASK); + } break; + } + mpp_frame_set_fmt(frame, (MppFrameFormat)(format & MPP_FRAME_FMT_MASK)); + if (aEncInStrm->nFlags) { + mpp_log_f("found eos true\n"); + mpp_frame_set_eos(frame, 1); + } + + if (size <= 0) { + mpp_frame_set_buffer(frame, NULL); + if (!aEncInStrm->nFlags) + mpp_err_f("found empty frame without eos flag set!\n"); + goto PUT_FRAME; + } + + if (fd_input < 0) { + fd_input = is_valid_dma_fd(fd); + } + if (fd_input) { + MppBufferInfo inputCommit; + + memset(&inputCommit, 0, sizeof(inputCommit)); + inputCommit.type = MPP_BUFFER_TYPE_ION; + inputCommit.size = size; + inputCommit.fd = fd; + if (size > 0) { + MppBuffer buffer = NULL; + ret = mpp_buffer_import(&buffer, &inputCommit); + if (ret) { + mpp_err_f("import input picture buffer failed\n"); + goto FUNC_RET; + } + mpp_frame_set_buffer(frame, buffer); + mpp_buffer_put(buffer); + buffer = NULL; + } + } else { + RK_U32 align_size = 0; + + if (NULL == aEncInStrm->buf) { + ret = MPP_ERR_NULL_PTR; + goto FUNC_RET; + } + if (format >= MPP_FMT_YUV420SP && format < MPP_FMT_YUV_BUTT) { + align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 3 / 2; + } else if (format >= MPP_FMT_YUV420SP_VU && format < MPP_FMT_YUV_BUTT) { + align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 3 / 2; + } else if (format >= MPP_FMT_RGB565 && format < MPP_FMT_BGR888) { + align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 3; + } else if (format >= MPP_FMT_RGB101010 && format < MPP_FMT_RGB_BUTT) { + align_size = hor_stride * MPP_ALIGN(ver_stride, 16) * 4; + } else { + mpp_err_f("unsupport input format:%d\n", format); + ret = MPP_NOK; + goto FUNC_RET; + } + if (align_size > 0) { + MppBuffer buffer = NULL; + ret = mpp_buffer_get(memGroup, &buffer, align_size); + if (ret) { + mpp_err_f("allocate input picture buffer failed\n"); + goto FUNC_RET; + } + copy_align_raw_buffer_to_dest((RK_U8 *)mpp_buffer_get_ptr(buffer), + aEncInStrm->buf, width, height, format); + mpp_frame_set_buffer(frame, buffer); + mpp_buffer_put(buffer); + buffer = NULL; + } + } + +PUT_FRAME: + + vpu_api_dbg_input("w %d h %d input fd %d size %d pts %lld, flag %d \n", + width, height, fd, size, aEncInStrm->timeUs, aEncInStrm->nFlags); + if (mlvec) { + MppMeta meta = mpp_frame_get_meta(frame); + + vpu_api_mlvec_set_dy_cfg(mlvec, &mlvec_dy_cfg, meta); + } + + ret = mpi->encode_put_frame(mpp_ctx, frame); + if (ret) + mpp_err_f("encode_put_frame ret %d\n", ret); + else + aEncInStrm->size = 0; + +FUNC_RET: + if (frame) + mpp_frame_deinit(&frame); + + vpu_api_dbg_func("leave ret %d\n", ret); + return ret; +} + +RK_S32 VpuApiLegacy::encoder_getstream(VpuCodecContext *ctx, EncoderOut_t *aEncOut) +{ + RK_S32 ret = 0; + MppPacket packet = NULL; + vpu_api_dbg_func("enter\n"); + + ret = mpi->encode_get_packet(mpp_ctx, &packet); + if (ret) { + mpp_err_f("encode_get_packet failed ret %d\n", ret); + goto FUNC_RET; + } + if (packet) { + RK_U8 *src = (RK_U8 *)mpp_packet_get_data(packet); + RK_U32 eos = mpp_packet_get_eos(packet); + RK_S64 pts = mpp_packet_get_pts(packet); + size_t length = mpp_packet_get_length(packet); + MppMeta meta = mpp_packet_get_meta(packet); + RK_S32 is_intra = 0; + + RK_U32 offset = 0; + if (ctx->videoCoding == OMX_RK_VIDEO_CodingAVC) { + offset = 4; + length = (length > offset) ? (length - offset) : 0; + } + aEncOut->data = NULL; + if (length > 0) { + aEncOut->data = mpp_calloc(RK_U8, MPP_ALIGN(length + 16, SZ_4K)); + if (aEncOut->data) + memcpy(aEncOut->data, src + offset, length); + } + + mpp_meta_get_s32(meta, KEY_OUTPUT_INTRA, &is_intra); + + aEncOut->size = (RK_S32)length; + aEncOut->timeUs = pts; + aEncOut->keyFrame = is_intra; + + vpu_api_dbg_output("get packet %p size %d pts %lld keyframe %d eos %d\n", + packet, length, pts, aEncOut->keyFrame, eos); + + mEosSet = eos; + mpp_packet_deinit(&packet); + } else { + aEncOut->size = 0; + vpu_api_dbg_output("get NULL packet, eos %d\n", mEosSet); + if (mEosSet) + ret = -1; + } + +FUNC_RET: + vpu_api_dbg_func("leave ret %d\n", ret); + return ret; +} + +RK_S32 VpuApiLegacy::perform(PerformCmd cmd, RK_S32 *data) +{ + vpu_api_dbg_func("enter\n"); + switch (cmd) { + case INPUT_FORMAT_MAP : { + EncInputPictureType vpu_frame_fmt = *(EncInputPictureType *)data; + MppFrameFormat mpp_frame_fmt = vpu_pic_type_remap_to_mpp(vpu_frame_fmt); + *(MppFrameFormat *)data = mpp_frame_fmt; + } break; + default: + mpp_err("cmd can not match with any option!"); + break; + } + vpu_api_dbg_func("leave\n"); return 0; } -RK_S32 VpuApi::control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param) +static RK_S32 frameReadyCallback(void *ctx, void *mppCtx, RK_S32 cmd, void *mppFrame) { - mpp_log_f("in\n"); - (void)ctx; + (void)mppCtx; (void)cmd; - (void)param; - mpp_log_f("ok\n"); - return 0; + (void)mppFrame; + VpuApiLegacy *vpuApi = (VpuApiLegacy *)ctx; + RK_S32 ret = 0; + + vpu_api_dbg_func("enter\n"); + + if (!vpuApi) { + return ret; + } + + if (vpuApi->frm_rdy_cb.cb) { + ret = vpuApi->frm_rdy_cb.cb(vpuApi->frm_rdy_cb.cbCtx); + } + + vpu_api_dbg_func("leave ret %d\n", ret); + + return ret; +} + +RK_S32 VpuApiLegacy::control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param) +{ + vpu_api_dbg_func("enter cmd 0x%x param %p\n", cmd, param); + + if (mpi == NULL && !init_ok) { + return 0; + } + + MpiCmd mpicmd = MPI_CMD_BUTT; + switch (cmd) { + case VPU_API_ENABLE_DEINTERLACE : { + mpicmd = MPP_DEC_SET_ENABLE_DEINTERLACE; + } break; + case VPU_API_ENC_SETCFG : { + MppCodingType coding = (MppCodingType)ctx->videoCoding; + + memcpy(&enc_param, param, sizeof(enc_param)); + return vpu_api_set_enc_cfg(mpp_ctx, mpi, enc_cfg, coding, format, &enc_param); + } break; + case VPU_API_ENC_GETCFG : { + memcpy(param, &enc_param, sizeof(enc_param)); + return mpi->control(mpp_ctx, MPP_ENC_GET_CFG, enc_cfg);; + } break; + case VPU_API_ENC_SETFORMAT : { + EncInputPictureType type = *((EncInputPictureType *)param); + MppCodingType coding = (MppCodingType)ctx->videoCoding; + MppFrameFormat old_fmt = format; + + format = vpu_pic_type_remap_to_mpp(type); + if (old_fmt != format) + return vpu_api_set_enc_cfg(mpp_ctx, mpi, enc_cfg, coding, format, &enc_param); + else + return 0; + } break; + case VPU_API_ENC_SETIDRFRAME : { + mpicmd = MPP_ENC_SET_IDR_FRAME; + } break; + case VPU_API_SET_VPUMEM_CONTEXT: { + mpicmd = MPP_DEC_SET_EXT_BUF_GROUP; + } break; + case VPU_API_USE_PRESENT_TIME_ORDER: { + mpicmd = MPP_DEC_SET_PRESENT_TIME_ORDER; + } break; + case VPU_API_SET_INFO_CHANGE: { + mpicmd = MPP_DEC_SET_INFO_CHANGE_READY; + } break; + case VPU_API_USE_FAST_MODE: { + mpicmd = MPP_DEC_SET_PARSER_FAST_MODE; + } break; + case VPU_API_DEC_GET_STREAM_COUNT: { + mpicmd = MPP_DEC_GET_STREAM_COUNT; + } break; + case VPU_API_GET_VPUMEM_USED_COUNT: { + mpicmd = MPP_DEC_GET_VPUMEM_USED_COUNT; + } break; + case VPU_API_SET_OUTPUT_BLOCK: { + mpicmd = MPP_SET_OUTPUT_TIMEOUT; + if (param) { + RK_S32 timeout = *((RK_S32*)param); + + if (timeout) { + if (timeout < 0) + mpp_log("set output mode to block\n"); + else + mpp_log("set output timeout %d ms\n", timeout); + } else { + mpp_log("set output mode to non-block\n"); + } + } + } break; + case VPU_API_SET_INPUT_BLOCK: { + mpicmd = MPP_SET_INPUT_TIMEOUT; + if (param) { + RK_S32 timeout = *((RK_S32*)param); + mInputTimeOutMs = timeout; + + if (timeout) { + if (timeout < 0) + mpp_log("set input mode to block\n"); + else + mpp_log("set input timeout %d ms\n", timeout); + } else { + mpp_log("set input mode to non-block\n"); + } + } + } break; + case VPU_API_GET_EOS_STATUS: { + *((RK_S32 *)param) = mEosSet; + mpicmd = MPI_CMD_BUTT; + } break; + case VPU_API_SET_FRAME_INFO: { + mpicmd = MPI_CMD_BUTT; + mpi->control(mpp_ctx, MPP_DEC_SET_FRAME_INFO, (MppParam)frm_info); + } break; + case VPU_API_GET_FRAME_INFO: { + *((VPU_GENERIC *)param) = vpug; + mpicmd = MPI_CMD_BUTT; + } break; + case VPU_API_SET_OUTPUT_MODE: { + mpicmd = MPP_DEC_SET_OUTPUT_FORMAT; + mpp_frame_set_fmt(frm_info, (param) ? (*((MppFrameFormat *)param)) : + (MPP_FMT_YUV420SP)); + } break; + case VPU_API_DEC_EN_FBC_HDR_256_ODD : { + MppCompat *compatItem = NULL; + compatItem = mpp_compat_query_by_id(MPP_COMPAT_DEC_FBC_HDR_256_ODD); + if (compatItem) { + mpp_compat_update(compatItem, 1); + } + } break; + case VPU_API_DEC_OUT_FRM_STRUCT_TYPE: { + dec_out_frm_struct_type = *((RK_S32 *)param); + return 0; + } break; + case VPU_API_DEC_EN_THUMBNAIL: { + RK_S32 ret = 0; + MppDecCfg cfg; + RK_U32 val = *((RK_U32 *)param); + ret = mpp_dec_cfg_init(&cfg); + if (ret) { + return ret; + } + ret = mpi->control(mpp_ctx, MPP_DEC_GET_CFG, cfg); + mpp_dec_cfg_set_u32(cfg, "base:enable_thumbnail", val); + ret = mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg); + mpp_dec_cfg_deinit(cfg); + return ret; + } break; + case VPU_API_DEC_EN_HDR_META: { + RK_S32 ret = 0; + MppDecCfg cfg; + RK_U32 val = *((RK_U32 *)param); + ret = mpp_dec_cfg_init(&cfg); + if (ret) { + return ret; + } + ret = mpi->control(mpp_ctx, MPP_DEC_GET_CFG, cfg); + mpp_dec_cfg_set_u32(cfg, "base:enable_hdr_meta", val); + ret = mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg); + mpp_dec_cfg_deinit(cfg); + return ret; + } break; + case VPU_API_SET_FRM_RDY_CB: { + RK_S32 ret = 0; + MppDecCfg cfg; + FrameRdyCB *cb = (FrameRdyCB *)param; + + ret = mpp_dec_cfg_init(&cfg); + if (ret) { + return ret; + } + + frm_rdy_cb.cb = cb->cb; + frm_rdy_cb.cbCtx = cb->cbCtx; + mpp_dec_cfg_set_ptr(cfg, "cb:frm_rdy_cb", + frm_rdy_cb.cb ? (void *)frm_rdy_cb.cb : (void *)frameReadyCallback); + mpp_dec_cfg_set_ptr(cfg, "cb:frm_rdy_ctx", frm_rdy_cb.cbCtx); + ret = mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg); + mpp_dec_cfg_deinit(cfg); + return ret; + } break; + case VPU_API_SET_DISABLE_ERROR: { + mpicmd = MPP_DEC_SET_DISABLE_ERROR; + } break; + case VPU_API_SET_DIS_ERR_CLR_MARK: { + mpicmd = MPP_DEC_SET_DIS_ERR_CLR_MARK; + } break; + case VPU_API_SET_IMMEDIATE_OUT: { + mpicmd = MPP_DEC_SET_IMMEDIATE_OUT; + } break; + case VPU_API_ENC_SET_VEPU22_CFG: { + mpicmd = MPP_ENC_SET_CODEC_CFG; + } break; + case VPU_API_ENC_GET_VEPU22_CFG: { + mpicmd = MPP_ENC_GET_CODEC_CFG; + } break; + case VPU_API_ENC_SET_VEPU22_CTU_QP: { + mpicmd = MPP_ENC_SET_CTU_QP; + } break; + case VPU_API_ENC_SET_VEPU22_ROI: { + mpicmd = MPP_ENC_SET_ROI_CFG; + } break; + case VPU_API_ENC_MPP_SETCFG: { + mpicmd = MPP_ENC_SET_CFG; + } break; + case VPU_API_ENC_MPP_GETCFG: { + *((MppEncCfg *)param) = enc_cfg; + return 0; + } break; + case VPU_API_ENC_SET_MAX_TID: { + RK_S32 max_tid = *(RK_S32 *)param; + + vpu_api_dbg_ctrl("VPU_API_ENC_SET_MAX_TID %d\n", max_tid); + mlvec_dy_cfg.max_tid = max_tid; + mlvec_dy_cfg.updated |= VPU_API_ENC_MAX_TID_UPDATED; + + if (mlvec) + vpu_api_mlvec_set_dy_max_tid(mlvec, max_tid); + + return 0; + } break; + case VPU_API_ENC_SET_MARK_LTR: { + RK_S32 mark_ltr = *(RK_S32 *)param; + + vpu_api_dbg_ctrl("VPU_API_ENC_SET_MARK_LTR %d\n", mark_ltr); + + mlvec_dy_cfg.mark_ltr = mark_ltr; + if (mark_ltr >= 0) + mlvec_dy_cfg.updated |= VPU_API_ENC_MARK_LTR_UPDATED; + + return 0; + } break; + case VPU_API_ENC_SET_USE_LTR: { + RK_S32 use_ltr = *(RK_S32 *)param; + + vpu_api_dbg_ctrl("VPU_API_ENC_SET_USE_LTR %d\n", use_ltr); + + mlvec_dy_cfg.use_ltr = use_ltr; + mlvec_dy_cfg.updated |= VPU_API_ENC_USE_LTR_UPDATED; + + return 0; + } break; + case VPU_API_ENC_SET_FRAME_QP: { + RK_S32 frame_qp = *(RK_S32 *)param; + + vpu_api_dbg_ctrl("VPU_API_ENC_SET_FRAME_QP %d\n", frame_qp); + + mlvec_dy_cfg.frame_qp = frame_qp; + mlvec_dy_cfg.updated |= VPU_API_ENC_FRAME_QP_UPDATED; + + return 0; + } break; + case VPU_API_ENC_SET_BASE_LAYER_PID: { + RK_S32 base_layer_pid = *(RK_S32 *)param; + + vpu_api_dbg_ctrl("VPU_API_ENC_SET_BASE_LAYER_PID %d\n", base_layer_pid); + + mlvec_dy_cfg.base_layer_pid = base_layer_pid; + mlvec_dy_cfg.updated |= VPU_API_ENC_BASE_PID_UPDATED; + + return 0; + } break; + case VPU_API_GET_EXTRA_INFO: { + EncoderOut_t *out = (EncoderOut_t *)param; + + vpu_api_dbg_ctrl("VPU_API_GET_EXTRA_INFO\n"); + + if (NULL == enc_hdr_pkt) { + if (NULL == enc_hdr_buf) { + enc_hdr_buf_size = SZ_1K; + enc_hdr_buf = mpp_calloc_size(RK_U8, enc_hdr_buf_size); + } + + if (enc_hdr_buf) + mpp_packet_init(&enc_hdr_pkt, enc_hdr_buf, enc_hdr_buf_size); + } + + mpp_assert(enc_hdr_pkt); + if (enc_hdr_pkt) { + mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, enc_hdr_pkt); + + RK_S32 length = mpp_packet_get_length(enc_hdr_pkt); + void *src = mpp_packet_get_data(enc_hdr_pkt); + + memcpy(out->data, src, length); + out->size = length; + } + return 0; + } break; + case VPU_API_SET_PARSER_SPLIT_MODE: { + mpicmd = MPP_DEC_SET_PARSER_SPLIT_MODE; + } break; + case VPU_API_DEC_EN_MVC: { + mpicmd = MPP_DEC_SET_ENABLE_MVC; + } break; + default: { + } break; + } + + RK_S32 ret = -1; + if (mpicmd < MPI_CMD_BUTT) + ret = mpi->control(mpp_ctx, mpicmd, (MppParam)param); + + vpu_api_dbg_func("leave\n"); + return ret; } diff --git a/mpp/legacy/vpu_api_legacy.h b/mpp/legacy/vpu_api_legacy.h index af228ae4f..7b15226bd 100644 --- a/mpp/legacy/vpu_api_legacy.h +++ b/mpp/legacy/vpu_api_legacy.h @@ -1,49 +1,106 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _VPU_API_H_ -#define _VPU_API_H_ - -#include "vpu_api.h" - -class VpuApi -{ -public: - VpuApi(); - ~VpuApi(); - - RK_S32 init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size); - RK_S32 flush(VpuCodecContext *ctx); - - RK_S32 decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut); - RK_S32 decode_sendstream(VpuCodecContext *ctx, VideoPacket_t *pkt); - RK_S32 decode_getoutframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut); - RK_S32 preProcessPacket(VpuCodecContext *ctx, VideoPacket_t *pkt); - - RK_S32 encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut); - RK_S32 encoder_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm); - RK_S32 encoder_getstream(VpuCodecContext *ctx, EncoderOut_t *aEncOut); - - RK_S32 send_stream(RK_U8* buf, RK_U32 size, RK_S64 timestamp, RK_S32 usePts); - RK_S32 get_frame(DecoderOut_t *aDecOut); - - RK_S32 perform(RK_U32 cmd, RK_U32 *data); - RK_S32 control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param); - -}; - -#endif /*_VPU_API_H_*/ - +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VPU_API_LEGACY_H +#define VPU_API_LEGACY_H + +#include + +#include "vpu_api.h" +#include "rk_mpi.h" +#include "rk_venc_cfg.h" + +#include "vpu_api_mlvec.h" + +#define OMX_BUFFERFLAG_EOS 0x00000001 + +#define VPU_API_DBG_FUNCTION (0x00000001) +#define VPU_API_DBG_INPUT (0x00000010) +#define VPU_API_DBG_OUTPUT (0x00000020) +#define VPU_API_DBG_CONTROL (0x00000040) + +#define vpu_api_dbg(flag, fmt, ...) mpp_dbg(vpu_api_debug, flag, fmt, ## __VA_ARGS__) +#define vpu_api_dbg_f(flag, fmt, ...) mpp_dbg_f(vpu_api_debug, flag, fmt, ## __VA_ARGS__) + +#define vpu_api_dbg_func(fmt, ...) vpu_api_dbg_f(VPU_API_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define vpu_api_dbg_input(fmt, ...) vpu_api_dbg_f(VPU_API_DBG_INPUT, fmt, ## __VA_ARGS__) +#define vpu_api_dbg_output(fmt, ...) vpu_api_dbg_f(VPU_API_DBG_OUTPUT, fmt, ## __VA_ARGS__) +#define vpu_api_dbg_ctrl(fmt, ...) vpu_api_dbg_f(VPU_API_DBG_CONTROL, fmt, ## __VA_ARGS__) + +extern RK_U32 vpu_api_debug; + +typedef enum { + INPUT_FORMAT_MAP, +} PerformCmd; + +class VpuApiLegacy +{ +public: + VpuApiLegacy(); + ~VpuApiLegacy(); + + RK_S32 init(VpuCodecContext *ctx, RK_U8 *extraData, RK_U32 extra_size); + RK_S32 flush(VpuCodecContext *ctx); + + RK_S32 decode(VpuCodecContext *ctx, VideoPacket_t *pkt, DecoderOut_t *aDecOut); + RK_S32 decode_sendstream(VideoPacket_t *pkt); + RK_S32 decode_getoutframe(VpuCodecContext *ctx, DecoderOut_t *aDecOut); + RK_S32 preProcessPacket(VpuCodecContext *ctx, VideoPacket_t *pkt); + + RK_S32 encode(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm, EncoderOut_t *aEncOut); + RK_S32 encoder_sendframe(VpuCodecContext *ctx, EncInputStream_t *aEncInStrm); + RK_S32 encoder_getstream(VpuCodecContext *ctx, EncoderOut_t *aEncOut); + + RK_S32 perform(PerformCmd cmd, RK_S32 *data); + RK_S32 control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param); + +public: + FrameRdyCB frm_rdy_cb; + +private: + VPU_GENERIC vpug; + MppCtx mpp_ctx; + MppApi *mpi; + RK_U32 init_ok; + RK_U32 frame_count; + RK_U32 set_eos; + MppFrame frm_info; + + /* encoder parameters */ + MppBufferGroup memGroup; + MppFrameFormat format; + + RK_U32 mInputTimeOutMs; + + RK_S32 fd_input; + RK_S32 fd_output; + + RK_U32 mEosSet; + + EncParameter_t enc_param; + MppEncCfg enc_cfg; + MppPacket enc_hdr_pkt; + void *enc_hdr_buf; + RK_S32 enc_hdr_buf_size; + + /* for mlvec */ + VpuApiMlvec mlvec; + VpuApiMlvecDynamicCfg mlvec_dy_cfg; + + RK_S32 dec_out_frm_struct_type; +}; + +#endif /* VPU_API_LEGACY_H */ diff --git a/mpp/legacy/vpu_api_mlvec.cpp b/mpp/legacy/vpu_api_mlvec.cpp new file mode 100644 index 000000000..f32c91710 --- /dev/null +++ b/mpp/legacy/vpu_api_mlvec.cpp @@ -0,0 +1,445 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vpu_api_mlvec" + +#include "string.h" + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "vpu_api_mlvec.h" +#include "vpu_api_legacy.h" + +#define VPU_API_DBG_MLVEC_FUNC (0x00010000) +#define VPU_API_DBG_MLVEC_FLOW (0x00020000) + +#define mlvec_dbg_func(fmt, ...) vpu_api_dbg_f(VPU_API_DBG_MLVEC_FUNC, fmt, ## __VA_ARGS__) +#define mlvec_dbg_flow(fmt, ...) vpu_api_dbg_f(VPU_API_DBG_MLVEC_FLOW, fmt, ## __VA_ARGS__) + +typedef struct VpuApiMlvecImpl_t { + MppCtx mpp; + MppApi *mpi; + MppEncCfg enc_cfg; + + VpuApiMlvecStaticCfg st_cfg; + VpuApiMlvecDynamicCfg dy_cfg; +} VpuApiMlvecImpl; + +MPP_RET vpu_api_mlvec_init(VpuApiMlvec *ctx) +{ + if (NULL == ctx) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mlvec_dbg_func("enter %p\n", ctx); + + VpuApiMlvecImpl *impl = mpp_calloc(VpuApiMlvecImpl, 1); + if (NULL == impl) + mpp_err_f("failed to create MLVEC context\n"); + + mpp_assert(sizeof(VpuApiMlvecStaticCfg) == sizeof(EncParameter_t)); + /* default disable frame_qp setup */ + impl->dy_cfg.frame_qp = -1; + + *ctx = impl; + + mlvec_dbg_func("leave %p %p\n", ctx, impl); + return (impl) ? (MPP_OK) : (MPP_NOK); +} + +MPP_RET vpu_api_mlvec_deinit(VpuApiMlvec ctx) +{ + mlvec_dbg_func("enter %p\n", ctx); + MPP_FREE(ctx); + mlvec_dbg_func("leave %p\n", ctx); + return MPP_OK; +} + +MPP_RET vpu_api_mlvec_setup(VpuApiMlvec ctx, MppCtx mpp, MppApi *mpi, MppEncCfg enc_cfg) +{ + if (NULL == ctx || NULL == mpp || NULL == mpi || NULL == enc_cfg) { + mpp_err_f("invalid NULL input ctx %p mpp %p mpi %p cfg %p\n", + ctx, mpp, mpi, enc_cfg); + return MPP_ERR_NULL_PTR; + } + + mlvec_dbg_func("enter %p\n", ctx); + + VpuApiMlvecImpl *impl = (VpuApiMlvecImpl *)ctx; + impl->mpp = mpp; + impl->mpi = mpi; + impl->enc_cfg = enc_cfg; + + mlvec_dbg_func("leave %p\n", ctx); + + return MPP_OK; +} + +MPP_RET vpu_api_mlvec_check_cfg(void *p) +{ + if (NULL == p) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + VpuApiMlvecStaticCfg *cfg = (VpuApiMlvecStaticCfg *)p; + RK_U32 magic = cfg->magic; + MPP_RET ret = MPP_OK; + + if ((((magic >> 24) & 0xff) != MLVEC_MAGIC) || + (((magic >> 16) & 0xff) != MLVEC_VERSION)) + ret = MPP_NOK; + + mlvec_dbg_flow("check mlvec cfg magic %08x %s\n", magic, + (ret == MPP_OK) ? "success" : "failed"); + + return ret; +} + +MPP_RET vpu_api_mlvec_set_st_cfg(VpuApiMlvec ctx, VpuApiMlvecStaticCfg *cfg) +{ + if (NULL == ctx || NULL == cfg) { + mpp_err_f("invalid NULL input ctx %p cfg %p\n"); + return MPP_ERR_NULL_PTR; + } + + mlvec_dbg_func("enter ctx %p cfg %p\n", ctx, cfg); + + /* check mlvec magic word */ + if (vpu_api_mlvec_check_cfg(cfg)) + return MPP_NOK; + + MPP_RET ret = MPP_OK; + /* update static configure */ + VpuApiMlvecImpl *impl = (VpuApiMlvecImpl *)ctx; + + memcpy(&impl->st_cfg, cfg, sizeof(impl->st_cfg)); + cfg = &impl->st_cfg; + + /* get mpp context and check */ + MppCtx mpp_ctx = impl->mpp; + MppApi *mpi = impl->mpi; + MppEncCfg enc_cfg = impl->enc_cfg; + + mpp_assert(mpp_ctx); + mpp_assert(mpi); + mpp_assert(enc_cfg); + + /* start control mpp */ + mlvec_dbg_flow("hdr_on_idr %d\n", cfg->hdr_on_idr); + MppEncHeaderMode mode = cfg->hdr_on_idr ? + MPP_ENC_HEADER_MODE_EACH_IDR : + MPP_ENC_HEADER_MODE_DEFAULT; + + ret = mpi->control(mpp_ctx, MPP_ENC_SET_HEADER_MODE, &mode); + if (ret) + mpp_err("setup enc header mode %d failed ret %d\n", mode, ret); + + mlvec_dbg_flow("add_prefix %d\n", cfg->add_prefix); + mpp_enc_cfg_set_s32(enc_cfg, "h264:prefix_mode", cfg->add_prefix); + + mlvec_dbg_flow("slice_mbs %d\n", cfg->slice_mbs); + if (cfg->slice_mbs) { + mpp_enc_cfg_set_u32(enc_cfg, "split:mode", MPP_ENC_SPLIT_BY_CTU); + mpp_enc_cfg_set_u32(enc_cfg, "split:arg", cfg->slice_mbs); + } else + mpp_enc_cfg_set_u32(enc_cfg, "split:mode", MPP_ENC_SPLIT_NONE); + + /* NOTE: ltr_frames is already configured */ + vpu_api_mlvec_set_dy_max_tid(ctx, cfg->max_tid); + + mlvec_dbg_func("leave ctx %p ret %d\n", ctx, ret); + + return ret; +} + +MPP_RET vpu_api_mlvec_set_dy_cfg(VpuApiMlvec ctx, VpuApiMlvecDynamicCfg *cfg, MppMeta meta) +{ + if (NULL == ctx || NULL == cfg || NULL == meta) { + mpp_err_f("invalid NULL input ctx %p cfg %p meta %p\n", + ctx, cfg, meta); + return MPP_ERR_NULL_PTR; + } + + mlvec_dbg_func("enter ctx %p cfg %p meta %p\n", ctx, cfg, meta); + + MPP_RET ret = MPP_OK; + VpuApiMlvecImpl *impl = (VpuApiMlvecImpl *)ctx; + VpuApiMlvecDynamicCfg *dst = &impl->dy_cfg; + + /* clear non-sticky flag first */ + dst->mark_ltr = -1; + dst->use_ltr = -1; + /* frame qp and base layer pid is sticky flag */ + + /* update flags */ + if (cfg->updated) { + if (cfg->updated & VPU_API_ENC_MARK_LTR_UPDATED) + dst->mark_ltr = cfg->mark_ltr; + + if (cfg->updated & VPU_API_ENC_USE_LTR_UPDATED) + dst->use_ltr = cfg->use_ltr; + + if (cfg->updated & VPU_API_ENC_FRAME_QP_UPDATED) + dst->frame_qp = cfg->frame_qp; + + if (cfg->updated & VPU_API_ENC_BASE_PID_UPDATED) + dst->base_layer_pid = cfg->base_layer_pid; + + /* dynamic max temporal layer count updated go through mpp ref cfg */ + cfg->updated = 0; + } + + mlvec_dbg_flow("ltr mark %2d use %2d frm qp %2d blpid %d\n", dst->mark_ltr, + dst->use_ltr, dst->frame_qp, dst->base_layer_pid); + + /* setup next frame configure */ + if (dst->mark_ltr >= 0) + mpp_meta_set_s32(meta, KEY_ENC_MARK_LTR, dst->mark_ltr); + + if (dst->use_ltr >= 0) + mpp_meta_set_s32(meta, KEY_ENC_USE_LTR, dst->use_ltr); + + if (dst->frame_qp >= 0) + mpp_meta_set_s32(meta, KEY_ENC_FRAME_QP, dst->frame_qp); + + if (dst->base_layer_pid >= 0) + mpp_meta_set_s32(meta, KEY_ENC_BASE_LAYER_PID, dst->base_layer_pid); + + mlvec_dbg_func("leave ctx %p ret %d\n", ctx, ret); + + return ret; +} + +MPP_RET vpu_api_mlvec_set_dy_max_tid(VpuApiMlvec ctx, RK_S32 max_tid) +{ + if (NULL == ctx) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mlvec_dbg_func("enter ctx %p max_tid %d\n", ctx, max_tid); + + MPP_RET ret = MPP_OK; + VpuApiMlvecImpl *impl = (VpuApiMlvecImpl *)ctx; + MppCtx mpp_ctx = impl->mpp; + MppApi *mpi = impl->mpi; + MppEncCfg enc_cfg = impl->enc_cfg; + + mpp_assert(mpp_ctx); + mpp_assert(mpi); + mpp_assert(enc_cfg); + + MppEncRefLtFrmCfg lt_ref[16]; + MppEncRefStFrmCfg st_ref[16]; + RK_S32 lt_cfg_cnt = 0; + RK_S32 st_cfg_cnt = 0; + RK_S32 tid0_loop = 0; + RK_S32 ltr_frames = impl->st_cfg.ltr_frames; + + memset(lt_ref, 0, sizeof(lt_ref)); + memset(st_ref, 0, sizeof(st_ref)); + + mlvec_dbg_flow("ltr_frames %d\n", ltr_frames); + mlvec_dbg_flow("max_tid %d\n", max_tid); + + switch (max_tid) { + case 0 : { + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + + st_cfg_cnt = 1; + tid0_loop = 1; + mlvec_dbg_flow("no tsvc\n"); + } break; + case 1 : { + /* set tsvc2 st-ref struct */ + /* st 0 layer 0 - ref */ + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + /* st 1 layer 1 - non-ref */ + st_ref[1].is_non_ref = 1; + st_ref[1].temporal_id = 1; + st_ref[1].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 0; + /* st 2 layer 0 - ref */ + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 0; + st_ref[2].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + + st_cfg_cnt = 3; + tid0_loop = 2; + mlvec_dbg_flow("tsvc2\n"); + } break; + case 2 : { + /* set tsvc3 st-ref struct */ + /* st 0 layer 0 - ref */ + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + /* st 1 layer 2 - non-ref */ + st_ref[1].is_non_ref = 0; + st_ref[1].temporal_id = 2; + st_ref[1].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 0; + /* st 2 layer 1 - ref */ + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 1; + st_ref[2].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + /* st 3 layer 2 - non-ref */ + st_ref[3].is_non_ref = 0; + st_ref[3].temporal_id = 2; + st_ref[3].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[3].ref_arg = 1; + st_ref[3].repeat = 0; + /* st 4 layer 0 - ref */ + st_ref[4].is_non_ref = 0; + st_ref[4].temporal_id = 0; + st_ref[4].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[4].ref_arg = 0; + st_ref[4].repeat = 0; + + st_cfg_cnt = 5; + tid0_loop = 4; + mlvec_dbg_flow("tsvc3\n"); + } break; + case 3 : { + /* set tsvc3 st-ref struct */ + /* st 0 layer 0 - ref */ + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + /* st 1 layer 3 - non-ref */ + st_ref[1].is_non_ref = 1; + st_ref[1].temporal_id = 3; + st_ref[1].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 0; + /* st 2 layer 2 - ref */ + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 2; + st_ref[2].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + /* st 3 layer 3 - non-ref */ + st_ref[3].is_non_ref = 1; + st_ref[3].temporal_id = 3; + st_ref[3].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[3].ref_arg = 0; + st_ref[3].repeat = 0; + /* st 4 layer 1 - ref */ + st_ref[4].is_non_ref = 0; + st_ref[4].temporal_id = 1; + st_ref[4].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[4].ref_arg = 0; + st_ref[4].repeat = 0; + /* st 5 layer 3 - non-ref */ + st_ref[5].is_non_ref = 1; + st_ref[5].temporal_id = 3; + st_ref[5].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[5].ref_arg = 0; + st_ref[5].repeat = 0; + /* st 6 layer 2 - ref */ + st_ref[6].is_non_ref = 0; + st_ref[6].temporal_id = 2; + st_ref[6].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[6].ref_arg = 0; + st_ref[6].repeat = 0; + /* st 7 layer 3 - non-ref */ + st_ref[7].is_non_ref = 1; + st_ref[7].temporal_id = 3; + st_ref[7].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[7].ref_arg = 0; + st_ref[7].repeat = 0; + /* st 8 layer 0 - ref */ + st_ref[8].is_non_ref = 0; + st_ref[8].temporal_id = 0; + st_ref[8].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[8].ref_arg = 0; + st_ref[8].repeat = 0; + + st_cfg_cnt = 9; + tid0_loop = 8; + mlvec_dbg_flow("tsvc4\n"); + } break; + default : { + mpp_err("invalid max temporal layer id %d\n", max_tid); + } break; + } + + if (ltr_frames) { + RK_S32 i; + + lt_cfg_cnt = ltr_frames; + mpp_assert(ltr_frames <= MPP_ENC_MAX_LT_REF_NUM); + for (i = 0; i < ltr_frames; i++) { + lt_ref[i].lt_idx = i; + lt_ref[i].temporal_id = 0; + lt_ref[i].ref_mode = REF_TO_PREV_LT_REF; + lt_ref[i].lt_gap = 0; + lt_ref[i].lt_delay = tid0_loop * i; + } + } + + if (lt_cfg_cnt) + mpp_assert(st_cfg_cnt); + + mlvec_dbg_flow("lt_cfg_cnt %d st_cfg_cnt %d\n", lt_cfg_cnt, st_cfg_cnt); + if (lt_cfg_cnt || st_cfg_cnt) { + MppEncRefCfg ref = NULL; + + mpp_enc_ref_cfg_init(&ref); + + ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cfg_cnt, st_cfg_cnt); + ret = mpp_enc_ref_cfg_add_lt_cfg(ref, lt_cfg_cnt, lt_ref); + ret = mpp_enc_ref_cfg_add_st_cfg(ref, st_cfg_cnt, st_ref); + ret = mpp_enc_ref_cfg_set_keep_cpb(ref, 1); + ret = mpp_enc_ref_cfg_check(ref); + + ret = mpi->control(mpp_ctx, MPP_ENC_SET_REF_CFG, ref); + if (ret) + mpp_err("mpi control enc set ref cfg failed ret %d\n", ret); + + mpp_enc_ref_cfg_deinit(&ref); + } else { + ret = mpi->control(mpp_ctx, MPP_ENC_SET_REF_CFG, NULL); + if (ret) + mpp_err("mpi control enc set ref cfg failed ret %d\n", ret); + } + + mlvec_dbg_func("leave ctx %p ret %d\n", ctx, ret); + + return ret; +} diff --git a/mpp/legacy/vpu_api_mlvec.h b/mpp/legacy/vpu_api_mlvec.h new file mode 100644 index 000000000..bd1c44bd1 --- /dev/null +++ b/mpp/legacy/vpu_api_mlvec.h @@ -0,0 +1,93 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VPU_API_MLVEC_H +#define VPU_API_MLVEC_H + +#include "rk_mpi.h" + +#define MLVEC_MAGIC 'M' +#define MLVEC_VERSION '0' + +#define VPU_API_ENC_MAX_TID_UPDATED (0x00000001) +#define VPU_API_ENC_MARK_LTR_UPDATED (0x00000002) +#define VPU_API_ENC_USE_LTR_UPDATED (0x00000004) +#define VPU_API_ENC_FRAME_QP_UPDATED (0x00000008) +#define VPU_API_ENC_BASE_PID_UPDATED (0x00000010) + +typedef struct VpuApiMlvecStaticCfg_t { + RK_S16 width; + RK_S16 sar_width; + RK_S16 height; + RK_S16 sar_height; + RK_S32 rc_mode; /* 0 - CQP mode; 1 - CBR mode; */ + RK_S32 bitRate; /* target bitrate */ + RK_S32 framerate; + RK_S32 qp; + RK_S32 enableCabac; + RK_S32 cabacInitIdc; + RK_S32 format; + RK_S32 intraPicRate; + RK_S32 framerateout; + RK_S32 profileIdc; + RK_S32 levelIdc; + + RK_S32 magic; /* MLVEC magic word */ + /* static configure */ + RK_S32 max_tid : 8; /* max temporal layer id */ + RK_S32 ltr_frames : 8; /* max long-term reference frame count */ + RK_S32 hdr_on_idr : 8; /* sps/pps header with IDR frame */ + RK_S32 add_prefix : 8; /* add prefix before each frame */ + RK_S32 slice_mbs : 16; /* macroblock row count for each slice */ + RK_S32 reserved : 16; +} VpuApiMlvecStaticCfg; + +typedef struct VpuApiMlvecDynamicCfg_t { + /* dynamic configure */ + RK_U32 updated; + RK_S32 max_tid; + RK_S32 mark_ltr; + RK_S32 use_ltr; + RK_S32 frame_qp; + RK_S32 base_layer_pid; +} VpuApiMlvecDynamicCfg; + +typedef void* VpuApiMlvec; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vpu_api_mlvec_init(VpuApiMlvec *ctx); +MPP_RET vpu_api_mlvec_deinit(VpuApiMlvec ctx); + +/* setup basic mpp info in vpu_api */ +MPP_RET vpu_api_mlvec_setup(VpuApiMlvec ctx, MppCtx mpp, MppApi *mpi, MppEncCfg enc_cfg); +/* check the input encoder parameter is mlvec configure or not */ +MPP_RET vpu_api_mlvec_check_cfg(void *p); + +/* setup mlvec static configure */ +MPP_RET vpu_api_mlvec_set_st_cfg(VpuApiMlvec ctx, VpuApiMlvecStaticCfg *cfg); +/* setup mlvec dynamic configure and setup MppMeta in MppFrame */ +MPP_RET vpu_api_mlvec_set_dy_cfg(VpuApiMlvec ctx, VpuApiMlvecDynamicCfg *cfg, MppMeta meta); +/* setup mlvec max temporal layer count dynamic configure */ +MPP_RET vpu_api_mlvec_set_dy_max_tid(VpuApiMlvec ctx, RK_S32 max_tid); + +#ifdef __cplusplus +} +#endif + +#endif /* VPU_API_MLVEC_H */ diff --git a/mpp/legacy/vpu_mem_legacy.c b/mpp/legacy/vpu_mem_legacy.c new file mode 100644 index 000000000..d357bf9c6 --- /dev/null +++ b/mpp/legacy/vpu_mem_legacy.c @@ -0,0 +1,311 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_buffer.h" + +#include "vpu.h" +#include "vpu_mem_legacy.h" + +#define VPU_MEM_DBG_FUNCTION (0x00000001) + +static RK_U32 vpu_mem_debug = 0; + +#define vpu_mem_dbg(flag, fmt, ...) mpp_dbg(vpu_mem_debug, flag, fmt, ## __VA_ARGS__) +#define vpu_mem_dbg_f(flag, fmt, ...) mpp_dbg_f(vpu_mem_debug, flag, fmt, ## __VA_ARGS__) + +#define vpu_mem_dbg_func(fmt, ...) vpu_mem_dbg_f(VPU_MEM_DBG_FUNCTION, fmt, ## __VA_ARGS__) + +static RK_S32 +commit_memory_handle(vpu_display_mem_pool *p, RK_S32 mem_hdl, RK_S32 size) +{ + MppBufferInfo info; + vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; + + vpu_mem_dbg_func("in pool %p hnl %p size %d\n", p, mem_hdl, size); + memset(&info, 0, sizeof(MppBufferInfo)); + info.type = MPP_BUFFER_TYPE_ION; + info.fd = mem_hdl; + info.size = size & 0x07ffffff; + info.index = (size & 0xf8000000) >> 27; + + p_mempool->size = size; + p_mempool->buff_size = size; + + mpp_buffer_commit(p_mempool->group, &info); + vpu_mem_dbg_func("out pool %p fd %d\n", p, info.fd); + return info.fd; +} + +static void* get_free_memory_vpumem(vpu_display_mem_pool *p) +{ + MPP_RET ret = MPP_OK; + MppBuffer buffer = NULL; + VPUMemLinear_t *dmabuf = mpp_calloc(VPUMemLinear_t, 1); + vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; + if (dmabuf == NULL) { + return NULL; + } + vpu_mem_dbg_func("in pool %p\n", p); + ret = mpp_buffer_get(p_mempool->group, &buffer, p_mempool->size); + if (MPP_OK != ret) { + mpp_free(dmabuf); + return NULL; + } + dmabuf->phy_addr = (RK_U32)mpp_buffer_get_fd(buffer); + dmabuf->vir_addr = (RK_U32*)mpp_buffer_get_ptr(buffer); + dmabuf->size = p_mempool->size; + dmabuf->offset = (RK_U32*)buffer; + vpu_mem_dbg_func("out pool %p ret %p fd %d size %d buffer %p\n", p, dmabuf, + dmabuf->phy_addr, dmabuf->size, buffer); + return dmabuf; + +} + +static RK_S32 inc_used_memory_handle_ref(vpu_display_mem_pool *p, void * hdl) +{ + VPUMemLinear_t *dmabuf = (VPUMemLinear_t *)hdl; + MppBuffer buffer = (MppBuffer)dmabuf->offset; + vpu_mem_dbg_func("pool %p hnd %p buffer %p\n", p, hdl, buffer); + if (buffer != NULL) { + mpp_buffer_inc_ref(buffer); + } + + (void)p; + return MPP_OK; +} + +static RK_S32 put_used_memory_handle(vpu_display_mem_pool *p, void *hdl) +{ + VPUMemLinear_t *dmabuf = (VPUMemLinear_t *)hdl; + MppBuffer buf = (MppBuffer)dmabuf->offset; + vpu_mem_dbg_func("pool %p hnd %p buffer %p\n", p, hdl, buf); + if (buf != NULL) { + mpp_buffer_put(buf); + memset(dmabuf, 0, sizeof(VPUMemLinear_t)); + } + (void)p; + return MPP_OK; +} + +static RK_S32 get_free_memory_num(vpu_display_mem_pool *p) +{ + vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; + RK_S32 ret = (p_mempool->group) ? + (mpp_buffer_group_unused(p_mempool->group)) : (0); + + vpu_mem_dbg_func("pool %p ret %d\n", p, ret); + return ret; +} + +static RK_S32 reset_vpu_mem_pool(vpu_display_mem_pool *p) +{ + vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; + mpp_buffer_group_clear(p_mempool->group); + return 0; +} + + +vpu_display_mem_pool* open_vpu_memory_pool() +{ + vpu_display_mem_pool_impl *p_mempool = + mpp_calloc(vpu_display_mem_pool_impl, 1); + + mpp_env_get_u32("vpu_mem_debug", &vpu_mem_debug, 0); + vpu_mem_dbg_func("in pool %p\n", p_mempool); + + if (NULL == p_mempool) { + return NULL; + } + mpp_buffer_group_get_external(&p_mempool->group, MPP_BUFFER_TYPE_ION); + if (NULL == p_mempool->group) { + return NULL; + } + p_mempool->commit_hdl = commit_memory_handle; + p_mempool->get_free = get_free_memory_vpumem; + p_mempool->put_used = put_used_memory_handle; + p_mempool->inc_used = inc_used_memory_handle_ref; + p_mempool->reset = reset_vpu_mem_pool; + p_mempool->get_unused_num = get_free_memory_num; + p_mempool->version = 1; + p_mempool->buff_size = -1; + + vpu_mem_dbg_func("out pool %p group %p\n", p_mempool, p_mempool->group); + return (vpu_display_mem_pool*)p_mempool; +} + +void close_vpu_memory_pool(vpu_display_mem_pool *p) +{ + vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)p; + + vpu_mem_dbg_func("pool %p group %p\n", p_mempool, p_mempool->group); + mpp_buffer_group_put(p_mempool->group); + mpp_free(p_mempool); + return; +} + +int create_vpu_memory_pool_allocator(vpu_display_mem_pool **ipool, + int num, int size) +{ + vpu_display_mem_pool_impl *p_mempool = + mpp_calloc(vpu_display_mem_pool_impl, 1); + + mpp_env_get_u32("vpu_mem_debug", &vpu_mem_debug, 0); + vpu_mem_dbg_func("in pool %p num %d size %d\n", p_mempool, num, size); + + if (NULL == p_mempool) + return -1; + + mpp_buffer_group_get_internal(&p_mempool->group, MPP_BUFFER_TYPE_ION); + mpp_buffer_group_limit_config(p_mempool->group, 0, num + 4); + p_mempool->commit_hdl = commit_memory_handle; + p_mempool->get_free = get_free_memory_vpumem; + p_mempool->put_used = put_used_memory_handle; + p_mempool->inc_used = inc_used_memory_handle_ref; + p_mempool->reset = reset_vpu_mem_pool; + p_mempool->get_unused_num = get_free_memory_num; + p_mempool->version = 0; + p_mempool->buff_size = size; + p_mempool->size = size; + *ipool = (vpu_display_mem_pool*)p_mempool; + + vpu_mem_dbg_func("out pool %p group %p\n", p_mempool, p_mempool->group); + return 0; +} + +void release_vpu_memory_pool_allocator(vpu_display_mem_pool *ipool) +{ + vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)ipool; + if (p_mempool == NULL) + return; + + vpu_mem_dbg_func("pool %p group %p\n", p_mempool, p_mempool->group); + + if (p_mempool->group) { + mpp_buffer_group_put(p_mempool->group); + p_mempool->group = NULL; + } + + vpu_mem_dbg_func("free %p\n", p_mempool); + mpp_free(p_mempool); + return; +} + +RK_S32 VPUMemJudgeIommu() +{ + int ret = 0; + + if (VPUClientGetIOMMUStatus() > 0) { + //mpp_err("media.used.iommu"); + ret = 1; + } + + return ret; +} + + +RK_S32 VPUMallocLinear(VPUMemLinear_t *p, RK_U32 size) +{ + int ret = 0; + MppBuffer buffer = NULL; + ret = mpp_buffer_get(NULL, &buffer, size); + if (ret != MPP_OK) { + return -1; + } + p->phy_addr = (RK_U32)mpp_buffer_get_fd(buffer); + p->vir_addr = (RK_U32*)mpp_buffer_get_ptr(buffer); + p->size = size; + p->offset = (RK_U32*)buffer; + return 0; +} + +RK_S32 VPUMallocLinearFromRender(VPUMemLinear_t *p, RK_U32 size, void *ctx) +{ + VPUMemLinear_t *dma_buf = NULL; + vpu_display_mem_pool_impl *p_mempool = (vpu_display_mem_pool_impl *)ctx; + if (ctx == NULL) { + return VPUMallocLinear(p, size); + } + dma_buf = (VPUMemLinear_t *) + p_mempool->get_free((vpu_display_mem_pool *)ctx); + memset(p, 0, sizeof(VPUMemLinear_t)); + if (dma_buf != NULL) { + if (dma_buf->size < size) { + mpp_free(dma_buf); + return -1; + } + memcpy(p, dma_buf, sizeof(VPUMemLinear_t)); + mpp_free(dma_buf); + return 0; + } + return -1; +} + +RK_S32 VPUFreeLinear(VPUMemLinear_t *p) +{ + if (p->offset != NULL) { + put_used_memory_handle(NULL, p); + } + return 0; +} + +RK_S32 VPUMemDuplicate(VPUMemLinear_t *dst, VPUMemLinear_t *src) +{ + MppBuffer buffer = (MppBuffer)src->offset; + if (buffer != NULL) { + mpp_buffer_inc_ref(buffer); + } + memcpy(dst, src, sizeof(VPUMemLinear_t)); + return 0; +} + +RK_S32 VPUMemLink(VPUMemLinear_t *p) +{ + (void)p; + return 0; +} + +RK_S32 VPUMemFlush(VPUMemLinear_t *p) +{ + (void)p; + return 0; +} + +RK_S32 VPUMemClean(VPUMemLinear_t *p) +{ + (void)p; + return 0; +} + + +RK_S32 VPUMemInvalidate(VPUMemLinear_t *p) +{ + (void)p; + return 0; +} + +RK_S32 VPUMemGetFD(VPUMemLinear_t *p) +{ + RK_S32 fd = 0; + MppBuffer buffer = (MppBuffer)p->offset; + fd = mpp_buffer_get_fd(buffer); + return fd; +} + diff --git a/mpp/legacy/vpu_mem_legacy.h b/mpp/legacy/vpu_mem_legacy.h new file mode 100644 index 000000000..98fd7b99d --- /dev/null +++ b/mpp/legacy/vpu_mem_legacy.h @@ -0,0 +1,27 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _VPU_MEM_H_ +#define _VPU_MEM_H_ + +#include "vpu_api.h" + +typedef struct vpu_display_mem_pool_impl { + vpu_display_mem_pool_FIELDS + MppBufferGroup group; + RK_S32 size; +} vpu_display_mem_pool_impl; + +#endif //_VPU_MEM_H_ \ No newline at end of file diff --git a/mpp/mpi.c b/mpp/mpi.c new file mode 100644 index 000000000..c729b5b21 --- /dev/null +++ b/mpp/mpi.c @@ -0,0 +1,571 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpi" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_sys.h" +#include "mpp_info.h" + +RK_U32 mpi_debug = 0; + +typedef struct { + MppCtxType type; + MppCodingType coding; + const char *type_name; + const char *coding_name; +} MppCodingTypeInfo; + +static MppCodingTypeInfo support_list[] = { +#if HAVE_MPEG2D + { MPP_CTX_DEC, MPP_VIDEO_CodingMPEG2, "dec", "mpeg2", }, +#endif +#if HAVE_MPEG4D + { MPP_CTX_DEC, MPP_VIDEO_CodingMPEG4, "dec", "mpeg4", }, +#endif +#if HAVE_H263D + { MPP_CTX_DEC, MPP_VIDEO_CodingH263, "dec", "h.263", }, +#endif +#if HAVE_H264D + { MPP_CTX_DEC, MPP_VIDEO_CodingAVC, "dec", "h.264/AVC", }, +#endif +#if HAVE_H265D + { MPP_CTX_DEC, MPP_VIDEO_CodingHEVC, "dec", "h.265/HEVC", }, +#endif +#if HAVE_VP8D + { MPP_CTX_DEC, MPP_VIDEO_CodingVP8, "dec", "vp8", }, +#endif +#if HAVE_VP9D + { MPP_CTX_DEC, MPP_VIDEO_CodingVP9, "dec", "VP9", }, +#endif +#if HAVE_AVSD + { MPP_CTX_DEC, MPP_VIDEO_CodingAVS, "dec", "avs", }, + { MPP_CTX_DEC, MPP_VIDEO_CodingAVSPLUS, "dec", "avs+", }, +#endif +#if HAVE_AVS2D + { MPP_CTX_DEC, MPP_VIDEO_CodingAVS2, "dec", "avs2", }, +#endif +#if HAVE_JPEGD + { MPP_CTX_DEC, MPP_VIDEO_CodingMJPEG, "dec", "jpeg", }, +#endif +#if HAVE_AV1D + { MPP_CTX_DEC, MPP_VIDEO_CodingAV1, "dec", "av1", }, +#endif +#if HAVE_H264E + { MPP_CTX_ENC, MPP_VIDEO_CodingAVC, "enc", "h.264/AVC", }, +#endif +#if HAVE_JPEGE + { MPP_CTX_ENC, MPP_VIDEO_CodingMJPEG, "enc", "jpeg", }, +#endif +#if HAVE_H265E + { MPP_CTX_ENC, MPP_VIDEO_CodingHEVC, "enc", "h265", }, +#endif +#if HAVE_VP8E + { MPP_CTX_ENC, MPP_VIDEO_CodingVP8, "enc", "vp8", } +#endif +}; + +#define check_mpp_ctx(ctx) _check_mpp_ctx(ctx, __FUNCTION__) + +static MPP_RET _check_mpp_ctx(MpiImpl *p, const char *caller) +{ + if (NULL == p || p->check != p || NULL == p->ctx) { + _mpp_err(MODULE_TAG, "found invalid context %p\n", caller, p); + return MPP_ERR_UNKNOW; + } + return MPP_OK; +} + +static MPP_RET mpi_decode(MppCtx ctx, MppPacket packet, MppFrame *frame) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p packet %p frame %p\n", ctx, packet, frame); + + do { + ret = check_mpp_ctx(p); + if (ret) + break; + + /* + * NOTE: packet and frame could be NULL + * If packet is NULL then it is equal to get_frame + * If frame is NULL then it is equal to put_packet + */ + if (frame) + *frame = NULL; + + ret = mpp_decode(p->ctx, packet, frame); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_decode_put_packet(MppCtx ctx, MppPacket packet) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p packet %p\n", ctx, packet); + do { + ret = check_mpp_ctx(p); + if (ret) + break; + + if (NULL == packet) { + mpp_err_f("found NULL input packet\n"); + ret = MPP_ERR_NULL_PTR; + break; + } + + ret = mpp_put_packet(p->ctx, packet); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_decode_get_frame(MppCtx ctx, MppFrame *frame) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame); + do { + ret = check_mpp_ctx(p); + if (ret) + break; + + if (NULL == frame) { + mpp_err_f("found NULL input frame\n"); + ret = MPP_ERR_NULL_PTR; + break; + } + + ret = mpp_get_frame(p->ctx, frame); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_encode(MppCtx ctx, MppFrame frame, MppPacket *packet) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p frame %p packet %p\n", ctx, frame, packet); + do { + ret = check_mpp_ctx(p); + if (ret) + break; + + if (NULL == frame || NULL == packet) { + mpp_err_f("found NULL input frame %p packet %p\n", frame, packet); + ret = MPP_ERR_NULL_PTR; + break; + } + + // TODO: do encode here + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_encode_put_frame(MppCtx ctx, MppFrame frame) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame); + do { + ret = check_mpp_ctx(p); + if (ret) + break; + + if (NULL == frame) { + mpp_err_f("found NULL input frame\n"); + ret = MPP_ERR_NULL_PTR; + break; + } + + ret = mpp_put_frame(p->ctx, frame); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_encode_get_packet(MppCtx ctx, MppPacket *packet) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p packet %p\n", ctx, packet); + do { + ret = check_mpp_ctx(p); + if (ret) + break; + + if (NULL == packet) { + mpp_err_f("found NULL input packet\n"); + ret = MPP_ERR_NULL_PTR; + break; + } + + ret = mpp_get_packet(p->ctx, packet); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_isp(MppCtx ctx, MppFrame dst, MppFrame src) +{ + MPP_RET ret = MPP_OK; + mpi_dbg_func("enter ctx %p dst %p src %p\n", ctx, dst, src); + + // TODO: do isp process here + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return MPP_OK; +} + +static MPP_RET mpi_isp_put_frame(MppCtx ctx, MppFrame frame) +{ + MPP_RET ret = MPP_OK; + mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame); + + // TODO: do isp put frame process here + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_isp_get_frame(MppCtx ctx, MppFrame *frame) +{ + MPP_RET ret = MPP_OK; + mpi_dbg_func("enter ctx %p frame %p\n", ctx, frame); + + // TODO: do isp get frame process here + + mpi_dbg_func("leave ret %d\n", ret); + return ret; +} + +static MPP_RET mpi_poll(MppCtx ctx, MppPortType type, MppPollType timeout) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p type %d timeout %d\n", ctx, type, timeout); + do { + ret = check_mpp_ctx(p); + if (ret) + break;; + + if (type >= MPP_PORT_BUTT || + timeout < MPP_POLL_BUTT || + timeout > MPP_POLL_MAX) { + mpp_err_f("invalid input type %d timeout %d\n", type, timeout); + ret = MPP_ERR_UNKNOW; + break; + } + + ret = mpp_poll(p->ctx, type, timeout); + if (ret > 0) + ret = MPP_OK; + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_dequeue(MppCtx ctx, MppPortType type, MppTask *task) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p type %d task %p\n", ctx, type, task); + do { + ret = check_mpp_ctx(p); + if (ret) + break;; + + if (type >= MPP_PORT_BUTT || NULL == task) { + mpp_err_f("invalid input type %d task %p\n", type, task); + ret = MPP_ERR_UNKNOW; + break; + } + + ret = mpp_dequeue(p->ctx, type, task); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_enqueue(MppCtx ctx, MppPortType type, MppTask task) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p type %d task %p\n", ctx, type, task); + do { + ret = check_mpp_ctx(p); + if (ret) + break;; + + if (type >= MPP_PORT_BUTT || NULL == task) { + mpp_err_f("invalid input type %d task %p\n", type, task); + ret = MPP_ERR_UNKNOW; + break; + } + + ret = mpp_enqueue(p->ctx, type, task); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_reset(MppCtx ctx) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p\n", ctx); + do { + ret = check_mpp_ctx(p); + if (ret) + break;; + + ret = mpp_reset(p->ctx); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MPP_RET mpi_control(MppCtx ctx, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + MpiImpl *p = (MpiImpl *)ctx; + + mpi_dbg_func("enter ctx %p cmd %x parm %p\n", ctx, cmd, param); + do { + ret = check_mpp_ctx(p); + if (ret) + break;; + + ret = mpp_control(p->ctx, cmd, param); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +static MppApi mpp_api = { + .size = sizeof(mpp_api), + .version = 0, + .decode = mpi_decode, + .decode_put_packet = mpi_decode_put_packet, + .decode_get_frame = mpi_decode_get_frame, + .encode = mpi_encode, + .encode_put_frame = mpi_encode_put_frame, + .encode_get_packet = mpi_encode_get_packet, + .isp = mpi_isp, + .isp_put_frame = mpi_isp_put_frame, + .isp_get_frame = mpi_isp_get_frame, + .poll = mpi_poll, + .dequeue = mpi_dequeue, + .enqueue = mpi_enqueue, + .reset = mpi_reset, + .control = mpi_control, + .reserv = {0}, +}; + +MPP_RET mpp_create(MppCtx *ctx, MppApi **mpi) +{ + mpp_env_get_u32("mpi_debug", &mpi_debug, 0); + mpp_get_log_level(); + + if (NULL == ctx || NULL == mpi) { + mpp_err_f("invalid input ctx %p mpi %p\n", ctx, mpi); + return MPP_ERR_NULL_PTR; + } + + *ctx = NULL; + *mpi = NULL; + + MPP_RET ret = MPP_OK; + mpi_dbg_func("enter ctx %p mpi %p\n", ctx, mpi); + do { + MpiImpl *p = mpp_malloc(MpiImpl, 1); + if (NULL == p) { + mpp_err_f("failed to allocate context\n"); + ret = MPP_ERR_MALLOC; + break; + } + + memset(p, 0, sizeof(*p)); + ret = mpp_ctx_create(&p->ctx, p); + if (ret || NULL == p->ctx) { + mpp_free(p); + mpp_err_f("failed to create Mpp context ret %d\n", ret); + ret = MPP_ERR_MALLOC; + break; + } + + mpp_api.version = 0; + p->api = &mpp_api; + p->check = p; + *ctx = p; + *mpi = p->api; + + mpp_sys_attach(p); + } while (0); + + show_mpp_version(); + + mpi_dbg_func("leave ret %d ctx %p mpi %p\n", ret, *ctx, *mpi); + return ret; +} + +MPP_RET mpp_init(MppCtx ctx, MppCtxType type, MppCodingType coding) +{ + MPP_RET ret = MPP_OK; + MpiImpl *p = (MpiImpl*)ctx; + + mpi_dbg_func("enter ctx %p type %d coding %d\n", ctx, type, coding); + do { + ret = check_mpp_ctx(p); + if (ret) + break; + + if (type >= MPP_CTX_BUTT || + coding >= MPP_VIDEO_CodingMax) { + mpp_err_f("invalid input type %d coding %d\n", type, coding); + ret = MPP_ERR_UNKNOW; + break; + } + + ret = mpp_ctx_init(p->ctx, type, coding); + p->type = type; + p->coding = coding; + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +MPP_RET mpp_destroy(MppCtx ctx) +{ + mpi_dbg_func("enter ctx %p\n", ctx); + + MPP_RET ret = MPP_OK; + MpiImpl *p = (MpiImpl*)ctx; + + do { + ret = check_mpp_ctx(p); + if (ret) + return ret; + + mpp_sys_detach(p); + + if (p->ctx) + mpp_ctx_destroy(p->ctx); + + mpp_free(p); + } while (0); + + mpi_dbg_func("leave ctx %p ret %d\n", ctx, ret); + return ret; +} + +MPP_RET mpp_check_support_format(MppCtxType type, MppCodingType coding) +{ + MPP_RET ret = MPP_NOK; + RK_U32 i = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(support_list); i++) { + MppCodingTypeInfo *info = &support_list[i]; + if (type == info->type && + coding == info->coding) { + ret = MPP_OK; + break; + } + } + return ret; +} + +void mpp_show_support_format(void) +{ + RK_U32 i = 0; + + mpp_log("mpp coding type support list:"); + + for (i = 0; i < MPP_ARRAY_ELEMS(support_list); i++) { + MppCodingTypeInfo *info = &support_list[i]; + mpp_log("type: %s id %d coding: %-16s id %d\n", + info->type_name, info->type, + info->coding_name, info->coding); + } +} + +typedef struct { + MppFrameFormat format; + const char *name; +} MppFrameFormatInfo; + +static MppFrameFormatInfo color_list[] = { + { MPP_FMT_YUV420SP, "YUV420SP, NV12" }, + { MPP_FMT_YUV420SP_10BIT, "YUV420SP-10bit" }, + { MPP_FMT_YUV422SP, "YUV422SP, NV16" }, + { MPP_FMT_YUV422SP_10BIT, "YUV422SP-10bit" }, + { MPP_FMT_YUV420P, "YUV420P, I420" }, + { MPP_FMT_YUV420SP_VU, "YUV420SP, NV21" }, + { MPP_FMT_YUV422P, "YUV422P, 422P" }, + { MPP_FMT_YUV422SP_VU, "YUV422SP, NV61" }, + { MPP_FMT_YUV422_YUYV, "YUV422-YUYV, YUY2" }, + { MPP_FMT_YUV422_UYVY, "YUV422-UYVY, UYVY" }, + { MPP_FMT_YUV400, "YUV400-Y8, Y800" }, + { MPP_FMT_YUV444SP, "YUV444SP, NV24" }, + { MPP_FMT_YUV444P, "YUV444P" }, + + { MPP_FMT_RGB565, "RGB565" }, + { MPP_FMT_BGR565, "BGR565" }, + { MPP_FMT_RGB555, "RGB555" }, + { MPP_FMT_BGR555, "BGR555" }, + { MPP_FMT_RGB888, "RGB888" }, + { MPP_FMT_BGR888, "BGR888" }, + + { MPP_FMT_ARGB8888, "ARGB8888" }, + { MPP_FMT_ABGR8888, "ABGR8888" }, + { MPP_FMT_BGRA8888, "BGRA8888" }, + { MPP_FMT_RGBA8888, "RGBA8888" }, +}; + +void mpp_show_color_format(void) +{ + RK_U32 i = 0; + + mpp_log("mpp color support list:"); + + for (i = 0; i < MPP_ARRAY_ELEMS(color_list); i++) { + MppFrameFormatInfo *info = &color_list[i]; + mpp_log("color: id %-5d 0x%05x %s\n", + info->format, info->format, info->name); + } +} diff --git a/mpp/mpi.cpp b/mpp/mpi.cpp deleted file mode 100644 index 8b412e83f..000000000 --- a/mpp/mpi.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpi" - -#include - -#include "rk_mpi.h" - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpi_impl.h" -#include "mpp.h" - -static MPP_RET mpi_config(MppCtx ctx, MppEncConfig cfg) -{ - (void)ctx; - (void)cfg; - MPI_FUNCTION_ENTER(); - - MPI_FUNCTION_LEAVE(); - return MPP_OK; -} - -static MPP_RET mpi_decode(MppCtx ctx, MppPacket packet, MppFrame *frame) -{ - (void)ctx; - (void)packet; - (void)frame; - MPI_FUNCTION_ENTER(); - - MPI_FUNCTION_LEAVE(); - return MPP_OK; -} - -static MPP_RET mpi_encode(MppCtx ctx, MppFrame frame, MppPacket *packet) -{ - (void)ctx; - (void)packet; - (void)frame; - MPI_FUNCTION_ENTER(); - - MPI_FUNCTION_LEAVE(); - return MPP_OK; -} - -static MPP_RET mpi_decode_put_packet(MppCtx ctx, MppPacket packet) -{ - MPI_FUNCTION_ENTER(); - MpiImpl *p = (MpiImpl *)ctx; - - if (NULL == p || p->check != p || NULL == p->ctx || NULL == packet) { - mpp_err("mpi_decode_put_packet found invalid context input ctx %p packet %p\n", - ctx, packet); - return MPP_ERR_UNKNOW; - } - - MPP_RET ret = p->ctx->put_packet(packet); - - MPI_FUNCTION_LEAVE(); - return ret; -} - -static MPP_RET mpi_decode_get_frame(MppCtx ctx, MppFrame *frame) -{ - MPI_FUNCTION_ENTER(); - MpiImpl *p = (MpiImpl *)ctx; - - if (NULL == p || p->check != p || NULL == p->ctx || NULL == frame) { - mpp_err("mpi_decode_get_frame found invalid context input ctx %p frame %p\n", - ctx, frame); - return MPP_ERR_UNKNOW; - } - - MPP_RET ret = p->ctx->get_frame(frame); - - MPI_FUNCTION_LEAVE(); - return ret; -} - -static MPP_RET mpi_encode_put_frame(MppCtx ctx, MppFrame frame) -{ - MPI_FUNCTION_ENTER(); - MpiImpl *p = (MpiImpl *)ctx; - - if (NULL == p || p->check != p || NULL == p->ctx || NULL == frame) { - mpp_err("mpi_encode_put_frame found invalid context input ctx %p frame %p\n", - ctx, frame); - return MPP_ERR_UNKNOW; - } - - MPP_RET ret = p->ctx->put_frame(frame); - - MPI_FUNCTION_LEAVE(); - return ret; -} - -static MPP_RET mpi_encode_get_packet(MppCtx ctx, MppPacket *packet) -{ - MPI_FUNCTION_ENTER(); - MpiImpl *p = (MpiImpl *)ctx; - - if (NULL == p || p->check != p || NULL == p->ctx || NULL == packet) { - mpp_err("mpi_encode_get_packet found invalid context input ctx %p packet %p\n", - ctx, packet); - return MPP_ERR_UNKNOW; - } - - MPP_RET ret = p->ctx->get_packet(packet); - - MPI_FUNCTION_LEAVE(); - return ret; -} - -static MPP_RET mpi_flush(MppCtx ctx) -{ - (void)ctx; - MPI_FUNCTION_ENTER(); - - MPI_FUNCTION_LEAVE(); - return MPP_OK; -} - -static MPP_RET mpi_control(MppCtx ctx, MpiCmd cmd, MppParam param) -{ - (void)ctx; - (void)cmd; - (void)param; - MPI_FUNCTION_ENTER(); - - MPI_FUNCTION_LEAVE(); - return MPP_OK; -} - -static MppApi mpp_api = { - sizeof(mpp_api), - 1, - mpi_config, - mpi_decode, - mpi_encode, - mpi_decode_put_packet, - mpi_decode_get_frame, - mpi_encode_put_frame, - mpi_encode_get_packet, - mpi_flush, - mpi_control, - {0}, -}; - -MPP_RET mpp_init(MppCtx *ctx, MppApi **mpi, MppCtxType type, MppCodingType coding) -{ - MpiImpl *p; - MPI_FUNCTION_ENTER(); - - if (NULL == ctx || NULL == mpi || - type >= MPP_CTX_BUTT || - coding >= MPP_VIDEO_CodingMax) { - mpp_err("mpp_init invalid input ctx %p mpi %p type %d coding %d\n", - ctx, mpi, type, coding); - return MPP_ERR_NULL_PTR; - } - - *ctx = NULL; - *mpi = NULL; - - p = mpp_malloc(MpiImpl, 1); - if (NULL == p) { - mpp_err("mpp_init failed to allocate context\n"); - return MPP_ERR_MALLOC; - } - - memset(p, 0, sizeof(*p)); - - p->ctx = new Mpp(type, coding); - if (NULL == p->ctx) { - mpp_free(p); - mpp_err("mpp_init failed to new Mpp\n"); - return MPP_ERR_MALLOC; - } - - p->api = &mpp_api; - p->check = p; - p->type = type; - p->coding = coding; - *ctx = p; - *mpi = p->api; - - get_mpi_debug(); - - MPI_FUNCTION_LEAVE_OK(); - return MPP_OK; -} - -MPP_RET mpp_deinit(MppCtx ctx) -{ - MpiImpl *p; - MPI_FUNCTION_ENTER(); - - if (NULL == ctx) { - mpp_err("mpp_deinit input ctx %p is null pointer\n", ctx); - return MPP_ERR_NULL_PTR; - } - - p = (MpiImpl*)ctx; - - if (p->check != p) { - mpp_err("mpp_deinit input invalid MppCtx\n"); - return MPP_ERR_UNKNOW; - } - - if (p->ctx) - delete p->ctx; - - mpp_free(p); - - MPI_FUNCTION_LEAVE(); - return MPP_OK; -} - diff --git a/mpp/mpi_impl.h b/mpp/mpi_impl.h deleted file mode 100644 index 8ae0e713e..000000000 --- a/mpp/mpi_impl.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_IMPL_H__ -#define __MPP_IMPL_H__ - -#include "mpp.h" -#include "vpu_api.h" - -#define MPI_DBG_FUNCTION (0x00000001) - - - -#define mpi_dbg(flag, fmt, ...) _mpp_dbg(mpi_debug, flag, fmt, ## __VA_ARGS__) -#define mpi_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpi_debug, flag, fmt, ## __VA_ARGS__) - -#define MPI_FUNCTION_ENTER() mpi_dbg_f(MPI_DBG_FUNCTION, "enter\n") -#define MPI_FUNCTION_LEAVE() mpi_dbg_f(MPI_DBG_FUNCTION, "leave\n") -#define MPI_FUNCTION_LEAVE_OK() mpi_dbg_f(MPI_DBG_FUNCTION, "success\n") -#define MPI_FUNCTION_LEAVE_FAIL() mpi_dbg_f(MPI_DBG_FUNCTION, "failed\n") - -typedef struct MpiImpl_t MpiImpl; - -struct MpiImpl_t { - MpiImpl *check; - MppCtxType type; - MppCodingType coding; - - MppApi *api; - Mpp *ctx; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -extern RK_U32 mpi_debug; -void get_mpi_debug(); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_IMPL_H__*/ diff --git a/mpp/mpp.c b/mpp/mpp.c index d397a45a7..bb9e25866 100644 --- a/mpp/mpp.c +++ b/mpp/mpp.c @@ -1,16 +1,1540 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp" + +#include +#include + +#include "rk_mpi.h" + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_impl.h" +#include "mpp_2str.h" +#include "mpp_debug.h" + +#include "mpp.h" +#include "mpp_hal.h" + +#include "mpp_task_impl.h" +#include "mpp_buffer_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_packet_impl.h" + +#include "kmpp.h" + +#define MPP_TEST_FRAME_SIZE SZ_1M +#define MPP_TEST_PACKET_SIZE SZ_512K + +static void mpp_notify_by_buffer_group(void *arg, void *group) +{ + Mpp *mpp = (Mpp *)arg; + mpp_notify_group(mpp, (MppBufferGroup)group); +} + +static void *list_wraper_packet(void *arg) +{ + MppPacket packet = *(MppPacket*)arg; + + if (mpp_packet_has_meta(packet)) { + MppMeta meta = mpp_packet_get_meta(packet); + MppFrame frm = NULL; + + if (MPP_OK == mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frm)) { + mpp_assert(frm); + mpp_frame_deinit(&frm); + } + } + + mpp_packet_deinit((MppPacket *)arg); + return NULL; +} + +static void *list_wraper_frame(void *arg) +{ + mpp_frame_deinit((MppFrame *)arg); + return NULL; +} + +static RK_S32 check_frm_task_cnt_cap(MppCodingType coding) +{ + RockchipSocType soc_type = mpp_get_soc_type(); + + if (soc_type == ROCKCHIP_SOC_RK3588 || soc_type == ROCKCHIP_SOC_RK3576) { + if (coding == MPP_VIDEO_CodingAVC || coding == MPP_VIDEO_CodingHEVC) + return 2; + if (coding == MPP_VIDEO_CodingMJPEG && soc_type == ROCKCHIP_SOC_RK3588) + return 4; + } + + mpp_log("Only rk3588's h264/265/jpeg and rk3576's h264/265 encoder can use frame parallel\n"); + + return 1; +} + +MPP_RET mpp_ctx_create(Mpp **mpp, MppCtx ctx) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + Mpp *p = mpp_calloc(Mpp, 1); + if (!p) { + mpp_err_f("failed to allocate mpp context\n"); + return MPP_ERR_MALLOC; + } + + /* Initialize all members to default values */ + p->mInputTaskCount = 1; + p->mOutputTaskCount = 1; + p->mInputTimeout = MPP_POLL_BUTT; + p->mOutputTimeout = MPP_POLL_BUTT; + p->mCtx = ctx; + p->mIoMode = MPP_IO_MODE_DEFAULT; + p->mType = MPP_CTX_BUTT; + p->mCoding = MPP_VIDEO_CodingUnused; + + mpp_env_get_u32("mpp_debug", &mpp_debug, 0); + + mpp_dec_cfg_init(&p->mDecCfg); + mpp_dec_cfg_set_u32(p->mDecCfg, "base:enable_vproc", MPP_VPROC_MODE_DEINTELACE); + + mpp_dump_init(&p->mDump); + + *mpp = p; + return MPP_OK; +} + +MPP_RET mpp_ctx_init(Mpp *mpp, MppCtxType type, MppCodingType coding) +{ + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp_check_soc_cap(type, coding)) { + mpp_err("unable to create %s %s for soc %s unsupported\n", + strof_ctx_type(type), strof_coding_type(coding), + mpp_get_soc_info()->compatible); + return MPP_NOK; + } + + if (mpp_check_support_format(type, coding)) { + mpp_err("unable to create %s %s for mpp unsupported\n", + strof_ctx_type(type), strof_coding_type(coding)); + return MPP_NOK; + } + + mpp_ops_init(mpp->mDump, type, coding); + + mpp->mType = type; + mpp->mCoding = coding; + + /* init kmpp venc */ + if (mpp->mVencInitKcfg) { + mpp->mKmpp = mpp_calloc(Kmpp, 1); + if (!mpp->mKmpp) { + mpp_err("failed to alloc kmpp context\n"); + return MPP_NOK; + } + mpp->mKmpp->mClientFd = -1; + mpp_get_api(mpp->mKmpp); + mpp->mKmpp->mVencInitKcfg = mpp->mVencInitKcfg; + ret = mpp->mKmpp->mApi->init(mpp->mKmpp, type, coding); + if (ret) { + mpp_err("failed to init kmpp ret %d\n", ret); + return ret; + } + mpp->mInitDone = 1; + return ret; + } + + mpp_task_queue_init(&mpp->mInputTaskQueue, mpp, "input"); + mpp_task_queue_init(&mpp->mOutputTaskQueue, mpp, "output"); + + switch (mpp->mType) { + case MPP_CTX_DEC : { + mpp->mPktIn = mpp_list_create(list_wraper_packet); + mpp->mFrmOut = mpp_list_create(list_wraper_frame); + + if (mpp->mInputTimeout == MPP_POLL_BUTT) + mpp->mInputTimeout = MPP_POLL_NON_BLOCK; + + if (mpp->mOutputTimeout == MPP_POLL_BUTT) + mpp->mOutputTimeout = MPP_POLL_NON_BLOCK; + + if (mpp->mCoding != MPP_VIDEO_CodingMJPEG) { + mpp_buffer_group_get_internal(&mpp->mPacketGroup, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE); + mpp_buffer_group_limit_config(mpp->mPacketGroup, 0, 3); + + mpp->mInputTaskCount = 4; + mpp->mOutputTaskCount = 4; + } + + mpp_task_queue_setup(mpp->mInputTaskQueue, mpp->mInputTaskCount); + mpp_task_queue_setup(mpp->mOutputTaskQueue, mpp->mOutputTaskCount); + + mpp->mUsrInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_INPUT); + mpp->mUsrOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_OUTPUT); + mpp->mMppInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_OUTPUT); + mpp->mMppOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_INPUT); + + mpp_dec_cfg_set_u32(mpp->mDecCfg, "base:disable_thread", mpp->mDisableThread); + + MppDecInitCfg cfg = { + coding, + mpp, + mpp->mDecCfg, + }; + + ret = mpp_dec_init(&mpp->mDec, &cfg); + if (ret) + break; + ret = mpp_dec_start(mpp->mDec); + if (ret) + break; + mpp->mInitDone = 1; + } break; + case MPP_CTX_ENC : { + mpp->mPktOut = mpp_list_create(list_wraper_packet); + mpp->mFrmIn = mpp_list_create(list_wraper_frame); + + if (mpp->mInputTimeout == MPP_POLL_BUTT) + mpp->mInputTimeout = MPP_POLL_BLOCK; + + if (mpp->mOutputTimeout == MPP_POLL_BUTT) + mpp->mOutputTimeout = MPP_POLL_NON_BLOCK; + + mpp_buffer_group_get_internal(&mpp->mPacketGroup, MPP_BUFFER_TYPE_ION); + mpp_buffer_group_get_internal(&mpp->mFrameGroup, MPP_BUFFER_TYPE_ION); + + if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) { + mpp->mEncAyncIo = 1; + + mpp->mInputTaskCount = check_frm_task_cnt_cap(coding); + if (mpp->mInputTaskCount == 1) + mpp->mInputTimeout = MPP_POLL_BLOCK; + } + mpp->mOutputTaskCount = 8; + + mpp_task_queue_setup(mpp->mInputTaskQueue, mpp->mInputTaskCount); + mpp_task_queue_setup(mpp->mOutputTaskQueue, mpp->mOutputTaskCount); + + mpp->mUsrInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_INPUT); + mpp->mUsrOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_OUTPUT); + mpp->mMppInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_OUTPUT); + mpp->mMppOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_INPUT); + + MppEncInitCfg cfg = { + coding, + mpp->mInputTaskCount, + mpp, + }; + + ret = mpp_enc_init_v2(&mpp->mEnc, &cfg); + if (ret) + break; + + if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) { + mpp->mEncAyncProc = 1; + ret = mpp_enc_start_async(mpp->mEnc); + } else { + ret = mpp_enc_start_v2(mpp->mEnc); + } + + if (ret) + break; + mpp->mInitDone = 1; + } break; + default : { + mpp_err("Mpp error type %d\n", mpp->mType); + } break; + } + + if (!mpp->mInitDone) { + mpp_err("error found on mpp initialization\n"); + mpp_clear(mpp); + } + + return ret; +} + +void mpp_clear(Mpp *mpp) +{ + if (!mpp) + return; + + /* MUST: release listener here */ + if (mpp->mFrameGroup) + mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup, + NULL, NULL); + + if (mpp->mType == MPP_CTX_DEC) { + if (mpp->mDec) { + mpp_dec_stop(mpp->mDec); + mpp_dec_deinit(mpp->mDec); + mpp->mDec = NULL; + } + } else { + if (mpp->mEnc) { + mpp_enc_stop_v2(mpp->mEnc); + mpp_enc_deinit_v2(mpp->mEnc); + mpp->mEnc = NULL; + } + } + + if (mpp->mInputTaskQueue) { + mpp_task_queue_deinit(mpp->mInputTaskQueue); + mpp->mInputTaskQueue = NULL; + } + if (mpp->mOutputTaskQueue) { + mpp_task_queue_deinit(mpp->mOutputTaskQueue); + mpp->mOutputTaskQueue = NULL; + } + + mpp->mUsrInPort = NULL; + mpp->mUsrOutPort = NULL; + mpp->mMppInPort = NULL; + mpp->mMppOutPort = NULL; + + if (mpp->mExtraPacket) { + mpp_packet_deinit(&mpp->mExtraPacket); + mpp->mExtraPacket = NULL; + } + + if (mpp->mPktIn) { + mpp_list_destroy(mpp->mPktIn); + mpp->mPktIn = NULL; + } + if (mpp->mPktOut) { + mpp_list_destroy(mpp->mPktOut); + mpp->mPktOut = NULL; + } + if (mpp->mFrmIn) { + mpp_list_destroy(mpp->mFrmIn); + mpp->mFrmIn = NULL; + } + if (mpp->mFrmOut) { + mpp_list_destroy(mpp->mFrmOut); + mpp->mFrmOut = NULL; + } + + if (mpp->mPacketGroup) { + mpp_buffer_group_put(mpp->mPacketGroup); + mpp->mPacketGroup = NULL; + } + + if (mpp->mFrameGroup && !mpp->mExternalBufferMode) { + mpp_buffer_group_put(mpp->mFrameGroup); + mpp->mFrameGroup = NULL; + } + + if (mpp->mKmpp) { + if (mpp->mKmpp->mApi && mpp->mKmpp->mApi->clear) + mpp->mKmpp->mApi->clear(mpp->mKmpp); + + MPP_FREE(mpp->mKmpp); + } + + if (mpp->mDecCfg) { + mpp_dec_cfg_deinit(mpp->mDecCfg); + mpp->mDecCfg = NULL; + } + + mpp_dump_deinit(&mpp->mDump); +} + +MPP_RET mpp_ctx_destroy(Mpp *mpp) +{ + if (!mpp) + return MPP_OK; + + mpp_clear(mpp); + mpp_free(mpp); + + return MPP_OK; +} + +MPP_RET mpp_start(Mpp *mpp) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + return MPP_OK; +} + +MPP_RET mpp_stop(Mpp *mpp) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + return MPP_OK; +} + +MPP_RET mpp_pause(Mpp *mpp) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + return MPP_OK; +} + +MPP_RET mpp_resume(Mpp *mpp) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + return MPP_OK; +} + +MPP_RET mpp_put_packet(Mpp *mpp, MppPacket packet) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + MPP_RET ret = MPP_NOK; + MppPollType timeout = mpp->mInputTimeout; + MppTask task_dequeue = NULL; + RK_U32 pkt_copy = 0; + + if (mpp->mDisableThread) { + mpp_err_f("no thread decoding case MUST use mpi_decode interface\n"); + return ret; + } + + if (mpp->mExtraPacket) { + MppPacket extra = mpp->mExtraPacket; + + mpp->mExtraPacket = NULL; + mpp_put_packet(mpp, extra); + } + + /* non-jpeg mode - reserve extra task for incoming eos packet */ + if (mpp->mInputTaskCount > 1) { + if (!mpp->mEosTask) { + /* handle eos packet on block mode */ + ret = mpp_poll(mpp, MPP_PORT_INPUT, MPP_POLL_BLOCK); + if (ret < 0) + goto RET; + + mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mEosTask); + if (NULL == mpp->mEosTask) { + mpp_err_f("fail to reserve eos task\n"); + ret = MPP_NOK; + goto RET; + } + } + + if (mpp_packet_get_eos(packet)) { + mpp_assert(mpp->mEosTask); + task_dequeue = mpp->mEosTask; + mpp->mEosTask = NULL; + } + } + + /* Use reserved task to send eos packet */ + if (mpp->mInputTask && !task_dequeue) { + task_dequeue = mpp->mInputTask; + mpp->mInputTask = NULL; + } + + if (NULL == task_dequeue) { + ret = mpp_poll(mpp, MPP_PORT_INPUT, timeout); + if (ret < 0) { + ret = MPP_ERR_BUFFER_FULL; + goto RET; + } + + /* do not pull here to avoid block wait */ + mpp_dequeue(mpp, MPP_PORT_INPUT, &task_dequeue); + if (NULL == task_dequeue) { + mpp_err_f("fail to get task on poll ret %d\n", ret); + ret = MPP_NOK; + goto RET; + } + } + + if (NULL == mpp_packet_get_buffer(packet)) { + /* packet copy path */ + MppPacket pkt_in = NULL; + + mpp_packet_copy_init(&pkt_in, packet); + mpp_packet_set_length(packet, 0); + pkt_copy = 1; + packet = pkt_in; + ret = MPP_OK; + } else { + /* packet zero copy path */ + timeout = MPP_POLL_BLOCK; + ret = MPP_OK; + } + + /* setup task */ + ret = mpp_task_meta_set_packet(task_dequeue, KEY_INPUT_PACKET, packet); + if (ret) { + mpp_err_f("set input frame to task ret %d\n", ret); + /* keep current task for next */ + mpp->mInputTask = task_dequeue; + goto RET; + } + + mpp_ops_dec_put_pkt(mpp->mDump, packet); + + /* enqueue valid task to decoder */ + ret = mpp_enqueue(mpp, MPP_PORT_INPUT, task_dequeue); + if (ret) { + mpp_err_f("enqueue ret %d\n", ret); + goto RET; + } + + mpp->mPacketPutCount++; + + if (timeout && !pkt_copy) + mpp_poll(mpp, MPP_PORT_INPUT, timeout); + +RET: + /* wait enqueued task finished */ + if (NULL == mpp->mInputTask) { + MPP_RET cnt = mpp_poll(mpp, MPP_PORT_INPUT, MPP_POLL_NON_BLOCK); + /* reserve one task for eos block mode */ + if (cnt >= 0) { + mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mInputTask); + mpp_assert(mpp->mInputTask); + } + } + + return ret; +} + +MPP_RET mpp_get_frame(Mpp *mpp, MppFrame *frame) +{ + MppFrame frm = NULL; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock); + + if (0 == mpp_list_size(mpp->mFrmOut)) { + if (mpp->mOutputTimeout) { + if (mpp->mOutputTimeout < 0) { + /* block wait */ + mpp_list_wait(mpp->mFrmOut); + } else { + MPP_RET ret = mpp_list_wait_timed(mpp->mFrmOut, mpp->mOutputTimeout); + + if (ret) { + mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock); + return ret; + } + } + } + } + + if (mpp_list_size(mpp->mFrmOut)) { + MppBuffer buffer; + + mpp_list_del_at_head(mpp->mFrmOut, &frm, sizeof(frm)); + mpp->mFrameGetCount++; + mpp_notify_flag(mpp, MPP_OUTPUT_DEQUEUE); + + buffer = mpp_frame_get_buffer(frm); + if (buffer) + mpp_buffer_sync_ro_begin(buffer); + } else { + // NOTE: Add signal here is not efficient + // This is for fix bug of stucking on decoder parser thread + // When decoder parser thread is block by info change and enter waiting. + // There is no way to wake up parser thread to continue decoding. + // The put_packet only signal sem on may be it better to use sem on info + // change too. + mpp_mutex_cond_lock(&mpp->mPktIn->cond_lock); + if (mpp_list_size(mpp->mPktIn)) + mpp_notify_flag(mpp, MPP_INPUT_ENQUEUE); + mpp_mutex_cond_unlock(&mpp->mPktIn->cond_lock); + } + + *frame = frm; + + // dump output + mpp_ops_dec_get_frm(mpp->mDump, frm); + mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock); + + return MPP_OK; +} + +MPP_RET mpp_get_frame_noblock(Mpp *mpp, MppFrame *frame) +{ + MppFrame first = NULL; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock); + if (mpp_list_size(mpp->mFrmOut)) { + mpp_list_del_at_head(mpp->mFrmOut, &first, sizeof(first)); + mpp_buffer_sync_ro_begin(mpp_frame_get_buffer(first)); + mpp->mFrameGetCount++; + } + mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock); + *frame = first; + + return MPP_OK; +} + +MPP_RET mpp_decode(Mpp *mpp, MppPacket packet, MppFrame *frame) +{ + RK_U32 pkt_done = 0; + RK_S32 frm_rdy = 0; + MPP_RET ret = MPP_OK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mDec) + return MPP_NOK; + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + /* + * If there is frame to return get the frame first + * But if the output mode is block then we need to send packet first + */ + if (!mpp->mOutputTimeout) { + mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock); + if (mpp_list_size(mpp->mFrmOut)) { + MppBuffer buffer; + + mpp_list_del_at_head(mpp->mFrmOut, frame, sizeof(*frame)); + buffer = mpp_frame_get_buffer(*frame); + if (buffer) + mpp_buffer_sync_ro_begin(buffer); + mpp->mFrameGetCount++; + mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock); + return MPP_OK; + } + mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock); + } + + do { + if (!pkt_done) + ret = mpp_dec_decode(mpp->mDec, packet); + + /* check input packet finished or not */ + if (!packet || !mpp_packet_get_length(packet)) + pkt_done = 1; + + /* always try getting frame */ + mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock); + if (mpp_list_size(mpp->mFrmOut)) { + MppBuffer buffer; + + mpp_list_del_at_head(mpp->mFrmOut, frame, sizeof(*frame)); + buffer = mpp_frame_get_buffer(*frame); + if (buffer) + mpp_buffer_sync_ro_begin(buffer); + mpp->mFrameGetCount++; + frm_rdy = 1; + } + mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock); + + /* return on flow error */ + if (ret < 0) + break; + + /* return on output frame is ready */ + if (frm_rdy) { + mpp_assert(ret > 0); + ret = MPP_OK; + break; + } + + /* return when packet is send and it is a non-block call */ + if (pkt_done) { + ret = MPP_OK; + break; + } + + /* otherwise continue decoding and getting frame */ + } while (1); + + return ret; +} + +MPP_RET mpp_put_frame(Mpp *mpp, MppFrame frame) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + sys_dbg_pts("%p input frame pts %lld\n", mpp, mpp_frame_get_pts(frame)); + + if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->put_frame) + return mpp->mKmpp->mApi->put_frame(mpp->mKmpp, frame); + + if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) { + mpp_set_io_mode(mpp, MPP_IO_MODE_NORMAL); + return mpp_put_frame_async(mpp, frame); + } + + MPP_RET ret = MPP_NOK; + MppStopwatch stopwatch = NULL; + + if (mpp_debug & MPP_DBG_TIMING) { + mpp_frame_set_stopwatch_enable(frame, 1); + stopwatch = mpp_frame_get_stopwatch(frame); + } + + mpp_stopwatch_record(stopwatch, NULL); + mpp_stopwatch_record(stopwatch, "put frame start"); + + if (mpp->mInputTask == NULL) { + mpp_stopwatch_record(stopwatch, "input port user poll"); + /* poll input port for valid task */ + ret = mpp_poll(mpp, MPP_PORT_INPUT, mpp->mInputTimeout); + if (ret < 0) { + if (mpp->mInputTimeout) + mpp_log_f("poll on set timeout %d ret %d\n", mpp->mInputTimeout, ret); + goto RET; + } + + /* dequeue task for setup */ + mpp_stopwatch_record(stopwatch, "input port user dequeue"); + ret = mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mInputTask); + if (ret || NULL == mpp->mInputTask) { + mpp_log_f("dequeue on set ret %d task %p\n", ret, mpp->mInputTask); + goto RET; + } + } + + mpp_assert(mpp->mInputTask); + + /* setup task */ + ret = mpp_task_meta_set_frame(mpp->mInputTask, KEY_INPUT_FRAME, frame); + if (ret) { + mpp_log_f("set input frame to task ret %d\n", ret); + goto RET; + } + + if (mpp_frame_has_meta(frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + MppPacket packet = NULL; + MppBuffer md_info_buf = NULL; + + mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet); + if (packet) { + ret = mpp_task_meta_set_packet(mpp->mInputTask, KEY_OUTPUT_PACKET, packet); + if (ret) { + mpp_log_f("set output packet to task ret %d\n", ret); + goto RET; + } + } + + mpp_meta_get_buffer(meta, KEY_MOTION_INFO, &md_info_buf); + if (md_info_buf) { + ret = mpp_task_meta_set_buffer(mpp->mInputTask, KEY_MOTION_INFO, md_info_buf); + if (ret) { + mpp_log_f("set output motion dection info ret %d\n", ret); + goto RET; + } + } + } + + // dump input + mpp_ops_enc_put_frm(mpp->mDump, frame); + + /* enqueue valid task to encoder */ + mpp_stopwatch_record(stopwatch, "input port user enqueue"); + ret = mpp_enqueue(mpp, MPP_PORT_INPUT, mpp->mInputTask); + if (ret) { + mpp_log_f("enqueue ret %d\n", ret); + goto RET; + } + + mpp->mInputTask = NULL; + /* wait enqueued task finished */ + mpp_stopwatch_record(stopwatch, "input port user poll"); + ret = mpp_poll(mpp, MPP_PORT_INPUT, mpp->mInputTimeout); + if (ret < 0) { + if (mpp->mInputTimeout) + mpp_log_f("poll on get timeout %d ret %d\n", mpp->mInputTimeout, ret); + goto RET; + } + + /* get previous enqueued task back */ + mpp_stopwatch_record(stopwatch, "input port user dequeue"); + ret = mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mInputTask); + if (ret) { + mpp_log_f("dequeue on get ret %d\n", ret); + goto RET; + } + + mpp_assert(mpp->mInputTask); + if (mpp->mInputTask) { + MppFrame frm_out = NULL; + + mpp_task_meta_get_frame(mpp->mInputTask, KEY_INPUT_FRAME, &frm_out); + mpp_assert(frm_out == frame); + } + +RET: + mpp_stopwatch_record(stopwatch, "put_frame finish"); + mpp_frame_set_stopwatch_enable(frame, 0); + return ret; +} + +MPP_RET mpp_get_packet(Mpp *mpp, MppPacket *packet) +{ + MppPacket pkt = NULL; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->get_packet) + return mpp->mKmpp->mApi->get_packet(mpp->mKmpp, packet); + + if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) { + mpp_set_io_mode(mpp, MPP_IO_MODE_NORMAL); + return mpp_get_packet_async(mpp, packet); + } + + MPP_RET ret = MPP_OK; + MppTask task = NULL; + + ret = mpp_poll(mpp, MPP_PORT_OUTPUT, mpp->mOutputTimeout); + if (ret < 0) { + // NOTE: Do not treat poll failure as error. Just clear output + ret = MPP_OK; + *packet = NULL; + goto RET; + } + + ret = mpp_dequeue(mpp, MPP_PORT_OUTPUT, &task); + if (ret || NULL == task) { + mpp_log_f("dequeue on get ret %d task %p\n", ret, task); + goto RET; + } + + mpp_assert(task); + + ret = mpp_task_meta_get_packet(task, KEY_OUTPUT_PACKET, packet); + if (ret) { + mpp_log_f("get output packet from task ret %d\n", ret); + goto RET; + } + + pkt = *packet; + if (!pkt) { + mpp_log_f("get invalid task without output packet\n"); + } else { + MppPacketImpl *impl = (MppPacketImpl *)pkt; + MppBuffer buf = impl->buffer; + + if (buf) { + RK_U32 offset = (RK_U32)((char *)impl->pos - (char *)impl->data); + + mpp_buffer_sync_ro_partial_begin(buf, offset, impl->length); + } + + sys_dbg_pts("%p output packet pts %lld\n", mpp, impl->pts); + } + + // dump output + mpp_ops_enc_get_pkt(mpp->mDump, pkt); + + ret = mpp_enqueue(mpp, MPP_PORT_OUTPUT, task); + if (ret) + mpp_log_f("enqueue on set ret %d\n", ret); +RET: + + return ret; +} + +MPP_RET mpp_put_frame_async(Mpp *mpp, MppFrame frame) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (NULL == mpp->mFrmIn) + return MPP_NOK; + + if (mpp_mutex_cond_trylock(&mpp->mFrmIn->cond_lock)) + return MPP_NOK; + + /* NOTE: the max input queue length is 2 */ + if (mpp_list_wait_le(mpp->mFrmIn, 10, 1)) { + mpp_mutex_cond_unlock(&mpp->mFrmIn->cond_lock); + return MPP_NOK; + } + + mpp_list_add_at_tail(mpp->mFrmIn, &frame, sizeof(frame)); + mpp->mFramePutCount++; + + mpp_notify_flag(mpp, MPP_INPUT_ENQUEUE); + mpp_mutex_cond_unlock(&mpp->mFrmIn->cond_lock); + + return MPP_OK; +} + +MPP_RET mpp_get_packet_async(Mpp *mpp, MppPacket *packet) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_mutex_cond_lock(&mpp->mPktOut->cond_lock); + *packet = NULL; + if (0 == mpp_list_size(mpp->mPktOut)) { + if (mpp->mOutputTimeout) { + if (mpp->mOutputTimeout < 0) { + /* block wait */ + mpp_list_wait(mpp->mPktOut); + } else { + MPP_RET ret = mpp_list_wait_timed(mpp->mPktOut, mpp->mOutputTimeout); + + if (ret) { + mpp_mutex_cond_unlock(&mpp->mPktOut->cond_lock); + return ret; + } + } + } else { + /* NOTE: in non-block mode the sleep is to avoid user's dead loop */ + msleep(1); + } + } + + if (mpp_list_size(mpp->mPktOut)) { + MppPacket pkt = NULL; + MppPacketImpl *impl = NULL; + RK_U32 offset; + + mpp_list_del_at_head(mpp->mPktOut, &pkt, sizeof(pkt)); + mpp->mPacketGetCount++; + mpp_notify_flag(mpp, MPP_OUTPUT_DEQUEUE); + + *packet = pkt; + + impl = (MppPacketImpl *)pkt; + if (impl->buffer) { + offset = (RK_U32)((char *)impl->pos - (char *)impl->data); + mpp_buffer_sync_ro_partial_begin(impl->buffer, offset, impl->length); + } + } else { + mpp_mutex_cond_lock(&mpp->mFrmIn->cond_lock); + if (mpp_list_size(mpp->mFrmIn)) + mpp_notify_flag(mpp, MPP_INPUT_ENQUEUE); + mpp_mutex_cond_unlock(&mpp->mFrmIn->cond_lock); + mpp_mutex_cond_unlock(&mpp->mPktOut->cond_lock); + + return MPP_NOK; + } + mpp_mutex_cond_unlock(&mpp->mPktOut->cond_lock); + + return MPP_OK; +} + +MPP_RET mpp_poll(Mpp *mpp, MppPortType type, MppPollType timeout) +{ + MppTaskQueue port = NULL; + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + mpp_set_io_mode(mpp, MPP_IO_MODE_TASK); + + switch (type) { + case MPP_PORT_INPUT : { + port = mpp->mUsrInPort; + } break; + case MPP_PORT_OUTPUT : { + port = mpp->mUsrOutPort; + } break; + default : { + } break; + } + + if (port) + ret = mpp_port_poll(port, timeout); + + return ret; +} + +MPP_RET mpp_dequeue(Mpp *mpp, MppPortType type, MppTask *task) +{ + MppTaskQueue port = NULL; + RK_U32 notify_flag = 0; + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + mpp_set_io_mode(mpp, MPP_IO_MODE_TASK); + + switch (type) { + case MPP_PORT_INPUT : { + port = mpp->mUsrInPort; + notify_flag = MPP_INPUT_DEQUEUE; + } break; + case MPP_PORT_OUTPUT : { + port = mpp->mUsrOutPort; + notify_flag = MPP_OUTPUT_DEQUEUE; + } break; + default : { + } break; + } + + if (port) { + ret = mpp_port_dequeue(port, task); + if (MPP_OK == ret) + mpp_notify_flag(mpp, notify_flag); + } + + return ret; +} + +MPP_RET mpp_enqueue(Mpp *mpp, MppPortType type, MppTask task) +{ + MppTaskQueue port = NULL; + RK_U32 notify_flag = 0; + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + mpp_set_io_mode(mpp, MPP_IO_MODE_TASK); + + switch (type) { + case MPP_PORT_INPUT : { + port = mpp->mUsrInPort; + notify_flag = MPP_INPUT_ENQUEUE; + } break; + case MPP_PORT_OUTPUT : { + port = mpp->mUsrOutPort; + notify_flag = MPP_OUTPUT_ENQUEUE; + } break; + default : { + } break; + } + + if (port) { + ret = mpp_port_enqueue(port, task); + // if enqueue success wait up thread + if (MPP_OK == ret) + mpp_notify_flag(mpp, notify_flag); + } + + return ret; +} + +void mpp_set_io_mode(Mpp *mpp, MppIoMode mode) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return; + } + + mpp_assert(mode == MPP_IO_MODE_NORMAL || mode == MPP_IO_MODE_TASK); + + if (mpp->mIoMode == MPP_IO_MODE_DEFAULT) + mpp->mIoMode = mode; + else if (mpp->mIoMode != mode) { + static const char *iomode_2str[] = { + "normal", + "task queue", + }; + + mpp_assert(mpp->mIoMode < MPP_IO_MODE_BUTT); + mpp_assert(mode < MPP_IO_MODE_BUTT); + mpp_err("can not reset io mode from %s to %s\n", + iomode_2str[!!mpp->mIoMode], iomode_2str[!!mode]); + } +} + +MPP_RET mpp_control(Mpp *mpp, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_ops_ctrl(mpp->mDump, cmd); + + if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->control) + return mpp->mKmpp->mApi->control(mpp->mKmpp, cmd, param); + + switch (cmd & CMD_MODULE_ID_MASK) { + case CMD_MODULE_OSAL : { + ret = mpp_control_osal(mpp, cmd, param); + } break; + case CMD_MODULE_MPP : { + mpp_assert(cmd > MPP_CMD_BASE); + mpp_assert(cmd < MPP_CMD_END); + + ret = mpp_control_mpp(mpp, cmd, param); + } break; + case CMD_MODULE_CODEC : { + switch (cmd & CMD_CTX_ID_MASK) { + case CMD_CTX_ID_DEC : { + mpp_assert(mpp->mType == MPP_CTX_DEC || mpp->mType == MPP_CTX_BUTT); + mpp_assert(cmd > MPP_DEC_CMD_BASE); + mpp_assert(cmd < MPP_DEC_CMD_END); + + ret = mpp_control_dec(mpp, cmd, param); + } break; + case CMD_CTX_ID_ENC : { + mpp_assert(mpp->mType == MPP_CTX_ENC); + mpp_assert(cmd > MPP_ENC_CMD_BASE); + mpp_assert(cmd < MPP_ENC_CMD_END); + + ret = mpp_control_enc(mpp, cmd, param); + } break; + case CMD_CTX_ID_ISP : { + mpp_assert(mpp->mType == MPP_CTX_ISP); + ret = mpp_control_isp(mpp, cmd, param); + } break; + default : { + mpp_assert(cmd > MPP_CODEC_CMD_BASE); + mpp_assert(cmd < MPP_CODEC_CMD_END); + + ret = mpp_control_codec(mpp, cmd, param); + } break; + } + } break; + default : { + } break; + } + + if (ret) + mpp_err("command %x param %p ret %d\n", cmd, param, ret); + + return ret; +} + +MPP_RET mpp_reset(Mpp *mpp) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + if (!mpp->mInitDone) + return MPP_ERR_INIT; + + if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->reset) + return mpp->mKmpp->mApi->reset(mpp->mKmpp); + + mpp_ops_reset(mpp->mDump); + + if (mpp->mType == MPP_CTX_DEC) { + /* + * On mp4 case extra data of sps/pps will be put at the beginning + * If these packet was reset before they are send to decoder then + * decoder can not get these important information to continue decoding + * To avoid this case happen we need to save it on reset beginning + * then restore it on reset end. + */ + mpp_mutex_cond_lock(&mpp->mPktIn->cond_lock); + while (mpp_list_size(mpp->mPktIn)) { + MppPacket pkt = NULL; + + mpp_list_del_at_head(mpp->mPktIn, &pkt, sizeof(pkt)); + mpp->mPacketGetCount++; + + RK_U32 flags = mpp_packet_get_flag(pkt); + if (flags & MPP_PACKET_FLAG_EXTRA_DATA) { + if (mpp->mExtraPacket) { + mpp_packet_deinit(&mpp->mExtraPacket); + } + mpp->mExtraPacket = pkt; + } else { + mpp_packet_deinit(&pkt); + } + } + mpp_list_flush(mpp->mPktIn); + mpp_mutex_cond_unlock(&mpp->mPktIn->cond_lock); + + mpp_dec_reset(mpp->mDec); + + mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock); + mpp_list_flush(mpp->mFrmOut); + mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock); + + mpp_port_awake(mpp->mUsrInPort); + mpp_port_awake(mpp->mUsrOutPort); + } else { + mpp_enc_reset_v2(mpp->mEnc); + } + + return MPP_OK; +} + +MPP_RET mpp_control_mpp(Mpp *mpp, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_OK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + switch (cmd) { + case MPP_SET_INPUT_BLOCK : + case MPP_SET_OUTPUT_BLOCK : + case MPP_SET_INTPUT_BLOCK_TIMEOUT : + case MPP_SET_OUTPUT_BLOCK_TIMEOUT : { + MppPollType block = (param) ? *((MppPollType *)param) : MPP_POLL_NON_BLOCK; + + if (block <= MPP_POLL_BUTT || block > MPP_POLL_MAX) { + mpp_err("invalid output timeout type %d should be in range [%d, %d]\n", + block, MPP_POLL_BUTT, MPP_POLL_MAX); + ret = MPP_ERR_VALUE; + break; + } + if (cmd == MPP_SET_INPUT_BLOCK || cmd == MPP_SET_INTPUT_BLOCK_TIMEOUT) + mpp->mInputTimeout = block; + else + mpp->mOutputTimeout = block; + + mpp_log("deprecated block control, use timeout control instead\n"); + } break; + + case MPP_SET_DISABLE_THREAD: { + mpp->mDisableThread = 1; + } break; + + case MPP_SET_INPUT_TIMEOUT: + case MPP_SET_OUTPUT_TIMEOUT: { + MppPollType timeout = (param) ? *((MppPollType *)param) : MPP_POLL_NON_BLOCK; + + if (timeout <= MPP_POLL_BUTT || timeout > MPP_POLL_MAX) { + mpp_err("invalid output timeout type %d should be in range [%d, %d]\n", + timeout, MPP_POLL_BUTT, MPP_POLL_MAX); + ret = MPP_ERR_VALUE; + break; + } + + if (cmd == MPP_SET_INPUT_TIMEOUT) + mpp->mInputTimeout = timeout; + else + mpp->mOutputTimeout = timeout; + } break; + case MPP_SET_VENC_INIT_KCFG: { + KmppObj obj = param; + + if (!obj) { + mpp_err_f("ctrl %d invalid param %p\n", cmd, param); + return MPP_ERR_VALUE; + } + mpp->mVencInitKcfg = obj; + } break; + case MPP_START : { + mpp_start(mpp); + } break; + case MPP_STOP : { + mpp_stop(mpp); + } break; + + case MPP_PAUSE : { + mpp_pause(mpp); + } break; + case MPP_RESUME : { + mpp_resume(mpp); + } break; + + default : { + ret = MPP_NOK; + } break; + } + return ret; +} + +MPP_RET mpp_control_osal(Mpp *mpp, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_assert(cmd > MPP_OSAL_CMD_BASE); + mpp_assert(cmd < MPP_OSAL_CMD_END); + + (void)cmd; + (void)param; + return ret; +} + +MPP_RET mpp_control_codec(Mpp *mpp, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + (void)cmd; + (void)param; + return ret; +} + +MPP_RET mpp_control_dec(Mpp *mpp, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + switch (cmd) { + case MPP_DEC_GET_THUMBNAIL_FRAME_INFO: + case MPP_DEC_SET_FRAME_INFO: { + ret = mpp_dec_control(mpp->mDec, cmd, param); + } break; + case MPP_DEC_SET_EXT_BUF_GROUP: { + /* + * NOTE: If frame buffer group is configured before decoder init + * then the buffer limitation maybe not be correctly setup + * without infomation from InfoChange frame. + * And the thread signal connection may not be setup here. It + * may have a bad effect on MPP efficiency. + */ + if (!mpp->mInitDone) { + mpp_err("WARNING: setup buffer group before decoder init\n"); + break; + } + + ret = MPP_OK; + if (!param) { + /* set to internal mode */ + if (mpp->mExternalBufferMode) { + /* switch from external mode to internal mode */ + mpp_assert(mpp->mFrameGroup); + mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup, + NULL, NULL); + mpp->mFrameGroup = NULL; + } else { + /* keep internal buffer mode cleanup old buffers */ + if (mpp->mFrameGroup) + mpp_buffer_group_clear(mpp->mFrameGroup); + } + + sys_dbg_info("using internal buffer group %p\n", mpp->mFrameGroup); + mpp->mExternalBufferMode = 0; + } else { + /* set to external mode */ + if (mpp->mExternalBufferMode) { + /* keep external buffer mode */ + if (mpp->mFrameGroup != param) { + /* switch to new buffer group */ + mpp_assert(mpp->mFrameGroup); + mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup, + NULL, NULL); + } else { + /* keep old group the external group user should cleanup its old buffers */ + } + } else { + /* switch from intenal mode to external mode */ + if (mpp->mFrameGroup) + mpp_buffer_group_put(mpp->mFrameGroup); + } + + sys_dbg_info("using external buffer group %p\n", mpp->mFrameGroup); + + mpp->mFrameGroup = (MppBufferGroup)param; + mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup, + mpp_notify_by_buffer_group, (void *)mpp); + mpp->mExternalBufferMode = 1; + mpp_notify_flag(mpp, MPP_DEC_NOTIFY_EXT_BUF_GRP_READY); + } + } break; + case MPP_DEC_SET_INFO_CHANGE_READY: { + sys_dbg_info("set info change ready\n"); + + ret = mpp_dec_control(mpp->mDec, cmd, param); + mpp_notify_flag(mpp, MPP_DEC_NOTIFY_INFO_CHG_DONE | MPP_DEC_NOTIFY_BUFFER_MATCH); + } break; + case MPP_DEC_SET_PRESENT_TIME_ORDER : + case MPP_DEC_SET_PARSER_SPLIT_MODE : + case MPP_DEC_SET_PARSER_FAST_MODE : + case MPP_DEC_SET_IMMEDIATE_OUT : + case MPP_DEC_SET_DISABLE_ERROR : + case MPP_DEC_SET_DIS_ERR_CLR_MARK : + case MPP_DEC_SET_ENABLE_DEINTERLACE : + case MPP_DEC_SET_ENABLE_FAST_PLAY : + case MPP_DEC_SET_ENABLE_MVC : + case MPP_DEC_SET_DISABLE_DPB_CHECK : + case MPP_DEC_SET_CODEC_MODE : { + /* + * These control may be set before mpp_init + * When this case happen record the config and wait for decoder init + */ + if (mpp->mDec) { + ret = mpp_dec_control(mpp->mDec, cmd, param); + return ret; + } + + ret = mpp_dec_set_cfg_by_cmd(mpp->mDecCfg, cmd, param); + } break; + case MPP_DEC_GET_STREAM_COUNT: { + mpp_mutex_cond_lock(&mpp->mPktIn->cond_lock); + *((RK_S32 *)param) = mpp_list_size(mpp->mPktIn); + ret = MPP_OK; + mpp_mutex_cond_unlock(&mpp->mPktIn->cond_lock); + } break; + case MPP_DEC_GET_VPUMEM_USED_COUNT : + case MPP_DEC_SET_OUTPUT_FORMAT : + case MPP_DEC_QUERY : + case MPP_DEC_SET_MAX_USE_BUFFER_SIZE: { + ret = mpp_dec_control(mpp->mDec, cmd, param); + } break; + case MPP_DEC_SET_CFG : { + if (mpp->mDec) + ret = mpp_dec_control(mpp->mDec, cmd, param); + else if (param) { + ret = (MPP_RET)kmpp_obj_update(mpp->mDecCfg, param); + } + } break; + case MPP_DEC_GET_CFG : { + if (mpp->mDec) + ret = mpp_dec_control(mpp->mDec, cmd, param); + else if (param) { + ret = (MPP_RET)kmpp_obj_copy_entry(param, mpp->mDecCfg); + } + } break; + default : { + } break; + } + return ret; +} + +MPP_RET mpp_control_enc(Mpp *mpp, MpiCmd cmd, MppParam param) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_assert(mpp->mEnc); + return mpp_enc_control_v2(mpp->mEnc, cmd, param); +} + +MPP_RET mpp_control_isp(Mpp *mpp, MpiCmd cmd, MppParam param) +{ + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_assert(cmd > MPP_ISP_CMD_BASE); + mpp_assert(cmd < MPP_ISP_CMD_END); + + (void)cmd; + (void)param; + return ret; +} + +MPP_RET mpp_notify_flag(Mpp *mpp, RK_U32 flag) +{ + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + switch (mpp->mType) { + case MPP_CTX_DEC : { + return mpp_dec_notify(mpp->mDec, flag); + } break; + case MPP_CTX_ENC : { + return mpp_enc_notify_v2(mpp->mEnc, flag); + } break; + default : { + mpp_err("unsupport context type %d\n", mpp->mType); + } break; + } + return MPP_NOK; +} + +MPP_RET mpp_notify_group(Mpp *mpp, MppBufferGroup group) +{ + MPP_RET ret = MPP_NOK; + + if (!mpp) { + mpp_err_f("invalid input mpp pointer\n"); + return MPP_ERR_NULL_PTR; + } + + switch (mpp->mType) { + case MPP_CTX_DEC : { + if (group == mpp->mFrameGroup) + ret = mpp_notify_flag(mpp, MPP_DEC_NOTIFY_BUFFER_VALID | MPP_DEC_NOTIFY_BUFFER_MATCH); + } break; + default : { + } break; + } + + return ret; +} diff --git a/mpp/mpp.cpp b/mpp/mpp.cpp deleted file mode 100644 index a5cb0e985..000000000 --- a/mpp/mpp.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp" - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_env.h" -#include "mpp_time.h" - -#include "mpp.h" -#include "mpp_dec.h" -#include "mpp_enc.h" -#include "mpp_hal.h" -#include "mpp_frame_impl.h" -#include "mpp_packet.h" -#include "mpp_packet_impl.h" - -#define MPP_TEST_FRAME_SIZE SZ_1M - -RK_U32 mpp_debug = 0; - -Mpp::Mpp(MppCtxType type, MppCodingType coding) - : mPackets(NULL), - mFrames(NULL), - mTasks(NULL), - mPacketPutCount(0), - mPacketGetCount(0), - mFramePutCount(0), - mFrameGetCount(0), - mTaskPutCount(0), - mTaskGetCount(0), - mInternalGroup(NULL), - mPacketGroup(NULL), - mFrameGroup(NULL), - mThreadCodec(NULL), - mThreadHal(NULL), - mType(type), - mCoding(coding), - mStatus(0), - mDec(NULL), - mEnc(NULL) -{ - switch (mType) { - case MPP_CTX_DEC : { - mPackets = new mpp_list((node_destructor)NULL); - mFrames = new mpp_list((node_destructor)mpp_frame_deinit); - mTasks = new mpp_list((node_destructor)NULL); - - mpp_dec_init(&mDec, coding); - mThreadCodec = new MppThread(mpp_dec_parser_thread, this); - mThreadHal = new MppThread(mpp_dec_hal_thread, this); - - mpp_buffer_group_normal_get(&mInternalGroup, MPP_BUFFER_TYPE_ION); - mpp_buffer_group_normal_get(&mPacketGroup, MPP_BUFFER_TYPE_NORMAL); - mpp_buffer_group_limited_get(&mFrameGroup, MPP_BUFFER_TYPE_ION); - mpp_buffer_group_limit_config(mFrameGroup, MPP_TEST_FRAME_SIZE, 4); - } break; - case MPP_CTX_ENC : { - mFrames = new mpp_list((node_destructor)NULL); - mPackets = new mpp_list((node_destructor)mpp_packet_deinit); - mTasks = new mpp_list((node_destructor)NULL); - - mpp_dec_init(&mDec, coding); - mThreadCodec = new MppThread(mpp_enc_control_thread, this); - mThreadHal = new MppThread(mpp_dec_hal_thread, this); - - mpp_buffer_group_normal_get(&mInternalGroup, MPP_BUFFER_TYPE_ION); - mpp_buffer_group_normal_get(&mPacketGroup, MPP_BUFFER_TYPE_NORMAL); - mpp_buffer_group_limited_get(&mFrameGroup, MPP_BUFFER_TYPE_ION); - } break; - default : { - mpp_err("Mpp error type %d\n", mType); - } break; - } - - if (mFrames && mPackets && - (mDec || mEnc) && - mThreadCodec && mThreadHal && - mPacketGroup && mFrameGroup) { - mThreadCodec->start(); - mThreadHal->start(); - } else - clear(); - - mpp_env_get_u32("mpp_debug", &mpp_debug, 0); -} - -Mpp::~Mpp () -{ - clear(); -} - -void Mpp::clear() -{ - if (mThreadCodec) - mThreadCodec->stop(); - if (mThreadHal) - mThreadHal->stop(); - - if (mThreadCodec) { - delete mThreadCodec; - mThreadCodec = NULL; - } - if (mThreadHal) { - delete mThreadHal; - mThreadHal = NULL; - } - if (mDec) { - if (mType == MPP_CTX_DEC) - mpp_dec_deinit(mDec); - else - mpp_dec_deinit(mDec); - mDec = NULL; - } - if (mPackets) { - delete mPackets; - mPackets = NULL; - } - if (mFrames) { - delete mFrames; - mFrames = NULL; - } - if (mTasks) { - delete mTasks; - mTasks = NULL; - } - if (mInternalGroup) { - mpp_buffer_group_put(mInternalGroup); - mInternalGroup = NULL; - } - if (mPacketGroup) { - mpp_buffer_group_put(mPacketGroup); - mPacketGroup = NULL; - } - if (mFrameGroup) { - mpp_buffer_group_put(mFrameGroup); - mFrameGroup = NULL; - } -} - -MPP_RET Mpp::put_packet(MppPacket packet) -{ - Mutex::Autolock autoLock(mPackets->mutex()); - if (mPackets->list_size() < 4) { - mPackets->add_at_tail(packet, sizeof(MppPacketImpl)); - mPacketPutCount++; - mThreadCodec->signal(); - return MPP_OK; - } - return MPP_NOK; -} - -MPP_RET Mpp::get_frame(MppFrame *frame) -{ - Mutex::Autolock autoLock(mFrames->mutex()); - MppFrame first = NULL; - - if (0 == mFrames->list_size()) { - mThreadCodec->signal(); - mFrames->wait(); - } - - if (mFrames->list_size()) { - mFrames->del_at_tail(&first, sizeof(frame)); - mFrameGetCount++; - mThreadHal->signal(); - - MppFrame prev = first; - MppFrame next = NULL; - while (mFrames->list_size()) { - mFrames->del_at_tail(&next, sizeof(frame)); - mFrameGetCount++; - mThreadHal->signal(); - mpp_frame_set_next(prev, next); - prev = next; - } - } - *frame = first; - return MPP_OK; -} - -MPP_RET Mpp::put_frame(MppFrame frame) -{ - Mutex::Autolock autoLock(mFrames->mutex()); - if (mFrames->list_size() < 4) { - mFrames->add_at_tail(frame, sizeof(MppFrameImpl)); - mThreadCodec->signal(); - mFramePutCount++; - return MPP_OK; - } - return MPP_NOK; -} - -MPP_RET Mpp::get_packet(MppPacket *packet) -{ - Mutex::Autolock autoLock(mPackets->mutex()); - if (mPackets->list_size()) { - mPackets->del_at_tail(packet, sizeof(packet)); - mPacketGetCount++; - } - return MPP_OK; -} - diff --git a/mpp/mpp.h b/mpp/mpp.h deleted file mode 100644 index 07c487c93..000000000 --- a/mpp/mpp.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_H__ -#define __MPP_H__ - -#include "mpp_list.h" -#include "mpp_dec.h" - -#define MPP_DBG_FUNCTION (0x00000001) -#define MPP_DBG_PACKET (0x00000002) -#define MPP_DBG_FRAME (0x00000004) -#define MPP_DBG_BUFFER (0x00000008) - -/* - * mpp hierarchy - * - * mpp layer create mpp_dec or mpp_dec instance - * mpp_dec create its parser and hal module - * mpp_enc create its control and hal module - * - * +-------+ - * | | - * +-------------+ mpp +-------------+ - * | | | | - * | +-------+ | - * | | - * | | - * | | - * +-----+-----+ +-----+-----+ - * | | | | - * +---+ mpp_dec +--+ +--+ mpp_enc +---+ - * | | | | | | | | - * | +-----------+ | | +-----------+ | - * | | | | - * | | | | - * | | | | - * +-------v------+ +-----v-----+ +-----v-----+ +------v-------+ - * | | | | | | | | - * | dec_parser | | dec_hal | | enc_hal | | enc_control | - * | | | | | | | | - * +--------------+ +-----------+ +-----------+ +--------------+ - */ - -class Mpp -{ -public: - Mpp(MppCtxType type, MppCodingType coding); - ~Mpp(); - - MPP_RET put_packet(MppPacket packet); - MPP_RET get_frame(MppFrame *frame); - - MPP_RET put_frame(MppFrame frame); - MPP_RET get_packet(MppPacket *packet); - - - mpp_list *mPackets; - mpp_list *mFrames; - mpp_list *mTasks; - - RK_U32 mPacketPutCount; - RK_U32 mPacketGetCount; - RK_U32 mFramePutCount; - RK_U32 mFrameGetCount; - RK_U32 mTaskPutCount; - RK_U32 mTaskGetCount; - - /* - * internal buffer group - * - for all kind of table like cabac / scaling list - * fixed to ion buffer group - * packet buffer group - * - packets in I/O, can be ion buffer or normal buffer - * frame buffer group - * - frames in I/O, normally should be a ion buffer group - */ - MppBufferGroup mInternalGroup; - MppBufferGroup mPacketGroup; - MppBufferGroup mFrameGroup; - - MppThread *mThreadCodec; - MppThread *mThreadHal; - - MppCtxType mType; - MppCodingType mCoding; - - RK_U32 mStatus; - - MppDec *mDec; - MppDec *mEnc; - -private: - void clear(); - - Mpp(); - Mpp(const Mpp &); - Mpp &operator=(const Mpp &); -}; - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_H__*/ diff --git a/mpp/mpp_buffer.cpp b/mpp/mpp_buffer.cpp deleted file mode 100644 index 5999a925d..000000000 --- a/mpp/mpp_buffer.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_buffer" - -#include - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_buffer_impl.h" - -MPP_RET mpp_buffer_commit(MppBufferGroup group, MppBufferInfo *info) -{ - if (NULL == group || NULL == info) { - mpp_err("mpp_buffer_commit input null pointer group %p info %p\n", - group, info); - return MPP_ERR_NULL_PTR; - } - - MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; - if (p->type != info->type || p->type >= MPP_BUFFER_TYPE_BUTT) { - mpp_err("mpp_buffer_commit invalid type found group %d info %d\n", - p->type, info->type); - return MPP_ERR_UNKNOW; - } - - return mpp_buffer_create(NULL, p->group_id, info); -} - -MPP_RET mpp_buffer_get_with_tag(const char *tag, MppBufferGroup group, MppBuffer *buffer, size_t size) -{ - if (NULL == group || NULL == buffer || 0 == size) { - mpp_err("mpp_buffer_get invalid input: group %p buffer %p size %u\n", - group, buffer, size); - return MPP_ERR_UNKNOW; - } - - MppBufferGroupImpl *tmp = (MppBufferGroupImpl *)group; - // try unused buffer first - MppBufferImpl *buf = mpp_buffer_get_unused(tmp, size); - if (NULL == buf) { - MppBufferInfo info = { - tmp->type, - size, - NULL, - NULL, - -1, - NULL, - }; - // if failed try init a new buffer - mpp_buffer_create(tag, tmp->group_id, &info); - buf = mpp_buffer_get_unused(tmp, size); - } - *buffer = buf; - return (buf) ? (MPP_OK) : (MPP_NOK); -} - -MPP_RET mpp_buffer_put(MppBuffer buffer) -{ - if (NULL == buffer) { - mpp_err("mpp_buffer_put invalid input: buffer %p\n", buffer); - return MPP_ERR_UNKNOW; - } - - return mpp_buffer_ref_dec((MppBufferImpl*)buffer); -} - -MPP_RET mpp_buffer_inc_ref(MppBuffer buffer) -{ - if (NULL == buffer) { - mpp_err("mpp_buffer_inc_ref invalid input: buffer %p\n", buffer); - return MPP_ERR_UNKNOW; - } - - return mpp_buffer_ref_inc((MppBufferImpl*)buffer); -} - -MPP_RET mpp_buffer_read(MppBuffer buffer, size_t offset, void *data, size_t size) -{ - if (NULL == buffer || NULL == data) { - mpp_err_f("invalid input: buffer %p data %p\n", buffer, data); - return MPP_ERR_UNKNOW; - } - - if (0 == size) - return MPP_OK; - - MppBufferImpl *p = (MppBufferImpl*)buffer; - void *src = p->info.ptr; - mpp_assert(src != NULL); - memcpy(data, (char*)src + offset, size); - return MPP_OK; -} - -MPP_RET mpp_buffer_write(MppBuffer buffer, size_t offset, void *data, size_t size) -{ - if (NULL == buffer || NULL == data) { - mpp_err_f("invalid input: buffer %p data %p\n", buffer, data); - return MPP_ERR_UNKNOW; - } - - if (0 == size) - return MPP_OK; - - MppBufferImpl *p = (MppBufferImpl*)buffer; - void *dst = p->info.ptr; - mpp_assert(dst != NULL); - memcpy((char*)dst + offset, data, size); - return MPP_OK; -} - -void *mpp_buffer_get_ptr(MppBuffer buffer) -{ - if (NULL == buffer) { - mpp_err_f("invalid input: buffer %p data %p\n", buffer); - return NULL; - } - - MppBufferImpl *p = (MppBufferImpl*)buffer; - void *ptr = p->info.ptr; - mpp_assert(ptr != NULL); - return ptr; -} - -int mpp_buffer_get_fd(MppBuffer buffer) -{ - if (NULL == buffer) { - mpp_err_f("invalid input: buffer %p data %p\n", buffer); - return -1; - } - - MppBufferImpl *p = (MppBufferImpl*)buffer; - int fd = p->info.fd; - mpp_assert(fd >= 0); - return fd; -} - -MPP_RET mpp_buffer_info_get(MppBuffer buffer, MppBufferInfo *info) -{ - if (NULL == buffer || NULL == info) { - mpp_err_f("invalid input: buffer %p info %p\n", buffer, info); - return MPP_ERR_UNKNOW; - } - - *info = ((MppBufferImpl*)buffer)->info; - return MPP_OK; -} - -MPP_RET mpp_buffer_group_get(const char *tag, MppBufferMode mode, - MppBufferGroup *group, MppBufferType type) -{ - if (NULL == group || - mode >= MPP_BUFFER_MODE_BUTT || - type >= MPP_BUFFER_TYPE_BUTT) { - mpp_err_f("input invalid group %p mode %d type %d\n", - group, mode, type); - return MPP_ERR_UNKNOW; - } - - return mpp_buffer_group_init((MppBufferGroupImpl**)group, tag, mode, type); -} - -MPP_RET mpp_buffer_group_put(MppBufferGroup group) -{ - if (NULL == group) { - mpp_err_f("input invalid group %p\n", group); - return MPP_NOK; - } - - return mpp_buffer_group_deinit((MppBufferGroupImpl *)group); -} - -MPP_RET mpp_buffer_group_limit_config(MppBufferGroup group, size_t size, RK_S32 count) -{ - if (NULL == group || 0 == size || count <= 0) { - mpp_err_f("input invalid group %p size %d count %d\n", - group, size, count); - return MPP_NOK; - } - - MppBufferGroupImpl *p = (MppBufferGroupImpl *)group; - mpp_assert(p->mode == MPP_BUFFER_MODE_LIMIT); - p->limit_size = size; - p->limit_count = count; - return MPP_OK; -} - diff --git a/mpp/mpp_buffer_impl.cpp b/mpp/mpp_buffer_impl.cpp deleted file mode 100644 index a0911379c..000000000 --- a/mpp/mpp_buffer_impl.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_buffer" - -#include - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_buffer_impl.h" - -#define SEARCH_GROUP_NORMAL(id) search_group_by_id_no_lock(&service.mListGroup, id) -#define SEARCH_GROUP_ORPHAN(id) search_group_by_id_no_lock(&service.mListOrphan, id) - -class MppBufferService -{ -public: - MppBufferService(); - ~MppBufferService(); - - Mutex mLock; - RK_U32 group_id; - RK_U32 group_count; - - struct list_head mListGroup; - - // list for used buffer which do not have group - struct list_head mListOrphan; -}; - -static MppBufferService service; - -static MppBufferGroupImpl *search_group_by_id_no_lock(struct list_head *list, RK_U32 group_id) -{ - MppBufferGroupImpl *pos, *n; - list_for_each_entry_safe(pos, n, list, MppBufferGroupImpl, list_group) { - if (pos->group_id == group_id) { - return pos; - } - } - return NULL; -} - -MPP_RET deinit_group_no_lock(MppBufferGroupImpl *group) -{ - mpp_alloctor_put(&group->allocator); - list_del_init(&group->list_group); - mpp_free(group); - service.group_count--; - return MPP_OK; -} - -MPP_RET deinit_buffer_no_lock(MppBufferImpl *buffer) -{ - mpp_assert(buffer->ref_count == 0); - mpp_assert(buffer->used == 0); - - list_del_init(&buffer->list_status); - MppBufferGroupImpl *group = SEARCH_GROUP_NORMAL(buffer->group_id); - if (group) { - if (buffer->internal) - group->alloc_api->free(group->allocator, &buffer->info); - - group->usage -= buffer->info.size; - group->count--; - } else { - group = SEARCH_GROUP_ORPHAN(buffer->group_id); - mpp_assert(group); - mpp_assert(buffer->mode == MPP_BUFFER_MODE_NORMAL); - group->alloc_api->free(group->allocator, &buffer->info); - group->usage -= buffer->info.size; - group->count--; - if (0 == group->usage) - deinit_group_no_lock(group); - } - - mpp_free(buffer); - - return MPP_OK; -} - -static MPP_RET check_buffer_group_limit(MppBufferGroupImpl *group) -{ - if (group->usage > group->limit) { - MppBufferImpl *pos, *n; - list_for_each_entry_safe(pos, n, &group->list_unused, MppBufferImpl, list_status) { - deinit_buffer_no_lock(pos); - } - } - - return (group->usage > group->limit) ? (MPP_NOK) : (MPP_OK); -} - -static MPP_RET inc_buffer_ref_no_lock(MppBufferImpl *buffer) -{ - MPP_RET ret = MPP_OK; - if (!buffer->used) { - MppBufferGroupImpl *group = SEARCH_GROUP_NORMAL(buffer->group_id); - // NOTE: when increasing ref_count the unused buffer must be under certain group - mpp_assert(group); - buffer->used = 1; - if (group) { - list_del_init(&buffer->list_status); - list_add_tail(&buffer->list_status, &group->list_used); - } else { - mpp_err("mpp_buffer_ref_inc unused buffer without group\n"); - ret = MPP_NOK; - } - } - buffer->ref_count++; - return ret; -} - -MPP_RET mpp_buffer_create(const char *tag, RK_U32 group_id, MppBufferInfo *info) -{ - MppBufferImpl *p = mpp_calloc(MppBufferImpl, 1); - if (NULL == p) { - mpp_err("mpp_buffer_create failed to allocate context\n"); - return MPP_ERR_MALLOC; - } - - Mutex::Autolock auto_lock(&service.mLock); - - MppBufferGroupImpl *group = SEARCH_GROUP_NORMAL(group_id); - if (group) { - if (NULL == info->ptr && info->fd == -1) { - MPP_RET ret = group->alloc_api->alloc(group->allocator, info); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_create failed to create buffer with size %d\n", info->size); - mpp_free(p); - return MPP_ERR_MALLOC; - } - p->internal = 1; - } - - p->info = *info; - p->mode = group->mode; - - if (NULL == tag) - tag = group->tag; - - strncpy(p->tag, tag, sizeof(p->tag)); - p->group_id = group_id; - INIT_LIST_HEAD(&p->list_status); - list_add_tail(&p->list_status, &group->list_unused); - group->usage += info->size; - group->count++; - } else { - mpp_err("mpp_buffer_create can not create buffer without group\n"); - mpp_free(p); - p = NULL; - } - - return (p) ? (MPP_OK) : (MPP_NOK); -} - -MPP_RET mpp_buffer_destroy(MppBufferImpl *buffer) -{ - Mutex::Autolock auto_lock(&service.mLock); - - deinit_buffer_no_lock(buffer); - - return MPP_OK; -} - -MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer) -{ - Mutex::Autolock auto_lock(&service.mLock); - return inc_buffer_ref_no_lock(buffer); -} - - -MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer) -{ - if (buffer->ref_count <= 0) { - mpp_err("mpp_buffer_ref_dec found non-positive ref_count %d\n", buffer->ref_count); - return MPP_NOK; - } - - Mutex::Autolock auto_lock(&service.mLock); - - buffer->ref_count--; - if (0 == buffer->ref_count) { - buffer->used = 0; - list_del_init(&buffer->list_status); - MppBufferGroupImpl *group = SEARCH_GROUP_NORMAL(buffer->group_id); - if (group) { - list_add_tail(&buffer->list_status, &group->list_unused); - check_buffer_group_limit(group); - } - } - - return MPP_OK; -} - -MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size) -{ - MppBufferImpl *buffer = NULL; - - Mutex::Autolock auto_lock(&service.mLock); - - if (!list_empty(&p->list_unused)) { - MppBufferImpl *pos, *n; - list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) { - if (pos->info.size == size) { - buffer = pos; - inc_buffer_ref_no_lock(buffer); - break; - } - } - } - - return buffer; -} - -MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, MppBufferMode mode, MppBufferType type) -{ - MppBufferGroupImpl *p = mpp_malloc(MppBufferGroupImpl, 1); - if (NULL == p) { - mpp_err("mpp_buffer_group_get failed to allocate context\n"); - *group = NULL; - return MPP_ERR_MALLOC; - } - - Mutex::Autolock auto_lock(&service.mLock); - - INIT_LIST_HEAD(&p->list_group); - INIT_LIST_HEAD(&p->list_used); - INIT_LIST_HEAD(&p->list_unused); - - list_add_tail(&p->list_group, &service.mListGroup); - - snprintf(p->tag, sizeof(p->tag), "%s_%d", tag, service.group_id); - p->mode = mode; - p->type = type; - p->limit = BUFFER_GROUP_SIZE_DEFAULT; - p->usage = 0; - p->count = 0; - p->group_id = service.group_id; - p->limit_size = 0; - p->limit_count = 0; - - // avoid group_id reuse - do { - service.group_id++; - if (NULL == SEARCH_GROUP_NORMAL(service.group_id) && - NULL == SEARCH_GROUP_ORPHAN(service.group_id)) - break; - } while (p->group_id != service.group_id); - service.group_count++; - - mpp_alloctor_get(&p->allocator, &p->alloc_api, type); - - *group = p; - - return MPP_OK; -} - -MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p) -{ - if (NULL == p) { - mpp_err("mpp_buffer_group_deinit found NULL pointer\n"); - return MPP_ERR_NULL_PTR; - } - - Mutex::Autolock auto_lock(&service.mLock); - - // remove unused list - if (!list_empty(&p->list_unused)) { - MppBufferImpl *pos, *n; - list_for_each_entry_safe(pos, n, &p->list_unused, MppBufferImpl, list_status) { - deinit_buffer_no_lock(pos); - } - } - - if (list_empty(&p->list_used)) { - deinit_group_no_lock(p); - } else { - // otherwise move the group to list_orphan and wait for buffer release - list_del_init(&p->list_group); - list_add_tail(&p->list_group, &service.mListOrphan); - mpp_err("mpp_group %p tag %s deinit with %d bytes buffer not released\n", p, p->tag, p->usage); - // if any buffer with mode MPP_BUFFER_MODE_COMMIT found it should be error - MppBufferImpl *pos, *n; - list_for_each_entry_safe(pos, n, &p->list_used, MppBufferImpl, list_status) { - mpp_assert(pos->mode != MPP_BUFFER_MODE_LIMIT); - } - } - - return MPP_OK; -} - -MppBufferService::MppBufferService() - : group_id(0), - group_count(0) -{ - INIT_LIST_HEAD(&mListGroup); - INIT_LIST_HEAD(&mListOrphan); -} - -MppBufferService::~MppBufferService() -{ - // remove all group first - if (!list_empty(&mListGroup)) { - MppBufferGroupImpl *pos, *n; - list_for_each_entry_safe(pos, n, &mListGroup, MppBufferGroupImpl, list_group) { - mpp_buffer_group_deinit(pos); - } - } - - // remove all orphan buffer - if (!list_empty(&mListOrphan)) { - MppBufferImpl *pos, *n; - list_for_each_entry_safe(pos, n, &mListOrphan, MppBufferImpl, list_status) { - deinit_buffer_no_lock(pos); - } - } -} - - diff --git a/mpp/mpp_buffer_impl.h b/mpp/mpp_buffer_impl.h deleted file mode 100644 index c695675fd..000000000 --- a/mpp/mpp_buffer_impl.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_BUFFER_IMPL_H__ -#define __MPP_BUFFER_IMPL_H__ - -#include "mpp_list.h" -#include "mpp_common.h" -#include "mpp_allocator.h" - -#define MPP_BUF_DBG_FUNCTION (0x00000001) - -#define mpp_buf_dbg(flag, fmt, ...) _mpp_dbg(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__) -#define mpp_buf_dbg_f(flag, fmt, ...) _mpp_dbg(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__) - -#define MPP_BUF_FUNCTION_ENTER() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "enter\n") -#define MPP_BUF_FUNCTION_LEAVE() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "leave\n") -#define MPP_BUF_FUNCTION_LEAVE_OK() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "success\n") -#define MPP_BUF_FUNCTION_LEAVE_FAIL() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "failed\n") - -typedef struct MppBufferImpl_t MppBufferImpl; -typedef struct MppBufferGroupImpl_t MppBufferGroupImpl; - -// use index instead of pointer to avoid invalid pointer -struct MppBufferImpl_t { - char tag[MPP_TAG_SIZE]; - RK_U32 group_id; - MppBufferMode mode; - - MppBufferInfo info; - - // used flag is for used/unused list detection - RK_U32 used; - RK_U32 internal; - RK_S32 ref_count; - struct list_head list_status; -}; - -struct MppBufferGroupImpl_t { - char tag[MPP_TAG_SIZE]; - RK_U32 group_id; - MppBufferMode mode; - MppBufferType type; - // used in limit mode only - size_t limit_size; - RK_S32 limit_count; - // status record - size_t limit; - size_t usage; - RK_S32 count; - - MppAllocator allocator; - MppAllocatorApi *alloc_api; - - // link to the other MppBufferGroupImpl - struct list_head list_group; - - // link to list_status in MppBufferImpl - struct list_head list_used; - struct list_head list_unused; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -extern RK_U32 mpp_buffer_debug; - -/* - * mpp_buffer_create : create a unused buffer with parameter tag/size/data - * buffer will be register to unused list - * - * mpp_buffer_destroy : destroy a buffer, it must be on unused status - * - * mpp_buffer_get_unused : get unused buffer with size. it will first search - * the unused list. if failed it will create on from - * group allocator. - * - * mpp_buffer_ref_inc : increase buffer's reference counter. if it is unused - * then it will be moved to used list. - * - * mpp_buffer_ref_dec : decrease buffer's reference counter. if the reference - * reduce to zero buffer will be moved to unused list. - * - * normal call flow will be like this: - * - * mpp_buffer_create - create a unused buffer - * mpp_buffer_get_unused - get the unused buffer - * mpp_buffer_ref_inc/dec - use the buffer - * mpp_buffer_destory - destroy the buffer - */ -MPP_RET mpp_buffer_create(const char *tag, RK_U32 group_id, MppBufferInfo *info); -MPP_RET mpp_buffer_destroy(MppBufferImpl *buffer); -MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer); -MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer); -MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size); - -MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, MppBufferMode mode, MppBufferType type); -MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_BUFFER_IMPL_H__*/ diff --git a/mpp/mpp_frame.cpp b/mpp/mpp_frame.cpp deleted file mode 100644 index 87d3472a4..000000000 --- a/mpp/mpp_frame.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_frame" - -#include - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_frame_impl.h" - -static const char *module_name = MODULE_TAG; - -static void setup_mpp_frame_name(MppFrameImpl *frame) -{ - frame->name = module_name; -} - -static void check_mpp_frame_name(MppFrameImpl *frame) -{ - mpp_assert(frame->name == module_name); - if (frame->name != module_name) - abort(); -} - -MPP_RET mpp_frame_init(MppFrame *frame) -{ - if (NULL == frame) { - mpp_err_f("invalid NULL pointer input\n"); - return MPP_ERR_NULL_PTR; - } - - MppFrameImpl *p = mpp_calloc(MppFrameImpl, 1); - if (NULL == p) { - mpp_err_f("malloc failed\n"); - return MPP_ERR_NULL_PTR; - } - - setup_mpp_frame_name(p); - *frame = p; - - return MPP_OK; -} - -MPP_RET mpp_frame_deinit(MppFrame *frame) -{ - if (NULL == frame || NULL == *frame) { - mpp_err_f("invalid NULL pointer input\n"); - return MPP_ERR_NULL_PTR; - } - - check_mpp_frame_name((MppFrameImpl *)*frame); - MppBuffer buffer = mpp_frame_get_buffer(*frame); - if (buffer) - mpp_buffer_put(buffer); - - mpp_free(*frame); - return MPP_OK; -} - -MppFrame mpp_frame_get_next(MppFrame frame) -{ - if (NULL == frame) { - mpp_err_f("invalid NULL pointer input\n"); - return NULL; - } - - MppFrameImpl *p = (MppFrameImpl *)frame; - check_mpp_frame_name(p); - return (MppFrame)p->next; -} - -MPP_RET mpp_frame_set_next(MppFrame frame, MppFrame next) -{ - if (NULL == frame) { - mpp_err_f("invalid NULL pointer input\n"); - return MPP_ERR_NULL_PTR; - } - - MppFrameImpl *p = (MppFrameImpl *)frame; - check_mpp_frame_name(p); - p->next = (MppFrameImpl *)next; - return MPP_OK; -} - -MPP_RET mpp_frame_copy(MppFrame dst, MppFrame src) -{ - if (NULL == dst || NULL == src) { - mpp_err_f("invalid NULL pointer input\n"); - return MPP_ERR_NULL_PTR; - } - - check_mpp_frame_name((MppFrameImpl *)dst); - memcpy(dst, src, sizeof(MppFrameImpl)); - return MPP_OK; -} - - -/* - * object access function macro - */ -#define MPP_FRAME_ACCESSORS(type, field) \ - type mpp_frame_get_##field(const MppFrame s) \ - { \ - check_mpp_frame_name((MppFrameImpl*)s); \ - return ((MppFrameImpl*)s)->field; \ - } \ - void mpp_frame_set_##field(MppFrame s, type v) \ - { \ - check_mpp_frame_name((MppFrameImpl*)s); \ - ((MppFrameImpl*)s)->field = v; \ - } - -MPP_FRAME_ACCESSORS(RK_U32, width) -MPP_FRAME_ACCESSORS(RK_U32, height) -MPP_FRAME_ACCESSORS(RK_U32, hor_stride) -MPP_FRAME_ACCESSORS(RK_U32, ver_stride) -MPP_FRAME_ACCESSORS(RK_U32, mode) -MPP_FRAME_ACCESSORS(RK_S64, pts) -MPP_FRAME_ACCESSORS(RK_S64, dts) -MPP_FRAME_ACCESSORS(MppFrameColorRange, color_range) -MPP_FRAME_ACCESSORS(MppFrameColorPrimaries, color_primaries) -MPP_FRAME_ACCESSORS(MppFrameColorTransferCharacteristic, color_trc) -MPP_FRAME_ACCESSORS(MppFrameColorSpace, colorspace) -MPP_FRAME_ACCESSORS(MppFrameChromaLocation, chroma_location) -MPP_FRAME_ACCESSORS(MppBuffer, buffer) - diff --git a/mpp/mpp_frame_impl.h b/mpp/mpp_frame_impl.h deleted file mode 100644 index afc3b3abe..000000000 --- a/mpp/mpp_frame_impl.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_FRAME_IMPL_H__ -#define __MPP_FRAME_IMPL_H__ - -#include "mpp_frame.h" - -typedef struct MppFrameImpl_t MppFrameImpl; - -struct MppFrameImpl_t { - const char *name; - - /* - * dimension parameter for display - */ - RK_U32 width; - RK_U32 height; - RK_U32 hor_stride; - RK_U32 ver_stride; - - /* - * interlaced related mode status - * - * 0 - frame - * 1 - top field - * 2 - bottom field - * 3 - paired top and bottom field - * 4 - deinterlaced flag - * 7 - deinterlaced paired field - */ - RK_U32 mode; - - /* - * pts - display time stamp - * dts - decode time stamp - */ - RK_S64 pts; - RK_S64 dts; - - MppFrameColorRange color_range; - MppFrameColorPrimaries color_primaries; - MppFrameColorTransferCharacteristic color_trc; - - /** - * YUV colorspace type. - * It must be accessed using av_frame_get_colorspace() and - * av_frame_set_colorspace(). - * - encoding: Set by user - * - decoding: Set by libavcodec - */ - MppFrameColorSpace colorspace; - MppFrameChromaLocation chroma_location; - - /* - * buffer information - */ - MppBuffer buffer; - - /* - * pointer for multiple frame output at one time - */ - MppFrameImpl *next; -}; - - -MPP_RET mpp_frame_set_next(MppFrame frame, MppFrame next); -MPP_RET mpp_frame_copy(MppFrame frame, MppFrame next); - -#endif /*__MPP_FRAME_IMPL_H__*/ diff --git a/mpp/mpp_impl.c b/mpp/mpp_impl.c new file mode 100644 index 000000000..eb74beffb --- /dev/null +++ b/mpp/mpp_impl.c @@ -0,0 +1,510 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_impl" + +#include +#include +#include +#include + +#include "rk_mpi_cmd.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_thread.h" +#include "mpp_common.h" + +#include "mpp_impl.h" + +#define MAX_FILE_NAME_LEN 512 +#define MAX_DUMP_WIDTH 960 +#define MAX_DUMP_HEIGHT 540 + +#define ops_log(fp, fmt, ...) _ops_log(fp, fmt, ## __VA_ARGS__) + +typedef enum MppOpsType_e { + MPP_DEC_OPS_BASE = 0, + MPP_DEC_INIT = MPP_DEC_OPS_BASE, + MPP_DEC_SE +} MppOpsType; + +/* dump data */ +typedef struct MppDumpImpl_t { + MppMutex lock; + RK_U32 log_version; + RK_U32 debug; + pid_t tid; + RK_S64 time_base; + + MppCtxType type; + MppCodingType coding; + + FILE *fp_in; // file for MppPacket + FILE *fp_out; // file for MppFrame + FILE *fp_ops; // file for decoder / encoder extra info + + RK_U8 *fp_buf; // for resample frame + RK_U32 pkt_offset; + RK_U32 dump_width; + RK_U32 dump_height; + RK_U32 dump_size; + + RK_U32 idx; +} MppDumpImpl; + +typedef union OpsArgs_u { + struct MppOpsInitArg_t { + MppCtxType type; + MppCodingType coding; + } init_arg; + + struct MppOpsPktArg_t { + RK_U32 offset; // offset in packet file + RK_U32 length; // pakcet length + RK_S64 pts; + } pkt_arg; + + struct MppOpsFrmArg_t { + RK_U32 fd; + RK_U32 info_change; + RK_U32 error; + RK_U32 discard; + RK_S64 pts; + } frm_arg; + + struct MppOpCtrlArg_t { + MpiCmd cmd; + } ctrl_arg; +} OpsArgs; + +typedef struct MppOpsInfo_t { + RK_U32 idx; + RK_U32 id; + RK_S64 time; + OpsArgs args; +} MppOpsInfo; + +/* + * decoder file dump: + * dec_pkt - decoder input byte raw stream file + * dec_cfg - decoder input stream offset and size info in format [u32 offset|u32 size] + * dec_frm - decoder output frame file with snapshot method + */ +static const char dec_pkt_path[] = "/data/mpp_dec_in.bin"; +static const char dec_ops_path[] = "/data/mpp_dec_ops.bin"; +static const char dec_frm_path[] = "/data/mpp_dec_out.bin"; + +static const char enc_frm_path[] = "/data/mpp_enc_in.bin"; +static const char enc_ops_path[] = "/data/mpp_enc_ops.bin"; +static const char enc_pkt_path[] = "/data/mpp_enc_out.bin"; + +static FILE *try_env_file(const char *env, const char *path, pid_t tid) +{ + const char *fname = NULL; + FILE *fp = NULL; + char name[MAX_FILE_NAME_LEN]; + + mpp_env_get_str(env, &fname, path); + if (fname == path) { + snprintf(name, sizeof(name) - 1, "%s-%d", path, tid); + fname = name; + } + + fp = fopen(fname, "w+b"); + mpp_log("open %s %p for dump\n", fname, fp); + + return fp; +} + +static RK_U8 fetch_data(RK_U32 fmt, RK_U8 *line, RK_U32 num) +{ + RK_U32 offset = 0; + RK_U32 value = 0; + + if (fmt == MPP_FMT_YUV420SP_10BIT) { + offset = (num * 2) & 7; + value = (line[num * 10 / 8] >> offset) | + (line[num * 10 / 8 + 1] << (8 - offset)); + + value = (value & 0x3ff) >> 2; + } else if (fmt == MPP_FMT_YUV420SP) { + value = line[num]; + } + + return (RK_U8)value; +} + +static void rearrange_pix(RK_U8 *tmp_line, RK_U8 *base, RK_U32 n) +{ + RK_U16 * pix = (RK_U16 *)(tmp_line + n * 16); + RK_U16 * base_u16 = (RK_U16 *)(base + n * 10); + + pix[0] = base_u16[0] & 0x03FF; + pix[1] = (base_u16[0] & 0xFC00) >> 10 | (base_u16[1] & 0x000F) << 6; + pix[2] = (base_u16[1] & 0x3FF0) >> 4; + pix[3] = (base_u16[1] & 0xC000) >> 14 | (base_u16[2] & 0x00FF) << 2; + pix[4] = (base_u16[2] & 0xFF00) >> 8 | (base_u16[3] & 0x0003) << 8; + pix[5] = (base_u16[3] & 0x0FFC) >> 2; + pix[6] = (base_u16[3] & 0xF000) >> 12 | (base_u16[4] & 0x003F) << 4; + pix[7] = (base_u16[4] & 0xFFC0) >> 6; +} + +static void dump_frame(FILE *fp, MppFrame frame, RK_U8 *tmp, RK_U32 w, RK_U32 h) +{ + RK_U32 i = 0, j = 0; + RK_U32 fmt = (mpp_frame_get_fmt(frame) & MPP_FRAME_FMT_MASK); + RK_U32 width = mpp_frame_get_width(frame); + RK_U32 height = mpp_frame_get_height(frame); + RK_U32 hor_stride = mpp_frame_get_hor_stride(frame); + RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); + RK_U8 *p_buf = (RK_U8 *) mpp_buffer_get_ptr(mpp_frame_get_buffer(frame)); + + RK_U8 *psrc = p_buf; + RK_U8 *pdes = tmp; + RK_U32 size = 0; + + if (pdes) { + if (hor_stride > w || ver_stride > h) { + RK_U32 step = MPP_MAX((hor_stride + w - 1) / w, + (ver_stride + h - 1) / h); + RK_U32 img_w = width / step; + RK_U32 img_h = height / step; + + img_w -= img_w & 0x1; + img_h -= img_h & 0x1; + for (i = 0; i < img_h; i++) { + for (j = 0; j < img_w; j++) + pdes[j] = fetch_data(fmt, psrc, j * step); + pdes += img_w; + psrc += step * hor_stride; + } + psrc = p_buf + hor_stride * ver_stride; + pdes = tmp + img_w * img_h; + for (i = 0; i < (img_h / 2); i++) { + for (j = 0; j < (img_w / 2); j++) { + pdes[2 * j + 0] = fetch_data(fmt, psrc, 2 * j * step + 0); + pdes[2 * j + 1] = fetch_data(fmt, psrc, 2 * j * step + 1); + } + pdes += img_w; + psrc += step * hor_stride; + } + width = img_w; + height = img_h; + } else if (fmt == MPP_FMT_YUV420SP_10BIT) { + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + pdes[j] = fetch_data(fmt, psrc, j); + pdes += width; + psrc += hor_stride; + } + psrc = p_buf + hor_stride * ver_stride; + pdes = tmp + width * height; + for (i = 0; i < height / 2; i++) { + for (j = 0; j < width; j++) + pdes[j] = fetch_data(fmt, psrc, j); + pdes += width; + psrc += hor_stride; + } + } + size = width * height * 1.5; + } else { + tmp = p_buf; + switch (fmt) { + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420P : { + size = hor_stride * ver_stride * 3 / 2; + } break; + case MPP_FMT_YUV422SP : { + size = hor_stride * ver_stride * 2; + } break; + case MPP_FMT_YUV444SP : { + size = hor_stride * ver_stride * 3; + } break; + case MPP_FMT_YUV420SP_10BIT : { + RK_U8 *base_y = p_buf; + RK_U8 *base_c = p_buf + hor_stride * ver_stride; + RK_U8 *tmp_line = (RK_U8 *)mpp_malloc(RK_U16, width); + + if (!tmp_line) { + mpp_log("tmp_line malloc fail"); + return; + } + + for (i = 0; i < height; i++, base_y += hor_stride) { + for (j = 0; j < MPP_ALIGN(width, 8) / 8; j++) + rearrange_pix(tmp_line, base_y, j); + fwrite(tmp_line, width * sizeof(RK_U16), 1, fp); + } + + for (i = 0; i < height / 2; i++, base_c += hor_stride) { + for (j = 0; j < MPP_ALIGN(width, 8) / 8; j++) + rearrange_pix(tmp_line, base_c, j); + fwrite(tmp_line, width * sizeof(RK_U16), 1, fp); + } + MPP_FREE(tmp_line); + } + default : break; + } + } + mpp_log("dump_yuv: w:h [%d:%d] stride [%d:%d] pts %lld\n", + width, height, hor_stride, ver_stride, mpp_frame_get_pts(frame)); + if (size) + fwrite(tmp, 1, size, fp); + fflush(fp); +} + +void _ops_log(FILE *fp, const char *fmt, ...) +{ + struct tm tm_buf; + struct tm* ptm; + struct timespec tp; + char logs[64]; + size_t len = 0; + va_list args; + va_start(args, fmt); + + clock_gettime(CLOCK_REALTIME_COARSE, &tp); + ptm = localtime_r(&tp.tv_sec, &tm_buf); + len = strftime(logs, sizeof(logs), "%m-%d %H:%M:%S", ptm); + mpp_assert(len < sizeof(logs)); + fprintf(fp, "%s.%03ld,", logs, tp.tv_nsec / 1000000); + vfprintf(fp, fmt, args); + fflush(fp); + + va_end(args); +} + +MPP_RET mpp_dump_init(MppDump *info) +{ + if (!(mpp_debug & (MPP_DBG_DUMP_IN | MPP_DBG_DUMP_OUT | MPP_DBG_DUMP_CFG))) { + *info = NULL; + return MPP_OK; + } + + MppDumpImpl *p = mpp_calloc(MppDumpImpl, 1); + + mpp_env_get_u32("mpp_dump_width", &p->dump_width, 0); + mpp_env_get_u32("mpp_dump_height", &p->dump_height, 0); + p->dump_size = p->dump_width * p->dump_height * 3 / 2; + + mpp_mutex_init(&p->lock); + p->debug = mpp_debug; + p->tid = syscall(SYS_gettid); + p->log_version = 0; + p->time_base = mpp_time(); + + *info = p; + + return MPP_OK; +} + +MPP_RET mpp_dump_deinit(MppDump *info) +{ + if (info && *info) { + MppDumpImpl *p = (MppDumpImpl *)*info; + + MPP_FCLOSE(p->fp_in); + MPP_FCLOSE(p->fp_out); + MPP_FCLOSE(p->fp_ops); + MPP_FREE(p->fp_buf); + + mpp_mutex_destroy(&p->lock); + + MPP_FREE(p); + } + + return MPP_OK; +} + +MPP_RET mpp_ops_init(MppDump info, MppCtxType type, MppCodingType coding) +{ + MppDumpImpl *p = (MppDumpImpl *)info; + + if (NULL == info) + return MPP_OK; + + mpp_mutex_lock(&p->lock); + + p->type = type; + p->coding = coding; + + if (type == MPP_CTX_DEC) { + if (p->debug & MPP_DBG_DUMP_IN) + p->fp_in = try_env_file("mpp_dump_in", dec_pkt_path, p->tid); + + if (p->debug & MPP_DBG_DUMP_OUT) { + p->fp_out = try_env_file("mpp_dump_out", dec_frm_path, p->tid); + if (p->dump_size) + p->fp_buf = mpp_malloc(RK_U8, p->dump_size); + } + + if (p->debug & MPP_DBG_DUMP_CFG) + p->fp_ops = try_env_file("mpp_dump_ops", dec_ops_path, p->tid); + } else { + if (p->debug & MPP_DBG_DUMP_IN) { + p->fp_in = try_env_file("mpp_dump_in", enc_frm_path, p->tid); + if (p->dump_size) + p->fp_buf = mpp_malloc(RK_U8, p->dump_size); + } + + if (p->debug & MPP_DBG_DUMP_OUT) + p->fp_out = try_env_file("mpp_dump_out", enc_pkt_path, p->tid); + + if (p->debug & MPP_DBG_DUMP_CFG) + p->fp_ops = try_env_file("mpp_dump_ops", enc_ops_path, p->tid); + } + + if (p->fp_ops) + ops_log(p->fp_ops, "%d,%s,%d,%d\n", p->idx++, "init", type, coding); + + mpp_mutex_unlock(&p->lock); + + return MPP_OK; +} + +MPP_RET mpp_ops_dec_put_pkt(MppDump info, MppPacket pkt) +{ + MppDumpImpl *p = (MppDumpImpl *)info; + if (NULL == p || NULL == pkt || NULL == p->fp_in) + return MPP_OK; + + RK_U32 length = mpp_packet_get_length(pkt); + + mpp_mutex_lock(&p->lock); + + if (p->fp_in) { + fwrite(mpp_packet_get_data(pkt), 1, length, p->fp_in); + fflush(p->fp_in); + } + + if (p->fp_ops) { + ops_log(p->fp_ops, "%d,%s,%d,%d\n", p->idx++, "pkt", p->pkt_offset, length); + + p->pkt_offset += length; + } + + mpp_mutex_unlock(&p->lock); + + return MPP_OK; +} + +MPP_RET mpp_ops_dec_get_frm(MppDump info, MppFrame frame) +{ + MppDumpImpl *p = (MppDumpImpl *)info; + + if (NULL == p || NULL == frame || NULL == p->fp_out) + return MPP_OK; + + mpp_mutex_lock(&p->lock); + + MppBuffer buf = mpp_frame_get_buffer(frame); + RK_S32 fd = (buf) ? mpp_buffer_get_fd(buf) : (-1); + RK_U32 info_change = mpp_frame_get_info_change(frame); + RK_U32 error = mpp_frame_get_errinfo(frame); + RK_U32 discard = mpp_frame_get_discard(frame); + + if (p->fp_ops) { + ops_log(p->fp_ops, "%d,%s,%d,%d,%d,%d,%lld\n", p->idx, "frm", fd, + info_change, error, discard, mpp_frame_get_pts(frame)); + } + + if (NULL == buf || fd < 0) { + mpp_err("failed to dump frame\n"); + mpp_mutex_unlock(&p->lock); + return MPP_NOK; + } + + dump_frame(p->fp_out, frame, p->fp_buf, p->dump_width, p->dump_height); + + if (p->debug & MPP_DBG_DUMP_LOG) { + RK_S64 pts = mpp_frame_get_pts(frame); + RK_U32 width = mpp_frame_get_hor_stride(frame); + RK_U32 height = mpp_frame_get_ver_stride(frame); + + mpp_log("yuv_info: [%d:%d] pts %lld", width, height, pts); + } + mpp_mutex_unlock(&p->lock); + + return MPP_OK; +} + +MPP_RET mpp_ops_enc_put_frm(MppDump info, MppFrame frame) +{ + MppDumpImpl *p = (MppDumpImpl *)info; + + if (NULL == p || NULL == frame || NULL == p->fp_in) + return MPP_OK; + + mpp_mutex_lock(&p->lock); + + dump_frame(p->fp_in, frame, p->fp_buf, p->dump_width, p->dump_height); + + if (p->debug & MPP_DBG_DUMP_LOG) { + RK_S64 pts = mpp_frame_get_pts(frame); + RK_U32 width = mpp_frame_get_hor_stride(frame); + RK_U32 height = mpp_frame_get_ver_stride(frame); + + mpp_log("yuv_info: [%d:%d] pts %lld", width, height, pts); + } + + mpp_mutex_unlock(&p->lock); + + return MPP_OK; +} + +MPP_RET mpp_ops_enc_get_pkt(MppDump info, MppPacket pkt) +{ + MppDumpImpl *p = (MppDumpImpl *)info; + + if (NULL == p || NULL == pkt) + return MPP_OK; + + RK_U32 length = mpp_packet_get_length(pkt); + mpp_mutex_lock(&p->lock); + + if (p->fp_out) { + fwrite(mpp_packet_get_data(pkt), 1, length, p->fp_out); + fflush(p->fp_out); + } + + mpp_mutex_unlock(&p->lock); + + return MPP_OK; +} + +MPP_RET mpp_ops_ctrl(MppDump info, MpiCmd cmd) +{ + MppDumpImpl *p = (MppDumpImpl *)info; + + if (NULL == p) + return MPP_OK; + + mpp_mutex_lock(&p->lock); + + if (p->fp_ops) + ops_log(p->fp_ops, "%d,%s,%d\n", p->idx, "ctrl", cmd); + mpp_mutex_unlock(&p->lock); + + return MPP_OK; +} + +MPP_RET mpp_ops_reset(MppDump info) +{ + MppDumpImpl *p = (MppDumpImpl *)info; + + if (NULL == p) + return MPP_OK; + + mpp_mutex_lock(&p->lock); + + if (p->fp_ops) + ops_log(p->fp_ops, "%d,%s\n", p->idx, "rst"); + mpp_mutex_unlock(&p->lock); + + return MPP_OK; +} diff --git a/mpp/mpp_info.c b/mpp/mpp_info.c new file mode 100644 index 000000000..79cb0206f --- /dev/null +++ b/mpp/mpp_info.c @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_info" + +#include +#include + +#include "mpp_log.h" +#include "mpp_env.h" +#include "mpp_info.h" + +#include "version.h" + +/* + * To avoid string | grep author getting multiple results + * use commit to replace author + */ +static const char mpp_version[] = MPP_VERSION; +static const RK_S32 mpp_history_cnt = MPP_VER_HIST_CNT; +static const char *mpp_history[] = { + MPP_VER_HIST_0, + MPP_VER_HIST_1, + MPP_VER_HIST_2, + MPP_VER_HIST_3, + MPP_VER_HIST_4, + MPP_VER_HIST_5, + MPP_VER_HIST_6, + MPP_VER_HIST_7, + MPP_VER_HIST_8, + MPP_VER_HIST_9, +}; + +void show_mpp_version(void) +{ + RK_U32 show_history = 0; + + mpp_env_get_u32("mpp_show_history", &show_history, 0); + + if (show_history) { + RK_S32 i; + + mpp_log("mpp version history %d:\n", mpp_history_cnt); + for (i = 0; i < mpp_history_cnt; i++) + mpp_log("%s\n", mpp_history[i]); + } else + mpp_log("mpp version: %s\n", mpp_version); +} + +const char *get_mpp_version(void) +{ + return mpp_version; +} diff --git a/mpp/mpp_info.cpp b/mpp/mpp_info.cpp deleted file mode 100644 index 117216a8e..000000000 --- a/mpp/mpp_info.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_info" - -#include -#include - -#include "mpp_log.h" -#include "mpp_env.h" -#include "mpp_info.h" - -#include "svn_info.h" - -mpp_info *mpp_info::singleton = NULL; - -/* - * To avoid string | grep author getting multiple results - * use commit to replace author - */ -static char mpp_version_revision[] = SVN_VERSION; -static char mpp_version_commit[] = SVN_AUTHOR; -static char mpp_version_date[] = SVN_DATE; -static char mpp_version_one_line[] = SVN_ONE_LINE; - -mpp_info *mpp_info::getInstance() -{ - if (singleton == NULL) { - singleton = new mpp_info(); - } - return singleton; -} - -static RK_CHIP_TYPE chip_version(void) -{ - RK_CHIP_TYPE type = NONE; - char *value = NULL; - RK_S32 ret = mpp_env_get_str("ro.product.board", &value, NULL); - - if (0 == ret) { - if (strstr(value, "rk29")) { - mpp_log("rk29 board found in board property"); - type = RK29; - } else if (strstr(value, "rk30")) { - mpp_log("rk30 board found in board property"); - type = RK30; - } - } - if (NONE == type) { - ret = mpp_env_get_str("ro.board.platform", &value, NULL); - if (0 == ret) { - if (strstr(value, "rk29")) { - mpp_log("rk29 board found in platform property"); - type = RK29; - } else if (strstr(value, "rk30")) { - mpp_log("rk30 board found in platform property"); - type = RK30; - } - } - } - - if (NONE == type) { - mpp_log("can not found matched chip type"); - } - return type; -} - -mpp_info::mpp_info() -{ - chip_type = chip_version(); - - mpp_info_revision = mpp_version_revision; - mpp_info_commit = mpp_version_commit; - mpp_info_date = mpp_version_date; - mpp_revision = atoi(SVN_VERSION); - - show_mpp_info(); -} - -void mpp_info::show_mpp_info() -{ - mpp_log("%s\n", mpp_version_one_line); -} - -RK_CHIP_TYPE get_chip_type() -{ - return chip_version(); -} - -int get_mpp_revision() -{ - return atoi(SVN_VERSION); -} - diff --git a/mpp/mpp_info.h b/mpp/mpp_info.h deleted file mode 100644 index 41d0a674c..000000000 --- a/mpp/mpp_info.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_INFO_H__ -#define __MPP_INFO_H__ - -typedef enum RK_CHIP_TYPE { - NONE, - RK29, - RK30, - RK31, - - RK_CHIP_NUM = 0x100, -} RK_CHIP_TYPE; - -#ifdef __cplusplus -class mpp_info -{ -public: - RK_CHIP_TYPE get_chip_type() {return chip_type;} - int get_mpp_revision() {return mpp_revision;} - void show_mpp_info(); - - static mpp_info *getInstance(); - virtual ~mpp_info() {}; -private: - static mpp_info *singleton; - mpp_info(); - int mpp_revision; - char *mpp_info_revision; - char *mpp_info_commit; - char *mpp_info_date; - RK_CHIP_TYPE chip_type; -}; - -extern "C" { -#endif /* __cplusplus */ - -RK_CHIP_TYPE get_chip_type(); -int get_mpp_revision(); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_INFO_H__*/ diff --git a/mpp/mpp_packet.cpp b/mpp/mpp_packet.cpp deleted file mode 100644 index 511ecda6a..000000000 --- a/mpp/mpp_packet.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_packet" - -#include - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_packet.h" -#include "mpp_packet_impl.h" - -static const char *module_name = MODULE_TAG; - -static void setup_mpp_packet_name(MppPacketImpl *packet) -{ - packet->name = module_name; -} - -static void check_mpp_packet_name(MppPacketImpl *packet) -{ - mpp_assert(packet->name == module_name); -} - -MPP_RET mpp_packet_new(MppPacket *packet) -{ - if (NULL == packet) { - mpp_err_f("invalid NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppPacketImpl *p = mpp_calloc(MppPacketImpl, 1); - *packet = p; - if (NULL == p) { - mpp_err_f("malloc failed\n"); - return MPP_ERR_NULL_PTR; - } - setup_mpp_packet_name(p); - return MPP_OK; -} - -MPP_RET mpp_packet_init(MppPacket *packet, void *data, size_t size) -{ - if (NULL == packet || NULL == data || 0 == size) { - mpp_err_f("invalid input packet %p data %p size %d\n", - packet, data, size); - return MPP_ERR_NULL_PTR; - } - - MPP_RET ret = mpp_packet_new(packet); - if (ret) { - mpp_err_f("new packet failed\n"); - return ret; - } - MppPacketImpl *p = (MppPacketImpl *)*packet; - p->data = p->pos = data; - p->size = p->length = size; - - return MPP_OK; -} - -MPP_RET mpp_packet_copy(MppPacket *packet, const MppPacket src) -{ - if (NULL == packet || NULL == src) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - check_mpp_packet_name((MppPacketImpl *)src); - size_t size = mpp_packet_get_size(src); - void *data = mpp_malloc_size(void, size); - if (NULL == data) { - mpp_err_f("malloc failed\n"); - return MPP_ERR_MALLOC; - } - - MPP_RET ret = mpp_packet_init(packet, data, size); - if (MPP_OK == ret) { - memcpy(data, mpp_packet_get_data(src), size); - return MPP_OK; - } - - mpp_err_f("malloc failed\n"); - mpp_free(data); - return ret; -} - -MPP_RET mpp_packet_deinit(MppPacket *packet) -{ - if (NULL == packet || NULL == *packet) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppPacketImpl *p = (MppPacketImpl *)(*packet); - check_mpp_packet_name(p); - mpp_free(p); - *packet = NULL; - return MPP_OK; -} - -void mpp_packet_set_pos(MppPacket packet, void *pos) -{ - MppPacketImpl *p = (MppPacketImpl *)packet; - check_mpp_packet_name(p); - p->pos = pos; - p->length = p->size - ((char *)pos - (char *)p->data); - mpp_assert(p->data <= p->pos); - mpp_assert(p->size >= p->length); -} - -void *mpp_packet_get_pos(const MppPacket packet) -{ - MppPacketImpl *p = (MppPacketImpl *)packet; - check_mpp_packet_name(p); - return p->pos; -} - -MPP_RET mpp_packet_set_eos(MppPacket packet) -{ - if (NULL == packet) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppPacketImpl *p = (MppPacketImpl *)packet; - check_mpp_packet_name(p); - p->flag |= MPP_PACKET_FLAG_EOS; - return MPP_OK; -} - -RK_U32 mpp_packet_get_eos(MppPacket packet) -{ - if (NULL == packet) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppPacketImpl *p = (MppPacketImpl *)packet; - check_mpp_packet_name(p); - return (p->flag & MPP_PACKET_FLAG_EOS) ? (1) : (0); -} - -MPP_RET mpp_packet_set_extra_data(MppPacket packet) -{ - if (NULL == packet) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - MppPacketImpl *p = (MppPacketImpl *)packet; - check_mpp_packet_name(p); - p->flag |= MPP_PACKET_FLAG_EXTRA_DATA; - return MPP_OK; -} - -MPP_RET mpp_packet_reset(MppPacketImpl *packet) -{ - if (NULL == packet) { - mpp_err_f("found NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - check_mpp_packet_name(packet); - memset(packet, 0, sizeof(*packet)); - return MPP_OK; -} - -MPP_RET mpp_packet_read(MppPacket packet, size_t offset, void *data, size_t size) -{ - if (NULL == packet || NULL == data) { - mpp_err_f("invalid input: packet %p data %p\n", packet, data); - return MPP_ERR_UNKNOW; - } - - if (0 == size) - return MPP_OK; - - void *src = mpp_packet_get_data(packet); - mpp_assert(src != NULL); - memcpy(data, (char*)src + offset, size); - return MPP_OK; -} - -MPP_RET mpp_packet_write(MppPacket packet, size_t offset, void *data, size_t size) -{ - if (NULL == packet || NULL == data) { - mpp_err_f("invalid input: packet %p data %p\n", packet, data); - return MPP_ERR_UNKNOW; - } - - if (0 == size) - return MPP_OK; - - void *dst = mpp_packet_get_data(packet); - mpp_assert(dst != NULL); - memcpy((char*)dst + offset, data, size); - return MPP_OK; -} - -/* - * object access function macro - */ -#define MPP_PACKET_ACCESSORS(type, field) \ - type mpp_packet_get_##field(const MppPacket s) \ - { \ - check_mpp_packet_name((MppPacketImpl*)s); \ - return ((MppPacketImpl*)s)->field; \ - } \ - void mpp_packet_set_##field(MppPacket s, type v) \ - { \ - check_mpp_packet_name((MppPacketImpl*)s); \ - ((MppPacketImpl*)s)->field = v; \ - } - -MPP_PACKET_ACCESSORS(void *, data) -MPP_PACKET_ACCESSORS(size_t, size) -MPP_PACKET_ACCESSORS(size_t, length) -MPP_PACKET_ACCESSORS(RK_S64, pts) -MPP_PACKET_ACCESSORS(RK_S64, dts) -MPP_PACKET_ACCESSORS(RK_U32, flag) - diff --git a/mpp/mpp_packet_impl.h b/mpp/mpp_packet_impl.h deleted file mode 100644 index 3633d87ef..000000000 --- a/mpp/mpp_packet_impl.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_IMPL_H__ -#define __MPP_IMPL_H__ - -#include "rk_type.h" -#include "mpp_err.h" - -#define MPP_PACKET_FLAG_EOS (0x00000001) -#define MPP_PACKET_FLAG_EXTRA_DATA (0x00000002) - -/* - * mpp_packet_imp structure - * - * data : pointer - * size : total buffer size - * offset : valid data start offset - * length : valid data length - * pts : packet pts - * dts : packet dts - */ -typedef struct MppPacketImpl_t { - const char *name; - - void *data; - void *pos; - size_t size; - size_t length; - - RK_S64 pts; - RK_S64 dts; - - RK_U32 flag; -} MppPacketImpl; - -/* - * mpp_packet_reset is only used internelly and should NOT be used outside - */ -MPP_RET mpp_packet_reset(MppPacketImpl *packet); - -#endif /*__MPP_IMPL_H__*/ diff --git a/mpp/mpp_sys.c b/mpp/mpp_sys.c new file mode 100644 index 000000000..cee91a14a --- /dev/null +++ b/mpp/mpp_sys.c @@ -0,0 +1,781 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_sys" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_2str.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" +#include "mpp_singleton.h" + +#include "mpp_sys.h" +#include "mpp_cfg_io.h" + +#define SYS_DBG_EN (0x00000001) +#define SYS_DBG_FLOW (0x00000002) + +#define SYS_DBG_CMD (0x00000010) +#define SYS_DBG_ARGS (0x00000020) +#define SYS_DBG_SPLIT (0x00000040) + +#define mpp_sys_dbg(flag, fmt, ...) mpp_dbg(mpp_sys_debug, flag, fmt, ## __VA_ARGS__) + +#define sys_dbg_flow(fmt, ...) mpp_sys_dbg(SYS_DBG_FLOW, fmt, ## __VA_ARGS__) +#define sys_dbg_cmd(fmt, ...) mpp_sys_dbg(SYS_DBG_CMD, fmt, ## __VA_ARGS__) +#define sys_dbg_args(fmt, ...) mpp_sys_dbg(SYS_DBG_ARGS, fmt, ## __VA_ARGS__) +#define sys_dbg_split(fmt, ...) mpp_sys_dbg(SYS_DBG_SPLIT, fmt, ## __VA_ARGS__) + +#define get_srv_sys() \ + ({ \ + MppSysSrv *__tmp; \ + if (srv_sys) { \ + __tmp = srv_sys; \ + } else { \ + mpp_err("mpp sys srv not init at %s\n", __FUNCTION__); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +typedef enum MppSysCmdType_e { + MPP_CMD_SYS, + MPP_CMD_VENC, + MPP_CMD_VDEC, +} MppSysCmdType; + +typedef struct MppSysSrv_t { + struct list_head list; + MppSThd thd; + rk_s32 pid; + rk_s32 ctx_id; + rk_s32 ctx_cnt; + rk_s32 exit_efd; +} MppSysSrv; + +typedef struct MppSysCmdInfo_t MppSysCmdInfo; + +struct MppSysCmdInfo_t { + const char *name; + const char *desc; + + rk_s32 (*cmd)(MppSysSrv *srv, const char **argv, void *ctx); + MppSysCmdInfo *sub_cmd[]; +}; + +static MppSysSrv *srv_sys = NULL; +static rk_u32 mpp_sys_debug = 0; + +rk_s32 mpp_sys_attach(MpiImpl *ctx) +{ + MppSysSrv *srv = get_srv_sys(); + + if (!srv || !srv->thd) + return rk_nok; + + INIT_LIST_HEAD(&ctx->list); + mpp_sthd_lock(srv->thd); + list_add_tail(&ctx->list, &srv->list); + ctx->ctx_id = srv->ctx_id++; + if (srv->ctx_id < 0) + srv->ctx_id = 0; + srv->ctx_cnt++; + mpp_sthd_unlock(srv->thd); + + return rk_ok; +} + +rk_s32 mpp_sys_detach(MpiImpl *ctx) +{ + MppSysSrv *srv = get_srv_sys(); + + if (!srv || !srv->thd) + return rk_nok; + + mpp_sthd_lock(srv->thd); + list_del_init(&ctx->list); + srv->ctx_cnt--; + mpp_sthd_unlock(srv->thd); + + return rk_ok; +} + +static rk_s32 split_line(char *buf, rk_s32 buf_len, const char *argv[], rk_s32 maxargv) +{ + rk_s32 argc = 0; + rk_s32 idx = 0; + rk_s32 end = buf_len; + rk_s32 i; + + sys_dbg_split("==== split_line: buf_len %d hex_dump:\n", end); + for (i = 0; i < end; i++) + sys_dbg_split(" [%02d] %02x '%c'\n", i, (unsigned char)buf[i], + isprint(buf[i]) ? buf[i] : '?'); + + while (argc < maxargv && idx < end) { + sys_dbg_split("---- new token loop -> idx %d\n", idx); + + while (idx < end && isspace((unsigned char)buf[idx])) { + sys_dbg_split(" skip space @%d char %02x", + idx, (unsigned char)buf[idx]); + idx++; + } + + if (idx >= end) + break; + + bool in_quote = false; + char quote_char = 0; + rk_s32 token_start = -1; + rk_s32 dst = idx; + + sys_dbg_split(" token body start: idx %2d char %02x\n", + idx, (unsigned char)buf[idx]); + + while (idx < end) { + char ch = buf[idx]; + + sys_dbg_split(" idx %2d raw %02x ch '%c' in_quote %d", + idx, (unsigned char)ch, isprint(ch) ? ch : '?', in_quote); + + if (!in_quote && isspace((unsigned char)ch)) { + if (token_start == -1) { + idx++; + continue; + } + sys_dbg_split(" break by space @%d", idx); + break; + } + + if (ch == '"' || ch == '\'') { + if (!in_quote) { + in_quote = true; + quote_char = ch; + idx++; + continue; + } + if (ch == quote_char) { + in_quote = false; + idx++; + continue; + } + } else if (ch == '\\' && in_quote) { + idx++; + if (idx >= end) + break; + + ch = buf[idx]; + sys_dbg_split(" escape next %02x", (unsigned char)ch); + + if (token_start == -1) + token_start = dst; + + buf[dst++] = ch; + idx++; + continue; + } + + if (in_quote || !isspace((unsigned char)ch)) { + if (token_start == -1) + token_start = dst; + buf[dst++] = ch; + idx++; + } else { + idx++; + } + } + + if (dst < end) { + buf[dst] = '\0'; + idx++; + } + sys_dbg_split(" token_end %d token_start %d", dst, token_start); + + if (token_start != -1 && token_start < end) + argv[argc++] = &buf[token_start]; + + sys_dbg_split(" argv[%d] = \"%s\"", argc - 1, &buf[token_start]); + } + + sys_dbg_split("==== final argc %d\n", argc); + + return argc; +} + +static rk_s32 mpp_sys_help(MppSysSrv *srv, const char **argv, void *ctx); +static rk_s32 mpp_sys_show(MppSysSrv *srv, const char **argv, void *ctx); +static rk_s32 mpp_sys_venc(MppSysSrv *srv, const char **argv, void *ctx); +static rk_s32 mpp_sys_venc_dump_cfg(MppSysSrv *srv, const char **argv, void *ctx); +static rk_s32 mpp_sys_venc_show_cfg(MppSysSrv *srv, const char **argv, void *ctx); + +static MppSysCmdInfo venc_dump_cfg = { + .name = "dump_cfg", + .desc = "dump venc currnt config to file", + .cmd = mpp_sys_venc_dump_cfg, + .sub_cmd = { + NULL, + }, +}; + +static MppSysCmdInfo venc_show_cfg = { + .name = "show_cfg", + .desc = "show all / enc / dec mpp instances", + .cmd = mpp_sys_venc_show_cfg, + .sub_cmd = { + NULL, + }, +}; + +static MppSysCmdInfo sys_help = { + .name = "help", + .desc = "show all commands", + .cmd = mpp_sys_help, + .sub_cmd = { + NULL, + }, +}; + +static MppSysCmdInfo sys_show = { + .name = "show", + .desc = "show all / enc / dec mpp instances", + .cmd = mpp_sys_show, + .sub_cmd = { + NULL, + }, +}; + +static MppSysCmdInfo venc_cmds = { + .name = "venc", + .desc = "venc command: [all / id] [cmd]", + .cmd = mpp_sys_venc, + .sub_cmd = { + &venc_dump_cfg, + &venc_show_cfg, + NULL, + }, +}; + +static MppSysCmdInfo *sys_cmds[] = { + &sys_help, + &sys_show, + &venc_cmds, + NULL, +}; + +static rk_s32 mpp_sys_help(MppSysSrv *srv, const char *argv[], void *ctx) +{ + MppSysCmdInfo **cmds = &sys_cmds[0]; + rk_s32 idx = 0; + (void)srv; + (void)argv; + (void)ctx; + + mpp_logi("mpp system command list:"); + + while (*cmds) { + MppSysCmdInfo *info = *cmds; + MppSysCmdInfo **subs = &info->sub_cmd[0]; + rk_s32 sub_idx = 0; + + mpp_logi("%2d | %-8s | : %s", idx, info->name, info->desc); + + while (*subs) { + MppSysCmdInfo *sub = *subs; + + mpp_logi(" |- %2d | %-8s | : %s", sub_idx, sub->name, sub->desc); + subs++; + sub_idx++; + } + + cmds++; + idx++; + } + + return 0; +} + +static rk_s32 mpp_sys_show(MppSysSrv *srv, const char *argv[], void *ctx) +{ + MpiImpl *impl; + MpiImpl *tmp; + rk_u32 show_mask = 0; + rk_s32 next = 0; + (void)ctx; + + if (argv[1]) { + rk_s32 i; + + static const char *filter[] = { + "dec", + "enc", + "all", + }; + static rk_u32 filter_mask[] = { + MPP_BIT(MPP_CTX_DEC), + MPP_BIT(MPP_CTX_ENC), + MPP_BIT32_OR(MPP_CTX_ENC, MPP_CTX_DEC), + }; + + for (i = 0; i < MPP_ARRAY_ELEMS_S(filter); i++) { + if (!strcmp(argv[1], filter[i])) { + show_mask = filter_mask[i]; + next++; + + mpp_logi("show %s contexts info:\n", filter[i]); + break; + } + } + } + + if (show_mask == 0) { + show_mask = MPP_BIT32_OR(MPP_CTX_ENC, MPP_CTX_DEC); + mpp_logi("show all contexts info:\n"); + } + + + mpp_sthd_lock(srv->thd); + + list_for_each_entry_safe(impl, tmp, &srv->list, MpiImpl, list) { + rk_u32 mask = MPP_BIT(impl->type); + + if ((show_mask & mask) == 0) + continue; + + switch (impl->type) { + case MPP_CTX_DEC : { + Mpp *mpp = impl->ctx; + MppDec dec = mpp->mDec; + MppEncCfg cfg = mpp_dec_to_cfg(dec); + rk_s32 width = 0; + rk_s32 height = 0; + + mpp_dec_cfg_get_s32(cfg, "status:width", &width); + mpp_dec_cfg_get_s32(cfg, "status:height", &height); + + mpp_logi("ctx %4d - dec %-6s - %4dx%-4d\n", impl->ctx_id, + strof_coding_type(impl->coding), width, height); + } break; + case MPP_CTX_ENC : { + Mpp *mpp = impl->ctx; + MppEnc enc = mpp->mEnc; + MppEncCfg cfg = mpp_enc_to_cfg(enc); + rk_s32 width = 0; + rk_s32 height = 0; + + mpp_enc_cfg_get_s32(cfg, "prep:width", &width); + mpp_enc_cfg_get_s32(cfg, "prep:height", &height); + + mpp_logi("ctx %4d - enc %-6s - %4dx%-4d\n", impl->ctx_id, + strof_coding_type(impl->coding), width, height); + } break; + default : { + } break; + } + } + + mpp_sthd_unlock(srv->thd); + + return next; +} + +static rk_s32 safe_atoi(const char *s, rk_s32 *out) +{ + char *e = NULL; + rk_long v; + + errno = 0; + v = strtol(s, &e, 10); + + if (e == s || *e != '\0') + return -1; + + if (errno == ERANGE || v < INT_MIN || v > INT_MAX) + return -2; + + *out = (int)v; + + return rk_ok; +} + +static rk_s32 mpp_sys_venc(MppSysSrv *srv, const char **argv, void *ctx) +{ + const char *cmd = NULL; + MppSysCmdInfo *sub = NULL; + MpiImpl *impl; + MpiImpl *tmp; + rk_s32 next = 0; + rk_s32 ctx_id = -1; + (void)ctx; + + if (argv[1]) { + rk_s32 ret = safe_atoi(argv[1], &ctx_id); + + if (ret == 0 && ctx_id >= 0) + next++; + else + ctx_id = -1; + } + + if (argv[next + 1]) { + MppSysCmdInfo **cmds = &venc_cmds.sub_cmd[0]; + rk_s32 j = 0; + + cmd = argv[next + 1]; + + while (*cmds) { + MppSysCmdInfo *t = *cmds; + bool match = !strcmp(cmd, t->name); + + sys_dbg_args("match %d %-8s -> %s", j, + t->name, match ? "yes" : "no"); + + if (match) { + sub = t; + break; + } + + cmds++; + } + + if (sub != NULL) + next++; + } + + if (sub == NULL) + return next; + + mpp_sthd_lock(srv->thd); + + list_for_each_entry_safe(impl, tmp, &srv->list, MpiImpl, list) { + if (impl->type != MPP_CTX_ENC) + continue; + + if (ctx_id >= 0 && impl->ctx_id != ctx_id) + continue; + + sub->cmd(srv, &argv[next + 1], impl); + } + + mpp_sthd_unlock(srv->thd); + + return next; +} + +static rk_s32 mpp_sys_venc_dump_cfg(MppSysSrv *srv, const char **argv, void *ctx) +{ + MpiImpl *impl = (MpiImpl *)ctx; + Mpp *mpp = impl->ctx; + MppEncCfg cfg; + FILE *fp; + + if (NULL == mpp->mEnc) { + mpp_loge("venc %d dump cfg but not init", impl->ctx_id); + return 0; + } + + cfg = mpp_enc_to_cfg(mpp->mEnc); + if (NULL == cfg) { + mpp_loge("venc %d dump cfg but get cfg failed", impl->ctx_id); + return 0; + } + + { + char file_name[128]; + char *buf = NULL; + + snprintf(file_name, sizeof(file_name) - 1, "%s/mpp-%d-%d.json", + argv[0], srv->pid, impl->ctx_id); + + fp = fopen(file_name, "w+b"); + if (NULL == fp) { + mpp_loge("venc %d dump cfg but open file %s failed %s\n", + impl->ctx_id, file_name, strerror(errno)); + return 0; + } + + mpp_enc_cfg_extract(cfg, MPP_CFG_STR_FMT_JSON, &buf); + if (buf) { + rk_s32 len = strlen(buf); + rk_s32 wr_nr = 0; + + wr_nr = fwrite(buf, 1, len, fp); + if (wr_nr != len) { + mpp_loge("venc %d write cfg to file %s failed, written %d/%d\n", + impl->ctx_id, file_name, wr_nr, len); + } + + mpp_free(buf); + } + + fclose(fp); + } + + return 1; +} + +static rk_s32 mpp_sys_venc_show_cfg(MppSysSrv *srv, const char **argv, void *ctx) +{ + MpiImpl *impl = (MpiImpl *)ctx; + Mpp *mpp = impl->ctx; + (void)srv; + (void)argv; + + mpp_logi("venc %d dump cfg:", impl->ctx_id); + + if (mpp->mEnc) { + MppEncCfg cfg = mpp_enc_to_cfg(mpp->mEnc); + + if (cfg) { + char *buf = NULL; + + mpp_enc_cfg_extract(cfg, MPP_CFG_STR_FMT_LOG, &buf); + if (buf) { + mpp_cfg_print_string(buf); + mpp_free(buf); + } + } + } + + return 0; +} + + +static rk_s32 mpp_sys_ctrl(rk_s32 pid, char *cmd, rk_s32 n) +{ + MppSysSrv *srv = get_srv_sys(); + MppSysCmdInfo **cmds = NULL; + const char *argv[32]; + rk_s32 argc; + rk_s32 i; + + sys_dbg_cmd("mpp-%d [cmd]: (%d) %s", pid, strlen(cmd), cmd); + + if (!srv || !srv->thd) + return rk_nok; + + argc = split_line(cmd, n, argv, 32); + + sys_dbg_args("argc %d", argc); + for (i = 0; i < argc; i++) + sys_dbg_args("argv[%d]: %s", i, argv[i]); + + for (i = 0; i < argc; i++) { + rk_s32 j = 0; + + if (!argv[i]) + break; + + sys_dbg_args("argv[%d]: %s", i, argv[i]); + + cmds = &sys_cmds[0]; + + while (*cmds) { + MppSysCmdInfo *info = *cmds; + bool match = !strcmp(argv[i], info->name); + + sys_dbg_args("match %d %-8s -> %s", j, + info->name, match ? "yes" : "no"); + + if (match) { + i += info->cmd(srv, &argv[i], NULL); + break; + } + + cmds++; + j++; + } + } + + return 0; +} + +static void *mpp_sys_srv(MppSThdCtx *data) +{ + MppSThd thd = data->thd; + MppSysSrv *ctx = (MppSysSrv *)data->ctx; + struct epoll_event ev = { .events = EPOLLIN }; + char cmd_buf[256]; + char name[128]; + MppSThdStatus status; + rk_s32 nf; + rk_s32 exit_efd = ctx->exit_efd; + rk_s32 fifo_fd = -1; + rk_s32 epoll_fd = -1; + rk_s32 pid = ctx->pid; + + snprintf(name, sizeof(name) - 1, "/tmp/mpp-%d-cmd", pid); + do { + if (0 != mkfifo(name, 0600)) { + sys_dbg_flow("pid %d mkfifo %s failed for %s\n", + pid, name, strerror(errno)); + break; + } + + fifo_fd = open(name, O_RDWR | O_CLOEXEC); + if (fifo_fd < 0) { + sys_dbg_flow("pid %d open fifo %s failed for %s\n", + pid, name, strerror(errno)); + break; + } + + /* add epoll and exit efd */ + epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (epoll_fd < 0) { + sys_dbg_flow("pid %d create epoll failed for %s\n", + pid, strerror(errno)); + break; + } + + sys_dbg_flow("pid %d create sys cmd fifo %s fd %d\n", + pid, name, fifo_fd); + + /* add exit event fd */ + ev.data.fd = exit_efd; + epoll_ctl(epoll_fd, EPOLL_CTL_ADD, exit_efd, &ev); + + ev.data.fd = fifo_fd; + epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fifo_fd, &ev); + + while (1) { + mpp_sthd_lock(thd); + status = mpp_sthd_get_status(thd); + mpp_sthd_unlock(thd); + + if (status != MPP_STHD_RUNNING) + break; + + nf = epoll_wait(epoll_fd, &ev, 1, -1); + if (nf <= 0) + continue; + + // exit event + if (ev.data.fd == exit_efd) { + rk_u64 u; + rk_s32 rd = read(exit_efd, &u, 8); + + if (rd == 8) + break; + } + + // normal event + if (ev.data.fd == fifo_fd) { + rk_s32 n = read(fifo_fd, cmd_buf, sizeof(cmd_buf) - 1); + + if (n > 0) { + cmd_buf[n] = '\0'; + mpp_sys_ctrl(pid, cmd_buf, n); + } + } + } + } while (0); + + /* clean up all fds */ + if (epoll_fd > 0) + close(epoll_fd); + + if (fifo_fd > 0) { + close(fifo_fd); + unlink(name); + } + + sys_dbg_flow("pid %d sys srv finish\n", pid); + + return NULL; +} + +static void mpp_sys_init(void) +{ + MppSysSrv *srv = srv_sys; + + mpp_env_get_u32("mpp_sys_debug", &mpp_sys_debug, 0); + + if (srv) + return; + + srv = mpp_calloc(MppSysSrv, 1); + if (!srv) { + mpp_err_f("alloc mpp sys srv failed\n"); + return; + } + + srv_sys = srv; + + INIT_LIST_HEAD(&srv->list); + srv->pid = getpid(); + + /* setup external command fifo and system service thread */ + if (mpp_sys_debug != 0) { + MppSThd sys_thd = NULL; + char name[64]; + rk_s32 exit_efd; + rk_s32 pid = srv->pid; + + mpp_sys_debug |= SYS_DBG_EN; + + /* create system service thread and its exit event fd */ + exit_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + + if (exit_efd < 0) { + sys_dbg_flow("pid %d create exit event fd failed ret %d %s\n", + pid, exit_efd, strerror(errno)); + return; + } + + srv->exit_efd = exit_efd; + snprintf(name, sizeof(name) - 1, "mpp-%d-sys-srv", pid); + sys_thd = mpp_sthd_get(name); + if (sys_thd) { + mpp_sthd_setup(sys_thd, mpp_sys_srv, srv); + mpp_sthd_start(sys_thd); + srv->thd = sys_thd; + } else { + sys_dbg_flow("pid %d create sys srv thread failed\n", pid); + } + } +} + +static void mpp_sys_deinit(void) +{ + MppSysSrv *srv = srv_sys; + + if (!srv) + return; + + srv_sys = NULL; + + if (srv->thd != NULL) { + /* notify system service to quit */ + rk_u64 exit_val = 1; + rk_s32 ret; + + mpp_sthd_stop(srv->thd); + ret = write(srv->exit_efd, &exit_val, sizeof(exit_val)); + if (ret != sizeof(exit_val)) { + mpp_loge("write to exit_efd failed, ret %zd expected %zu\n", + ret, sizeof(exit_val)); + } + + /* wait for system service to quit */ + mpp_sthd_stop_sync(srv->thd); + mpp_sthd_put(srv->thd); + srv->thd = NULL; + } + + mpp_free(srv); +} + +MPP_SINGLETON(MPP_SGLN_SYS, mpp_sys, mpp_sys_init, mpp_sys_deinit) diff --git a/mpp/soc.cmake b/mpp/soc.cmake new file mode 100644 index 000000000..4561aa480 --- /dev/null +++ b/mpp/soc.cmake @@ -0,0 +1,328 @@ +# This file setup the default enable flag of all supported codecs +# The default value is ON for all codecs +# If MPP_SOC is defined, we will enable/disable codecs based on the SoC capability + +# Define all supported codec types +set(MPP_CODEC_TYPES + # decoders + AVSD + AVS2D + H263D + H264D + H265D + MPEG2D + MPEG4D + VP8D + VP9D + JPEGD + AV1D + + # encoders + H264E + H265E + JPEGE + VP8E +) + +# Define all supported hardware types +set(MPP_HW_TYPES + # decoder + VDPU1 + VDPU2 + VDPU341 + VDPU34X + VDPU381 + VDPU382 + VDPU383 + VDPU384A + VDPU384B + VDPU720 + VDPU730 + AV1D_VPU + + # encoder + VEPU1 + VEPU2 + VEPU541 + VEPU580 + VEPU540C + VEPU510 + VEPU511 + VEPU511A + VEPU720 +) + +# Define SOC configuration table +# Format: add_soc_config(soc_pattern hw_list decoders encoders) +# - soc_pattern: SOC name, comma-separated list, or regex pattern +# Examples: "RK3588", "RK3066, RK3188", "RK356[678]" +# - hw_list: Hardware modules (comma-separated) +# Examples: "VDPU341,VDPU2,VEPU2" +# - decoders: Supported decoder codecs (comma-separated, empty string if none) +# Examples: "H264D,H265D,JPEGD" or "" +# - encoders: Supported encoder codecs (comma-separated, empty string if none) +# Examples: "H264E,JPEGE,VP8E" or "" +# +# Helper function to add a SOC configuration entry +function(add_soc_config soc_pattern hw_list decoders encoders) + set(codec_list "") + if (NOT decoders STREQUAL "") + set(codec_list "${decoders}") + endif() + if (NOT encoders STREQUAL "") + if (NOT codec_list STREQUAL "") + set(codec_list "${codec_list},${encoders}") + else() + set(codec_list "${encoders}") + endif() + endif() + set(entry "${soc_pattern}|${hw_list}|${codec_list}") + list(APPEND SOC_CONFIG_TABLE "${entry}") + set(SOC_CONFIG_TABLE "${SOC_CONFIG_TABLE}" PARENT_SCOPE) +endfunction() + +# Add SOC configurations +add_soc_config("RK3036" + "VDPU1,VDPU341,VDPU1" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "") + +add_soc_config("RK3066, RK3188" + "VDPU1,VDPU1,VEPU1" + "H263D,H264D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RK3288" + "VDPU341,VDPU1,VDPU1,VEPU1" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RK312[68]" + "VDPU1,VDPU341,VDPU1,VEPU1" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RK3128H" + "VDPU341,VDPU2,VEPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "H264E,VP8E") + +add_soc_config("RK3368" + "VDPU341,VDPU1,VDPU1,VEPU1" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RK3399" + "VDPU341,VDPU2,VEPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RK3328" + "VDPU341,VDPU2,VEPU2,VEPU22" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AVSD" + "H264E,JPEGE,VP8E,H265E") + +add_soc_config("RK3228" + "VDPU341,VDPU2,VEPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AVSD" + "H264E,VP8E") + +add_soc_config("RK3228H" + "VDPU341,VDPU2,VEPU2,VEPU22" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AVSD" + "H264E,VP8E,H265E") + +add_soc_config("RK3229" + "VDPU341,VDPU2,VEPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RV1108" + "VDPU2,VDPU341,VEPU2,VEPU541" + "H264D,JPEGD" + "H264E,JPEGE") + +add_soc_config("RV1109, RV1126" + "VDPU341,VDPU2,VEPU2,VEPU541" + "H264D,H265D,JPEGD" + "H264E,JPEGE,H265E") + +add_soc_config("RK3326, PX30" + "VDPU341,VDPU2,VEPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RK1808" + "VDPU2,VEPU2" + "H263D,H264D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD" + "H264E,JPEGE,VP8E") + +add_soc_config("RK356[678]" + "VDPU34X,VDPU720,VDPU2,VEPU541,VEPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AVSD" + "H264E,JPEGE,H265E") + +add_soc_config("RK3588" + "VDPU381,VDPU34X,VDPU720,VDPU2,AV1D_VPU,VEPU580,VEPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AV1D,AVSD,AVS2D" + "H264E,JPEGE,VP8E,H265E") + +add_soc_config("RK3528" + "VDPU382,VDPU720,VDPU2,VEPU540C" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,AVSD,AVS2D" + "H264E,H265E,JPEGE") + +add_soc_config("RK3528A" + "VDPU382,VDPU720,VDPU2,VEPU540C" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AVSD,AVS2D" + "H264E,H265E,JPEGE") + +add_soc_config("RK3562" + "VDPU382,VDPU720,VEPU540C" + "H264D,H265D,JPEGD,VP9D" + "H264E,JPEGE") + +add_soc_config("RK3576" + "VDPU383,VDPU720,VEPU510,VEPU720" + "H264D,H265D,JPEGD,VP9D,AV1D,AVS2D" + "H264E,H265E,JPEGE") + +add_soc_config("RV1126B" + "VDPU384A,VDPU720,VEPU511" + "H264D,H265D,JPEGD" + "H264E,H265E,JPEGE") + +add_soc_config("RK353[89]" + "VDPU384B,VDPU730,VDPU2" + "H263D,H264D,H265D,JPEGD,MPEG2D,MPEG4D,VP8D,VP9D,AV1D,AVSD" + "") + +add_soc_config("RK3572" + "VDPU384B,VDPU730,VEPU511A,VEPU720" + "H264D,H265D,JPEGD,VP9D,AV1D,AVS2D" + "H264E,H265E,JPEGE") + +# Helper macro to set all codec defaults +macro(set_all_codec_defaults value) + foreach(codec ${MPP_CODEC_TYPES}) + set(ENABLE_${codec}_DEFAULT ${value}) + endforeach() +endmacro() + +# Helper macro to enable HW +macro(soc_enable_hw) + foreach(hw ${ARGN}) + set(HAVE_${hw} ON) + add_definitions(-DHW_${hw}) + endforeach() +endmacro() + +# Helper macro to enable codecs +macro(soc_enable_codec) + foreach(codec ${ARGN}) + set(ENABLE_${codec}_DEFAULT ON) + endforeach() +endmacro() + +# Default to OFF (enable only what we need) +set_all_codec_defaults(OFF) + +# Process SOC configuration +if (MPP_SOC) + string(TOUPPER ${MPP_SOC} MPP_SOC_UPPER) + message(STATUS "Configuring for SoC: ${MPP_SOC_UPPER}") + + + # Helper function to auto-detect match type and check if SOC matches + # Supports: + # - Exact match: "RK3588" + # - Multiple exact matches: "RK3066, RK3188" + # - Regex pattern: "RK356[678]" (contains regex special chars) + function(soc_matches_pattern pattern soc_upper result_var) + set(matched FALSE) + + # Check if pattern contains regex special characters + if (pattern MATCHES "[]\\[^$|*+?()]") + # Use regex matching + if (soc_upper MATCHES ${pattern}) + set(matched TRUE) + endif() + elseif (pattern MATCHES ",") + # Multiple exact matches separated by comma + string(REPLACE "," ";" pattern_list ${pattern}) + foreach(p ${pattern_list}) + string(STRIP ${p} p_stripped) + if (soc_upper STREQUAL p_stripped) + set(matched TRUE) + break() + endif() + endforeach() + else() + # Single exact match + if (soc_upper STREQUAL pattern) + set(matched TRUE) + endif() + endif() + + set(${result_var} ${matched} PARENT_SCOPE) + endfunction() + + # Process SOC configuration + set(SOC_FOUND FALSE) + foreach(config_entry ${SOC_CONFIG_TABLE}) + + # Split by "|" (pipe separates the three main fields) + string(REPLACE "|" ";" config_list "${config_entry}") + list(LENGTH config_list list_len) + + # Extract fields with safe defaults + list(GET config_list 0 soc_pattern) + set(hw_list_str "") + set(codec_enable_str "") + + if (list_len GREATER 1) + list(GET config_list 1 hw_list_str) + endif() + if (list_len GREATER 2) + list(GET config_list 2 codec_enable_str) + endif() + + # Auto-detect match type and check if SOC matches + soc_matches_pattern("${soc_pattern}" "${MPP_SOC_UPPER}" matched) + + if (matched) + message(STATUS "Applying SOC configuration for: ${soc_pattern}") + message(STATUS "hw_list_str='${hw_list_str}', codec_enable_str='${codec_enable_str}'") + if (NOT hw_list_str STREQUAL "") + string(REPLACE "," ";" hw_list "${hw_list_str}") + #message(STATUS "DEBUG: hw_list='${hw_list}'") + soc_enable_hw(${hw_list}) + endif() + if (NOT codec_enable_str STREQUAL "") + string(REPLACE "," ";" codec_enable_list "${codec_enable_str}") + #message(STATUS "DEBUG: codec_enable_list='${codec_enable_list}'") + soc_enable_codec(${codec_enable_list}) + else() + # Empty codec_enable_list means enable all codecs + message(STATUS " Enabling all codecs") + set_all_codec_defaults(ON) + endif() + set(SOC_FOUND TRUE) + break() + endif() + endforeach() + + if (NOT SOC_FOUND) + message(WARNING "Unsupported SoC: ${MPP_SOC_UPPER}, falling back to generic configuration") + unset(MPP_SOC) + unset(MPP_SOC_UPPER) + + # Fallback: enable all hardware and codecs + soc_enable_hw(${MPP_HW_TYPES}) + set_all_codec_defaults(ON) + endif() +else() + # Fallback: enable all if no SOC specified + soc_enable_hw(${MPP_HW_TYPES}) + set_all_codec_defaults(ON) +endif() diff --git a/mpp/test/CMakeLists.txt b/mpp/test/CMakeLists.txt deleted file mode 100644 index 0374f0736..000000000 --- a/mpp/test/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# vim: syntax=cmake -# ---------------------------------------------------------------------------- -# mpp built-in unit test case -# ---------------------------------------------------------------------------- -# macro for adding mpp sub-module unit test -macro(add_mpp_test module) - set(test_name ${module}_test) - string(TOUPPER ${test_name} test_tag) - #message(STATUS "moduule : ${module}") - #message(STATUS "test_name : ${test_name}") - #message(STATUS "test_tag : ${test_tag}") - - option(${test_tag} "Build mpp ${module} unit test" ON) - if(${test_tag}) - add_executable(${test_name} ${test_name}.c) - target_link_libraries(${test_name} mpp) - set_target_properties(${test_name} PROPERTIES FOLDER "mpp/test") - install(TARGETS ${test_name} RUNTIME DESTINATION ${TEST_INSTALL_DIR}) - endif() -endmacro() - -# info system unit test -add_mpp_test(mpp_info) - -# h264 decoder test -option(H264D_TEST "Build mpp h264 decoder unit test" ON) -if(H264D_TEST) - set(test_name h264d_test) - add_executable(${test_name} ${test_name}.c h264d_rwfile.h h264d_rwfile.c) - target_link_libraries(${test_name} mpp) - set_target_properties(${test_name} PROPERTIES FOLDER "mpp/test") - install(TARGETS ${test_name} RUNTIME DESTINATION ${TEST_INSTALL_DIR}) -endif() - - diff --git a/mpp/test/h264d_rwfile.c b/mpp/test/h264d_rwfile.c deleted file mode 100644 index ed4ddc211..000000000 --- a/mpp/test/h264d_rwfile.c +++ /dev/null @@ -1,799 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include -#include -#include - -#include "mpp_log.h" -#include "mpp_packet.h" -#include "mpp_packet_impl.h" -#include "mpp_mem.h" -#include "mpp_env.h" -#include "h264d_log.h" -#include "h264d_rwfile.h" - - -#define MODULE_TAG "h264d_rwfile" -#define MAX_STRING_SIZE 128 - -#define MAX_ITEMS_TO_PARSE 32 -#define START_PREFIX_3BYTE 3 -#define MAX_ITEMS_TO_PARSE 32 - -#define RKVDEC_REG_HEADER 0x48474552 -#define RKVDEC_PPS_HEADER 0x48535050 -#define RKVDEC_SCL_HEADER 0x534c4353 -#define RKVDEC_RPS_HEADER 0x48535052 -#define RKVDEC_CRC_HEADER 0x48435243 -#define RKVDEC_STM_HEADER 0x4d525453 -#define RKVDEC_ERR_HEADER 0x524f5245 - - -static const RK_S32 IOBUFSIZE = 512 * 1024; //524288 -static const RK_S32 STMBUFSIZE = 512 * 1024; //524288 - - -//!< values for nal_unit_type -typedef enum { - NALU_TYPE_NULL = 0, - NALU_TYPE_SLICE = 1, - NALU_TYPE_DPA = 2, - NALU_TYPE_DPB = 3, - NALU_TYPE_DPC = 4, - NALU_TYPE_IDR = 5, - NALU_TYPE_SEI = 6, - NALU_TYPE_SPS = 7, - NALU_TYPE_PPS = 8, - NALU_TYPE_AUD = 9, // Access Unit Delimiter - NALU_TYPE_EOSEQ = 10, // end of sequence - NALU_TYPE_EOSTREAM = 11, // end of stream - NALU_TYPE_FILL = 12, - NALU_TYPE_SPSEXT = 13, - NALU_TYPE_PREFIX = 14, // prefix - NALU_TYPE_SUB_SPS = 15, - NALU_TYPE_SLICE_AUX = 19, - NALU_TYPE_SLC_EXT = 20, // slice extensive - NALU_TYPE_VDRD = 24 // View and Dependency Representation Delimiter NAL Unit - -} Nalu_type; - - -typedef struct { - RK_U8 *data_; - RK_U32 bytes_left_; - RK_S64 curr_byte_; - RK_S32 num_remaining_bits_in_curr_byte_; - RK_S64 prev_two_bytes_; - RK_S64 emulation_prevention_bytes_; - RK_S32 used_bits; - RK_U8 *buf; - RK_S32 buf_len; -} GetBitCtx_t; - -typedef struct { - RK_U32 header; - RK_U8 *data; - RK_U32 len; - RK_S32 pps_id; -} TempDataCtx_t; - -static void display_input_cmd(RK_S32 argc, char *argv[]) -{ - RK_S32 nn = 0; - char *pnamecmd = NULL; - char strcmd[MAX_STRING_SIZE] = {0}; - - strcat(strcmd, "INPUT_CMD: "); - pnamecmd = strrchr(argv[0], '/'); - pnamecmd = pnamecmd ? (pnamecmd + 1) : (strrchr(argv[0], '\\') + 1) ; - strcat(strcmd, pnamecmd); - for (nn = 1; nn < argc; nn++) { - strcat(strcmd, " "); - strcat(strcmd, argv[nn]); - } - mpp_log("%s \n", strcmd); -} - -static void print_help_message(char *cmd) -{ - mpp_log( - "##### Options\n" - " -h/--help : prints help message.\n" - " --cmppath :[string] Set golden input file store directory.\n" - " --outpath :[string] Set driver output file store directory.\n" - " -r/--raw :[number] Set bitstream raw cfg, 0/1: slice long 2:slice short.\n" - " -c/--cfg :[file] Set configure file< such as, decoder.cfg>.\n" - " -i/--input :[file] Set input bitstream file.\n" - " -n/--num :[number] Set decoded frames.\n" - "##### Examples of usage:\n" - " %s -h\n" - " %s -c decoder.cfg\n" - " %s -i input.bin -n 10 ", cmd, cmd, cmd); -} - -static RK_U8 *get_config_file_content(char *fname) -{ - FILE *fp_cfg = NULL; - RK_U8 *pbuf = NULL; - RK_U32 filesize = 0; - - if (!(fp_cfg = fopen(fname, "r"))) { - mpp_log("Cannot open configuration file %s.", fname); - goto __FAILED; - } - - if (fseek(fp_cfg, 0, SEEK_END)) { - mpp_log("Cannot fseek in configuration file %s.", fname); - goto __FAILED; - } - - filesize = ftell(fp_cfg); - - if (filesize > 150000) { - mpp_log("\n Unreasonable Filesize %d reported by ftell for configuration file %s.", filesize, fname); - goto __FAILED; - } - if (fseek(fp_cfg, 0, SEEK_SET)) { - mpp_log("Cannot fseek in configuration file %s.", fname); - goto __FAILED; - } - - if (!(pbuf = mpp_malloc_size(RK_U8, filesize + 1))) { - mpp_log("Cannot malloc content buffer for file %s.", fname); - goto __FAILED; - } - filesize = (long)fread(pbuf, 1, filesize, fp_cfg); - pbuf[filesize] = '\0'; - - FCLOSE(fp_cfg); - - return pbuf; -__FAILED: - FCLOSE(fp_cfg); - - return NULL; -} - -static MPP_RET parse_content(InputParams *p_in, RK_U8 *p) -{ - RK_S32 i = 0, item = 0; - RK_S32 InString = 0, InItem = 0; - RK_U8 *bufend = NULL; - RK_U8 *items[MAX_ITEMS_TO_PARSE] = { NULL }; - - //==== parsing - bufend = &p[strlen((const char *)p)]; - while (p < bufend) { - switch (*p) { - case 13: - ++p; - break; - case '#': // Found comment - *p = '\0'; // Replace '#' with '\0' in case of comment immediately following integer or string - while (*p != '\n' && p < bufend) // Skip till EOL or EOF, whichever comes first - ++p; - InString = 0; - InItem = 0; - break; - case '\n': - InItem = 0; - InString = 0; - *p++ = '\0'; - break; - case ' ': - case '\t': // Skip whitespace, leave state unchanged - if (InString) - p++; - else { - // Terminate non-strings once whitespace is found - *p++ = '\0'; - InItem = 0; - } - break; - - case '"': // Begin/End of String - *p++ = '\0'; - if (!InString) { - items[item++] = p; - InItem = ~InItem; - } else - InItem = 0; - InString = ~InString; // Toggle - break; - - default: - if (!InItem) { - items[item++] = p; - InItem = ~InItem; - } - p++; - } - } - item--; - //===== read syntax - for (i = 0; i < item; i += 3) { - if (!strncmp((const char*)items[i], "InputFile", 9)) { - strncpy((char *)p_in->infile_name, (const char*)items[i + 2], strlen((const char*)items[i + 2]) + 1); - } else if (!strncmp((const char*)items[i], "GoldenDataPath", 14)) { - strncpy((char *)p_in->cmp_path_dir, (const char*)items[i + 2], strlen((const char*)items[i + 2]) + 1); - } else if (!strncmp((const char*)items[i], "OutputDataPath", 14)) { - strncpy((char *)p_in->out_path_dir, (const char*)items[i + 2], strlen((const char*)items[i + 2]) + 1); - } else if (!strncmp((const char*)items[i], "DecodedFrames", 13)) { - if (!sscanf((const char*)items[i + 2], "%d", &p_in->iDecFrmNum)) { - goto __FAILED; - } - } else if (!strncmp((const char*)items[i], "BitStrmRawCfg", 13)) { - if (!sscanf((const char*)items[i + 2], "%d", &p_in->raw_cfg)) { - goto __FAILED; - } - } - } - - return MPP_OK; -__FAILED: - return MPP_NOK; -} - -static MPP_RET parse_command(InputParams *p_in, int ac, char *av[]) -{ - RK_S32 CLcount = 0; - RK_U8 *content = NULL; - char *pnamecmd = NULL; - RK_U8 have_cfg_flag = 0; - - CLcount = 1; - while (CLcount < ac) { - if (!strncmp(av[1], "-h", 2) || !strncmp(av[1], "--help", 6)) { - pnamecmd = strrchr(av[0], '/'); - pnamecmd = pnamecmd ? (pnamecmd + 1) : (strrchr(av[0], '\\') + 1) ; - print_help_message(pnamecmd); - goto __FAILED; - } else if (!strncmp(av[CLcount], "-n", 2) || !strncmp(av[1], "--num", 5)) { // decoded frames - if (!sscanf(av[CLcount + 1], "%d", &p_in->iDecFrmNum)) { - goto __FAILED; - } - CLcount += 2; - } else if (!strncmp(av[CLcount], "-i", 2) || !strncmp(av[1], "--input", 7)) { - strncpy(p_in->infile_name, av[CLcount + 1], strlen((const char*)av[CLcount + 1]) + 1); - CLcount += 2; - } else if (!strncmp(av[CLcount], "--cmppath", 9)) { // compare direct path - strncpy(p_in->cmp_path_dir, av[CLcount + 1], strlen((const char*)av[CLcount + 1]) + 1); - CLcount += 2; - } else if (!strncmp(av[CLcount], "--outpath", 9)) { // compare direct path - strncpy(p_in->out_path_dir, av[CLcount + 1], strlen((const char*)av[CLcount + 1]) + 1); - CLcount += 2; - } else if (!strncmp(av[1], "-r", 2) || !strncmp(av[CLcount], "--raw", 5)) { - if (!sscanf(av[CLcount + 1], "%d", &p_in->raw_cfg)) { - goto __FAILED; - } - CLcount += 2; - } else if (!strncmp(av[1], "-c", 2) || !strncmp(av[CLcount], "--cfg", 5)) { // configure file - strncpy(p_in->cfgfile_name, av[CLcount + 1], FILE_NAME_SIZE); - CLcount += 2; - have_cfg_flag = 1; - } else { - mpp_log("Error: %s cannot explain command! \n", av[CLcount]); - goto __FAILED; - } - } - if (have_cfg_flag) { - if (!(content = get_config_file_content(p_in->cfgfile_name))) { - goto __FAILED; - } - if (parse_content(p_in, content)) { - goto __FAILED; - } - mpp_free(content); - } - - return MPP_OK; -__FAILED: - - return MPP_NOK; -} - -static FILE *open_file(char *path, char *infile, char *sufix, const char *mode) -{ - char tmp_fname[FILE_NAME_SIZE] = { 0 }; - - sprintf(tmp_fname, "%s/%s%s", path, (strrchr(infile, '/') + 1), sufix); - - return fopen(tmp_fname, mode); -} - -static MPP_RET update_curr_byte(GetBitCtx_t *pStrmData) -{ - if (pStrmData->bytes_left_ < 1) - return MPP_NOK; - - // Emulation prevention three-byte detection. - // If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03). - if (*pStrmData->data_ == 0x03 && (pStrmData->prev_two_bytes_ & 0xffff) == 0) { - // Detected 0x000003, skip last byte. - ++pStrmData->data_; - --pStrmData->bytes_left_; - ++pStrmData->emulation_prevention_bytes_; - // Need another full three bytes before we can detect the sequence again. - pStrmData->prev_two_bytes_ = 0xffff; - - if (pStrmData->bytes_left_ < 1) - return MPP_NOK; - } - - // Load a new byte and advance pointers. - pStrmData->curr_byte_ = *pStrmData->data_++ & 0xff; - --pStrmData->bytes_left_; - pStrmData->num_remaining_bits_in_curr_byte_ = 8; - - pStrmData->prev_two_bytes_ = (pStrmData->prev_two_bytes_ << 8) | pStrmData->curr_byte_; - - return MPP_OK; -} - -// Read |num_bits| (1 to 31 inclusive) from the stream and return them -// in |out|, with first bit in the stream as MSB in |out| at position -// (|num_bits| - 1). -static MPP_RET read_bits(GetBitCtx_t *pStrmData, RK_S32 num_bits, RK_S32 *out) -{ - RK_S32 bits_left = num_bits; - *out = 0; - ASSERT(num_bits <= 31); - - while (pStrmData->num_remaining_bits_in_curr_byte_ < bits_left) { - // Take all that's left in current byte, shift to make space for the rest. - *out |= (pStrmData->curr_byte_ << (bits_left - pStrmData->num_remaining_bits_in_curr_byte_)); - bits_left -= pStrmData->num_remaining_bits_in_curr_byte_; - - if (update_curr_byte(pStrmData)) { - return MPP_NOK; - } - } - - *out |= (pStrmData->curr_byte_ >> (pStrmData->num_remaining_bits_in_curr_byte_ - bits_left)); - *out &= ((1 << num_bits) - 1); - pStrmData->num_remaining_bits_in_curr_byte_ -= bits_left; - pStrmData->used_bits += num_bits; - - return MPP_OK; -} - -static MPP_RET read_ue(GetBitCtx_t *pStrmData, RK_U32 *val) -{ - RK_S32 num_bits = -1; - RK_S32 bit; - RK_S32 rest; - // Count the number of contiguous zero bits. - do { - if (read_bits(pStrmData, 1, &bit)) { - return MPP_NOK; - } - num_bits++; - } while (bit == 0); - - if (num_bits > 31) { - return MPP_NOK; - } - // Calculate exp-Golomb code value of size num_bits. - *val = (1 << num_bits) - 1; - - if (num_bits > 0) { - if (read_bits(pStrmData, num_bits, &rest)) { - return MPP_NOK; - } - *val += rest; - } - - return MPP_OK; -} - -static void set_streamdata(GetBitCtx_t *pStrmData, RK_U8 *data, RK_S32 size) -{ - memset(pStrmData, 0, sizeof(GetBitCtx_t)); - pStrmData->data_ = data; - pStrmData->bytes_left_ = size; - pStrmData->num_remaining_bits_in_curr_byte_ = 0; - // Initially set to 0xffff to accept all initial two-byte sequences. - pStrmData->prev_two_bytes_ = 0xffff; - pStrmData->emulation_prevention_bytes_ = 0; - // add - pStrmData->buf = data; - pStrmData->buf_len = size; - pStrmData->used_bits = 0; -} - - -static void write_nalu_prefix(InputParams *p_in) -{ - if (p_in->IO.pfxbytes > START_PREFIX_3BYTE) { - p_in->strm.pbuf[p_in->strm.strmbytes++] = 0x00; - } - p_in->strm.pbuf[p_in->strm.strmbytes++] = 0x00; - p_in->strm.pbuf[p_in->strm.strmbytes++] = 0x00; - p_in->strm.pbuf[p_in->strm.strmbytes++] = 0x01; -} - -static RK_U8 read_one_byte(InputParams *p_in) -{ - RK_U8 data = 0; - - if (0 == fread(&data, 1, 1, p_in->fp_bitstream)) { - p_in->is_eof = 1; - } - - return data; -} - -static void find_next_nalu(InputParams *p_in) -{ - RK_U8 startcode_had_find = 0; - //-- first read three bytes - if (p_in->is_fist_nalu) { - p_in->IO.pbuf[p_in->IO.offset] = read_one_byte(p_in); - p_in->IO.pbuf[p_in->IO.offset + 1] = read_one_byte(p_in); - p_in->IO.pbuf[p_in->IO.offset + 2] = read_one_byte(p_in); - p_in->is_fist_nalu = 0; - } - do { - if (startcode_had_find) { - p_in->IO.nalubytes++; - } - //--- find 0x000001 - if ((p_in->IO.pbuf[p_in->IO.offset] == 0x00) - && (p_in->IO.pbuf[p_in->IO.offset + 1] == 0x00) - && (p_in->IO.pbuf[p_in->IO.offset + 2] == 0x01)) { - if (startcode_had_find) { //-- end_code - p_in->IO.nalubytes -= START_PREFIX_3BYTE; - if (p_in->IO.pbuf[p_in->IO.offset - 1] == 0x00) { - p_in->IO.pbuf[0] = 0x00; - p_in->IO.nalubytes--; - } else { - p_in->IO.pbuf[0] = 0xFF; - } - p_in->IO.pbuf[1] = 0x00; - p_in->IO.pbuf[2] = 0x00; - p_in->IO.pbuf[3] = 0x01; - p_in->IO.offset = 1; - break; - } else { //-- find strart_code - startcode_had_find = 1; - p_in->IO.nalubytes = 0; - p_in->IO.pfxbytes = START_PREFIX_3BYTE; - p_in->IO.pNALU = &p_in->IO.pbuf[p_in->IO.offset + START_PREFIX_3BYTE]; - if (p_in->IO.offset && (p_in->IO.pbuf[p_in->IO.offset - 1] == 0x00)) { - p_in->IO.pfxbytes++; - } - } - } - p_in->IO.offset++; - p_in->IO.pbuf[p_in->IO.offset + 2] = read_one_byte(p_in); - } while (!p_in->is_eof); -} - -static MPP_RET read_next_nalu(InputParams *p_in) -{ - RK_S32 forbidden_bit = -1; - RK_S32 nal_reference_idc = -1; - RK_S32 nal_unit_type = -1; - RK_S32 nalu_header_bytes = -1; - RK_U32 start_mb_nr = -1; - - GetBitCtx_t *pStrmData = (GetBitCtx_t *)p_in->bitctx; - memset(pStrmData, 0, sizeof(GetBitCtx_t)); - set_streamdata(pStrmData, p_in->IO.pNALU, 4); - read_bits( pStrmData, 1, &forbidden_bit); - ASSERT(forbidden_bit == 0); - read_bits( pStrmData, 2, &nal_reference_idc); - read_bits( pStrmData, 5, &nal_unit_type); - - nalu_header_bytes = 1; - if ((nal_unit_type == NALU_TYPE_PREFIX) || (nal_unit_type == NALU_TYPE_SLC_EXT)) { - nalu_header_bytes += 3; - } - //-- parse slice - if ( nal_unit_type == NALU_TYPE_SLICE || nal_unit_type == NALU_TYPE_IDR) { - set_streamdata(pStrmData, (p_in->IO.pNALU + nalu_header_bytes), 4); // reset - read_ue(pStrmData, &start_mb_nr); - - if (!p_in->is_fist_frame && (start_mb_nr == 0)) { - p_in->is_new_frame = 1; - } - p_in->is_fist_frame = 0; - } - if (!p_in->is_new_frame) { - write_nalu_prefix(p_in); - memcpy(&p_in->strm.pbuf[p_in->strm.strmbytes], p_in->IO.pNALU, p_in->IO.nalubytes); - p_in->strm.strmbytes += p_in->IO.nalubytes; - } - - return MPP_OK; -} - -static void reset_tmpdata_ctx(TempDataCtx_t *tmp) -{ - tmp->header = 0; - tmp->len = 0; - tmp->pps_id = 0; -} - - -static void read_golden_data(FILE *fp, TempDataCtx_t *tmpctx, RK_U32 frame_no) -{ - RK_U32 header = 0, datasize = 0; - - reset_tmpdata_ctx(tmpctx); - fread(&header, 1, sizeof(RK_U32), fp); - fread(&datasize, 1, sizeof(RK_U32), fp); - while (!feof(fp)) { - switch (header) { - case RKVDEC_PPS_HEADER: - tmpctx->pps_id = datasize >> 16; - datasize = datasize & 0xffff; - case RKVDEC_SCL_HEADER: - case RKVDEC_RPS_HEADER: - case RKVDEC_STM_HEADER: - fseek(fp, datasize, SEEK_CUR); - break; - case RKVDEC_REG_HEADER: - fseek(fp, datasize, SEEK_CUR); - goto __RETURN; - break; - case RKVDEC_CRC_HEADER: - fread(tmpctx->data, sizeof(RK_U8), datasize, fp); - tmpctx->len = datasize; - break; - case RKVDEC_ERR_HEADER: - break; - default: - mpp_log("ERROR: frame_no=%d. \n", frame_no); - ASSERT(0); - break; - } - fread(&header, 1, sizeof(RK_U32), fp); - fread(&datasize, 1, sizeof(RK_U32), fp); - } -__RETURN: - return; -} - -static void write_bytes(FILE *fp_in, TempDataCtx_t *tmpctx, FILE *fp_out) -{ - RK_U32 i = 0; - RK_U8 temp = 0; - RK_U32 data_temp = 0; - data_temp = (tmpctx->pps_id << 16) | tmpctx->len; - - fwrite(&tmpctx->header, sizeof(RK_U32), 1, fp_out); - fwrite(&data_temp, sizeof(RK_U32), 1, fp_out); - while (i < tmpctx->len) { - fread (&temp, sizeof(RK_U8), 1, fp_in); - fwrite(&temp, sizeof(RK_U8), 1, fp_out); - i++; - } -} - - -static void write_driver_bytes(FILE *fp_out, TempDataCtx_t *in_tmpctx, FILE *fp_in, RK_U32 frame_no) -{ - RK_U32 header = 0, datasize = 0; - TempDataCtx_t m_tmpctx = { 0 }; - - fread(&header, 1, sizeof(RK_U32), fp_in); - fread(&datasize, 1, sizeof(RK_U32), fp_in); - - while (!feof(fp_in)) { - memset(&m_tmpctx, 0, sizeof(TempDataCtx_t)); - switch (header) { - case RKVDEC_PPS_HEADER: - m_tmpctx.pps_id = in_tmpctx->pps_id; - case RKVDEC_SCL_HEADER: - case RKVDEC_RPS_HEADER: - case RKVDEC_STM_HEADER: - m_tmpctx.header = header; - m_tmpctx.len = datasize; - write_bytes(fp_in, &m_tmpctx, fp_out); - break; - case RKVDEC_REG_HEADER: - m_tmpctx.header = header; - m_tmpctx.len = datasize; - header = RKVDEC_CRC_HEADER; - fwrite(&header, sizeof(RK_U32), 1, fp_out); - fwrite(&in_tmpctx->len, sizeof(RK_U32), 1, fp_out); - fwrite(in_tmpctx->data, sizeof(RK_U8), in_tmpctx->len, fp_out); - write_bytes(fp_in, &m_tmpctx, fp_out); - return; - default: - mpp_log("ERROR: frame_no=%d. \n", frame_no); - ASSERT(0); - break; - } - fread(&header, 1, sizeof(RK_U32), fp_in); - fread(&datasize, 1, sizeof(RK_U32), fp_in); - } -} - - -/*! -*********************************************************************** -* \brief -* configure function to analyze command or configure file -*********************************************************************** -*/ -MPP_RET h264d_configure(InputParams *p_in, RK_S32 ac, char *av[]) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - VAL_CHECK(ret, ac > 1); - display_input_cmd(ac, av); - FUN_CHECK (ret = parse_command(p_in, ac, av)); - - return MPP_OK; -__FAILED: - return ret; -} - - -/*! -*********************************************************************** -* \brief -* close file -*********************************************************************** -*/ -MPP_RET h264d_close_files(InputParams *p_in) -{ - FCLOSE(p_in->fp_bitstream); - FCLOSE(p_in->fp_golden_data); - FCLOSE(p_in->fp_driver_data); - - return MPP_OK; -} - -/*! -*********************************************************************** -* \brief -* open file -*********************************************************************** -*/ -MPP_RET h264d_open_files(InputParams *p_in) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - FLE_CHECK(ret, p_in->fp_bitstream = fopen(p_in->infile_name, "rb")); - - return MPP_OK; -__FAILED: - h264d_close_files(p_in); - - return ret; -} - -/*! -*********************************************************************** -* \brief -* free frame buffer -*********************************************************************** -*/ - -MPP_RET h264d_free_frame_buffer(InputParams *p_in) -{ - if (p_in) { - mpp_free(p_in->IO.pbuf); - mpp_free(p_in->bitctx); - mpp_free(p_in->strm.pbuf); - } - - return MPP_NOK; -} -/*! -*********************************************************************** -* \brief -* alloc frame buffer -*********************************************************************** -*/ -MPP_RET h264d_alloc_frame_buffer(InputParams *p_in) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - p_in->IO.pbuf = mpp_malloc_size(RK_U8, IOBUFSIZE); - p_in->strm.pbuf = mpp_malloc_size(RK_U8, STMBUFSIZE); - p_in->bitctx = mpp_malloc_size(void, sizeof(GetBitCtx_t)); - MEM_CHECK(ret, p_in->IO.pbuf && p_in->strm.pbuf && p_in->bitctx); - p_in->is_fist_nalu = 1; - p_in->is_fist_frame = 1; - - return MPP_OK; -__FAILED: - return ret; -} - - -/*! -*********************************************************************** -* \brief -* read one frame -*********************************************************************** -*/ -MPP_RET h264d_read_one_frame(InputParams *p_in, MppPacket pkt) -{ - p_in->strm.strmbytes = 0; - p_in->is_new_frame = 0; - //-- copy first nalu - if (!p_in->is_fist_frame) { - write_nalu_prefix(p_in); - memcpy(&p_in->strm.pbuf[p_in->strm.strmbytes], p_in->IO.pNALU, p_in->IO.nalubytes); - p_in->strm.strmbytes += p_in->IO.nalubytes; - } - //-- read one nalu and copy to stream buffer - do { - find_next_nalu(p_in); - read_next_nalu(p_in); - } while (!p_in->is_new_frame && !p_in->is_eof); - //-- set code input context - ((MppPacketImpl *)pkt)->pos = p_in->strm.pbuf; - ((MppPacketImpl *)pkt)->size = p_in->strm.strmbytes; - if (p_in->is_eof) { - mpp_packet_set_eos(pkt); - } - - return MPP_OK; -} -/*! -*********************************************************************** -* \brief -* write fpage data to file -*********************************************************************** -*/ -MPP_RET h264d_write_fpga_data(InputParams *p_in) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - TempDataCtx_t tmpctx = { 0 }; - FILE *fp_log = NULL; - RK_U32 frame_no = 0; - RK_U32 ctrl_value = 0; - RK_U32 ctrl_debug = 0; - RK_U32 ctrl_fpga = 0; - RK_U32 ctrl_write = 0; - char *outpath_dir = NULL; - char *cmppath_dir = NULL; - - mpp_env_get_u32(logenv_name.ctrl, &ctrl_value, 0); - ctrl_debug = GetBitVal(ctrl_value, LOG_DEBUG); - ctrl_fpga = GetBitVal(ctrl_value, LOG_FPGA); - ctrl_write = GetBitVal(ctrl_value, LOG_WRITE); - INP_CHECK(ret, ctx, !(ctrl_debug && ctrl_fpga && ctrl_write)); - mpp_env_get_str(logenv_name.outpath, &outpath_dir, NULL); - mpp_env_get_str(logenv_name.cmppath, &cmppath_dir, NULL); - p_in->fp_driver_data = open_file(outpath_dir, p_in->infile_name, ".dat", "wb"); - p_in->fp_golden_data = open_file(cmppath_dir, p_in->infile_name, ".dat", "rb"); - fp_log = fopen(strcat(outpath_dir, "/h264d_driver_data.dat"), "rb"); - FLE_CHECK(ret, p_in->fp_golden_data); - FLE_CHECK(ret, p_in->fp_driver_data); - FLE_CHECK(ret, fp_log); - tmpctx.data = mpp_calloc_size(RK_U8, 128); - MEM_CHECK(ret, tmpctx.data); //!< for read golden fpga data - while (!feof(p_in->fp_golden_data) && !feof(fp_log)) { - read_golden_data (p_in->fp_golden_data, &tmpctx, frame_no); - write_driver_bytes(p_in->fp_driver_data, &tmpctx, fp_log, frame_no); - frame_no++; - } - //remove(out_name); -__RETURN: - ret = MPP_OK; -__FAILED: - mpp_free(tmpctx.data); - h264d_close_files(p_in); - - return ret; -} diff --git a/mpp/test/h264d_rwfile.h b/mpp/test/h264d_rwfile.h deleted file mode 100644 index ede16df77..000000000 --- a/mpp/test/h264d_rwfile.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -* -* Copyright 2015 Rockchip Electronics Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include "rk_type.h" -#include "mpp_err.h" -#include "mpp_packet.h" - -#ifndef __H264D_RWFILE_H__ -#define __H264D_RWFILE_H__ - - -#define FILE_NAME_SIZE 256 - - -// input parameters from configuration file -typedef struct inp_par_t { - RK_U32 iDecFrmNum; //!< set the max decode frame numbers - char infile_name[FILE_NAME_SIZE]; //!< H.264 input bitstrream - char cmp_path_dir[FILE_NAME_SIZE]; //!< golen - char cfgfile_name[FILE_NAME_SIZE]; //!< input configure file - char out_path_dir[FILE_NAME_SIZE]; //!< output - //--- input file - FILE *fp_bitstream; - FILE *fp_golden_data; - FILE *fp_driver_data; - //--- use in read bit stream - RK_U32 raw_cfg; - RK_U32 iFrmdecoded; - RK_U8 is_fist_nalu; - RK_U8 is_fist_frame; - RK_U8 is_eof; - RK_U8 is_new_frame; - struct { - RK_U8 *pbuf; - RK_U32 offset; - - RK_U8 *pNALU; - RK_U32 nalubytes; - RK_U8 pfxbytes; // start code prefix bytes - } IO; - struct { - RK_U8 *pbuf; - RK_U32 strmbytes; - } strm; - void *bitctx; -} InputParams; - - - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET h264d_configure (InputParams *in, RK_S32 ac, char *av[]); -MPP_RET h264d_open_files (InputParams *in); -MPP_RET h264d_close_files(InputParams *in); -MPP_RET h264d_alloc_frame_buffer(InputParams *in); -MPP_RET h264d_read_one_frame (InputParams *in, MppPacket pkt); -MPP_RET h264d_free_frame_buffer (InputParams *in); -MPP_RET h264d_write_fpga_data (InputParams *in); - -#ifdef __cplusplus -} -#endif - -#endif /* __H264D_RWFILE_H__ */ \ No newline at end of file diff --git a/mpp/test/h264d_test.c b/mpp/test/h264d_test.c deleted file mode 100644 index b01297b7a..000000000 --- a/mpp/test/h264d_test.c +++ /dev/null @@ -1,159 +0,0 @@ -/* -* Copyright 2010 Rockchip Electronics S.LSI Co. LTD -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#define MODULE_TAG "h264d_test" - -#if defined(_WIN32) -#include "vld.h" -#endif -#include -#include "mpp_log.h" -#include "mpp_env.h" -#include "mpp_dec.h" -#include "mpp_hal.h" -#include "mpp_mem.h" -#include "mpp_packet.h" -#include "mpp_packet_impl.h" -#include "mpp_hal.h" - -#include "h264d_log.h" -#include "h264d_rwfile.h" -#include "h264d_api.h" -#include "hal_h264d_api.h" - - -#define MODULE_TAG "h264d_test" - - -static MPP_RET manual_set_env(void) -{ -#if defined(_MSC_VER) - mpp_env_set_u32("h264d_log_help", 1 ); - mpp_env_set_u32("h264d_log_show", 1 ); - mpp_env_set_u32("h264d_log_ctrl", 0x007B ); - mpp_env_set_u32("h264d_log_level", 5 ); - mpp_env_set_u32("h264d_log_decframe", 0 ); - mpp_env_set_u32("h264d_log_begframe", 0 ); - mpp_env_set_u32("h264d_log_endframe", 0 ); - mpp_env_set_str("h264d_log_outpath", "F:/h264_log" ); - mpp_env_set_str("h264d_log_cmppath", "F:/h264_log" ); -#endif - return MPP_OK; -} - -static MPP_RET decoder_deinit(MppDec *pApi) -{ - - if (pApi->slots) { - mpp_buf_slot_deinit(pApi->slots); - pApi->slots = NULL; - } - if (pApi->parser) { - parser_deinit(pApi->parser); - pApi->parser = NULL; - } - if (pApi->hal) { - mpp_hal_deinit(pApi->hal); - pApi->hal = NULL; - } - - return MPP_OK; -} - -static MPP_RET decoder_init(MppDec *pApi) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - ParserCfg parser_cfg; - MppHalCfg hal_cfg; - MppCodingType coding = MPP_VIDEO_CodingAVC; - - // malloc slot - FUN_CHECK(ret = mpp_buf_slot_init(&pApi->slots)); - MEM_CHECK(ret, pApi->slots); - - // init parser part - memset(&parser_cfg, 0, sizeof(parser_cfg)); - parser_cfg.coding = coding; - parser_cfg.slots = pApi->slots; - FUN_CHECK(ret = parser_init(&pApi->parser, &parser_cfg)); - - // init hal part - memset(&hal_cfg, 0, sizeof(hal_cfg)); - hal_cfg.type = MPP_CTX_DEC; - hal_cfg.coding = coding; - hal_cfg.task_count = parser_cfg.task_count; - FUN_CHECK(ret = mpp_hal_init(&pApi->hal, &hal_cfg)); - pApi->tasks = hal_cfg.tasks; - - return MPP_OK; -__FAILED: - decoder_deinit(pApi); - - return ret; -} - - - -int main(int argc, char **argv) -{ - MPP_RET ret = MPP_ERR_UNKNOW; - - InputParams *pIn = mpp_calloc(InputParams, 1); - MppDec *pApi = mpp_calloc(MppDec, 1); - MppPacketImpl *pkt = mpp_calloc_size(MppPacketImpl, sizeof(MppPacketImpl)); - HalTask *task = mpp_calloc_size(HalTask, sizeof(HalTask)); - MEM_CHECK(ret, pIn && pApi && pkt && task); - mpp_log("== test start == \n"); - // set debug mode - FUN_CHECK(ret = manual_set_env()); - // input paramters configure - FUN_CHECK(ret = h264d_configure(pIn, argc, argv)); - // open files - FUN_CHECK(ret = h264d_open_files(pIn)); - FUN_CHECK(ret = h264d_alloc_frame_buffer(pIn)); - // init - FUN_CHECK(ret = decoder_init(pApi)); - do { - if (!pkt->size) { - FUN_CHECK(ret = h264d_read_one_frame(pIn, (MppPacket)pkt)); - } - FUN_CHECK(ret = parser_parse(pApi->parser, pkt, &task->dec)); - if (((HalDecTask*)&task->dec)->valid) { - FUN_CHECK(ret = mpp_hal_reg_gen(pApi->hal, task)); - //mpp_log("---- decoder, Frame_no = %d \n", pIn->iFrmdecoded); - //!< end of stream - if (!pkt->size && (pkt->flag & MPP_PACKET_FLAG_EOS)) { - break; - } - pIn->iFrmdecoded++; - } - } while (!pIn->iDecFrmNum || (pIn->iFrmdecoded < pIn->iDecFrmNum)); - - mpp_log("+++++++ all test return +++++++ \n"); - ret = MPP_OK; -__FAILED: - decoder_deinit(pApi); - h264d_free_frame_buffer(pIn); - h264d_write_fpga_data(pIn); //!< for fpga debug - h264d_close_files(pIn); - mpp_free(pIn); - mpp_free(pApi); - mpp_free(pkt); - mpp_free(task); - - return ret; -} - diff --git a/mpp/vproc.cmake b/mpp/vproc.cmake new file mode 100644 index 000000000..7c3552f65 --- /dev/null +++ b/mpp/vproc.cmake @@ -0,0 +1,20 @@ +option(ENABLE_VPROC "Enable video process" ON) +if( ENABLE_VPROC ) + set(HAVE_VPROC true) + add_definitions(-DHAVE_VPROC) + + set(HAVE_VPROC_IEP true) + set(VPROC_IEP vproc_iep) + add_definitions(-DHAVE_VPROC_IEP) + + set(HAVE_VPROC_IEP2 true) + set(VPROC_IEP2 vproc_iep2) + add_definitions(-DHAVE_VPROC_IEP2) +endif() + +option(ENABLE_VPROC_VDPP "Enable video display post processor" OFF) +if( ENABLE_VPROC_VDPP ) + set(HAVE_VPROC_VDPP true) + set(VPROC_VDPP vproc_vdpp) + add_definitions(-DHAVE_VPROC_VDPP) +endif() diff --git a/mpp/vproc/CMakeLists.txt b/mpp/vproc/CMakeLists.txt new file mode 100644 index 000000000..e6a10ad5c --- /dev/null +++ b/mpp/vproc/CMakeLists.txt @@ -0,0 +1,27 @@ +# vim: syntax=cmake + +if( HAVE_VPROC_IEP ) + add_subdirectory(iep) +endif() + +if( HAVE_VPROC_IEP2 ) + add_subdirectory(iep2) +endif() + +if( HAVE_VPROC_VDPP ) + add_subdirectory(vdpp) +endif() + +# ---------------------------------------------------------------------------- +# add mpp video process implement +# ---------------------------------------------------------------------------- +add_library(mpp_vproc STATIC + mpp_dec_vproc.c + mpp_vproc_dev.c + ) + +target_link_libraries(mpp_vproc + ${VPROC_IEP} + ${VPROC_IEP2} + ${VPROC_VDPP} + ) diff --git a/mpp/hal/worker/libvpu/CMakeLists.txt b/mpp/vproc/iep/CMakeLists.txt similarity index 58% rename from mpp/hal/worker/libvpu/CMakeLists.txt rename to mpp/vproc/iep/CMakeLists.txt index fe6bcd09f..6c076e675 100644 --- a/mpp/hal/worker/libvpu/CMakeLists.txt +++ b/mpp/vproc/iep/CMakeLists.txt @@ -1,9 +1,10 @@ # vim: syntax=cmake + # ---------------------------------------------------------------------------- -# add libvpu implement +# add vidoe process IEP (Image Enhancement Processor) implement # ---------------------------------------------------------------------------- -if(ANDROID) -add_library(vpu STATIC - vpu.c +add_library(vproc_iep OBJECT + iep.c ) -endif(ANDROID) \ No newline at end of file + +add_subdirectory(test) diff --git a/mpp/vproc/iep/iep.c b/mpp/vproc/iep/iep.c new file mode 100644 index 000000000..970cc2e08 --- /dev/null +++ b/mpp/vproc/iep/iep.c @@ -0,0 +1,630 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2018 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "iep" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "iep_api.h" +#include "iep.h" + +#define X (-1) + +static RK_S32 enh_alpha_table[][25] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + /*0*/ {X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X }, + /*1*/ {0, 8, 12, 16, 20, 24, 28, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X }, + /*2*/ {0, 4, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, X, X, X, X, X, X, X, X, X, X, X, X }, + /*3*/ {0, X, X, 8, X, X, 12, X, X, 16, X, X, 20, X, X, 24, X, X, 28, X, X, X, X, X, X }, + /*4*/ {0, 2, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }, + /*5*/ {0, X, X, X, X, 8, X, X, X, X, 12, X, X, X, X, 16, X, X, X, X, 20, X, X, X, X }, + /*6*/ {0, X, X, 4, X, X, 8, X, X, 10, X, X, 12, X, X, 14, X, X, 16, X, X, 18, X, X, 20 }, + /*7*/ {0, X, X, X, X, X, X, 8, X, X, X, X, X, X, 12, X, X, X, X, X, X, 16, X, X, X }, + /*8*/ {0, 1, 2, 3, 4, 5, 6, 7, 8, X, 9, X, 10, X, 11, X, 12, X, 13, X, 14, X, 15, X, 16 } +}; + +static const char *iep_name = "/dev/iep"; + +typedef struct IepCtxImpl_t { + IepMsg msg; + RK_S32 fd; + RK_S32 pid; + IepHwCap cap; +} IepCtxImpl; + +MPP_RET iep_init(IepCtx *ctx) +{ + if (NULL == ctx) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + RK_S32 fd = -1; + IepCtxImpl *impl = NULL; + + mpp_env_get_u32("iep_debug", &iep_debug, 0); + *ctx = NULL; + + do { + impl = mpp_calloc(IepCtxImpl, 1); + if (NULL == impl) { + mpp_err_f("failed to alloc context\n"); + break; + } + + fd = open(iep_name, O_RDWR | O_CLOEXEC); + if (fd < 0) { + mpp_err("can NOT find iep device %s\n", iep_name); + break; + } + + if (0 > ioctl(fd, IEP_QUERY_CAP, &impl->cap)) { + iep_dbg_func("Query IEP capability failed, using default cap\n"); + IepHwCap *cap = &impl->cap; + + cap->scaling_supported = 0; + cap->i4_deinterlace_supported = 1; + cap->i2_deinterlace_supported = 1; + cap->compression_noise_reduction_supported = 1; + cap->sampling_noise_reduction_supported = 1; + cap->hsb_enhancement_supported = 1; + cap->cg_enhancement_supported = 1; + cap->direct_path_supported = 1; + cap->max_dynamic_width = 1920; + cap->max_dynamic_height = 1088; + cap->max_static_width = 8192; + cap->max_static_height = 8192; + cap->max_enhance_radius = 3; + } + + impl->fd = fd; + impl->pid = getpid(); + + *ctx = impl; + return MPP_OK; + } while (0); + + if (fd > 0) + close(fd); + + MPP_FREE(impl); + + return MPP_NOK; +} + +MPP_RET iep_deinit(IepCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + IepCtxImpl *impl = (IepCtxImpl *)ctx; + + if (impl->fd > 0) { + close(impl->fd); + impl->fd = -1; + } + + return MPP_OK; +} + +static void dump_iep_img(IepImg *img) +{ + mpp_log("image %p\n", img); + mpp_log("act_w %d\n", img->act_w); + mpp_log("act_h %d\n", img->act_h); + mpp_log("x_off %d\n", img->x_off); + mpp_log("y_off %d\n", img->y_off); + mpp_log("vir_w %d\n", img->vir_w); + mpp_log("vir_h %d\n", img->vir_h); + mpp_log("format %d\n", img->format); + mpp_log("mem_addr %08x\n", img->mem_addr); + mpp_log("uv_addr %08x\n", img->uv_addr); + mpp_log("v_addr %08x\n", img->v_addr); +} + +static RK_U32 check_yuv_enhance_param(IepCmdParamYuvEnhance *yuv_enh) +{ + RK_U32 ret = 0; + if (yuv_enh->saturation < 0 || yuv_enh->saturation > 1.992) { + mpp_err("Invalidate parameter, yuv_enh_saturation!\n"); + ret |= 0x0001; + } + + if (yuv_enh->contrast < 0 || yuv_enh->contrast > 1.992) { + mpp_err("Invalidate parameter, yuv_enh_contrast!\n"); + ret |= 0x0002; + } + + if (yuv_enh->brightness < -32 || yuv_enh->brightness > 31) { + mpp_err("Invalidate parameter, yuv_enh_brightness!\n"); + ret |= 0x0004; + } + + if (yuv_enh->hue_angle < -30 || yuv_enh->hue_angle > 30) { + mpp_err("Invalidate parameter, yuv_enh_hue_angle!\n"); + ret |= 0x0008; + } + + if (yuv_enh->video_mode < 0 || yuv_enh->video_mode > 3) { + mpp_err("Invalidate parameter, video_mode!\n"); + ret |= 0x0010; + } + + if (yuv_enh->color_bar_y > 127 || yuv_enh->color_bar_u > 127 || + yuv_enh->color_bar_v > 127) { + mpp_err("Invalidate parameter, color_bar_*!\n"); + ret |= 0x0020; + } + return ret; +} + +static RK_U32 check_rgb_enhance_param(IepCmdParamRgbEnhance *rgb_enh) +{ + RK_U32 ret = 0; + if (rgb_enh->alpha_base > 8 || rgb_enh->alpha_base < 0 || + rgb_enh->alpha_num < 0 || rgb_enh->alpha_num > 24) { + mpp_err("Invalidate parameter, enh_alpha_base or enh_alpha_num!\n"); + ret |= 0x0001; + } + + if (enh_alpha_table[rgb_enh->alpha_base][rgb_enh->alpha_num] == -1) { + mpp_err("Invalidate parameter, enh_alpha_base or enh_alpha_num!\n"); + ret |= 0x0002; + } + + if (rgb_enh->threshold > 255 || rgb_enh->threshold < 0) { + mpp_err("Invalidate parameter, enh_threshold!\n"); + ret |= 0x0004; + } + + if (rgb_enh->radius > 4 || rgb_enh->radius < 1) { + mpp_err("Invalidate parameter, enh_radius!\n"); + ret |= 0x0008; + } + + if (rgb_enh->order < IEP_RGB_ENHANCE_ORDER_CG_DDE || + rgb_enh->order > IEP_RGB_ENHANCE_ORDER_DDE_CG) { + mpp_err("Invalidate parameter, rgb_contrast_enhance_mode!\n"); + ret |= 0x0010; + } + + if (rgb_enh->mode < IEP_RGB_ENHANCE_MODE_NO_OPERATION || + rgb_enh->mode > IEP_RGB_ENHANCE_MODE_EDGE_ENHANCE) { + mpp_err("Invalidate parameter, rgb_enhance_mode!\n"); + ret |= 0x0020; + } + + if (rgb_enh->coe > 3.96875 || rgb_enh->coe < 0) { + mpp_err("Invalidate parameter, rgb_enh_coe!\n"); + ret |= 0x0040; + } + + return ret; +} + +static RK_U32 check_msg_image(IepMsg *msg) +{ + RK_U32 ret = 0; + IepMsgImg *src = &msg->src; + IepMsgImg *dst = &msg->dst; + + if (!((src->format < IEP_FORMAT_RGB_BUTT) || + (src->format >= IEP_FORMAT_YUV_BASE && src->format < IEP_FORMAT_YUV_BUTT))) { + mpp_err("Invalidate parameter, i/o format!\n"); + ret |= 0x0001; + } + + if (src->act_w > 4096 || src->act_h > 8192) { + mpp_err("Invalidate parameter, source image size!\n"); + ret |= 0x0002; + } + + if (dst->act_w > 4096 || dst->act_h > 4096) { + mpp_err("Invalidate parameter, destination image size!\n"); + ret |= 0x0004; + } + + RK_S32 scl_fct_h = src->act_w > dst->act_w ? (src->act_w * 1000 / dst->act_w) : (dst->act_w * 1000 / src->act_w); + RK_S32 scl_fct_v = src->act_h > dst->act_h ? (src->act_h * 1000 / dst->act_h) : (dst->act_h * 1000 / src->act_h); + + if (scl_fct_h > 16000 || scl_fct_v > 16000) { + mpp_err("Invalidate parameter, scale factor!\n"); + ret |= 0x0008; + } + return ret; +} + +// rr = 1.7 rg = 1 rb = 0.6 +static RK_U32 cg_tab[] = { + 0x01010100, 0x03020202, 0x04030303, 0x05040404, + 0x05050505, 0x06060606, 0x07070606, 0x07070707, + 0x08080807, 0x09080808, 0x09090909, 0x0a090909, + 0x0a0a0a0a, 0x0b0a0a0a, 0x0b0b0b0b, 0x0c0b0b0b, + 0x0c0c0c0c, 0x0c0c0c0c, 0x0d0d0d0d, 0x0d0d0d0d, + 0x0e0e0d0d, 0x0e0e0e0e, 0x0e0e0e0e, 0x0f0f0f0f, + 0x0f0f0f0f, 0x10100f0f, 0x10101010, 0x10101010, + 0x11111110, 0x11111111, 0x11111111, 0x12121212, + 0x12121212, 0x12121212, 0x13131313, 0x13131313, + 0x13131313, 0x14141414, 0x14141414, 0x14141414, + 0x15151515, 0x15151515, 0x15151515, 0x16161615, + 0x16161616, 0x16161616, 0x17161616, 0x17171717, + 0x17171717, 0x17171717, 0x18181818, 0x18181818, + 0x18181818, 0x19191818, 0x19191919, 0x19191919, + 0x19191919, 0x1a1a1a19, 0x1a1a1a1a, 0x1a1a1a1a, + 0x1a1a1a1a, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x23222120, 0x27262524, 0x2b2a2928, 0x2f2e2d2c, + 0x33323130, 0x37363534, 0x3b3a3938, 0x3f3e3d3c, + 0x43424140, 0x47464544, 0x4b4a4948, 0x4f4e4d4c, + 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, + 0x63626160, 0x67666564, 0x6b6a6968, 0x6f6e6d6c, + 0x73727170, 0x77767574, 0x7b7a7978, 0x7f7e7d7c, + 0x83828180, 0x87868584, 0x8b8a8988, 0x8f8e8d8c, + 0x93929190, 0x97969594, 0x9b9a9998, 0x9f9e9d9c, + 0xa3a2a1a0, 0xa7a6a5a4, 0xabaaa9a8, 0xafaeadac, + 0xb3b2b1b0, 0xb7b6b5b4, 0xbbbab9b8, 0xbfbebdbc, + 0xc3c2c1c0, 0xc7c6c5c4, 0xcbcac9c8, 0xcfcecdcc, + 0xd3d2d1d0, 0xd7d6d5d4, 0xdbdad9d8, 0xdfdedddc, + 0xe3e2e1e0, 0xe7e6e5e4, 0xebeae9e8, 0xefeeedec, + 0xf3f2f1f0, 0xf7f6f5f4, 0xfbfaf9f8, 0xfffefdfc, + 0x06030100, 0x1b150f0a, 0x3a322922, 0x63584e44, + 0x95887b6f, 0xcebfb0a2, 0xfffeedde, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff +}; + +static void setup_cg_tab(double cg_rate, RK_U32 *base) +{ + RK_S32 i; + + for (i = 0; i < 64; i++) { + RK_U32 rgb_0 = 4 * i; + RK_U32 rgb_1 = 4 * i + 1; + RK_U32 rgb_2 = 4 * i + 2; + RK_U32 rgb_3 = 4 * i + 3; + + /// need modify later + RK_U32 cg_0 = pow(rgb_0, cg_rate); + RK_U32 cg_1 = pow(rgb_1, cg_rate); + RK_U32 cg_2 = pow(rgb_2, cg_rate); + RK_U32 cg_3 = pow(rgb_3, cg_rate); + + if (cg_0 > 255) cg_0 = 255; + if (cg_1 > 255) cg_1 = 255; + if (cg_2 > 255) cg_2 = 255; + if (cg_3 > 255) cg_3 = 255; + + RK_U32 tab_0 = (RK_U32)cg_0; + RK_U32 tab_1 = (RK_U32)cg_1; + RK_U32 tab_2 = (RK_U32)cg_2; + RK_U32 tab_3 = (RK_U32)cg_3; + + RK_U32 conf_value = (tab_3 << 24) + (tab_2 << 16) + (tab_1 << 8) + tab_0; + base[i] = conf_value; + } +} + +MPP_RET iep_control(IepCtx ctx, IepCmd cmd, void *param) +{ + if (NULL == ctx) { + mpp_err_f("invalid NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_RET ret = MPP_OK; + IepCtxImpl *impl = (IepCtxImpl *)ctx; + IepMsg *msg = &impl->msg; + + switch (cmd) { + case IEP_CMD_INIT : { + memset(msg, 0, sizeof(*msg)); + } break; + case IEP_CMD_SET_SRC : { + IepMsgImg *src = &msg->src; + + mpp_assert(param); + // NOTE: only update which is used + memcpy(&msg->src, param, sizeof(IepImg)); + + if ((src->format == IEP_FORMAT_YCbCr_420_P + || src->format == IEP_FORMAT_YCbCr_420_SP + || src->format == IEP_FORMAT_YCbCr_422_P + || src->format == IEP_FORMAT_YCbCr_422_SP + || src->format == IEP_FORMAT_YCrCb_420_P + || src->format == IEP_FORMAT_YCrCb_420_SP + || src->format == IEP_FORMAT_YCrCb_422_P + || src->format == IEP_FORMAT_YCrCb_422_SP) && + msg->dein_mode == IEP_DEI_MODE_DISABLE) { + msg->dein_mode = IEP_DEI_MODE_BYPASS; + } + if (iep_debug & IEP_DBG_IMAGE) { + mpp_log("setup src\n"); + dump_iep_img((IepImg *)param); + } + } break; + case IEP_CMD_SET_DST : { + mpp_assert(param); + // NOTE: only update which is used + memcpy(&msg->dst, param, sizeof(IepImg)); + + if (iep_debug & IEP_DBG_IMAGE) { + mpp_log("setup dst\n"); + dump_iep_img((IepImg *)param); + } + } break; + case IEP_CMD_SET_DEI_CFG : { + IepCmdParamDeiCfg *dei_cfg = (IepCmdParamDeiCfg *)param; + + if (NULL == param) { + msg->dein_high_fre_en = 0; + msg->dein_mode = IEP_DEI_MODE_I2O1; + msg->field_order = IEP_DEI_FLD_ORDER_BOT_FIRST; + msg->dein_ei_mode = 0; + msg->dein_ei_sel = 0; + msg->dein_ei_radius = 0; + msg->dein_ei_smooth = 0; + msg->dein_high_fre_fct = 0; + } else { + msg->dein_high_fre_en = dei_cfg->dei_high_freq_en; + msg->dein_mode = dei_cfg->dei_mode; + msg->field_order = dei_cfg->dei_field_order; + msg->dein_ei_mode = dei_cfg->dei_ei_mode; + msg->dein_ei_sel = dei_cfg->dei_ei_sel; + msg->dein_ei_radius = dei_cfg->dei_ei_radius; + msg->dein_ei_smooth = dei_cfg->dei_ei_smooth; + msg->dein_high_fre_fct = dei_cfg->dei_high_freq_fct; + } + switch (msg->dein_mode) { + case IEP_DEI_MODE_DISABLE : { + msg->dein_mode = IEP_DEI_MODE_BYPASS; + } break; + case IEP_DEI_MODE_I2O1 : + case IEP_DEI_MODE_I4O1 : + case IEP_DEI_MODE_I4O2 : { + // for avoid hardware error we need to config src1 and dst1 + if (!msg->src1.mem_addr) + memcpy(&msg->src1, &msg->src, sizeof(msg->src)); + if (!msg->dst1.mem_addr) + memcpy(&msg->dst1, &msg->dst, sizeof(msg->dst)); + } break; + default : { + } break; + } + } break; + case IEP_CMD_SET_DEI_SRC1 : { + mpp_assert(param); + // NOTE: only update which is used + memcpy(&msg->src1, param, sizeof(IepImg)); + if (iep_debug & IEP_DBG_IMAGE) { + mpp_log("setup src1\n"); + dump_iep_img((IepImg *)param); + } + } break; + case IEP_CMD_SET_DEI_DST1 : { + mpp_assert(param); + // NOTE: only update which is used + memcpy(&msg->dst1, param, sizeof(IepImg)); + if (iep_debug & IEP_DBG_IMAGE) { + mpp_log("setup dst1\n"); + dump_iep_img((IepImg *)param); + } + } break; + case IEP_CMD_SET_YUV_ENHANCE : { + IepCmdParamYuvEnhance *yuv_enh = (IepCmdParamYuvEnhance *)param; + + if (NULL == yuv_enh) { + msg->yuv_enhance_en = 1; + + msg->sat_con_int = 0x80; + msg->contrast_int = 0x80; + // hue_angle = 0 + msg->cos_hue_int = 0x00; + msg->sin_hue_int = 0x80; + + msg->yuv_enh_brightness = 0x00; + + msg->video_mode = IEP_VIDEO_MODE_NORMAL_VIDEO; + + msg->color_bar_u = 0; + msg->color_bar_v = 0; + msg->color_bar_y = 0; + break; + } + + if (check_yuv_enhance_param(yuv_enh)) { + ret = MPP_NOK; + break; + } + + if (msg->src.format >= 1 && msg->src.format <= 5 && + msg->dst.format >= 1 && msg->dst.format <= 5) { + mpp_err("Invalidate parameter, contradition between in/out format and yuv enhance\n"); + ret = MPP_NOK; + break; + } + + msg->yuv_enhance_en = 1; + + msg->sat_con_int = (RK_S32)(yuv_enh->saturation * yuv_enh->contrast * 128); + msg->contrast_int = (RK_S32)(yuv_enh->contrast * 128); + msg->cos_hue_int = (RK_S32)(cos(yuv_enh->hue_angle) * 128.0); + msg->sin_hue_int = (RK_S32)(sin(yuv_enh->hue_angle) * 128.0); + msg->yuv_enh_brightness = yuv_enh->brightness >= 0 ? + yuv_enh->brightness : + (yuv_enh->brightness + 64); + + msg->video_mode = yuv_enh->video_mode; + msg->color_bar_y = yuv_enh->color_bar_y; + msg->color_bar_u = yuv_enh->color_bar_u; + msg->color_bar_v = yuv_enh->color_bar_v; + } break; + case IEP_CMD_SET_RGB_ENHANCE : { + RK_U32 i; + IepCmdParamRgbEnhance *rgb_enh = (IepCmdParamRgbEnhance *)param; + + if (NULL == rgb_enh) { + msg->rgb_color_enhance_en = 1; + msg->rgb_enh_coe = 32; + msg->rgb_contrast_enhance_mode = IEP_RGB_ENHANCE_MODE_DETAIL_ENHANCE; + msg->rgb_cg_en = 0; + msg->enh_threshold = 255; + msg->enh_alpha = 8; + msg->enh_radius = 3; + + for (i = 0; i < MPP_ARRAY_ELEMS(cg_tab); i++) + msg->cg_tab[i] = cg_tab[i]; + + break; + } + + if (check_rgb_enhance_param(rgb_enh)) { + ret = MPP_NOK; + break; + } + + if ((msg->src.format & IEP_FORMAT_YUV_BASE) && + (msg->dst.format & IEP_FORMAT_YUV_BASE)) { + mpp_err("Invalidate parameter, contradition between in/out format and yuv enhance\n"); + ret = MPP_NOK; + break; + } + + msg->rgb_color_enhance_en = 1; + msg->rgb_enh_coe = (RK_U32)(rgb_enh->coe * 32); + msg->rgb_contrast_enhance_mode = rgb_enh->order; + msg->rgb_cg_en = rgb_enh->cg_en; + msg->rgb_enhance_mode = rgb_enh->mode; + + msg->enh_threshold = rgb_enh->threshold; + msg->enh_alpha = + enh_alpha_table[rgb_enh->alpha_base][rgb_enh->alpha_num]; + msg->enh_radius = rgb_enh->radius - 1; + + if (rgb_enh->cg_en) { + setup_cg_tab(rgb_enh->cg_rb, msg->cg_tab); + setup_cg_tab(rgb_enh->cg_rg, msg->cg_tab + 64); + setup_cg_tab(rgb_enh->cg_rb, msg->cg_tab + 128); + } + } break; + case IEP_CMD_SET_SCALE : { + IepCmdParamScale *scale = (IepCmdParamScale *)param; + + msg->scale_up_mode = (scale) ? (scale->scale_alg) : (IEP_SCALE_ALG_CATROM); + } break; + case IEP_CMD_SET_COLOR_CONVERT : { + IepCmdParamColorConvert *color_cvt = (IepCmdParamColorConvert *)param; + + if (NULL == color_cvt) { + msg->rgb2yuv_mode = IEP_COLOR_MODE_BT601_L; + msg->yuv2rgb_mode = IEP_COLOR_MODE_BT601_L; + msg->rgb2yuv_clip_en = 0; + msg->yuv2rgb_clip_en = 0; + msg->global_alpha_value = 0; + msg->dither_up_en = 1; + msg->dither_down_en = 1; + break; + } + + if (color_cvt->dither_up_en && msg->src.format != IEP_FORMAT_RGB_565) { + mpp_err("Invalidate parameter, contradiction between dither up enable and source image format!\n"); + ret = MPP_NOK; + break; + } + + if (color_cvt->dither_down_en && msg->dst.format != IEP_FORMAT_RGB_565) { + mpp_err("Invalidate parameter, contradiction between dither down enable and destination image format!\n"); + ret = MPP_NOK; + break; + } + + msg->rgb2yuv_mode = color_cvt->rgb2yuv_mode; + msg->yuv2rgb_mode = color_cvt->yuv2rgb_mode; + msg->rgb2yuv_clip_en = color_cvt->rgb2yuv_input_clip; + msg->yuv2rgb_clip_en = color_cvt->yuv2rgb_input_clip; + msg->global_alpha_value = color_cvt->global_alpha_value; + msg->dither_up_en = color_cvt->dither_up_en; + msg->dither_down_en = color_cvt->dither_down_en; + } break; + case IEP_CMD_RUN_SYNC : { + check_msg_image(msg); + + int ops_ret = ioctl(impl->fd, IEP_SET_PARAMETER, msg); + if (ops_ret < 0) + mpp_err("pid %d ioctl IEP_SET_PARAMETER failure\n", impl->pid); + + // NOTE: force result sync to avoid iep task queue full + ops_ret = ioctl(impl->fd, IEP_GET_RESULT_SYNC, 0); + if (ops_ret) + mpp_err("pid %d get result failure\n", impl->pid); + + ret = (MPP_RET)ops_ret; + } break; + case IEP_CMD_QUERY_CAP : { + if (param) + *(IepHwCap **)param = &impl->cap; + else + mpp_err("Can NOT query to NULL output\n"); + } break; + default : { + mpp_err("invalid command %d\n", cmd); + ret = MPP_NOK; + } break; + } + + return ret; +} + +static iep_com_ops iep_ops = { + .init = iep_init, + .deinit = iep_deinit, + .control = iep_control, + .reset = NULL, + .release = NULL, +}; + +iep_com_ctx* rockchip_iep_api_alloc_ctx(void) +{ + iep_com_ctx *com_ctx = (iep_com_ctx *)calloc(sizeof(*com_ctx), 1); + void *iep_ctx = calloc(sizeof(sizeof(void*)), 1); + + mpp_assert(com_ctx && iep_ctx); + + com_ctx->ops = &iep_ops; + com_ctx->priv = iep_ctx; + + return com_ctx; +} + +void rockchip_iep_api_release_ctx(iep_com_ctx *com_ctx) +{ + if (com_ctx->priv) { + free(com_ctx->priv); + com_ctx->priv = NULL; + } + + free(com_ctx); +} + diff --git a/mpp/vproc/iep/iep.h b/mpp/vproc/iep/iep.h new file mode 100644 index 000000000..432371431 --- /dev/null +++ b/mpp/vproc/iep/iep.h @@ -0,0 +1,239 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header is for communication between userspace driver and kernel driver */ + +#ifndef IEP_H +#define IEP_H + +#include +#include "rk_type.h" + +/* Capability for current iep version using by userspace to determine iep features */ +typedef struct IepHwCap_t { + RK_U8 scaling_supported; + RK_U8 i4_deinterlace_supported; + RK_U8 i2_deinterlace_supported; + RK_U8 compression_noise_reduction_supported; + RK_U8 sampling_noise_reduction_supported; + RK_U8 hsb_enhancement_supported; + RK_U8 cg_enhancement_supported; + RK_U8 direct_path_supported; + RK_U16 max_dynamic_width; + RK_U16 max_dynamic_height; + RK_U16 max_static_width; + RK_U16 max_static_height; + RK_U8 max_enhance_radius; +} IepHwCap; + +#define IEP_IOC_MAGIC 'i' + +#define IEP_SET_PARAMETER_REQ _IOW(IEP_IOC_MAGIC, 1, unsigned long) +#define IEP_SET_PARAMETER_DEINTERLACE _IOW(IEP_IOC_MAGIC, 2, unsigned long) +#define IEP_SET_PARAMETER_ENHANCE _IOW(IEP_IOC_MAGIC, 3, unsigned long) +#define IEP_SET_PARAMETER_CONVERT _IOW(IEP_IOC_MAGIC, 4, unsigned long) +#define IEP_SET_PARAMETER_SCALE _IOW(IEP_IOC_MAGIC, 5, unsigned long) +#define IEP_GET_RESULT_SYNC _IOW(IEP_IOC_MAGIC, 6, unsigned long) +#define IEP_GET_RESULT_ASYNC _IOW(IEP_IOC_MAGIC, 7, unsigned long) +#define IEP_SET_PARAMETER _IOW(IEP_IOC_MAGIC, 8, unsigned long) +#define IEP_RELEASE_CURRENT_TASK _IOW(IEP_IOC_MAGIC, 9, unsigned long) +#define IEP_GET_IOMMU_STATE _IOR(IEP_IOC_MAGIC, 10, unsigned long) +#define IEP_QUERY_CAP _IOR(IEP_IOC_MAGIC, 11, IepHwCap) + +enum { + DEI_MODE_BYPASS_DIS = 0x0, + DEI_MODE_I4O2 = 0x1, + DEI_MODE_I4O1B = 0x2, + DEI_MODE_I4O1T = 0x3, + DEI_MODE_I2O1B = 0x4, + DEI_MODE_I2O1T = 0x5, + DEI_MODE_BYPASS = 0x6, +}; + +// for rgb_enhance_mode +enum { + RGB_ENHANCE_BYPASS = 0x0, + RGB_ENHANCE_DENOISE = 0x1, + RGB_ENHANCE_DETAIL = 0x2, + RGB_ENHANCE_EDGE = 0x3, +}; + +// for rgb_contrast_enhance_mode +enum { + RGB_CONTRAST_CC_P_DDE = 0x0, // cg prior to dde + RGB_CONTRAST_DDE_P_CC = 0x1, // dde prior to cg +}; + +// for video mode +enum { + BLACK_SCREEN = 0x0, + BLUE_SCREEN = 0x1, + COLOR_BAR = 0x2, + NORMAL_MODE = 0x3, +}; + +/* +// Alpha Red Green Blue +{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_RGBA }, IEP_FORMAT_ARGB_8888 +{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, IEP_FORMAT_ABGR_8888 +{ 4, 32, {{ 8, 0, 32,24, 24,16, 16, 8 }}, GGL_RGB }, IEP_FORMAT_RGBA_8888 +{ 4, 32, {{ 8, 0, 16, 8, 24,16, 32,24 }}, GGL_BGRA }, IEP_FORMAT_BGRA_8888 +{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, IEP_FORMAT_RGB_565 +{ 2, 16, {{ 0, 0, 5, 0, 11, 5, 16,11 }}, GGL_RGB }, IEP_FORMAT_RGB_565 +*/ + +// for hardware format value +enum { + IEP_MSG_FMT_ARGB_8888 = 0x0, + IEP_MSG_FMT_ABGR_8888 = 0x1, + IEP_MSG_FMT_RGBA_8888 = 0x2, + IEP_MSG_FMT_BGRA_8888 = 0x3, + IEP_MSG_FMT_RGB_565 = 0x4, + IEP_MSG_FMT_BGR_565 = 0x5, + + IEP_MSG_FMT_YCbCr_422_SP = 0x10, + IEP_MSG_FMT_YCbCr_422_P = 0x11, + IEP_MSG_FMT_YCbCr_420_SP = 0x12, + IEP_MSG_FMT_YCbCr_420_P = 0x13, + IEP_MSG_FMT_YCrCb_422_SP = 0x14, + IEP_MSG_FMT_YCrCb_422_P = 0x15, // same as IEP_FORMAT_YCbCr_422_P + IEP_MSG_FMT_YCrCb_420_SP = 0x16, + IEP_MSG_FMT_YCrCb_420_P = 0x17, // same as IEP_FORMAT_YCbCr_420_P +}; + +/* + * + <--------------+ virtual width +------------> + + * | | + * +-------------------------------------------------+---+---+ + * | | ^ + * | + <---+ actual width +--> + | | + * | | | | | + * | +---------------------------+---+--+ | | + * | | | ^ | + + * | | | + | virtual + * | | | actual | height + * | | | height | + + * | | | + | | + * | | | ^ | | + * | +---------------------------+---+--+ | | + * | | ^ + * +-------------------------------------------------+---+---+ + */ +// NOTE: This is for kernel driver communication. keep it for compatibility +typedef struct IepMsgImg_t { + RK_U16 act_w; // act_width + RK_U16 act_h; // act_height + RK_S16 x_off; // x offset for the vir,word unit + RK_S16 y_off; // y offset for the vir,word unit + + RK_U16 vir_w; // unit :pix + RK_U16 vir_h; // unit :pix + RK_U32 format; + RK_U32 mem_addr; + RK_U32 uv_addr; + RK_U32 v_addr; + + RK_U8 rb_swap; // not be used + RK_U8 uv_swap; // not be used + + RK_U8 alpha_swap; // not be used +} IepMsgImg; + +typedef struct IepMsg_t { + IepMsgImg src; // src active window + IepMsgImg dst; // src virtual window + + IepMsgImg src1; + IepMsgImg dst1; + + IepMsgImg src_itemp; + IepMsgImg src_ftemp; + + IepMsgImg dst_itemp; + IepMsgImg dst_ftemp; + + RK_U8 dither_up_en; + RK_U8 dither_down_en; //not to be used + + RK_U8 yuv2rgb_mode; + RK_U8 rgb2yuv_mode; + + RK_U8 global_alpha_value; + + RK_U8 rgb2yuv_clip_en; + RK_U8 yuv2rgb_clip_en; + + RK_U8 lcdc_path_en; + RK_S32 off_x; + RK_S32 off_y; + RK_S32 width; + RK_S32 height; + RK_S32 layer; + + RK_U8 yuv_3D_denoise_en; + + /// yuv color enhance + RK_U8 yuv_enhance_en; + RK_S32 sat_con_int; + RK_S32 contrast_int; + RK_S32 cos_hue_int; + RK_S32 sin_hue_int; + RK_S8 yuv_enh_brightness; // -32 < brightness < 31 + RK_U8 video_mode; // 0 ~ 3 + RK_U8 color_bar_y; // 0 ~ 127 + RK_U8 color_bar_u; // 0 ~ 127 + RK_U8 color_bar_v; // 0 ~ 127 + + + RK_U8 rgb_enhance_en; // I don't know its usage + + RK_U8 rgb_color_enhance_en; // sw_rgb_color_enh_en + RK_U32 rgb_enh_coe; + + RK_U8 rgb_enhance_mode; // sw_rgb_enh_sel,dde sel + + RK_U8 rgb_cg_en; // sw_rgb_con_gam_en + RK_U32 cg_tab[192]; + + // sw_con_gam_order; 0 cg prior to dde, 1 dde prior to cg + RK_U8 rgb_contrast_enhance_mode; + + RK_S32 enh_threshold; + RK_S32 enh_alpha; + RK_S32 enh_radius; + + RK_U8 scale_up_mode; + + RK_U8 field_order; + RK_U8 dein_mode; + //DIL High Frequency + RK_U8 dein_high_fre_en; + RK_U8 dein_high_fre_fct; + //DIL EI + RK_U8 dein_ei_mode; + RK_U8 dein_ei_smooth; + RK_U8 dein_ei_sel; + RK_U8 dein_ei_radius; // when dein_ei_sel=0 will be used + + RK_U8 dil_mtn_tbl_en; + RK_U32 dil_mtn_tbl[8]; + + RK_U8 vir_addr_enable; + + void *base; +} IepMsg; + +#endif /* IEP_H */ diff --git a/mpp/vproc/iep/test/CMakeLists.txt b/mpp/vproc/iep/test/CMakeLists.txt new file mode 100644 index 000000000..ed89fc95a --- /dev/null +++ b/mpp/vproc/iep/test/CMakeLists.txt @@ -0,0 +1,12 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# mpp/vproc/iep built-in unit test case +# ---------------------------------------------------------------------------- +# iep unit test +option(IEP_TEST "Build base iep unit test" ${BUILD_TEST}) +if (IEP_TEST) + add_executable(iep_test iep_test.c) + target_link_libraries(iep_test ${MPP_SHARED} utils) + set_target_properties(iep_test PROPERTIES FOLDER "mpp/vproc/iep") + add_test(NAME iep_test COMMAND iep_test) +endif() diff --git a/mpp/vproc/iep/test/iep_dei.cfg b/mpp/vproc/iep/test/iep_dei.cfg new file mode 100644 index 000000000..1e9c921aa --- /dev/null +++ b/mpp/vproc/iep/test/iep_dei.cfg @@ -0,0 +1,8 @@ +[deinterlace] +dei_high_freq_en = 1 +dei_mode = 4 +dei_high_freq_fct = 0 +dei_ei_mode = 0 +dei_ei_smooth = 0 +dei_ei_sel = 0 +dei_ei_radius = 0 diff --git a/mpp/vproc/iep/test/iep_test.c b/mpp/vproc/iep/test/iep_test.c new file mode 100644 index 000000000..f69e95c0e --- /dev/null +++ b/mpp/vproc/iep/test/iep_test.c @@ -0,0 +1,573 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2018 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "iep_test" + +#include + +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" +#include "mpp_buffer.h" + +#include "iep_api.h" +#include "utils.h" +#include "iniparser.h" + +#define MAX_URL_LEN (100) +#define ADD_OFFSET(base, offset) ((RK_U32)base + ((RK_U32)(offset) << 10)) + +typedef enum { + TEST_CASE_NONE, + TEST_CASE_DEINTERLACE, + TEST_CASE_YUVENHANCE, + TEST_CASE_RGBENHANCE, +} TEST_CASE; + +typedef struct IepTestCfg_t { + RK_S32 src_w; + RK_S32 src_h; + RK_S32 src_fmt; + + RK_S32 dst_w; + RK_S32 dst_h; + RK_S32 dst_fmt; + + char src_url[MAX_URL_LEN]; + char dst_url[MAX_URL_LEN]; + char cfg_url[MAX_URL_LEN]; + + FILE *fp_src; + FILE *fp_dst; + + TEST_CASE mode; + + dictionary *ini; + IepCmdParamDeiCfg *dei_cfg; + IepCmdParamYuvEnhance *yuv_enh; + IepCmdParamRgbEnhance *rgb_enh; + IepCmdParamColorConvert *colorcvt; +} IepTestCfg; + +typedef struct IepTestInfo_t { + IepTestCfg *cfg; + + size_t src_size; + size_t dst_size; + + RK_U32 phy_src0; + RK_U32 phy_src1; + RK_U32 phy_dst0; + RK_U32 phy_dst1; + + RK_U8 *vir_src0; + RK_U8 *vir_src1; + RK_U8 *vir_dst0; + RK_U8 *vir_dst1; + + IepImg src; + IepImg dst; + + IepCtx ctx; +} IepTestInfo; + +static void parse_cfg(IepTestCfg *cfg) +{ + dictionary *ini = cfg->ini; + + cfg->dei_cfg = mpp_calloc(IepCmdParamDeiCfg, 1); + if (iniparser_find_entry(ini, "deinterlace")) { + mpp_assert(cfg->dei_cfg); + cfg->dei_cfg->dei_high_freq_en = + iniparser_getint(ini, "deinterlace:high_freq_en", 0); + cfg->dei_cfg->dei_mode = + (IepDeiMode)iniparser_getint(ini, "deinterlace:dei_mode", 0); + cfg->dei_cfg->dei_high_freq_fct = + iniparser_getint(ini, "deinterlace:dei_high_freq_fct", 0); + cfg->dei_cfg->dei_ei_mode = + iniparser_getint(ini, "deinterlace:dei_ei_mode", 0); + cfg->dei_cfg->dei_ei_smooth = + iniparser_getint(ini, "deinterlace:dei_ei_smooth", 0); + cfg->dei_cfg->dei_ei_sel = + iniparser_getint(ini, "deinterlace:dei_ei_sel", 0); + cfg->dei_cfg->dei_ei_radius = + iniparser_getint(ini, "deinterlace:dei_ei_radius", 0); + } else { + cfg->dei_cfg->dei_high_freq_en = 1; + cfg->dei_cfg->dei_mode = IEP_DEI_MODE_I4O1; + cfg->dei_cfg->dei_field_order = IEP_DEI_FLD_ORDER_BOT_FIRST; + cfg->dei_cfg->dei_ei_mode = 0; + cfg->dei_cfg->dei_ei_smooth = 0; + cfg->dei_cfg->dei_ei_sel = 0; + cfg->dei_cfg->dei_ei_radius = 0; + } + + if (iniparser_find_entry(ini, "yuv enhance")) { + cfg->yuv_enh = mpp_calloc(IepCmdParamYuvEnhance, 1); + cfg->yuv_enh->saturation = + iniparser_getint(ini, "yuv enhance:saturation", 0); + cfg->yuv_enh->contrast = + iniparser_getint(ini, "yuv enhance:contrast", 0); + cfg->yuv_enh->brightness = + iniparser_getint(ini, "yuv enhance:brightness", 0); + cfg->yuv_enh->hue_angle = + iniparser_getint(ini, "yuv enhance:hue_angle", 0); + cfg->yuv_enh->video_mode = + (IepVideoMode) + iniparser_getint(ini, "yuv enhance:video_mode", 0); + cfg->yuv_enh->color_bar_y = + iniparser_getint(ini, "yuv enhance:color_bar_y", 0); + cfg->yuv_enh->color_bar_u = + iniparser_getint(ini, "yuv enhance:color_bar_u", 0); + cfg->yuv_enh->color_bar_v = + iniparser_getint(ini, "yuv enhance:color_bar_v", 0); + } + + if (iniparser_find_entry(ini, "rgb enhance")) { + cfg->rgb_enh = mpp_calloc(IepCmdParamRgbEnhance, 1); + cfg->rgb_enh->coe = + iniparser_getint(ini, "rgb enhance:coe", 0); + cfg->rgb_enh->mode = + (IepRgbEnhanceMode) + iniparser_getint(ini, "rgb enhance:mode", 0); + cfg->rgb_enh->cg_en = + iniparser_getint(ini, "rgb enhance:cg_en", 0); + cfg->rgb_enh->cg_rr = + iniparser_getint(ini, "rgb enhance:cg_rr", 0); + cfg->rgb_enh->cg_rg = + iniparser_getint(ini, "rgb enhance:cg_rg", 0); + cfg->rgb_enh->cg_rb = + iniparser_getint(ini, "rgb enhance:cg_rb", 0); + cfg->rgb_enh->order = + (IepRgbEnhanceOrder) + iniparser_getint(ini, "rgb enhance:order", 0); + cfg->rgb_enh->threshold = + iniparser_getint(ini, "rgb enhance:threshold", 0); + cfg->rgb_enh->alpha_num = + iniparser_getint(ini, "rgb enhance:alpha_num", 0); + cfg->rgb_enh->alpha_base = + iniparser_getint(ini, "rgb enhance:alpha_base", 0); + cfg->rgb_enh->radius = + iniparser_getint(ini, "rgb enhance:radius", 0); + } + + if (iniparser_find_entry(ini, "colorcvt")) { + cfg->colorcvt = mpp_calloc(IepCmdParamColorConvert, 1); + cfg->colorcvt->rgb2yuv_mode = + (IepColorConvertMode) + iniparser_getint(ini, "colorcvt:rgb2yuv_mode", 0); + cfg->colorcvt->yuv2rgb_mode = + (IepColorConvertMode) + iniparser_getint(ini, "colorcvt:yuv2rgb_mode", 0); + cfg->colorcvt->rgb2yuv_input_clip = + iniparser_getint(ini, "colorcvt:rgb2yuv_input_clip", 0); + cfg->colorcvt->yuv2rgb_input_clip = + iniparser_getint(ini, "colorcvt:yuv2rgb_input_clip", 0); + cfg->colorcvt->global_alpha_value = + iniparser_getint(ini, "colorcvt:global_alpha_value", 0); + cfg->colorcvt->dither_up_en = + iniparser_getint(ini, "colorcvt:dither_up_en", 0); + cfg->colorcvt->dither_down_en = + iniparser_getint(ini, "colorcvt:dither_down_en", 0); + } +} + +static RK_S32 get_image_size(RK_S32 w, RK_S32 h, RK_S32 fmt) +{ + RK_S32 img_size = 0; + + switch (fmt) { + case IEP_FORMAT_ABGR_8888: + case IEP_FORMAT_ARGB_8888: + case IEP_FORMAT_BGRA_8888: + case IEP_FORMAT_RGBA_8888: + img_size = w * h * 4; + break; + case IEP_FORMAT_BGR_565: + case IEP_FORMAT_RGB_565: + case IEP_FORMAT_YCbCr_422_P: + case IEP_FORMAT_YCbCr_422_SP: + case IEP_FORMAT_YCrCb_422_P: + case IEP_FORMAT_YCrCb_422_SP: + img_size = w * h * 2; + break; + case IEP_FORMAT_YCbCr_420_P: + case IEP_FORMAT_YCbCr_420_SP: + case IEP_FORMAT_YCrCb_420_P: + case IEP_FORMAT_YCrCb_420_SP: + img_size = w * h * 3 / 2; + break; + default : { + } break; + } + return img_size; +} + +static void config_iep_img(IepImg *img, RK_S32 w, RK_S32 h, RK_S32 fmt, RK_U32 base) +{ + switch (fmt) { + case IEP_FORMAT_ABGR_8888: + case IEP_FORMAT_ARGB_8888: + case IEP_FORMAT_BGRA_8888: + case IEP_FORMAT_RGBA_8888: + img->v_addr = 0; + break; + case IEP_FORMAT_BGR_565: + case IEP_FORMAT_RGB_565: + case IEP_FORMAT_YCbCr_422_P: + case IEP_FORMAT_YCbCr_422_SP: + case IEP_FORMAT_YCrCb_422_P: + case IEP_FORMAT_YCrCb_422_SP: + img->v_addr = ADD_OFFSET(base, w * h + w * h / 2); + break; + case IEP_FORMAT_YCbCr_420_P: + case IEP_FORMAT_YCbCr_420_SP: + case IEP_FORMAT_YCrCb_420_P: + case IEP_FORMAT_YCrCb_420_SP: + img->v_addr = ADD_OFFSET(base, w * h + w * h / 4); + break; + default : { + } break; + } + + img->act_w = w; + img->act_h = h; + img->x_off = 0; + img->y_off = 0; + img->vir_w = w; + img->vir_h = h; + img->format = fmt; + img->mem_addr = base; + img->uv_addr = ADD_OFFSET(base, w * h); +} + +void* iep_process_thread(void *param) +{ + IepTestInfo *info = (IepTestInfo*)param; + IepTestCfg *cfg = info->cfg; + + config_iep_img(&info->src, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_src0); + config_iep_img(&info->dst, cfg->dst_w, cfg->dst_h, cfg->dst_fmt, info->phy_dst0); + + if (info->src_size > fread(info->vir_src0, 1, info->src_size, cfg->fp_src)) { + mpp_err("read file failed\n"); + return NULL; + } + + iep_control(info->ctx, IEP_CMD_INIT, NULL); + iep_control(info->ctx, IEP_CMD_SET_SRC, &info->src); + iep_control(info->ctx, IEP_CMD_SET_DST, &info->dst); + + switch (cfg->mode) { + case TEST_CASE_YUVENHANCE: { + iep_control(info->ctx, IEP_CMD_SET_YUV_ENHANCE, cfg->yuv_enh); + } break; + case TEST_CASE_RGBENHANCE: { + iep_control(info->ctx, IEP_CMD_SET_RGB_ENHANCE, cfg->rgb_enh); + } break; + case TEST_CASE_DEINTERLACE: { + IepImg src1; + IepImg dst1; + + if (info->src_size != fread(info->vir_src1, 1, info->src_size, cfg->fp_src)) + mpp_err("failed to read %d from input\n", info->src_size); + + config_iep_img(&src1, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_src1); + config_iep_img(&dst1, cfg->src_w, cfg->src_h, cfg->src_fmt, info->phy_dst1); + + iep_control(info->ctx, IEP_CMD_SET_DEI_SRC1, &src1); + iep_control(info->ctx, IEP_CMD_SET_DEI_DST1, &dst1); + iep_control(info->ctx, IEP_CMD_SET_DEI_CFG, cfg->dei_cfg); + } break; + default: { + } break; + } + + RK_S64 intime = mpp_time(); + if (0 == iep_control(info->ctx, IEP_CMD_RUN_SYNC, NULL)) + mpp_log("%d success\n", getpid()); + else + mpp_log("%d failure\n", getpid()); + + mpp_log("%s consume %lld ms\n", __func__, (mpp_time() - intime) / 1000); + + if (cfg->fp_dst) + fwrite(info->vir_dst0, 1, info->dst_size, cfg->fp_dst); + + return NULL; +} + +static RK_S32 str_to_iep_fmt(const char *str) +{ + RK_S32 fmt = -1; + + if (!strcmp(str, "argb8888")) + fmt = IEP_FORMAT_ARGB_8888; + else if (!strcmp(str, "abgr8888")) + fmt = IEP_FORMAT_ABGR_8888; + else if (!strcmp(str, "rgba8888")) + fmt = IEP_FORMAT_BGRA_8888; + else if (!strcmp(str, "bgra8888")) + fmt = IEP_FORMAT_BGRA_8888; + else if (!strcmp(str, "rgb565")) + fmt = IEP_FORMAT_RGB_565; + else if (!strcmp(str, "bgr565")) + fmt = IEP_FORMAT_BGR_565; + else if (!strcmp(str, "yuv422sp")) + fmt = IEP_FORMAT_YCbCr_422_SP; + else if (!strcmp(str, "yuv422p")) + fmt = IEP_FORMAT_YCbCr_422_P; + else if (!strcmp(str, "yuv420sp")) + fmt = IEP_FORMAT_YCbCr_420_SP; + else if (!strcmp(str, "yuv420p")) + fmt = IEP_FORMAT_YCbCr_420_P; + else if (!strcmp(str, "yvu422sp")) + fmt = IEP_FORMAT_YCrCb_422_SP; + else if (!strcmp(str, "yvu422p")) + fmt = IEP_FORMAT_YCrCb_422_P; + else if (!strcmp(str, "yvu420sp")) + fmt = IEP_FORMAT_YCrCb_420_SP; + else if (!strcmp(str, "yvu420p")) + fmt = IEP_FORMAT_YCrCb_420_P; + else + mpp_err("invalid format %s\n", str); + + return fmt; +} + +static MPP_RET check_input_cmd(IepTestCfg *cfg) +{ + MPP_RET ret = MPP_OK; + + if (cfg->src_w <= 0) { + mpp_err("non-positive input width %d\n", cfg->src_w); + ret = MPP_NOK; + } + if (cfg->src_h <= 0) { + mpp_err("non-positive input height %d\n", cfg->src_h); + ret = MPP_NOK; + } + if (cfg->src_fmt < IEP_FORMAT_ARGB_8888 || + cfg->src_fmt > IEP_FORMAT_YCrCb_420_P) { + mpp_err("invalid input format\n"); + ret = MPP_NOK; + } + if (cfg->fp_src == NULL) { + mpp_err("failed to open input file %s\n", cfg->src_url); + ret = MPP_NOK; + } + if (cfg->dst_w <= 0) { + mpp_err("non-positive input width %d\n", cfg->dst_w); + ret = MPP_NOK; + } + if (cfg->dst_h <= 0) { + mpp_err("non-positive input height %d\n", cfg->dst_h); + ret = MPP_NOK; + } + if (cfg->dst_fmt < IEP_FORMAT_ARGB_8888 || + cfg->dst_fmt > IEP_FORMAT_YCrCb_420_P) { + mpp_err("invalid input format\n"); + ret = MPP_NOK; + } + if (cfg->mode == TEST_CASE_NONE) { + mpp_err("invalid work mode\n"); + ret = MPP_NOK; + } + + return ret; +} + +static OptionInfo iep_test_cmd[] = { + {"w", "src_width", "input image width"}, + {"h", "src_height", "input image height"}, + {"c", "src_format", "input image format in ASCII string"}, + {"f", "src_file", "input image file name"}, + {"W", "dst_width", "output image width"}, + {"H", "dst_height", "output image height"}, + {"C", "dst_format", "output image format in ASCII string"}, + {"F", "dst_file", "output image file name"}, + {"m", "work_mode", "working mode of iep in ASCII string"}, + {"x", "configure", "configure file of working mode"}, +}; + +static void iep_test_help() +{ + mpp_log("usage: iep_test [options]\n"); + mpp_log("*******************************\n"); + show_options(iep_test_cmd); + mpp_log("*******************************\n"); + mpp_log("supported ASCII format strings:\n"); + mpp_log(" 0 - argb8888\n"); + mpp_log(" 1 - abgr8888\n"); + mpp_log(" 2 - rgba8888\n"); + mpp_log(" 3 - bgra8888\n"); + mpp_log(" 4 - rgb565\n"); + mpp_log(" 5 - bgr565\n"); + mpp_log(" 6 - yuv422sp\n"); + mpp_log(" 7 - yuv422p\n"); + mpp_log(" 8 - yuv420sp\n"); + mpp_log(" 9 - yuv420p\n"); + mpp_log("10 - yvu422sp\n"); + mpp_log("11 - yvu422p\n"); + mpp_log("12 - yvu420sp\n"); + mpp_log("13 - yvu420p\n"); + mpp_log("*******************************\n"); + mpp_log("supported work mode strings:\n"); + mpp_log(" 1 - deinterlace\n"); + mpp_log(" 2 - yuvenhance\n"); + mpp_log(" 3 - rgbenhance\n"); + mpp_log("************ sample ***********\n"); + mpp_log("iep_test -w 720 -h 480 -c yuv420p -f input.yuv -W 720 -H 480 -C yuv420p -F output.yuv -m deinterlace -x dil.cfg\n"); +} + +int main(int argc, char **argv) +{ + IepTestCfg cfg; + IepTestInfo info; + int ch; + + if (argc < 2) { + iep_test_help(); + return 0; + } + + memset(&cfg, 0, sizeof(cfg)); + memset(&info, 0, sizeof(info)); + cfg.src_fmt = IEP_FORMAT_YCbCr_420_SP; + cfg.dst_fmt = IEP_FORMAT_YCbCr_420_SP; + + /// get options + opterr = 0; + while ((ch = getopt(argc, argv, "f:w:h:c:F:W:H:C:m:x:")) != -1) { + switch (ch) { + case 'w': { + cfg.src_w = atoi(optarg); + } break; + case 'h': { + cfg.src_h = atoi(optarg); + } break; + case 'c': { + cfg.src_fmt = str_to_iep_fmt(optarg); + } break; + case 'W': { + cfg.dst_w = atoi(optarg); + } break; + case 'H': { + cfg.dst_h = atoi(optarg); + } break; + case 'C': { + cfg.dst_fmt = str_to_iep_fmt(optarg); + } break; + case 'f': { + mpp_log("input filename: %s\n", optarg); + strncpy(cfg.src_url, optarg, sizeof(cfg.src_url) - 1); + cfg.fp_src = fopen(cfg.src_url, "rb"); + } break; + case 'F': { + mpp_log("output filename: %s\n", optarg); + strncpy(cfg.dst_url, optarg, sizeof(cfg.dst_url) - 1); + cfg.fp_dst = fopen(cfg.dst_url, "w+b"); + } break; + case 'm': { + if (!strcmp(optarg, "deinterlace")) { + cfg.mode = TEST_CASE_DEINTERLACE; + } else if (!strcmp(optarg, "yuvenhance")) { + cfg.mode = TEST_CASE_YUVENHANCE; + } else if (!strcmp(optarg, "rgbenhance")) { + cfg.mode = TEST_CASE_RGBENHANCE; + } else { + mpp_err("invalid work mode %s\n", optarg); + cfg.mode = TEST_CASE_NONE; + } + } break; + case 'x': { + mpp_log("configure filename: %s\n", optarg); + strncpy(cfg.cfg_url, optarg, sizeof(cfg.cfg_url) - 1); + cfg.ini = iniparser_load(cfg.cfg_url); + if (cfg.ini) + parse_cfg(&cfg); + else + mpp_err("invalid configure file %s\n", optarg); + } break; + default: { + } break; + } + } + + if (check_input_cmd(&cfg)) { + mpp_err("failed to pass cmd line check\n"); + iep_test_help(); + return -1; + } + + info.cfg = &cfg; + info.src_size = get_image_size(cfg.src_w, cfg.src_h, cfg.src_fmt); + info.dst_size = get_image_size(cfg.dst_w, cfg.dst_h, cfg.dst_fmt); + + // allocate 12M in/out memory and initialize memory address + MppBuffer buffer = NULL; + size_t src_size = MPP_ALIGN(info.src_size, SZ_4K); + size_t dst_size = MPP_ALIGN(info.dst_size, SZ_4K); + // NOTE: deinterlace need 4 fields (2 frames) as input and output 2 frames + size_t total_size = src_size * 2 + dst_size * 2; + + mpp_buffer_get(NULL, &buffer, total_size); + mpp_assert(buffer); + + int buf_fd = mpp_buffer_get_fd(buffer); + RK_U8 *buf_ptr = (RK_U8 *)mpp_buffer_get_ptr(buffer); + + memset(buf_ptr, 0xff, total_size); + + info.phy_src0 = ADD_OFFSET(buf_fd, 0); + info.phy_src1 = ADD_OFFSET(buf_fd, src_size); + info.phy_dst0 = ADD_OFFSET(buf_fd, src_size * 2); + info.phy_dst1 = ADD_OFFSET(buf_fd, src_size * 2 + dst_size); + + info.vir_src0 = buf_ptr; + info.vir_src1 = buf_ptr + src_size; + info.vir_dst0 = buf_ptr + src_size * 2; + info.vir_dst1 = buf_ptr + src_size * 2 + dst_size; + + iep_init(&info.ctx); + + pthread_t td; + pthread_create(&td, NULL, iep_process_thread, &info); + pthread_join(td, NULL); + + if (info.ctx) { + iep_deinit(info.ctx); + info.ctx = NULL; + } + + if (cfg.fp_src) { + fclose(cfg.fp_src); + cfg.fp_src = NULL; + } + + if (cfg.fp_dst) { + fclose(cfg.fp_dst); + cfg.fp_dst = NULL; + } + + if (cfg.ini) { + iniparser_freedict(cfg.ini); + cfg.ini = NULL; + if (cfg.yuv_enh) + mpp_free(cfg.yuv_enh); + if (cfg.rgb_enh) + mpp_free(cfg.rgb_enh); + if (cfg.dei_cfg) + mpp_free(cfg.dei_cfg); + if (cfg.colorcvt) + mpp_free(cfg.colorcvt); + } + + mpp_buffer_put(buffer); + + return 0; +} diff --git a/mpp/vproc/iep2/CMakeLists.txt b/mpp/vproc/iep2/CMakeLists.txt new file mode 100644 index 000000000..b4e57bcf7 --- /dev/null +++ b/mpp/vproc/iep2/CMakeLists.txt @@ -0,0 +1,15 @@ +# vim: syntax=cmake + +# ---------------------------------------------------------------------------- +# add video process IEP2 (Image Enhancement Processor) implement +# ---------------------------------------------------------------------------- +add_library(vproc_iep2 OBJECT + iep2.c + iep2_ff.c + iep2_gmv.c + iep2_osd.c + iep2_pd.c + iep2_roi.c + ) + +add_subdirectory(test) diff --git a/mpp/vproc/iep2/iep2.c b/mpp/vproc/iep2/iep2.c new file mode 100644 index 000000000..9c2ddfa88 --- /dev/null +++ b/mpp/vproc/iep2/iep2.c @@ -0,0 +1,528 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iep2_api.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_buffer.h" + +#include "iep2_ff.h" +#include "iep2_pd.h" +#include "iep2_gmv.h" +#include "iep2_osd.h" +#include "iep2_roi.h" + +#include "iep2.h" +#include "mpp_service.h" +#include "mpp_platform.h" + +#define IEP2_TILE_W_MAX 120 +#define IEP2_TILE_H_MAX 480 +#define IEP2_OSD_EN 0 + +RK_U32 iep_debug = 0; +RK_U32 iep_md_pre_en = 0; + +/* default iep2 mtn table */ +static RK_U32 iep2_mtn_tab[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x01010000, 0x06050302, 0x0f0d0a08, 0x1c191512, + 0x2b282420, 0x3634312e, 0x3d3c3a38, 0x40403f3e, + 0x40404040, 0x40404040, 0x40404040, 0x40404040 +}; + +static MPP_RET get_param_from_env(struct iep2_api_ctx *ctx) +{ + struct iep2_params *params = &ctx->params; + mpp_env_get_u32("md_theta", ¶ms->md_theta, ctx->params.md_theta); + mpp_env_get_u32("md_r", ¶ms->md_r, ctx->params.md_r); + mpp_env_get_u32("md_lambda", ¶ms->md_lambda, ctx->params.md_lambda); + + mpp_env_get_u32("mv_similar_thr", ¶ms->mv_similar_thr, ctx->params.mv_similar_thr); + mpp_env_get_u32("mv_similar_num_thr0", ¶ms->mv_similar_num_thr0, ctx->params.mv_similar_num_thr0); + + mpp_env_get_u32("eedi_thr0", ¶ms->eedi_thr0, ctx->params.eedi_thr0); + mpp_env_get_u32("comb_t_thr", ¶ms->comb_t_thr, ctx->params.comb_t_thr); + mpp_env_get_u32("comb_feature_thr", ¶ms->comb_feature_thr, ctx->params.comb_feature_thr); + return MPP_OK; +} + +static MPP_RET iep2_init(IepCtx *ictx) +{ + MPP_RET ret; + struct iep2_api_ctx *ctx = *ictx; + MppReqV1 mpp_req; + RK_U32 client_data = IEP_CLIENT_TYPE; + + mpp_env_get_u32("iep_debug", &iep_debug, 0); + + ctx->fd = open("/dev/mpp_service", O_RDWR | O_CLOEXEC); + if (ctx->fd < 0) { + mpp_err("can NOT find device /dev/iep2\n"); + return MPP_NOK; + } + + mpp_req.cmd = MPP_CMD_INIT_CLIENT_TYPE; + mpp_req.flag = 0; + mpp_req.size = sizeof(client_data); + mpp_req.data_ptr = REQ_DATA_PTR(&client_data); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) { + mpp_err("ioctl set_client failed\n"); + return MPP_NOK; + } + + // set default parameters. + ctx->params.src_fmt = IEP2_FMT_YUV420; + ctx->params.src_yuv_swap = IEP2_YUV_SWAP_SP_UV; + ctx->params.dst_fmt = IEP2_FMT_YUV420; + ctx->params.dst_yuv_swap = IEP2_YUV_SWAP_SP_UV; + + ctx->params.src_y_stride = 720 / 4; + ctx->params.src_uv_stride = 720 / 4; + ctx->params.dst_y_stride = 720 / 4; + + ctx->params.tile_cols = 720 / 16; + ctx->params.tile_rows = 480 / 4; + + ctx->params.dil_mode = IEP2_DIL_MODE_I1O1T; + + ctx->params.dil_out_mode = IEP2_OUT_MODE_LINE; + ctx->params.dil_field_order = IEP2_FIELD_ORDER_TFF; + + ctx->params.md_theta = 1; + ctx->params.md_r = 6; + + if (mpp_get_soc_type() == ROCKCHIP_SOC_RK3528) { + mpp_env_get_u32("iep_md_pre_en", &iep_md_pre_en, 0); + if (iep_md_pre_en) { + ctx->params.md_lambda = 4; + } else { + ctx->params.md_lambda = 8; + } + } else { + ctx->params.md_lambda = 4; + } + + ctx->params.dect_resi_thr = 30; + ctx->params.osd_area_num = 0; + ctx->params.osd_gradh_thr = 60; + ctx->params.osd_gradv_thr = 60; + + ctx->params.osd_pos_limit_en = 0; + ctx->params.osd_pos_limit_num = 0; + + ctx->params.osd_pec_thr = 20; + ctx->params.osd_line_num = 2; + + ctx->params.me_pena = 5; + ctx->params.mv_similar_thr = 4; + ctx->params.mv_similar_num_thr0 = 4; + ctx->params.mv_bonus = 10; + ctx->params.me_thr_offset = 20; + + ctx->params.mv_left_limit = 28; + ctx->params.mv_right_limit = 27; + + ctx->params.eedi_thr0 = 12; + + memset(ctx->params.comb_osd_vld, 1, sizeof(ctx->params.comb_osd_vld)); + ctx->params.comb_t_thr = 4; + ctx->params.comb_feature_thr = 16; + ctx->params.comb_cnt_thr = 0; + + ctx->params.ble_backtoma_num = 1; + + ctx->params.mtn_en = 1; + memcpy(ctx->params.mtn_tab, iep2_mtn_tab, sizeof(ctx->params.mtn_tab)); + + ctx->params.roi_en = 0; + ctx->params.roi_layer_num = 0; + + ctx->params.dil_mode = IEP2_DIL_MODE_I1O1T; + ctx->params.src_fmt = IEP2_FMT_YUV420; + ctx->params.src_yuv_swap = IEP2_YUV_SWAP_SP_UV; + ctx->params.dst_fmt = IEP2_FMT_YUV420; + ctx->params.dst_yuv_swap = IEP2_YUV_SWAP_SP_UV; + ctx->params.src_y_stride = 720 / 4; + ctx->params.src_uv_stride = 720 / 4; + ctx->params.dst_y_stride = 720 / 4; + ctx->params.tile_cols = 720 / 16; + ctx->params.tile_rows = 480 / 4; + + memset(&ctx->ff_inf, 0, sizeof(ctx->ff_inf)); + + memset(&ctx->pd_inf, 0, sizeof(ctx->pd_inf)); + ctx->pd_inf.pdtype = PD_TYPES_UNKNOWN; + ctx->pd_inf.step = -1; + + ret = mpp_buffer_group_get_internal(&ctx->memGroup, MPP_BUFFER_TYPE_DRM); + if (MPP_OK != ret) { + close(ctx->fd); + mpp_err("memGroup mpp_buffer_group_get failed\n"); + return ret; + } + + ret = mpp_buffer_get(ctx->memGroup, &ctx->mv_buf, + IEP2_TILE_W_MAX * IEP2_TILE_H_MAX); + if (ret) { + close(ctx->fd); + mpp_buffer_group_put(ctx->memGroup); + mpp_err_f("allocate mv buffer failed\n"); + return MPP_NOK; + } + + ret = mpp_buffer_get(ctx->memGroup, &ctx->md_buf, 1920 * 1088); + if (ret) { + close(ctx->fd); + mpp_buffer_group_put(ctx->memGroup); + mpp_buffer_put(ctx->mv_buf); + mpp_err_f("allocate md buffer failed\n"); + return MPP_NOK; + } + + ctx->params.mv_addr = mpp_buffer_get_fd(ctx->mv_buf); + ctx->params.md_addr = mpp_buffer_get_fd(ctx->md_buf); + + return MPP_OK; +} + +static MPP_RET iep2_deinit(IepCtx ictx) +{ + struct iep2_api_ctx *ctx = ictx; + + close(ctx->fd); + + if (ctx->mv_buf) { + mpp_buffer_put(ctx->mv_buf); + ctx->mv_buf = NULL; + } + + if (ctx->md_buf) { + mpp_buffer_put(ctx->md_buf); + ctx->md_buf = NULL; + } + + if (ctx->memGroup) { + mpp_buffer_group_put(ctx->memGroup); + ctx->memGroup = NULL; + } + + return MPP_OK; +} + +static MPP_RET iep2_done(struct iep2_api_ctx *ctx) +{ + iep_dbg_trace("deinterlace detect osd cnt %d, combo %d\n", + ctx->output.dect_osd_cnt, + ctx->output.out_osd_comb_cnt); + + if (ctx->params.dil_mode == IEP2_DIL_MODE_I5O2 || + ctx->params.dil_mode == IEP2_DIL_MODE_I5O1T || + ctx->params.dil_mode == IEP2_DIL_MODE_I5O1B) { + struct mv_list ls; + +#if IEP2_OSD_EN + iep2_set_osd(ctx, &ls); +#else + memset(&ls, 0, sizeof(struct mv_list)); +#endif + iep2_update_gmv(ctx, &ls); + iep2_check_ffo(ctx); + iep2_check_pd(ctx); + get_param_from_env(ctx); +#if 0 + if (ctx->params.roi_en && ctx->params.osd_area_num > 0) { + struct iep2_rect r; + + ctx->params.roi_layer_num = 0; + + r.x = 0; + r.y = 0; + r.w = ctx->params.tile_cols; + r.h = ctx->params.tile_rows; + iep2_set_roi(ctx, &r, ROI_MODE_MA); + + r.x = ctx->params.osd_x_sta[0]; + r.y = ctx->params.osd_y_sta[0]; + r.w = ctx->params.osd_x_end[0] - ctx->params.osd_x_sta[0]; + r.h = ctx->params.osd_y_end[0] - ctx->params.osd_y_sta[0]; + iep2_set_roi(ctx, &r, ROI_MODE_MA_MC); + } +#endif + } + + if (ctx->params.dil_mode == IEP2_DIL_MODE_DECT || + ctx->params.dil_mode == IEP2_DIL_MODE_PD) { + iep2_check_ffo(ctx); + iep2_check_pd(ctx); + get_param_from_env(ctx); + } + + if (ctx->pd_inf.pdtype != PD_TYPES_UNKNOWN) { + ctx->params.dil_mode = IEP2_DIL_MODE_PD; + ctx->params.pd_mode = iep2_pd_get_output(&ctx->pd_inf); + } else { + // TODO, revise others mode replace by I5O2 + //ctx->params.dil_mode = IEP2_DIL_MODE_I5O2; + } + + return 0; +} + +static void iep2_set_param(struct iep2_api_ctx *ctx, + union iep2_api_content *param, + enum IEP2_PARAM_TYPE type) +{ + switch (type) { + case IEP2_PARAM_TYPE_COM: + ctx->params.src_fmt = param->com.sfmt; + ctx->params.src_yuv_swap = param->com.sswap; + ctx->params.dst_fmt = param->com.dfmt; + ctx->params.dst_yuv_swap = param->com.dswap; + ctx->params.src_y_stride = param->com.hor_stride; + ctx->params.src_y_stride /= 4; + ctx->params.src_uv_stride = + param->com.sswap == IEP2_YUV_SWAP_P ? + (param->com.hor_stride / 2 + 15) / 16 * 16 : param->com.hor_stride; + ctx->params.src_uv_stride /= 4; + ctx->params.dst_y_stride = param->com.hor_stride; + ctx->params.dst_y_stride /= 4; + ctx->params.tile_cols = (param->com.width + 15) / 16; + ctx->params.tile_rows = (param->com.height + 3) / 4; + iep_dbg_trace("set tile size (%d, %d)\n", param->com.width, param->com.height); + ctx->params.osd_pec_thr = (param->com.width * 26) >> 7; + break; + case IEP2_PARAM_TYPE_MODE: + ctx->params.dil_mode = param->mode.dil_mode; + ctx->params.dil_out_mode = param->mode.out_mode; + ctx->params.dil_field_order = param->mode.dil_order; + + iep_dbg_trace("deinterlace, mode %d, out mode %d, dil_order %d\n", + param->mode.dil_mode, param->mode.out_mode, param->mode.dil_order); + + if (param->mode.dil_order == IEP2_FIELD_ORDER_UND) { + ctx->ff_inf.frm_offset = 6; + ctx->ff_inf.fie_offset = 0; + } else { + ctx->ff_inf.frm_offset = 0; + ctx->ff_inf.fie_offset = 10; + } + + if (param->mode.dil_order == IEP2_FIELD_ORDER_TFF) { + ctx->ff_inf.tff_offset = 3; + ctx->ff_inf.bff_offset = 0; + } else { + ctx->ff_inf.tff_offset = 0; + ctx->ff_inf.bff_offset = 3; + } + break; + case IEP2_PARAM_TYPE_MD: + ctx->params.md_theta = param->md.md_theta; + ctx->params.md_r = param->md.md_r; + ctx->params.md_lambda = param->md.md_lambda; + break; + case IEP2_PARAM_TYPE_DECT: + case IEP2_PARAM_TYPE_OSD: + case IEP2_PARAM_TYPE_ME: + case IEP2_PARAM_TYPE_EEDI: + case IEP2_PARAM_TYPE_BLE: + case IEP2_PARAM_TYPE_COMB: + break; + case IEP2_PARAM_TYPE_ROI: + ctx->params.roi_en = param->roi.roi_en; + break; + default: + ; + } +} + +static MPP_RET iep2_param_check(struct iep2_api_ctx *ctx) +{ + if (ctx->params.tile_cols <= 0 || ctx->params.tile_cols > IEP2_TILE_W_MAX || + ctx->params.tile_rows <= 0 || ctx->params.tile_rows > IEP2_TILE_H_MAX) { + mpp_err("invalidate size (%u, %u)\n", + ctx->params.tile_cols, ctx->params.tile_rows); + return MPP_NOK; + } + + return MPP_OK; +} + +static MPP_RET iep2_start(struct iep2_api_ctx *ctx) +{ + MPP_RET ret; + MppReqV1 mpp_req[2]; + + mpp_assert(ctx); + + mpp_req[0].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[0].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[0].size = sizeof(ctx->params); + mpp_req[0].offset = 0; + mpp_req[0].data_ptr = REQ_DATA_PTR(&ctx->params); + + mpp_req[1].cmd = MPP_CMD_SET_REG_READ; + mpp_req[1].flag = MPP_FLAGS_MULTI_MSG | MPP_FLAGS_LAST_MSG; + mpp_req[1].size = sizeof(ctx->output); + mpp_req[1].offset = 0; + mpp_req[1].data_ptr = REQ_DATA_PTR(&ctx->output); + + iep_dbg_func("in\n"); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req[0]); + + if (ret) { + mpp_err_f("ioctl SET_REG failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + + return ret; +} + +static MPP_RET iep2_wait(struct iep2_api_ctx *ctx) +{ + MppReqV1 mpp_req; + MPP_RET ret; + + memset(&mpp_req, 0, sizeof(mpp_req)); + mpp_req.cmd = MPP_CMD_POLL_HW_FINISH; + mpp_req.flag |= MPP_FLAGS_LAST_MSG; + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + + return ret; +} + +static inline void set_addr(struct iep2_addr *addr, IepImg *img) +{ + addr->y = img->mem_addr; + addr->cbcr = img->uv_addr; + addr->cr = img->v_addr; +} + +static MPP_RET iep2_control(IepCtx ictx, IepCmd cmd, void *iparam) +{ + struct iep2_api_ctx *ctx = ictx; + + switch (cmd) { + case IEP_CMD_SET_DEI_CFG: { + struct iep2_api_params *param = (struct iep2_api_params *)iparam; + + iep2_set_param(ctx, ¶m->param, param->ptype); + } + break; + case IEP_CMD_SET_SRC: + set_addr(&ctx->params.src[0], (IepImg *)iparam); + break; + case IEP_CMD_SET_DEI_SRC1: + set_addr(&ctx->params.src[1], (IepImg *)iparam); + break; + case IEP_CMD_SET_DEI_SRC2: + set_addr(&ctx->params.src[2], (IepImg *)iparam); + break; + case IEP_CMD_SET_DST: + set_addr(&ctx->params.dst[0], (IepImg *)iparam); + break; + case IEP_CMD_SET_DEI_DST1: + set_addr(&ctx->params.dst[1], (IepImg *)iparam); + break; + case IEP_CMD_RUN_SYNC: { + struct iep2_api_info *inf = (struct iep2_api_info*)iparam; + + if (0 > iep2_param_check(ctx)) + break; + if (0 > iep2_start(ctx)) + return MPP_NOK; + iep2_wait(ctx); + + if (ctx->params.dil_mode == IEP2_DIL_MODE_PD) { + ctx->params.dil_mode = IEP2_DIL_MODE_DECT; + if (0 > iep2_start(ctx)) + return MPP_NOK; + iep2_wait(ctx); + } + + // store current pd mode; + if (inf) + inf->pd_flag = ctx->params.pd_mode; + iep2_done(ctx); + if (inf) { + inf->dil_order = ctx->ff_inf.field_order; + inf->frm_mode = ctx->ff_inf.frm_mode; + inf->pd_types = ctx->pd_inf.pdtype; + inf->dil_order_confidence_ratio = ctx->ff_inf.fo_ratio_avg; + } + } + break; + default: + ; + } + + return MPP_OK; +} + +static MPP_RET iep2_reset(IepCtx ictx) +{ + struct iep2_api_ctx *ctx = ictx; + + memset(&ctx->ff_inf, 0, sizeof(ctx->ff_inf)); + + return MPP_OK; +} + +static iep_com_ops iep2_ops = { + .init = iep2_init, + .deinit = iep2_deinit, + .control = iep2_control, + .reset = iep2_reset, + .release = NULL, +}; + +iep_com_ctx* rockchip_iep2_api_alloc_ctx(void) +{ + iep_com_ctx *com_ctx = calloc(sizeof(*com_ctx), 1); + struct iep2_api_ctx *iep2_ctx = calloc(sizeof(*iep2_ctx), 1); + + mpp_assert(com_ctx && iep2_ctx); + + com_ctx->ops = &iep2_ops; + com_ctx->priv = iep2_ctx; + + return com_ctx; +} + +void rockchip_iep2_api_release_ctx(iep_com_ctx *com_ctx) +{ + if (com_ctx->priv) { + free(com_ctx->priv); + com_ctx->priv = NULL; + } + + free(com_ctx); +} + diff --git a/mpp/vproc/iep2/iep2.h b/mpp/vproc/iep2/iep2.h new file mode 100644 index 000000000..a60fd5e65 --- /dev/null +++ b/mpp/vproc/iep2/iep2.h @@ -0,0 +1,160 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP2_H +#define IEP2_H + +#include + +#include "rk_type.h" + +#include "iep2_pd.h" +#include "iep2_ff.h" + +#define TILE_W 16 +#define TILE_H 4 +#define MVL 28 +#define MVR 27 + +#define TEST_DBG //printf +#define FLOOR(v, r) (((v) / (r)) * (r)) + +#define RKCLIP(a, min, max) ((a < min) ? (min) : ((a > max) ? max : a)) +#define RKABS(a) (RK_U32)(((a) >= 0) ? (a) : -(a)) +#define RKMIN(a, b) (((a) < (b)) ? (a) : (b)) +#define RKMAX(a, b) (((a) > (b)) ? (a) : (b)) + +struct iep2_addr { + uint32_t y; + uint32_t cbcr; + uint32_t cr; +}; + +struct iep2_params { + uint32_t src_fmt; + uint32_t src_yuv_swap; + uint32_t dst_fmt; + uint32_t dst_yuv_swap; + uint32_t tile_cols; + uint32_t tile_rows; + uint32_t src_y_stride; + uint32_t src_uv_stride; + uint32_t dst_y_stride; + + struct iep2_addr src[3]; // current, next, previous + struct iep2_addr dst[2]; // top/bottom field reconstructed frame + uint32_t mv_addr; + uint32_t md_addr; + + uint32_t dil_mode; + uint32_t dil_out_mode; + uint32_t dil_field_order; + + uint32_t md_theta; + uint32_t md_r; + uint32_t md_lambda; + + uint32_t dect_resi_thr; + uint32_t osd_area_num; + uint32_t osd_gradh_thr; + uint32_t osd_gradv_thr; + + uint32_t osd_pos_limit_en; + uint32_t osd_pos_limit_num; + + uint32_t osd_limit_area[2]; + + uint32_t osd_line_num; + uint32_t osd_pec_thr; + + uint32_t osd_x_sta[8]; + uint32_t osd_x_end[8]; + uint32_t osd_y_sta[8]; + uint32_t osd_y_end[8]; + + uint32_t me_pena; + uint32_t mv_bonus; + uint32_t mv_similar_thr; + uint32_t mv_similar_num_thr0; + int32_t me_thr_offset; + + uint32_t mv_left_limit; + uint32_t mv_right_limit; + + int8_t mv_tru_list[8]; + uint32_t mv_tru_vld[8]; + + uint32_t eedi_thr0; + + uint32_t ble_backtoma_num; + + uint32_t comb_cnt_thr; + uint32_t comb_feature_thr; + uint32_t comb_t_thr; + uint32_t comb_osd_vld[8]; + + uint32_t mtn_en; + uint32_t mtn_tab[16]; + + uint32_t pd_mode; + + uint32_t roi_en; + uint32_t roi_layer_num; + uint32_t roi_mode[8]; + uint32_t xsta[8]; + uint32_t xend[8]; + uint32_t ysta[8]; + uint32_t yend[8]; +}; + +struct iep2_output { + uint32_t mv_hist[MVL + MVR + 1]; + uint32_t dect_pd_tcnt; + uint32_t dect_pd_bcnt; + uint32_t dect_ff_cur_tcnt; + uint32_t dect_ff_cur_bcnt; + uint32_t dect_ff_nxt_tcnt; + uint32_t dect_ff_nxt_bcnt; + uint32_t dect_ff_ble_tcnt; + uint32_t dect_ff_ble_bcnt; + uint32_t dect_ff_nz; + uint32_t dect_ff_comb_f; + uint32_t dect_osd_cnt; + uint32_t out_comb_cnt; + uint32_t out_osd_comb_cnt; + uint32_t ff_gradt_tcnt; + uint32_t ff_gradt_bcnt; + uint32_t x_sta[8]; + uint32_t x_end[8]; + uint32_t y_sta[8]; + uint32_t y_end[8]; +}; + +struct iep2_api_ctx { + struct iep2_params params; + struct iep2_output output; + /* output */ + struct iep2_ff_info ff_inf; + struct iep2_pd_info pd_inf; + + MppBufferGroup memGroup; + MppBuffer mv_buf; + MppBuffer md_buf; + int first_cfg; + int fd; +}; + +#endif diff --git a/mpp/vproc/iep2/iep2_ff.c b/mpp/vproc/iep2/iep2_ff.c new file mode 100644 index 000000000..421c0f1ea --- /dev/null +++ b/mpp/vproc/iep2/iep2_ff.c @@ -0,0 +1,159 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "iep2" + +#include +#include +#include + +#include "mpp_common.h" + +#include "iep2.h" +#include "iep2_api.h" +#include "iep2_ff.h" + +void iep2_check_ffo(struct iep2_api_ctx *ctx) +{ + RK_S32 tcnt = ctx->output.dect_pd_tcnt; + RK_S32 bcnt = ctx->output.dect_pd_bcnt; + RK_U32 tdiff = ctx->output.ff_gradt_tcnt + 1; + RK_U32 bdiff = ctx->output.ff_gradt_bcnt + 1; + RK_U32 ff00t = (ctx->output.dect_ff_cur_tcnt << 5) / tdiff; + RK_U32 ff00b = (ctx->output.dect_ff_cur_bcnt << 5) / bdiff; + RK_U32 ff11t = (ctx->output.dect_ff_nxt_tcnt << 5) / tdiff; + RK_U32 ff11b = (ctx->output.dect_ff_nxt_bcnt << 5) / bdiff; + RK_S32 ff0t1b = (ctx->output.dect_ff_ble_tcnt << 5) / bdiff; + RK_S32 ff0b1t = (ctx->output.dect_ff_ble_bcnt << 5) / bdiff; + + RK_U32 ff00 = RKMIN(ff00t, ff00b); + RK_U32 ff11 = RKMIN(ff11t, ff11b); + RK_U32 ffx = RKMIN(ff0t1b, ff0b1t); + RK_U32 ffi = RKMAX(ff00, ff11); + RK_U32 thr = ffx / 10; + RK_U32 field_diff_ratio = 0; + + iep_dbg_trace("deinterlace pd_cnt %d : %d, gradt cnt %d : %d, cur cnt %d : %d, nxt cnt %d : %d, ble 01:%d 10:%d", + tcnt, bcnt, tdiff, bdiff, ctx->output.ff_gradt_tcnt, ctx->output.ff_gradt_bcnt, + ctx->output.dect_ff_cur_tcnt, ctx->output.dect_ff_cur_bcnt, + ctx->output.dect_ff_nxt_tcnt, ctx->output.dect_ff_nxt_bcnt, + ctx->output.dect_ff_ble_tcnt, ctx->output.dect_ff_ble_bcnt); + + iep_dbg_trace("deinterlace tdiff %u, bdiff %u, ff00t %u, ff00b %u, ff11t %u ff11b %u ff0t1b %u ff0b1t %u, ff00 %d, ff11 %d, ffx %d, ffi %d thr %d\n", + tdiff, bdiff, ff00t, ff00b, ff11t, ff11b, ff0t1b, ff0b1t, ff00, ff11, ffx, ffi, thr); + + RK_S32 tff_score = 0; + RK_S32 bff_score = 0; + RK_S32 coef = 0; + RK_S32 frm_score = 0; + RK_S32 fie_score = 0; + + iep_dbg_trace("deinterlace cur %u, %u, nxt %u, %u, ble %u, %u, diff %u, %u, nz %u, f %u, comb %u\n", + ctx->output.dect_ff_cur_tcnt, ctx->output.dect_ff_cur_bcnt, + ctx->output.dect_ff_nxt_tcnt, ctx->output.dect_ff_nxt_bcnt, + ctx->output.dect_ff_ble_tcnt, ctx->output.dect_ff_ble_bcnt, + tdiff, bdiff, + ctx->output.dect_ff_nz, ctx->output.dect_ff_comb_f, + ctx->output.out_comb_cnt); + + if (ff00t > 120 || ff00b > 120) { + iep_dbg_trace("deinterlace check ffo abort at %d\n", __LINE__); + return; + } + + iep_dbg_trace("deinterlace ffi %u ffx %u\n", ffi, ffx); + + if (ffi <= 3 && ffx <= 3) { + iep_dbg_trace("deinterlace check ffo abort at %d\n", __LINE__); + return; + } + + coef = 2; + + if ((ffi * coef <= ffx) && (ffx - ffi * coef) > 2 * ffx / 10) { + ctx->ff_inf.frm_score = RKCLIP(ctx->ff_inf.frm_score + 1, 0, 20); + ctx->ff_inf.fie_score = RKCLIP(ctx->ff_inf.fie_score - 1, 0, 20); + } else { + ctx->ff_inf.frm_score = RKCLIP(ctx->ff_inf.frm_score - 1, 0, 20); + ctx->ff_inf.fie_score = RKCLIP(ctx->ff_inf.fie_score + 1, 0, 20); + } + + iep_dbg_trace("deinterlace (frm,fie) offset %d, %d, score %d, %d\n", + ctx->ff_inf.frm_offset, ctx->ff_inf.fie_offset, + ctx->ff_inf.frm_score, ctx->ff_inf.fie_score); + + frm_score = ctx->ff_inf.frm_score + ctx->ff_inf.frm_offset; + fie_score = ctx->ff_inf.fie_score + ctx->ff_inf.fie_offset; + + + if (RKABS(frm_score - fie_score) > 10) { + if (frm_score > fie_score) { + ctx->ff_inf.frm_mode = IEP2_FF_MODE_FRAME; + iep_dbg_trace("deinterlace frame mode\n"); + } else { + ctx->ff_inf.frm_mode = IEP2_FF_MODE_FIELD; + iep_dbg_trace("deinterlace field mode\n"); + } + } else { + ctx->ff_inf.frm_mode = IEP2_FF_MODE_UND; + iep_dbg_trace("deinterlace mode unknown\n"); + } + + if (tcnt <= 3 && bcnt <= 3) { + iep_dbg_trace("deinterlace check ffo abort at %d\n", __LINE__); + return; + } + + thr = (thr == 0) ? 1 : thr; + + // field order detection + field_diff_ratio = RKABS(ff0t1b - ff0b1t) / thr * 10; + ctx->ff_inf.fo_ratio_sum = ctx->ff_inf.fo_ratio_sum + field_diff_ratio - ctx->ff_inf.fo_ratio[ctx->ff_inf.fo_ratio_idx]; + ctx->ff_inf.fo_ratio[ctx->ff_inf.fo_ratio_idx] = field_diff_ratio; + ctx->ff_inf.fo_ratio_idx = (ctx->ff_inf.fo_ratio_idx + 1) % FIELD_ORDER_RATIO_SIZE; + + ctx->ff_inf.fo_ratio_cnt++; + ctx->ff_inf.fo_ratio_cnt = RKMIN(ctx->ff_inf.fo_ratio_cnt, FIELD_ORDER_RATIO_SIZE); + ctx->ff_inf.fo_ratio_avg = ctx->ff_inf.fo_ratio_sum / ctx->ff_inf.fo_ratio_cnt; + + if (field_diff_ratio > 10) { + if (ff0t1b > ff0b1t) { + ctx->ff_inf.tff_score = RKCLIP(ctx->ff_inf.tff_score + 1, 0, 10); + ctx->ff_inf.bff_score = RKCLIP(ctx->ff_inf.bff_score - 1, 0, 10); + } else { + ctx->ff_inf.tff_score = RKCLIP(ctx->ff_inf.tff_score - 1, 0, 10); + ctx->ff_inf.bff_score = RKCLIP(ctx->ff_inf.bff_score + 1, 0, 10); + } + } + + tff_score = ctx->ff_inf.tff_score + ctx->ff_inf.tff_offset; + bff_score = ctx->ff_inf.bff_score + ctx->ff_inf.bff_offset; + iep_dbg_trace("deinterlace ff score %d : %d, offset %d : %d\n", tff_score, bff_score, ctx->ff_inf.tff_offset, ctx->ff_inf.bff_offset); + + if (RKABS(tff_score - bff_score) > 5) { + if (tff_score > bff_score) { + iep_dbg_trace("deinterlace field order tff\n"); + ctx->ff_inf.field_order = IEP2_FIELD_ORDER_TFF; + } else { + iep_dbg_trace("deinterlace field order bff\n"); + ctx->ff_inf.field_order = IEP2_FIELD_ORDER_BFF; + } + } else { + iep_dbg_trace("deinterlace field order unknown\n"); + ctx->ff_inf.field_order = IEP2_FIELD_ORDER_UND; + } + +} diff --git a/mpp/vproc/iep2/iep2_ff.h b/mpp/vproc/iep2/iep2_ff.h new file mode 100644 index 000000000..566b674ef --- /dev/null +++ b/mpp/vproc/iep2/iep2_ff.h @@ -0,0 +1,53 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP2_FF_H +#define IEP2_FF_H + +#include "rk_type.h" + +#define FIELD_ORDER_RATIO_SIZE (10) +struct iep2_ff_info { + RK_S32 tff_offset; + RK_S32 bff_offset; + RK_S32 tff_score; + RK_S32 bff_score; + RK_S32 frm_offset; + RK_S32 fie_offset; + RK_S32 frm_score; + RK_S32 fie_score; + RK_U32 field_order; + RK_U32 frm_mode; + RK_U32 fo_ratio[FIELD_ORDER_RATIO_SIZE]; + RK_U32 fo_ratio_idx; + RK_U32 fo_ratio_cnt; + RK_U32 fo_ratio_sum; + RK_U32 fo_ratio_avg; +}; + +struct iep2_api_ctx; + +#ifdef __cplusplus +extern "C" { +#endif + +void iep2_check_ffo(struct iep2_api_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/vproc/iep2/iep2_gmv.c b/mpp/vproc/iep2/iep2_gmv.c new file mode 100644 index 000000000..9f857b722 --- /dev/null +++ b/mpp/vproc/iep2/iep2_gmv.c @@ -0,0 +1,127 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "iep2" + +#include +#include +#include + +#include "mpp_common.h" + +#include "iep2_api.h" +#include "iep2_gmv.h" + +static void iep2_sort(uint32_t bin[], int map[], int size) +{ + int i, m, n; + uint32_t *dat = malloc(size * sizeof(uint32_t)); + + for (i = 0; i < size; ++i) { + map[i] = i; + dat[i] = bin[i]; + } + + for (m = 0; m < size; ++m) { + int max = m; + uint32_t temp; + int p; + + for (n = m + 1; n < size; ++n) if (dat[n] > dat[max]) max = n; + // Put found minimum element in its place + temp = dat[m]; + p = map[m]; + + map[m] = map[max]; + map[max] = p; + dat[m] = dat[max]; + dat[max] = temp; + } + + free(dat); +} + +static int iep2_is_subt_mv(int mv, struct mv_list *mv_ls) +{ + int i; + + for (i = 0; i < mv_ls->idx; ++i) { + if (RKABS(mv_ls->mv[i] - (mv * 4)) < 3) + return 1; + } + + return 0; +} + +void iep2_update_gmv(struct iep2_api_ctx *ctx, struct mv_list *mv_ls) +{ + int rows = ctx->params.tile_rows; + int cols = ctx->params.tile_cols; + uint32_t *bin = ctx->output.mv_hist; + int lbin = MPP_ARRAY_ELEMS(ctx->output.mv_hist); + int i; + + int map[MPP_ARRAY_ELEMS(ctx->output.mv_hist)]; + + uint32_t r = 6; + + // print mvc histogram of current motion estimation. + for (i = 0; i < lbin; ++i) { + if (bin[i] == 0) + continue; + iep_dbg_trace("mv(%d) %d\n", i - MVL, bin[i]); + } + + bin[MVL] = 0; // disable 0 mv + + // update motion vector candidates + iep2_sort(bin, map, lbin); + + iep_dbg_trace("sort map:\n"); + if (0) { + for (i = 0; i < lbin; ++i) { + fprintf(stderr, "%d ", map[i]); + } + fprintf(stderr, "\n"); + } + + memset(ctx->params.mv_tru_list, 0, sizeof(ctx->params.mv_tru_list)); + memset(ctx->params.mv_tru_vld, 0, sizeof(ctx->params.mv_tru_vld)); + + // Get top 8 candidates of current motion estimation. + for (i = 0; i < 8; ++i) { + int8_t x = map[i] - MVL; + + if (bin[map[i]] > r * ((rows * cols) >> 7) || + iep2_is_subt_mv(x, mv_ls)) { + + // 1 bit at low endian for mv valid check + ctx->params.mv_tru_list[i] = x; + ctx->params.mv_tru_vld[i] = 1; + } else { + if (i == 0) { + ctx->params.mv_tru_list[0] = 0; + ctx->params.mv_tru_vld[0] = 1; + } + break; + } + } + + for (i = 0; i < 8; ++i) + iep_dbg_trace("new mv candidates list[%d] (%d,%d) %d\n", + i, ctx->params.mv_tru_list[i], 0, ctx->params.mv_tru_vld[i]); +} + diff --git a/mpp/vproc/iep2/iep2_gmv.h b/mpp/vproc/iep2/iep2_gmv.h new file mode 100644 index 000000000..77bd9301b --- /dev/null +++ b/mpp/vproc/iep2/iep2_gmv.h @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP2_GMV_H +#define IEP2_GMV_H + +#include "iep2.h" +#include "iep2_api.h" + +void iep2_update_gmv(struct iep2_api_ctx *ctx, struct mv_list *ls); + +#endif diff --git a/mpp/vproc/iep2/iep2_osd.c b/mpp/vproc/iep2/iep2_osd.c new file mode 100644 index 000000000..dab19e441 --- /dev/null +++ b/mpp/vproc/iep2/iep2_osd.c @@ -0,0 +1,181 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iep2_gmv.h" + +#include +#include +#include + +#include "mpp_common.h" +#include "mpp_buffer.h" + +#include "iep2_api.h" + +void iep2_sort(uint32_t bin[], uint32_t map[], int size) +{ + int i, m, n; + uint32_t *dat = malloc(size * sizeof(uint32_t)); + + for (i = 0; i < size; ++i) { + map[i] = i; + dat[i] = bin[i]; + } + + for (m = 0; m < size; ++m) { + int max = m; + uint32_t temp; + int p; + + for (n = m + 1; n < size; ++n) + if (dat[n] > dat[max]) + max = n; + // Put found minimum element in its place + temp = dat[m]; + p = map[m]; + + map[m] = map[max]; + map[max] = p; + dat[m] = dat[max]; + dat[max] = temp; + } + + free(dat); +} + +static int iep2_osd_check(int8_t *mv, int w, int sx, int ex, int sy, int ey, + int *mvx) +{ + /* (28 + 27) * 4 + 1 */ + uint32_t hist[221]; + uint32_t map[221]; + int total = (ey - sy + 1) * (ex - sx + 1); + int non_zero = 0; + int domin = 0; + int i, j; + + memset(hist, 0, sizeof(hist)); + + for (i = sy; i <= ey; ++i) { + for (j = sx; j <= ex; ++j) { + int8_t v = mv[i * w + j]; + uint32_t idx = v + 28 * 4; + + if (idx >= MPP_ARRAY_ELEMS(hist)) { + mpp_log("invalid mv at (%d, %d)\n", j, i); + continue; + } + hist[idx]++; + } + } + + non_zero = total - hist[28 * 4]; + + iep2_sort(hist, map, MPP_ARRAY_ELEMS(hist)); + + domin = hist[map[0]]; + if (map[0] + 1 < MPP_ARRAY_ELEMS(hist)) + domin += hist[map[0] + 1]; + if (map[0] >= 1) + domin += hist[map[0] - 1]; + + iep_dbg_trace("total tiles in current osd: %d, non-zero %d\n", + total, non_zero); + + if (domin * 4 < non_zero * 3) { + iep_dbg_trace("main mv %d count %d not dominant\n", + map[0] - 28 * 4, domin); + return 0; + } + + *mvx = map[0] - 28 * 4; + + return 1; +} + +void iep2_set_osd(struct iep2_api_ctx *ctx, struct mv_list *ls) +{ + uint32_t i, j; + int idx = 0; + + int sx[8]; + int ex[8]; + int sy[8]; + int ey[8]; + + uint32_t osd_tile_cnt = 0; + int mvx; + int8_t *pmv = mpp_buffer_get_ptr(ctx->mv_buf); + + memset(ls, 0, sizeof(*ls)); + + for (i = 0; i < ctx->output.dect_osd_cnt; ++i) { + sx[i] = ctx->output.x_sta[i]; + ex[i] = ctx->output.x_end[i]; + sy[i] = ctx->output.y_sta[i]; + ey[i] = ctx->output.y_end[i]; + } + + /* Hardware isn't supporting subtitle regions overlap. */ + for (i = 0; i < ctx->output.dect_osd_cnt; ++i) { + for (j = i + 1; j < ctx->output.dect_osd_cnt; ++j) { + if (sy[j] == ey[i]) { + if (ex[i] - sx[i] > ex[j] - sx[j]) { + sy[j]++; + } else { + ey[i]--; + } + } else { + break; + } + } + } + + for (i = 0; i < ctx->output.dect_osd_cnt; ++i) { + if (!iep2_osd_check(pmv, ctx->params.tile_cols, + sx[i], ex[i], sy[i], ey[i], &mvx)) + continue; + + ctx->params.osd_x_sta[idx] = sx[i]; + ctx->params.osd_x_end[idx] = ex[i]; + ctx->params.osd_y_sta[idx] = sy[i]; + ctx->params.osd_y_end[idx] = ey[i]; + + osd_tile_cnt += (ex[i] - sx[i] + 1) * (ey[i] - sy[i] + 1); + + ls->mv[idx] = mvx; + ls->vld[idx] = 1; + + iep_dbg_trace("[%d] from [%d,%d][%d,%d] to [%d,%d][%d,%d] mv %d\n", i, + sx[i], ex[i], sy[i], ey[i], + ctx->params.osd_x_sta[idx], ctx->params.osd_x_end[idx], + ctx->params.osd_y_sta[idx], ctx->params.osd_y_end[idx], + ls->mv[idx]); + idx++; + } + + ctx->params.osd_area_num = idx; + ls->idx = idx; + + iep_dbg_trace("osd tile count %d comb %d\n", + osd_tile_cnt, ctx->output.out_osd_comb_cnt); + if (osd_tile_cnt * 2 > ctx->output.out_osd_comb_cnt * 3) { + memset(ctx->params.comb_osd_vld, 0, sizeof(ctx->params.comb_osd_vld)); + } else { + memset(ctx->params.comb_osd_vld, 1, sizeof(ctx->params.comb_osd_vld)); + } +} + diff --git a/mpp/vproc/iep2/iep2_osd.h b/mpp/vproc/iep2/iep2_osd.h new file mode 100644 index 000000000..54cebef33 --- /dev/null +++ b/mpp/vproc/iep2/iep2_osd.h @@ -0,0 +1,27 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP2_OSD_H +#define IEP2_OSD_H + +#include "iep2.h" +#include "iep2_api.h" + +struct iep2_api_ctx; + +void iep2_set_osd(struct iep2_api_ctx *ctx, struct mv_list *ls); + +#endif diff --git a/mpp/vproc/iep2/iep2_pd.c b/mpp/vproc/iep2/iep2_pd.c new file mode 100644 index 000000000..cd5a90c5f --- /dev/null +++ b/mpp/vproc/iep2/iep2_pd.c @@ -0,0 +1,258 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iep2_pd.h" + +#include +#ifdef SIMULATE +#include +#endif +#include +#include + +#include "mpp_common.h" +#include "iep_common.h" + +#include "iep2.h" +#include "iep2_api.h" + +#define RKMIN(a, b) (((a) < (b)) ? (a) : (b)) +#define RKMAX(a, b) (((a) > (b)) ? (a) : (b)) + +#define PD_TS 1 // Top field unchanged, Bottom field changed +#define PD_BS 2 // Top filed changed, Bottom field unchanged +#define PD_DF 0 // Both fileds changed. +#define PD_ID 3 + +#define PD_FRAME_PERIOD 5 + +#define FIELD_DIFF_SUM_THR 32 + +static int pd_table[][PD_FRAME_PERIOD] = { + { PD_TS, PD_DF, PD_BS, PD_DF, PD_DF }, // 3:2:3:2 + { PD_DF, PD_BS, PD_DF, PD_TS, PD_DF }, // 2:3:2:3 + { PD_TS, PD_BS, PD_DF, PD_DF, PD_DF }, // 2:3:3:2 + { PD_BS, PD_DF, PD_DF, PD_TS, PD_DF }, // 3:2:2:3 + { PD_DF, PD_DF, PD_DF, PD_DF, PD_DF } // unknown +}; + +// field intensity table +static int sp_table[][PD_FRAME_PERIOD] = { + { 0, 1, 1, 0, 0 }, + { 0, 0, 1, 1, 0 }, + { 0, 1, 0, 0, 0 }, + { 0, 1, 1, 1, 0 }, + { 1, 1, 1, 1, 1 } +}; + +static int fp_table[][PD_FRAME_PERIOD] = { + { 1, 1, 1, 0, 0 }, + { 0, 1, 1, 1, 0 }, + { 0, 1, 1, 0, 0 }, + { 1, 1, 1, 1, 0 }, + { 1, 1, 1, 1, 1 } +}; + +static char* pd_titles[] = { + "PULLDOWN 3:2:3:2", + "PULLDOWN 2:3:2:3", + "PULLDOWN 2:3:3:2", + "PULLDOWN 3:2:2:3", + "PULLDOWN UNKNOWN" +}; + +void iep2_check_pd(struct iep2_api_ctx *ctx) +{ + struct iep2_pd_info *pd_inf = &ctx->pd_inf; + int tcnt = ctx->output.dect_pd_tcnt; + int bcnt = ctx->output.dect_pd_bcnt; + int tdiff = ctx->output.ff_gradt_tcnt + 1; + int bdiff = ctx->output.ff_gradt_bcnt + 1; + int idx = pd_inf->i % PD_FRAME_PERIOD; + int ff00t = (ctx->output.dect_ff_cur_tcnt << 5) / tdiff; + int ff00b = (ctx->output.dect_ff_cur_bcnt << 5) / bdiff; + int nz = ctx->output.dect_ff_nz + 1; + int f = ctx->output.dect_ff_comb_f; + size_t i, j; + + pd_inf->spatial[idx] = RKMIN(ff00t, ff00b); + pd_inf->temporal[idx] = (tcnt < FIELD_DIFF_SUM_THR) | ((bcnt < FIELD_DIFF_SUM_THR) << 1); + pd_inf->fcoeff[idx] = f * 100 / nz; + + iep_dbg_trace("pd tcnt %d bcnt %d\n", tcnt, bcnt); + iep_dbg_trace("temporal(%d, %d) %d %d %d %d %d\n", + idx, pd_inf->step, + pd_inf->temporal[0], + pd_inf->temporal[1], + pd_inf->temporal[2], + pd_inf->temporal[3], + pd_inf->temporal[4]); + iep_dbg_trace("spatial(%d, %d) %d %d %d %d %d\n", + idx, pd_inf->step, + pd_inf->spatial[0], + pd_inf->spatial[1], + pd_inf->spatial[2], + pd_inf->spatial[3], + pd_inf->spatial[4]); + iep_dbg_trace("fcoeff(%d, %d) %d %d %d %d %d\n", + idx, pd_inf->step, + pd_inf->fcoeff[0], + pd_inf->fcoeff[1], + pd_inf->fcoeff[2], + pd_inf->fcoeff[3], + pd_inf->fcoeff[4]); + + if (pd_inf->pdtype != PD_TYPES_UNKNOWN && pd_inf->step != -1) { + int n = (int)pd_inf->pdtype; + int type = pd_table[n][(pd_inf->step + 1) % 5]; + + if ((type == PD_TS && !(tcnt < FIELD_DIFF_SUM_THR)) || + (type == PD_BS && !(bcnt < FIELD_DIFF_SUM_THR))) { + pd_inf->pdtype = PD_TYPES_UNKNOWN; + pd_inf->step = -1; + } + } + + pd_inf->step = pd_inf->step != -1 ? (pd_inf->step + 1) % 5 : -1; + + if (pd_inf->pdtype != PD_TYPES_UNKNOWN) { + pd_inf->i++; + return; + } else { + iep_dbg_trace("pulldown recheck start: old type %s\n", pd_titles[pd_inf->pdtype]); + } + + for (i = 0; i < MPP_ARRAY_ELEMS(pd_table); ++i) { + if (pd_inf->temporal[idx] == pd_table[i][0] && + pd_inf->temporal[(idx + 1) % 5] == pd_table[i][1] && + pd_inf->temporal[(idx + 2) % 5] == pd_table[i][2] && + pd_inf->temporal[(idx + 3) % 5] == pd_table[i][3] && + pd_inf->temporal[(idx + 4) % 5] == pd_table[i][4]) { + + iep_dbg_trace("[%d] match %s, current idx %d\n", i, pd_titles[i], idx % PD_FRAME_PERIOD); + + if (i != PD_TYPES_UNKNOWN) { + int vmax = 0x7fffffff; + int vmin = 0; + int fmax = 0x7fffffff; + int fmin = 0; + + iep_dbg_trace("get pulldown type %s\n", pd_titles[i]); + + for (j = 0; j < MPP_ARRAY_ELEMS(sp_table[i]); ++j) { + if (sp_table[i][j] == 1) { + vmax = RKMIN(vmax, pd_inf->spatial[j]); + } else { + vmin = RKMAX(vmin, pd_inf->spatial[j]); + } + } + + for (j = 0; j < MPP_ARRAY_ELEMS(fp_table[i]); ++j) { + if (fp_table[i][j] == 1) { + fmax = RKMIN(fmax, pd_inf->fcoeff[(idx + j) % 5]); + } else { + fmin = RKMAX(fmin, pd_inf->fcoeff[(idx + j) % 5]); + } + } + + if (vmax > vmin || fmax > fmin) { + pd_inf->pdtype = i; + + if (i == PD_TYPES_3_2_2_3 && pd_inf->spatial[1] > RKMAX(pd_inf->spatial[0], + pd_inf->spatial[4])) { + pd_inf->pdtype = PD_TYPES_3_2_3_2; + } + + iep_dbg_trace("confirm pulldown type %s\n", pd_titles[i]); + pd_inf->step = 0; + } + } + break; + } + } + + pd_inf->i++; +} + +char *PD_COMP_STRING[] = { + "PD_COMP_CC", + "PD_COMP_CN", + "PD_COMP_NC", + "PD_COMP_NON" +}; + +/** + * @brief get pulldown compose flag + * + * @param pd_inf + * @return int see @PD_COMP_STRING + */ +int iep2_pd_get_output(struct iep2_pd_info *pd_inf) +{ + int flag = PD_COMP_FLAG_CC; + int step = (pd_inf->step + 1) % 5; + + switch (pd_inf->pdtype) { + case PD_TYPES_3_2_3_2: + switch (step) { + case 1: + flag = PD_COMP_FLAG_NC; + break; + case 2: + flag = PD_COMP_FLAG_NON; + break; + } + break; + case PD_TYPES_2_3_2_3: + switch (step) { + case 2: + flag = PD_COMP_FLAG_CN; + break; + case 3: + flag = PD_COMP_FLAG_NON; + break; + } + break; + case PD_TYPES_2_3_3_2: + switch (step) { + case 2: + flag = PD_COMP_FLAG_NON; + break; + } + break; + case PD_TYPES_3_2_2_3: + switch (step) { + case 1: + case 2: + flag = PD_COMP_FLAG_CN; + break; + case 3: + flag = PD_COMP_FLAG_NON; + break; + } + break; + default: + mpp_log("unsupport telecine format %s\n", + pd_titles[(int)pd_inf->pdtype]); + return -1; + } + + iep_dbg_trace("-------------------------------------------------\n"); + iep_dbg_trace("step %d, idx %d, flag %s\n", + pd_inf->step, pd_inf->i, PD_COMP_STRING[flag]); + + return flag; +} diff --git a/mpp/vproc/iep2/iep2_pd.h b/mpp/vproc/iep2/iep2_pd.h new file mode 100644 index 000000000..23dd8f5af --- /dev/null +++ b/mpp/vproc/iep2/iep2_pd.h @@ -0,0 +1,34 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP2_PD_H +#define IEP2_PD_H + +struct iep2_pd_info { + int temporal[5]; + int spatial[5]; + int fcoeff[5]; + int i; + int pdtype; + int step; +}; + +struct iep2_api_ctx; + +void iep2_check_pd(struct iep2_api_ctx *ctx); +int iep2_pd_get_output(struct iep2_pd_info *pd_inf); + +#endif diff --git a/osal/window/os_log.c b/mpp/vproc/iep2/iep2_roi.c similarity index 50% rename from osal/window/os_log.c rename to mpp/vproc/iep2/iep2_roi.c index d6db74ca9..d0ec11757 100644 --- a/osal/window/os_log.c +++ b/mpp/vproc/iep2/iep2_roi.c @@ -1,5 +1,5 @@ /* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * Copyright 2020 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,22 +14,26 @@ * limitations under the License. */ +#include "iep2_roi.h" + #include -#include +#include +#include -#define LINE_SZ 1024 +#include "iep2_api.h" -void os_log(const char* tag, const char* msg, va_list list) +void iep2_set_roi(struct iep2_api_ctx *ctx, struct iep2_rect *r, + enum ROI_MODE mode) { - char line[LINE_SZ] = {0}; - _snprintf(line, sizeof(line), "%s: %s", tag, msg); - vfprintf(stdout, line, list); -} + int idx = ctx->params.roi_layer_num; -void os_err(const char* tag, const char* msg, va_list list) -{ - char line[LINE_SZ] = {0}; - _snprintf(line, sizeof(line), "%s: %s", tag, msg); - vfprintf(stderr, line, list); -} + ctx->params.roi_en = 1; + + ctx->params.xsta[idx] = r->x; + ctx->params.ysta[idx] = r->y; + ctx->params.xend[idx] = r->x + r->w - 1; + ctx->params.yend[idx] = r->y + r->h - 1; + ctx->params.roi_mode[idx] = mode; + ctx->params.roi_layer_num++; +} diff --git a/mpp/vproc/iep2/iep2_roi.h b/mpp/vproc/iep2/iep2_roi.h new file mode 100644 index 000000000..2effac5f6 --- /dev/null +++ b/mpp/vproc/iep2/iep2_roi.h @@ -0,0 +1,47 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP2_ROI_H +#define IEP2_ROI_H + +#include "iep2.h" + +struct iep2_api_ctx; + +struct iep2_rect { + int x; + int y; + int w; + int h; +}; + +enum ROI_MODE { + ROI_MODE_NORMAL, + ROI_MODE_BYPASS, + ROI_MODE_SPATIAL, + ROI_MODE_MA, + ROI_MODE_MA_MC, + ROI_MODE_MC_SPATIAL, + ROI_MODE_RESERVED0, + ROI_MODE_RESERVED1, + ROI_MODE_RESERVED2, + ROI_MODE_SPEC_MC +}; + +void iep2_set_roi(struct iep2_api_ctx *ctx, struct iep2_rect *r, + enum ROI_MODE mode); + +#endif diff --git a/mpp/vproc/iep2/test/CMakeLists.txt b/mpp/vproc/iep2/test/CMakeLists.txt new file mode 100644 index 000000000..437738a42 --- /dev/null +++ b/mpp/vproc/iep2/test/CMakeLists.txt @@ -0,0 +1,12 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# mpp/vproc/iep2 built-in unit test case +# ---------------------------------------------------------------------------- +# iep2 unit test +option(IEP2_TEST "Build base iep2 unit test" ${BUILD_TEST}) +if (IEP2_TEST) + add_executable(iep2_test iep2_test.c) + target_link_libraries(iep2_test ${MPP_SHARED} utils) + set_target_properties(iep2_test PROPERTIES FOLDER "mpp/vproc/iep2") + add_test(NAME iep2_test COMMAND iep2_test) +endif() diff --git a/mpp/vproc/iep2/test/iep2_test.c b/mpp/vproc/iep2/test/iep2_test.c new file mode 100644 index 000000000..286cea642 --- /dev/null +++ b/mpp/vproc/iep2/test/iep2_test.c @@ -0,0 +1,453 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "iep2_test" + +#include + +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" +#include "mpp_buffer.h" + +#include "iep2_api.h" +#include "utils.h" +//#include "iniparser.h" + +#define MAX_URL_LEN (100) + +typedef struct iep2_test_cfg_t { + RK_S32 w; + RK_S32 h; + RK_S32 src_fmt; + RK_S32 src_swa; + + RK_S32 dst_fmt; + RK_S32 dst_swa; + + char src_url[MAX_URL_LEN]; + char dst_url[MAX_URL_LEN]; + char slt_url[MAX_URL_LEN]; + + FILE *fp_src; + FILE *fp_dst; + FILE *fp_slt; + RK_U32 field_order; +} iep2_test_cfg; + +static OptionInfo iep2_test_cmd[] = { + {"w", "width", "input image width"}, + {"h", "height", "input image height"}, + {"c", "format", "input image format in ASCII string"}, + {"i", "src_file", "input image file name"}, + {"C", "dst_format", "output image format in ASCII string"}, + {"o", "dst_file", "output image file name"}, + {"v", "slt_file", "slt verify data file"} +}; + +static void iep2_test_help() +{ + mpp_log("usage: iep2_test [options]\n"); + mpp_log("*******************************\n"); + show_options(iep2_test_cmd); + mpp_log("*******************************\n"); + mpp_log("supported ASCII format strings:\n"); + mpp_log("1 - yuv422sp\n"); + mpp_log("2 - yuv422p [just for source format]\n"); + mpp_log("3 - yuv420sp\n"); + mpp_log("4 - yuv420p [just for source format]\n"); + mpp_log("5 - yvu422sp\n"); + mpp_log("6 - yvu420sp\n"); + mpp_log("************ sample ***********\n"); + mpp_log("iep2_test -w 720 -h 480 -c yuv420p -i input.yuv -C yuv420p -o output.yuv\n"); +} + +static RK_S32 str_to_iep2_fmt(const char *str) +{ + RK_S32 fmt = -1; + + mpp_log("format %s\n", str); + + if (!strcmp(str, "yuv422sp") || + !strcmp(str, "yuv422p") || + !strcmp(str, "yvu422sp")) + fmt = IEP2_FMT_YUV422; + else if (!strcmp(str, "yuv420p") || + !strcmp(str, "yuv420sp") || + !strcmp(str, "yvu420sp")) + fmt = IEP2_FMT_YUV420; + else + mpp_err("invalid format %s\n", str); + + return fmt; +} + +static RK_S32 str_to_iep2_swa(const char *str) +{ + RK_S32 swa = -1; + + if (!strcmp(str, "yuv422p") || + !strcmp(str, "yuv420p")) + swa = IEP2_YUV_SWAP_P; + else if (!strcmp(str, "yvu422sp") || + !strcmp(str, "yvu420sp")) + swa = IEP2_YUV_SWAP_SP_VU; + else if (!strcmp(str, "yuv422sp") || + !strcmp(str, "yuv420sp")) + swa = IEP2_YUV_SWAP_SP_UV; + else + mpp_err("invalid format %s\n", str); + + return swa; +} + +static MPP_RET check_input_cmd(iep2_test_cfg *cfg) +{ + MPP_RET ret = MPP_OK; + + if (cfg->w < 16 || cfg->w > 1920) { + mpp_err("invalid width %d\n", cfg->w); + ret = MPP_NOK; + } + + if (cfg->h < 4 || cfg->h > 1088) { + mpp_err("invalid height %d\n", cfg->h); + ret = MPP_NOK; + } + + mpp_log("src fmt %d, %d dst fmt %d, %d\n", + cfg->src_fmt, cfg->src_swa, + cfg->dst_fmt, cfg->dst_swa); + + if (cfg->src_fmt < IEP2_FMT_YUV422 || + cfg->src_fmt > IEP2_FMT_YUV420 || + cfg->src_swa < IEP2_YUV_SWAP_SP_UV || + cfg->src_swa > IEP2_YUV_SWAP_P) { + mpp_err("invalid input format\n"); + ret = MPP_NOK; + } + + if (cfg->fp_src == NULL) { + mpp_err("failed to open input file %s\n", cfg->src_url); + ret = MPP_NOK; + } + + if (cfg->dst_fmt < IEP2_FMT_YUV422 || + cfg->dst_fmt > IEP2_FMT_YUV420 || + cfg->dst_swa < IEP2_YUV_SWAP_SP_UV || + cfg->dst_swa > IEP2_YUV_SWAP_SP_VU) { + mpp_err("invalid output format\n"); + ret = MPP_NOK; + } + + return ret; +} + +static inline size_t get_frm_size(RK_S32 fmt, int w, int h) +{ + switch (fmt) { + case IEP2_FMT_YUV422: + return w * h * 2; + case IEP2_FMT_YUV420: + return w * h * 3 / 2; + default: + abort(); + return 0; + } +} + +static void iep2_test_set_img(iep_com_ctx *ctx, int w, int h, + IepImg *img, RK_S32 fd, IepCmd cmd) +{ + RK_S32 y_size = w * h; + img->mem_addr = fd; + img->uv_addr = fd + (y_size << 10); + switch (img->format) { + case IEP2_FMT_YUV422: + img->v_addr = fd + ((y_size + y_size / 2) << 10); + break; + case IEP2_FMT_YUV420: + img->v_addr = fd + ((y_size + y_size / 4) << 10); + break; + default: + break; + } + + MPP_RET ret = ctx->ops->control(ctx->priv, cmd, img); + if (ret) + mpp_log_f("control %08x failed %d\n", cmd, ret); +} + +void iep2_test(iep2_test_cfg *cfg) +{ + iep_com_ctx* iep2 = rockchip_iep2_api_alloc_ctx(); + size_t srcfrmsize = get_frm_size(cfg->src_fmt, cfg->w, cfg->h); + size_t dstfrmsize = get_frm_size(cfg->dst_fmt, cfg->w, cfg->h); + MppBuffer srcbuf[3]; + MppBuffer dstbuf[2]; + RK_U8 *psrc[3]; + RK_U8 *pdst[2]; + RK_S32 fdsrc[3]; + RK_S32 fddst[2]; + int prev, curr, next; + struct iep2_api_params params; + RK_U32 i; + RK_S32 field_order = IEP2_FIELD_ORDER_TFF; + RK_S32 out_order = field_order == IEP2_FIELD_ORDER_TFF ? 0 : 1; + DataCrc checkcrc; + struct iep2_api_info dei_info; + + // NOTISE, used IepImg structure for version compatibility consideration, + // only addresses in this structure are useful in iep2 + IepImg imgsrc[3]; + IepImg imgdst[2]; + + mpp_assert(iep2); + MppBufferGroup memGroup; + MPP_RET ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_DRM); + if (MPP_OK != ret) { + mpp_err("memGroup mpp_buffer_group_get failed\n"); + mpp_assert(0); + } + + memset(&checkcrc, 0, sizeof(checkcrc)); + checkcrc.sum = mpp_malloc(RK_ULONG, 512); + + mpp_buffer_get(memGroup, &srcbuf[0], srcfrmsize); + mpp_buffer_get(memGroup, &srcbuf[1], srcfrmsize); + mpp_buffer_get(memGroup, &srcbuf[2], srcfrmsize); + mpp_buffer_get(memGroup, &dstbuf[0], dstfrmsize); + mpp_buffer_get(memGroup, &dstbuf[1], dstfrmsize); + mpp_assert(srcbuf[0] && srcbuf[1] && srcbuf[2] && dstbuf[0] && dstbuf[1]); + + psrc[0] = mpp_buffer_get_ptr(srcbuf[0]); + psrc[1] = mpp_buffer_get_ptr(srcbuf[1]); + psrc[2] = mpp_buffer_get_ptr(srcbuf[2]); + + pdst[0] = mpp_buffer_get_ptr(dstbuf[0]); + pdst[1] = mpp_buffer_get_ptr(dstbuf[1]); + + fdsrc[0] = mpp_buffer_get_fd(srcbuf[0]); + fdsrc[1] = mpp_buffer_get_fd(srcbuf[1]); + fdsrc[2] = mpp_buffer_get_fd(srcbuf[2]); + + fddst[0] = mpp_buffer_get_fd(dstbuf[0]); + fddst[1] = mpp_buffer_get_fd(dstbuf[1]); + + iep2->ops->init(&iep2->priv); + + if (srcfrmsize > fread(psrc[0], 1, srcfrmsize, cfg->fp_src)) { + mpp_log("source exhaused\n"); + goto ret; + } + + if (srcfrmsize > fread(psrc[1], 1, srcfrmsize, cfg->fp_src)) { + mpp_log("source exhaused\n"); + goto ret; + } + + curr = 1; + + // set running mode. + /* if deinterlacing mode is one in the following list: + IEP2_DIL_MODE_I5O2, + IEP2_DIL_MODE_I5O1T, + IEP2_DIL_MODE_I5O1B, + IEP2_DIL_MODE_DECT + field order will auto detect by iep2 library. + so don't try to set field order during the playback. + */ + params.ptype = IEP2_PARAM_TYPE_MODE; + params.param.mode.dil_mode = IEP2_DIL_MODE_I5O2; + params.param.mode.out_mode = IEP2_OUT_MODE_LINE; + params.param.mode.dil_order = cfg->field_order; + + iep2->ops->control(iep2->priv, IEP_CMD_SET_DEI_CFG, ¶ms); + + // set the image format. + params.ptype = IEP2_PARAM_TYPE_COM; + params.param.com.sfmt = cfg->src_fmt; + params.param.com.dfmt = cfg->dst_fmt; + params.param.com.sswap = cfg->src_swa; + params.param.com.dswap = cfg->dst_swa; + params.param.com.width = cfg->w; + params.param.com.height = cfg->h; + params.param.com.hor_stride = cfg->w; + iep2->ops->control(iep2->priv, IEP_CMD_SET_DEI_CFG, ¶ms); + + for (i = 0; i < MPP_ARRAY_ELEMS(imgsrc); i++) + imgsrc[i].format = cfg->src_fmt; + + for (i = 0; i < MPP_ARRAY_ELEMS(imgdst); i++) + imgdst[i].format = cfg->dst_fmt; + + while (1) { + prev = (curr - 1) % 3; + curr = curr % 3; + next = (curr + 1) % 3; + + if (srcfrmsize > fread(psrc[next], 1, srcfrmsize, cfg->fp_src)) { + mpp_log("source exhaused\n"); + break; + } + + // notice the order of the input frames. + iep2_test_set_img(iep2, cfg->w, cfg->h, + &imgsrc[curr], fdsrc[curr], IEP_CMD_SET_SRC); + iep2_test_set_img(iep2, cfg->w, cfg->h, + &imgsrc[next], fdsrc[next], IEP_CMD_SET_DEI_SRC1); + iep2_test_set_img(iep2, cfg->w, cfg->h, + &imgsrc[prev], fdsrc[prev], IEP_CMD_SET_DEI_SRC2); + iep2_test_set_img(iep2, cfg->w, cfg->h, + &imgdst[0], fddst[0], IEP_CMD_SET_DST); + iep2_test_set_img(iep2, cfg->w, cfg->h, + &imgdst[1], fddst[1], IEP_CMD_SET_DEI_DST1); + + memset(pdst[0], 0, dstfrmsize); + memset(pdst[1], 0, dstfrmsize); + iep2->ops->control(iep2->priv, IEP_CMD_RUN_SYNC, &dei_info); + + if (cfg->fp_slt) { + calc_data_crc(pdst[out_order], dstfrmsize, &checkcrc); + write_data_crc(cfg->fp_slt, &checkcrc); + calc_data_crc(pdst[1 - out_order], dstfrmsize, &checkcrc); + write_data_crc(cfg->fp_slt, &checkcrc); + } + + out_order = dei_info.dil_order == IEP2_FIELD_ORDER_BFF ? 1 : 0; + + if (cfg->fp_dst) { + if (dstfrmsize > fwrite(pdst[out_order], 1, dstfrmsize, cfg->fp_dst)) { + mpp_err("destination dump failed\n"); + break; + } + + if (dstfrmsize > fwrite(pdst[1 - out_order], 1, dstfrmsize, cfg->fp_dst)) { + mpp_err("destination dump failed\n"); + break; + } + } + + curr++; + } + +ret: + mpp_buffer_put(srcbuf[0]); + mpp_buffer_put(srcbuf[1]); + mpp_buffer_put(srcbuf[2]); + + mpp_buffer_put(dstbuf[0]); + mpp_buffer_put(dstbuf[1]); + + MPP_FREE(checkcrc.sum); + + if (memGroup) { + mpp_buffer_group_put(memGroup); + memGroup = NULL; + } + + iep2->ops->deinit(iep2->priv); + + rockchip_iep2_api_release_ctx(iep2); +} + +int main(int argc, char **argv) +{ + iep2_test_cfg cfg; + int ch; + + if (argc < 2) { + iep2_test_help(); + return 0; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.src_fmt = IEP2_FMT_YUV420; + cfg.src_swa = IEP2_YUV_SWAP_SP_UV; + cfg.dst_fmt = IEP2_FMT_YUV420; + cfg.dst_swa = IEP2_YUV_SWAP_SP_UV; + + /// get options + opterr = 0; + while ((ch = getopt(argc, argv, "i:w:h:c:o:C:v:f:")) != -1) { + switch (ch) { + case 'w': { + cfg.w = atoi(optarg); + } break; + case 'h': { + cfg.h = atoi(optarg); + } break; + case 'c': { + cfg.src_fmt = str_to_iep2_fmt(optarg); + cfg.src_swa = str_to_iep2_swa(optarg); + } break; + case 'C': { + cfg.dst_fmt = str_to_iep2_fmt(optarg); + cfg.dst_swa = str_to_iep2_swa(optarg); + } break; + case 'i': { + mpp_log("input filename: %s\n", optarg); + strncpy(cfg.src_url, optarg, sizeof(cfg.src_url) - 1); + cfg.fp_src = fopen(cfg.src_url, "rb"); + } break; + case 'o': { + mpp_log("output filename: %s\n", optarg); + strncpy(cfg.dst_url, optarg, sizeof(cfg.dst_url) - 1); + cfg.fp_dst = fopen(cfg.dst_url, "w+b"); + } break; + case 'v': { + mpp_log("verify file: %s\n", optarg); + strncpy(cfg.slt_url, optarg, sizeof(cfg.slt_url) - 1); + cfg.fp_slt = fopen(cfg.slt_url, "w+b"); + } break; + case 'f': { + if (!strcmp(optarg, "TFF")) + cfg.field_order = IEP2_FIELD_ORDER_TFF; + else + cfg.field_order = IEP2_FIELD_ORDER_BFF; + } break; + default: { + } break; + } + } + + if (check_input_cmd(&cfg)) { + mpp_err("failed to pass cmd line check\n"); + iep2_test_help(); + return -1; + } + + iep2_test(&cfg); + + if (cfg.fp_src) { + fclose(cfg.fp_src); + cfg.fp_src = NULL; + } + + if (cfg.fp_dst) { + fclose(cfg.fp_dst); + cfg.fp_dst = NULL; + } + + if (cfg.fp_slt) { + fclose(cfg.fp_slt); + cfg.fp_slt = NULL; + } + + return 0; +} diff --git a/mpp/vproc/inc/hwpq_vdpp_proc_api.h b/mpp/vproc/inc/hwpq_vdpp_proc_api.h new file mode 100644 index 000000000..7e5b6e743 --- /dev/null +++ b/mpp/vproc/inc/hwpq_vdpp_proc_api.h @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HWPQ_VDPP_PROC_API_H +#define HWPQ_VDPP_PROC_API_H + +/* version definition */ +#define HWPQ_VDPP_PROC_VERSION_HEX (0x01040100) /* [31:0] = [major:8-minor:8-patch:16] */ +#define HWPQ_VDPP_PROC_VERSION_STR "v1.4.1" + +/* hwpq vdpp color format definition */ +#define VDPP_FRAME_FMT_COLOR_MASK (0x000f0000) /* DEPRECATED */ +#define VDPP_FRAME_FMT_YUV (0x00000000) /* DEPRECATED */ +#define VDPP_FRAME_FMT_RGB (0x00010000) /* DEPRECATED */ + +#define VDPP_HIST_LENGTH (10240) +#define HWPQ_VDPP_SOC_NAME_LENGTH (128) + +typedef enum vdpp_frame_format { + // YUV + VDPP_FMT_YUV_MIN = 0, /* the min YUV format value, please DO NOT use this item! */ + VDPP_FMT_NV24 = 0, /* YUV444SP, 24bpp, YYYY...YYYY.../UVUVUVUV...UVUVUVUV... */ + VDPP_FMT_NV16, /* YUV422SP, 16bpp, YYYY...YYYY.../UVUV...UVUV... */ /* RESERVED */ + VDPP_FMT_NV12, /* YUV420SP, 12bpp, YYYY...YYYY.../UVUV... */ + VDPP_FMT_NV15, /* RESERVED */ + VDPP_FMT_NV20, /* RESERVED */ + VDPP_FMT_NV30, /* RESERVED */ + VDPP_FMT_P010, /* RESERVED */ + VDPP_FMT_P210, /* RESERVED */ + VDPP_FMT_Q410, /* RESERVED */ + VDPP_FMT_Y_ONLY_8BIT, /* Only 8bit-Y Plane, For VDPP y-uv diff mode output & DCI_HIST input */ + VDPP_FMT_UV_ONLY_8BIT, /* Only 8bit-UV Plane, For VDPP y-uv diff mode output */ + VDPP_FMT_NV42, /* YUV444SP, 24bpp, YYYY...YYYY.../VUVUVUVU...VUVUVUVU... */ + VDPP_FMT_NV61, /* YUV422SP, 16bpp, YYYY...YYYY.../VUVU...VUVU... */ /* RESERVED */ + VDPP_FMT_NV21, /* YUV420SP, 12bpp, YYYY...YYYY.../VUVU... */ + VDPP_FMT_YUV_MAX, /* the max YUV format value, please DO NOT use this item! */ + + // YUV format alias + VDPP_FMT_NV24_VU = VDPP_FMT_NV42, + VDPP_FMT_NV16_VU = VDPP_FMT_NV61, + VDPP_FMT_NV12_VU = VDPP_FMT_NV21, + + // RGB + VDPP_FMT_RGB_MIN = 1000,/* the min RGB format value, please DO NOT use this item! */ + VDPP_FMT_RGBA = 1000, /* RGBA8888, 32bpp */ + VDPP_FMT_RG24, /* RGB888, 24bpp */ + VDPP_FMT_BG24, /* BGR888, 24bpp */ + VDPP_FMT_AB30, /* ABGR2101010, RESERVED */ + VDPP_FMT_RGB_MAX, /* the max RGB format value, please DO NOT use this item! */ +} HwpqVdppFormat; + +typedef enum VdppRangeInfo { + VDPP_LIMIT_RANGE, + VDPP_FULL_RANGE, +} HwpqVdppRange; + +typedef enum VdppRunMode { + VDPP_RUN_MODE_UNSUPPORTED = -1, + VDPP_RUN_MODE_VEP = 0, + VDPP_RUN_MODE_HIST = 1, +} HwpqVdppRunMode; + +typedef struct vdpp_plane_info { + int fd; + void *addr; + int offset; + + int w_vld; // image width, unit: pixel + int h_vld; // image height, unit: pixel + int w_vir; // aligned width, unit: pixel + int h_vir; // aligned height, unit: pixel +} HwpqVdppPlaneInfo; + +typedef struct vdpp_img_info { + HwpqVdppPlaneInfo img_yrgb; + HwpqVdppPlaneInfo img_cbcr; + HwpqVdppFormat img_fmt; +} HwpqVdppImgInfo; + +/* vdpp module config */ +typedef struct vdpp_params { + /* vdpp 1 features */ + // dmsr config + unsigned int dmsr_en; // default: 0 + unsigned int str_pri_y; // default: 10 + unsigned int str_sec_y; // default: 4 + unsigned int dumping_y; // default: 6 + unsigned int reserve_dmsr[4]; + + // es config (vdpp2 feature) + unsigned int es_en; // default: 0 + unsigned int es_iWgtGain; // default: 128 + unsigned int reserve_es[4]; + + // zme config + unsigned int zme_dering_en; // default: 1 + unsigned int reserve_zme[4]; + + /* vdpp 2 features */ + // hist_cnt config + unsigned int hist_cnt_en; // default: 1 + unsigned int hist_csc_range; // default: VDPP_LIMIT_RANGE. see HwpqVdppRange + unsigned int hist_vsd_mode; // (RESERVED) range: [0, 2], default: -1, means auto calculate + unsigned int hist_hsd_mode; // (RESERVED) range: [0, 1], default: -1, means auto calculate + unsigned int reserve_hist_cnt[2]; + + // sharp config + unsigned int shp_en; // default: 0 + unsigned int peaking_gain; // default: 196 + unsigned int shp_shoot_ctrl_en; // default: 1 + unsigned int shp_shoot_ctrl_over; // default: 8 + unsigned int shp_shoot_ctrl_under; // default: 8 + unsigned int reserve_shp[4]; + + /* vdpp3 features */ + // pyramid config + unsigned int pyr_en; // default: 0 + HwpqVdppImgInfo pyr_layers[8]; // Only 3 layers of luma data is supported in vdpp3 + unsigned int reserve_pyr[8]; + + // black_bar_detect config + unsigned int bbd_en; // default: 0 + unsigned int bbd_threshold; // default: 20 for U8 Full-range. always consider as Full-range. + unsigned int reserve_bbd[8]; + + /* new features add here */ +} HwpqVdppConfig; + +typedef struct hwpq_vdpp_info_t { + void *p_hist_addr; + unsigned int hist_length; + unsigned short vdpp_img_w_in; + unsigned short vdpp_img_h_in; + unsigned short vdpp_img_w_out; + unsigned short vdpp_img_h_out; + unsigned short vdpp_blk_size_h; + unsigned short vdpp_blk_size_v; +} HwpqVdppDciInfo; + +typedef union hwpq_vdpp_output_t { + /* mean luma result */ + struct { + int luma_avg; // U10 range: [0, 1023]. <0 means invalid value. + HwpqVdppDciInfo dci_vdpp_info; // dci info for VOP + } hist; + + /* bbd result, unit: pixel */ + struct HwpqVdppBbdSize { + int bbd_size_top; // [0, H], <0 means invalid value. + int bbd_size_bottom; // [0, H], <0 means invalid value. + int bbd_size_left; // [0, W], <0 means invalid value. + int bbd_size_right; // [0, W], <0 means invalid value. + } bbd; +} HwpqVdppOutput; + +typedef struct rk_vdpp_proc_params { + unsigned int frame_idx; + unsigned int yuv_diff_flag; // 0:single buffer out, 1:two buffers(luma/chroma) out + unsigned int hist_mode_en; // DCI_HIST_ONLY mode. 0:disable, 1:enable(see vdpp_run_mode) + + /* buffer info */ + HwpqVdppImgInfo src_img_info; // input image info + HwpqVdppImgInfo dst_img_info; // output image info + unsigned int hist_buf_fd; // fd of hist buffer, NOTE the buffer size should be >= VDPP_HIST_LENGTH ! + void *p_hist_buf; // virtual address of hist buffer, DONOT set to NULL ! + + unsigned int vdpp_config_update_flag; // set this to 1 if needs to update 'vdpp_config' + HwpqVdppConfig vdpp_config; + + /* DEPRECATED, use 'hwpq_vdpp_run_cmd()' with corresponding argument instead! */ + HwpqVdppDciInfo dci_vdpp_info; /* DEPRECATED, arg: HWPQ_VDPP_CMD_GET_HIST_RESULT */ + HwpqVdppOutput output; /* DEPRECATED, arg: HWPQ_VDPP_CMD_GET_BBD_RESULT */ +} HwpqVdppParams; + +/* hwpq vdpp commands */ +typedef enum { + HWPQ_VDPP_CMD_INIT, /* RESERVED */ + + /* Get useful info from a context, use 'HwpqVdppQueryInfo' as data in 'hwpq_vdpp_run_cmd()' */ + HWPQ_VDPP_CMD_GET_VERSION, /* get vdpp version info */ + HWPQ_VDPP_CMD_GET_SOC_NAME, /* get platform soc name */ + HWPQ_VDPP_CMD_GET_PYR_MIN_SIZE, /* get minimal virtual size for each layer of PYR */ + + /* Get result from a context, use 'HwpqVdppOutput' as data in 'hwpq_vdpp_run_cmd()' */ + HWPQ_VDPP_CMD_GET_HIST_RESULT = 0x0100, /* get DCI info */ + HWPQ_VDPP_CMD_GET_BBD_RESULT, /* get BBD result */ + + /* Set module config to default values */ + HWPQ_VDPP_CMD_SET_DEF_CFG = 0x1000, /* set 'HwpqVdppConfig' to default values */ +} HwpqVdppCmd; + +/* hwpq vdpp query infos */ +typedef union vdpp_query_info { + /* common query info */ + struct { + char soc_name[HWPQ_VDPP_SOC_NAME_LENGTH]; + } platform; + + struct { + int vdpp_ver; // {0x100, 0x200, 0x300} + } version; + + /* query pyr minimal virtual size info, unit: pixel */ + struct { + int dst_width; // [I] set the dst width after ZME, unit: pixel + int dst_height; // [I] set the dst height after ZME, unit: pixel + int nb_layers; // [O] get the number of layers exclude the original layer, always be 3 for now! + int vir_widths[8]; // [O] output virtual widths of each layer, unit: pixel + int vir_heights[8]; // [O] output virtual heights of each layer, unit: pixel + } pyr; +} HwpqVdppQueryInfo; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void* rk_vdpp_context; /* DEPRECATED, use HwpqVdppContext instead */ +typedef rk_vdpp_context HwpqVdppContext; + +int hwpq_vdpp_init(HwpqVdppContext *p_ctx_ptr); +int hwpq_vdpp_check_work_mode(HwpqVdppContext ctx, const HwpqVdppParams *p_proc_param); +int hwpq_vdpp_proc(HwpqVdppContext ctx, HwpqVdppParams *p_proc_param); +int hwpq_vdpp_deinit(HwpqVdppContext ctx); + +/** + * | cmd | data type | data_size | + * | ------------------------------ | ----------------- | ------------------------- | + * | HWPQ_VDPP_CMD_GET_VERSION | HwpqVdppQueryInfo | sizeof(HwpqVdppQueryInfo) | + * | HWPQ_VDPP_CMD_GET_SOC_NAME | HwpqVdppQueryInfo | sizeof(HwpqVdppQueryInfo) | + * | HWPQ_VDPP_CMD_GET_PYR_MIN_SIZE | HwpqVdppQueryInfo | sizeof(HwpqVdppQueryInfo) | + * | HWPQ_VDPP_CMD_GET_HIST_RESULT | HwpqVdppOutput | sizeof(HwpqVdppOutput) | + * | HWPQ_VDPP_CMD_GET_BBD_RESULT | HwpqVdppOutput | sizeof(HwpqVdppOutput) | + * | HWPQ_VDPP_CMD_SET_DEF_CFG | HwpqVdppConfig | sizeof(HwpqVdppConfig) | + */ +int hwpq_vdpp_run_cmd(HwpqVdppContext ctx, HwpqVdppCmd cmd, void *data, int data_size, void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* HWPQ_VDPP_PROC_API_H */ diff --git a/mpp/vproc/inc/iep2_api.h b/mpp/vproc/inc/iep2_api.h new file mode 100644 index 000000000..e8c852298 --- /dev/null +++ b/mpp/vproc/inc/iep2_api.h @@ -0,0 +1,155 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP2_API_H +#define IEP2_API_H + +#include +#include + +#include "iep_common.h" + +enum IEP2_FIELD_ORDER { + IEP2_FIELD_ORDER_TFF, + IEP2_FIELD_ORDER_BFF, + IEP2_FIELD_ORDER_UND +}; + +enum IEP2_FF_MODE { + IEP2_FF_MODE_FRAME, + IEP2_FF_MODE_FIELD, + IEP2_FF_MODE_UND +}; + +enum IEP2_FMT { + IEP2_FMT_YUV422 = 2, + IEP2_FMT_YUV420 +}; + +enum IEP2_YUV_SWAP { + IEP2_YUV_SWAP_SP_UV, + IEP2_YUV_SWAP_SP_VU, + IEP2_YUV_SWAP_P0, + IEP2_YUV_SWAP_P +}; + +enum IEP2_DIL_MODE { + IEP2_DIL_MODE_DISABLE, + IEP2_DIL_MODE_I5O2, + IEP2_DIL_MODE_I5O1T, + IEP2_DIL_MODE_I5O1B, + IEP2_DIL_MODE_I2O2, + IEP2_DIL_MODE_I1O1T, + IEP2_DIL_MODE_I1O1B, + IEP2_DIL_MODE_PD, + IEP2_DIL_MODE_BYPASS, + IEP2_DIL_MODE_DECT +}; + +enum IEP2_OUT_MODE { + IEP2_OUT_MODE_LINE, + IEP2_OUT_MODE_TILE +}; + +enum IEP2_PARAM_TYPE { + IEP2_PARAM_TYPE_COM, + IEP2_PARAM_TYPE_MODE, + IEP2_PARAM_TYPE_MD, + IEP2_PARAM_TYPE_DECT, + IEP2_PARAM_TYPE_OSD, + IEP2_PARAM_TYPE_ME, + IEP2_PARAM_TYPE_EEDI, + IEP2_PARAM_TYPE_BLE, + IEP2_PARAM_TYPE_COMB, + IEP2_PARAM_TYPE_ROI +}; + +// Pulldown compose flag +enum PD_COMP_FLAG { + PD_COMP_FLAG_CC, + PD_COMP_FLAG_CN, + PD_COMP_FLAG_NC, + PD_COMP_FLAG_NON +}; + +enum PD_TYPES { + PD_TYPES_3_2_3_2, + PD_TYPES_2_3_2_3, + PD_TYPES_2_3_3_2, + PD_TYPES_3_2_2_3, + PD_TYPES_UNKNOWN +}; + +union iep2_api_content { + struct { + enum IEP2_FMT sfmt; + enum IEP2_YUV_SWAP sswap; + enum IEP2_FMT dfmt; + enum IEP2_YUV_SWAP dswap; + int width; + int height; + int hor_stride; + } com; + + struct { + enum IEP2_DIL_MODE dil_mode; + enum IEP2_OUT_MODE out_mode; + enum IEP2_FIELD_ORDER dil_order; + enum IEP2_FF_MODE ff_mode; + } mode; + + struct { + uint32_t md_theta; + uint32_t md_r; + uint32_t md_lambda; + } md; + + struct { + uint32_t roi_en; + } roi; +}; + +struct iep2_api_params { + enum IEP2_PARAM_TYPE ptype; + union iep2_api_content param; +}; + +struct iep2_api_info { + enum IEP2_FIELD_ORDER dil_order; + enum IEP2_FF_MODE frm_mode; + enum PD_TYPES pd_types; + enum PD_COMP_FLAG pd_flag; + RK_U32 dil_order_confidence_ratio; +}; + +struct mv_list { + int mv[8]; + int vld[8]; + int idx; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +iep_com_ctx* rockchip_iep2_api_alloc_ctx(void); +void rockchip_iep2_api_release_ctx(iep_com_ctx *com_ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mpp/vproc/inc/iep_api.h b/mpp/vproc/inc/iep_api.h new file mode 100644 index 000000000..58f16cbac --- /dev/null +++ b/mpp/vproc/inc/iep_api.h @@ -0,0 +1,181 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP_API_H +#define IEP_API_H + +#include "rk_type.h" +#include "mpp_err.h" + +#include "iep_common.h" + +/* + * IepCmdParamSetSrc is parameter for: + * IEP_CMD_SET_SRC + * IEP_CMD_SET_DST + * IEP_CMD_SET_DEI_SRC1 + * IEP_CMD_SET_DEI_DST1 + */ +typedef struct IepCmdParamImage_t { + IepImg image; +} IepCmdParamImage; + +typedef enum IepDeiMode_e { + IEP_DEI_MODE_DISABLE, + IEP_DEI_MODE_I2O1, + IEP_DEI_MODE_I4O1, + IEP_DEI_MODE_I4O2, + IEP_DEI_MODE_BYPASS, + IEP_DEI_MODE_BUTT, +} IepDeiMode; + +typedef enum IepDeiFldOrder { + IEP_DEI_FLD_ORDER_TOP_FIRST, + IEP_DEI_FLD_ORDER_BOT_FIRST, + IEP_DEI_FLD_ORDER_BUTT, +} IepDeiFldOrder; + +/* IepCmdParamDeiCfg is parameter for IEP_CMD_SET_DEI_CFG */ +typedef struct IepCmdParamDeiCfg_t { + IepDeiMode dei_mode; + IepDeiFldOrder dei_field_order; + + RK_U32 dei_high_freq_en; + RK_U32 dei_high_freq_fct; // [0, 127] + + RK_U32 dei_ei_mode; // deinterlace edge interpolation 0: disable, 1: enable + RK_U32 dei_ei_smooth; // deinterlace edge interpolation for smooth effect 0: disable, 1: enable + RK_U32 dei_ei_sel; // deinterlace edge interpolation select + RK_U32 dei_ei_radius; // deinterlace edge interpolation radius [0, 3] +} IepCmdParamDeiCfg; + +typedef enum IepVideoMode_e { + IEP_VIDEO_MODE_BLACK_SCREEN, + IEP_VIDEO_MODE_BLUE_SCREEN, + IEP_VIDEO_MODE_COLOR_BAR, + IEP_VIDEO_MODE_NORMAL_VIDEO +} IepVideoMode; + +/* IepCmdParamYuvEnhance is parameter for IEP_CMD_SET_YUV_ENHANCE */ +typedef struct IepCmdParamYuvEnhance_t { + float saturation; // [0, 1.992] + float contrast; // [0, 1.992] + RK_S8 brightness; // [-32, 31] + float hue_angle; // [-30, 30] + IepVideoMode video_mode; + RK_U8 color_bar_y; // [0, 127] + RK_U8 color_bar_u; // [0, 127] + RK_U8 color_bar_v; // [0, 127] +} IepCmdParamYuvEnhance; + +typedef enum IepRgbEnhanceMode_e { + IEP_RGB_ENHANCE_MODE_NO_OPERATION, + IEP_RGB_ENHANCE_MODE_DENOISE, + IEP_RGB_ENHANCE_MODE_DETAIL_ENHANCE, + IEP_RGB_ENHANCE_MODE_EDGE_ENHANCE +} IepRgbEnhanceMode; + +typedef enum IepRgbEnhanceOrder_e { + IEP_RGB_ENHANCE_ORDER_CG_DDE, // CG(Contrast & Gammar) prior to DDE (De-noise, Detail & Edge Enhance) + IEP_RGB_ENHANCE_ORDER_DDE_CG // DDE prior to CG +} IepRgbEnhanceOrder; + +/* IepCmdParamRgbEnhance is parameter for IEP_CMD_SET_RGB_ENHANCE */ +typedef struct IepCmdParamRgbEnhance { + float coe; // [0, 3.96875] + IepRgbEnhanceMode mode; + RK_U8 cg_en; // sw_rgb_con_gam_en + double cg_rr; + double cg_rg; + double cg_rb; + IepRgbEnhanceOrder order; + + /// more than this value considered as detail, and less than this value considered as noise. + RK_S32 threshold; // [0, 255] + + /// combine the original pixel and enhanced pixel + /// if (enh_alpha_num / enh_alpha_base <= 1 ) enh_alpha_base = 8, else enh_alpha_base = 4 + /// (1/8 ... 8/8) (5/4 ... 24/4) + RK_S32 alpha_num; // [0, 24] + RK_S32 alpha_base; // {4, 8} + RK_S32 radius; // [1, 4] +} IepCmdParamRgbEnhance; + +typedef enum IepScaleAlg_e { + IEP_SCALE_ALG_HERMITE, + IEP_SCALE_ALG_SPLINE, + IEP_SCALE_ALG_CATROM, + IEP_SCALE_ALG_MITCHELL +} IepScaleAlg; + +/* IepCmdParamScale is parameter for IEP_CMD_SET_SCALE */ +typedef struct IepCmdParamScale_t { + IepScaleAlg scale_alg; +} IepCmdParamScale; + +typedef enum IepColorConvertMode_e { + IEP_COLOR_MODE_BT601_L, + IEP_COLOR_MODE_BT601_F, + IEP_COLOR_MODE_BT709_L, + IEP_COLOR_MODE_BT709_F +} IepColorConvertMode; + +/* IepCmdParamColorConvert is parameter for IEP_CMD_SET_COLOR_CONVERT */ +typedef struct IepCmdParamColorConvert_t { + IepColorConvertMode rgb2yuv_mode; + IepColorConvertMode yuv2rgb_mode; + RK_U8 rgb2yuv_input_clip; // 0:R/G/B [0, 255], 1:R/G/B [16, 235] + RK_U8 yuv2rgb_input_clip; // 0:Y/U/V [0, 255], 1:Y [16, 235] U/V [16, 240] + RK_U8 global_alpha_value; // global alpha value for output ARGB + RK_U8 dither_up_en; + RK_U8 dither_down_en; +} IepCmdParamColorConvert; + +/* IepCap is parameter for IEP_CMD_QUERY_CAP */ +typedef struct IepCap_t { + RK_U8 scaling_supported; + RK_U8 i4_deinterlace_supported; + RK_U8 i2_deinterlace_supported; + RK_U8 compression_noise_reduction_supported; + RK_U8 sampling_noise_reduction_supported; + RK_U8 hsb_enhancement_supported; + RK_U8 cg_enhancement_supported; + RK_U8 direct_path_supported; + RK_U16 max_dynamic_width; + RK_U16 max_dynamic_height; + RK_U16 max_static_width; + RK_U16 max_static_height; + RK_U8 max_enhance_radius; +} IepCap; + +typedef void* IepCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET iep_init(IepCtx *ctx); +MPP_RET iep_deinit(IepCtx ctx); +MPP_RET iep_control(IepCtx ctx, IepCmd cmd, void *param); + +iep_com_ctx* rockchip_iep_api_alloc_ctx(void); +void rockchip_iep_api_release_ctx(iep_com_ctx *com_ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* IEP_API_H */ diff --git a/mpp/vproc/inc/iep_common.h b/mpp/vproc/inc/iep_common.h new file mode 100644 index 000000000..b739d6bab --- /dev/null +++ b/mpp/vproc/inc/iep_common.h @@ -0,0 +1,134 @@ +/* + * Copyright 2020 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IEP_COMMON_H +#define IEP_COMMON_H + +#include "mpp_debug.h" + +#define IEP_DBG_FUNCTION (0x00000001) +#define IEP_DBG_TRACE (0x00000002) +#define IEP_DBG_IMAGE (0x00000010) + +#define iep_dbg(flag, fmt, ...) mpp_dbg(iep_debug, flag, "iep:" fmt, ## __VA_ARGS__) +#define iep_dbg_f(flag, fmt, ...) mpp_dbg_f(iep_debug, flag, fmt, ## __VA_ARGS__) +#define iep_dbg_func(fmt, ...) iep_dbg(IEP_DBG_FUNCTION, fmt, ## __VA_ARGS__) +#define iep_dbg_trace(fmt, ...) iep_dbg(IEP_DBG_TRACE, fmt, ## __VA_ARGS__) + +typedef enum IepCmd_e { + IEP_CMD_INIT, // reset msg to all zero + IEP_CMD_SET_SRC, // config source image info + IEP_CMD_SET_DST, // config destination image info + + // deinterlace command + IEP_CMD_SET_DEI_CFG = 0x0100, // config deinterlace configure + IEP_CMD_SET_DEI_SRC1, // config deinterlace extra source + IEP_CMD_SET_DEI_DST1, // config deinterlace extra destination + IEP_CMD_SET_DEI_SRC2, // in case of iep2 deinterlacing + + // color enhancement command + IEP_CMD_SET_YUV_ENHANCE = 0x0200, // config YUV enhancement parameter + IEP_CMD_SET_RGB_ENHANCE, // config RGB enhancement parameter + + // scale algorithm command + IEP_CMD_SET_SCALE = 0x0300, // config scale algorithm + + // color convert command + IEP_CMD_SET_COLOR_CONVERT = 0x0400, // config color convert parameter + + // hardware trigger command + IEP_CMD_RUN_SYNC = 0x1000, // start sync mode process + IEP_CMD_RUN_ASYNC, // start async mode process + + // hardware capability query command + IEP_CMD_QUERY_CAP = 0x8000, // query iep capability +} IepCmd; + +typedef enum IepFormat_e { + IEP_FORMAT_RGB_BASE = 0x0, + IEP_FORMAT_ARGB_8888 = IEP_FORMAT_RGB_BASE, + IEP_FORMAT_ABGR_8888 = 0x1, + IEP_FORMAT_RGBA_8888 = 0x2, + IEP_FORMAT_BGRA_8888 = 0x3, + IEP_FORMAT_RGB_565 = 0x4, + IEP_FORMAT_BGR_565 = 0x5, + IEP_FORMAT_RGB_BUTT, + + IEP_FORMAT_YUV_BASE = 0x10, + IEP_FORMAT_YCbCr_422_SP = IEP_FORMAT_YUV_BASE, + IEP_FORMAT_YCbCr_422_P = 0x11, + IEP_FORMAT_YCbCr_420_SP = 0x12, + IEP_FORMAT_YCbCr_420_P = 0x13, + IEP_FORMAT_YCrCb_422_SP = 0x14, + IEP_FORMAT_YCrCb_422_P = 0x15, // same as IEP_FORMAT_YCbCr_422_P + IEP_FORMAT_YCrCb_420_SP = 0x16, + IEP_FORMAT_YCrCb_420_P = 0x17, // same as IEP_FORMAT_YCbCr_420_P + IEP_FORMAT_YUV_BUTT, +} IepFormat; + +// iep image for external user +typedef struct IegImg_t { + RK_U16 act_w; // act_width + RK_U16 act_h; // act_height + RK_S16 x_off; // x offset for the vir,word unit + RK_S16 y_off; // y offset for the vir,word unit + + RK_U16 vir_w; // unit in byte + RK_U16 vir_h; // unit in byte + RK_U32 format; // IepFormat + RK_U32 mem_addr; // base address fd + RK_U32 uv_addr; // chroma address fd + (offset << 10) + RK_U32 v_addr; +} IepImg; + +typedef void* IepCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct iep_com_ctx_t iep_com_ctx; + +typedef struct iep_com_ops_t { + MPP_RET (*init)(IepCtx *ctx); + MPP_RET (*deinit)(IepCtx ctx); + MPP_RET (*control)(IepCtx ctx, IepCmd cmd, void *param); + MPP_RET (*reset)(IepCtx ctx); + void (*release)(iep_com_ctx *ctx); +} iep_com_ops; + +typedef struct iep_com_ctx_t { + iep_com_ops *ops; + IepCtx priv; + int ver; +} iep_com_ctx; + +struct dev_compatible { + const char *compatible; + iep_com_ctx* (*get)(void); + void (*put)(iep_com_ctx *ctx); + int ver; +}; + +iep_com_ctx* get_iep_ctx(void); +void put_iep_ctx(iep_com_ctx *ictx); +extern RK_U32 iep_debug; + +#ifdef __cplusplus +} +#endif + +#endif /* IEP_API_H */ diff --git a/mpp/vproc/inc/mpp_dec_vproc.h b/mpp/vproc/inc/mpp_dec_vproc.h new file mode 100644 index 000000000..72e621057 --- /dev/null +++ b/mpp/vproc/inc/mpp_dec_vproc.h @@ -0,0 +1,58 @@ +/* + * Copyright 2018 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MPP_DEC_VPROC_H +#define MPP_DEC_VPROC_H + +#include "mpp_dec_cfg.h" +#include "hal_dec_task.h" + +typedef struct MppDecVprocCfg_t { + void *mpp; + HalTaskGroup task_group; +} MppDecVprocCfg; + +typedef void* MppDecVprocCtx; + +#ifdef __cplusplus + +extern "C" { +#endif + +/* + * Functions usage: + * dec_vproc_init - get context with cfg + * dec_vproc_deinit - stop thread and destory context + * dec_vproc_start - start thread processing + * dec_vproc_signal - signal thread that one frame has be pushed for process + * dec_vproc_reset - reset process thread and discard all input + */ + +MPP_RET dec_vproc_init(MppDecVprocCtx *ctx, MppDecVprocCfg *cfg); +MPP_RET dec_vproc_deinit(MppDecVprocCtx ctx); + +MPP_RET dec_vproc_start(MppDecVprocCtx ctx); +MPP_RET dec_vproc_stop(MppDecVprocCtx ctx); +MPP_RET dec_vproc_signal(MppDecVprocCtx ctx); +MPP_RET dec_vproc_reset(MppDecVprocCtx ctx); +RK_U32 dec_vproc_get_version(MppDecVprocCtx ctx); +MPP_RET dec_vproc_set_mode(MppDecVprocCtx ctx, MppVprocMode mode); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEC_VPROC_H */ diff --git a/mpp/vproc/inc/vdpp_api.h b/mpp/vproc/inc/vdpp_api.h new file mode 100644 index 000000000..e93ddd5e0 --- /dev/null +++ b/mpp/vproc/inc/vdpp_api.h @@ -0,0 +1,432 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP_API_H +#define VDPP_API_H + +#include + +#include "mpp_debug.h" +#include "mpp_frame.h" + +#define RKVOP_PQ_PREPROCESS_GLOBAL_HIST_BIN_BITS (8) +#define RKVOP_PQ_PREPROCESS_GLOBAL_HIST_BIN_NUMS (1 << (RKVOP_PQ_PREPROCESS_GLOBAL_HIST_BIN_BITS)) +#define RKVOP_PQ_PREPROCESS_HIST_BITS_VERI (4) +#define RKVOP_PQ_PREPROCESS_HIST_BITS_HORI (4) +#define RKVOP_PQ_PREPROCESS_HIST_SIZE_VERI (1 << RKVOP_PQ_PREPROCESS_HIST_BITS_VERI) /* 16 */ +#define RKVOP_PQ_PREPROCESS_HIST_SIZE_HORI (1 << RKVOP_PQ_PREPROCESS_HIST_BITS_HORI) /* 16 */ +#define RKVOP_PQ_PREPROCESS_LOCAL_HIST_BIN_BITS (4) +#define RKVOP_PQ_PREPROCESS_LOCAL_HIST_BIN_NUMS (1 << (RKVOP_PQ_PREPROCESS_LOCAL_HIST_BIN_BITS)) + +/* for vdpp_api_content.hist.dci_csc_range */ +#define VDPP_COLOR_SPACE_LIMIT_RANGE (0) +#define VDPP_COLOR_SPACE_FULL_RANGE (1) + +#define VDPP_CAP_UNSUPPORTED (0) +#define VDPP_CAP_VEP (1 << 0) +#define VDPP_CAP_HIST (1 << 1) + +#define VDPP_WORK_MODE_VEP (2) +#define VDPP_WORK_MODE_DCI (3) /* hist mode */ + +/* for vdpp_api_content.com2.cfg_set */ +#define VDPP_DMSR_EN (4) +#define VDPP_ES_EN (2) +#define VDPP_SHARP_EN (1) + +/* DCI horizontal scale down mode select */ +#define VDPP_DCI_HSD_DISABLE (0) +#define VDPP_DCI_HSD_MODE_1 (1) +/* DCI vertical scale down mode select */ +#define VDPP_DCI_VSD_DISABLE (0) +#define VDPP_DCI_VSD_MODE_1 (1) +#define VDPP_DCI_VSD_MODE_2 (2) + +/* Pyramid layer number */ +#define VDPP_PYR_MAX_LAYERS (8) + +/* vdpp reg format definition */ +typedef enum VdppFmt_e { + VDPP_FMT_YUV444 = 0, // yuv444sp + VDPP_FMT_YUV420 = 3, // yuv420sp +} VdppFmt; + +typedef enum VdppYuvSwap_e { + VDPP_YUV_SWAP_SP_UV, + VDPP_YUV_SWAP_SP_VU, +} VdppYuvSwap; + +typedef enum VdppParamType_e { + VDPP_PARAM_TYPE_COM, + VDPP_PARAM_TYPE_DMSR, + VDPP_PARAM_TYPE_ZME_COM, + VDPP_PARAM_TYPE_ZME_COEFF, + VDPP_PARAM_TYPE_COM2 = 0x10, + VDPP_PARAM_TYPE_ES, + VDPP_PARAM_TYPE_HIST, + VDPP_PARAM_TYPE_SHARP, + VDPP_PARAM_TYPE_PYR = 0x20, // pyramid building + VDPP_PARAM_TYPE_BBD, // black bar detection +} VdppParamType; + +typedef enum VdppCmd_e { + VDPP_CMD_INIT, /* reset msg to all zero */ + VDPP_CMD_SET_SRC, /* config source image info */ + VDPP_CMD_SET_DST, /* config destination image info */ + VDPP_CMD_SET_COM_CFG, + /* DMSR command */ + VDPP_CMD_SET_DMSR_CFG = 0x0100, /* config DMSR configure */ + /* ZME command */ + VDPP_CMD_SET_ZME_COM_CFG = 0x0200, /* config ZME COM configure */ + VDPP_CMD_SET_ZME_COEFF_CFG, /* config ZME COEFF configure */ + /* hardware trigger command */ + VDPP_CMD_RUN_SYNC = 0x1000, /* start sync mode process */ + + /* new after vdpp2 */ + VDPP_CMD_SET_COM2_CFG = 0x2000, /* config common params for RK3576 */ + VDPP_CMD_SET_DST_C, /* config destination chroma info */ + VDPP_CMD_SET_HIST_FD, /* config dci hist fd */ + VDPP_CMD_SET_ES, /* config ES configure */ + VDPP_CMD_SET_DCI_HIST, /* config dci hist configure */ + VDPP_CMD_SET_SHARP, /* config sharp configure */ + VDPP_CMD_GET_AVG_LUMA = 0x2100, /* get average luma value */ + + /* new after vdpp3 */ + VDPP_CMD_SET_PYR = 0x3100, /* config pyramid building configure */ + VDPP_CMD_SET_BBD = 0x3200, /* config black bar detection configure */ + VDPP_CMD_GET_BBD, /* get black bar detection result to vdpp_results */ +} VdppCmd; + +/* forward declaration */ +typedef void* VdppCtx; +typedef struct VdppComCtx_t VdppComCtx; + +typedef struct VdppImg_t { + /* memory info */ + RK_U32 mem_addr; /* base address fd */ + RK_U32 uv_addr; /* chroma address fd */ + RK_U32 uv_off; /* chroma offset, unit: byte */ + RK_U32 y_off; /* luma offset, unit: byte */ + RK_U32 reserved1[4]; + + /* image info */ + RK_U32 fmt; /* see MppFrameFormat */ + RK_U32 wid; /* real width, unit: pixel */ + RK_U32 hgt; /* real width, unit: pixel */ + RK_U32 wid_vir; /* virtual width, unit: pixel */ + RK_U32 hgt_vir; /* virtual height, unit: pixel */ + RK_U32 reserved2[3]; +} VdppImg; + +typedef struct VdppComOps_t { + MPP_RET (*init)(VdppCtx ctx); + MPP_RET (*deinit)(VdppCtx ctx); + MPP_RET (*control)(VdppCtx ctx, VdppCmd cmd, void *param); + void (*release)(VdppComCtx *ctx); /* RESERVED */ + RK_S32 (*check_cap)(VdppCtx ctx); + MPP_RET (*reserve[3])(VdppCtx *ctx); +} VdppComOps; + +typedef VdppComOps vdpp_com_ops; // for compatibility + +typedef struct VdppComCtx_t { + VdppComOps *ops; + VdppCtx priv; + RK_S32 ver; // vdpp version, range: {0x100, 0x200, 0x300} +} VdppComCtx; + +typedef union VdppApiContent_u { + struct { + VdppYuvSwap sswap; + VdppFmt dfmt; // 0-yuv444sp, 3-yuv420sp + VdppYuvSwap dswap; + RK_S32 src_width; + RK_S32 src_height; + RK_S32 dst_width; + RK_S32 dst_height; + } com; + + struct { + bool enable; + RK_U32 str_pri_y; + RK_U32 str_sec_y; + RK_U32 dumping_y; + RK_U32 wgt_pri_gain_even_1; + RK_U32 wgt_pri_gain_even_2; + RK_U32 wgt_pri_gain_odd_1; + RK_U32 wgt_pri_gain_odd_2; + RK_U32 wgt_sec_gain; + RK_U32 blk_flat_th; + RK_U32 contrast_to_conf_map_x0; + RK_U32 contrast_to_conf_map_x1; + RK_U32 contrast_to_conf_map_y0; + RK_U32 contrast_to_conf_map_y1; + RK_U32 diff_core_th0; + RK_U32 diff_core_th1; + RK_U32 diff_core_wgt0; + RK_U32 diff_core_wgt1; + RK_U32 diff_core_wgt2; + RK_U32 edge_th_low_arr[7]; + RK_U32 edge_th_high_arr[7]; + } dmsr; + + struct { + bool bypass_enable; + bool dering_enable; + RK_U32 dering_sen_0; + RK_U32 dering_sen_1; + RK_U32 dering_blend_alpha; + RK_U32 dering_blend_beta; + const RK_S16 (*tap8_coeff)[17][8]; // 11x17x8 + const RK_S16 (*tap6_coeff)[17][8]; + } zme; + + /* new after vdpp2 */ + struct { + MppFrameFormat sfmt; // + VdppYuvSwap sswap; // {0-uv, 1-vu}, default: 0 + VdppFmt dfmt; // {0-yuv444sp, 3-yuv420sp} + VdppYuvSwap dswap; // {0-uv, 1-vu}, default: 0 + RK_U32 src_width; // unit: pixel + RK_U32 src_height; // unit: pixel + RK_U32 src_width_vir; // unit: pixel + RK_U32 src_height_vir; // unit: pixel + RK_U32 dst_width; // unit: pixel + RK_U32 dst_height; // unit: pixel + RK_U32 dst_width_vir; // unit: pixel + RK_U32 dst_height_vir; // unit: pixel + RK_U32 yuv_out_diff; // output luma/chroma buffer separated flag + RK_U32 dst_c_width; // unit: pixel + RK_U32 dst_c_height; // unit: pixel + RK_U32 dst_c_width_vir; // unit: pixel + RK_U32 dst_c_height_vir; // unit: pixel + /* 0-vdpp(vep), 1-dci_hist, use to set the work mode */ + RK_U32 hist_mode_en; + /* high 16 bit: mask; low 3 bit (msb->lsb): dmsr|es|sharp */ + RK_U32 cfg_set; + RK_S32 src_range; // {0-limited, 1-full}, default: 0 + } com2; + + struct { + RK_U32 es_bEnabledES; + RK_U32 es_iAngleDelta; + RK_U32 es_iAngleDeltaExtra; + RK_U32 es_iGradNoDirTh; + RK_U32 es_iGradFlatTh; + RK_U32 es_iWgtGain; + RK_U32 es_iWgtDecay; + RK_U32 es_iLowConfTh; + RK_U32 es_iLowConfRatio; + RK_U32 es_iConfCntTh; + RK_U32 es_iWgtLocalTh; + RK_U32 es_iK1; + RK_U32 es_iK2; + RK_U32 es_iDeltaLimit; + RK_U32 es_iDiff2conf_lut_x[9]; + RK_U32 es_iDiff2conf_lut_y[9]; + RK_U32 es_bEndpointCheckEnable; + /* generated by es_iAngleDelta and es_iAngleDeltaExtra */ + RK_U32 es_tan_hi_th; + RK_U32 es_tan_lo_th; + } es; + + struct { + RK_U32 hist_cnt_en; + RK_U32 dci_hsd_mode; // [0, 1], default: 0 + RK_U32 dci_vsd_mode; // [0, 2], default: 0 + RK_U32 dci_yrgb_gather_num; // DCI AXI bus yrgb data gather transfer number {0:2, 1:4, 2:8} + RK_U32 dci_yrgb_gather_en; // default: 0 + RK_U32 dci_csc_range; // {0-limited, 1-full}, default: 0 + RK_U32 hist_addr; // hist buffer fd + } hist; + + struct { + RK_S32 sharp_enable; // default: 1 + RK_S32 sharp_coloradj_bypass_en; // default: 1, DO NOT modify this! + + RK_S32 lti_h_enable; + RK_S32 lti_h_radius; + RK_S32 lti_h_slope; + RK_S32 lti_h_thresold; + RK_S32 lti_h_gain; + RK_S32 lti_h_noise_thr_pos; + RK_S32 lti_h_noise_thr_neg; + + RK_S32 lti_v_enable; + RK_S32 lti_v_radius; + RK_S32 lti_v_slope; + RK_S32 lti_v_thresold; + RK_S32 lti_v_gain; + RK_S32 lti_v_noise_thr_pos; + RK_S32 lti_v_noise_thr_neg; + + RK_S32 cti_h_enable; + RK_S32 cti_h_radius; + RK_S32 cti_h_slope; + RK_S32 cti_h_thresold; + RK_S32 cti_h_gain; + RK_S32 cti_h_noise_thr_pos; + RK_S32 cti_h_noise_thr_neg; + + RK_S32 peaking_enable; + RK_S32 peaking_gain; + + RK_S32 peaking_coring_enable; + RK_S32 peaking_coring_zero[8]; + RK_S32 peaking_coring_thr[8]; + RK_S32 peaking_coring_ratio[8]; + + RK_S32 peaking_gain_enable; + RK_S32 peaking_gain_pos[8]; + RK_S32 peaking_gain_neg[8]; + + RK_S32 peaking_limit_ctrl_enable; + RK_S32 peaking_limit_ctrl_pos0[8]; + RK_S32 peaking_limit_ctrl_pos1[8]; + RK_S32 peaking_limit_ctrl_neg0[8]; + RK_S32 peaking_limit_ctrl_neg1[8]; + RK_S32 peaking_limit_ctrl_ratio[8]; + RK_S32 peaking_limit_ctrl_bnd_pos[8]; + RK_S32 peaking_limit_ctrl_bnd_neg[8]; + + RK_S32 peaking_edge_ctrl_enable; + RK_S32 peaking_edge_ctrl_non_dir_thr; + RK_S32 peaking_edge_ctrl_dir_cmp_ratio; + RK_S32 peaking_edge_ctrl_non_dir_wgt_offset; + RK_S32 peaking_edge_ctrl_non_dir_wgt_ratio; + RK_S32 peaking_edge_ctrl_dir_cnt_thr; + RK_S32 peaking_edge_ctrl_dir_cnt_avg; + RK_S32 peaking_edge_ctrl_dir_cnt_offset; + RK_S32 peaking_edge_ctrl_diag_dir_thr; + RK_S32 peaking_edge_ctrl_diag_adj_gain_tab[8]; + + RK_S32 peaking_estc_enable; + RK_S32 peaking_estc_delta_offset_h; + RK_S32 peaking_estc_alpha_over_h; + RK_S32 peaking_estc_alpha_under_h; + RK_S32 peaking_estc_alpha_over_unlimit_h; + RK_S32 peaking_estc_alpha_under_unlimit_h; + RK_S32 peaking_estc_delta_offset_v; + RK_S32 peaking_estc_alpha_over_v; + RK_S32 peaking_estc_alpha_under_v; + RK_S32 peaking_estc_alpha_over_unlimit_v; + RK_S32 peaking_estc_alpha_under_unlimit_v; + RK_S32 peaking_estc_delta_offset_d0; + RK_S32 peaking_estc_alpha_over_d0; + RK_S32 peaking_estc_alpha_under_d0; + RK_S32 peaking_estc_alpha_over_unlimit_d0; + RK_S32 peaking_estc_alpha_under_unlimit_d0; + RK_S32 peaking_estc_delta_offset_d1; + RK_S32 peaking_estc_alpha_over_d1; + RK_S32 peaking_estc_alpha_under_d1; + RK_S32 peaking_estc_alpha_over_unlimit_d1; + RK_S32 peaking_estc_alpha_under_unlimit_d1; + RK_S32 peaking_estc_delta_offset_non; + RK_S32 peaking_estc_alpha_over_non; + RK_S32 peaking_estc_alpha_under_non; + RK_S32 peaking_estc_alpha_over_unlimit_non; + RK_S32 peaking_estc_alpha_under_unlimit_non; + RK_S32 peaking_filter_cfg_diag_enh_coef; + + RK_S32 peaking_filt_core_H0[6]; + RK_S32 peaking_filt_core_H1[6]; + RK_S32 peaking_filt_core_H2[6]; + RK_S32 peaking_filt_core_H3[6]; + RK_S32 peaking_filt_core_V0[3]; + RK_S32 peaking_filt_core_V1[3]; + RK_S32 peaking_filt_core_V2[3]; + RK_S32 peaking_filt_core_USM[3]; + + RK_S32 shootctrl_enable; + RK_S32 shootctrl_filter_radius; + RK_S32 shootctrl_delta_offset; + RK_S32 shootctrl_alpha_over; + RK_S32 shootctrl_alpha_under; + RK_S32 shootctrl_alpha_over_unlimit; + RK_S32 shootctrl_alpha_under_unlimit; + + RK_S32 global_gain_enable; + RK_S32 global_gain_lum_mode; + RK_S32 global_gain_lum_grd[6]; + RK_S32 global_gain_lum_val[6]; + RK_S32 global_gain_adp_grd[6]; + RK_S32 global_gain_adp_val[6]; + RK_S32 global_gain_var_grd[6]; + RK_S32 global_gain_var_val[6]; + + RK_S32 color_ctrl_enable; + + RK_S32 color_ctrl_p0_scaling_coef; + RK_S32 color_ctrl_p0_point_u; + RK_S32 color_ctrl_p0_point_v; + RK_S32 color_ctrl_p0_roll_tab[16]; + + RK_S32 color_ctrl_p1_scaling_coef; + RK_S32 color_ctrl_p1_point_u; + RK_S32 color_ctrl_p1_point_v; + RK_S32 color_ctrl_p1_roll_tab[16]; + + RK_S32 color_ctrl_p2_scaling_coef; + RK_S32 color_ctrl_p2_point_u; + RK_S32 color_ctrl_p2_point_v; + RK_S32 color_ctrl_p2_roll_tab[16]; + + RK_S32 color_ctrl_p3_scaling_coef; + RK_S32 color_ctrl_p3_point_u; + RK_S32 color_ctrl_p3_point_v; + RK_S32 color_ctrl_p3_roll_tab[16]; + + RK_S32 tex_adj_enable; + RK_S32 tex_adj_y_mode_select; + RK_S32 tex_adj_mode_select; + RK_S32 tex_adj_grd[6]; + RK_S32 tex_adj_val[6]; + } sharp; + + /* new after vdpp3 */ + struct { + RK_U32 pyr_en; + RK_U32 nb_layers; // [1, 3], default: 3 + VdppImg layer_imgs[VDPP_PYR_MAX_LAYERS]; // fd buffer of layer 1 + } pyr; + + struct { + RK_U32 bbd_en; + RK_U32 bbd_det_blcklmt; // luma threshold for black bar detection, always considered as full-range + } bbd; +} VdppApiContent; + +typedef union VdppResults_u { + struct { + RK_S32 luma_avg; // output mean luma value in U10 range, <0 means invalid value + } hist; + + struct { + RK_U32 bbd_size_top; // output black bar size on top + RK_U32 bbd_size_bottom; // output black bar size on bottom + RK_U32 bbd_size_left; // output black bar size on left + RK_U32 bbd_size_right; // output black bar size on right + } bbd; +} VdppResults; + +typedef struct VdppApiParams_t { + VdppParamType ptype; + VdppApiContent param; +} VdppApiParams; + +#ifdef __cplusplus +extern "C" { +#endif + +VdppComCtx *rockchip_vdpp_api_alloc_ctx(void); +void rockchip_vdpp_api_release_ctx(VdppComCtx *com_ctx); + +MPP_RET dci_hist_info_parser(const RK_U8 *p_pack_hist_addr, RK_U32 *p_hist_local, RK_U32 *p_hist_global); + +#ifdef __cplusplus +} +#endif + +#endif /* VDPP_API_H */ diff --git a/mpp/vproc/mpp_dec_vproc.c b/mpp/vproc/mpp_dec_vproc.c new file mode 100644 index 000000000..daf0741d6 --- /dev/null +++ b/mpp/vproc/mpp_dec_vproc.c @@ -0,0 +1,1228 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dec_vproc" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "mpp_dec_impl.h" + +#include "mpp_meta_impl.h" +#include "mpp_frame_impl.h" +#include "mpp_dec_vproc.h" +#include "iep_api.h" +#include "iep2_api.h" + +#define DUMP_FILE 1 + +#define dec_vproc_dbg(flag, fmt, ...) \ + do { \ + mpp_dbg(vproc_debug, flag, fmt, ## __VA_ARGS__); \ + } while (0) + +#define vproc_dbg_f(flag, fmt, ...) \ + do { \ + mpp_dbg_f(vproc_debug, flag, fmt, ## __VA_ARGS__); \ + } while (0) + +#define VPROC_DBG_FUNCTION (0x00000001) +#define VPROC_DBG_STATUS (0x00000002) +#define VPROC_DBG_RESET (0x00000004) +#define VPROC_DBG_DUMP_IN (0x00000010) +#define VPROC_DBG_DUMP_OUT (0x00000020) +#define VPROC_DBG_IN (0x00000040) +#define VPROC_DBG_OUT (0x00000080) + +#define vproc_dbg_func(fmt, ...) \ + vproc_dbg_f(VPROC_DBG_FUNCTION, fmt, ## __VA_ARGS__); +#define vproc_dbg_status(fmt, ...) \ + vproc_dbg_f(VPROC_DBG_STATUS, fmt, ## __VA_ARGS__); +#define vproc_dbg_reset(fmt, ...) \ + vproc_dbg_f(VPROC_DBG_RESET, fmt, ## __VA_ARGS__); +#define vproc_dbg_in(fmt, ...) \ + vproc_dbg_f(VPROC_DBG_IN, fmt, ## __VA_ARGS__); +#define vproc_dbg_out(fmt, ...) \ + vproc_dbg_f(VPROC_DBG_OUT, fmt, ## __VA_ARGS__); + +RK_U32 vproc_debug = 0; + +typedef union VprocTaskStatus_u { + RK_U32 val; + struct { + RK_U32 task_rdy : 1; + RK_U32 buf_rdy : 1; + }; +} VprocTaskStatus; + +typedef union VprocTaskWait_u { + RK_U32 val; + struct { + RK_U32 task_in : 1; + RK_U32 task_buf_in : 1; + }; +} VprocTaskWait; + +typedef struct MppDecVprocCtxImpl_t { + Mpp *mpp; + HalTaskGroup task_group; + MppBufSlots slots; + + MppThread *thd; + RK_U32 reset; + sem_t reset_sem; + + IepCtx iep_ctx; + iep_com_ctx *com_ctx; + IepCmdParamDeiCfg dei_cfg; + struct iep2_api_info dei_info; + + VprocTaskStatus task_status; + VprocTaskWait task_wait; + + // slot index for previous frame and current frame + RK_S32 prev_idx0; + MppFrame prev_frm0; + RK_S32 prev_idx1; + MppFrame prev_frm1; + enum IEP2_FF_MODE pre_ff_mode; + RK_U32 pd_mode; + MppBuffer out_buf0; + MppBuffer out_buf1; + MppVprocMode vproc_mode; + + MPP_RET (*set_dei)(MppDecVprocCtx *vproc_ctx, MppFrame frm); + MPP_RET (*start_dei)(MppDecVprocCtx *vproc_ctx, RK_U32 mode); + MPP_RET (*update_ref)(MppDecVprocCtx *vproc_ctx, MppFrame frm, RK_U32 index); +} MppDecVprocCtxImpl; + +static void dec_vproc_put_frame(Mpp *mpp, MppFrame frame, MppBuffer buf, RK_S64 pts, RK_U32 err) +{ + MppList *list = mpp->mFrmOut; + MppFrame out = mpp_frame_dup(frame); + MppFrameImpl *impl = (MppFrameImpl *)out; + MppBuffer src_buf = mpp_frame_get_buffer(frame); + + if (pts >= 0) + impl->pts = pts; + + if (buf) + impl->buffer = buf; + + /* check and copy hdr info */ + if (impl->meta && src_buf != buf) { + RK_S32 hdr_offset = 0; + RK_S32 hdr_size = 0; + + mpp_meta_s32_read(impl->meta, meta_hdr_offset_index, &hdr_offset); + mpp_meta_s32_read(impl->meta, meta_hdr_size_index, &hdr_size); + + if (hdr_offset && hdr_size) { + RK_U8 *src = (RK_U8 *)mpp_buffer_get_ptr(src_buf) + hdr_offset; + RK_U8 *dst = (RK_U8 *)mpp_buffer_get_ptr(buf) + hdr_offset; + + mpp_buffer_sync_ro_partial_begin(src_buf, hdr_offset, hdr_size); + memcpy(dst, src, hdr_size); + mpp_buffer_sync_partial_end(buf, hdr_offset, hdr_size); + } + } + + impl->errinfo |= err; + + mpp_mutex_cond_lock(&list->cond_lock); + mpp_list_add_at_tail(list, &out, sizeof(out)); + + mpp->mFramePutCount++; + vproc_dbg_out("Output frame[%d]:poc %d, pts %lld, err 0x%x, dis %x, buf ptr %p\n", + mpp->mFramePutCount, mpp_frame_get_poc(out), mpp_frame_get_pts(out), + mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame), + mpp_buffer_get_ptr(impl->buffer)); + mpp_mutex_cond_signal(&list->cond_lock); + mpp_mutex_cond_unlock(&list->cond_lock); + + if (mpp->mDec) + mpp_dec_callback(mpp->mDec, MPP_DEC_EVENT_ON_FRM_READY, out); +} + +static void dec_vproc_clr_prev0(MppDecVprocCtxImpl *ctx) +{ + if (vproc_debug & VPROC_DBG_STATUS) { + if (ctx->prev_frm0) { + MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm0); + RK_S32 fd = (buf) ? (mpp_buffer_get_fd(buf)) : (-1); + mpp_log("clearing prev index %d frm %p fd %d, poc%d\n", ctx->prev_idx0, + ctx->prev_frm0, fd, mpp_frame_get_poc(ctx->prev_frm0)); + } else + mpp_log("clearing nothing\n"); + } + + if (ctx->prev_frm0) { + MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm0); + if (buf) + mpp_buffer_put(buf); + } + if (ctx->prev_idx0 >= 0) + mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx0, SLOT_QUEUE_USE); + + ctx->prev_idx0 = -1; + ctx->prev_frm0 = NULL; +} + +static void dec_vproc_clr_prev1(MppDecVprocCtxImpl *ctx) +{ + if (vproc_debug & VPROC_DBG_STATUS) { + if (ctx->prev_frm1) { + MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm1); + RK_S32 fd = (buf) ? (mpp_buffer_get_fd(buf)) : (-1); + mpp_log("clearing prev index %d frm %p fd %d, poc %d\n", ctx->prev_idx1, + ctx->prev_frm1, fd, mpp_frame_get_poc(ctx->prev_frm1)); + } else + mpp_log("clearing nothing\n"); + } + if (ctx->prev_frm1) { + MppBuffer buf = mpp_frame_get_buffer(ctx->prev_frm1); + if (buf) + mpp_buffer_put(buf); + } + if (ctx->prev_idx1 >= 0) + mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx1, SLOT_QUEUE_USE); + + ctx->prev_idx1 = -1; + ctx->prev_frm1 = NULL; +} + +static void dec_vproc_clr_prev(MppDecVprocCtxImpl *ctx) +{ + dec_vproc_clr_prev0(ctx); + dec_vproc_clr_prev1(ctx); + if (ctx->out_buf0) { + mpp_buffer_put(ctx->out_buf0); + ctx->out_buf0 = NULL; + } + if (ctx->out_buf1) { + mpp_buffer_put(ctx->out_buf1); + ctx->out_buf1 = NULL; + } +} + +static void dec_vproc_set_img_fmt(IepImg *img, MppFrame frm) +{ + memset(img, 0, sizeof(*img)); + img->act_w = mpp_frame_get_width(frm); + img->act_h = mpp_frame_get_height(frm); + img->vir_w = mpp_frame_get_hor_stride(frm); + img->vir_h = mpp_frame_get_ver_stride(frm); + img->format = IEP_FORMAT_YCbCr_420_SP; +} + +static void dec_vproc_set_img(MppDecVprocCtxImpl *ctx, IepImg *img, RK_S32 fd, IepCmd cmd) +{ + RK_S32 y_size = img->vir_w * img->vir_h; + img->mem_addr = fd; + img->uv_addr = fd + (y_size << 10); + img->v_addr = fd + ((y_size + y_size / 4) << 10); + + MPP_RET ret = ctx->com_ctx->ops->control(ctx->iep_ctx, cmd, img); + if (ret) + mpp_log_f("control %08x failed %d\n", cmd, ret); +} + +static MPP_RET dec_vproc_start_dei_v1(MppDecVprocCtx *vproc_ctx, RK_U32 mode) +{ + MPP_RET ret = MPP_OK; + MppDecVprocCtxImpl *impl = (MppDecVprocCtxImpl *) vproc_ctx; + impl->dei_cfg.dei_field_order = ((mode & MPP_FRAME_FLAG_TOP_FIRST) != 0) ? + (IEP_DEI_FLD_ORDER_TOP_FIRST) : + (IEP_DEI_FLD_ORDER_BOT_FIRST); + ret = impl->com_ctx->ops->control(impl->iep_ctx, + IEP_CMD_SET_DEI_CFG, &impl->dei_cfg); + if (ret) + mpp_err_f("IEP_CMD_SET_DEI_CFG failed %d\n", ret); + + ret = impl->com_ctx->ops->control(impl->iep_ctx, IEP_CMD_RUN_SYNC, &impl->dei_info); + if (ret) + mpp_err_f("IEP_CMD_RUN_SYNC failed %d\n", ret); + + return ret; +} + +static MPP_RET dec_vproc_start_dei_v2(MppDecVprocCtx *vproc_ctx, RK_U32 mode) +{ + MPP_RET ret = MPP_OK; + MppDecVprocCtxImpl *impl = (MppDecVprocCtxImpl *) vproc_ctx; + (void)mode; + + ret = impl->com_ctx->ops->control(impl->iep_ctx, IEP_CMD_RUN_SYNC, &impl->dei_info); + if (ret) + mpp_log_f("IEP_CMD_RUN_SYNC failed %d\n", ret); + + return ret; +} + +static MPP_RET dec_vproc_set_dei_v1(MppDecVprocCtx *vproc_ctx, MppFrame frm) +{ + MPP_RET ret = MPP_OK; + IepImg img; + MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx; + + Mpp *mpp = ctx->mpp; + RK_U32 mode = mpp_frame_get_mode(frm); + MppBuffer buf = mpp_frame_get_buffer(frm); + MppBuffer dst0 = ctx->out_buf0; + MppBuffer dst1 = ctx->out_buf1; + int fd = -1; + RK_U32 frame_err = 0; + + // setup source IepImg + dec_vproc_set_img_fmt(&img, frm); + + ret = ctx->com_ctx->ops->control(ctx->iep_ctx, IEP_CMD_INIT, NULL); + if (ret) + mpp_log_f("IEP_CMD_INIT failed %d\n", ret); + + struct IepCap_t *cap = NULL; + ret = ctx->com_ctx->ops->control(ctx->iep_ctx, IEP_CMD_QUERY_CAP, &cap); + if (ret) + mpp_log_f("IEP_CMD_QUERY_CAP failed %d\n", ret); + + // setup destination IepImg with new buffer + // NOTE: when deinterlace is enabled parser thread will reserve + // more buffer than normal case + if (ctx->prev_frm0 && cap && cap->i4_deinterlace_supported) { + // 4 in 2 out case + vproc_dbg_status("4 field in and 2 frame out\n"); + RK_S64 prev_pts = mpp_frame_get_pts(ctx->prev_frm0); + RK_S64 curr_pts = mpp_frame_get_pts(frm); + RK_S64 first_pts = (prev_pts + curr_pts) / 2; + + buf = mpp_frame_get_buffer(ctx->prev_frm0); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC); + frame_err = mpp_frame_get_errinfo(ctx->prev_frm0) || + mpp_frame_get_discard(ctx->prev_frm0); + // setup dst 0 + mpp_assert(dst0); + fd = mpp_buffer_get_fd(dst0); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST); + + buf = mpp_frame_get_buffer(frm); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1); + frame_err |= mpp_frame_get_errinfo(frm) || + mpp_frame_get_discard(frm); + // setup dst 1 + mpp_assert(dst1); + fd = mpp_buffer_get_fd(dst1); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_DST1); + + ctx->dei_cfg.dei_mode = IEP_DEI_MODE_I4O2; + + mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2; + mpp_frame_set_mode(frm, mode); + + // start hardware + ctx->start_dei((MppDecVprocCtx *)ctx, mode); + + // NOTE: we need to process pts here + if (mode & MPP_FRAME_FLAG_TOP_FIRST) { + dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err); + dec_vproc_put_frame(mpp, frm, dst1, curr_pts, frame_err); + } else { + dec_vproc_put_frame(mpp, frm, dst1, first_pts, frame_err); + dec_vproc_put_frame(mpp, frm, dst0, curr_pts, frame_err); + } + ctx->out_buf0 = NULL; + ctx->out_buf1 = NULL; + } else { + // 2 in 1 out case + vproc_dbg_status("2 field in and 1 frame out\n"); + buf = mpp_frame_get_buffer(frm); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC); + frame_err = mpp_frame_get_errinfo(frm) || + mpp_frame_get_discard(frm); + + // setup dst 0 + mpp_assert(dst0); + fd = mpp_buffer_get_fd(dst0); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST); + + ctx->dei_cfg.dei_mode = IEP_DEI_MODE_I2O1; + mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1; + mpp_frame_set_mode(frm, mode); + + // start hardware + ctx->start_dei((MppDecVprocCtx *)ctx, mode); + dec_vproc_put_frame(mpp, frm, dst0, -1, frame_err); + ctx->out_buf0 = NULL; + } + + return ret; +} + +#if DUMP_FILE +static void dump_mppbuffer(MppBuffer buf, const char *fname, int stride, int height) +{ + char title[256]; + void *ptr = mpp_buffer_get_ptr(buf); + sprintf(title, "%s.%dx%d.yuv", fname, stride, height); + FILE *dump = fopen(title, "ab+"); + + if (dump) { + fwrite(ptr, 1, stride * height * 3 / 2, dump); + fclose(dump); + } +} +#else +#define dump_mppbuffer(...) +#endif + +static MPP_RET dec_vproc_config_dei_v2(MppDecVprocCtxImpl *ctx, MppFrame frm, + enum IEP2_DIL_MODE dil_mode) +{ + MPP_RET ret = MPP_OK; + MppBuffer buf = NULL; + RK_S32 fd = -1; + IepImg img; + struct iep2_api_params params; + iep_com_ops *ops = ctx->com_ctx->ops; + + if (!frm) { + mpp_err("found NULL pointer frm\n"); + ret = MPP_ERR_NULL_PTR; + return ret; + } + + /* default alloc 2 out buffer for IEP */ + if (!ctx->out_buf0 || !ctx->out_buf1) { + mpp_err("found NULL pointer out_buf0 %p out_buf1 %p\n", ctx->out_buf0, ctx->out_buf1); + ret = MPP_ERR_NULL_PTR; + return ret; + } + + // setup source IepImg + dec_vproc_set_img_fmt(&img, frm); + + if (vproc_debug & VPROC_DBG_DUMP_IN) + dump_mppbuffer(buf, "/data/dump/dump_in.yuv", img.vir_w, img.vir_h); + + vproc_dbg_status("set dil_mode %d\n", dil_mode); + // TODO: check the input frame + switch (dil_mode) { + case IEP2_DIL_MODE_I5O2: + case IEP2_DIL_MODE_I5O1T: + case IEP2_DIL_MODE_I5O1B: + case IEP2_DIL_MODE_DECT: { + // require 3 frames + buf = mpp_frame_get_buffer(ctx->prev_frm0); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC); + + buf = mpp_frame_get_buffer(frm); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1); + + buf = mpp_frame_get_buffer(ctx->prev_frm1); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2); + } break; + case IEP2_DIL_MODE_PD: { + // require 2 frame + buf = mpp_frame_get_buffer(frm); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1); + + if (ctx->prev_frm0) { + buf = mpp_frame_get_buffer(ctx->prev_frm0); + fd = mpp_buffer_get_fd(buf); + } else if (ctx->prev_frm1) { + buf = mpp_frame_get_buffer(ctx->prev_frm1); + fd = mpp_buffer_get_fd(buf); + } + + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2); + } break; + case IEP2_DIL_MODE_I2O2: + case IEP2_DIL_MODE_I1O1T: + case IEP2_DIL_MODE_I1O1B: + case IEP2_DIL_MODE_BYPASS: + default: { + buf = mpp_frame_get_buffer(frm); + fd = mpp_buffer_get_fd(buf); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_SRC); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC1); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_SRC2); + } break; + } + + // setup output + fd = mpp_buffer_get_fd(ctx->out_buf0); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DST); + fd = mpp_buffer_get_fd(ctx->out_buf1); + dec_vproc_set_img(ctx, &img, fd, IEP_CMD_SET_DEI_DST1); + + memset(¶ms, 0, sizeof(params)); + params.ptype = IEP2_PARAM_TYPE_MODE; + params.param.mode.dil_mode = dil_mode; + params.param.mode.out_mode = IEP2_OUT_MODE_LINE; + { + RK_U32 mode = mpp_frame_get_mode(frm); + RK_U32 fo_from_syntax = ((mode & MPP_FRAME_FLAG_TOP_FIRST) != 0) ? 1 : 0; + + /* refer to syntax */ + if ((mode & MPP_FRAME_FLAG_TOP_FIRST) && (mode & MPP_FRAME_FLAG_BOT_FIRST)) + params.param.mode.dil_order = IEP2_FIELD_ORDER_UND; + else if (fo_from_syntax) + params.param.mode.dil_order = IEP2_FIELD_ORDER_TFF; + else + params.param.mode.dil_order = IEP2_FIELD_ORDER_BFF; + + /* refer to IEP */ + if (ctx->pre_ff_mode == IEP2_FF_MODE_FIELD) { + RK_U32 fo_from_iep = (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_UND) ? + fo_from_syntax : (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_TFF); + RK_U32 is_tff = 0; + + if (fo_from_iep != fo_from_syntax) { + if (ctx->dei_info.dil_order_confidence_ratio > 30) + is_tff = fo_from_iep; + else + is_tff = fo_from_syntax; + } else { + is_tff = fo_from_syntax; + } + + if (is_tff) + params.param.mode.dil_order = IEP2_FIELD_ORDER_TFF; + else + params.param.mode.dil_order = IEP2_FIELD_ORDER_BFF; + + vproc_dbg_status("Config field order: is TFF %d, syn %d vs iep %d\n", + is_tff, fo_from_syntax, fo_from_iep); + } + } + ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, ¶ms); + + memset(¶ms, 0, sizeof(params)); + params.ptype = IEP2_PARAM_TYPE_COM; + params.param.com.sfmt = IEP2_FMT_YUV420; + params.param.com.dfmt = IEP2_FMT_YUV420; + params.param.com.sswap = IEP2_YUV_SWAP_SP_UV; + params.param.com.dswap = IEP2_YUV_SWAP_SP_UV; + params.param.com.width = img.act_w; + params.param.com.height = img.act_h; + params.param.com.hor_stride = img.vir_w;//img.act_w; + ops->control(ctx->iep_ctx, IEP_CMD_SET_DEI_CFG, ¶ms); + + return MPP_OK; +} + +MPP_RET dec_vproc_output_dei_v2(MppDecVprocCtxImpl *ctx, MppFrame frm, RK_U32 is_frm) +{ + MPP_RET ret = MPP_OK; + Mpp *mpp = ctx->mpp; + RK_U32 hor_stride = mpp_frame_get_hor_stride(frm); + RK_U32 ver_stride = mpp_frame_get_ver_stride(frm); + RK_U32 mode = mpp_frame_get_mode(frm); + RK_U32 dei_mode = mode & MPP_FRAME_FLAG_IEP_DEI_MASK; + MppBuffer dst0 = ctx->out_buf0; + MppBuffer dst1 = ctx->out_buf1; + RK_U32 frame_err = 0; + + vproc_dbg_status("is_frm %d frm %p, dei_mode %d field0 %p field1 %p", + is_frm, ctx->prev_frm1, dei_mode, dst0, dst1); + if (is_frm) { + if (ctx->prev_frm1) { + vproc_dbg_out("output frame prev1 poc %d\n", mpp_frame_get_poc(ctx->prev_frm1)); + dec_vproc_put_frame(mpp, ctx->prev_frm1, NULL, -1, 0); + if (ctx->prev_idx1 >= 0) + mpp_buf_slot_clr_flag(ctx->slots, ctx->prev_idx1, SLOT_QUEUE_USE); + ctx->prev_idx1 = -1; + ctx->prev_frm1 = NULL; + } + return ret; + } + + switch (dei_mode) { + case MPP_FRAME_FLAG_IEP_DEI_I4O2: { + RK_S64 prev_pts = mpp_frame_get_pts(ctx->prev_frm1); + RK_S64 curr_pts = mpp_frame_get_pts(ctx->prev_frm0); + RK_S64 first_pts = (prev_pts + curr_pts) / 2; + + frame_err |= mpp_frame_get_errinfo(ctx->prev_frm0) + mpp_frame_get_discard(ctx->prev_frm0); + frame_err |= mpp_frame_get_errinfo(ctx->prev_frm1) + mpp_frame_get_discard(ctx->prev_frm1); + + if (ctx->pd_mode) { + // NOTE: we need to process pts here if PD mode + if (ctx->dei_info.pd_flag != PD_COMP_FLAG_NON && + ctx->dei_info.pd_types != PD_TYPES_UNKNOWN) { + vproc_dbg_out("output at pd mode, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err); + if (vproc_debug & VPROC_DBG_DUMP_OUT) + dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, ver_stride); + ctx->out_buf0 = NULL; + } + } else { + RK_U32 fo_from_syntax = ((mode & MPP_FRAME_FLAG_TOP_FIRST) != 0) ? 1 : 0; + RK_U32 fo_from_iep = (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_UND) ? + fo_from_syntax : (ctx->dei_info.dil_order == IEP2_FIELD_ORDER_TFF); + RK_U32 is_tff = 0; + + if (fo_from_iep != fo_from_syntax) { + if (ctx->dei_info.dil_order_confidence_ratio > 30) + is_tff = fo_from_iep; + else + is_tff = fo_from_syntax; + } else { + is_tff = fo_from_syntax; + } + + vproc_dbg_status("Output field order: is TFF %d, syn %d vs iep %d\n", + is_tff, fo_from_syntax, fo_from_iep); + + if (is_tff) { + vproc_dbg_out("output at I4O2 for tff, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, dst0, first_pts, frame_err); + if (vproc_debug & VPROC_DBG_DUMP_OUT) + dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, ver_stride); + vproc_dbg_out("output at I4O2 for bff, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, dst1, curr_pts, frame_err); + if (vproc_debug & VPROC_DBG_DUMP_OUT) + dump_mppbuffer(dst1, "/data/dump/dump_output.yuv", hor_stride, ver_stride); + } else { + vproc_dbg_out("output at I4O2 for bff, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, dst1, first_pts, frame_err); + if (vproc_debug & VPROC_DBG_DUMP_OUT) + dump_mppbuffer(dst1, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm)); + vproc_dbg_out("output at I4O2 for tff, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, dst0, curr_pts, frame_err); + if (vproc_debug & VPROC_DBG_DUMP_OUT) + dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm)); + } + + ctx->out_buf0 = NULL; + ctx->out_buf1 = NULL; + } + } break; + case MPP_FRAME_FLAG_IEP_DEI_I2O1: + case MPP_FRAME_FLAG_IEP_DEI_I4O1: { + vproc_dbg_out("output at I2O1, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, dst0, -1, frame_err); + if (vproc_debug & VPROC_DBG_DUMP_OUT) + dump_mppbuffer(dst0, "/data/dump/dump_output.yuv", hor_stride, mpp_frame_get_height(frm)); + ctx->out_buf0 = NULL; + } + default: + break; + } + + return ret; +} + +static MPP_RET dec_vproc_dei_v2_deinterlace(MppDecVprocCtxImpl *ctx, MppFrame frm) +{ + MPP_RET ret = MPP_OK; + RK_U32 mode = mpp_frame_get_mode(frm); + enum IEP2_DIL_MODE dil_mode = IEP2_DIL_MODE_DISABLE; + + /* refer to syntax */ + if (((mode & MPP_FRAME_FLAG_PAIRED_FIELD) == MPP_FRAME_FLAG_FRAME) && + !(mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK)) + return dec_vproc_output_dei_v2(ctx, frm, 1); + + if (ctx->prev_frm1 && ctx->prev_frm0) { + // 5 in 2 out case + vproc_dbg_status("5 field in and 2 frame out\n"); + + if (!ctx->pd_mode) + dil_mode = IEP2_DIL_MODE_I5O2; + else + dil_mode = IEP2_DIL_MODE_PD; + + dec_vproc_config_dei_v2(ctx, frm, dil_mode); + + mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2; + mpp_frame_set_mode(frm, mode); + // start hardware + ctx->start_dei((MppDecVprocCtx *)ctx, mode); + + dec_vproc_output_dei_v2(ctx, frm, 0); + + if (ctx->dei_info.pd_types == PD_TYPES_UNKNOWN) + ctx->pd_mode = 0; + else + ctx->pd_mode = 1; + + } else if (ctx->prev_frm0 && ! ctx->prev_frm1) { + vproc_dbg_status("Wait for next frame to turn into I5O2"); + + if (ctx->out_buf0) { + mpp_buffer_put(ctx->out_buf0); + ctx->out_buf0 = NULL; + } + + if (ctx->out_buf1) { + mpp_buffer_put(ctx->out_buf1); + ctx->out_buf1 = NULL; + } + } else { + // 2 in 1 out case + vproc_dbg_status("2 field in and 1 frame out\n"); + dil_mode = IEP2_DIL_MODE_I1O1T; + + dec_vproc_config_dei_v2(ctx, frm, dil_mode); + + mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1; + mpp_frame_set_mode(frm, mode); + // start hardware + ctx->start_dei((MppDecVprocCtx *)ctx, mode); + + dec_vproc_output_dei_v2(ctx, frm, 0); + } + + return ret; +} + +static MPP_RET dec_vproc_dei_v2_detection(MppDecVprocCtxImpl *ctx, MppFrame frm) +{ + MPP_RET ret = MPP_OK; + RK_U32 mode = mpp_frame_get_mode(frm); + enum IEP2_DIL_MODE dil_mode = IEP2_DIL_MODE_DISABLE; + RK_U32 is_frame = 0; + + if (ctx->pre_ff_mode == IEP2_FF_MODE_UND) { + if (((mode & MPP_FRAME_FLAG_PAIRED_FIELD) == MPP_FRAME_FLAG_FRAME) && + !(mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK)) + is_frame = 1; + else + is_frame = 0; + } else { + is_frame = ctx->pre_ff_mode == IEP2_FF_MODE_FRAME ? 1 : 0; + } + + /* TODO: diff detection strategy */ + if (ctx->prev_frm1 && ctx->prev_frm0) { + // 5 in 2 out case + vproc_dbg_status("5 field in and 2 frame out\n"); + + if (!ctx->pd_mode) + dil_mode = IEP2_DIL_MODE_I5O2; + else + dil_mode = IEP2_DIL_MODE_PD; + + dec_vproc_config_dei_v2(ctx, frm, dil_mode); + + // start hardware + ctx->start_dei((MppDecVprocCtx *)ctx, mode); + + if (ctx->dei_info.frm_mode == IEP2_FF_MODE_FRAME) { + is_frame = 1; + } else if (ctx->dei_info.pd_types == PD_TYPES_UNKNOWN) { + ctx->pd_mode = 0; + is_frame = 0; + } else { + ctx->pd_mode = 1; + is_frame = 0; + } + + if (!is_frame) { + mode = mode | MPP_FRAME_FLAG_IEP_DEI_I4O2; + mpp_frame_set_mode(frm, mode); + } + } else if (ctx->prev_frm0 && ! ctx->prev_frm1) { + vproc_dbg_status("Wait for next frame to turn into I5O2"); + + if (ctx->out_buf0) { + mpp_buffer_put(ctx->out_buf0); + ctx->out_buf0 = NULL; + } + + if (ctx->out_buf1) { + mpp_buffer_put(ctx->out_buf1); + ctx->out_buf1 = NULL; + } + } else { + // 2 in 1 out case + vproc_dbg_status("2 field in and 1 frame out\n"); + dil_mode = IEP2_DIL_MODE_I1O1T; + + dec_vproc_config_dei_v2(ctx, frm, dil_mode); + + mode = mode | MPP_FRAME_FLAG_IEP_DEI_I2O1; + mpp_frame_set_mode(frm, mode); + // start hardware + ctx->start_dei((MppDecVprocCtx *)ctx, mode); + } + + ret = dec_vproc_output_dei_v2(ctx, frm, is_frame); + ctx->pre_ff_mode = ctx->dei_info.frm_mode; + + return ret; +} + +static MPP_RET dec_vproc_set_dei_v2(MppDecVprocCtx *vproc_ctx, MppFrame frm) +{ + MPP_RET ret = MPP_OK; + MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx; + /* RK_U32 mode = mpp_frame_get_mode(frm); + enum IEP2_DIL_MODE dil_mode = IEP2_DIL_MODE_DISABLE; */ + MppVprocMode vproc_mode = ctx->vproc_mode; + + switch (vproc_mode) { + case MPP_VPROC_MODE_DETECTION: { + dec_vproc_dei_v2_detection(ctx, frm); + } break; + case MPP_VPROC_MODE_DEINTELACE: { + dec_vproc_dei_v2_deinterlace(ctx, frm); + } break; + default: { + mpp_err("warning: vproc mode unknown!\n"); + ret = MPP_NOK; + } break; + } + + return ret; +} + +MPP_RET dec_vproc_update_ref_v1(MppDecVprocCtx *vproc_ctx, MppFrame frm, RK_U32 index) +{ + MPP_RET ret = MPP_OK; + MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx; + dec_vproc_clr_prev0(ctx); + ctx->prev_idx0 = index; + ctx->prev_frm0 = frm; + + return ret; +} + +MPP_RET dec_vproc_update_ref_v2(MppDecVprocCtx *vproc_ctx, MppFrame frm, RK_U32 index) +{ + MPP_RET ret = MPP_OK; + MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)vproc_ctx; + + dec_vproc_clr_prev1(ctx); + + ctx->prev_idx1 = ctx->prev_idx0; + ctx->prev_idx0 = index; + ctx->prev_frm1 = ctx->prev_frm0; + ctx->prev_frm0 = frm; + return ret; +} + +static MPP_RET dec_vproc_update_ref(MppDecVprocCtxImpl *ctx, MppFrame frm, RK_U32 index, RK_U32 eos) +{ + MPP_RET ret = MPP_OK; + Mpp *mpp = ctx->mpp; + + ret = ctx->update_ref((MppDecVprocCtx *)ctx, frm, index); + + if (eos) { + mpp_frame_init(&frm); + mpp_frame_set_eos(frm, eos); + vproc_dbg_out("output at update ref, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, NULL, -1, 0); + dec_vproc_clr_prev(ctx); + mpp_frame_deinit(&frm); + } + return ret; +} + +static void *dec_vproc_thread(void *data) +{ + MppDecVprocCtxImpl *ctx = (MppDecVprocCtxImpl *)data; + HalTaskGroup tasks = ctx->task_group; + MppThread *thd = ctx->thd; + Mpp *mpp = ctx->mpp; + MppDecImpl *dec = (MppDecImpl *)mpp->mDec; + MppBufSlots slots = dec->frame_slots; + + HalTaskHnd task = NULL; + HalTaskInfo task_info; + HalDecVprocTask *task_vproc = &task_info.dec_vproc; + + sys_dbg_info("mpp_dec_post_proc_thread started\n"); + + while (1) { + MPP_RET ret = MPP_OK; + + mpp_thread_lock(thd, THREAD_WORK); + if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd, THREAD_WORK)) { + mpp_thread_unlock(thd, THREAD_WORK); + break; + } + + if (ctx->task_wait.val && !ctx->reset) { + vproc_dbg_status("vproc thread wait %d", ctx->task_wait.val); + mpp_thread_wait(thd, THREAD_WORK); + } + mpp_thread_unlock(thd, THREAD_WORK); + + if (!ctx->task_status.task_rdy) { + if (hal_task_get_hnd(tasks, TASK_PROCESSING, &task)) { + if (ctx->reset) { + /* reset only on all task finished */ + vproc_dbg_reset("reset start\n"); + + dec_vproc_clr_prev(ctx); + + mpp_thread_lock(thd, THREAD_CONTROL); + ctx->reset = 0; + mpp_thread_unlock(thd, THREAD_CONTROL); + sem_post(&ctx->reset_sem); + ctx->task_wait.val = 0; + + vproc_dbg_reset("reset done\n"); + continue; + } + + ctx->task_wait.task_in = 1; + continue; + } + ctx->task_status.task_rdy = 1; + ctx->task_wait.task_in = 0; + } + + if (task) { + ret = hal_task_hnd_get_info(task, &task_info); + + mpp_assert(ret == MPP_OK); + + RK_S32 index = task_vproc->input; + RK_U32 eos = task_vproc->flags.eos; + RK_U32 change = task_vproc->flags.info_change; + MppFrame frm = NULL; + + if (eos && index < 0) { + vproc_dbg_status("eos signal\n"); + + mpp_frame_init(&frm); + mpp_frame_set_eos(frm, eos); + vproc_dbg_out("output at eos, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, NULL, -1, 0); + dec_vproc_clr_prev(ctx); + mpp_frame_deinit(&frm); + + hal_task_hnd_set_status(task, TASK_IDLE); + ctx->task_status.task_rdy = 0; + continue; + } + + mpp_buf_slot_get_prop(slots, index, SLOT_FRAME_PTR, &frm); + + if (change) { + vproc_dbg_status("info change\n"); + vproc_dbg_out("output at info change, frame poc %d\n", mpp_frame_get_poc(frm)); + dec_vproc_put_frame(mpp, frm, NULL, -1, 0); + dec_vproc_clr_prev(ctx); + + if (ctx->com_ctx->ops->reset) + ctx->com_ctx->ops->reset(ctx->iep_ctx); + + hal_task_hnd_set_status(task, TASK_IDLE); + ctx->task_status.task_rdy = 0; + continue; + } + vproc_dbg_status("vproc get buf in"); + if (!ctx->task_status.buf_rdy && !ctx->reset) { + MppBuffer buf = mpp_frame_get_buffer(frm); + size_t buf_size = mpp_buffer_get_size(buf); + + if (!ctx->out_buf0) { + mpp_buffer_get(mpp->mFrameGroup, &ctx->out_buf0, buf_size); + vproc_dbg_out("get out buf0 ptr %p\n", mpp_buffer_get_ptr(ctx->out_buf0)); + if (NULL == ctx->out_buf0) { + ctx->task_wait.task_buf_in = 1; + continue; + } + } + if (!ctx->out_buf1) { + mpp_buffer_get(mpp->mFrameGroup, &ctx->out_buf1, buf_size); + vproc_dbg_out("get out buf1 ptr %p\n", mpp_buffer_get_ptr(ctx->out_buf1)); + if (NULL == ctx->out_buf1) { + ctx->task_wait.task_buf_in = 1; + continue; + } + } + ctx->task_status.buf_rdy = 1; + } + + RK_S32 tmp = -1; + mpp_buf_slot_dequeue(slots, &tmp, QUEUE_DEINTERLACE); + mpp_assert(tmp == index); + + vproc_dbg_status("vproc get buf ready & start process "); + if (!ctx->reset && ctx->iep_ctx) { + vproc_dbg_in("processing frame poc %d, mode 0x%x, err %x vs %x, buf slot %x, ptr %p\n", + mpp_frame_get_poc(frm), mpp_frame_get_mode(frm), mpp_frame_get_errinfo(frm), + mpp_frame_get_discard(frm), index, mpp_buffer_get_ptr(mpp_frame_get_buffer(frm))); + ctx->set_dei((MppDecVprocCtx *)ctx, frm); + } + + dec_vproc_update_ref(ctx, frm, index, eos); + hal_task_hnd_set_status(task, TASK_IDLE); + ctx->task_status.val = 0; + ctx->task_wait.val = 0; + + vproc_dbg_status("vproc task done"); + } + } + sys_dbg_info("mpp_dec_post_proc_thread exited\n"); + + return NULL; +} + +MPP_RET dec_vproc_init(MppDecVprocCtx *ctx, MppDecVprocCfg *cfg) +{ + MPP_RET ret = MPP_OK; + if (NULL == ctx || NULL == cfg || NULL == cfg->mpp) { + mpp_err_f("found NULL input ctx %p mpp %p\n", ctx, cfg->mpp); + return MPP_ERR_NULL_PTR; + } + + vproc_dbg_func("in\n"); + mpp_env_get_u32("vproc_debug", &vproc_debug, 0); + + *ctx = NULL; + + MppDecVprocCtxImpl *p = mpp_calloc(MppDecVprocCtxImpl, 1); + if (NULL == p) { + mpp_err_f("malloc failed\n"); + return MPP_ERR_MALLOC; + } + + p->pre_ff_mode = IEP2_FF_MODE_UND; + p->mpp = (Mpp *)cfg->mpp; + p->slots = ((MppDecImpl *)p->mpp->mDec)->frame_slots; + p->thd = mpp_thread_create(dec_vproc_thread, p, "mpp_dec_vproc"); + sem_init(&p->reset_sem, 0, 0); + ret = hal_task_group_init(&p->task_group, TASK_BUTT, 4, sizeof(HalDecVprocTask)); + if (ret) { + mpp_err_f("create task group failed\n"); + mpp_thread_destroy(p->thd); + MPP_FREE(p); + return MPP_ERR_MALLOC; + } + cfg->task_group = p->task_group; + + p->com_ctx = get_iep_ctx(); + if (!p->com_ctx) { + mpp_err("failed to require context\n"); + mpp_thread_destroy(p->thd); + + if (p->task_group) { + hal_task_group_deinit(p->task_group); + p->task_group = NULL; + } + + MPP_FREE(p); + + return MPP_ERR_MALLOC; + } + + if (p->com_ctx->ver == 1) { + p->start_dei = dec_vproc_start_dei_v1; + p->set_dei = dec_vproc_set_dei_v1; + p->update_ref = dec_vproc_update_ref_v1; + } else { + p->start_dei = dec_vproc_start_dei_v2; + p->set_dei = dec_vproc_set_dei_v2; + p->update_ref = dec_vproc_update_ref_v2; + } + + ret = p->com_ctx->ops->init(&p->com_ctx->priv); + p->iep_ctx = p->com_ctx->priv; + if (!p->thd || ret) { + mpp_err("failed to create context\n"); + if (p->thd) { + mpp_thread_destroy(p->thd); + p->thd = NULL; + } + + if (p->iep_ctx) + p->com_ctx->ops->deinit(p->iep_ctx); + + if (p->task_group) { + hal_task_group_deinit(p->task_group); + p->task_group = NULL; + } + + put_iep_ctx(p->com_ctx); + + MPP_FREE(p); + } else { + p->dei_cfg.dei_mode = IEP_DEI_MODE_I2O1; + p->dei_cfg.dei_field_order = IEP_DEI_FLD_ORDER_BOT_FIRST; + /* + * We need to turn off this switch to prevent some areas + * of the video from flickering. + */ + p->dei_cfg.dei_high_freq_en = 0; + p->dei_cfg.dei_high_freq_fct = 64; + p->dei_cfg.dei_ei_mode = 0; + p->dei_cfg.dei_ei_smooth = 1; + p->dei_cfg.dei_ei_sel = 0; + p->dei_cfg.dei_ei_radius = 2; + + p->prev_idx0 = -1; + p->prev_frm0 = NULL; + p->prev_idx1 = -1; + p->prev_frm1 = NULL; + } + + *ctx = p; + + vproc_dbg_func("out\n"); + return ret; +} + +RK_U32 dec_vproc_get_version(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return 0; + } + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + return p->com_ctx->ver; +} + +MPP_RET dec_vproc_set_mode(MppDecVprocCtx ctx, MppVprocMode mode) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + p->vproc_mode = mode; + return MPP_OK; +} + +MPP_RET dec_vproc_deinit(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_dbg_func("in\n"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + if (p->thd) { + mpp_thread_destroy(p->thd); + p->thd = NULL; + } + + if (p->iep_ctx) + p->com_ctx->ops->deinit(p->iep_ctx); + + if (p->task_group) { + hal_task_group_deinit(p->task_group); + p->task_group = NULL; + } + + if (p->com_ctx) { + put_iep_ctx(p->com_ctx); + p->com_ctx = NULL; + } + + sem_destroy(&p->reset_sem); + mpp_free(p); + + vproc_dbg_func("out\n"); + return MPP_OK; +} + +MPP_RET dec_vproc_start(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_dbg_func("in\n"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + + if (p->thd) + mpp_thread_start(p->thd); + else + mpp_err("failed to start dec vproc thread\n"); + + vproc_dbg_func("out\n"); + return MPP_OK; +} + +MPP_RET dec_vproc_stop(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_dbg_func("in\n"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + + if (p->thd) + mpp_thread_stop(p->thd); + else + mpp_err("failed to stop dec vproc thread\n"); + + vproc_dbg_func("out\n"); + return MPP_OK; +} + +MPP_RET dec_vproc_signal(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_dbg_func("in\n"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + if (p->thd) { + mpp_thread_lock(p->thd, THREAD_WORK); + mpp_thread_signal(p->thd, THREAD_WORK); + mpp_thread_unlock(p->thd, THREAD_WORK); + } + + vproc_dbg_func("out\n"); + return MPP_OK; +} + +MPP_RET dec_vproc_reset(MppDecVprocCtx ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input\n"); + return MPP_ERR_NULL_PTR; + } + vproc_dbg_func("in\n"); + + MppDecVprocCtxImpl *p = (MppDecVprocCtxImpl *)ctx; + if (p->thd) { + MppThread *thd = p->thd; + + vproc_dbg_reset("reset contorl start\n"); + // wait reset finished + mpp_thread_lock(thd, THREAD_WORK); + mpp_thread_lock(thd, THREAD_CONTROL); + p->reset = 1; + mpp_thread_signal(thd, THREAD_WORK); + mpp_thread_unlock(thd, THREAD_CONTROL); + mpp_thread_unlock(thd, THREAD_WORK); + + vproc_dbg_reset("reset contorl wait\n"); + sem_wait(&p->reset_sem); + vproc_dbg_reset("reset contorl done\n"); + + mpp_assert(p->reset == 0); + } + + vproc_dbg_func("out\n"); + return MPP_OK; +} diff --git a/mpp/vproc/mpp_vproc_dev.c b/mpp/vproc/mpp_vproc_dev.c new file mode 100644 index 000000000..6232011b5 --- /dev/null +++ b/mpp/vproc/mpp_vproc_dev.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#include "iep_common.h" + +#include "mpp_common.h" +#include "mpp_log.h" + +#include "iep_api.h" +#include "iep2_api.h" + +struct dev_compatible dev_comp[] = { +#ifdef HAVE_VPROC_IEP + { + .compatible = "/dev/iep", + .get = rockchip_iep_api_alloc_ctx, + .put = rockchip_iep_api_release_ctx, + .ver = 1, + }, +#endif +#ifdef HAVE_VPROC_IEP2 + { + .compatible = "/dev/mpp_service", + .get = rockchip_iep2_api_alloc_ctx, + .put = rockchip_iep2_api_release_ctx, + .ver = 2, + }, +#endif +}; + +iep_com_ctx* get_iep_ctx(void) +{ + uint32_t i; + + for (i = 0; i < MPP_ARRAY_ELEMS(dev_comp); ++i) { + if (!access(dev_comp[i].compatible, F_OK)) { + iep_com_ctx *ctx = dev_comp[i].get(); + + ctx->ver = dev_comp[i].ver; + mpp_log("device %s select in vproc\n", dev_comp[i].compatible); + + ctx->ops->release = dev_comp[i].put; + + return ctx; + } + } + + return NULL; +} + +void put_iep_ctx(iep_com_ctx *ictx) +{ + if (ictx->ops->release) + ictx->ops->release(ictx); +} + diff --git a/mpp/vproc/vdpp/CMakeLists.txt b/mpp/vproc/vdpp/CMakeLists.txt new file mode 100644 index 000000000..34186dd13 --- /dev/null +++ b/mpp/vproc/vdpp/CMakeLists.txt @@ -0,0 +1,25 @@ +# vim: syntax=cmake + +# ---------------------------------------------------------------------------- +# add vdpp (Video Display Post Processor) implement +# ---------------------------------------------------------------------------- +add_library(vproc_vdpp OBJECT + vdpp_api.c + vdpp.c + vdpp2.c + vdpp3.c + vdpp_common.c +) + +add_subdirectory(test) + +# libvdpp.so for hwpq +add_library(vdpp SHARED hwpq_vdpp_proc.c ../../mpp_info.c) +set_target_properties(vdpp PROPERTIES FOLDER "mpp/vproc/vdpp") +set_target_properties(vdpp PROPERTIES CLEAN_DIRECT_OUTPUT 1) +target_link_libraries(vdpp osal mpp_base kmpp_base vproc_vdpp m) +if(ANDROID) + target_link_libraries(vdpp log) +endif() +set_target_properties(vdpp PROPERTIES C_VISIBILITY_PRESET default) +set_target_properties(vdpp PROPERTIES CXX_VISIBILITY_PRESET default) diff --git a/mpp/vproc/vdpp/hwpq_debug.h b/mpp/vproc/vdpp/hwpq_debug.h new file mode 100644 index 000000000..697474efe --- /dev/null +++ b/mpp/vproc/vdpp/hwpq_debug.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef HWPQ_DEBUG_H +#define HWPQ_DEBUG_H + +#include "mpp_log.h" + +#define HWPQ_VDPP_FATAL (0x00000001) +#define HWPQ_VDPP_ERROR (0x00000002) +#define HWPQ_VDPP_WARNING (0x00000004) +#define HWPQ_VDPP_INFO (0x00000008) +#define HWPQ_VDPP_DEBUG (0x00000010) +#define HWPQ_VDPP_TRACE (0x00000020) + +#define HWPQ_VDPP_DUMP_IN (0x00000100) +#define HWPQ_VDPP_DUMP_OUT (0x00000200) + +/* log macros */ +#define hwpq_log(log_func, log_lv, fmt, ...) \ + do { \ + if (hwpq_vdpp_debug & log_lv) \ + log_func(fmt, ##__VA_ARGS__); \ + } while (0) + +#define hwpq_logf(fmt, ...) hwpq_log(mpp_logf_f, HWPQ_VDPP_FATAL, fmt, ##__VA_ARGS__) +#define hwpq_loge(fmt, ...) hwpq_log(mpp_loge_f, HWPQ_VDPP_ERROR, fmt, ##__VA_ARGS__) +#define hwpq_logw(fmt, ...) hwpq_log(mpp_logw_f, HWPQ_VDPP_WARNING, fmt, ##__VA_ARGS__) +#define hwpq_logi(fmt, ...) hwpq_log(mpp_logi_f, HWPQ_VDPP_INFO, fmt, ##__VA_ARGS__) +#define hwpq_logd(fmt, ...) hwpq_log(mpp_logi_f, HWPQ_VDPP_DEBUG, fmt, ##__VA_ARGS__) +#define hwpq_logt(fmt, ...) hwpq_log(mpp_logi_f, HWPQ_VDPP_TRACE, fmt, ##__VA_ARGS__) +#define hwpq_logv(fmt, ...) hwpq_log(mpp_logi_f, HWPQ_VDPP_TRACE, fmt, ##__VA_ARGS__) + +#define hwpq_enter() hwpq_logv("--- enter ---"); +#define hwpq_leave() hwpq_logv("--- leave ---"); + +extern RK_U32 hwpq_vdpp_debug; + +#endif /* HWPQ_DEBUG_H */ \ No newline at end of file diff --git a/mpp/vproc/vdpp/hwpq_vdpp_proc.c b/mpp/vproc/vdpp/hwpq_vdpp_proc.c new file mode 100644 index 000000000..839b40243 --- /dev/null +++ b/mpp/vproc/vdpp/hwpq_vdpp_proc.c @@ -0,0 +1,1359 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hwpq_vdpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_buffer.h" +#include "mpp_soc.h" +#include "mpp_common.h" + +#include "vdpp_api.h" +#include "hwpq_vdpp_proc_api.h" +#include "hwpq_debug.h" + +#define HWPQ_VDPP_MAX_FILE_NAME_LEN (256) +#define HWPQ_VDPP_GLOBAL_HIST_OFFSET (16 * 16 * 16 * 18 / 8) +#define HWPQ_VDPP_GLOBAL_HIST_SIZE (256) + +/* macros for debug & log */ +#define HWPQ_VDPP_DEBUG_CFG_PROP "hwpq_debug" +#define HWPQ_VDPP_DEBUG_DUMP_PATH "/data/vendor/rkalgo/" + +RK_U32 hwpq_vdpp_debug = 0; + +typedef struct VdppCtxImpl_t { + // vdpp api + VdppComCtx *vdpp; + + MppBufferGroup memGroup; + MppBuffer histbuf; + + // outut data + struct { + // hist + RK_S32 luma_avg; + HwpqVdppDciInfo dci_vdpp_info; + + // bbd + RK_S32 bbd_size_top; + RK_S32 bbd_size_bottom; + RK_S32 bbd_size_left; + RK_S32 bbd_size_right; + } output; +} VdppCtxImpl; + +static void set_dmsr_default_config(VdppApiParams *api_params) +{ + api_params->ptype = VDPP_PARAM_TYPE_DMSR; + memset(&api_params->param, 0, sizeof(VdppApiContent)); + + api_params->param.dmsr.enable = 1; + api_params->param.dmsr.str_pri_y = 10; + api_params->param.dmsr.str_sec_y = 4; + api_params->param.dmsr.dumping_y = 6; + api_params->param.dmsr.wgt_pri_gain_even_1 = 12; + api_params->param.dmsr.wgt_pri_gain_even_2 = 12; + api_params->param.dmsr.wgt_pri_gain_odd_1 = 8; + api_params->param.dmsr.wgt_pri_gain_odd_2 = 16; + api_params->param.dmsr.wgt_sec_gain = 5; + api_params->param.dmsr.blk_flat_th = 20; + api_params->param.dmsr.contrast_to_conf_map_x0 = 1680; + api_params->param.dmsr.contrast_to_conf_map_x1 = 6720; + api_params->param.dmsr.contrast_to_conf_map_y0 = 0; + api_params->param.dmsr.contrast_to_conf_map_y1 = 65535; + api_params->param.dmsr.diff_core_th0 = 1; + api_params->param.dmsr.diff_core_th1 = 5; + api_params->param.dmsr.diff_core_wgt0 = 16; + api_params->param.dmsr.diff_core_wgt1 = 16; + api_params->param.dmsr.diff_core_wgt2 = 16; + api_params->param.dmsr.edge_th_low_arr[0] = 30; + api_params->param.dmsr.edge_th_low_arr[1] = 10; + api_params->param.dmsr.edge_th_low_arr[2] = 0; + api_params->param.dmsr.edge_th_low_arr[3] = 0; + api_params->param.dmsr.edge_th_low_arr[4] = 0; + api_params->param.dmsr.edge_th_low_arr[5] = 0; + api_params->param.dmsr.edge_th_low_arr[6] = 0; + api_params->param.dmsr.edge_th_high_arr[0] = 60; + api_params->param.dmsr.edge_th_high_arr[1] = 40; + api_params->param.dmsr.edge_th_high_arr[2] = 20; + api_params->param.dmsr.edge_th_high_arr[3] = 10; + api_params->param.dmsr.edge_th_high_arr[4] = 10; + api_params->param.dmsr.edge_th_high_arr[5] = 10; + api_params->param.dmsr.edge_th_high_arr[6] = 10; +} + +static void set_zme_default_config(VdppApiParams *api_params) +{ + api_params->ptype = VDPP_PARAM_TYPE_ZME_COM; + memset(&api_params->param, 0, sizeof(VdppApiContent)); + + api_params->param.zme.bypass_enable = 1; + api_params->param.zme.dering_enable = 1; + api_params->param.zme.dering_sen_0 = 16; + api_params->param.zme.dering_sen_1 = 4; + api_params->param.zme.dering_blend_alpha = 16; + api_params->param.zme.dering_blend_beta = 13; +} + +static void set_es_default_config(VdppApiParams *api_params) +{ + static const RK_S32 diff2conf_lut_x_tmp[9] = { + 0, 1024, 2048, 3072, 4096, 6144, 8192, 12288, 65535, + }; + static const RK_S32 diff2conf_lut_y_tmp[9] = { + 0, 84, 141, 179, 204, 233, 246, 253, 255, + }; + + api_params->ptype = VDPP_PARAM_TYPE_ES; + memset(&api_params->param, 0, sizeof(VdppApiContent)); + + api_params->param.es.es_bEnabledES = 0; + api_params->param.es.es_iAngleDelta = 17; + api_params->param.es.es_iAngleDeltaExtra = 5; + api_params->param.es.es_iGradNoDirTh = 37; + api_params->param.es.es_iGradFlatTh = 75; + api_params->param.es.es_iWgtGain = 128; + api_params->param.es.es_iWgtDecay = 128; + api_params->param.es.es_iLowConfTh = 96; + api_params->param.es.es_iLowConfRatio = 32; + api_params->param.es.es_iConfCntTh = 4; + api_params->param.es.es_iWgtLocalTh = 64; + api_params->param.es.es_iK1 = 4096; + api_params->param.es.es_iK2 = 7168; + api_params->param.es.es_iDeltaLimit = 65280; + memcpy(&api_params->param.es.es_iDiff2conf_lut_x[0], &diff2conf_lut_x_tmp[0], + sizeof(diff2conf_lut_x_tmp)); + memcpy(&api_params->param.es.es_iDiff2conf_lut_y[0], &diff2conf_lut_y_tmp[0], + sizeof(diff2conf_lut_y_tmp)); + api_params->param.es.es_bEndpointCheckEnable = 1; +} + +static void set_hist_cnt_default_config(VdppApiParams *p_api_params) +{ + p_api_params->ptype = VDPP_PARAM_TYPE_HIST; + memset(&p_api_params->param, 0, sizeof(VdppApiContent)); + + p_api_params->param.hist.hist_cnt_en = 1; + p_api_params->param.hist.dci_hsd_mode = VDPP_DCI_HSD_DISABLE; + p_api_params->param.hist.dci_vsd_mode = VDPP_DCI_VSD_DISABLE; + p_api_params->param.hist.dci_yrgb_gather_num = 0; + p_api_params->param.hist.dci_yrgb_gather_en = 0; + p_api_params->param.hist.dci_csc_range = VDPP_COLOR_SPACE_LIMIT_RANGE; +} + +static void set_shp_default_config(VdppApiParams *api_params) +{ + static const RK_S32 coring_zero_tmp[7] = { + 5, 5, 8, 5, 8, 5, 5, + }; + static const RK_S32 coring_thr_tmp[7] = { + 40, 40, 40, 24, 26, 30, 26, + }; + static const RK_S32 coring_ratio_tmp[7] = { + 1479, 1188, 1024, 1422, 1024, 1024, 1024, + }; + static const RK_S32 gain_pos_tmp[7] = { + 128, 256, 512, 256, 512, 256, 256, + }; + static const RK_S32 gain_neg_tmp[7] = { + 128, 256, 512, 256, 512, 256, 256, + }; + static const RK_S32 limit_ctrl_pos0_tmp[7] = { + 64, 64, 64, 64, 64, 64, 64, + }; + static const RK_S32 limit_ctrl_pos1_tmp[7] = { + 120, 120, 120, 120, 120, 120, 120, + }; + static const RK_S32 limit_ctrl_neg0_tmp[7] = { + 64, 64, 64, 64, 64, 64, 64, + }; + static const RK_S32 limit_ctrl_neg1_tmp[7] = { + 120, 120, 120, 120, 120, 120, 120, + }; + static const RK_S32 limit_ctrl_ratio_tmp[7] = { + 128, 128, 128, 128, 128, 128, 128, + }; + static const RK_S32 limit_ctrl_bnd_pos_tmp[7] = { + 81, 131, 63, 81, 63, 63, 63, + }; + static const RK_S32 limit_ctrl_bnd_neg_tmp[7] = { + 81, 131, 63, 81, 63, 63, 63, + }; + static const RK_S32 lum_grd_tmp[6] = { + 0, 200, 300, 860, 960, 102, + }; + static const RK_S32 lum_val_tmp[6] = { + 64, 64, 64, 64, 64, 64, + }; + static const RK_S32 adp_grd_tmp[6] = { + 0, 4, 60, 180, 300, 1023, + }; + static const RK_S32 adp_val_tmp[6] = { + 64, 64, 64, 64, 64, 64, + }; + static const RK_S32 var_grd_tmp[6] = { + 0, 39, 102, 209, 500, 1023, + }; + static const RK_S32 var_val_tmp[6] = { + 64, 64, 64, 64, 64, 64, + }; + static const RK_S32 diag_adj_gain_tab_tmp[8] = { + 6, 7, 8, 9, 10, 11, 12, 13, + }; + static const RK_S32 roll_tab_pattern0[16] = { + 0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 15, + }; + static const RK_S32 roll_tab_pattern1[16] = { + 31, 31, 30, 29, 28, 27, 25, 23, 21, 19, 18, 17, 16, 16, 15, 15, + }; + static const RK_S32 roll_tab_pattern2[16] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }; + static const RK_S32 tex_grd_tmp[6] = { + 0, 128, 256, 400, 600, 1023, + }; + static const RK_S32 tex_val_tmp[6] = { + 40, 60, 80, 100, 127, 127, + }; + + api_params->ptype = VDPP_PARAM_TYPE_SHARP; + memset(&api_params->param, 0, sizeof(VdppApiContent)); + + api_params->param.sharp.sharp_enable = 1; + api_params->param.sharp.sharp_coloradj_bypass_en = 1; + + api_params->param.sharp.lti_h_enable = 0; + api_params->param.sharp.lti_h_radius = 1; + api_params->param.sharp.lti_h_slope = 100; + api_params->param.sharp.lti_h_thresold = 21; + api_params->param.sharp.lti_h_gain = 8; + api_params->param.sharp.lti_h_noise_thr_pos = 1023; + api_params->param.sharp.lti_h_noise_thr_neg = 1023; + + api_params->param.sharp.lti_v_enable = 0; + api_params->param.sharp.lti_v_radius = 1; + api_params->param.sharp.lti_v_slope = 100; + api_params->param.sharp.lti_v_thresold = 21; + api_params->param.sharp.lti_v_gain = 8; + api_params->param.sharp.lti_v_noise_thr_pos = 1023; + api_params->param.sharp.lti_v_noise_thr_neg = 1023; + + api_params->param.sharp.cti_h_enable = 0; + api_params->param.sharp.cti_h_radius = 1; + api_params->param.sharp.cti_h_slope = 100; + api_params->param.sharp.cti_h_thresold = 21; + api_params->param.sharp.cti_h_gain = 8; + api_params->param.sharp.cti_h_noise_thr_pos = 1023; + api_params->param.sharp.cti_h_noise_thr_neg = 1023; + + api_params->param.sharp.peaking_enable = 1; + api_params->param.sharp.peaking_gain = 196; + + api_params->param.sharp.peaking_coring_enable = 1; + api_params->param.sharp.peaking_limit_ctrl_enable = 1; + api_params->param.sharp.peaking_gain_enable = 1; + + memcpy(api_params->param.sharp.peaking_coring_zero, coring_zero_tmp, sizeof(coring_zero_tmp)); + memcpy(api_params->param.sharp.peaking_coring_thr, coring_thr_tmp, sizeof(coring_thr_tmp)); + memcpy(api_params->param.sharp.peaking_coring_ratio, coring_ratio_tmp, sizeof(coring_ratio_tmp)); + memcpy(api_params->param.sharp.peaking_gain_pos, gain_pos_tmp, sizeof(gain_pos_tmp)); + memcpy(api_params->param.sharp.peaking_gain_neg, gain_neg_tmp, sizeof(gain_neg_tmp)); + memcpy(api_params->param.sharp.peaking_limit_ctrl_pos0, limit_ctrl_pos0_tmp, + sizeof(limit_ctrl_pos0_tmp)); + memcpy(api_params->param.sharp.peaking_limit_ctrl_pos1, limit_ctrl_pos1_tmp, + sizeof(limit_ctrl_pos1_tmp)); + memcpy(api_params->param.sharp.peaking_limit_ctrl_neg0, limit_ctrl_neg0_tmp, + sizeof(limit_ctrl_neg0_tmp)); + memcpy(api_params->param.sharp.peaking_limit_ctrl_neg1, limit_ctrl_neg1_tmp, + sizeof(limit_ctrl_neg1_tmp)); + memcpy(api_params->param.sharp.peaking_limit_ctrl_ratio, limit_ctrl_ratio_tmp, + sizeof(limit_ctrl_ratio_tmp)); + memcpy(api_params->param.sharp.peaking_limit_ctrl_bnd_pos, limit_ctrl_bnd_pos_tmp, + sizeof(limit_ctrl_bnd_pos_tmp)); + memcpy(api_params->param.sharp.peaking_limit_ctrl_bnd_neg, limit_ctrl_bnd_neg_tmp, + sizeof(limit_ctrl_bnd_neg_tmp)); + + api_params->param.sharp.peaking_edge_ctrl_enable = 1; + api_params->param.sharp.peaking_edge_ctrl_non_dir_thr = 16; + api_params->param.sharp.peaking_edge_ctrl_dir_cmp_ratio = 4; + api_params->param.sharp.peaking_edge_ctrl_non_dir_wgt_offset = 64; + api_params->param.sharp.peaking_edge_ctrl_non_dir_wgt_ratio = 16; + api_params->param.sharp.peaking_edge_ctrl_dir_cnt_thr = 2; + api_params->param.sharp.peaking_edge_ctrl_dir_cnt_avg = 3; + api_params->param.sharp.peaking_edge_ctrl_dir_cnt_offset = 2; + api_params->param.sharp.peaking_edge_ctrl_diag_dir_thr = 16; + + memcpy(api_params->param.sharp.peaking_edge_ctrl_diag_adj_gain_tab, diag_adj_gain_tab_tmp, + sizeof(diag_adj_gain_tab_tmp)); + + api_params->param.sharp.peaking_estc_enable = 1; + api_params->param.sharp.peaking_estc_delta_offset_h = 4; + api_params->param.sharp.peaking_estc_alpha_over_h = 8; + api_params->param.sharp.peaking_estc_alpha_under_h = 16; + api_params->param.sharp.peaking_estc_alpha_over_unlimit_h = 64; + api_params->param.sharp.peaking_estc_alpha_under_unlimit_h = 112; + api_params->param.sharp.peaking_estc_delta_offset_v = 4; + api_params->param.sharp.peaking_estc_alpha_over_v = 8; + api_params->param.sharp.peaking_estc_alpha_under_v = 16; + api_params->param.sharp.peaking_estc_alpha_over_unlimit_v = 64; + api_params->param.sharp.peaking_estc_alpha_under_unlimit_v = 112; + api_params->param.sharp.peaking_estc_delta_offset_d0 = 4; + api_params->param.sharp.peaking_estc_alpha_over_d0 = 16; + api_params->param.sharp.peaking_estc_alpha_under_d0 = 16; + api_params->param.sharp.peaking_estc_alpha_over_unlimit_d0 = 96; + api_params->param.sharp.peaking_estc_alpha_under_unlimit_d0 = 96; + api_params->param.sharp.peaking_estc_delta_offset_d1 = 4; + api_params->param.sharp.peaking_estc_alpha_over_d1 = 16; + api_params->param.sharp.peaking_estc_alpha_under_d1 = 16; + api_params->param.sharp.peaking_estc_alpha_over_unlimit_d1 = 96; + api_params->param.sharp.peaking_estc_alpha_under_unlimit_d1 = 96; + api_params->param.sharp.peaking_estc_delta_offset_non = 4; + api_params->param.sharp.peaking_estc_alpha_over_non = 8; + api_params->param.sharp.peaking_estc_alpha_under_non = 8; + api_params->param.sharp.peaking_estc_alpha_over_unlimit_non = 112; + api_params->param.sharp.peaking_estc_alpha_under_unlimit_non = 112; + api_params->param.sharp.peaking_filter_cfg_diag_enh_coef = 6; + + api_params->param.sharp.peaking_filt_core_H0[0] = 4; + api_params->param.sharp.peaking_filt_core_H0[1] = 16; + api_params->param.sharp.peaking_filt_core_H0[2] = 24; + api_params->param.sharp.peaking_filt_core_H1[0] = -16; + api_params->param.sharp.peaking_filt_core_H1[1] = 0; + api_params->param.sharp.peaking_filt_core_H1[2] = 32; + api_params->param.sharp.peaking_filt_core_H2[0] = 0; + api_params->param.sharp.peaking_filt_core_H2[1] = -16; + api_params->param.sharp.peaking_filt_core_H2[2] = 32; + api_params->param.sharp.peaking_filt_core_V0[0] = 1; + api_params->param.sharp.peaking_filt_core_V0[1] = 4; + api_params->param.sharp.peaking_filt_core_V0[2] = 6; + api_params->param.sharp.peaking_filt_core_V1[0] = -4; + api_params->param.sharp.peaking_filt_core_V1[1] = 0; + api_params->param.sharp.peaking_filt_core_V1[2] = 8; + api_params->param.sharp.peaking_filt_core_V2[0] = 0; + api_params->param.sharp.peaking_filt_core_V2[1] = -4; + api_params->param.sharp.peaking_filt_core_V2[2] = 8; + api_params->param.sharp.peaking_filt_core_USM[0] = 1; + api_params->param.sharp.peaking_filt_core_USM[1] = 4; + api_params->param.sharp.peaking_filt_core_USM[2] = 6; + + api_params->param.sharp.shootctrl_enable = 1; + api_params->param.sharp.shootctrl_filter_radius = 1; + api_params->param.sharp.shootctrl_delta_offset = 16; + api_params->param.sharp.shootctrl_alpha_over = 8; + api_params->param.sharp.shootctrl_alpha_under = 8; + api_params->param.sharp.shootctrl_alpha_over_unlimit = 112; + api_params->param.sharp.shootctrl_alpha_under_unlimit = 112; + + api_params->param.sharp.global_gain_enable = 0; + api_params->param.sharp.global_gain_lum_mode = 0; + + memcpy(api_params->param.sharp.global_gain_lum_grd, lum_grd_tmp, sizeof(lum_grd_tmp)); + memcpy(api_params->param.sharp.global_gain_lum_val, lum_val_tmp, sizeof(lum_val_tmp)); + memcpy(api_params->param.sharp.global_gain_adp_grd, adp_grd_tmp, sizeof(adp_grd_tmp)); + memcpy(api_params->param.sharp.global_gain_adp_val, adp_val_tmp, sizeof(adp_val_tmp)); + memcpy(api_params->param.sharp.global_gain_var_grd, var_grd_tmp, sizeof(var_grd_tmp)); + memcpy(api_params->param.sharp.global_gain_var_val, var_val_tmp, sizeof(var_val_tmp)); + + api_params->param.sharp.color_ctrl_enable = 0; + + api_params->param.sharp.color_ctrl_p0_scaling_coef = 1; + api_params->param.sharp.color_ctrl_p0_point_u = 115; + api_params->param.sharp.color_ctrl_p0_point_v = 155; + memcpy(api_params->param.sharp.color_ctrl_p0_roll_tab, roll_tab_pattern0, sizeof(roll_tab_pattern0)); + api_params->param.sharp.color_ctrl_p1_scaling_coef = 1; + api_params->param.sharp.color_ctrl_p1_point_u = 90; + api_params->param.sharp.color_ctrl_p1_point_v = 120; + memcpy(api_params->param.sharp.color_ctrl_p1_roll_tab, roll_tab_pattern1, sizeof(roll_tab_pattern1)); + api_params->param.sharp.color_ctrl_p2_scaling_coef = 1; + api_params->param.sharp.color_ctrl_p2_point_u = 128; + api_params->param.sharp.color_ctrl_p2_point_v = 128; + memcpy(api_params->param.sharp.color_ctrl_p2_roll_tab, roll_tab_pattern2, sizeof(roll_tab_pattern2)); + api_params->param.sharp.color_ctrl_p3_scaling_coef = 1; + api_params->param.sharp.color_ctrl_p3_point_u = 128; + api_params->param.sharp.color_ctrl_p3_point_v = 128; + memcpy(api_params->param.sharp.color_ctrl_p3_roll_tab, roll_tab_pattern2, sizeof(roll_tab_pattern2)); + + api_params->param.sharp.tex_adj_enable = 0; + api_params->param.sharp.tex_adj_y_mode_select = 3; + api_params->param.sharp.tex_adj_mode_select = 0; + + memcpy(api_params->param.sharp.tex_adj_grd, tex_grd_tmp, sizeof(tex_grd_tmp)); + memcpy(api_params->param.sharp.tex_adj_val, tex_val_tmp, sizeof(tex_val_tmp)); +} + +static void set_pyr_default_config(VdppApiParams *api_params) +{ + api_params->ptype = VDPP_PARAM_TYPE_PYR; + memset(&api_params->param, 0, sizeof(VdppApiContent)); + + api_params->param.pyr.pyr_en = 0; +} + +static void set_bbd_default_config(VdppApiParams *api_params) +{ + api_params->ptype = VDPP_PARAM_TYPE_BBD; + memset(&api_params->param, 0, sizeof(VdppApiContent)); + + api_params->param.bbd.bbd_en = 0; + api_params->param.bbd.bbd_det_blcklmt = 20; +} + +static RK_S32 vdpp_set_user_cfg(VdppComCtx *ctx, const HwpqVdppParams *hwpq_param, + RK_U32 cfg_update_flag) +{ + VdppApiParams params; + const HwpqVdppConfig *hwpq_config = &hwpq_param->vdpp_config; + const RK_S32 vdpp_ver = MPP_MAX(ctx->ver >> 8, 1); + RK_S32 i = 0; + RK_S32 ret = MPP_OK; + + if (cfg_update_flag == 0) { + hwpq_logw("vdpp config not update since cfg_update_flag==0.\n"); + return ret; + } + + hwpq_enter(); + hwpq_logd("update vdpp config... vdpp_ver=%d, hist_only_mode=%d\n", + vdpp_ver, hwpq_param->hist_mode_en); + + /* set vdpp1 configs */ + { + set_dmsr_default_config(¶ms); + params.param.dmsr.enable = hwpq_config->dmsr_en; + params.param.dmsr.str_pri_y = hwpq_config->str_pri_y; + params.param.dmsr.str_sec_y = hwpq_config->str_sec_y; + params.param.dmsr.dumping_y = hwpq_config->dumping_y; + ret |= ctx->ops->control(ctx->priv, VDPP_CMD_SET_DMSR_CFG, ¶ms); + hwpq_logv("set api param: dmsr.enable=%d\n", params.param.dmsr.enable); + + set_zme_default_config(¶ms); + params.param.zme.dering_enable = hwpq_config->zme_dering_en; + ctx->ops->control(ctx->priv, VDPP_CMD_SET_ZME_COM_CFG, ¶ms); + hwpq_logv("set api param: zme.bypass_enable=%d\n", params.param.zme.bypass_enable); + } + + /* set vdpp2 configs */ + if (vdpp_ver >= 2) { + set_es_default_config(¶ms); + params.param.es.es_bEnabledES = hwpq_config->es_en; + params.param.es.es_iWgtGain = hwpq_config->es_iWgtGain; + ret |= ctx->ops->control(ctx->priv, VDPP_CMD_SET_ES, ¶ms); + hwpq_logv("set api param: es.es_en=%d\n", params.param.es.es_bEnabledES); + + // set hist regs. NOTE that 'hist_fd' not set here! + set_hist_cnt_default_config(¶ms); + params.param.hist.hist_cnt_en = hwpq_config->hist_cnt_en; + params.param.hist.dci_csc_range = hwpq_config->hist_csc_range; + ret |= ctx->ops->control(ctx->priv, VDPP_CMD_SET_DCI_HIST, ¶ms); + hwpq_logv("set api param: hist.hist_en: %d\n", params.param.hist.hist_cnt_en); + + set_shp_default_config(¶ms); + params.param.sharp.sharp_enable = hwpq_config->shp_en; + params.param.sharp.peaking_gain = hwpq_config->peaking_gain; + params.param.sharp.shootctrl_enable = hwpq_config->shp_shoot_ctrl_en; + params.param.sharp.shootctrl_alpha_over = hwpq_config->shp_shoot_ctrl_over; + params.param.sharp.shootctrl_alpha_under = hwpq_config->shp_shoot_ctrl_under; + ret |= ctx->ops->control(ctx->priv, VDPP_CMD_SET_SHARP, ¶ms); + hwpq_logv("set api param: sharp.shp_en=%d\n", params.param.sharp.sharp_enable); + } + + /* set vdpp3 configs */ + if (vdpp_ver >= 3) { + set_pyr_default_config(¶ms); + params.param.pyr.pyr_en = hwpq_config->pyr_en && !hwpq_param->hist_mode_en && + hwpq_config->pyr_layers[0].img_yrgb.fd > 0 && + hwpq_config->pyr_layers[1].img_yrgb.fd > 0 && + hwpq_config->pyr_layers[2].img_yrgb.fd > 0; + hwpq_logv("set api param: pyr_en=%d\n", params.param.pyr.pyr_en); + if (params.param.pyr.pyr_en) { + params.param.pyr.nb_layers = 3; + for (i = 0; i < 3; i++) { + params.param.pyr.layer_imgs[i].mem_addr = hwpq_config->pyr_layers[i].img_yrgb.fd; + params.param.pyr.layer_imgs[i].wid_vir = hwpq_config->pyr_layers[i].img_yrgb.w_vir; + hwpq_logv("set api param: pyr[%d] addr=%u, wid_vir=%u (unit: pixel)\n", + i + 1, params.param.pyr.layer_imgs[i].mem_addr, + params.param.pyr.layer_imgs[i].wid_vir); + } + } + ret |= ctx->ops->control(ctx->priv, VDPP_CMD_SET_PYR, ¶ms); + + set_bbd_default_config(¶ms); + params.param.bbd.bbd_en = hwpq_config->bbd_en; + params.param.bbd.bbd_det_blcklmt = hwpq_config->bbd_threshold; + ret |= ctx->ops->control(ctx->priv, VDPP_CMD_SET_BBD, ¶ms); + hwpq_logv("set api param: bbd_en=%d, bbd_det_blcklmt=%d\n", params.param.bbd.bbd_en, + params.param.bbd.bbd_det_blcklmt); + } + + hwpq_leave(); + return ret; +} + +static MPP_RET vdpp_set_img(VdppComCtx *ctx, RK_S32 fd_yrgb, RK_S32 fd_cbcr, + RK_S32 cbcr_offset, VdppCmd cmd) +{ + VdppImg img; + + img.mem_addr = fd_yrgb; + img.uv_addr = fd_cbcr; + img.uv_off = cbcr_offset; + + hwpq_logd("set buf: type=%#x, yrgb_fd=%d, cbcr_fd=%d, cbcr_offset=%d\n", + cmd, fd_yrgb, fd_cbcr, cbcr_offset); + + return ctx->ops->control(ctx->priv, cmd, &img); +} + +static void *vdpp_map_buffer_with_fd(RK_S32 fd, size_t bufSize) +{ + void *ptr = NULL; + + if (fd > 0) { + ptr = mmap(NULL, bufSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + hwpq_loge("failed to mmap buffer, fd=%d, size=%zu\n", fd, bufSize); + return NULL; + } + } else { + hwpq_loge("failed to mmap buffer with invalid fd %d\n", fd); + } + + return ptr; +} + +static inline void vdpp_unmap_buffer(void *ptr, size_t bufSize) +{ + if (ptr) { + munmap(ptr, bufSize); + } +} + +#if 0 +static FILE *try_env_file(const char *env, const char *path, RK_S32 index) +{ + const char *fname = NULL; + FILE *fp = NULL; + char name[HWPQ_VDPP_MAX_FILE_NAME_LEN]; + pid_t tid = syscall(SYS_gettid); + + mpp_env_get_str(env, &fname, path); + if (fname == path) { + snprintf(name, sizeof(name) - 1, "%s_%03d-%d", path, index, tid); + fname = name; + } + + fp = fopen(fname, "w+b"); + hwpq_logi("open %s %p for dump\n", fname, fp); + + return fp; +} +#endif + +static void vdpp_dump_bufs(HwpqVdppParams *p_proc_param, RK_S32 index) +{ + FILE *fp_in = NULL; + FILE *fp_out = NULL; + char filename[256] = {0}; + (void)index; + + if (NULL == p_proc_param) { + hwpq_loge("found NULL proc_param %p!\n", p_proc_param); + return; + } + + if (hwpq_vdpp_debug & HWPQ_VDPP_DUMP_IN) { + RK_S32 map_flag = 0; + const HwpqVdppImgInfo *src_info = &p_proc_param->src_img_info; + + snprintf(filename, 255, "%s/hwpq_vdpp_in_%dx%d_fmt%d.bin", HWPQ_VDPP_DEBUG_DUMP_PATH, + src_info->img_yrgb.w_vir, src_info->img_yrgb.h_vir, src_info->img_fmt); + + // fp_in = try_env_file("hwpq_vdpp_dump_in", filename, tid, index); + fp_in = fopen(filename, "w+b"); + if (NULL == fp_in) { + hwpq_logw("failed to open file %s! %s\n", filename, strerror(errno)); + } else { + RK_S32 fd = src_info->img_yrgb.fd; + RK_U32 buf_size = src_info->img_yrgb.w_vir * src_info->img_yrgb.h_vir + + src_info->img_cbcr.w_vir * src_info->img_cbcr.h_vir * 2; + void *ptr = src_info->img_yrgb.addr; + + if (!ptr) { + vdpp_map_buffer_with_fd(fd, buf_size); + map_flag = 1; + } + + if (ptr == NULL) + hwpq_logw("vdpp dump fd(%d) map error!\n", fd); + else + fwrite(ptr, 1, buf_size, fp_in); + + fclose(fp_in); + if (map_flag) + vdpp_unmap_buffer(ptr, buf_size); + + hwpq_logi("dump input buffer to: %s, fd=%d, addr=%p, size=%u\n", + filename, fd, ptr, buf_size); + } + } + + if (hwpq_vdpp_debug & HWPQ_VDPP_DUMP_OUT) { + const HwpqVdppImgInfo *dst_info = &p_proc_param->dst_img_info; + + snprintf(filename, 255, "%s/hwpq_vdpp_out_%dx%d_fmt%d.bin", HWPQ_VDPP_DEBUG_DUMP_PATH, + dst_info->img_yrgb.w_vir, dst_info->img_yrgb.h_vir, dst_info->img_fmt); + + // fp_out = try_env_file("hwpq_vdpp_dump_out", filename, tid, index); + fp_out = fopen(filename, "w+b"); + if (NULL == fp_out) { + hwpq_logw("failed to open file %s! %s\n", filename, strerror(errno)); + } else { + RK_U32 map_size_y = 0; + RK_U32 map_size_c = 0; + RK_U32 buf_size_y = dst_info->img_yrgb.w_vir * dst_info->img_yrgb.h_vir; + RK_U32 buf_size_c = dst_info->img_cbcr.w_vir * dst_info->img_cbcr.h_vir * 2; + void *ptr_y = dst_info->img_yrgb.addr; + void *ptr_c = dst_info->img_cbcr.addr + ? (char *)dst_info->img_cbcr.addr + dst_info->img_cbcr.offset + : NULL; + + // map buffer first if needed + if (ptr_y == NULL) { + if (dst_info->img_yrgb.fd == dst_info->img_cbcr.fd) { + ptr_y = vdpp_map_buffer_with_fd(dst_info->img_yrgb.fd, buf_size_y + buf_size_c); + map_size_y = buf_size_y + buf_size_c; + if (ptr_c == NULL) + ptr_c = (char *)ptr_y + dst_info->img_cbcr.offset; + } else { + ptr_y = vdpp_map_buffer_with_fd(dst_info->img_yrgb.fd, buf_size_y); + map_size_y = buf_size_y; + } + } + if (ptr_c == NULL) { + if (dst_info->img_yrgb.fd == dst_info->img_cbcr.fd) + ptr_c = (char *)ptr_y + dst_info->img_cbcr.offset; + else { + ptr_c = (char *)vdpp_map_buffer_with_fd(dst_info->img_cbcr.fd, buf_size_c); + map_size_c = buf_size_c; + } + } + + if (ptr_y) + fwrite(ptr_y, 1, buf_size_y, fp_out); + if (ptr_c) + fwrite(ptr_c, 1, buf_size_c, fp_out); + + fclose(fp_out); + if (map_size_y > 0) + vdpp_unmap_buffer(ptr_y, map_size_y); + if (map_size_c > 0) + vdpp_unmap_buffer(ptr_c, map_size_c); + + hwpq_logi("dump output buffer to: %s, y/c_fd=%d/%d, addr=%p/%p, size=%u/%u\n", + filename, dst_info->img_yrgb.fd, dst_info->img_cbcr.fd, + ptr_y, ptr_c, buf_size_y, buf_size_c); + } + } + + MPP_FCLOSE(fp_in); + MPP_FCLOSE(fp_out); +} + +static MppFrameFormat img_format_convert(HwpqVdppFormat img_fmt_in) +{ + MppFrameFormat img_fmt_out = MPP_FMT_YUV420SP; + + switch (img_fmt_in) { + case VDPP_FMT_NV24: { + img_fmt_out = MPP_FMT_YUV444SP; + } break; + case VDPP_FMT_NV16: { + img_fmt_out = MPP_FMT_YUV422SP; + } break; + case VDPP_FMT_NV12: { + img_fmt_out = MPP_FMT_YUV420SP; + } break; + case VDPP_FMT_Y_ONLY_8BIT: { + img_fmt_out = MPP_FMT_YUV400; + } break; + case VDPP_FMT_NV15: + case VDPP_FMT_NV20: + case VDPP_FMT_NV30: { + img_fmt_out = MPP_FMT_YUV420SP_10BIT; + } break; + case VDPP_FMT_RGBA: { + img_fmt_out = MPP_FMT_RGBA8888; + } break; + case VDPP_FMT_RG24: { + img_fmt_out = MPP_FMT_RGB888; + } break; + case VDPP_FMT_BG24: { + img_fmt_out = MPP_FMT_BGR888; + } break; + default: { + hwpq_loge("unsupport input format(%x), set to NV12 !!", img_fmt_in); + } break; + } + + return img_fmt_out; +} + +static VdppFmt vdpp_format_convert(HwpqVdppFormat img_fmt_in) +{ + VdppFmt img_fmt_out = VDPP_FMT_YUV444; + + switch (img_fmt_in) { + case VDPP_FMT_NV24: + case VDPP_FMT_NV42: { + img_fmt_out = VDPP_FMT_YUV444; + } break; + case VDPP_FMT_NV12: + case VDPP_FMT_NV21: { + img_fmt_out = VDPP_FMT_YUV420; + } break; + default: { + hwpq_loge("unsupport output format(%d), force set to NV24 !!", img_fmt_in); + } break; + } + + return img_fmt_out; +} + +static VdppYuvSwap get_img_format_swap(HwpqVdppFormat img_fmt_in) +{ + VdppYuvSwap img_fmt_swap = VDPP_YUV_SWAP_SP_UV; + + switch (img_fmt_in) { + case VDPP_FMT_NV42: + case VDPP_FMT_NV61: + case VDPP_FMT_NV21: { + img_fmt_swap = VDPP_YUV_SWAP_SP_VU; + } break; + default: { + img_fmt_swap = VDPP_YUV_SWAP_SP_UV; + } break; + } + + return img_fmt_swap; +} + +static void dump_vdpp_params(const HwpqVdppParams *params) +{ + const HwpqVdppConfig *config = ¶ms->vdpp_config; + + hwpq_logv("dump vdpp proc params below:\n"); + hwpq_logv(" - vdpp_config_update_flag: %d, frame_idx: %d\n", + params->vdpp_config_update_flag, params->frame_idx); + hwpq_logv(" - src_img_info: fmt=%d, fd=%d, size=%dx%d, vir_size=%dx%d, offset=%d\n", + params->src_img_info.img_fmt, params->src_img_info.img_yrgb.fd, + params->src_img_info.img_yrgb.w_vld, params->src_img_info.img_yrgb.h_vld, + params->src_img_info.img_yrgb.w_vir, params->src_img_info.img_yrgb.h_vir, + params->src_img_info.img_yrgb.offset); + hwpq_logv(" - dst_img_info: fmt=%d, fd=%d, size=%dx%d, vir_size=%dx%d, offset=%d\n", + params->dst_img_info.img_fmt, params->dst_img_info.img_yrgb.fd, + params->dst_img_info.img_yrgb.w_vld, params->dst_img_info.img_yrgb.h_vld, + params->dst_img_info.img_yrgb.w_vir, params->dst_img_info.img_yrgb.h_vir, + params->dst_img_info.img_yrgb.offset); + hwpq_logv(" - yuv_diff_flag: %d\n", params->yuv_diff_flag); + if (params->yuv_diff_flag) { + hwpq_logv(" - dst_img_info chroma: fd=%d, size=%dx%d, vir_size=%dx%d, offset=%d\n", + params->dst_img_info.img_cbcr.fd, params->dst_img_info.img_cbcr.w_vld, + params->dst_img_info.img_cbcr.h_vld, params->dst_img_info.img_cbcr.w_vir, + params->dst_img_info.img_cbcr.h_vir, params->dst_img_info.img_cbcr.offset); + } + hwpq_logv(" - dmsr_en: %d, str_pri_y: %d, str_sec_y: %d, dumping_y: %d\n", + config->dmsr_en, config->str_pri_y, config->str_sec_y, config->dumping_y); + hwpq_logv(" - es_en: %d, es_iWgtGain: %d\n", config->es_en, config->es_iWgtGain); + hwpq_logv(" - shp_en: %d, peaking_gain: %d, shoot_ctrl_en: %d, shoot_ctrl_over/under: %d/%d\n", + config->shp_en, config->peaking_gain, config->shp_shoot_ctrl_en, + config->shp_shoot_ctrl_over, config->shp_shoot_ctrl_under); + hwpq_logv(" - zme_dering_en: %d\n", config->zme_dering_en); + hwpq_logv(" - hist_en: %d, hist_only_mode: %d, csc_range: %d, vsd: %d, hsd: %d, user_hist_buf: " + "fd=%d, addr=%p\n", + config->hist_cnt_en, params->hist_mode_en, config->hist_csc_range, + config->hist_vsd_mode, config->hist_hsd_mode, params->hist_buf_fd, params->p_hist_buf); + hwpq_logv(" - pyr_en: %d, fds: %d/%d/%d, addrs: %p/%p/%p\n", params->vdpp_config.pyr_en, + config->pyr_layers[0].img_yrgb.fd, config->pyr_layers[1].img_yrgb.fd, + config->pyr_layers[2].img_yrgb.fd, config->pyr_layers[0].img_yrgb.addr, + config->pyr_layers[1].img_yrgb.addr, config->pyr_layers[2].img_yrgb.addr); + hwpq_logv(" - bbd_en: %d, threshold: %d\n", config->bbd_en, config->bbd_threshold); +} + +int hwpq_vdpp_deinit(HwpqVdppContext ctx) +{ + VdppCtxImpl *ctx_impl = (VdppCtxImpl *)ctx; + VdppComCtx *ctx_com = NULL; + MPP_RET ret = MPP_NOK; + + if (NULL == ctx) { + hwpq_loge("found NULL input ctx %p!\n", ctx); + ret = MPP_ERR_NULL_PTR; + goto __RET; + } + + ctx_com = ctx_impl->vdpp; + if (NULL == ctx_com || NULL == ctx_com->ops) { + hwpq_loge("found NULL vdpp!\n"); + ret = MPP_ERR_NULL_PTR; + goto __RET; + } + + hwpq_enter(); + + if (ctx_com->ops->deinit) { + ret = ctx_com->ops->deinit(ctx_com->priv); + if (ret) { + hwpq_loge("vdpp deinit failed! ret %d\n", ret); + } + } + + if (ctx_impl->histbuf) { + mpp_buffer_put(ctx_impl->histbuf); + ctx_impl->histbuf = NULL; + } + + if (ctx_impl->memGroup) { + mpp_buffer_group_put(ctx_impl->memGroup); + ctx_impl->memGroup = NULL; + } + + rockchip_vdpp_api_release_ctx(ctx_com); + MPP_FREE(ctx_impl); + +__RET: + hwpq_leave(); + return ret; +} + +int hwpq_vdpp_init(HwpqVdppContext *p_ctx_ptr) +{ + VdppCtxImpl *ctx_impl = NULL; + VdppComCtx *ctx_com = NULL; + MppBufferGroup memGroup = NULL; + MppBuffer histbuf = NULL; + void *phist = NULL; + RK_S32 fdhist = 0; + MPP_RET ret = MPP_NOK; + + if (NULL == p_ctx_ptr) { + hwpq_loge("found NULL vdpp ctx pointer\n"); + ret = MPP_ERR_NULL_PTR; + goto __ERR; + } + + /* get env */ + mpp_env_get_u32(HWPQ_VDPP_DEBUG_CFG_PROP, &hwpq_vdpp_debug, 0); + hwpq_logi("get env '%s' flag: %#x", HWPQ_VDPP_DEBUG_CFG_PROP, hwpq_vdpp_debug); + + hwpq_enter(); + + /* alloc vdpp ctx impl */ + ctx_impl = mpp_malloc(VdppCtxImpl, 1); + if (NULL == ctx_impl) { + hwpq_loge("alloc vdpp ctx failed!"); + ret = MPP_ERR_MALLOC; + goto __ERR; + } + + /* alloc vdpp com ctx */ + ctx_com = rockchip_vdpp_api_alloc_ctx(); + if (NULL == ctx_com || NULL == ctx_com->ops) { + hwpq_loge("alloc vdpp ctx failed!"); + ret = MPP_ERR_MALLOC; + goto __ERR; + } + + /* alloc buffer group */ + ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_DRM); + if (ret) { + hwpq_loge("memGroup mpp_buffer_group_get failed! %d\n", ret); + ret = MPP_NOK; + goto __ERR; + } + + ret = mpp_buffer_get(memGroup, &histbuf, VDPP_HIST_LENGTH); + if (ret) { + hwpq_loge("alloc histbuf failed!\n", ret); + ret = MPP_NOK; + goto __ERR; + } + + phist = mpp_buffer_get_ptr(histbuf); + fdhist = mpp_buffer_get_fd(histbuf); + hwpq_logd("create internal histbuf(fd=%d, addr=%p) inside context.\n", fdhist, phist); + + if (ctx_com->ops->init) { + ret = ctx_com->ops->init(ctx_com->priv); + if (ret) { + hwpq_loge("vdpp init failed! ret %d\n", ret); + goto __ERR; + } + } + + ctx_impl->vdpp = ctx_com; + ctx_impl->memGroup = memGroup; + ctx_impl->histbuf = histbuf; + *p_ctx_ptr = (HwpqVdppContext)ctx_impl; + + hwpq_leave(); + return ret; + +__ERR: + if (histbuf) { + mpp_buffer_put(histbuf); + histbuf = NULL; + } + + if (memGroup) { + mpp_buffer_group_put(memGroup); + memGroup = NULL; + } + + rockchip_vdpp_api_release_ctx(ctx_com); + MPP_FREE(ctx_impl); + + hwpq_leave(); + return ret; +} + +static MPP_RET hwpq_vdpp_common_config(VdppComCtx *ctx, const HwpqVdppParams *p_proc_param) +{ + VdppApiParams params = {0}; + RK_S32 vdpp_ver = MPP_MAX(ctx->ver >> 8, 1); + RK_U32 hist_only_mode = p_proc_param->hist_mode_en; + RK_U32 yuv_out_diff = (p_proc_param->yuv_diff_flag && (vdpp_ver >= 2)); + MPP_RET ret = MPP_NOK; + + hwpq_enter(); + hwpq_logd("vdpp_ver: %d, yuv_diff: %d\n", vdpp_ver, yuv_out_diff); + + /* set common params */ + if (vdpp_ver >= 2) { + params.ptype = VDPP_PARAM_TYPE_COM2; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.com2.sfmt = img_format_convert(p_proc_param->src_img_info.img_fmt); + params.param.com2.sswap = get_img_format_swap(p_proc_param->src_img_info.img_fmt); + params.param.com2.src_width = p_proc_param->src_img_info.img_yrgb.w_vld; + params.param.com2.src_height = p_proc_param->src_img_info.img_yrgb.h_vld; + params.param.com2.src_width_vir = p_proc_param->src_img_info.img_yrgb.w_vir; + params.param.com2.src_height_vir = p_proc_param->src_img_info.img_yrgb.h_vir; + params.param.com2.src_range = p_proc_param->vdpp_config.hist_csc_range; + params.param.com2.dfmt = vdpp_format_convert(p_proc_param->dst_img_info.img_fmt); + params.param.com2.dswap = get_img_format_swap(p_proc_param->dst_img_info.img_fmt); + params.param.com2.dst_width = p_proc_param->dst_img_info.img_yrgb.w_vld; + params.param.com2.dst_height = p_proc_param->dst_img_info.img_yrgb.h_vld; + params.param.com2.dst_width_vir = p_proc_param->dst_img_info.img_yrgb.w_vir; + params.param.com2.dst_height_vir = p_proc_param->dst_img_info.img_yrgb.h_vir; + if (yuv_out_diff) { + params.param.com2.yuv_out_diff = yuv_out_diff; + params.param.com2.dst_c_width = p_proc_param->dst_img_info.img_cbcr.w_vld; + params.param.com2.dst_c_height = p_proc_param->dst_img_info.img_cbcr.h_vld; + params.param.com2.dst_c_width_vir = p_proc_param->dst_img_info.img_cbcr.w_vir; + params.param.com2.dst_c_height_vir = p_proc_param->dst_img_info.img_cbcr.h_vir; + } + params.param.com2.hist_mode_en = hist_only_mode; + ret = ctx->ops->control(ctx->priv, VDPP_CMD_SET_COM2_CFG, ¶ms); + + hwpq_logv("set api param: sfmt=%d, sswap=%d, src_range=%d, size=%dx%d [%dx%d]\n", + params.param.com2.sfmt, params.param.com2.sswap, params.param.com2.src_range, + params.param.com2.src_width, params.param.com2.src_height, + params.param.com2.src_width_vir, params.param.com2.src_height_vir); + hwpq_logv("set api param: dfmt=%d, dswap=%d, size=%dx%d [%dx%d]\n", + params.param.com2.dfmt, params.param.com2.dswap, + params.param.com2.dst_width, params.param.com2.dst_height, + params.param.com2.dst_width_vir, params.param.com2.dst_height_vir); + hwpq_logv("set api param: yuv_out_diff=%d, dst_c_size=%dx%d [%dx%d]\n", + params.param.com2.yuv_out_diff, params.param.com2.dst_c_width, + params.param.com2.dst_c_height, params.param.com2.dst_c_width_vir, + params.param.com2.dst_c_height_vir); + hwpq_logv("set api param: hist_only_mode=%d, cfg_set=%d\n", + params.param.com2.hist_mode_en, params.param.com2.cfg_set); + } else { + params.ptype = VDPP_PARAM_TYPE_COM; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.com.src_width = p_proc_param->src_img_info.img_yrgb.w_vld; + params.param.com.src_height = p_proc_param->src_img_info.img_yrgb.h_vld; + params.param.com.sswap = get_img_format_swap(p_proc_param->src_img_info.img_fmt); + params.param.com.dfmt = vdpp_format_convert(p_proc_param->dst_img_info.img_fmt); + params.param.com.dst_width = p_proc_param->dst_img_info.img_yrgb.w_vld; + params.param.com.dst_height = p_proc_param->dst_img_info.img_yrgb.h_vld; + params.param.com.dswap = get_img_format_swap(p_proc_param->dst_img_info.img_fmt); + ret = ctx->ops->control(ctx->priv, VDPP_CMD_SET_COM_CFG, ¶ms); + } + + hwpq_leave(); + return ret; +} + +int hwpq_vdpp_proc(HwpqVdppContext ctx, HwpqVdppParams *hwpq_param) +{ + VdppCtxImpl *ctx_impl = (VdppCtxImpl *)ctx; + VdppComCtx *ctx_com = NULL; + MppBuffer histbuf = NULL; + MppBufferGroup memGroup = NULL; + void *phist_internal = NULL; + void *phist_target = NULL; + RK_S32 fdhist_internal = 0; + RK_S32 fdhist_target = 0; + RK_S32 vdpp_ver = 1; + RK_U32 update_flag = 0; + RK_S32 ret = MPP_OK; + + static RK_S32 internal_frame_idx = 0; + + if (NULL == ctx || NULL == hwpq_param) { + hwpq_loge("found NULL input ctx %p proc_param %p\n", ctx, hwpq_param); + return MPP_ERR_NULL_PTR; + } + + ctx_com = ctx_impl->vdpp; + if (NULL == ctx_com || NULL == ctx_com->ops || NULL == ctx_com->ops->control) { + hwpq_loge("found NULL vdpp or vdpp ops\n"); + return MPP_ERR_NULL_PTR; + } + + // get env here so that we can change loglevel dynamically + mpp_env_get_u32(HWPQ_VDPP_DEBUG_CFG_PROP, &hwpq_vdpp_debug, 0); + hwpq_logt("get env '%s' flag: %#x", HWPQ_VDPP_DEBUG_CFG_PROP, hwpq_vdpp_debug); + + hwpq_enter(); + + vdpp_ver = MPP_MAX(ctx_com->ver >> 8, 1); + hwpq_logd("vdpp_ver flag: %#x -> %d", ctx_com->ver, vdpp_ver); + + memGroup = ctx_impl->memGroup; + histbuf = ctx_impl->histbuf; + if (NULL == memGroup || NULL == histbuf) { + hwpq_loge("found NULL memGroup %p or histbuf %p\n", memGroup, histbuf); + return MPP_ERR_NULL_PTR; + } + + dump_vdpp_params(hwpq_param); + + ret |= vdpp_set_img(ctx_com, hwpq_param->src_img_info.img_yrgb.fd, + hwpq_param->src_img_info.img_cbcr.fd, + hwpq_param->src_img_info.img_cbcr.offset, VDPP_CMD_SET_SRC); + ret |= vdpp_set_img(ctx_com, hwpq_param->dst_img_info.img_yrgb.fd, + hwpq_param->dst_img_info.img_cbcr.fd, + hwpq_param->dst_img_info.img_cbcr.offset, VDPP_CMD_SET_DST); + if (hwpq_param->yuv_diff_flag) + ret |= vdpp_set_img(ctx_com, hwpq_param->dst_img_info.img_yrgb.fd, + hwpq_param->dst_img_info.img_cbcr.fd, + hwpq_param->dst_img_info.img_cbcr.offset, VDPP_CMD_SET_DST_C); + + // call VDPP_CMD_SET_COM2_CFG + ret |= hwpq_vdpp_common_config(ctx_com, hwpq_param); + if (ret) { + hwpq_loge("vdpp common config failed! %d\n", ret); + return MPP_NOK; + } + + /* update params */ + update_flag = hwpq_param->vdpp_config_update_flag || (0 == hwpq_param->frame_idx) || + (0 == internal_frame_idx); + ret = vdpp_set_user_cfg(ctx_com, hwpq_param, update_flag); + if (ret) + hwpq_logw("warning: set user cfg failed for some module! %d\n", ret); + + /* set hist fd */ + if (vdpp_ver >= 2 && hwpq_param->vdpp_config.hist_cnt_en) { + phist_internal = mpp_buffer_get_ptr(histbuf); + fdhist_internal = mpp_buffer_get_fd(histbuf); + mpp_assert(phist_internal && fdhist_internal > 0); + + // use internal hist buffer if user not provide hist fd + if (hwpq_param->hist_buf_fd > 0) { + fdhist_target = hwpq_param->hist_buf_fd; + hwpq_logd("set api param: set hist fd to user config: fd=%d, addr=%p\n", + fdhist_target, hwpq_param->p_hist_buf); + } else { + fdhist_target = fdhist_internal; + hwpq_logd("set api param: set hist fd to internal(fd=%d) since the user not provide\n", + fdhist_target); + } + + ret = ctx_com->ops->control(ctx_com->priv, VDPP_CMD_SET_HIST_FD, &fdhist_target); + if (ret) { + hwpq_loge("set hist fd failed! %d\n", ret); + return MPP_NOK; + } + } + + /* run vdpp */ + ret = ctx_com->ops->control(ctx_com->priv, VDPP_CMD_RUN_SYNC, NULL); + if (ret) { + hwpq_loge("run vdpp failed!!! %d\n", ret); + return MPP_NOK; + } + + /* post process */ + memset(&ctx_impl->output, 0, sizeof(ctx_impl->output)); + ctx_impl->output.luma_avg = -1; // init to invalid value + ctx_impl->output.bbd_size_top = -1; + ctx_impl->output.bbd_size_bottom = -1; + ctx_impl->output.bbd_size_left = -1; + ctx_impl->output.bbd_size_right = -1; + + if ((vdpp_ver >= 2) && hwpq_param->vdpp_config.hist_cnt_en) { + /* Calc avg luma */ + RK_U32 *p_global_hist = NULL; + RK_U64 luma_sum = 0; + RK_U32 pixel_count = 0; + RK_U32 i; + + if (fdhist_target == fdhist_internal) { + phist_target = phist_internal; + hwpq_logd("count mean luma with internal hist: fd=%d, addr=%p\n", + fdhist_internal, phist_target); + } else { + if (hwpq_param->p_hist_buf) { + phist_target = hwpq_param->p_hist_buf; + hwpq_logd("count mean luma with user hist: fd=%d, addr=%p\n", + hwpq_param->hist_buf_fd, phist_target); + } else { + phist_target = vdpp_map_buffer_with_fd(hwpq_param->hist_buf_fd, VDPP_HIST_LENGTH); + hwpq_logd("count mean luma with user hist: fd=%d =map=> addr=%p\n", + hwpq_param->hist_buf_fd, phist_target); + } + } + if (phist_target) { + p_global_hist = (RK_U32 *)phist_target + HWPQ_VDPP_GLOBAL_HIST_OFFSET / 4; + for (i = 0; i < HWPQ_VDPP_GLOBAL_HIST_SIZE; i++) { + /* + bin0 ---> 0,1,2,3 ---> avg_luma = 1.5 = 0*4+1.5 + bin1 ---> 4,5,6,7 ---> avg_luma = 5.5 = 1*4+1.5 + ... + bin255 ---> 1020,1021,1022,1023 ---> avg_luma = 1021.5 = 255*4+1.5 + */ + RK_U32 luma_val = i * 8 + 3; + + luma_sum += p_global_hist[i] * luma_val; + pixel_count += p_global_hist[i]; + } + + if (pixel_count > 0) { + ctx_impl->output.luma_avg = luma_sum / pixel_count / 2; + hwpq_logd("get luma_avg from hist: %d (in U10)\n", ctx_impl->output.luma_avg); + } else { + hwpq_logw("pixel_count is zero! the hist data is invalid! output.luma_avg will be " + "set to -1!\n"); + ctx_impl->output.luma_avg = -1; + } + } else { + hwpq_logw("hist buffer is invalid!! output.luma_avg will be set to -1!\n"); + } + + /* update hwpq_vdpp_info_t */ + if (fdhist_target == fdhist_internal && hwpq_param->p_hist_buf) { + hwpq_logv("copy internal hist[%p] to user hist[%p]...\n", + phist_internal, hwpq_param->p_hist_buf); + memcpy(hwpq_param->p_hist_buf, phist_internal, VDPP_HIST_LENGTH); + } + + ctx_impl->output.dci_vdpp_info.p_hist_addr = phist_target; + ctx_impl->output.dci_vdpp_info.hist_length = VDPP_HIST_LENGTH; + ctx_impl->output.dci_vdpp_info.vdpp_img_w_in = hwpq_param->src_img_info.img_yrgb.w_vld; + ctx_impl->output.dci_vdpp_info.vdpp_img_h_in = hwpq_param->src_img_info.img_yrgb.h_vld; + ctx_impl->output.dci_vdpp_info.vdpp_img_w_out = hwpq_param->dst_img_info.img_yrgb.w_vld; + ctx_impl->output.dci_vdpp_info.vdpp_img_h_out = hwpq_param->dst_img_info.img_yrgb.h_vld; + ctx_impl->output.dci_vdpp_info.vdpp_blk_size_h = hwpq_param->src_img_info.img_yrgb.w_vld / 16; + ctx_impl->output.dci_vdpp_info.vdpp_blk_size_v = hwpq_param->src_img_info.img_yrgb.h_vld / 16; + } + + if ((vdpp_ver >= 3) && hwpq_param->vdpp_config.bbd_en) { + VdppResults results = {0}; + + ret = ctx_com->ops->control(ctx_com->priv, VDPP_CMD_GET_BBD, &results); + if (MPP_OK == ret) { + ctx_impl->output.bbd_size_top = results.bbd.bbd_size_top; + ctx_impl->output.bbd_size_bottom = results.bbd.bbd_size_bottom; + ctx_impl->output.bbd_size_left = results.bbd.bbd_size_left; + ctx_impl->output.bbd_size_right = results.bbd.bbd_size_right; + } else { + hwpq_loge("get bbd result error! %d\n", ret); + } + } + + vdpp_dump_bufs(hwpq_param, internal_frame_idx); + internal_frame_idx++; + + hwpq_leave(); + return MPP_OK; +} + +int hwpq_vdpp_check_work_mode(HwpqVdppContext ctx, const HwpqVdppParams *p_proc_param) +{ + RK_S32 cap_mode = VDPP_CAP_UNSUPPORTED; + VdppCtxImpl *ctx_impl = (VdppCtxImpl *)ctx; + VdppComCtx *ctx_com = NULL; + RK_S32 run_mode = VDPP_RUN_MODE_UNSUPPORTED; + MPP_RET ret = MPP_NOK; + + if (NULL == ctx || NULL == p_proc_param) { + hwpq_loge("found NULL vdpp %p proc_param %p!\n", ctx, p_proc_param); + return VDPP_RUN_MODE_UNSUPPORTED; + } + + ctx_com = ctx_impl->vdpp; + if (NULL == ctx_com || NULL == ctx_com->ops) { + hwpq_loge("found NULL vdpp or ops!\n"); + return VDPP_RUN_MODE_UNSUPPORTED; + } + + hwpq_enter(); + + ret = hwpq_vdpp_common_config(ctx_com, p_proc_param); + if (ret) { + hwpq_loge("vdpp common config failed! %d\n", ret); + return VDPP_RUN_MODE_UNSUPPORTED; + } + + if (ctx_com->ops->check_cap) + cap_mode = ctx_com->ops->check_cap(ctx_com->priv); + + hwpq_logd("vdpp cap_mode: %#x (1-VEP, 2-HIST)", cap_mode); + + /* vep first */ + if (VDPP_CAP_VEP & cap_mode) + run_mode = VDPP_RUN_MODE_VEP; + else if (VDPP_CAP_HIST & cap_mode) + run_mode = VDPP_RUN_MODE_HIST; + + hwpq_leave(); + return run_mode; +} + +int hwpq_vdpp_run_cmd(HwpqVdppContext ctx, HwpqVdppCmd cmd, void *data, int data_size, + void *user_data) +{ + VdppCtxImpl *ctx_impl = (VdppCtxImpl *)ctx; + VdppComCtx *ctx_com = NULL; + RK_S32 min_data_size = 0; + RK_S32 ret = MPP_OK; + (void)user_data; + + if (NULL == ctx || NULL == data) { + hwpq_loge("found NULL input ctx %p data %p\n", ctx, data); + return MPP_ERR_NULL_PTR; + } + + ctx_com = ctx_impl->vdpp; + if (NULL == ctx_com || NULL == ctx_com->ops || NULL == ctx_com->ops->control) { + hwpq_loge("found NULL vdpp or vdpp ops!\n"); + return MPP_ERR_NULL_PTR; + } + + hwpq_enter(); + + switch (cmd) { + case HWPQ_VDPP_CMD_GET_VERSION: + case HWPQ_VDPP_CMD_GET_SOC_NAME: + case HWPQ_VDPP_CMD_GET_PYR_MIN_SIZE: { + min_data_size = sizeof(HwpqVdppQueryInfo); + } break; + case HWPQ_VDPP_CMD_GET_HIST_RESULT: + case HWPQ_VDPP_CMD_GET_BBD_RESULT: { + min_data_size = sizeof(HwpqVdppOutput); + } break; + case HWPQ_VDPP_CMD_SET_DEF_CFG: { + min_data_size = sizeof(HwpqVdppConfig); + } break; + default: break; + } + + if (0 == min_data_size || data_size < min_data_size) { + hwpq_logw("data_size=%d is too small for cmd %d, Need %d bytes at least!\n", + data_size, cmd, min_data_size); + return MPP_ERR_VALUE; + } + + switch (cmd) { + case HWPQ_VDPP_CMD_GET_VERSION: { + HwpqVdppQueryInfo *query_info = (HwpqVdppQueryInfo *)data; + + query_info->version.vdpp_ver = ctx_com->ver; + } break; + case HWPQ_VDPP_CMD_GET_SOC_NAME: { + HwpqVdppQueryInfo *query_info = (HwpqVdppQueryInfo *)data; + + snprintf(query_info->platform.soc_name, HWPQ_VDPP_SOC_NAME_LENGTH - 1, "%s", + mpp_get_soc_name()); + } break; + case HWPQ_VDPP_CMD_GET_PYR_MIN_SIZE: { + HwpqVdppQueryInfo *query_info = (HwpqVdppQueryInfo *)data; + + if (query_info->pyr.dst_width < 128 || query_info->pyr.dst_height < 128) { + hwpq_logw("dst_width=%d or dst_height=%d is too small, Need >= 128.\n", + query_info->pyr.dst_width, query_info->pyr.dst_height); + } + query_info->pyr.nb_layers = 3; + query_info->pyr.vir_widths[0] = MPP_ALIGN(query_info->pyr.dst_width / 2, 16); + query_info->pyr.vir_widths[1] = MPP_ALIGN(query_info->pyr.dst_width / 4, 16); + query_info->pyr.vir_widths[2] = MPP_ALIGN(query_info->pyr.dst_width / 8, 16); + query_info->pyr.vir_heights[0] = (query_info->pyr.dst_height + 1) / 2; + query_info->pyr.vir_heights[1] = (query_info->pyr.dst_height + 3) / 4; + query_info->pyr.vir_heights[2] = (query_info->pyr.dst_height + 7) / 8; + } break; + case HWPQ_VDPP_CMD_GET_HIST_RESULT: { + HwpqVdppOutput *output = (HwpqVdppOutput *)data; + + output->hist.luma_avg = ctx_impl->output.luma_avg; + memcpy(&output->hist.dci_vdpp_info, &ctx_impl->output.dci_vdpp_info, + sizeof(HwpqVdppDciInfo)); + } break; + case HWPQ_VDPP_CMD_GET_BBD_RESULT: { + HwpqVdppOutput *output = (HwpqVdppOutput *)data; + + output->bbd.bbd_size_top = ctx_impl->output.bbd_size_top; + output->bbd.bbd_size_bottom = ctx_impl->output.bbd_size_bottom; + output->bbd.bbd_size_left = ctx_impl->output.bbd_size_left; + output->bbd.bbd_size_right = ctx_impl->output.bbd_size_right; + } break; + case HWPQ_VDPP_CMD_SET_DEF_CFG: { + HwpqVdppConfig *vdpp_config = (HwpqVdppConfig *)data; + + memset(vdpp_config, 0, sizeof(HwpqVdppConfig)); + vdpp_config->dmsr_en = 0; + vdpp_config->str_pri_y = 10; + vdpp_config->str_sec_y = 4; + vdpp_config->dumping_y = 6; + + vdpp_config->es_en = 0; + vdpp_config->es_iWgtGain = 128; + + vdpp_config->zme_dering_en = 1; + + vdpp_config->hist_cnt_en = 1; + vdpp_config->hist_csc_range = VDPP_LIMIT_RANGE; + + vdpp_config->shp_en = 0; + vdpp_config->peaking_gain = 196; + vdpp_config->shp_shoot_ctrl_en = 1; + vdpp_config->shp_shoot_ctrl_over = 8; + vdpp_config->shp_shoot_ctrl_under = 8; + + vdpp_config->pyr_en = 0; + for (int i = 0; i < 8; ++i) { + vdpp_config->pyr_layers[i].img_fmt = VDPP_FMT_Y_ONLY_8BIT; + } + + vdpp_config->bbd_en = 0; + vdpp_config->bbd_threshold = 20; + } break; + default: break; + } + + return ret; +} diff --git a/mpp/vproc/vdpp/test/CMakeLists.txt b/mpp/vproc/vdpp/test/CMakeLists.txt new file mode 100644 index 000000000..7196039af --- /dev/null +++ b/mpp/vproc/vdpp/test/CMakeLists.txt @@ -0,0 +1,18 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# mpp/vproc/vdpp built-in unit test case +# ---------------------------------------------------------------------------- +# vdpp unit test +option(VDPP_TEST "Build base vdpp unit test" ${BUILD_TEST}) +if (VDPP_TEST) + add_executable(vdpp_test vdpp_test.c) + target_link_libraries(vdpp_test ${MPP_SHARED} utils vproc_vdpp) + set_target_properties(vdpp_test PROPERTIES FOLDER "mpp/vproc/vdpp") + add_test(NAME vdpp_test COMMAND vdpp_test) + + # hwpq test (call libvdpp.so) + add_executable(hwpq_test hwpq_test.c) + target_link_libraries(hwpq_test vdpp ${ASAN_LIB}) + set_target_properties(hwpq_test PROPERTIES FOLDER "mpp/vproc/vdpp") + add_test(NAME hwpq_test COMMAND hwpq_test) +endif() diff --git a/mpp/vproc/vdpp/test/hwpq_test.c b/mpp/vproc/vdpp/test/hwpq_test.c new file mode 100644 index 000000000..43e803fb7 --- /dev/null +++ b/mpp/vproc/vdpp/test/hwpq_test.c @@ -0,0 +1,920 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "hwpq_vdpp" + +#include +#include +#include +#include +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_buffer.h" +#include "mpp_common.h" +#include "mpp_info.h" +#include "mpp_log.h" + +#include "hwpq_vdpp_proc_api.h" + +#define MAX_URL_LEN (256) +#define VDPP_WORK_MODE_VEP (2) +#define VDPP_WORK_MODE_DCI (3) /* hist only mode */ + +typedef struct { + char src_file_name[MAX_URL_LEN]; + char dst_file_name_y[MAX_URL_LEN]; + char dst_file_name_uv[MAX_URL_LEN]; + char dst_dir_name[MAX_URL_LEN]; + + RK_S32 img_fmt_i; // vdpp_frame_format + RK_S32 img_swap_i; // uv swap flag + RK_S32 img_range; // 0-limited, 1-full + RK_S32 img_w_i; + RK_S32 img_h_i; + RK_S32 img_w_i_vir; + RK_S32 img_h_i_vir; + + RK_S32 img_fmt_o; // vdpp_frame_format + RK_S32 img_swap_o; // uv swap flag + RK_S32 img_w_o; + RK_S32 img_h_o; + RK_S32 img_w_o_vir; + RK_S32 img_h_o_vir; + + RK_S32 uv_diff_flag; // set to 1 if need to separate the output luma & chroma data + RK_S32 img_w_o_c; // same to luma, no need to half for YUV420! + RK_S32 img_h_o_c; // same to luma, no need to half for YUV420! + RK_S32 img_w_o_c_vir; // same to luma, no need to half for YUV420! + RK_S32 img_h_o_c_vir; // same to luma, no need to half for YUV420! + + RK_S32 work_mode; // 2-vep, 3-dci_hist, otherwise-unsupported + RK_S32 nthreads; + RK_S32 frame_num; // default: 1. <0 means infinite loop + + /* high 16 bit: mask; low 3 bit (msb->lsb): dmsr|es|sharp */ + RK_S32 cfg_set; // used in com2, reset enable flag of dmsr/es/sharp + RK_S32 en_dmsr; + RK_S32 en_es; + RK_S32 en_shp; + RK_S32 en_hist; + RK_S32 en_pyr; + RK_S32 en_bbd; + RK_S32 bbd_th; // default: 20 in U8 range +} VdppCmdCfg; + +typedef struct { + RK_S32 chn; // thread id, [0, nthreads-1] + + FILE *fp_i; + FILE *fp_o_y; + FILE *fp_o_uv; + FILE *fp_o_hist; + FILE *fp_o_pyrs[3]; + FILE *fp_o_res; + + RK_U32 frm_eos; // frame end-of-stream flag + RK_U32 loop_times; +} VdppTestMultiCtx; + +typedef struct { + VdppCmdCfg *cmd; // point to the same cmd config + RK_S32 chn; // thread id, [0, nthreads-1] + + pthread_t thd; // thread for for each instance + VdppTestMultiCtx ctx; // context of vdpp +} VdppTestMultiCtxInfo; + +static RK_S32 parse_cmd(char **argv, RK_S32 argc, VdppCmdCfg *cfg); +static void print_help_info(); + +// static RK_S32 get_vdpp_format_uv_sample_shift(RK_S32 fmt, RK_S32 *p_ret_ratiox2); +static size_t get_frame_size(RK_S32 fmt, RK_U32 w, RK_U32 h); + +extern char *optarg; +extern int opterr; + +static void *multi_vdpp(void *cmd_ctx) +{ + VdppTestMultiCtxInfo *info = (VdppTestMultiCtxInfo *)cmd_ctx; + VdppTestMultiCtx *mul_ctx = &info->ctx; + VdppCmdCfg *cfg = info->cmd; + + HwpqVdppContext vdpp_ctx = NULL; // api ctx + HwpqVdppParams vdpp_params = {0}; + HwpqVdppQueryInfo vdpp_info = {0}; + HwpqVdppOutput vdpp_output = {0}; + RK_U32 vdpp_ver = 1; + RK_U32 yuv_out_diff = cfg->uv_diff_flag; + size_t srcfrmsize = 0; + size_t dstfrmsize = 0; + size_t dstfrmsize_c = 0; + RK_U32 pyr_vir_wids[3] = {0}; + RK_U32 pyr_vir_hgts[3] = {0}; + RK_U32 pyr_buf_sizes[3] = {0}; + RK_S32 pyr_fds[3] = { -1, -1, -1}; + void *pyr_addrs[3] = {0}; + + MppBufferGroup memGroup = NULL; + MppBuffer srcbuf = NULL; + MppBuffer dstbuf = NULL; + MppBuffer histbuf = NULL; + MppBuffer pyrbuf_l1 = NULL; + MppBuffer pyrbuf_l2 = NULL; + MppBuffer pyrbuf_l3 = NULL; + void *psrc = NULL; + void *pdst = NULL; + void *phist = NULL; + RK_S32 fdsrc = -1; + RK_S32 fddst = -1; + RK_S32 fdhist = -1; + RK_S32 frame_idx = 0; + RK_S32 i = 0; + RK_S32 ret = 0; + + /* init vdpp context */ + ret = hwpq_vdpp_init(&vdpp_ctx); + if (ret) { + mpp_loge("failed to init hwpq_vdpp context! %d", ret); + goto __RET; + } + + /* run cmds, query vdpp info */ + ret = hwpq_vdpp_run_cmd(vdpp_ctx, HWPQ_VDPP_CMD_GET_VERSION, &vdpp_info, + sizeof(vdpp_info), NULL); + vdpp_ver = vdpp_info.version.vdpp_ver >> 8; // {0x100, 0x200, 0x300} => {1, 2, 3} + + ret = hwpq_vdpp_run_cmd(vdpp_ctx, HWPQ_VDPP_CMD_GET_SOC_NAME, &vdpp_info, + sizeof(vdpp_info), NULL); + mpp_logi("get vdpp_info: vdpp_ver: %d, soc: %s\n", vdpp_ver, vdpp_info.platform.soc_name); + + memset(&vdpp_info, 0, sizeof(vdpp_info)); + vdpp_info.pyr.dst_width = cfg->img_w_o; + vdpp_info.pyr.dst_height = cfg->img_h_o; + ret = hwpq_vdpp_run_cmd(vdpp_ctx, HWPQ_VDPP_CMD_GET_PYR_MIN_SIZE, + &vdpp_info, sizeof(vdpp_info), NULL); + if (0 == ret) { + pyr_vir_wids[0] = vdpp_info.pyr.vir_widths[0]; + pyr_vir_wids[1] = vdpp_info.pyr.vir_widths[1]; + pyr_vir_wids[2] = vdpp_info.pyr.vir_widths[2]; + pyr_vir_hgts[0] = vdpp_info.pyr.vir_heights[0]; + pyr_vir_hgts[1] = vdpp_info.pyr.vir_heights[1]; + pyr_vir_hgts[2] = vdpp_info.pyr.vir_heights[2]; + } else { + mpp_logw("failed to run cmd: HWPQ_VDPP_CMD_GET_PYR_MIN_SIZE %d", ret); + pyr_vir_wids[0] = MPP_ALIGN(cfg->img_w_o / 2, 16); + pyr_vir_wids[1] = MPP_ALIGN(cfg->img_w_o / 4, 16); + pyr_vir_wids[2] = MPP_ALIGN(cfg->img_w_o / 8, 16); + pyr_vir_hgts[0] = (cfg->img_h_o + 1) / 2; + pyr_vir_hgts[1] = (cfg->img_h_o + 3) / 4; + pyr_vir_hgts[2] = (cfg->img_h_o + 7) / 8; + } + pyr_buf_sizes[0] = pyr_vir_wids[0] * pyr_vir_hgts[0]; + pyr_buf_sizes[1] = pyr_vir_wids[1] * pyr_vir_hgts[1]; + pyr_buf_sizes[2] = pyr_vir_wids[2] * pyr_vir_hgts[2]; + + ret = hwpq_vdpp_run_cmd(vdpp_ctx, HWPQ_VDPP_CMD_SET_DEF_CFG, &vdpp_params.vdpp_config, + sizeof(HwpqVdppConfig), NULL); + if (ret) { + mpp_logw("failed to run cmd: HWPQ_VDPP_CMD_SET_DEF_CFG %d", ret); + } + + /* update config with known info */ + yuv_out_diff = yuv_out_diff && (vdpp_ver >= 2); + cfg->en_dmsr &= (vdpp_ver >= 1) && (cfg->work_mode != VDPP_WORK_MODE_DCI); + cfg->en_es &= (vdpp_ver >= 2) && (cfg->work_mode != VDPP_WORK_MODE_DCI); + cfg->en_shp &= (vdpp_ver >= 2) && (cfg->work_mode != VDPP_WORK_MODE_DCI); + cfg->en_hist &= (vdpp_ver >= 2); + cfg->en_pyr &= (vdpp_ver >= 3) && (cfg->work_mode != VDPP_WORK_MODE_DCI); + cfg->en_bbd &= (vdpp_ver >= 3); + mpp_logi("update enbale flags: dmsr=%d, es=%d, shp=%d, hist=%d, pyr=%d, bbd=%d\n", + cfg->en_dmsr, cfg->en_es, cfg->en_shp, cfg->en_hist, cfg->en_pyr, cfg->en_bbd); + mpp_logi("is_yuv_out_diff: %d, work_mode: %d\n", yuv_out_diff, cfg->work_mode); + + srcfrmsize = get_frame_size(cfg->img_fmt_i, cfg->img_w_i_vir, cfg->img_h_i_vir); + dstfrmsize = get_frame_size(cfg->img_fmt_o, cfg->img_w_o_vir, cfg->img_h_o_vir); + dstfrmsize_c = get_frame_size(VDPP_FMT_UV_ONLY_8BIT, cfg->img_w_o_c_vir, cfg->img_h_o_c_vir); + + /* malloc buffers */ + ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_DRM); + if (MPP_OK != ret) { + mpp_loge("memGroup mpp_buffer_group_get failed!\n"); + return NULL; + } + + mpp_buffer_get(memGroup, &srcbuf, srcfrmsize); + mpp_buffer_get(memGroup, &dstbuf, dstfrmsize); + mpp_buffer_get(memGroup, &histbuf, VDPP_HIST_LENGTH); + mpp_buffer_get(memGroup, &pyrbuf_l1, pyr_buf_sizes[0]); + mpp_buffer_get(memGroup, &pyrbuf_l2, pyr_buf_sizes[1]); + mpp_buffer_get(memGroup, &pyrbuf_l3, pyr_buf_sizes[2]); + + psrc = mpp_buffer_get_ptr(srcbuf); + pdst = mpp_buffer_get_ptr(dstbuf); + phist = mpp_buffer_get_ptr(histbuf); + pyr_addrs[0] = mpp_buffer_get_ptr(pyrbuf_l1); + pyr_addrs[1] = mpp_buffer_get_ptr(pyrbuf_l2); + pyr_addrs[2] = mpp_buffer_get_ptr(pyrbuf_l3); + + fdsrc = mpp_buffer_get_fd(srcbuf); + fddst = mpp_buffer_get_fd(dstbuf); + fdhist = mpp_buffer_get_fd(histbuf); + pyr_fds[0] = mpp_buffer_get_fd(pyrbuf_l1); + pyr_fds[1] = mpp_buffer_get_fd(pyrbuf_l2); + pyr_fds[2] = mpp_buffer_get_fd(pyrbuf_l3); + + mpp_logi("src w:h [%d:%d] stride [%d:%d] require buf %d bytes. fd %d", cfg->img_w_i, + cfg->img_h_i, cfg->img_w_i_vir, cfg->img_h_i_vir, srcfrmsize, fdsrc); + mpp_logi("dst w:h [%d:%d] stride [%d:%d] require buf %d bytes. fd %d", cfg->img_w_o, + cfg->img_h_o, cfg->img_w_o_vir, cfg->img_h_o_vir, dstfrmsize, fddst); + if (yuv_out_diff) { + mpp_logi("dst_c w:h [%d:%d] stride [%d:%d] require buf %d bytes. fd %d", cfg->img_w_o_c, + cfg->img_h_o_c, cfg->img_w_o_c_vir, cfg->img_h_o_c_vir, dstfrmsize_c, fddst); + } + for (i = 0; i < 3; i++) { + mpp_logi("pyr[%d] info: size=%ux%u, require buf %u bytes. fd %d\n", + i + 1, pyr_vir_wids[i], pyr_vir_hgts[i], pyr_buf_sizes[i], pyr_fds[i]); + } + + /* open files */ + mul_ctx->chn = info->chn; + mul_ctx->fp_i = fopen(cfg->src_file_name, "rb"); + if (!mul_ctx->fp_i) { + mpp_loge("failed to open input file %s! %s", cfg->src_file_name, strerror(errno)); + goto __RET; + } + + if (cfg->dst_file_name_y[0]) { + mul_ctx->fp_o_y = fopen(cfg->dst_file_name_y, "wb"); + if (mul_ctx->fp_o_y == NULL) { + mpp_logw("failed to open output file %s! %s\n", cfg->dst_file_name_y, strerror(errno)); + } + } + + if (cfg->dst_file_name_uv[0]) { + mul_ctx->fp_o_uv = fopen(cfg->dst_file_name_uv, "wb"); + if (mul_ctx->fp_o_uv == NULL) { + mpp_logw("failed to open output chroma file %s! %s\n", + cfg->dst_file_name_uv, strerror(errno)); + } + } + + if (cfg->dst_dir_name[0]) { + char filename[MAX_URL_LEN] = {0}; + + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_com.txt", cfg->dst_dir_name); + mul_ctx->fp_o_res = fopen(filename, "wt"); + if (mul_ctx->fp_o_res == NULL) { + mpp_logw("failed to open output com file %s! %s\n", filename, strerror(errno)); + } + + if (cfg->en_hist) { + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_hist_packed.bin", cfg->dst_dir_name); + mul_ctx->fp_o_hist = fopen(filename, "wb"); + } + if (cfg->en_pyr) { + for (i = 0; i < 3; i++) { + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_pyr_l%d.yuv", + cfg->dst_dir_name, i + 1); + mul_ctx->fp_o_pyrs[i] = fopen(filename, "wb"); + } + } + } + + /* set parameters: switch module flag */ + { + vdpp_params.vdpp_config.dmsr_en = cfg->en_dmsr; + vdpp_params.vdpp_config.es_en = cfg->en_es; + vdpp_params.vdpp_config.shp_en = cfg->en_shp; + vdpp_params.vdpp_config.hist_cnt_en = cfg->en_hist; + vdpp_params.vdpp_config.hist_csc_range = cfg->img_range; + vdpp_params.vdpp_config.pyr_en = cfg->en_pyr; + vdpp_params.vdpp_config.bbd_en = cfg->en_bbd; + mpp_logi("modules to run: dmsr=%d, es=%d, shp=%d, hist=%d, pyr=%d, bbd=%d\n", + cfg->en_dmsr, cfg->en_es, cfg->en_shp, cfg->en_hist, cfg->en_pyr, cfg->en_bbd); + } + + /* set parameters: set buffer info */ + { + vdpp_params.src_img_info.img_fmt = cfg->img_fmt_i; + vdpp_params.src_img_info.img_yrgb.fd = fdsrc; + vdpp_params.src_img_info.img_yrgb.addr = psrc; + vdpp_params.src_img_info.img_yrgb.offset = 0; + vdpp_params.src_img_info.img_yrgb.w_vld = cfg->img_w_i; + vdpp_params.src_img_info.img_yrgb.h_vld = cfg->img_h_i; + vdpp_params.src_img_info.img_yrgb.w_vir = cfg->img_w_i_vir; + vdpp_params.src_img_info.img_yrgb.h_vir = cfg->img_h_i_vir; + + vdpp_params.src_img_info.img_cbcr.fd = fdsrc; + vdpp_params.src_img_info.img_cbcr.addr = psrc; + vdpp_params.src_img_info.img_cbcr.offset = cfg->img_w_i_vir * cfg->img_h_i_vir; + /* no need to set chroma size for input buffer, info not used */ + // vdpp_params.src_img_info.img_cbcr.w_vld = cfg->img_w_i / 2; // NV12 + // vdpp_params.src_img_info.img_cbcr.h_vld = cfg->img_h_i / 2; + // vdpp_params.src_img_info.img_cbcr.w_vir = cfg->img_w_i_vir / 2; + // vdpp_params.src_img_info.img_cbcr.h_vir = cfg->img_h_i_vir / 2; + + vdpp_params.dst_img_info.img_fmt = cfg->img_fmt_o; + vdpp_params.dst_img_info.img_yrgb.fd = fddst; + vdpp_params.dst_img_info.img_yrgb.addr = pdst; + vdpp_params.dst_img_info.img_yrgb.offset = 0; + vdpp_params.dst_img_info.img_yrgb.w_vld = cfg->img_w_o; + vdpp_params.dst_img_info.img_yrgb.h_vld = cfg->img_h_o; + vdpp_params.dst_img_info.img_yrgb.w_vir = cfg->img_w_o_vir; + vdpp_params.dst_img_info.img_yrgb.h_vir = cfg->img_h_o_vir; + + vdpp_params.dst_img_info.img_cbcr.fd = fddst; + vdpp_params.dst_img_info.img_cbcr.addr = pdst; + vdpp_params.dst_img_info.img_cbcr.offset = cfg->img_w_o_vir * cfg->img_h_o_vir; + vdpp_params.dst_img_info.img_cbcr.w_vld = cfg->img_w_o_c; + vdpp_params.dst_img_info.img_cbcr.h_vld = cfg->img_h_o_c; + vdpp_params.dst_img_info.img_cbcr.w_vir = cfg->img_w_o_c_vir; + vdpp_params.dst_img_info.img_cbcr.h_vir = cfg->img_h_o_c_vir; + + vdpp_params.hist_buf_fd = fdhist; + vdpp_params.p_hist_buf = phist; + + for (i = 0; i < 3; ++i) { + vdpp_params.vdpp_config.pyr_layers[i].img_yrgb.fd = pyr_fds[i]; + vdpp_params.vdpp_config.pyr_layers[i].img_yrgb.addr = pyr_addrs[i]; + vdpp_params.vdpp_config.pyr_layers[i].img_yrgb.w_vir = pyr_vir_wids[i]; + vdpp_params.vdpp_config.pyr_layers[i].img_yrgb.h_vir = pyr_vir_hgts[i]; + } + } + + /* set parameters: remaining config */ + { + // check if HIST_ONLY_MODE (DCI_HIST path) + RK_S32 work_mode_ref = hwpq_vdpp_check_work_mode(vdpp_ctx, &vdpp_params); + + vdpp_params.hist_mode_en = (VDPP_WORK_MODE_DCI == cfg->work_mode) || + (VDPP_RUN_MODE_HIST == work_mode_ref); + mpp_logi("check_work_mode: work_mode_ref=%d (0-vep, 1-dci), hist_only_mode=%d, en_hist=%d\n", + work_mode_ref, vdpp_params.hist_mode_en, cfg->en_hist); + + if ((VDPP_RUN_MODE_HIST == work_mode_ref) && (VDPP_WORK_MODE_DCI != cfg->work_mode)) { + mpp_loge("invalid work_mode(%d) and cap(%d)!\n", cfg->work_mode, work_mode_ref); + goto __RET; + } + + vdpp_params.yuv_diff_flag = yuv_out_diff; + vdpp_params.vdpp_config_update_flag = 1; + } + + /* run vdpp */ + while (1) { + /* read input frame data */ + vdpp_params.frame_idx = frame_idx++; + vdpp_params.vdpp_config_update_flag = (0 == vdpp_params.frame_idx); + + if ((srcfrmsize > fread(psrc, 1, srcfrmsize, mul_ctx->fp_i)) || feof(mul_ctx->fp_i)) { + mul_ctx->frm_eos = 1; + + if (cfg->frame_num < 0 || frame_idx < cfg->frame_num) { + clearerr(mul_ctx->fp_i); + rewind(mul_ctx->fp_i); + mul_ctx->frm_eos = 0; + mpp_logi("chn %d loop times %d\n", mul_ctx->chn, ++mul_ctx->loop_times); + continue; + } + mpp_logi("chn %d found last frame. feof %d\n", mul_ctx->chn, feof(mul_ctx->fp_i)); + } else if (ret == MPP_ERR_VALUE) + break; + + /* run vdpp */ + ret = hwpq_vdpp_proc(vdpp_ctx, &vdpp_params); + if (ret) + break; + + /* wirte output data */ + if (mul_ctx->fp_o_y) { + if (yuv_out_diff && vdpp_params.dst_img_info.img_cbcr.addr) { + fwrite(vdpp_params.dst_img_info.img_yrgb.addr, 1, + cfg->img_w_o_vir * cfg->img_h_o_vir, mul_ctx->fp_o_y); + fwrite(vdpp_params.dst_img_info.img_cbcr.addr + vdpp_params.dst_img_info.img_cbcr.offset, + 1, dstfrmsize_c, mul_ctx->fp_o_y); // write chroma data after dst luma + } else { + fwrite(vdpp_params.dst_img_info.img_yrgb.addr, 1, dstfrmsize, mul_ctx->fp_o_y); + } + mpp_logi("dst data dump to: %s\n", cfg->dst_file_name_y); + } + + if (yuv_out_diff && mul_ctx->fp_o_uv && vdpp_params.dst_img_info.img_cbcr.addr) { + fwrite(vdpp_params.dst_img_info.img_cbcr.addr + vdpp_params.dst_img_info.img_cbcr.offset, + 1, dstfrmsize_c, mul_ctx->fp_o_uv); + mpp_logi("dst chroma data dump to: %s\n", cfg->dst_file_name_uv); + } + + /* get & write hist result */ + if (cfg->en_hist && mul_ctx->fp_o_hist) { + ret = hwpq_vdpp_run_cmd(vdpp_ctx, HWPQ_VDPP_CMD_GET_HIST_RESULT, &vdpp_output, + sizeof(vdpp_output), NULL); + if (ret) { + mpp_logw("failed to run cmd: HWPQ_VDPP_CMD_GET_HIST_RESULT %d", ret); + } + + fwrite(vdpp_output.hist.dci_vdpp_info.p_hist_addr, 1, VDPP_HIST_LENGTH, + mul_ctx->fp_o_hist); + mpp_logi("get mean luma result: %d (in U10)\n", vdpp_output.hist.luma_avg); + if (mul_ctx->fp_o_res) { + fprintf(mul_ctx->fp_o_res, "mean luma result: %d\n", vdpp_output.hist.luma_avg); + fflush(mul_ctx->fp_o_res); + } + + // write dci info after hist + fwrite(&vdpp_output.hist.dci_vdpp_info, 1, sizeof(HwpqVdppDciInfo), mul_ctx->fp_o_hist); + + // or copy to dci_vdpp_info_t of hwpq + // memcpy(&pConfigHwpq->rk_hwpq_dci_cfg.dci_vdpp_info, &vdpp_output.hist.dci_vdpp_info, + // sizeof(HwpqVdppDciInfo)); + } + + /* write pyr result */ + if (cfg->en_pyr && !vdpp_params.hist_mode_en) { + for (i = 0; i < 3; ++i) { + if (mul_ctx->fp_o_pyrs[i]) { + fwrite(vdpp_params.vdpp_config.pyr_layers[i].img_yrgb.addr, + 1, pyr_buf_sizes[i], mul_ctx->fp_o_pyrs[i]); + } + } + } + + /* get bbd result */ + if (cfg->en_bbd) { + ret = hwpq_vdpp_run_cmd(vdpp_ctx, HWPQ_VDPP_CMD_GET_BBD_RESULT, &vdpp_output, + sizeof(vdpp_output), NULL); + if (ret) { + mpp_logw("failed to run cmd: HWPQ_VDPP_CMD_GET_BBD_RESULT %d", ret); + } + + mpp_logi("get bbd result: top/bottom/left/right = [%d, %d, %d, %d]\n", + vdpp_output.bbd.bbd_size_top, vdpp_output.bbd.bbd_size_bottom, + vdpp_output.bbd.bbd_size_left, vdpp_output.bbd.bbd_size_right); + if (mul_ctx->fp_o_res) { + fprintf(mul_ctx->fp_o_res, "bbd result: [top=%d, btm=%d, left=%d, right=%d]\n", + vdpp_output.bbd.bbd_size_top, vdpp_output.bbd.bbd_size_bottom, + vdpp_output.bbd.bbd_size_left, vdpp_output.bbd.bbd_size_right); + fflush(mul_ctx->fp_o_res); + } + } + + if (cfg->frame_num > 0 && frame_idx >= cfg->frame_num) { + mul_ctx->frm_eos = 1; + break; + } + + if (mul_ctx->frm_eos) + break; + } + +__RET: + if (mul_ctx->fp_i) { + fclose(mul_ctx->fp_i); + mul_ctx->fp_i = NULL; + } + if (mul_ctx->fp_o_y) { + fclose(mul_ctx->fp_o_y); + mul_ctx->fp_o_y = NULL; + } + if (mul_ctx->fp_o_uv) { + fclose(mul_ctx->fp_o_uv); + mul_ctx->fp_o_uv = NULL; + } + if (mul_ctx->fp_o_hist) { + fclose(mul_ctx->fp_o_hist); + mul_ctx->fp_o_hist = NULL; + } + for (i = 0; i < 3; ++i) { + if (mul_ctx->fp_o_pyrs[i]) { + fclose(mul_ctx->fp_o_pyrs[i]); + mul_ctx->fp_o_pyrs[i] = NULL; + } + } + + mpp_buffer_put(srcbuf); + mpp_buffer_put(dstbuf); + mpp_buffer_put(histbuf); + mpp_buffer_put(pyrbuf_l1); + mpp_buffer_put(pyrbuf_l2); + mpp_buffer_put(pyrbuf_l3); + + if (memGroup) { + mpp_buffer_group_put(memGroup); + memGroup = NULL; + } + + hwpq_vdpp_deinit(vdpp_ctx); + + return NULL; +} + +RK_S32 main(RK_S32 argc, char **argv) +{ + VdppCmdCfg vdpp_cmd_cfg; + VdppCmdCfg *cfg = &vdpp_cmd_cfg; + VdppTestMultiCtxInfo *ctxs = NULL; + RK_S32 i = 0; + RK_S32 ret = 0; + + mpp_logi("\n"); + mpp_logi("=========== hwpq test start ==============\n"); + ret = parse_cmd(argv, argc, cfg); + if (ret) { + return ret; + } + + ctxs = mpp_calloc(VdppTestMultiCtxInfo, cfg->nthreads); + if (NULL == ctxs) { + mpp_loge("failed to alloc context for instances!\n"); + ret = MPP_ERR_MALLOC; + goto __RET; + } + + for (i = 0; i < cfg->nthreads; i++) { + ctxs[i].cmd = cfg; + ctxs[i].chn = i; + + ret = pthread_create(&ctxs[i].thd, NULL, multi_vdpp, &ctxs[i]); + if (ret) { + mpp_loge("failed to create thread %d\n", i); + ret = MPP_NOK; + goto __RET; + } + } + + for (i = 0; i < cfg->nthreads; i++) + pthread_join(ctxs[i].thd, NULL); + +__RET: + MPP_FREE(ctxs); + ctxs = NULL; + + mpp_logi("=========== hwpq test end ==============\n\n"); + return ret; +} + +static RK_S32 parse_cmd(char **argv, RK_S32 argc, VdppCmdCfg *cfg) +{ + RK_S32 ch; + RK_S32 option_index = 0; + static struct option long_options[] = { + {"sw_vir", required_argument, 0, 0 }, // 0 + {"sh_vir", required_argument, 0, 0 }, + {"dw_vir", required_argument, 0, 0 }, + {"dh_vir", required_argument, 0, 0 }, + {"dwc", required_argument, 0, 0 }, // 4 + {"dhc", required_argument, 0, 0 }, + {"dwc_vir", required_argument, 0, 0 }, + {"dhc_vir", required_argument, 0, 0 }, + {"cfg_set", required_argument, 0, 0 }, // 8 + {"en_dmsr", required_argument, 0, 0 }, // 9 + {"en_es", required_argument, 0, 0 }, // 10 + {"en_shp", required_argument, 0, 0 }, // 11 + {"en_hist", required_argument, 0, 0 }, // 12 + {"en_pyr", required_argument, 0, 0 }, // 13 + {"en_bbd", required_argument, 0, 0 }, // 14 + {"bbd_th", required_argument, 0, 0 }, // 15 + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, + {"input", required_argument, 0, 'i'}, + {"output", required_argument, 0, 'o'}, + {"outc", required_argument, 0, 'O'}, + {"outdir", required_argument, 0, 'd'}, + {"swid", required_argument, 0, 'w'}, + {"shgt", required_argument, 0, 'g'}, + {"sfmt", required_argument, 0, 'f'}, + {"srange", required_argument, 0, 'r'}, + {"sswap", no_argument, 0, 's'}, + {"dwid", required_argument, 0, 'W'}, + {"dhgt", required_argument, 0, 'G'}, + {"dfmt", required_argument, 0, 'F'}, + {"dswap", no_argument, 0, 'S'}, + {"mode", required_argument, 0, 'm'}, + {"nframe", required_argument, 0, 'n'}, + {"nthread", required_argument, 0, 't'}, + {0, 0, 0, 0 }, + }; + + /* set default value */ + memset(cfg, 0, sizeof(VdppCmdCfg)); + cfg->img_w_i = 1920; + cfg->img_h_i = 1080; + cfg->img_fmt_o = -1; // init to -1 for later checking + cfg->work_mode = VDPP_WORK_MODE_VEP; + cfg->nthreads = 1; + cfg->frame_num = 1; + cfg->en_dmsr = 0; + cfg->en_es = 0; + cfg->en_shp = 0; + cfg->en_hist = 1; + cfg->en_pyr = 1; + cfg->en_bbd = 1; + cfg->bbd_th = 20; + + /* parse arguments */ + opterr = 0; + while ((ch = getopt_long_only(argc, argv, "i:o:O:d:w:g:f:r:W:G:F:m:n:t:hvsS", long_options, + &option_index)) != -1) { + switch (ch) { + case 0: { + mpp_logi(" - set %dth option: %s = %s", option_index, + long_options[option_index].name, optarg); + switch (option_index) { + case 0: { + cfg->img_w_i_vir = strtol(optarg, NULL, 0); + } break; + case 1: { + cfg->img_h_i_vir = strtol(optarg, NULL, 0); + } break; + case 2: { + cfg->img_w_o_vir = strtol(optarg, NULL, 0); + } break; + case 3: { + cfg->img_h_o_vir = strtol(optarg, NULL, 0); + } break; + case 4: { + cfg->img_w_o_c = strtol(optarg, NULL, 0); + } break; + case 5: { + cfg->img_h_o_c = strtol(optarg, NULL, 0); + } break; + case 6: { + cfg->img_w_o_c_vir = strtol(optarg, NULL, 0); + } break; + case 7: { + cfg->img_h_o_c_vir = strtol(optarg, NULL, 0); + } break; + case 8: { + cfg->cfg_set = strtol(optarg, NULL, 0); + } break; + case 9: { + cfg->en_dmsr = strtol(optarg, NULL, 0); + } break; + case 10: { + cfg->en_es = strtol(optarg, NULL, 0); + } break; + case 11: { + cfg->en_shp = strtol(optarg, NULL, 0); + } break; + case 12: { + cfg->en_hist = strtol(optarg, NULL, 0); + } break; + case 13: { + cfg->en_pyr = strtol(optarg, NULL, 0); + } break; + case 14: { + cfg->en_bbd = strtol(optarg, NULL, 0); + } break; + case 15: { + cfg->bbd_th = strtol(optarg, NULL, 0); + } break; + default: break; + } + } break; + case 'h': { + print_help_info(); + } return 1; + case 'v': { + mpp_logi("hwpq_vdpp_proc sdk version: %s\n", HWPQ_VDPP_PROC_VERSION_STR); + show_mpp_version(); + } return 2; + case 'i': { + strncpy(cfg->src_file_name, optarg, sizeof(cfg->src_file_name) - 1); + mpp_logi(" - set input filename: %s\n", cfg->src_file_name); + } break; + case 'o': { + strncpy(cfg->dst_file_name_y, optarg, sizeof(cfg->dst_file_name_y) - 1); + mpp_logi(" - set output [luma] filename: %s\n", cfg->dst_file_name_y); + } break; + case 'O': { + strncpy(cfg->dst_file_name_uv, optarg, sizeof(cfg->dst_file_name_uv) - 1); + cfg->uv_diff_flag = 1; + mpp_logi(" - set yuv_out_diff=1 since output chroma filename set: %s\n", + cfg->dst_file_name_uv); + } break; + case 'd': { + strncpy(cfg->dst_dir_name, optarg, sizeof(cfg->dst_dir_name) - 1); + mpp_logi(" - set output directory: %s\n", optarg); + } break; + case 'w': { + cfg->img_w_i = strtol(optarg, NULL, 0); + } break; + case 'g': { + cfg->img_h_i = strtol(optarg, NULL, 0); + } break; + case 'f': { + cfg->img_fmt_i = strtol(optarg, NULL, 0); + } break; + case 'r': { + cfg->img_range = strtol(optarg, NULL, 0); + mpp_logi(" - set input range: %d (0-Limit, 1-Full)\n", cfg->img_range); + } break; + case 's': { + cfg->img_swap_i = 1; + } break; + case 'W': { + cfg->img_w_o = strtol(optarg, NULL, 0); + } break; + case 'G': { + cfg->img_h_o = strtol(optarg, NULL, 0); + } break; + case 'F': { + cfg->img_fmt_o = strtol(optarg, NULL, 0); + } break; + case 'S': { + cfg->img_swap_o = 1; + } break; + case 'm': { + cfg->work_mode = MPP_MAX(VDPP_WORK_MODE_VEP, atoi(optarg)); + mpp_logi(" - set work mode: %d (2-vep, 3-dci_hist)\n", cfg->work_mode); + } break; + case 'n': { + cfg->frame_num = strtol(optarg, NULL, 0); + } break; + case 't': { + cfg->nthreads = strtol(optarg, NULL, 0); + if (cfg->nthreads < 1) + cfg->nthreads = 1; + } break; + default: break; + } + } + + /* check & adjust arguments */ + if (!cfg->src_file_name[0]) { + mpp_loge("input filename not specified!\n"); + return -1; + } + if (cfg->img_fmt_o < 0) + cfg->img_fmt_o = cfg->img_fmt_i; + if (cfg->work_mode != VDPP_WORK_MODE_DCI) { + if (cfg->img_fmt_o != VDPP_FMT_NV12 && cfg->img_fmt_o != VDPP_FMT_NV21 && + cfg->img_fmt_o != VDPP_FMT_NV24 && cfg->img_fmt_o != VDPP_FMT_NV42) { + mpp_loge("output format %d not supported!\n", cfg->img_fmt_o); + return -1; + } + } + mpp_logi(" - set input image size: %dx%d, hwpq_vdpp_format: %d\n", + cfg->img_w_i, cfg->img_h_i, cfg->img_fmt_i); + + if (!cfg->img_w_i_vir) + cfg->img_w_i_vir = cfg->img_w_i; + if (!cfg->img_h_i_vir) + cfg->img_h_i_vir = cfg->img_h_i; + if (!cfg->img_w_o) + cfg->img_w_o = cfg->img_w_i; + if (!cfg->img_h_o) + cfg->img_h_o = cfg->img_h_i; + if (!cfg->img_w_o_vir) + cfg->img_w_o_vir = cfg->img_w_o; + if (!cfg->img_h_o_vir) + cfg->img_h_o_vir = cfg->img_h_o; + if (cfg->uv_diff_flag) { + RK_S32 shift_bit = (cfg->img_fmt_o == VDPP_FMT_NV12) || (cfg->img_fmt_o == VDPP_FMT_NV21); + + if (!cfg->img_w_o_c) + cfg->img_w_o_c = cfg->img_w_o >> shift_bit; + if (!cfg->img_h_o_c) + cfg->img_h_o_c = cfg->img_h_i >> shift_bit; + if (!cfg->img_w_o_c_vir) + cfg->img_w_o_c_vir = cfg->img_w_o_c; + if (!cfg->img_h_o_c_vir) + cfg->img_h_o_c_vir = cfg->img_h_o_c; + mpp_logi(" - set output chroma image size: %dx%d, virtual size: %dx%d\n", + cfg->img_w_o_c, cfg->img_h_o_c, cfg->img_w_o_c_vir, cfg->img_h_o_c_vir); + } + mpp_logi(" - set output image size: %dx%d, virtual size: %dx%d, hwpq_vdpp_format: %d\n", + cfg->img_w_o, cfg->img_h_o, cfg->img_w_o_vir, cfg->img_h_o_vir, cfg->img_fmt_o); + mpp_logi(" - set enbale flags: dmsr=%d, es=%d, shp=%d, hist=%d, pyr=%d, bbd=%d\n", + cfg->en_dmsr, cfg->en_es, cfg->en_shp, cfg->en_hist, cfg->en_pyr, cfg->en_bbd); + + return 0; +} + +static void print_help_info() +{ + mpp_logi("Usage: hwpq_test [options]\n"); + mpp_logi("Options:\n"); + mpp_logi(" -h, --help : show this message\n"); + mpp_logi(" -v, --version : show version info\n"); + mpp_logi(" -i, --input : input filename\n"); + mpp_logi(" -o, --output [file]: output filename [of luma data] \n"); + mpp_logi(" -O, --outc [file]: output filename of chroma data \n"); + mpp_logi(" -d --outdir [dir]: output directory for other results(hist/pyr/slt/bbd...)\n"); + mpp_logi(" -w, --swid [int]: input valid width, unit: pixel, default: 1920\n"); + mpp_logi(" -g, --shgt [int]: input valid height, unit: pixel, default: 1080\n"); + mpp_logi(" --sw_vir [int]: input aligned width, unit: pixel\n"); + mpp_logi(" --sh_vir [int]: input aligned height, unit: pixel\n"); + mpp_logi(" -f, --sfmt [int]: input image format in HwpqVdppFormat\n"); + mpp_logi(" -s, --sswap : input image chroma_uv is swapped\n"); + mpp_logi(" -W, --dwid [int]: output valid width, unit: pixel, default: same to src\n"); + mpp_logi(" -G, --dhgt [int]: output valid height, unit: pixel, default: same to src\n"); + mpp_logi(" --dw_vir [int]: output aligned width, unit: pixel\n"); + mpp_logi(" --dh_vir [int]: output aligned height, unit: pixel\n"); + mpp_logi(" --dwc [int]: output chroma valid width, unit: pixel\n"); + mpp_logi(" --dhc [int]: output chroma valid height, unit: pixel\n"); + mpp_logi(" --dwc_vir [int]: output chroma aligned width, unit: pixel\n"); + mpp_logi(" --dhc_vir [int]: output chroma aligned height, unit: pixel\n"); + mpp_logi(" -F, --dfmt [int]: output image format in HwpqVdppFormat\n"); + mpp_logi(" -S, --dswap : output image chroma_uv is swapped\n"); + mpp_logi(" -m, --mode [int]: vdpp work mode: {2-vep, 3-dci_hist}, default: 2\n"); + mpp_logi(" -n, --nframe [int]: frame number, default: 1\n"); + mpp_logi(" -t, --nthread [int]: thread number, default: 1\n"); + mpp_logi(" --cfg_set [int]: high 16 bit: mask; low 3 bit (msb->lsb): dmsr|es|sharp. default: 0x0\n"); + mpp_logi(" --en_dmsr [int]: en_dmsr flag, default: 0\n"); + mpp_logi(" --en_es [int]: en_es flag, default: 0\n"); + mpp_logi(" --en_shp [int]: en_shp flag, default: 0\n"); + mpp_logi(" --en_hist [int]: en_hist flag, default: 1\n"); + mpp_logi(" --en_pyr [int]: en_pyr flag, default: 1\n"); + mpp_logi(" --en_bbd [int]: en_bbd flag, default: 1\n"); + mpp_logi(" --bbd_th [int]: bbd threshold, default: 20 in U8 input range\n"); +} + +#if 0 +static RK_S32 get_vdpp_format_uv_sample_shift(RK_S32 fmt, RK_S32 *p_ret_shiftx2) +{ + // Wc = Wy >> shifts[0], Hc = Hy >> shifts[1] + RK_S32 shifts[2] = {0}; + + switch (fmt) { + case VDPP_FMT_NV24: + case VDPP_FMT_NV24_VU: + case VDPP_FMT_NV30: + case VDPP_FMT_Q410: + shifts[0] = 0; + shifts[1] = 0; + break; + case VDPP_FMT_NV16: + case VDPP_FMT_NV16_VU: + case VDPP_FMT_NV20: + case VDPP_FMT_P210: + shifts[0] = 1; + shifts[1] = 0; + break; + case VDPP_FMT_NV12: + case VDPP_FMT_NV12_VU: + case VDPP_FMT_NV15: + case VDPP_FMT_P010: + shifts[0] = 1; + shifts[1] = 1; + break; + case VDPP_FMT_Y_ONLY_8BIT: + case VDPP_FMT_UV_ONLY_8BIT: + break; + default: return -1; + } + + if (p_ret_shiftx2) { + p_ret_shiftx2[0] = shifts[0]; + p_ret_shiftx2[1] = shifts[1]; + } + return 0; +} +#endif + +static inline size_t get_frame_size(RK_S32 fmt, RK_U32 w, RK_U32 h) +{ + size_t frame_size = 0; + + switch (fmt) { + case VDPP_FMT_Y_ONLY_8BIT: { + frame_size = w * h; + } break; + case VDPP_FMT_NV12: + case VDPP_FMT_NV21: { + frame_size = w * h * 3 / 2; + } break; + case VDPP_FMT_NV16: + case VDPP_FMT_NV61: + case VDPP_FMT_UV_ONLY_8BIT: { + frame_size = w * h * 2; + } break; + case VDPP_FMT_NV24: + case VDPP_FMT_NV42: + case VDPP_FMT_RG24: + case VDPP_FMT_BG24: { + frame_size = w * h * 3; + } break; + case VDPP_FMT_RGBA: { + frame_size = w * h * 4; + } break; + case VDPP_FMT_NV15: { + frame_size = w * h * 3 * 5 / 2 / 4; + } break; + case VDPP_FMT_NV20: { + frame_size = w * h * 2 * 5 / 4; + } break; + case VDPP_FMT_NV30: { + frame_size = w * h * 3 * 5 / 4; + } break; + default: { + frame_size = w * h * 4; + } break; + } + + return frame_size; +} diff --git a/mpp/vproc/vdpp/test/vdpp_test.c b/mpp/vproc/vdpp/test/vdpp_test.c new file mode 100644 index 000000000..8cff7200f --- /dev/null +++ b/mpp/vproc/vdpp/test/vdpp_test.c @@ -0,0 +1,1051 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpp_test" + +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_buffer.h" +#include "mpp_info.h" +#include "mpp_env.h" + +#include "utils.h" +#include "vdpp_api.h" + +#define MAX_URL_LEN (256) + +#define SHP_CFG_STRIDE (684) +#define DM_ZME_CFG_STRIDE (260) +#define ES_CFG_STRIDE (68) +#define YUV_MAX_SIZE (12582912) // 4096 * 2048 * 3 / 2 +#define DCI_HIST_SIZE (10240) // (16*16*16*18/8/4 + 256) * 4 + +typedef struct VdppTestCfg_t { + MppFrameFormat src_format; // see MppFrameFormat: 0-nv12, 15-nv24 + RK_U32 src_width; // unit: pixel + RK_U32 src_height; // unit: pixel + RK_U32 src_width_vir; // 16 align, unit: pixel + RK_U32 src_height_vir; // 8 align, unit: pixel + RK_U32 src_swap; // 0-UV, 1-VU + RK_U32 src_range; // 0-limited, 1-full + + RK_U32 dst_fmt; // see VDPP_FMT: 0-yuv444sp, 3-yuv420sp + RK_U32 dst_width; // unit: pixel + RK_U32 dst_height; // unit: pixel + RK_U32 dst_width_vir; // 16 align, unit: pixel + RK_U32 dst_height_vir; // 8 align, unit: pixel + RK_U32 dst_swap; // 0-UV, 1-VU + RK_U32 yuv_out_diff; // diff buffer for chroma data + RK_U32 dst_c_width; // unit: pixel + RK_U32 dst_c_height; // unit: pixel + RK_U32 dst_c_width_vir; // unit: pixel + RK_U32 dst_c_height_vir; // unit: pixel + + RK_U32 frame_num; // default: 1 + RK_U32 work_mode; // {1-iep(unsupported), 2-vep, 3-dci_hist} + + /* high 16 bit: mask; low 3 bit (msb->lsb): dmsr|es|sharp */ + RK_U32 cfg_set; // used in com2, reset enable flag of dmsr/es/sharp + RK_U32 en_dmsr; + RK_U32 en_es; + RK_U32 en_shp; + RK_U32 en_hist; + RK_U32 en_pyr; + RK_U32 en_bbd; + RK_U32 bbd_th; // default: 20 in U8 range + + char src_url[MAX_URL_LEN]; // input image filename + char dst_url[MAX_URL_LEN]; // output image filename + char dst_c_url[MAX_URL_LEN]; // output image filename for chroma data + char slt_url[MAX_URL_LEN]; // system level test file + char out_dir[MAX_URL_LEN]; // output directory for other results + + FILE *fp_src; + FILE *fp_dst; + FILE *fp_dst_c; + FILE *fp_hist; + FILE *fp_hist_l; + FILE *fp_hist_g; + FILE *fp_pyrs[3]; + FILE *fp_slt; + FILE *fp_result; +} VdppTestCfg; + +const RK_U32 local_hist_size = RKVOP_PQ_PREPROCESS_HIST_SIZE_VERI * RKVOP_PQ_PREPROCESS_HIST_SIZE_HORI * + RKVOP_PQ_PREPROCESS_LOCAL_HIST_BIN_NUMS * sizeof(RK_U32); +const RK_U32 global_hist_size = RKVOP_PQ_PREPROCESS_GLOBAL_HIST_BIN_NUMS * sizeof(RK_U32); + +extern void mpp_show_color_format(); + +static void print_help_info() +{ + mpp_logi("Usage: vdpq_test [options]\n"); + mpp_logi("Options:\n"); + mpp_logi(" -h, --help : show this message\n"); + mpp_logi(" -v, --version : show version info\n"); + mpp_logi(" -i, --input : input filename\n"); + mpp_logi(" -o, --output [file]: output filename [of luma data] \n"); + mpp_logi(" -O, --outc [file]: output filename of chroma data \n"); + mpp_logi(" -d --outdir [dir]: output directory for other results (hist/pyr data; avg_luma/bbd result...)\n"); + mpp_logi(" -w, --swid [int]: input valid width, unit: pixel, default: 1920\n"); + mpp_logi(" -g, --shgt [int]: input valid height, unit: pixel, default: 1080\n"); + mpp_logi(" --sw_vir [int]: input aligned width, unit: pixel\n"); + mpp_logi(" --sh_vir [int]: input aligned height, unit: pixel\n"); + mpp_logi(" -f, --sfmt [int]: input image format in MppFrameFormat, defualt: 0(nv12)\n"); + mpp_logi(" -s, --sswap : input image chroma_uv is swapped\n"); + mpp_logi(" -r, --srange [int]: input image range is limited(0) or full(1)\n"); + mpp_logi(" -W, --dwid [int]: output [luma] valid width, unit: pixel, default: same to src\n"); + mpp_logi(" -G, --dhgt [int]: output [luma] valid height, unit: pixel, default: same to src\n"); + mpp_logi(" --dw_vir [int]: output [luma] aligned width, unit: pixel\n"); + mpp_logi(" --dh_vir [int]: output [luma] aligned height, unit: pixel\n"); + mpp_logi(" --dwc [int]: output chroma valid width, unit: pixel\n"); + mpp_logi(" --dhc [int]: output chroma valid height, unit: pixel\n"); + mpp_logi(" --dwc_vir [int]: output chroma aligned width, unit: pixel\n"); + mpp_logi(" --dhc_vir [int]: output chroma aligned height, unit: pixel\n"); + mpp_logi(" -F, --dfmt [int]: output image format in ASCII string, defualt: yuv444\n"); + mpp_logi(" -S, --dswap : output image chroma_uv is swapped\n"); + mpp_logi(" -m, --mode [int]: vdpp work mode: {2-vep, 3-dci_hist}, default: 2\n"); + mpp_logi(" -n, --nframe [int]: frame number, default: 1\n"); + mpp_logi(" --slt : system level test file\n"); + mpp_logi(" --cfg_set [int]: high 16 bit: mask; low 3 bit (msb->lsb): dmsr|es|sharp. default: 0x0\n"); + mpp_logi(" --en_dmsr [int]: en_dmsr flag, default: 0\n"); + mpp_logi(" --en_es [int]: en_es flag, default: 0\n"); + mpp_logi(" --en_shp [int]: en_shp flag, default: 0\n"); + mpp_logi(" --en_hist [int]: en_hist flag, default: 1\n"); + mpp_logi(" --en_pyr [int]: en_pyr flag, default: 1\n"); + mpp_logi(" --en_bbd [int]: en_bbd flag, default: 1\n"); + mpp_logi(" --bbd_th [int]: bbd threshold, default: 20 in U8 input range\n"); +} + +static void vdpp_test_help() +{ + mpp_logi("usage: vdpp_test [options]\n"); + mpp_logi("*******************************\n"); + print_help_info(); + mpp_show_color_format(); + mpp_logi("*******************************\n"); + mpp_logi("supported output ASCII format strings:\n"); + mpp_logi("0 - yuv444(sp)\n"); + mpp_logi("2 - yuv420(sp) \n"); + mpp_logi("************ sample ***********\n"); + mpp_logi("vdpp_test -w 720 -g 480 -i input_yuv420.yuv -f 0 -W 1920 -G 1080 -F yuv444 -o " + "output_yuv444.yuv -n 1\n"); +} + +static RK_S32 str_to_vdpp_fmt(const char *str) +{ + RK_S32 fmt = -1; + + if (0 == strcmp(str, "yuv420") || 0 == strcmp(str, "2")) + fmt = VDPP_FMT_YUV420; + else if (0 == strcmp(str, "yuv444") || 0 == strcmp(str, "0")) + fmt = VDPP_FMT_YUV444; + else + mpp_loge("invalid output vdpp format %s!\n", str); + + return fmt; +} + +static inline size_t get_src_frm_size(RK_S32 fmt, RK_U32 w, RK_U32 h) +{ + RK_S32 frame_size; + + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP: + case MPP_FMT_YUV420P: { + frame_size = w * h * 3 / 2; + } break; + + case MPP_FMT_YUV422_YUYV: + case MPP_FMT_YUV422_YVYU: + case MPP_FMT_YUV422_UYVY: + case MPP_FMT_YUV422_VYUY: + case MPP_FMT_YUV422P: + case MPP_FMT_YUV422SP: + case MPP_FMT_RGB444: + case MPP_FMT_BGR444: + case MPP_FMT_RGB555: + case MPP_FMT_BGR555: + case MPP_FMT_RGB565: + case MPP_FMT_BGR565: { + frame_size = w * h * 2; + } break; + case MPP_FMT_YUV444P: + case MPP_FMT_YUV444SP: + case MPP_FMT_RGB888: + case MPP_FMT_BGR888: { + frame_size = w * h * 3; + } break; + case MPP_FMT_RGB101010: + case MPP_FMT_BGR101010: + case MPP_FMT_ARGB8888: + case MPP_FMT_ABGR8888: + case MPP_FMT_BGRA8888: + case MPP_FMT_RGBA8888: { + frame_size = w * h * 4; + } break; + case MPP_FMT_YUV420SP_10BIT: { + frame_size = w * h * 3 * 5 / 2 / 4; + } break; + case MPP_FMT_YUV422SP_10BIT: { + frame_size = w * h * 2 * 5 / 4; + } break; + case MPP_FMT_YUV444SP_10BIT: { + frame_size = w * h * 3 * 5 / 4; + } break; + default: { + frame_size = w * h * 4; + } break; + } + + return frame_size; +} + +static inline size_t get_dst_frm_size(RK_S32 fmt, RK_U32 w, RK_U32 h) +{ + switch (fmt) { + case VDPP_FMT_YUV444: + return w * h * 3; + case VDPP_FMT_YUV420: + return w * h * 3 / 2; + case VDPP_FMT_YUV444 + 10: // chroma of NV24 + case VDPP_FMT_YUV420 + 10: // chroma of NV12 + return w * h * 2; + default: { + mpp_loge("warning: unsupported output format %d!\n", fmt); + } return 0; + } +} + +static int parse_cmd(int argc, char **argv, VdppTestCfg *cfg) +{ + extern char *optarg; + extern int opterr; + RK_S32 ch; + RK_S32 option_index = 0; + + static struct option long_options[] = { + {"sw_vir", required_argument, 0, 0 }, // 0 + {"sh_vir", required_argument, 0, 0 }, + {"dw_vir", required_argument, 0, 0 }, + {"dh_vir", required_argument, 0, 0 }, + {"dwc", required_argument, 0, 0 }, // 4 + {"dhc", required_argument, 0, 0 }, + {"dwc_vir", required_argument, 0, 0 }, + {"dhc_vir", required_argument, 0, 0 }, + {"cfg_set", required_argument, 0, 0 }, // 8 + {"en_dmsr", required_argument, 0, 0 }, // 9 + {"en_es", required_argument, 0, 0 }, // 10 + {"en_shp", required_argument, 0, 0 }, // 11 + {"en_hist", required_argument, 0, 0 }, // 12 + {"en_pyr", required_argument, 0, 0 }, // 13 + {"en_bbd", required_argument, 0, 0 }, // 14 + {"bbd_th", required_argument, 0, 0 }, // 15 + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, + {"input", required_argument, 0, 'i'}, + {"output", required_argument, 0, 'o'}, + {"outc", required_argument, 0, 'O'}, // set 'uv_diff' to 1 if 'outc' valid + {"outdir", required_argument, 0, 'd'}, + {"swid", required_argument, 0, 'w'}, + {"shgt", required_argument, 0, 'g'}, + {"sfmt", required_argument, 0, 'f'}, + {"srange", required_argument, 0, 'r'}, + {"sswap", no_argument, 0, 's'}, + {"dwid", required_argument, 0, 'W'}, + {"dhgt", required_argument, 0, 'G'}, + {"dfmt", required_argument, 0, 'F'}, + {"dswap", no_argument, 0, 'S'}, + {"mode", required_argument, 0, 'm'}, + {"nframe", required_argument, 0, 'n'}, + {"slt", required_argument, 0, 't'}, + {0, 0, 0, 0 }, + }; + + /* set default values */ + memset(cfg, 0, sizeof(VdppTestCfg)); + cfg->src_format = MPP_FMT_YUV420SP; + cfg->src_swap = VDPP_YUV_SWAP_SP_UV; + cfg->src_range = VDPP_COLOR_SPACE_LIMIT_RANGE; + cfg->src_width = 1920; + cfg->src_height = 1080; + cfg->dst_fmt = VDPP_FMT_YUV420; + cfg->dst_swap = VDPP_YUV_SWAP_SP_UV; + cfg->work_mode = VDPP_WORK_MODE_VEP; + cfg->frame_num = 1; + cfg->en_dmsr = 0; + cfg->en_es = 0; + cfg->en_shp = 0; + cfg->en_hist = 1; + cfg->en_pyr = 1; + cfg->en_bbd = 1; + cfg->bbd_th = 20; + + /* parse arguments */ + opterr = 0; + while ((ch = getopt_long_only(argc, argv, "i:o:O:d:w:g:f:r:W:G:F:m:n:t:hvsS", long_options, + &option_index)) != -1) { + switch (ch) { + case 0: { + mpp_logi(" - set %dth option: %s = %s", option_index, + long_options[option_index].name, optarg); + switch (option_index) { + case 0: { + cfg->src_width_vir = strtol(optarg, NULL, 0); + } break; + case 1: { + cfg->src_height_vir = strtol(optarg, NULL, 0); + } break; + case 2: { + cfg->dst_width_vir = strtol(optarg, NULL, 0); + } break; + case 3: { + cfg->dst_height_vir = strtol(optarg, NULL, 0); + } break; + case 4: { + cfg->dst_c_width = strtol(optarg, NULL, 0); + } break; + case 5: { + cfg->dst_c_height = strtol(optarg, NULL, 0); + } break; + case 6: { + cfg->dst_c_width_vir = strtol(optarg, NULL, 0); + } break; + case 7: { + cfg->dst_c_height_vir = strtol(optarg, NULL, 0); + } break; + case 8: { + cfg->cfg_set = strtol(optarg, NULL, 0); + } break; + case 9: { + cfg->en_dmsr = strtol(optarg, NULL, 0); + } break; + case 10: { + cfg->en_es = strtol(optarg, NULL, 0); + } break; + case 11: { + cfg->en_shp = strtol(optarg, NULL, 0); + } break; + case 12: { + cfg->en_hist = strtol(optarg, NULL, 0); + } break; + case 13: { + cfg->en_pyr = strtol(optarg, NULL, 0); + } break; + case 14: { + cfg->en_bbd = strtol(optarg, NULL, 0); + } break; + case 15: { + cfg->bbd_th = strtol(optarg, NULL, 0); + } break; + default: break; + } + } break; + case 'h': { + vdpp_test_help(); + } return 1; + case 'v': { + show_mpp_version(); + } return 2; + case 'i': { + strncpy(cfg->src_url, optarg, sizeof(cfg->src_url) - 1); + mpp_logi(" - set input filename: %s\n", optarg); + } break; + case 'o': { + strncpy(cfg->dst_url, optarg, sizeof(cfg->dst_url) - 1); + mpp_logi(" - set output [luma] filename: %s\n", optarg); + } break; + case 'O': { + strncpy(cfg->dst_c_url, optarg, sizeof(cfg->dst_c_url) - 1); + cfg->yuv_out_diff = 1; + mpp_logi(" - set yuv_out_diff=1 since output chroma filename set: %s\n", optarg); + } break; + case 'd': { + strncpy(cfg->out_dir, optarg, sizeof(cfg->out_dir) - 1); + mpp_logi(" - set output directory: %s\n", optarg); + } break; + case 'w': { + cfg->src_width = strtol(optarg, NULL, 0); + } break; + case 'g': { + cfg->src_height = strtol(optarg, NULL, 0); + } break; + case 'f': { + cfg->src_format = strtol(optarg, NULL, 0); + mpp_logi(" - set input mpp format: %d\n", cfg->src_format); + } break; + case 'r': { + cfg->src_range = strtol(optarg, NULL, 0); + mpp_logi(" - set input range: %d (0-Limit, 1-Full)\n", cfg->src_range); + } break; + case 's': { + cfg->src_swap = 1; + mpp_logi(" - set input format UV swaped!\n"); + } break; + case 'W': { + cfg->dst_width = strtol(optarg, NULL, 0); + } break; + case 'G': { + cfg->dst_height = strtol(optarg, NULL, 0); + } break; + case 'F': { + cfg->dst_fmt = str_to_vdpp_fmt(optarg); + mpp_logi(" - set output format: %s -> %d (vdpp format)\n", optarg, cfg->dst_fmt); + } break; + case 'S': { + cfg->dst_swap = 1; + mpp_logi(" - set output format UV swaped!\n"); + } break; + case 'm': { + cfg->work_mode = MPP_MAX(VDPP_WORK_MODE_VEP, atoi(optarg)); + mpp_logi(" - set work mode: %d (2-vep, 3-dci_hist)\n", cfg->work_mode); + } break; + case 'n': { + cfg->frame_num = strtol(optarg, NULL, 0); + } break; + case 't': { + strncpy(cfg->slt_url, optarg, sizeof(cfg->slt_url) - 1); + mpp_logi(" - set slt filename: %s\n", optarg); + } break; + default: break; + } + } + + /* check & adjust arguments */ + if (!cfg->src_url[0]) { + mpp_err("input filename not specified!\n"); + return -1; + } + if (cfg->work_mode != VDPP_WORK_MODE_DCI) { + if (cfg->dst_fmt != VDPP_FMT_YUV420 && cfg->dst_fmt != VDPP_FMT_YUV444) { + mpp_loge("output format %d not supported!\n", cfg->dst_fmt); + return -1; + } + } + mpp_logi(" - set input image size: %dx%d, mpp format: %d, fullrange: %d\n", cfg->src_width, + cfg->src_height, cfg->src_format, cfg->src_range); + + if (!cfg->src_width_vir) + cfg->src_width_vir = MPP_ALIGN(cfg->src_width, 16); + if (!cfg->src_height_vir) + cfg->src_height_vir = MPP_ALIGN(cfg->src_height, 8); + if (!cfg->dst_width) + cfg->dst_width = cfg->src_width; + if (!cfg->dst_height) + cfg->dst_height = cfg->src_height; + if (!cfg->dst_width_vir) + cfg->dst_width_vir = MPP_ALIGN(cfg->dst_width, 16); + if (!cfg->dst_height_vir) + cfg->dst_height_vir = MPP_ALIGN(cfg->dst_height, 2); + if (cfg->yuv_out_diff) { + int shift_bit = (cfg->dst_fmt == VDPP_FMT_YUV420); // 1 for yuv420 + + if (!cfg->dst_c_width) + cfg->dst_c_width = cfg->dst_width >> shift_bit; + if (!cfg->dst_c_width_vir) + cfg->dst_c_width_vir = MPP_ALIGN(cfg->dst_c_width, 16); + if (!cfg->dst_c_height) + cfg->dst_c_height = cfg->dst_height >> shift_bit; + if (!cfg->dst_c_height_vir) + cfg->dst_c_height_vir = MPP_ALIGN(cfg->dst_c_height, 2); + mpp_logi(" - set output chroma size: %dx%d, virtual size: %dx%d\n", cfg->dst_c_width, + cfg->dst_c_height, cfg->dst_c_width_vir, cfg->dst_c_height_vir); + } + mpp_logi(" - set output image size: %dx%d, virtual size: %dx%d, vdpp format: %d\n", + cfg->dst_width, cfg->dst_height, cfg->dst_width_vir, cfg->dst_height_vir, cfg->dst_fmt); + mpp_logi(" - set enbale flags: dmsr=%d, es=%d, shp=%d, hist=%d, pyr=%d, bbd=%d\n", + cfg->en_dmsr, cfg->en_es, cfg->en_shp, cfg->en_hist, cfg->en_pyr, cfg->en_bbd); + + return 0; +} + +static void vdpp_test_set_img(VdppComCtx *ctx, RK_S32 fd_y, RK_S32 fd_c, + RK_U32 uv_offset, VdppCmd cmd) +{ + VdppImg img = {0}; + MPP_RET ret = MPP_OK; + + img.mem_addr = fd_y; + img.uv_addr = fd_c; + img.uv_off = uv_offset; + mpp_logi("set buf: type=%#x, yrgb_fd=%d, cbcr_fd=%d, chroma_offset=%d\n", + cmd, fd_y, fd_c, uv_offset); + + ret = ctx->ops->control(ctx->priv, cmd, &img); + if (ret) + mpp_loge_f("control %08x failed %d!\n", cmd, ret); +} + +int vdpp_test(VdppComCtx *vdppCtx, VdppTestCfg *cfg) +{ + MppBufferGroup memGroup = NULL; + MppBuffer srcbuf = NULL; + MppBuffer dstbuf = NULL; + MppBuffer dstbuf_c = NULL; + MppBuffer histbuf = NULL; + MppBuffer histbuf_l = NULL; + MppBuffer histbuf_g = NULL; + MppBuffer pyrbuf_l1 = NULL; + MppBuffer pyrbuf_l2 = NULL; + MppBuffer pyrbuf_l3 = NULL; + RK_U8 *psrc = NULL; + RK_U8 *pdst = NULL; + RK_U8 *pdst_c = NULL; + RK_U8 *phist = NULL; + RK_U8 *phist_l = NULL; + RK_U8 *phist_g = NULL; + RK_U8 *pyrAddrs[3] = {0}; + RK_S32 fdsrc = -1; + RK_S32 fddst = -1; + RK_S32 fddst_c = -1; + RK_S32 fdhist = -1; + RK_S32 pyrFds[3] = { -1, -1, -1}; + RK_U32 pyrWids[3] = {0}; + RK_U32 pyrHgts[3] = {0}; + RK_U32 pyrSizes[3] = {0}; + + VdppApiParams params; + VdppResults results = {0}; + DataCrc checkcrc; + + RK_U32 vdpp_ver = MPP_MAX(vdppCtx->ver >> 8, 1); // {0x100, 0x200, 0x300} + RK_U32 yuv_out_diff = (cfg->yuv_out_diff && (vdpp_ver >= 2)); + size_t srcfrmsize = 0; + size_t dstfrmsize = 0; + size_t dstfrmsize_c = 0; + size_t readsize = 0; + RK_U32 frame_cnt = 0; + RK_S32 i = 0; + MPP_RET ret = MPP_NOK; + + // calculate aligned width independently, dword 4x align + pyrWids[0] = MPP_ALIGN(cfg->dst_width / 2, 16); + pyrWids[1] = MPP_ALIGN(cfg->dst_width / 4, 16); + pyrWids[2] = MPP_ALIGN(cfg->dst_width / 8, 16); + pyrHgts[0] = (cfg->dst_height + 1) / 2; + pyrHgts[1] = (cfg->dst_height + 3) / 4; + pyrHgts[2] = (cfg->dst_height + 7) / 8; + pyrSizes[0] = pyrWids[0] * pyrHgts[0]; + pyrSizes[1] = pyrWids[1] * pyrHgts[1]; + pyrSizes[2] = pyrWids[2] * pyrHgts[2]; + + memset(&checkcrc, 0, sizeof(checkcrc)); + checkcrc.sum = mpp_malloc(RK_ULONG, 512); + + srcfrmsize = get_src_frm_size(cfg->src_format, cfg->src_width_vir, cfg->src_height_vir); + dstfrmsize = get_dst_frm_size(cfg->dst_fmt, cfg->dst_width_vir, cfg->dst_height_vir); + // (dst_fmt + 10) for chroma plane + dstfrmsize_c = get_dst_frm_size(cfg->dst_fmt + 10, cfg->dst_c_width_vir, cfg->dst_c_height_vir); + + /* create buffers */ + ret = mpp_buffer_group_get_internal(&memGroup, MPP_BUFFER_TYPE_DRM); + if (MPP_OK != ret) { + mpp_loge("memGroup mpp_buffer_group_get failed! %d\n", ret); + return ret; + } + + mpp_buffer_get(memGroup, &srcbuf, srcfrmsize); + mpp_buffer_get(memGroup, &dstbuf, dstfrmsize); + mpp_assert(srcbuf && dstbuf); + + mpp_buffer_get(memGroup, &histbuf, DCI_HIST_SIZE); + mpp_buffer_get(memGroup, &histbuf_l, local_hist_size); + mpp_buffer_get(memGroup, &histbuf_g, global_hist_size); + mpp_assert(histbuf && histbuf_l && histbuf_g); + + mpp_buffer_get(memGroup, &pyrbuf_l1, pyrSizes[0]); + mpp_buffer_get(memGroup, &pyrbuf_l2, pyrSizes[1]); + mpp_buffer_get(memGroup, &pyrbuf_l3, pyrSizes[2]); + mpp_assert(pyrbuf_l1 && pyrbuf_l2 && pyrbuf_l3); + + psrc = mpp_buffer_get_ptr(srcbuf); + pdst = mpp_buffer_get_ptr(dstbuf); + phist = mpp_buffer_get_ptr(histbuf); + phist_l = mpp_buffer_get_ptr(histbuf_l); + phist_g = mpp_buffer_get_ptr(histbuf_g); + pyrAddrs[0] = mpp_buffer_get_ptr(pyrbuf_l1); + pyrAddrs[1] = mpp_buffer_get_ptr(pyrbuf_l2); + pyrAddrs[2] = mpp_buffer_get_ptr(pyrbuf_l3); + + fdsrc = mpp_buffer_get_fd(srcbuf); + fddst = mpp_buffer_get_fd(dstbuf); + fdhist = mpp_buffer_get_fd(histbuf); + pyrFds[0] = mpp_buffer_get_fd(pyrbuf_l1); + pyrFds[1] = mpp_buffer_get_fd(pyrbuf_l2); + pyrFds[2] = mpp_buffer_get_fd(pyrbuf_l3); + + mpp_logi("vdpp_ver: %d, is_yuv_out_diff: %d, work_mode: %d", + vdpp_ver, yuv_out_diff, cfg->work_mode); + mpp_logi("src w:h [%d:%d] stride [%d:%d] require buf %d bytes. fd %d\n", cfg->src_width, + cfg->src_height, cfg->src_width_vir, cfg->src_height_vir, srcfrmsize, fdsrc); + mpp_logi("dst w:h [%d:%d] stride [%d:%d] require buf %d bytes. fd %d\n", cfg->dst_width, + cfg->dst_height, cfg->dst_width_vir, cfg->dst_height_vir, dstfrmsize, fddst); + + if (yuv_out_diff) { + mpp_buffer_get(memGroup, &dstbuf_c, dstfrmsize_c); + mpp_assert(dstbuf_c); + + pdst_c = mpp_buffer_get_ptr(dstbuf_c); + fddst_c = mpp_buffer_get_fd(dstbuf_c); + + mpp_logi("dst chroma w:h [%d:%d] stride [%d:%d] require buf %d bytes. fd %d\n", + cfg->dst_c_width, cfg->dst_c_height, cfg->dst_c_width_vir, + cfg->dst_c_height_vir, dstfrmsize_c, fddst_c); + } + + for (i = 0; i < 3; i++) { + mpp_logi("pyr[%d] info: size=%ux%u, require buf %u bytes. fd %d\n", + i + 1, pyrWids[i], pyrHgts[i], pyrSizes[i], pyrFds[i]); + } + + /* vdpp_params are all set to default values in init() */ + ret = vdppCtx->ops->init(vdppCtx->priv); + if (ret) { + mpp_err_f("init vdpp context failed! %d\n", ret); + return ret; + } + + /* set common api params */ + if (vdpp_ver >= 2) { + params.ptype = VDPP_PARAM_TYPE_COM2; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.com2.sfmt = cfg->src_format; + params.param.com2.sswap = cfg->src_swap; + params.param.com2.src_width = cfg->src_width; + params.param.com2.src_height = cfg->src_height; + params.param.com2.src_width_vir = cfg->src_width_vir; + params.param.com2.src_height_vir = cfg->src_height_vir; + params.param.com2.src_range = cfg->src_range; + params.param.com2.dfmt = cfg->dst_fmt; + params.param.com2.dswap = cfg->dst_swap; + params.param.com2.dst_width = cfg->dst_width; + params.param.com2.dst_height = cfg->dst_height; + params.param.com2.dst_width_vir = cfg->dst_width_vir; + params.param.com2.dst_height_vir = cfg->dst_height_vir; + if (yuv_out_diff) { + params.param.com2.yuv_out_diff = 1; + params.param.com2.dst_c_width = cfg->dst_c_width; + params.param.com2.dst_c_height = cfg->dst_c_height; + params.param.com2.dst_c_width_vir = cfg->dst_c_width_vir; + params.param.com2.dst_c_height_vir = cfg->dst_c_height_vir; + } + params.param.com2.hist_mode_en = cfg->work_mode == VDPP_WORK_MODE_DCI; + params.param.com2.cfg_set = cfg->cfg_set; + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_COM2_CFG, ¶ms); + + mpp_logi("set api param: sfmt=%d, sswap=%d, src_range=%d, size=%dx%d [%dx%d]\n", + params.param.com2.sfmt, params.param.com2.sswap, cfg->src_range, + params.param.com2.src_width, params.param.com2.src_height, + params.param.com2.src_width_vir, params.param.com2.src_height_vir); + mpp_logi("set api param: dfmt=%d, dswap=%d, size=%dx%d [%dx%d]\n", params.param.com2.dfmt, + params.param.com2.dswap, params.param.com2.dst_width, params.param.com2.dst_height, + params.param.com2.dst_width_vir, params.param.com2.dst_height_vir); + mpp_logi("set api param: yuv_out_diff=%d, dst_c_size=%dx%d [%dx%d]\n", + params.param.com2.yuv_out_diff, params.param.com2.dst_c_width, + params.param.com2.dst_c_height, params.param.com2.dst_c_width_vir, + params.param.com2.dst_c_height_vir); + mpp_logi("set api param: hist_only_mode=%d, cfg_set=%d\n", params.param.com2.hist_mode_en, + params.param.com2.cfg_set); + } else { + params.ptype = VDPP_PARAM_TYPE_COM; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.com.src_width = cfg->src_width; + params.param.com.src_height = cfg->src_height; + params.param.com.sswap = cfg->src_swap; + params.param.com.dfmt = cfg->dst_fmt; + params.param.com.dst_width = cfg->dst_width; + params.param.com.dst_height = cfg->dst_height; + params.param.com.dswap = cfg->dst_swap; + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_COM_CFG, ¶ms); + } + + /* close dmsr/es/sharp after com if needed, since the enable_flags will be reset by com */ + if (!cfg->en_dmsr) { + params.ptype = VDPP_PARAM_TYPE_DMSR; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.dmsr.enable = 0; + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_DMSR_CFG, ¶ms); + mpp_logi("set api param: disbale DMSR...\n"); + } + + if (!cfg->en_es) { + params.ptype = VDPP_PARAM_TYPE_ES; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.es.es_bEnabledES = 0; + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_ES, ¶ms); + mpp_logi("set api param: disbale ES...\n"); + } + + if (vdpp_ver >= 2) { + if (!cfg->en_shp) { + params.ptype = VDPP_PARAM_TYPE_SHARP; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.sharp.sharp_enable = 0; + params.param.sharp.sharp_coloradj_bypass_en = 1; + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_SHARP, ¶ms); + mpp_logi("set api param: disbale Sharp...\n"); + } + + params.ptype = VDPP_PARAM_TYPE_HIST; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.hist.hist_cnt_en = cfg->en_hist; + params.param.hist.dci_csc_range = cfg->src_range; + params.param.hist.hist_addr = fdhist; + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_DCI_HIST, ¶ms); + mpp_logi("set api param: hist_cnt_en=%d (work_mode=%d), csc_range=%d, hist_fd=%d\n", + params.param.hist.hist_cnt_en, cfg->work_mode, params.param.hist.dci_csc_range, + params.param.hist.hist_addr); + } + + /* set pyr & bbd params */ + if (vdpp_ver >= 3) { + params.ptype = VDPP_PARAM_TYPE_PYR; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.pyr.pyr_en = cfg->en_pyr && (pyrFds[0] > 0) && (pyrFds[1] > 0) && + (pyrFds[2] > 0) && cfg->work_mode != VDPP_WORK_MODE_DCI; + mpp_logi("set api param: pyr_en=%d.\n", params.param.pyr.pyr_en); + if (params.param.pyr.pyr_en) { + params.param.pyr.nb_layers = 3; + for (i = 0; i < 3; i++) { + params.param.pyr.layer_imgs[i].mem_addr = (RK_U32)pyrFds[i]; // fd + params.param.pyr.layer_imgs[i].wid_vir = pyrWids[i]; // unit: pixel + params.param.pyr.layer_imgs[i].hgt_vir = pyrHgts[i]; // unit: pixel + mpp_logi("set api param: pyr[%d] addr=%u, wid_vir=%u (unit: pixel)\n", + i + 1, params.param.pyr.layer_imgs[i].mem_addr, + params.param.pyr.layer_imgs[i].wid_vir); + } + } + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_PYR, ¶ms); + + params.ptype = VDPP_PARAM_TYPE_BBD; + memset(¶ms.param, 0, sizeof(VdppApiContent)); + params.param.bbd.bbd_en = cfg->en_bbd; + params.param.bbd.bbd_det_blcklmt = 20; + mpp_logi("set api param: bbd_en=%d, bbd_det_blcklmt=%d\n", params.param.bbd.bbd_en, + params.param.bbd.bbd_det_blcklmt); + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_BBD, ¶ms); + } + + /* check cap */ + { + RK_S32 cap = vdppCtx->ops->check_cap(vdppCtx->priv); + + mpp_logi("vdpp cap %#x (bitfield: 0-UNSUPPORTED, 1-VEP, 2-HIST)\n", cap); + } + + /* run vdpp */ + while (1) { + readsize = fread(psrc, 1, srcfrmsize, cfg->fp_src); + if (srcfrmsize > readsize) { + mpp_logi("source exhaused since readsize=%d < srcfrmsize=%d. total frames processed: %d\n", + readsize, srcfrmsize, frame_cnt); + break; + } + if (frame_cnt >= cfg->frame_num) + break; + + /* notice the order of the input frames */ + vdpp_test_set_img(vdppCtx, fdsrc, fdsrc, cfg->src_width_vir * cfg->src_height_vir, + VDPP_CMD_SET_SRC); + vdpp_test_set_img(vdppCtx, fddst, fddst, cfg->dst_width_vir * cfg->dst_height_vir, + VDPP_CMD_SET_DST); + if (yuv_out_diff) + vdpp_test_set_img(vdppCtx, fddst, fddst_c, 0, VDPP_CMD_SET_DST_C); + + if (cfg->en_hist) + vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_SET_HIST_FD, &fdhist); + + memset(pdst, 0, dstfrmsize); + memset(phist, 0, DCI_HIST_SIZE); + + ret = vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_RUN_SYNC, NULL); + if (ret) { + mpp_loge("found vdpp run error, exit! %d\n", ret); + break; + } + + frame_cnt++; + + // write dst data + if (cfg->fp_dst) { + if (yuv_out_diff && pdst_c) { + fwrite(pdst, 1, cfg->dst_width_vir * cfg->dst_height_vir, cfg->fp_dst); + fwrite(pdst_c, 1, dstfrmsize_c, cfg->fp_dst); // write chroma data after dst luma + } else + fwrite(pdst, 1, dstfrmsize, cfg->fp_dst); + mpp_logi("dst data dump to: %s\n", cfg->dst_url); + } + + if (yuv_out_diff && cfg->fp_dst_c && pdst_c) { + if (dstfrmsize_c > fwrite(pdst_c, 1, dstfrmsize_c, cfg->fp_dst_c)) { + mpp_loge("chroma dump failed, errno %d %s\n", errno, strerror(errno)); + break; + } + mpp_logi("dst chroma data dump to: %s\n", cfg->dst_c_url); + } + + // write hist data + if (cfg->en_hist) { + memset(phist_l, 0, local_hist_size); + memset(phist_g, 0, global_hist_size); + dci_hist_info_parser(phist, (RK_U32 *)phist_l, (RK_U32 *)phist_g); + + if (cfg->fp_hist) { + if (DCI_HIST_SIZE > fwrite(phist, 1, DCI_HIST_SIZE, cfg->fp_hist)) { + mpp_loge("packed hist dump err!\n"); + break; + } + } + if (cfg->fp_hist_l) { + if (local_hist_size > fwrite(phist_l, 1, local_hist_size, cfg->fp_hist_l)) { + mpp_loge("local hist dump err!\n"); + break; + } + } + if (cfg->fp_hist_g) { + if (global_hist_size > fwrite(phist_g, 1, global_hist_size, cfg->fp_hist_g)) { + mpp_loge("global hist dump err!\n"); + break; + } + } + + // get mean luma result + ret = vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_GET_AVG_LUMA, &results); + if (ret) { + mpp_loge("get mean luma result error! %d\n", ret); + } else { + mpp_logi("get mean luma result: %d (in U10)\n", results.hist.luma_avg); + if (cfg->fp_result) { + fprintf(cfg->fp_result, "mean luma result: %d\n", results.hist.luma_avg); + } + } + } + + // write pyr data + if (cfg->en_pyr) { + for (i = 0; i < 3; ++i) { + if (cfg->fp_pyrs[i]) { + if (pyrSizes[i] > fwrite(pyrAddrs[i], 1, pyrSizes[i], cfg->fp_pyrs[i])) { + mpp_loge("pryamid layer%d dump err!\n", i + 1); + break; + } + } + } + } + + // write crc, DONOT modify the code here! + if (cfg->fp_slt) { + if (pdst && cfg->work_mode != VDPP_WORK_MODE_DCI) { + calc_data_crc(pdst, dstfrmsize, &checkcrc); + write_data_crc(cfg->fp_slt, &checkcrc); + } + if (pdst_c && yuv_out_diff && cfg->work_mode != VDPP_WORK_MODE_DCI) { + calc_data_crc(pdst_c, dstfrmsize_c, &checkcrc); + write_data_crc(cfg->fp_slt, &checkcrc); + } + if (phist) { + calc_data_crc(phist, DCI_HIST_SIZE, &checkcrc); + write_data_crc(cfg->fp_slt, &checkcrc); + } + } + + // get bbd result + if (cfg->en_bbd) { + ret = vdppCtx->ops->control(vdppCtx->priv, VDPP_CMD_GET_BBD, &results); + if (ret) { + mpp_loge("get bbd result error! %d\n", ret); + } else { + mpp_logi("get bbd result: top/bottom/left/right = [%d, %d, %d, %d]\n", + results.bbd.bbd_size_top, results.bbd.bbd_size_bottom, + results.bbd.bbd_size_left, results.bbd.bbd_size_right); + if (cfg->fp_result) { + fprintf(cfg->fp_result, "bbd result: [top=%d, btm=%d, left=%d, right=%d]\n", + results.bbd.bbd_size_top, results.bbd.bbd_size_bottom, + results.bbd.bbd_size_left, results.bbd.bbd_size_right); + fflush(cfg->fp_result); + } + } + } + } + mpp_logi("=============run sync done=============cnt[%d]\n", frame_cnt); + + mpp_buffer_put(srcbuf); + mpp_buffer_put(dstbuf); + mpp_buffer_put(histbuf); + if (histbuf_l) + mpp_buffer_put(histbuf_l); + if (histbuf_g) + mpp_buffer_put(histbuf_g); + if (yuv_out_diff) + mpp_buffer_put(dstbuf_c); + if (pyrbuf_l1) + mpp_buffer_put(pyrbuf_l1); + if (pyrbuf_l2) + mpp_buffer_put(pyrbuf_l2); + if (pyrbuf_l3) + mpp_buffer_put(pyrbuf_l3); + + MPP_FREE(checkcrc.sum); + + if (memGroup) { + mpp_buffer_group_put(memGroup); + memGroup = NULL; + } + + ret = vdppCtx->ops->deinit(vdppCtx->priv); + if (ret) { + mpp_logw("vdpp deinit ret %d!\n", ret); + } + + return ret; +} + +RK_S32 main(RK_S32 argc, char **argv) +{ + VdppTestCfg cfg = {0}; + RK_U32 vdpp_ver = 1; + RK_S32 i = 0; + RK_S32 ret = 0; + + mpp_logi("\n"); + mpp_logi("=========== vdpp test start ==============\n"); + ret = parse_cmd(argc, argv, &cfg); + if (ret) { + return ret; + } + + VdppComCtx *vdppCtx = rockchip_vdpp_api_alloc_ctx(); + if (!vdppCtx) { + mpp_loge_f("alloc vdpp context failed! Exit...\n"); + return MPP_ERR_NULL_PTR; + } + + /* update enbale flags */ + vdpp_ver = MPP_MAX(vdppCtx->ver >> 8, 1); // {0x100, 0x200, 0x300} + cfg.en_dmsr &= (vdpp_ver >= 1) && (cfg.work_mode != VDPP_WORK_MODE_DCI); + cfg.en_es &= (vdpp_ver >= 2) && (cfg.work_mode != VDPP_WORK_MODE_DCI); + cfg.en_shp &= (vdpp_ver >= 2) && (cfg.work_mode != VDPP_WORK_MODE_DCI); + cfg.en_hist &= (vdpp_ver >= 2); + cfg.en_pyr &= (vdpp_ver >= 3) && (cfg.work_mode != VDPP_WORK_MODE_DCI); + cfg.en_bbd &= (vdpp_ver >= 3); + mpp_logi(" - update enbale flags: dmsr=%d, es=%d, shp=%d, hist=%d, pyr=%d, bbd=%d\n", + cfg.en_dmsr, cfg.en_es, cfg.en_shp, cfg.en_hist, cfg.en_pyr, cfg.en_bbd); + + /* open files */ + cfg.fp_src = fopen(cfg.src_url, "rb"); + if (cfg.fp_src == NULL) { + mpp_loge("failed to open input file %s! %s\n", cfg.src_url, strerror(errno)); + return -1; + } + + if (cfg.dst_url[0]) { + cfg.fp_dst = fopen(cfg.dst_url, "wb"); + if (cfg.fp_dst == NULL) { + mpp_logw("failed to open output file %s! %s\n", cfg.dst_url, strerror(errno)); + } + } + + if (cfg.dst_c_url[0]) { + cfg.fp_dst_c = fopen(cfg.dst_c_url, "wb"); + if (cfg.fp_dst_c == NULL) { + mpp_logw("failed to open output chroma file %s! %s\n", cfg.dst_c_url, strerror(errno)); + } + } + + if (cfg.slt_url[0]) { + cfg.fp_slt = fopen(cfg.slt_url, "wt"); + if (cfg.fp_slt == NULL) { + mpp_logw("failed to open output file %s! %s\n", cfg.slt_url, strerror(errno)); + } + } + + if (cfg.out_dir[0]) { + char filename[MAX_URL_LEN] = {0}; + + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_com.txt", cfg.out_dir); + cfg.fp_result = fopen(filename, "wt"); + if (cfg.fp_result == NULL) { + mpp_logw("failed to open output com file %s! %s\n", filename, strerror(errno)); + } + + if (cfg.en_hist) { + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_hist_packed.bin", cfg.out_dir); + cfg.fp_hist = fopen(filename, "wb"); + + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_hist_local.bin", cfg.out_dir); + cfg.fp_hist_l = fopen(filename, "wb"); + + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_hist_global.bin", cfg.out_dir); + cfg.fp_hist_g = fopen(filename, "wb"); + } + + if (cfg.en_pyr) { + for (i = 0; i < 3; ++i) { + snprintf(filename, MAX_URL_LEN - 1, "%s/vdpp_res_pyr_l%d.yuv", cfg.out_dir, i + 1); + cfg.fp_pyrs[i] = fopen(filename, "wb"); + } + } + } + + /* run vdpp test */ + ret = vdpp_test(vdppCtx, &cfg); + + /* close files */ + if (cfg.fp_src) { + fclose(cfg.fp_src); + cfg.fp_src = NULL; + } + + if (cfg.fp_dst) { + fclose(cfg.fp_dst); + cfg.fp_dst = NULL; + } + + if (cfg.fp_dst_c) { + fclose(cfg.fp_dst_c); + cfg.fp_dst_c = NULL; + } + + if (cfg.fp_hist) { + fclose(cfg.fp_hist); + cfg.fp_hist = NULL; + } + + if (cfg.fp_hist_l) { + fclose(cfg.fp_hist_l); + cfg.fp_hist_l = NULL; + } + + if (cfg.fp_hist_g) { + fclose(cfg.fp_hist_g); + cfg.fp_hist_g = NULL; + } + + if (cfg.fp_slt) { + fclose(cfg.fp_slt); + cfg.fp_slt = NULL; + } + + if (cfg.fp_result) { + fclose(cfg.fp_result); + cfg.fp_result = NULL; + } + + for (i = 0; i < 3; ++i) { + if (cfg.fp_pyrs[i]) { + fclose(cfg.fp_pyrs[i]); + cfg.fp_pyrs[i] = NULL; + } + } + + rockchip_vdpp_api_release_ctx(vdppCtx); + + mpp_logi("=========== vdpp test end ==============\n\n"); + return ret; +} diff --git a/mpp/vproc/vdpp/vdpp.c b/mpp/vproc/vdpp/vdpp.c new file mode 100644 index 000000000..670079c32 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp.c @@ -0,0 +1,1765 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpp" + +#include +#include +#include + +#include "mpp_common.h" +#include "mpp_env.h" +#include "mpp_service.h" +#include "mpp_platform.h" + +#include "vdpp.h" + +#define VDPP_MODE_MIN_WIDTH (128) +#define VDPP_MODE_MIN_HEIGHT (128) + +// default log level: warning +RK_U32 vdpp_debug = VDPP_LOG_FATAL | VDPP_LOG_ERROR | VDPP_LOG_WARNING; + +/** + * thresholds for different scaling coefs: + * | coef index | ratio | + * | ---------- | -------- | + * | 0 | >= 2.667 | + * | 1 | >= 2.000 | + * | 2 | >= 1.500 | + * | 3 | > 1.000 | + * | 4 | = 1.000 | + * | 5 | >= 0.833 | + * | 6 | >= 0.700 | + * | 7 | >= 0.500 | + * | 8 | >= 0.330 | + * | 9 | >= 0.250 | + * | 10 | < 0.250 | + */ +static const RK_U16 vdpp_scale_threshold[] = { + 2667, 2000, 1500, 1000, 833, 700, 500, 330, 250, +}; + +/* default ZME coefs */ +static const RK_S16 g_zme_tap8_coeff[11][17][8] = { +//>=2.667 + { + { 4, -12, 20, 488, 20, -12, 4, 0}, + { 4, -8, 8, 484, 36, -16, 4, 0}, + { 4, -4, -4, 476, 52, -20, 8, 0}, + { 0, 0, -16, 480, 68, -28, 8, 0}, + { 0, 4, -24, 472, 84, -32, 8, 0}, + { 0, 4, -36, 468, 100, -36, 12, 0}, + { 0, 8, -44, 456, 120, -40, 12, 0}, + { 0, 12, -52, 448, 136, -44, 12, 0}, + { 0, 12, -56, 436, 156, -48, 16, -4}, + { -4, 16, -60, 424, 176, -52, 16, -4}, + { -4, 16, -64, 412, 196, -56, 16, -4}, + { -4, 16, -68, 400, 216, -60, 16, -4}, + { -4, 20, -72, 380, 236, -64, 20, -4}, + { -4, 20, -72, 364, 256, -68, 20, -4}, + { -4, 20, -72, 348, 272, -68, 20, -4}, + { -4, 20, -72, 332, 292, -72, 20, -4}, + { -4, 20, -72, 312, 312, -72, 20, -4}, + }, +//>=2 + { + { 8, -24, 44, 456, 44, -24, 8, 0}, + { 8, -20, 28, 460, 56, -28, 8, 0}, + { 8, -16, 16, 452, 72, -32, 12, 0}, + { 4, -12, 8, 448, 88, -36, 12, 0}, + { 4, -8, -4, 444, 104, -40, 12, 0}, + { 4, -8, -16, 444, 120, -44, 12, 0}, + { 4, -4, -24, 432, 136, -48, 16, 0}, + { 4, 0, -32, 428, 152, -52, 16, -4}, + { 0, 4, -40, 424, 168, -56, 16, -4}, + { 0, 4, -44, 412, 188, -60, 16, -4}, + { 0, 8, -52, 400, 204, -60, 16, -4}, + { 0, 8, -56, 388, 224, -64, 16, -4}, + { 0, 12, -60, 372, 240, -64, 16, -4}, + { 0, 12, -64, 356, 264, -68, 16, -4}, + { 0, 12, -64, 340, 280, -68, 16, -4}, + { 0, 16, -68, 324, 296, -68, 16, -4}, + { 0, 16, -68, 308, 308, -68, 16, 0}, + }, +//>=1.5 + { + { 12, -32, 64, 424, 64, -32, 12, 0}, + { 8, -32, 52, 432, 76, -36, 12, 0}, + { 8, -28, 40, 432, 88, -40, 12, 0}, + { 8, -24, 28, 428, 104, -44, 12, 0}, + { 8, -20, 16, 424, 120, -48, 12, 0}, + { 8, -16, 8, 416, 132, -48, 12, 0}, + { 4, -16, -4, 420, 148, -52, 12, 0}, + { 4, -12, -12, 412, 164, -56, 12, 0}, + { 4, -8, -20, 400, 180, -56, 12, 0}, + { 4, -4, -28, 388, 196, -56, 12, 0}, + { 4, -4, -32, 380, 212, -60, 12, 0}, + { 4, 0, -40, 368, 228, -60, 12, 0}, + { 4, 0, -44, 356, 244, -60, 12, 0}, + { 0, 4, -48, 344, 260, -60, 12, 0}, + { 0, 4, -52, 332, 276, -60, 12, 0}, + { 0, 8, -56, 320, 292, -60, 8, 0}, + { 0, 8, -56, 304, 304, -56, 8, 0}, + }, +//>1 + { + { 12, -40, 84, 400, 84, -40, 12, 0}, + { 12, -40, 72, 404, 96, -44, 12, 0}, + { 12, -36, 60, 404, 108, -48, 12, 0}, + { 8, -32, 48, 404, 120, -48, 12, 0}, + { 8, -32, 36, 404, 136, -52, 12, 0}, + { 8, -28, 28, 396, 148, -52, 12, 0}, + { 8, -24, 16, 392, 160, -52, 12, 0}, + { 8, -20, 8, 384, 176, -56, 12, 0}, + { 8, -20, 0, 384, 188, -56, 8, 0}, + { 8, -16, -8, 372, 204, -56, 8, 0}, + { 8, -12, -16, 364, 216, -56, 8, 0}, + { 4, -12, -20, 356, 232, -56, 8, 0}, + { 4, -8, -28, 348, 244, -56, 8, 0}, + { 4, -8, -32, 332, 264, -52, 4, 0}, + { 4, -4, -36, 324, 272, -52, 4, 0}, + { 4, 0, -40, 312, 280, -48, 0, 4}, + { 4, 0, -44, 296, 296, -44, 0, 4}, + }, +//==1 + { + { 0, 0, 0, 511, 0, 0, 0, 0 }, + { -1, 3, -12, 511, 14, -4, 1, 0 }, + { -2, 6, -23, 509, 28, -8, 2, 0 }, + { -2, 9, -33, 503, 44, -12, 3, 0 }, + { -3, 11, -41, 496, 61, -16, 4, 0 }, + { -3, 13, -48, 488, 79, -21, 5, -1 }, + { -3, 14, -54, 477, 98, -25, 7, -2 }, + { -4, 16, -59, 465, 118, -30, 8, -2 }, + { -4, 17, -63, 451, 138, -35, 9, -1 }, + { -4, 18, -66, 437, 158, -39, 10, -2 }, + { -4, 18, -68, 421, 180, -44, 11, -2 }, + { -4, 18, -69, 404, 201, -48, 13, -3 }, + { -4, 18, -70, 386, 222, -52, 14, -2 }, + { -4, 18, -70, 368, 244, -56, 15, -3 }, + { -4, 18, -69, 348, 265, -59, 16, -3 }, + { -4, 18, -67, 329, 286, -63, 16, -3 }, + { -3, 17, -65, 307, 307, -65, 17, -3 }, + }, +//>=0.833 + { + { -16, 0, 145, 254, 145, 0, -16, 0 }, + { -16, -2, 140, 253, 151, 3, -17, 0 }, + { -15, -5, 135, 253, 157, 5, -18, 0 }, + { -14, -7, 129, 252, 162, 8, -18, 0 }, + { -13, -9, 123, 252, 167, 11, -19, 0 }, + { -13, -11, 118, 250, 172, 15, -19, 0 }, + { -12, -12, 112, 250, 177, 18, -20, -1 }, + { -11, -14, 107, 247, 183, 21, -20, -1 }, + { -10, -15, 101, 245, 188, 25, -21, -1 }, + { -9, -16, 96, 243, 192, 29, -21, -2 }, + { -8, -18, 90, 242, 197, 33, -22, -2 }, + { -8, -19, 85, 239, 202, 37, -22, -2 }, + { -7, -19, 80, 236, 206, 41, -22, -3 }, + { -7, -20, 75, 233, 210, 46, -22, -3 }, + { -6, -21, 69, 230, 215, 50, -22, -3 }, + { -5, -21, 65, 226, 219, 55, -22, -5 }, + { -5, -21, 60, 222, 222, 60, -21, -5 }, + }, +//>=0.7 + { + { -16, 0, 145, 254, 145, 0, -16, 0 }, + { -16, -2, 140, 253, 151, 3, -17, 0 }, + { -15, -5, 135, 253, 157, 5, -18, 0 }, + { -14, -7, 129, 252, 162, 8, -18, 0 }, + { -13, -9, 123, 252, 167, 11, -19, 0 }, + { -13, -11, 118, 250, 172, 15, -19, 0 }, + { -12, -12, 112, 250, 177, 18, -20, -1 }, + { -11, -14, 107, 247, 183, 21, -20, -1 }, + { -10, -15, 101, 245, 188, 25, -21, -1 }, + { -9, -16, 96, 243, 192, 29, -21, -2 }, + { -8, -18, 90, 242, 197, 33, -22, -2 }, + { -8, -19, 85, 239, 202, 37, -22, -2 }, + { -7, -19, 80, 236, 206, 41, -22, -3 }, + { -7, -20, 75, 233, 210, 46, -22, -3 }, + { -6, -21, 69, 230, 215, 50, -22, -3 }, + { -5, -21, 65, 226, 219, 55, -22, -5 }, + { -5, -21, 60, 222, 222, 60, -21, -5 }, + }, +//>=0.5 + { + { -16, 0, 145, 254, 145, 0, -16, 0 }, + { -16, -2, 140, 253, 151, 3, -17, 0 }, + { -15, -5, 135, 253, 157, 5, -18, 0 }, + { -14, -7, 129, 252, 162, 8, -18, 0 }, + { -13, -9, 123, 252, 167, 11, -19, 0 }, + { -13, -11, 118, 250, 172, 15, -19, 0 }, + { -12, -12, 112, 250, 177, 18, -20, -1 }, + { -11, -14, 107, 247, 183, 21, -20, -1 }, + { -10, -15, 101, 245, 188, 25, -21, -1 }, + { -9, -16, 96, 243, 192, 29, -21, -2 }, + { -8, -18, 90, 242, 197, 33, -22, -2 }, + { -8, -19, 85, 239, 202, 37, -22, -2 }, + { -7, -19, 80, 236, 206, 41, -22, -3 }, + { -7, -20, 75, 233, 210, 46, -22, -3 }, + { -6, -21, 69, 230, 215, 50, -22, -3 }, + { -5, -21, 65, 226, 219, 55, -22, -5 }, + { -5, -21, 60, 222, 222, 60, -21, -5 }, + }, +//>=0.33 + { + { -18, 18, 144, 226, 144, 19, -17, -4 }, + { -17, 16, 139, 226, 148, 21, -17, -4 }, + { -17, 13, 135, 227, 153, 24, -18, -5 }, + { -17, 11, 131, 226, 157, 27, -18, -5 }, + { -17, 9, 126, 225, 161, 30, -17, -5 }, + { -16, 6, 122, 225, 165, 33, -17, -6 }, + { -16, 4, 118, 224, 169, 37, -17, -7 }, + { -16, 2, 113, 224, 173, 40, -17, -7 }, + { -15, 0, 109, 222, 177, 43, -17, -7 }, + { -15, -1, 104, 220, 181, 47, -16, -8 }, + { -14, -3, 100, 218, 185, 51, -16, -9 }, + { -14, -5, 96, 217, 188, 54, -15, -9 }, + { -14, -6, 91, 214, 192, 58, -14, -9 }, + { -13, -7, 87, 212, 195, 62, -14, -10 }, + { -13, -9, 83, 210, 198, 66, -13, -10 }, + { -12, -10, 79, 207, 201, 70, -12, -11 }, + { -12, -11, 74, 205, 205, 74, -11, -12 }, + }, +//>=0.25 + { + { 14, 66, 113, 133, 113, 66, 14, -7 }, + { 12, 65, 112, 133, 114, 68, 15, -7 }, + { 11, 63, 111, 132, 115, 70, 17, -7 }, + { 10, 62, 110, 132, 116, 71, 18, -7 }, + { 8, 60, 108, 132, 118, 73, 20, -7 }, + { 7, 58, 107, 132, 119, 75, 21, -7 }, + { 6, 56, 106, 132, 120, 76, 23, -7 }, + { 5, 55, 105, 131, 121, 78, 24, -7 }, + { 4, 53, 103, 131, 122, 80, 26, -7 }, + { 3, 51, 102, 131, 122, 81, 28, -6 }, + { 2, 50, 101, 130, 123, 83, 29, -6 }, + { 1, 48, 99, 131, 124, 84, 31, -6 }, + { 0, 46, 98, 129, 125, 86, 33, -5 }, + { -1, 45, 97, 128, 126, 88, 34, -5 }, + { -2, 43, 95, 130, 126, 89, 36, -5 }, + { -3, 41, 94, 128, 127, 91, 38, -4 }, + { -3, 39, 92, 128, 128, 92, 39, -3 }, + }, +//others + { + { 39, 69, 93, 102, 93, 69, 39, 8 }, + { 38, 68, 92, 102, 93, 70, 40, 9 }, + { 37, 67, 91, 102, 93, 71, 41, 10 }, + { 36, 66, 91, 101, 94, 71, 42, 11 }, + { 35, 65, 90, 102, 94, 72, 43, 11 }, + { 34, 64, 89, 102, 94, 73, 44, 12 }, + { 33, 63, 88, 101, 95, 74, 45, 13 }, + { 32, 62, 88, 100, 95, 75, 46, 14 }, + { 31, 62, 87, 100, 95, 75, 47, 15 }, + { 30, 61, 86, 99, 96, 76, 48, 16 }, + { 29, 60, 86, 98, 96, 77, 49, 17 }, + { 28, 59, 85, 98, 96, 78, 50, 18 }, + { 27, 58, 84, 99, 97, 78, 50, 19 }, + { 26, 57, 83, 99, 97, 79, 51, 20 }, + { 25, 56, 83, 98, 97, 80, 52, 21 }, + { 24, 55, 82, 97, 98, 81, 53, 22 }, + { 23, 54, 81, 98, 98, 81, 54, 23 }, + } +}; + +static const RK_S16 g_zme_tap6_coeff[11][17][8] = { +//>=2.667 + { + { -12, 20, 492, 20, -12, 4, 0, 0}, + { -8, 8, 488, 36, -16, 4, 0, 0}, + { -4, -4, 488, 48, -20, 4, 0, 0}, + { 0, -16, 484, 64, -24, 4, 0, 0}, + { 0, -24, 476, 80, -28, 8, 0, 0}, + { 4, -32, 464, 100, -32, 8, 0, 0}, + { 8, -40, 456, 116, -36, 8, 0, 0}, + { 8, -48, 448, 136, -40, 8, 0, 0}, + { 12, -52, 436, 152, -44, 8, 0, 0}, + { 12, -60, 424, 172, -48, 12, 0, 0}, + { 12, -64, 412, 192, -52, 12, 0, 0}, + { 16, -64, 392, 212, -56, 12, 0, 0}, + { 16, -68, 380, 232, -60, 12, 0, 0}, + { 16, -68, 360, 248, -60, 16, 0, 0}, + { 16, -68, 344, 268, -64, 16, 0, 0}, + { 16, -68, 328, 288, -68, 16, 0, 0}, + { 16, -68, 308, 308, -68, 16, 0, 0}, + }, +//>=2 + { + { -20, 40, 468, 40, -20, 4, 0, 0}, + { -16, 28, 464, 56, -24, 4, 0, 0}, + { -16, 16, 464, 68, -28, 8, 0, 0}, + { -12, 4, 460, 84, -32, 8, 0, 0}, + { -8, -4, 452, 100, -36, 8, 0, 0}, + { -4, -12, 444, 116, -40, 8, 0, 0}, + { -4, -24, 440, 136, -44, 8, 0, 0}, + { 0, -32, 432, 152, -48, 8, 0, 0}, + { 0, -36, 416, 168, -48, 12, 0, 0}, + { 4, -44, 408, 184, -52, 12, 0, 0}, + { 4, -48, 400, 200, -56, 12, 0, 0}, + { 8, -52, 380, 220, -56, 12, 0, 0}, + { 8, -56, 372, 236, -60, 12, 0, 0}, + { 8, -60, 356, 256, -60, 12, 0, 0}, + { 12, -60, 340, 268, -60, 12, 0, 0}, + { 12, -60, 324, 288, -64, 12, 0, 0}, + { 12, -64, 308, 308, -64, 12, 0, 0}, + }, +//>=1.5 + { + { -28, 60, 440, 60, -28, 8, 0, 0}, + { -28, 48, 440, 76, -32, 8, 0, 0}, + { -24, 36, 440, 88, -36, 8, 0, 0}, + { -20, 28, 432, 104, -40, 8, 0, 0}, + { -16, 16, 428, 116, -40, 8, 0, 0}, + { -16, 4, 428, 132, -44, 8, 0, 0}, + { -12, -4, 420, 148, -48, 8, 0, 0}, + { -8, -12, 408, 164, -48, 8, 0, 0}, + { -8, -20, 404, 180, -52, 8, 0, 0}, + { -4, -24, 388, 196, -52, 8, 0, 0}, + { -4, -32, 384, 212, -56, 8, 0, 0}, + { 0, -36, 372, 224, -56, 8, 0, 0}, + { 0, -40, 360, 240, -56, 8, 0, 0}, + { 4, -44, 344, 256, -56, 8, 0, 0}, + { 4, -48, 332, 272, -56, 8, 0, 0}, + { 4, -52, 316, 292, -56, 8, 0, 0}, + { 8, -52, 300, 300, -52, 8, 0, 0}, + }, +//>1 + { + { -36, 80, 420, 80, -36, 4, 0, 0}, + { -32, 68, 412, 92, -36, 8, 0, 0}, + { -28, 56, 412, 104, -40, 8, 0, 0}, + { -28, 44, 412, 116, -40, 8, 0, 0}, + { -24, 36, 404, 132, -44, 8, 0, 0}, + { -24, 24, 404, 144, -44, 8, 0, 0}, + { -20, 16, 396, 160, -48, 8, 0, 0}, + { -16, 8, 388, 172, -48, 8, 0, 0}, + { -16, 0, 380, 188, -48, 8, 0, 0}, + { -12, -8, 376, 200, -48, 4, 0, 0}, + { -12, -12, 364, 216, -48, 4, 0, 0}, + { -8, -20, 356, 228, -48, 4, 0, 0}, + { -8, -24, 344, 244, -48, 4, 0, 0}, + { -4, -32, 332, 260, -48, 4, 0, 0}, + { -4, -36, 320, 272, -44, 4, 0, 0}, + { 0, -40, 308, 288, -44, 0, 0, 0}, + { 0, -40, 296, 296, -40, 0, 0, 0}, + }, +//==1 + { + { 0, 0, 511, 0, 0, 0, 0, 0 }, + { 3, -12, 511, 13, -3, 0, 0, 0 }, + { 6, -22, 507, 28, -7, 0, 0, 0 }, + { 8, -32, 502, 44, -11, 1, 0, 0 }, + { 10, -40, 495, 61, -15, 1, 0, 0 }, + { 11, -47, 486, 79, -19, 2, 0, 0 }, + { 12, -53, 476, 98, -24, 3, 0, 0 }, + { 13, -58, 464, 117, -28, 4, 0, 0 }, + { 14, -62, 451, 137, -33, 5, 0, 0 }, + { 15, -65, 437, 157, -38, 6, 0, 0 }, + { 15, -67, 420, 179, -42, 7, 0, 0 }, + { 15, -68, 404, 200, -46, 7, 0, 0 }, + { 14, -68, 386, 221, -50, 9, 0, 0 }, + { 14, -68, 367, 243, -54, 10, 0, 0 }, + { 14, -67, 348, 264, -58, 11, 0, 0 }, + { 13, -66, 328, 286, -61, 12, 0, 0 }, + { 13, -63, 306, 306, -63, 13, 0, 0 }, + }, +//>=0.833 + { + { -31, 104, 362, 104, -31, 4, 0, 0 }, + { -30, 94, 362, 114, -32, 4, 0, 0 }, + { -29, 84, 361, 125, -32, 3, 0, 0 }, + { -28, 75, 359, 136, -33, 3, 0, 0 }, + { -27, 66, 356, 147, -33, 3, 0, 0 }, + { -25, 57, 353, 158, -33, 2, 0, 0 }, + { -24, 49, 349, 169, -33, 2, 0, 0 }, + { -22, 41, 344, 180, -32, 1, 0, 0 }, + { -20, 33, 339, 191, -31, 0, 0, 0 }, + { -19, 26, 333, 203, -30, -1, 0, 0 }, + { -17, 19, 327, 214, -29, -2, 0, 0 }, + { -16, 13, 320, 225, -27, -3, 0, 0 }, + { -14, 7, 312, 236, -25, -4, 0, 0 }, + { -13, 1, 305, 246, -22, -5, 0, 0 }, + { -11, -4, 295, 257, -19, -6, 0, 0 }, + { -10, -8, 286, 267, -16, -7, 0, 0 }, + { -9, -12, 277, 277, -12, -9, 0, 0 }, + }, +//>=0.7 + { + { -31, 104, 362, 104, -31, 4, 0, 0 }, + { -30, 94, 362, 114, -32, 4, 0, 0 }, + { -29, 84, 361, 125, -32, 3, 0, 0 }, + { -28, 75, 359, 136, -33, 3, 0, 0 }, + { -27, 66, 356, 147, -33, 3, 0, 0 }, + { -25, 57, 353, 158, -33, 2, 0, 0 }, + { -24, 49, 349, 169, -33, 2, 0, 0 }, + { -22, 41, 344, 180, -32, 1, 0, 0 }, + { -20, 33, 339, 191, -31, 0, 0, 0 }, + { -19, 26, 333, 203, -30, -1, 0, 0 }, + { -17, 19, 327, 214, -29, -2, 0, 0 }, + { -16, 13, 320, 225, -27, -3, 0, 0 }, + { -14, 7, 312, 236, -25, -4, 0, 0 }, + { -13, 1, 305, 246, -22, -5, 0, 0 }, + { -11, -4, 295, 257, -19, -6, 0, 0 }, + { -10, -8, 286, 267, -16, -7, 0, 0 }, + { -9, -12, 277, 277, -12, -9, 0, 0 }, + }, +//>=0.5 + { + { -20, 130, 297, 130, -20, -5, 0, 0 }, + { -21, 122, 298, 138, -19, -6, 0, 0 }, + { -22, 115, 297, 146, -17, -7, 0, 0 }, + { -22, 108, 296, 153, -16, -7, 0, 0 }, + { -23, 101, 295, 161, -14, -8, 0, 0 }, + { -23, 93, 294, 169, -12, -9, 0, 0 }, + { -24, 87, 292, 177, -10, -10, 0, 0 }, + { -24, 80, 289, 185, -7, -11, 0, 0 }, + { -24, 73, 286, 193, -4, -12, 0, 0 }, + { -23, 66, 283, 200, -1, -13, 0, 0 }, + { -23, 60, 279, 208, 2, -14, 0, 0 }, + { -23, 54, 276, 215, 5, -15, 0, 0 }, + { -22, 48, 271, 222, 9, -16, 0, 0 }, + { -21, 42, 266, 229, 13, -17, 0, 0 }, + { -21, 37, 261, 236, 17, -18, 0, 0 }, + { -21, 32, 255, 242, 22, -18, 0, 0 }, + { -20, 27, 249, 249, 27, -20, 0, 0 }, + }, +//>=0.33 + { + { 16, 136, 217, 136, 16, -9, 0, 0 }, + { 13, 132, 217, 141, 18, -9, 0, 0 }, + { 11, 128, 217, 145, 21, -10, 0, 0 }, + { 9, 124, 216, 149, 24, -10, 0, 0 }, + { 7, 119, 216, 153, 27, -10, 0, 0 }, + { 5, 115, 216, 157, 30, -11, 0, 0 }, + { 3, 111, 215, 161, 33, -11, 0, 0 }, + { 1, 107, 214, 165, 36, -11, 0, 0 }, + { 0, 102, 213, 169, 39, -11, 0, 0 }, + { -2, 98, 211, 173, 43, -11, 0, 0 }, + { -3, 94, 209, 177, 46, -11, 0, 0 }, + { -4, 90, 207, 180, 50, -11, 0, 0 }, + { -5, 85, 206, 184, 53, -11, 0, 0 }, + { -6, 81, 203, 187, 57, -10, 0, 0 }, + { -7, 77, 201, 190, 61, -10, 0, 0 }, + { -8, 73, 198, 193, 65, -9, 0, 0 }, + { -9, 69, 196, 196, 69, -9, 0, 0 }, + }, +//>=0.25 + { + { 66, 115, 138, 115, 66, 12, 0, 0 }, + { 64, 114, 136, 116, 68, 14, 0, 0 }, + { 63, 113, 134, 117, 70, 15, 0, 0 }, + { 61, 111, 135, 118, 71, 16, 0, 0 }, + { 59, 110, 133, 119, 73, 18, 0, 0 }, + { 57, 108, 134, 120, 74, 19, 0, 0 }, + { 55, 107, 133, 121, 76, 20, 0, 0 }, + { 53, 105, 133, 121, 78, 22, 0, 0 }, + { 51, 104, 133, 122, 79, 23, 0, 0 }, + { 49, 102, 132, 123, 81, 25, 0, 0 }, + { 47, 101, 132, 124, 82, 26, 0, 0 }, + { 45, 99, 131, 125, 84, 28, 0, 0 }, + { 44, 98, 130, 125, 85, 30, 0, 0 }, + { 42, 96, 130, 126, 87, 31, 0, 0 }, + { 40, 95, 128, 127, 89, 33, 0, 0 }, + { 38, 93, 129, 127, 90, 35, 0, 0 }, + { 36, 92, 128, 128, 92, 36, 0, 0 }, + }, +//others + { + { 80, 105, 116, 105, 80, 26, 0, 0 }, + { 79, 104, 115, 105, 81, 28, 0, 0 }, + { 77, 103, 116, 106, 81, 29, 0, 0 }, + { 76, 102, 115, 106, 82, 31, 0, 0 }, + { 74, 101, 115, 106, 83, 33, 0, 0 }, + { 73, 100, 114, 106, 84, 35, 0, 0 }, + { 71, 99, 114, 107, 84, 37, 0, 0 }, + { 70, 98, 113, 107, 85, 39, 0, 0 }, + { 68, 98, 113, 107, 86, 40, 0, 0 }, + { 67, 97, 112, 108, 86, 42, 0, 0 }, + { 65, 96, 112, 108, 87, 44, 0, 0 }, + { 63, 95, 112, 108, 88, 46, 0, 0 }, + { 62, 94, 112, 108, 88, 48, 0, 0 }, + { 60, 93, 111, 109, 89, 50, 0, 0 }, + { 58, 93, 111, 109, 90, 51, 0, 0 }, + { 57, 92, 110, 110, 90, 53, 0, 0 }, + { 55, 91, 110, 110, 91, 55, 0, 0 }, + } +}; + +static MPP_RET vdpp_params_to_reg(Vdpp1Params* src_params, Vdpp1ApiCtx *ctx) +{ + Vdpp1Regs *dst_reg = &ctx->reg; + DmsrParams *dmsr_params = &src_params->dmsr_params; + ZmeParams *zme_params = &src_params->zme_params; + + memset(dst_reg, 0, sizeof(*dst_reg)); + + /* 1. set reg::common */ + dst_reg->common.reg0.sw_vdpp_frm_en = 1; + + /* 0x0004(reg1), TODO: add debug function */ + dst_reg->common.reg1.sw_vdpp_src_fmt = VDPP_FMT_YUV420; // vep only support yuv420 + dst_reg->common.reg1.sw_vdpp_src_yuv_swap = src_params->src_yuv_swap; + dst_reg->common.reg1.sw_vdpp_dst_fmt = src_params->dst_fmt; + dst_reg->common.reg1.sw_vdpp_dst_yuv_swap = src_params->dst_yuv_swap; + dst_reg->common.reg1.sw_vdpp_dbmsr_en = dmsr_params->dmsr_enable; + + /* 0x0008(reg2) */ + dst_reg->common.reg2.sw_vdpp_working_mode = VDPP_WORK_MODE_VEP; + + /* 0x000C ~ 0x001C(reg3 ~ reg7), skip */ + dst_reg->common.reg4.sw_vdpp_clk_on = 1; + dst_reg->common.reg4.sw_md_clk_on = 1; + dst_reg->common.reg4.sw_dect_clk_on = 1; + dst_reg->common.reg4.sw_me_clk_on = 1; + dst_reg->common.reg4.sw_mc_clk_on = 1; + dst_reg->common.reg4.sw_eedi_clk_on = 1; + dst_reg->common.reg4.sw_ble_clk_on = 1; + dst_reg->common.reg4.sw_out_clk_on = 1; + dst_reg->common.reg4.sw_ctrl_clk_on = 1; + dst_reg->common.reg4.sw_ram_clk_on = 1; + dst_reg->common.reg4.sw_dma_clk_on = 1; + dst_reg->common.reg4.sw_reg_clk_on = 1; + + /* 0x0020(reg8) */ + dst_reg->common.reg8.sw_vdpp_frm_done_en = 1; + dst_reg->common.reg8.sw_vdpp_osd_max_en = 1; + dst_reg->common.reg8.sw_vdpp_bus_error_en = 1; + dst_reg->common.reg8.sw_vdpp_timeout_int_en = 1; + dst_reg->common.reg8.sw_vdpp_config_error_en = 1; + /* 0x0024 ~ 0x002C(reg9 ~ reg11), skip */ + { + RK_U32 src_right_redundant = (16 - (src_params->src_width & 0xF)) & 0xF; + RK_U32 src_down_redundant = (8 - (src_params->src_height & 0x7)) & 0x7; + RK_U32 dst_right_redundant = (16 - (src_params->dst_width & 0xF)) & 0xF; + /* 0x0030(reg12) */ + dst_reg->common.reg12.sw_vdpp_src_vir_y_stride = (src_params->src_width + src_right_redundant + 3) / 4; + + /* 0x0034(reg13) */ + dst_reg->common.reg13.sw_vdpp_dst_vir_y_stride = (src_params->dst_width + dst_right_redundant + 3) / 4; + + /* 0x0038(reg14) */ + dst_reg->common.reg14.sw_vdpp_src_pic_width = src_params->src_width + src_right_redundant - 1; + dst_reg->common.reg14.sw_vdpp_src_right_redundant = src_right_redundant; + dst_reg->common.reg14.sw_vdpp_src_pic_height = src_params->src_height + src_down_redundant - 1; + dst_reg->common.reg14.sw_vdpp_src_down_redundant = src_down_redundant; + + /* 0x003C(reg15) */ + dst_reg->common.reg15.sw_vdpp_dst_pic_width = src_params->dst_width + dst_right_redundant - 1; + dst_reg->common.reg15.sw_vdpp_dst_right_redundant = dst_right_redundant; + dst_reg->common.reg15.sw_vdpp_dst_pic_height = src_params->dst_height - 1; + } + /* 0x0040 ~ 0x005C(reg16 ~ reg23), skip */ + dst_reg->common.reg20.sw_vdpp_timeout_en = 1; + dst_reg->common.reg20.sw_vdpp_timeout_cnt = 0x8FFFFFF; + + /* 0x0060(reg24) */ + dst_reg->common.reg24.sw_vdpp_src_addr_y = src_params->src.y; + + /* 0x0064(reg25) */ + dst_reg->common.reg25.sw_vdpp_src_addr_uv = src_params->src.cbcr; + + /* 0x0068(reg26) */ + dst_reg->common.reg26.sw_vdpp_dst_addr_y = src_params->dst.y; + + /* 0x006C(reg27) */ + dst_reg->common.reg27.sw_vdpp_dst_addr_uv = src_params->dst.cbcr; + + set_dmsr_to_vdpp_reg(dmsr_params, &dst_reg->dmsr); + + zme_params->src_width = src_params->src_width; + zme_params->src_height = src_params->src_height; + zme_params->dst_width = src_params->dst_width; + zme_params->dst_height = src_params->dst_height; + zme_params->dst_fmt = src_params->dst_fmt; + set_zme_to_vdpp_reg(zme_params, &dst_reg->zme); + + return MPP_OK; +} + +void vdpp_set_default_dmsr_param(DmsrParams* param) +{ + param->dmsr_enable = 1; + param->dmsr_str_pri_y = 10; + param->dmsr_str_sec_y = 4; + param->dmsr_dumping_y = 6; + param->dmsr_wgt_pri_gain_even_1 = 12; + param->dmsr_wgt_pri_gain_even_2 = 12; + param->dmsr_wgt_pri_gain_odd_1 = 8; + param->dmsr_wgt_pri_gain_odd_2 = 16; + param->dmsr_wgt_sec_gain = 5; + param->dmsr_blk_flat_th = 20; + param->dmsr_contrast_to_conf_map_x0 = 1680; + param->dmsr_contrast_to_conf_map_x1 = 6720; + param->dmsr_contrast_to_conf_map_y0 = 0; + param->dmsr_contrast_to_conf_map_y1 = 65535; + param->dmsr_diff_core_th0 = 1; + param->dmsr_diff_core_th1 = 5; + param->dmsr_diff_core_wgt0 = 16; + param->dmsr_diff_core_wgt1 = 16; + param->dmsr_diff_core_wgt2 = 16; + param->dmsr_edge_th_low_arr[0] = 30; + param->dmsr_edge_th_low_arr[1] = 10; + param->dmsr_edge_th_low_arr[2] = 0; + param->dmsr_edge_th_low_arr[3] = 0; + param->dmsr_edge_th_low_arr[4] = 0; + param->dmsr_edge_th_low_arr[5] = 0; + param->dmsr_edge_th_low_arr[6] = 0; + param->dmsr_edge_th_high_arr[0] = 60; + param->dmsr_edge_th_high_arr[1] = 40; + param->dmsr_edge_th_high_arr[2] = 20; + param->dmsr_edge_th_high_arr[3] = 10; + param->dmsr_edge_th_high_arr[4] = 10; + param->dmsr_edge_th_high_arr[5] = 10; + param->dmsr_edge_th_high_arr[6] = 10; +} + +void vdpp_set_default_zme_param(ZmeParams *param) +{ + param->zme_bypass_en = 1; + param->zme_dering_enable = 1; + param->zme_dering_sen_0 = 16; + param->zme_dering_sen_1 = 4; + param->zme_dering_blend_alpha = 16; + param->zme_dering_blend_beta = 13; + param->zme_tap8_coeff = g_zme_tap8_coeff; + param->zme_tap6_coeff = g_zme_tap6_coeff; +} + +static MPP_RET vdpp_set_default_param(Vdpp1Params *param) +{ + /* src_fmt only NV12 supported */ + param->src_yuv_swap = VDPP_YUV_SWAP_SP_UV; + param->dst_fmt = VDPP_FMT_YUV444; + param->dst_yuv_swap = VDPP_YUV_SWAP_SP_UV; + param->src_width = 1920; + param->src_height = 1080; + param->dst_width = 1920; + param->dst_height = 1080; + + vdpp_set_default_dmsr_param(¶m->dmsr_params); + vdpp_set_default_zme_param(¶m->zme_params); + + return MPP_OK; +} + +void set_dmsr_to_vdpp_reg(const DmsrParams *dmsr_param, RegDmsr *dmsr) +{ + /* 0x0080(reg0) */ + dmsr->reg0.sw_dmsr_edge_low_thre_0 = dmsr_param->dmsr_edge_th_low_arr[0]; + dmsr->reg0.sw_dmsr_edge_high_thre_0 = dmsr_param->dmsr_edge_th_high_arr[0]; + + /* 0x0084(reg1) */ + dmsr->reg1.sw_dmsr_edge_low_thre_1 = dmsr_param->dmsr_edge_th_low_arr[1]; + dmsr->reg1.sw_dmsr_edge_high_thre_1 = dmsr_param->dmsr_edge_th_high_arr[1]; + + /* 0x0088(reg2) */ + dmsr->reg2.sw_dmsr_edge_low_thre_2 = dmsr_param->dmsr_edge_th_low_arr[2]; + dmsr->reg2.sw_dmsr_edge_high_thre_2 = dmsr_param->dmsr_edge_th_high_arr[2]; + + /* 0x008C(reg3) */ + dmsr->reg3.sw_dmsr_edge_low_thre_3 = dmsr_param->dmsr_edge_th_low_arr[3]; + dmsr->reg3.sw_dmsr_edge_high_thre_3 = dmsr_param->dmsr_edge_th_high_arr[3]; + + /* 0x0090(reg4) */ + dmsr->reg4.sw_dmsr_edge_low_thre_4 = dmsr_param->dmsr_edge_th_low_arr[4]; + dmsr->reg4.sw_dmsr_edge_high_thre_4 = dmsr_param->dmsr_edge_th_high_arr[4]; + + /* 0x0094(reg5) */ + dmsr->reg5.sw_dmsr_edge_low_thre_5 = dmsr_param->dmsr_edge_th_low_arr[5]; + dmsr->reg5.sw_dmsr_edge_high_thre_5 = dmsr_param->dmsr_edge_th_high_arr[5]; + + /* 0x0098(reg6) */ + dmsr->reg6.sw_dmsr_edge_low_thre_6 = dmsr_param->dmsr_edge_th_low_arr[6]; + dmsr->reg6.sw_dmsr_edge_high_thre_6 = dmsr_param->dmsr_edge_th_high_arr[6]; + { + RK_U16 adj_mapping_k[7]; + RK_U16 tmp_diff; + RK_U16 i; + RK_U16 contrast2conf_mapping_k; + RK_U32 tmp_diff_y, tmp_diff_x; + + for (i = 0; i < 7; i++) { + tmp_diff = dmsr_param->dmsr_edge_th_high_arr[i] - dmsr_param->dmsr_edge_th_low_arr[i]; + adj_mapping_k[i] = (65535 / MPP_MAX(1, tmp_diff)); + } + tmp_diff_y = dmsr_param->dmsr_contrast_to_conf_map_y1 - dmsr_param->dmsr_contrast_to_conf_map_y0; + tmp_diff_x = MPP_MAX(dmsr_param->dmsr_contrast_to_conf_map_x1 - dmsr_param->dmsr_contrast_to_conf_map_x0, 1); + + contrast2conf_mapping_k = mpp_clip(256 * tmp_diff_y / tmp_diff_x, 0, 65535); + /* 0x009C(reg7) */ + dmsr->reg7.sw_dmsr_edge_k_0 = adj_mapping_k[0]; + dmsr->reg7.sw_dmsr_edge_k_1 = adj_mapping_k[1]; + + /* 0x00A0(reg8) */ + dmsr->reg8.sw_dmsr_edge_k_2 = adj_mapping_k[2]; + dmsr->reg8.sw_dmsr_edge_k_3 = adj_mapping_k[3]; + + /* 0x00A4(reg9) */ + dmsr->reg9.sw_dmsr_edge_k_4 = adj_mapping_k[4]; + dmsr->reg9.sw_dmsr_edge_k_5 = adj_mapping_k[5]; + + /* 0x00A8(reg10) */ + dmsr->reg10.sw_dmsr_edge_k_6 = adj_mapping_k[6]; + dmsr->reg10.sw_dmsr_dir_contrast_conf_f = contrast2conf_mapping_k; + } + /* 0x00AC(reg11) */ + dmsr->reg11.sw_dmsr_dir_contrast_conf_x0 = dmsr_param->dmsr_contrast_to_conf_map_x0; + dmsr->reg11.sw_dmsr_dir_contrast_conf_x1 = dmsr_param->dmsr_contrast_to_conf_map_x1; + + /* 0x00B0(reg12) */ + dmsr->reg12.sw_dmsr_dir_contrast_conf_y0 = dmsr_param->dmsr_contrast_to_conf_map_y0; + dmsr->reg12.sw_dmsr_dir_contrast_conf_y1 = dmsr_param->dmsr_contrast_to_conf_map_y1; + + /* 0x00B4(reg13) */ + dmsr->reg13.sw_dmsr_var_th = dmsr_param->dmsr_blk_flat_th; + + /* 0x00B8(reg14) */ + dmsr->reg14.sw_dmsr_diff_coring_th0 = dmsr_param->dmsr_diff_core_th0; + dmsr->reg14.sw_dmsr_diff_coring_th1 = dmsr_param->dmsr_diff_core_th1; + + /* 0x00BC(reg15) */ + dmsr->reg15.sw_dmsr_diff_coring_wgt0 = dmsr_param->dmsr_diff_core_wgt0; + dmsr->reg15.sw_dmsr_diff_coring_wgt1 = dmsr_param->dmsr_diff_core_wgt1; + dmsr->reg15.sw_dmsr_diff_coring_wgt2 = dmsr_param->dmsr_diff_core_wgt2; + { + RK_U16 diff_coring_y0 = dmsr_param->dmsr_diff_core_th0 * dmsr_param->dmsr_diff_core_wgt0; + RK_U16 diff_coring_y1 = (dmsr_param->dmsr_diff_core_th1 - dmsr_param->dmsr_diff_core_th0) * + dmsr_param->dmsr_diff_core_wgt1 + diff_coring_y0; + + /* 0x00C0(reg16) */ + dmsr->reg16.sw_dmsr_diff_coring_y0 = diff_coring_y0; + dmsr->reg16.sw_dmsr_diff_coring_y1 = diff_coring_y1; + } + /* 0x00C4(reg17) */ + dmsr->reg17.sw_dmsr_wgt_pri_gain_1_odd = dmsr_param->dmsr_wgt_pri_gain_odd_1; + dmsr->reg17.sw_dmsr_wgt_pri_gain_1_even = dmsr_param->dmsr_wgt_pri_gain_even_1; + dmsr->reg17.sw_dmsr_wgt_pri_gain_2_odd = dmsr_param->dmsr_wgt_pri_gain_odd_2; + dmsr->reg17.sw_dmsr_wgt_pri_gain_2_even = dmsr_param->dmsr_wgt_pri_gain_even_2; + + /* 0x00C8(reg18) */ + dmsr->reg18.sw_dmsr_wgt_sec_gain_1 = dmsr_param->dmsr_wgt_sec_gain; + dmsr->reg18.sw_dmsr_wgt_sec_gain_2 = dmsr_param->dmsr_wgt_sec_gain * 2; + + /* 0x00CC(reg19) */ + dmsr->reg19.sw_dmsr_strength_pri = dmsr_param->dmsr_str_pri_y; + dmsr->reg19.sw_dmsr_strength_sec = dmsr_param->dmsr_str_sec_y; + dmsr->reg19.sw_dmsr_dump = dmsr_param->dmsr_dumping_y; +} + +void calc_scale_factor(const ZmeParams *zme_params, VdppZmeScaleInfo *scale_info, RK_U8 bypass_en) +{ + RK_U16 act_width = scale_info->act_width; + RK_U16 dsp_width = scale_info->dsp_width; + + RK_U16 act_height = scale_info->act_height; + RK_U16 dsp_height = scale_info->dsp_height; + + RK_U8 xsd_en = 0; + RK_U8 xsu_en = 0; + RK_U8 xscl_mode = scale_info->xscl_mode; + RK_U16 xscl_factor; + RK_U8 xscl_offset = 0; // for center alignment + + RK_U8 ysd_en = 0; + RK_U8 ysu_en = 0; + RK_U8 yscl_mode = scale_info->yscl_mode; + RK_U16 yscl_factor; + RK_U8 yscl_offset = 0; // for center alignment + + RK_U8 xavg_en = 0; + RK_U8 xgt_en = 0; + RK_U8 xgt_mode = 0; + + RK_U8 yavg_en = 0; + RK_U8 ygt_en = 0; + RK_U8 ygt_mode = 0; + + RK_U32 f_xscl_factor_t; + RK_U32 f_yscl_factor_t; + RK_U32 f_xscl_factor_t1; + RK_U32 f_yscl_factor_t1; + + if (act_width >= dsp_width * 14) { + act_width = act_width / 4; + xgt_en = 1; + xgt_mode = 3; + } else if (act_width >= dsp_width * 7) { + act_width = act_width / 2; + xgt_en = 1; + xgt_mode = 1; + } + + if (act_width > dsp_width) { + xsd_en = 1; + xsu_en = 0; + xscl_factor = GET_SCALE_FACTOR_DN(act_width, dsp_width); + } else if (act_width < dsp_width) { + xsd_en = 0; + xsu_en = 1; + xscl_factor = GET_SCALE_FACTOR_UP(act_width, dsp_width); + } else { + xsd_en = 0; + xsu_en = 0; + xscl_factor = 1 << 12; + } + + if (yscl_mode <= SCL_BIL) { + if (act_height > dsp_height * 4) { + ygt_en = 1; + ygt_mode = 1; + act_height = act_height / 4; + } else if (act_height > dsp_height * 2) { + ygt_en = 1; + ygt_mode = 0; + act_height = act_height / 2; + } else { + ygt_en = 0; + ygt_mode = 0; + } + } + + if (yscl_mode == SCL_MPH) { + if (act_height >= dsp_height * 6) { + ygt_en = 1; + ygt_mode = 3; + } + } + + if (act_height > dsp_height) { + ysd_en = 1; + ysu_en = 0; + yscl_factor = GET_SCALE_FACTOR_DN(act_height, dsp_height); + } else if (act_height < dsp_height) { + ysd_en = 0; + ysu_en = 1; + yscl_factor = GET_SCALE_FACTOR_UP(act_height, dsp_height); + } else { + ysd_en = 0; + ysu_en = 0; + yscl_factor = 1 << 12; + } + + if (xsu_en == 1) { + f_xscl_factor_t = (1 << 16) * act_width / dsp_width; + f_xscl_factor_t1 = 1000 * (1 << 16) / f_xscl_factor_t; + } else { + f_xscl_factor_t = (1 << 12) * act_width / dsp_width; + f_xscl_factor_t1 = 1000 * (1 << 12) / f_xscl_factor_t; + } + + if (ysu_en == 1) { + f_yscl_factor_t = (1 << 16) * act_height / dsp_height; + f_yscl_factor_t1 = 1000 * (1 << 16) / f_yscl_factor_t; + } else { + f_yscl_factor_t = (1 << 12) * act_height / dsp_height; + f_yscl_factor_t1 = 1000 * (1 << 12) / f_yscl_factor_t; + } + + if (f_xscl_factor_t1 >= vdpp_scale_threshold[0]) { // >= 2.667 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[0]; + scale_info->xscl_coe_idx = 0; + } else if (f_xscl_factor_t1 >= vdpp_scale_threshold[1]) { // >= 2.000 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[1]; + scale_info->xscl_coe_idx = 1; + } else if (f_xscl_factor_t1 >= vdpp_scale_threshold[2]) { // >= 1.500 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[2]; + scale_info->xscl_coe_idx = 2; + } else if (f_xscl_factor_t1 > vdpp_scale_threshold[3]) { // > 1.000 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[3]; + scale_info->xscl_coe_idx = 3; + } else if (f_xscl_factor_t1 == vdpp_scale_threshold[3]) { // = 1.000 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[4]; + scale_info->xscl_coe_idx = 10; // should be 10, not 4 !! + } else if (f_xscl_factor_t1 >= vdpp_scale_threshold[4]) { // >= 0.833 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[5]; + scale_info->xscl_coe_idx = 4; // continue indexing from 4 + } else if (f_xscl_factor_t1 >= vdpp_scale_threshold[5]) { // >= 0.700 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[6]; + scale_info->xscl_coe_idx = 5; + } else if (f_xscl_factor_t1 >= vdpp_scale_threshold[6]) { // >= 0.500 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[7]; + scale_info->xscl_coe_idx = 6; + } else if (f_xscl_factor_t1 >= vdpp_scale_threshold[7]) { // >= 0.330 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[8]; + scale_info->xscl_coe_idx = 7; + } else if (f_xscl_factor_t1 >= vdpp_scale_threshold[8]) { // >= 0.250 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[9]; + scale_info->xscl_coe_idx = 8; + } else { // < 0.250 + scale_info->xscl_zme_coe = zme_params->zme_tap8_coeff[10]; + scale_info->xscl_coe_idx = 9; + } + + if (f_yscl_factor_t1 >= vdpp_scale_threshold[0]) { // >= 2.667 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[0]; + scale_info->yscl_coe_idx = 0; + } else if (f_yscl_factor_t1 >= vdpp_scale_threshold[1]) { // >= 2.000 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[1]; + scale_info->yscl_coe_idx = 1; + } else if (f_yscl_factor_t1 >= vdpp_scale_threshold[2]) { // >= 1.500 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[2]; + scale_info->yscl_coe_idx = 2; + } else if (f_yscl_factor_t1 > vdpp_scale_threshold[3]) { // > 1.000 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[3]; + scale_info->yscl_coe_idx = 3; + } else if (f_yscl_factor_t1 == vdpp_scale_threshold[3]) { // = 1.000 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[4]; + scale_info->yscl_coe_idx = 10; // should be 10, not 4 !! + } else if (f_yscl_factor_t1 >= vdpp_scale_threshold[4]) { // >= 0.833 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[5]; + scale_info->yscl_coe_idx = 4; // continue indexing from 4 + } else if (f_yscl_factor_t1 >= vdpp_scale_threshold[5]) { // >= 0.700 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[6]; + scale_info->yscl_coe_idx = 5; + } else if (f_yscl_factor_t1 >= vdpp_scale_threshold[6]) { // >= 0.500 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[7]; + scale_info->yscl_coe_idx = 6; + } else if (f_yscl_factor_t1 >= vdpp_scale_threshold[7]) { // >= 0.330 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[8]; + scale_info->yscl_coe_idx = 7; + } else if (f_yscl_factor_t1 >= vdpp_scale_threshold[8]) { // >= 0.250 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[9]; + scale_info->yscl_coe_idx = 8; + } else { // < 0.250 + scale_info->yscl_zme_coe = zme_params->zme_tap6_coeff[10]; + scale_info->yscl_coe_idx = 9; + } + + scale_info->xsd_en = xsd_en; + scale_info->xsu_en = xsu_en; + scale_info->xscl_mode = xscl_mode; + scale_info->xscl_factor = xscl_factor; + scale_info->xscl_offset = xscl_offset; + + scale_info->ysd_en = ysd_en; + scale_info->ysu_en = ysu_en; + scale_info->yscl_mode = yscl_mode; + scale_info->yscl_factor = yscl_factor; + scale_info->yscl_offset = yscl_offset; + + scale_info->xavg_en = xavg_en; + scale_info->xgt_en = xgt_en; + scale_info->xgt_mode = xgt_mode; + + scale_info->yavg_en = yavg_en; + scale_info->ygt_en = ygt_en; + scale_info->ygt_mode = ygt_mode; + + if (bypass_en) { + scale_info->xsd_bypass = !xsd_en; + scale_info->xsu_bypass = !xsu_en; + scale_info->ys_bypass = !(ysd_en || ysu_en); + } else { + scale_info->xsd_bypass = 0; + scale_info->xsu_bypass = 0; + scale_info->ys_bypass = 0; + } +} + +void set_zme_to_vdpp_reg(const ZmeParams *zme_params, RegZme *zme) +{ + /* 0x00D0(reg20), debug settings, skip */ + /* 3. set reg::zme */ + /* 3.1 set reg::zme::common */ + VdppZmeFmt zme_format_in = FMT_YCbCr420_888; /* only support yuv420 as input */ + VdppZmeScaleInfo yrgb_scl_info = {0}; + VdppZmeScaleInfo cbcr_scl_info = {0}; + + yrgb_scl_info.act_width = zme_params->src_width; + yrgb_scl_info.act_height = zme_params->src_height; + yrgb_scl_info.dsp_width = zme_params->dst_width; + yrgb_scl_info.dsp_height = zme_params->dst_height; + yrgb_scl_info.xscl_mode = SCL_MPH; + yrgb_scl_info.yscl_mode = SCL_MPH; + yrgb_scl_info.dering_en = zme_params->zme_dering_enable; + calc_scale_factor(zme_params, &yrgb_scl_info, zme_params->zme_bypass_en); + + cbcr_scl_info.act_width = zme_params->src_width / 2; + cbcr_scl_info.act_height = zme_params->src_height / 2; + if (zme_params->dst_fmt == VDPP_FMT_YUV444) { + if (!zme_params->yuv_out_diff) { + cbcr_scl_info.dsp_width = zme_params->dst_width; + cbcr_scl_info.dsp_height = zme_params->dst_height; + } else { + cbcr_scl_info.dsp_width = zme_params->dst_c_width; + cbcr_scl_info.dsp_height = zme_params->dst_c_height; + } + } else if (zme_params->dst_fmt == VDPP_FMT_YUV420) { + if (!zme_params->yuv_out_diff) { + cbcr_scl_info.dsp_width = zme_params->dst_width / 2; + cbcr_scl_info.dsp_height = zme_params->dst_height / 2; + } else { + /** @note: half the chroma size by user! */ + cbcr_scl_info.dsp_width = zme_params->dst_c_width; + cbcr_scl_info.dsp_height = zme_params->dst_c_height; + } + } else { + /* not supported */ + vdpp_loge("invalid output vdpp format %d!\n", zme_params->dst_fmt); + } + cbcr_scl_info.xscl_mode = SCL_MPH; + cbcr_scl_info.yscl_mode = SCL_MPH; + cbcr_scl_info.dering_en = zme_params->zme_dering_enable; + calc_scale_factor(zme_params, &cbcr_scl_info, zme_params->zme_bypass_en); + + /* 0x0800(reg0) */ + zme->common.reg0.bypass_en = 0; + zme->common.reg0.align_en = 0; + zme->common.reg0.format_in = zme_format_in; + if (zme_params->dst_fmt == VDPP_FMT_YUV444) + zme->common.reg0.format_out = FMT_YCbCr444_888; + else + zme->common.reg0.format_out = FMT_YCbCr420_888; + zme->common.reg0.auto_gating_en = 1; + + /* 0x0804 ~ 0x0808(reg1 ~ reg2), skip */ + + /* 0x080C(reg3), RESERVED */ + // zme->common.reg3.vir_width = zme_params->src_width; + // zme->common.reg3.vir_height = zme_params->src_height; + + /* 0x0810(reg4) */ + zme->common.reg4.yrgb_xsd_en = yrgb_scl_info.xsd_en; + zme->common.reg4.yrgb_xsu_en = yrgb_scl_info.xsu_en; + zme->common.reg4.yrgb_scl_mode = yrgb_scl_info.xscl_mode; + zme->common.reg4.yrgb_ysd_en = yrgb_scl_info.ysd_en; + zme->common.reg4.yrgb_ysu_en = yrgb_scl_info.ysu_en; + zme->common.reg4.yrgb_yscl_mode = yrgb_scl_info.yscl_mode; + zme->common.reg4.yrgb_dering_en = yrgb_scl_info.dering_en; + zme->common.reg4.yrgb_gt_en = yrgb_scl_info.ygt_en; + zme->common.reg4.yrgb_gt_mode = yrgb_scl_info.ygt_mode; + zme->common.reg4.yrgb_xgt_en = yrgb_scl_info.xgt_en; + zme->common.reg4.yrgb_xgt_mode = yrgb_scl_info.xgt_mode; + zme->common.reg4.yrgb_xsd_bypass = yrgb_scl_info.xsd_bypass; + zme->common.reg4.yrgb_ys_bypass = yrgb_scl_info.ys_bypass; + zme->common.reg4.yrgb_xsu_bypass = yrgb_scl_info.xsu_bypass; + + /* 0x0814(reg5), RESERVED */ + // zme->common.reg5.yrgb_src_width = yrgb_scl_info.act_width - 1; + // zme->common.reg5.yrgb_src_height = yrgb_scl_info.act_height - 1; + + /* 0x0818(reg6), RESERVED */ + // zme->common.reg6.yrgb_dst_width = yrgb_scl_info.dsp_width - 1; + // zme->common.reg6.yrgb_dst_height = yrgb_scl_info.dsp_height - 1; + + /* 0x081C(reg7) */ + zme->common.reg7.yrgb_dering_sen0 = zme_params->zme_dering_sen_0; + zme->common.reg7.yrgb_dering_sen1 = zme_params->zme_dering_sen_1; + zme->common.reg7.yrgb_dering_alpha = zme_params->zme_dering_blend_alpha; + zme->common.reg7.yrgb_dering_delta = zme_params->zme_dering_blend_beta; + + /* 0x0820(reg8) */ + zme->common.reg8.yrgb_xscl_factor = yrgb_scl_info.xscl_factor; + zme->common.reg8.yrgb_xscl_offset = yrgb_scl_info.xscl_offset; + + /* 0x0824(reg9) */ + zme->common.reg9.yrgb_yscl_factor = yrgb_scl_info.yscl_factor; + zme->common.reg9.yrgb_yscl_offset = yrgb_scl_info.yscl_offset; + + /* 0x0828 ~ 0x082C(reg10 ~ reg11), skip */ + + /* 0x0830(reg12) */ + zme->common.reg12.cbcr_xsd_en = cbcr_scl_info.xsd_en; + zme->common.reg12.cbcr_xsu_en = cbcr_scl_info.xsu_en; + zme->common.reg12.cbcr_xscl_mode = cbcr_scl_info.xscl_mode; + zme->common.reg12.cbcr_ysd_en = cbcr_scl_info.ysd_en; + zme->common.reg12.cbcr_ysu_en = cbcr_scl_info.ysu_en; + zme->common.reg12.cbcr_yscl_mode = cbcr_scl_info.yscl_mode; + zme->common.reg12.cbcr_dering_en = cbcr_scl_info.dering_en; + zme->common.reg12.cbcr_gt_en = cbcr_scl_info.ygt_en; + zme->common.reg12.cbcr_gt_mode = cbcr_scl_info.ygt_mode; + zme->common.reg12.cbcr_xgt_en = cbcr_scl_info.xgt_en; + zme->common.reg12.cbcr_xgt_mode = cbcr_scl_info.xgt_mode; + zme->common.reg12.cbcr_xsd_bypass = cbcr_scl_info.xsd_bypass; + zme->common.reg12.cbcr_ys_bypass = cbcr_scl_info.ys_bypass; + zme->common.reg12.cbcr_xsu_bypass = cbcr_scl_info.xsu_bypass; + + /* 0x0834(reg13), RESERVED */ + // zme->common.reg13.cbcr_src_width = cbcr_scl_info.act_width - 1; + // zme->common.reg13.cbcr_src_height = cbcr_scl_info.act_height - 1; + + /* 0x0838(reg14), RESERVED */ + // zme->common.reg14.cbcr_dst_width = cbcr_scl_info.dsp_width - 1; + // zme->common.reg14.cbcr_dst_height = cbcr_scl_info.dsp_height - 1; + + /* 0x083C(reg15) */ + zme->common.reg15.cbcr_dering_sen0 = zme_params->zme_dering_sen_0; + zme->common.reg15.cbcr_dering_sen1 = zme_params->zme_dering_sen_1; + zme->common.reg15.cbcr_dering_alpha = zme_params->zme_dering_blend_alpha; + zme->common.reg15.cbcr_dering_delta = zme_params->zme_dering_blend_beta; + + /* 0x0840(reg16) */ + zme->common.reg16.cbcr_xscl_factor = cbcr_scl_info.xscl_factor; + zme->common.reg16.cbcr_xscl_offset = cbcr_scl_info.xscl_offset; + + /* 0x0844(reg17) */ + zme->common.reg17.cbcr_yscl_factor = cbcr_scl_info.yscl_factor; + zme->common.reg17.cbcr_yscl_offset = cbcr_scl_info.yscl_offset; + + /* 3.2 set reg::zme::coef */ +#define VDPP_SET_ZME_COEF(index, row, col) \ + do { \ + zme->yrgb_hor_coe.reg##index.yrgb_hor_coe##row##_##col = yrgb_scl_info.xscl_zme_coe[row][col]; \ + zme->yrgb_ver_coe.reg##index.yrgb_ver_coe##row##_##col = yrgb_scl_info.yscl_zme_coe[row][col]; \ + zme->cbcr_hor_coe.reg##index.cbcr_hor_coe##row##_##col = cbcr_scl_info.xscl_zme_coe[row][col]; \ + zme->cbcr_ver_coe.reg##index.cbcr_ver_coe##row##_##col = cbcr_scl_info.yscl_zme_coe[row][col]; \ + } while (0) + + /* 0x0000(reg0) */ + VDPP_SET_ZME_COEF(0, 0, 0); + VDPP_SET_ZME_COEF(0, 0, 1); + + /* 0x0004(reg1) */ + VDPP_SET_ZME_COEF(1, 0, 2); + VDPP_SET_ZME_COEF(1, 0, 3); + + /* 0x0008(reg2) */ + VDPP_SET_ZME_COEF(2, 0, 4); + VDPP_SET_ZME_COEF(2, 0, 5); + + /* 0x000c(reg3) */ + VDPP_SET_ZME_COEF(3, 0, 6); + VDPP_SET_ZME_COEF(3, 0, 7); + + /* 0x0010(reg4) */ + VDPP_SET_ZME_COEF(4, 1, 0); + VDPP_SET_ZME_COEF(4, 1, 1); + + /* 0x0014(reg5) */ + VDPP_SET_ZME_COEF(5, 1, 2); + VDPP_SET_ZME_COEF(5, 1, 3); + + /* 0x0018(reg6) */ + VDPP_SET_ZME_COEF(6, 1, 4); + VDPP_SET_ZME_COEF(6, 1, 5); + + /* 0x001c(reg7) */ + VDPP_SET_ZME_COEF(7, 1, 6); + VDPP_SET_ZME_COEF(7, 1, 7); + + /* 0x0020(reg8) */ + VDPP_SET_ZME_COEF(8, 2, 0); + VDPP_SET_ZME_COEF(8, 2, 1); + + /* 0x0024(reg9) */ + VDPP_SET_ZME_COEF(9, 2, 2); + VDPP_SET_ZME_COEF(9, 2, 3); + + /* 0x0028(reg10) */ + VDPP_SET_ZME_COEF(10, 2, 4); + VDPP_SET_ZME_COEF(10, 2, 5); + + /* 0x002c(reg11) */ + VDPP_SET_ZME_COEF(11, 2, 6); + VDPP_SET_ZME_COEF(11, 2, 7); + + /* 0x0030(reg12) */ + VDPP_SET_ZME_COEF(12, 3, 0); + VDPP_SET_ZME_COEF(12, 3, 1); + + /* 0x0034(reg13) */ + VDPP_SET_ZME_COEF(13, 3, 2); + VDPP_SET_ZME_COEF(13, 3, 3); + + /* 0x0038(reg14) */ + VDPP_SET_ZME_COEF(14, 3, 4); + VDPP_SET_ZME_COEF(14, 3, 5); + + /* 0x003c(reg15) */ + VDPP_SET_ZME_COEF(15, 3, 6); + VDPP_SET_ZME_COEF(15, 3, 7); + + /* 0x0040(reg16) */ + VDPP_SET_ZME_COEF(16, 4, 0); + VDPP_SET_ZME_COEF(16, 4, 1); + + /* 0x0044(reg17) */ + VDPP_SET_ZME_COEF(17, 4, 2); + VDPP_SET_ZME_COEF(17, 4, 3); + + /* 0x0048(reg18) */ + VDPP_SET_ZME_COEF(18, 4, 4); + VDPP_SET_ZME_COEF(18, 4, 5); + + /* 0x004c(reg19) */ + VDPP_SET_ZME_COEF(19, 4, 6); + VDPP_SET_ZME_COEF(19, 4, 7); + + /* 0x0050(reg20) */ + VDPP_SET_ZME_COEF(20, 5, 0); + VDPP_SET_ZME_COEF(20, 5, 1); + + /* 0x0054(reg21) */ + VDPP_SET_ZME_COEF(21, 5, 2); + VDPP_SET_ZME_COEF(21, 5, 3); + + /* 0x0058(reg22) */ + VDPP_SET_ZME_COEF(22, 5, 4); + VDPP_SET_ZME_COEF(22, 5, 5); + + /* 0x005c(reg23) */ + VDPP_SET_ZME_COEF(23, 5, 6); + VDPP_SET_ZME_COEF(23, 5, 7); + + /* 0x0060(reg24) */ + VDPP_SET_ZME_COEF(24, 6, 0); + VDPP_SET_ZME_COEF(24, 6, 1); + + /* 0x0064(reg25) */ + VDPP_SET_ZME_COEF(25, 6, 2); + VDPP_SET_ZME_COEF(25, 6, 3); + + /* 0x0068(reg26) */ + VDPP_SET_ZME_COEF(26, 6, 4); + VDPP_SET_ZME_COEF(26, 6, 5); + + /* 0x006c(reg27) */ + VDPP_SET_ZME_COEF(27, 6, 6); + VDPP_SET_ZME_COEF(27, 6, 7); + + /* 0x0070(reg28) */ + VDPP_SET_ZME_COEF(28, 7, 0); + VDPP_SET_ZME_COEF(28, 7, 1); + + /* 0x0074(reg29) */ + VDPP_SET_ZME_COEF(29, 7, 2); + VDPP_SET_ZME_COEF(29, 7, 3); + + /* 0x0078(reg30) */ + VDPP_SET_ZME_COEF(30, 7, 4); + VDPP_SET_ZME_COEF(30, 7, 5); + + /* 0x007c(reg31) */ + VDPP_SET_ZME_COEF(31, 7, 6); + VDPP_SET_ZME_COEF(31, 7, 7); + + /* 0x0080(reg32) */ + VDPP_SET_ZME_COEF(32, 8, 0); + VDPP_SET_ZME_COEF(32, 8, 1); + + /* 0x0084(reg33) */ + VDPP_SET_ZME_COEF(33, 8, 2); + VDPP_SET_ZME_COEF(33, 8, 3); + + /* 0x0088(reg34) */ + VDPP_SET_ZME_COEF(34, 8, 4); + VDPP_SET_ZME_COEF(34, 8, 5); + + /* 0x008c(reg35) */ + VDPP_SET_ZME_COEF(35, 8, 6); + VDPP_SET_ZME_COEF(35, 8, 7); + + /* 0x0090(reg36) */ + VDPP_SET_ZME_COEF(36, 9, 0); + VDPP_SET_ZME_COEF(36, 9, 1); + + /* 0x0094(reg37) */ + VDPP_SET_ZME_COEF(37, 9, 2); + VDPP_SET_ZME_COEF(37, 9, 3); + + /* 0x0098(reg38) */ + VDPP_SET_ZME_COEF(38, 9, 4); + VDPP_SET_ZME_COEF(38, 9, 5); + + /* 0x009c(reg39) */ + VDPP_SET_ZME_COEF(39, 9, 6); + VDPP_SET_ZME_COEF(39, 9, 7); + + /* 0x00a0(reg40) */ + VDPP_SET_ZME_COEF(40, 10, 0); + VDPP_SET_ZME_COEF(40, 10, 1); + + /* 0x00a4(reg41) */ + VDPP_SET_ZME_COEF(41, 10, 2); + VDPP_SET_ZME_COEF(41, 10, 3); + + /* 0x00a8(reg42) */ + VDPP_SET_ZME_COEF(42, 10, 4); + VDPP_SET_ZME_COEF(42, 10, 5); + + /* 0x00ac(reg43) */ + VDPP_SET_ZME_COEF(43, 10, 6); + VDPP_SET_ZME_COEF(43, 10, 7); + + /* 0x00b0(reg44) */ + VDPP_SET_ZME_COEF(44, 11, 0); + VDPP_SET_ZME_COEF(44, 11, 1); + + /* 0x00b4(reg45) */ + VDPP_SET_ZME_COEF(45, 11, 2); + VDPP_SET_ZME_COEF(45, 11, 3); + + /* 0x00b8(reg46) */ + VDPP_SET_ZME_COEF(46, 11, 4); + VDPP_SET_ZME_COEF(46, 11, 5); + + /* 0x00bc(reg47) */ + VDPP_SET_ZME_COEF(47, 11, 6); + VDPP_SET_ZME_COEF(47, 11, 7); + + /* 0x00c0(reg48) */ + VDPP_SET_ZME_COEF(48, 12, 0); + VDPP_SET_ZME_COEF(48, 12, 1); + + /* 0x00c4(reg49) */ + VDPP_SET_ZME_COEF(49, 12, 2); + VDPP_SET_ZME_COEF(49, 12, 3); + + /* 0x00c8(reg50) */ + VDPP_SET_ZME_COEF(50, 12, 4); + VDPP_SET_ZME_COEF(50, 12, 5); + + /* 0x00cc(reg51) */ + VDPP_SET_ZME_COEF(51, 12, 6); + VDPP_SET_ZME_COEF(51, 12, 7); + + /* 0x00d0(reg52) */ + VDPP_SET_ZME_COEF(52, 13, 0); + VDPP_SET_ZME_COEF(52, 13, 1); + + /* 0x00d4(reg53) */ + VDPP_SET_ZME_COEF(53, 13, 2); + VDPP_SET_ZME_COEF(53, 13, 3); + + /* 0x00d8(reg54) */ + VDPP_SET_ZME_COEF(54, 13, 4); + VDPP_SET_ZME_COEF(54, 13, 5); + + /* 0x00dc(reg55) */ + VDPP_SET_ZME_COEF(55, 13, 6); + VDPP_SET_ZME_COEF(55, 13, 7); + + /* 0x00e0(reg56) */ + VDPP_SET_ZME_COEF(56, 14, 0); + VDPP_SET_ZME_COEF(56, 14, 1); + + /* 0x00e4(reg57) */ + VDPP_SET_ZME_COEF(57, 14, 2); + VDPP_SET_ZME_COEF(57, 14, 3); + + /* 0x00e8(reg58) */ + VDPP_SET_ZME_COEF(58, 14, 4); + VDPP_SET_ZME_COEF(58, 14, 5); + + /* 0x00ec(reg59) */ + VDPP_SET_ZME_COEF(59, 14, 6); + VDPP_SET_ZME_COEF(59, 14, 7); + + /* 0x00f0(reg60) */ + VDPP_SET_ZME_COEF(60, 15, 0); + VDPP_SET_ZME_COEF(60, 15, 1); + + /* 0x00f4(reg61) */ + VDPP_SET_ZME_COEF(61, 15, 2); + VDPP_SET_ZME_COEF(61, 15, 3); + + /* 0x00f8(reg62) */ + VDPP_SET_ZME_COEF(62, 15, 4); + VDPP_SET_ZME_COEF(62, 15, 5); + + /* 0x00fc(reg63) */ + VDPP_SET_ZME_COEF(63, 15, 6); + VDPP_SET_ZME_COEF(63, 15, 7); + + /* 0x0100(reg64) */ + VDPP_SET_ZME_COEF(64, 16, 0); + VDPP_SET_ZME_COEF(64, 16, 1); + + /* 0x0104(reg65) */ + VDPP_SET_ZME_COEF(65, 16, 2); + VDPP_SET_ZME_COEF(65, 16, 3); + + /* 0x0108(reg66) */ + VDPP_SET_ZME_COEF(66, 16, 4); + VDPP_SET_ZME_COEF(66, 16, 5); + + /* 0x010c(reg67) */ + VDPP_SET_ZME_COEF(67, 16, 6); + VDPP_SET_ZME_COEF(67, 16, 7); + +#undef VDPP_SET_ZME_COEF +} + +MPP_RET vdpp_init(VdppCtx ictx) +{ + MppReqV1 mpp_req; + RK_U32 client_data = VDPP_CLIENT_TYPE; + Vdpp1ApiCtx *ctx = ictx; + MPP_RET ret = MPP_OK; + + if (NULL == ictx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ictx); + return MPP_ERR_NULL_PTR; + } + + // default log level: warning + mpp_env_get_u32(VDPP_COM_DEBUG_ENV_NAME, &vdpp_debug, + (VDPP_LOG_FATAL | VDPP_LOG_ERROR | VDPP_LOG_WARNING)); + vdpp_logi("get env '%s' flag: %#x", VDPP_COM_DEBUG_ENV_NAME, vdpp_debug); + + vdpp_enter(); + + ctx->fd = open("/dev/mpp_service", O_RDWR | O_CLOEXEC); + if (ctx->fd < 0) { + vdpp_loge("can NOT find device /dev/vdpp\n"); + return MPP_NOK; + } + + mpp_req.cmd = MPP_CMD_INIT_CLIENT_TYPE; + mpp_req.flag = 0; + mpp_req.size = sizeof(client_data); + mpp_req.data_ptr = REQ_DATA_PTR(&client_data); + + /* set default parameters */ + memset(&ctx->params, 0, sizeof(Vdpp1Params)); + vdpp_set_default_param(&ctx->params); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) { + vdpp_loge("ioctl set_client failed!\n"); + return MPP_NOK; + } + + vdpp_leave(); + return ret; +} + +MPP_RET vdpp_deinit(VdppCtx ictx) +{ + Vdpp1ApiCtx *ctx = ictx; + + if (NULL == ictx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ictx); + return MPP_ERR_NULL_PTR; + } + + if (ctx->fd >= 0) { + close(ctx->fd); + ctx->fd = -1; + } + + return MPP_OK; +} + +static MPP_RET vdpp_set_param(Vdpp1ApiCtx *ctx, VdppApiContent *param, VdppParamType type) +{ + switch (type) { + case VDPP_PARAM_TYPE_COM: { + ctx->params.src_yuv_swap = param->com.sswap; + ctx->params.dst_fmt = param->com.dfmt; + ctx->params.dst_yuv_swap = param->com.dswap; + ctx->params.src_width = param->com.src_width; + ctx->params.src_height = param->com.src_height; + ctx->params.dst_width = param->com.dst_width; + ctx->params.dst_height = param->com.dst_height; + } break; + case VDPP_PARAM_TYPE_DMSR: { + mpp_assert(sizeof(ctx->params.dmsr_params) == sizeof(param->dmsr)); + memcpy(&ctx->params.dmsr_params, ¶m->dmsr, sizeof(DmsrParams)); + } break; + case VDPP_PARAM_TYPE_ZME_COM: { + ctx->params.zme_params.zme_bypass_en = param->zme.bypass_enable; + ctx->params.zme_params.zme_dering_enable = param->zme.dering_enable; + ctx->params.zme_params.zme_dering_sen_0 = param->zme.dering_sen_0; + ctx->params.zme_params.zme_dering_sen_1 = param->zme.dering_sen_1; + ctx->params.zme_params.zme_dering_blend_alpha = param->zme.dering_blend_alpha; + ctx->params.zme_params.zme_dering_blend_beta = param->zme.dering_blend_beta; + if (param->zme.tap8_coeff != NULL) + ctx->params.zme_params.zme_tap8_coeff = param->zme.tap8_coeff; + if (param->zme.tap6_coeff != NULL) + ctx->params.zme_params.zme_tap6_coeff = param->zme.tap6_coeff; + } break; + case VDPP_PARAM_TYPE_ZME_COEFF: { + if (param->zme.tap8_coeff != NULL) + ctx->params.zme_params.zme_tap8_coeff = param->zme.tap8_coeff; + if (param->zme.tap6_coeff != NULL) + ctx->params.zme_params.zme_tap6_coeff = param->zme.tap6_coeff; + } break; + default: { + vdpp_loge("unknown VDPP_PARAM_TYPE %#x !\n", type); + } break; + } + + return MPP_OK; +} + +static RK_S32 check_cap(Vdpp1Params *params) +{ + RK_S32 ret_cap = VDPP_CAP_UNSUPPORTED; + RK_U32 vep_mode_check = 0; + + if (NULL == params) { + vdpp_loge("found null pointer params\n"); + return VDPP_CAP_UNSUPPORTED; + } + + if ((params->src_height < VDPP_MODE_MIN_HEIGHT) || + (params->src_width < VDPP_MODE_MIN_WIDTH)) { + vdpp_logd("vep unsupported src img_w=%d img_h=%d\n", + params->src_width, params->src_height); + vep_mode_check++; + } + + if ((params->dst_height < VDPP_MODE_MIN_HEIGHT) || + (params->dst_width < VDPP_MODE_MIN_WIDTH)) { + vdpp_logd("vep unsupported dst img_w=%d img_h=%d\n", + params->dst_width, params->dst_height); + vep_mode_check++; + } + + if ((params->src_width & 1) || (params->src_height & 1) || + (params->dst_width & 1) || (params->dst_height & 1)) { + vdpp_logd("vep only support img_w/h_vld 2pix align\n"); + vdpp_logd("vep unsupported img_w_i=%d img_h_i=%d img_w_o=%d img_h_o=%d\n", + params->src_width, params->src_height, params->dst_width, params->dst_height); + vep_mode_check++; + } + + if (!vep_mode_check) { + ret_cap |= VDPP_CAP_VEP; + vdpp_logd("vdpp support mode: VDPP_CAP_VEP\n"); + } + + return ret_cap; +} + +static MPP_RET vdpp_start(Vdpp1ApiCtx *ctx) +{ + VdppRegOffsetInfo reg_off[2]; + MppReqV1 mpp_req[9]; + RK_U32 req_cnt = 0; + Vdpp1Regs *reg = NULL; + RK_S32 ret_cap = VDPP_CAP_UNSUPPORTED; + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + // get env here so that we can change loglevel dynamically + mpp_env_get_u32(VDPP_COM_DEBUG_ENV_NAME, &vdpp_debug, + (VDPP_LOG_FATAL | VDPP_LOG_ERROR | VDPP_LOG_WARNING)); + vdpp_logt("get env '%s' flag: %#x", VDPP_COM_DEBUG_ENV_NAME, vdpp_debug); + + vdpp_enter(); + + ret_cap = check_cap(&ctx->params); + if (!(ret_cap & VDPP_CAP_VEP)) { + vdpp_loge("found incompat work mode %s, cap %d\n", + working_mode_name[VDPP_WORK_MODE_VEP], ret_cap); + return MPP_NOK; + } + + reg = &ctx->reg; + + memset(reg_off, 0, sizeof(reg_off)); + memset(mpp_req, 0, sizeof(mpp_req)); + memset(reg, 0, sizeof(*reg)); + + vdpp_params_to_reg(&ctx->params, ctx); + + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.yrgb_hor_coe); + mpp_req[req_cnt].offset = VDPP_REG_OFF_YRGB_HOR_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.yrgb_hor_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.yrgb_ver_coe); + mpp_req[req_cnt].offset = VDPP_REG_OFF_YRGB_VER_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.yrgb_ver_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.cbcr_hor_coe); + mpp_req[req_cnt].offset = VDPP_REG_OFF_CBCR_HOR_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.cbcr_hor_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.cbcr_ver_coe); + mpp_req[req_cnt].offset = VDPP_REG_OFF_CBCR_VER_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.cbcr_ver_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.common); + mpp_req[req_cnt].offset = VDPP_REG_OFF_ZME_COMMON; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.common); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->dmsr); + mpp_req[req_cnt].offset = VDPP_REG_OFF_DMSR; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->dmsr); + + /* set reg offset */ + reg_off[0].reg_idx = 25; + reg_off[0].offset = ctx->params.src.cbcr_offset; + reg_off[1].reg_idx = 27; + reg_off[1].offset = ctx->params.dst.cbcr_offset; + + vdpp_logv("set reg: cbcr_offset for src/dst=%d/%d\n", reg_off[0].offset, reg_off[1].offset); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_ADDR_OFFSET; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG | MPP_FLAGS_REG_OFFSET_ALONE; + mpp_req[req_cnt].size = sizeof(reg_off); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(reg_off); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->common); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->common); + + /* read output register for common */ + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_READ; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG | MPP_FLAGS_LAST_MSG; + mpp_req[req_cnt].size = sizeof(reg->common); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->common); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req[0]); + + if (ret) { + vdpp_loge("ioctl SET_REG failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + + vdpp_leave(); + return ret; +} + +static MPP_RET vdpp_wait(Vdpp1ApiCtx *ctx) +{ + MppReqV1 mpp_req; + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + memset(&mpp_req, 0, sizeof(mpp_req)); + mpp_req.cmd = MPP_CMD_POLL_HW_FINISH; + mpp_req.flag |= MPP_FLAGS_LAST_MSG; + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) { + vdpp_loge("ioctl POLL_HW_FINISH failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + } + + return ret; +} + +static MPP_RET vdpp_done(Vdpp1ApiCtx *ctx) +{ + Vdpp1Regs *reg = NULL; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + vdpp_enter(); + + reg = &ctx->reg; + + vdpp_logd("ro_frm_done_sts=%d\n", reg->common.reg10.ro_frm_done_sts); + vdpp_logd("ro_osd_max_sts=%d\n", reg->common.reg10.ro_osd_max_sts); + vdpp_logd("ro_bus_error_sts=%d\n", reg->common.reg10.ro_bus_error_sts); + vdpp_logd("ro_timeout_sts=%d\n", reg->common.reg10.ro_timeout_sts); + vdpp_logd("ro_config_error_sts=%d\n", reg->common.reg10.ro_config_error_sts); + + if (reg->common.reg8.sw_vdpp_frm_done_en && + !reg->common.reg10.ro_frm_done_sts) { + vdpp_loge("run vdpp failed!!\n"); + return MPP_NOK; + } + + if (reg->common.reg10.ro_timeout_sts) { + vdpp_loge("run vdpp timeout!!\n"); + return MPP_NOK; + } + + vdpp_logi("run vdpp success! %d\n", reg->common.reg10); + vdpp_leave(); + return MPP_OK; +} + +MPP_RET vdpp_control(VdppCtx ictx, VdppCmd cmd, void *iparam) +{ + Vdpp1ApiCtx *ctx = ictx; + MPP_RET ret = MPP_OK; + + if ((NULL == iparam && VDPP_CMD_RUN_SYNC != cmd) || + (NULL == ictx)) { + vdpp_loge("found NULL iparam %p cmd %d ctx %p\n", iparam, cmd, ictx); + return MPP_ERR_NULL_PTR; + } + + switch (cmd) { + case VDPP_CMD_SET_COM_CFG: + case VDPP_CMD_SET_DMSR_CFG: + case VDPP_CMD_SET_ZME_COM_CFG: + case VDPP_CMD_SET_ZME_COEFF_CFG: { + VdppApiParams *api_param = (VdppApiParams *)iparam; + + ret = vdpp_set_param(ctx, &api_param->param, api_param->ptype); + if (ret) { + vdpp_loge("set vdpp parameter failed, type %d\n", api_param->ptype); + } + } break; + case VDPP_CMD_SET_SRC: { + set_addr(&ctx->params.src, (VdppImg *)iparam); + } break; + case VDPP_CMD_SET_DST: { + set_addr(&ctx->params.dst, (VdppImg *)iparam); + } break; + case VDPP_CMD_RUN_SYNC: { + ret = vdpp_start(ctx); + if (ret) { + vdpp_loge("run vdpp failed!!\n"); + return MPP_NOK; + } + + ret |= vdpp_wait(ctx); + ret |= vdpp_done(ctx); + } break; + default: { + vdpp_loge("unsupported control cmd %#x for vdpp1!\n", cmd); + ret = MPP_ERR_VALUE; + } break; + } + + return ret; +} + +RK_S32 vdpp_check_cap(VdppCtx ictx) +{ + Vdpp1ApiCtx *ctx = ictx; + + if (NULL == ictx) { + vdpp_loge("found NULL ctx %p!\n", ictx); + return VDPP_CAP_UNSUPPORTED; + } + + return check_cap(&ctx->params); +} diff --git a/mpp/vproc/vdpp/vdpp.h b/mpp/vproc/vdpp/vdpp.h new file mode 100644 index 000000000..1dca8dd3d --- /dev/null +++ b/mpp/vproc/vdpp/vdpp.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP_H +#define VDPP_H + +#include "vdpp_reg.h" +#include "vdpp_common.h" + +typedef enum ZME_FMT { + FMT_YCbCr420_888 = 4, + FMT_YCbCr444_888 = 6, +} VdppZmeFmt; + +typedef enum { + SCL_NEI = 0, + SCL_BIL = 1, + SCL_BIC = 2, + SCL_MPH = 3, +} VdppZmeScaleMode; + +typedef struct scl_info { + RK_U16 act_width; + RK_U16 dsp_width; + + RK_U16 act_height; + RK_U16 dsp_height; + + RK_U8 dering_en; + + RK_U8 xsd_en; + RK_U8 xsu_en; + RK_U8 xsd_bypass; + RK_U8 xsu_bypass; + RK_U8 xscl_mode; + RK_U16 xscl_factor; + RK_U8 xscl_offset; + + RK_U8 ysd_en; + RK_U8 ysu_en; + RK_U8 ys_bypass; + RK_U8 yscl_mode; + RK_U16 yscl_factor; + RK_U8 yscl_offset; + + RK_U8 xavg_en; + RK_U8 xgt_en; + RK_U8 xgt_mode; + + RK_U8 yavg_en; + RK_U8 ygt_en; + RK_U8 ygt_mode; + + const RK_S16 (*xscl_zme_coe)[8]; + const RK_S16 (*yscl_zme_coe)[8]; + + /* used after vdpp3 */ + RK_U8 xscl_coe_idx; // [0, 9], the coef index to use in x-axis + RK_U8 yscl_coe_idx; // [0, 9], the coef index to use in y-axis +} VdppZmeScaleInfo; + +typedef struct dmsr_params { + bool dmsr_enable; + RK_U32 dmsr_str_pri_y; + RK_U32 dmsr_str_sec_y; + RK_U32 dmsr_dumping_y; + RK_U32 dmsr_wgt_pri_gain_even_1; + RK_U32 dmsr_wgt_pri_gain_even_2; + RK_U32 dmsr_wgt_pri_gain_odd_1; + RK_U32 dmsr_wgt_pri_gain_odd_2; + RK_U32 dmsr_wgt_sec_gain; + RK_U32 dmsr_blk_flat_th; + RK_U32 dmsr_contrast_to_conf_map_x0; + RK_U32 dmsr_contrast_to_conf_map_x1; + RK_U32 dmsr_contrast_to_conf_map_y0; + RK_U32 dmsr_contrast_to_conf_map_y1; + RK_U32 dmsr_diff_core_th0; + RK_U32 dmsr_diff_core_th1; + RK_U32 dmsr_diff_core_wgt0; + RK_U32 dmsr_diff_core_wgt1; + RK_U32 dmsr_diff_core_wgt2; + RK_U32 dmsr_edge_th_low_arr[7]; + RK_U32 dmsr_edge_th_high_arr[7]; +} DmsrParams; + +typedef struct zme_params { + RK_U32 zme_bypass_en; + RK_U32 zme_dering_enable; + RK_U32 zme_dering_sen_0; + RK_U32 zme_dering_sen_1; + RK_U32 zme_dering_blend_alpha; + RK_U32 zme_dering_blend_beta; + const RK_S16 (*zme_tap8_coeff)[17][8]; // 11x17x8 + const RK_S16 (*zme_tap6_coeff)[17][8]; // 11x17x8 + + /* for scale info */ + RK_U32 src_width; + RK_U32 src_height; + RK_U32 dst_width; + RK_U32 dst_height; + RK_U32 dst_fmt; + + /* 3576(vdpp2) feature */ + RK_U32 yuv_out_diff; + RK_U32 dst_c_width; + RK_U32 dst_c_height; +} ZmeParams; + +typedef struct vdpp_params { + RK_U32 src_yuv_swap; + RK_U32 dst_fmt; + RK_U32 dst_yuv_swap; + RK_U32 src_width; + RK_U32 src_height; + RK_U32 dst_width; + RK_U32 dst_height; + + VdppAddr src; // src frame + VdppAddr dst; // dst frame + + DmsrParams dmsr_params; + ZmeParams zme_params; +} Vdpp1Params; + +typedef struct vdpp_api_ctx { + RK_S32 fd; // device fd, like '/dev/mpp_service' + Vdpp1Params params; + Vdpp1Regs reg; +} Vdpp1ApiCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vdpp_init(VdppCtx ictx); +MPP_RET vdpp_deinit(VdppCtx ictx); +MPP_RET vdpp_control(VdppCtx ictx, VdppCmd cmd, void *iparam); +RK_S32 vdpp_check_cap(VdppCtx ictx); + +#ifdef __cplusplus +} +#endif + +#endif /* VDPP_H */ diff --git a/mpp/vproc/vdpp/vdpp2.c b/mpp/vproc/vdpp/vdpp2.c new file mode 100644 index 000000000..99dfc2898 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp2.c @@ -0,0 +1,2009 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpp" + +#include +#include +#include +#include +#include + +#include "mpp_common.h" +#include "mpp_env.h" +#include "mpp_service.h" +#include "mpp_platform.h" + +#include "vdpp2.h" + +#define VDPP2_VEP_MAX_WIDTH (1920) +#define VDPP2_VEP_MAX_HEIGHT (2048) +#define VDPP2_HIST_MAX_WIDTH (4096) +#define VDPP2_HIST_MAX_HEIGHT (4096) +#define VDPP2_MODE_MIN_WIDTH (128) +#define VDPP2_MODE_MIN_HEIGHT (128) + +#define VDPP2_HIST_HSD_DISABLE_LIMIT (1920) +#define VDPP2_HIST_VSD_DISABLE_LIMIT (1080) +#define VDPP2_HIST_VSD_MODE_1_LIMIT (2160) + +// default log level: warning +extern RK_U32 vdpp_debug; + +/* default es parameters */ +static RK_S32 diff2conf_lut_x_tmp[9] = { + 0, 1024, 2048, 3072, 4096, 6144, 8192, 12288, 65535, +}; +static RK_S32 diff2conf_lut_y_tmp[9] = { + 0, 84, 141, 179, 204, 233, 246, 253, 255, +}; + +/* default sharp parameters */ +static RK_S32 coring_zero_tmp[7] = { + 5, 5, 8, 5, 8, 5, 5, +}; +static RK_S32 coring_thr_tmp[7] = { + 40, 40, 40, 24, 26, 30, 26, +}; +static RK_S32 coring_ratio_tmp[7] = { + 1479, 1188, 1024, 1422, 1024, 1024, 1024, +}; +static RK_S32 gain_pos_tmp[7] = { + 128, 256, 512, 256, 512, 256, 256, +}; +static RK_S32 gain_neg_tmp[7] = { + 128, 256, 512, 256, 512, 256, 256, +}; +static RK_S32 limit_ctrl_pos0_tmp[7] = { + 64, 64, 64, 64, 64, 64, 64, +}; +static RK_S32 limit_ctrl_pos1_tmp[7] = { + 120, 120, 120, 120, 120, 120, 120, +}; +static RK_S32 limit_ctrl_neg0_tmp[7] = { + 64, 64, 64, 64, 64, 64, 64, +}; +static RK_S32 limit_ctrl_neg1_tmp[7] = { + 120, 120, 120, 120, 120, 120, 120, +}; +static RK_S32 limit_ctrl_ratio_tmp[7] = { + 128, 128, 128, 128, 128, 128, 128, +}; +static RK_S32 limit_ctrl_bnd_pos_tmp[7] = { + 81, 131, 63, 81, 63, 63, 63, +}; +static RK_S32 limit_ctrl_bnd_neg_tmp[7] = { + 81, 131, 63, 81, 63, 63, 63, +}; +static RK_S32 lum_grd_tmp[6] = { + 0, 200, 300, 860, 960, 1023 +}; +static RK_S32 lum_val_tmp[6] = { + 64, 64, 64, 64, 64, 64, +}; +static RK_S32 adp_grd_tmp[6] = { + 0, 4, 60, 180, 300, 1023, +}; +static RK_S32 adp_val_tmp[6] = { + 64, 64, 64, 64, 64, 64, +}; +static RK_S32 var_grd_tmp[6] = { + 0, 39, 102, 209, 500, 1023, +}; +static RK_S32 var_val_tmp[6] = { + 64, 64, 64, 64, 64, 64, +}; +static RK_S32 diag_adj_gain_tab_tmp[8] = { + 6, 7, 8, 9, 10, 11, 12, 13, +}; +static RK_S32 roll_tab_pattern0[16] = { + 0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 15, +}; +static RK_S32 roll_tab_pattern1[16] = { + 31, 31, 30, 29, 28, 27, 25, 23, 21, 19, 18, 17, 16, 16, 15, 15, +}; +static RK_S32 roll_tab_pattern2[16] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +}; +static RK_S32 tex_grd_tmp[6] = { + 0, 128, 256, 400, 600, 1023, +}; +static RK_S32 tex_val_tmp[6] = { + 40, 60, 80, 100, 127, 127, +}; + + +int update_dci_ctl(HistParams *hist_params) +{ + RK_S32 dci_format = VDPP_DCI_FMT_BUTT; + RK_S32 dci_alpha_swap = 0; + RK_S32 dci_rbuv_swap = 0; + + /* for YUV formats: only consider luma data */ + /* for RGB unpacked formats: convert LSB order to MSB order */ + switch (hist_params->src_fmt) { + case MPP_FMT_YUV420SP: + case MPP_FMT_YUV422SP: + case MPP_FMT_YUV420P: + case MPP_FMT_YUV422P: + case MPP_FMT_YUV400: + case MPP_FMT_YUV440SP: + case MPP_FMT_YUV411SP: + case MPP_FMT_YUV444SP: + case MPP_FMT_YUV444P: { + dci_format = VDPP_DCI_FMT_Y_8bit_SP; + dci_rbuv_swap = 0; + } break; + case MPP_FMT_YUV420SP_VU: + case MPP_FMT_YUV422SP_VU: { + dci_format = VDPP_DCI_FMT_Y_8bit_SP; + dci_rbuv_swap = 1; + } break; + case MPP_FMT_YUV420SP_10BIT: + case MPP_FMT_YUV422SP_10BIT: + case MPP_FMT_YUV444SP_10BIT: { + dci_format = VDPP_DCI_FMT_Y_10bit_SP; + dci_rbuv_swap = 0; + } break; + case MPP_FMT_RGB888: { + dci_format = VDPP_DCI_FMT_RGB888; + dci_rbuv_swap = 1; + } break; + case MPP_FMT_BGR888: { + dci_format = VDPP_DCI_FMT_RGB888; + dci_rbuv_swap = 0; + } break; + case MPP_FMT_ARGB8888: { + dci_format = VDPP_DCI_FMT_ARGB8888; + dci_alpha_swap = 1; + dci_rbuv_swap = 1; + } break; + case MPP_FMT_ABGR8888: { + dci_format = VDPP_DCI_FMT_ARGB8888; + dci_alpha_swap = 1; + dci_rbuv_swap = 0; + } break; + case MPP_FMT_BGRA8888: { + dci_format = VDPP_DCI_FMT_ARGB8888; + dci_alpha_swap = 0; + dci_rbuv_swap = 0; + } break; + case MPP_FMT_RGBA8888: { + dci_format = VDPP_DCI_FMT_ARGB8888; + dci_alpha_swap = 0; + dci_rbuv_swap = 1; + } break; + default: break; + } + + if (dci_format == VDPP_DCI_FMT_BUTT) { + vdpp_loge("error: invalid input mpp format %d !", hist_params->src_fmt); + return MPP_ERR_VALUE; + } + + hist_params->dci_format = dci_format; + hist_params->dci_alpha_swap = dci_alpha_swap; + hist_params->dci_rbuv_swap = dci_rbuv_swap; + + vdpp_logv("input mpp_format=%d => dci_format=%d (0: rgb24, 1: argb32, 4: y8, 5: y10_packed), " + "alpha_swap=%d, rbuv_swap=%d", + hist_params->src_fmt, dci_format, dci_alpha_swap, dci_rbuv_swap); + return MPP_OK; +} + +void set_hist_to_vdpp2_reg(HistParams *hist_params, RegHist *hist, RegCom2 *reg_com) +{ + RK_S32 pic_vir_src_ystride; + RK_S32 hsd_sample_num, vsd_sample_num, sw_dci_blk_hsize, sw_dci_blk_vsize; + RK_U32 dci_hsd_mode, dci_vsd_mode; + MPP_RET ret = MPP_OK; + + // update 'dci_format/dci_alpha_swap/dci_rbuv_swap' according to input mpp format + ret = update_dci_ctl(hist_params); + if (ret) { + reg_com->reg1.sw_dci_en = 0; + return; + } + + pic_vir_src_ystride = (hist_params->src_width + 3) / 4; + + if (hist_params->dci_format == VDPP_DCI_FMT_RGB888) { + pic_vir_src_ystride = hist_params->src_width_vir * 3 / 4; + } else if (hist_params->dci_format == VDPP_DCI_FMT_ARGB8888) { + pic_vir_src_ystride = hist_params->src_width_vir * 4 / 4; + } else if (hist_params->dci_format == VDPP_DCI_FMT_Y_10bit_SP) { // Y 10bit SP + pic_vir_src_ystride = hist_params->src_width_vir * 10 / 8 / 4; + } else if (hist_params->dci_format == VDPP_DCI_FMT_Y_8bit_SP) { // Y 8bit SP + pic_vir_src_ystride = hist_params->src_width_vir / 4; + } else { + vdpp_loge("unsupported dci format %d!\n", hist_params->dci_format); + return; + } + + dci_hsd_mode = (hist_params->dci_hsd_mode & 1); + dci_vsd_mode = (hist_params->dci_vsd_mode & 3); + + /* check vdpp scale down mode for performance optimization */ + if (!(dci_hsd_mode & VDPP_DCI_HSD_MODE_1) && + (hist_params->src_width_vir > VDPP2_HIST_HSD_DISABLE_LIMIT)) { + vdpp_logd("w_vir %d hsd mode %d is optimized as mode 1\n", + hist_params->src_width_vir, dci_hsd_mode); + dci_hsd_mode = VDPP_DCI_HSD_MODE_1; + } + + if (!(dci_vsd_mode & VDPP_DCI_VSD_MODE_1) && + (hist_params->src_height_vir > VDPP2_HIST_VSD_DISABLE_LIMIT)) { + vdpp_logd("h_vir %d vsd mode %d is optimized as mode 1\n", + hist_params->src_height_vir, dci_vsd_mode); + dci_vsd_mode = VDPP_DCI_VSD_MODE_1; + } + + if (!(dci_vsd_mode & VDPP_DCI_VSD_MODE_2) && + (hist_params->src_height_vir > VDPP2_HIST_VSD_MODE_1_LIMIT)) { + vdpp_logd("h_vir %d vsd mode %d is optimized as mode 2\n", + hist_params->src_height_vir, dci_vsd_mode); + dci_vsd_mode = VDPP_DCI_VSD_MODE_2; + } + + dci_vsd_mode = (hist_params->working_mode == VDPP_WORK_MODE_VEP) ? 0 : dci_vsd_mode; + dci_hsd_mode = (hist_params->working_mode == VDPP_WORK_MODE_VEP) ? 0 : dci_hsd_mode; + vdpp_logv("final vsd/hsd mode: %d/%d, working_mode: %d\n", + dci_vsd_mode, dci_hsd_mode, hist_params->working_mode); + + switch (dci_hsd_mode) { + case VDPP_DCI_HSD_MODE_1: + hsd_sample_num = 4; + break; + case VDPP_DCI_HSD_DISABLE: + default: + hsd_sample_num = 2; + break; + } + + switch (dci_vsd_mode) { + case VDPP_DCI_VSD_MODE_1: + vsd_sample_num = 2; + break; + case VDPP_DCI_VSD_MODE_2: + vsd_sample_num = 4; + break; + case VDPP_DCI_VSD_DISABLE: + default: + vsd_sample_num = 1; + break; + } + + if (hist_params->src_height < 1080) + sw_dci_blk_vsize = hist_params->src_height / (16 * vsd_sample_num); + else + sw_dci_blk_vsize = (hist_params->src_height + (16 * vsd_sample_num - 1)) / (16 * vsd_sample_num); + + if (hist_params->src_width < 1080) + sw_dci_blk_hsize = hist_params->src_width / (16 * hsd_sample_num); + else + sw_dci_blk_hsize = (hist_params->src_width + (16 * hsd_sample_num - 1)) / (16 * hsd_sample_num); + + reg_com->reg1.sw_dci_en = hist_params->hist_cnt_en; + + hist->reg0.sw_dci_yrgb_addr = hist_params->src_addr; + hist->reg1.sw_dci_yrgb_vir_stride = pic_vir_src_ystride; + hist->reg1.sw_dci_yrgb_gather_num = hist_params->dci_yrgb_gather_num; + hist->reg1.sw_dci_yrgb_gather_en = hist_params->dci_yrgb_gather_en; + hist->reg2.sw_vep_src_pic_width = MPP_ALIGN_DOWN(hist_params->src_width, hsd_sample_num) - 1; + hist->reg2.sw_vep_src_pic_height = MPP_ALIGN_DOWN(hist_params->src_height, vsd_sample_num) - 1; + hist->reg3.sw_dci_data_format = hist_params->dci_format; + hist->reg3.sw_dci_csc_range = hist_params->dci_csc_range; + hist->reg3.sw_dci_vsd_mode = dci_vsd_mode; + hist->reg3.sw_dci_hsd_mode = dci_hsd_mode; + hist->reg3.sw_dci_alpha_swap = hist_params->dci_alpha_swap; + hist->reg3.sw_dci_rb_swap = hist_params->dci_rbuv_swap; + hist->reg3.sw_dci_blk_hsize = sw_dci_blk_hsize; + hist->reg3.sw_dci_blk_vsize = sw_dci_blk_vsize; + hist->reg4.sw_dci_hist_addr = hist_params->hist_addr; + + if (reg_com->reg1.sw_dci_en) { + vdpp_logv("set reg: dci_yrgb_addr(fd)=%d\n", hist->reg0.sw_dci_yrgb_addr); + vdpp_logv("set reg: dci_yrgb_vir_stride=%d [dword], gather_num=%d, gather_en=%d\n", + hist->reg1.sw_dci_yrgb_vir_stride, hist->reg1.sw_dci_yrgb_gather_num, + hist->reg1.sw_dci_yrgb_gather_en); + vdpp_logv("set reg: vep_src pic_width=%d [pixel], pic_height=%d [pixel]\n", + hist->reg2.sw_vep_src_pic_width, hist->reg2.sw_vep_src_pic_height); + vdpp_logv("set reg: dci_data_format=%d, csc_range=%d, vsd_mode=%d, hsd_mode=%d\n", + hist->reg3.sw_dci_data_format, hist->reg3.sw_dci_csc_range, + hist->reg3.sw_dci_vsd_mode, hist->reg3.sw_dci_hsd_mode); + vdpp_logv("set reg: dci_alpha_swap=%d, rb_swap=%d, blk_hsize=%d, blk_vsize=%d\n", + hist->reg3.sw_dci_alpha_swap, hist->reg3.sw_dci_rb_swap, + hist->reg3.sw_dci_blk_hsize, hist->reg3.sw_dci_blk_vsize); + vdpp_logv("set reg: dci_hist_addr(fd)=%d\n", hist->reg4.sw_dci_hist_addr); + } else { + vdpp_logv("set reg: dissable DCI_HIST!\n"); + } +} + +static void update_es_tan(EsParams* p_es_param) +{ + RK_U32 angle_lo_th, angle_hi_th; + + angle_lo_th = 23 - p_es_param->es_iAngleDelta - p_es_param->es_iAngleDeltaExtra; + angle_hi_th = 23 + p_es_param->es_iAngleDelta; + + p_es_param->es_tan_lo_th = mpp_clip(tan(angle_lo_th * acos(-1) / 180.0) * 512, 0, 511); + p_es_param->es_tan_hi_th = mpp_clip(tan(angle_hi_th * acos(-1) / 180.0) * 512, 0, 511); +} + +void set_es_to_vdpp2_reg(EsParams *p_es_param, RegEs *es) +{ + RK_U8 diff2conf_lut_k[8] = {0}; + RK_U8 conf_local_mean_th = 0; + RK_S32 i; + + if (p_es_param->es_iWgtGain > 0) { + conf_local_mean_th = mpp_clip(256 * (float)p_es_param->es_iWgtLocalTh / p_es_param->es_iWgtGain, 0, 255); + } + + update_es_tan(p_es_param); + + es->reg0.es_enable = p_es_param->es_bEnabledES; + es->reg1.dir_th = p_es_param->es_iGradNoDirTh; + es->reg1.flat_th = p_es_param->es_iGradFlatTh; + + es->reg2.tan_lo_th = p_es_param->es_tan_lo_th; + es->reg2.tan_hi_th = p_es_param->es_tan_hi_th; + + es->reg3.ep_chk_en = p_es_param->es_bEndpointCheckEnable; + es->reg3.mem_gat_en = 1; // enable this to reduce power consumption + + es->reg4.diff_gain0 = p_es_param->es_iK1; + es->reg4.diff_limit = p_es_param->es_iDeltaLimit; + + es->reg5.diff_gain1 = p_es_param->es_iK2; + es->reg5.lut_x0 = p_es_param->es_iDiff2conf_lut_x[0]; + + es->reg6.lut_x1 = p_es_param->es_iDiff2conf_lut_x[1]; + es->reg6.lut_x2 = p_es_param->es_iDiff2conf_lut_x[2]; + es->reg7.lut_x3 = p_es_param->es_iDiff2conf_lut_x[3]; + es->reg7.lut_x4 = p_es_param->es_iDiff2conf_lut_x[4]; + es->reg8.lut_x5 = p_es_param->es_iDiff2conf_lut_x[5]; + es->reg8.lut_x6 = p_es_param->es_iDiff2conf_lut_x[6]; + es->reg9.lut_x7 = p_es_param->es_iDiff2conf_lut_x[7]; + es->reg9.lut_x8 = p_es_param->es_iDiff2conf_lut_x[8]; + + es->reg10.lut_y0 = p_es_param->es_iDiff2conf_lut_y[0]; + es->reg10.lut_y1 = p_es_param->es_iDiff2conf_lut_y[1]; + es->reg10.lut_y2 = p_es_param->es_iDiff2conf_lut_y[2]; + es->reg10.lut_y3 = p_es_param->es_iDiff2conf_lut_y[3]; + es->reg11.lut_y4 = p_es_param->es_iDiff2conf_lut_y[4]; + es->reg11.lut_y5 = p_es_param->es_iDiff2conf_lut_y[5]; + es->reg11.lut_y6 = p_es_param->es_iDiff2conf_lut_y[6]; + es->reg11.lut_y7 = p_es_param->es_iDiff2conf_lut_y[7]; + es->reg12.lut_y8 = p_es_param->es_iDiff2conf_lut_y[8]; + + for (i = 0; i < 8; i++) { + double x0 = p_es_param->es_iDiff2conf_lut_x[i]; + double x1 = p_es_param->es_iDiff2conf_lut_x[i + 1]; + double y0 = p_es_param->es_iDiff2conf_lut_y[i]; + double y1 = p_es_param->es_iDiff2conf_lut_y[i + 1]; + + diff2conf_lut_k[i] = mpp_clip(FLOOR(256 * (y1 - y0) / (x1 - x0)), 0, 255); + } + es->reg13.lut_k0 = diff2conf_lut_k[0]; + es->reg13.lut_k1 = diff2conf_lut_k[1]; + es->reg13.lut_k2 = diff2conf_lut_k[2]; + es->reg13.lut_k3 = diff2conf_lut_k[3]; + es->reg14.lut_k4 = diff2conf_lut_k[4]; + es->reg14.lut_k5 = diff2conf_lut_k[5]; + es->reg14.lut_k6 = diff2conf_lut_k[6]; + es->reg14.lut_k7 = diff2conf_lut_k[7]; + + es->reg15.wgt_decay = p_es_param->es_iWgtDecay; + es->reg15.wgt_gain = p_es_param->es_iWgtGain; + + es->reg16.conf_mean_th = conf_local_mean_th; + es->reg16.conf_cnt_th = p_es_param->es_iConfCntTh; + es->reg16.low_conf_th = p_es_param->es_iLowConfTh; + es->reg16.low_conf_ratio = p_es_param->es_iLowConfRatio; +} + +void set_shp_to_vdpp2_reg(ShpParams *p_shp_param, RegShp *shp) +{ + /* Peaking Ctrl sw-process */ + RK_S32 peaking_ctrl_idx_P0[7] = {0}; + RK_S32 peaking_ctrl_idx_N0[7] = {0}; + RK_S32 peaking_ctrl_idx_P1[7] = {0}; + RK_S32 peaking_ctrl_idx_N1[7] = {0}; + RK_S32 peaking_ctrl_idx_P2[7] = {0}; + RK_S32 peaking_ctrl_idx_N2[7] = {0}; + RK_S32 peaking_ctrl_idx_P3[7] = {0}; + RK_S32 peaking_ctrl_idx_N3[7] = {0}; + + RK_S32 peaking_ctrl_value_N1[7] = {0}; + RK_S32 peaking_ctrl_value_N2[7] = {0}; + RK_S32 peaking_ctrl_value_N3[7] = {0}; + RK_S32 peaking_ctrl_value_P1[7] = {0}; + RK_S32 peaking_ctrl_value_P2[7] = {0}; + RK_S32 peaking_ctrl_value_P3[7] = {0}; + + RK_S32 peaking_ctrl_ratio_P01[7] = {0}; + RK_S32 peaking_ctrl_ratio_P12[7] = {0}; + RK_S32 peaking_ctrl_ratio_P23[7] = {0}; + RK_S32 peaking_ctrl_ratio_N01[7] = {0}; + RK_S32 peaking_ctrl_ratio_N12[7] = {0}; + RK_S32 peaking_ctrl_ratio_N23[7] = {0}; + + RK_S32 global_gain_slp_temp[5] = {0}; + RK_S32 ii; + + shp->reg0.sw_sharp_enable = p_shp_param->sharp_enable; + shp->reg0.sw_lti_enable = p_shp_param->lti_h_enable || p_shp_param->lti_v_enable; + shp->reg0.sw_cti_enable = p_shp_param->cti_h_enable; + shp->reg0.sw_peaking_enable = p_shp_param->peaking_enable; + shp->reg0.sw_peaking_ctrl_enable = p_shp_param->peaking_coring_enable || + p_shp_param->peaking_gain_enable || + p_shp_param->peaking_limit_ctrl_enable; + shp->reg0.sw_edge_proc_enable = p_shp_param->peaking_edge_ctrl_enable; + shp->reg0.sw_shoot_ctrl_enable = p_shp_param->shootctrl_enable; + shp->reg0.sw_gain_ctrl_enable = p_shp_param->global_gain_enable; + shp->reg0.sw_color_adj_enable = p_shp_param->color_ctrl_enable; + shp->reg0.sw_texture_adj_enable = p_shp_param->tex_adj_enable; + shp->reg0.sw_coloradj_bypass_en = p_shp_param->sharp_coloradj_bypass_en; + shp->reg0.sw_ink_enable = 0; + shp->reg0.sw_sharp_redundent_bypass = 0; + + if ((shp->reg0.sw_lti_enable == 1) && (p_shp_param->lti_h_enable == 0)) + p_shp_param->lti_h_gain = 0; + + if ((shp->reg0.sw_lti_enable == 1) && (p_shp_param->lti_v_enable == 0)) + p_shp_param->lti_v_gain = 0; + + shp->reg162.sw_ltih_radius = p_shp_param->lti_h_radius; + shp->reg162.sw_ltih_slp1 = p_shp_param->lti_h_slope; + shp->reg162.sw_ltih_thr1 = p_shp_param->lti_h_thresold; + shp->reg163.sw_ltih_noisethrneg = p_shp_param->lti_h_noise_thr_neg; + shp->reg163.sw_ltih_noisethrpos = p_shp_param->lti_h_noise_thr_pos; + shp->reg163.sw_ltih_tigain = p_shp_param->lti_h_gain; + + shp->reg164.sw_ltiv_radius = p_shp_param->lti_v_radius; + shp->reg164.sw_ltiv_slp1 = p_shp_param->lti_v_slope; + shp->reg164.sw_ltiv_thr1 = p_shp_param->lti_v_thresold; + shp->reg165.sw_ltiv_noisethrneg = p_shp_param->lti_v_noise_thr_neg; + shp->reg165.sw_ltiv_noisethrpos = p_shp_param->lti_v_noise_thr_pos; + shp->reg165.sw_ltiv_tigain = p_shp_param->lti_v_gain; + + shp->reg166.sw_ctih_radius = p_shp_param->cti_h_radius; + shp->reg166.sw_ctih_slp1 = p_shp_param->cti_h_slope; + shp->reg166.sw_ctih_thr1 = p_shp_param->cti_h_thresold; + shp->reg167.sw_ctih_noisethrneg = p_shp_param->cti_h_noise_thr_neg; + shp->reg167.sw_ctih_noisethrpos = p_shp_param->cti_h_noise_thr_pos; + shp->reg167.sw_ctih_tigain = p_shp_param->cti_h_gain; + + for (ii = 0; ii < 7; ii++) { + RK_S32 coring_ratio, coring_zero, coring_thr, gain_ctrl_pos, gain_ctrl_neg, limit_ctrl_p0, + limit_ctrl_p1, limit_ctrl_n0, limit_ctrl_n1, limit_ctrl_ratio; + RK_S32 ratio_pos_tmp, ratio_neg_tmp, peaking_ctrl_add_tmp; + + if (p_shp_param->peaking_coring_enable == 1) { + coring_ratio = p_shp_param->peaking_coring_ratio[ii]; + coring_zero = p_shp_param->peaking_coring_zero[ii] >> 2; + coring_thr = p_shp_param->peaking_coring_thr[ii] >> 2; + } else { + coring_ratio = 1024; + coring_zero = 0; + coring_thr = 0; + } + if (p_shp_param->peaking_gain_enable == 1) { + gain_ctrl_pos = p_shp_param->peaking_gain_pos[ii]; + gain_ctrl_neg = p_shp_param->peaking_gain_neg[ii]; + } else { + gain_ctrl_pos = 1024; + gain_ctrl_neg = 1024; + } + if (p_shp_param->peaking_limit_ctrl_enable == 1) { + limit_ctrl_p0 = p_shp_param->peaking_limit_ctrl_pos0[ii] >> 2; + limit_ctrl_p1 = p_shp_param->peaking_limit_ctrl_pos1[ii] >> 2; + limit_ctrl_n0 = p_shp_param->peaking_limit_ctrl_neg0[ii] >> 2; + limit_ctrl_n1 = p_shp_param->peaking_limit_ctrl_neg1[ii] >> 2; + limit_ctrl_ratio = p_shp_param->peaking_limit_ctrl_ratio[ii]; + } else { + limit_ctrl_p0 = 255 >> 2; + limit_ctrl_p1 = 255 >> 2; + limit_ctrl_n0 = 255 >> 2; + limit_ctrl_n1 = 255 >> 2; + limit_ctrl_ratio = 1024; + } + + peaking_ctrl_idx_P0[ii] = coring_zero; + peaking_ctrl_idx_N0[ii] = -coring_zero; + peaking_ctrl_idx_P1[ii] = coring_thr; + peaking_ctrl_idx_N1[ii] = -coring_thr; + peaking_ctrl_idx_P2[ii] = limit_ctrl_p0; + peaking_ctrl_idx_N2[ii] = -limit_ctrl_n0; + peaking_ctrl_idx_P3[ii] = limit_ctrl_p1; + peaking_ctrl_idx_N3[ii] = -limit_ctrl_n1; + + ratio_pos_tmp = (coring_ratio * gain_ctrl_pos + 512) >> 10; + ratio_neg_tmp = (coring_ratio * gain_ctrl_neg + 512) >> 10; + peaking_ctrl_value_P1[ii] = ((ratio_pos_tmp * (coring_thr - coring_zero) + 512) >> 10); + peaking_ctrl_value_N1[ii] = -((ratio_neg_tmp * (coring_thr - coring_zero) + 512) >> 10); + peaking_ctrl_ratio_P01[ii] = ratio_pos_tmp; + peaking_ctrl_ratio_N01[ii] = ratio_neg_tmp; + + peaking_ctrl_ratio_P12[ii] = gain_ctrl_pos; + peaking_ctrl_ratio_N12[ii] = gain_ctrl_neg; + + peaking_ctrl_add_tmp = (gain_ctrl_pos * (limit_ctrl_p0 - coring_thr) + 512) >> 10; + peaking_ctrl_value_P2[ii] = peaking_ctrl_value_P1[ii] + peaking_ctrl_add_tmp; + peaking_ctrl_add_tmp = (gain_ctrl_neg * (limit_ctrl_n0 - coring_thr) + 512) >> 10; + peaking_ctrl_value_N2[ii] = peaking_ctrl_value_N1[ii] - peaking_ctrl_add_tmp; + + ratio_pos_tmp = (limit_ctrl_ratio * gain_ctrl_pos + 512) >> 10; + ratio_neg_tmp = (limit_ctrl_ratio * gain_ctrl_neg + 512) >> 10; + + peaking_ctrl_add_tmp = (ratio_pos_tmp * (limit_ctrl_p1 - limit_ctrl_p0) + 512) >> 10; + peaking_ctrl_value_P3[ii] = peaking_ctrl_value_P2[ii] + peaking_ctrl_add_tmp; + peaking_ctrl_add_tmp = (ratio_neg_tmp * (limit_ctrl_n1 - limit_ctrl_n0) + 512) >> 10; + peaking_ctrl_value_N3[ii] = peaking_ctrl_value_N2[ii] - peaking_ctrl_add_tmp; + peaking_ctrl_ratio_P23[ii] = ratio_pos_tmp; + peaking_ctrl_ratio_N23[ii] = ratio_neg_tmp; + + peaking_ctrl_idx_N0[ii] = mpp_clip(peaking_ctrl_idx_N0[ii], -256, 255); + peaking_ctrl_idx_N1[ii] = mpp_clip(peaking_ctrl_idx_N1[ii], -256, 255); + peaking_ctrl_idx_N2[ii] = mpp_clip(peaking_ctrl_idx_N2[ii], -256, 255); + peaking_ctrl_idx_N3[ii] = mpp_clip(peaking_ctrl_idx_N3[ii], -256, 255); + peaking_ctrl_idx_P0[ii] = mpp_clip(peaking_ctrl_idx_P0[ii], -256, 255); + peaking_ctrl_idx_P1[ii] = mpp_clip(peaking_ctrl_idx_P1[ii], -256, 255); + peaking_ctrl_idx_P2[ii] = mpp_clip(peaking_ctrl_idx_P2[ii], -256, 255); + peaking_ctrl_idx_P3[ii] = mpp_clip(peaking_ctrl_idx_P3[ii], -256, 255); + + peaking_ctrl_value_N1[ii] = mpp_clip(peaking_ctrl_value_N1[ii], -256, 255); + peaking_ctrl_value_N2[ii] = mpp_clip(peaking_ctrl_value_N2[ii], -256, 255); + peaking_ctrl_value_N3[ii] = mpp_clip(peaking_ctrl_value_N3[ii], -256, 255); + peaking_ctrl_value_P1[ii] = mpp_clip(peaking_ctrl_value_P1[ii], -256, 255); + peaking_ctrl_value_P2[ii] = mpp_clip(peaking_ctrl_value_P2[ii], -256, 255); + peaking_ctrl_value_P3[ii] = mpp_clip(peaking_ctrl_value_P3[ii], -256, 255); + + peaking_ctrl_ratio_P01[ii] = mpp_clip(peaking_ctrl_ratio_P01[ii], 0, 4095); + peaking_ctrl_ratio_P12[ii] = mpp_clip(peaking_ctrl_ratio_P12[ii], 0, 4095); + peaking_ctrl_ratio_P23[ii] = mpp_clip(peaking_ctrl_ratio_P23[ii], 0, 4095); + peaking_ctrl_ratio_N01[ii] = mpp_clip(peaking_ctrl_ratio_N01[ii], 0, 4095); + peaking_ctrl_ratio_N12[ii] = mpp_clip(peaking_ctrl_ratio_N12[ii], 0, 4095); + peaking_ctrl_ratio_N23[ii] = mpp_clip(peaking_ctrl_ratio_N23[ii], 0, 4095); + } + + shp->reg12.sw_peaking0_idx_n0 = peaking_ctrl_idx_N0[0]; + shp->reg12.sw_peaking0_idx_n1 = peaking_ctrl_idx_N1[0]; + shp->reg13.sw_peaking0_idx_n2 = peaking_ctrl_idx_N2[0]; + shp->reg13.sw_peaking0_idx_n3 = peaking_ctrl_idx_N3[0]; + shp->reg14.sw_peaking0_idx_p0 = peaking_ctrl_idx_P0[0]; + shp->reg14.sw_peaking0_idx_p1 = peaking_ctrl_idx_P1[0]; + shp->reg15.sw_peaking0_idx_p2 = peaking_ctrl_idx_P2[0]; + shp->reg15.sw_peaking0_idx_p3 = peaking_ctrl_idx_P3[0]; + shp->reg16.sw_peaking0_value_n1 = peaking_ctrl_value_N1[0]; + shp->reg16.sw_peaking0_value_n2 = peaking_ctrl_value_N2[0]; + shp->reg17.sw_peaking0_value_n3 = peaking_ctrl_value_N3[0]; + shp->reg17.sw_peaking0_value_p1 = peaking_ctrl_value_P1[0]; + shp->reg18.sw_peaking0_value_p2 = peaking_ctrl_value_P2[0]; + shp->reg18.sw_peaking0_value_p3 = peaking_ctrl_value_P3[0]; + shp->reg19.sw_peaking0_ratio_n01 = peaking_ctrl_ratio_N01[0]; + shp->reg19.sw_peaking0_ratio_n12 = peaking_ctrl_ratio_N12[0]; + shp->reg20.sw_peaking0_ratio_n23 = peaking_ctrl_ratio_N23[0]; + shp->reg20.sw_peaking0_ratio_p01 = peaking_ctrl_ratio_P01[0]; + shp->reg21.sw_peaking0_ratio_p12 = peaking_ctrl_ratio_P12[0]; + shp->reg21.sw_peaking0_ratio_p23 = peaking_ctrl_ratio_P23[0]; + + shp->reg23.sw_peaking1_idx_n0 = peaking_ctrl_idx_N0[1]; + shp->reg23.sw_peaking1_idx_n1 = peaking_ctrl_idx_N1[1]; + shp->reg24.sw_peaking1_idx_n2 = peaking_ctrl_idx_N2[1]; + shp->reg24.sw_peaking1_idx_n3 = peaking_ctrl_idx_N3[1]; + shp->reg25.sw_peaking1_idx_p0 = peaking_ctrl_idx_P0[1]; + shp->reg25.sw_peaking1_idx_p1 = peaking_ctrl_idx_P1[1]; + shp->reg26.sw_peaking1_idx_p2 = peaking_ctrl_idx_P2[1]; + shp->reg26.sw_peaking1_idx_p3 = peaking_ctrl_idx_P3[1]; + shp->reg27.sw_peaking1_value_n1 = peaking_ctrl_value_N1[1]; + shp->reg27.sw_peaking1_value_n2 = peaking_ctrl_value_N2[1]; + shp->reg28.sw_peaking1_value_n3 = peaking_ctrl_value_N3[1]; + shp->reg28.sw_peaking1_value_p1 = peaking_ctrl_value_P1[1]; + shp->reg29.sw_peaking1_value_p2 = peaking_ctrl_value_P2[1]; + shp->reg29.sw_peaking1_value_p3 = peaking_ctrl_value_P3[1]; + shp->reg30.sw_peaking1_ratio_n01 = peaking_ctrl_ratio_N01[1]; + shp->reg30.sw_peaking1_ratio_n12 = peaking_ctrl_ratio_N12[1]; + shp->reg31.sw_peaking1_ratio_n23 = peaking_ctrl_ratio_N23[1]; + shp->reg31.sw_peaking1_ratio_p01 = peaking_ctrl_ratio_P01[1]; + shp->reg32.sw_peaking1_ratio_p12 = peaking_ctrl_ratio_P12[1]; + shp->reg32.sw_peaking1_ratio_p23 = peaking_ctrl_ratio_P23[1]; + + shp->reg34.sw_peaking2_idx_n0 = peaking_ctrl_idx_N0[2]; + shp->reg34.sw_peaking2_idx_n1 = peaking_ctrl_idx_N1[2]; + shp->reg35.sw_peaking2_idx_n2 = peaking_ctrl_idx_N2[2]; + shp->reg35.sw_peaking2_idx_n3 = peaking_ctrl_idx_N3[2]; + shp->reg36.sw_peaking2_idx_p0 = peaking_ctrl_idx_P0[2]; + shp->reg36.sw_peaking2_idx_p1 = peaking_ctrl_idx_P1[2]; + shp->reg37.sw_peaking2_idx_p2 = peaking_ctrl_idx_P2[2]; + shp->reg37.sw_peaking2_idx_p3 = peaking_ctrl_idx_P3[2]; + shp->reg38.sw_peaking2_value_n1 = peaking_ctrl_value_N1[2]; + shp->reg38.sw_peaking2_value_n2 = peaking_ctrl_value_N2[2]; + shp->reg39.sw_peaking2_value_n3 = peaking_ctrl_value_N3[2]; + shp->reg39.sw_peaking2_value_p1 = peaking_ctrl_value_P1[2]; + shp->reg40.sw_peaking2_value_p2 = peaking_ctrl_value_P2[2]; + shp->reg40.sw_peaking2_value_p3 = peaking_ctrl_value_P3[2]; + shp->reg41.sw_peaking2_ratio_n01 = peaking_ctrl_ratio_N01[2]; + shp->reg41.sw_peaking2_ratio_n12 = peaking_ctrl_ratio_N12[2]; + shp->reg42.sw_peaking2_ratio_n23 = peaking_ctrl_ratio_N23[2]; + shp->reg42.sw_peaking2_ratio_p01 = peaking_ctrl_ratio_P01[2]; + shp->reg43.sw_peaking2_ratio_p12 = peaking_ctrl_ratio_P12[2]; + shp->reg43.sw_peaking2_ratio_p23 = peaking_ctrl_ratio_P23[2]; + + shp->reg45.sw_peaking3_idx_n0 = peaking_ctrl_idx_N0[3]; + shp->reg45.sw_peaking3_idx_n1 = peaking_ctrl_idx_N1[3]; + shp->reg46.sw_peaking3_idx_n2 = peaking_ctrl_idx_N2[3]; + shp->reg46.sw_peaking3_idx_n3 = peaking_ctrl_idx_N3[3]; + shp->reg47.sw_peaking3_idx_p0 = peaking_ctrl_idx_P0[3]; + shp->reg47.sw_peaking3_idx_p1 = peaking_ctrl_idx_P1[3]; + shp->reg48.sw_peaking3_idx_p2 = peaking_ctrl_idx_P2[3]; + shp->reg48.sw_peaking3_idx_p3 = peaking_ctrl_idx_P3[3]; + shp->reg49.sw_peaking3_value_n1 = peaking_ctrl_value_N1[3]; + shp->reg49.sw_peaking3_value_n2 = peaking_ctrl_value_N2[3]; + shp->reg50.sw_peaking3_value_n3 = peaking_ctrl_value_N3[3]; + shp->reg50.sw_peaking3_value_p1 = peaking_ctrl_value_P1[3]; + shp->reg51.sw_peaking3_value_p2 = peaking_ctrl_value_P2[3]; + shp->reg51.sw_peaking3_value_p3 = peaking_ctrl_value_P3[3]; + shp->reg52.sw_peaking3_ratio_n01 = peaking_ctrl_ratio_N01[3]; + shp->reg52.sw_peaking3_ratio_n12 = peaking_ctrl_ratio_N12[3]; + shp->reg53.sw_peaking3_ratio_n23 = peaking_ctrl_ratio_N23[3]; + shp->reg53.sw_peaking3_ratio_p01 = peaking_ctrl_ratio_P01[3]; + shp->reg54.sw_peaking3_ratio_p12 = peaking_ctrl_ratio_P12[3]; + shp->reg54.sw_peaking3_ratio_p23 = peaking_ctrl_ratio_P23[3]; + + shp->reg56.sw_peaking4_idx_n0 = peaking_ctrl_idx_N0[4]; + shp->reg56.sw_peaking4_idx_n1 = peaking_ctrl_idx_N1[4]; + shp->reg57.sw_peaking4_idx_n2 = peaking_ctrl_idx_N2[4]; + shp->reg57.sw_peaking4_idx_n3 = peaking_ctrl_idx_N3[4]; + shp->reg58.sw_peaking4_idx_p0 = peaking_ctrl_idx_P0[4]; + shp->reg58.sw_peaking4_idx_p1 = peaking_ctrl_idx_P1[4]; + shp->reg59.sw_peaking4_idx_p2 = peaking_ctrl_idx_P2[4]; + shp->reg59.sw_peaking4_idx_p3 = peaking_ctrl_idx_P3[4]; + shp->reg60.sw_peaking4_value_n1 = peaking_ctrl_value_N1[4]; + shp->reg60.sw_peaking4_value_n2 = peaking_ctrl_value_N2[4]; + shp->reg61.sw_peaking4_value_n3 = peaking_ctrl_value_N3[4]; + shp->reg61.sw_peaking4_value_p1 = peaking_ctrl_value_P1[4]; + shp->reg62.sw_peaking4_value_p2 = peaking_ctrl_value_P2[4]; + shp->reg62.sw_peaking4_value_p3 = peaking_ctrl_value_P3[4]; + shp->reg63.sw_peaking4_ratio_n01 = peaking_ctrl_ratio_N01[4]; + shp->reg63.sw_peaking4_ratio_n12 = peaking_ctrl_ratio_N12[4]; + shp->reg64.sw_peaking4_ratio_n23 = peaking_ctrl_ratio_N23[4]; + shp->reg64.sw_peaking4_ratio_p01 = peaking_ctrl_ratio_P01[4]; + shp->reg65.sw_peaking4_ratio_p12 = peaking_ctrl_ratio_P12[4]; + shp->reg65.sw_peaking4_ratio_p23 = peaking_ctrl_ratio_P23[4]; + + shp->reg67.sw_peaking5_idx_n0 = peaking_ctrl_idx_N0[5]; + shp->reg67.sw_peaking5_idx_n1 = peaking_ctrl_idx_N1[5]; + shp->reg68.sw_peaking5_idx_n2 = peaking_ctrl_idx_N2[5]; + shp->reg68.sw_peaking5_idx_n3 = peaking_ctrl_idx_N3[5]; + shp->reg69.sw_peaking5_idx_p0 = peaking_ctrl_idx_P0[5]; + shp->reg69.sw_peaking5_idx_p1 = peaking_ctrl_idx_P1[5]; + shp->reg70.sw_peaking5_idx_p2 = peaking_ctrl_idx_P2[5]; + shp->reg70.sw_peaking5_idx_p3 = peaking_ctrl_idx_P3[5]; + shp->reg71.sw_peaking5_value_n1 = peaking_ctrl_value_N1[5]; + shp->reg71.sw_peaking5_value_n2 = peaking_ctrl_value_N2[5]; + shp->reg72.sw_peaking5_value_n3 = peaking_ctrl_value_N3[5]; + shp->reg72.sw_peaking5_value_p1 = peaking_ctrl_value_P1[5]; + shp->reg73.sw_peaking5_value_p2 = peaking_ctrl_value_P2[5]; + shp->reg73.sw_peaking5_value_p3 = peaking_ctrl_value_P3[5]; + shp->reg74.sw_peaking5_ratio_n01 = peaking_ctrl_ratio_N01[5]; + shp->reg74.sw_peaking5_ratio_n12 = peaking_ctrl_ratio_N12[5]; + shp->reg75.sw_peaking5_ratio_n23 = peaking_ctrl_ratio_N23[5]; + shp->reg75.sw_peaking5_ratio_p01 = peaking_ctrl_ratio_P01[5]; + shp->reg76.sw_peaking5_ratio_p12 = peaking_ctrl_ratio_P12[5]; + shp->reg76.sw_peaking5_ratio_p23 = peaking_ctrl_ratio_P23[5]; + + shp->reg78.sw_peaking6_idx_n0 = peaking_ctrl_idx_N0[6]; + shp->reg78.sw_peaking6_idx_n1 = peaking_ctrl_idx_N1[6]; + shp->reg79.sw_peaking6_idx_n2 = peaking_ctrl_idx_N2[6]; + shp->reg79.sw_peaking6_idx_n3 = peaking_ctrl_idx_N3[6]; + shp->reg80.sw_peaking6_idx_p0 = peaking_ctrl_idx_P0[6]; + shp->reg80.sw_peaking6_idx_p1 = peaking_ctrl_idx_P1[6]; + shp->reg81.sw_peaking6_idx_p2 = peaking_ctrl_idx_P2[6]; + shp->reg81.sw_peaking6_idx_p3 = peaking_ctrl_idx_P3[6]; + shp->reg82.sw_peaking6_value_n1 = peaking_ctrl_value_N1[6]; + shp->reg82.sw_peaking6_value_n2 = peaking_ctrl_value_N2[6]; + shp->reg83.sw_peaking6_value_n3 = peaking_ctrl_value_N3[6]; + shp->reg83.sw_peaking6_value_p1 = peaking_ctrl_value_P1[6]; + shp->reg84.sw_peaking6_value_p2 = peaking_ctrl_value_P2[6]; + shp->reg84.sw_peaking6_value_p3 = peaking_ctrl_value_P3[6]; + shp->reg85.sw_peaking6_ratio_n01 = peaking_ctrl_ratio_N01[6]; + shp->reg85.sw_peaking6_ratio_n12 = peaking_ctrl_ratio_N12[6]; + shp->reg86.sw_peaking6_ratio_n23 = peaking_ctrl_ratio_N23[6]; + shp->reg86.sw_peaking6_ratio_p01 = peaking_ctrl_ratio_P01[6]; + shp->reg87.sw_peaking6_ratio_p12 = peaking_ctrl_ratio_P12[6]; + shp->reg87.sw_peaking6_ratio_p23 = peaking_ctrl_ratio_P23[6]; + + shp->reg2.sw_peaking_v00 = p_shp_param->peaking_filt_core_V0[0]; + shp->reg2.sw_peaking_v01 = p_shp_param->peaking_filt_core_V0[1]; + shp->reg2.sw_peaking_v02 = p_shp_param->peaking_filt_core_V0[2]; + shp->reg2.sw_peaking_v10 = p_shp_param->peaking_filt_core_V1[0]; + shp->reg2.sw_peaking_v11 = p_shp_param->peaking_filt_core_V1[1]; + shp->reg2.sw_peaking_v12 = p_shp_param->peaking_filt_core_V1[2]; + shp->reg3.sw_peaking_v20 = p_shp_param->peaking_filt_core_V2[0]; + shp->reg3.sw_peaking_v21 = p_shp_param->peaking_filt_core_V2[1]; + shp->reg3.sw_peaking_v22 = p_shp_param->peaking_filt_core_V2[2]; + shp->reg3.sw_peaking_usm0 = p_shp_param->peaking_filt_core_USM[0]; + shp->reg3.sw_peaking_usm1 = p_shp_param->peaking_filt_core_USM[1]; + shp->reg3.sw_peaking_usm2 = p_shp_param->peaking_filt_core_USM[2]; + shp->reg3.sw_diag_coef = p_shp_param->peaking_filter_cfg_diag_enh_coef; + shp->reg4.sw_peaking_h00 = p_shp_param->peaking_filt_core_H0[0]; + shp->reg4.sw_peaking_h01 = p_shp_param->peaking_filt_core_H0[1]; + shp->reg4.sw_peaking_h02 = p_shp_param->peaking_filt_core_H0[2]; + shp->reg6.sw_peaking_h10 = p_shp_param->peaking_filt_core_H1[0]; + shp->reg6.sw_peaking_h11 = p_shp_param->peaking_filt_core_H1[1]; + shp->reg6.sw_peaking_h12 = p_shp_param->peaking_filt_core_H1[2]; + shp->reg8.sw_peaking_h20 = p_shp_param->peaking_filt_core_H2[0]; + shp->reg8.sw_peaking_h21 = p_shp_param->peaking_filt_core_H2[1]; + shp->reg8.sw_peaking_h22 = p_shp_param->peaking_filt_core_H2[2]; + + shp->reg100.sw_peaking_gain = p_shp_param->peaking_gain; + shp->reg100.sw_nondir_thr = p_shp_param->peaking_edge_ctrl_non_dir_thr; + shp->reg100.sw_dir_cmp_ratio = p_shp_param->peaking_edge_ctrl_dir_cmp_ratio; + shp->reg100.sw_nondir_wgt_ratio = p_shp_param->peaking_edge_ctrl_non_dir_wgt_ratio; + shp->reg101.sw_nondir_wgt_offset = p_shp_param->peaking_edge_ctrl_non_dir_wgt_offset; + shp->reg101.sw_dir_cnt_thr = p_shp_param->peaking_edge_ctrl_dir_cnt_thr; + shp->reg101.sw_dir_cnt_avg = p_shp_param->peaking_edge_ctrl_dir_cnt_avg; + shp->reg101.sw_dir_cnt_offset = p_shp_param->peaking_edge_ctrl_dir_cnt_offset; + shp->reg101.sw_diag_dir_thr = p_shp_param->peaking_edge_ctrl_diag_dir_thr; + shp->reg102.sw_diag_adjgain_tab0 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[0]; + shp->reg102.sw_diag_adjgain_tab1 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[1]; + shp->reg102.sw_diag_adjgain_tab2 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[2]; + shp->reg102.sw_diag_adjgain_tab3 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[3]; + shp->reg102.sw_diag_adjgain_tab4 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[4]; + shp->reg102.sw_diag_adjgain_tab5 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[5]; + shp->reg102.sw_diag_adjgain_tab6 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[6]; + shp->reg102.sw_diag_adjgain_tab7 = p_shp_param->peaking_edge_ctrl_diag_adj_gain_tab[7]; + + shp->reg103.sw_edge_alpha_over_non = p_shp_param->peaking_estc_alpha_over_non; + shp->reg103.sw_edge_alpha_under_non = p_shp_param->peaking_estc_alpha_under_non; + shp->reg103.sw_edge_alpha_over_unlimit_non = p_shp_param->peaking_estc_alpha_over_unlimit_non; + shp->reg103.sw_edge_alpha_under_unlimit_non = p_shp_param->peaking_estc_alpha_under_unlimit_non; + + shp->reg104.sw_edge_alpha_over_v = p_shp_param->peaking_estc_alpha_over_v; + shp->reg104.sw_edge_alpha_under_v = p_shp_param->peaking_estc_alpha_under_v; + shp->reg104.sw_edge_alpha_over_unlimit_v = p_shp_param->peaking_estc_alpha_over_unlimit_v; + shp->reg104.sw_edge_alpha_under_unlimit_v = p_shp_param->peaking_estc_alpha_under_unlimit_v; + + shp->reg105.sw_edge_alpha_over_h = p_shp_param->peaking_estc_alpha_over_h; + shp->reg105.sw_edge_alpha_under_h = p_shp_param->peaking_estc_alpha_under_h; + shp->reg105.sw_edge_alpha_over_unlimit_h = p_shp_param->peaking_estc_alpha_over_unlimit_h; + shp->reg105.sw_edge_alpha_under_unlimit_h = p_shp_param->peaking_estc_alpha_under_unlimit_h; + + shp->reg106.sw_edge_alpha_over_d0 = p_shp_param->peaking_estc_alpha_over_d0; + shp->reg106.sw_edge_alpha_under_d0 = p_shp_param->peaking_estc_alpha_under_d0; + shp->reg106.sw_edge_alpha_over_unlimit_d0 = p_shp_param->peaking_estc_alpha_over_unlimit_d0; + shp->reg106.sw_edge_alpha_under_unlimit_d0 = p_shp_param->peaking_estc_alpha_under_unlimit_d0; + + shp->reg107.sw_edge_alpha_over_d1 = p_shp_param->peaking_estc_alpha_over_d1; + shp->reg107.sw_edge_alpha_under_d1 = p_shp_param->peaking_estc_alpha_under_d1; + shp->reg107.sw_edge_alpha_over_unlimit_d1 = p_shp_param->peaking_estc_alpha_over_unlimit_d1; + shp->reg107.sw_edge_alpha_under_unlimit_d1 = p_shp_param->peaking_estc_alpha_under_unlimit_d1; + + shp->reg108.sw_edge_delta_offset_non = p_shp_param->peaking_estc_delta_offset_non; + shp->reg108.sw_edge_delta_offset_v = p_shp_param->peaking_estc_delta_offset_v; + shp->reg108.sw_edge_delta_offset_h = p_shp_param->peaking_estc_delta_offset_h; + shp->reg109.sw_edge_delta_offset_d0 = p_shp_param->peaking_estc_delta_offset_d0; + shp->reg109.sw_edge_delta_offset_d1 = p_shp_param->peaking_estc_delta_offset_d1; + + shp->reg110.sw_shoot_filt_radius = p_shp_param->shootctrl_filter_radius; + shp->reg110.sw_shoot_delta_offset = p_shp_param->shootctrl_delta_offset; + shp->reg110.sw_shoot_alpha_over = p_shp_param->shootctrl_alpha_over; + shp->reg110.sw_shoot_alpha_under = p_shp_param->shootctrl_alpha_under; + shp->reg111.sw_shoot_alpha_over_unlimit = p_shp_param->shootctrl_alpha_over_unlimit; + shp->reg111.sw_shoot_alpha_under_unlimit = p_shp_param->shootctrl_alpha_under_unlimit; + + //dst_reg->sharp.reg112.sw_adp_idx0 = p_shp_param->global_gain_adp_grd + shp->reg112.sw_adp_idx0 = p_shp_param->global_gain_adp_grd[1] >> 2; + shp->reg112.sw_adp_idx1 = p_shp_param->global_gain_adp_grd[2] >> 2; + shp->reg112.sw_adp_idx2 = p_shp_param->global_gain_adp_grd[3] >> 2; + shp->reg113.sw_adp_idx3 = p_shp_param->global_gain_adp_grd[4] >> 2; + shp->reg113.sw_adp_gain0 = p_shp_param->global_gain_adp_val[0]; + shp->reg113.sw_adp_gain1 = p_shp_param->global_gain_adp_val[1]; + shp->reg114.sw_adp_gain2 = p_shp_param->global_gain_adp_val[2]; + shp->reg114.sw_adp_gain3 = p_shp_param->global_gain_adp_val[3]; + shp->reg114.sw_adp_gain4 = p_shp_param->global_gain_adp_val[4]; + global_gain_slp_temp[0] = ROUND(128 * (float)(shp->reg113.sw_adp_gain1 - shp->reg113.sw_adp_gain0) / + MPP_MAX((float)(shp->reg112.sw_adp_idx0 - 0), 1)); + global_gain_slp_temp[1] = ROUND(128 * (float)(shp->reg114.sw_adp_gain2 - shp->reg113.sw_adp_gain1) / + MPP_MAX((float)(shp->reg112.sw_adp_idx1 - shp->reg112.sw_adp_idx0), 1)); + global_gain_slp_temp[2] = ROUND(128 * (float)(shp->reg114.sw_adp_gain3 - shp->reg114.sw_adp_gain2) / + MPP_MAX((float)(shp->reg112.sw_adp_idx2 - shp->reg112.sw_adp_idx1), 1)); + global_gain_slp_temp[3] = ROUND(128 * (float)(shp->reg114.sw_adp_gain4 - shp->reg114.sw_adp_gain3) / + MPP_MAX((float)(shp->reg113.sw_adp_idx3 - shp->reg112.sw_adp_idx2), 1)); + global_gain_slp_temp[4] = ROUND(128 * (float)(p_shp_param->global_gain_adp_val[5] - shp->reg114.sw_adp_gain4) / + MPP_MAX((float)(255 - shp->reg113.sw_adp_idx3), 1)); + shp->reg115.sw_adp_slp01 = mpp_clip(global_gain_slp_temp[0], -1024, 1023); + shp->reg115.sw_adp_slp12 = mpp_clip(global_gain_slp_temp[1], -1024, 1023); + shp->reg128.sw_adp_slp23 = mpp_clip(global_gain_slp_temp[2], -1024, 1023); + shp->reg128.sw_adp_slp34 = mpp_clip(global_gain_slp_temp[3], -1024, 1023); + shp->reg129.sw_adp_slp45 = mpp_clip(global_gain_slp_temp[4], -1024, 1023); + + shp->reg129.sw_var_idx0 = p_shp_param->global_gain_var_grd[1] >> 2; + shp->reg129.sw_var_idx1 = p_shp_param->global_gain_var_grd[2] >> 2; + shp->reg130.sw_var_idx2 = p_shp_param->global_gain_var_grd[3] >> 2; + shp->reg130.sw_var_idx3 = p_shp_param->global_gain_var_grd[4] >> 2; + shp->reg130.sw_var_gain0 = p_shp_param->global_gain_var_val[0]; + shp->reg131.sw_var_gain1 = p_shp_param->global_gain_var_val[1]; + shp->reg131.sw_var_gain2 = p_shp_param->global_gain_var_val[2]; + shp->reg131.sw_var_gain3 = p_shp_param->global_gain_var_val[3]; + shp->reg131.sw_var_gain4 = p_shp_param->global_gain_var_val[4]; + global_gain_slp_temp[0] = ROUND(128 * (float)(shp->reg131.sw_var_gain1 - shp->reg130.sw_var_gain0) / + MPP_MAX((float)(shp->reg129.sw_var_idx0 - 0), 1)); + global_gain_slp_temp[1] = ROUND(128 * (float)(shp->reg131.sw_var_gain2 - shp->reg131.sw_var_gain1) / + MPP_MAX((float)(shp->reg129.sw_var_idx1 - shp->reg129.sw_var_idx0), 1)); + global_gain_slp_temp[2] = ROUND(128 * (float)(shp->reg131.sw_var_gain3 - shp->reg131.sw_var_gain2) / + MPP_MAX((float)(shp->reg130.sw_var_idx2 - shp->reg129.sw_var_idx1), 1)); + global_gain_slp_temp[3] = ROUND(128 * (float)(shp->reg131.sw_var_gain4 - shp->reg131.sw_var_gain3) / + MPP_MAX((float)(shp->reg130.sw_var_idx3 - shp->reg130.sw_var_idx2), 1)); + global_gain_slp_temp[4] = ROUND(128 * (float)(p_shp_param->global_gain_var_val[5] - shp->reg131.sw_var_gain4) / + MPP_MAX((float)(255 - shp->reg130.sw_var_idx3), 1)); + shp->reg132.sw_var_slp01 = mpp_clip(global_gain_slp_temp[0], -1024, 1023); + shp->reg132.sw_var_slp12 = mpp_clip(global_gain_slp_temp[1], -1024, 1023); + shp->reg133.sw_var_slp23 = mpp_clip(global_gain_slp_temp[2], -1024, 1023); + shp->reg133.sw_var_slp34 = mpp_clip(global_gain_slp_temp[3], -1024, 1023); + shp->reg134.sw_var_slp45 = mpp_clip(global_gain_slp_temp[4], -1024, 1023); + + shp->reg134.sw_lum_select = p_shp_param->global_gain_lum_mode; + shp->reg134.sw_lum_idx0 = p_shp_param->global_gain_lum_grd[1] >> 2; + shp->reg135.sw_lum_idx1 = p_shp_param->global_gain_lum_grd[2] >> 2; + shp->reg135.sw_lum_idx2 = p_shp_param->global_gain_lum_grd[3] >> 2; + shp->reg135.sw_lum_idx3 = p_shp_param->global_gain_lum_grd[4] >> 2; + shp->reg136.sw_lum_gain0 = p_shp_param->global_gain_lum_val[0]; + shp->reg136.sw_lum_gain1 = p_shp_param->global_gain_lum_val[1]; + shp->reg136.sw_lum_gain2 = p_shp_param->global_gain_lum_val[2]; + shp->reg136.sw_lum_gain3 = p_shp_param->global_gain_lum_val[3]; + shp->reg137.sw_lum_gain4 = p_shp_param->global_gain_lum_val[4]; + global_gain_slp_temp[0] = ROUND(128 * (float)(shp->reg136.sw_lum_gain1 - shp->reg136.sw_lum_gain0) / + MPP_MAX((float)(shp->reg134.sw_lum_idx0 - 0), 1)); + global_gain_slp_temp[1] = ROUND(128 * (float)(shp->reg136.sw_lum_gain2 - shp->reg136.sw_lum_gain1) / + MPP_MAX((float)(shp->reg135.sw_lum_idx1 - shp->reg134.sw_lum_idx0), 1)); + global_gain_slp_temp[2] = ROUND(128 * (float)(shp->reg136.sw_lum_gain3 - shp->reg136.sw_lum_gain2) / + MPP_MAX((float)(shp->reg135.sw_lum_idx2 - shp->reg135.sw_lum_idx1), 1)); + global_gain_slp_temp[3] = ROUND(128 * (float)(shp->reg137.sw_lum_gain4 - shp->reg136.sw_lum_gain3) / + MPP_MAX((float)(shp->reg135.sw_lum_idx3 - shp->reg135.sw_lum_idx2), 1)); + global_gain_slp_temp[4] = ROUND(128 * (float)(p_shp_param->global_gain_lum_val[5] - shp->reg137.sw_lum_gain4) / + MPP_MAX((float)(255 - shp->reg135.sw_lum_idx3), 1)); + shp->reg137.sw_lum_slp01 = mpp_clip(global_gain_slp_temp[0], -1024, 1023); + shp->reg137.sw_lum_slp12 = mpp_clip(global_gain_slp_temp[1], -1024, 1023); + shp->reg138.sw_lum_slp23 = mpp_clip(global_gain_slp_temp[2], -1024, 1023); + shp->reg138.sw_lum_slp34 = mpp_clip(global_gain_slp_temp[3], -1024, 1023); + shp->reg139.sw_lum_slp45 = mpp_clip(global_gain_slp_temp[4], -1024, 1023); + + + shp->reg140.sw_adj_point_x0 = p_shp_param->color_ctrl_p0_point_u; + shp->reg140.sw_adj_point_y0 = p_shp_param->color_ctrl_p0_point_v; + shp->reg140.sw_adj_scaling_coef0 = p_shp_param->color_ctrl_p0_scaling_coef; + shp->reg141.sw_coloradj_tab0_0 = p_shp_param->color_ctrl_p0_roll_tab[0]; + shp->reg141.sw_coloradj_tab0_1 = p_shp_param->color_ctrl_p0_roll_tab[1]; + shp->reg141.sw_coloradj_tab0_2 = p_shp_param->color_ctrl_p0_roll_tab[2]; + shp->reg141.sw_coloradj_tab0_3 = p_shp_param->color_ctrl_p0_roll_tab[3]; + shp->reg141.sw_coloradj_tab0_4 = p_shp_param->color_ctrl_p0_roll_tab[4]; + shp->reg141.sw_coloradj_tab0_5 = p_shp_param->color_ctrl_p0_roll_tab[5]; + shp->reg142.sw_coloradj_tab0_6 = p_shp_param->color_ctrl_p0_roll_tab[6]; + shp->reg142.sw_coloradj_tab0_7 = p_shp_param->color_ctrl_p0_roll_tab[7]; + shp->reg142.sw_coloradj_tab0_8 = p_shp_param->color_ctrl_p0_roll_tab[8]; + shp->reg142.sw_coloradj_tab0_9 = p_shp_param->color_ctrl_p0_roll_tab[9]; + shp->reg142.sw_coloradj_tab0_10 = p_shp_param->color_ctrl_p0_roll_tab[10]; + shp->reg142.sw_coloradj_tab0_11 = p_shp_param->color_ctrl_p0_roll_tab[11]; + shp->reg143.sw_coloradj_tab0_12 = p_shp_param->color_ctrl_p0_roll_tab[12]; + shp->reg143.sw_coloradj_tab0_13 = p_shp_param->color_ctrl_p0_roll_tab[13]; + shp->reg143.sw_coloradj_tab0_14 = p_shp_param->color_ctrl_p0_roll_tab[14]; + shp->reg143.sw_coloradj_tab0_15 = p_shp_param->color_ctrl_p0_roll_tab[15]; + + shp->reg144.sw_adj_point_x1 = p_shp_param->color_ctrl_p1_point_u; + shp->reg144.sw_adj_point_y1 = p_shp_param->color_ctrl_p1_point_v; + shp->reg144.sw_adj_scaling_coef1 = p_shp_param->color_ctrl_p1_scaling_coef; + shp->reg145.sw_coloradj_tab1_0 = p_shp_param->color_ctrl_p1_roll_tab[0]; + shp->reg145.sw_coloradj_tab1_1 = p_shp_param->color_ctrl_p1_roll_tab[1]; + shp->reg145.sw_coloradj_tab1_2 = p_shp_param->color_ctrl_p1_roll_tab[2]; + shp->reg145.sw_coloradj_tab1_3 = p_shp_param->color_ctrl_p1_roll_tab[3]; + shp->reg145.sw_coloradj_tab1_4 = p_shp_param->color_ctrl_p1_roll_tab[4]; + shp->reg145.sw_coloradj_tab1_5 = p_shp_param->color_ctrl_p1_roll_tab[5]; + shp->reg146.sw_coloradj_tab1_6 = p_shp_param->color_ctrl_p1_roll_tab[6]; + shp->reg146.sw_coloradj_tab1_7 = p_shp_param->color_ctrl_p1_roll_tab[7]; + shp->reg146.sw_coloradj_tab1_8 = p_shp_param->color_ctrl_p1_roll_tab[8]; + shp->reg146.sw_coloradj_tab1_9 = p_shp_param->color_ctrl_p1_roll_tab[9]; + shp->reg146.sw_coloradj_tab1_10 = p_shp_param->color_ctrl_p1_roll_tab[10]; + shp->reg146.sw_coloradj_tab1_11 = p_shp_param->color_ctrl_p1_roll_tab[11]; + shp->reg147.sw_coloradj_tab1_12 = p_shp_param->color_ctrl_p1_roll_tab[12]; + shp->reg147.sw_coloradj_tab1_13 = p_shp_param->color_ctrl_p1_roll_tab[13]; + shp->reg147.sw_coloradj_tab1_14 = p_shp_param->color_ctrl_p1_roll_tab[14]; + shp->reg147.sw_coloradj_tab1_15 = p_shp_param->color_ctrl_p1_roll_tab[15]; + + shp->reg148.sw_adj_point_x2 = p_shp_param->color_ctrl_p2_point_u; + shp->reg148.sw_adj_point_y2 = p_shp_param->color_ctrl_p2_point_v; + shp->reg148.sw_adj_scaling_coef2 = p_shp_param->color_ctrl_p2_scaling_coef; + shp->reg149.sw_coloradj_tab2_0 = p_shp_param->color_ctrl_p2_roll_tab[0]; + shp->reg149.sw_coloradj_tab2_1 = p_shp_param->color_ctrl_p2_roll_tab[1]; + shp->reg149.sw_coloradj_tab2_2 = p_shp_param->color_ctrl_p2_roll_tab[2]; + shp->reg149.sw_coloradj_tab2_3 = p_shp_param->color_ctrl_p2_roll_tab[3]; + shp->reg149.sw_coloradj_tab2_4 = p_shp_param->color_ctrl_p2_roll_tab[4]; + shp->reg149.sw_coloradj_tab2_5 = p_shp_param->color_ctrl_p2_roll_tab[5]; + shp->reg150.sw_coloradj_tab2_6 = p_shp_param->color_ctrl_p2_roll_tab[6]; + shp->reg150.sw_coloradj_tab2_7 = p_shp_param->color_ctrl_p2_roll_tab[7]; + shp->reg150.sw_coloradj_tab2_8 = p_shp_param->color_ctrl_p2_roll_tab[8]; + shp->reg150.sw_coloradj_tab2_9 = p_shp_param->color_ctrl_p2_roll_tab[9]; + shp->reg150.sw_coloradj_tab2_10 = p_shp_param->color_ctrl_p2_roll_tab[10]; + shp->reg150.sw_coloradj_tab2_11 = p_shp_param->color_ctrl_p2_roll_tab[11]; + shp->reg151.sw_coloradj_tab2_12 = p_shp_param->color_ctrl_p2_roll_tab[12]; + shp->reg151.sw_coloradj_tab2_13 = p_shp_param->color_ctrl_p2_roll_tab[13]; + shp->reg151.sw_coloradj_tab2_14 = p_shp_param->color_ctrl_p2_roll_tab[14]; + shp->reg151.sw_coloradj_tab2_15 = p_shp_param->color_ctrl_p2_roll_tab[15]; + + shp->reg152.sw_adj_point_x3 = p_shp_param->color_ctrl_p3_point_u; + shp->reg152.sw_adj_point_y3 = p_shp_param->color_ctrl_p3_point_v; + shp->reg152.sw_adj_scaling_coef3 = p_shp_param->color_ctrl_p3_scaling_coef; + shp->reg153.sw_coloradj_tab3_0 = p_shp_param->color_ctrl_p3_roll_tab[0]; + shp->reg153.sw_coloradj_tab3_1 = p_shp_param->color_ctrl_p3_roll_tab[1]; + shp->reg153.sw_coloradj_tab3_2 = p_shp_param->color_ctrl_p3_roll_tab[2]; + shp->reg153.sw_coloradj_tab3_3 = p_shp_param->color_ctrl_p3_roll_tab[3]; + shp->reg153.sw_coloradj_tab3_4 = p_shp_param->color_ctrl_p3_roll_tab[4]; + shp->reg153.sw_coloradj_tab3_5 = p_shp_param->color_ctrl_p3_roll_tab[5]; + shp->reg154.sw_coloradj_tab3_6 = p_shp_param->color_ctrl_p3_roll_tab[6]; + shp->reg154.sw_coloradj_tab3_7 = p_shp_param->color_ctrl_p3_roll_tab[7]; + shp->reg154.sw_coloradj_tab3_8 = p_shp_param->color_ctrl_p3_roll_tab[8]; + shp->reg154.sw_coloradj_tab3_9 = p_shp_param->color_ctrl_p3_roll_tab[9]; + shp->reg154.sw_coloradj_tab3_10 = p_shp_param->color_ctrl_p3_roll_tab[10]; + shp->reg154.sw_coloradj_tab3_11 = p_shp_param->color_ctrl_p3_roll_tab[11]; + shp->reg155.sw_coloradj_tab3_12 = p_shp_param->color_ctrl_p3_roll_tab[12]; + shp->reg155.sw_coloradj_tab3_13 = p_shp_param->color_ctrl_p3_roll_tab[13]; + shp->reg155.sw_coloradj_tab3_14 = p_shp_param->color_ctrl_p3_roll_tab[14]; + shp->reg155.sw_coloradj_tab3_15 = p_shp_param->color_ctrl_p3_roll_tab[15]; + + + shp->reg156.sw_idxmode_select = p_shp_param->tex_adj_mode_select; + shp->reg156.sw_ymode_select = p_shp_param->tex_adj_y_mode_select; + shp->reg156.sw_tex_idx0 = p_shp_param->tex_adj_grd[1] >> 2; + shp->reg156.sw_tex_idx1 = p_shp_param->tex_adj_grd[2] >> 2; + shp->reg157.sw_tex_idx2 = p_shp_param->tex_adj_grd[3] >> 2; + shp->reg157.sw_tex_idx3 = p_shp_param->tex_adj_grd[4] >> 2; + shp->reg157.sw_tex_gain0 = p_shp_param->tex_adj_val[0]; + shp->reg158.sw_tex_gain1 = p_shp_param->tex_adj_val[1]; + shp->reg158.sw_tex_gain2 = p_shp_param->tex_adj_val[2]; + shp->reg158.sw_tex_gain3 = p_shp_param->tex_adj_val[3]; + shp->reg158.sw_tex_gain4 = p_shp_param->tex_adj_val[4]; + global_gain_slp_temp[0] = ROUND(128 * (float)(shp->reg158.sw_tex_gain1 - shp->reg157.sw_tex_gain0) / + MPP_MAX((float)(shp->reg156.sw_tex_idx0 - 0), 1)); + global_gain_slp_temp[1] = ROUND(128 * (float)(shp->reg158.sw_tex_gain2 - shp->reg158.sw_tex_gain1) / + MPP_MAX((float)(shp->reg156.sw_tex_idx1 - shp->reg156.sw_tex_idx0), 1)); + global_gain_slp_temp[2] = ROUND(128 * (float)(shp->reg158.sw_tex_gain3 - shp->reg158.sw_tex_gain2) / + MPP_MAX((float)(shp->reg157.sw_tex_idx2 - shp->reg156.sw_tex_idx1), 1)); + global_gain_slp_temp[3] = ROUND(128 * (float)(shp->reg158.sw_tex_gain4 - shp->reg158.sw_tex_gain3) / + MPP_MAX((float)(shp->reg157.sw_tex_idx3 - shp->reg157.sw_tex_idx2), 1)); + global_gain_slp_temp[4] = ROUND(128 * (float)(p_shp_param->tex_adj_val[5] - shp->reg158.sw_tex_gain4) / + MPP_MAX((float)(255 - shp->reg157.sw_tex_idx3), 1)); + shp->reg159.sw_tex_slp01 = mpp_clip(global_gain_slp_temp[0], -1024, 1023); + shp->reg159.sw_tex_slp12 = mpp_clip(global_gain_slp_temp[1], -1024, 1023); + shp->reg160.sw_tex_slp23 = mpp_clip(global_gain_slp_temp[2], -1024, 1023); + shp->reg160.sw_tex_slp34 = mpp_clip(global_gain_slp_temp[3], -1024, 1023); + shp->reg161.sw_tex_slp45 = mpp_clip(global_gain_slp_temp[4], -1024, 1023); +} + +static MPP_RET vdpp2_params_to_reg(Vdpp2Params* src_params, Vdpp2ApiCtx *ctx) +{ + Vdpp2Regs *dst_reg = &ctx->reg; + DmsrParams *dmsr_params = &src_params->dmsr_params; + ZmeParams *zme_params = &src_params->zme_params; + EsParams *es_params = &src_params->es_params; + ShpParams *shp_params = &src_params->shp_params; + HistParams *hist_params = &src_params->hist_params; + + memset(dst_reg, 0, sizeof(*dst_reg)); + + dst_reg->common.reg0.sw_vep_frm_en = 1; + + /* 0x0004(reg1) */ + dst_reg->common.reg1.sw_vep_src_fmt = VDPP_FMT_YUV420; // vep only support yuv420 + dst_reg->common.reg1.sw_vep_src_yuv_swap = src_params->src_yuv_swap; + + if (MPP_FMT_YUV420SP_VU == src_params->src_fmt) + dst_reg->common.reg1.sw_vep_src_yuv_swap = 1; + + dst_reg->common.reg1.sw_vep_dst_fmt = src_params->dst_fmt; + dst_reg->common.reg1.sw_vep_dst_yuv_swap = src_params->dst_yuv_swap; + dst_reg->common.reg1.sw_vep_dbmsr_en = (src_params->working_mode == VDPP_WORK_MODE_DCI) + ? 0 + : dmsr_params->dmsr_enable; + + vdpp_logv("set reg: vep_src_fmt=%d(must be 3 here), vep_src_yuv_swap=%d\n", + dst_reg->common.reg1.sw_vep_src_fmt, dst_reg->common.reg1.sw_vep_src_yuv_swap); + vdpp_logv("set reg: vep_dst_fmt=%d(vdppFmt: 0-444sp; 3-420sp), vep_dst_yuv_swap=%d\n", + dst_reg->common.reg1.sw_vep_dst_fmt, dst_reg->common.reg1.sw_vep_dst_yuv_swap); + + /* 0x0008(reg2) */ + dst_reg->common.reg2.sw_vdpp_working_mode = src_params->working_mode; + vdpp_logv("set reg: vdpp_working_mode=%d (1-iep2, 2-vep, 3-dci)\n", src_params->working_mode); + + /* 0x000C ~ 0x001C(reg3 ~ reg7), skip */ + dst_reg->common.reg4.sw_vep_clk_on = 1; + dst_reg->common.reg4.sw_md_clk_on = 1; + dst_reg->common.reg4.sw_dect_clk_on = 1; + dst_reg->common.reg4.sw_me_clk_on = 1; + dst_reg->common.reg4.sw_mc_clk_on = 1; + dst_reg->common.reg4.sw_eedi_clk_on = 1; + dst_reg->common.reg4.sw_ble_clk_on = 1; + dst_reg->common.reg4.sw_out_clk_on = 1; + dst_reg->common.reg4.sw_ctrl_clk_on = 1; + dst_reg->common.reg4.sw_ram_clk_on = 1; + dst_reg->common.reg4.sw_dma_clk_on = 1; + dst_reg->common.reg4.sw_reg_clk_on = 1; + + /* 0x0020(reg8) */ + dst_reg->common.reg8.sw_vep_frm_done_en = 1; + dst_reg->common.reg8.sw_vep_osd_max_en = 1; + dst_reg->common.reg8.sw_vep_bus_error_en = 1; + dst_reg->common.reg8.sw_vep_timeout_int_en = 1; + dst_reg->common.reg8.sw_vep_config_error_en = 1; + /* 0x0024 ~ 0x002C(reg9 ~ reg11), skip */ + { + RK_U32 src_right_redundant = (16 - (src_params->src_width & 0xF)) & 0xF; + RK_U32 src_down_redundant = (8 - (src_params->src_height & 0x7)) & 0x7; + // TODO: check if the dst_right_redundant is aligned to 2 or 4(for yuv420sp) + RK_U32 dst_right_redundant = (16 - (src_params->dst_width & 0xF)) & 0xF; + /* 0x0030(reg12) */ + dst_reg->common.reg12.sw_vep_src_vir_y_stride = src_params->src_width_vir / 4; + + /* 0x0034(reg13) */ + dst_reg->common.reg13.sw_vep_dst_vir_y_stride = src_params->dst_width_vir / 4; + + /* 0x0038(reg14) */ + dst_reg->common.reg14.sw_vep_src_pic_width = src_params->src_width + src_right_redundant - 1; + dst_reg->common.reg14.sw_vep_src_right_redundant = src_right_redundant; + dst_reg->common.reg14.sw_vep_src_pic_height = src_params->src_height + src_down_redundant - 1; + dst_reg->common.reg14.sw_vep_src_down_redundant = src_down_redundant; + + /* 0x003C(reg15) */ + dst_reg->common.reg15.sw_vep_dst_pic_width = src_params->dst_width + dst_right_redundant - 1; + dst_reg->common.reg15.sw_vep_dst_right_redundant = dst_right_redundant; + dst_reg->common.reg15.sw_vep_dst_pic_height = src_params->dst_height - 1; + } + /* 0x0040 ~ 0x005C(reg16 ~ reg23), skip */ + dst_reg->common.reg20.sw_vep_timeout_en = 1; + dst_reg->common.reg20.sw_vep_timeout_cnt = 0x8FFFFFF; + + /* 0x0060(reg24) */ + dst_reg->common.reg24.sw_vep_src_addr_y = src_params->src.y; + + /* 0x0064(reg25) */ + dst_reg->common.reg25.sw_vep_src_addr_uv = src_params->src.cbcr; + + /* 0x0068(reg26) */ + dst_reg->common.reg26.sw_vep_dst_addr_y = src_params->dst.y; + + /* 0x006C(reg27) */ + dst_reg->common.reg27.sw_vep_dst_addr_uv = src_params->dst.cbcr; + + if (src_params->yuv_out_diff) { + RK_S32 dst_c_width = src_params->dst_c_width; + RK_S32 dst_c_height = src_params->dst_c_height; + RK_S32 dst_c_width_vir = src_params->dst_c_width_vir; + RK_S32 dst_redundant_c = 0; + + /** @note: no need to half the chroma size for YUV420, since vdpp will do it according to the output format! */ + if (dst_reg->common.reg1.sw_vep_dst_fmt == VDPP_FMT_YUV420) { + dst_c_width *= 2; + dst_c_height *= 2; + dst_c_width_vir *= 2; + } + + dst_redundant_c = (16 - (dst_c_width & 0xF)) & 0xF; + dst_reg->common.reg1.sw_vep_yuvout_diff_en = 1; + dst_reg->common.reg13.sw_vep_dst_vir_c_stride = dst_c_width_vir / 4; // unit: dword + /* 0x0040(reg16) */ + dst_reg->common.reg16.sw_vep_dst_pic_width_c = dst_c_width + dst_redundant_c - 1; + dst_reg->common.reg16.sw_vep_dst_right_redundant_c = dst_redundant_c; + dst_reg->common.reg16.sw_vep_dst_pic_height_c = dst_c_height - 1; + + dst_reg->common.reg27.sw_vep_dst_addr_uv = src_params->dst_c.cbcr; + + vdpp_logv("set reg: vep_dst_vir_c_stride=%d [dword], vep_dst_right_redundant_c=%d [pixel]\n", + dst_reg->common.reg13.sw_vep_dst_vir_c_stride, dst_reg->common.reg16.sw_vep_dst_right_redundant_c); + vdpp_logv("set reg: vep_dst_pic_width_c=%d [pixel], vep_dst_pic_height_c=%d [pixel]\n", + dst_reg->common.reg16.sw_vep_dst_pic_width_c, dst_reg->common.reg16.sw_vep_dst_pic_height_c); + } + vdpp_logv("set reg: vep_yuvout_diff_en=%d, vep_dst_addr_uv(fd)=%d\n", + dst_reg->common.reg1.sw_vep_yuvout_diff_en, dst_reg->common.reg27.sw_vep_dst_addr_uv); + + /* vdpp1 */ + set_dmsr_to_vdpp_reg(dmsr_params, &dst_reg->dmsr); + + zme_params->src_width = src_params->src_width; + zme_params->src_height = src_params->src_height; + zme_params->dst_width = src_params->dst_width; + zme_params->dst_height = src_params->dst_height; + zme_params->dst_fmt = src_params->dst_fmt; + zme_params->yuv_out_diff = src_params->yuv_out_diff; + zme_params->dst_c_width = src_params->dst_c_width; + zme_params->dst_c_height = src_params->dst_c_height; + set_zme_to_vdpp_reg(zme_params, &dst_reg->zme); + + /* vdpp2 */ + hist_params->src_fmt = src_params->src_fmt; + hist_params->src_width = src_params->src_width; + hist_params->src_height = src_params->src_height; + hist_params->src_width_vir = src_params->src_width_vir; + hist_params->src_height_vir = src_params->src_height_vir; + hist_params->src_addr = src_params->src.y; + hist_params->working_mode = src_params->working_mode; + set_hist_to_vdpp2_reg(hist_params, &dst_reg->hist, &dst_reg->common); + + set_es_to_vdpp2_reg(es_params, &dst_reg->es); + set_shp_to_vdpp2_reg(shp_params, &dst_reg->sharp); + + return MPP_OK; +} + +static MPP_RET vdpp2_set_default_param(Vdpp2Params *param) +{ + // base + param->src_fmt = MPP_FMT_YUV420SP; // default 420sp + param->src_yuv_swap = VDPP_YUV_SWAP_SP_UV; + param->dst_fmt = VDPP_FMT_YUV444; + param->dst_yuv_swap = VDPP_YUV_SWAP_SP_UV; + param->src_width = 1920; + param->src_height = 1080; + param->dst_width = 1920; + param->dst_height = 1080; + param->yuv_out_diff = 0; + param->working_mode = VDPP_WORK_MODE_VEP; + + /* vdpp1 features */ + vdpp_set_default_dmsr_param(¶m->dmsr_params); + vdpp_set_default_zme_param(¶m->zme_params); + + /* vdpp2 features */ + vdpp2_set_default_es_param(¶m->es_params); + vdpp2_set_default_shp_param(¶m->shp_params); + vdpp2_set_default_hist_param(¶m->hist_params); + param->hist_params.src_fmt = param->src_fmt; + param->hist_params.src_width = param->src_width; + param->hist_params.src_height = param->src_height; + param->hist_params.src_width_vir = param->src_width; + param->hist_params.src_height_vir = param->src_height; + param->hist_params.src_addr = 0; + param->hist_params.working_mode = VDPP_WORK_MODE_VEP; + + return MPP_OK; +} + +void vdpp2_set_default_hist_param(HistParams *hist_params) +{ + if (!hist_params) { + vdpp_loge("NULL argument set! \n"); + return; + } + + memset(hist_params, 0, sizeof(HistParams)); +} + +void vdpp2_set_default_es_param(EsParams *param) +{ + param->es_bEnabledES = 0; + param->es_iAngleDelta = 17; + param->es_iAngleDeltaExtra = 5; + param->es_iGradNoDirTh = 37; + param->es_iGradFlatTh = 75; + param->es_iWgtGain = 128; + param->es_iWgtDecay = 128; + param->es_iLowConfTh = 96; + param->es_iLowConfRatio = 32; + param->es_iConfCntTh = 4; + param->es_iWgtLocalTh = 64; + param->es_iK1 = 4096; + param->es_iK2 = 7168; + param->es_iDeltaLimit = 65280; + memcpy(¶m->es_iDiff2conf_lut_x[0], &diff2conf_lut_x_tmp[0], sizeof(diff2conf_lut_x_tmp)); + memcpy(¶m->es_iDiff2conf_lut_y[0], &diff2conf_lut_y_tmp[0], sizeof(diff2conf_lut_y_tmp)); + param->es_bEndpointCheckEnable = 1; +} + +void vdpp2_set_default_shp_param(ShpParams *param) +{ + param->sharp_enable = 1; + param->sharp_coloradj_bypass_en = 1; + + param->lti_h_enable = 0; + param->lti_h_radius = 1; + param->lti_h_slope = 100; + param->lti_h_thresold = 21; + param->lti_h_gain = 8; + param->lti_h_noise_thr_pos = 1023; + param->lti_h_noise_thr_neg = 1023; + + param->lti_v_enable = 0; + param->lti_v_radius = 1; + param->lti_v_slope = 100; + param->lti_v_thresold = 21; + param->lti_v_gain = 8; + param->lti_v_noise_thr_pos = 1023; + param->lti_v_noise_thr_neg = 1023; + + param->cti_h_enable = 0; + param->cti_h_radius = 1; + param->cti_h_slope = 100; + param->cti_h_thresold = 21; + param->cti_h_gain = 8; + param->cti_h_noise_thr_pos = 1023; + param->cti_h_noise_thr_neg = 1023; + + param->peaking_enable = 1; + param->peaking_gain = 196; + + param->peaking_coring_enable = 1; + param->peaking_limit_ctrl_enable = 1; + param->peaking_gain_enable = 1; + + memcpy(param->peaking_coring_zero, coring_zero_tmp, sizeof(coring_zero_tmp)); + memcpy(param->peaking_coring_thr, coring_thr_tmp, sizeof(coring_thr_tmp)); + memcpy(param->peaking_coring_ratio, coring_ratio_tmp, sizeof(coring_ratio_tmp)); + memcpy(param->peaking_gain_pos, gain_pos_tmp, sizeof(gain_pos_tmp)); + memcpy(param->peaking_gain_neg, gain_neg_tmp, sizeof(gain_neg_tmp)); + memcpy(param->peaking_limit_ctrl_pos0, limit_ctrl_pos0_tmp, sizeof(limit_ctrl_pos0_tmp)); + memcpy(param->peaking_limit_ctrl_pos1, limit_ctrl_pos1_tmp, sizeof(limit_ctrl_pos1_tmp)); + memcpy(param->peaking_limit_ctrl_neg0, limit_ctrl_neg0_tmp, sizeof(limit_ctrl_neg0_tmp)); + memcpy(param->peaking_limit_ctrl_neg1, limit_ctrl_neg1_tmp, sizeof(limit_ctrl_neg1_tmp)); + memcpy(param->peaking_limit_ctrl_ratio, limit_ctrl_ratio_tmp, sizeof(limit_ctrl_ratio_tmp)); + memcpy(param->peaking_limit_ctrl_bnd_pos, limit_ctrl_bnd_pos_tmp, sizeof(limit_ctrl_bnd_pos_tmp)); + memcpy(param->peaking_limit_ctrl_bnd_neg, limit_ctrl_bnd_neg_tmp, sizeof(limit_ctrl_bnd_neg_tmp)); + + param->peaking_edge_ctrl_enable = 1; + param->peaking_edge_ctrl_non_dir_thr = 16; + param->peaking_edge_ctrl_dir_cmp_ratio = 4; + param->peaking_edge_ctrl_non_dir_wgt_offset = 64; + param->peaking_edge_ctrl_non_dir_wgt_ratio = 16; + param->peaking_edge_ctrl_dir_cnt_thr = 2; + param->peaking_edge_ctrl_dir_cnt_avg = 3; + param->peaking_edge_ctrl_dir_cnt_offset = 2; + param->peaking_edge_ctrl_diag_dir_thr = 16; + + memcpy(param->peaking_edge_ctrl_diag_adj_gain_tab, diag_adj_gain_tab_tmp, + sizeof(diag_adj_gain_tab_tmp)); + + param->peaking_estc_enable = 1; + param->peaking_estc_delta_offset_h = 4; + param->peaking_estc_alpha_over_h = 8; + param->peaking_estc_alpha_under_h = 16; + param->peaking_estc_alpha_over_unlimit_h = 64; + param->peaking_estc_alpha_under_unlimit_h = 112; + param->peaking_estc_delta_offset_v = 4; + param->peaking_estc_alpha_over_v = 8; + param->peaking_estc_alpha_under_v = 16; + param->peaking_estc_alpha_over_unlimit_v = 64; + param->peaking_estc_alpha_under_unlimit_v = 112; + param->peaking_estc_delta_offset_d0 = 4; + param->peaking_estc_alpha_over_d0 = 16; + param->peaking_estc_alpha_under_d0 = 16; + param->peaking_estc_alpha_over_unlimit_d0 = 96; + param->peaking_estc_alpha_under_unlimit_d0 = 96; + param->peaking_estc_delta_offset_d1 = 4; + param->peaking_estc_alpha_over_d1 = 16; + param->peaking_estc_alpha_under_d1 = 16; + param->peaking_estc_alpha_over_unlimit_d1 = 96; + param->peaking_estc_alpha_under_unlimit_d1 = 96; + param->peaking_estc_delta_offset_non = 4; + param->peaking_estc_alpha_over_non = 8; + param->peaking_estc_alpha_under_non = 8; + param->peaking_estc_alpha_over_unlimit_non = 112; + param->peaking_estc_alpha_under_unlimit_non = 112; + param->peaking_filter_cfg_diag_enh_coef = 6; + + param->peaking_filt_core_H0[0] = 4; + param->peaking_filt_core_H0[1] = 16; + param->peaking_filt_core_H0[2] = 24; + param->peaking_filt_core_H1[0] = -16; + param->peaking_filt_core_H1[1] = 0; + param->peaking_filt_core_H1[2] = 32; + param->peaking_filt_core_H2[0] = 0; + param->peaking_filt_core_H2[1] = -16; + param->peaking_filt_core_H2[2] = 32; + param->peaking_filt_core_V0[0] = 1; + param->peaking_filt_core_V0[1] = 4; + param->peaking_filt_core_V0[2] = 6; + param->peaking_filt_core_V1[0] = -4; + param->peaking_filt_core_V1[1] = 0; + param->peaking_filt_core_V1[2] = 8; + param->peaking_filt_core_V2[0] = 0; + param->peaking_filt_core_V2[1] = -4; + param->peaking_filt_core_V2[2] = 8; + param->peaking_filt_core_USM[0] = 1; + param->peaking_filt_core_USM[1] = 4; + param->peaking_filt_core_USM[2] = 6; + + param->shootctrl_enable = 1; + param->shootctrl_filter_radius = 1; + param->shootctrl_delta_offset = 16; + param->shootctrl_alpha_over = 8; + param->shootctrl_alpha_under = 8; + param->shootctrl_alpha_over_unlimit = 112; + param->shootctrl_alpha_under_unlimit = 112; + + param->global_gain_enable = 0; + param->global_gain_lum_mode = 0; + + memcpy(param->global_gain_lum_grd, lum_grd_tmp, sizeof(lum_grd_tmp)); + memcpy(param->global_gain_lum_val, lum_val_tmp, sizeof(lum_val_tmp)); + memcpy(param->global_gain_adp_grd, adp_grd_tmp, sizeof(adp_grd_tmp)); + memcpy(param->global_gain_adp_val, adp_val_tmp, sizeof(adp_val_tmp)); + memcpy(param->global_gain_var_grd, var_grd_tmp, sizeof(var_grd_tmp)); + memcpy(param->global_gain_var_val, var_val_tmp, sizeof(var_val_tmp)); + + param->color_ctrl_enable = 0; + + param->color_ctrl_p0_scaling_coef = 1; + param->color_ctrl_p0_point_u = 115; + param->color_ctrl_p0_point_v = 155; + memcpy(param->color_ctrl_p0_roll_tab, roll_tab_pattern0, sizeof(roll_tab_pattern0)); + param->color_ctrl_p1_scaling_coef = 1; + param->color_ctrl_p1_point_u = 90; + param->color_ctrl_p1_point_v = 120; + memcpy(param->color_ctrl_p1_roll_tab, roll_tab_pattern1, sizeof(roll_tab_pattern1)); + param->color_ctrl_p2_scaling_coef = 1; + param->color_ctrl_p2_point_u = 128; + param->color_ctrl_p2_point_v = 128; + memcpy(param->color_ctrl_p2_roll_tab, roll_tab_pattern2, sizeof(roll_tab_pattern2)); + param->color_ctrl_p3_scaling_coef = 1; + param->color_ctrl_p3_point_u = 128; + param->color_ctrl_p3_point_v = 128; + memcpy(param->color_ctrl_p3_roll_tab, roll_tab_pattern2, sizeof(roll_tab_pattern2)); + + param->tex_adj_enable = 0; + param->tex_adj_y_mode_select = 3; + param->tex_adj_mode_select = 0; + + memcpy(param->tex_adj_grd, tex_grd_tmp, sizeof(tex_grd_tmp)); + memcpy(param->tex_adj_val, tex_val_tmp, sizeof(tex_val_tmp)); +} + +MPP_RET vdpp2_init(VdppCtx ictx) +{ + MppReqV1 mpp_req; + RK_U32 client_data = VDPP_CLIENT_TYPE; + Vdpp2ApiCtx *ctx = ictx; + MPP_RET ret = MPP_OK; + + if (NULL == ictx) { + vdpp_loge("found NULL input vdpp2 ctx %p\n", ictx); + return MPP_ERR_NULL_PTR; + } + + // default log level: warning + mpp_env_get_u32(VDPP_COM_DEBUG_ENV_NAME, &vdpp_debug, + (VDPP_LOG_FATAL | VDPP_LOG_ERROR | VDPP_LOG_WARNING)); + vdpp_logi("get env '%s' flag: %#x", VDPP_COM_DEBUG_ENV_NAME, vdpp_debug); + + vdpp_enter(); + + ctx->fd = open("/dev/mpp_service", O_RDWR | O_CLOEXEC); + if (ctx->fd < 0) { + vdpp_loge("can NOT find device /dev/vdpp\n"); + return MPP_NOK; + } + + mpp_req.cmd = MPP_CMD_INIT_CLIENT_TYPE; + mpp_req.flag = 0; + mpp_req.size = sizeof(client_data); + mpp_req.data_ptr = REQ_DATA_PTR(&client_data); + + /* set default parameters */ + memset(&ctx->params, 0, sizeof(Vdpp2Params)); + vdpp2_set_default_param(&ctx->params); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) { + vdpp_loge("ioctl set_client failed!\n"); + return MPP_NOK; + } + + vdpp_leave(); + return ret; +} + +MPP_RET vdpp2_deinit(VdppCtx ictx) +{ + Vdpp2ApiCtx *ctx = NULL; + + if (NULL == ictx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ictx); + return MPP_ERR_NULL_PTR; + } + + ctx = ictx; + + if (ctx->fd >= 0) { + close(ctx->fd); + ctx->fd = -1; + } + + return MPP_OK; +} + +static MPP_RET vdpp2_set_param(Vdpp2ApiCtx *ctx, VdppApiContent *param, VdppParamType type) +{ + RK_U16 mask; + RK_U16 cfg_set; + + switch (type) { + case VDPP_PARAM_TYPE_COM: { // deprecated config + ctx->params.src_fmt = MPP_FMT_YUV420SP; // default 420 + ctx->params.src_yuv_swap = param->com.sswap; + ctx->params.dst_fmt = param->com.dfmt; + ctx->params.dst_yuv_swap = param->com.dswap; + ctx->params.src_width = param->com.src_width; + ctx->params.src_height = param->com.src_height; + ctx->params.dst_width = param->com.dst_width; + ctx->params.dst_height = param->com.dst_height; + + ctx->params.dmsr_params.dmsr_enable = 1; + ctx->params.es_params.es_bEnabledES = 1; + ctx->params.shp_params.sharp_enable = 1; + ctx->params.hist_params.hist_cnt_en = 0; // default disable + + /* set default vir stride */ + if (!ctx->params.src_width_vir) + ctx->params.src_width_vir = MPP_ALIGN(ctx->params.src_width, 16); + if (!ctx->params.src_height_vir) + ctx->params.src_height_vir = MPP_ALIGN(ctx->params.src_height, 8); + if (!ctx->params.dst_width) + ctx->params.dst_width = ctx->params.src_width; + if (!ctx->params.dst_height) + ctx->params.dst_height = ctx->params.src_height; + if (!ctx->params.dst_width_vir) + ctx->params.dst_width_vir = MPP_ALIGN(ctx->params.dst_width, 16); + if (!ctx->params.dst_height_vir) + ctx->params.dst_height_vir = MPP_ALIGN(ctx->params.dst_height, 2); + /* set default chrome stride */ + if (!ctx->params.dst_c_width) + ctx->params.dst_c_width = ctx->params.dst_width; + if (!ctx->params.dst_c_width_vir) + ctx->params.dst_c_width_vir = MPP_ALIGN(ctx->params.dst_c_width, 16); + if (!ctx->params.dst_c_height) + ctx->params.dst_c_height = ctx->params.dst_height; + if (!ctx->params.dst_c_height_vir) + ctx->params.dst_c_height_vir = MPP_ALIGN(ctx->params.dst_c_height, 2); + } break; + case VDPP_PARAM_TYPE_DMSR: { + mpp_assert(sizeof(ctx->params.dmsr_params) == sizeof(param->dmsr)); + memcpy(&ctx->params.dmsr_params, ¶m->dmsr, sizeof(DmsrParams)); + } break; + case VDPP_PARAM_TYPE_ZME_COM: { + ctx->params.zme_params.zme_bypass_en = param->zme.bypass_enable; + ctx->params.zme_params.zme_dering_enable = param->zme.dering_enable; + ctx->params.zme_params.zme_dering_sen_0 = param->zme.dering_sen_0; + ctx->params.zme_params.zme_dering_sen_1 = param->zme.dering_sen_1; + ctx->params.zme_params.zme_dering_blend_alpha = param->zme.dering_blend_alpha; + ctx->params.zme_params.zme_dering_blend_beta = param->zme.dering_blend_beta; + if (param->zme.tap8_coeff != NULL) + ctx->params.zme_params.zme_tap8_coeff = param->zme.tap8_coeff; + if (param->zme.tap6_coeff != NULL) + ctx->params.zme_params.zme_tap6_coeff = param->zme.tap6_coeff; + } break; + case VDPP_PARAM_TYPE_ZME_COEFF: { + if (param->zme.tap8_coeff != NULL) + ctx->params.zme_params.zme_tap8_coeff = param->zme.tap8_coeff; + if (param->zme.tap6_coeff != NULL) + ctx->params.zme_params.zme_tap6_coeff = param->zme.tap6_coeff; + } break; + case VDPP_PARAM_TYPE_COM2: { + mask = (param->com2.cfg_set >> 16) & 0x7; + cfg_set = (param->com2.cfg_set >> 0) & mask; + + ctx->params.src_yuv_swap = param->com2.sswap; + ctx->params.src_fmt = param->com2.sfmt; + ctx->params.dst_fmt = param->com2.dfmt; + ctx->params.dst_yuv_swap = param->com2.dswap; + ctx->params.src_width = param->com2.src_width; + ctx->params.src_height = param->com2.src_height; + ctx->params.src_width_vir = param->com2.src_width_vir; + ctx->params.src_height_vir = param->com2.src_height_vir; + ctx->params.dst_width = param->com2.dst_width; + ctx->params.dst_height = param->com2.dst_height; + ctx->params.dst_width_vir = param->com2.dst_width_vir; + ctx->params.dst_height_vir = param->com2.dst_height_vir; + ctx->params.yuv_out_diff = param->com2.yuv_out_diff; + ctx->params.dst_c_width = param->com2.dst_c_width; + ctx->params.dst_c_height = param->com2.dst_c_height; + ctx->params.dst_c_width_vir = param->com2.dst_c_width_vir; + ctx->params.dst_c_height_vir = param->com2.dst_c_height_vir; + ctx->params.working_mode = (param->com2.hist_mode_en != 0) ? + VDPP_WORK_MODE_DCI : VDPP_WORK_MODE_VEP; + if (mask & VDPP_DMSR_EN) + ctx->params.dmsr_params.dmsr_enable = ((cfg_set & VDPP_DMSR_EN) != 0) ? 1 : 0; + if (mask & VDPP_ES_EN) + ctx->params.es_params.es_bEnabledES = ((cfg_set & VDPP_ES_EN) != 0) ? 1 : 0; + if (mask & VDPP_SHARP_EN) + ctx->params.shp_params.sharp_enable = ((cfg_set & VDPP_SHARP_EN) != 0) ? 1 : 0; + } break; + case VDPP_PARAM_TYPE_ES: { + mpp_assert(sizeof(ctx->params.es_params) == sizeof(param->es)); + memcpy(&ctx->params.es_params, ¶m->es, sizeof(EsParams)); + } break; + case VDPP_PARAM_TYPE_HIST: { + ctx->params.hist_params.hist_cnt_en = param->hist.hist_cnt_en; + ctx->params.hist_params.dci_hsd_mode = param->hist.dci_hsd_mode; + ctx->params.hist_params.dci_vsd_mode = param->hist.dci_vsd_mode; + ctx->params.hist_params.dci_yrgb_gather_num = param->hist.dci_yrgb_gather_num; + ctx->params.hist_params.dci_yrgb_gather_en = param->hist.dci_yrgb_gather_en; + ctx->params.hist_params.dci_csc_range = param->hist.dci_csc_range; + ctx->params.hist_params.hist_addr = param->hist.hist_addr; + } break; + case VDPP_PARAM_TYPE_SHARP: { + mpp_assert(sizeof(ctx->params.shp_params) == sizeof(param->sharp)); + memcpy(&ctx->params.shp_params, ¶m->sharp, sizeof(ShpParams)); + } break; + default: { + vdpp_loge("unknown VDPP_PARAM_TYPE %#x !\n", type); + } break; + } + + return MPP_OK; +} + +static RK_S32 check_cap(Vdpp2Params *params) +{ + RK_S32 ret_cap = VDPP_CAP_UNSUPPORTED; + RK_U32 vep_mode_check = 0; + RK_U32 hist_mode_check = 0; + + if (NULL == params) { + vdpp_loge("found null pointer params\n"); + return VDPP_CAP_UNSUPPORTED; + } + + if (params->src_height_vir < params->src_height || + params->src_width_vir < params->src_width) { + vdpp_logd("invalid src img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->src_width, params->src_height, + params->src_width_vir, params->src_height_vir); + return VDPP_CAP_UNSUPPORTED; + } + + if (params->dst_height_vir < params->dst_height || + params->dst_width_vir < params->dst_width) { + vdpp_logd("invalid dst img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->dst_width, params->dst_height, + params->dst_width_vir, params->dst_height_vir); + return VDPP_CAP_UNSUPPORTED; + } + + if ((params->src_fmt != MPP_FMT_YUV420SP) && + (params->src_fmt != MPP_FMT_YUV420SP_VU)) { + vdpp_logd("vep only support nv12 or nv21\n"); + vep_mode_check++; + } + + if ((params->src_height_vir > VDPP2_VEP_MAX_HEIGHT) || + (params->src_width_vir > VDPP2_VEP_MAX_WIDTH) || + (params->src_height < VDPP2_MODE_MIN_HEIGHT) || + (params->src_width < VDPP2_MODE_MIN_WIDTH) || + (params->src_height_vir < VDPP2_MODE_MIN_HEIGHT) || + (params->src_width_vir < VDPP2_MODE_MIN_WIDTH)) { + vdpp_logd("vep unsupported src img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->src_width, params->src_height, + params->src_width_vir, params->src_height_vir); + vep_mode_check++; + } + + if ((params->dst_height_vir > VDPP2_VEP_MAX_HEIGHT) || + (params->dst_width_vir > VDPP2_VEP_MAX_WIDTH) || + (params->dst_height < VDPP2_MODE_MIN_HEIGHT) || + (params->dst_width < VDPP2_MODE_MIN_WIDTH) || + (params->dst_height_vir < VDPP2_MODE_MIN_HEIGHT) || + (params->dst_width_vir < VDPP2_MODE_MIN_WIDTH)) { + vdpp_logd("vep unsupported dst img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->dst_width, params->dst_height, + params->dst_width_vir, params->dst_height_vir); + vep_mode_check++; + } + + if ((params->src_width_vir & 0xf) || (params->dst_width_vir & 0xf)) { + vdpp_logd("vep only support img_w_i/o_vir 16Byte align\n"); + vdpp_logd("vep unsupported src img_w_vir=%d dst img_w_vir=%d\n", + params->src_width_vir, params->dst_width_vir); + vep_mode_check++; + } + + if (params->src_height_vir & 0x7) { + vdpp_logd("vep only support img_h_in_vir 8pix align\n"); + vdpp_logd("vep unsupported src img_h_vir=%d\n", params->src_height_vir); + vep_mode_check++; + } + + if (params->dst_height_vir & 0x1) { + vdpp_logd("vep only support img_h_out_vir 2pix align\n"); + vdpp_logd("vep unsupported dst img_h_vir=%d\n", params->dst_height_vir); + vep_mode_check++; + } + + if ((params->src_width & 1) || (params->src_height & 1) || + (params->dst_width & 1) || (params->dst_height & 1)) { + vdpp_logd("vep only support img_w/h_vld 2pix align\n"); + vdpp_logd("vep unsupported img_w_i=%d img_h_i=%d img_w_o=%d img_h_o=%d\n", + params->src_width, params->src_height, params->dst_width, params->dst_height); + vep_mode_check++; + } + + if (params->yuv_out_diff) { + if ((params->dst_c_height_vir > VDPP2_VEP_MAX_HEIGHT) || + (params->dst_c_width_vir > VDPP2_VEP_MAX_WIDTH) || + (params->dst_c_height < VDPP2_MODE_MIN_HEIGHT) || + (params->dst_c_width < VDPP2_MODE_MIN_WIDTH) || + (params->dst_c_height_vir < VDPP2_MODE_MIN_HEIGHT) || + (params->dst_c_width_vir < VDPP2_MODE_MIN_WIDTH) || + (params->dst_c_height_vir < params->dst_c_height) || + (params->dst_c_width_vir < params->dst_c_width)) { + vdpp_logd("vep unsupported dst_c img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->dst_c_width, params->dst_c_height, + params->dst_c_width_vir, params->dst_c_height_vir); + vep_mode_check++; + } + + if (params->dst_c_width_vir & 0xf) { + vdpp_logd("vep only support img_w_c_out_vir 16Byte align\n"); + vdpp_logd("vep unsupported dst img_w_c_vir=%d\n", params->dst_c_width_vir); + vep_mode_check++; + } + + if (params->dst_c_height_vir & 0x1) { + vdpp_logd("vep only support img_h_c_out_vir 2pix align\n"); + vdpp_logd("vep unsupported dst img_h_vir=%d\n", params->dst_c_height_vir); + vep_mode_check++; + } + + if ((params->dst_c_width & 1) || (params->dst_c_height & 1)) { + vdpp_logd("vep only support img_c_w/h_vld 2pix align\n"); + vdpp_logd("vep unsupported img_w_o=%d img_h_o=%d\n", + params->dst_c_width, params->dst_c_height); + vep_mode_check++; + } + } + + if ((params->src_height_vir > VDPP2_HIST_MAX_HEIGHT) || + (params->src_width_vir > VDPP2_HIST_MAX_WIDTH) || + (params->src_height < VDPP2_MODE_MIN_HEIGHT) || + (params->src_width < VDPP2_MODE_MIN_WIDTH)) { + vdpp_logd("dci unsupported src img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->src_width, params->src_height, + params->src_width_vir, params->src_height_vir); + hist_mode_check++; + } + + /* 10 bit input */ + if ((params->src_fmt == MPP_FMT_YUV420SP_10BIT) || + (params->src_fmt == MPP_FMT_YUV422SP_10BIT) || + (params->src_fmt == MPP_FMT_YUV444SP_10BIT)) { + if (params->src_width_vir & 0xf) { + vdpp_logd("dci Y-10bit input only support img_w_in_vir 16Byte align\n"); + hist_mode_check++; + } + } else { + if (params->src_width_vir & 0x3) { + vdpp_logd("dci only support img_w_in_vir 4Byte align\n"); + hist_mode_check++; + } + } + + // vdpp_logd("vdpp2 src img resolution: w-%d-%d, h-%d-%d\n", + // params->src_width, params->src_width_vir, + // params->src_height, params->src_height_vir); + // vdpp_logd("vdpp2 dst img resolution: w-%d-%d, h-%d-%d\n", + // params->dst_width, params->dst_width_vir, + // params->dst_height, params->dst_height_vir); + + if (!vep_mode_check) { + ret_cap |= VDPP_CAP_VEP; + vdpp_logd("vdpp2 support mode: VDPP_CAP_VEP\n"); + } + + if (!hist_mode_check) { + vdpp_logd("vdpp2 support mode: VDPP_CAP_HIST\n"); + ret_cap |= VDPP_CAP_HIST; + } + + return ret_cap; +} + +MPP_RET vdpp2_start(Vdpp2ApiCtx *ctx) +{ + VdppRegOffsetInfo reg_off[2]; + /* Note: req_cnt must be 12 here! Make sure req_cnt<=11! */ + MppReqV1 mpp_req[12]; + RK_U32 req_cnt = 0; + Vdpp2Regs *reg = NULL; + RK_S32 ret_cap = VDPP_CAP_UNSUPPORTED; + RK_S32 work_mode; + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp2 ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + // get env here so that we can change loglevel dynamically + mpp_env_get_u32(VDPP_COM_DEBUG_ENV_NAME, &vdpp_debug, + (VDPP_LOG_FATAL | VDPP_LOG_ERROR | VDPP_LOG_WARNING)); + vdpp_logt("get env '%s' flag: %#x", VDPP_COM_DEBUG_ENV_NAME, vdpp_debug); + + vdpp_enter(); + + work_mode = ctx->params.working_mode; + ret_cap = check_cap(&ctx->params); + if ((!(ret_cap & VDPP_CAP_VEP) && (VDPP_WORK_MODE_VEP == work_mode)) || + (!(ret_cap & VDPP_CAP_HIST) && (VDPP_WORK_MODE_DCI == work_mode))) { + vdpp_loge("found incompat work mode %d %s, cap %d\n", work_mode, + working_mode_name[work_mode & 3], ret_cap); + return MPP_NOK; + } + + reg = &ctx->reg; + + memset(reg_off, 0, sizeof(reg_off)); + memset(mpp_req, 0, sizeof(mpp_req)); + memset(reg, 0, sizeof(*reg)); + + vdpp2_params_to_reg(&ctx->params, ctx); + + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.yrgb_hor_coe); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_YRGB_HOR_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.yrgb_hor_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.yrgb_ver_coe); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_YRGB_VER_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.yrgb_ver_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.cbcr_hor_coe); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_CBCR_HOR_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.cbcr_hor_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.cbcr_ver_coe); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_CBCR_VER_COE; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.cbcr_ver_coe); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme.common); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_ZME_COMMON; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme.common); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->dmsr); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_DMSR; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->dmsr); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->hist); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_DCI_HIST; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->hist); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->es); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_ES; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->es); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->sharp); + mpp_req[req_cnt].offset = VDPP2_REG_OFF_SHARP; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->sharp); + + /* set reg offset */ + reg_off[0].reg_idx = 25; + reg_off[0].offset = ctx->params.src.cbcr_offset; + reg_off[1].reg_idx = 27; + + if (!ctx->params.yuv_out_diff) + reg_off[1].offset = ctx->params.dst.cbcr_offset; + else + reg_off[1].offset = ctx->params.dst_c.cbcr_offset; + + vdpp_logv("set reg: cbcr_offset for src/dst=%d/%d\n", reg_off[0].offset, reg_off[1].offset); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_ADDR_OFFSET; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG | MPP_FLAGS_REG_OFFSET_ALONE; + mpp_req[req_cnt].size = sizeof(reg_off); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(reg_off); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->common); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->common); + + /* read output register for common */ + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_READ; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG | MPP_FLAGS_LAST_MSG; + mpp_req[req_cnt].size = sizeof(reg->common); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->common); + mpp_assert(req_cnt <= 11); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req[0]); + + if (ret) { + vdpp_loge("ioctl SET_REG failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + + vdpp_leave(); + return ret; +} + +static MPP_RET vdpp2_wait(Vdpp2ApiCtx *ctx) +{ + MppReqV1 mpp_req; + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + memset(&mpp_req, 0, sizeof(mpp_req)); + mpp_req.cmd = MPP_CMD_POLL_HW_FINISH; + mpp_req.flag |= MPP_FLAGS_LAST_MSG; + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) { + vdpp_loge("ioctl POLL_HW_FINISH failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + } + + return ret; +} + +static MPP_RET vdpp2_done(Vdpp2ApiCtx *ctx) +{ + Vdpp2Regs *reg = NULL; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + vdpp_enter(); + + reg = &ctx->reg; + + vdpp_logd("ro_frm_done_sts=%d\n", reg->common.reg10.ro_frm_done_sts); + vdpp_logd("ro_osd_max_sts=%d\n", reg->common.reg10.ro_osd_max_sts); + vdpp_logd("ro_bus_error_sts=%d\n", reg->common.reg10.ro_bus_error_sts); + vdpp_logd("ro_timeout_sts=%d\n", reg->common.reg10.ro_timeout_sts); + vdpp_logd("ro_config_error_sts=%d\n", reg->common.reg10.ro_config_error_sts); + + if (reg->common.reg8.sw_vep_frm_done_en && + !reg->common.reg10.ro_frm_done_sts) { + vdpp_loge("run vdpp failed!!\n"); + return MPP_NOK; + } + + if (reg->common.reg10.ro_timeout_sts) { + vdpp_loge("run vdpp timeout!!\n"); + return MPP_NOK; + } + + vdpp_logi("run vdpp success! %d\n", reg->common.reg10); + vdpp_leave(); + return MPP_OK; +} + +MPP_RET vdpp2_control(VdppCtx ictx, VdppCmd cmd, void *iparam) +{ + Vdpp2ApiCtx *ctx = ictx; + MPP_RET ret = MPP_OK; + + if ((NULL == iparam && VDPP_CMD_RUN_SYNC != cmd) || + (NULL == ictx)) { + vdpp_loge("found NULL iparam %p cmd %d ctx %p\n", iparam, cmd, ictx); + return MPP_ERR_NULL_PTR; + } + + switch (cmd) { + case VDPP_CMD_SET_COM_CFG: + case VDPP_CMD_SET_DMSR_CFG: + case VDPP_CMD_SET_ZME_COM_CFG: + case VDPP_CMD_SET_ZME_COEFF_CFG: + case VDPP_CMD_SET_COM2_CFG: + case VDPP_CMD_SET_ES: + case VDPP_CMD_SET_DCI_HIST: + case VDPP_CMD_SET_SHARP: { + VdppApiParams *api_param = (VdppApiParams *)iparam; + + ret = vdpp2_set_param(ctx, &api_param->param, api_param->ptype); + if (ret) { + vdpp_loge("set vdpp parameter failed, type %d\n", api_param->ptype); + } + } break; + case VDPP_CMD_SET_SRC: { + set_addr(&ctx->params.src, (VdppImg *)iparam); + } break; + case VDPP_CMD_SET_DST: { + set_addr(&ctx->params.dst, (VdppImg *)iparam); + } break; + case VDPP_CMD_SET_DST_C: { + set_addr(&ctx->params.dst_c, (VdppImg *)iparam); + } break; + case VDPP_CMD_SET_HIST_FD: { + ctx->params.hist_params.hist_addr = *(RK_S32 *)iparam; + } break; + case VDPP_CMD_RUN_SYNC: { + ret = vdpp2_start(ctx); + if (ret) { + vdpp_loge("run vdpp failed!!\n"); + return MPP_NOK; + } + + ret |= vdpp2_wait(ctx); + ret |= vdpp2_done(ctx); + } break; + case VDPP_CMD_GET_AVG_LUMA: { + VdppResults *result = (VdppResults *)iparam; + + memset(result, 0, sizeof(VdppResults)); + + if (!ctx->params.hist_params.hist_cnt_en || ctx->params.hist_params.hist_addr <= 0) { + vdpp_logw("return invalid luma_avg value since the hist_cnt(%d)=0 or fd(%d)<=0!\n", + ctx->params.hist_params.hist_cnt_en, ctx->params.hist_params.hist_addr); + result->hist.luma_avg = -1; + } else { + RK_U32 *p_hist_packed = (RK_U32 *)mmap(NULL, VDPP_HIST_PACKED_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED, ctx->params.hist_params.hist_addr, 0); + + if (p_hist_packed) { + result->hist.luma_avg = get_avg_luma_from_hist(p_hist_packed + VDPP_HIST_GLOBAL_OFFSET / 4, + VDPP_HIST_GLOBAL_LENGTH); + munmap(p_hist_packed, VDPP_HIST_PACKED_SIZE); + } else { + result->hist.luma_avg = -1; + vdpp_loge("map hist fd(%d) failed! %s\n", ctx->params.hist_params.hist_addr, + strerror(errno)); + } + } + } break; + default: { + vdpp_loge("unsupported control cmd %#x for vdpp2!\n", cmd); + ret = MPP_ERR_VALUE; + } break; + } + + return ret; +} + +RK_S32 vdpp2_check_cap(VdppCtx ictx) +{ + Vdpp2ApiCtx *ctx = ictx; + + if (NULL == ictx) { + vdpp_loge("found NULL ctx %p!\n", ictx); + return VDPP_CAP_UNSUPPORTED; + } + + return check_cap(&ctx->params); +} diff --git a/mpp/vproc/vdpp/vdpp2.h b/mpp/vproc/vdpp/vdpp2.h new file mode 100644 index 000000000..92836cb55 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp2.h @@ -0,0 +1,260 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP2_H +#define VDPP2_H + +#include "vdpp2_reg.h" +#include "vdpp.h" + +typedef enum VdppDciFmt_e { + VDPP_DCI_FMT_RGB888, // 0, MSB order: [23:0]=[R8:G8:B8] + VDPP_DCI_FMT_ARGB8888, // 1, MSB order: [31:0]=[A8:R8:G8:B8] + VDPP_DCI_FMT_Y_8bit_SP = 4, // 4 + VDPP_DCI_FMT_Y_10bit_SP, // 5, [15:0]=[X6:Y10] + VDPP_DCI_FMT_BUTT, +} VdppDciFmt; // for reg-sw_dci_data_format + +typedef struct EsParams_t { + RK_U32 es_bEnabledES; + RK_U32 es_iAngleDelta; + RK_U32 es_iAngleDeltaExtra; + RK_U32 es_iGradNoDirTh; + RK_U32 es_iGradFlatTh; + RK_U32 es_iWgtGain; // should not be 0 + RK_U32 es_iWgtDecay; + RK_U32 es_iLowConfTh; + RK_U32 es_iLowConfRatio; + RK_U32 es_iConfCntTh; + RK_U32 es_iWgtLocalTh; + RK_U32 es_iK1; + RK_U32 es_iK2; + RK_U32 es_iDeltaLimit; + RK_U32 es_iDiff2conf_lut_x[9]; + RK_U32 es_iDiff2conf_lut_y[9]; + RK_U32 es_bEndpointCheckEnable; + RK_U32 es_tan_hi_th; + RK_U32 es_tan_lo_th; +} EsParams; + +typedef struct ShpParams_t { + RK_S32 sharp_enable; + RK_S32 sharp_coloradj_bypass_en; + + RK_S32 lti_h_enable; + RK_S32 lti_h_radius; + RK_S32 lti_h_slope; + RK_S32 lti_h_thresold; + RK_S32 lti_h_gain; + RK_S32 lti_h_noise_thr_pos; + RK_S32 lti_h_noise_thr_neg; + + RK_S32 lti_v_enable; + RK_S32 lti_v_radius; + RK_S32 lti_v_slope; + RK_S32 lti_v_thresold; + RK_S32 lti_v_gain; + RK_S32 lti_v_noise_thr_pos; + RK_S32 lti_v_noise_thr_neg; + + RK_S32 cti_h_enable; + RK_S32 cti_h_radius; + RK_S32 cti_h_slope; + RK_S32 cti_h_thresold; + RK_S32 cti_h_gain; + RK_S32 cti_h_noise_thr_pos; + RK_S32 cti_h_noise_thr_neg; + + RK_S32 peaking_enable; + RK_S32 peaking_gain; + + RK_S32 peaking_coring_enable; + RK_S32 peaking_coring_zero[8]; + RK_S32 peaking_coring_thr[8]; + RK_S32 peaking_coring_ratio[8]; + + RK_S32 peaking_gain_enable; + RK_S32 peaking_gain_pos[8]; + RK_S32 peaking_gain_neg[8]; + + RK_S32 peaking_limit_ctrl_enable; + RK_S32 peaking_limit_ctrl_pos0[8]; + RK_S32 peaking_limit_ctrl_pos1[8]; + RK_S32 peaking_limit_ctrl_neg0[8]; + RK_S32 peaking_limit_ctrl_neg1[8]; + RK_S32 peaking_limit_ctrl_ratio[8]; + RK_S32 peaking_limit_ctrl_bnd_pos[8]; + RK_S32 peaking_limit_ctrl_bnd_neg[8]; + + RK_S32 peaking_edge_ctrl_enable; + RK_S32 peaking_edge_ctrl_non_dir_thr; + RK_S32 peaking_edge_ctrl_dir_cmp_ratio; + RK_S32 peaking_edge_ctrl_non_dir_wgt_offset; + RK_S32 peaking_edge_ctrl_non_dir_wgt_ratio; + RK_S32 peaking_edge_ctrl_dir_cnt_thr; + RK_S32 peaking_edge_ctrl_dir_cnt_avg; + RK_S32 peaking_edge_ctrl_dir_cnt_offset; + RK_S32 peaking_edge_ctrl_diag_dir_thr; + RK_S32 peaking_edge_ctrl_diag_adj_gain_tab[8]; + + RK_S32 peaking_estc_enable; + RK_S32 peaking_estc_delta_offset_h; + RK_S32 peaking_estc_alpha_over_h; + RK_S32 peaking_estc_alpha_under_h; + RK_S32 peaking_estc_alpha_over_unlimit_h; + RK_S32 peaking_estc_alpha_under_unlimit_h; + RK_S32 peaking_estc_delta_offset_v; + RK_S32 peaking_estc_alpha_over_v; + RK_S32 peaking_estc_alpha_under_v; + RK_S32 peaking_estc_alpha_over_unlimit_v; + RK_S32 peaking_estc_alpha_under_unlimit_v; + RK_S32 peaking_estc_delta_offset_d0; + RK_S32 peaking_estc_alpha_over_d0; + RK_S32 peaking_estc_alpha_under_d0; + RK_S32 peaking_estc_alpha_over_unlimit_d0; + RK_S32 peaking_estc_alpha_under_unlimit_d0; + RK_S32 peaking_estc_delta_offset_d1; + RK_S32 peaking_estc_alpha_over_d1; + RK_S32 peaking_estc_alpha_under_d1; + RK_S32 peaking_estc_alpha_over_unlimit_d1; + RK_S32 peaking_estc_alpha_under_unlimit_d1; + RK_S32 peaking_estc_delta_offset_non; + RK_S32 peaking_estc_alpha_over_non; + RK_S32 peaking_estc_alpha_under_non; + RK_S32 peaking_estc_alpha_over_unlimit_non; + RK_S32 peaking_estc_alpha_under_unlimit_non; + RK_S32 peaking_filter_cfg_diag_enh_coef; + + RK_S32 peaking_filt_core_H0[6]; + RK_S32 peaking_filt_core_H1[6]; + RK_S32 peaking_filt_core_H2[6]; + RK_S32 peaking_filt_core_H3[6]; + RK_S32 peaking_filt_core_V0[3]; + RK_S32 peaking_filt_core_V1[3]; + RK_S32 peaking_filt_core_V2[3]; + RK_S32 peaking_filt_core_USM[3]; + + RK_S32 shootctrl_enable; + RK_S32 shootctrl_filter_radius; + RK_S32 shootctrl_delta_offset; + RK_S32 shootctrl_alpha_over; + RK_S32 shootctrl_alpha_under; + RK_S32 shootctrl_alpha_over_unlimit; + RK_S32 shootctrl_alpha_under_unlimit; + + RK_S32 global_gain_enable; + RK_S32 global_gain_lum_mode; + RK_S32 global_gain_lum_grd[6]; + RK_S32 global_gain_lum_val[6]; + RK_S32 global_gain_adp_grd[6]; + RK_S32 global_gain_adp_val[6]; + RK_S32 global_gain_var_grd[6]; + RK_S32 global_gain_var_val[6]; + + RK_S32 color_ctrl_enable; + + RK_S32 color_ctrl_p0_scaling_coef; + RK_S32 color_ctrl_p0_point_u; + RK_S32 color_ctrl_p0_point_v; + RK_S32 color_ctrl_p0_roll_tab[16]; + + RK_S32 color_ctrl_p1_scaling_coef; + RK_S32 color_ctrl_p1_point_u; + RK_S32 color_ctrl_p1_point_v; + RK_S32 color_ctrl_p1_roll_tab[16]; + + RK_S32 color_ctrl_p2_scaling_coef; + RK_S32 color_ctrl_p2_point_u; + RK_S32 color_ctrl_p2_point_v; + RK_S32 color_ctrl_p2_roll_tab[16]; + + RK_S32 color_ctrl_p3_scaling_coef; + RK_S32 color_ctrl_p3_point_u; + RK_S32 color_ctrl_p3_point_v; + RK_S32 color_ctrl_p3_roll_tab[16]; + + RK_S32 tex_adj_enable; + RK_S32 tex_adj_y_mode_select; + RK_S32 tex_adj_mode_select; + RK_S32 tex_adj_grd[6]; + RK_S32 tex_adj_val[6]; +} ShpParams; + +typedef struct hist_params { + RK_U32 hist_cnt_en; // [0, 1], default: 0 + RK_U32 dci_hsd_mode; // [0, 1], default: 0 + RK_U32 dci_vsd_mode; // [0, 2], default: 0 + RK_U32 dci_yrgb_gather_num; // DCI AXI bus yrgb data gather transfer number {0:2, 1:4, 2:8} + RK_U32 dci_yrgb_gather_en; // default: 0 + RK_S32 dci_format; // see VdppDciFmt: {0: rgb24, 1: argb32, 4: yuvsp-8bit, 5: yuvsp-10bit} + RK_S32 dci_alpha_swap; // [0, 1], default: 0 + RK_S32 dci_rbuv_swap; // [0, 1], default: 0 + RK_S32 dci_csc_range; // {0-limited, 1-full}, default: 0 + RK_S32 hist_addr; // dci hist buffer fd + + /* for register checking */ + RK_U32 src_fmt; // see MppFrameFormat, {0-nv12, 15-nv24} + RK_U32 src_width; // real width, unit: pixel + RK_U32 src_height; // real height, unit: pixel + RK_U32 src_width_vir; // aligned width, unit: pixel + RK_U32 src_height_vir; // aligned height, unit: pixel + RK_U32 src_addr; // src buffer fd + RK_U32 working_mode; // 1-IEP2, 2-VEP, 3-DCI_HIST +} HistParams; + +typedef struct vdpp2_params { + RK_U32 src_fmt; // see MppFrameFormat, {0-nv12, 15-nv24} + RK_U32 src_yuv_swap; // {0-no_swap(UV), 1-swap(VU)} + RK_U32 src_width; // real width, unit: pixel + RK_U32 src_height; // real height, unit: pixel + RK_U32 src_width_vir; // aligned width, unit: pixel + RK_U32 src_height_vir; // aligned height, unit: pixel + RK_U32 dst_fmt; // see VDPP_FMT, {0-yuv444sp, 3-yuv420sp} + RK_U32 dst_yuv_swap; // {0-no_swap(UV), 1-swap(VU)} + RK_U32 dst_width; // unit: pixel + RK_U32 dst_height; // unit: pixel + RK_U32 dst_width_vir; // unit: pixel + RK_U32 dst_height_vir; // unit: pixel + RK_U32 yuv_out_diff; // {0:single_buf_out, 1-two_separate_bufs_out} + RK_U32 dst_c_width; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 dst_c_height; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 dst_c_width_vir; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 dst_c_height_vir; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 working_mode; // 1-IEP2, 2-VEP, 3-DCI_HIST + + VdppAddr src; // src frame + VdppAddr dst; // dst frame + VdppAddr dst_c; // dst chroma frame, valid when yuv_out_diff=1 + + /* vdpp features */ + DmsrParams dmsr_params; + ZmeParams zme_params; + + /* vdpp2 features */ + HistParams hist_params; + EsParams es_params; + ShpParams shp_params; +} Vdpp2Params; + +typedef struct vdpp2_api_ctx { + RK_S32 fd; + Vdpp2Params params; + Vdpp2Regs reg; +} Vdpp2ApiCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vdpp2_init(VdppCtx ictx); +MPP_RET vdpp2_deinit(VdppCtx ictx); +MPP_RET vdpp2_control(VdppCtx ictx, VdppCmd cmd, void *iparam); +RK_S32 vdpp2_check_cap(VdppCtx ictx); + +#ifdef __cplusplus +} +#endif + +#endif /* VDPP2_H */ \ No newline at end of file diff --git a/mpp/vproc/vdpp/vdpp2_reg.h b/mpp/vproc/vdpp/vdpp2_reg.h new file mode 100644 index 000000000..f7e9d0c1a --- /dev/null +++ b/mpp/vproc/vdpp/vdpp2_reg.h @@ -0,0 +1,1346 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP2_REG_H +#define VDPP2_REG_H + +#include "vdpp_reg.h" + +#define VDPP2_REG_OFF_DMSR (0x0080) // 0x1080 +#define VDPP2_REG_OFF_DCI_HIST (0x00E0) // 0x10E0 +#define VDPP2_REG_OFF_ES (0x0100) // 0x1100 +#define VDPP2_REG_OFF_SHARP (0x0200) // 0x1200 +#define VDPP2_REG_OFF_YRGB_HOR_COE (0x2000) +#define VDPP2_REG_OFF_YRGB_VER_COE (0x2200) +#define VDPP2_REG_OFF_CBCR_HOR_COE (0x2400) +#define VDPP2_REG_OFF_CBCR_VER_COE (0x2600) +#define VDPP2_REG_OFF_ZME_COMMON (0x2800) + +typedef struct vdpp2_com2_reg { + struct { + RK_U32 sw_vep_frm_en : 1; + } reg0; // 0x0000 + + struct { + RK_U32 sw_vep_src_fmt : 2; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_vep_src_yuv_swap : 2; + RK_U32 sw_reserved_2 : 2; + RK_U32 sw_vep_dst_fmt : 2; + RK_U32 sw_vep_yuvout_diff_en : 1; + RK_U32 sw_reserved_3 : 1; + RK_U32 sw_vep_dst_yuv_swap : 2; + RK_U32 sw_reserved_4 : 2; + RK_U32 sw_vep_debug_data_en : 1; + RK_U32 sw_reserved_5 : 3; + RK_U32 sw_vep_rst_protect_dis : 1; + RK_U32 sys_vep_sreset_p : 1; + RK_U32 sw_vep_init_dis : 1; + RK_U32 sw_reserved_6 : 1; + RK_U32 sw_vep_dbmsr_en : 1; + RK_U32 sw_dci_en : 1; + } reg1; // 0x0004 + + struct { + RK_U32 sw_vdpp_working_mode : 2; + } reg2; // 0x0008 + + struct { + RK_U32 sw_vep_arqos_en : 1; + RK_U32 sw_vep_awqos_en : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_ar_mmu_qos3 : 4; + } reg3; // 0x000C + + struct { + RK_U32 sw_vep_clk_on : 1; + RK_U32 sw_md_clk_on : 1; + RK_U32 sw_dect_clk_on : 1; + RK_U32 sw_me_clk_on : 1; + RK_U32 sw_mc_clk_on : 1; + RK_U32 sw_eedi_clk_on : 1; + RK_U32 sw_ble_clk_on : 1; + RK_U32 sw_out_clk_on : 1; + RK_U32 sw_ctrl_clk_on : 1; + RK_U32 sw_ram_clk_on : 1; + RK_U32 sw_dma_clk_on : 1; + RK_U32 sw_reg_clk_on : 1; + } reg4; // 0x0010 + + struct { + RK_U32 ro_arst_finish_done : 1; + } reg5; // 0x0014 + + struct { + RK_U32 sw_ar_y_qos1 : 4; + RK_U32 sw_ar_y_qos2 : 4; + RK_U32 sw_ar_uv_qos1 : 4; + RK_U32 sw_ar_uv_qos2 : 4; + } reg6; // 0x0018 + + struct { + RK_U32 sw_aw_id7_qos : 4; + RK_U32 sw_aw_id8_qos : 4; + RK_U32 sw_aw_id9_qos : 4; + RK_U32 sw_aw_id10_qos : 4; + } reg7; // 0x001c + + struct { + RK_U32 sw_vep_frm_done_en : 1; + RK_U32 sw_vep_osd_max_en : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_vep_bus_error_en : 1; + RK_U32 sw_vep_timeout_int_en : 1; + RK_U32 sw_vep_config_error_en : 1; + } reg8; // 0x0020 + + struct { + RK_U32 sw_vep_frm_done_clr : 1; + RK_U32 sw_vep_osd_max_clr : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_vep_bus_error_clr : 1; + RK_U32 sw_vep_timeout_int_clr : 1; + RK_U32 sw_vep_config_error_clr : 1; + } reg9; // 0x0024 + + struct { + RK_U32 ro_frm_done_sts : 1; + RK_U32 ro_osd_max_sts : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 ro_bus_error_sts : 1; + RK_U32 ro_timeout_sts : 1; + RK_U32 ro_config_error_sts : 1; + } reg10; // 0x0028, read only + + struct { + RK_U32 ro_frm_done_raw : 1; + RK_U32 ro_osd_max_raw : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 ro_bus_error_raw : 1; + RK_U32 ro_timeout_raw : 1; + RK_U32 ro_config_error_raw : 1; + } reg11; // 0x002C, read only + + struct { + RK_U32 sw_vep_src_vir_y_stride : 16; + } reg12; // 0x0030 + + struct { + RK_U32 sw_vep_dst_vir_y_stride : 16; + RK_U32 sw_vep_dst_vir_c_stride : 16; + } reg13; // 0x0034 + + struct { + RK_U32 sw_vep_src_pic_width : 11; + RK_U32 sw_reserved_1 : 1; + RK_U32 sw_vep_src_right_redundant : 4; + RK_U32 sw_vep_src_pic_height : 11; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_vep_src_down_redundant : 3; + } reg14; // 0x0038 + + struct { + RK_U32 sw_vep_dst_pic_width : 11; + RK_U32 sw_reserved_1 : 1; + RK_U32 sw_vep_dst_right_redundant : 4; + RK_U32 sw_vep_dst_pic_height : 11; + } reg15; // 0x003C + + struct { + RK_U32 sw_vep_dst_pic_width_c : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_vep_dst_right_redundant_c : 4; + RK_U32 sw_vep_dst_pic_height_c : 11; + } reg16; // 0x0040 + + RK_U32 reg17; // 0x0044 + RK_U32 reg18; // 0x0048 + RK_U32 reg19; // 0x004C + + struct { + RK_U32 sw_vep_timeout_cnt : 31; + RK_U32 sw_vep_timeout_en : 1; + } reg20; // 0x0050 + + struct { + RK_U32 svnbuild : 20; + RK_U32 minor : 8; + RK_U32 major : 4; + } reg21; // 0x0054 + + struct { + RK_U32 dbg_frm_cnt : 16; + } reg22; // 0x0058 + + RK_U32 reg23; // 0x005C + + struct { + RK_U32 sw_vep_src_addr_y : 32; + } reg24; // 0x0060 + + struct { + RK_U32 sw_vep_src_addr_uv : 32; + } reg25; // 0x0064 + + struct { + RK_U32 sw_vep_dst_addr_y : 32; + } reg26; // 0x0068 + + struct { + RK_U32 sw_vep_dst_addr_uv : 32; + } reg27; // 0x006C +} RegCom2; // 0x0000 ~ 0x006C, 28 regs + +typedef struct vdpp2_hist_reg { + struct { + RK_U32 sw_dci_yrgb_addr : 32; + } reg0; // 0x00E0 + + struct { + RK_U32 sw_dci_yrgb_vir_stride : 16; + RK_U32 sw_dci_yrgb_gather_num : 4; + RK_U32 sw_dci_yrgb_gather_en : 1; + } reg1; // 0x00E4 + + struct { + RK_U32 sw_vep_src_pic_width : 12; + RK_U32 reserved1 : 4; + RK_U32 sw_vep_src_pic_height : 12; + } reg2; // 0x00E8 + + struct { + RK_U32 sw_dci_data_format : 3; + RK_U32 sw_dci_csc_range : 1; + RK_U32 sw_dci_vsd_mode : 2; + RK_U32 sw_dci_hsd_mode : 1; + RK_U32 sw_dci_alpha_swap : 1; + RK_U32 sw_dci_rb_swap : 1; + RK_U32 reserved1 : 7; + RK_U32 sw_dci_blk_hsize : 8; + RK_U32 sw_dci_blk_vsize : 8; + } reg3; // 0x00EC + + struct { + RK_U32 sw_dci_hist_addr : 32; + } reg4; // 0x00F0 +} RegHist; // 0x10E0 -> 0x00F0, 5 regs + +typedef struct vdpp2_es_reg { + struct { + RK_U32 es_enable : 1; + } reg0; // 0x0100 + + struct { + RK_U32 flat_th : 8; + RK_U32 dir_th : 8; + } reg1; // 0x0104 + + struct { + RK_U32 tan_hi_th : 9; + RK_U32 reserved1 : 7; + RK_U32 tan_lo_th : 9; + } reg2; // 0x0108 + + struct { + RK_U32 ep_chk_en : 1; + RK_U32 reserved1 : 7; + RK_U32 mem_gat_en : 1; + } reg3; // 0x010C + + struct { + RK_U32 diff_gain0 : 16; + RK_U32 diff_limit : 16; + } reg4; // 0x0110 + + struct { + RK_U32 lut_x0 : 16; + RK_U32 diff_gain1 : 16; + } reg5; // 0x0114 + + struct { + RK_U32 lut_x2 : 16; + RK_U32 lut_x1 : 16; + } reg6; // 0x0118 + + struct { + RK_U32 lut_x4 : 16; + RK_U32 lut_x3 : 16; + } reg7; // 0x011C + + struct { + RK_U32 lut_x6 : 16; + RK_U32 lut_x5 : 16; + } reg8; // 0x0120 + + struct { + RK_U32 lut_x8 : 16; + RK_U32 lut_x7 : 16; + } reg9; // 0x0124 + + struct { + RK_U32 lut_y0 : 8; + RK_U32 lut_y1 : 8; + RK_U32 lut_y2 : 8; + RK_U32 lut_y3 : 8; + } reg10; // 0x0128 + + struct { + RK_U32 lut_y4 : 8; + RK_U32 lut_y5 : 8; + RK_U32 lut_y6 : 8; + RK_U32 lut_y7 : 8; + } reg11; // 0x012C + + struct { + RK_U32 lut_y8 : 8; + } reg12; // 0x0130 + + struct { + RK_U32 lut_k0 : 8; + RK_U32 lut_k1 : 8; + RK_U32 lut_k2 : 8; + RK_U32 lut_k3 : 8; + } reg13; // 0x0134 + + struct { + RK_U32 lut_k4 : 8; + RK_U32 lut_k5 : 8; + RK_U32 lut_k6 : 8; + RK_U32 lut_k7 : 8; + } reg14; // 0x0138 + + struct { + RK_U32 wgt_decay : 8; + RK_U32 wgt_gain : 8; + } reg15; // 0x013C + + struct { + RK_U32 conf_mean_th : 8; + RK_U32 conf_cnt_th : 4; + RK_U32 reserved1 : 4; + RK_U32 low_conf_ratio : 8; + RK_U32 low_conf_th : 8; + } reg16; // 0x0140 + + struct { + RK_U32 ink_en : 1; + RK_U32 reserved1 : 3; + RK_U32 ink_mode : 4; + } reg17; // 0x0144 + + RK_U32 reg_018_027[10]; + + struct { + RK_U32 in_rdy : 1; + RK_U32 reserved1 : 3; + RK_U32 mem_in_vsync : 1; + RK_U32 reserved2 : 3; + RK_U32 in_hsync : 1; + RK_U32 reserved3 : 3; + RK_U32 in_vld : 1; + RK_U32 reserved4 : 3; + RK_U32 mem_in_line_cnt : 11; + } reg28; // 0x0170 + + struct { + RK_U32 in_pix : 16; + RK_U32 in_dir : 6; + RK_U32 reserved1 : 2; + RK_U32 in_flat : 2; + } reg29; // 0x0174 + + struct { + RK_U32 out_rdy : 1; + RK_U32 reserved1 : 3; + RK_U32 out_vsync : 1; + RK_U32 reserved2 : 3; + RK_U32 out_hsync : 1; + RK_U32 reserved3 : 3; + RK_U32 out_vld : 1; + RK_U32 reserved4 : 3; + RK_U32 out_line_cnt : 11; + } reg30; // 0x0178 + + struct { + RK_U32 out_pix : 16; + } reg31; // 0x017C + +} RegEs; // 0x1100 ~ 0x117C, 32 regs + +typedef struct vdpp2_shp_reg { + struct { + RK_U32 sw_sharp_enable : 1; + RK_U32 sw_lti_enable : 1; + RK_U32 sw_cti_enable : 1; + RK_U32 sw_peaking_enable : 1; + RK_U32 sw_peaking_ctrl_enable : 1; + RK_U32 reserved1 : 1; + RK_U32 sw_edge_proc_enable : 1; + RK_U32 sw_shoot_ctrl_enable : 1; + RK_U32 sw_gain_ctrl_enable : 1; + RK_U32 sw_color_adj_enable : 1; + RK_U32 sw_texture_adj_enable: 1; + RK_U32 sw_coloradj_bypass_en: 1; + RK_U32 sw_ink_enable : 1; + RK_U32 sw_sharp_redundent_bypass : 1; + } reg0; // 0x0200 + + struct { + RK_U32 sw_mem_gating_en : 1; + RK_U32 sw_lti_gating_en : 1; + RK_U32 sw_cti_gating_en : 1; + RK_U32 sw_peaking_gating_en : 1; + RK_U32 sw_peaking_ctrl_gating_en : 1; + RK_U32 reserved1 : 1; + RK_U32 sw_edge_proc_gating_en : 1; + RK_U32 sw_shoot_ctrl_gating_en : 1; + RK_U32 sw_gain_ctrl_gating_en : 1; + RK_U32 sw_color_adj_gating_en : 1; + RK_U32 sw_texture_adj_gating_en : 1; + } reg1; // 0x0204 + + struct { + RK_U32 sw_peaking_v00 : 4; + RK_U32 sw_peaking_v01 : 4; + RK_U32 sw_peaking_v02 : 4; + RK_U32 sw_peaking_v10 : 4; + RK_U32 sw_peaking_v11 : 4; + RK_U32 sw_peaking_v12 : 4; + } reg2; // 0x0208 + + struct { + RK_U32 sw_peaking_v20 : 4; + RK_U32 sw_peaking_v21 : 4; + RK_U32 sw_peaking_v22 : 4; + RK_U32 sw_peaking_usm0 : 4; + RK_U32 sw_peaking_usm1 : 4; + RK_U32 sw_peaking_usm2 : 4; + RK_U32 sw_diag_coef : 3; + } reg3; // 0x020C + + struct { + RK_U32 sw_peaking_h00 : 6; + RK_U32 reserved1 : 2; + RK_U32 sw_peaking_h01 : 6; + RK_U32 reserved2 : 2; + RK_U32 sw_peaking_h02 : 6; + } reg4; // 0x0210 + + RK_U32 reg5; + + struct { + RK_U32 sw_peaking_h10 : 6; + RK_U32 reserved1 : 2; + RK_U32 sw_peaking_h11 : 6; + RK_U32 reserved2 : 2; + RK_U32 sw_peaking_h12 : 6; + } reg6; // 0x0218 + + RK_U32 reg7; + + struct { + RK_U32 sw_peaking_h20 : 6; + RK_U32 reserved1 : 2; + RK_U32 sw_peaking_h21 : 6; + RK_U32 reserved2 : 2; + RK_U32 sw_peaking_h22 : 6; + } reg8; // 0x0220 + + RK_U32 reg_9_11[3]; + + struct { + RK_U32 sw_peaking0_idx_n0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking0_idx_n1 : 9; + } reg12; // 0x0230 + + struct { + RK_U32 sw_peaking0_idx_n2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking0_idx_n3 : 9; + } reg13; // 0x0234 + + struct { + RK_U32 sw_peaking0_idx_p0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking0_idx_p1 : 9; + } reg14; // 0x0238 + + struct { + RK_U32 sw_peaking0_idx_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking0_idx_p3 : 9; + } reg15; // 0x023C + + struct { + RK_U32 sw_peaking0_value_n1 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking0_value_n2 : 9; + } reg16; // 0x0240 + + struct { + RK_U32 sw_peaking0_value_n3 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking0_value_p1 : 9; + } reg17; // 0x0244 + + struct { + RK_U32 sw_peaking0_value_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking0_value_p3 : 9; + } reg18; // 0x0248 + + struct { + RK_U32 sw_peaking0_ratio_n01: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking0_ratio_n12: 12; + } reg19; // 0x024C + + struct { + RK_U32 sw_peaking0_ratio_n23: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking0_ratio_p01: 12; + } reg20; // 0x0250 + + struct { + RK_U32 sw_peaking0_ratio_p12: 12; + RK_U32 sw_peaking0_ratio_p23: 12; + } reg21; // 0x0254 + + RK_U32 reg22; + + struct { + RK_U32 sw_peaking1_idx_n0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking1_idx_n1 : 9; + } reg23; // 0x025C + + struct { + RK_U32 sw_peaking1_idx_n2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking1_idx_n3 : 9; + } reg24; // 0x0260 + + struct { + RK_U32 sw_peaking1_idx_p0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking1_idx_p1 : 9; + } reg25; // 0x0264 + + struct { + RK_U32 sw_peaking1_idx_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking1_idx_p3 : 9; + } reg26; // 0x0268 + + struct { + RK_U32 sw_peaking1_value_n1 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking1_value_n2 : 9; + } reg27; // 0x026C + + struct { + RK_U32 sw_peaking1_value_n3 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking1_value_p1 : 9; + } reg28; // 0x0270 + + struct { + RK_U32 sw_peaking1_value_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking1_value_p3 : 9; + } reg29; // 0x0274 + + struct { + RK_U32 sw_peaking1_ratio_n01: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking1_ratio_n12: 12; + } reg30; // 0x0278 + + struct { + RK_U32 sw_peaking1_ratio_n23: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking1_ratio_p01: 12; + } reg31; // 0x027C + + struct { + RK_U32 sw_peaking1_ratio_p12: 12; + RK_U32 sw_peaking1_ratio_p23: 12; + } reg32; // 0x0280 + + RK_U32 reg33; + + struct { + RK_U32 sw_peaking2_idx_n0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking2_idx_n1 : 9; + } reg34; // 0x0288 + + struct { + RK_U32 sw_peaking2_idx_n2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking2_idx_n3 : 9; + } reg35; // 0x028C + + struct { + RK_U32 sw_peaking2_idx_p0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking2_idx_p1 : 9; + } reg36; // 0x0290 + + struct { + RK_U32 sw_peaking2_idx_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking2_idx_p3 : 9; + } reg37; // 0x0294 + + struct { + RK_U32 sw_peaking2_value_n1 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking2_value_n2 : 9; + } reg38; // 0x0298 + + struct { + RK_U32 sw_peaking2_value_n3 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking2_value_p1 : 9; + } reg39; // 0x029C + + struct { + RK_U32 sw_peaking2_value_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking2_value_p3 : 9; + } reg40; // 0x02A0 + + struct { + RK_U32 sw_peaking2_ratio_n01: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking2_ratio_n12: 12; + } reg41; // 0x02A4 + + struct { + RK_U32 sw_peaking2_ratio_n23: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking2_ratio_p01: 12; + } reg42; // 0x02A8 + + struct { + RK_U32 sw_peaking2_ratio_p12: 12; + RK_U32 sw_peaking2_ratio_p23: 12; + } reg43; // 0x02AC + + RK_U32 reg44; + + struct { + RK_U32 sw_peaking3_idx_n0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking3_idx_n1 : 9; + } reg45; // 0x02B4 + + struct { + RK_U32 sw_peaking3_idx_n2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking3_idx_n3 : 9; + } reg46; // 0x02B8 + + struct { + RK_U32 sw_peaking3_idx_p0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking3_idx_p1 : 9; + } reg47; // 0x02BC + + struct { + RK_U32 sw_peaking3_idx_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking3_idx_p3 : 9; + } reg48; // 0x02C0 + + struct { + RK_U32 sw_peaking3_value_n1 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking3_value_n2 : 9; + } reg49; // 0x02C4 + + struct { + RK_U32 sw_peaking3_value_n3 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking3_value_p1 : 9; + } reg50; // 0x02C8 + + struct { + RK_U32 sw_peaking3_value_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking3_value_p3 : 9; + } reg51; // 0x02CC + + struct { + RK_U32 sw_peaking3_ratio_n01: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking3_ratio_n12: 12; + } reg52; // 0x02D0 + + struct { + RK_U32 sw_peaking3_ratio_n23: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking3_ratio_p01: 12; + } reg53; // 0x02D4 + + struct { + RK_U32 sw_peaking3_ratio_p12: 12; + RK_U32 sw_peaking3_ratio_p23: 12; + } reg54; // 0x02D8 + + RK_U32 reg55; + + struct { + RK_U32 sw_peaking4_idx_n0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking4_idx_n1 : 9; + } reg56; // 0x02E0 + + struct { + RK_U32 sw_peaking4_idx_n2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking4_idx_n3 : 9; + } reg57; // 0x02E4 + + struct { + RK_U32 sw_peaking4_idx_p0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking4_idx_p1 : 9; + } reg58; // 0x02E8 + + struct { + RK_U32 sw_peaking4_idx_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking4_idx_p3 : 9; + } reg59; // 0x02EC + + struct { + RK_U32 sw_peaking4_value_n1 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking4_value_n2 : 9; + } reg60; // 0x02F0 + + struct { + RK_U32 sw_peaking4_value_n3 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking4_value_p1 : 9; + } reg61; // 0x02F4 + + struct { + RK_U32 sw_peaking4_value_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking4_value_p3 : 9; + } reg62; // 0x02F8 + + struct { + RK_U32 sw_peaking4_ratio_n01: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking4_ratio_n12: 12; + } reg63; // 0x02FC + + struct { + RK_U32 sw_peaking4_ratio_n23: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking4_ratio_p01: 12; + } reg64; // 0x0300 + + struct { + RK_U32 sw_peaking4_ratio_p12: 12; + RK_U32 sw_peaking4_ratio_p23: 12; + } reg65; // 0x0304 + + RK_U32 reg66; + + struct { + RK_U32 sw_peaking5_idx_n0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking5_idx_n1 : 9; + } reg67; // 0x030C + + struct { + RK_U32 sw_peaking5_idx_n2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking5_idx_n3 : 9; + } reg68; // 0x0310 + + struct { + RK_U32 sw_peaking5_idx_p0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking5_idx_p1 : 9; + } reg69; // 0x0314 + + struct { + RK_U32 sw_peaking5_idx_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking5_idx_p3 : 9; + } reg70; // 0x0318 + + struct { + RK_U32 sw_peaking5_value_n1 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking5_value_n2 : 9; + } reg71; // 0x031C + + struct { + RK_U32 sw_peaking5_value_n3 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking5_value_p1 : 9; + } reg72; // 0x0320 + + struct { + RK_U32 sw_peaking5_value_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking5_value_p3 : 9; + } reg73; // 0x0324 + + struct { + RK_U32 sw_peaking5_ratio_n01: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking5_ratio_n12: 12; + } reg74; // 0x0328 + + struct { + RK_U32 sw_peaking5_ratio_n23: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking5_ratio_p01: 12; + } reg75; // 0x032C + + struct { + RK_U32 sw_peaking5_ratio_p12: 12; + RK_U32 sw_peaking5_ratio_p23: 12; + } reg76; // 0x0330 + + RK_U32 reg77; + + struct { + RK_U32 sw_peaking6_idx_n0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking6_idx_n1 : 9; + } reg78; // 0x0338 + + struct { + RK_U32 sw_peaking6_idx_n2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking6_idx_n3 : 9; + } reg79; // 0x033C + + struct { + RK_U32 sw_peaking6_idx_p0 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking6_idx_p1 : 9; + } reg80; // 0x0340 + + struct { + RK_U32 sw_peaking6_idx_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking6_idx_p3 : 9; + } reg81; // 0x0344 + + struct { + RK_U32 sw_peaking6_value_n1 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking6_value_n2 : 9; + } reg82; // 0x0348 + + struct { + RK_U32 sw_peaking6_value_n3 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking6_value_p1 : 9; + } reg83; // 0x034C + + struct { + RK_U32 sw_peaking6_value_p2 : 9; + RK_U32 reserved1 : 7; + RK_U32 sw_peaking6_value_p3 : 9; + } reg84; // 0x0350 + + struct { + RK_U32 sw_peaking6_ratio_n01: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking6_ratio_n12: 12; + } reg85; // 0x0354 + + struct { + RK_U32 sw_peaking6_ratio_n23: 12; + RK_U32 reserved1 : 4; + RK_U32 sw_peaking6_ratio_p01: 12; + } reg86; // 0x0358 + + struct { + RK_U32 sw_peaking6_ratio_p12: 12; + RK_U32 sw_peaking6_ratio_p23: 12; + } reg87; // 0x035C + + RK_U32 reg_88_99[12]; + + struct { + RK_U32 sw_peaking_gain : 10; + RK_U32 reserved1 : 2; + RK_U32 sw_nondir_thr : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_dir_cmp_ratio : 4; + RK_U32 sw_nondir_wgt_ratio : 5; + } reg100; // 0x0390 + + struct { + RK_U32 sw_nondir_wgt_offset : 8; + RK_U32 sw_dir_cnt_thr : 4; + RK_U32 sw_dir_cnt_avg : 3; + RK_U32 reserved1 : 1; + RK_U32 sw_dir_cnt_offset : 4; + RK_U32 sw_diag_dir_thr : 7; + } reg101; // 0x0394 + + struct { + RK_U32 sw_diag_adjgain_tab0 : 4; + RK_U32 sw_diag_adjgain_tab1 : 4; + RK_U32 sw_diag_adjgain_tab2 : 4; + RK_U32 sw_diag_adjgain_tab3 : 4; + RK_U32 sw_diag_adjgain_tab4 : 4; + RK_U32 sw_diag_adjgain_tab5 : 4; + RK_U32 sw_diag_adjgain_tab6 : 4; + RK_U32 sw_diag_adjgain_tab7 : 4; + } reg102; // 0x0398 + + struct { + RK_U32 sw_edge_alpha_over_non : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_edge_alpha_under_non : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_edge_alpha_over_unlimit_non : 7; + RK_U32 reserved3 : 1; + RK_U32 sw_edge_alpha_under_unlimit_non : 7; + } reg103; // 0x039C + + struct { + RK_U32 sw_edge_alpha_over_v : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_edge_alpha_under_v: 7; + RK_U32 reserved2 : 1; + RK_U32 sw_edge_alpha_over_unlimit_v : 7; + RK_U32 reserved3 : 1; + RK_U32 sw_edge_alpha_under_unlimit_v: 7; + } reg104; // 0x03A0 + + struct { + RK_U32 sw_edge_alpha_over_h : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_edge_alpha_under_h: 7; + RK_U32 reserved2 : 1; + RK_U32 sw_edge_alpha_over_unlimit_h : 7; + RK_U32 reserved3 : 1; + RK_U32 sw_edge_alpha_under_unlimit_h: 7; + } reg105; // 0x03A4 + + struct { + RK_U32 sw_edge_alpha_over_d0: 7; + RK_U32 reserved1 : 1; + RK_U32 sw_edge_alpha_under_d0 : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_edge_alpha_over_unlimit_d0: 7; + RK_U32 reserved3 : 1; + RK_U32 sw_edge_alpha_under_unlimit_d0 : 7; + } reg106; // 0x03A8 + + struct { + RK_U32 sw_edge_alpha_over_d1: 7; + RK_U32 reserved1 : 1; + RK_U32 sw_edge_alpha_under_d1 : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_edge_alpha_over_unlimit_d1: 7; + RK_U32 reserved3 : 1; + RK_U32 sw_edge_alpha_under_unlimit_d1 : 7; + } reg107; // 0x03AC + + struct { + RK_U32 sw_edge_delta_offset_non : 8; + RK_U32 sw_edge_delta_offset_v : 8; + RK_U32 sw_edge_delta_offset_h : 8; + } reg108; // 0x03B0 + + struct { + RK_U32 sw_edge_delta_offset_d0 : 8; + RK_U32 sw_edge_delta_offset_d1 : 8; + } reg109; // 0x03B4 + + struct { + RK_U32 sw_shoot_filt_radius : 1; + RK_U32 reserved1 : 3; + RK_U32 sw_shoot_delta_offset: 8; + RK_U32 sw_shoot_alpha_over : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_shoot_alpha_under : 7; + } reg110; // 0x03B8 + + struct { + RK_U32 sw_shoot_alpha_over_unlimit : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_shoot_alpha_under_unlimit : 7; + } reg111; // 0x03BC + + struct { + RK_U32 sw_adp_idx0 : 8; + RK_U32 reserved1 : 2; + RK_U32 sw_adp_idx1 : 8; + RK_U32 reserved2 : 2; + RK_U32 sw_adp_idx2 : 8; + } reg112; // 0x03C0 + + struct { + RK_U32 sw_adp_idx3 : 8; + RK_U32 reserved1 : 4; + RK_U32 sw_adp_gain0 : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_adp_gain1 : 7; + } reg113; // 0x03C4 + + struct { + RK_U32 sw_adp_gain2 : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_adp_gain3 : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_adp_gain4 : 7; + } reg114; // 0x03C8 + + struct { + RK_U32 sw_adp_slp01 : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_adp_slp12 : 11; + } reg115; // 0x03CC + + RK_U32 reg_116_127[12]; + + struct { + RK_U32 sw_adp_slp23 : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_adp_slp34 : 11; + } reg128; // 0x0400 + + struct { + RK_U32 sw_adp_slp45 : 11; + RK_U32 sw_var_idx0 : 8; + RK_U32 reserved1 : 2; + RK_U32 sw_var_idx1 : 8; + } reg129; // 0x0404 + + struct { + RK_U32 sw_var_idx2 : 8; + RK_U32 reserved1 : 4; + RK_U32 sw_var_idx3 : 8; + RK_U32 reserved2 : 4; + RK_U32 sw_var_gain0 : 7; + } reg130; // 0x0408 + + struct { + RK_U32 sw_var_gain1 : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_var_gain2 : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_var_gain3 : 7; + RK_U32 reserved3 : 1; + RK_U32 sw_var_gain4 : 7; + } reg131; // 0x040C + + struct { + RK_U32 sw_var_slp01 : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_var_slp12 : 11; + } reg132; // 0x0410 + + struct { + RK_U32 sw_var_slp23 : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_var_slp34 : 11; + } reg133; // 0x0414 + + struct { + RK_U32 sw_var_slp45 : 11; + RK_U32 reserved1 : 5; + RK_U32 sw_lum_select : 2; + RK_U32 reserved2 : 2; + RK_U32 sw_lum_idx0 : 8; + } reg134; // 0x0418 + + struct { + RK_U32 sw_lum_idx1 : 8; + RK_U32 reserved1 : 2; + RK_U32 sw_lum_idx2 : 8; + RK_U32 reserved2 : 2; + RK_U32 sw_lum_idx3 : 8; + } reg135; // 0x041C + + struct { + RK_U32 sw_lum_gain0 : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_lum_gain1 : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_lum_gain2 : 7; + RK_U32 reserved3 : 1; + RK_U32 sw_lum_gain3 : 7; + } reg136; // 0x0420 + + struct { + RK_U32 sw_lum_gain4 : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_lum_slp01 : 11; + RK_U32 reserved2 : 1; + RK_U32 sw_lum_slp12 : 11; + } reg137; // 0x0424 + + struct { + RK_U32 sw_lum_slp23 : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_lum_slp34 : 11; + } reg138; // 0x0428 + + struct { + RK_U32 sw_lum_slp45 : 11; + } reg139; // 0x042C + + struct { + RK_U32 sw_adj_point_x0 : 8; + RK_U32 reserved1 : 4; + RK_U32 sw_adj_point_y0 : 8; + RK_U32 reserved2 : 4; + RK_U32 sw_adj_scaling_coef0 : 3; + } reg140; // 0x0430 + + struct { + RK_U32 sw_coloradj_tab0_0 : 5; + RK_U32 sw_coloradj_tab0_1 : 5; + RK_U32 sw_coloradj_tab0_2 : 5; + RK_U32 sw_coloradj_tab0_3 : 5; + RK_U32 sw_coloradj_tab0_4 : 5; + RK_U32 sw_coloradj_tab0_5 : 5; + } reg141; // 0x0434 + + struct { + RK_U32 sw_coloradj_tab0_6 : 5; + RK_U32 sw_coloradj_tab0_7 : 5; + RK_U32 sw_coloradj_tab0_8 : 5; + RK_U32 sw_coloradj_tab0_9 : 5; + RK_U32 sw_coloradj_tab0_10 : 5; + RK_U32 sw_coloradj_tab0_11 : 5; + } reg142; // 0x0438 + + struct { + RK_U32 sw_coloradj_tab0_12 : 5; + RK_U32 sw_coloradj_tab0_13 : 5; + RK_U32 sw_coloradj_tab0_14 : 5; + RK_U32 sw_coloradj_tab0_15 : 5; + } reg143; // 0x043C + + struct { + RK_U32 sw_adj_point_x1 : 8; + RK_U32 reserved1 : 4; + RK_U32 sw_adj_point_y1 : 8; + RK_U32 reserved2 : 4; + RK_U32 sw_adj_scaling_coef1 : 3; + } reg144; // 0x0440 + + struct { + RK_U32 sw_coloradj_tab1_0 : 5; + RK_U32 sw_coloradj_tab1_1 : 5; + RK_U32 sw_coloradj_tab1_2 : 5; + RK_U32 sw_coloradj_tab1_3 : 5; + RK_U32 sw_coloradj_tab1_4 : 5; + RK_U32 sw_coloradj_tab1_5 : 5; + } reg145; // 0x0444 + + struct { + RK_U32 sw_coloradj_tab1_6 : 5; + RK_U32 sw_coloradj_tab1_7 : 5; + RK_U32 sw_coloradj_tab1_8 : 5; + RK_U32 sw_coloradj_tab1_9 : 5; + RK_U32 sw_coloradj_tab1_10 : 5; + RK_U32 sw_coloradj_tab1_11 : 5; + } reg146; // 0x0448 + + struct { + RK_U32 sw_coloradj_tab1_12 : 5; + RK_U32 sw_coloradj_tab1_13 : 5; + RK_U32 sw_coloradj_tab1_14 : 5; + RK_U32 sw_coloradj_tab1_15 : 5; + } reg147; // 0x044C + + struct { + RK_U32 sw_adj_point_x2 : 8; + RK_U32 reserved1 : 4; + RK_U32 sw_adj_point_y2 : 8; + RK_U32 reserved2 : 4; + RK_U32 sw_adj_scaling_coef2 : 3; + } reg148; // 0x0450 + + struct { + RK_U32 sw_coloradj_tab2_0 : 5; + RK_U32 sw_coloradj_tab2_1 : 5; + RK_U32 sw_coloradj_tab2_2 : 5; + RK_U32 sw_coloradj_tab2_3 : 5; + RK_U32 sw_coloradj_tab2_4 : 5; + RK_U32 sw_coloradj_tab2_5 : 5; + } reg149; // 0x0454 + + struct { + RK_U32 sw_coloradj_tab2_6 : 5; + RK_U32 sw_coloradj_tab2_7 : 5; + RK_U32 sw_coloradj_tab2_8 : 5; + RK_U32 sw_coloradj_tab2_9 : 5; + RK_U32 sw_coloradj_tab2_10 : 5; + RK_U32 sw_coloradj_tab2_11 : 5; + } reg150; // 0x0458 + + struct { + RK_U32 sw_coloradj_tab2_12 : 5; + RK_U32 sw_coloradj_tab2_13 : 5; + RK_U32 sw_coloradj_tab2_14 : 5; + RK_U32 sw_coloradj_tab2_15 : 5; + } reg151; // 0x045C + + struct { + RK_U32 sw_adj_point_x3 : 8; + RK_U32 reserved1 : 4; + RK_U32 sw_adj_point_y3 : 8; + RK_U32 reserved2 : 4; + RK_U32 sw_adj_scaling_coef3 : 3; + } reg152; // 0x0460 + + struct { + RK_U32 sw_coloradj_tab3_0 : 5; + RK_U32 sw_coloradj_tab3_1 : 5; + RK_U32 sw_coloradj_tab3_2 : 5; + RK_U32 sw_coloradj_tab3_3 : 5; + RK_U32 sw_coloradj_tab3_4 : 5; + RK_U32 sw_coloradj_tab3_5 : 5; + } reg153; // 0x0464 + + struct { + RK_U32 sw_coloradj_tab3_6 : 5; + RK_U32 sw_coloradj_tab3_7 : 5; + RK_U32 sw_coloradj_tab3_8 : 5; + RK_U32 sw_coloradj_tab3_9 : 5; + RK_U32 sw_coloradj_tab3_10 : 5; + RK_U32 sw_coloradj_tab3_11 : 5; + } reg154; // 0x0468 + + struct { + RK_U32 sw_coloradj_tab3_12 : 5; + RK_U32 sw_coloradj_tab3_13 : 5; + RK_U32 sw_coloradj_tab3_14 : 5; + RK_U32 sw_coloradj_tab3_15 : 5; + } reg155; // 0x046C + + struct { + RK_U32 sw_idxmode_select : 1; + RK_U32 sw_ymode_select : 2; + RK_U32 reserved1 : 1; + RK_U32 sw_tex_idx0 : 8; + RK_U32 reserved2 : 4; + RK_U32 sw_tex_idx1 : 8; + } reg156; // 0x0470 + + struct { + RK_U32 sw_tex_idx2 : 8; + RK_U32 reserved1 : 4; + RK_U32 sw_tex_idx3 : 8; + RK_U32 reserved2 : 4; + RK_U32 sw_tex_gain0 : 7; + } reg157; // 0x0474 + + struct { + RK_U32 sw_tex_gain1 : 7; + RK_U32 reserved1 : 1; + RK_U32 sw_tex_gain2 : 7; + RK_U32 reserved2 : 1; + RK_U32 sw_tex_gain3 : 7; + RK_U32 reserved3 : 1; + RK_U32 sw_tex_gain4 : 7; + } reg158; // 0x0478 + + struct { + RK_U32 sw_tex_slp01 : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_tex_slp12 : 11; + } reg159; // 0x047C + + struct { + RK_U32 sw_tex_slp23 : 11; + RK_U32 reserved1 : 1; + RK_U32 sw_tex_slp34 : 11; + } reg160; // 0x0480 + + struct { + RK_U32 sw_tex_slp45 : 11; + } reg161; // 0x0484 + + struct { + RK_U32 sw_ltih_radius : 1; + RK_U32 reserved1 : 3; + RK_U32 sw_ltih_slp1 : 9; + RK_U32 reserved2 : 3; + RK_U32 sw_ltih_thr1 : 9; + } reg162; // 0x0488 + + struct { + RK_U32 sw_ltih_noisethrneg : 10; + RK_U32 reserved1 : 2; + RK_U32 sw_ltih_noisethrpos : 10; + RK_U32 reserved2 : 2; + RK_U32 sw_ltih_tigain : 5; + } reg163; // 0x048C + + struct { + RK_U32 sw_ltiv_radius : 1; + RK_U32 reserved1 : 3; + RK_U32 sw_ltiv_slp1 : 9; + RK_U32 reserved2 : 3; + RK_U32 sw_ltiv_thr1 : 9; + } reg164; // 0x0490 + + struct { + RK_U32 sw_ltiv_noisethrneg : 10; + RK_U32 reserved1 : 2; + RK_U32 sw_ltiv_noisethrpos : 10; + RK_U32 reserved2 : 2; + RK_U32 sw_ltiv_tigain : 5; + } reg165; // 0x0494 + + struct { + RK_U32 sw_ctih_radius : 1; + RK_U32 reserved1 : 3; + RK_U32 sw_ctih_slp1 : 9; + RK_U32 reserved2 : 3; + RK_U32 sw_ctih_thr1 : 9; + } reg166; // 0x0498 + + struct { + RK_U32 sw_ctih_noisethrneg : 10; + RK_U32 reserved1 : 2; + RK_U32 sw_ctih_noisethrpos : 10; + RK_U32 reserved2 : 2; + RK_U32 sw_ctih_tigain : 5; + } reg167; // 0x049C + + RK_U32 reg_168_169[2]; + + struct { + RK_U32 sw_ink_mode : 4; + } reg170; // 0x04A8 + + RK_U32 reg171; + +} RegShp; // 0x1200 ~ 0x14a8, 171 regs + +typedef struct vdpp2_reg { + RegCom2 common; /* offset: 0x1000, end: 0x106C, size: 112 */ + RegDmsr dmsr; /* offset: 0x1080, end: 0x10D0, size: 84 */ + RegHist hist; /* offset: 0x10E0, end: 0x10F0, size: 20 */ + RegEs es; /* offset: 0x1100, end: 0x117C, size: 128 */ + RegShp sharp; /* offset: 0x1200, end: 0x14a8, size: 684 */ + RegZme zme; /* offset: 0x2000, end: 0x2844, size: 1160(valid)/2120(total) */ +} Vdpp2Regs; + +#endif /* VDPP2_REG_H */ diff --git a/mpp/vproc/vdpp/vdpp3.c b/mpp/vproc/vdpp/vdpp3.c new file mode 100644 index 000000000..97ca8ed47 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp3.c @@ -0,0 +1,1110 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpp" + +#include +#include +#include +#include +#include + +#include "mpp_common.h" +#include "mpp_env.h" +#include "mpp_service.h" +#include "mpp_platform.h" + +#include "vdpp3.h" + +#define VDPP3_VEP_MAX_WIDTH (1920) +#define VDPP3_VEP_MAX_HEIGHT (2048) +#define VDPP3_HIST_MAX_WIDTH (4096) +#define VDPP3_HIST_MAX_HEIGHT (4096) +#define VDPP3_MODE_MIN_WIDTH (128) +#define VDPP3_MODE_MIN_HEIGHT (128) + +#define VDPP3_HIST_HSD_DISABLE_LIMIT (1920) +#define VDPP3_HIST_VSD_DISABLE_LIMIT (1080) +#define VDPP3_HIST_VSD_MODE_1_LIMIT (2160) + +// default log level: warning +extern RK_U32 vdpp_debug; + +void set_pyramid_to_vdpp3_reg(const PyrParams *pyr_params, RegPyr* pyr_reg) +{ + pyr_reg->reg0.sw_pyramid_en = pyr_params->pyr_en; + pyr_reg->reg1.sw_pyramid_layer1_dst_addr = pyr_params->layer_imgs[0].mem_addr; + pyr_reg->reg3.sw_pyramid_layer2_dst_addr = pyr_params->layer_imgs[1].mem_addr; + pyr_reg->reg5.sw_pyramid_layer3_dst_addr = pyr_params->layer_imgs[2].mem_addr; + pyr_reg->reg2.sw_pyramid_layer1_dst_vir_wid = pyr_params->layer_imgs[0].wid_vir / 4; + pyr_reg->reg4.sw_pyramid_layer2_dst_vir_wid = pyr_params->layer_imgs[1].wid_vir / 4; + pyr_reg->reg6.sw_pyramid_layer3_dst_vir_wid = pyr_params->layer_imgs[2].wid_vir / 4; + + vdpp_logv("set reg: pyr_en=%d, fd=%d/%d/%d, vir_wid=%d/%d/%d\n", pyr_reg->reg0.sw_pyramid_en, + pyr_reg->reg1.sw_pyramid_layer1_dst_addr, pyr_reg->reg3.sw_pyramid_layer2_dst_addr, + pyr_reg->reg5.sw_pyramid_layer3_dst_addr, pyr_reg->reg2.sw_pyramid_layer1_dst_vir_wid, + pyr_reg->reg4.sw_pyramid_layer2_dst_vir_wid, pyr_reg->reg6.sw_pyramid_layer3_dst_vir_wid); + + if ((pyr_reg->reg2.sw_pyramid_layer1_dst_vir_wid & 0x3) || + (pyr_reg->reg4.sw_pyramid_layer2_dst_vir_wid & 0x3) || + (pyr_reg->reg6.sw_pyramid_layer3_dst_vir_wid & 0x3)) { + vdpp_logw("the pyr virtual width is not x4 aligned, pyr result might not be correct!!\n"); + } +} + +void set_bbd_to_vdpp3_reg(const BbdParams* bbd_params, RegBbd* bbd_reg) +{ + bbd_reg->reg0.sw_det_en = bbd_params->bbd_en; + bbd_reg->reg0.sw_det_blcklmt = bbd_params->bbd_det_blcklmt; + vdpp_logv("set reg: bbd_en=%d, lmt=%d\n", bbd_reg->reg0.sw_det_en, bbd_reg->reg0.sw_det_blcklmt); +} + +void set_zme_to_vdpp3_reg(const ZmeParams *zme_params, RegZme3 *zme_reg) +{ + VdppZmeFmt zme_format_in = FMT_YCbCr420_888; /* only support yuv420 as input */ + VdppZmeScaleInfo yrgb_scl_info = {0}; + VdppZmeScaleInfo cbcr_scl_info = {0}; + + yrgb_scl_info.act_width = zme_params->src_width; + yrgb_scl_info.act_height = zme_params->src_height; + yrgb_scl_info.dsp_width = zme_params->dst_width; + yrgb_scl_info.dsp_height = zme_params->dst_height; + yrgb_scl_info.xscl_mode = SCL_MPH; + yrgb_scl_info.yscl_mode = SCL_MPH; + yrgb_scl_info.dering_en = zme_params->zme_dering_enable; + calc_scale_factor(zme_params, &yrgb_scl_info, zme_params->zme_bypass_en); + + cbcr_scl_info.act_width = zme_params->src_width / 2; + cbcr_scl_info.act_height = zme_params->src_height / 2; + if (zme_params->dst_fmt == VDPP_FMT_YUV444) { + if (!zme_params->yuv_out_diff) { + cbcr_scl_info.dsp_width = zme_params->dst_width; + cbcr_scl_info.dsp_height = zme_params->dst_height; + } else { + cbcr_scl_info.dsp_width = zme_params->dst_c_width; + cbcr_scl_info.dsp_height = zme_params->dst_c_height; + } + } else if (zme_params->dst_fmt == VDPP_FMT_YUV420) { + if (!zme_params->yuv_out_diff) { + cbcr_scl_info.dsp_width = zme_params->dst_width / 2; + cbcr_scl_info.dsp_height = zme_params->dst_height / 2; + } else { + /** @note: half the chroma size by user! */ + cbcr_scl_info.dsp_width = zme_params->dst_c_width; + cbcr_scl_info.dsp_height = zme_params->dst_c_height; + } + } else { + /* not supported */ + vdpp_loge("invalid output vdpp format %d!\n", zme_params->dst_fmt); + } + cbcr_scl_info.xscl_mode = SCL_MPH; + cbcr_scl_info.yscl_mode = SCL_MPH; + cbcr_scl_info.dering_en = zme_params->zme_dering_enable; + calc_scale_factor(zme_params, &cbcr_scl_info, zme_params->zme_bypass_en); + + /* 0x0800(reg0) */ + zme_reg->reg0.bypass_en = 0; + zme_reg->reg0.align_en = 0; + zme_reg->reg0.format_in = zme_format_in; + if (zme_params->dst_fmt == VDPP_FMT_YUV444) + zme_reg->reg0.format_out = FMT_YCbCr444_888; + else + zme_reg->reg0.format_out = FMT_YCbCr420_888; + zme_reg->reg0.auto_gating_en = 1; + + /* 0x0804 ~ 0x080C(reg1 ~ reg3), skip */ + + /* 0x0810(reg4) */ + zme_reg->reg4.yrgb_xsd_en = yrgb_scl_info.xsd_en; + zme_reg->reg4.yrgb_xsu_en = yrgb_scl_info.xsu_en; + zme_reg->reg4.yrgb_scl_mode = yrgb_scl_info.xscl_mode; + zme_reg->reg4.yrgb_ysd_en = yrgb_scl_info.ysd_en; + zme_reg->reg4.yrgb_ysu_en = yrgb_scl_info.ysu_en; + zme_reg->reg4.yrgb_yscl_mode = yrgb_scl_info.yscl_mode; + zme_reg->reg4.yrgb_dering_en = yrgb_scl_info.dering_en; + zme_reg->reg4.yrgb_gt_en = yrgb_scl_info.ygt_en; + zme_reg->reg4.yrgb_gt_mode = yrgb_scl_info.ygt_mode; + zme_reg->reg4.yrgb_xsd_bypass = yrgb_scl_info.xsd_bypass; + zme_reg->reg4.yrgb_ys_bypass = yrgb_scl_info.ys_bypass; + zme_reg->reg4.yrgb_xsu_bypass = yrgb_scl_info.xsu_bypass; + + /* new vars in vdpp3 */ + zme_reg->reg4.yrgb_xscl_coe_sel = yrgb_scl_info.xscl_coe_idx; + zme_reg->reg4.yrgb_yscl_coe_sel = yrgb_scl_info.yscl_coe_idx; + + /* 0x0814 ~ 0x0818(reg5 ~ reg6), skip */ + + /* 0x081C(reg7) */ + zme_reg->reg7.yrgb_dering_sen0 = zme_params->zme_dering_sen_0; + zme_reg->reg7.yrgb_dering_sen1 = zme_params->zme_dering_sen_1; + zme_reg->reg7.yrgb_dering_alpha = zme_params->zme_dering_blend_alpha; + zme_reg->reg7.yrgb_dering_delta = zme_params->zme_dering_blend_beta; + + /* 0x0820(reg8) */ + zme_reg->reg8.yrgb_xscl_factor = yrgb_scl_info.xscl_factor; + zme_reg->reg8.yrgb_xscl_offset = yrgb_scl_info.xscl_offset; + + /* 0x0824(reg9) */ + zme_reg->reg9.yrgb_yscl_factor = yrgb_scl_info.yscl_factor; + zme_reg->reg9.yrgb_yscl_offset = yrgb_scl_info.yscl_offset; + + /* 0x0828 ~ 0x082C(reg10 ~ reg11), skip */ + + /* 0x0830(reg12) */ + zme_reg->reg12.cbcr_xsd_en = cbcr_scl_info.xsd_en; + zme_reg->reg12.cbcr_xsu_en = cbcr_scl_info.xsu_en; + zme_reg->reg12.cbcr_xscl_mode = cbcr_scl_info.xscl_mode; + zme_reg->reg12.cbcr_ysd_en = cbcr_scl_info.ysd_en; + zme_reg->reg12.cbcr_ysu_en = cbcr_scl_info.ysu_en; + zme_reg->reg12.cbcr_yscl_mode = cbcr_scl_info.yscl_mode; + zme_reg->reg12.cbcr_dering_en = cbcr_scl_info.dering_en; + zme_reg->reg12.cbcr_gt_en = cbcr_scl_info.ygt_en; + zme_reg->reg12.cbcr_gt_mode = cbcr_scl_info.ygt_mode; + zme_reg->reg12.cbcr_xsd_bypass = cbcr_scl_info.xsd_bypass; + zme_reg->reg12.cbcr_ys_bypass = cbcr_scl_info.ys_bypass; + zme_reg->reg12.cbcr_xsu_bypass = cbcr_scl_info.xsu_bypass; + + /* new vars in vdpp3 */ + zme_reg->reg12.cbcr_xscl_coe_sel = cbcr_scl_info.xscl_coe_idx; + zme_reg->reg12.cbcr_yscl_coe_sel = cbcr_scl_info.yscl_coe_idx; + + /* 0x0834 ~ 0x0838(reg13 ~ reg14), skip */ + + /* 0x083C(reg15) */ + zme_reg->reg15.cbcr_dering_sen0 = zme_params->zme_dering_sen_0; + zme_reg->reg15.cbcr_dering_sen1 = zme_params->zme_dering_sen_1; + zme_reg->reg15.cbcr_dering_alpha = zme_params->zme_dering_blend_alpha; + zme_reg->reg15.cbcr_dering_delta = zme_params->zme_dering_blend_beta; + + /* 0x0840(reg16) */ + zme_reg->reg16.cbcr_xscl_factor = cbcr_scl_info.xscl_factor; + zme_reg->reg16.cbcr_xscl_offset = cbcr_scl_info.xscl_offset; + + /* 0x0844(reg17) */ + zme_reg->reg17.cbcr_yscl_factor = cbcr_scl_info.yscl_factor; + zme_reg->reg17.cbcr_yscl_offset = cbcr_scl_info.yscl_offset; +} + +static MPP_RET vdpp3_params_to_reg(Vdpp3Params* src_params, Vdpp3ApiCtx *ctx) +{ + Vdpp3Regs *dst_reg = &ctx->reg; + DmsrParams *dmsr_params = &src_params->dmsr_params; + ZmeParams *zme_params = &src_params->zme_params; + EsParams *es_params = &src_params->es_params; + ShpParams *shp_params = &src_params->shp_params; + HistParams *hist_params = &src_params->hist_params; + PyrParams *pyr_params = &src_params->pyr_params; + BbdParams *bbd_params = &src_params->bbd_params; + + memset(dst_reg, 0, sizeof(*dst_reg)); + + dst_reg->common.reg0.sw_vep_frm_en = 1; + + /* 0x0004(reg1) */ + dst_reg->common.reg1.sw_vep_src_fmt = VDPP_FMT_YUV420; // vep only support yuv420 + dst_reg->common.reg1.sw_vep_src_yuv_swap = src_params->src_yuv_swap; + + if (MPP_FMT_YUV420SP_VU == src_params->src_fmt) + dst_reg->common.reg1.sw_vep_src_yuv_swap = 1; + + dst_reg->common.reg1.sw_vep_dst_fmt = src_params->dst_fmt; + dst_reg->common.reg1.sw_vep_dst_yuv_swap = src_params->dst_yuv_swap; + dst_reg->common.reg1.sw_vep_dbmsr_en = (src_params->working_mode == VDPP_WORK_MODE_DCI) + ? 0 + : dmsr_params->dmsr_enable; + + vdpp_logv("set reg: vep_src_fmt=%d(must be 3 here), vep_src_yuv_swap=%d\n", + dst_reg->common.reg1.sw_vep_src_fmt, dst_reg->common.reg1.sw_vep_src_yuv_swap); + vdpp_logv("set reg: vep_dst_fmt=%d(vdppFmt: 0-444sp; 3-420sp), vep_dst_yuv_swap=%d\n", + dst_reg->common.reg1.sw_vep_dst_fmt, dst_reg->common.reg1.sw_vep_dst_yuv_swap); + + /* 0x0008(reg2) */ + dst_reg->common.reg2.sw_vdpp_working_mode = src_params->working_mode; + vdpp_logv("set reg: vdpp_working_mode=%d (1-iep2, 2-vep, 3-dci)\n", src_params->working_mode); + + /* 0x000C ~ 0x001C(reg3 ~ reg7), skip */ + dst_reg->common.reg4.sw_vep_clk_on = 1; + dst_reg->common.reg4.sw_ctrl_clk_on = 1; + dst_reg->common.reg4.sw_ram_clk_on = 1; + dst_reg->common.reg4.sw_dma_clk_on = 1; + dst_reg->common.reg4.sw_reg_clk_on = 1; + + /* 0x0020(reg8) */ + dst_reg->common.reg8.sw_vep_frm_done_en = 1; + dst_reg->common.reg8.sw_vep_osd_max_en = 1; + dst_reg->common.reg8.sw_vep_bus_error_en = 1; + dst_reg->common.reg8.sw_vep_timeout_int_en = 1; + dst_reg->common.reg8.sw_vep_config_error_en = 1; + /* 0x0024 ~ 0x002C(reg9 ~ reg11), skip */ + { + RK_U32 src_right_redundant = (16 - (src_params->src_width & 0xF)) & 0xF; + RK_U32 src_down_redundant = (8 - (src_params->src_height & 0x7)) & 0x7; + // TODO: check if the dst_right_redundant is aligned to 2 or 4(for yuv420sp) + RK_U32 dst_right_redundant = (16 - (src_params->dst_width & 0xF)) & 0xF; + /* 0x0030(reg12) */ + dst_reg->common.reg12.sw_vep_src_vir_y_stride = src_params->src_width_vir / 4; + + /* 0x0034(reg13) */ + dst_reg->common.reg13.sw_vep_dst_vir_y_stride = src_params->dst_width_vir / 4; + + /* 0x0038(reg14) */ + dst_reg->common.reg14.sw_vep_src_pic_width = src_params->src_width + src_right_redundant - 1; + dst_reg->common.reg14.sw_vep_src_right_redundant = src_right_redundant; + dst_reg->common.reg14.sw_vep_src_pic_height = src_params->src_height + src_down_redundant - 1; + dst_reg->common.reg14.sw_vep_src_down_redundant = src_down_redundant; + + /* 0x003C(reg15) */ + dst_reg->common.reg15.sw_vep_dst_pic_width = src_params->dst_width + dst_right_redundant - 1; + dst_reg->common.reg15.sw_vep_dst_right_redundant = dst_right_redundant; + dst_reg->common.reg15.sw_vep_dst_pic_height = src_params->dst_height - 1; + } + /* 0x0040 ~ 0x005C(reg16 ~ reg23), skip */ + dst_reg->common.reg20.sw_vep_timeout_en = 1; + dst_reg->common.reg20.sw_vep_timeout_cnt = 0x8FFFFFF; + + /* 0x0060(reg24) */ + dst_reg->common.reg24.sw_vep_src_addr_y = src_params->src.y; + + /* 0x0064(reg25) */ + dst_reg->common.reg25.sw_vep_src_addr_uv = src_params->src.cbcr; + + /* 0x0068(reg26) */ + dst_reg->common.reg26.sw_vep_dst_addr_y = src_params->dst.y; + + /* 0x006C(reg27) */ + dst_reg->common.reg27.sw_vep_dst_addr_uv = src_params->dst.cbcr; + + if (src_params->yuv_out_diff) { + RK_S32 dst_c_width = src_params->dst_c_width; + RK_S32 dst_c_height = src_params->dst_c_height; + RK_S32 dst_c_width_vir = src_params->dst_c_width_vir; + RK_S32 dst_redundant_c = 0; + + /** @note: no need to half the chroma size for YUV420, since vdpp will do it according to the output format! */ + if (dst_reg->common.reg1.sw_vep_dst_fmt == VDPP_FMT_YUV420) { + dst_c_width *= 2; + dst_c_height *= 2; + dst_c_width_vir *= 2; + } + + dst_redundant_c = (16 - (dst_c_width & 0xF)) & 0xF; + dst_reg->common.reg1.sw_vep_yuvout_diff_en = 1; + dst_reg->common.reg13.sw_vep_dst_vir_c_stride = dst_c_width_vir / 4; // unit: dword + /* 0x0040(reg16) */ + dst_reg->common.reg16.sw_vep_dst_pic_width_c = dst_c_width + dst_redundant_c - 1; + dst_reg->common.reg16.sw_vep_dst_right_redundant_c = dst_redundant_c; + dst_reg->common.reg16.sw_vep_dst_pic_height_c = dst_c_height - 1; + + dst_reg->common.reg27.sw_vep_dst_addr_uv = src_params->dst_c.cbcr; + + vdpp_logv("set reg: vep_dst_virc_strd=%d [dword], vep_dst_right_redundant_c=%d [pixel]\n", + dst_reg->common.reg13.sw_vep_dst_vir_c_stride, + dst_reg->common.reg16.sw_vep_dst_right_redundant_c); + vdpp_logv("set reg: vep_dst_pic_wid_c=%d [pixel], vep_dst_pic_hgt_c=%d [pixel]\n", + dst_reg->common.reg16.sw_vep_dst_pic_width_c, + dst_reg->common.reg16.sw_vep_dst_pic_height_c); + } + vdpp_logv("set reg: vep_yuvout_diff_en=%d, vep_dst_addr_uv(fd)=%d\n", + dst_reg->common.reg1.sw_vep_yuvout_diff_en, dst_reg->common.reg27.sw_vep_dst_addr_uv); + + /* vdpp1 */ + set_dmsr_to_vdpp_reg(dmsr_params, &dst_reg->dmsr); + + zme_params->src_width = src_params->src_width; + zme_params->src_height = src_params->src_height; + zme_params->dst_width = src_params->dst_width; + zme_params->dst_height = src_params->dst_height; + zme_params->dst_fmt = src_params->dst_fmt; + zme_params->yuv_out_diff = src_params->yuv_out_diff; + zme_params->dst_c_width = src_params->dst_c_width; + zme_params->dst_c_height = src_params->dst_c_height; + set_zme_to_vdpp3_reg(zme_params, &dst_reg->zme); + + /* vdpp2 */ + hist_params->src_fmt = src_params->src_fmt; + hist_params->src_width = src_params->src_width; + hist_params->src_height = src_params->src_height; + hist_params->src_width_vir = src_params->src_width_vir; + hist_params->src_height_vir = src_params->src_height_vir; + hist_params->src_addr = src_params->src.y; + hist_params->working_mode = src_params->working_mode; + set_hist_to_vdpp2_reg(hist_params, &dst_reg->hist, &dst_reg->common); + + set_es_to_vdpp2_reg(es_params, &dst_reg->es); + set_shp_to_vdpp2_reg(shp_params, &dst_reg->sharp); + + /* vdpp3 */ + set_pyramid_to_vdpp3_reg(pyr_params, &dst_reg->pyr); + set_bbd_to_vdpp3_reg(bbd_params, &dst_reg->bbd); + + return MPP_OK; +} + +void vdpp3_set_default_pyr_param(PyrParams *pyr_params) +{ + memset(pyr_params, 0, sizeof(PyrParams)); + pyr_params->pyr_en = 0; + pyr_params->nb_layers = 3; +} + +void vdpp3_set_default_bbd_param(BbdParams *bbd_params) +{ + bbd_params->bbd_en = 1; + bbd_params->bbd_det_blcklmt = 20; // 20 in 255 + bbd_params->bbd_size_top = 0; + bbd_params->bbd_size_bottom = 0; + bbd_params->bbd_size_left = 0; + bbd_params->bbd_size_right = 0; +} + +MPP_RET vdpp3_set_default_param(Vdpp3Params *param) +{ + // base + param->src_fmt = MPP_FMT_YUV420SP; // default 420sp + param->src_yuv_swap = VDPP_YUV_SWAP_SP_UV; + param->dst_fmt = VDPP_FMT_YUV444; + param->dst_yuv_swap = VDPP_YUV_SWAP_SP_UV; + param->src_width = 1920; + param->src_height = 1080; + param->dst_width = 1920; + param->dst_height = 1080; + param->yuv_out_diff = 0; + param->working_mode = VDPP_WORK_MODE_VEP; + + /* vdpp1 features */ + vdpp_set_default_dmsr_param(¶m->dmsr_params); + vdpp_set_default_zme_param(¶m->zme_params); + + /* vdpp2 features */ + vdpp2_set_default_es_param(¶m->es_params); + vdpp2_set_default_shp_param(¶m->shp_params); + vdpp2_set_default_hist_param(¶m->hist_params); + param->hist_params.src_fmt = param->src_fmt; + param->hist_params.src_width = param->src_width; + param->hist_params.src_height = param->src_height; + param->hist_params.src_width_vir = param->src_width; + param->hist_params.src_height_vir = param->src_height; + param->hist_params.src_addr = 0; + param->hist_params.working_mode = VDPP_WORK_MODE_VEP; + + /* vdpp3 */ + vdpp3_set_default_pyr_param(¶m->pyr_params); + vdpp3_set_default_bbd_param(¶m->bbd_params); + + return MPP_OK; +} + +MPP_RET vdpp3_init(VdppCtx ictx) +{ + MppReqV1 mpp_req; + RK_U32 client_data = VDPP_CLIENT_TYPE; + Vdpp3ApiCtx *ctx = ictx; + MPP_RET ret = MPP_OK; + + if (NULL == ictx) { + vdpp_loge("found NULL input vdpp3 ctx %p\n", ictx); + return MPP_ERR_NULL_PTR; + } + + // default log level: warning + mpp_env_get_u32(VDPP_COM_DEBUG_ENV_NAME, &vdpp_debug, + (VDPP_LOG_FATAL | VDPP_LOG_ERROR | VDPP_LOG_WARNING)); + vdpp_logi("get env '%s' flag: %#x", VDPP_COM_DEBUG_ENV_NAME, vdpp_debug); + + vdpp_enter(); + + ctx->fd = open("/dev/mpp_service", O_RDWR | O_CLOEXEC); + if (ctx->fd < 0) { + vdpp_loge("can NOT find device /dev/vdpp\n"); + return MPP_NOK; + } + + mpp_req.cmd = MPP_CMD_INIT_CLIENT_TYPE; + mpp_req.flag = 0; + mpp_req.size = sizeof(client_data); + mpp_req.data_ptr = REQ_DATA_PTR(&client_data); + + /* set default parameters */ + memset(&ctx->params, 0, sizeof(Vdpp3Params)); + vdpp3_set_default_param(&ctx->params); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) { + vdpp_loge("ioctl set_client failed!\n"); + return MPP_NOK; + } + + vdpp_leave(); + return ret; +} + +MPP_RET vdpp3_deinit(VdppCtx ictx) +{ + Vdpp3ApiCtx *ctx = NULL; + + if (NULL == ictx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ictx); + return MPP_ERR_NULL_PTR; + } + + ctx = ictx; + + if (ctx->fd >= 0) { + close(ctx->fd); + ctx->fd = -1; + } + + return MPP_OK; +} + +static MPP_RET vdpp3_set_param(Vdpp3ApiCtx *ctx, VdppApiContent *param, VdppParamType type) +{ + RK_U16 mask; + RK_U16 cfg_set; + + switch (type) { + case VDPP_PARAM_TYPE_COM: { // deprecated config + ctx->params.src_fmt = MPP_FMT_YUV420SP; // default 420 + ctx->params.src_yuv_swap = param->com.sswap; + ctx->params.dst_fmt = param->com.dfmt; + ctx->params.dst_yuv_swap = param->com.dswap; + ctx->params.src_width = param->com.src_width; + ctx->params.src_height = param->com.src_height; + ctx->params.dst_width = param->com.dst_width; + ctx->params.dst_height = param->com.dst_height; + + ctx->params.dmsr_params.dmsr_enable = 1; + ctx->params.es_params.es_bEnabledES = 1; + ctx->params.shp_params.sharp_enable = 1; + ctx->params.hist_params.hist_cnt_en = 0; // default disable + + /* set default vir stride */ + if (!ctx->params.src_width_vir) + ctx->params.src_width_vir = MPP_ALIGN(ctx->params.src_width, 16); + if (!ctx->params.src_height_vir) + ctx->params.src_height_vir = MPP_ALIGN(ctx->params.src_height, 8); + if (!ctx->params.dst_width) + ctx->params.dst_width = ctx->params.src_width; + if (!ctx->params.dst_height) + ctx->params.dst_height = ctx->params.src_height; + if (!ctx->params.dst_width_vir) + ctx->params.dst_width_vir = MPP_ALIGN(ctx->params.dst_width, 16); + if (!ctx->params.dst_height_vir) + ctx->params.dst_height_vir = MPP_ALIGN(ctx->params.dst_height, 2); + /* set default chrome stride */ + if (!ctx->params.dst_c_width) + ctx->params.dst_c_width = ctx->params.dst_width; + if (!ctx->params.dst_c_width_vir) + ctx->params.dst_c_width_vir = MPP_ALIGN(ctx->params.dst_c_width, 16); + if (!ctx->params.dst_c_height) + ctx->params.dst_c_height = ctx->params.dst_height; + if (!ctx->params.dst_c_height_vir) + ctx->params.dst_c_height_vir = MPP_ALIGN(ctx->params.dst_c_height, 2); + } break; + case VDPP_PARAM_TYPE_DMSR: { + mpp_assert(sizeof(ctx->params.dmsr_params) == sizeof(param->dmsr)); + memcpy(&ctx->params.dmsr_params, ¶m->dmsr, sizeof(DmsrParams)); + } break; + case VDPP_PARAM_TYPE_ZME_COM: { + ctx->params.zme_params.zme_bypass_en = param->zme.bypass_enable; + ctx->params.zme_params.zme_dering_enable = param->zme.dering_enable; + ctx->params.zme_params.zme_dering_sen_0 = param->zme.dering_sen_0; + ctx->params.zme_params.zme_dering_sen_1 = param->zme.dering_sen_1; + ctx->params.zme_params.zme_dering_blend_alpha = param->zme.dering_blend_alpha; + ctx->params.zme_params.zme_dering_blend_beta = param->zme.dering_blend_beta; + } break; + case VDPP_PARAM_TYPE_ZME_COEFF: { + /** @note: coef fixed in vdpp3, check if need to disable this case. */ + if (param->zme.tap8_coeff != NULL) + ctx->params.zme_params.zme_tap8_coeff = param->zme.tap8_coeff; + if (param->zme.tap6_coeff != NULL) + ctx->params.zme_params.zme_tap6_coeff = param->zme.tap6_coeff; + } break; + case VDPP_PARAM_TYPE_COM2: { + mask = (param->com2.cfg_set >> 16) & 0x7; + cfg_set = (param->com2.cfg_set >> 0) & mask; + + ctx->params.src_yuv_swap = param->com2.sswap; + ctx->params.src_fmt = param->com2.sfmt; + ctx->params.dst_fmt = param->com2.dfmt; + ctx->params.dst_yuv_swap = param->com2.dswap; + ctx->params.src_width = param->com2.src_width; + ctx->params.src_height = param->com2.src_height; + ctx->params.src_width_vir = param->com2.src_width_vir; + ctx->params.src_height_vir = param->com2.src_height_vir; + ctx->params.dst_width = param->com2.dst_width; + ctx->params.dst_height = param->com2.dst_height; + ctx->params.dst_width_vir = param->com2.dst_width_vir; + ctx->params.dst_height_vir = param->com2.dst_height_vir; + ctx->params.yuv_out_diff = param->com2.yuv_out_diff; + ctx->params.dst_c_width = param->com2.dst_c_width; + ctx->params.dst_c_height = param->com2.dst_c_height; + ctx->params.dst_c_width_vir = param->com2.dst_c_width_vir; + ctx->params.dst_c_height_vir = param->com2.dst_c_height_vir; + ctx->params.working_mode = (param->com2.hist_mode_en != 0) ? + VDPP_WORK_MODE_DCI : VDPP_WORK_MODE_VEP; + if (mask & VDPP_DMSR_EN) + ctx->params.dmsr_params.dmsr_enable = ((cfg_set & VDPP_DMSR_EN) != 0) ? 1 : 0; + if (mask & VDPP_ES_EN) + ctx->params.es_params.es_bEnabledES = ((cfg_set & VDPP_ES_EN) != 0) ? 1 : 0; + if (mask & VDPP_SHARP_EN) + ctx->params.shp_params.sharp_enable = ((cfg_set & VDPP_SHARP_EN) != 0) ? 1 : 0; + } break; + case VDPP_PARAM_TYPE_ES: { + mpp_assert(sizeof(ctx->params.es_params) == sizeof(param->es)); + memcpy(&ctx->params.es_params, ¶m->es, sizeof(EsParams)); + } break; + case VDPP_PARAM_TYPE_HIST: { + ctx->params.hist_params.hist_cnt_en = param->hist.hist_cnt_en; + ctx->params.hist_params.dci_hsd_mode = param->hist.dci_hsd_mode; + ctx->params.hist_params.dci_vsd_mode = param->hist.dci_vsd_mode; + ctx->params.hist_params.dci_yrgb_gather_num = param->hist.dci_yrgb_gather_num; + ctx->params.hist_params.dci_yrgb_gather_en = param->hist.dci_yrgb_gather_en; + ctx->params.hist_params.dci_csc_range = param->hist.dci_csc_range; + ctx->params.hist_params.hist_addr = param->hist.hist_addr; + } break; + case VDPP_PARAM_TYPE_SHARP: { + mpp_assert(sizeof(ctx->params.shp_params) == sizeof(param->sharp)); + memcpy(&ctx->params.shp_params, ¶m->sharp, sizeof(ShpParams)); + } break; + case VDPP_PARAM_TYPE_PYR: { + mpp_assert(sizeof(ctx->params.pyr_params) == sizeof(param->pyr)); + memcpy(&ctx->params.pyr_params, ¶m->pyr, sizeof(PyrParams)); + } break; + case VDPP_PARAM_TYPE_BBD: { + ctx->params.bbd_params.bbd_en = param->bbd.bbd_en; + // check if need to convert threshold from full to limited + if (ctx->params.working_mode == VDPP_WORK_MODE_VEP && + ctx->params.src_range == VDPP_COLOR_SPACE_LIMIT_RANGE) { + ctx->params.bbd_params.bbd_det_blcklmt = DIV_255_FAST(param->bbd.bbd_det_blcklmt * 219) + 16; + vdpp_logd("set bbd_det_blcklmt from %d to %d since src_range(%d) is limited(0) and working mode(%d) is VEP(2)!\n", + param->bbd.bbd_det_blcklmt, ctx->params.bbd_params.bbd_det_blcklmt, + ctx->params.src_range, ctx->params.working_mode); + } else { + ctx->params.bbd_params.bbd_det_blcklmt = param->bbd.bbd_det_blcklmt; + vdpp_logd("set bbd_det_blcklmt to %d since src_range(%d) is full(1) or working mode(%d) is DCI_HIST(3)!\n", + param->bbd.bbd_det_blcklmt, ctx->params.src_range, ctx->params.working_mode); + } + } break; + default: { + vdpp_loge("unknown VDPP_PARAM_TYPE %#x !\n", type); + } break; + } + + return MPP_OK; +} + +static RK_S32 check_cap(Vdpp3Params *params) +{ + RK_S32 ret_cap = VDPP_CAP_UNSUPPORTED; + RK_U32 vep_mode_check = 0; + RK_U32 hist_mode_check = 0; + + if (NULL == params) { + vdpp_loge("found null pointer params\n"); + return VDPP_CAP_UNSUPPORTED; + } + + if (params->src_height_vir < params->src_height || + params->src_width_vir < params->src_width) { + vdpp_logd("invalid src img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->src_width, params->src_height, + params->src_width_vir, params->src_height_vir); + return VDPP_CAP_UNSUPPORTED; + } + + if (params->dst_height_vir < params->dst_height || + params->dst_width_vir < params->dst_width) { + vdpp_logd("invalid dst img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->dst_width, params->dst_height, + params->dst_width_vir, params->dst_height_vir); + return VDPP_CAP_UNSUPPORTED; + } + + if ((params->src_fmt != MPP_FMT_YUV420SP) && + (params->src_fmt != MPP_FMT_YUV420SP_VU)) { + vdpp_logd("vep only support nv12 or nv21\n"); + vep_mode_check++; + } + + if ((params->src_height_vir > VDPP3_VEP_MAX_HEIGHT) || + (params->src_width_vir > VDPP3_VEP_MAX_WIDTH) || + (params->src_height < VDPP3_MODE_MIN_HEIGHT) || + (params->src_width < VDPP3_MODE_MIN_WIDTH) || + (params->src_height_vir < VDPP3_MODE_MIN_HEIGHT) || + (params->src_width_vir < VDPP3_MODE_MIN_WIDTH)) { + vdpp_logd("vep unsupported src img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->src_width, params->src_height, + params->src_width_vir, params->src_height_vir); + vep_mode_check++; + } + + if ((params->dst_height_vir > VDPP3_VEP_MAX_HEIGHT) || + (params->dst_width_vir > VDPP3_VEP_MAX_WIDTH) || + (params->dst_height < VDPP3_MODE_MIN_HEIGHT) || + (params->dst_width < VDPP3_MODE_MIN_WIDTH) || + (params->dst_height_vir < VDPP3_MODE_MIN_HEIGHT) || + (params->dst_width_vir < VDPP3_MODE_MIN_WIDTH)) { + vdpp_logd("vep unsupported dst img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->dst_width, params->dst_height, + params->dst_width_vir, params->dst_height_vir); + vep_mode_check++; + } + + if ((params->src_width_vir & 0xf) || (params->dst_width_vir & 0xf)) { + vdpp_logd("vep only support img_w_i/o_vir 16Byte align\n"); + vdpp_logd("vep unsupported src img_w_vir=%d dst img_w_vir=%d\n", + params->src_width_vir, params->dst_width_vir); + vep_mode_check++; + } + + if (params->src_height_vir & 0x7) { + vdpp_logd("vep only support img_h_in_vir 8pix align\n"); + vdpp_logd("vep unsupported src img_h_vir=%d\n", params->src_height_vir); + vep_mode_check++; + } + + if (params->dst_height_vir & 0x1) { + vdpp_logd("vep only support img_h_out_vir 2pix align\n"); + vdpp_logd("vep unsupported dst img_h_vir=%d\n", params->dst_height_vir); + vep_mode_check++; + } + + if ((params->src_width & 1) || (params->src_height & 1) || + (params->dst_width & 1) || (params->dst_height & 1)) { + vdpp_logd("vep only support img_w/h_vld 2pix align\n"); + vdpp_logd("vep unsupported img_w_i=%d img_h_i=%d img_w_o=%d img_h_o=%d\n", + params->src_width, params->src_height, params->dst_width, params->dst_height); + vep_mode_check++; + } + + if (params->yuv_out_diff) { + if ((params->dst_c_height_vir > VDPP3_VEP_MAX_HEIGHT) || + (params->dst_c_width_vir > VDPP3_VEP_MAX_WIDTH) || + (params->dst_c_height < VDPP3_MODE_MIN_HEIGHT) || + (params->dst_c_width < VDPP3_MODE_MIN_WIDTH) || + (params->dst_c_height_vir < VDPP3_MODE_MIN_HEIGHT) || + (params->dst_c_width_vir < VDPP3_MODE_MIN_WIDTH) || + (params->dst_c_height_vir < params->dst_c_height) || + (params->dst_c_width_vir < params->dst_c_width)) { + vdpp_logd("vep unsupported dst_c img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->dst_c_width, params->dst_c_height, + params->dst_c_width_vir, params->dst_c_height_vir); + vep_mode_check++; + } + + if (params->dst_c_width_vir & 0xf) { + vdpp_logd("vep only support img_w_c_out_vir 16Byte align\n"); + vdpp_logd("vep unsupported dst img_w_c_vir=%d\n", params->dst_c_width_vir); + vep_mode_check++; + } + + if (params->dst_c_height_vir & 0x1) { + vdpp_logd("vep only support img_h_c_out_vir 2pix align\n"); + vdpp_logd("vep unsupported dst img_h_vir=%d\n", params->dst_c_height_vir); + vep_mode_check++; + } + + if ((params->dst_c_width & 1) || (params->dst_c_height & 1)) { + vdpp_logd("vep only support img_c_w/h_vld 2pix align\n"); + vdpp_logd("vep unsupported img_w_o=%d img_h_o=%d\n", + params->dst_c_width, params->dst_c_height); + vep_mode_check++; + } + } + + if ((params->src_height_vir > VDPP3_HIST_MAX_HEIGHT) || + (params->src_width_vir > VDPP3_HIST_MAX_WIDTH) || + (params->src_height < VDPP3_MODE_MIN_HEIGHT) || + (params->src_width < VDPP3_MODE_MIN_WIDTH)) { + vdpp_logd("dci unsupported src img_w=%d img_h=%d img_w_vir=%d img_h_vir=%d\n", + params->src_width, params->src_height, + params->src_width_vir, params->src_height_vir); + hist_mode_check++; + } + + /* 10 bit input */ + if ((params->src_fmt == MPP_FMT_YUV420SP_10BIT) || + (params->src_fmt == MPP_FMT_YUV422SP_10BIT) || + (params->src_fmt == MPP_FMT_YUV444SP_10BIT)) { + if (params->src_width_vir & 0xf) { + vdpp_logd("dci Y-10bit input only support img_w_in_vir 16Byte align\n"); + hist_mode_check++; + } + } else { + if (params->src_width_vir & 0x3) { + vdpp_logd("dci only support img_w_in_vir 4Byte align\n"); + hist_mode_check++; + } + } + + // vdpp_logd("vdpp3 src img resolution: w-%d-%d, h-%d-%d\n", + // params->src_width, params->src_width_vir, + // params->src_height, params->src_height_vir); + // vdpp_logd("vdpp3 dst img resolution: w-%d-%d, h-%d-%d\n", + // params->dst_width, params->dst_width_vir, + // params->dst_height, params->dst_height_vir); + + if (!vep_mode_check) { + ret_cap |= VDPP_CAP_VEP; + vdpp_logd("vdpp3 support mode: VDPP_CAP_VEP\n"); + } + + if (!hist_mode_check) { + vdpp_logd("vdpp3 support mode: VDPP_CAP_HIST\n"); + ret_cap |= VDPP_CAP_HIST; + } + + return ret_cap; +} + +MPP_RET vdpp3_start(Vdpp3ApiCtx *ctx) +{ + VdppRegOffsetInfo reg_off[2]; + /* Note: req_cnt must be 12 here! Make sure req_cnt<=11! */ + MppReqV1 mpp_req[12]; + RK_U32 req_cnt = 0; + Vdpp3Regs *reg = NULL; + RK_S32 ret_cap = VDPP_CAP_UNSUPPORTED; + RK_S32 work_mode; + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp3 ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + // get env here so that we can change loglevel dynamically + mpp_env_get_u32(VDPP_COM_DEBUG_ENV_NAME, &vdpp_debug, + (VDPP_LOG_FATAL | VDPP_LOG_ERROR | VDPP_LOG_WARNING)); + vdpp_logt("get env '%s' flag: %#x", VDPP_COM_DEBUG_ENV_NAME, vdpp_debug); + + vdpp_enter(); + + work_mode = ctx->params.working_mode; + ret_cap = check_cap(&ctx->params); + if ((!(ret_cap & VDPP_CAP_VEP) && (VDPP_WORK_MODE_VEP == work_mode)) || + (!(ret_cap & VDPP_CAP_HIST) && (VDPP_WORK_MODE_DCI == work_mode))) { + vdpp_loge("found incompat work mode %d %s, cap %d\n", work_mode, + working_mode_name[work_mode & 3], ret_cap); + return MPP_NOK; + } + + reg = &ctx->reg; + + memset(reg_off, 0, sizeof(reg_off)); + memset(mpp_req, 0, sizeof(mpp_req)); + memset(reg, 0, sizeof(*reg)); + + vdpp3_params_to_reg(&ctx->params, ctx); + + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->zme); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_ZME; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->zme); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->dmsr); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_DMSR; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->dmsr); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->hist); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_DCI_HIST; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->hist); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->es); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_ES; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->es); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->pyr); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_PYRAMID; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->pyr); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->bbd.reg0); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_BBD; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->bbd); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->sharp); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_SHARP; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->sharp); + + /* set reg offset */ + reg_off[0].reg_idx = 25; + reg_off[0].offset = ctx->params.src.cbcr_offset; + reg_off[1].reg_idx = 27; + + if (!ctx->params.yuv_out_diff) + reg_off[1].offset = ctx->params.dst.cbcr_offset; + else + reg_off[1].offset = ctx->params.dst_c.cbcr_offset; + + vdpp_logv("set reg: cbcr_offset for src/dst=%d/%d\n", reg_off[0].offset, reg_off[1].offset); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_ADDR_OFFSET; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG | MPP_FLAGS_REG_OFFSET_ALONE; + mpp_req[req_cnt].size = sizeof(reg_off); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(reg_off); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_WRITE; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->common); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->common); + + /* read output register for common */ + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_READ; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->common); + mpp_req[req_cnt].offset = 0; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->common); + + /* read output register for BBD (need to know vsd/hsd mode in hist) */ + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_READ; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG; + mpp_req[req_cnt].size = sizeof(reg->bbd); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_BBD; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->bbd); + + req_cnt++; + mpp_req[req_cnt].cmd = MPP_CMD_SET_REG_READ; + mpp_req[req_cnt].flag = MPP_FLAGS_MULTI_MSG | MPP_FLAGS_LAST_MSG; + mpp_req[req_cnt].size = sizeof(reg->hist); + mpp_req[req_cnt].offset = VDPP3_REG_OFF_DCI_HIST; + mpp_req[req_cnt].data_ptr = REQ_DATA_PTR(®->hist); + mpp_assert(req_cnt <= 11); + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req[0]); + + if (ret) { + vdpp_loge("ioctl SET_REG failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + + vdpp_leave(); + return ret; +} + +static MPP_RET vdpp3_wait(Vdpp3ApiCtx *ctx) +{ + MppReqV1 mpp_req; + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + memset(&mpp_req, 0, sizeof(mpp_req)); + mpp_req.cmd = MPP_CMD_POLL_HW_FINISH; + mpp_req.flag |= MPP_FLAGS_LAST_MSG; + + ret = (RK_S32)ioctl(ctx->fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) { + vdpp_loge("ioctl POLL_HW_FINISH failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + } + + return ret; +} + +static MPP_RET vdpp3_done(Vdpp3ApiCtx *ctx) +{ + Vdpp3Regs *reg = NULL; + Vdpp3Params *params = NULL; + + if (NULL == ctx) { + vdpp_loge("found NULL input vdpp ctx %p\n", ctx); + return MPP_ERR_NULL_PTR; + } + + vdpp_enter(); + + reg = &ctx->reg; + params = &ctx->params; + + vdpp_logd("ro_frm_done_sts=%d\n", reg->common.reg10.ro_frm_done_sts); + vdpp_logd("ro_osd_max_sts=%d\n", reg->common.reg10.ro_osd_max_sts); + vdpp_logd("ro_bus_error_sts=%d\n", reg->common.reg10.ro_bus_error_sts); + vdpp_logd("ro_timeout_sts=%d\n", reg->common.reg10.ro_timeout_sts); + vdpp_logd("ro_config_error_sts=%d\n", reg->common.reg10.ro_config_error_sts); + + if (reg->common.reg8.sw_vep_frm_done_en && + !reg->common.reg10.ro_frm_done_sts) { + vdpp_loge("run vdpp failed!!\n"); + return MPP_NOK; + } + + if (reg->common.reg10.ro_timeout_sts) { + vdpp_loge("run vdpp timeout!!\n"); + return MPP_NOK; + } + + vdpp_logv("read reg: bbd.sw_det_en=%d\n", reg->bbd.reg0.sw_det_en); + if (reg->bbd.reg0.sw_det_en) { + params->bbd_params.bbd_size_top = reg->bbd.reg1.blckbar_size_top; + params->bbd_params.bbd_size_bottom = reg->bbd.reg1.blckbar_size_bottom; + params->bbd_params.bbd_size_left = reg->bbd.reg2.blckbar_size_left; + params->bbd_params.bbd_size_right = reg->bbd.reg2.blckbar_size_right; + vdpp_logv("read reg: bbd.sw_det_blcklmt=%d\n", reg->bbd.reg0.sw_det_blcklmt); + vdpp_logv("read reg: bbd.blckbar_size_top=%d\n", reg->bbd.reg1.blckbar_size_top); + vdpp_logv("read reg: bbd.blckbar_size_bottom=%d\n", reg->bbd.reg1.blckbar_size_bottom); + vdpp_logv("read reg: bbd.blckbar_size_left=%d\n", reg->bbd.reg2.blckbar_size_left); + vdpp_logv("read reg: bbd.blckbar_size_right=%d\n", reg->bbd.reg2.blckbar_size_right); + + /* rescale bbd result if working_mode is 'VDPP_WORK_MODE_DCI' */ + if (VDPP_WORK_MODE_DCI == reg->common.reg2.sw_vdpp_working_mode) { + const RK_U32 bit_v = reg->hist.reg3.sw_dci_vsd_mode; + const RK_U32 bit_h = reg->hist.reg3.sw_dci_hsd_mode + 1; + + params->bbd_params.bbd_size_top <<= bit_v; + params->bbd_params.bbd_size_bottom <<= bit_v; + params->bbd_params.bbd_size_left <<= bit_h; + params->bbd_params.bbd_size_right <<= bit_h; + vdpp_logd("The working_mode is DCI, BBD result rescaled below:\n"); + vdpp_logd("rescaled: bbd.blckbar_size_top=%d\n", params->bbd_params.bbd_size_top); + vdpp_logd("rescaled: bbd.blckbar_size_bottom=%d\n", params->bbd_params.bbd_size_bottom); + vdpp_logd("rescaled: bbd.blckbar_size_left=%d\n", params->bbd_params.bbd_size_left); + vdpp_logd("rescaled: bbd.blckbar_size_right=%d\n", params->bbd_params.bbd_size_right); + vdpp_logd("NOTE this rescaled result might be a little bit different than the original result!\n"); + } + } + + vdpp_logi("run vdpp success! %d\n", reg->common.reg10); + vdpp_leave(); + return MPP_OK; +} + +MPP_RET vdpp3_control(VdppCtx ictx, VdppCmd cmd, void *iparam) +{ + Vdpp3ApiCtx *ctx = ictx; + MPP_RET ret = MPP_OK; + + if ((NULL == iparam && VDPP_CMD_RUN_SYNC != cmd) || + (NULL == ictx)) { + vdpp_loge("found NULL iparam %p cmd %d ctx %p\n", iparam, cmd, ictx); + return MPP_ERR_NULL_PTR; + } + + switch (cmd) { + case VDPP_CMD_SET_COM_CFG: + case VDPP_CMD_SET_DMSR_CFG: + case VDPP_CMD_SET_ZME_COM_CFG: + case VDPP_CMD_SET_ZME_COEFF_CFG: + case VDPP_CMD_SET_COM2_CFG: + case VDPP_CMD_SET_ES: + case VDPP_CMD_SET_DCI_HIST: + case VDPP_CMD_SET_SHARP: + case VDPP_CMD_SET_PYR: + case VDPP_CMD_SET_BBD: { + VdppApiParams *api_param = (VdppApiParams *)iparam; + + ret = vdpp3_set_param(ctx, &api_param->param, api_param->ptype); + if (ret) { + vdpp_loge("set vdpp parameter failed, type %d\n", api_param->ptype); + } + } break; + case VDPP_CMD_SET_SRC: { + set_addr(&ctx->params.src, (VdppImg *)iparam); + } break; + case VDPP_CMD_SET_DST: { + set_addr(&ctx->params.dst, (VdppImg *)iparam); + } break; + case VDPP_CMD_SET_DST_C: { + set_addr(&ctx->params.dst_c, (VdppImg *)iparam); + } break; + case VDPP_CMD_SET_HIST_FD: { + ctx->params.hist_params.hist_addr = *(RK_S32 *)iparam; + } break; + case VDPP_CMD_RUN_SYNC: { + ret = vdpp3_start(ctx); + if (ret) { + vdpp_loge("run vdpp failed!!\n"); + return MPP_NOK; + } + + ret |= vdpp3_wait(ctx); + ret |= vdpp3_done(ctx); + } break; + case VDPP_CMD_GET_AVG_LUMA: { + VdppResults *result = (VdppResults *)iparam; + + memset(result, 0, sizeof(VdppResults)); + + if (!ctx->params.hist_params.hist_cnt_en || ctx->params.hist_params.hist_addr <= 0) { + vdpp_logw("return invalid luma_avg value since the hist_cnt(%d)=0 or fd(%d)<=0!\n", + ctx->params.hist_params.hist_cnt_en, ctx->params.hist_params.hist_addr); + result->hist.luma_avg = -1; + } else { + RK_U32 *p_hist_packed = (RK_U32 *)mmap(NULL, VDPP_HIST_PACKED_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED, ctx->params.hist_params.hist_addr, 0); + + if (p_hist_packed) { + result->hist.luma_avg = get_avg_luma_from_hist(p_hist_packed + VDPP_HIST_GLOBAL_OFFSET / 4, + VDPP_HIST_GLOBAL_LENGTH); + munmap(p_hist_packed, VDPP_HIST_PACKED_SIZE); + } else { + result->hist.luma_avg = -1; + vdpp_loge("map hist fd(%d) failed! %s\n", ctx->params.hist_params.hist_addr, + strerror(errno)); + } + } + } break; + case VDPP_CMD_GET_BBD: { + if (!ctx->params.bbd_params.bbd_en) { + vdpp_loge("run cmd 'VDPP_CMD_GET_BBD' failed since the bbd is disabled!\n"); + return MPP_NOK; + } + VdppResults *result = (VdppResults *)iparam; + + memset(result, 0, sizeof(VdppResults)); + result->bbd.bbd_size_top = ctx->params.bbd_params.bbd_size_top; + result->bbd.bbd_size_bottom = ctx->params.bbd_params.bbd_size_bottom; + result->bbd.bbd_size_left = ctx->params.bbd_params.bbd_size_left; + result->bbd.bbd_size_right = ctx->params.bbd_params.bbd_size_right; + } break; + default: { + vdpp_loge("unsupported control cmd %#x for vdpp3!\n", cmd); + ret = MPP_ERR_VALUE; + } break; + } + + return ret; +} + +RK_S32 vdpp3_check_cap(VdppCtx ictx) +{ + Vdpp3ApiCtx *ctx = ictx; + + if (NULL == ictx) { + vdpp_loge("found NULL ctx %p!\n", ictx); + return VDPP_CAP_UNSUPPORTED; + } + + return check_cap(&ctx->params); +} diff --git a/mpp/vproc/vdpp/vdpp3.h b/mpp/vproc/vdpp/vdpp3.h new file mode 100644 index 000000000..72004fdd2 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp3.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP3_H +#define VDPP3_H + +#include "vdpp3_reg.h" +#include "vdpp2.h" + +typedef struct PyrParams_t { + RK_U32 pyr_en; + RK_U32 nb_layers; // [1, 3], default: 3 + VdppImg layer_imgs[VDPP_PYR_MAX_LAYERS]; // fd buffer of layer 1 +} PyrParams; + +typedef struct BbdParams_t { + RK_U32 bbd_en; //[i] support VEP & DCI_HIST path + RK_U32 bbd_det_blcklmt; //[i] luma threshold for black bar detection, always considered as full-range + RK_U32 bbd_size_top; //[o] output black bar size on top + RK_U32 bbd_size_bottom; //[o] output black bar size on bottom + RK_U32 bbd_size_left; //[o] output black bar size on left + RK_U32 bbd_size_right; //[o] output black bar size on right +} BbdParams; + +typedef struct vdpp3_params { + RK_U32 src_fmt; // see MppFrameFormat, {0-nv12, 15-nv24} + RK_U32 src_yuv_swap; // {0-no_swap(UV), 1-swap(VU)} + RK_U32 src_range; // {0-limited, 1-full} + RK_U32 src_width; // real width, unit: pixel + RK_U32 src_height; // real height, unit: pixel + RK_U32 src_width_vir; // aligned width, unit: pixel + RK_U32 src_height_vir; // aligned height, unit: pixel + RK_U32 dst_fmt; // see VDPP_FMT, {0-yuv444sp, 3-yuv420sp} + RK_U32 dst_yuv_swap; // {0-no_swap(UV), 1-swap(VU)} + RK_U32 dst_width; // unit: pixel + RK_U32 dst_height; // unit: pixel + RK_U32 dst_width_vir; // unit: pixel + RK_U32 dst_height_vir; // unit: pixel + RK_U32 yuv_out_diff; // {0:single_buf_out, 1-two_separate_bufs_out} + RK_U32 dst_c_width; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 dst_c_height; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 dst_c_width_vir; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 dst_c_height_vir; // unit: pixel, valid when yuv_out_diff=1 + RK_U32 working_mode; // 1-IEP2, 2-VEP, 3-DCI_HIST + + VdppAddr src; // src frame + VdppAddr dst; // dst frame + VdppAddr dst_c; // dst chroma frame, valid when yuv_out_diff=1 + + /* vdpp features */ + DmsrParams dmsr_params; + ZmeParams zme_params; + + /* vdpp2 features */ + HistParams hist_params; + EsParams es_params; + ShpParams shp_params; + + /* vdpp3 features */ + PyrParams pyr_params; + BbdParams bbd_params; +} Vdpp3Params; + +typedef struct vdpp3_api_ctx { + RK_S32 fd; + Vdpp3Params params; + Vdpp3Regs reg; +} Vdpp3ApiCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET vdpp3_init(VdppCtx ictx); +MPP_RET vdpp3_deinit(VdppCtx ictx); +MPP_RET vdpp3_control(VdppCtx ictx, VdppCmd cmd, void *iparam); +RK_S32 vdpp3_check_cap(VdppCtx ictx); + +#ifdef __cplusplus +} +#endif + +#endif /* VDPP3_H */ diff --git a/mpp/vproc/vdpp/vdpp3_reg.h b/mpp/vproc/vdpp/vdpp3_reg.h new file mode 100644 index 000000000..272388498 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp3_reg.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP3_REG_H +#define VDPP3_REG_H + +#include "vdpp2_reg.h" + +#define VDPP3_REG_OFF_DMSR (0x0080) +#define VDPP3_REG_OFF_DCI_HIST (0x00E0) +#define VDPP3_REG_OFF_ES (0x0100) +#define VDPP3_REG_OFF_PYRAMID (0x0190) +#define VDPP3_REG_OFF_BBD (0x01B0) +#define VDPP3_REG_OFF_SHARP (0x0200) +#define VDPP3_REG_OFF_ZME (0x2800) + + +/* zme: 0x2800 - 0x2844 */ +typedef struct vdpp3_zme_reg { + struct { + RK_U32 bypass_en : 1; + RK_U32 align_en : 1; + RK_U32 reserved_1 : 2; + RK_U32 format_in : 4; + RK_U32 format_out : 4; + RK_U32 reserved_2 : 19; + RK_U32 auto_gating_en : 1; + } reg0; /* 0x0800 */ + + /* reg1 0x0804 - reg2 0x080C */ + RK_U32 reg1_3[3]; + + struct { + RK_U32 yrgb_xsd_en : 1; + RK_U32 yrgb_xsu_en : 1; + RK_U32 yrgb_scl_mode : 2; + RK_U32 yrgb_ysd_en : 1; + RK_U32 yrgb_ysu_en : 1; + RK_U32 yrgb_yscl_mode : 2; + RK_U32 yrgb_dering_en : 1; + RK_U32 yrgb_gt_en : 1; + RK_U32 yrgb_gt_mode : 2; + RK_U32 reserved_1 : 4; + RK_U32 yrgb_xsd_bypass : 1; + RK_U32 yrgb_ys_bypass : 1; + RK_U32 yrgb_xsu_bypass : 1; + RK_U32 reserved_2 : 1; + RK_U32 yrgb_xscl_coe_sel : 4; + RK_U32 yrgb_yscl_coe_sel : 4; + RK_U32 reserved_3 : 4; + } reg4; /* 0x0810 */ + + /* reg5 0x0814 - reg6 x0818 */ + RK_U32 reg5_6[2]; + + struct { + RK_U32 yrgb_dering_sen0 : 5; + RK_U32 reserved_1 : 3; + RK_U32 yrgb_dering_sen1 : 5; + RK_U32 reserved_2 : 3; + RK_U32 yrgb_dering_alpha: 5; + RK_U32 reserved_3 : 3; + RK_U32 yrgb_dering_delta: 5; + RK_U32 reserved_4 : 3; + } reg7; /* 0x081C */ + + struct { + RK_U32 yrgb_xscl_factor : 16; + RK_U32 yrgb_xscl_offset : 16; + } reg8; /* 0x0820 */ + + struct { + RK_U32 yrgb_yscl_factor : 16; + RK_U32 yrgb_yscl_offset : 16; + } reg9; /* 0x0824 */ + + /* reg10 0x0828 - reg11 0x082C */ + RK_U32 reg10_11[2]; /* 0x0828 */ + + struct { + RK_U32 cbcr_xsd_en : 1; + RK_U32 cbcr_xsu_en : 1; + RK_U32 cbcr_xscl_mode : 2; + RK_U32 cbcr_ysd_en : 1; + RK_U32 cbcr_ysu_en : 1; + RK_U32 cbcr_yscl_mode : 2; + RK_U32 cbcr_dering_en : 1; + RK_U32 cbcr_gt_en : 1; + RK_U32 cbcr_gt_mode : 2; + RK_U32 reserved_1 : 4; + RK_U32 cbcr_xsd_bypass : 1; + RK_U32 cbcr_ys_bypass : 1; + RK_U32 cbcr_xsu_bypass : 1; + RK_U32 reserved_2 : 1; + RK_U32 cbcr_xscl_coe_sel: 4; + RK_U32 cbcr_yscl_coe_sel: 4; + RK_U32 reserved_3 : 4; + } reg12; /* 0x0830 */ + + /* reg13 0x0834 - reg14 0x0838 */ + RK_U32 reg13_14[2]; + + struct { + RK_U32 cbcr_dering_sen0 : 5; + RK_U32 reserved_1 : 3; + RK_U32 cbcr_dering_sen1 : 5; + RK_U32 reserved_2 : 3; + RK_U32 cbcr_dering_alpha: 5; + RK_U32 reserved_3 : 3; + RK_U32 cbcr_dering_delta: 5; + RK_U32 reserved_4 : 3; + } reg15; /* 0x083C */ + + struct { + RK_U32 cbcr_xscl_factor : 16; + RK_U32 cbcr_xscl_offset : 16; + } reg16; /* 0x0840 */ + + struct { + RK_U32 cbcr_yscl_factor : 16; + RK_U32 cbcr_yscl_offset : 16; + } reg17; /* 0x0844 */ +} RegZme3; + +/* pyramid: 0x1190 - 0x11A8 */ +typedef struct vdpp3_pyr_reg { + struct { + RK_U32 sw_pyramid_en : 1; + RK_U32 reserved : 31; + } reg0; // 0x0190 + + struct { + RK_U32 sw_pyramid_layer1_dst_addr : 32; + } reg1; // 0x0194 + + struct { + RK_U32 sw_pyramid_layer1_dst_vir_wid : 16; + RK_U32 reserved : 16; + } reg2; // 0x0198 + + struct { + RK_U32 sw_pyramid_layer2_dst_addr : 32; + } reg3; // 0x019C + + struct { + RK_U32 sw_pyramid_layer2_dst_vir_wid : 16; + RK_U32 reserved : 16; + } reg4; // 0x01A0 + + struct { + RK_U32 sw_pyramid_layer3_dst_addr : 32; + } reg5; // 0x01A4 + + struct { + RK_U32 sw_pyramid_layer3_dst_vir_wid : 16; + RK_U32 reserved : 16; + } reg6; // 0x01A8 +} RegPyr; + +/* bbd: 0x11B0 - 0x11B8 */ +typedef struct vdpp3_bbd_reg { + struct { + RK_U32 sw_det_en : 1; + RK_U32 reserved1 : 3; + RK_U32 sw_det_blcklmt : 8; + RK_U32 reserved2 : 20; + } reg0; // 0x01B0 + + struct { + RK_U32 blckbar_size_top : 12; + RK_U32 reserved1 : 4; + RK_U32 blckbar_size_bottom : 12; + RK_U32 reserved2 : 4; + } reg1; // 0x01B4 + + struct { + RK_U32 blckbar_size_left : 12; + RK_U32 reserved1 : 4; + RK_U32 blckbar_size_right : 12; + RK_U32 reserved2 : 4; + } reg2; // 0x01B8 +} RegBbd; + +typedef struct vdpp3_reg { + RegCom2 common; /* offset: 0x1000, end: 0x106C, size: 112 */ + RegDmsr dmsr; /* offset: 0x1080, end: 0x10D0, size: 84 */ + RegHist hist; /* offset: 0x10E0, end: 0x10F0, size: 20 */ + RegEs es; /* offset: 0x1100, end: 0x117C, size: 128 */ + RegShp sharp; /* offset: 0x1200, end: 0x14a8, size: 684 */ + RegPyr pyr; /* offset: 0x0190, end: 0x11A8, size: 28 */ + RegBbd bbd; /* offset: 0x01B0, end: 0x11B8, size: 12 */ + RegZme3 zme; /* offset: 0x2000, end: 0x2844, size: 1160(valid)/2120(total) */ +} Vdpp3Regs; + +#endif /* VDPP3_REG_H */ diff --git a/mpp/vproc/vdpp/vdpp_api.c b/mpp/vproc/vdpp/vdpp_api.c new file mode 100644 index 000000000..4c798326d --- /dev/null +++ b/mpp/vproc/vdpp/vdpp_api.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpp" + +#include "mpp_soc.h" +#include "mpp_mem.h" + +#include "vdpp_api.h" +#include "vdpp.h" +#include "vdpp2.h" +#include "vdpp3.h" + +VdppComCtx *rockchip_vdpp_api_alloc_ctx(void) +{ + VdppComCtx *com_ctx = mpp_calloc(VdppComCtx, 1); + VdppComOps *ops = mpp_calloc(VdppComOps, 1); + VdppCtx ctx = NULL; + RockchipSocType soc_type = mpp_get_soc_type(); + RK_U32 vdpp_ver = 0; + + switch (soc_type) { + case ROCKCHIP_SOC_RK3528: { + vdpp_ver = 1; + } break; + case ROCKCHIP_SOC_RK3576: { + vdpp_ver = 2; + } break; + case ROCKCHIP_SOC_RK3538: + case ROCKCHIP_SOC_RK3539: + case ROCKCHIP_SOC_RK3572: { + vdpp_ver = 3; + } break; + default: { + if (soc_type > ROCKCHIP_SOC_RK3539) { + vdpp_ver = 3; + vdpp_logw("unsupported soc_type %d for vdpp, try use vdpp3...\n", soc_type); + } else { + vdpp_logf("unsupported soc_type %d for vdpp!!!\n", soc_type); + goto __ERR; + } + } break; + } + + if (NULL == com_ctx || NULL == ops) { + vdpp_loge("failed to calloc com_ctx %p ops %p\n", com_ctx, ops); + goto __ERR; + } + + if (1 == vdpp_ver) { + ops->init = vdpp_init; + ops->deinit = vdpp_deinit; + ops->control = vdpp_control; + ops->check_cap = vdpp_check_cap; + com_ctx->ver = 0x100; + + ctx = mpp_calloc(Vdpp1ApiCtx, 1); + } else if (2 == vdpp_ver) { + ops->init = vdpp2_init; + ops->deinit = vdpp2_deinit; + ops->control = vdpp2_control; + ops->check_cap = vdpp2_check_cap; + com_ctx->ver = 0x200; + + ctx = mpp_calloc(Vdpp2ApiCtx, 1); + } else { + ops->init = vdpp3_init; + ops->deinit = vdpp3_deinit; + ops->control = vdpp3_control; + ops->check_cap = vdpp3_check_cap; + com_ctx->ver = 0x300; + + ctx = mpp_calloc(Vdpp3ApiCtx, 1); + } + + if (NULL == ctx) { + vdpp_loge("failed to calloc vdpp_api_ctx %p\n", ctx); + goto __ERR; + } + + com_ctx->ops = ops; + com_ctx->priv = ctx; + vdpp_logi("init vdp_api_ctx: soc=%d, vdpp_ver=%d\n", soc_type, com_ctx->ver >> 8); + + return com_ctx; + +__ERR: + MPP_FREE(com_ctx); + MPP_FREE(ops); + MPP_FREE(ctx); + return NULL; +} + +void rockchip_vdpp_api_release_ctx(VdppComCtx *com_ctx) +{ + if (NULL == com_ctx) + return; + + MPP_FREE(com_ctx->ops); + MPP_FREE(com_ctx->priv); + MPP_FREE(com_ctx); +} + +MPP_RET dci_hist_info_parser(const RK_U8 *p_pack_hist_addr, RK_U32 *p_hist_local, RK_U32 *p_hist_global) +{ + const RK_U32 local_hist_length = RKVOP_PQ_PREPROCESS_HIST_SIZE_VERI * + RKVOP_PQ_PREPROCESS_HIST_SIZE_HORI * + RKVOP_PQ_PREPROCESS_LOCAL_HIST_BIN_NUMS; + RK_U32 hw_hist_idx = 0; + RK_U32 idx = 0; + + if (NULL == p_pack_hist_addr || NULL == p_hist_local || NULL == p_hist_global) { + vdpp_loge("found NULL ptr, pack_hist %p hist_local %p hist_global %p\n", + p_pack_hist_addr, p_hist_local, p_hist_global); + return MPP_ERR_NULL_PTR; + } + + /* Hist packed (10240 byte) -> unpacked (local: 16 * 16 * 16 * U32 + global: 256 * U32) */ + for (idx = 0; idx < local_hist_length; idx = idx + 4) { + RK_U32 tmp0_u18, tmp1_u18, tmp2_u18, tmp3_u18; + RK_U32 tmp0_u8, tmp1_u8, tmp2_u8, tmp3_u8, tmp4_u8, tmp5_u8, tmp6_u8, tmp7_u8, tmp8_u8; + + tmp0_u8 = *(p_pack_hist_addr + hw_hist_idx + 0); + tmp1_u8 = *(p_pack_hist_addr + hw_hist_idx + 1); + tmp2_u8 = *(p_pack_hist_addr + hw_hist_idx + 2); + tmp3_u8 = *(p_pack_hist_addr + hw_hist_idx + 3); + tmp4_u8 = *(p_pack_hist_addr + hw_hist_idx + 4); + tmp5_u8 = *(p_pack_hist_addr + hw_hist_idx + 5); + tmp6_u8 = *(p_pack_hist_addr + hw_hist_idx + 6); + tmp7_u8 = *(p_pack_hist_addr + hw_hist_idx + 7); + tmp8_u8 = *(p_pack_hist_addr + hw_hist_idx + 8); + + tmp0_u18 = ((tmp2_u8 & ((1 << 2) - 1)) << 16) + (tmp1_u8 << 8) + tmp0_u8; + tmp1_u18 = ((tmp4_u8 & ((1 << 4) - 1)) << 14) + (tmp3_u8 << 6) + (tmp2_u8 >> 2); + tmp2_u18 = ((tmp6_u8 & ((1 << 6) - 1)) << 12) + (tmp5_u8 << 4) + (tmp4_u8 >> 4); + tmp3_u18 = (tmp8_u8 << 10) + (tmp7_u8 << 2) + (tmp6_u8 >> 6); + + *(p_hist_local + idx + 0) = tmp0_u18; + *(p_hist_local + idx + 1) = tmp1_u18; + *(p_hist_local + idx + 2) = tmp2_u18; + *(p_hist_local + idx + 3) = tmp3_u18; + hw_hist_idx += 9; + } + + for (idx = 0; idx < RKVOP_PQ_PREPROCESS_GLOBAL_HIST_BIN_NUMS; idx++) { + RK_U32 tmp0_u8, tmp1_u8, tmp2_u8, tmp3_u8; + RK_U32 tmp_u32; + + tmp0_u8 = *(p_pack_hist_addr + hw_hist_idx + 0); + tmp1_u8 = *(p_pack_hist_addr + hw_hist_idx + 1); + tmp2_u8 = *(p_pack_hist_addr + hw_hist_idx + 2); + tmp3_u8 = *(p_pack_hist_addr + hw_hist_idx + 3); + + tmp_u32 = (tmp3_u8 << 24) + (tmp2_u8 << 16) + (tmp1_u8 << 8) + tmp0_u8; + *(p_hist_global + idx + 0) = tmp_u32; + hw_hist_idx += 4; + } + + return MPP_OK; +} diff --git a/mpp/vproc/vdpp/vdpp_common.c b/mpp/vproc/vdpp/vdpp_common.c new file mode 100644 index 000000000..f81e58395 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp_common.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vdpp" + +#include "vdpp_common.h" + +const char *working_mode_name[] = { + NULL, + NULL, + "VEP MODE", + "DCI HIST MODE", +}; + +MPP_RET set_addr(VdppAddr *addr, VdppImg *img) +{ + if (NULL == addr || NULL == img) { + vdpp_loge("found NULL vdpp_addr %p img %p\n", addr, img); + return MPP_ERR_NULL_PTR; + } + + addr->y = img->mem_addr; + addr->cbcr = img->uv_addr; + addr->cbcr_offset = img->uv_off; + + return MPP_OK; +} + +RK_S32 get_avg_luma_from_hist(const RK_U32 *pHist, RK_S32 length) +{ + RK_S32 avg_luma = -1; + + if (pHist) { + RK_S64 luma_sum = 0; + RK_S32 pixel_count = 0; + RK_S32 i; + + for (i = 0; i < length; i++) { + /* + bin0 ---> 0,1,2,3 ---> avg_luma = 1.5 = 0*4+1.5 + bin1 ---> 4,5,6,7 ---> avg_luma = 5.5 = 1*4+1.5 + ... + bin255 ---> 1020,1021,1022,1023 ---> avg_luma = 1021.5 = 255*4+1.5 + */ + RK_U32 luma_val = i * 8 + 3; + + luma_sum += pHist[i] * luma_val; + pixel_count += pHist[i]; + } + + if (pixel_count > 0) { + avg_luma = luma_sum / pixel_count / 2; + vdpp_logd("get luma_avg from hist: %d (in U10)\n", avg_luma); + } else { + vdpp_logw("pixel_count is zero! the hist data is invalid!\n"); + avg_luma = -1; + } + } else { + vdpp_loge("the hist pointer is null!\n"); + } + + return avg_luma; +} \ No newline at end of file diff --git a/mpp/vproc/vdpp/vdpp_common.h b/mpp/vproc/vdpp/vdpp_common.h new file mode 100644 index 000000000..50a96893e --- /dev/null +++ b/mpp/vproc/vdpp/vdpp_common.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP_COMMON_H +#define VDPP_COMMON_H + + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_log.h" + +#include "vdpp_api.h" +#include "vdpp_reg.h" +#include "vdpp2_reg.h" +#include "vdpp3_reg.h" + +/* marco define */ +#define VDPP_TILE_W_MAX (120) +#define VDPP_TILE_H_MAX (480) + +// marcos for common use +#ifndef ROUND +#define CEIL(a) (int)( (double)(a) > (int)(a) ? (int)((a)+1) : (int)(a) ) +#define FLOOR(a) (int)( (double)(a) < (int)(a) ? (int)((a)-1) : (int)(a) ) +#define ROUND(a) (int)( (a) > 0 ? ((double) (a) + 0.5) : ((double) (a) - 0.5) ) +#endif +#define DIV_255_FAST(x) (((x) + 1 + (((x) + 1) >> 8)) >> 8) + +// marcos for zme +#define SCALE_FACTOR_DN_FIXPOINT_SHIFT (12) +#define SCALE_FACTOR_UP_FIXPOINT_SHIFT (16) +#define GET_SCALE_FACTOR_DN(src, dst) ((((src) - 1) << SCALE_FACTOR_DN_FIXPOINT_SHIFT) / ((dst) - 1)) +#define GET_SCALE_FACTOR_UP(src, dst) ((((src) - 1) << SCALE_FACTOR_UP_FIXPOINT_SHIFT) / ((dst) - 1)) + +// marcos for hist +#define VDPP_HIST_PACKED_SIZE (10240) +#define VDPP_HIST_GLOBAL_OFFSET (16 * 16 * 16 * 18 / 8) +#define VDPP_HIST_GLOBAL_LENGTH (256) + +/* vdpp log marco */ +#define VDPP_LOG_FATAL (0x00000001) +#define VDPP_LOG_ERROR (0x00000002) +#define VDPP_LOG_WARNING (0x00000004) +#define VDPP_LOG_INFO (0x00000008) +#define VDPP_LOG_DEBUG (0x00000010) +#define VDPP_LOG_TRACE (0x00000020) + +#define vdpp_log(log_func, log_lv, fmt, ...) \ + do { \ + if (vdpp_debug & log_lv) \ + log_func(fmt, ##__VA_ARGS__); \ + } while (0) + +#define vdpp_logf(fmt, ...) vdpp_log(mpp_logf_f, VDPP_LOG_FATAL, fmt, ##__VA_ARGS__) +#define vdpp_loge(fmt, ...) vdpp_log(mpp_loge_f, VDPP_LOG_ERROR, fmt, ##__VA_ARGS__) +#define vdpp_logw(fmt, ...) vdpp_log(mpp_logw_f, VDPP_LOG_WARNING, fmt, ##__VA_ARGS__) +#define vdpp_logi(fmt, ...) vdpp_log(mpp_logi_f, VDPP_LOG_INFO, fmt, ##__VA_ARGS__) +#define vdpp_logd(fmt, ...) vdpp_log(mpp_logi_f, VDPP_LOG_DEBUG, fmt, ##__VA_ARGS__) +#define vdpp_logt(fmt, ...) vdpp_log(mpp_logi_f, VDPP_LOG_TRACE, fmt, ##__VA_ARGS__) +#define vdpp_logv(fmt, ...) vdpp_log(mpp_logi_f, VDPP_LOG_TRACE, fmt, ##__VA_ARGS__) + +#define vdpp_enter() vdpp_logv("--- enter ---"); +#define vdpp_leave() vdpp_logv("--- leave ---"); + +#define VDPP_COM_DEBUG_ENV_NAME "vdpp_debug" + + +typedef struct FdTransInfo_t { + RK_U32 reg_idx; + RK_U32 offset; +} VdppRegOffsetInfo; + +typedef struct vdpp_addr { + RK_U32 y; + RK_U32 cbcr; + RK_U32 cbcr_offset; +} VdppAddr; + + +extern RK_U32 vdpp_debug; +extern const char *working_mode_name[]; + +#ifdef __cplusplus +extern "C" { +#endif + +/* common useful functions implemented in vdpp_common.c */ +MPP_RET set_addr(struct vdpp_addr *addr, VdppImg *img); +RK_S32 get_avg_luma_from_hist(const RK_U32 *pHist, RK_S32 length); + + +/* declared common useful functions here, but implemented in vdppX.c */ + +/* implemented in vdpp1 */ +typedef struct dmsr_params DmsrParams; // forward declarations +typedef struct zme_params ZmeParams; +typedef struct scl_info VdppZmeScaleInfo; + +void vdpp_set_default_dmsr_param(DmsrParams *dmsr_param); +void vdpp_set_default_zme_param(ZmeParams *zme_param); +void set_dmsr_to_vdpp_reg(const DmsrParams *dmsr_param, RegDmsr *dmsr_reg); +void set_zme_to_vdpp_reg(const ZmeParams *zme_params, RegZme *zme_reg); +void calc_scale_factor(const ZmeParams *zme_params, VdppZmeScaleInfo *scale_info, RK_U8 bypass_en); + +/* implemented in vdpp2 */ +typedef struct EsParams_t EsParams; // forward declarations +typedef struct ShpParams_t ShpParams; +typedef struct hist_params HistParams; + +void vdpp2_set_default_hist_param(HistParams *hist_param); +void vdpp2_set_default_es_param(EsParams *es_param); +void vdpp2_set_default_shp_param(ShpParams *shp_param); +void set_hist_to_vdpp2_reg(HistParams *hist_param, RegHist *hist_reg, RegCom2 *com_reg); +void set_es_to_vdpp2_reg(EsParams *es_param, RegEs *es_reg); +void set_shp_to_vdpp2_reg(ShpParams *shp_param, RegShp *shp_reg); +int update_dci_ctl(HistParams *hist_params); + +/* implemented in vdpp3 */ +typedef struct PyrParams_t PyrParams; // forward declarations +typedef struct BbdParams_t BbdParams; + +void vdpp3_set_default_pyr_param(PyrParams *pyr_param); +void vdpp3_set_default_bbd_param(BbdParams *bbd_param); +void set_pyr_to_vdpp3_reg(const PyrParams *pyr_params, RegPyr *pyr_reg); +void set_bbd_to_vdpp3_reg(const BbdParams *bbd_params, RegBbd *bbd_reg); +void set_zme_to_vdpp3_reg(const ZmeParams *zme_params, RegZme3 *zme_reg); + +#ifdef __cplusplus +} +#endif + +#endif /* VDPP_COMMON_H */ diff --git a/mpp/vproc/vdpp/vdpp_reg.h b/mpp/vproc/vdpp/vdpp_reg.h new file mode 100644 index 000000000..a843ad342 --- /dev/null +++ b/mpp/vproc/vdpp/vdpp_reg.h @@ -0,0 +1,1795 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef VDPP_REG_H +#define VDPP_REG_H + +#include "rk_type.h" + +#define VDPP_REG_OFF_DMSR (0x0080) +#define VDPP_REG_OFF_YRGB_HOR_COE (0x2000) +#define VDPP_REG_OFF_YRGB_VER_COE (0x2200) +#define VDPP_REG_OFF_CBCR_HOR_COE (0x2400) +#define VDPP_REG_OFF_CBCR_VER_COE (0x2600) +#define VDPP_REG_OFF_ZME_COMMON (0x2800) + +typedef struct vdpp_com_reg { + struct { + RK_U32 sw_vdpp_frm_en : 1; + } reg0; // 0x0000 + + struct { + RK_U32 sw_vdpp_src_fmt : 2; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_vdpp_src_yuv_swap : 2; + RK_U32 sw_reserved_2 : 2; + RK_U32 sw_vdpp_dst_fmt : 2; + RK_U32 sw_reserved_3 : 2; + RK_U32 sw_vdpp_dst_yuv_swap : 2; + RK_U32 sw_reserved_4 : 2; + RK_U32 sw_vdpp_debug_data_en : 1; + RK_U32 sw_reserved_5 : 3; + RK_U32 sw_vdpp_rst_protect_dis : 1; + RK_U32 sys_vdpp_sreset_p : 1; + RK_U32 sw_vdpp_init_dis : 1; + RK_U32 sw_reserved_6 : 1; + RK_U32 sw_vdpp_dbmsr_en : 1; + } reg1; // 0x0004 + + struct { + RK_U32 sw_vdpp_working_mode : 2; + } reg2; // 0x0008 + + RK_U32 reg3; // 0x000C + + struct { + RK_U32 sw_vdpp_clk_on : 1; + RK_U32 sw_md_clk_on : 1; + RK_U32 sw_dect_clk_on : 1; + RK_U32 sw_me_clk_on : 1; + RK_U32 sw_mc_clk_on : 1; + RK_U32 sw_eedi_clk_on : 1; + RK_U32 sw_ble_clk_on : 1; + RK_U32 sw_out_clk_on : 1; + RK_U32 sw_ctrl_clk_on : 1; + RK_U32 sw_ram_clk_on : 1; + RK_U32 sw_dma_clk_on : 1; + RK_U32 sw_reg_clk_on : 1; + } reg4; // 0x0010 + + struct { + RK_U32 ro_arst_finish_done : 1; + } reg5; // 0x0014 + + RK_U32 reg6; // 0x0018 + RK_U32 reg7; // 0x001c + + struct { + RK_U32 sw_vdpp_frm_done_en : 1; + RK_U32 sw_vdpp_osd_max_en : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_vdpp_bus_error_en : 1; + RK_U32 sw_vdpp_timeout_int_en : 1; + RK_U32 sw_vdpp_config_error_en : 1; + } reg8; // 0x0020 + + struct { + RK_U32 sw_vdpp_frm_done_clr : 1; + RK_U32 sw_vdpp_osd_max_clr : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_vdpp_bus_error_clr : 1; + RK_U32 sw_vdpp_timeout_int_clr : 1; + RK_U32 sw_vdpp_config_error_clr : 1; + } reg9; // 0x0024 + + struct { + RK_U32 ro_frm_done_sts : 1; + RK_U32 ro_osd_max_sts : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 ro_bus_error_sts : 1; + RK_U32 ro_timeout_sts : 1; + RK_U32 ro_config_error_sts : 1; + } reg10; // 0x0028, read only + + struct { + RK_U32 ro_frm_done_raw : 1; + RK_U32 ro_osd_max_raw : 1; + RK_U32 sw_reserved_1 : 2; + RK_U32 ro_bus_error_raw : 1; + RK_U32 ro_timeout_raw : 1; + RK_U32 ro_config_error_raw : 1; + } reg11; // 0x002C, read only + + struct { + RK_U32 sw_vdpp_src_vir_y_stride : 16; + } reg12; // 0x0030 + + struct { + RK_U32 sw_vdpp_dst_vir_y_stride : 16; + } reg13; // 0x0034 + + struct { + RK_U32 sw_vdpp_src_pic_width : 11; + RK_U32 sw_reserved_1 : 1; + RK_U32 sw_vdpp_src_right_redundant : 4; + RK_U32 sw_vdpp_src_pic_height : 11; + RK_U32 sw_reserved_2 : 1; + RK_U32 sw_vdpp_src_down_redundant : 3; + } reg14; // 0x0038 + + struct { + RK_U32 sw_vdpp_dst_pic_width : 11; + RK_U32 sw_reserved_1 : 1; + RK_U32 sw_vdpp_dst_right_redundant : 4; + RK_U32 sw_vdpp_dst_pic_height : 11; + } reg15; // 0x003C + + RK_U32 reg16; // 0x0040 + RK_U32 reg17; // 0x0044 + RK_U32 reg18; // 0x0048 + RK_U32 reg19; // 0x004C + + struct { + RK_U32 sw_vdpp_timeout_cnt : 31; + RK_U32 sw_vdpp_timeout_en : 1; + } reg20; // 0x0050 + + struct { + RK_U32 svnbuild : 20; + RK_U32 minor : 8; + RK_U32 major : 4; + } reg21; // 0x0054 + + struct { + RK_U32 dbg_frm_cnt : 16; + } reg22; // 0x0058 + + RK_U32 reg23; // 0x005C + + struct { + RK_U32 sw_vdpp_src_addr_y : 32; + } reg24; // 0x0060 + + struct { + RK_U32 sw_vdpp_src_addr_uv : 32; + } reg25; // 0x0064 + + struct { + RK_U32 sw_vdpp_dst_addr_y : 32; + } reg26; // 0x0068 + + struct { + RK_U32 sw_vdpp_dst_addr_uv : 32; + } reg27; // 0x006C +} RegCom; // 0x0000 ~ 0x006C, 28 regs + +typedef struct vdpp_dmsr_reg { + struct { + RK_U32 sw_dmsr_edge_low_thre_0 : 16; + RK_U32 sw_dmsr_edge_high_thre_0 : 16; + } reg0; /* 0x0080 */ + + struct { + RK_U32 sw_dmsr_edge_low_thre_1 : 16; + RK_U32 sw_dmsr_edge_high_thre_1 : 16; + } reg1; /* 0x0084 */ + + struct { + RK_U32 sw_dmsr_edge_low_thre_2 : 16; + RK_U32 sw_dmsr_edge_high_thre_2 : 16; + } reg2; /* 0x0088 */ + + struct { + RK_U32 sw_dmsr_edge_low_thre_3 : 16; + RK_U32 sw_dmsr_edge_high_thre_3 : 16; + } reg3; /* 0x008C */ + + struct { + RK_U32 sw_dmsr_edge_low_thre_4 : 16; + RK_U32 sw_dmsr_edge_high_thre_4 : 16; + } reg4; /* 0x0090 */ + + struct { + RK_U32 sw_dmsr_edge_low_thre_5 : 16; + RK_U32 sw_dmsr_edge_high_thre_5 : 16; + } reg5; /* 0x0094 */ + + struct { + RK_U32 sw_dmsr_edge_low_thre_6 : 16; + RK_U32 sw_dmsr_edge_high_thre_6 : 16; + } reg6; /* 0x0098 */ + + struct { + RK_U32 sw_dmsr_edge_k_0 : 16; + RK_U32 sw_dmsr_edge_k_1 : 16; + } reg7; /* 0x009C */ + + struct { + RK_U32 sw_dmsr_edge_k_2 : 16; + RK_U32 sw_dmsr_edge_k_3 : 16; + } reg8; /* 0x00A0 */ + + struct { + RK_U32 sw_dmsr_edge_k_4 : 16; + RK_U32 sw_dmsr_edge_k_5 : 16; + } reg9; /* 0x00A4 */ + + struct { + RK_U32 sw_dmsr_edge_k_6 : 16; + RK_U32 sw_dmsr_dir_contrast_conf_f : 16; + } reg10; /* 0x00A8 */ + + struct { + RK_U32 sw_dmsr_dir_contrast_conf_x0 : 16; + RK_U32 sw_dmsr_dir_contrast_conf_x1 : 16; + } reg11; /* 0x00AC */ + + struct { + RK_U32 sw_dmsr_dir_contrast_conf_y0 : 16; + RK_U32 sw_dmsr_dir_contrast_conf_y1 : 16; + } reg12; /* 0x00B0 */ + + struct { + RK_U32 sw_dmsr_var_th : 16; + } reg13; /* 0x00B4 */ + + struct { + RK_U32 sw_dmsr_diff_coring_th0 : 8; + RK_U32 sw_dmsr_diff_coring_th1 : 8; + } reg14; /* 0x00B8 */ + + struct { + RK_U32 sw_dmsr_diff_coring_wgt0 : 6; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_dmsr_diff_coring_wgt1 : 6; + RK_U32 sw_reserved_2 : 2; + RK_U32 sw_dmsr_diff_coring_wgt2 : 6; + } reg15; /* 0x00BC */ + + struct { + RK_U32 sw_dmsr_diff_coring_y0 : 14; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_dmsr_diff_coring_y1 : 14; + RK_U32 sw_reserved_2 : 2; + } reg16; /* 0x00C0 */ + + struct { + RK_U32 sw_dmsr_wgt_pri_gain_1_odd : 6; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_dmsr_wgt_pri_gain_1_even : 6; + RK_U32 sw_reserved_2 : 2; + RK_U32 sw_dmsr_wgt_pri_gain_2_odd : 6; + RK_U32 sw_reserved_3 : 2; + RK_U32 sw_dmsr_wgt_pri_gain_2_even : 6; + } reg17; /* 0x00C4 */ + + struct { + RK_U32 sw_dmsr_wgt_sec_gain_1 : 6; + RK_U32 sw_reserved_1 : 2; + RK_U32 sw_dmsr_wgt_sec_gain_2 : 6; + } reg18; /* 0x00C8 */ + + struct { + RK_U32 sw_dmsr_strength_pri : 5; + RK_U32 sw_reserved_1 : 3; + RK_U32 sw_dmsr_strength_sec : 5; + RK_U32 sw_reserved_2 : 3; + RK_U32 sw_dmsr_dump : 4; + } reg19; /* 0x00CC */ + + struct { + RK_U32 sw_dmsr_obv_point_h : 12; + RK_U32 sw_dmsr_obv_point_v : 12; + RK_U32 sw_dmsr_obv_enable : 1; + RK_U32 sw_dmsr_obv_mode : 1; + } reg20; /* 0x00D0 */ +} RegDmsr; // 0x0080 ~ 0x00D0, 21 regs + +typedef struct vdpp_zme_reg { + struct { + struct { + RK_U32 yrgb_hor_coe0_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe0_1 : 10; + } reg0; /* 0x0000 */ + struct { + RK_U32 yrgb_hor_coe0_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe0_3 : 10; + } reg1; /* 0x0004 */ + struct { + RK_U32 yrgb_hor_coe0_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe0_5 : 10; + } reg2; /* 0x0008 */ + struct { + RK_U32 yrgb_hor_coe0_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe0_7 : 10; + } reg3; /* 0x000c */ + struct { + RK_U32 yrgb_hor_coe1_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe1_1 : 10; + } reg4; /* 0x0010 */ + struct { + RK_U32 yrgb_hor_coe1_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe1_3 : 10; + } reg5; /* 0x0014 */ + struct { + RK_U32 yrgb_hor_coe1_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe1_5 : 10; + } reg6; /* 0x0018 */ + struct { + RK_U32 yrgb_hor_coe1_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe1_7 : 10; + } reg7; /* 0x001c */ + struct { + RK_U32 yrgb_hor_coe2_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe2_1 : 10; + } reg8; /* 0x0020 */ + struct { + RK_U32 yrgb_hor_coe2_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe2_3 : 10; + } reg9; /* 0x0024 */ + struct { + RK_U32 yrgb_hor_coe2_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe2_5 : 10; + } reg10; /* 0x0028 */ + struct { + RK_U32 yrgb_hor_coe2_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe2_7 : 10; + } reg11; /* 0x002c */ + struct { + RK_U32 yrgb_hor_coe3_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe3_1 : 10; + } reg12; /* 0x0030 */ + struct { + RK_U32 yrgb_hor_coe3_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe3_3 : 10; + } reg13; /* 0x0034 */ + struct { + RK_U32 yrgb_hor_coe3_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe3_5 : 10; + } reg14; /* 0x0038 */ + struct { + RK_U32 yrgb_hor_coe3_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe3_7 : 10; + } reg15; /* 0x003c */ + struct { + RK_U32 yrgb_hor_coe4_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe4_1 : 10; + } reg16; /* 0x0040 */ + struct { + RK_U32 yrgb_hor_coe4_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe4_3 : 10; + } reg17; /* 0x0044 */ + struct { + RK_U32 yrgb_hor_coe4_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe4_5 : 10; + } reg18; /* 0x0048 */ + struct { + RK_U32 yrgb_hor_coe4_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe4_7 : 10; + } reg19; /* 0x004c */ + struct { + RK_U32 yrgb_hor_coe5_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe5_1 : 10; + } reg20; /* 0x0050 */ + struct { + RK_U32 yrgb_hor_coe5_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe5_3 : 10; + } reg21; /* 0x0054 */ + struct { + RK_U32 yrgb_hor_coe5_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe5_5 : 10; + } reg22; /* 0x0058 */ + struct { + RK_U32 yrgb_hor_coe5_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe5_7 : 10; + } reg23; /* 0x005c */ + struct { + RK_U32 yrgb_hor_coe6_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe6_1 : 10; + } reg24; /* 0x0060 */ + struct { + RK_U32 yrgb_hor_coe6_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe6_3 : 10; + } reg25; /* 0x0064 */ + struct { + RK_U32 yrgb_hor_coe6_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe6_5 : 10; + } reg26; /* 0x0068 */ + struct { + RK_U32 yrgb_hor_coe6_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe6_7 : 10; + } reg27; /* 0x006c */ + struct { + RK_U32 yrgb_hor_coe7_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe7_1 : 10; + } reg28; /* 0x0070 */ + struct { + RK_U32 yrgb_hor_coe7_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe7_3 : 10; + } reg29; /* 0x0074 */ + struct { + RK_U32 yrgb_hor_coe7_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe7_5 : 10; + } reg30; /* 0x0078 */ + struct { + RK_U32 yrgb_hor_coe7_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe7_7 : 10; + } reg31; /* 0x007c */ + struct { + RK_U32 yrgb_hor_coe8_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe8_1 : 10; + } reg32; /* 0x0080 */ + struct { + RK_U32 yrgb_hor_coe8_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe8_3 : 10; + } reg33; /* 0x0084 */ + struct { + RK_U32 yrgb_hor_coe8_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe8_5 : 10; + } reg34; /* 0x0088 */ + struct { + RK_U32 yrgb_hor_coe8_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe8_7 : 10; + } reg35; /* 0x008c */ + struct { + RK_U32 yrgb_hor_coe9_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe9_1 : 10; + } reg36; /* 0x0090 */ + struct { + RK_U32 yrgb_hor_coe9_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe9_3 : 10; + } reg37; /* 0x0094 */ + struct { + RK_U32 yrgb_hor_coe9_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe9_5 : 10; + } reg38; /* 0x0098 */ + struct { + RK_U32 yrgb_hor_coe9_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe9_7 : 10; + } reg39; /* 0x009c */ + struct { + RK_U32 yrgb_hor_coe10_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe10_1 : 10; + } reg40; /* 0x00a0 */ + struct { + RK_U32 yrgb_hor_coe10_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe10_3 : 10; + } reg41; /* 0x00a4 */ + struct { + RK_U32 yrgb_hor_coe10_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe10_5 : 10; + } reg42; /* 0x00a8 */ + struct { + RK_U32 yrgb_hor_coe10_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe10_7 : 10; + } reg43; /* 0x00ac */ + struct { + RK_U32 yrgb_hor_coe11_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe11_1 : 10; + } reg44; /* 0x00b0 */ + struct { + RK_U32 yrgb_hor_coe11_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe11_3 : 10; + } reg45; /* 0x00b4 */ + struct { + RK_U32 yrgb_hor_coe11_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe11_5 : 10; + } reg46; /* 0x00b8 */ + struct { + RK_U32 yrgb_hor_coe11_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe11_7 : 10; + } reg47; /* 0x00bc */ + struct { + RK_U32 yrgb_hor_coe12_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe12_1 : 10; + } reg48; /* 0x00c0 */ + struct { + RK_U32 yrgb_hor_coe12_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe12_3 : 10; + } reg49; /* 0x00c4 */ + struct { + RK_U32 yrgb_hor_coe12_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe12_5 : 10; + } reg50; /* 0x00c8 */ + struct { + RK_U32 yrgb_hor_coe12_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe12_7 : 10; + } reg51; /* 0x00cc */ + struct { + RK_U32 yrgb_hor_coe13_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe13_1 : 10; + } reg52; /* 0x00d0 */ + struct { + RK_U32 yrgb_hor_coe13_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe13_3 : 10; + } reg53; /* 0x00d4 */ + struct { + RK_U32 yrgb_hor_coe13_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe13_5 : 10; + } reg54; /* 0x00d8 */ + struct { + RK_U32 yrgb_hor_coe13_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe13_7 : 10; + } reg55; /* 0x00dc */ + struct { + RK_U32 yrgb_hor_coe14_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe14_1 : 10; + } reg56; /* 0x00e0 */ + struct { + RK_U32 yrgb_hor_coe14_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe14_3 : 10; + } reg57; /* 0x00e4 */ + struct { + RK_U32 yrgb_hor_coe14_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe14_5 : 10; + } reg58; /* 0x00e8 */ + struct { + RK_U32 yrgb_hor_coe14_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe14_7 : 10; + } reg59; /* 0x00ec */ + struct { + RK_U32 yrgb_hor_coe15_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe15_1 : 10; + } reg60; /* 0x00f0 */ + struct { + RK_U32 yrgb_hor_coe15_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe15_3 : 10; + } reg61; /* 0x00f4 */ + struct { + RK_U32 yrgb_hor_coe15_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe15_5 : 10; + } reg62; /* 0x00f8 */ + struct { + RK_U32 yrgb_hor_coe15_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe15_7 : 10; + } reg63; /* 0x00fc */ + struct { + RK_U32 yrgb_hor_coe16_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe16_1 : 10; + } reg64; /* 0x0100 */ + struct { + RK_U32 yrgb_hor_coe16_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe16_3 : 10; + } reg65; /* 0x0104 */ + struct { + RK_U32 yrgb_hor_coe16_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe16_5 : 10; + } reg66; /* 0x0108 */ + struct { + RK_U32 yrgb_hor_coe16_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_hor_coe16_7 : 10; + } reg67; /* 0x010c */ + + } yrgb_hor_coe; // 0x0000 ~ 0x010c, 68 regs + + struct { + struct { + RK_U32 yrgb_ver_coe0_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe0_1 : 10; + } reg0; /* 0x0200 */ + struct { + RK_U32 yrgb_ver_coe0_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe0_3 : 10; + } reg1; /* 0x0204 */ + struct { + RK_U32 yrgb_ver_coe0_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe0_5 : 10; + } reg2; /* 0x0208 */ + struct { + RK_U32 yrgb_ver_coe0_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe0_7 : 10; + } reg3; /* 0x020c */ + struct { + RK_U32 yrgb_ver_coe1_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe1_1 : 10; + } reg4; /* 0x0210 */ + struct { + RK_U32 yrgb_ver_coe1_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe1_3 : 10; + } reg5; /* 0x0214 */ + struct { + RK_U32 yrgb_ver_coe1_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe1_5 : 10; + } reg6; /* 0x0218 */ + struct { + RK_U32 yrgb_ver_coe1_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe1_7 : 10; + } reg7; /* 0x021c */ + struct { + RK_U32 yrgb_ver_coe2_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe2_1 : 10; + } reg8; /* 0x0220 */ + struct { + RK_U32 yrgb_ver_coe2_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe2_3 : 10; + } reg9; /* 0x0224 */ + struct { + RK_U32 yrgb_ver_coe2_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe2_5 : 10; + } reg10; /* 0x0228 */ + struct { + RK_U32 yrgb_ver_coe2_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe2_7 : 10; + } reg11; /* 0x022c */ + struct { + RK_U32 yrgb_ver_coe3_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe3_1 : 10; + } reg12; /* 0x0230 */ + struct { + RK_U32 yrgb_ver_coe3_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe3_3 : 10; + } reg13; /* 0x0234 */ + struct { + RK_U32 yrgb_ver_coe3_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe3_5 : 10; + } reg14; /* 0x0238 */ + struct { + RK_U32 yrgb_ver_coe3_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe3_7 : 10; + } reg15; /* 0x023c */ + struct { + RK_U32 yrgb_ver_coe4_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe4_1 : 10; + } reg16; /* 0x0240 */ + struct { + RK_U32 yrgb_ver_coe4_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe4_3 : 10; + } reg17; /* 0x0244 */ + struct { + RK_U32 yrgb_ver_coe4_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe4_5 : 10; + } reg18; /* 0x0248 */ + struct { + RK_U32 yrgb_ver_coe4_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe4_7 : 10; + } reg19; /* 0x024c */ + struct { + RK_U32 yrgb_ver_coe5_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe5_1 : 10; + } reg20; /* 0x0250 */ + struct { + RK_U32 yrgb_ver_coe5_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe5_3 : 10; + } reg21; /* 0x0254 */ + struct { + RK_U32 yrgb_ver_coe5_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe5_5 : 10; + } reg22; /* 0x0258 */ + struct { + RK_U32 yrgb_ver_coe5_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe5_7 : 10; + } reg23; /* 0x025c */ + struct { + RK_U32 yrgb_ver_coe6_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe6_1 : 10; + } reg24; /* 0x0260 */ + struct { + RK_U32 yrgb_ver_coe6_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe6_3 : 10; + } reg25; /* 0x0264 */ + struct { + RK_U32 yrgb_ver_coe6_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe6_5 : 10; + } reg26; /* 0x0268 */ + struct { + RK_U32 yrgb_ver_coe6_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe6_7 : 10; + } reg27; /* 0x026c */ + struct { + RK_U32 yrgb_ver_coe7_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe7_1 : 10; + } reg28; /* 0x0270 */ + struct { + RK_U32 yrgb_ver_coe7_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe7_3 : 10; + } reg29; /* 0x0274 */ + struct { + RK_U32 yrgb_ver_coe7_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe7_5 : 10; + } reg30; /* 0x0278 */ + struct { + RK_U32 yrgb_ver_coe7_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe7_7 : 10; + } reg31; /* 0x027c */ + struct { + RK_U32 yrgb_ver_coe8_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe8_1 : 10; + } reg32; /* 0x0280 */ + struct { + RK_U32 yrgb_ver_coe8_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe8_3 : 10; + } reg33; /* 0x0284 */ + struct { + RK_U32 yrgb_ver_coe8_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe8_5 : 10; + } reg34; /* 0x0288 */ + struct { + RK_U32 yrgb_ver_coe8_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe8_7 : 10; + } reg35; /* 0x028c */ + struct { + RK_U32 yrgb_ver_coe9_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe9_1 : 10; + } reg36; /* 0x0290 */ + struct { + RK_U32 yrgb_ver_coe9_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe9_3 : 10; + } reg37; /* 0x0294 */ + struct { + RK_U32 yrgb_ver_coe9_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe9_5 : 10; + } reg38; /* 0x0298 */ + struct { + RK_U32 yrgb_ver_coe9_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe9_7 : 10; + } reg39; /* 0x029c */ + struct { + RK_U32 yrgb_ver_coe10_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe10_1 : 10; + } reg40; /* 0x02a0 */ + struct { + RK_U32 yrgb_ver_coe10_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe10_3 : 10; + } reg41; /* 0x02a4 */ + struct { + RK_U32 yrgb_ver_coe10_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe10_5 : 10; + } reg42; /* 0x02a8 */ + struct { + RK_U32 yrgb_ver_coe10_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe10_7 : 10; + } reg43; /* 0x02ac */ + struct { + RK_U32 yrgb_ver_coe11_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe11_1 : 10; + } reg44; /* 0x02b0 */ + struct { + RK_U32 yrgb_ver_coe11_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe11_3 : 10; + } reg45; /* 0x02b4 */ + struct { + RK_U32 yrgb_ver_coe11_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe11_5 : 10; + } reg46; /* 0x02b8 */ + struct { + RK_U32 yrgb_ver_coe11_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe11_7 : 10; + } reg47; /* 0x02bc */ + struct { + RK_U32 yrgb_ver_coe12_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe12_1 : 10; + } reg48; /* 0x02c0 */ + struct { + RK_U32 yrgb_ver_coe12_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe12_3 : 10; + } reg49; /* 0x02c4 */ + struct { + RK_U32 yrgb_ver_coe12_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe12_5 : 10; + } reg50; /* 0x02c8 */ + struct { + RK_U32 yrgb_ver_coe12_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe12_7 : 10; + } reg51; /* 0x02cc */ + struct { + RK_U32 yrgb_ver_coe13_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe13_1 : 10; + } reg52; /* 0x02d0 */ + struct { + RK_U32 yrgb_ver_coe13_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe13_3 : 10; + } reg53; /* 0x02d4 */ + struct { + RK_U32 yrgb_ver_coe13_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe13_5 : 10; + } reg54; /* 0x02d8 */ + struct { + RK_U32 yrgb_ver_coe13_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe13_7 : 10; + } reg55; /* 0x02dc */ + struct { + RK_U32 yrgb_ver_coe14_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe14_1 : 10; + } reg56; /* 0x02e0 */ + struct { + RK_U32 yrgb_ver_coe14_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe14_3 : 10; + } reg57; /* 0x02e4 */ + struct { + RK_U32 yrgb_ver_coe14_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe14_5 : 10; + } reg58; /* 0x02e8 */ + struct { + RK_U32 yrgb_ver_coe14_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe14_7 : 10; + } reg59; /* 0x02ec */ + struct { + RK_U32 yrgb_ver_coe15_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe15_1 : 10; + } reg60; /* 0x02f0 */ + struct { + RK_U32 yrgb_ver_coe15_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe15_3 : 10; + } reg61; /* 0x02f4 */ + struct { + RK_U32 yrgb_ver_coe15_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe15_5 : 10; + } reg62; /* 0x02f8 */ + struct { + RK_U32 yrgb_ver_coe15_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe15_7 : 10; + } reg63; /* 0x02fc */ + struct { + RK_U32 yrgb_ver_coe16_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe16_1 : 10; + } reg64; /* 0x0300 */ + struct { + RK_U32 yrgb_ver_coe16_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe16_3 : 10; + } reg65; /* 0x0304 */ + struct { + RK_U32 yrgb_ver_coe16_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe16_5 : 10; + } reg66; /* 0x0308 */ + struct { + RK_U32 yrgb_ver_coe16_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 yrgb_ver_coe16_7 : 10; + } reg67; /* 0x030c */ + + } yrgb_ver_coe; // 0x0200 ~ 0x030c, 68 regs + + struct { + struct { + RK_U32 cbcr_hor_coe0_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe0_1 : 10; + } reg0; /* 0x0400 */ + struct { + RK_U32 cbcr_hor_coe0_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe0_3 : 10; + } reg1; /* 0x0404 */ + struct { + RK_U32 cbcr_hor_coe0_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe0_5 : 10; + } reg2; /* 0x0408 */ + struct { + RK_U32 cbcr_hor_coe0_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe0_7 : 10; + } reg3; /* 0x040c */ + struct { + RK_U32 cbcr_hor_coe1_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe1_1 : 10; + } reg4; /* 0x0410 */ + struct { + RK_U32 cbcr_hor_coe1_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe1_3 : 10; + } reg5; /* 0x0414 */ + struct { + RK_U32 cbcr_hor_coe1_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe1_5 : 10; + } reg6; /* 0x0418 */ + struct { + RK_U32 cbcr_hor_coe1_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe1_7 : 10; + } reg7; /* 0x041c */ + struct { + RK_U32 cbcr_hor_coe2_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe2_1 : 10; + } reg8; /* 0x0420 */ + struct { + RK_U32 cbcr_hor_coe2_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe2_3 : 10; + } reg9; /* 0x0424 */ + struct { + RK_U32 cbcr_hor_coe2_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe2_5 : 10; + } reg10; /* 0x0428 */ + struct { + RK_U32 cbcr_hor_coe2_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe2_7 : 10; + } reg11; /* 0x042c */ + struct { + RK_U32 cbcr_hor_coe3_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe3_1 : 10; + } reg12; /* 0x0430 */ + struct { + RK_U32 cbcr_hor_coe3_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe3_3 : 10; + } reg13; /* 0x0434 */ + struct { + RK_U32 cbcr_hor_coe3_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe3_5 : 10; + } reg14; /* 0x0438 */ + struct { + RK_U32 cbcr_hor_coe3_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe3_7 : 10; + } reg15; /* 0x043c */ + struct { + RK_U32 cbcr_hor_coe4_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe4_1 : 10; + } reg16; /* 0x0440 */ + struct { + RK_U32 cbcr_hor_coe4_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe4_3 : 10; + } reg17; /* 0x0444 */ + struct { + RK_U32 cbcr_hor_coe4_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe4_5 : 10; + } reg18; /* 0x0448 */ + struct { + RK_U32 cbcr_hor_coe4_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe4_7 : 10; + } reg19; /* 0x044c */ + struct { + RK_U32 cbcr_hor_coe5_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe5_1 : 10; + } reg20; /* 0x0450 */ + struct { + RK_U32 cbcr_hor_coe5_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe5_3 : 10; + } reg21; /* 0x0454 */ + struct { + RK_U32 cbcr_hor_coe5_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe5_5 : 10; + } reg22; /* 0x0458 */ + struct { + RK_U32 cbcr_hor_coe5_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe5_7 : 10; + } reg23; /* 0x045c */ + struct { + RK_U32 cbcr_hor_coe6_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe6_1 : 10; + } reg24; /* 0x0460 */ + struct { + RK_U32 cbcr_hor_coe6_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe6_3 : 10; + } reg25; /* 0x0464 */ + struct { + RK_U32 cbcr_hor_coe6_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe6_5 : 10; + } reg26; /* 0x0468 */ + struct { + RK_U32 cbcr_hor_coe6_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe6_7 : 10; + } reg27; /* 0x046c */ + struct { + RK_U32 cbcr_hor_coe7_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe7_1 : 10; + } reg28; /* 0x0470 */ + struct { + RK_U32 cbcr_hor_coe7_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe7_3 : 10; + } reg29; /* 0x0474 */ + struct { + RK_U32 cbcr_hor_coe7_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe7_5 : 10; + } reg30; /* 0x0478 */ + struct { + RK_U32 cbcr_hor_coe7_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe7_7 : 10; + } reg31; /* 0x047c */ + struct { + RK_U32 cbcr_hor_coe8_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe8_1 : 10; + } reg32; /* 0x0480 */ + struct { + RK_U32 cbcr_hor_coe8_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe8_3 : 10; + } reg33; /* 0x0484 */ + struct { + RK_U32 cbcr_hor_coe8_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe8_5 : 10; + } reg34; /* 0x0488 */ + struct { + RK_U32 cbcr_hor_coe8_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe8_7 : 10; + } reg35; /* 0x048c */ + struct { + RK_U32 cbcr_hor_coe9_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe9_1 : 10; + } reg36; /* 0x0490 */ + struct { + RK_U32 cbcr_hor_coe9_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe9_3 : 10; + } reg37; /* 0x0494 */ + struct { + RK_U32 cbcr_hor_coe9_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe9_5 : 10; + } reg38; /* 0x0498 */ + struct { + RK_U32 cbcr_hor_coe9_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe9_7 : 10; + } reg39; /* 0x049c */ + struct { + RK_U32 cbcr_hor_coe10_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe10_1 : 10; + } reg40; /* 0x04a0 */ + struct { + RK_U32 cbcr_hor_coe10_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe10_3 : 10; + } reg41; /* 0x04a4 */ + struct { + RK_U32 cbcr_hor_coe10_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe10_5 : 10; + } reg42; /* 0x04a8 */ + struct { + RK_U32 cbcr_hor_coe10_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe10_7 : 10; + } reg43; /* 0x04ac */ + struct { + RK_U32 cbcr_hor_coe11_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe11_1 : 10; + } reg44; /* 0x04b0 */ + struct { + RK_U32 cbcr_hor_coe11_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe11_3 : 10; + } reg45; /* 0x04b4 */ + struct { + RK_U32 cbcr_hor_coe11_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe11_5 : 10; + } reg46; /* 0x04b8 */ + struct { + RK_U32 cbcr_hor_coe11_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe11_7 : 10; + } reg47; /* 0x04bc */ + struct { + RK_U32 cbcr_hor_coe12_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe12_1 : 10; + } reg48; /* 0x04c0 */ + struct { + RK_U32 cbcr_hor_coe12_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe12_3 : 10; + } reg49; /* 0x04c4 */ + struct { + RK_U32 cbcr_hor_coe12_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe12_5 : 10; + } reg50; /* 0x04c8 */ + struct { + RK_U32 cbcr_hor_coe12_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe12_7 : 10; + } reg51; /* 0x04cc */ + struct { + RK_U32 cbcr_hor_coe13_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe13_1 : 10; + } reg52; /* 0x04d0 */ + struct { + RK_U32 cbcr_hor_coe13_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe13_3 : 10; + } reg53; /* 0x04d4 */ + struct { + RK_U32 cbcr_hor_coe13_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe13_5 : 10; + } reg54; /* 0x04d8 */ + struct { + RK_U32 cbcr_hor_coe13_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe13_7 : 10; + } reg55; /* 0x04dc */ + struct { + RK_U32 cbcr_hor_coe14_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe14_1 : 10; + } reg56; /* 0x04e0 */ + struct { + RK_U32 cbcr_hor_coe14_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe14_3 : 10; + } reg57; /* 0x04e4 */ + struct { + RK_U32 cbcr_hor_coe14_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe14_5 : 10; + } reg58; /* 0x04e8 */ + struct { + RK_U32 cbcr_hor_coe14_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe14_7 : 10; + } reg59; /* 0x04ec */ + struct { + RK_U32 cbcr_hor_coe15_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe15_1 : 10; + } reg60; /* 0x04f0 */ + struct { + RK_U32 cbcr_hor_coe15_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe15_3 : 10; + } reg61; /* 0x04f4 */ + struct { + RK_U32 cbcr_hor_coe15_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe15_5 : 10; + } reg62; /* 0x04f8 */ + struct { + RK_U32 cbcr_hor_coe15_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe15_7 : 10; + } reg63; /* 0x04fc */ + struct { + RK_U32 cbcr_hor_coe16_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe16_1 : 10; + } reg64; /* 0x0500 */ + struct { + RK_U32 cbcr_hor_coe16_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe16_3 : 10; + } reg65; /* 0x0504 */ + struct { + RK_U32 cbcr_hor_coe16_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe16_5 : 10; + } reg66; /* 0x0508 */ + struct { + RK_U32 cbcr_hor_coe16_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_hor_coe16_7 : 10; + } reg67; /* 0x050c */ + + } cbcr_hor_coe; // 0x0400 ~ 0x050c, 68 regs + + struct { + struct { + RK_U32 cbcr_ver_coe0_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe0_1 : 10; + } reg0; /* 0x0600 */ + struct { + RK_U32 cbcr_ver_coe0_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe0_3 : 10; + } reg1; /* 0x0604 */ + struct { + RK_U32 cbcr_ver_coe0_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe0_5 : 10; + } reg2; /* 0x0608 */ + struct { + RK_U32 cbcr_ver_coe0_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe0_7 : 10; + } reg3; /* 0x060c */ + struct { + RK_U32 cbcr_ver_coe1_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe1_1 : 10; + } reg4; /* 0x0610 */ + struct { + RK_U32 cbcr_ver_coe1_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe1_3 : 10; + } reg5; /* 0x0614 */ + struct { + RK_U32 cbcr_ver_coe1_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe1_5 : 10; + } reg6; /* 0x0618 */ + struct { + RK_U32 cbcr_ver_coe1_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe1_7 : 10; + } reg7; /* 0x061c */ + struct { + RK_U32 cbcr_ver_coe2_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe2_1 : 10; + } reg8; /* 0x0620 */ + struct { + RK_U32 cbcr_ver_coe2_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe2_3 : 10; + } reg9; /* 0x0624 */ + struct { + RK_U32 cbcr_ver_coe2_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe2_5 : 10; + } reg10; /* 0x0628 */ + struct { + RK_U32 cbcr_ver_coe2_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe2_7 : 10; + } reg11; /* 0x062c */ + struct { + RK_U32 cbcr_ver_coe3_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe3_1 : 10; + } reg12; /* 0x0630 */ + struct { + RK_U32 cbcr_ver_coe3_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe3_3 : 10; + } reg13; /* 0x0634 */ + struct { + RK_U32 cbcr_ver_coe3_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe3_5 : 10; + } reg14; /* 0x0638 */ + struct { + RK_U32 cbcr_ver_coe3_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe3_7 : 10; + } reg15; /* 0x063c */ + struct { + RK_U32 cbcr_ver_coe4_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe4_1 : 10; + } reg16; /* 0x0640 */ + struct { + RK_U32 cbcr_ver_coe4_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe4_3 : 10; + } reg17; /* 0x0644 */ + struct { + RK_U32 cbcr_ver_coe4_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe4_5 : 10; + } reg18; /* 0x0648 */ + struct { + RK_U32 cbcr_ver_coe4_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe4_7 : 10; + } reg19; /* 0x064c */ + struct { + RK_U32 cbcr_ver_coe5_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe5_1 : 10; + } reg20; /* 0x0650 */ + struct { + RK_U32 cbcr_ver_coe5_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe5_3 : 10; + } reg21; /* 0x0654 */ + struct { + RK_U32 cbcr_ver_coe5_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe5_5 : 10; + } reg22; /* 0x0658 */ + struct { + RK_U32 cbcr_ver_coe5_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe5_7 : 10; + } reg23; /* 0x065c */ + struct { + RK_U32 cbcr_ver_coe6_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe6_1 : 10; + } reg24; /* 0x0660 */ + struct { + RK_U32 cbcr_ver_coe6_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe6_3 : 10; + } reg25; /* 0x0664 */ + struct { + RK_U32 cbcr_ver_coe6_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe6_5 : 10; + } reg26; /* 0x0668 */ + struct { + RK_U32 cbcr_ver_coe6_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe6_7 : 10; + } reg27; /* 0x066c */ + struct { + RK_U32 cbcr_ver_coe7_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe7_1 : 10; + } reg28; /* 0x0670 */ + struct { + RK_U32 cbcr_ver_coe7_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe7_3 : 10; + } reg29; /* 0x0674 */ + struct { + RK_U32 cbcr_ver_coe7_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe7_5 : 10; + } reg30; /* 0x0678 */ + struct { + RK_U32 cbcr_ver_coe7_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe7_7 : 10; + } reg31; /* 0x067c */ + struct { + RK_U32 cbcr_ver_coe8_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe8_1 : 10; + } reg32; /* 0x0680 */ + struct { + RK_U32 cbcr_ver_coe8_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe8_3 : 10; + } reg33; /* 0x0684 */ + struct { + RK_U32 cbcr_ver_coe8_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe8_5 : 10; + } reg34; /* 0x0688 */ + struct { + RK_U32 cbcr_ver_coe8_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe8_7 : 10; + } reg35; /* 0x068c */ + struct { + RK_U32 cbcr_ver_coe9_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe9_1 : 10; + } reg36; /* 0x0690 */ + struct { + RK_U32 cbcr_ver_coe9_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe9_3 : 10; + } reg37; /* 0x0694 */ + struct { + RK_U32 cbcr_ver_coe9_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe9_5 : 10; + } reg38; /* 0x0698 */ + struct { + RK_U32 cbcr_ver_coe9_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe9_7 : 10; + } reg39; /* 0x069c */ + struct { + RK_U32 cbcr_ver_coe10_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe10_1 : 10; + } reg40; /* 0x06a0 */ + struct { + RK_U32 cbcr_ver_coe10_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe10_3 : 10; + } reg41; /* 0x06a4 */ + struct { + RK_U32 cbcr_ver_coe10_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe10_5 : 10; + } reg42; /* 0x06a8 */ + struct { + RK_U32 cbcr_ver_coe10_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe10_7 : 10; + } reg43; /* 0x06ac */ + struct { + RK_U32 cbcr_ver_coe11_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe11_1 : 10; + } reg44; /* 0x06b0 */ + struct { + RK_U32 cbcr_ver_coe11_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe11_3 : 10; + } reg45; /* 0x06b4 */ + struct { + RK_U32 cbcr_ver_coe11_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe11_5 : 10; + } reg46; /* 0x06b8 */ + struct { + RK_U32 cbcr_ver_coe11_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe11_7 : 10; + } reg47; /* 0x06bc */ + struct { + RK_U32 cbcr_ver_coe12_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe12_1 : 10; + } reg48; /* 0x06c0 */ + struct { + RK_U32 cbcr_ver_coe12_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe12_3 : 10; + } reg49; /* 0x06c4 */ + struct { + RK_U32 cbcr_ver_coe12_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe12_5 : 10; + } reg50; /* 0x06c8 */ + struct { + RK_U32 cbcr_ver_coe12_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe12_7 : 10; + } reg51; /* 0x06cc */ + struct { + RK_U32 cbcr_ver_coe13_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe13_1 : 10; + } reg52; /* 0x06d0 */ + struct { + RK_U32 cbcr_ver_coe13_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe13_3 : 10; + } reg53; /* 0x06d4 */ + struct { + RK_U32 cbcr_ver_coe13_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe13_5 : 10; + } reg54; /* 0x06d8 */ + struct { + RK_U32 cbcr_ver_coe13_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe13_7 : 10; + } reg55; /* 0x06dc */ + struct { + RK_U32 cbcr_ver_coe14_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe14_1 : 10; + } reg56; /* 0x06e0 */ + struct { + RK_U32 cbcr_ver_coe14_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe14_3 : 10; + } reg57; /* 0x06e4 */ + struct { + RK_U32 cbcr_ver_coe14_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe14_5 : 10; + } reg58; /* 0x06e8 */ + struct { + RK_U32 cbcr_ver_coe14_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe14_7 : 10; + } reg59; /* 0x06ec */ + struct { + RK_U32 cbcr_ver_coe15_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe15_1 : 10; + } reg60; /* 0x06f0 */ + struct { + RK_U32 cbcr_ver_coe15_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe15_3 : 10; + } reg61; /* 0x06f4 */ + struct { + RK_U32 cbcr_ver_coe15_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe15_5 : 10; + } reg62; /* 0x06f8 */ + struct { + RK_U32 cbcr_ver_coe15_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe15_7 : 10; + } reg63; /* 0x06fc */ + struct { + RK_U32 cbcr_ver_coe16_0 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe16_1 : 10; + } reg64; /* 0x0700 */ + struct { + RK_U32 cbcr_ver_coe16_2 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe16_3 : 10; + } reg65; /* 0x0704 */ + struct { + RK_U32 cbcr_ver_coe16_4 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe16_5 : 10; + } reg66; /* 0x0708 */ + struct { + RK_U32 cbcr_ver_coe16_6 : 10; + RK_U32 sw_reserved_1 : 6; + RK_U32 cbcr_ver_coe16_7 : 10; + } reg67; /* 0x070c */ + + } cbcr_ver_coe; // 0x0600 ~ 0x070c, 68 regs + + struct { + struct { + RK_U32 bypass_en : 1; + RK_U32 align_en : 1; + RK_U32 reserved_1 : 2; + RK_U32 format_in : 4; + RK_U32 format_out : 4; + RK_U32 reserved_2 : 19; + RK_U32 auto_gating_en : 1; + } reg0; /* 0x0800 */ + + RK_U32 reg1; /* 0x0804 */ + RK_U32 reg2; /* 0x0808 */ + + struct { + RK_U32 vir_width : 16; + RK_U32 vir_height : 16; + } reg3; /* 0x080C */ + + struct { + RK_U32 yrgb_xsd_en : 1; + RK_U32 yrgb_xsu_en : 1; + RK_U32 yrgb_scl_mode : 2; + RK_U32 yrgb_ysd_en : 1; + RK_U32 yrgb_ysu_en : 1; + RK_U32 yrgb_yscl_mode : 2; + RK_U32 yrgb_dering_en : 1; + RK_U32 yrgb_gt_en : 1; + RK_U32 yrgb_gt_mode : 2; + RK_U32 yrgb_xgt_en : 1; + RK_U32 reserved_1 : 1; + RK_U32 yrgb_xgt_mode : 2; + RK_U32 yrgb_xsd_bypass : 1; + RK_U32 yrgb_ys_bypass : 1; + RK_U32 yrgb_xsu_bypass : 1; + } reg4; /* 0x0810 */ + + struct { + RK_U32 yrgb_src_width : 16; + RK_U32 yrgb_src_height : 16; + } reg5; /* 0x0814 */ + + struct { + RK_U32 yrgb_dst_width : 16; + RK_U32 yrgb_dst_height : 16; + } reg6; /* 0x0818 */ + + struct { + RK_U32 yrgb_dering_sen0 : 5; + RK_U32 reserved_1 : 3; + RK_U32 yrgb_dering_sen1 : 5; + RK_U32 reserved_2 : 3; + RK_U32 yrgb_dering_alpha: 5; + RK_U32 reserved_3 : 3; + RK_U32 yrgb_dering_delta: 5; + } reg7; /* 0x081C */ + + struct { + RK_U32 yrgb_xscl_factor : 16; + RK_U32 yrgb_xscl_offset : 16; + } reg8; /* 0x0820 */ + + struct { + RK_U32 yrgb_yscl_factor : 16; + RK_U32 yrgb_yscl_offset : 16; + } reg9; /* 0x0824 */ + + RK_U32 reg10; /* 0x0828 */ + RK_U32 reg11; /* 0x082C */ + + struct { + RK_U32 cbcr_xsd_en : 1; + RK_U32 cbcr_xsu_en : 1; + RK_U32 cbcr_xscl_mode : 2; + RK_U32 cbcr_ysd_en : 1; + RK_U32 cbcr_ysu_en : 1; + RK_U32 cbcr_yscl_mode : 2; + RK_U32 cbcr_dering_en : 1; + RK_U32 cbcr_gt_en : 1; + RK_U32 cbcr_gt_mode : 2; + RK_U32 cbcr_xgt_en : 1; + RK_U32 reserved_1 : 1; + RK_U32 cbcr_xgt_mode : 2; + RK_U32 cbcr_xsd_bypass : 1; + RK_U32 cbcr_ys_bypass : 1; + RK_U32 cbcr_xsu_bypass : 1; + } reg12; /* 0x0830 */ + + struct { + RK_U32 cbcr_src_width : 16; + RK_U32 cbcr_src_height : 16; + } reg13; /* 0x0834 */ + + struct { + RK_U32 cbcr_dst_width : 16; + RK_U32 cbcr_dst_height : 16; + } reg14; /* 0x0838 */ + + struct { + RK_U32 cbcr_dering_sen0 : 5; + RK_U32 reserved_1 : 3; + RK_U32 cbcr_dering_sen1 : 5; + RK_U32 reserved_2 : 3; + RK_U32 cbcr_dering_alpha: 5; + RK_U32 reserved_3 : 3; + RK_U32 cbcr_dering_delta: 5; + } reg15; /* 0x083C */ + + struct { + RK_U32 cbcr_xscl_factor : 16; + RK_U32 cbcr_xscl_offset : 16; + } reg16; /* 0x0840 */ + + struct { + RK_U32 cbcr_yscl_factor : 16; + RK_U32 cbcr_yscl_offset : 16; + } reg17; /* 0x0844 */ + + } common; // 0x0800 ~ 0x0844, 18 regs + +} RegZme; // 0x000 ~ 0x0844, 68*4+18=290(/530) regs + +typedef struct vdpp_reg { + RegCom common; /* offset: 0x1000, end: 0x106C, size: 112 */ + RegDmsr dmsr; /* offset: 0x1080, end: 0x10D0, size: 84 */ + RegZme zme; /* offset: 0x2000, end: 0x2844, size: 1160(valid)/2120(total) */ +} Vdpp1Regs; + +#endif /* VDPP_REG_H */ diff --git a/osal/CMakeLists.txt b/osal/CMakeLists.txt index 5570588f4..ee02d902a 100644 --- a/osal/CMakeLists.txt +++ b/osal/CMakeLists.txt @@ -1,37 +1,68 @@ # vim: syntax=cmake -if(${ANDROID}) -set(OS_DIR android) -elseif(${UNIX}) -set(OS_DIR linux) -elseif(${WIN32}) -set(OS_DIR window) -else() -message(SEND_ERROR "Can not found platform definistion ${CMAKE_SYSTEM}") -endif() -include_directories(.) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_REENTRANT -D_GNU_SOURCE") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") -add_library(osal STATIC - mpp_allocator.cpp - mpp_thread.cpp - mpp_common.cpp - mpp_time.cpp - mpp_list.cpp - mpp_mem.cpp - mpp_env.cpp - mpp_log.cpp - ${OS_DIR}/os_allocator.c - ${OS_DIR}/os_mem.c - ${OS_DIR}/os_env.c - ${OS_DIR}/os_log.c - ) +set(MPP_ALLOCATOR + allocator/allocator_std.c + allocator/allocator_ion.c + allocator/allocator_ext_dma.c + allocator/allocator_dma_heap.c + allocator/allocator_drm.c +) -if(ANDROID) - # in Android pthread is in libc, also need liblog - target_link_libraries(osal log stdc++ m c ) -else() - target_link_libraries(osal pthread) -endif() +set(MPP_DRIVER + driver/mpp_server.c + driver/mpp_device.c + driver/mpp_service.c + driver/vcodec_service.c + driver/mpp_vcodec_client.c +) -set_target_properties(osal PROPERTIES FOLDER "osal") +add_library(osal OBJECT + mpp_sgln_base.c + mpp_singleton.c + mpp_soc.c + mpp_platform.c + mpp_runtime.c + mpp_allocator.c + mpp_mem_pool.c + mpp_callback.c + mpp_eventfd.c + mpp_dmabuf.c + mpp_thread.c + mpp_compat.c + mpp_common.c + mpp_queue.c + mpp_trace.c + mpp_lock.c + mpp_time.c + mpp_list.c + mpp_ring.c + mpp_mem.c + mpp_env.c + mpp_log.c + osal_2str.c + # Those files have a compiler marco protection, so only target + # OS will be built + android/os_mem.c + android/os_env.c + android/os_log.c + linux/os_mem.c + linux/os_env.c + linux/os_log.c + ${MPP_ALLOCATOR} + ${MPP_DRIVER} +) + +target_include_directories(osal PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/inc" + "${CMAKE_CURRENT_SOURCE_DIR}/allocator" + "${CMAKE_CURRENT_SOURCE_DIR}/driver/inc" +) + +# unit test add_subdirectory(test) diff --git a/osal/allocator/allocator_dma_heap.c b/osal/allocator/allocator_dma_heap.c new file mode 100644 index 000000000..b08cc7c98 --- /dev/null +++ b/osal/allocator/allocator_dma_heap.c @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2010 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dma_heap" + +#include +#include +#include +#include +#include + +#include "os_mem.h" +#include "allocator_dma_heap.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_lock.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" +#include "mpp_runtime.h" + +#define DMA_HEAP_VALID_FD_FLAGS (O_CLOEXEC | O_ACCMODE) +#define DMA_HEAP_VALID_HEAP_FLAGS (0) + +struct dma_heap_allocation_data { + RK_U64 len; + RK_U32 fd; + RK_U32 fd_flags; + RK_U64 heap_flags; +}; + +#define DMA_HEAP_IOC_MAGIC 'H' +#define DMA_HEAP_IOCTL_ALLOC _IOWR(DMA_HEAP_IOC_MAGIC, 0x0, struct dma_heap_allocation_data) + +static RK_U32 dma_heap_debug = 0; + +#define DMA_HEAP_OPS (0x00000001) +#define DMA_HEAP_DEVICE (0x00000002) +#define DMA_HEAP_IOCTL (0x00000004) +#define DMA_HEAP_CHECK (0x00000008) + +#define dma_heap_dbg(flag, fmt, ...) mpp_dbg(dma_heap_debug, flag, fmt, ## __VA_ARGS__) +#define dma_heap_dbg_f(flag, fmt, ...) mpp_dbg_f(dma_heap_debug, flag, fmt, ## __VA_ARGS__) + +#define dma_heap_dbg_ops(fmt, ...) dma_heap_dbg(DMA_HEAP_OPS, fmt, ## __VA_ARGS__) +#define dma_heap_dbg_dev(fmt, ...) dma_heap_dbg(DMA_HEAP_DEVICE, fmt, ## __VA_ARGS__) +#define dma_heap_dbg_ioctl(fmt, ...) dma_heap_dbg(DMA_HEAP_IOCTL, fmt, ## __VA_ARGS__) +#define dma_heap_dbg_chk(fmt, ...) dma_heap_dbg(DMA_HEAP_CHECK, fmt, ## __VA_ARGS__) + +typedef struct { + RK_U32 alignment; + RK_S32 device; + RK_U32 flags; +} allocator_ctx_dmaheap; + +typedef struct DmaHeapInfo_t { + const char *name; + RK_S32 fd; + RK_U32 flags; +} DmaHeapInfo; + +static DmaHeapInfo heap_infos[MPP_ALLOC_FLAG_TYPE_NB] = { + { "system-uncached", -1, MPP_ALLOC_FLAG_NONE , }, /* 0 */ + { "system-uncached-dma32", -1, MPP_ALLOC_FLAG_DMA32, }, /* 1 */ + { "system", -1, MPP_ALLOC_FLAG_CACHABLE , }, /* 2 */ + { "system-dma32", -1, MPP_ALLOC_FLAG_CACHABLE | MPP_ALLOC_FLAG_DMA32, }, /* 3 */ + { "cma-uncached", -1, MPP_ALLOC_FLAG_CMA , }, /* 4 */ + { "cma-uncached-dma32", -1, MPP_ALLOC_FLAG_CMA | MPP_ALLOC_FLAG_DMA32, }, /* 5 */ + { "cma", -1, MPP_ALLOC_FLAG_CMA | MPP_ALLOC_FLAG_CACHABLE , }, /* 6 */ + { "cma-dma32", -1, MPP_ALLOC_FLAG_CMA | MPP_ALLOC_FLAG_CACHABLE | MPP_ALLOC_FLAG_DMA32, }, /* 7 */ +}; + +static int try_open_path(const char *name) +{ + static const char *heap_path = "/dev/dma_heap/"; + char buf[64]; + int fd; + + snprintf(buf, sizeof(buf) - 1, "%s%s", heap_path, name); + fd = open(buf, O_RDONLY | O_CLOEXEC); // read permission is enough + + dma_heap_dbg_ops("open dma_heap %-24s -> fd %d\n", name, fd); + + return fd; +} + +static MPP_RET try_flip_flag(RK_U32 orig, RK_U32 flag) +{ + DmaHeapInfo *dst = &heap_infos[orig]; + DmaHeapInfo *src; + RK_U32 used; + + if (orig & flag) + used = (RK_U32)(orig & (~flag)); + else + used = (RK_U32)(orig | flag); + + src = &heap_infos[used]; + if (src->fd > 0) { + /* found valid heap use it */ + dst->fd = mpp_dup(src->fd); + dst->flags = src->flags; + + dma_heap_dbg_chk("dma-heap type %x %s remap to %x %s\n", + orig, dst->name, used, src->name); + } + + return dst->fd > 0 ? MPP_OK : MPP_NOK; +} + +__attribute__ ((constructor)) +void dma_heap_init(void) +{ + DmaHeapInfo *info = NULL; + RK_U32 all_success = 1; + RK_U32 i; + + mpp_env_get_u32("dma_heap_debug", &dma_heap_debug, 0); + + /* go through all heap first */ + for (i = 0; i < MPP_ARRAY_ELEMS(heap_infos); i++) { + info = &heap_infos[i]; + + if (info->fd > 0) + continue; + + info->fd = try_open_path(info->name); + if (info->fd <= 0) + all_success = 0; + } + + if (!all_success) { + /* check remaining failed heap mapping */ + for (i = 0; i < MPP_ARRAY_ELEMS(heap_infos); i++) { + info = &heap_infos[i]; + + if (info->fd > 0) + continue; + + /* if original heap failed then try revert cacheable flag */ + if (MPP_OK == try_flip_flag((RK_U32)i, MPP_ALLOC_FLAG_CACHABLE)) + continue; + + /* if cacheable heap failed then try revert dma32 flag */ + if (MPP_OK == try_flip_flag((RK_U32)i, MPP_ALLOC_FLAG_DMA32)) + continue; + + /* if dma32 heap failed then try revert both cacheable and dma32 flag */ + if (MPP_OK == try_flip_flag((RK_U32)i, MPP_ALLOC_FLAG_CACHABLE | MPP_ALLOC_FLAG_DMA32)) + continue; + + dma_heap_dbg_chk("dma-heap type %x - %s remap failed\n", i, info->name); + } + } +} + +__attribute__ ((destructor)) +void dma_heap_deinit(void) +{ + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(heap_infos); i++) { + DmaHeapInfo *info = &heap_infos[i]; + + if (info->fd > 0) { + close(info->fd); + info->fd = -1; + } + } +} + +static int dma_heap_alloc(int fd, size_t len, RK_S32 *dmabuf_fd, RK_U32 flags) +{ + struct dma_heap_allocation_data data; + int ret; + + memset(&data, 0, sizeof(data)); + data.len = len; + data.fd_flags = O_RDWR | O_CLOEXEC; + data.heap_flags = 0; // heap_flags should be set to 0 + + ret = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data); + if (ret < 0) { + mpp_err("ioctl alloc failed for %s\n", strerror(errno)); + return ret; + } + + dma_heap_dbg_ioctl("ioctl alloc get fd %d\n", data.fd); + + *dmabuf_fd = data.fd; + + (void) flags; + return ret; +} + +static MPP_RET os_allocator_dma_heap_open(void **ctx, size_t alignment, MppAllocFlagType flags) +{ + allocator_ctx_dmaheap *p; + DmaHeapInfo *info = NULL; + RK_U32 type = 0; + + mpp_env_get_u32("dma_heap_debug", &dma_heap_debug, dma_heap_debug); + + if (NULL == ctx) { + mpp_err_f("does not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + *ctx = NULL; + + info = &heap_infos[flags]; + if (info->fd <= 0) { + mpp_err_f("open dma heap type %x %s failed!\n", type, info->name); + return MPP_ERR_UNKNOW; + } + + p = mpp_malloc(allocator_ctx_dmaheap, 1); + if (NULL == p) { + mpp_err_f("failed to allocate context\n"); + return MPP_ERR_MALLOC; + } else { + p->alignment = alignment; + p->flags = info->flags; + p->device = info->fd; + *ctx = p; + } + + dma_heap_dbg_ops("dev %d open heap type %x:%x\n", p->device, flags, info->flags); + + return MPP_OK; +} + +static MPP_RET os_allocator_dma_heap_alloc(void *ctx, MppBufferInfo *info) +{ + MPP_RET ret = MPP_OK; + allocator_ctx_dmaheap *p = NULL; + + if (NULL == ctx) { + mpp_err_f("does not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (allocator_ctx_dmaheap *)ctx; + + ret = dma_heap_alloc(p->device, info->size, (RK_S32 *)&info->fd, p->flags); + + dma_heap_dbg_ops("dev %d alloc %3d size %d\n", p->device, info->fd, info->size); + + if (ret) { + mpp_err_f("dma_heap_alloc failed ret %d\n", ret); + return ret; + } + + info->ptr = NULL; + return ret; +} + +static MPP_RET os_allocator_dma_heap_import(void *ctx, MppBufferInfo *data) +{ + allocator_ctx_dmaheap *p = (allocator_ctx_dmaheap *)ctx; + RK_S32 fd_ext = data->fd; + MPP_RET ret = MPP_OK; + + mpp_assert(fd_ext > 0); + + data->fd = mpp_dup(fd_ext); + data->ptr = NULL; + + dma_heap_dbg_ops("dev %d import %3d -> %3d\n", p->device, fd_ext, data->fd); + + mpp_assert(data->fd > 0); + + return ret; +} + +static MPP_RET os_allocator_dma_heap_free(void *ctx, MppBufferInfo *data) +{ + allocator_ctx_dmaheap *p = NULL; + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + mpp_err_f("does not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (allocator_ctx_dmaheap *)ctx; + + dma_heap_dbg_ops("dev %d free %3d size %d ptr %p\n", p->device, + data->fd, data->size, data->ptr); + + if (data->ptr) { + munmap(data->ptr, data->size); + data->ptr = NULL; + } + close(data->fd); + + return ret; +} + +static MPP_RET os_allocator_dma_heap_close(void *ctx) +{ + if (NULL == ctx) { + mpp_err("os_allocator_close doesn't accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + MPP_FREE(ctx); + + return MPP_OK; +} + +static MPP_RET os_allocator_dma_heap_mmap(void *ctx, MppBufferInfo *data) +{ + allocator_ctx_dmaheap *p; + MPP_RET ret = MPP_OK; + if (NULL == ctx) { + mpp_err("os_allocator_close do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + p = (allocator_ctx_dmaheap *)ctx; + + if (NULL == ctx) + return MPP_ERR_NULL_PTR; + + if (NULL == data->ptr) { + int flags = PROT_READ; + + if (fcntl(data->fd, F_GETFL) & O_RDWR) + flags |= PROT_WRITE; + + data->ptr = mmap(NULL, data->size, flags, MAP_SHARED, data->fd, 0); + if (data->ptr == MAP_FAILED) { + mpp_err("mmap failed: %s\n", strerror(errno)); + data->ptr = NULL; + return -errno; + } + + dma_heap_dbg_ops("dev %d mmap %3d ptr %p (%s)\n", p->device, + data->fd, data->ptr, + flags & PROT_WRITE ? "RDWR" : "RDONLY"); + } + + return ret; +} + +static MppAllocFlagType os_allocator_dma_heap_flags(void *ctx) +{ + allocator_ctx_dmaheap *p = (allocator_ctx_dmaheap *)ctx; + + return p ? (MppAllocFlagType)p->flags : MPP_ALLOC_FLAG_NONE; +} + +os_allocator allocator_dma_heap = { + .type = MPP_BUFFER_TYPE_DMA_HEAP, + .name = "dma_heap", + .open = os_allocator_dma_heap_open, + .close = os_allocator_dma_heap_close, + .alloc = os_allocator_dma_heap_alloc, + .free = os_allocator_dma_heap_free, + .import = os_allocator_dma_heap_import, + .release = os_allocator_dma_heap_free, + .mmap = os_allocator_dma_heap_mmap, + .flags = os_allocator_dma_heap_flags, +}; diff --git a/osal/allocator/allocator_dma_heap.h b/osal/allocator/allocator_dma_heap.h new file mode 100644 index 000000000..2b83fd508 --- /dev/null +++ b/osal/allocator/allocator_dma_heap.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#ifndef ALLOCATOR_DMA_HEAP_H +#define ALLOCATOR_DMA_HEAP_H + +#include "mpp_allocator_api.h" + +extern os_allocator allocator_dma_heap; + +#endif diff --git a/osal/allocator/allocator_drm.c b/osal/allocator/allocator_drm.c new file mode 100644 index 000000000..ef8371fa5 --- /dev/null +++ b/osal/allocator/allocator_drm.c @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2010 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_drm" + +#include +#include +#include +#include +#include + +#include +#include + +#include "os_mem.h" +#include "allocator_drm.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_runtime.h" + +#define DRM_FUNCTION (0x00000001) +#define DRM_DEVICE (0x00000002) +#define DRM_IOCTL (0x00000004) + +#define drm_dbg(flag, fmt, ...) mpp_dbg_f(drm_debug, flag, fmt, ## __VA_ARGS__) +#define drm_dbg_func(fmt, ...) drm_dbg(DRM_FUNCTION, fmt, ## __VA_ARGS__) +#define drm_dbg_dev(fmt, ...) drm_dbg(DRM_DEVICE, fmt, ## __VA_ARGS__) +#define drm_dbg_ioctl(fmt, ...) drm_dbg(DRM_IOCTL, fmt, ## __VA_ARGS__) + +static RK_U32 drm_debug = 0; + +/* memory type definitions. */ +enum drm_rockchip_gem_mem_type { + /* Physically Continuous memory. */ + ROCKCHIP_BO_CONTIG = 1 << 0, + /* cachable mapping. */ + ROCKCHIP_BO_CACHABLE = 1 << 1, + /* write-combine mapping. */ + ROCKCHIP_BO_WC = 1 << 2, + ROCKCHIP_BO_SECURE = 1 << 3, + /* keep kmap for cma buffer or alloc kmap for other type memory */ + ROCKCHIP_BO_ALLOC_KMAP = 1 << 4, + /* alloc page with gfp_dma32 */ + ROCKCHIP_BO_DMA32 = 1 << 5, + ROCKCHIP_BO_MASK = ROCKCHIP_BO_CONTIG | ROCKCHIP_BO_CACHABLE | + ROCKCHIP_BO_WC | ROCKCHIP_BO_SECURE | ROCKCHIP_BO_ALLOC_KMAP | + ROCKCHIP_BO_DMA32, +}; + +typedef struct { + RK_U32 alignment; + RK_S32 drm_device; + RK_U32 flags; +} allocator_ctx_drm; + +/* use renderD128 first to avoid GKI kernel permission issue */ +static const char *dev_drm[] = { + "/dev/dri/renderD128", + "/dev/dri/card0", +}; + +static RK_U32 to_rockchip_gem_mem_flag(RK_U32 flags) +{ + RK_U32 ret = 0; + + if (flags & MPP_ALLOC_FLAG_DMA32) + ret |= ROCKCHIP_BO_DMA32; + + if (flags & MPP_ALLOC_FLAG_CACHABLE) + ret |= ROCKCHIP_BO_CACHABLE; + + if (flags & MPP_ALLOC_FLAG_CMA) + ret |= ROCKCHIP_BO_CONTIG; + + return ret; +} + +static int drm_ioctl(int fd, int req, void *arg) +{ + int ret; + + do { + ret = ioctl(fd, req, arg); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + drm_dbg_ioctl("%x ret %d: %s\n", req, ret, strerror(errno)); + + return ret; +} + +static int drm_handle_to_fd(int fd, RK_U32 handle, int *map_fd, RK_U32 flags) +{ + int ret; + struct drm_prime_handle dph; + + memset(&dph, 0, sizeof(struct drm_prime_handle)); + dph.handle = handle; + dph.fd = -1; + dph.flags = flags; + + if (map_fd == NULL) + return -EINVAL; + + ret = drm_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph); + if (ret < 0) + return ret; + + *map_fd = dph.fd; + + drm_dbg_func("dev %d handle %d flags %x get fd %d\n", fd, handle, dph.flags, *map_fd); + + if (*map_fd < 0) { + mpp_err_f("map ioctl returned negative fd\n"); + return -EINVAL; + } + + return ret; +} + +static int drm_alloc(int fd, size_t len, size_t align, RK_U32 *handle, RK_U32 flags) +{ + int ret; + struct drm_mode_create_dumb dmcb; + + memset(&dmcb, 0, sizeof(struct drm_mode_create_dumb)); + dmcb.bpp = 8; + dmcb.width = (len + align - 1) & (~(align - 1)); + dmcb.height = 1; + dmcb.flags = to_rockchip_gem_mem_flag(flags); + + if (handle == NULL) + return -EINVAL; + + ret = drm_ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &dmcb); + if (ret < 0) + return ret; + + *handle = dmcb.handle; + drm_dbg_func("dev %d alloc aligned %d flags %x|%x handle %d size %lld\n", fd, + align, flags, dmcb.flags, dmcb.handle, dmcb.size); + + return ret; +} + +static int drm_free(int fd, RK_U32 handle) +{ + struct drm_mode_destroy_dumb data = { + .handle = handle, + }; + return drm_ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &data); +} + +static MPP_RET os_allocator_drm_open(void **ctx, size_t alignment, MppAllocFlagType flags) +{ + allocator_ctx_drm *p; + RK_S32 fd; + RK_S32 i; + + if (NULL == ctx) { + mpp_err_f("does not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + *ctx = NULL; + + mpp_env_get_u32("drm_debug", &drm_debug, 0); + + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dev_drm); i++) { + fd = open(dev_drm[i], O_RDWR | O_CLOEXEC); + if (fd > 0) + break; + } + + if (fd < 0) { + mpp_err_f("open all drm device failed.\n"); + mpp_err("Please check the following device path and access permission:\n"); + for (i = 0; i < (RK_S32)MPP_ARRAY_ELEMS(dev_drm); i++) + mpp_err("%s\n", dev_drm[i]); + return MPP_ERR_UNKNOW; + } else { + /* drop master by default to avoid becoming the drm master */ + drm_ioctl(fd, DRM_IOCTL_DROP_MASTER, 0); + } + + drm_dbg_dev("open drm dev fd %d flags %x\n", fd, flags); + + p = mpp_malloc(allocator_ctx_drm, 1); + if (NULL == p) { + close(fd); + mpp_err_f("failed to allocate context\n"); + return MPP_ERR_MALLOC; + } else { + /* + * default drm use cma, do nothing here + */ + p->alignment = alignment; + p->flags = flags; + p->drm_device = fd; + *ctx = p; + } + + return MPP_OK; +} + +static MPP_RET os_allocator_drm_alloc(void *ctx, MppBufferInfo *info) +{ + MPP_RET ret = MPP_OK; + allocator_ctx_drm *p = NULL; + + if (NULL == ctx) { + mpp_err_f("does not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (allocator_ctx_drm *)ctx; + + drm_dbg_func("dev %d alloc alignment %d size %d\n", p->drm_device, + p->alignment, info->size); + + ret = drm_alloc(p->drm_device, info->size, p->alignment, + (RK_U32 *)&info->hnd, p->flags); + if (ret) { + mpp_err_f("drm_alloc failed ret %d\n", ret); + return ret; + } + + ret = drm_handle_to_fd(p->drm_device, (RK_U32)((intptr_t)info->hnd), + &info->fd, DRM_CLOEXEC | DRM_RDWR); + + if (ret) { + mpp_err_f("handle_to_fd failed ret %d\n", ret); + return ret; + } + + drm_dbg_func("dev %d get handle %d with fd %d\n", p->drm_device, + (RK_U32)((intptr_t)info->hnd), info->fd); + + /* release handle to reduce iova usage */ + drm_free(p->drm_device, (RK_U32)((intptr_t)info->hnd)); + info->hnd = NULL; + info->ptr = NULL; + + return ret; +} + +static MPP_RET os_allocator_drm_import(void *ctx, MppBufferInfo *data) +{ + allocator_ctx_drm *p = (allocator_ctx_drm *)ctx; + RK_S32 fd_ext = data->fd; + MPP_RET ret = MPP_OK; + + drm_dbg_func("enter dev %d fd %d\n", p->drm_device, fd_ext); + + mpp_assert(fd_ext > 0); + + data->fd = mpp_dup(fd_ext); + data->ptr = NULL; + + if (data->fd <= 0) { + mpp_err_f(" fd dup return invalid fd %d\n", data->fd); + ret = MPP_NOK; + } + + drm_dbg_func("leave dev %d fd %d -> %d\n", p->drm_device, fd_ext, data->fd); + + return ret; +} + +static MPP_RET os_allocator_drm_free(void *ctx, MppBufferInfo *data) +{ + allocator_ctx_drm *p = NULL; + + if (NULL == ctx) { + mpp_err_f("does not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (allocator_ctx_drm *)ctx; + + drm_dbg_func("dev %d handle %p unmap %p fd %d size %d\n", p->drm_device, + data->hnd, data->ptr, data->fd, data->size); + + if (data->ptr) { + munmap(data->ptr, data->size); + data->ptr = NULL; + } + + if (data->fd > 0) { + close(data->fd); + data->fd = -1; + } else { + mpp_err_f("can not close invalid fd %d\n", data->fd); + } + + return MPP_OK; +} + +static MPP_RET os_allocator_drm_close(void *ctx) +{ + int ret; + allocator_ctx_drm *p; + + if (NULL == ctx) { + mpp_err("os_allocator_close doesn't accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = (allocator_ctx_drm *)ctx; + drm_dbg_func("dev %d", p->drm_device); + + ret = close(p->drm_device); + mpp_free(p); + if (ret < 0) + return (MPP_RET) - errno; + + return MPP_OK; +} + +static MPP_RET os_allocator_drm_mmap(void *ctx, MppBufferInfo *data) +{ + allocator_ctx_drm *p; + MPP_RET ret = MPP_OK; + if (NULL == ctx) { + mpp_err("os_allocator_close do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + p = (allocator_ctx_drm *)ctx; + + if (NULL == ctx) + return MPP_ERR_NULL_PTR; + + if (NULL == data->ptr) { + int flags = PROT_READ; + + if (fcntl(data->fd, F_GETFL) & O_RDWR) + flags |= PROT_WRITE; + + data->ptr = mmap(NULL, data->size, flags, MAP_SHARED, data->fd, 0); + if (data->ptr == MAP_FAILED) { + mpp_err("mmap failed: %s\n", strerror(errno)); + data->ptr = NULL; + return -errno; + } + + drm_dbg_func("dev %d mmap fd %d to %p (%s)\n", p->drm_device, + data->fd, data->ptr, + flags & PROT_WRITE ? "RDWR" : "RDONLY"); + } + + return ret; +} + +static MppAllocFlagType os_allocator_drm_flags(void *ctx) +{ + allocator_ctx_drm *p = (allocator_ctx_drm *)ctx; + + return p ? (MppAllocFlagType)p->flags : MPP_ALLOC_FLAG_NONE; +} + +os_allocator allocator_drm = { + .type = MPP_BUFFER_TYPE_DRM, + .name = "drm", + .open = os_allocator_drm_open, + .close = os_allocator_drm_close, + .alloc = os_allocator_drm_alloc, + .free = os_allocator_drm_free, + .import = os_allocator_drm_import, + .release = os_allocator_drm_free, + .mmap = os_allocator_drm_mmap, + .flags = os_allocator_drm_flags, +}; diff --git a/osal/allocator/allocator_drm.h b/osal/allocator/allocator_drm.h new file mode 100644 index 000000000..86c5bb94e --- /dev/null +++ b/osal/allocator/allocator_drm.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2010 Rockchip Electronics Co., Ltd. + */ + +#ifndef ALLOCATOR_DRM_H +#define ALLOCATOR_DRM_H + +#include "mpp_allocator_api.h" + +extern os_allocator allocator_drm; + +#endif diff --git a/osal/allocator/allocator_ext_dma.c b/osal/allocator/allocator_ext_dma.c new file mode 100644 index 000000000..8fca79cb5 --- /dev/null +++ b/osal/allocator/allocator_ext_dma.c @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2018 Rockchip Electronics Co., Ltd. + */ + +#include +#include + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "allocator_ext_dma.h" + +typedef struct { + size_t alignment; + MppAllocFlagType flags; +} allocator_ctx; + +static MPP_RET allocator_ext_dma_open(void **ctx, size_t alignment, MppAllocFlagType flags) +{ + MPP_RET ret = MPP_OK; + allocator_ctx *p = NULL; + + if (NULL == ctx) { + mpp_err_f("do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + p = mpp_malloc(allocator_ctx, 1); + if (NULL == p) { + mpp_err_f("failed to allocate context\n"); + ret = MPP_ERR_MALLOC; + } else { + p->alignment = alignment; + p->flags = flags; + } + + *ctx = p; + return ret; +} + +static MPP_RET allocator_ext_dma_alloc(void *ctx, MppBufferInfo *info) +{ + if (!ctx || !info) { + mpp_err_f("found NULL context input\n"); + return MPP_ERR_VALUE; + } + + return MPP_ERR_PERM; +} + +static MPP_RET allocator_ext_dma_free(void *ctx, MppBufferInfo *info) +{ + if (!ctx || !info) { + mpp_err_f("found NULL context input\n"); + return MPP_ERR_VALUE; + } + + return MPP_ERR_PERM; +} + +static MPP_RET allocator_ext_dma_import(void *ctx, MppBufferInfo *info) +{ + allocator_ctx *p = (allocator_ctx *)ctx; + mpp_assert(p); + mpp_assert(info->size); + + if (info->ptr) { + mpp_err_f("The ext_dma is not used for userptr\n"); + return MPP_ERR_VALUE; + } + + return ((info->fd < 0) ? MPP_ERR_VALUE : MPP_OK); +} + +static MPP_RET allocator_ext_dma_mmap(void *ctx, MppBufferInfo *info) +{ + void *ptr = NULL; + int flags = 0; + unsigned long offset = 0L; + mpp_assert(ctx); + mpp_assert(info->size); + mpp_assert(info->fd >= 0); + + if (info->ptr) + return MPP_OK; + + /* + * It is insecure to access the first memory page, + * usually system doesn't allow this behavior. + */ + flags = PROT_READ; + if (fcntl(info->fd, F_GETFL) & O_RDWR) + flags |= PROT_WRITE; + + ptr = mmap(NULL, info->size, flags, MAP_SHARED, info->fd, offset); + if (ptr == MAP_FAILED) + return MPP_ERR_NULL_PTR; + + info->ptr = ptr; + + return MPP_OK; +} + +static MPP_RET allocator_ext_dma_release(void *ctx, MppBufferInfo *info) +{ + mpp_assert(ctx); + mpp_assert(info->size); + + if (info->ptr) + munmap(info->ptr, info->size); + + info->ptr = NULL; + info->hnd = NULL; + info->fd = -1; + info->size = 0; + + return MPP_OK; +} + +static MPP_RET allocator_ext_dma_close(void *ctx) +{ + if (ctx) { + mpp_free(ctx); + return MPP_OK; + } + + mpp_err_f("found NULL context input\n"); + return MPP_ERR_VALUE; +} + +static MppAllocFlagType os_allocator_ext_dma_flags(void *ctx) +{ + allocator_ctx *p = (allocator_ctx *)ctx; + + return p ? (MppAllocFlagType)p->flags : MPP_ALLOC_FLAG_NONE; +} + +os_allocator allocator_ext_dma = { + .type = MPP_BUFFER_TYPE_EXT_DMA, + .name = "ext_dma", + .open = allocator_ext_dma_open, + .close = allocator_ext_dma_close, + .alloc = allocator_ext_dma_alloc, + .free = allocator_ext_dma_free, + .import = allocator_ext_dma_import, + .release = allocator_ext_dma_release, + .mmap = allocator_ext_dma_mmap, + .flags = os_allocator_ext_dma_flags, +}; diff --git a/osal/allocator/allocator_ext_dma.h b/osal/allocator/allocator_ext_dma.h new file mode 100644 index 000000000..8ddf71531 --- /dev/null +++ b/osal/allocator/allocator_ext_dma.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2018 Rockchip Electronics Co., Ltd. + */ + +#ifndef ALLOCATOR_EXT_DMA_H +#define ALLOCATOR_EXT_DMA_H + +#include "mpp_allocator_api.h" + +extern os_allocator allocator_ext_dma; + +#endif diff --git a/osal/allocator/allocator_ion.c b/osal/allocator/allocator_ion.c new file mode 100644 index 000000000..c6fc02b8c --- /dev/null +++ b/osal/allocator/allocator_ion.c @@ -0,0 +1,492 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_ion" + +#include +#include +#include +#include +#include + +#if defined(ARMLINUX) +#include +#else +#include "ion.h" +#endif + +#include "os_mem.h" +#include "allocator_ion.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" + +static RK_U32 ion_debug = 0; +static pthread_once_t once = PTHREAD_ONCE_INIT; +static pthread_mutex_t scandir_lock; + +#define ION_FUNCTION (0x00000001) +#define ION_DEVICE (0x00000002) +#define ION_CLINET (0x00000004) +#define ION_IOCTL (0x00000008) + +#define ION_DETECT_IOMMU_DISABLE (0x0) /* use ION_HEAP_TYPE_DMA */ +#define ION_DETECT_IOMMU_ENABLE (0x1) /* use ION_HEAP_TYPE_SYSTEM */ +#define ION_DETECT_NO_DTS (0x2) /* use ION_HEAP_TYPE_CARVEOUT */ + +#define ion_dbg(flag, fmt, ...) mpp_dbg(ion_debug, flag, fmt, ## __VA_ARGS__) +#define ion_dbg_f(flag, fmt, ...) mpp_dbg_f(ion_debug, flag, fmt, ## __VA_ARGS__) +#define ion_dbg_func(fmt, ...) ion_dbg_f(ION_FUNCTION, fmt, ## __VA_ARGS__) + +static int ion_ioctl(int fd, int req, void *arg) +{ + int ret = ioctl(fd, req, arg); + if (ret < 0) { + mpp_err("ion_ioctl %x failed with code %d: %s\n", req, + ret, strerror(errno)); + return -errno; + } + return ret; +} + +static int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, + unsigned int flags, ion_user_handle_t *handle) +{ + int ret = -EINVAL; + struct ion_allocation_data data = { + .len = len, + .align = align, + .heap_id_mask = heap_mask, + .flags = flags, + }; + + ion_dbg_func("enter: fd %d len %d align %d heap_mask %x flags %x", + fd, len, align, heap_mask, flags); + + if (handle) { + ret = ion_ioctl(fd, ION_IOC_ALLOC, &data); + if (ret >= 0) + *handle = data.handle; + } + + ion_dbg_func("leave: ret %d\n", ret); + + return ret; +} + +static int ion_free(int fd, ion_user_handle_t handle) +{ + int ret; + struct ion_handle_data data = { + .handle = handle, + }; + + ion_dbg_func("enter: fd %d\n", fd); + ret = ion_ioctl(fd, ION_IOC_FREE, &data); + ion_dbg_func("leave: ret %d\n", ret); + return ret; +} + +static int ion_map_fd(int fd, ion_user_handle_t handle, int *map_fd) +{ + int ret; + struct ion_fd_data data = { + .handle = handle, + }; + + if (map_fd == NULL) + return -EINVAL; + + ret = ion_ioctl(fd, ION_IOC_MAP, &data); + if (ret < 0) + return ret; + + *map_fd = data.fd; + if (*map_fd < 0) { + mpp_err("map ioctl returned negative fd\n"); + return -EINVAL; + } + + return 0; +} + +static int ion_mmap(int fd, size_t length, int prot, int flags, off_t offset, + void **ptr) +{ + static unsigned long pagesize_mask = 0; + if (ptr == NULL) + return -EINVAL; + + if (!pagesize_mask) + pagesize_mask = sysconf(_SC_PAGESIZE) - 1; + offset = offset & (~pagesize_mask); + + *ptr = mmap(NULL, length, prot, flags, fd, offset); + if (*ptr == MAP_FAILED) { + mpp_err("mmap failed: %s\n", strerror(errno)); + *ptr = NULL; + return -errno; + } + return 0; +} + +#include + +static const char *search_name = NULL; + +static int _compare_name(const struct dirent *dir) +{ + if (search_name && strstr(dir->d_name, search_name)) + return 1; + + return 0; +} + +static void scandir_lock_init(void) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&scandir_lock, &attr); + pthread_mutexattr_destroy(&attr); +} + +/* + * directory search function: + * search directory with dir_name on path. + * if found match dir append name on path and return + * + * return 0 for failure + * return positive value for length of new path + */ +static RK_S32 find_dir_in_path(char *path, const char *dir_name, + size_t max_length) +{ + struct dirent **dir; + RK_S32 path_len = strnlen(path, max_length); + RK_S32 new_path_len = 0; + RK_S32 n; + + pthread_once(&once, scandir_lock_init); + pthread_mutex_lock(&scandir_lock); + search_name = dir_name; + n = scandir(path, &dir, _compare_name, alphasort); + if (n <= 0) { + mpp_log("scan %s for %s return %d\n", path, dir_name, n); + } else { + mpp_assert(n == 1); + + new_path_len = path_len; + new_path_len += snprintf(path + path_len, max_length - path_len - 1, + "/%s", dir[0]->d_name); + free(dir[0]); + free(dir); + } + search_name = NULL; + pthread_mutex_unlock(&scandir_lock); + return new_path_len; +} + +#define MAX_PATH_NAME_SIZE 256 + +static RK_S32 check_sysfs_iommu() +{ + RK_U32 i = 0; + RK_U32 dts_info_found = 0; + RK_U32 ion_info_found = 0; + RK_S32 ret = ION_DETECT_IOMMU_DISABLE; + char path[MAX_PATH_NAME_SIZE]; + static char *dts_devices[] = { + "vpu_service", + "hevc_service", + "rkvdec", + "rkvenc", + "vpu_combo", + }; + static char *system_heaps[] = { + "vmalloc", + "system-heap", + }; + + mpp_env_get_u32("ion_debug", &ion_debug, 0); +#ifdef SOFIA_3GR_LINUX + return ret; +#endif + + for (i = 0; i < MPP_ARRAY_ELEMS(dts_devices); i++) { + snprintf(path, sizeof(path), "/proc/device-tree"); + if (find_dir_in_path(path, dts_devices[i], sizeof(path))) { + if (find_dir_in_path(path, "iommu_enabled", sizeof(path))) { + FILE *iommu_fp = fopen(path, "rb"); + + if (iommu_fp) { + RK_U32 iommu_enabled = 0; + if (fread(&iommu_enabled, sizeof(RK_U32), 1, iommu_fp)) + mpp_log("%s iommu_enabled %d\n", dts_devices[i], + (iommu_enabled > 0)); + fclose(iommu_fp); + if (iommu_enabled) + ret = ION_DETECT_IOMMU_ENABLE; + } + dts_info_found = 1; + break; + } + } + } + + if (!dts_info_found) { + for (i = 0; i < MPP_ARRAY_ELEMS(system_heaps); i++) { + snprintf(path, sizeof(path), "/sys/kernel/debug/ion/heaps"); + if (find_dir_in_path(path, system_heaps[i], sizeof(path))) { + mpp_log("%s found\n", system_heaps[i]); + ret = ION_DETECT_IOMMU_ENABLE; + ion_info_found = 1; + break; + } + } + } + + if (!dts_info_found && !ion_info_found) { + mpp_err("can not find any hint from all possible devices\n"); + ret = ION_DETECT_NO_DTS; + } + + return ret; +} + +typedef struct { + size_t alignment; + RK_S32 ion_device; + MppAllocFlagType flags; +} allocator_ctx_ion; + +static const char *dev_ion = "/dev/ion"; +static RK_S32 ion_heap_id = -1; +static RK_U32 ion_heap_mask = (1 << ION_HEAP_TYPE_SYSTEM); +static pthread_mutex_t lock; + +static MPP_RET allocator_ion_open(void **ctx, size_t alignment, MppAllocFlagType flags) +{ + RK_S32 fd; + allocator_ctx_ion *p; + + if (NULL == ctx) { + mpp_err("os_allocator_open Android do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + *ctx = NULL; + + fd = open(dev_ion, O_RDWR | O_CLOEXEC); + if (fd < 0) { + mpp_err("open %s failed!\n", dev_ion); + return MPP_ERR_UNKNOW; + } + + ion_dbg(ION_DEVICE, "open ion dev fd %d\n", fd); + + p = mpp_malloc(allocator_ctx_ion, 1); + if (NULL == p) { + close(fd); + mpp_err("os_allocator_open Android failed to allocate context\n"); + return MPP_ERR_MALLOC; + } else { + /* + * do heap id detection here: + * if there is no vpu_service use default ION_HEAP_TYPE_SYSTEM_CONTIG + * if there is vpu_service then check the iommu_enable status + */ + pthread_mutex_lock(&lock); + if (ion_heap_id < 0) { + int detect_result = check_sysfs_iommu(); + const char *heap_name = NULL; + + switch (detect_result) { + case ION_DETECT_IOMMU_DISABLE : { + ion_heap_mask = (1 << ION_HEAP_TYPE_DMA); + ion_heap_id = ION_HEAP_TYPE_DMA; + heap_name = "ION_HEAP_TYPE_DMA"; + } break; + case ION_DETECT_IOMMU_ENABLE : { + ion_heap_mask = (1 << ION_HEAP_TYPE_SYSTEM); + ion_heap_id = ION_HEAP_TYPE_SYSTEM; + heap_name = "ION_HEAP_TYPE_SYSTEM"; + } break; + case ION_DETECT_NO_DTS : { + ion_heap_mask = (1 << ION_HEAP_TYPE_CARVEOUT); + ion_heap_id = ION_HEAP_TYPE_CARVEOUT; + heap_name = "ION_HEAP_TYPE_CARVEOUT"; + } break; + default : { + mpp_err("invalid detect result %d\n", detect_result); + ion_heap_mask = (1 << ION_HEAP_TYPE_DMA); + ion_heap_id = ION_HEAP_TYPE_DMA; + heap_name = "ION_HEAP_TYPE_DMA"; + } break; + } + mpp_log("using ion heap %s\n", heap_name); + } + pthread_mutex_unlock(&lock); + p->alignment = alignment; + p->flags = flags; + p->ion_device = fd; + *ctx = p; + } + + return MPP_OK; +} + +static MPP_RET allocator_ion_alloc(void *ctx, MppBufferInfo *info) +{ + MPP_RET ret = MPP_OK; + int fd = -1; + ion_user_handle_t hnd = -1; + allocator_ctx_ion *p = NULL; + + if (NULL == ctx) { + mpp_err("os_allocator_close Android do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + ion_dbg_func("enter: ctx %p size %d\n", ctx, info->size); + + p = (allocator_ctx_ion *)ctx; + ret = ion_alloc(p->ion_device, info->size, p->alignment, ion_heap_mask, + 0, &hnd); + if (ret) + mpp_err_f("ion_alloc failed ret %d\n", ret); + else { + ret = ion_map_fd(p->ion_device, hnd, &fd); + if (ret) + mpp_err_f("ion_map_fd failed ret %d\n", ret); + } + + info->fd = fd; + info->ptr = NULL; + info->hnd = (void *)(intptr_t)hnd; + + ion_dbg_func("leave: ret %d handle %d fd %d\n", ret, hnd, fd); + return ret; +} + +static MPP_RET allocator_ion_import(void *ctx, MppBufferInfo *data) +{ + MPP_RET ret = MPP_NOK; + allocator_ctx_ion *p = (allocator_ctx_ion *)ctx; + struct ion_fd_data fd_data; + + ion_dbg_func("enter: ctx %p dev %d fd %d size %d\n", + ctx, p->ion_device, data->fd, data->size); + + fd_data.fd = data->fd; + ret = ion_ioctl(p->ion_device, ION_IOC_IMPORT, &fd_data); + if (0 > fd_data.handle) { + mpp_err_f("fd %d import failed for %s\n", data->fd, strerror(errno)); + goto RET; + } + + data->hnd = (void *)(intptr_t)fd_data.handle; + ret = ion_map_fd(p->ion_device, fd_data.handle, &data->fd); + data->ptr = NULL; +RET: + ion_dbg_func("leave: ret %d handle %d\n", ret, data->hnd); + return ret; +} + +static MPP_RET allocator_ion_mmap(void *ctx, MppBufferInfo *data) +{ + MPP_RET ret = MPP_OK; + + if (NULL == ctx) { + mpp_err_f("do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + ion_dbg_func("enter: ctx %p fd %d size %d\n", ctx, data->fd, data->size); + + if (NULL == data->ptr) + ret = ion_mmap(data->fd, data->size, PROT_READ | PROT_WRITE, + MAP_SHARED, 0, &data->ptr); + + ion_dbg_func("leave: ret %d ptr %p\n", ret, data->ptr); + return ret; +} + +static MPP_RET allocator_ion_free(void *ctx, MppBufferInfo *data) +{ + allocator_ctx_ion *p = NULL; + if (NULL == ctx) { + mpp_err_f("do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + ion_dbg_func("enter: ctx %p fd %d ptr %p size %d\n", + ctx, data->fd, data->ptr, data->size); + + p = (allocator_ctx_ion *)ctx; + if (data->ptr) { + munmap(data->ptr, data->size); + data->ptr = NULL; + } + + if (data->fd > 0) { + close(data->fd); + data->fd = -1; + } + + if (data->hnd) { + ion_free(p->ion_device, (ion_user_handle_t)((intptr_t)data->hnd)); + data->hnd = NULL; + } + + ion_dbg_func("leave\n"); + return MPP_OK; +} + +static MPP_RET allocator_ion_close(void *ctx) +{ + int ret; + allocator_ctx_ion *p; + + if (NULL == ctx) { + mpp_err("os_allocator_close Android do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + ion_dbg_func("enter: ctx\n", ctx); + + p = (allocator_ctx_ion *)ctx; + ret = close(p->ion_device); + mpp_free(p); + if (ret < 0) + ret = (MPP_RET) - errno; + + ion_dbg_func("leave: ret %d\n", ret); + + return ret; +} + +static MppAllocFlagType os_allocator_ion_flags(void *ctx) +{ + allocator_ctx_ion *p = (allocator_ctx_ion *)ctx; + + return p ? p->flags : MPP_ALLOC_FLAG_NONE; +} + +os_allocator allocator_ion = { + .type = MPP_BUFFER_TYPE_ION, + .name = "ion", + .open = allocator_ion_open, + .close = allocator_ion_close, + .alloc = allocator_ion_alloc, + .free = allocator_ion_free, + .import = allocator_ion_import, + .release = allocator_ion_free, + .mmap = allocator_ion_mmap, + .flags = os_allocator_ion_flags, +}; diff --git a/osal/allocator/allocator_ion.h b/osal/allocator/allocator_ion.h new file mode 100644 index 000000000..147dede63 --- /dev/null +++ b/osal/allocator/allocator_ion.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef ALLOCATOR_ION_H +#define ALLOCATOR_ION_H + +#include "mpp_allocator_api.h" + +extern os_allocator allocator_ion; + +#endif diff --git a/osal/allocator/allocator_std.c b/osal/allocator/allocator_std.c new file mode 100644 index 000000000..fe4b17097 --- /dev/null +++ b/osal/allocator/allocator_std.c @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#include + +#include "os_mem.h" +#include "mpp_mem.h" +#include "mpp_debug.h" + +#include "allocator_std.h" + +typedef struct { + size_t alignment; + MppAllocFlagType flags; + RK_S32 fd_count; +} allocator_ctx; + +static MPP_RET allocator_std_open(void **ctx, size_t alignment, MppAllocFlagType flags) +{ + allocator_ctx *p = NULL; + + if (NULL == ctx) { + mpp_err_f("do not accept NULL input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_err_f("Warning: std allocator should be used on simulation mode only\n"); + + p = mpp_malloc(allocator_ctx, 1); + if (p) { + p->alignment = alignment; + p->flags = flags; + p->fd_count = 0; + } + + *ctx = p; + return p ? MPP_OK : MPP_NOK; +} + +static MPP_RET allocator_std_alloc(void *ctx, MppBufferInfo *info) +{ + if (NULL == ctx) { + mpp_err_f("found NULL context input\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_err_f("Warning: std allocator should be used on simulation mode only\n"); + (void)info; + + return MPP_NOK; +} + +static MPP_RET allocator_std_free(void *ctx, MppBufferInfo *info) +{ + (void) ctx; + if (info->ptr) + os_free(info->ptr); + return MPP_OK; +} + +static MPP_RET allocator_std_import(void *ctx, MppBufferInfo *info) +{ + allocator_ctx *p = (allocator_ctx *)ctx; + mpp_assert(ctx); + mpp_assert(info->ptr); + mpp_assert(info->size); + info->hnd = NULL; + info->fd = p->fd_count++; + return MPP_OK; +} + +static MPP_RET allocator_std_release(void *ctx, MppBufferInfo *info) +{ + (void) ctx; + mpp_assert(info->ptr); + mpp_assert(info->size); + info->ptr = NULL; + info->size = 0; + info->hnd = NULL; + info->fd = -1; + return MPP_OK; +} + +static MPP_RET allocator_std_mmap(void *ctx, MppBufferInfo *info) +{ + mpp_assert(ctx); + mpp_assert(info->ptr); + mpp_assert(info->size); + return MPP_OK; +} + +static MPP_RET allocator_std_close(void *ctx) +{ + MPP_FREE(ctx); + return MPP_OK; +} + +static MppAllocFlagType os_allocator_std_flags(void *ctx) +{ + (void) ctx; + return MPP_ALLOC_FLAG_NONE; +} + +os_allocator allocator_std = { + .type = MPP_BUFFER_TYPE_NORMAL, + .name = "std", + .open = allocator_std_open, + .close = allocator_std_close, + .alloc = allocator_std_alloc, + .free = allocator_std_free, + .import = allocator_std_import, + .release = allocator_std_release, + .mmap = allocator_std_mmap, + .flags = os_allocator_std_flags, +}; diff --git a/osal/allocator/allocator_std.h b/osal/allocator/allocator_std.h new file mode 100644 index 000000000..3d56d84e6 --- /dev/null +++ b/osal/allocator/allocator_std.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef ALLOCATOR_STD_H +#define ALLOCATOR_STD_H + +#include "mpp_allocator_api.h" + +extern os_allocator allocator_std; + +#endif diff --git a/osal/allocator/ion.h b/osal/allocator/ion.h new file mode 100644 index 000000000..572b25590 --- /dev/null +++ b/osal/allocator/ion.h @@ -0,0 +1,488 @@ +/* + * include/linux/ion.h + * + * Copyright (C) 2011 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef LINUX_ION_H +#define LINUX_ION_H + +#include +#define ION_VERSION "1.0" + +typedef int ion_user_handle_t; + +/** + * enum ion_heap_types - list of all possible types of heaps + * @ION_HEAP_TYPE_SYSTEM: memory allocated via vmalloc + * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc + * @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved + * carveout heap, allocations are physically + * contiguous + * @ION_HEAP_TYPE_DMA: memory allocated via DMA API + * @ION_NUM_HEAPS: helper for iterating over heaps, a bit mask + * is used to identify the heaps, so only 32 + * total heap types are supported + */ +enum ion_heap_type { + ION_HEAP_TYPE_SYSTEM, + ION_HEAP_TYPE_SYSTEM_CONTIG, + ION_HEAP_TYPE_CARVEOUT, + ION_HEAP_TYPE_CHUNK, + ION_HEAP_TYPE_DMA, + ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always + are at the end of this enum */ + ION_NUM_HEAPS = 16, +}; +enum ion_heap_ids { + ION_NOR_HEAP_ID = 0, + ION_CMA_HEAP_ID = 1, + + ION_VPU_ID = 16, + ION_CAM_ID = 17, + ION_UI_ID = 18, +}; + +#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM) +#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG) +#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT) +#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA) + +#ifdef __KERNEL__ +struct ion_device; +struct ion_heap; +struct ion_mapper; +struct ion_client; +struct ion_buffer; + +/* This should be removed some day when phys_addr_t's are fully + plumbed in the kernel, and all instances of ion_phys_addr_t should + be converted to phys_addr_t. For the time being many kernel interfaces + do not accept phys_addr_t's that would have to */ +#define ion_phys_addr_t unsigned long + +/** + * struct ion_platform_heap - defines a heap in the given platform + * @type: type of the heap from ion_heap_type enum + * @id: unique identifier for heap. When allocating (lower numbers + * will be allocated from first) + * @name: used for debug purposes + * @base: base address of heap in physical memory if applicable + * @size: size of the heap in bytes if applicable + * + * Provided by the board file. + */ +struct ion_platform_heap { + enum ion_heap_type type; + unsigned int id; + const char *name; + ion_phys_addr_t base; + size_t size; +}; + +/** + * struct ion_platform_data - array of platform heaps passed from board file + * @nr: number of structures in the array + * @heaps: array of platform_heap structions + * + * Provided by the board file in the form of platform data to a platform device. + */ +struct ion_platform_data { + int nr; + struct ion_platform_heap heaps[]; +}; + +/** + * ion_client_create() - allocate a client and returns it + * @dev: the global ion device + * @heap_mask: mask of heaps this client can allocate from + * @name: used for debugging + */ +struct ion_client *ion_client_create(struct ion_device *dev, + unsigned int heap_mask, const char *name); + +/** + * ion_client_destroy() - free's a client and all it's handles + * @client: the client + * + * Free the provided client and all it's resources including + * any handles it is holding. + */ +void ion_client_destroy(struct ion_client *client); + +/** + * ion_alloc - allocate ion memory + * @client: the client + * @len: size of the allocation + * @align: requested allocation alignment, lots of hardware blocks have + * alignment requirements of some kind + * @flags: mask of heaps to allocate from, if multiple bits are set + * heaps will be tried in order from lowest to highest order bit + * + * Allocate memory in one of the heaps provided in heap mask and return + * an opaque handle to it. + */ +struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + size_t align, unsigned int flags); + +/** + * ion_free - free a handle + * @client: the client + * @handle: the handle to free + * + * Free the provided handle. + */ +void ion_free(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_phys - returns the physical address and len of a handle + * @client: the client + * @handle: the handle + * @addr: a pointer to put the address in + * @len: a pointer to put the length in + * + * This function queries the heap for a particular handle to get the + * handle's physical address. It't output is only correct if + * a heap returns physically contiguous memory -- in other cases + * this api should not be implemented -- ion_map_dma should be used + * instead. Returns -EINVAL if the handle is invalid. This has + * no implications on the reference counting of the handle -- + * the returned value may not be valid if the caller is not + * holding a reference. + */ +int ion_phys(struct ion_client *client, struct ion_handle *handle, + ion_phys_addr_t *addr, size_t *len); + +/** + * ion_map_kernel - create mapping for the given handle + * @client: the client + * @handle: handle to map + * + * Map the given handle into the kernel and return a kernel address that + * can be used to access this address. + */ +void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_unmap_kernel() - destroy a kernel mapping for a handle + * @client: the client + * @handle: handle to unmap + */ +void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_map_dma - create a dma mapping for a given handle + * @client: the client + * @handle: handle to map + * + * Return an sglist describing the given handle + */ +struct scatterlist *ion_map_dma(struct ion_client *client, + struct ion_handle *handle); + +/** + * ion_unmap_dma() - destroy a dma mapping for a handle + * @client: the client + * @handle: handle to unmap + */ +void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle); + +/** + * ion_share() - given a handle, obtain a buffer to pass to other clients + * @client: the client + * @handle: the handle to share + * + * Given a handle, return a buffer, which exists in a global name + * space, and can be passed to other clients. Should be passed into ion_import + * to obtain a new handle for this buffer. + * + * NOTE: This function does do not an extra reference. The burden is on the + * caller to make sure the buffer doesn't go away while it's being passed to + * another client. That is, ion_free should not be called on this handle until + * the buffer has been imported into the other client. + */ +struct ion_buffer *ion_share(struct ion_client *client, + struct ion_handle *handle); + +/** + * ion_import() - given an buffer in another client, import it + * @client: this blocks client + * @buffer: the buffer to import (as obtained from ion_share) + * + * Given a buffer, add it to the client and return the handle to use to refer + * to it further. This is called to share a handle from one kernel client to + * another. + */ +struct ion_handle *ion_import(struct ion_client *client, + struct ion_buffer *buffer); + +/** + * ion_import_fd() - given an fd obtained via ION_IOC_SHARE ioctl, import it + * @client: this blocks client + * @fd: the fd + * + * A helper function for drivers that will be recieving ion buffers shared + * with them from userspace. These buffers are represented by a file + * descriptor obtained as the return from the ION_IOC_SHARE ioctl. + * This function coverts that fd into the underlying buffer, and returns + * the handle to use to refer to it further. + */ +struct ion_handle *ion_import_fd(struct ion_client *client, int fd); +#endif /* __KERNEL__ */ + +/** + * DOC: Ion Userspace API + * + * create a client by opening /dev/ion + * most operations handled via following ioctls + * + */ + +/** + * struct ion_allocation_data - metadata passed from userspace for allocations + * @len: size of the allocation + * @align: required alignment of the allocation + * @flags: flags passed to heap + * @handle: pointer that will be populated with a cookie to use to refer + * to this allocation + * + * Provided by userspace as an argument to the ioctl + */ +struct ion_allocation_data { + size_t len; + size_t align; + unsigned int heap_id_mask; + unsigned int flags; + ion_user_handle_t handle; +}; + +/** + * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair + * @handle: a handle + * @fd: a file descriptor representing that handle + * + * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with + * the handle returned from ion alloc, and the kernel returns the file + * descriptor to share or map in the fd field. For ION_IOC_IMPORT, userspace + * provides the file descriptor and the kernel returns the handle. + */ +struct ion_fd_data { + ion_user_handle_t handle; + int fd; +}; + +/** + * struct ion_handle_data - a handle passed to/from the kernel + * @handle: a handle + */ +struct ion_handle_data { + ion_user_handle_t handle; +}; + +/** + * struct ion_custom_data - metadata passed to/from userspace for a custom ioctl + * @cmd: the custom ioctl function to call + * @arg: additional data to pass to the custom ioctl, typically a user + * pointer to a predefined structure + * + * This works just like the regular cmd and arg fields of an ioctl. + */ +struct ion_custom_data { + unsigned int cmd; + unsigned long arg; +}; + +/* struct ion_flush_data - data passed to ion for flushing caches + * + * @handle: handle with data to flush + * @fd: fd to flush + * @vaddr: userspace virtual address mapped with mmap + * @offset: offset into the handle to flush + * @length: length of handle to flush + * + * Performs cache operations on the handle. If p is the start address + * of the handle, p + offset through p + offset + length will have + * the cache operations performed + */ +struct ion_flush_data { + //struct ion_handle *handle; + ion_user_handle_t handle; + int fd; + void *vaddr; + unsigned int offset; + unsigned int length; +}; + +/// no available in new ion-kernel +struct ion_phys_data { + //struct ion_handle *handle; + ion_user_handle_t handle; + unsigned long phys; + unsigned long size; +}; + +struct ion_cacheop_data { +#define ION_CACHE_FLUSH 0 +#define ION_CACHE_CLEAN 1 +#define ION_CACHE_INV 2 + unsigned int type; + struct ion_handle *handle; + void *virt; +}; +struct ion_buffer_info { + unsigned long phys; + unsigned long size; +}; +struct ion_client_info { +#define MAX_BUFFER_COUNT 127 + unsigned int count; + unsigned long total_size; + struct ion_buffer_info buf[MAX_BUFFER_COUNT]; +}; +struct ion_heap_info { + unsigned int id; + unsigned long allocated_size; + unsigned long max_allocated; + unsigned long total_size; +}; + +struct ion_share_obj_data { + int fd; + void *obj; +}; +/////////////////////////////////////////////////// + +#define ION_IOC_MAGIC 'I' + +/** + * DOC: ION_IOC_ALLOC - allocate memory + * + * Takes an ion_allocation_data struct and returns it with the handle field + * populated with the opaque handle for the allocation. + */ +#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ + struct ion_allocation_data) + +/** + * DOC: ION_IOC_FREE - free memory + * + * Takes an ion_handle_data struct and frees the handle. + */ +#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) + +/** + * DOC: ION_IOC_MAP - get a file descriptor to mmap + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be used as an argument to mmap. + */ +#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data) + +/** + * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation + * + * Takes an ion_fd_data struct with the handle field populated with a valid + * opaque handle. Returns the struct with the fd field set to a file + * descriptor open in the current address space. This file descriptor + * can then be passed to another process. The corresponding opaque handle can + * be retrieved via ION_IOC_IMPORT. + */ +#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data) + +/** + * DOC: ION_IOC_IMPORT - imports a shared file descriptor + * + * Takes an ion_fd_data struct with the fd field populated with a valid file + * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle + * filed set to the corresponding opaque handle. + */ +#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data) + +/** + * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory + * + * Deprecated in favor of using the dma_buf api's correctly (syncing + * will happend automatically when the buffer is mapped to a device). + * If necessary should be used after touching a cached buffer from the cpu, + * this will make the buffer in memory coherent. + */ +#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data) + +/** + * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl + * + * Takes the argument of the architecture specific ioctl to call and + * passes appropriate userdata for that ioctl + */ +#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data) + + +#if 1 +#define ION_IOC_ROCKCHIP_MAGIC 'R' + +/** + * Clean the caches of the handle specified. + */ +#define ION_IOC_CLEAN_CACHES _IOWR(ION_IOC_ROCKCHIP_MAGIC, 0, \ + struct ion_flush_data) +/** + * Invalidate the caches of the handle specified. + */ +#define ION_IOC_INV_CACHES _IOWR(ION_IOC_ROCKCHIP_MAGIC, 1, \ + struct ion_flush_data) +/** + * Clean and invalidate the caches of the handle specified. + */ +#define ION_IOC_CLEAN_INV_CACHES _IOWR(ION_IOC_ROCKCHIP_MAGIC, 2, \ + struct ion_flush_data) + +/** + * Get phys addr of the handle specified. + */ +#define ION_IOC_GET_PHYS _IOWR(ION_IOC_ROCKCHIP_MAGIC, 3, \ + struct ion_phys_data) + +#define ION_IOC_CLEAN_CACHES _IOWR(ION_IOC_ROCKCHIP_MAGIC, 0, struct ion_flush_data) +#define ION_IOC_INV_CACHES _IOWR(ION_IOC_ROCKCHIP_MAGIC, 1, struct ion_flush_data) +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define ION_IOC_CLEAN_INV_CACHES _IOWR(ION_IOC_ROCKCHIP_MAGIC, 2, struct ion_flush_data) + +#define ION_IOC_GET_SHARE _IOWR(ION_IOC_ROCKCHIP_MAGIC, 4, struct ion_share_obj_data) +#define ION_IOC_SET_SHARE _IOWR(ION_IOC_ROCKCHIP_MAGIC, 5, struct ion_share_obj_data) + +#else +/// no available in new ion-kernel. +#define ION_CUSTOM_GET_PHYS _IOWR(ION_IOC_MAGIC, 15, \ + struct ion_phys_data) + +#define ION_CUSTOM_CACHE_OP _IOWR(ION_IOC_MAGIC, 8, \ + struct ion_cacheop_data) + +#define ION_CUSTOM_GET_CLIENT_INFO _IOWR(ION_IOC_MAGIC, 9, \ + struct ion_client_info) + +#define ION_CUSTOM_GET_HEAP_INFO _IOWR(ION_IOC_MAGIC, 10, \ + struct ion_heap_info) +/* Compatible with pmem */ +struct ion_pmem_region { + unsigned long offset; + unsigned long len; +}; +#define ION_PMEM_GET_PHYS _IOW('p', 1, unsigned int) +#define ION_PMEM_CACHE_FLUSH _IOW('p', 8, unsigned int) +#endif +/////////////////////////////////////////// + +#endif /* LINUX_ION_H */ diff --git a/osal/android/os_allocator.c b/osal/android/os_allocator.c deleted file mode 100644 index 8fd75f73f..000000000 --- a/osal/android/os_allocator.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include - -#include "os_mem.h" -#include "os_allocator.h" - -#include "mpp_mem.h" -#include "mpp_log.h" - -typedef struct { - RK_U32 alignment; -} allocator_ctx_normal; - -MPP_RET os_allocator_normal_open(void **ctx, size_t alignment) -{ - MPP_RET ret = MPP_OK; - allocator_ctx_normal *p = NULL; - - if (NULL == ctx) { - mpp_err("os_allocator_open Android do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - p = mpp_malloc(allocator_ctx_normal, 1); - if (NULL == p) { - mpp_err("os_allocator_open Android failed to allocate context\n"); - ret = MPP_ERR_MALLOC; - } else - p->alignment = alignment; - - *ctx = p; - return ret; -} - -MPP_RET os_allocator_normal_alloc(void *ctx, MppBufferInfo *info) -{ - allocator_ctx_normal *p = NULL; - - if (NULL == ctx) { - mpp_err("os_allocator_close Android do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - p = (allocator_ctx_normal *)ctx; - return os_malloc(&info->ptr, p->alignment, info->size); -} - -MPP_RET os_allocator_normal_free(void *ctx, MppBufferInfo *info) -{ - (void) ctx; - if (info->ptr) - os_free(info->ptr); - return MPP_OK; -} - -MPP_RET os_allocator_normal_close(void *ctx) -{ - if (ctx) { - mpp_free(ctx); - return MPP_OK; - } - mpp_err("os_allocator_close Linux found NULL context input\n"); - return MPP_NOK; -} - -static os_allocator allocator_normal = { - os_allocator_normal_open, - os_allocator_normal_alloc, - os_allocator_normal_free, - os_allocator_normal_close, -}; - -static RK_U32 ion_debug = 0; - -#define ION_FUNCTION (0x00000001) -#define ION_DEVICE (0x00000002) -#define ION_CLINET (0x00000004) -#define ION_IOCTL (0x00000008) - -#define ion_dbg(flag, fmt, ...) _mpp_dbg(ion_debug, flag, fmt, ## __VA_ARGS__) - -static int ion_ioctl(int fd, int req, void *arg) -{ - int ret = ioctl(fd, req, arg); - if (ret < 0) { - mpp_err("ion_ioctl %x failed with code %d: %s\n", req, - ret, strerror(errno)); - return -errno; - } - return ret; -} - -static int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, - unsigned int flags, ion_user_handle_t *handle) -{ - int ret; - struct ion_allocation_data data = { - .len = len, - .align = align, - .heap_id_mask = heap_mask, - .flags = flags, - }; - - if (handle == NULL) - return -EINVAL; - - ret = ion_ioctl(fd, ION_IOC_ALLOC, &data); - if (ret < 0) - return ret; - *handle = data.handle; - return ret; -} - -static int ion_free(int fd, ion_user_handle_t handle) -{ - struct ion_handle_data data = { - .handle = handle, - }; - return ion_ioctl(fd, ION_IOC_FREE, &data); -} - -static int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, - int flags, off_t offset, unsigned char **ptr, int *map_fd) -{ - int ret; - struct ion_fd_data data = { - .handle = handle, - }; - - if (map_fd == NULL) - return -EINVAL; - if (ptr == NULL) - return -EINVAL; - - ret = ion_ioctl(fd, ION_IOC_MAP, &data); - if (ret < 0) - return ret; - *map_fd = data.fd; - if (*map_fd < 0) { - mpp_err("map ioctl returned negative fd\n"); - return -EINVAL; - } - *ptr = mmap(NULL, length, prot, flags, *map_fd, offset); - if (*ptr == MAP_FAILED) { - mpp_err("mmap failed: %s\n", strerror(errno)); - return -errno; - } - return ret; -} - -typedef struct { - RK_U32 alignment; - RK_S32 ion_device; - RK_U32 heap_id; -} allocator_ctx_ion; - -MPP_RET os_allocator_ion_open(void **ctx, size_t alignment) -{ - RK_S32 fd; - allocator_ctx_ion *p; - - if (NULL == ctx) { - mpp_err("os_allocator_open Android do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - *ctx = NULL; - - fd = open("/dev/ion", O_RDWR); - if (fd < 0) { - mpp_err("open /dev/ion failed!\n"); - return MPP_ERR_UNKNOW; - } - - ion_dbg(ION_DEVICE, "open ion dev fd %d\n", fd); - - p = mpp_malloc(allocator_ctx_ion, 1); - if (NULL == p) { - close(fd); - mpp_err("os_allocator_open Android failed to allocate context\n"); - return MPP_ERR_MALLOC; - } else { - p->alignment = alignment; - p->ion_device = fd; - p->heap_id = ION_HEAP_TYPE_SYSTEM_CONTIG; /* ION_HEAP_TYPE_CARVEOUT */ - *ctx = p; - } - - return MPP_OK; -} - -MPP_RET os_allocator_ion_alloc(void *ctx, MppBufferInfo *info) -{ - MPP_RET ret = MPP_OK; - allocator_ctx_ion *p = NULL; - - if (NULL == ctx) { - mpp_err("os_allocator_close Android do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - p = (allocator_ctx_ion *)ctx; - ret = ion_alloc(p->ion_device, info->size, p->alignment, - p->heap_id, 0, - (ion_user_handle_t *)&info->hnd); - if (ret) { - mpp_err("os_allocator_ion_alloc ion_alloc failed ret %d\n", ret); - return ret; - } - ret = ion_map(p->ion_device, (ion_user_handle_t)info->hnd, info->size, - PROT_READ | PROT_WRITE, MAP_SHARED, (off_t)0, - (unsigned char**)&info->ptr, &info->fd); - if (ret) { - mpp_err("os_allocator_ion_alloc ion_map failed ret %d\n", ret); - return ret; - } - return ret; -} - -MPP_RET os_allocator_ion_free(void *ctx, MppBufferInfo *data) -{ - allocator_ctx_ion *p = NULL; - if (NULL == ctx) { - mpp_err("os_allocator_close Android do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - p = (allocator_ctx_ion *)ctx; - munmap(data->ptr, data->size); - close(data->fd); - ion_free(p->ion_device, (ion_user_handle_t)data->hnd); - return MPP_OK; -} - -MPP_RET os_allocator_ion_close(void *ctx) -{ - int ret; - allocator_ctx_ion *p; - - if (NULL == ctx) { - mpp_err("os_allocator_close Android do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - p = (allocator_ctx_ion *)ctx; - ret = close(p->ion_device); - if (ret < 0) - return (MPP_RET) - errno; - return MPP_OK; -} - -static os_allocator allocator_ion = { - os_allocator_ion_open, - os_allocator_ion_alloc, - os_allocator_ion_free, - os_allocator_ion_close, -}; - -MPP_RET os_allocator_get(os_allocator *api, MppBufferType type) -{ - MPP_RET ret = MPP_OK; - switch (type) { - case MPP_BUFFER_TYPE_NORMAL : - case MPP_BUFFER_TYPE_V4L2 : { - *api = allocator_normal; - } break; - case MPP_BUFFER_TYPE_ION : { - *api = allocator_ion; - } break; - default : { - ret = MPP_NOK; - } break; - } - return ret; -} - diff --git a/osal/android/os_env.c b/osal/android/os_env.c index a2fae1e4f..504ed6326 100644 --- a/osal/android/os_env.c +++ b/osal/android/os_env.c @@ -1,77 +1,67 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "os_env.h" -#include - -/* - * NOTE: __system_property_set only available after android-21 - * So the library should compiled on latest ndk - */ - -RK_S32 os_get_env_u32(const char *name, RK_U32 *value, RK_U32 default_value) -{ - char prop[PROP_VALUE_MAX + 1]; - int len = __system_property_get(name, prop); - if (len > 0) { - char *endptr; - int base = (prop[0] == '0' && prop[1] == 'x') ? (16) : (10); - errno = 0; - *value = strtoul(prop, &endptr, base); - if (errno || (prop == endptr)) { - errno = 0; - *value = default_value; - } - } else { - *value = default_value; - } - return 0; -} - -RK_S32 os_get_env_str(const char *name, char **value, char *default_value) -{ - // use unsigned char to avoid warnning - static unsigned char env_str[2][PROP_VALUE_MAX + 1]; - static RK_U32 env_idx = 0; - char *prop = (char *)env_str[env_idx]; - int len = __system_property_get(name, prop); - if (len > 0) { - *value = prop; - env_idx = !env_idx; - } else { - *value = default_value; - } - return 0; -} - -RK_S32 os_set_env_u32(const char *name, RK_U32 value) -{ - char buf[PROP_VALUE_MAX + 1 + 2]; - snprintf(buf, sizeof(buf), "0x%x", value); - int len = __system_property_set(name, buf); - return (len) ? (0) : (-1); -} - -RK_S32 os_set_env_str(const char *name, char *value) -{ - int len = __system_property_set(name, value); - return (len) ? (0) : (-1); -} - - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(__ANDROID__) +#include +#include +#include +#include "os_env.h" +#include + +/* + * NOTE: __system_property_set only available after android-21 + * So the library should compiled on latest ndk + */ + +RK_S32 os_get_env_u32(const char *name, RK_U32 *value, RK_U32 default_value) +{ + char prop[PROP_VALUE_MAX + 1]; + int len = __system_property_get(name, prop); + if (len > 0) { + char *endptr; + int base = (prop[0] == '0' && prop[1] == 'x') ? (16) : (10); + errno = 0; + *value = strtoul(prop, &endptr, base); + if (errno || (prop == endptr)) { + errno = 0; + *value = default_value; + } + } else { + *value = default_value; + } + return 0; +} + +RK_S32 os_get_env_str(const char *name, const char **value, const char *default_value) +{ + // use unsigned char to avoid warnning + static unsigned char env_str[2][PROP_VALUE_MAX + 1]; + static RK_U32 env_idx = 0; + char *prop = (char *)env_str[env_idx]; + int len = __system_property_get(name, prop); + if (len > 0) { + *value = prop; + env_idx = !env_idx; + } else { + *value = default_value; + } + return 0; +} + +RK_S32 os_set_env_u32(const char *name, RK_U32 value) +{ + char buf[PROP_VALUE_MAX + 1 + 2]; + snprintf(buf, sizeof(buf) - 1, "0x%x", value); + int len = __system_property_set(name, buf); + return (len) ? (0) : (-1); +} + +RK_S32 os_set_env_str(const char *name, char *value) +{ + int len = __system_property_set(name, value); + return (len) ? (0) : (-1); +} + +#endif diff --git a/osal/android/os_log.c b/osal/android/os_log.c index c4f067371..ee7c3d79e 100644 --- a/osal/android/os_log.c +++ b/osal/android/os_log.c @@ -1,28 +1,39 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -void os_log(const char* tag, const char* msg, va_list list) -{ - __android_log_vprint(ANDROID_LOG_INFO, tag, msg, list); -} - -void os_err(const char* tag, const char* msg, va_list list) -{ - __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, list); -} - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(__ANDROID__) +#include + +void os_log_trace(const char* tag, const char* msg, va_list list) +{ + __android_log_vprint(ANDROID_LOG_VERBOSE, tag, msg, list); +} + +void os_log_debug(const char* tag, const char* msg, va_list list) +{ + __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, list); +} + +void os_log_info(const char* tag, const char* msg, va_list list) +{ + __android_log_vprint(ANDROID_LOG_INFO, tag, msg, list); +} + +void os_log_warn(const char* tag, const char* msg, va_list list) +{ + __android_log_vprint(ANDROID_LOG_WARN, tag, msg, list); +} + +void os_log_error(const char* tag, const char* msg, va_list list) +{ + __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, list); +} + +void os_log_fatal(const char* tag, const char* msg, va_list list) +{ + __android_log_vprint(ANDROID_LOG_FATAL, tag, msg, list); +} + +#endif diff --git a/osal/android/os_mem.c b/osal/android/os_mem.c index 03daf1b5e..7d16541a5 100644 --- a/osal/android/os_mem.c +++ b/osal/android/os_mem.c @@ -1,36 +1,38 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "os_mem.h" - -int os_malloc(void **memptr, size_t alignment, size_t size) -{ - return posix_memalign(memptr, alignment, size); -} - -int os_realloc(void *src, void **dst, size_t alignment, size_t size) -{ - (void)alignment; - *dst = realloc(src, size); - return (*dst) ? (0) : (-1); -} - -void os_free(void *ptr) -{ - free(ptr); -} - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(__ANDROID__) +#include +#include "os_mem.h" + +int os_malloc(void **memptr, size_t alignment, size_t size) +{ + (void)alignment; + int ret = 0; + void *ptr = malloc(size); + + if (ptr) { + *memptr = ptr; + } else { + *memptr = NULL; + ret = -1; + } + return ret; + + //return posix_memalign(memptr, alignment, size); +} + +int os_realloc(void *src, void **dst, size_t alignment, size_t size) +{ + (void)alignment; + *dst = realloc(src, size); + return (*dst) ? (0) : (-1); +} + +void os_free(void *ptr) +{ + free(ptr); +} +#endif diff --git a/osal/driver/inc/mpp_device_debug.h b/osal/driver/inc/mpp_device_debug.h new file mode 100644 index 000000000..7f7e6eeed --- /dev/null +++ b/osal/driver/inc/mpp_device_debug.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_DEVICE_DEBUG_H +#define MPP_DEVICE_DEBUG_H + +#include "mpp_debug.h" + +#define MPP_DEVICE_DBG_FUNC (0x00000001) +#define MPP_DEVICE_DBG_PROBE (0x00000002) +#define MPP_DEVICE_DBG_DETAIL (0x00000004) +#define MPP_DEVICE_DBG_REG (0x00000010) +#define MPP_DEVICE_DBG_TIME (0x00000020) +#define MPP_DEVICE_DBG_MSG (0x00000040) +#define MPP_DEVICE_DBG_BUF (0x00000080) + +#define mpp_dev_dbg(flag, fmt, ...) mpp_dbg(mpp_device_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_dev_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_device_debug, flag, fmt, ## __VA_ARGS__) + +#define mpp_dev_dbg_func(fmt, ...) mpp_dev_dbg_f(MPP_DEVICE_DBG_FUNC, fmt, ## __VA_ARGS__) +#define mpp_dev_dbg_probe(fmt, ...) mpp_dev_dbg_f(MPP_DEVICE_DBG_PROBE, fmt, ## __VA_ARGS__) +#define mpp_dev_dbg_detail(fmt, ...) mpp_dev_dbg(MPP_DEVICE_DBG_DETAIL, fmt, ## __VA_ARGS__) +#define mpp_dev_dbg_reg(fmt, ...) mpp_dev_dbg(MPP_DEVICE_DBG_REG, fmt, ## __VA_ARGS__) +#define mpp_dev_dbg_time(fmt, ...) mpp_dev_dbg(MPP_DEVICE_DBG_TIME, fmt, ## __VA_ARGS__) +#define mpp_dev_dbg_msg(fmt, ...) mpp_dev_dbg(MPP_DEVICE_DBG_MSG, fmt, ## __VA_ARGS__) +#define mpp_dev_dbg_buf(fmt, ...) mpp_dev_dbg(MPP_DEVICE_DBG_BUF, fmt, ## __VA_ARGS__) + +extern RK_U32 mpp_device_debug; + +#endif /* MPP_DEVICE_DEBUG_H */ diff --git a/osal/driver/inc/mpp_service_impl.h b/osal/driver/inc/mpp_service_impl.h new file mode 100644 index 000000000..160f3b404 --- /dev/null +++ b/osal/driver/inc/mpp_service_impl.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SERVICE_IMPL_H +#define MPP_SERVICE_IMPL_H + +#include "mpp_list.h" + +#include "mpp_device.h" +#include "mpp_service.h" + +#define MAX_REG_OFFSET 64 +#define MAX_RCB_OFFSET 32 +#define MAX_INFO_COUNT 16 + +typedef struct FdTransInfo_t { + RK_U32 reg_idx; + RK_U32 offset; +} RegOffsetInfo; + +typedef struct RcbInfo_t { + RK_U32 reg_idx; + RK_U32 size; +} RcbInfo; + +typedef struct MppDevMppService_t { + RK_S32 client_type; + RK_S32 client; + RK_S32 server; + void *serv_ctx; + RK_S32 batch_io; + MppCbCtx *dev_cb; + + MppReqV1 *reqs; + RK_S32 req_max; + RK_S32 req_cnt; + + RegOffsetInfo *reg_offset_info; + RK_S32 reg_offset_max; + RK_S32 reg_offset_count; + RK_S32 reg_offset_pos; + + RcbInfo *rcb_info; + RK_S32 rcb_max; + RK_S32 rcb_count; + RK_S32 rcb_pos; + + MppDevBatCmd bat_cmd; + + RK_S32 info_count; + MppDevInfoCfg info[MAX_INFO_COUNT]; + + /* support max cmd buttom */ + const MppServiceCmdCap *cap; + RK_U32 support_set_info; + RK_U32 support_set_rcb_info; + RK_U32 support_hw_irq; + + pthread_mutex_t lock_bufs; + struct list_head list_bufs; +} MppDevMppService; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_service_ioctl(RK_S32 fd, RK_U32 cmd, RK_U32 size, void *param); +RK_S32 mpp_service_ioctl_request(RK_S32 fd, MppReqV1 *req); +MPP_RET mpp_service_check_cmd_valid(RK_U32 cmd, const MppServiceCmdCap *cap); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SERVICE_IMPL_H */ diff --git a/osal/driver/inc/mpp_vcodec_client.h b/osal/driver/inc/mpp_vcodec_client.h new file mode 100644 index 000000000..e3260b288 --- /dev/null +++ b/osal/driver/inc/mpp_vcodec_client.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_VCODEC_CLIENT_H +#define MPP_VCODEC_CLIENT_H + +#include "rk_type.h" +#include "mpp_err.h" + +#define VCODEC_ID_BASE_COMMON (0x00000000) +#define VCODEC_ID_BASE_STATE (0x00000100) +#define VCODEC_ID_BASE_FLOW (0x00000200) + +#define VCODEC_ID_BASE_INPUT (0x00000400) +#define VCODEC_ID_BASE_INPUT_ACK (0x00000500) + +#define VCODEC_ID_BASE_OUTPUT (0x00000600) +#define VCODEC_ID_BASE_OUTPUT_ACK (0x00000700) + +enum vcodec_event_id { + /* channel comment event */ + VCODEC_CHAN_CREATE = VCODEC_ID_BASE_COMMON, + VCODEC_CHAN_DESTROY, + VCODEC_CHAN_RESET, + VCODEC_CHAN_CONTROL, + + /* channel state change event */ + VCODEC_CHAN_START = VCODEC_ID_BASE_STATE, + VCODEC_CHAN_STOP, + VCODEC_CHAN_PAUSE, + VCODEC_CHAN_RESUME, + + /* channel data flow event */ + VCODEC_CHAN_BIND = VCODEC_ID_BASE_FLOW, + VCODEC_CHAN_UNBIND, + + /* channel input side io event from external module */ + VCODEC_CHAN_IN_FRM_RDY = VCODEC_ID_BASE_INPUT, + VCODEC_CHAN_IN_FRM_START, + VCODEC_CHAN_IN_FRM_EARLY_END, + VCODEC_CHAN_IN_FRM_END, + + /* channel input side ack event from vcodec module */ + VCODEC_CHAN_IN_BLOCK = VCODEC_ID_BASE_INPUT_ACK, + + /* channel output side io event from vcodec module */ + VCODEC_CHAN_OUT_STRM_Q_FULL = VCODEC_ID_BASE_OUTPUT, + VCODEC_CHAN_OUT_STRM_BUF_RDY, + VCODEC_CHAN_OUT_STRM_END, + /* new get packet interface */ + VCODEC_CHAN_OUT_PKT_RDY, + + /* channel input side ack event from external module */ + VCODEC_CHAN_OUT_BLOCK = VCODEC_ID_BASE_OUTPUT_ACK, + +}; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_vcodec_open(void); +MPP_RET mpp_vcodec_ioctl(RK_S32 fd, RK_U32 cmd, RK_U32 ctrl_cmd, RK_U32 size, void *param); +MPP_RET mpp_vcodec_close(RK_S32 fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/driver/mpp_device.c b/osal/driver/mpp_device.c new file mode 100644 index 000000000..b40557e7d --- /dev/null +++ b/osal/driver/mpp_device.c @@ -0,0 +1,267 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_device" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_common.h" + +#include "mpp_platform.h" +#include "mpp_device_debug.h" +#include "mpp_service_api.h" +#include "vcodec_service_api.h" + +typedef struct MppDevImpl_t { + MppClientType type; + + void *ctx; + const MppDevApi *api; +} MppDevImpl; + +RK_U32 mpp_device_debug = 0; + +MPP_RET mpp_dev_init(MppDev *ctx, MppClientType type) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input ctx\n"); + return MPP_ERR_NULL_PTR; + } + + mpp_env_get_u32("mpp_device_debug", &mpp_device_debug, 0); + + *ctx = NULL; + + RK_U32 codec_type = mpp_get_vcodec_type(); + if (!(codec_type & (1 << type))) { + mpp_err_f("found unsupported client type %d in platform %x\n", + type, codec_type); + return MPP_ERR_VALUE; + } + + MppIoctlVersion ioctl_version = mpp_get_ioctl_version(); + const MppDevApi *api = NULL; + + switch (ioctl_version) { + case IOCTL_VCODEC_SERVICE : { + api = &vcodec_service_api; + } break; + case IOCTL_MPP_SERVICE_V1 : { + api = &mpp_service_api; + } break; + default : { + mpp_err_f("invalid ioctl verstion %d\n", ioctl_version); + return MPP_NOK; + } break; + } + + MppDevImpl *impl = mpp_calloc(MppDevImpl, 1); + void *impl_ctx = mpp_calloc_size(void, api->ctx_size); + if (NULL == impl || NULL == impl_ctx) { + mpp_err_f("malloc failed impl %p impl_ctx %p\n", impl, impl_ctx); + MPP_FREE(impl); + MPP_FREE(impl_ctx); + return MPP_ERR_MALLOC; + } + + impl->ctx = impl_ctx; + impl->api = api; + impl->type = type; + *ctx = impl; + + return api->init(impl_ctx, type); +} + +MPP_RET mpp_dev_deinit(MppDev ctx) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input ctx\n"); + return MPP_ERR_NULL_PTR; + } + + MppDevImpl *p = (MppDevImpl *)ctx; + MPP_RET ret = MPP_OK; + + if (p->api && p->api->deinit && p->ctx) + ret = p->api->deinit(p->ctx); + + MPP_FREE(p->ctx); + MPP_FREE(p); + + return ret; +} + +MPP_RET mpp_dev_ioctl(MppDev ctx, RK_S32 cmd, void *param) +{ + if (NULL == ctx) { + mpp_err_f("found NULL input ctx\n"); + return MPP_ERR_NULL_PTR; + } + + MppDevImpl *p = (MppDevImpl *)ctx; + const MppDevApi *api = p->api; + void *impl_ctx = p->ctx; + MPP_RET ret = MPP_OK; + + if (NULL == impl_ctx || NULL == api) + return ret; + + switch (cmd) { + case MPP_DEV_BATCH_ON : { + if (api->attach) + ret = api->attach(impl_ctx); + } break; + case MPP_DEV_BATCH_OFF : { + if (api->detach) + ret = api->detach(impl_ctx); + } break; + case MPP_DEV_DELIMIT : { + if (api->delimit) + ret = api->delimit(impl_ctx); + } break; + case MPP_DEV_SET_CB_CTX: { + if (api->set_cb_ctx) + ret = api->set_cb_ctx(impl_ctx, param); + } break; + case MPP_DEV_REG_WR : { + if (api->reg_wr) + ret = api->reg_wr(impl_ctx, param); + } break; + case MPP_DEV_REG_RD : { + if (api->reg_rd) + ret = api->reg_rd(impl_ctx, param); + } break; + case MPP_DEV_REG_OFFSET : { + if (api->reg_offset) + ret = api->reg_offset(impl_ctx, param); + } break; + case MPP_DEV_REG_OFFS : { + if (api->reg_offs) + ret = api->reg_offs(impl_ctx, param); + } break; + case MPP_DEV_RCB_INFO : { + if (api->rcb_info) + ret = api->rcb_info(impl_ctx, param); + } break; + case MPP_DEV_SET_INFO : { + if (api->set_info) + ret = api->set_info(impl_ctx, param); + } break; + case MPP_DEV_SET_ERR_REF_HACK : { + if (api->set_err_ref_hack) + ret = api->set_err_ref_hack(impl_ctx, param); + } break; + case MPP_DEV_LOCK_MAP : { + if (api->lock_map) + ret = api->lock_map(impl_ctx); + } break; + case MPP_DEV_UNLOCK_MAP : { + if (api->unlock_map) + ret = api->unlock_map(impl_ctx); + } break; + case MPP_DEV_ATTACH_FD : { + if (api->attach_fd) + ret = api->attach_fd(impl_ctx, param); + } break; + case MPP_DEV_DETACH_FD : { + if (api->detach_fd) + ret = api->detach_fd(impl_ctx, param); + } break; + case MPP_DEV_CMD_SEND : { + if (api->cmd_send) + ret = api->cmd_send(impl_ctx); + } break; + case MPP_DEV_CMD_POLL : { + if (api->cmd_poll) + ret = api->cmd_poll(impl_ctx, param); + } break; + default : { + mpp_err_f("invalid cmd %d\n", cmd); + } break; + } + + return ret; +} + +MPP_RET mpp_dev_set_reg_offset(MppDev dev, RK_S32 index, RK_U32 offset) +{ + MppDevRegOffsetCfg trans_cfg; + + trans_cfg.reg_idx = index; + trans_cfg.offset = offset; + + return mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg); +} + +/* register offset multi config */ +MPP_RET mpp_dev_multi_offset_init(MppDevRegOffCfgs **cfgs, RK_S32 size) +{ + RK_S32 cfg_size = sizeof(MppDevRegOffCfgs) + size * sizeof(MppDevRegOffsetCfg); + MppDevRegOffCfgs *p = NULL; + + if (NULL == cfgs || size <= 0) { + mpp_err_f("invalid pointer %p size %d\n", cfgs, size); + return MPP_NOK; + } + + p = mpp_calloc_size(MppDevRegOffCfgs, cfg_size); + if (p) + p->size = size; + + *cfgs = p; + + return (p) ? MPP_OK : MPP_NOK; +} + +MPP_RET mpp_dev_multi_offset_deinit(MppDevRegOffCfgs *cfgs) +{ + MPP_FREE(cfgs); + + return MPP_OK; +} + +MPP_RET mpp_dev_multi_offset_reset(MppDevRegOffCfgs *cfgs) +{ + if (cfgs) { + memset(cfgs->cfgs, 0, cfgs->count * sizeof(cfgs->cfgs[0])); + cfgs->count = 0; + } + + return MPP_OK; +} + +MPP_RET mpp_dev_multi_offset_update(MppDevRegOffCfgs *cfgs, RK_S32 index, RK_U32 offset) +{ + MppDevRegOffsetCfg *cfg; + RK_S32 count; + RK_S32 i; + + if (NULL == cfgs) + return MPP_NOK; + + if (cfgs->count >= cfgs->size) { + mpp_err_f("invalid cfgs count %d : %d\n", cfgs->count, cfgs->size); + return MPP_NOK; + } + + count = cfgs->count; + cfg = cfgs->cfgs; + + for (i = 0; i < count; i++, cfg++) { + + if (cfg->reg_idx == (RK_U32)index) { + cfg->offset = offset; + return MPP_OK; + } + } + + cfg->reg_idx = index; + cfg->offset = offset; + cfgs->count++; + + return MPP_OK; +} diff --git a/osal/driver/mpp_server.c b/osal/driver/mpp_server.c new file mode 100644 index 000000000..1e49ae356 --- /dev/null +++ b/osal/driver/mpp_server.c @@ -0,0 +1,941 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_server" + +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_list.h" +#include "mpp_time.h" +#include "osal_2str.h" +#include "mpp_common.h" +#include "mpp_thread.h" +#include "mpp_mem_pool.h" +#include "mpp_singleton.h" + +#include "mpp_server.h" +#include "mpp_device_debug.h" +#include "mpp_service_impl.h" + +#define MAX_BATCH_TASK 8 +#define MAX_SESSION_TASK 4 +#define MAX_REQ_SEND_CNT MAX_REQ_NUM +#define MAX_REQ_WAIT_CNT 2 + +#define MPP_SERVER_DBG_FLOW (0x00000001) + +#define mpp_serv_dbg(flag, fmt, ...) mpp_dbg(mpp_server_debug, flag, fmt, ## __VA_ARGS__) +#define mpp_serv_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_server_debug, flag, fmt, ## __VA_ARGS__) + +#define mpp_serv_dbg_flow(fmt, ...) mpp_serv_dbg(MPP_SERVER_DBG_FLOW, fmt, ## __VA_ARGS__) + +#define FIFO_WRITE(size, count, wr, rd) \ + do { \ + wr++; \ + if (wr >= size) wr = 0; \ + count++; \ + mpp_assert(count <= size); \ + } while (0) + +#define FIFO_READ(size, count, wr, rd) \ + do { \ + rd++; \ + if (rd >= size) rd = 0; \ + count--; \ + mpp_assert(count >= 0); \ + } while (0) + +#define get_srv_server() \ + ({ \ + MppDevServer *__tmp; \ + if (!srv_server) { \ + mpp_server_init(); \ + } \ + __tmp = srv_server; \ + if (!__tmp || !__tmp->inited) { \ + mpp_err("mpp server srv not init for %s at %s\n", \ + __tmp ? __tmp->server_error : "invalid server", __FUNCTION__); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +typedef struct MppDevTask_t MppDevTask; +typedef struct MppDevBatTask_t MppDevBatTask; +typedef struct MppDevSession_t MppDevSession; +typedef struct MppDevBatServ_t MppDevBatServ; + +struct MppDevTask_t { + /* link to server */ + struct list_head link_server; + /* link to session tasks */ + struct list_head link_session; + /* link to batch tasks */ + struct list_head link_batch; + + MppDevSession *session; + MppDevBatTask *batch; + + rk_s32 slot_idx; + + /* lock by server */ + rk_s32 task_id; + /* lock by batch */ + rk_s32 batch_slot_id; + + MppReqV1 *req; + rk_s32 req_cnt; +}; + +struct MppDevBatTask_t { + MppMutexCond cond; + + /* link to server */ + struct list_head link_server; + /* link to session tasks */ + struct list_head link_tasks; + + rk_u32 batch_id; + + MppDevBatCmd *bat_cmd; + MppReqV1 *send_reqs; + MppReqV1 *wait_reqs; + + /* lock and clean by server */ + rk_s32 send_req_cnt; + rk_s32 wait_req_cnt; + + /* lock by server */ + rk_s32 fill_cnt; + rk_s32 fill_full; + rk_s32 fill_timeout; + rk_s32 poll_cnt; +}; + +struct MppDevSession_t { + MppMutexCond cond_lock; + + /* hash table to server */ + struct list_head list_server; + /* link to session waiting tasks */ + struct list_head list_wait; + /* link to session free tasks */ + struct list_head list_done; + + MppDevMppService *ctx; + MppDevBatServ *server; + + rk_s32 client; + + rk_s32 task_wait; + rk_s32 task_done; + + MppDevTask tasks[MAX_SESSION_TASK]; +}; + +struct MppDevBatServ_t { + MppMutex lock; + + rk_s32 server_fd; + rk_u32 batch_id; + rk_u32 task_id; + + /* timer for serializing process */ + MppTimer timer; + + /* session register */ + struct list_head session_list; + rk_s32 session_count; + + /* batch task queue */ + struct list_head list_batch; + struct list_head list_batch_free; + MppMemPool batch_pool; + rk_s32 batch_max_count; + rk_s32 batch_task_size; + rk_s32 batch_run; + rk_s32 batch_free; + rk_s32 max_task_in_batch; + + /* link to all pending tasks */ + struct list_head pending_task; + rk_s32 pending_count; +}; + +typedef struct MppDevServer_t { + const char *server_error; + const char *server_name; + rk_s32 inited; + rk_u32 enable; + MppMutex lock; + MppDevBatServ *bat_server[VPU_CLIENT_BUTT]; + + MppMemPool session_pool; + MppMemPool batch_pool; + + rk_s32 max_task_in_batch; + + const MppServiceCmdCap *cmd_cap; +} MppDevServer; + +static MppDevServer *srv_server = NULL; +static rk_u32 mpp_server_debug = 0; + +static void batch_reset(MppDevBatTask *batch) +{ + mpp_assert(list_empty(&batch->link_tasks)); + + batch->fill_cnt = 0; + batch->fill_full = 0; + batch->fill_timeout = 0; + batch->poll_cnt = 0; + batch->send_req_cnt = 0; + batch->wait_req_cnt = 0; +} + +MppDevBatTask *batch_add(MppDevBatServ *server) +{ + MppDevBatTask *batch = (MppDevBatTask *)mpp_mem_pool_get_f(server->batch_pool); + + mpp_assert(batch); + if (!batch) + return batch; + + INIT_LIST_HEAD(&batch->link_server); + INIT_LIST_HEAD(&batch->link_tasks); + + batch->send_reqs = (MppReqV1 *)(batch + 1); + batch->wait_reqs = batch->send_reqs + + (server->max_task_in_batch * MAX_REQ_SEND_CNT); + batch->bat_cmd = (MppDevBatCmd *)(batch->wait_reqs + + (server->max_task_in_batch * MAX_REQ_WAIT_CNT)); + + batch_reset(batch); + list_add_tail(&batch->link_server, &server->list_batch_free); + server->batch_free++; + + mpp_serv_dbg_flow("batch add free count %d:%d\n", server->batch_run, server->batch_free); + return batch; +} + +void batch_del(MppDevBatServ *server, MppDevBatTask *batch) +{ + mpp_assert(batch); + mpp_assert(batch->fill_cnt == 0); + mpp_assert(list_empty(&batch->link_tasks)); + + list_del_init(&batch->link_server); + + mpp_mem_pool_put_f(server->batch_pool, batch); + server->batch_free--; + mpp_serv_dbg_flow("batch del free count %d:%d\n", server->batch_run, server->batch_free); +} + +void batch_send(MppDevBatServ *server, MppDevBatTask *batch) +{ + rk_s32 ret = 0; + + mpp_assert(batch->send_req_cnt); + + ret = mpp_service_ioctl_request(server->server_fd, batch->send_reqs); + if (ret) { + mpp_err_f("ioctl batch cmd failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + mpp_serv_dbg_flow("batch %d -> send failed\n", batch->batch_id); + } + + list_del_init(&batch->link_server); + list_add_tail(&batch->link_server, &server->list_batch); + server->batch_free--; + server->batch_run++; + mpp_serv_dbg_flow("batch %d -> send %d for %s\n", batch->batch_id, + batch->fill_cnt, batch->fill_timeout ? "timeout" : "ready"); +} + +void process_task(void *p) +{ + MppDevBatServ *server = (MppDevBatServ *)p; + MppMutex *lock = &server->lock; + rk_s32 ret = rk_ok; + MppDevTask *task; + MppDevBatTask *batch; + MppDevSession *session = NULL; + MppDevBatCmd *bat_cmd; + MppReqV1 *req = NULL; + rk_s32 pending = 0; + + mpp_serv_dbg_flow("process task start\n"); + + /* 1. try poll and get finished task */ + do { + batch = list_first_entry_or_null(&server->list_batch, MppDevBatTask, link_server); + if (!batch) + break; + + mpp_assert(batch->wait_req_cnt); + ret = mpp_service_ioctl_request(server->server_fd, batch->wait_reqs); + if (!ret) { + MppDevTask *n; + + list_for_each_entry_safe(task, n, &batch->link_tasks, MppDevTask, link_batch) { + rk_s32 batch_slot_id = task->batch_slot_id; + MppDevBatCmd *cmd = batch->bat_cmd + batch_slot_id; + + mpp_assert(batch_slot_id < server->max_task_in_batch); + session = task->session; + + ret = cmd->ret; + if (ret == EAGAIN) + continue; + + if (ret == -EIO) { + mpp_err_f("batch %d:%d task %d poll error found\n", + batch->batch_id, task->batch_slot_id, task->task_id); + cmd->flag |= 1; + continue; + } + if (ret == 0) { + list_del_init(&task->link_batch); + task->batch = NULL; + + mpp_serv_dbg_flow("batch %d:%d session %d ready and remove\n", + batch->batch_id, task->batch_slot_id, session->client); + mpp_mutex_cond_lock(&session->cond_lock); + session->task_done++; + mpp_mutex_cond_signal(&session->cond_lock); + mpp_mutex_cond_unlock(&session->cond_lock); + if (session->ctx && session->ctx->dev_cb) + mpp_callback(session->ctx->dev_cb, NULL); + + batch->poll_cnt++; + cmd->flag |= 1; + } + } + + mpp_serv_dbg_flow("batch %d fill %d poll %d\n", batch->batch_id, + batch->fill_cnt, batch->poll_cnt); + + if (batch->poll_cnt == batch->fill_cnt) { + mpp_serv_dbg_flow("batch %d poll done\n", batch->batch_id); + list_del_init(&batch->link_server); + list_add_tail(&batch->link_server, &server->list_batch_free); + server->batch_run--; + server->batch_free++; + + batch_reset(batch); + batch = NULL; + continue; + } + } else { + mpp_log_f("batch %d poll ret %d errno %d %s", batch->batch_id, + ret, errno, strerror(errno)); + mpp_log_f("stop timer\n"); + mpp_timer_set_enable(server->timer, 0); + } + break; + } while (1); + + /* 2. get prending task to fill */ + mpp_mutex_lock(lock); + pending = server->pending_count; + if (!pending && !server->batch_run && !server->session_count) { + mpp_timer_set_enable(server->timer, 0); + mpp_serv_dbg_flow("stop timer\n"); + } + mpp_mutex_unlock(lock); + + mpp_serv_dbg_flow("pending %d running %d free %d max %d process start\n", + pending, server->batch_run, server->batch_free, server->batch_max_count); + +try_proc_pending_task: + /* 3. try get batch task*/ + if (!server->batch_free) { + /* if not enough and max count does not reached create new batch */ + if (server->batch_free + server->batch_run >= server->batch_max_count) { + mpp_serv_dbg_flow("finish for not batch slot\n"); + return ; + } + + batch_add(server); + } + mpp_assert(server->batch_free); + + /* 4. if no pending task to send check timeout batch and send it */ + if (!pending) { + if (!server->batch_free) { + /* no pending and no free batch just done */ + return; + } + + batch = list_first_entry_or_null(&server->list_batch_free, MppDevBatTask, link_server); + mpp_assert(batch); + if (!batch) { + mpp_log_f("batch run %d free %d\n", server->batch_run, server->batch_free); + return; + } + + /* send one timeout task */ + if (batch->fill_cnt) + batch_send(server, batch); + + mpp_serv_dbg_flow("finish for no pending task\n"); + return; + } + + mpp_serv_dbg_flow("pending task %d left to process\n", pending); + + /* 5. add task to add batch and try send batch */ + if (!server->batch_free) { + /* no pending and no free batch just done */ + return; + } + + batch = list_first_entry_or_null(&server->list_batch_free, MppDevBatTask, link_server); + mpp_assert(batch); + mpp_assert(pending); + + task = NULL; + mpp_mutex_lock(lock); + task = list_first_entry_or_null(&server->pending_task, MppDevTask, link_server); + list_del_init(&task->link_server); + server->pending_count--; + mpp_mutex_unlock(lock); + pending--; + + /* first task and setup new batch id */ + if (!batch->fill_cnt) + batch->batch_id = server->batch_id++; + + task->batch = batch; + task->batch_slot_id = batch->fill_cnt++; + mpp_assert(task->batch_slot_id < server->max_task_in_batch); + list_add_tail(&task->link_batch, &batch->link_tasks); + if (batch->fill_cnt >= server->max_task_in_batch) + batch->fill_full = 1; + + session = task->session; + mpp_assert(session); + mpp_assert(session->ctx); + + bat_cmd = batch->bat_cmd + task->batch_slot_id; + bat_cmd->flag = 0; + bat_cmd->client = session->client; + bat_cmd->ret = 0; + + /* fill task to batch */ + /* add session info before each session task and then copy session request */ + req = &batch->send_reqs[batch->send_req_cnt++]; + req->cmd = MPP_CMD_SET_SESSION_FD; + req->flag = MPP_FLAGS_MULTI_MSG; + req->offset = 0; + req->size = sizeof(*bat_cmd); + req->data_ptr = REQ_DATA_PTR(bat_cmd); + + { + rk_s32 i; + + for (i = 0; i < task->req_cnt; i++) + batch->send_reqs[batch->send_req_cnt++] = task->req[i]; + } + + mpp_assert(batch->send_req_cnt <= server->max_task_in_batch * MAX_REQ_NUM); + + /* setup poll request */ + req = &batch->wait_reqs[batch->wait_req_cnt++]; + req->cmd = MPP_CMD_SET_SESSION_FD; + req->flag = MPP_FLAGS_MULTI_MSG; + req->offset = 0; + req->size = sizeof(*bat_cmd); + req->data_ptr = REQ_DATA_PTR(bat_cmd); + + req = &batch->wait_reqs[batch->wait_req_cnt++]; + req->cmd = MPP_CMD_POLL_HW_FINISH; + req->flag = MPP_FLAGS_POLL_NON_BLOCK | MPP_FLAGS_MULTI_MSG | MPP_FLAGS_LAST_MSG; + req->offset = 0; + req->size = 0; + req->data_ptr = 0; + + mpp_serv_dbg_flow("batch %d:%d add task %d:%d:%d\n", + batch->batch_id, task->batch_slot_id, session->client, + task->slot_idx, task->task_id); + + if (batch->fill_full) { + list_del_init(&batch->link_server); + list_add_tail(&batch->link_server, &server->list_batch); + mpp_serv_dbg_flow("batch %d -> fill_nb %d fill ready\n", + batch->batch_id, batch->fill_cnt); + batch_send(server, batch); + batch = NULL; + } + goto try_proc_pending_task; +} + +static void *mpp_server_thread(void *ctx) +{ + process_task((MppDevBatServ *)ctx); + return NULL; +} + +rk_s32 send_task(MppDevMppService *ctx) +{ + MppDevTask *task = NULL; + MppDevSession *session = (MppDevSession *)ctx->serv_ctx; + + if (!session || !session->server) { + mpp_err_f("invalid ctx %p session %p send task\n", ctx, session); + return rk_nok; + } + + MppDevBatServ *server = session->server; + + /* get free task from session and add to run list */ + mpp_mutex_cond_lock(&session->cond_lock); + /* get a free task and setup */ + task = list_first_entry_or_null(&session->list_done, MppDevTask, link_session); + mpp_assert(task); + + task->req = ctx->reqs; + task->req_cnt = ctx->req_cnt; + + list_del_init(&task->link_session); + list_add_tail(&task->link_session, &session->list_wait); + + session->task_wait++; + mpp_mutex_cond_unlock(&session->cond_lock); + + mpp_mutex_lock(&server->lock); + task->task_id = server->task_id++; + list_del_init(&task->link_server); + list_add_tail(&task->link_server, &server->pending_task); + server->pending_count++; + mpp_serv_dbg_flow("session %d:%d add pending %d\n", + session->client, task->slot_idx, server->pending_count); + + mpp_timer_set_enable(server->timer, 1); + mpp_mutex_unlock(&server->lock); + + return rk_ok; +} + +rk_s32 wait_task(MppDevMppService *ctx, rk_s64 timeout) +{ + rk_s32 ret = rk_ok; + MppDevTask *task = NULL; + MppDevSession *session = (MppDevSession *)ctx->serv_ctx; + (void) timeout; + + if (!session) { + mpp_err_f("invalid ctx %p send task\n", ctx); + return rk_nok; + } + + task = list_first_entry_or_null(&session->list_wait, MppDevTask, link_session); + mpp_assert(task); + + mpp_mutex_cond_lock(&session->cond_lock); + if (session->task_wait != session->task_done) { + mpp_serv_dbg_flow("session %d wait %d start %d:%d\n", session->client, + task->task_id, session->task_wait, session->task_done); + mpp_mutex_cond_wait(&session->cond_lock); + } + mpp_serv_dbg_flow("session %d wait %d done %d:%d\n", session->client, + task->task_id, session->task_wait, session->task_done); + mpp_mutex_cond_unlock(&session->cond_lock); + + list_del_init(&task->link_session); + list_add_tail(&task->link_session, &session->list_done); + + return ret; +} + +static MppDevBatServ *bat_server_get(MppDevServer *srv, MppClientType client_type) +{ + MppDevBatServ *server = NULL; + char timer_name[32]; + + mpp_mutex_lock(&srv->lock); + + server = srv->bat_server[client_type]; + if (server) { + mpp_mutex_unlock(&srv->lock); + return server; + } + + server = mpp_calloc(MppDevBatServ, 1); + if (!server) { + mpp_err("mpp server failed to get bat server\n"); + mpp_mutex_unlock(&srv->lock); + return NULL; + } + + server->server_fd = open(srv->server_name, O_RDWR | O_CLOEXEC); + if (server->server_fd < 0) { + mpp_err("mpp server get bat server failed to open device\n"); + goto failed; + } + + snprintf(timer_name, sizeof(timer_name) - 1, "%s_bat", + strof_client_type(client_type)); + + server->timer = mpp_timer_get(timer_name); + if (!server->timer) { + mpp_err("mpp server get bat server failed to create timer\n"); + goto failed; + } + + mpp_mutex_init(&server->lock); + + mpp_timer_set_callback(server->timer, mpp_server_thread, server); + /* 10ms */ + mpp_timer_set_timing(server->timer, 10, 10); + + INIT_LIST_HEAD(&server->session_list); + INIT_LIST_HEAD(&server->list_batch); + INIT_LIST_HEAD(&server->list_batch_free); + INIT_LIST_HEAD(&server->pending_task); + + server->batch_pool = srv->batch_pool; + server->max_task_in_batch = srv->max_task_in_batch; + + srv->bat_server[client_type] = server; + mpp_mutex_unlock(&srv->lock); + + return server; + +failed: + if (server) { + if (server->timer) { + mpp_timer_put(server->timer); + server->timer = NULL; + } + + if (server->server_fd >= 0) { + close(server->server_fd); + server->server_fd = -1; + } + mpp_mutex_destroy(&server->lock); + } + MPP_FREE(server); + mpp_mutex_unlock(&srv->lock); + + return NULL; +} + +static rk_s32 bat_server_put(MppDevServer *srv, MppClientType client_type) +{ + MppDevBatServ *server = NULL; + MppDevBatTask *batch, *n; + + mpp_mutex_lock(&srv->lock); + + if (!srv->bat_server[client_type]) { + mpp_mutex_unlock(&srv->lock); + return rk_ok; + } + + server = srv->bat_server[client_type]; + srv->bat_server[client_type] = NULL; + + mpp_assert(server->batch_run == 0); + mpp_assert(list_empty(&server->list_batch)); + mpp_assert(server->pending_count == 0); + + /* stop thread first */ + if (server->timer) { + mpp_timer_put(server->timer); + server->timer = NULL; + } + + if (server->batch_free) { + list_for_each_entry_safe(batch, n, &server->list_batch_free, MppDevBatTask, link_server) { + batch_del(server, batch); + } + } else { + mpp_assert(list_empty(&server->list_batch_free)); + } + + if (server->server_fd >= 0) { + close(server->server_fd); + server->server_fd = -1; + } + mpp_mutex_destroy(&server->lock); + MPP_FREE(server); + mpp_mutex_unlock(&srv->lock); + + return rk_ok; +} + +static rk_s32 server_attach(MppDevServer *srv, MppDevMppService *ctx) +{ + MppClientType client_type = (MppClientType)ctx->client_type; + MppDevBatServ *server; + MppDevSession *session; + rk_u32 i; + + if (client_type < 0 || client_type >= VPU_CLIENT_BUTT) { + mpp_err("mpp server attach failed with invalid client type %d\n", client_type); + return rk_nok; + } + + /* if client type server is not created create it first */ + server = bat_server_get(srv, client_type); + if (!server) { + mpp_err("mpp server get bat server with client type %d failed\n", client_type); + return rk_nok; + } + + mpp_mutex_lock(&srv->lock); + if (ctx->serv_ctx) { + mpp_mutex_unlock(&srv->lock); + return rk_ok; + } + + session = (MppDevSession *)mpp_mem_pool_get_f(srv->session_pool); + + INIT_LIST_HEAD(&session->list_server); + INIT_LIST_HEAD(&session->list_wait); + INIT_LIST_HEAD(&session->list_done); + + session->ctx = ctx; + session->server = server; + session->client = ctx->client; + mpp_mutex_cond_init(&session->cond_lock); + session->task_wait = 0; + session->task_done = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(session->tasks); i++) { + MppDevTask *task = &session->tasks[i]; + + INIT_LIST_HEAD(&task->link_server); + INIT_LIST_HEAD(&task->link_session); + INIT_LIST_HEAD(&task->link_batch); + task->session = session; + task->batch = NULL; + task->task_id = -1; + task->slot_idx = i; + + list_add_tail(&task->link_session, &session->list_done); + } + + list_add_tail(&session->list_server, &server->session_list); + ctx->serv_ctx = session; + + if (srv->enable) { + ctx->batch_io = 1; + ctx->server = server->server_fd; + } else { + ctx->batch_io = 0; + ctx->server = ctx->client; + } + + server->batch_max_count++; + server->session_count++; + mpp_mutex_unlock(&srv->lock); + + return rk_ok; +} + +static rk_s32 server_detach(MppDevServer *srv, MppDevMppService *ctx) +{ + MppClientType client_type = (MppClientType)ctx->client_type; + MppDevBatServ *server = bat_server_get(srv, client_type); + MppDevSession *session = (MppDevSession *)ctx->serv_ctx; + + mpp_assert(server); + + mpp_mutex_lock(&srv->lock); + if (!ctx->serv_ctx) { + mpp_mutex_unlock(&srv->lock); + return rk_ok; + } + + ctx->server = ctx->client; + ctx->serv_ctx = NULL; + ctx->batch_io = 0; + + mpp_assert(server); + mpp_assert(session); + mpp_assert(session->client == ctx->client); + mpp_assert(session->task_wait == session->task_done); + mpp_assert(list_empty(&session->list_wait)); + + list_del_init(&session->list_server); + + mpp_mutex_cond_destroy(&session->cond_lock); + + mpp_mem_pool_put_f(srv->session_pool, session); + server->batch_max_count++; + server->session_count++; + + mpp_mutex_unlock(&srv->lock); + + return rk_ok; +} + +static void server_clear(MppDevServer *srv) +{ + if (srv) { + if (srv->session_pool) { + mpp_mem_pool_deinit_f(srv->session_pool); + srv->session_pool = NULL; + } + + if (srv->batch_pool) { + mpp_mem_pool_deinit_f(srv->batch_pool); + srv->batch_pool = NULL; + } + + srv->inited = 0; + srv->enable = 0; + + mpp_free(srv); + } +} + +static void mpp_server_init() +{ + MppDevServer *srv = srv_server; + rk_s32 batch_task_size = 0; + + if (srv) + return; + + srv = mpp_calloc(MppDevServer, 1); + if (!srv) { + mpp_err_f("failed to allocate mpp_server service\n"); + return; + } + + srv_server = srv; + + srv->server_error = NULL; + srv->server_name = NULL; + srv->inited = 0; + srv->enable = 1; + srv->session_pool = NULL; + srv->batch_pool = NULL; + srv->max_task_in_batch = 0; + srv->cmd_cap = NULL; + + mpp_env_get_u32("mpp_server_debug", &mpp_server_debug, 0); + mpp_env_get_u32("mpp_server_enable", &srv->enable, 1); + mpp_env_get_u32("mpp_server_batch_task", (rk_u32 *)&srv->max_task_in_batch, + MAX_BATCH_TASK); + + mpp_assert(srv->max_task_in_batch >= 1 && srv->max_task_in_batch <= 32); + batch_task_size = sizeof(MppDevBatTask) + srv->max_task_in_batch * + (sizeof(MppReqV1) * (MAX_REQ_SEND_CNT + MAX_REQ_WAIT_CNT) + + sizeof(MppDevBatCmd)); + + srv->cmd_cap = mpp_get_mpp_service_cmd_cap(); + if (rk_ok != mpp_service_check_cmd_valid(MPP_CMD_SET_SESSION_FD, srv->cmd_cap)) { + srv->server_error = "mpp_service cmd not support"; + return; + } + + mpp_mutex_init(&srv->lock); + memset(srv->bat_server, 0, sizeof(srv->bat_server)); + + do { + srv->server_name = mpp_get_mpp_service_name(); + if (!srv->server_name) { + srv->server_error = "get service device failed"; + break; + } + + srv->session_pool = mpp_mem_pool_init_f("server_session", sizeof(MppDevSession)); + if (!srv->session_pool) { + srv->server_error = "create session pool failed"; + break; + } + + srv->batch_pool = mpp_mem_pool_init_f("server_batch", batch_task_size); + if (!srv->batch_pool) { + srv->server_error = "create batch tack pool failed"; + break; + } + + srv->inited = 1; + } while (0); + + if (!srv->inited) { + server_clear(srv); + srv_server = NULL; + } +} + +static void mpp_server_deinit() +{ + MppDevServer *srv = srv_server; + + srv_server = NULL; + + if (srv) { + rk_s32 i; + + for (i = 0; i < VPU_CLIENT_BUTT; i++) + bat_server_put(srv, (MppClientType)i); + + mpp_mutex_destroy(&srv->lock); + server_clear(srv); + } +} + +rk_s32 mpp_server_attach(MppDev ctx) +{ + MppDevServer *srv = get_srv_server(); + rk_s32 ret = rk_nok; + + if (srv && ctx) { + MppDevMppService *dev = (MppDevMppService *)ctx; + + ret = server_attach(srv, dev); + } + + return ret; +} + +rk_s32 mpp_server_detach(MppDev ctx) +{ + MppDevServer *srv = get_srv_server(); + rk_s32 ret = rk_nok; + + if (srv && ctx) { + MppDevMppService *dev = (MppDevMppService *)ctx; + + ret = server_detach(srv, dev); + } + + return ret; +} + +rk_s32 mpp_server_send_task(MppDev ctx) +{ + MppDevServer *srv = get_srv_server(); + rk_s32 ret = rk_nok; + + if (srv && ctx) + ret = send_task((MppDevMppService *)ctx); + + return ret; +} + +rk_s32 mpp_server_wait_task(MppDev ctx, rk_s64 timeout) +{ + MppDevServer *srv = get_srv_server(); + rk_s32 ret = rk_nok; + + if (srv && ctx) + ret = wait_task((MppDevMppService *)ctx, timeout); + + return ret; +} + +MPP_SINGLETON(MPP_SGLN_SERVER, mpp_server, mpp_server_init, mpp_server_deinit) diff --git a/osal/driver/mpp_service.c b/osal/driver/mpp_service.c new file mode 100644 index 000000000..526c4fd8f --- /dev/null +++ b/osal/driver/mpp_service.c @@ -0,0 +1,854 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_serivce" + +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "osal_2str.h" + +#include "mpp_device_debug.h" +#include "mpp_service_api.h" +#include "mpp_service_impl.h" +#include "mpp_server.h" + +typedef struct MppServiceQueryCfg_t { + RK_U32 cmd_butt; + const char *name; +} MppServiceQueryCfg; + +static const MppServiceQueryCfg query_cfg[] = { + { MPP_CMD_QUERY_BASE, "query_cmd", }, + { MPP_CMD_INIT_BASE, "init_cmd", }, + { MPP_CMD_SEND_BASE, "send_cmd", }, + { MPP_CMD_POLL_BASE, "poll_cmd", }, + { MPP_CMD_CONTROL_BASE, "control_cmd", }, +}; + +static const RK_U32 query_count = MPP_ARRAY_ELEMS(query_cfg); + +const char *mpp_get_mpp_service_name(void) +{ + static const char *mpp_service_name = NULL; + static const char *mpp_service_dev[] = { + "/dev/mpp_service", + "/dev/mpp-service", + }; + + if (mpp_service_name) + return mpp_service_name; + + if (!access(mpp_service_dev[0], F_OK | R_OK | W_OK)) { + mpp_service_name = mpp_service_dev[0]; + } else if (!access(mpp_service_dev[1], F_OK | R_OK | W_OK)) + mpp_service_name = mpp_service_dev[1]; + + return mpp_service_name; +} + +RK_S32 mpp_service_ioctl(RK_S32 fd, RK_U32 cmd, RK_U32 size, void *param) +{ + MppReqV1 mpp_req; + + memset(&mpp_req, 0, sizeof(mpp_req)); + + mpp_req.cmd = cmd; + mpp_req.flag = 0; + mpp_req.size = size; + mpp_req.offset = 0; + mpp_req.data_ptr = REQ_DATA_PTR(param); + + return (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &mpp_req); +} + +RK_S32 mpp_service_ioctl_request(RK_S32 fd, MppReqV1 *req) +{ + return (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, req); +} + +MPP_RET mpp_service_check_cmd_valid(RK_U32 cmd, const MppServiceCmdCap *cap) +{ + RK_U32 found = 0; + + if (cap->support_cmd > 0) { + found = (cmd < cap->query_cmd) ? 1 : 0; + found = (cmd >= MPP_CMD_INIT_BASE && cmd < cap->init_cmd) ? 1 : found; + found = (cmd >= MPP_CMD_SEND_BASE && cmd < cap->send_cmd) ? 1 : found; + found = (cmd >= MPP_CMD_POLL_BASE && cmd < cap->poll_cmd) ? 1 : found; + found = (cmd >= MPP_CMD_CONTROL_BASE && cmd < cap->ctrl_cmd) ? 1 : found; + } else { + /* old kernel before support_cmd query is valid */ + found = (cmd >= MPP_CMD_INIT_BASE && cmd <= MPP_CMD_INIT_TRANS_TABLE) ? 1 : found; + found = (cmd >= MPP_CMD_SEND_BASE && cmd <= MPP_CMD_SET_REG_ADDR_OFFSET) ? 1 : found; + found = (cmd >= MPP_CMD_POLL_BASE && cmd <= MPP_CMD_POLL_HW_FINISH) ? 1 : found; + found = (cmd >= MPP_CMD_CONTROL_BASE && cmd <= MPP_CMD_RELEASE_FD) ? 1 : found; + } + + return (found != 0) ? MPP_OK : MPP_NOK; +} + +void check_mpp_service_cap(RK_U32 *codec_type, RK_U32 *hw_ids, MppServiceCmdCap *cap) +{ + MppReqV1 mpp_req; + RK_S32 fd = -1; + RK_S32 ret = 0; + RK_U32 *cmd_butt = &cap->query_cmd;; + RK_U32 hw_support = 0; + RK_U32 val; + RK_U32 i; + + /* for device check on startup */ + mpp_env_get_u32("mpp_device_debug", &mpp_device_debug, 0); + + *codec_type = 0; + memset(hw_ids, 0, sizeof(RK_U32) * 32); + + /* check hw_support flag for valid client type */ + fd = open(mpp_get_mpp_service_name(), O_RDWR | O_CLOEXEC); + if (fd < 0) { + mpp_err("open mpp_service to check cmd capability failed\n"); + memset(cap, 0, sizeof(*cap)); + return ; + } + ret = mpp_service_ioctl(fd, MPP_CMD_PROBE_HW_SUPPORT, 0, &hw_support); + if (!ret) { + mpp_dev_dbg_probe("vcodec_support %08x\n", hw_support); + *codec_type = hw_support; + } + cap->support_cmd = !access("/proc/mpp_service/supports-cmd", F_OK) || + !access("/proc/mpp_service/support_cmd", F_OK); + if (cap->support_cmd) { + for (i = 0; i < query_count; i++, cmd_butt++) { + const MppServiceQueryCfg *cfg = &query_cfg[i]; + + memset(&mpp_req, 0, sizeof(mpp_req)); + + val = cfg->cmd_butt; + mpp_req.cmd = MPP_CMD_QUERY_CMD_SUPPORT; + mpp_req.data_ptr = REQ_DATA_PTR(&val); + + ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &mpp_req); + if (ret) + mpp_err_f("query %-11s support error %s.\n", cfg->name, strerror(errno)); + else { + *cmd_butt = val; + mpp_dev_dbg_probe("query %-11s support %04x\n", cfg->name, val); + } + } + } + close(fd); + + /* check each valid client type for hw_id */ + /* kernel need to set client type then get hw_id */ + for (i = 0; i < 32; i++) { + if (hw_support & (1 << i)) { + val = i; + + fd = open(mpp_get_mpp_service_name(), O_RDWR | O_CLOEXEC); + if (fd < 0) { + mpp_err("open mpp_service to check cmd capability failed\n"); + break; + } + /* set client type first */ + ret = mpp_service_ioctl(fd, MPP_CMD_INIT_CLIENT_TYPE, sizeof(val), &val); + if (ret) { + mpp_err("check valid client type %d failed\n", i); + } else { + /* then get hw_id */ + ret = mpp_service_ioctl(fd, MPP_CMD_QUERY_HW_ID, sizeof(val), &val); + if (!ret) { + mpp_dev_dbg_probe("client %-10s hw_id %08x\n", + strof_client_type((MppClientType)i), val); + hw_ids[i] = val; + } else + mpp_err("check valid client %-10s for hw_id failed\n", + strof_client_type((MppClientType)i)); + } + close(fd); + } + } +} + +MppReqV1 *mpp_service_next_req(MppDevMppService *p) +{ + MppReqV1 *mpp_req = NULL; + + if (p->req_cnt >= p->req_max) { + mpp_dev_dbg_msg("enlarge request count %d -> %d\n", + p->req_max, p->req_max * 2); + p->reqs = mpp_realloc(p->reqs, MppReqV1, p->req_max * 2); + if (NULL == p->reqs) { + mpp_err_f("failed to enlarge request buffer\n"); + return NULL; + } + + p->req_max *= 2; + } + + mpp_req = &p->reqs[p->req_cnt++]; + + return mpp_req; +} + +RegOffsetInfo *mpp_service_next_reg_offset(MppDevMppService *p) +{ + RegOffsetInfo *info = NULL; + + if (p->reg_offset_count + p->reg_offset_pos >= p->reg_offset_max) { + RegOffsetInfo *orig = p->reg_offset_info; + + mpp_dev_dbg_msg("enlarge reg offset count %d -> %d\n", + p->reg_offset_max, p->reg_offset_max * 2); + p->reg_offset_info = mpp_realloc(p->reg_offset_info, RegOffsetInfo, p->reg_offset_max * 2); + if (NULL == p->reg_offset_info) { + mpp_err_f("failed to enlarge request buffer\n"); + return NULL; + } + if (orig != p->reg_offset_info) + mpp_logw_f("enlarge reg offset buffer and get different pointer\n"); + + p->reg_offset_max *= 2; + } + + info = &p->reg_offset_info[p->reg_offset_count + p->reg_offset_pos]; + mpp_dev_dbg_msg("reg offset %d : %d\n", p->reg_offset_pos, p->reg_offset_count); + p->reg_offset_count++; + + return info; +} + + +RcbInfo *mpp_service_next_rcb_info(MppDevMppService *p) +{ + RcbInfo *info = NULL; + + if (p->rcb_count + p->rcb_pos >= p->rcb_max) { + mpp_dev_dbg_msg("enlarge rcb info count %d -> %d\n", + p->rcb_max, p->rcb_max * 2); + p->rcb_info = mpp_realloc(p->rcb_info, RcbInfo, p->rcb_max * 2); + if (NULL == p->rcb_info) { + mpp_err_f("failed to enlarge request buffer\n"); + return NULL; + } + + p->rcb_max *= 2; + } + + info = &p->rcb_info[p->rcb_count + p->rcb_pos]; + mpp_dev_dbg_msg("rcb info %d : %d\n", p->rcb_pos, p->rcb_count); + p->rcb_count++; + + return info; +} + +static MPP_RET mpp_service_ioc_attach_fd(MppDevBufMapNode *node) +{ + MppReqV1 mpp_req; + RK_S32 fd = node->buf_fd; + MPP_RET ret; + + mpp_req.cmd = MPP_CMD_TRANS_FD_TO_IOVA; + mpp_req.flag = MPP_FLAGS_LAST_MSG; + mpp_req.size = sizeof(RK_U32); + mpp_req.offset = 0; + mpp_req.data_ptr = REQ_DATA_PTR(&fd); + + ret = mpp_service_ioctl_request(node->dev_fd, &mpp_req); + if (ret) { + mpp_err_f("failed ret %d errno %d %s\n", ret, errno, strerror(errno)); + node->iova = (RK_U32)(-1); + } else { + node->iova = (RK_U32)fd; + } + + return ret; +} + +static MPP_RET mpp_service_ioc_detach_fd(MppDevBufMapNode *node) +{ + RK_S32 fd = node->buf_fd; + MppReqV1 mpp_req; + MPP_RET ret; + + mpp_req.cmd = MPP_CMD_RELEASE_FD; + mpp_req.flag = MPP_FLAGS_LAST_MSG; + mpp_req.size = sizeof(RK_U32); + mpp_req.offset = 0; + mpp_req.data_ptr = REQ_DATA_PTR(&fd); + + ret = mpp_service_ioctl_request(node->dev_fd, &mpp_req); + if (ret) { + mpp_err_f("failed ret %d errno %d %s\n", ret, errno, strerror(errno)); + } + node->iova = (RK_U32)(-1); + return ret; +} + +MPP_RET mpp_service_init(void *ctx, MppClientType type) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MPP_RET ret = MPP_NOK; + + p->cap = mpp_get_mpp_service_cmd_cap(); + p->client = open(mpp_get_mpp_service_name(), O_RDWR | O_CLOEXEC); + if (p->client < 0) { + mpp_err("open mpp_service failed\n"); + return ret; + } + + /* set client type first */ + ret = mpp_service_ioctl(p->client, MPP_CMD_INIT_CLIENT_TYPE, sizeof(type), &type); + if (ret) + mpp_err("set client type %d failed\n", type); + + mpp_assert(p->cap); + if (MPP_OK == mpp_service_check_cmd_valid(MPP_CMD_SEND_CODEC_INFO, p->cap)) + p->support_set_info = 1; + if (MPP_OK == mpp_service_check_cmd_valid(MPP_CMD_SET_RCB_INFO, p->cap)) { + RK_U32 disable_rcb_info = 0; + + mpp_env_get_u32("disable_rcb_info", &disable_rcb_info, 0); + p->support_set_rcb_info = !disable_rcb_info; + } + if (MPP_OK == mpp_service_check_cmd_valid(MPP_CMD_POLL_HW_IRQ, p->cap)) + p->support_hw_irq = 1; + + /* default server fd is the opened client fd */ + p->client_type = type; + p->server = p->client; + p->batch_io = 0; + p->serv_ctx = NULL; + p->dev_cb = NULL; + + p->bat_cmd.flag = 0; + p->bat_cmd.client = p->client; + p->bat_cmd.ret = 0; + + p->req_max = MAX_REQ_NUM; + p->reqs = mpp_malloc(MppReqV1, p->req_max); + if (NULL == p->reqs) { + mpp_err("create request buffer failed\n"); + ret = MPP_ERR_MALLOC; + } + + p->reg_offset_max = MAX_REG_OFFSET; + p->reg_offset_info = mpp_malloc(RegOffsetInfo, p->reg_offset_max); + if (NULL == p->reg_offset_info) { + mpp_err("create register offset buffer failed\n"); + ret = MPP_ERR_MALLOC; + } + p->reg_offset_pos = 0; + p->reg_offset_count = 0; + + p->rcb_max = MAX_RCB_OFFSET; + p->rcb_info = mpp_malloc(RcbInfo, p->rcb_max); + if (NULL == p->rcb_info) { + mpp_err("create rcb info buffer failed\n"); + ret = MPP_ERR_MALLOC; + } + p->rcb_pos = 0; + p->rcb_count = 0; + + INIT_LIST_HEAD(&p->list_bufs); + { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p->lock_bufs, &attr); + pthread_mutexattr_destroy(&attr); + } + return ret; +} + +MPP_RET mpp_service_deinit(void *ctx) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MppDevBufMapNode *pos, *n; + + pthread_mutex_lock(&p->lock_bufs); + list_for_each_entry_safe(pos, n, &p->list_bufs, MppDevBufMapNode, list_dev) { + pthread_mutex_t *lock_buf = pos->lock_buf; + + mpp_assert(pos->lock_buf && pos->lock_dev); + mpp_assert(pos->lock_dev == &p->lock_bufs); + + pthread_mutex_lock(lock_buf); + + list_del_init(&pos->list_dev); + list_del_init(&pos->list_buf); + pos->lock_buf = NULL; + pos->lock_dev = NULL; + mpp_service_ioc_detach_fd(pos); + mpp_mem_pool_put_f(pos->pool, pos); + + pthread_mutex_unlock(lock_buf); + } + pthread_mutex_unlock(&p->lock_bufs); + pthread_mutex_destroy(&p->lock_bufs); + + if (p->batch_io) + mpp_server_detach(p); + + if (p->client) + close(p->client); + + MPP_FREE(p->reqs); + MPP_FREE(p->reg_offset_info); + MPP_FREE(p->rcb_info); + + return MPP_OK; +} + +MPP_RET mpp_service_attach(void *ctx) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + + if (p->req_cnt) { + mpp_err_f("can not switch on bat mode when service working\n"); + return MPP_NOK; + } + + if (!p->batch_io) + mpp_server_attach(p); + + return MPP_OK; +} + +MPP_RET mpp_service_detach(void *ctx) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + + if (p->req_cnt) { + mpp_err_f("can not switch off bat mode when service working\n"); + return MPP_NOK; + } + + if (p->batch_io) + mpp_server_detach(p); + + return MPP_OK; +} + +MPP_RET mpp_service_delimit(void *ctx) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MppReqV1 *mpp_req = NULL; + + /* set fd trans info if needed */ + if (p->reg_offset_count) { + mpp_req = mpp_service_next_req(p); + + mpp_req->cmd = MPP_CMD_SET_REG_ADDR_OFFSET; + mpp_req->flag = MPP_FLAGS_REG_OFFSET_ALONE; + mpp_req->size = (p->reg_offset_count) * sizeof(RegOffsetInfo); + mpp_req->offset = 0; + mpp_req->data_ptr = REQ_DATA_PTR(&p->reg_offset_info[p->reg_offset_pos]); + p->reg_offset_pos += p->reg_offset_count; + p->reg_offset_count = 0; + } + + /* set rcb offst info if needed */ + if (p->rcb_count) { + mpp_req = mpp_service_next_req(p); + + mpp_req->cmd = MPP_CMD_SET_RCB_INFO; + mpp_req->flag = 0; + mpp_req->size = p->rcb_count * sizeof(RcbInfo); + mpp_req->offset = 0; + mpp_req->data_ptr = REQ_DATA_PTR(&p->rcb_info[p->rcb_pos]); + p->rcb_pos += p->rcb_count; + p->rcb_count = 0; + } + + mpp_req = mpp_service_next_req(p); + mpp_req->cmd = MPP_CMD_SET_SESSION_FD; + mpp_req->flag = MPP_FLAGS_MULTI_MSG; + mpp_req->offset = 0; + mpp_req->size = sizeof(p->bat_cmd); + mpp_req->data_ptr = REQ_DATA_PTR(&p->bat_cmd); + + return MPP_OK; +} + +MPP_RET mpp_service_set_cb_ctx(void *ctx, MppCbCtx *cb_ctx) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + + p->dev_cb = cb_ctx; + + return MPP_OK; +} + +MPP_RET mpp_service_reg_wr(void *ctx, MppDevRegWrCfg *cfg) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MppReqV1 *mpp_req = mpp_service_next_req(p); + + mpp_req->cmd = MPP_CMD_SET_REG_WRITE; + mpp_req->flag = 0; + mpp_req->size = cfg->size; + mpp_req->offset = cfg->offset; + mpp_req->data_ptr = REQ_DATA_PTR(cfg->reg); + + return MPP_OK; +} + +MPP_RET mpp_service_reg_rd(void *ctx, MppDevRegRdCfg *cfg) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MppReqV1 *mpp_req = mpp_service_next_req(p); + + mpp_req->cmd = MPP_CMD_SET_REG_READ; + mpp_req->flag = 0; + mpp_req->size = cfg->size; + mpp_req->offset = cfg->offset; + mpp_req->data_ptr = REQ_DATA_PTR(cfg->reg); + + return MPP_OK; +} + +MPP_RET mpp_service_reg_offset(void *ctx, MppDevRegOffsetCfg *cfg) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + RegOffsetInfo *info; + RK_S32 i; + + if (!cfg->offset) + return MPP_OK; + + if (p->reg_offset_count >= MAX_REG_OFFSET) { + mpp_err_f("reach max offset definition\n", MAX_REG_OFFSET); + return MPP_NOK; + } + + for (i = 0; i < p->reg_offset_count; i++) { + info = &p->reg_offset_info[p->reg_offset_pos + i]; + + if (info->reg_idx == cfg->reg_idx) { + mpp_err_f("reg[%d] offset has been set, cover old %d -> %d\n", + info->reg_idx, info->offset, cfg->offset); + info->offset = cfg->offset; + return MPP_OK; + } + } + + info = mpp_service_next_reg_offset(p); + info->reg_idx = cfg->reg_idx; + info->offset = cfg->offset; + + return MPP_OK; +} + +MPP_RET mpp_service_reg_offsets(void *ctx, MppDevRegOffCfgs *cfgs) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + RegOffsetInfo *info; + RK_S32 i; + + if (cfgs->count <= 0) + return MPP_OK; + + if (p->reg_offset_count >= MAX_REG_OFFSET || + p->reg_offset_count + cfgs->count >= MAX_REG_OFFSET) { + mpp_err_f("reach max offset definition\n", MAX_REG_OFFSET); + return MPP_NOK; + } + + for (i = 0; i < cfgs->count; i++) { + MppDevRegOffsetCfg *cfg = &cfgs->cfgs[i]; + RK_S32 j; + + for (j = 0; j < p->reg_offset_count; j++) { + info = &p->reg_offset_info[p->reg_offset_pos + j]; + + if (info->reg_idx == cfg->reg_idx) { + mpp_err_f("reg[%d] offset has been set, cover old %d -> %d\n", + info->reg_idx, info->offset, cfg->offset); + info->offset = cfg->offset; + continue; + } + } + + info = mpp_service_next_reg_offset(p);; + info->reg_idx = cfg->reg_idx; + info->offset = cfg->offset; + } + + return MPP_OK; +} + +MPP_RET mpp_service_rcb_info(void *ctx, MppDevRcbInfoCfg *cfg) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + + if (!p->support_set_rcb_info) + return MPP_OK; + + if (p->rcb_count >= MAX_RCB_OFFSET) { + mpp_err_f("reach max offset definition\n", MAX_RCB_OFFSET); + return MPP_NOK; + } + + RcbInfo *info = mpp_service_next_rcb_info(p); + + info->reg_idx = cfg->reg_idx; + info->size = cfg->size; + + return MPP_OK; +} + +MPP_RET mpp_service_set_info(void *ctx, MppDevInfoCfg *cfg) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + + if (!p->support_set_info) + return MPP_OK; + + if (!p->info_count) + memset(p->info, 0, sizeof(p->info)); + + memcpy(&p->info[p->info_count], cfg, sizeof(MppDevInfoCfg)); + p->info_count++; + + return MPP_OK; +} + +MPP_RET mpp_service_set_err_ref_hack(void *ctx, RK_U32 *enable) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MppReqV1 mpp_req; + + mpp_req.cmd = MPP_CMD_SET_ERR_REF_HACK; + mpp_req.flag = MPP_FLAGS_LAST_MSG; + mpp_req.size = sizeof(RK_U32); + mpp_req.offset = 0; + mpp_req.data_ptr = REQ_DATA_PTR(enable); + + return mpp_service_ioctl_request(p->client, &mpp_req); +} + +MPP_RET mpp_service_lock_map(void *ctx) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + + mpp_dev_dbg_buf("dev %d lock mapping\n", p->client); + pthread_mutex_lock(&p->lock_bufs); + return MPP_OK; +} + +MPP_RET mpp_service_unlock_map(void *ctx) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + + mpp_dev_dbg_buf("dev %d unlock mapping\n", p->client); + pthread_mutex_unlock(&p->lock_bufs); + return MPP_OK; +} + +MPP_RET mpp_service_attach_fd(void *ctx, MppDevBufMapNode *node) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MPP_RET ret; + + mpp_assert(node->buffer); + mpp_assert(node->lock_buf); + mpp_assert(node->buf_fd >= 0); + + node->lock_dev = &p->lock_bufs; + node->dev_fd = p->client; + ret = mpp_service_ioc_attach_fd(node); + if (ret) { + node->lock_dev = NULL; + node->dev_fd = -1; + list_del_init(&node->list_dev); + } else { + list_add_tail(&node->list_dev, &p->list_bufs); + } + + mpp_dev_dbg_buf("node %p dev %d attach fd %d iova %x\n", + node, node->dev_fd, node->buf_fd, node->iova); + + return ret; +} + +MPP_RET mpp_service_detach_fd(void *ctx, MppDevBufMapNode *node) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MPP_RET ret; + + mpp_assert(node->buffer); + mpp_assert(node->lock_buf); + mpp_assert(node->buf_fd >= 0); + mpp_assert(node->dev_fd >= 0); + mpp_assert(node->lock_dev == &p->lock_bufs); + + mpp_dev_dbg_buf("node %p dev %d detach fd %d iova %x\n", + node, node->dev_fd, node->buf_fd, node->iova); + + ret = mpp_service_ioc_detach_fd(node); + node->dev = NULL; + node->dev_fd = -1; + node->lock_dev = NULL; + list_del_init(&node->list_dev); + + return ret; +} + +MPP_RET mpp_service_cmd_send(void *ctx) +{ + MPP_RET ret = MPP_OK; + MppDevMppService *p = (MppDevMppService *)ctx; + + if (p->req_cnt <= 0 || p->req_cnt > p->req_max) { + mpp_err_f("ctx %p invalid request count %d\n", ctx, p->req_cnt); + return MPP_ERR_VALUE; + } + + if (p->info_count) { + if (p->support_set_info) { + MppReqV1 mpp_req; + + mpp_req.cmd = MPP_CMD_SEND_CODEC_INFO; + mpp_req.flag = MPP_FLAGS_LAST_MSG; + mpp_req.size = p->info_count * sizeof(p->info[0]); + mpp_req.offset = 0; + mpp_req.data_ptr = REQ_DATA_PTR(p->info); + + ret = mpp_service_ioctl_request(p->client, &mpp_req); + if (ret) + p->support_set_info = 0; + } + p->info_count = 0; + } + + /* set fd trans info if needed */ + if (p->reg_offset_count) { + MppReqV1 *mpp_req = mpp_service_next_req(p); + + mpp_req->cmd = MPP_CMD_SET_REG_ADDR_OFFSET; + mpp_req->flag = MPP_FLAGS_REG_OFFSET_ALONE; + mpp_req->size = (p->reg_offset_count) * sizeof(RegOffsetInfo); + mpp_req->offset = 0; + mpp_req->data_ptr = REQ_DATA_PTR(&p->reg_offset_info[p->reg_offset_pos]); + p->reg_offset_pos += p->reg_offset_count; + } + + /* set rcb offst info if needed */ + if (p->rcb_count) { + MppReqV1 *mpp_req = mpp_service_next_req(p); + + mpp_req->cmd = MPP_CMD_SET_RCB_INFO; + mpp_req->flag = 0; + mpp_req->size = p->rcb_count * sizeof(RcbInfo); + mpp_req->offset = 0; + mpp_req->data_ptr = REQ_DATA_PTR(&p->rcb_info[p->rcb_pos]); + p->rcb_pos += p->rcb_count; + } + + /* setup flag for multi message request */ + if (p->req_cnt > 1) { + RK_S32 i; + + for (i = 0; i < p->req_cnt; i++) + p->reqs[i].flag |= MPP_FLAGS_MULTI_MSG; + } + p->reqs[p->req_cnt - 1].flag |= MPP_FLAGS_LAST_MSG | MPP_FLAGS_REG_OFFSET_ALONE; + + if (p->batch_io) { + ret = mpp_server_send_task(ctx); + if (ret) + mpp_err_f("send task to server ret %d\n", ret); + } else { + ret = mpp_service_ioctl_request(p->server, &p->reqs[0]); + if (ret) { + mpp_err_f("ioctl MPP_IOC_CFG_V1 failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + } + + p->req_cnt = 0; + p->reg_offset_count = 0; + p->reg_offset_pos = 0; + p->rcb_count = 0; + p->rcb_pos = 0; + p->rcb_count = 0; + return ret; +} + +MPP_RET mpp_service_cmd_poll(void *ctx, MppDevPollCfg *cfg) +{ + MppDevMppService *p = (MppDevMppService *)ctx; + MPP_RET ret = MPP_OK; + + if (p->batch_io) { + ret = mpp_server_wait_task(ctx, 0); + } else { + MppReqV1 dev_req; + + memset(&dev_req, 0, sizeof(dev_req)); + + if (p->support_hw_irq && cfg) { + dev_req.cmd = MPP_CMD_POLL_HW_IRQ; + dev_req.flag |= MPP_FLAGS_LAST_MSG | MPP_FLAGS_REG_OFFSET_ALONE; + + dev_req.size = sizeof(*cfg) + cfg->count_max * sizeof(cfg->slice_info[0]); + dev_req.offset = 0; + dev_req.data_ptr = REQ_DATA_PTR(cfg); + } else { + dev_req.cmd = MPP_CMD_POLL_HW_FINISH; + dev_req.flag |= MPP_FLAGS_LAST_MSG | MPP_FLAGS_REG_OFFSET_ALONE; + + if (cfg) { + mpp_assert(cfg->count_max); + if (cfg->count_max) { + cfg->count_ret = 1; + cfg->slice_info[0].val = 0; + cfg->slice_info[0].last = 1; + } + } + } + + ret = mpp_service_ioctl_request(p->server, &dev_req); + if (ret) { + mpp_err_f("ioctl MPP_IOC_CFG_V1 failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + } + + return ret; +} + +const MppDevApi mpp_service_api = { + "mpp_service", + sizeof(MppDevMppService), + mpp_service_init, + mpp_service_deinit, + mpp_service_attach, + mpp_service_detach, + mpp_service_delimit, + mpp_service_set_cb_ctx, + mpp_service_reg_wr, + mpp_service_reg_rd, + mpp_service_reg_offset, + mpp_service_reg_offsets, + mpp_service_rcb_info, + mpp_service_set_info, + mpp_service_set_err_ref_hack, + mpp_service_lock_map, + mpp_service_unlock_map, + mpp_service_attach_fd, + mpp_service_detach_fd, + mpp_service_cmd_send, + mpp_service_cmd_poll, +}; diff --git a/osal/driver/mpp_vcodec_client.c b/osal/driver/mpp_vcodec_client.c new file mode 100644 index 000000000..74d5a273b --- /dev/null +++ b/osal/driver/mpp_vcodec_client.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_vcodec" + +#include +#include +#include +#include + +#include "mpp_log.h" +#include "mpp_env.h" +#include "mpp_common.h" +#include "mpp_vcodec_client.h" + +#define VOCDEC_IOC_MAGIC 'V' +#define VOCDEC_IOC_CFG _IOW(VOCDEC_IOC_MAGIC, 1, unsigned int) + +typedef struct vcodec_req_t { + RK_U32 cmd; + RK_U32 ctrl_cmd; + RK_U32 size; + RK_U64 data; +} vcodec_req; + +#if __SIZEOF_POINTER__ == 4 +#define REQ_DATA_PTR(ptr) ((RK_U32)ptr) +#elif __SIZEOF_POINTER__ == 8 +#define REQ_DATA_PTR(ptr) ((RK_U64)ptr) +#endif + +RK_S32 mpp_vcodec_open(void) +{ + RK_S32 fd = -1; + + fd = open("/dev/vcodec", O_RDWR | O_CLOEXEC); + if (fd < 0) { + mpp_err("open /dev/vcodec failed errno %d %s\n", errno, strerror(errno)); + return -1; + } + + return fd; +} + +MPP_RET mpp_vcodec_ioctl(RK_S32 fd, RK_U32 cmd, RK_U32 ctrl_cmd, RK_U32 size, void *param) +{ + vcodec_req req; + RK_S32 ret = 0; + + memset(&req, 0, sizeof(req)); + req.cmd = cmd; + req.ctrl_cmd = ctrl_cmd; + req.size = size; + req.data = REQ_DATA_PTR(param); + + ret = (RK_S32)ioctl(fd, VOCDEC_IOC_CFG, &req); + if (ret) { + mpp_err("ioctl fd %d failed ret %d errno %d %s\n", + fd, ret, errno, strerror(errno)); + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_vcodec_close(RK_S32 fd) +{ + if (fd) + close(fd); + + return MPP_OK; +} diff --git a/osal/driver/vcodec_service.c b/osal/driver/vcodec_service.c new file mode 100644 index 000000000..980c8f300 --- /dev/null +++ b/osal/driver/vcodec_service.c @@ -0,0 +1,732 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "vcodec_service" + +#include +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_list.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "vpu.h" +#include "mpp_soc.h" +#include "mpp_platform.h" +#include "vcodec_service.h" +#include "vcodec_service_api.h" + +#define MAX_REGS_COUNT 3 +#define MPX_EXTRA_INFO_NUM 16 +#define MAX_INFO_COUNT 16 +#define INFO_FORMAT_TYPE 3 + +typedef struct MppReq_t { + RK_U32 *req; + RK_U32 size; +} MppReq; + +typedef struct VcodecExtraSlot_t { + RK_U32 reg_idx; + RK_U32 offset; +} VcodecExtraSlot; + +typedef struct VcodecExtraInfo_t { + RK_U32 magic; // Fix magic value 0x4C4A46 + RK_U32 count; // valid patch info count + VcodecExtraSlot slots[MPX_EXTRA_INFO_NUM]; +} VcodecExtraInfo; + +typedef struct VcodecRegCfg_t { + RK_U32 reg_size; + VcodecExtraInfo extra_info; + + void *reg_set; + void *reg_get; +} VcodecRegCfg; + +typedef struct MppDevVcodecService_t { + RK_S32 client_type; + RK_U64 fmt; + RK_S32 fd; + RK_S32 max_regs; + RK_U32 reg_size; + + RK_S32 reg_send_idx; + RK_S32 reg_poll_idx; + + VcodecRegCfg regs[MAX_REGS_COUNT]; + + RK_S32 info_count; + MppDevInfoCfg info[MAX_INFO_COUNT]; +} MppDevVcodecService; + +/* For vpu1 / vpu2 */ +static const char *mpp_vpu_dev[] = { + "/dev/vpu_service", + "/dev/vpu-service", + "/dev/mpp_service", +}; + +/* For hevc 4K decoder */ +static const char *mpp_hevc_dev[] = { + "/dev/hevc_service", + "/dev/hevc-service", + "/dev/mpp_service", +}; + +/* For H.264/H.265/VP9 4K decoder */ +static const char *mpp_rkvdec_dev[] = { + "/dev/rkvdec", + "/dev/mpp_service", +}; + +/* For H.264 4K encoder */ +static const char *mpp_rkvenc_dev[] = { + "/dev/rkvenc", + "/dev/mpp_service", +}; + +/* For avs+ decoder */ +static const char *mpp_avsd_dev[] = { + "/dev/avsd", + "/dev/mpp_service", +}; + +/* For H.264 / jpeg encoder */ +static const char *mpp_vepu_dev[] = { + "/dev/vepu", + "/dev/mpp_service", +}; + +/* For H.265 encoder */ +static const char *mpp_h265e_dev[] = { + "/dev/h265e", + "/dev/mpp_service", +}; + +/* For jpeg decoder */ +static const char *mpp_jpegd_dev[] = { + "/dev/mpp_service", +}; + +static const char *mpp_jpege_dev[] = { + "/dev/mpp_service", +}; + +#define mpp_find_device(dev) _mpp_find_device(dev, MPP_ARRAY_ELEMS(dev)) + +static const char *_mpp_find_device(const char **dev, RK_U32 size) +{ + RK_U32 i; + + for (i = 0; i < size; i++) + if (!access(dev[i], F_OK)) + return dev[i]; + + return NULL; +} + +const char *mpp_get_platform_dev_name(MppCtxType type, MppCodingType coding, RK_U32 platform) +{ + const char *dev = NULL; + + if ((platform & HAVE_RKVDEC) && (type == MPP_CTX_DEC) && + (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC || + coding == MPP_VIDEO_CodingAVS2 || + coding == MPP_VIDEO_CodingVP9)) { + dev = mpp_find_device(mpp_rkvdec_dev); + } else if ((platform & HAVE_HEVC_DEC) && (type == MPP_CTX_DEC) && + (coding == MPP_VIDEO_CodingHEVC)) { + dev = mpp_find_device(mpp_hevc_dev); + } else if ((platform & HAVE_AVSDEC) && (type == MPP_CTX_DEC) && + (coding == MPP_VIDEO_CodingAVS)) { + dev = mpp_find_device(mpp_avsd_dev); + } else if ((platform & HAVE_RKVENC) && (type == MPP_CTX_ENC) && + (coding == MPP_VIDEO_CodingAVC)) { + dev = mpp_find_device(mpp_rkvenc_dev); + } else if ((platform & HAVE_VEPU22) && (type == MPP_CTX_ENC) && + (coding == MPP_VIDEO_CodingHEVC)) { + dev = mpp_find_device(mpp_h265e_dev); + } else { + if (type == MPP_CTX_ENC) + dev = mpp_find_device(mpp_vepu_dev); + + if (dev == NULL) + dev = mpp_find_device(mpp_vpu_dev); + } + + return dev; +} + +const char *mpp_get_vcodec_dev_name(MppCtxType type, MppCodingType coding) +{ + const char *dev = NULL; + RockchipSocType soc_type = mpp_get_soc_type(); + + switch (soc_type) { + case ROCKCHIP_SOC_RK3036 : { + /* rk3036 do NOT have encoder */ + if (type == MPP_CTX_ENC) + dev = NULL; + else if (coding == MPP_VIDEO_CodingHEVC && type == MPP_CTX_DEC) + dev = mpp_find_device(mpp_hevc_dev); + else + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RK3066 : + case ROCKCHIP_SOC_RK3188 : { + /* rk3066/rk3188 have vpu1 only */ + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RK3288 : + case ROCKCHIP_SOC_RK312X : + case ROCKCHIP_SOC_RK3368 : + case ROCKCHIP_SOC_RK3326 : + case ROCKCHIP_SOC_PX30 : { + /* + * rk3288/rk312x/rk3368 have codec: + * 1 - vpu1 + * 2 - RK hevc decoder + */ + if (coding == MPP_VIDEO_CodingHEVC && type == MPP_CTX_DEC) + dev = mpp_find_device(mpp_hevc_dev); + else + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RK3128H : { + /* + * rk3128H have codec: + * 1 - vpu2 + * 2 - RK H.264/H.265 1080p@60fps decoder + * NOTE: rk3128H do NOT have jpeg encoder + */ + if (type == MPP_CTX_DEC && + (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC)) + dev = mpp_find_device(mpp_rkvdec_dev); + else if (type == MPP_CTX_ENC && coding == MPP_VIDEO_CodingMJPEG) + dev = NULL; + else if (type == MPP_CTX_DEC && coding == MPP_VIDEO_CodingVP9) + dev = NULL; + else + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RK3399 : + case ROCKCHIP_SOC_RK3229 : { + /* + * rk3399/rk3229 have codec: + * 1 - vpu2 + * 2 - RK H.264/H.265/VP9 4K decoder + */ + if (type == MPP_CTX_DEC && + (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC || + coding == MPP_VIDEO_CodingVP9)) + dev = mpp_find_device(mpp_rkvdec_dev); + else + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RK3228 : { + /* + * rk3228 have codec: + * 1 - vpu2 + * 2 - RK H.264/H.265 4K decoder + * NOTE: rk3228 do NOT have jpeg encoder + */ + if (type == MPP_CTX_DEC && + (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC)) + dev = mpp_find_device(mpp_rkvdec_dev); + else if (type == MPP_CTX_ENC && coding == MPP_VIDEO_CodingMJPEG) + dev = NULL; + else + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RK3228H : { + /* + * rk3228h has codec: + * 1 - vpu2 + * 2 - RK H.264/H.265 4K decoder + * 3 - avs+ decoder + * 4 - H.265 encoder + */ + if (type == MPP_CTX_ENC) { + if (coding == MPP_VIDEO_CodingHEVC) + dev = mpp_find_device(mpp_h265e_dev); + else + dev = mpp_find_device(mpp_vepu_dev); + } else if (type == MPP_CTX_DEC) { + if (coding == MPP_VIDEO_CodingAVS) + dev = mpp_find_device(mpp_avsd_dev); + else if (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC) + dev = mpp_find_device(mpp_rkvdec_dev); + else + dev = mpp_find_device(mpp_vpu_dev); + } + } break; + case ROCKCHIP_SOC_RK3328 : { + /* + * rk3228 has codec: + * 1 - vpu2 + * 2 - RK H.264/H.265/VP9 4K decoder + * 4 - H.265 encoder + */ + if (type == MPP_CTX_ENC) { + if (coding == MPP_VIDEO_CodingHEVC) + dev = mpp_find_device(mpp_h265e_dev); + else + dev = mpp_find_device(mpp_vepu_dev); + } else if (type == MPP_CTX_DEC) { + if (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC || + coding == MPP_VIDEO_CodingVP9) { + dev = mpp_find_device(mpp_rkvdec_dev); + } else + dev = mpp_find_device(mpp_vpu_dev); + } + } break; + case ROCKCHIP_SOC_RV1108 : { + /* + * rv1108 has codec: + * 1 - vpu2 + * 2 - RK H.264 4K decoder + * 3 - RK H.264 4K encoder + */ + if (coding == MPP_VIDEO_CodingAVC) { + if (type == MPP_CTX_ENC) + dev = mpp_find_device(mpp_rkvenc_dev); + else + dev = mpp_find_device(mpp_rkvdec_dev); + } else if (coding == MPP_VIDEO_CodingMJPEG) + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RV1109 : + case ROCKCHIP_SOC_RV1126 : { + /* + * rv1108 has codec: + * 1 - vpu2 for jpeg encoder and decoder + * 2 - RK H.264/H.265 4K decoder + * 3 - RK H.264/H.265 4K encoder + */ + if (coding == MPP_VIDEO_CodingAVC || coding == MPP_VIDEO_CodingHEVC) { + if (type == MPP_CTX_ENC) + dev = mpp_find_device(mpp_rkvenc_dev); + else + dev = mpp_find_device(mpp_rkvdec_dev); + } else if (coding == MPP_VIDEO_CodingMJPEG) + dev = mpp_find_device(mpp_vpu_dev); + } break; + case ROCKCHIP_SOC_RK3566 : + case ROCKCHIP_SOC_RK3567 : + case ROCKCHIP_SOC_RK3568 : { + /* + * rk3566/rk3568 has codec: + * 1 - vpu2 for jpeg/vp8 encoder and decoder + * 2 - RK H.264/H.265/VP9 4K decoder + * 3 - RK H.264/H.265 4K encoder + * 3 - RK jpeg decoder + */ + if (type == MPP_CTX_DEC) { + if (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC || + coding == MPP_VIDEO_CodingVP9) + dev = mpp_find_device(mpp_rkvdec_dev); + else if (coding == MPP_VIDEO_CodingMJPEG) + dev = mpp_find_device(mpp_jpegd_dev); + else + dev = mpp_find_device(mpp_vpu_dev); + } else if (type == MPP_CTX_ENC) { + if (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC) + dev = mpp_find_device(mpp_rkvenc_dev); + else if (coding == MPP_VIDEO_CodingMJPEG || + coding == MPP_VIDEO_CodingVP8) + dev = mpp_find_device(mpp_vpu_dev); + else + dev = NULL; + } + } break; + case ROCKCHIP_SOC_RK3588 : { + /* + * rk3588 has codec: + * 1 - RK H.264/H.265/VP9/AVS2 8K decoder + * 2 - RK H.264/H.265 8K encoder + * 3 - vpu2 for jpeg/vp8 encoder and decoder + * 4 - RK jpeg decoder + */ + if (type == MPP_CTX_DEC) { + if (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC || + coding == MPP_VIDEO_CodingAVS2 || + coding == MPP_VIDEO_CodingVP9) + dev = mpp_find_device(mpp_rkvdec_dev); + else if (coding == MPP_VIDEO_CodingMJPEG) + dev = mpp_find_device(mpp_jpegd_dev); + else + dev = mpp_find_device(mpp_vpu_dev); + } else if (type == MPP_CTX_ENC) { + if (coding == MPP_VIDEO_CodingAVC || + coding == MPP_VIDEO_CodingHEVC) + dev = mpp_find_device(mpp_rkvenc_dev); + else if (coding == MPP_VIDEO_CodingMJPEG || + coding == MPP_VIDEO_CodingVP8) + dev = mpp_find_device(mpp_vpu_dev); + else + dev = NULL; + } + } break; + case ROCKCHIP_SOC_RK3576 : + case ROCKCHIP_SOC_RV1126B : + case ROCKCHIP_SOC_RK3572 : { + if (type == MPP_CTX_DEC) { + if (coding == MPP_VIDEO_CodingMJPEG) + dev = mpp_find_device(mpp_jpegd_dev); + else + dev = mpp_find_device(mpp_rkvdec_dev); + } else if (type == MPP_CTX_ENC) { + if (coding == MPP_VIDEO_CodingMJPEG) + dev = mpp_find_device(mpp_jpege_dev); + else + dev = mpp_find_device(mpp_rkvenc_dev); + } + } break; + default : { + /* default case for unknown compatible */ + RK_U32 vcodec_type = mpp_get_vcodec_type(); + + dev = mpp_get_platform_dev_name(type, coding, vcodec_type); + } break; + } + + return dev; +} + +static RK_S32 vcodec_service_ioctl(RK_S32 fd, RK_S32 cmd, void *regs, RK_S32 size) +{ + MppReq req; + + req.req = regs; + req.size = size; + + return (RK_S32)ioctl(fd, cmd, &req); +} + +static void extra_info_init(VcodecExtraInfo *info) +{ + info->magic = EXTRA_INFO_MAGIC; + info->count = 0; +} + +static void update_extra_info(VcodecExtraInfo *info, char* fmt, VcodecRegCfg* send_cfg) +{ + void *reg_set = send_cfg->reg_set; + RK_U32 reg_size = send_cfg->reg_size; + + if (info->count) { + if (!strstr(fmt, "mjpeg")) { + RK_U32 *reg = (RK_U32*)reg_set; + RK_U32 i = 0; + + for (i = 0; i < info->count; i++) { + VcodecExtraSlot *slot = &info->slots[i]; + + reg[slot->reg_idx] |= (slot->offset << 10); + } + info->count = 0; + } else { + void *extra_data = reg_set + reg_size; + RK_S32 extra_size = sizeof(send_cfg->extra_info); + + memcpy(extra_data, info, extra_size); + send_cfg->reg_size += extra_size; + extra_info_init(info); + } + } +} + +MPP_RET vcodec_service_init(void *ctx, MppClientType type) +{ + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + static RK_S32 vcodec_ioctl_version = -1; + VPU_CLIENT_TYPE client_type; + const char *name = NULL; + RK_U32 reg_size = 0; + RK_S32 max_regs = 2; + MPP_RET ret = MPP_NOK; + + switch (type) { + case VPU_CLIENT_VDPU1 : { + name = mpp_find_device(mpp_vpu_dev); + client_type = VPU_DEC; + reg_size = VDPU1_REGISTERS; + } break; + case VPU_CLIENT_VDPU2 : { + name = mpp_find_device(mpp_vpu_dev); + client_type = VPU_DEC; + reg_size = VDPU2_REGISTERS; + } break; + case VPU_CLIENT_VDPU1_PP : { + name = mpp_find_device(mpp_vpu_dev); + client_type = VPU_DEC_PP; + if (ROCKCHIP_SOC_RK3036 == mpp_get_soc_type()) + reg_size = VDPU1_REGISTERS; + else + reg_size = VDPU1_PP_REGISTERS; + } break; + case VPU_CLIENT_VDPU2_PP : { + name = mpp_find_device(mpp_vpu_dev); + client_type = VPU_DEC_PP; + reg_size = VDPU2_PP_REGISTERS; + } break; + case VPU_CLIENT_HEVC_DEC : { + name = mpp_find_device(mpp_hevc_dev); + client_type = VPU_DEC; + reg_size = RKHEVC_REGISTERS; + max_regs = 3; + } break; + case VPU_CLIENT_RKVDEC : { + name = mpp_find_device(mpp_rkvdec_dev); + client_type = VPU_DEC; + reg_size = RKVDEC_REGISTERS; + max_regs = 3; + } break; + case VPU_CLIENT_AVSPLUS_DEC : { + name = mpp_find_device(mpp_avsd_dev); + client_type = VPU_DEC; + reg_size = AVSD_REGISTERS; + } break; + case VPU_CLIENT_RKVENC : { + name = mpp_find_device(mpp_rkvenc_dev); + client_type = VPU_ENC; + reg_size = AVSD_REGISTERS; + } break; + case VPU_CLIENT_VEPU1 : { + name = mpp_find_device(mpp_vpu_dev); + client_type = VPU_ENC; + reg_size = VEPU1_REGISTERS; + } break; + case VPU_CLIENT_VEPU2 : { + name = mpp_find_device(mpp_vepu_dev); + if (NULL == name) + name = mpp_find_device(mpp_vpu_dev); + client_type = VPU_ENC; + reg_size = VEPU2_REGISTERS; + } break; + default : { + mpp_err_f("unsupported client type %d\n", type); + return ret; + } break; + } + + p->fd = open(name, O_RDWR | O_CLOEXEC); + if (p->fd < 0) { + mpp_err("open vcodec_service %s failed\n", name); + return ret; + } + + if (vcodec_ioctl_version < 0) { + ret = (RK_S32)ioctl(p->fd, VPU_IOC_SET_CLIENT_TYPE, (unsigned long)client_type); + if (!ret) { + vcodec_ioctl_version = 0; + } else { + ret = (RK_S32)ioctl(p->fd, VPU_IOC_SET_CLIENT_TYPE_U32, (RK_U32)client_type); + if (!ret) + vcodec_ioctl_version = 1; + } + mpp_assert(ret == MPP_OK); + } else { + RK_U32 cmd = (vcodec_ioctl_version == 0) ? + (VPU_IOC_SET_CLIENT_TYPE) : + (VPU_IOC_SET_CLIENT_TYPE_U32); + + ret = (RK_S32)ioctl(p->fd, cmd, client_type); + } + + p->max_regs = max_regs; + p->reg_size = reg_size * sizeof(RK_U32); + { + RK_S32 i; + + for (i = 0; i < max_regs; i++) { + VcodecRegCfg *reg = &p->regs[i]; + + reg->reg_size = p->reg_size; + extra_info_init(®->extra_info); + } + } + + return ret; +} + +MPP_RET vcodec_service_deinit(void *ctx) +{ + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + + if (p->fd) + close(p->fd); + + return MPP_OK; +} + +MPP_RET vcodec_service_reg_wr(void *ctx, MppDevRegWrCfg *cfg) +{ + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx]; + + mpp_assert(cfg->offset == 0); + send_cfg->reg_set = cfg->reg; + send_cfg->reg_size = cfg->size; + + if (p->reg_size != cfg->size) + mpp_err_f("reg size mismatch wr %d rd %d\n", + p->reg_size, cfg->size); + + return MPP_OK; +} + +MPP_RET vcodec_service_reg_rd(void *ctx, MppDevRegRdCfg *cfg) +{ + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx]; + + mpp_assert(cfg->offset == 0); + send_cfg->reg_get = cfg->reg; + if (send_cfg->reg_size != cfg->size) + mpp_err_f("reg size mismatch rd %d rd %d\n", + send_cfg->reg_size, cfg->size); + + return MPP_OK; +} + +MPP_RET vcodec_service_reg_offset(void *ctx, MppDevRegOffsetCfg *cfg) +{ + if (cfg->offset) { + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx]; + VcodecExtraInfo *extra = &send_cfg->extra_info; + VcodecExtraSlot *slot; + RK_U32 i; + + for (i = 0; i < extra->count; i++) { + slot = &extra->slots[i]; + + if (slot->reg_idx == cfg->reg_idx) { + mpp_err_f("reg[%d] offset has been set, cover old %d -> %d\n", + slot->reg_idx, slot->offset, cfg->offset); + slot->offset = cfg->offset; + return MPP_OK; + } + } + + slot = &extra->slots[extra->count]; + slot->reg_idx = cfg->reg_idx; + slot->offset = cfg->offset; + extra->count++; + } + + return MPP_OK; +} + +MPP_RET vcodec_service_cmd_send(void *ctx) +{ + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx]; + VcodecExtraInfo *extra = &send_cfg->extra_info; + void *reg_set = send_cfg->reg_set; + char *fmt = (char*)&p->fmt; + + update_extra_info(extra, fmt, send_cfg); + + MPP_RET ret = vcodec_service_ioctl(p->fd, VPU_IOC_SET_REG, + reg_set, send_cfg->reg_size); + if (ret) { + mpp_err_f("ioctl VPU_IOC_SET_REG failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + + p->reg_send_idx++; + if (p->reg_send_idx >= p->max_regs) + p->reg_send_idx = 0; + p->info_count = 0; + + return ret; +} + +MPP_RET vcodec_service_cmd_poll(void *ctx, MppDevPollCfg *cfg) +{ + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + VcodecRegCfg *poll_cfg = &p->regs[p->reg_poll_idx]; + void *reg_get = poll_cfg->reg_get; + RK_S32 reg_size = poll_cfg->reg_size; + MPP_RET ret = vcodec_service_ioctl(p->fd, VPU_IOC_GET_REG, + reg_get, reg_size); + if (ret) { + mpp_err_f("ioctl VPU_IOC_GET_REG failed ret %d errno %d %s\n", + ret, errno, strerror(errno)); + ret = errno; + } + + p->reg_poll_idx++; + if (p->reg_poll_idx >= p->max_regs) + p->reg_poll_idx = 0; + + (void)cfg; + return ret; +} + +MPP_RET vcodec_service_set_info(void *ctx, MppDevInfoCfg *cfg) +{ + MppDevVcodecService *p = (MppDevVcodecService *)ctx; + + if (!p->info_count) + memset(p->info, 0, sizeof(p->info)); + + if (p->info_count >= MAX_INFO_COUNT) { + mpp_err("info count reach max\n"); + return MPP_NOK; + } + + memcpy(&p->info[p->info_count], cfg, sizeof(MppDevInfoCfg)); + p->info_count++; + + if (cfg->type == INFO_FORMAT_TYPE) { + p->fmt = cfg->data; + } + return MPP_OK; +} + +const MppDevApi vcodec_service_api = { + "vcodec_service", + sizeof(MppDevVcodecService), + vcodec_service_init, + vcodec_service_deinit, + NULL, + NULL, + NULL, + NULL, + vcodec_service_reg_wr, + vcodec_service_reg_rd, + vcodec_service_reg_offset, + NULL, + NULL, + vcodec_service_set_info, + NULL, + NULL, + NULL, + NULL, + NULL, + vcodec_service_cmd_send, + vcodec_service_cmd_poll, +}; diff --git a/osal/inc/mpp_allocator.h b/osal/inc/mpp_allocator.h index 32c32ca3f..b14f958fb 100644 --- a/osal/inc/mpp_allocator.h +++ b/osal/inc/mpp_allocator.h @@ -1,45 +1,48 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_ALLOCATOR_H__ -#define __MPP_ALLOCATOR_H__ - -#include "rk_type.h" -#include "mpp_buffer.h" - -typedef void *MppAllocator; - -typedef struct MppAllocatorApi_t { - RK_U32 size; - RK_U32 version; - - MPP_RET (*alloc)(MppAllocator allocator, MppBufferInfo *data); - MPP_RET (*free)(MppAllocator allocator, MppBufferInfo *data); -} MppAllocatorApi; - -#ifdef __cplusplus -extern "C" { -#endif - -MPP_RET mpp_alloctor_get(MppAllocator *allocator, MppAllocatorApi **api, MppBufferType type); -MPP_RET mpp_alloctor_put(MppAllocator *allocator); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_ALLOCATOR_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_ALLOCATOR_H +#define MPP_ALLOCATOR_H + +#include "mpp_bit.h" +#include "mpp_buffer.h" + +typedef enum MppAllocFlagType_e { + MPP_ALLOC_FLAG_NONE = 0U, + MPP_ALLOC_FLAG_DMA32 = MPP_BIT(0), + MPP_ALLOC_FLAG_CACHABLE = MPP_BIT(1), + MPP_ALLOC_FLAG_CMA = MPP_BIT(2), + MPP_ALLOC_FLAG_TYPE_MASK = MPP_FLAG_OR(MPP_ALLOC_FLAG_CMA, MPP_ALLOC_FLAG_CACHABLE, MPP_ALLOC_FLAG_DMA32), + MPP_ALLOC_FLAG_TYPE_NB, +} MppAllocFlagType; + +typedef void *MppAllocator; + +typedef struct MppAllocatorApi_t { + RK_U32 size; + RK_U32 version; + + MPP_RET (*alloc)(MppAllocator allocator, MppBufferInfo *data); + MPP_RET (*free)(MppAllocator allocator, MppBufferInfo *data); + MPP_RET (*import)(MppAllocator allocator, MppBufferInfo *data); + MPP_RET (*release)(MppAllocator allocator, MppBufferInfo *data); + MPP_RET (*mmap)(MppAllocator allocator, MppBufferInfo *data); +} MppAllocatorApi; + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOTE: flag may be updated by allocator */ +MPP_RET mpp_allocator_get(MppAllocator *allocator, MppAllocatorApi **api, + MppBufferType type, MppAllocFlagType flag); +MPP_RET mpp_allocator_put(MppAllocator *allocator); +MppAllocFlagType mpp_allocator_get_flags(const MppAllocator allocator); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ALLOCATOR_H */ diff --git a/osal/inc/mpp_callback.h b/osal/inc/mpp_callback.h new file mode 100644 index 000000000..cff9d01cf --- /dev/null +++ b/osal/inc/mpp_callback.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_CALLBACK_H +#define MPP_CALLBACK_H + +#include "rk_type.h" +#include "mpp_err.h" + +typedef MPP_RET (*MppCallBack)(const char *caller, void *ctx, RK_S32 cmd, void *param); + +typedef struct DecCallBackCtx_t { + MppCallBack callBack; + void *ctx; + RK_S32 cmd; +} MppCbCtx; + +#ifdef __cplusplus +extern "C" { +#endif + +#define mpp_callback(ctx, param) mpp_callback_f(__FUNCTION__, ctx, param) + +MPP_RET mpp_callback_f(const char *caller, MppCbCtx *ctx, void *param); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_CALLBACK_H */ diff --git a/osal/inc/mpp_common.h b/osal/inc/mpp_common.h index 563d553b6..f0173cda3 100644 --- a/osal/inc/mpp_common.h +++ b/osal/inc/mpp_common.h @@ -1,81 +1,249 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_COMMON_H__ -#define __MPP_COMMON_H__ - -#include "rk_type.h" - -#define MPP_TAG_SIZE 32 - -#define MPP_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MPP_MAX3(a, b, c) MPP_MAX(MPP_MAX(a,b),c) -#define MPP_MAX4(a, b, c, d) MPP_MAX((a), MPP_MAX3((b), (c), (d))) - -#define MPP_MIN(a,b) ((a) > (b) ? (b) : (a)) -#define MPP_MIN3(a,b,c) MPP_MIN(MPP_MIN(a,b),c) -#define MPP_MIN4(a, b, c, d) MPP_MIN((a), MPP_MIN3((b), (c), (d))) - -#define MPP_SWAP(type, a, b) do {type SWAP_tmp = b; b = a; a = SWAP_tmp;} while(0) -#define MPP_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) -#define MPP_ALIGN(x, a) (((x)+(a)-1)&~((a)-1)) -#define MPP_VSWAP(a, b) { a ^= b; b ^= a; a ^= b; } - - -#include -#if defined(_WIN32) && !defined(__MINGW32CE__) -#define snprintf _snprintf -#define fseeko _fseeki64 - -#include -#include -#define chdir _chdir -#define mkdir _mkdir -#define access _access -#elif defined(__MINGW32CE__) -#define fseeko fseeko64 -#else -#include -#include -#include -#define mkdir(x) mkdir(x, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -RK_S32 mpp_log2(RK_U32 v); -RK_S32 mpp_log2_16bit(RK_U32 v); - -static __inline RK_S32 mpp_ceil_log2(RK_S32 x) -{ - return mpp_log2((x - 1) << 1); -} - -static __inline RK_S32 mpp_clip(RK_S32 a, RK_S32 amin, RK_S32 amax) -{ - if (a < amin) return amin; - else if (a > amax) return amax; - else return a; -} - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_COMMON_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_COMMON_H +#define MPP_COMMON_H + +#include "rk_type.h" + +#define MPP_TAG_SIZE 32 + +#define MPP_ABS(x) ((x) < (0) ? -(x) : (x)) + +#define MPP_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MPP_MAX3(a, b, c) MPP_MAX(MPP_MAX(a,b),c) +#define MPP_MAX4(a, b, c, d) MPP_MAX((a), MPP_MAX3((b), (c), (d))) + +#define MPP_MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MPP_MIN3(a,b,c) MPP_MIN(MPP_MIN(a,b),c) +#define MPP_MIN4(a, b, c, d) MPP_MIN((a), MPP_MIN3((b), (c), (d))) + +#define MPP_DIV(a, b) (((b) != 0) ? (a) / (b) : (a)) + +#define MPP_CLIP3(l, h, v) ((v) < (l) ? (l) : ((v) > (h) ? (h) : (v))) +#define MPP_SIGN(a) ((a) < (0) ? (-1) : (1)) +#define MPP_DIV_SIGN(a, b) (((a) + (MPP_SIGN(a) * (b)) / 2) / (b)) + +#define MPP_SWAP(type, a, b) do {type SWAP_tmp = b; b = a; a = SWAP_tmp;} while(0) +#define MPP_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#define MPP_ARRAY_ELEMS_U(a) ((rk_u32)(sizeof(a) / sizeof((a)[0]))) +#define MPP_ARRAY_ELEMS_S(a) ((rk_s32)(sizeof(a) / sizeof((a)[0]))) +#define MPP_ALIGN(x, a) (((x)+(a)-1)&~((a)-1)) +#define MPP_ALIGN_DOWN(x, a) ((x)&~((a)-1)) +#define MPP_ALIGN_GEN(x, a) (((x)+(a)-1)/(a)*(a)) +#define MPP_VSWAP(a, b) { a ^= b; b ^= a; a ^= b; } + +#define MPP_ROUNDUP(N, M) MPP_ALIGN(M, N) +#define MPP_DIVUP(N, M) (MPP_ROUNDUP(N, M) / N) + +#define MPP_GENMASK(h, l) (((1ULL << ((h) + 1)) - 1) & ~((1ULL << (l)) - 1)) + +#define MPP_RB16(x) ((((const RK_U8*)(x))[0] << 8) | ((const RK_U8*)(x))[1]) +#define MPP_WB16(p, d) do { \ + ((RK_U8*)(p))[1] = (d); \ + ((RK_U8*)(p))[0] = (d)>>8; } while(0) + +#define MPP_RL16(x) ((((const RK_U8*)(x))[1] << 8) | \ + ((const RK_U8*)(x))[0]) +#define MPP_WL16(p, d) do { \ + ((RK_U8*)(p))[0] = (d); \ + ((RK_U8*)(p))[1] = (d)>>8; } while(0) + +#define MPP_RB32(x) ((((const RK_U8*)(x))[0] << 24) | \ + (((const RK_U8*)(x))[1] << 16) | \ + (((const RK_U8*)(x))[2] << 8) | \ + ((const RK_U8*)(x))[3]) +#define MPP_WB32(p, d) do { \ + ((RK_U8*)(p))[3] = (d); \ + ((RK_U8*)(p))[2] = (d)>>8; \ + ((RK_U8*)(p))[1] = (d)>>16; \ + ((RK_U8*)(p))[0] = (d)>>24; } while(0) + +#define MPP_RL32(x) ((((const RK_U8*)(x))[3] << 24) | \ + (((const RK_U8*)(x))[2] << 16) | \ + (((const RK_U8*)(x))[1] << 8) | \ + ((const RK_U8*)(x))[0]) +#define MPP_WL32(p, d) do { \ + ((RK_U8*)(p))[0] = (d); \ + ((RK_U8*)(p))[1] = (d)>>8; \ + ((RK_U8*)(p))[2] = (d)>>16; \ + ((RK_U8*)(p))[3] = (d)>>24; } while(0) + +#define MPP_RB64(x) (((RK_U64)((const RK_U8*)(x))[0] << 56) | \ + ((RK_U64)((const RK_U8*)(x))[1] << 48) | \ + ((RK_U64)((const RK_U8*)(x))[2] << 40) | \ + ((RK_U64)((const RK_U8*)(x))[3] << 32) | \ + ((RK_U64)((const RK_U8*)(x))[4] << 24) | \ + ((RK_U64)((const RK_U8*)(x))[5] << 16) | \ + ((RK_U64)((const RK_U8*)(x))[6] << 8) | \ + (RK_U64)((const RK_U8*)(x))[7]) +#define MPP_WB64(p, d) do { \ + ((RK_U8*)(p))[7] = (d); \ + ((RK_U8*)(p))[6] = (d)>>8; \ + ((RK_U8*)(p))[5] = (d)>>16; \ + ((RK_U8*)(p))[4] = (d)>>24; \ + ((RK_U8*)(p))[3] = (d)>>32; \ + ((RK_U8*)(p))[2] = (d)>>40; \ + ((RK_U8*)(p))[1] = (d)>>48; \ + ((RK_U8*)(p))[0] = (d)>>56; } while(0) + +#define MPP_RL64(x) (((RK_U64)((const RK_U8*)(x))[7] << 56) | \ + ((RK_U64)((const RK_U8*)(x))[6] << 48) | \ + ((RK_U64)((const RK_U8*)(x))[5] << 40) | \ + ((RK_U64)((const RK_U8*)(x))[4] << 32) | \ + ((RK_U64)((const RK_U8*)(x))[3] << 24) | \ + ((RK_U64)((const RK_U8*)(x))[2] << 16) | \ + ((RK_U64)((const RK_U8*)(x))[1] << 8) | \ + (RK_U64)((const RK_U8*)(x))[0]) +#define MPP_WL64(p, d) do { \ + ((RK_U8*)(p))[0] = (d); \ + ((RK_U8*)(p))[1] = (d)>>8; \ + ((RK_U8*)(p))[2] = (d)>>16; \ + ((RK_U8*)(p))[3] = (d)>>24; \ + ((RK_U8*)(p))[4] = (d)>>32; \ + ((RK_U8*)(p))[5] = (d)>>40; \ + ((RK_U8*)(p))[6] = (d)>>48; \ + ((RK_U8*)(p))[7] = (d)>>56; } while(0) + +#define MPP_RB24(x) ((((const RK_U8*)(x))[0] << 16) | \ + (((const RK_U8*)(x))[1] << 8) | \ + ((const RK_U8*)(x))[2]) +#define MPP_WB24(p, d) do { \ + ((RK_U8*)(p))[2] = (d); \ + ((RK_U8*)(p))[1] = (d)>>8; \ + ((RK_U8*)(p))[0] = (d)>>16; } while(0) + +#define MPP_RL24(x) ((((const RK_U8*)(x))[2] << 16) | \ + (((const RK_U8*)(x))[1] << 8) | \ + ((const RK_U8*)(x))[0]) + +#define MPP_WL24(p, d) do { \ + ((RK_U8*)(p))[0] = (d); \ + ((RK_U8*)(p))[1] = (d)>>8; \ + ((RK_U8*)(p))[2] = (d)>>16; } while(0) + +#include +#if defined(_WIN32) && !defined(__MINGW32CE__) +#define snprintf _snprintf +#define fseeko _fseeki64 + +#include +#include +#include + +#define chdir _chdir +#define mkdir _mkdir +#define access _access +#define off_t _off_t + +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +#define X_OK 1 /* Test for execute permission. */ +#define F_OK 0 /* Test for existence. */ + +#elif defined(__MINGW32CE__) +#define fseeko fseeko64 +#else +#include +#include +#include +#include +#include +#define mkdir(x) mkdir(x, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) +#endif + +#define container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) + +#define __RETURN __Return +#define __FAILED __failed + +#define ARG_T(t) t +#define ARG_N(a,b,c,d,N,...) N +#define ARG_N_HELPER(...) ARG_T(ARG_N(__VA_ARGS__)) +#define COUNT_ARG(...) ARG_N_HELPER(__VA_ARGS__,4,3,2,1,0) + +#define SZ_1K (1024) +#define SZ_2K (SZ_1K*2) +#define SZ_4K (SZ_1K*4) +#define SZ_8K (SZ_1K*8) +#define SZ_16K (SZ_1K*16) +#define SZ_32K (SZ_1K*32) +#define SZ_64K (SZ_1K*64) +#define SZ_128K (SZ_1K*128) +#define SZ_256K (SZ_1K*256) +#define SZ_512K (SZ_1K*512) +#define SZ_1M (SZ_1K*SZ_1K) +#define SZ_2M (SZ_1M*2) +#define SZ_4M (SZ_1M*4) +#define SZ_8M (SZ_1M*8) +#define SZ_16M (SZ_1M*16) +#define SZ_32M (SZ_1M*32) +#define SZ_64M (SZ_1M*64) +#define SZ_80M (SZ_1M*80) +#define SZ_128M (SZ_1M*128) + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_log2(RK_U32 v); +RK_S32 mpp_log2_16bit(RK_U32 v); + +static __inline RK_S32 mpp_ceil_log2(RK_S32 x) +{ + return mpp_log2(((RK_U32)x - 1U) << 1); +} + +static __inline RK_S32 mpp_clip(RK_S32 a, RK_S32 amin, RK_S32 amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +static __inline RK_S32 mpp_dup(RK_S32 fd) +{ + /* avoid stdin / stdout / stderr so start from 3 */ +#ifdef F_DUPFD_CLOEXEC + return fcntl(fd, F_DUPFD_CLOEXEC, 3); +#else + RK_S32 new_fd = -1; + + new_fd = fcntl(fd, F_DUPFD, 3); + if (new_fd == -1) + return -1; + + if (fcntl(new_fd, F_SETFD, FD_CLOEXEC) == -1) + return -1; + + return new_fd; +#endif +} + +RK_S32 axb_div_c(RK_S32 a, RK_S32 b, RK_S32 c); +RK_U32 mpp_align_8(RK_U32 val); +RK_U32 mpp_align_16(RK_U32 val); +RK_U32 mpp_align_64(RK_U32 val); +RK_U32 mpp_align_128(RK_U32 val); +RK_U32 mpp_align_256_odd(RK_U32 val); +RK_U32 mpp_align_128_odd_plus_64(RK_U32 val); +RK_U32 mpp_align_wxh2yuv420(RK_U32 val); +RK_U32 mpp_align_wxh2yuv422(RK_U32 val); +RK_U32 mpp_align_wxh2yuv444(RK_U32 val); + +// Clip a signed integer to the range [0, 2^n - 1] +RK_U32 mpp_clip_uint_pow2(RK_S32 val, RK_S32 n); +// Divide an unsigned integer x by 2^n and round to nearest integer +RK_U64 mpp_round_pow2(RK_U64 x, RK_U16 n); +// Divide a signed integer x by 2^n and round to nearest integer +RK_S64 mpp_round_pow2_signed(RK_S64 x, RK_U16 n); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_COMMON_H */ + diff --git a/osal/inc/mpp_compat_impl.h b/osal/inc/mpp_compat_impl.h new file mode 100644 index 000000000..3b85c4872 --- /dev/null +++ b/osal/inc/mpp_compat_impl.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_COMPAT_IMPL_H +#define MPP_COMPAT_IMPL_H + +#include "rk_type.h" + +extern RK_S32 *compat_ext_fbc_buf_size; +extern RK_S32 *compat_ext_async_input; +extern RK_S32 *compat_ext_fbc_hdr_256_odd; + +#endif /* MPP_COMPAT_IMPL_H */ diff --git a/osal/inc/mpp_debug.h b/osal/inc/mpp_debug.h new file mode 100644 index 000000000..9f60e7211 --- /dev/null +++ b/osal/inc/mpp_debug.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_DEBUG_H +#define MPP_DEBUG_H + +#include + +#include "rk_type.h" +#include "mpp_err.h" +#include "mpp_log.h" + +#define MPP_DBG_TIMING (0x00000001) +#define MPP_DBG_PTS (0x00000002) +#define MPP_DBG_INFO (0x00000004) +#define MPP_DBG_PLATFORM (0x00000010) + +#define MPP_DBG_DUMP_LOG (0x00000100) +#define MPP_DBG_DUMP_IN (0x00000200) +#define MPP_DBG_DUMP_OUT (0x00000400) +#define MPP_DBG_DUMP_CFG (0x00000800) + +#define mpp_dbg(debug, flag, fmt, ...) mpp_log_c((debug) & (flag), fmt, ## __VA_ARGS__) +#define mpp_dbg_f(debug, flag, fmt, ...) mpp_log_cf((debug) & (flag), fmt, ## __VA_ARGS__) + +#define sys_dbg(flag, fmt, ...) mpp_dbg(mpp_debug, flag, fmt, ## __VA_ARGS__) +#define sys_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_debug, flag, fmt, ## __VA_ARGS__) + +#define sys_dbg_pts(fmt, ...) sys_dbg(MPP_DBG_PTS, fmt, ## __VA_ARGS__) +#define sys_dbg_info(fmt, ...) sys_dbg(MPP_DBG_INFO, fmt, ## __VA_ARGS__) +#define sys_dbg_platform(fmt, ...) sys_dbg(MPP_DBG_PLATFORM, fmt, ## __VA_ARGS__) + +#define MPP_ABORT (0x10000000) + +/* + * mpp_dbg usage: + * + * in h264d module define module debug flag variable like: h265d_debug + * then define h265d_dbg macro as follow : + * + * extern RK_U32 h265d_debug; + * + * #define H265D_DBG_FUNCTION (0x00000001) + * #define H265D_DBG_VPS (0x00000002) + * #define H265D_DBG_SPS (0x00000004) + * #define H265D_DBG_PPS (0x00000008) + * #define H265D_DBG_SLICE_HDR (0x00000010) + * + * #define h265d_dbg(flag, fmt, ...) mpp_dbg(h265d_debug, flag, fmt, ## __VA_ARGS__) + * + * finally use environment control the debug flag + * + * mpp_get_env_u32("h264d_debug", &h265d_debug, 0) + * + */ +/* + * sub-module debug flag usage example: + * +------+-------------------+ + * | 8bit | 24bit | + * +------+-------------------+ + * 0~15 bit: software debug print + * 16~23 bit: hardware debug print + * 24~31 bit: information print format + */ + +#define mpp_abort() do { \ + if (mpp_debug & MPP_ABORT) { \ + abort(); \ + } \ +} while (0) + +#define MPP_STRINGS(x) MPP_TO_STRING(x) +#define MPP_TO_STRING(x) #x + +#define mpp_assert(cond) do { \ + if (!(cond)) { \ + mpp_err("Assertion %s failed at %s:%d\n", \ + MPP_STRINGS(cond), __FUNCTION__, __LINE__); \ + mpp_abort(); \ + } \ +} while (0) + +/* llog for long log */ + +#define mpp_llogf(fmt, ...) mpp_llog(MPP_LOG_FATAL, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_lloge(fmt, ...) mpp_llog(MPP_LOG_ERROR, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_llogw(fmt, ...) mpp_llog(MPP_LOG_WARN, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_llogi(fmt, ...) mpp_llog(MPP_LOG_INFO, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_llogd(fmt, ...) mpp_llog(MPP_LOG_DEBUG, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) +#define mpp_llogv(fmt, ...) mpp_llog(MPP_LOG_VERBOSE, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) + +#define mpp_llogf_f(fmt, ...) mpp_llog(MPP_LOG_FATAL, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_lloge_f(fmt, ...) mpp_llog(MPP_LOG_ERROR, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_llogw_f(fmt, ...) mpp_llog(MPP_LOG_WARN, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_llogi_f(fmt, ...) mpp_llog(MPP_LOG_INFO, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_llogd_f(fmt, ...) mpp_llog(MPP_LOG_DEBUG, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) +#define mpp_llogv_f(fmt, ...) mpp_llog(MPP_LOG_VERBOSE, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) + +#ifdef __cplusplus +extern "C" { +#endif + +extern RK_U32 mpp_debug; +void mpp_llog(int level, const char *tag, const char *fmt, const char *func, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEBUG_H */ diff --git a/osal/inc/mpp_dev_defs.h b/osal/inc/mpp_dev_defs.h new file mode 100644 index 000000000..be6195308 --- /dev/null +++ b/osal/inc/mpp_dev_defs.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_DEV_DEFS_H +#define MPP_DEV_DEFS_H + +#include "rk_type.h" + +/* + * Platform video codec hardware feature + */ +typedef enum MppClientType_e { + VPU_CLIENT_VDPU1 = 0, /* 0x00000001 */ + VPU_CLIENT_VDPU2 = 1, /* 0x00000002 */ + VPU_CLIENT_VDPU1_PP = 2, /* 0x00000004 */ + VPU_CLIENT_VDPU2_PP = 3, /* 0x00000008 */ + VPU_CLIENT_AV1DEC = 4, /* 0x00000010 */ + + VPU_CLIENT_HEVC_DEC = 8, /* 0x00000100 */ + VPU_CLIENT_RKVDEC = 9, /* 0x00000200 */ + VPU_CLIENT_AVSPLUS_DEC = 12, /* 0x00001000 */ + VPU_CLIENT_JPEG_DEC = 13, /* 0x00002000 */ + + VPU_CLIENT_RKVENC = 16, /* 0x00010000 */ + VPU_CLIENT_VEPU1 = 17, /* 0x00020000 */ + VPU_CLIENT_VEPU2 = 18, /* 0x00040000 */ + VPU_CLIENT_VEPU2_JPEG = 19, /* 0x00080000 */ + VPU_CLIENT_JPEG_ENC = 20, /* 0x00100000 */ + + VPU_CLIENT_VEPU22 = 24, /* 0x01000000 */ + + IEP_CLIENT_TYPE = 28, /* 0x10000000 */ + VDPP_CLIENT_TYPE = 29, /* 0x20000000 */ + + VPU_CLIENT_BUTT, +} MppClientType; + +#define CLIENT_TYPE_MASK_DEC 0x0000ffff +#define CLIENT_TYPE_MASK_ENC 0x0fff0000 +#define CLIENT_TYPE_MASK_VPROC 0xf0000000 + +/* RK combined codec */ +#define HAVE_VDPU1 (1 << VPU_CLIENT_VDPU1) /* 0x00000001 */ +#define HAVE_VDPU2 (1 << VPU_CLIENT_VDPU2) /* 0x00000002 */ +#define HAVE_VDPU1_PP (1 << VPU_CLIENT_VDPU1_PP) /* 0x00000004 */ +#define HAVE_VDPU2_PP (1 << VPU_CLIENT_VDPU2_PP) /* 0x00000008 */ +#define HAVE_AV1DEC (1 << VPU_CLIENT_AV1DEC) /* 0x00000008 */ +/* RK standalone decoder */ +#define HAVE_HEVC_DEC (1 << VPU_CLIENT_HEVC_DEC) /* 0x00000100 */ +#define HAVE_RKVDEC (1 << VPU_CLIENT_RKVDEC) /* 0x00000200 */ +#define HAVE_AVSDEC (1 << VPU_CLIENT_AVSPLUS_DEC) /* 0x00001000 */ +#define HAVE_JPEG_DEC (1 << VPU_CLIENT_JPEG_DEC) /* 0x00002000 */ +/* RK standalone encoder */ +#define HAVE_RKVENC (1 << VPU_CLIENT_RKVENC) /* 0x00010000 */ +#define HAVE_VEPU1 (1 << VPU_CLIENT_VEPU1) /* 0x00020000 */ +#define HAVE_VEPU2 (1 << VPU_CLIENT_VEPU2) /* 0x00040000 */ +#define HAVE_VEPU2_JPEG (1 << VPU_CLIENT_VEPU2_JPEG) /* 0x00080000 */ +#define HAVE_JPEG_ENC (1 << VPU_CLIENT_JPEG_ENC) /* 0x00100000 */ +/* External encoder */ +#define HAVE_VEPU22 (1 << VPU_CLIENT_VEPU22) /* 0x01000000 */ +/* RK Image Enhance Processor for deinterlacing */ +#define HAVE_IEP (1 << IEP_CLIENT_TYPE) /* 0x10000000 */ +/* RK Image Enhance Processor for dispaly */ +#define HAVE_VDPP (1 << VDPP_CLIENT_TYPE) /* 0x20000000 */ + +/* Platform image process hardware feature */ +#define HAVE_IPP (0x00000001) + +#endif /* MPP_DEV_DEFS_H */ diff --git a/osal/inc/mpp_device.h b/osal/inc/mpp_device.h new file mode 100644 index 000000000..765d3093e --- /dev/null +++ b/osal/inc/mpp_device.h @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_DEVICE_H +#define MPP_DEVICE_H + +#include "mpp_err.h" +#include "mpp_list.h" +#include "mpp_mem_pool.h" + +#include "mpp_dev_defs.h" +#include "mpp_callback.h" + +#define MPP_MAX_REG_TRANS_NUM 80 + +typedef void* MppDev; + +typedef enum MppDevIoctlCmd_e { + /* device batch mode config */ + MPP_DEV_BATCH_ON, + MPP_DEV_BATCH_OFF, + MPP_DEV_DELIMIT, + MPP_DEV_SET_CB_CTX, + + /* hardware operation setup config */ + MPP_DEV_REG_WR, + MPP_DEV_REG_RD, + MPP_DEV_REG_OFFSET, + MPP_DEV_REG_OFFS, + MPP_DEV_RCB_INFO, + MPP_DEV_SET_INFO, + MPP_DEV_SET_ERR_REF_HACK, + MPP_DEV_LOCK_MAP, + MPP_DEV_UNLOCK_MAP, + MPP_DEV_ATTACH_FD, + MPP_DEV_DETACH_FD, + + MPP_DEV_CMD_SEND, + MPP_DEV_CMD_POLL, + + MPP_DEV_IOCTL_CMD_BUTT, +} MppDevIoctlCmd; + +/* for MPP_DEV_REG_WR */ +typedef struct MppDevRegWrCfg_t { + void *reg; + RK_U32 size; + RK_U32 offset; +} MppDevRegWrCfg; + +/* for MPP_DEV_REG_RD */ +typedef struct MppDevRegRdCfg_t { + void *reg; + RK_U32 size; + RK_U32 offset; +} MppDevRegRdCfg; + +/* for MPP_DEV_REG_OFFSET */ +typedef struct MppDevRegOffsetCfg_t { + RK_U32 reg_idx; + RK_U32 offset; +} MppDevRegOffsetCfg; + +/* for multi MPP_DEV_REG_OFFSET */ +typedef struct MppDevRegOffsCfg_t { + RK_S32 size; + RK_S32 count; + MppDevRegOffsetCfg cfgs[0]; +} MppDevRegOffCfgs; + +/* for MPP_DEV_RCB_INFO */ +typedef struct MppDevRcbInfoCfg_t { + RK_U32 reg_idx; + RK_U32 size; +} MppDevRcbInfoCfg; + +/* for MPP_DEV_SET_INFO */ +typedef struct MppDevSetInfoCfg_t { + RK_U32 type; + RK_U32 flag; + RK_U64 data; +} MppDevInfoCfg; + +/* + * VEPU_5XX Slice Info Register Structure + * + * Different VEPU versions have different bitfield layouts: + * - VEPU580/541: 25-bit length + 7-bit reserved + * - VEPU510: 31-bit length + 1-bit last flag + * - VEPU511/511A: 30-bit length + 1-bit last + 1-bit stream_id + */ +typedef union MppDevPollEncSliceInfo_u { + RK_U32 val; + + /* Generic access - compatible with VEPU580/VEPU541 */ + struct { + RK_U32 length : 31; + RK_U32 last : 1; + }; + + /* VEPU510 specific access */ + struct { + RK_U32 sli_len : 31; + RK_U32 sli_lst : 1; + } vepu510; + + /* VEPU511/511A specific access */ + struct { + RK_U32 sli_len : 30; + RK_U32 sli_lst : 1; + RK_U32 sli_sid : 1; /* stream id */ + } vepu511; +} MppDevPollEncSliceInfo; + +/* for MPP_DEV_POLL */ +typedef struct MppDevPollCfg_t { + RK_S32 poll_type; + RK_S32 poll_ret; + RK_S32 count_max; + RK_S32 count_ret; + MppDevPollEncSliceInfo slice_info[0]; +} MppDevPollCfg; + +typedef struct MppDevBufMapNode_t { + /* data write by buffer function */ + struct list_head list_buf; + pthread_mutex_t *lock_buf; + MppBuffer buffer; + MppDev dev; + MppMemPool pool; + RK_S32 buf_fd; + + /* data write by device function */ + struct list_head list_dev; + pthread_mutex_t *lock_dev; + RK_S32 dev_fd; + RK_U32 iova; +} MppDevBufMapNode; + +typedef struct MppDevApi_t { + const char *name; + RK_U32 ctx_size; + MPP_RET (*init)(void *ctx, MppClientType type); + MPP_RET (*deinit)(void *ctx); + + /* bat mode function */ + MPP_RET (*attach)(void *ctx); + MPP_RET (*detach)(void *ctx); + MPP_RET (*delimit)(void *ctx); + MPP_RET (*set_cb_ctx)(void *ctx, MppCbCtx *cb); + + /* config the cmd on preparing */ + MPP_RET (*reg_wr)(void *ctx, MppDevRegWrCfg *cfg); + MPP_RET (*reg_rd)(void *ctx, MppDevRegRdCfg *cfg); + MPP_RET (*reg_offset)(void *ctx, MppDevRegOffsetCfg *cfg); + MPP_RET (*reg_offs)(void *ctx, MppDevRegOffCfgs *cfg); + MPP_RET (*rcb_info)(void *ctx, MppDevRcbInfoCfg *cfg); + MPP_RET (*set_info)(void *ctx, MppDevInfoCfg *cfg); + MPP_RET (*set_err_ref_hack)(void *ctx, RK_U32 *enable); + + /* buffer attach / detach */ + MPP_RET (*lock_map)(void *ctx); + MPP_RET (*unlock_map)(void *ctx); + MPP_RET (*attach_fd)(void *ctx, MppDevBufMapNode *node); + MPP_RET (*detach_fd)(void *ctx, MppDevBufMapNode *node); + + /* send cmd to hardware */ + MPP_RET (*cmd_send)(void *ctx); + + /* poll cmd from hardware */ + MPP_RET (*cmd_poll)(void *ctx, MppDevPollCfg *cfg); +} MppDevApi; + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_dev_init(MppDev *ctx, MppClientType type); +MPP_RET mpp_dev_deinit(MppDev ctx); + +MPP_RET mpp_dev_ioctl(MppDev ctx, RK_S32 cmd, void *param); + +/* special helper function for large address offset config */ +MPP_RET mpp_dev_set_reg_offset(MppDev dev, RK_S32 index, RK_U32 offset); + +/* register offset multi config */ +MPP_RET mpp_dev_multi_offset_init(MppDevRegOffCfgs **cfgs, RK_S32 size); +MPP_RET mpp_dev_multi_offset_deinit(MppDevRegOffCfgs *cfgs); + +MPP_RET mpp_dev_multi_offset_reset(MppDevRegOffCfgs *cfgs); +MPP_RET mpp_dev_multi_offset_update(MppDevRegOffCfgs *cfgs, RK_S32 index, RK_U32 offset); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DEVICE_H */ diff --git a/osal/inc/mpp_dmabuf.h b/osal/inc/mpp_dmabuf.h new file mode 100644 index 000000000..cc123595a --- /dev/null +++ b/osal/inc/mpp_dmabuf.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_DMABUF_H +#define MPP_DMABUF_H + +#include "rk_type.h" +#include "mpp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MPP_RET mpp_dmabuf_sync_begin(RK_S32 fd, RK_S32 ro, const char *caller); +MPP_RET mpp_dmabuf_sync_end(RK_S32 fd, RK_S32 ro, const char *caller); +MPP_RET mpp_dmabuf_sync_partial_begin(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller); +MPP_RET mpp_dmabuf_sync_partial_end(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller); +MPP_RET mpp_dmabuf_set_name(RK_S32 fd, const char *name, const char *caller); + +RK_U32 mpp_dmabuf_sync_partial_support(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_DMABUF_H */ \ No newline at end of file diff --git a/osal/inc/mpp_env.h b/osal/inc/mpp_env.h index c22ba4812..42e8739e5 100644 --- a/osal/inc/mpp_env.h +++ b/osal/inc/mpp_env.h @@ -1,37 +1,26 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_ENV_H__ -#define __MPP_ENV_H__ - -#include "rk_type.h" - -#ifdef __cplusplus -extern "C" { -#endif - -RK_S32 mpp_env_get_u32(const char *name, RK_U32 *value, RK_U32 default_value); -RK_S32 mpp_env_get_str(const char *name, char **value, char *default_value); - -RK_S32 mpp_env_set_u32(const char *name, RK_U32 value); -RK_S32 mpp_env_set_str(const char *name, char *value); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_ENV_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_ENV_H +#define MPP_ENV_H + +#include "rk_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_env_get_u32(const char *name, RK_U32 *value, RK_U32 default_value); +RK_S32 mpp_env_get_str(const char *name, const char **value, const char *default_value); + +RK_S32 mpp_env_set_u32(const char *name, RK_U32 value); +RK_S32 mpp_env_set_str(const char *name, char *value); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_ENV_H */ + diff --git a/osal/inc/mpp_eventfd.h b/osal/inc/mpp_eventfd.h new file mode 100644 index 000000000..40e5fc3c9 --- /dev/null +++ b/osal/inc/mpp_eventfd.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_EVENTFD_H +#define MPP_EVENTFD_H + +#include "rk_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_eventfd_get(RK_U32 init); +RK_S32 mpp_eventfd_put(RK_S32 fd); + +RK_S32 mpp_eventfd_read(RK_S32 fd, RK_U64 *val, RK_S64 timeout); +RK_S32 mpp_eventfd_write(RK_S32 fd, RK_U64 val); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_EVENTFD_H */ + diff --git a/osal/inc/mpp_hash.h b/osal/inc/mpp_hash.h new file mode 100644 index 000000000..8198c722b --- /dev/null +++ b/osal/inc/mpp_hash.h @@ -0,0 +1,379 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_HASH_H +#define MPP_HASH_H + +#include +#include + +#include "rk_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GOLDEN_RATIO_32 0x61C88647U +#define GOLDEN_RATIO_64 0x61C8864680B583EBULL + +#if __SIZEOF_POINTER__ == 4 +#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32 +#define hash_long(val, bits) hash_32(val, bits) +#elif __SIZEOF_POINTER__ == 8 +#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64 +#define hash_long(val, bits) hash_64(val, bits) +#else +#error __SIZEOF_POINTER__ not 4 or 8 +#endif + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +struct hlist_head { + struct hlist_node *first; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) + +#define LIST_POISON1 ((struct hlist_node*) 0x100) +#define LIST_POISON2 ((struct hlist_node**) 0x200) + +#define WRITE_ONCE(var, val) \ + (*((volatile typeof(val) *)(&(var))) = (val)) + +#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) + +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return (h->pprev == NULL) ? 1 : 0; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return (READ_ONCE(h->first) == NULL) ? 1 : 0; +} + +static inline void hlist_del_(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + + WRITE_ONCE(*pprev, next); + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + hlist_del_(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (hlist_unhashed(n) == 0) { + hlist_del_(n); + INIT_HLIST_NODE(n); + } +} + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + WRITE_ONCE(h->first, n); + n->pprev = &h->first; +} + +static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + WRITE_ONCE(*(n->pprev), n); +} + +static inline void hlist_add_behind(struct hlist_node *n, struct hlist_node *prev) +{ + n->next = prev->next; + WRITE_ONCE(prev->next, n); + n->pprev = &prev->next; + + if (n->next) + n->next->pprev = &n->next; +} + +static inline void hlist_add_fake(struct hlist_node *n) +{ + n->pprev = &n->next; +} + +static inline int hlist_fake(struct hlist_node *h) +{ + return (h->pprev == &h->next) ? 1 : 0; +} + +static inline int +hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h) +{ + return (!n->next && n->pprev == &h->first) ? 1 : 0; +} + +static inline void hlist_move_list(struct hlist_head *old, + struct hlist_head *_new) +{ + _new->first = old->first; + if (_new->first) + _new->first->pprev = &_new->first; + old->first = NULL; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos ; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +#define hlist_entry_safe(ptr, type, member) \ + ({ typeof(ptr) ____ptr = (ptr); \ + ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + }) + +#define hlist_for_each_entry(pos, head, member) \ + for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ + pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +#define hlist_for_each_entry_continue(pos, member) \ + for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\ + pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +#define hlist_for_each_entry_from(pos, member) \ + for (; pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +#define hlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\ + pos && ({ n = pos->member.next; 1; }); \ + pos = hlist_entry_safe(n, typeof(*pos), member)) + +#define DEFINE_HASHTABLE(name, bits) \ + struct hlist_head name[1 << (bits)] = \ + { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } + +#define DECLARE_HASHTABLE(name, bits) \ + struct hlist_head name[1 << (bits)] + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +#define ilog2(n) \ + ( \ + (n) & (1ULL << 63) ? 63 : \ + (n) & (1ULL << 62) ? 62 : \ + (n) & (1ULL << 61) ? 61 : \ + (n) & (1ULL << 60) ? 60 : \ + (n) & (1ULL << 59) ? 59 : \ + (n) & (1ULL << 58) ? 58 : \ + (n) & (1ULL << 57) ? 57 : \ + (n) & (1ULL << 56) ? 56 : \ + (n) & (1ULL << 55) ? 55 : \ + (n) & (1ULL << 54) ? 54 : \ + (n) & (1ULL << 53) ? 53 : \ + (n) & (1ULL << 52) ? 52 : \ + (n) & (1ULL << 51) ? 51 : \ + (n) & (1ULL << 50) ? 50 : \ + (n) & (1ULL << 49) ? 49 : \ + (n) & (1ULL << 48) ? 48 : \ + (n) & (1ULL << 47) ? 47 : \ + (n) & (1ULL << 46) ? 46 : \ + (n) & (1ULL << 45) ? 45 : \ + (n) & (1ULL << 44) ? 44 : \ + (n) & (1ULL << 43) ? 43 : \ + (n) & (1ULL << 42) ? 42 : \ + (n) & (1ULL << 41) ? 41 : \ + (n) & (1ULL << 40) ? 40 : \ + (n) & (1ULL << 39) ? 39 : \ + (n) & (1ULL << 38) ? 38 : \ + (n) & (1ULL << 37) ? 37 : \ + (n) & (1ULL << 36) ? 36 : \ + (n) & (1ULL << 35) ? 35 : \ + (n) & (1ULL << 34) ? 34 : \ + (n) & (1ULL << 33) ? 33 : \ + (n) & (1ULL << 32) ? 32 : \ + (n) & (1ULL << 31) ? 31 : \ + (n) & (1ULL << 30) ? 30 : \ + (n) & (1ULL << 29) ? 29 : \ + (n) & (1ULL << 28) ? 28 : \ + (n) & (1ULL << 27) ? 27 : \ + (n) & (1ULL << 26) ? 26 : \ + (n) & (1ULL << 25) ? 25 : \ + (n) & (1ULL << 24) ? 24 : \ + (n) & (1ULL << 23) ? 23 : \ + (n) & (1ULL << 22) ? 22 : \ + (n) & (1ULL << 21) ? 21 : \ + (n) & (1ULL << 20) ? 20 : \ + (n) & (1ULL << 19) ? 19 : \ + (n) & (1ULL << 18) ? 18 : \ + (n) & (1ULL << 17) ? 17 : \ + (n) & (1ULL << 16) ? 16 : \ + (n) & (1ULL << 15) ? 15 : \ + (n) & (1ULL << 14) ? 14 : \ + (n) & (1ULL << 13) ? 13 : \ + (n) & (1ULL << 12) ? 12 : \ + (n) & (1ULL << 11) ? 11 : \ + (n) & (1ULL << 10) ? 10 : \ + (n) & (1ULL << 9) ? 9 : \ + (n) & (1ULL << 8) ? 8 : \ + (n) & (1ULL << 7) ? 7 : \ + (n) & (1ULL << 6) ? 6 : \ + (n) & (1ULL << 5) ? 5 : \ + (n) & (1ULL << 4) ? 4 : \ + (n) & (1ULL << 3) ? 3 : \ + (n) & (1ULL << 2) ? 2 : \ + (n) & (1ULL << 1) ? 1 : 0 \ + ) + +#define HASH_SIZE(name) (ARRAY_SIZE(name)) +#define HASH_BITS(name) ilog2(HASH_SIZE(name)) + +/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */ +#define hash_min(val, bits) \ + (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits)) + +#define hash_add(hashtable, node, key) \ + hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) + +/** + * hash_empty - check whether a hashtable is empty + * @hashtable: hashtable to check + * + * This has to be a macro since HASH_BITS() will not work on pointers since + * it calculates the size during preprocessing. + */ +#define hash_empty(hashtable) hash_empty_(hashtable, HASH_SIZE(hashtable)) + +/** + * hash_for_each - iterate over a hashtable + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each(name, bkt, obj, member) \ + for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name); \ + (bkt)++) \ + hlist_for_each_entry(obj, &name[bkt], member) + +/** + * hash_for_each_safe - iterate over a hashtable safe against removal of + * hash entry + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @tmp: a &struct used for temporary storage + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each_safe(name, bkt, tmp, obj, member) \ + for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name); \ + (bkt)++) \ + hlist_for_each_entry_safe(obj, tmp, &name[bkt], member) + +#define hash_for_each_possible(name, obj, member, key) \ + hlist_for_each_entry(obj, &name[hash_min(key, HASH_BITS(name))], member) + +static inline RK_U32 hash_32(RK_U32 val, unsigned int bits) +{ + /* On some cpus multiply is faster, on others gcc will do shifts */ + RK_U32 hash = val * GOLDEN_RATIO_32; + + /* High bits are more random, so use them. */ + return hash >> (32U - bits); +} + +static inline RK_U32 hash_32_(RK_U32 val) +{ + return val * GOLDEN_RATIO_32; +} + +static inline RK_U32 hash_64(RK_U64 val, unsigned int bits) +{ +#if __SIZEOF_POINTER__ == 8 + /* 64x64-bit multiply is efficient on all 64-bit processors */ + return (RK_U32)(val * GOLDEN_RATIO_64 >> (64U - bits)); +#else + /* Hash 64 bits using only 32x32-bit multiply. */ + RK_U32 val_low32 = (RK_U32)(val & 0xFFFFFFFFU); + RK_U32 val_high32 = (RK_U32)(val >> 32); + + return hash_32(val_low32 ^ (val_high32 * GOLDEN_RATIO_32), bits); +#endif +} + +static inline RK_U32 hash_ptr(const void *ptr, unsigned int bits) +{ + return hash_long((unsigned long)(uintptr_t)ptr, bits); +} + +/* This really should be called fold32_ptr; it does no hashing to speak of. */ +static inline RK_U32 hash32_ptr(const void *ptr) +{ + unsigned long val = (unsigned long)(uintptr_t)ptr; + +#if __SIZEOF_POINTER__ == 8 + val ^= (val >> 32); +#endif + return (RK_U32)val; +} + +/** + * hash_hashed - check whether an object is in any hashtable + * @node: the &struct hlist_node of the object to be checked + */ +static inline bool hash_hashed(struct hlist_node *node) +{ + return hlist_unhashed(node) == 0; +} + +static inline bool hash_empty_(struct hlist_head *ht, unsigned int sz) +{ + unsigned int i; + + for (i = 0; i < sz; i++) + if (hlist_empty(&ht[i]) == 0) + return false; + + return true; +} + +/** + * hash_del - remove an object from a hashtable + * @node: &struct hlist_node of the object to remove + */ +static inline void hash_del(struct hlist_node *node) +{ + hlist_del_init(node); +} + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_HASH_H */ diff --git a/osal/inc/mpp_list.h b/osal/inc/mpp_list.h index a8454acd7..49ad05833 100644 --- a/osal/inc/mpp_list.h +++ b/osal/inc/mpp_list.h @@ -1,95 +1,75 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ /* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. */ -#ifndef __MPP_LIST_H__ -#define __MPP_LIST_H__ +#ifndef MPP_LIST_H +#define MPP_LIST_H #include "rk_type.h" +#include "mpp_err.h" #include "mpp_thread.h" /* - * two list structures are defined, one for C++, the other for C + * two list structures are defined here: + * 1. MppList : list with key + * 2. struct list_head : typical list head */ #ifdef __cplusplus +extern "C" { +#endif +typedef struct MppListNode_t MppListNode; // desctructor of list node -typedef void *(*node_destructor)(void *); +typedef void *(*node_destructor)(void *arg); -struct mpp_list_node; -class mpp_list -{ -public: - mpp_list(node_destructor func); - ~mpp_list(); - - // for FIFO or FILO implement - // adding functions support simple structure like C struct or C++ class pointer, - // do not support C++ object - RK_S32 add_at_head(void *data, RK_S32 size); - RK_S32 add_at_tail(void *data, RK_S32 size); - // deleting function will copy the stored data to input pointer with size as size - // if NULL is passed to deleting functions, the node will be delete directly - RK_S32 del_at_head(void *data, RK_S32 size); - RK_S32 del_at_tail(void *data, RK_S32 size); - - // for status check - RK_S32 list_is_empty(); - RK_S32 list_size(); - - // for vector implement - not implemented yet - // adding function will return a key - RK_S32 add_by_key(void *data, RK_S32 size, RK_U32 *key); - RK_S32 del_by_key(void *data, RK_S32 size, RK_U32 key); - RK_S32 show_by_key(void *data, RK_U32 key); - - RK_S32 flush(); - - // open lock function for external combination usage - void lock(); - void unlock(); - RK_S32 trylock(); - - // open lock function for external auto lock - Mutex *mutex(); - - void wait(); - void signal(); - -private: - Mutex mMutex; - Condition mCondition; - - node_destructor destroy; - struct mpp_list_node *head; - RK_S32 count; - static RK_U32 keys; - static RK_U32 get_key(); - - mpp_list(); - mpp_list(const mpp_list &); - mpp_list &operator=(const mpp_list &); +struct MppListNode_t { + MppListNode *prev; + MppListNode *next; + rk_u32 key; + rk_s32 size; }; -#endif +typedef struct MppList_t { + MppListNode *head; + int count; + node_destructor destroy; + MppMutexCond cond_lock; + rk_u32 keys; +} MppList; + +int mpp_list_add_at_head(MppList *list, void *data, int size); +int mpp_list_add_at_tail(MppList *list, void *data, int size); +int mpp_list_del_at_head(MppList *list, void *data, int size); +int mpp_list_del_at_tail(MppList *list, void *data, int size); + +rk_s32 mpp_list_fifo_wr(MppList *list, void *data, rk_s32 size); +rk_s32 mpp_list_fifo_rd(MppList *list, void *data, rk_s32 *size); + +int mpp_list_is_empty(MppList *list); +int mpp_list_size(MppList *list); + +rk_s32 mpp_list_add_by_key(MppList *list, void *data, rk_s32 size, rk_u32 *key); +rk_s32 mpp_list_del_by_key(MppList *list, void *data, rk_s32 size, rk_u32 key); +rk_s32 mpp_list_show_by_key(MppList *list, void *data, rk_u32 key); + +void mpp_list_flush(MppList *list); + +MPP_RET mpp_list_wait(MppList* list); +MPP_RET mpp_list_wait_timed(MppList *list, rk_s64 timeout); +MPP_RET mpp_list_wait_lt(MppList *list, rk_s64 timeout, rk_s32 val); +MPP_RET mpp_list_wait_le(MppList *list, rk_s64 timeout, rk_s32 val); +MPP_RET mpp_list_wait_gt(MppList *list, rk_s64 timeout, rk_s32 val); +MPP_RET mpp_list_wait_ge(MppList *list, rk_s64 timeout, rk_s32 val); + +void mpp_list_signal(MppList *list); +rk_u32 mpp_list_get_key(MppList *list); + +MppList *mpp_list_create(node_destructor func); +void mpp_list_destroy(MppList *list); -#ifdef __cplusplus -extern "C" { -#endif struct list_head { struct list_head *next, *prev; @@ -111,25 +91,49 @@ struct list_head { #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -/* - * due to typeof gcc extension list_for_each_entry and list_for_each_entry_safe - * can not be used on windows platform - * So we add a extra type parameter to the macro - */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +#define list_first_entry_or_null(ptr, type, member) ({ \ + struct list_head *head__ = (ptr); \ + struct list_head *pos__ = head__->next; \ + pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ +}) + +#define list_next_entry(pos, type, member) \ + list_entry((pos)->member.next, type, member) + +#define list_prev_entry(pos, type, member) \ + list_entry((pos)->member.prev, type, member) + #define list_for_each_entry(pos, head, type, member) \ for (pos = list_entry((head)->next, type, member); \ &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member)) + pos = list_next_entry(pos, type, member)) #define list_for_each_entry_safe(pos, n, head, type, member) \ - for (pos = list_entry((head)->next, type, member), \ - n = list_entry(pos->member.next, type, member); \ + for (pos = list_first_entry(head, type, member), \ + n = list_next_entry(pos, type, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, type, member)) + +#define list_for_each_entry_reverse(pos, head, type, member) \ + for (pos = list_last_entry(head, type, member); \ + &pos->member != (head); \ + pos = list_prev_entry(pos, type, member)) + +#define list_for_each_entry_safe_reverse(pos, n, head, type, member) \ + for (pos = list_last_entry(head, type, member), \ + n = list_prev_entry(pos, type, member); \ &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) + pos = n, n = list_prev_entry(n, type, member)) -static __inline void __list_add(struct list_head * _new, - struct list_head * prev, - struct list_head * next) +static __inline void list_add_(struct list_head * _new, + struct list_head * prev, + struct list_head * next) { next->prev = _new; _new->next = next; @@ -139,15 +143,15 @@ static __inline void __list_add(struct list_head * _new, static __inline void list_add(struct list_head *_new, struct list_head *head) { - __list_add(_new, head, head->next); + list_add_(_new, head, head->next); } static __inline void list_add_tail(struct list_head *_new, struct list_head *head) { - __list_add(_new, head->prev, head); + list_add_(_new, head->prev, head); } -static __inline void __list_del(struct list_head * prev, struct list_head * next) +static __inline void list_del_(struct list_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; @@ -155,24 +159,40 @@ static __inline void __list_del(struct list_head * prev, struct list_head * next static __inline void list_del_init(struct list_head *entry) { - __list_del(entry->prev, entry->next); + list_del_(entry->prev, entry->next); INIT_LIST_HEAD(entry); } +static __inline void list_move(struct list_head *list, struct list_head *head) +{ + list_del_(list->prev, list->next); + list_add(list, head); +} + +static __inline void list_move_tail(struct list_head *list, struct list_head *head) +{ + list_del_(list->prev, list->next); + list_add_tail(list, head); +} + static __inline int list_is_last(const struct list_head *list, const struct list_head *head) { - return list->next == head; + return (list->next == head) ? 1 : 0; } static __inline int list_empty(struct list_head *head) { - return head->next == head; + return (head->next == head) ? 1 : 0; } +typedef rk_s32 (*ListCmpFunc)(void *arg, const struct list_head *list1, const struct list_head *list2); + +void list_sort(void *priv, struct list_head *head, ListCmpFunc cmp); + #ifdef __cplusplus } #endif -#endif /*__MPP_LIST_H__*/ +#endif /* MPP_LIST_H */ diff --git a/osal/inc/mpp_lock.h b/osal/inc/mpp_lock.h new file mode 100644 index 000000000..655582971 --- /dev/null +++ b/osal/inc/mpp_lock.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_LOCK_H +#define MPP_LOCK_H + +#include + +#include "rk_type.h" + +#define MPP_FETCH_ADD __sync_fetch_and_add +#define MPP_FETCH_SUB __sync_fetch_and_sub +#define MPP_FETCH_OR __sync_fetch_and_or +#define MPP_FETCH_AND __sync_fetch_and_and +#define MPP_FETCH_XOR __sync_fetch_and_xor +#define MPP_FETCH_NAND __sync_fetch_and_nand + +#define MPP_ADD_FETCH __sync_add_and_fetch +#define MPP_SUB_FETCH __sync_sub_and_fetch +#define MPP_OR_FETCH __sync_or_and_fetch +#define MPP_AND_FETCH __sync_and_and_fetch +#define MPP_XOR_FETCH __sync_xor_and_fetch +#define MPP_NAND_FETCH __sync_nand_and_fetch + +#define MPP_BOOL_CAS __sync_bool_compare_and_swap +#define MPP_VAL_CAS __sync_val_compare_and_swap + +#define MPP_SYNC __sync_synchronize +#define MPP_SYNC_TEST_SET __sync_lock_test_and_set +#define MPP_SYNC_CLR __sync_lock_release + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + RK_U32 lock; + RK_U32 debug; + RK_S64 count; + RK_S64 time; +} spinlock_t; + +void mpp_spinlock_init(spinlock_t *lock); +void mpp_spinlock_deinit(spinlock_t *lock, const char *name); +void mpp_spinlock_lock(spinlock_t *lock); +void mpp_spinlock_unlock(spinlock_t *lock); +bool mpp_spinlock_trylock(spinlock_t *lock); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_LOCK_H */ diff --git a/osal/inc/mpp_log.h b/osal/inc/mpp_log.h deleted file mode 100644 index 035a40094..000000000 --- a/osal/inc/mpp_log.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_LOG_H__ -#define __MPP_LOG_H__ - -#include "rk_type.h" -#include - -/* - * mpp runtime log system usage: - * mpp_err is for error status message, it will print for sure. - * mpp_log is for important message like open/close/reset/flush, it will print too. - * mpp_dbg is for all optional message. it can be controlled by debug and flag. - */ - -#define mpp_log(fmt, ...) _mpp_log(MODULE_TAG, fmt, NULL, ## __VA_ARGS__) -#define mpp_err(fmt, ...) _mpp_err(MODULE_TAG, fmt, NULL, ## __VA_ARGS__) - -#define _mpp_dbg(debug, flag, fmt, ...) \ - __mpp_dbg(debug, flag, MODULE_TAG, fmt, NULL, ## __VA_ARGS__) - -extern RK_U32 mpp_debug; -#define mpp_dbg(flag, fmt, ...) _mpp_dbg(mpp_debug, flag, fmt, ## __VA_ARGS__) - -/* - * _f function will add function name to the log - */ -#define mpp_log_f(fmt, ...) _mpp_log(MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) -#define mpp_err_f(fmt, ...) _mpp_err(MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) -#define _mpp_dbg_f(debug, flag, fmt, ...) \ - __mpp_dbg(debug, flag, MODULE_TAG, fmt, __FUNCTION__, ## __VA_ARGS__) - -/* - * mpp_dbg usage: - * - * in h264d module define module debug flag variable like: h265d_debug - * then define h265d_dbg macro as follow : - * - * extern RK_U32 h265d_debug; - * - * #define H265D_DBG_FUNCTION (0x00000001) - * #define H265D_DBG_VPS (0x00000002) - * #define H265D_DBG_SPS (0x00000004) - * #define H265D_DBG_PPS (0x00000008) - * #define H265D_DBG_SLICE_HDR (0x00000010) - * - * #define h265d_dbg(flag, fmt, ...) mpp_dbg(h265d_debug, flag, fmt, ## __VA_ARGS__) - * - * finally use environment control the debug flag - * - * mpp_get_env_u32("h264d_debug", &h265d_debug, 0) - * - */ -/* - * sub-module debug flag usage example: - * +------+-------------------+ - * | 8bit | 24bit | - * +------+-------------------+ - * 0~15 bit: software debug print - * 16~23 bit: hardware debug print - * 24~31 bit: information print format - */ - -#ifdef __DEBUG -#define mpp_abort() abort() -#else -#define mpp_abort() -#endif - -#define MPP_STRINGS(x) MPP_TO_STRING(x) -#define MPP_TO_STRING(x) #x - -#define mpp_assert(cond) do { \ - if (!(cond)) { \ - mpp_err("Assertion %s failed at %s:%d\n", \ - MPP_STRINGS(cond), __FILE__, __LINE__); \ - mpp_abort(); \ - } \ -} while (0) - - -#ifdef __cplusplus -extern "C" { -#endif - -void mpp_log_set_flag(RK_U32 flag); -RK_U32 mpp_log_get_flag(); - -void _mpp_log(const char *tag, const char *fmt, const char *func, ...); -void _mpp_err(const char *tag, const char *fmt, const char *func, ...); -void __mpp_dbg(RK_U32 debug, RK_U32 flag, const char *tag, const char *fmt, const char *func, ...); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_LOG_H__*/ diff --git a/osal/inc/mpp_mem.h b/osal/inc/mpp_mem.h index c77d31d4a..5e0ec34cc 100644 --- a/osal/inc/mpp_mem.h +++ b/osal/inc/mpp_mem.h @@ -1,65 +1,59 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_MEM_H__ -#define __MPP_MEM_H__ - -#include - -#include "rk_type.h" - -#define mpp_malloc_tagged(type, count, tag) \ - (type*)mpp_osal_malloc(tag, sizeof(type) * (count)) - -#define mpp_malloc(type, count) \ - (type*)mpp_osal_malloc(MODULE_TAG, sizeof(type) * (count)) - -#define mpp_malloc_size(type, size) \ - (type*)mpp_osal_malloc(MODULE_TAG, size) - -#define mpp_calloc_size(type, size) \ - (type*)mpp_osal_calloc(MODULE_TAG, size) - -#define mpp_calloc(type, count) \ - (type*)mpp_osal_calloc(MODULE_TAG, sizeof(type) * (count)) - -#define mpp_realloc(ptr, type, count) \ - (type*)mpp_osal_realloc(MODULE_TAG, ptr, sizeof(type) * (count)) - -#define mpp_free(ptr) \ - do { \ - if (ptr) { \ - mpp_osal_free(ptr); \ - ptr = NULL; \ - } \ - } while (0) - -#ifdef __cplusplus -extern "C" { -#endif - -void mpp_show_mem_status(); -void *mpp_osal_malloc(const char *tag, size_t size); -void *mpp_osal_calloc(const char *tag, size_t size); -void *mpp_osal_realloc(const char *tag, void *ptr, size_t size); -void mpp_osal_free(void *ptr); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_MEM_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_MEM_H +#define MPP_MEM_H + +#include + +#include "rk_type.h" +#include "mpp_err.h" + +#define mpp_malloc_with_caller(type, count, caller) \ + (type*)mpp_osal_malloc(caller, sizeof(type) * (count)) + +#define mpp_malloc(type, count) \ + (type*)mpp_osal_malloc(__FUNCTION__, sizeof(type) * (count)) + +#define mpp_malloc_size(type, size) \ + (type*)mpp_osal_malloc(__FUNCTION__, size) + +#define mpp_calloc(type, count) \ + (type*)mpp_osal_calloc(__FUNCTION__, sizeof(type) * (count)) + +#define mpp_calloc_size(type, size) \ + (type*)mpp_osal_calloc(__FUNCTION__, size) + +#define mpp_realloc(ptr, type, count) \ + (type*)mpp_osal_realloc(__FUNCTION__, ptr, sizeof(type) * (count)) + +#define mpp_realloc_size(ptr, type, size) \ + (type*)mpp_osal_realloc(__FUNCTION__, ptr, size) + +#define mpp_free(ptr) \ + mpp_osal_free(__FUNCTION__, ptr) + +#define MPP_FREE(ptr) do { if(ptr) mpp_free(ptr); ptr = NULL; } while (0) +#define MPP_FCLOSE(fp) do { if(fp) fclose(fp); fp = NULL; } while (0) + +#ifdef __cplusplus +extern "C" { +#endif + +void *mpp_osal_malloc(const char *caller, size_t size); +void *mpp_osal_calloc(const char *caller, size_t size); +void *mpp_osal_realloc(const char *caller, void *ptr, size_t size); +void mpp_osal_free(const char *caller, void *ptr); + +void mpp_show_mem_status(void); +rk_u32 mpp_mem_total_now(void); +rk_u32 mpp_mem_total_max(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_MEM_H */ + diff --git a/osal/inc/mpp_mem_pool.h b/osal/inc/mpp_mem_pool.h new file mode 100644 index 000000000..3574a3454 --- /dev/null +++ b/osal/inc/mpp_mem_pool.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_MEM_POOL_H +#define MPP_MEM_POOL_H + +#include "mpp_mem.h" + +typedef void* MppMemPool; + +#ifdef __cplusplus +extern "C" { +#endif + +#define mpp_mem_pool_init_f(name, size) mpp_mem_pool_init(name, size, __FUNCTION__) +#define mpp_mem_pool_deinit_f(pool) mpp_mem_pool_deinit(pool, __FUNCTION__); + +#define mpp_mem_pool_get_f(pool) mpp_mem_pool_get(pool, __FUNCTION__) +#define mpp_mem_pool_put_f(pool, p) mpp_mem_pool_put(pool, p, __FUNCTION__) + +MppMemPool mpp_mem_pool_init(const char *name, size_t size, const char *caller); +void mpp_mem_pool_deinit(MppMemPool pool, const char *caller); + +void *mpp_mem_pool_get(MppMemPool pool, const char *caller); +void mpp_mem_pool_put(MppMemPool pool, void *p, const char *caller); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_MEM_POOL_H */ diff --git a/osal/inc/mpp_platform.h b/osal/inc/mpp_platform.h new file mode 100644 index 000000000..e89dee5b2 --- /dev/null +++ b/osal/inc/mpp_platform.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_PLATFORM_H +#define MPP_PLATFORM_H + +#include "rk_type.h" +#include "mpp_soc.h" + +/* + * Platform flag detection is for rockchip hardware platform detection + */ +typedef enum MppIoctlVersion_e { + IOCTL_VCODEC_SERVICE, + IOCTL_MPP_SERVICE_V1, + IOCTL_VERSION_BUTT, +} MppIoctlVersion; + +typedef enum MppKernelVersion_e { + KERNEL_UNKNOWN, + KERNEL_3_10, + KERNEL_4_4, + KERNEL_4_19, + KERNEL_5_10, + KERNEL_6_1, + KERNEL_VERSION_BUTT, +} MppKernelVersion; + +#ifdef __cplusplus +extern "C" { +#endif + +MppIoctlVersion mpp_get_ioctl_version(void); +MppKernelVersion mpp_get_kernel_version(void); +rk_u32 mpp_get_2d_hw_flag(void); +rk_u32 mpp_get_client_hw_id(RK_S32 client_type); +rk_u32 mpp_get_vcodec_type(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_PLATFORM_H */ diff --git a/osal/inc/mpp_queue.h b/osal/inc/mpp_queue.h new file mode 100644 index 000000000..f2250364e --- /dev/null +++ b/osal/inc/mpp_queue.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_QUEUE_H +#define MPP_QUEUE_H + +#include "mpp_list.h" + +typedef struct MppQueue_t { + MppList* list; + sem_t queue_pending; + int flush_flag; +} MppQueue; + +#endif diff --git a/osal/inc/mpp_ring.h b/osal/inc/mpp_ring.h new file mode 100644 index 000000000..a2dc9ba0f --- /dev/null +++ b/osal/inc/mpp_ring.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_RING_H +#define MPP_RING_H + +#include "rk_type.h" + +typedef void* MppRing; + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_ring_get(MppRing *ring, rk_s32 size, const char *name); +rk_s32 mpp_ring_put(MppRing ring); + +void *mpp_ring_get_ptr(MppRing ring); +/* resize ring buffer to new size */ +void *mpp_ring_resize(MppRing ring, rk_s32 new_size); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_RING_H */ diff --git a/osal/inc/mpp_runtime.h b/osal/inc/mpp_runtime.h new file mode 100644 index 000000000..90a2f19b8 --- /dev/null +++ b/osal/inc/mpp_runtime.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_RUNTIME_H +#define MPP_RUNTIME_H + +#include "mpp_buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Runtime function detection is to support different binary on different + * runtime environment. This is usefull on product environemnt. + */ +rk_u32 mpp_rt_allcator_is_valid(MppBufferType type); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_RUNTIME_H */ + diff --git a/osal/inc/mpp_server.h b/osal/inc/mpp_server.h new file mode 100644 index 000000000..959bcbdb6 --- /dev/null +++ b/osal/inc/mpp_server.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SERVER_H +#define MPP_SERVER_H + +#include "mpp_device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_server_attach(MppDev ctx); +rk_s32 mpp_server_detach(MppDev ctx); + +rk_s32 mpp_server_send_task(MppDev ctx); +rk_s32 mpp_server_wait_task(MppDev ctx, RK_S64 timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SERVER_H */ diff --git a/osal/inc/mpp_service.h b/osal/inc/mpp_service.h new file mode 100644 index 000000000..213c07ffd --- /dev/null +++ b/osal/inc/mpp_service.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SERVICE_H +#define MPP_SERVICE_H + +#include "rk_type.h" +#include + +/* Use 'v' as magic number */ +#define MPP_IOC_MAGIC 'v' +#define MPP_IOC_CFG_V1 _IOW(MPP_IOC_MAGIC, 1, unsigned int) +#define MAX_REQ_NUM 16 + +#if __SIZEOF_POINTER__ == 4 +#define REQ_DATA_PTR(ptr) ((RK_U32)ptr) +#elif __SIZEOF_POINTER__ == 8 +#define REQ_DATA_PTR(ptr) ((RK_U64)ptr) +#endif + +/* define flags for mpp_request */ +#define MPP_FLAGS_MULTI_MSG (0x00000001) +#define MPP_FLAGS_LAST_MSG (0x00000002) +#define MPP_FLAGS_REG_FD_NO_TRANS (0x00000004) +#define MPP_FLAGS_SCL_FD_NO_TRANS (0x00000008) +#define MPP_FLAGS_REG_OFFSET_ALONE (0x00000010) +#define MPP_FLAGS_POLL_NON_BLOCK (0x00000020) +#define MPP_FLAGS_SECURE_MODE (0x00010000) + +/* mpp service capability description */ +typedef enum MppDevCmd_e { + MPP_DEV_GET_START = 0, + MPP_DEV_GET_MAX_WIDTH, + MPP_DEV_GET_MAX_HEIGHT, + MPP_DEV_GET_MIN_WIDTH, + MPP_DEV_GET_MIN_HEIGHT, + MPP_DEV_GET_MMU_STATUS, + + MPP_DEV_SET_START = 0x01000000, + MPP_DEV_SET_HARD_PLATFORM, // set paltform by user + MPP_DEV_ENABLE_POSTPROCCESS, + + MPP_DEV_PROP_BUTT, +} MppDevCmd; + +typedef enum MppServiceCmdType_e { + MPP_CMD_QUERY_BASE = 0, + MPP_CMD_PROBE_HW_SUPPORT = MPP_CMD_QUERY_BASE + 0, + MPP_CMD_QUERY_HW_ID = MPP_CMD_QUERY_BASE + 1, + MPP_CMD_QUERY_CMD_SUPPORT = MPP_CMD_QUERY_BASE + 2, + MPP_CMD_QUERY_BUTT, + + MPP_CMD_INIT_BASE = 0x100, + MPP_CMD_INIT_CLIENT_TYPE = MPP_CMD_INIT_BASE + 0, + MPP_CMD_INIT_DRIVER_DATA = MPP_CMD_INIT_BASE + 1, + MPP_CMD_INIT_TRANS_TABLE = MPP_CMD_INIT_BASE + 2, + MPP_CMD_INIT_BUTT, + + MPP_CMD_SEND_BASE = 0x200, + MPP_CMD_SET_REG_WRITE = MPP_CMD_SEND_BASE + 0, + MPP_CMD_SET_REG_READ = MPP_CMD_SEND_BASE + 1, + MPP_CMD_SET_REG_ADDR_OFFSET = MPP_CMD_SEND_BASE + 2, + MPP_CMD_SET_RCB_INFO = MPP_CMD_SEND_BASE + 3, + /* for batch process start a task of one session */ + MPP_CMD_SET_SESSION_FD = MPP_CMD_SEND_BASE + 4, + MPP_CMD_SEND_BUTT, + + MPP_CMD_POLL_BASE = 0x300, + MPP_CMD_POLL_HW_FINISH = MPP_CMD_POLL_BASE + 0, + MPP_CMD_POLL_HW_IRQ = MPP_CMD_POLL_BASE + 1, + MPP_CMD_POLL_BUTT, + + MPP_CMD_CONTROL_BASE = 0x400, + MPP_CMD_RESET_SESSION = MPP_CMD_CONTROL_BASE + 0, + MPP_CMD_TRANS_FD_TO_IOVA = MPP_CMD_CONTROL_BASE + 1, + MPP_CMD_RELEASE_FD = MPP_CMD_CONTROL_BASE + 2, + MPP_CMD_SEND_CODEC_INFO = MPP_CMD_CONTROL_BASE + 3, + MPP_CMD_SET_ERR_REF_HACK = MPP_CMD_CONTROL_BASE + 4, + MPP_CMD_CONTROL_BUTT, + + MPP_CMD_BUTT, +} MppServiceCmdType; + +typedef struct mppReqV1_t { + RK_U32 cmd; + RK_U32 flag; + RK_U32 size; + RK_U32 offset; + RK_U64 data_ptr; +} MppReqV1; + +typedef struct MppServiceCmdCap_t { + RK_U32 support_cmd; + RK_U32 query_cmd; + RK_U32 init_cmd; + RK_U32 send_cmd; + RK_U32 poll_cmd; + RK_U32 ctrl_cmd; +} MppServiceCmdCap; + +typedef struct MppDevBatCmd_t { + RK_U64 flag; + RK_S32 client; + RK_S32 ret; +} MppDevBatCmd; + +#ifdef __cplusplus +extern "C" { +#endif + +void check_mpp_service_cap(RK_U32 *codec_type, RK_U32 *hw_ids, MppServiceCmdCap *cap); +const MppServiceCmdCap *mpp_get_mpp_service_cmd_cap(void); +const char *mpp_get_mpp_service_name(void); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SERVICE_H */ diff --git a/osal/inc/mpp_service_api.h b/osal/inc/mpp_service_api.h new file mode 100644 index 000000000..2f19f8c3e --- /dev/null +++ b/osal/inc/mpp_service_api.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SERVICE_API_H +#define MPP_SERVICE_API_H + +#include "mpp_device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppDevApi mpp_service_api; + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SERVICE_API_H */ diff --git a/osal/inc/mpp_sgln_base.h b/osal/inc/mpp_sgln_base.h new file mode 100644 index 000000000..215333694 --- /dev/null +++ b/osal/inc/mpp_sgln_base.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SGLN_BASE_H +#define MPP_SGLN_BASE_H + +#include "rk_type.h" + +typedef struct MppSglnInfo_t { + rk_s32 id; + const char *name; + void (*init)(void); + void (*deinit)(void); +} MppSglnInfo; + +typedef struct MppSglnList_t { + rk_u32 count; + rk_u32 capacity; + MppSglnInfo *entries; +} MppSglnList; + +typedef struct MppSglnBase_t { + const char *name; + MppSglnList *arrays[2]; + rk_u32 array_count; + rk_u32 max_name_len; + rk_u32 debug; +} MppSglnBase; + +#define MPP_SGLN_STR(x) #x +#define MPP_SGLN_CAT(p, x) p##_##x +#define MPP_SGLN_CTOR(p, x) MPP_SGLN_CAT(p, x) + +/* warning: constructor priorities from 0 to 100 are reserved for the implementation */ +#define MPP_SGLN_BASE_ID 101 +#define MPP_SGLN_MAX_CNT 64 + +#define MPP_SGLN_DEF(add, id, name, init, deinit) \ + _Static_assert((id) >= 0, "singleton id must be >= 0"); \ + _Static_assert((id) < MPP_SGLN_MAX_CNT, "singleton id out of range"); \ + __attribute__((constructor(MPP_SGLN_BASE_ID + id))) \ + static void MPP_SGLN_CTOR(add, name)(void) { \ + MppSglnInfo info = { id, MPP_SGLN_STR(name), init, deinit, }; \ + add(&info, __FUNCTION__); \ + } + +#define MPP_MODULE_DEF(add, name, init, deinit) \ + __attribute__((constructor(MPP_SGLN_BASE_ID + 64))) \ + static void MPP_SGLN_CTOR(add, name)(void) { \ + MppSglnInfo info = { -1, MPP_SGLN_STR(name), init, deinit, }; \ + add(&info, __FUNCTION__); \ + } + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_sgln_base_add(MppSglnBase *base, MppSglnInfo *info, const char *caller); +void mpp_sgln_base_deinit(MppSglnBase *base); +void mpp_sgln_base_run_init(MppSglnBase *base); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SGLN_BASE_H */ diff --git a/osal/inc/mpp_singleton.h b/osal/inc/mpp_singleton.h new file mode 100644 index 000000000..81b322de1 --- /dev/null +++ b/osal/inc/mpp_singleton.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SINGLETON_H +#define MPP_SINGLETON_H + +#include "mpp_sgln_base.h" + +#define MPP_SGLN_MAX_CNT 64 +#define MPP_SGLN_NO_ID_MAX_CNT 128 + +typedef enum MppSingletonId_e { + MPP_SGLN_BASE = 0, + /* osal base module */ + MPP_SGLN_OS_LOG = MPP_SGLN_BASE, + MPP_SGLN_OS_MEM, + MPP_SGLN_TRACE, + MPP_SGLN_DMABUF, + MPP_SGLN_OS_ALLOCATOR, + MPP_SGLN_MEM_POOL, + /* hardware platform */ + MPP_SGLN_SOC, + MPP_SGLN_PLATFORM, + MPP_SGLN_SERVER, + MPP_SGLN_CLUSTER, + /* software platform */ + MPP_SGLN_RUNTIME, + MPP_SGLN_SYS, + MPP_SGLN_RING, + /* kernel module (MUST before userspace module) */ + MPP_SGLN_KOBJ, + MPP_SGLN_KMPP_IOC, + MPP_SGLN_KMPP_BUF_GRP_CFG, + MPP_SGLN_KMPP_BUF_GRP, + MPP_SGLN_KMPP_BUF_CFG, + MPP_SGLN_KMPP_BUFFER, + MPP_SGLN_KMPP_META, + MPP_SGLN_KMPP_FRAME, + MPP_SGLN_KMPP_PACKET, + MPP_SGLN_KMPP_VENC_CFG, + MPP_SGLN_KMPP_VENC, + MPP_SGLN_KMPP_VDEC_CFG, + MPP_SGLN_KMPP_VDEC, + /* userspace base module */ + MPP_SGLN_BUFFER, + MPP_SGLN_META, + MPP_SGLN_FRAME, + MPP_SGLN_PACKET, + /* userspace system module */ + MPP_SGLN_SYS_CFG, + MPP_SGLN_ENC_CFG, + MPP_SGLN_DEC_CFG, + MPP_SGLN_ENC_RC_API, +} MppSingletonId; + +#define MPP_SINGLETON(id, name, init, deinit) \ + MPP_SGLN_DEF(mpp_singleton_add, id, name, init, deinit) + +#define MPP_MODULE_ADD(name, init, deinit) \ + MPP_MODULE_DEF(mpp_singleton_add, name, init, deinit) + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s32 mpp_singleton_add(MppSglnInfo *info, const char *caller); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SINGLETON_H */ diff --git a/osal/inc/mpp_soc.h b/osal/inc/mpp_soc.h new file mode 100644 index 000000000..db515d7bb --- /dev/null +++ b/osal/inc/mpp_soc.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_SOC_H +#define MPP_SOC_H + +#include "mpp_dev_defs.h" + +/* Do NOT use this outside MPP it may be changed in new version */ +typedef enum RockchipSocType_e { + ROCKCHIP_SOC_AUTO, + ROCKCHIP_SOC_RK3036, + ROCKCHIP_SOC_RK3066, + ROCKCHIP_SOC_RK3188, + ROCKCHIP_SOC_RK3288, + ROCKCHIP_SOC_RK312X, + ROCKCHIP_SOC_RK3368, + ROCKCHIP_SOC_RK3399, + ROCKCHIP_SOC_RK3228H, + ROCKCHIP_SOC_RK3328, + ROCKCHIP_SOC_RK3228, + ROCKCHIP_SOC_RK3229, + ROCKCHIP_SOC_RV1108, + ROCKCHIP_SOC_RV1109, + ROCKCHIP_SOC_RV1126, + ROCKCHIP_SOC_RK3326, + ROCKCHIP_SOC_RK3128H, + ROCKCHIP_SOC_PX30, + ROCKCHIP_SOC_RK1808, + ROCKCHIP_SOC_RK3566, + ROCKCHIP_SOC_RK3567, + ROCKCHIP_SOC_RK3568, + ROCKCHIP_SOC_RK3588, + ROCKCHIP_SOC_RK3528, + ROCKCHIP_SOC_RK3562, + ROCKCHIP_SOC_RK3576, + ROCKCHIP_SOC_RV1126B, + ROCKCHIP_SOC_RK3538, + ROCKCHIP_SOC_RK3572, + ROCKCHIP_SOC_RK3539, + ROCKCHIP_SOC_BUTT, +} RockchipSocType; + +typedef struct MppDecHwCap_t { + rk_u32 cap_coding; + + MppClientType type : 8; + + rk_u32 cap_fbc : 4; + rk_u32 cap_4k : 1; + rk_u32 cap_8k : 1; + rk_u32 cap_colmv_compress : 1; + rk_u32 cap_hw_h265_rps : 1; + rk_u32 cap_hw_vp9_prob : 1; + rk_u32 cap_jpg_pp_out : 1; + rk_u32 cap_10bit : 1; + rk_u32 cap_down_scale : 1; + rk_u32 cap_lmt_linebuf : 1; + rk_u32 cap_core_num : 3; + rk_u32 cap_hw_jpg_fix : 1; + rk_u32 reserved : 8; +} MppDecHwCap; + +typedef struct MppEncHwCap_t { + rk_u32 cap_coding; + + MppClientType type : 8; + + rk_u32 cap_fbc : 4; + rk_u32 cap_4k : 1; + rk_u32 cap_8k : 1; + rk_u32 cap_hw_osd : 1; + rk_u32 cap_hw_roi : 1; + rk_u32 reserved : 16; +} MppEncHwCap; + +typedef struct { + const char *compatible; + const RockchipSocType soc_type; + const rk_u32 vcodec_type; + + /* Max 6 decoder cap */ + const MppDecHwCap *dec_caps[6]; + /* Max 4 encoder cap */ + const MppEncHwCap *enc_caps[4]; +} MppSocInfo; + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 mpp_coding_to_index(MppCodingType coding); + +const char *mpp_get_soc_name(void); +RockchipSocType mpp_get_soc_type(void); + +const MppSocInfo *mpp_get_soc_info(void); +rk_u32 mpp_check_soc_cap(MppCtxType type, MppCodingType coding); +const MppDecHwCap* mpp_get_dec_hw_info_by_client_type(MppClientType client_type); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_SOC_H */ diff --git a/osal/inc/mpp_thread.h b/osal/inc/mpp_thread.h index 599ca3ba2..6d1600a86 100644 --- a/osal/inc/mpp_thread.h +++ b/osal/inc/mpp_thread.h @@ -1,189 +1,189 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * File : mpp_thread.h - * Description : thread library for different OS - * Author : herman.chen@rock-chips.com - * Date : 9:47 2015/7/27 - */ - -#ifndef __MPP_THREAD_H__ -#define __MPP_THREAD_H__ - -#if defined(_WIN32) && !defined(__MINGW32CE__) - -/* - * NOTE: POSIX Threads for Win32 - * Downloaded from http://www.sourceware.org/pthreads-win32/ - */ -#include "semaphore.h" -#include "pthread.h" -#pragma comment(lib, "pthreadVC2.lib") - -#else - -#include -#include -#include - -#if defined(ANDROID) -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER -#endif - -#endif - -typedef void *(*MppThreadFunc)(void *); - -typedef enum { - MPP_THREAD_UNINITED, - MPP_THREAD_RUNNING, - MPP_THREAD_WAITING, - MPP_THREAD_STOPPING, -} MppThreadStatus; - -#ifdef __cplusplus - -class Mutex; -class Condition; - -/* - * for shorter type name and function name - */ -class Mutex -{ -public: - Mutex(); - ~Mutex(); - - void lock(); - void unlock(); - int trylock(); - - class Autolock - { - public: - inline Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); } - inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); } - inline ~Autolock() { mLock.unlock(); } - private: - Mutex& mLock; - }; - -private: - friend class Condition; - - pthread_mutex_t mMutex; - - Mutex(const Mutex &); - Mutex &operator = (const Mutex&); -}; - -inline Mutex::Mutex() -{ - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&mMutex, &attr); - pthread_mutexattr_destroy(&attr); -} -inline Mutex::~Mutex() -{ - pthread_mutex_destroy(&mMutex); -} -inline void Mutex::lock() -{ - pthread_mutex_lock(&mMutex); -} -inline void Mutex::unlock() -{ - pthread_mutex_unlock(&mMutex); -} -inline int Mutex::trylock() -{ - return pthread_mutex_trylock(&mMutex); -} - -typedef Mutex::Autolock AutoMutex; - - -/* - * for shorter type name and function name - */ -class Condition -{ -public: - Condition(); - Condition(int type); - ~Condition(); - void wait(Mutex& mutex); - void signal(); - -private: - pthread_cond_t mCond; -}; - -inline Condition::Condition() -{ - pthread_cond_init(&mCond, NULL); -} -inline Condition::~Condition() -{ - pthread_cond_destroy(&mCond); -} -inline void Condition::wait(Mutex& mutex) -{ - pthread_cond_wait(&mCond, &mutex.mMutex); -} -inline void Condition::signal() -{ - pthread_cond_signal(&mCond); -} - - -class MppThread -{ -public: - MppThread(MppThreadFunc func, void *ctx); - ~MppThread() {}; - - MppThreadStatus get_status(); - void set_status(MppThreadStatus status); - - void start(); - void stop(); - void lock() { mLock.lock(); } - void unlock() { mLock.unlock(); } - void wait() { mCondition.wait(mLock); } - void signal() { mCondition.signal(); } - -private: - Mutex mLock; - Condition mCondition; - pthread_t mThread; - - MppThreadStatus mStatus; - MppThreadFunc mFunction; - void *mContext; - - MppThread(); - MppThread(const MppThread &); - MppThread &operator=(const MppThread &); -}; - -#endif - -#endif /*__MPP_THREAD_H__*/ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_THREAD_H +#define MPP_THREAD_H + +#include +#include +#include +#include +#include + +#include "rk_type.h" + +#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#endif + +#if defined(__USE_XOPEN2K) || (defined(__ANDROID__) && __ANDROID_API__ >= 21) +#define COND_USE_CLOCK_MONOTONIC +#endif + +#define THREAD_NAME_LEN 16 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*MppThreadFunc)(void *arg); + +typedef enum MppThreadStatus_e { + MPP_THREAD_UNINITED, + MPP_THREAD_READY, + MPP_THREAD_RUNNING, + MPP_THREAD_WAITING, + MPP_THREAD_STOPPING, +} MppThreadStatus; + +typedef struct MppMutex_t { + pthread_mutex_t lock; +} MppMutex; + +typedef struct MppCond_t { + pthread_cond_t cond; + clockid_t clock_id; +} MppCond; + +typedef struct MppMutexCond_t { + MppMutex lock; + MppCond cond; +} MppMutexCond; + +typedef enum MppThreadSignalId_e { + THREAD_WORK, + THREAD_INPUT, + THREAD_OUTPUT, + THREAD_CONTROL, + THREAD_SIGNAL_BUTT, +} MppThreadSignalId; + +typedef struct MppThread_t { + pthread_t thd; + MppMutexCond mutex_cond[THREAD_SIGNAL_BUTT]; + MppThreadStatus thd_status[THREAD_SIGNAL_BUTT]; + MppThreadFunc func; + char name[THREAD_NAME_LEN]; + void *ctx; +} MppThread; + +// Mutex functions +void mpp_mutex_init(MppMutex *mutex); +void mpp_mutex_destroy(MppMutex *mutex); +void mpp_mutex_lock(MppMutex *mutex); +void mpp_mutex_unlock(MppMutex *mutex); +int mpp_mutex_trylock(MppMutex *mutex); + +// Condition functions +void mpp_cond_init(MppCond *condition); +void mpp_cond_destroy(MppCond *condition); +rk_s32 mpp_cond_wait(MppCond *condition, MppMutex *mutex); +rk_s32 mpp_cond_timedwait(MppCond *condition, MppMutex *mutex, rk_s64 timeout); +rk_s32 mpp_cond_signal(MppCond *condition); +rk_s32 mpp_cond_broadcast(MppCond *condition); + +// Mutex-Condition functions +void mpp_mutex_cond_init(MppMutexCond *mutexCond); +void mpp_mutex_cond_destroy(MppMutexCond *mutexCond); +void mpp_mutex_cond_lock(MppMutexCond *mutexCond); +void mpp_mutex_cond_unlock(MppMutexCond *mutexCond); +int mpp_mutex_cond_trylock(MppMutexCond *mutexCond); +rk_s32 mpp_mutex_cond_wait(MppMutexCond *mutexCond); +rk_s32 mpp_mutex_cond_timedwait(MppMutexCond *mutexCond, rk_s64 timeout); +void mpp_mutex_cond_signal(MppMutexCond *mutexCond); +void mpp_mutex_cond_broadcast(MppMutexCond *mutexCond); + +// Thread functions +void mpp_thread_init(MppThread *thread, MppThreadFunc func, void *ctx, const char *name); +void mpp_thread_set_status(MppThread *thread, MppThreadStatus status, MppThreadSignalId id); +MppThreadStatus mpp_thread_get_status(MppThread *thread, MppThreadSignalId id); +void mpp_thread_lock(MppThread *thread, MppThreadSignalId id); +void mpp_thread_unlock(MppThread *thread, MppThreadSignalId id); +void mpp_thread_wait(MppThread *thread, MppThreadSignalId id); +void mpp_thread_signal(MppThread *thread, MppThreadSignalId id); + +MppThread *mpp_thread_create(MppThreadFunc func, void *ctx, const char *name); +void mpp_thread_destroy(MppThread *thread); +void mpp_thread_start(MppThread *thread); +void mpp_thread_stop(MppThread *thread); + + +/* + * status transaction: + * create + * v + * MPP_THREAD_UNINITED + * v + * setup + * v + * destroy <- MPP_THREAD_READY <-------------------+ + * v | + * start | + * v | + * MPP_THREAD_RUNNING -> stop -> MPP_THREAD_STOPPING + * v | + * wait | + * v | + * MPP_THREAD_WAITING -> stop ------------+ + * + */ +typedef enum MppSThdStatus_e { + MPP_STHD_UNINITED, + MPP_STHD_READY, + MPP_STHD_RUNNING, + MPP_STHD_WAITING, + MPP_STHD_STOPPING, + MPP_STHD_BUTT, +} MppSThdStatus; + +/* MppSThd for Mpp Simple Thread */ +typedef void* MppSThd; +typedef void* MppSThdGrp; + +typedef struct MppSThdCtx_t { + MppSThd thd; + void *ctx; +} MppSThdCtx; + +typedef void *(*MppSThdFunc)(MppSThdCtx *ctx); + +MppSThd mpp_sthd_get(const char *name); +void mpp_sthd_put(MppSThd thd); + +MppSThdStatus mpp_sthd_get_status(MppSThd thd); +const char* mpp_sthd_get_name(MppSThd thd); +rk_s32 mpp_sthd_get_idx(MppSThd thd); +rk_s32 mpp_sthd_check(MppSThd thd); + +void mpp_sthd_setup(MppSThd thd, MppSThdFunc func, void *ctx); + +void mpp_sthd_start(MppSThd thd); +void mpp_sthd_stop(MppSThd thd); +void mpp_sthd_stop_sync(MppSThd thd); + +void mpp_sthd_lock(MppSThd thd); +void mpp_sthd_unlock(MppSThd thd); +int mpp_sthd_trylock(MppSThd thd); + +void mpp_sthd_wait(MppSThd thd); +void mpp_sthd_signal(MppSThd thd); +void mpp_sthd_broadcast(MppSThd thd); + +/* multi-thread group with same callback and context */ +MppSThdGrp mpp_sthd_grp_get(const char *name, rk_s32 count); +void mpp_sthd_grp_put(MppSThdGrp grp); + +void mpp_sthd_grp_setup(MppSThdGrp grp, MppSThdFunc func, void *ctx); +MppSThd mpp_sthd_grp_get_each(MppSThdGrp grp, rk_s32 idx); + +void mpp_sthd_grp_start(MppSThdGrp grp); +void mpp_sthd_grp_stop(MppSThdGrp grp); +void mpp_sthd_grp_stop_sync(MppSThdGrp grp); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/osal/inc/mpp_time.h b/osal/inc/mpp_time.h index 8eae3c9cf..1ac31d632 100644 --- a/osal/inc/mpp_time.h +++ b/osal/inc/mpp_time.h @@ -1,44 +1,99 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MPP_TIME_H__ -#define __MPP_TIME_H__ - -#include "rk_type.h" - -// TODO: add usleep function on windows - -#if defined(_WIN32) && !defined(__MINGW32CE__) -#include -#define msleep Sleep -#define sleep(x) Sleep((x)*1000) -#else -#include -#define msleep(x) usleep((x)*1000) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -RK_S64 mpp_time(); - -#ifdef __cplusplus -} -#endif - -#endif /*__MPP_TIME_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_TIME_H +#define MPP_TIME_H + +#include + +#include "mpp_thread.h" + +#define msleep(x) usleep((x)*1000) + +typedef void* MppClock; +typedef void* MppTimer; +typedef void* MppStopwatch; + +#ifdef __cplusplus +extern "C" { +#endif + +rk_s64 mpp_time(void); +void mpp_time_diff(rk_s64 start, rk_s64 end, rk_s64 limit, const char *fmt); + +/* + * Clock create / destroy / enable / disable function + * Note when clock is create it is default disabled user need to call enable + * fucntion with enable = 1 to enable the clock. + * User can use enable function with enable = 0 to disable the clock. + */ +MppClock mpp_clock_get(const char *name); +void mpp_clock_put(MppClock clk); +void mpp_clock_enable(MppClock clk, rk_u32 enable); + +/* + * Clock basic operation function: + * start : let clock start timing counter + * pause : let clock pause and return the diff to start time + * reset : let clock counter to all zero + */ +rk_s64 mpp_clock_start(MppClock clk); +rk_s64 mpp_clock_pause(MppClock clk); +rk_s64 mpp_clock_reset(MppClock clk); + +/* + * These clock helper function can only be call when clock is paused: + * mpp_clock_get_sum - Return clock sum up total value + * mpp_clock_get_count - Return clock sum up counter value + * mpp_clock_get_name - Return clock name + */ +rk_s64 mpp_clock_get_sum(MppClock clk); +rk_s64 mpp_clock_get_count(MppClock clk); +const char *mpp_clock_get_name(MppClock clk); + +/* + * MppTimer is for timer with callback function + * It will provide the ability to repeat doing something until it is + * disalble or put. + * + * Timer work flow: + * + * 1. mpp_timer_get + * 2. mpp_timer_set_callback + * 3. mpp_timer_set_timing(initial, interval) + * 4. mpp_timer_set_enable(initial, 1) + * ... running ... + * 5. mpp_timer_set_enable(initial, 0) + * 6. mpp_timer_put + */ +MppTimer mpp_timer_get(const char *name); +void mpp_timer_set_callback(MppTimer timer, MppThreadFunc func, void *ctx); +void mpp_timer_set_timing(MppTimer timer, rk_s32 initial, rk_s32 interval); +void mpp_timer_set_enable(MppTimer timer, rk_s32 enable); +void mpp_timer_put(MppTimer timer); + +/* + * MppStopwatch is for timer to record event and time + * + * Stopwatch work flow: + * + * 1. mpp_stopwatch_get + * 2. mpp_stopwatch_setup(max_count, show_on_exit) + * 3. mpp_stopwatch_record(event) + * ... running ... + * 4. mpp_stopwatch_record(event) + * 5. mpp_stopwatch_put (show events and time) + */ +MppStopwatch mpp_stopwatch_get(const char *name); +void mpp_stopwatch_set_show_on_exit(MppStopwatch stopwatch, rk_s32 show_on_exit); +void mpp_stopwatch_record(MppStopwatch stopwatch, const char *event); +void mpp_stopwatch_put(MppStopwatch timer); +rk_s64 mpp_stopwatch_elapsed_time(MppStopwatch stopwatch); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_TIME_H */ diff --git a/osal/inc/mpp_trace.h b/osal/inc/mpp_trace.h new file mode 100644 index 000000000..a873e407b --- /dev/null +++ b/osal/inc/mpp_trace.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_TRACE_H +#define MPP_TRACE_H + +#include "rk_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void mpp_trace_begin(const char* name); +void mpp_trace_end(const char* name); +void mpp_trace_async_begin(const char* name, rk_s32 cookie); +void mpp_trace_async_end(const char* name, rk_s32 cookie); +void mpp_trace_int32(const char* name, rk_s32 value); +void mpp_trace_int64(const char* name, rk_s64 value); + +#ifdef __cplusplus +} +#endif + +#endif /* MPP_TRACE_H */ \ No newline at end of file diff --git a/osal/inc/osal_2str.h b/osal/inc/osal_2str.h new file mode 100644 index 000000000..7a3346981 --- /dev/null +++ b/osal/inc/osal_2str.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef OSAL_2STR_H +#define OSAL_2STR_H + +#include "mpp_dev_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +const char *strof_client_type(MppClientType type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/inc/vcodec_service.h b/osal/inc/vcodec_service.h new file mode 100644 index 000000000..9ae050cd9 --- /dev/null +++ b/osal/inc/vcodec_service.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef VCODEC_SERVICE_H +#define VCODEC_SERVICE_H + +#include "rk_type.h" + +#define EXTRA_INFO_MAGIC (0x4C4A46) + +#define VPU_IOC_MAGIC 'l' + +#define VPU_IOC_SET_CLIENT_TYPE _IOW(VPU_IOC_MAGIC, 1, unsigned long) +#define VPU_IOC_GET_HW_FUSE_STATUS _IOW(VPU_IOC_MAGIC, 2, unsigned long) +#define VPU_IOC_SET_REG _IOW(VPU_IOC_MAGIC, 3, unsigned long) +#define VPU_IOC_GET_REG _IOW(VPU_IOC_MAGIC, 4, unsigned long) + +#define VPU_IOC_SET_CLIENT_TYPE_U32 _IOW(VPU_IOC_MAGIC, 1, unsigned int) + +#define VPU_IOC_WRITE(nr, size) _IOC(_IOC_WRITE, VPU_IOC_MAGIC, (nr), (size)) + +#define VDPU1_REGISTERS (101) +#define VDPU2_REGISTERS (159) +#define VDPU1_PP_REGISTERS (164) +#define VDPU2_PP_REGISTERS (184) +#define RKHEVC_REGISTERS (68) +#define RKVDEC_REGISTERS (78) +#define AVSD_REGISTERS (60) + +#define VEPU1_REGISTERS (164) +#define VEPU2_REGISTERS (184) +#define RKVENC_REGISTERS (140) + +#define EXTRA_INFO_SIZE (sizeof(RK_U32) * 34U) + +#ifdef __cplusplus +extern "C" { +#endif + +const char *mpp_get_vcodec_dev_name(MppCtxType type, MppCodingType coding); + +#ifdef __cplusplus +} +#endif + +#endif /* VCODEC_SERVICE_H */ diff --git a/osal/inc/vcodec_service_api.h b/osal/inc/vcodec_service_api.h new file mode 100644 index 000000000..baf0b0061 --- /dev/null +++ b/osal/inc/vcodec_service_api.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#ifndef VCODEC_SERVICE_API_H +#define VCODEC_SERVICE_API_H + +#include "mpp_device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const MppDevApi vcodec_service_api; + +#ifdef __cplusplus +} +#endif + +#endif /* VCODEC_SERVICE_API_H */ diff --git a/osal/linux/drm.h b/osal/linux/drm.h new file mode 100644 index 000000000..4d093d7bb --- /dev/null +++ b/osal/linux/drm.h @@ -0,0 +1,1021 @@ +/** + * \file drm.h + * Header for the Direct Rendering Manager + * + * \author Rickard E. (Rik) Faith + * + * \par Acknowledgments: + * Dec 1999, Richard Henderson , move to generic \c cmpxchg. + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DRM_H_ +#define _DRM_H_ + +#if defined(__KERNEL__) + +#include +#include +typedef unsigned int drm_handle_t; + +#elif defined(__linux__) + +#include +#include +typedef unsigned int drm_handle_t; + +#else /* One of the BSDs */ + +#include +#include +typedef int8_t __s8; +typedef uint8_t __u8; +typedef int16_t __s16; +typedef uint16_t __u16; +typedef int32_t __s32; +typedef uint32_t __u32; +typedef int64_t __s64; +typedef uint64_t __u64; +typedef size_t __kernel_size_t; +typedef unsigned long drm_handle_t; + +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#define __user + +#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ +#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ +#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ +#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ + +#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ +#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ +#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) +#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) +#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) + +typedef unsigned int drm_context_t; +typedef unsigned int drm_drawable_t; +typedef unsigned int drm_magic_t; + +/** + * Cliprect. + * + * \warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well + * + * \note KW: Actually it's illegal to change either for + * backwards-compatibility reasons. + */ +struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +}; + +/** + * Drawable information. + */ +struct drm_drawable_info { + unsigned int num_rects; + struct drm_clip_rect *rects; +}; + +/** + * Texture region, + */ +struct drm_tex_region { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; + unsigned int age; +}; + +/** + * Hardware lock. + * + * The lock structure is a simple cache-line aligned integer. To avoid + * processor bus contention on a multiprocessor system, there should not be any + * other data stored in the same cache line. + */ +struct drm_hw_lock { + __volatile__ unsigned int lock; /**< lock variable */ + char padding[60]; /**< Pad to cache line */ +}; + +/** + * DRM_IOCTL_VERSION ioctl argument type. + * + * \sa drmGetVersion(). + */ +struct drm_version { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + __kernel_size_t name_len; /**< Length of name buffer */ + char __user *name; /**< Name of driver */ + __kernel_size_t date_len; /**< Length of date buffer */ + char __user *date; /**< User-space buffer to hold date */ + __kernel_size_t desc_len; /**< Length of desc buffer */ + char __user *desc; /**< User-space buffer to hold desc */ +}; + +/** + * DRM_IOCTL_GET_UNIQUE ioctl argument type. + * + * \sa drmGetBusid() and drmSetBusId(). + */ +struct drm_unique { + __kernel_size_t unique_len; /**< Length of unique */ + char __user *unique; /**< Unique name for driver instantiation */ +}; + +struct drm_list { + int count; /**< Length of user-space structures */ + struct drm_version __user *version; +}; + +struct drm_block { + int unused; +}; + +/** + * DRM_IOCTL_CONTROL ioctl argument type. + * + * \sa drmCtlInstHandler() and drmCtlUninstHandler(). + */ +struct drm_control { + enum { + DRM_ADD_COMMAND, + DRM_RM_COMMAND, + DRM_INST_HANDLER, + DRM_UNINST_HANDLER + } func; + int irq; +}; + +/** + * Type of memory to map. + */ +enum drm_map_type { + _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ + _DRM_REGISTERS = 1, /**< no caching, no core dump */ + _DRM_SHM = 2, /**< shared, cached */ + _DRM_AGP = 3, /**< AGP/GART */ + _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ + _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ +}; + +/** + * Memory mapping flags. + */ +enum drm_map_flags { + _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ + _DRM_READ_ONLY = 0x02, + _DRM_LOCKED = 0x04, /**< shared, cached, locked */ + _DRM_KERNEL = 0x08, /**< kernel requires access */ + _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ + _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ + _DRM_REMOVABLE = 0x40, /**< Removable mapping */ + _DRM_DRIVER = 0x80 /**< Managed by driver */ +}; + +struct drm_ctx_priv_map { + unsigned int ctx_id; /**< Context requesting private mapping */ + void *handle; /**< Handle of map */ +}; + +/** + * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls + * argument type. + * + * \sa drmAddMap(). + */ +struct drm_map { + unsigned long offset; /**< Requested physical address (0 for SAREA)*/ + unsigned long size; /**< Requested physical size (bytes) */ + enum drm_map_type type; /**< Type of memory to map */ + enum drm_map_flags flags; /**< Flags */ + void *handle; /**< User-space: "Handle" to pass to mmap() */ + /**< Kernel-space: kernel-virtual address */ + int mtrr; /**< MTRR slot used */ + /* Private data */ +}; + +/** + * DRM_IOCTL_GET_CLIENT ioctl argument type. + */ +struct drm_client { + int idx; /**< Which client desired? */ + int auth; /**< Is client authenticated? */ + unsigned long pid; /**< Process ID */ + unsigned long uid; /**< User ID */ + unsigned long magic; /**< Magic */ + unsigned long iocs; /**< Ioctl count */ +}; + +enum drm_stat_type { + _DRM_STAT_LOCK, + _DRM_STAT_OPENS, + _DRM_STAT_CLOSES, + _DRM_STAT_IOCTLS, + _DRM_STAT_LOCKS, + _DRM_STAT_UNLOCKS, + _DRM_STAT_VALUE, /**< Generic value */ + _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ + _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ + + _DRM_STAT_IRQ, /**< IRQ */ + _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ + _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ + _DRM_STAT_DMA, /**< DMA */ + _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ + _DRM_STAT_MISSED /**< Missed DMA opportunity */ + /* Add to the *END* of the list */ +}; + +/** + * DRM_IOCTL_GET_STATS ioctl argument type. + */ +struct drm_stats { + unsigned long count; + struct { + unsigned long value; + enum drm_stat_type type; + } data[15]; +}; + +/** + * Hardware locking flags. + */ +enum drm_lock_flags { + _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +}; + +/** + * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. + * + * \sa drmGetLock() and drmUnlock(). + */ +struct drm_lock { + int context; + enum drm_lock_flags flags; +}; + +/** + * DMA flags + * + * \warning + * These values \e must match xf86drm.h. + * + * \sa drm_dma. + */ +enum drm_dma_flags { + /* Flags for DMA buffer dispatch */ + _DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note The buffer may not yet have + * been processed by the hardware -- + * getting a hardware lock with the + * hardware quiescent will ensure + * that the buffer has been + * processed. + */ + _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + + /* Flags for DMA buffer request */ + _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ +}; + +/** + * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. + * + * \sa drmAddBufs(). + */ +struct drm_buf_desc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ + enum { + _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ + _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ + _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ + _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ + } flags; + unsigned long agp_start; /**< + * Start address of where the AGP buffers are + * in the AGP aperture + */ +}; + +/** + * DRM_IOCTL_INFO_BUFS ioctl argument type. + */ +struct drm_buf_info { + int count; /**< Entries in list */ + struct drm_buf_desc __user *list; +}; + +/** + * DRM_IOCTL_FREE_BUFS ioctl argument type. + */ +struct drm_buf_free { + int count; + int __user *list; +}; + +/** + * Buffer information + * + * \sa drm_buf_map. + */ +struct drm_buf_pub { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + void __user *address; /**< Address of buffer */ +}; + +/** + * DRM_IOCTL_MAP_BUFS ioctl argument type. + */ +struct drm_buf_map { + int count; /**< Length of the buffer list */ +#ifdef __cplusplus + void __user *virt; +#else + void __user *virtual; /**< Mmap'd area in user-virtual */ +#endif + struct drm_buf_pub __user *list; /**< Buffer information */ +}; + +/** + * DRM_IOCTL_DMA ioctl argument type. + * + * Indices here refer to the offset into the buffer list in drm_buf_get. + * + * \sa drmDMA(). + */ +struct drm_dma { + int context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int __user *send_indices; /**< List of handles to buffers */ + int __user *send_sizes; /**< Lengths of data to send */ + enum drm_dma_flags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size for buffers */ + int __user *request_indices; /**< Buffer information */ + int __user *request_sizes; + int granted_count; /**< Number of buffers granted */ +}; + +enum drm_ctx_flags { + _DRM_CONTEXT_PRESERVED = 0x01, + _DRM_CONTEXT_2DONLY = 0x02 +}; + +/** + * DRM_IOCTL_ADD_CTX ioctl argument type. + * + * \sa drmCreateContext() and drmDestroyContext(). + */ +struct drm_ctx { + drm_context_t handle; + enum drm_ctx_flags flags; +}; + +/** + * DRM_IOCTL_RES_CTX ioctl argument type. + */ +struct drm_ctx_res { + int count; + struct drm_ctx __user *contexts; +}; + +/** + * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. + */ +struct drm_draw { + drm_drawable_t handle; +}; + +/** + * DRM_IOCTL_UPDATE_DRAW ioctl argument type. + */ +typedef enum { + DRM_DRAWABLE_CLIPRECTS +} drm_drawable_info_type_t; + +struct drm_update_draw { + drm_drawable_t handle; + unsigned int type; + unsigned int num; + unsigned long long data; +}; + +/** + * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. + */ +struct drm_auth { + drm_magic_t magic; +}; + +/** + * DRM_IOCTL_IRQ_BUSID ioctl argument type. + * + * \sa drmGetInterruptFromBusID(). + */ +struct drm_irq_busid { + int irq; /**< IRQ number */ + int busnum; /**< bus number */ + int devnum; /**< device number */ + int funcnum; /**< function number */ +}; + +enum drm_vblank_seq_type { + _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + /* bits 1-6 are reserved for high crtcs */ + _DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, + _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ + _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ + _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ + _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ + _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */ +}; +#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1 + +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) + +struct drm_wait_vblank_request { + enum drm_vblank_seq_type type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + enum drm_vblank_seq_type type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +/** + * DRM_IOCTL_WAIT_VBLANK ioctl argument type. + * + * \sa drmWaitVBlank(). + */ +union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +}; + +#define _DRM_PRE_MODESET 1 +#define _DRM_POST_MODESET 2 + +/** + * DRM_IOCTL_MODESET_CTL ioctl argument type + * + * \sa drmModesetCtl(). + */ +struct drm_modeset_ctl { + __u32 crtc; + __u32 cmd; +}; + +/** + * DRM_IOCTL_AGP_ENABLE ioctl argument type. + * + * \sa drmAgpEnable(). + */ +struct drm_agp_mode { + unsigned long mode; /**< AGP mode */ +}; + +/** + * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. + * + * \sa drmAgpAlloc() and drmAgpFree(). + */ +struct drm_agp_buffer { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for binding / unbinding */ + unsigned long type; /**< Type of memory to allocate */ + unsigned long physical; /**< Physical used by i810 */ +}; + +/** + * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. + * + * \sa drmAgpBind() and drmAgpUnbind(). + */ +struct drm_agp_binding { + unsigned long handle; /**< From drm_agp_buffer */ + unsigned long offset; /**< In bytes -- will round to page boundary */ +}; + +/** + * DRM_IOCTL_AGP_INFO ioctl argument type. + * + * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), + * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), + * drmAgpVendorId() and drmAgpDeviceId(). + */ +struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +}; + +/** + * DRM_IOCTL_SG_ALLOC ioctl argument type. + */ +struct drm_scatter_gather { + unsigned long size; /**< In bytes -- will round to page boundary */ + unsigned long handle; /**< Used for mapping / unmapping */ +}; + +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +}; + +/** DRM_IOCTL_GEM_CLOSE ioctl argument type */ +struct drm_gem_close { + /** Handle of the object to be closed. */ + __u32 handle; + __u32 pad; +}; + +/** DRM_IOCTL_GEM_FLINK ioctl argument type */ +struct drm_gem_flink { + /** Handle for the object being named */ + __u32 handle; + + /** Returned global name */ + __u32 name; +}; + +/** DRM_IOCTL_GEM_OPEN ioctl argument type */ +struct drm_gem_open { + /** Name of object being opened */ + __u32 name; + + /** Returned handle for the object */ + __u32 handle; + + /** Returned size of the object */ + __u64 size; +}; + +#define DRM_CAP_DUMB_BUFFER 0x1 +#define DRM_CAP_VBLANK_HIGH_CRTC 0x2 +#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3 +#define DRM_CAP_DUMB_PREFER_SHADOW 0x4 +#define DRM_CAP_PRIME 0x5 +#define DRM_PRIME_CAP_IMPORT 0x1 +#define DRM_PRIME_CAP_EXPORT 0x2 +#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 +#define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +/* + * The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight + * combination for the hardware cursor. The intention is that a hardware + * agnostic userspace can query a cursor plane size to use. + * + * Note that the cross-driver contract is to merely return a valid size; + * drivers are free to attach another meaning on top, eg. i915 returns the + * maximum plane size. + */ +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#define DRM_CAP_ADDFB2_MODIFIERS 0x10 +#define DRM_CAP_PAGE_FLIP_TARGET 0x11 +#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 +#define DRM_CAP_SYNCOBJ 0x13 + +/** DRM_IOCTL_GET_CAP ioctl argument type */ +struct drm_get_cap { + __u64 capability; + __u64 value; +}; + +/** + * DRM_CLIENT_CAP_STEREO_3D + * + * if set to 1, the DRM core will expose the stereo 3D capabilities of the + * monitor by advertising the supported 3D layouts in the flags of struct + * drm_mode_modeinfo. + */ +#define DRM_CLIENT_CAP_STEREO_3D 1 + +/** + * DRM_CLIENT_CAP_UNIVERSAL_PLANES + * + * If set to 1, the DRM core will expose all planes (overlay, primary, and + * cursor) to userspace. + */ +#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 + +/** + * DRM_CLIENT_CAP_ATOMIC + * + * If set to 1, the DRM core will expose atomic properties to userspace + */ +#define DRM_CLIENT_CAP_ATOMIC 3 + +/** + * DRM_CLIENT_CAP_ASPECT_RATIO + * + * If set to 1, the DRM core will provide aspect ratio information in modes. + */ +#define DRM_CLIENT_CAP_ASPECT_RATIO 4 + +/** + * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS + * + * If set to 1, the DRM core will expose special connectors to be used for + * writing back to memory the scene setup in the commit. Depends on client + * also supporting DRM_CLIENT_CAP_ATOMIC + */ +#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 + +/* + * DRM_CLIENT_CAP_SHARE_PLANES + * + * If set to 1, the DRM core will expose share planes to userspace. + */ +#define DRM_CLIENT_CAP_SHARE_PLANES 6 + +/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ +struct drm_set_client_cap { + __u64 capability; + __u64 value; +}; + +#define DRM_RDWR O_RDWR +#define DRM_CLOEXEC O_CLOEXEC +struct drm_prime_handle { + __u32 handle; + + /** Flags.. only applicable for handle->fd */ + __u32 flags; + + /** Returned dmabuf file descriptor */ + __s32 fd; +}; + +struct drm_syncobj_create { + __u32 handle; +#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0) + __u32 flags; +}; + +struct drm_syncobj_destroy { + __u32 handle; + __u32 pad; +}; + +#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) +#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) +struct drm_syncobj_handle { + __u32 handle; + __u32 flags; + + __s32 fd; + __u32 pad; +}; + +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) +struct drm_syncobj_wait { + __u64 handles; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + +struct drm_syncobj_array { + __u64 handles; + __u32 count_handles; + __u32 pad; +}; + +/* Query current scanout sequence number */ +struct drm_crtc_get_sequence { + __u32 crtc_id; /* requested crtc_id */ + __u32 active; /* return: crtc output is active */ + __u64 sequence; /* return: most recent vblank sequence */ + __s64 sequence_ns; /* return: most recent time of first pixel out */ +}; + +/* Queue event to be delivered at specified sequence. Time stamp marks + * when the first pixel of the refresh cycle leaves the display engine + * for the display + */ +#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001 /* sequence is relative to current */ +#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002 /* Use next sequence if we've missed */ + +struct drm_crtc_queue_sequence { + __u32 crtc_id; + __u32 flags; + __u64 sequence; /* on input, target sequence. on output, actual sequence */ + __u64 user_data; /* user data passed to event */ +}; + +#if defined(__cplusplus) +} +#endif + +#include "drm_mode.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DRM_IOCTL_BASE 'd' +#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) +#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) + +#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version) +#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth) +#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid) +#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map) +#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) +#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) +#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) +#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) +#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) +#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) +#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap) +#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap) + +#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) +#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) +#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) +#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block) +#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control) +#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map) +#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc) +#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc) +#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info) +#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map) +#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free) + +#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map) + +#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) +#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) + +#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) +#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) + +#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) +#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) +#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) +#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx) +#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx) +#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx) +#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res) +#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw) +#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw) +#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma) +#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock) +#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) +#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) + +#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) +#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) + +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding) + +#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather) +#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather) + +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) + +#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence) +#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence) + +#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) + +#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) +#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) +#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) +#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) +#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) +#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) +#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */ +#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */ + +#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) +#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) +#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) +#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) +#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) +#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) + +#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb) +#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb) +#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb) +#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res) +#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) +#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) +#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) +#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) +#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) +#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) +#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) +#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) + +#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create) +#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) +#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait) +#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array) +#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array) + +#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease) +#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees) +#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease) +#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease) + +/** + * Device specific ioctls should only be in their respective headers + * The device specific ioctl range is from 0x40 to 0x9f. + * Generic IOCTLS restart at 0xA0. + * + * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and + * drmCommandReadWrite(). + */ +#define DRM_COMMAND_BASE 0x40 +#define DRM_COMMAND_END 0xA0 + +/** + * Header for events written back to userspace on the drm fd. The + * type defines the type of event, the length specifies the total + * length of the event (including the header), and user_data is + * typically a 64 bit value passed with the ioctl that triggered the + * event. A read on the drm fd will always only return complete + * events, that is, if for example the read buffer is 100 bytes, and + * there are two 64 byte events pending, only one will be returned. + * + * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and + * up are chipset specific. + */ +struct drm_event { + __u32 type; + __u32 length; +}; + +#define DRM_EVENT_VBLANK 0x01 +#define DRM_EVENT_FLIP_COMPLETE 0x02 +#define DRM_EVENT_CRTC_SEQUENCE 0x03 + +struct drm_event_vblank { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 sequence; + __u32 crtc_id; /* 0 on older kernels that do not support this */ +}; + +/* Event delivered at sequence. Time stamp marks when the first pixel + * of the refresh cycle leaves the display engine for the display + */ +struct drm_event_crtc_sequence { + struct drm_event base; + __u64 user_data; + __s64 time_ns; + __u64 sequence; +}; + +/* typedef area */ +#ifndef __KERNEL__ +typedef struct drm_clip_rect drm_clip_rect_t; +typedef struct drm_drawable_info drm_drawable_info_t; +typedef struct drm_tex_region drm_tex_region_t; +typedef struct drm_hw_lock drm_hw_lock_t; +typedef struct drm_version drm_version_t; +typedef struct drm_unique drm_unique_t; +typedef struct drm_list drm_list_t; +typedef struct drm_block drm_block_t; +typedef struct drm_control drm_control_t; +typedef enum drm_map_type drm_map_type_t; +typedef enum drm_map_flags drm_map_flags_t; +typedef struct drm_ctx_priv_map drm_ctx_priv_map_t; +typedef struct drm_map drm_map_t; +typedef struct drm_client drm_client_t; +typedef enum drm_stat_type drm_stat_type_t; +typedef struct drm_stats drm_stats_t; +typedef enum drm_lock_flags drm_lock_flags_t; +typedef struct drm_lock drm_lock_t; +typedef enum drm_dma_flags drm_dma_flags_t; +typedef struct drm_buf_desc drm_buf_desc_t; +typedef struct drm_buf_info drm_buf_info_t; +typedef struct drm_buf_free drm_buf_free_t; +typedef struct drm_buf_pub drm_buf_pub_t; +typedef struct drm_buf_map drm_buf_map_t; +typedef struct drm_dma drm_dma_t; +typedef union drm_wait_vblank drm_wait_vblank_t; +typedef struct drm_agp_mode drm_agp_mode_t; +typedef enum drm_ctx_flags drm_ctx_flags_t; +typedef struct drm_ctx drm_ctx_t; +typedef struct drm_ctx_res drm_ctx_res_t; +typedef struct drm_draw drm_draw_t; +typedef struct drm_update_draw drm_update_draw_t; +typedef struct drm_auth drm_auth_t; +typedef struct drm_irq_busid drm_irq_busid_t; +typedef enum drm_vblank_seq_type drm_vblank_seq_type_t; + +typedef struct drm_agp_buffer drm_agp_buffer_t; +typedef struct drm_agp_binding drm_agp_binding_t; +typedef struct drm_agp_info drm_agp_info_t; +typedef struct drm_scatter_gather drm_scatter_gather_t; +typedef struct drm_set_version drm_set_version_t; +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/osal/linux/drm_mode.h b/osal/linux/drm_mode.h new file mode 100644 index 000000000..f74fa3c4b --- /dev/null +++ b/osal/linux/drm_mode.h @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2007 Dave Airlie + * Copyright (c) 2007 Jakob Bornecrantz + * Copyright (c) 2008 Red Hat Inc. + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA + * Copyright (c) 2007-2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _DRM_MODE_H +#define _DRM_MODE_H + +#define DRM_DISPLAY_INFO_LEN 32 +#define DRM_CONNECTOR_NAME_LEN 32 +#define DRM_DISPLAY_MODE_LEN 32 +#define DRM_PROP_NAME_LEN 32 + +#define DRM_MODE_TYPE_BUILTIN (1<<0) +#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) +#define DRM_MODE_TYPE_PREFERRED (1<<3) +#define DRM_MODE_TYPE_DEFAULT (1<<4) +#define DRM_MODE_TYPE_USERDEF (1<<5) +#define DRM_MODE_TYPE_DRIVER (1<<6) + +/* Video mode flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) +#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) +#define DRM_MODE_FLAG_3D_NONE (0<<14) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) +#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) +#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) +#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) +#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + +/* Scaling mode options */ +#define DRM_MODE_SCALE_NONE 0 /* Unmodified timing (display or + software can still scale) */ +#define DRM_MODE_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ +#define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ +#define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ + +/* Dithering mode options */ +#define DRM_MODE_DITHERING_OFF 0 +#define DRM_MODE_DITHERING_ON 1 +#define DRM_MODE_DITHERING_AUTO 2 + +/* Dirty info options */ +#define DRM_MODE_DIRTY_OFF 0 +#define DRM_MODE_DIRTY_ON 1 +#define DRM_MODE_DIRTY_ANNOTATE 2 + +/* rotation property bits */ +#define DRM_ROTATE_0 0 +#define DRM_ROTATE_90 1 +#define DRM_ROTATE_180 2 +#define DRM_ROTATE_270 3 +#define DRM_REFLECT_X 4 +#define DRM_REFLECT_Y 5 + +struct drm_mode_modeinfo { + __u32 clock; + __u16 hdisplay, hsync_start, hsync_end, htotal, hskew; + __u16 vdisplay, vsync_start, vsync_end, vtotal, vscan; + + __u32 vrefresh; + + __u32 flags; + __u32 type; + char name[DRM_DISPLAY_MODE_LEN]; +}; + +struct drm_mode_card_res { + __u64 fb_id_ptr; + __u64 crtc_id_ptr; + __u64 connector_id_ptr; + __u64 encoder_id_ptr; + __u32 count_fbs; + __u32 count_crtcs; + __u32 count_connectors; + __u32 count_encoders; + __u32 min_width, max_width; + __u32 min_height, max_height; +}; + +struct drm_mode_crtc { + __u64 set_connectors_ptr; + __u32 count_connectors; + + __u32 crtc_id; /**< Id */ + __u32 fb_id; /**< Id of framebuffer */ + + __u32 x, y; /**< Position on the frameuffer */ + + __u32 gamma_size; + __u32 mode_valid; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_PRESENT_TOP_FIELD (1<<0) +#define DRM_MODE_PRESENT_BOTTOM_FIELD (1<<1) + +/* Planes blend with or override other bits on the CRTC */ +struct drm_mode_set_plane { + __u32 plane_id; + __u32 crtc_id; + __u32 fb_id; /* fb object contains surface format type */ + __u32 flags; + + /* Signed dest location allows it to be partially off screen */ + __s32 crtc_x, crtc_y; + __u32 crtc_w, crtc_h; + + /* Source values are 16.16 fixed point */ + __u32 src_x, src_y; + __u32 src_h, src_w; +}; + +struct drm_mode_get_plane { + __u32 plane_id; + + __u32 crtc_id; + __u32 fb_id; + + __u32 possible_crtcs; + __u32 gamma_size; + + __u32 count_format_types; + __u64 format_type_ptr; +}; + +struct drm_mode_get_plane_res { + __u64 plane_id_ptr; + __u32 count_planes; +}; + +#define DRM_MODE_ENCODER_NONE 0 +#define DRM_MODE_ENCODER_DAC 1 +#define DRM_MODE_ENCODER_TMDS 2 +#define DRM_MODE_ENCODER_LVDS 3 +#define DRM_MODE_ENCODER_TVDAC 4 +#define DRM_MODE_ENCODER_VIRTUAL 5 +#define DRM_MODE_ENCODER_DSI 6 +#define DRM_MODE_ENCODER_DPMST 7 + +struct drm_mode_get_encoder { + __u32 encoder_id; + __u32 encoder_type; + + __u32 crtc_id; /**< Id of crtc */ + + __u32 possible_crtcs; + __u32 possible_clones; +}; + +/* This is for connectors with multiple signal types. */ +/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +#define DRM_MODE_SUBCONNECTOR_Automatic 0 +#define DRM_MODE_SUBCONNECTOR_Unknown 0 +#define DRM_MODE_SUBCONNECTOR_DVID 3 +#define DRM_MODE_SUBCONNECTOR_DVIA 4 +#define DRM_MODE_SUBCONNECTOR_Composite 5 +#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +#define DRM_MODE_SUBCONNECTOR_Component 8 +#define DRM_MODE_SUBCONNECTOR_SCART 9 + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 +#define DRM_MODE_CONNECTOR_TV 13 +#define DRM_MODE_CONNECTOR_eDP 14 +#define DRM_MODE_CONNECTOR_VIRTUAL 15 +#define DRM_MODE_CONNECTOR_DSI 16 + +struct drm_mode_get_connector { + + __u64 encoders_ptr; + __u64 modes_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + + __u32 count_modes; + __u32 count_props; + __u32 count_encoders; + + __u32 encoder_id; /**< Current Encoder */ + __u32 connector_id; /**< Id */ + __u32 connector_type; + __u32 connector_type_id; + + __u32 connection; + __u32 mm_width, mm_height; /**< HxW in millimeters */ + __u32 subpixel; +}; + +#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_RANGE (1<<1) +#define DRM_MODE_PROP_IMMUTABLE (1<<2) +#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ +#define DRM_MODE_PROP_BLOB (1<<4) +#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ + +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, + * grab a chunk of the bits to use as integer type id. + */ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE(n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) + +/* the PROP_ATOMIC flag is used to hide properties from userspace that + * is not aware of atomic properties. This is mostly to work around + * older userspace (DDX drivers) that read/write each prop they find, + * witout being aware that this could be triggering a lengthy modeset. + */ +#define DRM_MODE_PROP_ATOMIC 0x80000000 + +struct drm_mode_property_enum { + __u64 value; + char name[DRM_PROP_NAME_LEN]; +}; + +struct drm_mode_get_property { + __u64 values_ptr; /* values and blob lengths */ + __u64 enum_blob_ptr; /* enum and blob id ptrs */ + + __u32 prop_id; + __u32 flags; + char name[DRM_PROP_NAME_LEN]; + + __u32 count_values; + __u32 count_enum_blobs; +}; + +struct drm_mode_connector_set_property { + __u64 value; + __u32 prop_id; + __u32 connector_id; +}; + +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb +#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee + +struct drm_mode_obj_get_properties { + __u64 props_ptr; + __u64 prop_values_ptr; + __u32 count_props; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_obj_set_property { + __u64 value; + __u32 prop_id; + __u32 obj_id; + __u32 obj_type; +}; + +struct drm_mode_get_blob { + __u32 blob_id; + __u32 length; + __u64 data; +}; + +struct drm_mode_fb_cmd { + __u32 fb_id; + __u32 width, height; + __u32 pitch; + __u32 bpp; + __u32 depth; + /* driver specific handle */ + __u32 handle; +}; + +#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ + +struct drm_mode_fb_cmd2 { + __u32 fb_id; + __u32 width, height; + __u32 pixel_format; /* fourcc code from drm_fourcc.h */ + __u32 flags; + + /* + * In case of planar formats, this ioctl allows up to 4 + * buffer objects with offsets and pitches per plane. + * The pitch and offset order is dictated by the fourcc, + * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as: + * + * YUV 4:2:0 image with a plane of 8 bit Y samples + * followed by an interleaved U/V plane containing + * 8 bit 2x2 subsampled colour difference samples. + * + * So it would consist of Y as offset[0] and UV as + * offset[1]. Note that offset[0] will generally + * be 0. + */ + __u32 handles[4]; + __u32 pitches[4]; /* pitch for each plane */ + __u32 offsets[4]; /* offset of each plane */ +}; + +#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 +#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 +#define DRM_MODE_FB_DIRTY_FLAGS 0x03 + +/* + * Mark a region of a framebuffer as dirty. + * + * Some hardware does not automatically update display contents + * as a hardware or software draw to a framebuffer. This ioctl + * allows userspace to tell the kernel and the hardware what + * regions of the framebuffer have changed. + * + * The kernel or hardware is free to update more then just the + * region specified by the clip rects. The kernel or hardware + * may also delay and/or coalesce several calls to dirty into a + * single update. + * + * Userspace may annotate the updates, the annotates are a + * promise made by the caller that the change is either a copy + * of pixels or a fill of a single color in the region specified. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then + * the number of updated regions are half of num_clips given, + * where the clip rects are paired in src and dst. The width and + * height of each one of the pairs must match. + * + * If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller + * promises that the region specified of the clip rects is filled + * completely with a single color as given in the color argument. + */ + +struct drm_mode_fb_dirty_cmd { + __u32 fb_id; + __u32 flags; + __u32 color; + __u32 num_clips; + __u64 clips_ptr; +}; + +struct drm_mode_mode_cmd { + __u32 connector_id; + struct drm_mode_modeinfo mode; +}; + +#define DRM_MODE_CURSOR_BO (1<<0) +#define DRM_MODE_CURSOR_MOVE (1<<1) + +/* + * depending on the value in flags diffrent members are used. + * + * CURSOR_BO uses + * crtc + * width + * height + * handle - if 0 turns the cursor of + * + * CURSOR_MOVE uses + * crtc + * x + * y + */ +struct drm_mode_cursor { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; +}; + +struct drm_mode_cursor2 { + __u32 flags; + __u32 crtc_id; + __s32 x; + __s32 y; + __u32 width; + __u32 height; + /* driver specific handle */ + __u32 handle; + __s32 hot_x; + __s32 hot_y; +}; + +struct drm_mode_crtc_lut { + __u32 crtc_id; + __u32 gamma_size; + + /* pointers to arrays */ + __u64 red; + __u64 green; + __u64 blue; +}; + +#define DRM_MODE_PAGE_FLIP_EVENT 0x01 +#define DRM_MODE_PAGE_FLIP_ASYNC 0x02 +#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC) + +/* + * Request a page flip on the specified crtc. + * + * This ioctl will ask KMS to schedule a page flip for the specified + * crtc. Once any pending rendering targeting the specified fb (as of + * ioctl time) has completed, the crtc will be reprogrammed to display + * that fb after the next vertical refresh. The ioctl returns + * immediately, but subsequent rendering to the current fb will block + * in the execbuffer ioctl until the page flip happens. If a page + * flip is already pending as the ioctl is called, EBUSY will be + * returned. + * + * The ioctl supports one flag, DRM_MODE_PAGE_FLIP_EVENT, which will + * request that drm sends back a vblank event (see drm.h: struct + * drm_event_vblank) when the page flip is done. The user_data field + * passed in with this ioctl will be returned as the user_data field + * in the vblank event struct. + * + * The reserved field must be zero until we figure out something + * clever to use it for. + */ + +struct drm_mode_crtc_page_flip { + __u32 crtc_id; + __u32 fb_id; + __u32 flags; + __u32 reserved; + __u64 user_data; +}; + +/* create a dumb scanout buffer */ +struct drm_mode_create_dumb { + __u32 height; + __u32 width; + __u32 bpp; + __u32 flags; + /* handle, pitch, size will be returned */ + __u32 handle; + __u32 pitch; + __u64 size; +}; + +/* set up for mmap of a dumb scanout buffer */ +struct drm_mode_map_dumb { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + +struct drm_mode_destroy_dumb { + __u32 handle; +}; + +/* page-flip flags are valid, plus: */ +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 + +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK |\ + DRM_MODE_ATOMIC_ALLOW_MODESET) + +struct drm_mode_atomic { + __u32 flags; + __u32 count_objs; + __u64 objs_ptr; + __u64 count_props_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + __u64 reserved; + __u64 user_data; +}; + +/** + * Create a new 'blob' data property, copying length bytes from data pointer, + * and returning new blob ID. + */ +struct drm_mode_create_blob { + /** Pointer to data to copy. */ + __u64 data; + /** Length of data to copy. */ + __u32 length; + /** Return: new property ID. */ + __u32 blob_id; +}; + +/** + * Destroy a user-created blob property. + */ +struct drm_mode_destroy_blob { + __u32 blob_id; +}; + +#endif diff --git a/osal/linux/os_allocator.c b/osal/linux/os_allocator.c deleted file mode 100644 index 2e8a813bc..000000000 --- a/osal/linux/os_allocator.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "os_mem.h" -#include "os_allocator.h" - -#include "mpp_mem.h" -#include "mpp_log.h" - -/* - * Linux only support MPP_BUFFER_TYPE_NORMAL so far - * we can support MPP_BUFFER_TYPE_V4L2 later - */ -typedef struct { - size_t alignment; -} allocator_ctx; - -MPP_RET os_allocator_normal_open(void **ctx, size_t alignment) -{ - MPP_RET ret = MPP_OK; - allocator_ctx *p = NULL; - - if (NULL == ctx) { - mpp_err("os_allocator_open Linux do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - p = mpp_malloc(allocator_ctx, 1); - if (NULL == p) { - mpp_err("os_allocator_open Linux failed to allocate context\n"); - ret = MPP_ERR_MALLOC; - } else - p->alignment = alignment; - - *ctx = p; - return ret; -} - -MPP_RET os_allocator_normal_alloc(void *ctx, MppBufferInfo *info) -{ - allocator_ctx *p = NULL; - - if (NULL == ctx) { - mpp_err("os_allocator_alloc Linux found NULL context input\n"); - return MPP_ERR_NULL_PTR; - } - - p = (allocator_ctx *)ctx; - return os_malloc(&info->ptr, p->alignment, info->size); -} - -MPP_RET os_allocator_normal_free(void *ctx, MppBufferInfo *info) -{ - (void) ctx; - if (info->ptr) - os_free(info->ptr); - return MPP_OK; -} - -MPP_RET os_allocator_normal_close(void *ctx) -{ - if (ctx) { - mpp_free(ctx); - return MPP_OK; - } - mpp_err("os_allocator_close Linux found NULL context input\n"); - return MPP_NOK; -} - -static os_allocator allocator_normal = { - os_allocator_normal_open, - os_allocator_normal_alloc, - os_allocator_normal_free, - os_allocator_normal_close, -}; - -static os_allocator allocator_v4l2 = { - os_allocator_normal_open, - os_allocator_normal_alloc, - os_allocator_normal_free, - os_allocator_normal_close, -}; - -MPP_RET os_allocator_get(os_allocator *api, MppBufferType type) -{ - MPP_RET ret = MPP_OK; - switch (type) { - case MPP_BUFFER_TYPE_NORMAL : - case MPP_BUFFER_TYPE_ION : { - *api = allocator_normal; - } break; - case MPP_BUFFER_TYPE_V4L2 : { - mpp_err("os_allocator_get Linux MPP_BUFFER_TYPE_V4L2 do not implement yet\n"); - *api = allocator_v4l2; - } break; - default : { - ret = MPP_NOK; - } break; - } - return ret; -} - diff --git a/osal/linux/os_env.c b/osal/linux/os_env.c index ed1d5d9e2..64a527639 100644 --- a/osal/linux/os_env.c +++ b/osal/linux/os_env.c @@ -1,63 +1,53 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "os_env.h" - -#define ENV_BUF_SIZE_LINUX 1024 - -RK_S32 os_get_env_u32(const char *name, RK_U32 *value, RK_U32 default_value) -{ - char *ptr = getenv(name); - if (NULL == ptr) { - *value = default_value; - } else { - char *endptr; - int base = (ptr[0] == '0' && ptr[1] == 'x') ? (16) : (10); - errno = 0; - *value = strtoul(ptr, &endptr, base); - if (errno || (ptr == endptr)) { - errno = 0; - *value = default_value; - } - } - return 0; -} - -RK_S32 os_get_env_str(const char *name, char **value, char *default_value) -{ - *value = getenv(name); - if (NULL == *value) { - *value = default_value; - } - return 0; -} - -RK_S32 os_set_env_u32(const char *name, RK_U32 value) -{ - char buf[ENV_BUF_SIZE_LINUX]; - snprintf(buf, sizeof(buf), "%u", value); - return setenv(name, buf, 1); -} - -RK_S32 os_set_env_str(const char *name, char *value) -{ - return setenv(name, value, 1); -} - - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(linux) && !defined(__ANDROID__) +#include +#include +#include +#include "os_env.h" + +#define ENV_BUF_SIZE_LINUX 1024 + +RK_S32 os_get_env_u32(const char *name, RK_U32 *value, RK_U32 default_value) +{ + char *ptr = getenv(name); + if (NULL == ptr) { + *value = default_value; + } else { + char *endptr; + int base = (ptr[0] == '0' && ptr[1] == 'x') ? (16) : (10); + errno = 0; + *value = strtoul(ptr, &endptr, base); + if (errno || (ptr == endptr)) { + errno = 0; + *value = default_value; + } + } + return 0; +} + +RK_S32 os_get_env_str(const char *name, const char **value, const char *default_value) +{ + *value = getenv(name); + if (NULL == *value) { + *value = default_value; + } + return 0; +} + +RK_S32 os_set_env_u32(const char *name, RK_U32 value) +{ + char buf[ENV_BUF_SIZE_LINUX]; + snprintf(buf, sizeof(buf) - 1, "%u", value); + return setenv(name, buf, 1); +} + +RK_S32 os_set_env_str(const char *name, char *value) +{ + return setenv(name, value, 1); +} + +#endif diff --git a/osal/linux/os_log.c b/osal/linux/os_log.c index 51cd16362..e39359e79 100644 --- a/osal/linux/os_log.c +++ b/osal/linux/os_log.c @@ -1,35 +1,86 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#define LINE_SZ 1024 - -void os_log(const char* tag, const char* msg, va_list list) -{ - char line[LINE_SZ] = {0}; - snprintf(line, sizeof(line), "%s: %s", tag, msg); - vfprintf(stdout, line, list); -} - -void os_err(const char* tag, const char* msg, va_list list) -{ - char line[LINE_SZ] = {0}; - snprintf(line, sizeof(line), "%s: %s", tag, msg); - vfprintf(stderr, line, list); -} - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(linux) && !defined(__ANDROID__) + +#define MODULE_TAG "os_log" + +#include +#include +#include + +#include "os_log.h" +#include "os_env.h" +#include "mpp_singleton.h" + +#define LINE_SZ 1024 + +void syslog_wrapper_init() +{ + int option = LOG_PID; + RK_U32 syslog_perror = 1; + RK_U32 syslog_cons = 0; + + os_get_env_u32("mpp_syslog_perror", &syslog_perror, 1); + if (syslog_perror) + option |= LOG_PERROR; + + os_get_env_u32("mpp_syslog_cons", &syslog_cons, 0); + if (syslog_cons) + option |= LOG_CONS; + + openlog("mpp", option, LOG_USER); +} + +void syslog_wrapper_deinit() +{ + closelog(); +} + +void os_log_trace(const char* tag, const char* msg, va_list list) +{ + char line[LINE_SZ] = {0}; + snprintf(line, sizeof(line) - 1, "%s: %s", tag, msg); + vsyslog(LOG_NOTICE, line, list); +} + +void os_log_debug(const char* tag, const char* msg, va_list list) +{ + char line[LINE_SZ] = {0}; + snprintf(line, sizeof(line) - 1, "%s: %s", tag, msg); + vsyslog(LOG_DEBUG, line, list); +} + +void os_log_info(const char* tag, const char* msg, va_list list) +{ + char line[LINE_SZ] = {0}; + snprintf(line, sizeof(line) - 1, "%s: %s", tag, msg); + vsyslog(LOG_INFO, line, list); +} + +void os_log_warn(const char* tag, const char* msg, va_list list) +{ + char line[LINE_SZ] = {0}; + snprintf(line, sizeof(line) - 1, "%s: %s", tag, msg); + vsyslog(LOG_WARNING, line, list); +} + +void os_log_error(const char* tag, const char* msg, va_list list) +{ + char line[LINE_SZ] = {0}; + snprintf(line, sizeof(line) - 1, "%s: %s", tag, msg); + vsyslog(LOG_ERR, line, list); +} + +void os_log_fatal(const char* tag, const char* msg, va_list list) +{ + char line[LINE_SZ] = {0}; + snprintf(line, sizeof(line) - 1, "%s: %s", tag, msg); + vsyslog(LOG_CRIT, line, list); +} + +MPP_SINGLETON(MPP_SGLN_OS_LOG, os_log, syslog_wrapper_init, syslog_wrapper_deinit) + +#endif diff --git a/osal/linux/os_mem.c b/osal/linux/os_mem.c index 03daf1b5e..abadf3638 100644 --- a/osal/linux/os_mem.c +++ b/osal/linux/os_mem.c @@ -1,36 +1,27 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "os_mem.h" - -int os_malloc(void **memptr, size_t alignment, size_t size) -{ - return posix_memalign(memptr, alignment, size); -} - -int os_realloc(void *src, void **dst, size_t alignment, size_t size) -{ - (void)alignment; - *dst = realloc(src, size); - return (*dst) ? (0) : (-1); -} - -void os_free(void *ptr) -{ - free(ptr); -} - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(linux) && !defined(__ANDROID__) +#include +#include "os_mem.h" + +int os_malloc(void **memptr, size_t alignment, size_t size) +{ + return posix_memalign(memptr, alignment, size); +} + +int os_realloc(void *src, void **dst, size_t alignment, size_t size) +{ + (void)alignment; + *dst = realloc(src, size); + return (*dst) ? (0) : (-1); +} + +void os_free(void *ptr) +{ + free(ptr); +} + +#endif diff --git a/osal/mpp_allocator.c b/osal/mpp_allocator.c new file mode 100644 index 000000000..afc307f8b --- /dev/null +++ b/osal/mpp_allocator.c @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_allocator" + +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_runtime.h" +#include "mpp_thread.h" +#include "mpp_allocator.h" + +#include "allocator_std.h" +#include "allocator_ion.h" +#include "allocator_drm.h" +#include "allocator_ext_dma.h" +#include "allocator_dma_heap.h" + +#include + +#define MPP_ALLOCATOR_LOCK(p) pthread_mutex_lock(&(p)->lock); +#define MPP_ALLOCATOR_UNLOCK(p) pthread_mutex_unlock(&(p)->lock); + +typedef enum OsAllocatorApiId_e { + ALLOC_API_ALLOC, + ALLOC_API_FREE, + ALLOC_API_IMPORT, + ALLOC_API_RELEASE, + ALLOC_API_MMAP, + ALLOC_API_BUTT, +} OsAllocatorApiId; + +typedef struct MppAllocatorImpl_t { + pthread_mutex_t lock; + MppBufferType type; + MppAllocFlagType flags; + size_t alignment; + os_allocator os_api; + void *ctx; +} MppAllocatorImpl; + +static MPP_RET mpp_allocator_api_wrapper(MppAllocator allocator, + MppBufferInfo *info, + OsAllocatorApiId id) +{ + MppAllocatorImpl *p = (MppAllocatorImpl *)allocator; + OsAllocatorFunc func; + MPP_RET ret = MPP_NOK; + + if (!p || !info || id >= ALLOC_API_BUTT) { + mpp_err_f("invalid input: allocator %p info %p id %d\n", + allocator, info, id); + return MPP_ERR_UNKNOW; + } + + MPP_ALLOCATOR_LOCK(p); + switch (id) { + case ALLOC_API_ALLOC : { + func = p->os_api.alloc; + } break; + case ALLOC_API_FREE : { + func = p->os_api.free; + } break; + case ALLOC_API_IMPORT : { + func = p->os_api.import; + } break; + case ALLOC_API_RELEASE : { + func = p->os_api.release; + } break; + case ALLOC_API_MMAP : { + func = p->os_api.mmap; + } break; + default : { + func = NULL; + } break; + } + + if (func && p->ctx) + ret = func(p->ctx, info); + + MPP_ALLOCATOR_UNLOCK(p); + + return ret; +} + +static MPP_RET mpp_allocator_alloc(MppAllocator allocator, MppBufferInfo *info) +{ + return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_ALLOC); +} + +static MPP_RET mpp_allocator_free(MppAllocator allocator, MppBufferInfo *info) +{ + return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_FREE); +} + +static MPP_RET mpp_allocator_import(MppAllocator allocator, MppBufferInfo *info) +{ + return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_IMPORT); +} + +static MPP_RET mpp_allocator_release(MppAllocator allocator, + MppBufferInfo *info) +{ + return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_RELEASE); +} + +static MPP_RET mpp_allocator_mmap(MppAllocator allocator, MppBufferInfo *info) +{ + return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_MMAP); +} + +static MppAllocatorApi mpp_allocator_api = { + .size = sizeof(mpp_allocator_api), + .version = 1, + .alloc = mpp_allocator_alloc, + .free = mpp_allocator_free, + .import = mpp_allocator_import, + .release = mpp_allocator_release, + .mmap = mpp_allocator_mmap, +}; + +MPP_RET mpp_allocator_get(MppAllocator *allocator, MppAllocatorApi **api, + MppBufferType type, MppAllocFlagType flags) +{ + MppBufferType buffer_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK); + MppAllocatorImpl *p = NULL; + + do { + if (!allocator || !api || buffer_type >= MPP_BUFFER_TYPE_BUTT) { + mpp_err_f("invalid input: allocator %p api %p type %d\n", + allocator, api, buffer_type); + break; + } + + p = mpp_malloc(MppAllocatorImpl, 1); + if (!p) { + mpp_err_f("failed to malloc allocator context\n"); + break; + } + + p->type = buffer_type; + p->flags = flags; + + switch (buffer_type) { + case MPP_BUFFER_TYPE_NORMAL : { + p->os_api = allocator_std; + } break; + case MPP_BUFFER_TYPE_ION : { + p->os_api = (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DMA_HEAP) != 0) ? allocator_dma_heap : + (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION) != 0) ? allocator_ion : + (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM) != 0) ? allocator_drm : + allocator_std; + } break; + case MPP_BUFFER_TYPE_EXT_DMA: { + p->os_api = allocator_ext_dma; + } break; + case MPP_BUFFER_TYPE_DRM : { + p->os_api = (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DMA_HEAP) != 0) ? allocator_dma_heap : + (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM) != 0) ? allocator_drm : + (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION) != 0) ? allocator_ion : + allocator_std; + } break; + case MPP_BUFFER_TYPE_DMA_HEAP: { + p->os_api = (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DMA_HEAP) != 0) ? allocator_dma_heap : + (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM) != 0) ? allocator_drm : + (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION) != 0) ? allocator_ion : + allocator_std; + } break; + default : { + } break; + } + + if (p->os_api.open(&p->ctx, SZ_4K, flags)) + break; + + /* update the real buffer type and flags */ + p->type = p->os_api.type; + if (p->os_api.flags) + p->flags = p->os_api.flags(p->ctx); + + { + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p->lock, &attr); + pthread_mutexattr_destroy(&attr); + } + + *allocator = p; + *api = &mpp_allocator_api; + + return MPP_OK; + } while (0); + + MPP_FREE(p); + *allocator = NULL; + *api = NULL; + + return MPP_NOK; +} + +MPP_RET mpp_allocator_put(MppAllocator *allocator) +{ + MppAllocatorImpl *p = (MppAllocatorImpl *)*allocator; + + if (!p) { + mpp_err_f("invalid input: allocator %p\n", allocator); + return MPP_ERR_NULL_PTR; + } + + if (!p) + return MPP_OK; + *allocator = NULL; + + if (p->os_api.close && p->ctx) + p->os_api.close(p->ctx); + pthread_mutex_destroy(&p->lock); + mpp_free(p); + + return MPP_OK; +} + +MppAllocFlagType mpp_allocator_get_flags(const MppAllocator allocator) +{ + MppAllocatorImpl *p = (MppAllocatorImpl *)allocator; + + return p ? p->flags : MPP_ALLOC_FLAG_NONE; +} diff --git a/osal/mpp_allocator.cpp b/osal/mpp_allocator.cpp deleted file mode 100644 index 9d98eafc1..000000000 --- a/osal/mpp_allocator.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_allocator" - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_allocator.h" -#include "mpp_allocator_impl.h" - -#include "os_allocator.h" - -#define MPP_ALLOCATOR_LOCK(p) pthread_mutex_lock(&(p)->lock); -#define MPP_ALLOCATOR_UNLOCK(p) pthread_mutex_unlock(&(p)->lock); - -MPP_RET mpp_allocator_alloc(MppAllocator allocator, MppBufferInfo *info) -{ - if (NULL == allocator || NULL == info) { - mpp_err("mpp_allocator_alloc invalid input: allocator %p info %p\n", - allocator, info); - return MPP_ERR_UNKNOW; - } - - MPP_RET ret = MPP_OK; - MppAllocatorImpl *p = (MppAllocatorImpl *)allocator; - MPP_ALLOCATOR_LOCK(p); - if (p->os_api.alloc) - ret = p->os_api.alloc(p->ctx, info); - MPP_ALLOCATOR_UNLOCK(p); - - return ret; -} - -MPP_RET mpp_allocator_free(MppAllocator allocator, MppBufferInfo *info) -{ - if (NULL == allocator || NULL == info) { - mpp_err("mpp_allocator_alloc invalid input: allocator %p info %p\n", - allocator, info); - return MPP_ERR_UNKNOW; - } - - MPP_RET ret = MPP_OK; - MppAllocatorImpl *p = (MppAllocatorImpl *)allocator; - MPP_ALLOCATOR_LOCK(p); - if (p->os_api.free) - ret = p->os_api.free(p->ctx, info); - MPP_ALLOCATOR_UNLOCK(p); - - return ret; -} - -static MppAllocatorApi mpp_allocator_api = { - sizeof(mpp_allocator_api), - 1, - mpp_allocator_alloc, - mpp_allocator_free, -}; - -MPP_RET mpp_alloctor_get(MppAllocator *allocator, MppAllocatorApi **api, MppBufferType type) -{ - if (NULL == allocator || NULL == api || type >= MPP_BUFFER_TYPE_BUTT) { - mpp_err("mpp_alloctor_get invalid input: buffer %p api %p type %d\n", - allocator, api, type); - return MPP_ERR_UNKNOW; - } - - MppAllocatorImpl *p = mpp_malloc(MppAllocatorImpl, 1); - if (NULL == p) { - mpp_err("mpp_alloctor_get failed to malloc allocator context\n"); - return MPP_ERR_NULL_PTR; - } else - p->type = type; - - - MPP_RET ret = os_allocator_get(&p->os_api, type); - if (MPP_OK == ret) { - p->alignment = SZ_4K; - ret = p->os_api.open(&p->ctx, p->alignment); - } - if (MPP_OK == ret) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&p->lock, &attr); - pthread_mutexattr_destroy(&attr); - - *allocator = p; - *api = &mpp_allocator_api; - } else { - mpp_err("mpp_alloctor_get type %d failed\n", type); - mpp_free(p); - *allocator = NULL; - *api = NULL; - } - - return ret; -} - -MPP_RET mpp_alloctor_put(MppAllocator *allocator) -{ - if (NULL == allocator) { - mpp_err("mpp_alloctor_put invalid input: buffer %p\n", allocator); - return MPP_ERR_NULL_PTR; - } - - MppAllocatorImpl *p = (MppAllocatorImpl *)*allocator; - *allocator = NULL; - if (p->os_api.close) - p->os_api.close(p->ctx); - pthread_mutex_destroy(&p->lock); - mpp_free(p); - - return MPP_OK; -} - diff --git a/osal/mpp_allocator_api.h b/osal/mpp_allocator_api.h new file mode 100644 index 000000000..087b8dff2 --- /dev/null +++ b/osal/mpp_allocator_api.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_ALLOCATOR_API_H +#define MPP_ALLOCATOR_API_H + +#include "mpp_allocator.h" + +typedef MPP_RET (*OsAllocatorFunc)(void *ctx, MppBufferInfo *info); + +typedef struct os_allocator_t { + MppBufferType type; + const char *name; + + MPP_RET (*open)(void **ctx, size_t alignment, MppAllocFlagType flags); + MPP_RET (*close)(void *ctx); + + OsAllocatorFunc alloc; + OsAllocatorFunc free; + OsAllocatorFunc import; + OsAllocatorFunc release; + OsAllocatorFunc mmap; + + /* allocator real flag update callback */ + MppAllocFlagType (*flags)(void *ctx); +} os_allocator; + +#endif /* MPP_ALLOCATOR_API_H */ diff --git a/osal/mpp_callback.c b/osal/mpp_callback.c new file mode 100644 index 000000000..4d5dd213f --- /dev/null +++ b/osal/mpp_callback.c @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_callback" + +#include "mpp_callback.h" + +MPP_RET mpp_callback_f(const char *caller, MppCbCtx *ctx, void *param) +{ + if (ctx && ctx->ctx && ctx->callBack) + return ctx->callBack(caller, ctx->ctx, ctx->cmd, param); + + return MPP_OK; +} diff --git a/osal/mpp_common.c b/osal/mpp_common.c new file mode 100644 index 000000000..dbfd1d122 --- /dev/null +++ b/osal/mpp_common.c @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#include "mpp_common.h" + +static const RK_U8 log2_tab[256] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; + +RK_S32 mpp_log2(RK_U32 v) +{ + RK_S32 n = 0; + + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += log2_tab[v]; + + return n; +} + +RK_S32 mpp_log2_16bit(RK_U32 v) +{ + RK_S32 n = 0; + + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += log2_tab[v]; + + return n; +} + +RK_S32 axb_div_c(RK_S32 a, RK_S32 b, RK_S32 c) +{ + RK_U32 left = 32; + RK_U32 right = 0; + RK_U32 shift; + RK_S32 sign = 1; + RK_S32 tmp; + + 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; (((RK_U32)a << left) >> left) != (RK_U32)a; --left) + ; + + left--; + + while (((RK_U32)b >> right) > (RK_U32)c) + right++; + + if (right > left) { + return 0x7FFFFFFF * sign; + } else { + shift = left - right; + return (RK_S32)((((RK_U32)a << shift) / + (RK_U32)c * (RK_U32)b) >> shift) * sign; + } +} + +RK_U32 mpp_align_8(RK_U32 val) +{ + return MPP_ALIGN(val, 8); +} + +RK_U32 mpp_align_16(RK_U32 val) +{ + return MPP_ALIGN(val, 16); +} + +RK_U32 mpp_align_64(RK_U32 val) +{ + return MPP_ALIGN(val, 64); +} + +RK_U32 mpp_align_128(RK_U32 val) +{ + return MPP_ALIGN(val, 128); +} + +RK_U32 mpp_align_256_odd(RK_U32 val) +{ + return MPP_ALIGN(val, 256) | 256; +} + +RK_U32 mpp_align_128_odd_plus_64(RK_U32 val) +{ + val = MPP_ALIGN(val, 64); + if (((val - 64) % 256 == 128)) + return val; + else + return ((MPP_ALIGN(val, 128) | 128) + 64); +} + +RK_U32 mpp_align_wxh2yuv420(RK_U32 val) +{ + return (val * 3 / 2); +} + +RK_U32 mpp_align_wxh2yuv422(RK_U32 val) +{ + return (val * 2); +} + +RK_U32 mpp_align_wxh2yuv444(RK_U32 val) +{ + return (val * 3); +} + +// Clip a signed integer to the range [0, 2^n - 1] +RK_U32 mpp_clip_uint_pow2(RK_S32 val, RK_S32 n) +{ + /* Calculate mask: 2^n - 1 */ + RK_U32 mask = (1 << n) - 1; + + /* Check if value is out of range */ + RK_U32 sign = val & ~mask; + + /* If out of range, return boundary value; otherwise return original value */ + return sign ? (RK_U32)(-val >> 31 & mask) : (RK_U32)val; +} + +// Divide an unsigned integer x by 2^n and round to nearest integer +RK_U64 mpp_round_pow2(RK_U64 x, RK_U16 n) +{ + /* Special case: no division needed when n=0 */ + if (n == 0) + return x; + + /* Calculate offset: 2^(n-1) for rounding */ + RK_U64 offset = (RK_U64)1 << (n - 1); + + /* Add offset then right-shift n bits to achieve division and rounding */ + return (x + offset) >> n; +} + +// Divide a signed integer x by 2^n and round to nearest integer +RK_S64 mpp_round_pow2_signed(RK_S64 x, RK_U16 n) +{ + if (x < 0) + return -((RK_S64)mpp_round_pow2(-x, n)); + else + return (RK_S64)mpp_round_pow2(x, n); +} \ No newline at end of file diff --git a/osal/mpp_common.cpp b/osal/mpp_common.cpp deleted file mode 100644 index 4c9412677..000000000 --- a/osal/mpp_common.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mpp_common.h" - -static const RK_U8 log2_tab[256] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 -}; - -RK_S32 mpp_log2(RK_U32 v) -{ - RK_S32 n = 0; - if (v & 0xffff0000) { - v >>= 16; - n += 16; - } - if (v & 0xff00) { - v >>= 8; - n += 8; - } - n += log2_tab[v]; - - return n; -} - -RK_S32 mpp_log2_16bit(RK_U32 v) -{ - RK_S32 n = 0; - if (v & 0xff00) { - v >>= 8; - n += 8; - } - n += log2_tab[v]; - - return n; -} - diff --git a/osal/mpp_compat.c b/osal/mpp_compat.c new file mode 100644 index 000000000..7eb07702f --- /dev/null +++ b/osal/mpp_compat.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_compat" + +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "mpp_compat.h" +#include "mpp_compat_impl.h" + +static MppCompat compats[] = { + { + MPP_COMPAT_INC_FBC_BUF_SIZE, + MPP_COMPAT_BOOL, + 1, +#if defined(__ANDROID__) + /* + * The codecs might need extra lines for deblock output, but the + * android world rather risk memory overflow than using the correct + * buf size. + */ + 0, +#else + 1, +#endif + "increase decoder fbc buffer size", + &compats[1], + }, + { + MPP_COMPAT_ENC_ASYNC_INPUT, + MPP_COMPAT_BOOL, + 1, + 0, + "support encoder async input mode", + NULL, + }, + { + MPP_COMPAT_DEC_FBC_HDR_256_ODD, + MPP_COMPAT_BOOL, + 0, + 0, + "set decoder fbc header stride to 256 odd align", + NULL, + }, +}; + +RK_S32 *compat_ext_fbc_buf_size = &compats[MPP_COMPAT_INC_FBC_BUF_SIZE].value_usr; +RK_S32 *compat_ext_async_input = &compats[MPP_COMPAT_ENC_ASYNC_INPUT].value_usr; +RK_S32 *compat_ext_fbc_hdr_256_odd = &compats[MPP_COMPAT_DEC_FBC_HDR_256_ODD].value_usr; + +MppCompat *mpp_compat_query(void) +{ + return compats; +} + +MppCompat *mpp_compat_query_by_id(MppCompatId id) +{ + RK_U32 i; + + for (i = 0; i < MPP_ARRAY_ELEMS(compats); i++) { + if (compats[i].feature_id == id) + return &compats[i]; + } + + return NULL; +} + +MPP_RET mpp_compat_update(MppCompat *compat, RK_S32 value) +{ + if (NULL == compat) + return MPP_NOK; + + if (compat->feature_id >= MPP_COMPAT_BUTT) + return MPP_NOK; + + if (compat != &compats[compat->feature_id]) + return MPP_NOK; + + if (compat->feature_type == MPP_COMPAT_BOOL) + if (value != 0 && value != 1) + return MPP_NOK; + + compat->value_usr = value; + return MPP_OK; +} + +void mpp_compat_show(void) +{ + const MppCompat *compat = compats; + + mpp_log("id| name -- mpp compat info\n"); + + while (compat) { + mpp_log("%d | %s\n", compat->feature_id, compat->name); + + compat = compat->next; + } +} diff --git a/osal/mpp_dmabuf.c b/osal/mpp_dmabuf.c new file mode 100644 index 000000000..d725c3aea --- /dev/null +++ b/osal/mpp_dmabuf.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_common.h" +#include "mpp_dmabuf.h" +#include "mpp_singleton.h" +#include + +#define MPP_NO_PARTIAL_SUPPORT 25 /* ENOTTY */ +#define CACHE_LINE_SIZE 64 + +static RK_U32 has_partial_ops = 0; + +#ifndef DMA_BUF_IOCTL_SYNC_PARTIAL + +#define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 1, const char *) + +struct dma_buf_sync_partial { + __u64 flags; + __u32 offset; + __u32 len; +}; + +#define DMA_BUF_IOCTL_SYNC_PARTIAL _IOW(DMA_BUF_BASE, 2, struct dma_buf_sync_partial) + +#endif + +static void mpp_dmabuf_init(void) +{ + /* + * update has_partial_ops by env + * NOTE: When dmaheap is enabled the dmaheap fd partial ops is fine. + * But the drm fd partial ops may have error when kernel version above 4.19 + * So we provide the mpp_dmabuf_has_partial_ops env to disable partial ops. + */ + mpp_env_get_u32("mpp_dmabuf_has_partial_ops", &has_partial_ops, has_partial_ops); +} + +MPP_SINGLETON(MPP_SGLN_DMABUF, mpp_dmabuf, mpp_dmabuf_init, NULL) + +MPP_RET mpp_dmabuf_sync_begin(RK_S32 fd, RK_S32 ro, const char *caller) +{ + struct dma_buf_sync sync; + RK_S32 ret; + + sync.flags = DMA_BUF_SYNC_START | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync); + if (ret) { + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_dmabuf_sync_end(RK_S32 fd, RK_S32 ro, const char *caller) +{ + struct dma_buf_sync sync; + RK_S32 ret; + + sync.flags = DMA_BUF_SYNC_END | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync); + if (ret) { + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; +} + +MPP_RET mpp_dmabuf_sync_partial_begin(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller) +{ + if (has_partial_ops) { + struct dma_buf_sync_partial sync; + RK_S32 ret; + + if (!length) + return MPP_OK; + + sync.flags = DMA_BUF_SYNC_START | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + sync.offset = MPP_ALIGN_DOWN(offset, CACHE_LINE_SIZE); + sync.len = MPP_ALIGN(length + offset - sync.offset, CACHE_LINE_SIZE); + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC_PARTIAL, &sync); + if (ret) { + if (errno == MPP_NO_PARTIAL_SUPPORT) { + has_partial_ops = 0; + goto NOT_SUPPORT; + } + + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; + } + +NOT_SUPPORT: + return mpp_dmabuf_sync_begin(fd, ro, caller); +} + +MPP_RET mpp_dmabuf_sync_partial_end(RK_S32 fd, RK_S32 ro, RK_U32 offset, RK_U32 length, const char *caller) +{ + if (has_partial_ops) { + struct dma_buf_sync_partial sync; + RK_S32 ret; + + if (!length) + return MPP_OK; + + sync.flags = DMA_BUF_SYNC_END | (ro ? DMA_BUF_SYNC_READ : DMA_BUF_SYNC_RW); + sync.offset = MPP_ALIGN_DOWN(offset, CACHE_LINE_SIZE); + sync.len = MPP_ALIGN(length + offset - sync.offset, CACHE_LINE_SIZE); + + ret = ioctl(fd, DMA_BUF_IOCTL_SYNC_PARTIAL, &sync); + if (ret) { + if (errno == MPP_NO_PARTIAL_SUPPORT) { + has_partial_ops = 0; + goto NOT_SUPPORT; + } + + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; + } + +NOT_SUPPORT: + return mpp_dmabuf_sync_end(fd, ro, caller); +} + +MPP_RET mpp_dmabuf_set_name(RK_S32 fd, const char *name, const char *caller) +{ + RK_S32 ret = ioctl(fd, DMA_BUF_SET_NAME, name); + if (ret) { + mpp_err_f("ioctl failed for %s from %s\n", strerror(errno), caller); + return MPP_NOK; + } + + return MPP_OK; +} + +RK_U32 mpp_dmabuf_sync_partial_support(void) +{ + return has_partial_ops; +} diff --git a/osal/mpp_env.c b/osal/mpp_env.c new file mode 100644 index 000000000..e228a34af --- /dev/null +++ b/osal/mpp_env.c @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#include "mpp_env.h" +#include "os_env.h" + +// TODO: add previous value compare to save call times + +RK_S32 mpp_env_get_u32(const char *name, RK_U32 *value, RK_U32 default_value) +{ + return os_get_env_u32(name, value, default_value); +} + +RK_S32 mpp_env_get_str(const char *name, const char **value, const char *default_value) +{ + return os_get_env_str(name, value, default_value); +} + +RK_S32 mpp_env_set_u32(const char *name, RK_U32 value) +{ + return os_set_env_u32(name, value); +} + +RK_S32 mpp_env_set_str(const char *name, char *value) +{ + return os_set_env_str(name, value); +} + + diff --git a/osal/mpp_env.cpp b/osal/mpp_env.cpp deleted file mode 100644 index 76e2081d5..000000000 --- a/osal/mpp_env.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mpp_env.h" -#include "os_env.h" - -// TODO: add previous value compare to save call times - -RK_S32 mpp_env_get_u32(const char *name, RK_U32 *value, RK_U32 default_value) -{ - return os_get_env_u32(name, value, default_value); -} - -RK_S32 mpp_env_get_str(const char *name, char **value, char *default_value) -{ - return os_get_env_str(name, value, default_value); -} - -RK_S32 mpp_env_set_u32(const char *name, RK_U32 value) -{ - return os_set_env_u32(name, value); -} - -RK_S32 mpp_env_set_str(const char *name, char *value) -{ - return os_set_env_str(name, value); -} - - diff --git a/osal/mpp_eventfd.c b/osal/mpp_eventfd.c new file mode 100644 index 000000000..d11e94e2b --- /dev/null +++ b/osal/mpp_eventfd.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include + +#include "mpp_eventfd.h" + +RK_S32 mpp_eventfd_get(RK_U32 init) +{ + RK_S32 fd = eventfd(init, 0); + + if (fd < 0) + fd = errno; + + return fd; +} + +RK_S32 mpp_eventfd_put(RK_S32 fd) +{ + if (fd >= 0) + close(fd); + + return 0; +} + +RK_S32 mpp_eventfd_read(RK_S32 fd, RK_U64 *val, RK_S64 timeout) +{ + struct pollfd nfds; + RK_U64 tmp = 0; + RK_S32 ret = 0; + + if (NULL == val) + val = &tmp; + + nfds.fd = fd; + nfds.events = POLLIN; + + ret = poll(&nfds, 1, timeout); + if (ret == 1 && (nfds.revents & POLLIN) && + sizeof(RK_U64) == read(fd, val, sizeof(RK_U64))) { + ret = 0; + } else + ret = errno; + + return ret; +} + +RK_S32 mpp_eventfd_write(RK_S32 fd, RK_U64 val) +{ + RK_S32 ret = 0; + + if (sizeof(RK_U64) != write(fd, &val, sizeof(val))) + ret = errno; + + return ret; +} diff --git a/osal/mpp_list.c b/osal/mpp_list.c new file mode 100644 index 000000000..9d0f65c7d --- /dev/null +++ b/osal/mpp_list.c @@ -0,0 +1,598 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_list" + +#include +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#define LIST_DEBUG(fmt, ...) mpp_log(fmt, ## __VA_ARGS__) +#define LIST_ERROR(fmt, ...) mpp_err(fmt, ## __VA_ARGS__) + +static inline void list_node_init(MppListNode *node) +{ + node->prev = node->next = node; +} + +static inline void list_node_init_with_key_and_size(MppListNode *node, rk_u32 key, rk_s32 size) +{ + list_node_init(node); + node->key = key; + node->size = size; +} + +static MppListNode* create_list(void *data, rk_s32 size, rk_u32 key) +{ + MppListNode *node = mpp_malloc_size(MppListNode, sizeof(MppListNode) + size); + + if (node) { + void *dst = (void*)(node + 1); + list_node_init_with_key_and_size(node, key, size); + memcpy(dst, data, size); + } else { + LIST_ERROR("failed to allocate list node"); + } + return node; +} + +static inline void _mpp_list_add(MppListNode * _new, MppListNode * prev, MppListNode * next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +static inline void mpp_list_add(MppListNode *_new, MppListNode *head) +{ + _mpp_list_add(_new, head, head->next); +} + +static inline void mpp_list_add_tail(MppListNode *_new, MppListNode *head) +{ + _mpp_list_add(_new, head->prev, head); +} + +int mpp_list_add_at_head(MppList *list, void *data, int size) +{ + rk_s32 ret = -EINVAL; + + if (list->head) { + MppListNode *node = create_list(data, size, 0); + if (node) { + mpp_list_add(node, list->head); + list->count++; + ret = 0; + } else { + ret = -ENOMEM; + } + } + return ret; +} + +int mpp_list_add_at_tail(MppList *list, void *data, int size) +{ + rk_s32 ret = -EINVAL; + + if (list->head) { + MppListNode *node = create_list(data, size, 0); + + if (node) { + mpp_list_add_tail(node, list->head); + list->count++; + ret = 0; + } else { + ret = -ENOMEM; + } + } + return ret; +} + +static void release_list(MppListNode*node, void *data, rk_s32 size) +{ + void *src = (void*)(node + 1); + + if (node->size == size) { + if (data) + memcpy(data, src, size); + } else { + LIST_ERROR("node size check failed when release_list"); + size = (size < node->size) ? (size) : (node->size); + if (data) + memcpy(data, src, size); + } + mpp_free(node); +} + +static inline void _mpp_list_del(MppListNode *prev, MppListNode *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void mpp_list_del_init(MppListNode *node) +{ + _mpp_list_del(node->prev, node->next); + list_node_init(node); +} + +static inline void _list_del_node_no_lock(MppListNode *node, void *data, rk_s32 size) +{ + mpp_list_del_init(node); + release_list(node, data, size); +} + +int mpp_list_del_at_head(MppList *list, void *data, int size) +{ + rk_s32 ret = -EINVAL; + + if (list->head && list->count) { + _list_del_node_no_lock(list->head->next, data, size); + list->count--; + ret = 0; + } + return ret; +} + +int mpp_list_del_at_tail(MppList *list, void *data, int size) +{ + rk_s32 ret = -EINVAL; + + if (list->head && list->count) { + _list_del_node_no_lock(list->head->prev, data, size); + list->count--; + ret = 0; + } + return ret; +} +static MppListNode* create_list_with_size(void *data, rk_s32 size, rk_u32 key) +{ + MppListNode *node = mpp_malloc_size(MppListNode, sizeof(MppListNode) + sizeof(size) + size); + + if (node) { + rk_s32 *dst = (rk_s32 *)(node + 1); + list_node_init_with_key_and_size(node, key, size); + *dst++ = size; + memcpy(dst, data, size); + } else { + LIST_ERROR("failed to allocate list node"); + } + return node; +} + +rk_s32 mpp_list_fifo_wr(MppList *list, void *data, rk_s32 size) +{ + rk_s32 ret = -EINVAL; + + if (list && list->head) { + MppListNode *node = create_list_with_size(data, size, 0); + + if (node) { + mpp_list_add_tail(node, list->head); + list->count++; + ret = 0; + } else { + ret = -ENOMEM; + } + } + return ret; +} + +static void release_list_with_size(MppListNode* node, void *data, rk_s32 *size) +{ + rk_s32 *src = (rk_s32*)(node + 1); + rk_s32 data_size = *src++; + + *size = data_size; + + if (data) + memcpy(data, src, data_size); + + mpp_free(node); +} + +rk_s32 mpp_list_fifo_rd(MppList *list, void *data, rk_s32 *size) +{ + rk_s32 ret = -EINVAL; + + if (list && list->head && list->count) { + MppListNode *node = list->head->next; + + mpp_list_del_init(node); + release_list_with_size(node, data, size); + list->count--; + ret = 0; + } + return ret; +} + +int mpp_list_is_empty(MppList *list) +{ + return list->count == 0; +} + +int mpp_list_size(MppList *list) +{ + return list->count; +} + +rk_s32 mpp_list_add_by_key(MppList *list, void *data, rk_s32 size, rk_u32 *key) +{ + rk_s32 ret = 0; + + if (list->head) { + MppListNode *node; + rk_u32 list_key = mpp_list_get_key(list); + + *key = list_key; + node = create_list(data, size, list_key); + if (node) { + mpp_list_add_tail(node, list->head); + list->count++; + ret = 0; + } else { + ret = -ENOMEM; + } + } + return ret; +} + +rk_s32 mpp_list_del_by_key(MppList *list, void *data, rk_s32 size, rk_u32 key) +{ + rk_s32 ret = 0; + + if (list && list->head && list->count) { + MppListNode *tmp = list->head->next; + + ret = -EINVAL; + while (tmp->next != list->head) { + if (tmp->key == key) { + _list_del_node_no_lock(tmp, data, size); + list->count--; + break; + } + tmp = tmp->next; + } + } + return ret; +} + + +rk_s32 mpp_list_show_by_key(MppList *list, void *data, rk_u32 key) +{ + rk_s32 ret = -EINVAL; + + (void)list; + (void)data; + (void)key; + return ret; +} + +void mpp_list_flush(MppList* list) +{ + if (list->head) { + while (list->count) { + MppListNode* node = list->head->next; + + mpp_list_del_init(node); + + if (list->destroy) { + list->destroy((void*)(node + 1)); + } + + mpp_free(node); + list->count--; + } + } + + mpp_list_signal(list); +} + +MPP_RET mpp_list_wait(MppList* list) +{ + int ret; + + ret = mpp_mutex_cond_wait(&list->cond_lock); + + if (ret == 0) { + return MPP_OK; + } else if (ret == ETIMEDOUT) { + return MPP_NOK; + } else { + return MPP_NOK; + } +} + +MPP_RET mpp_list_wait_timed(MppList *list, rk_s64 timeout) +{ + int ret; + + ret = (MPP_RET)mpp_mutex_cond_timedwait(&list->cond_lock, timeout); + + if (ret == 0) { + return MPP_OK; + } else if (ret == ETIMEDOUT) { + return MPP_ERR_TIMEOUT; + } else { + return MPP_NOK; + } +} + +MPP_RET mpp_list_wait_lt(MppList *list, rk_s64 timeout, rk_s32 val) +{ + if (list->count < val) + return MPP_OK; + + if (timeout < 0) { + return mpp_list_wait(list); + } else { + return mpp_list_wait_timed(list, timeout); + } +} + +MPP_RET mpp_list_wait_le(MppList *list, rk_s64 timeout, rk_s32 val) +{ + if (list->count <= val) + return MPP_OK; + + if (timeout < 0) { + return mpp_list_wait(list); + } else { + return mpp_list_wait_timed(list, timeout); + } +} + +MPP_RET mpp_list_wait_gt(MppList *list, rk_s64 timeout, rk_s32 val) +{ + if (list->count > val) + return MPP_OK; + + if (timeout < 0) { + return mpp_list_wait(list); + } else { + return mpp_list_wait_timed(list, timeout); + } +} + +MPP_RET mpp_list_wait_ge(MppList *list, rk_s64 timeout, rk_s32 val) +{ + if (list->count >= val) + return MPP_OK; + + if (timeout < 0) { + return mpp_list_wait(list); + } else { + return mpp_list_wait_timed(list, timeout); + } +} + +void mpp_list_signal(MppList *list) +{ + mpp_mutex_cond_signal(&list->cond_lock); +} + +rk_u32 mpp_list_get_key(MppList *list) +{ + return list->keys++; +} + +MppList *mpp_list_create(node_destructor func) +{ + MppList *list = mpp_malloc(MppList, 1); + + if (list == NULL) { + LIST_ERROR("Failed to allocate memory for mpp_list.\n"); + return NULL; + } + + list->destroy = func; + list->count = 0; + + list->head = mpp_malloc(MppListNode, 1); + if (list->head == NULL) { + LIST_ERROR("Failed to allocate memory for list header.\n"); + mpp_free(list); + return NULL; + } + + list_node_init_with_key_and_size(list->head, 0, 0); + + mpp_mutex_cond_init(&list->cond_lock); + + return list; +} + +void mpp_list_destroy(MppList *list) +{ + MppListNode *node; + + if (!list) + return; + + mpp_list_flush(list); + + node = list->head->next; + while (node != list->head) { + MppListNode *next = node->next; + + mpp_free(node); + node = next; + } + + mpp_mutex_cond_destroy(&list->cond_lock); + + mpp_free(list->head); + list->head = NULL; + + mpp_free(list); + list = NULL; +} + +/* list sort porting from kernel list_sort.c */ + +/* + * Returns a list organized in an intermediate format suited + * to chaining of merge() calls: null-terminated, no reserved or + * sentinel head node, "prev" links not maintained. + */ +static struct list_head *merge(void *priv, ListCmpFunc cmp, + struct list_head *a, struct list_head *b) +{ + struct list_head *head, **tail = &head; + + for (;;) { + /* if equal, take 'a' -- important for sort stability */ + if (cmp(priv, a, b) <= 0) { + *tail = a; + tail = &a->next; + a = a->next; + if (!a) { + *tail = b; + break; + } + } else { + *tail = b; + tail = &b->next; + b = b->next; + if (!b) { + *tail = a; + break; + } + } + } + return head; +} + +/* + * Combine final list merge with restoration of standard doubly-linked + * list structure. This approach duplicates code from merge(), but + * runs faster than the tidier alternatives of either a separate final + * prev-link restoration pass, or maintaining the prev links + * throughout. + */ +static void merge_final(void *priv, ListCmpFunc cmp, struct list_head *head, + struct list_head *a, struct list_head *b) +{ + struct list_head *tail = head; + rk_u8 count = 0; + + for (;;) { + /* if equal, take 'a' -- important for sort stability */ + if (cmp(priv, a, b) <= 0) { + tail->next = a; + a->prev = tail; + tail = a; + a = a->next; + if (!a) + break; + } else { + tail->next = b; + b->prev = tail; + tail = b; + b = b->next; + if (!b) { + b = a; + break; + } + } + } + + /* Finish linking remainder of list b on to tail */ + tail->next = b; + do { + /* + * If the merge is highly unbalanced (e.g. the input is + * already sorted), this loop may run many iterations. + * Continue callbacks to the client even though no + * element comparison is needed, so the client's cmp() + * routine can invoke cond_resched() periodically. + */ + if (!++count) + cmp(priv, b, b); + b->prev = tail; + tail = b; + b = b->next; + } while (b); + + /* And the final links to make a circular doubly-linked list */ + tail->next = head; + head->prev = tail; +} + +void list_sort(void *priv, struct list_head *head, ListCmpFunc cmp) +{ + struct list_head *list = head->next, *pending = NULL; + size_t count = 0; /* Count of pending */ + + if (list == head->prev) /* Zero or one elements */ + return; + + /* Convert to a null-terminated singly-linked list. */ + head->prev->next = NULL; + + /* + * Data structure invariants: + * - All lists are singly linked and null-terminated; prev + * pointers are not maintained. + * - pending is a prev-linked "list of lists" of sorted + * sublists awaiting further merging. + * - Each of the sorted sublists is power-of-two in size. + * - Sublists are sorted by size and age, smallest & newest at front. + * - There are zero to two sublists of each size. + * - A pair of pending sublists are merged as soon as the number + * of following pending elements equals their size (i.e. + * each time count reaches an odd multiple of that size). + * That ensures each later final merge will be at worst 2:1. + * - Each round consists of: + * - Merging the two sublists selected by the highest bit + * which flips when count is incremented, and + * - Adding an element from the input as a size-1 sublist. + */ + do { + size_t bits; + struct list_head **tail = &pending; + + /* Find the least-significant clear bit in count */ + for (bits = count; bits & 1; bits >>= 1) + tail = &(*tail)->prev; + /* Do the indicated merge */ + if (bits) { + struct list_head *a = *tail, *b = a->prev; + + a = merge(priv, cmp, b, a); + /* Install the merged result in place of the inputs */ + a->prev = b->prev; + *tail = a; + } + + /* Move one element from input list to pending */ + list->prev = pending; + pending = list; + list = list->next; + pending->next = NULL; + count++; + } while (list); + + /* End of input; merge together all the pending lists. */ + list = pending; + pending = pending->prev; + for (;;) { + struct list_head *next = pending->prev; + + if (!next) + break; + list = merge(priv, cmp, pending, list); + pending = next; + } + /* The final merge, rebuilding prev links */ + merge_final(priv, cmp, head, pending, list); +} diff --git a/osal/mpp_lock.c b/osal/mpp_lock.c new file mode 100644 index 000000000..74a716948 --- /dev/null +++ b/osal/mpp_lock.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_lock" + +#include "mpp_env.h" +#include "mpp_log.h" +#include "mpp_lock.h" +#include "mpp_time.h" + +#define LOCK_IDLE 0 +#define LOCK_BUSY 1 + +void mpp_spinlock_init(spinlock_t *lock) +{ + MPP_SYNC_CLR(&lock->lock); + lock->count = 0; + lock->time = 0; + + mpp_env_get_u32("mpp_lock_debug", &lock->debug, 0); +} + +void mpp_spinlock_lock(spinlock_t *lock) +{ + RK_S64 time = 0; + + if (lock->debug) + time = mpp_time(); + + while (!MPP_BOOL_CAS(&lock->lock, LOCK_IDLE, LOCK_BUSY)) { + sched_yield(); + } + + if (lock->debug && time) { + lock->time += mpp_time() - time; + lock->count++; + } +} + +void mpp_spinlock_deinit(spinlock_t *lock, const char *name) +{ + if (lock->debug && lock->count) { + mpp_log("lock %s lock %lld times take time %lld avg %d", name, + lock->count, lock->time, (RK_S32)(lock->time / lock->count)); + } +} + +void mpp_spinlock_unlock(spinlock_t *lock) +{ + MPP_SYNC_CLR(&lock->lock); +} + +bool mpp_spinlock_trylock(spinlock_t *lock) +{ + RK_S64 time = 0; + bool ret; + + if (lock->debug) + time = mpp_time(); + + ret = MPP_BOOL_CAS(&lock->lock, LOCK_IDLE, LOCK_BUSY); + + if (ret && lock->debug && time) { + lock->time += mpp_time() - time; + lock->count++; + } + + return ret; +} diff --git a/osal/mpp_log.c b/osal/mpp_log.c new file mode 100644 index 000000000..fbf3871d0 --- /dev/null +++ b/osal/mpp_log.c @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_log" + +#include +#include + +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "os_log.h" + +#define MPP_LOG_MAX_LEN 256 + +#ifdef __cplusplus +extern "C" { +#endif + +RK_U32 mpp_debug = 0; + +// TODO: add log timing information and switch flag +static const char *msg_log_warning = "log message is long\n"; +static const char *msg_log_nothing = "\n"; +static int mpp_log_level = MPP_LOG_INFO; +static MppLogCb mpp_log_ext_cb = NULL; +static void *mpp_log_ext_ctx = NULL; + +static os_log_callback log_func[] = { + NULL, /* MPP_LOG_DEFAULT */ + os_log_fatal, /* MPP_LOG_FATAL */ + os_log_error, /* MPP_LOG_ERROR */ + os_log_warn, /* MPP_LOG_WARN */ + os_log_info, /* MPP_LOG_INFO */ + os_log_debug, /* MPP_LOG_DEBUG */ + os_log_trace, /* MPP_LOG_VERBOSE */ + os_log_info, /* MPP_LOG_DEFAULT */ +}; + +static void __mpp_log(os_log_callback func, const char *tag, const char *fmt, + const char *fname, va_list args) +{ + char msg[MPP_LOG_MAX_LEN + 1]; + char *tmp = msg; + const char *buf = fmt; + size_t len_fmt = strnlen(fmt, MPP_LOG_MAX_LEN); + size_t len_name = (fname) ? (strnlen(fname, MPP_LOG_MAX_LEN)) : (0); + size_t buf_left = MPP_LOG_MAX_LEN; + size_t len_all = len_fmt + len_name; + + if (NULL == tag) + tag = MODULE_TAG; + + if (len_name) { + buf = msg; + buf_left -= snprintf(msg, buf_left, "%s ", fname); + tmp += len_name + 1; + } + + if (len_all == 0) { + buf = msg_log_nothing; + } else if (len_all >= MPP_LOG_MAX_LEN) { + buf_left -= snprintf(tmp, buf_left, "%s", msg_log_warning); + buf = msg; + } else { + snprintf(tmp, buf_left, "%s", fmt); + if (fmt[len_fmt - 1] != '\n') { + tmp[len_fmt] = '\n'; + tmp[len_fmt + 1] = '\0'; + } + buf = msg; + } + + func(tag, buf, args); +} + +void _mpp_log(const char *tag, const char *fmt, const char *fname, ...) +{ + va_list args; + + mpp_logw("warning: use new logx function\n"); + + va_start(args, fname); + __mpp_log(os_log_info, tag, fmt, fname, args); + va_end(args); +} + +void _mpp_err(const char *tag, const char *fmt, const char *fname, ...) +{ + va_list args; + + mpp_logw("warning: use new logx function\n"); + + va_start(args, fname); + __mpp_log(os_log_error, tag, fmt, fname, args); + va_end(args); +} + +void _mpp_log_l(int level, const char *tag, const char *fmt, const char *fname, ...) +{ + va_list args; + int log_level; + + if (mpp_log_ext_cb) { + va_start(args, fname); + mpp_log_ext_cb(mpp_log_ext_ctx, level, tag, fmt, fname, args); + va_end(args); + return; + } + + if (level <= MPP_LOG_UNKNOWN || level >= MPP_LOG_SILENT) + return; + + log_level = mpp_log_level; + if (log_level >= MPP_LOG_SILENT) + return; + + if (level > log_level) + return; + + va_start(args, fname); + __mpp_log(log_func[level], tag, fmt, fname, args); + va_end(args); +} + +void mpp_llog(int level, const char *tag, const char *fmt, const char *fname, ...) +{ + va_list args; + char *log_buf = NULL; + int log_size = SZ_1K; + int log_base = 0; + int log_len = 0; + int log_level; + int i; + + if (mpp_log_ext_cb) { + va_start(args, fname); + mpp_log_ext_cb(mpp_log_ext_ctx, level, tag, fmt, fname, args); + va_end(args); + return; + } + + if (level <= MPP_LOG_UNKNOWN || level >= MPP_LOG_SILENT) + return; + + log_level = mpp_log_level; + if (log_level >= MPP_LOG_SILENT) + return; + + if (level > log_level) + return; + + if (NULL == tag) + tag = MODULE_TAG; + + + va_start(args, fname); + + /* get log len and create buffer */ + do { + log_buf = (char *)malloc(log_size); + if (!log_buf) + break; + + log_len = vsnprintf(log_buf, log_size - 1, fmt, args); + if (log_len < log_size - 1) + break; + + free(log_buf); + log_size <<= 1; + } while (1); + + va_end(args); + + for (i = 0; i < log_len; i++) { + if (log_buf[i] == '\n') { + /* skip empty line */ + if (log_base < i) { + log_buf[i] = '\0'; + log_func[level](tag, log_buf + log_base, args); + /* restore \n */ + log_buf[i] = '\n'; + } + + log_base = i + 1; + } + } + + if (log_buf) + free(log_buf); +} + +void mpp_set_log_level(int level) +{ + if (level <= MPP_LOG_UNKNOWN || level > MPP_LOG_SILENT) { + mpp_logw("log level should in range [%d : %d] invalid intput %d\n", + MPP_LOG_FATAL, MPP_LOG_SILENT, level); + level = MPP_LOG_INFO; + } + + mpp_log_level = level; +} + +int mpp_get_log_level(void) +{ + int level; + + mpp_env_get_u32("mpp_log_level", (RK_U32 *)&level, mpp_log_level); + + if (level <= MPP_LOG_UNKNOWN || level > MPP_LOG_SILENT) + level = MPP_LOG_INFO; + + mpp_log_level = level; + + return level; +} + +int mpp_set_log_callback(void *ctx, MppLogCb cb) +{ + mpp_log_ext_cb = cb; + mpp_log_ext_ctx = ctx; + + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/osal/mpp_log.cpp b/osal/mpp_log.cpp deleted file mode 100644 index c9f150436..000000000 --- a/osal/mpp_log.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_log" - -#include -#include -#include - -#include "mpp_log.h" -#include "mpp_mem.h" -#include "mpp_common.h" - -#include "os_log.h" - -#define MPP_LOG_MAX_LEN 256 - -typedef void (*mpp_log_callback)(const char*, const char*, va_list); - - -#ifdef __cplusplus -extern "C" { -#endif - -static RK_U32 mpp_log_flag = 0; - -// TODO: add log timing information and switch flag -static const char *msg_log_warning = "log message is long\n"; -static const char *msg_log_nothing = "\n"; - -void __mpp_log(mpp_log_callback func, const char *tag, const char *fmt, const char *fname, va_list args) -{ - char msg[MPP_LOG_MAX_LEN + 1]; - char *tmp = msg; - const char *buf = fmt; - size_t len_fmt = strnlen(fmt, MPP_LOG_MAX_LEN); - size_t len_name = (fname) ? (strnlen(fname, MPP_LOG_MAX_LEN)) : (0); - size_t buf_left = MPP_LOG_MAX_LEN; - size_t len_all = len_fmt + len_name; - - if (NULL == tag) - tag = MODULE_TAG; - - if (len_name) { - buf = msg; - buf_left -= snprintf(msg, buf_left, "%s ", fname); - tmp += len_name + 1; - } - - if (len_all == 0) { - buf = msg_log_nothing; - } else if (len_all >= MPP_LOG_MAX_LEN) { - buf_left -= snprintf(tmp, buf_left, "%s", msg_log_warning); - buf = msg; - } else { - snprintf(tmp, buf_left, "%s", fmt); - if (fmt[len_fmt - 1] != '\n') { - tmp[len_fmt] = '\n'; - tmp[len_fmt + 1] = '\0'; - } - buf = msg; - } - - func(tag, buf, args); -} - -void _mpp_log(const char *tag, const char *fmt, const char *fname, ...) -{ - va_list args; - va_start(args, fname); - __mpp_log(os_log, tag, fmt, fname, args); - va_end(args); -} - -void __mpp_dbg(RK_U32 debug, RK_U32 flag, const char *tag, const char *fmt, const char *fname, ...) -{ - if (debug & flag) { - va_list args; - va_start(args, fname); - __mpp_log(os_log, tag, fmt, fname, args); - va_end(args); - } -} - -void _mpp_err(const char *tag, const char *fmt, const char *fname, ...) -{ - va_list args; - va_start(args, fname); - __mpp_log(os_err, tag, fmt, fname, args); - va_end(args); -} - -void mpp_log_set_flag(RK_U32 flag) -{ - mpp_log_flag = flag; - return ; -} - -RK_U32 mpp_log_get_flag() -{ - return mpp_log_flag; -} - -#ifdef __cplusplus -} -#endif diff --git a/osal/mpp_mem.c b/osal/mpp_mem.c new file mode 100644 index 000000000..e5eb66002 --- /dev/null +++ b/osal/mpp_mem.c @@ -0,0 +1,799 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_mem" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "os_mem.h" + +// mpp_mem_debug bit mask +#define MEM_DEBUG_EN (0x00000001) +// NOTE: runtime log need debug enable +#define MEM_RUNTIME_LOG (0x00000002) +#define MEM_NODE_LOG (0x00000004) +#define MEM_EXT_ROOM (0x00000010) +#define MEM_POISON (0x00000020) + +// default memory align size is set to 32 +#define MEM_MAX_INDEX (0x7fffffff) +#define MEM_ALIGN 32 +#define MEM_ALIGN_MASK (MEM_ALIGN - 1) +#define MEM_ALIGNED(x) (((x) + MEM_ALIGN_MASK) & (~MEM_ALIGN_MASK)) +#define MEM_HEAD_ROOM(debug) (((debug & MEM_EXT_ROOM) != 0) ? (MEM_ALIGN) : (0)) +#define MEM_NODE_MAX (1024) +#define MEM_FREE_MAX (512) +#define MEM_LOG_MAX (1024) +#define MEM_CHECK_MARK (0xdd) +#define MEM_HEAD_MASK (0xab) +#define MEM_TAIL_MASK (0xcd) + +#define MPP_MEM_ASSERT(srv, cond) \ + do { \ + if (!(cond)) { \ + mpp_err("found mpp_mem assert failed, start dumping:\n"); \ + mpp_mem_srv_dump(srv, __FUNCTION__); \ + mpp_assert(cond); \ + } \ + } while (0) + +#define get_srv_mem(caller) \ + ({ \ + MppMemSrv *__tmp; \ + if (!srv_mem) { \ + mpp_mem_srv_init(); \ + } \ + if (srv_mem) { \ + __tmp = srv_mem; \ + } else { \ + mpp_err("mpp mem srv not init at %s : %s\n", __FUNCTION__, caller); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +#define get_srv_mem_f() \ + ({ \ + MppMemSrv *__tmp; \ + if (!srv_mem) { \ + mpp_mem_srv_init(); \ + } \ + if (srv_mem) { \ + __tmp = srv_mem; \ + } else { \ + mpp_err("mpp mem srv not init at %s\n", __FUNCTION__); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +typedef enum MppMemOps_e { + MEM_MALLOC, + MEM_REALLOC, + MEM_FREE, + MEM_FREE_DELAY, + + MEM_OPS_BUTT, +} MppMemOps; + +/* + * Here we combined valid flag with index value to keep node structure small + * If index >= 0 this node is valid otherwise it is invalid + * When we need to invalid one index use ~ to revert all bit + * Then max valid index is 0x7fffffff. When index goes beyond it and becomes + * negative value index will be reset to zero. + */ +typedef struct MppMemNode_t { + rk_s32 index; + size_t size; + void *ptr; + const char *caller; +} MppMemNode; + +typedef struct MppMemLog_t { + rk_u32 index; + MppMemOps ops; + size_t size_0; // size at input + size_t size_1; // size at output + void *ptr; // ptr at input + void *ret; // ptr at output + MppMemNode *node; // node for operation + const char *caller; +} MppMemLog; + +typedef struct MppMemSrv_t { + // data for node record and delay free check + rk_s32 nodes_max; + rk_s32 nodes_idx; + rk_s32 nodes_cnt; + rk_s32 frees_max; + rk_s32 frees_idx; + rk_s32 frees_cnt; + + MppMemNode *nodes; + MppMemNode *frees; + + // data for log record + rk_u32 log_index; + rk_s32 log_max; + rk_s32 log_idx; + rk_s32 log_cnt; + + MppMemLog *logs; + rk_u32 total_size; + rk_u32 total_max; + pthread_mutex_t lock; + rk_u32 debug; +} MppMemSrv; + +static MppMemSrv *srv_mem = NULL; + +static const char *ops2str[MEM_OPS_BUTT] = { + "malloc", + "realloc", + "free", + "delayed", +}; + +static void show_mem(rk_u32 *buf, rk_s32 size) +{ + mpp_err("dumping buf %p size %d start\n", buf, size); + + while (size > 0) { + if (size >= 16) { + mpp_err("%08x %08x %08x %08x\n", buf[0], buf[1], buf[2], buf[3]); + buf += 4; + size -= 16; + } else if (size >= 12) { + mpp_err("%08x %08x %08x\n", buf[0], buf[1], buf[2]); + buf += 3; + size -= 12; + } else if (size >= 8) { + mpp_err("%08x %08x\n", buf[0], buf[1]); + buf += 2; + size -= 8; + } else if (size >= 4) { + mpp_err("%08x\n", buf[0]); + buf += 1; + size -= 4; + } else { + mpp_log("end with size %d\n", size); + break; + } + } + mpp_err("dumping buf %p size %d end\n", buf, size); +} + +static void set_mem_ext_room(void *p, size_t size) +{ + memset((rk_u8 *)p - MEM_ALIGN, MEM_HEAD_MASK, MEM_ALIGN); + memset((rk_u8 *)p + size, MEM_TAIL_MASK, MEM_ALIGN); +} + +void mpp_mem_srv_dump(MppMemSrv *srv, const char *caller) +{ + MppMemNode *node = srv->nodes; + rk_s32 start; + rk_s32 tmp_cnt; + rk_s32 i; + + mpp_log("mpp_mem enter status dumping from %s:\n", caller); + + mpp_log("mpp_mem node count %d:\n", srv->nodes_cnt); + if (srv->nodes_cnt) { + for (i = 0; i < srv->nodes_max; i++, node++) { + if (node->index < 0) + continue; + + mpp_log("mpp_memory index %d caller %-32s size %-8u ptr %p\n", + node->index, node->caller, node->size, node->ptr); + } + } + + node = srv->frees; + mpp_log("mpp_mem free count %d:\n", srv->frees_cnt); + if (srv->frees_cnt) { + for (i = 0; i < srv->frees_max; i++, node++) { + if (node->index < 0) + continue; + + mpp_log("mpp_freed index %d caller %-32s size %-8u ptr %p\n", + node->index, node->caller, node->size, node->ptr); + } + } + + start = srv->log_idx - srv->log_cnt; + tmp_cnt = srv->log_cnt; + + if (start < 0) + start += srv->log_max; + + mpp_log("mpp_mem enter log dumping:\n"); + + while (tmp_cnt) { + MppMemLog *log = &srv->logs[start]; + + mpp_log("idx %-8d op: %-7s from %-32s ptr %10p %10p size %7d %7d\n", + log->index, ops2str[log->ops], log->caller, + log->ptr, log->ret, log->size_0, log->size_1); + + start++; + if (start >= srv->log_max) + start = 0; + + tmp_cnt--; + } +} + +static void check_mem(MppMemSrv *srv, void *ptr, size_t size, const char *caller) +{ + rk_u8 *p; + rk_s32 i; + + if ((srv->debug & MEM_EXT_ROOM) == 0) + return ; + + p = (rk_u8 *)ptr - MEM_ALIGN; + + for (i = 0; i < MEM_ALIGN; i++) { + if (p[i] != MEM_HEAD_MASK) { + mpp_err("%s checking ptr %p head room found error!\n", caller, ptr); + mpp_mem_srv_dump(srv, caller); + show_mem((rk_u32 *)p, MEM_ALIGN); + mpp_abort(); + } + } + + p = (rk_u8 *)ptr + size; + for (i = 0; i < MEM_ALIGN; i++) { + if (p[i] != MEM_TAIL_MASK) { + mpp_err("%s checking ptr %p tail room found error!\n", caller, ptr); + mpp_mem_srv_dump(srv, caller); + show_mem((rk_u32 *)p, MEM_ALIGN); + mpp_abort(); + } + } +} + +static void check_node(MppMemSrv *srv, MppMemNode *node, const char *caller) +{ + if ((srv->debug & MEM_EXT_ROOM) == 0) + return ; + + check_mem(srv, node->ptr, node->size, caller); +} + +static rk_s32 check_poison(MppMemSrv *srv, MppMemNode *node) +{ + if ((srv->debug & MEM_POISON) == 0) + return 0; + + // check oldest memory and free it + rk_u8 *node_ptr = (rk_u8 *)node->ptr; + rk_s32 size = node->size; + rk_s32 i = 0; + rk_s32 start = -1; + rk_s32 end = -1; + + if (size >= 1024) + return 0; + + for (; i < size; i++) { + if (node_ptr[i] != MEM_CHECK_MARK) { + if (start < 0) { + start = i; + } + end = i + 1; + } + } + + if (start >= 0 || end >= 0) { + mpp_err_f("found memory %p size %d caller %s overwrite from %d to %d\n", + node_ptr, size, node->caller, start, end); + mpp_mem_srv_dump(srv, node->caller); + } + + return end - start; +} + +static void reset_node(MppMemSrv *srv, void *ptr, void *ret, size_t size, const char *caller) +{ + MppMemNode *node = srv->nodes; + rk_s32 i = 0; + + if (srv->debug & MEM_NODE_LOG) + mpp_log("mem cnt: %5d total %8d equ size %8d at %s\n", + srv->nodes_cnt, srv->total_size, size, __FUNCTION__); + + MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max); + + for (i = 0; i < srv->nodes_max; i++, node++) { + if (node->index >= 0 && node->ptr == ptr) { + srv->total_size += size; + srv->total_size -= node->size; + + node->ptr = ret; + node->size = size; + node->caller = caller; + + if (srv->debug & MEM_EXT_ROOM) + set_mem_ext_room(ret, size); + break; + } + } +} + +static void add_log(MppMemSrv *srv, MppMemOps ops, const char *caller, void *ptr, + void *ret, size_t size_0, size_t size_1) +{ + MppMemLog *log = &srv->logs[srv->log_idx]; + + if (srv->debug & MEM_RUNTIME_LOG) + mpp_log("%-7s ptr %010p %010p size %8u %8u at %s\n", + ops2str[ops], ptr, ret, size_0, size_1, caller); + + log->index = srv->log_index++; + log->ops = ops; + log->size_0 = size_0; + log->size_1 = size_1; + log->ptr = ptr; + log->ret = ret; + log->node = NULL; + log->caller = caller; + + srv->log_idx++; + if (srv->log_idx >= srv->log_max) + srv->log_idx = 0; + + if (srv->log_cnt < srv->log_max) + srv->log_cnt++; +} + +static void add_node(MppMemSrv *srv, void *ptr, size_t size, const char *caller) +{ + MppMemNode *node; + rk_s32 i; + + if (srv->debug & MEM_NODE_LOG) + mpp_log("mem cnt: %5d total %8d inc size %8d at %s\n", + srv->nodes_cnt, srv->total_size, size, caller); + + if (srv->nodes_cnt >= srv->nodes_max) { + mpp_err("******************************************************\n"); + mpp_err("* Reach max limit of mpp_mem counter %5d *\n", srv->nodes_max); + mpp_err("* Increase limit by setup env mpp_mem_node_max or *\n"); + mpp_err("* recompile mpp with larger macro MEM_NODE_MAX value *\n"); + mpp_err("******************************************************\n"); + mpp_abort(); + } + + node = srv->nodes; + for (i = 0; i < srv->nodes_max; i++, node++) { + if (node->index < 0) { + node->index = srv->nodes_idx++; + node->size = size; + node->ptr = ptr; + node->caller = caller; + + // NOTE: reset node index on revert + if (srv->nodes_idx < 0) + srv->nodes_idx = 0; + + srv->nodes_cnt++; + srv->total_size += size; + if (srv->total_size > srv->total_max) + srv->total_max = srv->total_size; + break; + } + } +} + +static void del_node(MppMemSrv *srv, void *ptr, size_t *size, const char *caller) +{ + MppMemNode *node = srv->nodes; + rk_s32 i; + + MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max); + + for (i = 0; i < srv->nodes_max; i++, node++) { + if (node->index >= 0 && node->ptr == ptr) { + *size = node->size; + node->index = ~node->index; + srv->nodes_cnt--; + srv->total_size -= node->size; + + if (srv->debug & MEM_NODE_LOG) + mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n", + srv->nodes_cnt, srv->total_size, node->size, caller); + return ; + } + } + + mpp_err("%s fail to find node with ptr %p\n", caller, ptr); + mpp_abort(); + return ; +} + +static void *delay_del_node(MppMemSrv *srv, void *ptr, size_t *size, const char *caller) +{ + MppMemNode *node = srv->nodes; + MppMemNode *free_node = NULL; + void *ret = NULL; + rk_s32 i = 0; + + // clear output first + *size = 0; + + // find the node to save + MPP_MEM_ASSERT(srv, srv->nodes_cnt <= srv->nodes_max); + for (i = 0; i < srv->nodes_max; i++, node++) { + if (node->index >= 0 && node->ptr == ptr) { + check_node(srv, node, caller); + break; + } + } + + MPP_MEM_ASSERT(srv, i < srv->nodes_max); + if (srv->debug & MEM_NODE_LOG) + mpp_log("mem cnt: %5d total %8d dec size %8d at %s\n", + srv->nodes_cnt, srv->total_size, node->size, caller); + + MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max); + + if (srv->frees_cnt) { + MppMemNode *tmp = srv->frees; + + // NODE: check all data here + for (i = 0; i < srv->frees_max; i++, tmp++) { + if (tmp->index >= 0) { + check_node(srv, tmp, caller); + check_poison(srv, tmp); + } + } + } + + if (srv->frees_cnt >= srv->frees_max) { + // free list full start del + rk_s32 frees_last = srv->frees_idx - srv->frees_cnt; + + if (frees_last < 0) + frees_last += srv->frees_max; + + free_node = &srv->frees[frees_last]; + + if (free_node->index >= 0) { + check_node(srv, free_node, caller); + check_poison(srv, free_node); + ret = free_node->ptr; + *size = free_node->size; + free_node->index = ~free_node->index; + srv->frees_cnt--; + } + } + + MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max); + + // free list is NOT full just store + free_node = &srv->frees[srv->frees_idx]; + srv->frees_idx++; + if (srv->frees_idx >= srv->frees_max) + srv->frees_idx = 0; + if (srv->frees_cnt < srv->frees_max) + srv->frees_cnt++; + + MPP_MEM_ASSERT(srv, srv->frees_cnt <= srv->frees_max); + + memcpy(&srv->frees[srv->frees_idx], node, sizeof(*node)); + + if ((srv->debug & MEM_POISON) && (node->size < 1024)) + memset(node->ptr, MEM_CHECK_MARK, node->size); + + node->index = ~node->index; + srv->total_size -= node->size; + srv->nodes_cnt--; + + return ret; +} + +static void mpp_mem_srv_init() +{ + MppMemSrv *srv = srv_mem; + + if (srv) + return; + + os_malloc((void **)&srv, MEM_ALIGN, sizeof(*srv)); + mpp_assert(srv); + srv_mem = srv; + + memset(srv, 0, sizeof(*srv)); + + mpp_env_get_u32("mpp_mem_debug", &srv->debug, 0); + + srv->nodes_max = MEM_NODE_MAX; + srv->frees_max = MEM_FREE_MAX; + srv->log_max = MEM_LOG_MAX; + + { + // init mutex lock + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&srv->lock, &attr); + pthread_mutexattr_destroy(&attr); + } + + pthread_mutex_lock(&srv->lock); + + // add more flag if debug enabled + if (srv->debug) + srv->debug |= MEM_DEBUG_EN; + + if (srv->debug & MEM_DEBUG_EN) { + size_t size; + + mpp_env_get_u32("mpp_mem_node_max", (rk_u32 *)&srv->nodes_max, MEM_NODE_MAX); + + mpp_log_f("mpp_mem_debug enabled %x max node %d\n", + srv->debug, srv->nodes_max); + + size = srv->nodes_max * sizeof(MppMemNode); + os_malloc((void **)&srv->nodes, MEM_ALIGN, size); + mpp_assert(srv->nodes); + memset(srv->nodes, 0xff, size); + add_node(srv, srv->nodes, size, __FUNCTION__); + + size = srv->frees_max * sizeof(MppMemNode); + os_malloc((void **)&srv->frees, MEM_ALIGN, size); + mpp_assert(srv->frees); + memset(srv->frees, 0xff, size); + add_node(srv, srv->frees, size, __FUNCTION__); + + size = srv->log_max * sizeof(MppMemLog); + os_malloc((void **)&srv->logs, MEM_ALIGN, size); + mpp_assert(srv->logs); + add_node(srv, srv->logs, size, __FUNCTION__); + + add_node(srv, srv, sizeof(MppMemSrv), __FUNCTION__); + } + + pthread_mutex_unlock(&srv->lock); +} + +static void mpp_mem_srv_deinit() +{ + MppMemSrv *srv = get_srv_mem_f(); + + if (!srv) + return; + + if (srv->debug & MEM_DEBUG_EN) { + MppMemNode *node = srv->nodes; + size_t size = 0; + rk_s32 i = 0; + + pthread_mutex_lock(&srv->lock); + + // delete self node first + del_node(srv, srv, &size, __FUNCTION__); + del_node(srv, srv->nodes, &size, __FUNCTION__); + del_node(srv, srv->frees, &size, __FUNCTION__); + del_node(srv, srv->logs, &size, __FUNCTION__); + + // then check leak memory + if (srv->nodes_cnt) { + for (i = 0; i < srv->nodes_max; i++, node++) { + if (node->index >= 0) { + mpp_log("found idx %8d mem %10p size %d leaked from %s\n", + node->index, node->ptr, node->size, node->caller); + srv->nodes_cnt--; + add_log(srv, MEM_FREE, __FUNCTION__, node->ptr, NULL, + node->size, 0); + } + } + + mpp_assert(srv->nodes_cnt == 0); + } + + // finally release all delay free memory + if (srv->frees_cnt) { + node = srv->frees; + + for (i = 0; i < srv->frees_max; i++, node++) { + if (node->index >= 0) { + os_free((rk_u8 *)node->ptr - MEM_HEAD_ROOM(srv->debug)); + node->index = ~node->index; + srv->frees_cnt--; + add_log(srv, MEM_FREE_DELAY, __FUNCTION__, node->ptr, NULL, + node->size, 0); + } + } + + mpp_assert(srv->frees_cnt == 0); + } + + os_free(srv->nodes); + os_free(srv->frees); + os_free(srv->logs); + + pthread_mutex_unlock(&srv->lock); + } + + pthread_mutex_destroy(&srv->lock); + + os_free(srv); + srv_mem = NULL; +} + +MPP_SINGLETON(MPP_SGLN_OS_MEM, mpp_mem, mpp_mem_srv_init, mpp_mem_srv_deinit) + +void *mpp_osal_malloc(const char *caller, size_t size) +{ + MppMemSrv *srv = get_srv_mem(caller); + rk_u32 debug = srv->debug; + size_t size_align = MEM_ALIGNED(size); + size_t size_real = ((debug & MEM_EXT_ROOM) != 0) ? (size_align + 2 * MEM_ALIGN) : (size_align); + void *ptr; + + os_malloc(&ptr, MEM_ALIGN, size_real); + + if (debug) { + pthread_mutex_lock(&srv->lock); + + add_log(srv, MEM_MALLOC, caller, NULL, ptr, size, size_real); + + if (ptr) { + if (debug & MEM_EXT_ROOM) { + ptr = (rk_u8 *)ptr + MEM_ALIGN; + set_mem_ext_room(ptr, size); + } + + add_node(srv, ptr, size, caller); + } + + pthread_mutex_unlock(&srv->lock); + } + + return ptr; +} + +void *mpp_osal_calloc(const char *caller, size_t size) +{ + void *ptr = mpp_osal_malloc(caller, size); + + if (ptr) + memset(ptr, 0, size); + + return ptr; +} + +void *mpp_osal_realloc(const char *caller, void *ptr, size_t size) +{ + MppMemSrv *srv = get_srv_mem(caller); + rk_u32 debug = srv->debug; + size_t size_align; + size_t size_real; + void *ptr_real; + void *ret; + + if (!ptr) + return mpp_osal_malloc(caller, size); + + if (0 == size) { + mpp_err("warning: realloc %p to zero size\n", ptr); + return NULL; + } + + size_align = MEM_ALIGNED(size); + size_real = ((debug & MEM_EXT_ROOM) != 0) ? (size_align + 2 * MEM_ALIGN) : (size_align); + ptr_real = (rk_u8 *)ptr - MEM_HEAD_ROOM(debug); + + os_realloc(ptr_real, &ret, MEM_ALIGN, size_align); + + if (!ret) { + // if realloc fail the original buffer will be kept the same. + mpp_err("mpp_realloc ptr %p to size %d failed\n", ptr, size); + } else { + pthread_mutex_lock(&srv->lock); + + // if realloc success reset the node and record + if (debug) { + void *ret_ptr = ((debug & MEM_EXT_ROOM) != 0) ? + ((rk_u8 *)ret + MEM_ALIGN) : (ret); + + reset_node(srv, ptr, ret_ptr, size, caller); + add_log(srv, MEM_REALLOC, caller, ptr, ret_ptr, size, size_real); + ret = ret_ptr; + } + + pthread_mutex_unlock(&srv->lock); + } + + return ret; +} + +void mpp_osal_free(const char *caller, void *ptr) +{ + MppMemSrv *srv = get_srv_mem(caller); + size_t size = 0; + + if (!ptr) + return; + + if (!srv || !srv->debug) { + os_free(ptr); + return ; + } + + pthread_mutex_lock(&srv->lock); + + if (srv->debug & MEM_POISON) { + // NODE: keep this node and delete delay node + void *ret = delay_del_node(srv, ptr, &size, caller); + if (ret) + os_free((rk_u8 *)ret - MEM_ALIGN); + + add_log(srv, MEM_FREE_DELAY, caller, ptr, ret, size, 0); + } else { + void *ptr_real = (rk_u8 *)ptr - MEM_HEAD_ROOM(srv->debug); + + // NODE: delete node and return size here + del_node(srv, ptr, &size, caller); + check_mem(srv, ptr, size, caller); + os_free(ptr_real); + add_log(srv, MEM_FREE, caller, ptr, ptr_real, size, 0); + } + + pthread_mutex_unlock(&srv->lock); +} + +/* dump memory status */ +void mpp_show_mem_status() +{ + MppMemSrv *srv = get_srv_mem_f(); + + if (srv) { + pthread_mutex_lock(&srv->lock); + if (srv->debug & MEM_DEBUG_EN) + mpp_mem_srv_dump(srv, __FUNCTION__); + pthread_mutex_unlock(&srv->lock); + } +} + +rk_u32 mpp_mem_total_now() +{ + MppMemSrv *srv = get_srv_mem_f(); + rk_u32 total_now = 0; + + if (srv) { + pthread_mutex_lock(&srv->lock); + total_now = srv->total_size; + pthread_mutex_unlock(&srv->lock); + } + + return total_now; +} + +rk_u32 mpp_mem_total_max() +{ + MppMemSrv *srv = get_srv_mem_f(); + rk_u32 total_max = 0; + + if (srv) { + pthread_mutex_lock(&srv->lock); + total_max = srv->total_max; + pthread_mutex_unlock(&srv->lock); + } + + return total_max; +} diff --git a/osal/mpp_mem.cpp b/osal/mpp_mem.cpp deleted file mode 100644 index ed05b2acd..000000000 --- a/osal/mpp_mem.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_mem" - -#include - -#include "rk_type.h" -#include "mpp_err.h" - -#include "mpp_log.h" -#include "mpp_env.h" -#include "mpp_mem.h" -#include "mpp_list.h" -#include "mpp_common.h" - -#include "os_mem.h" - -// export configure for script detection -#define CONFIG_OSAL_MEM_LIST "osal_mem_list" -#define CONFIG_OSAL_MEM_STUFF "osal_mem_stuff" - - -// default memory align size is set to 32 -#define RK_OSAL_MEM_ALIGN 32 - -// osal_mem_flag bit mask -#define OSAL_MEM_LIST_EN (0x00000001) -#define OSAL_MEM_STUFF_EN (0x00000002) - -static RK_S32 osal_mem_flag = -1; -static struct list_head mem_list; - -struct mem_node { - struct list_head list; - void *ptr; - size_t size; - - /* memory node extra information */ - char tag[MPP_TAG_SIZE]; -}; - -static void get_osal_mem_flag() -{ - if (osal_mem_flag < 0) { - RK_U32 val; - osal_mem_flag = 0; - mpp_env_get_u32(CONFIG_OSAL_MEM_LIST, &val, 0); - if (val) { - osal_mem_flag |= OSAL_MEM_LIST_EN; - } - mpp_env_get_u32(CONFIG_OSAL_MEM_STUFF, &val, 0); - if (val) { - osal_mem_flag |= OSAL_MEM_STUFF_EN; - } - INIT_LIST_HEAD(&mem_list); - } -} - -void *mpp_osal_malloc(const char *tag, size_t size) -{ - void *ptr; - get_osal_mem_flag(); - - if (MPP_OK == os_malloc(&ptr, RK_OSAL_MEM_ALIGN, size)) { - if (osal_mem_flag & OSAL_MEM_LIST_EN) { - struct mem_node *node = (struct mem_node *)malloc(sizeof(struct mem_node)); - INIT_LIST_HEAD(&node->list); - list_add_tail(&node->list, &mem_list); - node->ptr = ptr; - node->size = size; - strncpy(node->tag, tag, sizeof(node->tag)); - } - - return ptr; - } else - return NULL; -} - -void *mpp_osal_calloc(const char *tag, size_t size) -{ - void *ptr = mpp_osal_malloc(tag, size); - if (ptr) - memset(ptr, 0, size); - return ptr; -} - -void *mpp_osal_realloc(const char *tag, void *ptr, size_t size) -{ - void *ret; - - if (NULL == ptr) - return mpp_osal_malloc(tag, size); - - if (0 == size) - return NULL; - - get_osal_mem_flag(); - - if (osal_mem_flag & OSAL_MEM_LIST_EN) { - struct mem_node *pos, *n; - ret = NULL; - list_for_each_entry_safe(pos, n, &mem_list, struct mem_node, list) { - if (ptr == pos->ptr) { - if (MPP_OK == os_realloc(ptr, &pos->ptr, RK_OSAL_MEM_ALIGN, size)) { - pos->size = size; - strncpy(pos->tag, tag, sizeof(pos->tag)); - ret = pos->ptr; - } else { - list_del_init(&pos->list); - free(pos); - } - break; - } - } - } else { - os_realloc(ptr, &ret, RK_OSAL_MEM_ALIGN, size); - } - - if (NULL == ret) - mpp_err("mpp_realloc ptr 0x%p to size %d failed\n", ptr, size); - - return ret; -} - -void mpp_osal_free(void *ptr) -{ - if (NULL == ptr) - return; - - get_osal_mem_flag(); - - if (osal_mem_flag & OSAL_MEM_LIST_EN) { - struct mem_node *pos, *n; - list_for_each_entry_safe(pos, n, &mem_list, struct mem_node, list) { - if (ptr == pos->ptr) { - list_del_init(&pos->list); - free(pos); - break; - } - } - } - - os_free(ptr); -} - -/* - * dump memory status - * this function need MODULE_TAG statistic information - */ -void mpp_show_mem_status() -{ - // TODO: add memory dump implement -} - diff --git a/osal/mpp_mem_pool.c b/osal/mpp_mem_pool.c new file mode 100644 index 000000000..015675677 --- /dev/null +++ b/osal/mpp_mem_pool.c @@ -0,0 +1,303 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_mem_pool" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_list.h" +#include "mpp_debug.h" +#include "mpp_singleton.h" + +#include "mpp_mem_pool.h" + +#define MEM_POOL_DBG_FLOW (0x00000001) +#define MEM_POOL_DBG_EXIT (0x00000002) + +#define mem_pool_dbg(flag, fmt, ...) mpp_dbg(mpp_mem_pool_debug, flag, fmt, ## __VA_ARGS__) +#define mem_pool_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_mem_pool_debug, flag, fmt, ## __VA_ARGS__) + +#define mem_pool_dbg_flow(fmt, ...) mem_pool_dbg(MEM_POOL_DBG_FLOW, fmt, ## __VA_ARGS__) +#define mem_pool_dbg_exit(fmt, ...) mem_pool_dbg(MEM_POOL_DBG_EXIT, fmt, ## __VA_ARGS__) + +#define get_srv_mem_pool(caller) \ + ({ \ + MppMemPoolSrv *__tmp; \ + if (!srv_mem_pool) { \ + mem_pool_srv_init(); \ + } \ + if (srv_mem_pool) { \ + __tmp = srv_mem_pool; \ + } else { \ + mpp_err("mpp mem pool srv not init at %s : %s\n", __FUNCTION__, caller); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +static rk_u32 mpp_mem_pool_debug = 0; + +/* + * Aligning MppMemPoolNode to 8-byte + * Avoiding alignment traps caused by compiler optimizations + */ +typedef struct MppMemPoolNode_t { + void *check; + struct list_head list; + void *ptr; + rk_u64 size; +} MppMemPoolNode; + +typedef struct MppMemPoolImpl_t { + void *check; + const char *name; + size_t size; + pthread_mutex_t lock; + struct list_head service_link; + + struct list_head used; + struct list_head unused; + rk_s32 used_count; + rk_s32 unused_count; + + /* extra flag for C++ static destruction order error */ + rk_s32 finalized; +} MppMemPoolImpl; + +typedef struct MppMemPoolService_t { + struct list_head list; + pthread_mutex_t lock; +} MppMemPoolSrv; + +static MppMemPoolSrv *srv_mem_pool = NULL; + +static void mem_pool_srv_init() +{ + MppMemPoolSrv *srv = srv_mem_pool; + + mpp_env_get_u32("mpp_mem_pool_debug", &mpp_mem_pool_debug, 0); + + if (srv) + return; + + srv = mpp_malloc(MppMemPoolSrv, 1); + if (!srv) { + mpp_err_f("failed to allocate pool service\n"); + return; + } + + srv_mem_pool = srv; + + { + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&srv->lock, &attr); + pthread_mutexattr_destroy(&attr); + } + + INIT_LIST_HEAD(&srv->list); +} + +static void put_pool(MppMemPoolSrv *srv, MppMemPoolImpl *impl, const char *caller) +{ + MppMemPoolNode *node, *m; + + if (impl != impl->check) { + mpp_err_f("invalid mem impl %p check %p at %s\n", impl, impl->check, caller); + return; + } + + if (impl->finalized) + return; + + pthread_mutex_lock(&impl->lock); + + if (!list_empty(&impl->unused)) { + list_for_each_entry_safe(node, m, &impl->unused, MppMemPoolNode, list) { + MPP_FREE(node); + impl->unused_count--; + } + } + + if (!list_empty(&impl->used)) { + mpp_err_f("pool %-16s found %d used buffer size %4d at %s\n", + impl->name, impl->used_count, impl->size, caller); + + list_for_each_entry_safe(node, m, &impl->used, MppMemPoolNode, list) { + MPP_FREE(node); + impl->used_count--; + } + } + + if (impl->used_count || impl->unused_count) + mpp_err_f("pool %-16s size %4d found leaked buffer used:unused [%d:%d] at %s\n", + impl->name, impl->size, impl->used_count, impl->unused_count, caller); + + pthread_mutex_unlock(&impl->lock); + + if (srv) { + pthread_mutex_lock(&srv->lock); + list_del_init(&impl->service_link); + pthread_mutex_unlock(&srv->lock); + } + + impl->finalized = 1; + mpp_free(impl); +} + +static void mem_pool_srv_deinit() +{ + MppMemPoolSrv *srv = srv_mem_pool; + + if (!srv) + return; + + if (!list_empty(&srv->list)) { + MppMemPoolImpl *pos, *n; + + list_for_each_entry_safe(pos, n, &srv->list, MppMemPoolImpl, service_link) { + mem_pool_dbg_exit("pool %-16s size %4d leaked\n", pos->name, pos->size); + put_pool(srv, pos, __FUNCTION__); + } + } + + pthread_mutex_destroy(&srv->lock); + + mpp_free(srv); + srv_mem_pool = NULL; +} + +MppMemPool mpp_mem_pool_init(const char *name, size_t size, const char *caller) +{ + MppMemPoolSrv *srv = get_srv_mem_pool(caller); + MppMemPoolImpl *pool; + + if (!srv) + return NULL; + + pool = mpp_calloc(MppMemPoolImpl, 1); + if (!pool) + return NULL; + + { + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&pool->lock, &attr); + pthread_mutexattr_destroy(&attr); + } + + pool->check = pool; + pool->name = name; + pool->size = size; + pool->used_count = 0; + pool->unused_count = 0; + pool->finalized = 0; + + INIT_LIST_HEAD(&pool->used); + INIT_LIST_HEAD(&pool->unused); + INIT_LIST_HEAD(&pool->service_link); + + pthread_mutex_lock(&srv->lock); + list_add_tail(&pool->service_link, &srv->list); + pthread_mutex_unlock(&srv->lock); + + mem_pool_dbg_flow("pool %-16s size %4d init at %s\n", pool->name, size, caller); + + return pool; +} + +void mpp_mem_pool_deinit(MppMemPool pool, const char *caller) +{ + MppMemPoolSrv *srv = get_srv_mem_pool(caller); + MppMemPoolImpl *impl = (MppMemPoolImpl *)pool; + + mem_pool_dbg_flow("pool %-16s size %4d deinit at %s\n", + impl->name, impl->size, caller); + + put_pool(srv, impl, caller); +} + +void *mpp_mem_pool_get(MppMemPool pool, const char *caller) +{ + MppMemPoolImpl *impl = (MppMemPoolImpl *)pool; + MppMemPoolNode *node = NULL; + void* ptr = NULL; + + pthread_mutex_lock(&impl->lock); + + mem_pool_dbg_flow("pool %-16s size %4d get used:unused [%d:%d] at %s\n", + impl->name, impl->size, impl->used_count, impl->unused_count, caller); + + if (!list_empty(&impl->unused)) { + node = list_first_entry(&impl->unused, MppMemPoolNode, list); + if (node) { + list_del_init(&node->list); + list_add_tail(&node->list, &impl->used); + impl->unused_count--; + impl->used_count++; + ptr = node->ptr; + node->check = node; + goto DONE; + } + } + + node = mpp_malloc_size(MppMemPoolNode, sizeof(MppMemPoolNode) + impl->size); + if (!node) { + mpp_err_f("failed to create node from size %4d pool\n", impl->size); + goto DONE; + } + + node->check = node; + node->ptr = (void *)(node + 1); + node->size = impl->size; + INIT_LIST_HEAD(&node->list); + list_add_tail(&node->list, &impl->used); + impl->used_count++; + ptr = node->ptr; + +DONE: + pthread_mutex_unlock(&impl->lock); + if (node) + memset(node->ptr, 0 , node->size); + return ptr; +} + +void mpp_mem_pool_put(MppMemPool pool, void *p, const char *caller) +{ + MppMemPoolImpl *impl = (MppMemPoolImpl *)pool; + MppMemPoolNode *node = (MppMemPoolNode *)((rk_u8 *)p - sizeof(MppMemPoolNode)); + + if (impl != impl->check) { + mpp_err_f("invalid mem pool %p check %p\n", impl, impl->check); + return ; + } + + if (node != node->check) { + mpp_err_f("invalid mem pool ptr %p node %p check %p\n", + p, node, node->check); + return ; + } + + pthread_mutex_lock(&impl->lock); + + mem_pool_dbg_flow("pool %-16s size %4d put used:unused [%d:%d] at %s\n", + impl->name, impl->size, impl->used_count, impl->unused_count, caller); + + list_del_init(&node->list); + list_add(&node->list, &impl->unused); + impl->used_count--; + impl->unused_count++; + node->check = NULL; + + pthread_mutex_unlock(&impl->lock); +} + +MPP_SINGLETON(MPP_SGLN_MEM_POOL, mpp_mem_pool, mem_pool_srv_init, mem_pool_srv_deinit) diff --git a/osal/mpp_platform.c b/osal/mpp_platform.c new file mode 100644 index 000000000..a7c2c5f65 --- /dev/null +++ b/osal/mpp_platform.c @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_platform" + +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_platform.h" +#include "mpp_service.h" +#include "mpp_singleton.h" + +#define get_srv_platform() \ + ({ \ + MppPlatformService *__tmp; \ + if (!srv_platform) { \ + mpp_plat_srv_init(); \ + } \ + if (srv_platform) { \ + __tmp = srv_platform; \ + } else { \ + mpp_err("mpp platform srv not init at %s\n", __FUNCTION__); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +typedef struct MppPlatformService_t { + MppIoctlVersion ioctl_version; + MppKernelVersion kernel_version; + rk_u32 vcodec_type; + rk_u32 hw_ids[32]; + MppServiceCmdCap mpp_service_cmd_cap; + const MppSocInfo *soc_info; + const char *soc_name; +} MppPlatformService; + +static MppPlatformService *srv_platform = NULL; + +static MppKernelVersion check_kernel_version(void) +{ + static const char *kernel_version_path = "/proc/version"; + MppKernelVersion version = KERNEL_UNKNOWN; + FILE *fp = NULL; + char buf[32]; + + if (access(kernel_version_path, F_OK | R_OK)) + return version; + + fp = fopen(kernel_version_path, "rb"); + if (fp) { + size_t len = fread(buf, 1, sizeof(buf) - 1, fp); + char *pos = NULL; + + buf[len] = '\0'; + pos = strstr(buf, "Linux version "); + if (pos) { + rk_s32 major = 0; + rk_s32 minor = 0; + rk_s32 last = 0; + rk_s32 count = 0; + + pos += 14; + count = sscanf(pos, "%d.%d.%d ", &major, &minor, &last); + if (count >= 2 && major > 0 && minor > 0) { + switch (major) { + case 3: { + version = KERNEL_3_10; + } break; + case 4: { + version = KERNEL_4_4; + if (minor >= 19) + version = KERNEL_4_19; + } break; + case 5: { + version = KERNEL_5_10; + } break; + case 6: { + version = KERNEL_6_1; + } break; + default: break; + } + } + } + fclose(fp); + } + return version; +} + +static void mpp_plat_srv_init() +{ + /* judge vdpu support version */ + MppPlatformService *srv = srv_platform; + MppServiceCmdCap *cap; + + if (srv) + return; + + srv = mpp_calloc(MppPlatformService, 1); + if (!srv) { + mpp_err_f("failed to allocate platform service\n"); + return; + } + + srv_platform = srv; + + /* default value */ + cap = &srv->mpp_service_cmd_cap; + cap->support_cmd = 0; + cap->query_cmd = MPP_CMD_QUERY_BASE + 1; + cap->init_cmd = MPP_CMD_INIT_BASE + 1; + cap->send_cmd = MPP_CMD_SEND_BASE + 1; + cap->poll_cmd = MPP_CMD_POLL_BASE + 1; + cap->ctrl_cmd = MPP_CMD_CONTROL_BASE + 0; + + mpp_env_get_u32("mpp_debug", &mpp_debug, 0); + + /* read soc name */ + srv->soc_name = mpp_get_soc_name(); + srv->soc_info = mpp_get_soc_info(); + + if (srv->soc_info->soc_type == ROCKCHIP_SOC_AUTO) + mpp_log("can not found match soc name: %s\n", srv->soc_name); + + srv->ioctl_version = IOCTL_VCODEC_SERVICE; + if (mpp_get_mpp_service_name()) { + srv->ioctl_version = IOCTL_MPP_SERVICE_V1; + check_mpp_service_cap(&srv->vcodec_type, srv->hw_ids, cap); + sys_dbg_platform("vcodec_type from kernel 0x%08x, vs from soc info 0x%08x\n", + srv->vcodec_type, srv->soc_info->vcodec_type); + } + srv->kernel_version = check_kernel_version(); + if (!srv->vcodec_type) { + srv->vcodec_type = srv->soc_info->vcodec_type; + } else { + // Compare kernel result with soc infomation. + rk_u32 diff_type = srv->vcodec_type ^ srv->soc_info->vcodec_type; + rk_u32 i; + + for (i = 0; i <= VPU_CLIENT_VEPU22; i++) { + rk_u32 mask = 1 << i; + + if (diff_type & mask) { + MppClientType client_type = (MppClientType) i; + + sys_dbg_platform("confliction found at client_type %d\n", client_type); + + if (srv->soc_info->vcodec_type & mask) { + mpp_err("client %d driver is not ready!\n", client_type); + } else { + sys_dbg_platform("client %d driver is ready but not declared!\n", client_type); + if (client_type == VPU_CLIENT_VDPU2_PP) + srv->vcodec_type &= ~mask; + } + } + } + + sys_dbg_platform("vcode_type 0x%08x\n", srv->vcodec_type); + } + + return; +} + +static void mpp_plat_srv_deinit() +{ + MPP_FREE(srv_platform); +} + +MppIoctlVersion mpp_get_ioctl_version(void) +{ + MppPlatformService *srv = get_srv_platform(); + MppIoctlVersion ver = IOCTL_MPP_SERVICE_V1; + + if (srv) + ver = srv->ioctl_version; + + return ver; +} + +MppKernelVersion mpp_get_kernel_version(void) +{ + MppPlatformService *srv = get_srv_platform(); + MppKernelVersion ver = KERNEL_UNKNOWN; + + if (srv) + ver = srv->kernel_version; + + return ver; +} + +rk_u32 mpp_get_2d_hw_flag(void) +{ + rk_u32 flag = 0; + + if (!access("/dev/iep", F_OK)) + flag |= HAVE_IEP; + + return flag; +} + +const MppServiceCmdCap *mpp_get_mpp_service_cmd_cap(void) +{ + MppPlatformService *srv = get_srv_platform(); + const MppServiceCmdCap *cap = NULL; + + if (srv) + cap = &srv->mpp_service_cmd_cap; + + return cap; +} + +rk_u32 mpp_get_client_hw_id(rk_s32 client_type) +{ + MppPlatformService *srv = get_srv_platform(); + rk_u32 hw_id = 0; + + if (srv && srv->vcodec_type & (1 << client_type)) + hw_id = srv->hw_ids[client_type]; + + return hw_id; +} + +rk_u32 mpp_get_vcodec_type(void) +{ + MppPlatformService *srv = get_srv_platform(); + static rk_u32 vcodec_type = 0; + + if (vcodec_type) + return vcodec_type; + + if (srv) + vcodec_type = srv->vcodec_type; + + return vcodec_type; +} + +MPP_SINGLETON(MPP_SGLN_PLATFORM, mpp_platform, mpp_plat_srv_init, mpp_plat_srv_deinit) diff --git a/osal/mpp_queue.c b/osal/mpp_queue.c new file mode 100644 index 000000000..162a176fb --- /dev/null +++ b/osal/mpp_queue.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#include "mpp_mem.h" +#include "mpp_queue.h" + +MppQueue* mpp_queue_create(node_destructor func) +{ + MppQueue *queue = mpp_malloc(MppQueue, 1); + + queue->list = mpp_list_create(func); + sem_init(&queue->queue_pending, 0, 0); + queue->flush_flag = 0; + + return queue; +} + +void mpp_queue_destroy(MppQueue *queue) +{ + mpp_list_destroy(queue->list); + mpp_free(queue); +} + +rk_s32 mpp_queue_push(MppQueue *queue, void *data, rk_s32 size) +{ + rk_s32 ret = rk_ok; + + ret = mpp_list_add_at_tail(queue->list, data, size); + queue->flush_flag = 0; + sem_post(&queue->queue_pending); + + return ret; +} + +rk_s32 mpp_queue_pull(MppQueue *queue, void *data, rk_s32 size) +{ + rk_s32 ret = rk_ok; + + if (!queue->flush_flag) + sem_wait(&queue->queue_pending); + + mpp_mutex_cond_lock(&queue->list->cond_lock); + if (!mpp_list_size(queue->list)) { + mpp_mutex_cond_unlock(&queue->list->cond_lock); + return ret; + } + + ret = mpp_list_del_at_head(queue->list, data, size); + mpp_mutex_cond_unlock(&queue->list->cond_lock); + + return ret; +} + +rk_s32 mpp_queue_flush(MppQueue *queue) +{ + if (queue->flush_flag) + return 0; + + queue->flush_flag = 1; + sem_post(&queue->queue_pending); + mpp_list_flush(queue->list); + + return 0; +} diff --git a/osal/mpp_ring.c b/osal/mpp_ring.c new file mode 100644 index 000000000..c2a08de44 --- /dev/null +++ b/osal/mpp_ring.c @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_ring" + +#include +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_mem_pool.h" +#include "mpp_singleton.h" + +#include "mpp_ring.h" + +#define RING_DBG_FLOW (0x00000001) +#define RING_DBG_INIT (0x00000002) + +#define ring_dbg(flag, fmt, ...) mpp_dbg(mpp_ring_debug, flag, fmt, ## __VA_ARGS__) +#define ring_dbg_f(flag, fmt, ...) mpp_dbg_f(mpp_ring_debug, flag, fmt, ## __VA_ARGS__) + +#define ring_dbg_flow(fmt, ...) ring_dbg(RING_DBG_FLOW, fmt, ## __VA_ARGS__) +#define ring_dbg_init(fmt, ...) ring_dbg(RING_DBG_INIT, fmt, ## __VA_ARGS__) + +typedef struct MppRingImpl_t { + void *ptr; + rk_s32 fd; + rk_s32 size; + rk_s32 size_align; +} MppRingImpl; + +static const char *module_name = MODULE_TAG; +static MppMemPool pool_ring = NULL; +static rk_s32 page_sz = 0; +static rk_u32 mpp_ring_debug = 0; + +#ifdef __BIONIC__ + +/* Android ndk before API 29 */ +#include + +#ifndef MFD_CLOEXEC +#define MFD_CLOEXEC 0x0001U +#endif + +#ifndef __NR_memfd_create +#if defined(__aarch64__) && !defined(__ILP32__) +# define __NR_memfd_create 279 /* 64-bit ARM64 */ +#elif defined(__arm__) || defined(__aarch64__) && defined(__ILP32__) +# define __NR_memfd_create 356 /* 32-bit ARM / compat */ +#else +#error "please define __NR_memfd_create for your arch" +#endif +#endif + +static inline int memfd_create_impl(const char *name, unsigned int flags) +{ + return syscall(__NR_memfd_create, name, flags); +} + +#define memfd_create memfd_create_impl + +#endif + +static void *mmap_twice(RK_S32 fd, RK_S32 n) +{ + char *whole; + char *base; + char *base2; + + whole = mmap(NULL, 2 * n, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + if (whole == MAP_FAILED) { + mpp_loge("whole mmap size %d failed %s\n", 2 * n, strerror(errno)); + return NULL; + } + + base = mmap(whole, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); + if (base == MAP_FAILED) { + mpp_loge("first segment mmap size %d failed %s\n", n, strerror(errno)); + munmap(whole, 2 * n); + return NULL; + } + + base2 = mmap(whole + n, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); + if (base2 == MAP_FAILED) { + munmap(whole, 2 * n); + mpp_loge("second segment mmap size %d failed %s\n", n, strerror(errno)); + return NULL; + } + + ring_dbg_flow("mmap twice fd %d size %d whole %p base %p:%p\n", + fd, n, whole, base, base2); + + return whole; +} + +static void munmap_twice(void *ptr, rk_s32 n) +{ + if (ptr) { + ring_dbg_flow("mummap twice size %d ptr %p:%p\n", n, ptr, (char *)ptr + n); + munmap(ptr, 2 * n); + } +} + +static void mpp_ring_srv_init() +{ + if (pool_ring) + return; + + mpp_env_get_u32("mpp_ring_debug", &mpp_ring_debug, 0); + + page_sz = sysconf(_SC_PAGESIZE); + pool_ring = mpp_mem_pool_init_f(MODULE_TAG, sizeof(MppRingImpl)); + + ring_dbg_init("page size %d\n", page_sz); +} + +static void mpp_ring_srv_deinit() +{ + if (pool_ring) { + mpp_mem_pool_deinit_f(pool_ring); + pool_ring = NULL; + } +} + +MPP_SINGLETON(MPP_SGLN_RING, mpp_ring, mpp_ring_srv_init, mpp_ring_srv_deinit) + +rk_s32 mpp_ring_get(MppRing *ring, rk_s32 size, const char *name) +{ + MppRingImpl *impl = NULL; + void *ptr = NULL; + rk_s32 fd = -1; + rk_s32 size_align; + + mpp_env_get_u32("mpp_ring_debug", &mpp_ring_debug, 0); + + if (NULL == ring || size <= 0) { + mpp_loge_f("invalid input ring %p size %d\n", ring, size); + return rk_nok; + } + + *ring = NULL; + + if (NULL == name) + name = module_name; + + size_align = MPP_ALIGN(size, page_sz); + + do { + fd = memfd_create(name, MFD_CLOEXEC); + if (fd < 0) { + mpp_loge_f("failed to create memfd ret %d %s\n", fd, strerror(errno)); + break; + } + + if (ftruncate(fd, size_align) < 0) { + mpp_loge_f("failed to truncate memfd ret %d %s\n", fd, strerror(errno)); + break; + } + + ptr = mmap_twice(fd, size_align); + if (ptr == NULL) + break; + + impl = (MppRingImpl*)mpp_mem_pool_get_f(pool_ring); + if (NULL == impl) { + mpp_loge_f("failed to get ring impl from pool\n"); + break; + } + + impl->ptr = ptr; + impl->fd = fd; + impl->size = size; + impl->size_align = size_align; + *ring = impl; + + ring_dbg_flow("mpp_ring_get size %d -> aligned %d fd %d ptr %p\n", + size, size_align, fd, ptr); + + return rk_ok; + } while (0); + + munmap_twice(ptr, size_align); + + if (fd >= 0) + close(fd); + + return rk_nok; +} + +rk_s32 mpp_ring_put(MppRing ring) +{ + MppRingImpl *impl = (MppRingImpl *)ring; + + if (NULL == impl) + return rk_nok; + + ring_dbg_flow("mpp_ring_put aligned %d fd %d ptr %p\n", + impl->size_align, impl->fd, impl->ptr); + + munmap_twice(impl->ptr, impl->size_align); + + if (impl->fd >= 0) + close(impl->fd); + + mpp_mem_pool_put_f(pool_ring, impl); + + return rk_ok; +} + +void *mpp_ring_get_ptr(MppRing ring) +{ + MppRingImpl *impl = (MppRingImpl *)ring; + + return (impl != NULL) ? impl->ptr : NULL; +} + +void *mpp_ring_resize(MppRing ring, rk_s32 new_size) +{ + MppRingImpl *impl = (MppRingImpl *)ring; + rk_s32 new_aligned; + void *new_ptr; + + if (!impl || new_size <= 0) + return NULL; + + new_aligned = MPP_ALIGN(new_size, page_sz); + + if (new_aligned == impl->size) + return impl->ptr; + + munmap_twice(impl->ptr, impl->size); + + if (ftruncate(impl->fd, new_aligned) < 0) { + mpp_loge_f("resize ftruncate failed %s\n", strerror(errno)); + + /* rollback original buffer */ + impl->ptr = mmap_twice(impl->fd, impl->size); + return impl->ptr; + } + + new_ptr = mmap_twice(impl->fd, new_aligned); + if (new_ptr == MAP_FAILED) { + mpp_loge("resize mmap_twice failed %s\n", strerror(errno)); + + /* rollback original buffer */ + if (ftruncate(impl->fd, impl->size_align) < 0) { + mpp_loge("resize rollback ftruncate failed %s\n", strerror(errno)); + } else { + new_ptr = mmap_twice(impl->fd, impl->size); + new_aligned = impl->size; + } + } + + ring_dbg_flow("mpp_ring_reisze %p:%d -> %p:%d\n", + impl->ptr, impl->size, new_ptr, new_aligned); + + impl->ptr = new_ptr; + impl->size = new_size; + impl->size_align = new_aligned; + + return new_ptr; +} diff --git a/osal/mpp_runtime.c b/osal/mpp_runtime.c new file mode 100644 index 000000000..110c6d8a1 --- /dev/null +++ b/osal/mpp_runtime.c @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_rt" + +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "mpp_runtime.h" + +#define MAX_DTS_PATH_LEN 256 + +#define get_srv_runtime() \ + ({ \ + MppRuntimeSrv *__tmp; \ + if (!srv_runtime) { \ + mpp_rt_srv_init(); \ + } \ + if (srv_runtime) { \ + __tmp = srv_runtime; \ + } else { \ + mpp_err("mpp runtime srv not init at %s\n", __FUNCTION__); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +static rk_u32 mpp_rt_debug = 0; + +static const char *mpp_dts_base = "/proc/device-tree/"; + +static const char *mpp_vpu_names[] = { + "vpu_service", + "vpu-service", + "vpu", + //"hevc_service", + //"hevc-service", + //"rkvdec", + //"rkvenc", + //"vpu_combo", +}; + +#define mpp_rt_dbg(fmt, ...) do { if (mpp_rt_debug) mpp_log(fmt, ## __VA_ARGS__); } while (0) + +static const char *mpp_vpu_address[] = { + "", /* old kernel */ + "@10108000", /* rk3036 */ + "@20020000", /* rk322x */ + "@30000000", /* rv1108 */ + "@ff9a0000", /* rk3288/3366 */ + "@ff350000", /* rk322xh/3328 */ + "@ff650000", /* rk3399 */ +}; + +typedef struct MppRuntimeService_t { + rk_u32 allocator_valid[MPP_BUFFER_TYPE_BUTT]; +} MppRuntimeSrv; + +static MppRuntimeSrv *srv_runtime; + +static void mpp_rt_srv_init() +{ + MppRuntimeSrv *srv = srv_runtime; + + mpp_env_get_u32("mpp_rt_debug", &mpp_rt_debug, 0); + + if (srv) + return; + + srv = mpp_calloc(MppRuntimeSrv, 1); + if (!srv) { + mpp_err_f("failed to allocate runtime service\n"); + return; + } + + srv_runtime = srv; + + srv->allocator_valid[MPP_BUFFER_TYPE_NORMAL] = 1; + srv->allocator_valid[MPP_BUFFER_TYPE_ION] = !access("/dev/ion", F_OK | R_OK | W_OK); + srv->allocator_valid[MPP_BUFFER_TYPE_DRM] = + !access("/dev/dri/renderD128", F_OK | R_OK | W_OK) || + !access("/dev/dri/card0", F_OK | R_OK | W_OK); + srv->allocator_valid[MPP_BUFFER_TYPE_DMA_HEAP] = !access("/dev/dma_heap/system", F_OK | R_OK) && + !access("/dev/dma_heap/system-dma32", F_OK | R_OK) && + !access("/dev/dma_heap/system-uncached", F_OK | R_OK) && + !access("/dev/dma_heap/system-uncached-dma32", F_OK | R_OK); + + if (!srv->allocator_valid[MPP_BUFFER_TYPE_ION] && + !srv->allocator_valid[MPP_BUFFER_TYPE_DRM] && + !srv->allocator_valid[MPP_BUFFER_TYPE_DMA_HEAP]) { + mpp_err("can NOT found any allocator\n"); + return; + } + + if (srv->allocator_valid[MPP_BUFFER_TYPE_DMA_HEAP]) { + mpp_rt_dbg("use dma heap allocator\n"); + return; + } + + if (srv->allocator_valid[MPP_BUFFER_TYPE_ION] && !srv->allocator_valid[MPP_BUFFER_TYPE_DRM]) { + mpp_rt_dbg("use ion allocator\n"); + return; + } + + if (!srv->allocator_valid[MPP_BUFFER_TYPE_ION] && srv->allocator_valid[MPP_BUFFER_TYPE_DRM]) { + mpp_rt_dbg("use drm allocator\n"); + return; + } + + if (!access("/dev/mpp_service", F_OK | R_OK | W_OK)) { + srv->allocator_valid[MPP_BUFFER_TYPE_ION] = 0; + + mpp_rt_dbg("use drm allocator for mpp_service\n"); + return; + } + + // If both ion and drm is enabled detect allocator in dts to choose one + // TODO: When unify dma fd kernel is completed this part will be removed. + if (srv->allocator_valid[MPP_BUFFER_TYPE_ION] && + srv->allocator_valid[MPP_BUFFER_TYPE_DRM]) { + /* Detect hardware buffer type is ion or drm */ + rk_u32 i, j; + char path[MAX_DTS_PATH_LEN]; + rk_u32 path_len = MAX_DTS_PATH_LEN - 1; + rk_u32 dts_path_len = snprintf(path, path_len, "%s", mpp_dts_base); + char *p = path + dts_path_len; + rk_u32 allocator_found = 0; + + path_len -= dts_path_len; + + for (i = 0; i < MPP_ARRAY_ELEMS(mpp_vpu_names); i++) { + for (j = 0; j < MPP_ARRAY_ELEMS(mpp_vpu_address); j++) { + rk_u32 dev_path_len = snprintf(p, path_len, "%s%s", + mpp_vpu_names[i], mpp_vpu_address[j]); + int f_ok = access(path, F_OK); + if (f_ok == 0) { + snprintf(p + dev_path_len, path_len - dev_path_len, "/%s", "allocator"); + f_ok = access(path, F_OK); + if (f_ok == 0) { + rk_s32 val = 0; + FILE *fp = fopen(path, "rb"); + if (fp) { + size_t len = fread(&val, 1, 4, fp); + // zero for ion non-zero for drm -> + // zero - disable drm + // non-zero - disable ion + if (len != 4) { + mpp_err("failed to read dts allocator value default 0\n"); + val = 0; + } + + if (val == 0) { + srv->allocator_valid[MPP_BUFFER_TYPE_DRM] = 0; + mpp_rt_dbg("found ion allocator in dts\n"); + } else { + srv->allocator_valid[MPP_BUFFER_TYPE_ION] = 0; + mpp_rt_dbg("found drm allocator in dts\n"); + } + allocator_found = 1; + } + } + } + if (allocator_found) + break; + } + if (allocator_found) + break; + } + + if (!allocator_found) + mpp_log("Can NOT found allocator in dts, enable both ion and drm\n"); + } + return; +} + +static void mpp_rt_srv_deinit() +{ + MPP_FREE(srv_runtime); +} + +rk_u32 mpp_rt_allcator_is_valid(MppBufferType type) +{ + MppBufferType buffer_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK); + rk_u32 valid = 0; + + if (buffer_type < MPP_BUFFER_TYPE_BUTT) { + MppRuntimeSrv *srv = get_srv_runtime(); + + if (srv) + valid = srv->allocator_valid[buffer_type]; + } + + return valid; +} + +MPP_SINGLETON(MPP_SGLN_RUNTIME, mpp_runtime, mpp_rt_srv_init, mpp_rt_srv_deinit) diff --git a/osal/mpp_sgln_base.c b/osal/mpp_sgln_base.c new file mode 100644 index 000000000..ea4b8280f --- /dev/null +++ b/osal/mpp_sgln_base.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#include + +#include "mpp_common.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_sgln_base.h" + +#define SGLN_LOG(base, fmt, ...) \ + do { if ((base)->debug) printf("%s: " fmt, (base)->name, ##__VA_ARGS__); } while (0) + +#define SGLN_ERR(base, fmt, ...) \ + printf("%s: " fmt, (base)->name, ##__VA_ARGS__) + +rk_s32 mpp_sgln_base_add(MppSglnBase *base, MppSglnInfo *info, const char *caller) +{ + MppSglnList *arr; + rk_s32 id; + + mpp_env_get_u32(base->name, &base->debug, 0); + + if (!info) { + SGLN_ERR(base, "can not add NULL entry at %s\n", caller); + return rk_nok; + } + + id = info->id; + + arr = (id < 0 && base->array_count > 1) ? base->arrays[1] : base->arrays[0]; + + if (id >= 0) { + if (id >= (rk_s32)arr->capacity) { + SGLN_ERR(base, "id %d larger than max %d at %s\n", id, arr->capacity, caller); + return rk_nok; + } + if (arr->entries[id].name) { + SGLN_ERR(base, "entry %d has been registered at %s\n", id, caller); + return rk_nok; + } + arr->count = MPP_MAX(arr->count, (rk_u32)id + 1); + } else { + if (arr->count >= arr->capacity) { + SGLN_ERR(base, "no-id list full at %s\n", caller); + abort(); + return rk_nok; + } + info->id = arr->count++; + } + + arr->entries[info->id] = *info; + + { + rk_u32 len = strlen(info->name); + + if (len > base->max_name_len) + base->max_name_len = len; + } + + SGLN_LOG(base, "entry %2d %-*s registered at %s\n", + info->id, base->max_name_len, info->name, caller); + + return rk_ok; +} + +void mpp_sgln_base_deinit(MppSglnBase *base) +{ + rk_s32 j; + + SGLN_LOG(base, "deinit enter\n"); + + for (j = base->array_count - 1; j >= 0; j--) { + MppSglnList *arr = base->arrays[j]; + rk_s32 i; + + for (i = (rk_s32)arr->count - 1; i >= 0; i--) { + MppSglnInfo *info = &arr->entries[i]; + + if (info->name && info->deinit) { + SGLN_LOG(base, "entry %2d %-*s deinit start\n", + info->id, base->max_name_len, info->name); + info->deinit(); + SGLN_LOG(base, "entry %2d %-*s deinit finish\n", + info->id, base->max_name_len, info->name); + } + } + } + + SGLN_LOG(base, "deinit leave\n"); +} + +void mpp_sgln_base_run_init(MppSglnBase *base) +{ + rk_s64 sum = 0; + rk_s32 j; + + SGLN_LOG(base, "init enter\n"); + + for (j = 0; j < (rk_s32)base->array_count; j++) { + MppSglnList *arr = base->arrays[j]; + rk_s32 i; + + for (i = 0; i < (rk_s32)arr->count; i++) { + MppSglnInfo *info = &arr->entries[i]; + + if (info->name && info->init) { + rk_s64 time = mpp_time(); + SGLN_LOG(base, "entry %2d %-*s init start\n", + info->id, base->max_name_len, info->name); + info->init(); + time = mpp_time() - time; + sum += time; + SGLN_LOG(base, "entry %2d %-*s init finish %lld us\n", + info->id, base->max_name_len, info->name, time); + } + } + } + + SGLN_LOG(base, "init leave total %lld us\n", sum); +} diff --git a/osal/mpp_singleton.c b/osal/mpp_singleton.c new file mode 100644 index 000000000..57956df29 --- /dev/null +++ b/osal/mpp_singleton.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + */ + +#include + +#include "mpp_singleton.h" + +static MppSglnInfo mpp_info_with_id[MPP_SGLN_MAX_CNT] = {0}; +static MppSglnInfo mpp_info_without_id[MPP_SGLN_NO_ID_MAX_CNT] = {0}; + +static MppSglnList mpp_arr_with_id = { + .count = 0, + .capacity = MPP_SGLN_MAX_CNT, + .entries = mpp_info_with_id, +}; + +static MppSglnList mpp_arr_without_id = { + .count = 0, + .capacity = MPP_SGLN_NO_ID_MAX_CNT, + .entries = mpp_info_without_id, +}; + +static MppSglnBase mpp_sgln_base = { + .name = "mpp_sgln_debug", + .arrays = {&mpp_arr_with_id, &mpp_arr_without_id}, + .array_count = 2, + .max_name_len = 12, + .debug = 0, +}; + +rk_s32 mpp_singleton_add(MppSglnInfo *info, const char *caller) +{ + return mpp_sgln_base_add(&mpp_sgln_base, info, caller); +} + +static void mpp_singleton_deinit(void) +{ + mpp_sgln_base_deinit(&mpp_sgln_base); +} + +__attribute__((constructor(65535))) +static void mpp_singleton_init(void) +{ + atexit(mpp_singleton_deinit); + mpp_sgln_base_run_init(&mpp_sgln_base); +} diff --git a/osal/mpp_soc.c b/osal/mpp_soc.c new file mode 100644 index 000000000..a8a4bc0d7 --- /dev/null +++ b/osal/mpp_soc.c @@ -0,0 +1,1309 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2020 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_soc" + +#include +#include +#include +#include + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "mpp_soc.h" +#include "mpp_platform.h" + +#define MAX_SOC_NAME_LENGTH 128 + +#define get_srv_soc() \ + ({ \ + MppSocSrv *__tmp; \ + if (!srv_soc) { \ + mpp_soc_srv_init(); \ + } \ + if (srv_soc) { \ + __tmp = srv_soc; \ + } else { \ + mpp_err("mpp soc srv not init at %s\n", __FUNCTION__); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +#define CODING_TO_IDX(type) \ + ((rk_u32)(type) >= (rk_u32)MPP_VIDEO_CodingKhronosExtensions) ? \ + ((rk_u32)(-1)) : \ + ((rk_u32)(type) >= (rk_u32)MPP_VIDEO_CodingVC1) ? \ + ((rk_u32)(type) - (rk_u32)MPP_VIDEO_CodingVC1 + 16) : \ + ((rk_u32)(type) - (rk_u32)MPP_VIDEO_CodingUnused) + +#define HAVE_MPEG2 ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingMPEG2)))) +#define HAVE_H263 ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingH263)))) +#define HAVE_MPEG4 ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingMPEG4)))) +#define HAVE_AVC ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingAVC)))) +#define HAVE_MJPEG ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingMJPEG)))) +#define HAVE_VP8 ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingVP8)))) +#define HAVE_VP9 ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingVP9)))) +#define HAVE_HEVC ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingHEVC)))) +#define HAVE_AVSP ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingAVSPLUS)))) +#define HAVE_AVS ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingAVS)))) +#define HAVE_AVS2 ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingAVS2)))) +#define HAVE_AV1 ((rk_u32)(1 << (CODING_TO_IDX(MPP_VIDEO_CodingAV1)))) + +#define CAP_CODING_VDPU (HAVE_MPEG2|HAVE_H263|HAVE_MPEG4|HAVE_AVC|HAVE_MJPEG|HAVE_VP8|HAVE_AVS) +#define CAP_CODING_JPEGD_PP (HAVE_MJPEG) +#define CAP_CODING_AVSD (HAVE_AVS) +#define CAP_CODING_AVSPD (HAVE_AVSP) +#define CAP_CODING_AV1D (HAVE_AV1) +#define CAP_CODING_HEVC (HAVE_HEVC) +#define CAP_CODING_VDPU341 (HAVE_AVC|HAVE_HEVC|HAVE_VP9) +#define CAP_CODING_VDPU341_LITE (HAVE_AVC|HAVE_HEVC) +#define CAP_CODING_VDPU381 (HAVE_AVC|HAVE_HEVC|HAVE_VP9|HAVE_AVS2) +#define CAP_CODING_VDPU382 (HAVE_AVC|HAVE_HEVC|HAVE_AVS2) +#define CAP_CODING_VDPU383 (HAVE_AVC|HAVE_HEVC|HAVE_VP9|HAVE_AVS2|HAVE_AV1) +#define CAP_CODING_VDPU384A (HAVE_AVC|HAVE_HEVC) +#define CAP_CODING_VDPU384B (HAVE_AVC|HAVE_HEVC|HAVE_VP9|HAVE_AVS2|HAVE_AV1) +#define CAP_CODING_VDPU384B_NO_AVS2 (HAVE_AVC|HAVE_HEVC|HAVE_VP9|HAVE_AV1) + +#define CAP_CODING_VEPU1 (HAVE_AVC|HAVE_MJPEG|HAVE_VP8) +#define CAP_CODING_VEPU_LITE (HAVE_AVC|HAVE_MJPEG) +#define CAP_CODING_VEPU22 (HAVE_HEVC) +#define CAP_CODING_VEPU54X (HAVE_AVC|HAVE_HEVC) +#define CAP_CODING_VEPU540C (HAVE_AVC|HAVE_HEVC|HAVE_MJPEG) +#define CAP_CODING_VEPU511 (HAVE_AVC|HAVE_HEVC|HAVE_MJPEG) +#define CAP_CODING_VEPU511A (HAVE_AVC|HAVE_HEVC) + +static const MppDecHwCap vdpu1 = { + .cap_coding = CAP_CODING_VDPU, + .type = VPU_CLIENT_VDPU1, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu1_2160p = { + .cap_coding = CAP_CODING_VDPU, + .type = VPU_CLIENT_VDPU1, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu1_jpeg_pp = { + .cap_coding = CAP_CODING_JPEGD_PP, + .type = VPU_CLIENT_VDPU1_PP, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 1, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu2 = { + .cap_coding = CAP_CODING_VDPU, + .type = VPU_CLIENT_VDPU2, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu2_jpeg = { + .cap_coding = HAVE_MJPEG, + .type = VPU_CLIENT_VDPU2, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu2_jpeg_pp = { + .cap_coding = CAP_CODING_JPEGD_PP, + .type = VPU_CLIENT_VDPU2_PP, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 1, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu2_jpeg_fix = { + .cap_coding = HAVE_MJPEG, + .type = VPU_CLIENT_VDPU2, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 1, + .reserved = 0, +}; + +static const MppDecHwCap vdpu2_jpeg_pp_fix = { + .cap_coding = CAP_CODING_JPEGD_PP, + .type = VPU_CLIENT_VDPU2_PP, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 1, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 1, + .reserved = 0, +}; + +static const MppDecHwCap rk_hevc = { + .cap_coding = CAP_CODING_HEVC, + .type = VPU_CLIENT_HEVC_DEC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap rk_hevc_1080p = { + .cap_coding = CAP_CODING_HEVC, + .type = VPU_CLIENT_HEVC_DEC, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu341 = { + .cap_coding = CAP_CODING_VDPU341, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 0, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu341_lite = { + .cap_coding = CAP_CODING_VDPU341_LITE, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 0, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu341_lite_1080p = { + .cap_coding = CAP_CODING_VDPU341_LITE, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu341_h264 = { + .cap_coding = HAVE_AVC, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 0, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +/* vdpu34x support AFBC_V2 output */ +static const MppDecHwCap vdpu34x = { + .cap_coding = CAP_CODING_VDPU341, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 2, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 1, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 0, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu38x = { + .cap_coding = CAP_CODING_VDPU381, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 2, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 1, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 2, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu382a = { + .cap_coding = CAP_CODING_VDPU381, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 2, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 1, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu382 = { + .cap_coding = CAP_CODING_VDPU382, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 2, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 1, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu382_lite = { + .cap_coding = CAP_CODING_VDPU341, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 1, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu383 = { + .cap_coding = CAP_CODING_VDPU383, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 2, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 1, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu384a = { + .cap_coding = CAP_CODING_VDPU384A, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu384b = { + .cap_coding = CAP_CODING_VDPU384B, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 1, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap vdpu384b_no_avs2 = { + .cap_coding = CAP_CODING_VDPU384B_NO_AVS2, + .type = VPU_CLIENT_RKVDEC, + .cap_fbc = 1, + .cap_4k = 1, + .cap_8k = 1, + .cap_colmv_compress = 1, + .cap_hw_h265_rps = 1, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 1, + .cap_down_scale = 1, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap avspd = { + .cap_coding = CAP_CODING_AVSPD, + .type = VPU_CLIENT_AVSPLUS_DEC, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppDecHwCap rkjpegd = { + .cap_coding = HAVE_MJPEG, + .type = VPU_CLIENT_JPEG_DEC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 0, + .cap_core_num = 1, + .cap_hw_jpg_fix = 1, + .reserved = 0, +}; + +static const MppDecHwCap av1d = { + .cap_coding = CAP_CODING_AV1D, + .type = VPU_CLIENT_AV1DEC, + .cap_fbc = 1, + .cap_4k = 1, + .cap_8k = 0, + .cap_colmv_compress = 0, + .cap_hw_h265_rps = 0, + .cap_hw_vp9_prob = 0, + .cap_jpg_pp_out = 0, + .cap_10bit = 0, + .cap_down_scale = 0, + .cap_lmt_linebuf = 1, + .cap_core_num = 1, + .cap_hw_jpg_fix = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu1 = { + .cap_coding = CAP_CODING_VEPU1, + .type = VPU_CLIENT_VEPU1, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu2 = { + .cap_coding = CAP_CODING_VEPU1, + .type = VPU_CLIENT_VEPU2, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu2_no_vp8 = { + .cap_coding = HAVE_AVC | HAVE_MJPEG, + .type = VPU_CLIENT_VEPU2, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu2_no_jpeg = { + .cap_coding = HAVE_AVC | HAVE_VP8, + .type = VPU_CLIENT_VEPU2, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu2_jpeg = { + .cap_coding = HAVE_MJPEG, + .type = VPU_CLIENT_VEPU2, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu2_jpeg_enhanced = { + .cap_coding = HAVE_MJPEG, + .type = VPU_CLIENT_VEPU2_JPEG, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu22 = { + .cap_coding = CAP_CODING_HEVC, + .type = VPU_CLIENT_VEPU22, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +static const MppEncHwCap vepu540p = { + .cap_coding = HAVE_AVC, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 0, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 1, + .cap_hw_roi = 1, + .reserved = 0, +}; + +static const MppEncHwCap vepu541 = { + .cap_coding = CAP_CODING_VEPU54X, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 1, + .cap_4k = 1, + .cap_8k = 0, + .cap_hw_osd = 1, + .cap_hw_roi = 1, + .reserved = 0, +}; + +/* vepu540 support both AFBC_V1 and AFBC_V2 input */ +static const MppEncHwCap vepu540 = { + .cap_coding = CAP_CODING_VEPU54X, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 0x1 | 0x2, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 1, + .cap_hw_roi = 1, + .reserved = 0, +}; + +/* vepu58x */ +static const MppEncHwCap vepu58x = { + .cap_coding = CAP_CODING_VEPU54X, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 0x1 | 0x2, + .cap_4k = 1, + .cap_8k = 1, + .cap_hw_osd = 1, + .cap_hw_roi = 1, + .reserved = 0, +}; + +static const MppEncHwCap vepu540c = { + .cap_coding = CAP_CODING_VEPU540C, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 0x1 | 0x2, + .cap_4k = 0, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 1, + .reserved = 0, +}; + +static const MppEncHwCap vepu540c_no_hevc = { + .cap_coding = (HAVE_AVC | HAVE_MJPEG), + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 1, + .cap_hw_osd = 0, + .cap_hw_roi = 1, + .reserved = 0, +}; + +static const MppEncHwCap vepu510 = { + .cap_coding = CAP_CODING_VEPU54X, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 1, + .cap_hw_osd = 0, + .cap_hw_roi = 1, + .reserved = 0, +}; + +static const MppEncHwCap vepu511 = { + .cap_coding = CAP_CODING_VEPU511, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 2, + .cap_4k = 1, + .cap_8k = 0, + .cap_hw_osd = 1, + .cap_hw_roi = 1, + .reserved = 0, +}; + +static const MppEncHwCap vepu511a = { + .cap_coding = CAP_CODING_VEPU511A, + .type = VPU_CLIENT_RKVENC, + .cap_fbc = 2, + .cap_4k = 1, + .cap_8k = 0, + .cap_hw_osd = 0, + .cap_hw_roi = 1, + .reserved = 0, +}; + +static const MppEncHwCap rkjpege_vpu720 = { + .cap_coding = HAVE_MJPEG, + .type = VPU_CLIENT_JPEG_ENC, + .cap_fbc = 0, + .cap_4k = 1, + .cap_8k = 1, + .cap_hw_osd = 0, + .cap_hw_roi = 0, + .reserved = 0, +}; + +/* + * NOTE: + * vpu1 = vdpu1 + vepu1 + * vpu2 = vdpu2 + vepu2 + */ +static const MppSocInfo mpp_soc_infos[] = { + { /* + * rk3036 has + * 1 - vdpu1 + * 2 - RK hevc decoder + * rk3036 do NOT have encoder + */ + "rk3036", + ROCKCHIP_SOC_RK3036, + HAVE_VDPU1 | HAVE_VDPU1_PP | HAVE_HEVC_DEC, + { &rk_hevc_1080p, &vdpu1, &vdpu1_jpeg_pp, NULL, NULL, NULL, }, + { NULL, NULL, NULL, NULL, }, + }, + { /* rk3066 has vpu1 only */ + "rk3066", + ROCKCHIP_SOC_RK3066, + HAVE_VDPU1 | HAVE_VDPU1_PP | HAVE_VEPU1, + { &vdpu1, &vdpu1_jpeg_pp, NULL, NULL, NULL, NULL, }, + { &vepu1, NULL, NULL, NULL, }, + }, + { /* rk3188 has vpu1 only */ + "rk3188", + ROCKCHIP_SOC_RK3188, + HAVE_VDPU1 | HAVE_VDPU1_PP | HAVE_VEPU1, + { &vdpu1, &vdpu1_jpeg_pp, NULL, NULL, NULL, NULL, }, + { &vepu1, NULL, NULL, NULL, }, + }, + { /* + * rk3288 has + * 1 - vpu1 with 2160p AVC decoder + * 2 - RK hevc 4K decoder + */ + "rk3288", + ROCKCHIP_SOC_RK3288, + HAVE_VDPU1 | HAVE_VDPU1_PP | HAVE_VEPU1 | HAVE_HEVC_DEC, + { &rk_hevc, &vdpu1_2160p, &vdpu1_jpeg_pp, NULL, NULL, NULL, }, + { &vepu1, NULL, NULL, NULL, }, + }, + { /* + * rk3126 has + * 1 - vpu1 + * 2 - RK hevc 1080p decoder + */ + "rk3126", + ROCKCHIP_SOC_RK312X, + HAVE_VDPU1 | HAVE_VDPU1_PP | HAVE_VEPU1 | HAVE_HEVC_DEC, + { &rk_hevc_1080p, &vdpu1, &vdpu1_jpeg_pp, NULL, NULL, NULL, }, + { &vepu1, NULL, NULL, NULL, }, + }, + { /* + * rk3128 has + * 1 - vpu1 + * 2 - RK hevc 1080p decoder + */ + "rk3128", + ROCKCHIP_SOC_RK312X, + HAVE_VDPU1 | HAVE_VDPU1_PP | HAVE_VEPU1 | HAVE_HEVC_DEC, + { &rk_hevc_1080p, &vdpu1, &vdpu1_jpeg_pp, NULL, NULL, NULL, }, + { &vepu1, NULL, NULL, NULL, }, + }, + { /* + * rk3128h has + * 1 - vpu2 + * 2 - RK H.264/H.265 1080p@60fps decoder + * NOTE: rk3128H do NOT have jpeg encoder + */ + "rk3128h", + ROCKCHIP_SOC_RK3128H, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC, + { &vdpu341_lite_1080p, &vdpu2, &vdpu2_jpeg_pp, NULL, NULL, NULL, }, + { &vepu2_no_jpeg, NULL, NULL, NULL, }, + }, + { /* + * rk3368 has + * 1 - vpu1 + * 2 - RK hevc 4K decoder + */ + "rk3368", + ROCKCHIP_SOC_RK3368, + HAVE_VDPU1 | HAVE_VDPU1_PP | HAVE_VEPU1 | HAVE_HEVC_DEC, + { &rk_hevc, &vdpu1_2160p, &vdpu1_jpeg_pp, NULL, NULL, NULL, }, + { &vepu1, NULL, NULL, NULL, }, + }, + { /* + * rk3399 has + * 1 - vpu2 + * 2 - H.264/H.265/VP9 4K decoder + */ + "rk3399", + ROCKCHIP_SOC_RK3399, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC, + { &vdpu341, &vdpu2, &vdpu2_jpeg_pp, NULL, NULL, NULL, }, + { &vepu2, NULL, NULL, NULL, }, + }, + { /* + * rk3328 has codec: + * 1 - vpu2 + * 2 - RK H.264/H.265/VP9 4K decoder + * 4 - H.265 encoder + */ + "rk3328", + ROCKCHIP_SOC_RK3328, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_VEPU22, + { &vdpu341, &vdpu2, &vdpu2_jpeg_pp, NULL, NULL, NULL, }, + { &vepu2, &vepu22, NULL, NULL, }, + }, + { /* + * rk3228 have codec: + * 1 - vpu2 + * 2 - RK H.264/H.265 4K decoder + * NOTE: rk3228 do NOT have jpeg encoder + */ + "rk3228", + ROCKCHIP_SOC_RK3228, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC, + { &vdpu341_lite, &vdpu2, &vdpu2_jpeg_pp, NULL, NULL, NULL, }, + { &vepu2_no_jpeg, NULL, NULL, NULL, }, + }, + { /* + * rk3228h has + * 1 - vpu2 + * 2 - RK H.264/H.265 4K decoder + * 3 - avs+ decoder + * 4 - H.265 1080p encoder + * rk3228h first for string matching + */ + "rk3228h", + ROCKCHIP_SOC_RK3228H, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_AVSDEC | HAVE_VEPU22, + { &vdpu341_lite, &vdpu2, &vdpu2_jpeg_pp, &avspd, NULL, NULL, }, + { &vepu2_no_jpeg, &vepu22, NULL, NULL, }, + }, + { /* + * rk3229 has + * 1 - vpu2 + * 2 - H.264/H.265/VP9 4K decoder + */ + "rk3229", + ROCKCHIP_SOC_RK3229, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC, + { &vdpu341, &vdpu2, &vdpu2_jpeg_pp, NULL, NULL, NULL, }, + { &vepu2, NULL, NULL, NULL, }, + }, + { /* + * rv1108 has codec: + * 1 - vpu2 for jpeg encoder and decoder + * 2 - RK H.264 4K decoder + * 3 - RK H.264 4K encoder + */ + "rv1108", + ROCKCHIP_SOC_RV1108, + HAVE_VDPU2 | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_RKVENC, + { &vdpu2_jpeg, &vdpu341_h264, NULL, NULL, NULL, NULL, }, + { &vepu2_jpeg, &vepu540p, NULL, NULL, }, + }, + { /* + * rv1109 has codec: + * 1 - vpu2 for jpeg encoder and decoder + * 2 - RK H.264/H.265 4K decoder + * 3 - RK H.264/H.265 4K encoder + */ + "rv1109", + ROCKCHIP_SOC_RV1109, + HAVE_VDPU2 | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_RKVENC, + { &vdpu2_jpeg_fix, &vdpu341_lite, NULL, NULL, NULL, NULL, }, + { &vepu2_jpeg, &vepu541, NULL, NULL, }, + }, + { /* + * rv1126 has codec: + * 1 - vpu2 for jpeg encoder and decoder + * 2 - RK H.264/H.265 4K decoder + * 3 - RK H.264/H.265 4K encoder + */ + "rv1126", + ROCKCHIP_SOC_RV1126, + HAVE_VDPU2 | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_RKVENC, + { &vdpu2_jpeg_fix, &vdpu341_lite, NULL, NULL, NULL, NULL, }, + { &vepu2_jpeg, &vepu541, NULL, NULL, }, + }, + { /* + * rk3326 has + * 1 - vpu2 + * 2 - RK hevc 1080p decoder + */ + "rk3326", + ROCKCHIP_SOC_RK3326, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_HEVC_DEC, + { &rk_hevc_1080p, &vdpu2, &vdpu2_jpeg_pp_fix, NULL, NULL, NULL, }, + { &vepu2, NULL, NULL, NULL, }, + }, + { /* + * px30 has + * 1 - vpu2 + * 2 - RK hevc 1080p decoder + */ + "px30", + ROCKCHIP_SOC_RK3326, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_HEVC_DEC, + { &rk_hevc_1080p, &vdpu2, &vdpu2_jpeg_pp_fix, NULL, NULL, NULL, }, + { &vepu2, NULL, NULL, NULL, }, + }, + { /* + * px30 has vpu2 only + */ + "rk1808", + ROCKCHIP_SOC_RK1808, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2, + { &vdpu2, &vdpu2_jpeg_pp, NULL, NULL, NULL, NULL, }, + { &vepu2, NULL, NULL, NULL, }, + }, + { /* + * rk3566/rk3567/rk3568 has codec: + * 1 - vpu2 for jpeg encoder and decoder + * 2 - RK H.264/H.265/VP9 4K decoder + * 3 - RK H.264/H.265 4K encoder + * 3 - RK jpeg decoder + */ + "rk3566", + ROCKCHIP_SOC_RK3566, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_RKVENC | HAVE_JPEG_DEC, + { &vdpu34x, &rkjpegd, &vdpu2, &vdpu2_jpeg_pp_fix, NULL, NULL, }, + { &vepu540, &vepu2_no_vp8, NULL, NULL, }, + }, + { /* + * rk3566/rk3567/rk3568 has codec: + * 1 - vpu2 for jpeg encoder and decoder + * 2 - RK H.264/H.265/VP9 4K decoder + * 3 - RK H.264/H.265 4K encoder + * 3 - RK jpeg decoder + */ + "rk3567", + ROCKCHIP_SOC_RK3567, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_RKVENC | HAVE_JPEG_DEC, + { &vdpu34x, &rkjpegd, &vdpu2, &vdpu2_jpeg_pp_fix, NULL, NULL, }, + { &vepu540, &vepu2_no_vp8, NULL, NULL, }, + }, + { /* + * rk3566/rk3567/rk3568 has codec: + * 1 - vpu2 for jpeg encoder and decoder + * 2 - RK H.264/H.265/VP9 4K decoder + * 3 - RK H.264/H.265 4K encoder + * 3 - RK jpeg decoder + */ + "rk3568", + ROCKCHIP_SOC_RK3568, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_RKVENC | HAVE_JPEG_DEC, + { &vdpu34x, &rkjpegd, &vdpu2, &vdpu2_jpeg_pp_fix, NULL, NULL, }, + { &vepu540, &vepu2_no_vp8, NULL, NULL, }, + }, + { /* + * rk3588 has codec: + * 1 - vpu2 for jpeg/vp8 encoder and decoder + * 2 - RK H.264/H.265/VP9 8K decoder + * 3 - RK H.264/H.265 8K encoder + * 4 - RK jpeg decoder + */ + "rk3588", + ROCKCHIP_SOC_RK3588, + HAVE_VDPU2 | HAVE_VDPU2_PP | HAVE_VEPU2 | HAVE_RKVDEC | HAVE_RKVENC | + HAVE_JPEG_DEC | HAVE_AV1DEC | HAVE_AVSDEC | HAVE_VEPU2_JPEG, + { &vdpu38x, &rkjpegd, &vdpu2, &vdpu2_jpeg_pp_fix, &av1d, &avspd}, + { &vepu58x, &vepu2, &vepu2_jpeg_enhanced, NULL, }, + }, + { /* + * rk3528 has codec: + * 1 - vpu2 for jpeg/vp8 decoder + * 2 - RK H.264/H.265 4K decoder + * 3 - RK H.264/H.265 1080P encoder + * 4 - RK jpeg decoder + */ + "rk3528", + ROCKCHIP_SOC_RK3528, + HAVE_RKVDEC | HAVE_RKVENC | HAVE_VDPU2 | HAVE_JPEG_DEC | HAVE_AVSDEC, + { &vdpu382, &rkjpegd, &vdpu2, &avspd, NULL, NULL, }, + { &vepu540c, NULL, NULL, NULL, }, + }, + { /* + * rk3528a has codec: + * 1 - vpu2 for jpeg/vp8 decoder + * 2 - RK H.264/H.265/VP9 4K decoder + * 3 - RK H.264/H.265 1080P encoder + * 4 - RK jpeg decoder + */ + "rk3528a", + ROCKCHIP_SOC_RK3528, + HAVE_RKVDEC | HAVE_RKVENC | HAVE_VDPU2 | HAVE_JPEG_DEC | HAVE_AVSDEC, + { &vdpu382a, &rkjpegd, &vdpu2, &avspd, NULL, NULL, }, + { &vepu540c, NULL, NULL, NULL, }, + }, + { /* + * rk3562 has codec: + * 1 - RK H.264/H.265/VP9 4K decoder + * 2 - RK H.264 1080P encoder + * 3 - RK jpeg decoder + */ + "rk3562", + ROCKCHIP_SOC_RK3562, + HAVE_RKVDEC | HAVE_RKVENC | HAVE_JPEG_DEC, + { &vdpu382_lite, &rkjpegd, NULL, NULL, NULL, NULL, }, + { &vepu540c_no_hevc, NULL, NULL, NULL, }, + }, + { /* + * rk3576 has codec: + * 1 - RK H.264/H.265/VP9/AVS2/AV1 8K decoder + * 2 - RK H.264/H.265 8K encoder + * 3 - RK jpeg decoder/encoder + */ + "rk3576", + ROCKCHIP_SOC_RK3576, + HAVE_RKVDEC | HAVE_RKVENC | HAVE_JPEG_DEC | HAVE_JPEG_ENC, + { &vdpu383, &rkjpegd, NULL, NULL, NULL, NULL}, + { &vepu510, &rkjpege_vpu720, NULL, NULL}, + }, + { /* + * rv1126b has codec: + * 1 - RK H.264/H.265 4K decoder + * 2 - RK H.264/H.265/jpeg 4K encoder + * 3 - RK jpeg decoder + */ + "rv1126b", + ROCKCHIP_SOC_RV1126B, + HAVE_RKVDEC | HAVE_RKVENC | HAVE_JPEG_DEC, + { &vdpu384a, &rkjpegd, NULL, NULL, NULL, NULL}, + { &vepu511, NULL, NULL, NULL}, + }, + { /* + * RK3538 has codec: + * 1 - RK H.264/H.265/VP9/AV1 1080P decoder + * 2 - RK jpeg decoder + */ + "rk3538", + ROCKCHIP_SOC_RK3538, + HAVE_RKVDEC | HAVE_JPEG_DEC | HAVE_VDPU2, + { &vdpu384b_no_avs2, &rkjpegd, &vdpu2, NULL, NULL, NULL}, + { NULL, NULL, NULL, NULL}, + }, + { /* + * RK3572 has codec: + * 1 - RK H.264/H.265/VP9/AVS2/AV1 8K decoder + * 2 - RK H.264/H.265/jpeg 4K encoder + * 3 - RK jpeg decoder + */ + "rk3572", + ROCKCHIP_SOC_RK3572, + HAVE_RKVDEC | HAVE_RKVENC | HAVE_JPEG_DEC | HAVE_JPEG_ENC, + { &vdpu384b, &rkjpegd, NULL, NULL, NULL, NULL}, + { &vepu511a, &rkjpege_vpu720, NULL, NULL}, + }, + { /* + * RK3539 has codec: + * 1 - RK H.264/H.265/VP9/AV1 4K decoder + * 2 - RK jpeg decoder + */ + "rk3539", + ROCKCHIP_SOC_RK3539, + HAVE_RKVDEC | HAVE_JPEG_DEC | HAVE_VDPU2, + { &vdpu384b_no_avs2, &rkjpegd, &vdpu2, NULL, NULL, NULL}, + { NULL, NULL, NULL, NULL}, + }, +}; + +static const MppSocInfo mpp_soc_default = { + "unknown", + ROCKCHIP_SOC_AUTO, + HAVE_VDPU2 | HAVE_VEPU2 | HAVE_VDPU1 | HAVE_VEPU1, + { &vdpu2, &vdpu1, NULL, NULL, }, + { &vepu2, &vepu1, NULL, NULL, }, +}; + +RK_S32 mpp_coding_to_index(MppCodingType coding) +{ + return (RK_S32)(CODING_TO_IDX(coding)); +} + +static void read_soc_name(char *name, rk_s32 size) +{ + const char *path = "/proc/device-tree/compatible"; + char *ptr = NULL; + rk_s32 fd = open(path, O_RDONLY); + + if (fd < 0) { + mpp_err("open %s error\n", path); + } else { + ssize_t soc_name_len = 0; + + snprintf(name, size - 1, "unknown"); + soc_name_len = read(fd, name, size - 1); + if (soc_name_len > 0) { + name[soc_name_len] = '\0'; + /* replacing the termination character to space */ + for (ptr = name;; ptr = name) { + ptr += strnlen(name, size); + if (ptr >= name + soc_name_len - 1) + break; + *ptr = ' '; + } + + sys_dbg_platform("chip name: %s\n", name); + } + + close(fd); + } +} + +static const MppSocInfo *check_soc_info(const char *soc_name) +{ + rk_s32 i; + + for (i = MPP_ARRAY_ELEMS(mpp_soc_infos) - 1; i >= 0; i--) { + const char *compatible = mpp_soc_infos[i].compatible; + + if (strstr(soc_name, compatible)) { + sys_dbg_platform("match chip name: %s\n", compatible); + return &mpp_soc_infos[i]; + } + } + + return NULL; +} + +typedef struct MppSocSrv_t { + char soc_name[MAX_SOC_NAME_LENGTH]; + const MppSocInfo *soc_info; + rk_u32 dec_coding_cap; + rk_u32 enc_coding_cap; +} MppSocSrv; + +static MppSocSrv *srv_soc = NULL; + +static void mpp_soc_srv_init() +{ + MppSocSrv *srv = srv_soc; + rk_u32 vcodec_type = 0; + rk_u32 i; + + if (srv) + return; + + srv = mpp_calloc(MppSocSrv, 1); + if (!srv) { + mpp_err_f("failed to allocate soc service\n"); + return; + } + + srv_soc = srv; + + mpp_env_get_u32("mpp_debug", &mpp_debug, 0); + + read_soc_name(srv->soc_name, sizeof(srv->soc_name)); + srv->soc_info = check_soc_info(srv->soc_name); + if (NULL == srv->soc_info) { + sys_dbg_platform("use default chip info\n"); + srv->soc_info = &mpp_soc_default; + } + + for (i = 0; i < MPP_ARRAY_ELEMS(srv->soc_info->dec_caps); i++) { + const MppDecHwCap *cap = srv->soc_info->dec_caps[i]; + + if (cap && cap->cap_coding) { + srv->dec_coding_cap |= cap->cap_coding; + vcodec_type |= (1 << cap->type); + } + } + + for (i = 0; i < MPP_ARRAY_ELEMS(srv->soc_info->enc_caps); i++) { + const MppEncHwCap *cap = srv->soc_info->enc_caps[i]; + + if (cap && cap->cap_coding) { + srv->enc_coding_cap |= cap->cap_coding; + vcodec_type |= (1 << cap->type); + } + } + + sys_dbg_platform("coding caps: dec %08x enc %08x\n", + srv->dec_coding_cap, srv->enc_coding_cap); + sys_dbg_platform("vcodec type from cap: %08x, from soc_info %08x\n", + vcodec_type, srv->soc_info->vcodec_type); + mpp_assert(srv->soc_info->vcodec_type == vcodec_type); +} + +static void mpp_soc_srv_deinit() +{ + MPP_FREE(srv_soc); +} + +const char *mpp_get_soc_name(void) +{ + MppSocSrv *srv = get_srv_soc(); + const char *name = NULL; + + if (srv) + name = srv->soc_name; + + return name; +} + +const MppSocInfo *mpp_get_soc_info(void) +{ + MppSocSrv *srv = get_srv_soc(); + const MppSocInfo *info = NULL; + + if (srv) + info = srv->soc_info; + + return info; +} + +RockchipSocType mpp_get_soc_type(void) +{ + MppSocSrv *srv = get_srv_soc(); + RockchipSocType type = ROCKCHIP_SOC_AUTO; + + if (srv) + type = srv->soc_info->soc_type; + + return type; +} + +static rk_u32 is_valid_cap_coding(rk_u32 cap, MppCodingType coding) +{ + rk_s32 index = CODING_TO_IDX(coding); + + if (index > 0 && index < 32 && (cap & (rk_u32)(1 << index))) + return 1; + + return 0; +} + +rk_u32 mpp_check_soc_cap(MppCtxType type, MppCodingType coding) +{ + MppSocSrv *srv = get_srv_soc(); + rk_u32 cap = 0; + + if (srv) { + if (type == MPP_CTX_DEC) + cap = srv->dec_coding_cap; + else if (type == MPP_CTX_ENC) + cap = srv->enc_coding_cap; + else + return 0; + } + + if (!cap) + return 0; + + return is_valid_cap_coding(cap, coding); +} + +const MppDecHwCap* mpp_get_dec_hw_info_by_client_type(MppClientType client_type) +{ + const MppDecHwCap* hw_info = NULL; + const MppSocInfo *info = mpp_get_soc_info(); + rk_u32 i = 0; + + for (i = 0; i < MPP_ARRAY_ELEMS(info->dec_caps); i++) { + if (info->dec_caps[i] && info->dec_caps[i]->type == client_type) { + hw_info = info->dec_caps[i]; + break; + } + } + + return hw_info; +} + +MPP_SINGLETON(MPP_SGLN_SOC, mpp_soc, mpp_soc_srv_init, mpp_soc_srv_deinit) diff --git a/osal/mpp_thread.c b/osal/mpp_thread.c new file mode 100644 index 000000000..fc9741c00 --- /dev/null +++ b/osal/mpp_thread.c @@ -0,0 +1,821 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_thread" + +#include + +#include "mpp_mem.h" +#include "mpp_lock.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" + +#define THREAD_DBG_FUNC (0x00000001) + +static rk_u32 thread_debug = 0; + +#define thread_dbg(flag, fmt, ...) mpp_dbg(thread_debug, flag, fmt, ## __VA_ARGS__) + +MppThread *mpp_thread_create(MppThreadFunc func, void *ctx, const char *name) +{ + MppThread *thread = mpp_malloc(MppThread, 1); + int i; + + if (thread) { + thread->func = func; + thread->ctx = ctx; + + thread->thd_status[THREAD_WORK] = MPP_THREAD_UNINITED; + thread->thd_status[THREAD_INPUT] = MPP_THREAD_RUNNING; + thread->thd_status[THREAD_OUTPUT] = MPP_THREAD_RUNNING; + thread->thd_status[THREAD_CONTROL] = MPP_THREAD_RUNNING; + + if (name) { + strncpy(thread->name, name, THREAD_NAME_LEN - 1); + thread->name[THREAD_NAME_LEN - 1] = '\0'; + } else { + snprintf(thread->name, THREAD_NAME_LEN, "MppThread"); + } + for (i = 0; i < THREAD_SIGNAL_BUTT; i++) { + mpp_mutex_cond_init(&thread->mutex_cond[i]); + } + } + + return thread; +} + +void mpp_thread_dump_status(MppThread *thread) +{ + mpp_log("thread %s status: %d %d %d %d\n", thread->name, + thread->thd_status[THREAD_WORK], thread->thd_status[THREAD_INPUT], + thread->thd_status[THREAD_OUTPUT], thread->thd_status[THREAD_CONTROL]); +} + +void mpp_thread_start(MppThread *thread) +{ + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + if (mpp_thread_get_status(thread, THREAD_WORK) == MPP_THREAD_UNINITED) { + mpp_thread_set_status(thread, MPP_THREAD_RUNNING, THREAD_WORK); + if (0 == pthread_create(&thread->thd, &attr, thread->func, thread->ctx)) { + int ret = pthread_setname_np(thread->thd, thread->name); + if (ret) { + mpp_err("thread %p setname %s failed\n", thread->func, thread->name); + } + thread_dbg(THREAD_DBG_FUNC, "thread %s %p context %p create success\n", + thread->name, thread->func, thread->ctx); + } else { + mpp_thread_set_status(thread, MPP_THREAD_UNINITED, THREAD_WORK); + } + } + + pthread_attr_destroy(&attr); +} + +void mpp_thread_stop(MppThread *thread) +{ + if (mpp_thread_get_status(thread, THREAD_WORK) != MPP_THREAD_UNINITED) { + void *dummy; + + mpp_thread_lock(thread, THREAD_WORK); + mpp_thread_set_status(thread, MPP_THREAD_STOPPING, THREAD_WORK); + + thread_dbg(THREAD_DBG_FUNC, "MPP_THREAD_STOPPING status set thd %p\n", (void *)thread); + mpp_thread_signal(thread, THREAD_WORK); + mpp_thread_unlock(thread, THREAD_WORK); + + pthread_join(thread->thd, &dummy); + thread_dbg(THREAD_DBG_FUNC, "thread %s %p context %p destroy success\n", thread->name, thread->func, thread->ctx); + + mpp_thread_set_status(thread, MPP_THREAD_UNINITED, THREAD_WORK); + } +} + +void mpp_thread_destroy(MppThread *thread) +{ + if (thread) { + mpp_thread_stop(thread); + mpp_free(thread); + } +} + +void mpp_mutex_init(MppMutex *mutex) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex->lock, &attr); + pthread_mutexattr_destroy(&attr); +} + +void mpp_mutex_destroy(MppMutex *mutex) +{ + pthread_mutex_destroy(&mutex->lock); +} + +void mpp_mutex_lock(MppMutex *mutex) +{ + pthread_mutex_lock(&mutex->lock); +} + +void mpp_mutex_unlock(MppMutex *mutex) +{ + pthread_mutex_unlock(&mutex->lock); +} + +int mpp_mutex_trylock(MppMutex *mutex) +{ + return pthread_mutex_trylock(&mutex->lock); +} + +// MppCond functions +void mpp_cond_init(MppCond *condition) +{ +#ifdef COND_USE_CLOCK_MONOTONIC + pthread_condattr_t attr; + + pthread_condattr_init(&attr);; + + if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) { + pthread_cond_init(&condition->cond, NULL); + condition->clock_id = CLOCK_REALTIME; + } else { + pthread_cond_init(&condition->cond, &attr); + condition->clock_id = CLOCK_MONOTONIC; + } + + pthread_condattr_destroy(&attr); +#else + pthread_cond_init(&condition->cond, NULL); + condition->clock_id = CLOCK_REALTIME; +#endif // COND_USE_CLOCK_MONOTONIC +} + +void mpp_cond_destroy(MppCond *condition) +{ + pthread_cond_destroy(&condition->cond); +} + +rk_s32 mpp_cond_wait(MppCond *condition, MppMutex *mutex) +{ + return pthread_cond_wait(&condition->cond, &mutex->lock); +} + +rk_s32 mpp_cond_timedwait(MppCond *condition, MppMutex *mutex, rk_s64 timeout) +{ + struct timespec ts; + + clock_gettime(condition->clock_id, &ts); + + ts.tv_sec += timeout / 1000; + ts.tv_nsec += (timeout % 1000) * 1000000; + ts.tv_sec += ts.tv_nsec / 1000000000; + ts.tv_nsec %= 1000000000; + + return pthread_cond_timedwait(&condition->cond, &mutex->lock, &ts); +} + +rk_s32 mpp_cond_signal(MppCond *condition) +{ + return pthread_cond_signal(&condition->cond); +} + +rk_s32 mpp_cond_broadcast(MppCond *condition) +{ + return pthread_cond_broadcast(&condition->cond); +} + +// MppMutexCond functions +void mpp_mutex_cond_init(MppMutexCond *mutexCond) +{ + mpp_mutex_init(&mutexCond->lock); + mpp_cond_init(&mutexCond->cond); +} + +void mpp_mutex_cond_destroy(MppMutexCond *mutexCond) +{ + mpp_mutex_destroy(&mutexCond->lock); + mpp_cond_destroy(&mutexCond->cond); +} + +void mpp_mutex_cond_lock(MppMutexCond *mutexCond) +{ + mpp_mutex_lock(&mutexCond->lock); +} + +void mpp_mutex_cond_unlock(MppMutexCond *mutexCond) +{ + mpp_mutex_unlock(&mutexCond->lock); +} + +int mpp_mutex_cond_trylock(MppMutexCond *mutexCond) +{ + return mpp_mutex_trylock(&mutexCond->lock); +} + +rk_s32 mpp_mutex_cond_wait(MppMutexCond *mutexCond) +{ + return mpp_cond_wait(&mutexCond->cond, &mutexCond->lock); +} + +rk_s32 mpp_mutex_cond_timedwait(MppMutexCond *mutexCond, rk_s64 timeout) +{ + return mpp_cond_timedwait(&mutexCond->cond, &mutexCond->lock, timeout); +} + +void mpp_mutex_cond_signal(MppMutexCond *mutexCond) +{ + mpp_cond_signal(&mutexCond->cond); +} + +void mpp_mutex_cond_broadcast(MppMutexCond *mutexCond) +{ + mpp_cond_broadcast(&mutexCond->cond); +} + +// MppThread functions +void mpp_thread_init(MppThread *thread, MppThreadFunc func, void *ctx, const char *name) +{ + thread->func = func; + thread->ctx = ctx; + int i; + + if (name) { + strncpy(thread->name, name, THREAD_NAME_LEN - 1); + thread->name[THREAD_NAME_LEN - 1] = '\0'; + } + for (i = 0; i < THREAD_SIGNAL_BUTT; i++) { + mpp_mutex_cond_init(&thread->mutex_cond[i]); + thread->thd_status[i] = MPP_THREAD_UNINITED; + } +} + +void mpp_thread_set_status(MppThread *thread, MppThreadStatus status, MppThreadSignalId id) +{ + assert(id < THREAD_SIGNAL_BUTT); + thread->thd_status[id] = status; +} + +MppThreadStatus mpp_thread_get_status(MppThread *thread, MppThreadSignalId id) +{ + assert(id < THREAD_SIGNAL_BUTT); + return thread->thd_status[id]; +} + +void mpp_thread_lock(MppThread *thread, MppThreadSignalId id) +{ + assert(id < THREAD_SIGNAL_BUTT); + mpp_mutex_cond_lock(&thread->mutex_cond[id]); +} + +void mpp_thread_unlock(MppThread *thread, MppThreadSignalId id) +{ + assert(id < THREAD_SIGNAL_BUTT); + mpp_mutex_cond_unlock(&thread->mutex_cond[id]); +} + +void mpp_thread_wait(MppThread *thread, MppThreadSignalId id) +{ + assert(id < THREAD_SIGNAL_BUTT); + MppThreadStatus status = thread->thd_status[id]; + thread->thd_status[id] = MPP_THREAD_WAITING; + mpp_mutex_cond_wait(&thread->mutex_cond[id]); + + if (thread->thd_status[id] == MPP_THREAD_WAITING) + thread->thd_status[id] = status; +} + +void mpp_thread_signal(MppThread *thread, MppThreadSignalId id) +{ + assert(id < THREAD_SIGNAL_BUTT); + mpp_mutex_cond_signal(&thread->mutex_cond[id]); +} + +typedef struct MppSThdImpl_t { + char *name; + MppSThdFunc func; + MppSThdStatus status; + rk_s32 idx; + pthread_t thd; + pthread_mutex_t lock; + pthread_cond_t cond; + MppSThdCtx ctx; +} MppSThdImpl; + +typedef struct MppSThdGrpImpl_t { + char name[THREAD_NAME_LEN]; + rk_s32 count; + MppSThdStatus status; + pthread_mutex_t lock; + MppSThdImpl thds[]; +} MppSThdGrpImpl; + +static const char *state2str(MppSThdStatus state) +{ + static const char *strof_sthd_status[] = { + "uninited", + "ready", + "running", + "waiting", + "stopping", + "invalid" + }; + + return state < MPP_STHD_BUTT ? strof_sthd_status[state] : strof_sthd_status[MPP_STHD_BUTT]; +} + +static rk_s32 check_sthd(const char *name, MppSThdImpl *thd) +{ + if (!thd) { + mpp_err("mpp_sthd NULL found at %s\n", name); + return MPP_NOK; + } + + if (thd->ctx.thd != thd) { + mpp_err("mpp_sthd check %p:%p mismatch at %s\n", thd->ctx.thd, thd, name); + return MPP_NOK; + } + + return MPP_OK; +} + +#define CHECK_STHD(thd) check_sthd(__FUNCTION__, (MppSThdImpl *)(thd)) + +static void mpp_sthd_init(MppSThdImpl *thd, rk_s32 idx) +{ + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&thd->lock, &attr); + pthread_mutexattr_destroy(&attr); + + pthread_cond_init(&thd->cond, NULL); + thd->ctx.thd = thd; + thd->idx = idx; +} + +static void mpp_sthd_deinit(MppSThdImpl *thd) +{ + mpp_assert(thd->ctx.thd == thd); + mpp_assert(thd->status < MPP_STHD_RUNNING); + + pthread_mutex_lock(&thd->lock); + thd->status = MPP_STHD_UNINITED; + thd->ctx.thd = NULL; + pthread_mutex_unlock(&thd->lock); + + pthread_cond_destroy(&thd->cond); + pthread_mutex_destroy(&thd->lock); +} + +static MPP_RET mpp_sthd_create(MppSThdImpl *thd) +{ + pthread_attr_t attr; + MPP_RET ret = MPP_NOK; + + mpp_assert(thd->ctx.thd == thd); + mpp_assert(thd->status < MPP_STHD_RUNNING); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + // NOTE: set status to running first + thd->status = MPP_STHD_RUNNING; + if (0 == pthread_create(&thd->thd, &attr, (MppThreadFunc)thd->func, &thd->ctx)) { + ret = (MPP_RET)pthread_setname_np(thd->thd, thd->name); + if (ret) + mpp_err("%s %p setname failed\n", thd->thd, thd->func); + + thread_dbg(THREAD_DBG_FUNC, "thread %s %p context %p create success\n", + thd->name, thd->func, thd->ctx.ctx); + ret = MPP_OK; + } else { + thd->status = MPP_STHD_READY; + } + + pthread_attr_destroy(&attr); + + return ret; +} + +MppSThd mpp_sthd_get(const char *name) +{ + rk_s32 size = MPP_ALIGN(sizeof(MppSThdImpl), 8) + THREAD_NAME_LEN; + MppSThdImpl *thd = mpp_calloc_size(MppSThdImpl, size); + + if (!thd) { + mpp_err_f("failed to create simple thread\n"); + return NULL; + } + + thd->name = (char *)(thd + 1); + if (!name) + name = "mpp_sthd"; + + snprintf(thd->name, THREAD_NAME_LEN - 1, "%s", name); + + mpp_sthd_init(thd, -1); + + return thd; +} + +void mpp_sthd_put(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + mpp_assert(impl); + mpp_assert(impl->ctx.thd == impl); + mpp_assert(impl->status == MPP_STHD_UNINITED || impl->status == MPP_STHD_READY); + + mpp_sthd_deinit(impl); + + mpp_free(impl); +} + +MppSThdStatus mpp_sthd_get_status(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + return impl->status; +} + +const char* mpp_sthd_get_name(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + return impl->name; +} + +rk_s32 mpp_sthd_get_idx(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + return impl->idx; +} + +rk_s32 mpp_sthd_check(MppSThd thd) +{ + return CHECK_STHD(thd); +} + +void mpp_sthd_setup(MppSThd thd, MppSThdFunc func, void *ctx) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + MppSThdStatus status; + + CHECK_STHD(impl); + + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_UNINITED : + case MPP_STHD_READY : { + impl->func = func; + impl->ctx.ctx = ctx; + impl->status = func ? MPP_STHD_READY : MPP_STHD_UNINITED; + } break; + default : { + mpp_err("%s can NOT setup on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); + + CHECK_STHD(impl); +} + +void mpp_sthd_start(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + MppSThdStatus status; + + CHECK_STHD(impl); + + /* we can only change callback function on uninit */ + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_READY : { + mpp_sthd_create(impl); + } break; + default : { + mpp_err("%s can NOT start on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); + + CHECK_STHD(impl); +} + +void mpp_sthd_stop(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + MppSThdStatus status; + + CHECK_STHD(impl); + + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_RUNNING : + case MPP_STHD_WAITING : { + impl->status = MPP_STHD_STOPPING; + pthread_cond_signal(&impl->cond); + } break; + default : { + mpp_err("%s can NOT stop on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); + + CHECK_STHD(impl); +} + +void mpp_sthd_stop_sync(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + MppSThdStatus status; + + CHECK_STHD(impl); + + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_STOPPING : { + void *dummy; + + pthread_join(impl->thd, &dummy); + impl->status = MPP_STHD_READY; + } break; + default : { + mpp_err("%s can NOT stop on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); + + CHECK_STHD(impl); +} + +void mpp_sthd_lock(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + pthread_mutex_lock(&impl->lock); +} + +void mpp_sthd_unlock(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + pthread_mutex_unlock(&impl->lock); +} + +int mpp_sthd_trylock(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + return pthread_mutex_trylock(&impl->lock); +} + +void mpp_sthd_wait(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + if (impl->status == MPP_STHD_RUNNING) + impl->status = MPP_STHD_WAITING; + + pthread_cond_wait(&impl->cond, &impl->lock); + + if (impl->status == MPP_STHD_WAITING) + impl->status = MPP_STHD_RUNNING; +} + +void mpp_sthd_signal(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + pthread_cond_signal(&impl->cond); +} + +void mpp_sthd_broadcast(MppSThd thd) +{ + MppSThdImpl *impl = (MppSThdImpl *)thd; + + CHECK_STHD(impl); + + pthread_cond_broadcast(&impl->cond); +} + +MppSThdGrp mpp_sthd_grp_get(const char *name, rk_s32 count) +{ + MppSThdGrpImpl *grp = NULL; + + if (count > 0) { + rk_s32 elem_size = MPP_ALIGN(sizeof(MppSThdImpl), 8); + rk_s32 total_size = MPP_ALIGN(sizeof(MppSThdGrpImpl), 8) + count * elem_size; + + grp = mpp_calloc_size(MppSThdGrpImpl, total_size); + if (grp) { + pthread_mutexattr_t attr; + rk_s32 i; + + if (!name) + name = "mpp_sthd_grp"; + + snprintf(grp->name, THREAD_NAME_LEN - 1, "%s", name); + + grp->count = count; + for (i = 0; i < count; i++) { + MppSThdImpl *thd = &grp->thds[i]; + + thd->name = grp->name; + mpp_sthd_init(thd, i); + } + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&grp->lock, &attr); + pthread_mutexattr_destroy(&attr); + } + } + + if (!grp) + mpp_err_f("can NOT create %d threads group\n", count); + + return grp; +} + +void mpp_sthd_grp_put(MppSThdGrp grp) +{ + MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp; + rk_s32 i; + + mpp_assert(impl); + mpp_assert(impl->status == MPP_STHD_UNINITED || impl->status == MPP_STHD_READY); + + for (i = 0; i < impl->count; i++) { + MppSThdImpl *thd = &impl->thds[i]; + + mpp_sthd_deinit(thd); + } + + mpp_free(impl); +} + +void mpp_sthd_grp_setup(MppSThdGrp grp, MppSThdFunc func, void *ctx) +{ + MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp; + MppSThdStatus status; + + mpp_assert(impl); + + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_UNINITED : + case MPP_STHD_READY : { + MppSThdStatus next = func ? MPP_STHD_READY : MPP_STHD_UNINITED; + rk_s32 i; + + for (i = 0; i < impl->count; i++) { + MppSThdImpl *thd = &impl->thds[i]; + + thd->func = func; + thd->ctx.ctx = ctx; + thd->status = next; + } + impl->status = next; + } break; + default : { + mpp_err("%s can NOT setup on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); +} + +void mpp_sthd_grp_start(MppSThdGrp grp) +{ + MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp; + MppSThdStatus status; + + mpp_assert(impl); + + /* we can only change callback function on uninit */ + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_READY : { + rk_s32 i; + + for (i = 0; i < impl->count; i++) + mpp_sthd_start(&impl->thds[i]); + + impl->status = MPP_STHD_RUNNING; + } break; + default : { + mpp_err("%s can NOT start on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); +} + +void mpp_sthd_grp_stop(MppSThdGrp grp) +{ + MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp; + MppSThdStatus status; + + mpp_assert(impl); + + /* we can only change callback function on uninit */ + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_RUNNING : + case MPP_STHD_WAITING : { + rk_s32 i; + + impl->status = MPP_STHD_STOPPING; + + for (i = 0; i < impl->count; i++) { + MppSThdImpl *thd = &impl->thds[i]; + + pthread_mutex_lock(&thd->lock); + thd->status = MPP_STHD_STOPPING; + pthread_cond_signal(&thd->cond); + pthread_mutex_unlock(&thd->lock); + } + } break; + default : { + mpp_err("%s can NOT stop on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); +} + +void mpp_sthd_grp_stop_sync(MppSThdGrp grp) +{ + MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp; + MppSThdStatus status; + + mpp_assert(impl); + + /* we can only change callback function on uninit */ + pthread_mutex_lock(&impl->lock); + status = impl->status; + switch (status) { + case MPP_STHD_STOPPING : { + void *dummy; + rk_s32 i; + + status = MPP_STHD_STOPPING; + for (i = 0; i < impl->count; i++) { + MppSThdImpl *thd = &impl->thds[i]; + + pthread_join(thd->thd, &dummy); + thd->status = MPP_STHD_READY; + } + impl->status = MPP_STHD_READY; + } break; + default : { + mpp_err("%s can NOT stop sync on %s\n", impl->name, state2str(status)); + } break; + } + pthread_mutex_unlock(&impl->lock); +} + +MppSThd mpp_sthd_grp_get_each(MppSThdGrp grp, rk_s32 idx) +{ + MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp; + MppSThd ret = NULL; + + mpp_assert(impl); + mpp_assert(idx >= 0 && idx < impl->count); + + pthread_mutex_lock(&impl->lock); + ret = &impl->thds[idx]; + pthread_mutex_unlock(&impl->lock); + + return ret; +} \ No newline at end of file diff --git a/osal/mpp_thread.cpp b/osal/mpp_thread.cpp deleted file mode 100644 index 359874522..000000000 --- a/osal/mpp_thread.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_thread" - -#include "mpp_log.h" -#include "mpp_thread.h" - -#define MPP_THREAD_DBG_FUNCTION (0x00000001) - -static RK_U32 thread_debug = 0; - -#define thread_dbg(flag, fmt, ...) _mpp_dbg(thread_debug, flag, fmt, ## __VA_ARGS__) - -MppThread::MppThread(MppThreadFunc func, void *ctx) - : mStatus(MPP_THREAD_UNINITED), - mFunction(func), - mContext(ctx) -{ -} - -MppThreadStatus MppThread::get_status() -{ - return mStatus; -} -void MppThread::set_status(MppThreadStatus status) -{ - mStatus = status; -} - -void MppThread::start() -{ - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - if (MPP_THREAD_UNINITED == mStatus) { - // NOTE: set status here first to avoid unexpected loop quit racing condition - mStatus = MPP_THREAD_RUNNING; - if (0 == pthread_create(&mThread, &attr, mFunction, mContext)) - thread_dbg(MPP_THREAD_DBG_FUNCTION, "mThread %p mContext %p create success\n", - mFunction, mContext); - else - mStatus = MPP_THREAD_UNINITED; - } - pthread_attr_destroy(&attr); -} - -void MppThread::stop() -{ - if (MPP_THREAD_UNINITED != mStatus) { - mStatus = MPP_THREAD_STOPPING; - signal(); - - void *dummy; - pthread_join(mThread, &dummy); - thread_dbg(MPP_THREAD_DBG_FUNCTION, "mThread %p mContext %p destroy success\n", - mFunction, mContext); - - mStatus = MPP_THREAD_UNINITED; - } -} - diff --git a/osal/mpp_time.c b/osal/mpp_time.c new file mode 100644 index 000000000..e05dc20a3 --- /dev/null +++ b/osal/mpp_time.c @@ -0,0 +1,563 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_time" + +#include +#include +#include +#include +#include + +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_thread.h" + +rk_s64 mpp_time(void) +{ + struct timespec time = {0, 0}; + + clock_gettime(CLOCK_MONOTONIC, &time); + return (rk_s64)time.tv_sec * 1000000 + (rk_s64)time.tv_nsec / 1000; +} + +void mpp_time_diff(rk_s64 start, rk_s64 end, rk_s64 limit, const char *fmt) +{ + rk_s64 diff = end - start; + + if (diff >= limit) + sys_dbg(MPP_DBG_TIMING, "%s timing %lld us\n", fmt, diff); +} + +typedef struct MppClockImpl_t { + const char *check; + char name[16]; + rk_u32 enable; + rk_s64 base; + rk_s64 time; + rk_s64 sum; + rk_s64 count; +} MppClockImpl; + +static const char *clock_name = "mpp_clock"; + +MPP_RET check_is_mpp_clock(void *clock) +{ + if (clock && ((MppClockImpl*)clock)->check == clock_name) + return MPP_OK; + + mpp_err_f("pointer %p failed on check\n", clock); + mpp_abort(); + return MPP_NOK; +} + +MppClock mpp_clock_get(const char *name) +{ + MppClockImpl *impl = mpp_calloc(MppClockImpl, 1); + + if (impl) { + impl->check = clock_name; + snprintf(impl->name, sizeof(impl->name) - 1, name, NULL); + } else + mpp_err_f("malloc failed\n"); + + return impl; +} + +void mpp_clock_put(MppClock clk) +{ + if (check_is_mpp_clock(clk)) { + mpp_err_f("invalid clock %p\n", clk); + return; + } + + mpp_free(clk); +} + +void mpp_clock_enable(MppClock clk, rk_u32 enable) +{ + if (check_is_mpp_clock(clk)) { + mpp_err_f("invalid clock %p\n", clk); + } else { + MppClockImpl *p = (MppClockImpl *)clk; + + p->enable = (enable != 0) ? (1) : (0); + } +} + +rk_s64 mpp_clock_start(MppClock clk) +{ + MppClockImpl *p = (MppClockImpl *)clk; + + if (check_is_mpp_clock(p)) { + mpp_err_f("invalid clock %p\n", p); + return 0; + } + + if (!p->enable) + return 0; + + p->base = mpp_time(); + p->time = 0; + return p->base; +} + +rk_s64 mpp_clock_pause(MppClock clk) +{ + MppClockImpl *p = (MppClockImpl *)clk; + rk_s64 time; + + if (check_is_mpp_clock(p)) { + mpp_err_f("invalid clock %p\n", p); + return 0; + } + + if (!p->enable) + return 0; + + time = mpp_time(); + + if (!p->time) { + // first pause after start + p->sum += time - p->base; + p->count++; + } + + p->time = time; + + return p->time - p->base; +} + +rk_s64 mpp_clock_reset(MppClock clk) +{ + MppClockImpl *p = (MppClockImpl *)clk; + + if (check_is_mpp_clock(p)) { + mpp_err_f("invalid clock %p\n", p); + } else { + p->base = 0; + p->time = 0; + p->sum = 0; + p->count = 0; + } + + return 0; +} + +rk_s64 mpp_clock_get_sum(MppClock clk) +{ + MppClockImpl *p = (MppClockImpl *)clk; + + if (check_is_mpp_clock(p)) { + mpp_err_f("invalid clock %p\n", p); + return 0; + } + + return (p->enable != 0) ? (p->sum) : (0); +} + +rk_s64 mpp_clock_get_count(MppClock clk) +{ + MppClockImpl *p = (MppClockImpl *)clk; + + if (check_is_mpp_clock(p)) { + mpp_err_f("invalid clock %p\n", p); + return 0; + } + + return (p->enable != 0) ? (p->count) : (0); +} + +const char *mpp_clock_get_name(MppClock clk) +{ + MppClockImpl *p = (MppClockImpl *)clk; + + if (check_is_mpp_clock(p)) { + mpp_err_f("invalid clock %p\n", p); + return NULL; + } + + return p->name; +} + +typedef struct MppTimerImpl_t { + const char *check; + char name[16]; + + rk_s32 enabled; + rk_s32 initial; + rk_s32 interval; + rk_s32 timer_fd; + rk_s32 epoll_fd; + + MppThread *thd; + MppThreadFunc func; + void *ctx; +} MppTimerImpl; + +static const char *timer_name = "mpp_timer"; + +MPP_RET check_is_mpp_timer(void *timer) +{ + if (timer && ((MppTimerImpl*)timer)->check == timer_name) + return MPP_OK; + + mpp_err_f("pointer %p failed on check\n", timer); + mpp_abort(); + return MPP_NOK; +} + +static void *mpp_timer_thread(void *ctx) +{ + struct itimerspec ts; + MppTimerImpl *impl = (MppTimerImpl *)ctx; + MppThread *thd = impl->thd; + rk_s32 timer_fd = impl->timer_fd; + rk_s32 ret = 0; + + // first expire time + ts.it_value.tv_sec = impl->initial / 1000; + ts.it_value.tv_nsec = (impl->initial % 1000) * 1000; + + // last expire time + ts.it_interval.tv_sec = impl->interval / 1000; + ts.it_interval.tv_nsec = (impl->interval % 1000) * 1000 * 1000; + + ret = timerfd_settime(timer_fd, 0, &ts, NULL); + if (ret < 0) { + mpp_err("timerfd_settime error, Error:[%d:%s]", errno, strerror(errno)); + return NULL; + } + + while (1) { + struct epoll_event events; + rk_s32 fd_cnt; + + if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd, THREAD_WORK)) + break; + + memset(&events, 0, sizeof(events)); + + /* wait epoll event */ + fd_cnt = epoll_wait(impl->epoll_fd, &events, 1, 500); + if (fd_cnt && (events.events & EPOLLIN) && (events.data.fd == timer_fd)) { + rk_u64 exp = 0; + ssize_t cnt = read(timer_fd, &exp, sizeof(exp)); + + mpp_assert(cnt == sizeof(exp)); + impl->func(impl->ctx); + } + } + + return NULL; +} + +MppTimer mpp_timer_get(const char *name) +{ + MppTimerImpl *impl = NULL; + rk_s32 timer_fd = -1; + rk_s32 epoll_fd = -1; + + do { + struct epoll_event event; + + impl = mpp_calloc(MppTimerImpl, 1); + if (!impl) { + mpp_err_f("malloc failed\n"); + break; + } + + timer_fd = timerfd_create(CLOCK_REALTIME, 0); + if (timer_fd < 0) + break; + + epoll_fd = epoll_create(1); + if (epoll_fd < 0) + break; + + memset(&event, 0, sizeof(event)); + event.data.fd = timer_fd; + event.events = EPOLLIN | EPOLLET; + + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &event) < 0) + break; + + impl->timer_fd = timer_fd; + impl->epoll_fd = epoll_fd; + /* default 1 second (1000ms) looper */ + impl->initial = 1000; + impl->interval = 1000; + impl->check = timer_name; + snprintf(impl->name, sizeof(impl->name) - 1, name, NULL); + + return impl; + } while (0); + + mpp_err_f("failed to create timer\n"); + + if (impl) { + mpp_free(impl); + impl = NULL; + } + + if (timer_fd >= 0) { + close(timer_fd); + timer_fd = -1; + } + + if (epoll_fd >= 0) { + close(epoll_fd); + epoll_fd = -1; + } + + return NULL; +} + +void mpp_timer_set_callback(MppTimer timer, MppThreadFunc func, void *ctx) +{ + MppTimerImpl *impl = (MppTimerImpl *)timer; + + if (check_is_mpp_timer(impl)) { + mpp_err_f("invalid timer %p\n", impl); + return; + } + + if (!func) { + mpp_err_f("invalid NULL callback\n"); + return; + } + + impl->func = func; + impl->ctx = ctx; +} + +void mpp_timer_set_timing(MppTimer timer, rk_s32 initial, rk_s32 interval) +{ + MppTimerImpl *impl = (MppTimerImpl *)timer; + + if (check_is_mpp_timer(impl)) { + mpp_err_f("invalid timer %p\n", impl); + return; + } + + impl->initial = initial; + impl->interval = interval; +} + +void mpp_timer_set_enable(MppTimer timer, rk_s32 enable) +{ + MppTimerImpl *impl = (MppTimerImpl *)timer; + + if (check_is_mpp_timer(impl)) { + mpp_err_f("invalid timer %p\n", impl); + return; + } + + if (!impl->func || impl->initial < 0 || impl->interval < 0) { + mpp_err_f("invalid func %p initial %d interval %d\n", + impl->func, impl->initial, impl->interval); + return; + } + + if (enable) { + if (!impl->enabled && !impl->thd) { + MppThread *thd = mpp_thread_create(mpp_timer_thread, impl, impl->name); + + if (thd) { + impl->thd = thd; + impl->enabled = 1; + mpp_thread_start(impl->thd); + } + } + } else { + if (impl->enabled && impl->thd) { + mpp_thread_stop(impl->thd); + impl->enabled = 0; + } + } +} + +void mpp_timer_put(MppTimer timer) +{ + MppTimerImpl *impl = (MppTimerImpl *)timer; + + if (check_is_mpp_timer(impl)) { + mpp_err_f("invalid timer %p\n", impl); + return; + } + + if (impl->enabled) + mpp_timer_set_enable(impl, 0); + + if (impl->timer_fd >= 0) { + close(impl->timer_fd); + impl->timer_fd = -1; + } + + if (impl->epoll_fd >= 0) { + close(impl->epoll_fd); + impl->epoll_fd = -1; + } + + if (impl->thd) { + mpp_thread_destroy(impl->thd); + impl->thd = NULL; + } + + if (impl) { + mpp_free(impl); + impl = NULL; + } +} + +#define STOPWATCH_TRACE_STR_LEN 64 + +typedef struct MppStopwatchNode_t { + char event[STOPWATCH_TRACE_STR_LEN]; + rk_s64 time; +} MppStopwatchNode; + +typedef struct MppStopwatchImpl_t { + const char *check; + char name[STOPWATCH_TRACE_STR_LEN]; + + rk_s32 max_count; + rk_s32 filled_count; + rk_s32 show_on_exit; + rk_s32 log_len; + rk_s64 time_elipsed; + + MppStopwatchNode *nodes; +} MppStopwatchImpl; + +static const char *stopwatch_name = "mpp_stopwatch"; + +MPP_RET check_is_mpp_stopwatch(void *stopwatch) +{ + if (stopwatch && ((MppStopwatchImpl*)stopwatch)->check == stopwatch_name) + return MPP_OK; + + mpp_err_f("pointer %p failed on check\n", stopwatch); + mpp_abort(); + return MPP_NOK; +} + +MppStopwatch mpp_stopwatch_get(const char *name) +{ + MppStopwatchImpl *impl = mpp_calloc(MppStopwatchImpl, 1); + MppStopwatchNode *nodes = mpp_calloc(MppStopwatchNode, 8); + + if (impl && nodes) { + impl->check = stopwatch_name; + snprintf(impl->name, sizeof(impl->name) - 1, name, NULL); + impl->nodes = nodes; + impl->max_count = 8; + } else { + mpp_err_f("malloc failed\n"); + MPP_FREE(impl); + MPP_FREE(nodes); + } + + return impl; +} + +void mpp_stopwatch_set_show_on_exit(MppStopwatch stopwatch, rk_s32 show_on_exit) +{ + MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch; + + if (check_is_mpp_stopwatch(impl)) { + mpp_err_f("invalid stopwatch %p\n", impl); + return; + } + + impl->show_on_exit = show_on_exit; +} + +void mpp_stopwatch_record(MppStopwatch stopwatch, const char *event) +{ + MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch; + + /* do not print noisy log */ + if (!impl) + return; + + if (check_is_mpp_stopwatch(impl)) { + mpp_err_f("invalid stopwatch %p on %s\n", impl, event); + return; + } + + if (impl->filled_count >= impl->max_count) { + rk_s32 max_count = impl->max_count * 2; + MppStopwatchNode *nodes = mpp_realloc(impl->nodes, MppStopwatchNode, + max_count); + + if (nodes) { + impl->nodes = nodes; + impl->max_count = max_count; + } + } + + if (impl->filled_count < impl->max_count) { + MppStopwatchNode *node = impl->nodes + impl->filled_count; + + node->time = mpp_time(); + if (event) { + rk_s32 len = snprintf(node->event, sizeof(node->event) - 1, "%s", event); + + if (len > impl->log_len) + impl->log_len = len; + } + impl->filled_count++; + } +} + +void mpp_stopwatch_put(MppStopwatch stopwatch) +{ + MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch; + + if (check_is_mpp_stopwatch(impl)) { + mpp_err_f("invalid stopwatch %p\n", impl); + return; + } + + if (impl->show_on_exit && impl->nodes && impl->filled_count) { + MppStopwatchNode *node = impl->nodes; + rk_s64 last_time = node->time; + rk_s32 i; + char fmt[32]; + + snprintf(fmt, sizeof(fmt) - 1, "%%s %%-%ds: %%6.2f\n", impl->log_len); + node++; + + for (i = 1; i < impl->filled_count; i++) { + mpp_log(fmt, impl->name, node->event, + (float)(node->time - last_time) / 1000); + last_time = node->time; + node++; + } + } + MPP_FREE(impl->nodes); + MPP_FREE(impl); +} + +rk_s64 mpp_stopwatch_elapsed_time(MppStopwatch stopwatch) +{ + MppStopwatchImpl *impl = (MppStopwatchImpl *)stopwatch; + + if (check_is_mpp_stopwatch(impl)) { + mpp_err_f("invalid stopwatch %p\n", impl); + return 0; + } + + if (impl->filled_count < 2) + return 0; + + rk_s64 base_time = impl->nodes[0].time; + rk_s64 curr_time = impl->nodes[impl->filled_count - 1].time; + rk_s64 elapsed_time = curr_time - base_time; + return elapsed_time; +} diff --git a/osal/mpp_trace.c b/osal/mpp_trace.c new file mode 100644 index 000000000..05b653750 --- /dev/null +++ b/osal/mpp_trace.c @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_trace" + +#include +#include + +#include "mpp_log.h" +#include "mpp_mem.h" +#include "mpp_common.h" +#include "mpp_singleton.h" + +#include "mpp_trace.h" + +#define ATRACE_MESSAGE_LENGTH 256 + +#define get_srv_trace() \ + ({ \ + MppTraceSrv *__tmp; \ + if (!srv_trace) { \ + mpp_trace_srv_init(); \ + } \ + if (srv_trace) { \ + __tmp = srv_trace; \ + } else { \ + mpp_err("mpp trace srv not init at %s : %s\n", __FUNCTION__); \ + __tmp = NULL; \ + } \ + __tmp; \ + }) + +typedef struct MppTraceSrv_t { + const char *name; + rk_s32 fd; +} MppTraceSrv; + +static MppTraceSrv *srv_trace = NULL; + +static void mpp_trace_srv_init() +{ + static const char *ftrace_paths[] = { + "/sys/kernel/debug/tracing/trace_marker", + "/debug/tracing/trace_marker", + "/debugfs/tracing/trace_marker", + }; + MppTraceSrv *srv = srv_trace; + rk_u32 i; + + if (srv) + return; + + srv = mpp_calloc(MppTraceSrv, 1); + if (!srv) { + mpp_err_f("failed to allocate trace service\n"); + return; + } + + srv_trace = srv; + srv->fd = -1; + + for (i = 0; i < MPP_ARRAY_ELEMS(ftrace_paths); i++) { + if (!access(ftrace_paths[i], F_OK)) { + rk_s32 fd = open(ftrace_paths[i], O_WRONLY | O_CLOEXEC); + + if (fd >= 0) { + srv->fd = fd; + srv->name = ftrace_paths[i]; + break; + } + } + } +} + +static void mpp_trace_srv_deinit() +{ + MppTraceSrv *srv = srv_trace; + + if (srv) { + if (srv->fd >= 0) { + close(srv->fd); + srv->fd = -1; + } + mpp_free(srv); + } + + srv_trace = NULL; +} + +static void mpp_trace_write(rk_s32 fd, const char *fmt, ...) +{ + char buf[ATRACE_MESSAGE_LENGTH]; + va_list ap; + rk_s32 len; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf) - 1, fmt, ap); + va_end(ap); + + (void)!write(fd, buf, len); +} + +void mpp_trace_begin(const char* name) +{ + MppTraceSrv *srv = get_srv_trace(); + + if (srv && srv->fd >= 0) + mpp_trace_write(srv->fd, "B|%d|%s", getpid(), name); +} + +void mpp_trace_end(const char* name) +{ + MppTraceSrv *srv = get_srv_trace(); + + if (srv && srv->fd >= 0) + mpp_trace_write(srv->fd, "E|%d|%s", getpid(), name); +} + +void mpp_trace_async_begin(const char* name, rk_s32 cookie) +{ + MppTraceSrv *srv = get_srv_trace(); + + if (srv && srv->fd >= 0) + mpp_trace_write(srv->fd, "S|%d|%s|%d", getpid(), name, cookie); +} + +void mpp_trace_async_end(const char* name, rk_s32 cookie) +{ + MppTraceSrv *srv = get_srv_trace(); + + if (srv && srv->fd >= 0) + mpp_trace_write(srv->fd, "F|%d|%s|%d", getpid(), name, cookie); +} + +void mpp_trace_int32(const char* name, rk_s32 value) +{ + MppTraceSrv *srv = get_srv_trace(); + + if (srv && srv->fd >= 0) + mpp_trace_write(srv->fd, "C|%d|%s|%d", getpid(), name, value); +} + +void mpp_trace_int64(const char* name, RK_S64 value) +{ + MppTraceSrv *srv = get_srv_trace(); + + if (srv && srv->fd >= 0) + mpp_trace_write(srv->fd, "C|%d|%s|%lld", getpid(), name, value); +} + +MPP_SINGLETON(MPP_SGLN_TRACE, mpp_trace, mpp_trace_srv_init, mpp_trace_srv_deinit) diff --git a/osal/os_env.h b/osal/os_env.h index 50e5f6fe6..ed6f6e1a4 100644 --- a/osal/os_env.h +++ b/osal/os_env.h @@ -1,37 +1,26 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OS_ENV_H__ -#define __OS_ENV_H__ - -#include "rk_type.h" - -#ifdef __cplusplus -extern "C" { -#endif - -RK_S32 os_get_env_u32(const char *name, RK_U32 *value, RK_U32 default_value); -RK_S32 os_get_env_str(const char *name, char **value, char *default_value); - -RK_S32 os_set_env_u32(const char *name, RK_U32 value); -RK_S32 os_set_env_str(const char *name, char *value); - -#ifdef __cplusplus -} -#endif - -#endif /*__OS_ENV_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef OS_ENV_H +#define OS_ENV_H + +#include "rk_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +RK_S32 os_get_env_u32(const char *name, RK_U32 *value, RK_U32 default_value); +RK_S32 os_get_env_str(const char *name, const char **value, const char *default_value); + +RK_S32 os_set_env_u32(const char *name, RK_U32 value); +RK_S32 os_set_env_str(const char *name, char *value); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_ENV_H */ + diff --git a/osal/os_log.h b/osal/os_log.h index c552eda8b..1ab65c9cd 100644 --- a/osal/os_log.h +++ b/osal/os_log.h @@ -1,39 +1,34 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * all os log function will provide two interface - * os_log and os_err - * os_log for general message - * os_err for error message - */ - -#ifndef __OS_LOG_H__ -#define __OS_LOG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void os_log(const char* tag, const char* msg, va_list list); -void os_err(const char* tag, const char* msg, va_list list); - -#ifdef __cplusplus -} -#endif - -#endif /*__OS_LOG_H__*/ - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +/* + * all os log function will provide two interface + * os_log and os_err + * os_log for general message + * os_err for error message + */ + +#ifndef OS_LOG_H +#define OS_LOG_H + +typedef void (*os_log_callback)(const char* tag, const char* msg, va_list list); + +#ifdef __cplusplus +extern "C" { +#endif + +void os_log_trace(const char* tag, const char* msg, va_list list); +void os_log_debug(const char* tag, const char* msg, va_list list); +void os_log_info (const char* tag, const char* msg, va_list list); +void os_log_warn (const char* tag, const char* msg, va_list list); +void os_log_error(const char* tag, const char* msg, va_list list); +void os_log_fatal(const char* tag, const char* msg, va_list list); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_LOG_H */ + diff --git a/osal/os_mem.h b/osal/os_mem.h index 90022e74d..ed8723806 100644 --- a/osal/os_mem.h +++ b/osal/os_mem.h @@ -1,34 +1,23 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OS_MEM_H__ -#define __OS_MEM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -int os_malloc(void **memptr, size_t alignment, size_t size); -int os_realloc(void *src, void **dst, size_t alignment, size_t size); -void os_free(void *ptr); - -#ifdef __cplusplus -} -#endif - -#endif /*__OS_MEM_H__*/ - - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#ifndef OS_MEM_H +#define OS_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +int os_malloc(void **memptr, size_t alignment, size_t size); +int os_realloc(void *src, void **dst, size_t alignment, size_t size); +void os_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* OS_MEM_H */ + + diff --git a/osal/osal_2str.c b/osal/osal_2str.c new file mode 100644 index 000000000..c615d4187 --- /dev/null +++ b/osal/osal_2str.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#include "osal_2str.h" + +const char *strof_client_type(MppClientType type) +{ + static const char *client_type_name[] = { + /* 0 ~ 3 */ + /* VPU_CLIENT_VDPU1 */ "vdpu1", + /* VPU_CLIENT_VDPU2 */ "vdpu2", + /* VPU_CLIENT_VDPU1_PP */ "vdpu1_pp", + /* VPU_CLIENT_VDPU2_PP */ "vdpu2_pp", + /* 4 ~ 7 */ + /* VPU_CLIENT_AV1DEC */ "av1dec", + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* 8 ~ 11 */ + /* VPU_CLIENT_HEVC_DEC */ "rkhevc", + /* VPU_CLIENT_RKVDEC */ "rkvdec", + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* 12 ~ 15 */ + /* VPU_CLIENT_AVSPLUS_DEC */ "avsd", + /* VPU_CLIENT_JPEG_DEC */ "rkjpegd", + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* 16 ~ 19 */ + /* VPU_CLIENT_RKVENC */ "rkvenc", + /* VPU_CLIENT_VEPU1 */ "vepu1", + /* VPU_CLIENT_VEPU2 */ "vepu2", + /* VPU_CLIENT_VEPU2_JPEG */ "vepu2_jpeg", + /* VPU_CLIENT_JPEG_ENC */ "rkjpege", + /* 21 ~ 23 */ + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* 24 ~ 27 */ + /* VPU_CLIENT_VEPU22 */ "vepu22", + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* 28 ~ 31 */ + /* IEP_CLIENT_TYPE */ "iep", + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + /* VPU_CLIENT_BUTT */ NULL, + }; + + if (type < 0 || type >= VPU_CLIENT_BUTT) + return NULL; + + return client_type_name[type]; +} diff --git a/osal/test/CMakeLists.txt b/osal/test/CMakeLists.txt index 4411ca8ba..f545b6b56 100644 --- a/osal/test/CMakeLists.txt +++ b/osal/test/CMakeLists.txt @@ -10,12 +10,11 @@ macro(add_mpp_osal_test module) #message(STATUS "test_name : ${test_name}") #message(STATUS "test_tag : ${test_tag}") - option(${test_tag} "Build osal ${module} unit test" ON) + option(${test_tag} "Build osal ${module} unit test" ${BUILD_TEST}) if(${test_tag}) add_executable(${test_name} ${test_name}.c) - target_link_libraries(${test_name} osal) + target_link_libraries(${test_name} ${MPP_SHARED}) set_target_properties(${test_name} PROPERTIES FOLDER "osal/test") - install(TARGETS ${test_name} RUNTIME DESTINATION ${TEST_INSTALL_DIR}) add_test(NAME ${test_name} COMMAND ${test_name}) endif() endmacro() @@ -26,9 +25,32 @@ add_mpp_osal_test(mpp_log) # env system unit test add_mpp_osal_test(mpp_env) +# dmabuf system unit test +add_mpp_osal_test(mpp_dmabuf) + # malloc system unit test add_mpp_osal_test(mpp_mem) +# mpp_mem_pool unit test +add_mpp_osal_test(mpp_mem_pool) + +# time system unit test +add_mpp_osal_test(mpp_time) + +# trace system unit test +add_mpp_osal_test(mpp_trace) + +# hardware platform feature detection unit test +add_mpp_osal_test(mpp_platform) + +# software runtime feature detection unit test +add_mpp_osal_test(mpp_runtime) + # thread implement unit test add_mpp_osal_test(mpp_thread) +# eventfd implement unit test +add_mpp_osal_test(mpp_eventfd) + +# ring buffer unit test +add_mpp_osal_test(mpp_ring) diff --git a/osal/test/mpp_dmabuf_test.c b/osal/test/mpp_dmabuf_test.c new file mode 100644 index 000000000..f50f3cbb9 --- /dev/null +++ b/osal/test/mpp_dmabuf_test.c @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_dmabuf_test" + +#include +#include + +#include "mpp_log.h" +#include "mpp_buffer.h" +#include "mpp_common.h" +#include "mpp_dmabuf.h" + +int main(void) +{ + MppBufferGroup grp = NULL; + MppBuffer buf = NULL; + RK_S32 fd = -1; + RK_U8 *ptr = NULL; + MPP_RET ret = MPP_NOK; + + mpp_logi("mpp dmabuf test start\n"); + + do { + ret = mpp_buffer_group_get_internal(&grp, MPP_BUFFER_TYPE_DMA_HEAP | MPP_BUFFER_FLAGS_CACHABLE); + if (ret) { + mpp_loge("get dmaheap buffer group failed ret %d\n", ret); + break; + } + + ret = mpp_buffer_get(grp, &buf, SZ_1M); + if (ret) { + mpp_loge("get 1M dmaheap buffer failed ret %d\n", ret); + break; + } + + fd = mpp_buffer_get_fd(buf); + ptr = mpp_buffer_get_ptr(buf); + + ret = mpp_dmabuf_sync_begin(fd, 0, MODULE_TAG); + if (ret) { + mpp_loge("get dmaheap buffer sync begin failed ret %d\n", ret); + break; + } + + ptr[0] = 'a'; + ptr[1] = 'b'; + ptr[2] = 'c'; + ptr[3] = 'd'; + + mpp_logi("ioctl begin cpu access success\n"); + + ret = mpp_dmabuf_sync_end(fd, 0, MODULE_TAG); + if (ret) { + mpp_loge("get dmaheap buffer sync begin failed ret %d\n", ret); + break; + } + + mpp_logi("ioctl end cpu access success\n"); + + ret = mpp_dmabuf_sync_partial_begin(fd, 0, 0, SZ_512K, MODULE_TAG); + mpp_logi("ioctl begin cpu access partial %s\n", ret ? "failed" : "success"); + + ret = mpp_dmabuf_sync_partial_end(fd, 0, 0, SZ_512K, MODULE_TAG); + mpp_logi("ioctl end cpu access partial %s\n", ret ? "failed" : "success"); + + ret = mpp_dmabuf_set_name(fd, "dmabuf_test", MODULE_TAG); + mpp_logi("ioctl set name %s\n", ret ? "failed" : "success"); + + ret = mpp_dmabuf_sync_partial_support(); + mpp_logi("ioctl sync partial %s\n", ret ? "YES" : "NO"); + + ret = MPP_OK; + } while (0); + + if (buf) { + mpp_buffer_put(buf); + buf = NULL; + } + + if (grp) { + mpp_buffer_group_put(grp); + grp = NULL; + } + + mpp_logi("mpp dmabuf test done %s\n", ret ? "failed" : "success"); + + return 0; +} diff --git a/osal/test/mpp_env_test.c b/osal/test/mpp_env_test.c index b4590b3bb..32dfa57f4 100644 --- a/osal/test/mpp_env_test.c +++ b/osal/test/mpp_env_test.c @@ -1,47 +1,36 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_env_test" -#include "mpp_env.h" -#include "mpp_log.h" - -const char env_debug[] = "test_env_debug"; -const char env_string[] = "test_env_string"; -char env_test_string[] = "just for debug"; - -int main() -{ - RK_U32 env_debug_u32 = 0x100; - char *env_string_str = env_test_string; - - mpp_env_set_u32(env_debug, env_debug_u32); - mpp_env_set_str(env_string, env_string_str); - mpp_log("set env: %s to %u\n", env_debug, env_debug_u32); - mpp_log("set env: %s to %s\n", env_string, env_string_str); - - env_debug_u32 = 0; - env_string_str = NULL; - mpp_log("clear local value to zero\n"); - - mpp_env_get_u32(env_debug, &env_debug_u32, 0); - mpp_env_get_str(env_string, &env_string_str, NULL); - - mpp_log("get env: %s is %u\n", env_debug, env_debug_u32); - mpp_log("get env: %s is %s\n", env_string, env_string_str); - - return 0; -} - +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_env_test" + +#include "mpp_env.h" +#include "mpp_log.h" + +const char env_debug[] = "test_env_debug"; +const char env_string[] = "test_env_string"; +char env_test_string[] = "just for debug"; + +int main(void) +{ + RK_U32 env_debug_u32 = 0x100; + const char *env_str_out = NULL; + + mpp_env_set_u32(env_debug, env_debug_u32); + mpp_env_set_str(env_string, env_test_string); + mpp_log("set env: %s to %u\n", env_debug, env_debug_u32); + mpp_log("set env: %s to %s\n", env_string, env_test_string); + + env_debug_u32 = 0; + mpp_log("start reading env:\n"); + + mpp_env_get_u32(env_debug, &env_debug_u32, 0); + mpp_env_get_str(env_string, &env_str_out, NULL); + + mpp_log("get env: %s is %u\n", env_debug, env_debug_u32); + mpp_log("get env: %s is %s\n", env_string, env_str_out); + + return 0; +} + diff --git a/osal/test/mpp_eventfd_test.c b/osal/test/mpp_eventfd_test.c new file mode 100644 index 000000000..7829f31db --- /dev/null +++ b/osal/test/mpp_eventfd_test.c @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_eventfd_test" + +#include "mpp_log.h" +#include "mpp_time.h" +#include "mpp_common.h" +#include "mpp_thread.h" +#include "mpp_eventfd.h" + +#define WR_VAL 1 +#define RD_VAL 10 + +static RK_S32 data_fd = -1; +static RK_S32 sync_fd = -1; +static RK_U64 wr_val_base = WR_VAL; +static RK_U64 rd_val_base = RD_VAL; +static RK_U64 wr_val = WR_VAL; +static RK_U64 rd_val = RD_VAL; +static RK_S32 wr_ret = -1; +static RK_S32 rd_ret = -1; +static RK_S64 wr_timeout = -1; +static RK_S64 rd_timeout = -1; + +void reset_test() +{ + wr_val = wr_val_base; + rd_val = rd_val_base; + wr_ret = -1; + rd_ret = -1; + rd_val_base++; + + mpp_eventfd_write(data_fd, 0); + mpp_eventfd_read(data_fd, NULL, 0); + + mpp_log("eventfd test on writing %lld -> %lld\n", wr_val, rd_val); +} + +void *thread_read(void *arg) +{ + (void) arg; + mpp_eventfd_write(sync_fd, 1); + + rd_ret = mpp_eventfd_read(data_fd, &rd_val, rd_timeout); + mpp_log("eventfd read %d timeout %d ret %lld val %lld\n", data_fd, rd_timeout, rd_ret, rd_val); + + return NULL; +} + +int main(void) +{ + pthread_t td; + + mpp_log("eventfd test start\n"); + + data_fd = mpp_eventfd_get(0); + sync_fd = mpp_eventfd_get(0); + + mpp_log("eventfd get data_fd %d sync_fd %d\n", data_fd, sync_fd); + + reset_test(); + rd_timeout = -1; + wr_timeout = 0; + + pthread_create(&td, NULL, thread_read, NULL); + mpp_eventfd_read(sync_fd, NULL, -1); + mpp_log("eventfd write %d val %lld\n", data_fd, wr_val); + wr_ret = mpp_eventfd_write(data_fd, wr_val); + pthread_join(td, NULL); + mpp_log("eventfd block mode test wr: %lld ret %d rd: %lld ret %d - %s\n", + wr_val, wr_ret, rd_val, rd_ret, + (wr_val == rd_val) ? "success" : "failed"); + + reset_test(); + rd_timeout = 0; + wr_timeout = 100; + + pthread_create(&td, NULL, thread_read, NULL); + mpp_eventfd_read(sync_fd, NULL, -1); + msleep(wr_timeout); + mpp_log("eventfd write %d val %lld\n", data_fd, wr_val); + wr_ret = mpp_eventfd_write(data_fd, wr_val); + pthread_join(td, NULL); + mpp_log("eventfd non-block mode test wr: %lld ret %d rd: %lld ret %d - %s\n", + wr_val, wr_ret, rd_val, rd_ret, + (wr_val != rd_val) ? "success" : "failed"); + + reset_test(); + rd_timeout = 100; + wr_timeout = 1; + + pthread_create(&td, NULL, thread_read, NULL); + mpp_eventfd_read(sync_fd, NULL, -1); + msleep(wr_timeout); + mpp_log("eventfd write %d val %lld\n", data_fd, wr_val); + wr_ret = mpp_eventfd_write(data_fd, wr_val); + pthread_join(td, NULL); + mpp_log("eventfd timeout mode test wr: %lld ret %d rd: %lld ret %d - %s\n", + wr_val, wr_ret, rd_val, rd_ret, + (wr_val == rd_val) ? "success" : "failed"); + + reset_test(); + rd_timeout = 1; + wr_timeout = 100; + + pthread_create(&td, NULL, thread_read, NULL); + mpp_eventfd_read(sync_fd, NULL, -1); + msleep(wr_timeout); + mpp_log("eventfd write %d val %lld\n", data_fd, wr_val); + wr_ret = mpp_eventfd_write(data_fd, wr_val); + pthread_join(td, NULL); + mpp_log("eventfd timeout mode test wr: %lld ret %d rd: %lld ret %d - %s\n", + wr_val, wr_ret, rd_val, rd_ret, + (wr_val != rd_val) ? "success" : "failed"); + + mpp_eventfd_put(data_fd); + mpp_eventfd_put(sync_fd); + + mpp_log("eventfd test done\n"); + + return 0; +} + diff --git a/osal/test/mpp_log_test.c b/osal/test/mpp_log_test.c index 7bf4f548e..cc5ae61c4 100644 --- a/osal/test/mpp_log_test.c +++ b/osal/test/mpp_log_test.c @@ -1,54 +1,120 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ /* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. */ #define MODULE_TAG "mpp_log_test" #include "mpp_log.h" -int main() +int main(void) { - RK_U32 flag_dbg = 0x02; - RK_U32 flag_set = 0xffff; - RK_U32 flag_get = 0; - - mpp_err("mpp log test start\n"); - - mpp_err_f("log_f test\n"); - - mpp_log("mpp log flag_set: %08x\n", mpp_log_get_flag()); - - mpp_log("set flag_set to %08x\n", flag_set); - - mpp_log_set_flag(flag_set); + mpp_logi("mpp log test start\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nset log level to MPP_LOG_VERBOSE\n"); + mpp_set_log_level(MPP_LOG_VERBOSE); + + mpp_logf("test mpp_logf\n"); + mpp_loge("test mpp_loge\n"); + mpp_logw("test mpp_logw\n"); + mpp_logi("test mpp_logi\n"); + mpp_logd("test mpp_logd\n"); + mpp_logv("test mpp_logv\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nset log level to MPP_LOG_DEBUG\n"); + mpp_set_log_level(MPP_LOG_DEBUG); + + mpp_logf("test mpp_logf\n"); + mpp_loge("test mpp_loge\n"); + mpp_logw("test mpp_logw\n"); + mpp_logi("test mpp_logi\n"); + mpp_logd("test mpp_logd\n"); + mpp_logv("test mpp_logv\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nset log level to MPP_LOG_INFO\n"); + mpp_set_log_level(MPP_LOG_INFO); + + mpp_logf("test mpp_logf\n"); + mpp_loge("test mpp_loge\n"); + mpp_logw("test mpp_logw\n"); + mpp_logi("test mpp_logi\n"); + mpp_logd("test mpp_logd\n"); + mpp_logv("test mpp_logv\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nset log level to MPP_LOG_WARN\n"); + mpp_set_log_level(MPP_LOG_WARN); + + mpp_logf("test mpp_logf\n"); + mpp_loge("test mpp_loge\n"); + mpp_logw("test mpp_logw\n"); + mpp_logi("test mpp_logi\n"); + mpp_logd("test mpp_logd\n"); + mpp_logv("test mpp_logv\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nset log level to MPP_LOG_ERROR\n"); + mpp_set_log_level(MPP_LOG_ERROR); + + mpp_logf("test mpp_logf\n"); + mpp_loge("test mpp_loge\n"); + mpp_logw("test mpp_logw\n"); + mpp_logi("test mpp_logi\n"); + mpp_logd("test mpp_logd\n"); + mpp_logv("test mpp_logv\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nset log level to MPP_LOG_FATAL\n"); + mpp_set_log_level(MPP_LOG_FATAL); + + mpp_logf("test mpp_logf\n"); + mpp_loge("test mpp_loge\n"); + mpp_logw("test mpp_logw\n"); + mpp_logi("test mpp_logi\n"); + mpp_logd("test mpp_logd\n"); + mpp_logv("test mpp_logv\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nset log level to MPP_LOG_SILENT\n"); + mpp_set_log_level(MPP_LOG_SILENT); + + mpp_logf("test mpp_logf\n"); + mpp_loge("test mpp_loge\n"); + mpp_logw("test mpp_logw\n"); + mpp_logi("test mpp_logi\n"); + mpp_logd("test mpp_logd\n"); + mpp_logv("test mpp_logv\n"); + + mpp_set_log_level(MPP_LOG_INFO); + mpp_logi("\nchange MODULE_TAG to log_test\n"); + +#undef MODULE_TAG +#define MODULE_TAG "log_test" + + mpp_logi("\nlog with tag changed to log_test\n"); + +#undef MODULE_TAG +#define MODULE_TAG "mpp_log_test" - flag_get = mpp_log_get_flag(); + mpp_logi("\ndeprecated function test\n"); - mpp_log("mpp log flag_get: %08x\n", flag_get); + mpp_log("call mpp_log -- info log\n"); + mpp_log_f("call mpp_log_f -- info log with function name\n"); - mpp_assert(flag_set == flag_get); + mpp_log("\n"); - mpp_log("try _mpp_dbg test 0 debug %x, flag %x", flag_get, flag_dbg); - _mpp_dbg(flag_get, flag_dbg, "mpp_dbg printing debug %x, flag %x", flag_get, flag_dbg); + mpp_err("call mpp_err -- error log\n"); + mpp_err_f("call mpp_err_f -- error log with function name\n"); - flag_dbg = 0; + mpp_logi("\ndeprecated function log\n"); - mpp_log("try _mpp_dbg test 0 debug %x, flag %x", flag_get, flag_dbg); - _mpp_dbg(flag_get, flag_dbg, "mpp_dbg printing debug %x, flag %x", flag_get, flag_dbg); + _mpp_log(MODULE_TAG, "log test", "_mpp_log"); + _mpp_err(MODULE_TAG, "log test", "_mpp_err"); - mpp_err("mpp log log test done\n"); + mpp_log("\nmpp log test done\n"); return 0; } diff --git a/osal/test/mpp_mem_pool_test.c b/osal/test/mpp_mem_pool_test.c new file mode 100644 index 000000000..cae6fb124 --- /dev/null +++ b/osal/test/mpp_mem_pool_test.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_mem_pool_test" + +#include + +#include "mpp_log.h" +#include "mpp_mem_pool.h" + +#define MPP_MEM_POOL_TEST_SIZE 1024 +#define MPP_MEM_POOL_TEST_COUNT 20 + +int main(void) +{ + MppMemPool pool = NULL; + size_t size = MPP_MEM_POOL_TEST_SIZE; + void *p [MPP_MEM_POOL_TEST_COUNT]; + rk_u32 i; + + mpp_log("mpp_mem_pool_test start\n"); + + pool = mpp_mem_pool_init_f(MODULE_TAG, size); + if (NULL == pool) { + mpp_err("mpp_mem_pool_test mpp_mem_pool_init failed\n"); + goto mpp_mem_pool_test_failed; + } + + for (i = 0; i < MPP_MEM_POOL_TEST_COUNT; i++) { + p[i] = mpp_mem_pool_get_f(pool); + if (!p[i]) { + mpp_err("mpp_mem_pool_test mpp_mem_pool_get_f failed\n"); + goto mpp_mem_pool_test_failed; + } + } + + for (i = 0; i < MPP_MEM_POOL_TEST_COUNT / 2; i++) { + if (p[i]) { + mpp_mem_pool_put_f(pool, p[i]); + p[i] = NULL; + } + } + + for (i = 0; i < MPP_MEM_POOL_TEST_COUNT / 4; i++) { + p[i] = mpp_mem_pool_get_f(pool); + if (!p[i]) { + mpp_err("mpp_mem_pool_test mpp_mem_pool_get_f failed\n"); + goto mpp_mem_pool_test_failed; + } + } + + for (i = 0; i < MPP_MEM_POOL_TEST_COUNT; i++) { + if (p[i]) { + mpp_mem_pool_put_f(pool, p[i]); + p[i] = NULL; + } + } + + mpp_log("mpp_mem_pool_test success\n"); + return MPP_OK; + +mpp_mem_pool_test_failed: + mpp_log("mpp_mem_pool_test failed\n"); + return MPP_NOK; +} + diff --git a/osal/test/mpp_mem_test.c b/osal/test/mpp_mem_test.c index 9d142dae4..98682bb4c 100644 --- a/osal/test/mpp_mem_test.c +++ b/osal/test/mpp_mem_test.c @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ /* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. */ #define MODULE_TAG "mpp_mem_test" @@ -22,11 +11,10 @@ // TODO: need to add pressure test case and parameter scan case -int main() +int main(void) { void *tmp = NULL; - mpp_env_set_u32("osal_mem_list", 1); tmp = mpp_calloc(int, 100); if (tmp) { mpp_log("calloc success ptr 0x%p\n", tmp); diff --git a/osal/test/mpp_platform_test.c b/osal/test/mpp_platform_test.c new file mode 100644 index 000000000..1551f65a6 --- /dev/null +++ b/osal/test/mpp_platform_test.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_plat_test" + +#include "mpp_log.h" +#include "mpp_platform.h" +#include "vcodec_service.h" + +int main(void) +{ + const char *dev = NULL; + RK_U32 vcodec_type = mpp_get_vcodec_type(); + MppKernelVersion kernel_version = mpp_get_kernel_version(); + MppIoctlVersion ioctl_version = mpp_get_ioctl_version(); + + mpp_log("kernel version: %s\n", + kernel_version == KERNEL_UNKNOWN ? "unknown" : + kernel_version == KERNEL_3_10 ? "3.10" : + kernel_version == KERNEL_4_4 ? "4.4" : + kernel_version == KERNEL_4_19 ? "4.19" : + kernel_version == KERNEL_5_10 ? "5.10" : + kernel_version == KERNEL_6_1 ? "6.1" : + NULL); + mpp_log("ioctl version: %s\n", + ioctl_version == IOCTL_VCODEC_SERVICE ? "vcodec_service" : + ioctl_version == IOCTL_MPP_SERVICE_V1 ? "mpp_service" : + "unknown"); + mpp_log("\n"); + + mpp_log("chip name: %s\n", mpp_get_soc_name()); + mpp_log("\n"); + mpp_log("chip vcodec type %08x\n", vcodec_type); + + if (vcodec_type & (HAVE_VDPU1 | HAVE_VEPU1)) + mpp_log("found vpu1 codec\n"); + + if (vcodec_type & (HAVE_VDPU2 | HAVE_VEPU2)) + mpp_log("found vpu2 codec\n"); + + if (vcodec_type & HAVE_HEVC_DEC) + mpp_log("found rk hevc decoder\n"); + + if (vcodec_type & HAVE_RKVDEC) + mpp_log("found rkvdec decoder\n"); + + if (vcodec_type & HAVE_AVSDEC) + mpp_log("found avs+ decoder\n"); + + if (vcodec_type & HAVE_JPEG_DEC) + mpp_log("found rk jpeg decoder\n"); + + if (vcodec_type & HAVE_JPEG_ENC) + mpp_log("found rk jpeg encoder\n"); + + if (vcodec_type & HAVE_RKVENC) + mpp_log("found rkvenc encoder\n"); + + if (vcodec_type & HAVE_VEPU2) + mpp_log("found vpu2 encoder\n"); + + if (vcodec_type & HAVE_VEPU22) + mpp_log("found h265 stand-alone encoder\n"); + + mpp_log("\n"); + mpp_log("start probing decoder device name:\n"); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingAVC); + mpp_log("H.264 decoder: %s\n", dev); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingHEVC); + mpp_log("H.265 decoder: %s\n", dev); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingMJPEG); + mpp_log("MJPEG decoder: %s\n", dev); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingVP9); + mpp_log("VP9 decoder: %s\n", dev); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_DEC, MPP_VIDEO_CodingAVSPLUS); + mpp_log("avs+ decoder: %s\n", dev); + + mpp_log("\n"); + mpp_log("start probing encoder device name:\n"); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_ENC, MPP_VIDEO_CodingAVC); + mpp_log("H.264 encoder: %s\n", dev); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_ENC, MPP_VIDEO_CodingHEVC); + mpp_log("H.265 encoder: %s\n", dev); + + dev = mpp_get_vcodec_dev_name(MPP_CTX_ENC, MPP_VIDEO_CodingMJPEG); + mpp_log("MJPEG encoder: %s\n", dev); + + mpp_log("mpp platform test done\n"); + + return 0; +} + diff --git a/osal/test/mpp_ring_test.c b/osal/test/mpp_ring_test.c new file mode 100644 index 000000000..58b7eed26 --- /dev/null +++ b/osal/test/mpp_ring_test.c @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2026 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_ring_test" + +#include + +#include "mpp_log.h" +#include "mpp_ring.h" + +static rk_s32 test_ring_ptr(rk_u8 *ptr, rk_s32 size) +{ + mpp_logi("ptr: [0] %02x [%d-1] %02x [%d] %02x [2*%d-1] %02x\n", + ptr[0], size, ptr[size - 1], size, ptr[size], size, ptr[2 * size - 1]); + + if (ptr[0] != ptr[size] || ptr[size - 1] != ptr[2 * size - 1]) { + mpp_loge("failed to get real %d ring buffer\n", size); + return rk_nok; + } + + return rk_ok; +} + +int main(void) +{ + MppRing ring = NULL; + rk_u8 *ptr; + rk_s32 size = 4096; + rk_s32 ret; + + mpp_logi("start\n"); + + do { + ret = mpp_ring_get(&ring, size, MODULE_TAG); + if (ret != rk_ok || ring == NULL) { + mpp_loge("failed to get ring buffer size %d\n", size); + break; + } + + ret = rk_nok; + + ptr = (rk_u8 *)mpp_ring_get_ptr(ring); + if (ptr == NULL) { + mpp_loge("failed to get ring buffer ptr\n"); + break; + } + + mpp_logi("ring buffer %p get size %d ptr %p\n", ring, size, ptr); + + mpp_logi("memset ptr 0 ~ size to 1\n"); + memset(ptr, 1, size); + + if (test_ring_ptr(ptr, size) != rk_ok) { + mpp_loge("failed to get real %d ring buffer\n", size); + break; + } + + mpp_logi("memset ptr %d ~ 2*%d to 2\n", size, size); + memset(ptr + size, 2, size); + + if (test_ring_ptr(ptr, size) != rk_ok) { + mpp_loge("failed to get real %d ring buffer\n", size); + break; + } + + mpp_logi("resize ring buffer size %d -> %d\n", size, size * 2); + + size *= 2; + ptr = mpp_ring_resize(ring, size); + + mpp_logi("resize ring buffer size %d ptr %p\n", size, ptr); + + mpp_logi("memset ptr 0 ~ %d-1 to 3\n", size); + memset(ptr, 3, size); + + if (test_ring_ptr(ptr, size) != rk_ok) { + mpp_loge("failed to get real %d ring buffer\n", size); + break; + } + + mpp_logi("memset ptr %d ~ 2*%d to 4\n", size, size); + memset(ptr + size, 4, size); + + if (test_ring_ptr(ptr, size) != rk_ok) { + mpp_loge("failed to get real %d ring buffer\n", size); + break; + } + + ret = mpp_ring_put(ring); + ring = NULL; + } while (0); + + mpp_logi("done %s\n", ret == 0 ? "ok" : "failed"); + + if (ring) { + mpp_ring_put(ring); + ring = NULL; + } + + return ret; +} diff --git a/osal/test/mpp_runtime_test.c b/osal/test/mpp_runtime_test.c new file mode 100644 index 000000000..e550f6308 --- /dev/null +++ b/osal/test/mpp_runtime_test.c @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_rt_test" + +#include +#include +#include +#include + +#ifdef __GLIBC__ +#include +#endif + +#ifdef __ANDROID__ +#include +#include +#endif + +#if defined(__USE_XOPEN2K) || (defined(__ANDROID__) && __ANDROID_API__ >= 21) +#define COND_USE_CLOCK_MONOTONIC +#endif + +#include "mpp_log.h" +#include "mpp_runtime.h" + +clockid_t clock_id = CLOCK_REALTIME; + +rk_s32 allocator_check() +{ + if (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION)) + mpp_logi("mpp found ion buffer is valid\n"); + else + mpp_logi("mpp found ion buffer is invalid\n"); + + if (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM)) + mpp_logi("mpp found drm buffer is valid\n"); + else + mpp_logi("mpp found drm buffer is invalid\n"); + + return MPP_OK; +} + +#if defined(__ANDROID__) +// Android OS +int os_check() +{ + char version_str[PROP_VALUE_MAX]; + char sdk_str[PROP_VALUE_MAX]; + rk_u32 sdk_api_level = 0; + + mpp_logi("Compiled for Android System.\n"); + + __system_property_get("ro.build.version.sdk", sdk_str); + __system_property_get("ro.build.version.release", version_str); + sdk_api_level = atoi(sdk_str); + + mpp_logi("Running on Android %s, api level %d, program compiled with api level %d.\n", + version_str, sdk_api_level, __ANDROID_API__); + + if (sdk_api_level < __ANDROID_API__) + mpp_logi("Warning!!! Target is compiled for a higher api level than current system.\n"); + + // check libc +#if defined(__BIONIC__) + mpp_logi("Using bionic libc.\n"); +#else + mpp_logi("Unknown libc.\n"); +#endif // __BIONIC__ + +// POSIX C compatibility test + if (__ANDROID_API__ >= 21) { + clock_id = CLOCK_MONOTONIC; + mpp_logi("pthread_condattr_setclock is defined.\n"); + + if (__ANDROID_API__ >= 30) + mpp_logi("pthread_cond_clockwait is defined.\n"); + else + mpp_logi("pthread_cond_clockwait is not defined.\n"); + } else { + mpp_logi("pthread_condattr_setclock is not defined.\n"); + } + + return 0; +} + +#else + +// Linux OS +int os_check() +{ +#if defined(linux) && !defined(__ANDROID__) + mpp_logi("Compiled for Linux.\n"); +#else + mpp_logi("Compiled for Unknown OS.\n"); +#endif // OS check + + // check libc +#if defined(__GLIBC__) + mpp_logi("Compiled with glibc %d-%d, running with glibc %s.\n", __GLIBC__, __GLIBC_MINOR__, gnu_get_libc_version()); +#elif defined(__UCLIBC__) + mpp_logi("Using uClibc.\n"); +#if defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) && defined(__UCLIBC_SUBLEVEL__) + mpp_logi("Compiled with uClibc version: %d.%d.%d.\n", + __UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__); +#else + mpp_logi("uClibc version macros not available.\n"); +#endif + mpp_logi("pthread_cond_clockwait is not defined.\n"); +#elif defined(__MUSL__) + mpp_logi("Using musl libc.\n"); +#else + mpp_logi("Unknown libc.\n"); +#endif // LIBC check + +// POSIX C compatibility test +#if defined(__USE_XOPEN2K) + clock_id = CLOCK_MONOTONIC; + mpp_logi("XPG6 is supported.\n"); + mpp_logi("pthread_condattr_setclock is defined.\n"); +#else + mpp_logi("XPG6 is not supported.\n"); + mpp_logi("pthread_condattr_setclock is not defined.\n"); +#endif // __USE_XOPEN2K + + return 0; +} +#endif // USE_XOPEN2K + +#ifdef COND_USE_CLOCK_MONOTONIC +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond; +rk_u32 condition = 0; + +void *wait_thread() +{ + int ret; + struct timespec ts, ts_s, ts_e; + char time_str[64]; + struct tm *tm_info; + + pthread_mutex_lock(&mutex); + + clock_gettime(CLOCK_MONOTONIC, &ts); + clock_gettime(CLOCK_REALTIME, &ts_s); + + ts.tv_sec += 1; // timeout after 1 sec + tm_info = localtime(&ts_s.tv_sec); + strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info); + + mpp_logi("Current time is: %s.%08ld.\n", time_str, ts_s.tv_nsec); + mpp_logi("Thread is waiting at monotonic time: %ld sec %ld nsec, will be timeout after 1 sec.\n", + ts.tv_sec, ts.tv_nsec); + + while (!condition) { + ret = pthread_cond_timedwait(&cond, &mutex, &ts); + + if (ret == ETIMEDOUT) { + clock_gettime(CLOCK_REALTIME, &ts_e); + tm_info = localtime(&ts_e.tv_sec); + strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info); + + mpp_logi("Timeout expired at %s.%09ld.\n", time_str, ts_e.tv_nsec); + + if ((ts_e.tv_sec - ts_s.tv_sec) != 1) + mpp_loge("Error! Timeout expired too soon or too late.\n"); + else + mpp_logi("pthrad_cond_timedwait is reliable when using CLOCK_MONOTONIC\n"); + + pthread_mutex_unlock(&mutex); + return NULL; + } + } + + mpp_logi("Thread is waked up."); + pthread_mutex_unlock(&mutex); + return NULL; +} + +int check_pthread_clock() +{ + pthread_condattr_t cond_attr; + pthread_t thread; + + pthread_condattr_init(&cond_attr); + if (pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC)) { + mpp_loge("pthread is not supported with CLOCK_MONOTONIC\n"); + pthread_condattr_destroy(&cond_attr); + pthread_mutex_destroy(&mutex); + return -1; + } + pthread_cond_init(&cond, &cond_attr); + + pthread_create(&thread, NULL, wait_thread, NULL); + pthread_join(thread, NULL); + + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); + pthread_condattr_destroy(&cond_attr); + + return 0; +} +#endif // COND_USE_CLOCK_MONOTONIC + +int main(void) +{ + allocator_check(); + // system compatibility test +#if defined(__LP64__) + mpp_logi("This is 64-bit program.\n"); +#else + mpp_logi("This is 32-bit program.\n"); +#endif // __LP64__ + + os_check(); + +#ifdef COND_USE_CLOCK_MONOTONIC + if (check_pthread_clock()) + mpp_loge("Warning! pthread_cond_timedwait will not be reliable!\n"); +#else + mpp_logi("pthread clock compatibility checking is skipped.\n"); + mpp_loge("Warning! pthread_cond_timedwait will not be reliable!\n"); +#endif // COND_USE_CLOCK_MONOTONIC + + return 0; +} diff --git a/osal/test/mpp_thread_test.c b/osal/test/mpp_thread_test.c index ddf8bd1a5..600691f53 100644 --- a/osal/test/mpp_thread_test.c +++ b/osal/test/mpp_thread_test.c @@ -1,18 +1,6 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ /* - * - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. */ #define MODULE_TAG "mpp_thread_test" @@ -23,13 +11,25 @@ #include "rk_type.h" -#include "mpp_log.h" +#include "mpp_debug.h" #include "mpp_thread.h" #include "mpp_time.h" // TODO: add thread mutex and condition test case #define MAX_THREAD_NUM 10 +#define MAX_LOCK_LOOP 10000 + +static RK_S32 thread_debug = 0; +#define thread_dbg(fmt, ...) mpp_dbg(thread_debug, 1, fmt, ## __VA_ARGS__) + +static pthread_mutex_t mutex_0; +static pthread_mutex_t mutex_1; +static pthread_cond_t cond_0; +static pthread_cond_t cond_1; +static volatile RK_S32 flag_0 = 1; +static volatile RK_S32 flag_1 = 1; + void *thread_test(void *pdata) { int idx = *((int*)pdata); @@ -39,13 +39,95 @@ void *thread_test(void *pdata) return NULL; } -int main() +void* mutex_performance_test_loop_0(void *arg) +{ + RK_S32 i = 0; + + for (i = 0; i < MAX_LOCK_LOOP; i++) { + thread_dbg("0 %5d lock\n", i); + pthread_mutex_lock(&mutex_0); + + thread_dbg("0 %5d wait flag %d\n", i, flag_0); + if (flag_0) { + pthread_cond_wait(&cond_0, &mutex_0); + } + + thread_dbg("0 %5d signal\n", i); + pthread_mutex_lock(&mutex_1); + flag_1 = 0; + pthread_cond_signal(&cond_1); + pthread_mutex_unlock(&mutex_1); + + thread_dbg("0 %5d unlock\n", i); + flag_0 = 1; + pthread_mutex_unlock(&mutex_0); + } + (void)arg; + return NULL; +} + +void *mutex_performance_test_loop_1(void *arg) +{ + RK_S32 i = 0; + + for (i = 0; i < MAX_LOCK_LOOP; i++) { + thread_dbg("1 %5d lock\n", i); + pthread_mutex_lock(&mutex_1); + + thread_dbg("1 %5d wait flag %d\n", i, flag_1); + if (flag_1) { + pthread_cond_wait(&cond_1, &mutex_1); + } + + thread_dbg("1 %5d signal\n", i); + pthread_mutex_lock(&mutex_0); + flag_0 = 0; + pthread_cond_signal(&cond_0); + pthread_mutex_unlock(&mutex_0); + + thread_dbg("1 %5d unlock\n", i); + flag_1 = 1; + pthread_mutex_unlock(&mutex_1); + } + (void)arg; + return NULL; +} + +void mutex_performance_test_once(void) +{ + pthread_mutexattr_t attr; + pthread_mutex_t mutex; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&mutex, &attr); + pthread_mutexattr_destroy(&attr); + + pthread_mutex_lock(&mutex); + pthread_mutex_unlock(&mutex); + + pthread_mutex_lock(&mutex); + pthread_mutex_unlock(&mutex); + + pthread_mutex_lock(&mutex); + pthread_mutex_unlock(&mutex); + + pthread_mutex_lock(&mutex); + pthread_mutex_unlock(&mutex); + + pthread_mutex_destroy(&mutex); +} + +int main(void) { int i; int pdata[MAX_THREAD_NUM]; pthread_t threads[MAX_THREAD_NUM]; pthread_attr_t attr; + pthread_mutexattr_t mutex_attr; void *dummy; + RK_S64 time_start, time_end; mpp_log("vpu test start\n"); pthread_attr_init(&attr); @@ -55,7 +137,6 @@ int main() pdata[i] = i; pthread_create(&threads[i], &attr, thread_test, &pdata[i]); } - pthread_attr_destroy(&attr); sleep(2); @@ -63,6 +144,40 @@ int main() pthread_join(threads[i], &dummy); } + mpp_debug = MPP_DBG_TIMING; + time_start = mpp_time(); + + for (i = 0; i < MAX_LOCK_LOOP; i++) + mutex_performance_test_once(); + + time_end = mpp_time(); + mpp_time_diff(time_start, time_end, 0, "lock unlock test"); + + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&mutex_0, &mutex_attr); + pthread_mutex_init(&mutex_1, &mutex_attr); + pthread_cond_init(&cond_0, NULL); + pthread_cond_init(&cond_1, NULL); + pthread_mutexattr_destroy(&mutex_attr); + + time_start = mpp_time(); + pthread_create(&threads[0], &attr, mutex_performance_test_loop_0, NULL); + flag_0 = 0; + pthread_create(&threads[1], &attr, mutex_performance_test_loop_1, NULL); + + pthread_join(threads[0], &dummy); + pthread_join(threads[1], &dummy); + time_end = mpp_time(); + mpp_time_diff(time_start, time_end, 0, "lock and signal test"); + + pthread_cond_destroy(&cond_0); + pthread_cond_destroy(&cond_1); + + pthread_attr_destroy(&attr); + + mpp_debug = 0; mpp_log("vpu test end\n"); return 0; } diff --git a/osal/test/mpp_time_test.c b/osal/test/mpp_time_test.c new file mode 100644 index 000000000..0a7dc7156 --- /dev/null +++ b/osal/test/mpp_time_test.c @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_time_test" + +#include "mpp_log.h" +#include "mpp_time.h" + +void *timer_test(void *param) +{ + static RK_S32 count = 0; + (void) param; + + mpp_log("mpp timer trigger %d\n", count++); + + return NULL; +} + +int main(void) +{ + RK_S64 time_0; + RK_S64 time_1; + MppClock clock; + MppTimer timer; + RK_S32 i; + + mpp_log("mpp time test start\n"); + + time_0 = mpp_time(); + + msleep(10); + + time_1 = mpp_time(); + + mpp_log("time 0 %lld us\n", time_0); + mpp_log("time 1 %lld us\n", time_1); + mpp_log("diff expected 10 ms real %.2f ms\n", (float)(time_1 - time_0) / 1000); + + mpp_log("mpp time test done\n"); + + mpp_log("mpp timer test start\n"); + + timer = mpp_timer_get("test"); + + mpp_timer_set_callback(timer, timer_test, NULL); + mpp_timer_set_timing(timer, 1000, 1000); + mpp_timer_set_enable(timer, 1); + + sleep(2); + + mpp_timer_put(timer); + + mpp_log("mpp timer test done\n"); + + mpp_log("mpp clock test start\n"); + + clock = mpp_clock_get("clock loop test"); + + mpp_clock_enable(clock, 1); + + for (i = 0; i < 1000; i++) { + mpp_clock_start(clock); + msleep(2); + mpp_clock_pause(clock); + } + + mpp_log("loop 1000 times clock 2ms start/pause operation:\n"); + mpp_log("total time %8.3f ms\n", mpp_clock_get_sum(clock) / 1000.0); + mpp_log("average time %8.3f ms\n", + mpp_clock_get_sum(clock) / mpp_clock_get_count(clock) / 1000.0); + + mpp_clock_reset(clock); + + for (i = 0; i < 10000; i++) { + mpp_clock_start(clock); + mpp_time(); + mpp_clock_pause(clock); + } + + mpp_log("mpp_time cost %.3f ms\n", + mpp_clock_get_sum(clock) / mpp_clock_get_count(clock) / 1000.0); + + mpp_clock_reset(clock); + mpp_clock_start(clock); + msleep(20); + time_0 = mpp_clock_pause(clock); + msleep(20); + time_1 = mpp_clock_pause(clock); + + mpp_log("mpp_time pause 0 at %.3f ms pause 1 at %.3f ms\n", + time_0 / 1000.0, time_1 / 1000.0); + + mpp_clock_put(clock); + + mpp_log("mpp time test done\n"); + + return 0; +} diff --git a/osal/test/mpp_trace_test.c b/osal/test/mpp_trace_test.c new file mode 100644 index 000000000..1c150d4f3 --- /dev/null +++ b/osal/test/mpp_trace_test.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_trace_test" + +#include "mpp_log.h" + +#include "mpp_trace.h" + +int main(void) +{ + mpp_log("mpp trace test start\n"); + + mpp_trace_begin("mpp_trace_test"); + mpp_trace_end("mpp_trace_test"); + + mpp_trace_async_begin("mpp_trace_test async", 10); + mpp_trace_async_end("mpp_trace_test async", 10); + + mpp_trace_int32("mpp_trace_test int32", 256); + mpp_trace_int64("mpp_trace_test int64", 100000000); + + mpp_log("mpp trace test done\n"); + + return 0; +} diff --git a/osal/window/os_allocator.c b/osal/window/os_allocator.c deleted file mode 100644 index f21e9fd43..000000000 --- a/osal/window/os_allocator.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "os_mem.h" -#include "os_allocator.h" - -#include "mpp_mem.h" -#include "mpp_log.h" - -/* - * window only support MPP_BUFFER_TYPE_NORMAL - */ - -typedef struct { - size_t alignment; -} allocator_ctx; - -MPP_RET os_allocator_open(void **ctx, size_t alignment) -{ - MPP_RET ret = MPP_OK; - allocator_ctx *p = NULL; - - if (NULL == ctx) { - mpp_err("os_allocator_open Window do not accept NULL input\n"); - return MPP_ERR_NULL_PTR; - } - - p = mpp_malloc(allocator_ctx, 1); - if (NULL == p) { - mpp_err("os_allocator_open Window failed to allocate context\n"); - ret = MPP_ERR_MALLOC; - } else - p->alignment = alignment; - - *ctx = p; - return ret; -} - -MPP_RET os_allocator_alloc(void *ctx, MppBufferInfo *info) -{ - allocator_ctx *p = NULL; - - if (NULL == ctx) { - mpp_err("os_allocator_alloc Window found NULL context input\n"); - return MPP_ERR_NULL_PTR; - } - - p = (allocator_ctx *)ctx; - return (MPP_RET)os_malloc(&info->ptr, p->alignment, info->size); -} - -MPP_RET os_allocator_free(void *ctx, MppBufferInfo *info) -{ - (void) ctx; - if (info->ptr) - os_free(info->ptr); - return MPP_OK; -} - -MPP_RET os_allocator_close(void *ctx) -{ - if (ctx) { - mpp_free(ctx); - return MPP_OK; - } - mpp_err("os_allocator_close Window found NULL context input\n"); - return MPP_NOK; -} - -static os_allocator allocator_window = { - os_allocator_open, - os_allocator_alloc, - os_allocator_free, - os_allocator_close, -}; - -MPP_RET os_allocator_get(os_allocator *api, MppBufferType type) -{ - MPP_RET ret = MPP_OK; - switch (type) { - case MPP_BUFFER_TYPE_NORMAL : - case MPP_BUFFER_TYPE_ION : - case MPP_BUFFER_TYPE_V4L2 : { - *api = allocator_window; - } break; - default : { - ret = MPP_NOK; - } break; - } - return ret; -} - diff --git a/osal/window/os_env.c b/osal/window/os_env.c deleted file mode 100644 index 8aefa580e..000000000 --- a/osal/window/os_env.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include "os_env.h" - -#define ENV_BUF_SIZE_WIN 1024 - -RK_S32 os_get_env_u32(const char *name, RK_U32 *value, RK_U32 default_value) -{ - char *ptr = getenv(name); - if (NULL == ptr) { - *value = default_value; - } else { - char *endptr; - int base = (ptr[0] == '0' && ptr[1] == 'x') ? (16) : (10); - errno = 0; - *value = strtoul(ptr, &endptr, base); - if (errno || (ptr == endptr)) { - errno = 0; - *value = default_value; - } - } - return 0; -} - -RK_S32 os_get_env_str(const char *name, char **value, char *default_value) -{ - *value = getenv(name); - if (NULL == *value) { - *value = default_value; - } - return 0; -} - -RK_S32 os_set_env_u32(const char *name, RK_U32 value) -{ - char buf[ENV_BUF_SIZE_WIN]; - _snprintf(buf, sizeof(buf), "%s=%lu", name, value); - return _putenv(buf); -} - -RK_S32 os_set_env_str(const char *name, char *value) -{ - char buf[ENV_BUF_SIZE_WIN]; - _snprintf(buf, sizeof(buf), "%s=%s", name, value); - return _putenv(buf); -} - - diff --git a/osal/window/os_mem.c b/osal/window/os_mem.c deleted file mode 100644 index f73e01a19..000000000 --- a/osal/window/os_mem.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "os_mem.h" - -int os_malloc(void **memptr, size_t alignment, size_t size) -{ - *memptr = _aligned_malloc(size, alignment); - return (*memptr) ? (0) : (-1); -} - -int os_realloc(void *src, void **dst, size_t alignment, size_t size) -{ - *dst = _aligned_realloc(src, size, alignment); - return (*dst) ? (0) : (-1); -} - -void os_free(void *ptr) -{ - _aligned_free(ptr); -} - diff --git a/osal/window/pthread/dll/x64/pthreadGC2.dll b/osal/window/pthread/dll/x64/pthreadGC2.dll deleted file mode 100644 index 841d4a216..000000000 Binary files a/osal/window/pthread/dll/x64/pthreadGC2.dll and /dev/null differ diff --git a/osal/window/pthread/dll/x64/pthreadVC2.dll b/osal/window/pthread/dll/x64/pthreadVC2.dll deleted file mode 100644 index 165b4d26e..000000000 Binary files a/osal/window/pthread/dll/x64/pthreadVC2.dll and /dev/null differ diff --git a/osal/window/pthread/dll/x86/pthreadGC2.dll b/osal/window/pthread/dll/x86/pthreadGC2.dll deleted file mode 100644 index 67b9289df..000000000 Binary files a/osal/window/pthread/dll/x86/pthreadGC2.dll and /dev/null differ diff --git a/osal/window/pthread/dll/x86/pthreadGCE2.dll b/osal/window/pthread/dll/x86/pthreadGCE2.dll deleted file mode 100644 index 9e18ea24b..000000000 Binary files a/osal/window/pthread/dll/x86/pthreadGCE2.dll and /dev/null differ diff --git a/osal/window/pthread/dll/x86/pthreadVC2.dll b/osal/window/pthread/dll/x86/pthreadVC2.dll deleted file mode 100644 index fcb5d9dcc..000000000 Binary files a/osal/window/pthread/dll/x86/pthreadVC2.dll and /dev/null differ diff --git a/osal/window/pthread/dll/x86/pthreadVCE2.dll b/osal/window/pthread/dll/x86/pthreadVCE2.dll deleted file mode 100644 index 9d148cc0d..000000000 Binary files a/osal/window/pthread/dll/x86/pthreadVCE2.dll and /dev/null differ diff --git a/osal/window/pthread/dll/x86/pthreadVSE2.dll b/osal/window/pthread/dll/x86/pthreadVSE2.dll deleted file mode 100644 index 8129116fd..000000000 Binary files a/osal/window/pthread/dll/x86/pthreadVSE2.dll and /dev/null differ diff --git a/osal/window/pthread/inc/pthread.h b/osal/window/pthread/inc/pthread.h deleted file mode 100644 index 436ea8b6b..000000000 --- a/osal/window/pthread/inc/pthread.h +++ /dev/null @@ -1,1368 +0,0 @@ -/* This is an implementation of the threads API of POSIX 1003.1-2001. - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#if !defined( PTHREAD_H ) -#define PTHREAD_H - -/* - * See the README file for an explanation of the pthreads-win32 version - * numbering scheme and how the DLL is named etc. - */ -#define PTW32_VERSION 2,9,1,0 -#define PTW32_VERSION_STRING "2, 9, 1, 0\0" - -/* There are three implementations of cancel cleanup. - * Note that pthread.h is included in both application - * compilation units and also internally for the library. - * The code here and within the library aims to work - * for all reasonable combinations of environments. - * - * The three implementations are: - * - * WIN32 SEH - * C - * C++ - * - * Please note that exiting a push/pop block via - * "return", "exit", "break", or "continue" will - * lead to different behaviour amongst applications - * depending upon whether the library was built - * using SEH, C++, or C. For example, a library built - * with SEH will call the cleanup routine, while both - * C++ and C built versions will not. - */ - -/* - * Define defaults for cleanup code. - * Note: Unless the build explicitly defines one of the following, then - * we default to standard C style cleanup. This style uses setjmp/longjmp - * in the cancelation and thread exit implementations and therefore won't - * do stack unwinding if linked to applications that have it (e.g. - * C++ apps). This is currently consistent with most/all commercial Unix - * POSIX threads implementations. - */ -#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) -# define __CLEANUP_C -#endif - -#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) -#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. -#endif - -/* - * Stop here if we are being included by the resource compiler. - */ -#if !defined(RC_INVOKED) - -#undef PTW32_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_LEVEL -#define PTW32_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_LEVEL -#define PTW32_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_LEVEL_MAX 3 - -#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL) -#define PTW32_LEVEL PTW32_LEVEL_MAX -/* Include everything */ -#endif - -#if defined(_UWIN) -# define HAVE_STRUCT_TIMESPEC 1 -# define HAVE_SIGNAL_H 1 -# undef HAVE_PTW32_CONFIG_H -# pragma comment(lib, "pthread") -#endif - -/* - * ------------------------------------------------------------- - * - * - * Module: pthread.h - * - * Purpose: - * Provides an implementation of PThreads based upon the - * standard: - * - * POSIX 1003.1-2001 - * and - * The Single Unix Specification version 3 - * - * (these two are equivalent) - * - * in order to enhance code portability between Windows, - * various commercial Unix implementations, and Linux. - * - * See the ANNOUNCE file for a full list of conforming - * routines and defined constants, and a list of missing - * routines and constants not defined in this implementation. - * - * Authors: - * There have been many contributors to this library. - * The initial implementation was contributed by - * John Bossom, and several others have provided major - * sections or revisions of parts of the implementation. - * Often significant effort has been contributed to - * find and fix important bugs and other problems to - * improve the reliability of the library, which sometimes - * is not reflected in the amount of code which changed as - * result. - * As much as possible, the contributors are acknowledged - * in the ChangeLog file in the source code distribution - * where their changes are noted in detail. - * - * Contributors are listed in the CONTRIBUTORS file. - * - * As usual, all bouquets go to the contributors, and all - * brickbats go to the project maintainer. - * - * Maintainer: - * The code base for this project is coordinated and - * eventually pre-tested, packaged, and made available by - * - * Ross Johnson - * - * QA Testers: - * Ultimately, the library is tested in the real world by - * a host of competent and demanding scientists and - * engineers who report bugs and/or provide solutions - * which are then fixed or incorporated into subsequent - * versions of the library. Each time a bug is fixed, a - * test case is written to prove the fix and ensure - * that later changes to the code don't reintroduce the - * same error. The number of test cases is slowly growing - * and therefore so is the code reliability. - * - * Compliance: - * See the file ANNOUNCE for the list of implemented - * and not-implemented routines and defined options. - * Of course, these are all defined is this file as well. - * - * Web site: - * The source code and other information about this library - * are available from - * - * http://sources.redhat.com/pthreads-win32/ - * - * ------------------------------------------------------------- - */ - -/* Try to avoid including windows.h */ -#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus) -#define PTW32_INCLUDE_WINDOWS_H -#endif - -#if defined(PTW32_INCLUDE_WINDOWS_H) -#include -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) -/* - * VC++6.0 or early compiler's header has no DWORD_PTR type. - */ -typedef unsigned long DWORD_PTR; -typedef unsigned long ULONG_PTR; -#endif -/* - * ----------------- - * autoconf switches - * ----------------- - */ - -#if defined(HAVE_PTW32_CONFIG_H) -#include "config.h" -#endif /* HAVE_PTW32_CONFIG_H */ - -#if !defined(NEED_FTIME) -#include -#else /* NEED_FTIME */ -/* use native WIN32 time API */ -#endif /* NEED_FTIME */ - -#if defined(HAVE_SIGNAL_H) -#include -#endif /* HAVE_SIGNAL_H */ - -#include - -/* - * Boolean values to make us independent of system includes. - */ -enum { - PTW32_FALSE = 0, - PTW32_TRUE = (! PTW32_FALSE) -}; - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Several systems don't define some error numbers. - */ -#if !defined(ENOTSUP) -# define ENOTSUP 48 /* This is the value in Solaris. */ -#endif - -#if !defined(ETIMEDOUT) -# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */ -#endif - -#if !defined(ENOSYS) -# define ENOSYS 140 /* Semi-arbitrary value */ -#endif - -#if !defined(EDEADLK) -# if defined(EDEADLOCK) -# define EDEADLK EDEADLOCK -# else -# define EDEADLK 36 /* This is the value in MSVC. */ -# endif -#endif - -/* POSIX 2008 - related to robust mutexes */ -#if !defined(EOWNERDEAD) -# define EOWNERDEAD 43 -#endif -#if !defined(ENOTRECOVERABLE) -# define ENOTRECOVERABLE 44 -#endif - -#include - -/* - * To avoid including windows.h we define only those things that we - * actually need from it. - */ -#if !defined(PTW32_INCLUDE_WINDOWS_H) -#if !defined(HANDLE) -# define PTW32__HANDLE_DEF -# define HANDLE void * -#endif -#if !defined(DWORD) -# define PTW32__DWORD_DEF -# define DWORD unsigned long -#endif -#endif - -#if !defined(HAVE_STRUCT_TIMESPEC) -#define HAVE_STRUCT_TIMESPEC -#if !defined(_TIMESPEC_DEFINED) -#define _TIMESPEC_DEFINED -struct timespec { - time_t tv_sec; - long tv_nsec; -}; -#endif /* _TIMESPEC_DEFINED */ -#endif /* HAVE_STRUCT_TIMESPEC */ - -#if !defined(SIG_BLOCK) -#define SIG_BLOCK 0 -#endif /* SIG_BLOCK */ - -#if !defined(SIG_UNBLOCK) -#define SIG_UNBLOCK 1 -#endif /* SIG_UNBLOCK */ - -#if !defined(SIG_SETMASK) -#define SIG_SETMASK 2 -#endif /* SIG_SETMASK */ - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -/* - * ------------------------------------------------------------- - * - * POSIX 1003.1-2001 Options - * ========================= - * - * Options are normally set in , which is not provided - * with pthreads-win32. - * - * For conformance with the Single Unix Specification (version 3), all of the - * options below are defined, and have a value of either -1 (not supported) - * or 200112L (supported). - * - * These options can neither be left undefined nor have a value of 0, because - * either indicates that sysconf(), which is not implemented, may be used at - * runtime to check the status of the option. - * - * _POSIX_THREADS (== 200112L) - * If == 200112L, you can use threads - * - * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) - * If == 200112L, you can control the size of a thread's - * stack - * pthread_attr_getstacksize - * pthread_attr_setstacksize - * - * _POSIX_THREAD_ATTR_STACKADDR (== -1) - * If == 200112L, you can allocate and control a thread's - * stack. If not supported, the following functions - * will return ENOSYS, indicating they are not - * supported: - * pthread_attr_getstackaddr - * pthread_attr_setstackaddr - * - * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) - * If == 200112L, you can use realtime scheduling. - * This option indicates that the behaviour of some - * implemented functions conforms to the additional TPS - * requirements in the standard. E.g. rwlocks favour - * writers over readers when threads have equal priority. - * - * _POSIX_THREAD_PRIO_INHERIT (== -1) - * If == 200112L, you can create priority inheritance - * mutexes. - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PRIO_PROTECT (== -1) - * If == 200112L, you can create priority ceiling mutexes - * Indicates the availability of: - * pthread_mutex_getprioceiling - * pthread_mutex_setprioceiling - * pthread_mutexattr_getprioceiling - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprioceiling - * pthread_mutexattr_setprotocol + - * - * _POSIX_THREAD_PROCESS_SHARED (== -1) - * If set, you can create mutexes and condition - * variables that can be shared with another - * process.If set, indicates the availability - * of: - * pthread_mutexattr_getpshared - * pthread_mutexattr_setpshared - * pthread_condattr_getpshared - * pthread_condattr_setpshared - * - * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) - * If == 200112L you can use the special *_r library - * functions that provide thread-safe behaviour - * - * _POSIX_READER_WRITER_LOCKS (== 200112L) - * If == 200112L, you can use read/write locks - * - * _POSIX_SPIN_LOCKS (== 200112L) - * If == 200112L, you can use spin locks - * - * _POSIX_BARRIERS (== 200112L) - * If == 200112L, you can use barriers - * - * + These functions provide both 'inherit' and/or - * 'protect' protocol, based upon these macro - * settings. - * - * ------------------------------------------------------------- - */ - -/* - * POSIX Options - */ -#undef _POSIX_THREADS -#define _POSIX_THREADS 200809L - -#undef _POSIX_READER_WRITER_LOCKS -#define _POSIX_READER_WRITER_LOCKS 200809L - -#undef _POSIX_SPIN_LOCKS -#define _POSIX_SPIN_LOCKS 200809L - -#undef _POSIX_BARRIERS -#define _POSIX_BARRIERS 200809L - -#undef _POSIX_THREAD_SAFE_FUNCTIONS -#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L - -#undef _POSIX_THREAD_ATTR_STACKSIZE -#define _POSIX_THREAD_ATTR_STACKSIZE 200809L - -/* - * The following options are not supported - */ -#undef _POSIX_THREAD_ATTR_STACKADDR -#define _POSIX_THREAD_ATTR_STACKADDR -1 - -#undef _POSIX_THREAD_PRIO_INHERIT -#define _POSIX_THREAD_PRIO_INHERIT -1 - -#undef _POSIX_THREAD_PRIO_PROTECT -#define _POSIX_THREAD_PRIO_PROTECT -1 - -/* TPS is not fully supported. */ -#undef _POSIX_THREAD_PRIORITY_SCHEDULING -#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 - -#undef _POSIX_THREAD_PROCESS_SHARED -#define _POSIX_THREAD_PROCESS_SHARED -1 - - -/* - * POSIX 1003.1-2001 Limits - * =========================== - * - * These limits are normally set in , which is not provided with - * pthreads-win32. - * - * PTHREAD_DESTRUCTOR_ITERATIONS - * Maximum number of attempts to destroy - * a thread's thread-specific data on - * termination (must be at least 4) - * - * PTHREAD_KEYS_MAX - * Maximum number of thread-specific data keys - * available per process (must be at least 128) - * - * PTHREAD_STACK_MIN - * Minimum supported stack size for a thread - * - * PTHREAD_THREADS_MAX - * Maximum number of threads supported per - * process (must be at least 64). - * - * SEM_NSEMS_MAX - * The maximum number of semaphores a process can have. - * (must be at least 256) - * - * SEM_VALUE_MAX - * The maximum value a semaphore can have. - * (must be at least 32767) - * - */ -#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 - -#undef PTHREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS - -#undef _POSIX_THREAD_KEYS_MAX -#define _POSIX_THREAD_KEYS_MAX 128 - -#undef PTHREAD_KEYS_MAX -#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX - -#undef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN 0 - -#undef _POSIX_THREAD_THREADS_MAX -#define _POSIX_THREAD_THREADS_MAX 64 - - /* Arbitrary value */ -#undef PTHREAD_THREADS_MAX -#define PTHREAD_THREADS_MAX 2019 - -#undef _POSIX_SEM_NSEMS_MAX -#define _POSIX_SEM_NSEMS_MAX 256 - - /* Arbitrary value */ -#undef SEM_NSEMS_MAX -#define SEM_NSEMS_MAX 1024 - -#undef _POSIX_SEM_VALUE_MAX -#define _POSIX_SEM_VALUE_MAX 32767 - -#undef SEM_VALUE_MAX -#define SEM_VALUE_MAX INT_MAX - - -#if defined(__GNUC__) && !defined(__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * The Open Watcom C/C++ compiler uses a non-standard calling convention - * that passes function args in registers unless __cdecl is explicitly specified - * in exposed function prototypes. - * - * We force all calls to cdecl even though this could slow Watcom code down - * slightly. If you know that the Watcom compiler will be used to build both - * the DLL and application, then you can probably define this as a null string. - * Remember that pthread.h (this file) is used for both the DLL and application builds. - */ -#define PTW32_CDECL __cdecl - -#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX -# include -#else -/* - * Generic handle type - intended to extend uniqueness beyond - * that available with a simple pointer. It should scale for either - * IA-32 or IA-64. - */ -typedef struct { - void * p; /* Pointer to actual object */ - unsigned int x; /* Extra information - reuse count etc */ -} ptw32_handle_t; - -typedef ptw32_handle_t pthread_t; -typedef struct pthread_attr_t_ * pthread_attr_t; -typedef struct pthread_once_t_ pthread_once_t; -typedef struct pthread_key_t_ * pthread_key_t; -typedef struct pthread_mutex_t_ * pthread_mutex_t; -typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; -typedef struct pthread_cond_t_ * pthread_cond_t; -typedef struct pthread_condattr_t_ * pthread_condattr_t; -#endif -typedef struct pthread_rwlock_t_ * pthread_rwlock_t; -typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; -typedef struct pthread_spinlock_t_ * pthread_spinlock_t; -typedef struct pthread_barrier_t_ * pthread_barrier_t; -typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; - -/* - * ==================== - * ==================== - * POSIX Threads - * ==================== - * ==================== - */ - -enum { -/* - * pthread_attr_{get,set}detachstate - */ - PTHREAD_CREATE_JOINABLE = 0, /* Default */ - PTHREAD_CREATE_DETACHED = 1, - -/* - * pthread_attr_{get,set}inheritsched - */ - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1, /* Default */ - -/* - * pthread_{get,set}scope - */ - PTHREAD_SCOPE_PROCESS = 0, - PTHREAD_SCOPE_SYSTEM = 1, /* Default */ - -/* - * pthread_setcancelstate paramters - */ - PTHREAD_CANCEL_ENABLE = 0, /* Default */ - PTHREAD_CANCEL_DISABLE = 1, - -/* - * pthread_setcanceltype parameters - */ - PTHREAD_CANCEL_ASYNCHRONOUS = 0, - PTHREAD_CANCEL_DEFERRED = 1, /* Default */ - -/* - * pthread_mutexattr_{get,set}pshared - * pthread_condattr_{get,set}pshared - */ - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1, - -/* - * pthread_mutexattr_{get,set}robust - */ - PTHREAD_MUTEX_STALLED = 0, /* Default */ - PTHREAD_MUTEX_ROBUST = 1, - -/* - * pthread_barrier_wait - */ - PTHREAD_BARRIER_SERIAL_THREAD = -1 -}; - -/* - * ==================== - * ==================== - * Cancelation - * ==================== - * ==================== - */ -#define PTHREAD_CANCELED ((void *)(size_t) -1) - - -/* - * ==================== - * ==================== - * Once Key - * ==================== - * ==================== - */ -#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} - -struct pthread_once_t_ -{ - int done; /* indicates if user function has been executed */ - void * lock; - int reserved1; - int reserved2; -}; - - -/* - * ==================== - * ==================== - * Object initialisers - * ==================== - * ==================== - */ -#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1) -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2) -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3) - -/* - * Compatibility with LinuxThreads - */ -#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER -#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER - -#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1) - -#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1) - -#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1) - - -/* - * Mutex types. - */ -enum -{ - /* Compatibility with LinuxThreads */ - PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, - /* For compatibility with POSIX */ - PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, - PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL -}; - - -typedef struct ptw32_cleanup_t ptw32_cleanup_t; - -#if defined(_MSC_VER) -/* Disable MSVC 'anachronism used' warning */ -#pragma warning( disable : 4229 ) -#endif - -typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); - -#if defined(_MSC_VER) -#pragma warning( default : 4229 ) -#endif - -struct ptw32_cleanup_t -{ - ptw32_cleanup_callback_t routine; - void *arg; - struct ptw32_cleanup_t *prev; -}; - -#if defined(__CLEANUP_SEH) - /* - * WIN32 SEH version of cancel cleanup. - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ - _cleanup.arg = (_arg); \ - __try \ - { \ - -#define pthread_cleanup_pop( _execute ) \ - } \ - __finally \ - { \ - if( _execute || AbnormalTermination()) \ - { \ - (*(_cleanup.routine))( _cleanup.arg ); \ - } \ - } \ - } - -#else /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_C) - - /* - * C implementation of PThreads cancel cleanup - */ - -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - ptw32_cleanup_t _cleanup; \ - \ - ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ - -#define pthread_cleanup_pop( _execute ) \ - (void) ptw32_pop_cleanup( _execute ); \ - } - -#else /* __CLEANUP_C */ - -#if defined(__CLEANUP_CXX) - - /* - * C++ version of cancel cleanup. - * - John E. Bossom. - */ - - class PThreadCleanup { - /* - * PThreadCleanup - * - * Purpose - * This class is a C++ helper class that is - * used to implement pthread_cleanup_push/ - * pthread_cleanup_pop. - * The destructor of this class automatically - * pops the pushed cleanup routine regardless - * of how the code exits the scope - * (i.e. such as by an exception) - */ - ptw32_cleanup_callback_t cleanUpRout; - void * obj; - int executeIt; - - public: - PThreadCleanup() : - cleanUpRout( 0 ), - obj( 0 ), - executeIt( 0 ) - /* - * No cleanup performed - */ - { - } - - PThreadCleanup( - ptw32_cleanup_callback_t routine, - void * arg ) : - cleanUpRout( routine ), - obj( arg ), - executeIt( 1 ) - /* - * Registers a cleanup routine for 'arg' - */ - { - } - - ~PThreadCleanup() - { - if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) - { - (void) (*cleanUpRout)( obj ); - } - } - - void execute( int exec ) - { - executeIt = exec; - } - }; - - /* - * C++ implementation of PThreads cancel cleanup; - * This implementation takes advantage of a helper - * class who's destructor automatically calls the - * cleanup routine if we exit our scope weirdly - */ -#define pthread_cleanup_push( _rout, _arg ) \ - { \ - PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ - (void *) (_arg) ); - -#define pthread_cleanup_pop( _execute ) \ - cleanup.execute( _execute ); \ - } - -#else - -#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. - -#endif /* __CLEANUP_CXX */ - -#endif /* __CLEANUP_C */ - -#endif /* __CLEANUP_SEH */ - -/* - * =============== - * =============== - * Methods - * =============== - * =============== - */ - -/* - * PThread Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, - int *detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, - void **stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, - size_t * stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, - int detachstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, - void *stackaddr); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, - size_t stacksize); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *, - int *); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, - int inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr, - int * inheritsched); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, - int); - -PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, - int *); - -/* - * PThread Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, - const pthread_attr_t * attr, - void *(PTW32_CDECL *start) (void *), - void *arg); - -PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); - -PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, - pthread_t t2); - -PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); - -PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, - void **value_ptr); - -PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, - int *oldstate); - -PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, - int *oldtype); - -PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); - -PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, - void (PTW32_CDECL *init_routine) (void)); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX -PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); - -PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, - ptw32_cleanup_callback_t routine, - void *arg); -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread Specific Data Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, - void (PTW32_CDECL *destructor) (void *)); - -PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); - -PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, - const void *value); - -PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); - - -/* - * Mutex Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, - int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust( - pthread_mutexattr_t *attr, - int robust); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust( - const pthread_mutexattr_t * attr, - int * robust); - -/* - * Barrier Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t - * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, - int pshared); - -/* - * Mutex Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, - const pthread_mutexattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex); - -/* - * Spinlock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); - -/* - * Barrier Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, - const pthread_barrierattr_t * attr, - unsigned int count); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); - -PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); - -/* - * Condition Variable Attribute Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, - int pshared); - -/* - * Condition Variable Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, - const pthread_condattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, - pthread_mutex_t * mutex); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, - pthread_mutex_t * mutex, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); - -PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); - -/* - * Scheduling - */ -PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, - int policy, - const struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, - int *policy, - struct sched_param *param); - -PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); - -PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); - -/* - * Read-Write Lock Functions - */ -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, - const pthread_rwlockattr_t *attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, - const struct timespec *abstime); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, - int *pshared); - -PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, - int pshared); - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 - -/* - * Signal Functions. Should be defined in but MSVC and MinGW32 - * already have signal.h that don't define these. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); - -/* - * Non-portable functions - */ - -/* - * Compatibility with Linux. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, - int kind); -PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, - int *kind); - -/* - * Possibly supported by other POSIX threads implementations - */ -PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); -PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); -PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread); - -/* - * Useful if an application wants to statically link - * the lib rather than load the DLL at run-time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); -PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); - -/* - * Features that are auto-detected at load/run time. - */ -PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); -enum ptw32_features { - PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ - PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ -}; - -/* - * Register a system time change with the library. - * Causes the library to perform various functions - * in response to the change. Should be called whenever - * the application's top level window receives a - * WM_TIMECHANGE message. It can be passed directly to - * pthread_create() as a new thread if desired. - */ -PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); - -#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* - * Returns the Win32 HANDLE for the POSIX thread. - */ -PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); -/* - * Returns the win32 thread ID for POSIX thread. - */ -PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread); - - -/* - * Protected Methods - * - * This function blocks until the given WIN32 handle - * is signaled or pthread_cancel had been called. - * This function allows the caller to hook into the - * PThreads cancel mechanism. It is implemented using - * - * WaitForMultipleObjects - * - * on 'waitHandle' and a manually reset WIN32 Event - * used to implement pthread_cancel. The 'timeout' - * argument to TimedWait is simply passed to - * WaitForMultipleObjects. - */ -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); -PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, - DWORD timeout); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -/* - * Thread-Safe C Runtime Library Mappings. - */ -#if !defined(_UWIN) -# if defined(NEED_ERRNO) - PTW32_DLLPORT int * PTW32_CDECL _errno( void ); -# else -# if !defined(errno) -# if (defined(_MT) || defined(_DLL)) - __declspec(dllimport) extern int * __cdecl _errno(void); -# define errno (*_errno()) -# endif -# endif -# endif -#endif - -/* - * Some compiler environments don't define some things. - */ -#if defined(__BORLANDC__) -# define _ftime ftime -# define _timeb timeb -#endif - -#if defined(__cplusplus) - -/* - * Internal exceptions - */ -class ptw32_exception {}; -class ptw32_exception_cancel : public ptw32_exception {}; -class ptw32_exception_exit : public ptw32_exception {}; - -#endif - -#if PTW32_LEVEL >= PTW32_LEVEL_MAX - -/* FIXME: This is only required if the library was built using SEH */ -/* - * Get internal SEH tag - */ -PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); - -#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ - -#if !defined(PTW32_BUILD) - -#if defined(__CLEANUP_SEH) - -/* - * Redefine the SEH __except keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#define __except( E ) \ - __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ - ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) - -#endif /* __CLEANUP_SEH */ - -#if defined(__CLEANUP_CXX) - -/* - * Redefine the C++ catch keyword to ensure that applications - * propagate our internal exceptions up to the library's internal handlers. - */ -#if defined(_MSC_VER) - /* - * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' - * if you want Pthread-Win32 cancelation and pthread_exit to work. - */ - -#if !defined(PtW32NoCatchWarn) - -#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") -#pragma message("------------------------------------------------------------------") -#pragma message("When compiling applications with MSVC++ and C++ exception handling:") -#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") -#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") -#pragma message(" cancelation and pthread_exit to work. For example:") -#pragma message("") -#pragma message(" #if defined(PtW32CatchAll)") -#pragma message(" PtW32CatchAll") -#pragma message(" #else") -#pragma message(" catch(...)") -#pragma message(" #endif") -#pragma message(" {") -#pragma message(" /* Catchall block processing */") -#pragma message(" }") -#pragma message("------------------------------------------------------------------") - -#endif - -#define PtW32CatchAll \ - catch( ptw32_exception & ) { throw; } \ - catch( ... ) - -#else /* _MSC_VER */ - -#define catch( E ) \ - catch( ptw32_exception & ) { throw; } \ - catch( E ) - -#endif /* _MSC_VER */ - -#endif /* __CLEANUP_CXX */ - -#endif /* ! PTW32_BUILD */ - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#if defined(PTW32__HANDLE_DEF) -# undef HANDLE -#endif -#if defined(PTW32__DWORD_DEF) -# undef DWORD -#endif - -#undef PTW32_LEVEL -#undef PTW32_LEVEL_MAX - -#endif /* ! RC_INVOKED */ - -#endif /* PTHREAD_H */ diff --git a/osal/window/pthread/inc/sched.h b/osal/window/pthread/inc/sched.h deleted file mode 100644 index e25eb56b0..000000000 --- a/osal/window/pthread/inc/sched.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Module: sched.h - * - * Purpose: - * Provides an implementation of POSIX realtime extensions - * as defined in - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#if !defined(_SCHED_H) -#define _SCHED_H - -#undef PTW32_SCHED_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_SCHED_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_SCHED_LEVEL -#define PTW32_SCHED_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_SCHED_LEVEL -#define PTW32_SCHED_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_SCHED_LEVEL_MAX 3 - -#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL) -#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX -/* Include everything */ -#endif - - -#if defined(__GNUC__) && !defined(__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ - -#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) -# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX -/* For pid_t */ -# include -/* Required by Unix 98 */ -# include -# else - typedef int pid_t; -# endif -#else - typedef int pid_t; -#endif - -/* Thread scheduling policies */ - -enum { - SCHED_OTHER = 0, - SCHED_FIFO, - SCHED_RR, - SCHED_MIN = SCHED_OTHER, - SCHED_MAX = SCHED_RR -}; - -struct sched_param { - int sched_priority; -}; - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -PTW32_DLLPORT int __cdecl sched_yield (void); - -PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); - -PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); - -PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); - -PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); - -/* - * Note that this macro returns ENOTSUP rather than - * ENOSYS as might be expected. However, returning ENOSYS - * should mean that sched_get_priority_{min,max} are - * not implemented as well as sched_rr_get_interval. - * This is not the case, since we just don't support - * round-robin scheduling. Therefore I have chosen to - * return the same value as sched_setscheduler when - * SCHED_RR is passed to it. - */ -#define sched_rr_get_interval(_pid, _interval) \ - ( errno = ENOTSUP, (int) -1 ) - - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#undef PTW32_SCHED_LEVEL -#undef PTW32_SCHED_LEVEL_MAX - -#endif /* !_SCHED_H */ - diff --git a/osal/window/pthread/inc/semaphore.h b/osal/window/pthread/inc/semaphore.h deleted file mode 100644 index f7a4286e4..000000000 --- a/osal/window/pthread/inc/semaphore.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Module: semaphore.h - * - * Purpose: - * Semaphores aren't actually part of the PThreads standard. - * They are defined by the POSIX Standard: - * - * POSIX 1003.1b-1993 (POSIX.1b) - * - * -------------------------------------------------------------------------- - * - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#if !defined( SEMAPHORE_H ) -#define SEMAPHORE_H - -#undef PTW32_SEMAPHORE_LEVEL - -#if defined(_POSIX_SOURCE) -#define PTW32_SEMAPHORE_LEVEL 0 -/* Early POSIX */ -#endif - -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 -#undef PTW32_SEMAPHORE_LEVEL -#define PTW32_SEMAPHORE_LEVEL 1 -/* Include 1b, 1c and 1d */ -#endif - -#if defined(INCLUDE_NP) -#undef PTW32_SEMAPHORE_LEVEL -#define PTW32_SEMAPHORE_LEVEL 2 -/* Include Non-Portable extensions */ -#endif - -#define PTW32_SEMAPHORE_LEVEL_MAX 3 - -#if !defined(PTW32_SEMAPHORE_LEVEL) -#define PTW32_SEMAPHORE_LEVEL PTW32_SEMAPHORE_LEVEL_MAX -/* Include everything */ -#endif - -#if defined(__GNUC__) && ! defined (__declspec) -# error Please upgrade your GNU compiler to one that supports __declspec. -#endif - -/* - * When building the library, you should define PTW32_BUILD so that - * the variables/functions are exported correctly. When using the library, - * do NOT define PTW32_BUILD, and then the variables/functions will - * be imported correctly. - */ -#if !defined(PTW32_STATIC_LIB) -# if defined(PTW32_BUILD) -# define PTW32_DLLPORT __declspec (dllexport) -# else -# define PTW32_DLLPORT __declspec (dllimport) -# endif -#else -# define PTW32_DLLPORT -#endif - -/* - * This is a duplicate of what is in the autoconf config.h, - * which is only used when building the pthread-win32 libraries. - */ - -#if !defined(PTW32_CONFIG_H) -# if defined(WINCE) -# define NEED_ERRNO -# define NEED_SEM -# endif -# if defined(__MINGW64__) -# define HAVE_STRUCT_TIMESPEC -# define HAVE_MODE_T -# elif defined(_UWIN) || defined(__MINGW32__) -# define HAVE_MODE_T -# endif -#endif - -/* - * - */ - -#if PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX -#if defined(NEED_ERRNO) -#include "need_errno.h" -#else -#include -#endif -#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */ - -#define _POSIX_SEMAPHORES - -#if defined(__cplusplus) -extern "C" -{ -#endif /* __cplusplus */ - -#if !defined(HAVE_MODE_T) -typedef unsigned int mode_t; -#endif - - -typedef struct sem_t_ * sem_t; - -PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, - int pshared, - unsigned int value); - -PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, - const struct timespec * abstime); - -PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, - int count); - -PTW32_DLLPORT int __cdecl sem_open (const char * name, - int oflag, - mode_t mode, - unsigned int value); - -PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); - -PTW32_DLLPORT int __cdecl sem_unlink (const char * name); - -PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, - int * sval); - -#if defined(__cplusplus) -} /* End of extern "C" */ -#endif /* __cplusplus */ - -#undef PTW32_SEMAPHORE_LEVEL -#undef PTW32_SEMAPHORE_LEVEL_MAX - -#endif /* !SEMAPHORE_H */ diff --git a/osal/window/pthread/lib/x64/pthreadVC2.lib b/osal/window/pthread/lib/x64/pthreadVC2.lib deleted file mode 100644 index 1b07e0e9a..000000000 Binary files a/osal/window/pthread/lib/x64/pthreadVC2.lib and /dev/null differ diff --git a/osal/window/pthread/lib/x86/pthreadVC2.lib b/osal/window/pthread/lib/x86/pthreadVC2.lib deleted file mode 100644 index c20ee200d..000000000 Binary files a/osal/window/pthread/lib/x86/pthreadVC2.lib and /dev/null differ diff --git a/osal/window/pthread/lib/x86/pthreadVCE2.lib b/osal/window/pthread/lib/x86/pthreadVCE2.lib deleted file mode 100644 index 7f05317ba..000000000 Binary files a/osal/window/pthread/lib/x86/pthreadVCE2.lib and /dev/null differ diff --git a/osal/window/pthread/lib/x86/pthreadVSE2.lib b/osal/window/pthread/lib/x86/pthreadVSE2.lib deleted file mode 100644 index 3f3335d46..000000000 Binary files a/osal/window/pthread/lib/x86/pthreadVSE2.lib and /dev/null differ diff --git a/osal/window/stdint.h b/osal/window/stdint.h deleted file mode 100644 index 6e72e7f7b..000000000 --- a/osal/window/stdint.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -/* a minimal set of C99 types for use with MSVC */ - -typedef signed char int8_t; -typedef short int int16_t; -typedef int int32_t; -typedef __int64 int64_t; - -typedef unsigned char uint8_t; -typedef unsigned short int uint16_t; -typedef unsigned int uint32_t; -typedef unsigned __int64 uint64_t; diff --git a/pkgconfig/rockchip_mpp.pc.cmake b/pkgconfig/rockchip_mpp.pc.cmake new file mode 100644 index 000000000..9d7d84c8b --- /dev/null +++ b/pkgconfig/rockchip_mpp.pc.cmake @@ -0,0 +1,12 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: rockchip_mpp +Description: Rockchip Media Process Platform +Requires.private: +Version: 1.3.9 +Libs: -L${libdir} -lrockchip_mpp @MPP_PKGCONFIG_DEPENDENT_LIBS@ +Libs.private: +Cflags: -I${includedir} diff --git a/pkgconfig/rockchip_vpu.pc.cmake b/pkgconfig/rockchip_vpu.pc.cmake new file mode 100644 index 000000000..f75d8d9af --- /dev/null +++ b/pkgconfig/rockchip_vpu.pc.cmake @@ -0,0 +1,12 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: rockchip_vpu +Description: Rockchip Media Process Platform (Legacy) +Requires.private: +Version: 0.3.1 +Libs: -L${libdir} -lrockchip_vpu @MPP_PKGCONFIG_DEPENDENT_LIBS@ +Libs.private: +Cflags: -I${includedir} diff --git a/readme.txt b/readme.txt index 61dfdba98..878dfb61a 100644 --- a/readme.txt +++ b/readme.txt @@ -1,250 +1,391 @@ -Media Process Platform (MPP) module directory description: - -MPP : Media Process Platform -MPI : Media Process Interface -HAL : Hardware Abstract Layer -OSAL : Operation System Abstract Layer - -Rules: -1. header file arrange rule -a. inc directory in each module folder is for external module usage. -b. module internal header file should be put along with the implement file. -c. header file should not contain any relative path or absolute path, all include path should be keep in Makefile. -2. compiling system rule -a. for cross platform compiling use cmake as the compiling management system. -b. use cmake out-of-source build, final binary and library will be install to out/ directory. -3. header file include order -a. MODULE_TAG -b. system header -c. osal header -d. module header - -NOTE: -1. when run on window pthreadVC2.dll needed to be copied to the system directory. - ----- top - | - |----- build CMake out-of-source build directory - | | - | |----- cmake cmake script directory - | | - | |----- android android build directory - | | - | |----- linux linux build directory - | | - | |----- vc12-x86_64 visual studio 2013 on x86_64 build directory - | - |----- inc header file for external usage, including platform header and mpi header - | - |----- mpi Media Process Interface: the api function implement in public (vpu_api layer) - | - |----- mpp Media Process Platform : mpi function private implement and mpp infrastructure (vpu_api private layer) - | | - | |----- codec all video codec parser, convert stream to protocol structure - | | | - | | |----- inc header files provided by codec module for external usage - | | | - | | |----- dec - | | | | - | | | |----- h264 - | | | | - | | | |----- h265 - | | | | - | | | |----- vp9 - | | | | - | | | |----- jpeg - | | | - | | |----- enc - | | | - | | |----- h264 - | | | - | | |----- h265 - | | | - | | |----- jpeg - | | - | |----- hal Hardware Abstract Layer (HAL): modules used in mpi - | | | - | | |----- inc header files provided by hal for external usage - | | | - | | |----- iep iep user library - | | | - | | |----- pp post-processor user library - | | | - | | |----- rga rga user library - | | | - | | |----- deinter deinterlace function module including pp/iep/rga - | | | - | | |----- rkdec rockchip hardware decoder register generation library - | | | | - | | | |----- h264d generate register file from H.264 structure created by codec parser - | | | | - | | | |----- h265d generate register file from H.265 structure created by codec parser - | | | | - | | | |----- vp9d generate register file from vp9 structure created by codec parser - | | | - | | |----- vpu vpu register generation library - | | | - | | |----- h264d generate register file from H.264 structure created by codec parser - | | | - | | |----- h265d generate register file from H.265 structure created by codec parser - | | - | |----- legacy legacy vpu_api interface - | | - | |----- syntax syntax interface for different video codec protocol - | - |----- test mpi/mpp unit test files and mpi demo files - | - |----- out final release binary output directory - | | - | |----- bin executable binary file output directory - | | - | |----- inc header file output directory - | | - | |----- lib library file output directory - | - |----- osal Operation System Abstract Layer: abstract layer for different operation system - | - |----- mem mpi memory subsystem for hardware - | - |----- android google's android - | - |----- linux mainline linux kernel - | - |----- window microsoft's window - | - |----- test OASL unit test - - -Here is the mpp implement overall framework: - - +-------------------------+ +--------+ - | | | | - | MPI / MPP | | | - | buffer queue manage | | | - | | | | - +-------------------------+ | | - | | - +-------------------------+ | | - | | | | - | codec | | OSAL | - | decoder / encoder | | | - | | | | - +-------------------------+ | | - | | - +-----------+ +-----------+ | | - | | | | | | - | parser | | HAL | | | - | recoder | | reg_gen | | | - | | | | | | - +-----------+ +-----------+ +--------+ - - -Here is the Media Process Interface hierarchical structure -MpiPacket and MpiFrame is the stream I/O data structure. -And MpiBuffer encapsulates different buffer implement like Linux's dma-buf and Android's ion. -This part is learned from ffmpeg. - - +-------------------+ - | | - | MPI | - | | - +---------+---------+ - | - | - v - +---------+---------+ - | | - +---+ ctx +---+ - | | | | - | +-------------------+ | - | | - v v - +-------+-------+ +-------+-------+ - | | | | - | packet | | frame | - | | | | - +---------------+ +-------+-------+ - | - | - v - +-------+-------+ - | | - | buffer | - | | - +---------------+ - - - -Take H.264 deocder for example. Video stream will first queued by MPI/MPP layer, MPP will send the stream to codec layer, -codec layer parses the stream header and generates a protocol standard output. This output will be send to HAL to generate -register file set and communicate with hardware. Hardware will complete the task and resend information back. MPP notify -codec by hardware result, codec output decoded frame by display order. - -MPI MPP decoder parser HAL - - + + + + + - | | | | | - | open context | | | | - +----------------> | | | | - | | | | | - | init | | | | - +----------------> | | | | - | | | | | - | | init | | | - | +----------------> | | | - | | | | | - | | | init | | - | | +----------------> | | - | | | | | - | | | | open | - | | +-----------------------------------> | - | | | | | - | decode | | | | - +----------------> | | | | - | | | | | - | | send_stream | | | - | +----------------> | | | - | | | | | - | | | parse_stream | | - | | +----------------> | | - | | | | | - | | | | reg generation | - | | +-----------------------------------> | - | | | | | - | | | | send_regs | - | | +-----------------------------------> | - | | | | | - | | | | wait_regs | - | | +-----------------------------------> | - | | | | | - | | | notify_hw_end | | - | | +----------------> | | - | | | | | - | | get_picture | | | - | +----------------> | | | - | | | | | - | | | get_picture | | - | | +----------------> | | - | | | | | - | flush | | | | - +----------------> | | | | - | | | | | - | | flush | | | - | +----------------> | | | - | | | | | - | | | reset | | - | | +----------------> | | - | | | | | - | close | | | | - +----------------> | | | | - | | | | | - | | close | | | - | +----------------> | | | - | | | | | - | | | close | | - | | +----------------> | | - | | | | | - | | | | close | - | | +-----------------------------------> | - + + + + + - +Media Process Platform (MPP) module directory description: + +MPP : Media Process Platform +MPI : Media Process Interface +HAL : Hardware Abstract Layer +OSAL : Operation System Abstract Layer + +Rules: +1. header file arrange rule +a. inc directory in each module folder is for external module usage. +b. module internal header file should be put along with the implement file. +c. header file should not contain any relative path or absolute path, all + include path should be keep in Makefile. +2. compiling system rule +a. for cross platform compiling use cmake as the compiling management system. +b. use cmake out-of-source build, final binary and library will be install to + out/ directory. +3. header file include order +a. MODULE_TAG +b. system header +c. osal header +d. module header + +NOTE: +1. Windows support is NOT maintained any more. +2. Mpp support all rockchip chipset now including: + RK29XX/RK30XX/RK31XX + RK3288/RK3368/RK3399 + RK3228/RK3229/RK3228H/RK3328 + RK3528/RK3528A + RK3562 + RK3566/RK3568 + RK3588 + RV1108/RV1107 + RV1109/RV1126 +3. Mpp support all format hardware can support except VC1. +4. you can get demo about mpp applied to linux and android. + Liunx : https://github.com/WainDing/mpp_linux_cpp + https://github.com/MUZLATAN + https://github.com/nyanmisaka + Android : https://github.com/c-xh/RKMediaCodecDemo +5. offical github: https://github.com/rockchip-linux/mpp + develop github: https://github.com/HermanChen/mpp + develop gitee : https://gitee.com/hermanchen82/mpp +6. Commit message format should base on https://keepachangelog.com/en/1.0.0/ + +More document can be found at http://opensource.rock-chips.com/wiki_Mpp + +---- top + | + |----- build CMake out-of-source build directory + | | + | |----- cmake cmake script directory + | | + | |----- android android build directory + | | + | |----- linux linux build directory + | | + | |----- vc10-x86_64 visual studio 2010 on x86_64 build directory + | | + | |----- vc12-x86_64 visual studio 2013 on x86_64 build directory + | + |----- doc design documents of mpp + | + |----- inc header file for external usage, including + | platform header and mpi header + | + |----- mpp Media Process Platform : mpi function private + | | implement and mpp infrastructure (vpu_api + | | private layer) + | | + | |----- base base components including MppBuffer, MppFrame, + | | MppPacket, MppTask, MppMeta, etc. + | | + | |----- common video codec protocol syntax interface for both + | | codec parser and hal + | | + | |----- codec all video codec parser, convert stream to + | | | protocol structure + | | | + | | |----- inc header files provided by codec module for + | | | external usage + | | | + | | |----- dec + | | | | + | | | |----- dummy decoder parser work flow sample + | | | | + | | | |----- h263 + | | | | + | | | |----- h264 + | | | | + | | | |----- h265 + | | | | + | | | |----- m2v mpeg2 parser + | | | | + | | | |----- mpg4 mpeg4 parser + | | | | + | | | |----- vp8 + | | | | + | | | |----- vp9 + | | | | + | | | |----- jpeg + | | | + | | |----- enc + | | | + | | |----- dummy encoder controllor work flow sample + | | | + | | |----- h264 + | | | + | | |----- h265 + | | | + | | |----- jpeg + | | + | |----- hal Hardware Abstract Layer (HAL): modules used in mpi + | | | + | | |----- inc header files provided by hal for external usage + | | | + | | |----- iep iep user library + | | | + | | |----- pp post-processor user library + | | | + | | |----- deinter deinterlace function module including pp/iep + | | | + | | |----- rkdec rockchip hardware decoder register generation + | | | | + | | | |----- h264d generate register file from H.264 syntax info + | | | | + | | | |----- h265d generate register file from H.265 syntax info + | | | | + | | | |----- vp9d generate register file from vp9 syntax info + | | | + | | |----- vpu vpu register generation library + | | | + | | |----- h263d generate register file from H.263 syntax info + | | | + | | |----- h264d generate register file from H.264 syntax info + | | | + | | |----- h265d generate register file from H.265 syntax info + | | | + | | |----- jpegd generate register file from jpeg syntax info + | | | + | | |----- jpege generate register file from jpeg syntax info + | | | + | | |----- m2vd generate register file from mpeg2 syntax info + | | | + | | |----- mpg4d generate register file from mpeg4 syntax info + | | | + | | |----- vp8d generate register file from vp8 syntax info + | | + | |----- legacy generate new libvpu to include old vpuapi path + | | and new mpp path + | | + | |----- test mpp internal video protocol unit test and demo + | + |----- test mpp buffer/packet component unit test and + | mpp/mpi/vpu_api demo + | + |----- out final release binary output directory + | | + | |----- bin executable binary file output directory + | | + | |----- inc header file output directory + | | + | |----- lib library file output directory + | + |----- osal Operation System Abstract Layer: abstract layer + | | for different operation system + | | + | |----- allocator supported allocator including Android ion and + | | Linux drm + | | + | |----- android google's android + | | + | |----- inc osal header file for mpp modules + | | + | |----- linux mainline linux kernel + | | + | |----- windows microsoft's windows + | | + | |----- test OASL unit test + | + |----- tools coding style format tools + | + |----- utils small util functions + + +Here is the mpp implement overall framework: + + +---------------------------------------+ + | | + | OpenMax / gstreamer / libva | + | | + +---------------------------------------+ + + +-------------------- MPP ----------------------+ + | | + | +-------------------------+ +--------+ | + | | | | | | + | | MPI / MPP | | | | + | | buffer queue manage | | | | + | | | | | | + | +-------------------------+ | | | + | | | | + | +-------------------------+ | | | + | | | | | | + | | codec | | OSAL | | + | | decoder / encoder | | | | + | | | | | | + | +-------------------------+ | | | + | | | | + | +-----------+ +-----------+ | | | + | | | | | | | | + | | parser | | HAL | | | | + | | recoder | | reg_gen | | | | + | | | | | | | | + | +-----------+ +-----------+ +--------| | + | | + +-------------------- MPP ----------------------+ + + +---------------------------------------+ + | | + | kernel | + | RK vcodec_service / v4l2 | + | | + +---------------------------------------+ + + + +Here is the Media Process Interface hierarchical structure +MpiPacket and MpiFrame is the stream I/O data structure. +And MpiBuffer encapsulates different buffer implement like Linux's dma-buf and +Android's ion. +This part is learned from ff. + + +-------------------+ + | | + | MPI | + | | + +---------+---------+ + | + | + v + +---------+---------+ + | | + +---+ ctx +---+ + | | | | + | +-------------------+ | + | | + v v + +-------+-------+ +-------+-------+ + | | | | + | packet | | frame | + | | | | + +---------------+ +-------+-------+ + | | + | | + | | + | +---------------+ | + | | | | + +---->+ buffer +<----+ + | | + +---------------+ + + + +Take H.264 deocder for example. Video stream will first queued by MPI/MPP layer, +MPP will send the stream to codec layer, codec layer parses the stream header +and generates a protocol standard output. This output will be send to HAL to +generate register file set and communicate with hardware. Hardware will complete +the task and resend information back. MPP notify codec by hardware result, codec +output decoded frame by display order. + +MPI MPP decoder parser HAL + + + + + + + + | | | | | + | open context | | | | + +----------------> | | | | + | | | | | + | init | | | | + +----------------> | | | | + | | | | | + | | init | | | + | +----------------> | | | + | | | | | + | | | init | | + | | +----------------> | | + | | | | | + | | | | open | + | | +-----------------------------------> | + | | | | | + | decode | | | | + +----------------> | | | | + | | | | | + | | send_stream | | | + | +----------------> | | | + | | | | | + | | | parse_stream | | + | | +----------------> | | + | | | | | + | | | | reg generation | + | | +-----------------------------------> | + | | | | | + | | | | send_regs | + | | +-----------------------------------> | + | | | | | + | | | | wait_regs | + | | +-----------------------------------> | + | | | | | + | | | notify_hw_end | | + | | +----------------> | | + | | | | | + | | get_picture | | | + | +----------------> | | | + | | | | | + | | | get_picture | | + | | +----------------> | | + | | | | | + | flush | | | | + +----------------> | | | | + | | | | | + | | flush | | | + | +----------------> | | | + | | | | | + | | | reset | | + | | +----------------> | | + | | | | | + | close | | | | + +----------------> | | | | + | | | | | + | | close | | | + | +----------------> | | | + | | | | | + | | | close | | + | | +----------------> | | + | | | | | + | | | | close | + | | +-----------------------------------> | + + + + + + + +There are three memory usage modes that decoder can support: + +Mode 1: Pure internal mode +In the mode user will NOT call MPP_DEC_SET_EXT_BUF_GROUP control to decoder. +Only call MPP_DEC_SET_INFO_CHANGE_READY to let decoder go on. Then decoder will +use create buffer internally and user need to release each frame they get. + +Advantage: +Easy to use and get a demo quickly +Disadvantage: +1. The buffer from decoder may not be return before decoder is close. + So memory leak or crash may happen. +2. The decoder memory usage can not be control. Decoder is on a free-to-run + status and consume all memory it can get. +3. Difficult to implement zero-copy display path. + +Mode 2: Half internal mode +This is the mode current mpi_dec_test code using. User need to create +MppBufferGroup according to the returned info change MppFrame. +User can use mpp_buffer_group_limit_config to limit decoder memory usage. + +Advantage: +1. Easy to use +2. User can release MppBufferGroup after decoder is closed. + So memory can stay longer safely. +3. Can limit the memory usage by mpp_buffer_group_limit_config +Disadvantage: +1. The buffer limitation is still not accurate. Memory usage is 100% fixed. +2. Also difficult to implement zero-copy display path. + +Mode 3: Pure external mode +In this mode use need to create empty MppBufferGroup and import memory from +external allocator by file handle. +On Android surfaceflinger will create buffer. Then mediaserver get file handle +from surfaceflinger and commit to decoder's MppBufferGroup. + +Advantage: +1. Most efficient way for zero-copy display +Disadvantage: +1. Difficult to learn and use. +2. Player work flow may limit this usage. +3. May need external parser to get the correct buffer size for the external + allocator. + +The required buffer size caculation: +hor_stride * ver_stride * 3 / 2 for pixel data +hor_stride * ver_stride / 2 for extra info +Total hor_stride * ver_stride * 2 will be enough. + +For H.264/H.265 20+ buffers will be enough. +For other codec 10 buffers will be enough. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fc0f76a09..7f17b5bed 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,31 +3,67 @@ # mpp built-in unit test case # ---------------------------------------------------------------------------- # macro for adding mpp sub-module unit test -macro(add_mpp_test module) +macro(add_mpp_test module ext) set(test_name ${module}_test) + set(file_name ${test_name}.${ext}) string(TOUPPER ${test_name} test_tag) #message(STATUS "moduule : ${module}") #message(STATUS "test_name : ${test_name}") #message(STATUS "test_tag : ${test_tag}") - option(${test_tag} "Build mpp ${module} unit test" ON) + option(${test_tag} "Build mpp ${module}.${ext} unit test" ${BUILD_TEST}) if(${test_tag}) - add_executable(${test_name} ${test_name}.c) - target_link_libraries(${test_name} mpp) + add_executable(${test_name} ${file_name} mpp_event_trigger.c mpp_parse_cfg.c) + target_link_libraries(${test_name} ${MPP_SHARED} utils) set_target_properties(${test_name} PROPERTIES FOLDER "test") - install(TARGETS ${test_name} RUNTIME DESTINATION ${TEST_INSTALL_DIR}) - add_test(NAME ${test_name} COMMAND ${test_name}) + install(TARGETS ${test_name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + #add_test(NAME ${test_name} COMMAND ${test_name}) endif() endmacro() -# legacy vpu_api unit test -add_mpp_test(vpu_api) +# mpp info test +add_mpp_test(mpp_info c) + +# mpi decoder unit test +add_mpp_test(mpi_dec c) + +# mpi decoder multi-thread input / output unit test +add_mpp_test(mpi_dec_mt c) + +# mpi decoder no-thread input / output unit test +add_mpp_test(mpi_dec_nt c) -# mpp_buffer unit test -add_mpp_test(mpp_buffer) +# mpi encoder unit test +add_mpp_test(mpi_enc c) + +# mpi encoder multi-thread input / output unit test +add_mpp_test(mpi_enc_mt c) + +# new mpi rc unit test +add_mpp_test(mpi_rc2 c) + +# new dec multi unit test +add_mpp_test(mpi_dec_multi c) + +macro(add_legacy_test module) + set(test_name ${module}_test) + string(TOUPPER ${test_name} test_tag) + #message(STATUS "moduule : ${module}") + #message(STATUS "test_name : ${test_name}") + #message(STATUS "test_tag : ${test_tag}") -# mpp_packet unit test -add_mpp_test(mpp_packet) + option(${test_tag} "Build legacy ${module} unit test" ${BUILD_TEST}) + if(${test_tag}) + add_executable(${test_name} ${test_name}.c) + if(ASAN_CHECK) + target_link_libraries(${test_name} ${ASAN_LIB} pthread dl) + else(ASAN_CHECK) + target_link_libraries(${test_name} dl) + endif(ASAN_CHECK) + set_target_properties(${test_name} PROPERTIES FOLDER "test") + install(TARGETS ${test_name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() +endmacro() -# mpi unit test -add_mpp_test(mpi) +# legacy vpu_api unit test +add_legacy_test(vpu_api) diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000..d4f164505 --- /dev/null +++ b/test/README.md @@ -0,0 +1,29 @@ +# Unit test description + +## There are some unit test for testing mpp functions in this catalog. + +### mpi_enc_test: +use sync interface(poll,dequeue and enqueue), encode raw yuv to compress video. + +### mpi_dec_test: +use sync interface and async interface(decode_put_packet and decode_get_frame), +decode compress video to raw yuv. + +### mpi_rc_test: +encode use detailed bitrate control config. + +### mpi_rc2_test: +encode use detailed bitrate control config,and cfg param come from mpi_rc.cfg. + +### mpi_test: +simple description of mpi calling method, just for reference + +### mpp_event_trigger: +event trigger test. + +### mpp_parse_cfg: +mpp parser cfg test. + +### vpu_api_test +encode or decode use legacy interface, in order to compatible with the previous +vpu interface. diff --git a/test/cfg/enc/base_h264_1920x1080.json b/test/cfg/enc/base_h264_1920x1080.json new file mode 100644 index 000000000..9986d7ba0 --- /dev/null +++ b/test/cfg/enc/base_h264_1920x1080.json @@ -0,0 +1,200 @@ +"enc_cfg" : { + "codec" : { + "type" : 7 + }, + "base" : { + "low_delay" : 0, + "smt1_en" : 0, + "smt3_en" : 0 + }, + "rc" : { + "mode" : 0, + "quality" : 2, + "bps_target" : 0, + "bps_max" : 0, + "bps_min" : 0, + "fps_in_flex" : 0, + "fps_in_num" : 30, + "fps_in_denorm" : 1, + "fps_in_denom" : 1, + "fps_out_flex" : 0, + "fps_out_num" : 30, + "fps_out_denorm" : 1, + "fps_out_denom" : 1, + "fps_chg_no_idr" : 0, + "gop" : 60, + "ref_cfg" : {}, + "max_reenc_times" : 0, + "priority" : 0, + "drop_mode" : 0, + "drop_thd" : 20, + "drop_gap" : 1, + "max_i_prop" : 30, + "min_i_prop" : 10, + "init_ip_ratio" : 160, + "super_mode" : 0, + "super_i_thd" : 0, + "super_p_thd" : 0, + "debreath_en" : 0, + "debreath_strength" : 0, + "qp_init" : -1, + "qp_min" : 10, + "qp_max" : 51, + "qp_min_i" : 10, + "qp_max_i" : 51, + "qp_step" : 0, + "qp_ip" : 2, + "qp_vi" : 0, + "hier_qp_en" : 0, + "hier_qp_delta" : [], + "hier_frame_num" : [], + "stats_time" : 0, + "refresh_en" : 0, + "refresh_mode" : 0, + "refresh_num" : 0, + "fqp_min_i" : 10, + "fqp_min_p" : 10, + "fqp_max_i" : 45, + "fqp_max_p" : 45, + "mt_st_swth_frm_qp" : 0, + "inst_br_lvl" : 0 + }, + "prep" : { + "width" : 1920, + "height" : 1080, + "max_width" : 0, + "max_height" : 0, + "hor_stride" : 0, + "ver_stride" : 0, + "format" : 0, + "format_out" : 0, + "chroma_ds_mode" : 0, + "fix_chroma_en" : 0, + "fix_chroma_u" : 0, + "fix_chroma_v" : 0, + "colorspace" : 2, + "colorprim" : 2, + "colortrc" : 2, + "colorrange" : 2, + "range" : 2, + "range_out" : 0, + "rotation" : 0, + "mirroring" : 0, + "flip" : 0 + }, + "h264" : { + "stream_type" : 0, + "profile" : 100, + "level" : 40, + "poc_type" : 0, + "log2_max_poc_lsb" : 12, + "log2_max_frm_num" : 12, + "gaps_not_allowed" : 0, + "cabac_en" : 1, + "cabac_idc" : 0, + "trans8x8" : 1, + "const_intra" : 0, + "scaling_list" : 0, + "cb_qp_offset" : -6, + "cr_qp_offset" : -6, + "dblk_disable" : 0, + "dblk_alpha" : 0, + "dblk_beta" : 0, + "qp_init" : -1, + "qp_min" : 10, + "qp_max" : 51, + "qp_min_i" : 10, + "qp_max_i" : 51, + "qp_step" : 0, + "qp_delta_ip" : 2, + "max_tid" : 0, + "max_ltr" : 0, + "prefix_mode" : 0, + "base_layer_pid" : 0, + "constraint_set" : 0, + "vui_en" : 1 + }, + "split" : { + "mode" : 0, + "arg" : 0, + "out" : 0 + }, + "hw" : { + "qp_row" : 2, + "qp_row_i" : 2, + "aq_thrd_i" : [], + "aq_thrd_p" : [], + "aq_step_i" : [], + "aq_step_p" : [], + "mb_rc_disable" : 0, + "aq_rnge_arr" : [], + "mode_bias" : [], + "skip_bias_en" : 0, + "skip_sad" : 8, + "skip_bias" : 4, + "qbias_i" : 0, + "qbias_p" : 0, + "qbias_en" : 1, + "qbias_arr" : [], + "flt_str_i" : 0, + "flt_str_p" : 0 + }, + "tune" : { + "scene_mode" : 0, + "se_mode" : 0, + "deblur_en" : 0, + "deblur_str" : 0, + "anti_flicker_str" : 0, + "lambda_idx_i" : 0, + "lambda_idx_p" : 0, + "atr_str_i" : 0, + "atr_str_p" : 0, + "atl_str" : 0, + "sao_str_i" : 0, + "sao_str_p" : 0, + "rc_container" : 0, + "vmaf_opt" : 0, + "motion_static_switch_enable" : 0, + "atf_str" : 0, + "lgt_chg_lvl" : 0, + "static_frm_num" : 0, + "madp16_th" : 0, + "skip16_wgt" : 0, + "skip32_wgt" : 0, + "speed" : 0, + "bg_delta_qp_i" : -10, + "bg_delta_qp_p" : -10, + "fg_delta_qp_i" : 3, + "fg_delta_qp_p" : 1, + "bmap_qpmin_i" : 30, + "bmap_qpmin_p" : 30, + "bmap_qpmax_i" : 45, + "bmap_qpmax_p" : 47, + "min_bg_fqp" : 30, + "max_bg_fqp" : 45, + "min_fg_fqp" : 25, + "max_fg_fqp" : 35, + "fg_area" : 0, + "qpmap_en" : 0 + } +} +"enc_args" : { + "type_src" : 0, + "frame_num" : 30, + "loop_cnt" : 0, + "nthreads" : 1, + "frm_step" : 1, + "gop_mode" : 0, + "vi_len" : 0, + "quiet" : 0, + "trace_fps" : 0, + "kmpp_en" : 0, + "osd_enable" : 0, + "osd_mode" : 0, + "user_data_enable" : 0, + "roi_enable" : 0, + "roi_jpeg_enable" : 0, + "jpeg_osd_case" : 0, + "constraint_set" : 0, + "sei_mode" : 0 +} \ No newline at end of file diff --git a/test/cfg/enc/base_h265_1920x1080.json b/test/cfg/enc/base_h265_1920x1080.json new file mode 100644 index 000000000..1f3cd4f15 --- /dev/null +++ b/test/cfg/enc/base_h265_1920x1080.json @@ -0,0 +1,199 @@ +"enc_cfg" : { + "codec" : { + "type" : 16777220 + }, + "base" : { + "low_delay" : 0, + "smt1_en" : 0, + "smt3_en" : 0 + }, + "rc" : { + "mode" : 0, + "quality" : 2, + "bps_target" : 0, + "bps_max" : 0, + "bps_min" : 0, + "fps_in_flex" : 0, + "fps_in_num" : 30, + "fps_in_denorm" : 1, + "fps_in_denom" : 1, + "fps_out_flex" : 0, + "fps_out_num" : 30, + "fps_out_denorm" : 1, + "fps_out_denom" : 1, + "fps_chg_no_idr" : 0, + "gop" : 60, + "ref_cfg" : {}, + "max_reenc_times" : 0, + "priority" : 0, + "drop_mode" : 0, + "drop_thd" : 20, + "drop_gap" : 1, + "max_i_prop" : 30, + "min_i_prop" : 10, + "init_ip_ratio" : 160, + "super_mode" : 0, + "super_i_thd" : 0, + "super_p_thd" : 0, + "debreath_en" : 0, + "debreath_strength" : 0, + "qp_init" : -1, + "qp_min" : 10, + "qp_max" : 51, + "qp_min_i" : 10, + "qp_max_i" : 51, + "qp_step" : 0, + "qp_ip" : 2, + "qp_vi" : 2, + "hier_qp_en" : 0, + "hier_qp_delta" : [], + "hier_frame_num" : [], + "stats_time" : 0, + "refresh_en" : 0, + "refresh_mode" : 0, + "refresh_num" : 0, + "fqp_min_i" : 10, + "fqp_min_p" : 10, + "fqp_max_i" : 45, + "fqp_max_p" : 45, + "mt_st_swth_frm_qp" : 0, + "inst_br_lvl" : 0 + }, + "prep" : { + "width" : 1920, + "height" : 1080, + "max_width" : 0, + "max_height" : 0, + "hor_stride" : 0, + "ver_stride" : 0, + "format" : 0, + "format_out" : 0, + "chroma_ds_mode" : 0, + "fix_chroma_en" : 0, + "fix_chroma_u" : 0, + "fix_chroma_v" : 0, + "colorspace" : 2, + "colorprim" : 2, + "colortrc" : 2, + "colorrange" : 2, + "range" : 2, + "range_out" : 0, + "rotation" : 0, + "mirroring" : 0, + "flip" : 0 + }, + "h265" : { + "profile" : 1, + "tier" : 0, + "level" : 120, + "scaling_list" : 0, + "cb_qp_offset" : 0, + "cr_qp_offset" : 0, + "diff_cu_qp_delta_depth" : 0, + "dblk_disable" : 0, + "dblk_alpha" : 0, + "dblk_beta" : 0, + "qp_init" : -1, + "qp_min" : 10, + "qp_max" : 51, + "qp_min_i" : 10, + "qp_max_i" : 51, + "qp_step" : 0, + "qp_delta_ip" : 2, + "sao_luma_disable" : 0, + "sao_chroma_disable" : 0, + "sao_bit_ratio" : 0, + "lpf_acs_sli_en" : 0, + "lpf_acs_tile_disable" : 0, + "auto_tile" : 0, + "max_tid" : 0, + "max_ltr" : 0, + "base_layer_pid" : 0, + "const_intra" : 0, + "lcu_size" : 0, + "vui_en" : 1 + }, + "split" : { + "mode" : 0, + "arg" : 0, + "out" : 0 + }, + "hw" : { + "qp_row" : 2, + "qp_row_i" : 2, + "aq_thrd_i" : [], + "aq_thrd_p" : [], + "aq_step_i" : [], + "aq_step_p" : [], + "mb_rc_disable" : 0, + "aq_rnge_arr" : [], + "mode_bias" : [], + "skip_bias_en" : 0, + "skip_sad" : 8, + "skip_bias" : 4, + "qbias_i" : 0, + "qbias_p" : 0, + "qbias_en" : 1, + "qbias_arr" : [], + "flt_str_i" : 0, + "flt_str_p" : 0 + }, + "tune" : { + "scene_mode" : 0, + "se_mode" : 0, + "deblur_en" : 0, + "deblur_str" : 0, + "anti_flicker_str" : 0, + "lambda_idx_i" : 0, + "lambda_idx_p" : 0, + "atr_str_i" : 0, + "atr_str_p" : 0, + "atl_str" : 0, + "sao_str_i" : 0, + "sao_str_p" : 0, + "rc_container" : 0, + "vmaf_opt" : 0, + "motion_static_switch_enable" : 0, + "atf_str" : 0, + "lgt_chg_lvl" : 0, + "static_frm_num" : 0, + "madp16_th" : 0, + "skip16_wgt" : 0, + "skip32_wgt" : 0, + "speed" : 0, + "bg_delta_qp_i" : -10, + "bg_delta_qp_p" : -10, + "fg_delta_qp_i" : 3, + "fg_delta_qp_p" : 1, + "bmap_qpmin_i" : 30, + "bmap_qpmin_p" : 30, + "bmap_qpmax_i" : 45, + "bmap_qpmax_p" : 47, + "min_bg_fqp" : 30, + "max_bg_fqp" : 45, + "min_fg_fqp" : 25, + "max_fg_fqp" : 35, + "fg_area" : 0, + "qpmap_en" : 0 + } +} +"enc_args" : { + "type_src" : 0, + "frame_num" : 30, + "loop_cnt" : 0, + "nthreads" : 1, + "frm_step" : 1, + "gop_mode" : 0, + "vi_len" : 0, + "quiet" : 0, + "trace_fps" : 0, + "kmpp_en" : 0, + "osd_enable" : 0, + "osd_mode" : 0, + "user_data_enable" : 0, + "roi_enable" : 0, + "roi_jpeg_enable" : 0, + "jpeg_osd_case" : 0, + "constraint_set" : 0, + "sei_mode" : 0 +} \ No newline at end of file diff --git a/test/cfg/enc/base_jpg_1920x1080.json b/test/cfg/enc/base_jpg_1920x1080.json new file mode 100644 index 000000000..461c4593b --- /dev/null +++ b/test/cfg/enc/base_jpg_1920x1080.json @@ -0,0 +1,178 @@ +"enc_cfg" : { + "codec" : { + "type" : 8 + }, + "base" : { + "low_delay" : 0, + "smt1_en" : 0, + "smt3_en" : 0 + }, + "rc" : { + "mode" : 2, + "quality" : 0, + "bps_target" : 0, + "bps_max" : 0, + "bps_min" : 0, + "fps_in_flex" : 0, + "fps_in_num" : 30, + "fps_in_denorm" : 1, + "fps_in_denom" : 1, + "fps_out_flex" : 0, + "fps_out_num" : 30, + "fps_out_denorm" : 1, + "fps_out_denom" : 1, + "fps_chg_no_idr" : 0, + "gop" : 60, + "ref_cfg" : {}, + "max_reenc_times" : 0, + "priority" : 0, + "drop_mode" : 0, + "drop_thd" : 20, + "drop_gap" : 1, + "max_i_prop" : 0, + "min_i_prop" : 0, + "init_ip_ratio" : 0, + "super_mode" : 0, + "super_i_thd" : 0, + "super_p_thd" : 0, + "debreath_en" : 0, + "debreath_strength" : 0, + "qp_init" : 0, + "qp_min" : 0, + "qp_max" : 0, + "qp_min_i" : 0, + "qp_max_i" : 0, + "qp_step" : 0, + "qp_ip" : 0, + "qp_vi" : 0, + "hier_qp_en" : 0, + "hier_qp_delta" : [], + "hier_frame_num" : [], + "stats_time" : 0, + "refresh_en" : 0, + "refresh_mode" : 0, + "refresh_num" : 0, + "fqp_min_i" : 0, + "fqp_min_p" : 0, + "fqp_max_i" : 0, + "fqp_max_p" : 0, + "mt_st_swth_frm_qp" : 0, + "inst_br_lvl" : 0 + }, + "prep" : { + "width" : 1920, + "height" : 1080, + "max_width" : 0, + "max_height" : 0, + "hor_stride" : 0, + "ver_stride" : 0, + "format" : 0, + "format_out" : 0, + "chroma_ds_mode" : 0, + "fix_chroma_en" : 0, + "fix_chroma_u" : 0, + "fix_chroma_v" : 0, + "colorspace" : 2, + "colorprim" : 2, + "colortrc" : 2, + "colorrange" : 2, + "range" : 2, + "range_out" : 0, + "rotation" : 0, + "mirroring" : 0, + "flip" : 0 + }, + "jpeg" : { + "q_mode" : 0, + "quant" : -1, + "q_factor" : 80, + "qf_max" : 99, + "qf_min" : 1, + "qtable_y" : [], + "qtable_u" : [], + "qtable_v" : [] + }, + "split" : { + "mode" : 0, + "arg" : 0, + "out" : 0 + }, + "hw" : { + "qp_row" : 0, + "qp_row_i" : 0, + "aq_thrd_i" : [], + "aq_thrd_p" : [], + "aq_step_i" : [], + "aq_step_p" : [], + "mb_rc_disable" : 0, + "aq_rnge_arr" : [], + "mode_bias" : [], + "skip_bias_en" : 0, + "skip_sad" : 8, + "skip_bias" : 4, + "qbias_i" : 0, + "qbias_p" : 0, + "qbias_en" : 1, + "qbias_arr" : [], + "flt_str_i" : 0, + "flt_str_p" : 0 + }, + "tune" : { + "scene_mode" : 0, + "se_mode" : 0, + "deblur_en" : 0, + "deblur_str" : 0, + "anti_flicker_str" : 0, + "lambda_idx_i" : 0, + "lambda_idx_p" : 0, + "atr_str_i" : 0, + "atr_str_p" : 0, + "atl_str" : 0, + "sao_str_i" : 0, + "sao_str_p" : 0, + "rc_container" : 0, + "vmaf_opt" : 0, + "motion_static_switch_enable" : 0, + "atf_str" : 0, + "lgt_chg_lvl" : 0, + "static_frm_num" : 0, + "madp16_th" : 0, + "skip16_wgt" : 0, + "skip32_wgt" : 0, + "speed" : 0, + "bg_delta_qp_i" : 0, + "bg_delta_qp_p" : 0, + "fg_delta_qp_i" : 0, + "fg_delta_qp_p" : 0, + "bmap_qpmin_i" : 0, + "bmap_qpmin_p" : 0, + "bmap_qpmax_i" : 0, + "bmap_qpmax_p" : 0, + "min_bg_fqp" : 0, + "max_bg_fqp" : 0, + "min_fg_fqp" : 0, + "max_fg_fqp" : 0, + "fg_area" : 0, + "qpmap_en" : 0 + } +} +"enc_args" : { + "type_src" : 0, + "frame_num" : 3, + "loop_cnt" : 0, + "nthreads" : 1, + "frm_step" : 1, + "gop_mode" : 0, + "vi_len" : 0, + "quiet" : 0, + "trace_fps" : 0, + "kmpp_en" : 0, + "osd_enable" : 0, + "osd_mode" : 0, + "user_data_enable" : 0, + "roi_enable" : 0, + "roi_jpeg_enable" : 0, + "jpeg_osd_case" : 0, + "constraint_set" : 0, + "sei_mode" : 0 +} \ No newline at end of file diff --git a/test/cfg/enc/codec_h264.json b/test/cfg/enc/codec_h264.json new file mode 100644 index 000000000..1d195686a --- /dev/null +++ b/test/cfg/enc/codec_h264.json @@ -0,0 +1,37 @@ +"enc_cfg" : { + "codec" : { + "type" : 7 + }, + "h264" : { + "stream_type" : 0, + "profile" : 100, + "level" : 40, + "poc_type" : 0, + "log2_max_poc_lsb" : 12, + "log2_max_frm_num" : 12, + "gaps_not_allowed" : 0, + "cabac_en" : 1, + "cabac_idc" : 0, + "trans8x8" : 1, + "const_intra" : 0, + "scaling_list" : 0, + "cb_qp_offset" : -6, + "cr_qp_offset" : -6, + "dblk_disable" : 0, + "dblk_alpha" : 0, + "dblk_beta" : 0, + "qp_init" : -1, + "qp_min" : 10, + "qp_max" : 51, + "qp_min_i" : 10, + "qp_max_i" : 51, + "qp_step" : 0, + "qp_delta_ip" : 2, + "max_tid" : 0, + "max_ltr" : 0, + "prefix_mode" : 0, + "base_layer_pid" : 0, + "constraint_set" : 0, + "vui_en" : 1 + } +} \ No newline at end of file diff --git a/test/cfg/enc/codec_h265.json b/test/cfg/enc/codec_h265.json new file mode 100644 index 000000000..361f7cbc0 --- /dev/null +++ b/test/cfg/enc/codec_h265.json @@ -0,0 +1,36 @@ +"enc_cfg" : { + "codec" : { + "type" : 16777220 + }, + "h265" : { + "profile" : 1, + "tier" : 0, + "level" : 120, + "scaling_list" : 0, + "cb_qp_offset" : 0, + "cr_qp_offset" : 0, + "diff_cu_qp_delta_depth" : 0, + "dblk_disable" : 0, + "dblk_alpha" : 0, + "dblk_beta" : 0, + "qp_init" : -1, + "qp_min" : 10, + "qp_max" : 51, + "qp_min_i" : 10, + "qp_max_i" : 51, + "qp_step" : 0, + "qp_delta_ip" : 2, + "sao_luma_disable" : 0, + "sao_chroma_disable" : 0, + "sao_bit_ratio" : 0, + "lpf_acs_sli_en" : 0, + "lpf_acs_tile_disable" : 0, + "auto_tile" : 0, + "max_tid" : 0, + "max_ltr" : 0, + "base_layer_pid" : 0, + "const_intra" : 0, + "lcu_size" : 0, + "vui_en" : 1 + } +} \ No newline at end of file diff --git a/test/cfg/enc/codec_jpg.json b/test/cfg/enc/codec_jpg.json new file mode 100644 index 000000000..4cc61974a --- /dev/null +++ b/test/cfg/enc/codec_jpg.json @@ -0,0 +1,15 @@ +"enc_cfg" : { + "codec" : { + "type" : 8 + }, + "jpeg" : { + "q_mode" : 0, + "quant" : -1, + "q_factor" : 80, + "qf_max" : 99, + "qf_min" : 1, + "qtable_y" : [], + "qtable_u" : [], + "qtable_v" : [] + } +} \ No newline at end of file diff --git a/test/cfg/enc/fmt_abgr8888.json b/test/cfg/enc/fmt_abgr8888.json new file mode 100644 index 000000000..a426738ba --- /dev/null +++ b/test/cfg/enc/fmt_abgr8888.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65547 + } + } +} diff --git a/test/cfg/enc/fmt_argb8888.json b/test/cfg/enc/fmt_argb8888.json new file mode 100644 index 000000000..b288ff853 --- /dev/null +++ b/test/cfg/enc/fmt_argb8888.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65546 + } + } +} diff --git a/test/cfg/enc/fmt_bgr555.json b/test/cfg/enc/fmt_bgr555.json new file mode 100644 index 000000000..57e14e739 --- /dev/null +++ b/test/cfg/enc/fmt_bgr555.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65539 + } + } +} diff --git a/test/cfg/enc/fmt_bgr565.json b/test/cfg/enc/fmt_bgr565.json new file mode 100644 index 000000000..33537b903 --- /dev/null +++ b/test/cfg/enc/fmt_bgr565.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65537 + } + } +} diff --git a/test/cfg/enc/fmt_bgr888.json b/test/cfg/enc/fmt_bgr888.json new file mode 100644 index 000000000..672910f1d --- /dev/null +++ b/test/cfg/enc/fmt_bgr888.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65543 + } + } +} diff --git a/test/cfg/enc/fmt_bgra8888.json b/test/cfg/enc/fmt_bgra8888.json new file mode 100644 index 000000000..dfb598522 --- /dev/null +++ b/test/cfg/enc/fmt_bgra8888.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65548 + } + } +} diff --git a/test/cfg/enc/fmt_rgb555.json b/test/cfg/enc/fmt_rgb555.json new file mode 100644 index 000000000..fb2c1de18 --- /dev/null +++ b/test/cfg/enc/fmt_rgb555.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65538 + } + } +} diff --git a/test/cfg/enc/fmt_rgb565.json b/test/cfg/enc/fmt_rgb565.json new file mode 100644 index 000000000..d064cb1fa --- /dev/null +++ b/test/cfg/enc/fmt_rgb565.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65536 + } + } +} diff --git a/test/cfg/enc/fmt_rgb888.json b/test/cfg/enc/fmt_rgb888.json new file mode 100644 index 000000000..42ac8551f --- /dev/null +++ b/test/cfg/enc/fmt_rgb888.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65542 + } + } +} diff --git a/test/cfg/enc/fmt_rgba8888.json b/test/cfg/enc/fmt_rgba8888.json new file mode 100644 index 000000000..fd14cc02f --- /dev/null +++ b/test/cfg/enc/fmt_rgba8888.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 65549 + } + } +} diff --git a/test/cfg/enc/fmt_uyvy422.json b/test/cfg/enc/fmt_uyvy422.json new file mode 100644 index 000000000..a4e7a9d40 --- /dev/null +++ b/test/cfg/enc/fmt_uyvy422.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 10 + } + } +} diff --git a/test/cfg/enc/fmt_yuv400.json b/test/cfg/enc/fmt_yuv400.json new file mode 100644 index 000000000..8a50275cc --- /dev/null +++ b/test/cfg/enc/fmt_yuv400.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 12 + } + } +} diff --git a/test/cfg/enc/fmt_yuv420p.json b/test/cfg/enc/fmt_yuv420p.json new file mode 100644 index 000000000..9ed566a47 --- /dev/null +++ b/test/cfg/enc/fmt_yuv420p.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 4 + } + } +} diff --git a/test/cfg/enc/fmt_yuv420sp.json b/test/cfg/enc/fmt_yuv420sp.json new file mode 100644 index 000000000..ff35a2aa5 --- /dev/null +++ b/test/cfg/enc/fmt_yuv420sp.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 0 + } + } +} diff --git a/test/cfg/enc/fmt_yuv420sp_10bit.json b/test/cfg/enc/fmt_yuv420sp_10bit.json new file mode 100644 index 000000000..eb1ca6672 --- /dev/null +++ b/test/cfg/enc/fmt_yuv420sp_10bit.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 1 + } + } +} diff --git a/test/cfg/enc/fmt_yuv420sp_vu.json b/test/cfg/enc/fmt_yuv420sp_vu.json new file mode 100644 index 000000000..77b4f3b92 --- /dev/null +++ b/test/cfg/enc/fmt_yuv420sp_vu.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 5 + } + } +} diff --git a/test/cfg/enc/fmt_yuv422p.json b/test/cfg/enc/fmt_yuv422p.json new file mode 100644 index 000000000..22fb5b47f --- /dev/null +++ b/test/cfg/enc/fmt_yuv422p.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 6 + } + } +} diff --git a/test/cfg/enc/fmt_yuv422sp.json b/test/cfg/enc/fmt_yuv422sp.json new file mode 100644 index 000000000..b81651e51 --- /dev/null +++ b/test/cfg/enc/fmt_yuv422sp.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 2 + } + } +} diff --git a/test/cfg/enc/fmt_yuv422sp_10bit.json b/test/cfg/enc/fmt_yuv422sp_10bit.json new file mode 100644 index 000000000..4c1f367fd --- /dev/null +++ b/test/cfg/enc/fmt_yuv422sp_10bit.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 3 + } + } +} diff --git a/test/cfg/enc/fmt_yuv422sp_vu.json b/test/cfg/enc/fmt_yuv422sp_vu.json new file mode 100644 index 000000000..040f48ff2 --- /dev/null +++ b/test/cfg/enc/fmt_yuv422sp_vu.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 7 + } + } +} diff --git a/test/cfg/enc/fmt_yuv444p.json b/test/cfg/enc/fmt_yuv444p.json new file mode 100644 index 000000000..84a98546e --- /dev/null +++ b/test/cfg/enc/fmt_yuv444p.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 16 + } + } +} diff --git a/test/cfg/enc/fmt_yuv444sp.json b/test/cfg/enc/fmt_yuv444sp.json new file mode 100644 index 000000000..a0e936308 --- /dev/null +++ b/test/cfg/enc/fmt_yuv444sp.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 15 + } + } +} diff --git a/test/cfg/enc/fmt_yuyv422.json b/test/cfg/enc/fmt_yuyv422.json new file mode 100644 index 000000000..f5dff56d6 --- /dev/null +++ b/test/cfg/enc/fmt_yuyv422.json @@ -0,0 +1,7 @@ +{ + "enc_cfg" : { + "prep" : { + "format" : 8 + } + } +} diff --git a/test/cfg/enc/func_debreath.json b/test/cfg/enc/func_debreath.json new file mode 100644 index 000000000..4d00f20f9 --- /dev/null +++ b/test/cfg/enc/func_debreath.json @@ -0,0 +1,6 @@ +"enc_cfg" : { + "rc" : { + "debreath_en" : 1, + "debreath_strength" : 16 + } +} \ No newline at end of file diff --git a/test/cfg/enc/func_flip.json b/test/cfg/enc/func_flip.json new file mode 100644 index 000000000..c7ff64603 --- /dev/null +++ b/test/cfg/enc/func_flip.json @@ -0,0 +1,5 @@ +"enc_cfg" : { + "prep" : { + "flip" : 1 + } +} \ No newline at end of file diff --git a/test/cfg/enc/func_mirror.json b/test/cfg/enc/func_mirror.json new file mode 100644 index 000000000..588b36662 --- /dev/null +++ b/test/cfg/enc/func_mirror.json @@ -0,0 +1,5 @@ +"enc_cfg" : { + "prep" : { + "mirroring" : 1 + } +} \ No newline at end of file diff --git a/test/cfg/enc/func_multi_threads.json b/test/cfg/enc/func_multi_threads.json new file mode 100644 index 000000000..632f8687e --- /dev/null +++ b/test/cfg/enc/func_multi_threads.json @@ -0,0 +1,3 @@ +"enc_args" : { + "nthreads" : 5 +} \ No newline at end of file diff --git a/test/cfg/enc/func_osd.json b/test/cfg/enc/func_osd.json new file mode 100644 index 000000000..356029b62 --- /dev/null +++ b/test/cfg/enc/func_osd.json @@ -0,0 +1,3 @@ +"enc_args" : { + "osd_enable" : 1 +} \ No newline at end of file diff --git a/test/cfg/enc/func_roi.json b/test/cfg/enc/func_roi.json new file mode 100644 index 000000000..862a9374e --- /dev/null +++ b/test/cfg/enc/func_roi.json @@ -0,0 +1,3 @@ +"enc_args" : { + "roi_enable" : 1 +} \ No newline at end of file diff --git a/test/cfg/enc/func_rot_180.json b/test/cfg/enc/func_rot_180.json new file mode 100644 index 000000000..ac957ce1c --- /dev/null +++ b/test/cfg/enc/func_rot_180.json @@ -0,0 +1,5 @@ +"enc_cfg" : { + "prep" : { + "rotation" : 2 + } +} \ No newline at end of file diff --git a/test/cfg/enc/func_rot_270.json b/test/cfg/enc/func_rot_270.json new file mode 100644 index 000000000..d2e372e87 --- /dev/null +++ b/test/cfg/enc/func_rot_270.json @@ -0,0 +1,5 @@ +"enc_cfg" : { + "prep" : { + "rotation" : 3 + } +} \ No newline at end of file diff --git a/test/cfg/enc/func_rot_90.json b/test/cfg/enc/func_rot_90.json new file mode 100644 index 000000000..d0c3f2da9 --- /dev/null +++ b/test/cfg/enc/func_rot_90.json @@ -0,0 +1,5 @@ +"enc_cfg" : { + "prep" : { + "rotation" : 1 + } +} \ No newline at end of file diff --git a/test/cfg/enc/func_split_slice_by_byte.json b/test/cfg/enc/func_split_slice_by_byte.json new file mode 100644 index 000000000..0727d0777 --- /dev/null +++ b/test/cfg/enc/func_split_slice_by_byte.json @@ -0,0 +1,7 @@ +"enc_cfg" : { + "split" : { + "mode" : 1, + "arg" : 1024, + "out" : 0 + } +} \ No newline at end of file diff --git a/test/cfg/enc/func_split_slice_by_ctu.json b/test/cfg/enc/func_split_slice_by_ctu.json new file mode 100644 index 000000000..6b4038455 --- /dev/null +++ b/test/cfg/enc/func_split_slice_by_ctu.json @@ -0,0 +1,7 @@ +"enc_cfg" : { + "split" : { + "mode" : 2, + "arg" : 256, + "out" : 0 + } +} \ No newline at end of file diff --git a/test/cfg/enc/res_1280x720.json b/test/cfg/enc/res_1280x720.json new file mode 100644 index 000000000..11a7bdb01 --- /dev/null +++ b/test/cfg/enc/res_1280x720.json @@ -0,0 +1,6 @@ +"enc_cfg" : { + "prep" : { + "width" : 1280, + "height" : 720 + } +} \ No newline at end of file diff --git a/test/cfg/enc/res_1920x1080.json b/test/cfg/enc/res_1920x1080.json new file mode 100644 index 000000000..dd5782b37 --- /dev/null +++ b/test/cfg/enc/res_1920x1080.json @@ -0,0 +1,6 @@ +"enc_cfg" : { + "prep" : { + "width" : 1920, + "height" : 1080 + } +} \ No newline at end of file diff --git a/test/cfg/enc/res_3840x2160.json b/test/cfg/enc/res_3840x2160.json new file mode 100644 index 000000000..7425728f6 --- /dev/null +++ b/test/cfg/enc/res_3840x2160.json @@ -0,0 +1,6 @@ +"enc_cfg" : { + "prep" : { + "width" : 3840, + "height" : 2160 + } +} \ No newline at end of file diff --git a/test/cfg/mpp_cfg/test_cfg.json b/test/cfg/mpp_cfg/test_cfg.json new file mode 100644 index 000000000..f234ead22 --- /dev/null +++ b/test/cfg/mpp_cfg/test_cfg.json @@ -0,0 +1,52 @@ +{ + "width": 1920, + "height": 1080, + "fps": 30.5, + "enabled": true, + "name": "test_config", + "s8_val": -128, + "u8_val": 255, + "s16_val": -32768, + "u16_val": 65535, + "s32_val": -2147483648, + "u32_val": 4294967295, + "s64_val": -1000000, + "u64_val": 1000000, + "values": [0, 1, 2, 3, 4, 5], + "s8_array": [-128, -64, 0, 64, 127], + "u8_array": [0, 64, 128, 192, 255], + "s16_array": [-1000, -500, 0, 500, 1000], + "u16_array": [0, 1000, 2000, 3000, 4000], + "s64_array": [-1000000, -500000, 0, 500000, 1000000], + "u64_array": [0, 1000000, 2000000, 3000000, 4000000], + "bool_array": [true, false, true, false], + "string_array": ["hello", "world", "mpp", "test"], + "nested_array": [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9] + ], + "codec": { + "type": "h264", + "profile": "high", + "level": 4.1, + "bitrate": 4000000 + }, + "objects": [ + { + "id": 100, + "name": "obj_a", + "active": true + }, + { + "id": 101, + "name": "obj_b", + "active": false + }, + { + "id": 102, + "name": "obj_c", + "active": true + } + ] +} diff --git a/test/cfg/mpp_cfg/test_cfg.toml b/test/cfg/mpp_cfg/test_cfg.toml new file mode 100644 index 000000000..df409f3c6 --- /dev/null +++ b/test/cfg/mpp_cfg/test_cfg.toml @@ -0,0 +1,29 @@ +width = 1920 +height = 1080 +fps = 30.5 +enabled = true +name = "test_config" +s8_val = -128 +u8_val = 255 +s16_val = -32768 +u16_val = 65535 +s32_val = -2147483648 +u32_val = 4294967295 +s64_val = -1000000 +u64_val = 1000000 + +values = [0, 1, 2, 3, 4, 5] +s8_array = [-128, -64, 0, 64, 127] +u8_array = [0, 64, 128, 192, 255] +s16_array = [-1000, -500, 0, 500, 1000] +u16_array = [0, 1000, 2000, 3000, 4000] +s64_array = [-1000000, -500000, 0, 500000, 1000000] +u64_array = [0, 1000000, 2000000, 3000000, 4000000] +bool_array = [true, false, true, false] +string_array = ["hello", "world", "mpp", "test"] + +[codec] +type = "h264" +profile = "high" +level = 4.1 +bitrate = 4000000 diff --git a/test/mpi_dec_mt_test.c b/test/mpi_dec_mt_test.c new file mode 100644 index 000000000..d6b6a0fa2 --- /dev/null +++ b/test/mpi_dec_mt_test.c @@ -0,0 +1,443 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(_WIN32) +#include "vld.h" +#endif + +#define MODULE_TAG "mpi_dec_mt_test" + +#include +#include + +#include "rk_mpi.h" + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "mpi_dec_utils.h" + +typedef struct { + MpiDecTestCmd *cmd; + MppCtx ctx; + MppApi *mpi; + + volatile RK_U32 loop_end; + + /* buffer for stream data reading */ + char *buf; + + /* input and output */ + DecBufMgr buf_mgr; + MppBufferGroup frm_grp; + MppPacket packet; + size_t packet_size; + MppFrame frame; + + FILE *fp_output; + RK_S32 frame_count; + RK_S32 frame_num; + FileReader reader; + + /* runtime flag */ + RK_U32 quiet; +} MpiDecMtLoopData; + +void *thread_input(void *arg) +{ + MpiDecMtLoopData *data = (MpiDecMtLoopData *)arg; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + MppPacket packet = data->packet; + FileReader reader = data->reader; + RK_U32 quiet = data->quiet; + + mpp_log_q(quiet, "put packet thread start\n"); + + do { + RK_U32 pkt_eos = 0; + FileBufSlot *slot = NULL; + MPP_RET ret = reader_read(reader, &slot); + if (ret) + break; + + mpp_packet_set_data(packet, slot->data); + mpp_packet_set_size(packet, slot->size); + mpp_packet_set_pos(packet, slot->data); + mpp_packet_set_length(packet, slot->size); + + pkt_eos = slot->eos; + // setup eos flag + if (pkt_eos) { + if (data->frame_num < 0 || data->frame_count < data->frame_num) { + mpp_log_q(quiet, "%p loop again\n", ctx); + reader_rewind(reader); + pkt_eos = 0; + } else { + mpp_log_q(quiet, "%p found last packet\n", ctx); + mpp_packet_set_eos(packet); + } + } + + // send packet until it success + do { + ret = mpi->decode_put_packet(ctx, packet); + if (MPP_OK == ret) { + mpp_assert(0 == mpp_packet_get_length(packet)); + break; + + } + // if failed wait a moment and retry + msleep(1); + } while (!data->loop_end); + + if (pkt_eos) + break; + } while (!data->loop_end); + + mpp_log_q(quiet, "put packet thread end\n"); + + return NULL; +} + +void *thread_output(void *arg) +{ + MpiDecMtLoopData *data = (MpiDecMtLoopData *)arg; + MpiDecTestCmd *cmd = data->cmd; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + RK_U32 quiet = data->quiet; + + mpp_log_q(quiet, "get frame thread start\n"); + + // then get all available frame and release + do { + RK_U32 frm_eos = 0; + MppFrame frame = NULL; + MPP_RET ret = mpi->decode_get_frame(ctx, &frame); + + if (ret) { + mpp_err("decode_get_frame failed ret %d\n", ret); + continue; + } + + if (NULL == frame) { + msleep(1); + continue; + } + + if (mpp_frame_get_info_change(frame)) { + // found info change and create buffer group for decoding + RK_U32 width = mpp_frame_get_width(frame); + RK_U32 height = mpp_frame_get_height(frame); + RK_U32 hor_stride = mpp_frame_get_hor_stride(frame); + RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); + RK_U32 buf_size = mpp_frame_get_buf_size(frame); + MppBufferGroup grp = NULL; + + mpp_log_q(quiet, "decode_get_frame get info changed found\n"); + mpp_log_q(quiet, "decoder require buffer w:h [%d:%d] stride [%d:%d] size %d\n", + width, height, hor_stride, ver_stride, buf_size); + + if (MPP_FRAME_FMT_IS_FBC(cmd->format) || MPP_FRAME_FMT_IS_TILE(cmd->format)) { + MppFrame frm = NULL; + + mpp_frame_init(&frm); + mpp_frame_set_width(frm, width); + mpp_frame_set_height(frm, height); + mpp_frame_set_fmt(frm, cmd->format); + + ret = mpi->control(ctx, MPP_DEC_SET_FRAME_INFO, frm); + mpp_frame_deinit(&frm); + + if (ret) { + mpp_err("set fbc frame info failed\n"); + break; + } + } + + grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode); + /* Set buffer to mpp decoder */ + ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp); + if (ret) { + mpp_err("%p set buffer group failed ret %d\n", ctx, ret); + break; + } + data->frm_grp = grp; + + ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); + if (ret) { + mpp_err("info change ready failed ret %d\n", ret); + break; + } + } else { + char log_buf[256]; + RK_S32 log_size = sizeof(log_buf) - 1; + RK_S32 log_len = 0; + RK_U32 err_info = mpp_frame_get_errinfo(frame); + RK_U32 discard = mpp_frame_get_discard(frame); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + "decode get frame %d", data->frame_count); + + if (mpp_frame_has_meta(frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + RK_S32 temporal_id = 0; + + mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + " tid %d", temporal_id); + } + + if (err_info || discard) { + log_len += snprintf(log_buf + log_len, log_size - log_len, + " err %x discard %x", err_info, discard); + } + mpp_log_q(quiet, "%p %s\n", ctx, log_buf); + + data->frame_count++; + if (data->fp_output && !err_info) + dump_mpp_frame_to_file(frame, data->fp_output); + + fps_calc_inc(cmd->fps); + } + + frm_eos = mpp_frame_get_eos(frame); + mpp_frame_deinit(&frame); + + if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) || + ((data->frame_num == 0) && frm_eos)) + data->loop_end = 1; + } while (!data->loop_end); + + mpp_log_q(quiet, "get frame thread end\n"); + + return NULL; +} + +int mt_dec_decode(MpiDecTestCmd *cmd) +{ + MPP_RET ret = MPP_OK; + FileReader reader = cmd->reader; + + // base flow context + MppCtx ctx = NULL; + MppApi *mpi = NULL; + + // input / output + MppPacket packet = NULL; + MppFrame frame = NULL; + + // config for runtime mode + MppDecCfg cfg = NULL; + RK_U32 need_split = 1; + + // paramter for resource malloc + RK_U32 width = cmd->width; + RK_U32 height = cmd->height; + MppCodingType type = cmd->type; + + pthread_t thd_in; + pthread_t thd_out = 0; + pthread_attr_t attr; + MpiDecMtLoopData data; + + mpp_log("mpi_dec_mt_test start\n"); + memset(&data, 0, sizeof(data)); + + if (cmd->have_output) { + data.fp_output = fopen(cmd->file_output, "w+b"); + if (NULL == data.fp_output) { + mpp_err("failed to open output file %s\n", cmd->file_output); + goto MPP_TEST_OUT; + } + } + + ret = dec_buf_mgr_init(&data.buf_mgr); + if (ret) { + mpp_err("dec_buf_mgr_init failed\n"); + goto MPP_TEST_OUT; + } + + ret = mpp_packet_init(&packet, NULL, 0); + if (ret) { + mpp_err("mpp_packet_init failed\n"); + goto MPP_TEST_OUT; + } + + mpp_log("mpi_dec_mt_test decoder test start w %d h %d type %d\n", width, height, type); + + // decoder demo + ret = mpp_create(&ctx, &mpi); + if (ret) { + mpp_err("mpp_create failed\n"); + goto MPP_TEST_OUT; + } + + ret = mpp_init(ctx, MPP_CTX_DEC, type); + if (ret) { + mpp_err("mpp_init failed\n"); + goto MPP_TEST_OUT; + } + + // NOTE: timeout value please refer to MppPollType definition + // 0 - non-block call (default) + // -1 - block call + // +val - timeout value in ms + { + MppPollType timeout = MPP_POLL_BLOCK; + MppParam param = &timeout; + + ret = mpi->control(ctx, MPP_SET_OUTPUT_TIMEOUT, param); + if (ret) { + mpp_err("Failed to set output timeout %d ret %d\n", timeout, ret); + goto MPP_TEST_OUT; + } + } + + mpp_dec_cfg_init(&cfg); + + /* get default config from decoder context */ + ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg); + if (ret) { + mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + /* + * split_parse is to enable mpp internal frame spliter when the input + * packet is not aplited into frames. + */ + ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split); + if (ret) { + mpp_err("%p failed to set split_parse ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg); + if (ret) { + mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret); + goto MPP_TEST_OUT; + } + + data.cmd = cmd; + data.ctx = ctx; + data.mpi = mpi; + data.loop_end = 0; + data.packet = packet; + data.frame = frame; + data.frame_count = 0; + data.frame_num = cmd->frame_num; + data.reader = reader; + data.quiet = cmd->quiet; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + ret = pthread_create(&thd_in, &attr, thread_input, &data); + if (ret) { + mpp_err("failed to create thread for input ret %d\n", ret); + goto THREAD_END; + } + + ret = pthread_create(&thd_out, &attr, thread_output, &data); + if (ret) { + mpp_err("failed to create thread for output ret %d\n", ret); + goto THREAD_END; + } + + if (cmd->frame_num < 0) { + // wait for input then quit decoding + mpp_log("*******************************************\n"); + mpp_log("**** Press Enter to stop loop decoding ****\n"); + mpp_log("*******************************************\n"); + + (void)getc(stdin); + data.loop_end = 1; + } + +THREAD_END: + pthread_attr_destroy(&attr); + + pthread_join(thd_in, NULL); + pthread_join(thd_out, NULL); + + ret = mpi->reset(ctx); + if (ret) { + mpp_err("mpi->reset failed\n"); + goto MPP_TEST_OUT; + } + +MPP_TEST_OUT: + if (packet) { + mpp_packet_deinit(&packet); + packet = NULL; + } + + if (frame) { + mpp_frame_deinit(&frame); + frame = NULL; + } + + if (ctx) { + mpp_destroy(ctx); + ctx = NULL; + } + + data.frm_grp = NULL; + if (data.buf_mgr) { + dec_buf_mgr_deinit(data.buf_mgr); + data.buf_mgr = NULL; + } + + if (data.fp_output) { + fclose(data.fp_output); + data.fp_output = NULL; + } + + if (cfg) { + mpp_dec_cfg_deinit(cfg); + cfg = NULL; + } + + return ret; +} + +int main(int argc, char **argv) +{ + RK_S32 ret = 0; + MpiDecTestCmd cmd_ctx; + MpiDecTestCmd* cmd = &cmd_ctx; + + memset((void*)cmd, 0, sizeof(*cmd)); + // default use block mode + cmd->timeout = -1; + + // parse the cmd option + ret = mpi_dec_test_cmd_init(cmd, argc, argv); + if (ret) + goto RET; + + mpi_dec_test_cmd_options(cmd); + + if (cmd->type == MPP_VIDEO_CodingMJPEG) { + mpp_log("mpi_dec_mt_test not support mjpeg yet\n"); + goto RET; + } + + ret = mt_dec_decode(cmd); + if (MPP_OK == ret) + mpp_log("test success\n"); + else + mpp_err("test failed ret %d\n", ret); + +RET: + mpi_dec_test_cmd_deinit(cmd); + + return ret; +} diff --git a/test/mpi_dec_multi_test.c b/test/mpi_dec_multi_test.c new file mode 100644 index 000000000..9bae837f4 --- /dev/null +++ b/test/mpi_dec_multi_test.c @@ -0,0 +1,649 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(_WIN32) +#include "vld.h" +#endif + +#define MODULE_TAG "mpi_dec_multi_test" + +#include +#include + +#include "rk_mpi.h" + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "mpi_dec_utils.h" + +/* For each instance thread setup */ +typedef struct { + MpiDecTestCmd *cmd; + MppCtx ctx; + MppApi *mpi; + + /* end of stream flag when set quit the loop */ + RK_U32 loop_end; + + /* input and output */ + DecBufMgr buf_mgr; + MppBufferGroup frm_grp; + MppPacket packet; + MppFrame frame; + + FILE *fp_output; + RK_S32 packet_count; + RK_S32 frame_count; + RK_S32 frame_num; + + RK_S64 first_pkt; + RK_S64 first_frm; + + /* runtime flag */ + RK_U32 quiet; +} MpiDecMultiCtx; + +/* For each instance thread return value */ +typedef struct { + float frame_rate; + RK_S64 elapsed_time; + RK_S32 frame_count; + RK_S64 delay; +} MpiDecMultiCtxRet; + +typedef struct { + MpiDecTestCmd *cmd; // pointer to global command line info + + pthread_t thd; // thread for for each instance + MpiDecMultiCtx ctx; // context of decoder + MpiDecMultiCtxRet ret; // return of decoder +} MpiDecMultiCtxInfo; + +static int multi_dec_simple(MpiDecMultiCtx *data) +{ + MpiDecTestCmd *cmd = data->cmd; + RK_U32 pkt_done = 0; + RK_U32 pkt_eos = 0; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + MppPacket packet = data->packet; + FileReader reader = cmd->reader; + FileBufSlot *slot = NULL; + RK_U32 quiet = data->quiet; + MPP_RET ret = reader_index_read(reader, data->packet_count++, &slot); + + mpp_assert(ret == MPP_OK); + mpp_assert(slot); + + pkt_eos = slot->eos; + + if (pkt_eos) { + if (data->frame_num < 0 || data->frame_num > data->frame_count) { + mpp_log_q(quiet, "%p loop again\n", ctx); + data->packet_count = 0; + pkt_eos = 0; + } else { + mpp_log_q(quiet, "%p found last packet\n", ctx); + data->loop_end = 1; + } + } + + mpp_packet_set_data(packet, slot->data); + mpp_packet_set_size(packet, slot->size); + mpp_packet_set_pos(packet, slot->data); + mpp_packet_set_length(packet, slot->size); + // setup eos flag + if (pkt_eos) + mpp_packet_set_eos(packet); + + do { + RK_U32 frm_eos = 0; + RK_S32 times = 5; + // send the packet first if packet is not done + if (!pkt_done) { + ret = mpi->decode_put_packet(ctx, packet); + if (MPP_OK == ret) { + pkt_done = 1; + if (!data->first_pkt) + data->first_pkt = mpp_time(); + } + } + + // then get all available frame and release + do { + RK_S32 get_frm = 0; + MppFrame frame = NULL; + + try_again: + ret = mpi->decode_get_frame(ctx, &frame); + if (MPP_ERR_TIMEOUT == ret) { + if (times > 0) { + times--; + msleep(2); + goto try_again; + } + mpp_err("decode_get_frame failed too much time\n"); + } + if (ret) { + mpp_err("decode_get_frame failed ret %d\n", ret); + break; + } + + if (frame) { + if (mpp_frame_get_info_change(frame)) { + RK_U32 width = mpp_frame_get_width(frame); + RK_U32 height = mpp_frame_get_height(frame); + RK_U32 hor_stride = mpp_frame_get_hor_stride(frame); + RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); + RK_U32 buf_size = mpp_frame_get_buf_size(frame); + MppBufferGroup grp = NULL; + + mpp_log_q(quiet, "decode_get_frame get info changed found\n"); + mpp_log_q(quiet, "decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d", + width, height, hor_stride, ver_stride, buf_size); + + if (MPP_FRAME_FMT_IS_FBC(cmd->format) || MPP_FRAME_FMT_IS_TILE(cmd->format)) { + MppFrame frm = NULL; + + mpp_frame_init(&frm); + mpp_frame_set_width(frm, width); + mpp_frame_set_height(frm, height); + mpp_frame_set_fmt(frm, cmd->format); + + ret = mpi->control(ctx, MPP_DEC_SET_FRAME_INFO, frm); + mpp_frame_deinit(&frm); + + if (ret) { + mpp_err("set fbc frame info failed\n"); + break; + } + } + + grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode); + /* Set buffer to mpp decoder */ + ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp); + if (ret) { + mpp_err("%p set buffer group failed ret %d\n", ctx, ret); + break; + } + data->frm_grp = grp; + + /* + * All buffer group config done. Set info change ready to let + * decoder continue decoding + */ + ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); + if (ret) { + mpp_err("info change ready failed ret %d\n", ret); + break; + } + } else { + RK_U32 err_info = 0; + + if (!data->first_frm) + data->first_frm = mpp_time(); + + err_info = mpp_frame_get_errinfo(frame) | + mpp_frame_get_discard(frame); + if (err_info) { + mpp_log_q(quiet, "decoder_get_frame get err info:%d discard:%d.\n", + mpp_frame_get_errinfo(frame), + mpp_frame_get_discard(frame)); + } + mpp_log_q(quiet, "decode_get_frame get frame %d\n", + data->frame_count); + + data->frame_count++; + if (data->fp_output && !err_info) + dump_mpp_frame_to_file(frame, data->fp_output); + + fps_calc_inc(cmd->fps); + } + frm_eos = mpp_frame_get_eos(frame); + mpp_frame_deinit(&frame); + get_frm = 1; + } + + // if last packet is send but last frame is not found continue + if (pkt_eos && pkt_done && !frm_eos) { + msleep(1); + continue; + } + + if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) || + ((data->frame_num == 0) && frm_eos)) + break; + + if (get_frm) + continue; + break; + } while (1); + + if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) || + ((data->frame_num == 0) && frm_eos)) { + data->loop_end = 1; + break; + } + + if (pkt_done) + break; + + /* + * why sleep here: + * mpi->decode_put_packet will failed when packet in internal queue is + * full,waiting the package is consumed .Usually hardware decode one + * frame which resolution is 1080p needs 2 ms,so here we sleep 3ms + * * is enough. + */ + msleep(1); + } while (1); + + return ret; +} + +static int multi_dec_advanced(MpiDecMultiCtx *data) +{ + MPP_RET ret = MPP_OK; + MpiDecTestCmd *cmd = data->cmd; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + MppPacket packet = NULL; + MppFrame frame = data->frame; + MppTask task = NULL; + RK_U32 quiet = data->quiet; + FileBufSlot *slot = NULL; + + ret = reader_index_read(cmd->reader, 0, &slot); + mpp_assert(ret == MPP_OK); + mpp_assert(slot); + + mpp_packet_init_with_buffer(&packet, slot->buf); + + // setup eos flag + if (slot->eos) + mpp_packet_set_eos(packet); + + ret = mpi->poll(ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK); + if (ret) { + mpp_err("mpp input poll failed\n"); + return ret; + } + + ret = mpi->dequeue(ctx, MPP_PORT_INPUT, &task); /* input queue */ + if (ret) { + mpp_err("mpp task input dequeue failed\n"); + return ret; + } + + mpp_assert(task); + + mpp_task_meta_set_packet(task, KEY_INPUT_PACKET, packet); + mpp_task_meta_set_frame (task, KEY_OUTPUT_FRAME, frame); + + ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task); /* input queue */ + if (ret) { + mpp_err("mpp task input enqueue failed\n"); + return ret; + } + + if (!data->first_pkt) + data->first_pkt = mpp_time(); + + /* poll and wait here */ + ret = mpi->poll(ctx, MPP_PORT_OUTPUT, MPP_POLL_BLOCK); + if (ret) { + mpp_err("mpp output poll failed\n"); + return ret; + } + + ret = mpi->dequeue(ctx, MPP_PORT_OUTPUT, &task); /* output queue */ + if (ret) { + mpp_err("mpp task output dequeue failed\n"); + return ret; + } + + mpp_assert(task); + + if (task) { + MppFrame frame_out = NULL; + + mpp_task_meta_get_frame(task, KEY_OUTPUT_FRAME, &frame_out); + + if (frame) { + if (!data->first_frm) + data->first_frm = mpp_time(); + + if (data->fp_output) + dump_mpp_frame_to_file(frame, data->fp_output); + + mpp_log_q(quiet, "%p decoded frame %d\n", ctx, data->frame_count); + data->frame_count++; + + if (mpp_frame_get_eos(frame_out)) { + mpp_log_q(quiet, "%p found eos frame\n", ctx); + } + fps_calc_inc(cmd->fps); + } + + if (data->frame_num > 0) { + if (data->frame_count >= data->frame_num) + data->loop_end = 1; + } else if (data->frame_num == 0) { + if (slot->eos) + data->loop_end = 1; + } + + /* output queue */ + ret = mpi->enqueue(ctx, MPP_PORT_OUTPUT, task); + if (ret) + mpp_err("mpp task output enqueue failed\n"); + } + + /* + * The following input port task dequeue and enqueue is to make sure that + * the input packet can be released. We can directly deinit the input packet + * after frame output in most cases. + */ + if (0) { + mpp_packet_deinit(&packet); + } else { + ret = mpi->dequeue(ctx, MPP_PORT_INPUT, &task); /* input queue */ + if (ret) { + mpp_err("%p mpp task input dequeue failed\n", ctx); + return ret; + } + + mpp_assert(task); + if (task) { + MppPacket packet_out = NULL; + + mpp_task_meta_get_packet(task, KEY_INPUT_PACKET, &packet_out); + + if (!packet_out || packet_out != packet) + mpp_err_f("mismatch packet %p -> %p\n", packet, packet_out); + + mpp_packet_deinit(&packet_out); + + /* input empty task back to mpp to maintain task status */ + ret = mpi->enqueue(ctx, MPP_PORT_INPUT, task); + if (ret) + mpp_err("%p mpp task input enqueue failed\n", ctx); + } + } + + return ret; +} + +void* multi_dec_decode(void *cmd_ctx) +{ + MpiDecMultiCtxInfo *info = (MpiDecMultiCtxInfo *)cmd_ctx; + MpiDecMultiCtx *dec_ctx = &info->ctx; + MpiDecMultiCtxRet *rets = &info->ret; + MpiDecTestCmd *cmd = info->cmd; + MPP_RET ret = MPP_OK; + + // base flow context + MppCtx ctx = NULL; + MppApi *mpi = NULL; + + // input / output + MppPacket packet = NULL; + MppFrame frame = NULL; + + // config for runtime mode + MppDecCfg cfg = NULL; + RK_U32 need_split = 1; + + // paramter for resource malloc + RK_U32 width = cmd->width; + RK_U32 height = cmd->height; + MppCodingType type = cmd->type; + + // resources + MppBuffer frm_buf = NULL; + + if (cmd->have_output) { + dec_ctx->fp_output = fopen(cmd->file_output, "w+b"); + if (NULL == dec_ctx->fp_output) { + mpp_err("failed to open output file %s\n", cmd->file_output); + goto MPP_TEST_OUT; + } + } + + ret = dec_buf_mgr_init(&dec_ctx->buf_mgr); + if (ret) { + mpp_err("dec_buf_mgr_init failed\n"); + goto MPP_TEST_OUT; + } + + if (cmd->simple) { + ret = mpp_packet_init(&packet, NULL, 0); + if (ret) { + mpp_err("mpp_packet_init failed\n"); + goto MPP_TEST_OUT; + } + } else { + RK_U32 hor_stride = MPP_ALIGN(width, 16); + RK_U32 ver_stride = MPP_ALIGN(height, 16); + + ret = mpp_frame_init(&frame); /* output frame */ + if (ret) { + mpp_err("mpp_frame_init failed\n"); + goto MPP_TEST_OUT; + } + + dec_ctx->frm_grp = dec_buf_mgr_setup(dec_ctx->buf_mgr, hor_stride * ver_stride * 2, 4, cmd->buf_mode); + if (!dec_ctx->frm_grp) { + mpp_err("failed to get buffer group for input frame ret %d\n", ret); + ret = MPP_NOK; + goto MPP_TEST_OUT; + } + + /* + * NOTE: For jpeg could have YUV420 and YUV422 the buffer should be + * larger for output. And the buffer dimension should align to 16. + * YUV420 buffer is 3/2 times of w*h. + * YUV422 buffer is 2 times of w*h. + * So create larger buffer with 2 times w*h. + */ + ret = mpp_buffer_get(dec_ctx->frm_grp, &frm_buf, hor_stride * ver_stride * 2); + if (ret) { + mpp_err("failed to get buffer for input frame ret %d\n", ret); + goto MPP_TEST_OUT; + } + + mpp_frame_set_buffer(frame, frm_buf); + } + + // decoder demo + ret = mpp_create(&ctx, &mpi); + if (ret) { + mpp_err("mpp_create failed\n"); + goto MPP_TEST_OUT; + } + + mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n", + ctx, width, height, type); + + ret = mpp_init(ctx, MPP_CTX_DEC, type); + if (ret) { + mpp_err("mpp_init failed\n"); + goto MPP_TEST_OUT; + } + + mpp_dec_cfg_init(&cfg); + + /* get default config from decoder context */ + ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg); + if (ret) { + mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + /* + * split_parse is to enable mpp internal frame spliter when the input + * packet is not aplited into frames. + */ + ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split); + if (ret) { + mpp_err("%p failed to set split_parse ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg); + if (ret) { + mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret); + goto MPP_TEST_OUT; + } + + dec_ctx->cmd = cmd; + dec_ctx->ctx = ctx; + dec_ctx->mpi = mpi; + dec_ctx->packet = packet; + dec_ctx->frame = frame; + dec_ctx->packet_count = 0; + dec_ctx->frame_count = 0; + dec_ctx->frame_num = cmd->frame_num; + dec_ctx->quiet = cmd->quiet; + + RK_S64 t_s, t_e; + + t_s = mpp_time(); + if (cmd->simple) { + while (!dec_ctx->loop_end) + multi_dec_simple(dec_ctx); + } else { + while (!dec_ctx->loop_end) + multi_dec_advanced(dec_ctx); + } + t_e = mpp_time(); + + ret = mpi->reset(ctx); + if (ret) { + mpp_err("mpi->reset failed\n"); + goto MPP_TEST_OUT; + } + + rets->elapsed_time = t_e - t_s; + rets->frame_count = dec_ctx->frame_count; + rets->frame_rate = (float)dec_ctx->frame_count * 1000000 / rets->elapsed_time; + rets->delay = dec_ctx->first_frm - dec_ctx->first_pkt; + +MPP_TEST_OUT: + if (packet) { + mpp_packet_deinit(&packet); + packet = NULL; + } + + if (frame) { + mpp_frame_deinit(&frame); + frame = NULL; + } + + if (ctx) { + mpp_destroy(ctx); + ctx = NULL; + } + + if (!cmd->simple) { + if (frm_buf) { + mpp_buffer_put(frm_buf); + frm_buf = NULL; + } + } + + dec_ctx->frm_grp = NULL; + if (dec_ctx->buf_mgr) { + dec_buf_mgr_deinit(dec_ctx->buf_mgr); + dec_ctx->buf_mgr = NULL; + } + + if (dec_ctx->fp_output) { + fclose(dec_ctx->fp_output); + dec_ctx->fp_output = NULL; + } + + if (cfg) { + mpp_dec_cfg_deinit(cfg); + cfg = NULL; + } + + return NULL; +} + +int main(int argc, char **argv) +{ + RK_S32 ret = 0; + MpiDecTestCmd cmd_ctx; + MpiDecTestCmd* cmd = &cmd_ctx; + MpiDecMultiCtxInfo *ctxs = NULL; + RK_S32 i = 0; + float total_rate = 0.0; + + memset((void*)cmd, 0, sizeof(*cmd)); + cmd->nthreads = 1; + + // parse the cmd option + ret = mpi_dec_test_cmd_init(cmd, argc, argv); + if (ret) + goto RET; + + mpi_dec_test_cmd_options(cmd); + + cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0); + + ctxs = mpp_calloc(MpiDecMultiCtxInfo, cmd->nthreads); + if (NULL == ctxs) { + mpp_err("failed to alloc context for instances\n"); + return -1; + } + + for (i = 0; i < cmd->nthreads; i++) { + ctxs[i].cmd = cmd; + + ret = pthread_create(&ctxs[i].thd, NULL, multi_dec_decode, &ctxs[i]); + if (ret) { + mpp_log("failed to create thread %d\n", i); + return ret; + } + } + + if (cmd->frame_num < 0) { + // wait for input then quit decoding + mpp_log("*******************************************\n"); + mpp_log("**** Press Enter to stop loop decoding ****\n"); + mpp_log("*******************************************\n"); + + (void)getc(stdin); + for (i = 0; i < cmd->nthreads; i++) + ctxs[i].ctx.loop_end = 1; + } + + for (i = 0; i < cmd->nthreads; i++) + pthread_join(ctxs[i].thd, NULL); + + for (i = 0; i < cmd->nthreads; i++) { + MpiDecMultiCtxRet *dec_ret = &ctxs[i].ret; + + mpp_log("chn %2d decode %d frames time %lld ms delay %3d ms fps %3.2f\n", i, + dec_ret->frame_count, (RK_S64)(dec_ret->elapsed_time / 1000), + (RK_S32)(dec_ret->delay / 1000), dec_ret->frame_rate); + + total_rate += dec_ret->frame_rate; + } + mpp_free(ctxs); + ctxs = NULL; + + total_rate /= cmd->nthreads; + mpp_log("average frame rate %.2f\n", total_rate); + +RET: + mpi_dec_test_cmd_deinit(cmd); + + return (int)total_rate; +} diff --git a/test/mpi_dec_nt_test.c b/test/mpi_dec_nt_test.c new file mode 100644 index 000000000..8da5c3391 --- /dev/null +++ b/test/mpi_dec_nt_test.c @@ -0,0 +1,521 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#if defined(_WIN32) +#include "vld.h" +#endif + +#define MODULE_TAG "mpi_dec_nt_test" + +#include +#include "rk_mpi.h" + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_common.h" +#include "mpi_dec_utils.h" + +typedef struct { + MpiDecTestCmd *cmd; + MppCtx ctx; + MppApi *mpi; + RK_U32 quiet; + + /* end of stream flag when set quit the loop */ + RK_U32 loop_end; + + /* input and output */ + DecBufMgr buf_mgr; + MppBufferGroup frm_grp; + MppPacket packet; + MppFrame frame; + + FILE *fp_output; + RK_S32 frame_count; + RK_S32 frame_num; + + RK_S64 first_pkt; + RK_S64 first_frm; + + size_t max_usage; + float frame_rate; + RK_S64 elapsed_time; + RK_S64 delay; + FILE *fp_verify; + FrmCrc checkcrc; +} MpiDecLoopData; + +static int dec_loop(MpiDecLoopData *data) +{ + RK_U32 pkt_done = 0; + RK_U32 pkt_eos = 0; + MPP_RET ret = MPP_OK; + MpiDecTestCmd *cmd = data->cmd; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + MppPacket packet = data->packet; + FileBufSlot *slot = NULL; + RK_U32 quiet = data->quiet; + FrmCrc *checkcrc = &data->checkcrc; + + // when packet size is valid read the input binary file + ret = reader_read(cmd->reader, &slot); + + mpp_assert(ret == MPP_OK); + mpp_assert(slot); + + pkt_eos = slot->eos; + + if (pkt_eos) { + if (data->frame_num < 0 || data->frame_num > data->frame_count) { + mpp_log_q(quiet, "%p loop again\n", ctx); + reader_rewind(cmd->reader); + pkt_eos = 0; + } else { + mpp_log_q(quiet, "%p found last packet\n", ctx); + data->loop_end = 1; + } + } + + if (!slot->buf) { + /* non-jpeg decoding */ + mpp_packet_set_data(packet, slot->data); + mpp_packet_set_size(packet, slot->size); + mpp_packet_set_pos(packet, slot->data); + mpp_packet_set_length(packet, slot->size); + } else { + /* jpeg decoding */ + void *buf = mpp_buffer_get_ptr(slot->buf); + size_t size = mpp_buffer_get_size(slot->buf); + + mpp_packet_set_data(packet, buf); + mpp_packet_set_size(packet, size); + mpp_packet_set_pos(packet, buf); + mpp_packet_set_length(packet, size); + mpp_packet_set_buffer(packet, slot->buf); + } + + // setup eos flag + if (pkt_eos) + mpp_packet_set_eos(packet); + + do { + RK_U32 frm_eos = 0; + RK_S32 get_frm = 0; + MppFrame frame = NULL; + + // send the packet first if packet is not done + ret = mpi->decode(ctx, packet, &frame); + if (ret) + mpp_err("decode failed ret %d\n", ret); + + // then get all available frame and release + if (frame) { + if (mpp_frame_get_info_change(frame)) { + RK_U32 width = mpp_frame_get_width(frame); + RK_U32 height = mpp_frame_get_height(frame); + RK_U32 hor_stride = mpp_frame_get_hor_stride(frame); + RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); + RK_U32 buf_size = mpp_frame_get_buf_size(frame); + MppBufferGroup grp = NULL; + + mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx); + mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d", + ctx, width, height, hor_stride, ver_stride, buf_size); + + if (MPP_FRAME_FMT_IS_FBC(cmd->format) || MPP_FRAME_FMT_IS_TILE(cmd->format)) { + MppFrame frm = NULL; + + mpp_frame_init(&frm); + mpp_frame_set_width(frm, width); + mpp_frame_set_height(frm, height); + mpp_frame_set_fmt(frm, cmd->format); + + ret = mpi->control(ctx, MPP_DEC_SET_FRAME_INFO, frm); + mpp_frame_deinit(&frm); + + if (ret) { + mpp_err("set fbc frame info failed\n"); + break; + } + } + + grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode); + /* Set buffer to mpp decoder */ + ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp); + if (ret) { + mpp_err("%p set buffer group failed ret %d\n", ctx, ret); + break; + } + + data->frm_grp = grp; + + /* + * All buffer group config done. Set info change ready to let + * decoder continue decoding + */ + ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); + if (ret) { + mpp_err("%p info change ready failed ret %d\n", ctx, ret); + break; + } + + mpp_frame_deinit(&frame); + continue; + } else { + char log_buf[256]; + RK_S32 log_size = sizeof(log_buf) - 1; + RK_S32 log_len = 0; + RK_U32 err_info = mpp_frame_get_errinfo(frame); + RK_U32 discard = mpp_frame_get_discard(frame); + + if (!data->first_frm) + data->first_frm = mpp_time(); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + "decode get frame %d", data->frame_count); + + if (mpp_frame_has_meta(frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + RK_S32 temporal_id = 0; + + mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + " tid %d", temporal_id); + } + + if (err_info || discard) { + log_len += snprintf(log_buf + log_len, log_size - log_len, + " err %x discard %x", err_info, discard); + } + mpp_log_q(quiet, "%p %s\n", ctx, log_buf); + + data->frame_count++; + if (data->fp_output && !err_info) + dump_mpp_frame_to_file(frame, data->fp_output); + + if (data->fp_verify) { + calc_frm_crc(frame, checkcrc); + write_frm_crc(data->fp_verify, checkcrc); + } + + fps_calc_inc(cmd->fps); + } + frm_eos = mpp_frame_get_eos(frame); + mpp_frame_deinit(&frame); + get_frm = 1; + } + + // try get runtime frame memory usage + if (data->frm_grp) { + size_t usage = mpp_buffer_group_usage(data->frm_grp); + if (usage > data->max_usage) + data->max_usage = usage; + } + + // when get one output frame check the output frame count limit + if (get_frm) { + if (data->frame_num > 0) { + // when get enough frame quit + if (data->frame_count >= data->frame_num) { + data->loop_end = 1; + break; + } + } else { + // when get last frame quit + if (frm_eos) { + mpp_log_q(quiet, "%p found last packet\n", ctx); + data->loop_end = 1; + break; + } + } + } + + if (packet) { + if (mpp_packet_get_length(packet)) { + msleep(1); + continue; + } + + if (!data->first_pkt) + data->first_pkt = mpp_time(); + + packet = NULL; + pkt_done = 1; + } + + mpp_assert(pkt_done); + + // if last packet is send but last frame is not found continue + if (pkt_eos && !frm_eos) { + msleep(1); + continue; + } + + if (pkt_done) + break; + + /* + * why sleep here: + * mpi->decode_put_packet will failed when packet in internal queue is + * full,waiting the package is consumed .Usually hardware decode one + * frame which resolution is 1080p needs 2 ms,so here we sleep 1ms + * * is enough. + */ + msleep(1); + } while (1); + + return ret; +} + +void *thread_decode(void *arg) +{ + MpiDecLoopData *data = (MpiDecLoopData *)arg; + RK_S64 t_s, t_e; + + memset(&data->checkcrc, 0, sizeof(data->checkcrc)); + data->checkcrc.luma.sum = mpp_malloc(RK_ULONG, 512); + data->checkcrc.chroma.sum = mpp_malloc(RK_ULONG, 512); + + t_s = mpp_time(); + + while (!data->loop_end) + dec_loop(data); + + t_e = mpp_time(); + data->elapsed_time = t_e - t_s; + data->frame_rate = (float)data->frame_count * 1000000 / data->elapsed_time; + data->delay = data->first_frm - data->first_pkt; + + mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n", + data->frame_count, (RK_S64)(data->elapsed_time / 1000), + (RK_S32)(data->delay / 1000), data->frame_rate); + + MPP_FREE(data->checkcrc.luma.sum); + MPP_FREE(data->checkcrc.chroma.sum); + + return NULL; +} + +int dec_nt_decode(MpiDecTestCmd *cmd) +{ + // base flow context + MppCtx ctx = NULL; + MppApi *mpi = NULL; + + // input / output + MppPacket packet = NULL; + MppFrame frame = NULL; + + // paramter for resource malloc + RK_U32 width = cmd->width; + RK_U32 height = cmd->height; + MppCodingType type = cmd->type; + + // config for runtime mode + MppDecCfg cfg = NULL; + RK_U32 need_split = 1; + + // resources + MppBuffer frm_buf = NULL; + pthread_t thd; + pthread_attr_t attr; + MpiDecLoopData data; + MPP_RET ret = MPP_OK; + + mpp_log("mpi_dec_test start\n"); + memset(&data, 0, sizeof(data)); + pthread_attr_init(&attr); + + cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0); + + if (cmd->have_output) { + data.fp_output = fopen(cmd->file_output, "w+b"); + if (NULL == data.fp_output) { + mpp_err("failed to open output file %s\n", cmd->file_output); + goto MPP_TEST_OUT; + } + } + + if (cmd->file_slt) { + data.fp_verify = fopen(cmd->file_slt, "wt"); + if (!data.fp_verify) + mpp_err("failed to open verify file %s\n", cmd->file_slt); + } + + ret = dec_buf_mgr_init(&data.buf_mgr); + if (ret) { + mpp_err("dec_buf_mgr_init failed\n"); + goto MPP_TEST_OUT; + } + + ret = mpp_packet_init(&packet, NULL, 0); + mpp_err_f("mpp_packet_init get %p\n", packet); + if (ret) { + mpp_err("mpp_packet_init failed\n"); + goto MPP_TEST_OUT; + } + + // decoder demo + ret = mpp_create(&ctx, &mpi); + if (ret) { + mpp_err("mpp_create failed\n"); + goto MPP_TEST_OUT; + } + + mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n", + ctx, width, height, type); + + ret = mpi->control(ctx, MPP_SET_DISABLE_THREAD, NULL); + + ret = mpp_init(ctx, MPP_CTX_DEC, type); + if (ret) { + mpp_err("%p mpp_init failed\n", ctx); + goto MPP_TEST_OUT; + } + + mpp_dec_cfg_init(&cfg); + + /* get default config from decoder context */ + ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg); + if (ret) { + mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + /* + * split_parse is to enable mpp internal frame spliter when the input + * packet is not aplited into frames. + */ + ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split); + if (ret) { + mpp_err("%p failed to set split_parse ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg); + if (ret) { + mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret); + goto MPP_TEST_OUT; + } + + data.cmd = cmd; + data.ctx = ctx; + data.mpi = mpi; + data.loop_end = 0; + data.packet = packet; + data.frame = frame; + data.frame_count = 0; + data.frame_num = cmd->frame_num; + data.quiet = cmd->quiet; + + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + ret = pthread_create(&thd, &attr, thread_decode, &data); + if (ret) { + mpp_err("failed to create thread for input ret %d\n", ret); + goto MPP_TEST_OUT; + } + + if (cmd->frame_num < 0) { + // wait for input then quit decoding + mpp_log("*******************************************\n"); + mpp_log("**** Press Enter to stop loop decoding ****\n"); + mpp_log("*******************************************\n"); + + (void)getc(stdin); + data.loop_end = 1; + } + + pthread_join(thd, NULL); + + cmd->max_usage = data.max_usage; + + ret = mpi->reset(ctx); + if (ret) { + mpp_err("%p mpi->reset failed\n", ctx); + goto MPP_TEST_OUT; + } + +MPP_TEST_OUT: + if (data.packet) { + mpp_packet_deinit(&data.packet); + data.packet = NULL; + } + + if (frame) { + mpp_frame_deinit(&frame); + frame = NULL; + } + + if (ctx) { + mpp_destroy(ctx); + ctx = NULL; + } + + if (!cmd->simple) { + if (frm_buf) { + mpp_buffer_put(frm_buf); + frm_buf = NULL; + } + } + + data.frm_grp = NULL; + if (data.buf_mgr) { + dec_buf_mgr_deinit(data.buf_mgr); + data.buf_mgr = NULL; + } + + if (data.fp_output) { + fclose(data.fp_output); + data.fp_output = NULL; + } + + if (data.fp_verify) { + fclose(data.fp_verify); + data.fp_verify = NULL; + } + + if (cfg) { + mpp_dec_cfg_deinit(cfg); + cfg = NULL; + } + + pthread_attr_destroy(&attr); + + return ret; +} + +int main(int argc, char **argv) +{ + RK_S32 ret = 0; + MpiDecTestCmd cmd_ctx; + MpiDecTestCmd* cmd = &cmd_ctx; + + memset((void*)cmd, 0, sizeof(*cmd)); + cmd->format = MPP_FMT_BUTT; + cmd->pkt_size = MPI_DEC_STREAM_SIZE; + + // parse the cmd option + ret = mpi_dec_test_cmd_init(cmd, argc, argv); + if (ret) + goto RET; + + mpi_dec_test_cmd_options(cmd); + + ret = dec_nt_decode(cmd); + if (MPP_OK == ret) + mpp_log("test success max memory %.2f MB\n", cmd->max_usage / (float)(1 << 20)); + else + mpp_err("test failed ret %d\n", ret); + +RET: + mpi_dec_test_cmd_deinit(cmd); + + return ret; +} + diff --git a/test/mpi_dec_test.c b/test/mpi_dec_test.c new file mode 100644 index 000000000..a064cb827 --- /dev/null +++ b/test/mpi_dec_test.c @@ -0,0 +1,656 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(_WIN32) +#include "vld.h" +#endif + +#define MODULE_TAG "mpi_dec_test" + +#include +#include "rk_mpi.h" + +#include "mpp_mem.h" +#include "mpp_env.h" +#include "mpp_time.h" +#include "mpp_common.h" +#include "mpi_dec_utils.h" + +typedef struct { + MpiDecTestCmd *cmd; + MppCtx ctx; + MppApi *mpi; + RK_U32 quiet; + + /* end of stream flag when set quit the loop */ + RK_U32 loop_end; + + /* input and output */ + DecBufMgr buf_mgr; + MppBufferGroup frm_grp; + MppPacket packet; + MppFrame frame; + + FILE *fp_output; + RK_S32 frame_count; + RK_S32 frame_num; + + RK_S64 first_pkt; + RK_S64 first_frm; + + size_t max_usage; + float frame_rate; + RK_S64 elapsed_time; + RK_S64 delay; + FILE *fp_verify; + FrmCrc checkcrc; +} MpiDecLoopData; + +static int dec_simple(MpiDecLoopData *data) +{ + RK_U32 pkt_done = 0; + RK_U32 pkt_eos = 0; + MPP_RET ret = MPP_OK; + MpiDecTestCmd *cmd = data->cmd; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + MppPacket packet = data->packet; + FileBufSlot *slot = NULL; + RK_U32 quiet = data->quiet; + FrmCrc *checkcrc = &data->checkcrc; + + // when packet size is valid read the input binary file + ret = reader_read(cmd->reader, &slot); + + mpp_assert(ret == MPP_OK); + mpp_assert(slot); + + pkt_eos = slot->eos; + + if (pkt_eos) { + if (data->frame_num < 0 || data->frame_num > data->frame_count) { + mpp_log_q(quiet, "%p loop again\n", ctx); + reader_rewind(cmd->reader); + pkt_eos = 0; + } else { + mpp_log_q(quiet, "%p found last packet\n", ctx); + data->loop_end = 1; + } + } + + mpp_packet_set_data(packet, slot->data); + mpp_packet_set_size(packet, slot->size); + mpp_packet_set_pos(packet, slot->data); + mpp_packet_set_length(packet, slot->size); + // setup eos flag + if (pkt_eos) + mpp_packet_set_eos(packet); + + do { + RK_U32 frm_eos = 0; + RK_S32 times = 30; + + // send the packet first if packet is not done + if (!pkt_done) { + ret = mpi->decode_put_packet(ctx, packet); + if (MPP_OK == ret) { + pkt_done = 1; + if (!data->first_pkt) + data->first_pkt = mpp_time(); + } + } + + // then get all available frame and release + do { + RK_S32 get_frm = 0; + MppFrame frame = NULL; + + try_again: + ret = mpi->decode_get_frame(ctx, &frame); + if (MPP_ERR_TIMEOUT == ret) { + if (times > 0) { + times--; + msleep(1); + goto try_again; + } + mpp_err("%p decode_get_frame failed too much time\n", ctx); + } + if (ret) { + mpp_err("%p decode_get_frame failed ret %d\n", ret, ctx); + break; + } + + if (frame) { + if (mpp_frame_get_info_change(frame)) { + RK_U32 width = mpp_frame_get_width(frame); + RK_U32 height = mpp_frame_get_height(frame); + RK_U32 hor_stride = mpp_frame_get_hor_stride(frame); + RK_U32 ver_stride = mpp_frame_get_ver_stride(frame); + RK_U32 buf_size = mpp_frame_get_buf_size(frame); + MppBufferGroup grp = NULL; + + mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx); + mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d", + ctx, width, height, hor_stride, ver_stride, buf_size); + + if (MPP_FRAME_FMT_IS_FBC(cmd->format) || MPP_FRAME_FMT_IS_TILE(cmd->format)) { + MppFrame frm = NULL; + + mpp_frame_init(&frm); + mpp_frame_set_width(frm, width); + mpp_frame_set_height(frm, height); + mpp_frame_set_fmt(frm, cmd->format); + + ret = mpi->control(ctx, MPP_DEC_SET_FRAME_INFO, frm); + mpp_frame_deinit(&frm); + + if (ret) { + mpp_err("set fbc frame info failed\n"); + break; + } + } + + grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode); + /* Set buffer to mpp decoder */ + ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp); + if (ret) { + mpp_err("%p set buffer group failed ret %d\n", ctx, ret); + break; + } + data->frm_grp = grp; + + /* + * All buffer group config done. Set info change ready to let + * decoder continue decoding + */ + ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); + if (ret) { + mpp_err("%p info change ready failed ret %d\n", ctx, ret); + break; + } + } else { + char log_buf[256]; + RK_S32 log_size = sizeof(log_buf) - 1; + RK_S32 log_len = 0; + RK_U32 err_info = mpp_frame_get_errinfo(frame); + RK_U32 discard = mpp_frame_get_discard(frame); + + if (!data->first_frm) + data->first_frm = mpp_time(); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + "decode get frame %d", data->frame_count); + + if (mpp_frame_has_meta(frame)) { + MppMeta meta = mpp_frame_get_meta(frame); + RK_S32 temporal_id = 0; + + mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + " tid %d", temporal_id); + } + + if (err_info || discard) { + log_len += snprintf(log_buf + log_len, log_size - log_len, + " err %x discard %x", err_info, discard); + } + mpp_log_q(quiet, "%p %s\n", ctx, log_buf); + + data->frame_count++; + if (data->fp_output && !err_info) + dump_mpp_frame_to_file(frame, data->fp_output); + + if (data->fp_verify) { + calc_frm_crc(frame, checkcrc); + write_frm_crc(data->fp_verify, checkcrc); + } + + fps_calc_inc(cmd->fps); + } + frm_eos = mpp_frame_get_eos(frame); + mpp_frame_deinit(&frame); + get_frm = 1; + } + + // try get runtime frame memory usage + if (data->frm_grp) { + size_t usage = mpp_buffer_group_usage(data->frm_grp); + if (usage > data->max_usage) + data->max_usage = usage; + } + + // if last packet is send but last frame is not found continue + if (pkt_eos && pkt_done && !frm_eos) { + msleep(1); + continue; + } + + if (frm_eos) { + mpp_log_q(quiet, "%p found last packet\n", ctx); + break; + } + + if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) || + ((data->frame_num == 0) && frm_eos)) + break; + + if (get_frm) + continue; + break; + } while (1); + + if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) || + ((data->frame_num == 0) && frm_eos)) { + data->loop_end = 1; + break; + } + + if (pkt_done) + break; + + /* + * why sleep here: + * mpi->decode_put_packet will failed when packet in internal queue is + * full,waiting the package is consumed .Usually hardware decode one + * frame which resolution is 1080p needs 2 ms,so here we sleep 1ms + * * is enough. + */ + msleep(1); + } while (1); + + return ret; +} + +static int dec_advanced(MpiDecLoopData *data) +{ + MPP_RET ret = MPP_OK; + MpiDecTestCmd *cmd = data->cmd; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + MppPacket packet = NULL; + MppPacket packet_ret = NULL; + MppFrame frame = data->frame; + MppFrame frame_ret = NULL; + MppMeta meta = NULL; + RK_U32 quiet = data->quiet; + FileBufSlot *slot = NULL; + FrmCrc *checkcrc = &data->checkcrc; + + ret = reader_index_read(cmd->reader, 0, &slot); + mpp_assert(ret == MPP_OK); + mpp_assert(slot); + + mpp_packet_init_with_buffer(&packet, slot->buf); + + // setup eos flag + if (slot->eos) + mpp_packet_set_eos(packet); + + /* use the MppFrame with prealloced buffer and do not release */ + meta = mpp_packet_get_meta(packet); + if (meta) + mpp_meta_set_frame(meta, KEY_OUTPUT_FRAME, frame); + + ret = mpi->decode_put_packet(ctx, packet); + if (ret) { + mpp_err("%p mpp decode put packet failed ret %d\n", ctx, ret); + data->loop_end = 1; + goto DONE; + } + + if (!data->first_pkt) + data->first_pkt = mpp_time(); + + ret = mpi->decode_get_frame(ctx, &frame_ret); + if (ret || !frame_ret) { + mpp_err("%p mpp decode get frame failed ret %d frame %p\n", ctx, ret, frame_ret); + data->loop_end = 1; + goto DONE; + } + + if (!data->first_frm) + data->first_frm = mpp_time(); + + if (frame_ret != frame) + mpp_err_f("mismatch frame %p -> %p\n", frame_ret, frame); + + /* write frame to file here */ + if (data->fp_output) + dump_mpp_frame_to_file(frame_ret, data->fp_output); + + if (data->fp_verify) { + calc_frm_crc(frame_ret, checkcrc); + write_frm_crc(data->fp_verify, checkcrc); + } + + mpp_log_q(quiet, "%p decoded frame %d\n", ctx, data->frame_count); + data->frame_count++; + + if (mpp_frame_get_eos(frame_ret)) + mpp_log_q(quiet, "%p found eos frame\n", ctx); + + fps_calc_inc(cmd->fps); + + meta = mpp_frame_get_meta(frame); + if (meta) { + ret = mpp_meta_get_packet(meta, KEY_INPUT_PACKET, &packet_ret); + if (ret || !packet_ret) { + mpp_err("%p mpp meta get packet failed ret %d\n", ctx, ret); + goto DONE; + } + + if (packet_ret != packet) + mpp_err_f("mismatch packet %p -> %p\n", packet, packet_ret); + } + + if (data->frame_num > 0) { + if (data->frame_count >= data->frame_num) + data->loop_end = 1; + } else if (data->frame_num == 0) { + if (slot->eos) + data->loop_end = 1; + } + +DONE: + mpp_packet_deinit(&packet); + + return ret; +} + +void *thread_decode(void *arg) +{ + MpiDecLoopData *data = (MpiDecLoopData *)arg; + MpiDecTestCmd *cmd = data->cmd; + MppCtx ctx = data->ctx; + MppApi *mpi = data->mpi; + RK_S64 t_s, t_e; + + memset(&data->checkcrc, 0, sizeof(data->checkcrc)); + data->checkcrc.luma.sum = mpp_malloc(RK_ULONG, 512); + data->checkcrc.chroma.sum = mpp_malloc(RK_ULONG, 512); + + t_s = mpp_time(); + + if (cmd->simple) { + while (!data->loop_end) + dec_simple(data); + } else { + /* NOTE: change output format before jpeg decoding */ + if (MPP_FRAME_FMT_IS_YUV(cmd->format) || MPP_FRAME_FMT_IS_RGB(cmd->format)) { + MPP_RET ret = mpi->control(ctx, MPP_DEC_SET_OUTPUT_FORMAT, &cmd->format); + if (ret) { + mpp_err("Failed to set output format 0x%x\n", cmd->format); + return NULL; + } + } + + while (!data->loop_end) + dec_advanced(data); + } + + t_e = mpp_time(); + data->elapsed_time = t_e - t_s; + data->frame_rate = (float)data->frame_count * 1000000 / data->elapsed_time; + data->delay = data->first_frm - data->first_pkt; + + mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n", + data->frame_count, (RK_S64)(data->elapsed_time / 1000), + (RK_S32)(data->delay / 1000), data->frame_rate); + + MPP_FREE(data->checkcrc.luma.sum); + MPP_FREE(data->checkcrc.chroma.sum); + + return NULL; +} + +int dec_decode(MpiDecTestCmd *cmd) +{ + // base flow context + MppCtx ctx = NULL; + MppApi *mpi = NULL; + + // input / output + MppPacket packet = NULL; + MppFrame frame = NULL; + + // paramter for resource malloc + RK_U32 width = cmd->width; + RK_U32 height = cmd->height; + MppCodingType type = cmd->type; + + // config for runtime mode + MppDecCfg cfg = NULL; + RK_U32 need_split = 1; + + // resources + MppBuffer frm_buf = NULL; + pthread_t thd; + pthread_attr_t attr; + MpiDecLoopData data; + MPP_RET ret = MPP_OK; + + mpp_log("mpi_dec_test start\n"); + memset(&data, 0, sizeof(data)); + pthread_attr_init(&attr); + + cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0); + + if (cmd->have_output) { + data.fp_output = fopen(cmd->file_output, "w+b"); + if (NULL == data.fp_output) { + mpp_err("failed to open output file %s\n", cmd->file_output); + goto MPP_TEST_OUT; + } + } + + if (cmd->file_slt) { + data.fp_verify = fopen(cmd->file_slt, "wt"); + if (!data.fp_verify) + mpp_err("failed to open verify file %s\n", cmd->file_slt); + } + + ret = dec_buf_mgr_init(&data.buf_mgr); + if (ret) { + mpp_err("dec_buf_mgr_init failed\n"); + goto MPP_TEST_OUT; + } + + if (cmd->simple) { + ret = mpp_packet_init(&packet, NULL, 0); + if (ret) { + mpp_err("mpp_packet_init failed\n"); + goto MPP_TEST_OUT; + } + } else { + RK_U32 hor_stride = MPP_ALIGN(width, 16); + RK_U32 ver_stride = MPP_ALIGN(height, 16); + + ret = mpp_frame_init(&frame); /* output frame */ + if (ret) { + mpp_err("mpp_frame_init failed\n"); + goto MPP_TEST_OUT; + } + + data.frm_grp = dec_buf_mgr_setup(data.buf_mgr, hor_stride * ver_stride * 4, 4, cmd->buf_mode); + if (!data.frm_grp) { + mpp_err("failed to get buffer group for input frame ret %d\n", ret); + ret = MPP_NOK; + goto MPP_TEST_OUT; + } + + /* + * NOTE: For jpeg could have YUV420 and YUV422 the buffer should be + * larger for output. And the buffer dimension should align to 16. + * YUV420 buffer is 3/2 times of w*h. + * YUV422 buffer is 2 times of w*h. + * So create larger buffer with 2 times w*h. + */ + ret = mpp_buffer_get(data.frm_grp, &frm_buf, hor_stride * ver_stride * 4); + if (ret) { + mpp_err("failed to get buffer for input frame ret %d\n", ret); + goto MPP_TEST_OUT; + } + + mpp_frame_set_buffer(frame, frm_buf); + } + + // decoder demo + ret = mpp_create(&ctx, &mpi); + if (ret) { + mpp_err("mpp_create failed\n"); + goto MPP_TEST_OUT; + } + + mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n", + ctx, width, height, type); + + ret = mpp_init(ctx, MPP_CTX_DEC, type); + if (ret) { + mpp_err("%p mpp_init failed\n", ctx); + goto MPP_TEST_OUT; + } + + mpp_dec_cfg_init(&cfg); + + /* get default config from decoder context */ + ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg); + if (ret) { + mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + /* + * split_parse is to enable mpp internal frame spliter when the input + * packet is not aplited into frames. + */ + ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split); + if (ret) { + mpp_err("%p failed to set split_parse ret %d\n", ctx, ret); + goto MPP_TEST_OUT; + } + + ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg); + if (ret) { + mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret); + goto MPP_TEST_OUT; + } + + data.cmd = cmd; + data.ctx = ctx; + data.mpi = mpi; + data.loop_end = 0; + data.packet = packet; + data.frame = frame; + data.frame_count = 0; + data.frame_num = cmd->frame_num; + data.quiet = cmd->quiet; + + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + ret = pthread_create(&thd, &attr, thread_decode, &data); + if (ret) { + mpp_err("failed to create thread for input ret %d\n", ret); + goto MPP_TEST_OUT; + } + + if (cmd->frame_num < 0) { + // wait for input then quit decoding + mpp_log("*******************************************\n"); + mpp_log("**** Press Enter to stop loop decoding ****\n"); + mpp_log("*******************************************\n"); + + (void)getc(stdin); + data.loop_end = 1; + } + + pthread_join(thd, NULL); + + cmd->max_usage = data.max_usage; + + ret = mpi->reset(ctx); + if (ret) { + mpp_err("%p mpi->reset failed\n", ctx); + goto MPP_TEST_OUT; + } + +MPP_TEST_OUT: + if (data.packet) { + mpp_packet_deinit(&data.packet); + data.packet = NULL; + } + + if (frame) { + mpp_frame_deinit(&frame); + frame = NULL; + } + + if (ctx) { + mpp_destroy(ctx); + ctx = NULL; + } + + if (!cmd->simple) { + if (frm_buf) { + mpp_buffer_put(frm_buf); + frm_buf = NULL; + } + } + + data.frm_grp = NULL; + if (data.buf_mgr) { + dec_buf_mgr_deinit(data.buf_mgr); + data.buf_mgr = NULL; + } + + if (data.fp_output) { + fclose(data.fp_output); + data.fp_output = NULL; + } + + if (data.fp_verify) { + fclose(data.fp_verify); + data.fp_verify = NULL; + } + + if (cfg) { + mpp_dec_cfg_deinit(cfg); + cfg = NULL; + } + + pthread_attr_destroy(&attr); + + return ret; +} + +int main(int argc, char **argv) +{ + RK_S32 ret = 0; + MpiDecTestCmd cmd_ctx; + MpiDecTestCmd* cmd = &cmd_ctx; + + memset((void*)cmd, 0, sizeof(*cmd)); + cmd->format = MPP_FMT_BUTT; + cmd->pkt_size = MPI_DEC_STREAM_SIZE; + + // parse the cmd option + ret = mpi_dec_test_cmd_init(cmd, argc, argv); + if (ret) + goto RET; + + mpi_dec_test_cmd_options(cmd); + + ret = dec_decode(cmd); + if (MPP_OK == ret) + mpp_log("test success max memory %.2f MB\n", cmd->max_usage / (float)(1 << 20)); + else + mpp_err("test failed ret %d\n", ret); + +RET: + mpi_dec_test_cmd_deinit(cmd); + + return ret; +} + diff --git a/test/mpi_enc_mt_test.c b/test/mpi_enc_mt_test.c new file mode 100644 index 000000000..4a14af949 --- /dev/null +++ b/test/mpi_enc_mt_test.c @@ -0,0 +1,680 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpi_enc_mt_test" + +#include +#include "rk_mpi.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_list.h" +#include "mpp_lock.h" +#include "mpp_debug.h" +#include "mpp_common.h" + +#include "utils.h" +#include "mpi_enc_utils.h" +#include "camera_source.h" +#include "mpp_enc_roi_utils.h" + +#define BUF_COUNT 4 + +/* For each instance thread return value */ +typedef struct { + float frame_rate; + RK_U64 bit_rate; + + RK_S64 time_start; + RK_S64 time_delay; + RK_S64 time_total; + + RK_S64 elapsed_time; + RK_S32 frame_count; + RK_S64 stream_size; + RK_S64 delay; +} MpiEncMtCtxRet; + +typedef struct MpiEncMtTestPriv_t { + MppList *list_buf; + MppBuffer frm_buf[BUF_COUNT]; + MppBuffer pkt_buf[BUF_COUNT]; +} MpiEncMtTestPriv; + +typedef struct { + MppEncTestObjSet *obj_set; + const char *name; + RK_S32 chn; + + pthread_t thd_in; // thread for for frame input + pthread_t thd_out; // thread for for packet output + + struct list_head frm_list; + spinlock_t frm_lock; + + MpiEncTestData ctx; // context of encoder + MpiEncMtTestPriv priv; // private data for multi encoder + MpiEncMtCtxRet ret; // return of encoder +} MpiEncMtCtxInfo; + +MPP_RET mt_test_res_init(MpiEncMtCtxInfo *info) +{ + MppEncTestObjSet *obj_set = info->obj_set; + MpiEncTestArgs *cmd = obj_set->cmd; + MpiEncTestData *p = &info->ctx; + MpiEncMtTestPriv *priv = &info->priv; + MppPollType timeout = MPP_POLL_NON_BLOCK; + RK_U32 quiet = cmd->quiet; + MPP_RET ret = MPP_OK; + RK_S32 i; + + mpp_log_q(quiet, "%s start\n", info->name); + + priv->list_buf = mpp_list_create(NULL); + if (NULL == priv->list_buf) { + mpp_err_f("failed to get mpp buffer list\n"); + return MPP_ERR_MALLOC; + } + + ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM); + if (ret) { + mpp_err_f("failed to get mpp buffer group ret %d\n", ret); + return ret; + } + + for (i = 0; i < BUF_COUNT; i++) { + ret = mpp_buffer_get(p->buf_grp, &priv->frm_buf[i], p->frame_size + p->header_size); + if (ret) { + mpp_err_f("failed to get buffer for input frame ret %d\n", ret); + return ret; + } + + ret = mpp_buffer_get(p->buf_grp, &priv->pkt_buf[i], p->frame_size); + if (ret) { + mpp_err_f("failed to get buffer for output packet ret %d\n", ret); + return ret; + } + + mpp_list_add_at_tail(priv->list_buf, &priv->frm_buf[i], sizeof(priv->frm_buf[i])); + } + + // encoder demo + ret = mpp_create(&p->ctx, &p->mpi); + if (ret) { + mpp_err("mpp_create failed ret %d\n", ret); + return ret; + } + + mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n", + p->ctx, p->width, p->height, p->type); + + ret = p->mpi->control(p->ctx, MPP_SET_INPUT_TIMEOUT, &timeout); + if (ret) { + mpp_err("mpi control set input timeout %d ret %d\n", timeout, ret); + return ret; + } + + timeout = MPP_POLL_BLOCK; + + ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout); + if (ret) { + mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret); + return ret; + } + + ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type); + if (ret) { + mpp_err("mpp_init failed ret %d\n", ret); + return ret; + } + + ret = mpp_enc_cfg_init(&p->cfg); + if (ret) { + mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret); + return ret; + } + + ret = p->mpi->control(p->ctx, MPP_ENC_GET_CFG, p->cfg); + if (ret) { + mpp_err_f("get enc cfg failed ret %d\n", ret); + return ret; + } + + ret = mpi_enc_cfg_setup(p, cmd, obj_set->cfg_obj); + if (ret) { + mpp_err_f("test mpp setup failed ret %d\n", ret); + } + + return ret; +} + +MPP_RET mt_test_res_deinit(MpiEncMtCtxInfo *info) +{ + MpiEncTestData *p = &info->ctx; + MpiEncMtTestPriv *priv = &info->priv; + MPP_RET ret = MPP_OK; + RK_S32 i; + + p->mpi->reset(p->ctx); + if (ret) { + mpp_err("mpi->reset failed\n"); + return ret; + } + + if (p->ctx) { + mpp_destroy(p->ctx); + p->ctx = NULL; + } + + if (p->cfg) { + mpp_enc_cfg_deinit(p->cfg); + p->cfg = NULL; + } + + for (i = 0; i < BUF_COUNT; i++) { + if (priv->frm_buf[i]) { + mpp_buffer_put(priv->frm_buf[i]); + priv->frm_buf[i] = NULL; + } + + if (priv->pkt_buf[i]) { + mpp_buffer_put(priv->pkt_buf[i]); + priv->pkt_buf[i] = NULL; + } + } + + if (p->osd_data.buf) { + mpp_buffer_put(p->osd_data.buf); + p->osd_data.buf = NULL; + } + + if (p->buf_grp) { + mpp_buffer_group_put(p->buf_grp); + p->buf_grp = NULL; + } + + if (priv->list_buf) { + mpp_list_destroy(priv->list_buf); + priv->list_buf = NULL; + } + + if (p->roi_ctx) { + mpp_enc_roi_deinit(p->roi_ctx); + p->roi_ctx = NULL; + } + + return MPP_OK; +} + +void *enc_test_input(void *arg) +{ + MpiEncMtCtxInfo *info = (MpiEncMtCtxInfo *)arg; + MppEncTestObjSet *obj_set = info->obj_set; + MpiEncTestArgs *cmd = obj_set->cmd; + MpiEncTestData *p = &info->ctx; + MpiEncMtTestPriv *priv = &info->priv; + RK_S32 chn = info->chn; + MppApi *mpi = p->mpi; + MppCtx ctx = p->ctx; + MppList *list_buf = priv->list_buf; + RK_U32 cap_num = 0; + RK_U32 quiet = cmd->quiet; + MPP_RET ret = MPP_OK; + + mpp_log_q(quiet, "%s start\n", info->name); + + while (1) { + MppMeta meta = NULL; + MppFrame frame = NULL; + MppBuffer buffer = NULL; + void *buf = NULL; + RK_S32 cam_frm_idx = -1; + MppBuffer cam_buf = NULL; + + mpp_mutex_cond_lock(&list_buf->cond_lock); + if (!mpp_list_size(list_buf)) + mpp_list_wait(list_buf); + + buffer = NULL; + mpp_list_del_at_head(list_buf, &buffer, sizeof(buffer)); + if (NULL == buffer) { + mpp_mutex_cond_unlock(&list_buf->cond_lock); + continue; + } + + buf = mpp_buffer_get_ptr(buffer); + mpp_mutex_cond_unlock(&list_buf->cond_lock); + + if (p->fp_input) { + ret = read_image((RK_U8 *)buf, p->fp_input, p->width, p->height, + p->hor_stride, p->ver_stride, p->fmt); + if (ret == MPP_NOK || feof(p->fp_input)) { + p->frm_eos = 1; + + if (p->frame_num < 0 || p->frm_cnt_in < p->frame_num) { + clearerr(p->fp_input); + rewind(p->fp_input); + p->frm_eos = 0; + mpp_log_q(quiet, "chn %d loop times %d\n", chn, ++p->loop_times); + if (buffer) { + mpp_mutex_cond_lock(&list_buf->cond_lock); + mpp_list_add_at_tail(list_buf, &buffer, sizeof(buffer)); + mpp_mutex_cond_unlock(&list_buf->cond_lock); + } + continue; + } + mpp_log_q(quiet, "chn %d found last frame. feof %d\n", chn, feof(p->fp_input)); + } else if (ret == MPP_ERR_VALUE) + break; + } else { + if (p->cam_ctx == NULL) { + ret = fill_image((RK_U8 *)buf, p->width, p->height, p->hor_stride, + p->ver_stride, p->fmt, p->frm_cnt_in * p->frm_step); + if (ret) + break; + } else { + cam_frm_idx = camera_source_get_frame(p->cam_ctx); + mpp_assert(cam_frm_idx >= 0); + + /* skip unstable frames */ + if (cap_num++ < 50) { + camera_source_put_frame(p->cam_ctx, cam_frm_idx); + continue; + } + + cam_buf = camera_frame_to_buf(p->cam_ctx, cam_frm_idx); + mpp_assert(cam_buf); + } + } + + ret = mpp_frame_init(&frame); + if (ret) { + mpp_err_f("mpp_frame_init failed\n"); + break; + } + + mpp_frame_set_width(frame, p->width); + mpp_frame_set_height(frame, p->height); + mpp_frame_set_hor_stride(frame, p->hor_stride); + mpp_frame_set_ver_stride(frame, p->ver_stride); + mpp_frame_set_fmt(frame, p->fmt); + mpp_frame_set_eos(frame, p->frm_eos); + + if (p->fp_input && feof(p->fp_input)) + mpp_frame_set_buffer(frame, NULL); + else if (cam_buf) + mpp_frame_set_buffer(frame, cam_buf); + else + mpp_frame_set_buffer(frame, buffer); + + meta = mpp_frame_get_meta(frame); + + if (cmd->osd_enable || cmd->user_data_enable || cmd->roi_enable) { + if (cmd->user_data_enable) { + MppEncUserData user_data; + const char *str = "this is user data\n"; + + if ((p->frm_cnt_in & 10) == 0) { + user_data.pdata = (void *)str; + user_data.len = strlen(str) + 1; + mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data); + } + static RK_U8 uuid_debug_info[16] = { + 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65, + 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a + }; + + MppEncUserDataSet data_group; + MppEncUserDataFull datas[2]; + const char *str1 = "this is user data 1\n"; + const char *str2 = "this is user data 2\n"; + data_group.count = 2; + datas[0].len = strlen(str1) + 1; + datas[0].pdata = (void *)str1; + datas[0].uuid = uuid_debug_info; + + datas[1].len = strlen(str2) + 1; + datas[1].pdata = (void *)str2; + datas[1].uuid = uuid_debug_info; + + data_group.datas = datas; + + mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group); + } + + if (cmd->osd_enable) { + /* gen and cfg osd plt */ + mpi_enc_gen_osd_plt(&p->osd_plt, p->frm_cnt_in); + + p->osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL; + p->osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF; + p->osd_plt_cfg.plt = &p->osd_plt; + + ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &p->osd_plt_cfg); + if (ret) { + mpp_err("mpi control enc set osd plt failed ret %d\n", ret); + break; + } + + /* gen and cfg osd plt */ + mpi_enc_gen_osd_data(&p->osd_data, p->buf_grp, p->width, + p->height, p->frm_cnt_in); + mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&p->osd_data); + } + + if (cmd->roi_enable) { + RoiRegionCfg *region = &p->roi_region; + + /* calculated in pixels */ + region->x = MPP_ALIGN(p->width / 8, 16); + region->y = MPP_ALIGN(p->height / 8, 16); + region->w = 128; + region->h = 256; + region->force_intra = 0; + region->qp_mode = 1; + region->qp_val = 24; + + mpp_enc_roi_add_region(p->roi_ctx, region); + + region->x = MPP_ALIGN(p->width / 2, 16); + region->y = MPP_ALIGN(p->height / 4, 16); + region->w = 256; + region->h = 128; + region->force_intra = 1; + region->qp_mode = 1; + region->qp_val = 10; + + mpp_enc_roi_add_region(p->roi_ctx, region); + + /* send roi info by metadata */ + mpp_enc_roi_setup_meta(p->roi_ctx, meta); + } + } + + if (!p->first_frm) + p->first_frm = mpp_time(); + /* + * NOTE: in non-block mode the frame can be resent. + * The default input timeout mode is block. + * + * User should release the input frame to meet the requirements of + * resource creator must be the resource destroyer. + */ + p->frm_cnt_in++; + do { + ret = mpi->encode_put_frame(ctx, frame); + if (ret) + msleep(1); + } while (ret); + + if (cam_frm_idx >= 0) + camera_source_put_frame(p->cam_ctx, cam_frm_idx); + + if (p->frame_num > 0 && p->frm_cnt_in >= p->frame_num) { + p->frm_eos = 1; + break; + } + + if (p->loop_end) { + p->frm_eos = 1; + break; + } + + if (p->frm_eos) + break; + } + + return NULL; +} + +void *enc_test_output(void *arg) +{ + MpiEncMtCtxInfo *info = (MpiEncMtCtxInfo *)arg; + MppEncTestObjSet *obj_set = info->obj_set; + MpiEncTestArgs *cmd = obj_set->cmd; + MpiEncTestData *p = &info->ctx; + MpiEncMtTestPriv *priv = &info->priv; + MpiEncMtCtxRet *enc_ret = &info->ret; + MppList *list_buf = priv->list_buf; + RK_S32 chn = info->chn; + MppApi *mpi = p->mpi; + MppCtx ctx = p->ctx; + RK_U32 quiet = cmd->quiet; + MPP_RET ret = MPP_OK; + MppPacket packet = NULL; + RK_U32 eoi = 1; + + void *ptr; + size_t len; + char log_buf[256]; + RK_S32 log_size = sizeof(log_buf) - 1; + RK_S32 log_len = 0; + + while (1) { + ret = mpi->encode_get_packet(ctx, &packet); + if (ret || NULL == packet) { + msleep(1); + continue; + } + + p->last_pkt = mpp_time(); + + // write packet to file here + ptr = mpp_packet_get_pos(packet); + len = mpp_packet_get_length(packet); + log_size = sizeof(log_buf) - 1; + log_len = 0; + + if (!p->first_pkt) + p->first_pkt = mpp_time(); + + p->pkt_eos = mpp_packet_get_eos(packet); + + if (p->fp_output[chn]) + fwrite(ptr, 1, len, p->fp_output[chn]); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + "encoded frame %-4d", p->frm_cnt_out); + + /* for low delay partition encoding */ + if (mpp_packet_is_partition(packet)) { + eoi = mpp_packet_is_eoi(packet); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + " pkt %d", p->frm_pkt_cnt); + p->frm_pkt_cnt = (eoi != 0) ? (0) : (p->frm_pkt_cnt + 1); + } + + log_len += snprintf(log_buf + log_len, log_size - log_len, + " size %-7zu", len); + + if (mpp_packet_has_meta(packet)) { + MppMeta meta = mpp_packet_get_meta(packet); + MppFrame frm = NULL; + RK_S32 temporal_id = 0; + RK_S32 lt_idx = -1; + RK_S32 avg_qp = -1; + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " tid %d", temporal_id); + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, <_idx)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " lt %d", lt_idx); + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " qp %d", avg_qp); + + if (MPP_OK == mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frm)) { + MppBuffer frm_buf = NULL; + + mpp_assert(frm); + frm_buf = mpp_frame_get_buffer(frm); + + if (frm_buf) { + mpp_mutex_cond_lock(&list_buf->cond_lock); + mpp_list_add_at_tail(list_buf, &frm_buf, sizeof(frm_buf)); + mpp_list_signal(list_buf); + mpp_mutex_cond_unlock(&list_buf->cond_lock); + } + + mpp_frame_deinit(&frm); + } + } + + mpp_log_q(quiet, "chn %d %s\n", chn, log_buf); + + mpp_packet_deinit(&packet); + fps_calc_inc(cmd->fps); + + p->stream_size += len; + p->frm_cnt_out += eoi; + + if (p->frm_cnt_out != p->frm_cnt_in) + continue; + + if (p->frame_num > 0 && p->frm_cnt_out >= p->frame_num) { + p->pkt_eos = 1; + break; + } + + if (p->frm_eos) { + p->pkt_eos = 1; + break; + } + + if (p->pkt_eos) { + mpp_log_q(quiet, "chn %d found last packet\n", chn); + mpp_assert(p->frm_eos); + break; + } + } while (!eoi); + + enc_ret->elapsed_time = p->last_pkt - p->first_frm; + enc_ret->frame_count = p->frm_cnt_out; + enc_ret->stream_size = p->stream_size; + enc_ret->frame_rate = (float)p->frm_cnt_out * 1000000 / enc_ret->elapsed_time; + enc_ret->bit_rate = (p->stream_size * 8 * (cmd->fps_out_num / cmd->fps_out_den)) / p->frm_cnt_out; + enc_ret->delay = p->first_pkt - p->first_frm; + + return NULL; +} + +int enc_test_mt(MppEncTestObjSet *obj_set, const char *name) +{ + MpiEncMtCtxInfo *ctxs = NULL; + MpiEncTestArgs *cmd = obj_set->cmd; + float total_rate = 0.0; + RK_S32 ret = MPP_NOK; + RK_S32 i = 0; + + ctxs = mpp_calloc(MpiEncMtCtxInfo, cmd->nthreads); + if (NULL == ctxs) { + mpp_err("failed to alloc context for instances\n"); + return -1; + } + + for (i = 0; i < cmd->nthreads; i++) { + ctxs[i].obj_set = obj_set; + ctxs[i].name = name; + ctxs[i].chn = i; + + ret = mpi_enc_ctx_init(&ctxs[i].ctx, cmd, i); + if (ret) { + mpp_err_f("test ctx init failed ret %d\n", ret); + return ret; + } + + ret = mt_test_res_init(&ctxs[i]); + if (ret) { + mpp_err_f("test resource deinit failed ret %d\n", ret); + return ret; + } + + ret = pthread_create(&ctxs[i].thd_out, NULL, enc_test_output, &ctxs[i]); + if (ret) { + mpp_err("failed to create thread %d\n", i); + return ret; + } + + ret = pthread_create(&ctxs[i].thd_in, NULL, enc_test_input, &ctxs[i]); + if (ret) { + mpp_err("failed to create thread %d\n", i); + return ret; + } + } + + + if (cmd->frame_num < 0) { + // wait for input then quit encoding + mpp_log("*******************************************\n"); + mpp_log("**** Press Enter to stop loop encoding ****\n"); + mpp_log("*******************************************\n"); + + (void)getc(stdin); + mpp_log_f("loop_end start"); + for (i = 0; i < cmd->nthreads; i++) + ctxs[i].ctx.loop_end = 1; + } + + for (i = 0; i < cmd->nthreads; i++) { + pthread_join(ctxs[i].thd_in, NULL); + pthread_join(ctxs[i].thd_out, NULL); + + ret = mt_test_res_deinit(&ctxs[i]); + if (ret) { + mpp_err_f("test resource deinit failed ret %d\n", ret); + return ret; + } + + ret = mpi_enc_ctx_deinit(&ctxs[i].ctx); + if (ret) { + mpp_err_f("test ctx deinit failed ret %d\n", ret); + return ret; + } + } + + for (i = 0; i < cmd->nthreads; i++) { + MpiEncMtCtxRet *enc_ret = &ctxs[i].ret; + + mpp_log("chn %d encode %d frames time %lld ms delay %3d ms fps %3.2f bps %lld\n", + i, enc_ret->frame_count, (RK_S64)(enc_ret->elapsed_time / 1000), + (RK_S32)(enc_ret->delay / 1000), enc_ret->frame_rate, enc_ret->bit_rate); + + total_rate += enc_ret->frame_rate; + } + + MPP_FREE(ctxs); + + total_rate /= cmd->nthreads; + mpp_log("%s average frame rate %.2f\n", name, total_rate); + + return ret; +} + +int main(int argc, char **argv) +{ + MppEncTestObjSet *obj_set = NULL; + RK_S32 ret; + + ret = mpi_enc_test_objset_get(&obj_set); + if (ret) + goto DONE; + + // parse the cmd option + ret = mpi_enc_test_objset_update_by_args(obj_set, argc, argv, MODULE_TAG); + if (ret) + goto DONE; + + ret = enc_test_mt(obj_set, argv[0]); + +DONE: + mpi_enc_test_objset_put(obj_set); + + return ret; +} diff --git a/test/mpi_enc_test.c b/test/mpi_enc_test.c new file mode 100644 index 000000000..ac840058e --- /dev/null +++ b/test/mpi_enc_test.c @@ -0,0 +1,767 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#if defined(_WIN32) +#include "vld.h" +#endif + +#define MODULE_TAG "mpi_enc_test" + +#include +#include +#include "rk_mpi.h" +#include "rk_venc_kcfg.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_debug.h" +#include "mpp_common.h" +#include "mpp_soc.h" + +#include "utils.h" +#include "mpi_enc_utils.h" +#include "camera_source.h" +#include "mpp_enc_roi_utils.h" +#include "mpp_rc_api.h" +#include "osd3_test.h" +#include "kmpp_obj.h" + +/* For each instance thread return value */ +typedef struct { + float frame_rate; + RK_U64 bit_rate; + RK_S64 elapsed_time; + RK_S32 frame_count; + RK_S64 stream_size; + RK_S64 delay; +} MpiEncMultiCtxRet; + +typedef struct MpiEncTestPriv_t { + MppBuffer frm_buf; + MppBuffer pkt_buf; + MppBuffer md_info; +} MpiEncTestPriv; + +typedef struct { + MppEncTestObjSet *obj_set; + const char *name; + RK_S32 chn; + + pthread_t thd; // thread for for each instance + MpiEncTestData ctx; // context of encoder + MpiEncTestPriv priv; // private data for encoder + MpiEncMultiCtxRet ret; // return of encoder +} MpiEncMultiCtxInfo; + +static RK_S32 get_mdinfo_size(MpiEncTestData *p, MppCodingType type) +{ + RockchipSocType soc_type = mpp_get_soc_type(); + RK_S32 md_size; + RK_U32 w = p->hor_stride, h = p->ver_stride; + + if (soc_type == ROCKCHIP_SOC_RV1126B) { + md_size = (MPP_VIDEO_CodingHEVC == type) ? + (MPP_ALIGN(w, 32) >> 5) * (MPP_ALIGN(h, 32) >> 5) * 20 : + (MPP_ALIGN(w, 64) >> 6) * (MPP_ALIGN(h, 16) >> 4) * 16; + } else if (soc_type == ROCKCHIP_SOC_RK3588) { + md_size = (MPP_ALIGN(w, 64) >> 6) * (MPP_ALIGN(h, 64) >> 6) * 32; + } else { + md_size = (MPP_VIDEO_CodingHEVC == type) ? + (MPP_ALIGN(w, 32) >> 5) * (MPP_ALIGN(h, 32) >> 5) * 16 : + (MPP_ALIGN(w, 64) >> 6) * (MPP_ALIGN(h, 16) >> 4) * 16; + } + + return md_size; +} + +static MPP_RET kmpp_cfg_init(MpiEncMultiCtxInfo *info) +{ + MppVencKcfg init_kcfg = NULL; + MpiEncTestData *p = &info->ctx; + MpiEncTestArgs *cmd = info->obj_set->cmd; + MPP_RET ret = MPP_NOK; + + mpp_venc_kcfg_init(&init_kcfg, MPP_VENC_KCFG_TYPE_INIT); + if (!init_kcfg) { + mpp_err_f("kmpp_venc_init_cfg_init failed\n"); + return ret; + } + + p->init_kcfg = init_kcfg; + + mpp_venc_kcfg_set_u32(init_kcfg, "type", MPP_CTX_ENC); + mpp_venc_kcfg_set_u32(init_kcfg, "coding", p->type); + mpp_venc_kcfg_set_s32(init_kcfg, "chan_id", 0); + mpp_venc_kcfg_set_s32(init_kcfg, "online", 0); + mpp_venc_kcfg_set_u32(init_kcfg, "buf_size", 0); + mpp_venc_kcfg_set_u32(init_kcfg, "max_strm_cnt", 0); + mpp_venc_kcfg_set_u32(init_kcfg, "shared_buf_en", 0); + mpp_venc_kcfg_set_u32(init_kcfg, "smart_en", cmd->rc_mode == MPP_ENC_RC_MODE_SMTRC); + mpp_venc_kcfg_set_u32(init_kcfg, "max_width", p->width); + mpp_venc_kcfg_set_u32(init_kcfg, "max_height", p->height); + mpp_venc_kcfg_set_u32(init_kcfg, "max_lt_cnt", 0); + mpp_venc_kcfg_set_u32(init_kcfg, "qpmap_en", cmd->deblur_en); + mpp_venc_kcfg_set_u32(init_kcfg, "chan_dup", 0); + mpp_venc_kcfg_set_u32(init_kcfg, "tmvp_enable", 0); + mpp_venc_kcfg_set_u32(init_kcfg, "only_smartp", 0); + /* set notify mode to zero to disable rockit ko call back */ + mpp_venc_kcfg_set_u32(init_kcfg, "ntfy_mode", 0); + /* set input timeout to block mode to insure put_frame ioctl return while encoding finished */ + mpp_venc_kcfg_set_s32(init_kcfg, "input_timeout", MPP_POLL_BLOCK); + + ret = p->mpi->control(p->ctx, MPP_SET_VENC_INIT_KCFG, init_kcfg); + if (ret) + mpp_err_f("mpi control set kmpp enc cfg failed ret %d\n", ret); + + return ret; +} + +MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info) +{ + MppEncTestObjSet *obj_set = info->obj_set; + MpiEncTestArgs *cmd = obj_set->cmd; + MpiEncTestData *p = &info->ctx; + MpiEncTestPriv *priv = &info->priv; + MppApi *mpi = p->mpi; + MppCtx ctx = p->ctx; + RK_U32 quiet = cmd->quiet; + RK_S32 chn = info->chn; + RK_U32 cap_num = 0; + DataCrc checkcrc; + MPP_RET ret = MPP_OK; + RK_FLOAT psnr_const = 0; + RK_U32 sse_unit_in_pixel = 0; + RK_U32 soc_type; + + memset(&checkcrc, 0, sizeof(checkcrc)); + checkcrc.sum = mpp_malloc(RK_ULONG, 512); + soc_type = mpp_get_soc_type(); + + if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { + MppPacket packet = NULL; + + /* + * Can use packet with normal malloc buffer as input not pkt_buf. + * Please refer to vpu_api_legacy.cpp for normal buffer case. + * Using pkt_buf buffer here is just for simplifing demo. + */ + mpp_packet_init_with_buffer(&packet, priv->pkt_buf); + /* NOTE: It is important to clear output packet length!! */ + mpp_packet_set_length(packet, 0); + + ret = mpi->control(ctx, MPP_ENC_GET_HDR_SYNC, packet); + if (ret) { + mpp_err("mpi control enc get extra info failed\n"); + goto RET; + } else { + /* get and write sps/pps for H.264 */ + + void *ptr = mpp_packet_get_pos(packet); + size_t len = mpp_packet_get_length(packet); + + if (p->fp_output[chn]) + fwrite(ptr, 1, len, p->fp_output[chn]); + } + + mpp_packet_deinit(&packet); + + sse_unit_in_pixel = p->type == MPP_VIDEO_CodingAVC ? 16 : 8; + psnr_const = (16 + log2(MPP_ALIGN(p->width, sse_unit_in_pixel) * + MPP_ALIGN(p->height, sse_unit_in_pixel))); + } + while (!p->pkt_eos) { + MppMeta meta = NULL; + MppFrame frame = NULL; + MppPacket packet = NULL; + void *buf = mpp_buffer_get_ptr(priv->frm_buf); + RK_S32 cam_frm_idx = -1; + MppBuffer cam_buf = NULL; + RK_U32 eoi = 1; + + if (p->fp_input) { + mpp_buffer_sync_begin(priv->frm_buf); + ret = read_image(buf, p->fp_input, p->width, p->height, + p->hor_stride, p->ver_stride, p->fmt); + if (ret == MPP_NOK || feof(p->fp_input)) { + p->frm_eos = 1; + + if (p->frame_num < 0) { + clearerr(p->fp_input); + rewind(p->fp_input); + p->frm_eos = 0; + mpp_log_q(quiet, "chn %d loop times %d\n", chn, ++p->loop_times); + continue; + } + mpp_log_q(quiet, "chn %d found last frame. feof %d\n", chn, feof(p->fp_input)); + } else if (ret == MPP_ERR_VALUE) + goto RET; + mpp_buffer_sync_end(priv->frm_buf); + } else { + if (p->cam_ctx == NULL) { + mpp_buffer_sync_begin(priv->frm_buf); + ret = fill_image(buf, p->width, p->height, p->hor_stride, + p->ver_stride, p->fmt, p->frm_cnt_out * p->frm_step); + if (ret) + goto RET; + mpp_buffer_sync_end(priv->frm_buf); + } else { + cam_frm_idx = camera_source_get_frame(p->cam_ctx); + mpp_assert(cam_frm_idx >= 0); + + /* skip unstable frames */ + if (cap_num++ < 50) { + camera_source_put_frame(p->cam_ctx, cam_frm_idx); + continue; + } + + cam_buf = camera_frame_to_buf(p->cam_ctx, cam_frm_idx); + mpp_assert(cam_buf); + } + } + + ret = mpp_frame_init(&frame); + if (ret) { + mpp_err_f("mpp_frame_init failed\n"); + goto RET; + } + + mpp_frame_set_width(frame, p->width); + mpp_frame_set_height(frame, p->height); + mpp_frame_set_hor_stride(frame, p->hor_stride); + mpp_frame_set_ver_stride(frame, p->ver_stride); + mpp_frame_set_fmt(frame, p->fmt); + mpp_frame_set_eos(frame, p->frm_eos); + + if (p->fp_input && feof(p->fp_input)) + mpp_frame_set_buffer(frame, NULL); + else if (cam_buf) + mpp_frame_set_buffer(frame, cam_buf); + else + mpp_frame_set_buffer(frame, priv->frm_buf); + + meta = mpp_frame_get_meta(frame); + mpp_packet_init_with_buffer(&packet, priv->pkt_buf); + /* NOTE: It is important to clear output packet length!! */ + mpp_packet_set_length(packet, 0); + mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet); + mpp_meta_set_buffer(meta, KEY_MOTION_INFO, priv->md_info); + + if (cmd->osd_enable || cmd->user_data_enable || cmd->roi_enable || cmd->roi_jpeg_enable) { + if (cmd->user_data_enable) { + MppEncUserData user_data; + char *str = "this is user data\n"; + + if ((p->frm_cnt_out & 10) == 0) { + user_data.pdata = str; + user_data.len = strlen(str) + 1; + mpp_meta_set_ptr(meta, KEY_USER_DATA, &user_data); + } + static RK_U8 uuid_debug_info[16] = { + 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65, + 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a + }; + + MppEncUserDataSet data_group; + MppEncUserDataFull datas[2]; + char *str1 = "this is user data 1\n"; + char *str2 = "this is user data 2\n"; + data_group.count = 2; + datas[0].len = strlen(str1) + 1; + datas[0].pdata = str1; + datas[0].uuid = uuid_debug_info; + + datas[1].len = strlen(str2) + 1; + datas[1].pdata = str2; + datas[1].uuid = uuid_debug_info; + + data_group.datas = datas; + + mpp_meta_set_ptr(meta, KEY_USER_DATAS, &data_group); + } + + if (cmd->osd_enable) { + if (soc_type == ROCKCHIP_SOC_RV1126B) { + /* osd for RV1126B use struct MppEncOSDData3 */ + RK_S32 osd_case; + if (!p->osd_pattern) { + osd3_gen_smpte_bar_argb(&p->osd_pattern); + } + + if (p->type == MPP_VIDEO_CodingMJPEG) { + osd_case = cmd->jpeg_osd_case; + } else { + osd_case = p->frm_cnt_out; + } + + osd3_get_test_case(&p->osd_data3, p->osd_pattern, + (RK_U32)osd_case % OSD_CASE_BUTT, &p->osd_buffer); + + mpp_meta_set_ptr(meta, KEY_OSD_DATA3, (void*)&p->osd_data3); + } else { + /* gen and cfg osd plt */ + mpi_enc_gen_osd_plt(&p->osd_plt, p->frm_cnt_out); + + p->osd_plt_cfg.change = MPP_ENC_OSD_PLT_CFG_CHANGE_ALL; + p->osd_plt_cfg.type = MPP_ENC_OSD_PLT_TYPE_USERDEF; + p->osd_plt_cfg.plt = &p->osd_plt; + + ret = mpi->control(ctx, MPP_ENC_SET_OSD_PLT_CFG, &p->osd_plt_cfg); + if (ret) { + mpp_err("mpi control enc set osd plt failed ret %d\n", ret); + goto RET; + } + + /* gen and cfg osd plt */ + mpi_enc_gen_osd_data(&p->osd_data, p->buf_grp, p->width, + p->height, p->frm_cnt_out); + mpp_meta_set_ptr(meta, KEY_OSD_DATA, (void*)&p->osd_data); + } + } + + if (cmd->roi_enable) { + RoiRegionCfg *region = &p->roi_region; + + /* calculated in pixels */ + region->x = MPP_ALIGN(p->width / 8, 16); + region->y = MPP_ALIGN(p->height / 8, 16); + region->w = 128; + region->h = 256; + region->force_intra = 0; + region->qp_mode = 1; + region->qp_val = 24; + + mpp_enc_roi_add_region(p->roi_ctx, region); + + region->x = MPP_ALIGN(p->width / 2, 16); + region->y = MPP_ALIGN(p->height / 4, 16); + region->w = 256; + region->h = 128; + region->force_intra = 1; + region->qp_mode = 1; + region->qp_val = 10; + + mpp_enc_roi_add_region(p->roi_ctx, region); + + /* send roi info by metadata */ + mpp_enc_roi_setup_meta(p->roi_ctx, meta); + } + + if (cmd->roi_jpeg_enable) { + RK_U32 index; + RK_U32 width = 128; + RK_U32 height = 128; + RK_U32 start_x = 0; + RK_U32 start_y = 0; + + p->roi_jpeg_cfg.change = 1; + p->roi_jpeg_cfg.non_roi_en = 1; + p->roi_jpeg_cfg.non_roi_level = 0; + + for (index = 0; index < 16; index++) { + if ((start_x + width) > p->width || (start_y + height) > p->height) + break; + p->roi_jpeg_cfg.regions[index].roi_en = 1; + p->roi_jpeg_cfg.regions[index].x = start_x; + p->roi_jpeg_cfg.regions[index].y = start_y; + p->roi_jpeg_cfg.regions[index].w = width; + p->roi_jpeg_cfg.regions[index].h = height; + p->roi_jpeg_cfg.regions[index].level = 63; + + start_x += width; + start_y += height; + } + + if (cmd->kmpp_en) + ret = mpi->control(ctx, MPP_ENC_SET_JPEG_ROI_CFG, &p->roi_jpeg_cfg); + else + mpp_meta_set_ptr(meta, KEY_JPEG_ROI_DATA, (void*)&p->roi_jpeg_cfg); + } + } + + if (!p->first_frm) + p->first_frm = mpp_time(); + /* + * NOTE: in non-block mode the frame can be resent. + * The default input timeout mode is block. + * + * User should release the input frame to meet the requirements of + * resource creator must be the resource destroyer. + */ + ret = mpi->encode_put_frame(ctx, frame); + if (ret) { + mpp_err("chn %d encode put frame failed\n", chn); + mpp_frame_deinit(&frame); + goto RET; + } + + mpp_frame_deinit(&frame); + + do { + ret = mpi->encode_get_packet(ctx, &packet); + if (ret) { + mpp_err("chn %d encode get packet failed\n", chn); + goto RET; + } + + mpp_assert(packet); + + if (packet) { + // write packet to file here + void *ptr = mpp_packet_get_pos(packet); + size_t len = mpp_packet_get_length(packet); + char log_buf[256]; + RK_S32 log_size = sizeof(log_buf) - 1; + RK_S32 log_len = 0; + + if (!p->first_pkt) + p->first_pkt = mpp_time(); + + p->pkt_eos = mpp_packet_get_eos(packet); + + if (p->fp_output[chn]) + fwrite(ptr, 1, len, p->fp_output[chn]); + + if (p->fp_verify && !p->pkt_eos) { + calc_data_crc((RK_U8 *)ptr, (RK_U32)len, &checkcrc); + mpp_log("p->frm_cnt_out=%d, len=%d\n", p->frm_cnt_out, len); + write_data_crc(p->fp_verify, &checkcrc); + } + + log_len += snprintf(log_buf + log_len, log_size - log_len, + "encoded frame %-4d", p->frm_cnt_out); + + /* for low delay partition encoding */ + if (mpp_packet_is_partition(packet)) { + eoi = mpp_packet_is_eoi(packet); + + log_len += snprintf(log_buf + log_len, log_size - log_len, + " pkt %d", p->frm_pkt_cnt); + p->frm_pkt_cnt = (eoi != 0) ? (0) : (p->frm_pkt_cnt + 1); + } + + log_len += snprintf(log_buf + log_len, log_size - log_len, + " size %-7zu", len); + + if (mpp_packet_has_meta(packet)) { + meta = mpp_packet_get_meta(packet); + RK_S32 temporal_id = 0; + RK_S32 lt_idx = -1; + RK_S32 avg_qp = -1, bps_rt = -1; + RK_S32 use_lt_idx = -1; + RK_S64 sse = 0; + RK_FLOAT psnr = 0; + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " tid %d", temporal_id); + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, <_idx)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " lt %d", lt_idx); + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " qp %2d", avg_qp); + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_BPS_RT, &bps_rt)) + log_len += snprintf(log_buf + log_len, log_size - log_len, + " bps_rt %d", bps_rt); + + if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_USE_LTR, &use_lt_idx)) + log_len += snprintf(log_buf + log_len, log_size - log_len, " vi"); + + if (MPP_OK == mpp_meta_get_s64(meta, KEY_ENC_SSE, &sse)) { + psnr = 3.01029996 * (psnr_const - log2(sse)); + log_len += snprintf(log_buf + log_len, log_size - log_len, + " psnr %.4f", psnr); + } + } + + mpp_log_q(quiet, "chn %d %s\n", chn, log_buf); + + mpp_packet_deinit(&packet); + fps_calc_inc(cmd->fps); + + p->stream_size += len; + p->frm_cnt_out += eoi; + + if (p->pkt_eos) { + mpp_log_q(quiet, "chn %d found last packet\n", chn); + mpp_assert(p->frm_eos); + } + } + } while (!eoi); + + if (cam_frm_idx >= 0) + camera_source_put_frame(p->cam_ctx, cam_frm_idx); + + if (p->frame_num > 0 && p->frm_cnt_out >= p->frame_num) + break; + + if (p->loop_end) + break; + + if (p->frm_eos && p->pkt_eos) + break; + } +RET: + MPP_FREE(checkcrc.sum); + + return ret; +} + +void *enc_test(void *arg) +{ + MpiEncMultiCtxInfo *info = (MpiEncMultiCtxInfo *)arg; + MppEncTestObjSet *obj_set = info->obj_set; + MpiEncTestArgs *cmd = obj_set->cmd; + MpiEncTestData *p = &info->ctx; + MpiEncTestPriv *priv = &info->priv; + MpiEncMultiCtxRet *enc_ret = &info->ret; + MppPollType timeout = MPP_POLL_BLOCK; + RK_U32 quiet = cmd->quiet; + MPP_RET ret = MPP_OK; + RK_S64 t_s = 0; + RK_S64 t_e = 0; + size_t mdinfo_size; + + mpp_log_q(quiet, "%s start\n", info->name); + + ret = mpi_enc_ctx_init(p, cmd, info->chn); + if (ret) { + mpp_err_f("test data init failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_CACHABLE); + if (ret) { + mpp_err_f("failed to get mpp buffer group ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = mpp_buffer_get(p->buf_grp, &priv->frm_buf, p->frame_size + p->header_size); + if (ret) { + mpp_err_f("failed to get buffer for input frame ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = mpp_buffer_get(p->buf_grp, &priv->pkt_buf, p->frame_size); + if (ret) { + mpp_err_f("failed to get buffer for output packet ret %d\n", ret); + goto MPP_TEST_OUT; + } + + mdinfo_size = get_mdinfo_size(p, cmd->type); + ret = mpp_buffer_get(p->buf_grp, &priv->md_info, mdinfo_size); + if (ret) { + mpp_err_f("failed to get buffer for motion info output packet ret %d\n", ret); + goto MPP_TEST_OUT; + } + + // encoder demo + ret = mpp_create(&p->ctx, &p->mpi); + if (ret) { + mpp_err("mpp_create failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + mpp_log_q(quiet, "%p encoder test start w %d h %d type %d\n", + p->ctx, p->width, p->height, p->type); + + ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout); + if (MPP_OK != ret) { + mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret); + goto MPP_TEST_OUT; + } + + if (cmd->kmpp_en) + kmpp_cfg_init(info); + + ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type); + if (ret) { + mpp_err("mpp_init failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + if (cmd->kmpp_en) + ret = mpp_enc_cfg_init_k(&p->cfg); + else + ret = mpp_enc_cfg_init(&p->cfg); + if (ret) { + mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = p->mpi->control(p->ctx, MPP_ENC_GET_CFG, p->cfg); + if (ret) { + mpp_err_f("get enc cfg failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = mpi_enc_cfg_setup(p, cmd, obj_set->cfg_obj); + if (ret) { + mpp_err_f("test mpp setup failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + t_s = mpp_time(); + ret = test_mpp_run(info); + t_e = mpp_time(); + if (ret) { + mpp_err_f("test mpp run failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = p->mpi->reset(p->ctx); + if (ret) { + mpp_err("mpi->reset failed\n"); + goto MPP_TEST_OUT; + } + + enc_ret->elapsed_time = t_e - t_s; + enc_ret->frame_count = p->frm_cnt_out; + enc_ret->stream_size = p->stream_size; + enc_ret->frame_rate = (float)p->frm_cnt_out * 1000000 / enc_ret->elapsed_time; + enc_ret->bit_rate = (p->stream_size * 8 * (cmd->fps_out_num / cmd->fps_out_den)) / p->frm_cnt_out; + enc_ret->delay = p->first_pkt - p->first_frm; + +MPP_TEST_OUT: + if (p->ctx) { + mpp_destroy(p->ctx); + p->ctx = NULL; + } + + if (p->cfg) { + mpp_enc_cfg_deinit(p->cfg); + p->cfg = NULL; + } + + if (priv->frm_buf) { + mpp_buffer_put(priv->frm_buf); + priv->frm_buf = NULL; + } + + if (priv->pkt_buf) { + mpp_buffer_put(priv->pkt_buf); + priv->pkt_buf = NULL; + } + + if (priv->md_info) { + mpp_buffer_put(priv->md_info); + priv->md_info = NULL; + } + + if (p->osd_data.buf) { + mpp_buffer_put(p->osd_data.buf); + p->osd_data.buf = NULL; + } + + if (p->osd_buffer) { + kmpp_obj_put_f(p->osd_buffer); + p->osd_buffer = NULL; + } + + if (p->buf_grp) { + mpp_buffer_group_put(p->buf_grp); + p->buf_grp = NULL; + } + + if (p->roi_ctx) { + mpp_enc_roi_deinit(p->roi_ctx); + p->roi_ctx = NULL; + } + if (p->init_kcfg) + mpp_venc_kcfg_deinit(p->init_kcfg); + + if (p->osd_pattern) { + free(p->osd_pattern); + p->osd_pattern = NULL; + } + + mpi_enc_ctx_deinit(p); + + return NULL; +} + +int enc_test_multi(MppEncTestObjSet* obj_set, const char *name) +{ + MpiEncMultiCtxInfo *ctxs = NULL; + MpiEncTestArgs *cmd = obj_set->cmd; + float total_rate = 0.0; + RK_S32 ret = MPP_NOK; + RK_S32 i = 0; + + ctxs = mpp_calloc(MpiEncMultiCtxInfo, cmd->nthreads); + if (NULL == ctxs) { + mpp_err("failed to alloc context for instances\n"); + return -1; + } + + for (i = 0; i < cmd->nthreads; i++) { + ctxs[i].obj_set = obj_set; + ctxs[i].name = name; + ctxs[i].chn = i; + + ret = pthread_create(&ctxs[i].thd, NULL, enc_test, &ctxs[i]); + if (ret) { + mpp_err("failed to create thread %d\n", i); + return ret; + } + } + + if (cmd->frame_num < 0) { + // wait for input then quit encoding + mpp_log("*******************************************\n"); + mpp_log("**** Press Enter to stop loop encoding ****\n"); + mpp_log("*******************************************\n"); + + (void)getc(stdin); + for (i = 0; i < cmd->nthreads; i++) + ctxs[i].ctx.loop_end = 1; + } + + for (i = 0; i < cmd->nthreads; i++) + pthread_join(ctxs[i].thd, NULL); + + for (i = 0; i < cmd->nthreads; i++) { + MpiEncMultiCtxRet *enc_ret = &ctxs[i].ret; + + mpp_log("chn %d encode %d frames time %lld ms delay %3d ms fps %3.2f bps %lld\n", + i, enc_ret->frame_count, (RK_S64)(enc_ret->elapsed_time / 1000), + (RK_S32)(enc_ret->delay / 1000), enc_ret->frame_rate, enc_ret->bit_rate); + + total_rate += enc_ret->frame_rate; + } + + MPP_FREE(ctxs); + + total_rate /= cmd->nthreads; + mpp_log("%s average frame rate %.2f\n", name, total_rate); + + return ret; +} + +int main(int argc, char **argv) +{ + MppEncTestObjSet *obj_set = NULL; + RK_S32 ret; + + ret = mpi_enc_test_objset_get(&obj_set); + if (ret) + goto DONE; + + // parse the cmd option + ret = mpi_enc_test_objset_update_by_args(obj_set, argc, argv, MODULE_TAG); + if (ret) + goto DONE; + + ret = enc_test_multi(obj_set, argv[0]); + +DONE: + mpi_enc_test_objset_put(obj_set); + + return ret; +} diff --git a/test/mpi_rc.cfg b/test/mpi_rc.cfg new file mode 100644 index 000000000..1f373c93b --- /dev/null +++ b/test/mpi_rc.cfg @@ -0,0 +1,17 @@ +[CONFIG] +# index type can be 'frm' or 'msec', frm stand for event trigger at frame index, +# and msec represent event trigger at time (milli second). +index: frm +# loop represent the event will repeat at that point, for example, the first +# index is 1, the last index is 171, and loop is 200, when the last event occur, +# next event will occur after (200 + 1 - 171) times notify. if loop < 0, it +# means there is no loop, event trigger will be stop when all the event had been +# trigger +loop: 200 +[EVENT] +#idx bps fps +0 2000000 30 +40 4000000 30 +100 5000000 30 +150 3000000 30 +171 6000000 27 diff --git a/test/mpi_rc2_test.c b/test/mpi_rc2_test.c new file mode 100644 index 000000000..f7d9fc193 --- /dev/null +++ b/test/mpi_rc2_test.c @@ -0,0 +1,1149 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpi_rc_test" + +#include +#include + +#include "rk_mpi.h" + +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_time.h" +#include "mpp_common.h" + +#include "mpi_dec_utils.h" +#include "mpi_enc_utils.h" + +#define MPI_BIT_DEPTH 8 +#define MPI_PIXEL_MAX ((1 << MPI_BIT_DEPTH) - 1) + +typedef RK_U8 pixel; + +typedef struct { + double psnr_y; + double ssim_y; + RK_U32 avg_bitrate; // Every sequence, byte per second + RK_U32 ins_bitrate; // Every second, byte per second + RK_U32 frame_size; // Every frame, byte +} MpiRcStat; + +typedef struct { + FILE *fp_input; + FILE *fp_enc_out; + FILE *fp_stat; +} MpiRcFile; + +typedef struct { + MpiEncTestArgs* enc_cmd; + MpiRcStat stat; + MpiRcFile file; + + RK_U8 *com_buf; + MppCtx enc_ctx; + MppCtx dec_ctx_post; + MppCtx dec_ctx_pre; + MppApi *enc_mpi; + MppApi *dec_mpi_post; + MppApi *dec_mpi_pre; + + /* 1. pre-decoder data */ + FileReader reader; + MppCodingType dec_type; + RK_S32 pre_pkt_idx; + RK_S32 pre_frm_idx; + RK_S32 pre_frm_num; + MppPacket dec_pkt_pre; + RK_U8 *dec_in_buf_pre; + RK_U32 dec_in_buf_pre_size; + + /* 2. encoder data */ + MppBufferGroup pkt_grp; + MppPacket enc_pkt; + + MppEncRcCfg rc_cfg; + MppEncPrepCfg prep_cfg; + + MppTask enc_in_task; + MppTask enc_out_task; + + /* 3. post-decoder data */ + MppPacket dec_pkt_post; + RK_U8 *dec_in_buf_post; + RK_U32 dec_in_buf_post_size; + + RK_U32 loop_end; + RK_U32 pkt_eos; + RK_S32 frm_eos; + RK_U32 enc_pkt_eos; + MppEncCfg cfg; + + RK_S32 frm_idx; + RK_U64 total_bits; + double total_psnrs; + double total_ssims; + RK_U32 calc_base_idx; + RK_U32 stream_size_1s; + pthread_t dec_thr; + RK_S64 start_enc; +} MpiRc2TestCtx; + +static void mpi_rc_deinit(MpiRc2TestCtx *ctx) +{ + MpiRcFile *file = &ctx->file; + + if (file->fp_enc_out) { + fclose(file->fp_enc_out); + file->fp_enc_out = NULL; + } + + if (file->fp_stat) { + fclose(file->fp_stat); + file->fp_stat = NULL; + } + + if (file->fp_input) { + fclose(file->fp_input); + file->fp_input = NULL; + } + + if (ctx->reader) { + reader_deinit(ctx->reader); + ctx->reader = NULL; + } + + MPP_FREE(ctx->com_buf); +} + +static MPP_RET mpi_rc_init(MpiRc2TestCtx *ctx) +{ + MpiEncTestArgs* enc_cmd = ctx->enc_cmd; + + if (enc_cmd->file_input) + reader_init(&ctx->reader, enc_cmd->file_input, enc_cmd->type_src); + + if (NULL == ctx->reader) { + mpp_err("failed to open dec input file %s\n", enc_cmd->file_input); + return MPP_NOK; + } + + mpp_log("input file %s size %ld\n", enc_cmd->file_input, reader_size(ctx->reader)); + ctx->dec_type = enc_cmd->type_src; + + if (enc_cmd->file_output) { + MpiRcFile *file = &ctx->file; + + file->fp_enc_out = fopen(enc_cmd->file_output, "w+b"); + if (NULL == file->fp_enc_out) { + mpp_err("failed to open enc output file %s\n", enc_cmd->file_output); + return MPP_ERR_OPEN_FILE; + } + } + + return MPP_OK; +} + +static MPP_RET mpi_rc_cmp_frame(MppFrame frame_in, MppFrame frame_out) +{ + void *enc_buf = mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_in)); + void *dec_buf = mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_out)); + RK_U32 enc_width = mpp_frame_get_width(frame_in); + RK_U32 enc_height = mpp_frame_get_height(frame_in); + RK_U32 dec_width = mpp_frame_get_width(frame_out); + RK_U32 dec_height = mpp_frame_get_height(frame_out); + + if (!enc_buf) { + mpp_err_f("enc buf is NULL"); + return MPP_NOK; + } + + if (!dec_buf) { + mpp_err_f("dec buf is NULL"); + return MPP_NOK; + } + + if (enc_width != dec_width) { + mpp_err_f("enc_width %d != dec_width %d", enc_width, dec_width); + return MPP_NOK; + } + + if (enc_height != dec_height) { + mpp_err_f("enc_height %d != dec_height %d", enc_height, dec_height); + return MPP_NOK; + } + + return MPP_OK; +} + +static void mpi_rc_calc_psnr(MpiRcStat *stat, MppFrame frame_in, + MppFrame frame_out) +{ + RK_U32 x, y; + RK_S32 tmp; + double ssd_y = 0.0; + double mse_y = 0.0; + double psnr_y = 0.0; + + RK_U32 width = mpp_frame_get_width(frame_in); + RK_U32 height = mpp_frame_get_height(frame_in); + RK_U32 luma_size = width * height; + RK_U32 enc_hor_stride = mpp_frame_get_hor_stride(frame_in); + RK_U32 dec_hor_stride = mpp_frame_get_hor_stride(frame_out); + RK_U8 *enc_buf = (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_in)); + RK_U8 *dec_buf = (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_out)); + RK_U8 *enc_buf_y = enc_buf; + RK_U8 *dec_buf_y = dec_buf; + + for (y = 0 ; y < height; y++) { + for (x = 0; x < width; x++) { + tmp = enc_buf_y[x + y * enc_hor_stride] - + dec_buf_y[x + y * dec_hor_stride]; + tmp *= tmp; + ssd_y += tmp; + } + } + // NOTE: should be 65025.0 rather than 65025, + // because 65025*luma_size may exceed + // 1 << 32. + mse_y = ssd_y / (65025.0 * luma_size); // 65025=255*255 + if (mse_y <= 0.0000000001) + psnr_y = 100; + else + psnr_y = -10.0 * log10f(mse_y); + + stat->psnr_y = psnr_y; +} + +static float ssim_end1( int s1, int s2, int ss, int s12 ) +{ + /* + * Maximum value for 10-bit is: ss*64 = (2^10-1)^2*16*4*64 = 4286582784, + * which will overflow in some cases. + * s1*s1, s2*s2, and s1*s2 also obtain this value for edge cases: + * ((2^10-1)*16*4)^2 = 4286582784. + * Maximum value for 9-bit is: ss*64 = (2^9-1)^2*16*4*64 = 1069551616, + * which will not overflow. + */ + static const int ssim_c1 = + (int)(.01 * .01 * MPI_PIXEL_MAX * MPI_PIXEL_MAX * 64 + .5); + static const int ssim_c2 = + (int)(.03 * .03 * MPI_PIXEL_MAX * MPI_PIXEL_MAX * 64 * 63 + .5); + int fs1 = s1; + int fs2 = s2; + int fss = ss; + int fs12 = s12; + int vars = fss * 64 - fs1 * fs1 - fs2 * fs2; + int covar = fs12 * 64 - fs1 * fs2; + + return (float)(2 * fs1 * fs2 + ssim_c1) * + (float)(2 * covar + ssim_c2) / + ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * + (float)(vars + ssim_c2)); +} + +static float ssim_end4( int sum0[5][4], int sum1[5][4], int width ) +{ + double ssim = 0.0; + int i = 0; + + for (i = 0; i < width; i++ ) + ssim += ssim_end1(sum0[i][0] + sum0[i + 1][0] + + sum1[i][0] + sum1[i + 1][0], + sum0[i][1] + sum0[i + 1][1] + + sum1[i][1] + sum1[i + 1][1], + sum0[i][2] + sum0[i + 1][2] + + sum1[i][2] + sum1[i + 1][2], + sum0[i][3] + sum0[i + 1][3] + + sum1[i][3] + sum1[i + 1][3] ); + return ssim; +} + +static void ssim_4x4x2_core( const pixel *pix1, intptr_t stride1, + const pixel *pix2, intptr_t stride2, + int sums[2][4] ) +{ + int a = 0; + int b = 0; + int x = 0; + int y = 0; + int z = 0; + + for (z = 0; z < 2; z++ ) { + uint32_t s1 = 0, s2 = 0, ss = 0, s12 = 0; + for (y = 0; y < 4; y++ ) + for ( x = 0; x < 4; x++ ) { + a = pix1[x + y * stride1]; + b = pix2[x + y * stride2]; + s1 += a; + s2 += b; + ss += a * a; + ss += b * b; + s12 += a * b; + + } + sums[z][0] = s1; + sums[z][1] = s2; + sums[z][2] = ss; + sums[z][3] = s12; + pix1 += 4; + pix2 += 4; + } +} + +static float calc_ssim(pixel *pix1, RK_U32 stride1, + pixel *pix2, RK_U32 stride2, + int width, int height, void *buf, int *cnt) +{ + int x = 0; + int y = 0; + int z = 0; + float ssim = 0.0; + int (*sum0)[4] = buf; + int (*sum1)[4] = sum0 + (width >> 2) + 3; + + width >>= 2; + height >>= 2; + for ( y = 1; y < height; y++ ) { + for ( ; z <= y; z++ ) { + MPP_SWAP( void*, sum0, sum1 ); + for ( x = 0; x < width; x += 2 ) + ssim_4x4x2_core(&pix1[4 * (x + z * stride1)], + stride1, &pix2[4 * (x + z * stride2)], + stride2, &sum0[x] ); + } + for ( x = 0; x < width - 1; x += 4 ) + ssim += ssim_end4(sum0 + x, sum1 + x, + MPP_MIN(4, width - x - 1)); + + } + *cnt = (height - 1) * (width - 1); + return ssim; +} + +static void mpi_rc_calc_ssim(MpiRc2TestCtx *ctx, MppFrame frame_in, MppFrame frame_out) +{ + int cnt = 0; + float ssim = 0; + MpiRcStat *stat = &ctx->stat; + RK_U32 width = mpp_frame_get_width(frame_in); + RK_U32 height = mpp_frame_get_height(frame_in); + RK_U32 enc_hor_stride = mpp_frame_get_hor_stride(frame_in); + RK_U32 dec_hor_stride = mpp_frame_get_hor_stride(frame_out); + pixel *enc_buf = + (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_in)); + pixel *dec_buf = + (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_out)); + pixel *enc_buf_y = enc_buf; + pixel *dec_buf_y = dec_buf; + + if (NULL == ctx->com_buf) + ctx->com_buf = mpp_malloc(RK_U8, enc_hor_stride * mpp_frame_get_ver_stride(frame_out) * 2); + + ssim = calc_ssim(enc_buf_y, enc_hor_stride, dec_buf_y, dec_hor_stride, + width - 2, height - 2, ctx->com_buf, &cnt); + ssim /= (float)cnt; + + stat->ssim_y = (double)ssim; +} + +static MPP_RET mpi_rc_calc_stat(MpiRc2TestCtx *ctx, + MppFrame frame_in, MppFrame frame_out) +{ + MPP_RET ret = MPP_OK; + MpiRcStat *stat = &ctx->stat; + + ret = mpi_rc_cmp_frame(frame_in, frame_out); + if (ret) { + mpp_err_f("mpi_rc_cmp_frame failed ret %d", ret); + return MPP_NOK; + } + + if (ctx->enc_cmd->psnr_en) { + mpi_rc_calc_psnr(stat, frame_in, frame_out); + ctx->total_psnrs += stat->psnr_y; + } + if (ctx->enc_cmd->ssim_en) { + mpi_rc_calc_ssim(ctx, frame_in, frame_out); + ctx->total_ssims += stat->ssim_y; + } + + return ret; +} + +static void mpi_rc_log_stat(MpiRc2TestCtx *ctx, RK_U32 frame_count, + RK_U32 one_second, RK_U32 seq_end) +{ + //static char rc_log_str[1024] = {0}; + MpiRcStat *stat = &ctx->stat; + MpiRcFile *file = &ctx->file; + FILE *fp = file->fp_stat; + + mpp_log("frame %3d | frame_size %6d bytes | psnr %5.2f | ssim %5.5f", + frame_count, stat->frame_size, stat->psnr_y, stat->ssim_y); + if (one_second) + mpp_log("ins_bitrate %f kbps", stat->ins_bitrate * 8.0 / 1000); + + if (fp) { + fprintf(fp, "%3d,%6d,%5.2f,%5.5f,", + frame_count, stat->frame_size, stat->psnr_y, stat->ssim_y); + if (one_second) + fprintf(fp, "bitsrate: %d,", stat->ins_bitrate); + if (!seq_end) + fprintf(fp, "\n"); + } +} + +static MPP_RET mpi_rc_enc_init(MpiRc2TestCtx *ctx) +{ + MpiEncTestArgs* enc_cmd = ctx->enc_cmd; + MppApi *enc_mpi = NULL; + MppCtx enc_ctx = NULL; + MppPollType block = MPP_POLL_NON_BLOCK; + MppEncRcCfg *rc_cfg = &ctx->rc_cfg; + MppEncSeiMode sei_mode = MPP_ENC_SEI_MODE_ONE_SEQ; + MppEncCfg cfg = ctx->cfg; + RK_U32 debreath_en = 0; + RK_U32 debreath_s = 0; + MPP_RET ret = MPP_OK; + + // encoder init + ret = mpp_create(&ctx->enc_ctx, &ctx->enc_mpi); + if (ret) { + mpp_err("mpp_create encoder failed\n"); + goto MPP_TEST_OUT; + } + + enc_mpi = ctx->enc_mpi; + enc_ctx = ctx->enc_ctx; + + rc_cfg->fps_in_denom = 1; + rc_cfg->fps_out_denom = 1; + rc_cfg->fps_in_num = 30; + rc_cfg->fps_out_num = 30; + rc_cfg->fps_in_flex = 0; + rc_cfg->fps_out_flex = 0; + rc_cfg->max_reenc_times = 1; + rc_cfg->gop = enc_cmd->gop_len; + + block = MPP_POLL_BLOCK; + ret = enc_mpi->control(enc_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block); + if (ret) { + mpp_err("enc_mpi->control MPP_SET_INPUT_TIMEOUT failed\n"); + goto MPP_TEST_OUT; + } + block = MPP_POLL_BLOCK; + ret = enc_mpi->control(enc_ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&block); + if (ret) { + mpp_err("enc_mpi->control MPP_SET_OUTPUT_TIMEOUT failed\n"); + goto MPP_TEST_OUT; + } + + ret = mpp_init(enc_ctx, MPP_CTX_ENC, enc_cmd->type); + if (ret) { + mpp_err("mpp_init enc failed\n"); + goto MPP_TEST_OUT; + } + + if (enc_cmd->width) + mpp_enc_cfg_set_s32(cfg, "prep:width", enc_cmd->width); + if (enc_cmd->height) + mpp_enc_cfg_set_s32(cfg, "prep:height", enc_cmd->height); + if (enc_cmd->hor_stride) + mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", enc_cmd->hor_stride); + if (enc_cmd->ver_stride) + mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", enc_cmd->ver_stride); + mpp_enc_cfg_set_s32(cfg, "prep:format", MPP_FMT_YUV420SP); + + mpp_enc_cfg_set_s32(cfg, "rc:mode", enc_cmd->rc_mode); + + switch (enc_cmd->rc_mode) { + case MPP_ENC_RC_MODE_FIXQP : { + /* do not set bps on fix qp mode */ + } break; + case MPP_ENC_RC_MODE_CBR : { + /* CBR mode has narrow bound */ + mpp_enc_cfg_set_s32(cfg, "rc:bps_target", enc_cmd->bps_target); + mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_cmd->bps_max ? enc_cmd->bps_max : enc_cmd->bps_target * 3 / 2); + mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_cmd->bps_min ? enc_cmd->bps_max : enc_cmd->bps_target / 2); + } break; + case MPP_ENC_RC_MODE_VBR : { + /* CBR mode has wide bound */ + mpp_enc_cfg_set_s32(cfg, "rc:bps_target", enc_cmd->bps_target); + mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_cmd->bps_max ? enc_cmd->bps_max : enc_cmd->bps_target * 17 / 16); + mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_cmd->bps_min ? enc_cmd->bps_max : enc_cmd->bps_target * 1 / 16); + } break; + default : { + mpp_err_f("unsupport encoder rc mode %d\n", enc_cmd->rc_mode); + } break; + } + + /* fix input / output frame rate */ + mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", rc_cfg->fps_in_flex); + mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", rc_cfg->fps_in_num); + mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denom", rc_cfg->fps_in_denom); + mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", rc_cfg->fps_out_flex); + mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", rc_cfg->fps_out_num); + mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denom", rc_cfg->fps_out_denom); + mpp_enc_cfg_set_s32(cfg, "rc:gop", enc_cmd->gop_len ? enc_cmd->gop_len : 30 * 2); + + /* drop frame or not when bitrate overflow */ + mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED); + mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); /* 20% of max bps */ + mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */ + + mpp_env_get_u32("dbrh_en", &debreath_en, 0); + mpp_env_get_u32("dbrh_s", &debreath_s, 16); + + mpp_enc_cfg_set_u32(cfg, "rc:debreath_en", debreath_en); + mpp_enc_cfg_set_u32(cfg, "rc:debreath_strength", debreath_s); + + /* setup codec */ + mpp_enc_cfg_set_s32(cfg, "codec:type", enc_cmd->type); + switch (enc_cmd->type) { + case MPP_VIDEO_CodingAVC : { + /* + * H.264 profile_idc parameter + * 66 - Baseline profile + * 77 - Main profile + * 100 - High profile + */ + mpp_enc_cfg_set_s32(cfg, "h264:profile", 100); + /* + * H.264 level_idc parameter + * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps + * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps + * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps + * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps + * 50 / 51 / 52 - 4K@30fps + */ + mpp_enc_cfg_set_s32(cfg, "h264:level", 40); + mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1); + mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0); + mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1); + + if (enc_cmd->rc_mode == MPP_ENC_RC_MODE_FIXQP) { + mpp_enc_cfg_set_s32(cfg, "h264:qp_init", 20); + mpp_enc_cfg_set_s32(cfg, "h264:qp_max", 16); + mpp_enc_cfg_set_s32(cfg, "h264:qp_min", 16); + mpp_enc_cfg_set_s32(cfg, "h264:qp_max_i", 20); + mpp_enc_cfg_set_s32(cfg, "h264:qp_min_i", 20); + } else { + mpp_enc_cfg_set_s32(cfg, "h264:qp_init", 26); + mpp_enc_cfg_set_s32(cfg, "h264:qp_max", 51); + mpp_enc_cfg_set_s32(cfg, "h264:qp_min", 10); + mpp_enc_cfg_set_s32(cfg, "h264:qp_max_i", 46); + mpp_enc_cfg_set_s32(cfg, "h264:qp_min_i", 18); + } + } break; + case MPP_VIDEO_CodingMJPEG : { + mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80); + mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99); + mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1); + } break; + case MPP_VIDEO_CodingVP8 : { + mpp_enc_cfg_set_s32(cfg, "vp8:qp_init", 40); + mpp_enc_cfg_set_s32(cfg, "vp8:qp_max", 127); + mpp_enc_cfg_set_s32(cfg, "vp8:qp_min", 0); + mpp_enc_cfg_set_s32(cfg, "vp8:qp_max_i", 127); + mpp_enc_cfg_set_s32(cfg, "vp8:qp_min_i", 0); + } break; + case MPP_VIDEO_CodingHEVC : { + mpp_enc_cfg_set_s32(cfg, "h265:qp_init", enc_cmd->rc_mode == MPP_ENC_RC_MODE_FIXQP ? -1 : 26); + mpp_enc_cfg_set_s32(cfg, "h265:qp_max", 51); + mpp_enc_cfg_set_s32(cfg, "h265:qp_min", 10); + mpp_enc_cfg_set_s32(cfg, "h265:qp_max_i", 46); + mpp_enc_cfg_set_s32(cfg, "h265:qp_min_i", 18); + } break; + default : { + mpp_err_f("unsupport encoder coding type %d\n", enc_cmd->type); + } break; + } + + ret = enc_mpi->control(enc_ctx, MPP_ENC_SET_CFG, cfg); + if (ret) { + mpp_err("mpi control enc set cfg failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + /* optional */ + ret = enc_mpi->control(enc_ctx, MPP_ENC_SET_SEI_CFG, &sei_mode); + if (ret) { + mpp_err("mpi control enc set sei cfg failed ret %d\n", ret); + goto MPP_TEST_OUT; + } +MPP_TEST_OUT: + return ret; +} + +static MPP_RET mpi_rc_post_dec_init(MpiRc2TestCtx *ctx) +{ + MpiEncTestArgs *enc_cmd = ctx->enc_cmd; + MppApi *dec_mpi = NULL; + MppCtx dec_ctx = NULL; + MppPollType block = MPP_POLL_NON_BLOCK; + RK_U32 need_split = 0; + MPP_RET ret = MPP_OK; + + // decoder init + ret = mpp_create(&ctx->dec_ctx_post, &ctx->dec_mpi_post); + if (ret) { + mpp_err("mpp_create decoder failed\n"); + goto MPP_TEST_OUT; + } + + dec_mpi = ctx->dec_mpi_post; + dec_ctx = ctx->dec_ctx_post; + + ret = mpp_packet_init(&ctx->dec_pkt_post, + ctx->dec_in_buf_post, ctx->dec_in_buf_post_size); + if (ret) { + mpp_err("mpp_packet_init failed\n"); + goto MPP_TEST_OUT; + } + + ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, &need_split); + if (ret) { + mpp_err("dec_mpi->control failed\n"); + goto MPP_TEST_OUT; + } + ret = dec_mpi->control(dec_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block); + if (ret) { + mpp_err("dec_mpi->control dec MPP_SET_INPUT_TIMEOUT failed\n"); + goto MPP_TEST_OUT; + } + + block = MPP_POLL_NON_BLOCK; + ret = dec_mpi->control(dec_ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&block); + if (ret) { + mpp_err("dec_mpi->control MPP_SET_OUTPUT_TIMEOUT failed\n"); + goto MPP_TEST_OUT; + } + + ret = mpp_init(dec_ctx, MPP_CTX_DEC, enc_cmd->type); + if (ret) { + mpp_err("mpp_init dec failed\n"); + goto MPP_TEST_OUT; + } + +MPP_TEST_OUT: + + return ret; +} + +static MPP_RET mpi_rc_dec_post_decode(MpiRc2TestCtx *ctx, MppFrame orig_frm) +{ + MPP_RET ret = MPP_OK; + RK_S32 dec_pkt_done = 0; + MppFrame out_frm = NULL; + + do { + if (ctx->pkt_eos) + mpp_packet_set_eos(ctx->dec_pkt_post); + + // send the packet first if packet is not done + if (!dec_pkt_done) { + ret = ctx->dec_mpi_post->decode_put_packet(ctx->dec_ctx_post, + ctx->dec_pkt_post); + if (MPP_OK == ret) + dec_pkt_done = 1; + } + + // then get all available frame and release + do { + RK_S32 dec_get_frm = 0; + RK_U32 dec_frm_eos = 0; + + ret = ctx->dec_mpi_post->decode_get_frame(ctx->dec_ctx_post, + &out_frm); + if (ret) { + mpp_err("decode_get_frame failed ret %d\n", ret); + break; + } + + if (out_frm) { + if (mpp_frame_get_info_change(out_frm)) { + mpp_log("decode_get_frame get info changed found\n"); + ctx->dec_mpi_post->control(ctx->dec_ctx_post, + MPP_DEC_SET_INFO_CHANGE_READY, + NULL); + } else { + mpi_rc_calc_stat(ctx, orig_frm, out_frm); + mpi_rc_log_stat(ctx, ctx->frm_idx, + !((ctx->frm_idx - ctx->calc_base_idx + 1) % + ctx->rc_cfg.fps_in_num), + 0); + dec_get_frm = 1; + } + dec_frm_eos = mpp_frame_get_eos(out_frm); + mpp_frame_deinit(&out_frm); + out_frm = NULL; + } + + // if last packet is send but last frame is not found continue + if (ctx->pkt_eos && dec_pkt_done && !dec_frm_eos) + continue; + + if (dec_get_frm) + break; + } while (1); + + if (dec_pkt_done) + break; + + msleep(5); + } while (1); + + return ret; +} + +static MPP_RET mpi_rc_pre_dec_init(MpiRc2TestCtx *ctx) +{ + RK_U32 need_split = 1; + MppPollType block = MPP_POLL_NON_BLOCK; + RK_U32 fast_en = 0; + MppApi *dec_mpi = NULL; + MppCtx dec_ctx = NULL; + MppFrameFormat format = MPP_FMT_YUV420SP; + RK_U32 fbc_en = 0; + MPP_RET ret = MPP_OK; + + mpp_env_get_u32("fbc_dec_en", &fbc_en, 0); + mpp_env_get_u32("fast_en", &fast_en, 0); + + if (fbc_en) + format = format | MPP_FRAME_FBC_AFBC_V2; + + // decoder init + ret = mpp_create(&ctx->dec_ctx_pre, &ctx->dec_mpi_pre); + if (ret) { + mpp_err("mpp_create decoder failed\n"); + goto MPP_TEST_OUT; + } + + dec_mpi = ctx->dec_mpi_pre; + dec_ctx = ctx->dec_ctx_pre; + + ret = mpp_packet_init(&ctx->dec_pkt_pre, ctx->dec_in_buf_pre, ctx->dec_in_buf_pre_size); + if (ret) { + mpp_err("mpp_packet_init failed\n"); + goto MPP_TEST_OUT; + } + + ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, &need_split); + if (ret) { + mpp_err("dec_mpi->control failed\n"); + goto MPP_TEST_OUT; + } + + ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_PARSER_FAST_MODE, &fast_en); + if (ret) { + mpp_err("dec_mpi->control failed\n"); + goto MPP_TEST_OUT; + } + + ret = dec_mpi->control(dec_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block); + if (ret) { + mpp_err("dec_mpi->control dec MPP_SET_INPUT_TIMEOUT failed\n"); + goto MPP_TEST_OUT; + } + + block = MPP_POLL_NON_BLOCK; + ret = dec_mpi->control(dec_ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&block); + if (ret) { + mpp_err("dec_mpi->control MPP_SET_OUTPUT_TIMEOUT failed\n"); + goto MPP_TEST_OUT; + } + + ret = mpp_init(dec_ctx, MPP_CTX_DEC, ctx->dec_type); + if (ret) { + mpp_err("mpp_init dec failed\n"); + goto MPP_TEST_OUT; + } + + ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_OUTPUT_FORMAT, &format); + if (ret) { + mpp_err("dec_mpi->control failed\n"); + goto MPP_TEST_OUT; + } + +MPP_TEST_OUT: + return ret; +} + +static MPP_RET mpi_rc_info_change(MpiRc2TestCtx *ctx, MppFrame frm) +{ + MPP_RET ret = MPP_OK; + + mpp_enc_cfg_set_s32(ctx->cfg, "prep:width", mpp_frame_get_width(frm)); + mpp_enc_cfg_set_s32(ctx->cfg, "prep:height", mpp_frame_get_height(frm)); + mpp_enc_cfg_set_s32(ctx->cfg, "prep:hor_stride", mpp_frame_get_hor_stride(frm)); + mpp_enc_cfg_set_s32(ctx->cfg, "prep:ver_stride", mpp_frame_get_ver_stride(frm)); + mpp_enc_cfg_set_s32(ctx->cfg, "prep:format", mpp_frame_get_fmt(frm)); + + ret = ctx->enc_mpi->control(ctx->enc_ctx, MPP_ENC_SET_CFG, ctx->cfg); + + ctx->dec_mpi_post->control(ctx->dec_ctx_post, MPP_DEC_SET_FRAME_INFO, (MppParam)frm); + + return ret; +} + +static MPP_RET mpi_rc_enc(MpiRc2TestCtx *ctx) +{ + MPP_RET ret = MPP_OK; + MppApi *mpi = ctx->dec_mpi_pre; + MppCtx dec_ctx = ctx->dec_ctx_pre; + MppFrame frm = NULL; + + do { + ret = mpi->decode_get_frame(dec_ctx, &frm); + if (ret) { + mpp_err("decode_get_frame failed ret %d\n", ret); + break; + } + + if (frm) { + ctx->frm_eos = mpp_frame_get_eos(frm); + if (mpp_frame_get_info_change(frm)) { + mpp_log("decode_get_frame get info changed found\n"); + mpi->control(dec_ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); + mpi_rc_info_change(ctx, frm); + ctx->start_enc = mpp_time(); + } else { + void *ptr; + size_t len; + /*force eos*/ + if ((ctx->enc_cmd->frame_num > 0) && (ctx->frm_idx > ctx->enc_cmd->frame_num)) { + ctx->loop_end = 1; + mpp_frame_set_eos(frm, 1); + ctx->frm_eos = mpp_frame_get_eos(frm); + } +#ifndef ASYN_ENC + ctx->enc_mpi->encode_put_frame(ctx->enc_ctx, frm); + ctx->enc_mpi->encode_get_packet(ctx->enc_ctx, &ctx->enc_pkt); +#else + LAST_PACKET: + ctx->enc_mpi->encode(ctx->enc_ctx, frm, &ctx->enc_pkt); + frm = NULL; //ASYN_ENC will free after get packet +#endif + if (ctx->enc_pkt) { + len = mpp_packet_get_length(ctx->enc_pkt); + ctx->stat.frame_size = len; + ctx->stream_size_1s += len; + ctx->total_bits += len * 8; + if ((ctx->frm_idx - ctx->calc_base_idx + 1) % + ctx->rc_cfg.fps_in_num == 0) { + ctx->stat.ins_bitrate = ctx->stream_size_1s; + ctx->stream_size_1s = 0; + } + + ptr = mpp_packet_get_pos(ctx->enc_pkt); + if (ctx->file.fp_enc_out) + fwrite(ptr, 1, len, ctx->file.fp_enc_out); + + /* check post packet first */ + if (len > ctx->dec_in_buf_post_size) { + RK_U32 buf_size = MPP_ALIGN(len, SZ_4K); + + ctx->dec_in_buf_post = mpp_realloc(ctx->dec_in_buf_post, RK_U8, buf_size); + ctx->dec_in_buf_post_size = buf_size; + + mpp_packet_set_data(ctx->dec_pkt_post, ctx->dec_in_buf_post); + mpp_packet_set_size(ctx->dec_pkt_post, buf_size); + mpp_packet_set_pos(ctx->dec_pkt_post, ctx->dec_in_buf_post); + mpp_packet_set_length(ctx->dec_pkt_post, 0); + } + + /* decode one frame */ + // write packet to dec input + mpp_packet_write(ctx->dec_pkt_post, 0, ptr, len); + // reset pos + mpp_packet_set_pos(ctx->dec_pkt_post, ctx->dec_in_buf_post); + mpp_packet_set_length(ctx->dec_pkt_post, len); + mpp_packet_set_size(ctx->dec_pkt_post, len); + + if (mpp_packet_has_meta(ctx->enc_pkt)) { + MppFrame frame = NULL; + MppMeta meta = mpp_packet_get_meta(ctx->enc_pkt); + mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frame); + if (ctx->enc_cmd->ssim_en || ctx->enc_cmd->psnr_en) { + mpp_packet_write(ctx->dec_pkt_post, 0, ptr, len); + mpi_rc_dec_post_decode(ctx, frame); + } + if (frame) { + frm = frame; //ASYN_ENC delay free + } + } else { + if (ctx->enc_cmd->ssim_en || ctx->enc_cmd->psnr_en) { + mpp_packet_write(ctx->dec_pkt_post, 0, ptr, len); + mpi_rc_dec_post_decode(ctx, frm); + } + } + ctx->enc_pkt_eos = mpp_packet_get_eos(ctx->enc_pkt); + ctx->frm_idx++; + mpp_packet_deinit(&ctx->enc_pkt); + } + + } + mpp_frame_deinit(&frm); + frm = NULL; + } else { + msleep(3); + continue; + } +#ifdef ANSY_ENC + if (ctx->frm_eos && !ctx->enc_pkt_eos) { + goto LAST_PACKET; + } +#endif + if (ctx->enc_pkt_eos) { + break; + } + } while (1); + return ret; +} + +static MPP_RET mpi_rc_buffer_init(MpiRc2TestCtx *ctx) +{ + /* NOTE: packet buffer may overflow */ + size_t packet_size = SZ_256K; + MPP_RET ret = MPP_OK; + + ret = mpp_buffer_group_get_internal(&ctx->pkt_grp, MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err("failed to get buffer group for output packet ret %d\n", ret); + goto RET; + } + + ctx->dec_in_buf_post = mpp_calloc(RK_U8, packet_size); + if (NULL == ctx->dec_in_buf_post) { + mpp_err("mpi_dec_test malloc input stream buffer failed\n"); + goto RET; + } + + ctx->dec_in_buf_post_size = packet_size; + + ctx->frm_idx = 0; + ctx->calc_base_idx = 0; + ctx->stream_size_1s = 0; + + return ret; +RET: + ctx->dec_ctx_pre = NULL; + ctx->dec_ctx_post = NULL; + MPP_FREE(ctx->dec_in_buf_post); + + if (ctx->pkt_grp) { + mpp_buffer_group_put(ctx->pkt_grp); + ctx->pkt_grp = NULL; + } + + return ret; +} + +#define CHECK_RET(x) do { \ + if (x < 0) { \ + mpp_err_f("%d failed\n"); \ + goto MPP_TEST_OUT; \ + } \ + } while (0) + +static void *rc2_pre_dec_thread(void *param) +{ + MpiRc2TestCtx *ctx = (MpiRc2TestCtx *)param; + FileReader reader = ctx->reader; + FileBufSlot *slot = NULL; + MppPacket packet = ctx->dec_pkt_pre; + MppApi *mpi = ctx->dec_mpi_pre; + MppCtx dec_ctx = ctx->dec_ctx_pre; + MPP_RET ret = MPP_OK; + RK_S32 dec_pkt_done = 0; + + while (!ctx->loop_end) { + RK_U32 pkt_eos = 0; + dec_pkt_done = 0; + ret = reader_index_read(reader, ctx->pre_pkt_idx++, &slot); + pkt_eos = slot->eos; + if (pkt_eos) { + if (ctx->enc_cmd->frame_num < 0) { + ctx->pre_pkt_idx = 0; + pkt_eos = 0; + } else if (!ctx->enc_cmd->frame_num) { + ctx->loop_end = 1; + } else { + ctx->pre_pkt_idx = 0; + pkt_eos = 0; + } + } + + if ((ctx->enc_cmd->frame_num > 0) && (ctx->frm_idx > ctx->enc_cmd->frame_num)) { + mpp_log("frm_idx %d, frame_num %d", + ctx->frm_idx, ctx->enc_cmd->frame_num); + ctx->loop_end = 1; + } + mpp_packet_set_data(packet, slot->data); + mpp_packet_set_size(packet, slot->size); + mpp_packet_set_pos(packet, slot->data); + mpp_packet_set_length(packet, slot->size); + + if (ctx->loop_end) { + mpp_packet_set_eos(packet); + ctx->pkt_eos = 1; + } + + do { + ret = mpi->decode_put_packet(dec_ctx, packet); + if (MPP_OK == ret) + dec_pkt_done = 1; + else + msleep(5); + if (ctx->loop_end) { + break; + } + } while (!dec_pkt_done); + + if (ctx->pkt_eos) { + mpp_log("dec stream finish\n"); + break; + } + } + mpp_log("rc2_pre_dec_thread exit"); + return NULL; +} + +static MPP_RET mpi_rc_codec(MpiRc2TestCtx *ctx) +{ + MPP_RET ret = MPP_OK; + RK_S64 t_e; + + CHECK_RET(mpi_rc_buffer_init(ctx)); + CHECK_RET(mpi_rc_post_dec_init(ctx)); + CHECK_RET(mpi_rc_pre_dec_init(ctx)); + CHECK_RET(mpp_enc_cfg_init(&ctx->cfg)); + CHECK_RET(mpi_rc_enc_init(ctx)); + + pthread_create(&ctx->dec_thr, NULL, rc2_pre_dec_thread, ctx); + + while (1) { + mpi_rc_enc(ctx); + if (ctx->enc_pkt_eos) { + mpp_log("stream finish\n"); + break; + } + } + + t_e = mpp_time(); + RK_U64 elapsed_time = t_e - ctx->start_enc; + float frame_rate = (float)ctx->frm_idx * 1000000 / elapsed_time; + mpp_log("enc_dec %d frame use time %lld ms frm rate %.2f\n", + ctx->frm_idx, elapsed_time / 1000, frame_rate); + + if (ctx->frm_idx) { + MpiEncTestArgs* enc_cmd = ctx->enc_cmd; + + mpp_log("%s: %s: average: bps %d | psnr %5.2f | ssim %5.5f", + enc_cmd->file_input, enc_cmd->gop_mode ? "smart_p" : "normal_p", + 30 * (RK_U32)(ctx->total_bits / ctx->frm_idx), + ctx->total_psnrs / ctx->frm_idx, ctx->total_ssims / ctx->frm_idx); + if (ctx->file.fp_stat) + fprintf(ctx->file.fp_stat, "%s: %s: average: bps %dk | psnr %5.2f | ssim %5.5f \n", + enc_cmd->file_input, enc_cmd->gop_mode ? "smart_p" : "normal_p", + 30 * (RK_U32)(ctx->total_bits / ctx->frm_idx) / 1000, + ctx->total_psnrs / ctx->frm_idx, ctx->total_ssims / ctx->frm_idx); + } + + CHECK_RET(ctx->enc_mpi->reset(ctx->enc_ctx)); + CHECK_RET(ctx->dec_mpi_pre->reset(ctx->dec_ctx_pre)); + CHECK_RET(ctx->dec_mpi_post->reset(ctx->dec_ctx_post)); + +MPP_TEST_OUT: + // encoder deinit + + pthread_join(ctx->dec_thr, NULL); + + if (ctx->enc_ctx) { + mpp_destroy(ctx->enc_ctx); + ctx->enc_ctx = NULL; + } + + if (ctx->pkt_grp) { + mpp_buffer_group_put(ctx->pkt_grp); + ctx->pkt_grp = NULL; + } + + // decoder deinit + if (ctx->dec_pkt_post) { + mpp_packet_deinit(&ctx->dec_pkt_post); + ctx->dec_pkt_post = NULL; + } + + if (ctx->dec_pkt_pre) { + mpp_packet_deinit(&ctx->dec_pkt_pre); + ctx->dec_pkt_pre = NULL; + } + + if (ctx->cfg) { + mpp_enc_cfg_deinit(ctx->cfg); + ctx->cfg = NULL; + } + + if (ctx->dec_ctx_post) { + mpp_destroy(ctx->dec_ctx_post); + ctx->dec_ctx_post = NULL; + } + + if (ctx->dec_ctx_pre) { + mpp_destroy(ctx->dec_ctx_pre); + ctx->dec_ctx_pre = NULL; + } + + MPP_FREE(ctx->dec_in_buf_post); + MPP_FREE(ctx->dec_in_buf_pre); + + return ret; +} + +int main(int argc, char **argv) +{ + MppEncTestObjSet *obj_set = NULL; + MpiRc2TestCtx *ctx = NULL; + MPP_RET ret; + + ret = mpi_enc_test_objset_get(&obj_set); + if (ret) + goto DONE; + + ret = mpi_enc_test_objset_update_by_args(obj_set, argc, argv, MODULE_TAG); + if (ret) + goto DONE; + + ctx = mpp_calloc(MpiRc2TestCtx, 1); + if (NULL == ctx) { + ret = MPP_ERR_MALLOC; + goto DONE; + } + + ctx->enc_cmd = obj_set->cmd; + + ret = mpi_rc_init(ctx); + if (ret) { + mpp_err("mpi_rc_init failded ret %d", ret); + goto DONE; + } + + ret = mpi_rc_codec(ctx); + if (ret) + mpp_err("mpi_rc_codec failded ret %d", ret); + +DONE: + if (ctx) { + mpi_rc_deinit(ctx); + ctx = NULL; + } + + mpi_enc_test_objset_put(obj_set); + + return (int)ret; +} diff --git a/test/mpi_test.c b/test/mpi_test.c deleted file mode 100644 index 71dd6d00d..000000000 --- a/test/mpi_test.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined(_WIN32) -#include "vld.h" -#endif - -#define MODULE_TAG "mpi_test" - -#include -#include "rk_mpi.h" -#include "mpp_log.h" -#include "mpp_env.h" - - -#define MPI_DEC_LOOP_COUNT 4 -#define MPI_ENC_LOOP_COUNT 4 - -#define MPI_STREAM_SIZE (SZ_512K) - -int main() -{ - MPP_RET ret; - MppCtx ctx = NULL; - MppApi *mpi = NULL; - MppEncConfig cfg; - - MppPacket dec_in = NULL; - MppFrame dec_out = NULL; - - MppFrame enc_in = NULL; - MppPacket enc_out = NULL; - - MpiCmd cmd = MPP_CMD_BASE; - MppParam param = NULL; - - RK_S32 i; - char *buf = NULL; - RK_S32 size = MPI_STREAM_SIZE; - - mpp_log("mpi_test start\n"); - - mpp_env_set_u32("mpi_debug", 0x1); - - buf = (char *)malloc(size); - if (NULL == buf) { - mpp_err("mpi_test malloc failed\n"); - goto MPP_TEST_FAILED; - } - - mpp_log("mpi_test decoder test start\n"); - - // decoder demo - ret = mpp_init(&ctx, &mpi, MPP_CTX_DEC, MPP_VIDEO_CodingUnused); - if (MPP_OK != ret) { - mpp_err("mpp_init failed\n"); - goto MPP_TEST_FAILED; - } - - // NOTE: decoder do not need control function - - ret = mpi->control(ctx, cmd, param); - if (MPP_OK != ret) { - mpp_err("mpi->control failed\n"); - goto MPP_TEST_FAILED; - } - - // interface with both input and output - for (i = 0; i < MPI_DEC_LOOP_COUNT; i++) { - mpp_packet_init(&dec_in, buf, size); - - // IMPORTANT: eos flag will flush all decoded frame - if (i == MPI_DEC_LOOP_COUNT - 1) - mpp_packet_set_eos(dec_in); - - // TODO: read stream data to buf - - ret = mpi->decode(ctx, dec_in, &dec_out); - if (MPP_OK != ret) { - goto MPP_TEST_FAILED; - } - - if (dec_out) { - // interface may output multiple frame at one time - do { - MppFrame next = mpp_frame_get_next(dec_out); - - // TODO: diaplay function called here - - mpp_frame_deinit(&dec_out); - dec_out = next; - } while (dec_out); - } - - mpp_packet_deinit(&dec_in); - } - - // interface with input and output separated - for (i = 0; i < MPI_DEC_LOOP_COUNT; i++) { - mpp_packet_init(&dec_in, buf, size); - mpp_packet_set_pts(dec_in, i); - - // IMPORTANT: eos flag will flush all decoded frame - if (i == MPI_DEC_LOOP_COUNT - 1) - mpp_packet_set_eos(dec_in); - - // TODO: read stream data to buf - - ret = mpi->decode_put_packet(ctx, dec_in); - if (MPP_OK != ret) { - goto MPP_TEST_FAILED; - } - - mpp_packet_deinit(&dec_in); - } - - for (i = 0; i < MPI_DEC_LOOP_COUNT; ) { - ret = mpi->decode_get_frame(ctx, &dec_out); - if (MPP_OK != ret) { - goto MPP_TEST_FAILED; - } - - if (dec_out) { - // interface may output multiple frame at one time - do { - MppFrame next = mpp_frame_get_next(dec_out); - - // TODO: diaplay function called here - - mpp_frame_deinit(&dec_out); - dec_out = next; - i++; - } while (dec_out); - } - } - - - ret = mpi->flush(ctx); - if (MPP_OK != ret) { - mpp_err("mpi->flush failed\n"); - goto MPP_TEST_FAILED; - } - - mpp_deinit(ctx); - - - mpp_log("mpi_test encoder test start\n"); - - // encoder demo - ret = mpp_init(&ctx, &mpi, MPP_CTX_ENC, MPP_VIDEO_CodingUnused); - if (MPP_OK != ret) { - mpp_err("mpp_init failed\n"); - goto MPP_TEST_FAILED; - } - - memset(&cfg, 0, sizeof(cfg)); - - ret = mpi->config(ctx, cfg); - if (MPP_OK != ret) { - mpp_err("mpi->config failed\n"); - goto MPP_TEST_FAILED; - } - - ret = mpi->control(ctx, cmd, param); - if (MPP_OK != ret) { - mpp_err("mpi->control failed\n"); - goto MPP_TEST_FAILED; - } - - - - // interface with both input and output - for (i = 0; i < MPI_ENC_LOOP_COUNT; i++) { - mpp_frame_init(&enc_in); - - mpi->encode(ctx, enc_in, &enc_out); - if (MPP_OK != ret) { - goto MPP_TEST_FAILED; - } - - if (enc_out) - mpp_packet_deinit(&enc_out); - - mpp_frame_deinit(&enc_in); - } - - // interface with input and output separated - for (i = 0; i < MPI_ENC_LOOP_COUNT; i++) { - mpp_frame_init(&enc_in); - - // TODO: read stream data to buf - - mpi->encode_put_frame(ctx, enc_in); - if (MPP_OK != ret) { - goto MPP_TEST_FAILED; - } - - mpp_frame_deinit(&enc_in); - } - - for (i = 0; i < MPI_ENC_LOOP_COUNT; i++) { - mpi->encode_get_packet(ctx, &enc_out); - if (MPP_OK != ret) { - goto MPP_TEST_FAILED; - } - - if (enc_out) { - mpp_packet_deinit(&enc_out); - } - } - - - ret = mpi->flush(ctx); - if (MPP_OK != ret) { - mpp_err("mpi->flush failed\n"); - goto MPP_TEST_FAILED; - } - - if (dec_in) - mpp_packet_deinit(&dec_in); - - if (enc_in) - mpp_frame_deinit(&enc_in); - - mpp_deinit(ctx); - free(buf); - - mpp_log("mpi_test success\n"); - - return 0; - -MPP_TEST_FAILED: - if (dec_in) - mpp_packet_deinit(&dec_in); - - if (enc_in) - mpp_frame_deinit(&enc_in); - - if (ctx) - mpp_deinit(ctx); - if (buf) - free(buf); - - mpp_log("mpi_test failed\n"); - - return -1; -} - diff --git a/test/mpp_buffer_test.c b/test/mpp_buffer_test.c deleted file mode 100644 index d70a84a38..000000000 --- a/test/mpp_buffer_test.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "mpp_buffer_test" - -#include - -#include "mpp_log.h" -#include "mpp_buffer.h" - -#define MPP_BUFFER_TEST_SIZE (SZ_1K*4) -#define MPP_BUFFER_TEST_COMMIT_COUNT 10 -#define MPP_BUFFER_TEST_NORMAL_COUNT 10 - -int main() -{ - MPP_RET ret = MPP_OK; - MppBufferInfo commit; - MppBufferGroup group = NULL; - MppBuffer commit_buffer[MPP_BUFFER_TEST_COMMIT_COUNT]; - void *commit_ptr[MPP_BUFFER_TEST_COMMIT_COUNT]; - MppBuffer normal_buffer[MPP_BUFFER_TEST_NORMAL_COUNT]; - size_t size = MPP_BUFFER_TEST_SIZE; - RK_S32 count = MPP_BUFFER_TEST_COMMIT_COUNT; - RK_S32 i; - - mpp_log("mpp_buffer_test start\n"); - - memset(commit_ptr, 0, sizeof(commit_ptr)); - memset(commit_buffer, 0, sizeof(commit_buffer)); - memset(normal_buffer, 0, sizeof(normal_buffer)); - - ret = mpp_buffer_group_limited_get(&group, MPP_BUFFER_TYPE_NORMAL); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_test mpp_buffer_group_get failed\n"); - goto MPP_BUFFER_failed; - } - - mpp_buffer_group_limit_config(group, size, count); - - mpp_log("mpp_buffer_test commit mode start\n"); - - commit.type = MPP_BUFFER_TYPE_NORMAL; - commit.size = size; - - for (i = 0; i < count; i++) { - commit_ptr[i] = malloc(size); - if (NULL == commit_ptr[i]) { - mpp_err("mpp_buffer_test malloc failed\n"); - goto MPP_BUFFER_failed; - } - - commit.ptr = commit_ptr[i]; - - ret = mpp_buffer_commit(group, &commit); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_test mpp_buffer_commit failed\n"); - goto MPP_BUFFER_failed; - } - } - - for (i = 0; i < count; i++) { - ret = mpp_buffer_get(group, &commit_buffer[i], size); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_test mpp_buffer_get commit mode failed\n"); - goto MPP_BUFFER_failed; - } - } - - for (i = 0; i < count; i++) { - if (commit_buffer[i]) { - ret = mpp_buffer_put(commit_buffer[i]); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_test mpp_buffer_put commit mode failed\n"); - goto MPP_BUFFER_failed; - } - commit_buffer[i] = NULL; - } - } - - for (i = 0; i < count; i++) { - if (commit_ptr[i]) { - free(commit_ptr[i]); - commit_ptr[i] = NULL; - } - } - - mpp_buffer_group_put(group); - - mpp_log("mpp_buffer_test commit mode success\n"); - - mpp_log("mpp_buffer_test normal mode start\n"); - - ret = mpp_buffer_group_normal_get(&group, MPP_BUFFER_TYPE_ION); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_test mpp_buffer_group_get failed\n"); - goto MPP_BUFFER_failed; - } - - for (i = 0; i < MPP_BUFFER_TEST_NORMAL_COUNT; i++) { - ret = mpp_buffer_get(group, &normal_buffer[i], (i + 1) * SZ_1K); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_test mpp_buffer_get mode normal failed\n"); - goto MPP_BUFFER_failed; - } - } - - for (i = 0; i < MPP_BUFFER_TEST_NORMAL_COUNT; i++) { - if (normal_buffer[i]) { - ret = mpp_buffer_put(normal_buffer[i]); - if (MPP_OK != ret) { - mpp_err("mpp_buffer_test mpp_buffer_get mode normal failed\n"); - goto MPP_BUFFER_failed; - } - normal_buffer[i] = NULL; - } - } - - mpp_log("mpp_buffer_test normal mode success\n"); - - if (group) { - mpp_buffer_group_put(group); - group = NULL; - } - - mpp_log("mpp_buffer_test success\n"); - return ret; - -MPP_BUFFER_failed: - for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { - if (commit_buffer[i]) - mpp_buffer_put(commit_buffer[i]); - } - - for (i = 0; i < MPP_BUFFER_TEST_COMMIT_COUNT; i++) { - if (commit_ptr[i]) { - free(commit_ptr[i]); - commit_ptr[i] = NULL; - } - } - for (i = 0; i < MPP_BUFFER_TEST_NORMAL_COUNT; i++) { - if (normal_buffer[i]) - mpp_buffer_put(normal_buffer[i]); - } - - if (group) { - mpp_buffer_group_put(group); - group = NULL; - } - - mpp_log("mpp_buffer_test failed\n"); - return ret; -} - diff --git a/test/mpp_event_trigger.c b/test/mpp_event_trigger.c new file mode 100644 index 000000000..867b0adfd --- /dev/null +++ b/test/mpp_event_trigger.c @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpp_event_trigger.h" + +#include "mpp_debug.h" + +struct event_ctx_impl { + int (*notify)(void *param); + + event_trigger trigger; + + pthread_cond_t condition; + pthread_mutex_t mutex; + RK_U32 semval; + + pthread_t thr; + RK_S32 flag; + + struct event_packet *ea; + int event_idx; + + void *parent; +}; + +static int event_create(struct event_ctx_impl *ctx) +{ + int ret; + + ret = pthread_cond_init(&ctx->condition, NULL); + if (ret != 0) + return -1; + + ret = pthread_mutex_init(&ctx->mutex, NULL); + if (ret != 0) + return -1; + + ctx->semval = ctx->ea->e[0].idx; + mpp_log_f("with %u\n", ctx->semval); + + return 0; +} + +static void event_destroy(struct event_ctx_impl *ctx) +{ + pthread_cond_destroy(&ctx->condition); + pthread_mutex_destroy(&ctx->mutex); +} + +/* initialize and schedule next event */ +static void event_init(struct event_ctx_impl *ctx) +{ + struct ievent *e_curr; + struct ievent *e_next; + + pthread_mutex_lock(&ctx->mutex); + e_curr = &ctx->ea->e[ctx->event_idx % ctx->ea->cnt]; + e_next = &ctx->ea->e[(++ctx->event_idx) % ctx->ea->cnt]; + + mpp_log("curr %d, next %d\n", + e_curr->idx, e_next->idx); + + if (e_next->idx > e_curr->idx) + ctx->semval = e_next->idx - e_curr->idx; + else if (ctx->ea->loop > 0) + ctx->semval = e_next->idx + ctx->ea->loop - e_curr->idx; + else + ctx->flag = 0; + + mpp_log_f("semval %u\n", ctx->semval); + pthread_mutex_unlock(&ctx->mutex); +} + +/* wait the event trigger deadline */ +/*static void event_wait(struct event_ctx_impl *ctx) +{ + pthread_mutex_lock(&ctx->mutex); + while (ctx->semval > 0) + pthread_cond_wait(&ctx->condition, &ctx->mutex); + + ctx->semval--; + pthread_mutex_unlock(&ctx->mutex); +}*/ + +/* wait the event trigger deadline with timeout, avoid dead lock */ +static int event_timed_wait(struct event_ctx_impl *ctx, unsigned int milli_sec) +{ + int err = 0; + struct timespec final_time; + struct timeval curr_time; + long int microdelay; + + gettimeofday(&curr_time, NULL); + /* + * convert timeval to timespec and add delay in milliseconds + * for the timeout + */ + microdelay = ((milli_sec * 1000 + curr_time.tv_usec)); + final_time.tv_sec = curr_time.tv_sec + (microdelay / 1000000); + final_time.tv_nsec = (microdelay % 1000000) * 1000; + pthread_mutex_lock(&ctx->mutex); + while (ctx->semval > 0) { + err = pthread_cond_timedwait(&ctx->condition, &ctx->mutex, &final_time); + if (err != 0) + ctx->semval--; + } + ctx->semval--; + pthread_mutex_unlock(&ctx->mutex); + return err; +} + +/* event heart beat */ +static void event_down(struct event_ctx_impl *ctx) +{ + pthread_mutex_lock(&ctx->mutex); + ctx->semval--; + pthread_cond_signal(&ctx->condition); + pthread_mutex_unlock(&ctx->mutex); +} + +/* a callback to notify the event trigger that there is a event heart beat */ +static int event_notify(void *param) +{ + struct event_ctx_impl *ctx = (struct event_ctx_impl *)param; + + if (ctx->flag) + event_down(ctx); + + return 0; +} + +static void *event_trigger_thread(void *param) +{ + struct event_ctx_impl *ctx = (struct event_ctx_impl *)param; + struct timeval curr_time; + long start_time, curr; + RK_S32 ret; + + gettimeofday(&curr_time, NULL); + + start_time = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000; + event_create(ctx); + + while (1) { + ret = event_timed_wait(ctx, ctx->semval * 10000); + if (!ctx->flag) + break; + + if (ret == ETIMEDOUT) { + mpp_err("wait event timeout\n"); + break; + } + + gettimeofday(&curr_time, NULL); + + curr = curr_time.tv_sec * 1000 + curr_time.tv_usec / 1000; + /* TODO, trigger event */ + mpp_log("[%ld ms] event idx %d triggered\n", + curr - start_time, ctx->event_idx); + mpp_log("cnt %d\n", ctx->ea->cnt); + ctx->trigger(ctx->parent, ctx->ea->e[ctx->event_idx % ctx->ea->cnt].event); + + /* schedule next event */ + event_init(ctx); + if (!ctx->flag) + break; + } + + event_destroy(ctx); + + mpp_log_f("exit\n"); + + return NULL; +} + +struct event_ctx* event_ctx_create(struct event_packet *ea, + event_trigger trigger, void *parent) +{ + struct event_ctx_impl *ctx = (struct event_ctx_impl *)malloc(sizeof(*ctx)); + + if (ctx == NULL) { + mpp_err("allocate event ctx failed\n"); + return NULL; + } + + assert(ea->cnt <= 128); + + ctx->event_idx = 0; + ctx->ea = ea; + + ctx->notify = event_notify; + ctx->trigger = trigger; + ctx->parent = parent; + + ctx->flag = 1; + pthread_create(&ctx->thr, NULL, event_trigger_thread, ctx); + + return (struct event_ctx *)ctx; +} + +void event_ctx_release(struct event_ctx *ctx) +{ + void *ret; + struct event_ctx_impl *ictx = (struct event_ctx_impl *)ctx; + + assert(ctx != NULL); + + if (ictx->flag) { + ictx->flag = 0; + ictx->semval = 0; + pthread_cond_signal(&ictx->condition); + } + + pthread_join(ictx->thr, &ret); + + free(ictx); +} + +#ifdef EVENT_TRIGGER_TEST +/* + * the following codes is the sample to use the event trigger + */ +struct event_impl { + int cnt; + int loop; + int idx[128]; + int event[128]; +}; + +/* a callback to notify test that a event occur */ +static void event_occur(void *parent, void *event) +{ + int *e = (int *)event; + mpp_log("event %d occur\n", *e); +} + +int main(int argc, char **argv) +{ + struct event_ctx *ctx; + int i = 0; + struct event_impl ie; + struct event_packet ea; + + ie.cnt = 4; + ie.loop = 25; + ie.event[0] = ie.idx[0] = 4; + ie.event[1] = ie.idx[1] = 8; + ie.event[2] = ie.idx[2] = 18; + ie.event[3] = ie.idx[3] = 20; + + ea.cnt = ie.cnt; + ea.loop = ie.loop; + + for (i = 0; i < ie.cnt; ++i) { + ea.e[i].idx = ie.idx[i]; + ea.e[i].event = &ie.event[i]; + } + + ctx = event_ctx_create(&ea, event_occur, NULL); + + while (i++ < 100) { + usleep(10 * 1000); + mpp_log("%03d:\n", i); + ctx->notify((void*)ctx); + } + + event_ctx_release(ctx); + + return 0; +} +#endif diff --git a/test/mpp_event_trigger.h b/test/mpp_event_trigger.h new file mode 100644 index 000000000..429cad963 --- /dev/null +++ b/test/mpp_event_trigger.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_EVENT_TRIGGER_H +#define MPP_EVENT_TRIGGER_H + +typedef void (*event_trigger)(void *parent, void *event); + +struct ievent { + int idx; + void *event; +}; + +struct event_packet { + int cnt; + int loop; + struct ievent e[128]; +}; + +struct event_ctx { + int (*notify)(void *param); +}; + +struct event_ctx* event_ctx_create(struct event_packet *e, + event_trigger trigger, void *parent); +void event_ctx_release(struct event_ctx *ictx); + +#endif diff --git a/test/mpp_info_test.c b/test/mpp_info_test.c new file mode 100644 index 000000000..61d8d83c7 --- /dev/null +++ b/test/mpp_info_test.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#define MODULE_TAG "mpp_info_test" + +#include "mpp_log.h" +#include "mpp_env.h" +#include "mpp_info.h" +#include "mpp_compat.h" + +int main(void) +{ + mpp_env_set_u32("mpp_show_history", 0); + + mpp_log("normal version log:\n"); + show_mpp_version(); + + mpp_env_set_u32("mpp_show_history", 1); + mpp_log("history version log:\n"); + + show_mpp_version(); + mpp_env_set_u32("mpp_show_history", 0); + + mpp_compat_show(); + + return 0; +} + diff --git a/test/mpp_parse_cfg.c b/test/mpp_parse_cfg.c new file mode 100644 index 000000000..3cd80c0ac --- /dev/null +++ b/test/mpp_parse_cfg.c @@ -0,0 +1,255 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#include +#include + +#include "mpp_parse_cfg.h" + +#include "mpp_log.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +enum CONFIG_TYPE { + CONFIG_TYPE_OPTION, + CONFIG_TYPE_EVENT, + + OPT_TYPE_INDEX_TYPE, + OPT_TYPE_LOOP_NUM, + + IDX_TYPE_FRM_NUM, + IDX_TYPE_MSEC, +}; + +struct options_table { + int type; + const char *type_str; +}; + +/* table for converting string to type */ +static struct options_table op_tbl[] = { + {CONFIG_TYPE_OPTION, "[CONFIG]"}, + {CONFIG_TYPE_EVENT, "[EVENT]"}, + + {OPT_TYPE_INDEX_TYPE, "index"}, + {OPT_TYPE_LOOP_NUM, "loop"}, + + {IDX_TYPE_FRM_NUM, "frm"}, + {IDX_TYPE_MSEC, "msec"}, +}; + +struct cfg_file { + FILE *file; + char cache[128]; + RK_S32 cache_on; +}; + +/* get rid of leading and following space from string */ +static char *string_trim(char *string) +{ + char *p = string; + long len; + + if (string == NULL) + return NULL; + + while (*p == ' ') + p++; + + len = strlen(p); + + while (p[len - 1] == ' ') + len--; + p[len] = '\0'; + + return p; +} + +static char *read_cfg_line(struct cfg_file *cfg) +{ + int ch; + int i; + + while (!cfg->cache_on) { + i = 0; + + while (1) { + ch = fgetc(cfg->file); + if (i == 0 && ch == EOF) + return NULL; + else if (ch == EOF || feof(cfg->file) || ch == '\n') + break; + + cfg->cache[i++] = ch; + } + cfg->cache[i] = '\0'; + + /* a note, ignore and get the next line */ + if (cfg->cache[0] != '#') + break; + } + + cfg->cache_on = 1; + return string_trim(cfg->cache); +} + +static inline void invalid_cfg_cache(struct cfg_file *cfg) +{ + cfg->cache_on = 0; +} + +static char *get_opt_value(char *line) +{ + size_t i; + + for (i = 0; i < strlen(line); ++i) { + if (line[i] == ':') + return string_trim(&line[i + 1]); + } + + return NULL; +} + +/* convert string to index by look up map table */ +static int lookup_opt_type(char *line) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(op_tbl); ++i) { + if (!strncmp(op_tbl[i].type_str, line, + strlen(op_tbl[i].type_str))) { + mpp_log("option type %s find\n", op_tbl[i].type_str); + return op_tbl[i].type; + } + } + + return -1; +} + +static int scan_event_line(struct cfg_file *cfg, struct rc_event *event) +{ + char *line = read_cfg_line(cfg); + + if (line != NULL && line[0] != '\n' && line[0] != '[') { + sscanf(line, "%d\t%d\t%f", + &event->idx, &event->bps, &event->fps); + mpp_log("idx: %d, bps %u, fps: %f\n", + event->idx, event->bps, event->fps); + invalid_cfg_cache(cfg); + } else { + return -1; + } + + return 0; +} + +static int parse_events(struct cfg_file *cfg, struct rc_test_config *ea) +{ + int ret; + int i; + + for (i = 0; i < 128; ++i) { + ret = scan_event_line(cfg, &ea->event[i]); + if (ret < 0) { + ea->event_cnt = i; + break; + } + } + + return 0; +} + +static int parse_options(struct cfg_file *cfg, struct rc_test_config *ea) +{ + char *opt; + int type; + + while (1) { + opt = read_cfg_line(cfg); + + if (opt && opt[0] != '\n' && opt[0] != '[') { + type = lookup_opt_type(opt); + + switch (type) { + case OPT_TYPE_INDEX_TYPE: + ea->idx_type = lookup_opt_type(get_opt_value(opt)); + break; + case OPT_TYPE_LOOP_NUM: + sscanf(get_opt_value(opt), "%d", &ea->loop); + mpp_log("loop num: %d\n", ea->loop); + break; + default: + break; + } + + invalid_cfg_cache(cfg); + } else { + break; + } + } + return 0; +} + +int mpp_parse_config(char *cfg_url, struct rc_test_config *ea) +{ + struct cfg_file cfg; + + if (cfg_url == NULL || strlen(cfg_url) == 0) { + mpp_err("invalid input config url\n"); + return -1; + } + + cfg.file = fopen(cfg_url, "rb"); + if (cfg.file == NULL) { + mpp_err("fopen %s failed\n", cfg_url); + return -1; + } + cfg.cache_on = 0; + + while (1) { + char *line = read_cfg_line(&cfg); + + if (!line) + break; + + invalid_cfg_cache(&cfg); + if (line[0] == '[') { + int type = lookup_opt_type(line); + + switch (type) { + case CONFIG_TYPE_EVENT: + parse_events(&cfg, ea); + break; + case CONFIG_TYPE_OPTION: + parse_options(&cfg, ea); + break; + default: + mpp_err("invalid config type find\n"); + fclose(cfg.file); + return -1; + } + } + } + + fclose(cfg.file); + + return 0; +} + +#ifdef PARSE_CONFIG_TEST +int main(int argc, char **argv) +{ + struct rc_test_config event_array; + + if (argc < 2) { + mpp_err("invalid input argument\n"); + return -1; + } + + mpp_parse_config(argv[1], &event_array); + + return 0; +} +#endif diff --git a/test/mpp_parse_cfg.h b/test/mpp_parse_cfg.h new file mode 100644 index 000000000..00651d594 --- /dev/null +++ b/test/mpp_parse_cfg.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef MPP_PARSE_CFG_H +#define MPP_PARSE_CFG_H + +struct rc_event { + union { + int msec; + int frm; + int idx; + }; + float fps; + int bps; +}; + +struct rc_test_config { + int idx_type; + int loop; + struct rc_event event[128]; + int event_cnt; +}; + +int mpp_parse_config(char *cfg_url, struct rc_test_config *ea); + +#endif diff --git a/test/vpu_api_test.c b/test/vpu_api_test.c index 2dbfcd580..1c11005a5 100644 --- a/test/vpu_api_test.c +++ b/test/vpu_api_test.c @@ -1,762 +1,805 @@ -/* - * Copyright 2010 Rockchip Electronics S.LSI Co. LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define MODULE_TAG "vpu_api_demo" - -#include -#include -#include - -#include "mpp_log.h" -#include "mpp_time.h" - -#include "vpu_api.h" - -static RK_U32 VPU_API_DEMO_DEBUG_DISABLE = 0; - -#define BSWAP32(x) \ - ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) - -#define DEMO_ERR_RET(err) do { ret = err; goto DEMO_OUT; } while (0) -#define DECODE_ERR_RET(err) do { ret = err; goto DECODE_OUT; } while (0) -#define ENCODE_ERR_RET(err) do { ret = err; goto ENCODE_OUT; } while (0) - - -typedef enum VPU_API_DEMO_RET { - VPU_DEMO_OK = 0, - VPU_DEMO_PARSE_HELP_OK = 1, - - VPU_DEMO_ERROR_BASE = -100, - ERROR_INVALID_PARAM = VPU_DEMO_ERROR_BASE - 1, - ERROR_INVALID_STREAM = VPU_DEMO_ERROR_BASE - 2, - ERROR_IO = VPU_DEMO_ERROR_BASE - 3, - ERROR_MEMORY = VPU_DEMO_ERROR_BASE - 4, - ERROR_INIT_VPU = VPU_DEMO_ERROR_BASE - 5, - - ERROR_VPU_DECODE = VPU_DEMO_ERROR_BASE - 90, -} VPU_API_DEMO_RET; - -typedef struct VpuApiCmd { - char* name; - char* argname; - char* help; -} VpuApiCmd_t; - -typedef struct VpuApiDemoCmdContext { - RK_U32 width; - RK_U32 height; - CODEC_TYPE codec_type; - OMX_RK_VIDEO_CODINGTYPE coding; - char input_file[200]; - char output_file[200]; - RK_U8 have_input; - RK_U8 have_output; - RK_U8 disable_debug; - RK_U32 record_frames; - RK_S64 record_start_ms; -} VpuApiDemoCmdContext_t; - -typedef struct VpuApiEncInput { - EncInputStream_t stream; - RK_U32 capability; -} VpuApiEncInput; - -static VpuApiCmd_t vpuApiCmd[] = { - {"i", "input_file", "input bitstream file"}, - {"o", "output_file", "output bitstream file, "}, - {"w", "width", "the width of input bitstream"}, - {"h", "height", "the height of input bitstream"}, - {"t", "codec_type", "the codec type, dec: deoder, enc: encoder, default: decoder"}, - {"coding", "coding_type", "encoding type of the bitstream"}, - {"vframes", "number", "set the number of video frames to record"}, - {"ss", "time_off", "set the start time offset, use Ms as the unit."}, - {"d", "disable", "disable the debug output info."}, -}; - -static void show_usage() -{ - mpp_log("usage: vpu_apiDemo [options] input_file, \n\n"); - - mpp_log("Getting help:\n"); - mpp_log("-help --print options of vpu api demo\n"); -} - -static RK_S32 show_help() -{ - RK_S32 i = 0; - RK_S32 n = sizeof(vpuApiCmd) / sizeof(VpuApiCmd_t); - - mpp_log("usage: vpu_apiDemo [options] input_file, \n\n"); - - for (i = 0; i < n; i++) { - mpp_log("-%s %s\t\t%s\n", - vpuApiCmd[i].name, vpuApiCmd[i].argname, vpuApiCmd[i].help); - } - - return 0; -} - -static RK_S32 parse_options(int argc, char **argv, VpuApiDemoCmdContext_t* cmdCxt) -{ - char *opt; - RK_S32 optindex, handleoptions = 1, ret = 0; - - if ((argc < 2) || (cmdCxt == NULL)) { - mpp_log("vpu api demo, input parameter invalid\n"); - show_usage(); - return ERROR_INVALID_PARAM; - } - - /* parse options */ - optindex = 1; - while (optindex < argc) { - opt = argv[optindex++]; - - if (handleoptions && opt[0] == '-' && opt[1] != '\0') { - if (opt[1] == '-') { - if (opt[2] != '\0') { - opt++; - } else { - handleoptions = 0; - continue; - } - } - - opt++; - - switch (*opt) { - case 'i': - if (argv[optindex]) { - memcpy(cmdCxt->input_file, argv[optindex], strlen(argv[optindex])); - cmdCxt->input_file[strlen(argv[optindex])] = '\0'; - cmdCxt->have_input = 1; - } else { - mpp_log("input file is invalid\n"); - ret = -1; - goto PARSE_OPINIONS_OUT; - } - break; - case 'o': - if (argv[optindex]) { - memcpy(cmdCxt->output_file, argv[optindex], strlen(argv[optindex])); - cmdCxt->output_file[strlen(argv[optindex])] = '\0'; - cmdCxt->have_output = 1; - break; - } else { - mpp_log("out file is invalid\n"); - ret = -1; - goto PARSE_OPINIONS_OUT; - } - case 'd': - cmdCxt->disable_debug = 1; - break; - case 'w': - if (argv[optindex]) { - cmdCxt->width = atoi(argv[optindex]); - break; - } else { - mpp_log("input width is invalid\n"); - ret = -1; - goto PARSE_OPINIONS_OUT; - } - case 'h': - if ((*(opt + 1) != '\0') && !strncmp(opt, "help", 4)) { - show_help(); - ret = VPU_DEMO_PARSE_HELP_OK; - goto PARSE_OPINIONS_OUT; - } else if (argv[optindex]) { - cmdCxt->height = atoi(argv[optindex]); - } else { - mpp_log("input height is invalid\n"); - ret = -1; - goto PARSE_OPINIONS_OUT; - } - break; - case 't': - if (argv[optindex]) { - cmdCxt->codec_type = atoi(argv[optindex]); - break; - } else { - mpp_log("input codec_type is invalid\n"); - ret = -1; - goto PARSE_OPINIONS_OUT; - } - - default: - if ((*(opt + 1) != '\0') && argv[optindex]) { - if (!strncmp(opt, "coding", 6)) { - mpp_log("coding, argv[optindex]: %s", - argv[optindex]); - cmdCxt->coding = atoi(argv[optindex]); - } else if (!strncmp(opt, "vframes", 7)) { - cmdCxt->record_frames = atoi(argv[optindex]); - } else if (!strncmp(opt, "ss", 2)) { - cmdCxt->record_start_ms = atoi(argv[optindex]); - } else { - ret = -1; - goto PARSE_OPINIONS_OUT; - } - } else { - ret = -1; - goto PARSE_OPINIONS_OUT; - } - break; - } - - optindex += ret; - } - } - -PARSE_OPINIONS_OUT: - if (ret < 0) { - mpp_log("vpu api demo, input parameter invalid\n"); - show_usage(); - return ERROR_INVALID_PARAM; - } - return ret; -} - -static RK_S32 readBytesFromFile(RK_U8* buf, RK_S32 aBytes, FILE* file) -{ - RK_S32 ret = 0; - - if ((NULL == buf) || (NULL == file) || (0 == aBytes)) { - return -1; - } - - ret = (RK_S32)fread(buf, 1, aBytes, file); - if (ret != aBytes) { - mpp_log("read %d bytes from file fail\n", aBytes); - return -1; - } - - return 0; -} - -static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) -{ - FILE* pInFile = NULL; - FILE* pOutFile = NULL; - struct VpuCodecContext *ctx = NULL; - RK_S32 nal = 0x00000001; - RK_S32 fileSize, ret, size; - EncoderOut_t enc_out_yuv; - EncoderOut_t *enc_out = NULL; - VpuApiEncInput enc_in_strm; - VpuApiEncInput *api_enc_in = &enc_in_strm; - EncInputStream_t *enc_in = NULL; - EncParameter_t *enc_param = NULL; - RK_S64 fakeTimeUs = 0; - RK_U32 w_align = 0; - RK_U32 h_align = 0; - - int Format = VPU_H264ENC_YUV420_SEMIPLANAR; - - if (cmd == NULL) { - return -1; - } - - if ((cmd->have_input == 0) || (cmd->width <= 0) || (cmd->height <= 0) - || (cmd->coding <= OMX_RK_VIDEO_CodingAutoDetect)) { - mpp_log("Warning: missing needed parameters for vpu api demo\n"); - } - - if (cmd->have_input) { - mpp_log("input bitstream w: %d, h: %d, coding: %d(%s), path: %s\n", - cmd->width, cmd->height, cmd->coding, - cmd->codec_type == CODEC_DECODER ? "decode" : "encode", - cmd->input_file); - - pInFile = fopen(cmd->input_file, "rb"); - if (pInFile == NULL) { - mpp_log("input file not exsist\n"); - ENCODE_ERR_RET(ERROR_INVALID_PARAM); - } - } else { - mpp_log("please set input bitstream file\n"); - ENCODE_ERR_RET(ERROR_INVALID_PARAM); - } - - if (cmd->have_output) { - mpp_log("vpu api demo output file: %s\n", - cmd->output_file); - pOutFile = fopen(cmd->output_file, "wb"); - if (pOutFile == NULL) { - mpp_log("can not write output file\n"); - ENCODE_ERR_RET(ERROR_INVALID_PARAM); - } - } - - fseek(pInFile, 0L, SEEK_END); - fileSize = ftell(pInFile); - fseek(pInFile, 0L, SEEK_SET); - - memset(&enc_in_strm, 0, sizeof(VpuApiEncInput)); - enc_in = &enc_in_strm.stream; - enc_in->buf = NULL; - - memset(&enc_out_yuv, 0, sizeof(EncoderOut_t)); - enc_out = &enc_out_yuv; - enc_out->data = (RK_U8*)malloc(cmd->width * cmd->height); - if (enc_out->data == NULL) { - ENCODE_ERR_RET(ERROR_MEMORY); - } - - ret = vpu_open_context(&ctx); - if (ret || (ctx == NULL)) { - ENCODE_ERR_RET(ERROR_MEMORY); - } - - /* - ** now init vpu api context. codecType, codingType, width ,height - ** are all needed before init. - */ - ctx->codecType = cmd->codec_type; - ctx->videoCoding = cmd->coding; - ctx->width = cmd->width; - ctx->height = cmd->height; - ctx->no_thread = 1; - - ctx->private_data = malloc(sizeof(EncParameter_t)); - memset(ctx->private_data, 0, sizeof(EncParameter_t)); - - enc_param = (EncParameter_t*)ctx->private_data; - enc_param->width = cmd->width; - enc_param->height = cmd->height; - enc_param->bitRate = 100000; - enc_param->framerate = 25; - enc_param->enableCabac = 0; - enc_param->cabacInitIdc = 0; - enc_param->intraPicRate = 30; - - if ((ret = ctx->init(ctx, NULL, 0)) != 0) { - mpp_log("init vpu api context fail, ret: 0x%X\n", ret); - ENCODE_ERR_RET(ERROR_INIT_VPU); - } - - /* - ** init of VpuCodecContext while running encode, it returns - ** sps and pps of encoder output, you need to save sps and pps - ** after init. - */ - mpp_log("encode init ok, sps len: %d\n", ctx->extradata_size); - if (pOutFile && (ctx->extradata_size > 0)) { - mpp_log("dump %d bytes enc output stream to file\n", - ctx->extradata_size); - - /* save sps and pps */ - fwrite(ctx->extradata, 1, ctx->extradata_size, pOutFile); - fflush(pOutFile); - } - - ctx->control(ctx, VPU_API_ENC_SETFORMAT, &Format); - - ctx->control(ctx, VPU_API_ENC_GETCFG, enc_param); - enc_param->rc_mode = 1; - ctx->control(ctx, VPU_API_ENC_SETCFG, enc_param); - /* - ** vpu api encode process. - */ - mpp_log("init vpu api context ok, input yuv stream file size: %d\n", fileSize); - w_align = ((ctx->width + 15) & (~15)); - h_align = ((ctx->height + 15) & (~15)); - size = w_align * h_align * 3 / 2; - nal = BSWAP32(nal); - - do { - if (ftell(pInFile) >= fileSize) { - mpp_log("read end of file, complete\n"); - break; - } - - if (enc_in && (enc_in->size == 0)) { - if (enc_in->buf == NULL) { - enc_in->buf = (RK_U8*)(malloc)(size); - if (enc_in->buf == NULL) { - ENCODE_ERR_RET(ERROR_MEMORY); - } - api_enc_in->capability = size; - } - - if (api_enc_in->capability < ((RK_U32)size)) { - enc_in->buf = (RK_U8*)(realloc)((void*)(enc_in->buf), size); - if (enc_in->buf == NULL) { - ENCODE_ERR_RET(ERROR_MEMORY); - } - api_enc_in->capability = size; - } - - if (readBytesFromFile(enc_in->buf, size, pInFile)) { - break; - } else { - enc_in->size = size; - enc_in->timeUs = fakeTimeUs; - fakeTimeUs += 40000; - } - - mpp_log("read one frame, size: %d, timeUs: %lld, filePos: %ld\n", - enc_in->size, enc_in->timeUs , ftell(pInFile)); - } - - if ((ret = ctx->encode(ctx, enc_in, enc_out)) < 0) { - ENCODE_ERR_RET(ERROR_VPU_DECODE); - } else { - mpp_log("vpu encode one frame, out len: %d, left size: %d\n", - enc_out->size, enc_in->size); - - /* - ** encoder output stream is raw bitstream, you need to add nal - ** head by yourself. - */ - if ((enc_out->size) && (enc_out->data)) { - if (pOutFile) { - mpp_log("dump %d bytes enc output stream to file\n", - enc_out->size); - fwrite((RK_U8*)&nal, 1, 4, pOutFile); - fwrite(enc_out->data, 1, enc_out->size, pOutFile); - fflush(pOutFile); - } - - enc_out->size = 0; - } - } - - msleep(3); - } while (1); - -ENCODE_OUT: - if (enc_in && enc_in->buf) { - free(enc_in->buf); - enc_in->buf = NULL; - } - if (enc_out && (enc_out->data)) { - free(enc_out->data); - enc_out->data = NULL; - } - if (ctx) { - if (ctx->private_data) { - free(ctx->private_data); - ctx->private_data = NULL; - } - vpu_close_context(&ctx); - ctx = NULL; - } - if (pInFile) { - fclose(pInFile); - pInFile = NULL; - } - if (pOutFile) { - fclose(pOutFile); - pOutFile = NULL; - } - - if (ret) { - mpp_log("encode demo fail, err: %d\n", ret); - } else { - mpp_log("encode demo complete OK.\n"); - } - return ret; - -} - -static RK_S32 vpu_decode_demo(VpuApiDemoCmdContext_t *cmd) -{ - FILE* pInFile = NULL; - FILE* pOutFile = NULL; - struct VpuCodecContext* ctx = NULL; - RK_S32 fileSize = 0, pkt_size = 0; - RK_S32 ret = 0; - RK_U32 frame_count = 0; - DecoderOut_t decOut; - VideoPacket_t demoPkt; - VideoPacket_t* pkt = NULL; - DecoderOut_t *pOut = NULL; - VPU_FRAME *frame = NULL; - RK_S64 fakeTimeUs = 0; - RK_U8* pExtra = NULL; - RK_U32 extraSize = 0; - RK_U32 wAlign16 = 0; - RK_U32 hAlign16 = 0; - RK_U32 frameSize = 0; - - if (cmd == NULL) { - return -1; - } - - if ((cmd->have_input == 0) || (cmd->width <= 0) || (cmd->height <= 0) - || (cmd->coding <= OMX_RK_VIDEO_CodingAutoDetect)) { - mpp_log("Warning: missing needed parameters for vpu api demo\n"); - } - - if (cmd->have_input) { - mpp_log("input bitstream w: %d, h: %d, coding: %d(%s), path: %s\n", - cmd->width, cmd->height, cmd->coding, - cmd->codec_type == CODEC_DECODER ? "decode" : "encode", - cmd->input_file); - - pInFile = fopen(cmd->input_file, "rb"); - if (pInFile == NULL) { - mpp_log("input file not exsist\n"); - DECODE_ERR_RET(ERROR_INVALID_PARAM); - } - } else { - mpp_log("please set input bitstream file\n"); - DECODE_ERR_RET(ERROR_INVALID_PARAM); - } - - if (cmd->have_output) { - mpp_log("vpu api demo output file: %s\n", - cmd->output_file); - pOutFile = fopen(cmd->output_file, "wb"); - if (pOutFile == NULL) { - mpp_log("can not write output file\n"); - DECODE_ERR_RET(ERROR_INVALID_PARAM); - } - if (cmd->record_frames == 0) - cmd->record_frames = 5; - } - - fseek(pInFile, 0L, SEEK_END); - fileSize = ftell(pInFile); - fseek(pInFile, 0L, SEEK_SET); - - memset(&demoPkt, 0, sizeof(VideoPacket_t)); - pkt = &demoPkt; - pkt->data = NULL; - pkt->pts = VPU_API_NOPTS_VALUE; - pkt->dts = VPU_API_NOPTS_VALUE; - - memset(&decOut, 0, sizeof(DecoderOut_t)); - pOut = &decOut; - - pOut->data = (RK_U8*)(malloc)(sizeof(VPU_FRAME)); - if (pOut->data == NULL) { - DECODE_ERR_RET(ERROR_MEMORY); - } - memset(pOut->data, 0, sizeof(VPU_FRAME)); - - ret = vpu_open_context(&ctx); - if (ret || (ctx == NULL)) { - DECODE_ERR_RET(ERROR_MEMORY); - } - - /* - ** read codec extra data from input stream file. - */ - if (readBytesFromFile((RK_U8*)(&extraSize), 4, pInFile)) { - DECODE_ERR_RET(ERROR_IO); - } - - mpp_log("codec extra data size: %d\n", extraSize); - - pExtra = (RK_U8*)(malloc)(extraSize); - if (pExtra == NULL) { - DECODE_ERR_RET(ERROR_MEMORY); - } - memset(pExtra, 0, extraSize); - - if (readBytesFromFile(pExtra, extraSize, pInFile)) { - DECODE_ERR_RET(ERROR_IO); - } - - /* - ** now init vpu api context. codecType, codingType, width ,height - ** are all needed before init. - */ - ctx->codecType = cmd->codec_type; - ctx->videoCoding = cmd->coding; - ctx->width = cmd->width; - ctx->height = cmd->height; - ctx->no_thread = 1; - - if ((ret = ctx->init(ctx, pExtra, extraSize)) != 0) { - mpp_log("init vpu api context fail, ret: 0x%X\n", ret); - DECODE_ERR_RET(ERROR_INIT_VPU); - } - - /* - ** vpu api decoder process. - */ - mpp_log("init vpu api context ok, fileSize: %d\n", fileSize); - - do { - if (ftell(pInFile) >= fileSize) { - mpp_log("read end of file, complete\n"); - break; - } - - if (pkt && (pkt->size == 0)) { - if (readBytesFromFile((RK_U8*)(&pkt_size), 4, pInFile)) { - break; - } - - if (pkt->data == NULL) { - pkt->data = (RK_U8*)(malloc)(pkt_size); - if (pkt->data == NULL) { - DECODE_ERR_RET(ERROR_MEMORY); - } - pkt->capability = pkt_size; - } - - if (pkt->capability < ((RK_U32)pkt_size)) { - pkt->data = (RK_U8*)(realloc)((void*)(pkt->data), pkt_size); - if (pkt->data == NULL) { - DECODE_ERR_RET(ERROR_MEMORY); - } - pkt->capability = pkt_size; - } - - if (readBytesFromFile(pkt->data, pkt_size, pInFile)) { - break; - } else { - pkt->size = pkt_size; - pkt->pts = fakeTimeUs; - fakeTimeUs += 40000; - } - - mpp_log("read one packet, size: %d, pts: %lld, filePos: %ld\n", - pkt->size, pkt->pts, ftell(pInFile)); - } - - /* note: must set out put size to 0 before do decoder. */ - pOut->size = 0; - - if ((ret = ctx->decode(ctx, pkt, pOut)) != 0) { - DECODE_ERR_RET(ERROR_VPU_DECODE); - } else { - mpp_log("vpu decode one frame, out len: %d, left size: %d\n", - pOut->size, pkt->size); - - /* - ** both virtual and physical address of the decoded frame are contained - ** in structure named VPU_FRAME, if you want to use virtual address, make - ** sure you have done VPUMemLink before. - */ - if ((pOut->size) && (pOut->data)) { - frame = (VPU_FRAME *)(pOut->data); - VPUMemLink(&frame->vpumem); - wAlign16 = ((frame->DisplayWidth + 15) & (~15)); - hAlign16 = ((frame->DisplayHeight + 15) & (~15)); - frameSize = wAlign16 * hAlign16 * 3 / 2; - - if (pOutFile && (frame_count++ < cmd->record_frames)) { - mpp_log("write %d frame(yuv420sp) data, %d bytes to file\n", - frame_count, frameSize); - - fwrite((RK_U8*)(frame->vpumem.vir_addr), 1, frameSize, pOutFile); - fflush(pOutFile); - } - - /* - ** remember use VPUFreeLinear to free, other wise memory leak will - ** give you a surprise. - */ - VPUFreeLinear(&frame->vpumem); - pOut->size = 0; - } - } - - msleep(3); - } while (!(ctx->decoder_err)); - -DECODE_OUT: - if (pkt && pkt->data) { - free(pkt->data); - pkt->data = NULL; - } - if (pOut && (pOut->data)) { - free(pOut->data); - pOut->data = NULL; - } - if (pExtra) { - free(pExtra); - pExtra = NULL; - } - if (ctx) { - vpu_close_context(&ctx); - ctx = NULL; - } - if (pInFile) { - fclose(pInFile); - pInFile = NULL; - } - if (pOutFile) { - fclose(pOutFile); - pOutFile = NULL; - } - - if (ret) { - mpp_log("decode demo fail, err: %d\n", ret); - } else { - mpp_log("encode demo complete OK.\n"); - } - return ret; -} - - -int main(int argc, char **argv) -{ - RK_S32 ret = 0; - VpuApiDemoCmdContext_t demoCmdCtx; - VpuApiDemoCmdContext_t *cmd = NULL; - VPU_API_DEMO_DEBUG_DISABLE = 0; - - mpp_log("/******* vpu api demo in *******/\n"); - if (argc == 1) { - show_usage(); - mpp_log("vpu api demo complete directly\n"); - return 0; - } - - cmd = &demoCmdCtx; - memset (cmd, 0, sizeof(VpuApiDemoCmdContext_t)); - cmd->codec_type = CODEC_DECODER; - if ((ret = parse_options(argc, argv, cmd)) != 0) { - if (ret == VPU_DEMO_PARSE_HELP_OK) { - return 0; - } - - mpp_log("parse_options fail\n\n"); - show_usage(); - DEMO_ERR_RET(ERROR_INVALID_PARAM); - } - - if (cmd->disable_debug) { - VPU_API_DEMO_DEBUG_DISABLE = 1; - } - - switch (cmd->codec_type) { - case CODEC_DECODER: - ret = vpu_decode_demo(cmd); - break; - case CODEC_ENCODER: - ret = vpu_encode_demo(cmd); - break; - - default: - ret = ERROR_INVALID_PARAM; - break; - } - -DEMO_OUT: - if (ret) { - mpp_log("vpu api demo fail, err: %d\n", ret); - } else { - mpp_log("vpu api demo complete OK.\n"); - } - return ret; -} +/* SPDX-License-Identifier: Apache-2.0 OR MIT */ +/* + * Copyright (c) 2015 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include + +#include "vpu_api.h" + +#define FOR_TEST_ENCODE 1 + +#define BSWAP32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define DEMO_ERR_RET(err) do { ret = err; goto DEMO_OUT; } while (0) +#define DECODE_ERR_RET(err) do { ret = err; goto DECODE_OUT; } while (0) +#define ENCODE_ERR_RET(err) do { ret = err; goto ENCODE_OUT; } while (0) + +typedef enum VPU_API_DEMO_RET { + VPU_DEMO_OK = 0, + VPU_DEMO_PARSE_HELP_OK = 1, + + VPU_DEMO_ERROR_BASE = -100, + ERROR_INVALID_PARAM = VPU_DEMO_ERROR_BASE - 1, + ERROR_INVALID_STREAM = VPU_DEMO_ERROR_BASE - 2, + ERROR_IO = VPU_DEMO_ERROR_BASE - 3, + ERROR_MEMORY = VPU_DEMO_ERROR_BASE - 4, + ERROR_INIT_VPU = VPU_DEMO_ERROR_BASE - 5, + + ERROR_VPU_DECODE = VPU_DEMO_ERROR_BASE - 90, +} VPU_API_DEMO_RET; + +typedef struct VpuApiDemoCmdContext { + RK_U32 width; + RK_U32 height; + CODEC_TYPE codec_type; + OMX_RK_VIDEO_CODINGTYPE coding; + char input_file[200]; + char output_file[200]; + RK_U8 have_input; + RK_U8 have_output; + RK_U32 record_frames; + RK_S64 record_start_ms; +} VpuApiDemoCmdContext_t; + +typedef struct VpuApiEncInput { + EncInputStream_t stream; + RK_U32 capability; +} VpuApiEncInput; + +typedef struct VpuApiOptionInfo_t { + const char* name; + const char* argname; + const char* help; +} VpuApiOptionInfo; + +static VpuApiOptionInfo vpuApiCmd[] = { + { "i", "input_file", "input bitstream file" }, + { "o", "output_file", "output bitstream file, " }, + { "w", "width", "the width of input bitstream" }, + { "h", "height", "the height of input bitstream" }, + { "t", "codec_type", "the codec type, dec: deoder, enc: encoder, default: decoder" }, + { "coding", "coding_type", "encoding type of the bitstream" }, + { "vframes", "number", "set the number of video frames to record" }, + { "ss", "time_off", "set the start time offset, use Ms as the unit." }, +}; + +static void *vpuapi_hdl = NULL; +static VpuCodecContext_t *ctx; +RK_S32 (*vpuapi_open_ctx)(VpuCodecContext_t **ctx); +RK_S32 (*vpuapi_close_ctx)(VpuCodecContext_t **ctx); +RK_S32 (*vpuapi_mem_link)(VPUMemLinear_t *p); +RK_S32 (*vpuapi_mem_free)(VPUMemLinear_t *p); + +static void show_usage() +{ + printf("usage: vpu_apiDemo [options] input_file, \n\n"); + + printf("Getting help:\n"); + printf("-help --print options of vpu api demo\n"); +} + +static RK_S32 show_help() +{ + RK_S32 i; + RK_S32 count = sizeof(vpuApiCmd) / sizeof(vpuApiCmd[0]); + VpuApiOptionInfo *opt = vpuApiCmd; + + printf("usage: vpu_apiDemo [opt] input_file, \n\n"); + for (i = 0; i < count; i++) + printf("-%s %-16s\t%s\n", opt[i].name, opt[i].argname, opt[i].help); + + return 0; +} + +static RK_S32 parse_options(int argc, char **argv, VpuApiDemoCmdContext_t *cmdCxt) +{ + char *opt; + RK_S32 optindex, handleoptions = 1, ret = 0; + + if ((argc < 2) || (cmdCxt == NULL)) { + printf("vpu api demo, input parameter invalid\n"); + show_usage(); + return ERROR_INVALID_PARAM; + } + + /* parse options */ + optindex = 1; + while (optindex < argc) { + opt = argv[optindex++]; + + if (handleoptions && opt[0] == '-' && opt[1] != '\0') { + if (opt[1] == '-') { + if (opt[2] != '\0') { + opt++; + } else { + handleoptions = 0; + continue; + } + } + + opt++; + + switch (*opt) { + case 'i': + if (argv[optindex]) { + memcpy(cmdCxt->input_file, argv[optindex], strlen(argv[optindex])); + cmdCxt->input_file[strlen(argv[optindex])] = '\0'; + cmdCxt->have_input = 1; + } else { + printf("input file is invalid\n"); + ret = -1; + goto PARSE_OPINIONS_OUT; + } + break; + case 'o': + if (argv[optindex]) { + memcpy(cmdCxt->output_file, argv[optindex], strlen(argv[optindex])); + cmdCxt->output_file[strlen(argv[optindex])] = '\0'; + cmdCxt->have_output = 1; + break; + } else { + printf("out file is invalid\n"); + ret = -1; + goto PARSE_OPINIONS_OUT; + } + case 'w': + if (argv[optindex]) { + cmdCxt->width = atoi(argv[optindex]); + break; + } else { + printf("input width is invalid\n"); + ret = -1; + goto PARSE_OPINIONS_OUT; + } + case 'h': + if ((*(opt + 1) != '\0') && !strncmp(opt, "help", 4)) { + show_help(); + ret = VPU_DEMO_PARSE_HELP_OK; + goto PARSE_OPINIONS_OUT; + } else if (argv[optindex]) { + cmdCxt->height = atoi(argv[optindex]); + } else { + printf("input height is invalid\n"); + ret = -1; + goto PARSE_OPINIONS_OUT; + } + break; + case 't': + if (argv[optindex]) { + cmdCxt->codec_type = atoi(argv[optindex]); + break; + } else { + printf("input codec_type is invalid\n"); + ret = -1; + goto PARSE_OPINIONS_OUT; + } + + default: + if ((*(opt + 1) != '\0') && argv[optindex]) { + if (!strncmp(opt, "coding", 6)) { + printf("coding, argv[optindex]: %s", + argv[optindex]); + cmdCxt->coding = atoi(argv[optindex]); + } else if (!strncmp(opt, "vframes", 7)) { + cmdCxt->record_frames = atoi(argv[optindex]); + } else if (!strncmp(opt, "ss", 2)) { + cmdCxt->record_start_ms = atoi(argv[optindex]); + } else { + ret = -1; + goto PARSE_OPINIONS_OUT; + } + } else { + ret = -1; + goto PARSE_OPINIONS_OUT; + } + break; + } + + optindex += ret; + } + } + +PARSE_OPINIONS_OUT: + if (ret < 0) { + printf("vpu api demo, input parameter invalid\n"); + show_usage(); + return ERROR_INVALID_PARAM; + } + return ret; +} + +static RK_S32 readBytesFromFile(RK_U8 *buf, RK_S32 aBytes, FILE *file) +{ + RK_S32 ret = 0; + + if ((NULL == buf) || (NULL == file) || (0 == aBytes)) { + return -1; + } + + ret = (RK_S32)fread(buf, 1, aBytes, file); + if (ret != aBytes) { + printf("read %d bytes from file fail\n", aBytes); + return -1; + } + + return 0; +} + +static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd) +{ + FILE *pInFile = NULL; + FILE *pOutFile = NULL; + RK_S32 nal = 0x00000001; + RK_S32 fileSize; + RK_S32 ret = 0; + RK_S32 size; + RK_U32 readOneFrameSize = 0; + EncoderOut_t enc_out_yuv; + EncoderOut_t *enc_out = NULL; + VpuApiEncInput enc_in_strm; + VpuApiEncInput *api_enc_in = &enc_in_strm; + EncInputStream_t *enc_in = NULL; + EncParameter_t *enc_param = NULL; + RK_S64 fakeTimeUs = 0; + RK_U32 w_align = 0; + RK_U32 h_align = 0; + + int Format = ENC_INPUT_YUV420_PLANAR; + + if (cmd == NULL) { + return -1; + } + + if ((cmd->have_input == 0) || (cmd->width <= 0) || (cmd->height <= 0) + || (cmd->coding <= OMX_RK_VIDEO_CodingAutoDetect)) { + printf("Warning: missing needed parameters for vpu api demo\n"); + } + + if (cmd->have_input) { + printf("input bitstream w: %d, h: %d, coding: %d(%s), path: %s\n", + cmd->width, cmd->height, cmd->coding, + cmd->codec_type == CODEC_DECODER ? "decode" : "encode", + cmd->input_file); + + pInFile = fopen(cmd->input_file, "rb"); + if (pInFile == NULL) { + printf("input file not exsist\n"); + ENCODE_ERR_RET(ERROR_INVALID_PARAM); + } + } else { + printf("please set input bitstream file\n"); + ENCODE_ERR_RET(ERROR_INVALID_PARAM); + } + + if (cmd->have_output) { + printf("vpu api demo output file: %s\n", + cmd->output_file); + pOutFile = fopen(cmd->output_file, "wb"); + if (pOutFile == NULL) { + printf("can not write output file\n"); + ENCODE_ERR_RET(ERROR_INVALID_PARAM); + } + } + +#ifdef FOR_TEST_ENCODE + ctx = (struct VpuCodecContext *)malloc(sizeof(struct VpuCodecContext)); + if (!ctx) { + printf("Input context has not been properly allocated"); + return -1; + } + memset(ctx, 0, sizeof(struct VpuCodecContext)); + + ctx->videoCoding = OMX_RK_VIDEO_CodingAVC; + ctx->codecType = CODEC_ENCODER; + ctx->width = cmd->width; + ctx->height = cmd->height; +#endif + + fseek(pInFile, 0L, SEEK_END); + fileSize = ftell(pInFile); + fseek(pInFile, 0L, SEEK_SET); + + memset(&enc_in_strm, 0, sizeof(VpuApiEncInput)); + enc_in = &enc_in_strm.stream; + enc_in->buf = NULL; + + memset(&enc_out_yuv, 0, sizeof(EncoderOut_t)); + enc_out = &enc_out_yuv; + enc_out->data = (RK_U8 *)malloc(cmd->width * cmd->height); + if (enc_out->data == NULL) { + ENCODE_ERR_RET(ERROR_MEMORY); + } + + ret = vpuapi_open_ctx(&ctx); + if (ret || (ctx == NULL)) { + ENCODE_ERR_RET(ERROR_MEMORY); + } + + /* + ** now init vpu api context. codecType, codingType, width ,height + ** are all needed before init. + */ + ctx->codecType = cmd->codec_type; + ctx->videoCoding = cmd->coding; + ctx->width = cmd->width; + ctx->height = cmd->height; + ctx->no_thread = 1; + + ctx->private_data = malloc(sizeof(EncParameter_t)); + memset(ctx->private_data, 0, sizeof(EncParameter_t)); + + enc_param = (EncParameter_t *)ctx->private_data; + enc_param->width = cmd->width; + enc_param->height = cmd->height; + enc_param->format = ENC_INPUT_YUV420_PLANAR; + enc_param->rc_mode = 0; + enc_param->bitRate = 4000000; + enc_param->framerate = 25; + enc_param->enableCabac = 1; + enc_param->cabacInitIdc = 0; + enc_param->intraPicRate = 30; + enc_param->profileIdc = 100; + enc_param->levelIdc = 40; + + if ((ret = ctx->init(ctx, NULL, 0)) != 0) { + printf("init vpu api context fail, ret: 0x%X\n", ret); + ENCODE_ERR_RET(ERROR_INIT_VPU); + } + + /* + ** init of VpuCodecContext while running encode, it returns + ** sps and pps of encoder output, you need to save sps and pps + ** after init. + */ + printf("encode init ok, sps len: %d\n", ctx->extradata_size); + if (pOutFile && (ctx->extradata_size > 0)) { + printf("dump %d bytes enc output stream to file\n", + ctx->extradata_size); + + /* save sps and pps */ + fwrite(ctx->extradata, 1, ctx->extradata_size, pOutFile); + fflush(pOutFile); + } + + ret = ctx->control(ctx, VPU_API_ENC_SETFORMAT, &Format); + if (ret) + printf("VPU_API_ENC_SETFORMAT ret %d\n", ret); + + ret = ctx->control(ctx, VPU_API_ENC_GETCFG, enc_param); + if (ret) + printf("VPU_API_ENC_GETCFG ret %d\n", ret); + + enc_param->rc_mode = 1; + + ret = ctx->control(ctx, VPU_API_ENC_SETCFG, enc_param); + if (ret) + printf("VPU_API_ENC_SETCFG ret %d\n", ret); + + /* + ** vpu api encode process. + */ + printf("init vpu api context ok, input yuv stream file size: %d\n", fileSize); + w_align = ((ctx->width + 15) & (~15)); + h_align = ((ctx->height + 15) & (~15)); + size = w_align * h_align * 3 / 2; + readOneFrameSize = ctx->width * ctx->height * 3 / 2; + printf("%d %d %d %d %d", ctx->width, ctx->height, w_align, h_align, size); + nal = BSWAP32(nal); + + do { + if (ftell(pInFile) >= fileSize) { + printf("read end of file, complete\n"); + break; + } + + if (enc_in && (enc_in->size == 0)) { + if (enc_in->buf == NULL) { + enc_in->buf = (RK_U8 *)(malloc)(size); + if (enc_in->buf == NULL) { + ENCODE_ERR_RET(ERROR_MEMORY); + } + api_enc_in->capability = size; + } + + if (api_enc_in->capability < ((RK_U32)size)) { + enc_in->buf = (RK_U8 *)(realloc)((void *)(enc_in->buf), size); + if (enc_in->buf == NULL) { + ENCODE_ERR_RET(ERROR_MEMORY); + } + api_enc_in->capability = size; + } + + if (readBytesFromFile(enc_in->buf, readOneFrameSize, pInFile)) { + break; + } else { + enc_in->size = size; + enc_in->timeUs = fakeTimeUs; + fakeTimeUs += 40000; + } + + printf("read one frame, size: %d, timeUs: %lld, filePos: %ld\n", + enc_in->size, enc_in->timeUs, ftell(pInFile)); + } + + if ((ret = ctx->encode(ctx, enc_in, enc_out)) < 0) { + ENCODE_ERR_RET(ERROR_VPU_DECODE); + } else { + enc_in->size = 0; // TODO encode completely, and set enc_in->size to 0 + printf("vpu encode one frame, out len: %d, left size: %d\n", + enc_out->size, enc_in->size); + + /* + ** encoder output stream is raw bitstream, you need to add nal + ** head by yourself. + */ + if ((enc_out->size) && (enc_out->data)) { + if (pOutFile) { + printf("dump %d bytes enc output stream to file\n", + enc_out->size); + //fwrite((RK_U8*)&nal, 1, 4, pOutFile); // because output stream have start code, so here mask this code + fwrite(enc_out->data, 1, enc_out->size, pOutFile); + fflush(pOutFile); + } + + enc_out->size = 0; + } + } + + usleep(3000); + } while (1); + +ENCODE_OUT: + if (enc_in && enc_in->buf) { + free(enc_in->buf); + enc_in->buf = NULL; + } + if (enc_out && (enc_out->data)) { + free(enc_out->data); + enc_out->data = NULL; + } + if (ctx) { + if (ctx->private_data) { + free(ctx->private_data); + ctx->private_data = NULL; + } + vpuapi_close_ctx(&ctx); + ctx = NULL; + } + if (pInFile) { + fclose(pInFile); + pInFile = NULL; + } + if (pOutFile) { + fclose(pOutFile); + pOutFile = NULL; + } + + if (ret) { + printf("encode demo fail, err: %d\n", ret); + } else { + printf("encode demo complete OK.\n"); + } + return ret; + +} + +static RK_S32 vpu_decode_demo(VpuApiDemoCmdContext_t *cmd) +{ + FILE *pInFile = NULL; + FILE *pOutFile = NULL; + RK_S32 fileSize = 0, pkt_size = 0; + RK_S32 ret = 0; + RK_U32 frame_count = 0; + DecoderOut_t decOut; + VideoPacket_t demoPkt; + VideoPacket_t *pkt = NULL; + DecoderOut_t *pOut = NULL; + VPU_FRAME *frame = NULL; + RK_S64 fakeTimeUs = 0; + RK_U8 *pExtra = NULL; + RK_U32 extraSize = 0; + RK_U32 wAlign16 = 0; + RK_U32 hAlign16 = 0; + RK_U32 frameSize = 0; + + if (cmd == NULL) { + return -1; + } + + if ((cmd->have_input == 0) || (cmd->width <= 0) || (cmd->height <= 0) + || (cmd->coding <= OMX_RK_VIDEO_CodingAutoDetect)) { + printf("Warning: missing needed parameters for vpu api demo\n"); + } + + if (cmd->have_input) { + printf("input bitstream w: %d, h: %d, coding: %d(%s), path: %s\n", + cmd->width, cmd->height, cmd->coding, + cmd->codec_type == CODEC_DECODER ? "decode" : "encode", + cmd->input_file); + + pInFile = fopen(cmd->input_file, "rb"); + if (pInFile == NULL) { + printf("input file not exsist\n"); + DECODE_ERR_RET(ERROR_INVALID_PARAM); + } + } else { + printf("please set input bitstream file\n"); + DECODE_ERR_RET(ERROR_INVALID_PARAM); + } + + if (cmd->have_output) { + printf("vpu api demo output file: %s\n", + cmd->output_file); + pOutFile = fopen(cmd->output_file, "wb"); + if (pOutFile == NULL) { + printf("can not write output file\n"); + DECODE_ERR_RET(ERROR_INVALID_PARAM); + } + if (cmd->record_frames == 0) + cmd->record_frames = 5; + } + + fseek(pInFile, 0L, SEEK_END); + fileSize = ftell(pInFile); + fseek(pInFile, 0L, SEEK_SET); + + memset(&demoPkt, 0, sizeof(VideoPacket_t)); + pkt = &demoPkt; + pkt->data = NULL; + pkt->pts = VPU_API_NOPTS_VALUE; + pkt->dts = VPU_API_NOPTS_VALUE; + + memset(&decOut, 0, sizeof(DecoderOut_t)); + pOut = &decOut; + + ret = vpuapi_open_ctx(&ctx); + if (ret || (ctx == NULL)) { + DECODE_ERR_RET(ERROR_MEMORY); + } + + /* + ** read codec extra data from input stream file. + */ + if (readBytesFromFile((RK_U8 *)(&extraSize), 4, pInFile)) { + DECODE_ERR_RET(ERROR_IO); + } + + printf("codec extra data size: %d\n", extraSize); + + pExtra = (RK_U8 *)(malloc)(extraSize); + if (pExtra == NULL) { + DECODE_ERR_RET(ERROR_MEMORY); + } + memset(pExtra, 0, extraSize); + + if (readBytesFromFile(pExtra, extraSize, pInFile)) { + DECODE_ERR_RET(ERROR_IO); + } + + /* + ** now init vpu api context. codecType, codingType, width ,height + ** are all needed before init. + */ + ctx->codecType = cmd->codec_type; + ctx->videoCoding = cmd->coding; + ctx->width = cmd->width; + ctx->height = cmd->height; + ctx->no_thread = 1; + + if ((ret = ctx->init(ctx, pExtra, extraSize)) != 0) { + printf("init vpu api context fail, ret: 0x%X\n", ret); + DECODE_ERR_RET(ERROR_INIT_VPU); + } + + /* + ** vpu api decoder process. + */ + printf("init vpu api context ok, fileSize: %d\n", fileSize); + + do { + if (ftell(pInFile) >= fileSize) { + printf("read end of file, complete\n"); + break; + } + + if (pkt && (pkt->size == 0)) { + if (readBytesFromFile((RK_U8 *)(&pkt_size), 4, pInFile)) { + break; + } + + if (pkt->data == NULL) { + pkt->data = (RK_U8 *)(malloc)(pkt_size); + if (pkt->data == NULL) { + DECODE_ERR_RET(ERROR_MEMORY); + } + pkt->capability = pkt_size; + } + + if (pkt->capability < ((RK_U32)pkt_size)) { + pkt->data = (RK_U8 *)(realloc)((void *)(pkt->data), pkt_size); + if (pkt->data == NULL) { + DECODE_ERR_RET(ERROR_MEMORY); + } + pkt->capability = pkt_size; + } + + if (readBytesFromFile(pkt->data, pkt_size, pInFile)) { + break; + } else { + pkt->size = pkt_size; + pkt->pts = fakeTimeUs; + fakeTimeUs += 40000; + } + + printf("read one packet, size: %d, pts: %lld, filePos: %ld\n", + pkt->size, pkt->pts, ftell(pInFile)); + } + + /* note: must set out put size to 0 before do decoder. */ + pOut->size = 0; + + if (ctx->decode_sendstream(ctx, pkt) != 0) { + printf("send packet failed"); + DECODE_ERR_RET(ERROR_VPU_DECODE); + } + + + if ((ret = ctx->decode_getframe(ctx, pOut)) != 0) { + printf("get decoded data failed\n"); + DECODE_ERR_RET(ERROR_VPU_DECODE); + } else { + printf("vpu decode one frame, out len: %d, left size: %d\n", + pOut->size, pkt->size); + + /* + ** both virtual and physical address of the decoded frame are contained + ** in structure named VPU_FRAME, if you want to use virtual address, make + ** sure you have done VPUMemLink before. + */ + if ((pOut->size) && (pOut->data)) { + frame = (VPU_FRAME *)(pOut->data); + vpuapi_mem_link(&frame->vpumem); + wAlign16 = ((frame->DisplayWidth + 15) & (~15)); + hAlign16 = ((frame->DisplayHeight + 15) & (~15)); + frameSize = wAlign16 * hAlign16 * 3 / 2; + + if (pOutFile && (frame_count++ < cmd->record_frames)) { + printf("write %d frame(yuv420sp) data, %d bytes to file\n", + frame_count, frameSize); + + fwrite((RK_U8 *)(frame->vpumem.vir_addr), 1, frameSize, pOutFile); + fflush(pOutFile); + } + + /* + ** remember use VPUFreeLinear to free, other wise memory leak will + ** give you a surprise. + */ + vpuapi_mem_free(&frame->vpumem); + // NOTE: pOut->data is malloc from vpu_api we need to free it. + free(pOut->data); + pOut->data = NULL; + pOut->size = 0; + } + } + + usleep(3000); + } while (!(ctx->decoder_err)); + +DECODE_OUT: + if (pkt && pkt->data) { + free(pkt->data); + pkt->data = NULL; + } + if (pOut && (pOut->data)) { + free(pOut->data); + pOut->data = NULL; + } + if (pExtra) { + free(pExtra); + pExtra = NULL; + } + if (ctx) { + vpuapi_close_ctx(&ctx); + ctx = NULL; + } + if (pInFile) { + fclose(pInFile); + pInFile = NULL; + } + if (pOutFile) { + fclose(pOutFile); + pOutFile = NULL; + } + + if (ret) { + printf("decode demo fail, err: %d\n", ret); + } else { + printf("encode demo complete OK.\n"); + } + return ret; +} + +/* vpu_api is only on Android platform */ +int main(int argc, char **argv) +{ + RK_S32 ret = 0; + VpuApiDemoCmdContext_t demoCmdCtx; + VpuApiDemoCmdContext_t *cmd = NULL; + + printf("/******* vpu api demo in *******/\n"); + if (argc == 1) { + show_usage(); + return 0; + } + + /* open library for access */ + vpuapi_hdl = dlopen("libvpu.so", RTLD_LAZY | RTLD_GLOBAL); + if (NULL == vpuapi_hdl) { + printf("failed to open libvpu.so\n"); + ret = -1; + goto DEMO_OUT; + } + + vpuapi_open_ctx = (RK_S32 (*)(VpuCodecContext_t **ctx))dlsym(vpuapi_hdl, "vpu_open_context"); + vpuapi_close_ctx = (RK_S32 (*)(VpuCodecContext_t **ctx))dlsym(vpuapi_hdl, "vpu_close_context"); + vpuapi_mem_link = (RK_S32 (*)(VPUMemLinear_t * p))dlsym(vpuapi_hdl, "VPUMemLink"); + vpuapi_mem_free = (RK_S32 (*)(VPUMemLinear_t * p))dlsym(vpuapi_hdl, "VPUFreeLinear"); + + if (NULL == vpuapi_open_ctx || NULL == vpuapi_close_ctx || + NULL == vpuapi_mem_link || NULL == vpuapi_mem_free) { + printf("failed to open vpu_open_context %p vpu_close_context %p\n", + vpuapi_open_ctx, vpuapi_close_ctx); + printf("failed to open VPUMemLink %p VPUFreeLinear %p\n", + vpuapi_mem_link, vpuapi_mem_free); + ret = -1; + goto DEMO_OUT; + } + + printf("get vpuapi handle %p vpu_open_context %p vpu_close_context %p\n", + vpuapi_hdl, vpuapi_open_ctx, vpuapi_close_ctx); + + cmd = &demoCmdCtx; + memset(cmd, 0, sizeof(VpuApiDemoCmdContext_t)); + cmd->codec_type = CODEC_DECODER; + if ((ret = parse_options(argc, argv, cmd)) != 0) { + if (ret == VPU_DEMO_PARSE_HELP_OK) { + return 0; + } + + printf("parse_options fail\n\n"); + show_usage(); + DEMO_ERR_RET(ERROR_INVALID_PARAM); + } + + switch (cmd->codec_type) { + case CODEC_DECODER : { + ret = vpu_decode_demo(cmd); + } break; + case CODEC_ENCODER : { + ret = vpu_encode_demo(cmd); + } break; + default : { + ret = ERROR_INVALID_PARAM; + } break; + } + +DEMO_OUT: + if (ret) { + printf("vpu api demo fail, err: %d\n", ret); + if (vpuapi_hdl) { + dlclose(vpuapi_hdl); + vpuapi_hdl = NULL; + } + } else { + printf("vpu api demo complete OK.\n"); + } + return ret; +} diff --git a/tools/astyle b/tools/astyle new file mode 100755 index 000000000..d66ee115e Binary files /dev/null and b/tools/astyle differ diff --git a/tools/astylerc b/tools/astylerc index 61be20ee8..8772e6b7e 100644 --- a/tools/astylerc +++ b/tools/astylerc @@ -1,11 +1,9 @@ # directory setting ---recursive --exclude=../build ---exclude=../osal/window/pthread +--exclude=../osal/linux/drm.h # bracket style setting --style=linux -#--style=kr # indent setting --indent=spaces=4 @@ -13,7 +11,7 @@ #--indent-switches #--indent-preprocessor --min-conditional-indent=0 ---max-instatement-indent=80 +--max-instatement-indent=120 # padding setting #--break-blocks diff --git a/tools/changelog.sh b/tools/changelog.sh new file mode 100755 index 000000000..fbb05820f --- /dev/null +++ b/tools/changelog.sh @@ -0,0 +1,231 @@ +#!/bin/bash +## Author LinkinStar / HermanChen + +# solve the space by IFS +OLDIFS=$IFS +IFS=`echo -en "\n\b"` +echo -en $IFS + +declare -g changelog_file="CHANGELOG.md" +declare -g git_repo_rootdir +declare -g current_tag +declare -g previous_tag +declare -g prev_changelog +declare -g prev_changelog_version +declare -g prev_tag +declare -g curr_tag + +# changelog version define +declare -g version_tag + +function log_filter_and_print() { + local title=$1 + local prefix=$2 + local -a msgs=() + local msg_cnt=0 + local prefix_len=${#prefix} + + # filter log and find the matched prefix number + for msg in ${orig_logs[@]} + do + if [[ $msg == "$prefix"* ]]; then + msgs[msg_cnt]=$msg + let msg_cnt++ + + echo "$prefix commit $msg_cnt - ${msg}" + fi + done + + if [ $msg_cnt -gt 0 ]; then + echo -e "### $title" >> ${changelog_file} + + for msg in ${msgs[@]} + do + # check log mode + local pos=$prefix_len + local log + + # message mode: prefix: xxxx + log=$(echo $msg | grep -i "^$prefix:") + #echo "pos $pos log $log" + if [ "$log" != "" ]; then + let pos++ + fi + + # remove extra space + log=$(echo ${msg:$pos} | sed -e 's/^[ ]*//g' | sed -e 's/[ ]*$//g') + echo -e "- $log" >> ${changelog_file} + done + + echo -e "" >> ${changelog_file} + fi +} + +usage="changelog helper script + use -t / --version to create a new tag commit and update CHANGELOG.md + by insert new version on top, + + the basic commit message should be structured as follows: + [optional scope]: + [optional body] + [optional footer(s)] + + Type + Must be one of the following: + feat: A new feature + fix: A bug fix + docs: Documentation only changes + style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) + refactor: A code change that neither fixes a bug nor adds a feature + perf: A code change that improves performance + test: Adding missing or correcting existing tests + chore: Changes to the build process or auxiliary tools and libraries such as documentation generation + + https://www.conventionalcommits.org/zh-hans/v1.0.0/ + + .option('-t, --version', 'create a version tag with changelog update') + .option('-t, --prev', 'setup the previous version tag as baseline') + .option('-f, --file [file]', 'file to write to, defaults to ./CHANGELOG.md, use - for stdout', './CHANGELOG.md') + .option('-u, --repo-url [url]', 'specify the repo URL for commit links') +" + +while [ $# -gt 0 ]; do + case $1 in + --help | -h) + echo "$usage" + exit 1 + ;; + --version | -t) + version_tag=$2 + shift + ;; + --prev | -p) + prev_tag=$2 + shift + ;; + --file | -f) + changelog_file=$2 + echo "save changelog to file ${changelog_file}" + shift + ;; + --repo-url | -u) + git_repo_rootdir=$2 + echo "set repo rootdir to ${git_repo_rootdir}" + shift + ;; + *) + # skip invalid option + shift + ;; + esac + shift +done + +# check git command +if ! command -v git >/dev/null; then + >&2 echo "ERROR: git command is not available" + echo "$usage" + exit 1 +fi + +# if repo root is not set set sefault repo root +if [ -z $git_repo_rootdir ]; then + git_repo_rootdir=$(git rev-parse --show-toplevel 2>/dev/null) +fi + +# check repo root valid or not +if [ -z ${git_repo_rootdir} ] || [ ! -d ${git_repo_rootdir} ]; then + echo "ERROR: can not found repo root" + echo "$usage" + exit 1 +fi + +# cd to rootdir +cd $git_repo_rootdir + +# check version tag exist or not +if [ -z ${version_tag} ]; then + echo "ERROR: can not run without a new version tag" + echo "$usage" + exit 1 +fi + +tag_log=$(git tag -v ${version_tag} | grep object) +if [ ! -z ${tag_log} ]; then + echo "ERROR: can not run with an existing tag ${version_tag}" + echo "$usage" + exit 1 +fi + +# create new tag with empty commit +git commit --allow-empty -s -m "docs: Update ${version_tag} CHANGELOG.md" +tag_date=`date '+%Y-%m-%d'` +git tag ${version_tag} -m "${version_tag} version at ${tag_date}" + +# if changelog file is not exist then create it +if [[ ! -f ${changelog_file} ]]; then + touch ${changelog_file} +else + # get old changelog + prev_changelog=$(cat $changelog_file) + prev_changelog_version=$(echo $prev_changelog | grep -E "## *.*.* *" | head -1 | awk '{ print $2 }') + + rm -rf ${changelog_file} + touch ${changelog_file} +fi + +# get current version info +curr_ver=$(git describe --tags --long) +curr_tag=$(git describe --tags --abbrev=0) +if [ -n "${prev_tag+x}" ] && [ -z "$prev_tag" ]; then + prev_tag=$(git describe --tags --abbrev=0 "$curr_tag"^) +fi +date="$(date '+%Y-%m-%d')" + +echo "curr ver: ${curr_ver}" +echo "curr tag: ${curr_tag}" +echo "prev tag: ${prev_tag}" + +# dump log between two tags +orig_logs=$(git log --pretty="%s" --no-merges $curr_tag...$prev_tag) +echo "commits: from ${prev_tag} to ${curr_tag}" +echo "${orig_logs}" + +# check unreleased version number +unreleased_count=$(echo ${curr_ver} | grep -E "## *.*.* *" | head -1 | awk -F "-" '{ printf $2 }') +echo "unreleased version count: ${unreleased_count}" + +# write unreleased information +if [ "$unreleased_count" ] && [ $unreleased_count -gt 0 ]; then + echo -e "## Unreleased (${date})\n" >> ${changelog_file} + + unreleased_logs=$(git log --pretty="%s" --no-merges HEAD...$curr_tag) + for msg in ${unreleased_logs[@]} + do + echo -e "- ${msg}" >> ${changelog_file} + done + + echo -e "" >> ${changelog_file} +else + echo -e "## $curr_tag ($date)" >> ${changelog_file} +fi + +# write taged information +log_filter_and_print "Feature" "feat" +log_filter_and_print "Fix" "fix" +log_filter_and_print "Docs" "docs" +log_filter_and_print "Style" "Style" +log_filter_and_print "Refactor" "refactor" +log_filter_and_print "Perf" "perf" +log_filter_and_print "Test" "test" +log_filter_and_print "Chore" "chore" + +echo -e "${prev_changelog}" >> ${changelog_file} + +# add CHANGELOG.md +git add ${changelog_file} +git commit --amend -C ${curr_ver} +# update tag message +git tag -f ${version_tag} -m "${version_tag} version at ${tag_date}" + +IFS=$OLDIFS diff --git a/tools/hooks/pre-commit b/tools/hooks/pre-commit new file mode 100755 index 000000000..7aef3cedc --- /dev/null +++ b/tools/hooks/pre-commit @@ -0,0 +1,31 @@ +#!/bin/sh + +out_file="./fmt_df.txt" +cur_dir=$(pwd) +script_dir=tools/ + +echo "[git-hook]: before commit, format code use mpp_astyle.sh ..." + +cd $script_dir +./mpp_astyle.sh + +cd $cur_dir + +git status -s | grep "^MM " > $out_file + +if [ -s $out_file ] +then { + echo "[git-hook]: code changed after formating, please commit again." + rm $out_file + echo "[git-hook]: git status below:" + git status + exit 1 +} else { + echo "[git-hook]: nothing change after formating, commit continues." + if [ -f $out_file ] + then { + rm $out_file + } fi + exit 0 +} fi + diff --git a/tools/mpp_astyle.bat b/tools/mpp_astyle.bat index 085bbc9cd..4c2543848 100644 --- a/tools/mpp_astyle.bat +++ b/tools/mpp_astyle.bat @@ -1,3 +1,3 @@ @echo off -astyle.exe --options=astylerc ../*.cpp ../*.c ../*.h -pause \ No newline at end of file +astyle.exe --options=astylerc --recursive ../*.cpp ../*.c ../*.h +pause diff --git a/tools/mpp_astyle.sh b/tools/mpp_astyle.sh index 14f24bb2c..c05c4ed1c 100755 --- a/tools/mpp_astyle.sh +++ b/tools/mpp_astyle.sh @@ -1,4 +1,4 @@ #!/bin/bash set -e -astyle --options=astylerc ../*.cpp ../*.c ../*.h +./astyle --quiet --options=astylerc --recursive "../*.cpp" "../*.c" "../*.h" diff --git a/tools/mpp_doxyfile b/tools/mpp_doxyfile new file mode 100644 index 000000000..89c7fdbc6 --- /dev/null +++ b/tools/mpp_doxyfile @@ -0,0 +1,2303 @@ +# Doxyfile 1.8.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "My Project" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../inc + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /